FILE
mlo.h
File preview with syntax highlighting.
linux-6.19.14/drivers/net/wireless/intel/iwlwifi/mld/mlo.h
1/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ 2/* 3 * Copyright (C) 2024-2025 Intel Corporation 4 */ 5#ifndef __iwl_mld_mlo_h__ 6#define __iwl_mld_mlo_h__ 7 8#include <linux/ieee80211.h> 9#include <linux/types.h> 10#include <net/mac80211.h> 11#include "iwl-config.h" 12#include "iwl-trans.h" 13#include "iface.h" 14#include "phy.h" 15 16struct iwl_mld; 17 18void iwl_mld_emlsr_prevent_done_wk(struct wiphy *wiphy, struct wiphy_work *wk); 19void iwl_mld_emlsr_tmp_non_bss_done_wk(struct wiphy *wiphy, 20 struct wiphy_work *wk); 21 22static inline bool iwl_mld_emlsr_active(struct ieee80211_vif *vif) 23{ 24 /* Set on phy context activation, so should be a good proxy */ 25 return !!(vif->driver_flags & IEEE80211_VIF_EML_ACTIVE); 26} 27 28static inline bool iwl_mld_vif_has_emlsr_cap(struct ieee80211_vif *vif) 29{ 30 struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif); 31 32 /* We only track/permit EMLSR state once authorized */ 33 if (!mld_vif->authorized) 34 return false; 35 36 /* No EMLSR on dual radio devices */ 37 return ieee80211_vif_type_p2p(vif) == NL80211_IFTYPE_STATION && 38 ieee80211_vif_is_mld(vif) && 39 vif->cfg.eml_cap & IEEE80211_EML_CAP_EMLSR_SUPP && 40 !CSR_HW_RFID_IS_CDB(mld_vif->mld->trans->info.hw_rf_id); 41} 42 43static inline int 44iwl_mld_max_active_links(struct iwl_mld *mld, struct ieee80211_vif *vif) 45{ 46 if (vif->type == NL80211_IFTYPE_AP) 47 return mld->fw->ucode_capa.num_beacons; 48 49 if (ieee80211_vif_type_p2p(vif) == NL80211_IFTYPE_STATION) 50 return IWL_FW_MAX_ACTIVE_LINKS_NUM; 51 52 /* For now, do not accept more links on other interface types */ 53 return 1; 54} 55 56static inline int 57iwl_mld_count_active_links(struct iwl_mld *mld, struct ieee80211_vif *vif) 58{ 59 struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif); 60 struct iwl_mld_link *mld_link; 61 int n_active = 0; 62 63 for_each_mld_vif_valid_link(mld_vif, mld_link) { 64 if (rcu_access_pointer(mld_link->chan_ctx)) 65 n_active++; 66 } 67 68 return n_active; 69} 70 71static inline u8 iwl_mld_get_primary_link(struct ieee80211_vif *vif) 72{ 73 struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif); 74 75 lockdep_assert_wiphy(mld_vif->mld->wiphy); 76 77 if (!ieee80211_vif_is_mld(vif) || WARN_ON(!vif->active_links)) 78 return 0; 79 80 /* In AP mode, there is no primary link */ 81 if (vif->type == NL80211_IFTYPE_AP) 82 return __ffs(vif->active_links); 83 84 if (iwl_mld_emlsr_active(vif) && 85 !WARN_ON(!(BIT(mld_vif->emlsr.primary) & vif->active_links))) 86 return mld_vif->emlsr.primary; 87 88 return __ffs(vif->active_links); 89} 90 91/* 92 * For non-MLO/single link, this will return the deflink/single active link, 93 * respectively 94 */ 95static inline u8 iwl_mld_get_other_link(struct ieee80211_vif *vif, u8 link_id) 96{ 97 switch (hweight16(vif->active_links)) { 98 case 0: 99 return 0; 100 default: 101 WARN_ON(1); 102 fallthrough; 103 case 1: 104 return __ffs(vif->active_links); 105 case 2: 106 return __ffs(vif->active_links & ~BIT(link_id)); 107 } 108} 109 110s8 iwl_mld_get_emlsr_rssi_thresh(struct iwl_mld *mld, 111 const struct cfg80211_chan_def *chandef, 112 bool low); 113 114/* EMLSR block/unblock and exit */ 115void iwl_mld_block_emlsr(struct iwl_mld *mld, struct ieee80211_vif *vif, 116 enum iwl_mld_emlsr_blocked reason, u8 link_to_keep); 117int iwl_mld_block_emlsr_sync(struct iwl_mld *mld, struct ieee80211_vif *vif, 118 enum iwl_mld_emlsr_blocked reason, u8 link_to_keep); 119void iwl_mld_unblock_emlsr(struct iwl_mld *mld, struct ieee80211_vif *vif, 120 enum iwl_mld_emlsr_blocked reason); 121void iwl_mld_exit_emlsr(struct iwl_mld *mld, struct ieee80211_vif *vif, 122 enum iwl_mld_emlsr_exit exit, u8 link_to_keep); 123 124int iwl_mld_emlsr_check_non_bss_block(struct iwl_mld *mld, 125 int pending_link_changes); 126 127void iwl_mld_handle_emlsr_mode_notif(struct iwl_mld *mld, 128 struct iwl_rx_packet *pkt); 129void iwl_mld_handle_emlsr_trans_fail_notif(struct iwl_mld *mld, 130 struct iwl_rx_packet *pkt); 131 132void iwl_mld_emlsr_check_tpt(struct wiphy *wiphy, struct wiphy_work *wk); 133void iwl_mld_emlsr_unblock_tpt_wk(struct wiphy *wiphy, struct wiphy_work *wk); 134 135void iwl_mld_select_links(struct iwl_mld *mld); 136 137void iwl_mld_emlsr_check_bt(struct iwl_mld *mld); 138 139void iwl_mld_emlsr_check_chan_load(struct ieee80211_hw *hw, 140 struct iwl_mld_phy *phy, 141 u32 prev_chan_load_not_by_us); 142 143/** 144 * iwl_mld_retry_emlsr - Retry entering EMLSR 145 * @mld: MLD context 146 * @vif: VIF to retry EMLSR on 147 * 148 * Retry entering EMLSR on the given VIF. 149 * Use this if one of the parameters that can prevent EMLSR has changed. 150 */ 151void iwl_mld_retry_emlsr(struct iwl_mld *mld, struct ieee80211_vif *vif); 152 153struct iwl_mld_link_sel_data { 154 u8 link_id; 155 const struct cfg80211_chan_def *chandef; 156 s32 signal; 157 u16 grade; 158}; 159 160void iwl_mld_emlsr_block_tmp_non_bss(struct iwl_mld *mld); 161 162#if IS_ENABLED(CONFIG_IWLWIFI_KUNIT_TESTS) 163u32 iwl_mld_emlsr_pair_state(struct ieee80211_vif *vif, 164 struct iwl_mld_link_sel_data *a, 165 struct iwl_mld_link_sel_data *b); 166#endif 167 168void iwl_mld_start_ignoring_tpt_updates(struct iwl_mld *mld); 169void iwl_mld_stop_ignoring_tpt_updates(struct iwl_mld *mld); 170 171#endif /* __iwl_mld_mlo_h__ */
~/
Read-only file preview.