File Index
Files and directories
Sign in
FILE

mac80211.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c C
   1// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
   2/*
   3 * Copyright (C) 2024-2025 Intel Corporation
   4 */
   5
   6#include <net/mac80211.h>
   7#include <linux/fips.h>
   8#include <linux/ip.h>
   9
  10#include "mld.h"
  11#include "mac80211.h"
  12#include "phy.h"
  13#include "iface.h"
  14#include "power.h"
  15#include "sta.h"
  16#include "agg.h"
  17#include "scan.h"
  18#include "d3.h"
  19#include "tlc.h"
  20#include "key.h"
  21#include "ap.h"
  22#include "tx.h"
  23#include "roc.h"
  24#include "mlo.h"
  25#include "stats.h"
  26#include "iwl-nvm-parse.h"
  27#include "ftm-initiator.h"
  28#include "low_latency.h"
  29#include "fw/api/scan.h"
  30#include "fw/api/context.h"
  31#include "fw/api/filter.h"
  32#include "fw/api/sta.h"
  33#include "fw/api/tdls.h"
  34#ifdef CONFIG_PM_SLEEP
  35#include "fw/api/d3.h"
  36#endif /* CONFIG_PM_SLEEP */
  37#include "iwl-trans.h"
  38
  39#define IWL_MLD_LIMITS(ap)					\
  40	{							\
  41		.max = 2,					\
  42		.types = BIT(NL80211_IFTYPE_STATION),		\
  43	},							\
  44	{							\
  45		.max = 1,					\
  46		.types = ap |					\
  47			 BIT(NL80211_IFTYPE_P2P_CLIENT) |	\
  48			 BIT(NL80211_IFTYPE_P2P_GO),		\
  49	},							\
  50	{							\
  51		.max = 1,					\
  52		.types = BIT(NL80211_IFTYPE_P2P_DEVICE),	\
  53	}
  54
  55static const struct ieee80211_iface_limit iwl_mld_limits[] = {
  56	IWL_MLD_LIMITS(0)
  57};
  58
  59static const struct ieee80211_iface_limit iwl_mld_limits_ap[] = {
  60	IWL_MLD_LIMITS(BIT(NL80211_IFTYPE_AP))
  61};
  62
  63static const struct ieee80211_iface_combination
  64iwl_mld_iface_combinations[] = {
  65	{
  66		.num_different_channels = 2,
  67		.max_interfaces = 4,
  68		.limits = iwl_mld_limits,
  69		.n_limits = ARRAY_SIZE(iwl_mld_limits),
  70	},
  71	{
  72		.num_different_channels = 1,
  73		.max_interfaces = 4,
  74		.limits = iwl_mld_limits_ap,
  75		.n_limits = ARRAY_SIZE(iwl_mld_limits_ap),
  76	},
  77};
  78
  79static const u8 ext_capa_base[IWL_MLD_STA_EXT_CAPA_SIZE] = {
  80	[0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,
  81	[2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT,
  82	[7] = WLAN_EXT_CAPA8_OPMODE_NOTIF |
  83	      WLAN_EXT_CAPA8_MAX_MSDU_IN_AMSDU_LSB,
  84	[8] = WLAN_EXT_CAPA9_MAX_MSDU_IN_AMSDU_MSB,
  85};
  86
  87#define IWL_MLD_EMLSR_CAPA	(IEEE80211_EML_CAP_EMLSR_SUPP | \
  88				 IEEE80211_EML_CAP_EMLSR_PADDING_DELAY_32US << \
  89					__bf_shf(IEEE80211_EML_CAP_EMLSR_PADDING_DELAY) | \
  90				 IEEE80211_EML_CAP_EMLSR_TRANSITION_DELAY_64US << \
  91					__bf_shf(IEEE80211_EML_CAP_EMLSR_TRANSITION_DELAY))
  92#define IWL_MLD_CAPA_OPS (FIELD_PREP_CONST( \
  93			IEEE80211_MLD_CAP_OP_TID_TO_LINK_MAP_NEG_SUPP, \
  94			IEEE80211_MLD_CAP_OP_TID_TO_LINK_MAP_NEG_SUPP_SAME) | \
  95			IEEE80211_MLD_CAP_OP_LINK_RECONF_SUPPORT)
  96
  97static void iwl_mld_hw_set_addresses(struct iwl_mld *mld)
  98{
  99	struct wiphy *wiphy = mld->wiphy;
 100	int num_addrs = 1;
 101
 102	/* Extract MAC address */
 103	memcpy(mld->addresses[0].addr, mld->nvm_data->hw_addr, ETH_ALEN);
 104	wiphy->addresses = mld->addresses;
 105	wiphy->n_addresses = 1;
 106
 107	/* Extract additional MAC addresses if available */
 108	if (mld->nvm_data->n_hw_addrs > 1)
 109		num_addrs = min(mld->nvm_data->n_hw_addrs,
 110				IWL_MLD_MAX_ADDRESSES);
 111
 112	for (int i = 1; i < num_addrs; i++) {
 113		memcpy(mld->addresses[i].addr,
 114		       mld->addresses[i - 1].addr,
 115		       ETH_ALEN);
 116		mld->addresses[i].addr[ETH_ALEN - 1]++;
 117		wiphy->n_addresses++;
 118	}
 119}
 120
 121static void iwl_mld_hw_set_channels(struct iwl_mld *mld)
 122{
 123	struct wiphy *wiphy = mld->wiphy;
 124	struct ieee80211_supported_band *bands = mld->nvm_data->bands;
 125
 126	wiphy->bands[NL80211_BAND_2GHZ] = &bands[NL80211_BAND_2GHZ];
 127	wiphy->bands[NL80211_BAND_5GHZ] = &bands[NL80211_BAND_5GHZ];
 128
 129	if (bands[NL80211_BAND_6GHZ].n_channels)
 130		wiphy->bands[NL80211_BAND_6GHZ] = &bands[NL80211_BAND_6GHZ];
 131}
 132
 133static void iwl_mld_hw_set_security(struct iwl_mld *mld)
 134{
 135	struct ieee80211_hw *hw = mld->hw;
 136	static const u32 mld_ciphers[] = {
 137		WLAN_CIPHER_SUITE_WEP40,
 138		WLAN_CIPHER_SUITE_WEP104,
 139		WLAN_CIPHER_SUITE_TKIP,
 140		WLAN_CIPHER_SUITE_CCMP,
 141		WLAN_CIPHER_SUITE_GCMP,
 142		WLAN_CIPHER_SUITE_GCMP_256,
 143		WLAN_CIPHER_SUITE_AES_CMAC,
 144		WLAN_CIPHER_SUITE_BIP_GMAC_128,
 145		WLAN_CIPHER_SUITE_BIP_GMAC_256
 146	};
 147
 148	if (fips_enabled)
 149		return;
 150
 151	hw->wiphy->n_cipher_suites = ARRAY_SIZE(mld_ciphers);
 152	hw->wiphy->cipher_suites = mld_ciphers;
 153
 154	ieee80211_hw_set(hw, MFP_CAPABLE);
 155	wiphy_ext_feature_set(hw->wiphy,
 156			      NL80211_EXT_FEATURE_BEACON_PROTECTION);
 157}
 158
 159static void iwl_mld_hw_set_antennas(struct iwl_mld *mld)
 160{
 161	struct wiphy *wiphy = mld->wiphy;
 162
 163	wiphy->available_antennas_tx = iwl_mld_get_valid_tx_ant(mld);
 164	wiphy->available_antennas_rx = iwl_mld_get_valid_rx_ant(mld);
 165}
 166
 167static void iwl_mld_hw_set_pm(struct iwl_mld *mld)
 168{
 169#ifdef CONFIG_PM_SLEEP
 170	struct wiphy *wiphy = mld->wiphy;
 171
 172	if (!device_can_wakeup(mld->trans->dev))
 173		return;
 174
 175	if (fips_enabled)
 176		return;
 177
 178	mld->wowlan.flags |= WIPHY_WOWLAN_MAGIC_PKT |
 179			     WIPHY_WOWLAN_DISCONNECT |
 180			     WIPHY_WOWLAN_EAP_IDENTITY_REQ |
 181			     WIPHY_WOWLAN_RFKILL_RELEASE |
 182			     WIPHY_WOWLAN_NET_DETECT |
 183			     WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
 184			     WIPHY_WOWLAN_GTK_REKEY_FAILURE |
 185			     WIPHY_WOWLAN_4WAY_HANDSHAKE;
 186
 187	mld->wowlan.n_patterns = IWL_WOWLAN_MAX_PATTERNS;
 188	mld->wowlan.pattern_min_len = IWL_WOWLAN_MIN_PATTERN_LEN;
 189	mld->wowlan.pattern_max_len = IWL_WOWLAN_MAX_PATTERN_LEN;
 190	mld->wowlan.max_nd_match_sets = IWL_SCAN_MAX_PROFILES_V2;
 191
 192	wiphy->wowlan = &mld->wowlan;
 193#endif /* CONFIG_PM_SLEEP */
 194}
 195
 196static void iwl_mac_hw_set_radiotap(struct iwl_mld *mld)
 197{
 198	struct ieee80211_hw *hw = mld->hw;
 199
 200	hw->radiotap_mcs_details |= IEEE80211_RADIOTAP_MCS_HAVE_FEC |
 201				    IEEE80211_RADIOTAP_MCS_HAVE_STBC;
 202
 203	hw->radiotap_vht_details |= IEEE80211_RADIOTAP_VHT_KNOWN_STBC |
 204				    IEEE80211_RADIOTAP_VHT_KNOWN_BEAMFORMED;
 205
 206	hw->radiotap_timestamp.units_pos =
 207		IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US |
 208		IEEE80211_RADIOTAP_TIMESTAMP_SPOS_PLCP_SIG_ACQ;
 209
 210	/* this is the case for CCK frames, it's better (only 8) for OFDM */
 211	hw->radiotap_timestamp.accuracy = 22;
 212}
 213
 214static void iwl_mac_hw_set_flags(struct iwl_mld *mld)
 215{
 216	struct ieee80211_hw *hw = mld->hw;
 217
 218	ieee80211_hw_set(hw, USES_RSS);
 219	ieee80211_hw_set(hw, HANDLES_QUIET_CSA);
 220	ieee80211_hw_set(hw, AP_LINK_PS);
 221	ieee80211_hw_set(hw, SIGNAL_DBM);
 222	ieee80211_hw_set(hw, SPECTRUM_MGMT);
 223	ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS);
 224	ieee80211_hw_set(hw, WANT_MONITOR_VIF);
 225	ieee80211_hw_set(hw, SUPPORTS_PS);
 226	ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS);
 227	ieee80211_hw_set(hw, AMPDU_AGGREGATION);
 228	ieee80211_hw_set(hw, CONNECTION_MONITOR);
 229	ieee80211_hw_set(hw, CHANCTX_STA_CSA);
 230	ieee80211_hw_set(hw, SUPPORT_FAST_XMIT);
 231	ieee80211_hw_set(hw, SUPPORTS_CLONED_SKBS);
 232	ieee80211_hw_set(hw, NEEDS_UNIQUE_STA_ADDR);
 233	ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW);
 234	ieee80211_hw_set(hw, BUFF_MMPDU_TXQ);
 235	ieee80211_hw_set(hw, STA_MMPDU_TXQ);
 236	ieee80211_hw_set(hw, TX_AMSDU);
 237	ieee80211_hw_set(hw, TX_FRAG_LIST);
 238	ieee80211_hw_set(hw, TX_AMPDU_SETUP_IN_HW);
 239	ieee80211_hw_set(hw, HAS_RATE_CONTROL);
 240	ieee80211_hw_set(hw, SUPPORTS_REORDERING_BUFFER);
 241	ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS);
 242	ieee80211_hw_set(hw, SUPPORTS_AMSDU_IN_AMPDU);
 243	ieee80211_hw_set(hw, TDLS_WIDER_BW);
 244}
 245
 246static void iwl_mac_hw_set_wiphy(struct iwl_mld *mld)
 247{
 248	struct ieee80211_hw *hw = mld->hw;
 249	struct wiphy *wiphy = hw->wiphy;
 250	const struct iwl_ucode_capabilities *ucode_capa = &mld->fw->ucode_capa;
 251
 252	snprintf(wiphy->fw_version,
 253		 sizeof(wiphy->fw_version),
 254		 "%.31s", mld->fw->fw_version);
 255
 256	wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
 257				 BIT(NL80211_IFTYPE_P2P_CLIENT) |
 258				 BIT(NL80211_IFTYPE_AP) |
 259				 BIT(NL80211_IFTYPE_P2P_GO) |
 260				 BIT(NL80211_IFTYPE_P2P_DEVICE) |
 261				 BIT(NL80211_IFTYPE_ADHOC);
 262
 263	wiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR |
 264			   NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR |
 265			   NL80211_FEATURE_ND_RANDOM_MAC_ADDR |
 266			   NL80211_FEATURE_HT_IBSS |
 267			   NL80211_FEATURE_P2P_GO_CTWIN |
 268			   NL80211_FEATURE_LOW_PRIORITY_SCAN |
 269			   NL80211_FEATURE_P2P_GO_OPPPS |
 270			   NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE |
 271			   NL80211_FEATURE_SUPPORTS_WMM_ADMISSION |
 272			   NL80211_FEATURE_TX_POWER_INSERTION |
 273			   NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES;
 274
 275	wiphy->flags |= WIPHY_FLAG_IBSS_RSN |
 276			WIPHY_FLAG_AP_UAPSD |
 277			WIPHY_FLAG_HAS_CHANNEL_SWITCH |
 278			WIPHY_FLAG_SPLIT_SCAN_6GHZ |
 279			WIPHY_FLAG_SUPPORTS_TDLS |
 280			WIPHY_FLAG_SUPPORTS_EXT_KEK_KCK;
 281
 282	/* For fips_enabled, don't support WiFi7 due to WPA3/MFP requirements */
 283	if (mld->nvm_data->sku_cap_11be_enable &&
 284	    !iwlwifi_mod_params.disable_11ax &&
 285	    !iwlwifi_mod_params.disable_11be &&
 286	    !fips_enabled)
 287		wiphy->flags |= WIPHY_FLAG_SUPPORTS_MLO;
 288
 289	/* the firmware uses u8 for num of iterations, but 0xff is saved for
 290	 * infinite loop, so the maximum number of iterations is actually 254.
 291	 */
 292	wiphy->max_sched_scan_plan_iterations = 254;
 293	wiphy->max_sched_scan_ie_len = iwl_mld_scan_max_template_size();
 294	wiphy->max_scan_ie_len = iwl_mld_scan_max_template_size();
 295	wiphy->max_sched_scan_ssids = PROBE_OPTION_MAX;
 296	wiphy->max_scan_ssids = PROBE_OPTION_MAX;
 297	wiphy->max_sched_scan_plans = IWL_MAX_SCHED_SCAN_PLANS;
 298	wiphy->max_sched_scan_reqs = 1;
 299	wiphy->max_sched_scan_plan_interval = U16_MAX;
 300	wiphy->max_match_sets = IWL_SCAN_MAX_PROFILES_V2;
 301
 302	wiphy->max_remain_on_channel_duration = 10000;
 303
 304	wiphy->hw_version = mld->trans->info.hw_id;
 305
 306	wiphy->hw_timestamp_max_peers = 1;
 307
 308	wiphy->iface_combinations = iwl_mld_iface_combinations;
 309	wiphy->n_iface_combinations = ARRAY_SIZE(iwl_mld_iface_combinations);
 310
 311	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
 312	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_DFS_CONCURRENT);
 313	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
 314	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_SCAN_START_TIME);
 315	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BSS_PARENT_TSF);
 316	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_SCAN_MIN_PREQ_CONTENT);
 317	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_ACCEPT_BCAST_PROBE_RESP);
 318	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_MAX_CHANNEL_TIME);
 319	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_OCE_PROBE_REQ_HIGH_TX_RATE);
 320	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER);
 321	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_SPP_AMSDU_SUPPORT);
 322
 323	if (fw_has_capa(ucode_capa, IWL_UCODE_TLV_CAPA_PROTECTED_TWT))
 324		wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_PROTECTED_TWT);
 325
 326	if (iwlmld_mod_params.power_scheme != IWL_POWER_SCHEME_CAM)
 327		wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
 328	else
 329		wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
 330
 331	/* We are done for non-HE */
 332	if (iwlwifi_mod_params.disable_11ax)
 333		return;
 334
 335	ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID);
 336	ieee80211_hw_set(hw, SUPPORTS_ONLY_HE_MULTI_BSSID);
 337
 338	wiphy->iftype_ext_capab = mld->ext_capab;
 339	wiphy->num_iftype_ext_capab = ARRAY_SIZE(mld->ext_capab);
 340
 341	BUILD_BUG_ON(sizeof(mld->sta_ext_capab) < sizeof(ext_capa_base));
 342
 343	memcpy(mld->sta_ext_capab, ext_capa_base, sizeof(ext_capa_base));
 344
 345	mld->ext_capab[0].iftype = NL80211_IFTYPE_STATION;
 346	mld->ext_capab[0].extended_capabilities = mld->sta_ext_capab;
 347	mld->ext_capab[0].extended_capabilities_mask = mld->sta_ext_capab;
 348	mld->ext_capab[0].extended_capabilities_len = sizeof(mld->sta_ext_capab);
 349
 350	if (!mld->nvm_data->sku_cap_11be_enable ||
 351	    iwlwifi_mod_params.disable_11be)
 352		return;
 353
 354	mld->ext_capab[0].eml_capabilities = IWL_MLD_EMLSR_CAPA;
 355	mld->ext_capab[0].mld_capa_and_ops = IWL_MLD_CAPA_OPS;
 356
 357}
 358
 359static void iwl_mac_hw_set_misc(struct iwl_mld *mld)
 360{
 361	struct ieee80211_hw *hw = mld->hw;
 362
 363	hw->queues = IEEE80211_NUM_ACS;
 364
 365	hw->netdev_features = NETIF_F_HIGHDMA | NETIF_F_SG;
 366	hw->netdev_features |= mld->trans->mac_cfg->base->features;
 367
 368	hw->max_tx_fragments = mld->trans->info.max_skb_frags;
 369	hw->max_listen_interval = IWL_MLD_CONN_LISTEN_INTERVAL;
 370
 371	hw->uapsd_max_sp_len = IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL;
 372	hw->uapsd_queues = IEEE80211_WMM_IE_STA_QOSINFO_AC_VO |
 373			   IEEE80211_WMM_IE_STA_QOSINFO_AC_VI |
 374			   IEEE80211_WMM_IE_STA_QOSINFO_AC_BK |
 375			   IEEE80211_WMM_IE_STA_QOSINFO_AC_BE;
 376
 377	hw->chanctx_data_size = sizeof(struct iwl_mld_phy);
 378	hw->vif_data_size = sizeof(struct iwl_mld_vif);
 379	hw->sta_data_size = sizeof(struct iwl_mld_sta);
 380	hw->txq_data_size = sizeof(struct iwl_mld_txq);
 381
 382	/* TODO: Remove this division when IEEE80211_MAX_AMPDU_BUF_EHT size
 383	 * is supported.
 384	 * Note: ensure that IWL_DEFAULT_QUEUE_SIZE_EHT is updated accordingly.
 385	 */
 386	hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_EHT / 2;
 387}
 388
 389static int iwl_mld_hw_verify_preconditions(struct iwl_mld *mld)
 390{
 391	int ratecheck;
 392
 393	/* check for rates version 3 */
 394	ratecheck =
 395		(iwl_fw_lookup_cmd_ver(mld->fw, TX_CMD, 0) >= 11) +
 396		(iwl_fw_lookup_notif_ver(mld->fw, DATA_PATH_GROUP,
 397					 TLC_MNG_UPDATE_NOTIF, 0) >= 4) +
 398		(iwl_fw_lookup_notif_ver(mld->fw, LEGACY_GROUP,
 399					 REPLY_RX_MPDU_CMD, 0) >= 6) +
 400		(iwl_fw_lookup_notif_ver(mld->fw, LONG_GROUP, TX_CMD, 0) >= 9);
 401
 402	if (ratecheck != 0 && ratecheck != 4) {
 403		IWL_ERR(mld, "Firmware has inconsistent rates\n");
 404		return -EINVAL;
 405	}
 406
 407	/* 11ax is expected to be enabled for all supported devices */
 408	if (WARN_ON(!mld->nvm_data->sku_cap_11ax_enable))
 409		return -EINVAL;
 410
 411	/* LAR is expected to be enabled for all supported devices */
 412	if (WARN_ON(!mld->nvm_data->lar_enabled))
 413		return -EINVAL;
 414
 415	/* All supported devices are currently using version 3 of the cmd.
 416	 * Since version 3, IWL_SCAN_MAX_PROFILES_V2 shall be used where
 417	 * necessary.
 418	 */
 419	if (WARN_ON(iwl_fw_lookup_cmd_ver(mld->fw,
 420					  SCAN_OFFLOAD_UPDATE_PROFILES_CMD,
 421					  IWL_FW_CMD_VER_UNKNOWN) != 3))
 422		return -EINVAL;
 423
 424	return 0;
 425}
 426
 427int iwl_mld_register_hw(struct iwl_mld *mld)
 428{
 429	/* verify once essential preconditions required for setting
 430	 * the hw capabilities
 431	 */
 432	if (iwl_mld_hw_verify_preconditions(mld))
 433		return -EINVAL;
 434
 435	iwl_mld_hw_set_addresses(mld);
 436	iwl_mld_hw_set_channels(mld);
 437	iwl_mld_hw_set_security(mld);
 438	iwl_mld_hw_set_pm(mld);
 439	iwl_mld_hw_set_antennas(mld);
 440	iwl_mac_hw_set_radiotap(mld);
 441	iwl_mac_hw_set_flags(mld);
 442	iwl_mac_hw_set_wiphy(mld);
 443	iwl_mac_hw_set_misc(mld);
 444
 445	SET_IEEE80211_DEV(mld->hw, mld->trans->dev);
 446
 447	return ieee80211_register_hw(mld->hw);
 448}
 449
 450static void
 451iwl_mld_mac80211_tx(struct ieee80211_hw *hw,
 452		    struct ieee80211_tx_control *control, struct sk_buff *skb)
 453{
 454	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
 455	struct ieee80211_sta *sta = control->sta;
 456	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 457	struct ieee80211_hdr *hdr = (void *)skb->data;
 458	u32 link_id = u32_get_bits(info->control.flags,
 459				   IEEE80211_TX_CTRL_MLO_LINK);
 460
 461	/* In AP mode, mgmt frames are sent on the bcast station,
 462	 * so the FW can't translate the MLD addr to the link addr. Do it here
 463	 */
 464	if (ieee80211_is_mgmt(hdr->frame_control) && sta &&
 465	    link_id != IEEE80211_LINK_UNSPECIFIED &&
 466	    !ieee80211_is_probe_resp(hdr->frame_control)) {
 467		/* translate MLD addresses to LINK addresses */
 468		struct ieee80211_link_sta *link_sta =
 469			rcu_dereference(sta->link[link_id]);
 470		struct ieee80211_bss_conf *link_conf =
 471			rcu_dereference(info->control.vif->link_conf[link_id]);
 472		struct ieee80211_mgmt *mgmt;
 473
 474		if (WARN_ON(!link_sta || !link_conf)) {
 475			ieee80211_free_txskb(hw, skb);
 476			return;
 477		}
 478
 479		mgmt = (void *)hdr;
 480		memcpy(mgmt->da, link_sta->addr, ETH_ALEN);
 481		memcpy(mgmt->sa, link_conf->addr, ETH_ALEN);
 482		memcpy(mgmt->bssid, link_conf->bssid, ETH_ALEN);
 483	}
 484
 485	iwl_mld_tx_skb(mld, skb, NULL);
 486}
 487
 488static void
 489iwl_mld_restart_cleanup(struct iwl_mld *mld)
 490{
 491	iwl_cleanup_mld(mld);
 492
 493	ieee80211_iterate_interfaces(mld->hw, IEEE80211_IFACE_ITER_ACTIVE,
 494				     iwl_mld_cleanup_vif, NULL);
 495
 496	ieee80211_iterate_stations_atomic(mld->hw,
 497					  iwl_mld_cleanup_sta, NULL);
 498
 499	iwl_mld_ftm_restart_cleanup(mld);
 500}
 501
 502static
 503int iwl_mld_mac80211_start(struct ieee80211_hw *hw)
 504{
 505	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
 506	bool in_d3 = false;
 507	int ret = 0;
 508
 509	lockdep_assert_wiphy(mld->wiphy);
 510
 511#ifdef CONFIG_PM_SLEEP
 512	/* Unless the host goes into hibernate the FW always stays on and
 513	 * the d3_resume flow is used. When wowlan is configured, mac80211
 514	 * would call it's resume callback and the wowlan_resume flow
 515	 * would be used.
 516	 */
 517
 518	in_d3 = mld->fw_status.in_d3;
 519	if (in_d3) {
 520		/* mac80211 already cleaned up the state, no need for cleanup */
 521		ret = iwl_mld_no_wowlan_resume(mld);
 522		if (ret) {
 523			iwl_mld_stop_fw(mld);
 524			/* We're not really restarting in the sense of
 525			 * in_hw_restart even if we got an error during
 526			 * this. We'll just start again below and have
 527			 * nothing to recover, mac80211 will do anyway.
 528			 */
 529			mld->fw_status.in_hw_restart = false;
 530		}
 531	}
 532#endif /* CONFIG_PM_SLEEP */
 533
 534	if (mld->fw_status.in_hw_restart) {
 535		iwl_mld_stop_fw(mld);
 536		iwl_mld_restart_cleanup(mld);
 537	}
 538
 539	if (!in_d3 || ret) {
 540		ret = iwl_mld_start_fw(mld);
 541		if (ret)
 542			goto error;
 543	}
 544
 545	mld->scan.last_start_time_jiffies = jiffies;
 546
 547	iwl_dbg_tlv_time_point(&mld->fwrt, IWL_FW_INI_TIME_POINT_POST_INIT,
 548			       NULL);
 549	iwl_dbg_tlv_time_point(&mld->fwrt, IWL_FW_INI_TIME_POINT_PERIODIC,
 550			       NULL);
 551
 552	return 0;
 553
 554error:
 555	/* If we failed to restart the hw, there is nothing useful
 556	 * we can do but indicate we are no longer in restart.
 557	 */
 558	mld->fw_status.in_hw_restart = false;
 559
 560	return ret;
 561}
 562
 563static
 564void iwl_mld_mac80211_stop(struct ieee80211_hw *hw, bool suspend)
 565{
 566	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
 567
 568	lockdep_assert_wiphy(mld->wiphy);
 569
 570	wiphy_work_cancel(mld->wiphy, &mld->add_txqs_wk);
 571
 572	/* if the suspend flow fails the fw is in error. Stop it here, and it
 573	 * will be started upon wakeup
 574	 */
 575	if (!suspend ||
 576	    (IS_ENABLED(CONFIG_PM_SLEEP) && iwl_mld_no_wowlan_suspend(mld)))
 577		iwl_mld_stop_fw(mld);
 578
 579	/* Clear in_hw_restart flag when stopping the hw, as mac80211 won't
 580	 * execute the restart.
 581	 */
 582	mld->fw_status.in_hw_restart = false;
 583
 584	/* We shouldn't have any UIDs still set. Loop over all the UIDs to
 585	 * make sure there's nothing left there and warn if any is found.
 586	 */
 587	for (int i = 0; i < ARRAY_SIZE(mld->scan.uid_status); i++)
 588		if (WARN_ONCE(mld->scan.uid_status[i],
 589			      "UMAC scan UID %d status was not cleaned (0x%x 0x%x)\n",
 590			      i, mld->scan.uid_status[i], mld->scan.status))
 591			mld->scan.uid_status[i] = 0;
 592}
 593
 594static
 595int iwl_mld_mac80211_config(struct ieee80211_hw *hw, int radio_idx,
 596			    u32 changed)
 597{
 598	return 0;
 599}
 600
 601static
 602int iwl_mld_mac80211_add_interface(struct ieee80211_hw *hw,
 603				   struct ieee80211_vif *vif)
 604{
 605	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
 606	int ret;
 607
 608	lockdep_assert_wiphy(mld->wiphy);
 609
 610	/* Construct mld_vif, add it to fw, and map its ID to ieee80211_vif */
 611	ret = iwl_mld_add_vif(mld, vif);
 612	if (ret)
 613		return ret;
 614
 615	/*
 616	 * Add the default link, but not if this is an MLD vif as that implies
 617	 * the HW is restarting and it will be configured by change_vif_links.
 618	 */
 619	if (!ieee80211_vif_is_mld(vif))
 620		ret = iwl_mld_add_link(mld, &vif->bss_conf);
 621	if (ret)
 622		goto err;
 623
 624	if (vif->type == NL80211_IFTYPE_STATION) {
 625		vif->driver_flags |= IEEE80211_VIF_REMOVE_AP_AFTER_DISASSOC;
 626		if (!vif->p2p)
 627			vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER |
 628					     IEEE80211_VIF_SUPPORTS_CQM_RSSI;
 629	}
 630
 631	if (vif->p2p)
 632		vif->driver_flags |= IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW;
 633
 634	/*
 635	 * For an MLD vif (in restart) we may not have a link; delay the call
 636	 * the initial change_vif_links.
 637	 */
 638	if (vif->type == NL80211_IFTYPE_STATION &&
 639	    !ieee80211_vif_is_mld(vif))
 640		iwl_mld_update_mac_power(mld, vif, false);
 641
 642	if (vif->type == NL80211_IFTYPE_MONITOR) {
 643		mld->monitor.on = true;
 644		ieee80211_hw_set(mld->hw, RX_INCLUDES_FCS);
 645	}
 646
 647	if (vif->type == NL80211_IFTYPE_P2P_DEVICE)
 648		mld->p2p_device_vif = vif;
 649
 650	return 0;
 651
 652err:
 653	iwl_mld_rm_vif(mld, vif);
 654	return ret;
 655}
 656
 657static
 658void iwl_mld_mac80211_remove_interface(struct ieee80211_hw *hw,
 659				       struct ieee80211_vif *vif)
 660{
 661	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
 662
 663	lockdep_assert_wiphy(mld->wiphy);
 664
 665	if (ieee80211_vif_type_p2p(vif) == NL80211_IFTYPE_STATION)
 666		vif->driver_flags &= ~(IEEE80211_VIF_BEACON_FILTER |
 667				       IEEE80211_VIF_SUPPORTS_CQM_RSSI);
 668
 669	if (vif->type == NL80211_IFTYPE_MONITOR) {
 670		__clear_bit(IEEE80211_HW_RX_INCLUDES_FCS, mld->hw->flags);
 671		mld->monitor.on = false;
 672	}
 673
 674	if (vif->type == NL80211_IFTYPE_P2P_DEVICE)
 675		mld->p2p_device_vif = NULL;
 676
 677	iwl_mld_remove_link(mld, &vif->bss_conf);
 678
 679#ifdef CONFIG_IWLWIFI_DEBUGFS
 680	debugfs_remove(iwl_mld_vif_from_mac80211(vif)->dbgfs_slink);
 681	iwl_mld_vif_from_mac80211(vif)->dbgfs_slink = NULL;
 682#endif
 683
 684	iwl_mld_rm_vif(mld, vif);
 685
 686	mld->monitor.phy.valid = false;
 687}
 688
 689struct iwl_mld_mc_iter_data {
 690	struct iwl_mld *mld;
 691	int port_id;
 692};
 693
 694static void iwl_mld_mc_iface_iterator(void *data, u8 *mac,
 695				      struct ieee80211_vif *vif)
 696{
 697	struct iwl_mld_mc_iter_data *mc_data = data;
 698	struct iwl_mld *mld = mc_data->mld;
 699	struct iwl_mcast_filter_cmd *cmd = mld->mcast_filter_cmd;
 700	struct iwl_host_cmd hcmd = {
 701		.id = MCAST_FILTER_CMD,
 702		.dataflags[0] = IWL_HCMD_DFL_NOCOPY,
 703	};
 704	int ret, len;
 705
 706	/* If we don't have free ports, mcast frames will be dropped */
 707	if (WARN_ON_ONCE(mc_data->port_id >= MAX_PORT_ID_NUM))
 708		return;
 709
 710	if (vif->type != NL80211_IFTYPE_STATION || !vif->cfg.assoc)
 711		return;
 712
 713	cmd->port_id = mc_data->port_id++;
 714	ether_addr_copy(cmd->bssid, vif->bss_conf.bssid);
 715	len = roundup(sizeof(*cmd) + cmd->count * ETH_ALEN, 4);
 716
 717	hcmd.len[0] = len;
 718	hcmd.data[0] = cmd;
 719
 720	ret = iwl_mld_send_cmd(mld, &hcmd);
 721	if (ret)
 722		IWL_ERR(mld, "mcast filter cmd error. ret=%d\n", ret);
 723}
 724
 725void iwl_mld_recalc_multicast_filter(struct iwl_mld *mld)
 726{
 727	struct iwl_mld_mc_iter_data iter_data = {
 728		.mld = mld,
 729	};
 730
 731	if (WARN_ON_ONCE(!mld->mcast_filter_cmd))
 732		return;
 733
 734	ieee80211_iterate_active_interfaces(mld->hw,
 735					    IEEE80211_IFACE_ITER_NORMAL,
 736					    iwl_mld_mc_iface_iterator,
 737					    &iter_data);
 738}
 739
 740static u64
 741iwl_mld_mac80211_prepare_multicast(struct ieee80211_hw *hw,
 742				   struct netdev_hw_addr_list *mc_list)
 743{
 744	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
 745	struct iwl_mcast_filter_cmd *cmd;
 746	struct netdev_hw_addr *addr;
 747	int addr_count = netdev_hw_addr_list_count(mc_list);
 748	bool pass_all = addr_count > MAX_MCAST_FILTERING_ADDRESSES;
 749	int len;
 750
 751	if (pass_all)
 752		addr_count = 0;
 753
 754	/* len must be a multiple of 4 */
 755	len = roundup(sizeof(*cmd) + addr_count * ETH_ALEN, 4);
 756	cmd = kzalloc(len, GFP_ATOMIC);
 757	if (!cmd)
 758		return 0;
 759
 760	if (pass_all) {
 761		cmd->pass_all = 1;
 762		goto out;
 763	}
 764
 765	netdev_hw_addr_list_for_each(addr, mc_list) {
 766		IWL_DEBUG_MAC80211(mld, "mcast addr (%d): %pM\n",
 767				   cmd->count, addr->addr);
 768		ether_addr_copy(&cmd->addr_list[cmd->count * ETH_ALEN],
 769				addr->addr);
 770		cmd->count++;
 771	}
 772
 773out:
 774	return (u64)(unsigned long)cmd;
 775}
 776
 777static
 778void iwl_mld_mac80211_configure_filter(struct ieee80211_hw *hw,
 779				       unsigned int changed_flags,
 780				       unsigned int *total_flags,
 781				       u64 multicast)
 782{
 783	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
 784	struct iwl_mcast_filter_cmd *cmd = (void *)(unsigned long)multicast;
 785
 786	/* Replace previous configuration */
 787	kfree(mld->mcast_filter_cmd);
 788	mld->mcast_filter_cmd = cmd;
 789
 790	if (!cmd)
 791		goto out;
 792
 793	if (changed_flags & FIF_ALLMULTI)
 794		cmd->pass_all = !!(*total_flags & FIF_ALLMULTI);
 795
 796	if (cmd->pass_all)
 797		cmd->count = 0;
 798
 799	iwl_mld_recalc_multicast_filter(mld);
 800out:
 801	*total_flags = 0;
 802}
 803
 804static
 805void iwl_mld_mac80211_wake_tx_queue(struct ieee80211_hw *hw,
 806				    struct ieee80211_txq *txq)
 807{
 808	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
 809	struct iwl_mld_txq *mld_txq = iwl_mld_txq_from_mac80211(txq);
 810
 811	if (likely(mld_txq->status.allocated) || !txq->sta) {
 812		iwl_mld_tx_from_txq(mld, txq);
 813		return;
 814	}
 815
 816	/* We don't support TSPEC tids. %IEEE80211_NUM_TIDS is for mgmt */
 817	if (txq->tid != IEEE80211_NUM_TIDS && txq->tid >= IWL_MAX_TID_COUNT) {
 818		IWL_DEBUG_MAC80211(mld, "TID %d is not supported\n", txq->tid);
 819		return;
 820	}
 821
 822	/* The worker will handle any packets we leave on the txq now */
 823
 824	spin_lock_bh(&mld->add_txqs_lock);
 825	/* The list is being deleted only after the queue is fully allocated. */
 826	if (list_empty(&mld_txq->list) &&
 827	    /* recheck under lock, otherwise it can be added twice */
 828	    !mld_txq->status.allocated) {
 829		list_add_tail(&mld_txq->list, &mld->txqs_to_add);
 830		wiphy_work_queue(mld->wiphy, &mld->add_txqs_wk);
 831	}
 832	spin_unlock_bh(&mld->add_txqs_lock);
 833}
 834
 835static void iwl_mld_teardown_tdls_peers(struct iwl_mld *mld)
 836{
 837	lockdep_assert_wiphy(mld->wiphy);
 838
 839	for (int i = 0; i < mld->fw->ucode_capa.num_stations; i++) {
 840		struct ieee80211_link_sta *link_sta;
 841		struct iwl_mld_sta *mld_sta;
 842
 843		link_sta = wiphy_dereference(mld->wiphy,
 844					     mld->fw_id_to_link_sta[i]);
 845		if (IS_ERR_OR_NULL(link_sta))
 846			continue;
 847
 848		if (!link_sta->sta->tdls)
 849			continue;
 850
 851		mld_sta = iwl_mld_sta_from_mac80211(link_sta->sta);
 852
 853		ieee80211_tdls_oper_request(mld_sta->vif, link_sta->addr,
 854					    NL80211_TDLS_TEARDOWN,
 855					    WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED,
 856					    GFP_KERNEL);
 857	}
 858}
 859
 860static
 861int iwl_mld_add_chanctx(struct ieee80211_hw *hw,
 862			struct ieee80211_chanctx_conf *ctx)
 863{
 864	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
 865	struct iwl_mld_phy *phy = iwl_mld_phy_from_mac80211(ctx);
 866	int fw_id = iwl_mld_allocate_fw_phy_id(mld);
 867	int ret;
 868
 869	if (fw_id < 0)
 870		return fw_id;
 871
 872	phy->mld = mld;
 873	phy->fw_id = fw_id;
 874	phy->chandef = *iwl_mld_get_chandef_from_chanctx(mld, ctx);
 875
 876	ret = iwl_mld_phy_fw_action(mld, ctx, FW_CTXT_ACTION_ADD);
 877	if (ret) {
 878		mld->used_phy_ids &= ~BIT(phy->fw_id);
 879		return ret;
 880	}
 881
 882	if (hweight8(mld->used_phy_ids) > 1)
 883		iwl_mld_teardown_tdls_peers(mld);
 884
 885	return 0;
 886}
 887
 888static
 889void iwl_mld_remove_chanctx(struct ieee80211_hw *hw,
 890			    struct ieee80211_chanctx_conf *ctx)
 891{
 892	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
 893	struct iwl_mld_phy *phy = iwl_mld_phy_from_mac80211(ctx);
 894
 895	iwl_mld_phy_fw_action(mld, ctx, FW_CTXT_ACTION_REMOVE);
 896	mld->used_phy_ids &= ~BIT(phy->fw_id);
 897}
 898
 899static
 900void iwl_mld_change_chanctx(struct ieee80211_hw *hw,
 901			    struct ieee80211_chanctx_conf *ctx, u32 changed)
 902{
 903	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
 904	struct iwl_mld_phy *phy = iwl_mld_phy_from_mac80211(ctx);
 905	struct cfg80211_chan_def *chandef =
 906		iwl_mld_get_chandef_from_chanctx(mld, ctx);
 907
 908	/* We don't care about these */
 909	if (!(changed & ~(IEEE80211_CHANCTX_CHANGE_RX_CHAINS |
 910			  IEEE80211_CHANCTX_CHANGE_RADAR |
 911			  IEEE80211_CHANCTX_CHANGE_CHANNEL)))
 912		return;
 913
 914	/* Check if a FW update is required */
 915
 916	if (changed & IEEE80211_CHANCTX_CHANGE_AP)
 917		goto update;
 918
 919	if (chandef->chan == phy->chandef.chan &&
 920	    chandef->center_freq1 == phy->chandef.center_freq1 &&
 921	    chandef->punctured == phy->chandef.punctured) {
 922		/* Check if we are toggling between HT and non-HT, no-op */
 923		if (phy->chandef.width == chandef->width ||
 924		    (phy->chandef.width <= NL80211_CHAN_WIDTH_20 &&
 925		     chandef->width <= NL80211_CHAN_WIDTH_20))
 926			return;
 927	}
 928update:
 929
 930	iwl_mld_update_phy_chandef(mld, ctx);
 931}
 932
 933static u8
 934iwl_mld_chandef_get_primary_80(struct cfg80211_chan_def *chandef)
 935{
 936	int data_start;
 937	int control_start;
 938	int bw;
 939
 940	if (chandef->width == NL80211_CHAN_WIDTH_320)
 941		bw = 320;
 942	else if (chandef->width == NL80211_CHAN_WIDTH_160)
 943		bw = 160;
 944	else
 945		return 0;
 946
 947	/* data is bw wide so the start is half the width */
 948	data_start = chandef->center_freq1 - bw / 2;
 949	/* control is 20Mhz width */
 950	control_start = chandef->chan->center_freq - 10;
 951
 952	return (control_start - data_start) / 80;
 953}
 954
 955static bool iwl_mld_can_activate_link(struct iwl_mld *mld,
 956				      struct ieee80211_vif *vif,
 957				      struct ieee80211_bss_conf *link)
 958{
 959	struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
 960	struct iwl_mld_sta *mld_sta;
 961	struct iwl_mld_link_sta *link_sta;
 962
 963	/* In association, we activate the assoc link before adding the STA. */
 964	if (!mld_vif->ap_sta || !vif->cfg.assoc)
 965		return true;
 966
 967	mld_sta = iwl_mld_sta_from_mac80211(mld_vif->ap_sta);
 968
 969	/* When switching links, we need to wait with the activation until the
 970	 * STA was added to the FW. It'll be activated in
 971	 * iwl_mld_update_link_stas
 972	 */
 973	link_sta = wiphy_dereference(mld->wiphy, mld_sta->link[link->link_id]);
 974
 975	/* In restart we can have a link_sta that doesn't exist in FW yet */
 976	return link_sta && link_sta->in_fw;
 977}
 978
 979static
 980int iwl_mld_assign_vif_chanctx(struct ieee80211_hw *hw,
 981			       struct ieee80211_vif *vif,
 982			       struct ieee80211_bss_conf *link,
 983			       struct ieee80211_chanctx_conf *ctx)
 984{
 985	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
 986	struct iwl_mld_link *mld_link = iwl_mld_link_from_mac80211(link);
 987	struct iwl_mld_link *temp_mld_link;
 988	struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
 989	u16 final_active_links = 0;
 990	int ret;
 991
 992	lockdep_assert_wiphy(mld->wiphy);
 993
 994	if (WARN_ON(!mld_link))
 995		return -EINVAL;
 996
 997	if (!rcu_access_pointer(mld_link->chan_ctx)) {
 998		/* Track addition of non-BSS link */
 999		if (ieee80211_vif_type_p2p(vif) != NL80211_IFTYPE_STATION) {
1000			ret = iwl_mld_emlsr_check_non_bss_block(mld, 1);
1001			if (ret)
1002				return ret;
1003		}
1004	}
1005
1006	/* for AP, mac parameters such as HE support are updated at this stage. */
1007	if (vif->type == NL80211_IFTYPE_AP) {
1008		ret = iwl_mld_mac_fw_action(mld, vif, FW_CTXT_ACTION_MODIFY);
1009
1010		if (ret) {
1011			IWL_ERR(mld, "failed to update MAC %pM\n", vif->addr);
1012			return -EINVAL;
1013		}
1014	}
1015
1016	rcu_assign_pointer(mld_link->chan_ctx, ctx);
1017
1018	/* We cannot rely on vif->active_links at this stage as it contains
1019	 * both the removed links and the newly added links.
1020	 * Therefore, we create our own bitmap of the final active links,
1021	 * which does not include the removed links.
1022	 */
1023	for_each_mld_vif_valid_link(mld_vif, temp_mld_link) {
1024		if (rcu_access_pointer(temp_mld_link->chan_ctx))
1025			final_active_links |= BIT(link_id);
1026	}
1027
1028	if (hweight16(final_active_links) > 1) {
1029		/* Indicate to mac80211 that EML is enabled */
1030		vif->driver_flags |= IEEE80211_VIF_EML_ACTIVE;
1031		mld_vif->emlsr.last_entry_ts = jiffies;
1032
1033		if (final_active_links == mld_vif->emlsr.selected_links)
1034			mld_vif->emlsr.primary = mld_vif->emlsr.selected_primary;
1035		else
1036			mld_vif->emlsr.primary = __ffs(final_active_links);
1037
1038		iwl_dbg_tlv_time_point(&mld->fwrt, IWL_FW_INI_TIME_ESR_LINK_UP,
1039				       NULL);
1040	}
1041
1042	/* First send the link command with the phy context ID.
1043	 * Now that we have the phy, we know the band so also the rates
1044	 */
1045	ret = iwl_mld_change_link_in_fw(mld, link,
1046					LINK_CONTEXT_MODIFY_RATES_INFO);
1047	if (ret)
1048		goto err;
1049
1050	/* TODO: Initialize rate control for the AP station, since we might be
1051	 * doing a link switch here - we cannot initialize it before since
1052	 * this needs the phy context assigned (and in FW?), and we cannot
1053	 * do it later because it needs to be initialized as soon as we're
1054	 * able to TX on the link, i.e. when active. (task=link-switch)
1055	 */
1056
1057	/* Now activate the link */
1058	if (iwl_mld_can_activate_link(mld, vif, link)) {
1059		ret = iwl_mld_activate_link(mld, link);
1060		if (ret)
1061			goto err;
1062	}
1063
1064	if (vif->type == NL80211_IFTYPE_STATION)
1065		iwl_mld_send_ap_tx_power_constraint_cmd(mld, vif, link);
1066
1067	if (vif->type == NL80211_IFTYPE_MONITOR) {
1068		ret = iwl_mld_add_mon_sta(mld, vif, link);
1069		if (ret)
1070			goto deactivate_link;
1071
1072		mld->monitor.p80 =
1073			iwl_mld_chandef_get_primary_80(&vif->bss_conf.chanreq.oper);
1074	}
1075
1076	return 0;
1077
1078deactivate_link:
1079	if (mld_link->active)
1080		iwl_mld_deactivate_link(mld, link);
1081err:
1082	RCU_INIT_POINTER(mld_link->chan_ctx, NULL);
1083	return ret;
1084}
1085
1086static
1087void iwl_mld_unassign_vif_chanctx(struct ieee80211_hw *hw,
1088				  struct ieee80211_vif *vif,
1089				  struct ieee80211_bss_conf *link,
1090				  struct ieee80211_chanctx_conf *ctx)
1091{
1092	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
1093	struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
1094	struct iwl_mld_link *mld_link = iwl_mld_link_from_mac80211(link);
1095	unsigned int n_active = iwl_mld_count_active_links(mld, vif);
1096
1097	if (WARN_ON(!mld_link))
1098		return;
1099
1100	/* Track removal of non-BSS link */
1101	if (ieee80211_vif_type_p2p(vif) != NL80211_IFTYPE_STATION)
1102		iwl_mld_emlsr_check_non_bss_block(mld, -1);
1103
1104	iwl_mld_deactivate_link(mld, link);
1105
1106	if (vif->type == NL80211_IFTYPE_MONITOR)
1107		iwl_mld_remove_mon_sta(mld, vif, link);
1108
1109	if (n_active > 1) {
1110		/* Indicate to mac80211 that EML is disabled */
1111		vif->driver_flags &= ~IEEE80211_VIF_EML_ACTIVE;
1112
1113		iwl_dbg_tlv_time_point(&mld->fwrt,
1114				       IWL_FW_INI_TIME_ESR_LINK_DOWN,
1115				       NULL);
1116	}
1117
1118	RCU_INIT_POINTER(mld_link->chan_ctx, NULL);
1119
1120	/* in the non-MLO case, remove/re-add the link to clean up FW state.
1121	 * In MLO, it'll be done in drv_change_vif_link
1122	 */
1123	if (!ieee80211_vif_is_mld(vif) && !mld_vif->ap_sta &&
1124	    !WARN_ON_ONCE(vif->cfg.assoc) &&
1125	    vif->type != NL80211_IFTYPE_AP && !mld->fw_status.in_hw_restart) {
1126		iwl_mld_remove_link(mld, link);
1127		iwl_mld_add_link(mld, link);
1128	}
1129}
1130
1131static
1132int iwl_mld_mac80211_set_rts_threshold(struct ieee80211_hw *hw, int radio_idx,
1133				       u32 value)
1134{
1135	return 0;
1136}
1137
1138static void
1139iwl_mld_link_info_changed_ap_ibss(struct iwl_mld *mld,
1140				  struct ieee80211_vif *vif,
1141				  struct ieee80211_bss_conf *link,
1142				  u64 changes)
1143{
1144	u32 link_changes = 0;
1145
1146	if (changes & BSS_CHANGED_ERP_SLOT)
1147		link_changes |= LINK_CONTEXT_MODIFY_RATES_INFO;
1148
1149	if (changes & (BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_HT))
1150		link_changes |= LINK_CONTEXT_MODIFY_PROTECT_FLAGS;
1151
1152	if (changes & (BSS_CHANGED_QOS | BSS_CHANGED_BANDWIDTH))
1153		link_changes |= LINK_CONTEXT_MODIFY_QOS_PARAMS;
1154
1155	if (changes & BSS_CHANGED_HE_BSS_COLOR)
1156		link_changes |= LINK_CONTEXT_MODIFY_HE_PARAMS;
1157
1158	if (link_changes)
1159		iwl_mld_change_link_in_fw(mld, link, link_changes);
1160
1161	if (changes & BSS_CHANGED_BEACON)
1162		iwl_mld_update_beacon_template(mld, vif, link);
1163}
1164
1165static
1166u32 iwl_mld_link_changed_mapping(struct iwl_mld *mld,
1167				 struct ieee80211_vif *vif,
1168				 struct ieee80211_bss_conf *link_conf,
1169				 u64 changes)
1170{
1171	u32 link_changes = 0;
1172	bool has_he, has_eht;
1173
1174	if (changes & BSS_CHANGED_QOS && vif->cfg.assoc && link_conf->qos)
1175		link_changes |= LINK_CONTEXT_MODIFY_QOS_PARAMS;
1176
1177	if (changes & (BSS_CHANGED_ERP_PREAMBLE | BSS_CHANGED_BASIC_RATES |
1178		       BSS_CHANGED_ERP_SLOT))
1179		link_changes |= LINK_CONTEXT_MODIFY_RATES_INFO;
1180
1181	if (changes & (BSS_CHANGED_HT | BSS_CHANGED_ERP_CTS_PROT))
1182		link_changes |= LINK_CONTEXT_MODIFY_PROTECT_FLAGS;
1183
1184	/* TODO: task=MLO check mac80211's HE flags and if command is needed
1185	 * every time there's a link change. Currently used flags are
1186	 * BSS_CHANGED_HE_OBSS_PD and BSS_CHANGED_HE_BSS_COLOR.
1187	 */
1188	has_he = link_conf->he_support && !iwlwifi_mod_params.disable_11ax;
1189	has_eht = link_conf->eht_support && !iwlwifi_mod_params.disable_11be;
1190
1191	if (vif->cfg.assoc && (has_he || has_eht)) {
1192		IWL_DEBUG_MAC80211(mld, "Associated in HE mode\n");
1193		link_changes |= LINK_CONTEXT_MODIFY_HE_PARAMS;
1194	}
1195
1196	return link_changes;
1197}
1198
1199static void
1200iwl_mld_mac80211_link_info_changed_sta(struct iwl_mld *mld,
1201				       struct ieee80211_vif *vif,
1202				       struct ieee80211_bss_conf *link_conf,
1203				       u64 changes)
1204{
1205	u32 link_changes = iwl_mld_link_changed_mapping(mld, vif, link_conf,
1206							changes);
1207
1208	if (link_changes)
1209		iwl_mld_change_link_in_fw(mld, link_conf, link_changes);
1210
1211	if (changes & BSS_CHANGED_TPE)
1212		iwl_mld_send_ap_tx_power_constraint_cmd(mld, vif, link_conf);
1213
1214	if (changes & BSS_CHANGED_BEACON_INFO)
1215		iwl_mld_update_mac_power(mld, vif, false);
1216
1217	/* The firmware will wait quite a while after association before it
1218	 * starts filtering the beacons. We can safely enable beacon filtering
1219	 * upon CQM configuration, even if we didn't get a beacon yet.
1220	 */
1221	if (changes & (BSS_CHANGED_CQM | BSS_CHANGED_BEACON_INFO))
1222		iwl_mld_enable_beacon_filter(mld, link_conf, false);
1223
1224	if (changes & BSS_CHANGED_BANDWIDTH)
1225		iwl_mld_retry_emlsr(mld, vif);
1226}
1227
1228static int iwl_mld_update_mu_groups(struct iwl_mld *mld,
1229				    struct ieee80211_bss_conf *link_conf)
1230{
1231	struct iwl_mu_group_mgmt_cmd cmd = {};
1232
1233	BUILD_BUG_ON(sizeof(cmd.membership_status) !=
1234		     sizeof(link_conf->mu_group.membership));
1235	BUILD_BUG_ON(sizeof(cmd.user_position) !=
1236		     sizeof(link_conf->mu_group.position));
1237
1238	memcpy(cmd.membership_status, link_conf->mu_group.membership,
1239	       WLAN_MEMBERSHIP_LEN);
1240	memcpy(cmd.user_position, link_conf->mu_group.position,
1241	       WLAN_USER_POSITION_LEN);
1242
1243	return iwl_mld_send_cmd_pdu(mld,
1244				    WIDE_ID(DATA_PATH_GROUP,
1245					    UPDATE_MU_GROUPS_CMD),
1246				    &cmd);
1247}
1248
1249static void
1250iwl_mld_mac80211_link_info_changed(struct ieee80211_hw *hw,
1251				   struct ieee80211_vif *vif,
1252				   struct ieee80211_bss_conf *link_conf,
1253				   u64 changes)
1254{
1255	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
1256
1257	switch (vif->type) {
1258	case NL80211_IFTYPE_STATION:
1259		iwl_mld_mac80211_link_info_changed_sta(mld, vif, link_conf,
1260						       changes);
1261		break;
1262	case NL80211_IFTYPE_AP:
1263	case NL80211_IFTYPE_ADHOC:
1264		iwl_mld_link_info_changed_ap_ibss(mld, vif, link_conf,
1265						  changes);
1266		break;
1267	case NL80211_IFTYPE_MONITOR:
1268		/* The firmware tracks this on its own in STATION mode, but
1269		 * obviously not in sniffer mode.
1270		 */
1271		if (changes & BSS_CHANGED_MU_GROUPS)
1272			iwl_mld_update_mu_groups(mld, link_conf);
1273		break;
1274	default:
1275		/* shouldn't happen */
1276		WARN_ON_ONCE(1);
1277	}
1278
1279	/* We now know our BSSID, we can configure the MAC context with
1280	 * eht_support if needed.
1281	 */
1282	if (changes & BSS_CHANGED_BSSID)
1283		iwl_mld_mac_fw_action(mld, vif, FW_CTXT_ACTION_MODIFY);
1284
1285	if (changes & BSS_CHANGED_TXPOWER)
1286		iwl_mld_set_tx_power(mld, link_conf, link_conf->txpower);
1287}
1288
1289static void
1290iwl_mld_smps_workaround(struct iwl_mld *mld, struct ieee80211_vif *vif, bool enable)
1291{
1292	struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
1293	bool workaround_required =
1294		iwl_fw_lookup_cmd_ver(mld->fw, MAC_PM_POWER_TABLE, 0) < 2;
1295
1296	if (!workaround_required)
1297		return;
1298
1299	/* Send the device-level power commands since the
1300	 * firmware checks the POWER_TABLE_CMD's POWER_SAVE_EN bit to
1301	 * determine SMPS mode.
1302	 */
1303	if (mld_vif->ps_disabled == !enable)
1304		return;
1305
1306	mld_vif->ps_disabled = !enable;
1307
1308	iwl_mld_update_device_power(mld, false);
1309}
1310
1311static
1312void iwl_mld_mac80211_vif_cfg_changed(struct ieee80211_hw *hw,
1313				      struct ieee80211_vif *vif,
1314				      u64 changes)
1315{
1316	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
1317	int ret;
1318
1319	lockdep_assert_wiphy(mld->wiphy);
1320
1321	if (vif->type != NL80211_IFTYPE_STATION)
1322		return;
1323
1324	if (changes & BSS_CHANGED_ASSOC) {
1325		ret = iwl_mld_mac_fw_action(mld, vif, FW_CTXT_ACTION_MODIFY);
1326		if (ret)
1327			IWL_ERR(mld, "failed to update context\n");
1328
1329		if (vif->cfg.assoc) {
1330			/* Clear statistics to get clean beacon counter, and
1331			 * ask for periodic statistics, as they are needed for
1332			 * link selection and RX OMI decisions.
1333			 */
1334			iwl_mld_clear_stats_in_fw(mld);
1335			iwl_mld_request_periodic_fw_stats(mld, true);
1336
1337			iwl_mld_set_vif_associated(mld, vif);
1338		} else {
1339			iwl_mld_request_periodic_fw_stats(mld, false);
1340		}
1341	}
1342
1343	if (changes & BSS_CHANGED_PS) {
1344		iwl_mld_smps_workaround(mld, vif, vif->cfg.ps);
1345		iwl_mld_update_mac_power(mld, vif, false);
1346	}
1347
1348	/* TODO: task=MLO BSS_CHANGED_MLD_VALID_LINKS/CHANGED_MLD_TTLM */
1349}
1350
1351static int
1352iwl_mld_mac80211_hw_scan(struct ieee80211_hw *hw,
1353			 struct ieee80211_vif *vif,
1354			 struct ieee80211_scan_request *hw_req)
1355{
1356	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
1357	int ret;
1358
1359	if (WARN_ON(!hw_req->req.n_channels ||
1360		    hw_req->req.n_channels >
1361		    mld->fw->ucode_capa.n_scan_channels))
1362		return -EINVAL;
1363
1364	ret = iwl_mld_regular_scan_start(mld, vif, &hw_req->req, &hw_req->ies);
1365	if (!ret) {
1366		/* We will be busy with scanning, so the counters may not reflect the
1367		 * reality. Stop checking the counters until the scan ends
1368		 */
1369		iwl_mld_start_ignoring_tpt_updates(mld);
1370	}
1371
1372	return ret;
1373}
1374
1375static void
1376iwl_mld_mac80211_cancel_hw_scan(struct ieee80211_hw *hw,
1377				struct ieee80211_vif *vif)
1378{
1379	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
1380
1381	/* Due to a race condition, it's possible that mac80211 asks
1382	 * us to stop a hw_scan when it's already stopped. This can
1383	 * happen, for instance, if we stopped the scan ourselves,
1384	 * called ieee80211_scan_completed() and the userspace called
1385	 * cancel scan before ieee80211_scan_work() could run.
1386	 * To handle that, simply return if the scan is not running.
1387	 */
1388	if (mld->scan.status & IWL_MLD_SCAN_REGULAR) {
1389		iwl_mld_scan_stop(mld, IWL_MLD_SCAN_REGULAR, true);
1390		/* Scan is over, we can check again the tpt counters */
1391		iwl_mld_stop_ignoring_tpt_updates(mld);
1392	}
1393}
1394
1395static int
1396iwl_mld_mac80211_sched_scan_start(struct ieee80211_hw *hw,
1397				  struct ieee80211_vif *vif,
1398				  struct cfg80211_sched_scan_request *req,
1399				  struct ieee80211_scan_ies *ies)
1400{
1401	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
1402
1403	return iwl_mld_sched_scan_start(mld, vif, req, ies, IWL_MLD_SCAN_SCHED);
1404}
1405
1406static int
1407iwl_mld_mac80211_sched_scan_stop(struct ieee80211_hw *hw,
1408				 struct ieee80211_vif *vif)
1409{
1410	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
1411
1412	/* Due to a race condition, it's possible that mac80211 asks
1413	 * us to stop a sched_scan when it's already stopped. This
1414	 * can happen, for instance, if we stopped the scan ourselves,
1415	 * called ieee80211_sched_scan_stopped() and the userspace called
1416	 * stop sched scan before ieee80211_sched_scan_stopped_work()
1417	 * could run. To handle this, simply return if the scan is
1418	 * not running.
1419	 */
1420	if (!(mld->scan.status & IWL_MLD_SCAN_SCHED))
1421		return 0;
1422
1423	return iwl_mld_scan_stop(mld, IWL_MLD_SCAN_SCHED, false);
1424}
1425
1426static void
1427iwl_mld_mac80211_reconfig_complete(struct ieee80211_hw *hw,
1428				   enum ieee80211_reconfig_type reconfig_type)
1429{
1430	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
1431
1432	switch (reconfig_type) {
1433	case IEEE80211_RECONFIG_TYPE_RESTART:
1434		mld->fw_status.in_hw_restart = false;
1435		iwl_mld_send_recovery_cmd(mld, ERROR_RECOVERY_END_OF_RECOVERY);
1436		iwl_trans_finish_sw_reset(mld->trans);
1437		/* no need to lock, adding in parallel would schedule too */
1438		if (!list_empty(&mld->txqs_to_add))
1439			wiphy_work_queue(mld->wiphy, &mld->add_txqs_wk);
1440
1441		IWL_INFO(mld, "restart completed\n");
1442		break;
1443	case IEEE80211_RECONFIG_TYPE_SUSPEND:
1444		break;
1445	}
1446}
1447
1448static
1449void iwl_mld_mac80211_mgd_prepare_tx(struct ieee80211_hw *hw,
1450				     struct ieee80211_vif *vif,
1451				     struct ieee80211_prep_tx_info *info)
1452{
1453	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
1454	u32 duration = IWL_MLD_SESSION_PROTECTION_ASSOC_TIME_MS;
1455
1456	/* After a successful association the connection is established
1457	 * and we can rely on the quota to send the disassociation frame.
1458	 */
1459	if (info->was_assoc)
1460		return;
1461
1462	if (info->duration > duration)
1463		duration = info->duration;
1464
1465	iwl_mld_schedule_session_protection(mld, vif, duration,
1466					    IWL_MLD_SESSION_PROTECTION_MIN_TIME_MS,
1467					    info->link_id);
1468}
1469
1470static
1471void iwl_mld_mac_mgd_complete_tx(struct ieee80211_hw *hw,
1472				 struct ieee80211_vif *vif,
1473				 struct ieee80211_prep_tx_info *info)
1474{
1475	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
1476
1477	/* Successful authentication is the only case that requires to let
1478	 * the session protection go. We'll need it for the upcoming
1479	 * association. For all the other cases, we need to cancel the session
1480	 * protection.
1481	 * After successful association the connection is established and
1482	 * further mgd tx can rely on the quota.
1483	 */
1484	if (info->success && info->subtype == IEEE80211_STYPE_AUTH)
1485		return;
1486
1487	/* The firmware will be on medium after we configure the vif as
1488	 * associated. Removing the session protection allows the firmware
1489	 * to stop being on medium. In order to ensure the continuity of our
1490	 * presence on medium, we need first to configure the vif as associated
1491	 * and only then, remove the session protection.
1492	 * Currently, mac80211 calls vif_cfg_changed() first and then,
1493	 * drv_mgd_complete_tx(). Ensure that this assumption stays true by
1494	 * a warning.
1495	 */
1496	WARN_ON(info->success &&
1497		(info->subtype == IEEE80211_STYPE_ASSOC_REQ ||
1498		 info->subtype == IEEE80211_STYPE_REASSOC_REQ) &&
1499		!vif->cfg.assoc);
1500
1501	iwl_mld_cancel_session_protection(mld, vif, info->link_id);
1502}
1503
1504static int
1505iwl_mld_mac80211_conf_tx(struct ieee80211_hw *hw,
1506			 struct ieee80211_vif *vif,
1507			 unsigned int link_id, u16 ac,
1508			 const struct ieee80211_tx_queue_params *params)
1509{
1510	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
1511	struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
1512	struct iwl_mld_link *link;
1513
1514	lockdep_assert_wiphy(mld->wiphy);
1515
1516	link = iwl_mld_link_dereference_check(mld_vif, link_id);
1517	if (!link)
1518		return -EINVAL;
1519
1520	link->queue_params[ac] = *params;
1521
1522	/* No need to update right away, we'll get BSS_CHANGED_QOS
1523	 * The exception is P2P_DEVICE interface which needs immediate update.
1524	 */
1525	if (vif->type == NL80211_IFTYPE_P2P_DEVICE)
1526		iwl_mld_change_link_in_fw(mld, &vif->bss_conf,
1527					  LINK_CONTEXT_MODIFY_QOS_PARAMS);
1528
1529	return 0;
1530}
1531
1532static void iwl_mld_set_uapsd(struct iwl_mld *mld, struct ieee80211_vif *vif)
1533{
1534	vif->driver_flags &= ~IEEE80211_VIF_SUPPORTS_UAPSD;
1535
1536	if (vif->type != NL80211_IFTYPE_STATION)
1537		return;
1538
1539	if (vif->p2p &&
1540	    !(iwlwifi_mod_params.uapsd_disable & IWL_DISABLE_UAPSD_P2P_CLIENT))
1541		vif->driver_flags |= IEEE80211_VIF_SUPPORTS_UAPSD;
1542
1543	if (!vif->p2p &&
1544	    !(iwlwifi_mod_params.uapsd_disable & IWL_DISABLE_UAPSD_BSS))
1545		vif->driver_flags |= IEEE80211_VIF_SUPPORTS_UAPSD;
1546}
1547
1548int iwl_mld_tdls_sta_count(struct iwl_mld *mld)
1549{
1550	int count = 0;
1551
1552	lockdep_assert_wiphy(mld->wiphy);
1553
1554	for (int i = 0; i < mld->fw->ucode_capa.num_stations; i++) {
1555		struct ieee80211_link_sta *link_sta;
1556
1557		link_sta = wiphy_dereference(mld->wiphy,
1558					     mld->fw_id_to_link_sta[i]);
1559		if (IS_ERR_OR_NULL(link_sta))
1560			continue;
1561
1562		if (!link_sta->sta->tdls)
1563			continue;
1564
1565		count++;
1566	}
1567
1568	return count;
1569}
1570
1571static void iwl_mld_check_he_obss_narrow_bw_ru_iter(struct wiphy *wiphy,
1572						    struct cfg80211_bss *bss,
1573						    void *_data)
1574{
1575	bool *tolerated = _data;
1576	const struct cfg80211_bss_ies *ies;
1577	const struct element *elem;
1578
1579	rcu_read_lock();
1580	ies = rcu_dereference(bss->ies);
1581	elem = cfg80211_find_elem(WLAN_EID_EXT_CAPABILITY, ies->data,
1582				  ies->len);
1583
1584	if (!elem || elem->datalen < 10 ||
1585	    !(elem->data[10] &
1586	      WLAN_EXT_CAPA10_OBSS_NARROW_BW_RU_TOLERANCE_SUPPORT)) {
1587		*tolerated = false;
1588	}
1589	rcu_read_unlock();
1590}
1591
1592static void
1593iwl_mld_check_he_obss_narrow_bw_ru(struct iwl_mld *mld,
1594				   struct iwl_mld_link *mld_link,
1595				   struct ieee80211_bss_conf *link_conf)
1596{
1597	bool tolerated = true;
1598
1599	if (WARN_ON_ONCE(!link_conf->chanreq.oper.chan))
1600		return;
1601
1602	if (!(link_conf->chanreq.oper.chan->flags & IEEE80211_CHAN_RADAR)) {
1603		mld_link->he_ru_2mhz_block = false;
1604		return;
1605	}
1606
1607	cfg80211_bss_iter(mld->wiphy, &link_conf->chanreq.oper,
1608			  iwl_mld_check_he_obss_narrow_bw_ru_iter, &tolerated);
1609
1610	/* If there is at least one AP on radar channel that cannot
1611	 * tolerate 26-tone RU UL OFDMA transmissions using HE TB PPDU.
1612	 */
1613	mld_link->he_ru_2mhz_block = !tolerated;
1614}
1615
1616static void iwl_mld_link_set_2mhz_block(struct iwl_mld *mld,
1617					struct ieee80211_vif *vif,
1618					struct ieee80211_sta *sta)
1619{
1620	struct ieee80211_link_sta *link_sta;
1621	unsigned int link_id;
1622
1623	for_each_sta_active_link(vif, sta, link_sta, link_id) {
1624		struct ieee80211_bss_conf *link_conf =
1625			link_conf_dereference_protected(vif, link_id);
1626		struct iwl_mld_link *mld_link =
1627			iwl_mld_link_from_mac80211(link_conf);
1628
1629		if (WARN_ON(!link_conf || !mld_link))
1630			continue;
1631
1632		if (link_sta->he_cap.has_he)
1633			iwl_mld_check_he_obss_narrow_bw_ru(mld, mld_link,
1634							   link_conf);
1635	}
1636}
1637
1638static int iwl_mld_move_sta_state_up(struct iwl_mld *mld,
1639				     struct ieee80211_vif *vif,
1640				     struct ieee80211_sta *sta,
1641				     enum ieee80211_sta_state old_state,
1642				     enum ieee80211_sta_state new_state)
1643{
1644	struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
1645	int tdls_count = 0;
1646	int ret;
1647
1648	if (old_state == IEEE80211_STA_NOTEXIST &&
1649	    new_state == IEEE80211_STA_NONE) {
1650		if (sta->tdls) {
1651			if (vif->p2p || hweight8(mld->used_phy_ids) != 1)
1652				return -EBUSY;
1653
1654			tdls_count = iwl_mld_tdls_sta_count(mld);
1655			if (tdls_count >= IWL_TDLS_STA_COUNT)
1656				return -EBUSY;
1657		}
1658
1659		ret = iwl_mld_add_sta(mld, sta, vif, STATION_TYPE_PEER);
1660		if (ret)
1661			return ret;
1662
1663		/* just added first TDLS STA, so disable PM */
1664		if (sta->tdls && tdls_count == 0)
1665			iwl_mld_update_mac_power(mld, vif, false);
1666
1667		if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
1668			mld_vif->ap_sta = sta;
1669
1670		/* Initialize TLC here already - this really tells
1671		 * the firmware only what the supported legacy rates are
1672		 * (may be) since it's initialized already from what the
1673		 * AP advertised in the beacon/probe response. This will
1674		 * allow the firmware to send auth/assoc frames with one
1675		 * of the supported rates already, rather than having to
1676		 * use a mandatory rate.
1677		 * If we're the AP, we'll just assume mandatory rates at
1678		 * this point, but we know nothing about the STA anyway.
1679		 */
1680		iwl_mld_config_tlc(mld, vif, sta);
1681
1682		return ret;
1683	} else if (old_state == IEEE80211_STA_NONE &&
1684		   new_state == IEEE80211_STA_AUTH) {
1685		iwl_mld_set_uapsd(mld, vif);
1686		return 0;
1687	} else if (old_state == IEEE80211_STA_AUTH &&
1688		   new_state == IEEE80211_STA_ASSOC) {
1689		ret = iwl_mld_update_all_link_stations(mld, sta);
1690
1691		if (vif->type == NL80211_IFTYPE_STATION)
1692			iwl_mld_link_set_2mhz_block(mld, vif, sta);
1693
1694		if (sta->tdls) {
1695			/*
1696			 * update MAC since wifi generation flags may change,
1697			 * we also update MAC on association to the AP via the
1698			 * vif assoc change
1699			 */
1700			iwl_mld_mac_fw_action(mld, vif, FW_CTXT_ACTION_MODIFY);
1701		}
1702
1703		/* Now the link_sta's capabilities are set, update the FW */
1704		iwl_mld_config_tlc(mld, vif, sta);
1705
1706		if (vif->type == NL80211_IFTYPE_AP) {
1707			/* Update MAC_CFG_FILTER_ACCEPT_BEACON if at least
1708			 * one sta is associated
1709			 */
1710			if (++mld_vif->num_associated_stas == 1)
1711				ret = iwl_mld_mac_fw_action(mld, vif,
1712							    FW_CTXT_ACTION_MODIFY);
1713		}
1714
1715		return ret;
1716	} else if (old_state == IEEE80211_STA_ASSOC &&
1717		   new_state == IEEE80211_STA_AUTHORIZED) {
1718		ret = 0;
1719
1720		if (!sta->tdls) {
1721			mld_vif->authorized = true;
1722
1723			/* Ensure any block due to a non-BSS link is synced */
1724			iwl_mld_emlsr_check_non_bss_block(mld, 0);
1725
1726			/* Block EMLSR until a certain throughput it reached */
1727			if (!mld->fw_status.in_hw_restart &&
1728			    IWL_MLD_ENTER_EMLSR_TPT_THRESH > 0)
1729				iwl_mld_block_emlsr(mld_vif->mld, vif,
1730						    IWL_MLD_EMLSR_BLOCKED_TPT,
1731						    0);
1732
1733			/* clear COEX_HIGH_PRIORITY_ENABLE */
1734			ret = iwl_mld_mac_fw_action(mld, vif,
1735						    FW_CTXT_ACTION_MODIFY);
1736			if (ret)
1737				return ret;
1738			iwl_mld_smps_workaround(mld, vif, vif->cfg.ps);
1739		}
1740
1741		/* MFP is set by default before the station is authorized.
1742		 * Clear it here in case it's not used.
1743		 */
1744		if (!sta->mfp)
1745			ret = iwl_mld_update_all_link_stations(mld, sta);
1746
1747		/* We can use wide bandwidth now, not only 20 MHz */
1748		iwl_mld_config_tlc(mld, vif, sta);
1749
1750		return ret;
1751	} else {
1752		return -EINVAL;
1753	}
1754}
1755
1756static int iwl_mld_move_sta_state_down(struct iwl_mld *mld,
1757				       struct ieee80211_vif *vif,
1758				       struct ieee80211_sta *sta,
1759				       enum ieee80211_sta_state old_state,
1760				       enum ieee80211_sta_state new_state)
1761{
1762	struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
1763
1764	if (old_state == IEEE80211_STA_AUTHORIZED &&
1765	    new_state == IEEE80211_STA_ASSOC) {
1766		if (!sta->tdls) {
1767			mld_vif->authorized = false;
1768
1769			memset(&mld_vif->emlsr.zeroed_on_not_authorized, 0,
1770			       sizeof(mld_vif->emlsr.zeroed_on_not_authorized));
1771
1772			wiphy_delayed_work_cancel(mld->wiphy,
1773						  &mld_vif->emlsr.prevent_done_wk);
1774			wiphy_delayed_work_cancel(mld->wiphy,
1775						  &mld_vif->emlsr.tmp_non_bss_done_wk);
1776			wiphy_work_cancel(mld->wiphy, &mld_vif->emlsr.unblock_tpt_wk);
1777			wiphy_delayed_work_cancel(mld->wiphy,
1778						  &mld_vif->emlsr.check_tpt_wk);
1779			wiphy_delayed_work_cancel(mld->wiphy,
1780						  &mld_vif->mlo_scan_start_wk);
1781
1782			iwl_mld_reset_cca_40mhz_workaround(mld, vif);
1783			iwl_mld_smps_workaround(mld, vif, true);
1784		}
1785
1786		/* once we move into assoc state, need to update the FW to
1787		 * stop using wide bandwidth
1788		 */
1789		iwl_mld_config_tlc(mld, vif, sta);
1790	} else if (old_state == IEEE80211_STA_ASSOC &&
1791		   new_state == IEEE80211_STA_AUTH) {
1792		if (vif->type == NL80211_IFTYPE_AP &&
1793		    !WARN_ON(!mld_vif->num_associated_stas)) {
1794			/* Update MAC_CFG_FILTER_ACCEPT_BEACON if the last sta
1795			 * is disassociating
1796			 */
1797			if (--mld_vif->num_associated_stas == 0)
1798				iwl_mld_mac_fw_action(mld, vif,
1799						      FW_CTXT_ACTION_MODIFY);
1800		}
1801	} else if (old_state == IEEE80211_STA_AUTH &&
1802		   new_state == IEEE80211_STA_NONE) {
1803		/* nothing */
1804	} else if (old_state == IEEE80211_STA_NONE &&
1805		   new_state == IEEE80211_STA_NOTEXIST) {
1806		iwl_mld_remove_sta(mld, sta);
1807
1808		if (sta->tdls && iwl_mld_tdls_sta_count(mld) == 0) {
1809			/* just removed last TDLS STA, so enable PM */
1810			iwl_mld_update_mac_power(mld, vif, false);
1811		}
1812
1813		if (sta->tdls) {
1814			/*
1815			 * update MAC since wifi generation flags may change,
1816			 * we also update MAC on disassociation to the AP via
1817			 * the vif assoc change
1818			 */
1819			iwl_mld_mac_fw_action(mld, vif, FW_CTXT_ACTION_MODIFY);
1820		}
1821	} else {
1822		return -EINVAL;
1823	}
1824	return 0;
1825}
1826
1827static int iwl_mld_mac80211_sta_state(struct ieee80211_hw *hw,
1828				      struct ieee80211_vif *vif,
1829				      struct ieee80211_sta *sta,
1830				      enum ieee80211_sta_state old_state,
1831				      enum ieee80211_sta_state new_state)
1832{
1833	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
1834	struct iwl_mld_sta *mld_sta = iwl_mld_sta_from_mac80211(sta);
1835
1836	IWL_DEBUG_MAC80211(mld, "station %pM state change %d->%d\n",
1837			   sta->addr, old_state, new_state);
1838
1839	mld_sta->sta_state = new_state;
1840
1841	if (old_state < new_state)
1842		return iwl_mld_move_sta_state_up(mld, vif, sta, old_state,
1843						 new_state);
1844	else
1845		return iwl_mld_move_sta_state_down(mld, vif, sta, old_state,
1846						   new_state);
1847}
1848
1849static void iwl_mld_mac80211_flush(struct ieee80211_hw *hw,
1850				   struct ieee80211_vif *vif,
1851				   u32 queues, bool drop)
1852{
1853	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
1854
1855	/* Make sure we're done with the deferred traffic before flushing */
1856	iwl_mld_add_txq_list(mld);
1857
1858	for (int i = 0; i < mld->fw->ucode_capa.num_stations; i++) {
1859		struct ieee80211_link_sta *link_sta =
1860			wiphy_dereference(mld->wiphy,
1861					  mld->fw_id_to_link_sta[i]);
1862
1863		if (IS_ERR_OR_NULL(link_sta))
1864			continue;
1865
1866		/* Check that the sta belongs to the given vif */
1867		if (vif && vif != iwl_mld_sta_from_mac80211(link_sta->sta)->vif)
1868			continue;
1869
1870		if (drop)
1871			iwl_mld_flush_sta_txqs(mld, link_sta->sta);
1872		else
1873			iwl_mld_wait_sta_txqs_empty(mld, link_sta->sta);
1874	}
1875}
1876
1877static void iwl_mld_mac80211_flush_sta(struct ieee80211_hw *hw,
1878				       struct ieee80211_vif *vif,
1879				       struct ieee80211_sta *sta)
1880{
1881	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
1882
1883	iwl_mld_flush_sta_txqs(mld, sta);
1884}
1885
1886static int
1887iwl_mld_mac80211_ampdu_action(struct ieee80211_hw *hw,
1888			      struct ieee80211_vif *vif,
1889			      struct ieee80211_ampdu_params *params)
1890{
1891	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
1892	struct ieee80211_sta *sta = params->sta;
1893	enum ieee80211_ampdu_mlme_action action = params->action;
1894	u16 tid = params->tid;
1895	u16 ssn = params->ssn;
1896	u16 buf_size = params->buf_size;
1897	u16 timeout = params->timeout;
1898	int ret;
1899
1900	IWL_DEBUG_HT(mld, "A-MPDU action on addr %pM tid: %d action: %d\n",
1901		     sta->addr, tid, action);
1902
1903	switch (action) {
1904	case IEEE80211_AMPDU_RX_START:
1905		if (!iwl_enable_rx_ampdu()) {
1906			ret = -EINVAL;
1907			break;
1908		}
1909		ret = iwl_mld_ampdu_rx_start(mld, sta, tid, ssn, buf_size,
1910					     timeout);
1911		break;
1912	case IEEE80211_AMPDU_RX_STOP:
1913		ret = iwl_mld_ampdu_rx_stop(mld, sta, tid);
1914		break;
1915	default:
1916		/* The mac80211 TX_AMPDU_SETUP_IN_HW flag is set for all
1917		 * devices, since all support TX A-MPDU offload in hardware.
1918		 * Therefore, no TX action should be requested here.
1919		 */
1920		WARN_ON_ONCE(1);
1921		return -EINVAL;
1922	}
1923
1924	return ret;
1925}
1926
1927static bool iwl_mld_can_hw_csum(struct sk_buff *skb)
1928{
1929	u8 protocol = ip_hdr(skb)->protocol;
1930
1931	return protocol == IPPROTO_TCP || protocol == IPPROTO_UDP;
1932}
1933
1934static bool iwl_mld_mac80211_can_aggregate(struct ieee80211_hw *hw,
1935					   struct sk_buff *head,
1936					   struct sk_buff *skb)
1937{
1938	if (!IS_ENABLED(CONFIG_INET))
1939		return false;
1940
1941	/* For now don't aggregate IPv6 in AMSDU */
1942	if (skb->protocol != htons(ETH_P_IP))
1943		return false;
1944
1945	/* Allow aggregation only if both frames have the same HW csum offload
1946	 * capability, ensuring consistent HW or SW csum handling in A-MSDU.
1947	 */
1948	return iwl_mld_can_hw_csum(skb) == iwl_mld_can_hw_csum(head);
1949}
1950
1951static void iwl_mld_mac80211_sync_rx_queues(struct ieee80211_hw *hw)
1952{
1953	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
1954
1955	iwl_mld_sync_rx_queues(mld, IWL_MLD_RXQ_EMPTY, NULL, 0);
1956}
1957
1958static void iwl_mld_sta_rc_update(struct ieee80211_hw *hw,
1959				  struct ieee80211_vif *vif,
1960				  struct ieee80211_link_sta *link_sta,
1961				  u32 changed)
1962{
1963	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
1964
1965	if (changed & (IEEE80211_RC_BW_CHANGED |
1966		       IEEE80211_RC_SUPP_RATES_CHANGED |
1967		       IEEE80211_RC_NSS_CHANGED)) {
1968		struct ieee80211_bss_conf *link =
1969			link_conf_dereference_check(vif, link_sta->link_id);
1970
1971		if (WARN_ON(!link))
1972			return;
1973
1974		iwl_mld_config_tlc_link(mld, vif, link, link_sta);
1975	}
1976}
1977
1978#ifdef CONFIG_PM_SLEEP
1979static void iwl_mld_set_wakeup(struct ieee80211_hw *hw, bool enabled)
1980{
1981	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
1982
1983	device_set_wakeup_enable(mld->trans->dev, enabled);
1984}
1985
1986/* Returns 0 on success. 1 if failed to suspend with wowlan:
1987 * If the circumstances didn't satisfy the conditions for suspension
1988 * with wowlan, mac80211 would use the no_wowlan flow.
1989 * If an error had occurred we update the trans status and state here
1990 * and the result will be stopping the FW.
1991 */
1992static int
1993iwl_mld_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
1994{
1995	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
1996	int ret;
1997
1998	iwl_fw_runtime_suspend(&mld->fwrt);
1999
2000	ret = iwl_mld_wowlan_suspend(mld, wowlan);
2001	if (ret)
2002		return 1;
2003
2004	if (iwl_mld_no_wowlan_suspend(mld))
2005		return 1;
2006
2007	return 0;
2008}
2009
2010static int iwl_mld_resume(struct ieee80211_hw *hw)
2011{
2012	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
2013	int ret;
2014
2015	ret = iwl_mld_wowlan_resume(mld);
2016	if (ret)
2017		return ret;
2018
2019	iwl_fw_runtime_resume(&mld->fwrt);
2020
2021	iwl_mld_low_latency_restart(mld);
2022
2023	return 0;
2024}
2025#endif
2026
2027static int iwl_mld_alloc_ptk_pn(struct iwl_mld *mld,
2028				struct iwl_mld_sta *mld_sta,
2029				struct ieee80211_key_conf *key,
2030				struct iwl_mld_ptk_pn **ptk_pn)
2031{
2032	u8 num_rx_queues = mld->trans->info.num_rxqs;
2033	int keyidx = key->keyidx;
2034	struct ieee80211_key_seq seq;
2035
2036	if (WARN_ON(keyidx >= ARRAY_SIZE(mld_sta->ptk_pn)))
2037		return -EINVAL;
2038
2039	WARN_ON(rcu_access_pointer(mld_sta->ptk_pn[keyidx]));
2040	*ptk_pn = kzalloc(struct_size(*ptk_pn, q, num_rx_queues),
2041			  GFP_KERNEL);
2042	if (!*ptk_pn)
2043		return -ENOMEM;
2044
2045	for (u8 tid = 0; tid < IWL_MAX_TID_COUNT; tid++) {
2046		ieee80211_get_key_rx_seq(key, tid, &seq);
2047		for (u8 q = 0; q < num_rx_queues; q++)
2048			memcpy((*ptk_pn)->q[q].pn[tid], seq.ccmp.pn,
2049			       IEEE80211_CCMP_PN_LEN);
2050	}
2051
2052	rcu_assign_pointer(mld_sta->ptk_pn[keyidx], *ptk_pn);
2053
2054	return 0;
2055}
2056
2057static int iwl_mld_set_key_add(struct iwl_mld *mld,
2058			       struct ieee80211_vif *vif,
2059			       struct ieee80211_sta *sta,
2060			       struct ieee80211_key_conf *key)
2061{
2062	struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
2063	struct iwl_mld_sta *mld_sta =
2064		sta ? iwl_mld_sta_from_mac80211(sta) : NULL;
2065	struct iwl_mld_ptk_pn *ptk_pn = NULL;
2066	int keyidx = key->keyidx;
2067	int ret;
2068
2069	/* Will be set to 0 if added successfully */
2070	key->hw_key_idx = STA_KEY_IDX_INVALID;
2071
2072	switch (key->cipher) {
2073	case WLAN_CIPHER_SUITE_WEP40:
2074	case WLAN_CIPHER_SUITE_WEP104:
2075		IWL_DEBUG_MAC80211(mld, "Use SW encryption for WEP\n");
2076		return -EOPNOTSUPP;
2077	case WLAN_CIPHER_SUITE_TKIP:
2078		if (vif->type == NL80211_IFTYPE_STATION) {
2079			key->flags |= IEEE80211_KEY_FLAG_PUT_MIC_SPACE;
2080			break;
2081		}
2082		IWL_DEBUG_MAC80211(mld, "Use SW encryption for TKIP\n");
2083		return -EOPNOTSUPP;
2084	case WLAN_CIPHER_SUITE_CCMP:
2085	case WLAN_CIPHER_SUITE_GCMP:
2086	case WLAN_CIPHER_SUITE_GCMP_256:
2087	case WLAN_CIPHER_SUITE_AES_CMAC:
2088	case WLAN_CIPHER_SUITE_BIP_GMAC_128:
2089	case WLAN_CIPHER_SUITE_BIP_GMAC_256:
2090		break;
2091	default:
2092		return -EOPNOTSUPP;
2093	}
2094
2095	if (keyidx == 6 || keyidx == 7)
2096		iwl_mld_track_bigtk(mld, vif, key, true);
2097
2098	/* After exiting from RFKILL, hostapd configures GTK/ITGK before the
2099	 * AP is started, but those keys can't be sent to the FW before the
2100	 * MCAST/BCAST STAs are added to it (which happens upon AP start).
2101	 * Store it here to be sent later when the AP is started.
2102	 */
2103	if ((vif->type == NL80211_IFTYPE_ADHOC ||
2104	     vif->type == NL80211_IFTYPE_AP) && !sta &&
2105	     !mld_vif->ap_ibss_active)
2106		return iwl_mld_store_ap_early_key(mld, key, mld_vif);
2107
2108	if (!mld->fw_status.in_hw_restart && mld_sta &&
2109	    key->flags & IEEE80211_KEY_FLAG_PAIRWISE &&
2110	    (key->cipher == WLAN_CIPHER_SUITE_CCMP ||
2111	     key->cipher == WLAN_CIPHER_SUITE_GCMP ||
2112	     key->cipher == WLAN_CIPHER_SUITE_GCMP_256)) {
2113		ret = iwl_mld_alloc_ptk_pn(mld, mld_sta, key, &ptk_pn);
2114		if (ret)
2115			return ret;
2116	}
2117
2118	IWL_DEBUG_MAC80211(mld, "set hwcrypto key (sta:%pM, id:%d)\n",
2119			   sta ? sta->addr : NULL, keyidx);
2120
2121	ret = iwl_mld_add_key(mld, vif, sta, key);
2122	if (ret) {
2123		IWL_WARN(mld, "set key failed (%d)\n", ret);
2124		if (ptk_pn) {
2125			RCU_INIT_POINTER(mld_sta->ptk_pn[keyidx], NULL);
2126			kfree(ptk_pn);
2127		}
2128
2129		return -EOPNOTSUPP;
2130	}
2131
2132	return 0;
2133}
2134
2135static void iwl_mld_set_key_remove(struct iwl_mld *mld,
2136				   struct ieee80211_vif *vif,
2137				   struct ieee80211_sta *sta,
2138				   struct ieee80211_key_conf *key)
2139{
2140	struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
2141	struct iwl_mld_sta *mld_sta =
2142		sta ? iwl_mld_sta_from_mac80211(sta) : NULL;
2143	int keyidx = key->keyidx;
2144
2145	if (keyidx == 6 || keyidx == 7)
2146		iwl_mld_track_bigtk(mld, vif, key, false);
2147
2148	if (mld_sta && key->flags & IEEE80211_KEY_FLAG_PAIRWISE &&
2149	    (key->cipher == WLAN_CIPHER_SUITE_CCMP ||
2150	     key->cipher == WLAN_CIPHER_SUITE_GCMP ||
2151	     key->cipher == WLAN_CIPHER_SUITE_GCMP_256)) {
2152		struct iwl_mld_ptk_pn *ptk_pn;
2153
2154		if (WARN_ON(keyidx >= ARRAY_SIZE(mld_sta->ptk_pn)))
2155			return;
2156
2157		ptk_pn = wiphy_dereference(mld->wiphy,
2158					   mld_sta->ptk_pn[keyidx]);
2159		RCU_INIT_POINTER(mld_sta->ptk_pn[keyidx], NULL);
2160		if (!WARN_ON(!ptk_pn))
2161			kfree_rcu(ptk_pn, rcu_head);
2162	}
2163
2164	/* if this key was stored to be added later to the FW - free it here */
2165	if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
2166		iwl_mld_free_ap_early_key(mld, key, mld_vif);
2167
2168	/* We already removed it */
2169	if (key->hw_key_idx == STA_KEY_IDX_INVALID)
2170		return;
2171
2172	IWL_DEBUG_MAC80211(mld, "disable hwcrypto key\n");
2173
2174	iwl_mld_remove_key(mld, vif, sta, key);
2175}
2176
2177static int iwl_mld_mac80211_set_key(struct ieee80211_hw *hw,
2178				    enum set_key_cmd cmd,
2179				    struct ieee80211_vif *vif,
2180				    struct ieee80211_sta *sta,
2181				    struct ieee80211_key_conf *key)
2182{
2183	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
2184	int ret;
2185
2186	switch (cmd) {
2187	case SET_KEY:
2188		ret = iwl_mld_set_key_add(mld, vif, sta, key);
2189		if (ret)
2190			ret = -EOPNOTSUPP;
2191		break;
2192	case DISABLE_KEY:
2193		iwl_mld_set_key_remove(mld, vif, sta, key);
2194		ret = 0;
2195		break;
2196	default:
2197		ret = -EINVAL;
2198		break;
2199	}
2200
2201	return ret;
2202}
2203
2204static int
2205iwl_mld_pre_channel_switch(struct ieee80211_hw *hw,
2206			   struct ieee80211_vif *vif,
2207			   struct ieee80211_channel_switch *chsw)
2208{
2209	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
2210	struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
2211	struct iwl_mld_link *mld_link =
2212		iwl_mld_link_dereference_check(mld_vif, chsw->link_id);
2213	u8 primary;
2214	int selected;
2215
2216	lockdep_assert_wiphy(mld->wiphy);
2217
2218	if (WARN_ON(!mld_link))
2219		return -EINVAL;
2220
2221	IWL_DEBUG_MAC80211(mld, "pre CSA to freq %d\n",
2222			   chsw->chandef.center_freq1);
2223
2224	if (!iwl_mld_emlsr_active(vif))
2225		return 0;
2226
2227	primary = iwl_mld_get_primary_link(vif);
2228
2229	/* stay on the primary link unless it is undergoing a CSA with quiet */
2230	if (chsw->link_id == primary && chsw->block_tx)
2231		selected = iwl_mld_get_other_link(vif, primary);
2232	else
2233		selected = primary;
2234
2235	/* Remember to tell the firmware that this link can't tx
2236	 * Note that this logic seems to be unrelated to emlsr, but it
2237	 * really is needed only when emlsr is active. When we have a
2238	 * single link, the firmware will handle all this on its own.
2239	 * In multi-link scenarios, we can learn about the CSA from
2240	 * another link and this logic is too complex for the firmware
2241	 * to track.
2242	 * Since we want to de-activate the link that got a CSA with mode=1,
2243	 * we need to tell the firmware not to send any frame on that link
2244	 * as the firmware may not be aware that link is under a CSA
2245	 * with mode=1 (no Tx allowed).
2246	 */
2247	mld_link->silent_deactivation = chsw->block_tx;
2248	iwl_mld_exit_emlsr(mld, vif, IWL_MLD_EMLSR_EXIT_CSA, selected);
2249
2250	return 0;
2251}
2252
2253static void
2254iwl_mld_channel_switch(struct ieee80211_hw *hw,
2255		       struct ieee80211_vif *vif,
2256		       struct ieee80211_channel_switch *chsw)
2257{
2258	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
2259
2260	/* By implementing this operation, we prevent mac80211 from
2261	 * starting its own channel switch timer, so that we can call
2262	 * ieee80211_chswitch_done() ourselves at the right time
2263	 * (Upon receiving the channel_switch_start notification from the fw)
2264	 */
2265	IWL_DEBUG_MAC80211(mld,
2266			   "dummy channel switch op\n");
2267}
2268
2269static int
2270iwl_mld_post_channel_switch(struct ieee80211_hw *hw,
2271			    struct ieee80211_vif *vif,
2272			    struct ieee80211_bss_conf *link_conf)
2273{
2274	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
2275	struct iwl_mld_link *mld_link = iwl_mld_link_from_mac80211(link_conf);
2276
2277	lockdep_assert_wiphy(mld->wiphy);
2278
2279	WARN_ON(mld_link->silent_deactivation);
2280
2281	return 0;
2282}
2283
2284static void
2285iwl_mld_abort_channel_switch(struct ieee80211_hw *hw,
2286			     struct ieee80211_vif *vif,
2287			     struct ieee80211_bss_conf *link_conf)
2288{
2289	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
2290	struct iwl_mld_link *mld_link = iwl_mld_link_from_mac80211(link_conf);
2291
2292	IWL_DEBUG_MAC80211(mld,
2293			   "abort channel switch op\n");
2294	mld_link->silent_deactivation = false;
2295}
2296
2297static int
2298iwl_mld_switch_vif_chanctx_swap(struct ieee80211_hw *hw,
2299				struct ieee80211_vif_chanctx_switch *vifs)
2300{
2301	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
2302	int ret;
2303
2304	iwl_mld_unassign_vif_chanctx(hw, vifs[0].vif, vifs[0].link_conf,
2305				     vifs[0].old_ctx);
2306	iwl_mld_remove_chanctx(hw, vifs[0].old_ctx);
2307
2308	ret = iwl_mld_add_chanctx(hw, vifs[0].new_ctx);
2309	if (ret) {
2310		IWL_ERR(mld, "failed to add new_ctx during channel switch\n");
2311		goto out_reassign;
2312	}
2313
2314	ret = iwl_mld_assign_vif_chanctx(hw, vifs[0].vif, vifs[0].link_conf,
2315					 vifs[0].new_ctx);
2316	if (ret) {
2317		IWL_ERR(mld,
2318			"failed to assign new_ctx during channel switch\n");
2319		goto out_remove;
2320	}
2321
2322	return 0;
2323
2324 out_remove:
2325	iwl_mld_remove_chanctx(hw, vifs[0].new_ctx);
2326 out_reassign:
2327	if (iwl_mld_add_chanctx(hw, vifs[0].old_ctx)) {
2328		IWL_ERR(mld, "failed to add old_ctx after failure\n");
2329		return ret;
2330	}
2331
2332	if (iwl_mld_assign_vif_chanctx(hw, vifs[0].vif, vifs[0].link_conf,
2333				       vifs[0].old_ctx))
2334		IWL_ERR(mld, "failed to reassign old_ctx after failure\n");
2335
2336	return ret;
2337}
2338
2339static int
2340iwl_mld_switch_vif_chanctx_reassign(struct ieee80211_hw *hw,
2341				    struct ieee80211_vif_chanctx_switch *vifs)
2342{
2343	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
2344	int ret;
2345
2346	iwl_mld_unassign_vif_chanctx(hw, vifs[0].vif, vifs[0].link_conf,
2347				     vifs[0].old_ctx);
2348	ret = iwl_mld_assign_vif_chanctx(hw, vifs[0].vif, vifs[0].link_conf,
2349					 vifs[0].new_ctx);
2350	if (ret) {
2351		IWL_ERR(mld,
2352			"failed to assign new_ctx during channel switch\n");
2353		goto out_reassign;
2354	}
2355
2356	return 0;
2357
2358out_reassign:
2359	if (iwl_mld_assign_vif_chanctx(hw, vifs[0].vif, vifs[0].link_conf,
2360				       vifs[0].old_ctx))
2361		IWL_ERR(mld, "failed to reassign old_ctx after failure\n");
2362
2363	return ret;
2364}
2365
2366static int
2367iwl_mld_switch_vif_chanctx(struct ieee80211_hw *hw,
2368			   struct ieee80211_vif_chanctx_switch *vifs,
2369			   int n_vifs,
2370			   enum ieee80211_chanctx_switch_mode mode)
2371{
2372	int ret;
2373
2374	/* we only support a single-vif right now */
2375	if (n_vifs > 1)
2376		return -EOPNOTSUPP;
2377
2378	switch (mode) {
2379	case CHANCTX_SWMODE_SWAP_CONTEXTS:
2380		ret = iwl_mld_switch_vif_chanctx_swap(hw, vifs);
2381		break;
2382	case CHANCTX_SWMODE_REASSIGN_VIF:
2383		ret = iwl_mld_switch_vif_chanctx_reassign(hw, vifs);
2384		break;
2385	default:
2386		ret = -EOPNOTSUPP;
2387		break;
2388	}
2389
2390	return ret;
2391}
2392
2393static void iwl_mld_sta_pre_rcu_remove(struct ieee80211_hw *hw,
2394				       struct ieee80211_vif *vif,
2395				       struct ieee80211_sta *sta)
2396{
2397	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
2398	struct iwl_mld_sta *mld_sta = iwl_mld_sta_from_mac80211(sta);
2399	struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
2400	struct iwl_mld_link_sta *mld_link_sta;
2401	u8 link_id;
2402
2403	lockdep_assert_wiphy(mld->wiphy);
2404
2405	/* This is called before mac80211 does RCU synchronisation,
2406	 * so here we already invalidate our internal RCU-protected
2407	 * station pointer. The rest of the code will thus no longer
2408	 * be able to find the station this way, and we don't rely
2409	 * on further RCU synchronisation after the sta_state()
2410	 * callback deleted the station.
2411	 */
2412	for_each_mld_link_sta(mld_sta, mld_link_sta, link_id)
2413		RCU_INIT_POINTER(mld->fw_id_to_link_sta[mld_link_sta->fw_id],
2414				 NULL);
2415
2416	if (sta == mld_vif->ap_sta)
2417		mld_vif->ap_sta = NULL;
2418}
2419
2420static void
2421iwl_mld_mac80211_mgd_protect_tdls_discover(struct ieee80211_hw *hw,
2422					   struct ieee80211_vif *vif,
2423					   unsigned int link_id)
2424{
2425	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
2426	struct ieee80211_bss_conf *link_conf;
2427	u32 duration;
2428	int ret;
2429
2430	link_conf = wiphy_dereference(hw->wiphy, vif->link_conf[link_id]);
2431	if (WARN_ON_ONCE(!link_conf))
2432		return;
2433
2434	/* Protect the session to hear the TDLS setup response on the channel */
2435
2436	duration = 2 * link_conf->dtim_period * link_conf->beacon_int;
2437
2438	ret = iwl_mld_start_session_protection(mld, vif, duration, duration,
2439					       link_id, HZ / 5);
2440	if (ret)
2441		IWL_ERR(mld,
2442			"Failed to start session protection for TDLS: %d\n",
2443			ret);
2444}
2445
2446static bool iwl_mld_can_activate_links(struct ieee80211_hw *hw,
2447				       struct ieee80211_vif *vif,
2448				       u16 desired_links)
2449{
2450	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
2451	int n_links = hweight16(desired_links);
2452
2453	/* Check if HW supports the wanted number of links */
2454	return n_links <= iwl_mld_max_active_links(mld, vif);
2455}
2456
2457static int
2458iwl_mld_change_vif_links(struct ieee80211_hw *hw,
2459			 struct ieee80211_vif *vif,
2460			 u16 old_links, u16 new_links,
2461			 struct ieee80211_bss_conf *old[IEEE80211_MLD_MAX_NUM_LINKS])
2462{
2463	struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
2464	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
2465	struct ieee80211_bss_conf *link_conf;
2466	u16 removed = old_links & ~new_links;
2467	u16 added = new_links & ~old_links;
2468	int err;
2469
2470	lockdep_assert_wiphy(mld->wiphy);
2471
2472	/*
2473	 * No bits designate non-MLO mode. We can handle MLO exit/enter by
2474	 * simply mapping that to link ID zero internally.
2475	 * Note that mac80211 does such a non-MLO to MLO switch during restart
2476	 * if it was in MLO before. In that case, we do not have a link to
2477	 * remove.
2478	 */
2479	if (old_links == 0 && !mld->fw_status.in_hw_restart)
2480		removed |= BIT(0);
2481
2482	if (new_links == 0)
2483		added |= BIT(0);
2484
2485	for (int i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
2486		if (removed & BIT(i) && !WARN_ON(!old[i]))
2487			iwl_mld_remove_link(mld, old[i]);
2488	}
2489
2490	for (int i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
2491		if (added & BIT(i)) {
2492			link_conf = link_conf_dereference_protected(vif, i);
2493			if (!link_conf) {
2494				err = -EINVAL;
2495				goto remove_added_links;
2496			}
2497
2498			err = iwl_mld_add_link(mld, link_conf);
2499			if (err)
2500				goto remove_added_links;
2501		}
2502	}
2503
2504	/*
2505	 * Ensure we always have a valid primary_link. When using multiple
2506	 * links the proper value is set in assign_vif_chanctx.
2507	 */
2508	mld_vif->emlsr.primary = new_links ? __ffs(new_links) : 0;
2509
2510	/*
2511	 * Special MLO restart case. We did not have a link when the interface
2512	 * was added, so do the power configuration now.
2513	 */
2514	if (old_links == 0 && mld->fw_status.in_hw_restart)
2515		iwl_mld_update_mac_power(mld, vif, false);
2516
2517	return 0;
2518
2519remove_added_links:
2520	for (int i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
2521		if (!(added & BIT(i)))
2522			continue;
2523
2524		link_conf = link_conf_dereference_protected(vif, i);
2525		if (!link_conf || !iwl_mld_link_from_mac80211(link_conf))
2526			continue;
2527
2528		iwl_mld_remove_link(mld, link_conf);
2529	}
2530
2531	if (WARN_ON(!iwl_mld_error_before_recovery(mld)))
2532		return err;
2533
2534	/* reconfig will fix us anyway */
2535	return 0;
2536}
2537
2538static int iwl_mld_change_sta_links(struct ieee80211_hw *hw,
2539				    struct ieee80211_vif *vif,
2540				    struct ieee80211_sta *sta,
2541				    u16 old_links, u16 new_links)
2542{
2543	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
2544
2545	return iwl_mld_update_link_stas(mld, vif, sta, old_links, new_links);
2546}
2547
2548static int iwl_mld_mac80211_join_ibss(struct ieee80211_hw *hw,
2549				      struct ieee80211_vif *vif)
2550{
2551	return iwl_mld_start_ap_ibss(hw, vif, &vif->bss_conf);
2552}
2553
2554static void iwl_mld_mac80211_leave_ibss(struct ieee80211_hw *hw,
2555					struct ieee80211_vif *vif)
2556{
2557	return iwl_mld_stop_ap_ibss(hw, vif, &vif->bss_conf);
2558}
2559
2560static int iwl_mld_mac80211_tx_last_beacon(struct ieee80211_hw *hw)
2561{
2562	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
2563
2564	return mld->ibss_manager;
2565}
2566
2567static void iwl_mld_prep_add_interface(struct ieee80211_hw *hw,
2568				       enum nl80211_iftype type)
2569{
2570	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
2571
2572	IWL_DEBUG_MAC80211(mld, "prep_add_interface: type=%u\n", type);
2573
2574	if (!(type == NL80211_IFTYPE_AP ||
2575	      type == NL80211_IFTYPE_P2P_GO ||
2576	      type == NL80211_IFTYPE_P2P_CLIENT))
2577		return;
2578
2579	iwl_mld_emlsr_block_tmp_non_bss(mld);
2580}
2581
2582static int iwl_mld_set_hw_timestamp(struct ieee80211_hw *hw,
2583				    struct ieee80211_vif *vif,
2584				    struct cfg80211_set_hw_timestamp *hwts)
2585{
2586	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
2587	u32 protocols = 0;
2588
2589	/* HW timestamping is only supported for a specific station */
2590	if (!hwts->macaddr)
2591		return -EOPNOTSUPP;
2592
2593	if (hwts->enable)
2594		protocols =
2595			IWL_TIME_SYNC_PROTOCOL_TM | IWL_TIME_SYNC_PROTOCOL_FTM;
2596
2597	return iwl_mld_time_sync_config(mld, hwts->macaddr, protocols);
2598}
2599
2600static int iwl_mld_start_pmsr(struct ieee80211_hw *hw,
2601			      struct ieee80211_vif *vif,
2602			      struct cfg80211_pmsr_request *request)
2603{
2604	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
2605
2606	return iwl_mld_ftm_start(mld, vif, request);
2607}
2608
2609static enum ieee80211_neg_ttlm_res
2610iwl_mld_can_neg_ttlm(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
2611		     struct ieee80211_neg_ttlm *neg_ttlm)
2612{
2613	u16 map;
2614
2615	/* Verify all TIDs are mapped to the same links set */
2616	map = neg_ttlm->downlink[0];
2617	for (int i = 0; i < IEEE80211_TTLM_NUM_TIDS; i++) {
2618		if (neg_ttlm->downlink[i] != neg_ttlm->uplink[i] ||
2619		    neg_ttlm->uplink[i] != map)
2620			return NEG_TTLM_RES_REJECT;
2621	}
2622
2623	return NEG_TTLM_RES_ACCEPT;
2624}
2625
2626static int iwl_mld_get_antenna(struct ieee80211_hw *hw, int radio_idx,
2627			       u32 *tx_ant, u32 *rx_ant)
2628{
2629	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
2630
2631	*tx_ant = iwl_mld_get_valid_tx_ant(mld);
2632	*rx_ant = iwl_mld_get_valid_rx_ant(mld);
2633
2634	return 0;
2635}
2636
2637static int iwl_mld_set_antenna(struct ieee80211_hw *hw, int radio_idx,
2638			       u32 tx_ant, u32 rx_ant)
2639{
2640	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
2641
2642	if (WARN_ON(!mld->nvm_data))
2643		return -EBUSY;
2644
2645	/* mac80211 ensures the device is not started,
2646	 * so the firmware cannot be running
2647	 */
2648
2649	mld->set_tx_ant = tx_ant;
2650	mld->set_rx_ant = rx_ant;
2651
2652	iwl_reinit_cab(mld->trans, mld->nvm_data, tx_ant, rx_ant, mld->fw);
2653
2654	return 0;
2655}
2656
2657const struct ieee80211_ops iwl_mld_hw_ops = {
2658	.tx = iwl_mld_mac80211_tx,
2659	.start = iwl_mld_mac80211_start,
2660	.stop = iwl_mld_mac80211_stop,
2661	.config = iwl_mld_mac80211_config,
2662	.get_antenna = iwl_mld_get_antenna,
2663	.set_antenna = iwl_mld_set_antenna,
2664	.add_interface = iwl_mld_mac80211_add_interface,
2665	.remove_interface = iwl_mld_mac80211_remove_interface,
2666	.conf_tx = iwl_mld_mac80211_conf_tx,
2667	.prepare_multicast = iwl_mld_mac80211_prepare_multicast,
2668	.configure_filter = iwl_mld_mac80211_configure_filter,
2669	.reconfig_complete = iwl_mld_mac80211_reconfig_complete,
2670	.wake_tx_queue = iwl_mld_mac80211_wake_tx_queue,
2671	.add_chanctx = iwl_mld_add_chanctx,
2672	.remove_chanctx = iwl_mld_remove_chanctx,
2673	.change_chanctx = iwl_mld_change_chanctx,
2674	.assign_vif_chanctx = iwl_mld_assign_vif_chanctx,
2675	.unassign_vif_chanctx = iwl_mld_unassign_vif_chanctx,
2676	.set_rts_threshold = iwl_mld_mac80211_set_rts_threshold,
2677	.link_info_changed = iwl_mld_mac80211_link_info_changed,
2678	.vif_cfg_changed = iwl_mld_mac80211_vif_cfg_changed,
2679	.set_key = iwl_mld_mac80211_set_key,
2680	.hw_scan = iwl_mld_mac80211_hw_scan,
2681	.cancel_hw_scan = iwl_mld_mac80211_cancel_hw_scan,
2682	.sched_scan_start = iwl_mld_mac80211_sched_scan_start,
2683	.sched_scan_stop = iwl_mld_mac80211_sched_scan_stop,
2684	.mgd_prepare_tx = iwl_mld_mac80211_mgd_prepare_tx,
2685	.mgd_complete_tx = iwl_mld_mac_mgd_complete_tx,
2686	.sta_state = iwl_mld_mac80211_sta_state,
2687	.sta_statistics = iwl_mld_mac80211_sta_statistics,
2688	.get_survey = iwl_mld_mac80211_get_survey,
2689	.flush = iwl_mld_mac80211_flush,
2690	.flush_sta = iwl_mld_mac80211_flush_sta,
2691	.ampdu_action = iwl_mld_mac80211_ampdu_action,
2692	.can_aggregate_in_amsdu = iwl_mld_mac80211_can_aggregate,
2693	.sync_rx_queues = iwl_mld_mac80211_sync_rx_queues,
2694	.link_sta_rc_update = iwl_mld_sta_rc_update,
2695	.start_ap = iwl_mld_start_ap_ibss,
2696	.stop_ap = iwl_mld_stop_ap_ibss,
2697	.pre_channel_switch = iwl_mld_pre_channel_switch,
2698	.channel_switch = iwl_mld_channel_switch,
2699	.post_channel_switch = iwl_mld_post_channel_switch,
2700	.abort_channel_switch = iwl_mld_abort_channel_switch,
2701	.switch_vif_chanctx = iwl_mld_switch_vif_chanctx,
2702	.sta_pre_rcu_remove = iwl_mld_sta_pre_rcu_remove,
2703	.remain_on_channel = iwl_mld_start_roc,
2704	.cancel_remain_on_channel = iwl_mld_cancel_roc,
2705	.can_activate_links = iwl_mld_can_activate_links,
2706	.change_vif_links = iwl_mld_change_vif_links,
2707	.change_sta_links = iwl_mld_change_sta_links,
2708#ifdef CONFIG_PM_SLEEP
2709	.suspend = iwl_mld_suspend,
2710	.resume = iwl_mld_resume,
2711	.set_wakeup = iwl_mld_set_wakeup,
2712	.set_rekey_data = iwl_mld_set_rekey_data,
2713#if IS_ENABLED(CONFIG_IPV6)
2714	.ipv6_addr_change = iwl_mld_ipv6_addr_change,
2715#endif /* IS_ENABLED(CONFIG_IPV6) */
2716#endif /* CONFIG_PM_SLEEP */
2717#ifdef CONFIG_IWLWIFI_DEBUGFS
2718	.vif_add_debugfs = iwl_mld_add_vif_debugfs,
2719	.link_add_debugfs = iwl_mld_add_link_debugfs,
2720	.link_sta_add_debugfs = iwl_mld_add_link_sta_debugfs,
2721#endif
2722	.mgd_protect_tdls_discover = iwl_mld_mac80211_mgd_protect_tdls_discover,
2723	.join_ibss = iwl_mld_mac80211_join_ibss,
2724	.leave_ibss = iwl_mld_mac80211_leave_ibss,
2725	.tx_last_beacon = iwl_mld_mac80211_tx_last_beacon,
2726	.prep_add_interface = iwl_mld_prep_add_interface,
2727	.set_hw_timestamp = iwl_mld_set_hw_timestamp,
2728	.start_pmsr = iwl_mld_start_pmsr,
2729	.can_neg_ttlm = iwl_mld_can_neg_ttlm,
2730};
~/ Read-only file preview.