]> git.ipfire.org Git - thirdparty/openwrt.git/blob
72f3e9a56752e333df85f94e115462c3f49d478d
[thirdparty/openwrt.git] /
1 From patchwork Wed Sep 18 21:20:53 2024
2 Content-Type: text/plain; charset="utf-8"
3 MIME-Version: 1.0
4 Content-Transfer-Encoding: 7bit
5 X-Patchwork-Submitter: Pradeep Kumar Chitrapu <quic_pradeepc@quicinc.com>
6 X-Patchwork-Id: 13807217
7 X-Patchwork-Delegate: quic_jjohnson@quicinc.com
8 Received: from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com
9 [205.220.168.131])
10 (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
11 (No client certificate requested)
12 by smtp.subspace.kernel.org (Postfix) with ESMTPS id 01CB41CB521
13 for <linux-wireless@vger.kernel.org>; Wed, 18 Sep 2024 21:21:15 +0000 (UTC)
14 Authentication-Results: smtp.subspace.kernel.org;
15 arc=none smtp.client-ip=205.220.168.131
16 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;
17 t=1726694478; cv=none;
18 b=CCnmzPX7wAnXz6jkBGnfJkO3OTVTa1pEVXaY+i3jcRKLwLmYLBkbQB7d5qZASnEWRw4vJRXQbpKaSNlechv1fw+VqQci5hz7GrwDmSDWwFwNKynwUkaS+V6CUoPkxGmvijlkSH5/Sp7n4JBdH9MZdY9ACaPCGZlgpTeAiRpgqyQ=
19 ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org;
20 s=arc-20240116; t=1726694478; c=relaxed/simple;
21 bh=mOCMplbDFdsxafoM0lh9GOTg8poXfVWSA2JaaPzd5gg=;
22 h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References:
23 MIME-Version:Content-Type;
24 b=m9Y3ZEQjhVcT6ObjX34KItzxLUdCbzQDCo4za4qtMsxHQCEQSny2a/lTtWTbAB42n+JZkBRjC1xrrdmRnXSxy58EZpvKNutjY0YonbJ/hMfa97U5qRTD/50prvNqxkFINPijMCNMgKsnCBz6tfcB78j3qnEvZjNP4eV4rbTicUg=
25 ARC-Authentication-Results: i=1; smtp.subspace.kernel.org;
26 dmarc=pass (p=none dis=none) header.from=quicinc.com;
27 spf=pass smtp.mailfrom=quicinc.com;
28 dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com
29 header.b=lKsSrYSp; arc=none smtp.client-ip=205.220.168.131
30 Authentication-Results: smtp.subspace.kernel.org;
31 dmarc=pass (p=none dis=none) header.from=quicinc.com
32 Authentication-Results: smtp.subspace.kernel.org;
33 spf=pass smtp.mailfrom=quicinc.com
34 Authentication-Results: smtp.subspace.kernel.org;
35 dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com
36 header.b="lKsSrYSp"
37 Received: from pps.filterd (m0279864.ppops.net [127.0.0.1])
38 by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id
39 48IINFa1032091;
40 Wed, 18 Sep 2024 21:21:09 GMT
41 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h=
42 cc:content-transfer-encoding:content-type:date:from:in-reply-to
43 :message-id:mime-version:references:subject:to; s=qcppdkim1; bh=
44 97aZlelAxnf1oZWK/vk3qg6OISdr4sArbqi18OQE/2Y=; b=lKsSrYSpewbykrq1
45 6WJRbLR0y481zo+GgIgfHUNcpF2NhItbbS8mgWYFPaMaoohciRsbAYdFFZrc9BG3
46 9IyAzZvpFzBox/oaJjDm/zLc2GVYMSGtwO3W0mMk2uVXU7ZB8dBDNimtsLmXTa1t
47 jyV6n0wj3jlGU1kDYu6zPgrcxWF1NnScnosftToVpHqM7TLfDaj8EJWuzsJnau2A
48 CUOS2o9wPZPAScyeL91kJOHtJddltuJrvLFxbi4gGZW7dWUus99UjFzGTAan/JVK
49 yb5Xr8iEzP2141KqZ9FMQqwqYOGc10t+yYXPMep/fo1mfziiB5kQ0tRtaWQ01Auw
50 uPa6OQ==
51 Received: from nalasppmta04.qualcomm.com (Global_NAT1.qualcomm.com
52 [129.46.96.20])
53 by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 41n4geb5e1-1
54 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT);
55 Wed, 18 Sep 2024 21:21:09 +0000 (GMT)
56 Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com
57 [10.47.209.196])
58 by NALASPPMTA04.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id
59 48ILL8jN020567
60 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT);
61 Wed, 18 Sep 2024 21:21:08 GMT
62 Received: from ath12k-linux1.qualcomm.com (10.80.80.8) by
63 nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server
64 (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id
65 15.2.1544.9; Wed, 18 Sep 2024 14:21:08 -0700
66 From: Pradeep Kumar Chitrapu <quic_pradeepc@quicinc.com>
67 To: <ath12k@lists.infradead.org>
68 CC: <linux-wireless@vger.kernel.org>,
69 Pradeep Kumar Chitrapu
70 <quic_pradeepc@quicinc.com>,
71 Muna Sinada <quic_msinada@quicinc.com>,
72 "Jeff
73 Johnson" <quic_jjohnson@quicinc.com>
74 Subject: [PATCH V8 6/9] wifi: ath12k: add support for setting fixed HE
75 rate/GI/LTF
76 Date: Wed, 18 Sep 2024 14:20:53 -0700
77 Message-ID: <20240918212056.4137076-7-quic_pradeepc@quicinc.com>
78 X-Mailer: git-send-email 2.34.1
79 In-Reply-To: <20240918212056.4137076-1-quic_pradeepc@quicinc.com>
80 References: <20240918212056.4137076-1-quic_pradeepc@quicinc.com>
81 Precedence: bulk
82 X-Mailing-List: linux-wireless@vger.kernel.org
83 List-Id: <linux-wireless.vger.kernel.org>
84 List-Subscribe: <mailto:linux-wireless+subscribe@vger.kernel.org>
85 List-Unsubscribe: <mailto:linux-wireless+unsubscribe@vger.kernel.org>
86 MIME-Version: 1.0
87 X-ClientProxiedBy: nasanex01a.na.qualcomm.com (10.52.223.231) To
88 nalasex01a.na.qualcomm.com (10.47.209.196)
89 X-QCInternal: smtphost
90 X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800
91 signatures=585085
92 X-Proofpoint-GUID: GGIeqOgMFye5oFp39WDjK5DZ7YoCK3Ap
93 X-Proofpoint-ORIG-GUID: GGIeqOgMFye5oFp39WDjK5DZ7YoCK3Ap
94 X-Proofpoint-Virus-Version: vendor=baseguard
95 engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.60.29
96 definitions=2024-09-06_09,2024-09-06_01,2024-09-02_01
97 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0
98 malwarescore=0
99 mlxlogscore=999 impostorscore=0 bulkscore=0 clxscore=1015
100 lowpriorityscore=0 adultscore=0 phishscore=0 suspectscore=0
101 priorityscore=1501 mlxscore=0 spamscore=0 classifier=spam adjust=0
102 reason=mlx scancount=1 engine=8.19.0-2408220000
103 definitions=main-2409180140
104
105 Add support to set fixed HE rate/GI/LTF values using nl80211.
106 Reuse parts of the existing code path already used for HT/VHT
107 to implement the new helpers symmetrically, similar to how
108 HT/VHT is handled.
109
110 Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1
111
112 Co-developed-by: Muna Sinada <quic_msinada@quicinc.com>
113 Signed-off-by: Muna Sinada <quic_msinada@quicinc.com>
114 Signed-off-by: Pradeep Kumar Chitrapu <quic_pradeepc@quicinc.com>
115 Acked-by: Jeff Johnson <quic_jjohnson@quicinc.com>
116 ---
117 drivers/net/wireless/ath/ath12k/mac.c | 604 ++++++++++++++++++++++++--
118 drivers/net/wireless/ath/ath12k/wmi.h | 18 +
119 2 files changed, 574 insertions(+), 48 deletions(-)
120
121 --- a/drivers/net/wireless/ath/ath12k/mac.c
122 +++ b/drivers/net/wireless/ath/ath12k/mac.c
123 @@ -441,6 +441,18 @@ ath12k_mac_max_vht_nss(const u16 *vht_mc
124 return 1;
125 }
126
127 +static u32
128 +ath12k_mac_max_he_nss(const u16 he_mcs_mask[NL80211_HE_NSS_MAX])
129 +{
130 + int nss;
131 +
132 + for (nss = NL80211_HE_NSS_MAX - 1; nss >= 0; nss--)
133 + if (he_mcs_mask[nss])
134 + return nss + 1;
135 +
136 + return 1;
137 +}
138 +
139 static u8 ath12k_parse_mpdudensity(u8 mpdudensity)
140 {
141 /* From IEEE Std 802.11-2020 defined values for "Minimum MPDU Start Spacing":
142 @@ -1916,6 +1928,14 @@ static void ath12k_peer_assoc_h_ht(struc
143 arg->peer_rate_caps |= WMI_HOST_RC_CW40_FLAG;
144 }
145
146 + /* As firmware handles these two flags (IEEE80211_HT_CAP_SGI_20
147 + * and IEEE80211_HT_CAP_SGI_40) for enabling SGI, reset both
148 + * flags if guard interval is Default GI
149 + */
150 + if (arvif->bitrate_mask.control[band].gi == NL80211_TXRATE_DEFAULT_GI)
151 + arg->peer_ht_caps &= ~(IEEE80211_HT_CAP_SGI_20 |
152 + IEEE80211_HT_CAP_SGI_40);
153 +
154 if (arvif->bitrate_mask.control[band].gi != NL80211_TXRATE_FORCE_LGI) {
155 if (ht_cap->cap & (IEEE80211_HT_CAP_SGI_20 |
156 IEEE80211_HT_CAP_SGI_40))
157 @@ -2039,11 +2059,12 @@ static void ath12k_peer_assoc_h_vht(stru
158 struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
159 struct cfg80211_chan_def def;
160 enum nl80211_band band;
161 - const u16 *vht_mcs_mask;
162 + u16 *vht_mcs_mask;
163 u16 tx_mcs_map;
164 u8 ampdu_factor;
165 u8 max_nss, vht_mcs;
166 - int i;
167 + int i, vht_nss, nss_idx;
168 + bool user_rate_valid = true;
169
170 if (WARN_ON(ath12k_mac_vif_chan(vif, &def)))
171 return;
172 @@ -2086,6 +2107,25 @@ static void ath12k_peer_assoc_h_vht(stru
173 if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160)
174 arg->bw_160 = true;
175
176 + vht_nss = ath12k_mac_max_vht_nss(vht_mcs_mask);
177 +
178 + if (vht_nss > sta->deflink.rx_nss) {
179 + user_rate_valid = false;
180 + for (nss_idx = sta->deflink.rx_nss - 1; nss_idx >= 0; nss_idx--) {
181 + if (vht_mcs_mask[nss_idx]) {
182 + user_rate_valid = true;
183 + break;
184 + }
185 + }
186 + }
187 +
188 + if (!user_rate_valid) {
189 + ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
190 + "Setting vht range MCS value to peer supported nss:%d for peer %pM\n",
191 + sta->deflink.rx_nss, sta->deflink.addr);
192 + vht_mcs_mask[sta->deflink.rx_nss - 1] = vht_mcs_mask[vht_nss - 1];
193 + }
194 +
195 /* Calculate peer NSS capability from VHT capabilities if STA
196 * supports VHT.
197 */
198 @@ -2125,23 +2165,105 @@ static void ath12k_peer_assoc_h_vht(stru
199 /* TODO: rxnss_override */
200 }
201
202 +static int ath12k_mac_get_max_he_mcs_map(u16 mcs_map, int nss)
203 +{
204 + switch ((mcs_map >> (2 * nss)) & 0x3) {
205 + case IEEE80211_HE_MCS_SUPPORT_0_7: return BIT(8) - 1;
206 + case IEEE80211_HE_MCS_SUPPORT_0_9: return BIT(10) - 1;
207 + case IEEE80211_HE_MCS_SUPPORT_0_11: return BIT(12) - 1;
208 + }
209 + return 0;
210 +}
211 +
212 +static u16 ath12k_peer_assoc_h_he_limit(u16 tx_mcs_set,
213 + const u16 *he_mcs_limit)
214 +{
215 + int idx_limit;
216 + int nss;
217 + u16 mcs_map;
218 + u16 mcs;
219 +
220 + for (nss = 0; nss < NL80211_HE_NSS_MAX; nss++) {
221 + mcs_map = ath12k_mac_get_max_he_mcs_map(tx_mcs_set, nss) &
222 + he_mcs_limit[nss];
223 +
224 + if (mcs_map)
225 + idx_limit = fls(mcs_map) - 1;
226 + else
227 + idx_limit = -1;
228 +
229 + switch (idx_limit) {
230 + case 0 ... 7:
231 + mcs = IEEE80211_HE_MCS_SUPPORT_0_7;
232 + break;
233 + case 8:
234 + case 9:
235 + mcs = IEEE80211_HE_MCS_SUPPORT_0_9;
236 + break;
237 + case 10:
238 + case 11:
239 + mcs = IEEE80211_HE_MCS_SUPPORT_0_11;
240 + break;
241 + default:
242 + WARN_ON(1);
243 + fallthrough;
244 + case -1:
245 + mcs = IEEE80211_HE_MCS_NOT_SUPPORTED;
246 + break;
247 + }
248 +
249 + tx_mcs_set &= ~(0x3 << (nss * 2));
250 + tx_mcs_set |= mcs << (nss * 2);
251 + }
252 +
253 + return tx_mcs_set;
254 +}
255 +
256 +static bool
257 +ath12k_peer_assoc_h_he_masked(const u16 he_mcs_mask[NL80211_HE_NSS_MAX])
258 +{
259 + int nss;
260 +
261 + for (nss = 0; nss < NL80211_HE_NSS_MAX; nss++)
262 + if (he_mcs_mask[nss])
263 + return false;
264 +
265 + return true;
266 +}
267 +
268 static void ath12k_peer_assoc_h_he(struct ath12k *ar,
269 struct ieee80211_vif *vif,
270 struct ieee80211_sta *sta,
271 struct ath12k_wmi_peer_assoc_arg *arg)
272 {
273 const struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap;
274 + struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
275 + struct cfg80211_chan_def def;
276 int i;
277 u8 ampdu_factor, max_nss;
278 u8 rx_mcs_80 = IEEE80211_HE_MCS_NOT_SUPPORTED;
279 u8 rx_mcs_160 = IEEE80211_HE_MCS_NOT_SUPPORTED;
280 u16 mcs_160_map, mcs_80_map;
281 bool support_160;
282 - u16 v;
283 + enum nl80211_band band;
284 + u16 *he_mcs_mask;
285 + u8 he_mcs;
286 + u16 he_tx_mcs = 0, v = 0;
287 + int he_nss, nss_idx;
288 + bool user_rate_valid = true;
289 +
290 + if (WARN_ON(ath12k_mac_vif_chan(vif, &def)))
291 + return;
292
293 if (!he_cap->has_he)
294 return;
295
296 + band = def.chan->band;
297 + he_mcs_mask = arvif->bitrate_mask.control[band].he_mcs;
298 +
299 + if (ath12k_peer_assoc_h_he_masked(he_mcs_mask))
300 + return;
301 +
302 arg->he_flag = true;
303
304 support_160 = !!(he_cap->he_cap_elem.phy_cap_info[0] &
305 @@ -2247,25 +2369,47 @@ static void ath12k_peer_assoc_h_he(struc
306 if (he_cap->he_cap_elem.mac_cap_info[0] & IEEE80211_HE_MAC_CAP0_TWT_REQ)
307 arg->twt_requester = true;
308
309 + he_nss = ath12k_mac_max_he_nss(he_mcs_mask);
310 +
311 + if (he_nss > sta->deflink.rx_nss) {
312 + user_rate_valid = false;
313 + for (nss_idx = sta->deflink.rx_nss - 1; nss_idx >= 0; nss_idx--) {
314 + if (he_mcs_mask[nss_idx]) {
315 + user_rate_valid = true;
316 + break;
317 + }
318 + }
319 + }
320 +
321 + if (!user_rate_valid) {
322 + ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
323 + "Setting he range MCS value to peer supported nss:%d for peer %pM\n",
324 + sta->deflink.rx_nss, sta->deflink.addr);
325 + he_mcs_mask[sta->deflink.rx_nss - 1] = he_mcs_mask[he_nss - 1];
326 + }
327 +
328 switch (sta->deflink.bandwidth) {
329 case IEEE80211_STA_RX_BW_160:
330 if (he_cap->he_cap_elem.phy_cap_info[0] &
331 IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G) {
332 - v = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_80p80);
333 + v = ath12k_peer_assoc_h_he_limit(v, he_mcs_mask);
334 arg->peer_he_rx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80_80] = v;
335
336 v = le16_to_cpu(he_cap->he_mcs_nss_supp.tx_mcs_80p80);
337 arg->peer_he_tx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80_80] = v;
338
339 arg->peer_he_mcs_count++;
340 + he_tx_mcs = v;
341 }
342 v = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_160);
343 arg->peer_he_rx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_160] = v;
344
345 - v = le16_to_cpu(he_cap->he_mcs_nss_supp.tx_mcs_160);
346 + v = ath12k_peer_assoc_h_he_limit(v, he_mcs_mask);
347 arg->peer_he_tx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_160] = v;
348
349 arg->peer_he_mcs_count++;
350 + if (!he_tx_mcs)
351 + he_tx_mcs = v;
352 fallthrough;
353
354 default:
355 @@ -2273,11 +2417,34 @@ static void ath12k_peer_assoc_h_he(struc
356 arg->peer_he_rx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80] = v;
357
358 v = le16_to_cpu(he_cap->he_mcs_nss_supp.tx_mcs_80);
359 + v = ath12k_peer_assoc_h_he_limit(v, he_mcs_mask);
360 arg->peer_he_tx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80] = v;
361
362 arg->peer_he_mcs_count++;
363 + if (!he_tx_mcs)
364 + he_tx_mcs = v;
365 break;
366 }
367 +
368 + /* Calculate peer NSS capability from HE capabilities if STA
369 + * supports HE.
370 + */
371 + for (i = 0, max_nss = 0, he_mcs = 0; i < NL80211_HE_NSS_MAX; i++) {
372 + he_mcs = he_tx_mcs >> (2 * i) & 3;
373 +
374 + /* In case of fixed rates, MCS Range in he_tx_mcs might have
375 + * unsupported range, with he_mcs_mask set, so check either of them
376 + * to find nss.
377 + */
378 + if (he_mcs != IEEE80211_HE_MCS_NOT_SUPPORTED ||
379 + he_mcs_mask[i])
380 + max_nss = i + 1;
381 + }
382 + arg->peer_nss = min(sta->deflink.rx_nss, max_nss);
383 +
384 + ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
385 + "mac he peer %pM nss %d mcs cnt %d\n",
386 + sta->deflink.addr, arg->peer_nss, arg->peer_he_mcs_count);
387 }
388
389 static void ath12k_peer_assoc_h_he_6ghz(struct ath12k *ar,
390 @@ -2586,6 +2753,7 @@ static void ath12k_peer_assoc_h_phymode(
391 enum nl80211_band band;
392 const u8 *ht_mcs_mask;
393 const u16 *vht_mcs_mask;
394 + const u16 *he_mcs_mask;
395 enum wmi_phy_mode phymode = MODE_UNKNOWN;
396
397 if (WARN_ON(ath12k_mac_vif_chan(vif, &def)))
398 @@ -2594,6 +2762,7 @@ static void ath12k_peer_assoc_h_phymode(
399 band = def.chan->band;
400 ht_mcs_mask = arvif->bitrate_mask.control[band].ht_mcs;
401 vht_mcs_mask = arvif->bitrate_mask.control[band].vht_mcs;
402 + he_mcs_mask = arvif->bitrate_mask.control[band].he_mcs;
403
404 switch (band) {
405 case NL80211_BAND_2GHZ:
406 @@ -2602,7 +2771,8 @@ static void ath12k_peer_assoc_h_phymode(
407 phymode = MODE_11BE_EHT40_2G;
408 else
409 phymode = MODE_11BE_EHT20_2G;
410 - } else if (sta->deflink.he_cap.has_he) {
411 + } else if (sta->deflink.he_cap.has_he &&
412 + !ath12k_peer_assoc_h_he_masked(he_mcs_mask)) {
413 if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80)
414 phymode = MODE_11AX_HE80_2G;
415 else if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
416 @@ -2632,7 +2802,8 @@ static void ath12k_peer_assoc_h_phymode(
417 /* Check EHT first */
418 if (sta->deflink.eht_cap.has_eht) {
419 phymode = ath12k_mac_get_phymode_eht(ar, sta);
420 - } else if (sta->deflink.he_cap.has_he) {
421 + } else if (sta->deflink.he_cap.has_he &&
422 + !ath12k_peer_assoc_h_he_masked(he_mcs_mask)) {
423 phymode = ath12k_mac_get_phymode_he(ar, sta);
424 } else if (sta->deflink.vht_cap.vht_supported &&
425 !ath12k_peer_assoc_h_vht_masked(vht_mcs_mask)) {
426 @@ -4311,6 +4482,20 @@ ath12k_mac_bitrate_mask_num_vht_rates(st
427 }
428
429 static int
430 +ath12k_mac_bitrate_mask_num_he_rates(struct ath12k *ar,
431 + enum nl80211_band band,
432 + const struct cfg80211_bitrate_mask *mask)
433 +{
434 + int num_rates = 0;
435 + int i;
436 +
437 + for (i = 0; i < ARRAY_SIZE(mask->control[band].he_mcs); i++)
438 + num_rates += hweight16(mask->control[band].he_mcs[i]);
439 +
440 + return num_rates;
441 +}
442 +
443 +static int
444 ath12k_mac_set_peer_vht_fixed_rate(struct ath12k_vif *arvif,
445 struct ieee80211_sta *sta,
446 const struct cfg80211_bitrate_mask *mask,
447 @@ -4356,6 +4541,57 @@ ath12k_mac_set_peer_vht_fixed_rate(struc
448 return ret;
449 }
450
451 +static int
452 +ath12k_mac_set_peer_he_fixed_rate(struct ath12k_vif *arvif,
453 + struct ieee80211_sta *sta,
454 + const struct cfg80211_bitrate_mask *mask,
455 + enum nl80211_band band)
456 +{
457 + struct ath12k *ar = arvif->ar;
458 + u8 he_rate, nss;
459 + u32 rate_code;
460 + int ret, i;
461 +
462 + lockdep_assert_held(&ar->conf_mutex);
463 +
464 + nss = 0;
465 +
466 + for (i = 0; i < ARRAY_SIZE(mask->control[band].he_mcs); i++) {
467 + if (hweight16(mask->control[band].he_mcs[i]) == 1) {
468 + nss = i + 1;
469 + he_rate = ffs(mask->control[band].he_mcs[i]) - 1;
470 + }
471 + }
472 +
473 + if (!nss) {
474 + ath12k_warn(ar->ab, "No single HE Fixed rate found to set for %pM",
475 + sta->deflink.addr);
476 + return -EINVAL;
477 + }
478 +
479 + /* Avoid updating invalid nss as fixed rate*/
480 + if (nss > sta->deflink.rx_nss)
481 + return -EINVAL;
482 +
483 + ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
484 + "Setting Fixed HE Rate for peer %pM. Device will not switch to any other selected rates",
485 + sta->deflink.addr);
486 +
487 + rate_code = ATH12K_HW_RATE_CODE(he_rate, nss - 1,
488 + WMI_RATE_PREAMBLE_HE);
489 +
490 + ret = ath12k_wmi_set_peer_param(ar, sta->deflink.addr,
491 + arvif->vdev_id,
492 + WMI_PEER_PARAM_FIXED_RATE,
493 + rate_code);
494 + if (ret)
495 + ath12k_warn(ar->ab,
496 + "failed to update STA %pM Fixed Rate %d: %d\n",
497 + sta->deflink.addr, rate_code, ret);
498 +
499 + return ret;
500 +}
501 +
502 static int ath12k_station_assoc(struct ath12k *ar,
503 struct ieee80211_vif *vif,
504 struct ieee80211_sta *sta,
505 @@ -4367,7 +4603,7 @@ static int ath12k_station_assoc(struct a
506 struct cfg80211_chan_def def;
507 enum nl80211_band band;
508 struct cfg80211_bitrate_mask *mask;
509 - u8 num_vht_rates;
510 + u8 num_vht_rates, num_he_rates;
511
512 lockdep_assert_held(&ar->conf_mutex);
513
514 @@ -4398,15 +4634,19 @@ static int ath12k_station_assoc(struct a
515 }
516
517 num_vht_rates = ath12k_mac_bitrate_mask_num_vht_rates(ar, band, mask);
518 + num_he_rates = ath12k_mac_bitrate_mask_num_he_rates(ar, band, mask);
519
520 - /* If single VHT rate is configured (by set_bitrate_mask()),
521 - * peer_assoc will disable VHT. This is now enabled by a peer specific
522 + /* If single VHT/HE rate is configured (by set_bitrate_mask()),
523 + * peer_assoc will disable VHT/HE. This is now enabled by a peer specific
524 * fixed param.
525 * Note that all other rates and NSS will be disabled for this peer.
526 */
527 if (sta->deflink.vht_cap.vht_supported && num_vht_rates == 1) {
528 - ret = ath12k_mac_set_peer_vht_fixed_rate(arvif, sta, mask,
529 - band);
530 + ret = ath12k_mac_set_peer_vht_fixed_rate(arvif, sta, mask, band);
531 + if (ret)
532 + return ret;
533 + } else if (sta->deflink.he_cap.has_he && num_he_rates == 1) {
534 + ret = ath12k_mac_set_peer_he_fixed_rate(arvif, sta, mask, band);
535 if (ret)
536 return ret;
537 }
538 @@ -4480,8 +4720,9 @@ static void ath12k_sta_rc_update_wk(stru
539 enum nl80211_band band;
540 const u8 *ht_mcs_mask;
541 const u16 *vht_mcs_mask;
542 - u32 changed, bw, nss, smps, bw_prev;
543 - int err, num_vht_rates;
544 + const u16 *he_mcs_mask;
545 + u32 changed, bw, nss, mac_nss, smps, bw_prev;
546 + int err, num_vht_rates, num_he_rates;
547 const struct cfg80211_bitrate_mask *mask;
548 struct ath12k_wmi_peer_assoc_arg peer_arg;
549 enum wmi_phy_mode peer_phymode;
550 @@ -4497,6 +4738,7 @@ static void ath12k_sta_rc_update_wk(stru
551 band = def.chan->band;
552 ht_mcs_mask = arvif->bitrate_mask.control[band].ht_mcs;
553 vht_mcs_mask = arvif->bitrate_mask.control[band].vht_mcs;
554 + he_mcs_mask = arvif->bitrate_mask.control[band].he_mcs;
555
556 spin_lock_bh(&ar->data_lock);
557
558 @@ -4513,8 +4755,10 @@ static void ath12k_sta_rc_update_wk(stru
559 mutex_lock(&ar->conf_mutex);
560
561 nss = max_t(u32, 1, nss);
562 - nss = min(nss, max(ath12k_mac_max_ht_nss(ht_mcs_mask),
563 - ath12k_mac_max_vht_nss(vht_mcs_mask)));
564 + mac_nss = max3(ath12k_mac_max_ht_nss(ht_mcs_mask),
565 + ath12k_mac_max_vht_nss(vht_mcs_mask),
566 + ath12k_mac_max_he_nss(he_mcs_mask));
567 + nss = min(nss, mac_nss);
568
569 if (changed & IEEE80211_RC_BW_CHANGED) {
570 ath12k_peer_assoc_h_phymode(ar, arvif->vif, sta, &peer_arg);
571 @@ -4592,6 +4836,8 @@ static void ath12k_sta_rc_update_wk(stru
572 mask = &arvif->bitrate_mask;
573 num_vht_rates = ath12k_mac_bitrate_mask_num_vht_rates(ar, band,
574 mask);
575 + num_he_rates = ath12k_mac_bitrate_mask_num_he_rates(ar, band,
576 + mask);
577
578 /* Peer_assoc_prepare will reject vht rates in
579 * bitrate_mask if its not available in range format and
580 @@ -4607,11 +4853,24 @@ static void ath12k_sta_rc_update_wk(stru
581 if (sta->deflink.vht_cap.vht_supported && num_vht_rates == 1) {
582 ath12k_mac_set_peer_vht_fixed_rate(arvif, sta, mask,
583 band);
584 + } else if (sta->deflink.he_cap.has_he && num_he_rates == 1) {
585 + ath12k_mac_set_peer_he_fixed_rate(arvif, sta, mask, band);
586 } else {
587 - /* If the peer is non-VHT or no fixed VHT rate
588 + /* If the peer is non-VHT/HE or no fixed VHT/HE rate
589 * is provided in the new bitrate mask we set the
590 - * other rates using peer_assoc command.
591 + * other rates using peer_assoc command. Also clear
592 + * the peer fixed rate settings as it has higher proprity
593 + * than peer assoc
594 */
595 +
596 + err = ath12k_wmi_set_peer_param(ar, sta->deflink.addr,
597 + arvif->vdev_id,
598 + WMI_PEER_PARAM_FIXED_RATE,
599 + WMI_FIXED_RATE_NONE);
600 + if (err)
601 + ath12k_warn(ar->ab,
602 + "failed to disable peer fixed rate for STA %pM ret %d\n",
603 + sta->deflink.addr, err);
604 ath12k_peer_assoc_prepare(ar, arvif->vif, sta,
605 &peer_arg, true);
606
607 @@ -7059,10 +7318,13 @@ static int ath12k_mac_op_add_interface(s
608
609 for (i = 0; i < ARRAY_SIZE(arvif->bitrate_mask.control); i++) {
610 arvif->bitrate_mask.control[i].legacy = 0xffffffff;
611 + arvif->bitrate_mask.control[i].gi = NL80211_TXRATE_FORCE_SGI;
612 memset(arvif->bitrate_mask.control[i].ht_mcs, 0xff,
613 sizeof(arvif->bitrate_mask.control[i].ht_mcs));
614 memset(arvif->bitrate_mask.control[i].vht_mcs, 0xff,
615 sizeof(arvif->bitrate_mask.control[i].vht_mcs));
616 + memset(arvif->bitrate_mask.control[i].he_mcs, 0xff,
617 + sizeof(arvif->bitrate_mask.control[i].he_mcs));
618 }
619
620 /* Allocate Default Queue now and reassign during actual vdev create */
621 @@ -8223,19 +8485,40 @@ ath12k_mac_has_single_legacy_rate(struct
622 if (ath12k_mac_bitrate_mask_num_vht_rates(ar, band, mask))
623 return false;
624
625 + if (ath12k_mac_bitrate_mask_num_he_rates(ar, band, mask))
626 + return false;
627 +
628 return num_rates == 1;
629 }
630
631 +static __le16
632 +ath12k_mac_get_tx_mcs_map(const struct ieee80211_sta_he_cap *he_cap)
633 +{
634 + if (he_cap->he_cap_elem.phy_cap_info[0] &
635 + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)
636 + return he_cap->he_mcs_nss_supp.tx_mcs_80p80;
637 +
638 + if (he_cap->he_cap_elem.phy_cap_info[0] &
639 + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G)
640 + return he_cap->he_mcs_nss_supp.tx_mcs_160;
641 +
642 + return he_cap->he_mcs_nss_supp.tx_mcs_80;
643 +}
644 +
645 static bool
646 ath12k_mac_bitrate_mask_get_single_nss(struct ath12k *ar,
647 + struct ieee80211_vif *vif,
648 enum nl80211_band band,
649 const struct cfg80211_bitrate_mask *mask,
650 int *nss)
651 {
652 struct ieee80211_supported_band *sband = &ar->mac.sbands[band];
653 u16 vht_mcs_map = le16_to_cpu(sband->vht_cap.vht_mcs.tx_mcs_map);
654 + const struct ieee80211_sta_he_cap *he_cap;
655 + u16 he_mcs_map = 0;
656 u8 ht_nss_mask = 0;
657 u8 vht_nss_mask = 0;
658 + u8 he_nss_mask = 0;
659 int i;
660
661 /* No need to consider legacy here. Basic rates are always present
662 @@ -8262,7 +8545,24 @@ ath12k_mac_bitrate_mask_get_single_nss(s
663 return false;
664 }
665
666 - if (ht_nss_mask != vht_nss_mask)
667 + he_cap = ieee80211_get_he_iftype_cap_vif(sband, vif);
668 + if (!he_cap)
669 + return false;
670 +
671 + he_mcs_map = le16_to_cpu(ath12k_mac_get_tx_mcs_map(he_cap));
672 +
673 + for (i = 0; i < ARRAY_SIZE(mask->control[band].he_mcs); i++) {
674 + if (mask->control[band].he_mcs[i] == 0)
675 + continue;
676 +
677 + if (mask->control[band].he_mcs[i] ==
678 + ath12k_mac_get_max_he_mcs_map(he_mcs_map, i))
679 + he_nss_mask |= BIT(i);
680 + else
681 + return false;
682 + }
683 +
684 + if (ht_nss_mask != vht_nss_mask || ht_nss_mask != he_nss_mask)
685 return false;
686
687 if (ht_nss_mask == 0)
688 @@ -8309,54 +8609,158 @@ ath12k_mac_get_single_legacy_rate(struct
689 return 0;
690 }
691
692 -static int ath12k_mac_set_fixed_rate_params(struct ath12k_vif *arvif,
693 - u32 rate, u8 nss, u8 sgi, u8 ldpc)
694 +static int
695 +ath12k_mac_set_fixed_rate_gi_ltf(struct ath12k_vif *arvif, u8 he_gi, u8 he_ltf)
696 {
697 struct ath12k *ar = arvif->ar;
698 - u32 vdev_param;
699 int ret;
700
701 - lockdep_assert_held(&ar->conf_mutex);
702 + /* 0.8 = 0, 1.6 = 2 and 3.2 = 3. */
703 + if (he_gi && he_gi != 0xFF)
704 + he_gi += 1;
705
706 - ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac set fixed rate params vdev %i rate 0x%02x nss %u sgi %u\n",
707 - arvif->vdev_id, rate, nss, sgi);
708 + ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
709 + WMI_VDEV_PARAM_SGI, he_gi);
710 + if (ret) {
711 + ath12k_warn(ar->ab, "failed to set HE GI:%d, error:%d\n",
712 + he_gi, ret);
713 + return ret;
714 + }
715 + /* start from 1 */
716 + if (he_ltf != 0xFF)
717 + he_ltf += 1;
718
719 - vdev_param = WMI_VDEV_PARAM_FIXED_RATE;
720 ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
721 - vdev_param, rate);
722 + WMI_VDEV_PARAM_HE_LTF, he_ltf);
723 if (ret) {
724 - ath12k_warn(ar->ab, "failed to set fixed rate param 0x%02x: %d\n",
725 - rate, ret);
726 + ath12k_warn(ar->ab, "failed to set HE LTF:%d, error:%d\n",
727 + he_ltf, ret);
728 return ret;
729 }
730 + return 0;
731 +}
732 +
733 +static int
734 +ath12k_mac_set_auto_rate_gi_ltf(struct ath12k_vif *arvif, u16 he_gi, u8 he_ltf)
735 +{
736 + struct ath12k *ar = arvif->ar;
737 + int ret;
738 + u32 he_ar_gi_ltf;
739 +
740 + if (he_gi != 0xFF) {
741 + switch (he_gi) {
742 + case NL80211_RATE_INFO_HE_GI_0_8:
743 + he_gi = WMI_AUTORATE_800NS_GI;
744 + break;
745 + case NL80211_RATE_INFO_HE_GI_1_6:
746 + he_gi = WMI_AUTORATE_1600NS_GI;
747 + break;
748 + case NL80211_RATE_INFO_HE_GI_3_2:
749 + he_gi = WMI_AUTORATE_3200NS_GI;
750 + break;
751 + default:
752 + ath12k_warn(ar->ab, "Invalid GI\n");
753 + return -EINVAL;
754 + }
755 + }
756 +
757 + if (he_ltf != 0xFF) {
758 + switch (he_ltf) {
759 + case NL80211_RATE_INFO_HE_1XLTF:
760 + he_ltf = WMI_HE_AUTORATE_LTF_1X;
761 + break;
762 + case NL80211_RATE_INFO_HE_2XLTF:
763 + he_ltf = WMI_HE_AUTORATE_LTF_2X;
764 + break;
765 + case NL80211_RATE_INFO_HE_4XLTF:
766 + he_ltf = WMI_HE_AUTORATE_LTF_4X;
767 + break;
768 + default:
769 + ath12k_warn(ar->ab, "Invalid LTF\n");
770 + return -EINVAL;
771 + }
772 + }
773 +
774 + he_ar_gi_ltf = he_gi | he_ltf;
775
776 - vdev_param = WMI_VDEV_PARAM_NSS;
777 ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
778 - vdev_param, nss);
779 + WMI_VDEV_PARAM_AUTORATE_MISC_CFG,
780 + he_ar_gi_ltf);
781 if (ret) {
782 - ath12k_warn(ar->ab, "failed to set nss param %d: %d\n",
783 - nss, ret);
784 + ath12k_warn(ar->ab,
785 + "failed to set HE autorate GI:%u, LTF:%u params, error:%d\n",
786 + he_gi, he_ltf, ret);
787 return ret;
788 }
789
790 - vdev_param = WMI_VDEV_PARAM_SGI;
791 + return 0;
792 +}
793 +
794 +static int ath12k_mac_set_rate_params(struct ath12k_vif *arvif,
795 + u32 rate, u8 nss, u8 sgi, u8 ldpc,
796 + u8 he_gi, u8 he_ltf, bool he_fixed_rate)
797 +{
798 + struct ath12k *ar = arvif->ar;
799 + u32 vdev_param;
800 + int ret;
801 +
802 + lockdep_assert_held(&ar->conf_mutex);
803 +
804 + ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
805 + "mac set rate params vdev %i rate 0x%02x nss 0x%02x sgi 0x%02x ldpc 0x%02x\n",
806 + arvif->vdev_id, rate, nss, sgi, ldpc);
807 +
808 + ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
809 + "he_gi 0x%02x he_ltf 0x%02x he_fixed_rate %d\n", he_gi,
810 + he_ltf, he_fixed_rate);
811 +
812 + if (!arvif->vif->bss_conf.he_support) {
813 + vdev_param = WMI_VDEV_PARAM_FIXED_RATE;
814 + ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
815 + vdev_param, rate);
816 + if (ret) {
817 + ath12k_warn(ar->ab, "failed to set fixed rate param 0x%02x: %d\n",
818 + rate, ret);
819 + return ret;
820 + }
821 + }
822 +
823 + vdev_param = WMI_VDEV_PARAM_NSS;
824 +
825 ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
826 - vdev_param, sgi);
827 + vdev_param, nss);
828 if (ret) {
829 - ath12k_warn(ar->ab, "failed to set sgi param %d: %d\n",
830 - sgi, ret);
831 + ath12k_warn(ar->ab, "failed to set nss param %d: %d\n",
832 + nss, ret);
833 return ret;
834 }
835
836 - vdev_param = WMI_VDEV_PARAM_LDPC;
837 ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
838 - vdev_param, ldpc);
839 + WMI_VDEV_PARAM_LDPC, ldpc);
840 if (ret) {
841 ath12k_warn(ar->ab, "failed to set ldpc param %d: %d\n",
842 ldpc, ret);
843 return ret;
844 }
845
846 + if (arvif->vif->bss_conf.he_support) {
847 + if (he_fixed_rate)
848 + ret = ath12k_mac_set_fixed_rate_gi_ltf(arvif, he_gi, he_ltf);
849 + else
850 + ret = ath12k_mac_set_auto_rate_gi_ltf(arvif, he_gi, he_ltf);
851 + if (ret)
852 + return ret;
853 + } else {
854 + vdev_param = WMI_VDEV_PARAM_SGI;
855 + ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
856 + vdev_param, sgi);
857 + if (ret) {
858 + ath12k_warn(ar->ab, "failed to set sgi param %d: %d\n",
859 + sgi, ret);
860 + return ret;
861 + }
862 + }
863 +
864 return 0;
865 }
866
867 @@ -8385,6 +8789,31 @@ ath12k_mac_vht_mcs_range_present(struct
868 return true;
869 }
870
871 +static bool
872 +ath12k_mac_he_mcs_range_present(struct ath12k *ar,
873 + enum nl80211_band band,
874 + const struct cfg80211_bitrate_mask *mask)
875 +{
876 + int i;
877 + u16 he_mcs;
878 +
879 + for (i = 0; i < NL80211_HE_NSS_MAX; i++) {
880 + he_mcs = mask->control[band].he_mcs[i];
881 +
882 + switch (he_mcs) {
883 + case 0:
884 + case BIT(8) - 1:
885 + case BIT(10) - 1:
886 + case BIT(12) - 1:
887 + break;
888 + default:
889 + return false;
890 + }
891 + }
892 +
893 + return true;
894 +}
895 +
896 static void ath12k_mac_set_bitrate_mask_iter(void *data,
897 struct ieee80211_sta *sta)
898 {
899 @@ -8424,6 +8853,54 @@ static void ath12k_mac_disable_peer_fixe
900 }
901
902 static int
903 +ath12k_mac_validate_vht_he_fixed_rate_settings(struct ath12k *ar, enum nl80211_band band,
904 + const struct cfg80211_bitrate_mask *mask)
905 +{
906 + bool he_fixed_rate = false, vht_fixed_rate = false;
907 + struct ath12k_peer *peer;
908 + const u16 *vht_mcs_mask, *he_mcs_mask;
909 + u8 vht_nss, he_nss;
910 + int ret = 0;
911 +
912 + vht_mcs_mask = mask->control[band].vht_mcs;
913 + he_mcs_mask = mask->control[band].he_mcs;
914 +
915 + if (ath12k_mac_bitrate_mask_num_vht_rates(ar, band, mask) == 1)
916 + vht_fixed_rate = true;
917 +
918 + if (ath12k_mac_bitrate_mask_num_he_rates(ar, band, mask) == 1)
919 + he_fixed_rate = true;
920 +
921 + if (!vht_fixed_rate && !he_fixed_rate)
922 + return 0;
923 +
924 + vht_nss = ath12k_mac_max_vht_nss(vht_mcs_mask);
925 + he_nss = ath12k_mac_max_he_nss(he_mcs_mask);
926 +
927 + rcu_read_lock();
928 + spin_lock_bh(&ar->ab->base_lock);
929 + list_for_each_entry(peer, &ar->ab->peers, list) {
930 + if (peer->sta) {
931 + if (vht_fixed_rate &&
932 + (!peer->sta->deflink.vht_cap.vht_supported ||
933 + peer->sta->deflink.rx_nss < vht_nss)) {
934 + ret = -EINVAL;
935 + goto exit;
936 + }
937 + if (he_fixed_rate && (!peer->sta->deflink.he_cap.has_he ||
938 + peer->sta->deflink.rx_nss < he_nss)) {
939 + ret = -EINVAL;
940 + goto exit;
941 + }
942 + }
943 + }
944 +exit:
945 + spin_unlock_bh(&ar->ab->base_lock);
946 + rcu_read_unlock();
947 + return ret;
948 +}
949 +
950 +static int
951 ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw,
952 struct ieee80211_vif *vif,
953 const struct cfg80211_bitrate_mask *mask)
954 @@ -8434,13 +8911,17 @@ ath12k_mac_op_set_bitrate_mask(struct ie
955 enum nl80211_band band;
956 const u8 *ht_mcs_mask;
957 const u16 *vht_mcs_mask;
958 + const u16 *he_mcs_mask;
959 + u8 he_ltf = 0;
960 + u8 he_gi = 0;
961 u32 rate;
962 - u8 nss;
963 + u8 nss, mac_nss;
964 u8 sgi;
965 u8 ldpc;
966 int single_nss;
967 int ret;
968 int num_rates;
969 + bool he_fixed_rate = false;
970
971 if (ath12k_mac_vif_chan(vif, &def))
972 return -EPERM;
973 @@ -8448,6 +8929,7 @@ ath12k_mac_op_set_bitrate_mask(struct ie
974 band = def.chan->band;
975 ht_mcs_mask = mask->control[band].ht_mcs;
976 vht_mcs_mask = mask->control[band].vht_mcs;
977 + he_mcs_mask = mask->control[band].he_mcs;
978 ldpc = !!(ar->ht_cap_info & WMI_HT_CAP_LDPC);
979
980 sgi = mask->control[band].gi;
981 @@ -8456,6 +8938,9 @@ ath12k_mac_op_set_bitrate_mask(struct ie
982 goto out;
983 }
984
985 + he_gi = mask->control[band].he_gi;
986 + he_ltf = mask->control[band].he_ltf;
987 +
988 /* mac80211 doesn't support sending a fixed HT/VHT MCS alone, rather it
989 * requires passing at least one of used basic rates along with them.
990 * Fixed rate setting across different preambles(legacy, HT, VHT) is
991 @@ -8475,15 +8960,27 @@ ath12k_mac_op_set_bitrate_mask(struct ie
992 ieee80211_iterate_stations_mtx(hw,
993 ath12k_mac_disable_peer_fixed_rate,
994 arvif);
995 - } else if (ath12k_mac_bitrate_mask_get_single_nss(ar, band, mask,
996 + } else if (ath12k_mac_bitrate_mask_get_single_nss(ar, vif, band, mask,
997 &single_nss)) {
998 rate = WMI_FIXED_RATE_NONE;
999 nss = single_nss;
1000 + mutex_lock(&ar->conf_mutex);
1001 + arvif->bitrate_mask = *mask;
1002 + ieee80211_iterate_stations_mtx(hw,
1003 + ath12k_mac_set_bitrate_mask_iter,
1004 + arvif);
1005 + mutex_unlock(&ar->conf_mutex);
1006 } else {
1007 rate = WMI_FIXED_RATE_NONE;
1008 - nss = min_t(u32, ar->num_tx_chains,
1009 - max(ath12k_mac_max_ht_nss(ht_mcs_mask),
1010 - ath12k_mac_max_vht_nss(vht_mcs_mask)));
1011 +
1012 + if (!ath12k_mac_validate_vht_he_fixed_rate_settings(ar, band, mask))
1013 + ath12k_warn(ar->ab,
1014 + "could not update fixed rate settings to all peers due to mcs/nss incompatiblity\n");
1015 +
1016 + mac_nss = max3(ath12k_mac_max_ht_nss(ht_mcs_mask),
1017 + ath12k_mac_max_vht_nss(vht_mcs_mask),
1018 + ath12k_mac_max_he_nss(he_mcs_mask));
1019 + nss = min_t(u32, ar->num_tx_chains, mac_nss);
1020
1021 /* If multiple rates across different preambles are given
1022 * we can reconfigure this info with all peers using PEER_ASSOC
1023 @@ -8519,12 +9016,22 @@ ath12k_mac_op_set_bitrate_mask(struct ie
1024 goto out;
1025 }
1026
1027 + num_rates = ath12k_mac_bitrate_mask_num_he_rates(ar, band, mask);
1028 + if (num_rates == 1)
1029 + he_fixed_rate = true;
1030 +
1031 + if (!ath12k_mac_he_mcs_range_present(ar, band, mask) &&
1032 + num_rates > 1) {
1033 + ath12k_warn(ar->ab,
1034 + "Setting more than one HE MCS Value in bitrate mask not supported\n");
1035 + return -EINVAL;
1036 + }
1037 +
1038 + mutex_lock(&ar->conf_mutex);
1039 ieee80211_iterate_stations_mtx(hw,
1040 ath12k_mac_disable_peer_fixed_rate,
1041 arvif);
1042
1043 - mutex_lock(&ar->conf_mutex);
1044 -
1045 arvif->bitrate_mask = *mask;
1046 ieee80211_iterate_stations_mtx(hw,
1047 ath12k_mac_set_bitrate_mask_iter,
1048 @@ -8535,9 +9042,10 @@ ath12k_mac_op_set_bitrate_mask(struct ie
1049
1050 mutex_lock(&ar->conf_mutex);
1051
1052 - ret = ath12k_mac_set_fixed_rate_params(arvif, rate, nss, sgi, ldpc);
1053 + ret = ath12k_mac_set_rate_params(arvif, rate, nss, sgi, ldpc, he_gi,
1054 + he_ltf, he_fixed_rate);
1055 if (ret) {
1056 - ath12k_warn(ar->ab, "failed to set fixed rate params on vdev %i: %d\n",
1057 + ath12k_warn(ar->ab, "failed to set rate params on vdev %i: %d\n",
1058 arvif->vdev_id, ret);
1059 }
1060
1061 --- a/drivers/net/wireless/ath/ath12k/wmi.h
1062 +++ b/drivers/net/wireless/ath/ath12k/wmi.h
1063 @@ -220,6 +220,22 @@ enum WMI_HOST_WLAN_BAND {
1064 WMI_HOST_WLAN_2G_5G_CAP = 3,
1065 };
1066
1067 +/* Parameters used for WMI_VDEV_PARAM_AUTORATE_MISC_CFG command.
1068 + * Used only for HE auto rate mode.
1069 + */
1070 +enum {
1071 + /* HE LTF related configuration */
1072 + WMI_HE_AUTORATE_LTF_1X = BIT(0),
1073 + WMI_HE_AUTORATE_LTF_2X = BIT(1),
1074 + WMI_HE_AUTORATE_LTF_4X = BIT(2),
1075 +
1076 + /* HE GI related configuration */
1077 + WMI_AUTORATE_400NS_GI = BIT(8),
1078 + WMI_AUTORATE_800NS_GI = BIT(9),
1079 + WMI_AUTORATE_1600NS_GI = BIT(10),
1080 + WMI_AUTORATE_3200NS_GI = BIT(11),
1081 +};
1082 +
1083 enum wmi_cmd_group {
1084 /* 0 to 2 are reserved */
1085 WMI_GRP_START = 0x3,
1086 @@ -1132,7 +1148,9 @@ enum wmi_tlv_vdev_param {
1087 WMI_VDEV_PARAM_HE_RANGE_EXT,
1088 WMI_VDEV_PARAM_ENABLE_BCAST_PROBE_RESPONSE,
1089 WMI_VDEV_PARAM_FILS_MAX_CHANNEL_GUARD_TIME,
1090 + WMI_VDEV_PARAM_HE_LTF = 0x74,
1091 WMI_VDEV_PARAM_BA_MODE = 0x7e,
1092 + WMI_VDEV_PARAM_AUTORATE_MISC_CFG = 0x80,
1093 WMI_VDEV_PARAM_SET_HE_SOUNDING_MODE = 0x87,
1094 WMI_VDEV_PARAM_6GHZ_PARAMS = 0x99,
1095 WMI_VDEV_PARAM_PROTOTYPE = 0x8000,