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 
7 static 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 
14 	mutex_lock(&mvm->mutex);
15 
16 	iwl_mvm_mac_init_mvmvif(mvm, mvmvif);
17 
18 	mvmvif->mvm = mvm;
19 
20 	/* Not much to do here. The stack will not allow interface
21 	 * types or combinations that we didn't advertise, so we
22 	 * don't really have to check the types.
23 	 */
24 
25 	/* make sure that beacon statistics don't go backwards with FW reset */
26 	if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
27 		mvmvif->deflink.beacon_stats.accu_num_beacons +=
28 			mvmvif->deflink.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 	iwl_mvm_vif_dbgfs_register(mvm, vif);
85 
86 	if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) &&
87 	    vif->type == NL80211_IFTYPE_STATION && !vif->p2p &&
88 	    !mvm->csme_vif && mvm->mei_registered) {
89 		iwl_mei_set_nic_info(vif->addr, mvm->nvm_data->hw_addr);
90 		iwl_mei_set_netdev(ieee80211_vif_to_wdev(vif)->netdev);
91 		mvm->csme_vif = vif;
92 	}
93 
94 	goto out_unlock;
95 
96  out_free_bf:
97 	if (mvm->bf_allowed_vif == mvmvif) {
98 		mvm->bf_allowed_vif = NULL;
99 		vif->driver_flags &= ~(IEEE80211_VIF_BEACON_FILTER |
100 				       IEEE80211_VIF_SUPPORTS_CQM_RSSI);
101 	}
102  out_remove_mac:
103 	mvmvif->link[0] = NULL;
104 	iwl_mvm_mld_mac_ctxt_remove(mvm, vif);
105  out_unlock:
106 	mutex_unlock(&mvm->mutex);
107 
108 	return ret;
109 }
110 
111 static void iwl_mvm_mld_mac_remove_interface(struct ieee80211_hw *hw,
112 					     struct ieee80211_vif *vif)
113 {
114 	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
115 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
116 	struct iwl_probe_resp_data *probe_data;
117 
118 	iwl_mvm_prepare_mac_removal(mvm, vif);
119 
120 	if (!(vif->type == NL80211_IFTYPE_AP ||
121 	      vif->type == NL80211_IFTYPE_ADHOC))
122 		iwl_mvm_tcm_rm_vif(mvm, vif);
123 
124 	mutex_lock(&mvm->mutex);
125 
126 	if (vif == mvm->csme_vif) {
127 		iwl_mei_set_netdev(NULL);
128 		mvm->csme_vif = NULL;
129 	}
130 
131 	if (mvm->bf_allowed_vif == mvmvif) {
132 		mvm->bf_allowed_vif = NULL;
133 		vif->driver_flags &= ~(IEEE80211_VIF_BEACON_FILTER |
134 				       IEEE80211_VIF_SUPPORTS_CQM_RSSI);
135 	}
136 
137 	if (vif->bss_conf.ftm_responder)
138 		memset(&mvm->ftm_resp_stats, 0, sizeof(mvm->ftm_resp_stats));
139 
140 	iwl_mvm_vif_dbgfs_clean(mvm, vif);
141 
142 	/* For AP/GO interface, the tear down of the resources allocated to the
143 	 * interface is be handled as part of the stop_ap flow.
144 	 */
145 	if (vif->type == NL80211_IFTYPE_AP ||
146 	    vif->type == NL80211_IFTYPE_ADHOC) {
147 #ifdef CONFIG_NL80211_TESTMODE
148 		if (vif == mvm->noa_vif) {
149 			mvm->noa_vif = NULL;
150 			mvm->noa_duration = 0;
151 		}
152 #endif
153 	}
154 
155 	iwl_mvm_power_update_mac(mvm);
156 
157 	/* Before the interface removal, mac80211 would cancel the ROC, and the
158 	 * ROC worker would be scheduled if needed. The worker would be flushed
159 	 * in iwl_mvm_prepare_mac_removal() and thus at this point the link is
160 	 * not active. So need only to remove the link.
161 	 */
162 	if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
163 		if (mvmvif->deflink.phy_ctxt) {
164 			iwl_mvm_phy_ctxt_unref(mvm, mvmvif->deflink.phy_ctxt);
165 			mvmvif->deflink.phy_ctxt = NULL;
166 		}
167 		mvm->p2p_device_vif = NULL;
168 		iwl_mvm_remove_link(mvm, vif, &vif->bss_conf);
169 	} else {
170 		iwl_mvm_disable_link(mvm, vif, &vif->bss_conf);
171 	}
172 
173 	iwl_mvm_mld_mac_ctxt_remove(mvm, vif);
174 
175 	RCU_INIT_POINTER(mvm->vif_id_to_mac[mvmvif->id], NULL);
176 
177 	probe_data = rcu_dereference_protected(mvmvif->deflink.probe_resp_data,
178 					       lockdep_is_held(&mvm->mutex));
179 	RCU_INIT_POINTER(mvmvif->deflink.probe_resp_data, NULL);
180 	if (probe_data)
181 		kfree_rcu(probe_data, rcu_head);
182 
183 	if (vif->type == NL80211_IFTYPE_MONITOR) {
184 		mvm->monitor_on = false;
185 		__clear_bit(IEEE80211_HW_RX_INCLUDES_FCS, mvm->hw->flags);
186 	}
187 
188 	mutex_unlock(&mvm->mutex);
189 }
190 
191 static unsigned int iwl_mvm_mld_count_active_links(struct ieee80211_vif *vif)
192 {
193 	unsigned int n_active = 0;
194 	int i;
195 
196 	for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
197 		struct ieee80211_bss_conf *link_conf;
198 
199 		link_conf = link_conf_dereference_protected(vif, i);
200 		if (link_conf &&
201 		    rcu_access_pointer(link_conf->chanctx_conf))
202 			n_active++;
203 	}
204 
205 	return n_active;
206 }
207 
208 static int iwl_mvm_esr_mode_active(struct iwl_mvm *mvm,
209 				   struct ieee80211_vif *vif)
210 {
211 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
212 	int link_id, ret = 0;
213 
214 	mvmvif->esr_active = true;
215 
216 	/* Disable SMPS overrideing by user */
217 	vif->driver_flags |= IEEE80211_VIF_DISABLE_SMPS_OVERRIDE;
218 
219 	iwl_mvm_update_smps_on_active_links(mvm, vif, IWL_MVM_SMPS_REQ_FW,
220 					    IEEE80211_SMPS_OFF);
221 
222 	for_each_mvm_vif_valid_link(mvmvif, link_id) {
223 		struct iwl_mvm_vif_link_info *link = mvmvif->link[link_id];
224 
225 		if (!link->phy_ctxt)
226 			continue;
227 
228 		ret = iwl_mvm_phy_send_rlc(mvm, link->phy_ctxt, 2, 2);
229 		if (ret)
230 			break;
231 
232 		link->phy_ctxt->rlc_disabled = true;
233 	}
234 
235 	return ret;
236 }
237 
238 static int
239 __iwl_mvm_mld_assign_vif_chanctx(struct iwl_mvm *mvm,
240 				 struct ieee80211_vif *vif,
241 				 struct ieee80211_bss_conf *link_conf,
242 				 struct ieee80211_chanctx_conf *ctx,
243 				 bool switching_chanctx)
244 {
245 	u16 *phy_ctxt_id = (u16 *)ctx->drv_priv;
246 	struct iwl_mvm_phy_ctxt *phy_ctxt = &mvm->phy_ctxts[*phy_ctxt_id];
247 	unsigned int n_active = iwl_mvm_mld_count_active_links(vif);
248 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
249 	unsigned int link_id = link_conf->link_id;
250 	int ret;
251 
252 	/* if the assigned one was not counted yet, count it now */
253 	if (!rcu_access_pointer(link_conf->chanctx_conf))
254 		n_active++;
255 
256 	if (n_active > iwl_mvm_max_active_links(mvm, vif))
257 		return -EOPNOTSUPP;
258 
259 	if (WARN_ON_ONCE(!mvmvif->link[link_id]))
260 		return -EINVAL;
261 
262 	/* mac parameters such as HE support can change at this stage
263 	 * For sta, need first to configure correct state from drv_sta_state
264 	 * and only after that update mac config.
265 	 */
266 	if (vif->type == NL80211_IFTYPE_AP) {
267 		ret = iwl_mvm_mld_mac_ctxt_changed(mvm, vif, false);
268 		if (ret) {
269 			IWL_ERR(mvm, "failed to update MAC %pM\n", vif->addr);
270 			return -EINVAL;
271 		}
272 	}
273 
274 	mvmvif->link[link_id]->phy_ctxt = phy_ctxt;
275 
276 	if (iwl_mvm_is_esr_supported(mvm->fwrt.trans) && n_active > 1) {
277 		mvmvif->link[link_id]->listen_lmac = true;
278 		ret = iwl_mvm_esr_mode_active(mvm, vif);
279 		if (ret) {
280 			IWL_ERR(mvm, "failed to activate ESR mode (%d)\n", ret);
281 			goto out;
282 		}
283 	}
284 
285 	if (switching_chanctx) {
286 		/* reactivate if we turned this off during channel switch */
287 		if (vif->type == NL80211_IFTYPE_AP)
288 			mvmvif->ap_ibss_active = true;
289 	}
290 
291 	/* send it first with phy context ID */
292 	ret = iwl_mvm_link_changed(mvm, vif, link_conf, 0, false);
293 	if (ret)
294 		goto out;
295 
296 	/* Initialize rate control for the AP station, since we might be
297 	 * doing a link switch here - we cannot initialize it before since
298 	 * this needs the phy context assigned (and in FW?), and we cannot
299 	 * do it later because it needs to be initialized as soon as we're
300 	 * able to TX on the link, i.e. when active.
301 	 */
302 	if (mvmvif->ap_sta) {
303 		struct ieee80211_link_sta *link_sta;
304 
305 		rcu_read_lock();
306 		link_sta = rcu_dereference(mvmvif->ap_sta->link[link_id]);
307 
308 		if (!WARN_ON_ONCE(!link_sta))
309 			iwl_mvm_rs_rate_init(mvm, vif, mvmvif->ap_sta,
310 					     link_conf, link_sta,
311 					     phy_ctxt->channel->band);
312 		rcu_read_unlock();
313 	}
314 
315 	/* then activate */
316 	ret = iwl_mvm_link_changed(mvm, vif, link_conf,
317 				   LINK_CONTEXT_MODIFY_ACTIVE |
318 				   LINK_CONTEXT_MODIFY_RATES_INFO,
319 				   true);
320 	if (ret)
321 		goto out;
322 
323 	/*
324 	 * Power state must be updated before quotas,
325 	 * otherwise fw will complain.
326 	 */
327 	iwl_mvm_power_update_mac(mvm);
328 
329 	if (vif->type == NL80211_IFTYPE_MONITOR) {
330 		ret = iwl_mvm_mld_add_snif_sta(mvm, vif, link_conf);
331 		if (ret)
332 			goto deactivate;
333 	}
334 
335 	return 0;
336 
337 deactivate:
338 	iwl_mvm_link_changed(mvm, vif, link_conf, LINK_CONTEXT_MODIFY_ACTIVE,
339 			     false);
340 out:
341 	mvmvif->link[link_id]->phy_ctxt = NULL;
342 	iwl_mvm_power_update_mac(mvm);
343 	return ret;
344 }
345 
346 static int iwl_mvm_mld_assign_vif_chanctx(struct ieee80211_hw *hw,
347 					  struct ieee80211_vif *vif,
348 					  struct ieee80211_bss_conf *link_conf,
349 					  struct ieee80211_chanctx_conf *ctx)
350 {
351 	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
352 	int ret;
353 
354 	mutex_lock(&mvm->mutex);
355 	ret = __iwl_mvm_mld_assign_vif_chanctx(mvm, vif, link_conf, ctx, false);
356 	mutex_unlock(&mvm->mutex);
357 
358 	return ret;
359 }
360 
361 static int iwl_mvm_esr_mode_inactive(struct iwl_mvm *mvm,
362 				     struct ieee80211_vif *vif)
363 {
364 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
365 	struct ieee80211_bss_conf *link_conf;
366 	int link_id, ret = 0;
367 
368 	mvmvif->esr_active = false;
369 
370 	vif->driver_flags &= ~IEEE80211_VIF_DISABLE_SMPS_OVERRIDE;
371 
372 	iwl_mvm_update_smps_on_active_links(mvm, vif, IWL_MVM_SMPS_REQ_FW,
373 					    IEEE80211_SMPS_AUTOMATIC);
374 
375 	for_each_vif_active_link(vif, link_conf, link_id) {
376 		struct ieee80211_chanctx_conf *chanctx_conf;
377 		struct iwl_mvm_phy_ctxt *phy_ctxt;
378 		u8 static_chains, dynamic_chains;
379 
380 		mvmvif->link[link_id]->listen_lmac = false;
381 
382 		rcu_read_lock();
383 
384 		chanctx_conf = rcu_dereference(link_conf->chanctx_conf);
385 		phy_ctxt = mvmvif->link[link_id]->phy_ctxt;
386 
387 		if (!chanctx_conf || !phy_ctxt) {
388 			rcu_read_unlock();
389 			continue;
390 		}
391 
392 		phy_ctxt->rlc_disabled = false;
393 		static_chains = chanctx_conf->rx_chains_static;
394 		dynamic_chains = chanctx_conf->rx_chains_dynamic;
395 
396 		rcu_read_unlock();
397 
398 		ret = iwl_mvm_phy_send_rlc(mvm, phy_ctxt, static_chains,
399 					   dynamic_chains);
400 		if (ret)
401 			break;
402 	}
403 
404 	return ret;
405 }
406 
407 static void
408 __iwl_mvm_mld_unassign_vif_chanctx(struct iwl_mvm *mvm,
409 				   struct ieee80211_vif *vif,
410 				   struct ieee80211_bss_conf *link_conf,
411 				   struct ieee80211_chanctx_conf *ctx,
412 				   bool switching_chanctx)
413 
414 {
415 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
416 	unsigned int n_active = iwl_mvm_mld_count_active_links(vif);
417 	unsigned int link_id = link_conf->link_id;
418 
419 	/* shouldn't happen, but verify link_id is valid before accessing */
420 	if (WARN_ON_ONCE(!mvmvif->link[link_id]))
421 		return;
422 
423 	if (vif->type == NL80211_IFTYPE_AP && switching_chanctx) {
424 		mvmvif->csa_countdown = false;
425 
426 		/* Set CS bit on all the stations */
427 		iwl_mvm_modify_all_sta_disable_tx(mvm, mvmvif, true);
428 
429 		/* Save blocked iface, the timeout is set on the next beacon */
430 		rcu_assign_pointer(mvm->csa_tx_blocked_vif, vif);
431 
432 		mvmvif->ap_ibss_active = false;
433 	}
434 
435 	iwl_mvm_link_changed(mvm, vif, link_conf,
436 			     LINK_CONTEXT_MODIFY_ACTIVE, false);
437 
438 	if (iwl_mvm_is_esr_supported(mvm->fwrt.trans) && n_active > 1) {
439 		int ret = iwl_mvm_esr_mode_inactive(mvm, vif);
440 
441 		if (ret)
442 			IWL_ERR(mvm, "failed to deactivate ESR mode (%d)\n",
443 				ret);
444 	}
445 
446 	if (vif->type == NL80211_IFTYPE_MONITOR)
447 		iwl_mvm_mld_rm_snif_sta(mvm, vif);
448 
449 	if (switching_chanctx)
450 		return;
451 	mvmvif->link[link_id]->phy_ctxt = NULL;
452 	iwl_mvm_power_update_mac(mvm);
453 }
454 
455 static void iwl_mvm_mld_unassign_vif_chanctx(struct ieee80211_hw *hw,
456 					     struct ieee80211_vif *vif,
457 					     struct ieee80211_bss_conf *link_conf,
458 					     struct ieee80211_chanctx_conf *ctx)
459 {
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 	mutex_unlock(&mvm->mutex);
465 }
466 
467 static int iwl_mvm_mld_start_ap_ibss(struct ieee80211_hw *hw,
468 				     struct ieee80211_vif *vif,
469 				     struct ieee80211_bss_conf *link_conf)
470 {
471 	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
472 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
473 	int ret;
474 
475 	mutex_lock(&mvm->mutex);
476 	/* Send the beacon template */
477 	ret = iwl_mvm_mac_ctxt_beacon_changed(mvm, vif, link_conf);
478 	if (ret)
479 		goto out_unlock;
480 
481 	/* the link should be already activated when assigning chan context */
482 	ret = iwl_mvm_link_changed(mvm, vif, link_conf,
483 				   LINK_CONTEXT_MODIFY_ALL &
484 				   ~LINK_CONTEXT_MODIFY_ACTIVE,
485 				   true);
486 	if (ret)
487 		goto out_unlock;
488 
489 	ret = iwl_mvm_mld_add_mcast_sta(mvm, vif, link_conf);
490 	if (ret)
491 		goto out_unlock;
492 
493 	/* Send the bcast station. At this stage the TBTT and DTIM time
494 	 * events are added and applied to the scheduler
495 	 */
496 	ret = iwl_mvm_mld_add_bcast_sta(mvm, vif, link_conf);
497 	if (ret)
498 		goto out_rm_mcast;
499 
500 	if (iwl_mvm_start_ap_ibss_common(hw, vif, &ret))
501 		goto out_failed;
502 
503 	/* Need to update the P2P Device MAC (only GO, IBSS is single vif) */
504 	if (vif->p2p && mvm->p2p_device_vif)
505 		iwl_mvm_mld_mac_ctxt_changed(mvm, mvm->p2p_device_vif, false);
506 
507 	iwl_mvm_bt_coex_vif_change(mvm);
508 
509 	/* we don't support TDLS during DCM */
510 	if (iwl_mvm_phy_ctx_count(mvm) > 1)
511 		iwl_mvm_teardown_tdls_peers(mvm);
512 
513 	iwl_mvm_ftm_restart_responder(mvm, vif, link_conf);
514 
515 	goto out_unlock;
516 
517 out_failed:
518 	iwl_mvm_power_update_mac(mvm);
519 	mvmvif->ap_ibss_active = false;
520 	iwl_mvm_mld_rm_bcast_sta(mvm, vif, link_conf);
521 out_rm_mcast:
522 	iwl_mvm_mld_rm_mcast_sta(mvm, vif, link_conf);
523 out_unlock:
524 	mutex_unlock(&mvm->mutex);
525 	return ret;
526 }
527 
528 static int iwl_mvm_mld_start_ap(struct ieee80211_hw *hw,
529 				struct ieee80211_vif *vif,
530 				struct ieee80211_bss_conf *link_conf)
531 {
532 	return iwl_mvm_mld_start_ap_ibss(hw, vif, link_conf);
533 }
534 
535 static int iwl_mvm_mld_start_ibss(struct ieee80211_hw *hw,
536 				  struct ieee80211_vif *vif)
537 {
538 	return iwl_mvm_mld_start_ap_ibss(hw, vif, &vif->bss_conf);
539 }
540 
541 static void iwl_mvm_mld_stop_ap_ibss(struct ieee80211_hw *hw,
542 				     struct ieee80211_vif *vif,
543 				     struct ieee80211_bss_conf *link_conf)
544 {
545 	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
546 
547 	mutex_lock(&mvm->mutex);
548 
549 	iwl_mvm_stop_ap_ibss_common(mvm, vif);
550 
551 	/* Need to update the P2P Device MAC (only GO, IBSS is single vif) */
552 	if (vif->p2p && mvm->p2p_device_vif)
553 		iwl_mvm_mld_mac_ctxt_changed(mvm, mvm->p2p_device_vif, false);
554 
555 	iwl_mvm_ftm_responder_clear(mvm, vif);
556 
557 	iwl_mvm_mld_rm_bcast_sta(mvm, vif, link_conf);
558 	iwl_mvm_mld_rm_mcast_sta(mvm, vif, link_conf);
559 
560 	iwl_mvm_power_update_mac(mvm);
561 	mutex_unlock(&mvm->mutex);
562 }
563 
564 static void iwl_mvm_mld_stop_ap(struct ieee80211_hw *hw,
565 				struct ieee80211_vif *vif,
566 				struct ieee80211_bss_conf *link_conf)
567 {
568 	iwl_mvm_mld_stop_ap_ibss(hw, vif, link_conf);
569 }
570 
571 static void iwl_mvm_mld_stop_ibss(struct ieee80211_hw *hw,
572 				  struct ieee80211_vif *vif)
573 {
574 	iwl_mvm_mld_stop_ap_ibss(hw, vif, &vif->bss_conf);
575 }
576 
577 static int iwl_mvm_mld_mac_sta_state(struct ieee80211_hw *hw,
578 				     struct ieee80211_vif *vif,
579 				     struct ieee80211_sta *sta,
580 				     enum ieee80211_sta_state old_state,
581 				     enum ieee80211_sta_state new_state)
582 {
583 	static const struct iwl_mvm_sta_state_ops callbacks = {
584 		.add_sta = iwl_mvm_mld_add_sta,
585 		.update_sta = iwl_mvm_mld_update_sta,
586 		.rm_sta = iwl_mvm_mld_rm_sta,
587 		.mac_ctxt_changed = iwl_mvm_mld_mac_ctxt_changed,
588 	};
589 
590 	return iwl_mvm_mac_sta_state_common(hw, vif, sta, old_state, new_state,
591 					    &callbacks);
592 }
593 
594 static void
595 iwl_mvm_mld_link_info_changed_station(struct iwl_mvm *mvm,
596 				      struct ieee80211_vif *vif,
597 				      struct ieee80211_bss_conf *link_conf,
598 				      u64 changes)
599 {
600 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
601 	bool has_he, has_eht;
602 	u32 link_changes = 0;
603 	int ret;
604 
605 	if (WARN_ON_ONCE(!mvmvif->link[link_conf->link_id]))
606 		return;
607 
608 	has_he = link_conf->he_support && !iwlwifi_mod_params.disable_11ax;
609 	has_eht = link_conf->eht_support && !iwlwifi_mod_params.disable_11be;
610 
611 	/* Update EDCA params */
612 	if (changes & BSS_CHANGED_QOS && vif->cfg.assoc && link_conf->qos)
613 		link_changes |= LINK_CONTEXT_MODIFY_QOS_PARAMS;
614 
615 	if (changes & BSS_CHANGED_ERP_SLOT)
616 		link_changes |= LINK_CONTEXT_MODIFY_RATES_INFO;
617 
618 	if (vif->cfg.assoc && (has_he || has_eht)) {
619 		IWL_DEBUG_MAC80211(mvm, "Associated in HE mode\n");
620 		link_changes |= LINK_CONTEXT_MODIFY_HE_PARAMS;
621 	}
622 
623 	/* Update EHT Puncturing info */
624 	if (changes & BSS_CHANGED_EHT_PUNCTURING && vif->cfg.assoc)
625 		link_changes |= LINK_CONTEXT_MODIFY_EHT_PARAMS;
626 
627 	if (link_changes) {
628 		ret = iwl_mvm_link_changed(mvm, vif, link_conf, link_changes,
629 					   true);
630 		if (ret)
631 			IWL_ERR(mvm, "failed to update link\n");
632 	}
633 
634 	ret = iwl_mvm_mld_mac_ctxt_changed(mvm, vif, false);
635 	if (ret)
636 		IWL_ERR(mvm, "failed to update MAC %pM\n", vif->addr);
637 
638 	memcpy(mvmvif->link[link_conf->link_id]->bssid, link_conf->bssid,
639 	       ETH_ALEN);
640 
641 	iwl_mvm_bss_info_changed_station_common(mvm, vif, link_conf, changes);
642 }
643 
644 static bool iwl_mvm_mld_vif_have_valid_ap_sta(struct iwl_mvm_vif *mvmvif)
645 {
646 	int i;
647 
648 	for_each_mvm_vif_valid_link(mvmvif, i) {
649 		if (mvmvif->link[i]->ap_sta_id != IWL_MVM_INVALID_STA)
650 			return true;
651 	}
652 
653 	return false;
654 }
655 
656 static void iwl_mvm_mld_vif_delete_all_stas(struct iwl_mvm *mvm,
657 					    struct ieee80211_vif *vif)
658 {
659 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
660 	int i, ret;
661 
662 	if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
663 		return;
664 
665 	for_each_mvm_vif_valid_link(mvmvif, i) {
666 		struct iwl_mvm_vif_link_info *link = mvmvif->link[i];
667 
668 		if (!link)
669 			continue;
670 
671 		iwl_mvm_sec_key_remove_ap(mvm, vif, link, i);
672 		ret = iwl_mvm_mld_rm_sta_id(mvm, link->ap_sta_id);
673 		if (ret)
674 			IWL_ERR(mvm, "failed to remove AP station\n");
675 
676 		link->ap_sta_id = IWL_MVM_INVALID_STA;
677 	}
678 }
679 
680 static void iwl_mvm_mld_vif_cfg_changed_station(struct iwl_mvm *mvm,
681 						struct ieee80211_vif *vif,
682 						u64 changes)
683 {
684 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
685 	struct ieee80211_bss_conf *link_conf;
686 	bool protect = false;
687 	unsigned int i;
688 	int ret;
689 
690 	/* This might get called without active links during the
691 	 * chanctx switch, but we don't care about it anyway.
692 	 */
693 	if (changes == BSS_CHANGED_IDLE)
694 		return;
695 
696 	ret = iwl_mvm_mld_mac_ctxt_changed(mvm, vif, false);
697 	if (ret)
698 		IWL_ERR(mvm, "failed to update MAC %pM\n", vif->addr);
699 
700 	mvmvif->associated = vif->cfg.assoc;
701 
702 	if (changes & BSS_CHANGED_ASSOC) {
703 		if (vif->cfg.assoc) {
704 			/* clear statistics to get clean beacon counter */
705 			iwl_mvm_request_statistics(mvm, true);
706 			iwl_mvm_sf_update(mvm, vif, false);
707 			iwl_mvm_power_vif_assoc(mvm, vif);
708 
709 			for_each_mvm_vif_valid_link(mvmvif, i) {
710 				memset(&mvmvif->link[i]->beacon_stats, 0,
711 				       sizeof(mvmvif->link[i]->beacon_stats));
712 
713 				if (vif->p2p) {
714 					iwl_mvm_update_smps(mvm, vif,
715 							    IWL_MVM_SMPS_REQ_PROT,
716 							    IEEE80211_SMPS_DYNAMIC, i);
717 				}
718 
719 				rcu_read_lock();
720 				link_conf = rcu_dereference(vif->link_conf[i]);
721 				if (link_conf && !link_conf->dtim_period)
722 					protect = true;
723 				rcu_read_unlock();
724 			}
725 
726 			if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) &&
727 			    protect) {
728 				/* If we're not restarting and still haven't
729 				 * heard a beacon (dtim period unknown) then
730 				 * make sure we still have enough minimum time
731 				 * remaining in the time event, since the auth
732 				 * might actually have taken quite a while
733 				 * (especially for SAE) and so the remaining
734 				 * time could be small without us having heard
735 				 * a beacon yet.
736 				 */
737 				iwl_mvm_protect_assoc(mvm, vif, 0);
738 			}
739 
740 			iwl_mvm_sf_update(mvm, vif, false);
741 
742 			/* FIXME: need to decide about misbehaving AP handling */
743 			iwl_mvm_power_vif_assoc(mvm, vif);
744 		} else if (iwl_mvm_mld_vif_have_valid_ap_sta(mvmvif)) {
745 			iwl_mvm_mei_host_disassociated(mvm);
746 
747 			/* If update fails - SF might be running in associated
748 			 * mode while disassociated - which is forbidden.
749 			 */
750 			ret = iwl_mvm_sf_update(mvm, vif, false);
751 			WARN_ONCE(ret &&
752 				  !test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED,
753 					    &mvm->status),
754 				  "Failed to update SF upon disassociation\n");
755 
756 			/* If we get an assert during the connection (after the
757 			 * station has been added, but before the vif is set
758 			 * to associated), mac80211 will re-add the station and
759 			 * then configure the vif. Since the vif is not
760 			 * associated, we would remove the station here and
761 			 * this would fail the recovery.
762 			 */
763 			iwl_mvm_mld_vif_delete_all_stas(mvm, vif);
764 		}
765 
766 		iwl_mvm_bss_info_changed_station_assoc(mvm, vif, changes);
767 	}
768 
769 	if (changes & BSS_CHANGED_PS) {
770 		ret = iwl_mvm_power_update_mac(mvm);
771 		if (ret)
772 			IWL_ERR(mvm, "failed to update power mode\n");
773 	}
774 }
775 
776 static void
777 iwl_mvm_mld_link_info_changed_ap_ibss(struct iwl_mvm *mvm,
778 				      struct ieee80211_vif *vif,
779 				      struct ieee80211_bss_conf *link_conf,
780 				      u64 changes)
781 {
782 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
783 	u32 link_changes = LINK_CONTEXT_MODIFY_PROTECT_FLAGS |
784 			   LINK_CONTEXT_MODIFY_QOS_PARAMS;
785 
786 	/* Changes will be applied when the AP/IBSS is started */
787 	if (!mvmvif->ap_ibss_active)
788 		return;
789 
790 	if (link_conf->he_support)
791 		link_changes |= LINK_CONTEXT_MODIFY_HE_PARAMS;
792 
793 	if (changes & BSS_CHANGED_ERP_SLOT)
794 		link_changes |= LINK_CONTEXT_MODIFY_RATES_INFO;
795 
796 	if (changes & (BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_ERP_SLOT |
797 		       BSS_CHANGED_HT |
798 		       BSS_CHANGED_BANDWIDTH | BSS_CHANGED_QOS |
799 		       BSS_CHANGED_HE_BSS_COLOR) &&
800 		       iwl_mvm_link_changed(mvm, vif, link_conf,
801 					    link_changes, true))
802 		IWL_ERR(mvm, "failed to update MAC %pM\n", vif->addr);
803 
804 	/* Need to send a new beacon template to the FW */
805 	if (changes & BSS_CHANGED_BEACON &&
806 	    iwl_mvm_mac_ctxt_beacon_changed(mvm, vif, link_conf))
807 		IWL_WARN(mvm, "Failed updating beacon data\n");
808 
809 	/* FIXME: need to decide if we need FTM responder per link */
810 	if (changes & BSS_CHANGED_FTM_RESPONDER) {
811 		int ret = iwl_mvm_ftm_start_responder(mvm, vif, link_conf);
812 
813 		if (ret)
814 			IWL_WARN(mvm, "Failed to enable FTM responder (%d)\n",
815 				 ret);
816 	}
817 }
818 
819 static void iwl_mvm_mld_link_info_changed(struct ieee80211_hw *hw,
820 					  struct ieee80211_vif *vif,
821 					  struct ieee80211_bss_conf *link_conf,
822 					  u64 changes)
823 {
824 	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
825 
826 	mutex_lock(&mvm->mutex);
827 
828 	switch (vif->type) {
829 	case NL80211_IFTYPE_STATION:
830 		iwl_mvm_mld_link_info_changed_station(mvm, vif, link_conf,
831 						      changes);
832 		break;
833 	case NL80211_IFTYPE_AP:
834 	case NL80211_IFTYPE_ADHOC:
835 		iwl_mvm_mld_link_info_changed_ap_ibss(mvm, vif, link_conf,
836 						      changes);
837 		break;
838 	case NL80211_IFTYPE_MONITOR:
839 		if (changes & BSS_CHANGED_MU_GROUPS)
840 			iwl_mvm_update_mu_groups(mvm, vif);
841 		break;
842 	default:
843 		/* shouldn't happen */
844 		WARN_ON_ONCE(1);
845 	}
846 
847 	if (changes & BSS_CHANGED_TXPOWER) {
848 		IWL_DEBUG_CALIB(mvm, "Changing TX Power to %d dBm\n",
849 				link_conf->txpower);
850 		iwl_mvm_set_tx_power(mvm, vif, link_conf->txpower);
851 	}
852 
853 	mutex_unlock(&mvm->mutex);
854 }
855 
856 static void iwl_mvm_mld_vif_cfg_changed(struct ieee80211_hw *hw,
857 					struct ieee80211_vif *vif,
858 					u64 changes)
859 {
860 	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
861 
862 	mutex_lock(&mvm->mutex);
863 
864 	if (changes & BSS_CHANGED_IDLE && !vif->cfg.idle)
865 		iwl_mvm_scan_stop(mvm, IWL_MVM_SCAN_SCHED, true);
866 
867 	if (vif->type == NL80211_IFTYPE_STATION)
868 		iwl_mvm_mld_vif_cfg_changed_station(mvm, vif, changes);
869 
870 	mutex_unlock(&mvm->mutex);
871 }
872 
873 static int
874 iwl_mvm_mld_switch_vif_chanctx(struct ieee80211_hw *hw,
875 			       struct ieee80211_vif_chanctx_switch *vifs,
876 			       int n_vifs,
877 			       enum ieee80211_chanctx_switch_mode mode)
878 {
879 	static const struct iwl_mvm_switch_vif_chanctx_ops ops = {
880 		.__assign_vif_chanctx = __iwl_mvm_mld_assign_vif_chanctx,
881 		.__unassign_vif_chanctx = __iwl_mvm_mld_unassign_vif_chanctx,
882 	};
883 
884 	return iwl_mvm_switch_vif_chanctx_common(hw, vifs, n_vifs, mode, &ops);
885 }
886 
887 static void iwl_mvm_mld_config_iface_filter(struct ieee80211_hw *hw,
888 					    struct ieee80211_vif *vif,
889 					    unsigned int filter_flags,
890 					    unsigned int changed_flags)
891 {
892 	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
893 
894 	/* We support only filter for probe requests */
895 	if (!(changed_flags & FIF_PROBE_REQ))
896 		return;
897 
898 	/* Supported only for p2p client interfaces */
899 	if (vif->type != NL80211_IFTYPE_STATION || !vif->cfg.assoc ||
900 	    !vif->p2p)
901 		return;
902 
903 	mutex_lock(&mvm->mutex);
904 	iwl_mvm_mld_mac_ctxt_changed(mvm, vif, false);
905 	mutex_unlock(&mvm->mutex);
906 }
907 
908 static int
909 iwl_mvm_mld_mac_conf_tx(struct ieee80211_hw *hw,
910 			struct ieee80211_vif *vif,
911 			unsigned int link_id, u16 ac,
912 			const struct ieee80211_tx_queue_params *params)
913 {
914 	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
915 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
916 	struct iwl_mvm_vif_link_info *mvm_link = mvmvif->link[link_id];
917 
918 	if (!mvm_link)
919 		return -EINVAL;
920 
921 	mvm_link->queue_params[ac] = *params;
922 
923 	/* No need to update right away, we'll get BSS_CHANGED_QOS
924 	 * The exception is P2P_DEVICE interface which needs immediate update.
925 	 */
926 	if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
927 		int ret;
928 
929 		mutex_lock(&mvm->mutex);
930 		ret = iwl_mvm_link_changed(mvm, vif, &vif->bss_conf,
931 					   LINK_CONTEXT_MODIFY_QOS_PARAMS,
932 					   true);
933 		mutex_unlock(&mvm->mutex);
934 		return ret;
935 	}
936 	return 0;
937 }
938 
939 static int iwl_mvm_mld_roc_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
940 {
941 	int ret;
942 
943 	lockdep_assert_held(&mvm->mutex);
944 
945 	/* The PHY context ID might have changed so need to set it */
946 	ret = iwl_mvm_link_changed(mvm, vif, &vif->bss_conf, 0, false);
947 	if (WARN(ret, "Failed to set PHY context ID\n"))
948 		return ret;
949 
950 	ret = iwl_mvm_link_changed(mvm, vif, &vif->bss_conf,
951 				   LINK_CONTEXT_MODIFY_ACTIVE |
952 				   LINK_CONTEXT_MODIFY_RATES_INFO,
953 				   true);
954 
955 	if (WARN(ret, "Failed linking P2P_DEVICE\n"))
956 		return ret;
957 
958 	/* The station and queue allocation must be done only after the linking
959 	 * is done, as otherwise the FW might incorrectly configure its state.
960 	 */
961 	return iwl_mvm_mld_add_bcast_sta(mvm, vif, &vif->bss_conf);
962 }
963 
964 static int iwl_mvm_mld_roc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
965 			   struct ieee80211_channel *channel, int duration,
966 			   enum ieee80211_roc_type type)
967 {
968 	static const struct iwl_mvm_roc_ops ops = {
969 		.add_aux_sta_for_hs20 = iwl_mvm_mld_add_aux_sta,
970 		.link = iwl_mvm_mld_roc_link,
971 	};
972 
973 	return iwl_mvm_roc_common(hw, vif, channel, duration, type, &ops);
974 }
975 
976 static int
977 iwl_mvm_mld_change_vif_links(struct ieee80211_hw *hw,
978 			     struct ieee80211_vif *vif,
979 			     u16 old_links, u16 new_links,
980 			     struct ieee80211_bss_conf *old[IEEE80211_MLD_MAX_NUM_LINKS])
981 {
982 	struct iwl_mvm_vif_link_info *new_link[IEEE80211_MLD_MAX_NUM_LINKS] = {};
983 	unsigned int n_active = iwl_mvm_mld_count_active_links(vif);
984 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
985 	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
986 	u16 removed = old_links & ~new_links;
987 	u16 added = new_links & ~old_links;
988 	int err, i;
989 
990 	if (hweight16(new_links) > 1 &&
991 	    n_active > iwl_mvm_max_active_links(mvm, vif))
992 		return -EOPNOTSUPP;
993 
994 	for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
995 		int r;
996 
997 		if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
998 			break;
999 
1000 		if (!(added & BIT(i)))
1001 			continue;
1002 		new_link[i] = kzalloc(sizeof(*new_link[i]), GFP_KERNEL);
1003 		if (!new_link[i]) {
1004 			err = -ENOMEM;
1005 			goto free;
1006 		}
1007 
1008 		new_link[i]->bcast_sta.sta_id = IWL_MVM_INVALID_STA;
1009 		new_link[i]->mcast_sta.sta_id = IWL_MVM_INVALID_STA;
1010 		new_link[i]->ap_sta_id = IWL_MVM_INVALID_STA;
1011 		new_link[i]->fw_link_id = IWL_MVM_FW_LINK_ID_INVALID;
1012 
1013 		for (r = 0; r < NUM_IWL_MVM_SMPS_REQ; r++)
1014 			new_link[i]->smps_requests[r] =
1015 				IEEE80211_SMPS_AUTOMATIC;
1016 	}
1017 
1018 	mutex_lock(&mvm->mutex);
1019 
1020 	if (old_links == 0) {
1021 		err = iwl_mvm_disable_link(mvm, vif, &vif->bss_conf);
1022 		if (err)
1023 			goto out_err;
1024 		mvmvif->link[0] = NULL;
1025 	}
1026 
1027 	for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
1028 		if (removed & BIT(i)) {
1029 			struct ieee80211_bss_conf *link_conf = old[i];
1030 
1031 			err = iwl_mvm_disable_link(mvm, vif, link_conf);
1032 			if (err)
1033 				goto out_err;
1034 			kfree(mvmvif->link[i]);
1035 			mvmvif->link[i] = NULL;
1036 		} else if (added & BIT(i)) {
1037 			struct ieee80211_bss_conf *link_conf;
1038 
1039 			link_conf = link_conf_dereference_protected(vif, i);
1040 			if (WARN_ON(!link_conf))
1041 				continue;
1042 
1043 			if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART,
1044 				      &mvm->status))
1045 				mvmvif->link[i] = new_link[i];
1046 			new_link[i] = NULL;
1047 			err = iwl_mvm_add_link(mvm, vif, link_conf);
1048 			if (err)
1049 				goto out_err;
1050 		}
1051 	}
1052 
1053 	err = 0;
1054 	if (new_links == 0) {
1055 		mvmvif->link[0] = &mvmvif->deflink;
1056 		err = iwl_mvm_add_link(mvm, vif, &vif->bss_conf);
1057 	}
1058 
1059 out_err:
1060 	/* we really don't have a good way to roll back here ... */
1061 	mutex_unlock(&mvm->mutex);
1062 
1063 free:
1064 	for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++)
1065 		kfree(new_link[i]);
1066 	return err;
1067 }
1068 
1069 static int
1070 iwl_mvm_mld_change_sta_links(struct ieee80211_hw *hw,
1071 			     struct ieee80211_vif *vif,
1072 			     struct ieee80211_sta *sta,
1073 			     u16 old_links, u16 new_links)
1074 {
1075 	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
1076 	int ret;
1077 
1078 	mutex_lock(&mvm->mutex);
1079 	ret = iwl_mvm_mld_update_sta_links(mvm, vif, sta, old_links, new_links);
1080 	mutex_unlock(&mvm->mutex);
1081 
1082 	return ret;
1083 }
1084 
1085 const struct ieee80211_ops iwl_mvm_mld_hw_ops = {
1086 	.tx = iwl_mvm_mac_tx,
1087 	.wake_tx_queue = iwl_mvm_mac_wake_tx_queue,
1088 	.ampdu_action = iwl_mvm_mac_ampdu_action,
1089 	.get_antenna = iwl_mvm_op_get_antenna,
1090 	.start = iwl_mvm_mac_start,
1091 	.reconfig_complete = iwl_mvm_mac_reconfig_complete,
1092 	.stop = iwl_mvm_mac_stop,
1093 	.add_interface = iwl_mvm_mld_mac_add_interface,
1094 	.remove_interface = iwl_mvm_mld_mac_remove_interface,
1095 	.config = iwl_mvm_mac_config,
1096 	.prepare_multicast = iwl_mvm_prepare_multicast,
1097 	.configure_filter = iwl_mvm_configure_filter,
1098 	.config_iface_filter = iwl_mvm_mld_config_iface_filter,
1099 	.link_info_changed = iwl_mvm_mld_link_info_changed,
1100 	.vif_cfg_changed = iwl_mvm_mld_vif_cfg_changed,
1101 	.hw_scan = iwl_mvm_mac_hw_scan,
1102 	.cancel_hw_scan = iwl_mvm_mac_cancel_hw_scan,
1103 	.sta_pre_rcu_remove = iwl_mvm_sta_pre_rcu_remove,
1104 	.sta_state = iwl_mvm_mld_mac_sta_state,
1105 	.sta_notify = iwl_mvm_mac_sta_notify,
1106 	.allow_buffered_frames = iwl_mvm_mac_allow_buffered_frames,
1107 	.release_buffered_frames = iwl_mvm_mac_release_buffered_frames,
1108 	.set_rts_threshold = iwl_mvm_mac_set_rts_threshold,
1109 	.sta_rc_update = iwl_mvm_sta_rc_update,
1110 	.conf_tx = iwl_mvm_mld_mac_conf_tx,
1111 	.mgd_prepare_tx = iwl_mvm_mac_mgd_prepare_tx,
1112 	.mgd_complete_tx = iwl_mvm_mac_mgd_complete_tx,
1113 	.mgd_protect_tdls_discover = iwl_mvm_mac_mgd_protect_tdls_discover,
1114 	.flush = iwl_mvm_mac_flush,
1115 	.flush_sta = iwl_mvm_mac_flush_sta,
1116 	.sched_scan_start = iwl_mvm_mac_sched_scan_start,
1117 	.sched_scan_stop = iwl_mvm_mac_sched_scan_stop,
1118 	.set_key = iwl_mvm_mac_set_key,
1119 	.update_tkip_key = iwl_mvm_mac_update_tkip_key,
1120 	.remain_on_channel = iwl_mvm_mld_roc,
1121 	.cancel_remain_on_channel = iwl_mvm_cancel_roc,
1122 	.add_chanctx = iwl_mvm_add_chanctx,
1123 	.remove_chanctx = iwl_mvm_remove_chanctx,
1124 	.change_chanctx = iwl_mvm_change_chanctx,
1125 	.assign_vif_chanctx = iwl_mvm_mld_assign_vif_chanctx,
1126 	.unassign_vif_chanctx = iwl_mvm_mld_unassign_vif_chanctx,
1127 	.switch_vif_chanctx = iwl_mvm_mld_switch_vif_chanctx,
1128 
1129 	.start_ap = iwl_mvm_mld_start_ap,
1130 	.stop_ap = iwl_mvm_mld_stop_ap,
1131 	.join_ibss = iwl_mvm_mld_start_ibss,
1132 	.leave_ibss = iwl_mvm_mld_stop_ibss,
1133 
1134 	.tx_last_beacon = iwl_mvm_tx_last_beacon,
1135 
1136 	.set_tim = iwl_mvm_set_tim,
1137 
1138 	.channel_switch = iwl_mvm_channel_switch,
1139 	.pre_channel_switch = iwl_mvm_pre_channel_switch,
1140 	.post_channel_switch = iwl_mvm_post_channel_switch,
1141 	.abort_channel_switch = iwl_mvm_abort_channel_switch,
1142 	.channel_switch_rx_beacon = iwl_mvm_channel_switch_rx_beacon,
1143 
1144 	.tdls_channel_switch = iwl_mvm_tdls_channel_switch,
1145 	.tdls_cancel_channel_switch = iwl_mvm_tdls_cancel_channel_switch,
1146 	.tdls_recv_channel_switch = iwl_mvm_tdls_recv_channel_switch,
1147 
1148 	.event_callback = iwl_mvm_mac_event_callback,
1149 
1150 	.sync_rx_queues = iwl_mvm_sync_rx_queues,
1151 
1152 	CFG80211_TESTMODE_CMD(iwl_mvm_mac_testmode_cmd)
1153 
1154 #ifdef CONFIG_PM_SLEEP
1155 	/* look at d3.c */
1156 	.suspend = iwl_mvm_suspend,
1157 	.resume = iwl_mvm_resume,
1158 	.set_wakeup = iwl_mvm_set_wakeup,
1159 	.set_rekey_data = iwl_mvm_set_rekey_data,
1160 #if IS_ENABLED(CONFIG_IPV6)
1161 	.ipv6_addr_change = iwl_mvm_ipv6_addr_change,
1162 #endif
1163 	.set_default_unicast_key = iwl_mvm_set_default_unicast_key,
1164 #endif
1165 	.get_survey = iwl_mvm_mac_get_survey,
1166 	.sta_statistics = iwl_mvm_mac_sta_statistics,
1167 	.get_ftm_responder_stats = iwl_mvm_mac_get_ftm_responder_stats,
1168 	.start_pmsr = iwl_mvm_start_pmsr,
1169 	.abort_pmsr = iwl_mvm_abort_pmsr,
1170 
1171 #ifdef CONFIG_IWLWIFI_DEBUGFS
1172 	.link_sta_add_debugfs = iwl_mvm_link_sta_add_debugfs,
1173 #endif
1174 	.set_hw_timestamp = iwl_mvm_set_hw_timestamp,
1175 
1176 	.change_vif_links = iwl_mvm_mld_change_vif_links,
1177 	.change_sta_links = iwl_mvm_mld_change_sta_links,
1178 };
1179