From: Mordechay Goodstein <mordechay.goodstein@xxxxxxxxx> Driver tells mac80211 to sends ADDBA with SSN (starting sequence number) from the head of the queue, while the transmission of all the frames in the queue may take a while, which causes the peer to time out. In order to fix this scenario, add an option to defer ADDBA transmit until queue is drained. Signed-off-by: Mordechay Goodstein <mordechay.goodstein@xxxxxxxxx> Signed-off-by: Luca Coelho <luciano.coelho@xxxxxxxxx> --- include/net/mac80211.h | 6 +++++- net/mac80211/agg-tx.c | 12 +++++++++++- net/mac80211/sta_info.h | 2 ++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index f2b0a7795d0a..bcf706798e52 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -3119,7 +3119,10 @@ enum ieee80211_filter_flags { * @IEEE80211_AMPDU_RX_START: start RX aggregation * @IEEE80211_AMPDU_RX_STOP: stop RX aggregation * @IEEE80211_AMPDU_TX_START: start TX aggregation, the driver must either - * call ieee80211_start_tx_ba_cb_irqsafe() or return the special + * call ieee80211_start_tx_ba_cb_irqsafe() or + * call ieee80211_start_tx_ba_cb_irqsafe() with status + * %IEEE80211_AMPDU_TX_START_DELAY_ADDBA to delay addba after + * ieee80211_start_tx_ba_cb_irqsafe is called, or just return the special * status %IEEE80211_AMPDU_TX_START_IMMEDIATE. * @IEEE80211_AMPDU_TX_OPERATIONAL: TX aggregation has become operational * @IEEE80211_AMPDU_TX_STOP_CONT: stop TX aggregation but continue transmitting @@ -3145,6 +3148,7 @@ enum ieee80211_ampdu_mlme_action { }; #define IEEE80211_AMPDU_TX_START_IMMEDIATE 1 +#define IEEE80211_AMPDU_TX_START_DELAY_ADDBA 2 /** * struct ieee80211_ampdu_params - AMPDU action parameters diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 32f40c4f3120..c2d5f512526d 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c @@ -483,6 +483,8 @@ static void ieee80211_send_addba_with_timeout(struct sta_info *sta, tid_tx->dialog_token, sta->tid_seq[tid] >> 4, buf_size, tid_tx->timeout); + + WARN_ON(test_and_set_bit(HT_AGG_STATE_SENT_ADDBA, &tid_tx->state)); } void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) @@ -521,7 +523,9 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) params.ssn = sta->tid_seq[tid] >> 4; ret = drv_ampdu_action(local, sdata, ¶ms); - if (ret == IEEE80211_AMPDU_TX_START_IMMEDIATE) { + if (ret == IEEE80211_AMPDU_TX_START_DELAY_ADDBA) { + return; + } else if (ret == IEEE80211_AMPDU_TX_START_IMMEDIATE) { /* * We didn't send the request yet, so don't need to check * here if we already got a response, just mark as driver @@ -765,6 +769,12 @@ 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_SENT_ADDBA, &tid_tx->state)) { + ieee80211_send_addba_with_timeout(sta, tid_tx); + /* RESPONSE_RECEIVED state whould trigger the flow again */ + return; + } + if (test_bit(HT_AGG_STATE_RESPONSE_RECEIVED, &tid_tx->state)) ieee80211_agg_tx_operational(local, sta, tid); } diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 364a35414d05..78ab18eee1ec 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -3,6 +3,7 @@ * Copyright 2002-2005, Devicescape Software, Inc. * Copyright 2013-2014 Intel Mobile Communications GmbH * Copyright(c) 2015-2017 Intel Deutschland GmbH + * Copyright(c) 2020 Intel Corporation */ #ifndef STA_INFO_H @@ -115,6 +116,7 @@ enum ieee80211_sta_info_flags { #define HT_AGG_STATE_WANT_STOP 5 #define HT_AGG_STATE_START_CB 6 #define HT_AGG_STATE_STOP_CB 7 +#define HT_AGG_STATE_SENT_ADDBA 8 DECLARE_EWMA(avg_signal, 10, 8) enum ieee80211_agg_stop_reason { -- 2.25.1