lkml.org 
[lkml]   [2010]   [Apr]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[022/139] mac80211: move netdev queue enabling to correct spot
    2.6.33-stable review patch.  If anyone has any objections, please let us know.

    ------------------

    From: Johannes Berg <johannes.berg@intel.com>

    commit 7236fe29fd72d17074574ba312e7f1bb9d10abaa upstream.

    "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>
    Signed-off-by: John W. Linville <linville@tuxdriver.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

    ---
    net/mac80211/tx.c | 6 ++++++
    net/mac80211/util.c | 12 ++++++------
    2 files changed, 12 insertions(+), 6 deletions(-)

    --- a/net/mac80211/tx.c
    +++ b/net/mac80211/tx.c
    @@ -1945,6 +1945,7 @@ static bool ieee80211_tx_pending_skb(str
    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;
    @@ -1983,6 +1984,11 @@ void ieee80211_tx_pending(unsigned long
    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);

    --- a/net/mac80211/util.c
    +++ b/net/mac80211/util.c
    @@ -280,13 +280,13 @@ static void __ieee80211_wake_queue(struc
    /* 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,



    \
     
     \ /
      Last update: 2010-04-22 22:33    [W:0.022 / U:92.612 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site