diff options
author | Johannes Berg <johannes.berg@intel.com> | 2010-03-22 16:42:43 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-03-30 15:37:28 -0400 |
commit | 7236fe29fd72d17074574ba312e7f1bb9d10abaa (patch) | |
tree | 6afd1fed2871daca52f5a8b3070337ae1b6ada0d /net/mac80211/util.c | |
parent | 05a9a1617026977422c7c5ed3aeac6f46fa2132c (diff) |
mac80211: move netdev queue enabling to correct spot
"mac80211: fix skb buffering issue" still left a race
between enabling the hardware queues and the virtual
interface queues. In hindsight it's totally obvious
that enabling the netdev queues for a hardware queue
when the hardware queue is enabled is wrong, because
it could well possible that we can fill the hw queue
with packets we already have pending. Thus, we must
only enable the netdev queues once all the pending
packets have been processed and sent off to the device.
In testing, I haven't been able to trigger this race
condition, but it's clearly there, possibly only when
aggregation is being enabled.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Cc: stable@kernel.org
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/util.c')
-rw-r--r-- | net/mac80211/util.c | 12 |
1 files changed, 6 insertions, 6 deletions
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index e6b1fba980c6..53af57047435 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -279,13 +279,13 @@ static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue, | |||
279 | /* someone still has this queue stopped */ | 279 | /* someone still has this queue stopped */ |
280 | return; | 280 | return; |
281 | 281 | ||
282 | if (!skb_queue_empty(&local->pending[queue])) | 282 | if (skb_queue_empty(&local->pending[queue])) { |
283 | rcu_read_lock(); | ||
284 | list_for_each_entry_rcu(sdata, &local->interfaces, list) | ||
285 | netif_tx_wake_queue(netdev_get_tx_queue(sdata->dev, queue)); | ||
286 | rcu_read_unlock(); | ||
287 | } else | ||
283 | tasklet_schedule(&local->tx_pending_tasklet); | 288 | tasklet_schedule(&local->tx_pending_tasklet); |
284 | |||
285 | rcu_read_lock(); | ||
286 | list_for_each_entry_rcu(sdata, &local->interfaces, list) | ||
287 | netif_tx_wake_queue(netdev_get_tx_queue(sdata->dev, queue)); | ||
288 | rcu_read_unlock(); | ||
289 | } | 289 | } |
290 | 290 | ||
291 | void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue, | 291 | void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue, |