diff mbox series

[16/20] wifi: mac80211: agg-tx: prevent start/stop race

Message ID 20230618214436.e5b52777462a.I0b2ed6658e81804279f5d7c9c1918cb1f6626bf2@changeid (mailing list archive)
State Accepted
Delegated to: Johannes Berg
Headers show
Series cfg80211/mac80211 patches from our internal tree 2023-06-18 | expand

Commit Message

Greenman, Gregory June 18, 2023, 6:49 p.m. UTC
From: Johannes Berg <johannes.berg@intel.com>

There were crashes reported in this code, and the timer_shutdown()
warning in one of the previous patches indicates that the timeout
timer for the AP response (addba_resp_timer) is still armed while
we're stopping the aggregation session.

After a very long deliberation of the code, so far the only way I
could find that might cause this would be the following sequence:
 - session start requested
 - session start indicated to driver, but driver returns
   IEEE80211_AMPDU_TX_START_DELAY_ADDBA
 - session stop requested, sets HT_AGG_STATE_WANT_STOP
 - session stop worker runs ___ieee80211_stop_tx_ba_session(),
   sets HT_AGG_STATE_STOPPING

From here on, the order doesn't matter exactly, but:

 1. driver calls ieee80211_start_tx_ba_cb_irqsafe(),
    setting HT_AGG_STATE_START_CB
 2. driver calls ieee80211_stop_tx_ba_cb_irqsafe(),
    setting HT_AGG_STATE_STOP_CB
 3. the worker will run ieee80211_start_tx_ba_cb() for
    HT_AGG_STATE_START_CB
 4. the worker will run ieee80211_stop_tx_ba_cb() for
    HT_AGG_STATE_STOP_CB

(the order could also be 1./3./2./4.)

This will cause ieee80211_start_tx_ba_cb() to send out the AddBA
request frame to the AP and arm the timer, but we're already in
the middle of stopping and so the ieee80211_stop_tx_ba_cb() will
no longer assume it needs to stop anything.

Prevent this by checking for WANT_STOP/STOPPING in the start CB,
and warn if we're sending a frame on a stopping session.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Gregory Greenman <gregory.greenman@intel.com>
---
 net/mac80211/agg-tx.c | 8 ++++++++
 1 file changed, 8 insertions(+)
diff mbox series

Patch

diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
index 118ad2e24dbb..b6b772685881 100644
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
@@ -457,6 +457,10 @@  static void ieee80211_send_addba_with_timeout(struct sta_info *sta,
 	u8 tid = tid_tx->tid;
 	u16 buf_size;
 
+	if (WARN_ON_ONCE(test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state) ||
+			 test_bit(HT_AGG_STATE_WANT_STOP, &tid_tx->state)))
+		return;
+
 	lockdep_assert_held(&sta->ampdu_mlme.mtx);
 
 	/* activate the timer for the recipient's addBA response */
@@ -802,6 +806,10 @@  void ieee80211_start_tx_ba_cb(struct sta_info *sta, int tid,
 	if (WARN_ON(test_and_set_bit(HT_AGG_STATE_DRV_READY, &tid_tx->state)))
 		return;
 
+	if (test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state) ||
+	    test_bit(HT_AGG_STATE_WANT_STOP, &tid_tx->state))
+		return;
+
 	if (!test_bit(HT_AGG_STATE_SENT_ADDBA, &tid_tx->state)) {
 		ieee80211_send_addba_with_timeout(sta, tid_tx);
 		/* RESPONSE_RECEIVED state whould trigger the flow again */