3f63eb08d17db80bb099a5d4b95d6cf7039c2013
[openwrt/openwrt.git] /
1 From patchwork Wed May 21 22:45:36 2025
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: 14096125
7 X-Patchwork-Delegate: quic_jjohnson@quicinc.com
8 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com
9 [205.220.180.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 9A17F1B0F20
13 for <linux-wireless@vger.kernel.org>; Wed, 21 May 2025 22:45:59 +0000 (UTC)
14 Authentication-Results: smtp.subspace.kernel.org;
15 arc=none smtp.client-ip=205.220.180.131
16 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;
17 t=1747867562; cv=none;
18 b=bEGfSmKJAIERqJyK0yJndcYM+a7cpfrIkMLoGUTFvAkrcwqnlh3F9AqLbcb8fKznhfaQKFVRUdpVGSjFaplFVSp20RuXvPC2NLb0eKZrz5qS/4geTMxY/BeWuVN+i3ouoQzfYz8Vq6sTqLE5d6b650cCVf8hpY+VZ3ZTNWxVvdA=
19 ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org;
20 s=arc-20240116; t=1747867562; c=relaxed/simple;
21 bh=hBxlXRYYCPbv8+evEatym1UfdpOfENFUVDWgibN+XTg=;
22 h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References:
23 MIME-Version:Content-Type;
24 b=U32JKi6TAoRF/9e1cv0vPGUM6BaRhoFXM0b36j5PBpvKQmRXKDF/UNScd5EJnrFOPlgjPD7GOc+TdHqsFGk/7pNucA1++GU00SZ0q/223zg5dCsYLmfLrRu3G22WZS2hWuNKuUPFJEFFLEJ8UQWKtFB0oWsQcx+Oj1mWPbBrDU8=
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=bzVTzUcl; arc=none smtp.client-ip=205.220.180.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="bzVTzUcl"
37 Received: from pps.filterd (m0279868.ppops.net [127.0.0.1])
38 by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id
39 54LJiK6V032422;
40 Wed, 21 May 2025 22:45:55 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 cpcIGD4iPSOaZzDkHZpoGs5Kor0sF3EnocHYcBOazgM=; b=bzVTzUclt3RkLn9A
45 YI8+MC64RjF5llUqmQ0G53D8sAQZ+95fc92X/ZrZvnyr7X0FBI+gU05yKzNuv4M5
46 XcIWK7Y8gjr55i9w18cWHGW2Q/JGC8pJlx0A/SEAMIMXeeEmgJqdKowT2wMjzIIH
47 wb7JmE9d6z6ZKcgQYx9KICXaaEFQ9uxyRyjlJMMEJ3zb7MjxZPCCGtCI31Aqczpk
48 B3X+1UgRT+OJzV6vIF0kdn/sjU69iZNHoPAUDYqInWCs2lPLMUO5mckhOG3fH8s6
49 jmhgpwlpUYx18jawRUpklvujXfFiDV4daXLeUKzL5b08f5OcSRvd7+iOytudYgr0
50 U9VYkw==
51 Received: from nalasppmta03.qualcomm.com (Global_NAT1.qualcomm.com
52 [129.46.96.20])
53 by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 46rwfb4b3w-1
54 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT);
55 Wed, 21 May 2025 22:45:55 +0000 (GMT)
56 Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com
57 [10.47.209.196])
58 by NALASPPMTA03.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id
59 54LMjsC2027097
60 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT);
61 Wed, 21 May 2025 22:45:54 GMT
62 Received: from ath12k-linux2.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, 21 May 2025 15:45:53 -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 Subject: [PATCH ath-next V14 6/9] wifi: ath12k: add support for setting fixed
73 HE rate/GI/LTF
74 Date: Wed, 21 May 2025 15:45:36 -0700
75 Message-ID: <20250521224539.355985-7-quic_pradeepc@quicinc.com>
76 X-Mailer: git-send-email 2.43.0
77 In-Reply-To: <20250521224539.355985-1-quic_pradeepc@quicinc.com>
78 References: <20250521224539.355985-1-quic_pradeepc@quicinc.com>
79 Precedence: bulk
80 X-Mailing-List: linux-wireless@vger.kernel.org
81 List-Id: <linux-wireless.vger.kernel.org>
82 List-Subscribe: <mailto:linux-wireless+subscribe@vger.kernel.org>
83 List-Unsubscribe: <mailto:linux-wireless+unsubscribe@vger.kernel.org>
84 MIME-Version: 1.0
85 X-ClientProxiedBy: nasanex01a.na.qualcomm.com (10.52.223.231) To
86 nalasex01a.na.qualcomm.com (10.47.209.196)
87 X-QCInternal: smtphost
88 X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800
89 signatures=585085
90 X-Proofpoint-ORIG-GUID: 7uuxK_kl_b0JzKZoWIyq_ZYKeKL3it15
91 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUwNTIxMDIyNiBTYWx0ZWRfX7sjoM15po0tB
92 FcR1nwzr8TocaDYnIXgl13rA+kjwsizlMt/N5cu8dCWo9YQKqFNy42Z2VEYmoDRw7dBnYnsMIL/
93 wwv4hQYQslnxilRJaX/MVQ50/xxhSry8NrKA2QXvIg3btmiW4gQfrn3+k1Rm3o/gAGv2Yz4R8lw
94 YBPHVdQkgGJXYgsiB/b+copbnU621GYiYrCW6yUQHHIiwzjMljzzsk+9Koc6yeVByyPj86P80y7
95 2C8L1vuRAy8gCMSScMB9CyQ6+tLCKa1W2bhA0Oxz/+RGEXbujS4NDXCWz+EqIaYS5HXuD32pODy
96 O2wMURrbgE5PJIjjvpAdtqZL65QVaoVK1LWU6Co0NtHytEjuaZmr1hbb4hVDAtQio2Bw/K8yCM+
97 ikcJ1sGkE78mu/U7gQjG6g0Z71Q/w13jBOz+RIocPFi2FyEjy5KDFmUBzY+jDCIRLi06R8sP
98 X-Proofpoint-GUID: 7uuxK_kl_b0JzKZoWIyq_ZYKeKL3it15
99 X-Authority-Analysis: v=2.4 cv=dLCmmPZb c=1 sm=1 tr=0 ts=682e57a3 cx=c_pps
100 a=ouPCqIW2jiPt+lZRy3xVPw==:117 a=ouPCqIW2jiPt+lZRy3xVPw==:17
101 a=GEpy-HfZoHoA:10 a=dt9VzEwgFbYA:10 a=COk6AnOGAAAA:8 a=KygRlO7-s-l5tpycOzUA:9
102 a=TjNXssC_j7lpFel5tvFf:22
103 X-Proofpoint-Virus-Version: vendor=baseguard
104 engine=ICAP:2.0.293,Aquarius:18.0.1099,Hydra:6.0.736,FMLib:17.12.80.40
105 definitions=2025-05-21_07,2025-05-20_03,2025-03-28_01
106 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0
107 mlxscore=0 clxscore=1015 adultscore=0 bulkscore=0 phishscore=0 suspectscore=0
108 impostorscore=0 malwarescore=0 lowpriorityscore=0 mlxlogscore=999 spamscore=0
109 priorityscore=1501 classifier=spam authscore=0 authtc=n/a authcc=
110 route=outbound adjust=0 reason=mlx scancount=1 engine=8.19.0-2505160000
111 definitions=main-2505210226
112
113 Add support to set fixed HE rate/GI/LTF values using nl80211.
114 Reuse parts of the existing code path already used for HT/VHT
115 to implement the new helpers symmetrically, similar to how
116 HT/VHT is handled.
117
118 Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1
119
120 Co-developed-by: Muna Sinada <quic_msinada@quicinc.com>
121 Signed-off-by: Muna Sinada <quic_msinada@quicinc.com>
122 Signed-off-by: Pradeep Kumar Chitrapu <quic_pradeepc@quicinc.com>
123 ---
124 drivers/net/wireless/ath/ath12k/mac.c | 650 +++++++++++++++++++++++---
125 drivers/net/wireless/ath/ath12k/wmi.h | 27 ++
126 2 files changed, 625 insertions(+), 52 deletions(-)
127
128 --- a/drivers/net/wireless/ath/ath12k/mac.c
129 +++ b/drivers/net/wireless/ath/ath12k/mac.c
130 @@ -518,6 +518,18 @@ ath12k_mac_max_vht_nss(const u16 *vht_mc
131 return 1;
132 }
133
134 +static u32
135 +ath12k_mac_max_he_nss(const u16 he_mcs_mask[NL80211_HE_NSS_MAX])
136 +{
137 + int nss;
138 +
139 + for (nss = NL80211_HE_NSS_MAX - 1; nss >= 0; nss--)
140 + if (he_mcs_mask[nss])
141 + return nss + 1;
142 +
143 + return 1;
144 +}
145 +
146 static u8 ath12k_parse_mpdudensity(u8 mpdudensity)
147 {
148 /* From IEEE Std 802.11-2020 defined values for "Minimum MPDU Start Spacing":
149 @@ -2135,9 +2147,15 @@ static void ath12k_peer_assoc_h_ht(struc
150 arg->peer_rate_caps |= WMI_HOST_RC_CW40_FLAG;
151 }
152
153 - if (arvif->bitrate_mask.control[band].gi != NL80211_TXRATE_FORCE_LGI) {
154 - if (ht_cap->cap & (IEEE80211_HT_CAP_SGI_20 |
155 - IEEE80211_HT_CAP_SGI_40))
156 + /* As firmware handles these two flags (IEEE80211_HT_CAP_SGI_20
157 + * and IEEE80211_HT_CAP_SGI_40) for enabling SGI, reset both
158 + * flags if guard interval is to force Long GI
159 + */
160 + if (arvif->bitrate_mask.control[band].gi == NL80211_TXRATE_FORCE_LGI) {
161 + arg->peer_ht_caps &= ~(IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40);
162 + } else {
163 + /* Enable SGI flag if either SGI_20 or SGI_40 is supported */
164 + if (ht_cap->cap & (IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40))
165 arg->peer_rate_caps |= WMI_HOST_RC_SGI_FLAG;
166 }
167
168 @@ -2260,11 +2278,12 @@ static void ath12k_peer_assoc_h_vht(stru
169 struct ieee80211_link_sta *link_sta;
170 struct cfg80211_chan_def def;
171 enum nl80211_band band;
172 - const u16 *vht_mcs_mask;
173 + u16 *vht_mcs_mask;
174 u16 tx_mcs_map;
175 u8 ampdu_factor;
176 u8 max_nss, vht_mcs;
177 - int i;
178 + int i, vht_nss, nss_idx;
179 + bool user_rate_valid = true;
180
181 lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
182
183 @@ -2317,6 +2336,25 @@ static void ath12k_peer_assoc_h_vht(stru
184 if (link_sta->bandwidth == IEEE80211_STA_RX_BW_160)
185 arg->bw_160 = true;
186
187 + vht_nss = ath12k_mac_max_vht_nss(vht_mcs_mask);
188 +
189 + if (vht_nss > link_sta->rx_nss) {
190 + user_rate_valid = false;
191 + for (nss_idx = link_sta->rx_nss - 1; nss_idx >= 0; nss_idx--) {
192 + if (vht_mcs_mask[nss_idx]) {
193 + user_rate_valid = true;
194 + break;
195 + }
196 + }
197 + }
198 +
199 + if (!user_rate_valid) {
200 + ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
201 + "Setting vht range MCS value to peer supported nss:%d for peer %pM\n",
202 + link_sta->rx_nss, arsta->addr);
203 + vht_mcs_mask[link_sta->rx_nss - 1] = vht_mcs_mask[vht_nss - 1];
204 + }
205 +
206 /* Calculate peer NSS capability from VHT capabilities if STA
207 * supports VHT.
208 */
209 @@ -2356,6 +2394,72 @@ static void ath12k_peer_assoc_h_vht(stru
210 /* TODO: rxnss_override */
211 }
212
213 +static int ath12k_mac_get_max_he_mcs_map(u16 mcs_map, int nss)
214 +{
215 + switch ((mcs_map >> (2 * nss)) & 0x3) {
216 + case IEEE80211_HE_MCS_SUPPORT_0_7: return BIT(8) - 1;
217 + case IEEE80211_HE_MCS_SUPPORT_0_9: return BIT(10) - 1;
218 + case IEEE80211_HE_MCS_SUPPORT_0_11: return BIT(12) - 1;
219 + }
220 + return 0;
221 +}
222 +
223 +static u16 ath12k_peer_assoc_h_he_limit(u16 tx_mcs_set,
224 + const u16 *he_mcs_limit)
225 +{
226 + int idx_limit;
227 + int nss;
228 + u16 mcs_map;
229 + u16 mcs;
230 +
231 + for (nss = 0; nss < NL80211_HE_NSS_MAX; nss++) {
232 + mcs_map = ath12k_mac_get_max_he_mcs_map(tx_mcs_set, nss) &
233 + he_mcs_limit[nss];
234 +
235 + if (mcs_map)
236 + idx_limit = fls(mcs_map) - 1;
237 + else
238 + idx_limit = -1;
239 +
240 + switch (idx_limit) {
241 + case 0 ... 7:
242 + mcs = IEEE80211_HE_MCS_SUPPORT_0_7;
243 + break;
244 + case 8:
245 + case 9:
246 + mcs = IEEE80211_HE_MCS_SUPPORT_0_9;
247 + break;
248 + case 10:
249 + case 11:
250 + mcs = IEEE80211_HE_MCS_SUPPORT_0_11;
251 + break;
252 + default:
253 + WARN_ON(1);
254 + fallthrough;
255 + case -1:
256 + mcs = IEEE80211_HE_MCS_NOT_SUPPORTED;
257 + break;
258 + }
259 +
260 + tx_mcs_set &= ~(0x3 << (nss * 2));
261 + tx_mcs_set |= mcs << (nss * 2);
262 + }
263 +
264 + return tx_mcs_set;
265 +}
266 +
267 +static bool
268 +ath12k_peer_assoc_h_he_masked(const u16 he_mcs_mask[NL80211_HE_NSS_MAX])
269 +{
270 + int nss;
271 +
272 + for (nss = 0; nss < NL80211_HE_NSS_MAX; nss++)
273 + if (he_mcs_mask[nss])
274 + return false;
275 +
276 + return true;
277 +}
278 +
279 static void ath12k_peer_assoc_h_he(struct ath12k *ar,
280 struct ath12k_link_vif *arvif,
281 struct ath12k_link_sta *arsta,
282 @@ -2366,18 +2470,28 @@ static void ath12k_peer_assoc_h_he(struc
283 const struct ieee80211_sta_he_cap *he_cap;
284 struct ieee80211_bss_conf *link_conf;
285 struct ieee80211_link_sta *link_sta;
286 + struct cfg80211_chan_def def;
287 int i;
288 u8 ampdu_factor, max_nss;
289 u8 rx_mcs_80 = IEEE80211_HE_MCS_NOT_SUPPORTED;
290 u8 rx_mcs_160 = IEEE80211_HE_MCS_NOT_SUPPORTED;
291 u16 mcs_160_map, mcs_80_map;
292 + u8 link_id = arvif->link_id;
293 bool support_160;
294 - u16 v;
295 + enum nl80211_band band;
296 + u16 *he_mcs_mask;
297 + u8 he_mcs;
298 + u16 he_tx_mcs = 0, v = 0;
299 + int he_nss, nss_idx;
300 + bool user_rate_valid = true;
301 +
302 + if (WARN_ON(ath12k_mac_vif_link_chan(vif, link_id, &def)))
303 + return;
304
305 link_conf = ath12k_mac_get_link_bss_conf(arvif);
306 if (!link_conf) {
307 ath12k_warn(ar->ab, "unable to access bss link conf in peer assoc he for vif %pM link %u",
308 - vif->addr, arvif->link_id);
309 + vif->addr, link_id);
310 return;
311 }
312
313 @@ -2392,6 +2506,12 @@ static void ath12k_peer_assoc_h_he(struc
314 if (!he_cap->has_he)
315 return;
316
317 + band = def.chan->band;
318 + he_mcs_mask = arvif->bitrate_mask.control[band].he_mcs;
319 +
320 + if (ath12k_peer_assoc_h_he_masked(he_mcs_mask))
321 + return;
322 +
323 arg->he_flag = true;
324
325 support_160 = !!(he_cap->he_cap_elem.phy_cap_info[0] &
326 @@ -2497,25 +2617,47 @@ static void ath12k_peer_assoc_h_he(struc
327 if (he_cap->he_cap_elem.mac_cap_info[0] & IEEE80211_HE_MAC_CAP0_TWT_REQ)
328 arg->twt_requester = true;
329
330 + he_nss = ath12k_mac_max_he_nss(he_mcs_mask);
331 +
332 + if (he_nss > link_sta->rx_nss) {
333 + user_rate_valid = false;
334 + for (nss_idx = link_sta->rx_nss - 1; nss_idx >= 0; nss_idx--) {
335 + if (he_mcs_mask[nss_idx]) {
336 + user_rate_valid = true;
337 + break;
338 + }
339 + }
340 + }
341 +
342 + if (!user_rate_valid) {
343 + ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
344 + "Setting he range MCS value to peer supported nss:%d for peer %pM\n",
345 + link_sta->rx_nss, arsta->addr);
346 + he_mcs_mask[link_sta->rx_nss - 1] = he_mcs_mask[he_nss - 1];
347 + }
348 +
349 switch (link_sta->bandwidth) {
350 case IEEE80211_STA_RX_BW_160:
351 if (he_cap->he_cap_elem.phy_cap_info[0] &
352 IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G) {
353 - v = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_80p80);
354 + v = ath12k_peer_assoc_h_he_limit(v, he_mcs_mask);
355 arg->peer_he_rx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80_80] = v;
356
357 v = le16_to_cpu(he_cap->he_mcs_nss_supp.tx_mcs_80p80);
358 arg->peer_he_tx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80_80] = v;
359
360 arg->peer_he_mcs_count++;
361 + he_tx_mcs = v;
362 }
363 v = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_160);
364 arg->peer_he_rx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_160] = v;
365
366 - v = le16_to_cpu(he_cap->he_mcs_nss_supp.tx_mcs_160);
367 + v = ath12k_peer_assoc_h_he_limit(v, he_mcs_mask);
368 arg->peer_he_tx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_160] = v;
369
370 arg->peer_he_mcs_count++;
371 + if (!he_tx_mcs)
372 + he_tx_mcs = v;
373 fallthrough;
374
375 default:
376 @@ -2523,11 +2665,36 @@ static void ath12k_peer_assoc_h_he(struc
377 arg->peer_he_rx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80] = v;
378
379 v = le16_to_cpu(he_cap->he_mcs_nss_supp.tx_mcs_80);
380 + v = ath12k_peer_assoc_h_he_limit(v, he_mcs_mask);
381 arg->peer_he_tx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80] = v;
382
383 arg->peer_he_mcs_count++;
384 + if (!he_tx_mcs)
385 + he_tx_mcs = v;
386 break;
387 }
388 +
389 + /* Calculate peer NSS capability from HE capabilities if STA
390 + * supports HE.
391 + */
392 + for (i = 0, max_nss = 0, he_mcs = 0; i < NL80211_HE_NSS_MAX; i++) {
393 + he_mcs = he_tx_mcs >> (2 * i) & 3;
394 +
395 + /* In case of fixed rates, MCS Range in he_tx_mcs might have
396 + * unsupported range, with he_mcs_mask set, so check either of them
397 + * to find nss.
398 + */
399 + if (he_mcs != IEEE80211_HE_MCS_NOT_SUPPORTED ||
400 + he_mcs_mask[i])
401 + max_nss = i + 1;
402 + }
403 +
404 + max_nss = min(max_nss, ar->num_tx_chains);
405 + arg->peer_nss = min(link_sta->rx_nss, max_nss);
406 +
407 + ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
408 + "mac he peer %pM nss %d mcs cnt %d\n",
409 + arsta->addr, arg->peer_nss, arg->peer_he_mcs_count);
410 }
411
412 static void ath12k_peer_assoc_h_he_6ghz(struct ath12k *ar,
413 @@ -2863,6 +3030,7 @@ static void ath12k_peer_assoc_h_phymode(
414 enum nl80211_band band;
415 const u8 *ht_mcs_mask;
416 const u16 *vht_mcs_mask;
417 + const u16 *he_mcs_mask;
418 enum wmi_phy_mode phymode = MODE_UNKNOWN;
419
420 lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
421 @@ -2876,6 +3044,7 @@ static void ath12k_peer_assoc_h_phymode(
422 band = def.chan->band;
423 ht_mcs_mask = arvif->bitrate_mask.control[band].ht_mcs;
424 vht_mcs_mask = arvif->bitrate_mask.control[band].vht_mcs;
425 + he_mcs_mask = arvif->bitrate_mask.control[band].he_mcs;
426
427 link_sta = ath12k_mac_get_link_sta(arsta);
428 if (!link_sta) {
429 @@ -2891,7 +3060,8 @@ static void ath12k_peer_assoc_h_phymode(
430 phymode = MODE_11BE_EHT40_2G;
431 else
432 phymode = MODE_11BE_EHT20_2G;
433 - } else if (link_sta->he_cap.has_he) {
434 + } else if (link_sta->he_cap.has_he &&
435 + !ath12k_peer_assoc_h_he_masked(he_mcs_mask)) {
436 if (link_sta->bandwidth == IEEE80211_STA_RX_BW_80)
437 phymode = MODE_11AX_HE80_2G;
438 else if (link_sta->bandwidth == IEEE80211_STA_RX_BW_40)
439 @@ -2921,7 +3091,8 @@ static void ath12k_peer_assoc_h_phymode(
440 /* Check EHT first */
441 if (link_sta->eht_cap.has_eht) {
442 phymode = ath12k_mac_get_phymode_eht(ar, link_sta);
443 - } else if (link_sta->he_cap.has_he) {
444 + } else if (link_sta->he_cap.has_he &&
445 + !ath12k_peer_assoc_h_he_masked(he_mcs_mask)) {
446 phymode = ath12k_mac_get_phymode_he(ar, link_sta);
447 } else if (link_sta->vht_cap.vht_supported &&
448 !ath12k_peer_assoc_h_vht_masked(vht_mcs_mask)) {
449 @@ -4190,10 +4361,13 @@ static struct ath12k_link_vif *ath12k_ma
450
451 for (i = 0; i < ARRAY_SIZE(arvif->bitrate_mask.control); i++) {
452 arvif->bitrate_mask.control[i].legacy = 0xffffffff;
453 + arvif->bitrate_mask.control[i].gi = NL80211_TXRATE_DEFAULT_GI;
454 memset(arvif->bitrate_mask.control[i].ht_mcs, 0xff,
455 sizeof(arvif->bitrate_mask.control[i].ht_mcs));
456 memset(arvif->bitrate_mask.control[i].vht_mcs, 0xff,
457 sizeof(arvif->bitrate_mask.control[i].vht_mcs));
458 + memset(arvif->bitrate_mask.control[i].he_mcs, 0xff,
459 + sizeof(arvif->bitrate_mask.control[i].he_mcs));
460 }
461
462 /* Allocate Default Queue now and reassign during actual vdev create */
463 @@ -5083,6 +5257,20 @@ ath12k_mac_bitrate_mask_num_vht_rates(st
464 }
465
466 static int
467 +ath12k_mac_bitrate_mask_num_he_rates(struct ath12k *ar,
468 + enum nl80211_band band,
469 + const struct cfg80211_bitrate_mask *mask)
470 +{
471 + int num_rates = 0;
472 + int i;
473 +
474 + for (i = 0; i < ARRAY_SIZE(mask->control[band].he_mcs); i++)
475 + num_rates += hweight16(mask->control[band].he_mcs[i]);
476 +
477 + return num_rates;
478 +}
479 +
480 +static int
481 ath12k_mac_set_peer_vht_fixed_rate(struct ath12k_link_vif *arvif,
482 struct ath12k_link_sta *arsta,
483 const struct cfg80211_bitrate_mask *mask,
484 @@ -5128,6 +5316,60 @@ ath12k_mac_set_peer_vht_fixed_rate(struc
485 return ret;
486 }
487
488 +static int
489 +ath12k_mac_set_peer_he_fixed_rate(struct ath12k_link_vif *arvif,
490 + struct ath12k_link_sta *arsta,
491 + const struct cfg80211_bitrate_mask *mask,
492 + enum nl80211_band band)
493 +{
494 + struct ath12k *ar = arvif->ar;
495 + u8 he_rate, nss;
496 + u32 rate_code;
497 + int ret, i;
498 + struct ath12k_sta *ahsta = arsta->ahsta;
499 + struct ieee80211_sta *sta;
500 +
501 + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
502 +
503 + sta = ath12k_ahsta_to_sta(ahsta);
504 + nss = 0;
505 +
506 + for (i = 0; i < ARRAY_SIZE(mask->control[band].he_mcs); i++) {
507 + if (hweight16(mask->control[band].he_mcs[i]) == 1) {
508 + nss = i + 1;
509 + he_rate = ffs(mask->control[band].he_mcs[i]) - 1;
510 + }
511 + }
512 +
513 + if (!nss) {
514 + ath12k_warn(ar->ab, "No single HE Fixed rate found to set for %pM",
515 + arsta->addr);
516 + return -EINVAL;
517 + }
518 +
519 + /* Avoid updating invalid nss as fixed rate*/
520 + if (nss > sta->deflink.rx_nss)
521 + return -EINVAL;
522 +
523 + ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
524 + "Setting Fixed HE Rate for peer %pM. Device will not switch to any other selected rates",
525 + arsta->addr);
526 +
527 + rate_code = ATH12K_HW_RATE_CODE(he_rate, nss - 1,
528 + WMI_RATE_PREAMBLE_HE);
529 +
530 + ret = ath12k_wmi_set_peer_param(ar, arsta->addr,
531 + arvif->vdev_id,
532 + WMI_PEER_PARAM_FIXED_RATE,
533 + rate_code);
534 + if (ret)
535 + ath12k_warn(ar->ab,
536 + "failed to update STA %pM Fixed Rate %d: %d\n",
537 + arsta->addr, rate_code, ret);
538 +
539 + return ret;
540 +}
541 +
542 static int ath12k_mac_station_assoc(struct ath12k *ar,
543 struct ath12k_link_vif *arvif,
544 struct ath12k_link_sta *arsta,
545 @@ -5140,7 +5382,7 @@ static int ath12k_mac_station_assoc(stru
546 struct cfg80211_chan_def def;
547 enum nl80211_band band;
548 struct cfg80211_bitrate_mask *mask;
549 - u8 num_vht_rates;
550 + u8 num_vht_rates, num_he_rates;
551 u8 link_id = arvif->link_id;
552
553 lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
554 @@ -5180,9 +5422,10 @@ static int ath12k_mac_station_assoc(stru
555 }
556
557 num_vht_rates = ath12k_mac_bitrate_mask_num_vht_rates(ar, band, mask);
558 + num_he_rates = ath12k_mac_bitrate_mask_num_he_rates(ar, band, mask);
559
560 - /* If single VHT rate is configured (by set_bitrate_mask()),
561 - * peer_assoc will disable VHT. This is now enabled by a peer specific
562 + /* If single VHT/HE rate is configured (by set_bitrate_mask()),
563 + * peer_assoc will disable VHT/HE. This is now enabled by a peer specific
564 * fixed param.
565 * Note that all other rates and NSS will be disabled for this peer.
566 */
567 @@ -5193,8 +5436,9 @@ static int ath12k_mac_station_assoc(stru
568 }
569
570 if (link_sta->vht_cap.vht_supported && num_vht_rates == 1) {
571 - ret = ath12k_mac_set_peer_vht_fixed_rate(arvif, arsta, mask,
572 - band);
573 + ret = ath12k_mac_set_peer_vht_fixed_rate(arvif, arsta, mask, band);
574 + } else if (link_sta->he_cap.has_he && num_he_rates == 1) {
575 + ret = ath12k_mac_set_peer_he_fixed_rate(arvif, arsta, mask, band);
576 if (ret)
577 return ret;
578 }
579 @@ -5258,8 +5502,9 @@ static void ath12k_sta_rc_update_wk(stru
580 enum nl80211_band band;
581 const u8 *ht_mcs_mask;
582 const u16 *vht_mcs_mask;
583 - u32 changed, bw, nss, smps, bw_prev;
584 - int err, num_vht_rates;
585 + const u16 *he_mcs_mask;
586 + u32 changed, bw, nss, mac_nss, smps, bw_prev;
587 + int err, num_vht_rates, num_he_rates;
588 const struct cfg80211_bitrate_mask *mask;
589 enum wmi_phy_mode peer_phymode;
590 struct ath12k_link_sta *arsta;
591 @@ -5279,6 +5524,7 @@ static void ath12k_sta_rc_update_wk(stru
592 band = def.chan->band;
593 ht_mcs_mask = arvif->bitrate_mask.control[band].ht_mcs;
594 vht_mcs_mask = arvif->bitrate_mask.control[band].vht_mcs;
595 + he_mcs_mask = arvif->bitrate_mask.control[band].he_mcs;
596
597 spin_lock_bh(&ar->data_lock);
598
599 @@ -5293,8 +5539,10 @@ static void ath12k_sta_rc_update_wk(stru
600 spin_unlock_bh(&ar->data_lock);
601
602 nss = max_t(u32, 1, nss);
603 - nss = min(nss, max(ath12k_mac_max_ht_nss(ht_mcs_mask),
604 - ath12k_mac_max_vht_nss(vht_mcs_mask)));
605 + mac_nss = max3(ath12k_mac_max_ht_nss(ht_mcs_mask),
606 + ath12k_mac_max_vht_nss(vht_mcs_mask),
607 + ath12k_mac_max_he_nss(he_mcs_mask));
608 + nss = min(nss, mac_nss);
609
610 struct ath12k_wmi_peer_assoc_arg *peer_arg __free(kfree) =
611 kzalloc(sizeof(*peer_arg), GFP_KERNEL);
612 @@ -5377,6 +5625,8 @@ static void ath12k_sta_rc_update_wk(stru
613 mask = &arvif->bitrate_mask;
614 num_vht_rates = ath12k_mac_bitrate_mask_num_vht_rates(ar, band,
615 mask);
616 + num_he_rates = ath12k_mac_bitrate_mask_num_he_rates(ar, band,
617 + mask);
618
619 /* Peer_assoc_prepare will reject vht rates in
620 * bitrate_mask if its not available in range format and
621 @@ -5399,11 +5649,24 @@ static void ath12k_sta_rc_update_wk(stru
622 if (link_sta->vht_cap.vht_supported && num_vht_rates == 1) {
623 ath12k_mac_set_peer_vht_fixed_rate(arvif, arsta, mask,
624 band);
625 + } else if (link_sta->he_cap.has_he && num_he_rates == 1) {
626 + ath12k_mac_set_peer_he_fixed_rate(arvif, arsta, mask, band);
627 } else {
628 - /* If the peer is non-VHT or no fixed VHT rate
629 + /* If the peer is non-VHT/HE or no fixed VHT/HE rate
630 * is provided in the new bitrate mask we set the
631 - * other rates using peer_assoc command.
632 + * other rates using peer_assoc command. Also clear
633 + * the peer fixed rate settings as it has higher proprity
634 + * than peer assoc
635 */
636 + err = ath12k_wmi_set_peer_param(ar, arsta->addr,
637 + arvif->vdev_id,
638 + WMI_PEER_PARAM_FIXED_RATE,
639 + WMI_FIXED_RATE_NONE);
640 + if (err)
641 + ath12k_warn(ar->ab,
642 + "failed to disable peer fixed rate for STA %pM ret %d\n",
643 + arsta->addr, err);
644 +
645 ath12k_peer_assoc_prepare(ar, arvif, arsta,
646 peer_arg, true);
647
648 @@ -9903,19 +10166,40 @@ ath12k_mac_has_single_legacy_rate(struct
649 if (ath12k_mac_bitrate_mask_num_vht_rates(ar, band, mask))
650 return false;
651
652 + if (ath12k_mac_bitrate_mask_num_he_rates(ar, band, mask))
653 + return false;
654 +
655 return num_rates == 1;
656 }
657
658 +static __le16
659 +ath12k_mac_get_tx_mcs_map(const struct ieee80211_sta_he_cap *he_cap)
660 +{
661 + if (he_cap->he_cap_elem.phy_cap_info[0] &
662 + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)
663 + return he_cap->he_mcs_nss_supp.tx_mcs_80p80;
664 +
665 + if (he_cap->he_cap_elem.phy_cap_info[0] &
666 + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G)
667 + return he_cap->he_mcs_nss_supp.tx_mcs_160;
668 +
669 + return he_cap->he_mcs_nss_supp.tx_mcs_80;
670 +}
671 +
672 static bool
673 ath12k_mac_bitrate_mask_get_single_nss(struct ath12k *ar,
674 + struct ieee80211_vif *vif,
675 enum nl80211_band band,
676 const struct cfg80211_bitrate_mask *mask,
677 int *nss)
678 {
679 struct ieee80211_supported_band *sband = &ar->mac.sbands[band];
680 u16 vht_mcs_map = le16_to_cpu(sband->vht_cap.vht_mcs.tx_mcs_map);
681 + const struct ieee80211_sta_he_cap *he_cap;
682 + u16 he_mcs_map = 0;
683 u8 ht_nss_mask = 0;
684 u8 vht_nss_mask = 0;
685 + u8 he_nss_mask = 0;
686 int i;
687
688 /* No need to consider legacy here. Basic rates are always present
689 @@ -9942,7 +10226,24 @@ ath12k_mac_bitrate_mask_get_single_nss(s
690 return false;
691 }
692
693 - if (ht_nss_mask != vht_nss_mask)
694 + he_cap = ieee80211_get_he_iftype_cap_vif(sband, vif);
695 + if (!he_cap)
696 + return false;
697 +
698 + he_mcs_map = le16_to_cpu(ath12k_mac_get_tx_mcs_map(he_cap));
699 +
700 + for (i = 0; i < ARRAY_SIZE(mask->control[band].he_mcs); i++) {
701 + if (mask->control[band].he_mcs[i] == 0)
702 + continue;
703 +
704 + if (mask->control[band].he_mcs[i] ==
705 + ath12k_mac_get_max_he_mcs_map(he_mcs_map, i))
706 + he_nss_mask |= BIT(i);
707 + else
708 + return false;
709 + }
710 +
711 + if (ht_nss_mask != vht_nss_mask || ht_nss_mask != he_nss_mask)
712 return false;
713
714 if (ht_nss_mask == 0)
715 @@ -9989,54 +10290,182 @@ ath12k_mac_get_single_legacy_rate(struct
716 return 0;
717 }
718
719 -static int ath12k_mac_set_fixed_rate_params(struct ath12k_link_vif *arvif,
720 - u32 rate, u8 nss, u8 sgi, u8 ldpc)
721 +static int
722 +ath12k_mac_set_fixed_rate_gi_ltf(struct ath12k_link_vif *arvif, u8 he_gi, u8 he_ltf)
723 {
724 struct ath12k *ar = arvif->ar;
725 - u32 vdev_param;
726 int ret;
727
728 lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
729
730 - ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac set fixed rate params vdev %i rate 0x%02x nss %u sgi %u\n",
731 - arvif->vdev_id, rate, nss, sgi);
732 + /* 0.8 = 0, 1.6 = 2 and 3.2 = 3. */
733 + if (he_gi && he_gi != 0xFF)
734 + he_gi += 1;
735
736 - vdev_param = WMI_VDEV_PARAM_FIXED_RATE;
737 ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
738 - vdev_param, rate);
739 + WMI_VDEV_PARAM_SGI, he_gi);
740 if (ret) {
741 - ath12k_warn(ar->ab, "failed to set fixed rate param 0x%02x: %d\n",
742 - rate, ret);
743 + ath12k_warn(ar->ab, "failed to set HE GI:%d, error:%d\n",
744 + he_gi, ret);
745 return ret;
746 }
747 + /* start from 1 */
748 + if (he_ltf != 0xFF)
749 + he_ltf += 1;
750
751 - vdev_param = WMI_VDEV_PARAM_NSS;
752 ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
753 - vdev_param, nss);
754 + WMI_VDEV_PARAM_HE_LTF, he_ltf);
755 if (ret) {
756 - ath12k_warn(ar->ab, "failed to set nss param %d: %d\n",
757 - nss, ret);
758 + ath12k_warn(ar->ab, "failed to set HE LTF:%d, error:%d\n",
759 + he_ltf, ret);
760 return ret;
761 }
762 + return 0;
763 +}
764 +
765 +static int
766 +ath12k_mac_set_auto_rate_gi_ltf(struct ath12k_link_vif *arvif, u16 he_gi, u8 he_ltf)
767 +{
768 + struct ath12k *ar = arvif->ar;
769 + int ret;
770 + u32 he_ar_gi_ltf;
771 +
772 + if (he_gi != 0xFF) {
773 + switch (he_gi) {
774 + case NL80211_RATE_INFO_HE_GI_0_8:
775 + he_gi = WMI_AUTORATE_800NS_GI;
776 + break;
777 + case NL80211_RATE_INFO_HE_GI_1_6:
778 + he_gi = WMI_AUTORATE_1600NS_GI;
779 + break;
780 + case NL80211_RATE_INFO_HE_GI_3_2:
781 + he_gi = WMI_AUTORATE_3200NS_GI;
782 + break;
783 + default:
784 + ath12k_warn(ar->ab, "Invalid GI\n");
785 + return -EINVAL;
786 + }
787 + }
788 +
789 + if (he_ltf != 0xFF) {
790 + switch (he_ltf) {
791 + case NL80211_RATE_INFO_HE_1XLTF:
792 + he_ltf = WMI_HE_AUTORATE_LTF_1X;
793 + break;
794 + case NL80211_RATE_INFO_HE_2XLTF:
795 + he_ltf = WMI_HE_AUTORATE_LTF_2X;
796 + break;
797 + case NL80211_RATE_INFO_HE_4XLTF:
798 + he_ltf = WMI_HE_AUTORATE_LTF_4X;
799 + break;
800 + default:
801 + ath12k_warn(ar->ab, "Invalid LTF\n");
802 + return -EINVAL;
803 + }
804 + }
805 +
806 + he_ar_gi_ltf = he_gi | he_ltf;
807
808 - vdev_param = WMI_VDEV_PARAM_SGI;
809 ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
810 - vdev_param, sgi);
811 + WMI_VDEV_PARAM_AUTORATE_MISC_CFG,
812 + he_ar_gi_ltf);
813 if (ret) {
814 - ath12k_warn(ar->ab, "failed to set sgi param %d: %d\n",
815 - sgi, ret);
816 + ath12k_warn(ar->ab,
817 + "failed to set HE autorate GI:%u, LTF:%u params, error:%d\n",
818 + he_gi, he_ltf, ret);
819 return ret;
820 }
821
822 - vdev_param = WMI_VDEV_PARAM_LDPC;
823 + return 0;
824 +}
825 +
826 +static u32 ath12k_mac_nlgi_to_wmigi(enum nl80211_txrate_gi gi)
827 +{
828 + switch (gi) {
829 + case NL80211_TXRATE_DEFAULT_GI:
830 + return WMI_GI_400_NS;
831 + case NL80211_TXRATE_FORCE_LGI:
832 + return WMI_GI_800_NS;
833 + default:
834 + return WMI_GI_400_NS;
835 + }
836 +}
837 +
838 +static int ath12k_mac_set_rate_params(struct ath12k_link_vif *arvif,
839 + u32 rate, u8 nss, u8 sgi, u8 ldpc,
840 + u8 he_gi, u8 he_ltf, bool he_fixed_rate)
841 +{
842 + struct ieee80211_bss_conf *link_conf;
843 + struct ath12k *ar = arvif->ar;
844 + u32 vdev_param;
845 + u32 param_value;
846 + int ret;
847 + bool he_support;
848 +
849 + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
850 +
851 + link_conf = ath12k_mac_get_link_bss_conf(arvif);
852 + if (!link_conf)
853 + return -EINVAL;
854 +
855 + he_support = link_conf->he_support;
856 +
857 + ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
858 + "mac set rate params vdev %i rate 0x%02x nss 0x%02x sgi 0x%02x ldpc 0x%02x\n",
859 + arvif->vdev_id, rate, nss, sgi, ldpc);
860 +
861 + ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
862 + "he_gi 0x%02x he_ltf 0x%02x he_fixed_rate %d\n", he_gi,
863 + he_ltf, he_fixed_rate);
864 +
865 + if (!he_support) {
866 + vdev_param = WMI_VDEV_PARAM_FIXED_RATE;
867 + ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
868 + vdev_param, rate);
869 + if (ret) {
870 + ath12k_warn(ar->ab, "failed to set fixed rate param 0x%02x: %d\n",
871 + rate, ret);
872 + return ret;
873 + }
874 + }
875 +
876 + vdev_param = WMI_VDEV_PARAM_NSS;
877 +
878 ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
879 - vdev_param, ldpc);
880 + vdev_param, nss);
881 + if (ret) {
882 + ath12k_warn(ar->ab, "failed to set nss param %d: %d\n",
883 + nss, ret);
884 + return ret;
885 + }
886 +
887 + ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
888 + WMI_VDEV_PARAM_LDPC, ldpc);
889 if (ret) {
890 ath12k_warn(ar->ab, "failed to set ldpc param %d: %d\n",
891 ldpc, ret);
892 return ret;
893 }
894
895 + if (he_support) {
896 + if (he_fixed_rate)
897 + ret = ath12k_mac_set_fixed_rate_gi_ltf(arvif, he_gi, he_ltf);
898 + else
899 + ret = ath12k_mac_set_auto_rate_gi_ltf(arvif, he_gi, he_ltf);
900 + if (ret)
901 + return ret;
902 + } else {
903 + vdev_param = WMI_VDEV_PARAM_SGI;
904 + param_value = ath12k_mac_nlgi_to_wmigi(sgi);
905 + ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
906 + vdev_param, param_value);
907 + if (ret) {
908 + ath12k_warn(ar->ab, "failed to set sgi param %d: %d\n",
909 + sgi, ret);
910 + return ret;
911 + }
912 + }
913 +
914 return 0;
915 }
916
917 @@ -10065,6 +10494,31 @@ ath12k_mac_vht_mcs_range_present(struct
918 return true;
919 }
920
921 +static bool
922 +ath12k_mac_he_mcs_range_present(struct ath12k *ar,
923 + enum nl80211_band band,
924 + const struct cfg80211_bitrate_mask *mask)
925 +{
926 + int i;
927 + u16 he_mcs;
928 +
929 + for (i = 0; i < NL80211_HE_NSS_MAX; i++) {
930 + he_mcs = mask->control[band].he_mcs[i];
931 +
932 + switch (he_mcs) {
933 + case 0:
934 + case BIT(8) - 1:
935 + case BIT(10) - 1:
936 + case BIT(12) - 1:
937 + break;
938 + default:
939 + return false;
940 + }
941 + }
942 +
943 + return true;
944 +}
945 +
946 static void ath12k_mac_set_bitrate_mask_iter(void *data,
947 struct ieee80211_sta *sta)
948 {
949 @@ -10073,7 +10527,10 @@ static void ath12k_mac_set_bitrate_mask_
950 struct ath12k_link_sta *arsta;
951 struct ath12k *ar = arvif->ar;
952
953 - arsta = rcu_dereference(ahsta->link[arvif->link_id]);
954 + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
955 +
956 + arsta = wiphy_dereference(ath12k_ar_to_hw(ar)->wiphy,
957 + ahsta->link[arvif->link_id]);
958 if (!arsta || arsta->arvif != arvif)
959 return;
960
961 @@ -10111,6 +10568,61 @@ static void ath12k_mac_disable_peer_fixe
962 arsta->addr, ret);
963 }
964
965 +static bool
966 +ath12k_mac_validate_fixed_rate_settings(struct ath12k *ar, enum nl80211_band band,
967 + const struct cfg80211_bitrate_mask *mask,
968 + unsigned int link_id)
969 +{
970 + bool he_fixed_rate = false, vht_fixed_rate = false;
971 + const u16 *vht_mcs_mask, *he_mcs_mask;
972 + struct ieee80211_link_sta *link_sta;
973 + struct ath12k_peer *peer, *tmp;
974 + u8 vht_nss, he_nss;
975 + int ret = true;
976 +
977 + vht_mcs_mask = mask->control[band].vht_mcs;
978 + he_mcs_mask = mask->control[band].he_mcs;
979 +
980 + if (ath12k_mac_bitrate_mask_num_vht_rates(ar, band, mask) == 1)
981 + vht_fixed_rate = true;
982 +
983 + if (ath12k_mac_bitrate_mask_num_he_rates(ar, band, mask) == 1)
984 + he_fixed_rate = true;
985 +
986 + if (!vht_fixed_rate && !he_fixed_rate)
987 + return true;
988 +
989 + vht_nss = ath12k_mac_max_vht_nss(vht_mcs_mask);
990 + he_nss = ath12k_mac_max_he_nss(he_mcs_mask);
991 +
992 + rcu_read_lock();
993 + spin_lock_bh(&ar->ab->base_lock);
994 + list_for_each_entry_safe(peer, tmp, &ar->ab->peers, list) {
995 + if (peer->sta) {
996 + link_sta = rcu_dereference(peer->sta->link[link_id]);
997 + if (!link_sta) {
998 + ret = false;
999 + goto exit;
1000 + }
1001 +
1002 + if (vht_fixed_rate && (!link_sta->vht_cap.vht_supported ||
1003 + link_sta->rx_nss < vht_nss)) {
1004 + ret = false;
1005 + goto exit;
1006 + }
1007 + if (he_fixed_rate && (!link_sta->he_cap.has_he ||
1008 + link_sta->rx_nss < he_nss)) {
1009 + ret = false;
1010 + goto exit;
1011 + }
1012 + }
1013 + }
1014 +exit:
1015 + spin_unlock_bh(&ar->ab->base_lock);
1016 + rcu_read_unlock();
1017 + return ret;
1018 +}
1019 +
1020 static int
1021 ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw,
1022 struct ieee80211_vif *vif,
1023 @@ -10123,13 +10635,17 @@ ath12k_mac_op_set_bitrate_mask(struct ie
1024 enum nl80211_band band;
1025 const u8 *ht_mcs_mask;
1026 const u16 *vht_mcs_mask;
1027 + const u16 *he_mcs_mask;
1028 + u8 he_ltf = 0;
1029 + u8 he_gi = 0;
1030 u32 rate;
1031 - u8 nss;
1032 + u8 nss, mac_nss;
1033 u8 sgi;
1034 u8 ldpc;
1035 int single_nss;
1036 int ret;
1037 int num_rates;
1038 + bool he_fixed_rate = false;
1039
1040 lockdep_assert_wiphy(hw->wiphy);
1041
1042 @@ -10144,14 +10660,18 @@ ath12k_mac_op_set_bitrate_mask(struct ie
1043 band = def.chan->band;
1044 ht_mcs_mask = mask->control[band].ht_mcs;
1045 vht_mcs_mask = mask->control[band].vht_mcs;
1046 + he_mcs_mask = mask->control[band].he_mcs;
1047 ldpc = !!(ar->ht_cap_info & WMI_HT_CAP_LDPC);
1048
1049 sgi = mask->control[band].gi;
1050 - if (sgi == NL80211_TXRATE_FORCE_LGI) {
1051 + if (sgi == NL80211_TXRATE_FORCE_SGI) {
1052 ret = -EINVAL;
1053 goto out;
1054 }
1055
1056 + he_gi = mask->control[band].he_gi;
1057 + he_ltf = mask->control[band].he_ltf;
1058 +
1059 /* mac80211 doesn't support sending a fixed HT/VHT MCS alone, rather it
1060 * requires passing at least one of used basic rates along with them.
1061 * Fixed rate setting across different preambles(legacy, HT, VHT) is
1062 @@ -10168,18 +10688,31 @@ ath12k_mac_op_set_bitrate_mask(struct ie
1063 arvif->vdev_id, ret);
1064 goto out;
1065 }
1066 +
1067 ieee80211_iterate_stations_mtx(hw,
1068 ath12k_mac_disable_peer_fixed_rate,
1069 arvif);
1070 - } else if (ath12k_mac_bitrate_mask_get_single_nss(ar, band, mask,
1071 + } else if (ath12k_mac_bitrate_mask_get_single_nss(ar, vif, band, mask,
1072 &single_nss)) {
1073 rate = WMI_FIXED_RATE_NONE;
1074 nss = single_nss;
1075 + arvif->bitrate_mask = *mask;
1076 +
1077 + ieee80211_iterate_stations_atomic(hw,
1078 + ath12k_mac_set_bitrate_mask_iter,
1079 + arvif);
1080 } else {
1081 rate = WMI_FIXED_RATE_NONE;
1082 - nss = min_t(u32, ar->num_tx_chains,
1083 - max(ath12k_mac_max_ht_nss(ht_mcs_mask),
1084 - ath12k_mac_max_vht_nss(vht_mcs_mask)));
1085 +
1086 + if (!ath12k_mac_validate_fixed_rate_settings(ar, band,
1087 + mask, arvif->link_id))
1088 + ath12k_warn(ar->ab,
1089 + "failed to update fixed rate settings due to mcs/nss incompatibility\n");
1090 +
1091 + mac_nss = max3(ath12k_mac_max_ht_nss(ht_mcs_mask),
1092 + ath12k_mac_max_vht_nss(vht_mcs_mask),
1093 + ath12k_mac_max_he_nss(he_mcs_mask));
1094 + nss = min_t(u32, ar->num_tx_chains, mac_nss);
1095
1096 /* If multiple rates across different preambles are given
1097 * we can reconfigure this info with all peers using PEER_ASSOC
1098 @@ -10211,9 +10744,21 @@ ath12k_mac_op_set_bitrate_mask(struct ie
1099 */
1100 ath12k_warn(ar->ab,
1101 "Setting more than one MCS Value in bitrate mask not supported\n");
1102 - return -EINVAL;
1103 + ret = -EINVAL;
1104 + goto out;
1105 }
1106
1107 + num_rates = ath12k_mac_bitrate_mask_num_he_rates(ar, band, mask);
1108 + if (num_rates == 1)
1109 + he_fixed_rate = true;
1110 +
1111 + if (!ath12k_mac_he_mcs_range_present(ar, band, mask) &&
1112 + num_rates > 1) {
1113 + ath12k_warn(ar->ab,
1114 + "Setting more than one HE MCS Value in bitrate mask not supported\n");
1115 + ret = -EINVAL;
1116 + goto out;
1117 + }
1118 ieee80211_iterate_stations_mtx(hw,
1119 ath12k_mac_disable_peer_fixed_rate,
1120 arvif);
1121 @@ -10224,9 +10769,10 @@ ath12k_mac_op_set_bitrate_mask(struct ie
1122 arvif);
1123 }
1124
1125 - ret = ath12k_mac_set_fixed_rate_params(arvif, rate, nss, sgi, ldpc);
1126 + ret = ath12k_mac_set_rate_params(arvif, rate, nss, sgi, ldpc, he_gi,
1127 + he_ltf, he_fixed_rate);
1128 if (ret) {
1129 - ath12k_warn(ar->ab, "failed to set fixed rate params on vdev %i: %d\n",
1130 + ath12k_warn(ar->ab, "failed to set rate params on vdev %i: %d\n",
1131 arvif->vdev_id, ret);
1132 }
1133
1134 --- a/drivers/net/wireless/ath/ath12k/wmi.h
1135 +++ b/drivers/net/wireless/ath/ath12k/wmi.h
1136 @@ -220,6 +220,22 @@ enum WMI_HOST_WLAN_BAND {
1137 WMI_HOST_WLAN_2G_5G_CAP = 3,
1138 };
1139
1140 +/* Parameters used for WMI_VDEV_PARAM_AUTORATE_MISC_CFG command.
1141 + * Used only for HE auto rate mode.
1142 + */
1143 +enum {
1144 + /* HE LTF related configuration */
1145 + WMI_HE_AUTORATE_LTF_1X = BIT(0),
1146 + WMI_HE_AUTORATE_LTF_2X = BIT(1),
1147 + WMI_HE_AUTORATE_LTF_4X = BIT(2),
1148 +
1149 + /* HE GI related configuration */
1150 + WMI_AUTORATE_400NS_GI = BIT(8),
1151 + WMI_AUTORATE_800NS_GI = BIT(9),
1152 + WMI_AUTORATE_1600NS_GI = BIT(10),
1153 + WMI_AUTORATE_3200NS_GI = BIT(11),
1154 +};
1155 +
1156 enum wmi_cmd_group {
1157 /* 0 to 2 are reserved */
1158 WMI_GRP_START = 0x3,
1159 @@ -1145,7 +1161,9 @@ enum wmi_tlv_vdev_param {
1160 WMI_VDEV_PARAM_HE_RANGE_EXT,
1161 WMI_VDEV_PARAM_ENABLE_BCAST_PROBE_RESPONSE,
1162 WMI_VDEV_PARAM_FILS_MAX_CHANNEL_GUARD_TIME,
1163 + WMI_VDEV_PARAM_HE_LTF = 0x74,
1164 WMI_VDEV_PARAM_BA_MODE = 0x7e,
1165 + WMI_VDEV_PARAM_AUTORATE_MISC_CFG = 0x80,
1166 WMI_VDEV_PARAM_SET_HE_SOUNDING_MODE = 0x87,
1167 WMI_VDEV_PARAM_6GHZ_PARAMS = 0x99,
1168 WMI_VDEV_PARAM_PROTOTYPE = 0x8000,
1169 @@ -3579,6 +3597,15 @@ struct wmi_force_fw_hang_cmd {
1170 __le32 delay_time_ms;
1171 } __packed;
1172
1173 +/* Param values to be sent for WMI_VDEV_PARAM_SGI param_id
1174 + * which are used in 11n, 11ac systems
1175 + * @WMI_GI_800_NS - Always uses 0.8us (Long GI)
1176 + * @WMI_GI_400_NS - Firmware switches between 0.4us (Short GI)
1177 + * and 0.8us (Long GI) based on packet error rate.
1178 + */
1179 +#define WMI_GI_800_NS 0
1180 +#define WMI_GI_400_NS 1
1181 +
1182 struct wmi_vdev_set_param_cmd {
1183 __le32 tlv_header;
1184 __le32 vdev_id;