File Index
Files and directories
Sign in
FILE

mac-ctxt.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c C
   1// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
   2/*
   3 * Copyright (C) 2012-2014, 2018-2025 Intel Corporation
   4 * Copyright (C) 2013-2014 Intel Mobile Communications GmbH
   5 * Copyright (C) 2015-2017 Intel Deutschland GmbH
   6 */
   7#include <linux/etherdevice.h>
   8#include <linux/crc32.h>
   9#include <net/mac80211.h>
  10#include "iwl-io.h"
  11#include "iwl-prph.h"
  12#include "fw-api.h"
  13#include "mvm.h"
  14#include "time-event.h"
  15#include "iwl-utils.h"
  16
  17const u8 iwl_mvm_ac_to_tx_fifo[] = {
  18	IWL_MVM_TX_FIFO_VO,
  19	IWL_MVM_TX_FIFO_VI,
  20	IWL_MVM_TX_FIFO_BE,
  21	IWL_MVM_TX_FIFO_BK,
  22};
  23
  24const u8 iwl_mvm_ac_to_gen2_tx_fifo[] = {
  25	IWL_GEN2_EDCA_TX_FIFO_VO,
  26	IWL_GEN2_EDCA_TX_FIFO_VI,
  27	IWL_GEN2_EDCA_TX_FIFO_BE,
  28	IWL_GEN2_EDCA_TX_FIFO_BK,
  29	IWL_GEN2_TRIG_TX_FIFO_VO,
  30	IWL_GEN2_TRIG_TX_FIFO_VI,
  31	IWL_GEN2_TRIG_TX_FIFO_BE,
  32	IWL_GEN2_TRIG_TX_FIFO_BK,
  33};
  34
  35const u8 iwl_mvm_ac_to_bz_tx_fifo[] = {
  36	IWL_BZ_EDCA_TX_FIFO_VO,
  37	IWL_BZ_EDCA_TX_FIFO_VI,
  38	IWL_BZ_EDCA_TX_FIFO_BE,
  39	IWL_BZ_EDCA_TX_FIFO_BK,
  40	IWL_BZ_TRIG_TX_FIFO_VO,
  41	IWL_BZ_TRIG_TX_FIFO_VI,
  42	IWL_BZ_TRIG_TX_FIFO_BE,
  43	IWL_BZ_TRIG_TX_FIFO_BK,
  44};
  45
  46struct iwl_mvm_mac_iface_iterator_data {
  47	struct iwl_mvm *mvm;
  48	struct ieee80211_vif *vif;
  49	unsigned long available_mac_ids[BITS_TO_LONGS(NUM_MAC_INDEX_DRIVER)];
  50	unsigned long available_tsf_ids[BITS_TO_LONGS(NUM_TSF_IDS)];
  51	enum iwl_tsf_id preferred_tsf;
  52	bool found_vif;
  53};
  54
  55static void iwl_mvm_mac_tsf_id_iter(void *_data, u8 *mac,
  56				    struct ieee80211_vif *vif)
  57{
  58	struct iwl_mvm_mac_iface_iterator_data *data = _data;
  59	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
  60	u16 min_bi;
  61
  62	/* Skip the interface for which we are trying to assign a tsf_id  */
  63	if (vif == data->vif)
  64		return;
  65
  66	/*
  67	 * The TSF is a hardware/firmware resource, there are 4 and
  68	 * the driver should assign and free them as needed. However,
  69	 * there are cases where 2 MACs should share the same TSF ID
  70	 * for the purpose of clock sync, an optimization to avoid
  71	 * clock drift causing overlapping TBTTs/DTIMs for a GO and
  72	 * client in the system.
  73	 *
  74	 * The firmware will decide according to the MAC type which
  75	 * will be the leader and follower. Clients that need to sync
  76	 * with a remote station will be the leader, and an AP or GO
  77	 * will be the follower.
  78	 *
  79	 * Depending on the new interface type it can be following
  80	 * or become the leader of an existing interface.
  81	 */
  82	switch (data->vif->type) {
  83	case NL80211_IFTYPE_STATION:
  84		/*
  85		 * The new interface is a client, so if the one we're iterating
  86		 * is an AP, and the beacon interval of the AP is a multiple or
  87		 * divisor of the beacon interval of the client, the same TSF
  88		 * should be used to avoid drift between the new client and
  89		 * existing AP. The existing AP will get drift updates from the
  90		 * new client context in this case.
  91		 */
  92		if (vif->type != NL80211_IFTYPE_AP ||
  93		    data->preferred_tsf != NUM_TSF_IDS ||
  94		    !test_bit(mvmvif->tsf_id, data->available_tsf_ids))
  95			break;
  96
  97		min_bi = min(data->vif->bss_conf.beacon_int,
  98			     vif->bss_conf.beacon_int);
  99
 100		if (!min_bi)
 101			break;
 102
 103		if ((data->vif->bss_conf.beacon_int -
 104		     vif->bss_conf.beacon_int) % min_bi == 0) {
 105			data->preferred_tsf = mvmvif->tsf_id;
 106			return;
 107		}
 108		break;
 109
 110	case NL80211_IFTYPE_AP:
 111		/*
 112		 * The new interface is AP/GO, so if its beacon interval is a
 113		 * multiple or a divisor of the beacon interval of an existing
 114		 * interface, it should get drift updates from an existing
 115		 * client or use the same TSF as an existing GO. There's no
 116		 * drift between TSFs internally but if they used different
 117		 * TSFs then a new client MAC could update one of them and
 118		 * cause drift that way.
 119		 */
 120		if ((vif->type != NL80211_IFTYPE_AP &&
 121		     vif->type != NL80211_IFTYPE_STATION) ||
 122		    data->preferred_tsf != NUM_TSF_IDS ||
 123		    !test_bit(mvmvif->tsf_id, data->available_tsf_ids))
 124			break;
 125
 126		min_bi = min(data->vif->bss_conf.beacon_int,
 127			     vif->bss_conf.beacon_int);
 128
 129		if (!min_bi)
 130			break;
 131
 132		if ((data->vif->bss_conf.beacon_int -
 133		     vif->bss_conf.beacon_int) % min_bi == 0) {
 134			data->preferred_tsf = mvmvif->tsf_id;
 135			return;
 136		}
 137		break;
 138	default:
 139		/*
 140		 * For all other interface types there's no need to
 141		 * take drift into account. Either they're exclusive
 142		 * like IBSS and monitor, or we don't care much about
 143		 * their TSF (like P2P Device), but we won't be able
 144		 * to share the TSF resource.
 145		 */
 146		break;
 147	}
 148
 149	/*
 150	 * Unless we exited above, we can't share the TSF resource
 151	 * that the virtual interface we're iterating over is using
 152	 * with the new one, so clear the available bit and if this
 153	 * was the preferred one, reset that as well.
 154	 */
 155	__clear_bit(mvmvif->tsf_id, data->available_tsf_ids);
 156
 157	if (data->preferred_tsf == mvmvif->tsf_id)
 158		data->preferred_tsf = NUM_TSF_IDS;
 159}
 160
 161static void iwl_mvm_mac_iface_iterator(void *_data, u8 *mac,
 162				       struct ieee80211_vif *vif)
 163{
 164	struct iwl_mvm_mac_iface_iterator_data *data = _data;
 165	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 166
 167	/* Iterator may already find the interface being added -- skip it */
 168	if (vif == data->vif) {
 169		data->found_vif = true;
 170		return;
 171	}
 172
 173	/* Mark MAC IDs as used by clearing the available bit, and
 174	 * (below) mark TSFs as used if their existing use is not
 175	 * compatible with the new interface type.
 176	 * No locking or atomic bit operations are needed since the
 177	 * data is on the stack of the caller function.
 178	 */
 179	__clear_bit(mvmvif->id, data->available_mac_ids);
 180
 181	/* find a suitable tsf_id */
 182	iwl_mvm_mac_tsf_id_iter(_data, mac, vif);
 183}
 184
 185void iwl_mvm_mac_ctxt_recalc_tsf_id(struct iwl_mvm *mvm,
 186				    struct ieee80211_vif *vif)
 187{
 188	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 189	struct iwl_mvm_mac_iface_iterator_data data = {
 190		.mvm = mvm,
 191		.vif = vif,
 192		.available_tsf_ids = { (1 << NUM_TSF_IDS) - 1 },
 193		/* no preference yet */
 194		.preferred_tsf = NUM_TSF_IDS,
 195	};
 196
 197	ieee80211_iterate_active_interfaces_atomic(
 198		mvm->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
 199		iwl_mvm_mac_tsf_id_iter, &data);
 200
 201	if (data.preferred_tsf != NUM_TSF_IDS)
 202		mvmvif->tsf_id = data.preferred_tsf;
 203	else if (!test_bit(mvmvif->tsf_id, data.available_tsf_ids))
 204		mvmvif->tsf_id = find_first_bit(data.available_tsf_ids,
 205						NUM_TSF_IDS);
 206}
 207
 208int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
 209{
 210	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 211	struct iwl_mvm_mac_iface_iterator_data data = {
 212		.mvm = mvm,
 213		.vif = vif,
 214		.available_mac_ids = { (1 << NUM_MAC_INDEX_DRIVER) - 1 },
 215		.available_tsf_ids = { (1 << NUM_TSF_IDS) - 1 },
 216		/* no preference yet */
 217		.preferred_tsf = NUM_TSF_IDS,
 218		.found_vif = false,
 219	};
 220	int ret;
 221
 222	lockdep_assert_held(&mvm->mutex);
 223
 224	/*
 225	 * Allocate a MAC ID and a TSF for this MAC, along with the queues
 226	 * and other resources.
 227	 */
 228
 229	/*
 230	 * Before the iterator, we start with all MAC IDs and TSFs available.
 231	 *
 232	 * During iteration, all MAC IDs are cleared that are in use by other
 233	 * virtual interfaces, and all TSF IDs are cleared that can't be used
 234	 * by this new virtual interface because they're used by an interface
 235	 * that can't share it with the new one.
 236	 * At the same time, we check if there's a preferred TSF in the case
 237	 * that we should share it with another interface.
 238	 */
 239
 240	/* MAC ID 0 should be used only for the managed/IBSS vif with non-MLO
 241	 * FW API
 242	 */
 243	if (!mvm->mld_api_is_used) {
 244		switch (vif->type) {
 245		case NL80211_IFTYPE_ADHOC:
 246			break;
 247		case NL80211_IFTYPE_STATION:
 248			if (!vif->p2p)
 249				break;
 250			fallthrough;
 251		default:
 252			__clear_bit(0, data.available_mac_ids);
 253		}
 254	}
 255
 256	ieee80211_iterate_active_interfaces_atomic(
 257		mvm->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
 258		iwl_mvm_mac_iface_iterator, &data);
 259
 260	/*
 261	 * In the case we're getting here during resume, it's similar to
 262	 * firmware restart, and with RESUME_ALL the iterator will find
 263	 * the vif being added already.
 264	 * We don't want to reassign any IDs in either case since doing
 265	 * so would probably assign different IDs (as interfaces aren't
 266	 * necessarily added in the same order), but the old IDs were
 267	 * preserved anyway, so skip ID assignment for both resume and
 268	 * recovery.
 269	 */
 270	if (data.found_vif)
 271		return 0;
 272
 273	/* Therefore, in recovery, we can't get here */
 274	if (WARN_ON_ONCE(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)))
 275		return -EBUSY;
 276
 277	mvmvif->id = find_first_bit(data.available_mac_ids,
 278				    NUM_MAC_INDEX_DRIVER);
 279	if (mvmvif->id == NUM_MAC_INDEX_DRIVER) {
 280		IWL_ERR(mvm, "Failed to init MAC context - no free ID!\n");
 281		ret = -EIO;
 282		goto exit_fail;
 283	}
 284
 285	if (data.preferred_tsf != NUM_TSF_IDS)
 286		mvmvif->tsf_id = data.preferred_tsf;
 287	else
 288		mvmvif->tsf_id = find_first_bit(data.available_tsf_ids,
 289						NUM_TSF_IDS);
 290	if (mvmvif->tsf_id == NUM_TSF_IDS) {
 291		IWL_ERR(mvm, "Failed to init MAC context - no free TSF!\n");
 292		ret = -EIO;
 293		goto exit_fail;
 294	}
 295
 296	mvmvif->color = 0;
 297
 298	INIT_LIST_HEAD(&mvmvif->time_event_data.list);
 299	mvmvif->time_event_data.id = TE_MAX;
 300	mvmvif->roc_activity = ROC_NUM_ACTIVITIES;
 301
 302	iwl_mvm_init_link(&mvmvif->deflink);
 303
 304	/* No need to allocate data queues to P2P Device MAC */
 305	if (vif->type == NL80211_IFTYPE_P2P_DEVICE)
 306		return 0;
 307
 308	/* Allocate the CAB queue for softAP and GO interfaces */
 309	if (vif->type == NL80211_IFTYPE_AP ||
 310	    vif->type == NL80211_IFTYPE_ADHOC) {
 311		/*
 312		 * For TVQM this will be overwritten later with the FW assigned
 313		 * queue value (when queue is enabled).
 314		 */
 315		mvmvif->deflink.cab_queue = IWL_MVM_DQA_GCAST_QUEUE;
 316	}
 317
 318	return 0;
 319
 320exit_fail:
 321	memset(mvmvif, 0, sizeof(struct iwl_mvm_vif));
 322	return ret;
 323}
 324
 325static void iwl_mvm_ack_rates(struct iwl_mvm *mvm,
 326			      struct ieee80211_vif *vif,
 327			      enum nl80211_band band,
 328			      u8 *cck_rates, u8 *ofdm_rates)
 329{
 330	struct ieee80211_supported_band *sband;
 331	unsigned long basic = vif->bss_conf.basic_rates;
 332	int lowest_present_ofdm = 100;
 333	int lowest_present_cck = 100;
 334	u8 cck = 0;
 335	u8 ofdm = 0;
 336	int i;
 337
 338	sband = mvm->hw->wiphy->bands[band];
 339
 340	for_each_set_bit(i, &basic, BITS_PER_LONG) {
 341		int hw = sband->bitrates[i].hw_value;
 342		if (hw >= IWL_FIRST_OFDM_RATE) {
 343			ofdm |= BIT(hw - IWL_FIRST_OFDM_RATE);
 344			if (lowest_present_ofdm > hw)
 345				lowest_present_ofdm = hw;
 346		} else {
 347			BUILD_BUG_ON(IWL_FIRST_CCK_RATE != 0);
 348
 349			cck |= BIT(hw);
 350			if (lowest_present_cck > hw)
 351				lowest_present_cck = hw;
 352		}
 353	}
 354
 355	/*
 356	 * Now we've got the basic rates as bitmaps in the ofdm and cck
 357	 * variables. This isn't sufficient though, as there might not
 358	 * be all the right rates in the bitmap. E.g. if the only basic
 359	 * rates are 5.5 Mbps and 11 Mbps, we still need to add 1 Mbps
 360	 * and 6 Mbps because the 802.11-2007 standard says in 9.6:
 361	 *
 362	 *    [...] a STA responding to a received frame shall transmit
 363	 *    its Control Response frame [...] at the highest rate in the
 364	 *    BSSBasicRateSet parameter that is less than or equal to the
 365	 *    rate of the immediately previous frame in the frame exchange
 366	 *    sequence ([...]) and that is of the same modulation class
 367	 *    ([...]) as the received frame. If no rate contained in the
 368	 *    BSSBasicRateSet parameter meets these conditions, then the
 369	 *    control frame sent in response to a received frame shall be
 370	 *    transmitted at the highest mandatory rate of the PHY that is
 371	 *    less than or equal to the rate of the received frame, and
 372	 *    that is of the same modulation class as the received frame.
 373	 *
 374	 * As a consequence, we need to add all mandatory rates that are
 375	 * lower than all of the basic rates to these bitmaps.
 376	 */
 377
 378	if (IWL_RATE_24M_INDEX < lowest_present_ofdm)
 379		ofdm |= IWL_RATE_BIT_MSK(24) >> IWL_FIRST_OFDM_RATE;
 380	if (IWL_RATE_12M_INDEX < lowest_present_ofdm)
 381		ofdm |= IWL_RATE_BIT_MSK(12) >> IWL_FIRST_OFDM_RATE;
 382	/* 6M already there or needed so always add */
 383	ofdm |= IWL_RATE_BIT_MSK(6) >> IWL_FIRST_OFDM_RATE;
 384
 385	/*
 386	 * CCK is a bit more complex with DSSS vs. HR/DSSS vs. ERP.
 387	 * Note, however:
 388	 *  - if no CCK rates are basic, it must be ERP since there must
 389	 *    be some basic rates at all, so they're OFDM => ERP PHY
 390	 *    (or we're in 5 GHz, and the cck bitmap will never be used)
 391	 *  - if 11M is a basic rate, it must be ERP as well, so add 5.5M
 392	 *  - if 5.5M is basic, 1M and 2M are mandatory
 393	 *  - if 2M is basic, 1M is mandatory
 394	 *  - if 1M is basic, that's the only valid ACK rate.
 395	 * As a consequence, it's not as complicated as it sounds, just add
 396	 * any lower rates to the ACK rate bitmap.
 397	 */
 398	if (IWL_RATE_11M_INDEX < lowest_present_cck)
 399		cck |= IWL_RATE_BIT_MSK(11) >> IWL_FIRST_CCK_RATE;
 400	if (IWL_RATE_5M_INDEX < lowest_present_cck)
 401		cck |= IWL_RATE_BIT_MSK(5) >> IWL_FIRST_CCK_RATE;
 402	if (IWL_RATE_2M_INDEX < lowest_present_cck)
 403		cck |= IWL_RATE_BIT_MSK(2) >> IWL_FIRST_CCK_RATE;
 404	/* 1M already there or needed so always add */
 405	cck |= IWL_RATE_BIT_MSK(1) >> IWL_FIRST_CCK_RATE;
 406
 407	*cck_rates = cck;
 408	*ofdm_rates = ofdm;
 409}
 410
 411void iwl_mvm_set_fw_basic_rates(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 412				struct iwl_mvm_vif_link_info *link_info,
 413				__le32 *cck_rates, __le32 *ofdm_rates)
 414{
 415	struct iwl_mvm_phy_ctxt *phy_ctxt;
 416	u8 cck_ack_rates = 0, ofdm_ack_rates = 0;
 417	enum nl80211_band band = NL80211_BAND_2GHZ;
 418
 419	phy_ctxt = link_info->phy_ctxt;
 420	if (phy_ctxt && phy_ctxt->channel)
 421		band = phy_ctxt->channel->band;
 422
 423	iwl_mvm_ack_rates(mvm, vif, band, &cck_ack_rates, &ofdm_ack_rates);
 424
 425	*cck_rates = cpu_to_le32((u32)cck_ack_rates);
 426	*ofdm_rates = cpu_to_le32((u32)ofdm_ack_rates);
 427}
 428
 429void iwl_mvm_set_fw_protection_flags(struct iwl_mvm *mvm,
 430				     struct ieee80211_vif *vif,
 431				     struct ieee80211_bss_conf *link_conf,
 432				     __le32 *protection_flags, u32 ht_flag,
 433				     u32 tgg_flag)
 434{
 435	/* for both sta and ap, ht_operation_mode hold the protection_mode */
 436	u8 protection_mode = link_conf->ht_operation_mode &
 437				 IEEE80211_HT_OP_MODE_PROTECTION;
 438	bool ht_enabled = !!(link_conf->ht_operation_mode &
 439			     IEEE80211_HT_OP_MODE_PROTECTION);
 440
 441	if (link_conf->use_cts_prot)
 442		*protection_flags |= cpu_to_le32(tgg_flag);
 443
 444	IWL_DEBUG_RATE(mvm, "use_cts_prot %d, ht_operation_mode %d\n",
 445		       link_conf->use_cts_prot,
 446		       link_conf->ht_operation_mode);
 447
 448	if (!ht_enabled)
 449		return;
 450
 451	IWL_DEBUG_RATE(mvm, "protection mode set to %d\n", protection_mode);
 452	/*
 453	 * See section 9.23.3.1 of IEEE 80211-2012.
 454	 * Nongreenfield HT STAs Present is not supported.
 455	 */
 456	switch (protection_mode) {
 457	case IEEE80211_HT_OP_MODE_PROTECTION_NONE:
 458		break;
 459	case IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER:
 460	case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED:
 461		*protection_flags |= cpu_to_le32(ht_flag);
 462		break;
 463	case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ:
 464		/* Protect when channel wider than 20MHz */
 465		if (link_conf->chanreq.oper.width > NL80211_CHAN_WIDTH_20)
 466			*protection_flags |= cpu_to_le32(ht_flag);
 467		break;
 468	default:
 469		IWL_ERR(mvm, "Illegal protection mode %d\n",
 470			protection_mode);
 471		break;
 472	}
 473}
 474
 475void iwl_mvm_set_fw_qos_params(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 476			       struct ieee80211_bss_conf *link_conf,
 477			       struct iwl_ac_qos *ac, __le32 *qos_flags)
 478{
 479	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 480	struct iwl_mvm_vif_link_info *mvm_link =
 481		mvmvif->link[link_conf->link_id];
 482	int i;
 483
 484	if (!mvm_link)
 485		return;
 486
 487	for (i = 0; i < IEEE80211_NUM_ACS; i++) {
 488		u8 txf = iwl_mvm_mac_ac_to_tx_fifo(mvm, i);
 489		u8 ucode_ac = iwl_mvm_mac80211_ac_to_ucode_ac(i);
 490
 491		ac[ucode_ac].cw_min =
 492			cpu_to_le16(mvm_link->queue_params[i].cw_min);
 493		ac[ucode_ac].cw_max =
 494			cpu_to_le16(mvm_link->queue_params[i].cw_max);
 495		ac[ucode_ac].edca_txop =
 496			cpu_to_le16(mvm_link->queue_params[i].txop * 32);
 497		ac[ucode_ac].aifsn = mvm_link->queue_params[i].aifs;
 498		ac[ucode_ac].fifos_mask = BIT(txf);
 499	}
 500
 501	if (link_conf->qos)
 502		*qos_flags |= cpu_to_le32(MAC_QOS_FLG_UPDATE_EDCA);
 503
 504	if (link_conf->chanreq.oper.width != NL80211_CHAN_WIDTH_20_NOHT)
 505		*qos_flags |= cpu_to_le32(MAC_QOS_FLG_TGN);
 506}
 507
 508int iwl_mvm_get_mac_type(struct ieee80211_vif *vif)
 509{
 510	u32 mac_type = FW_MAC_TYPE_BSS_STA;
 511
 512	switch (vif->type) {
 513	case NL80211_IFTYPE_STATION:
 514		if (vif->p2p)
 515			mac_type = FW_MAC_TYPE_P2P_STA;
 516		else
 517			mac_type = FW_MAC_TYPE_BSS_STA;
 518		break;
 519	case NL80211_IFTYPE_AP:
 520		mac_type = FW_MAC_TYPE_GO;
 521		break;
 522	case NL80211_IFTYPE_MONITOR:
 523		mac_type = FW_MAC_TYPE_LISTENER;
 524		break;
 525	case NL80211_IFTYPE_P2P_DEVICE:
 526		mac_type = FW_MAC_TYPE_P2P_DEVICE;
 527		break;
 528	case NL80211_IFTYPE_ADHOC:
 529		mac_type = FW_MAC_TYPE_IBSS;
 530		break;
 531	default:
 532		WARN_ON_ONCE(1);
 533	}
 534	return mac_type;
 535}
 536
 537static void iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
 538					struct ieee80211_vif *vif,
 539					struct iwl_mac_ctx_cmd *cmd,
 540					const u8 *bssid_override,
 541					u32 action)
 542{
 543	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 544	const u8 *bssid = bssid_override ?: vif->bss_conf.bssid;
 545	u32 ht_flag;
 546
 547	cmd->id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
 548							    mvmvif->color));
 549	cmd->action = cpu_to_le32(action);
 550	cmd->mac_type = cpu_to_le32(iwl_mvm_get_mac_type(vif));
 551
 552	cmd->tsf_id = cpu_to_le32(mvmvif->tsf_id);
 553
 554	memcpy(cmd->node_addr, vif->addr, ETH_ALEN);
 555
 556	if (bssid)
 557		memcpy(cmd->bssid_addr, bssid, ETH_ALEN);
 558	else
 559		eth_broadcast_addr(cmd->bssid_addr);
 560
 561	iwl_mvm_set_fw_basic_rates(mvm, vif, &mvmvif->deflink, &cmd->cck_rates,
 562				   &cmd->ofdm_rates);
 563
 564	cmd->cck_short_preamble =
 565		cpu_to_le32(vif->bss_conf.use_short_preamble ?
 566			    MAC_FLG_SHORT_PREAMBLE : 0);
 567	cmd->short_slot =
 568		cpu_to_le32(vif->bss_conf.use_short_slot ?
 569			    MAC_FLG_SHORT_SLOT : 0);
 570
 571	cmd->filter_flags = 0;
 572
 573	iwl_mvm_set_fw_qos_params(mvm, vif, &vif->bss_conf, cmd->ac,
 574				  &cmd->qos_flags);
 575
 576	/* The fw does not distinguish between ht and fat */
 577	ht_flag = MAC_PROT_FLG_HT_PROT | MAC_PROT_FLG_FAT_PROT;
 578	iwl_mvm_set_fw_protection_flags(mvm, vif, &vif->bss_conf,
 579					&cmd->protection_flags,
 580					ht_flag, MAC_PROT_FLG_TGG_PROTECT);
 581}
 582
 583static int iwl_mvm_mac_ctxt_send_cmd(struct iwl_mvm *mvm,
 584				     struct iwl_mac_ctx_cmd *cmd)
 585{
 586	int ret = iwl_mvm_send_cmd_pdu(mvm, MAC_CONTEXT_CMD, 0,
 587				       sizeof(*cmd), cmd);
 588	if (ret)
 589		IWL_ERR(mvm, "Failed to send MAC_CONTEXT_CMD (action:%d): %d\n",
 590			le32_to_cpu(cmd->action), ret);
 591	return ret;
 592}
 593
 594void iwl_mvm_set_fw_dtim_tbtt(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 595			      struct ieee80211_bss_conf *link_conf,
 596			      __le64 *dtim_tsf, __le32 *dtim_time,
 597			      __le32 *assoc_beacon_arrive_time)
 598{
 599	u32 dtim_offs;
 600
 601	/*
 602	 * The DTIM count counts down, so when it is N that means N
 603	 * more beacon intervals happen until the DTIM TBTT. Therefore
 604	 * add this to the current time. If that ends up being in the
 605	 * future, the firmware will handle it.
 606	 *
 607	 * Also note that the system_timestamp (which we get here as
 608	 * "sync_device_ts") and TSF timestamp aren't at exactly the
 609	 * same offset in the frame -- the TSF is at the first symbol
 610	 * of the TSF, the system timestamp is at signal acquisition
 611	 * time. This means there's an offset between them of at most
 612	 * a few hundred microseconds (24 * 8 bits + PLCP time gives
 613	 * 384us in the longest case), this is currently not relevant
 614	 * as the firmware wakes up around 2ms before the TBTT.
 615	 */
 616	dtim_offs = link_conf->sync_dtim_count *
 617			link_conf->beacon_int;
 618	/* convert TU to usecs */
 619	dtim_offs *= 1024;
 620
 621	*dtim_tsf =
 622		cpu_to_le64(link_conf->sync_tsf + dtim_offs);
 623	*dtim_time =
 624		cpu_to_le32(link_conf->sync_device_ts + dtim_offs);
 625	*assoc_beacon_arrive_time =
 626		cpu_to_le32(link_conf->sync_device_ts);
 627
 628	IWL_DEBUG_INFO(mvm, "DTIM TBTT is 0x%llx/0x%x, offset %d\n",
 629		       le64_to_cpu(*dtim_tsf),
 630		       le32_to_cpu(*dtim_time),
 631		       dtim_offs);
 632}
 633
 634__le32 iwl_mvm_mac_ctxt_cmd_p2p_sta_get_oppps_ctwin(struct iwl_mvm *mvm,
 635						    struct ieee80211_vif *vif)
 636{
 637	struct ieee80211_p2p_noa_attr *noa =
 638		&vif->bss_conf.p2p_noa_attr;
 639
 640	return cpu_to_le32(noa->oppps_ctwindow &
 641			IEEE80211_P2P_OPPPS_CTWINDOW_MASK);
 642}
 643
 644u32 iwl_mvm_mac_ctxt_cmd_sta_get_twt_policy(struct iwl_mvm *mvm,
 645					    struct ieee80211_vif *vif)
 646{
 647	u32 twt_policy = 0;
 648
 649	if (vif->bss_conf.twt_requester && IWL_MVM_USE_TWT)
 650		twt_policy |= TWT_SUPPORTED;
 651	if (vif->bss_conf.twt_protected)
 652		twt_policy |= PROTECTED_TWT_SUPPORTED;
 653	if (vif->bss_conf.twt_broadcast)
 654		twt_policy |= BROADCAST_TWT_SUPPORTED;
 655
 656	return twt_policy;
 657}
 658
 659static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,
 660				    struct ieee80211_vif *vif,
 661				    u32 action, bool force_assoc_off,
 662				    const u8 *bssid_override)
 663{
 664	struct iwl_mac_ctx_cmd cmd = {};
 665	struct iwl_mac_data_sta *ctxt_sta;
 666
 667	WARN_ON(vif->type != NL80211_IFTYPE_STATION);
 668
 669	/* Fill the common data for all mac context types */
 670	iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, bssid_override, action);
 671
 672	/*
 673	 * We always want to hear MCAST frames, if we're not authorized yet,
 674	 * we'll drop them.
 675	 */
 676	cmd.filter_flags |= cpu_to_le32(MAC_FILTER_ACCEPT_GRP);
 677
 678	if (vif->p2p) {
 679		cmd.p2p_sta.ctwin =
 680			iwl_mvm_mac_ctxt_cmd_p2p_sta_get_oppps_ctwin(mvm, vif);
 681
 682		ctxt_sta = &cmd.p2p_sta.sta;
 683	} else {
 684		ctxt_sta = &cmd.sta;
 685	}
 686
 687	/* We need the dtim_period to set the MAC as associated */
 688	if (vif->cfg.assoc && vif->bss_conf.dtim_period &&
 689	    !force_assoc_off) {
 690		struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 691
 692		iwl_mvm_set_fw_dtim_tbtt(mvm, vif, &vif->bss_conf,
 693					 &ctxt_sta->dtim_tsf,
 694					 &ctxt_sta->dtim_time,
 695					 &ctxt_sta->assoc_beacon_arrive_time);
 696
 697		ctxt_sta->is_assoc = cpu_to_le32(1);
 698
 699		if (!mvmvif->authorized &&
 700		    fw_has_capa(&mvm->fw->ucode_capa,
 701				IWL_UCODE_TLV_CAPA_COEX_HIGH_PRIO))
 702			ctxt_sta->data_policy |=
 703				cpu_to_le32(COEX_HIGH_PRIORITY_ENABLE);
 704	} else {
 705		ctxt_sta->is_assoc = cpu_to_le32(0);
 706
 707		/* Allow beacons to pass through as long as we are not
 708		 * associated, or we do not have dtim period information.
 709		 */
 710		cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_BEACON);
 711	}
 712
 713	ctxt_sta->bi = cpu_to_le32(vif->bss_conf.beacon_int);
 714	ctxt_sta->dtim_interval = cpu_to_le32(vif->bss_conf.beacon_int *
 715					      vif->bss_conf.dtim_period);
 716
 717	ctxt_sta->listen_interval = cpu_to_le32(mvm->hw->conf.listen_interval);
 718	ctxt_sta->assoc_id = cpu_to_le32(vif->cfg.aid);
 719
 720	if (vif->probe_req_reg && vif->cfg.assoc && vif->p2p)
 721		cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST);
 722
 723	if (vif->bss_conf.he_support && !iwlwifi_mod_params.disable_11ax) {
 724		cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_11AX);
 725		ctxt_sta->data_policy |=
 726			cpu_to_le32(iwl_mvm_mac_ctxt_cmd_sta_get_twt_policy(mvm, vif));
 727	}
 728
 729
 730	return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
 731}
 732
 733static int iwl_mvm_mac_ctxt_cmd_listener(struct iwl_mvm *mvm,
 734					 struct ieee80211_vif *vif,
 735					 u32 action)
 736{
 737	struct iwl_mac_ctx_cmd cmd = {};
 738	u32 tfd_queue_msk = 0;
 739	int ret;
 740
 741	WARN_ON(vif->type != NL80211_IFTYPE_MONITOR);
 742
 743	iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, NULL, action);
 744
 745	cmd.filter_flags = cpu_to_le32(MAC_FILTER_IN_PROMISC |
 746				       MAC_FILTER_IN_CONTROL_AND_MGMT |
 747				       MAC_FILTER_IN_BEACON |
 748				       MAC_FILTER_IN_PROBE_REQUEST |
 749				       MAC_FILTER_IN_CRC32 |
 750				       MAC_FILTER_ACCEPT_GRP);
 751	ieee80211_hw_set(mvm->hw, RX_INCLUDES_FCS);
 752
 753	/*
 754	 * the queue mask is only relevant for old TX API, and
 755	 * mvm->snif_queue isn't set here (it's still set to
 756	 * IWL_MVM_INVALID_QUEUE so the BIT() of it is UB)
 757	 */
 758	if (!iwl_mvm_has_new_tx_api(mvm))
 759		tfd_queue_msk = BIT(mvm->snif_queue);
 760
 761	/* Allocate sniffer station */
 762	ret = iwl_mvm_allocate_int_sta(mvm, &mvm->snif_sta, tfd_queue_msk,
 763				       vif->type, IWL_STA_GENERAL_PURPOSE);
 764	if (ret)
 765		return ret;
 766
 767	return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
 768}
 769
 770static int iwl_mvm_mac_ctxt_cmd_ibss(struct iwl_mvm *mvm,
 771				     struct ieee80211_vif *vif,
 772				     u32 action)
 773{
 774	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 775	struct iwl_mac_ctx_cmd cmd = {};
 776
 777	WARN_ON(vif->type != NL80211_IFTYPE_ADHOC);
 778
 779	iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, NULL, action);
 780
 781	cmd.filter_flags = cpu_to_le32(MAC_FILTER_IN_BEACON |
 782				       MAC_FILTER_IN_PROBE_REQUEST |
 783				       MAC_FILTER_ACCEPT_GRP);
 784
 785	/* cmd.ibss.beacon_time/cmd.ibss.beacon_tsf are curently ignored */
 786	cmd.ibss.bi = cpu_to_le32(vif->bss_conf.beacon_int);
 787
 788	/* TODO: Assumes that the beacon id == mac context id */
 789	cmd.ibss.beacon_template = cpu_to_le32(mvmvif->id);
 790
 791	return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
 792}
 793
 794struct iwl_mvm_go_iterator_data {
 795	bool go_active;
 796};
 797
 798static void iwl_mvm_go_iterator(void *_data, u8 *mac, struct ieee80211_vif *vif)
 799{
 800	struct iwl_mvm_go_iterator_data *data = _data;
 801	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 802
 803	if (vif->type == NL80211_IFTYPE_AP && vif->p2p &&
 804	    mvmvif->ap_ibss_active)
 805		data->go_active = true;
 806}
 807
 808__le32 iwl_mac_ctxt_p2p_dev_has_extended_disc(struct iwl_mvm *mvm,
 809					      struct ieee80211_vif *vif)
 810{
 811	struct iwl_mvm_go_iterator_data data = {};
 812
 813	/*
 814	 * This flag should be set to true when the P2P Device is
 815	 * discoverable and there is at least another active P2P GO. Settings
 816	 * this flag will allow the P2P Device to be discoverable on other
 817	 * channels in addition to its listen channel.
 818	 * Note that this flag should not be set in other cases as it opens the
 819	 * Rx filters on all MAC and increases the number of interrupts.
 820	 */
 821	ieee80211_iterate_active_interfaces_atomic(
 822		mvm->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
 823		iwl_mvm_go_iterator, &data);
 824
 825	return cpu_to_le32(data.go_active ? 1 : 0);
 826}
 827
 828static int iwl_mvm_mac_ctxt_cmd_p2p_device(struct iwl_mvm *mvm,
 829					   struct ieee80211_vif *vif,
 830					   u32 action)
 831{
 832	struct iwl_mac_ctx_cmd cmd = {};
 833
 834	WARN_ON(vif->type != NL80211_IFTYPE_P2P_DEVICE);
 835
 836	iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, NULL, action);
 837
 838	cmd.p2p_dev.is_disc_extended =
 839		iwl_mac_ctxt_p2p_dev_has_extended_disc(mvm, vif);
 840
 841	/* Override the filter flags to accept only probe requests */
 842	cmd.filter_flags = cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST);
 843
 844	return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
 845}
 846
 847void iwl_mvm_mac_ctxt_set_tim(struct iwl_mvm *mvm,
 848			      __le32 *tim_index, __le32 *tim_size,
 849			      u8 *beacon, u32 frame_size)
 850{
 851	u32 tim_idx;
 852	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)beacon;
 853
 854	/* The index is relative to frame start but we start looking at the
 855	 * variable-length part of the beacon. */
 856	tim_idx = mgmt->u.beacon.variable - beacon;
 857
 858	/* Parse variable-length elements of beacon to find WLAN_EID_TIM */
 859	while ((tim_idx < (frame_size - 2)) &&
 860			(beacon[tim_idx] != WLAN_EID_TIM))
 861		tim_idx += beacon[tim_idx+1] + 2;
 862
 863	/* If TIM field was found, set variables */
 864	if ((tim_idx < (frame_size - 1)) && (beacon[tim_idx] == WLAN_EID_TIM)) {
 865		*tim_index = cpu_to_le32(tim_idx);
 866		*tim_size = cpu_to_le32((u32)beacon[tim_idx + 1]);
 867	} else {
 868		IWL_WARN(mvm, "Unable to find TIM Element in beacon\n");
 869	}
 870}
 871
 872u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct iwl_mvm *mvm,
 873				    struct ieee80211_tx_info *info,
 874				    struct ieee80211_vif *vif)
 875{
 876	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 877	struct ieee80211_supported_band *sband;
 878	unsigned long basic = vif->bss_conf.basic_rates;
 879	u16 lowest_cck = IWL_RATE_COUNT, lowest_ofdm = IWL_RATE_COUNT;
 880	u32 link_id = u32_get_bits(info->control.flags,
 881				   IEEE80211_TX_CTRL_MLO_LINK);
 882	u8 band = info->band;
 883	u8 rate;
 884	u32 i;
 885
 886	if (link_id == IEEE80211_LINK_UNSPECIFIED && ieee80211_vif_is_mld(vif)) {
 887		for (i = 0; i < ARRAY_SIZE(mvmvif->link); i++) {
 888			if (!mvmvif->link[i])
 889				continue;
 890			/* shouldn't do this when >1 link is active */
 891			WARN_ON_ONCE(link_id != IEEE80211_LINK_UNSPECIFIED);
 892			link_id = i;
 893		}
 894	}
 895
 896	if (link_id < IEEE80211_LINK_UNSPECIFIED) {
 897		struct ieee80211_bss_conf *link_conf;
 898
 899		rcu_read_lock();
 900		link_conf = rcu_dereference(vif->link_conf[link_id]);
 901		if (link_conf) {
 902			basic = link_conf->basic_rates;
 903			if (link_conf->chanreq.oper.chan)
 904				band = link_conf->chanreq.oper.chan->band;
 905		}
 906		rcu_read_unlock();
 907	}
 908
 909	sband = mvm->hw->wiphy->bands[band];
 910	for_each_set_bit(i, &basic, BITS_PER_LONG) {
 911		u16 hw = sband->bitrates[i].hw_value;
 912
 913		if (hw >= IWL_FIRST_OFDM_RATE) {
 914			if (lowest_ofdm > hw)
 915				lowest_ofdm = hw;
 916		} else if (lowest_cck > hw) {
 917			lowest_cck = hw;
 918		}
 919	}
 920
 921	if (band == NL80211_BAND_2GHZ && !vif->p2p &&
 922	    vif->type != NL80211_IFTYPE_P2P_DEVICE &&
 923	    !(info->flags & IEEE80211_TX_CTL_NO_CCK_RATE)) {
 924		if (lowest_cck != IWL_RATE_COUNT)
 925			rate = lowest_cck;
 926		else if (lowest_ofdm != IWL_RATE_COUNT)
 927			rate = lowest_ofdm;
 928		else
 929			rate = IWL_RATE_1M_INDEX;
 930	} else if (lowest_ofdm != IWL_RATE_COUNT) {
 931		rate = lowest_ofdm;
 932	} else {
 933		rate = IWL_RATE_6M_INDEX;
 934	}
 935
 936	return rate;
 937}
 938
 939u16 iwl_mvm_mac_ctxt_get_beacon_flags(const struct iwl_fw *fw, u8 rate_idx)
 940{
 941	u16 flags = iwl_mvm_mac80211_idx_to_hwrate(fw, rate_idx);
 942	bool is_new_rate = iwl_fw_lookup_cmd_ver(fw, BEACON_TEMPLATE_CMD, 0) > 10;
 943
 944	if (rate_idx <= IWL_LAST_CCK_RATE)
 945		flags |= is_new_rate ? IWL_MAC_BEACON_CCK
 946			  : IWL_MAC_BEACON_CCK_V1;
 947
 948	return flags;
 949}
 950
 951u8 iwl_mvm_mac_ctxt_get_beacon_rate(struct iwl_mvm *mvm,
 952				    struct ieee80211_tx_info *info,
 953				    struct ieee80211_vif *vif)
 954{
 955	struct ieee80211_supported_band *sband =
 956		mvm->hw->wiphy->bands[info->band];
 957	u32 legacy = vif->bss_conf.beacon_tx_rate.control[info->band].legacy;
 958
 959	/* if beacon rate was configured try using it */
 960	if (hweight32(legacy) == 1) {
 961		u32 rate = ffs(legacy) - 1;
 962
 963		return sband->bitrates[rate].hw_value;
 964	}
 965
 966	return iwl_mvm_mac_ctxt_get_lowest_rate(mvm, info, vif);
 967}
 968
 969static void iwl_mvm_mac_ctxt_set_tx(struct iwl_mvm *mvm,
 970				    struct ieee80211_vif *vif,
 971				    struct sk_buff *beacon,
 972				    struct iwl_tx_cmd_v6_params *tx_params)
 973{
 974	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 975	struct ieee80211_tx_info *info;
 976	u8 rate;
 977	u32 tx_flags;
 978
 979	info = IEEE80211_SKB_CB(beacon);
 980
 981	/* Set up TX command fields */
 982	tx_params->len = cpu_to_le16((u16)beacon->len);
 983	tx_params->sta_id = mvmvif->deflink.bcast_sta.sta_id;
 984	tx_params->life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE);
 985	tx_flags = TX_CMD_FLG_SEQ_CTL | TX_CMD_FLG_TSF;
 986	tx_flags |=
 987		iwl_mvm_bt_coex_tx_prio(mvm, (void *)beacon->data, info, 0) <<
 988						TX_CMD_FLG_BT_PRIO_POS;
 989	tx_params->tx_flags = cpu_to_le32(tx_flags);
 990
 991	if (!fw_has_capa(&mvm->fw->ucode_capa,
 992			 IWL_UCODE_TLV_CAPA_BEACON_ANT_SELECTION)) {
 993		iwl_mvm_toggle_tx_ant(mvm, &mvm->mgmt_last_antenna_idx);
 994
 995		tx_params->rate_n_flags =
 996			cpu_to_le32(BIT(mvm->mgmt_last_antenna_idx) <<
 997				    RATE_MCS_ANT_POS);
 998	}
 999
1000	rate = iwl_mvm_mac_ctxt_get_beacon_rate(mvm, info, vif);
1001
1002	tx_params->rate_n_flags |=
1003		cpu_to_le32(iwl_mvm_mac80211_idx_to_hwrate(mvm->fw, rate));
1004	if (rate == IWL_FIRST_CCK_RATE)
1005		tx_params->rate_n_flags |= cpu_to_le32(RATE_MCS_CCK_MSK_V1);
1006
1007}
1008
1009int iwl_mvm_mac_ctxt_send_beacon_cmd(struct iwl_mvm *mvm,
1010				     struct sk_buff *beacon,
1011				     void *data, int len)
1012{
1013	struct iwl_host_cmd cmd = {
1014		.id = BEACON_TEMPLATE_CMD,
1015		.flags = CMD_ASYNC,
1016	};
1017
1018	cmd.len[0] = len;
1019	cmd.data[0] = data;
1020	cmd.dataflags[0] = 0;
1021	cmd.len[1] = beacon->len;
1022	cmd.data[1] = beacon->data;
1023	cmd.dataflags[1] = IWL_HCMD_DFL_DUP;
1024
1025	return iwl_mvm_send_cmd(mvm, &cmd);
1026}
1027
1028static int iwl_mvm_mac_ctxt_send_beacon_v6(struct iwl_mvm *mvm,
1029					   struct ieee80211_vif *vif,
1030					   struct sk_buff *beacon)
1031{
1032	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1033	struct iwl_mac_beacon_cmd_v6 beacon_cmd = {};
1034
1035	iwl_mvm_mac_ctxt_set_tx(mvm, vif, beacon, &beacon_cmd.tx);
1036
1037	beacon_cmd.template_id = cpu_to_le32((u32)mvmvif->id);
1038
1039	if (vif->type == NL80211_IFTYPE_AP)
1040		iwl_mvm_mac_ctxt_set_tim(mvm, &beacon_cmd.tim_idx,
1041					 &beacon_cmd.tim_size,
1042					 beacon->data, beacon->len);
1043
1044	return iwl_mvm_mac_ctxt_send_beacon_cmd(mvm, beacon, &beacon_cmd,
1045						sizeof(beacon_cmd));
1046}
1047
1048static int iwl_mvm_mac_ctxt_send_beacon_v7(struct iwl_mvm *mvm,
1049					   struct ieee80211_vif *vif,
1050					   struct sk_buff *beacon)
1051{
1052	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1053	struct iwl_mac_beacon_cmd_v7 beacon_cmd = {};
1054
1055	iwl_mvm_mac_ctxt_set_tx(mvm, vif, beacon, &beacon_cmd.tx);
1056
1057	beacon_cmd.template_id = cpu_to_le32((u32)mvmvif->id);
1058
1059	if (vif->type == NL80211_IFTYPE_AP)
1060		iwl_mvm_mac_ctxt_set_tim(mvm, &beacon_cmd.tim_idx,
1061					 &beacon_cmd.tim_size,
1062					 beacon->data, beacon->len);
1063
1064	beacon_cmd.csa_offset =
1065		cpu_to_le32(iwl_find_ie_offset(beacon->data,
1066					       WLAN_EID_CHANNEL_SWITCH,
1067					       beacon->len));
1068	beacon_cmd.ecsa_offset =
1069		cpu_to_le32(iwl_find_ie_offset(beacon->data,
1070					       WLAN_EID_EXT_CHANSWITCH_ANN,
1071					       beacon->len));
1072
1073	return iwl_mvm_mac_ctxt_send_beacon_cmd(mvm, beacon, &beacon_cmd,
1074						sizeof(beacon_cmd));
1075}
1076
1077bool iwl_mvm_enable_fils(struct iwl_mvm *mvm,
1078			 struct ieee80211_vif *vif,
1079			 struct ieee80211_chanctx_conf *ctx)
1080{
1081	if (vif->type != NL80211_IFTYPE_AP || IWL_MVM_DISABLE_AP_FILS)
1082		return false;
1083
1084	if (cfg80211_channel_is_psc(ctx->def.chan))
1085		return true;
1086
1087	return (ctx->def.chan->band == NL80211_BAND_6GHZ &&
1088		ctx->def.width >= NL80211_CHAN_WIDTH_80);
1089}
1090
1091static int iwl_mvm_mac_ctxt_send_beacon_v9(struct iwl_mvm *mvm,
1092					   struct ieee80211_vif *vif,
1093					   struct sk_buff *beacon,
1094					   struct ieee80211_bss_conf *link_conf)
1095{
1096	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1097	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(beacon);
1098	struct iwl_mac_beacon_cmd beacon_cmd = {};
1099	u8 rate = iwl_mvm_mac_ctxt_get_beacon_rate(mvm, info, vif);
1100	u16 flags;
1101	struct ieee80211_chanctx_conf *ctx;
1102	int channel;
1103	flags = iwl_mvm_mac_ctxt_get_beacon_flags(mvm->fw, rate);
1104
1105	/* Enable FILS on PSC channels only */
1106	rcu_read_lock();
1107	ctx = rcu_dereference(link_conf->chanctx_conf);
1108	channel = ieee80211_frequency_to_channel(ctx->def.chan->center_freq);
1109	WARN_ON(channel == 0);
1110	if (iwl_mvm_enable_fils(mvm, vif, ctx)) {
1111		flags |= iwl_fw_lookup_cmd_ver(mvm->fw, BEACON_TEMPLATE_CMD,
1112					       0) > 10 ?
1113			IWL_MAC_BEACON_FILS :
1114			IWL_MAC_BEACON_FILS_V1;
1115		beacon_cmd.short_ssid =
1116			cpu_to_le32(~crc32_le(~0, vif->cfg.ssid,
1117					      vif->cfg.ssid_len));
1118	}
1119	rcu_read_unlock();
1120
1121	beacon_cmd.flags = cpu_to_le16(flags);
1122	beacon_cmd.byte_cnt = cpu_to_le16((u16)beacon->len);
1123
1124	if (WARN_ON(!mvmvif->link[link_conf->link_id]))
1125		return -EINVAL;
1126
1127	if (iwl_fw_lookup_cmd_ver(mvm->fw, BEACON_TEMPLATE_CMD, 0) > 12)
1128		beacon_cmd.link_id =
1129			cpu_to_le32(mvmvif->link[link_conf->link_id]->fw_link_id);
1130	else
1131		beacon_cmd.link_id = cpu_to_le32((u32)mvmvif->id);
1132
1133	if (vif->type == NL80211_IFTYPE_AP)
1134		iwl_mvm_mac_ctxt_set_tim(mvm, &beacon_cmd.tim_idx,
1135					 &beacon_cmd.tim_size,
1136					 beacon->data, beacon->len);
1137
1138	beacon_cmd.csa_offset =
1139		cpu_to_le32(iwl_find_ie_offset(beacon->data,
1140					       WLAN_EID_CHANNEL_SWITCH,
1141					       beacon->len));
1142	beacon_cmd.ecsa_offset =
1143		cpu_to_le32(iwl_find_ie_offset(beacon->data,
1144					       WLAN_EID_EXT_CHANSWITCH_ANN,
1145					       beacon->len));
1146
1147	if (vif->type == NL80211_IFTYPE_AP &&
1148	    iwl_fw_lookup_cmd_ver(mvm->fw, BEACON_TEMPLATE_CMD, 0) >= 14)
1149		beacon_cmd.btwt_offset =
1150			cpu_to_le32(iwl_find_ie_offset(beacon->data,
1151						       WLAN_EID_S1G_TWT,
1152						       beacon->len));
1153
1154	return iwl_mvm_mac_ctxt_send_beacon_cmd(mvm, beacon, &beacon_cmd,
1155						sizeof(beacon_cmd));
1156}
1157
1158static int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm,
1159					struct ieee80211_vif *vif,
1160					struct sk_buff *beacon,
1161					struct ieee80211_bss_conf *link_conf)
1162{
1163	if (WARN_ON(!beacon))
1164		return -EINVAL;
1165
1166	if (IWL_MVM_NON_TRANSMITTING_AP)
1167		return 0;
1168
1169	if (!fw_has_capa(&mvm->fw->ucode_capa,
1170			 IWL_UCODE_TLV_CAPA_CSA_AND_TBTT_OFFLOAD))
1171		return iwl_mvm_mac_ctxt_send_beacon_v6(mvm, vif, beacon);
1172
1173	if (fw_has_api(&mvm->fw->ucode_capa,
1174		       IWL_UCODE_TLV_API_NEW_BEACON_TEMPLATE))
1175		return iwl_mvm_mac_ctxt_send_beacon_v9(mvm, vif, beacon,
1176						       link_conf);
1177
1178	return iwl_mvm_mac_ctxt_send_beacon_v7(mvm, vif, beacon);
1179}
1180
1181/* The beacon template for the AP/GO/IBSS has changed and needs update */
1182int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm,
1183				    struct ieee80211_vif *vif,
1184				    struct ieee80211_bss_conf *link_conf)
1185{
1186	struct sk_buff *beacon;
1187	int ret;
1188
1189	WARN_ON(vif->type != NL80211_IFTYPE_AP &&
1190		vif->type != NL80211_IFTYPE_ADHOC);
1191
1192	beacon = ieee80211_beacon_get_template(mvm->hw, vif, NULL,
1193					       link_conf->link_id);
1194	if (!beacon)
1195		return -ENOMEM;
1196
1197#ifdef CONFIG_IWLWIFI_DEBUGFS
1198	if (mvm->beacon_inject_active) {
1199		dev_kfree_skb(beacon);
1200		return -EBUSY;
1201	}
1202#endif
1203
1204	ret = iwl_mvm_mac_ctxt_send_beacon(mvm, vif, beacon, link_conf);
1205	dev_kfree_skb(beacon);
1206	return ret;
1207}
1208
1209struct iwl_mvm_mac_ap_iterator_data {
1210	struct iwl_mvm *mvm;
1211	struct ieee80211_vif *vif;
1212	u32 beacon_device_ts;
1213	u16 beacon_int;
1214};
1215
1216/* Find the beacon_device_ts and beacon_int for a managed interface */
1217static void iwl_mvm_mac_ap_iterator(void *_data, u8 *mac,
1218				    struct ieee80211_vif *vif)
1219{
1220	struct iwl_mvm_mac_ap_iterator_data *data = _data;
1221
1222	if (vif->type != NL80211_IFTYPE_STATION || !vif->cfg.assoc)
1223		return;
1224
1225	/* Station client has higher priority over P2P client*/
1226	if (vif->p2p && data->beacon_device_ts)
1227		return;
1228
1229	data->beacon_device_ts = vif->bss_conf.sync_device_ts;
1230	data->beacon_int = vif->bss_conf.beacon_int;
1231}
1232
1233/*
1234 * Fill the filter flags for mac context of type AP or P2P GO.
1235 */
1236void iwl_mvm_mac_ctxt_cmd_ap_set_filter_flags(struct iwl_mvm *mvm,
1237					      struct iwl_mvm_vif *mvmvif,
1238					      __le32 *filter_flags,
1239					      int accept_probe_req_flag,
1240					      int accept_beacon_flag)
1241{
1242	/*
1243	 * in AP mode, pass probe requests and beacons from other APs
1244	 * (needed for ht protection); when there're no any associated
1245	 * station don't ask FW to pass beacons to prevent unnecessary
1246	 * wake-ups.
1247	 */
1248	*filter_flags |= cpu_to_le32(accept_probe_req_flag);
1249	if (mvmvif->ap_assoc_sta_count || !mvm->drop_bcn_ap_mode) {
1250		*filter_flags |= cpu_to_le32(accept_beacon_flag);
1251		IWL_DEBUG_HC(mvm, "Asking FW to pass beacons\n");
1252	} else {
1253		IWL_DEBUG_HC(mvm, "No need to receive beacons\n");
1254	}
1255}
1256
1257/*
1258 * Fill the specific data for mac context of type AP of P2P GO
1259 */
1260static void iwl_mvm_mac_ctxt_cmd_fill_ap(struct iwl_mvm *mvm,
1261					 struct ieee80211_vif *vif,
1262					 struct iwl_mac_ctx_cmd *cmd,
1263					 struct iwl_mac_data_ap *ctxt_ap,
1264					 bool add)
1265{
1266	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1267	struct iwl_mvm_mac_ap_iterator_data data = {
1268		.mvm = mvm,
1269		.vif = vif,
1270		.beacon_device_ts = 0
1271	};
1272
1273	/* in AP mode, the MCAST FIFO takes the EDCA params from VO */
1274	cmd->ac[IWL_MVM_TX_FIFO_VO].fifos_mask |= BIT(IWL_MVM_TX_FIFO_MCAST);
1275
1276	iwl_mvm_mac_ctxt_cmd_ap_set_filter_flags(mvm, mvmvif,
1277						 &cmd->filter_flags,
1278						 MAC_FILTER_IN_PROBE_REQUEST,
1279						 MAC_FILTER_IN_BEACON);
1280
1281	ctxt_ap->bi = cpu_to_le32(vif->bss_conf.beacon_int);
1282	ctxt_ap->dtim_interval = cpu_to_le32(vif->bss_conf.beacon_int *
1283					     vif->bss_conf.dtim_period);
1284
1285	if (!fw_has_api(&mvm->fw->ucode_capa,
1286			IWL_UCODE_TLV_API_STA_TYPE))
1287		ctxt_ap->mcast_qid = cpu_to_le32(mvmvif->deflink.cab_queue);
1288
1289	/*
1290	 * Only set the beacon time when the MAC is being added, when we
1291	 * just modify the MAC then we should keep the time -- the firmware
1292	 * can otherwise have a "jumping" TBTT.
1293	 */
1294	if (add) {
1295		/*
1296		 * If there is a station/P2P client interface which is
1297		 * associated, set the AP's TBTT far enough from the station's
1298		 * TBTT. Otherwise, set it to the current system time
1299		 */
1300		ieee80211_iterate_active_interfaces_atomic(
1301			mvm->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
1302			iwl_mvm_mac_ap_iterator, &data);
1303
1304		if (data.beacon_device_ts) {
1305			u32 rand = get_random_u32_inclusive(36, 63);
1306			mvmvif->ap_beacon_time = data.beacon_device_ts +
1307				ieee80211_tu_to_usec(data.beacon_int * rand /
1308						     100);
1309		} else {
1310			mvmvif->ap_beacon_time = iwl_mvm_get_systime(mvm);
1311		}
1312	}
1313
1314	ctxt_ap->beacon_time = cpu_to_le32(mvmvif->ap_beacon_time);
1315	ctxt_ap->beacon_tsf = 0; /* unused */
1316
1317	/* TODO: Assume that the beacon id == mac context id */
1318	ctxt_ap->beacon_template = cpu_to_le32(mvmvif->id);
1319}
1320
1321static int iwl_mvm_mac_ctxt_cmd_ap(struct iwl_mvm *mvm,
1322				   struct ieee80211_vif *vif,
1323				   u32 action)
1324{
1325	struct iwl_mac_ctx_cmd cmd = {};
1326
1327	WARN_ON(vif->type != NL80211_IFTYPE_AP || vif->p2p);
1328
1329	/* Fill the common data for all mac context types */
1330	iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, NULL, action);
1331
1332	/* Fill the data specific for ap mode */
1333	iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd, &cmd.ap,
1334				     action == FW_CTXT_ACTION_ADD);
1335
1336	return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
1337}
1338
1339static int iwl_mvm_mac_ctxt_cmd_go(struct iwl_mvm *mvm,
1340				   struct ieee80211_vif *vif,
1341				   u32 action)
1342{
1343	struct iwl_mac_ctx_cmd cmd = {};
1344	struct ieee80211_p2p_noa_attr *noa = &vif->bss_conf.p2p_noa_attr;
1345
1346	WARN_ON(vif->type != NL80211_IFTYPE_AP || !vif->p2p);
1347
1348	/* Fill the common data for all mac context types */
1349	iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, NULL, action);
1350
1351	/* Fill the data specific for GO mode */
1352	iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd, &cmd.go.ap,
1353				     action == FW_CTXT_ACTION_ADD);
1354
1355	cmd.go.ctwin = cpu_to_le32(noa->oppps_ctwindow &
1356					IEEE80211_P2P_OPPPS_CTWINDOW_MASK);
1357	cmd.go.opp_ps_enabled =
1358			cpu_to_le32(!!(noa->oppps_ctwindow &
1359					IEEE80211_P2P_OPPPS_ENABLE_BIT));
1360
1361	return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
1362}
1363
1364static int iwl_mvm_mac_ctx_send(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
1365				u32 action, bool force_assoc_off,
1366				const u8 *bssid_override)
1367{
1368	switch (vif->type) {
1369	case NL80211_IFTYPE_STATION:
1370		return iwl_mvm_mac_ctxt_cmd_sta(mvm, vif, action,
1371						force_assoc_off,
1372						bssid_override);
1373	case NL80211_IFTYPE_AP:
1374		if (!vif->p2p)
1375			return iwl_mvm_mac_ctxt_cmd_ap(mvm, vif, action);
1376		else
1377			return iwl_mvm_mac_ctxt_cmd_go(mvm, vif, action);
1378	case NL80211_IFTYPE_MONITOR:
1379		return iwl_mvm_mac_ctxt_cmd_listener(mvm, vif, action);
1380	case NL80211_IFTYPE_P2P_DEVICE:
1381		return iwl_mvm_mac_ctxt_cmd_p2p_device(mvm, vif, action);
1382	case NL80211_IFTYPE_ADHOC:
1383		return iwl_mvm_mac_ctxt_cmd_ibss(mvm, vif, action);
1384	default:
1385		break;
1386	}
1387
1388	return -EOPNOTSUPP;
1389}
1390
1391int iwl_mvm_mac_ctxt_add(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
1392{
1393	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1394	int ret;
1395
1396	if (WARN_ONCE(mvmvif->uploaded, "Adding active MAC %pM/%d\n",
1397		      vif->addr, ieee80211_vif_type_p2p(vif)))
1398		return -EIO;
1399
1400	ret = iwl_mvm_mac_ctx_send(mvm, vif, FW_CTXT_ACTION_ADD,
1401				   true, NULL);
1402	if (ret)
1403		return ret;
1404
1405	/* will only do anything at resume from D3 time */
1406	iwl_mvm_set_last_nonqos_seq(mvm, vif);
1407
1408	mvmvif->uploaded = true;
1409	return 0;
1410}
1411
1412int iwl_mvm_mac_ctxt_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
1413			     bool force_assoc_off, const u8 *bssid_override)
1414{
1415	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1416
1417	if (WARN_ONCE(!mvmvif->uploaded, "Changing inactive MAC %pM/%d\n",
1418		      vif->addr, ieee80211_vif_type_p2p(vif)))
1419		return -EIO;
1420
1421	return iwl_mvm_mac_ctx_send(mvm, vif, FW_CTXT_ACTION_MODIFY,
1422				    force_assoc_off, bssid_override);
1423}
1424
1425int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
1426{
1427	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1428	struct iwl_mac_ctx_cmd cmd;
1429	int ret;
1430
1431	if (WARN_ONCE(!mvmvif->uploaded, "Removing inactive MAC %pM/%d\n",
1432		      vif->addr, ieee80211_vif_type_p2p(vif)))
1433		return -EIO;
1434
1435	memset(&cmd, 0, sizeof(cmd));
1436
1437	cmd.id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
1438							   mvmvif->color));
1439	cmd.action = cpu_to_le32(FW_CTXT_ACTION_REMOVE);
1440
1441	ret = iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
1442	if (ret)
1443		return ret;
1444
1445	mvmvif->uploaded = false;
1446
1447	if (vif->type == NL80211_IFTYPE_MONITOR) {
1448		__clear_bit(IEEE80211_HW_RX_INCLUDES_FCS, mvm->hw->flags);
1449		iwl_mvm_dealloc_snif_sta(mvm);
1450	}
1451
1452	return 0;
1453}
1454
1455static void iwl_mvm_csa_count_down(struct iwl_mvm *mvm,
1456				   struct ieee80211_vif *csa_vif, u32 gp2,
1457				   bool tx_success)
1458{
1459	struct iwl_mvm_vif *mvmvif =
1460			iwl_mvm_vif_from_mac80211(csa_vif);
1461
1462	/* Don't start to countdown from a failed beacon */
1463	if (!tx_success && !mvmvif->csa_countdown)
1464		return;
1465
1466	mvmvif->csa_countdown = true;
1467
1468	if (!ieee80211_beacon_cntdwn_is_complete(csa_vif, 0)) {
1469		int c = ieee80211_beacon_update_cntdwn(csa_vif, 0);
1470
1471		iwl_mvm_mac_ctxt_beacon_changed(mvm, csa_vif,
1472						&csa_vif->bss_conf);
1473		if (csa_vif->p2p &&
1474		    !iwl_mvm_te_scheduled(&mvmvif->time_event_data) && gp2 &&
1475		    tx_success) {
1476			u32 rel_time = (c + 1) *
1477				       csa_vif->bss_conf.beacon_int -
1478				       IWL_MVM_CHANNEL_SWITCH_TIME_GO;
1479			u32 apply_time = gp2 + rel_time * 1024;
1480
1481			iwl_mvm_schedule_csa_period(mvm, csa_vif,
1482					 IWL_MVM_CHANNEL_SWITCH_TIME_GO -
1483					 IWL_MVM_CHANNEL_SWITCH_MARGIN,
1484					 apply_time);
1485		}
1486	} else if (!iwl_mvm_te_scheduled(&mvmvif->time_event_data)) {
1487		/* we don't have CSA NoA scheduled yet, switch now */
1488		ieee80211_csa_finish(csa_vif, 0);
1489		RCU_INIT_POINTER(mvm->csa_vif, NULL);
1490	}
1491}
1492
1493void iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm,
1494			     struct iwl_rx_cmd_buffer *rxb)
1495{
1496	struct iwl_rx_packet *pkt = rxb_addr(rxb);
1497	unsigned int pkt_len = iwl_rx_packet_payload_len(pkt);
1498	struct iwl_extended_beacon_notif *beacon = (void *)pkt->data;
1499	struct iwl_extended_beacon_notif_v5 *beacon_v5 = (void *)pkt->data;
1500	struct ieee80211_vif *csa_vif;
1501	struct ieee80211_vif *tx_blocked_vif;
1502	struct agg_tx_status *agg_status;
1503	u16 status;
1504
1505	lockdep_assert_held(&mvm->mutex);
1506
1507	mvm->ap_last_beacon_gp2 = le32_to_cpu(beacon->gp2);
1508
1509	if (!iwl_mvm_is_short_beacon_notif_supported(mvm)) {
1510		struct iwl_tx_resp *beacon_notify_hdr =
1511			&beacon_v5->beacon_notify_hdr;
1512
1513		if (unlikely(pkt_len < sizeof(*beacon_v5)))
1514			return;
1515
1516		mvm->ibss_manager = beacon_v5->ibss_mgr_status != 0;
1517		agg_status = iwl_mvm_get_agg_status(mvm, beacon_notify_hdr);
1518		status = le16_to_cpu(agg_status->status) & TX_STATUS_MSK;
1519		IWL_DEBUG_RX(mvm,
1520			     "beacon status %#x retries:%d tsf:0x%016llX gp2:0x%X rate:%d\n",
1521			     status, beacon_notify_hdr->failure_frame,
1522			     le64_to_cpu(beacon->tsf),
1523			     mvm->ap_last_beacon_gp2,
1524			     le32_to_cpu(beacon_notify_hdr->initial_rate));
1525	} else {
1526		if (unlikely(pkt_len < sizeof(*beacon)))
1527			return;
1528
1529		mvm->ibss_manager = beacon->ibss_mgr_status != 0;
1530		status = le32_to_cpu(beacon->status) & TX_STATUS_MSK;
1531		IWL_DEBUG_RX(mvm,
1532			     "beacon status %#x tsf:0x%016llX gp2:0x%X\n",
1533			     status, le64_to_cpu(beacon->tsf),
1534			     mvm->ap_last_beacon_gp2);
1535	}
1536
1537	csa_vif = rcu_dereference_protected(mvm->csa_vif,
1538					    lockdep_is_held(&mvm->mutex));
1539	if (unlikely(csa_vif && csa_vif->bss_conf.csa_active))
1540		iwl_mvm_csa_count_down(mvm, csa_vif, mvm->ap_last_beacon_gp2,
1541				       (status == TX_STATUS_SUCCESS));
1542
1543	tx_blocked_vif = rcu_dereference_protected(mvm->csa_tx_blocked_vif,
1544						lockdep_is_held(&mvm->mutex));
1545	if (unlikely(tx_blocked_vif)) {
1546		struct iwl_mvm_vif *mvmvif =
1547			iwl_mvm_vif_from_mac80211(tx_blocked_vif);
1548
1549		/*
1550		 * The channel switch is started and we have blocked the
1551		 * stations. If this is the first beacon (the timeout wasn't
1552		 * set), set the unblock timeout, otherwise countdown
1553		 */
1554		if (!mvm->csa_tx_block_bcn_timeout)
1555			mvm->csa_tx_block_bcn_timeout =
1556				IWL_MVM_CS_UNBLOCK_TX_TIMEOUT;
1557		else
1558			mvm->csa_tx_block_bcn_timeout--;
1559
1560		/* Check if the timeout is expired, and unblock tx */
1561		if (mvm->csa_tx_block_bcn_timeout == 0) {
1562			iwl_mvm_modify_all_sta_disable_tx(mvm, mvmvif, false);
1563			RCU_INIT_POINTER(mvm->csa_tx_blocked_vif, NULL);
1564		}
1565	}
1566}
1567
1568static void
1569iwl_mvm_handle_missed_beacons_notif(struct iwl_mvm *mvm,
1570				    const struct iwl_missed_beacons_notif *mb,
1571				    struct iwl_rx_packet *pkt)
1572{
1573	struct iwl_fw_dbg_trigger_missed_bcon *bcon_trig;
1574	struct iwl_fw_dbg_trigger_tlv *trigger;
1575	u32 stop_trig_missed_bcon, stop_trig_missed_bcon_since_rx;
1576	u32 rx_missed_bcon, rx_missed_bcon_since_rx;
1577	struct ieee80211_vif *vif;
1578	/* Id can be mac/link id depending on the notification version */
1579	u32 id = le32_to_cpu(mb->link_id);
1580	union iwl_dbg_tlv_tp_data tp_data = { .fw_pkt = pkt };
1581	u32 mac_type;
1582	u8 notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP,
1583					       MISSED_BEACONS_NOTIFICATION,
1584					       0);
1585	u8 new_notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, MAC_CONF_GROUP,
1586						   MISSED_BEACONS_NOTIF, 0);
1587
1588	/* If the firmware uses the new notification (from MAC_CONF_GROUP),
1589	 * refer to that notification's version.
1590	 * Note that the new notification from MAC_CONF_GROUP starts from
1591	 * version 5.
1592	 */
1593	if (new_notif_ver)
1594		notif_ver = new_notif_ver;
1595
1596	IWL_DEBUG_INFO(mvm,
1597		       "missed bcn %s_id=%u, consecutive=%u (%u)\n",
1598		       notif_ver < 4 ? "mac" : "link",
1599		       id,
1600		       le32_to_cpu(mb->consec_missed_beacons),
1601		       le32_to_cpu(mb->consec_missed_beacons_since_last_rx));
1602
1603	/*
1604	 * starting from version 4 the ID is link ID, but driver
1605	 * uses link ID == MAC ID, so always treat as MAC ID
1606	 */
1607	vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, false);
1608	if (!vif)
1609		return;
1610
1611	mac_type = iwl_mvm_get_mac_type(vif);
1612
1613	IWL_DEBUG_INFO(mvm, "missed beacon mac_type=%u,\n", mac_type);
1614
1615	rx_missed_bcon = le32_to_cpu(mb->consec_missed_beacons);
1616	rx_missed_bcon_since_rx =
1617		le32_to_cpu(mb->consec_missed_beacons_since_last_rx);
1618	/*
1619	 * TODO: the threshold should be adjusted based on latency conditions,
1620	 * and/or in case of a CS flow on one of the other AP vifs.
1621	 */
1622	if (rx_missed_bcon >= IWL_MVM_MISSED_BEACONS_THRESHOLD_LONG) {
1623		if (rx_missed_bcon_since_rx >= IWL_MVM_MISSED_BEACONS_SINCE_RX_THOLD) {
1624			iwl_mvm_connection_loss(mvm, vif, "missed beacons");
1625		} else {
1626			IWL_WARN(mvm,
1627				 "missed beacons exceeds threshold, but receiving data. Stay connected, Expect bugs.\n");
1628			IWL_WARN(mvm,
1629				 "missed_beacons:%d, missed_beacons_since_rx:%d\n",
1630				 rx_missed_bcon, rx_missed_bcon_since_rx);
1631		}
1632	} else if (rx_missed_bcon_since_rx > IWL_MVM_MISSED_BEACONS_THRESHOLD) {
1633		if (!iwl_mvm_has_new_tx_api(mvm))
1634			ieee80211_beacon_loss(vif);
1635		else
1636			ieee80211_cqm_beacon_loss_notify(vif, GFP_ATOMIC);
1637	}
1638
1639	iwl_dbg_tlv_time_point(&mvm->fwrt,
1640			       IWL_FW_INI_TIME_POINT_MISSED_BEACONS, &tp_data);
1641
1642	trigger = iwl_fw_dbg_trigger_on(&mvm->fwrt, ieee80211_vif_to_wdev(vif),
1643					FW_DBG_TRIGGER_MISSED_BEACONS);
1644	if (!trigger)
1645		return;
1646
1647	bcon_trig = (void *)trigger->data;
1648	stop_trig_missed_bcon = le32_to_cpu(bcon_trig->stop_consec_missed_bcon);
1649	stop_trig_missed_bcon_since_rx =
1650		le32_to_cpu(bcon_trig->stop_consec_missed_bcon_since_rx);
1651
1652	/* TODO: implement start trigger */
1653
1654	if (rx_missed_bcon_since_rx >= stop_trig_missed_bcon_since_rx ||
1655	    rx_missed_bcon >= stop_trig_missed_bcon)
1656		iwl_fw_dbg_collect_trig(&mvm->fwrt, trigger, NULL);
1657}
1658
1659void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm,
1660				     struct iwl_rx_cmd_buffer *rxb)
1661{
1662	struct iwl_rx_packet *pkt = rxb_addr(rxb);
1663
1664	iwl_mvm_handle_missed_beacons_notif(mvm, (const void *)pkt->data, pkt);
1665}
1666
1667void iwl_mvm_rx_missed_beacons_notif_legacy(struct iwl_mvm *mvm,
1668					    struct iwl_rx_cmd_buffer *rxb)
1669{
1670	struct iwl_rx_packet *pkt = rxb_addr(rxb);
1671	const struct iwl_missed_beacons_notif_v4 *mb_v4 =
1672		(const void *)pkt->data;
1673	struct iwl_missed_beacons_notif mb = {
1674		.link_id = mb_v4->link_id,
1675		.consec_missed_beacons = mb_v4->consec_missed_beacons,
1676		.consec_missed_beacons_since_last_rx =
1677			mb_v4->consec_missed_beacons_since_last_rx,
1678		.other_link_id = cpu_to_le32(IWL_MVM_FW_LINK_ID_INVALID),
1679	};
1680
1681	iwl_mvm_handle_missed_beacons_notif(mvm, &mb, pkt);
1682}
1683
1684void iwl_mvm_rx_stored_beacon_notif(struct iwl_mvm *mvm,
1685				    struct iwl_rx_cmd_buffer *rxb)
1686{
1687	struct iwl_rx_packet *pkt = rxb_addr(rxb);
1688	unsigned int pkt_len = iwl_rx_packet_payload_len(pkt);
1689	struct iwl_stored_beacon_notif_common *sb = (void *)pkt->data;
1690	struct ieee80211_rx_status rx_status;
1691	struct sk_buff *skb;
1692	u8 *data;
1693	u32 size = le32_to_cpu(sb->byte_count);
1694	int ver = iwl_fw_lookup_cmd_ver(mvm->fw,
1695					WIDE_ID(PROT_OFFLOAD_GROUP, STORED_BEACON_NTF),
1696					0);
1697
1698	if (size == 0)
1699		return;
1700
1701	/* handle per-version differences */
1702	if (ver <= 2) {
1703		struct iwl_stored_beacon_notif_v2 *sb_v2 = (void *)pkt->data;
1704
1705		if (pkt_len < struct_size(sb_v2, data, size))
1706			return;
1707
1708		data = sb_v2->data;
1709	} else {
1710		struct iwl_stored_beacon_notif *sb_v3 = (void *)pkt->data;
1711
1712		if (pkt_len < struct_size(sb_v3, data, size))
1713			return;
1714
1715		data = sb_v3->data;
1716	}
1717
1718	skb = alloc_skb(size, GFP_ATOMIC);
1719	if (!skb) {
1720		IWL_ERR(mvm, "alloc_skb failed\n");
1721		return;
1722	}
1723
1724	/* update rx_status according to the notification's metadata */
1725	memset(&rx_status, 0, sizeof(rx_status));
1726	rx_status.mactime = le64_to_cpu(sb->tsf);
1727	/* TSF as indicated by the firmware  is at INA time */
1728	rx_status.flag |= RX_FLAG_MACTIME_PLCP_START;
1729	rx_status.device_timestamp = le32_to_cpu(sb->system_time);
1730	rx_status.band =
1731		(sb->band & cpu_to_le16(RX_RES_PHY_FLAGS_BAND_24)) ?
1732				NL80211_BAND_2GHZ : NL80211_BAND_5GHZ;
1733	rx_status.freq =
1734		ieee80211_channel_to_frequency(le16_to_cpu(sb->channel),
1735					       rx_status.band);
1736
1737	/* copy the data */
1738	skb_put_data(skb, data, size);
1739	memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
1740
1741	/* pass it as regular rx to mac80211 */
1742	ieee80211_rx_napi(mvm->hw, NULL, skb, NULL);
1743}
1744
1745void iwl_mvm_probe_resp_data_notif(struct iwl_mvm *mvm,
1746				   struct iwl_rx_cmd_buffer *rxb)
1747{
1748	struct iwl_rx_packet *pkt = rxb_addr(rxb);
1749	struct iwl_probe_resp_data_notif *notif = (void *)pkt->data;
1750	struct iwl_probe_resp_data *old_data, *new_data;
1751	u32 id = le32_to_cpu(notif->mac_id);
1752	struct ieee80211_vif *vif;
1753	struct iwl_mvm_vif *mvmvif;
1754
1755	IWL_DEBUG_INFO(mvm, "Probe response data notif: noa %d, csa %d\n",
1756		       notif->noa_active, notif->csa_counter);
1757
1758	vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, false);
1759	if (!vif)
1760		return;
1761
1762	mvmvif = iwl_mvm_vif_from_mac80211(vif);
1763
1764	/*
1765	 * len_low should be 2 + n*13 (where n is the number of descriptors.
1766	 * 13 is the size of a NoA descriptor). We can have either one or two
1767	 * descriptors.
1768	 */
1769	if (IWL_FW_CHECK(mvm, notif->noa_active &&
1770			 notif->noa_attr.len_low != 2 +
1771			 sizeof(struct ieee80211_p2p_noa_desc) &&
1772			 notif->noa_attr.len_low != 2 +
1773			 sizeof(struct ieee80211_p2p_noa_desc) * 2,
1774			 "Invalid noa_attr.len_low (%d)\n",
1775			 notif->noa_attr.len_low))
1776		return;
1777
1778	new_data = kzalloc(sizeof(*new_data), GFP_KERNEL);
1779	if (!new_data)
1780		return;
1781
1782	memcpy(&new_data->notif, notif, sizeof(new_data->notif));
1783
1784	/* noa_attr contains 1 reserved byte, need to substruct it */
1785	new_data->noa_len = sizeof(struct ieee80211_vendor_ie) +
1786			    sizeof(new_data->notif.noa_attr) - 1;
1787
1788	/*
1789	 * If it's a one time NoA, only one descriptor is needed,
1790	 * adjust the length according to len_low.
1791	 */
1792	if (new_data->notif.noa_attr.len_low ==
1793	    sizeof(struct ieee80211_p2p_noa_desc) + 2)
1794		new_data->noa_len -= sizeof(struct ieee80211_p2p_noa_desc);
1795
1796	old_data = rcu_dereference_protected(mvmvif->deflink.probe_resp_data,
1797					     lockdep_is_held(&mvmvif->mvm->mutex));
1798	rcu_assign_pointer(mvmvif->deflink.probe_resp_data, new_data);
1799
1800	if (old_data)
1801		kfree_rcu(old_data, rcu_head);
1802
1803	if (notif->csa_counter != IWL_PROBE_RESP_DATA_NO_CSA &&
1804	    notif->csa_counter >= 1)
1805		ieee80211_beacon_set_cntdwn(vif, notif->csa_counter);
1806}
1807
1808void iwl_mvm_channel_switch_start_notif(struct iwl_mvm *mvm,
1809					struct iwl_rx_cmd_buffer *rxb)
1810{
1811	struct iwl_rx_packet *pkt = rxb_addr(rxb);
1812	struct ieee80211_vif *csa_vif, *vif;
1813	struct iwl_mvm_vif *mvmvif, *csa_mvmvif;
1814	u32 id_n_color, csa_id;
1815	/* save mac_id or link_id to use later to cancel csa if needed */
1816	u32 id;
1817	u32 mac_link_id = 0;
1818	u8 notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, MAC_CONF_GROUP,
1819					       CHANNEL_SWITCH_START_NOTIF, 0);
1820	bool csa_active;
1821
1822	rcu_read_lock();
1823
1824	if (notif_ver < 3) {
1825		struct iwl_channel_switch_start_notif_v1 *notif = (void *)pkt->data;
1826		u32 mac_id;
1827
1828		id_n_color = le32_to_cpu(notif->id_and_color);
1829		mac_id = id_n_color & FW_CTXT_ID_MSK;
1830
1831		vif = iwl_mvm_rcu_dereference_vif_id(mvm, mac_id, true);
1832		if (!vif)
1833			goto out_unlock;
1834
1835		id = mac_id;
1836		csa_active = vif->bss_conf.csa_active;
1837	} else {
1838		struct iwl_channel_switch_start_notif *notif = (void *)pkt->data;
1839		u32 link_id = le32_to_cpu(notif->link_id);
1840
1841		/* we use link ID == MAC ID */
1842		vif = iwl_mvm_rcu_dereference_vif_id(mvm, link_id, true);
1843		if (!vif)
1844			goto out_unlock;
1845
1846		id = link_id;
1847		mac_link_id = vif->bss_conf.link_id;
1848		csa_active = vif->bss_conf.csa_active;
1849	}
1850
1851	mvmvif = iwl_mvm_vif_from_mac80211(vif);
1852	if (notif_ver >= 3)
1853		id_n_color = FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color);
1854
1855	switch (vif->type) {
1856	case NL80211_IFTYPE_AP:
1857		csa_vif = rcu_dereference(mvm->csa_vif);
1858		if (WARN_ON(!csa_vif || !csa_vif->bss_conf.csa_active ||
1859			    csa_vif != vif))
1860			goto out_unlock;
1861
1862		csa_mvmvif = iwl_mvm_vif_from_mac80211(csa_vif);
1863		csa_id = FW_CMD_ID_AND_COLOR(csa_mvmvif->id, csa_mvmvif->color);
1864		if (WARN(csa_id != id_n_color,
1865			 "channel switch noa notification on unexpected vif (csa_vif=%d, notif=%d)",
1866			 csa_id, id_n_color))
1867			goto out_unlock;
1868
1869		IWL_DEBUG_INFO(mvm, "Channel Switch Started Notification\n");
1870
1871		schedule_delayed_work(&mvm->cs_tx_unblock_dwork,
1872				      msecs_to_jiffies(IWL_MVM_CS_UNBLOCK_TX_TIMEOUT *
1873						       csa_vif->bss_conf.beacon_int));
1874
1875		ieee80211_csa_finish(csa_vif, 0);
1876
1877		rcu_read_unlock();
1878
1879		RCU_INIT_POINTER(mvm->csa_vif, NULL);
1880		return;
1881	case NL80211_IFTYPE_STATION:
1882		/*
1883		 * if we don't know about an ongoing channel switch,
1884		 * make sure FW cancels it
1885		 */
1886		if (iwl_fw_lookup_notif_ver(mvm->fw, MAC_CONF_GROUP,
1887					    CHANNEL_SWITCH_ERROR_NOTIF,
1888					    0) && !csa_active) {
1889			IWL_DEBUG_INFO(mvm, "Channel Switch was canceled\n");
1890			iwl_mvm_cancel_channel_switch(mvm, vif, id);
1891			break;
1892		}
1893
1894		iwl_mvm_csa_client_absent(mvm, vif);
1895		cancel_delayed_work(&mvmvif->csa_work);
1896		ieee80211_chswitch_done(vif, true, mac_link_id);
1897		break;
1898	default:
1899		/* should never happen */
1900		WARN_ON_ONCE(1);
1901		break;
1902	}
1903out_unlock:
1904	rcu_read_unlock();
1905}
1906
1907void iwl_mvm_channel_switch_error_notif(struct iwl_mvm *mvm,
1908					struct iwl_rx_cmd_buffer *rxb)
1909{
1910	struct iwl_rx_packet *pkt = rxb_addr(rxb);
1911	struct iwl_channel_switch_error_notif *notif = (void *)pkt->data;
1912	struct ieee80211_vif *vif;
1913	u32 id = le32_to_cpu(notif->link_id);
1914	u32 csa_err_mask = le32_to_cpu(notif->csa_err_mask);
1915
1916	rcu_read_lock();
1917	vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, true);
1918	if (!vif) {
1919		rcu_read_unlock();
1920		return;
1921	}
1922
1923	IWL_DEBUG_INFO(mvm, "FW reports CSA error: id=%u, csa_err_mask=%u\n",
1924		       id, csa_err_mask);
1925	if (csa_err_mask & (CS_ERR_COUNT_ERROR |
1926			    CS_ERR_LONG_DELAY_AFTER_CS |
1927			    CS_ERR_TX_BLOCK_TIMER_EXPIRED))
1928		ieee80211_channel_switch_disconnect(vif);
1929	rcu_read_unlock();
1930}
~/ Read-only file preview.