Lines Matching +full:fixed +full:- +full:links

1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
3 * Copyright (C) 2022 - 2024 Intel Corporation
6 #include "time-event.h"
57 lockdep_assert_held(&mvm->mutex); in iwl_mvm_get_free_fw_link_id()
59 for (i = 0; i < ARRAY_SIZE(mvm->link_id_to_link_conf); i++) in iwl_mvm_get_free_fw_link_id()
60 if (!rcu_access_pointer(mvm->link_id_to_link_conf[i])) in iwl_mvm_get_free_fw_link_id()
72 cmd->action = cpu_to_le32(action); in iwl_mvm_link_cmd_send()
87 mvmvif->link[link_conf->link_id]; in iwl_mvm_set_link_mapping()
89 if (link_info->fw_link_id == IWL_MVM_FW_LINK_ID_INVALID) { in iwl_mvm_set_link_mapping()
90 link_info->fw_link_id = iwl_mvm_get_free_fw_link_id(mvm, in iwl_mvm_set_link_mapping()
92 if (link_info->fw_link_id >= in iwl_mvm_set_link_mapping()
93 ARRAY_SIZE(mvm->link_id_to_link_conf)) in iwl_mvm_set_link_mapping()
94 return -EINVAL; in iwl_mvm_set_link_mapping()
96 rcu_assign_pointer(mvm->link_id_to_link_conf[link_info->fw_link_id], in iwl_mvm_set_link_mapping()
107 unsigned int link_id = link_conf->link_id; in iwl_mvm_add_link()
108 struct iwl_mvm_vif_link_info *link_info = mvmvif->link[link_id]; in iwl_mvm_add_link()
111 u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id, 1); in iwl_mvm_add_link()
115 return -EINVAL; in iwl_mvm_add_link()
121 /* Update SF - Disable if needed. if this fails, SF might still be on in iwl_mvm_add_link()
122 * while many macs are bound, which is forbidden - so fail the binding. in iwl_mvm_add_link()
125 return -EINVAL; in iwl_mvm_add_link()
127 cmd.link_id = cpu_to_le32(link_info->fw_link_id); in iwl_mvm_add_link()
128 cmd.mac_id = cpu_to_le32(mvmvif->id); in iwl_mvm_add_link()
129 cmd.spec_link_id = link_conf->link_id; in iwl_mvm_add_link()
130 WARN_ON_ONCE(link_info->phy_ctxt); in iwl_mvm_add_link()
133 memcpy(cmd.local_link_addr, link_conf->addr, ETH_ALEN); in iwl_mvm_add_link()
135 if (vif->type == NL80211_IFTYPE_ADHOC && link_conf->bssid) in iwl_mvm_add_link()
136 memcpy(cmd.ibss_bssid_addr, link_conf->bssid, ETH_ALEN); in iwl_mvm_add_link()
139 cmd.listen_lmac = cpu_to_le32(link_info->listen_lmac); in iwl_mvm_add_link()
162 mvmvif->link[link_id]; in iwl_mvm_esr_vif_iterator()
163 if (vif == data->vif && link_id == data->link_id) in iwl_mvm_esr_vif_iterator()
165 if (link_info->active) in iwl_mvm_esr_vif_iterator()
166 data->lift_block = false; in iwl_mvm_esr_vif_iterator()
173 /* An active link of a non-station vif blocks EMLSR. Upon activation in iwl_mvm_esr_non_bss_link()
175 * was the last non-station link active, and if so unblock the bss vif in iwl_mvm_esr_non_bss_link()
191 ieee80211_iterate_active_interfaces(mvm->hw, in iwl_mvm_esr_non_bss_link()
195 mutex_lock(&mvm->mutex); in iwl_mvm_esr_non_bss_link()
197 mutex_unlock(&mvm->mutex); in iwl_mvm_esr_non_bss_link()
208 unsigned int link_id = link_conf->link_id; in iwl_mvm_link_changed()
209 struct iwl_mvm_vif_link_info *link_info = mvmvif->link[link_id]; in iwl_mvm_link_changed()
215 u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id, 1); in iwl_mvm_link_changed()
218 link_info->fw_link_id == IWL_MVM_FW_LINK_ID_INVALID)) in iwl_mvm_link_changed()
219 return -EINVAL; in iwl_mvm_link_changed()
228 if (!link_info->phy_ctxt) in iwl_mvm_link_changed()
234 WARN_ON_ONCE(active == link_info->active); in iwl_mvm_link_changed()
239 if (!active && vif->type == NL80211_IFTYPE_STATION) { in iwl_mvm_link_changed()
241 if (link_info->csa_block_tx) { in iwl_mvm_link_changed()
243 link_info->csa_block_tx = false; in iwl_mvm_link_changed()
248 cmd.link_id = cpu_to_le32(link_info->fw_link_id); in iwl_mvm_link_changed()
253 phyctxt = link_info->phy_ctxt; in iwl_mvm_link_changed()
255 cmd.phy_id = cpu_to_le32(phyctxt->id); in iwl_mvm_link_changed()
258 cmd.mac_id = cpu_to_le32(mvmvif->id); in iwl_mvm_link_changed()
260 memcpy(cmd.local_link_addr, link_conf->addr, ETH_ALEN); in iwl_mvm_link_changed()
264 if (vif->type == NL80211_IFTYPE_ADHOC && link_conf->bssid) in iwl_mvm_link_changed()
265 memcpy(cmd.ibss_bssid_addr, link_conf->bssid, ETH_ALEN); in iwl_mvm_link_changed()
270 cmd.cck_short_preamble = cpu_to_le32(link_conf->use_short_preamble); in iwl_mvm_link_changed()
271 cmd.short_slot = cpu_to_le32(link_conf->use_short_slot); in iwl_mvm_link_changed()
283 cmd.bi = cpu_to_le32(link_conf->beacon_int); in iwl_mvm_link_changed()
284 cmd.dtim_interval = cpu_to_le32(link_conf->beacon_int * in iwl_mvm_link_changed()
285 link_conf->dtim_period); in iwl_mvm_link_changed()
287 if (!link_conf->he_support || iwlwifi_mod_params.disable_11ax || in iwl_mvm_link_changed()
288 (vif->type == NL80211_IFTYPE_STATION && !vif->cfg.assoc)) { in iwl_mvm_link_changed()
293 cmd.htc_trig_based_pkt_ext = link_conf->htc_trig_based_pkt_ext; in iwl_mvm_link_changed()
295 if (link_conf->uora_exists) { in iwl_mvm_link_changed()
297 link_conf->uora_ocw_range & 0x7; in iwl_mvm_link_changed()
299 (link_conf->uora_ocw_range >> 3) & 0x7; in iwl_mvm_link_changed()
303 if (changes & LINK_CONTEXT_MODIFY_HE_PARAMS && mvmvif->ap_sta) { in iwl_mvm_link_changed()
305 link_sta_dereference_check(mvmvif->ap_sta, link_id); in iwl_mvm_link_changed()
307 if (!WARN_ON(!link_sta) && link_sta->he_cap.has_he && in iwl_mvm_link_changed()
308 link_sta->he_cap.he_cap_elem.mac_cap_info[5] & in iwl_mvm_link_changed()
315 if (iwl_mvm_set_fw_mu_edca_params(mvm, mvmvif->link[link_id], in iwl_mvm_link_changed()
326 ctx = rcu_dereference(link_conf->chanctx_conf); in iwl_mvm_link_changed()
331 !link_conf->eht_support || !def || in iwl_mvm_link_changed()
332 iwl_fw_lookup_cmd_ver(mvm->fw, PHY_CONTEXT_CMD, 1) >= 6) in iwl_mvm_link_changed()
335 cmd.puncture_mask = cpu_to_le16(def->punctured); in iwl_mvm_link_changed()
339 cmd.bss_color = link_conf->he_bss_color.color; in iwl_mvm_link_changed()
341 if (!link_conf->he_bss_color.enabled) { in iwl_mvm_link_changed()
346 cmd.frame_time_rts_th = cpu_to_le16(link_conf->frame_time_rts_th); in iwl_mvm_link_changed()
348 /* Block 26-tone RU OFDMA transmissions */ in iwl_mvm_link_changed()
349 if (link_info->he_ru_2mhz_block) { in iwl_mvm_link_changed()
354 if (link_conf->nontransmitted) { in iwl_mvm_link_changed()
356 link_conf->transmitter_bssid); in iwl_mvm_link_changed()
357 cmd.bssid_index = link_conf->bssid_index; in iwl_mvm_link_changed()
364 cmd.spec_link_id = link_conf->link_id; in iwl_mvm_link_changed()
366 cmd.listen_lmac = cpu_to_le32(link_info->listen_lmac); in iwl_mvm_link_changed()
370 link_info->active = active; in iwl_mvm_link_changed()
380 mvmvif->link[link_conf->link_id]; in iwl_mvm_unset_link_mapping()
384 link_info->fw_link_id >= in iwl_mvm_unset_link_mapping()
385 ARRAY_SIZE(mvm->link_id_to_link_conf))) in iwl_mvm_unset_link_mapping()
386 return -EINVAL; in iwl_mvm_unset_link_mapping()
388 RCU_INIT_POINTER(mvm->link_id_to_link_conf[link_info->fw_link_id], in iwl_mvm_unset_link_mapping()
397 unsigned int link_id = link_conf->link_id; in iwl_mvm_remove_link()
398 struct iwl_mvm_vif_link_info *link_info = mvmvif->link[link_id]; in iwl_mvm_remove_link()
406 cmd.link_id = cpu_to_le32(link_info->fw_link_id); in iwl_mvm_remove_link()
407 link_info->fw_link_id = IWL_MVM_FW_LINK_ID_INVALID; in iwl_mvm_remove_link()
408 cmd.spec_link_id = link_conf->link_id; in iwl_mvm_remove_link()
453 * The grades are actually estimated throughput, represented as fixed-point
457 RSSI_TO_GRADE_LINE(-85, -89, 177),
458 RSSI_TO_GRADE_LINE(-83, -86, 344),
459 RSSI_TO_GRADE_LINE(-82, -85, 516),
460 RSSI_TO_GRADE_LINE(-80, -83, 688),
461 RSSI_TO_GRADE_LINE(-77, -79, 1032),
462 RSSI_TO_GRADE_LINE(-73, -76, 1376),
463 RSSI_TO_GRADE_LINE(-70, -74, 1548),
464 RSSI_TO_GRADE_LINE(-69, -72, 1750),
465 RSSI_TO_GRADE_LINE(-65, -68, 2064),
466 RSSI_TO_GRADE_LINE(-61, -66, 2294),
467 RSSI_TO_GRADE_LINE(-58, -61, 2580),
468 RSSI_TO_GRADE_LINE(-55, -58, 2868),
469 RSSI_TO_GRADE_LINE(-46, -55, 3098),
470 RSSI_TO_GRADE_LINE(-43, -54, 3442)
473 #define MAX_GRADE (rssi_to_grade_map[ARRAY_SIZE(rssi_to_grade_map) - 1].grade)
479 /* Factors calculation is done with fixed-point with a scaling factor of 1/256 */
489 link_conf->chanreq.oper.width; in iwl_mvm_get_puncturing_factor()
504 n_punctured = hweight16(link_conf->chanreq.oper.punctured); in iwl_mvm_get_puncturing_factor()
507 return SCALE_FACTOR - puncturing_penalty; in iwl_mvm_get_puncturing_factor()
513 struct ieee80211_vif *vif = link_conf->vif; in iwl_mvm_get_chan_load()
515 iwl_mvm_vif_from_mac80211(link_conf->vif)->link[link_conf->link_id]; in iwl_mvm_get_chan_load()
518 enum nl80211_band band = link_conf->chanreq.oper.chan->band; in iwl_mvm_get_chan_load()
524 if (ieee80211_vif_link_active(vif, link_conf->link_id)) in iwl_mvm_get_chan_load()
525 ies = rcu_dereference(link_conf->bss->beacon_ies); in iwl_mvm_get_chan_load()
527 ies = rcu_dereference(link_conf->bss->ies); in iwl_mvm_get_chan_load()
531 ies->data, ies->len); in iwl_mvm_get_chan_load()
537 bss_load_elem->datalen != sizeof(*bss_load)) { in iwl_mvm_get_chan_load()
557 bss_load = (const void *)bss_load_elem->data; in iwl_mvm_get_chan_load()
558 /* Channel util is in range 0-255 */ in iwl_mvm_get_chan_load()
559 chan_load = bss_load->channel_util; in iwl_mvm_get_chan_load()
562 if (!mvm_link || !mvm_link->active) in iwl_mvm_get_chan_load()
565 if (WARN_ONCE(!mvm_link->phy_ctxt, in iwl_mvm_get_chan_load()
567 link_conf->link_id)) in iwl_mvm_get_chan_load()
572 NORMALIZE_PERCENT_TO_255(mvm_link->phy_ctxt->channel_load_by_us); in iwl_mvm_get_chan_load()
576 chan_load -= chan_load_by_us; in iwl_mvm_get_chan_load()
584 return SCALE_FACTOR - iwl_mvm_get_chan_load(link_conf); in iwl_mvm_get_chan_load_factor()
599 band = link_conf->chanreq.oper.chan->band; in iwl_mvm_get_link_grade()
606 link_rssi = MBM_TO_DBM(link_conf->bss->signal); in iwl_mvm_get_link_grade()
616 /* No valid RSSI - take the lowest grade */ in iwl_mvm_get_link_grade()
625 if (link_rssi > line->rssi[rssi_idx]) in iwl_mvm_get_link_grade()
627 grade = line->grade; in iwl_mvm_get_link_grade()
648 /* TODO: don't select links that weren't discovered in the last scan */ in iwl_mvm_set_link_selection_data()
657 data[n_data].chandef = &link_conf->chanreq.oper; in iwl_mvm_set_link_selection_data()
658 data[n_data].signal = link_conf->bss->signal / 100; in iwl_mvm_set_link_selection_data()
696 if (WARN_ON(chandef->chan->band != NL80211_BAND_2GHZ && in iwl_mvm_get_esr_rssi_thresh()
697 chandef->chan->band != NL80211_BAND_5GHZ && in iwl_mvm_get_esr_rssi_thresh()
698 chandef->chan->band != NL80211_BAND_6GHZ)) in iwl_mvm_get_esr_rssi_thresh()
707 return low ? threshs->low : threshs->high; in iwl_mvm_get_esr_rssi_thresh()
716 struct wiphy *wiphy = mvm->hw->wiphy; in iwl_mvm_esr_disallowed_with_link()
721 conf = wiphy_dereference(wiphy, vif->link_conf[link->link_id]); in iwl_mvm_esr_disallowed_with_link()
725 /* BT Coex effects eSR mode only if one of the links is on LB */ in iwl_mvm_esr_disallowed_with_link()
726 if (link->chandef->chan->band == NL80211_BAND_2GHZ && in iwl_mvm_esr_disallowed_with_link()
727 (!iwl_mvm_bt_coex_calculate_esr_mode(mvm, vif, link->signal, in iwl_mvm_esr_disallowed_with_link()
731 thresh = iwl_mvm_get_esr_rssi_thresh(mvm, link->chandef, in iwl_mvm_esr_disallowed_with_link()
734 if (link->signal < thresh) in iwl_mvm_esr_disallowed_with_link()
737 if (conf->csa_active) in iwl_mvm_esr_disallowed_with_link()
743 link->link_id); in iwl_mvm_esr_disallowed_with_link()
755 struct iwl_mvm *mvm = mvmvif->mvm; in iwl_mvm_mld_valid_link_pair()
758 /* Per-link considerations */ in iwl_mvm_mld_valid_link_pair()
763 if (a->chandef->width != b->chandef->width || in iwl_mvm_mld_valid_link_pair()
764 !(a->chandef->chan->band == NL80211_BAND_6GHZ && in iwl_mvm_mld_valid_link_pair()
765 b->chandef->chan->band == NL80211_BAND_5GHZ)) in iwl_mvm_mld_valid_link_pair()
770 "Links %d and %d are not a valid pair for EMLSR\n", in iwl_mvm_mld_valid_link_pair()
771 a->link_id, b->link_id); in iwl_mvm_mld_valid_link_pair()
782 * Returns the combined eSR grade of two given links.
783 * Returns 0 if eSR is not allowed with these 2 links.
792 struct wiphy *wiphy = ieee80211_vif_to_wdev(vif)->wiphy; in iwl_mvm_get_esr_grade()
798 if (b->grade > a->grade) in iwl_mvm_get_esr_grade()
801 *primary_id = a->link_id; in iwl_mvm_get_esr_grade()
806 primary_conf = wiphy_dereference(wiphy, vif->link_conf[*primary_id]); in iwl_mvm_get_esr_grade()
813 return a->grade + in iwl_mvm_get_esr_grade()
814 ((b->grade * primary_load) / SCALE_FACTOR); in iwl_mvm_get_esr_grade()
827 lockdep_assert_wiphy(mvm->hw->wiphy); in iwl_mvm_select_links()
829 if (!mvmvif->authorized || !ieee80211_vif_is_mld(vif)) in iwl_mvm_select_links()
836 * links in iwl_mvm_select_links()
847 primary_link = best_link->link_id; in iwl_mvm_select_links()
848 new_active_links = BIT(best_link->link_id); in iwl_mvm_select_links()
852 mvmvif->esr_disable_reason || n_data == 1) in iwl_mvm_select_links()
874 /* For equal grade - prefer EMLSR */ in iwl_mvm_select_links()
875 if (best_link->grade > max_esr_grade) { in iwl_mvm_select_links()
876 primary_link = best_link->link_id; in iwl_mvm_select_links()
877 new_active_links = BIT(best_link->link_id); in iwl_mvm_select_links()
883 mvmvif->link_selection_res = new_active_links; in iwl_mvm_select_links()
884 mvmvif->link_selection_primary = primary_link; in iwl_mvm_select_links()
892 lockdep_assert(lockdep_is_held(&mvmvif->mvm->mutex) || in iwl_mvm_get_primary_link()
893 lockdep_is_held(&mvmvif->mvm->hw->wiphy->mtx)); in iwl_mvm_get_primary_link()
899 if (vif->type == NL80211_IFTYPE_AP) in iwl_mvm_get_primary_link()
900 return __ffs(vif->active_links); in iwl_mvm_get_primary_link()
902 if (mvmvif->esr_active && in iwl_mvm_get_primary_link()
903 !WARN_ON(!(BIT(mvmvif->primary_link) & vif->active_links))) in iwl_mvm_get_primary_link()
904 return mvmvif->primary_link; in iwl_mvm_get_primary_link()
906 return __ffs(vif->active_links); in iwl_mvm_get_primary_link()
910 * For non-MLO/single link, this will return the deflink/single active link,
915 switch (hweight16(vif->active_links)) { in iwl_mvm_get_other_link()
922 return __ffs(vif->active_links); in iwl_mvm_get_other_link()
924 return __ffs(vif->active_links & ~BIT(link_id)); in iwl_mvm_get_other_link()
939 mvmvif->last_esr_exit.ts + in iwl_mvm_check_esr_prevention()
943 lockdep_assert_held(&mvm->mutex); in iwl_mvm_check_esr_prevention()
954 if (timeout_expired || mvmvif->last_esr_exit.reason != reason) { in iwl_mvm_check_esr_prevention()
955 mvmvif->exit_same_reason_count = 1; in iwl_mvm_check_esr_prevention()
959 mvmvif->exit_same_reason_count++; in iwl_mvm_check_esr_prevention()
960 if (WARN_ON(mvmvif->exit_same_reason_count < 2 || in iwl_mvm_check_esr_prevention()
961 mvmvif->exit_same_reason_count > 3)) in iwl_mvm_check_esr_prevention()
964 mvmvif->esr_disable_reason |= IWL_MVM_ESR_BLOCKED_PREVENTION; in iwl_mvm_check_esr_prevention()
970 delay = mvmvif->exit_same_reason_count == 2 ? in iwl_mvm_check_esr_prevention()
976 delay / HZ, mvmvif->exit_same_reason_count, in iwl_mvm_check_esr_prevention()
979 wiphy_delayed_work_queue(mvm->hw->wiphy, in iwl_mvm_check_esr_prevention()
980 &mvmvif->prevent_esr_done_wk, delay); in iwl_mvm_check_esr_prevention()
995 lockdep_assert_held(&mvm->mutex); in iwl_mvm_exit_esr()
1001 if (!mvmvif->esr_active) in iwl_mvm_exit_esr()
1004 if (WARN_ON(!ieee80211_vif_is_mld(vif) || !mvmvif->authorized)) in iwl_mvm_exit_esr()
1007 if (WARN_ON(!(vif->active_links & BIT(link_to_keep)))) in iwl_mvm_exit_esr()
1008 link_to_keep = __ffs(vif->active_links); in iwl_mvm_exit_esr()
1012 "Exiting EMLSR. reason = %s (0x%x). Current active links=0x%x, new active links = 0x%x\n", in iwl_mvm_exit_esr()
1014 vif->active_links, new_active_links); in iwl_mvm_exit_esr()
1022 mvmvif->last_esr_exit.ts = jiffies; in iwl_mvm_exit_esr()
1023 mvmvif->last_esr_exit.reason = reason; in iwl_mvm_exit_esr()
1026 * If EMLSR is prevented now - don't try to get back to EMLSR. in iwl_mvm_exit_esr()
1033 /* If EMLSR is not blocked - try enabling it again in 30 seconds */ in iwl_mvm_exit_esr()
1034 wiphy_delayed_work_queue(mvm->hw->wiphy, in iwl_mvm_exit_esr()
1035 &mvmvif->mlo_int_scan_wk, in iwl_mvm_exit_esr()
1045 lockdep_assert_held(&mvm->mutex); in iwl_mvm_block_esr()
1054 if (mvmvif->esr_disable_reason & reason) in iwl_mvm_block_esr()
1061 mvmvif->esr_disable_reason |= reason; in iwl_mvm_block_esr()
1063 iwl_mvm_print_esr_state(mvm, mvmvif->esr_disable_reason); in iwl_mvm_block_esr()
1086 mutex_lock(&mvm->mutex); in iwl_mvm_block_esr_sync()
1089 mutex_unlock(&mvm->mutex); in iwl_mvm_block_esr_sync()
1098 bool need_new_sel = time_after(jiffies, mvmvif->last_esr_exit.ts + in iwl_mvm_esr_unblocked()
1101 lockdep_assert_held(&mvm->mutex); in iwl_mvm_esr_unblocked()
1103 if (!ieee80211_vif_is_mld(vif) || !mvmvif->authorized || in iwl_mvm_esr_unblocked()
1104 mvmvif->esr_active) in iwl_mvm_esr_unblocked()
1113 !(mvmvif->last_esr_exit.reason & IWL_MVM_BLOCK_ESR_REASONS)) { in iwl_mvm_esr_unblocked()
1122 if (need_new_sel || hweight16(mvmvif->link_selection_res) < 2) { in iwl_mvm_esr_unblocked()
1124 wiphy_delayed_work_queue(mvm->hw->wiphy, in iwl_mvm_esr_unblocked()
1125 &mvmvif->mlo_int_scan_wk, 0); in iwl_mvm_esr_unblocked()
1134 mvmvif->link_selection_res); in iwl_mvm_esr_unblocked()
1136 mvmvif->link_selection_res); in iwl_mvm_esr_unblocked()
1145 lockdep_assert_held(&mvm->mutex); in iwl_mvm_unblock_esr()
1155 if (!(mvmvif->esr_disable_reason & reason)) in iwl_mvm_unblock_esr()
1158 mvmvif->esr_disable_reason &= ~reason; in iwl_mvm_unblock_esr()
1163 iwl_mvm_print_esr_state(mvm, mvmvif->esr_disable_reason); in iwl_mvm_unblock_esr()
1165 if (!mvmvif->esr_disable_reason) in iwl_mvm_unblock_esr()