Path: blob/main/sys/contrib/dev/iwlwifi/mld/mlo.h
101200 views
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */1/*2* Copyright (C) 2024-2025 Intel Corporation3*/4#ifndef __iwl_mld_mlo_h__5#define __iwl_mld_mlo_h__67#include <linux/ieee80211.h>8#include <linux/types.h>9#include <net/mac80211.h>10#include "iwl-config.h"11#include "iwl-trans.h"12#include "iface.h"13#include "phy.h"1415struct iwl_mld;1617void iwl_mld_emlsr_prevent_done_wk(struct wiphy *wiphy, struct wiphy_work *wk);18void iwl_mld_emlsr_tmp_non_bss_done_wk(struct wiphy *wiphy,19struct wiphy_work *wk);2021static inline bool iwl_mld_emlsr_active(struct ieee80211_vif *vif)22{23/* Set on phy context activation, so should be a good proxy */24return !!(vif->driver_flags & IEEE80211_VIF_EML_ACTIVE);25}2627static inline bool iwl_mld_vif_has_emlsr_cap(struct ieee80211_vif *vif)28{29struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);3031/* We only track/permit EMLSR state once authorized */32if (!mld_vif->authorized)33return false;3435/* No EMLSR on dual radio devices */36return ieee80211_vif_type_p2p(vif) == NL80211_IFTYPE_STATION &&37ieee80211_vif_is_mld(vif) &&38vif->cfg.eml_cap & IEEE80211_EML_CAP_EMLSR_SUPP &&39!CSR_HW_RFID_IS_CDB(mld_vif->mld->trans->info.hw_rf_id);40}4142static inline int43iwl_mld_max_active_links(struct iwl_mld *mld, struct ieee80211_vif *vif)44{45if (vif->type == NL80211_IFTYPE_AP)46return mld->fw->ucode_capa.num_beacons;4748if (ieee80211_vif_type_p2p(vif) == NL80211_IFTYPE_STATION)49return IWL_FW_MAX_ACTIVE_LINKS_NUM;5051/* For now, do not accept more links on other interface types */52return 1;53}5455static inline int56iwl_mld_count_active_links(struct iwl_mld *mld, struct ieee80211_vif *vif)57{58struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);59struct iwl_mld_link *mld_link;60int n_active = 0;6162for_each_mld_vif_valid_link(mld_vif, mld_link) {63if (rcu_access_pointer(mld_link->chan_ctx))64n_active++;65}6667return n_active;68}6970static inline u8 iwl_mld_get_primary_link(struct ieee80211_vif *vif)71{72struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);7374lockdep_assert_wiphy(mld_vif->mld->wiphy);7576if (!ieee80211_vif_is_mld(vif) || WARN_ON(!vif->active_links))77return 0;7879/* In AP mode, there is no primary link */80if (vif->type == NL80211_IFTYPE_AP)81return __ffs(vif->active_links);8283if (iwl_mld_emlsr_active(vif) &&84!WARN_ON(!(BIT(mld_vif->emlsr.primary) & vif->active_links)))85return mld_vif->emlsr.primary;8687return __ffs(vif->active_links);88}8990/*91* For non-MLO/single link, this will return the deflink/single active link,92* respectively93*/94static inline u8 iwl_mld_get_other_link(struct ieee80211_vif *vif, u8 link_id)95{96switch (hweight16(vif->active_links)) {97case 0:98return 0;99default:100WARN_ON(1);101fallthrough;102case 1:103return __ffs(vif->active_links);104case 2:105return __ffs(vif->active_links & ~BIT(link_id));106}107}108109s8 iwl_mld_get_emlsr_rssi_thresh(struct iwl_mld *mld,110const struct cfg80211_chan_def *chandef,111bool low);112113/* EMLSR block/unblock and exit */114void iwl_mld_block_emlsr(struct iwl_mld *mld, struct ieee80211_vif *vif,115enum iwl_mld_emlsr_blocked reason, u8 link_to_keep);116int iwl_mld_block_emlsr_sync(struct iwl_mld *mld, struct ieee80211_vif *vif,117enum iwl_mld_emlsr_blocked reason, u8 link_to_keep);118void iwl_mld_unblock_emlsr(struct iwl_mld *mld, struct ieee80211_vif *vif,119enum iwl_mld_emlsr_blocked reason);120void iwl_mld_exit_emlsr(struct iwl_mld *mld, struct ieee80211_vif *vif,121enum iwl_mld_emlsr_exit exit, u8 link_to_keep);122123int iwl_mld_emlsr_check_non_bss_block(struct iwl_mld *mld,124int pending_link_changes);125126void iwl_mld_handle_emlsr_mode_notif(struct iwl_mld *mld,127struct iwl_rx_packet *pkt);128void iwl_mld_handle_emlsr_trans_fail_notif(struct iwl_mld *mld,129struct iwl_rx_packet *pkt);130131void iwl_mld_emlsr_check_tpt(struct wiphy *wiphy, struct wiphy_work *wk);132void iwl_mld_emlsr_unblock_tpt_wk(struct wiphy *wiphy, struct wiphy_work *wk);133134void iwl_mld_select_links(struct iwl_mld *mld);135136void iwl_mld_emlsr_check_bt(struct iwl_mld *mld);137138void iwl_mld_emlsr_check_chan_load(struct ieee80211_hw *hw,139struct iwl_mld_phy *phy,140u32 prev_chan_load_not_by_us);141142/**143* iwl_mld_retry_emlsr - Retry entering EMLSR144* @mld: MLD context145* @vif: VIF to retry EMLSR on146*147* Retry entering EMLSR on the given VIF.148* Use this if one of the parameters that can prevent EMLSR has changed.149*/150void iwl_mld_retry_emlsr(struct iwl_mld *mld, struct ieee80211_vif *vif);151152struct iwl_mld_link_sel_data {153u8 link_id;154const struct cfg80211_chan_def *chandef;155s32 signal;156u16 grade;157};158159void iwl_mld_emlsr_block_tmp_non_bss(struct iwl_mld *mld);160161#if IS_ENABLED(CONFIG_IWLWIFI_KUNIT_TESTS)162u32 iwl_mld_emlsr_pair_state(struct ieee80211_vif *vif,163struct iwl_mld_link_sel_data *a,164struct iwl_mld_link_sel_data *b);165#endif166167void iwl_mld_start_ignoring_tpt_updates(struct iwl_mld *mld);168void iwl_mld_stop_ignoring_tpt_updates(struct iwl_mld *mld);169170#endif /* __iwl_mld_mlo_h__ */171172173