18c2ecf20Sopenharmony_ci/****************************************************************************** 28c2ecf20Sopenharmony_ci * 38c2ecf20Sopenharmony_ci * This file is provided under a dual BSD/GPLv2 license. When using or 48c2ecf20Sopenharmony_ci * redistributing this file, you may do so under either license. 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * GPL LICENSE SUMMARY 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * Copyright(c) 2012 - 2014, 2018 - 2020 Intel Corporation. All rights reserved. 98c2ecf20Sopenharmony_ci * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH 108c2ecf20Sopenharmony_ci * Copyright(c) 2016 - 2017 Intel Deutschland GmbH 118c2ecf20Sopenharmony_ci * 128c2ecf20Sopenharmony_ci * This program is free software; you can redistribute it and/or modify 138c2ecf20Sopenharmony_ci * it under the terms of version 2 of the GNU General Public License as 148c2ecf20Sopenharmony_ci * published by the Free Software Foundation. 158c2ecf20Sopenharmony_ci * 168c2ecf20Sopenharmony_ci * This program is distributed in the hope that it will be useful, but 178c2ecf20Sopenharmony_ci * WITHOUT ANY WARRANTY; without even the implied warranty of 188c2ecf20Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 198c2ecf20Sopenharmony_ci * General Public License for more details. 208c2ecf20Sopenharmony_ci * 218c2ecf20Sopenharmony_ci * The full GNU General Public License is included in this distribution 228c2ecf20Sopenharmony_ci * in the file called COPYING. 238c2ecf20Sopenharmony_ci * 248c2ecf20Sopenharmony_ci * Contact Information: 258c2ecf20Sopenharmony_ci * Intel Linux Wireless <linuxwifi@intel.com> 268c2ecf20Sopenharmony_ci * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 278c2ecf20Sopenharmony_ci * 288c2ecf20Sopenharmony_ci * BSD LICENSE 298c2ecf20Sopenharmony_ci * 308c2ecf20Sopenharmony_ci * Copyright(c) 2012 - 2014, 2018 - 2020 Intel Corporation. All rights reserved. 318c2ecf20Sopenharmony_ci * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH 328c2ecf20Sopenharmony_ci * Copyright(c) 2016 - 2017 Intel Deutschland GmbH 338c2ecf20Sopenharmony_ci * All rights reserved. 348c2ecf20Sopenharmony_ci * 358c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or without 368c2ecf20Sopenharmony_ci * modification, are permitted provided that the following conditions 378c2ecf20Sopenharmony_ci * are met: 388c2ecf20Sopenharmony_ci * 398c2ecf20Sopenharmony_ci * * Redistributions of source code must retain the above copyright 408c2ecf20Sopenharmony_ci * notice, this list of conditions and the following disclaimer. 418c2ecf20Sopenharmony_ci * * Redistributions in binary form must reproduce the above copyright 428c2ecf20Sopenharmony_ci * notice, this list of conditions and the following disclaimer in 438c2ecf20Sopenharmony_ci * the documentation and/or other materials provided with the 448c2ecf20Sopenharmony_ci * distribution. 458c2ecf20Sopenharmony_ci * * Neither the name Intel Corporation nor the names of its 468c2ecf20Sopenharmony_ci * contributors may be used to endorse or promote products derived 478c2ecf20Sopenharmony_ci * from this software without specific prior written permission. 488c2ecf20Sopenharmony_ci * 498c2ecf20Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 508c2ecf20Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 518c2ecf20Sopenharmony_ci * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 528c2ecf20Sopenharmony_ci * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 538c2ecf20Sopenharmony_ci * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 548c2ecf20Sopenharmony_ci * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 558c2ecf20Sopenharmony_ci * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 568c2ecf20Sopenharmony_ci * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 578c2ecf20Sopenharmony_ci * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 588c2ecf20Sopenharmony_ci * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 598c2ecf20Sopenharmony_ci * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 608c2ecf20Sopenharmony_ci * 618c2ecf20Sopenharmony_ci *****************************************************************************/ 628c2ecf20Sopenharmony_ci#include <linux/module.h> 638c2ecf20Sopenharmony_ci#include <linux/vmalloc.h> 648c2ecf20Sopenharmony_ci#include <net/mac80211.h> 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci#include "fw/notif-wait.h" 678c2ecf20Sopenharmony_ci#include "iwl-trans.h" 688c2ecf20Sopenharmony_ci#include "iwl-op-mode.h" 698c2ecf20Sopenharmony_ci#include "fw/img.h" 708c2ecf20Sopenharmony_ci#include "iwl-debug.h" 718c2ecf20Sopenharmony_ci#include "iwl-drv.h" 728c2ecf20Sopenharmony_ci#include "iwl-modparams.h" 738c2ecf20Sopenharmony_ci#include "mvm.h" 748c2ecf20Sopenharmony_ci#include "iwl-phy-db.h" 758c2ecf20Sopenharmony_ci#include "iwl-eeprom-parse.h" 768c2ecf20Sopenharmony_ci#include "iwl-csr.h" 778c2ecf20Sopenharmony_ci#include "iwl-io.h" 788c2ecf20Sopenharmony_ci#include "iwl-prph.h" 798c2ecf20Sopenharmony_ci#include "rs.h" 808c2ecf20Sopenharmony_ci#include "fw/api/scan.h" 818c2ecf20Sopenharmony_ci#include "time-event.h" 828c2ecf20Sopenharmony_ci#include "fw-api.h" 838c2ecf20Sopenharmony_ci#include "fw/acpi.h" 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci#define DRV_DESCRIPTION "The new Intel(R) wireless AGN driver for Linux" 868c2ecf20Sopenharmony_ciMODULE_DESCRIPTION(DRV_DESCRIPTION); 878c2ecf20Sopenharmony_ciMODULE_AUTHOR(DRV_AUTHOR); 888c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_cistatic const struct iwl_op_mode_ops iwl_mvm_ops; 918c2ecf20Sopenharmony_cistatic const struct iwl_op_mode_ops iwl_mvm_ops_mq; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_cistruct iwl_mvm_mod_params iwlmvm_mod_params = { 948c2ecf20Sopenharmony_ci .power_scheme = IWL_POWER_SCHEME_BPS, 958c2ecf20Sopenharmony_ci /* rest of fields are 0 by default */ 968c2ecf20Sopenharmony_ci}; 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_cimodule_param_named(init_dbg, iwlmvm_mod_params.init_dbg, bool, 0444); 998c2ecf20Sopenharmony_ciMODULE_PARM_DESC(init_dbg, 1008c2ecf20Sopenharmony_ci "set to true to debug an ASSERT in INIT fw (default: false"); 1018c2ecf20Sopenharmony_cimodule_param_named(power_scheme, iwlmvm_mod_params.power_scheme, int, 0444); 1028c2ecf20Sopenharmony_ciMODULE_PARM_DESC(power_scheme, 1038c2ecf20Sopenharmony_ci "power management scheme: 1-active, 2-balanced, 3-low power, default: 2"); 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci/* 1068c2ecf20Sopenharmony_ci * module init and exit functions 1078c2ecf20Sopenharmony_ci */ 1088c2ecf20Sopenharmony_cistatic int __init iwl_mvm_init(void) 1098c2ecf20Sopenharmony_ci{ 1108c2ecf20Sopenharmony_ci int ret; 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci ret = iwl_mvm_rate_control_register(); 1138c2ecf20Sopenharmony_ci if (ret) { 1148c2ecf20Sopenharmony_ci pr_err("Unable to register rate control algorithm: %d\n", ret); 1158c2ecf20Sopenharmony_ci return ret; 1168c2ecf20Sopenharmony_ci } 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci ret = iwl_opmode_register("iwlmvm", &iwl_mvm_ops); 1198c2ecf20Sopenharmony_ci if (ret) 1208c2ecf20Sopenharmony_ci pr_err("Unable to register MVM op_mode: %d\n", ret); 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci return ret; 1238c2ecf20Sopenharmony_ci} 1248c2ecf20Sopenharmony_cimodule_init(iwl_mvm_init); 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_cistatic void __exit iwl_mvm_exit(void) 1278c2ecf20Sopenharmony_ci{ 1288c2ecf20Sopenharmony_ci iwl_opmode_deregister("iwlmvm"); 1298c2ecf20Sopenharmony_ci iwl_mvm_rate_control_unregister(); 1308c2ecf20Sopenharmony_ci} 1318c2ecf20Sopenharmony_cimodule_exit(iwl_mvm_exit); 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_cistatic void iwl_mvm_nic_config(struct iwl_op_mode *op_mode) 1348c2ecf20Sopenharmony_ci{ 1358c2ecf20Sopenharmony_ci struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); 1368c2ecf20Sopenharmony_ci struct iwl_trans_debug *dbg = &mvm->trans->dbg; 1378c2ecf20Sopenharmony_ci u8 radio_cfg_type, radio_cfg_step, radio_cfg_dash; 1388c2ecf20Sopenharmony_ci u32 reg_val = 0; 1398c2ecf20Sopenharmony_ci u32 phy_config = iwl_mvm_get_phy_config(mvm); 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci radio_cfg_type = (phy_config & FW_PHY_CFG_RADIO_TYPE) >> 1428c2ecf20Sopenharmony_ci FW_PHY_CFG_RADIO_TYPE_POS; 1438c2ecf20Sopenharmony_ci radio_cfg_step = (phy_config & FW_PHY_CFG_RADIO_STEP) >> 1448c2ecf20Sopenharmony_ci FW_PHY_CFG_RADIO_STEP_POS; 1458c2ecf20Sopenharmony_ci radio_cfg_dash = (phy_config & FW_PHY_CFG_RADIO_DASH) >> 1468c2ecf20Sopenharmony_ci FW_PHY_CFG_RADIO_DASH_POS; 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci /* SKU control */ 1498c2ecf20Sopenharmony_ci reg_val |= CSR_HW_REV_STEP(mvm->trans->hw_rev) << 1508c2ecf20Sopenharmony_ci CSR_HW_IF_CONFIG_REG_POS_MAC_STEP; 1518c2ecf20Sopenharmony_ci reg_val |= CSR_HW_REV_DASH(mvm->trans->hw_rev) << 1528c2ecf20Sopenharmony_ci CSR_HW_IF_CONFIG_REG_POS_MAC_DASH; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci /* radio configuration */ 1558c2ecf20Sopenharmony_ci reg_val |= radio_cfg_type << CSR_HW_IF_CONFIG_REG_POS_PHY_TYPE; 1568c2ecf20Sopenharmony_ci reg_val |= radio_cfg_step << CSR_HW_IF_CONFIG_REG_POS_PHY_STEP; 1578c2ecf20Sopenharmony_ci reg_val |= radio_cfg_dash << CSR_HW_IF_CONFIG_REG_POS_PHY_DASH; 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci WARN_ON((radio_cfg_type << CSR_HW_IF_CONFIG_REG_POS_PHY_TYPE) & 1608c2ecf20Sopenharmony_ci ~CSR_HW_IF_CONFIG_REG_MSK_PHY_TYPE); 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci /* 1638c2ecf20Sopenharmony_ci * TODO: Bits 7-8 of CSR in 8000 HW family and higher set the ADC 1648c2ecf20Sopenharmony_ci * sampling, and shouldn't be set to any non-zero value. 1658c2ecf20Sopenharmony_ci * The same is supposed to be true of the other HW, but unsetting 1668c2ecf20Sopenharmony_ci * them (such as the 7260) causes automatic tests to fail on seemingly 1678c2ecf20Sopenharmony_ci * unrelated errors. Need to further investigate this, but for now 1688c2ecf20Sopenharmony_ci * we'll separate cases. 1698c2ecf20Sopenharmony_ci */ 1708c2ecf20Sopenharmony_ci if (mvm->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_8000) 1718c2ecf20Sopenharmony_ci reg_val |= CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI; 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci if (iwl_fw_dbg_is_d3_debug_enabled(&mvm->fwrt) || 1748c2ecf20Sopenharmony_ci (iwl_trans_dbg_ini_valid(mvm->trans) && 1758c2ecf20Sopenharmony_ci dbg->fw_mon_cfg[IWL_FW_INI_ALLOCATION_ID_INTERNAL].buf_location) 1768c2ecf20Sopenharmony_ci ) 1778c2ecf20Sopenharmony_ci reg_val |= CSR_HW_IF_CONFIG_REG_D3_DEBUG; 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci iwl_trans_set_bits_mask(mvm->trans, CSR_HW_IF_CONFIG_REG, 1808c2ecf20Sopenharmony_ci CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH | 1818c2ecf20Sopenharmony_ci CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP | 1828c2ecf20Sopenharmony_ci CSR_HW_IF_CONFIG_REG_MSK_PHY_TYPE | 1838c2ecf20Sopenharmony_ci CSR_HW_IF_CONFIG_REG_MSK_PHY_STEP | 1848c2ecf20Sopenharmony_ci CSR_HW_IF_CONFIG_REG_MSK_PHY_DASH | 1858c2ecf20Sopenharmony_ci CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | 1868c2ecf20Sopenharmony_ci CSR_HW_IF_CONFIG_REG_BIT_MAC_SI | 1878c2ecf20Sopenharmony_ci CSR_HW_IF_CONFIG_REG_D3_DEBUG, 1888c2ecf20Sopenharmony_ci reg_val); 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci IWL_DEBUG_INFO(mvm, "Radio type=0x%x-0x%x-0x%x\n", radio_cfg_type, 1918c2ecf20Sopenharmony_ci radio_cfg_step, radio_cfg_dash); 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci /* 1948c2ecf20Sopenharmony_ci * W/A : NIC is stuck in a reset state after Early PCIe power off 1958c2ecf20Sopenharmony_ci * (PCIe power is lost before PERST# is asserted), causing ME FW 1968c2ecf20Sopenharmony_ci * to lose ownership and not being able to obtain it back. 1978c2ecf20Sopenharmony_ci */ 1988c2ecf20Sopenharmony_ci if (!mvm->trans->cfg->apmg_not_supported) 1998c2ecf20Sopenharmony_ci iwl_set_bits_mask_prph(mvm->trans, APMG_PS_CTRL_REG, 2008c2ecf20Sopenharmony_ci APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS, 2018c2ecf20Sopenharmony_ci ~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS); 2028c2ecf20Sopenharmony_ci} 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci/** 2058c2ecf20Sopenharmony_ci * enum iwl_rx_handler_context context for Rx handler 2068c2ecf20Sopenharmony_ci * @RX_HANDLER_SYNC : this means that it will be called in the Rx path 2078c2ecf20Sopenharmony_ci * which can't acquire mvm->mutex. 2088c2ecf20Sopenharmony_ci * @RX_HANDLER_ASYNC_LOCKED : If the handler needs to hold mvm->mutex 2098c2ecf20Sopenharmony_ci * (and only in this case!), it should be set as ASYNC. In that case, 2108c2ecf20Sopenharmony_ci * it will be called from a worker with mvm->mutex held. 2118c2ecf20Sopenharmony_ci * @RX_HANDLER_ASYNC_UNLOCKED : in case the handler needs to lock the 2128c2ecf20Sopenharmony_ci * mutex itself, it will be called from a worker without mvm->mutex held. 2138c2ecf20Sopenharmony_ci */ 2148c2ecf20Sopenharmony_cienum iwl_rx_handler_context { 2158c2ecf20Sopenharmony_ci RX_HANDLER_SYNC, 2168c2ecf20Sopenharmony_ci RX_HANDLER_ASYNC_LOCKED, 2178c2ecf20Sopenharmony_ci RX_HANDLER_ASYNC_UNLOCKED, 2188c2ecf20Sopenharmony_ci}; 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci/** 2218c2ecf20Sopenharmony_ci * struct iwl_rx_handlers handler for FW notification 2228c2ecf20Sopenharmony_ci * @cmd_id: command id 2238c2ecf20Sopenharmony_ci * @context: see &iwl_rx_handler_context 2248c2ecf20Sopenharmony_ci * @fn: the function is called when notification is received 2258c2ecf20Sopenharmony_ci */ 2268c2ecf20Sopenharmony_cistruct iwl_rx_handlers { 2278c2ecf20Sopenharmony_ci u16 cmd_id; 2288c2ecf20Sopenharmony_ci enum iwl_rx_handler_context context; 2298c2ecf20Sopenharmony_ci void (*fn)(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb); 2308c2ecf20Sopenharmony_ci}; 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci#define RX_HANDLER(_cmd_id, _fn, _context) \ 2338c2ecf20Sopenharmony_ci { .cmd_id = _cmd_id, .fn = _fn, .context = _context } 2348c2ecf20Sopenharmony_ci#define RX_HANDLER_GRP(_grp, _cmd, _fn, _context) \ 2358c2ecf20Sopenharmony_ci { .cmd_id = WIDE_ID(_grp, _cmd), .fn = _fn, .context = _context } 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci/* 2388c2ecf20Sopenharmony_ci * Handlers for fw notifications 2398c2ecf20Sopenharmony_ci * Convention: RX_HANDLER(CMD_NAME, iwl_mvm_rx_CMD_NAME 2408c2ecf20Sopenharmony_ci * This list should be in order of frequency for performance purposes. 2418c2ecf20Sopenharmony_ci * 2428c2ecf20Sopenharmony_ci * The handler can be one from three contexts, see &iwl_rx_handler_context 2438c2ecf20Sopenharmony_ci */ 2448c2ecf20Sopenharmony_cistatic const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = { 2458c2ecf20Sopenharmony_ci RX_HANDLER(TX_CMD, iwl_mvm_rx_tx_cmd, RX_HANDLER_SYNC), 2468c2ecf20Sopenharmony_ci RX_HANDLER(BA_NOTIF, iwl_mvm_rx_ba_notif, RX_HANDLER_SYNC), 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci RX_HANDLER_GRP(DATA_PATH_GROUP, TLC_MNG_UPDATE_NOTIF, 2498c2ecf20Sopenharmony_ci iwl_mvm_tlc_update_notif, RX_HANDLER_SYNC), 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci RX_HANDLER(BT_PROFILE_NOTIFICATION, iwl_mvm_rx_bt_coex_notif, 2528c2ecf20Sopenharmony_ci RX_HANDLER_ASYNC_LOCKED), 2538c2ecf20Sopenharmony_ci RX_HANDLER(BEACON_NOTIFICATION, iwl_mvm_rx_beacon_notif, 2548c2ecf20Sopenharmony_ci RX_HANDLER_ASYNC_LOCKED), 2558c2ecf20Sopenharmony_ci RX_HANDLER(STATISTICS_NOTIFICATION, iwl_mvm_rx_statistics, 2568c2ecf20Sopenharmony_ci RX_HANDLER_ASYNC_LOCKED), 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci RX_HANDLER(BA_WINDOW_STATUS_NOTIFICATION_ID, 2598c2ecf20Sopenharmony_ci iwl_mvm_window_status_notif, RX_HANDLER_SYNC), 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci RX_HANDLER(TIME_EVENT_NOTIFICATION, iwl_mvm_rx_time_event_notif, 2628c2ecf20Sopenharmony_ci RX_HANDLER_SYNC), 2638c2ecf20Sopenharmony_ci RX_HANDLER_GRP(MAC_CONF_GROUP, SESSION_PROTECTION_NOTIF, 2648c2ecf20Sopenharmony_ci iwl_mvm_rx_session_protect_notif, RX_HANDLER_SYNC), 2658c2ecf20Sopenharmony_ci RX_HANDLER(MCC_CHUB_UPDATE_CMD, iwl_mvm_rx_chub_update_mcc, 2668c2ecf20Sopenharmony_ci RX_HANDLER_ASYNC_LOCKED), 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci RX_HANDLER(EOSP_NOTIFICATION, iwl_mvm_rx_eosp_notif, RX_HANDLER_SYNC), 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci RX_HANDLER(SCAN_ITERATION_COMPLETE, 2718c2ecf20Sopenharmony_ci iwl_mvm_rx_lmac_scan_iter_complete_notif, RX_HANDLER_SYNC), 2728c2ecf20Sopenharmony_ci RX_HANDLER(SCAN_OFFLOAD_COMPLETE, 2738c2ecf20Sopenharmony_ci iwl_mvm_rx_lmac_scan_complete_notif, 2748c2ecf20Sopenharmony_ci RX_HANDLER_ASYNC_LOCKED), 2758c2ecf20Sopenharmony_ci RX_HANDLER(MATCH_FOUND_NOTIFICATION, iwl_mvm_rx_scan_match_found, 2768c2ecf20Sopenharmony_ci RX_HANDLER_SYNC), 2778c2ecf20Sopenharmony_ci RX_HANDLER(SCAN_COMPLETE_UMAC, iwl_mvm_rx_umac_scan_complete_notif, 2788c2ecf20Sopenharmony_ci RX_HANDLER_ASYNC_LOCKED), 2798c2ecf20Sopenharmony_ci RX_HANDLER(SCAN_ITERATION_COMPLETE_UMAC, 2808c2ecf20Sopenharmony_ci iwl_mvm_rx_umac_scan_iter_complete_notif, RX_HANDLER_SYNC), 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci RX_HANDLER(CARD_STATE_NOTIFICATION, iwl_mvm_rx_card_state_notif, 2838c2ecf20Sopenharmony_ci RX_HANDLER_SYNC), 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci RX_HANDLER(MISSED_BEACONS_NOTIFICATION, iwl_mvm_rx_missed_beacons_notif, 2868c2ecf20Sopenharmony_ci RX_HANDLER_SYNC), 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci RX_HANDLER(REPLY_ERROR, iwl_mvm_rx_fw_error, RX_HANDLER_SYNC), 2898c2ecf20Sopenharmony_ci RX_HANDLER(PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION, 2908c2ecf20Sopenharmony_ci iwl_mvm_power_uapsd_misbehaving_ap_notif, RX_HANDLER_SYNC), 2918c2ecf20Sopenharmony_ci RX_HANDLER(DTS_MEASUREMENT_NOTIFICATION, iwl_mvm_temp_notif, 2928c2ecf20Sopenharmony_ci RX_HANDLER_ASYNC_LOCKED), 2938c2ecf20Sopenharmony_ci RX_HANDLER_GRP(PHY_OPS_GROUP, DTS_MEASUREMENT_NOTIF_WIDE, 2948c2ecf20Sopenharmony_ci iwl_mvm_temp_notif, RX_HANDLER_ASYNC_UNLOCKED), 2958c2ecf20Sopenharmony_ci RX_HANDLER_GRP(PHY_OPS_GROUP, CT_KILL_NOTIFICATION, 2968c2ecf20Sopenharmony_ci iwl_mvm_ct_kill_notif, RX_HANDLER_SYNC), 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci RX_HANDLER(TDLS_CHANNEL_SWITCH_NOTIFICATION, iwl_mvm_rx_tdls_notif, 2998c2ecf20Sopenharmony_ci RX_HANDLER_ASYNC_LOCKED), 3008c2ecf20Sopenharmony_ci RX_HANDLER(MFUART_LOAD_NOTIFICATION, iwl_mvm_rx_mfuart_notif, 3018c2ecf20Sopenharmony_ci RX_HANDLER_SYNC), 3028c2ecf20Sopenharmony_ci RX_HANDLER_GRP(LOCATION_GROUP, TOF_RESPONDER_STATS, 3038c2ecf20Sopenharmony_ci iwl_mvm_ftm_responder_stats, RX_HANDLER_ASYNC_LOCKED), 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci RX_HANDLER_GRP(LOCATION_GROUP, TOF_RANGE_RESPONSE_NOTIF, 3068c2ecf20Sopenharmony_ci iwl_mvm_ftm_range_resp, RX_HANDLER_ASYNC_LOCKED), 3078c2ecf20Sopenharmony_ci RX_HANDLER_GRP(LOCATION_GROUP, TOF_LC_NOTIF, 3088c2ecf20Sopenharmony_ci iwl_mvm_ftm_lc_notif, RX_HANDLER_ASYNC_LOCKED), 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci RX_HANDLER_GRP(DEBUG_GROUP, MFU_ASSERT_DUMP_NTF, 3118c2ecf20Sopenharmony_ci iwl_mvm_mfu_assert_dump_notif, RX_HANDLER_SYNC), 3128c2ecf20Sopenharmony_ci RX_HANDLER_GRP(PROT_OFFLOAD_GROUP, STORED_BEACON_NTF, 3138c2ecf20Sopenharmony_ci iwl_mvm_rx_stored_beacon_notif, RX_HANDLER_SYNC), 3148c2ecf20Sopenharmony_ci RX_HANDLER_GRP(DATA_PATH_GROUP, MU_GROUP_MGMT_NOTIF, 3158c2ecf20Sopenharmony_ci iwl_mvm_mu_mimo_grp_notif, RX_HANDLER_SYNC), 3168c2ecf20Sopenharmony_ci RX_HANDLER_GRP(DATA_PATH_GROUP, STA_PM_NOTIF, 3178c2ecf20Sopenharmony_ci iwl_mvm_sta_pm_notif, RX_HANDLER_SYNC), 3188c2ecf20Sopenharmony_ci RX_HANDLER_GRP(MAC_CONF_GROUP, PROBE_RESPONSE_DATA_NOTIF, 3198c2ecf20Sopenharmony_ci iwl_mvm_probe_resp_data_notif, 3208c2ecf20Sopenharmony_ci RX_HANDLER_ASYNC_LOCKED), 3218c2ecf20Sopenharmony_ci RX_HANDLER_GRP(MAC_CONF_GROUP, CHANNEL_SWITCH_NOA_NOTIF, 3228c2ecf20Sopenharmony_ci iwl_mvm_channel_switch_noa_notif, 3238c2ecf20Sopenharmony_ci RX_HANDLER_SYNC), 3248c2ecf20Sopenharmony_ci}; 3258c2ecf20Sopenharmony_ci#undef RX_HANDLER 3268c2ecf20Sopenharmony_ci#undef RX_HANDLER_GRP 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci/* Please keep this array *SORTED* by hex value. 3298c2ecf20Sopenharmony_ci * Access is done through binary search 3308c2ecf20Sopenharmony_ci */ 3318c2ecf20Sopenharmony_cistatic const struct iwl_hcmd_names iwl_mvm_legacy_names[] = { 3328c2ecf20Sopenharmony_ci HCMD_NAME(UCODE_ALIVE_NTFY), 3338c2ecf20Sopenharmony_ci HCMD_NAME(REPLY_ERROR), 3348c2ecf20Sopenharmony_ci HCMD_NAME(ECHO_CMD), 3358c2ecf20Sopenharmony_ci HCMD_NAME(INIT_COMPLETE_NOTIF), 3368c2ecf20Sopenharmony_ci HCMD_NAME(PHY_CONTEXT_CMD), 3378c2ecf20Sopenharmony_ci HCMD_NAME(DBG_CFG), 3388c2ecf20Sopenharmony_ci HCMD_NAME(SCAN_CFG_CMD), 3398c2ecf20Sopenharmony_ci HCMD_NAME(SCAN_REQ_UMAC), 3408c2ecf20Sopenharmony_ci HCMD_NAME(SCAN_ABORT_UMAC), 3418c2ecf20Sopenharmony_ci HCMD_NAME(SCAN_COMPLETE_UMAC), 3428c2ecf20Sopenharmony_ci HCMD_NAME(BA_WINDOW_STATUS_NOTIFICATION_ID), 3438c2ecf20Sopenharmony_ci HCMD_NAME(ADD_STA_KEY), 3448c2ecf20Sopenharmony_ci HCMD_NAME(ADD_STA), 3458c2ecf20Sopenharmony_ci HCMD_NAME(REMOVE_STA), 3468c2ecf20Sopenharmony_ci HCMD_NAME(FW_GET_ITEM_CMD), 3478c2ecf20Sopenharmony_ci HCMD_NAME(TX_CMD), 3488c2ecf20Sopenharmony_ci HCMD_NAME(SCD_QUEUE_CFG), 3498c2ecf20Sopenharmony_ci HCMD_NAME(TXPATH_FLUSH), 3508c2ecf20Sopenharmony_ci HCMD_NAME(MGMT_MCAST_KEY), 3518c2ecf20Sopenharmony_ci HCMD_NAME(WEP_KEY), 3528c2ecf20Sopenharmony_ci HCMD_NAME(SHARED_MEM_CFG), 3538c2ecf20Sopenharmony_ci HCMD_NAME(TDLS_CHANNEL_SWITCH_CMD), 3548c2ecf20Sopenharmony_ci HCMD_NAME(MAC_CONTEXT_CMD), 3558c2ecf20Sopenharmony_ci HCMD_NAME(TIME_EVENT_CMD), 3568c2ecf20Sopenharmony_ci HCMD_NAME(TIME_EVENT_NOTIFICATION), 3578c2ecf20Sopenharmony_ci HCMD_NAME(BINDING_CONTEXT_CMD), 3588c2ecf20Sopenharmony_ci HCMD_NAME(TIME_QUOTA_CMD), 3598c2ecf20Sopenharmony_ci HCMD_NAME(NON_QOS_TX_COUNTER_CMD), 3608c2ecf20Sopenharmony_ci HCMD_NAME(LEDS_CMD), 3618c2ecf20Sopenharmony_ci HCMD_NAME(LQ_CMD), 3628c2ecf20Sopenharmony_ci HCMD_NAME(FW_PAGING_BLOCK_CMD), 3638c2ecf20Sopenharmony_ci HCMD_NAME(SCAN_OFFLOAD_REQUEST_CMD), 3648c2ecf20Sopenharmony_ci HCMD_NAME(SCAN_OFFLOAD_ABORT_CMD), 3658c2ecf20Sopenharmony_ci HCMD_NAME(HOT_SPOT_CMD), 3668c2ecf20Sopenharmony_ci HCMD_NAME(SCAN_OFFLOAD_PROFILES_QUERY_CMD), 3678c2ecf20Sopenharmony_ci HCMD_NAME(BT_COEX_UPDATE_REDUCED_TXP), 3688c2ecf20Sopenharmony_ci HCMD_NAME(BT_COEX_CI), 3698c2ecf20Sopenharmony_ci HCMD_NAME(PHY_CONFIGURATION_CMD), 3708c2ecf20Sopenharmony_ci HCMD_NAME(CALIB_RES_NOTIF_PHY_DB), 3718c2ecf20Sopenharmony_ci HCMD_NAME(PHY_DB_CMD), 3728c2ecf20Sopenharmony_ci HCMD_NAME(SCAN_OFFLOAD_COMPLETE), 3738c2ecf20Sopenharmony_ci HCMD_NAME(SCAN_OFFLOAD_UPDATE_PROFILES_CMD), 3748c2ecf20Sopenharmony_ci HCMD_NAME(POWER_TABLE_CMD), 3758c2ecf20Sopenharmony_ci HCMD_NAME(PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION), 3768c2ecf20Sopenharmony_ci HCMD_NAME(REPLY_THERMAL_MNG_BACKOFF), 3778c2ecf20Sopenharmony_ci HCMD_NAME(DC2DC_CONFIG_CMD), 3788c2ecf20Sopenharmony_ci HCMD_NAME(NVM_ACCESS_CMD), 3798c2ecf20Sopenharmony_ci HCMD_NAME(BEACON_NOTIFICATION), 3808c2ecf20Sopenharmony_ci HCMD_NAME(BEACON_TEMPLATE_CMD), 3818c2ecf20Sopenharmony_ci HCMD_NAME(TX_ANT_CONFIGURATION_CMD), 3828c2ecf20Sopenharmony_ci HCMD_NAME(BT_CONFIG), 3838c2ecf20Sopenharmony_ci HCMD_NAME(STATISTICS_CMD), 3848c2ecf20Sopenharmony_ci HCMD_NAME(STATISTICS_NOTIFICATION), 3858c2ecf20Sopenharmony_ci HCMD_NAME(EOSP_NOTIFICATION), 3868c2ecf20Sopenharmony_ci HCMD_NAME(REDUCE_TX_POWER_CMD), 3878c2ecf20Sopenharmony_ci HCMD_NAME(CARD_STATE_NOTIFICATION), 3888c2ecf20Sopenharmony_ci HCMD_NAME(MISSED_BEACONS_NOTIFICATION), 3898c2ecf20Sopenharmony_ci HCMD_NAME(TDLS_CONFIG_CMD), 3908c2ecf20Sopenharmony_ci HCMD_NAME(MAC_PM_POWER_TABLE), 3918c2ecf20Sopenharmony_ci HCMD_NAME(TDLS_CHANNEL_SWITCH_NOTIFICATION), 3928c2ecf20Sopenharmony_ci HCMD_NAME(MFUART_LOAD_NOTIFICATION), 3938c2ecf20Sopenharmony_ci HCMD_NAME(RSS_CONFIG_CMD), 3948c2ecf20Sopenharmony_ci HCMD_NAME(SCAN_ITERATION_COMPLETE_UMAC), 3958c2ecf20Sopenharmony_ci HCMD_NAME(REPLY_RX_PHY_CMD), 3968c2ecf20Sopenharmony_ci HCMD_NAME(REPLY_RX_MPDU_CMD), 3978c2ecf20Sopenharmony_ci HCMD_NAME(BAR_FRAME_RELEASE), 3988c2ecf20Sopenharmony_ci HCMD_NAME(FRAME_RELEASE), 3998c2ecf20Sopenharmony_ci HCMD_NAME(BA_NOTIF), 4008c2ecf20Sopenharmony_ci HCMD_NAME(MCC_UPDATE_CMD), 4018c2ecf20Sopenharmony_ci HCMD_NAME(MCC_CHUB_UPDATE_CMD), 4028c2ecf20Sopenharmony_ci HCMD_NAME(MARKER_CMD), 4038c2ecf20Sopenharmony_ci HCMD_NAME(BT_PROFILE_NOTIFICATION), 4048c2ecf20Sopenharmony_ci HCMD_NAME(BCAST_FILTER_CMD), 4058c2ecf20Sopenharmony_ci HCMD_NAME(MCAST_FILTER_CMD), 4068c2ecf20Sopenharmony_ci HCMD_NAME(REPLY_SF_CFG_CMD), 4078c2ecf20Sopenharmony_ci HCMD_NAME(REPLY_BEACON_FILTERING_CMD), 4088c2ecf20Sopenharmony_ci HCMD_NAME(D3_CONFIG_CMD), 4098c2ecf20Sopenharmony_ci HCMD_NAME(PROT_OFFLOAD_CONFIG_CMD), 4108c2ecf20Sopenharmony_ci HCMD_NAME(OFFLOADS_QUERY_CMD), 4118c2ecf20Sopenharmony_ci HCMD_NAME(REMOTE_WAKE_CONFIG_CMD), 4128c2ecf20Sopenharmony_ci HCMD_NAME(MATCH_FOUND_NOTIFICATION), 4138c2ecf20Sopenharmony_ci HCMD_NAME(DTS_MEASUREMENT_NOTIFICATION), 4148c2ecf20Sopenharmony_ci HCMD_NAME(WOWLAN_PATTERNS), 4158c2ecf20Sopenharmony_ci HCMD_NAME(WOWLAN_CONFIGURATION), 4168c2ecf20Sopenharmony_ci HCMD_NAME(WOWLAN_TSC_RSC_PARAM), 4178c2ecf20Sopenharmony_ci HCMD_NAME(WOWLAN_TKIP_PARAM), 4188c2ecf20Sopenharmony_ci HCMD_NAME(WOWLAN_KEK_KCK_MATERIAL), 4198c2ecf20Sopenharmony_ci HCMD_NAME(WOWLAN_GET_STATUSES), 4208c2ecf20Sopenharmony_ci HCMD_NAME(SCAN_ITERATION_COMPLETE), 4218c2ecf20Sopenharmony_ci HCMD_NAME(D0I3_END_CMD), 4228c2ecf20Sopenharmony_ci HCMD_NAME(LTR_CONFIG), 4238c2ecf20Sopenharmony_ci HCMD_NAME(LDBG_CONFIG_CMD), 4248c2ecf20Sopenharmony_ci}; 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ci/* Please keep this array *SORTED* by hex value. 4278c2ecf20Sopenharmony_ci * Access is done through binary search 4288c2ecf20Sopenharmony_ci */ 4298c2ecf20Sopenharmony_cistatic const struct iwl_hcmd_names iwl_mvm_system_names[] = { 4308c2ecf20Sopenharmony_ci HCMD_NAME(SHARED_MEM_CFG_CMD), 4318c2ecf20Sopenharmony_ci HCMD_NAME(INIT_EXTENDED_CFG_CMD), 4328c2ecf20Sopenharmony_ci HCMD_NAME(FW_ERROR_RECOVERY_CMD), 4338c2ecf20Sopenharmony_ci}; 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_ci/* Please keep this array *SORTED* by hex value. 4368c2ecf20Sopenharmony_ci * Access is done through binary search 4378c2ecf20Sopenharmony_ci */ 4388c2ecf20Sopenharmony_cistatic const struct iwl_hcmd_names iwl_mvm_mac_conf_names[] = { 4398c2ecf20Sopenharmony_ci HCMD_NAME(CHANNEL_SWITCH_TIME_EVENT_CMD), 4408c2ecf20Sopenharmony_ci HCMD_NAME(SESSION_PROTECTION_CMD), 4418c2ecf20Sopenharmony_ci HCMD_NAME(SESSION_PROTECTION_NOTIF), 4428c2ecf20Sopenharmony_ci HCMD_NAME(CHANNEL_SWITCH_NOA_NOTIF), 4438c2ecf20Sopenharmony_ci}; 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_ci/* Please keep this array *SORTED* by hex value. 4468c2ecf20Sopenharmony_ci * Access is done through binary search 4478c2ecf20Sopenharmony_ci */ 4488c2ecf20Sopenharmony_cistatic const struct iwl_hcmd_names iwl_mvm_phy_names[] = { 4498c2ecf20Sopenharmony_ci HCMD_NAME(CMD_DTS_MEASUREMENT_TRIGGER_WIDE), 4508c2ecf20Sopenharmony_ci HCMD_NAME(CTDP_CONFIG_CMD), 4518c2ecf20Sopenharmony_ci HCMD_NAME(TEMP_REPORTING_THRESHOLDS_CMD), 4528c2ecf20Sopenharmony_ci HCMD_NAME(GEO_TX_POWER_LIMIT), 4538c2ecf20Sopenharmony_ci HCMD_NAME(CT_KILL_NOTIFICATION), 4548c2ecf20Sopenharmony_ci HCMD_NAME(DTS_MEASUREMENT_NOTIF_WIDE), 4558c2ecf20Sopenharmony_ci}; 4568c2ecf20Sopenharmony_ci 4578c2ecf20Sopenharmony_ci/* Please keep this array *SORTED* by hex value. 4588c2ecf20Sopenharmony_ci * Access is done through binary search 4598c2ecf20Sopenharmony_ci */ 4608c2ecf20Sopenharmony_cistatic const struct iwl_hcmd_names iwl_mvm_data_path_names[] = { 4618c2ecf20Sopenharmony_ci HCMD_NAME(DQA_ENABLE_CMD), 4628c2ecf20Sopenharmony_ci HCMD_NAME(UPDATE_MU_GROUPS_CMD), 4638c2ecf20Sopenharmony_ci HCMD_NAME(TRIGGER_RX_QUEUES_NOTIF_CMD), 4648c2ecf20Sopenharmony_ci HCMD_NAME(STA_HE_CTXT_CMD), 4658c2ecf20Sopenharmony_ci HCMD_NAME(RFH_QUEUE_CONFIG_CMD), 4668c2ecf20Sopenharmony_ci HCMD_NAME(TLC_MNG_CONFIG_CMD), 4678c2ecf20Sopenharmony_ci HCMD_NAME(CHEST_COLLECTOR_FILTER_CONFIG_CMD), 4688c2ecf20Sopenharmony_ci HCMD_NAME(STA_PM_NOTIF), 4698c2ecf20Sopenharmony_ci HCMD_NAME(MU_GROUP_MGMT_NOTIF), 4708c2ecf20Sopenharmony_ci HCMD_NAME(RX_QUEUES_NOTIFICATION), 4718c2ecf20Sopenharmony_ci}; 4728c2ecf20Sopenharmony_ci 4738c2ecf20Sopenharmony_ci/* Please keep this array *SORTED* by hex value. 4748c2ecf20Sopenharmony_ci * Access is done through binary search 4758c2ecf20Sopenharmony_ci */ 4768c2ecf20Sopenharmony_cistatic const struct iwl_hcmd_names iwl_mvm_location_names[] = { 4778c2ecf20Sopenharmony_ci HCMD_NAME(TOF_RANGE_REQ_CMD), 4788c2ecf20Sopenharmony_ci HCMD_NAME(TOF_CONFIG_CMD), 4798c2ecf20Sopenharmony_ci HCMD_NAME(TOF_RANGE_ABORT_CMD), 4808c2ecf20Sopenharmony_ci HCMD_NAME(TOF_RANGE_REQ_EXT_CMD), 4818c2ecf20Sopenharmony_ci HCMD_NAME(TOF_RESPONDER_CONFIG_CMD), 4828c2ecf20Sopenharmony_ci HCMD_NAME(TOF_RESPONDER_DYN_CONFIG_CMD), 4838c2ecf20Sopenharmony_ci HCMD_NAME(TOF_LC_NOTIF), 4848c2ecf20Sopenharmony_ci HCMD_NAME(TOF_RESPONDER_STATS), 4858c2ecf20Sopenharmony_ci HCMD_NAME(TOF_MCSI_DEBUG_NOTIF), 4868c2ecf20Sopenharmony_ci HCMD_NAME(TOF_RANGE_RESPONSE_NOTIF), 4878c2ecf20Sopenharmony_ci}; 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_ci/* Please keep this array *SORTED* by hex value. 4908c2ecf20Sopenharmony_ci * Access is done through binary search 4918c2ecf20Sopenharmony_ci */ 4928c2ecf20Sopenharmony_cistatic const struct iwl_hcmd_names iwl_mvm_prot_offload_names[] = { 4938c2ecf20Sopenharmony_ci HCMD_NAME(STORED_BEACON_NTF), 4948c2ecf20Sopenharmony_ci}; 4958c2ecf20Sopenharmony_ci 4968c2ecf20Sopenharmony_ci/* Please keep this array *SORTED* by hex value. 4978c2ecf20Sopenharmony_ci * Access is done through binary search 4988c2ecf20Sopenharmony_ci */ 4998c2ecf20Sopenharmony_cistatic const struct iwl_hcmd_names iwl_mvm_regulatory_and_nvm_names[] = { 5008c2ecf20Sopenharmony_ci HCMD_NAME(NVM_ACCESS_COMPLETE), 5018c2ecf20Sopenharmony_ci HCMD_NAME(NVM_GET_INFO), 5028c2ecf20Sopenharmony_ci HCMD_NAME(TAS_CONFIG), 5038c2ecf20Sopenharmony_ci}; 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_cistatic const struct iwl_hcmd_arr iwl_mvm_groups[] = { 5068c2ecf20Sopenharmony_ci [LEGACY_GROUP] = HCMD_ARR(iwl_mvm_legacy_names), 5078c2ecf20Sopenharmony_ci [LONG_GROUP] = HCMD_ARR(iwl_mvm_legacy_names), 5088c2ecf20Sopenharmony_ci [SYSTEM_GROUP] = HCMD_ARR(iwl_mvm_system_names), 5098c2ecf20Sopenharmony_ci [MAC_CONF_GROUP] = HCMD_ARR(iwl_mvm_mac_conf_names), 5108c2ecf20Sopenharmony_ci [PHY_OPS_GROUP] = HCMD_ARR(iwl_mvm_phy_names), 5118c2ecf20Sopenharmony_ci [DATA_PATH_GROUP] = HCMD_ARR(iwl_mvm_data_path_names), 5128c2ecf20Sopenharmony_ci [LOCATION_GROUP] = HCMD_ARR(iwl_mvm_location_names), 5138c2ecf20Sopenharmony_ci [PROT_OFFLOAD_GROUP] = HCMD_ARR(iwl_mvm_prot_offload_names), 5148c2ecf20Sopenharmony_ci [REGULATORY_AND_NVM_GROUP] = 5158c2ecf20Sopenharmony_ci HCMD_ARR(iwl_mvm_regulatory_and_nvm_names), 5168c2ecf20Sopenharmony_ci}; 5178c2ecf20Sopenharmony_ci 5188c2ecf20Sopenharmony_ci/* this forward declaration can avoid to export the function */ 5198c2ecf20Sopenharmony_cistatic void iwl_mvm_async_handlers_wk(struct work_struct *wk); 5208c2ecf20Sopenharmony_ci 5218c2ecf20Sopenharmony_cistatic u32 iwl_mvm_min_backoff(struct iwl_mvm *mvm) 5228c2ecf20Sopenharmony_ci{ 5238c2ecf20Sopenharmony_ci const struct iwl_pwr_tx_backoff *backoff = mvm->cfg->pwr_tx_backoffs; 5248c2ecf20Sopenharmony_ci u64 dflt_pwr_limit; 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_ci if (!backoff) 5278c2ecf20Sopenharmony_ci return 0; 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_ci dflt_pwr_limit = iwl_acpi_get_pwr_limit(mvm->dev); 5308c2ecf20Sopenharmony_ci 5318c2ecf20Sopenharmony_ci while (backoff->pwr) { 5328c2ecf20Sopenharmony_ci if (dflt_pwr_limit >= backoff->pwr) 5338c2ecf20Sopenharmony_ci return backoff->backoff; 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_ci backoff++; 5368c2ecf20Sopenharmony_ci } 5378c2ecf20Sopenharmony_ci 5388c2ecf20Sopenharmony_ci return 0; 5398c2ecf20Sopenharmony_ci} 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_cistatic void iwl_mvm_tx_unblock_dwork(struct work_struct *work) 5428c2ecf20Sopenharmony_ci{ 5438c2ecf20Sopenharmony_ci struct iwl_mvm *mvm = 5448c2ecf20Sopenharmony_ci container_of(work, struct iwl_mvm, cs_tx_unblock_dwork.work); 5458c2ecf20Sopenharmony_ci struct ieee80211_vif *tx_blocked_vif; 5468c2ecf20Sopenharmony_ci struct iwl_mvm_vif *mvmvif; 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_ci mutex_lock(&mvm->mutex); 5498c2ecf20Sopenharmony_ci 5508c2ecf20Sopenharmony_ci tx_blocked_vif = 5518c2ecf20Sopenharmony_ci rcu_dereference_protected(mvm->csa_tx_blocked_vif, 5528c2ecf20Sopenharmony_ci lockdep_is_held(&mvm->mutex)); 5538c2ecf20Sopenharmony_ci 5548c2ecf20Sopenharmony_ci if (!tx_blocked_vif) 5558c2ecf20Sopenharmony_ci goto unlock; 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_ci mvmvif = iwl_mvm_vif_from_mac80211(tx_blocked_vif); 5588c2ecf20Sopenharmony_ci iwl_mvm_modify_all_sta_disable_tx(mvm, mvmvif, false); 5598c2ecf20Sopenharmony_ci RCU_INIT_POINTER(mvm->csa_tx_blocked_vif, NULL); 5608c2ecf20Sopenharmony_ciunlock: 5618c2ecf20Sopenharmony_ci mutex_unlock(&mvm->mutex); 5628c2ecf20Sopenharmony_ci} 5638c2ecf20Sopenharmony_ci 5648c2ecf20Sopenharmony_cistatic int iwl_mvm_fwrt_dump_start(void *ctx) 5658c2ecf20Sopenharmony_ci{ 5668c2ecf20Sopenharmony_ci struct iwl_mvm *mvm = ctx; 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_ci mutex_lock(&mvm->mutex); 5698c2ecf20Sopenharmony_ci 5708c2ecf20Sopenharmony_ci return 0; 5718c2ecf20Sopenharmony_ci} 5728c2ecf20Sopenharmony_ci 5738c2ecf20Sopenharmony_cistatic void iwl_mvm_fwrt_dump_end(void *ctx) 5748c2ecf20Sopenharmony_ci{ 5758c2ecf20Sopenharmony_ci struct iwl_mvm *mvm = ctx; 5768c2ecf20Sopenharmony_ci 5778c2ecf20Sopenharmony_ci mutex_unlock(&mvm->mutex); 5788c2ecf20Sopenharmony_ci} 5798c2ecf20Sopenharmony_ci 5808c2ecf20Sopenharmony_cistatic bool iwl_mvm_fwrt_fw_running(void *ctx) 5818c2ecf20Sopenharmony_ci{ 5828c2ecf20Sopenharmony_ci return iwl_mvm_firmware_running(ctx); 5838c2ecf20Sopenharmony_ci} 5848c2ecf20Sopenharmony_ci 5858c2ecf20Sopenharmony_cistatic int iwl_mvm_fwrt_send_hcmd(void *ctx, struct iwl_host_cmd *host_cmd) 5868c2ecf20Sopenharmony_ci{ 5878c2ecf20Sopenharmony_ci struct iwl_mvm *mvm = (struct iwl_mvm *)ctx; 5888c2ecf20Sopenharmony_ci int ret; 5898c2ecf20Sopenharmony_ci 5908c2ecf20Sopenharmony_ci mutex_lock(&mvm->mutex); 5918c2ecf20Sopenharmony_ci ret = iwl_mvm_send_cmd(mvm, host_cmd); 5928c2ecf20Sopenharmony_ci mutex_unlock(&mvm->mutex); 5938c2ecf20Sopenharmony_ci 5948c2ecf20Sopenharmony_ci return ret; 5958c2ecf20Sopenharmony_ci} 5968c2ecf20Sopenharmony_ci 5978c2ecf20Sopenharmony_cistatic bool iwl_mvm_d3_debug_enable(void *ctx) 5988c2ecf20Sopenharmony_ci{ 5998c2ecf20Sopenharmony_ci return IWL_MVM_D3_DEBUG; 6008c2ecf20Sopenharmony_ci} 6018c2ecf20Sopenharmony_ci 6028c2ecf20Sopenharmony_cistatic const struct iwl_fw_runtime_ops iwl_mvm_fwrt_ops = { 6038c2ecf20Sopenharmony_ci .dump_start = iwl_mvm_fwrt_dump_start, 6048c2ecf20Sopenharmony_ci .dump_end = iwl_mvm_fwrt_dump_end, 6058c2ecf20Sopenharmony_ci .fw_running = iwl_mvm_fwrt_fw_running, 6068c2ecf20Sopenharmony_ci .send_hcmd = iwl_mvm_fwrt_send_hcmd, 6078c2ecf20Sopenharmony_ci .d3_debug_enable = iwl_mvm_d3_debug_enable, 6088c2ecf20Sopenharmony_ci}; 6098c2ecf20Sopenharmony_ci 6108c2ecf20Sopenharmony_cistatic struct iwl_op_mode * 6118c2ecf20Sopenharmony_ciiwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, 6128c2ecf20Sopenharmony_ci const struct iwl_fw *fw, struct dentry *dbgfs_dir) 6138c2ecf20Sopenharmony_ci{ 6148c2ecf20Sopenharmony_ci struct ieee80211_hw *hw; 6158c2ecf20Sopenharmony_ci struct iwl_op_mode *op_mode; 6168c2ecf20Sopenharmony_ci struct iwl_mvm *mvm; 6178c2ecf20Sopenharmony_ci struct iwl_trans_config trans_cfg = {}; 6188c2ecf20Sopenharmony_ci static const u8 no_reclaim_cmds[] = { 6198c2ecf20Sopenharmony_ci TX_CMD, 6208c2ecf20Sopenharmony_ci }; 6218c2ecf20Sopenharmony_ci int err, scan_size; 6228c2ecf20Sopenharmony_ci u32 min_backoff; 6238c2ecf20Sopenharmony_ci enum iwl_amsdu_size rb_size_default; 6248c2ecf20Sopenharmony_ci 6258c2ecf20Sopenharmony_ci /* 6268c2ecf20Sopenharmony_ci * We use IWL_MVM_STATION_COUNT_MAX to check the validity of the station 6278c2ecf20Sopenharmony_ci * index all over the driver - check that its value corresponds to the 6288c2ecf20Sopenharmony_ci * array size. 6298c2ecf20Sopenharmony_ci */ 6308c2ecf20Sopenharmony_ci BUILD_BUG_ON(ARRAY_SIZE(mvm->fw_id_to_mac_id) != 6318c2ecf20Sopenharmony_ci IWL_MVM_STATION_COUNT_MAX); 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_ci /******************************** 6348c2ecf20Sopenharmony_ci * 1. Allocating and configuring HW data 6358c2ecf20Sopenharmony_ci ********************************/ 6368c2ecf20Sopenharmony_ci hw = ieee80211_alloc_hw(sizeof(struct iwl_op_mode) + 6378c2ecf20Sopenharmony_ci sizeof(struct iwl_mvm), 6388c2ecf20Sopenharmony_ci &iwl_mvm_hw_ops); 6398c2ecf20Sopenharmony_ci if (!hw) 6408c2ecf20Sopenharmony_ci return NULL; 6418c2ecf20Sopenharmony_ci 6428c2ecf20Sopenharmony_ci hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF; 6438c2ecf20Sopenharmony_ci 6448c2ecf20Sopenharmony_ci if (cfg->max_tx_agg_size) 6458c2ecf20Sopenharmony_ci hw->max_tx_aggregation_subframes = cfg->max_tx_agg_size; 6468c2ecf20Sopenharmony_ci else 6478c2ecf20Sopenharmony_ci hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF; 6488c2ecf20Sopenharmony_ci 6498c2ecf20Sopenharmony_ci op_mode = hw->priv; 6508c2ecf20Sopenharmony_ci 6518c2ecf20Sopenharmony_ci mvm = IWL_OP_MODE_GET_MVM(op_mode); 6528c2ecf20Sopenharmony_ci mvm->dev = trans->dev; 6538c2ecf20Sopenharmony_ci mvm->trans = trans; 6548c2ecf20Sopenharmony_ci mvm->cfg = cfg; 6558c2ecf20Sopenharmony_ci mvm->fw = fw; 6568c2ecf20Sopenharmony_ci mvm->hw = hw; 6578c2ecf20Sopenharmony_ci 6588c2ecf20Sopenharmony_ci iwl_fw_runtime_init(&mvm->fwrt, trans, fw, &iwl_mvm_fwrt_ops, mvm, 6598c2ecf20Sopenharmony_ci dbgfs_dir); 6608c2ecf20Sopenharmony_ci 6618c2ecf20Sopenharmony_ci mvm->init_status = 0; 6628c2ecf20Sopenharmony_ci 6638c2ecf20Sopenharmony_ci if (iwl_mvm_has_new_rx_api(mvm)) { 6648c2ecf20Sopenharmony_ci op_mode->ops = &iwl_mvm_ops_mq; 6658c2ecf20Sopenharmony_ci trans->rx_mpdu_cmd_hdr_size = 6668c2ecf20Sopenharmony_ci (trans->trans_cfg->device_family >= 6678c2ecf20Sopenharmony_ci IWL_DEVICE_FAMILY_AX210) ? 6688c2ecf20Sopenharmony_ci sizeof(struct iwl_rx_mpdu_desc) : 6698c2ecf20Sopenharmony_ci IWL_RX_DESC_SIZE_V1; 6708c2ecf20Sopenharmony_ci } else { 6718c2ecf20Sopenharmony_ci op_mode->ops = &iwl_mvm_ops; 6728c2ecf20Sopenharmony_ci trans->rx_mpdu_cmd_hdr_size = 6738c2ecf20Sopenharmony_ci sizeof(struct iwl_rx_mpdu_res_start); 6748c2ecf20Sopenharmony_ci 6758c2ecf20Sopenharmony_ci if (WARN_ON(trans->num_rx_queues > 1)) 6768c2ecf20Sopenharmony_ci goto out_free; 6778c2ecf20Sopenharmony_ci } 6788c2ecf20Sopenharmony_ci 6798c2ecf20Sopenharmony_ci mvm->fw_restart = iwlwifi_mod_params.fw_restart ? -1 : 0; 6808c2ecf20Sopenharmony_ci 6818c2ecf20Sopenharmony_ci if (iwl_mvm_has_new_tx_api(mvm)) { 6828c2ecf20Sopenharmony_ci /* 6838c2ecf20Sopenharmony_ci * If we have the new TX/queue allocation API initialize them 6848c2ecf20Sopenharmony_ci * all to invalid numbers. We'll rewrite the ones that we need 6858c2ecf20Sopenharmony_ci * later, but that doesn't happen for all of them all of the 6868c2ecf20Sopenharmony_ci * time (e.g. P2P Device is optional), and if a dynamic queue 6878c2ecf20Sopenharmony_ci * ends up getting number 2 (IWL_MVM_DQA_P2P_DEVICE_QUEUE) then 6888c2ecf20Sopenharmony_ci * iwl_mvm_is_static_queue() erroneously returns true, and we 6898c2ecf20Sopenharmony_ci * might have things getting stuck. 6908c2ecf20Sopenharmony_ci */ 6918c2ecf20Sopenharmony_ci mvm->aux_queue = IWL_MVM_INVALID_QUEUE; 6928c2ecf20Sopenharmony_ci mvm->snif_queue = IWL_MVM_INVALID_QUEUE; 6938c2ecf20Sopenharmony_ci mvm->probe_queue = IWL_MVM_INVALID_QUEUE; 6948c2ecf20Sopenharmony_ci mvm->p2p_dev_queue = IWL_MVM_INVALID_QUEUE; 6958c2ecf20Sopenharmony_ci } else { 6968c2ecf20Sopenharmony_ci mvm->aux_queue = IWL_MVM_DQA_AUX_QUEUE; 6978c2ecf20Sopenharmony_ci mvm->snif_queue = IWL_MVM_DQA_INJECT_MONITOR_QUEUE; 6988c2ecf20Sopenharmony_ci mvm->probe_queue = IWL_MVM_DQA_AP_PROBE_RESP_QUEUE; 6998c2ecf20Sopenharmony_ci mvm->p2p_dev_queue = IWL_MVM_DQA_P2P_DEVICE_QUEUE; 7008c2ecf20Sopenharmony_ci } 7018c2ecf20Sopenharmony_ci 7028c2ecf20Sopenharmony_ci mvm->sf_state = SF_UNINIT; 7038c2ecf20Sopenharmony_ci if (iwl_mvm_has_unified_ucode(mvm)) 7048c2ecf20Sopenharmony_ci iwl_fw_set_current_image(&mvm->fwrt, IWL_UCODE_REGULAR); 7058c2ecf20Sopenharmony_ci else 7068c2ecf20Sopenharmony_ci iwl_fw_set_current_image(&mvm->fwrt, IWL_UCODE_INIT); 7078c2ecf20Sopenharmony_ci mvm->drop_bcn_ap_mode = true; 7088c2ecf20Sopenharmony_ci 7098c2ecf20Sopenharmony_ci mutex_init(&mvm->mutex); 7108c2ecf20Sopenharmony_ci spin_lock_init(&mvm->async_handlers_lock); 7118c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&mvm->time_event_list); 7128c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&mvm->aux_roc_te_list); 7138c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&mvm->async_handlers_list); 7148c2ecf20Sopenharmony_ci spin_lock_init(&mvm->time_event_lock); 7158c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&mvm->ftm_initiator.loc_list); 7168c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&mvm->ftm_initiator.pasn_list); 7178c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&mvm->resp_pasn_list); 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_ci INIT_WORK(&mvm->async_handlers_wk, iwl_mvm_async_handlers_wk); 7208c2ecf20Sopenharmony_ci INIT_WORK(&mvm->roc_done_wk, iwl_mvm_roc_done_wk); 7218c2ecf20Sopenharmony_ci INIT_DELAYED_WORK(&mvm->tdls_cs.dwork, iwl_mvm_tdls_ch_switch_work); 7228c2ecf20Sopenharmony_ci INIT_DELAYED_WORK(&mvm->scan_timeout_dwork, iwl_mvm_scan_timeout_wk); 7238c2ecf20Sopenharmony_ci INIT_WORK(&mvm->add_stream_wk, iwl_mvm_add_new_dqa_stream_wk); 7248c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&mvm->add_stream_txqs); 7258c2ecf20Sopenharmony_ci 7268c2ecf20Sopenharmony_ci init_waitqueue_head(&mvm->rx_sync_waitq); 7278c2ecf20Sopenharmony_ci 7288c2ecf20Sopenharmony_ci atomic_set(&mvm->queue_sync_counter, 0); 7298c2ecf20Sopenharmony_ci 7308c2ecf20Sopenharmony_ci SET_IEEE80211_DEV(mvm->hw, mvm->trans->dev); 7318c2ecf20Sopenharmony_ci 7328c2ecf20Sopenharmony_ci spin_lock_init(&mvm->tcm.lock); 7338c2ecf20Sopenharmony_ci INIT_DELAYED_WORK(&mvm->tcm.work, iwl_mvm_tcm_work); 7348c2ecf20Sopenharmony_ci mvm->tcm.ts = jiffies; 7358c2ecf20Sopenharmony_ci mvm->tcm.ll_ts = jiffies; 7368c2ecf20Sopenharmony_ci mvm->tcm.uapsd_nonagg_ts = jiffies; 7378c2ecf20Sopenharmony_ci 7388c2ecf20Sopenharmony_ci INIT_DELAYED_WORK(&mvm->cs_tx_unblock_dwork, iwl_mvm_tx_unblock_dwork); 7398c2ecf20Sopenharmony_ci 7408c2ecf20Sopenharmony_ci mvm->cmd_ver.d0i3_resp = 7418c2ecf20Sopenharmony_ci iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP, D0I3_END_CMD, 7428c2ecf20Sopenharmony_ci 0); 7438c2ecf20Sopenharmony_ci /* we only support version 1 */ 7448c2ecf20Sopenharmony_ci if (WARN_ON_ONCE(mvm->cmd_ver.d0i3_resp > 1)) 7458c2ecf20Sopenharmony_ci goto out_free; 7468c2ecf20Sopenharmony_ci 7478c2ecf20Sopenharmony_ci mvm->cmd_ver.range_resp = 7488c2ecf20Sopenharmony_ci iwl_fw_lookup_notif_ver(mvm->fw, LOCATION_GROUP, 7498c2ecf20Sopenharmony_ci TOF_RANGE_RESPONSE_NOTIF, 5); 7508c2ecf20Sopenharmony_ci /* we only support up to version 8 */ 7518c2ecf20Sopenharmony_ci if (WARN_ON_ONCE(mvm->cmd_ver.range_resp > 8)) 7528c2ecf20Sopenharmony_ci goto out_free; 7538c2ecf20Sopenharmony_ci 7548c2ecf20Sopenharmony_ci /* 7558c2ecf20Sopenharmony_ci * Populate the state variables that the transport layer needs 7568c2ecf20Sopenharmony_ci * to know about. 7578c2ecf20Sopenharmony_ci */ 7588c2ecf20Sopenharmony_ci trans_cfg.op_mode = op_mode; 7598c2ecf20Sopenharmony_ci trans_cfg.no_reclaim_cmds = no_reclaim_cmds; 7608c2ecf20Sopenharmony_ci trans_cfg.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds); 7618c2ecf20Sopenharmony_ci 7628c2ecf20Sopenharmony_ci if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) 7638c2ecf20Sopenharmony_ci rb_size_default = IWL_AMSDU_2K; 7648c2ecf20Sopenharmony_ci else 7658c2ecf20Sopenharmony_ci rb_size_default = IWL_AMSDU_4K; 7668c2ecf20Sopenharmony_ci 7678c2ecf20Sopenharmony_ci switch (iwlwifi_mod_params.amsdu_size) { 7688c2ecf20Sopenharmony_ci case IWL_AMSDU_DEF: 7698c2ecf20Sopenharmony_ci trans_cfg.rx_buf_size = rb_size_default; 7708c2ecf20Sopenharmony_ci break; 7718c2ecf20Sopenharmony_ci case IWL_AMSDU_4K: 7728c2ecf20Sopenharmony_ci trans_cfg.rx_buf_size = IWL_AMSDU_4K; 7738c2ecf20Sopenharmony_ci break; 7748c2ecf20Sopenharmony_ci case IWL_AMSDU_8K: 7758c2ecf20Sopenharmony_ci trans_cfg.rx_buf_size = IWL_AMSDU_8K; 7768c2ecf20Sopenharmony_ci break; 7778c2ecf20Sopenharmony_ci case IWL_AMSDU_12K: 7788c2ecf20Sopenharmony_ci trans_cfg.rx_buf_size = IWL_AMSDU_12K; 7798c2ecf20Sopenharmony_ci break; 7808c2ecf20Sopenharmony_ci default: 7818c2ecf20Sopenharmony_ci pr_err("%s: Unsupported amsdu_size: %d\n", KBUILD_MODNAME, 7828c2ecf20Sopenharmony_ci iwlwifi_mod_params.amsdu_size); 7838c2ecf20Sopenharmony_ci trans_cfg.rx_buf_size = rb_size_default; 7848c2ecf20Sopenharmony_ci } 7858c2ecf20Sopenharmony_ci 7868c2ecf20Sopenharmony_ci trans->wide_cmd_header = true; 7878c2ecf20Sopenharmony_ci trans_cfg.bc_table_dword = 7888c2ecf20Sopenharmony_ci mvm->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210; 7898c2ecf20Sopenharmony_ci 7908c2ecf20Sopenharmony_ci trans_cfg.command_groups = iwl_mvm_groups; 7918c2ecf20Sopenharmony_ci trans_cfg.command_groups_size = ARRAY_SIZE(iwl_mvm_groups); 7928c2ecf20Sopenharmony_ci 7938c2ecf20Sopenharmony_ci trans_cfg.cmd_queue = IWL_MVM_DQA_CMD_QUEUE; 7948c2ecf20Sopenharmony_ci trans_cfg.cmd_fifo = IWL_MVM_TX_FIFO_CMD; 7958c2ecf20Sopenharmony_ci trans_cfg.scd_set_active = true; 7968c2ecf20Sopenharmony_ci 7978c2ecf20Sopenharmony_ci trans_cfg.cb_data_offs = offsetof(struct ieee80211_tx_info, 7988c2ecf20Sopenharmony_ci driver_data[2]); 7998c2ecf20Sopenharmony_ci 8008c2ecf20Sopenharmony_ci trans_cfg.sw_csum_tx = IWL_MVM_SW_TX_CSUM_OFFLOAD; 8018c2ecf20Sopenharmony_ci 8028c2ecf20Sopenharmony_ci /* Set a short watchdog for the command queue */ 8038c2ecf20Sopenharmony_ci trans_cfg.cmd_q_wdg_timeout = 8048c2ecf20Sopenharmony_ci iwl_mvm_get_wd_timeout(mvm, NULL, false, true); 8058c2ecf20Sopenharmony_ci 8068c2ecf20Sopenharmony_ci snprintf(mvm->hw->wiphy->fw_version, 8078c2ecf20Sopenharmony_ci sizeof(mvm->hw->wiphy->fw_version), 8088c2ecf20Sopenharmony_ci "%s", fw->fw_version); 8098c2ecf20Sopenharmony_ci 8108c2ecf20Sopenharmony_ci /* Configure transport layer */ 8118c2ecf20Sopenharmony_ci iwl_trans_configure(mvm->trans, &trans_cfg); 8128c2ecf20Sopenharmony_ci 8138c2ecf20Sopenharmony_ci trans->rx_mpdu_cmd = REPLY_RX_MPDU_CMD; 8148c2ecf20Sopenharmony_ci trans->dbg.dest_tlv = mvm->fw->dbg.dest_tlv; 8158c2ecf20Sopenharmony_ci trans->dbg.n_dest_reg = mvm->fw->dbg.n_dest_reg; 8168c2ecf20Sopenharmony_ci memcpy(trans->dbg.conf_tlv, mvm->fw->dbg.conf_tlv, 8178c2ecf20Sopenharmony_ci sizeof(trans->dbg.conf_tlv)); 8188c2ecf20Sopenharmony_ci trans->dbg.trigger_tlv = mvm->fw->dbg.trigger_tlv; 8198c2ecf20Sopenharmony_ci 8208c2ecf20Sopenharmony_ci trans->iml = mvm->fw->iml; 8218c2ecf20Sopenharmony_ci trans->iml_len = mvm->fw->iml_len; 8228c2ecf20Sopenharmony_ci 8238c2ecf20Sopenharmony_ci /* set up notification wait support */ 8248c2ecf20Sopenharmony_ci iwl_notification_wait_init(&mvm->notif_wait); 8258c2ecf20Sopenharmony_ci 8268c2ecf20Sopenharmony_ci /* Init phy db */ 8278c2ecf20Sopenharmony_ci mvm->phy_db = iwl_phy_db_init(trans); 8288c2ecf20Sopenharmony_ci if (!mvm->phy_db) { 8298c2ecf20Sopenharmony_ci IWL_ERR(mvm, "Cannot init phy_db\n"); 8308c2ecf20Sopenharmony_ci goto out_free; 8318c2ecf20Sopenharmony_ci } 8328c2ecf20Sopenharmony_ci 8338c2ecf20Sopenharmony_ci IWL_INFO(mvm, "Detected %s, REV=0x%X\n", 8348c2ecf20Sopenharmony_ci mvm->trans->name, mvm->trans->hw_rev); 8358c2ecf20Sopenharmony_ci 8368c2ecf20Sopenharmony_ci if (iwlwifi_mod_params.nvm_file) 8378c2ecf20Sopenharmony_ci mvm->nvm_file_name = iwlwifi_mod_params.nvm_file; 8388c2ecf20Sopenharmony_ci else 8398c2ecf20Sopenharmony_ci IWL_DEBUG_EEPROM(mvm->trans->dev, 8408c2ecf20Sopenharmony_ci "working without external nvm file\n"); 8418c2ecf20Sopenharmony_ci 8428c2ecf20Sopenharmony_ci err = iwl_trans_start_hw(mvm->trans); 8438c2ecf20Sopenharmony_ci if (err) 8448c2ecf20Sopenharmony_ci goto out_free; 8458c2ecf20Sopenharmony_ci 8468c2ecf20Sopenharmony_ci mutex_lock(&mvm->mutex); 8478c2ecf20Sopenharmony_ci err = iwl_run_init_mvm_ucode(mvm, true); 8488c2ecf20Sopenharmony_ci if (err && err != -ERFKILL) 8498c2ecf20Sopenharmony_ci iwl_fw_dbg_error_collect(&mvm->fwrt, FW_DBG_TRIGGER_DRIVER); 8508c2ecf20Sopenharmony_ci if (!iwlmvm_mod_params.init_dbg || !err) 8518c2ecf20Sopenharmony_ci iwl_mvm_stop_device(mvm); 8528c2ecf20Sopenharmony_ci mutex_unlock(&mvm->mutex); 8538c2ecf20Sopenharmony_ci if (err < 0) { 8548c2ecf20Sopenharmony_ci IWL_ERR(mvm, "Failed to run INIT ucode: %d\n", err); 8558c2ecf20Sopenharmony_ci goto out_free; 8568c2ecf20Sopenharmony_ci } 8578c2ecf20Sopenharmony_ci 8588c2ecf20Sopenharmony_ci scan_size = iwl_mvm_scan_size(mvm); 8598c2ecf20Sopenharmony_ci 8608c2ecf20Sopenharmony_ci mvm->scan_cmd = kmalloc(scan_size, GFP_KERNEL); 8618c2ecf20Sopenharmony_ci if (!mvm->scan_cmd) 8628c2ecf20Sopenharmony_ci goto out_free; 8638c2ecf20Sopenharmony_ci 8648c2ecf20Sopenharmony_ci /* invalidate ids to prevent accidental removal of sta_id 0 */ 8658c2ecf20Sopenharmony_ci mvm->aux_sta.sta_id = IWL_MVM_INVALID_STA; 8668c2ecf20Sopenharmony_ci mvm->snif_sta.sta_id = IWL_MVM_INVALID_STA; 8678c2ecf20Sopenharmony_ci 8688c2ecf20Sopenharmony_ci /* Set EBS as successful as long as not stated otherwise by the FW. */ 8698c2ecf20Sopenharmony_ci mvm->last_ebs_successful = true; 8708c2ecf20Sopenharmony_ci 8718c2ecf20Sopenharmony_ci err = iwl_mvm_mac_setup_register(mvm); 8728c2ecf20Sopenharmony_ci if (err) 8738c2ecf20Sopenharmony_ci goto out_free; 8748c2ecf20Sopenharmony_ci mvm->hw_registered = true; 8758c2ecf20Sopenharmony_ci 8768c2ecf20Sopenharmony_ci min_backoff = iwl_mvm_min_backoff(mvm); 8778c2ecf20Sopenharmony_ci iwl_mvm_thermal_initialize(mvm, min_backoff); 8788c2ecf20Sopenharmony_ci 8798c2ecf20Sopenharmony_ci iwl_mvm_dbgfs_register(mvm, dbgfs_dir); 8808c2ecf20Sopenharmony_ci 8818c2ecf20Sopenharmony_ci if (!iwl_mvm_has_new_rx_stats_api(mvm)) 8828c2ecf20Sopenharmony_ci memset(&mvm->rx_stats_v3, 0, 8838c2ecf20Sopenharmony_ci sizeof(struct mvm_statistics_rx_v3)); 8848c2ecf20Sopenharmony_ci else 8858c2ecf20Sopenharmony_ci memset(&mvm->rx_stats, 0, sizeof(struct mvm_statistics_rx)); 8868c2ecf20Sopenharmony_ci 8878c2ecf20Sopenharmony_ci iwl_mvm_toggle_tx_ant(mvm, &mvm->mgmt_last_antenna_idx); 8888c2ecf20Sopenharmony_ci 8898c2ecf20Sopenharmony_ci return op_mode; 8908c2ecf20Sopenharmony_ci 8918c2ecf20Sopenharmony_ci out_free: 8928c2ecf20Sopenharmony_ci iwl_fw_flush_dumps(&mvm->fwrt); 8938c2ecf20Sopenharmony_ci iwl_fw_runtime_free(&mvm->fwrt); 8948c2ecf20Sopenharmony_ci 8958c2ecf20Sopenharmony_ci if (iwlmvm_mod_params.init_dbg) 8968c2ecf20Sopenharmony_ci return op_mode; 8978c2ecf20Sopenharmony_ci iwl_phy_db_free(mvm->phy_db); 8988c2ecf20Sopenharmony_ci kfree(mvm->scan_cmd); 8998c2ecf20Sopenharmony_ci iwl_trans_op_mode_leave(trans); 9008c2ecf20Sopenharmony_ci 9018c2ecf20Sopenharmony_ci ieee80211_free_hw(mvm->hw); 9028c2ecf20Sopenharmony_ci return NULL; 9038c2ecf20Sopenharmony_ci} 9048c2ecf20Sopenharmony_ci 9058c2ecf20Sopenharmony_cistatic void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode) 9068c2ecf20Sopenharmony_ci{ 9078c2ecf20Sopenharmony_ci struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); 9088c2ecf20Sopenharmony_ci int i; 9098c2ecf20Sopenharmony_ci 9108c2ecf20Sopenharmony_ci iwl_mvm_leds_exit(mvm); 9118c2ecf20Sopenharmony_ci 9128c2ecf20Sopenharmony_ci iwl_mvm_thermal_exit(mvm); 9138c2ecf20Sopenharmony_ci 9148c2ecf20Sopenharmony_ci ieee80211_unregister_hw(mvm->hw); 9158c2ecf20Sopenharmony_ci 9168c2ecf20Sopenharmony_ci kfree(mvm->scan_cmd); 9178c2ecf20Sopenharmony_ci kfree(mvm->mcast_filter_cmd); 9188c2ecf20Sopenharmony_ci mvm->mcast_filter_cmd = NULL; 9198c2ecf20Sopenharmony_ci 9208c2ecf20Sopenharmony_ci kfree(mvm->error_recovery_buf); 9218c2ecf20Sopenharmony_ci mvm->error_recovery_buf = NULL; 9228c2ecf20Sopenharmony_ci 9238c2ecf20Sopenharmony_ci iwl_trans_op_mode_leave(mvm->trans); 9248c2ecf20Sopenharmony_ci 9258c2ecf20Sopenharmony_ci iwl_phy_db_free(mvm->phy_db); 9268c2ecf20Sopenharmony_ci mvm->phy_db = NULL; 9278c2ecf20Sopenharmony_ci 9288c2ecf20Sopenharmony_ci kfree(mvm->nvm_data); 9298c2ecf20Sopenharmony_ci for (i = 0; i < NVM_MAX_NUM_SECTIONS; i++) 9308c2ecf20Sopenharmony_ci kfree(mvm->nvm_sections[i].data); 9318c2ecf20Sopenharmony_ci 9328c2ecf20Sopenharmony_ci cancel_delayed_work_sync(&mvm->tcm.work); 9338c2ecf20Sopenharmony_ci 9348c2ecf20Sopenharmony_ci iwl_fw_runtime_free(&mvm->fwrt); 9358c2ecf20Sopenharmony_ci mutex_destroy(&mvm->mutex); 9368c2ecf20Sopenharmony_ci 9378c2ecf20Sopenharmony_ci ieee80211_free_hw(mvm->hw); 9388c2ecf20Sopenharmony_ci} 9398c2ecf20Sopenharmony_ci 9408c2ecf20Sopenharmony_cistruct iwl_async_handler_entry { 9418c2ecf20Sopenharmony_ci struct list_head list; 9428c2ecf20Sopenharmony_ci struct iwl_rx_cmd_buffer rxb; 9438c2ecf20Sopenharmony_ci enum iwl_rx_handler_context context; 9448c2ecf20Sopenharmony_ci void (*fn)(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb); 9458c2ecf20Sopenharmony_ci}; 9468c2ecf20Sopenharmony_ci 9478c2ecf20Sopenharmony_civoid iwl_mvm_async_handlers_purge(struct iwl_mvm *mvm) 9488c2ecf20Sopenharmony_ci{ 9498c2ecf20Sopenharmony_ci struct iwl_async_handler_entry *entry, *tmp; 9508c2ecf20Sopenharmony_ci 9518c2ecf20Sopenharmony_ci spin_lock_bh(&mvm->async_handlers_lock); 9528c2ecf20Sopenharmony_ci list_for_each_entry_safe(entry, tmp, &mvm->async_handlers_list, list) { 9538c2ecf20Sopenharmony_ci iwl_free_rxb(&entry->rxb); 9548c2ecf20Sopenharmony_ci list_del(&entry->list); 9558c2ecf20Sopenharmony_ci kfree(entry); 9568c2ecf20Sopenharmony_ci } 9578c2ecf20Sopenharmony_ci spin_unlock_bh(&mvm->async_handlers_lock); 9588c2ecf20Sopenharmony_ci} 9598c2ecf20Sopenharmony_ci 9608c2ecf20Sopenharmony_cistatic void iwl_mvm_async_handlers_wk(struct work_struct *wk) 9618c2ecf20Sopenharmony_ci{ 9628c2ecf20Sopenharmony_ci struct iwl_mvm *mvm = 9638c2ecf20Sopenharmony_ci container_of(wk, struct iwl_mvm, async_handlers_wk); 9648c2ecf20Sopenharmony_ci struct iwl_async_handler_entry *entry, *tmp; 9658c2ecf20Sopenharmony_ci LIST_HEAD(local_list); 9668c2ecf20Sopenharmony_ci 9678c2ecf20Sopenharmony_ci /* Ensure that we are not in stop flow (check iwl_mvm_mac_stop) */ 9688c2ecf20Sopenharmony_ci 9698c2ecf20Sopenharmony_ci /* 9708c2ecf20Sopenharmony_ci * Sync with Rx path with a lock. Remove all the entries from this list, 9718c2ecf20Sopenharmony_ci * add them to a local one (lock free), and then handle them. 9728c2ecf20Sopenharmony_ci */ 9738c2ecf20Sopenharmony_ci spin_lock_bh(&mvm->async_handlers_lock); 9748c2ecf20Sopenharmony_ci list_splice_init(&mvm->async_handlers_list, &local_list); 9758c2ecf20Sopenharmony_ci spin_unlock_bh(&mvm->async_handlers_lock); 9768c2ecf20Sopenharmony_ci 9778c2ecf20Sopenharmony_ci list_for_each_entry_safe(entry, tmp, &local_list, list) { 9788c2ecf20Sopenharmony_ci if (entry->context == RX_HANDLER_ASYNC_LOCKED) 9798c2ecf20Sopenharmony_ci mutex_lock(&mvm->mutex); 9808c2ecf20Sopenharmony_ci entry->fn(mvm, &entry->rxb); 9818c2ecf20Sopenharmony_ci iwl_free_rxb(&entry->rxb); 9828c2ecf20Sopenharmony_ci list_del(&entry->list); 9838c2ecf20Sopenharmony_ci if (entry->context == RX_HANDLER_ASYNC_LOCKED) 9848c2ecf20Sopenharmony_ci mutex_unlock(&mvm->mutex); 9858c2ecf20Sopenharmony_ci kfree(entry); 9868c2ecf20Sopenharmony_ci } 9878c2ecf20Sopenharmony_ci} 9888c2ecf20Sopenharmony_ci 9898c2ecf20Sopenharmony_cistatic inline void iwl_mvm_rx_check_trigger(struct iwl_mvm *mvm, 9908c2ecf20Sopenharmony_ci struct iwl_rx_packet *pkt) 9918c2ecf20Sopenharmony_ci{ 9928c2ecf20Sopenharmony_ci struct iwl_fw_dbg_trigger_tlv *trig; 9938c2ecf20Sopenharmony_ci struct iwl_fw_dbg_trigger_cmd *cmds_trig; 9948c2ecf20Sopenharmony_ci int i; 9958c2ecf20Sopenharmony_ci 9968c2ecf20Sopenharmony_ci trig = iwl_fw_dbg_trigger_on(&mvm->fwrt, NULL, 9978c2ecf20Sopenharmony_ci FW_DBG_TRIGGER_FW_NOTIF); 9988c2ecf20Sopenharmony_ci if (!trig) 9998c2ecf20Sopenharmony_ci return; 10008c2ecf20Sopenharmony_ci 10018c2ecf20Sopenharmony_ci cmds_trig = (void *)trig->data; 10028c2ecf20Sopenharmony_ci 10038c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(cmds_trig->cmds); i++) { 10048c2ecf20Sopenharmony_ci /* don't collect on CMD 0 */ 10058c2ecf20Sopenharmony_ci if (!cmds_trig->cmds[i].cmd_id) 10068c2ecf20Sopenharmony_ci break; 10078c2ecf20Sopenharmony_ci 10088c2ecf20Sopenharmony_ci if (cmds_trig->cmds[i].cmd_id != pkt->hdr.cmd || 10098c2ecf20Sopenharmony_ci cmds_trig->cmds[i].group_id != pkt->hdr.group_id) 10108c2ecf20Sopenharmony_ci continue; 10118c2ecf20Sopenharmony_ci 10128c2ecf20Sopenharmony_ci iwl_fw_dbg_collect_trig(&mvm->fwrt, trig, 10138c2ecf20Sopenharmony_ci "CMD 0x%02x.%02x received", 10148c2ecf20Sopenharmony_ci pkt->hdr.group_id, pkt->hdr.cmd); 10158c2ecf20Sopenharmony_ci break; 10168c2ecf20Sopenharmony_ci } 10178c2ecf20Sopenharmony_ci} 10188c2ecf20Sopenharmony_ci 10198c2ecf20Sopenharmony_cistatic void iwl_mvm_rx_common(struct iwl_mvm *mvm, 10208c2ecf20Sopenharmony_ci struct iwl_rx_cmd_buffer *rxb, 10218c2ecf20Sopenharmony_ci struct iwl_rx_packet *pkt) 10228c2ecf20Sopenharmony_ci{ 10238c2ecf20Sopenharmony_ci int i; 10248c2ecf20Sopenharmony_ci union iwl_dbg_tlv_tp_data tp_data = { .fw_pkt = pkt }; 10258c2ecf20Sopenharmony_ci 10268c2ecf20Sopenharmony_ci iwl_dbg_tlv_time_point(&mvm->fwrt, 10278c2ecf20Sopenharmony_ci IWL_FW_INI_TIME_POINT_FW_RSP_OR_NOTIF, &tp_data); 10288c2ecf20Sopenharmony_ci iwl_mvm_rx_check_trigger(mvm, pkt); 10298c2ecf20Sopenharmony_ci 10308c2ecf20Sopenharmony_ci /* 10318c2ecf20Sopenharmony_ci * Do the notification wait before RX handlers so 10328c2ecf20Sopenharmony_ci * even if the RX handler consumes the RXB we have 10338c2ecf20Sopenharmony_ci * access to it in the notification wait entry. 10348c2ecf20Sopenharmony_ci */ 10358c2ecf20Sopenharmony_ci iwl_notification_wait_notify(&mvm->notif_wait, pkt); 10368c2ecf20Sopenharmony_ci 10378c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(iwl_mvm_rx_handlers); i++) { 10388c2ecf20Sopenharmony_ci const struct iwl_rx_handlers *rx_h = &iwl_mvm_rx_handlers[i]; 10398c2ecf20Sopenharmony_ci struct iwl_async_handler_entry *entry; 10408c2ecf20Sopenharmony_ci 10418c2ecf20Sopenharmony_ci if (rx_h->cmd_id != WIDE_ID(pkt->hdr.group_id, pkt->hdr.cmd)) 10428c2ecf20Sopenharmony_ci continue; 10438c2ecf20Sopenharmony_ci 10448c2ecf20Sopenharmony_ci if (rx_h->context == RX_HANDLER_SYNC) { 10458c2ecf20Sopenharmony_ci rx_h->fn(mvm, rxb); 10468c2ecf20Sopenharmony_ci return; 10478c2ecf20Sopenharmony_ci } 10488c2ecf20Sopenharmony_ci 10498c2ecf20Sopenharmony_ci entry = kzalloc(sizeof(*entry), GFP_ATOMIC); 10508c2ecf20Sopenharmony_ci /* we can't do much... */ 10518c2ecf20Sopenharmony_ci if (!entry) 10528c2ecf20Sopenharmony_ci return; 10538c2ecf20Sopenharmony_ci 10548c2ecf20Sopenharmony_ci entry->rxb._page = rxb_steal_page(rxb); 10558c2ecf20Sopenharmony_ci entry->rxb._offset = rxb->_offset; 10568c2ecf20Sopenharmony_ci entry->rxb._rx_page_order = rxb->_rx_page_order; 10578c2ecf20Sopenharmony_ci entry->fn = rx_h->fn; 10588c2ecf20Sopenharmony_ci entry->context = rx_h->context; 10598c2ecf20Sopenharmony_ci spin_lock(&mvm->async_handlers_lock); 10608c2ecf20Sopenharmony_ci list_add_tail(&entry->list, &mvm->async_handlers_list); 10618c2ecf20Sopenharmony_ci spin_unlock(&mvm->async_handlers_lock); 10628c2ecf20Sopenharmony_ci schedule_work(&mvm->async_handlers_wk); 10638c2ecf20Sopenharmony_ci break; 10648c2ecf20Sopenharmony_ci } 10658c2ecf20Sopenharmony_ci} 10668c2ecf20Sopenharmony_ci 10678c2ecf20Sopenharmony_cistatic void iwl_mvm_rx(struct iwl_op_mode *op_mode, 10688c2ecf20Sopenharmony_ci struct napi_struct *napi, 10698c2ecf20Sopenharmony_ci struct iwl_rx_cmd_buffer *rxb) 10708c2ecf20Sopenharmony_ci{ 10718c2ecf20Sopenharmony_ci struct iwl_rx_packet *pkt = rxb_addr(rxb); 10728c2ecf20Sopenharmony_ci struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); 10738c2ecf20Sopenharmony_ci u16 cmd = WIDE_ID(pkt->hdr.group_id, pkt->hdr.cmd); 10748c2ecf20Sopenharmony_ci 10758c2ecf20Sopenharmony_ci if (likely(cmd == WIDE_ID(LEGACY_GROUP, REPLY_RX_MPDU_CMD))) 10768c2ecf20Sopenharmony_ci iwl_mvm_rx_rx_mpdu(mvm, napi, rxb); 10778c2ecf20Sopenharmony_ci else if (cmd == WIDE_ID(LEGACY_GROUP, REPLY_RX_PHY_CMD)) 10788c2ecf20Sopenharmony_ci iwl_mvm_rx_rx_phy_cmd(mvm, rxb); 10798c2ecf20Sopenharmony_ci else 10808c2ecf20Sopenharmony_ci iwl_mvm_rx_common(mvm, rxb, pkt); 10818c2ecf20Sopenharmony_ci} 10828c2ecf20Sopenharmony_ci 10838c2ecf20Sopenharmony_cistatic void iwl_mvm_rx_mq(struct iwl_op_mode *op_mode, 10848c2ecf20Sopenharmony_ci struct napi_struct *napi, 10858c2ecf20Sopenharmony_ci struct iwl_rx_cmd_buffer *rxb) 10868c2ecf20Sopenharmony_ci{ 10878c2ecf20Sopenharmony_ci struct iwl_rx_packet *pkt = rxb_addr(rxb); 10888c2ecf20Sopenharmony_ci struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); 10898c2ecf20Sopenharmony_ci u16 cmd = WIDE_ID(pkt->hdr.group_id, pkt->hdr.cmd); 10908c2ecf20Sopenharmony_ci 10918c2ecf20Sopenharmony_ci if (likely(cmd == WIDE_ID(LEGACY_GROUP, REPLY_RX_MPDU_CMD))) 10928c2ecf20Sopenharmony_ci iwl_mvm_rx_mpdu_mq(mvm, napi, rxb, 0); 10938c2ecf20Sopenharmony_ci else if (unlikely(cmd == WIDE_ID(DATA_PATH_GROUP, 10948c2ecf20Sopenharmony_ci RX_QUEUES_NOTIFICATION))) 10958c2ecf20Sopenharmony_ci iwl_mvm_rx_queue_notif(mvm, napi, rxb, 0); 10968c2ecf20Sopenharmony_ci else if (cmd == WIDE_ID(LEGACY_GROUP, FRAME_RELEASE)) 10978c2ecf20Sopenharmony_ci iwl_mvm_rx_frame_release(mvm, napi, rxb, 0); 10988c2ecf20Sopenharmony_ci else if (cmd == WIDE_ID(LEGACY_GROUP, BAR_FRAME_RELEASE)) 10998c2ecf20Sopenharmony_ci iwl_mvm_rx_bar_frame_release(mvm, napi, rxb, 0); 11008c2ecf20Sopenharmony_ci else if (cmd == WIDE_ID(DATA_PATH_GROUP, RX_NO_DATA_NOTIF)) 11018c2ecf20Sopenharmony_ci iwl_mvm_rx_monitor_no_data(mvm, napi, rxb, 0); 11028c2ecf20Sopenharmony_ci else 11038c2ecf20Sopenharmony_ci iwl_mvm_rx_common(mvm, rxb, pkt); 11048c2ecf20Sopenharmony_ci} 11058c2ecf20Sopenharmony_ci 11068c2ecf20Sopenharmony_cistatic void iwl_mvm_async_cb(struct iwl_op_mode *op_mode, 11078c2ecf20Sopenharmony_ci const struct iwl_device_cmd *cmd) 11088c2ecf20Sopenharmony_ci{ 11098c2ecf20Sopenharmony_ci struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); 11108c2ecf20Sopenharmony_ci 11118c2ecf20Sopenharmony_ci /* 11128c2ecf20Sopenharmony_ci * For now, we only set the CMD_WANT_ASYNC_CALLBACK for ADD_STA 11138c2ecf20Sopenharmony_ci * commands that need to block the Tx queues. 11148c2ecf20Sopenharmony_ci */ 11158c2ecf20Sopenharmony_ci iwl_trans_block_txq_ptrs(mvm->trans, false); 11168c2ecf20Sopenharmony_ci} 11178c2ecf20Sopenharmony_ci 11188c2ecf20Sopenharmony_cistatic int iwl_mvm_is_static_queue(struct iwl_mvm *mvm, int queue) 11198c2ecf20Sopenharmony_ci{ 11208c2ecf20Sopenharmony_ci return queue == mvm->aux_queue || queue == mvm->probe_queue || 11218c2ecf20Sopenharmony_ci queue == mvm->p2p_dev_queue || queue == mvm->snif_queue; 11228c2ecf20Sopenharmony_ci} 11238c2ecf20Sopenharmony_ci 11248c2ecf20Sopenharmony_cistatic void iwl_mvm_queue_state_change(struct iwl_op_mode *op_mode, 11258c2ecf20Sopenharmony_ci int hw_queue, bool start) 11268c2ecf20Sopenharmony_ci{ 11278c2ecf20Sopenharmony_ci struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); 11288c2ecf20Sopenharmony_ci struct ieee80211_sta *sta; 11298c2ecf20Sopenharmony_ci struct ieee80211_txq *txq; 11308c2ecf20Sopenharmony_ci struct iwl_mvm_txq *mvmtxq; 11318c2ecf20Sopenharmony_ci int i; 11328c2ecf20Sopenharmony_ci unsigned long tid_bitmap; 11338c2ecf20Sopenharmony_ci struct iwl_mvm_sta *mvmsta; 11348c2ecf20Sopenharmony_ci u8 sta_id; 11358c2ecf20Sopenharmony_ci 11368c2ecf20Sopenharmony_ci sta_id = iwl_mvm_has_new_tx_api(mvm) ? 11378c2ecf20Sopenharmony_ci mvm->tvqm_info[hw_queue].sta_id : 11388c2ecf20Sopenharmony_ci mvm->queue_info[hw_queue].ra_sta_id; 11398c2ecf20Sopenharmony_ci 11408c2ecf20Sopenharmony_ci if (WARN_ON_ONCE(sta_id >= mvm->fw->ucode_capa.num_stations)) 11418c2ecf20Sopenharmony_ci return; 11428c2ecf20Sopenharmony_ci 11438c2ecf20Sopenharmony_ci rcu_read_lock(); 11448c2ecf20Sopenharmony_ci 11458c2ecf20Sopenharmony_ci sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]); 11468c2ecf20Sopenharmony_ci if (IS_ERR_OR_NULL(sta)) 11478c2ecf20Sopenharmony_ci goto out; 11488c2ecf20Sopenharmony_ci mvmsta = iwl_mvm_sta_from_mac80211(sta); 11498c2ecf20Sopenharmony_ci 11508c2ecf20Sopenharmony_ci if (iwl_mvm_is_static_queue(mvm, hw_queue)) { 11518c2ecf20Sopenharmony_ci if (!start) 11528c2ecf20Sopenharmony_ci ieee80211_stop_queues(mvm->hw); 11538c2ecf20Sopenharmony_ci else if (mvmsta->sta_state != IEEE80211_STA_NOTEXIST) 11548c2ecf20Sopenharmony_ci ieee80211_wake_queues(mvm->hw); 11558c2ecf20Sopenharmony_ci 11568c2ecf20Sopenharmony_ci goto out; 11578c2ecf20Sopenharmony_ci } 11588c2ecf20Sopenharmony_ci 11598c2ecf20Sopenharmony_ci if (iwl_mvm_has_new_tx_api(mvm)) { 11608c2ecf20Sopenharmony_ci int tid = mvm->tvqm_info[hw_queue].txq_tid; 11618c2ecf20Sopenharmony_ci 11628c2ecf20Sopenharmony_ci tid_bitmap = BIT(tid); 11638c2ecf20Sopenharmony_ci } else { 11648c2ecf20Sopenharmony_ci tid_bitmap = mvm->queue_info[hw_queue].tid_bitmap; 11658c2ecf20Sopenharmony_ci } 11668c2ecf20Sopenharmony_ci 11678c2ecf20Sopenharmony_ci for_each_set_bit(i, &tid_bitmap, IWL_MAX_TID_COUNT + 1) { 11688c2ecf20Sopenharmony_ci int tid = i; 11698c2ecf20Sopenharmony_ci 11708c2ecf20Sopenharmony_ci if (tid == IWL_MAX_TID_COUNT) 11718c2ecf20Sopenharmony_ci tid = IEEE80211_NUM_TIDS; 11728c2ecf20Sopenharmony_ci 11738c2ecf20Sopenharmony_ci txq = sta->txq[tid]; 11748c2ecf20Sopenharmony_ci mvmtxq = iwl_mvm_txq_from_mac80211(txq); 11758c2ecf20Sopenharmony_ci mvmtxq->stopped = !start; 11768c2ecf20Sopenharmony_ci 11778c2ecf20Sopenharmony_ci if (start && mvmsta->sta_state != IEEE80211_STA_NOTEXIST) { 11788c2ecf20Sopenharmony_ci local_bh_disable(); 11798c2ecf20Sopenharmony_ci iwl_mvm_mac_itxq_xmit(mvm->hw, txq); 11808c2ecf20Sopenharmony_ci local_bh_enable(); 11818c2ecf20Sopenharmony_ci } 11828c2ecf20Sopenharmony_ci } 11838c2ecf20Sopenharmony_ci 11848c2ecf20Sopenharmony_ciout: 11858c2ecf20Sopenharmony_ci rcu_read_unlock(); 11868c2ecf20Sopenharmony_ci} 11878c2ecf20Sopenharmony_ci 11888c2ecf20Sopenharmony_cistatic void iwl_mvm_stop_sw_queue(struct iwl_op_mode *op_mode, int hw_queue) 11898c2ecf20Sopenharmony_ci{ 11908c2ecf20Sopenharmony_ci iwl_mvm_queue_state_change(op_mode, hw_queue, false); 11918c2ecf20Sopenharmony_ci} 11928c2ecf20Sopenharmony_ci 11938c2ecf20Sopenharmony_cistatic void iwl_mvm_wake_sw_queue(struct iwl_op_mode *op_mode, int hw_queue) 11948c2ecf20Sopenharmony_ci{ 11958c2ecf20Sopenharmony_ci iwl_mvm_queue_state_change(op_mode, hw_queue, true); 11968c2ecf20Sopenharmony_ci} 11978c2ecf20Sopenharmony_ci 11988c2ecf20Sopenharmony_cistatic void iwl_mvm_set_rfkill_state(struct iwl_mvm *mvm) 11998c2ecf20Sopenharmony_ci{ 12008c2ecf20Sopenharmony_ci bool state = iwl_mvm_is_radio_killed(mvm); 12018c2ecf20Sopenharmony_ci 12028c2ecf20Sopenharmony_ci if (state) 12038c2ecf20Sopenharmony_ci wake_up(&mvm->rx_sync_waitq); 12048c2ecf20Sopenharmony_ci 12058c2ecf20Sopenharmony_ci wiphy_rfkill_set_hw_state(mvm->hw->wiphy, state); 12068c2ecf20Sopenharmony_ci} 12078c2ecf20Sopenharmony_ci 12088c2ecf20Sopenharmony_civoid iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state) 12098c2ecf20Sopenharmony_ci{ 12108c2ecf20Sopenharmony_ci if (state) 12118c2ecf20Sopenharmony_ci set_bit(IWL_MVM_STATUS_HW_CTKILL, &mvm->status); 12128c2ecf20Sopenharmony_ci else 12138c2ecf20Sopenharmony_ci clear_bit(IWL_MVM_STATUS_HW_CTKILL, &mvm->status); 12148c2ecf20Sopenharmony_ci 12158c2ecf20Sopenharmony_ci iwl_mvm_set_rfkill_state(mvm); 12168c2ecf20Sopenharmony_ci} 12178c2ecf20Sopenharmony_ci 12188c2ecf20Sopenharmony_cistatic bool iwl_mvm_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state) 12198c2ecf20Sopenharmony_ci{ 12208c2ecf20Sopenharmony_ci struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); 12218c2ecf20Sopenharmony_ci bool rfkill_safe_init_done = READ_ONCE(mvm->rfkill_safe_init_done); 12228c2ecf20Sopenharmony_ci bool unified = iwl_mvm_has_unified_ucode(mvm); 12238c2ecf20Sopenharmony_ci 12248c2ecf20Sopenharmony_ci if (state) 12258c2ecf20Sopenharmony_ci set_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status); 12268c2ecf20Sopenharmony_ci else 12278c2ecf20Sopenharmony_ci clear_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status); 12288c2ecf20Sopenharmony_ci 12298c2ecf20Sopenharmony_ci iwl_mvm_set_rfkill_state(mvm); 12308c2ecf20Sopenharmony_ci 12318c2ecf20Sopenharmony_ci /* iwl_run_init_mvm_ucode is waiting for results, abort it. */ 12328c2ecf20Sopenharmony_ci if (rfkill_safe_init_done) 12338c2ecf20Sopenharmony_ci iwl_abort_notification_waits(&mvm->notif_wait); 12348c2ecf20Sopenharmony_ci 12358c2ecf20Sopenharmony_ci /* 12368c2ecf20Sopenharmony_ci * Don't ask the transport to stop the firmware. We'll do it 12378c2ecf20Sopenharmony_ci * after cfg80211 takes us down. 12388c2ecf20Sopenharmony_ci */ 12398c2ecf20Sopenharmony_ci if (unified) 12408c2ecf20Sopenharmony_ci return false; 12418c2ecf20Sopenharmony_ci 12428c2ecf20Sopenharmony_ci /* 12438c2ecf20Sopenharmony_ci * Stop the device if we run OPERATIONAL firmware or if we are in the 12448c2ecf20Sopenharmony_ci * middle of the calibrations. 12458c2ecf20Sopenharmony_ci */ 12468c2ecf20Sopenharmony_ci return state && rfkill_safe_init_done; 12478c2ecf20Sopenharmony_ci} 12488c2ecf20Sopenharmony_ci 12498c2ecf20Sopenharmony_cistatic void iwl_mvm_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb) 12508c2ecf20Sopenharmony_ci{ 12518c2ecf20Sopenharmony_ci struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); 12528c2ecf20Sopenharmony_ci struct ieee80211_tx_info *info; 12538c2ecf20Sopenharmony_ci 12548c2ecf20Sopenharmony_ci info = IEEE80211_SKB_CB(skb); 12558c2ecf20Sopenharmony_ci iwl_trans_free_tx_cmd(mvm->trans, info->driver_data[1]); 12568c2ecf20Sopenharmony_ci ieee80211_free_txskb(mvm->hw, skb); 12578c2ecf20Sopenharmony_ci} 12588c2ecf20Sopenharmony_ci 12598c2ecf20Sopenharmony_cistruct iwl_mvm_reprobe { 12608c2ecf20Sopenharmony_ci struct device *dev; 12618c2ecf20Sopenharmony_ci struct work_struct work; 12628c2ecf20Sopenharmony_ci}; 12638c2ecf20Sopenharmony_ci 12648c2ecf20Sopenharmony_cistatic void iwl_mvm_reprobe_wk(struct work_struct *wk) 12658c2ecf20Sopenharmony_ci{ 12668c2ecf20Sopenharmony_ci struct iwl_mvm_reprobe *reprobe; 12678c2ecf20Sopenharmony_ci 12688c2ecf20Sopenharmony_ci reprobe = container_of(wk, struct iwl_mvm_reprobe, work); 12698c2ecf20Sopenharmony_ci if (device_reprobe(reprobe->dev)) 12708c2ecf20Sopenharmony_ci dev_err(reprobe->dev, "reprobe failed!\n"); 12718c2ecf20Sopenharmony_ci put_device(reprobe->dev); 12728c2ecf20Sopenharmony_ci kfree(reprobe); 12738c2ecf20Sopenharmony_ci module_put(THIS_MODULE); 12748c2ecf20Sopenharmony_ci} 12758c2ecf20Sopenharmony_ci 12768c2ecf20Sopenharmony_civoid iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error) 12778c2ecf20Sopenharmony_ci{ 12788c2ecf20Sopenharmony_ci iwl_abort_notification_waits(&mvm->notif_wait); 12798c2ecf20Sopenharmony_ci iwl_dbg_tlv_del_timers(mvm->trans); 12808c2ecf20Sopenharmony_ci 12818c2ecf20Sopenharmony_ci /* 12828c2ecf20Sopenharmony_ci * This is a bit racy, but worst case we tell mac80211 about 12838c2ecf20Sopenharmony_ci * a stopped/aborted scan when that was already done which 12848c2ecf20Sopenharmony_ci * is not a problem. It is necessary to abort any os scan 12858c2ecf20Sopenharmony_ci * here because mac80211 requires having the scan cleared 12868c2ecf20Sopenharmony_ci * before restarting. 12878c2ecf20Sopenharmony_ci * We'll reset the scan_status to NONE in restart cleanup in 12888c2ecf20Sopenharmony_ci * the next start() call from mac80211. If restart isn't called 12898c2ecf20Sopenharmony_ci * (no fw restart) scan status will stay busy. 12908c2ecf20Sopenharmony_ci */ 12918c2ecf20Sopenharmony_ci iwl_mvm_report_scan_aborted(mvm); 12928c2ecf20Sopenharmony_ci 12938c2ecf20Sopenharmony_ci /* 12948c2ecf20Sopenharmony_ci * If we're restarting already, don't cycle restarts. 12958c2ecf20Sopenharmony_ci * If INIT fw asserted, it will likely fail again. 12968c2ecf20Sopenharmony_ci * If WoWLAN fw asserted, don't restart either, mac80211 12978c2ecf20Sopenharmony_ci * can't recover this since we're already half suspended. 12988c2ecf20Sopenharmony_ci */ 12998c2ecf20Sopenharmony_ci if (!mvm->fw_restart && fw_error) { 13008c2ecf20Sopenharmony_ci iwl_fw_error_collect(&mvm->fwrt); 13018c2ecf20Sopenharmony_ci } else if (test_bit(IWL_MVM_STATUS_STARTING, 13028c2ecf20Sopenharmony_ci &mvm->status)) { 13038c2ecf20Sopenharmony_ci IWL_ERR(mvm, "Starting mac, retry will be triggered anyway\n"); 13048c2ecf20Sopenharmony_ci } else if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) { 13058c2ecf20Sopenharmony_ci struct iwl_mvm_reprobe *reprobe; 13068c2ecf20Sopenharmony_ci 13078c2ecf20Sopenharmony_ci IWL_ERR(mvm, 13088c2ecf20Sopenharmony_ci "Firmware error during reconfiguration - reprobe!\n"); 13098c2ecf20Sopenharmony_ci 13108c2ecf20Sopenharmony_ci /* 13118c2ecf20Sopenharmony_ci * get a module reference to avoid doing this while unloading 13128c2ecf20Sopenharmony_ci * anyway and to avoid scheduling a work with code that's 13138c2ecf20Sopenharmony_ci * being removed. 13148c2ecf20Sopenharmony_ci */ 13158c2ecf20Sopenharmony_ci if (!try_module_get(THIS_MODULE)) { 13168c2ecf20Sopenharmony_ci IWL_ERR(mvm, "Module is being unloaded - abort\n"); 13178c2ecf20Sopenharmony_ci return; 13188c2ecf20Sopenharmony_ci } 13198c2ecf20Sopenharmony_ci 13208c2ecf20Sopenharmony_ci reprobe = kzalloc(sizeof(*reprobe), GFP_ATOMIC); 13218c2ecf20Sopenharmony_ci if (!reprobe) { 13228c2ecf20Sopenharmony_ci module_put(THIS_MODULE); 13238c2ecf20Sopenharmony_ci return; 13248c2ecf20Sopenharmony_ci } 13258c2ecf20Sopenharmony_ci reprobe->dev = get_device(mvm->trans->dev); 13268c2ecf20Sopenharmony_ci INIT_WORK(&reprobe->work, iwl_mvm_reprobe_wk); 13278c2ecf20Sopenharmony_ci schedule_work(&reprobe->work); 13288c2ecf20Sopenharmony_ci } else if (test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, 13298c2ecf20Sopenharmony_ci &mvm->status)) { 13308c2ecf20Sopenharmony_ci IWL_ERR(mvm, "HW restart already requested, but not started\n"); 13318c2ecf20Sopenharmony_ci } else if (mvm->fwrt.cur_fw_img == IWL_UCODE_REGULAR && 13328c2ecf20Sopenharmony_ci mvm->hw_registered && 13338c2ecf20Sopenharmony_ci !test_bit(STATUS_TRANS_DEAD, &mvm->trans->status)) { 13348c2ecf20Sopenharmony_ci if (mvm->fw->ucode_capa.error_log_size) { 13358c2ecf20Sopenharmony_ci u32 src_size = mvm->fw->ucode_capa.error_log_size; 13368c2ecf20Sopenharmony_ci u32 src_addr = mvm->fw->ucode_capa.error_log_addr; 13378c2ecf20Sopenharmony_ci u8 *recover_buf = kzalloc(src_size, GFP_ATOMIC); 13388c2ecf20Sopenharmony_ci 13398c2ecf20Sopenharmony_ci if (recover_buf) { 13408c2ecf20Sopenharmony_ci mvm->error_recovery_buf = recover_buf; 13418c2ecf20Sopenharmony_ci iwl_trans_read_mem_bytes(mvm->trans, 13428c2ecf20Sopenharmony_ci src_addr, 13438c2ecf20Sopenharmony_ci recover_buf, 13448c2ecf20Sopenharmony_ci src_size); 13458c2ecf20Sopenharmony_ci } 13468c2ecf20Sopenharmony_ci } 13478c2ecf20Sopenharmony_ci 13488c2ecf20Sopenharmony_ci iwl_fw_error_collect(&mvm->fwrt); 13498c2ecf20Sopenharmony_ci 13508c2ecf20Sopenharmony_ci if (fw_error && mvm->fw_restart > 0) 13518c2ecf20Sopenharmony_ci mvm->fw_restart--; 13528c2ecf20Sopenharmony_ci set_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status); 13538c2ecf20Sopenharmony_ci ieee80211_restart_hw(mvm->hw); 13548c2ecf20Sopenharmony_ci } 13558c2ecf20Sopenharmony_ci} 13568c2ecf20Sopenharmony_ci 13578c2ecf20Sopenharmony_cistatic void iwl_mvm_nic_error(struct iwl_op_mode *op_mode) 13588c2ecf20Sopenharmony_ci{ 13598c2ecf20Sopenharmony_ci struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); 13608c2ecf20Sopenharmony_ci 13618c2ecf20Sopenharmony_ci if (!test_bit(STATUS_TRANS_DEAD, &mvm->trans->status)) 13628c2ecf20Sopenharmony_ci iwl_mvm_dump_nic_error_log(mvm); 13638c2ecf20Sopenharmony_ci 13648c2ecf20Sopenharmony_ci iwl_mvm_nic_restart(mvm, true); 13658c2ecf20Sopenharmony_ci} 13668c2ecf20Sopenharmony_ci 13678c2ecf20Sopenharmony_cistatic void iwl_mvm_cmd_queue_full(struct iwl_op_mode *op_mode) 13688c2ecf20Sopenharmony_ci{ 13698c2ecf20Sopenharmony_ci struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); 13708c2ecf20Sopenharmony_ci 13718c2ecf20Sopenharmony_ci WARN_ON(1); 13728c2ecf20Sopenharmony_ci iwl_mvm_nic_restart(mvm, true); 13738c2ecf20Sopenharmony_ci} 13748c2ecf20Sopenharmony_ci 13758c2ecf20Sopenharmony_ci#define IWL_MVM_COMMON_OPS \ 13768c2ecf20Sopenharmony_ci /* these could be differentiated */ \ 13778c2ecf20Sopenharmony_ci .async_cb = iwl_mvm_async_cb, \ 13788c2ecf20Sopenharmony_ci .queue_full = iwl_mvm_stop_sw_queue, \ 13798c2ecf20Sopenharmony_ci .queue_not_full = iwl_mvm_wake_sw_queue, \ 13808c2ecf20Sopenharmony_ci .hw_rf_kill = iwl_mvm_set_hw_rfkill_state, \ 13818c2ecf20Sopenharmony_ci .free_skb = iwl_mvm_free_skb, \ 13828c2ecf20Sopenharmony_ci .nic_error = iwl_mvm_nic_error, \ 13838c2ecf20Sopenharmony_ci .cmd_queue_full = iwl_mvm_cmd_queue_full, \ 13848c2ecf20Sopenharmony_ci .nic_config = iwl_mvm_nic_config, \ 13858c2ecf20Sopenharmony_ci /* as we only register one, these MUST be common! */ \ 13868c2ecf20Sopenharmony_ci .start = iwl_op_mode_mvm_start, \ 13878c2ecf20Sopenharmony_ci .stop = iwl_op_mode_mvm_stop 13888c2ecf20Sopenharmony_ci 13898c2ecf20Sopenharmony_cistatic const struct iwl_op_mode_ops iwl_mvm_ops = { 13908c2ecf20Sopenharmony_ci IWL_MVM_COMMON_OPS, 13918c2ecf20Sopenharmony_ci .rx = iwl_mvm_rx, 13928c2ecf20Sopenharmony_ci}; 13938c2ecf20Sopenharmony_ci 13948c2ecf20Sopenharmony_cistatic void iwl_mvm_rx_mq_rss(struct iwl_op_mode *op_mode, 13958c2ecf20Sopenharmony_ci struct napi_struct *napi, 13968c2ecf20Sopenharmony_ci struct iwl_rx_cmd_buffer *rxb, 13978c2ecf20Sopenharmony_ci unsigned int queue) 13988c2ecf20Sopenharmony_ci{ 13998c2ecf20Sopenharmony_ci struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); 14008c2ecf20Sopenharmony_ci struct iwl_rx_packet *pkt = rxb_addr(rxb); 14018c2ecf20Sopenharmony_ci u16 cmd = WIDE_ID(pkt->hdr.group_id, pkt->hdr.cmd); 14028c2ecf20Sopenharmony_ci 14038c2ecf20Sopenharmony_ci if (unlikely(cmd == WIDE_ID(LEGACY_GROUP, FRAME_RELEASE))) 14048c2ecf20Sopenharmony_ci iwl_mvm_rx_frame_release(mvm, napi, rxb, queue); 14058c2ecf20Sopenharmony_ci else if (unlikely(cmd == WIDE_ID(DATA_PATH_GROUP, 14068c2ecf20Sopenharmony_ci RX_QUEUES_NOTIFICATION))) 14078c2ecf20Sopenharmony_ci iwl_mvm_rx_queue_notif(mvm, napi, rxb, queue); 14088c2ecf20Sopenharmony_ci else if (likely(cmd == WIDE_ID(LEGACY_GROUP, REPLY_RX_MPDU_CMD))) 14098c2ecf20Sopenharmony_ci iwl_mvm_rx_mpdu_mq(mvm, napi, rxb, queue); 14108c2ecf20Sopenharmony_ci} 14118c2ecf20Sopenharmony_ci 14128c2ecf20Sopenharmony_cistatic const struct iwl_op_mode_ops iwl_mvm_ops_mq = { 14138c2ecf20Sopenharmony_ci IWL_MVM_COMMON_OPS, 14148c2ecf20Sopenharmony_ci .rx = iwl_mvm_rx_mq, 14158c2ecf20Sopenharmony_ci .rx_rss = iwl_mvm_rx_mq_rss, 14168c2ecf20Sopenharmony_ci}; 1417