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