Linux Audio

Check our new training course

Loading...
v6.8
   1// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
   2/*
   3 * Copyright (C) 2022-2023 Intel Corporation
   4 */
   5#include "mvm.h"
   6
   7static int iwl_mvm_mld_mac_add_interface(struct ieee80211_hw *hw,
   8					 struct ieee80211_vif *vif)
   9{
  10	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
  11	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
  12	int ret;
  13	int i;
  14
  15	mutex_lock(&mvm->mutex);
  16
 
 
  17	mvmvif->mvm = mvm;
  18
  19	/* Not much to do here. The stack will not allow interface
  20	 * types or combinations that we didn't advertise, so we
  21	 * don't really have to check the types.
  22	 */
  23
  24	/* make sure that beacon statistics don't go backwards with FW reset */
  25	if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
  26		for_each_mvm_vif_valid_link(mvmvif, i)
  27			mvmvif->link[i]->beacon_stats.accu_num_beacons +=
  28				mvmvif->link[i]->beacon_stats.num_beacons;
  29
  30	/* Allocate resources for the MAC context, and add it to the fw  */
  31	ret = iwl_mvm_mac_ctxt_init(mvm, vif);
  32	if (ret)
  33		goto out_unlock;
  34
  35	rcu_assign_pointer(mvm->vif_id_to_mac[mvmvif->id], vif);
  36
  37	mvmvif->features |= hw->netdev_features;
  38
  39	/* reset deflink MLO parameters */
  40	mvmvif->deflink.fw_link_id = IWL_MVM_FW_LINK_ID_INVALID;
  41	mvmvif->deflink.active = 0;
  42	/* the first link always points to the default one */
  43	mvmvif->link[0] = &mvmvif->deflink;
  44
  45	ret = iwl_mvm_mld_mac_ctxt_add(mvm, vif);
  46	if (ret)
  47		goto out_unlock;
  48
  49	/* beacon filtering */
  50	ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0);
  51	if (ret)
  52		goto out_remove_mac;
  53
  54	if (!mvm->bf_allowed_vif &&
  55	    vif->type == NL80211_IFTYPE_STATION && !vif->p2p) {
  56		mvm->bf_allowed_vif = mvmvif;
  57		vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER |
  58				     IEEE80211_VIF_SUPPORTS_CQM_RSSI;
  59	}
  60
  61	ret = iwl_mvm_add_link(mvm, vif, &vif->bss_conf);
  62	if (ret)
  63		goto out_free_bf;
  64
  65	/* Save a pointer to p2p device vif, so it can later be used to
  66	 * update the p2p device MAC when a GO is started/stopped
  67	 */
  68	if (vif->type == NL80211_IFTYPE_P2P_DEVICE)
  69		mvm->p2p_device_vif = vif;
  70
  71	ret = iwl_mvm_power_update_mac(mvm);
  72	if (ret)
  73		goto out_free_bf;
  74
  75	iwl_mvm_tcm_add_vif(mvm, vif);
  76	INIT_DELAYED_WORK(&mvmvif->csa_work,
  77			  iwl_mvm_channel_switch_disconnect_wk);
  78
  79	if (vif->type == NL80211_IFTYPE_MONITOR) {
  80		mvm->monitor_on = true;
  81		ieee80211_hw_set(mvm->hw, RX_INCLUDES_FCS);
  82	}
  83
  84	if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
  85		iwl_mvm_vif_dbgfs_add_link(mvm, vif);
  86
  87	if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) &&
  88	    vif->type == NL80211_IFTYPE_STATION && !vif->p2p &&
  89	    !mvm->csme_vif && mvm->mei_registered) {
  90		iwl_mei_set_nic_info(vif->addr, mvm->nvm_data->hw_addr);
  91		iwl_mei_set_netdev(ieee80211_vif_to_wdev(vif)->netdev);
  92		mvm->csme_vif = vif;
  93	}
  94
 
 
 
  95	goto out_unlock;
  96
  97 out_free_bf:
  98	if (mvm->bf_allowed_vif == mvmvif) {
  99		mvm->bf_allowed_vif = NULL;
 100		vif->driver_flags &= ~(IEEE80211_VIF_BEACON_FILTER |
 101				       IEEE80211_VIF_SUPPORTS_CQM_RSSI);
 102	}
 103 out_remove_mac:
 104	mvmvif->link[0] = NULL;
 105	iwl_mvm_mld_mac_ctxt_remove(mvm, vif);
 106 out_unlock:
 107	mutex_unlock(&mvm->mutex);
 108
 109	return ret;
 110}
 111
 112static void iwl_mvm_mld_mac_remove_interface(struct ieee80211_hw *hw,
 113					     struct ieee80211_vif *vif)
 114{
 115	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
 116	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 117	struct iwl_probe_resp_data *probe_data;
 118
 119	iwl_mvm_prepare_mac_removal(mvm, vif);
 120
 121	if (!(vif->type == NL80211_IFTYPE_AP ||
 122	      vif->type == NL80211_IFTYPE_ADHOC))
 123		iwl_mvm_tcm_rm_vif(mvm, vif);
 124
 125	mutex_lock(&mvm->mutex);
 126
 127	if (vif == mvm->csme_vif) {
 128		iwl_mei_set_netdev(NULL);
 129		mvm->csme_vif = NULL;
 130	}
 131
 132	if (mvm->bf_allowed_vif == mvmvif) {
 133		mvm->bf_allowed_vif = NULL;
 134		vif->driver_flags &= ~(IEEE80211_VIF_BEACON_FILTER |
 135				       IEEE80211_VIF_SUPPORTS_CQM_RSSI);
 136	}
 137
 138	if (vif->bss_conf.ftm_responder)
 139		memset(&mvm->ftm_resp_stats, 0, sizeof(mvm->ftm_resp_stats));
 140
 141	iwl_mvm_vif_dbgfs_rm_link(mvm, vif);
 142
 143	/* For AP/GO interface, the tear down of the resources allocated to the
 144	 * interface is be handled as part of the stop_ap flow.
 145	 */
 146	if (vif->type == NL80211_IFTYPE_AP ||
 147	    vif->type == NL80211_IFTYPE_ADHOC) {
 148#ifdef CONFIG_NL80211_TESTMODE
 149		if (vif == mvm->noa_vif) {
 150			mvm->noa_vif = NULL;
 151			mvm->noa_duration = 0;
 152		}
 153#endif
 154	}
 155
 156	iwl_mvm_power_update_mac(mvm);
 157
 158	/* Before the interface removal, mac80211 would cancel the ROC, and the
 159	 * ROC worker would be scheduled if needed. The worker would be flushed
 160	 * in iwl_mvm_prepare_mac_removal() and thus at this point the link is
 161	 * not active. So need only to remove the link.
 162	 */
 163	if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
 164		if (mvmvif->deflink.phy_ctxt) {
 165			iwl_mvm_phy_ctxt_unref(mvm, mvmvif->deflink.phy_ctxt);
 166			mvmvif->deflink.phy_ctxt = NULL;
 167		}
 168		mvm->p2p_device_vif = NULL;
 169		iwl_mvm_remove_link(mvm, vif, &vif->bss_conf);
 170	} else {
 171		iwl_mvm_disable_link(mvm, vif, &vif->bss_conf);
 172	}
 173
 174	iwl_mvm_mld_mac_ctxt_remove(mvm, vif);
 175
 176	RCU_INIT_POINTER(mvm->vif_id_to_mac[mvmvif->id], NULL);
 177
 178	probe_data = rcu_dereference_protected(mvmvif->deflink.probe_resp_data,
 179					       lockdep_is_held(&mvm->mutex));
 180	RCU_INIT_POINTER(mvmvif->deflink.probe_resp_data, NULL);
 181	if (probe_data)
 182		kfree_rcu(probe_data, rcu_head);
 183
 184	if (vif->type == NL80211_IFTYPE_MONITOR) {
 185		mvm->monitor_on = false;
 186		__clear_bit(IEEE80211_HW_RX_INCLUDES_FCS, mvm->hw->flags);
 187	}
 188
 189	mutex_unlock(&mvm->mutex);
 190}
 191
 192static unsigned int iwl_mvm_mld_count_active_links(struct ieee80211_vif *vif)
 193{
 194	unsigned int n_active = 0;
 195	int i;
 196
 197	for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
 198		struct ieee80211_bss_conf *link_conf;
 199
 200		link_conf = link_conf_dereference_protected(vif, i);
 201		if (link_conf &&
 202		    rcu_access_pointer(link_conf->chanctx_conf))
 203			n_active++;
 204	}
 205
 206	return n_active;
 207}
 208
 209static int iwl_mvm_esr_mode_active(struct iwl_mvm *mvm,
 210				   struct ieee80211_vif *vif)
 211{
 212	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 213	int link_id, ret = 0;
 214
 215	mvmvif->esr_active = true;
 216
 217	/* Indicate to mac80211 that EML is enabled */
 218	vif->driver_flags |= IEEE80211_VIF_EML_ACTIVE;
 219
 220	iwl_mvm_update_smps_on_active_links(mvm, vif, IWL_MVM_SMPS_REQ_FW,
 221					    IEEE80211_SMPS_OFF);
 222
 223	for_each_mvm_vif_valid_link(mvmvif, link_id) {
 224		struct iwl_mvm_vif_link_info *link = mvmvif->link[link_id];
 225
 226		if (!link->phy_ctxt)
 227			continue;
 228
 229		ret = iwl_mvm_phy_send_rlc(mvm, link->phy_ctxt, 2, 2);
 230		if (ret)
 231			break;
 232
 233		link->phy_ctxt->rlc_disabled = true;
 234	}
 235
 236	return ret;
 237}
 238
 239static int
 240__iwl_mvm_mld_assign_vif_chanctx(struct iwl_mvm *mvm,
 241				 struct ieee80211_vif *vif,
 242				 struct ieee80211_bss_conf *link_conf,
 243				 struct ieee80211_chanctx_conf *ctx,
 244				 bool switching_chanctx)
 245{
 246	u16 *phy_ctxt_id = (u16 *)ctx->drv_priv;
 247	struct iwl_mvm_phy_ctxt *phy_ctxt = &mvm->phy_ctxts[*phy_ctxt_id];
 248	unsigned int n_active = iwl_mvm_mld_count_active_links(vif);
 249	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 
 250	unsigned int link_id = link_conf->link_id;
 251	int ret;
 252
 253	/* if the assigned one was not counted yet, count it now */
 254	if (!rcu_access_pointer(link_conf->chanctx_conf))
 255		n_active++;
 256
 257	if (n_active > iwl_mvm_max_active_links(mvm, vif))
 258		return -EOPNOTSUPP;
 259
 260	if (WARN_ON_ONCE(!mvmvif->link[link_id]))
 261		return -EINVAL;
 262
 
 
 
 
 263	/* mac parameters such as HE support can change at this stage
 264	 * For sta, need first to configure correct state from drv_sta_state
 265	 * and only after that update mac config.
 266	 */
 267	if (vif->type == NL80211_IFTYPE_AP) {
 268		ret = iwl_mvm_mld_mac_ctxt_changed(mvm, vif, false);
 269		if (ret) {
 270			IWL_ERR(mvm, "failed to update MAC %pM\n", vif->addr);
 271			return -EINVAL;
 272		}
 273	}
 274
 275	mvmvif->link[link_id]->phy_ctxt = phy_ctxt;
 276
 277	if (iwl_mvm_is_esr_supported(mvm->fwrt.trans) && n_active > 1) {
 278		mvmvif->link[link_id]->listen_lmac = true;
 279		ret = iwl_mvm_esr_mode_active(mvm, vif);
 280		if (ret) {
 281			IWL_ERR(mvm, "failed to activate ESR mode (%d)\n", ret);
 282			goto out;
 283		}
 284	}
 285
 286	if (switching_chanctx) {
 287		/* reactivate if we turned this off during channel switch */
 288		if (vif->type == NL80211_IFTYPE_AP)
 289			mvmvif->ap_ibss_active = true;
 290	}
 291
 292	/* send it first with phy context ID */
 293	ret = iwl_mvm_link_changed(mvm, vif, link_conf, 0, false);
 294	if (ret)
 295		goto out;
 296
 297	/* Initialize rate control for the AP station, since we might be
 298	 * doing a link switch here - we cannot initialize it before since
 299	 * this needs the phy context assigned (and in FW?), and we cannot
 300	 * do it later because it needs to be initialized as soon as we're
 301	 * able to TX on the link, i.e. when active.
 302	 *
 303	 * Firmware restart isn't quite correct yet for MLO, but we don't
 304	 * need to do it in that case anyway since it will happen from the
 305	 * normal station state callback.
 306	 */
 307	if (mvmvif->ap_sta &&
 308	    !test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
 309		struct ieee80211_link_sta *link_sta;
 310
 311		rcu_read_lock();
 312		link_sta = rcu_dereference(mvmvif->ap_sta->link[link_id]);
 313
 314		if (!WARN_ON_ONCE(!link_sta))
 315			iwl_mvm_rs_rate_init(mvm, vif, mvmvif->ap_sta,
 316					     link_conf, link_sta,
 317					     phy_ctxt->channel->band);
 318		rcu_read_unlock();
 319	}
 320
 321	/* then activate */
 322	ret = iwl_mvm_link_changed(mvm, vif, link_conf,
 323				   LINK_CONTEXT_MODIFY_ACTIVE |
 324				   LINK_CONTEXT_MODIFY_RATES_INFO,
 325				   true);
 326	if (ret)
 327		goto out;
 328
 329	/*
 330	 * Power state must be updated before quotas,
 331	 * otherwise fw will complain.
 332	 */
 333	iwl_mvm_power_update_mac(mvm);
 334
 335	if (vif->type == NL80211_IFTYPE_MONITOR) {
 336		ret = iwl_mvm_mld_add_snif_sta(mvm, vif, link_conf);
 337		if (ret)
 338			goto deactivate;
 339	}
 340
 341	return 0;
 342
 343deactivate:
 344	iwl_mvm_link_changed(mvm, vif, link_conf, LINK_CONTEXT_MODIFY_ACTIVE,
 345			     false);
 346out:
 347	mvmvif->link[link_id]->phy_ctxt = NULL;
 348	iwl_mvm_power_update_mac(mvm);
 349	return ret;
 350}
 351
 352static int iwl_mvm_mld_assign_vif_chanctx(struct ieee80211_hw *hw,
 353					  struct ieee80211_vif *vif,
 354					  struct ieee80211_bss_conf *link_conf,
 355					  struct ieee80211_chanctx_conf *ctx)
 356{
 357	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
 358	int ret;
 359
 360	mutex_lock(&mvm->mutex);
 361	ret = __iwl_mvm_mld_assign_vif_chanctx(mvm, vif, link_conf, ctx, false);
 362	mutex_unlock(&mvm->mutex);
 363
 364	return ret;
 365}
 366
 367static int iwl_mvm_esr_mode_inactive(struct iwl_mvm *mvm,
 368				     struct ieee80211_vif *vif)
 369{
 370	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 371	struct ieee80211_bss_conf *link_conf;
 372	int link_id, ret = 0;
 373
 374	mvmvif->esr_active = false;
 375
 376	vif->driver_flags &= ~IEEE80211_VIF_EML_ACTIVE;
 377
 378	iwl_mvm_update_smps_on_active_links(mvm, vif, IWL_MVM_SMPS_REQ_FW,
 379					    IEEE80211_SMPS_AUTOMATIC);
 380
 381	for_each_vif_active_link(vif, link_conf, link_id) {
 382		struct ieee80211_chanctx_conf *chanctx_conf;
 383		struct iwl_mvm_phy_ctxt *phy_ctxt;
 384		u8 static_chains, dynamic_chains;
 385
 386		mvmvif->link[link_id]->listen_lmac = false;
 387
 388		rcu_read_lock();
 389
 390		chanctx_conf = rcu_dereference(link_conf->chanctx_conf);
 391		phy_ctxt = mvmvif->link[link_id]->phy_ctxt;
 392
 393		if (!chanctx_conf || !phy_ctxt) {
 394			rcu_read_unlock();
 395			continue;
 396		}
 397
 398		phy_ctxt->rlc_disabled = false;
 399		static_chains = chanctx_conf->rx_chains_static;
 400		dynamic_chains = chanctx_conf->rx_chains_dynamic;
 401
 402		rcu_read_unlock();
 403
 404		ret = iwl_mvm_phy_send_rlc(mvm, phy_ctxt, static_chains,
 405					   dynamic_chains);
 406		if (ret)
 407			break;
 408	}
 409
 410	return ret;
 411}
 412
 413static void
 414__iwl_mvm_mld_unassign_vif_chanctx(struct iwl_mvm *mvm,
 415				   struct ieee80211_vif *vif,
 416				   struct ieee80211_bss_conf *link_conf,
 417				   struct ieee80211_chanctx_conf *ctx,
 418				   bool switching_chanctx)
 419
 420{
 421	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 422	unsigned int n_active = iwl_mvm_mld_count_active_links(vif);
 423	unsigned int link_id = link_conf->link_id;
 424
 425	/* shouldn't happen, but verify link_id is valid before accessing */
 426	if (WARN_ON_ONCE(!mvmvif->link[link_id]))
 427		return;
 428
 429	if (vif->type == NL80211_IFTYPE_AP && switching_chanctx) {
 430		mvmvif->csa_countdown = false;
 431
 432		/* Set CS bit on all the stations */
 433		iwl_mvm_modify_all_sta_disable_tx(mvm, mvmvif, true);
 434
 435		/* Save blocked iface, the timeout is set on the next beacon */
 436		rcu_assign_pointer(mvm->csa_tx_blocked_vif, vif);
 437
 438		mvmvif->ap_ibss_active = false;
 439	}
 440
 441	iwl_mvm_link_changed(mvm, vif, link_conf,
 442			     LINK_CONTEXT_MODIFY_ACTIVE, false);
 443
 444	if (iwl_mvm_is_esr_supported(mvm->fwrt.trans) && n_active > 1) {
 445		int ret = iwl_mvm_esr_mode_inactive(mvm, vif);
 446
 447		if (ret)
 448			IWL_ERR(mvm, "failed to deactivate ESR mode (%d)\n",
 449				ret);
 450	}
 451
 452	if (vif->type == NL80211_IFTYPE_MONITOR)
 453		iwl_mvm_mld_rm_snif_sta(mvm, vif);
 454
 455	if (switching_chanctx)
 456		return;
 457	mvmvif->link[link_id]->phy_ctxt = NULL;
 458	iwl_mvm_power_update_mac(mvm);
 459}
 460
 461static void iwl_mvm_mld_unassign_vif_chanctx(struct ieee80211_hw *hw,
 462					     struct ieee80211_vif *vif,
 463					     struct ieee80211_bss_conf *link_conf,
 464					     struct ieee80211_chanctx_conf *ctx)
 465{
 466	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 467	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
 468
 469	mutex_lock(&mvm->mutex);
 470	__iwl_mvm_mld_unassign_vif_chanctx(mvm, vif, link_conf, ctx, false);
 471	/* in the non-MLD case, remove/re-add the link to clean up FW state */
 472	if (!ieee80211_vif_is_mld(vif) && !mvmvif->ap_sta &&
 473	    !WARN_ON_ONCE(vif->cfg.assoc)) {
 474		iwl_mvm_remove_link(mvm, vif, link_conf);
 475		iwl_mvm_add_link(mvm, vif, link_conf);
 476	}
 477	mutex_unlock(&mvm->mutex);
 478}
 479
 480static int iwl_mvm_mld_start_ap_ibss(struct ieee80211_hw *hw,
 481				     struct ieee80211_vif *vif,
 482				     struct ieee80211_bss_conf *link_conf)
 483{
 484	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
 485	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 486	int ret;
 487
 488	mutex_lock(&mvm->mutex);
 489	/* Send the beacon template */
 490	ret = iwl_mvm_mac_ctxt_beacon_changed(mvm, vif, link_conf);
 491	if (ret)
 492		goto out_unlock;
 493
 494	/* the link should be already activated when assigning chan context */
 495	ret = iwl_mvm_link_changed(mvm, vif, link_conf,
 496				   LINK_CONTEXT_MODIFY_ALL &
 497				   ~LINK_CONTEXT_MODIFY_ACTIVE,
 498				   true);
 499	if (ret)
 500		goto out_unlock;
 501
 502	ret = iwl_mvm_mld_add_mcast_sta(mvm, vif, link_conf);
 503	if (ret)
 504		goto out_unlock;
 505
 506	/* Send the bcast station. At this stage the TBTT and DTIM time
 507	 * events are added and applied to the scheduler
 508	 */
 509	ret = iwl_mvm_mld_add_bcast_sta(mvm, vif, link_conf);
 510	if (ret)
 511		goto out_rm_mcast;
 512
 513	if (iwl_mvm_start_ap_ibss_common(hw, vif, &ret))
 514		goto out_failed;
 515
 516	/* Need to update the P2P Device MAC (only GO, IBSS is single vif) */
 517	if (vif->p2p && mvm->p2p_device_vif)
 518		iwl_mvm_mld_mac_ctxt_changed(mvm, mvm->p2p_device_vif, false);
 519
 520	iwl_mvm_bt_coex_vif_change(mvm);
 521
 522	/* we don't support TDLS during DCM */
 523	if (iwl_mvm_phy_ctx_count(mvm) > 1)
 524		iwl_mvm_teardown_tdls_peers(mvm);
 525
 526	iwl_mvm_ftm_restart_responder(mvm, vif, link_conf);
 527
 528	goto out_unlock;
 529
 530out_failed:
 531	iwl_mvm_power_update_mac(mvm);
 532	mvmvif->ap_ibss_active = false;
 533	iwl_mvm_mld_rm_bcast_sta(mvm, vif, link_conf);
 534out_rm_mcast:
 535	iwl_mvm_mld_rm_mcast_sta(mvm, vif, link_conf);
 536out_unlock:
 537	mutex_unlock(&mvm->mutex);
 538	return ret;
 539}
 540
 541static int iwl_mvm_mld_start_ap(struct ieee80211_hw *hw,
 542				struct ieee80211_vif *vif,
 543				struct ieee80211_bss_conf *link_conf)
 544{
 545	return iwl_mvm_mld_start_ap_ibss(hw, vif, link_conf);
 546}
 547
 548static int iwl_mvm_mld_start_ibss(struct ieee80211_hw *hw,
 549				  struct ieee80211_vif *vif)
 550{
 551	return iwl_mvm_mld_start_ap_ibss(hw, vif, &vif->bss_conf);
 552}
 553
 554static void iwl_mvm_mld_stop_ap_ibss(struct ieee80211_hw *hw,
 555				     struct ieee80211_vif *vif,
 556				     struct ieee80211_bss_conf *link_conf)
 557{
 558	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
 559
 560	mutex_lock(&mvm->mutex);
 561
 562	iwl_mvm_stop_ap_ibss_common(mvm, vif);
 563
 564	/* Need to update the P2P Device MAC (only GO, IBSS is single vif) */
 565	if (vif->p2p && mvm->p2p_device_vif)
 566		iwl_mvm_mld_mac_ctxt_changed(mvm, mvm->p2p_device_vif, false);
 567
 568	iwl_mvm_ftm_responder_clear(mvm, vif);
 569
 570	iwl_mvm_mld_rm_bcast_sta(mvm, vif, link_conf);
 571	iwl_mvm_mld_rm_mcast_sta(mvm, vif, link_conf);
 572
 573	iwl_mvm_power_update_mac(mvm);
 574	mutex_unlock(&mvm->mutex);
 575}
 576
 577static void iwl_mvm_mld_stop_ap(struct ieee80211_hw *hw,
 578				struct ieee80211_vif *vif,
 579				struct ieee80211_bss_conf *link_conf)
 580{
 581	iwl_mvm_mld_stop_ap_ibss(hw, vif, link_conf);
 582}
 583
 584static void iwl_mvm_mld_stop_ibss(struct ieee80211_hw *hw,
 585				  struct ieee80211_vif *vif)
 586{
 587	iwl_mvm_mld_stop_ap_ibss(hw, vif, &vif->bss_conf);
 588}
 589
 590static int iwl_mvm_mld_mac_sta_state(struct ieee80211_hw *hw,
 591				     struct ieee80211_vif *vif,
 592				     struct ieee80211_sta *sta,
 593				     enum ieee80211_sta_state old_state,
 594				     enum ieee80211_sta_state new_state)
 595{
 596	static const struct iwl_mvm_sta_state_ops callbacks = {
 597		.add_sta = iwl_mvm_mld_add_sta,
 598		.update_sta = iwl_mvm_mld_update_sta,
 599		.rm_sta = iwl_mvm_mld_rm_sta,
 600		.mac_ctxt_changed = iwl_mvm_mld_mac_ctxt_changed,
 601	};
 602
 603	return iwl_mvm_mac_sta_state_common(hw, vif, sta, old_state, new_state,
 604					    &callbacks);
 605}
 606
 607struct iwl_mvm_link_sel_data {
 608	u8 link_id;
 609	enum nl80211_band band;
 
 610	bool active;
 611};
 612
 613static bool iwl_mvm_mld_valid_link_pair(struct iwl_mvm_link_sel_data *a,
 
 614					struct iwl_mvm_link_sel_data *b)
 615{
 616	return a->band != b->band;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 617}
 618
 619void iwl_mvm_mld_select_links(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 620			      bool valid_links_changed)
 621{
 622	struct iwl_mvm_link_sel_data data[IEEE80211_MLD_MAX_NUM_LINKS];
 623	unsigned long usable_links = ieee80211_vif_usable_links(vif);
 624	u32 max_active_links = iwl_mvm_max_active_links(mvm, vif);
 625	u16 new_active_links;
 626	u8 link_id, n_data = 0, i, j;
 627
 628	if (!IWL_MVM_AUTO_EML_ENABLE)
 629		return;
 630
 631	if (!ieee80211_vif_is_mld(vif) || usable_links == 1)
 632		return;
 633
 634	/* The logic below is a simple version that doesn't suit more than 2
 635	 * links
 636	 */
 637	WARN_ON_ONCE(max_active_links > 2);
 638
 639	/* if only a single active link is supported, assume that the one
 640	 * selected by higher layer for connection establishment is the best.
 641	 */
 642	if (max_active_links == 1 && !valid_links_changed)
 643		return;
 644
 645	/* If we are already using the maximal number of active links, don't do
 646	 * any change. This can later be optimized to pick a 'better' link pair.
 647	 */
 648	if (hweight16(vif->active_links) == max_active_links)
 649		return;
 650
 651	rcu_read_lock();
 652
 653	for_each_set_bit(link_id, &usable_links, IEEE80211_MLD_MAX_NUM_LINKS) {
 654		struct ieee80211_bss_conf *link_conf =
 655			rcu_dereference(vif->link_conf[link_id]);
 656
 657		if (WARN_ON_ONCE(!link_conf))
 658			continue;
 659
 660		data[n_data].link_id = link_id;
 661		data[n_data].band = link_conf->chandef.chan->band;
 662		data[n_data].active = vif->active_links & BIT(link_id);
 663		n_data++;
 664	}
 665
 666	rcu_read_unlock();
 667
 668	/* this is expected to be the current active link */
 669	if (n_data == 1)
 670		return;
 671
 672	new_active_links = 0;
 673
 674	/* Assume that after association only a single link is active, thus,
 675	 * select only the 2nd link
 676	 */
 677	if (!valid_links_changed) {
 678		for (i = 0; i < n_data; i++) {
 679			if (data[i].active)
 680				break;
 681		}
 682
 683		if (WARN_ON_ONCE(i == n_data))
 684			return;
 685
 686		for (j = 0; j < n_data; j++) {
 687			if (i == j)
 688				continue;
 689
 690			if (iwl_mvm_mld_valid_link_pair(&data[i], &data[j]))
 
 691				break;
 692		}
 693
 694		if (j != n_data)
 695			new_active_links = BIT(data[i].link_id) |
 696				BIT(data[j].link_id);
 697	} else {
 698		/* Try to find a valid link pair for EMLSR operation. If a pair
 699		 * is not found continue using the current active link.
 700		 */
 701		for (i = 0; i < n_data; i++) {
 702			for (j = 0; j < n_data; j++) {
 703				if (i == j)
 704					continue;
 705
 706				if (iwl_mvm_mld_valid_link_pair(&data[i],
 707								&data[j]))
 708					break;
 709			}
 710
 711			/* found a valid pair for EMLSR, use it */
 712			if (j != n_data) {
 713				new_active_links = BIT(data[i].link_id) |
 714					BIT(data[j].link_id);
 715				break;
 716			}
 717		}
 718	}
 719
 720	if (!new_active_links)
 721		return;
 722
 723	if (vif->active_links != new_active_links)
 724		ieee80211_set_active_links_async(vif, new_active_links);
 725}
 726
 727static void
 728iwl_mvm_mld_link_info_changed_station(struct iwl_mvm *mvm,
 729				      struct ieee80211_vif *vif,
 730				      struct ieee80211_bss_conf *link_conf,
 731				      u64 changes)
 732{
 733	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 734	bool has_he, has_eht;
 735	u32 link_changes = 0;
 736	int ret;
 737
 738	if (WARN_ON_ONCE(!mvmvif->link[link_conf->link_id]))
 739		return;
 740
 741	has_he = link_conf->he_support && !iwlwifi_mod_params.disable_11ax;
 742	has_eht = link_conf->eht_support && !iwlwifi_mod_params.disable_11be;
 743
 744	/* Update EDCA params */
 745	if (changes & BSS_CHANGED_QOS && vif->cfg.assoc && link_conf->qos)
 746		link_changes |= LINK_CONTEXT_MODIFY_QOS_PARAMS;
 747
 748	if (changes & BSS_CHANGED_ERP_SLOT)
 749		link_changes |= LINK_CONTEXT_MODIFY_RATES_INFO;
 750
 751	if (vif->cfg.assoc && (has_he || has_eht)) {
 752		IWL_DEBUG_MAC80211(mvm, "Associated in HE mode\n");
 753		link_changes |= LINK_CONTEXT_MODIFY_HE_PARAMS;
 754	}
 755
 756	/* Update EHT Puncturing info */
 757	if (changes & BSS_CHANGED_EHT_PUNCTURING && vif->cfg.assoc)
 758		link_changes |= LINK_CONTEXT_MODIFY_EHT_PARAMS;
 759
 760	if (link_changes) {
 761		ret = iwl_mvm_link_changed(mvm, vif, link_conf, link_changes,
 762					   true);
 763		if (ret)
 764			IWL_ERR(mvm, "failed to update link\n");
 765	}
 766
 767	ret = iwl_mvm_mld_mac_ctxt_changed(mvm, vif, false);
 768	if (ret)
 769		IWL_ERR(mvm, "failed to update MAC %pM\n", vif->addr);
 770
 771	if (changes & BSS_CHANGED_MLD_VALID_LINKS)
 772		iwl_mvm_mld_select_links(mvm, vif, true);
 773
 774	memcpy(mvmvif->link[link_conf->link_id]->bssid, link_conf->bssid,
 775	       ETH_ALEN);
 776
 777	iwl_mvm_bss_info_changed_station_common(mvm, vif, link_conf, changes);
 778}
 779
 780static bool iwl_mvm_mld_vif_have_valid_ap_sta(struct iwl_mvm_vif *mvmvif)
 781{
 782	int i;
 783
 784	for_each_mvm_vif_valid_link(mvmvif, i) {
 785		if (mvmvif->link[i]->ap_sta_id != IWL_MVM_INVALID_STA)
 786			return true;
 787	}
 788
 789	return false;
 790}
 791
 792static void iwl_mvm_mld_vif_delete_all_stas(struct iwl_mvm *mvm,
 793					    struct ieee80211_vif *vif)
 794{
 795	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 796	int i, ret;
 797
 798	if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
 799		return;
 800
 801	for_each_mvm_vif_valid_link(mvmvif, i) {
 802		struct iwl_mvm_vif_link_info *link = mvmvif->link[i];
 803
 804		if (!link)
 805			continue;
 806
 807		iwl_mvm_sec_key_remove_ap(mvm, vif, link, i);
 808		ret = iwl_mvm_mld_rm_sta_id(mvm, link->ap_sta_id);
 809		if (ret)
 810			IWL_ERR(mvm, "failed to remove AP station\n");
 811
 812		link->ap_sta_id = IWL_MVM_INVALID_STA;
 813	}
 814}
 815
 816static void iwl_mvm_mld_vif_cfg_changed_station(struct iwl_mvm *mvm,
 817						struct ieee80211_vif *vif,
 818						u64 changes)
 819{
 820	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 821	struct ieee80211_bss_conf *link_conf;
 822	bool protect = false;
 823	unsigned int i;
 824	int ret;
 825
 826	/* This might get called without active links during the
 827	 * chanctx switch, but we don't care about it anyway.
 828	 */
 829	if (changes == BSS_CHANGED_IDLE)
 830		return;
 831
 832	ret = iwl_mvm_mld_mac_ctxt_changed(mvm, vif, false);
 833	if (ret)
 834		IWL_ERR(mvm, "failed to update MAC %pM\n", vif->addr);
 835
 836	mvmvif->associated = vif->cfg.assoc;
 837
 838	if (changes & BSS_CHANGED_ASSOC) {
 839		if (vif->cfg.assoc) {
 840			/* clear statistics to get clean beacon counter */
 841			iwl_mvm_request_statistics(mvm, true);
 842			iwl_mvm_sf_update(mvm, vif, false);
 843			iwl_mvm_power_vif_assoc(mvm, vif);
 844
 845			for_each_mvm_vif_valid_link(mvmvif, i) {
 846				memset(&mvmvif->link[i]->beacon_stats, 0,
 847				       sizeof(mvmvif->link[i]->beacon_stats));
 848
 849				if (vif->p2p) {
 850					iwl_mvm_update_smps(mvm, vif,
 851							    IWL_MVM_SMPS_REQ_PROT,
 852							    IEEE80211_SMPS_DYNAMIC, i);
 853				}
 854
 855				rcu_read_lock();
 856				link_conf = rcu_dereference(vif->link_conf[i]);
 857				if (link_conf && !link_conf->dtim_period)
 858					protect = true;
 859				rcu_read_unlock();
 860			}
 861
 862			if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) &&
 863			    protect) {
 864				/* We are in assoc so only one link is active-
 865				 * The association link
 866				 */
 867				unsigned int link_id =
 868					ffs(vif->active_links) - 1;
 869
 870				/* If we're not restarting and still haven't
 871				 * heard a beacon (dtim period unknown) then
 872				 * make sure we still have enough minimum time
 873				 * remaining in the time event, since the auth
 874				 * might actually have taken quite a while
 875				 * (especially for SAE) and so the remaining
 876				 * time could be small without us having heard
 877				 * a beacon yet.
 878				 */
 879				iwl_mvm_protect_assoc(mvm, vif, 0, link_id);
 880			}
 881
 882			iwl_mvm_sf_update(mvm, vif, false);
 883
 884			/* FIXME: need to decide about misbehaving AP handling */
 885			iwl_mvm_power_vif_assoc(mvm, vif);
 886		} else if (iwl_mvm_mld_vif_have_valid_ap_sta(mvmvif)) {
 887			iwl_mvm_mei_host_disassociated(mvm);
 888
 889			/* If update fails - SF might be running in associated
 890			 * mode while disassociated - which is forbidden.
 891			 */
 892			ret = iwl_mvm_sf_update(mvm, vif, false);
 893			WARN_ONCE(ret &&
 894				  !test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED,
 895					    &mvm->status),
 896				  "Failed to update SF upon disassociation\n");
 897
 898			/* If we get an assert during the connection (after the
 899			 * station has been added, but before the vif is set
 900			 * to associated), mac80211 will re-add the station and
 901			 * then configure the vif. Since the vif is not
 902			 * associated, we would remove the station here and
 903			 * this would fail the recovery.
 904			 */
 905			iwl_mvm_mld_vif_delete_all_stas(mvm, vif);
 906		}
 907
 908		iwl_mvm_bss_info_changed_station_assoc(mvm, vif, changes);
 909	}
 910
 911	if (changes & BSS_CHANGED_PS) {
 912		ret = iwl_mvm_power_update_mac(mvm);
 913		if (ret)
 914			IWL_ERR(mvm, "failed to update power mode\n");
 915	}
 916}
 917
 918static void
 919iwl_mvm_mld_link_info_changed_ap_ibss(struct iwl_mvm *mvm,
 920				      struct ieee80211_vif *vif,
 921				      struct ieee80211_bss_conf *link_conf,
 922				      u64 changes)
 923{
 924	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 925	u32 link_changes = LINK_CONTEXT_MODIFY_PROTECT_FLAGS |
 926			   LINK_CONTEXT_MODIFY_QOS_PARAMS;
 927
 928	/* Changes will be applied when the AP/IBSS is started */
 929	if (!mvmvif->ap_ibss_active)
 930		return;
 931
 932	if (link_conf->he_support)
 933		link_changes |= LINK_CONTEXT_MODIFY_HE_PARAMS;
 934
 935	if (changes & BSS_CHANGED_ERP_SLOT)
 936		link_changes |= LINK_CONTEXT_MODIFY_RATES_INFO;
 937
 938	if (changes & (BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_ERP_SLOT |
 939		       BSS_CHANGED_HT |
 940		       BSS_CHANGED_BANDWIDTH | BSS_CHANGED_QOS |
 941		       BSS_CHANGED_HE_BSS_COLOR) &&
 942		       iwl_mvm_link_changed(mvm, vif, link_conf,
 943					    link_changes, true))
 944		IWL_ERR(mvm, "failed to update MAC %pM\n", vif->addr);
 945
 946	/* Need to send a new beacon template to the FW */
 947	if (changes & BSS_CHANGED_BEACON &&
 948	    iwl_mvm_mac_ctxt_beacon_changed(mvm, vif, link_conf))
 949		IWL_WARN(mvm, "Failed updating beacon data\n");
 950
 951	/* FIXME: need to decide if we need FTM responder per link */
 952	if (changes & BSS_CHANGED_FTM_RESPONDER) {
 953		int ret = iwl_mvm_ftm_start_responder(mvm, vif, link_conf);
 954
 955		if (ret)
 956			IWL_WARN(mvm, "Failed to enable FTM responder (%d)\n",
 957				 ret);
 958	}
 959}
 960
 961static void iwl_mvm_mld_link_info_changed(struct ieee80211_hw *hw,
 962					  struct ieee80211_vif *vif,
 963					  struct ieee80211_bss_conf *link_conf,
 964					  u64 changes)
 965{
 966	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
 967
 968	mutex_lock(&mvm->mutex);
 969
 970	switch (vif->type) {
 971	case NL80211_IFTYPE_STATION:
 972		iwl_mvm_mld_link_info_changed_station(mvm, vif, link_conf,
 973						      changes);
 974		break;
 975	case NL80211_IFTYPE_AP:
 976	case NL80211_IFTYPE_ADHOC:
 977		iwl_mvm_mld_link_info_changed_ap_ibss(mvm, vif, link_conf,
 978						      changes);
 979		break;
 980	case NL80211_IFTYPE_MONITOR:
 981		if (changes & BSS_CHANGED_MU_GROUPS)
 982			iwl_mvm_update_mu_groups(mvm, vif);
 983		break;
 984	default:
 985		/* shouldn't happen */
 986		WARN_ON_ONCE(1);
 987	}
 988
 989	if (changes & BSS_CHANGED_TXPOWER) {
 990		IWL_DEBUG_CALIB(mvm, "Changing TX Power to %d dBm\n",
 991				link_conf->txpower);
 992		iwl_mvm_set_tx_power(mvm, vif, link_conf->txpower);
 993	}
 994
 995	mutex_unlock(&mvm->mutex);
 996}
 997
 998static void iwl_mvm_mld_vif_cfg_changed(struct ieee80211_hw *hw,
 999					struct ieee80211_vif *vif,
1000					u64 changes)
1001{
1002	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
1003
1004	mutex_lock(&mvm->mutex);
1005
1006	if (changes & BSS_CHANGED_IDLE && !vif->cfg.idle)
1007		iwl_mvm_scan_stop(mvm, IWL_MVM_SCAN_SCHED, true);
1008
1009	if (vif->type == NL80211_IFTYPE_STATION)
1010		iwl_mvm_mld_vif_cfg_changed_station(mvm, vif, changes);
1011
1012	mutex_unlock(&mvm->mutex);
1013}
1014
1015static int
1016iwl_mvm_mld_switch_vif_chanctx(struct ieee80211_hw *hw,
1017			       struct ieee80211_vif_chanctx_switch *vifs,
1018			       int n_vifs,
1019			       enum ieee80211_chanctx_switch_mode mode)
1020{
1021	static const struct iwl_mvm_switch_vif_chanctx_ops ops = {
1022		.__assign_vif_chanctx = __iwl_mvm_mld_assign_vif_chanctx,
1023		.__unassign_vif_chanctx = __iwl_mvm_mld_unassign_vif_chanctx,
1024	};
1025
1026	return iwl_mvm_switch_vif_chanctx_common(hw, vifs, n_vifs, mode, &ops);
1027}
1028
1029static void iwl_mvm_mld_config_iface_filter(struct ieee80211_hw *hw,
1030					    struct ieee80211_vif *vif,
1031					    unsigned int filter_flags,
1032					    unsigned int changed_flags)
1033{
1034	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
1035
1036	/* We support only filter for probe requests */
1037	if (!(changed_flags & FIF_PROBE_REQ))
1038		return;
1039
1040	/* Supported only for p2p client interfaces */
1041	if (vif->type != NL80211_IFTYPE_STATION || !vif->cfg.assoc ||
1042	    !vif->p2p)
1043		return;
1044
1045	mutex_lock(&mvm->mutex);
1046	iwl_mvm_mld_mac_ctxt_changed(mvm, vif, false);
1047	mutex_unlock(&mvm->mutex);
1048}
1049
1050static int
1051iwl_mvm_mld_mac_conf_tx(struct ieee80211_hw *hw,
1052			struct ieee80211_vif *vif,
1053			unsigned int link_id, u16 ac,
1054			const struct ieee80211_tx_queue_params *params)
1055{
1056	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
1057	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1058	struct iwl_mvm_vif_link_info *mvm_link = mvmvif->link[link_id];
1059
1060	if (!mvm_link)
1061		return -EINVAL;
1062
1063	mvm_link->queue_params[ac] = *params;
1064
1065	/* No need to update right away, we'll get BSS_CHANGED_QOS
1066	 * The exception is P2P_DEVICE interface which needs immediate update.
1067	 */
1068	if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
1069		int ret;
1070
1071		mutex_lock(&mvm->mutex);
1072		ret = iwl_mvm_link_changed(mvm, vif, &vif->bss_conf,
1073					   LINK_CONTEXT_MODIFY_QOS_PARAMS,
1074					   true);
1075		mutex_unlock(&mvm->mutex);
1076		return ret;
1077	}
1078	return 0;
1079}
1080
1081static int iwl_mvm_mld_roc_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
1082{
1083	int ret;
1084
1085	lockdep_assert_held(&mvm->mutex);
1086
1087	/* The PHY context ID might have changed so need to set it */
1088	ret = iwl_mvm_link_changed(mvm, vif, &vif->bss_conf, 0, false);
1089	if (WARN(ret, "Failed to set PHY context ID\n"))
1090		return ret;
1091
1092	ret = iwl_mvm_link_changed(mvm, vif, &vif->bss_conf,
1093				   LINK_CONTEXT_MODIFY_ACTIVE |
1094				   LINK_CONTEXT_MODIFY_RATES_INFO,
1095				   true);
1096
1097	if (WARN(ret, "Failed linking P2P_DEVICE\n"))
1098		return ret;
1099
1100	/* The station and queue allocation must be done only after the linking
1101	 * is done, as otherwise the FW might incorrectly configure its state.
1102	 */
1103	return iwl_mvm_mld_add_bcast_sta(mvm, vif, &vif->bss_conf);
1104}
1105
1106static int iwl_mvm_mld_roc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
1107			   struct ieee80211_channel *channel, int duration,
1108			   enum ieee80211_roc_type type)
1109{
1110	static const struct iwl_mvm_roc_ops ops = {
1111		.add_aux_sta_for_hs20 = iwl_mvm_mld_add_aux_sta,
1112		.link = iwl_mvm_mld_roc_link,
1113	};
1114
1115	return iwl_mvm_roc_common(hw, vif, channel, duration, type, &ops);
1116}
1117
1118static int
1119iwl_mvm_mld_change_vif_links(struct ieee80211_hw *hw,
1120			     struct ieee80211_vif *vif,
1121			     u16 old_links, u16 new_links,
1122			     struct ieee80211_bss_conf *old[IEEE80211_MLD_MAX_NUM_LINKS])
1123{
1124	struct iwl_mvm_vif_link_info *new_link[IEEE80211_MLD_MAX_NUM_LINKS] = {};
1125	unsigned int n_active = iwl_mvm_mld_count_active_links(vif);
1126	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1127	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
1128	u16 removed = old_links & ~new_links;
1129	u16 added = new_links & ~old_links;
1130	int err, i;
1131
1132	if (hweight16(new_links) > 1 &&
1133	    n_active > iwl_mvm_max_active_links(mvm, vif))
1134		return -EOPNOTSUPP;
1135
1136	for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
1137		int r;
1138
1139		if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
1140			break;
1141
1142		if (!(added & BIT(i)))
1143			continue;
1144		new_link[i] = kzalloc(sizeof(*new_link[i]), GFP_KERNEL);
1145		if (!new_link[i]) {
1146			err = -ENOMEM;
1147			goto free;
1148		}
1149
1150		new_link[i]->bcast_sta.sta_id = IWL_MVM_INVALID_STA;
1151		new_link[i]->mcast_sta.sta_id = IWL_MVM_INVALID_STA;
1152		new_link[i]->ap_sta_id = IWL_MVM_INVALID_STA;
1153		new_link[i]->fw_link_id = IWL_MVM_FW_LINK_ID_INVALID;
1154
1155		for (r = 0; r < NUM_IWL_MVM_SMPS_REQ; r++)
1156			new_link[i]->smps_requests[r] =
1157				IEEE80211_SMPS_AUTOMATIC;
1158	}
1159
1160	mutex_lock(&mvm->mutex);
1161
1162	if (old_links == 0) {
1163		err = iwl_mvm_disable_link(mvm, vif, &vif->bss_conf);
1164		if (err)
1165			goto out_err;
1166		mvmvif->link[0] = NULL;
1167	}
1168
1169	for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
1170		if (removed & BIT(i)) {
1171			struct ieee80211_bss_conf *link_conf = old[i];
1172
1173			err = iwl_mvm_disable_link(mvm, vif, link_conf);
1174			if (err)
1175				goto out_err;
1176			kfree(mvmvif->link[i]);
1177			mvmvif->link[i] = NULL;
1178		} else if (added & BIT(i)) {
1179			struct ieee80211_bss_conf *link_conf;
1180
1181			link_conf = link_conf_dereference_protected(vif, i);
1182			if (WARN_ON(!link_conf))
1183				continue;
1184
1185			if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART,
1186				      &mvm->status))
1187				mvmvif->link[i] = new_link[i];
1188			new_link[i] = NULL;
1189			err = iwl_mvm_add_link(mvm, vif, link_conf);
1190			if (err)
1191				goto out_err;
1192		}
1193	}
1194
1195	err = 0;
1196	if (new_links == 0) {
1197		mvmvif->link[0] = &mvmvif->deflink;
1198		err = iwl_mvm_add_link(mvm, vif, &vif->bss_conf);
1199	}
1200
1201out_err:
1202	/* we really don't have a good way to roll back here ... */
1203	mutex_unlock(&mvm->mutex);
1204
1205free:
1206	for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++)
1207		kfree(new_link[i]);
1208	return err;
1209}
1210
1211static int
1212iwl_mvm_mld_change_sta_links(struct ieee80211_hw *hw,
1213			     struct ieee80211_vif *vif,
1214			     struct ieee80211_sta *sta,
1215			     u16 old_links, u16 new_links)
1216{
1217	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
1218	int ret;
1219
1220	mutex_lock(&mvm->mutex);
1221	ret = iwl_mvm_mld_update_sta_links(mvm, vif, sta, old_links, new_links);
1222	mutex_unlock(&mvm->mutex);
1223
1224	return ret;
1225}
1226
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1227const struct ieee80211_ops iwl_mvm_mld_hw_ops = {
1228	.tx = iwl_mvm_mac_tx,
1229	.wake_tx_queue = iwl_mvm_mac_wake_tx_queue,
1230	.ampdu_action = iwl_mvm_mac_ampdu_action,
1231	.get_antenna = iwl_mvm_op_get_antenna,
1232	.set_antenna = iwl_mvm_op_set_antenna,
1233	.start = iwl_mvm_mac_start,
1234	.reconfig_complete = iwl_mvm_mac_reconfig_complete,
1235	.stop = iwl_mvm_mac_stop,
1236	.add_interface = iwl_mvm_mld_mac_add_interface,
1237	.remove_interface = iwl_mvm_mld_mac_remove_interface,
1238	.config = iwl_mvm_mac_config,
1239	.prepare_multicast = iwl_mvm_prepare_multicast,
1240	.configure_filter = iwl_mvm_configure_filter,
1241	.config_iface_filter = iwl_mvm_mld_config_iface_filter,
1242	.link_info_changed = iwl_mvm_mld_link_info_changed,
1243	.vif_cfg_changed = iwl_mvm_mld_vif_cfg_changed,
1244	.hw_scan = iwl_mvm_mac_hw_scan,
1245	.cancel_hw_scan = iwl_mvm_mac_cancel_hw_scan,
1246	.sta_pre_rcu_remove = iwl_mvm_sta_pre_rcu_remove,
1247	.sta_state = iwl_mvm_mld_mac_sta_state,
1248	.sta_notify = iwl_mvm_mac_sta_notify,
1249	.allow_buffered_frames = iwl_mvm_mac_allow_buffered_frames,
1250	.release_buffered_frames = iwl_mvm_mac_release_buffered_frames,
1251	.set_rts_threshold = iwl_mvm_mac_set_rts_threshold,
1252	.sta_rc_update = iwl_mvm_sta_rc_update,
1253	.conf_tx = iwl_mvm_mld_mac_conf_tx,
1254	.mgd_prepare_tx = iwl_mvm_mac_mgd_prepare_tx,
1255	.mgd_complete_tx = iwl_mvm_mac_mgd_complete_tx,
1256	.mgd_protect_tdls_discover = iwl_mvm_mac_mgd_protect_tdls_discover,
1257	.flush = iwl_mvm_mac_flush,
1258	.flush_sta = iwl_mvm_mac_flush_sta,
1259	.sched_scan_start = iwl_mvm_mac_sched_scan_start,
1260	.sched_scan_stop = iwl_mvm_mac_sched_scan_stop,
1261	.set_key = iwl_mvm_mac_set_key,
1262	.update_tkip_key = iwl_mvm_mac_update_tkip_key,
1263	.remain_on_channel = iwl_mvm_mld_roc,
1264	.cancel_remain_on_channel = iwl_mvm_cancel_roc,
1265	.add_chanctx = iwl_mvm_add_chanctx,
1266	.remove_chanctx = iwl_mvm_remove_chanctx,
1267	.change_chanctx = iwl_mvm_change_chanctx,
1268	.assign_vif_chanctx = iwl_mvm_mld_assign_vif_chanctx,
1269	.unassign_vif_chanctx = iwl_mvm_mld_unassign_vif_chanctx,
1270	.switch_vif_chanctx = iwl_mvm_mld_switch_vif_chanctx,
1271
1272	.start_ap = iwl_mvm_mld_start_ap,
1273	.stop_ap = iwl_mvm_mld_stop_ap,
1274	.join_ibss = iwl_mvm_mld_start_ibss,
1275	.leave_ibss = iwl_mvm_mld_stop_ibss,
1276
1277	.tx_last_beacon = iwl_mvm_tx_last_beacon,
1278
1279	.channel_switch = iwl_mvm_channel_switch,
1280	.pre_channel_switch = iwl_mvm_pre_channel_switch,
1281	.post_channel_switch = iwl_mvm_post_channel_switch,
1282	.abort_channel_switch = iwl_mvm_abort_channel_switch,
1283	.channel_switch_rx_beacon = iwl_mvm_channel_switch_rx_beacon,
1284
1285	.tdls_channel_switch = iwl_mvm_tdls_channel_switch,
1286	.tdls_cancel_channel_switch = iwl_mvm_tdls_cancel_channel_switch,
1287	.tdls_recv_channel_switch = iwl_mvm_tdls_recv_channel_switch,
1288
1289	.event_callback = iwl_mvm_mac_event_callback,
1290
1291	.sync_rx_queues = iwl_mvm_sync_rx_queues,
1292
1293	CFG80211_TESTMODE_CMD(iwl_mvm_mac_testmode_cmd)
1294
1295#ifdef CONFIG_PM_SLEEP
1296	/* look at d3.c */
1297	.suspend = iwl_mvm_suspend,
1298	.resume = iwl_mvm_resume,
1299	.set_wakeup = iwl_mvm_set_wakeup,
1300	.set_rekey_data = iwl_mvm_set_rekey_data,
1301#if IS_ENABLED(CONFIG_IPV6)
1302	.ipv6_addr_change = iwl_mvm_ipv6_addr_change,
1303#endif
1304	.set_default_unicast_key = iwl_mvm_set_default_unicast_key,
1305#endif
1306	.get_survey = iwl_mvm_mac_get_survey,
1307	.sta_statistics = iwl_mvm_mac_sta_statistics,
1308	.get_ftm_responder_stats = iwl_mvm_mac_get_ftm_responder_stats,
1309	.start_pmsr = iwl_mvm_start_pmsr,
1310	.abort_pmsr = iwl_mvm_abort_pmsr,
1311
1312#ifdef CONFIG_IWLWIFI_DEBUGFS
1313	.vif_add_debugfs = iwl_mvm_vif_add_debugfs,
1314	.link_add_debugfs = iwl_mvm_link_add_debugfs,
1315	.link_sta_add_debugfs = iwl_mvm_link_sta_add_debugfs,
1316#endif
1317	.set_hw_timestamp = iwl_mvm_set_hw_timestamp,
1318
1319	.change_vif_links = iwl_mvm_mld_change_vif_links,
1320	.change_sta_links = iwl_mvm_mld_change_sta_links,
 
 
1321};
v6.9.4
   1// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
   2/*
   3 * Copyright (C) 2022-2024 Intel Corporation
   4 */
   5#include "mvm.h"
   6
   7static int iwl_mvm_mld_mac_add_interface(struct ieee80211_hw *hw,
   8					 struct ieee80211_vif *vif)
   9{
  10	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
  11	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
  12	int ret;
  13	int i;
  14
  15	mutex_lock(&mvm->mutex);
  16
  17	iwl_mvm_mac_init_mvmvif(mvm, mvmvif);
  18
  19	mvmvif->mvm = mvm;
  20
  21	/* Not much to do here. The stack will not allow interface
  22	 * types or combinations that we didn't advertise, so we
  23	 * don't really have to check the types.
  24	 */
  25
  26	/* make sure that beacon statistics don't go backwards with FW reset */
  27	if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
  28		for_each_mvm_vif_valid_link(mvmvif, i)
  29			mvmvif->link[i]->beacon_stats.accu_num_beacons +=
  30				mvmvif->link[i]->beacon_stats.num_beacons;
  31
  32	/* Allocate resources for the MAC context, and add it to the fw  */
  33	ret = iwl_mvm_mac_ctxt_init(mvm, vif);
  34	if (ret)
  35		goto out_unlock;
  36
  37	rcu_assign_pointer(mvm->vif_id_to_mac[mvmvif->id], vif);
  38
  39	mvmvif->features |= hw->netdev_features;
  40
  41	/* reset deflink MLO parameters */
  42	mvmvif->deflink.fw_link_id = IWL_MVM_FW_LINK_ID_INVALID;
  43	mvmvif->deflink.active = 0;
  44	/* the first link always points to the default one */
  45	mvmvif->link[0] = &mvmvif->deflink;
  46
  47	ret = iwl_mvm_mld_mac_ctxt_add(mvm, vif);
  48	if (ret)
  49		goto out_unlock;
  50
  51	/* beacon filtering */
  52	ret = iwl_mvm_disable_beacon_filter(mvm, vif);
  53	if (ret)
  54		goto out_remove_mac;
  55
  56	if (!mvm->bf_allowed_vif &&
  57	    vif->type == NL80211_IFTYPE_STATION && !vif->p2p) {
  58		mvm->bf_allowed_vif = mvmvif;
  59		vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER |
  60				     IEEE80211_VIF_SUPPORTS_CQM_RSSI;
  61	}
  62
  63	ret = iwl_mvm_add_link(mvm, vif, &vif->bss_conf);
  64	if (ret)
  65		goto out_free_bf;
  66
  67	/* Save a pointer to p2p device vif, so it can later be used to
  68	 * update the p2p device MAC when a GO is started/stopped
  69	 */
  70	if (vif->type == NL80211_IFTYPE_P2P_DEVICE)
  71		mvm->p2p_device_vif = vif;
  72
  73	ret = iwl_mvm_power_update_mac(mvm);
  74	if (ret)
  75		goto out_free_bf;
  76
  77	iwl_mvm_tcm_add_vif(mvm, vif);
  78	INIT_DELAYED_WORK(&mvmvif->csa_work,
  79			  iwl_mvm_channel_switch_disconnect_wk);
  80
  81	if (vif->type == NL80211_IFTYPE_MONITOR) {
  82		mvm->monitor_on = true;
  83		ieee80211_hw_set(mvm->hw, RX_INCLUDES_FCS);
  84	}
  85
  86	if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
  87		iwl_mvm_vif_dbgfs_add_link(mvm, vif);
  88
  89	if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) &&
  90	    vif->type == NL80211_IFTYPE_STATION && !vif->p2p &&
  91	    !mvm->csme_vif && mvm->mei_registered) {
  92		iwl_mei_set_nic_info(vif->addr, mvm->nvm_data->hw_addr);
  93		iwl_mei_set_netdev(ieee80211_vif_to_wdev(vif)->netdev);
  94		mvm->csme_vif = vif;
  95	}
  96
  97	if (vif->p2p || iwl_fw_lookup_cmd_ver(mvm->fw, PHY_CONTEXT_CMD, 1) < 5)
  98		vif->driver_flags |= IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW;
  99
 100	goto out_unlock;
 101
 102 out_free_bf:
 103	if (mvm->bf_allowed_vif == mvmvif) {
 104		mvm->bf_allowed_vif = NULL;
 105		vif->driver_flags &= ~(IEEE80211_VIF_BEACON_FILTER |
 106				       IEEE80211_VIF_SUPPORTS_CQM_RSSI);
 107	}
 108 out_remove_mac:
 109	mvmvif->link[0] = NULL;
 110	iwl_mvm_mld_mac_ctxt_remove(mvm, vif);
 111 out_unlock:
 112	mutex_unlock(&mvm->mutex);
 113
 114	return ret;
 115}
 116
 117static void iwl_mvm_mld_mac_remove_interface(struct ieee80211_hw *hw,
 118					     struct ieee80211_vif *vif)
 119{
 120	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
 121	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 122	struct iwl_probe_resp_data *probe_data;
 123
 124	iwl_mvm_prepare_mac_removal(mvm, vif);
 125
 126	if (!(vif->type == NL80211_IFTYPE_AP ||
 127	      vif->type == NL80211_IFTYPE_ADHOC))
 128		iwl_mvm_tcm_rm_vif(mvm, vif);
 129
 130	mutex_lock(&mvm->mutex);
 131
 132	if (vif == mvm->csme_vif) {
 133		iwl_mei_set_netdev(NULL);
 134		mvm->csme_vif = NULL;
 135	}
 136
 137	if (mvm->bf_allowed_vif == mvmvif) {
 138		mvm->bf_allowed_vif = NULL;
 139		vif->driver_flags &= ~(IEEE80211_VIF_BEACON_FILTER |
 140				       IEEE80211_VIF_SUPPORTS_CQM_RSSI);
 141	}
 142
 143	if (vif->bss_conf.ftm_responder)
 144		memset(&mvm->ftm_resp_stats, 0, sizeof(mvm->ftm_resp_stats));
 145
 146	iwl_mvm_vif_dbgfs_rm_link(mvm, vif);
 147
 148	/* For AP/GO interface, the tear down of the resources allocated to the
 149	 * interface is be handled as part of the stop_ap flow.
 150	 */
 151	if (vif->type == NL80211_IFTYPE_AP ||
 152	    vif->type == NL80211_IFTYPE_ADHOC) {
 153#ifdef CONFIG_NL80211_TESTMODE
 154		if (vif == mvm->noa_vif) {
 155			mvm->noa_vif = NULL;
 156			mvm->noa_duration = 0;
 157		}
 158#endif
 159	}
 160
 161	iwl_mvm_power_update_mac(mvm);
 162
 163	/* Before the interface removal, mac80211 would cancel the ROC, and the
 164	 * ROC worker would be scheduled if needed. The worker would be flushed
 165	 * in iwl_mvm_prepare_mac_removal() and thus at this point the link is
 166	 * not active. So need only to remove the link.
 167	 */
 168	if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
 169		if (mvmvif->deflink.phy_ctxt) {
 170			iwl_mvm_phy_ctxt_unref(mvm, mvmvif->deflink.phy_ctxt);
 171			mvmvif->deflink.phy_ctxt = NULL;
 172		}
 173		mvm->p2p_device_vif = NULL;
 174		iwl_mvm_remove_link(mvm, vif, &vif->bss_conf);
 175	} else {
 176		iwl_mvm_disable_link(mvm, vif, &vif->bss_conf);
 177	}
 178
 179	iwl_mvm_mld_mac_ctxt_remove(mvm, vif);
 180
 181	RCU_INIT_POINTER(mvm->vif_id_to_mac[mvmvif->id], NULL);
 182
 183	probe_data = rcu_dereference_protected(mvmvif->deflink.probe_resp_data,
 184					       lockdep_is_held(&mvm->mutex));
 185	RCU_INIT_POINTER(mvmvif->deflink.probe_resp_data, NULL);
 186	if (probe_data)
 187		kfree_rcu(probe_data, rcu_head);
 188
 189	if (vif->type == NL80211_IFTYPE_MONITOR) {
 190		mvm->monitor_on = false;
 191		__clear_bit(IEEE80211_HW_RX_INCLUDES_FCS, mvm->hw->flags);
 192	}
 193
 194	mutex_unlock(&mvm->mutex);
 195}
 196
 197static unsigned int iwl_mvm_mld_count_active_links(struct iwl_mvm_vif *mvmvif)
 198{
 199	unsigned int n_active = 0;
 200	int i;
 201
 202	for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
 203		if (mvmvif->link[i] && mvmvif->link[i]->phy_ctxt)
 
 
 
 
 204			n_active++;
 205	}
 206
 207	return n_active;
 208}
 209
 210static int iwl_mvm_esr_mode_active(struct iwl_mvm *mvm,
 211				   struct ieee80211_vif *vif)
 212{
 213	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 214	int link_id, ret = 0;
 215
 216	mvmvif->esr_active = true;
 217
 218	/* Indicate to mac80211 that EML is enabled */
 219	vif->driver_flags |= IEEE80211_VIF_EML_ACTIVE;
 220
 221	iwl_mvm_update_smps_on_active_links(mvm, vif, IWL_MVM_SMPS_REQ_FW,
 222					    IEEE80211_SMPS_OFF);
 223
 224	for_each_mvm_vif_valid_link(mvmvif, link_id) {
 225		struct iwl_mvm_vif_link_info *link = mvmvif->link[link_id];
 226
 227		if (!link->phy_ctxt)
 228			continue;
 229
 230		ret = iwl_mvm_phy_send_rlc(mvm, link->phy_ctxt, 2, 2);
 231		if (ret)
 232			break;
 233
 234		link->phy_ctxt->rlc_disabled = true;
 235	}
 236
 237	return ret;
 238}
 239
 240static int
 241__iwl_mvm_mld_assign_vif_chanctx(struct iwl_mvm *mvm,
 242				 struct ieee80211_vif *vif,
 243				 struct ieee80211_bss_conf *link_conf,
 244				 struct ieee80211_chanctx_conf *ctx,
 245				 bool switching_chanctx)
 246{
 247	u16 *phy_ctxt_id = (u16 *)ctx->drv_priv;
 248	struct iwl_mvm_phy_ctxt *phy_ctxt = &mvm->phy_ctxts[*phy_ctxt_id];
 
 249	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 250	unsigned int n_active = iwl_mvm_mld_count_active_links(mvmvif);
 251	unsigned int link_id = link_conf->link_id;
 252	int ret;
 253
 
 
 
 
 
 
 
 254	if (WARN_ON_ONCE(!mvmvif->link[link_id]))
 255		return -EINVAL;
 256
 257	/* if the assigned one was not counted yet, count it now */
 258	if (!mvmvif->link[link_id]->phy_ctxt)
 259		n_active++;
 260
 261	/* mac parameters such as HE support can change at this stage
 262	 * For sta, need first to configure correct state from drv_sta_state
 263	 * and only after that update mac config.
 264	 */
 265	if (vif->type == NL80211_IFTYPE_AP) {
 266		ret = iwl_mvm_mld_mac_ctxt_changed(mvm, vif, false);
 267		if (ret) {
 268			IWL_ERR(mvm, "failed to update MAC %pM\n", vif->addr);
 269			return -EINVAL;
 270		}
 271	}
 272
 273	mvmvif->link[link_id]->phy_ctxt = phy_ctxt;
 274
 275	if (iwl_mvm_is_esr_supported(mvm->fwrt.trans) && n_active > 1) {
 276		mvmvif->link[link_id]->listen_lmac = true;
 277		ret = iwl_mvm_esr_mode_active(mvm, vif);
 278		if (ret) {
 279			IWL_ERR(mvm, "failed to activate ESR mode (%d)\n", ret);
 280			goto out;
 281		}
 282	}
 283
 284	if (switching_chanctx) {
 285		/* reactivate if we turned this off during channel switch */
 286		if (vif->type == NL80211_IFTYPE_AP)
 287			mvmvif->ap_ibss_active = true;
 288	}
 289
 290	/* send it first with phy context ID */
 291	ret = iwl_mvm_link_changed(mvm, vif, link_conf, 0, false);
 292	if (ret)
 293		goto out;
 294
 295	/* Initialize rate control for the AP station, since we might be
 296	 * doing a link switch here - we cannot initialize it before since
 297	 * this needs the phy context assigned (and in FW?), and we cannot
 298	 * do it later because it needs to be initialized as soon as we're
 299	 * able to TX on the link, i.e. when active.
 
 
 
 
 300	 */
 301	if (mvmvif->ap_sta) {
 
 302		struct ieee80211_link_sta *link_sta;
 303
 304		rcu_read_lock();
 305		link_sta = rcu_dereference(mvmvif->ap_sta->link[link_id]);
 306
 307		if (!WARN_ON_ONCE(!link_sta))
 308			iwl_mvm_rs_rate_init(mvm, vif, mvmvif->ap_sta,
 309					     link_conf, link_sta,
 310					     phy_ctxt->channel->band);
 311		rcu_read_unlock();
 312	}
 313
 314	/* then activate */
 315	ret = iwl_mvm_link_changed(mvm, vif, link_conf,
 316				   LINK_CONTEXT_MODIFY_ACTIVE |
 317				   LINK_CONTEXT_MODIFY_RATES_INFO,
 318				   true);
 319	if (ret)
 320		goto out;
 321
 322	/*
 323	 * Power state must be updated before quotas,
 324	 * otherwise fw will complain.
 325	 */
 326	iwl_mvm_power_update_mac(mvm);
 327
 328	if (vif->type == NL80211_IFTYPE_MONITOR) {
 329		ret = iwl_mvm_mld_add_snif_sta(mvm, vif, link_conf);
 330		if (ret)
 331			goto deactivate;
 332	}
 333
 334	return 0;
 335
 336deactivate:
 337	iwl_mvm_link_changed(mvm, vif, link_conf, LINK_CONTEXT_MODIFY_ACTIVE,
 338			     false);
 339out:
 340	mvmvif->link[link_id]->phy_ctxt = NULL;
 341	iwl_mvm_power_update_mac(mvm);
 342	return ret;
 343}
 344
 345static int iwl_mvm_mld_assign_vif_chanctx(struct ieee80211_hw *hw,
 346					  struct ieee80211_vif *vif,
 347					  struct ieee80211_bss_conf *link_conf,
 348					  struct ieee80211_chanctx_conf *ctx)
 349{
 350	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
 351	int ret;
 352
 353	mutex_lock(&mvm->mutex);
 354	ret = __iwl_mvm_mld_assign_vif_chanctx(mvm, vif, link_conf, ctx, false);
 355	mutex_unlock(&mvm->mutex);
 356
 357	return ret;
 358}
 359
 360static int iwl_mvm_esr_mode_inactive(struct iwl_mvm *mvm,
 361				     struct ieee80211_vif *vif)
 362{
 363	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 364	struct ieee80211_bss_conf *link_conf;
 365	int link_id, ret = 0;
 366
 367	mvmvif->esr_active = false;
 368
 369	vif->driver_flags &= ~IEEE80211_VIF_EML_ACTIVE;
 370
 371	iwl_mvm_update_smps_on_active_links(mvm, vif, IWL_MVM_SMPS_REQ_FW,
 372					    IEEE80211_SMPS_AUTOMATIC);
 373
 374	for_each_vif_active_link(vif, link_conf, link_id) {
 375		struct ieee80211_chanctx_conf *chanctx_conf;
 376		struct iwl_mvm_phy_ctxt *phy_ctxt;
 377		u8 static_chains, dynamic_chains;
 378
 379		mvmvif->link[link_id]->listen_lmac = false;
 380
 381		rcu_read_lock();
 382
 383		chanctx_conf = rcu_dereference(link_conf->chanctx_conf);
 384		phy_ctxt = mvmvif->link[link_id]->phy_ctxt;
 385
 386		if (!chanctx_conf || !phy_ctxt) {
 387			rcu_read_unlock();
 388			continue;
 389		}
 390
 391		phy_ctxt->rlc_disabled = false;
 392		static_chains = chanctx_conf->rx_chains_static;
 393		dynamic_chains = chanctx_conf->rx_chains_dynamic;
 394
 395		rcu_read_unlock();
 396
 397		ret = iwl_mvm_phy_send_rlc(mvm, phy_ctxt, static_chains,
 398					   dynamic_chains);
 399		if (ret)
 400			break;
 401	}
 402
 403	return ret;
 404}
 405
 406static void
 407__iwl_mvm_mld_unassign_vif_chanctx(struct iwl_mvm *mvm,
 408				   struct ieee80211_vif *vif,
 409				   struct ieee80211_bss_conf *link_conf,
 410				   struct ieee80211_chanctx_conf *ctx,
 411				   bool switching_chanctx)
 412
 413{
 414	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 415	unsigned int n_active = iwl_mvm_mld_count_active_links(mvmvif);
 416	unsigned int link_id = link_conf->link_id;
 417
 418	/* shouldn't happen, but verify link_id is valid before accessing */
 419	if (WARN_ON_ONCE(!mvmvif->link[link_id]))
 420		return;
 421
 422	if (vif->type == NL80211_IFTYPE_AP && switching_chanctx) {
 423		mvmvif->csa_countdown = false;
 424
 425		/* Set CS bit on all the stations */
 426		iwl_mvm_modify_all_sta_disable_tx(mvm, mvmvif, true);
 427
 428		/* Save blocked iface, the timeout is set on the next beacon */
 429		rcu_assign_pointer(mvm->csa_tx_blocked_vif, vif);
 430
 431		mvmvif->ap_ibss_active = false;
 432	}
 433
 434	iwl_mvm_link_changed(mvm, vif, link_conf,
 435			     LINK_CONTEXT_MODIFY_ACTIVE, false);
 436
 437	if (iwl_mvm_is_esr_supported(mvm->fwrt.trans) && n_active > 1) {
 438		int ret = iwl_mvm_esr_mode_inactive(mvm, vif);
 439
 440		if (ret)
 441			IWL_ERR(mvm, "failed to deactivate ESR mode (%d)\n",
 442				ret);
 443	}
 444
 445	if (vif->type == NL80211_IFTYPE_MONITOR)
 446		iwl_mvm_mld_rm_snif_sta(mvm, vif);
 447
 448	if (switching_chanctx)
 449		return;
 450	mvmvif->link[link_id]->phy_ctxt = NULL;
 451	iwl_mvm_power_update_mac(mvm);
 452}
 453
 454static void iwl_mvm_mld_unassign_vif_chanctx(struct ieee80211_hw *hw,
 455					     struct ieee80211_vif *vif,
 456					     struct ieee80211_bss_conf *link_conf,
 457					     struct ieee80211_chanctx_conf *ctx)
 458{
 459	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 460	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
 461
 462	mutex_lock(&mvm->mutex);
 463	__iwl_mvm_mld_unassign_vif_chanctx(mvm, vif, link_conf, ctx, false);
 464	/* in the non-MLD case, remove/re-add the link to clean up FW state */
 465	if (!ieee80211_vif_is_mld(vif) && !mvmvif->ap_sta &&
 466	    !WARN_ON_ONCE(vif->cfg.assoc)) {
 467		iwl_mvm_remove_link(mvm, vif, link_conf);
 468		iwl_mvm_add_link(mvm, vif, link_conf);
 469	}
 470	mutex_unlock(&mvm->mutex);
 471}
 472
 473static int iwl_mvm_mld_start_ap_ibss(struct ieee80211_hw *hw,
 474				     struct ieee80211_vif *vif,
 475				     struct ieee80211_bss_conf *link_conf)
 476{
 477	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
 478	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 479	int ret;
 480
 481	mutex_lock(&mvm->mutex);
 482	/* Send the beacon template */
 483	ret = iwl_mvm_mac_ctxt_beacon_changed(mvm, vif, link_conf);
 484	if (ret)
 485		goto out_unlock;
 486
 487	/* the link should be already activated when assigning chan context */
 488	ret = iwl_mvm_link_changed(mvm, vif, link_conf,
 489				   LINK_CONTEXT_MODIFY_ALL &
 490				   ~LINK_CONTEXT_MODIFY_ACTIVE,
 491				   true);
 492	if (ret)
 493		goto out_unlock;
 494
 495	ret = iwl_mvm_mld_add_mcast_sta(mvm, vif, link_conf);
 496	if (ret)
 497		goto out_unlock;
 498
 499	/* Send the bcast station. At this stage the TBTT and DTIM time
 500	 * events are added and applied to the scheduler
 501	 */
 502	ret = iwl_mvm_mld_add_bcast_sta(mvm, vif, link_conf);
 503	if (ret)
 504		goto out_rm_mcast;
 505
 506	if (iwl_mvm_start_ap_ibss_common(hw, vif, &ret))
 507		goto out_failed;
 508
 509	/* Need to update the P2P Device MAC (only GO, IBSS is single vif) */
 510	if (vif->p2p && mvm->p2p_device_vif)
 511		iwl_mvm_mld_mac_ctxt_changed(mvm, mvm->p2p_device_vif, false);
 512
 513	iwl_mvm_bt_coex_vif_change(mvm);
 514
 515	/* we don't support TDLS during DCM */
 516	if (iwl_mvm_phy_ctx_count(mvm) > 1)
 517		iwl_mvm_teardown_tdls_peers(mvm);
 518
 519	iwl_mvm_ftm_restart_responder(mvm, vif, link_conf);
 520
 521	goto out_unlock;
 522
 523out_failed:
 524	iwl_mvm_power_update_mac(mvm);
 525	mvmvif->ap_ibss_active = false;
 526	iwl_mvm_mld_rm_bcast_sta(mvm, vif, link_conf);
 527out_rm_mcast:
 528	iwl_mvm_mld_rm_mcast_sta(mvm, vif, link_conf);
 529out_unlock:
 530	mutex_unlock(&mvm->mutex);
 531	return ret;
 532}
 533
 534static int iwl_mvm_mld_start_ap(struct ieee80211_hw *hw,
 535				struct ieee80211_vif *vif,
 536				struct ieee80211_bss_conf *link_conf)
 537{
 538	return iwl_mvm_mld_start_ap_ibss(hw, vif, link_conf);
 539}
 540
 541static int iwl_mvm_mld_start_ibss(struct ieee80211_hw *hw,
 542				  struct ieee80211_vif *vif)
 543{
 544	return iwl_mvm_mld_start_ap_ibss(hw, vif, &vif->bss_conf);
 545}
 546
 547static void iwl_mvm_mld_stop_ap_ibss(struct ieee80211_hw *hw,
 548				     struct ieee80211_vif *vif,
 549				     struct ieee80211_bss_conf *link_conf)
 550{
 551	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
 552
 553	mutex_lock(&mvm->mutex);
 554
 555	iwl_mvm_stop_ap_ibss_common(mvm, vif);
 556
 557	/* Need to update the P2P Device MAC (only GO, IBSS is single vif) */
 558	if (vif->p2p && mvm->p2p_device_vif)
 559		iwl_mvm_mld_mac_ctxt_changed(mvm, mvm->p2p_device_vif, false);
 560
 561	iwl_mvm_ftm_responder_clear(mvm, vif);
 562
 563	iwl_mvm_mld_rm_bcast_sta(mvm, vif, link_conf);
 564	iwl_mvm_mld_rm_mcast_sta(mvm, vif, link_conf);
 565
 566	iwl_mvm_power_update_mac(mvm);
 567	mutex_unlock(&mvm->mutex);
 568}
 569
 570static void iwl_mvm_mld_stop_ap(struct ieee80211_hw *hw,
 571				struct ieee80211_vif *vif,
 572				struct ieee80211_bss_conf *link_conf)
 573{
 574	iwl_mvm_mld_stop_ap_ibss(hw, vif, link_conf);
 575}
 576
 577static void iwl_mvm_mld_stop_ibss(struct ieee80211_hw *hw,
 578				  struct ieee80211_vif *vif)
 579{
 580	iwl_mvm_mld_stop_ap_ibss(hw, vif, &vif->bss_conf);
 581}
 582
 583static int iwl_mvm_mld_mac_sta_state(struct ieee80211_hw *hw,
 584				     struct ieee80211_vif *vif,
 585				     struct ieee80211_sta *sta,
 586				     enum ieee80211_sta_state old_state,
 587				     enum ieee80211_sta_state new_state)
 588{
 589	static const struct iwl_mvm_sta_state_ops callbacks = {
 590		.add_sta = iwl_mvm_mld_add_sta,
 591		.update_sta = iwl_mvm_mld_update_sta,
 592		.rm_sta = iwl_mvm_mld_rm_sta,
 593		.mac_ctxt_changed = iwl_mvm_mld_mac_ctxt_changed,
 594	};
 595
 596	return iwl_mvm_mac_sta_state_common(hw, vif, sta, old_state, new_state,
 597					    &callbacks);
 598}
 599
 600struct iwl_mvm_link_sel_data {
 601	u8 link_id;
 602	enum nl80211_band band;
 603	enum nl80211_chan_width width;
 604	bool active;
 605};
 606
 607static bool iwl_mvm_mld_valid_link_pair(struct ieee80211_vif *vif,
 608					struct iwl_mvm_link_sel_data *a,
 609					struct iwl_mvm_link_sel_data *b)
 610{
 611	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 612
 613	if (a->band == b->band)
 614		return false;
 615
 616	/* BT Coex effects eSR mode only if one of the link is on LB */
 617	if (a->band == NL80211_BAND_2GHZ || b->band == NL80211_BAND_2GHZ)
 618		return !(mvmvif->esr_disable_reason & IWL_MVM_ESR_DISABLE_COEX);
 619
 620	return true;
 621}
 622
 623static u8
 624iwl_mvm_set_link_selection_data(struct ieee80211_vif *vif,
 625				struct iwl_mvm_link_sel_data *data,
 626				unsigned long usable_links)
 627{
 628	u8 n_data = 0;
 629	unsigned long link_id;
 630
 631	rcu_read_lock();
 632
 633	for_each_set_bit(link_id, &usable_links, IEEE80211_MLD_MAX_NUM_LINKS) {
 634		struct ieee80211_bss_conf *link_conf =
 635			rcu_dereference(vif->link_conf[link_id]);
 636
 637		if (WARN_ON_ONCE(!link_conf))
 638			continue;
 639
 640		data[n_data].link_id = link_id;
 641		data[n_data].band = link_conf->chanreq.oper.chan->band;
 642		data[n_data].width = link_conf->chanreq.oper.width;
 643		data[n_data].active = vif->active_links & BIT(link_id);
 644		n_data++;
 645	}
 646
 647	rcu_read_unlock();
 648
 649	return n_data;
 650}
 651
 652void iwl_mvm_mld_select_links(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 653			      bool valid_links_changed)
 654{
 655	struct iwl_mvm_link_sel_data data[IEEE80211_MLD_MAX_NUM_LINKS];
 656	unsigned long usable_links = ieee80211_vif_usable_links(vif);
 657	u32 max_active_links = iwl_mvm_max_active_links(mvm, vif);
 658	u16 new_active_links;
 659	u8 n_data, i, j;
 660
 661	if (!IWL_MVM_AUTO_EML_ENABLE)
 662		return;
 663
 664	if (!ieee80211_vif_is_mld(vif) || usable_links == 1)
 665		return;
 666
 667	/* The logic below is a simple version that doesn't suit more than 2
 668	 * links
 669	 */
 670	WARN_ON_ONCE(max_active_links > 2);
 671
 672	/* if only a single active link is supported, assume that the one
 673	 * selected by higher layer for connection establishment is the best.
 674	 */
 675	if (max_active_links == 1 && !valid_links_changed)
 676		return;
 677
 678	/* If we are already using the maximal number of active links, don't do
 679	 * any change. This can later be optimized to pick a 'better' link pair.
 680	 */
 681	if (hweight16(vif->active_links) == max_active_links)
 682		return;
 683
 684	n_data = iwl_mvm_set_link_selection_data(vif, data, usable_links);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 685
 686	/* this is expected to be the current active link */
 687	if (n_data == 1)
 688		return;
 689
 690	new_active_links = 0;
 691
 692	/* Assume that after association only a single link is active, thus,
 693	 * select only the 2nd link
 694	 */
 695	if (!valid_links_changed) {
 696		for (i = 0; i < n_data; i++) {
 697			if (data[i].active)
 698				break;
 699		}
 700
 701		if (WARN_ON_ONCE(i == n_data))
 702			return;
 703
 704		for (j = 0; j < n_data; j++) {
 705			if (i == j)
 706				continue;
 707
 708			if (iwl_mvm_mld_valid_link_pair(vif, &data[i],
 709							&data[j]))
 710				break;
 711		}
 712
 713		if (j != n_data)
 714			new_active_links = BIT(data[i].link_id) |
 715				BIT(data[j].link_id);
 716	} else {
 717		/* Try to find a valid link pair for EMLSR operation. If a pair
 718		 * is not found continue using the current active link.
 719		 */
 720		for (i = 0; i < n_data; i++) {
 721			for (j = 0; j < n_data; j++) {
 722				if (i == j)
 723					continue;
 724
 725				if (iwl_mvm_mld_valid_link_pair(vif, &data[i],
 726								&data[j]))
 727					break;
 728			}
 729
 730			/* found a valid pair for EMLSR, use it */
 731			if (j != n_data) {
 732				new_active_links = BIT(data[i].link_id) |
 733					BIT(data[j].link_id);
 734				break;
 735			}
 736		}
 737	}
 738
 739	if (!new_active_links)
 740		return;
 741
 742	if (vif->active_links != new_active_links)
 743		ieee80211_set_active_links_async(vif, new_active_links);
 744}
 745
 746static void
 747iwl_mvm_mld_link_info_changed_station(struct iwl_mvm *mvm,
 748				      struct ieee80211_vif *vif,
 749				      struct ieee80211_bss_conf *link_conf,
 750				      u64 changes)
 751{
 752	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 753	bool has_he, has_eht;
 754	u32 link_changes = 0;
 755	int ret;
 756
 757	if (WARN_ON_ONCE(!mvmvif->link[link_conf->link_id]))
 758		return;
 759
 760	has_he = link_conf->he_support && !iwlwifi_mod_params.disable_11ax;
 761	has_eht = link_conf->eht_support && !iwlwifi_mod_params.disable_11be;
 762
 763	/* Update EDCA params */
 764	if (changes & BSS_CHANGED_QOS && vif->cfg.assoc && link_conf->qos)
 765		link_changes |= LINK_CONTEXT_MODIFY_QOS_PARAMS;
 766
 767	if (changes & BSS_CHANGED_ERP_SLOT)
 768		link_changes |= LINK_CONTEXT_MODIFY_RATES_INFO;
 769
 770	if (vif->cfg.assoc && (has_he || has_eht)) {
 771		IWL_DEBUG_MAC80211(mvm, "Associated in HE mode\n");
 772		link_changes |= LINK_CONTEXT_MODIFY_HE_PARAMS;
 773	}
 774
 775	/* if associated, maybe puncturing changed - we'll check later */
 776	if (vif->cfg.assoc)
 777		link_changes |= LINK_CONTEXT_MODIFY_EHT_PARAMS;
 778
 779	if (link_changes) {
 780		ret = iwl_mvm_link_changed(mvm, vif, link_conf, link_changes,
 781					   true);
 782		if (ret)
 783			IWL_ERR(mvm, "failed to update link\n");
 784	}
 785
 786	ret = iwl_mvm_mld_mac_ctxt_changed(mvm, vif, false);
 787	if (ret)
 788		IWL_ERR(mvm, "failed to update MAC %pM\n", vif->addr);
 789
 790	if (changes & BSS_CHANGED_MLD_VALID_LINKS)
 791		iwl_mvm_mld_select_links(mvm, vif, true);
 792
 793	memcpy(mvmvif->link[link_conf->link_id]->bssid, link_conf->bssid,
 794	       ETH_ALEN);
 795
 796	iwl_mvm_bss_info_changed_station_common(mvm, vif, link_conf, changes);
 797}
 798
 799static bool iwl_mvm_mld_vif_have_valid_ap_sta(struct iwl_mvm_vif *mvmvif)
 800{
 801	int i;
 802
 803	for_each_mvm_vif_valid_link(mvmvif, i) {
 804		if (mvmvif->link[i]->ap_sta_id != IWL_MVM_INVALID_STA)
 805			return true;
 806	}
 807
 808	return false;
 809}
 810
 811static void iwl_mvm_mld_vif_delete_all_stas(struct iwl_mvm *mvm,
 812					    struct ieee80211_vif *vif)
 813{
 814	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 815	int i, ret;
 816
 817	if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
 818		return;
 819
 820	for_each_mvm_vif_valid_link(mvmvif, i) {
 821		struct iwl_mvm_vif_link_info *link = mvmvif->link[i];
 822
 823		if (!link)
 824			continue;
 825
 826		iwl_mvm_sec_key_remove_ap(mvm, vif, link, i);
 827		ret = iwl_mvm_mld_rm_sta_id(mvm, link->ap_sta_id);
 828		if (ret)
 829			IWL_ERR(mvm, "failed to remove AP station\n");
 830
 831		link->ap_sta_id = IWL_MVM_INVALID_STA;
 832	}
 833}
 834
 835static void iwl_mvm_mld_vif_cfg_changed_station(struct iwl_mvm *mvm,
 836						struct ieee80211_vif *vif,
 837						u64 changes)
 838{
 839	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 840	struct ieee80211_bss_conf *link_conf;
 841	bool protect = false;
 842	unsigned int i;
 843	int ret;
 844
 845	/* This might get called without active links during the
 846	 * chanctx switch, but we don't care about it anyway.
 847	 */
 848	if (changes == BSS_CHANGED_IDLE)
 849		return;
 850
 851	ret = iwl_mvm_mld_mac_ctxt_changed(mvm, vif, false);
 852	if (ret)
 853		IWL_ERR(mvm, "failed to update MAC %pM\n", vif->addr);
 854
 855	mvmvif->associated = vif->cfg.assoc;
 856
 857	if (changes & BSS_CHANGED_ASSOC) {
 858		if (vif->cfg.assoc) {
 859			/* clear statistics to get clean beacon counter */
 860			iwl_mvm_request_statistics(mvm, true);
 861			iwl_mvm_sf_update(mvm, vif, false);
 862			iwl_mvm_power_vif_assoc(mvm, vif);
 863
 864			for_each_mvm_vif_valid_link(mvmvif, i) {
 865				memset(&mvmvif->link[i]->beacon_stats, 0,
 866				       sizeof(mvmvif->link[i]->beacon_stats));
 867
 868				if (vif->p2p) {
 869					iwl_mvm_update_smps(mvm, vif,
 870							    IWL_MVM_SMPS_REQ_PROT,
 871							    IEEE80211_SMPS_DYNAMIC, i);
 872				}
 873
 874				rcu_read_lock();
 875				link_conf = rcu_dereference(vif->link_conf[i]);
 876				if (link_conf && !link_conf->dtim_period)
 877					protect = true;
 878				rcu_read_unlock();
 879			}
 880
 881			if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) &&
 882			    protect) {
 883				/* We are in assoc so only one link is active-
 884				 * The association link
 885				 */
 886				unsigned int link_id =
 887					ffs(vif->active_links) - 1;
 888
 889				/* If we're not restarting and still haven't
 890				 * heard a beacon (dtim period unknown) then
 891				 * make sure we still have enough minimum time
 892				 * remaining in the time event, since the auth
 893				 * might actually have taken quite a while
 894				 * (especially for SAE) and so the remaining
 895				 * time could be small without us having heard
 896				 * a beacon yet.
 897				 */
 898				iwl_mvm_protect_assoc(mvm, vif, 0, link_id);
 899			}
 900
 901			iwl_mvm_sf_update(mvm, vif, false);
 902
 903			/* FIXME: need to decide about misbehaving AP handling */
 904			iwl_mvm_power_vif_assoc(mvm, vif);
 905		} else if (iwl_mvm_mld_vif_have_valid_ap_sta(mvmvif)) {
 906			iwl_mvm_mei_host_disassociated(mvm);
 907
 908			/* If update fails - SF might be running in associated
 909			 * mode while disassociated - which is forbidden.
 910			 */
 911			ret = iwl_mvm_sf_update(mvm, vif, false);
 912			WARN_ONCE(ret &&
 913				  !test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED,
 914					    &mvm->status),
 915				  "Failed to update SF upon disassociation\n");
 916
 917			/* If we get an assert during the connection (after the
 918			 * station has been added, but before the vif is set
 919			 * to associated), mac80211 will re-add the station and
 920			 * then configure the vif. Since the vif is not
 921			 * associated, we would remove the station here and
 922			 * this would fail the recovery.
 923			 */
 924			iwl_mvm_mld_vif_delete_all_stas(mvm, vif);
 925		}
 926
 927		iwl_mvm_bss_info_changed_station_assoc(mvm, vif, changes);
 928	}
 929
 930	if (changes & BSS_CHANGED_PS) {
 931		ret = iwl_mvm_power_update_mac(mvm);
 932		if (ret)
 933			IWL_ERR(mvm, "failed to update power mode\n");
 934	}
 935}
 936
 937static void
 938iwl_mvm_mld_link_info_changed_ap_ibss(struct iwl_mvm *mvm,
 939				      struct ieee80211_vif *vif,
 940				      struct ieee80211_bss_conf *link_conf,
 941				      u64 changes)
 942{
 943	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 944	u32 link_changes = LINK_CONTEXT_MODIFY_PROTECT_FLAGS |
 945			   LINK_CONTEXT_MODIFY_QOS_PARAMS;
 946
 947	/* Changes will be applied when the AP/IBSS is started */
 948	if (!mvmvif->ap_ibss_active)
 949		return;
 950
 951	if (link_conf->he_support)
 952		link_changes |= LINK_CONTEXT_MODIFY_HE_PARAMS;
 953
 954	if (changes & BSS_CHANGED_ERP_SLOT)
 955		link_changes |= LINK_CONTEXT_MODIFY_RATES_INFO;
 956
 957	if (changes & (BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_ERP_SLOT |
 958		       BSS_CHANGED_HT |
 959		       BSS_CHANGED_BANDWIDTH | BSS_CHANGED_QOS |
 960		       BSS_CHANGED_HE_BSS_COLOR) &&
 961		       iwl_mvm_link_changed(mvm, vif, link_conf,
 962					    link_changes, true))
 963		IWL_ERR(mvm, "failed to update MAC %pM\n", vif->addr);
 964
 965	/* Need to send a new beacon template to the FW */
 966	if (changes & BSS_CHANGED_BEACON &&
 967	    iwl_mvm_mac_ctxt_beacon_changed(mvm, vif, link_conf))
 968		IWL_WARN(mvm, "Failed updating beacon data\n");
 969
 970	/* FIXME: need to decide if we need FTM responder per link */
 971	if (changes & BSS_CHANGED_FTM_RESPONDER) {
 972		int ret = iwl_mvm_ftm_start_responder(mvm, vif, link_conf);
 973
 974		if (ret)
 975			IWL_WARN(mvm, "Failed to enable FTM responder (%d)\n",
 976				 ret);
 977	}
 978}
 979
 980static void iwl_mvm_mld_link_info_changed(struct ieee80211_hw *hw,
 981					  struct ieee80211_vif *vif,
 982					  struct ieee80211_bss_conf *link_conf,
 983					  u64 changes)
 984{
 985	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
 986
 987	mutex_lock(&mvm->mutex);
 988
 989	switch (vif->type) {
 990	case NL80211_IFTYPE_STATION:
 991		iwl_mvm_mld_link_info_changed_station(mvm, vif, link_conf,
 992						      changes);
 993		break;
 994	case NL80211_IFTYPE_AP:
 995	case NL80211_IFTYPE_ADHOC:
 996		iwl_mvm_mld_link_info_changed_ap_ibss(mvm, vif, link_conf,
 997						      changes);
 998		break;
 999	case NL80211_IFTYPE_MONITOR:
1000		if (changes & BSS_CHANGED_MU_GROUPS)
1001			iwl_mvm_update_mu_groups(mvm, vif);
1002		break;
1003	default:
1004		/* shouldn't happen */
1005		WARN_ON_ONCE(1);
1006	}
1007
1008	if (changes & BSS_CHANGED_TXPOWER) {
1009		IWL_DEBUG_CALIB(mvm, "Changing TX Power to %d dBm\n",
1010				link_conf->txpower);
1011		iwl_mvm_set_tx_power(mvm, vif, link_conf->txpower);
1012	}
1013
1014	mutex_unlock(&mvm->mutex);
1015}
1016
1017static void iwl_mvm_mld_vif_cfg_changed(struct ieee80211_hw *hw,
1018					struct ieee80211_vif *vif,
1019					u64 changes)
1020{
1021	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
1022
1023	mutex_lock(&mvm->mutex);
1024
1025	if (changes & BSS_CHANGED_IDLE && !vif->cfg.idle)
1026		iwl_mvm_scan_stop(mvm, IWL_MVM_SCAN_SCHED, true);
1027
1028	if (vif->type == NL80211_IFTYPE_STATION)
1029		iwl_mvm_mld_vif_cfg_changed_station(mvm, vif, changes);
1030
1031	mutex_unlock(&mvm->mutex);
1032}
1033
1034static int
1035iwl_mvm_mld_switch_vif_chanctx(struct ieee80211_hw *hw,
1036			       struct ieee80211_vif_chanctx_switch *vifs,
1037			       int n_vifs,
1038			       enum ieee80211_chanctx_switch_mode mode)
1039{
1040	static const struct iwl_mvm_switch_vif_chanctx_ops ops = {
1041		.__assign_vif_chanctx = __iwl_mvm_mld_assign_vif_chanctx,
1042		.__unassign_vif_chanctx = __iwl_mvm_mld_unassign_vif_chanctx,
1043	};
1044
1045	return iwl_mvm_switch_vif_chanctx_common(hw, vifs, n_vifs, mode, &ops);
1046}
1047
1048static void iwl_mvm_mld_config_iface_filter(struct ieee80211_hw *hw,
1049					    struct ieee80211_vif *vif,
1050					    unsigned int filter_flags,
1051					    unsigned int changed_flags)
1052{
1053	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
1054
1055	/* We support only filter for probe requests */
1056	if (!(changed_flags & FIF_PROBE_REQ))
1057		return;
1058
1059	/* Supported only for p2p client interfaces */
1060	if (vif->type != NL80211_IFTYPE_STATION || !vif->cfg.assoc ||
1061	    !vif->p2p)
1062		return;
1063
1064	mutex_lock(&mvm->mutex);
1065	iwl_mvm_mld_mac_ctxt_changed(mvm, vif, false);
1066	mutex_unlock(&mvm->mutex);
1067}
1068
1069static int
1070iwl_mvm_mld_mac_conf_tx(struct ieee80211_hw *hw,
1071			struct ieee80211_vif *vif,
1072			unsigned int link_id, u16 ac,
1073			const struct ieee80211_tx_queue_params *params)
1074{
1075	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
1076	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1077	struct iwl_mvm_vif_link_info *mvm_link = mvmvif->link[link_id];
1078
1079	if (!mvm_link)
1080		return -EINVAL;
1081
1082	mvm_link->queue_params[ac] = *params;
1083
1084	/* No need to update right away, we'll get BSS_CHANGED_QOS
1085	 * The exception is P2P_DEVICE interface which needs immediate update.
1086	 */
1087	if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
1088		int ret;
1089
1090		mutex_lock(&mvm->mutex);
1091		ret = iwl_mvm_link_changed(mvm, vif, &vif->bss_conf,
1092					   LINK_CONTEXT_MODIFY_QOS_PARAMS,
1093					   true);
1094		mutex_unlock(&mvm->mutex);
1095		return ret;
1096	}
1097	return 0;
1098}
1099
1100static int iwl_mvm_mld_roc_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
1101{
1102	int ret;
1103
1104	lockdep_assert_held(&mvm->mutex);
1105
1106	/* The PHY context ID might have changed so need to set it */
1107	ret = iwl_mvm_link_changed(mvm, vif, &vif->bss_conf, 0, false);
1108	if (WARN(ret, "Failed to set PHY context ID\n"))
1109		return ret;
1110
1111	ret = iwl_mvm_link_changed(mvm, vif, &vif->bss_conf,
1112				   LINK_CONTEXT_MODIFY_ACTIVE |
1113				   LINK_CONTEXT_MODIFY_RATES_INFO,
1114				   true);
1115
1116	if (WARN(ret, "Failed linking P2P_DEVICE\n"))
1117		return ret;
1118
1119	/* The station and queue allocation must be done only after the linking
1120	 * is done, as otherwise the FW might incorrectly configure its state.
1121	 */
1122	return iwl_mvm_mld_add_bcast_sta(mvm, vif, &vif->bss_conf);
1123}
1124
1125static int iwl_mvm_mld_roc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
1126			   struct ieee80211_channel *channel, int duration,
1127			   enum ieee80211_roc_type type)
1128{
1129	static const struct iwl_mvm_roc_ops ops = {
1130		.add_aux_sta_for_hs20 = iwl_mvm_mld_add_aux_sta,
1131		.link = iwl_mvm_mld_roc_link,
1132	};
1133
1134	return iwl_mvm_roc_common(hw, vif, channel, duration, type, &ops);
1135}
1136
1137static int
1138iwl_mvm_mld_change_vif_links(struct ieee80211_hw *hw,
1139			     struct ieee80211_vif *vif,
1140			     u16 old_links, u16 new_links,
1141			     struct ieee80211_bss_conf *old[IEEE80211_MLD_MAX_NUM_LINKS])
1142{
1143	struct iwl_mvm_vif_link_info *new_link[IEEE80211_MLD_MAX_NUM_LINKS] = {};
 
1144	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1145	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
1146	u16 removed = old_links & ~new_links;
1147	u16 added = new_links & ~old_links;
1148	int err, i;
1149
 
 
 
 
1150	for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
1151		int r;
1152
1153		if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
1154			break;
1155
1156		if (!(added & BIT(i)))
1157			continue;
1158		new_link[i] = kzalloc(sizeof(*new_link[i]), GFP_KERNEL);
1159		if (!new_link[i]) {
1160			err = -ENOMEM;
1161			goto free;
1162		}
1163
1164		new_link[i]->bcast_sta.sta_id = IWL_MVM_INVALID_STA;
1165		new_link[i]->mcast_sta.sta_id = IWL_MVM_INVALID_STA;
1166		new_link[i]->ap_sta_id = IWL_MVM_INVALID_STA;
1167		new_link[i]->fw_link_id = IWL_MVM_FW_LINK_ID_INVALID;
1168
1169		for (r = 0; r < NUM_IWL_MVM_SMPS_REQ; r++)
1170			new_link[i]->smps_requests[r] =
1171				IEEE80211_SMPS_AUTOMATIC;
1172	}
1173
1174	mutex_lock(&mvm->mutex);
1175
1176	if (old_links == 0) {
1177		err = iwl_mvm_disable_link(mvm, vif, &vif->bss_conf);
1178		if (err)
1179			goto out_err;
1180		mvmvif->link[0] = NULL;
1181	}
1182
1183	for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
1184		if (removed & BIT(i)) {
1185			struct ieee80211_bss_conf *link_conf = old[i];
1186
1187			err = iwl_mvm_disable_link(mvm, vif, link_conf);
1188			if (err)
1189				goto out_err;
1190			kfree(mvmvif->link[i]);
1191			mvmvif->link[i] = NULL;
1192		} else if (added & BIT(i)) {
1193			struct ieee80211_bss_conf *link_conf;
1194
1195			link_conf = link_conf_dereference_protected(vif, i);
1196			if (WARN_ON(!link_conf))
1197				continue;
1198
1199			if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART,
1200				      &mvm->status))
1201				mvmvif->link[i] = new_link[i];
1202			new_link[i] = NULL;
1203			err = iwl_mvm_add_link(mvm, vif, link_conf);
1204			if (err)
1205				goto out_err;
1206		}
1207	}
1208
1209	err = 0;
1210	if (new_links == 0) {
1211		mvmvif->link[0] = &mvmvif->deflink;
1212		err = iwl_mvm_add_link(mvm, vif, &vif->bss_conf);
1213	}
1214
1215out_err:
1216	/* we really don't have a good way to roll back here ... */
1217	mutex_unlock(&mvm->mutex);
1218
1219free:
1220	for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++)
1221		kfree(new_link[i]);
1222	return err;
1223}
1224
1225static int
1226iwl_mvm_mld_change_sta_links(struct ieee80211_hw *hw,
1227			     struct ieee80211_vif *vif,
1228			     struct ieee80211_sta *sta,
1229			     u16 old_links, u16 new_links)
1230{
1231	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
1232	int ret;
1233
1234	mutex_lock(&mvm->mutex);
1235	ret = iwl_mvm_mld_update_sta_links(mvm, vif, sta, old_links, new_links);
1236	mutex_unlock(&mvm->mutex);
1237
1238	return ret;
1239}
1240
1241/*
1242 * This function receives a subset of the usable links bitmap and
1243 * returns the primary link id, and -1 if such link doesn't exist
1244 * (e.g. non-MLO connection) or wasn't found.
1245 */
1246int iwl_mvm_mld_get_primary_link(struct iwl_mvm *mvm,
1247				 struct ieee80211_vif *vif,
1248				 unsigned long usable_links)
1249{
1250	struct iwl_mvm_link_sel_data data[IEEE80211_MLD_MAX_NUM_LINKS];
1251	u8 link_id, n_data = 0;
1252
1253	if (!ieee80211_vif_is_mld(vif) || !vif->cfg.assoc)
1254		return -1;
1255
1256	for_each_set_bit(link_id, &usable_links, IEEE80211_MLD_MAX_NUM_LINKS) {
1257		struct ieee80211_bss_conf *link_conf =
1258			link_conf_dereference_protected(vif, link_id);
1259
1260		if (WARN_ON_ONCE(!link_conf))
1261			continue;
1262
1263		data[n_data].link_id = link_id;
1264		data[n_data].band = link_conf->chanreq.oper.chan->band;
1265		data[n_data].width = link_conf->chanreq.oper.width;
1266		data[n_data].active = true;
1267		n_data++;
1268	}
1269
1270	if (n_data <= 1)
1271		return -1;
1272
1273	/* The logic should be modified to handle more than 2 links */
1274	WARN_ON_ONCE(n_data > 2);
1275
1276	/* Primary link is the link with the wider bandwidth or higher band */
1277	if (data[0].width > data[1].width)
1278		return data[0].link_id;
1279	if (data[0].width < data[1].width)
1280		return data[1].link_id;
1281	if (data[0].band >= data[1].band)
1282		return data[0].link_id;
1283
1284	return data[1].link_id;
1285}
1286
1287void iwl_mvm_recalc_esr(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
1288{
1289	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1290	bool enable = !mvmvif->esr_disable_reason;
1291	int link_id;
1292
1293	/* Nothing to do */
1294	if (mvmvif->esr_active == enable)
1295		return;
1296
1297	if (enable) {
1298		/* Try to re-enable eSR */
1299		iwl_mvm_mld_select_links(mvm, vif, false);
1300		return;
1301	}
1302
1303	/*
1304	 * Find the primary link, as we want to switch to it and drop the
1305	 * secondary one.
1306	 */
1307	link_id = iwl_mvm_mld_get_primary_link(mvm, vif, vif->active_links);
1308	WARN_ON(link_id < 0);
1309
1310	ieee80211_set_active_links_async(vif,
1311					 vif->active_links & BIT(link_id));
1312}
1313
1314/*
1315 * This function receives a bitmap of usable links and check if we can enter
1316 * eSR on those links.
1317 */
1318static bool iwl_mvm_can_enter_esr(struct iwl_mvm *mvm,
1319				  struct ieee80211_vif *vif,
1320				  unsigned long desired_links)
1321{
1322	u16 usable_links = ieee80211_vif_usable_links(vif);
1323	struct iwl_mvm_link_sel_data data[IEEE80211_MLD_MAX_NUM_LINKS];
1324	const struct wiphy_iftype_ext_capab *ext_capa;
1325	u8 n_data;
1326
1327	if (!ieee80211_vif_is_mld(vif) || !vif->cfg.assoc ||
1328	    hweight16(usable_links) <= 1)
1329		return false;
1330
1331	if (!(vif->cfg.eml_cap & IEEE80211_EML_CAP_EMLSR_SUPP))
1332		return false;
1333
1334	ext_capa = cfg80211_get_iftype_ext_capa(mvm->hw->wiphy,
1335						ieee80211_vif_type_p2p(vif));
1336	if (!ext_capa ||
1337	    !(ext_capa->eml_capabilities & IEEE80211_EML_CAP_EMLSR_SUPP))
1338		return false;
1339
1340	n_data = iwl_mvm_set_link_selection_data(vif, data, desired_links);
1341
1342	if (n_data != 2)
1343		return false;
1344
1345
1346	return iwl_mvm_mld_valid_link_pair(vif, &data[0], &data[1]);
1347}
1348
1349static bool iwl_mvm_mld_can_activate_links(struct ieee80211_hw *hw,
1350					   struct ieee80211_vif *vif,
1351					   u16 desired_links)
1352{
1353	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
1354	int n_links = hweight16(desired_links);
1355	bool ret = true;
1356
1357	if (n_links <= 1)
1358		return true;
1359
1360	mutex_lock(&mvm->mutex);
1361
1362	/* Check if HW supports the wanted number of links */
1363	if (n_links > iwl_mvm_max_active_links(mvm, vif)) {
1364		ret = false;
1365		goto unlock;
1366	}
1367
1368	/* If it is an eSR device, check that we can enter eSR */
1369	if (iwl_mvm_is_esr_supported(mvm->fwrt.trans))
1370		ret = iwl_mvm_can_enter_esr(mvm, vif, desired_links);
1371unlock:
1372	mutex_unlock(&mvm->mutex);
1373	return ret;
1374}
1375
1376static enum ieee80211_neg_ttlm_res
1377iwl_mvm_mld_can_neg_ttlm(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
1378			 struct ieee80211_neg_ttlm *neg_ttlm)
1379{
1380	u16 map;
1381	u8 i;
1382
1383	/* Verify all TIDs are mapped to the same links set */
1384	map = neg_ttlm->downlink[0];
1385	for (i = 0; i < IEEE80211_TTLM_NUM_TIDS; i++) {
1386		if (neg_ttlm->downlink[i] != neg_ttlm->uplink[i] ||
1387		    neg_ttlm->uplink[i] != map)
1388			return NEG_TTLM_RES_REJECT;
1389	}
1390
1391	return NEG_TTLM_RES_ACCEPT;
1392}
1393
1394const struct ieee80211_ops iwl_mvm_mld_hw_ops = {
1395	.tx = iwl_mvm_mac_tx,
1396	.wake_tx_queue = iwl_mvm_mac_wake_tx_queue,
1397	.ampdu_action = iwl_mvm_mac_ampdu_action,
1398	.get_antenna = iwl_mvm_op_get_antenna,
1399	.set_antenna = iwl_mvm_op_set_antenna,
1400	.start = iwl_mvm_mac_start,
1401	.reconfig_complete = iwl_mvm_mac_reconfig_complete,
1402	.stop = iwl_mvm_mac_stop,
1403	.add_interface = iwl_mvm_mld_mac_add_interface,
1404	.remove_interface = iwl_mvm_mld_mac_remove_interface,
1405	.config = iwl_mvm_mac_config,
1406	.prepare_multicast = iwl_mvm_prepare_multicast,
1407	.configure_filter = iwl_mvm_configure_filter,
1408	.config_iface_filter = iwl_mvm_mld_config_iface_filter,
1409	.link_info_changed = iwl_mvm_mld_link_info_changed,
1410	.vif_cfg_changed = iwl_mvm_mld_vif_cfg_changed,
1411	.hw_scan = iwl_mvm_mac_hw_scan,
1412	.cancel_hw_scan = iwl_mvm_mac_cancel_hw_scan,
1413	.sta_pre_rcu_remove = iwl_mvm_sta_pre_rcu_remove,
1414	.sta_state = iwl_mvm_mld_mac_sta_state,
1415	.sta_notify = iwl_mvm_mac_sta_notify,
1416	.allow_buffered_frames = iwl_mvm_mac_allow_buffered_frames,
1417	.release_buffered_frames = iwl_mvm_mac_release_buffered_frames,
1418	.set_rts_threshold = iwl_mvm_mac_set_rts_threshold,
1419	.sta_rc_update = iwl_mvm_sta_rc_update,
1420	.conf_tx = iwl_mvm_mld_mac_conf_tx,
1421	.mgd_prepare_tx = iwl_mvm_mac_mgd_prepare_tx,
1422	.mgd_complete_tx = iwl_mvm_mac_mgd_complete_tx,
1423	.mgd_protect_tdls_discover = iwl_mvm_mac_mgd_protect_tdls_discover,
1424	.flush = iwl_mvm_mac_flush,
1425	.flush_sta = iwl_mvm_mac_flush_sta,
1426	.sched_scan_start = iwl_mvm_mac_sched_scan_start,
1427	.sched_scan_stop = iwl_mvm_mac_sched_scan_stop,
1428	.set_key = iwl_mvm_mac_set_key,
1429	.update_tkip_key = iwl_mvm_mac_update_tkip_key,
1430	.remain_on_channel = iwl_mvm_mld_roc,
1431	.cancel_remain_on_channel = iwl_mvm_cancel_roc,
1432	.add_chanctx = iwl_mvm_add_chanctx,
1433	.remove_chanctx = iwl_mvm_remove_chanctx,
1434	.change_chanctx = iwl_mvm_change_chanctx,
1435	.assign_vif_chanctx = iwl_mvm_mld_assign_vif_chanctx,
1436	.unassign_vif_chanctx = iwl_mvm_mld_unassign_vif_chanctx,
1437	.switch_vif_chanctx = iwl_mvm_mld_switch_vif_chanctx,
1438
1439	.start_ap = iwl_mvm_mld_start_ap,
1440	.stop_ap = iwl_mvm_mld_stop_ap,
1441	.join_ibss = iwl_mvm_mld_start_ibss,
1442	.leave_ibss = iwl_mvm_mld_stop_ibss,
1443
1444	.tx_last_beacon = iwl_mvm_tx_last_beacon,
1445
1446	.channel_switch = iwl_mvm_channel_switch,
1447	.pre_channel_switch = iwl_mvm_pre_channel_switch,
1448	.post_channel_switch = iwl_mvm_post_channel_switch,
1449	.abort_channel_switch = iwl_mvm_abort_channel_switch,
1450	.channel_switch_rx_beacon = iwl_mvm_channel_switch_rx_beacon,
1451
1452	.tdls_channel_switch = iwl_mvm_tdls_channel_switch,
1453	.tdls_cancel_channel_switch = iwl_mvm_tdls_cancel_channel_switch,
1454	.tdls_recv_channel_switch = iwl_mvm_tdls_recv_channel_switch,
1455
1456	.event_callback = iwl_mvm_mac_event_callback,
1457
1458	.sync_rx_queues = iwl_mvm_sync_rx_queues,
1459
1460	CFG80211_TESTMODE_CMD(iwl_mvm_mac_testmode_cmd)
1461
1462#ifdef CONFIG_PM_SLEEP
1463	/* look at d3.c */
1464	.suspend = iwl_mvm_suspend,
1465	.resume = iwl_mvm_resume,
1466	.set_wakeup = iwl_mvm_set_wakeup,
1467	.set_rekey_data = iwl_mvm_set_rekey_data,
1468#if IS_ENABLED(CONFIG_IPV6)
1469	.ipv6_addr_change = iwl_mvm_ipv6_addr_change,
1470#endif
1471	.set_default_unicast_key = iwl_mvm_set_default_unicast_key,
1472#endif
1473	.get_survey = iwl_mvm_mac_get_survey,
1474	.sta_statistics = iwl_mvm_mac_sta_statistics,
1475	.get_ftm_responder_stats = iwl_mvm_mac_get_ftm_responder_stats,
1476	.start_pmsr = iwl_mvm_start_pmsr,
1477	.abort_pmsr = iwl_mvm_abort_pmsr,
1478
1479#ifdef CONFIG_IWLWIFI_DEBUGFS
1480	.vif_add_debugfs = iwl_mvm_vif_add_debugfs,
1481	.link_add_debugfs = iwl_mvm_link_add_debugfs,
1482	.link_sta_add_debugfs = iwl_mvm_link_sta_add_debugfs,
1483#endif
1484	.set_hw_timestamp = iwl_mvm_set_hw_timestamp,
1485
1486	.change_vif_links = iwl_mvm_mld_change_vif_links,
1487	.change_sta_links = iwl_mvm_mld_change_sta_links,
1488	.can_activate_links = iwl_mvm_mld_can_activate_links,
1489	.can_neg_ttlm = iwl_mvm_mld_can_neg_ttlm,
1490};