Lines Matching +full:fixed +full:- +full:links
1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
3 * Copyright (C) 2024-2025 Intel Corporation
90 if (WARN_ON(!(mld_vif->emlsr.blocked_reasons & in iwl_mld_emlsr_prevent_done_wk()
94 iwl_mld_unblock_emlsr(mld_vif->mld, vif, in iwl_mld_emlsr_prevent_done_wk()
106 if (WARN_ON(!(mld_vif->emlsr.blocked_reasons & in iwl_mld_emlsr_tmp_non_bss_done_wk()
110 iwl_mld_unblock_emlsr(mld_vif->mld, vif, in iwl_mld_emlsr_tmp_non_bss_done_wk()
137 if (time_after(jiffies, mld_vif->emlsr.last_exit_ts + in iwl_mld_check_emlsr_prevention()
139 mld_vif->emlsr.last_exit_reason != reason) in iwl_mld_check_emlsr_prevention()
140 mld_vif->emlsr.exit_repeat_count = 0; in iwl_mld_check_emlsr_prevention()
142 mld_vif->emlsr.last_exit_reason = reason; in iwl_mld_check_emlsr_prevention()
143 mld_vif->emlsr.last_exit_ts = jiffies; in iwl_mld_check_emlsr_prevention()
144 mld_vif->emlsr.exit_repeat_count++; in iwl_mld_check_emlsr_prevention()
154 mld_vif->emlsr.blocked_reasons |= IWL_MLD_EMLSR_BLOCKED_PREVENTION; in iwl_mld_check_emlsr_prevention()
158 if (mld_vif->emlsr.exit_repeat_count > 1 && in iwl_mld_check_emlsr_prevention()
160 if (mld_vif->emlsr.exit_repeat_count == 2) in iwl_mld_check_emlsr_prevention()
169 WARN_ON(mld_vif->emlsr.exit_repeat_count > 3); in iwl_mld_check_emlsr_prevention()
174 delay / HZ, mld_vif->emlsr.exit_repeat_count, in iwl_mld_check_emlsr_prevention()
177 wiphy_delayed_work_queue(mld->wiphy, in iwl_mld_check_emlsr_prevention()
178 &mld_vif->emlsr.prevent_done_wk, delay); in iwl_mld_check_emlsr_prevention()
191 phy->avg_channel_load_not_by_us = 0; in iwl_mld_clear_avg_chan_load_iter()
202 lockdep_assert_wiphy(mld->wiphy); in _iwl_mld_exit_emlsr()
212 if (WARN_ON(!ieee80211_vif_is_mld(vif) || !mld_vif->authorized)) in _iwl_mld_exit_emlsr()
215 if (WARN_ON(!(vif->active_links & BIT(link_to_keep)))) in _iwl_mld_exit_emlsr()
216 link_to_keep = __ffs(vif->active_links); in _iwl_mld_exit_emlsr()
220 "Exiting EMLSR. reason = %s (0x%x). Current active links=0x%x, new active links = 0x%x\n", in _iwl_mld_exit_emlsr()
222 vif->active_links, new_active_links); in _iwl_mld_exit_emlsr()
235 ieee80211_iter_chan_contexts_atomic(mld->hw, in _iwl_mld_exit_emlsr()
254 lockdep_assert_wiphy(mld->wiphy); in _iwl_mld_emlsr_block()
259 if (mld_vif->emlsr.blocked_reasons & reason) in _iwl_mld_emlsr_block()
262 mld_vif->emlsr.blocked_reasons |= reason; in _iwl_mld_emlsr_block()
267 iwl_mld_print_emlsr_blocked(mld, mld_vif->emlsr.blocked_reasons); in _iwl_mld_emlsr_block()
270 wiphy_delayed_work_cancel(mld_vif->mld->wiphy, in _iwl_mld_emlsr_block()
271 &mld_vif->emlsr.check_tpt_wk); in _iwl_mld_emlsr_block()
297 lockdep_assert_wiphy(mld->wiphy); in iwl_mld_unblock_emlsr()
302 if (!(mld_vif->emlsr.blocked_reasons & reason)) in iwl_mld_unblock_emlsr()
305 mld_vif->emlsr.blocked_reasons &= ~reason; in iwl_mld_unblock_emlsr()
310 iwl_mld_print_emlsr_blocked(mld, mld_vif->emlsr.blocked_reasons); in iwl_mld_unblock_emlsr()
313 wiphy_delayed_work_queue(mld_vif->mld->wiphy, in iwl_mld_unblock_emlsr()
314 &mld_vif->emlsr.check_tpt_wk, in iwl_mld_unblock_emlsr()
317 if (mld_vif->emlsr.blocked_reasons) in iwl_mld_unblock_emlsr()
334 switch (le32_to_cpu(notif->action)) { in iwl_mld_vif_iter_emlsr_mode_notif()
336 iwl_mld_exit_emlsr(mld_vif->mld, vif, in iwl_mld_vif_iter_emlsr_mode_notif()
343 IWL_WARN(mld_vif->mld, "Unexpected EMLSR notification: %d\n", in iwl_mld_vif_iter_emlsr_mode_notif()
344 le32_to_cpu(notif->action)); in iwl_mld_vif_iter_emlsr_mode_notif()
351 ieee80211_iterate_active_interfaces_mtx(mld->hw, in iwl_mld_handle_emlsr_mode_notif()
354 pkt->data); in iwl_mld_handle_emlsr_mode_notif()
370 const struct iwl_esr_trans_fail_notif *notif = (const void *)pkt->data; in iwl_mld_handle_emlsr_trans_fail_notif()
371 u32 fw_link_id = le32_to_cpu(notif->link_id); in iwl_mld_handle_emlsr_trans_fail_notif()
376 le32_to_cpu(notif->activation) ? "enter" : "exit", in iwl_mld_handle_emlsr_trans_fail_notif()
377 bss_conf ? bss_conf->link_id : -1, in iwl_mld_handle_emlsr_trans_fail_notif()
378 le32_to_cpu(notif->link_id), in iwl_mld_handle_emlsr_trans_fail_notif()
379 le32_to_cpu(notif->err_code)); in iwl_mld_handle_emlsr_trans_fail_notif()
382 "FW reported failure to %sactivate EMLSR on a non-existing link: %d\n", in iwl_mld_handle_emlsr_trans_fail_notif()
383 le32_to_cpu(notif->activation) ? "" : "de", in iwl_mld_handle_emlsr_trans_fail_notif()
386 mld->hw, IEEE80211_IFACE_ITER_NORMAL, in iwl_mld_handle_emlsr_trans_fail_notif()
392 if (!le32_to_cpu(notif->activation)) { in iwl_mld_handle_emlsr_trans_fail_notif()
393 ieee80211_connection_loss(bss_conf->vif); in iwl_mld_handle_emlsr_trans_fail_notif()
401 iwl_mld_exit_emlsr(mld, bss_conf->vif, IWL_MLD_EMLSR_EXIT_FAIL_ENTRY, in iwl_mld_handle_emlsr_trans_fail_notif()
402 bss_conf->link_id); in iwl_mld_handle_emlsr_trans_fail_notif()
405 /* Active non-station link tracking */
415 *count += iwl_mld_count_active_links(mld_vif->mld, vif); in iwl_mld_count_non_bss_links()
431 if (data->block) { in iwl_mld_vif_iter_update_emlsr_non_bss_block()
432 ret = iwl_mld_block_emlsr_sync(mld_vif->mld, vif, in iwl_mld_vif_iter_update_emlsr_non_bss_block()
436 data->result = ret; in iwl_mld_vif_iter_update_emlsr_non_bss_block()
438 iwl_mld_unblock_emlsr(mld_vif->mld, vif, in iwl_mld_vif_iter_update_emlsr_non_bss_block()
446 /* An active link of a non-station vif blocks EMLSR. Upon activation in iwl_mld_emlsr_check_non_bss_block()
448 * was the last non-station link active, and if so unblock the bss vif in iwl_mld_emlsr_check_non_bss_block()
453 /* No need to count if we are activating a non-BSS link */ in iwl_mld_emlsr_check_non_bss_block()
455 ieee80211_iterate_active_interfaces_mtx(mld->hw, in iwl_mld_emlsr_check_non_bss_block()
462 * pending_link_changes is non-zero). in iwl_mld_emlsr_check_non_bss_block()
466 ieee80211_iterate_active_interfaces_mtx(mld->hw, in iwl_mld_emlsr_check_non_bss_block()
484 struct iwl_mld *mld = mld_vif->mld; in iwl_mld_emlsr_check_tpt()
492 if (!iwl_mld_vif_has_emlsr_cap(vif) || !mld_vif->ap_sta) in iwl_mld_emlsr_check_tpt()
495 mld_sta = iwl_mld_sta_from_mac80211(mld_vif->ap_sta); in iwl_mld_emlsr_check_tpt()
498 if (!mld_sta->mpdu_counters) in iwl_mld_emlsr_check_tpt()
506 if (WARN_ON(mld_vif->emlsr.blocked_reasons & IWL_MLD_EMLSR_BLOCKED_TPT)) in iwl_mld_emlsr_check_tpt()
520 sec_link_id = sec_link->fw_id; in iwl_mld_emlsr_check_tpt()
522 sec_link_id = -1; in iwl_mld_emlsr_check_tpt()
525 /* Sum up RX and TX MPDUs from the different queues/links */ in iwl_mld_emlsr_check_tpt()
526 for (int q = 0; q < mld->trans->num_rx_queues; q++) { in iwl_mld_emlsr_check_tpt()
528 &mld_sta->mpdu_counters[q]; in iwl_mld_emlsr_check_tpt()
530 spin_lock_bh(&queue_counter->lock); in iwl_mld_emlsr_check_tpt()
534 link < ARRAY_SIZE(queue_counter->per_link); in iwl_mld_emlsr_check_tpt()
536 total_tx += queue_counter->per_link[link].tx; in iwl_mld_emlsr_check_tpt()
537 total_rx += queue_counter->per_link[link].rx; in iwl_mld_emlsr_check_tpt()
540 if (sec_link_id != -1) { in iwl_mld_emlsr_check_tpt()
541 sec_link_tx += queue_counter->per_link[sec_link_id].tx; in iwl_mld_emlsr_check_tpt()
542 sec_link_rx += queue_counter->per_link[sec_link_id].rx; in iwl_mld_emlsr_check_tpt()
545 memset(queue_counter->per_link, 0, in iwl_mld_emlsr_check_tpt()
546 sizeof(queue_counter->per_link)); in iwl_mld_emlsr_check_tpt()
548 spin_unlock_bh(&queue_counter->lock); in iwl_mld_emlsr_check_tpt()
554 /* If we don't have enough MPDUs - exit EMLSR */ in iwl_mld_emlsr_check_tpt()
563 if (sec_link_id == -1) in iwl_mld_emlsr_check_tpt()
587 wiphy_delayed_work_queue(mld_vif->mld->wiphy, in iwl_mld_emlsr_check_tpt()
588 &mld_vif->emlsr.check_tpt_wk, in iwl_mld_emlsr_check_tpt()
599 iwl_mld_unblock_emlsr(mld_vif->mld, vif, IWL_MLD_EMLSR_BLOCKED_TPT); in iwl_mld_emlsr_unblock_tpt_wk()
610 if (WARN_ON(chandef->chan->band != NL80211_BAND_2GHZ && in iwl_mld_get_emlsr_rssi_thresh()
611 chandef->chan->band != NL80211_BAND_5GHZ && in iwl_mld_get_emlsr_rssi_thresh()
612 chandef->chan->band != NL80211_BAND_6GHZ)) in iwl_mld_get_emlsr_rssi_thresh()
619 switch (chandef->width) { in iwl_mld_get_emlsr_rssi_thresh()
644 struct wiphy *wiphy = mld->wiphy; in iwl_mld_emlsr_disallowed_with_link()
648 conf = wiphy_dereference(wiphy, vif->link_conf[link->link_id]); in iwl_mld_emlsr_disallowed_with_link()
652 if (link->chandef->chan->band == NL80211_BAND_2GHZ && mld->bt_is_active) in iwl_mld_emlsr_disallowed_with_link()
655 if (link->signal < in iwl_mld_emlsr_disallowed_with_link()
656 iwl_mld_get_emlsr_rssi_thresh(mld, link->chandef, false)) in iwl_mld_emlsr_disallowed_with_link()
659 if (conf->csa_active) in iwl_mld_emlsr_disallowed_with_link()
665 link->link_id, in iwl_mld_emlsr_disallowed_with_link()
685 * TODO: don't select links that weren't discovered in the last scan in iwl_mld_set_link_sel_data()
698 if (ktime_before(link_conf->bss->ts_boottime, in iwl_mld_set_link_sel_data()
699 mld->scan.last_mlo_scan_time)) in iwl_mld_set_link_sel_data()
703 data[n_data].chandef = &link_conf->chanreq.oper; in iwl_mld_set_link_sel_data()
704 data[n_data].signal = MBM_TO_DBM(link_conf->bss->signal); in iwl_mld_set_link_sel_data()
722 switch (phy->chandef.width) { in iwl_mld_get_min_chan_load_thresh()
742 iwl_mld_link_dereference_check(mld_vif, a->link_id); in iwl_mld_channel_load_allows_emlsr()
747 if (!link_a || !link_a->active) { in iwl_mld_channel_load_allows_emlsr()
752 chanctx_a = wiphy_dereference(mld->wiphy, link_a->chan_ctx); in iwl_mld_channel_load_allows_emlsr()
758 iwl_mld_phy_from_mac80211(chanctx_a)->avg_channel_load_not_by_us; in iwl_mld_channel_load_allows_emlsr()
772 if (a->chandef->width <= b->chandef->width) in iwl_mld_channel_load_allows_emlsr()
775 bw_a = nl80211_chan_width_to_mhz(a->chandef->width); in iwl_mld_channel_load_allows_emlsr()
776 bw_b = nl80211_chan_width_to_mhz(b->chandef->width); in iwl_mld_channel_load_allows_emlsr()
799 struct iwl_mld *mld = mld_vif->mld; in iwl_mld_valid_emlsr_pair()
802 /* Per-link considerations */ in iwl_mld_valid_emlsr_pair()
807 if (a->chandef->chan->band == b->chandef->chan->band) in iwl_mld_valid_emlsr_pair()
814 "Links %d and %d are not a valid pair for EMLSR\n", in iwl_mld_valid_emlsr_pair()
815 a->link_id, b->link_id); in iwl_mld_valid_emlsr_pair()
817 "Links bandwidth are: %d and %d\n", in iwl_mld_valid_emlsr_pair()
818 nl80211_chan_width_to_mhz(a->chandef->width), in iwl_mld_valid_emlsr_pair()
819 nl80211_chan_width_to_mhz(b->chandef->width)); in iwl_mld_valid_emlsr_pair()
827 /* Calculation is done with fixed-point with a scaling factor of 1/256 */
831 * Returns the combined grade of two given links.
832 * Returns 0 if EMLSR is not allowed with these 2 links.
842 struct wiphy *wiphy = ieee80211_vif_to_wdev(vif)->wiphy; in iwl_mld_get_emlsr_grade()
848 if (b->grade > a->grade) in iwl_mld_get_emlsr_grade()
851 *primary_id = a->link_id; in iwl_mld_get_emlsr_grade()
856 primary_conf = wiphy_dereference(wiphy, vif->link_conf[*primary_id]); in iwl_mld_get_emlsr_grade()
864 return a->grade + ((b->grade * primary_load) / SCALE_FACTOR); in iwl_mld_get_emlsr_grade()
878 lockdep_assert_wiphy(mld->wiphy); in _iwl_mld_select_links()
880 if (!mld_vif->authorized || hweight16(usable_links) <= 1) in _iwl_mld_select_links()
883 if (WARN(ktime_before(mld->scan.last_mlo_scan_time, in _iwl_mld_select_links()
886 "Last MLO scan was too long ago, can't select links\n")) in _iwl_mld_select_links()
889 /* The logic below is simple and not suited for more than 2 links */ in _iwl_mld_select_links()
900 new_primary = best_link->link_id; in _iwl_mld_select_links()
901 new_active = BIT(best_link->link_id); in _iwl_mld_select_links()
902 max_grade = best_link->grade; in _iwl_mld_select_links()
907 mld_vif->emlsr.blocked_reasons) in _iwl_mld_select_links()
937 mld_vif->emlsr.selected_primary = new_primary; in _iwl_mld_select_links()
938 mld_vif->emlsr.selected_links = new_active; in _iwl_mld_select_links()
947 struct iwl_mld *mld = mld_vif->mld; in iwl_mld_vif_iter_select_links()
954 ieee80211_iterate_active_interfaces_mtx(mld->hw, in iwl_mld_select_links()
964 struct iwl_mld *mld = mld_vif->mld; in iwl_mld_emlsr_check_bt_iter()
968 if (!mld->bt_is_active) { in iwl_mld_emlsr_check_bt_iter()
980 if (WARN_ON(!link->chanreq.oper.chan)) in iwl_mld_emlsr_check_bt_iter()
983 if (link->chanreq.oper.chan->band == NL80211_BAND_2GHZ) { in iwl_mld_emlsr_check_bt_iter()
993 ieee80211_iterate_active_interfaces_mtx(mld->hw, in iwl_mld_emlsr_check_bt()
1008 const struct iwl_mld_phy *phy = data->phy; in iwl_mld_chan_load_update_iter()
1012 struct iwl_mld *mld = iwl_mld_vif_from_mac80211(vif)->mld; in iwl_mld_chan_load_update_iter()
1022 if (chanctx != rcu_access_pointer(prim_link->chanctx_conf)) in iwl_mld_chan_load_update_iter()
1038 u32 old_chan_load = data->prev_chan_load_not_by_us; in iwl_mld_chan_load_update_iter()
1039 u32 new_chan_load = phy->avg_channel_load_not_by_us; in iwl_mld_chan_load_update_iter()
1072 mld_vif->emlsr.blocked_reasons) in iwl_mld_retry_emlsr()