6282f4462e6b4570061cd4bbf74c312336ae43b9
[librecmc/librecmc.git] /
1 From df8e3729ffc0aa645839693f74ee7b6d999cdf64 Mon Sep 17 00:00:00 2001
2 From: Maharaja Kennadyrajan <quic_mkenna@quicinc.com>
3 Date: Tue, 9 May 2023 20:07:24 +0300
4 Subject: [PATCH] wifi: ath11k: Send HT fixed rate in WMI peer fixed param
5
6 Due to the firmware behavior with HT fixed rate setting,
7 HT fixed rate MCS with NSS > 1 are treated as NSS = 1
8 HT rates in the firmware and enables the HT fixed rate of
9 NSS = 1.
10
11 This leads to HT fixed rate is always configured for NSS = 1
12 even though the user sets NSS = 2 or > 1 HT fixed MCS in the
13 set bitrate command.
14
15 Currently HT fixed MCS is sent via WMI peer assoc command.
16 Fix this issue, by sending the HT fixed rate MCS in WMI peer
17 fixed param instead of sending in peer assoc command.
18
19 Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1
20
21 Signed-off-by: Maharaja Kennadyrajan <quic_mkenna@quicinc.com>
22 Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
23 Link: https://lore.kernel.org/r/20230504092033.3542456-3-quic_mkenna@quicinc.com
24 ---
25  drivers/net/wireless/ath/ath11k/mac.c | 63 ++++++++++++++++++++++++++-
26  1 file changed, 61 insertions(+), 2 deletions(-)
27
28 --- a/drivers/net/wireless/ath/ath11k/mac.c
29 +++ b/drivers/net/wireless/ath/ath11k/mac.c
30 @@ -4480,6 +4480,54 @@ ath11k_mac_set_peer_he_fixed_rate(struct
31         return ret;
32  }
33  
34 +static int
35 +ath11k_mac_set_peer_ht_fixed_rate(struct ath11k_vif *arvif,
36 +                                 struct ieee80211_sta *sta,
37 +                                 const struct cfg80211_bitrate_mask *mask,
38 +                                 enum nl80211_band band)
39 +{
40 +       struct ath11k *ar = arvif->ar;
41 +       u8 ht_rate, nss = 0;
42 +       u32 rate_code;
43 +       int ret, i;
44 +
45 +       lockdep_assert_held(&ar->conf_mutex);
46 +
47 +       for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++) {
48 +               if (hweight8(mask->control[band].ht_mcs[i]) == 1) {
49 +                       nss = i + 1;
50 +                       ht_rate = ffs(mask->control[band].ht_mcs[i]) - 1;
51 +               }
52 +       }
53 +
54 +       if (!nss) {
55 +               ath11k_warn(ar->ab, "No single HT Fixed rate found to set for %pM",
56 +                           sta->addr);
57 +               return -EINVAL;
58 +       }
59 +
60 +       /* Avoid updating invalid nss as fixed rate*/
61 +       if (nss > sta->deflink.rx_nss)
62 +               return -EINVAL;
63 +
64 +       ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
65 +                  "Setting Fixed HT Rate for peer %pM. Device will not switch to any other selected rates",
66 +                  sta->addr);
67 +
68 +       rate_code = ATH11K_HW_RATE_CODE(ht_rate, nss - 1,
69 +                                       WMI_RATE_PREAMBLE_HT);
70 +       ret = ath11k_wmi_set_peer_param(ar, sta->addr,
71 +                                       arvif->vdev_id,
72 +                                       WMI_PEER_PARAM_FIXED_RATE,
73 +                                       rate_code);
74 +       if (ret)
75 +               ath11k_warn(ar->ab,
76 +                           "failed to update STA %pM HT Fixed Rate %d: %d\n",
77 +                           sta->addr, rate_code, ret);
78 +
79 +       return ret;
80 +}
81 +
82  static int ath11k_station_assoc(struct ath11k *ar,
83                                 struct ieee80211_vif *vif,
84                                 struct ieee80211_sta *sta,
85 @@ -4491,7 +4539,7 @@ static int ath11k_station_assoc(struct a
86         struct cfg80211_chan_def def;
87         enum nl80211_band band;
88         struct cfg80211_bitrate_mask *mask;
89 -       u8 num_vht_rates, num_he_rates;
90 +       u8 num_ht_rates, num_vht_rates, num_he_rates;
91  
92         lockdep_assert_held(&ar->conf_mutex);
93  
94 @@ -4519,6 +4567,7 @@ static int ath11k_station_assoc(struct a
95  
96         num_vht_rates = ath11k_mac_bitrate_mask_num_vht_rates(ar, band, mask);
97         num_he_rates = ath11k_mac_bitrate_mask_num_he_rates(ar, band, mask);
98 +       num_ht_rates = ath11k_mac_bitrate_mask_num_ht_rates(ar, band, mask);
99  
100         /* If single VHT/HE rate is configured (by set_bitrate_mask()),
101          * peer_assoc will disable VHT/HE. This is now enabled by a peer specific
102 @@ -4535,6 +4584,11 @@ static int ath11k_station_assoc(struct a
103                                                         band);
104                 if (ret)
105                         return ret;
106 +       } else if (sta->deflink.ht_cap.ht_supported && num_ht_rates == 1) {
107 +               ret = ath11k_mac_set_peer_ht_fixed_rate(arvif, sta, mask,
108 +                                                       band);
109 +               if (ret)
110 +                       return ret;
111         }
112  
113         /* Re-assoc is run only to update supported rates for given station. It
114 @@ -4608,7 +4662,7 @@ static void ath11k_sta_rc_update_wk(stru
115         const u16 *vht_mcs_mask;
116         const u16 *he_mcs_mask;
117         u32 changed, bw, nss, smps, bw_prev;
118 -       int err, num_vht_rates, num_he_rates;
119 +       int err, num_ht_rates, num_vht_rates, num_he_rates;
120         const struct cfg80211_bitrate_mask *mask;
121         struct peer_assoc_params peer_arg;
122         enum wmi_phy_mode peer_phymode;
123 @@ -4724,6 +4778,8 @@ static void ath11k_sta_rc_update_wk(stru
124  
125         if (changed & IEEE80211_RC_SUPP_RATES_CHANGED) {
126                 mask = &arvif->bitrate_mask;
127 +               num_ht_rates = ath11k_mac_bitrate_mask_num_ht_rates(ar, band,
128 +                                                                   mask);
129                 num_vht_rates = ath11k_mac_bitrate_mask_num_vht_rates(ar, band,
130                                                                       mask);
131                 num_he_rates = ath11k_mac_bitrate_mask_num_he_rates(ar, band,
132 @@ -4746,6 +4802,9 @@ static void ath11k_sta_rc_update_wk(stru
133                 } else if (sta->deflink.he_cap.has_he && num_he_rates == 1) {
134                         ath11k_mac_set_peer_he_fixed_rate(arvif, sta, mask,
135                                                           band);
136 +               } else if (sta->deflink.ht_cap.ht_supported && num_ht_rates == 1) {
137 +                       ath11k_mac_set_peer_ht_fixed_rate(arvif, sta, mask,
138 +                                                         band);
139                 } else {
140                         /* If the peer is non-VHT/HE or no fixed VHT/HE rate
141                          * is provided in the new bitrate mask we set the