summary refs log tree commit diff
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-11-18 17:15:06 +0100
committerJohn W. Linville <linville@tuxdriver.com>2009-11-18 17:01:47 -0500
commit8ade00824607fcfa8842572012d4393b40a74a94 (patch)
treee88b9ce6d6743294e5287d6c3729bbb215cabb3e
parent70e3bb504ccfe6ba725ab120bdb516d205d834f9 (diff)
downloadlinux-8ade00824607fcfa8842572012d4393b40a74a94.tar.gz
mac80211: fix addba timer (again...)
commit 2171abc58644e09dbba546d91366b12743115396
  Author: Johannes Berg <johannes@sipsolutions.net>
  Date:   Thu Oct 29 08:34:00 2009 +0100

      mac80211: fix addba timer

left a problem in there, even if the timer was
never started it could be deleted and then added.

Linus pointed out that del_timer_sync() isn't
actually needed if we make the timer able to
deal with no longer being needed when it gets
queued _while_ we're in the locked section that
also deletes it. For that the timer function only
needs to check the HT_ADDBA_RECEIVED_MSK bit as
well as the HT_ADDBA_REQUESTED_MSK bit, only if
the former is clear should it do anything.

Cc: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--net/mac80211/agg-tx.c18
1 files changed, 8 insertions, 10 deletions
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
index b09948ceec4a..206fd82f0c76 100644
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
@@ -173,12 +173,14 @@ static void sta_addba_resp_timer_expired(unsigned long data)
 
 	/* check if the TID waits for addBA response */
 	spin_lock_bh(&sta->lock);
-	if (!(*state & HT_ADDBA_REQUESTED_MSK)) {
+	if ((*state & (HT_ADDBA_REQUESTED_MSK | HT_ADDBA_RECEIVED_MSK)) !=
+						HT_ADDBA_REQUESTED_MSK) {
 		spin_unlock_bh(&sta->lock);
 		*state = HT_AGG_STATE_IDLE;
 #ifdef CONFIG_MAC80211_HT_DEBUG
 		printk(KERN_DEBUG "timer expired on tid %d but we are not "
-				"expecting addBA response there", tid);
+				"(or no longer) expecting addBA response there",
+			tid);
 #endif
 		return;
 	}
@@ -666,21 +668,21 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local,
 
 	state = &sta->ampdu_mlme.tid_state_tx[tid];
 
-	del_timer_sync(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
-
 	spin_lock_bh(&sta->lock);
 
 	if (!(*state & HT_ADDBA_REQUESTED_MSK))
-		goto timer_still_needed;
+		goto out;
 
 	if (mgmt->u.action.u.addba_resp.dialog_token !=
 		sta->ampdu_mlme.tid_tx[tid]->dialog_token) {
 #ifdef CONFIG_MAC80211_HT_DEBUG
 		printk(KERN_DEBUG "wrong addBA response token, tid %d\n", tid);
 #endif /* CONFIG_MAC80211_HT_DEBUG */
-		goto timer_still_needed;
+		goto out;
 	}
 
+	del_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
+
 #ifdef CONFIG_MAC80211_HT_DEBUG
 	printk(KERN_DEBUG "switched off addBA timer for tid %d \n", tid);
 #endif /* CONFIG_MAC80211_HT_DEBUG */
@@ -699,10 +701,6 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local,
 		___ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR);
 	}
 
-	goto out;
-
- timer_still_needed:
-	add_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
  out:
 	spin_unlock_bh(&sta->lock);
 }