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 if (vif->cfg.assoc) { 736 /* clear statistics to get clean beacon counter */ 737 iwl_mvm_request_statistics(mvm, true); 738 iwl_mvm_sf_update(mvm, vif, false); 739 iwl_mvm_power_vif_assoc(mvm, vif); 740 741 for_each_mvm_vif_valid_link(mvmvif, i) { 742 memset(&mvmvif->link[i]->beacon_stats, 0, 743 sizeof(mvmvif->link[i]->beacon_stats)); 744 745 if (vif->p2p) { 746 iwl_mvm_update_smps(mvm, vif, 747 IWL_MVM_SMPS_REQ_PROT, 748 IEEE80211_SMPS_DYNAMIC, i); 749 } 750 751 rcu_read_lock(); 752 link_conf = rcu_dereference(vif->link_conf[i]); 753 if (link_conf && !link_conf->dtim_period) 754 protect = true; 755 rcu_read_unlock(); 756 } 757 758 if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) && 759 protect) { 760 /* If we're not restarting and still haven't 761 * heard a beacon (dtim period unknown) then 762 * make sure we still have enough minimum time 763 * remaining in the time event, since the auth 764 * might actually have taken quite a while 765 * (especially for SAE) and so the remaining 766 * time could be small without us having heard 767 * a beacon yet. 768 */ 769 iwl_mvm_protect_assoc(mvm, vif, 0); 770 } 771 772 iwl_mvm_sf_update(mvm, vif, false); 773 774 /* FIXME: need to decide about misbehaving AP handling */ 775 iwl_mvm_power_vif_assoc(mvm, vif); 776 } else if (iwl_mvm_mld_vif_have_valid_ap_sta(mvmvif)) { 777 iwl_mvm_mei_host_disassociated(mvm); 778 779 /* If update fails - SF might be running in associated 780 * mode while disassociated - which is forbidden. 781 */ 782 ret = iwl_mvm_sf_update(mvm, vif, false); 783 WARN_ONCE(ret && 784 !test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, 785 &mvm->status), 786 "Failed to update SF upon disassociation\n"); 787 788 /* If we get an assert during the connection (after the 789 * station has been added, but before the vif is set 790 * to associated), mac80211 will re-add the station and 791 * then configure the vif. Since the vif is not 792 * associated, we would remove the station here and 793 * this would fail the recovery. 794 */ 795 iwl_mvm_mld_vif_delete_all_stas(mvm, vif); 796 } 797 798 iwl_mvm_bss_info_changed_station_assoc(mvm, vif, changes); 799 } 800 801 if (changes & BSS_CHANGED_PS) { 802 ret = iwl_mvm_power_update_mac(mvm); 803 if (ret) 804 IWL_ERR(mvm, "failed to update power mode\n"); 805 } 806 } 807 808 static void 809 iwl_mvm_mld_link_info_changed_ap_ibss(struct iwl_mvm *mvm, 810 struct ieee80211_vif *vif, 811 struct ieee80211_bss_conf *link_conf, 812 u64 changes) 813 { 814 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 815 u32 link_changes = LINK_CONTEXT_MODIFY_PROTECT_FLAGS | 816 LINK_CONTEXT_MODIFY_QOS_PARAMS; 817 818 /* Changes will be applied when the AP/IBSS is started */ 819 if (!mvmvif->ap_ibss_active) 820 return; 821 822 if (link_conf->he_support) 823 link_changes |= LINK_CONTEXT_MODIFY_HE_PARAMS; 824 825 if (changes & BSS_CHANGED_ERP_SLOT) 826 link_changes |= LINK_CONTEXT_MODIFY_RATES_INFO; 827 828 if (changes & (BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_ERP_SLOT | 829 BSS_CHANGED_HT | 830 BSS_CHANGED_BANDWIDTH | BSS_CHANGED_QOS | 831 BSS_CHANGED_HE_BSS_COLOR) && 832 iwl_mvm_link_changed(mvm, vif, link_conf, 833 link_changes, true)) 834 IWL_ERR(mvm, "failed to update MAC %pM\n", vif->addr); 835 836 /* Need to send a new beacon template to the FW */ 837 if (changes & BSS_CHANGED_BEACON && 838 iwl_mvm_mac_ctxt_beacon_changed(mvm, vif, link_conf)) 839 IWL_WARN(mvm, "Failed updating beacon data\n"); 840 841 /* FIXME: need to decide if we need FTM responder per link */ 842 if (changes & BSS_CHANGED_FTM_RESPONDER) { 843 int ret = iwl_mvm_ftm_start_responder(mvm, vif, link_conf); 844 845 if (ret) 846 IWL_WARN(mvm, "Failed to enable FTM responder (%d)\n", 847 ret); 848 } 849 } 850 851 static void iwl_mvm_mld_link_info_changed(struct ieee80211_hw *hw, 852 struct ieee80211_vif *vif, 853 struct ieee80211_bss_conf *link_conf, 854 u64 changes) 855 { 856 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); 857 858 mutex_lock(&mvm->mutex); 859 860 switch (vif->type) { 861 case NL80211_IFTYPE_STATION: 862 iwl_mvm_mld_link_info_changed_station(mvm, vif, link_conf, 863 changes); 864 break; 865 case NL80211_IFTYPE_AP: 866 case NL80211_IFTYPE_ADHOC: 867 iwl_mvm_mld_link_info_changed_ap_ibss(mvm, vif, link_conf, 868 changes); 869 break; 870 case NL80211_IFTYPE_MONITOR: 871 if (changes & BSS_CHANGED_MU_GROUPS) 872 iwl_mvm_update_mu_groups(mvm, vif); 873 break; 874 default: 875 /* shouldn't happen */ 876 WARN_ON_ONCE(1); 877 } 878 879 if (changes & BSS_CHANGED_TXPOWER) { 880 IWL_DEBUG_CALIB(mvm, "Changing TX Power to %d dBm\n", 881 link_conf->txpower); 882 iwl_mvm_set_tx_power(mvm, vif, link_conf->txpower); 883 } 884 885 mutex_unlock(&mvm->mutex); 886 } 887 888 static void iwl_mvm_mld_vif_cfg_changed(struct ieee80211_hw *hw, 889 struct ieee80211_vif *vif, 890 u64 changes) 891 { 892 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); 893 894 mutex_lock(&mvm->mutex); 895 896 if (changes & BSS_CHANGED_IDLE && !vif->cfg.idle) 897 iwl_mvm_scan_stop(mvm, IWL_MVM_SCAN_SCHED, true); 898 899 if (vif->type == NL80211_IFTYPE_STATION) 900 iwl_mvm_mld_vif_cfg_changed_station(mvm, vif, changes); 901 902 mutex_unlock(&mvm->mutex); 903 } 904 905 static int 906 iwl_mvm_mld_switch_vif_chanctx(struct ieee80211_hw *hw, 907 struct ieee80211_vif_chanctx_switch *vifs, 908 int n_vifs, 909 enum ieee80211_chanctx_switch_mode mode) 910 { 911 static const struct iwl_mvm_switch_vif_chanctx_ops ops = { 912 .__assign_vif_chanctx = __iwl_mvm_mld_assign_vif_chanctx, 913 .__unassign_vif_chanctx = __iwl_mvm_mld_unassign_vif_chanctx, 914 }; 915 916 return iwl_mvm_switch_vif_chanctx_common(hw, vifs, n_vifs, mode, &ops); 917 } 918 919 static void iwl_mvm_mld_config_iface_filter(struct ieee80211_hw *hw, 920 struct ieee80211_vif *vif, 921 unsigned int filter_flags, 922 unsigned int changed_flags) 923 { 924 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); 925 926 /* We support only filter for probe requests */ 927 if (!(changed_flags & FIF_PROBE_REQ)) 928 return; 929 930 /* Supported only for p2p client interfaces */ 931 if (vif->type != NL80211_IFTYPE_STATION || !vif->cfg.assoc || 932 !vif->p2p) 933 return; 934 935 mutex_lock(&mvm->mutex); 936 iwl_mvm_mld_mac_ctxt_changed(mvm, vif, false); 937 mutex_unlock(&mvm->mutex); 938 } 939 940 static int 941 iwl_mvm_mld_mac_conf_tx(struct ieee80211_hw *hw, 942 struct ieee80211_vif *vif, 943 unsigned int link_id, u16 ac, 944 const struct ieee80211_tx_queue_params *params) 945 { 946 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); 947 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 948 struct iwl_mvm_vif_link_info *mvm_link = mvmvif->link[link_id]; 949 950 if (!mvm_link) 951 return -EINVAL; 952 953 mvm_link->queue_params[ac] = *params; 954 955 /* No need to update right away, we'll get BSS_CHANGED_QOS 956 * The exception is P2P_DEVICE interface which needs immediate update. 957 */ 958 if (vif->type == NL80211_IFTYPE_P2P_DEVICE) { 959 int ret; 960 961 mutex_lock(&mvm->mutex); 962 ret = iwl_mvm_link_changed(mvm, vif, &vif->bss_conf, 963 LINK_CONTEXT_MODIFY_QOS_PARAMS, 964 true); 965 mutex_unlock(&mvm->mutex); 966 return ret; 967 } 968 return 0; 969 } 970 971 static int iwl_mvm_link_switch_phy_ctx(struct iwl_mvm *mvm, 972 struct ieee80211_vif *vif, 973 struct iwl_mvm_phy_ctxt *new_phy_ctxt) 974 { 975 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 976 int ret = 0; 977 978 lockdep_assert_held(&mvm->mutex); 979 980 /* Inorder to change the phy_ctx of a link, the link needs to be 981 * inactive. Therefore, first deactivate the link, then change its 982 * phy_ctx, and then activate it again. 983 */ 984 ret = iwl_mvm_link_changed(mvm, vif, &vif->bss_conf, 985 LINK_CONTEXT_MODIFY_ACTIVE, false); 986 if (WARN(ret, "Failed to deactivate link\n")) 987 return ret; 988 989 iwl_mvm_phy_ctxt_unref(mvm, mvmvif->deflink.phy_ctxt); 990 991 mvmvif->deflink.phy_ctxt = new_phy_ctxt; 992 993 ret = iwl_mvm_link_changed(mvm, vif, &vif->bss_conf, 0, false); 994 if (WARN(ret, "Failed to deactivate link\n")) 995 return ret; 996 997 ret = iwl_mvm_link_changed(mvm, vif, &vif->bss_conf, 998 LINK_CONTEXT_MODIFY_ACTIVE, true); 999 WARN(ret, "Failed binding P2P_DEVICE\n"); 1000 return ret; 1001 } 1002 1003 static int iwl_mvm_mld_roc(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 1004 struct ieee80211_channel *channel, int duration, 1005 enum ieee80211_roc_type type) 1006 { 1007 static const struct iwl_mvm_roc_ops ops = { 1008 .add_aux_sta_for_hs20 = iwl_mvm_mld_add_aux_sta, 1009 .switch_phy_ctxt = iwl_mvm_link_switch_phy_ctx, 1010 }; 1011 1012 return iwl_mvm_roc_common(hw, vif, channel, duration, type, &ops); 1013 } 1014 1015 static int 1016 iwl_mvm_mld_change_vif_links(struct ieee80211_hw *hw, 1017 struct ieee80211_vif *vif, 1018 u16 old_links, u16 new_links, 1019 struct ieee80211_bss_conf *old[IEEE80211_MLD_MAX_NUM_LINKS]) 1020 { 1021 struct iwl_mvm_vif_link_info *new_link[IEEE80211_MLD_MAX_NUM_LINKS] = {}; 1022 unsigned int n_active = iwl_mvm_mld_count_active_links(vif); 1023 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 1024 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); 1025 u16 removed = old_links & ~new_links; 1026 u16 added = new_links & ~old_links; 1027 int err, i; 1028 1029 if (hweight16(new_links) > 1 && 1030 n_active > iwl_mvm_max_active_links(mvm, vif)) 1031 return -EOPNOTSUPP; 1032 1033 for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) { 1034 int r; 1035 1036 if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) 1037 break; 1038 1039 if (!(added & BIT(i))) 1040 continue; 1041 new_link[i] = kzalloc(sizeof(*new_link[i]), GFP_KERNEL); 1042 if (!new_link[i]) { 1043 err = -ENOMEM; 1044 goto free; 1045 } 1046 1047 new_link[i]->bcast_sta.sta_id = IWL_MVM_INVALID_STA; 1048 new_link[i]->mcast_sta.sta_id = IWL_MVM_INVALID_STA; 1049 new_link[i]->ap_sta_id = IWL_MVM_INVALID_STA; 1050 new_link[i]->fw_link_id = IWL_MVM_FW_LINK_ID_INVALID; 1051 1052 for (r = 0; r < NUM_IWL_MVM_SMPS_REQ; r++) 1053 new_link[i]->smps_requests[r] = 1054 IEEE80211_SMPS_AUTOMATIC; 1055 } 1056 1057 mutex_lock(&mvm->mutex); 1058 1059 if (old_links == 0) { 1060 err = iwl_mvm_disable_link(mvm, vif, &vif->bss_conf); 1061 if (err) 1062 goto out_err; 1063 mvmvif->link[0] = NULL; 1064 } 1065 1066 for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) { 1067 if (removed & BIT(i)) { 1068 struct ieee80211_bss_conf *link_conf = old[i]; 1069 1070 err = iwl_mvm_disable_link(mvm, vif, link_conf); 1071 if (err) 1072 goto out_err; 1073 kfree(mvmvif->link[i]); 1074 mvmvif->link[i] = NULL; 1075 } else if (added & BIT(i)) { 1076 struct ieee80211_bss_conf *link_conf; 1077 1078 link_conf = link_conf_dereference_protected(vif, i); 1079 if (WARN_ON(!link_conf)) 1080 continue; 1081 1082 if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, 1083 &mvm->status)) 1084 mvmvif->link[i] = new_link[i]; 1085 new_link[i] = NULL; 1086 err = iwl_mvm_add_link(mvm, vif, link_conf); 1087 if (err) 1088 goto out_err; 1089 } 1090 } 1091 1092 if (err) 1093 goto out_err; 1094 1095 err = 0; 1096 if (new_links == 0) { 1097 mvmvif->link[0] = &mvmvif->deflink; 1098 err = iwl_mvm_add_link(mvm, vif, &vif->bss_conf); 1099 } 1100 1101 out_err: 1102 /* we really don't have a good way to roll back here ... */ 1103 mutex_unlock(&mvm->mutex); 1104 1105 free: 1106 for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) 1107 kfree(new_link[i]); 1108 return err; 1109 } 1110 1111 static int 1112 iwl_mvm_mld_change_sta_links(struct ieee80211_hw *hw, 1113 struct ieee80211_vif *vif, 1114 struct ieee80211_sta *sta, 1115 u16 old_links, u16 new_links) 1116 { 1117 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); 1118 int ret; 1119 1120 mutex_lock(&mvm->mutex); 1121 ret = iwl_mvm_mld_update_sta_links(mvm, vif, sta, old_links, new_links); 1122 mutex_unlock(&mvm->mutex); 1123 1124 return ret; 1125 } 1126 1127 const struct ieee80211_ops iwl_mvm_mld_hw_ops = { 1128 .tx = iwl_mvm_mac_tx, 1129 .wake_tx_queue = iwl_mvm_mac_wake_tx_queue, 1130 .ampdu_action = iwl_mvm_mac_ampdu_action, 1131 .get_antenna = iwl_mvm_op_get_antenna, 1132 .start = iwl_mvm_mac_start, 1133 .reconfig_complete = iwl_mvm_mac_reconfig_complete, 1134 .stop = iwl_mvm_mac_stop, 1135 .add_interface = iwl_mvm_mld_mac_add_interface, 1136 .remove_interface = iwl_mvm_mld_mac_remove_interface, 1137 .config = iwl_mvm_mac_config, 1138 .prepare_multicast = iwl_mvm_prepare_multicast, 1139 .configure_filter = iwl_mvm_configure_filter, 1140 .config_iface_filter = iwl_mvm_mld_config_iface_filter, 1141 .link_info_changed = iwl_mvm_mld_link_info_changed, 1142 .vif_cfg_changed = iwl_mvm_mld_vif_cfg_changed, 1143 .hw_scan = iwl_mvm_mac_hw_scan, 1144 .cancel_hw_scan = iwl_mvm_mac_cancel_hw_scan, 1145 .sta_pre_rcu_remove = iwl_mvm_sta_pre_rcu_remove, 1146 .sta_state = iwl_mvm_mld_mac_sta_state, 1147 .sta_notify = iwl_mvm_mac_sta_notify, 1148 .allow_buffered_frames = iwl_mvm_mac_allow_buffered_frames, 1149 .release_buffered_frames = iwl_mvm_mac_release_buffered_frames, 1150 .set_rts_threshold = iwl_mvm_mac_set_rts_threshold, 1151 .sta_rc_update = iwl_mvm_sta_rc_update, 1152 .conf_tx = iwl_mvm_mld_mac_conf_tx, 1153 .mgd_prepare_tx = iwl_mvm_mac_mgd_prepare_tx, 1154 .mgd_complete_tx = iwl_mvm_mac_mgd_complete_tx, 1155 .mgd_protect_tdls_discover = iwl_mvm_mac_mgd_protect_tdls_discover, 1156 .flush = iwl_mvm_mac_flush, 1157 .flush_sta = iwl_mvm_mac_flush_sta, 1158 .sched_scan_start = iwl_mvm_mac_sched_scan_start, 1159 .sched_scan_stop = iwl_mvm_mac_sched_scan_stop, 1160 .set_key = iwl_mvm_mac_set_key, 1161 .update_tkip_key = iwl_mvm_mac_update_tkip_key, 1162 .remain_on_channel = iwl_mvm_mld_roc, 1163 .cancel_remain_on_channel = iwl_mvm_cancel_roc, 1164 .add_chanctx = iwl_mvm_add_chanctx, 1165 .remove_chanctx = iwl_mvm_remove_chanctx, 1166 .change_chanctx = iwl_mvm_change_chanctx, 1167 .assign_vif_chanctx = iwl_mvm_mld_assign_vif_chanctx, 1168 .unassign_vif_chanctx = iwl_mvm_mld_unassign_vif_chanctx, 1169 .switch_vif_chanctx = iwl_mvm_mld_switch_vif_chanctx, 1170 1171 .start_ap = iwl_mvm_mld_start_ap, 1172 .stop_ap = iwl_mvm_mld_stop_ap, 1173 .join_ibss = iwl_mvm_mld_start_ibss, 1174 .leave_ibss = iwl_mvm_mld_stop_ibss, 1175 1176 .tx_last_beacon = iwl_mvm_tx_last_beacon, 1177 1178 .set_tim = iwl_mvm_set_tim, 1179 1180 .channel_switch = iwl_mvm_channel_switch, 1181 .pre_channel_switch = iwl_mvm_pre_channel_switch, 1182 .post_channel_switch = iwl_mvm_post_channel_switch, 1183 .abort_channel_switch = iwl_mvm_abort_channel_switch, 1184 .channel_switch_rx_beacon = iwl_mvm_channel_switch_rx_beacon, 1185 1186 .tdls_channel_switch = iwl_mvm_tdls_channel_switch, 1187 .tdls_cancel_channel_switch = iwl_mvm_tdls_cancel_channel_switch, 1188 .tdls_recv_channel_switch = iwl_mvm_tdls_recv_channel_switch, 1189 1190 .event_callback = iwl_mvm_mac_event_callback, 1191 1192 .sync_rx_queues = iwl_mvm_sync_rx_queues, 1193 1194 CFG80211_TESTMODE_CMD(iwl_mvm_mac_testmode_cmd) 1195 1196 #ifdef CONFIG_PM_SLEEP 1197 /* look at d3.c */ 1198 .suspend = iwl_mvm_suspend, 1199 .resume = iwl_mvm_resume, 1200 .set_wakeup = iwl_mvm_set_wakeup, 1201 .set_rekey_data = iwl_mvm_set_rekey_data, 1202 #if IS_ENABLED(CONFIG_IPV6) 1203 .ipv6_addr_change = iwl_mvm_ipv6_addr_change, 1204 #endif 1205 .set_default_unicast_key = iwl_mvm_set_default_unicast_key, 1206 #endif 1207 .get_survey = iwl_mvm_mac_get_survey, 1208 .sta_statistics = iwl_mvm_mac_sta_statistics, 1209 .get_ftm_responder_stats = iwl_mvm_mac_get_ftm_responder_stats, 1210 .start_pmsr = iwl_mvm_start_pmsr, 1211 .abort_pmsr = iwl_mvm_abort_pmsr, 1212 1213 #ifdef CONFIG_IWLWIFI_DEBUGFS 1214 .link_sta_add_debugfs = iwl_mvm_link_sta_add_debugfs, 1215 #endif 1216 .set_hw_timestamp = iwl_mvm_set_hw_timestamp, 1217 1218 .change_vif_links = iwl_mvm_mld_change_vif_links, 1219 .change_sta_links = iwl_mvm_mld_change_sta_links, 1220 }; 1221