1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
3 * Copyright (C) 2022-2023 Intel Corporation
7 static int iwl_mvm_mld_mac_add_interface(struct ieee80211_hw *hw,
8 struct ieee80211_vif *vif)
10 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
11 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
14 mutex_lock(&mvm->mutex);
18 /* Not much to do here. The stack will not allow interface
19 * types or combinations that we didn't advertise, so we
20 * don't really have to check the types.
23 /* make sure that beacon statistics don't go backwards with FW reset */
24 if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
25 mvmvif->deflink.beacon_stats.accu_num_beacons +=
26 mvmvif->deflink.beacon_stats.num_beacons;
28 /* Allocate resources for the MAC context, and add it to the fw */
29 ret = iwl_mvm_mac_ctxt_init(mvm, vif);
33 rcu_assign_pointer(mvm->vif_id_to_mac[mvmvif->id], vif);
35 mvmvif->features |= hw->netdev_features;
37 /* reset deflink MLO parameters */
38 mvmvif->deflink.fw_link_id = IWL_MVM_FW_LINK_ID_INVALID;
39 mvmvif->deflink.active = 0;
40 /* the first link always points to the default one */
41 mvmvif->link[0] = &mvmvif->deflink;
43 ret = iwl_mvm_mld_mac_ctxt_add(mvm, vif);
47 /* beacon filtering */
48 ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0);
52 if (!mvm->bf_allowed_vif &&
53 vif->type == NL80211_IFTYPE_STATION && !vif->p2p) {
54 mvm->bf_allowed_vif = mvmvif;
55 vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER |
56 IEEE80211_VIF_SUPPORTS_CQM_RSSI;
60 * P2P_DEVICE interface does not have a channel context assigned to it,
61 * so a dedicated PHY context is allocated to it and the corresponding
62 * MAC context is bound to it at this stage.
64 if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
65 mvmvif->deflink.phy_ctxt = iwl_mvm_get_free_phy_ctxt(mvm);
66 if (!mvmvif->deflink.phy_ctxt) {
71 iwl_mvm_phy_ctxt_ref(mvm, mvmvif->deflink.phy_ctxt);
72 ret = iwl_mvm_add_link(mvm, vif, &vif->bss_conf);
76 ret = iwl_mvm_link_changed(mvm, vif, &vif->bss_conf,
77 LINK_CONTEXT_MODIFY_ACTIVE |
78 LINK_CONTEXT_MODIFY_RATES_INFO,
83 ret = iwl_mvm_mld_add_bcast_sta(mvm, vif, &vif->bss_conf);
87 /* Save a pointer to p2p device vif, so it can later be used to
88 * update the p2p device MAC when a GO is started/stopped
90 mvm->p2p_device_vif = vif;
92 ret = iwl_mvm_add_link(mvm, vif, &vif->bss_conf);
97 ret = iwl_mvm_power_update_mac(mvm);
101 iwl_mvm_tcm_add_vif(mvm, vif);
102 INIT_DELAYED_WORK(&mvmvif->csa_work,
103 iwl_mvm_channel_switch_disconnect_wk);
105 if (vif->type == NL80211_IFTYPE_MONITOR) {
106 mvm->monitor_on = true;
107 ieee80211_hw_set(mvm->hw, RX_INCLUDES_FCS);
110 iwl_mvm_vif_dbgfs_register(mvm, vif);
112 if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) &&
113 vif->type == NL80211_IFTYPE_STATION && !vif->p2p &&
114 !mvm->csme_vif && mvm->mei_registered) {
115 iwl_mei_set_nic_info(vif->addr, mvm->nvm_data->hw_addr);
116 iwl_mei_set_netdev(ieee80211_vif_to_wdev(vif)->netdev);
123 iwl_mvm_disable_link(mvm, vif, &vif->bss_conf);
125 iwl_mvm_phy_ctxt_unref(mvm, mvmvif->deflink.phy_ctxt);
127 if (mvm->bf_allowed_vif == mvmvif) {
128 mvm->bf_allowed_vif = NULL;
129 vif->driver_flags &= ~(IEEE80211_VIF_BEACON_FILTER |
130 IEEE80211_VIF_SUPPORTS_CQM_RSSI);
133 mvmvif->deflink.phy_ctxt = NULL;
134 mvmvif->link[0] = NULL;
135 iwl_mvm_mld_mac_ctxt_remove(mvm, vif);
137 mutex_unlock(&mvm->mutex);
142 static void iwl_mvm_mld_mac_remove_interface(struct ieee80211_hw *hw,
143 struct ieee80211_vif *vif)
145 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
146 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
147 struct iwl_probe_resp_data *probe_data;
149 iwl_mvm_prepare_mac_removal(mvm, vif);
151 if (!(vif->type == NL80211_IFTYPE_AP ||
152 vif->type == NL80211_IFTYPE_ADHOC))
153 iwl_mvm_tcm_rm_vif(mvm, vif);
155 mutex_lock(&mvm->mutex);
157 if (vif == mvm->csme_vif) {
158 iwl_mei_set_netdev(NULL);
159 mvm->csme_vif = NULL;
162 if (mvm->bf_allowed_vif == mvmvif) {
163 mvm->bf_allowed_vif = NULL;
164 vif->driver_flags &= ~(IEEE80211_VIF_BEACON_FILTER |
165 IEEE80211_VIF_SUPPORTS_CQM_RSSI);
168 if (vif->bss_conf.ftm_responder)
169 memset(&mvm->ftm_resp_stats, 0, sizeof(mvm->ftm_resp_stats));
171 iwl_mvm_vif_dbgfs_clean(mvm, vif);
173 /* For AP/GO interface, the tear down of the resources allocated to the
174 * interface is be handled as part of the stop_ap flow.
176 if (vif->type == NL80211_IFTYPE_AP ||
177 vif->type == NL80211_IFTYPE_ADHOC) {
178 #ifdef CONFIG_NL80211_TESTMODE
179 if (vif == mvm->noa_vif) {
181 mvm->noa_duration = 0;
186 iwl_mvm_power_update_mac(mvm);
188 if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
189 mvm->p2p_device_vif = NULL;
191 /* P2P device uses only one link */
192 iwl_mvm_mld_rm_bcast_sta(mvm, vif, &vif->bss_conf);
193 iwl_mvm_disable_link(mvm, vif, &vif->bss_conf);
194 iwl_mvm_phy_ctxt_unref(mvm, mvmvif->deflink.phy_ctxt);
195 mvmvif->deflink.phy_ctxt = NULL;
197 iwl_mvm_disable_link(mvm, vif, &vif->bss_conf);
200 iwl_mvm_mld_mac_ctxt_remove(mvm, vif);
202 RCU_INIT_POINTER(mvm->vif_id_to_mac[mvmvif->id], NULL);
204 probe_data = rcu_dereference_protected(mvmvif->deflink.probe_resp_data,
205 lockdep_is_held(&mvm->mutex));
206 RCU_INIT_POINTER(mvmvif->deflink.probe_resp_data, NULL);
208 kfree_rcu(probe_data, rcu_head);
210 if (vif->type == NL80211_IFTYPE_MONITOR) {
211 mvm->monitor_on = false;
212 __clear_bit(IEEE80211_HW_RX_INCLUDES_FCS, mvm->hw->flags);
215 mutex_unlock(&mvm->mutex);
219 __iwl_mvm_mld_assign_vif_chanctx(struct iwl_mvm *mvm,
220 struct ieee80211_vif *vif,
221 struct ieee80211_bss_conf *link_conf,
222 struct ieee80211_chanctx_conf *ctx,
223 bool switching_chanctx)
225 u16 *phy_ctxt_id = (u16 *)ctx->drv_priv;
226 struct iwl_mvm_phy_ctxt *phy_ctxt = &mvm->phy_ctxts[*phy_ctxt_id];
227 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
228 unsigned int link_id = link_conf->link_id;
231 if (WARN_ON_ONCE(!mvmvif->link[link_id]))
234 /* mac parameters such as HE support can change at this stage
235 * For sta, need first to configure correct state from drv_sta_state
236 * and only after that update mac config.
238 if (vif->type == NL80211_IFTYPE_AP) {
239 ret = iwl_mvm_mld_mac_ctxt_changed(mvm, vif, false);
241 IWL_ERR(mvm, "failed to update MAC %pM\n", vif->addr);
246 mvmvif->link[link_id]->phy_ctxt = phy_ctxt;
248 if (switching_chanctx) {
249 /* reactivate if we turned this off during channel switch */
250 if (vif->type == NL80211_IFTYPE_AP)
251 mvmvif->ap_ibss_active = true;
254 /* send it first with phy context ID */
255 ret = iwl_mvm_link_changed(mvm, vif, link_conf, 0, false);
259 /* Initialize rate control for the AP station, since we might be
260 * doing a link switch here - we cannot initialize it before since
261 * this needs the phy context assigned (and in FW?), and we cannot
262 * do it later because it needs to be initialized as soon as we're
263 * able to TX on the link, i.e. when active.
265 * Firmware restart isn't quite correct yet for MLO, but we don't
266 * need to do it in that case anyway since it will happen from the
267 * normal station state callback.
269 if (mvmvif->ap_sta &&
270 !test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
271 struct ieee80211_link_sta *link_sta;
274 link_sta = rcu_dereference(mvmvif->ap_sta->link[link_id]);
276 if (!WARN_ON_ONCE(!link_sta))
277 iwl_mvm_rs_rate_init(mvm, vif, mvmvif->ap_sta,
279 phy_ctxt->channel->band);
284 ret = iwl_mvm_link_changed(mvm, vif, link_conf,
285 LINK_CONTEXT_MODIFY_ACTIVE |
286 LINK_CONTEXT_MODIFY_RATES_INFO,
292 * Power state must be updated before quotas,
293 * otherwise fw will complain.
295 iwl_mvm_power_update_mac(mvm);
297 if (vif->type == NL80211_IFTYPE_MONITOR) {
298 ret = iwl_mvm_mld_add_snif_sta(mvm, vif, link_conf);
306 iwl_mvm_link_changed(mvm, vif, link_conf, LINK_CONTEXT_MODIFY_ACTIVE,
309 mvmvif->link[link_id]->phy_ctxt = NULL;
310 iwl_mvm_power_update_mac(mvm);
314 static int iwl_mvm_mld_assign_vif_chanctx(struct ieee80211_hw *hw,
315 struct ieee80211_vif *vif,
316 struct ieee80211_bss_conf *link_conf,
317 struct ieee80211_chanctx_conf *ctx)
319 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
322 mutex_lock(&mvm->mutex);
323 ret = __iwl_mvm_mld_assign_vif_chanctx(mvm, vif, link_conf, ctx, false);
324 mutex_unlock(&mvm->mutex);
330 __iwl_mvm_mld_unassign_vif_chanctx(struct iwl_mvm *mvm,
331 struct ieee80211_vif *vif,
332 struct ieee80211_bss_conf *link_conf,
333 struct ieee80211_chanctx_conf *ctx,
334 bool switching_chanctx)
336 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
337 unsigned int link_id = link_conf->link_id;
339 /* shouldn't happen, but verify link_id is valid before accessing */
340 if (WARN_ON_ONCE(!mvmvif->link[link_id]))
343 if (vif->type == NL80211_IFTYPE_AP && switching_chanctx) {
344 mvmvif->csa_countdown = false;
346 /* Set CS bit on all the stations */
347 iwl_mvm_modify_all_sta_disable_tx(mvm, mvmvif, true);
349 /* Save blocked iface, the timeout is set on the next beacon */
350 rcu_assign_pointer(mvm->csa_tx_blocked_vif, vif);
352 mvmvif->ap_ibss_active = false;
355 if (vif->type == NL80211_IFTYPE_MONITOR)
356 iwl_mvm_mld_rm_snif_sta(mvm, vif);
358 iwl_mvm_link_changed(mvm, vif, link_conf,
359 LINK_CONTEXT_MODIFY_ACTIVE, false);
361 if (switching_chanctx)
363 mvmvif->link[link_id]->phy_ctxt = NULL;
364 iwl_mvm_power_update_mac(mvm);
367 static void iwl_mvm_mld_unassign_vif_chanctx(struct ieee80211_hw *hw,
368 struct ieee80211_vif *vif,
369 struct ieee80211_bss_conf *link_conf,
370 struct ieee80211_chanctx_conf *ctx)
372 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
374 mutex_lock(&mvm->mutex);
375 __iwl_mvm_mld_unassign_vif_chanctx(mvm, vif, link_conf, ctx, false);
376 mutex_unlock(&mvm->mutex);
379 static int iwl_mvm_mld_start_ap_ibss(struct ieee80211_hw *hw,
380 struct ieee80211_vif *vif,
381 struct ieee80211_bss_conf *link_conf)
383 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
384 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
387 mutex_lock(&mvm->mutex);
388 /* Send the beacon template */
389 ret = iwl_mvm_mac_ctxt_beacon_changed(mvm, vif, link_conf);
393 /* the link should be already activated when assigning chan context */
394 ret = iwl_mvm_link_changed(mvm, vif, link_conf,
395 LINK_CONTEXT_MODIFY_ALL &
396 ~LINK_CONTEXT_MODIFY_ACTIVE,
401 ret = iwl_mvm_mld_add_mcast_sta(mvm, vif, link_conf);
405 /* Send the bcast station. At this stage the TBTT and DTIM time
406 * events are added and applied to the scheduler
408 ret = iwl_mvm_mld_add_bcast_sta(mvm, vif, link_conf);
412 if (iwl_mvm_start_ap_ibss_common(hw, vif, &ret))
415 /* Need to update the P2P Device MAC (only GO, IBSS is single vif) */
416 if (vif->p2p && mvm->p2p_device_vif)
417 iwl_mvm_mld_mac_ctxt_changed(mvm, mvm->p2p_device_vif, false);
419 iwl_mvm_bt_coex_vif_change(mvm);
421 /* we don't support TDLS during DCM */
422 if (iwl_mvm_phy_ctx_count(mvm) > 1)
423 iwl_mvm_teardown_tdls_peers(mvm);
425 iwl_mvm_ftm_restart_responder(mvm, vif, link_conf);
430 iwl_mvm_power_update_mac(mvm);
431 mvmvif->ap_ibss_active = false;
432 iwl_mvm_mld_rm_bcast_sta(mvm, vif, link_conf);
434 iwl_mvm_mld_rm_mcast_sta(mvm, vif, link_conf);
436 mutex_unlock(&mvm->mutex);
440 static int iwl_mvm_mld_start_ap(struct ieee80211_hw *hw,
441 struct ieee80211_vif *vif,
442 struct ieee80211_bss_conf *link_conf)
444 return iwl_mvm_mld_start_ap_ibss(hw, vif, link_conf);
447 static int iwl_mvm_mld_start_ibss(struct ieee80211_hw *hw,
448 struct ieee80211_vif *vif)
450 return iwl_mvm_mld_start_ap_ibss(hw, vif, &vif->bss_conf);
453 static void iwl_mvm_mld_stop_ap_ibss(struct ieee80211_hw *hw,
454 struct ieee80211_vif *vif,
455 struct ieee80211_bss_conf *link_conf)
457 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
459 mutex_lock(&mvm->mutex);
461 iwl_mvm_stop_ap_ibss_common(mvm, vif);
463 /* Need to update the P2P Device MAC (only GO, IBSS is single vif) */
464 if (vif->p2p && mvm->p2p_device_vif)
465 iwl_mvm_mld_mac_ctxt_changed(mvm, mvm->p2p_device_vif, false);
467 iwl_mvm_ftm_responder_clear(mvm, vif);
469 iwl_mvm_mld_rm_bcast_sta(mvm, vif, link_conf);
470 iwl_mvm_mld_rm_mcast_sta(mvm, vif, link_conf);
472 iwl_mvm_power_update_mac(mvm);
473 mutex_unlock(&mvm->mutex);
476 static void iwl_mvm_mld_stop_ap(struct ieee80211_hw *hw,
477 struct ieee80211_vif *vif,
478 struct ieee80211_bss_conf *link_conf)
480 iwl_mvm_mld_stop_ap_ibss(hw, vif, link_conf);
483 static void iwl_mvm_mld_stop_ibss(struct ieee80211_hw *hw,
484 struct ieee80211_vif *vif)
486 iwl_mvm_mld_stop_ap_ibss(hw, vif, &vif->bss_conf);
489 static int iwl_mvm_mld_mac_sta_state(struct ieee80211_hw *hw,
490 struct ieee80211_vif *vif,
491 struct ieee80211_sta *sta,
492 enum ieee80211_sta_state old_state,
493 enum ieee80211_sta_state new_state)
495 static const struct iwl_mvm_sta_state_ops callbacks = {
496 .add_sta = iwl_mvm_mld_add_sta,
497 .update_sta = iwl_mvm_mld_update_sta,
498 .rm_sta = iwl_mvm_mld_rm_sta,
499 .mac_ctxt_changed = iwl_mvm_mld_mac_ctxt_changed,
502 return iwl_mvm_mac_sta_state_common(hw, vif, sta, old_state, new_state,
507 iwl_mvm_mld_link_info_changed_station(struct iwl_mvm *mvm,
508 struct ieee80211_vif *vif,
509 struct ieee80211_bss_conf *link_conf,
512 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
513 bool has_he, has_eht;
514 u32 link_changes = 0;
517 if (WARN_ON_ONCE(!mvmvif->link[link_conf->link_id]))
520 has_he = link_conf->he_support && !iwlwifi_mod_params.disable_11ax;
521 has_eht = link_conf->eht_support && !iwlwifi_mod_params.disable_11be;
523 /* Update EDCA params */
524 if (changes & BSS_CHANGED_QOS && vif->cfg.assoc && link_conf->qos)
525 link_changes |= LINK_CONTEXT_MODIFY_QOS_PARAMS;
527 if (changes & BSS_CHANGED_ERP_SLOT)
528 link_changes |= LINK_CONTEXT_MODIFY_RATES_INFO;
530 if (vif->cfg.assoc && (has_he || has_eht)) {
531 IWL_DEBUG_MAC80211(mvm, "Associated in HE mode\n");
532 link_changes |= LINK_CONTEXT_MODIFY_HE_PARAMS;
535 /* Update EHT Puncturing info */
536 if (changes & BSS_CHANGED_EHT_PUNCTURING && vif->cfg.assoc && has_eht)
537 link_changes |= LINK_CONTEXT_MODIFY_EHT_PARAMS;
540 ret = iwl_mvm_link_changed(mvm, vif, link_conf, link_changes,
543 IWL_ERR(mvm, "failed to update link\n");
546 ret = iwl_mvm_mld_mac_ctxt_changed(mvm, vif, false);
548 IWL_ERR(mvm, "failed to update MAC %pM\n", vif->addr);
550 memcpy(mvmvif->link[link_conf->link_id]->bssid, link_conf->bssid,
553 iwl_mvm_bss_info_changed_station_common(mvm, vif, link_conf, changes);
556 static bool iwl_mvm_mld_vif_have_valid_ap_sta(struct iwl_mvm_vif *mvmvif)
560 for_each_mvm_vif_valid_link(mvmvif, i) {
561 if (mvmvif->link[i]->ap_sta_id != IWL_MVM_INVALID_STA)
568 static void iwl_mvm_mld_vif_delete_all_stas(struct iwl_mvm *mvm,
569 struct ieee80211_vif *vif)
571 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
574 if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
577 for_each_mvm_vif_valid_link(mvmvif, i) {
578 struct iwl_mvm_vif_link_info *link = mvmvif->link[i];
583 iwl_mvm_sec_key_remove_ap(mvm, vif, link, i);
584 ret = iwl_mvm_mld_rm_sta_id(mvm, link->ap_sta_id);
586 IWL_ERR(mvm, "failed to remove AP station\n");
588 link->ap_sta_id = IWL_MVM_INVALID_STA;
592 static void iwl_mvm_mld_vif_cfg_changed_station(struct iwl_mvm *mvm,
593 struct ieee80211_vif *vif,
596 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
597 struct ieee80211_bss_conf *link_conf;
598 bool protect = false;
602 /* This might get called without active links during the
603 * chanctx switch, but we don't care about it anyway.
605 if (changes == BSS_CHANGED_IDLE)
608 ret = iwl_mvm_mld_mac_ctxt_changed(mvm, vif, false);
610 IWL_ERR(mvm, "failed to update MAC %pM\n", vif->addr);
612 mvmvif->associated = vif->cfg.assoc;
614 if (!(changes & BSS_CHANGED_ASSOC))
617 if (vif->cfg.assoc) {
618 /* clear statistics to get clean beacon counter */
619 iwl_mvm_request_statistics(mvm, true);
620 iwl_mvm_sf_update(mvm, vif, false);
621 iwl_mvm_power_vif_assoc(mvm, vif);
623 for_each_mvm_vif_valid_link(mvmvif, i) {
624 memset(&mvmvif->link[i]->beacon_stats, 0,
625 sizeof(mvmvif->link[i]->beacon_stats));
628 iwl_mvm_update_smps(mvm, vif,
629 IWL_MVM_SMPS_REQ_PROT,
630 IEEE80211_SMPS_DYNAMIC, i);
634 link_conf = rcu_dereference(vif->link_conf[i]);
635 if (link_conf && !link_conf->dtim_period)
640 if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) &&
642 /* If we're not restarting and still haven't
643 * heard a beacon (dtim period unknown) then
644 * make sure we still have enough minimum time
645 * remaining in the time event, since the auth
646 * might actually have taken quite a while
647 * (especially for SAE) and so the remaining
648 * time could be small without us having heard
651 iwl_mvm_protect_assoc(mvm, vif, 0);
654 iwl_mvm_sf_update(mvm, vif, false);
656 /* FIXME: need to decide about misbehaving AP handling */
657 iwl_mvm_power_vif_assoc(mvm, vif);
658 } else if (iwl_mvm_mld_vif_have_valid_ap_sta(mvmvif)) {
659 iwl_mvm_mei_host_disassociated(mvm);
661 /* If update fails - SF might be running in associated
662 * mode while disassociated - which is forbidden.
664 ret = iwl_mvm_sf_update(mvm, vif, false);
666 !test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED,
668 "Failed to update SF upon disassociation\n");
670 /* If we get an assert during the connection (after the
671 * station has been added, but before the vif is set
672 * to associated), mac80211 will re-add the station and
673 * then configure the vif. Since the vif is not
674 * associated, we would remove the station here and
675 * this would fail the recovery.
677 iwl_mvm_mld_vif_delete_all_stas(mvm, vif);
680 iwl_mvm_bss_info_changed_station_assoc(mvm, vif, changes);
684 iwl_mvm_mld_link_info_changed_ap_ibss(struct iwl_mvm *mvm,
685 struct ieee80211_vif *vif,
686 struct ieee80211_bss_conf *link_conf,
689 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
690 u32 link_changes = LINK_CONTEXT_MODIFY_PROTECT_FLAGS |
691 LINK_CONTEXT_MODIFY_QOS_PARAMS;
693 /* Changes will be applied when the AP/IBSS is started */
694 if (!mvmvif->ap_ibss_active)
697 if (link_conf->he_support)
698 link_changes |= LINK_CONTEXT_MODIFY_HE_PARAMS;
700 if (changes & BSS_CHANGED_ERP_SLOT)
701 link_changes |= LINK_CONTEXT_MODIFY_RATES_INFO;
703 if (changes & (BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_ERP_SLOT |
705 BSS_CHANGED_BANDWIDTH | BSS_CHANGED_QOS |
706 BSS_CHANGED_HE_BSS_COLOR) &&
707 iwl_mvm_link_changed(mvm, vif, link_conf,
709 IWL_ERR(mvm, "failed to update MAC %pM\n", vif->addr);
711 /* Need to send a new beacon template to the FW */
712 if (changes & BSS_CHANGED_BEACON &&
713 iwl_mvm_mac_ctxt_beacon_changed(mvm, vif, link_conf))
714 IWL_WARN(mvm, "Failed updating beacon data\n");
716 /* FIXME: need to decide if we need FTM responder per link */
717 if (changes & BSS_CHANGED_FTM_RESPONDER) {
718 int ret = iwl_mvm_ftm_start_responder(mvm, vif, link_conf);
721 IWL_WARN(mvm, "Failed to enable FTM responder (%d)\n",
726 static void iwl_mvm_mld_link_info_changed(struct ieee80211_hw *hw,
727 struct ieee80211_vif *vif,
728 struct ieee80211_bss_conf *link_conf,
731 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
733 mutex_lock(&mvm->mutex);
736 case NL80211_IFTYPE_STATION:
737 iwl_mvm_mld_link_info_changed_station(mvm, vif, link_conf,
740 case NL80211_IFTYPE_AP:
741 case NL80211_IFTYPE_ADHOC:
742 iwl_mvm_mld_link_info_changed_ap_ibss(mvm, vif, link_conf,
745 case NL80211_IFTYPE_MONITOR:
746 if (changes & BSS_CHANGED_MU_GROUPS)
747 iwl_mvm_update_mu_groups(mvm, vif);
750 /* shouldn't happen */
754 if (changes & BSS_CHANGED_TXPOWER) {
755 IWL_DEBUG_CALIB(mvm, "Changing TX Power to %d dBm\n",
757 iwl_mvm_set_tx_power(mvm, vif, link_conf->txpower);
760 mutex_unlock(&mvm->mutex);
763 static void iwl_mvm_mld_vif_cfg_changed(struct ieee80211_hw *hw,
764 struct ieee80211_vif *vif,
767 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
769 mutex_lock(&mvm->mutex);
771 if (changes & BSS_CHANGED_IDLE && !vif->cfg.idle)
772 iwl_mvm_scan_stop(mvm, IWL_MVM_SCAN_SCHED, true);
774 if (vif->type == NL80211_IFTYPE_STATION)
775 iwl_mvm_mld_vif_cfg_changed_station(mvm, vif, changes);
777 mutex_unlock(&mvm->mutex);
781 iwl_mvm_mld_switch_vif_chanctx(struct ieee80211_hw *hw,
782 struct ieee80211_vif_chanctx_switch *vifs,
784 enum ieee80211_chanctx_switch_mode mode)
786 static const struct iwl_mvm_switch_vif_chanctx_ops ops = {
787 .__assign_vif_chanctx = __iwl_mvm_mld_assign_vif_chanctx,
788 .__unassign_vif_chanctx = __iwl_mvm_mld_unassign_vif_chanctx,
791 return iwl_mvm_switch_vif_chanctx_common(hw, vifs, n_vifs, mode, &ops);
794 static void iwl_mvm_mld_config_iface_filter(struct ieee80211_hw *hw,
795 struct ieee80211_vif *vif,
796 unsigned int filter_flags,
797 unsigned int changed_flags)
799 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
801 /* We support only filter for probe requests */
802 if (!(changed_flags & FIF_PROBE_REQ))
805 /* Supported only for p2p client interfaces */
806 if (vif->type != NL80211_IFTYPE_STATION || !vif->cfg.assoc ||
810 mutex_lock(&mvm->mutex);
811 iwl_mvm_mld_mac_ctxt_changed(mvm, vif, false);
812 mutex_unlock(&mvm->mutex);
816 iwl_mvm_mld_mac_conf_tx(struct ieee80211_hw *hw,
817 struct ieee80211_vif *vif,
818 unsigned int link_id, u16 ac,
819 const struct ieee80211_tx_queue_params *params)
821 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
822 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
823 struct iwl_mvm_vif_link_info *mvm_link = mvmvif->link[link_id];
828 mvm_link->queue_params[ac] = *params;
830 /* No need to update right away, we'll get BSS_CHANGED_QOS
831 * The exception is P2P_DEVICE interface which needs immediate update.
833 if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
836 mutex_lock(&mvm->mutex);
837 ret = iwl_mvm_link_changed(mvm, vif, &vif->bss_conf,
838 LINK_CONTEXT_MODIFY_QOS_PARAMS,
840 mutex_unlock(&mvm->mutex);
846 static int iwl_mvm_link_switch_phy_ctx(struct iwl_mvm *mvm,
847 struct ieee80211_vif *vif,
848 struct iwl_mvm_phy_ctxt *new_phy_ctxt)
850 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
853 lockdep_assert_held(&mvm->mutex);
855 /* Inorder to change the phy_ctx of a link, the link needs to be
856 * inactive. Therefore, first deactivate the link, then change its
857 * phy_ctx, and then activate it again.
859 ret = iwl_mvm_link_changed(mvm, vif, &vif->bss_conf,
860 LINK_CONTEXT_MODIFY_ACTIVE, false);
861 if (WARN(ret, "Failed to deactivate link\n"))
864 iwl_mvm_phy_ctxt_unref(mvm, mvmvif->deflink.phy_ctxt);
866 mvmvif->deflink.phy_ctxt = new_phy_ctxt;
868 ret = iwl_mvm_link_changed(mvm, vif, &vif->bss_conf, 0, false);
869 if (WARN(ret, "Failed to deactivate link\n"))
872 ret = iwl_mvm_link_changed(mvm, vif, &vif->bss_conf,
873 LINK_CONTEXT_MODIFY_ACTIVE, true);
874 WARN(ret, "Failed binding P2P_DEVICE\n");
878 static int iwl_mvm_mld_roc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
879 struct ieee80211_channel *channel, int duration,
880 enum ieee80211_roc_type type)
882 static const struct iwl_mvm_roc_ops ops = {
883 .add_aux_sta_for_hs20 = iwl_mvm_mld_add_aux_sta,
884 .switch_phy_ctxt = iwl_mvm_link_switch_phy_ctx,
887 return iwl_mvm_roc_common(hw, vif, channel, duration, type, &ops);
891 iwl_mvm_mld_change_vif_links(struct ieee80211_hw *hw,
892 struct ieee80211_vif *vif,
893 u16 old_links, u16 new_links,
894 struct ieee80211_bss_conf *old[IEEE80211_MLD_MAX_NUM_LINKS])
896 struct iwl_mvm_vif_link_info *new_link[IEEE80211_MLD_MAX_NUM_LINKS] = {};
897 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
898 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
899 u16 removed = old_links & ~new_links;
900 u16 added = new_links & ~old_links;
903 if (hweight16(new_links) > 2) {
905 } else if (hweight16(new_links) > 1) {
906 unsigned int n_active = 0;
908 for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
909 struct ieee80211_bss_conf *link_conf;
911 link_conf = link_conf_dereference_protected(vif, i);
913 rcu_access_pointer(link_conf->chanctx_conf))
917 if (vif->type == NL80211_IFTYPE_AP) {
918 if (n_active > mvm->fw->ucode_capa.num_beacons)
920 } else if (n_active > 1) {
925 for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
928 if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
931 if (!(added & BIT(i)))
933 new_link[i] = kzalloc(sizeof(*new_link[i]), GFP_KERNEL);
939 new_link[i]->bcast_sta.sta_id = IWL_MVM_INVALID_STA;
940 new_link[i]->mcast_sta.sta_id = IWL_MVM_INVALID_STA;
941 new_link[i]->ap_sta_id = IWL_MVM_INVALID_STA;
942 new_link[i]->fw_link_id = IWL_MVM_FW_LINK_ID_INVALID;
944 for (r = 0; r < NUM_IWL_MVM_SMPS_REQ; r++)
945 new_link[i]->smps_requests[r] =
946 IEEE80211_SMPS_AUTOMATIC;
949 mutex_lock(&mvm->mutex);
951 if (old_links == 0) {
952 err = iwl_mvm_disable_link(mvm, vif, &vif->bss_conf);
955 mvmvif->link[0] = NULL;
958 for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
959 if (removed & BIT(i)) {
960 struct ieee80211_bss_conf *link_conf = old[i];
962 err = iwl_mvm_disable_link(mvm, vif, link_conf);
965 kfree(mvmvif->link[i]);
966 mvmvif->link[i] = NULL;
969 if (added & BIT(i)) {
970 struct ieee80211_bss_conf *link_conf;
972 link_conf = link_conf_dereference_protected(vif, i);
973 if (WARN_ON(!link_conf))
976 if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART,
978 mvmvif->link[i] = new_link[i];
980 err = iwl_mvm_add_link(mvm, vif, link_conf);
987 if (new_links == 0) {
988 mvmvif->link[0] = &mvmvif->deflink;
989 err = iwl_mvm_add_link(mvm, vif, &vif->bss_conf);
993 /* we really don't have a good way to roll back here ... */
994 mutex_unlock(&mvm->mutex);
997 for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++)
1003 iwl_mvm_mld_change_sta_links(struct ieee80211_hw *hw,
1004 struct ieee80211_vif *vif,
1005 struct ieee80211_sta *sta,
1006 u16 old_links, u16 new_links)
1008 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
1011 mutex_lock(&mvm->mutex);
1012 ret = iwl_mvm_mld_update_sta_links(mvm, vif, sta, old_links, new_links);
1013 mutex_unlock(&mvm->mutex);
1018 const struct ieee80211_ops iwl_mvm_mld_hw_ops = {
1019 .tx = iwl_mvm_mac_tx,
1020 .wake_tx_queue = iwl_mvm_mac_wake_tx_queue,
1021 .ampdu_action = iwl_mvm_mac_ampdu_action,
1022 .get_antenna = iwl_mvm_op_get_antenna,
1023 .start = iwl_mvm_mac_start,
1024 .reconfig_complete = iwl_mvm_mac_reconfig_complete,
1025 .stop = iwl_mvm_mac_stop,
1026 .add_interface = iwl_mvm_mld_mac_add_interface,
1027 .remove_interface = iwl_mvm_mld_mac_remove_interface,
1028 .config = iwl_mvm_mac_config,
1029 .prepare_multicast = iwl_mvm_prepare_multicast,
1030 .configure_filter = iwl_mvm_configure_filter,
1031 .config_iface_filter = iwl_mvm_mld_config_iface_filter,
1032 .link_info_changed = iwl_mvm_mld_link_info_changed,
1033 .vif_cfg_changed = iwl_mvm_mld_vif_cfg_changed,
1034 .hw_scan = iwl_mvm_mac_hw_scan,
1035 .cancel_hw_scan = iwl_mvm_mac_cancel_hw_scan,
1036 .sta_pre_rcu_remove = iwl_mvm_sta_pre_rcu_remove,
1037 .sta_state = iwl_mvm_mld_mac_sta_state,
1038 .sta_notify = iwl_mvm_mac_sta_notify,
1039 .allow_buffered_frames = iwl_mvm_mac_allow_buffered_frames,
1040 .release_buffered_frames = iwl_mvm_mac_release_buffered_frames,
1041 .set_rts_threshold = iwl_mvm_mac_set_rts_threshold,
1042 .sta_rc_update = iwl_mvm_sta_rc_update,
1043 .conf_tx = iwl_mvm_mld_mac_conf_tx,
1044 .mgd_prepare_tx = iwl_mvm_mac_mgd_prepare_tx,
1045 .mgd_complete_tx = iwl_mvm_mac_mgd_complete_tx,
1046 .mgd_protect_tdls_discover = iwl_mvm_mac_mgd_protect_tdls_discover,
1047 .flush = iwl_mvm_mac_flush,
1048 .sched_scan_start = iwl_mvm_mac_sched_scan_start,
1049 .sched_scan_stop = iwl_mvm_mac_sched_scan_stop,
1050 .set_key = iwl_mvm_mac_set_key,
1051 .update_tkip_key = iwl_mvm_mac_update_tkip_key,
1052 .remain_on_channel = iwl_mvm_mld_roc,
1053 .cancel_remain_on_channel = iwl_mvm_cancel_roc,
1054 .add_chanctx = iwl_mvm_add_chanctx,
1055 .remove_chanctx = iwl_mvm_remove_chanctx,
1056 .change_chanctx = iwl_mvm_change_chanctx,
1057 .assign_vif_chanctx = iwl_mvm_mld_assign_vif_chanctx,
1058 .unassign_vif_chanctx = iwl_mvm_mld_unassign_vif_chanctx,
1059 .switch_vif_chanctx = iwl_mvm_mld_switch_vif_chanctx,
1061 .start_ap = iwl_mvm_mld_start_ap,
1062 .stop_ap = iwl_mvm_mld_stop_ap,
1063 .join_ibss = iwl_mvm_mld_start_ibss,
1064 .leave_ibss = iwl_mvm_mld_stop_ibss,
1066 .tx_last_beacon = iwl_mvm_tx_last_beacon,
1068 .set_tim = iwl_mvm_set_tim,
1070 .channel_switch = iwl_mvm_channel_switch,
1071 .pre_channel_switch = iwl_mvm_pre_channel_switch,
1072 .post_channel_switch = iwl_mvm_post_channel_switch,
1073 .abort_channel_switch = iwl_mvm_abort_channel_switch,
1074 .channel_switch_rx_beacon = iwl_mvm_channel_switch_rx_beacon,
1076 .tdls_channel_switch = iwl_mvm_tdls_channel_switch,
1077 .tdls_cancel_channel_switch = iwl_mvm_tdls_cancel_channel_switch,
1078 .tdls_recv_channel_switch = iwl_mvm_tdls_recv_channel_switch,
1080 .event_callback = iwl_mvm_mac_event_callback,
1082 .sync_rx_queues = iwl_mvm_sync_rx_queues,
1084 CFG80211_TESTMODE_CMD(iwl_mvm_mac_testmode_cmd)
1086 #ifdef CONFIG_PM_SLEEP
1088 .suspend = iwl_mvm_suspend,
1089 .resume = iwl_mvm_resume,
1090 .set_wakeup = iwl_mvm_set_wakeup,
1091 .set_rekey_data = iwl_mvm_set_rekey_data,
1092 #if IS_ENABLED(CONFIG_IPV6)
1093 .ipv6_addr_change = iwl_mvm_ipv6_addr_change,
1095 .set_default_unicast_key = iwl_mvm_set_default_unicast_key,
1097 .get_survey = iwl_mvm_mac_get_survey,
1098 .sta_statistics = iwl_mvm_mac_sta_statistics,
1099 .get_ftm_responder_stats = iwl_mvm_mac_get_ftm_responder_stats,
1100 .start_pmsr = iwl_mvm_start_pmsr,
1101 .abort_pmsr = iwl_mvm_abort_pmsr,
1103 #ifdef CONFIG_IWLWIFI_DEBUGFS
1104 .link_sta_add_debugfs = iwl_mvm_link_sta_add_debugfs,
1106 .set_hw_timestamp = iwl_mvm_set_hw_timestamp,
1108 .change_vif_links = iwl_mvm_mld_change_vif_links,
1109 .change_sta_links = iwl_mvm_mld_change_sta_links,