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