File Index
Files and directories
Sign in
FILE

mlo.h

File preview with syntax highlighting.

linux-6.19.14/drivers/net/wireless/intel/iwlwifi/mld/mlo.h C
  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.