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