1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2 /* 3 * Copyright (C) 2024-2025 Intel Corporation 4 */ 5 #include "mlo.h" 6 #include "phy.h" 7 8 /* Block reasons helper */ 9 #define HANDLE_EMLSR_BLOCKED_REASONS(HOW) \ 10 HOW(PREVENTION) \ 11 HOW(WOWLAN) \ 12 HOW(FW) \ 13 HOW(ROC) \ 14 HOW(NON_BSS) \ 15 HOW(TMP_NON_BSS) \ 16 HOW(TPT) 17 18 static const char * 19 iwl_mld_get_emlsr_blocked_string(enum iwl_mld_emlsr_blocked blocked) 20 { 21 /* Using switch without "default" will warn about missing entries */ 22 switch (blocked) { 23 #define REASON_CASE(x) case IWL_MLD_EMLSR_BLOCKED_##x: return #x; 24 HANDLE_EMLSR_BLOCKED_REASONS(REASON_CASE) 25 #undef REASON_CASE 26 } 27 28 return "ERROR"; 29 } 30 31 static void iwl_mld_print_emlsr_blocked(struct iwl_mld *mld, u32 mask) 32 { 33 #define NAME_FMT(x) "%s" 34 #define NAME_PR(x) (mask & IWL_MLD_EMLSR_BLOCKED_##x) ? "[" #x "]" : "", 35 IWL_DEBUG_INFO(mld, 36 "EMLSR blocked = " HANDLE_EMLSR_BLOCKED_REASONS(NAME_FMT) 37 " (0x%x)\n", 38 HANDLE_EMLSR_BLOCKED_REASONS(NAME_PR) 39 mask); 40 #undef NAME_FMT 41 #undef NAME_PR 42 } 43 44 /* Exit reasons helper */ 45 #define HANDLE_EMLSR_EXIT_REASONS(HOW) \ 46 HOW(BLOCK) \ 47 HOW(MISSED_BEACON) \ 48 HOW(FAIL_ENTRY) \ 49 HOW(CSA) \ 50 HOW(EQUAL_BAND) \ 51 HOW(BANDWIDTH) \ 52 HOW(LOW_RSSI) \ 53 HOW(LINK_USAGE) \ 54 HOW(BT_COEX) \ 55 HOW(CHAN_LOAD) \ 56 HOW(RFI) 57 58 static const char * 59 iwl_mld_get_emlsr_exit_string(enum iwl_mld_emlsr_exit exit) 60 { 61 /* Using switch without "default" will warn about missing entries */ 62 switch (exit) { 63 #define REASON_CASE(x) case IWL_MLD_EMLSR_EXIT_##x: return #x; 64 HANDLE_EMLSR_EXIT_REASONS(REASON_CASE) 65 #undef REASON_CASE 66 } 67 68 return "ERROR"; 69 } 70 71 static void iwl_mld_print_emlsr_exit(struct iwl_mld *mld, u32 mask) 72 { 73 #define NAME_FMT(x) "%s" 74 #define NAME_PR(x) (mask & IWL_MLD_EMLSR_EXIT_##x) ? "[" #x "]" : "", 75 IWL_DEBUG_INFO(mld, 76 "EMLSR exit = " HANDLE_EMLSR_EXIT_REASONS(NAME_FMT) 77 " (0x%x)\n", 78 HANDLE_EMLSR_EXIT_REASONS(NAME_PR) 79 mask); 80 #undef NAME_FMT 81 #undef NAME_PR 82 } 83 84 void iwl_mld_emlsr_prevent_done_wk(struct wiphy *wiphy, struct wiphy_work *wk) 85 { 86 struct iwl_mld_vif *mld_vif = container_of(wk, struct iwl_mld_vif, 87 emlsr.prevent_done_wk.work); 88 struct ieee80211_vif *vif = 89 container_of((void *)mld_vif, struct ieee80211_vif, drv_priv); 90 91 if (WARN_ON(!(mld_vif->emlsr.blocked_reasons & 92 IWL_MLD_EMLSR_BLOCKED_PREVENTION))) 93 return; 94 95 iwl_mld_unblock_emlsr(mld_vif->mld, vif, 96 IWL_MLD_EMLSR_BLOCKED_PREVENTION); 97 } 98 99 void iwl_mld_emlsr_tmp_non_bss_done_wk(struct wiphy *wiphy, 100 struct wiphy_work *wk) 101 { 102 struct iwl_mld_vif *mld_vif = container_of(wk, struct iwl_mld_vif, 103 emlsr.prevent_done_wk.work); 104 struct ieee80211_vif *vif = 105 container_of((void *)mld_vif, struct ieee80211_vif, drv_priv); 106 107 if (WARN_ON(!(mld_vif->emlsr.blocked_reasons & 108 IWL_MLD_EMLSR_BLOCKED_TMP_NON_BSS))) 109 return; 110 111 iwl_mld_unblock_emlsr(mld_vif->mld, vif, 112 IWL_MLD_EMLSR_BLOCKED_TMP_NON_BSS); 113 } 114 115 #define IWL_MLD_TRIGGER_LINK_SEL_TIME (HZ * IWL_MLD_TRIGGER_LINK_SEL_TIME_SEC) 116 #define IWL_MLD_SCAN_EXPIRE_TIME (HZ * IWL_MLD_SCAN_EXPIRE_TIME_SEC) 117 118 /* Exit reasons that can cause longer EMLSR prevention */ 119 #define IWL_MLD_PREVENT_EMLSR_REASONS (IWL_MLD_EMLSR_EXIT_MISSED_BEACON | \ 120 IWL_MLD_EMLSR_EXIT_LINK_USAGE) 121 #define IWL_MLD_PREVENT_EMLSR_TIMEOUT (HZ * 400) 122 123 #define IWL_MLD_EMLSR_PREVENT_SHORT (HZ * 300) 124 #define IWL_MLD_EMLSR_PREVENT_LONG (HZ * 600) 125 126 static void iwl_mld_check_emlsr_prevention(struct iwl_mld *mld, 127 struct iwl_mld_vif *mld_vif, 128 enum iwl_mld_emlsr_exit reason) 129 { 130 unsigned long delay; 131 132 /* 133 * Reset the counter if more than 400 seconds have passed between one 134 * exit and the other, or if we exited due to a different reason. 135 * Will also reset the counter after the long prevention is done. 136 */ 137 if (time_after(jiffies, mld_vif->emlsr.last_exit_ts + 138 IWL_MLD_PREVENT_EMLSR_TIMEOUT) || 139 mld_vif->emlsr.last_exit_reason != reason) 140 mld_vif->emlsr.exit_repeat_count = 0; 141 142 mld_vif->emlsr.last_exit_reason = reason; 143 mld_vif->emlsr.last_exit_ts = jiffies; 144 mld_vif->emlsr.exit_repeat_count++; 145 146 /* 147 * Do not add a prevention when the reason was a block. For a block, 148 * EMLSR will be enabled again on unblock. 149 */ 150 if (reason == IWL_MLD_EMLSR_EXIT_BLOCK) 151 return; 152 153 /* Set prevention for a minimum of 30 seconds */ 154 mld_vif->emlsr.blocked_reasons |= IWL_MLD_EMLSR_BLOCKED_PREVENTION; 155 delay = IWL_MLD_TRIGGER_LINK_SEL_TIME; 156 157 /* Handle repeats for reasons that can cause long prevention */ 158 if (mld_vif->emlsr.exit_repeat_count > 1 && 159 reason & IWL_MLD_PREVENT_EMLSR_REASONS) { 160 if (mld_vif->emlsr.exit_repeat_count == 2) 161 delay = IWL_MLD_EMLSR_PREVENT_SHORT; 162 else 163 delay = IWL_MLD_EMLSR_PREVENT_LONG; 164 165 /* 166 * The timeouts are chosen so that this will not happen, i.e. 167 * IWL_MLD_EMLSR_PREVENT_LONG > IWL_MLD_PREVENT_EMLSR_TIMEOUT 168 */ 169 WARN_ON(mld_vif->emlsr.exit_repeat_count > 3); 170 } 171 172 IWL_DEBUG_INFO(mld, 173 "Preventing EMLSR for %ld seconds due to %u exits with the reason = %s (0x%x)\n", 174 delay / HZ, mld_vif->emlsr.exit_repeat_count, 175 iwl_mld_get_emlsr_exit_string(reason), reason); 176 177 wiphy_delayed_work_queue(mld->wiphy, 178 &mld_vif->emlsr.prevent_done_wk, delay); 179 } 180 181 static void iwl_mld_clear_avg_chan_load_iter(struct ieee80211_hw *hw, 182 struct ieee80211_chanctx_conf *ctx, 183 void *dat) 184 { 185 struct iwl_mld_phy *phy = iwl_mld_phy_from_mac80211(ctx); 186 187 /* It is ok to do it for all chanctx (and not only for the ones that 188 * belong to the EMLSR vif) since EMLSR is not allowed if there is 189 * another vif. 190 */ 191 phy->avg_channel_load_not_by_us = 0; 192 } 193 194 static int _iwl_mld_exit_emlsr(struct iwl_mld *mld, struct ieee80211_vif *vif, 195 enum iwl_mld_emlsr_exit exit, u8 link_to_keep, 196 bool sync) 197 { 198 struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif); 199 u16 new_active_links; 200 int ret = 0; 201 202 lockdep_assert_wiphy(mld->wiphy); 203 204 /* On entry failure need to exit anyway, even if entered from debugfs */ 205 if (exit != IWL_MLD_EMLSR_EXIT_FAIL_ENTRY && !IWL_MLD_AUTO_EML_ENABLE) 206 return 0; 207 208 /* Ignore exit request if EMLSR is not active */ 209 if (!iwl_mld_emlsr_active(vif)) 210 return 0; 211 212 if (WARN_ON(!ieee80211_vif_is_mld(vif) || !mld_vif->authorized)) 213 return 0; 214 215 if (WARN_ON(!(vif->active_links & BIT(link_to_keep)))) 216 link_to_keep = __ffs(vif->active_links); 217 218 new_active_links = BIT(link_to_keep); 219 IWL_DEBUG_INFO(mld, 220 "Exiting EMLSR. reason = %s (0x%x). Current active links=0x%x, new active links = 0x%x\n", 221 iwl_mld_get_emlsr_exit_string(exit), exit, 222 vif->active_links, new_active_links); 223 224 if (sync) 225 ret = ieee80211_set_active_links(vif, new_active_links); 226 else 227 ieee80211_set_active_links_async(vif, new_active_links); 228 229 /* Update latest exit reason and check EMLSR prevention */ 230 iwl_mld_check_emlsr_prevention(mld, mld_vif, exit); 231 232 /* channel_load_not_by_us is invalid when in EMLSR. 233 * Clear it so wrong values won't be used. 234 */ 235 ieee80211_iter_chan_contexts_atomic(mld->hw, 236 iwl_mld_clear_avg_chan_load_iter, 237 NULL); 238 239 return ret; 240 } 241 242 void iwl_mld_exit_emlsr(struct iwl_mld *mld, struct ieee80211_vif *vif, 243 enum iwl_mld_emlsr_exit exit, u8 link_to_keep) 244 { 245 _iwl_mld_exit_emlsr(mld, vif, exit, link_to_keep, false); 246 } 247 248 static int _iwl_mld_emlsr_block(struct iwl_mld *mld, struct ieee80211_vif *vif, 249 enum iwl_mld_emlsr_blocked reason, 250 u8 link_to_keep, bool sync) 251 { 252 struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif); 253 254 lockdep_assert_wiphy(mld->wiphy); 255 256 if (!IWL_MLD_AUTO_EML_ENABLE || !iwl_mld_vif_has_emlsr_cap(vif)) 257 return 0; 258 259 if (mld_vif->emlsr.blocked_reasons & reason) 260 return 0; 261 262 mld_vif->emlsr.blocked_reasons |= reason; 263 264 IWL_DEBUG_INFO(mld, 265 "Blocking EMLSR mode. reason = %s (0x%x)\n", 266 iwl_mld_get_emlsr_blocked_string(reason), reason); 267 iwl_mld_print_emlsr_blocked(mld, mld_vif->emlsr.blocked_reasons); 268 269 if (reason == IWL_MLD_EMLSR_BLOCKED_TPT) 270 wiphy_delayed_work_cancel(mld_vif->mld->wiphy, 271 &mld_vif->emlsr.check_tpt_wk); 272 273 return _iwl_mld_exit_emlsr(mld, vif, IWL_MLD_EMLSR_EXIT_BLOCK, 274 link_to_keep, sync); 275 } 276 277 void iwl_mld_block_emlsr(struct iwl_mld *mld, struct ieee80211_vif *vif, 278 enum iwl_mld_emlsr_blocked reason, u8 link_to_keep) 279 { 280 _iwl_mld_emlsr_block(mld, vif, reason, link_to_keep, false); 281 } 282 283 int iwl_mld_block_emlsr_sync(struct iwl_mld *mld, struct ieee80211_vif *vif, 284 enum iwl_mld_emlsr_blocked reason, u8 link_to_keep) 285 { 286 return _iwl_mld_emlsr_block(mld, vif, reason, link_to_keep, true); 287 } 288 289 static void _iwl_mld_select_links(struct iwl_mld *mld, 290 struct ieee80211_vif *vif); 291 292 void iwl_mld_trigger_link_selection(struct iwl_mld *mld, 293 struct ieee80211_vif *vif) 294 { 295 bool last_scan_was_recent = 296 time_before(jiffies, mld->scan.last_mlo_scan_jiffies + 297 IWL_MLD_SCAN_EXPIRE_TIME); 298 299 if (last_scan_was_recent) { 300 IWL_DEBUG_EHT(mld, "MLO scan was recent, skip.\n"); 301 _iwl_mld_select_links(mld, vif); 302 } else { 303 IWL_DEBUG_EHT(mld, "Doing link selection after MLO scan\n"); 304 iwl_mld_int_mlo_scan(mld, vif); 305 } 306 } 307 308 void iwl_mld_unblock_emlsr(struct iwl_mld *mld, struct ieee80211_vif *vif, 309 enum iwl_mld_emlsr_blocked reason) 310 { 311 struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif); 312 313 lockdep_assert_wiphy(mld->wiphy); 314 315 if (!IWL_MLD_AUTO_EML_ENABLE || !iwl_mld_vif_has_emlsr_cap(vif)) 316 return; 317 318 if (!(mld_vif->emlsr.blocked_reasons & reason)) 319 return; 320 321 mld_vif->emlsr.blocked_reasons &= ~reason; 322 323 IWL_DEBUG_INFO(mld, 324 "Unblocking EMLSR mode. reason = %s (0x%x)\n", 325 iwl_mld_get_emlsr_blocked_string(reason), reason); 326 iwl_mld_print_emlsr_blocked(mld, mld_vif->emlsr.blocked_reasons); 327 328 if (reason == IWL_MLD_EMLSR_BLOCKED_TPT) 329 wiphy_delayed_work_queue(mld_vif->mld->wiphy, 330 &mld_vif->emlsr.check_tpt_wk, 331 round_jiffies_relative(IWL_MLD_TPT_COUNT_WINDOW)); 332 333 if (mld_vif->emlsr.blocked_reasons) 334 return; 335 336 IWL_DEBUG_INFO(mld, "EMLSR is unblocked\n"); 337 iwl_mld_trigger_link_selection(mld, vif); 338 } 339 340 static void 341 iwl_mld_vif_iter_emlsr_mode_notif(void *data, u8 *mac, 342 struct ieee80211_vif *vif) 343 { 344 struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif); 345 struct iwl_esr_mode_notif *notif = (void *)data; 346 347 if (!iwl_mld_vif_has_emlsr_cap(vif)) 348 return; 349 350 switch (le32_to_cpu(notif->action)) { 351 case ESR_RECOMMEND_ENTER: 352 iwl_mld_unblock_emlsr(mld_vif->mld, vif, 353 IWL_MLD_EMLSR_BLOCKED_FW); 354 break; 355 case ESR_RECOMMEND_LEAVE: 356 iwl_mld_block_emlsr(mld_vif->mld, vif, 357 IWL_MLD_EMLSR_BLOCKED_FW, 358 iwl_mld_get_primary_link(vif)); 359 break; 360 case ESR_FORCE_LEAVE: 361 default: 362 /* ESR_FORCE_LEAVE should not happen at this point */ 363 IWL_WARN(mld_vif->mld, "Unexpected EMLSR notification: %d\n", 364 le32_to_cpu(notif->action)); 365 } 366 } 367 368 void iwl_mld_handle_emlsr_mode_notif(struct iwl_mld *mld, 369 struct iwl_rx_packet *pkt) 370 { 371 ieee80211_iterate_active_interfaces_mtx(mld->hw, 372 IEEE80211_IFACE_ITER_NORMAL, 373 iwl_mld_vif_iter_emlsr_mode_notif, 374 pkt->data); 375 } 376 377 static void 378 iwl_mld_vif_iter_disconnect_emlsr(void *data, u8 *mac, 379 struct ieee80211_vif *vif) 380 { 381 if (!iwl_mld_vif_has_emlsr_cap(vif)) 382 return; 383 384 ieee80211_connection_loss(vif); 385 } 386 387 void iwl_mld_handle_emlsr_trans_fail_notif(struct iwl_mld *mld, 388 struct iwl_rx_packet *pkt) 389 { 390 const struct iwl_esr_trans_fail_notif *notif = (const void *)pkt->data; 391 u32 fw_link_id = le32_to_cpu(notif->link_id); 392 struct ieee80211_bss_conf *bss_conf = 393 iwl_mld_fw_id_to_link_conf(mld, fw_link_id); 394 395 IWL_DEBUG_INFO(mld, "Failed to %s EMLSR on link %d (FW: %d), reason %d\n", 396 le32_to_cpu(notif->activation) ? "enter" : "exit", 397 bss_conf ? bss_conf->link_id : -1, 398 le32_to_cpu(notif->link_id), 399 le32_to_cpu(notif->err_code)); 400 401 if (IWL_FW_CHECK(mld, !bss_conf, 402 "FW reported failure to %sactivate EMLSR on a non-existing link: %d\n", 403 le32_to_cpu(notif->activation) ? "" : "de", 404 fw_link_id)) { 405 ieee80211_iterate_active_interfaces_mtx( 406 mld->hw, IEEE80211_IFACE_ITER_NORMAL, 407 iwl_mld_vif_iter_disconnect_emlsr, NULL); 408 return; 409 } 410 411 /* Disconnect if we failed to deactivate a link */ 412 if (!le32_to_cpu(notif->activation)) { 413 ieee80211_connection_loss(bss_conf->vif); 414 return; 415 } 416 417 /* 418 * We failed to activate the second link, go back to the link specified 419 * by the firmware as that is the one that is still valid now. 420 */ 421 iwl_mld_exit_emlsr(mld, bss_conf->vif, IWL_MLD_EMLSR_EXIT_FAIL_ENTRY, 422 bss_conf->link_id); 423 } 424 425 /* Active non-station link tracking */ 426 static void iwl_mld_count_non_bss_links(void *_data, u8 *mac, 427 struct ieee80211_vif *vif) 428 { 429 struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif); 430 int *count = _data; 431 432 if (ieee80211_vif_type_p2p(vif) == NL80211_IFTYPE_STATION) 433 return; 434 435 *count += iwl_mld_count_active_links(mld_vif->mld, vif); 436 } 437 438 struct iwl_mld_update_emlsr_block_data { 439 bool block; 440 int result; 441 }; 442 443 static void 444 iwl_mld_vif_iter_update_emlsr_non_bss_block(void *_data, u8 *mac, 445 struct ieee80211_vif *vif) 446 { 447 struct iwl_mld_update_emlsr_block_data *data = _data; 448 struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif); 449 int ret; 450 451 if (data->block) { 452 ret = iwl_mld_block_emlsr_sync(mld_vif->mld, vif, 453 IWL_MLD_EMLSR_BLOCKED_NON_BSS, 454 iwl_mld_get_primary_link(vif)); 455 if (ret) 456 data->result = ret; 457 } else { 458 iwl_mld_unblock_emlsr(mld_vif->mld, vif, 459 IWL_MLD_EMLSR_BLOCKED_NON_BSS); 460 } 461 } 462 463 int iwl_mld_emlsr_check_non_bss_block(struct iwl_mld *mld, 464 int pending_link_changes) 465 { 466 /* An active link of a non-station vif blocks EMLSR. Upon activation 467 * block EMLSR on the bss vif. Upon deactivation, check if this link 468 * was the last non-station link active, and if so unblock the bss vif 469 */ 470 struct iwl_mld_update_emlsr_block_data block_data = {}; 471 int count = pending_link_changes; 472 473 /* No need to count if we are activating a non-BSS link */ 474 if (count <= 0) 475 ieee80211_iterate_active_interfaces_mtx(mld->hw, 476 IEEE80211_IFACE_ITER_NORMAL, 477 iwl_mld_count_non_bss_links, 478 &count); 479 480 /* 481 * We could skip updating it if the block change did not change (and 482 * pending_link_changes is non-zero). 483 */ 484 block_data.block = !!count; 485 486 ieee80211_iterate_active_interfaces_mtx(mld->hw, 487 IEEE80211_IFACE_ITER_NORMAL, 488 iwl_mld_vif_iter_update_emlsr_non_bss_block, 489 &block_data); 490 491 return block_data.result; 492 } 493 494 #define EMLSR_SEC_LINK_MIN_PERC 10 495 #define EMLSR_MIN_TX 3000 496 #define EMLSR_MIN_RX 400 497 498 void iwl_mld_emlsr_check_tpt(struct wiphy *wiphy, struct wiphy_work *wk) 499 { 500 struct iwl_mld_vif *mld_vif = container_of(wk, struct iwl_mld_vif, 501 emlsr.check_tpt_wk.work); 502 struct ieee80211_vif *vif = 503 container_of((void *)mld_vif, struct ieee80211_vif, drv_priv); 504 struct iwl_mld *mld = mld_vif->mld; 505 struct iwl_mld_sta *mld_sta; 506 struct iwl_mld_link *sec_link; 507 unsigned long total_tx = 0, total_rx = 0; 508 unsigned long sec_link_tx = 0, sec_link_rx = 0; 509 u8 sec_link_tx_perc, sec_link_rx_perc; 510 s8 sec_link_id; 511 512 if (!iwl_mld_vif_has_emlsr_cap(vif) || !mld_vif->ap_sta) 513 return; 514 515 mld_sta = iwl_mld_sta_from_mac80211(mld_vif->ap_sta); 516 517 /* We only count for the AP sta in a MLO connection */ 518 if (!mld_sta->mpdu_counters) 519 return; 520 521 /* This wk should only run when the TPT blocker isn't set. 522 * When the blocker is set, the decision to remove it, as well as 523 * clearing the counters is done in DP (to avoid having a wk every 524 * 5 seconds when idle. When the blocker is unset, we are not idle anyway) 525 */ 526 if (WARN_ON(mld_vif->emlsr.blocked_reasons & IWL_MLD_EMLSR_BLOCKED_TPT)) 527 return; 528 /* 529 * TPT is unblocked, need to check if the TPT criteria is still met. 530 * 531 * If EMLSR is active, then we also need to check the secondar link 532 * requirements. 533 */ 534 if (iwl_mld_emlsr_active(vif)) { 535 sec_link_id = iwl_mld_get_other_link(vif, iwl_mld_get_primary_link(vif)); 536 sec_link = iwl_mld_link_dereference_check(mld_vif, sec_link_id); 537 if (WARN_ON_ONCE(!sec_link)) 538 return; 539 /* We need the FW ID here */ 540 sec_link_id = sec_link->fw_id; 541 } else { 542 sec_link_id = -1; 543 } 544 545 /* Sum up RX and TX MPDUs from the different queues/links */ 546 for (int q = 0; q < mld->trans->num_rx_queues; q++) { 547 struct iwl_mld_per_q_mpdu_counter *queue_counter = 548 &mld_sta->mpdu_counters[q]; 549 550 spin_lock_bh(&queue_counter->lock); 551 552 /* The link IDs that doesn't exist will contain 0 */ 553 for (int link = 0; 554 link < ARRAY_SIZE(queue_counter->per_link); 555 link++) { 556 total_tx += queue_counter->per_link[link].tx; 557 total_rx += queue_counter->per_link[link].rx; 558 } 559 560 if (sec_link_id != -1) { 561 sec_link_tx += queue_counter->per_link[sec_link_id].tx; 562 sec_link_rx += queue_counter->per_link[sec_link_id].rx; 563 } 564 565 memset(queue_counter->per_link, 0, 566 sizeof(queue_counter->per_link)); 567 568 spin_unlock_bh(&queue_counter->lock); 569 } 570 571 IWL_DEBUG_INFO(mld, "total Tx MPDUs: %ld. total Rx MPDUs: %ld\n", 572 total_tx, total_rx); 573 574 /* If we don't have enough MPDUs - exit EMLSR */ 575 if (total_tx < IWL_MLD_ENTER_EMLSR_TPT_THRESH && 576 total_rx < IWL_MLD_ENTER_EMLSR_TPT_THRESH) { 577 iwl_mld_block_emlsr(mld, vif, IWL_MLD_EMLSR_BLOCKED_TPT, 578 iwl_mld_get_primary_link(vif)); 579 return; 580 } 581 582 /* EMLSR is not active */ 583 if (sec_link_id == -1) 584 return; 585 586 IWL_DEBUG_INFO(mld, "Secondary Link %d: Tx MPDUs: %ld. Rx MPDUs: %ld\n", 587 sec_link_id, sec_link_tx, sec_link_rx); 588 589 /* Calculate the percentage of the secondary link TX/RX */ 590 sec_link_tx_perc = total_tx ? sec_link_tx * 100 / total_tx : 0; 591 sec_link_rx_perc = total_rx ? sec_link_rx * 100 / total_rx : 0; 592 593 /* 594 * The TX/RX percentage is checked only if it exceeds the required 595 * minimum. In addition, RX is checked only if the TX check failed. 596 */ 597 if ((total_tx > EMLSR_MIN_TX && 598 sec_link_tx_perc < EMLSR_SEC_LINK_MIN_PERC) || 599 (total_rx > EMLSR_MIN_RX && 600 sec_link_rx_perc < EMLSR_SEC_LINK_MIN_PERC)) { 601 iwl_mld_exit_emlsr(mld, vif, IWL_MLD_EMLSR_EXIT_LINK_USAGE, 602 iwl_mld_get_primary_link(vif)); 603 return; 604 } 605 606 /* Check again when the next window ends */ 607 wiphy_delayed_work_queue(mld_vif->mld->wiphy, 608 &mld_vif->emlsr.check_tpt_wk, 609 round_jiffies_relative(IWL_MLD_TPT_COUNT_WINDOW)); 610 } 611 612 void iwl_mld_emlsr_unblock_tpt_wk(struct wiphy *wiphy, struct wiphy_work *wk) 613 { 614 struct iwl_mld_vif *mld_vif = container_of(wk, struct iwl_mld_vif, 615 emlsr.unblock_tpt_wk); 616 struct ieee80211_vif *vif = 617 container_of((void *)mld_vif, struct ieee80211_vif, drv_priv); 618 619 iwl_mld_unblock_emlsr(mld_vif->mld, vif, IWL_MLD_EMLSR_BLOCKED_TPT); 620 } 621 622 /* 623 * Link selection 624 */ 625 struct iwl_mld_link_sel_data { 626 u8 link_id; 627 const struct cfg80211_chan_def *chandef; 628 s32 signal; 629 u16 grade; 630 }; 631 632 s8 iwl_mld_get_emlsr_rssi_thresh(struct iwl_mld *mld, 633 const struct cfg80211_chan_def *chandef, 634 bool low) 635 { 636 if (WARN_ON(chandef->chan->band != NL80211_BAND_2GHZ && 637 chandef->chan->band != NL80211_BAND_5GHZ && 638 chandef->chan->band != NL80211_BAND_6GHZ)) 639 return S8_MAX; 640 641 #define RSSI_THRESHOLD(_low, _bw) \ 642 (_low) ? IWL_MLD_LOW_RSSI_THRESH_##_bw##MHZ \ 643 : IWL_MLD_HIGH_RSSI_THRESH_##_bw##MHZ 644 645 switch (chandef->width) { 646 case NL80211_CHAN_WIDTH_20_NOHT: 647 case NL80211_CHAN_WIDTH_20: 648 /* 320 MHz has the same thresholds as 20 MHz */ 649 case NL80211_CHAN_WIDTH_320: 650 return RSSI_THRESHOLD(low, 20); 651 case NL80211_CHAN_WIDTH_40: 652 return RSSI_THRESHOLD(low, 40); 653 case NL80211_CHAN_WIDTH_80: 654 return RSSI_THRESHOLD(low, 80); 655 case NL80211_CHAN_WIDTH_160: 656 return RSSI_THRESHOLD(low, 160); 657 default: 658 WARN_ON(1); 659 return S8_MAX; 660 } 661 #undef RSSI_THRESHOLD 662 } 663 664 static u32 665 iwl_mld_emlsr_disallowed_with_link(struct iwl_mld *mld, 666 struct ieee80211_vif *vif, 667 struct iwl_mld_link_sel_data *link, 668 bool primary) 669 { 670 struct wiphy *wiphy = mld->wiphy; 671 struct ieee80211_bss_conf *conf; 672 enum iwl_mld_emlsr_exit ret = 0; 673 674 conf = wiphy_dereference(wiphy, vif->link_conf[link->link_id]); 675 if (WARN_ON_ONCE(!conf)) 676 return false; 677 678 if (link->chandef->chan->band == NL80211_BAND_2GHZ && mld->bt_is_active) 679 ret |= IWL_MLD_EMLSR_EXIT_BT_COEX; 680 681 if (link->signal < 682 iwl_mld_get_emlsr_rssi_thresh(mld, link->chandef, false)) 683 ret |= IWL_MLD_EMLSR_EXIT_LOW_RSSI; 684 685 if (conf->csa_active) 686 ret |= IWL_MLD_EMLSR_EXIT_CSA; 687 688 if (ret) { 689 IWL_DEBUG_INFO(mld, 690 "Link %d is not allowed for EMLSR as %s\n", 691 link->link_id, 692 primary ? "primary" : "secondary"); 693 iwl_mld_print_emlsr_exit(mld, ret); 694 } 695 696 return ret; 697 } 698 699 static u8 700 iwl_mld_set_link_sel_data(struct iwl_mld *mld, 701 struct ieee80211_vif *vif, 702 struct iwl_mld_link_sel_data *data, 703 unsigned long usable_links, 704 u8 *best_link_idx) 705 { 706 u8 n_data = 0; 707 u16 max_grade = 0; 708 unsigned long link_id; 709 710 /* 711 * TODO: don't select links that weren't discovered in the last scan 712 * This requires mac80211 (or cfg80211) changes to forward/track when 713 * a BSS was last updated. cfg80211 already tracks this information but 714 * it is not exposed within the kernel. 715 */ 716 for_each_set_bit(link_id, &usable_links, IEEE80211_MLD_MAX_NUM_LINKS) { 717 struct ieee80211_bss_conf *link_conf = 718 link_conf_dereference_protected(vif, link_id); 719 720 if (WARN_ON_ONCE(!link_conf)) 721 continue; 722 723 /* Ignore any BSS that was not seen in the last 5 seconds */ 724 if (ktime_before(link_conf->bss->ts_boottime, 725 ktime_sub_ns(ktime_get_boottime_ns(), 726 (u64)5 * NSEC_PER_SEC))) 727 continue; 728 729 data[n_data].link_id = link_id; 730 data[n_data].chandef = &link_conf->chanreq.oper; 731 data[n_data].signal = MBM_TO_DBM(link_conf->bss->signal); 732 data[n_data].grade = iwl_mld_get_link_grade(mld, link_conf); 733 734 if (n_data == 0 || data[n_data].grade > max_grade) { 735 max_grade = data[n_data].grade; 736 *best_link_idx = n_data; 737 } 738 n_data++; 739 } 740 741 return n_data; 742 } 743 744 static bool 745 iwl_mld_valid_emlsr_pair(struct ieee80211_vif *vif, 746 struct iwl_mld_link_sel_data *a, 747 struct iwl_mld_link_sel_data *b) 748 { 749 struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif); 750 struct iwl_mld *mld = mld_vif->mld; 751 enum iwl_mld_emlsr_exit ret = 0; 752 753 /* Per-link considerations */ 754 if (iwl_mld_emlsr_disallowed_with_link(mld, vif, a, true) || 755 iwl_mld_emlsr_disallowed_with_link(mld, vif, b, false)) 756 return false; 757 758 if (a->chandef->chan->band == b->chandef->chan->band) { 759 ret |= IWL_MLD_EMLSR_EXIT_EQUAL_BAND; 760 } else if (a->chandef->width != b->chandef->width) { 761 /* TODO: task=EMLSR task=statistics 762 * replace BANDWIDTH exit reason with channel load criteria 763 */ 764 ret |= IWL_MLD_EMLSR_EXIT_BANDWIDTH; 765 } 766 767 if (ret) { 768 IWL_DEBUG_INFO(mld, 769 "Links %d and %d are not a valid pair for EMLSR\n", 770 a->link_id, b->link_id); 771 IWL_DEBUG_INFO(mld, 772 "Links bandwidth are: %d and %d\n", 773 nl80211_chan_width_to_mhz(a->chandef->width), 774 nl80211_chan_width_to_mhz(b->chandef->width)); 775 iwl_mld_print_emlsr_exit(mld, ret); 776 return false; 777 } 778 779 return true; 780 } 781 782 /* Calculation is done with fixed-point with a scaling factor of 1/256 */ 783 #define SCALE_FACTOR 256 784 785 /* 786 * Returns the combined grade of two given links. 787 * Returns 0 if EMLSR is not allowed with these 2 links. 788 */ 789 static 790 unsigned int iwl_mld_get_emlsr_grade(struct iwl_mld *mld, 791 struct ieee80211_vif *vif, 792 struct iwl_mld_link_sel_data *a, 793 struct iwl_mld_link_sel_data *b, 794 u8 *primary_id) 795 { 796 struct ieee80211_bss_conf *primary_conf; 797 struct wiphy *wiphy = ieee80211_vif_to_wdev(vif)->wiphy; 798 unsigned int primary_load; 799 800 lockdep_assert_wiphy(wiphy); 801 802 /* a is always primary, b is always secondary */ 803 if (b->grade > a->grade) 804 swap(a, b); 805 806 *primary_id = a->link_id; 807 808 if (!iwl_mld_valid_emlsr_pair(vif, a, b)) 809 return 0; 810 811 primary_conf = wiphy_dereference(wiphy, vif->link_conf[*primary_id]); 812 813 if (WARN_ON_ONCE(!primary_conf)) 814 return 0; 815 816 primary_load = iwl_mld_get_chan_load(mld, primary_conf); 817 818 /* The more the primary link is loaded, the more worthwhile EMLSR becomes */ 819 return a->grade + ((b->grade * primary_load) / SCALE_FACTOR); 820 } 821 822 static void _iwl_mld_select_links(struct iwl_mld *mld, 823 struct ieee80211_vif *vif) 824 { 825 struct iwl_mld_link_sel_data data[IEEE80211_MLD_MAX_NUM_LINKS]; 826 struct iwl_mld_link_sel_data *best_link; 827 struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif); 828 int max_active_links = iwl_mld_max_active_links(mld, vif); 829 u16 new_active, usable_links = ieee80211_vif_usable_links(vif); 830 u8 best_idx, new_primary, n_data; 831 u16 max_grade; 832 833 lockdep_assert_wiphy(mld->wiphy); 834 835 if (!mld_vif->authorized || hweight16(usable_links) <= 1) 836 return; 837 838 if (WARN(time_before(mld->scan.last_mlo_scan_jiffies, 839 jiffies - IWL_MLD_SCAN_EXPIRE_TIME), 840 "Last MLO scan was too long ago, can't select links\n")) 841 return; 842 843 /* The logic below is simple and not suited for more than 2 links */ 844 WARN_ON_ONCE(max_active_links > 2); 845 846 n_data = iwl_mld_set_link_sel_data(mld, vif, data, usable_links, 847 &best_idx); 848 849 if (WARN(!n_data, "Couldn't find a valid grade for any link!\n")) 850 return; 851 852 /* Default to selecting the single best link */ 853 best_link = &data[best_idx]; 854 new_primary = best_link->link_id; 855 new_active = BIT(best_link->link_id); 856 max_grade = best_link->grade; 857 858 /* If EMLSR is not possible, activate the best link */ 859 if (max_active_links == 1 || n_data == 1 || 860 !iwl_mld_vif_has_emlsr_cap(vif) || !IWL_MLD_AUTO_EML_ENABLE || 861 mld_vif->emlsr.blocked_reasons) 862 goto set_active; 863 864 /* Try to find the best link combination */ 865 for (u8 a = 0; a < n_data; a++) { 866 for (u8 b = a + 1; b < n_data; b++) { 867 u8 best_in_pair; 868 u16 emlsr_grade = 869 iwl_mld_get_emlsr_grade(mld, vif, 870 &data[a], &data[b], 871 &best_in_pair); 872 873 /* 874 * Prefer (new) EMLSR combination to prefer EMLSR over 875 * a single link. 876 */ 877 if (emlsr_grade < max_grade) 878 continue; 879 880 max_grade = emlsr_grade; 881 new_primary = best_in_pair; 882 new_active = BIT(data[a].link_id) | 883 BIT(data[b].link_id); 884 } 885 } 886 887 set_active: 888 IWL_DEBUG_INFO(mld, "Link selection result: 0x%x. Primary = %d\n", 889 new_active, new_primary); 890 891 mld_vif->emlsr.selected_primary = new_primary; 892 mld_vif->emlsr.selected_links = new_active; 893 894 ieee80211_set_active_links_async(vif, new_active); 895 } 896 897 static void iwl_mld_vif_iter_select_links(void *_data, u8 *mac, 898 struct ieee80211_vif *vif) 899 { 900 struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif); 901 struct iwl_mld *mld = mld_vif->mld; 902 903 _iwl_mld_select_links(mld, vif); 904 } 905 906 void iwl_mld_select_links(struct iwl_mld *mld) 907 { 908 ieee80211_iterate_active_interfaces_mtx(mld->hw, 909 IEEE80211_IFACE_ITER_NORMAL, 910 iwl_mld_vif_iter_select_links, 911 NULL); 912 } 913 914 void iwl_mld_emlsr_check_equal_bw(struct iwl_mld *mld, 915 struct ieee80211_vif *vif, 916 struct ieee80211_bss_conf *link) 917 { 918 u8 other_link_id = iwl_mld_get_other_link(vif, link->link_id); 919 struct ieee80211_bss_conf *other_link = 920 link_conf_dereference_check(vif, other_link_id); 921 922 if (!ieee80211_vif_link_active(vif, link->link_id) || 923 !iwl_mld_emlsr_active(vif) || 924 WARN_ON(link->link_id == other_link_id || !other_link)) 925 return; 926 927 if (link->chanreq.oper.width != other_link->chanreq.oper.width) 928 iwl_mld_exit_emlsr(mld, vif, IWL_MLD_EMLSR_EXIT_BANDWIDTH, 929 iwl_mld_get_primary_link(vif)); 930 } 931 932 static void iwl_mld_emlsr_check_bt_iter(void *_data, u8 *mac, 933 struct ieee80211_vif *vif) 934 { 935 struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif); 936 struct iwl_mld *mld = mld_vif->mld; 937 struct ieee80211_bss_conf *link; 938 unsigned int link_id; 939 940 if (!mld->bt_is_active) { 941 iwl_mld_retry_emlsr(mld, vif); 942 return; 943 } 944 945 /* BT is turned ON but we are not in EMLSR, nothing to do */ 946 if (!iwl_mld_emlsr_active(vif)) 947 return; 948 949 /* In EMLSR and BT is turned ON */ 950 951 for_each_vif_active_link(vif, link, link_id) { 952 if (WARN_ON(!link->chanreq.oper.chan)) 953 continue; 954 955 if (link->chanreq.oper.chan->band == NL80211_BAND_2GHZ) { 956 iwl_mld_exit_emlsr(mld, vif, IWL_MLD_EMLSR_EXIT_BT_COEX, 957 iwl_mld_get_primary_link(vif)); 958 return; 959 } 960 } 961 } 962 963 void iwl_mld_emlsr_check_bt(struct iwl_mld *mld) 964 { 965 ieee80211_iterate_active_interfaces_mtx(mld->hw, 966 IEEE80211_IFACE_ITER_NORMAL, 967 iwl_mld_emlsr_check_bt_iter, 968 NULL); 969 } 970 971 static void iwl_mld_emlsr_check_chan_load_iter(void *_data, u8 *mac, 972 struct ieee80211_vif *vif) 973 { 974 struct iwl_mld *mld = (struct iwl_mld *)_data; 975 struct ieee80211_bss_conf *prim_link; 976 unsigned int prim_link_id; 977 int chan_load; 978 979 if (!iwl_mld_emlsr_active(vif)) 980 return; 981 982 prim_link_id = iwl_mld_get_primary_link(vif); 983 prim_link = link_conf_dereference_protected(vif, prim_link_id); 984 if (WARN_ON(!prim_link)) 985 return; 986 987 chan_load = iwl_mld_get_chan_load_by_others(mld, prim_link, true); 988 989 if (chan_load < 0) 990 return; 991 992 /* chan_load is in range [0,255] */ 993 if (chan_load < NORMALIZE_PERCENT_TO_255(IWL_MLD_CHAN_LOAD_THRESH)) 994 iwl_mld_exit_emlsr(mld, vif, IWL_MLD_EMLSR_EXIT_CHAN_LOAD, 995 prim_link_id); 996 } 997 998 void iwl_mld_emlsr_check_chan_load(struct iwl_mld *mld) 999 { 1000 ieee80211_iterate_active_interfaces_mtx(mld->hw, 1001 IEEE80211_IFACE_ITER_NORMAL, 1002 iwl_mld_emlsr_check_chan_load_iter, 1003 (void *)(uintptr_t)mld); 1004 } 1005 1006 void iwl_mld_retry_emlsr(struct iwl_mld *mld, struct ieee80211_vif *vif) 1007 { 1008 struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif); 1009 1010 if (!iwl_mld_vif_has_emlsr_cap(vif) || iwl_mld_emlsr_active(vif) || 1011 mld_vif->emlsr.blocked_reasons) 1012 return; 1013 1014 iwl_mld_trigger_link_selection(mld, vif); 1015 } 1016