aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/util.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2010-08-27 07:45:28 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-08-27 13:53:31 -0400
commit5b714c6a3753dad0798a70a049e15c7f6bc9446b (patch)
tree39345981014b14e881cbfbef87a4a3a74469fada /net/mac80211/util.c
parentc35d02705e9c2db90a89b29142046b4ffd5a76e5 (diff)
mac80211: fix offchannel queue stop
Somebody noticed this problem, and I outlined to them how to fix it, but haven't heard back from them. So while I was adding the state field I figured I could use it to fix it. The problem, as I understand it, is that when we go offchannel while the driver has a queue stopped, the driver will likely start draining the queue and then enable it while offchannel. This in turn will enable the interface queue, and that leads to transmitting data frames on the wrong channel. Fix this by keeping track of offchannel status per interface, and not enabling the interface queues on interfaces that are offchannel when the driver enables a queue. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/util.c')
-rw-r--r--net/mac80211/util.c5
1 files changed, 4 insertions, 1 deletions
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index d38b3767e8cc..bd40b11d5ab9 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -283,8 +283,11 @@ static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue,
283 283
284 if (skb_queue_empty(&local->pending[queue])) { 284 if (skb_queue_empty(&local->pending[queue])) {
285 rcu_read_lock(); 285 rcu_read_lock();
286 list_for_each_entry_rcu(sdata, &local->interfaces, list) 286 list_for_each_entry_rcu(sdata, &local->interfaces, list) {
287 if (test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state))
288 continue;
287 netif_wake_subqueue(sdata->dev, queue); 289 netif_wake_subqueue(sdata->dev, queue);
290 }
288 rcu_read_unlock(); 291 rcu_read_unlock();
289 } else 292 } else
290 tasklet_schedule(&local->tx_pending_tasklet); 293 tasklet_schedule(&local->tx_pending_tasklet);