aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rt2x00/rt2x00queue.c
diff options
context:
space:
mode:
authorHelmut Schaa <helmut.schaa@googlemail.com>2011-01-30 13:16:03 +0100
committerJohn W. Linville <linville@tuxdriver.com>2011-01-31 15:06:22 -0500
commit69cf36a4523be026bc16743c5c989c5e82edb7d9 (patch)
tree0c6572b724d840d879ff12861d8ac57da1bad635 /drivers/net/wireless/rt2x00/rt2x00queue.c
parentd828cd5a95e532636dbc495e4b94b625ab9abdad (diff)
downloadkernel_samsung_smdk4412-69cf36a4523be026bc16743c5c989c5e82edb7d9.zip
kernel_samsung_smdk4412-69cf36a4523be026bc16743c5c989c5e82edb7d9.tar.gz
kernel_samsung_smdk4412-69cf36a4523be026bc16743c5c989c5e82edb7d9.tar.bz2
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/rt2x00queue.c')
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.c38
1 files changed, 29 insertions, 9 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index ca82b3a..24bcdb4 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -566,9 +566,35 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
return 0;
}
+int rt2x00queue_clear_beacon(struct rt2x00_dev *rt2x00dev,
+ struct ieee80211_vif *vif)
+{
+ struct rt2x00_intf *intf = vif_to_intf(vif);
+
+ if (unlikely(!intf->beacon))
+ return -ENOBUFS;
+
+ mutex_lock(&intf->beacon_skb_mutex);
+
+ /*
+ * Clean up the beacon skb.
+ */
+ rt2x00queue_free_skb(intf->beacon);
+
+ /*
+ * Clear beacon (single bssid devices don't need to clear the beacon
+ * since the beacon queue will get stopped anyway).
+ */
+ if (rt2x00dev->ops->lib->clear_beacon)
+ rt2x00dev->ops->lib->clear_beacon(intf->beacon);
+
+ mutex_unlock(&intf->beacon_skb_mutex);
+
+ return 0;
+}
+
int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
- struct ieee80211_vif *vif,
- const bool enable_beacon)
+ struct ieee80211_vif *vif)
{
struct rt2x00_intf *intf = vif_to_intf(vif);
struct skb_frame_desc *skbdesc;
@@ -584,12 +610,6 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
*/
rt2x00queue_free_skb(intf->beacon);
- if (!enable_beacon) {
- rt2x00queue_stop_queue(intf->beacon->queue);
- mutex_unlock(&intf->beacon_skb_mutex);
- return 0;
- }
-
intf->beacon->skb = ieee80211_beacon_get(rt2x00dev->hw, vif);
if (!intf->beacon->skb) {
mutex_unlock(&intf->beacon_skb_mutex);
@@ -611,7 +631,7 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
skbdesc->entry = intf->beacon;
/*
- * Send beacon to hardware and enable beacon genaration..
+ * Send beacon to hardware.
*/
rt2x00dev->ops->lib->write_beacon(intf->beacon, &txdesc);