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