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