1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2 /* 3 * Copyright (C) 2017 Intel Deutschland GmbH 4 * Copyright (C) 2018-2021 Intel Corporation 5 */ 6 #include "rs.h" 7 #include "fw-api.h" 8 #include "sta.h" 9 #include "iwl-op-mode.h" 10 #include "mvm.h" 11 12 static u8 rs_fw_bw_from_sta_bw(struct ieee80211_sta *sta) 13 { 14 switch (sta->bandwidth) { 15 case IEEE80211_STA_RX_BW_160: 16 return IWL_TLC_MNG_CH_WIDTH_160MHZ; 17 case IEEE80211_STA_RX_BW_80: 18 return IWL_TLC_MNG_CH_WIDTH_80MHZ; 19 case IEEE80211_STA_RX_BW_40: 20 return IWL_TLC_MNG_CH_WIDTH_40MHZ; 21 case IEEE80211_STA_RX_BW_20: 22 default: 23 return IWL_TLC_MNG_CH_WIDTH_20MHZ; 24 } 25 } 26 27 static u8 rs_fw_set_active_chains(u8 chains) 28 { 29 u8 fw_chains = 0; 30 31 if (chains & ANT_A) 32 fw_chains |= IWL_TLC_MNG_CHAIN_A_MSK; 33 if (chains & ANT_B) 34 fw_chains |= IWL_TLC_MNG_CHAIN_B_MSK; 35 36 return fw_chains; 37 } 38 39 static u8 rs_fw_sgi_cw_support(struct ieee80211_sta *sta) 40 { 41 struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; 42 struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap; 43 struct ieee80211_sta_he_cap *he_cap = &sta->he_cap; 44 u8 supp = 0; 45 46 if (he_cap->has_he) 47 return 0; 48 49 if (ht_cap->cap & IEEE80211_HT_CAP_SGI_20) 50 supp |= BIT(IWL_TLC_MNG_CH_WIDTH_20MHZ); 51 if (ht_cap->cap & IEEE80211_HT_CAP_SGI_40) 52 supp |= BIT(IWL_TLC_MNG_CH_WIDTH_40MHZ); 53 if (vht_cap->cap & IEEE80211_VHT_CAP_SHORT_GI_80) 54 supp |= BIT(IWL_TLC_MNG_CH_WIDTH_80MHZ); 55 if (vht_cap->cap & IEEE80211_VHT_CAP_SHORT_GI_160) 56 supp |= BIT(IWL_TLC_MNG_CH_WIDTH_160MHZ); 57 58 return supp; 59 } 60 61 static u16 rs_fw_get_config_flags(struct iwl_mvm *mvm, 62 struct ieee80211_sta *sta, 63 struct ieee80211_supported_band *sband) 64 { 65 struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; 66 struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap; 67 struct ieee80211_sta_he_cap *he_cap = &sta->he_cap; 68 bool vht_ena = vht_cap->vht_supported; 69 u16 flags = 0; 70 71 /* get STBC flags */ 72 if (mvm->cfg->ht_params->stbc && 73 (num_of_ant(iwl_mvm_get_valid_tx_ant(mvm)) > 1)) { 74 if (he_cap->has_he && he_cap->he_cap_elem.phy_cap_info[2] & 75 IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ) 76 flags |= IWL_TLC_MNG_CFG_FLAGS_STBC_MSK; 77 else if (vht_cap->cap & IEEE80211_VHT_CAP_RXSTBC_MASK) 78 flags |= IWL_TLC_MNG_CFG_FLAGS_STBC_MSK; 79 else if (ht_cap->cap & IEEE80211_HT_CAP_RX_STBC) 80 flags |= IWL_TLC_MNG_CFG_FLAGS_STBC_MSK; 81 } 82 83 if (mvm->cfg->ht_params->ldpc && 84 ((ht_cap->cap & IEEE80211_HT_CAP_LDPC_CODING) || 85 (vht_ena && (vht_cap->cap & IEEE80211_VHT_CAP_RXLDPC)))) 86 flags |= IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK; 87 88 /* consider LDPC support in case of HE */ 89 if (he_cap->has_he && (he_cap->he_cap_elem.phy_cap_info[1] & 90 IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD)) 91 flags |= IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK; 92 93 if (sband->iftype_data && sband->iftype_data->he_cap.has_he && 94 !(sband->iftype_data->he_cap.he_cap_elem.phy_cap_info[1] & 95 IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD)) 96 flags &= ~IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK; 97 98 if (he_cap->has_he && 99 (he_cap->he_cap_elem.phy_cap_info[3] & 100 IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_MASK)) 101 flags |= IWL_TLC_MNG_CFG_FLAGS_HE_DCM_NSS_1_MSK; 102 103 return flags; 104 } 105 106 static 107 int rs_fw_vht_highest_rx_mcs_index(const struct ieee80211_sta_vht_cap *vht_cap, 108 int nss) 109 { 110 u16 rx_mcs = le16_to_cpu(vht_cap->vht_mcs.rx_mcs_map) & 111 (0x3 << (2 * (nss - 1))); 112 rx_mcs >>= (2 * (nss - 1)); 113 114 switch (rx_mcs) { 115 case IEEE80211_VHT_MCS_SUPPORT_0_7: 116 return IWL_TLC_MNG_HT_RATE_MCS7; 117 case IEEE80211_VHT_MCS_SUPPORT_0_8: 118 return IWL_TLC_MNG_HT_RATE_MCS8; 119 case IEEE80211_VHT_MCS_SUPPORT_0_9: 120 return IWL_TLC_MNG_HT_RATE_MCS9; 121 default: 122 WARN_ON_ONCE(1); 123 break; 124 } 125 126 return 0; 127 } 128 129 static void 130 rs_fw_vht_set_enabled_rates(const struct ieee80211_sta *sta, 131 const struct ieee80211_sta_vht_cap *vht_cap, 132 struct iwl_tlc_config_cmd_v4 *cmd) 133 { 134 u16 supp; 135 int i, highest_mcs; 136 u8 max_nss = sta->rx_nss; 137 struct ieee80211_vht_cap ieee_vht_cap = { 138 .vht_cap_info = cpu_to_le32(vht_cap->cap), 139 .supp_mcs = vht_cap->vht_mcs, 140 }; 141 142 /* the station support only a single receive chain */ 143 if (sta->smps_mode == IEEE80211_SMPS_STATIC) 144 max_nss = 1; 145 146 for (i = 0; i < max_nss && i < IWL_TLC_NSS_MAX; i++) { 147 int nss = i + 1; 148 149 highest_mcs = rs_fw_vht_highest_rx_mcs_index(vht_cap, nss); 150 if (!highest_mcs) 151 continue; 152 153 supp = BIT(highest_mcs + 1) - 1; 154 if (sta->bandwidth == IEEE80211_STA_RX_BW_20) 155 supp &= ~BIT(IWL_TLC_MNG_HT_RATE_MCS9); 156 157 cmd->ht_rates[i][IWL_TLC_MCS_PER_BW_80] = cpu_to_le16(supp); 158 /* 159 * Check if VHT extended NSS indicates that the bandwidth/NSS 160 * configuration is supported - only for MCS 0 since we already 161 * decoded the MCS bits anyway ourselves. 162 */ 163 if (sta->bandwidth == IEEE80211_STA_RX_BW_160 && 164 ieee80211_get_vht_max_nss(&ieee_vht_cap, 165 IEEE80211_VHT_CHANWIDTH_160MHZ, 166 0, true, nss) >= nss) 167 cmd->ht_rates[i][IWL_TLC_MCS_PER_BW_160] = 168 cmd->ht_rates[i][IWL_TLC_MCS_PER_BW_80]; 169 } 170 } 171 172 static u16 rs_fw_he_ieee80211_mcs_to_rs_mcs(u16 mcs) 173 { 174 switch (mcs) { 175 case IEEE80211_HE_MCS_SUPPORT_0_7: 176 return BIT(IWL_TLC_MNG_HT_RATE_MCS7 + 1) - 1; 177 case IEEE80211_HE_MCS_SUPPORT_0_9: 178 return BIT(IWL_TLC_MNG_HT_RATE_MCS9 + 1) - 1; 179 case IEEE80211_HE_MCS_SUPPORT_0_11: 180 return BIT(IWL_TLC_MNG_HT_RATE_MCS11 + 1) - 1; 181 case IEEE80211_HE_MCS_NOT_SUPPORTED: 182 return 0; 183 } 184 185 WARN(1, "invalid HE MCS %d\n", mcs); 186 return 0; 187 } 188 189 static void 190 rs_fw_he_set_enabled_rates(const struct ieee80211_sta *sta, 191 struct ieee80211_supported_band *sband, 192 struct iwl_tlc_config_cmd_v4 *cmd) 193 { 194 const struct ieee80211_sta_he_cap *he_cap = &sta->he_cap; 195 u16 mcs_160 = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_160); 196 u16 mcs_80 = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_80); 197 u16 tx_mcs_80 = 198 le16_to_cpu(sband->iftype_data->he_cap.he_mcs_nss_supp.tx_mcs_80); 199 u16 tx_mcs_160 = 200 le16_to_cpu(sband->iftype_data->he_cap.he_mcs_nss_supp.tx_mcs_160); 201 int i; 202 u8 nss = sta->rx_nss; 203 204 /* the station support only a single receive chain */ 205 if (sta->smps_mode == IEEE80211_SMPS_STATIC) 206 nss = 1; 207 208 for (i = 0; i < nss && i < IWL_TLC_NSS_MAX; i++) { 209 u16 _mcs_160 = (mcs_160 >> (2 * i)) & 0x3; 210 u16 _mcs_80 = (mcs_80 >> (2 * i)) & 0x3; 211 u16 _tx_mcs_160 = (tx_mcs_160 >> (2 * i)) & 0x3; 212 u16 _tx_mcs_80 = (tx_mcs_80 >> (2 * i)) & 0x3; 213 214 /* If one side doesn't support - mark both as not supporting */ 215 if (_mcs_80 == IEEE80211_HE_MCS_NOT_SUPPORTED || 216 _tx_mcs_80 == IEEE80211_HE_MCS_NOT_SUPPORTED) { 217 _mcs_80 = IEEE80211_HE_MCS_NOT_SUPPORTED; 218 _tx_mcs_80 = IEEE80211_HE_MCS_NOT_SUPPORTED; 219 } 220 if (_mcs_80 > _tx_mcs_80) 221 _mcs_80 = _tx_mcs_80; 222 cmd->ht_rates[i][IWL_TLC_MCS_PER_BW_80] = 223 cpu_to_le16(rs_fw_he_ieee80211_mcs_to_rs_mcs(_mcs_80)); 224 225 /* If one side doesn't support - mark both as not supporting */ 226 if (_mcs_160 == IEEE80211_HE_MCS_NOT_SUPPORTED || 227 _tx_mcs_160 == IEEE80211_HE_MCS_NOT_SUPPORTED) { 228 _mcs_160 = IEEE80211_HE_MCS_NOT_SUPPORTED; 229 _tx_mcs_160 = IEEE80211_HE_MCS_NOT_SUPPORTED; 230 } 231 if (_mcs_160 > _tx_mcs_160) 232 _mcs_160 = _tx_mcs_160; 233 cmd->ht_rates[i][IWL_TLC_MCS_PER_BW_160] = 234 cpu_to_le16(rs_fw_he_ieee80211_mcs_to_rs_mcs(_mcs_160)); 235 } 236 } 237 238 static void rs_fw_set_supp_rates(struct ieee80211_sta *sta, 239 struct ieee80211_supported_band *sband, 240 struct iwl_tlc_config_cmd_v4 *cmd) 241 { 242 int i; 243 u16 supp = 0; 244 unsigned long tmp; /* must be unsigned long for for_each_set_bit */ 245 const struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; 246 const struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap; 247 const struct ieee80211_sta_he_cap *he_cap = &sta->he_cap; 248 249 /* non HT rates */ 250 tmp = sta->supp_rates[sband->band]; 251 for_each_set_bit(i, &tmp, BITS_PER_LONG) 252 supp |= BIT(sband->bitrates[i].hw_value); 253 254 cmd->non_ht_rates = cpu_to_le16(supp); 255 cmd->mode = IWL_TLC_MNG_MODE_NON_HT; 256 257 /* HT/VHT rates */ 258 if (he_cap->has_he) { 259 cmd->mode = IWL_TLC_MNG_MODE_HE; 260 rs_fw_he_set_enabled_rates(sta, sband, cmd); 261 } else if (vht_cap->vht_supported) { 262 cmd->mode = IWL_TLC_MNG_MODE_VHT; 263 rs_fw_vht_set_enabled_rates(sta, vht_cap, cmd); 264 } else if (ht_cap->ht_supported) { 265 cmd->mode = IWL_TLC_MNG_MODE_HT; 266 cmd->ht_rates[IWL_TLC_NSS_1][IWL_TLC_MCS_PER_BW_80] = 267 cpu_to_le16(ht_cap->mcs.rx_mask[0]); 268 269 /* the station support only a single receive chain */ 270 if (sta->smps_mode == IEEE80211_SMPS_STATIC) 271 cmd->ht_rates[IWL_TLC_NSS_2][IWL_TLC_MCS_PER_BW_80] = 272 0; 273 else 274 cmd->ht_rates[IWL_TLC_NSS_2][IWL_TLC_MCS_PER_BW_80] = 275 cpu_to_le16(ht_cap->mcs.rx_mask[1]); 276 } 277 } 278 279 void iwl_mvm_tlc_update_notif(struct iwl_mvm *mvm, 280 struct iwl_rx_cmd_buffer *rxb) 281 { 282 struct iwl_rx_packet *pkt = rxb_addr(rxb); 283 struct iwl_tlc_update_notif *notif; 284 struct ieee80211_sta *sta; 285 struct iwl_mvm_sta *mvmsta; 286 struct iwl_lq_sta_rs_fw *lq_sta; 287 u32 flags; 288 289 rcu_read_lock(); 290 291 notif = (void *)pkt->data; 292 sta = rcu_dereference(mvm->fw_id_to_mac_id[notif->sta_id]); 293 if (IS_ERR_OR_NULL(sta)) { 294 /* can happen in remove station flow where mvm removed internally 295 * the station before removing from FW 296 */ 297 IWL_DEBUG_RATE(mvm, 298 "Invalid mvm RCU pointer for sta id (%d) in TLC notification\n", 299 notif->sta_id); 300 goto out; 301 } 302 303 mvmsta = iwl_mvm_sta_from_mac80211(sta); 304 305 if (!mvmsta) { 306 IWL_ERR(mvm, "Invalid sta id (%d) in FW TLC notification\n", 307 notif->sta_id); 308 goto out; 309 } 310 311 flags = le32_to_cpu(notif->flags); 312 313 lq_sta = &mvmsta->lq_sta.rs_fw; 314 315 if (flags & IWL_TLC_NOTIF_FLAG_RATE) { 316 char pretty_rate[100]; 317 318 if (iwl_fw_lookup_notif_ver(mvm->fw, DATA_PATH_GROUP, 319 TLC_MNG_UPDATE_NOTIF, 0) < 3) { 320 rs_pretty_print_rate_v1(pretty_rate, 321 sizeof(pretty_rate), 322 le32_to_cpu(notif->rate)); 323 IWL_DEBUG_RATE(mvm, 324 "Got rate in old format. Rate: %s. Converting.\n", 325 pretty_rate); 326 lq_sta->last_rate_n_flags = 327 iwl_new_rate_from_v1(le32_to_cpu(notif->rate)); 328 } else { 329 lq_sta->last_rate_n_flags = le32_to_cpu(notif->rate); 330 } 331 rs_pretty_print_rate(pretty_rate, sizeof(pretty_rate), 332 lq_sta->last_rate_n_flags); 333 IWL_DEBUG_RATE(mvm, "new rate: %s\n", pretty_rate); 334 } 335 336 if (flags & IWL_TLC_NOTIF_FLAG_AMSDU && !mvmsta->orig_amsdu_len) { 337 u16 size = le32_to_cpu(notif->amsdu_size); 338 int i; 339 340 if (sta->max_amsdu_len < size) { 341 /* 342 * In debug sta->max_amsdu_len < size 343 * so also check with orig_amsdu_len which holds the 344 * original data before debugfs changed the value 345 */ 346 WARN_ON(mvmsta->orig_amsdu_len < size); 347 goto out; 348 } 349 350 mvmsta->amsdu_enabled = le32_to_cpu(notif->amsdu_enabled); 351 mvmsta->max_amsdu_len = size; 352 sta->max_rc_amsdu_len = mvmsta->max_amsdu_len; 353 354 for (i = 0; i < IWL_MAX_TID_COUNT; i++) { 355 if (mvmsta->amsdu_enabled & BIT(i)) 356 sta->max_tid_amsdu_len[i] = 357 iwl_mvm_max_amsdu_size(mvm, sta, i); 358 else 359 /* 360 * Not so elegant, but this will effectively 361 * prevent AMSDU on this TID 362 */ 363 sta->max_tid_amsdu_len[i] = 1; 364 } 365 366 IWL_DEBUG_RATE(mvm, 367 "AMSDU update. AMSDU size: %d, AMSDU selected size: %d, AMSDU TID bitmap 0x%X\n", 368 le32_to_cpu(notif->amsdu_size), size, 369 mvmsta->amsdu_enabled); 370 } 371 out: 372 rcu_read_unlock(); 373 } 374 375 u16 rs_fw_get_max_amsdu_len(struct ieee80211_sta *sta) 376 { 377 struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); 378 const struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap; 379 const struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; 380 381 if (mvmsta->vif->bss_conf.chandef.chan->band == NL80211_BAND_6GHZ) { 382 switch (le16_get_bits(sta->he_6ghz_capa.capa, 383 IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LEN)) { 384 case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454: 385 return IEEE80211_MAX_MPDU_LEN_VHT_11454; 386 case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991: 387 return IEEE80211_MAX_MPDU_LEN_VHT_7991; 388 default: 389 return IEEE80211_MAX_MPDU_LEN_VHT_3895; 390 } 391 } else 392 if (vht_cap->vht_supported) { 393 switch (vht_cap->cap & IEEE80211_VHT_CAP_MAX_MPDU_MASK) { 394 case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454: 395 return IEEE80211_MAX_MPDU_LEN_VHT_11454; 396 case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991: 397 return IEEE80211_MAX_MPDU_LEN_VHT_7991; 398 default: 399 return IEEE80211_MAX_MPDU_LEN_VHT_3895; 400 } 401 } else if (ht_cap->ht_supported) { 402 if (ht_cap->cap & IEEE80211_HT_CAP_MAX_AMSDU) 403 /* 404 * agg is offloaded so we need to assume that agg 405 * are enabled and max mpdu in ampdu is 4095 406 * (spec 802.11-2016 9.3.2.1) 407 */ 408 return IEEE80211_MAX_MPDU_LEN_HT_BA; 409 else 410 return IEEE80211_MAX_MPDU_LEN_HT_3839; 411 } 412 413 /* in legacy mode no amsdu is enabled so return zero */ 414 return 0; 415 } 416 417 void rs_fw_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, 418 enum nl80211_band band, bool update) 419 { 420 struct ieee80211_hw *hw = mvm->hw; 421 struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); 422 struct iwl_lq_sta_rs_fw *lq_sta = &mvmsta->lq_sta.rs_fw; 423 u32 cmd_id = iwl_cmd_id(TLC_MNG_CONFIG_CMD, DATA_PATH_GROUP, 0); 424 struct ieee80211_supported_band *sband = hw->wiphy->bands[band]; 425 u16 max_amsdu_len = rs_fw_get_max_amsdu_len(sta); 426 struct iwl_tlc_config_cmd_v4 cfg_cmd = { 427 .sta_id = mvmsta->sta_id, 428 .max_ch_width = update ? 429 rs_fw_bw_from_sta_bw(sta) : RATE_MCS_CHAN_WIDTH_20, 430 .flags = cpu_to_le16(rs_fw_get_config_flags(mvm, sta, sband)), 431 .chains = rs_fw_set_active_chains(iwl_mvm_get_valid_tx_ant(mvm)), 432 .sgi_ch_width_supp = rs_fw_sgi_cw_support(sta), 433 .max_mpdu_len = iwl_mvm_is_csum_supported(mvm) ? 434 cpu_to_le16(max_amsdu_len) : 0, 435 }; 436 int ret; 437 int cmd_ver; 438 439 memset(lq_sta, 0, offsetof(typeof(*lq_sta), pers)); 440 441 #ifdef CONFIG_IWLWIFI_DEBUGFS 442 iwl_mvm_reset_frame_stats(mvm); 443 #endif 444 rs_fw_set_supp_rates(sta, sband, &cfg_cmd); 445 446 /* 447 * since TLC offload works with one mode we can assume 448 * that only vht/ht is used and also set it as station max amsdu 449 */ 450 sta->max_amsdu_len = max_amsdu_len; 451 452 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, DATA_PATH_GROUP, 453 TLC_MNG_CONFIG_CMD, 0); 454 if (cmd_ver == 4) { 455 ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, CMD_ASYNC, 456 sizeof(cfg_cmd), &cfg_cmd); 457 } else if (cmd_ver < 4) { 458 struct iwl_tlc_config_cmd_v3 cfg_cmd_v3 = { 459 .sta_id = cfg_cmd.sta_id, 460 .max_ch_width = cfg_cmd.max_ch_width, 461 .mode = cfg_cmd.mode, 462 .chains = cfg_cmd.chains, 463 .amsdu = !!cfg_cmd.max_mpdu_len, 464 .flags = cfg_cmd.flags, 465 .non_ht_rates = cfg_cmd.non_ht_rates, 466 .ht_rates[0][0] = cfg_cmd.ht_rates[0][0], 467 .ht_rates[0][1] = cfg_cmd.ht_rates[0][1], 468 .ht_rates[1][0] = cfg_cmd.ht_rates[1][0], 469 .ht_rates[1][1] = cfg_cmd.ht_rates[1][1], 470 .sgi_ch_width_supp = cfg_cmd.sgi_ch_width_supp, 471 .max_mpdu_len = cfg_cmd.max_mpdu_len, 472 }; 473 474 u16 cmd_size = sizeof(cfg_cmd_v3); 475 476 /* In old versions of the API the struct is 4 bytes smaller */ 477 if (iwl_fw_lookup_cmd_ver(mvm->fw, DATA_PATH_GROUP, 478 TLC_MNG_CONFIG_CMD, 0) < 3) 479 cmd_size -= 4; 480 481 ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, CMD_ASYNC, cmd_size, 482 &cfg_cmd_v3); 483 } else { 484 ret = -EINVAL; 485 } 486 487 if (ret) 488 IWL_ERR(mvm, "Failed to send rate scale config (%d)\n", ret); 489 } 490 491 int rs_fw_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta, 492 bool enable) 493 { 494 /* TODO: need to introduce a new FW cmd since LQ cmd is not relevant */ 495 IWL_DEBUG_RATE(mvm, "tx protection - not implemented yet.\n"); 496 return 0; 497 } 498 499 void iwl_mvm_rs_add_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta) 500 { 501 struct iwl_lq_sta_rs_fw *lq_sta = &mvmsta->lq_sta.rs_fw; 502 503 IWL_DEBUG_RATE(mvm, "create station rate scale window\n"); 504 505 lq_sta->pers.drv = mvm; 506 lq_sta->pers.sta_id = mvmsta->sta_id; 507 lq_sta->pers.chains = 0; 508 memset(lq_sta->pers.chain_signal, 0, sizeof(lq_sta->pers.chain_signal)); 509 lq_sta->pers.last_rssi = S8_MIN; 510 lq_sta->last_rate_n_flags = 0; 511 512 #ifdef CONFIG_MAC80211_DEBUGFS 513 lq_sta->pers.dbg_fixed_rate = 0; 514 #endif 515 } 516