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