1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
3 * Copyright (C) 2017 Intel Deutschland GmbH
4 * Copyright (C) 2018-2024 Intel Corporation
9 #include "iwl-op-mode.h"
12 static u8
rs_fw_bw_from_sta_bw(const struct ieee80211_link_sta
*link_sta
)
14 switch (link_sta
->bandwidth
) {
15 case IEEE80211_STA_RX_BW_320
:
16 return IWL_TLC_MNG_CH_WIDTH_320MHZ
;
17 case IEEE80211_STA_RX_BW_160
:
18 return IWL_TLC_MNG_CH_WIDTH_160MHZ
;
19 case IEEE80211_STA_RX_BW_80
:
20 return IWL_TLC_MNG_CH_WIDTH_80MHZ
;
21 case IEEE80211_STA_RX_BW_40
:
22 return IWL_TLC_MNG_CH_WIDTH_40MHZ
;
23 case IEEE80211_STA_RX_BW_20
:
25 return IWL_TLC_MNG_CH_WIDTH_20MHZ
;
29 static u8
rs_fw_set_active_chains(u8 chains
)
34 fw_chains
|= IWL_TLC_MNG_CHAIN_A_MSK
;
36 fw_chains
|= IWL_TLC_MNG_CHAIN_B_MSK
;
41 static u8
rs_fw_sgi_cw_support(struct ieee80211_link_sta
*link_sta
)
43 struct ieee80211_sta_ht_cap
*ht_cap
= &link_sta
->ht_cap
;
44 struct ieee80211_sta_vht_cap
*vht_cap
= &link_sta
->vht_cap
;
45 struct ieee80211_sta_he_cap
*he_cap
= &link_sta
->he_cap
;
51 if (ht_cap
->cap
& IEEE80211_HT_CAP_SGI_20
)
52 supp
|= BIT(IWL_TLC_MNG_CH_WIDTH_20MHZ
);
53 if (ht_cap
->cap
& IEEE80211_HT_CAP_SGI_40
)
54 supp
|= BIT(IWL_TLC_MNG_CH_WIDTH_40MHZ
);
55 if (vht_cap
->cap
& IEEE80211_VHT_CAP_SHORT_GI_80
)
56 supp
|= BIT(IWL_TLC_MNG_CH_WIDTH_80MHZ
);
57 if (vht_cap
->cap
& IEEE80211_VHT_CAP_SHORT_GI_160
)
58 supp
|= BIT(IWL_TLC_MNG_CH_WIDTH_160MHZ
);
63 static u16
rs_fw_get_config_flags(struct iwl_mvm
*mvm
,
64 struct ieee80211_vif
*vif
,
65 struct ieee80211_link_sta
*link_sta
,
66 const struct ieee80211_sta_he_cap
*sband_he_cap
)
68 struct ieee80211_sta_ht_cap
*ht_cap
= &link_sta
->ht_cap
;
69 struct ieee80211_sta_vht_cap
*vht_cap
= &link_sta
->vht_cap
;
70 struct ieee80211_sta_he_cap
*he_cap
= &link_sta
->he_cap
;
71 bool vht_ena
= vht_cap
->vht_supported
;
75 if (mvm
->cfg
->ht_params
->stbc
&&
76 (num_of_ant(iwl_mvm_get_valid_tx_ant(mvm
)) > 1)) {
77 if (he_cap
->has_he
&& he_cap
->he_cap_elem
.phy_cap_info
[2] &
78 IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ
)
79 flags
|= IWL_TLC_MNG_CFG_FLAGS_STBC_MSK
;
80 else if (vht_cap
->cap
& IEEE80211_VHT_CAP_RXSTBC_MASK
)
81 flags
|= IWL_TLC_MNG_CFG_FLAGS_STBC_MSK
;
82 else if (ht_cap
->cap
& IEEE80211_HT_CAP_RX_STBC
)
83 flags
|= IWL_TLC_MNG_CFG_FLAGS_STBC_MSK
;
86 if (mvm
->cfg
->ht_params
->ldpc
&&
87 ((ht_cap
->cap
& IEEE80211_HT_CAP_LDPC_CODING
) ||
88 (vht_ena
&& (vht_cap
->cap
& IEEE80211_VHT_CAP_RXLDPC
))))
89 flags
|= IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK
;
91 /* consider LDPC support in case of HE */
92 if (he_cap
->has_he
&& (he_cap
->he_cap_elem
.phy_cap_info
[1] &
93 IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD
))
94 flags
|= IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK
;
97 !(sband_he_cap
->he_cap_elem
.phy_cap_info
[1] &
98 IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD
))
99 flags
&= ~IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK
;
101 if (he_cap
->has_he
&&
102 (he_cap
->he_cap_elem
.phy_cap_info
[3] &
103 IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_MASK
&&
105 sband_he_cap
->he_cap_elem
.phy_cap_info
[3] &
106 IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_MASK
))
107 flags
|= IWL_TLC_MNG_CFG_FLAGS_HE_DCM_NSS_1_MSK
;
113 int rs_fw_vht_highest_rx_mcs_index(const struct ieee80211_sta_vht_cap
*vht_cap
,
116 u16 rx_mcs
= le16_to_cpu(vht_cap
->vht_mcs
.rx_mcs_map
) &
117 (0x3 << (2 * (nss
- 1)));
118 rx_mcs
>>= (2 * (nss
- 1));
121 case IEEE80211_VHT_MCS_SUPPORT_0_7
:
122 return IWL_TLC_MNG_HT_RATE_MCS7
;
123 case IEEE80211_VHT_MCS_SUPPORT_0_8
:
124 return IWL_TLC_MNG_HT_RATE_MCS8
;
125 case IEEE80211_VHT_MCS_SUPPORT_0_9
:
126 return IWL_TLC_MNG_HT_RATE_MCS9
;
136 rs_fw_vht_set_enabled_rates(const struct ieee80211_link_sta
*link_sta
,
137 const struct ieee80211_sta_vht_cap
*vht_cap
,
138 struct iwl_tlc_config_cmd_v4
*cmd
)
142 u8 max_nss
= link_sta
->rx_nss
;
143 struct ieee80211_vht_cap ieee_vht_cap
= {
144 .vht_cap_info
= cpu_to_le32(vht_cap
->cap
),
145 .supp_mcs
= vht_cap
->vht_mcs
,
148 /* the station support only a single receive chain */
149 if (link_sta
->smps_mode
== IEEE80211_SMPS_STATIC
)
152 for (i
= 0; i
< max_nss
&& i
< IWL_TLC_NSS_MAX
; i
++) {
155 highest_mcs
= rs_fw_vht_highest_rx_mcs_index(vht_cap
, nss
);
159 supp
= BIT(highest_mcs
+ 1) - 1;
160 if (link_sta
->bandwidth
== IEEE80211_STA_RX_BW_20
)
161 supp
&= ~BIT(IWL_TLC_MNG_HT_RATE_MCS9
);
163 cmd
->ht_rates
[i
][IWL_TLC_MCS_PER_BW_80
] = cpu_to_le16(supp
);
165 * Check if VHT extended NSS indicates that the bandwidth/NSS
166 * configuration is supported - only for MCS 0 since we already
167 * decoded the MCS bits anyway ourselves.
169 if (link_sta
->bandwidth
== IEEE80211_STA_RX_BW_160
&&
170 ieee80211_get_vht_max_nss(&ieee_vht_cap
,
171 IEEE80211_VHT_CHANWIDTH_160MHZ
,
172 0, true, nss
) >= nss
)
173 cmd
->ht_rates
[i
][IWL_TLC_MCS_PER_BW_160
] =
174 cmd
->ht_rates
[i
][IWL_TLC_MCS_PER_BW_80
];
178 static u16
rs_fw_he_ieee80211_mcs_to_rs_mcs(u16 mcs
)
181 case IEEE80211_HE_MCS_SUPPORT_0_7
:
182 return BIT(IWL_TLC_MNG_HT_RATE_MCS7
+ 1) - 1;
183 case IEEE80211_HE_MCS_SUPPORT_0_9
:
184 return BIT(IWL_TLC_MNG_HT_RATE_MCS9
+ 1) - 1;
185 case IEEE80211_HE_MCS_SUPPORT_0_11
:
186 return BIT(IWL_TLC_MNG_HT_RATE_MCS11
+ 1) - 1;
187 case IEEE80211_HE_MCS_NOT_SUPPORTED
:
191 WARN(1, "invalid HE MCS %d\n", mcs
);
196 rs_fw_he_set_enabled_rates(const struct ieee80211_link_sta
*link_sta
,
197 const struct ieee80211_sta_he_cap
*sband_he_cap
,
198 struct iwl_tlc_config_cmd_v4
*cmd
)
200 const struct ieee80211_sta_he_cap
*he_cap
= &link_sta
->he_cap
;
201 u16 mcs_160
= le16_to_cpu(he_cap
->he_mcs_nss_supp
.rx_mcs_160
);
202 u16 mcs_80
= le16_to_cpu(he_cap
->he_mcs_nss_supp
.rx_mcs_80
);
203 u16 tx_mcs_80
= le16_to_cpu(sband_he_cap
->he_mcs_nss_supp
.tx_mcs_80
);
204 u16 tx_mcs_160
= le16_to_cpu(sband_he_cap
->he_mcs_nss_supp
.tx_mcs_160
);
206 u8 nss
= link_sta
->rx_nss
;
208 /* the station support only a single receive chain */
209 if (link_sta
->smps_mode
== IEEE80211_SMPS_STATIC
)
212 for (i
= 0; i
< nss
&& i
< IWL_TLC_NSS_MAX
; i
++) {
213 u16 _mcs_160
= (mcs_160
>> (2 * i
)) & 0x3;
214 u16 _mcs_80
= (mcs_80
>> (2 * i
)) & 0x3;
215 u16 _tx_mcs_160
= (tx_mcs_160
>> (2 * i
)) & 0x3;
216 u16 _tx_mcs_80
= (tx_mcs_80
>> (2 * i
)) & 0x3;
218 /* If one side doesn't support - mark both as not supporting */
219 if (_mcs_80
== IEEE80211_HE_MCS_NOT_SUPPORTED
||
220 _tx_mcs_80
== IEEE80211_HE_MCS_NOT_SUPPORTED
) {
221 _mcs_80
= IEEE80211_HE_MCS_NOT_SUPPORTED
;
222 _tx_mcs_80
= IEEE80211_HE_MCS_NOT_SUPPORTED
;
224 if (_mcs_80
> _tx_mcs_80
)
225 _mcs_80
= _tx_mcs_80
;
226 cmd
->ht_rates
[i
][IWL_TLC_MCS_PER_BW_80
] =
227 cpu_to_le16(rs_fw_he_ieee80211_mcs_to_rs_mcs(_mcs_80
));
229 /* If one side doesn't support - mark both as not supporting */
230 if (_mcs_160
== IEEE80211_HE_MCS_NOT_SUPPORTED
||
231 _tx_mcs_160
== IEEE80211_HE_MCS_NOT_SUPPORTED
) {
232 _mcs_160
= IEEE80211_HE_MCS_NOT_SUPPORTED
;
233 _tx_mcs_160
= IEEE80211_HE_MCS_NOT_SUPPORTED
;
235 if (_mcs_160
> _tx_mcs_160
)
236 _mcs_160
= _tx_mcs_160
;
237 cmd
->ht_rates
[i
][IWL_TLC_MCS_PER_BW_160
] =
238 cpu_to_le16(rs_fw_he_ieee80211_mcs_to_rs_mcs(_mcs_160
));
242 static u8
rs_fw_eht_max_nss(u8 rx_nss
, u8 tx_nss
)
244 u8 tx
= u8_get_bits(tx_nss
, IEEE80211_EHT_MCS_NSS_TX
);
245 u8 rx
= u8_get_bits(rx_nss
, IEEE80211_EHT_MCS_NSS_RX
);
246 /* the max nss that can be used,
247 * is the min with our tx capa and the peer rx capa.
252 #define MAX_NSS_MCS(mcs_num, rx, tx) \
253 rs_fw_eht_max_nss((rx)->rx_tx_mcs ##mcs_num## _max_nss, \
254 (tx)->rx_tx_mcs ##mcs_num## _max_nss)
256 static void rs_fw_set_eht_mcs_nss(__le16 ht_rates
[][3],
257 enum IWL_TLC_MCS_PER_BW bw
,
258 u8 max_nss
, u16 mcs_msk
)
261 ht_rates
[IWL_TLC_NSS_2
][bw
] |= cpu_to_le16(mcs_msk
);
264 ht_rates
[IWL_TLC_NSS_1
][bw
] |= cpu_to_le16(mcs_msk
);
268 struct ieee80211_eht_mcs_nss_supp_bw
*
269 rs_fw_rs_mcs2eht_mcs(enum IWL_TLC_MCS_PER_BW bw
,
270 const struct ieee80211_eht_mcs_nss_supp
*eht_mcs
)
273 case IWL_TLC_MCS_PER_BW_80
:
274 return &eht_mcs
->bw
._80
;
275 case IWL_TLC_MCS_PER_BW_160
:
276 return &eht_mcs
->bw
._160
;
277 case IWL_TLC_MCS_PER_BW_320
:
278 return &eht_mcs
->bw
._320
;
285 rs_fw_eht_set_enabled_rates(struct ieee80211_vif
*vif
,
286 const struct ieee80211_link_sta
*link_sta
,
287 const struct ieee80211_sta_he_cap
*sband_he_cap
,
288 const struct ieee80211_sta_eht_cap
*sband_eht_cap
,
289 struct iwl_tlc_config_cmd_v4
*cmd
)
291 /* peer RX mcs capa */
292 const struct ieee80211_eht_mcs_nss_supp
*eht_rx_mcs
=
293 &link_sta
->eht_cap
.eht_mcs_nss_supp
;
294 /* our TX mcs capa */
295 const struct ieee80211_eht_mcs_nss_supp
*eht_tx_mcs
=
296 &sband_eht_cap
->eht_mcs_nss_supp
;
298 enum IWL_TLC_MCS_PER_BW bw
;
299 struct ieee80211_eht_mcs_nss_supp_20mhz_only mcs_rx_20
;
300 struct ieee80211_eht_mcs_nss_supp_20mhz_only mcs_tx_20
;
302 /* peer is 20Mhz only */
303 if (vif
->type
== NL80211_IFTYPE_AP
&&
304 !(link_sta
->he_cap
.he_cap_elem
.phy_cap_info
[0] &
305 IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_MASK_ALL
)) {
306 mcs_rx_20
= eht_rx_mcs
->only_20mhz
;
308 mcs_rx_20
.rx_tx_mcs7_max_nss
= eht_rx_mcs
->bw
._80
.rx_tx_mcs9_max_nss
;
309 mcs_rx_20
.rx_tx_mcs9_max_nss
= eht_rx_mcs
->bw
._80
.rx_tx_mcs9_max_nss
;
310 mcs_rx_20
.rx_tx_mcs11_max_nss
= eht_rx_mcs
->bw
._80
.rx_tx_mcs11_max_nss
;
311 mcs_rx_20
.rx_tx_mcs13_max_nss
= eht_rx_mcs
->bw
._80
.rx_tx_mcs13_max_nss
;
314 /* nic is 20Mhz only */
315 if (!(sband_he_cap
->he_cap_elem
.phy_cap_info
[0] &
316 IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_MASK_ALL
)) {
317 mcs_tx_20
= eht_tx_mcs
->only_20mhz
;
319 mcs_tx_20
.rx_tx_mcs7_max_nss
= eht_tx_mcs
->bw
._80
.rx_tx_mcs9_max_nss
;
320 mcs_tx_20
.rx_tx_mcs9_max_nss
= eht_tx_mcs
->bw
._80
.rx_tx_mcs9_max_nss
;
321 mcs_tx_20
.rx_tx_mcs11_max_nss
= eht_tx_mcs
->bw
._80
.rx_tx_mcs11_max_nss
;
322 mcs_tx_20
.rx_tx_mcs13_max_nss
= eht_tx_mcs
->bw
._80
.rx_tx_mcs13_max_nss
;
325 /* rates for 20/40/80 bw */
326 bw
= IWL_TLC_MCS_PER_BW_80
;
327 rs_fw_set_eht_mcs_nss(cmd
->ht_rates
, bw
,
328 MAX_NSS_MCS(7, &mcs_rx_20
, &mcs_tx_20
), GENMASK(7, 0));
329 rs_fw_set_eht_mcs_nss(cmd
->ht_rates
, bw
,
330 MAX_NSS_MCS(9, &mcs_rx_20
, &mcs_tx_20
), GENMASK(9, 8));
331 rs_fw_set_eht_mcs_nss(cmd
->ht_rates
, bw
,
332 MAX_NSS_MCS(11, &mcs_rx_20
, &mcs_tx_20
), GENMASK(11, 10));
333 rs_fw_set_eht_mcs_nss(cmd
->ht_rates
, bw
,
334 MAX_NSS_MCS(13, &mcs_rx_20
, &mcs_tx_20
), GENMASK(13, 12));
336 /* rate for 160/320 bw */
337 for (bw
= IWL_TLC_MCS_PER_BW_160
; bw
<= IWL_TLC_MCS_PER_BW_320
; bw
++) {
338 const struct ieee80211_eht_mcs_nss_supp_bw
*mcs_rx
=
339 rs_fw_rs_mcs2eht_mcs(bw
, eht_rx_mcs
);
340 const struct ieee80211_eht_mcs_nss_supp_bw
*mcs_tx
=
341 rs_fw_rs_mcs2eht_mcs(bw
, eht_tx_mcs
);
343 /* got unsupported index for bw */
344 if (!mcs_rx
|| !mcs_tx
)
347 /* break out if we don't support the bandwidth */
348 if (cmd
->max_ch_width
< (bw
+ IWL_TLC_MNG_CH_WIDTH_80MHZ
))
351 rs_fw_set_eht_mcs_nss(cmd
->ht_rates
, bw
,
352 MAX_NSS_MCS(9, mcs_rx
, mcs_tx
), GENMASK(9, 0));
353 rs_fw_set_eht_mcs_nss(cmd
->ht_rates
, bw
,
354 MAX_NSS_MCS(11, mcs_rx
, mcs_tx
), GENMASK(11, 10));
355 rs_fw_set_eht_mcs_nss(cmd
->ht_rates
, bw
,
356 MAX_NSS_MCS(13, mcs_rx
, mcs_tx
), GENMASK(13, 12));
359 /* the station support only a single receive chain */
360 if (link_sta
->smps_mode
== IEEE80211_SMPS_STATIC
||
361 link_sta
->rx_nss
< 2)
362 memset(cmd
->ht_rates
[IWL_TLC_NSS_2
], 0,
363 sizeof(cmd
->ht_rates
[IWL_TLC_NSS_2
]));
366 static void rs_fw_set_supp_rates(struct ieee80211_vif
*vif
,
367 struct ieee80211_link_sta
*link_sta
,
368 struct ieee80211_supported_band
*sband
,
369 const struct ieee80211_sta_he_cap
*sband_he_cap
,
370 const struct ieee80211_sta_eht_cap
*sband_eht_cap
,
371 struct iwl_tlc_config_cmd_v4
*cmd
)
375 unsigned long tmp
; /* must be unsigned long for for_each_set_bit */
376 const struct ieee80211_sta_ht_cap
*ht_cap
= &link_sta
->ht_cap
;
377 const struct ieee80211_sta_vht_cap
*vht_cap
= &link_sta
->vht_cap
;
378 const struct ieee80211_sta_he_cap
*he_cap
= &link_sta
->he_cap
;
381 tmp
= link_sta
->supp_rates
[sband
->band
];
382 for_each_set_bit(i
, &tmp
, BITS_PER_LONG
)
383 supp
|= BIT(sband
->bitrates
[i
].hw_value
);
385 cmd
->non_ht_rates
= cpu_to_le16(supp
);
386 cmd
->mode
= IWL_TLC_MNG_MODE_NON_HT
;
389 if (link_sta
->eht_cap
.has_eht
&& sband_he_cap
&& sband_eht_cap
) {
390 cmd
->mode
= IWL_TLC_MNG_MODE_EHT
;
391 rs_fw_eht_set_enabled_rates(vif
, link_sta
, sband_he_cap
,
393 } else if (he_cap
->has_he
&& sband_he_cap
) {
394 cmd
->mode
= IWL_TLC_MNG_MODE_HE
;
395 rs_fw_he_set_enabled_rates(link_sta
, sband_he_cap
, cmd
);
396 } else if (vht_cap
->vht_supported
) {
397 cmd
->mode
= IWL_TLC_MNG_MODE_VHT
;
398 rs_fw_vht_set_enabled_rates(link_sta
, vht_cap
, cmd
);
399 } else if (ht_cap
->ht_supported
) {
400 cmd
->mode
= IWL_TLC_MNG_MODE_HT
;
401 cmd
->ht_rates
[IWL_TLC_NSS_1
][IWL_TLC_MCS_PER_BW_80
] =
402 cpu_to_le16(ht_cap
->mcs
.rx_mask
[0]);
404 /* the station support only a single receive chain */
405 if (link_sta
->smps_mode
== IEEE80211_SMPS_STATIC
)
406 cmd
->ht_rates
[IWL_TLC_NSS_2
][IWL_TLC_MCS_PER_BW_80
] =
409 cmd
->ht_rates
[IWL_TLC_NSS_2
][IWL_TLC_MCS_PER_BW_80
] =
410 cpu_to_le16(ht_cap
->mcs
.rx_mask
[1]);
414 void iwl_mvm_tlc_update_notif(struct iwl_mvm
*mvm
,
415 struct iwl_rx_cmd_buffer
*rxb
)
417 struct iwl_rx_packet
*pkt
= rxb_addr(rxb
);
418 struct iwl_tlc_update_notif
*notif
;
419 struct ieee80211_sta
*sta
;
420 struct ieee80211_link_sta
*link_sta
;
421 struct iwl_mvm_sta
*mvmsta
;
422 struct iwl_mvm_link_sta
*mvm_link_sta
;
423 struct iwl_lq_sta_rs_fw
*lq_sta
;
428 notif
= (void *)pkt
->data
;
429 link_sta
= rcu_dereference(mvm
->fw_id_to_link_sta
[notif
->sta_id
]);
430 sta
= rcu_dereference(mvm
->fw_id_to_mac_id
[notif
->sta_id
]);
431 if (IS_ERR_OR_NULL(sta
) || !link_sta
) {
432 /* can happen in remove station flow where mvm removed internally
433 * the station before removing from FW
436 "Invalid mvm RCU pointer for sta id (%d) in TLC notification\n",
441 mvmsta
= iwl_mvm_sta_from_mac80211(sta
);
443 flags
= le32_to_cpu(notif
->flags
);
445 mvm_link_sta
= rcu_dereference(mvmsta
->link
[link_sta
->link_id
]);
448 "Invalid mvmsta RCU pointer for link (%d) of sta id (%d) in TLC notification\n",
449 link_sta
->link_id
, notif
->sta_id
);
452 lq_sta
= &mvm_link_sta
->lq_sta
.rs_fw
;
454 if (flags
& IWL_TLC_NOTIF_FLAG_RATE
) {
455 char pretty_rate
[100];
457 if (iwl_fw_lookup_notif_ver(mvm
->fw
, DATA_PATH_GROUP
,
458 TLC_MNG_UPDATE_NOTIF
, 0) < 3) {
459 rs_pretty_print_rate_v1(pretty_rate
,
461 le32_to_cpu(notif
->rate
));
463 "Got rate in old format. Rate: %s. Converting.\n",
465 lq_sta
->last_rate_n_flags
=
466 iwl_new_rate_from_v1(le32_to_cpu(notif
->rate
));
468 lq_sta
->last_rate_n_flags
= le32_to_cpu(notif
->rate
);
470 rs_pretty_print_rate(pretty_rate
, sizeof(pretty_rate
),
471 lq_sta
->last_rate_n_flags
);
472 IWL_DEBUG_RATE(mvm
, "new rate: %s\n", pretty_rate
);
475 if (flags
& IWL_TLC_NOTIF_FLAG_AMSDU
&& !mvm_link_sta
->orig_amsdu_len
) {
476 u32 enabled
= le32_to_cpu(notif
->amsdu_enabled
);
477 u16 size
= le32_to_cpu(notif
->amsdu_size
);
485 if (link_sta
->agg
.max_amsdu_len
< size
) {
487 * In debug link_sta->agg.max_amsdu_len < size
488 * so also check with orig_amsdu_len which holds the
489 * original data before debugfs changed the value
491 WARN_ON(mvm_link_sta
->orig_amsdu_len
< size
);
495 mvmsta
->amsdu_enabled
= enabled
;
496 mvmsta
->max_amsdu_len
= size
;
497 link_sta
->agg
.max_rc_amsdu_len
= mvmsta
->max_amsdu_len
;
499 for (i
= 0; i
< IWL_MAX_TID_COUNT
; i
++) {
500 if (mvmsta
->amsdu_enabled
& BIT(i
))
501 link_sta
->agg
.max_tid_amsdu_len
[i
] =
502 iwl_mvm_max_amsdu_size(mvm
, sta
, i
);
505 * Not so elegant, but this will effectively
506 * prevent AMSDU on this TID
508 link_sta
->agg
.max_tid_amsdu_len
[i
] = 1;
511 ieee80211_sta_recalc_aggregates(sta
);
514 "AMSDU update. AMSDU size: %d, AMSDU selected size: %d, AMSDU TID bitmap 0x%X\n",
515 le32_to_cpu(notif
->amsdu_size
), size
,
516 mvmsta
->amsdu_enabled
);
522 u16
rs_fw_get_max_amsdu_len(struct ieee80211_sta
*sta
,
523 struct ieee80211_bss_conf
*link_conf
,
524 struct ieee80211_link_sta
*link_sta
)
526 const struct ieee80211_sta_vht_cap
*vht_cap
= &link_sta
->vht_cap
;
527 const struct ieee80211_sta_ht_cap
*ht_cap
= &link_sta
->ht_cap
;
528 const struct ieee80211_sta_eht_cap
*eht_cap
= &link_sta
->eht_cap
;
530 if (WARN_ON_ONCE(!link_conf
->chanreq
.oper
.chan
))
531 return IEEE80211_MAX_MPDU_LEN_VHT_3895
;
533 if (link_conf
->chanreq
.oper
.chan
->band
== NL80211_BAND_6GHZ
) {
534 switch (le16_get_bits(link_sta
->he_6ghz_capa
.capa
,
535 IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LEN
)) {
536 case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454
:
537 return IEEE80211_MAX_MPDU_LEN_VHT_11454
;
538 case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991
:
539 return IEEE80211_MAX_MPDU_LEN_VHT_7991
;
541 return IEEE80211_MAX_MPDU_LEN_VHT_3895
;
543 } else if (link_conf
->chanreq
.oper
.chan
->band
== NL80211_BAND_2GHZ
&&
545 switch (u8_get_bits(eht_cap
->eht_cap_elem
.mac_cap_info
[0],
546 IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_MASK
)) {
547 case IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_11454
:
548 return IEEE80211_MAX_MPDU_LEN_VHT_11454
;
549 case IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_7991
:
550 return IEEE80211_MAX_MPDU_LEN_VHT_7991
;
552 return IEEE80211_MAX_MPDU_LEN_VHT_3895
;
554 } else if (vht_cap
->vht_supported
) {
555 switch (vht_cap
->cap
& IEEE80211_VHT_CAP_MAX_MPDU_MASK
) {
556 case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454
:
557 return IEEE80211_MAX_MPDU_LEN_VHT_11454
;
558 case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991
:
559 return IEEE80211_MAX_MPDU_LEN_VHT_7991
;
561 return IEEE80211_MAX_MPDU_LEN_VHT_3895
;
563 } else if (ht_cap
->ht_supported
) {
564 if (ht_cap
->cap
& IEEE80211_HT_CAP_MAX_AMSDU
)
566 * agg is offloaded so we need to assume that agg
567 * are enabled and max mpdu in ampdu is 4095
568 * (spec 802.11-2016 9.3.2.1)
570 return IEEE80211_MAX_MPDU_LEN_HT_BA
;
572 return IEEE80211_MAX_MPDU_LEN_HT_3839
;
575 /* in legacy mode no amsdu is enabled so return zero */
579 void iwl_mvm_rs_fw_rate_init(struct iwl_mvm
*mvm
,
580 struct ieee80211_vif
*vif
,
581 struct ieee80211_sta
*sta
,
582 struct ieee80211_bss_conf
*link_conf
,
583 struct ieee80211_link_sta
*link_sta
,
584 enum nl80211_band band
)
586 struct ieee80211_hw
*hw
= mvm
->hw
;
587 struct iwl_mvm_sta
*mvmsta
= iwl_mvm_sta_from_mac80211(sta
);
588 u32 cmd_id
= WIDE_ID(DATA_PATH_GROUP
, TLC_MNG_CONFIG_CMD
);
589 struct ieee80211_supported_band
*sband
= hw
->wiphy
->bands
[band
];
590 u16 max_amsdu_len
= rs_fw_get_max_amsdu_len(sta
, link_conf
, link_sta
);
591 const struct ieee80211_sta_he_cap
*sband_he_cap
=
592 ieee80211_get_he_iftype_cap_vif(sband
, vif
);
593 const struct ieee80211_sta_eht_cap
*sband_eht_cap
=
594 ieee80211_get_eht_iftype_cap_vif(sband
, vif
);
595 struct iwl_mvm_link_sta
*mvm_link_sta
;
596 struct iwl_lq_sta_rs_fw
*lq_sta
;
597 struct iwl_tlc_config_cmd_v4 cfg_cmd
= {
598 .max_ch_width
= mvmsta
->authorized
?
599 rs_fw_bw_from_sta_bw(link_sta
) : IWL_TLC_MNG_CH_WIDTH_20MHZ
,
600 .flags
= cpu_to_le16(rs_fw_get_config_flags(mvm
, vif
, link_sta
,
602 .chains
= rs_fw_set_active_chains(iwl_mvm_get_valid_tx_ant(mvm
)),
603 .sgi_ch_width_supp
= rs_fw_sgi_cw_support(link_sta
),
604 .max_mpdu_len
= iwl_mvm_is_csum_supported(mvm
) ?
605 cpu_to_le16(max_amsdu_len
) : 0,
607 unsigned int link_id
= link_conf
->link_id
;
608 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(mvmsta
->vif
);
612 /* Enable extra EHT LTF if there's mutual support by AP and client */
614 sband_eht_cap
->eht_cap_elem
.phy_cap_info
[5] &
615 IEEE80211_EHT_PHY_CAP5_SUPP_EXTRA_EHT_LTF
&&
616 link_sta
->eht_cap
.has_eht
&&
617 link_sta
->eht_cap
.eht_cap_elem
.phy_cap_info
[5] &
618 IEEE80211_EHT_PHY_CAP5_SUPP_EXTRA_EHT_LTF
) {
619 IWL_DEBUG_RATE(mvm
, "Set support for Extra EHT LTF\n");
621 cpu_to_le16(IWL_TLC_MNG_CFG_FLAGS_EHT_EXTRA_LTF_MSK
);
625 mvm_link_sta
= rcu_dereference(mvmsta
->link
[link_id
]);
626 if (WARN_ON_ONCE(!mvm_link_sta
)) {
631 cfg_cmd
.sta_id
= mvm_link_sta
->sta_id
;
633 lq_sta
= &mvm_link_sta
->lq_sta
.rs_fw
;
634 memset(lq_sta
, 0, offsetof(typeof(*lq_sta
), pers
));
638 #ifdef CONFIG_IWLWIFI_DEBUGFS
639 iwl_mvm_reset_frame_stats(mvm
);
641 rs_fw_set_supp_rates(vif
, link_sta
, sband
,
642 sband_he_cap
, sband_eht_cap
,
646 * since TLC offload works with one mode we can assume
647 * that only vht/ht is used and also set it as station max amsdu
649 link_sta
->agg
.max_amsdu_len
= max_amsdu_len
;
650 ieee80211_sta_recalc_aggregates(sta
);
652 cfg_cmd
.max_tx_op
= cpu_to_le16(mvmvif
->max_tx_op
);
654 cmd_ver
= iwl_fw_lookup_cmd_ver(mvm
->fw
, cmd_id
, 0);
655 IWL_DEBUG_RATE(mvm
, "TLC CONFIG CMD, sta_id=%d, max_ch_width=%d, mode=%d\n",
656 cfg_cmd
.sta_id
, cfg_cmd
.max_ch_width
, cfg_cmd
.mode
);
657 IWL_DEBUG_RATE(mvm
, "TLC CONFIG CMD, chains=0x%X, ch_wid_supp=%d, flags=0x%X\n",
658 cfg_cmd
.chains
, cfg_cmd
.sgi_ch_width_supp
, cfg_cmd
.flags
);
659 IWL_DEBUG_RATE(mvm
, "TLC CONFIG CMD, mpdu_len=%d, no_ht_rate=0x%X, tx_op=%d\n",
660 cfg_cmd
.max_mpdu_len
, cfg_cmd
.non_ht_rates
, cfg_cmd
.max_tx_op
);
661 IWL_DEBUG_RATE(mvm
, "TLC CONFIG CMD, ht_rate[0][0]=0x%X, ht_rate[1][0]=0x%X\n",
662 cfg_cmd
.ht_rates
[0][0], cfg_cmd
.ht_rates
[1][0]);
663 IWL_DEBUG_RATE(mvm
, "TLC CONFIG CMD, ht_rate[0][1]=0x%X, ht_rate[1][1]=0x%X\n",
664 cfg_cmd
.ht_rates
[0][1], cfg_cmd
.ht_rates
[1][1]);
665 IWL_DEBUG_RATE(mvm
, "TLC CONFIG CMD, ht_rate[0][2]=0x%X, ht_rate[1][2]=0x%X\n",
666 cfg_cmd
.ht_rates
[0][2], cfg_cmd
.ht_rates
[1][2]);
668 ret
= iwl_mvm_send_cmd_pdu(mvm
, cmd_id
, CMD_ASYNC
,
669 sizeof(cfg_cmd
), &cfg_cmd
);
670 } else if (cmd_ver
< 4) {
671 struct iwl_tlc_config_cmd_v3 cfg_cmd_v3
= {
672 .sta_id
= cfg_cmd
.sta_id
,
673 .max_ch_width
= cfg_cmd
.max_ch_width
,
674 .mode
= cfg_cmd
.mode
,
675 .chains
= cfg_cmd
.chains
,
676 .amsdu
= !!cfg_cmd
.max_mpdu_len
,
677 .flags
= cfg_cmd
.flags
,
678 .non_ht_rates
= cfg_cmd
.non_ht_rates
,
679 .ht_rates
[0][0] = cfg_cmd
.ht_rates
[0][0],
680 .ht_rates
[0][1] = cfg_cmd
.ht_rates
[0][1],
681 .ht_rates
[1][0] = cfg_cmd
.ht_rates
[1][0],
682 .ht_rates
[1][1] = cfg_cmd
.ht_rates
[1][1],
683 .sgi_ch_width_supp
= cfg_cmd
.sgi_ch_width_supp
,
684 .max_mpdu_len
= cfg_cmd
.max_mpdu_len
,
687 u16 cmd_size
= sizeof(cfg_cmd_v3
);
689 /* In old versions of the API the struct is 4 bytes smaller */
690 if (iwl_fw_lookup_cmd_ver(mvm
->fw
, cmd_id
, 0) < 3)
693 ret
= iwl_mvm_send_cmd_pdu(mvm
, cmd_id
, CMD_ASYNC
, cmd_size
,
700 IWL_ERR(mvm
, "Failed to send rate scale config (%d)\n", ret
);
703 int rs_fw_tx_protection(struct iwl_mvm
*mvm
, struct iwl_mvm_sta
*mvmsta
,
706 /* TODO: need to introduce a new FW cmd since LQ cmd is not relevant */
707 IWL_DEBUG_RATE(mvm
, "tx protection - not implemented yet.\n");
711 void iwl_mvm_rs_add_sta_link(struct iwl_mvm
*mvm
,
712 struct iwl_mvm_link_sta
*link_sta
)
714 struct iwl_lq_sta_rs_fw
*lq_sta
;
716 lq_sta
= &link_sta
->lq_sta
.rs_fw
;
718 lq_sta
->pers
.drv
= mvm
;
719 lq_sta
->pers
.sta_id
= link_sta
->sta_id
;
720 lq_sta
->pers
.chains
= 0;
721 memset(lq_sta
->pers
.chain_signal
, 0,
722 sizeof(lq_sta
->pers
.chain_signal
));
723 lq_sta
->pers
.last_rssi
= S8_MIN
;
724 lq_sta
->last_rate_n_flags
= 0;
726 #ifdef CONFIG_MAC80211_DEBUGFS
727 lq_sta
->pers
.dbg_fixed_rate
= 0;
731 void iwl_mvm_rs_add_sta(struct iwl_mvm
*mvm
, struct iwl_mvm_sta
*mvmsta
)
733 unsigned int link_id
;
735 IWL_DEBUG_RATE(mvm
, "create station rate scale window\n");
737 for (link_id
= 0; link_id
< ARRAY_SIZE(mvmsta
->link
); link_id
++) {
738 struct iwl_mvm_link_sta
*link
=
739 rcu_dereference_protected(mvmsta
->link
[link_id
],
740 lockdep_is_held(&mvm
->mutex
));
744 iwl_mvm_rs_add_sta_link(mvm
, link
);