From: Greg Kroah-Hartman <gre...@linuxfoundation.org>

From: Felix Fietkau <n...@nbd.name>

commit 3b9ea7206d7e1fdd7419cbd10badd3b2c80d04b4 upstream.

When transmitting to a receiver in dynamic SMPS mode, all transmissions that
use multiple spatial streams need to be sent using CTS-to-self or RTS/CTS to
give the receiver's extra chains some time to wake up.
This fixes the tx rate getting stuck at <= MCS7 for some clients, especially
Intel ones, which make aggressive use of SMPS.

Cc: sta...@vger.kernel.org
Reported-by: Martin Kennedy <hurri...@gmail.com>
Signed-off-by: Felix Fietkau <n...@nbd.name>
Signed-off-by: Kalle Valo <kv...@codeaurora.org>
Link: https://lore.kernel.org/r/20210214184911.96702-1-...@nbd.name
Signed-off-by: Greg Kroah-Hartman <gre...@linuxfoundation.org>
---
 drivers/net/wireless/ath/ath9k/ath9k.h |    3 ++-
 drivers/net/wireless/ath/ath9k/xmit.c  |    6 ++++++
 2 files changed, 8 insertions(+), 1 deletion(-)

--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -178,7 +178,8 @@ struct ath_frame_info {
        s8 txq;
        u8 keyix;
        u8 rtscts_rate;
-       u8 retries : 7;
+       u8 retries : 6;
+       u8 dyn_smps : 1;
        u8 baw_tracked : 1;
        u8 tx_power;
        enum ath9k_key_type keytype:2;
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -1228,6 +1228,11 @@ static void ath_buf_set_rate(struct ath_
                                 is_40, is_sgi, is_sp);
                        if (rix < 8 && (tx_info->flags & IEEE80211_TX_CTL_STBC))
                                info->rates[i].RateFlags |= 
ATH9K_RATESERIES_STBC;
+                       if (rix >= 8 && fi->dyn_smps) {
+                               info->rates[i].RateFlags |=
+                                       ATH9K_RATESERIES_RTS_CTS;
+                               info->flags |= ATH9K_TXDESC_CTSENA;
+                       }
 
                        info->txpower[i] = ath_get_rate_txpower(sc, bf, rix,
                                                                is_40, false);
@@ -2114,6 +2119,7 @@ static void setup_frame_info(struct ieee
                fi->keyix = an->ps_key;
        else
                fi->keyix = ATH9K_TXKEYIX_INVALID;
+       fi->dyn_smps = sta && sta->smps_mode == IEEE80211_SMPS_DYNAMIC;
        fi->keytype = keytype;
        fi->framelen = framelen;
        fi->tx_power = txpower;


Reply via email to