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