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"
58 lockdep_assert_held(&mvm->mutex); in iwl_mvm_get_free_fw_link_id()
60 for (i = 0; i < ARRAY_SIZE(mvm->link_id_to_link_conf); i++) in iwl_mvm_get_free_fw_link_id()
61 if (!rcu_access_pointer(mvm->link_id_to_link_conf[i])) in iwl_mvm_get_free_fw_link_id()
73 cmd->action = cpu_to_le32(action); in iwl_mvm_link_cmd_send()
88 mvmvif->link[link_conf->link_id]; in iwl_mvm_set_link_mapping()
90 if (link_info->fw_link_id == IWL_MVM_FW_LINK_ID_INVALID) { in iwl_mvm_set_link_mapping()
91 link_info->fw_link_id = iwl_mvm_get_free_fw_link_id(mvm, in iwl_mvm_set_link_mapping()
93 if (link_info->fw_link_id >= in iwl_mvm_set_link_mapping()
94 ARRAY_SIZE(mvm->link_id_to_link_conf)) in iwl_mvm_set_link_mapping()
95 return -EINVAL; in iwl_mvm_set_link_mapping()
97 rcu_assign_pointer(mvm->link_id_to_link_conf[link_info->fw_link_id], in iwl_mvm_set_link_mapping()
108 unsigned int link_id = link_conf->link_id; in iwl_mvm_add_link()
109 struct iwl_mvm_vif_link_info *link_info = mvmvif->link[link_id]; in iwl_mvm_add_link()
112 u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id, 1); in iwl_mvm_add_link()
116 return -EINVAL; in iwl_mvm_add_link()
122 /* Update SF - Disable if needed. if this fails, SF might still be on in iwl_mvm_add_link()
123 * while many macs are bound, which is forbidden - so fail the binding. in iwl_mvm_add_link()
126 return -EINVAL; in iwl_mvm_add_link()
128 cmd.link_id = cpu_to_le32(link_info->fw_link_id); in iwl_mvm_add_link()
129 cmd.mac_id = cpu_to_le32(mvmvif->id); in iwl_mvm_add_link()
130 cmd.spec_link_id = link_conf->link_id; in iwl_mvm_add_link()
131 WARN_ON_ONCE(link_info->phy_ctxt); in iwl_mvm_add_link()
134 memcpy(cmd.local_link_addr, link_conf->addr, ETH_ALEN); in iwl_mvm_add_link()
136 if (vif->type == NL80211_IFTYPE_ADHOC && link_conf->bssid) in iwl_mvm_add_link()
137 memcpy(cmd.ibss_bssid_addr, link_conf->bssid, ETH_ALEN); in iwl_mvm_add_link()
140 cmd.listen_lmac = cpu_to_le32(link_info->listen_lmac); in iwl_mvm_add_link()
163 mvmvif->link[link_id]; in iwl_mvm_esr_vif_iterator()
164 if (vif == data->vif && link_id == data->link_id) in iwl_mvm_esr_vif_iterator()
166 if (link_info->active) in iwl_mvm_esr_vif_iterator()
167 data->lift_block = false; in iwl_mvm_esr_vif_iterator()
174 /* An active link of a non-station vif blocks EMLSR. Upon activation in iwl_mvm_esr_non_bss_link()
176 * was the last non-station link active, and if so unblock the bss vif in iwl_mvm_esr_non_bss_link()
192 ieee80211_iterate_active_interfaces(mvm->hw, in iwl_mvm_esr_non_bss_link()
196 mutex_lock(&mvm->mutex); in iwl_mvm_esr_non_bss_link()
198 mutex_unlock(&mvm->mutex); in iwl_mvm_esr_non_bss_link()
209 unsigned int link_id = link_conf->link_id; in iwl_mvm_link_changed()
210 struct iwl_mvm_vif_link_info *link_info = mvmvif->link[link_id]; in iwl_mvm_link_changed()
216 u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id, 1); in iwl_mvm_link_changed()
219 link_info->fw_link_id == IWL_MVM_FW_LINK_ID_INVALID)) in iwl_mvm_link_changed()
220 return -EINVAL; in iwl_mvm_link_changed()
229 if (!link_info->phy_ctxt) in iwl_mvm_link_changed()
235 WARN_ON_ONCE(active == link_info->active); in iwl_mvm_link_changed()
240 if (!active && vif->type == NL80211_IFTYPE_STATION) { in iwl_mvm_link_changed()
242 if (link_info->csa_block_tx) { in iwl_mvm_link_changed()
244 link_info->csa_block_tx = false; in iwl_mvm_link_changed()
249 cmd.link_id = cpu_to_le32(link_info->fw_link_id); in iwl_mvm_link_changed()
254 phyctxt = link_info->phy_ctxt; in iwl_mvm_link_changed()
256 cmd.phy_id = cpu_to_le32(phyctxt->id); in iwl_mvm_link_changed()
259 cmd.mac_id = cpu_to_le32(mvmvif->id); in iwl_mvm_link_changed()
261 memcpy(cmd.local_link_addr, link_conf->addr, ETH_ALEN); in iwl_mvm_link_changed()
265 if (vif->type == NL80211_IFTYPE_ADHOC && link_conf->bssid) in iwl_mvm_link_changed()
266 memcpy(cmd.ibss_bssid_addr, link_conf->bssid, ETH_ALEN); in iwl_mvm_link_changed()
271 cmd.cck_short_preamble = cpu_to_le32(link_conf->use_short_preamble); in iwl_mvm_link_changed()
272 cmd.short_slot = cpu_to_le32(link_conf->use_short_slot); in iwl_mvm_link_changed()
284 cmd.bi = cpu_to_le32(link_conf->beacon_int); in iwl_mvm_link_changed()
285 cmd.dtim_interval = cpu_to_le32(link_conf->beacon_int * in iwl_mvm_link_changed()
286 link_conf->dtim_period); in iwl_mvm_link_changed()
288 if (!link_conf->he_support || iwlwifi_mod_params.disable_11ax || in iwl_mvm_link_changed()
289 (vif->type == NL80211_IFTYPE_STATION && !vif->cfg.assoc)) { in iwl_mvm_link_changed()
294 cmd.htc_trig_based_pkt_ext = link_conf->htc_trig_based_pkt_ext; in iwl_mvm_link_changed()
296 if (link_conf->uora_exists) { in iwl_mvm_link_changed()
298 link_conf->uora_ocw_range & 0x7; in iwl_mvm_link_changed()
300 (link_conf->uora_ocw_range >> 3) & 0x7; in iwl_mvm_link_changed()
304 if (changes & LINK_CONTEXT_MODIFY_HE_PARAMS && mvmvif->ap_sta) { in iwl_mvm_link_changed()
306 link_sta_dereference_check(mvmvif->ap_sta, link_id); in iwl_mvm_link_changed()
308 if (!WARN_ON(!link_sta) && link_sta->he_cap.has_he && in iwl_mvm_link_changed()
309 link_sta->he_cap.he_cap_elem.mac_cap_info[5] & in iwl_mvm_link_changed()
316 if (iwl_mvm_set_fw_mu_edca_params(mvm, mvmvif->link[link_id], in iwl_mvm_link_changed()
327 ctx = rcu_dereference(link_conf->chanctx_conf); in iwl_mvm_link_changed()
332 !link_conf->eht_support || !def || in iwl_mvm_link_changed()
333 iwl_fw_lookup_cmd_ver(mvm->fw, PHY_CONTEXT_CMD, 1) >= 6) in iwl_mvm_link_changed()
336 cmd.puncture_mask = cpu_to_le16(def->punctured); in iwl_mvm_link_changed()
340 cmd.bss_color = link_conf->he_bss_color.color; in iwl_mvm_link_changed()
342 if (!link_conf->he_bss_color.enabled) { in iwl_mvm_link_changed()
347 cmd.frame_time_rts_th = cpu_to_le16(link_conf->frame_time_rts_th); in iwl_mvm_link_changed()
349 /* Block 26-tone RU OFDMA transmissions */ in iwl_mvm_link_changed()
350 if (link_info->he_ru_2mhz_block) { in iwl_mvm_link_changed()
355 if (link_conf->nontransmitted) { in iwl_mvm_link_changed()
357 link_conf->transmitter_bssid); in iwl_mvm_link_changed()
358 cmd.bssid_index = link_conf->bssid_index; in iwl_mvm_link_changed()
366 cmd.spec_link_id = link_conf->link_id; in iwl_mvm_link_changed()
368 cmd.listen_lmac = cpu_to_le32(link_info->listen_lmac); in iwl_mvm_link_changed()
372 link_info->active = active; in iwl_mvm_link_changed()
382 mvmvif->link[link_conf->link_id]; in iwl_mvm_unset_link_mapping()
386 link_info->fw_link_id >= in iwl_mvm_unset_link_mapping()
387 ARRAY_SIZE(mvm->link_id_to_link_conf))) in iwl_mvm_unset_link_mapping()
388 return -EINVAL; in iwl_mvm_unset_link_mapping()
390 RCU_INIT_POINTER(mvm->link_id_to_link_conf[link_info->fw_link_id], in iwl_mvm_unset_link_mapping()
399 unsigned int link_id = link_conf->link_id; in iwl_mvm_remove_link()
400 struct iwl_mvm_vif_link_info *link_info = mvmvif->link[link_id]; in iwl_mvm_remove_link()
408 cmd.link_id = cpu_to_le32(link_info->fw_link_id); in iwl_mvm_remove_link()
409 link_info->fw_link_id = IWL_MVM_FW_LINK_ID_INVALID; in iwl_mvm_remove_link()
410 cmd.spec_link_id = link_conf->link_id; in iwl_mvm_remove_link()
454 * The grades are actually estimated throughput, represented as fixed-point
458 RSSI_TO_GRADE_LINE(-85, -89, 177),
459 RSSI_TO_GRADE_LINE(-83, -86, 344),
460 RSSI_TO_GRADE_LINE(-82, -85, 516),
461 RSSI_TO_GRADE_LINE(-80, -83, 688),
462 RSSI_TO_GRADE_LINE(-77, -79, 1032),
463 RSSI_TO_GRADE_LINE(-73, -76, 1376),
464 RSSI_TO_GRADE_LINE(-70, -74, 1548),
465 RSSI_TO_GRADE_LINE(-69, -72, 1750),
466 RSSI_TO_GRADE_LINE(-65, -68, 2064),
467 RSSI_TO_GRADE_LINE(-61, -66, 2294),
468 RSSI_TO_GRADE_LINE(-58, -61, 2580),
469 RSSI_TO_GRADE_LINE(-55, -58, 2868),
470 RSSI_TO_GRADE_LINE(-46, -55, 3098),
471 RSSI_TO_GRADE_LINE(-43, -54, 3442)
474 #define MAX_GRADE (rssi_to_grade_map[ARRAY_SIZE(rssi_to_grade_map) - 1].grade)
480 /* Factors calculation is done with fixed-point with a scaling factor of 1/256 */
490 link_conf->chanreq.oper.width; in iwl_mvm_get_puncturing_factor()
505 n_punctured = hweight16(link_conf->chanreq.oper.punctured); in iwl_mvm_get_puncturing_factor()
508 return SCALE_FACTOR - puncturing_penalty; in iwl_mvm_get_puncturing_factor()
514 struct ieee80211_vif *vif = link_conf->vif; in iwl_mvm_get_chan_load()
516 iwl_mvm_vif_from_mac80211(link_conf->vif)->link[link_conf->link_id]; in iwl_mvm_get_chan_load()
519 enum nl80211_band band = link_conf->chanreq.oper.chan->band; in iwl_mvm_get_chan_load()
525 if (ieee80211_vif_link_active(vif, link_conf->link_id)) in iwl_mvm_get_chan_load()
526 ies = rcu_dereference(link_conf->bss->beacon_ies); in iwl_mvm_get_chan_load()
528 ies = rcu_dereference(link_conf->bss->ies); in iwl_mvm_get_chan_load()
532 ies->data, ies->len); in iwl_mvm_get_chan_load()
538 bss_load_elem->datalen != sizeof(*bss_load)) { in iwl_mvm_get_chan_load()
558 bss_load = (const void *)bss_load_elem->data; in iwl_mvm_get_chan_load()
559 /* Channel util is in range 0-255 */ in iwl_mvm_get_chan_load()
560 chan_load = bss_load->channel_util; in iwl_mvm_get_chan_load()
563 if (!mvm_link || !mvm_link->active) in iwl_mvm_get_chan_load()
566 if (WARN_ONCE(!mvm_link->phy_ctxt, in iwl_mvm_get_chan_load()
568 link_conf->link_id)) in iwl_mvm_get_chan_load()
573 NORMALIZE_PERCENT_TO_255(mvm_link->phy_ctxt->channel_load_by_us); in iwl_mvm_get_chan_load()
577 chan_load -= chan_load_by_us; in iwl_mvm_get_chan_load()
585 return SCALE_FACTOR - iwl_mvm_get_chan_load(link_conf); in iwl_mvm_get_chan_load_factor()
600 band = link_conf->chanreq.oper.chan->band; in iwl_mvm_get_link_grade()
607 link_rssi = MBM_TO_DBM(link_conf->bss->signal); in iwl_mvm_get_link_grade()
617 /* No valid RSSI - take the lowest grade */ in iwl_mvm_get_link_grade()
626 if (link_rssi > line->rssi[rssi_idx]) in iwl_mvm_get_link_grade()
628 grade = line->grade; in iwl_mvm_get_link_grade()
649 /* TODO: don't select links that weren't discovered in the last scan */ in iwl_mvm_set_link_selection_data()
658 data[n_data].chandef = &link_conf->chanreq.oper; in iwl_mvm_set_link_selection_data()
659 data[n_data].signal = link_conf->bss->signal / 100; in iwl_mvm_set_link_selection_data()
697 if (WARN_ON(chandef->chan->band != NL80211_BAND_2GHZ && in iwl_mvm_get_esr_rssi_thresh()
698 chandef->chan->band != NL80211_BAND_5GHZ && in iwl_mvm_get_esr_rssi_thresh()
699 chandef->chan->band != NL80211_BAND_6GHZ)) in iwl_mvm_get_esr_rssi_thresh()
708 return low ? threshs->low : threshs->high; in iwl_mvm_get_esr_rssi_thresh()
717 struct wiphy *wiphy = mvm->hw->wiphy; in iwl_mvm_esr_disallowed_with_link()
722 conf = wiphy_dereference(wiphy, vif->link_conf[link->link_id]); in iwl_mvm_esr_disallowed_with_link()
726 /* BT Coex effects eSR mode only if one of the links is on LB */ in iwl_mvm_esr_disallowed_with_link()
727 if (link->chandef->chan->band == NL80211_BAND_2GHZ && in iwl_mvm_esr_disallowed_with_link()
728 (!iwl_mvm_bt_coex_calculate_esr_mode(mvm, vif, link->signal, in iwl_mvm_esr_disallowed_with_link()
732 thresh = iwl_mvm_get_esr_rssi_thresh(mvm, link->chandef, in iwl_mvm_esr_disallowed_with_link()
735 if (link->signal < thresh) in iwl_mvm_esr_disallowed_with_link()
738 if (conf->csa_active) in iwl_mvm_esr_disallowed_with_link()
744 link->link_id); in iwl_mvm_esr_disallowed_with_link()
756 struct iwl_mvm *mvm = mvmvif->mvm; in iwl_mvm_mld_valid_link_pair()
759 /* Per-link considerations */ in iwl_mvm_mld_valid_link_pair()
764 if (a->chandef->chan->band == b->chandef->chan->band || in iwl_mvm_mld_valid_link_pair()
765 a->chandef->width != b->chandef->width) 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()
1171 link->bcast_sta.sta_id = IWL_INVALID_STA; in iwl_mvm_init_link()
1172 link->mcast_sta.sta_id = IWL_INVALID_STA; in iwl_mvm_init_link()
1173 link->ap_sta_id = IWL_INVALID_STA; in iwl_mvm_init_link()
1176 link->smps_requests[r] = in iwl_mvm_init_link()