Skip to content

Commit

Permalink
mac80211: move netdev queue enabling to correct spot
Browse files Browse the repository at this point in the history
"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>
  • Loading branch information
Johannes Berg authored and John W. Linville committed Mar 30, 2010
1 parent 05a9a16 commit 7236fe2
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 6 deletions.
6 changes: 6 additions & 0 deletions net/mac80211/tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -1991,6 +1991,7 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local,
void ieee80211_tx_pending(unsigned long data)
{
struct ieee80211_local *local = (struct ieee80211_local *)data;
struct ieee80211_sub_if_data *sdata;
unsigned long flags;
int i;
bool txok;
Expand Down Expand Up @@ -2029,6 +2030,11 @@ void ieee80211_tx_pending(unsigned long data)
if (!txok)
break;
}

if (skb_queue_empty(&local->pending[i]))
list_for_each_entry_rcu(sdata, &local->interfaces, list)
netif_tx_wake_queue(
netdev_get_tx_queue(sdata->dev, i));
}
spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);

Expand Down
12 changes: 6 additions & 6 deletions net/mac80211/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -279,13 +279,13 @@ static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue,
/* someone still has this queue stopped */
return;

if (!skb_queue_empty(&local->pending[queue]))
if (skb_queue_empty(&local->pending[queue])) {
rcu_read_lock();
list_for_each_entry_rcu(sdata, &local->interfaces, list)
netif_tx_wake_queue(netdev_get_tx_queue(sdata->dev, queue));
rcu_read_unlock();
} else
tasklet_schedule(&local->tx_pending_tasklet);

rcu_read_lock();
list_for_each_entry_rcu(sdata, &local->interfaces, list)
netif_tx_wake_queue(netdev_get_tx_queue(sdata->dev, queue));
rcu_read_unlock();
}

void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue,
Expand Down

0 comments on commit 7236fe2

Please sign in to comment.