]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
mac80211: fix TX aggregation session timer
authorJohannes Berg <johannes.berg@intel.com>
Mon, 7 May 2012 15:57:36 +0000 (17:57 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Wed, 16 May 2012 16:46:04 +0000 (12:46 -0400)
In commit 12d3952fc4a1cd96234bc7023bf7eefeb0bb6355
("mac80211: optimize aggregation session timeout handling")
two bugs were introduced:
 1) RCU usage was completely broken since no locks are held
 2) the timer must not rearm when agg session is stopping

Reported-and-tested-by: Larry Finger <Larry.Finger@lwfinger.net>
Cc: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
net/mac80211/agg-tx.c

index 5b7053c58732f47e8dad0faf92256c8b6e7dc44f..7cf07158805c198e827af160a9f705881c4b20fa 100644 (file)
@@ -421,16 +421,22 @@ static void sta_tx_agg_session_timer_expired(unsigned long data)
        struct tid_ampdu_tx *tid_tx;
        unsigned long timeout;
 
-       tid_tx = rcu_dereference_protected_tid_tx(sta, *ptid);
-       if (!tid_tx)
+       rcu_read_lock();
+       tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[*ptid]);
+       if (!tid_tx || test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) {
+               rcu_read_unlock();
                return;
+       }
 
        timeout = tid_tx->last_tx + TU_TO_JIFFIES(tid_tx->timeout);
        if (time_is_after_jiffies(timeout)) {
                mod_timer(&tid_tx->session_timer, timeout);
+               rcu_read_unlock();
                return;
        }
 
+       rcu_read_unlock();
+
 #ifdef CONFIG_MAC80211_HT_DEBUG
        printk(KERN_DEBUG "tx session timer expired on tid %d\n", (u16)*ptid);
 #endif