FILE
mld.c
File preview with syntax highlighting.
linux-6.19.14/drivers/net/wireless/intel/iwlwifi/mld/mld.c
1// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2/* 3 * Copyright (C) 2024-2025 Intel Corporation 4 */ 5#include <linux/rtnetlink.h> 6#include <net/mac80211.h> 7 8#include "fw/api/rx.h" 9#include "fw/api/datapath.h" 10#include "fw/api/commands.h" 11#include "fw/api/offload.h" 12#include "fw/api/coex.h" 13#include "fw/dbg.h" 14#include "fw/uefi.h" 15 16#include "mld.h" 17#include "mlo.h" 18#include "mac80211.h" 19#include "led.h" 20#include "scan.h" 21#include "tx.h" 22#include "sta.h" 23#include "regulatory.h" 24#include "thermal.h" 25#include "low_latency.h" 26#include "hcmd.h" 27#include "fw/api/location.h" 28 29#include "iwl-nvm-parse.h" 30 31#define DRV_DESCRIPTION "Intel(R) MLD wireless driver for Linux" 32MODULE_DESCRIPTION(DRV_DESCRIPTION); 33MODULE_LICENSE("GPL"); 34MODULE_IMPORT_NS("IWLWIFI"); 35 36static const struct iwl_op_mode_ops iwl_mld_ops; 37 38static int __init iwl_mld_init(void) 39{ 40 int ret = iwl_opmode_register("iwlmld", &iwl_mld_ops); 41 42 if (ret) 43 pr_err("Unable to register MLD op_mode: %d\n", ret); 44 45 return ret; 46} 47module_init(iwl_mld_init); 48 49static void __exit iwl_mld_exit(void) 50{ 51 iwl_opmode_deregister("iwlmld"); 52} 53module_exit(iwl_mld_exit); 54 55static void iwl_mld_hw_set_regulatory(struct iwl_mld *mld) 56{ 57 struct wiphy *wiphy = mld->wiphy; 58 59 wiphy->regulatory_flags |= REGULATORY_WIPHY_SELF_MANAGED; 60 wiphy->regulatory_flags |= REGULATORY_ENABLE_RELAX_NO_IR; 61} 62 63VISIBLE_IF_IWLWIFI_KUNIT 64void iwl_construct_mld(struct iwl_mld *mld, struct iwl_trans *trans, 65 const struct iwl_rf_cfg *cfg, const struct iwl_fw *fw, 66 struct ieee80211_hw *hw, struct dentry *dbgfs_dir) 67{ 68 mld->dev = trans->dev; 69 mld->trans = trans; 70 mld->cfg = cfg; 71 mld->fw = fw; 72 mld->hw = hw; 73 mld->wiphy = hw->wiphy; 74 mld->debugfs_dir = dbgfs_dir; 75 76 iwl_notification_wait_init(&mld->notif_wait); 77 78 /* Setup async RX handling */ 79 spin_lock_init(&mld->async_handlers_lock); 80 INIT_LIST_HEAD(&mld->async_handlers_list); 81 wiphy_work_init(&mld->async_handlers_wk, 82 iwl_mld_async_handlers_wk); 83 84 /* Dynamic Queue Allocation */ 85 spin_lock_init(&mld->add_txqs_lock); 86 INIT_LIST_HEAD(&mld->txqs_to_add); 87 wiphy_work_init(&mld->add_txqs_wk, iwl_mld_add_txqs_wk); 88 89 /* Setup RX queues sync wait queue */ 90 init_waitqueue_head(&mld->rxq_sync.waitq); 91} 92EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_construct_mld); 93 94static void __acquires(&mld->wiphy->mtx) 95iwl_mld_fwrt_dump_start(void *ctx) 96{ 97 struct iwl_mld *mld = ctx; 98 99 wiphy_lock(mld->wiphy); 100} 101 102static void __releases(&mld->wiphy->mtx) 103iwl_mld_fwrt_dump_end(void *ctx) 104{ 105 struct iwl_mld *mld = ctx; 106 107 wiphy_unlock(mld->wiphy); 108} 109 110static bool iwl_mld_d3_debug_enable(void *ctx) 111{ 112 return IWL_MLD_D3_DEBUG; 113} 114 115static int iwl_mld_fwrt_send_hcmd(void *ctx, struct iwl_host_cmd *host_cmd) 116{ 117 struct iwl_mld *mld = (struct iwl_mld *)ctx; 118 int ret; 119 120 wiphy_lock(mld->wiphy); 121 ret = iwl_mld_send_cmd(mld, host_cmd); 122 wiphy_unlock(mld->wiphy); 123 124 return ret; 125} 126 127static const struct iwl_fw_runtime_ops iwl_mld_fwrt_ops = { 128 .dump_start = iwl_mld_fwrt_dump_start, 129 .dump_end = iwl_mld_fwrt_dump_end, 130 .send_hcmd = iwl_mld_fwrt_send_hcmd, 131 .d3_debug_enable = iwl_mld_d3_debug_enable, 132}; 133 134static void 135iwl_mld_construct_fw_runtime(struct iwl_mld *mld, struct iwl_trans *trans, 136 const struct iwl_fw *fw, 137 struct dentry *debugfs_dir) 138{ 139 iwl_fw_runtime_init(&mld->fwrt, trans, fw, &iwl_mld_fwrt_ops, mld, 140 NULL, NULL, debugfs_dir); 141 142 iwl_fw_set_current_image(&mld->fwrt, IWL_UCODE_REGULAR); 143} 144 145/* Please keep this array *SORTED* by hex value. 146 * Access is done through binary search 147 */ 148static const struct iwl_hcmd_names iwl_mld_legacy_names[] = { 149 HCMD_NAME(UCODE_ALIVE_NTFY), 150 HCMD_NAME(REPLY_ERROR), 151 HCMD_NAME(INIT_COMPLETE_NOTIF), 152 HCMD_NAME(PHY_CONTEXT_CMD), 153 HCMD_NAME(SCAN_CFG_CMD), 154 HCMD_NAME(SCAN_REQ_UMAC), 155 HCMD_NAME(SCAN_ABORT_UMAC), 156 HCMD_NAME(SCAN_COMPLETE_UMAC), 157 HCMD_NAME(TX_CMD), 158 HCMD_NAME(TXPATH_FLUSH), 159 HCMD_NAME(LEDS_CMD), 160 HCMD_NAME(WNM_80211V_TIMING_MEASUREMENT_NOTIFICATION), 161 HCMD_NAME(WNM_80211V_TIMING_MEASUREMENT_CONFIRM_NOTIFICATION), 162 HCMD_NAME(PHY_CONFIGURATION_CMD), 163 HCMD_NAME(SCAN_OFFLOAD_UPDATE_PROFILES_CMD), 164 HCMD_NAME(POWER_TABLE_CMD), 165 HCMD_NAME(PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION), 166 HCMD_NAME(BEACON_NOTIFICATION), 167 HCMD_NAME(BEACON_TEMPLATE_CMD), 168 HCMD_NAME(TX_ANT_CONFIGURATION_CMD), 169 HCMD_NAME(BT_CONFIG), 170 HCMD_NAME(REDUCE_TX_POWER_CMD), 171 HCMD_NAME(MISSED_BEACONS_NOTIFICATION), 172 HCMD_NAME(MAC_PM_POWER_TABLE), 173 HCMD_NAME(MFUART_LOAD_NOTIFICATION), 174 HCMD_NAME(SCAN_START_NOTIFICATION_UMAC), 175 HCMD_NAME(RSS_CONFIG_CMD), 176 HCMD_NAME(SCAN_ITERATION_COMPLETE_UMAC), 177 HCMD_NAME(REPLY_RX_MPDU_CMD), 178 HCMD_NAME(BA_NOTIF), 179 HCMD_NAME(MCC_UPDATE_CMD), 180 HCMD_NAME(MCC_CHUB_UPDATE_CMD), 181 HCMD_NAME(MCAST_FILTER_CMD), 182 HCMD_NAME(REPLY_BEACON_FILTERING_CMD), 183 HCMD_NAME(PROT_OFFLOAD_CONFIG_CMD), 184 HCMD_NAME(MATCH_FOUND_NOTIFICATION), 185 HCMD_NAME(WOWLAN_PATTERNS), 186 HCMD_NAME(WOWLAN_CONFIGURATION), 187 HCMD_NAME(WOWLAN_TSC_RSC_PARAM), 188 HCMD_NAME(WOWLAN_KEK_KCK_MATERIAL), 189 HCMD_NAME(DEBUG_HOST_COMMAND), 190 HCMD_NAME(LDBG_CONFIG_CMD), 191}; 192 193/* Please keep this array *SORTED* by hex value. 194 * Access is done through binary search 195 */ 196static const struct iwl_hcmd_names iwl_mld_system_names[] = { 197 HCMD_NAME(SHARED_MEM_CFG_CMD), 198 HCMD_NAME(SOC_CONFIGURATION_CMD), 199 HCMD_NAME(INIT_EXTENDED_CFG_CMD), 200 HCMD_NAME(FW_ERROR_RECOVERY_CMD), 201 HCMD_NAME(RFI_CONFIG_CMD), 202 HCMD_NAME(RFI_GET_FREQ_TABLE_CMD), 203 HCMD_NAME(SYSTEM_STATISTICS_CMD), 204 HCMD_NAME(SYSTEM_STATISTICS_END_NOTIF), 205}; 206 207/* Please keep this array *SORTED* by hex value. 208 * Access is done through binary search 209 */ 210static const struct iwl_hcmd_names iwl_mld_reg_and_nvm_names[] = { 211 HCMD_NAME(LARI_CONFIG_CHANGE), 212 HCMD_NAME(NVM_GET_INFO), 213 HCMD_NAME(TAS_CONFIG), 214 HCMD_NAME(SAR_OFFSET_MAPPING_TABLE_CMD), 215 HCMD_NAME(MCC_ALLOWED_AP_TYPE_CMD), 216}; 217 218/* Please keep this array *SORTED* by hex value. 219 * Access is done through binary search 220 */ 221static const struct iwl_hcmd_names iwl_mld_debug_names[] = { 222 HCMD_NAME(HOST_EVENT_CFG), 223 HCMD_NAME(DBGC_SUSPEND_RESUME), 224}; 225 226/* Please keep this array *SORTED* by hex value. 227 * Access is done through binary search 228 */ 229static const struct iwl_hcmd_names iwl_mld_mac_conf_names[] = { 230 HCMD_NAME(LOW_LATENCY_CMD), 231 HCMD_NAME(SESSION_PROTECTION_CMD), 232 HCMD_NAME(MAC_CONFIG_CMD), 233 HCMD_NAME(LINK_CONFIG_CMD), 234 HCMD_NAME(STA_CONFIG_CMD), 235 HCMD_NAME(AUX_STA_CMD), 236 HCMD_NAME(STA_REMOVE_CMD), 237 HCMD_NAME(ROC_CMD), 238 HCMD_NAME(MISSED_BEACONS_NOTIF), 239 HCMD_NAME(EMLSR_TRANS_FAIL_NOTIF), 240 HCMD_NAME(ROC_NOTIF), 241 HCMD_NAME(CHANNEL_SWITCH_ERROR_NOTIF), 242 HCMD_NAME(SESSION_PROTECTION_NOTIF), 243 HCMD_NAME(PROBE_RESPONSE_DATA_NOTIF), 244 HCMD_NAME(CHANNEL_SWITCH_START_NOTIF), 245}; 246 247/* Please keep this array *SORTED* by hex value. 248 * Access is done through binary search 249 */ 250static const struct iwl_hcmd_names iwl_mld_data_path_names[] = { 251 HCMD_NAME(TRIGGER_RX_QUEUES_NOTIF_CMD), 252 HCMD_NAME(WNM_PLATFORM_PTM_REQUEST_CMD), 253 HCMD_NAME(WNM_80211V_TIMING_MEASUREMENT_CONFIG_CMD), 254 HCMD_NAME(RFH_QUEUE_CONFIG_CMD), 255 HCMD_NAME(TLC_MNG_CONFIG_CMD), 256 HCMD_NAME(RX_BAID_ALLOCATION_CONFIG_CMD), 257 HCMD_NAME(SCD_QUEUE_CONFIG_CMD), 258 HCMD_NAME(SEC_KEY_CMD), 259 HCMD_NAME(ESR_MODE_NOTIF), 260 HCMD_NAME(MONITOR_NOTIF), 261 HCMD_NAME(TLC_MNG_UPDATE_NOTIF), 262 HCMD_NAME(BEACON_FILTER_IN_NOTIF), 263 HCMD_NAME(PHY_AIR_SNIFFER_NOTIF), 264 HCMD_NAME(MU_GROUP_MGMT_NOTIF), 265}; 266 267/* Please keep this array *SORTED* by hex value. 268 * Access is done through binary search 269 */ 270static const struct iwl_hcmd_names iwl_mld_scan_names[] = { 271 HCMD_NAME(CHANNEL_SURVEY_NOTIF), 272}; 273 274/* Please keep this array *SORTED* by hex value. 275 * Access is done through binary search 276 */ 277static const struct iwl_hcmd_names iwl_mld_location_names[] = { 278 HCMD_NAME(TOF_RANGE_REQ_CMD), 279 HCMD_NAME(TOF_RANGE_RESPONSE_NOTIF), 280}; 281 282/* Please keep this array *SORTED* by hex value. 283 * Access is done through binary search 284 */ 285static const struct iwl_hcmd_names iwl_mld_phy_names[] = { 286 HCMD_NAME(CMD_DTS_MEASUREMENT_TRIGGER_WIDE), 287 HCMD_NAME(CTDP_CONFIG_CMD), 288 HCMD_NAME(TEMP_REPORTING_THRESHOLDS_CMD), 289 HCMD_NAME(PER_CHAIN_LIMIT_OFFSET_CMD), 290 HCMD_NAME(CT_KILL_NOTIFICATION), 291 HCMD_NAME(DTS_MEASUREMENT_NOTIF_WIDE), 292}; 293 294/* Please keep this array *SORTED* by hex value. 295 * Access is done through binary search 296 */ 297static const struct iwl_hcmd_names iwl_mld_statistics_names[] = { 298 HCMD_NAME(STATISTICS_OPER_NOTIF), 299 HCMD_NAME(STATISTICS_OPER_PART1_NOTIF), 300}; 301 302/* Please keep this array *SORTED* by hex value. 303 * Access is done through binary search 304 */ 305static const struct iwl_hcmd_names iwl_mld_prot_offload_names[] = { 306 HCMD_NAME(WOWLAN_WAKE_PKT_NOTIFICATION), 307 HCMD_NAME(WOWLAN_INFO_NOTIFICATION), 308 HCMD_NAME(D3_END_NOTIFICATION), 309}; 310 311/* Please keep this array *SORTED* by hex value. 312 * Access is done through binary search 313 */ 314static const struct iwl_hcmd_names iwl_mld_coex_names[] = { 315 HCMD_NAME(PROFILE_NOTIF), 316}; 317 318VISIBLE_IF_IWLWIFI_KUNIT 319const struct iwl_hcmd_arr iwl_mld_groups[] = { 320 [LEGACY_GROUP] = HCMD_ARR(iwl_mld_legacy_names), 321 [LONG_GROUP] = HCMD_ARR(iwl_mld_legacy_names), 322 [SYSTEM_GROUP] = HCMD_ARR(iwl_mld_system_names), 323 [MAC_CONF_GROUP] = HCMD_ARR(iwl_mld_mac_conf_names), 324 [DATA_PATH_GROUP] = HCMD_ARR(iwl_mld_data_path_names), 325 [SCAN_GROUP] = HCMD_ARR(iwl_mld_scan_names), 326 [LOCATION_GROUP] = HCMD_ARR(iwl_mld_location_names), 327 [REGULATORY_AND_NVM_GROUP] = HCMD_ARR(iwl_mld_reg_and_nvm_names), 328 [DEBUG_GROUP] = HCMD_ARR(iwl_mld_debug_names), 329 [PHY_OPS_GROUP] = HCMD_ARR(iwl_mld_phy_names), 330 [STATISTICS_GROUP] = HCMD_ARR(iwl_mld_statistics_names), 331 [PROT_OFFLOAD_GROUP] = HCMD_ARR(iwl_mld_prot_offload_names), 332 [BT_COEX_GROUP] = HCMD_ARR(iwl_mld_coex_names), 333}; 334EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_mld_groups); 335 336#if IS_ENABLED(CONFIG_IWLWIFI_KUNIT_TESTS) 337const unsigned int global_iwl_mld_goups_size = ARRAY_SIZE(iwl_mld_groups); 338EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(global_iwl_mld_goups_size); 339#endif 340 341static void 342iwl_mld_configure_trans(struct iwl_op_mode *op_mode) 343{ 344 struct iwl_mld *mld = IWL_OP_MODE_GET_MLD(op_mode); 345 static const u8 no_reclaim_cmds[] = {TX_CMD}; 346 struct iwl_trans *trans = mld->trans; 347 u32 eckv_value; 348 349 iwl_bios_setup_step(trans, &mld->fwrt); 350 iwl_uefi_get_step_table(trans); 351 352 if (iwl_bios_get_eckv(&mld->fwrt, &eckv_value)) 353 IWL_DEBUG_RADIO(mld, "ECKV table doesn't exist in BIOS\n"); 354 else 355 trans->conf.ext_32khz_clock_valid = !!eckv_value; 356 357 trans->conf.rx_buf_size = iwl_amsdu_size_to_rxb_size(); 358 trans->conf.command_groups = iwl_mld_groups; 359 trans->conf.command_groups_size = ARRAY_SIZE(iwl_mld_groups); 360 trans->conf.fw_reset_handshake = true; 361 trans->conf.queue_alloc_cmd_ver = 362 iwl_fw_lookup_cmd_ver(mld->fw, WIDE_ID(DATA_PATH_GROUP, 363 SCD_QUEUE_CONFIG_CMD), 364 0); 365 trans->conf.cb_data_offs = offsetof(struct ieee80211_tx_info, 366 driver_data[2]); 367 BUILD_BUG_ON(sizeof(no_reclaim_cmds) > 368 sizeof(trans->conf.no_reclaim_cmds)); 369 memcpy(trans->conf.no_reclaim_cmds, no_reclaim_cmds, 370 sizeof(no_reclaim_cmds)); 371 trans->conf.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds); 372 373 trans->conf.rx_mpdu_cmd = REPLY_RX_MPDU_CMD; 374 trans->conf.rx_mpdu_cmd_hdr_size = sizeof(struct iwl_rx_mpdu_desc); 375 trans->conf.wide_cmd_header = true; 376 377 iwl_trans_op_mode_enter(trans, op_mode); 378} 379 380/* 381 ***************************************************** 382 * op mode ops functions 383 ***************************************************** 384 */ 385 386#define NUM_FW_LOAD_RETRIES 3 387static struct iwl_op_mode * 388iwl_op_mode_mld_start(struct iwl_trans *trans, const struct iwl_rf_cfg *cfg, 389 const struct iwl_fw *fw, struct dentry *dbgfs_dir) 390{ 391 struct ieee80211_hw *hw; 392 struct iwl_op_mode *op_mode; 393 struct iwl_mld *mld; 394 int ret; 395 396 /* Allocate and initialize a new hardware device */ 397 hw = ieee80211_alloc_hw(sizeof(struct iwl_op_mode) + 398 sizeof(struct iwl_mld), 399 &iwl_mld_hw_ops); 400 if (!hw) 401 return ERR_PTR(-ENOMEM); 402 403 op_mode = hw->priv; 404 405 op_mode->ops = &iwl_mld_ops; 406 407 mld = IWL_OP_MODE_GET_MLD(op_mode); 408 409 iwl_construct_mld(mld, trans, cfg, fw, hw, dbgfs_dir); 410 411 /* we'll verify later it matches between commands */ 412 mld->fw_rates_ver_3 = iwl_fw_lookup_cmd_ver(mld->fw, TX_CMD, 0) >= 11; 413 414 iwl_mld_construct_fw_runtime(mld, trans, fw, dbgfs_dir); 415 416 iwl_mld_get_bios_tables(mld); 417 iwl_uefi_get_sgom_table(trans, &mld->fwrt); 418 mld->bios_enable_puncturing = iwl_uefi_get_puncturing(&mld->fwrt); 419 420 iwl_mld_hw_set_regulatory(mld); 421 422 /* Configure transport layer with the opmode specific params */ 423 iwl_mld_configure_trans(op_mode); 424 425 /* needed for regulatory init */ 426 rtnl_lock(); 427 /* Needed for sending commands */ 428 wiphy_lock(mld->wiphy); 429 430 for (int i = 0; i < NUM_FW_LOAD_RETRIES; i++) { 431 ret = iwl_mld_load_fw(mld); 432 if (!ret) 433 break; 434 } 435 436 if (!ret) { 437 mld->nvm_data = iwl_get_nvm(mld->trans, mld->fw, 0, 0); 438 if (IS_ERR(mld->nvm_data)) { 439 IWL_ERR(mld, "Failed to read NVM: %d\n", ret); 440 ret = PTR_ERR(mld->nvm_data); 441 } 442 } 443 444 if (ret) { 445 wiphy_unlock(mld->wiphy); 446 rtnl_unlock(); 447 goto err; 448 } 449 450 /* We are about to stop the FW. Notifications may require an 451 * operational FW, so handle them all here before we stop. 452 */ 453 wiphy_work_flush(mld->wiphy, &mld->async_handlers_wk); 454 455 iwl_mld_stop_fw(mld); 456 457 wiphy_unlock(mld->wiphy); 458 rtnl_unlock(); 459 460 ret = iwl_mld_leds_init(mld); 461 if (ret) 462 goto free_nvm; 463 464 ret = iwl_mld_alloc_scan_cmd(mld); 465 if (ret) 466 goto leds_exit; 467 468 ret = iwl_mld_low_latency_init(mld); 469 if (ret) 470 goto free_scan_cmd; 471 472 ret = iwl_mld_register_hw(mld); 473 if (ret) 474 goto low_latency_free; 475 476 iwl_mld_toggle_tx_ant(mld, &mld->mgmt_tx_ant); 477 478 iwl_mld_add_debugfs_files(mld, dbgfs_dir); 479 iwl_mld_thermal_initialize(mld); 480 481 iwl_mld_ptp_init(mld); 482 483 return op_mode; 484 485low_latency_free: 486 iwl_mld_low_latency_free(mld); 487free_scan_cmd: 488 kfree(mld->scan.cmd); 489leds_exit: 490 iwl_mld_leds_exit(mld); 491free_nvm: 492 kfree(mld->nvm_data); 493err: 494 iwl_trans_op_mode_leave(mld->trans); 495 ieee80211_free_hw(mld->hw); 496 return ERR_PTR(ret); 497} 498 499static void 500iwl_op_mode_mld_stop(struct iwl_op_mode *op_mode) 501{ 502 struct iwl_mld *mld = IWL_OP_MODE_GET_MLD(op_mode); 503 504 iwl_mld_ptp_remove(mld); 505 iwl_mld_leds_exit(mld); 506 507 iwl_mld_thermal_exit(mld); 508 509 wiphy_lock(mld->wiphy); 510 iwl_mld_low_latency_stop(mld); 511 iwl_mld_deinit_time_sync(mld); 512 wiphy_unlock(mld->wiphy); 513 514 ieee80211_unregister_hw(mld->hw); 515 516 iwl_fw_runtime_free(&mld->fwrt); 517 iwl_mld_low_latency_free(mld); 518 519 iwl_trans_op_mode_leave(mld->trans); 520 521 kfree(mld->nvm_data); 522 kfree(mld->scan.cmd); 523 kfree(mld->channel_survey); 524 kfree(mld->error_recovery_buf); 525 kfree(mld->mcast_filter_cmd); 526 527 ieee80211_free_hw(mld->hw); 528} 529 530static void iwl_mld_queue_state_change(struct iwl_op_mode *op_mode, 531 int hw_queue, bool queue_full) 532{ 533 struct iwl_mld *mld = IWL_OP_MODE_GET_MLD(op_mode); 534 struct ieee80211_txq *txq; 535 struct iwl_mld_sta *mld_sta; 536 struct iwl_mld_txq *mld_txq; 537 538 rcu_read_lock(); 539 540 txq = rcu_dereference(mld->fw_id_to_txq[hw_queue]); 541 if (!txq) { 542 rcu_read_unlock(); 543 544 if (queue_full) { 545 /* An internal queue is not expected to become full */ 546 IWL_WARN(mld, 547 "Internal hw_queue %d is full! stopping all queues\n", 548 hw_queue); 549 /* Stop all queues, as an internal queue is not 550 * mapped to a mac80211 one 551 */ 552 ieee80211_stop_queues(mld->hw); 553 } else { 554 ieee80211_wake_queues(mld->hw); 555 } 556 557 return; 558 } 559 560 mld_txq = iwl_mld_txq_from_mac80211(txq); 561 mld_sta = txq->sta ? iwl_mld_sta_from_mac80211(txq->sta) : NULL; 562 563 mld_txq->status.stop_full = queue_full; 564 565 if (!queue_full && mld_sta && 566 mld_sta->sta_state != IEEE80211_STA_NOTEXIST) { 567 local_bh_disable(); 568 iwl_mld_tx_from_txq(mld, txq); 569 local_bh_enable(); 570 } 571 572 rcu_read_unlock(); 573} 574 575static void 576iwl_mld_queue_full(struct iwl_op_mode *op_mode, int hw_queue) 577{ 578 iwl_mld_queue_state_change(op_mode, hw_queue, true); 579} 580 581static void 582iwl_mld_queue_not_full(struct iwl_op_mode *op_mode, int hw_queue) 583{ 584 iwl_mld_queue_state_change(op_mode, hw_queue, false); 585} 586 587static bool 588iwl_mld_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state) 589{ 590 struct iwl_mld *mld = IWL_OP_MODE_GET_MLD(op_mode); 591 592 iwl_mld_set_hwkill(mld, state); 593 594 return false; 595} 596 597static void 598iwl_mld_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb) 599{ 600 struct iwl_mld *mld = IWL_OP_MODE_GET_MLD(op_mode); 601 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 602 603 iwl_trans_free_tx_cmd(mld->trans, info->driver_data[1]); 604 ieee80211_free_txskb(mld->hw, skb); 605} 606 607static void iwl_mld_read_error_recovery_buffer(struct iwl_mld *mld) 608{ 609 u32 src_size = mld->fw->ucode_capa.error_log_size; 610 u32 src_addr = mld->fw->ucode_capa.error_log_addr; 611 u8 *recovery_buf; 612 int ret; 613 614 /* no recovery buffer size defined in a TLV */ 615 if (!src_size) 616 return; 617 618 recovery_buf = kzalloc(src_size, GFP_ATOMIC); 619 if (!recovery_buf) 620 return; 621 622 ret = iwl_trans_read_mem_bytes(mld->trans, src_addr, 623 recovery_buf, src_size); 624 if (ret) { 625 IWL_ERR(mld, "Failed to read error recovery buffer (%d)\n", 626 ret); 627 kfree(recovery_buf); 628 return; 629 } 630 631 mld->error_recovery_buf = recovery_buf; 632} 633 634static void iwl_mld_restart_nic(struct iwl_mld *mld) 635{ 636 iwl_mld_read_error_recovery_buffer(mld); 637 638 mld->fwrt.trans->dbg.restart_required = false; 639 640 ieee80211_restart_hw(mld->hw); 641} 642 643static void 644iwl_mld_nic_error(struct iwl_op_mode *op_mode, 645 enum iwl_fw_error_type type) 646{ 647 struct iwl_mld *mld = IWL_OP_MODE_GET_MLD(op_mode); 648 bool trans_dead = iwl_trans_is_dead(mld->trans); 649 650 if (type == IWL_ERR_TYPE_CMD_QUEUE_FULL) 651 IWL_ERR(mld, "Command queue full!\n"); 652 else if (!trans_dead && !mld->fw_status.do_not_dump_once) 653 iwl_fwrt_dump_error_logs(&mld->fwrt); 654 655 mld->fw_status.do_not_dump_once = false; 656 657 /* It is necessary to abort any os scan here because mac80211 requires 658 * having the scan cleared before restarting. 659 * We'll reset the scan_status to NONE in restart cleanup in 660 * the next drv_start() call from mac80211. If ieee80211_hw_restart 661 * isn't called scan status will stay busy. 662 */ 663 iwl_mld_report_scan_aborted(mld); 664 665 /* 666 * This should be first thing before trying to collect any 667 * data to avoid endless loops if any HW error happens while 668 * collecting debug data. 669 * It might not actually be true that we'll restart, but the 670 * setting doesn't matter if we're going to be unbound either. 671 */ 672 if (type != IWL_ERR_TYPE_RESET_HS_TIMEOUT && 673 mld->fw_status.running) 674 mld->fw_status.in_hw_restart = true; 675} 676 677static void iwl_mld_dump_error(struct iwl_op_mode *op_mode, 678 struct iwl_fw_error_dump_mode *mode) 679{ 680 struct iwl_mld *mld = IWL_OP_MODE_GET_MLD(op_mode); 681 682 /* if we come in from opmode we have the mutex held */ 683 if (mode->context == IWL_ERR_CONTEXT_FROM_OPMODE) { 684 lockdep_assert_wiphy(mld->wiphy); 685 iwl_fw_error_collect(&mld->fwrt); 686 } else { 687 wiphy_lock(mld->wiphy); 688 if (mode->context != IWL_ERR_CONTEXT_ABORT) 689 iwl_fw_error_collect(&mld->fwrt); 690 wiphy_unlock(mld->wiphy); 691 } 692} 693 694static bool iwl_mld_sw_reset(struct iwl_op_mode *op_mode, 695 enum iwl_fw_error_type type) 696{ 697 struct iwl_mld *mld = IWL_OP_MODE_GET_MLD(op_mode); 698 699 /* SW reset can happen for TOP error w/o NIC error, so 700 * also abort scan here and set in_hw_restart, when we 701 * had a NIC error both were already done. 702 */ 703 iwl_mld_report_scan_aborted(mld); 704 mld->fw_status.in_hw_restart = true; 705 706 /* Do restart only in the following conditions are met: 707 * - we consider the FW as running 708 * - The trigger that brought us here is defined as one that requires 709 * a restart (in the debug TLVs) 710 */ 711 if (!mld->fw_status.running || !mld->fwrt.trans->dbg.restart_required) 712 return false; 713 714 iwl_mld_restart_nic(mld); 715 return true; 716} 717 718static void 719iwl_mld_time_point(struct iwl_op_mode *op_mode, 720 enum iwl_fw_ini_time_point tp_id, 721 union iwl_dbg_tlv_tp_data *tp_data) 722{ 723 struct iwl_mld *mld = IWL_OP_MODE_GET_MLD(op_mode); 724 725 iwl_dbg_tlv_time_point(&mld->fwrt, tp_id, tp_data); 726} 727 728#ifdef CONFIG_PM_SLEEP 729static void iwl_mld_device_powered_off(struct iwl_op_mode *op_mode) 730{ 731 struct iwl_mld *mld = IWL_OP_MODE_GET_MLD(op_mode); 732 733 wiphy_lock(mld->wiphy); 734 iwl_mld_stop_fw(mld); 735 mld->fw_status.in_d3 = false; 736 wiphy_unlock(mld->wiphy); 737} 738#else 739static void iwl_mld_device_powered_off(struct iwl_op_mode *op_mode) 740{} 741#endif 742 743static void iwl_mld_dump(struct iwl_op_mode *op_mode) 744{ 745 struct iwl_mld *mld = IWL_OP_MODE_GET_MLD(op_mode); 746 struct iwl_fw_runtime *fwrt = &mld->fwrt; 747 748 if (!iwl_trans_fw_running(fwrt->trans)) 749 return; 750 751 iwl_dbg_tlv_time_point(fwrt, IWL_FW_INI_TIME_POINT_USER_TRIGGER, NULL); 752} 753 754static const struct iwl_op_mode_ops iwl_mld_ops = { 755 .start = iwl_op_mode_mld_start, 756 .stop = iwl_op_mode_mld_stop, 757 .rx = iwl_mld_rx, 758 .rx_rss = iwl_mld_rx_rss, 759 .queue_full = iwl_mld_queue_full, 760 .queue_not_full = iwl_mld_queue_not_full, 761 .hw_rf_kill = iwl_mld_set_hw_rfkill_state, 762 .free_skb = iwl_mld_free_skb, 763 .nic_error = iwl_mld_nic_error, 764 .dump_error = iwl_mld_dump_error, 765 .sw_reset = iwl_mld_sw_reset, 766 .time_point = iwl_mld_time_point, 767 .device_powered_off = pm_sleep_ptr(iwl_mld_device_powered_off), 768 .dump = iwl_mld_dump, 769}; 770 771struct iwl_mld_mod_params iwlmld_mod_params = { 772 .power_scheme = IWL_POWER_SCHEME_BPS, 773}; 774 775module_param_named(power_scheme, iwlmld_mod_params.power_scheme, int, 0444); 776MODULE_PARM_DESC(power_scheme, 777 "power management scheme: 1-active, 2-balanced, default: 2");
~/
Read-only file preview.