1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2 /* 3 * Copyright (C) 2024-2025 Intel Corporation 4 */ 5 6 #include <net/mac80211.h> 7 8 #include "tlc.h" 9 #include "hcmd.h" 10 #include "sta.h" 11 12 #include "fw/api/rs.h" 13 #include "fw/api/context.h" 14 #include "fw/api/dhc.h" 15 16 static u8 iwl_mld_fw_bw_from_sta_bw(const struct ieee80211_link_sta *link_sta) 17 { 18 switch (link_sta->bandwidth) { 19 case IEEE80211_STA_RX_BW_320: 20 return IWL_TLC_MNG_CH_WIDTH_320MHZ; 21 case IEEE80211_STA_RX_BW_160: 22 return IWL_TLC_MNG_CH_WIDTH_160MHZ; 23 case IEEE80211_STA_RX_BW_80: 24 return IWL_TLC_MNG_CH_WIDTH_80MHZ; 25 case IEEE80211_STA_RX_BW_40: 26 return IWL_TLC_MNG_CH_WIDTH_40MHZ; 27 case IEEE80211_STA_RX_BW_20: 28 default: 29 return IWL_TLC_MNG_CH_WIDTH_20MHZ; 30 } 31 } 32 33 static __le16 34 iwl_mld_get_tlc_cmd_flags(struct iwl_mld *mld, 35 struct ieee80211_vif *vif, 36 struct ieee80211_link_sta *link_sta, 37 const struct ieee80211_sta_he_cap *own_he_cap, 38 const struct ieee80211_sta_eht_cap *own_eht_cap) 39 { 40 struct ieee80211_sta_ht_cap *ht_cap = &link_sta->ht_cap; 41 struct ieee80211_sta_vht_cap *vht_cap = &link_sta->vht_cap; 42 struct ieee80211_sta_he_cap *he_cap = &link_sta->he_cap; 43 bool has_vht = vht_cap->vht_supported; 44 u16 flags = 0; 45 46 /* STBC flags */ 47 if (mld->cfg->ht_params.stbc && 48 (hweight8(iwl_mld_get_valid_tx_ant(mld)) > 1)) { 49 if (he_cap->has_he && he_cap->he_cap_elem.phy_cap_info[2] & 50 IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ) 51 flags |= IWL_TLC_MNG_CFG_FLAGS_STBC_MSK; 52 else if (vht_cap->cap & IEEE80211_VHT_CAP_RXSTBC_MASK) 53 flags |= IWL_TLC_MNG_CFG_FLAGS_STBC_MSK; 54 else if (ht_cap->cap & IEEE80211_HT_CAP_RX_STBC) 55 flags |= IWL_TLC_MNG_CFG_FLAGS_STBC_MSK; 56 } 57 58 /* LDPC */ 59 if (mld->cfg->ht_params.ldpc && 60 ((ht_cap->cap & IEEE80211_HT_CAP_LDPC_CODING) || 61 (has_vht && (vht_cap->cap & IEEE80211_VHT_CAP_RXLDPC)))) 62 flags |= IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK; 63 64 if (he_cap->has_he && (he_cap->he_cap_elem.phy_cap_info[1] & 65 IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD)) 66 flags |= IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK; 67 68 if (own_he_cap && 69 !(own_he_cap->he_cap_elem.phy_cap_info[1] & 70 IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD)) 71 flags &= ~IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK; 72 73 /* DCM */ 74 if (he_cap->has_he && 75 (he_cap->he_cap_elem.phy_cap_info[3] & 76 IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_MASK && 77 own_he_cap && 78 own_he_cap->he_cap_elem.phy_cap_info[3] & 79 IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_MASK)) 80 flags |= IWL_TLC_MNG_CFG_FLAGS_HE_DCM_NSS_1_MSK; 81 82 /* Extra EHT LTF */ 83 if (own_eht_cap && 84 own_eht_cap->eht_cap_elem.phy_cap_info[5] & 85 IEEE80211_EHT_PHY_CAP5_SUPP_EXTRA_EHT_LTF && 86 link_sta->eht_cap.has_eht && 87 link_sta->eht_cap.eht_cap_elem.phy_cap_info[5] & 88 IEEE80211_EHT_PHY_CAP5_SUPP_EXTRA_EHT_LTF) { 89 flags |= IWL_TLC_MNG_CFG_FLAGS_EHT_EXTRA_LTF_MSK; 90 } 91 92 return cpu_to_le16(flags); 93 } 94 95 static u8 iwl_mld_get_fw_chains(struct iwl_mld *mld) 96 { 97 u8 chains = iwl_mld_get_valid_tx_ant(mld); 98 u8 fw_chains = 0; 99 100 if (chains & ANT_A) 101 fw_chains |= IWL_TLC_MNG_CHAIN_A_MSK; 102 if (chains & ANT_B) 103 fw_chains |= IWL_TLC_MNG_CHAIN_B_MSK; 104 105 return fw_chains; 106 } 107 108 static u8 iwl_mld_get_fw_sgi(struct ieee80211_link_sta *link_sta) 109 { 110 struct ieee80211_sta_ht_cap *ht_cap = &link_sta->ht_cap; 111 struct ieee80211_sta_vht_cap *vht_cap = &link_sta->vht_cap; 112 struct ieee80211_sta_he_cap *he_cap = &link_sta->he_cap; 113 u8 sgi_chwidths = 0; 114 115 /* If the association supports HE, HT/VHT rates will never be used for 116 * Tx and therefor there's no need to set the 117 * sgi-per-channel-width-support bits 118 */ 119 if (he_cap->has_he) 120 return 0; 121 122 if (ht_cap->cap & IEEE80211_HT_CAP_SGI_20) 123 sgi_chwidths |= BIT(IWL_TLC_MNG_CH_WIDTH_20MHZ); 124 if (ht_cap->cap & IEEE80211_HT_CAP_SGI_40) 125 sgi_chwidths |= BIT(IWL_TLC_MNG_CH_WIDTH_40MHZ); 126 if (vht_cap->cap & IEEE80211_VHT_CAP_SHORT_GI_80) 127 sgi_chwidths |= BIT(IWL_TLC_MNG_CH_WIDTH_80MHZ); 128 if (vht_cap->cap & IEEE80211_VHT_CAP_SHORT_GI_160) 129 sgi_chwidths |= BIT(IWL_TLC_MNG_CH_WIDTH_160MHZ); 130 131 return sgi_chwidths; 132 } 133 134 static int 135 iwl_mld_get_highest_fw_mcs(const struct ieee80211_sta_vht_cap *vht_cap, 136 int nss) 137 { 138 u16 rx_mcs = le16_to_cpu(vht_cap->vht_mcs.rx_mcs_map) & 139 (0x3 << (2 * (nss - 1))); 140 rx_mcs >>= (2 * (nss - 1)); 141 142 switch (rx_mcs) { 143 case IEEE80211_VHT_MCS_SUPPORT_0_7: 144 return IWL_TLC_MNG_HT_RATE_MCS7; 145 case IEEE80211_VHT_MCS_SUPPORT_0_8: 146 return IWL_TLC_MNG_HT_RATE_MCS8; 147 case IEEE80211_VHT_MCS_SUPPORT_0_9: 148 return IWL_TLC_MNG_HT_RATE_MCS9; 149 default: 150 WARN_ON_ONCE(1); 151 break; 152 } 153 154 return 0; 155 } 156 157 static void 158 iwl_mld_fill_vht_rates(const struct ieee80211_link_sta *link_sta, 159 const struct ieee80211_sta_vht_cap *vht_cap, 160 struct iwl_tlc_config_cmd *cmd) 161 { 162 u32 supp; 163 int i, highest_mcs; 164 u8 max_nss = link_sta->rx_nss; 165 struct ieee80211_vht_cap ieee_vht_cap = { 166 .vht_cap_info = cpu_to_le32(vht_cap->cap), 167 .supp_mcs = vht_cap->vht_mcs, 168 }; 169 170 /* the station support only a single receive chain */ 171 if (link_sta->smps_mode == IEEE80211_SMPS_STATIC) 172 max_nss = 1; 173 174 for (i = 0; i < max_nss && i < IWL_TLC_NSS_MAX; i++) { 175 int nss = i + 1; 176 177 highest_mcs = iwl_mld_get_highest_fw_mcs(vht_cap, nss); 178 if (!highest_mcs) 179 continue; 180 181 supp = BIT(highest_mcs + 1) - 1; 182 if (link_sta->bandwidth == IEEE80211_STA_RX_BW_20) 183 supp &= ~BIT(IWL_TLC_MNG_HT_RATE_MCS9); 184 185 cmd->ht_rates[i][IWL_TLC_MCS_PER_BW_80] = cpu_to_le32(supp); 186 /* Check if VHT extended NSS indicates that the bandwidth/NSS 187 * configuration is supported - only for MCS 0 since we already 188 * decoded the MCS bits anyway ourselves. 189 */ 190 if (link_sta->bandwidth == IEEE80211_STA_RX_BW_160 && 191 ieee80211_get_vht_max_nss(&ieee_vht_cap, 192 IEEE80211_VHT_CHANWIDTH_160MHZ, 193 0, true, nss) >= nss) 194 cmd->ht_rates[i][IWL_TLC_MCS_PER_BW_160] = 195 cmd->ht_rates[i][IWL_TLC_MCS_PER_BW_80]; 196 } 197 } 198 199 static u32 iwl_mld_he_mac80211_mcs_to_fw_mcs(u16 mcs) 200 { 201 switch (mcs) { 202 case IEEE80211_HE_MCS_SUPPORT_0_7: 203 return BIT(IWL_TLC_MNG_HT_RATE_MCS7 + 1) - 1; 204 case IEEE80211_HE_MCS_SUPPORT_0_9: 205 return BIT(IWL_TLC_MNG_HT_RATE_MCS9 + 1) - 1; 206 case IEEE80211_HE_MCS_SUPPORT_0_11: 207 return BIT(IWL_TLC_MNG_HT_RATE_MCS11 + 1) - 1; 208 case IEEE80211_HE_MCS_NOT_SUPPORTED: 209 return 0; 210 } 211 212 WARN(1, "invalid HE MCS %d\n", mcs); 213 return 0; 214 } 215 216 static void 217 iwl_mld_fill_he_rates(const struct ieee80211_link_sta *link_sta, 218 const struct ieee80211_sta_he_cap *own_he_cap, 219 struct iwl_tlc_config_cmd *cmd) 220 { 221 const struct ieee80211_sta_he_cap *he_cap = &link_sta->he_cap; 222 u16 mcs_160 = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_160); 223 u16 mcs_80 = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_80); 224 u16 tx_mcs_80 = le16_to_cpu(own_he_cap->he_mcs_nss_supp.tx_mcs_80); 225 u16 tx_mcs_160 = le16_to_cpu(own_he_cap->he_mcs_nss_supp.tx_mcs_160); 226 int i; 227 u8 nss = link_sta->rx_nss; 228 229 /* the station support only a single receive chain */ 230 if (link_sta->smps_mode == IEEE80211_SMPS_STATIC) 231 nss = 1; 232 233 for (i = 0; i < nss && i < IWL_TLC_NSS_MAX; i++) { 234 u16 _mcs_160 = (mcs_160 >> (2 * i)) & 0x3; 235 u16 _mcs_80 = (mcs_80 >> (2 * i)) & 0x3; 236 u16 _tx_mcs_160 = (tx_mcs_160 >> (2 * i)) & 0x3; 237 u16 _tx_mcs_80 = (tx_mcs_80 >> (2 * i)) & 0x3; 238 239 /* If one side doesn't support - mark both as not supporting */ 240 if (_mcs_80 == IEEE80211_HE_MCS_NOT_SUPPORTED || 241 _tx_mcs_80 == IEEE80211_HE_MCS_NOT_SUPPORTED) { 242 _mcs_80 = IEEE80211_HE_MCS_NOT_SUPPORTED; 243 _tx_mcs_80 = IEEE80211_HE_MCS_NOT_SUPPORTED; 244 } 245 if (_mcs_80 > _tx_mcs_80) 246 _mcs_80 = _tx_mcs_80; 247 cmd->ht_rates[i][IWL_TLC_MCS_PER_BW_80] = 248 cpu_to_le32(iwl_mld_he_mac80211_mcs_to_fw_mcs(_mcs_80)); 249 250 /* If one side doesn't support - mark both as not supporting */ 251 if (_mcs_160 == IEEE80211_HE_MCS_NOT_SUPPORTED || 252 _tx_mcs_160 == IEEE80211_HE_MCS_NOT_SUPPORTED) { 253 _mcs_160 = IEEE80211_HE_MCS_NOT_SUPPORTED; 254 _tx_mcs_160 = IEEE80211_HE_MCS_NOT_SUPPORTED; 255 } 256 if (_mcs_160 > _tx_mcs_160) 257 _mcs_160 = _tx_mcs_160; 258 cmd->ht_rates[i][IWL_TLC_MCS_PER_BW_160] = 259 cpu_to_le32(iwl_mld_he_mac80211_mcs_to_fw_mcs(_mcs_160)); 260 } 261 } 262 263 static void iwl_mld_set_eht_mcs(__le32 ht_rates[][3], 264 enum IWL_TLC_MCS_PER_BW bw, 265 u8 max_nss, u32 mcs_msk) 266 { 267 if (max_nss >= 2) 268 ht_rates[IWL_TLC_NSS_2][bw] |= cpu_to_le32(mcs_msk); 269 270 if (max_nss >= 1) 271 ht_rates[IWL_TLC_NSS_1][bw] |= cpu_to_le32(mcs_msk); 272 } 273 274 static const 275 struct ieee80211_eht_mcs_nss_supp_bw * 276 iwl_mld_get_eht_mcs_of_bw(enum IWL_TLC_MCS_PER_BW bw, 277 const struct ieee80211_eht_mcs_nss_supp *eht_mcs) 278 { 279 switch (bw) { 280 case IWL_TLC_MCS_PER_BW_80: 281 return &eht_mcs->bw._80; 282 case IWL_TLC_MCS_PER_BW_160: 283 return &eht_mcs->bw._160; 284 case IWL_TLC_MCS_PER_BW_320: 285 return &eht_mcs->bw._320; 286 default: 287 return NULL; 288 } 289 } 290 291 static u8 iwl_mld_get_eht_max_nss(u8 rx_nss, u8 tx_nss) 292 { 293 u8 tx = u8_get_bits(tx_nss, IEEE80211_EHT_MCS_NSS_TX); 294 u8 rx = u8_get_bits(rx_nss, IEEE80211_EHT_MCS_NSS_RX); 295 /* the max nss that can be used, 296 * is the min with our tx capa and the peer rx capa. 297 */ 298 return min(tx, rx); 299 } 300 301 #define MAX_NSS_MCS(mcs_num, rx, tx) \ 302 iwl_mld_get_eht_max_nss((rx)->rx_tx_mcs ##mcs_num## _max_nss, \ 303 (tx)->rx_tx_mcs ##mcs_num## _max_nss) 304 305 static void 306 iwl_mld_fill_eht_rates(struct ieee80211_vif *vif, 307 const struct ieee80211_link_sta *link_sta, 308 const struct ieee80211_sta_he_cap *own_he_cap, 309 const struct ieee80211_sta_eht_cap *own_eht_cap, 310 struct iwl_tlc_config_cmd *cmd) 311 { 312 /* peer RX mcs capa */ 313 const struct ieee80211_eht_mcs_nss_supp *eht_rx_mcs = 314 &link_sta->eht_cap.eht_mcs_nss_supp; 315 /* our TX mcs capa */ 316 const struct ieee80211_eht_mcs_nss_supp *eht_tx_mcs = 317 &own_eht_cap->eht_mcs_nss_supp; 318 319 enum IWL_TLC_MCS_PER_BW bw; 320 struct ieee80211_eht_mcs_nss_supp_20mhz_only mcs_rx_20; 321 struct ieee80211_eht_mcs_nss_supp_20mhz_only mcs_tx_20; 322 323 /* peer is 20 MHz only */ 324 if (vif->type == NL80211_IFTYPE_AP && 325 !(link_sta->he_cap.he_cap_elem.phy_cap_info[0] & 326 IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_MASK_ALL)) { 327 mcs_rx_20 = eht_rx_mcs->only_20mhz; 328 } else { 329 mcs_rx_20.rx_tx_mcs7_max_nss = 330 eht_rx_mcs->bw._80.rx_tx_mcs9_max_nss; 331 mcs_rx_20.rx_tx_mcs9_max_nss = 332 eht_rx_mcs->bw._80.rx_tx_mcs9_max_nss; 333 mcs_rx_20.rx_tx_mcs11_max_nss = 334 eht_rx_mcs->bw._80.rx_tx_mcs11_max_nss; 335 mcs_rx_20.rx_tx_mcs13_max_nss = 336 eht_rx_mcs->bw._80.rx_tx_mcs13_max_nss; 337 } 338 339 /* NIC is capable of 20 MHz only */ 340 if (!(own_he_cap->he_cap_elem.phy_cap_info[0] & 341 IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_MASK_ALL)) { 342 mcs_tx_20 = eht_tx_mcs->only_20mhz; 343 } else { 344 mcs_tx_20.rx_tx_mcs7_max_nss = 345 eht_tx_mcs->bw._80.rx_tx_mcs9_max_nss; 346 mcs_tx_20.rx_tx_mcs9_max_nss = 347 eht_tx_mcs->bw._80.rx_tx_mcs9_max_nss; 348 mcs_tx_20.rx_tx_mcs11_max_nss = 349 eht_tx_mcs->bw._80.rx_tx_mcs11_max_nss; 350 mcs_tx_20.rx_tx_mcs13_max_nss = 351 eht_tx_mcs->bw._80.rx_tx_mcs13_max_nss; 352 } 353 354 /* rates for 20/40/80 MHz */ 355 bw = IWL_TLC_MCS_PER_BW_80; 356 iwl_mld_set_eht_mcs(cmd->ht_rates, bw, 357 MAX_NSS_MCS(7, &mcs_rx_20, &mcs_tx_20), 358 GENMASK(7, 0)); 359 iwl_mld_set_eht_mcs(cmd->ht_rates, bw, 360 MAX_NSS_MCS(9, &mcs_rx_20, &mcs_tx_20), 361 GENMASK(9, 8)); 362 iwl_mld_set_eht_mcs(cmd->ht_rates, bw, 363 MAX_NSS_MCS(11, &mcs_rx_20, &mcs_tx_20), 364 GENMASK(11, 10)); 365 iwl_mld_set_eht_mcs(cmd->ht_rates, bw, 366 MAX_NSS_MCS(13, &mcs_rx_20, &mcs_tx_20), 367 GENMASK(13, 12)); 368 369 /* rates for 160/320 MHz */ 370 for (bw = IWL_TLC_MCS_PER_BW_160; bw <= IWL_TLC_MCS_PER_BW_320; bw++) { 371 const struct ieee80211_eht_mcs_nss_supp_bw *mcs_rx = 372 iwl_mld_get_eht_mcs_of_bw(bw, eht_rx_mcs); 373 const struct ieee80211_eht_mcs_nss_supp_bw *mcs_tx = 374 iwl_mld_get_eht_mcs_of_bw(bw, eht_tx_mcs); 375 376 /* got unsupported index for bw */ 377 if (!mcs_rx || !mcs_tx) 378 continue; 379 380 /* break out if we don't support the bandwidth */ 381 if (cmd->max_ch_width < (bw + IWL_TLC_MNG_CH_WIDTH_80MHZ)) 382 break; 383 384 iwl_mld_set_eht_mcs(cmd->ht_rates, bw, 385 MAX_NSS_MCS(9, mcs_rx, mcs_tx), 386 GENMASK(9, 0)); 387 iwl_mld_set_eht_mcs(cmd->ht_rates, bw, 388 MAX_NSS_MCS(11, mcs_rx, mcs_tx), 389 GENMASK(11, 10)); 390 iwl_mld_set_eht_mcs(cmd->ht_rates, bw, 391 MAX_NSS_MCS(13, mcs_rx, mcs_tx), 392 GENMASK(13, 12)); 393 } 394 395 /* the station support only a single receive chain */ 396 if (link_sta->smps_mode == IEEE80211_SMPS_STATIC || 397 link_sta->rx_nss < 2) 398 memset(cmd->ht_rates[IWL_TLC_NSS_2], 0, 399 sizeof(cmd->ht_rates[IWL_TLC_NSS_2])); 400 } 401 402 static void 403 iwl_mld_fill_supp_rates(struct iwl_mld *mld, struct ieee80211_vif *vif, 404 struct ieee80211_link_sta *link_sta, 405 struct ieee80211_supported_band *sband, 406 const struct ieee80211_sta_he_cap *own_he_cap, 407 const struct ieee80211_sta_eht_cap *own_eht_cap, 408 struct iwl_tlc_config_cmd *cmd) 409 { 410 int i; 411 u16 non_ht_rates = 0; 412 unsigned long rates_bitmap; 413 const struct ieee80211_sta_ht_cap *ht_cap = &link_sta->ht_cap; 414 const struct ieee80211_sta_vht_cap *vht_cap = &link_sta->vht_cap; 415 const struct ieee80211_sta_he_cap *he_cap = &link_sta->he_cap; 416 417 /* non HT rates */ 418 rates_bitmap = link_sta->supp_rates[sband->band]; 419 for_each_set_bit(i, &rates_bitmap, BITS_PER_LONG) 420 non_ht_rates |= BIT(sband->bitrates[i].hw_value); 421 422 cmd->non_ht_rates = cpu_to_le16(non_ht_rates); 423 cmd->mode = IWL_TLC_MNG_MODE_NON_HT; 424 425 if (link_sta->eht_cap.has_eht && own_he_cap && own_eht_cap) { 426 cmd->mode = IWL_TLC_MNG_MODE_EHT; 427 iwl_mld_fill_eht_rates(vif, link_sta, own_he_cap, 428 own_eht_cap, cmd); 429 } else if (he_cap->has_he && own_he_cap) { 430 cmd->mode = IWL_TLC_MNG_MODE_HE; 431 iwl_mld_fill_he_rates(link_sta, own_he_cap, cmd); 432 } else if (vht_cap->vht_supported) { 433 cmd->mode = IWL_TLC_MNG_MODE_VHT; 434 iwl_mld_fill_vht_rates(link_sta, vht_cap, cmd); 435 } else if (ht_cap->ht_supported) { 436 cmd->mode = IWL_TLC_MNG_MODE_HT; 437 cmd->ht_rates[IWL_TLC_NSS_1][IWL_TLC_MCS_PER_BW_80] = 438 cpu_to_le32(ht_cap->mcs.rx_mask[0]); 439 440 /* the station support only a single receive chain */ 441 if (link_sta->smps_mode == IEEE80211_SMPS_STATIC) 442 cmd->ht_rates[IWL_TLC_NSS_2][IWL_TLC_MCS_PER_BW_80] = 443 0; 444 else 445 cmd->ht_rates[IWL_TLC_NSS_2][IWL_TLC_MCS_PER_BW_80] = 446 cpu_to_le32(ht_cap->mcs.rx_mask[1]); 447 } 448 } 449 450 static void iwl_mld_convert_tlc_cmd_to_v4(struct iwl_tlc_config_cmd *cmd, 451 struct iwl_tlc_config_cmd_v4 *cmd_v4) 452 { 453 /* Copy everything until ht_rates */ 454 memcpy(cmd_v4, cmd, offsetof(struct iwl_tlc_config_cmd, ht_rates)); 455 456 /* Convert ht_rates from __le32 to __le16 */ 457 BUILD_BUG_ON(ARRAY_SIZE(cmd_v4->ht_rates) != ARRAY_SIZE(cmd->ht_rates)); 458 BUILD_BUG_ON(ARRAY_SIZE(cmd_v4->ht_rates[0]) != ARRAY_SIZE(cmd->ht_rates[0])); 459 460 for (int nss = 0; nss < ARRAY_SIZE(cmd->ht_rates); nss++) 461 for (int bw = 0; bw < ARRAY_SIZE(cmd->ht_rates[nss]); bw++) 462 cmd_v4->ht_rates[nss][bw] = 463 cpu_to_le16(le32_to_cpu(cmd->ht_rates[nss][bw])); 464 465 /* Copy the rest */ 466 cmd_v4->max_mpdu_len = cmd->max_mpdu_len; 467 cmd_v4->max_tx_op = cmd->max_tx_op; 468 } 469 470 static void iwl_mld_send_tlc_cmd(struct iwl_mld *mld, 471 struct ieee80211_vif *vif, 472 struct ieee80211_link_sta *link_sta, 473 enum nl80211_band band) 474 { 475 struct iwl_mld_sta *mld_sta = iwl_mld_sta_from_mac80211(link_sta->sta); 476 struct ieee80211_supported_band *sband = mld->hw->wiphy->bands[band]; 477 const struct ieee80211_sta_he_cap *own_he_cap = 478 ieee80211_get_he_iftype_cap_vif(sband, vif); 479 const struct ieee80211_sta_eht_cap *own_eht_cap = 480 ieee80211_get_eht_iftype_cap_vif(sband, vif); 481 struct iwl_tlc_config_cmd cmd = { 482 /* For AP mode, use 20 MHz until the STA is authorized */ 483 .max_ch_width = mld_sta->sta_state > IEEE80211_STA_ASSOC ? 484 iwl_mld_fw_bw_from_sta_bw(link_sta) : 485 IWL_TLC_MNG_CH_WIDTH_20MHZ, 486 .flags = iwl_mld_get_tlc_cmd_flags(mld, vif, link_sta, 487 own_he_cap, own_eht_cap), 488 .chains = iwl_mld_get_fw_chains(mld), 489 .sgi_ch_width_supp = iwl_mld_get_fw_sgi(link_sta), 490 .max_mpdu_len = cpu_to_le16(link_sta->agg.max_amsdu_len), 491 }; 492 int fw_sta_id = iwl_mld_fw_sta_id_from_link_sta(mld, link_sta); 493 u32 cmd_id = WIDE_ID(DATA_PATH_GROUP, TLC_MNG_CONFIG_CMD); 494 u8 cmd_ver = iwl_fw_lookup_cmd_ver(mld->fw, cmd_id, 0); 495 struct iwl_tlc_config_cmd_v4 cmd_v4; 496 void *cmd_ptr; 497 u8 cmd_size; 498 int ret; 499 500 if (fw_sta_id < 0) 501 return; 502 503 cmd.sta_id = fw_sta_id; 504 505 iwl_mld_fill_supp_rates(mld, vif, link_sta, sband, 506 own_he_cap, own_eht_cap, 507 &cmd); 508 509 if (cmd_ver == 5) { 510 cmd_ptr = &cmd; 511 cmd_size = sizeof(cmd); 512 } else if (cmd_ver == 4) { 513 iwl_mld_convert_tlc_cmd_to_v4(&cmd, &cmd_v4); 514 cmd_ptr = &cmd_v4; 515 cmd_size = sizeof(cmd_v4); 516 } else { 517 IWL_ERR(mld, "Unsupported TLC config cmd version %d\n", 518 cmd_ver); 519 return; 520 } 521 522 IWL_DEBUG_RATE(mld, 523 "TLC CONFIG CMD, sta_id=%d, max_ch_width=%d, mode=%d\n", 524 cmd.sta_id, cmd.max_ch_width, cmd.mode); 525 526 /* Send async since this can be called within a RCU-read section */ 527 ret = iwl_mld_send_cmd_with_flags_pdu(mld, cmd_id, CMD_ASYNC, cmd_ptr, 528 cmd_size); 529 if (ret) 530 IWL_ERR(mld, "Failed to send TLC cmd (%d)\n", ret); 531 } 532 533 int iwl_mld_send_tlc_dhc(struct iwl_mld *mld, u8 sta_id, u32 type, u32 data) 534 { 535 struct { 536 struct iwl_dhc_cmd dhc; 537 struct iwl_dhc_tlc_cmd tlc; 538 } __packed cmd = { 539 .tlc.sta_id = sta_id, 540 .tlc.type = cpu_to_le32(type), 541 .tlc.data[0] = cpu_to_le32(data), 542 .dhc.length = cpu_to_le32(sizeof(cmd.tlc) >> 2), 543 .dhc.index_and_mask = 544 cpu_to_le32(DHC_TABLE_INTEGRATION | DHC_TARGET_UMAC | 545 DHC_INTEGRATION_TLC_DEBUG_CONFIG), 546 }; 547 int ret; 548 549 ret = iwl_mld_send_cmd_with_flags_pdu(mld, 550 WIDE_ID(IWL_ALWAYS_LONG_GROUP, 551 DEBUG_HOST_COMMAND), 552 CMD_ASYNC, &cmd); 553 IWL_DEBUG_RATE(mld, "sta_id %d, type: 0x%X, value: 0x%X, ret%d\n", 554 sta_id, type, data, ret); 555 return ret; 556 } 557 558 void iwl_mld_config_tlc_link(struct iwl_mld *mld, 559 struct ieee80211_vif *vif, 560 struct ieee80211_bss_conf *link_conf, 561 struct ieee80211_link_sta *link_sta) 562 { 563 struct iwl_mld_sta *mld_sta = iwl_mld_sta_from_mac80211(link_sta->sta); 564 enum nl80211_band band; 565 566 if (WARN_ON_ONCE(!link_conf->chanreq.oper.chan)) 567 return; 568 569 /* Before we have information about a station, configure the A-MSDU RC 570 * limit such that iwlmd and mac80211 would not be allowed to build 571 * A-MSDUs. 572 */ 573 if (mld_sta->sta_state < IEEE80211_STA_ASSOC) { 574 link_sta->agg.max_rc_amsdu_len = 1; 575 ieee80211_sta_recalc_aggregates(link_sta->sta); 576 } 577 578 band = link_conf->chanreq.oper.chan->band; 579 iwl_mld_send_tlc_cmd(mld, vif, link_sta, band); 580 } 581 582 void iwl_mld_config_tlc(struct iwl_mld *mld, struct ieee80211_vif *vif, 583 struct ieee80211_sta *sta) 584 { 585 struct ieee80211_bss_conf *link; 586 int link_id; 587 588 lockdep_assert_wiphy(mld->wiphy); 589 590 for_each_vif_active_link(vif, link, link_id) { 591 struct ieee80211_link_sta *link_sta = 592 link_sta_dereference_check(sta, link_id); 593 594 if (!link || !link_sta) 595 continue; 596 597 iwl_mld_config_tlc_link(mld, vif, link, link_sta); 598 } 599 } 600 601 static u16 602 iwl_mld_get_amsdu_size_of_tid(struct iwl_mld *mld, 603 struct ieee80211_link_sta *link_sta, 604 unsigned int tid) 605 { 606 struct ieee80211_sta *sta = link_sta->sta; 607 struct ieee80211_vif *vif = iwl_mld_sta_from_mac80211(sta)->vif; 608 const u8 tid_to_mac80211_ac[] = { 609 IEEE80211_AC_BE, 610 IEEE80211_AC_BK, 611 IEEE80211_AC_BK, 612 IEEE80211_AC_BE, 613 IEEE80211_AC_VI, 614 IEEE80211_AC_VI, 615 IEEE80211_AC_VO, 616 IEEE80211_AC_VO, 617 }; 618 unsigned int result = link_sta->agg.max_rc_amsdu_len; 619 u8 ac, txf, lmac; 620 621 lockdep_assert_wiphy(mld->wiphy); 622 623 /* Don't send an AMSDU that will be longer than the TXF. 624 * Add a security margin of 256 for the TX command + headers. 625 * We also want to have the start of the next packet inside the 626 * fifo to be able to send bursts. 627 */ 628 629 if (WARN_ON(tid >= ARRAY_SIZE(tid_to_mac80211_ac))) 630 return 0; 631 632 ac = tid_to_mac80211_ac[tid]; 633 634 /* For HE redirect to trigger based fifos */ 635 if (link_sta->he_cap.has_he) 636 ac += 4; 637 638 txf = iwl_mld_mac80211_ac_to_fw_tx_fifo(ac); 639 640 /* Only one link: take the lmac according to the band */ 641 if (hweight16(sta->valid_links) <= 1) { 642 enum nl80211_band band; 643 struct ieee80211_bss_conf *link = 644 wiphy_dereference(mld->wiphy, 645 vif->link_conf[link_sta->link_id]); 646 647 if (WARN_ON(!link || !link->chanreq.oper.chan)) 648 band = NL80211_BAND_2GHZ; 649 else 650 band = link->chanreq.oper.chan->band; 651 lmac = iwl_mld_get_lmac_id(mld, band); 652 653 /* More than one link but with 2 lmacs: take the minimum */ 654 } else if (fw_has_capa(&mld->fw->ucode_capa, 655 IWL_UCODE_TLV_CAPA_CDB_SUPPORT)) { 656 lmac = IWL_LMAC_5G_INDEX; 657 result = min_t(unsigned int, result, 658 mld->fwrt.smem_cfg.lmac[lmac].txfifo_size[txf] - 256); 659 lmac = IWL_LMAC_24G_INDEX; 660 /* More than one link but only one lmac */ 661 } else { 662 lmac = IWL_LMAC_24G_INDEX; 663 } 664 665 return min_t(unsigned int, result, 666 mld->fwrt.smem_cfg.lmac[lmac].txfifo_size[txf] - 256); 667 } 668 669 void iwl_mld_handle_tlc_notif(struct iwl_mld *mld, 670 struct iwl_rx_packet *pkt) 671 { 672 struct iwl_tlc_update_notif *notif = (void *)pkt->data; 673 struct ieee80211_link_sta *link_sta; 674 u32 flags = le32_to_cpu(notif->flags); 675 u32 enabled; 676 u16 size; 677 678 if (IWL_FW_CHECK(mld, notif->sta_id >= mld->fw->ucode_capa.num_stations, 679 "Invalid sta id (%d) in TLC notification\n", 680 notif->sta_id)) 681 return; 682 683 link_sta = wiphy_dereference(mld->wiphy, 684 mld->fw_id_to_link_sta[notif->sta_id]); 685 686 if (WARN(IS_ERR_OR_NULL(link_sta), 687 "link_sta of sta id (%d) doesn't exist\n", notif->sta_id)) 688 return; 689 690 if (flags & IWL_TLC_NOTIF_FLAG_RATE) { 691 struct iwl_mld_link_sta *mld_link_sta = 692 iwl_mld_link_sta_from_mac80211(link_sta); 693 char pretty_rate[100]; 694 695 if (WARN_ON(!mld_link_sta)) 696 return; 697 698 mld_link_sta->last_rate_n_flags = 699 iwl_v3_rate_from_v2_v3(notif->rate, 700 mld->fw_rates_ver_3); 701 702 rs_pretty_print_rate(pretty_rate, sizeof(pretty_rate), 703 mld_link_sta->last_rate_n_flags); 704 IWL_DEBUG_RATE(mld, "TLC notif: new rate = %s\n", pretty_rate); 705 } 706 707 /* We are done processing the notif */ 708 if (!(flags & IWL_TLC_NOTIF_FLAG_AMSDU)) 709 return; 710 711 enabled = le32_to_cpu(notif->amsdu_enabled); 712 size = le32_to_cpu(notif->amsdu_size); 713 714 if (size < 2000) { 715 size = 0; 716 enabled = 0; 717 } 718 719 if (IWL_FW_CHECK(mld, size > link_sta->agg.max_amsdu_len, 720 "Invalid AMSDU len in TLC notif: %d (Max AMSDU len: %d)\n", 721 size, link_sta->agg.max_amsdu_len)) 722 return; 723 724 link_sta->agg.max_rc_amsdu_len = size; 725 726 for (int i = 0; i < IWL_MAX_TID_COUNT; i++) { 727 if (enabled & BIT(i)) 728 link_sta->agg.max_tid_amsdu_len[i] = 729 iwl_mld_get_amsdu_size_of_tid(mld, link_sta, i); 730 else 731 link_sta->agg.max_tid_amsdu_len[i] = 1; 732 } 733 734 ieee80211_sta_recalc_aggregates(link_sta->sta); 735 736 IWL_DEBUG_RATE(mld, 737 "AMSDU update. AMSDU size: %d, AMSDU selected size: %d, AMSDU TID bitmap 0x%X\n", 738 le32_to_cpu(notif->amsdu_size), size, enabled); 739 } 740