summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-05-07 19:57:36 +0400
committerJohn W. Linville <linville@tuxdriver.com>2012-05-16 20:46:04 +0400
commit9e73dee7d38e9fa00f6dd1492cfbbc5719378e4a (patch)
tree1f2681c5a41e5bc732e9468fececac6806e7bfaf /net
parenta9d3c05cca51d80ef2b9eddabf794c9458e36c2c (diff)
downloadlinux-9e73dee7d38e9fa00f6dd1492cfbbc5719378e4a.tar.xz
mac80211: fix TX aggregation session timer
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>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/agg-tx.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
index 5b7053c58732..7cf07158805c 100644
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
@@ -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