mac80211 improvements
Subsystems (2)
Johannes Berg
maintainercover mac80211 improvements
Here are a number of improvements for mac80211's virtual interface handling (master netdev, cleanups) and driver API (beaconing).
I have tested these patches on b43 in AP, STA and IBSS modes (communicating with my N810 or an AP) and have not seen any issues.
I would appreciate testing on other hardware (I can probably cover iwl4965, rt61pci and zd1211 next week), but I don't expect much trouble.
johannes
Johannes Berg
maintainerPATCH 1/4 mac80211: make master netdev handling sane
Currently, almost every interface type has a 'bss' pointer pointing to BSS information. This BSS information, however, is for a _local_ BSS, not for the BSS we joined, so having it on a STA mode interface makes little sense, but now they have it pointing to the master device, which is an AP mode virtual interface. However, except for some bitrate control data, this pointer is only used in AP/VLAN modes (for power saving stations.)
Overall, it is not necessary to even have the master netdev be a valid virtual interface, and it doesn't have to be on the list of interfaces either.
This patch changes the master netdev to be special, it now
- no longer is on the list of virtual interfaces, which lets me remove a lot of tests for that
- no longer has sub_if_data attached, since that isn't used
Additionally, this patch changes some vlan/ap mode handling that is related to these 'bss' pointers described above (but in the VLAN case they actually make sense because there they point to the AP they belong to); it also adds some debugging code to IEEE80211_DEV_TO_SUB_IF to validate it is not called on the master netdev any more.
******
** Please test!
**
** I have not tested this patch heavily yet, especially not ** in anything other than STA mode. I believe it should work ** with the possible exception of power saving in IBSS, but ** I don't think we handle that anyway because we don't do ** anything about ATIM windows etc.
******
--- net/mac80211/cfg.c | 2 net/mac80211/debugfs_netdev.c | 34 +++++++++++--- net/mac80211/ieee80211_i.h | 41 ++++++++++------- net/mac80211/iface.c | 64 +++++--------------------- net/mac80211/main.c | 96 +++++++++++----------------------------- net/mac80211/mlme.c | 56 +++++++---------------- net/mac80211/rc80211_pid_algo.c | 8 +-- net/mac80211/rx.c | 15 ++---- net/mac80211/sta_info.c | 29 ++++++++---- net/mac80211/tx.c | 11 ++-- net/mac80211/wext.c | 10 +--- 11 files changed, 153 insertions(+), 213 deletions(-)
net/mac80211/ieee80211_i.h +24 -17
@@ -237,8 +237,6 @@ struct ieee80211_if_ap {struct sk_buff_head ps_bc_buf;atomic_t num_sta_ps;/* number of stations in PS mode */ int dtim_count; -int force_unicast_rateidx;/* forced TX rateidx for unicast frames */ -int max_ratectrl_rateidx;/* max TX rateidx for rate control */ int num_beacons;/* number of TXed beacon frames for this BSS */ };
@@ -248,7 +246,6 @@ struct ieee80211_if_wds { };struct ieee80211_if_vlan { -struct ieee80211_sub_if_data *ap;struct list_head list; };
@@ -432,16 +429,18 @@ struct ieee80211_sub_if_data {struct ieee80211_key *keys[NUM_DEFAULT_KEYS ];struct ieee80211_key *default_key; +/* BSS configuration for this interface. */ +struct ieee80211_bss_conf bss_conf; +/* -* BSS configuration for this interface. -* -* FIXME: I feel bad putting this here when we already have a -* bss pointer, but the bss pointer is just wrong when -* you have multiple virtual STA mode interfaces... -* This needs to be fixed. +* AP this belongs to: self in AP mode and +* corresponding AP in VLAN mode, NULL for +* all others (might be needed later in IBSS) */ -struct ieee80211_bss_conf bss_conf; -struct ieee80211_if_ap *bss;/* BSS that this device belongs to */ +struct ieee80211_if_ap *bss; + +int force_unicast_rateidx;/* forced TX rateidx for unicast frames */ +int max_ratectrl_rateidx;/* max TX rateidx for rate control */ union {struct ieee80211_if_ap ap;
@@ -533,8 +532,6 @@ struct ieee80211_sub_if_data *vif_to_sda return container_of(p, struct ieee80211_sub_if_data, vif); } -#define IEEE80211_DEV_TO_SUB_IF (dev) netdev_priv(dev) -enum {IEEE80211_RX_MSG =1 ,IEEE80211_TX_STATUS_MSG =2 ,
@@ -760,6 +757,16 @@ static inline int ieee80211_is_multiqueu#endif } +static inline struct ieee80211_sub_if_data * +IEEE80211_DEV_TO_SUB_IF (struct net_device *dev) +{ +struct ieee80211_local *local =wdev_priv (dev->ieee80211_ptr); + +BUG_ON (!local || local->mdev == dev); + +return netdev_priv (dev); +} +/* this struct represents 802.11n's RA/TID combination */ struct ieee80211_ra_tid {u8 ra[ETH_ALEN ];
@@ -882,8 +889,8 @@ int ieee80211_sta_scan_results(struct neieee80211_rx_result ieee80211_sta_rx_scan (struct net_device *dev,struct sk_buff *skb,struct ieee80211_rx_status *rx_status); -void ieee80211_rx_bss_list_init (struct net_device *dev); -void ieee80211_rx_bss_list_deinit (struct net_device *dev); +void ieee80211_rx_bss_list_init (struct ieee80211_local *local); +void ieee80211_rx_bss_list_deinit (struct ieee80211_local *local);int ieee80211_sta_set_extra_ie (struct net_device *dev,char *ie,size_t len); struct sta_info *ieee80211_ibss_add_sta(struct net_device *dev, struct sk_buff *skb, u8 *bssid,
@@ -924,8 +931,8 @@ static inline void ieee80211_start_mesh( {}#endif -/* ieee80211_iface.c */ -int ieee80211_if_add (struct net_device *dev,const char *name, +/* interface handling */ +int ieee80211_if_add (struct ieee80211_local *local,const char *name,struct net_device **new_dev,int type,struct vif_params *params);void ieee80211_if_set_type (struct net_device *dev,int type);
net/mac80211/iface.c +13 -51
147 lines not on this page · raw message
net/mac80211/main.c +28 -68
238 lines not on this page · raw message
net/mac80211/rx.c +5 -10
@@ -649,8 +649,7 @@ static void ap_sta_ps_start(struct net_d sdata = sta->sdata; -if (sdata->bss) -atomic_inc (&sdata->bss->num_sta_ps); +atomic_inc (&sdata->bss->num_sta_ps);set_and_clear_sta_flags (sta,WLAN_STA_PS ,WLAN_STA_PSPOLL );#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG printk(KERN_DEBUG "%s: STA %s aid %d enters power save mode\n",
@@ -669,8 +668,7 @@ static int ap_sta_ps_end(struct net_devi sdata = sta->sdata; -if (sdata->bss) -atomic_dec (&sdata->bss->num_sta_ps); +atomic_dec (&sdata->bss->num_sta_ps);clear_sta_flags (sta,WLAN_STA_PS |WLAN_STA_PSPOLL );
@@ -744,7 +742,9 @@ ieee80211_rx_h_sta_process(struct ieee80 sta->last_qual = rx->status->qual; sta->last_noise = rx->status->noise; -if (!(rx->fc &IEEE80211_FCTL_MOREFRAGS )) { +if (!(rx->fc &IEEE80211_FCTL_MOREFRAGS ) && + (rx->sdata->vif.type ==IEEE80211_IF_TYPE_AP || + rx->sdata->vif.type ==IEEE80211_IF_TYPE_VLAN )) {/* Change STA power saving mode only in the end of a frame * exchange sequence */ if (test_sta_flags(sta, WLAN_STA_PS) &&
@@ -1776,11 +1776,6 @@ static int prepare_for_handlers(struct ireturn 0 ; rx->flags &= ~IEEE80211_RX_RA_MATCH ; } -if (sdata->dev == sdata->local->mdev && - !(rx->flags &IEEE80211_RX_IN_SCAN )) -/* do not receive anything via -* master device when not scanning */ -return 0 ;break ;case IEEE80211_IF_TYPE_WDS : if (bssid ||
net/mac80211/sta_info.c +21 -8
@@ -319,7 +319,9 @@ int sta_info_insert(struct sta_info *sta/* notify driver */ if (local->ops->sta_notify) {if (sdata->vif.type ==IEEE80211_IF_TYPE_VLAN ) - sdata = sdata->u.vlan.ap; + sdata =container_of (sdata->bss, + struct ieee80211_sub_if_data, + u.ap); local->ops->sta_notify (local_to_hw (local), &sdata->vif,STA_NOTIFY_ADD , sta->addr);
@@ -374,8 +376,10 @@ static inline void __bss_tim_clear(strucstatic void __sta_info_set_tim_bit (struct ieee80211_if_ap *bss,struct sta_info *sta) { -if (bss) -__bss_tim_set (bss, sta->aid); +BUG_ON (!bss); + +__bss_tim_set (bss, sta->aid); +if (sta->local->ops->set_tim) { sta->local->tim_in_locked_section = true; sta->local->ops->set_tim (local_to_hw (sta->local), sta->aid,1 );
@@ -387,6 +391,8 @@ void sta_info_set_tim_bit(struct sta_inf {unsigned long flags; +BUG_ON (!sta->sdata->bss); +spin_lock_irqsave (&sta->local->sta_lock, flags);__sta_info_set_tim_bit (sta->sdata->bss, sta);spin_unlock_irqrestore (&sta->local->sta_lock, flags);
@@ -395,8 +401,10 @@ void sta_info_set_tim_bit(struct sta_infstatic void __sta_info_clear_tim_bit (struct ieee80211_if_ap *bss,struct sta_info *sta) { -if (bss) -__bss_tim_clear (bss, sta->aid); +BUG_ON (!bss); + +__bss_tim_clear (bss, sta->aid); +if (sta->local->ops->set_tim) { sta->local->tim_in_locked_section = true; sta->local->ops->set_tim (local_to_hw (sta->local), sta->aid,0 );
@@ -408,6 +416,8 @@ void sta_info_clear_tim_bit(struct sta_i {unsigned long flags; +BUG_ON (!sta->sdata->bss); +spin_lock_irqsave (&sta->local->sta_lock, flags);__sta_info_clear_tim_bit (sta->sdata->bss, sta);spin_unlock_irqrestore (&sta->local->sta_lock, flags);
@@ -436,8 +446,9 @@ void __sta_info_unlink(struct sta_info *list_del (&(*sta)->list);if (test_and_clear_sta_flags (*sta,WLAN_STA_PS )) { -if (sdata->bss) -atomic_dec (&sdata->bss->num_sta_ps); +BUG_ON (!sdata->bss); + +atomic_dec (&sdata->bss->num_sta_ps);__sta_info_clear_tim_bit (sdata->bss, *sta); }
@@ -445,7 +456,9 @@ void __sta_info_unlink(struct sta_info *if (local->ops->sta_notify) {if (sdata->vif.type ==IEEE80211_IF_TYPE_VLAN ) - sdata = sdata->u.vlan.ap; + sdata =container_of (sdata->bss, + struct ieee80211_sub_if_data, + u.ap); local->ops->sta_notify (local_to_hw (local), &sdata->vif,STA_NOTIFY_REMOVE , (*sta)->addr);
net/mac80211/tx.c +7 -4
@@ -303,8 +303,7 @@ static void purge_old_ps_buffers(structlist_for_each_entry_rcu (sdata, &local->interfaces, list) {struct ieee80211_if_ap *ap; -if (sdata->dev == local->mdev || - sdata->vif.type !=IEEE80211_IF_TYPE_AP ) +if (sdata->vif.type !=IEEE80211_IF_TYPE_AP )continue ; ap = &sdata->u.ap; skb =skb_dequeue (&ap->ps_bc_buf);
@@ -346,8 +345,12 @@ ieee80211_tx_h_multicast_ps_buf(struct i* This is done either by the hardware or us. */ -/* not AP/IBSS or ordered frame */ -if (!tx->sdata->bss || (tx->fc &IEEE80211_FCTL_ORDER )) +/* powersaving STAs only in AP/VLAN mode */ +if (!tx->sdata->bss) +return TX_CONTINUE ; + +/* no buffering for ordered frames */ +if (tx->fc &IEEE80211_FCTL_ORDER )return TX_CONTINUE ;/* no stations in PS mode */
net/mac80211/wext.c +4 -6
@@ -627,16 +627,14 @@ static int ieee80211_ioctl_siwrate(strucstruct ieee80211_supported_band *sband; sdata =IEEE80211_DEV_TO_SUB_IF (dev); -if (!sdata->bss) -return -ENODEV ; sband = local->hw.wiphy->bands[local->hw.conf.channel->band];/* target_rate = -1, rate->fixed = 0 means auto only, so use all rates * target_rate = X, rate->fixed = 1 means only rate X * target_rate = X, rate->fixed = 0 means all rates <= X */ - sdata->bss->max_ratectrl_rateidx =-1 ; - sdata->bss->force_unicast_rateidx =-1 ; + sdata->max_ratectrl_rateidx =-1 ; + sdata->force_unicast_rateidx =-1 ;if (rate->value <0 )return 0 ;
@@ -645,9 +643,9 @@ static int ieee80211_ioctl_siwrate(strucint this_rate = brate->bitrate;if (target_rate == this_rate) { - sdata->bss->max_ratectrl_rateidx = i; + sdata->max_ratectrl_rateidx = i;if (rate->fixed) - sdata->bss->force_unicast_rateidx = i; + sdata->force_unicast_rateidx = i; err =0 ;break ; }
net/mac80211/debugfs_netdev.c +27 -7
@@ -156,6 +156,8 @@ static const struct file_operations name/* common attributes */ IEEE80211_IF_FILE (drop_unencrypted, drop_unencrypted,DEC ); +IEEE80211_IF_FILE (force_unicast_rateidx, force_unicast_rateidx,DEC ); +IEEE80211_IF_FILE (max_ratectrl_rateidx, max_ratectrl_rateidx,DEC );/* STA/IBSS attributes */ IEEE80211_IF_FILE (state, u.sta.state,DEC );
@@ -191,8 +193,6 @@ __IEEE80211_IF_FILE(flags);IEEE80211_IF_FILE (num_sta_ps, u.ap.num_sta_ps,ATOMIC );IEEE80211_IF_FILE (dtim_count, u.ap.dtim_count,DEC );IEEE80211_IF_FILE (num_beacons, u.ap.num_beacons,DEC ); -IEEE80211_IF_FILE (force_unicast_rateidx, u.ap.force_unicast_rateidx,DEC ); -IEEE80211_IF_FILE (max_ratectrl_rateidx, u.ap.max_ratectrl_rateidx,DEC );static ssize_t ieee80211_if_fmt_num_buffered_multicast (const struct ieee80211_sub_if_data *sdata,char *buf,int buflen)
@@ -248,6 +248,9 @@ IEEE80211_IF_WFILE(min_discovery_timeoutstatic void add_sta_files (struct ieee80211_sub_if_data *sdata) {DEBUGFS_ADD (drop_unencrypted, sta); +DEBUGFS_ADD (force_unicast_rateidx, ap); +DEBUGFS_ADD (max_ratectrl_rateidx, ap); +DEBUGFS_ADD (state, sta);DEBUGFS_ADD (bssid, sta);DEBUGFS_ADD (prev_bssid, sta);
@@ -268,23 +271,29 @@ static void add_sta_files(struct ieee802static void add_ap_files (struct ieee80211_sub_if_data *sdata) {DEBUGFS_ADD (drop_unencrypted, ap); +DEBUGFS_ADD (force_unicast_rateidx, ap); +DEBUGFS_ADD (max_ratectrl_rateidx, ap); +DEBUGFS_ADD (num_sta_ps, ap);DEBUGFS_ADD (dtim_count, ap);DEBUGFS_ADD (num_beacons, ap); -DEBUGFS_ADD (force_unicast_rateidx, ap); -DEBUGFS_ADD (max_ratectrl_rateidx, ap);DEBUGFS_ADD (num_buffered_multicast, ap); }static void add_wds_files (struct ieee80211_sub_if_data *sdata) {DEBUGFS_ADD (drop_unencrypted, wds); +DEBUGFS_ADD (force_unicast_rateidx, ap); +DEBUGFS_ADD (max_ratectrl_rateidx, ap); +DEBUGFS_ADD (peer, wds); }static void add_vlan_files (struct ieee80211_sub_if_data *sdata) {DEBUGFS_ADD (drop_unencrypted, vlan); +DEBUGFS_ADD (force_unicast_rateidx, ap); +DEBUGFS_ADD (max_ratectrl_rateidx, ap); }static void add_monitor_files (struct ieee80211_sub_if_data *sdata)
@@ -372,6 +381,9 @@ static void add_files(struct ieee80211_sstatic void del_sta_files (struct ieee80211_sub_if_data *sdata) {DEBUGFS_DEL (drop_unencrypted, sta); +DEBUGFS_DEL (force_unicast_rateidx, ap); +DEBUGFS_DEL (max_ratectrl_rateidx, ap); +DEBUGFS_DEL (state, sta);DEBUGFS_DEL (bssid, sta);DEBUGFS_DEL (prev_bssid, sta);
@@ -392,23 +404,29 @@ static void del_sta_files(struct ieee802static void del_ap_files (struct ieee80211_sub_if_data *sdata) {DEBUGFS_DEL (drop_unencrypted, ap); +DEBUGFS_DEL (force_unicast_rateidx, ap); +DEBUGFS_DEL (max_ratectrl_rateidx, ap); +DEBUGFS_DEL (num_sta_ps, ap);DEBUGFS_DEL (dtim_count, ap);DEBUGFS_DEL (num_beacons, ap); -DEBUGFS_DEL (force_unicast_rateidx, ap); -DEBUGFS_DEL (max_ratectrl_rateidx, ap);DEBUGFS_DEL (num_buffered_multicast, ap); }static void del_wds_files (struct ieee80211_sub_if_data *sdata) {DEBUGFS_DEL (drop_unencrypted, wds); +DEBUGFS_DEL (force_unicast_rateidx, ap); +DEBUGFS_DEL (max_ratectrl_rateidx, ap); +DEBUGFS_DEL (peer, wds); }static void del_vlan_files (struct ieee80211_sub_if_data *sdata) {DEBUGFS_DEL (drop_unencrypted, vlan); +DEBUGFS_DEL (force_unicast_rateidx, ap); +DEBUGFS_DEL (max_ratectrl_rateidx, ap); }static void del_monitor_files (struct ieee80211_sub_if_data *sdata)
@@ -525,7 +543,7 @@ static int netdev_notify(struct notifier {struct net_device *dev = ndev;struct dentry *dir; -struct ieee80211_sub_if_data *sdata =IEEE80211_DEV_TO_SUB_IF (dev); +struct ieee80211_sub_if_data *sdata;char buf[10 +IFNAMSIZ ];if (state !=NETDEV_CHANGENAME )
@@ -537,6 +555,8 @@ static int netdev_notify(struct notifierif (dev->ieee80211_ptr->wiphy->privid != mac80211_wiphy_privid)return 0 ; + sdata =IEEE80211_DEV_TO_SUB_IF (dev); +sprintf (buf,"netdev:%s" , dev->name); dir = sdata->debugfsdir;if (!debugfs_rename (dir->d_parent, dir, dir->d_parent, buf))
net/mac80211/rc80211_pid_algo.c +4 -4
@@ -259,8 +259,8 @@ static void rate_control_pid_tx_status(v/* Don't update the state if we're not controlling the rate. */ sdata = sta->sdata; -if (sdata->bss && sdata->bss->force_unicast_rateidx >-1 ) { - sta->txrate_idx = sdata->bss->max_ratectrl_rateidx; +if (sdata->force_unicast_rateidx >-1 ) { + sta->txrate_idx = sdata->max_ratectrl_rateidx; goto unlock; }
@@ -337,8 +337,8 @@ static void rate_control_pid_get_rate(vo/* If a forced rate is in effect, select it. */ sdata =IEEE80211_DEV_TO_SUB_IF (dev); -if (sdata->bss && sdata->bss->force_unicast_rateidx >-1 ) - sta->txrate_idx = sdata->bss->force_unicast_rateidx; +if (sdata->force_unicast_rateidx >-1 ) + sta->txrate_idx = sdata->force_unicast_rateidx; rateidx = sta->txrate_idx;
net/mac80211/cfg.c +1 -1
@@ -57,7 +57,7 @@ static int ieee80211_add_iface(struct wiif (itype ==IEEE80211_IF_TYPE_INVALID )return -EINVAL ; - err =ieee80211_if_add (local->mdev, name, &dev, itype, params); + err =ieee80211_if_add (local, name, &dev, itype, params);if (err || itype !=IEEE80211_IF_TYPE_MNTR || !flags)return err;
net/mac80211/mlme.c +19 -37
173 lines not on this page · raw message
Re: [RFT 1/4] mac80211: make master netdev handling sane
Quoted 9 lines · Johannes Berg
******
** Please test!
**
** I have not tested this patch heavily yet, especially not ** in anything other than STA mode. I believe it should work ** with the possible exception of power saving in IBSS, but ** I don't think we handle that anyway because we don't do ** anything about ATIM windows etc.
******
Are there any devices on the market which properly support PSM in Ad-Hoc mode? At least N800/N810 don't support it.
I have heard that the standard is quite unclear regarding this. And, after seeing the countless ways APs have managed to break PSM in infrastructure mode, I can only imagine what kind of interoperability problems there are with PSM in Ad-Hoc mode :)
So I think we should forget PSM in Ad-Hoc mode, at least for now.
Signature · 1 line
Kalle Valo
Johannes Berg
maintainerRe: [RFT 1/4] mac80211: make master netdev handling sane
Quoted 3 lines
Are there any devices on the market which properly support PSM in Ad-Hoc mode? At least N800/N810 don't support it.
I haven't got a clue. I didn't even know the N810 supported ad-hoc until I connected it to another network and it saved it ;)
Quoted 6 lines
I have heard that the standard is quite unclear regarding this. And, after seeing the countless ways APs have managed to break PSM in infrastructure mode, I can only imagine what kind of interoperability problems there are with PSM in Ad-Hoc mode :)
So I think we should forget PSM in Ad-Hoc mode, at least for now.
I briefly looked at 802.11-2007 and couldn't really figure out what is required and what isn't so it does seem a little unclear. I agree with you on this point, if somebody cares to research it should be easy to add back since we're not removing the AP mode code.
johannes
Johannes Berg
maintainerRe: [RFT 1/4] mac80211: make master netdev handling sane
In reply to Johannes BergQuoted 26 lines · Johannes Berg
plain text document attachment (004-mac80211-master-not-ap.patch) Currently, almost every interface type has a 'bss' pointer pointing to BSS information. This BSS information, however, is for a _local_ BSS, not for the BSS we joined, so having it on a STA mode interface makes little sense, but now they have it pointing to the master device, which is an AP mode virtual interface. However, except for some bitrate control data, this pointer is only used in AP/VLAN modes (for power saving stations.)
Overall, it is not necessary to even have the master netdev be a valid virtual interface, and it doesn't have to be on the list of interfaces either.
This patch changes the master netdev to be special, it now
- no longer is on the list of virtual interfaces, which lets me remove a lot of tests for that
- no longer hassub_if_dataattached, since that isn't usedAdditionally, this patch changes some vlan/ap mode handling that is related to these 'bss' pointers described above (but in the VLAN case they actually make sense because there they point to the AP they belong to); it also adds some debugging code to
IEEE80211_DEV_TO_SUB_IFto validate it is not called on the master netdev any more.
net/mac80211/mlme.c void ieee80211_scan_completed(struct iee · line 3909
Quoted 6 lines
net/mac80211/mlme.c +0
-5list_for_each_entry_rcu (sdata, &local->interfaces, list) { - -/* No need to wake the master device. */ -if (sdata->dev == local->mdev) -continue ; -
Just noticed that the patch was missing two hunks like that, I'll post with them when I post this for good.
johannes
Johannes Berg
maintainerPATCH 2/4 mac80211: revamp virtual interface handling
In reply to Johannes BergThis patch revamps the virtual interface handling and makes the code much easier to follow. Fewer functions, better names, less spaghetti code.
--- net/mac80211/cfg.c | 24 -- net/mac80211/debugfs.c | 15 - net/mac80211/debugfs_netdev.c | 14 - net/mac80211/debugfs_netdev.h | 5 net/mac80211/ieee80211_i.h | 21 -- net/mac80211/iface.c | 337 +++++++++++++++++++----------------------- net/mac80211/main.c | 18 -- net/mac80211/wext.c | 3 8 files changed, 172 insertions(+), 265 deletions(-)
net/mac80211/cfg.c +4 -20
@@ -50,9 +50,6 @@ static int ieee80211_add_iface(struct wistruct ieee80211_sub_if_data *sdata;int err; -if (unlikely (local->reg_state !=IEEE80211_DEV_REGISTERED )) -return -ENODEV ; - itype =nl80211_type_to_mac80211_type (type);if (itype ==IEEE80211_IF_TYPE_INVALID )return -EINVAL ;
@@ -68,35 +65,26 @@ static int ieee80211_add_iface(struct wistatic int ieee80211_del_iface (struct wiphy *wiphy,int ifindex) { -struct ieee80211_local *local =wiphy_priv (wiphy);struct net_device *dev; -char *name; - -if (unlikely (local->reg_state !=IEEE80211_DEV_REGISTERED )) -return -ENODEV ;/* we're under RTNL */ dev =__dev_get_by_index (&init_net, ifindex);if (!dev) -return 0 ; +return -ENODEV ; - name = dev->name; +ieee80211_if_remove (dev); -return ieee80211_if_remove (local->mdev, name,-1 ); +return 0 ; }static int ieee80211_change_iface (struct wiphy *wiphy,int ifindex,enum nl80211_iftype type,u32 *flags,struct vif_params *params) { -struct ieee80211_local *local =wiphy_priv (wiphy);struct net_device *dev;enum ieee80211_if_types itype;struct ieee80211_sub_if_data *sdata; -if (unlikely (local->reg_state !=IEEE80211_DEV_REGISTERED )) -return -ENODEV ; -/* we're under RTNL */ dev =__dev_get_by_index (&init_net, ifindex);if (!dev)
@@ -111,11 +99,7 @@ static int ieee80211_change_iface(struct sdata =IEEE80211_DEV_TO_SUB_IF (dev); -if (sdata->vif.type ==IEEE80211_IF_TYPE_VLAN ) -return -EOPNOTSUPP ; - -ieee80211_if_reinit (dev); -ieee80211_if_set_type (dev, itype); +ieee80211_if_change_type (sdata, itype);if (ieee80211_vif_is_mesh (&sdata->vif) && params->mesh_id_len) ieee80211_if_sta_set_mesh_id(&sdata->u.sta,
net/mac80211/ieee80211_i.h +6 -15
@@ -558,12 +558,6 @@ struct ieee80211_local {bool tim_in_locked_section;/* see ieee80211_beacon_get() */ int tx_headroom;/* required headroom for hardware/radiotap */ -enum { -IEEE80211_DEV_UNINITIALIZED =0 , -IEEE80211_DEV_REGISTERED , -IEEE80211_DEV_UNREGISTERED , - } reg_state; -/* Tasklet and skb queue to process calls from IRQ mode. All frames * added to skb_queue will be processed, but frames in * skb_queue_unreliable may be dropped if the total length of these
@@ -863,7 +857,6 @@ int ieee80211_hw_config(struct ieee80211int ieee80211_if_config (struct net_device *dev);int ieee80211_if_config_beacon (struct net_device *dev);void ieee80211_tx_set_protected (struct ieee80211_tx_data *tx); -void ieee80211_if_setup (struct net_device *dev);u32 ieee80211_handle_ht (struct ieee80211_local *local,int enable_ht,struct ieee80211_ht_info *req_ht_cap,struct ieee80211_ht_bss_info *req_bss_cap);
@@ -932,16 +925,14 @@ static inline void ieee80211_start_mesh(#endif /* interface handling */ +void ieee80211_if_setup (struct net_device *dev);int ieee80211_if_add (struct ieee80211_local *local,const char *name, -struct net_device **new_dev,int type, +struct net_device **new_dev,enum ieee80211_if_types type,struct vif_params *params); -void ieee80211_if_set_type (struct net_device *dev,int type); -void ieee80211_if_reinit (struct net_device *dev); -void __ieee80211_if_del (struct ieee80211_local *local, -struct ieee80211_sub_if_data *sdata); -int ieee80211_if_remove (struct net_device *dev,const char *name,int id); -void ieee80211_if_free (struct net_device *dev); -void ieee80211_if_sdata_init (struct ieee80211_sub_if_data *sdata); +void ieee80211_if_change_type (struct ieee80211_sub_if_data *sdata, +enum ieee80211_if_types type); +void ieee80211_if_remove (struct net_device *dev); +void ieee80211_remove_interfaces (struct ieee80211_local *local);/* tx handling */ void ieee80211_clear_tx_pending (struct ieee80211_local *local);
net/mac80211/iface.c +153 -184
408 lines not on this page · raw message
net/mac80211/debugfs.c +1 -14
@@ -70,16 +70,6 @@ DEBUGFS_READONLY_FILE(rate_ctrl_alg, 100/* statistics stuff */ -static inline int rtnl_lock_local (struct ieee80211_local *local) -{ -rtnl_lock (); -if (unlikely (local->reg_state !=IEEE80211_DEV_REGISTERED )) { -rtnl_unlock (); -return -ENODEV ; - } -return 0 ; -} - #define DEBUGFS_STATS_FILE(name, buflen, fmt, value...) \ DEBUGFS_READONLY_FILE(stats_ ##name, buflen, fmt, ##value)
@@ -96,10 +86,7 @@ static ssize_t format_devstat_counter(stif (!local->ops->get_stats)return -EOPNOTSUPP ; - res =rtnl_lock_local (local); -if (res) -return res; - +rtnl_lock (); res = local->ops->get_stats (local_to_hw (local), &stats);rtnl_unlock ();if (!res)
net/mac80211/main.c +3 -15
@@ -965,7 +965,6 @@ static const struct header_ops ieee80211 .cache_update = eth_header_cache_update, }; -/* Must not be called for mdev */ void ieee80211_if_setup (struct net_device *dev) {ether_setup (dev);
@@ -975,7 +974,7 @@ void ieee80211_if_setup(struct net_devic dev->change_mtu = ieee80211_change_mtu; dev->open = ieee80211_open; dev->stop = ieee80211_stop; - dev->destructor = ieee80211_if_free; + dev->destructor = free_netdev; }/* everything else */
@@ -1772,7 +1771,6 @@ int ieee80211_register_hw(struct ieee802printk (KERN_WARNING "%s: Failed to add default virtual iface\n" ,wiphy_name (local->hw.wiphy)); - local->reg_state =IEEE80211_DEV_REGISTERED ;rtnl_unlock ();ieee80211_led_init (local);
@@ -1802,30 +1800,20 @@ EXPORT_SYMBOL(ieee80211_register_hw);void ieee80211_unregister_hw (struct ieee80211_hw *hw) {struct ieee80211_local *local =hw_to_local (hw); -struct ieee80211_sub_if_data *sdata, *tmp;tasklet_kill (&local->tx_pending_tasklet);tasklet_kill (&local->tasklet);rtnl_lock (); -BUG_ON (local->reg_state !=IEEE80211_DEV_REGISTERED ); - - local->reg_state =IEEE80211_DEV_UNREGISTERED ; -/* * At this point, interface list manipulations are fine * because the driver cannot be handing us frames any * more and the tasklet is killed. */ -/* -* First, we remove all virtual interfaces. -*/ -list_for_each_entry_safe (sdata, tmp, &local->interfaces, list) { -list_del (&sdata->list); -__ieee80211_if_del (local, sdata); - } +/* First, we remove all virtual interfaces. */ +ieee80211_remove_interfaces (local);/* then, finally, remove the master interface */ unregister_netdevice (local->mdev);
net/mac80211/wext.c +1 -2
@@ -301,8 +301,7 @@ static int ieee80211_ioctl_siwmode(strucif (netif_running (dev))return -EBUSY ; -ieee80211_if_reinit (dev); -ieee80211_if_set_type (dev, type); +ieee80211_if_change_type (sdata, type);return 0 ; }
net/mac80211/debugfs_netdev.c +4 -10
@@ -476,12 +476,12 @@ static void del_mesh_config(struct ieee8 }#endif -static void del_files (struct ieee80211_sub_if_data *sdata,int type) +static void del_files (struct ieee80211_sub_if_data *sdata) {if (!sdata->debugfsdir)return ; -switch (type) { +switch (sdata->vif.type) {case IEEE80211_IF_TYPE_MESH_POINT :#ifdef CONFIG_MAC80211_MESH del_mesh_stats (sdata);
@@ -521,22 +521,16 @@ void ieee80211_debugfs_add_netdev(structsprintf (buf,"netdev:%s" , sdata->dev->name); sdata->debugfsdir =debugfs_create_dir (buf, sdata->local->hw.wiphy->debugfsdir); +add_files (sdata); }void ieee80211_debugfs_remove_netdev (struct ieee80211_sub_if_data *sdata) { -del_files (sdata, sdata->vif.type); +del_files (sdata);debugfs_remove (sdata->debugfsdir); sdata->debugfsdir =NULL ; } -void ieee80211_debugfs_change_if_type (struct ieee80211_sub_if_data *sdata, -int oldtype) -{ -del_files (sdata, oldtype); -add_files (sdata); -} -static int netdev_notify (struct notifier_block *nb,unsigned long state,void *ndev)
net/mac80211/debugfs_netdev.h +0 -5
@@ -6,8 +6,6 @@#ifdef CONFIG_MAC80211_DEBUGFS void ieee80211_debugfs_add_netdev (struct ieee80211_sub_if_data *sdata);void ieee80211_debugfs_remove_netdev (struct ieee80211_sub_if_data *sdata); -void ieee80211_debugfs_change_if_type (struct ieee80211_sub_if_data *sdata, -int oldtype);void ieee80211_debugfs_netdev_init (void );void ieee80211_debugfs_netdev_exit (void );#else
@@ -17,9 +15,6 @@ static inline void ieee80211_debugfs_addstatic inline void ieee80211_debugfs_remove_netdev (struct ieee80211_sub_if_data *sdata) {} -static inline void ieee80211_debugfs_change_if_type ( -struct ieee80211_sub_if_data *sdata,int oldtype) -{}static inline void ieee80211_debugfs_netdev_init (void ) {}
Johannes Berg
maintainerPATCH 3/4 mac80211: push interface checks down
In reply to Johannes BergThis patch pushes the "netif_running()" and "same type as before" checks down into ieee80211_if_change_type() to centralise the logic instead of duplicating it for cfg80211 and wext.
--- net/mac80211/cfg.c | 8 ++++---- net/mac80211/ieee80211_i.h | 4 ++-- net/mac80211/iface.c | 20 ++++++++++++++++++-- net/mac80211/wext.c | 9 +-------- 4 files changed, 25 insertions(+), 16 deletions(-)
net/mac80211/cfg.c +4 -4
@@ -84,22 +84,22 @@ static int ieee80211_change_iface(structstruct net_device *dev;enum ieee80211_if_types itype;struct ieee80211_sub_if_data *sdata; +int ret;/* we're under RTNL */ dev =__dev_get_by_index (&init_net, ifindex);if (!dev)return -ENODEV ; -if (netif_running (dev)) -return -EBUSY ; - itype =nl80211_type_to_mac80211_type (type);if (itype ==IEEE80211_IF_TYPE_INVALID )return -EINVAL ; sdata =IEEE80211_DEV_TO_SUB_IF (dev); -ieee80211_if_change_type (sdata, itype); + ret =ieee80211_if_change_type (sdata, itype); +if (ret) +return ret;if (ieee80211_vif_is_mesh (&sdata->vif) && params->mesh_id_len) ieee80211_if_sta_set_mesh_id(&sdata->u.sta,
net/mac80211/ieee80211_i.h +2 -2
@@ -929,8 +929,8 @@ void ieee80211_if_setup(struct net_devicint ieee80211_if_add (struct ieee80211_local *local,const char *name,struct net_device **new_dev,enum ieee80211_if_types type,struct vif_params *params); -void ieee80211_if_change_type (struct ieee80211_sub_if_data *sdata, -enum ieee80211_if_types type); +int ieee80211_if_change_type (struct ieee80211_sub_if_data *sdata, +enum ieee80211_if_types type);void ieee80211_if_remove (struct net_device *dev);void ieee80211_remove_interfaces (struct ieee80211_local *local);
net/mac80211/iface.c +18 -2
@@ -138,9 +138,23 @@ static void ieee80211_setup_sdata(structieee80211_debugfs_add_netdev (sdata); } -void ieee80211_if_change_type (struct ieee80211_sub_if_data *sdata, -enum ieee80211_if_types type) +int ieee80211_if_change_type (struct ieee80211_sub_if_data *sdata, +enum ieee80211_if_types type) { +ASSERT_RTNL (); + +if (type == sdata->vif.type) +return 0 ; + +/* +* We could, here, on changes between IBSS/STA/MESH modes, +* invoke an MLME function instead that disassociates etc. +* and goes into the requested mode. +*/ + +if (netif_running (sdata->dev)) +return -EBUSY ; +/* Purge and reset type-dependent state. */ ieee80211_teardown_sdata (sdata->dev);ieee80211_setup_sdata (sdata, type);
@@ -149,6 +163,8 @@ void ieee80211_if_change_type(struct iee sdata->basic_rates =0 ; sdata->drop_unencrypted =0 ; sdata->sequence =0 ; + +return 0 ; } int ieee80211_if_add(struct ieee80211_local *local, const char *name,
net/mac80211/wext.c +1 -8
@@ -296,14 +296,7 @@ static int ieee80211_ioctl_siwmode(strucreturn -EINVAL ; } -if (type == sdata->vif.type) -return 0 ; -if (netif_running (dev)) -return -EBUSY ; - -ieee80211_if_change_type (sdata, type); - -return 0 ; +return ieee80211_if_change_type (sdata, type); }
Johannes Berg
maintainerPATCH 4/4 mac80211: revamp beacon configuration
In reply to Johannes BergThis patch changes mac80211's beacon configuration handling to never pass skbs to the driver directly but rather always require the driver to use ieee80211_beacon_get(). Additionally, it introduces "change flags" on the config_interface() call to enable drivers to figure out what is changing. Finally, it removes the beacon_update() driver callback in favour of having IBSS beacon delivered by ieee80211_beacon_get() as well.
--- drivers/net/wireless/ath5k/base.c | 13 +++ drivers/net/wireless/b43/main.c | 48 +++++------- drivers/net/wireless/b43legacy/main.c | 45 ++++------- drivers/net/wireless/iwlwifi/iwl3945-base.c | 19 ++++ drivers/net/wireless/iwlwifi/iwl4965-base.c | 18 +++- drivers/net/wireless/rt2x00/rt2400pci.c | 2 drivers/net/wireless/rt2x00/rt2500pci.c | 2 drivers/net/wireless/rt2x00/rt2500usb.c | 2 drivers/net/wireless/rt2x00/rt2x00.h | 2 drivers/net/wireless/rt2x00/rt2x00dev.c | 10 +- drivers/net/wireless/rt2x00/rt2x00mac.c | 22 ++++- drivers/net/wireless/rt2x00/rt61pci.c | 2 drivers/net/wireless/rt2x00/rt73usb.c | 2 drivers/net/wireless/zd1211rw/zd_mac.c | 21 +---- include/net/mac80211.h | 49 ++++-------- net/mac80211/cfg.c | 4 - net/mac80211/ieee80211_i.h | 3 net/mac80211/main.c | 59 ++++++-------- net/mac80211/mlme.c | 112 +++++++++++----------------- net/mac80211/tx.c | 36 +++++---- net/mac80211/wext.c | 2 21 files changed, 225 insertions(+), 248 deletions(-)
include/net/mac80211.h +16 -33
@@ -519,33 +519,38 @@ struct ieee80211_if_init_conf { };/** +* enum ieee80211_if_conf_change - interface config change flags +* +* @IEEE80211_IFCC_BSSID: The BSSID changed. +* @IEEE80211_IFCC_SSID: The SSID changed. +* @IEEE80211_IFCC_BEACON: The beacon for this interface changed +* (currently AP and MESH only), use ieee80211_beacon_get(). +*/ +enum ieee80211_if_conf_change { +IEEE80211_IFCC_BSSID =BIT (0 ), +IEEE80211_IFCC_SSID =BIT (1 ), +IEEE80211_IFCC_BEACON =BIT (2 ), +}; + +/** * struct ieee80211_if_conf - configuration of an interface * -* @type: type of the interface. This is always the same as was specified in -* &struct ieee80211_if_init_conf. The type of an interface never changes -* during the life of the interface; this field is present only for -* convenience. +* @changed: parameters that have changed, see &enum ieee80211_if_conf_change. * @bssid: BSSID of the network we are associated to/creating. * @ssid: used (together with @ssid_len) by drivers for hardware that * generate beacons independently. The pointer is valid only during the * config_interface() call, so copy the value somewhere if you need * it. * @ssid_len: length of the @ssid field. -* @beacon: beacon template. Valid only if @host_gen_beacon_template in -* &struct ieee80211_hw is set. The driver is responsible of freeing -* the sk_buff. -* @beacon_control: tx_control for the beacon template, this field is only -* valid when the @beacon field was set. * * This structure is passed to the config_interface() callback of * &struct ieee80211_hw. */ struct ieee80211_if_conf { -int type; +u32 changed;u8 *bssid;u8 *ssid;size_t ssid_len; -struct sk_buff *beacon; };/**
@@ -673,15 +678,6 @@ enum ieee80211_tkip_key_type {* any particular flags. There are some exceptions to this rule, * however, so you are advised to review these flags carefully. * -* @IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE: -* The device only needs to be supplied with a beacon template. -* If you need the host to generate each beacon then don't use -* this flag and call ieee80211_beacon_get() when you need the -* next beacon frame. Note that if you set this flag, you must -* implement the set_tim() callback for powersave mode to work -* properly. -* This flag is only relevant for access-point mode. -* * @IEEE80211_HW_RX_INCLUDES_FCS: * Indicates that received frames passed to the stack include * the FCS at the end.
@@ -1141,17 +1137,6 @@ enum ieee80211_ampdu_mlme_action {* function is optional if the firmware/hardware takes full care of * TSF synchronization. * -* @beacon_update: Setup beacon data for IBSS beacons. Unlike access point, -* IBSS uses a fixed beacon frame which is configured using this -* function. -* If the driver returns success (0) from this callback, it owns -* the skb. That means the driver is responsible to kfree_skb() it. -* The control structure is not dynamically allocated. That means the -* driver does not own the pointer and if it needs it somewhere -* outside of the context of this function, it must copy it -* somewhere else. -* This handler is required only for IBSS mode. -* * @tx_last_beacon: Determine whether the last IBSS beacon was sent by us. * This is needed only for IBSS mode and the result of this function is * used to determine whether to reply to Probe Requests.
@@ -1209,8 +1194,6 @@ struct ieee80211_ops { struct ieee80211_tx_queue_stats *stats);u64 (*get_tsf)(struct ieee80211_hw *hw);void (*reset_tsf)(struct ieee80211_hw *hw); -int (*beacon_update)(struct ieee80211_hw *hw, -struct sk_buff *skb);int (*tx_last_beacon)(struct ieee80211_hw *hw); int (*ampdu_action)(struct ieee80211_hw *hw, enum ieee80211_ampdu_mlme_action action,
net/mac80211/cfg.c +2 -2
@@ -469,7 +469,7 @@ static int ieee80211_config_beacon(struckfree (old); -return ieee80211_if_config_beacon (sdata->dev); +return ieee80211_if_config (sdata,IEEE80211_IFCC_BEACON ); } static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev,
@@ -523,7 +523,7 @@ static int ieee80211_del_beacon(struct wsynchronize_rcu ();kfree (old); -return ieee80211_if_config_beacon (dev); +return ieee80211_if_config (sdata,IEEE80211_IFCC_BEACON ); }/* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */
net/mac80211/ieee80211_i.h +1 -2
@@ -854,8 +854,7 @@ static inline int ieee80211_bssid_match(/* ieee80211.c */ int ieee80211_hw_config (struct ieee80211_local *local); -int ieee80211_if_config (struct net_device *dev); -int ieee80211_if_config_beacon (struct net_device *dev); +int ieee80211_if_config (struct ieee80211_sub_if_data *sdata,u32 changed);void ieee80211_tx_set_protected (struct ieee80211_tx_data *tx); u32 ieee80211_handle_ht(struct ieee80211_local *local, int enable_ht, struct ieee80211_ht_info *req_ht_cap,
net/mac80211/main.c +25 -34
89 lines not on this page · raw message
net/mac80211/mlme.c +45 -67
182 lines not on this page · raw message
net/mac80211/wext.c +1 -1
@@ -444,7 +444,7 @@ static int ieee80211_ioctl_siwessid(strumemset (sdata->u.ap.ssid + len,0 ,IEEE80211_MAX_SSID_LEN - len); sdata->u.ap.ssid_len = len; -return ieee80211_if_config (dev); +return ieee80211_if_config (sdata,IEEE80211_IFCC_SSID ); }return -EOPNOTSUPP ; }
drivers/net/wireless/b43/main.c +20 -28
82 lines not on this page · raw message
drivers/net/wireless/ath5k/base.c +12 -1
@@ -207,7 +207,6 @@ static struct ieee80211_ops ath5k_hw_ops .get_tx_stats = ath5k_get_tx_stats, .get_tsf = ath5k_get_tsf, .reset_tsf = ath5k_reset_tsf, - .beacon_update = ath5k_beacon_update, };/*
@@ -2785,6 +2784,18 @@ ath5k_config_interface(struct ieee80211_* a clean way of letting us retrieve this yet. */ ath5k_hw_set_associd (ah, ah->ah_bssid,0 ); } + +if (conf->changed &IEEE80211_IFCC_BEACON && + vif->type ==IEEE80211_IF_TYPE_IBSS ) { +struct sk_buff *beacon =ieee80211_beacon_get (hw, vif); +if (!beacon) { + ret = -ENOMEM ; + goto unlock; + } +/* call old handler for now */ +ath5k_beacon_update (hw, beacon); + } +mutex_unlock (&sc->lock);return ath5k_reset (hw);
drivers/net/wireless/b43legacy/main.c +17 -28
79 lines not on this page · raw message
drivers/net/wireless/iwlwifi/iwl3945-base.c +16 -3
@@ -6889,6 +6889,9 @@ static void iwl3945_config_ap(struct iwl* clear sta table, add BCAST sta... */ } +/* temporary */ +static int iwl3945_mac_beacon_update (struct ieee80211_hw *hw,struct sk_buff *skb); +static int iwl3945_mac_config_interface (struct ieee80211_hw *hw,struct ieee80211_vif *vif,struct ieee80211_if_conf *conf)
@@ -6906,10 +6909,21 @@ static int iwl3945_mac_config_interface(return 0 ; } +/* handle this temporarily here */ +if (priv->iw_mode ==IEEE80211_IF_TYPE_IBSS && + conf->changed &IEEE80211_IFCC_BEACON ) { +struct sk_buff *beacon =ieee80211_beacon_get (hw, vif); +if (!beacon) +return -ENOMEM ; + rc =iwl3945_mac_beacon_update (hw, beacon); +if (rc) +return rc; + } +/* XXX: this MUST use conf->mac_addr */ if ((priv->iw_mode ==IEEE80211_IF_TYPE_AP ) && - (!conf->beacon || !conf->ssid_len)) { + (!conf->ssid_len)) {IWL_DEBUG_MAC80211 ("Leaving in AP mode because HostAPD is not ready.\n" );return 0 ;
@@ -6941,7 +6955,7 @@ static int iwl3945_mac_config_interface(if (priv->ibss_beacon)dev_kfree_skb (priv->ibss_beacon); - priv->ibss_beacon = conf->beacon; + priv->ibss_beacon =ieee80211_beacon_get (hw, vif); }if (iwl3945_is_rfkill (priv))
@@ -7922,7 +7936,6 @@ static struct ieee80211_ops iwl3945_hw_o .conf_tx = iwl3945_mac_conf_tx, .get_tsf = iwl3945_mac_get_tsf, .reset_tsf = iwl3945_mac_reset_tsf, - .beacon_update = iwl3945_mac_beacon_update, .hw_scan = iwl3945_mac_hw_scan };
drivers/net/wireless/iwlwifi/iwl4965-base.c +15 -3
@@ -2912,6 +2912,9 @@ static void iwl4965_config_ap(struct iwl* clear sta table, add BCAST sta... */ } +/* temporary */ +static int iwl4965_mac_beacon_update (struct ieee80211_hw *hw,struct sk_buff *skb); +static int iwl4965_mac_config_interface (struct ieee80211_hw *hw,struct ieee80211_vif *vif,struct ieee80211_if_conf *conf)
@@ -2929,8 +2932,18 @@ static int iwl4965_mac_config_interface(return 0 ; } +if (priv->iw_mode ==IEEE80211_IF_TYPE_IBSS && + conf->changed &IEEE80211_IFCC_BEACON ) { +struct sk_buff *beacon =ieee80211_beacon_get (hw, vif); +if (!beacon) +return -ENOMEM ; + rc =iwl4965_mac_beacon_update (hw, beacon); +if (rc) +return rc; + } +if ((priv->iw_mode ==IEEE80211_IF_TYPE_AP ) && - (!conf->beacon || !conf->ssid_len)) { + (!conf->ssid_len)) {IWL_DEBUG_MAC80211 ("Leaving in AP mode because HostAPD is not ready.\n" );return 0 ;
@@ -2962,7 +2975,7 @@ static int iwl4965_mac_config_interface(if (priv->ibss_beacon)dev_kfree_skb (priv->ibss_beacon); - priv->ibss_beacon = conf->beacon; + priv->ibss_beacon =ieee80211_beacon_get (hw, vif); }if (iwl_is_rfkill (priv))
@@ -4090,7 +4103,6 @@ static struct ieee80211_ops iwl4965_hw_o .get_tx_stats = iwl4965_mac_get_tx_stats, .conf_tx = iwl4965_mac_conf_tx, .reset_tsf = iwl4965_mac_reset_tsf, - .beacon_update = iwl4965_mac_beacon_update, .bss_info_changed = iwl4965_bss_info_changed, .ampdu_action = iwl4965_mac_ampdu_action, .hw_scan = iwl4965_mac_hw_scan
drivers/net/wireless/rt2x00/rt2400pci.c +1 -1
@@ -1558,7 +1558,6 @@ static const struct ieee80211_ops rt2400 .conf_tx = rt2400pci_conf_tx, .get_tx_stats = rt2x00mac_get_tx_stats, .get_tsf = rt2400pci_get_tsf, - .beacon_update = rt2400pci_beacon_update, .tx_last_beacon = rt2400pci_tx_last_beacon, };
@@ -1578,6 +1577,7 @@ static const struct rt2x00lib_ops rt2400 .write_tx_data = rt2x00pci_write_tx_data, .kick_tx_queue = rt2400pci_kick_tx_queue, .fill_rxdone = rt2400pci_fill_rxdone, + .beacon_update = rt2400pci_beacon_update, .config_filter = rt2400pci_config_filter, .config_intf = rt2400pci_config_intf, .config_erp = rt2400pci_config_erp,
drivers/net/wireless/rt2x00/rt2500pci.c +1 -1
@@ -1875,7 +1875,6 @@ static const struct ieee80211_ops rt2500 .conf_tx = rt2x00mac_conf_tx, .get_tx_stats = rt2x00mac_get_tx_stats, .get_tsf = rt2500pci_get_tsf, - .beacon_update = rt2500pci_beacon_update, .tx_last_beacon = rt2500pci_tx_last_beacon, };
@@ -1895,6 +1894,7 @@ static const struct rt2x00lib_ops rt2500 .write_tx_data = rt2x00pci_write_tx_data, .kick_tx_queue = rt2500pci_kick_tx_queue, .fill_rxdone = rt2500pci_fill_rxdone, + .beacon_update = rt2500pci_beacon_update, .config_filter = rt2500pci_config_filter, .config_intf = rt2500pci_config_intf, .config_erp = rt2500pci_config_erp,
drivers/net/wireless/rt2x00/rt2500usb.c +1 -1
@@ -1775,7 +1775,6 @@ static const struct ieee80211_ops rt2500 .bss_info_changed = rt2x00mac_bss_info_changed, .conf_tx = rt2x00mac_conf_tx, .get_tx_stats = rt2x00mac_get_tx_stats, - .beacon_update = rt2500usb_beacon_update, };static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
@@ -1793,6 +1792,7 @@ static const struct rt2x00lib_ops rt2500 .get_tx_data_len = rt2500usb_get_tx_data_len, .kick_tx_queue = rt2500usb_kick_tx_queue, .fill_rxdone = rt2500usb_fill_rxdone, + .beacon_update = rt2500usb_beacon_update, .config_filter = rt2500usb_config_filter, .config_intf = rt2500usb_config_intf, .config_erp = rt2500usb_config_erp,
drivers/net/wireless/rt2x00/rt2x00.h +2 -0
@@ -534,6 +534,8 @@ struct rt2x00lib_ops {/* * Configuration handlers. */ +int (*beacon_update) (struct ieee80211_hw *hw,struct sk_buff *bcn); +void (*config_filter) (struct rt2x00_dev *rt2x00dev,const unsigned int filter_flags); void (*config_intf) (struct rt2x00_dev *rt2x00dev,
drivers/net/wireless/rt2x00/rt2x00dev.c +5 -5
@@ -409,7 +409,6 @@ static void rt2x00lib_intf_scheduled_ite {struct rt2x00_dev *rt2x00dev = data;struct rt2x00_intf *intf =vif_to_intf (vif); -struct sk_buff *skb;struct ieee80211_bss_conf conf;int delayed_flags;
@@ -436,10 +435,11 @@ static void rt2x00lib_intf_scheduled_itereturn ;if (delayed_flags &DELAYED_UPDATE_BEACON ) { - skb =ieee80211_beacon_get (rt2x00dev->hw, vif); -if (skb && - rt2x00dev->ops->hw->beacon_update (rt2x00dev->hw, skb)) -dev_kfree_skb (skb); +struct ieee80211_if_conf conf; + conf.bssid = conf.ssid =NULL ; + conf.ssid_len =0 ; + conf.changed =IEEE80211_IFCC_BEACON ; + rt2x00dev->ops->hw->config_interface (rt2x00dev->hw, vif, &conf); }if (delayed_flags &DELAYED_CONFIG_ERP )
drivers/net/wireless/rt2x00/rt2x00mac.c +16 -6
@@ -348,6 +348,7 @@ int rt2x00mac_config_interface(struct ie {struct rt2x00_dev *rt2x00dev = hw->priv;struct rt2x00_intf *intf =vif_to_intf (vif); +struct sk_buff *beacon;int status;/*
@@ -363,8 +364,11 @@ int rt2x00mac_config_interface(struct ie* If the interface does not work in master mode, * then the bssid value in the interface structure * should now be set. +* +* conf->bssid can be NULL if coming from the internal +* beacon update routine. */ -if (conf->type !=IEEE80211_IF_TYPE_AP ) +if (conf->bssid && vif->type !=IEEE80211_IF_TYPE_AP )memcpy (&intf->bssid, conf->bssid,ETH_ALEN );spin_unlock (&intf->lock);
@@ -375,17 +379,23 @@ int rt2x00mac_config_interface(struct ie* values as arguments we make keep access to rt2x00_intf thread safe * even without the lock. */ -rt2x00lib_config_intf (rt2x00dev, intf, conf->type,NULL , conf->bssid); +rt2x00lib_config_intf (rt2x00dev, intf, vif->type,NULL , conf->bssid);/* -* We only need to initialize the beacon when master mode is enabled. +* We only need to initialize the beacon when in master/ibss mode. */ -if (conf->type !=IEEE80211_IF_TYPE_AP || !conf->beacon) +if ((vif->type !=IEEE80211_IF_TYPE_AP && + vif->type !=IEEE80211_IF_TYPE_IBSS ) || + !(conf->changed &IEEE80211_IFCC_BEACON ))return 0 ; - status = rt2x00dev->ops->hw->beacon_update (rt2x00dev->hw, conf->beacon); + beacon =ieee80211_beacon_get (rt2x00dev->hw, vif); +if (!beacon) +return -ENOMEM ; + + status = rt2x00dev->ops->lib->beacon_update (rt2x00dev->hw, beacon);if (status) -dev_kfree_skb (conf->beacon); +dev_kfree_skb (beacon);return status; }
drivers/net/wireless/rt2x00/rt61pci.c +1 -1
@@ -2427,7 +2427,6 @@ static const struct ieee80211_ops rt61pc .conf_tx = rt2x00mac_conf_tx, .get_tx_stats = rt2x00mac_get_tx_stats, .get_tsf = rt61pci_get_tsf, - .beacon_update = rt61pci_beacon_update, };static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
@@ -2449,6 +2448,7 @@ static const struct rt2x00lib_ops rt61pc .write_tx_data = rt2x00pci_write_tx_data, .kick_tx_queue = rt61pci_kick_tx_queue, .fill_rxdone = rt61pci_fill_rxdone, + .beacon_update = rt61pci_beacon_update, .config_filter = rt61pci_config_filter, .config_intf = rt61pci_config_intf, .config_erp = rt61pci_config_erp,
drivers/net/wireless/rt2x00/rt73usb.c +1 -1
@@ -2031,7 +2031,6 @@ static const struct ieee80211_ops rt73us .conf_tx = rt2x00mac_conf_tx, .get_tx_stats = rt2x00mac_get_tx_stats, .get_tsf = rt73usb_get_tsf, - .beacon_update = rt73usb_beacon_update, };static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
@@ -2052,6 +2051,7 @@ static const struct rt2x00lib_ops rt73us .get_tx_data_len = rt73usb_get_tx_data_len, .kick_tx_queue = rt73usb_kick_tx_queue, .fill_rxdone = rt73usb_fill_rxdone, + .beacon_update = rt73usb_beacon_update, .config_filter = rt73usb_config_filter, .config_intf = rt73usb_config_intf, .config_erp = rt73usb_config_erp,
drivers/net/wireless/zd1211rw/zd_mac.c +6 -15
@@ -703,9 +703,12 @@ static int zd_op_config_interface(structif (mac->type ==IEEE80211_IF_TYPE_MESH_POINT || mac->type ==IEEE80211_IF_TYPE_IBSS ) { associated = true; -if (conf->beacon) { -zd_mac_config_beacon (hw, conf->beacon); -kfree_skb (conf->beacon); +if (conf->changed &IEEE80211_IFCC_BEACON ) { +struct sk_buff *beacon =ieee80211_beacon_get (hw, vif); +if (!beacon) +return -ENOMEM ; +zd_mac_config_beacon (hw, beacon); +kfree_skb (beacon);zd_set_beacon_interval (&mac->chip,BCN_MODE_IBSS | hw->conf.beacon_int); }
@@ -861,17 +864,6 @@ static void zd_op_bss_info_changed(struc } } -static int zd_op_beacon_update (struct ieee80211_hw *hw, -struct sk_buff *skb) -{ -struct zd_mac *mac =zd_hw_mac (hw); -zd_mac_config_beacon (hw, skb); -kfree_skb (skb); -zd_set_beacon_interval (&mac->chip,BCN_MODE_IBSS | - hw->conf.beacon_int); -return 0 ; -} -static const struct ieee80211_ops zd_ops = { .tx = zd_op_tx, .start = zd_op_start,
@@ -882,7 +874,6 @@ static const struct ieee80211_ops zd_ops .config_interface = zd_op_config_interface, .configure_filter = zd_op_configure_filter, .bss_info_changed = zd_op_bss_info_changed, - .beacon_update = zd_op_beacon_update, };struct ieee80211_hw *zd_mac_alloc_hw (struct usb_interface *intf)
net/mac80211/tx.c +21 -15
@@ -1795,17 +1795,17 @@ struct sk_buff *ieee80211_beacon_get(str struct ieee80211_vif *vif) {struct ieee80211_local *local =hw_to_local (hw); -struct sk_buff *skb; +struct sk_buff *skb =NULL ;struct ieee80211_tx_info *info;struct net_device *bdev;struct ieee80211_sub_if_data *sdata =NULL ;struct ieee80211_if_ap *ap =NULL ; +struct ieee80211_if_sta *ifsta =NULL ;struct rate_selection rsel;struct beacon_data *beacon;struct ieee80211_supported_band *sband;struct ieee80211_mgmt *mgmt;int *num_beacons; -bool err = true;enum ieee80211_band band = local->hw.conf.channel->band;u8 *pos;
@@ -1859,9 +1859,24 @@ struct sk_buff *ieee80211_beacon_get(str beacon->tail, beacon->tail_len); num_beacons = &ap->num_beacons; + }else + goto out; + }else if (sdata->vif.type ==IEEE80211_IF_TYPE_IBSS ) { +struct ieee80211_hdr *hdr; + ifsta = &sdata->u.sta; - err = false; - } +if (!ifsta->probe_resp) + goto out; + + skb =skb_copy (ifsta->probe_resp,GFP_ATOMIC ); +if (!skb) + goto out; + + hdr = (struct ieee80211_hdr *) skb->data; + hdr->frame_control =IEEE80211_FC (IEEE80211_FTYPE_MGMT , +IEEE80211_STYPE_BEACON ); + + num_beacons = &ifsta->num_beacons; }else if (ieee80211_vif_is_mesh (&sdata->vif)) {/* headroom, head length, tail length and maximum TIM length */ skb =dev_alloc_skb (local->tx_headroom +400 );
@@ -1888,17 +1903,8 @@ struct sk_buff *ieee80211_beacon_get(strmesh_mgmt_ies_add (skb, sdata->dev); num_beacons = &sdata->u.sta.num_beacons; - - err = false; - } - -if (err) { -#ifdef CONFIG_MAC80211_VERBOSE_DEBUG -if (net_ratelimit ()) -printk (KERN_DEBUG "no beacon data avail for %s\n" , - bdev->name); -#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ - skb =NULL ; + }else { +WARN_ON (1 ); goto out; }
Quoted 9 lines · Johannes Berg
Here are a number of improvements for mac80211's virtual interface handling (master netdev, cleanups) and driver API (beaconing).
I have tested these patches on b43 in AP, STA and IBSS modes (communicating with my N810 or an AP) and have not seen any issues.
I would appreciate testing on other hardware (I can probably cover iwl4965, rt61pci and zd1211 next week), but I don't expect much trouble.
I have added these patches to rt2x00.git for testing purposes.
And to be more precise, the following patches have been added:
004-mac80211-master-not-ap.patch
005-mac80211-iface-cleanups.patch
006-mac80211-push-alive-check-down.patch
007-mac80211-beacon-revamp.patch
008-deprecate-sys-wireless.patch
009-local-bh-enable-consolidate.patch
010-linux-radiotap-rxflags.patch
011-allow-ap-vlan-modes.patch
Ivo
Johannes Berg
maintainerQuoted 4 lines · Ivo van Doorn
Quoted 3 lines · Johannes Berg
Here are a number of improvements for mac80211's virtual interface handling (master netdev, cleanups) and driver API (beaconing).
Quoted 8 lines
Quoted 6 lines
I have tested these patches on b43 in AP, STA and IBSS modes (communicating with my N810 or an AP) and have not seen any issues.
I would appreciate testing on other hardware (I can probably cover iwl4965, rt61pci and zd1211 next week), but I don't expect much trouble.
I have added these patches to rt2x00.git for testing purposes.
Cool, thanks, let me know of any problems.
Quoted 6 lines
And to be more precise, the following patches have been added:
004-mac80211-master-not-ap.patch
005-mac80211-iface-cleanups.patch
006-mac80211-push-alive-check-down.patch
007-mac80211-beacon-revamp.patch
Those I intend to push soonish.
Quoted 1 line
008-deprecate-sys-wireless.patch
That one too, but hal (depends on it, patch is in git) needs a new release first I guess.
Quoted 1 line
009-local-bh-enable-consolidate.patch
Ingo Molnar is handling that one.
Quoted 1 line
010-linux-radiotap-rxflags.patch
Pending radiotap list discussion about those new things, but I'm fairly confident I'll post this one too this or next week.
Quoted 1 line
011-allow-ap-vlan-modes.patch
Well that we all know about :)
johannes