diff options
author | Helmut Schaa <helmut.schaa@googlemail.com> | 2011-01-30 15:16:03 +0300 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-01-31 23:06:22 +0300 |
commit | 69cf36a4523be026bc16743c5c989c5e82edb7d9 (patch) | |
tree | 0c6572b724d840d879ff12861d8ac57da1bad635 /drivers/net/wireless/rt2x00/rt2x00mac.c | |
parent | d828cd5a95e532636dbc495e4b94b625ab9abdad (diff) | |
download | linux-69cf36a4523be026bc16743c5c989c5e82edb7d9.tar.xz |
rt2x00: Refactor beacon code to make use of start- and stop_queue
This patch allows to dynamically remove beaconing interfaces without
shutting beaconing down on all interfaces.
The only place to start and stop beaconing are now the start- and
stop_queue callbacks. Hence, we can remove some register writes during
interface bring up (config_intf) and only write the correct sync mode
to the register there.
When multiple beaconing interfaces are present we should enable
beaconing as soon as mac80211 enables beaconing on at least one of
them. The beacon queue gets stopped when the last beaconing
interface was stopped by mac80211. Therefore, introduce another
interface counter to keep track ot the number of enabled beaconing
interfaces and start or stop the beacon queue accordingly.
To allow single interfaces to stop beaconing, add a new driver
callback clear_beacon to clear a single interface's beacon without
affecting the other interfaces. Don't overload the clear_entry callback
for clearing beacons as that would introduce additional overhead
(check for each TX queue) into the clear_entry callback which is used
on the drivers TX/RX hotpaths.
Furthermore, the write beacon callback doesn't need to enable beaconing
anymore but since beaconing should be disabled while a new beacon is
written or cleared we still disable beacon generation and enable it
afterwards again in the driver specific callbacks. However, beacon
related interrupts should not be disabled/enabled here, that's solely
done from the start- and stop queue callbacks. It would be nice to stop
the beacon queue just before the beacon update and enable it afterwards
in rt2x00queue itself instead of the current implementation that relies
on the driver doing the right thing. However, since start- and
stop_queue are mutex protected we cannot use them for atomic beacon
updates.
Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
Acked-by: Gertjan van Wingerde <gwingerde@gmail.com>
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2x00mac.c')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00mac.c | 41 |
1 files changed, 38 insertions, 3 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index f3da051df39e..7d3316724bb4 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -619,9 +619,44 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, /* * Update the beacon. */ - if (changes & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_ENABLED)) - rt2x00queue_update_beacon(rt2x00dev, vif, - bss_conf->enable_beacon); + if (changes & BSS_CHANGED_BEACON) + rt2x00queue_update_beacon(rt2x00dev, vif); + + /* + * Start/stop beaconing. + */ + if (changes & BSS_CHANGED_BEACON_ENABLED) { + if (!bss_conf->enable_beacon && intf->enable_beacon) { + rt2x00queue_clear_beacon(rt2x00dev, vif); + rt2x00dev->intf_beaconing--; + intf->enable_beacon = false; + + if (rt2x00dev->intf_beaconing == 0) { + /* + * Last beaconing interface disabled + * -> stop beacon queue. + */ + mutex_lock(&intf->beacon_skb_mutex); + rt2x00queue_stop_queue(rt2x00dev->bcn); + mutex_unlock(&intf->beacon_skb_mutex); + } + + + } else if (bss_conf->enable_beacon && !intf->enable_beacon) { + rt2x00dev->intf_beaconing++; + intf->enable_beacon = true; + + if (rt2x00dev->intf_beaconing == 1) { + /* + * First beaconing interface enabled + * -> start beacon queue. + */ + mutex_lock(&intf->beacon_skb_mutex); + rt2x00queue_start_queue(rt2x00dev->bcn); + mutex_unlock(&intf->beacon_skb_mutex); + } + } + } /* * When the association status has changed we must reset the link |