1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
3 * Copyright (C) 2022-2024 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
);
17 iwl_mvm_mac_init_mvmvif(mvm
, mvmvif
);
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.
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
;
32 /* Allocate resources for the MAC context, and add it to the fw */
33 ret
= iwl_mvm_mac_ctxt_init(mvm
, vif
);
37 rcu_assign_pointer(mvm
->vif_id_to_mac
[mvmvif
->id
], vif
);
39 mvmvif
->features
|= hw
->netdev_features
;
41 /* reset deflink MLO parameters */
42 mvmvif
->deflink
.fw_link_id
= IWL_MVM_FW_LINK_ID_INVALID
;
43 mvmvif
->deflink
.active
= 0;
45 ret
= iwl_mvm_mld_mac_ctxt_add(mvm
, vif
);
49 /* beacon filtering */
50 ret
= iwl_mvm_disable_beacon_filter(mvm
, vif
);
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
;
61 /* We want link[0] to point to the default link, unless we have MLO and
62 * in this case this will be modified later by .change_vif_links()
63 * If we are in the restart flow with an MLD connection, we will wait
64 * to .change_vif_links() to setup the links.
66 if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART
, &mvm
->status
) ||
67 !ieee80211_vif_is_mld(vif
)) {
68 mvmvif
->link
[0] = &mvmvif
->deflink
;
70 ret
= iwl_mvm_add_link(mvm
, vif
, &vif
->bss_conf
);
75 /* Save a pointer to p2p device vif, so it can later be used to
76 * update the p2p device MAC when a GO is started/stopped
78 if (vif
->type
== NL80211_IFTYPE_P2P_DEVICE
)
79 mvm
->p2p_device_vif
= vif
;
81 ret
= iwl_mvm_power_update_mac(mvm
);
85 iwl_mvm_tcm_add_vif(mvm
, vif
);
87 if (vif
->type
== NL80211_IFTYPE_MONITOR
) {
88 mvm
->monitor_on
= true;
89 ieee80211_hw_set(mvm
->hw
, RX_INCLUDES_FCS
);
92 if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART
, &mvm
->status
))
93 iwl_mvm_vif_dbgfs_add_link(mvm
, vif
);
95 if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART
, &mvm
->status
) &&
96 vif
->type
== NL80211_IFTYPE_STATION
&& !vif
->p2p
&&
97 !mvm
->csme_vif
&& mvm
->mei_registered
) {
98 iwl_mei_set_nic_info(vif
->addr
, mvm
->nvm_data
->hw_addr
);
99 iwl_mei_set_netdev(ieee80211_vif_to_wdev(vif
)->netdev
);
103 if (vif
->p2p
|| iwl_fw_lookup_cmd_ver(mvm
->fw
, PHY_CONTEXT_CMD
, 1) < 5)
104 vif
->driver_flags
|= IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW
;
109 if (mvm
->bf_allowed_vif
== mvmvif
) {
110 mvm
->bf_allowed_vif
= NULL
;
111 vif
->driver_flags
&= ~(IEEE80211_VIF_BEACON_FILTER
|
112 IEEE80211_VIF_SUPPORTS_CQM_RSSI
);
115 mvmvif
->link
[0] = NULL
;
116 iwl_mvm_mld_mac_ctxt_remove(mvm
, vif
);
120 static void iwl_mvm_mld_mac_remove_interface(struct ieee80211_hw
*hw
,
121 struct ieee80211_vif
*vif
)
123 struct iwl_mvm
*mvm
= IWL_MAC80211_GET_MVM(hw
);
124 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
125 struct iwl_probe_resp_data
*probe_data
;
127 iwl_mvm_prepare_mac_removal(mvm
, vif
);
129 if (!(vif
->type
== NL80211_IFTYPE_AP
||
130 vif
->type
== NL80211_IFTYPE_ADHOC
))
131 iwl_mvm_tcm_rm_vif(mvm
, vif
);
135 if (vif
== mvm
->csme_vif
) {
136 iwl_mei_set_netdev(NULL
);
137 mvm
->csme_vif
= NULL
;
140 if (mvm
->bf_allowed_vif
== mvmvif
) {
141 mvm
->bf_allowed_vif
= NULL
;
142 vif
->driver_flags
&= ~(IEEE80211_VIF_BEACON_FILTER
|
143 IEEE80211_VIF_SUPPORTS_CQM_RSSI
);
146 if (vif
->bss_conf
.ftm_responder
)
147 memset(&mvm
->ftm_resp_stats
, 0, sizeof(mvm
->ftm_resp_stats
));
149 iwl_mvm_vif_dbgfs_rm_link(mvm
, vif
);
151 /* For AP/GO interface, the tear down of the resources allocated to the
152 * interface is be handled as part of the stop_ap flow.
154 if (vif
->type
== NL80211_IFTYPE_AP
||
155 vif
->type
== NL80211_IFTYPE_ADHOC
) {
156 #ifdef CONFIG_NL80211_TESTMODE
157 if (vif
== mvm
->noa_vif
) {
159 mvm
->noa_duration
= 0;
164 iwl_mvm_power_update_mac(mvm
);
166 /* Before the interface removal, mac80211 would cancel the ROC, and the
167 * ROC worker would be scheduled if needed. The worker would be flushed
168 * in iwl_mvm_prepare_mac_removal() and thus at this point the link is
169 * not active. So need only to remove the link.
171 if (vif
->type
== NL80211_IFTYPE_P2P_DEVICE
) {
172 if (mvmvif
->deflink
.phy_ctxt
) {
173 iwl_mvm_phy_ctxt_unref(mvm
, mvmvif
->deflink
.phy_ctxt
);
174 mvmvif
->deflink
.phy_ctxt
= NULL
;
176 mvm
->p2p_device_vif
= NULL
;
177 iwl_mvm_remove_link(mvm
, vif
, &vif
->bss_conf
);
179 iwl_mvm_disable_link(mvm
, vif
, &vif
->bss_conf
);
182 iwl_mvm_mld_mac_ctxt_remove(mvm
, vif
);
184 RCU_INIT_POINTER(mvm
->vif_id_to_mac
[mvmvif
->id
], NULL
);
186 probe_data
= rcu_dereference_protected(mvmvif
->deflink
.probe_resp_data
,
187 lockdep_is_held(&mvm
->mutex
));
188 RCU_INIT_POINTER(mvmvif
->deflink
.probe_resp_data
, NULL
);
190 kfree_rcu(probe_data
, rcu_head
);
192 if (vif
->type
== NL80211_IFTYPE_MONITOR
) {
193 mvm
->monitor_on
= false;
194 __clear_bit(IEEE80211_HW_RX_INCLUDES_FCS
, mvm
->hw
->flags
);
198 static unsigned int iwl_mvm_mld_count_active_links(struct iwl_mvm_vif
*mvmvif
)
200 unsigned int n_active
= 0;
203 for (i
= 0; i
< IEEE80211_MLD_MAX_NUM_LINKS
; i
++) {
204 if (mvmvif
->link
[i
] && mvmvif
->link
[i
]->phy_ctxt
)
211 static void iwl_mvm_restart_mpdu_count(struct iwl_mvm
*mvm
,
212 struct iwl_mvm_vif
*mvmvif
)
214 struct ieee80211_sta
*ap_sta
= mvmvif
->ap_sta
;
215 struct iwl_mvm_sta
*mvmsta
;
217 lockdep_assert_held(&mvm
->mutex
);
222 mvmsta
= iwl_mvm_sta_from_mac80211(ap_sta
);
223 if (!mvmsta
->mpdu_counters
)
226 for (int q
= 0; q
< mvm
->trans
->num_rx_queues
; q
++) {
227 spin_lock_bh(&mvmsta
->mpdu_counters
[q
].lock
);
228 memset(mvmsta
->mpdu_counters
[q
].per_link
, 0,
229 sizeof(mvmsta
->mpdu_counters
[q
].per_link
));
230 mvmsta
->mpdu_counters
[q
].window_start
= jiffies
;
231 spin_unlock_bh(&mvmsta
->mpdu_counters
[q
].lock
);
234 IWL_DEBUG_INFO(mvm
, "MPDU counters are cleared\n");
237 static int iwl_mvm_esr_mode_active(struct iwl_mvm
*mvm
,
238 struct ieee80211_vif
*vif
)
240 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
241 int link_id
, ret
= 0;
243 mvmvif
->esr_active
= true;
245 /* Indicate to mac80211 that EML is enabled */
246 vif
->driver_flags
|= IEEE80211_VIF_EML_ACTIVE
;
248 iwl_mvm_update_smps_on_active_links(mvm
, vif
, IWL_MVM_SMPS_REQ_FW
,
251 for_each_mvm_vif_valid_link(mvmvif
, link_id
) {
252 struct iwl_mvm_vif_link_info
*link
= mvmvif
->link
[link_id
];
257 ret
= iwl_mvm_phy_send_rlc(mvm
, link
->phy_ctxt
, 2, 2);
261 link
->phy_ctxt
->rlc_disabled
= true;
264 if (vif
->active_links
== mvmvif
->link_selection_res
&&
265 !WARN_ON(!(vif
->active_links
& BIT(mvmvif
->link_selection_primary
))))
266 mvmvif
->primary_link
= mvmvif
->link_selection_primary
;
268 mvmvif
->primary_link
= __ffs(vif
->active_links
);
270 /* Needed for tracking RSSI */
271 iwl_mvm_request_periodic_system_statistics(mvm
, true);
274 * Restart the MPDU counters and the counting window, so when the
275 * statistics arrive (which is where we look at the counters) we
276 * will be at the end of the window.
278 iwl_mvm_restart_mpdu_count(mvm
, mvmvif
);
280 iwl_dbg_tlv_time_point(&mvm
->fwrt
, IWL_FW_INI_TIME_ESR_LINK_UP
,
287 __iwl_mvm_mld_assign_vif_chanctx(struct iwl_mvm
*mvm
,
288 struct ieee80211_vif
*vif
,
289 struct ieee80211_bss_conf
*link_conf
,
290 struct ieee80211_chanctx_conf
*ctx
,
291 bool switching_chanctx
)
293 u16
*phy_ctxt_id
= (u16
*)ctx
->drv_priv
;
294 struct iwl_mvm_phy_ctxt
*phy_ctxt
= &mvm
->phy_ctxts
[*phy_ctxt_id
];
295 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
296 unsigned int n_active
= iwl_mvm_mld_count_active_links(mvmvif
);
297 unsigned int link_id
= link_conf
->link_id
;
300 if (WARN_ON_ONCE(!mvmvif
->link
[link_id
]))
303 /* if the assigned one was not counted yet, count it now */
304 if (!mvmvif
->link
[link_id
]->phy_ctxt
)
307 /* mac parameters such as HE support can change at this stage
308 * For sta, need first to configure correct state from drv_sta_state
309 * and only after that update mac config.
311 if (vif
->type
== NL80211_IFTYPE_AP
) {
312 ret
= iwl_mvm_mld_mac_ctxt_changed(mvm
, vif
, false);
314 IWL_ERR(mvm
, "failed to update MAC %pM\n", vif
->addr
);
319 mvmvif
->link
[link_id
]->phy_ctxt
= phy_ctxt
;
321 if (iwl_mvm_is_esr_supported(mvm
->fwrt
.trans
) && n_active
> 1) {
322 mvmvif
->link
[link_id
]->listen_lmac
= true;
323 ret
= iwl_mvm_esr_mode_active(mvm
, vif
);
325 IWL_ERR(mvm
, "failed to activate ESR mode (%d)\n", ret
);
326 iwl_mvm_request_periodic_system_statistics(mvm
, false);
331 if (switching_chanctx
) {
332 /* reactivate if we turned this off during channel switch */
333 if (vif
->type
== NL80211_IFTYPE_AP
)
334 mvmvif
->ap_ibss_active
= true;
337 /* send it first with phy context ID */
338 ret
= iwl_mvm_link_changed(mvm
, vif
, link_conf
, 0, false);
343 * if link switching (link not active yet) we'll activate it in
344 * firmware later on link-info change, which mac80211 guarantees
345 * for link switch after the stations are set up
347 if (ieee80211_vif_link_active(vif
, link_conf
->link_id
)) {
348 ret
= iwl_mvm_link_changed(mvm
, vif
, link_conf
,
349 LINK_CONTEXT_MODIFY_ACTIVE
|
350 LINK_CONTEXT_MODIFY_RATES_INFO
,
356 if (vif
->type
== NL80211_IFTYPE_STATION
)
357 iwl_mvm_send_ap_tx_power_constraint_cmd(mvm
, vif
,
362 * Power state must be updated before quotas,
363 * otherwise fw will complain.
365 iwl_mvm_power_update_mac(mvm
);
367 if (vif
->type
== NL80211_IFTYPE_MONITOR
) {
368 ret
= iwl_mvm_mld_add_snif_sta(mvm
, vif
, link_conf
);
376 iwl_mvm_link_changed(mvm
, vif
, link_conf
, LINK_CONTEXT_MODIFY_ACTIVE
,
379 mvmvif
->link
[link_id
]->phy_ctxt
= NULL
;
380 iwl_mvm_power_update_mac(mvm
);
384 static int iwl_mvm_mld_assign_vif_chanctx(struct ieee80211_hw
*hw
,
385 struct ieee80211_vif
*vif
,
386 struct ieee80211_bss_conf
*link_conf
,
387 struct ieee80211_chanctx_conf
*ctx
)
389 struct iwl_mvm
*mvm
= IWL_MAC80211_GET_MVM(hw
);
391 /* update EMLSR mode */
392 if (ieee80211_vif_type_p2p(vif
) != NL80211_IFTYPE_STATION
) {
395 ret
= iwl_mvm_esr_non_bss_link(mvm
, vif
, link_conf
->link_id
,
398 * Don't activate this link if failed to exit EMLSR in
406 return __iwl_mvm_mld_assign_vif_chanctx(mvm
, vif
, link_conf
, ctx
, false);
409 static int iwl_mvm_esr_mode_inactive(struct iwl_mvm
*mvm
,
410 struct ieee80211_vif
*vif
)
412 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
413 struct ieee80211_bss_conf
*link_conf
;
414 int link_id
, ret
= 0;
416 mvmvif
->esr_active
= false;
418 vif
->driver_flags
&= ~IEEE80211_VIF_EML_ACTIVE
;
420 iwl_mvm_update_smps_on_active_links(mvm
, vif
, IWL_MVM_SMPS_REQ_FW
,
421 IEEE80211_SMPS_AUTOMATIC
);
423 for_each_vif_active_link(vif
, link_conf
, link_id
) {
424 struct ieee80211_chanctx_conf
*chanctx_conf
;
425 struct iwl_mvm_phy_ctxt
*phy_ctxt
;
426 u8 static_chains
, dynamic_chains
;
428 mvmvif
->link
[link_id
]->listen_lmac
= false;
432 chanctx_conf
= rcu_dereference(link_conf
->chanctx_conf
);
433 phy_ctxt
= mvmvif
->link
[link_id
]->phy_ctxt
;
435 if (!chanctx_conf
|| !phy_ctxt
) {
440 phy_ctxt
->rlc_disabled
= false;
441 static_chains
= chanctx_conf
->rx_chains_static
;
442 dynamic_chains
= chanctx_conf
->rx_chains_dynamic
;
446 ret
= iwl_mvm_phy_send_rlc(mvm
, phy_ctxt
, static_chains
,
452 iwl_mvm_request_periodic_system_statistics(mvm
, false);
454 /* Start a new counting window */
455 iwl_mvm_restart_mpdu_count(mvm
, mvmvif
);
457 iwl_dbg_tlv_time_point(&mvm
->fwrt
, IWL_FW_INI_TIME_ESR_LINK_DOWN
,
464 __iwl_mvm_mld_unassign_vif_chanctx(struct iwl_mvm
*mvm
,
465 struct ieee80211_vif
*vif
,
466 struct ieee80211_bss_conf
*link_conf
,
467 struct ieee80211_chanctx_conf
*ctx
,
468 bool switching_chanctx
)
471 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
472 unsigned int n_active
= iwl_mvm_mld_count_active_links(mvmvif
);
473 unsigned int link_id
= link_conf
->link_id
;
475 /* shouldn't happen, but verify link_id is valid before accessing */
476 if (WARN_ON_ONCE(!mvmvif
->link
[link_id
]))
479 if (vif
->type
== NL80211_IFTYPE_AP
&& switching_chanctx
) {
480 mvmvif
->csa_countdown
= false;
482 /* Set CS bit on all the stations */
483 iwl_mvm_modify_all_sta_disable_tx(mvm
, mvmvif
, true);
485 /* Save blocked iface, the timeout is set on the next beacon */
486 rcu_assign_pointer(mvm
->csa_tx_blocked_vif
, vif
);
488 mvmvif
->ap_ibss_active
= false;
491 iwl_mvm_link_changed(mvm
, vif
, link_conf
,
492 LINK_CONTEXT_MODIFY_ACTIVE
, false);
494 if (iwl_mvm_is_esr_supported(mvm
->fwrt
.trans
) && n_active
> 1) {
495 int ret
= iwl_mvm_esr_mode_inactive(mvm
, vif
);
498 IWL_ERR(mvm
, "failed to deactivate ESR mode (%d)\n",
502 if (vif
->type
== NL80211_IFTYPE_MONITOR
)
503 iwl_mvm_mld_rm_snif_sta(mvm
, vif
);
505 if (switching_chanctx
)
507 mvmvif
->link
[link_id
]->phy_ctxt
= NULL
;
508 iwl_mvm_power_update_mac(mvm
);
511 static void iwl_mvm_mld_unassign_vif_chanctx(struct ieee80211_hw
*hw
,
512 struct ieee80211_vif
*vif
,
513 struct ieee80211_bss_conf
*link_conf
,
514 struct ieee80211_chanctx_conf
*ctx
)
516 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
517 struct iwl_mvm
*mvm
= IWL_MAC80211_GET_MVM(hw
);
519 mutex_lock(&mvm
->mutex
);
520 __iwl_mvm_mld_unassign_vif_chanctx(mvm
, vif
, link_conf
, ctx
, false);
521 /* in the non-MLD case, remove/re-add the link to clean up FW state */
522 if (!ieee80211_vif_is_mld(vif
) && !mvmvif
->ap_sta
&&
523 !WARN_ON_ONCE(vif
->cfg
.assoc
)) {
524 iwl_mvm_remove_link(mvm
, vif
, link_conf
);
525 iwl_mvm_add_link(mvm
, vif
, link_conf
);
527 mutex_unlock(&mvm
->mutex
);
529 /* update EMLSR mode */
530 if (ieee80211_vif_type_p2p(vif
) != NL80211_IFTYPE_STATION
)
531 iwl_mvm_esr_non_bss_link(mvm
, vif
, link_conf
->link_id
, false);
535 iwl_mvm_tpe_sta_cmd_data(struct iwl_txpower_constraints_cmd
*cmd
,
536 const struct ieee80211_bss_conf
*bss_info
)
541 * NOTE: the 0 here is IEEE80211_TPE_CAT_6GHZ_DEFAULT,
542 * we fully ignore IEEE80211_TPE_CAT_6GHZ_SUBORDINATE
545 BUILD_BUG_ON(ARRAY_SIZE(cmd
->psd_pwr
) !=
546 ARRAY_SIZE(bss_info
->tpe
.psd_local
[0].power
));
548 /* if not valid, mac80211 puts default (max value) */
549 for (i
= 0; i
< ARRAY_SIZE(cmd
->psd_pwr
); i
++)
550 cmd
->psd_pwr
[i
] = min(bss_info
->tpe
.psd_local
[0].power
[i
],
551 bss_info
->tpe
.psd_reg_client
[0].power
[i
]);
553 BUILD_BUG_ON(ARRAY_SIZE(cmd
->eirp_pwr
) !=
554 ARRAY_SIZE(bss_info
->tpe
.max_local
[0].power
));
556 for (i
= 0; i
< ARRAY_SIZE(cmd
->eirp_pwr
); i
++)
557 cmd
->eirp_pwr
[i
] = min(bss_info
->tpe
.max_local
[0].power
[i
],
558 bss_info
->tpe
.max_reg_client
[0].power
[i
]);
562 iwl_mvm_send_ap_tx_power_constraint_cmd(struct iwl_mvm
*mvm
,
563 struct ieee80211_vif
*vif
,
564 struct ieee80211_bss_conf
*bss_conf
,
567 struct iwl_txpower_constraints_cmd cmd
= {};
568 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
569 struct iwl_mvm_vif_link_info
*link_info
=
570 mvmvif
->link
[bss_conf
->link_id
];
571 u32 cmd_id
= WIDE_ID(PHY_OPS_GROUP
, AP_TX_POWER_CONSTRAINTS_CMD
);
572 u32 cmd_ver
= iwl_fw_lookup_cmd_ver(mvm
->fw
, cmd_id
,
573 IWL_FW_CMD_VER_UNKNOWN
);
576 lockdep_assert_held(&mvm
->mutex
);
578 if (cmd_ver
== IWL_FW_CMD_VER_UNKNOWN
)
581 if (!link_info
->active
||
582 link_info
->fw_link_id
== IWL_MVM_FW_LINK_ID_INVALID
)
585 if (bss_conf
->chanreq
.oper
.chan
->band
!= NL80211_BAND_6GHZ
)
588 cmd
.link_id
= cpu_to_le16(link_info
->fw_link_id
);
589 memset(cmd
.psd_pwr
, DEFAULT_TPE_TX_POWER
, sizeof(cmd
.psd_pwr
));
590 memset(cmd
.eirp_pwr
, DEFAULT_TPE_TX_POWER
, sizeof(cmd
.eirp_pwr
));
593 cmd
.ap_type
= cpu_to_le16(IWL_6GHZ_AP_TYPE_VLP
);
594 } else if (bss_conf
->power_type
== IEEE80211_REG_UNSET_AP
) {
597 cmd
.ap_type
= cpu_to_le16(bss_conf
->power_type
- 1);
598 iwl_mvm_tpe_sta_cmd_data(&cmd
, bss_conf
);
601 ret
= iwl_mvm_send_cmd_pdu(mvm
,
602 WIDE_ID(PHY_OPS_GROUP
,
603 AP_TX_POWER_CONSTRAINTS_CMD
),
604 0, sizeof(cmd
), &cmd
);
607 "failed to send AP_TX_POWER_CONSTRAINTS_CMD (%d)\n",
611 static int iwl_mvm_mld_start_ap_ibss(struct ieee80211_hw
*hw
,
612 struct ieee80211_vif
*vif
,
613 struct ieee80211_bss_conf
*link_conf
)
615 struct iwl_mvm
*mvm
= IWL_MAC80211_GET_MVM(hw
);
616 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
621 if (vif
->type
== NL80211_IFTYPE_AP
)
622 iwl_mvm_send_ap_tx_power_constraint_cmd(mvm
, vif
,
625 /* Send the beacon template */
626 ret
= iwl_mvm_mac_ctxt_beacon_changed(mvm
, vif
, link_conf
);
630 /* the link should be already activated when assigning chan context */
631 ret
= iwl_mvm_link_changed(mvm
, vif
, link_conf
,
632 LINK_CONTEXT_MODIFY_ALL
&
633 ~LINK_CONTEXT_MODIFY_ACTIVE
,
638 ret
= iwl_mvm_mld_add_mcast_sta(mvm
, vif
, link_conf
);
642 /* Send the bcast station. At this stage the TBTT and DTIM time
643 * events are added and applied to the scheduler
645 ret
= iwl_mvm_mld_add_bcast_sta(mvm
, vif
, link_conf
);
649 if (iwl_mvm_start_ap_ibss_common(hw
, vif
, &ret
))
652 /* Need to update the P2P Device MAC (only GO, IBSS is single vif) */
653 if (vif
->p2p
&& mvm
->p2p_device_vif
)
654 iwl_mvm_mld_mac_ctxt_changed(mvm
, mvm
->p2p_device_vif
, false);
656 iwl_mvm_bt_coex_vif_change(mvm
);
658 /* we don't support TDLS during DCM */
659 if (iwl_mvm_phy_ctx_count(mvm
) > 1)
660 iwl_mvm_teardown_tdls_peers(mvm
);
662 iwl_mvm_ftm_restart_responder(mvm
, vif
, link_conf
);
667 iwl_mvm_power_update_mac(mvm
);
668 mvmvif
->ap_ibss_active
= false;
669 iwl_mvm_mld_rm_bcast_sta(mvm
, vif
, link_conf
);
671 iwl_mvm_mld_rm_mcast_sta(mvm
, vif
, link_conf
);
675 static int iwl_mvm_mld_start_ap(struct ieee80211_hw
*hw
,
676 struct ieee80211_vif
*vif
,
677 struct ieee80211_bss_conf
*link_conf
)
679 return iwl_mvm_mld_start_ap_ibss(hw
, vif
, link_conf
);
682 static int iwl_mvm_mld_start_ibss(struct ieee80211_hw
*hw
,
683 struct ieee80211_vif
*vif
)
685 return iwl_mvm_mld_start_ap_ibss(hw
, vif
, &vif
->bss_conf
);
688 static void iwl_mvm_mld_stop_ap_ibss(struct ieee80211_hw
*hw
,
689 struct ieee80211_vif
*vif
,
690 struct ieee80211_bss_conf
*link_conf
)
692 struct iwl_mvm
*mvm
= IWL_MAC80211_GET_MVM(hw
);
696 iwl_mvm_stop_ap_ibss_common(mvm
, vif
);
698 /* Need to update the P2P Device MAC (only GO, IBSS is single vif) */
699 if (vif
->p2p
&& mvm
->p2p_device_vif
)
700 iwl_mvm_mld_mac_ctxt_changed(mvm
, mvm
->p2p_device_vif
, false);
702 iwl_mvm_ftm_responder_clear(mvm
, vif
);
704 iwl_mvm_mld_rm_bcast_sta(mvm
, vif
, link_conf
);
705 iwl_mvm_mld_rm_mcast_sta(mvm
, vif
, link_conf
);
707 iwl_mvm_power_update_mac(mvm
);
710 static void iwl_mvm_mld_stop_ap(struct ieee80211_hw
*hw
,
711 struct ieee80211_vif
*vif
,
712 struct ieee80211_bss_conf
*link_conf
)
714 iwl_mvm_mld_stop_ap_ibss(hw
, vif
, link_conf
);
717 static void iwl_mvm_mld_stop_ibss(struct ieee80211_hw
*hw
,
718 struct ieee80211_vif
*vif
)
720 iwl_mvm_mld_stop_ap_ibss(hw
, vif
, &vif
->bss_conf
);
723 static int iwl_mvm_mld_mac_sta_state(struct ieee80211_hw
*hw
,
724 struct ieee80211_vif
*vif
,
725 struct ieee80211_sta
*sta
,
726 enum ieee80211_sta_state old_state
,
727 enum ieee80211_sta_state new_state
)
729 static const struct iwl_mvm_sta_state_ops callbacks
= {
730 .add_sta
= iwl_mvm_mld_add_sta
,
731 .update_sta
= iwl_mvm_mld_update_sta
,
732 .rm_sta
= iwl_mvm_mld_rm_sta
,
733 .mac_ctxt_changed
= iwl_mvm_mld_mac_ctxt_changed
,
736 return iwl_mvm_mac_sta_state_common(hw
, vif
, sta
, old_state
, new_state
,
740 static bool iwl_mvm_esr_bw_criteria(struct iwl_mvm
*mvm
,
741 struct ieee80211_vif
*vif
,
742 struct ieee80211_bss_conf
*link_conf
)
744 struct ieee80211_bss_conf
*other_link
;
747 /* Exit EMLSR if links don't have equal bandwidths */
748 for_each_vif_active_link(vif
, other_link
, link_id
) {
749 if (link_id
== link_conf
->link_id
)
751 if (link_conf
->chanreq
.oper
.width
==
752 other_link
->chanreq
.oper
.width
)
760 iwl_mvm_mld_link_info_changed_station(struct iwl_mvm
*mvm
,
761 struct ieee80211_vif
*vif
,
762 struct ieee80211_bss_conf
*link_conf
,
765 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
766 bool has_he
, has_eht
;
767 u32 link_changes
= 0;
770 if (WARN_ON_ONCE(!mvmvif
->link
[link_conf
->link_id
]))
773 /* not yet marked active in vif means during link switch */
774 if (!ieee80211_vif_link_active(vif
, link_conf
->link_id
) &&
775 vif
->cfg
.assoc
&& mvmvif
->link
[link_conf
->link_id
]->phy_ctxt
)
776 link_changes
|= LINK_CONTEXT_MODIFY_ACTIVE
;
778 has_he
= link_conf
->he_support
&& !iwlwifi_mod_params
.disable_11ax
;
779 has_eht
= link_conf
->eht_support
&& !iwlwifi_mod_params
.disable_11be
;
781 /* Update EDCA params */
782 if (changes
& BSS_CHANGED_QOS
&& vif
->cfg
.assoc
&& link_conf
->qos
)
783 link_changes
|= LINK_CONTEXT_MODIFY_QOS_PARAMS
;
785 if (changes
& BSS_CHANGED_ERP_SLOT
)
786 link_changes
|= LINK_CONTEXT_MODIFY_RATES_INFO
;
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
;
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
));
801 /* if associated, maybe puncturing changed - we'll check later */
803 link_changes
|= LINK_CONTEXT_MODIFY_EHT_PARAMS
;
806 ret
= iwl_mvm_link_changed(mvm
, vif
, link_conf
, link_changes
,
809 IWL_ERR(mvm
, "failed to update link\n");
812 ret
= iwl_mvm_mld_mac_ctxt_changed(mvm
, vif
, false);
814 IWL_ERR(mvm
, "failed to update MAC %pM\n", vif
->addr
);
816 memcpy(mvmvif
->link
[link_conf
->link_id
]->bssid
, link_conf
->bssid
,
819 iwl_mvm_bss_info_changed_station_common(mvm
, vif
, link_conf
, changes
);
822 static bool iwl_mvm_mld_vif_have_valid_ap_sta(struct iwl_mvm_vif
*mvmvif
)
826 for_each_mvm_vif_valid_link(mvmvif
, i
) {
827 if (mvmvif
->link
[i
]->ap_sta_id
!= IWL_INVALID_STA
)
834 static void iwl_mvm_mld_vif_delete_all_stas(struct iwl_mvm
*mvm
,
835 struct ieee80211_vif
*vif
)
837 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
840 if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART
, &mvm
->status
))
843 for_each_mvm_vif_valid_link(mvmvif
, i
) {
844 struct iwl_mvm_vif_link_info
*link
= mvmvif
->link
[i
];
849 iwl_mvm_sec_key_remove_ap(mvm
, vif
, link
, i
);
850 ret
= iwl_mvm_mld_rm_sta_id(mvm
, link
->ap_sta_id
);
852 IWL_ERR(mvm
, "failed to remove AP station\n");
854 link
->ap_sta_id
= IWL_INVALID_STA
;
858 static void iwl_mvm_mld_vif_cfg_changed_station(struct iwl_mvm
*mvm
,
859 struct ieee80211_vif
*vif
,
862 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
863 struct ieee80211_bss_conf
*link_conf
;
864 bool protect
= false;
868 /* This might get called without active links during the
869 * chanctx switch, but we don't care about it anyway.
871 if (changes
== BSS_CHANGED_IDLE
)
874 ret
= iwl_mvm_mld_mac_ctxt_changed(mvm
, vif
, false);
876 IWL_ERR(mvm
, "failed to update MAC %pM\n", vif
->addr
);
878 mvmvif
->associated
= vif
->cfg
.assoc
;
880 if (changes
& BSS_CHANGED_ASSOC
) {
881 if (vif
->cfg
.assoc
) {
882 mvmvif
->session_prot_connection_loss
= false;
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
);
889 for_each_mvm_vif_valid_link(mvmvif
, i
) {
890 memset(&mvmvif
->link
[i
]->beacon_stats
, 0,
891 sizeof(mvmvif
->link
[i
]->beacon_stats
));
894 iwl_mvm_update_smps(mvm
, vif
,
895 IWL_MVM_SMPS_REQ_PROT
,
896 IEEE80211_SMPS_DYNAMIC
, i
);
900 link_conf
= rcu_dereference(vif
->link_conf
[i
]);
901 if (link_conf
&& !link_conf
->dtim_period
)
906 if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART
, &mvm
->status
) &&
908 /* We are in assoc so only one link is active-
909 * The association link
911 unsigned int link_id
=
912 ffs(vif
->active_links
) - 1;
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
923 iwl_mvm_protect_assoc(mvm
, vif
, 0, link_id
);
926 iwl_mvm_sf_update(mvm
, vif
, false);
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
);
933 /* If update fails - SF might be running in associated
934 * mode while disassociated - which is forbidden.
936 ret
= iwl_mvm_sf_update(mvm
, vif
, false);
938 !test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED
,
940 "Failed to update SF upon disassociation\n");
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.
949 iwl_mvm_mld_vif_delete_all_stas(mvm
, vif
);
952 iwl_mvm_bss_info_changed_station_assoc(mvm
, vif
, changes
);
955 if (changes
& BSS_CHANGED_PS
) {
956 ret
= iwl_mvm_power_update_mac(mvm
);
958 IWL_ERR(mvm
, "failed to update power mode\n");
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);
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
,
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
;
977 /* Changes will be applied when the AP/IBSS is started */
978 if (!mvmvif
->ap_ibss_active
)
981 if (link_conf
->he_support
)
982 link_changes
|= LINK_CONTEXT_MODIFY_HE_PARAMS
;
984 if (changes
& BSS_CHANGED_ERP_SLOT
)
985 link_changes
|= LINK_CONTEXT_MODIFY_RATES_INFO
;
987 if (changes
& (BSS_CHANGED_ERP_CTS_PROT
| BSS_CHANGED_ERP_SLOT
|
989 BSS_CHANGED_BANDWIDTH
| BSS_CHANGED_QOS
|
990 BSS_CHANGED_HE_BSS_COLOR
) &&
991 iwl_mvm_link_changed(mvm
, vif
, link_conf
,
993 IWL_ERR(mvm
, "failed to update MAC %pM\n", vif
->addr
);
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");
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
);
1005 IWL_WARN(mvm
, "Failed to enable FTM responder (%d)\n",
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
,
1015 struct iwl_mvm
*mvm
= IWL_MAC80211_GET_MVM(hw
);
1019 switch (vif
->type
) {
1020 case NL80211_IFTYPE_STATION
:
1021 iwl_mvm_mld_link_info_changed_station(mvm
, vif
, link_conf
,
1024 case NL80211_IFTYPE_AP
:
1025 case NL80211_IFTYPE_ADHOC
:
1026 iwl_mvm_mld_link_info_changed_ap_ibss(mvm
, vif
, link_conf
,
1029 case NL80211_IFTYPE_MONITOR
:
1030 if (changes
& BSS_CHANGED_MU_GROUPS
)
1031 iwl_mvm_update_mu_groups(mvm
, vif
);
1034 /* shouldn't happen */
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
, link_conf
, link_conf
->txpower
);
1045 static void iwl_mvm_mld_vif_cfg_changed(struct ieee80211_hw
*hw
,
1046 struct ieee80211_vif
*vif
,
1049 struct iwl_mvm
*mvm
= IWL_MAC80211_GET_MVM(hw
);
1053 if (changes
& BSS_CHANGED_IDLE
&& !vif
->cfg
.idle
)
1054 iwl_mvm_scan_stop(mvm
, IWL_MVM_SCAN_SCHED
, true);
1056 if (vif
->type
== NL80211_IFTYPE_STATION
)
1057 iwl_mvm_mld_vif_cfg_changed_station(mvm
, vif
, changes
);
1061 iwl_mvm_mld_switch_vif_chanctx(struct ieee80211_hw
*hw
,
1062 struct ieee80211_vif_chanctx_switch
*vifs
,
1064 enum ieee80211_chanctx_switch_mode mode
)
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
,
1071 return iwl_mvm_switch_vif_chanctx_common(hw
, vifs
, n_vifs
, mode
, &ops
);
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
)
1079 struct iwl_mvm
*mvm
= IWL_MAC80211_GET_MVM(hw
);
1081 /* We support only filter for probe requests */
1082 if (!(changed_flags
& FIF_PROBE_REQ
))
1085 /* Supported only for p2p client interfaces */
1086 if (vif
->type
!= NL80211_IFTYPE_STATION
|| !vif
->cfg
.assoc
||
1091 iwl_mvm_mld_mac_ctxt_changed(mvm
, vif
, false);
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
)
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
];
1107 mvm_link
->queue_params
[ac
] = *params
;
1109 /* No need to update right away, we'll get BSS_CHANGED_QOS
1110 * The exception is P2P_DEVICE interface which needs immediate update.
1112 if (vif
->type
== NL80211_IFTYPE_P2P_DEVICE
) {
1114 return iwl_mvm_link_changed(mvm
, vif
, &vif
->bss_conf
,
1115 LINK_CONTEXT_MODIFY_QOS_PARAMS
,
1121 static int iwl_mvm_mld_roc_link(struct iwl_mvm
*mvm
, struct ieee80211_vif
*vif
)
1125 lockdep_assert_held(&mvm
->mutex
);
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"))
1132 ret
= iwl_mvm_link_changed(mvm
, vif
, &vif
->bss_conf
,
1133 LINK_CONTEXT_MODIFY_ACTIVE
|
1134 LINK_CONTEXT_MODIFY_RATES_INFO
,
1137 if (WARN(ret
, "Failed linking P2P_DEVICE\n"))
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.
1143 return iwl_mvm_mld_add_bcast_sta(mvm
, vif
, &vif
->bss_conf
);
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
)
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
,
1155 return iwl_mvm_roc_common(hw
, vif
, channel
, duration
, type
, &ops
);
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
])
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
;
1171 for (i
= 0; i
< IEEE80211_MLD_MAX_NUM_LINKS
; i
++) {
1172 if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART
, &mvm
->status
))
1175 if (!(added
& BIT(i
)))
1177 new_link
[i
] = kzalloc(sizeof(*new_link
[i
]), GFP_KERNEL
);
1183 new_link
[i
]->fw_link_id
= IWL_MVM_FW_LINK_ID_INVALID
;
1184 iwl_mvm_init_link(new_link
[i
]);
1187 mutex_lock(&mvm
->mutex
);
1189 /* If we're in RESTART flow, the default link wasn't added in
1190 * drv_add_interface(), and link[0] doesn't point to it.
1192 if (old_links
== 0 && !test_bit(IWL_MVM_STATUS_IN_HW_RESTART
,
1194 err
= iwl_mvm_disable_link(mvm
, vif
, &vif
->bss_conf
);
1197 mvmvif
->link
[0] = NULL
;
1200 for (i
= 0; i
< IEEE80211_MLD_MAX_NUM_LINKS
; i
++) {
1201 if (removed
& BIT(i
)) {
1202 struct ieee80211_bss_conf
*link_conf
= old
[i
];
1204 err
= iwl_mvm_disable_link(mvm
, vif
, link_conf
);
1207 kfree(mvmvif
->link
[i
]);
1208 mvmvif
->link
[i
] = NULL
;
1209 } else if (added
& BIT(i
)) {
1210 struct ieee80211_bss_conf
*link_conf
;
1212 link_conf
= link_conf_dereference_protected(vif
, i
);
1213 if (WARN_ON(!link_conf
))
1216 if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART
,
1218 mvmvif
->link
[i
] = new_link
[i
];
1220 err
= iwl_mvm_add_link(mvm
, vif
, link_conf
);
1227 if (new_links
== 0) {
1228 mvmvif
->link
[0] = &mvmvif
->deflink
;
1229 err
= iwl_mvm_add_link(mvm
, vif
, &vif
->bss_conf
);
1231 mvmvif
->primary_link
= 0;
1232 } else if (!(new_links
& BIT(mvmvif
->primary_link
))) {
1234 * Ensure we always have a valid primary_link, the real
1235 * decision happens later when PHY is activated.
1237 mvmvif
->primary_link
= __ffs(new_links
);
1241 /* we really don't have a good way to roll back here ... */
1242 mutex_unlock(&mvm
->mutex
);
1245 for (i
= 0; i
< IEEE80211_MLD_MAX_NUM_LINKS
; i
++)
1251 iwl_mvm_mld_change_sta_links(struct ieee80211_hw
*hw
,
1252 struct ieee80211_vif
*vif
,
1253 struct ieee80211_sta
*sta
,
1254 u16 old_links
, u16 new_links
)
1256 struct iwl_mvm
*mvm
= IWL_MAC80211_GET_MVM(hw
);
1259 return iwl_mvm_mld_update_sta_links(mvm
, vif
, sta
, old_links
, new_links
);
1262 bool iwl_mvm_vif_has_esr_cap(struct iwl_mvm
*mvm
, struct ieee80211_vif
*vif
)
1264 const struct wiphy_iftype_ext_capab
*ext_capa
;
1266 lockdep_assert_held(&mvm
->mutex
);
1268 if (!ieee80211_vif_is_mld(vif
) || !vif
->cfg
.assoc
||
1269 hweight16(ieee80211_vif_usable_links(vif
)) == 1)
1272 if (!(vif
->cfg
.eml_cap
& IEEE80211_EML_CAP_EMLSR_SUPP
))
1275 ext_capa
= cfg80211_get_iftype_ext_capa(mvm
->hw
->wiphy
,
1276 ieee80211_vif_type_p2p(vif
));
1278 (ext_capa
->eml_capabilities
& IEEE80211_EML_CAP_EMLSR_SUPP
));
1281 static bool iwl_mvm_mld_can_activate_links(struct ieee80211_hw
*hw
,
1282 struct ieee80211_vif
*vif
,
1285 struct iwl_mvm
*mvm
= IWL_MAC80211_GET_MVM(hw
);
1286 int n_links
= hweight16(desired_links
);
1293 /* Check if HW supports the wanted number of links */
1294 if (n_links
> iwl_mvm_max_active_links(mvm
, vif
))
1297 /* If it is an eSR device, check that we can enter eSR */
1298 return iwl_mvm_is_esr_supported(mvm
->fwrt
.trans
) &&
1299 iwl_mvm_vif_has_esr_cap(mvm
, vif
);
1302 static enum ieee80211_neg_ttlm_res
1303 iwl_mvm_mld_can_neg_ttlm(struct ieee80211_hw
*hw
, struct ieee80211_vif
*vif
,
1304 struct ieee80211_neg_ttlm
*neg_ttlm
)
1309 /* Verify all TIDs are mapped to the same links set */
1310 map
= neg_ttlm
->downlink
[0];
1311 for (i
= 0; i
< IEEE80211_TTLM_NUM_TIDS
; i
++) {
1312 if (neg_ttlm
->downlink
[i
] != neg_ttlm
->uplink
[i
] ||
1313 neg_ttlm
->uplink
[i
] != map
)
1314 return NEG_TTLM_RES_REJECT
;
1317 return NEG_TTLM_RES_ACCEPT
;
1321 iwl_mvm_mld_mac_pre_channel_switch(struct ieee80211_hw
*hw
,
1322 struct ieee80211_vif
*vif
,
1323 struct ieee80211_channel_switch
*chsw
)
1325 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
1326 struct iwl_mvm
*mvm
= IWL_MAC80211_GET_MVM(hw
);
1329 mutex_lock(&mvm
->mutex
);
1330 if (mvmvif
->esr_active
) {
1331 u8 primary
= iwl_mvm_get_primary_link(vif
);
1334 /* prefer primary unless quiet CSA on it */
1335 if (chsw
->link_id
== primary
&& chsw
->block_tx
)
1336 selected
= iwl_mvm_get_other_link(vif
, primary
);
1341 * remembers to tell the firmware that this link can't tx
1342 * Note that this logic seems to be unrelated to esr, but it
1343 * really is needed only when esr is active. When we have a
1344 * single link, the firmware will handle all this on its own.
1345 * In multi-link scenarios, we can learn about the CSA from
1346 * another link and this logic is too complex for the firmware
1348 * Since we want to de-activate the link that got a CSA, we
1349 * need to tell the firmware not to send any frame on that link
1350 * as the firmware may not be aware that link is under a CSA
1351 * with mode=1 (no Tx allowed).
1353 if (chsw
->block_tx
&& mvmvif
->link
[chsw
->link_id
])
1354 mvmvif
->link
[chsw
->link_id
]->csa_block_tx
= true;
1356 iwl_mvm_exit_esr(mvm
, vif
, IWL_MVM_ESR_EXIT_CSA
, selected
);
1357 mutex_unlock(&mvm
->mutex
);
1360 * If we've not kept the link active that's doing the CSA
1361 * then we don't need to do anything else, just return.
1363 if (selected
!= chsw
->link_id
)
1366 mutex_lock(&mvm
->mutex
);
1369 ret
= iwl_mvm_pre_channel_switch(mvm
, vif
, chsw
);
1370 mutex_unlock(&mvm
->mutex
);
1375 #define IWL_MVM_MLD_UNBLOCK_ESR_NON_BSS_TIMEOUT (5 * HZ)
1377 static void iwl_mvm_mld_prep_add_interface(struct ieee80211_hw
*hw
,
1378 enum nl80211_iftype type
)
1380 struct iwl_mvm
*mvm
= IWL_MAC80211_GET_MVM(hw
);
1381 struct ieee80211_vif
*bss_vif
= iwl_mvm_get_bss_vif(mvm
);
1382 struct iwl_mvm_vif
*mvmvif
;
1385 IWL_DEBUG_MAC80211(mvm
, "prep_add_interface: type=%u\n",
1388 if (IS_ERR_OR_NULL(bss_vif
) ||
1389 !(type
== NL80211_IFTYPE_AP
||
1390 type
== NL80211_IFTYPE_P2P_GO
||
1391 type
== NL80211_IFTYPE_P2P_CLIENT
))
1394 mvmvif
= iwl_mvm_vif_from_mac80211(bss_vif
);
1395 ret
= iwl_mvm_block_esr_sync(mvm
, bss_vif
,
1396 IWL_MVM_ESR_BLOCKED_TMP_NON_BSS
);
1400 wiphy_delayed_work_queue(mvmvif
->mvm
->hw
->wiphy
,
1401 &mvmvif
->unblock_esr_tmp_non_bss_wk
,
1402 IWL_MVM_MLD_UNBLOCK_ESR_NON_BSS_TIMEOUT
);
1405 const struct ieee80211_ops iwl_mvm_mld_hw_ops
= {
1406 .tx
= iwl_mvm_mac_tx
,
1407 .wake_tx_queue
= iwl_mvm_mac_wake_tx_queue
,
1408 .ampdu_action
= iwl_mvm_mac_ampdu_action
,
1409 .get_antenna
= iwl_mvm_op_get_antenna
,
1410 .set_antenna
= iwl_mvm_op_set_antenna
,
1411 .start
= iwl_mvm_mac_start
,
1412 .reconfig_complete
= iwl_mvm_mac_reconfig_complete
,
1413 .stop
= iwl_mvm_mac_stop
,
1414 .add_interface
= iwl_mvm_mld_mac_add_interface
,
1415 .remove_interface
= iwl_mvm_mld_mac_remove_interface
,
1416 .config
= iwl_mvm_mac_config
,
1417 .prepare_multicast
= iwl_mvm_prepare_multicast
,
1418 .configure_filter
= iwl_mvm_configure_filter
,
1419 .config_iface_filter
= iwl_mvm_mld_config_iface_filter
,
1420 .link_info_changed
= iwl_mvm_mld_link_info_changed
,
1421 .vif_cfg_changed
= iwl_mvm_mld_vif_cfg_changed
,
1422 .hw_scan
= iwl_mvm_mac_hw_scan
,
1423 .cancel_hw_scan
= iwl_mvm_mac_cancel_hw_scan
,
1424 .sta_pre_rcu_remove
= iwl_mvm_sta_pre_rcu_remove
,
1425 .sta_state
= iwl_mvm_mld_mac_sta_state
,
1426 .sta_notify
= iwl_mvm_mac_sta_notify
,
1427 .allow_buffered_frames
= iwl_mvm_mac_allow_buffered_frames
,
1428 .release_buffered_frames
= iwl_mvm_mac_release_buffered_frames
,
1429 .set_rts_threshold
= iwl_mvm_mac_set_rts_threshold
,
1430 .link_sta_rc_update
= iwl_mvm_sta_rc_update
,
1431 .conf_tx
= iwl_mvm_mld_mac_conf_tx
,
1432 .mgd_prepare_tx
= iwl_mvm_mac_mgd_prepare_tx
,
1433 .mgd_complete_tx
= iwl_mvm_mac_mgd_complete_tx
,
1434 .mgd_protect_tdls_discover
= iwl_mvm_mac_mgd_protect_tdls_discover
,
1435 .flush
= iwl_mvm_mac_flush
,
1436 .flush_sta
= iwl_mvm_mac_flush_sta
,
1437 .sched_scan_start
= iwl_mvm_mac_sched_scan_start
,
1438 .sched_scan_stop
= iwl_mvm_mac_sched_scan_stop
,
1439 .set_key
= iwl_mvm_mac_set_key
,
1440 .update_tkip_key
= iwl_mvm_mac_update_tkip_key
,
1441 .remain_on_channel
= iwl_mvm_mld_roc
,
1442 .cancel_remain_on_channel
= iwl_mvm_cancel_roc
,
1443 .add_chanctx
= iwl_mvm_add_chanctx
,
1444 .remove_chanctx
= iwl_mvm_remove_chanctx
,
1445 .change_chanctx
= iwl_mvm_change_chanctx
,
1446 .assign_vif_chanctx
= iwl_mvm_mld_assign_vif_chanctx
,
1447 .unassign_vif_chanctx
= iwl_mvm_mld_unassign_vif_chanctx
,
1448 .switch_vif_chanctx
= iwl_mvm_mld_switch_vif_chanctx
,
1450 .start_ap
= iwl_mvm_mld_start_ap
,
1451 .stop_ap
= iwl_mvm_mld_stop_ap
,
1452 .join_ibss
= iwl_mvm_mld_start_ibss
,
1453 .leave_ibss
= iwl_mvm_mld_stop_ibss
,
1455 .tx_last_beacon
= iwl_mvm_tx_last_beacon
,
1457 .channel_switch
= iwl_mvm_channel_switch
,
1458 .pre_channel_switch
= iwl_mvm_mld_mac_pre_channel_switch
,
1459 .post_channel_switch
= iwl_mvm_post_channel_switch
,
1460 .abort_channel_switch
= iwl_mvm_abort_channel_switch
,
1461 .channel_switch_rx_beacon
= iwl_mvm_channel_switch_rx_beacon
,
1463 .tdls_channel_switch
= iwl_mvm_tdls_channel_switch
,
1464 .tdls_cancel_channel_switch
= iwl_mvm_tdls_cancel_channel_switch
,
1465 .tdls_recv_channel_switch
= iwl_mvm_tdls_recv_channel_switch
,
1467 .event_callback
= iwl_mvm_mac_event_callback
,
1469 .sync_rx_queues
= iwl_mvm_sync_rx_queues
,
1471 CFG80211_TESTMODE_CMD(iwl_mvm_mac_testmode_cmd
)
1473 #ifdef CONFIG_PM_SLEEP
1475 .suspend
= iwl_mvm_suspend
,
1476 .resume
= iwl_mvm_resume
,
1477 .set_wakeup
= iwl_mvm_set_wakeup
,
1478 .set_rekey_data
= iwl_mvm_set_rekey_data
,
1479 #if IS_ENABLED(CONFIG_IPV6)
1480 .ipv6_addr_change
= iwl_mvm_ipv6_addr_change
,
1482 .set_default_unicast_key
= iwl_mvm_set_default_unicast_key
,
1484 .get_survey
= iwl_mvm_mac_get_survey
,
1485 .sta_statistics
= iwl_mvm_mac_sta_statistics
,
1486 .get_ftm_responder_stats
= iwl_mvm_mac_get_ftm_responder_stats
,
1487 .start_pmsr
= iwl_mvm_start_pmsr
,
1488 .abort_pmsr
= iwl_mvm_abort_pmsr
,
1490 #ifdef CONFIG_IWLWIFI_DEBUGFS
1491 .vif_add_debugfs
= iwl_mvm_vif_add_debugfs
,
1492 .link_add_debugfs
= iwl_mvm_link_add_debugfs
,
1493 .link_sta_add_debugfs
= iwl_mvm_link_sta_add_debugfs
,
1495 .set_hw_timestamp
= iwl_mvm_set_hw_timestamp
,
1497 .change_vif_links
= iwl_mvm_mld_change_vif_links
,
1498 .change_sta_links
= iwl_mvm_mld_change_sta_links
,
1499 .can_activate_links
= iwl_mvm_mld_can_activate_links
,
1500 .can_neg_ttlm
= iwl_mvm_mld_can_neg_ttlm
,
1501 .prep_add_interface
= iwl_mvm_mld_prep_add_interface
,