1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2 /* 3 * Copyright (C) 2022 - 2024 Intel Corporation 4 */ 5 #include "mvm.h" 6 #include "time-event.h" 7 8 #define HANDLE_ESR_REASONS(HOW) \ 9 HOW(BLOCKED_PREVENTION) \ 10 HOW(BLOCKED_WOWLAN) \ 11 HOW(BLOCKED_TPT) \ 12 HOW(BLOCKED_FW) \ 13 HOW(BLOCKED_NON_BSS) \ 14 HOW(BLOCKED_ROC) \ 15 HOW(BLOCKED_TMP_NON_BSS) \ 16 HOW(EXIT_MISSED_BEACON) \ 17 HOW(EXIT_LOW_RSSI) \ 18 HOW(EXIT_COEX) \ 19 HOW(EXIT_BANDWIDTH) \ 20 HOW(EXIT_CSA) \ 21 HOW(EXIT_LINK_USAGE) 22 23 static const char *const iwl_mvm_esr_states_names[] = { 24 #define NAME_ENTRY(x) [ilog2(IWL_MVM_ESR_##x)] = #x, 25 HANDLE_ESR_REASONS(NAME_ENTRY) 26 }; 27 28 const char *iwl_get_esr_state_string(enum iwl_mvm_esr_state state) 29 { 30 int offs = ilog2(state); 31 32 if (offs >= ARRAY_SIZE(iwl_mvm_esr_states_names) || 33 !iwl_mvm_esr_states_names[offs]) 34 return "UNKNOWN"; 35 36 return iwl_mvm_esr_states_names[offs]; 37 } 38 39 static void iwl_mvm_print_esr_state(struct iwl_mvm *mvm, u32 mask) 40 { 41 #define NAME_FMT(x) "%s" 42 #define NAME_PR(x) (mask & IWL_MVM_ESR_##x) ? "[" #x "]" : "", 43 IWL_DEBUG_INFO(mvm, 44 "EMLSR state = " HANDLE_ESR_REASONS(NAME_FMT) 45 " (0x%x)\n", 46 HANDLE_ESR_REASONS(NAME_PR) 47 mask); 48 #undef NAME_FMT 49 #undef NAME_PR 50 } 51 52 static int iwl_mvm_link_cmd_send(struct iwl_mvm *mvm, 53 struct iwl_link_config_cmd *cmd, 54 enum iwl_ctxt_action action) 55 { 56 int ret; 57 58 cmd->action = cpu_to_le32(action); 59 ret = iwl_mvm_send_cmd_pdu(mvm, 60 WIDE_ID(MAC_CONF_GROUP, LINK_CONFIG_CMD), 0, 61 sizeof(*cmd), cmd); 62 if (ret) 63 IWL_ERR(mvm, "Failed to send LINK_CONFIG_CMD (action:%d): %d\n", 64 action, ret); 65 return ret; 66 } 67 68 void iwl_mvm_set_link_fw_id(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 69 struct ieee80211_bss_conf *link_conf) 70 { 71 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 72 struct iwl_mvm_vif_link_info *link_info = 73 mvmvif->link[link_conf->link_id]; 74 75 if (link_info->fw_link_id == IWL_MVM_FW_LINK_ID_INVALID) 76 link_info->fw_link_id = mvmvif->id; 77 } 78 79 int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 80 struct ieee80211_bss_conf *link_conf) 81 { 82 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 83 unsigned int link_id = link_conf->link_id; 84 struct iwl_mvm_vif_link_info *link_info = mvmvif->link[link_id]; 85 struct iwl_link_config_cmd cmd = {}; 86 unsigned int cmd_id = WIDE_ID(MAC_CONF_GROUP, LINK_CONFIG_CMD); 87 u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id, 1); 88 89 if (WARN_ON_ONCE(!link_info)) 90 return -EINVAL; 91 92 iwl_mvm_set_link_fw_id(mvm, vif, link_conf); 93 94 /* Update SF - Disable if needed. if this fails, SF might still be on 95 * while many macs are bound, which is forbidden - so fail the binding. 96 */ 97 if (iwl_mvm_sf_update(mvm, vif, false)) 98 return -EINVAL; 99 100 cmd.link_id = cpu_to_le32(link_info->fw_link_id); 101 cmd.mac_id = cpu_to_le32(mvmvif->id); 102 cmd.spec_link_id = link_conf->link_id; 103 WARN_ON_ONCE(link_info->phy_ctxt); 104 cmd.phy_id = cpu_to_le32(FW_CTXT_INVALID); 105 106 memcpy(cmd.local_link_addr, link_conf->addr, ETH_ALEN); 107 108 if (vif->type == NL80211_IFTYPE_ADHOC && link_conf->bssid) 109 memcpy(cmd.ibss_bssid_addr, link_conf->bssid, ETH_ALEN); 110 111 if (cmd_ver < 2) 112 cmd.listen_lmac = cpu_to_le32(link_info->listen_lmac); 113 114 return iwl_mvm_link_cmd_send(mvm, &cmd, FW_CTXT_ACTION_ADD); 115 } 116 117 struct iwl_mvm_esr_iter_data { 118 struct ieee80211_vif *vif; 119 unsigned int link_id; 120 bool lift_block; 121 }; 122 123 static void iwl_mvm_esr_vif_iterator(void *_data, u8 *mac, 124 struct ieee80211_vif *vif) 125 { 126 struct iwl_mvm_esr_iter_data *data = _data; 127 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 128 int link_id; 129 130 if (ieee80211_vif_type_p2p(vif) == NL80211_IFTYPE_STATION) 131 return; 132 133 for_each_mvm_vif_valid_link(mvmvif, link_id) { 134 struct iwl_mvm_vif_link_info *link_info = 135 mvmvif->link[link_id]; 136 if (vif == data->vif && link_id == data->link_id) 137 continue; 138 if (link_info->active) 139 data->lift_block = false; 140 } 141 } 142 143 int iwl_mvm_esr_non_bss_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 144 unsigned int link_id, bool active) 145 { 146 /* An active link of a non-station vif blocks EMLSR. Upon activation 147 * block EMLSR on the bss vif. Upon deactivation, check if this link 148 * was the last non-station link active, and if so unblock the bss vif 149 */ 150 struct ieee80211_vif *bss_vif = iwl_mvm_get_bss_vif(mvm); 151 struct iwl_mvm_esr_iter_data data = { 152 .vif = vif, 153 .link_id = link_id, 154 .lift_block = true, 155 }; 156 157 if (IS_ERR_OR_NULL(bss_vif)) 158 return 0; 159 160 if (active) 161 return iwl_mvm_block_esr_sync(mvm, bss_vif, 162 IWL_MVM_ESR_BLOCKED_NON_BSS); 163 164 ieee80211_iterate_active_interfaces(mvm->hw, 165 IEEE80211_IFACE_ITER_NORMAL, 166 iwl_mvm_esr_vif_iterator, &data); 167 if (data.lift_block) { 168 mutex_lock(&mvm->mutex); 169 iwl_mvm_unblock_esr(mvm, bss_vif, IWL_MVM_ESR_BLOCKED_NON_BSS); 170 mutex_unlock(&mvm->mutex); 171 } 172 173 return 0; 174 } 175 176 int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 177 struct ieee80211_bss_conf *link_conf, 178 u32 changes, bool active) 179 { 180 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 181 unsigned int link_id = link_conf->link_id; 182 struct iwl_mvm_vif_link_info *link_info = mvmvif->link[link_id]; 183 struct iwl_mvm_phy_ctxt *phyctxt; 184 struct iwl_link_config_cmd cmd = {}; 185 u32 ht_flag, flags = 0, flags_mask = 0; 186 int ret; 187 unsigned int cmd_id = WIDE_ID(MAC_CONF_GROUP, LINK_CONFIG_CMD); 188 u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id, 1); 189 190 if (WARN_ON_ONCE(!link_info || 191 link_info->fw_link_id == IWL_MVM_FW_LINK_ID_INVALID)) 192 return -EINVAL; 193 194 if (changes & LINK_CONTEXT_MODIFY_ACTIVE) { 195 /* When activating a link, phy context should be valid; 196 * when deactivating a link, it also should be valid since 197 * the link was active before. So, do nothing in this case. 198 * Since a link is added first with FW_CTXT_INVALID, then we 199 * can get here in case it's removed before it was activated. 200 */ 201 if (!link_info->phy_ctxt) 202 return 0; 203 204 /* Catch early if driver tries to activate or deactivate a link 205 * twice. 206 */ 207 WARN_ON_ONCE(active == link_info->active); 208 209 /* When deactivating a link session protection should 210 * be stopped. Also let the firmware know if we can't Tx. 211 */ 212 if (!active && vif->type == NL80211_IFTYPE_STATION) { 213 iwl_mvm_stop_session_protection(mvm, vif); 214 if (link_info->csa_block_tx) { 215 cmd.block_tx = 1; 216 link_info->csa_block_tx = false; 217 } 218 } 219 } 220 221 cmd.link_id = cpu_to_le32(link_info->fw_link_id); 222 223 /* The phy_id, link address and listen_lmac can be modified only until 224 * the link becomes active, otherwise they will be ignored. 225 */ 226 phyctxt = link_info->phy_ctxt; 227 if (phyctxt) 228 cmd.phy_id = cpu_to_le32(phyctxt->id); 229 else 230 cmd.phy_id = cpu_to_le32(FW_CTXT_INVALID); 231 cmd.mac_id = cpu_to_le32(mvmvif->id); 232 233 memcpy(cmd.local_link_addr, link_conf->addr, ETH_ALEN); 234 235 cmd.active = cpu_to_le32(active); 236 237 if (vif->type == NL80211_IFTYPE_ADHOC && link_conf->bssid) 238 memcpy(cmd.ibss_bssid_addr, link_conf->bssid, ETH_ALEN); 239 240 iwl_mvm_set_fw_basic_rates(mvm, vif, link_info, 241 &cmd.cck_rates, &cmd.ofdm_rates); 242 243 cmd.cck_short_preamble = cpu_to_le32(link_conf->use_short_preamble); 244 cmd.short_slot = cpu_to_le32(link_conf->use_short_slot); 245 246 /* The fw does not distinguish between ht and fat */ 247 ht_flag = LINK_PROT_FLG_HT_PROT | LINK_PROT_FLG_FAT_PROT; 248 iwl_mvm_set_fw_protection_flags(mvm, vif, link_conf, 249 &cmd.protection_flags, 250 ht_flag, LINK_PROT_FLG_TGG_PROTECT); 251 252 iwl_mvm_set_fw_qos_params(mvm, vif, link_conf, cmd.ac, 253 &cmd.qos_flags); 254 255 256 cmd.bi = cpu_to_le32(link_conf->beacon_int); 257 cmd.dtim_interval = cpu_to_le32(link_conf->beacon_int * 258 link_conf->dtim_period); 259 260 if (!link_conf->he_support || iwlwifi_mod_params.disable_11ax || 261 (vif->type == NL80211_IFTYPE_STATION && !vif->cfg.assoc)) { 262 changes &= ~LINK_CONTEXT_MODIFY_HE_PARAMS; 263 goto send_cmd; 264 } 265 266 cmd.htc_trig_based_pkt_ext = link_conf->htc_trig_based_pkt_ext; 267 268 if (link_conf->uora_exists) { 269 cmd.rand_alloc_ecwmin = 270 link_conf->uora_ocw_range & 0x7; 271 cmd.rand_alloc_ecwmax = 272 (link_conf->uora_ocw_range >> 3) & 0x7; 273 } 274 275 /* ap_sta may be NULL if we're disconnecting */ 276 if (changes & LINK_CONTEXT_MODIFY_HE_PARAMS && mvmvif->ap_sta) { 277 struct ieee80211_link_sta *link_sta = 278 link_sta_dereference_check(mvmvif->ap_sta, link_id); 279 280 if (!WARN_ON(!link_sta) && link_sta->he_cap.has_he && 281 link_sta->he_cap.he_cap_elem.mac_cap_info[5] & 282 IEEE80211_HE_MAC_CAP5_OM_CTRL_UL_MU_DATA_DIS_RX) 283 cmd.ul_mu_data_disable = 1; 284 } 285 286 /* TODO how to set ndp_fdbk_buff_th_exp? */ 287 288 if (iwl_mvm_set_fw_mu_edca_params(mvm, mvmvif->link[link_id], 289 &cmd.trig_based_txf[0])) { 290 flags |= LINK_FLG_MU_EDCA_CW; 291 flags_mask |= LINK_FLG_MU_EDCA_CW; 292 } 293 294 if (changes & LINK_CONTEXT_MODIFY_EHT_PARAMS) { 295 struct ieee80211_chanctx_conf *ctx; 296 struct cfg80211_chan_def *def = NULL; 297 298 rcu_read_lock(); 299 ctx = rcu_dereference(link_conf->chanctx_conf); 300 if (ctx) 301 def = iwl_mvm_chanctx_def(mvm, ctx); 302 303 if (iwlwifi_mod_params.disable_11be || 304 !link_conf->eht_support || !def || 305 iwl_fw_lookup_cmd_ver(mvm->fw, PHY_CONTEXT_CMD, 1) >= 6) 306 changes &= ~LINK_CONTEXT_MODIFY_EHT_PARAMS; 307 else 308 cmd.puncture_mask = cpu_to_le16(def->punctured); 309 rcu_read_unlock(); 310 } 311 312 cmd.bss_color = link_conf->he_bss_color.color; 313 314 if (!link_conf->he_bss_color.enabled) { 315 flags |= LINK_FLG_BSS_COLOR_DIS; 316 flags_mask |= LINK_FLG_BSS_COLOR_DIS; 317 } 318 319 cmd.frame_time_rts_th = cpu_to_le16(link_conf->frame_time_rts_th); 320 321 /* Block 26-tone RU OFDMA transmissions */ 322 if (link_info->he_ru_2mhz_block) { 323 flags |= LINK_FLG_RU_2MHZ_BLOCK; 324 flags_mask |= LINK_FLG_RU_2MHZ_BLOCK; 325 } 326 327 if (link_conf->nontransmitted) { 328 ether_addr_copy(cmd.ref_bssid_addr, 329 link_conf->transmitter_bssid); 330 cmd.bssid_index = link_conf->bssid_index; 331 } 332 333 send_cmd: 334 cmd.modify_mask = cpu_to_le32(changes); 335 cmd.flags = cpu_to_le32(flags); 336 if (cmd_ver < 6) 337 cmd.flags_mask = cpu_to_le32(flags_mask); 338 cmd.spec_link_id = link_conf->link_id; 339 if (cmd_ver < 2) 340 cmd.listen_lmac = cpu_to_le32(link_info->listen_lmac); 341 342 ret = iwl_mvm_link_cmd_send(mvm, &cmd, FW_CTXT_ACTION_MODIFY); 343 if (!ret && (changes & LINK_CONTEXT_MODIFY_ACTIVE)) 344 link_info->active = active; 345 346 return ret; 347 } 348 349 int iwl_mvm_remove_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 350 struct ieee80211_bss_conf *link_conf) 351 { 352 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 353 unsigned int link_id = link_conf->link_id; 354 struct iwl_mvm_vif_link_info *link_info = mvmvif->link[link_id]; 355 struct iwl_link_config_cmd cmd = {}; 356 int ret; 357 358 cmd.link_id = cpu_to_le32(link_info->fw_link_id); 359 link_info->fw_link_id = IWL_MVM_FW_LINK_ID_INVALID; 360 cmd.spec_link_id = link_conf->link_id; 361 cmd.phy_id = cpu_to_le32(FW_CTXT_INVALID); 362 363 ret = iwl_mvm_link_cmd_send(mvm, &cmd, FW_CTXT_ACTION_REMOVE); 364 365 if (!ret && iwl_mvm_sf_update(mvm, vif, true)) 366 IWL_ERR(mvm, "Failed to update SF state\n"); 367 368 return ret; 369 } 370 371 /* link should be deactivated before removal, so in most cases we need to 372 * perform these two operations together 373 */ 374 int iwl_mvm_disable_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 375 struct ieee80211_bss_conf *link_conf) 376 { 377 int ret; 378 379 ret = iwl_mvm_link_changed(mvm, vif, link_conf, 380 LINK_CONTEXT_MODIFY_ACTIVE, false); 381 if (ret) 382 return ret; 383 384 ret = iwl_mvm_remove_link(mvm, vif, link_conf); 385 if (ret) 386 return ret; 387 388 return ret; 389 } 390 391 struct iwl_mvm_rssi_to_grade { 392 s8 rssi[2]; 393 u16 grade; 394 }; 395 396 #define RSSI_TO_GRADE_LINE(_lb, _hb_uhb, _grade) \ 397 { \ 398 .rssi = {_lb, _hb_uhb}, \ 399 .grade = _grade \ 400 } 401 402 /* 403 * This array must be sorted by increasing RSSI for proper functionality. 404 * The grades are actually estimated throughput, represented as fixed-point 405 * with a scale factor of 1/10. 406 */ 407 static const struct iwl_mvm_rssi_to_grade rssi_to_grade_map[] = { 408 RSSI_TO_GRADE_LINE(-85, -89, 177), 409 RSSI_TO_GRADE_LINE(-83, -86, 344), 410 RSSI_TO_GRADE_LINE(-82, -85, 516), 411 RSSI_TO_GRADE_LINE(-80, -83, 688), 412 RSSI_TO_GRADE_LINE(-77, -79, 1032), 413 RSSI_TO_GRADE_LINE(-73, -76, 1376), 414 RSSI_TO_GRADE_LINE(-70, -74, 1548), 415 RSSI_TO_GRADE_LINE(-69, -72, 1750), 416 RSSI_TO_GRADE_LINE(-65, -68, 2064), 417 RSSI_TO_GRADE_LINE(-61, -66, 2294), 418 RSSI_TO_GRADE_LINE(-58, -61, 2580), 419 RSSI_TO_GRADE_LINE(-55, -58, 2868), 420 RSSI_TO_GRADE_LINE(-46, -55, 3098), 421 RSSI_TO_GRADE_LINE(-43, -54, 3442) 422 }; 423 424 #define MAX_GRADE (rssi_to_grade_map[ARRAY_SIZE(rssi_to_grade_map) - 1].grade) 425 426 #define DEFAULT_CHAN_LOAD_LB 30 427 #define DEFAULT_CHAN_LOAD_HB 15 428 #define DEFAULT_CHAN_LOAD_UHB 0 429 430 /* Factors calculation is done with fixed-point with a scaling factor of 1/256 */ 431 #define SCALE_FACTOR 256 432 433 /* Convert a percentage from [0,100] to [0,255] */ 434 #define NORMALIZE_PERCENT_TO_255(percentage) ((percentage) * SCALE_FACTOR / 100) 435 436 static unsigned int 437 iwl_mvm_get_puncturing_factor(const struct ieee80211_bss_conf *link_conf) 438 { 439 enum nl80211_chan_width chan_width = 440 link_conf->chanreq.oper.width; 441 int mhz = nl80211_chan_width_to_mhz(chan_width); 442 unsigned int n_subchannels, n_punctured, puncturing_penalty; 443 444 if (WARN_ONCE(mhz < 20 || mhz > 320, 445 "Invalid channel width : (%d)\n", mhz)) 446 return SCALE_FACTOR; 447 448 /* No puncturing, no penalty */ 449 if (mhz < 80) 450 return SCALE_FACTOR; 451 452 /* total number of subchannels */ 453 n_subchannels = mhz / 20; 454 /* how many of these are punctured */ 455 n_punctured = hweight16(link_conf->chanreq.oper.punctured); 456 457 puncturing_penalty = n_punctured * SCALE_FACTOR / n_subchannels; 458 return SCALE_FACTOR - puncturing_penalty; 459 } 460 461 static unsigned int 462 iwl_mvm_get_chan_load(struct ieee80211_bss_conf *link_conf) 463 { 464 struct ieee80211_vif *vif = link_conf->vif; 465 struct iwl_mvm_vif_link_info *mvm_link = 466 iwl_mvm_vif_from_mac80211(link_conf->vif)->link[link_conf->link_id]; 467 const struct element *bss_load_elem; 468 const struct ieee80211_bss_load_elem *bss_load; 469 enum nl80211_band band = link_conf->chanreq.oper.chan->band; 470 const struct cfg80211_bss_ies *ies; 471 unsigned int chan_load; 472 u32 chan_load_by_us; 473 474 rcu_read_lock(); 475 if (ieee80211_vif_link_active(vif, link_conf->link_id)) 476 ies = rcu_dereference(link_conf->bss->beacon_ies); 477 else 478 ies = rcu_dereference(link_conf->bss->ies); 479 480 if (ies) 481 bss_load_elem = cfg80211_find_elem(WLAN_EID_QBSS_LOAD, 482 ies->data, ies->len); 483 else 484 bss_load_elem = NULL; 485 486 /* If there isn't BSS Load element, take the defaults */ 487 if (!bss_load_elem || 488 bss_load_elem->datalen != sizeof(*bss_load)) { 489 rcu_read_unlock(); 490 switch (band) { 491 case NL80211_BAND_2GHZ: 492 chan_load = DEFAULT_CHAN_LOAD_LB; 493 break; 494 case NL80211_BAND_5GHZ: 495 chan_load = DEFAULT_CHAN_LOAD_HB; 496 break; 497 case NL80211_BAND_6GHZ: 498 chan_load = DEFAULT_CHAN_LOAD_UHB; 499 break; 500 default: 501 chan_load = 0; 502 break; 503 } 504 /* The defaults are given in percentage */ 505 return NORMALIZE_PERCENT_TO_255(chan_load); 506 } 507 508 bss_load = (const void *)bss_load_elem->data; 509 /* Channel util is in range 0-255 */ 510 chan_load = bss_load->channel_util; 511 rcu_read_unlock(); 512 513 if (!mvm_link || !mvm_link->active) 514 return chan_load; 515 516 if (WARN_ONCE(!mvm_link->phy_ctxt, 517 "Active link (%u) without phy ctxt assigned!\n", 518 link_conf->link_id)) 519 return chan_load; 520 521 /* channel load by us is given in percentage */ 522 chan_load_by_us = 523 NORMALIZE_PERCENT_TO_255(mvm_link->phy_ctxt->channel_load_by_us); 524 525 /* Use only values that firmware sends that can possibly be valid */ 526 if (chan_load_by_us <= chan_load) 527 chan_load -= chan_load_by_us; 528 529 return chan_load; 530 } 531 532 static unsigned int 533 iwl_mvm_get_chan_load_factor(struct ieee80211_bss_conf *link_conf) 534 { 535 return SCALE_FACTOR - iwl_mvm_get_chan_load(link_conf); 536 } 537 538 /* This function calculates the grade of a link. Returns 0 in error case */ 539 VISIBLE_IF_IWLWIFI_KUNIT 540 unsigned int iwl_mvm_get_link_grade(struct ieee80211_bss_conf *link_conf) 541 { 542 enum nl80211_band band; 543 int i, rssi_idx; 544 s32 link_rssi; 545 unsigned int grade = MAX_GRADE; 546 547 if (WARN_ON_ONCE(!link_conf)) 548 return 0; 549 550 band = link_conf->chanreq.oper.chan->band; 551 if (WARN_ONCE(band != NL80211_BAND_2GHZ && 552 band != NL80211_BAND_5GHZ && 553 band != NL80211_BAND_6GHZ, 554 "Invalid band (%u)\n", band)) 555 return 0; 556 557 link_rssi = MBM_TO_DBM(link_conf->bss->signal); 558 /* 559 * For 6 GHz the RSSI of the beacons is lower than 560 * the RSSI of the data. 561 */ 562 if (band == NL80211_BAND_6GHZ) 563 link_rssi += 4; 564 565 rssi_idx = band == NL80211_BAND_2GHZ ? 0 : 1; 566 567 /* No valid RSSI - take the lowest grade */ 568 if (!link_rssi) 569 link_rssi = rssi_to_grade_map[0].rssi[rssi_idx]; 570 571 /* Get grade based on RSSI */ 572 for (i = 0; i < ARRAY_SIZE(rssi_to_grade_map); i++) { 573 const struct iwl_mvm_rssi_to_grade *line = 574 &rssi_to_grade_map[i]; 575 576 if (link_rssi > line->rssi[rssi_idx]) 577 continue; 578 grade = line->grade; 579 break; 580 } 581 582 /* apply the channel load and puncturing factors */ 583 grade = grade * iwl_mvm_get_chan_load_factor(link_conf) / SCALE_FACTOR; 584 grade = grade * iwl_mvm_get_puncturing_factor(link_conf) / SCALE_FACTOR; 585 return grade; 586 } 587 EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_mvm_get_link_grade); 588 589 static 590 u8 iwl_mvm_set_link_selection_data(struct ieee80211_vif *vif, 591 struct iwl_mvm_link_sel_data *data, 592 unsigned long usable_links, 593 u8 *best_link_idx) 594 { 595 u8 n_data = 0; 596 u16 max_grade = 0; 597 unsigned long link_id; 598 599 /* TODO: don't select links that weren't discovered in the last scan */ 600 for_each_set_bit(link_id, &usable_links, IEEE80211_MLD_MAX_NUM_LINKS) { 601 struct ieee80211_bss_conf *link_conf = 602 link_conf_dereference_protected(vif, link_id); 603 604 if (WARN_ON_ONCE(!link_conf)) 605 continue; 606 607 data[n_data].link_id = link_id; 608 data[n_data].chandef = &link_conf->chanreq.oper; 609 data[n_data].signal = link_conf->bss->signal / 100; 610 data[n_data].grade = iwl_mvm_get_link_grade(link_conf); 611 612 if (data[n_data].grade > max_grade) { 613 max_grade = data[n_data].grade; 614 *best_link_idx = n_data; 615 } 616 n_data++; 617 } 618 619 return n_data; 620 } 621 622 struct iwl_mvm_bw_to_rssi_threshs { 623 s8 low; 624 s8 high; 625 }; 626 627 #define BW_TO_RSSI_THRESHOLDS(_bw) \ 628 [IWL_PHY_CHANNEL_MODE ## _bw] = { \ 629 .low = IWL_MVM_LOW_RSSI_THRESH_##_bw##MHZ, \ 630 .high = IWL_MVM_HIGH_RSSI_THRESH_##_bw##MHZ \ 631 } 632 633 s8 iwl_mvm_get_esr_rssi_thresh(struct iwl_mvm *mvm, 634 const struct cfg80211_chan_def *chandef, 635 bool low) 636 { 637 const struct iwl_mvm_bw_to_rssi_threshs bw_to_rssi_threshs_map[] = { 638 BW_TO_RSSI_THRESHOLDS(20), 639 BW_TO_RSSI_THRESHOLDS(40), 640 BW_TO_RSSI_THRESHOLDS(80), 641 BW_TO_RSSI_THRESHOLDS(160) 642 /* 320 MHz has the same thresholds as 20 MHz */ 643 }; 644 const struct iwl_mvm_bw_to_rssi_threshs *threshs; 645 u8 chan_width = iwl_mvm_get_channel_width(chandef); 646 647 if (WARN_ON(chandef->chan->band != NL80211_BAND_2GHZ && 648 chandef->chan->band != NL80211_BAND_5GHZ && 649 chandef->chan->band != NL80211_BAND_6GHZ)) 650 return S8_MAX; 651 652 /* 6 GHz will always use 20 MHz thresholds, regardless of the BW */ 653 if (chan_width == IWL_PHY_CHANNEL_MODE320) 654 chan_width = IWL_PHY_CHANNEL_MODE20; 655 656 threshs = &bw_to_rssi_threshs_map[chan_width]; 657 658 return low ? threshs->low : threshs->high; 659 } 660 661 static u32 662 iwl_mvm_esr_disallowed_with_link(struct iwl_mvm *mvm, 663 struct ieee80211_vif *vif, 664 const struct iwl_mvm_link_sel_data *link, 665 bool primary) 666 { 667 struct wiphy *wiphy = mvm->hw->wiphy; 668 struct ieee80211_bss_conf *conf; 669 enum iwl_mvm_esr_state ret = 0; 670 s8 thresh; 671 672 conf = wiphy_dereference(wiphy, vif->link_conf[link->link_id]); 673 if (WARN_ON_ONCE(!conf)) 674 return false; 675 676 /* BT Coex effects eSR mode only if one of the links is on LB */ 677 if (link->chandef->chan->band == NL80211_BAND_2GHZ && 678 (!iwl_mvm_bt_coex_calculate_esr_mode(mvm, vif, link->signal, 679 primary))) 680 ret |= IWL_MVM_ESR_EXIT_COEX; 681 682 thresh = iwl_mvm_get_esr_rssi_thresh(mvm, link->chandef, 683 false); 684 685 if (link->signal < thresh) 686 ret |= IWL_MVM_ESR_EXIT_LOW_RSSI; 687 688 if (conf->csa_active) 689 ret |= IWL_MVM_ESR_EXIT_CSA; 690 691 if (ret) { 692 IWL_DEBUG_INFO(mvm, 693 "Link %d is not allowed for esr\n", 694 link->link_id); 695 iwl_mvm_print_esr_state(mvm, ret); 696 } 697 return ret; 698 } 699 700 VISIBLE_IF_IWLWIFI_KUNIT 701 bool iwl_mvm_mld_valid_link_pair(struct ieee80211_vif *vif, 702 const struct iwl_mvm_link_sel_data *a, 703 const struct iwl_mvm_link_sel_data *b) 704 { 705 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 706 struct iwl_mvm *mvm = mvmvif->mvm; 707 enum iwl_mvm_esr_state ret = 0; 708 709 /* Per-link considerations */ 710 if (iwl_mvm_esr_disallowed_with_link(mvm, vif, a, true) || 711 iwl_mvm_esr_disallowed_with_link(mvm, vif, b, false)) 712 return false; 713 714 if (a->chandef->chan->band == b->chandef->chan->band || 715 a->chandef->width != b->chandef->width) 716 ret |= IWL_MVM_ESR_EXIT_BANDWIDTH; 717 718 if (ret) { 719 IWL_DEBUG_INFO(mvm, 720 "Links %d and %d are not a valid pair for EMLSR\n", 721 a->link_id, b->link_id); 722 iwl_mvm_print_esr_state(mvm, ret); 723 return false; 724 } 725 726 return true; 727 728 } 729 EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_mvm_mld_valid_link_pair); 730 731 /* 732 * Returns the combined eSR grade of two given links. 733 * Returns 0 if eSR is not allowed with these 2 links. 734 */ 735 static 736 unsigned int iwl_mvm_get_esr_grade(struct ieee80211_vif *vif, 737 const struct iwl_mvm_link_sel_data *a, 738 const struct iwl_mvm_link_sel_data *b, 739 u8 *primary_id) 740 { 741 struct ieee80211_bss_conf *primary_conf; 742 struct wiphy *wiphy = ieee80211_vif_to_wdev(vif)->wiphy; 743 unsigned int primary_load; 744 745 lockdep_assert_wiphy(wiphy); 746 747 /* a is always primary, b is always secondary */ 748 if (b->grade > a->grade) 749 swap(a, b); 750 751 *primary_id = a->link_id; 752 753 if (!iwl_mvm_mld_valid_link_pair(vif, a, b)) 754 return 0; 755 756 primary_conf = wiphy_dereference(wiphy, vif->link_conf[*primary_id]); 757 758 if (WARN_ON_ONCE(!primary_conf)) 759 return 0; 760 761 primary_load = iwl_mvm_get_chan_load(primary_conf); 762 763 return a->grade + 764 ((b->grade * primary_load) / SCALE_FACTOR); 765 } 766 767 void iwl_mvm_select_links(struct iwl_mvm *mvm, struct ieee80211_vif *vif) 768 { 769 struct iwl_mvm_link_sel_data data[IEEE80211_MLD_MAX_NUM_LINKS]; 770 struct iwl_mvm_link_sel_data *best_link; 771 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 772 u32 max_active_links = iwl_mvm_max_active_links(mvm, vif); 773 u16 usable_links = ieee80211_vif_usable_links(vif); 774 u8 best, primary_link, best_in_pair, n_data; 775 u16 max_esr_grade = 0, new_active_links; 776 777 lockdep_assert_wiphy(mvm->hw->wiphy); 778 779 if (!mvmvif->authorized || !ieee80211_vif_is_mld(vif)) 780 return; 781 782 if (!IWL_MVM_AUTO_EML_ENABLE) 783 return; 784 785 /* The logic below is a simple version that doesn't suit more than 2 786 * links 787 */ 788 WARN_ON_ONCE(max_active_links > 2); 789 790 n_data = iwl_mvm_set_link_selection_data(vif, data, usable_links, 791 &best); 792 793 if (WARN(!n_data, "Couldn't find a valid grade for any link!\n")) 794 return; 795 796 best_link = &data[best]; 797 primary_link = best_link->link_id; 798 new_active_links = BIT(best_link->link_id); 799 800 /* eSR is not supported/blocked, or only one usable link */ 801 if (max_active_links == 1 || !iwl_mvm_vif_has_esr_cap(mvm, vif) || 802 mvmvif->esr_disable_reason || n_data == 1) 803 goto set_active; 804 805 for (u8 a = 0; a < n_data; a++) 806 for (u8 b = a + 1; b < n_data; b++) { 807 u16 esr_grade = iwl_mvm_get_esr_grade(vif, &data[a], 808 &data[b], 809 &best_in_pair); 810 811 if (esr_grade <= max_esr_grade) 812 continue; 813 814 max_esr_grade = esr_grade; 815 primary_link = best_in_pair; 816 new_active_links = BIT(data[a].link_id) | 817 BIT(data[b].link_id); 818 } 819 820 /* No valid pair was found, go with the best link */ 821 if (hweight16(new_active_links) <= 1) 822 goto set_active; 823 824 /* For equal grade - prefer EMLSR */ 825 if (best_link->grade > max_esr_grade) { 826 primary_link = best_link->link_id; 827 new_active_links = BIT(best_link->link_id); 828 } 829 set_active: 830 IWL_DEBUG_INFO(mvm, "Link selection result: 0x%x. Primary = %d\n", 831 new_active_links, primary_link); 832 ieee80211_set_active_links_async(vif, new_active_links); 833 mvmvif->link_selection_res = new_active_links; 834 mvmvif->link_selection_primary = primary_link; 835 } 836 837 u8 iwl_mvm_get_primary_link(struct ieee80211_vif *vif) 838 { 839 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 840 841 /* relevant data is written with both locks held, so read with either */ 842 lockdep_assert(lockdep_is_held(&mvmvif->mvm->mutex) || 843 lockdep_is_held(&mvmvif->mvm->hw->wiphy->mtx)); 844 845 if (!ieee80211_vif_is_mld(vif)) 846 return 0; 847 848 /* In AP mode, there is no primary link */ 849 if (vif->type == NL80211_IFTYPE_AP) 850 return __ffs(vif->active_links); 851 852 if (mvmvif->esr_active && 853 !WARN_ON(!(BIT(mvmvif->primary_link) & vif->active_links))) 854 return mvmvif->primary_link; 855 856 return __ffs(vif->active_links); 857 } 858 859 /* 860 * For non-MLO/single link, this will return the deflink/single active link, 861 * respectively 862 */ 863 u8 iwl_mvm_get_other_link(struct ieee80211_vif *vif, u8 link_id) 864 { 865 switch (hweight16(vif->active_links)) { 866 case 0: 867 return 0; 868 default: 869 WARN_ON(1); 870 fallthrough; 871 case 1: 872 return __ffs(vif->active_links); 873 case 2: 874 return __ffs(vif->active_links & ~BIT(link_id)); 875 } 876 } 877 878 /* Reasons that can cause esr prevention */ 879 #define IWL_MVM_ESR_PREVENT_REASONS IWL_MVM_ESR_EXIT_MISSED_BEACON 880 #define IWL_MVM_PREVENT_ESR_TIMEOUT (HZ * 400) 881 #define IWL_MVM_ESR_PREVENT_SHORT (HZ * 300) 882 #define IWL_MVM_ESR_PREVENT_LONG (HZ * 600) 883 884 static bool iwl_mvm_check_esr_prevention(struct iwl_mvm *mvm, 885 struct iwl_mvm_vif *mvmvif, 886 enum iwl_mvm_esr_state reason) 887 { 888 bool timeout_expired = time_after(jiffies, 889 mvmvif->last_esr_exit.ts + 890 IWL_MVM_PREVENT_ESR_TIMEOUT); 891 unsigned long delay; 892 893 lockdep_assert_held(&mvm->mutex); 894 895 /* Only handle reasons that can cause prevention */ 896 if (!(reason & IWL_MVM_ESR_PREVENT_REASONS)) 897 return false; 898 899 /* 900 * Reset the counter if more than 400 seconds have passed between one 901 * exit and the other, or if we exited due to a different reason. 902 * Will also reset the counter after the long prevention is done. 903 */ 904 if (timeout_expired || mvmvif->last_esr_exit.reason != reason) { 905 mvmvif->exit_same_reason_count = 1; 906 return false; 907 } 908 909 mvmvif->exit_same_reason_count++; 910 if (WARN_ON(mvmvif->exit_same_reason_count < 2 || 911 mvmvif->exit_same_reason_count > 3)) 912 return false; 913 914 mvmvif->esr_disable_reason |= IWL_MVM_ESR_BLOCKED_PREVENTION; 915 916 /* 917 * For the second exit, use a short prevention, and for the third one, 918 * use a long prevention. 919 */ 920 delay = mvmvif->exit_same_reason_count == 2 ? 921 IWL_MVM_ESR_PREVENT_SHORT : 922 IWL_MVM_ESR_PREVENT_LONG; 923 924 IWL_DEBUG_INFO(mvm, 925 "Preventing EMLSR for %ld seconds due to %u exits with the reason = %s (0x%x)\n", 926 delay / HZ, mvmvif->exit_same_reason_count, 927 iwl_get_esr_state_string(reason), reason); 928 929 wiphy_delayed_work_queue(mvm->hw->wiphy, 930 &mvmvif->prevent_esr_done_wk, delay); 931 return true; 932 } 933 934 #define IWL_MVM_TRIGGER_LINK_SEL_TIME (IWL_MVM_TRIGGER_LINK_SEL_TIME_SEC * HZ) 935 936 /* API to exit eSR mode */ 937 void iwl_mvm_exit_esr(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 938 enum iwl_mvm_esr_state reason, 939 u8 link_to_keep) 940 { 941 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 942 u16 new_active_links; 943 bool prevented; 944 945 lockdep_assert_held(&mvm->mutex); 946 947 if (!IWL_MVM_AUTO_EML_ENABLE) 948 return; 949 950 /* Nothing to do */ 951 if (!mvmvif->esr_active) 952 return; 953 954 if (WARN_ON(!ieee80211_vif_is_mld(vif) || !mvmvif->authorized)) 955 return; 956 957 if (WARN_ON(!(vif->active_links & BIT(link_to_keep)))) 958 link_to_keep = __ffs(vif->active_links); 959 960 new_active_links = BIT(link_to_keep); 961 IWL_DEBUG_INFO(mvm, 962 "Exiting EMLSR. reason = %s (0x%x). Current active links=0x%x, new active links = 0x%x\n", 963 iwl_get_esr_state_string(reason), reason, 964 vif->active_links, new_active_links); 965 966 ieee80211_set_active_links_async(vif, new_active_links); 967 968 /* Prevent EMLSR if needed */ 969 prevented = iwl_mvm_check_esr_prevention(mvm, mvmvif, reason); 970 971 /* Remember why and when we exited EMLSR */ 972 mvmvif->last_esr_exit.ts = jiffies; 973 mvmvif->last_esr_exit.reason = reason; 974 975 /* 976 * If EMLSR is prevented now - don't try to get back to EMLSR. 977 * If we exited due to a blocking event, we will try to get back to 978 * EMLSR when the corresponding unblocking event will happen. 979 */ 980 if (prevented || reason & IWL_MVM_BLOCK_ESR_REASONS) 981 return; 982 983 /* If EMLSR is not blocked - try enabling it again in 30 seconds */ 984 wiphy_delayed_work_queue(mvm->hw->wiphy, 985 &mvmvif->mlo_int_scan_wk, 986 round_jiffies_relative(IWL_MVM_TRIGGER_LINK_SEL_TIME)); 987 } 988 989 void iwl_mvm_block_esr(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 990 enum iwl_mvm_esr_state reason, 991 u8 link_to_keep) 992 { 993 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 994 995 lockdep_assert_held(&mvm->mutex); 996 997 if (!IWL_MVM_AUTO_EML_ENABLE) 998 return; 999 1000 /* This should be called only with disable reasons */ 1001 if (WARN_ON(!(reason & IWL_MVM_BLOCK_ESR_REASONS))) 1002 return; 1003 1004 if (mvmvif->esr_disable_reason & reason) 1005 return; 1006 1007 IWL_DEBUG_INFO(mvm, 1008 "Blocking EMLSR mode. reason = %s (0x%x)\n", 1009 iwl_get_esr_state_string(reason), reason); 1010 1011 mvmvif->esr_disable_reason |= reason; 1012 1013 iwl_mvm_print_esr_state(mvm, mvmvif->esr_disable_reason); 1014 1015 iwl_mvm_exit_esr(mvm, vif, reason, link_to_keep); 1016 } 1017 1018 int iwl_mvm_block_esr_sync(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 1019 enum iwl_mvm_esr_state reason) 1020 { 1021 int primary_link = iwl_mvm_get_primary_link(vif); 1022 int ret; 1023 1024 if (!IWL_MVM_AUTO_EML_ENABLE || !ieee80211_vif_is_mld(vif)) 1025 return 0; 1026 1027 /* This should be called only with blocking reasons */ 1028 if (WARN_ON(!(reason & IWL_MVM_BLOCK_ESR_REASONS))) 1029 return 0; 1030 1031 /* leave ESR immediately, not only async with iwl_mvm_block_esr() */ 1032 ret = ieee80211_set_active_links(vif, BIT(primary_link)); 1033 if (ret) 1034 return ret; 1035 1036 mutex_lock(&mvm->mutex); 1037 /* only additionally block for consistency and to avoid concurrency */ 1038 iwl_mvm_block_esr(mvm, vif, reason, primary_link); 1039 mutex_unlock(&mvm->mutex); 1040 1041 return 0; 1042 } 1043 1044 static void iwl_mvm_esr_unblocked(struct iwl_mvm *mvm, 1045 struct ieee80211_vif *vif) 1046 { 1047 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 1048 bool need_new_sel = time_after(jiffies, mvmvif->last_esr_exit.ts + 1049 IWL_MVM_TRIGGER_LINK_SEL_TIME); 1050 1051 lockdep_assert_held(&mvm->mutex); 1052 1053 if (!ieee80211_vif_is_mld(vif) || !mvmvif->authorized || 1054 mvmvif->esr_active) 1055 return; 1056 1057 IWL_DEBUG_INFO(mvm, "EMLSR is unblocked\n"); 1058 1059 /* If we exited due to an EXIT reason, and the exit was in less than 1060 * 30 seconds, then a MLO scan was scheduled already. 1061 */ 1062 if (!need_new_sel && 1063 !(mvmvif->last_esr_exit.reason & IWL_MVM_BLOCK_ESR_REASONS)) { 1064 IWL_DEBUG_INFO(mvm, "Wait for MLO scan\n"); 1065 return; 1066 } 1067 1068 /* 1069 * If EMLSR was blocked for more than 30 seconds, or the last link 1070 * selection decided to not enter EMLSR, trigger a new scan. 1071 */ 1072 if (need_new_sel || hweight16(mvmvif->link_selection_res) < 2) { 1073 IWL_DEBUG_INFO(mvm, "Trigger MLO scan\n"); 1074 wiphy_delayed_work_queue(mvm->hw->wiphy, 1075 &mvmvif->mlo_int_scan_wk, 0); 1076 /* 1077 * If EMLSR was blocked for less than 30 seconds, and the last link 1078 * selection decided to use EMLSR, activate EMLSR using the previous 1079 * link selection result. 1080 */ 1081 } else { 1082 IWL_DEBUG_INFO(mvm, 1083 "Use the latest link selection result: 0x%x\n", 1084 mvmvif->link_selection_res); 1085 ieee80211_set_active_links_async(vif, 1086 mvmvif->link_selection_res); 1087 } 1088 } 1089 1090 void iwl_mvm_unblock_esr(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 1091 enum iwl_mvm_esr_state reason) 1092 { 1093 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 1094 1095 lockdep_assert_held(&mvm->mutex); 1096 1097 if (!IWL_MVM_AUTO_EML_ENABLE) 1098 return; 1099 1100 /* This should be called only with disable reasons */ 1101 if (WARN_ON(!(reason & IWL_MVM_BLOCK_ESR_REASONS))) 1102 return; 1103 1104 /* No Change */ 1105 if (!(mvmvif->esr_disable_reason & reason)) 1106 return; 1107 1108 mvmvif->esr_disable_reason &= ~reason; 1109 1110 IWL_DEBUG_INFO(mvm, 1111 "Unblocking EMLSR mode. reason = %s (0x%x)\n", 1112 iwl_get_esr_state_string(reason), reason); 1113 iwl_mvm_print_esr_state(mvm, mvmvif->esr_disable_reason); 1114 1115 if (!mvmvif->esr_disable_reason) 1116 iwl_mvm_esr_unblocked(mvm, vif); 1117 } 1118 1119 void iwl_mvm_init_link(struct iwl_mvm_vif_link_info *link) 1120 { 1121 link->bcast_sta.sta_id = IWL_INVALID_STA; 1122 link->mcast_sta.sta_id = IWL_INVALID_STA; 1123 link->ap_sta_id = IWL_INVALID_STA; 1124 1125 for (int r = 0; r < NUM_IWL_MVM_SMPS_REQ; r++) 1126 link->smps_requests[r] = 1127 IEEE80211_SMPS_AUTOMATIC; 1128 } 1129