mac80211: don't stop a single aggregation session twice
authorJohannes Berg <johannes.berg@intel.com>
Thu, 24 Nov 2011 19:06:14 +0000 (20:06 +0100)
committerJohn W. Linville <linville@tuxdriver.com>
Mon, 28 Nov 2011 18:46:41 +0000 (13:46 -0500)
Nikolay noticed (by code review) that mac80211 can
attempt to stop an aggregation session while it is
already being stopped. So to fix it, check whether
stop is already being done and bail out if so.

Also move setting the STOPPING state into the lock
so things are properly atomic.

Cc: stable@vger.kernel.org
Reported-by: Nikolay Martynov <mar.kolya@gmail.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
net/mac80211/agg-tx.c

index 2ac033989e016304047dca1ecaacbd9519ae697e..674b345ade811ab55e14453f287753aca2f43d30 100644 (file)
@@ -160,6 +160,12 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
                return -ENOENT;
        }
 
+       /* if we're already stopping ignore any new requests to stop */
+       if (test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) {
+               spin_unlock_bh(&sta->lock);
+               return -EALREADY;
+       }
+
        if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) {
                /* not even started yet! */
                ieee80211_assign_tid_tx(sta, tid, NULL);
@@ -168,6 +174,8 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
                return 0;
        }
 
+       set_bit(HT_AGG_STATE_STOPPING, &tid_tx->state);
+
        spin_unlock_bh(&sta->lock);
 
 #ifdef CONFIG_MAC80211_HT_DEBUG
@@ -175,8 +183,6 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
               sta->sta.addr, tid);
 #endif /* CONFIG_MAC80211_HT_DEBUG */
 
-       set_bit(HT_AGG_STATE_STOPPING, &tid_tx->state);
-
        del_timer_sync(&tid_tx->addba_resp_timer);
 
        /*