iwlwifi: update Intel's mvm/mld drivers
This version is based on git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git e5f0a698b34ed76002dc5cff3804a61c80233a7a ( tag: v6.17 ). Some of the changes we reported upstream got incorporated in this (or the v6.16) release. This also includes a change from iwlwifi-next.git::next for missing symbols iwl_mvm_v3_rate_from_fw() and iwl_mvm_v3_rate_to_fw() were originally comitted to mvm/rs.[ch] which we do not have. That left us with unresolved symbols. For the never comitted v6.16 driver update I had started to piece these together but they have been migrated out to utils.c so take them from there until the next release hopefully ships this change. Obtained from: git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next.git branch next, 1b49af228594452206d5c50a33b6a341428edb63 MFC after: 3 days
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018-2024 Intel Corporation
|
||||
* Copyright (C) 2018-2025 Intel Corporation
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/stringify.h>
|
||||
@@ -15,40 +15,16 @@
|
||||
/* Lowest firmware API version supported */
|
||||
#define IWL_22000_UCODE_API_MIN 77
|
||||
|
||||
/* NVM versions */
|
||||
#define IWL_22000_NVM_VERSION 0x0a1d
|
||||
|
||||
/* Memory offsets and lengths */
|
||||
#define IWL_22000_DCCM_OFFSET 0x800000 /* LMAC1 */
|
||||
#define IWL_22000_DCCM_LEN 0x10000 /* LMAC1 */
|
||||
#define IWL_22000_DCCM2_OFFSET 0x880000
|
||||
#define IWL_22000_DCCM2_LEN 0x8000
|
||||
#define IWL_22000_SMEM_OFFSET 0x400000
|
||||
#define IWL_22000_SMEM_LEN 0xD0000
|
||||
|
||||
#define IWL_QU_B_HR_B_FW_PRE "iwlwifi-Qu-b0-hr-b0"
|
||||
#define IWL_QU_C_HR_B_FW_PRE "iwlwifi-Qu-c0-hr-b0"
|
||||
#define IWL_QU_B_JF_B_FW_PRE "iwlwifi-Qu-b0-jf-b0"
|
||||
#define IWL_QU_C_JF_B_FW_PRE "iwlwifi-Qu-c0-jf-b0"
|
||||
#define IWL_QUZ_A_HR_B_FW_PRE "iwlwifi-QuZ-a0-hr-b0"
|
||||
#define IWL_QUZ_A_JF_B_FW_PRE "iwlwifi-QuZ-a0-jf-b0"
|
||||
#define IWL_CC_A_FW_PRE "iwlwifi-cc-a0"
|
||||
|
||||
#define IWL_QU_B_HR_B_MODULE_FIRMWARE(api) \
|
||||
IWL_QU_B_HR_B_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_QUZ_A_HR_B_MODULE_FIRMWARE(api) \
|
||||
IWL_QUZ_A_HR_B_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_QUZ_A_JF_B_MODULE_FIRMWARE(api) \
|
||||
IWL_QUZ_A_JF_B_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_QU_C_HR_B_MODULE_FIRMWARE(api) \
|
||||
IWL_QU_C_HR_B_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_QU_B_JF_B_MODULE_FIRMWARE(api) \
|
||||
IWL_QU_B_JF_B_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_CC_A_MODULE_FIRMWARE(api) \
|
||||
IWL_CC_A_FW_PRE "-" __stringify(api) ".ucode"
|
||||
|
||||
static const struct iwl_base_params iwl_22000_base_params = {
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE_32K,
|
||||
static const struct iwl_family_base_params iwl_22000_base = {
|
||||
.num_of_queues = 512,
|
||||
.max_tfd_queue_size = 256,
|
||||
.shadow_ram_support = true,
|
||||
@@ -57,156 +33,78 @@ static const struct iwl_base_params iwl_22000_base_params = {
|
||||
.max_event_log_size = 512,
|
||||
.shadow_reg_enable = true,
|
||||
.pcie_l1_allowed = true,
|
||||
.smem_offset = IWL_22000_SMEM_OFFSET,
|
||||
.smem_len = IWL_22000_SMEM_LEN,
|
||||
.features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
|
||||
.apmg_not_supported = true,
|
||||
.mac_addr_from_csr = 0x380,
|
||||
.min_umac_error_event_table = 0x400000,
|
||||
.d3_debug_data_base_addr = 0x401000,
|
||||
.d3_debug_data_length = 60 * 1024,
|
||||
.mon_smem_regs = {
|
||||
.write_ptr = {
|
||||
.addr = LDBG_M2S_BUF_WPTR,
|
||||
.mask = LDBG_M2S_BUF_WPTR_VAL_MSK,
|
||||
},
|
||||
.cycle_cnt = {
|
||||
.addr = LDBG_M2S_BUF_WRAP_CNT,
|
||||
.mask = LDBG_M2S_BUF_WRAP_CNT_VAL_MSK,
|
||||
},
|
||||
},
|
||||
.gp2_reg_addr = 0xa02c68,
|
||||
.mon_dram_regs = {
|
||||
.write_ptr = {
|
||||
.addr = MON_BUFF_WRPTR_VER2,
|
||||
.mask = 0xffffffff,
|
||||
},
|
||||
.cycle_cnt = {
|
||||
.addr = MON_BUFF_CYCLE_CNT_VER2,
|
||||
.mask = 0xffffffff,
|
||||
},
|
||||
},
|
||||
.ucode_api_min = IWL_22000_UCODE_API_MIN,
|
||||
.ucode_api_max = IWL_22000_UCODE_API_MAX,
|
||||
};
|
||||
|
||||
const struct iwl_ht_params iwl_22000_ht_params = {
|
||||
.stbc = true,
|
||||
.ldpc = true,
|
||||
.ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ) |
|
||||
BIT(NL80211_BAND_6GHZ),
|
||||
};
|
||||
|
||||
#define IWL_DEVICE_22000_COMMON \
|
||||
.ucode_api_min = IWL_22000_UCODE_API_MIN, \
|
||||
.led_mode = IWL_LED_RF_STATE, \
|
||||
.nvm_hw_section_num = 10, \
|
||||
.non_shared_ant = ANT_B, \
|
||||
.dccm_offset = IWL_22000_DCCM_OFFSET, \
|
||||
.dccm_len = IWL_22000_DCCM_LEN, \
|
||||
.dccm2_offset = IWL_22000_DCCM2_OFFSET, \
|
||||
.dccm2_len = IWL_22000_DCCM2_LEN, \
|
||||
.smem_offset = IWL_22000_SMEM_OFFSET, \
|
||||
.smem_len = IWL_22000_SMEM_LEN, \
|
||||
.features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, \
|
||||
.apmg_not_supported = true, \
|
||||
.trans.mq_rx_supported = true, \
|
||||
.vht_mu_mimo_supported = true, \
|
||||
.mac_addr_from_csr = 0x380, \
|
||||
.ht_params = &iwl_22000_ht_params, \
|
||||
.nvm_ver = IWL_22000_NVM_VERSION, \
|
||||
.trans.rf_id = true, \
|
||||
.trans.gen2 = true, \
|
||||
.nvm_type = IWL_NVM_EXT, \
|
||||
.dbgc_supported = true, \
|
||||
.min_umac_error_event_table = 0x400000, \
|
||||
.d3_debug_data_base_addr = 0x401000, \
|
||||
.d3_debug_data_length = 60 * 1024, \
|
||||
.mon_smem_regs = { \
|
||||
.write_ptr = { \
|
||||
.addr = LDBG_M2S_BUF_WPTR, \
|
||||
.mask = LDBG_M2S_BUF_WPTR_VAL_MSK, \
|
||||
}, \
|
||||
.cycle_cnt = { \
|
||||
.addr = LDBG_M2S_BUF_WRAP_CNT, \
|
||||
.mask = LDBG_M2S_BUF_WRAP_CNT_VAL_MSK, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define IWL_DEVICE_22500 \
|
||||
IWL_DEVICE_22000_COMMON, \
|
||||
.ucode_api_max = IWL_22000_UCODE_API_MAX, \
|
||||
.trans.device_family = IWL_DEVICE_FAMILY_22000, \
|
||||
.trans.base_params = &iwl_22000_base_params, \
|
||||
.gp2_reg_addr = 0xa02c68, \
|
||||
.mon_dram_regs = { \
|
||||
.write_ptr = { \
|
||||
.addr = MON_BUFF_WRPTR_VER2, \
|
||||
.mask = 0xffffffff, \
|
||||
}, \
|
||||
.cycle_cnt = { \
|
||||
.addr = MON_BUFF_CYCLE_CNT_VER2, \
|
||||
.mask = 0xffffffff, \
|
||||
}, \
|
||||
}
|
||||
|
||||
const struct iwl_cfg_trans_params iwl_qu_trans_cfg = {
|
||||
const struct iwl_mac_cfg iwl_qu_mac_cfg = {
|
||||
.mq_rx_supported = true,
|
||||
.rf_id = true,
|
||||
.gen2 = true,
|
||||
.device_family = IWL_DEVICE_FAMILY_22000,
|
||||
.base_params = &iwl_22000_base_params,
|
||||
.base = &iwl_22000_base,
|
||||
.integrated = true,
|
||||
.xtal_latency = 500,
|
||||
.ltr_delay = IWL_CFG_TRANS_LTR_DELAY_200US,
|
||||
};
|
||||
|
||||
const struct iwl_cfg_trans_params iwl_qu_medium_latency_trans_cfg = {
|
||||
const struct iwl_mac_cfg iwl_qu_medium_latency_mac_cfg = {
|
||||
.mq_rx_supported = true,
|
||||
.rf_id = true,
|
||||
.gen2 = true,
|
||||
.device_family = IWL_DEVICE_FAMILY_22000,
|
||||
.base_params = &iwl_22000_base_params,
|
||||
.base = &iwl_22000_base,
|
||||
.integrated = true,
|
||||
.xtal_latency = 1820,
|
||||
.ltr_delay = IWL_CFG_TRANS_LTR_DELAY_1820US,
|
||||
};
|
||||
|
||||
const struct iwl_cfg_trans_params iwl_qu_long_latency_trans_cfg = {
|
||||
const struct iwl_mac_cfg iwl_qu_long_latency_mac_cfg = {
|
||||
.mq_rx_supported = true,
|
||||
.rf_id = true,
|
||||
.gen2 = true,
|
||||
.device_family = IWL_DEVICE_FAMILY_22000,
|
||||
.base_params = &iwl_22000_base_params,
|
||||
.base = &iwl_22000_base,
|
||||
.integrated = true,
|
||||
.xtal_latency = 12000,
|
||||
.low_latency_xtal = true,
|
||||
.ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US,
|
||||
};
|
||||
|
||||
/*
|
||||
* If the device doesn't support HE, no need to have that many buffers.
|
||||
* 22000 devices can split multiple frames into a single RB, so fewer are
|
||||
* needed; AX210 cannot (but use smaller RBs by default) - these sizes
|
||||
* were picked according to 8 MSDUs inside 256 A-MSDUs in an A-MPDU, with
|
||||
* additional overhead to account for processing time.
|
||||
*/
|
||||
#define IWL_NUM_RBDS_NON_HE 512
|
||||
#define IWL_NUM_RBDS_22000_HE 2048
|
||||
|
||||
/*
|
||||
* All JF radio modules are part of the 9000 series, but the MAC part
|
||||
* looks more like 22000. That's why this device is here, but called
|
||||
* 9560 nevertheless.
|
||||
*/
|
||||
const struct iwl_cfg iwl9560_qu_b0_jf_b0_cfg = {
|
||||
.fw_name_pre = IWL_QU_B_JF_B_FW_PRE,
|
||||
IWL_DEVICE_22500,
|
||||
.num_rbds = IWL_NUM_RBDS_NON_HE,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl9560_qu_c0_jf_b0_cfg = {
|
||||
.fw_name_pre = IWL_QU_C_JF_B_FW_PRE,
|
||||
IWL_DEVICE_22500,
|
||||
.num_rbds = IWL_NUM_RBDS_NON_HE,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl9560_quz_a0_jf_b0_cfg = {
|
||||
.fw_name_pre = IWL_QUZ_A_JF_B_FW_PRE,
|
||||
IWL_DEVICE_22500,
|
||||
/*
|
||||
* This device doesn't support receiving BlockAck with a large bitmap
|
||||
* so we need to restrict the size of transmitted aggregation to the
|
||||
* HT size; mac80211 would otherwise pick the HE max (256) by default.
|
||||
*/
|
||||
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
|
||||
.num_rbds = IWL_NUM_RBDS_NON_HE,
|
||||
};
|
||||
|
||||
const struct iwl_cfg_trans_params iwl_ax200_trans_cfg = {
|
||||
const struct iwl_mac_cfg iwl_ax200_mac_cfg = {
|
||||
.device_family = IWL_DEVICE_FAMILY_22000,
|
||||
.base_params = &iwl_22000_base_params,
|
||||
.base = &iwl_22000_base,
|
||||
.mq_rx_supported = true,
|
||||
.rf_id = true,
|
||||
.gen2 = true,
|
||||
.bisr_workaround = 1,
|
||||
};
|
||||
|
||||
const char iwl_ax101_name[] = "Intel(R) Wi-Fi 6 AX101";
|
||||
const char iwl_ax200_name[] = "Intel(R) Wi-Fi 6 AX200 160MHz";
|
||||
const char iwl_ax201_name[] = "Intel(R) Wi-Fi 6 AX201 160MHz";
|
||||
const char iwl_ax203_name[] = "Intel(R) Wi-Fi 6 AX203";
|
||||
const char iwl_ax204_name[] = "Intel(R) Wi-Fi 6 AX204 160MHz";
|
||||
|
||||
const char iwl_ax200_killer_1650w_name[] =
|
||||
"Killer(R) Wi-Fi 6 AX1650w 160MHz Wireless Network Adapter (200D2W)";
|
||||
const char iwl_ax200_killer_1650x_name[] =
|
||||
@@ -216,213 +114,4 @@ const char iwl_ax201_killer_1650s_name[] =
|
||||
const char iwl_ax201_killer_1650i_name[] =
|
||||
"Killer(R) Wi-Fi 6 AX1650i 160MHz Wireless Network Adapter (201NGW)";
|
||||
|
||||
const struct iwl_cfg iwl_qu_b0_hr1_b0 = {
|
||||
.fw_name_pre = IWL_QU_B_HR_B_FW_PRE,
|
||||
IWL_DEVICE_22500,
|
||||
/*
|
||||
* This device doesn't support receiving BlockAck with a large bitmap
|
||||
* so we need to restrict the size of transmitted aggregation to the
|
||||
* HT size; mac80211 would otherwise pick the HE max (256) by default.
|
||||
*/
|
||||
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
|
||||
.tx_with_siso_diversity = true,
|
||||
.num_rbds = IWL_NUM_RBDS_22000_HE,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl_qu_b0_hr_b0 = {
|
||||
.fw_name_pre = IWL_QU_B_HR_B_FW_PRE,
|
||||
IWL_DEVICE_22500,
|
||||
/*
|
||||
* This device doesn't support receiving BlockAck with a large bitmap
|
||||
* so we need to restrict the size of transmitted aggregation to the
|
||||
* HT size; mac80211 would otherwise pick the HE max (256) by default.
|
||||
*/
|
||||
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
|
||||
.num_rbds = IWL_NUM_RBDS_22000_HE,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl_ax201_cfg_qu_hr = {
|
||||
.name = "Intel(R) Wi-Fi 6 AX201 160MHz",
|
||||
.fw_name_pre = IWL_QU_B_HR_B_FW_PRE,
|
||||
IWL_DEVICE_22500,
|
||||
/*
|
||||
* This device doesn't support receiving BlockAck with a large bitmap
|
||||
* so we need to restrict the size of transmitted aggregation to the
|
||||
* HT size; mac80211 would otherwise pick the HE max (256) by default.
|
||||
*/
|
||||
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
|
||||
.num_rbds = IWL_NUM_RBDS_22000_HE,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl_qu_c0_hr1_b0 = {
|
||||
.fw_name_pre = IWL_QU_C_HR_B_FW_PRE,
|
||||
IWL_DEVICE_22500,
|
||||
/*
|
||||
* This device doesn't support receiving BlockAck with a large bitmap
|
||||
* so we need to restrict the size of transmitted aggregation to the
|
||||
* HT size; mac80211 would otherwise pick the HE max (256) by default.
|
||||
*/
|
||||
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
|
||||
.tx_with_siso_diversity = true,
|
||||
.num_rbds = IWL_NUM_RBDS_22000_HE,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl_qu_c0_hr_b0 = {
|
||||
.fw_name_pre = IWL_QU_C_HR_B_FW_PRE,
|
||||
IWL_DEVICE_22500,
|
||||
/*
|
||||
* This device doesn't support receiving BlockAck with a large bitmap
|
||||
* so we need to restrict the size of transmitted aggregation to the
|
||||
* HT size; mac80211 would otherwise pick the HE max (256) by default.
|
||||
*/
|
||||
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
|
||||
.num_rbds = IWL_NUM_RBDS_22000_HE,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl_ax201_cfg_qu_c0_hr_b0 = {
|
||||
.name = "Intel(R) Wi-Fi 6 AX201 160MHz",
|
||||
.fw_name_pre = IWL_QU_C_HR_B_FW_PRE,
|
||||
IWL_DEVICE_22500,
|
||||
/*
|
||||
* This device doesn't support receiving BlockAck with a large bitmap
|
||||
* so we need to restrict the size of transmitted aggregation to the
|
||||
* HT size; mac80211 would otherwise pick the HE max (256) by default.
|
||||
*/
|
||||
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
|
||||
.num_rbds = IWL_NUM_RBDS_22000_HE,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl_quz_a0_hr1_b0 = {
|
||||
.fw_name_pre = IWL_QUZ_A_HR_B_FW_PRE,
|
||||
IWL_DEVICE_22500,
|
||||
/*
|
||||
* This device doesn't support receiving BlockAck with a large bitmap
|
||||
* so we need to restrict the size of transmitted aggregation to the
|
||||
* HT size; mac80211 would otherwise pick the HE max (256) by default.
|
||||
*/
|
||||
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
|
||||
.tx_with_siso_diversity = true,
|
||||
.num_rbds = IWL_NUM_RBDS_22000_HE,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl_ax201_cfg_quz_hr = {
|
||||
.name = "Intel(R) Wi-Fi 6 AX201 160MHz",
|
||||
.fw_name_pre = IWL_QUZ_A_HR_B_FW_PRE,
|
||||
IWL_DEVICE_22500,
|
||||
/*
|
||||
* This device doesn't support receiving BlockAck with a large bitmap
|
||||
* so we need to restrict the size of transmitted aggregation to the
|
||||
* HT size; mac80211 would otherwise pick the HE max (256) by default.
|
||||
*/
|
||||
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
|
||||
.num_rbds = IWL_NUM_RBDS_22000_HE,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl_ax1650s_cfg_quz_hr = {
|
||||
.name = "Killer(R) Wi-Fi 6 AX1650s 160MHz Wireless Network Adapter (201D2W)",
|
||||
.fw_name_pre = IWL_QUZ_A_HR_B_FW_PRE,
|
||||
IWL_DEVICE_22500,
|
||||
/*
|
||||
* This device doesn't support receiving BlockAck with a large bitmap
|
||||
* so we need to restrict the size of transmitted aggregation to the
|
||||
* HT size; mac80211 would otherwise pick the HE max (256) by default.
|
||||
*/
|
||||
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
|
||||
.num_rbds = IWL_NUM_RBDS_22000_HE,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl_ax1650i_cfg_quz_hr = {
|
||||
.name = "Killer(R) Wi-Fi 6 AX1650i 160MHz Wireless Network Adapter (201NGW)",
|
||||
.fw_name_pre = IWL_QUZ_A_HR_B_FW_PRE,
|
||||
IWL_DEVICE_22500,
|
||||
/*
|
||||
* This device doesn't support receiving BlockAck with a large bitmap
|
||||
* so we need to restrict the size of transmitted aggregation to the
|
||||
* HT size; mac80211 would otherwise pick the HE max (256) by default.
|
||||
*/
|
||||
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
|
||||
.num_rbds = IWL_NUM_RBDS_22000_HE,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl_ax200_cfg_cc = {
|
||||
.fw_name_pre = IWL_CC_A_FW_PRE,
|
||||
IWL_DEVICE_22500,
|
||||
/*
|
||||
* This device doesn't support receiving BlockAck with a large bitmap
|
||||
* so we need to restrict the size of transmitted aggregation to the
|
||||
* HT size; mac80211 would otherwise pick the HE max (256) by default.
|
||||
*/
|
||||
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
|
||||
.num_rbds = IWL_NUM_RBDS_22000_HE,
|
||||
};
|
||||
|
||||
const struct iwl_cfg killer1650s_2ax_cfg_qu_b0_hr_b0 = {
|
||||
.name = "Killer(R) Wi-Fi 6 AX1650s 160MHz Wireless Network Adapter (201NGW)",
|
||||
.fw_name_pre = IWL_QU_B_HR_B_FW_PRE,
|
||||
IWL_DEVICE_22500,
|
||||
/*
|
||||
* This device doesn't support receiving BlockAck with a large bitmap
|
||||
* so we need to restrict the size of transmitted aggregation to the
|
||||
* HT size; mac80211 would otherwise pick the HE max (256) by default.
|
||||
*/
|
||||
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
|
||||
.num_rbds = IWL_NUM_RBDS_22000_HE,
|
||||
};
|
||||
|
||||
const struct iwl_cfg killer1650i_2ax_cfg_qu_b0_hr_b0 = {
|
||||
.name = "Killer(R) Wi-Fi 6 AX1650i 160MHz Wireless Network Adapter (201D2W)",
|
||||
.fw_name_pre = IWL_QU_B_HR_B_FW_PRE,
|
||||
IWL_DEVICE_22500,
|
||||
/*
|
||||
* This device doesn't support receiving BlockAck with a large bitmap
|
||||
* so we need to restrict the size of transmitted aggregation to the
|
||||
* HT size; mac80211 would otherwise pick the HE max (256) by default.
|
||||
*/
|
||||
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
|
||||
.num_rbds = IWL_NUM_RBDS_22000_HE,
|
||||
};
|
||||
|
||||
const struct iwl_cfg killer1650s_2ax_cfg_qu_c0_hr_b0 = {
|
||||
.name = "Killer(R) Wi-Fi 6 AX1650s 160MHz Wireless Network Adapter (201NGW)",
|
||||
.fw_name_pre = IWL_QU_C_HR_B_FW_PRE,
|
||||
IWL_DEVICE_22500,
|
||||
/*
|
||||
* This device doesn't support receiving BlockAck with a large bitmap
|
||||
* so we need to restrict the size of transmitted aggregation to the
|
||||
* HT size; mac80211 would otherwise pick the HE max (256) by default.
|
||||
*/
|
||||
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
|
||||
.num_rbds = IWL_NUM_RBDS_22000_HE,
|
||||
};
|
||||
|
||||
const struct iwl_cfg killer1650i_2ax_cfg_qu_c0_hr_b0 = {
|
||||
.name = "Killer(R) Wi-Fi 6 AX1650i 160MHz Wireless Network Adapter (201D2W)",
|
||||
.fw_name_pre = IWL_QU_C_HR_B_FW_PRE,
|
||||
IWL_DEVICE_22500,
|
||||
/*
|
||||
* This device doesn't support receiving BlockAck with a large bitmap
|
||||
* so we need to restrict the size of transmitted aggregation to the
|
||||
* HT size; mac80211 would otherwise pick the HE max (256) by default.
|
||||
*/
|
||||
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
|
||||
.num_rbds = IWL_NUM_RBDS_22000_HE,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl_cfg_quz_a0_hr_b0 = {
|
||||
.fw_name_pre = IWL_QUZ_A_HR_B_FW_PRE,
|
||||
IWL_DEVICE_22500,
|
||||
/*
|
||||
* This device doesn't support receiving BlockAck with a large bitmap
|
||||
* so we need to restrict the size of transmitted aggregation to the
|
||||
* HT size; mac80211 would otherwise pick the HE max (256) by default.
|
||||
*/
|
||||
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
|
||||
.num_rbds = IWL_NUM_RBDS_22000_HE,
|
||||
};
|
||||
|
||||
MODULE_FIRMWARE(IWL_QU_B_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_QU_C_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_QU_B_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_QUZ_A_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_QUZ_A_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_CC_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2020, 2023 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2020, 2023, 2025 Intel Corporation
|
||||
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2015 Intel Deutschland GmbH
|
||||
*/
|
||||
@@ -49,7 +49,7 @@
|
||||
#define IWL7265D_FW_PRE "iwlwifi-7265D"
|
||||
#define IWL7265D_MODULE_FIRMWARE(api) IWL7265D_FW_PRE "-" __stringify(api) ".ucode"
|
||||
|
||||
static const struct iwl_base_params iwl7000_base_params = {
|
||||
static const struct iwl_family_base_params iwl7000_base = {
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE_16K,
|
||||
.num_of_queues = 31,
|
||||
.max_tfd_queue_size = 256,
|
||||
@@ -60,6 +60,7 @@ static const struct iwl_base_params iwl7000_base_params = {
|
||||
.shadow_reg_enable = true,
|
||||
.pcie_l1_allowed = true,
|
||||
.apmg_wake_up_wa = true,
|
||||
.nvm_hw_section_num = 0,
|
||||
};
|
||||
|
||||
static const struct iwl_tt_params iwl7000_high_temp_tt_params = {
|
||||
@@ -84,16 +85,13 @@ static const struct iwl_tt_params iwl7000_high_temp_tt_params = {
|
||||
.support_tx_backoff = true,
|
||||
};
|
||||
|
||||
static const struct iwl_ht_params iwl7000_ht_params = {
|
||||
.stbc = true,
|
||||
.ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
|
||||
const struct iwl_mac_cfg iwl7000_mac_cfg = {
|
||||
.device_family = IWL_DEVICE_FAMILY_7000,
|
||||
.base = &iwl7000_base,
|
||||
};
|
||||
|
||||
#define IWL_DEVICE_7000_COMMON \
|
||||
.trans.device_family = IWL_DEVICE_FAMILY_7000, \
|
||||
.trans.base_params = &iwl7000_base_params, \
|
||||
.led_mode = IWL_LED_RF_STATE, \
|
||||
.nvm_hw_section_num = 0, \
|
||||
.non_shared_ant = ANT_A, \
|
||||
.dccm_offset = IWL7000_DCCM_OFFSET
|
||||
|
||||
@@ -117,77 +115,52 @@ static const struct iwl_ht_params iwl7000_ht_params = {
|
||||
.ucode_api_max = IWL7265D_UCODE_API_MAX, \
|
||||
.ucode_api_min = IWL7265D_UCODE_API_MIN
|
||||
|
||||
const struct iwl_cfg iwl7260_2ac_cfg = {
|
||||
.name = "Intel(R) Dual Band Wireless AC 7260",
|
||||
const char iwl7260_2ac_name[] = "Intel(R) Dual Band Wireless AC 7260";
|
||||
const char iwl7260_2n_name[] = "Intel(R) Dual Band Wireless N 7260";
|
||||
const char iwl7260_n_name[] = "Intel(R) Wireless N 7260";
|
||||
const char iwl3160_2ac_name[] = "Intel(R) Dual Band Wireless AC 3160";
|
||||
const char iwl3160_2n_name[] = "Intel(R) Dual Band Wireless N 3160";
|
||||
const char iwl3160_n_name[] = "Intel(R) Wireless N 3160";
|
||||
const char iwl3165_2ac_name[] = "Intel(R) Dual Band Wireless-AC 3165";
|
||||
const char iwl3168_2ac_name[] = "Intel(R) Dual Band Wireless-AC 3168";
|
||||
const char iwl7265_2ac_name[] = "Intel(R) Dual Band Wireless-AC 7265";
|
||||
const char iwl7265_2n_name[] = "Intel(R) Dual Band Wireless-N 7265";
|
||||
const char iwl7265_n_name[] = "Intel(R) Wireless-N 7265";
|
||||
|
||||
const struct iwl_rf_cfg iwl7260_cfg = {
|
||||
.fw_name_pre = IWL7260_FW_PRE,
|
||||
IWL_DEVICE_7000,
|
||||
.ht_params = &iwl7000_ht_params,
|
||||
.ht_params = {
|
||||
.stbc = true,
|
||||
.ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
|
||||
},
|
||||
.nvm_ver = IWL7260_NVM_VERSION,
|
||||
.host_interrupt_operation_mode = true,
|
||||
.lp_xtal_workaround = true,
|
||||
.dccm_len = IWL7260_DCCM_LEN,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl7260_2ac_cfg_high_temp = {
|
||||
.name = "Intel(R) Dual Band Wireless AC 7260",
|
||||
const struct iwl_rf_cfg iwl7260_high_temp_cfg = {
|
||||
.fw_name_pre = IWL7260_FW_PRE,
|
||||
IWL_DEVICE_7000,
|
||||
.ht_params = &iwl7000_ht_params,
|
||||
.ht_params = {
|
||||
.stbc = true,
|
||||
.ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
|
||||
},
|
||||
.nvm_ver = IWL7260_NVM_VERSION,
|
||||
.high_temp = true,
|
||||
.host_interrupt_operation_mode = true,
|
||||
.lp_xtal_workaround = true,
|
||||
.dccm_len = IWL7260_DCCM_LEN,
|
||||
.thermal_params = &iwl7000_high_temp_tt_params,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl7260_2n_cfg = {
|
||||
.name = "Intel(R) Dual Band Wireless N 7260",
|
||||
.fw_name_pre = IWL7260_FW_PRE,
|
||||
IWL_DEVICE_7000,
|
||||
.ht_params = &iwl7000_ht_params,
|
||||
.nvm_ver = IWL7260_NVM_VERSION,
|
||||
.host_interrupt_operation_mode = true,
|
||||
.lp_xtal_workaround = true,
|
||||
.dccm_len = IWL7260_DCCM_LEN,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl7260_n_cfg = {
|
||||
.name = "Intel(R) Wireless N 7260",
|
||||
.fw_name_pre = IWL7260_FW_PRE,
|
||||
IWL_DEVICE_7000,
|
||||
.ht_params = &iwl7000_ht_params,
|
||||
.nvm_ver = IWL7260_NVM_VERSION,
|
||||
.host_interrupt_operation_mode = true,
|
||||
.lp_xtal_workaround = true,
|
||||
.dccm_len = IWL7260_DCCM_LEN,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl3160_2ac_cfg = {
|
||||
.name = "Intel(R) Dual Band Wireless AC 3160",
|
||||
const struct iwl_rf_cfg iwl3160_cfg = {
|
||||
.fw_name_pre = IWL3160_FW_PRE,
|
||||
IWL_DEVICE_7000,
|
||||
.ht_params = &iwl7000_ht_params,
|
||||
.nvm_ver = IWL3160_NVM_VERSION,
|
||||
.host_interrupt_operation_mode = true,
|
||||
.dccm_len = IWL3160_DCCM_LEN,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl3160_2n_cfg = {
|
||||
.name = "Intel(R) Dual Band Wireless N 3160",
|
||||
.fw_name_pre = IWL3160_FW_PRE,
|
||||
IWL_DEVICE_7000,
|
||||
.ht_params = &iwl7000_ht_params,
|
||||
.nvm_ver = IWL3160_NVM_VERSION,
|
||||
.host_interrupt_operation_mode = true,
|
||||
.dccm_len = IWL3160_DCCM_LEN,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl3160_n_cfg = {
|
||||
.name = "Intel(R) Wireless N 3160",
|
||||
.fw_name_pre = IWL3160_FW_PRE,
|
||||
IWL_DEVICE_7000,
|
||||
.ht_params = &iwl7000_ht_params,
|
||||
.ht_params = {
|
||||
.stbc = true,
|
||||
.ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
|
||||
},
|
||||
.nvm_ver = IWL3160_NVM_VERSION,
|
||||
.host_interrupt_operation_mode = true,
|
||||
.dccm_len = IWL3160_DCCM_LEN,
|
||||
@@ -204,88 +177,52 @@ static const struct iwl_pwr_tx_backoff iwl7265_pwr_tx_backoffs[] = {
|
||||
{0},
|
||||
};
|
||||
|
||||
static const struct iwl_ht_params iwl7265_ht_params = {
|
||||
.stbc = true,
|
||||
.ldpc = true,
|
||||
.ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl3165_2ac_cfg = {
|
||||
.name = "Intel(R) Dual Band Wireless AC 3165",
|
||||
const struct iwl_rf_cfg iwl3165_2ac_cfg = {
|
||||
.fw_name_pre = IWL7265D_FW_PRE,
|
||||
IWL_DEVICE_7005D,
|
||||
.ht_params = &iwl7000_ht_params,
|
||||
.ht_params = {
|
||||
.stbc = true,
|
||||
.ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
|
||||
},
|
||||
.nvm_ver = IWL3165_NVM_VERSION,
|
||||
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
|
||||
.dccm_len = IWL7265_DCCM_LEN,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl3168_2ac_cfg = {
|
||||
.name = "Intel(R) Dual Band Wireless AC 3168",
|
||||
const struct iwl_rf_cfg iwl3168_2ac_cfg = {
|
||||
.fw_name_pre = IWL3168_FW_PRE,
|
||||
IWL_DEVICE_3008,
|
||||
.ht_params = &iwl7000_ht_params,
|
||||
.ht_params = {
|
||||
.stbc = true,
|
||||
.ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
|
||||
},
|
||||
.nvm_ver = IWL3168_NVM_VERSION,
|
||||
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
|
||||
.dccm_len = IWL7265_DCCM_LEN,
|
||||
.nvm_type = IWL_NVM_SDP,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl7265_2ac_cfg = {
|
||||
.name = "Intel(R) Dual Band Wireless AC 7265",
|
||||
const struct iwl_rf_cfg iwl7265_cfg = {
|
||||
.fw_name_pre = IWL7265_FW_PRE,
|
||||
IWL_DEVICE_7005,
|
||||
.ht_params = &iwl7265_ht_params,
|
||||
.ht_params = {
|
||||
.stbc = true,
|
||||
.ldpc = true,
|
||||
.ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
|
||||
},
|
||||
.nvm_ver = IWL7265_NVM_VERSION,
|
||||
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
|
||||
.dccm_len = IWL7265_DCCM_LEN,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl7265_2n_cfg = {
|
||||
.name = "Intel(R) Dual Band Wireless N 7265",
|
||||
.fw_name_pre = IWL7265_FW_PRE,
|
||||
IWL_DEVICE_7005,
|
||||
.ht_params = &iwl7265_ht_params,
|
||||
.nvm_ver = IWL7265_NVM_VERSION,
|
||||
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
|
||||
.dccm_len = IWL7265_DCCM_LEN,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl7265_n_cfg = {
|
||||
.name = "Intel(R) Wireless N 7265",
|
||||
.fw_name_pre = IWL7265_FW_PRE,
|
||||
IWL_DEVICE_7005,
|
||||
.ht_params = &iwl7265_ht_params,
|
||||
.nvm_ver = IWL7265_NVM_VERSION,
|
||||
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
|
||||
.dccm_len = IWL7265_DCCM_LEN,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl7265d_2ac_cfg = {
|
||||
.name = "Intel(R) Dual Band Wireless AC 7265",
|
||||
const struct iwl_rf_cfg iwl7265d_cfg = {
|
||||
.fw_name_pre = IWL7265D_FW_PRE,
|
||||
IWL_DEVICE_7005D,
|
||||
.ht_params = &iwl7265_ht_params,
|
||||
.nvm_ver = IWL7265D_NVM_VERSION,
|
||||
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
|
||||
.dccm_len = IWL7265_DCCM_LEN,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl7265d_2n_cfg = {
|
||||
.name = "Intel(R) Dual Band Wireless N 7265",
|
||||
.fw_name_pre = IWL7265D_FW_PRE,
|
||||
IWL_DEVICE_7005D,
|
||||
.ht_params = &iwl7265_ht_params,
|
||||
.nvm_ver = IWL7265D_NVM_VERSION,
|
||||
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
|
||||
.dccm_len = IWL7265_DCCM_LEN,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl7265d_n_cfg = {
|
||||
.name = "Intel(R) Wireless N 7265",
|
||||
.fw_name_pre = IWL7265D_FW_PRE,
|
||||
IWL_DEVICE_7005D,
|
||||
.ht_params = &iwl7265_ht_params,
|
||||
.ht_params = {
|
||||
.stbc = true,
|
||||
.ldpc = true,
|
||||
.ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
|
||||
},
|
||||
.nvm_ver = IWL7265D_NVM_VERSION,
|
||||
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
|
||||
.dccm_len = IWL7265_DCCM_LEN,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2014, 2018-2020, 2023 Intel Corporation
|
||||
* Copyright (C) 2014, 2018-2020, 2023, 2025 Intel Corporation
|
||||
* Copyright (C) 2014-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016 Intel Deutschland GmbH
|
||||
*/
|
||||
@@ -35,9 +35,7 @@
|
||||
#define IWL8265_MODULE_FIRMWARE(api) \
|
||||
IWL8265_FW_PRE "-" __stringify(api) ".ucode"
|
||||
|
||||
#define DEFAULT_NVM_FILE_FAMILY_8000C "nvmData-8000C"
|
||||
|
||||
static const struct iwl_base_params iwl8000_base_params = {
|
||||
static const struct iwl_family_base_params iwl8000_base = {
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE_32K,
|
||||
.num_of_queues = 31,
|
||||
.max_tfd_queue_size = 256,
|
||||
@@ -47,12 +45,12 @@ static const struct iwl_base_params iwl8000_base_params = {
|
||||
.max_event_log_size = 512,
|
||||
.shadow_reg_enable = true,
|
||||
.pcie_l1_allowed = true,
|
||||
};
|
||||
|
||||
static const struct iwl_ht_params iwl8000_ht_params = {
|
||||
.stbc = true,
|
||||
.ldpc = true,
|
||||
.ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
|
||||
.nvm_hw_section_num = 10,
|
||||
.features = NETIF_F_RXCSUM,
|
||||
.smem_offset = IWL8260_SMEM_OFFSET,
|
||||
.smem_len = IWL8260_SMEM_LEN,
|
||||
.apmg_not_supported = true,
|
||||
.min_umac_error_event_table = 0x800000,
|
||||
};
|
||||
|
||||
static const struct iwl_tt_params iwl8000_tt_params = {
|
||||
@@ -76,30 +74,20 @@ static const struct iwl_tt_params iwl8000_tt_params = {
|
||||
.support_tx_backoff = true,
|
||||
};
|
||||
|
||||
const struct iwl_mac_cfg iwl8000_mac_cfg = {
|
||||
.device_family = IWL_DEVICE_FAMILY_8000,
|
||||
.base = &iwl8000_base,
|
||||
};
|
||||
|
||||
#define IWL_DEVICE_8000_COMMON \
|
||||
.trans.device_family = IWL_DEVICE_FAMILY_8000, \
|
||||
.trans.base_params = &iwl8000_base_params, \
|
||||
.led_mode = IWL_LED_RF_STATE, \
|
||||
.nvm_hw_section_num = 10, \
|
||||
.features = NETIF_F_RXCSUM, \
|
||||
.non_shared_ant = ANT_A, \
|
||||
.dccm_offset = IWL8260_DCCM_OFFSET, \
|
||||
.dccm_len = IWL8260_DCCM_LEN, \
|
||||
.dccm2_offset = IWL8260_DCCM2_OFFSET, \
|
||||
.dccm2_len = IWL8260_DCCM2_LEN, \
|
||||
.smem_offset = IWL8260_SMEM_OFFSET, \
|
||||
.smem_len = IWL8260_SMEM_LEN, \
|
||||
.default_nvm_file_C_step = DEFAULT_NVM_FILE_FAMILY_8000C, \
|
||||
.thermal_params = &iwl8000_tt_params, \
|
||||
.apmg_not_supported = true, \
|
||||
.nvm_type = IWL_NVM_EXT, \
|
||||
.dbgc_supported = true, \
|
||||
.min_umac_error_event_table = 0x800000
|
||||
|
||||
#define IWL_DEVICE_8000 \
|
||||
IWL_DEVICE_8000_COMMON, \
|
||||
.ucode_api_max = IWL8000_UCODE_API_MAX, \
|
||||
.ucode_api_min = IWL8000_UCODE_API_MIN \
|
||||
.nvm_type = IWL_NVM_EXT
|
||||
|
||||
#define IWL_DEVICE_8260 \
|
||||
IWL_DEVICE_8000_COMMON, \
|
||||
@@ -111,47 +99,39 @@ static const struct iwl_tt_params iwl8000_tt_params = {
|
||||
.ucode_api_max = IWL8265_UCODE_API_MAX, \
|
||||
.ucode_api_min = IWL8265_UCODE_API_MIN \
|
||||
|
||||
const struct iwl_cfg iwl8260_2n_cfg = {
|
||||
.name = "Intel(R) Dual Band Wireless N 8260",
|
||||
const char iwl8260_2n_name[] = "Intel(R) Dual Band Wireless-N 8260";
|
||||
const char iwl8260_2ac_name[] = "Intel(R) Dual Band Wireless-AC 8260";
|
||||
const char iwl8265_2ac_name[] = "Intel(R) Dual Band Wireless-AC 8265";
|
||||
const char iwl8275_2ac_name[] = "Intel(R) Dual Band Wireless-AC 8275";
|
||||
const char iwl4165_2ac_name[] = "Intel(R) Dual Band Wireless-AC 4165";
|
||||
|
||||
const char iwl_killer_1435i_name[] =
|
||||
"Killer(R) Wireless-AC 1435i Wireless Network Adapter (8265D2W)";
|
||||
const char iwl_killer_1434_kix_name[] =
|
||||
"Killer(R) Wireless-AC 1435-KIX Wireless Network Adapter (8265NGW)";
|
||||
|
||||
const struct iwl_rf_cfg iwl8260_cfg = {
|
||||
.fw_name_pre = IWL8000_FW_PRE,
|
||||
IWL_DEVICE_8260,
|
||||
.ht_params = &iwl8000_ht_params,
|
||||
.ht_params = {
|
||||
.stbc = true,
|
||||
.ldpc = true,
|
||||
.ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
|
||||
},
|
||||
.nvm_ver = IWL8000_NVM_VERSION,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl8260_2ac_cfg = {
|
||||
.name = "Intel(R) Dual Band Wireless AC 8260",
|
||||
.fw_name_pre = IWL8000_FW_PRE,
|
||||
IWL_DEVICE_8260,
|
||||
.ht_params = &iwl8000_ht_params,
|
||||
.nvm_ver = IWL8000_NVM_VERSION,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl8265_2ac_cfg = {
|
||||
.name = "Intel(R) Dual Band Wireless AC 8265",
|
||||
const struct iwl_rf_cfg iwl8265_cfg = {
|
||||
.fw_name_pre = IWL8265_FW_PRE,
|
||||
IWL_DEVICE_8265,
|
||||
.ht_params = &iwl8000_ht_params,
|
||||
.ht_params = {
|
||||
.stbc = true,
|
||||
.ldpc = true,
|
||||
.ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
|
||||
},
|
||||
.nvm_ver = IWL8000_NVM_VERSION,
|
||||
.vht_mu_mimo_supported = true,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl8275_2ac_cfg = {
|
||||
.name = "Intel(R) Dual Band Wireless AC 8275",
|
||||
.fw_name_pre = IWL8265_FW_PRE,
|
||||
IWL_DEVICE_8265,
|
||||
.ht_params = &iwl8000_ht_params,
|
||||
.nvm_ver = IWL8000_NVM_VERSION,
|
||||
.vht_mu_mimo_supported = true,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl4165_2ac_cfg = {
|
||||
.name = "Intel(R) Dual Band Wireless AC 4165",
|
||||
.fw_name_pre = IWL8000_FW_PRE,
|
||||
IWL_DEVICE_8000,
|
||||
.ht_params = &iwl8000_ht_params,
|
||||
.nvm_ver = IWL8000_NVM_VERSION,
|
||||
};
|
||||
|
||||
MODULE_FIRMWARE(IWL8000_MODULE_FIRMWARE(IWL8000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL8265_MODULE_FIRMWARE(IWL8265_UCODE_API_MAX));
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018-2021, 2023 Intel Corporation
|
||||
* Copyright (C) 2018-2021, 2023, 2025 Intel Corporation
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/stringify.h>
|
||||
@@ -15,14 +15,7 @@
|
||||
/* Lowest firmware API version supported */
|
||||
#define IWL9000_UCODE_API_MIN 30
|
||||
|
||||
/* NVM versions */
|
||||
#define IWL9000_NVM_VERSION 0x0a1d
|
||||
|
||||
/* Memory offsets and lengths */
|
||||
#define IWL9000_DCCM_OFFSET 0x800000
|
||||
#define IWL9000_DCCM_LEN 0x18000
|
||||
#define IWL9000_DCCM2_OFFSET 0x880000
|
||||
#define IWL9000_DCCM2_LEN 0x8000
|
||||
#define IWL9000_SMEM_OFFSET 0x400000
|
||||
#define IWL9000_SMEM_LEN 0x68000
|
||||
|
||||
@@ -33,7 +26,7 @@
|
||||
#define IWL9260_MODULE_FIRMWARE(api) \
|
||||
IWL9260_FW_PRE "-" __stringify(api) ".ucode"
|
||||
|
||||
static const struct iwl_base_params iwl9000_base_params = {
|
||||
static const struct iwl_family_base_params iwl9000_base = {
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE_32K,
|
||||
.num_of_queues = 31,
|
||||
.max_tfd_queue_size = 256,
|
||||
@@ -43,150 +36,69 @@ static const struct iwl_base_params iwl9000_base_params = {
|
||||
.max_event_log_size = 512,
|
||||
.shadow_reg_enable = true,
|
||||
.pcie_l1_allowed = true,
|
||||
};
|
||||
|
||||
static const struct iwl_ht_params iwl9000_ht_params = {
|
||||
.stbc = true,
|
||||
.ldpc = true,
|
||||
.ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
|
||||
};
|
||||
|
||||
static const struct iwl_tt_params iwl9000_tt_params = {
|
||||
.ct_kill_entry = 115,
|
||||
.ct_kill_exit = 93,
|
||||
.ct_kill_duration = 5,
|
||||
.dynamic_smps_entry = 111,
|
||||
.dynamic_smps_exit = 107,
|
||||
.tx_protection_entry = 112,
|
||||
.tx_protection_exit = 105,
|
||||
.tx_backoff = {
|
||||
{.temperature = 110, .backoff = 200},
|
||||
{.temperature = 111, .backoff = 600},
|
||||
{.temperature = 112, .backoff = 1200},
|
||||
{.temperature = 113, .backoff = 2000},
|
||||
{.temperature = 114, .backoff = 4000},
|
||||
.smem_offset = IWL9000_SMEM_OFFSET,
|
||||
.smem_len = IWL9000_SMEM_LEN,
|
||||
.features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
|
||||
.apmg_not_supported = true,
|
||||
.mac_addr_from_csr = 0x380,
|
||||
.min_umac_error_event_table = 0x800000,
|
||||
.d3_debug_data_base_addr = 0x401000,
|
||||
.d3_debug_data_length = 92 * 1024,
|
||||
.nvm_hw_section_num = 10,
|
||||
.mon_smem_regs = {
|
||||
.write_ptr = {
|
||||
.addr = LDBG_M2S_BUF_WPTR,
|
||||
.mask = LDBG_M2S_BUF_WPTR_VAL_MSK,
|
||||
},
|
||||
.cycle_cnt = {
|
||||
.addr = LDBG_M2S_BUF_WRAP_CNT,
|
||||
.mask = LDBG_M2S_BUF_WRAP_CNT_VAL_MSK,
|
||||
},
|
||||
},
|
||||
.support_ct_kill = true,
|
||||
.support_dynamic_smps = true,
|
||||
.support_tx_protection = true,
|
||||
.support_tx_backoff = true,
|
||||
.mon_dram_regs = {
|
||||
.write_ptr = {
|
||||
.addr = MON_BUFF_WRPTR_VER2,
|
||||
.mask = 0xffffffff,
|
||||
},
|
||||
.cycle_cnt = {
|
||||
.addr = MON_BUFF_CYCLE_CNT_VER2,
|
||||
.mask = 0xffffffff,
|
||||
},
|
||||
},
|
||||
.ucode_api_max = IWL9000_UCODE_API_MAX,
|
||||
.ucode_api_min = IWL9000_UCODE_API_MIN,
|
||||
};
|
||||
|
||||
#define IWL_DEVICE_9000 \
|
||||
.ucode_api_max = IWL9000_UCODE_API_MAX, \
|
||||
.ucode_api_min = IWL9000_UCODE_API_MIN, \
|
||||
.led_mode = IWL_LED_RF_STATE, \
|
||||
.nvm_hw_section_num = 10, \
|
||||
.non_shared_ant = ANT_B, \
|
||||
.dccm_offset = IWL9000_DCCM_OFFSET, \
|
||||
.dccm_len = IWL9000_DCCM_LEN, \
|
||||
.dccm2_offset = IWL9000_DCCM2_OFFSET, \
|
||||
.dccm2_len = IWL9000_DCCM2_LEN, \
|
||||
.smem_offset = IWL9000_SMEM_OFFSET, \
|
||||
.smem_len = IWL9000_SMEM_LEN, \
|
||||
.features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, \
|
||||
.thermal_params = &iwl9000_tt_params, \
|
||||
.apmg_not_supported = true, \
|
||||
.num_rbds = 512, \
|
||||
.vht_mu_mimo_supported = true, \
|
||||
.mac_addr_from_csr = 0x380, \
|
||||
.nvm_type = IWL_NVM_EXT, \
|
||||
.dbgc_supported = true, \
|
||||
.min_umac_error_event_table = 0x800000, \
|
||||
.d3_debug_data_base_addr = 0x401000, \
|
||||
.d3_debug_data_length = 92 * 1024, \
|
||||
.ht_params = &iwl9000_ht_params, \
|
||||
.nvm_ver = IWL9000_NVM_VERSION, \
|
||||
.mon_smem_regs = { \
|
||||
.write_ptr = { \
|
||||
.addr = LDBG_M2S_BUF_WPTR, \
|
||||
.mask = LDBG_M2S_BUF_WPTR_VAL_MSK, \
|
||||
}, \
|
||||
.cycle_cnt = { \
|
||||
.addr = LDBG_M2S_BUF_WRAP_CNT, \
|
||||
.mask = LDBG_M2S_BUF_WRAP_CNT_VAL_MSK, \
|
||||
}, \
|
||||
}, \
|
||||
.mon_dram_regs = { \
|
||||
.write_ptr = { \
|
||||
.addr = MON_BUFF_WRPTR_VER2, \
|
||||
.mask = 0xffffffff, \
|
||||
}, \
|
||||
.cycle_cnt = { \
|
||||
.addr = MON_BUFF_CYCLE_CNT_VER2, \
|
||||
.mask = 0xffffffff, \
|
||||
}, \
|
||||
}
|
||||
|
||||
const struct iwl_cfg_trans_params iwl9000_trans_cfg = {
|
||||
const struct iwl_mac_cfg iwl9000_mac_cfg = {
|
||||
.device_family = IWL_DEVICE_FAMILY_9000,
|
||||
.base_params = &iwl9000_base_params,
|
||||
.base = &iwl9000_base,
|
||||
.mq_rx_supported = true,
|
||||
.rf_id = true,
|
||||
};
|
||||
|
||||
const struct iwl_cfg_trans_params iwl9560_trans_cfg = {
|
||||
const struct iwl_mac_cfg iwl9560_mac_cfg = {
|
||||
.device_family = IWL_DEVICE_FAMILY_9000,
|
||||
.base_params = &iwl9000_base_params,
|
||||
.base = &iwl9000_base,
|
||||
.mq_rx_supported = true,
|
||||
.rf_id = true,
|
||||
.integrated = true,
|
||||
.xtal_latency = 650,
|
||||
};
|
||||
|
||||
const struct iwl_cfg_trans_params iwl9560_long_latency_trans_cfg = {
|
||||
const struct iwl_mac_cfg iwl9560_long_latency_mac_cfg = {
|
||||
.device_family = IWL_DEVICE_FAMILY_9000,
|
||||
.base_params = &iwl9000_base_params,
|
||||
.base = &iwl9000_base,
|
||||
.mq_rx_supported = true,
|
||||
.rf_id = true,
|
||||
.integrated = true,
|
||||
.xtal_latency = 2820,
|
||||
};
|
||||
|
||||
const struct iwl_cfg_trans_params iwl9560_shared_clk_trans_cfg = {
|
||||
const struct iwl_mac_cfg iwl9560_shared_clk_mac_cfg = {
|
||||
.device_family = IWL_DEVICE_FAMILY_9000,
|
||||
.base_params = &iwl9000_base_params,
|
||||
.base = &iwl9000_base,
|
||||
.mq_rx_supported = true,
|
||||
.rf_id = true,
|
||||
.integrated = true,
|
||||
.xtal_latency = 670,
|
||||
.extra_phy_cfg_flags = FW_PHY_CFG_SHARED_CLK
|
||||
};
|
||||
|
||||
const char iwl9162_name[] = "Intel(R) Wireless-AC 9162";
|
||||
const char iwl9260_name[] = "Intel(R) Wireless-AC 9260";
|
||||
const char iwl9260_1_name[] = "Intel(R) Wireless-AC 9260-1";
|
||||
const char iwl9270_name[] = "Intel(R) Wireless-AC 9270";
|
||||
const char iwl9461_name[] = "Intel(R) Wireless-AC 9461";
|
||||
const char iwl9462_name[] = "Intel(R) Wireless-AC 9462";
|
||||
const char iwl9560_name[] = "Intel(R) Wireless-AC 9560";
|
||||
const char iwl9162_160_name[] = "Intel(R) Wireless-AC 9162 160MHz";
|
||||
const char iwl9260_160_name[] = "Intel(R) Wireless-AC 9260 160MHz";
|
||||
const char iwl9270_160_name[] = "Intel(R) Wireless-AC 9270 160MHz";
|
||||
const char iwl9461_160_name[] = "Intel(R) Wireless-AC 9461 160MHz";
|
||||
const char iwl9462_160_name[] = "Intel(R) Wireless-AC 9462 160MHz";
|
||||
const char iwl9560_160_name[] = "Intel(R) Wireless-AC 9560 160MHz";
|
||||
|
||||
const char iwl9260_killer_1550_name[] =
|
||||
"Killer (R) Wireless-AC 1550 Wireless Network Adapter (9260NGW) 160MHz";
|
||||
const char iwl9560_killer_1550i_name[] =
|
||||
"Killer (R) Wireless-AC 1550i Wireless Network Adapter (9560NGW)";
|
||||
const char iwl9560_killer_1550i_160_name[] =
|
||||
"Killer(R) Wireless-AC 1550i Wireless Network Adapter (9560NGW) 160MHz";
|
||||
const char iwl9560_killer_1550s_name[] =
|
||||
"Killer (R) Wireless-AC 1550s Wireless Network Adapter (9560NGW)";
|
||||
const char iwl9560_killer_1550s_160_name[] =
|
||||
"Killer(R) Wireless-AC 1550s Wireless Network Adapter (9560D2W) 160MHz";
|
||||
|
||||
const struct iwl_cfg iwl9260_2ac_cfg = {
|
||||
.fw_name_pre = IWL9260_FW_PRE,
|
||||
IWL_DEVICE_9000,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl9560_2ac_cfg_soc = {
|
||||
.fw_name_pre = IWL9000_FW_PRE,
|
||||
IWL_DEVICE_9000,
|
||||
};
|
||||
|
||||
MODULE_FIRMWARE(IWL9000_MODULE_FIRMWARE(IWL9000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL9260_MODULE_FIRMWARE(IWL9000_UCODE_API_MAX));
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018-2024 Intel Corporation
|
||||
* Copyright (C) 2018-2025 Intel Corporation
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/stringify.h>
|
||||
@@ -13,61 +13,13 @@
|
||||
#define IWL_AX210_UCODE_API_MAX 89
|
||||
|
||||
/* Lowest firmware API version supported */
|
||||
#define IWL_AX210_UCODE_API_MIN 77
|
||||
|
||||
/* NVM versions */
|
||||
#define IWL_AX210_NVM_VERSION 0x0a1d
|
||||
#define IWL_AX210_UCODE_API_MIN 89
|
||||
|
||||
/* Memory offsets and lengths */
|
||||
#define IWL_AX210_DCCM_OFFSET 0x800000 /* LMAC1 */
|
||||
#define IWL_AX210_DCCM_LEN 0x10000 /* LMAC1 */
|
||||
#define IWL_AX210_DCCM2_OFFSET 0x880000
|
||||
#define IWL_AX210_DCCM2_LEN 0x8000
|
||||
#define IWL_AX210_SMEM_OFFSET 0x400000
|
||||
#define IWL_AX210_SMEM_LEN 0xD0000
|
||||
|
||||
#define IWL_SO_A_JF_B_FW_PRE "iwlwifi-so-a0-jf-b0"
|
||||
#define IWL_SO_A_HR_B_FW_PRE "iwlwifi-so-a0-hr-b0"
|
||||
#define IWL_SO_A_GF_A_FW_PRE "iwlwifi-so-a0-gf-a0"
|
||||
#define IWL_TY_A_GF_A_FW_PRE "iwlwifi-ty-a0-gf-a0"
|
||||
#define IWL_SO_A_GF4_A_FW_PRE "iwlwifi-so-a0-gf4-a0"
|
||||
#define IWL_SO_A_MR_A_FW_PRE "iwlwifi-so-a0-mr-a0"
|
||||
#define IWL_MA_A_HR_B_FW_PRE "iwlwifi-ma-a0-hr-b0"
|
||||
#define IWL_MA_A_GF_A_FW_PRE "iwlwifi-ma-a0-gf-a0"
|
||||
#define IWL_MA_A_GF4_A_FW_PRE "iwlwifi-ma-a0-gf4-a0"
|
||||
#define IWL_MA_A_MR_A_FW_PRE "iwlwifi-ma-a0-mr-a0"
|
||||
#define IWL_MA_B_HR_B_FW_PRE "iwlwifi-ma-b0-hr-b0"
|
||||
#define IWL_MA_B_GF_A_FW_PRE "iwlwifi-ma-b0-gf-a0"
|
||||
#define IWL_MA_B_GF4_A_FW_PRE "iwlwifi-ma-b0-gf4-a0"
|
||||
#define IWL_MA_B_MR_A_FW_PRE "iwlwifi-ma-b0-mr-a0"
|
||||
|
||||
#define IWL_SO_A_JF_B_MODULE_FIRMWARE(api) \
|
||||
IWL_SO_A_JF_B_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_SO_A_HR_B_MODULE_FIRMWARE(api) \
|
||||
IWL_SO_A_HR_B_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_SO_A_GF_A_MODULE_FIRMWARE(api) \
|
||||
IWL_SO_A_GF_A_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_TY_A_GF_A_MODULE_FIRMWARE(api) \
|
||||
IWL_TY_A_GF_A_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_MA_A_HR_B_FW_MODULE_FIRMWARE(api) \
|
||||
IWL_MA_A_HR_B_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_MA_A_GF_A_FW_MODULE_FIRMWARE(api) \
|
||||
IWL_MA_A_GF_A_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_MA_A_GF4_A_FW_MODULE_FIRMWARE(api) \
|
||||
IWL_MA_A_GF4_A_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_MA_A_MR_A_FW_MODULE_FIRMWARE(api) \
|
||||
IWL_MA_A_MR_A_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_MA_B_HR_B_FW_MODULE_FIRMWARE(api) \
|
||||
IWL_MA_B_HR_B_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_MA_B_GF_A_FW_MODULE_FIRMWARE(api) \
|
||||
IWL_MA_B_GF_A_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_MA_B_GF4_A_FW_MODULE_FIRMWARE(api) \
|
||||
IWL_MA_B_GF4_A_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_MA_B_MR_A_FW_MODULE_FIRMWARE(api) \
|
||||
IWL_MA_B_MR_A_FW_PRE "-" __stringify(api) ".ucode"
|
||||
|
||||
static const struct iwl_base_params iwl_ax210_base_params = {
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE_32K,
|
||||
static const struct iwl_family_base_params iwl_ax210_base = {
|
||||
.num_of_queues = 512,
|
||||
.max_tfd_queue_size = 65536,
|
||||
.shadow_ram_support = true,
|
||||
@@ -76,74 +28,60 @@ static const struct iwl_base_params iwl_ax210_base_params = {
|
||||
.max_event_log_size = 512,
|
||||
.shadow_reg_enable = true,
|
||||
.pcie_l1_allowed = true,
|
||||
.smem_offset = IWL_AX210_SMEM_OFFSET,
|
||||
.smem_len = IWL_AX210_SMEM_LEN,
|
||||
.features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
|
||||
.apmg_not_supported = true,
|
||||
.mac_addr_from_csr = 0x380,
|
||||
.min_umac_error_event_table = 0x400000,
|
||||
.d3_debug_data_base_addr = 0x401000,
|
||||
.d3_debug_data_length = 60 * 1024,
|
||||
.mon_smem_regs = {
|
||||
.write_ptr = {
|
||||
.addr = LDBG_M2S_BUF_WPTR,
|
||||
.mask = LDBG_M2S_BUF_WPTR_VAL_MSK,
|
||||
},
|
||||
.cycle_cnt = {
|
||||
.addr = LDBG_M2S_BUF_WRAP_CNT,
|
||||
.mask = LDBG_M2S_BUF_WRAP_CNT_VAL_MSK,
|
||||
},
|
||||
},
|
||||
.min_txq_size = 128,
|
||||
.gp2_reg_addr = 0xd02c68,
|
||||
.min_ba_txq_size = IWL_DEFAULT_QUEUE_SIZE_HE,
|
||||
.mon_dram_regs = {
|
||||
.write_ptr = {
|
||||
.addr = DBGC_CUR_DBGBUF_STATUS,
|
||||
.mask = DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK,
|
||||
},
|
||||
.cycle_cnt = {
|
||||
.addr = DBGC_DBGBUF_WRAP_AROUND,
|
||||
.mask = 0xffffffff,
|
||||
},
|
||||
.cur_frag = {
|
||||
.addr = DBGC_CUR_DBGBUF_STATUS,
|
||||
.mask = DBGC_CUR_DBGBUF_STATUS_IDX_MSK,
|
||||
},
|
||||
},
|
||||
.ucode_api_min = IWL_AX210_UCODE_API_MIN,
|
||||
.ucode_api_max = IWL_AX210_UCODE_API_MAX,
|
||||
};
|
||||
|
||||
#define IWL_DEVICE_AX210_COMMON \
|
||||
.ucode_api_min = IWL_AX210_UCODE_API_MIN, \
|
||||
.led_mode = IWL_LED_RF_STATE, \
|
||||
.nvm_hw_section_num = 10, \
|
||||
.non_shared_ant = ANT_B, \
|
||||
.dccm_offset = IWL_AX210_DCCM_OFFSET, \
|
||||
.dccm_len = IWL_AX210_DCCM_LEN, \
|
||||
.dccm2_offset = IWL_AX210_DCCM2_OFFSET, \
|
||||
.dccm2_len = IWL_AX210_DCCM2_LEN, \
|
||||
.smem_offset = IWL_AX210_SMEM_OFFSET, \
|
||||
.smem_len = IWL_AX210_SMEM_LEN, \
|
||||
.features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, \
|
||||
.apmg_not_supported = true, \
|
||||
.trans.mq_rx_supported = true, \
|
||||
.vht_mu_mimo_supported = true, \
|
||||
.mac_addr_from_csr = 0x380, \
|
||||
.ht_params = &iwl_22000_ht_params, \
|
||||
.nvm_ver = IWL_AX210_NVM_VERSION, \
|
||||
.trans.rf_id = true, \
|
||||
.trans.gen2 = true, \
|
||||
.nvm_type = IWL_NVM_EXT, \
|
||||
.dbgc_supported = true, \
|
||||
.min_umac_error_event_table = 0x400000, \
|
||||
.d3_debug_data_base_addr = 0x401000, \
|
||||
.d3_debug_data_length = 60 * 1024, \
|
||||
.mon_smem_regs = { \
|
||||
.write_ptr = { \
|
||||
.addr = LDBG_M2S_BUF_WPTR, \
|
||||
.mask = LDBG_M2S_BUF_WPTR_VAL_MSK, \
|
||||
}, \
|
||||
.cycle_cnt = { \
|
||||
.addr = LDBG_M2S_BUF_WRAP_CNT, \
|
||||
.mask = LDBG_M2S_BUF_WRAP_CNT_VAL_MSK, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define IWL_DEVICE_AX210 \
|
||||
IWL_DEVICE_AX210_COMMON, \
|
||||
.ucode_api_max = IWL_AX210_UCODE_API_MAX, \
|
||||
.trans.umac_prph_offset = 0x300000, \
|
||||
.trans.device_family = IWL_DEVICE_FAMILY_AX210, \
|
||||
.trans.base_params = &iwl_ax210_base_params, \
|
||||
.min_txq_size = 128, \
|
||||
.gp2_reg_addr = 0xd02c68, \
|
||||
.min_ba_txq_size = IWL_DEFAULT_QUEUE_SIZE_HE, \
|
||||
.mon_dram_regs = { \
|
||||
.write_ptr = { \
|
||||
.addr = DBGC_CUR_DBGBUF_STATUS, \
|
||||
.mask = DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK, \
|
||||
}, \
|
||||
.cycle_cnt = { \
|
||||
.addr = DBGC_DBGBUF_WRAP_AROUND, \
|
||||
.mask = 0xffffffff, \
|
||||
}, \
|
||||
.cur_frag = { \
|
||||
.addr = DBGC_CUR_DBGBUF_STATUS, \
|
||||
.mask = DBGC_CUR_DBGBUF_STATUS_IDX_MSK, \
|
||||
}, \
|
||||
}
|
||||
|
||||
const struct iwl_cfg_trans_params iwl_so_trans_cfg = {
|
||||
const struct iwl_mac_cfg iwl_ty_mac_cfg = {
|
||||
.mq_rx_supported = true,
|
||||
.rf_id = true,
|
||||
.gen2 = true,
|
||||
.device_family = IWL_DEVICE_FAMILY_AX210,
|
||||
.base_params = &iwl_ax210_base_params,
|
||||
.base = &iwl_ax210_base,
|
||||
.umac_prph_offset = 0x300000,
|
||||
/* TODO: the following values need to be checked */
|
||||
.xtal_latency = 500,
|
||||
};
|
||||
|
||||
const struct iwl_mac_cfg iwl_so_mac_cfg = {
|
||||
.mq_rx_supported = true,
|
||||
.gen2 = true,
|
||||
.device_family = IWL_DEVICE_FAMILY_AX210,
|
||||
.base = &iwl_ax210_base,
|
||||
.umac_prph_offset = 0x300000,
|
||||
.integrated = true,
|
||||
/* TODO: the following values need to be checked */
|
||||
@@ -151,12 +89,11 @@ const struct iwl_cfg_trans_params iwl_so_trans_cfg = {
|
||||
.ltr_delay = IWL_CFG_TRANS_LTR_DELAY_200US,
|
||||
};
|
||||
|
||||
const struct iwl_cfg_trans_params iwl_so_long_latency_trans_cfg = {
|
||||
const struct iwl_mac_cfg iwl_so_long_latency_mac_cfg = {
|
||||
.mq_rx_supported = true,
|
||||
.rf_id = true,
|
||||
.gen2 = true,
|
||||
.device_family = IWL_DEVICE_FAMILY_AX210,
|
||||
.base_params = &iwl_ax210_base_params,
|
||||
.base = &iwl_ax210_base,
|
||||
.umac_prph_offset = 0x300000,
|
||||
.integrated = true,
|
||||
.low_latency_xtal = true,
|
||||
@@ -164,12 +101,11 @@ const struct iwl_cfg_trans_params iwl_so_long_latency_trans_cfg = {
|
||||
.ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US,
|
||||
};
|
||||
|
||||
const struct iwl_cfg_trans_params iwl_so_long_latency_imr_trans_cfg = {
|
||||
const struct iwl_mac_cfg iwl_so_long_latency_imr_mac_cfg = {
|
||||
.mq_rx_supported = true,
|
||||
.rf_id = true,
|
||||
.gen2 = true,
|
||||
.device_family = IWL_DEVICE_FAMILY_AX210,
|
||||
.base_params = &iwl_ax210_base_params,
|
||||
.base = &iwl_ax210_base,
|
||||
.umac_prph_offset = 0x300000,
|
||||
.integrated = true,
|
||||
.low_latency_xtal = true,
|
||||
@@ -178,130 +114,11 @@ const struct iwl_cfg_trans_params iwl_so_long_latency_imr_trans_cfg = {
|
||||
.imr_enabled = true,
|
||||
};
|
||||
|
||||
/*
|
||||
* If the device doesn't support HE, no need to have that many buffers.
|
||||
* AX210 devices can split multiple frames into a single RB, so fewer are
|
||||
* needed; AX210 cannot (but use smaller RBs by default) - these sizes
|
||||
* were picked according to 8 MSDUs inside 256 A-MSDUs in an A-MPDU, with
|
||||
* additional overhead to account for processing time.
|
||||
*/
|
||||
#define IWL_NUM_RBDS_NON_HE 512
|
||||
#define IWL_NUM_RBDS_AX210_HE 4096
|
||||
|
||||
const struct iwl_cfg_trans_params iwl_ma_trans_cfg = {
|
||||
const struct iwl_mac_cfg iwl_ma_mac_cfg = {
|
||||
.device_family = IWL_DEVICE_FAMILY_AX210,
|
||||
.base_params = &iwl_ax210_base_params,
|
||||
.base = &iwl_ax210_base,
|
||||
.mq_rx_supported = true,
|
||||
.rf_id = true,
|
||||
.gen2 = true,
|
||||
.integrated = true,
|
||||
.umac_prph_offset = 0x300000
|
||||
};
|
||||
|
||||
const char iwl_ax211_name[] = "Intel(R) Wi-Fi 6E AX211 160MHz";
|
||||
const char iwl_ax221_name[] = "Intel(R) Wi-Fi 6E AX221 160MHz";
|
||||
const char iwl_ax231_name[] = "Intel(R) Wi-Fi 6E AX231 160MHz";
|
||||
const char iwl_ax411_name[] = "Intel(R) Wi-Fi 6E AX411 160MHz";
|
||||
|
||||
const char iwl_ax210_killer_1675w_name[] =
|
||||
"Killer(R) Wi-Fi 6E AX1675w 160MHz Wireless Network Adapter (210D2W)";
|
||||
const char iwl_ax210_killer_1675x_name[] =
|
||||
"Killer(R) Wi-Fi 6E AX1675x 160MHz Wireless Network Adapter (210NGW)";
|
||||
const char iwl_ax211_killer_1675s_name[] =
|
||||
"Killer(R) Wi-Fi 6E AX1675s 160MHz Wireless Network Adapter (211NGW)";
|
||||
const char iwl_ax211_killer_1675i_name[] =
|
||||
"Killer(R) Wi-Fi 6E AX1675i 160MHz Wireless Network Adapter (211NGW)";
|
||||
const char iwl_ax411_killer_1690s_name[] =
|
||||
"Killer(R) Wi-Fi 6E AX1690s 160MHz Wireless Network Adapter (411D2W)";
|
||||
const char iwl_ax411_killer_1690i_name[] =
|
||||
"Killer(R) Wi-Fi 6E AX1690i 160MHz Wireless Network Adapter (411NGW)";
|
||||
|
||||
const struct iwl_cfg iwlax210_2ax_cfg_so_jf_b0 = {
|
||||
.name = "Intel(R) Wireless-AC 9560 160MHz",
|
||||
.fw_name_pre = IWL_SO_A_JF_B_FW_PRE,
|
||||
IWL_DEVICE_AX210,
|
||||
.num_rbds = IWL_NUM_RBDS_NON_HE,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwlax211_2ax_cfg_so_gf_a0 = {
|
||||
.name = iwl_ax211_name,
|
||||
.fw_name_pre = IWL_SO_A_GF_A_FW_PRE,
|
||||
.uhb_supported = true,
|
||||
IWL_DEVICE_AX210,
|
||||
.num_rbds = IWL_NUM_RBDS_AX210_HE,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwlax211_2ax_cfg_so_gf_a0_long = {
|
||||
.name = iwl_ax211_name,
|
||||
.fw_name_pre = IWL_SO_A_GF_A_FW_PRE,
|
||||
.uhb_supported = true,
|
||||
IWL_DEVICE_AX210,
|
||||
.num_rbds = IWL_NUM_RBDS_AX210_HE,
|
||||
.trans.xtal_latency = 12000,
|
||||
.trans.low_latency_xtal = true,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwlax210_2ax_cfg_ty_gf_a0 = {
|
||||
.name = "Intel(R) Wi-Fi 6 AX210 160MHz",
|
||||
.fw_name_pre = IWL_TY_A_GF_A_FW_PRE,
|
||||
.uhb_supported = true,
|
||||
IWL_DEVICE_AX210,
|
||||
.num_rbds = IWL_NUM_RBDS_AX210_HE,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwlax411_2ax_cfg_so_gf4_a0 = {
|
||||
.name = iwl_ax411_name,
|
||||
.fw_name_pre = IWL_SO_A_GF4_A_FW_PRE,
|
||||
.uhb_supported = true,
|
||||
IWL_DEVICE_AX210,
|
||||
.num_rbds = IWL_NUM_RBDS_AX210_HE,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwlax411_2ax_cfg_so_gf4_a0_long = {
|
||||
.name = iwl_ax411_name,
|
||||
.fw_name_pre = IWL_SO_A_GF4_A_FW_PRE,
|
||||
.uhb_supported = true,
|
||||
IWL_DEVICE_AX210,
|
||||
.num_rbds = IWL_NUM_RBDS_AX210_HE,
|
||||
.trans.xtal_latency = 12000,
|
||||
.trans.low_latency_xtal = true,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl_cfg_so_a0_ms_a0 = {
|
||||
.fw_name_pre = IWL_SO_A_MR_A_FW_PRE,
|
||||
.uhb_supported = false,
|
||||
IWL_DEVICE_AX210,
|
||||
.num_rbds = IWL_NUM_RBDS_AX210_HE,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl_cfg_ma = {
|
||||
.fw_name_mac = "ma",
|
||||
.uhb_supported = true,
|
||||
IWL_DEVICE_AX210,
|
||||
.num_rbds = IWL_NUM_RBDS_AX210_HE,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl_cfg_so_a0_hr_a0 = {
|
||||
.fw_name_pre = IWL_SO_A_HR_B_FW_PRE,
|
||||
IWL_DEVICE_AX210,
|
||||
.num_rbds = IWL_NUM_RBDS_AX210_HE,
|
||||
};
|
||||
|
||||
MODULE_FIRMWARE(IWL_SO_A_JF_B_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_SO_A_HR_B_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_SO_A_GF_A_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_TY_A_GF_A_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_MA_A_HR_B_FW_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_MA_A_GF_A_FW_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_MA_A_GF4_A_FW_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_MA_A_MR_A_FW_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_MA_B_HR_B_FW_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_MA_B_GF_A_FW_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_MA_B_GF4_A_FW_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_MA_B_MR_A_FW_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX));
|
||||
|
||||
MODULE_FIRMWARE("iwlwifi-so-a0-gf-a0.pnvm");
|
||||
MODULE_FIRMWARE("iwlwifi-so-a0-gf4-a0.pnvm");
|
||||
MODULE_FIRMWARE("iwlwifi-ty-a0-gf-a0.pnvm");
|
||||
MODULE_FIRMWARE("iwlwifi-ma-b0-gf-a0.pnvm");
|
||||
MODULE_FIRMWARE("iwlwifi-ma-b0-gf4-a0.pnvm");
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018-2024 Intel Corporation
|
||||
* Copyright (C) 2018-2025 Intel Corporation
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/stringify.h>
|
||||
@@ -10,50 +10,22 @@
|
||||
#include "fw/api/txq.h"
|
||||
|
||||
/* Highest firmware API version supported */
|
||||
#define IWL_BZ_UCODE_API_MAX 92
|
||||
#define IWL_BZ_UCODE_API_MAX 102
|
||||
|
||||
/* Lowest firmware API version supported */
|
||||
#define IWL_BZ_UCODE_API_MIN 90
|
||||
|
||||
/* NVM versions */
|
||||
#define IWL_BZ_NVM_VERSION 0x0a1d
|
||||
#define IWL_BZ_UCODE_API_MIN 98
|
||||
|
||||
/* Memory offsets and lengths */
|
||||
#define IWL_BZ_DCCM_OFFSET 0x800000 /* LMAC1 */
|
||||
#define IWL_BZ_DCCM_LEN 0x10000 /* LMAC1 */
|
||||
#define IWL_BZ_DCCM2_OFFSET 0x880000
|
||||
#define IWL_BZ_DCCM2_LEN 0x8000
|
||||
#define IWL_BZ_SMEM_OFFSET 0x400000
|
||||
#define IWL_BZ_SMEM_LEN 0xD0000
|
||||
|
||||
#define IWL_BZ_A_HR_B_FW_PRE "iwlwifi-bz-a0-hr-b0"
|
||||
#define IWL_BZ_A_GF_A_FW_PRE "iwlwifi-bz-a0-gf-a0"
|
||||
#define IWL_BZ_A_GF4_A_FW_PRE "iwlwifi-bz-a0-gf4-a0"
|
||||
#define IWL_BZ_A_FM_B_FW_PRE "iwlwifi-bz-a0-fm-b0"
|
||||
#define IWL_BZ_A_FM_C_FW_PRE "iwlwifi-bz-a0-fm-c0"
|
||||
#define IWL_BZ_A_FM4_B_FW_PRE "iwlwifi-bz-a0-fm4-b0"
|
||||
#define IWL_GL_B_FM_B_FW_PRE "iwlwifi-gl-b0-fm-b0"
|
||||
#define IWL_GL_C_FM_C_FW_PRE "iwlwifi-gl-c0-fm-c0"
|
||||
|
||||
#define IWL_BZ_A_HR_B_MODULE_FIRMWARE(api) \
|
||||
IWL_BZ_A_HR_B_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_BZ_A_GF_A_MODULE_FIRMWARE(api) \
|
||||
IWL_BZ_A_GF_A_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_BZ_A_GF4_A_MODULE_FIRMWARE(api) \
|
||||
IWL_BZ_A_GF4_A_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_BZ_A_FM_B_MODULE_FIRMWARE(api) \
|
||||
IWL_BZ_A_FM_B_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_BZ_A_FM_C_MODULE_FIRMWARE(api) \
|
||||
IWL_BZ_A_FM_C_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_BZ_A_FM4_B_MODULE_FIRMWARE(api) \
|
||||
IWL_BZ_A_FM4_B_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_GL_B_FM_B_MODULE_FIRMWARE(api) \
|
||||
IWL_GL_B_FM_B_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_GL_C_FM_C_MODULE_FIRMWARE(api) \
|
||||
IWL_GL_C_FM_C_FW_PRE "-" __stringify(api) ".ucode"
|
||||
|
||||
static const struct iwl_base_params iwl_bz_base_params = {
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE_32K,
|
||||
static const struct iwl_family_base_params iwl_bz_base = {
|
||||
.num_of_queues = 512,
|
||||
.max_tfd_queue_size = 65536,
|
||||
.shadow_ram_support = true,
|
||||
@@ -62,84 +34,55 @@ static const struct iwl_base_params iwl_bz_base_params = {
|
||||
.max_event_log_size = 512,
|
||||
.shadow_reg_enable = true,
|
||||
.pcie_l1_allowed = true,
|
||||
.smem_offset = IWL_BZ_SMEM_OFFSET,
|
||||
.smem_len = IWL_BZ_SMEM_LEN,
|
||||
.apmg_not_supported = true,
|
||||
.mac_addr_from_csr = 0x30,
|
||||
.min_umac_error_event_table = 0xD0000,
|
||||
.d3_debug_data_base_addr = 0x401000,
|
||||
.d3_debug_data_length = 60 * 1024,
|
||||
.mon_smem_regs = {
|
||||
.write_ptr = {
|
||||
.addr = LDBG_M2S_BUF_WPTR,
|
||||
.mask = LDBG_M2S_BUF_WPTR_VAL_MSK,
|
||||
},
|
||||
.cycle_cnt = {
|
||||
.addr = LDBG_M2S_BUF_WRAP_CNT,
|
||||
.mask = LDBG_M2S_BUF_WRAP_CNT_VAL_MSK,
|
||||
},
|
||||
},
|
||||
.min_txq_size = 128,
|
||||
.gp2_reg_addr = 0xd02c68,
|
||||
.min_ba_txq_size = IWL_DEFAULT_QUEUE_SIZE_EHT,
|
||||
.mon_dram_regs = {
|
||||
.write_ptr = {
|
||||
.addr = DBGC_CUR_DBGBUF_STATUS,
|
||||
.mask = DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK,
|
||||
},
|
||||
.cycle_cnt = {
|
||||
.addr = DBGC_DBGBUF_WRAP_AROUND,
|
||||
.mask = 0xffffffff,
|
||||
},
|
||||
.cur_frag = {
|
||||
.addr = DBGC_CUR_DBGBUF_STATUS,
|
||||
.mask = DBGC_CUR_DBGBUF_STATUS_IDX_MSK,
|
||||
},
|
||||
},
|
||||
.mon_dbgi_regs = {
|
||||
.write_ptr = {
|
||||
.addr = DBGI_SRAM_FIFO_POINTERS,
|
||||
.mask = DBGI_SRAM_FIFO_POINTERS_WR_PTR_MSK,
|
||||
},
|
||||
},
|
||||
.features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
|
||||
.ucode_api_max = IWL_BZ_UCODE_API_MAX,
|
||||
.ucode_api_min = IWL_BZ_UCODE_API_MIN,
|
||||
};
|
||||
|
||||
#define IWL_DEVICE_BZ_COMMON \
|
||||
.ucode_api_max = IWL_BZ_UCODE_API_MAX, \
|
||||
.ucode_api_min = IWL_BZ_UCODE_API_MIN, \
|
||||
.led_mode = IWL_LED_RF_STATE, \
|
||||
.nvm_hw_section_num = 10, \
|
||||
.non_shared_ant = ANT_B, \
|
||||
.dccm_offset = IWL_BZ_DCCM_OFFSET, \
|
||||
.dccm_len = IWL_BZ_DCCM_LEN, \
|
||||
.dccm2_offset = IWL_BZ_DCCM2_OFFSET, \
|
||||
.dccm2_len = IWL_BZ_DCCM2_LEN, \
|
||||
.smem_offset = IWL_BZ_SMEM_OFFSET, \
|
||||
.smem_len = IWL_BZ_SMEM_LEN, \
|
||||
.apmg_not_supported = true, \
|
||||
.trans.mq_rx_supported = true, \
|
||||
.vht_mu_mimo_supported = true, \
|
||||
.mac_addr_from_csr = 0x30, \
|
||||
.nvm_ver = IWL_BZ_NVM_VERSION, \
|
||||
.trans.rf_id = true, \
|
||||
.trans.gen2 = true, \
|
||||
.nvm_type = IWL_NVM_EXT, \
|
||||
.dbgc_supported = true, \
|
||||
.min_umac_error_event_table = 0xD0000, \
|
||||
.d3_debug_data_base_addr = 0x401000, \
|
||||
.d3_debug_data_length = 60 * 1024, \
|
||||
.mon_smem_regs = { \
|
||||
.write_ptr = { \
|
||||
.addr = LDBG_M2S_BUF_WPTR, \
|
||||
.mask = LDBG_M2S_BUF_WPTR_VAL_MSK, \
|
||||
}, \
|
||||
.cycle_cnt = { \
|
||||
.addr = LDBG_M2S_BUF_WRAP_CNT, \
|
||||
.mask = LDBG_M2S_BUF_WRAP_CNT_VAL_MSK, \
|
||||
}, \
|
||||
}, \
|
||||
.trans.umac_prph_offset = 0x300000, \
|
||||
.trans.device_family = IWL_DEVICE_FAMILY_BZ, \
|
||||
.trans.base_params = &iwl_bz_base_params, \
|
||||
.min_txq_size = 128, \
|
||||
.gp2_reg_addr = 0xd02c68, \
|
||||
.min_ba_txq_size = IWL_DEFAULT_QUEUE_SIZE_EHT, \
|
||||
.mon_dram_regs = { \
|
||||
.write_ptr = { \
|
||||
.addr = DBGC_CUR_DBGBUF_STATUS, \
|
||||
.mask = DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK, \
|
||||
}, \
|
||||
.cycle_cnt = { \
|
||||
.addr = DBGC_DBGBUF_WRAP_AROUND, \
|
||||
.mask = 0xffffffff, \
|
||||
}, \
|
||||
.cur_frag = { \
|
||||
.addr = DBGC_CUR_DBGBUF_STATUS, \
|
||||
.mask = DBGC_CUR_DBGBUF_STATUS_IDX_MSK, \
|
||||
}, \
|
||||
}, \
|
||||
.mon_dbgi_regs = { \
|
||||
.write_ptr = { \
|
||||
.addr = DBGI_SRAM_FIFO_POINTERS, \
|
||||
.mask = DBGI_SRAM_FIFO_POINTERS_WR_PTR_MSK, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define IWL_DEVICE_BZ \
|
||||
IWL_DEVICE_BZ_COMMON, \
|
||||
.ht_params = &iwl_22000_ht_params
|
||||
|
||||
/*
|
||||
* This size was picked according to 8 MSDUs inside 512 A-MSDUs in an
|
||||
* A-MPDU, with additional overhead to account for processing time.
|
||||
*/
|
||||
#define IWL_NUM_RBDS_BZ_EHT (512 * 16)
|
||||
|
||||
const struct iwl_cfg_trans_params iwl_bz_trans_cfg = {
|
||||
const struct iwl_mac_cfg iwl_bz_mac_cfg = {
|
||||
.device_family = IWL_DEVICE_FAMILY_BZ,
|
||||
.base_params = &iwl_bz_base_params,
|
||||
.base = &iwl_bz_base,
|
||||
.mq_rx_supported = true,
|
||||
.rf_id = true,
|
||||
.gen2 = true,
|
||||
.integrated = true,
|
||||
.umac_prph_offset = 0x300000,
|
||||
@@ -148,35 +91,18 @@ const struct iwl_cfg_trans_params iwl_bz_trans_cfg = {
|
||||
.ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US,
|
||||
};
|
||||
|
||||
const char iwl_bz_name[] = "Intel(R) TBD Bz device";
|
||||
const char iwl_fm_name[] = "Intel(R) Wi-Fi 7 BE201 320MHz";
|
||||
const char iwl_gl_name[] = "Intel(R) Wi-Fi 7 BE200 320MHz";
|
||||
const char iwl_mtp_name[] = "Intel(R) Wi-Fi 7 BE202 160MHz";
|
||||
|
||||
const struct iwl_cfg iwl_cfg_bz = {
|
||||
.fw_name_mac = "bz",
|
||||
.uhb_supported = true,
|
||||
IWL_DEVICE_BZ,
|
||||
.features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
|
||||
.num_rbds = IWL_NUM_RBDS_BZ_EHT,
|
||||
const struct iwl_mac_cfg iwl_gl_mac_cfg = {
|
||||
.device_family = IWL_DEVICE_FAMILY_BZ,
|
||||
.base = &iwl_bz_base,
|
||||
.mq_rx_supported = true,
|
||||
.gen2 = true,
|
||||
.umac_prph_offset = 0x300000,
|
||||
.xtal_latency = 12000,
|
||||
.low_latency_xtal = true,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl_cfg_gl = {
|
||||
.fw_name_mac = "gl",
|
||||
.uhb_supported = true,
|
||||
IWL_DEVICE_BZ,
|
||||
.features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
|
||||
.num_rbds = IWL_NUM_RBDS_BZ_EHT,
|
||||
};
|
||||
|
||||
|
||||
MODULE_FIRMWARE(IWL_BZ_A_HR_B_MODULE_FIRMWARE(IWL_BZ_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_BZ_A_GF_A_MODULE_FIRMWARE(IWL_BZ_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_BZ_A_GF4_A_MODULE_FIRMWARE(IWL_BZ_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_BZ_A_FM_B_MODULE_FIRMWARE(IWL_BZ_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_BZ_A_FM_C_MODULE_FIRMWARE(IWL_BZ_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_BZ_A_FM4_B_MODULE_FIRMWARE(IWL_BZ_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_GL_B_FM_B_MODULE_FIRMWARE(IWL_BZ_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_GL_C_FM_C_MODULE_FIRMWARE(IWL_BZ_UCODE_API_MAX));
|
||||
|
||||
MODULE_FIRMWARE("iwlwifi-gl-c0-fm-c0.pnvm");
|
||||
IWL_FW_AND_PNVM(IWL_BZ_A_FM_B_FW_PRE, IWL_BZ_UCODE_API_MAX);
|
||||
IWL_FW_AND_PNVM(IWL_BZ_A_FM_C_FW_PRE, IWL_BZ_UCODE_API_MAX);
|
||||
IWL_FW_AND_PNVM(IWL_BZ_A_FM4_B_FW_PRE, IWL_BZ_UCODE_API_MAX);
|
||||
IWL_FW_AND_PNVM(IWL_GL_B_FM_B_FW_PRE, IWL_BZ_UCODE_API_MAX);
|
||||
IWL_FW_AND_PNVM(IWL_GL_C_FM_C_FW_PRE, IWL_BZ_UCODE_API_MAX);
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2024-2025 Intel Corporation
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/stringify.h>
|
||||
#include "iwl-config.h"
|
||||
#include "iwl-prph.h"
|
||||
#include "fw/api/txq.h"
|
||||
|
||||
/* Highest firmware API version supported */
|
||||
#define IWL_DR_UCODE_API_MAX 102
|
||||
|
||||
/* Lowest firmware API version supported */
|
||||
#define IWL_DR_UCODE_API_MIN 98
|
||||
|
||||
/* Memory offsets and lengths */
|
||||
#define IWL_DR_SMEM_OFFSET 0x400000
|
||||
#define IWL_DR_SMEM_LEN 0xD0000
|
||||
|
||||
#define IWL_DR_A_PE_A_FW_PRE "iwlwifi-dr-a0-pe-a0"
|
||||
|
||||
#define IWL_DR_A_PE_A_FW_MODULE_FIRMWARE(api) \
|
||||
IWL_DR_A_PE_A_FW_PRE "-" __stringify(api) ".ucode"
|
||||
|
||||
static const struct iwl_family_base_params iwl_dr_base = {
|
||||
.num_of_queues = 512,
|
||||
.max_tfd_queue_size = 65536,
|
||||
.shadow_ram_support = true,
|
||||
.led_compensation = 57,
|
||||
.wd_timeout = IWL_LONG_WD_TIMEOUT,
|
||||
.max_event_log_size = 512,
|
||||
.shadow_reg_enable = true,
|
||||
.pcie_l1_allowed = true,
|
||||
.smem_offset = IWL_DR_SMEM_OFFSET,
|
||||
.smem_len = IWL_DR_SMEM_LEN,
|
||||
.apmg_not_supported = true,
|
||||
.mac_addr_from_csr = 0x30,
|
||||
.min_umac_error_event_table = 0xD0000,
|
||||
.d3_debug_data_base_addr = 0x401000,
|
||||
.d3_debug_data_length = 60 * 1024,
|
||||
.mon_smem_regs = {
|
||||
.write_ptr = {
|
||||
.addr = LDBG_M2S_BUF_WPTR,
|
||||
.mask = LDBG_M2S_BUF_WPTR_VAL_MSK,
|
||||
},
|
||||
.cycle_cnt = {
|
||||
.addr = LDBG_M2S_BUF_WRAP_CNT,
|
||||
.mask = LDBG_M2S_BUF_WRAP_CNT_VAL_MSK,
|
||||
},
|
||||
},
|
||||
.min_txq_size = 128,
|
||||
.gp2_reg_addr = 0xd02c68,
|
||||
.min_ba_txq_size = IWL_DEFAULT_QUEUE_SIZE_EHT,
|
||||
.mon_dram_regs = {
|
||||
.write_ptr = {
|
||||
.addr = DBGC_CUR_DBGBUF_STATUS,
|
||||
.mask = DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK,
|
||||
},
|
||||
.cycle_cnt = {
|
||||
.addr = DBGC_DBGBUF_WRAP_AROUND,
|
||||
.mask = 0xffffffff,
|
||||
},
|
||||
.cur_frag = {
|
||||
.addr = DBGC_CUR_DBGBUF_STATUS,
|
||||
.mask = DBGC_CUR_DBGBUF_STATUS_IDX_MSK,
|
||||
},
|
||||
},
|
||||
.mon_dbgi_regs = {
|
||||
.write_ptr = {
|
||||
.addr = DBGI_SRAM_FIFO_POINTERS,
|
||||
.mask = DBGI_SRAM_FIFO_POINTERS_WR_PTR_MSK,
|
||||
},
|
||||
},
|
||||
.features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
|
||||
.ucode_api_max = IWL_DR_UCODE_API_MAX,
|
||||
.ucode_api_min = IWL_DR_UCODE_API_MIN,
|
||||
};
|
||||
|
||||
const struct iwl_mac_cfg iwl_dr_mac_cfg = {
|
||||
.device_family = IWL_DEVICE_FAMILY_DR,
|
||||
.base = &iwl_dr_base,
|
||||
.mq_rx_supported = true,
|
||||
.gen2 = true,
|
||||
.integrated = true,
|
||||
.umac_prph_offset = 0x300000,
|
||||
.xtal_latency = 12000,
|
||||
.low_latency_xtal = true,
|
||||
.ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US,
|
||||
};
|
||||
|
||||
MODULE_FIRMWARE(IWL_DR_A_PE_A_FW_MODULE_FIRMWARE(IWL_DR_UCODE_API_MAX));
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018-2025 Intel Corporation
|
||||
*/
|
||||
#include "iwl-config.h"
|
||||
|
||||
/* NVM versions */
|
||||
#define IWL_FM_NVM_VERSION 0x0a1d
|
||||
|
||||
#define IWL_DEVICE_FM \
|
||||
.ht_params = { \
|
||||
.stbc = true, \
|
||||
.ldpc = true, \
|
||||
.ht40_bands = BIT(NL80211_BAND_2GHZ) | \
|
||||
BIT(NL80211_BAND_5GHZ), \
|
||||
}, \
|
||||
.led_mode = IWL_LED_RF_STATE, \
|
||||
.non_shared_ant = ANT_B, \
|
||||
.vht_mu_mimo_supported = true, \
|
||||
.uhb_supported = true, \
|
||||
.num_rbds = IWL_NUM_RBDS_EHT, \
|
||||
.nvm_ver = IWL_FM_NVM_VERSION, \
|
||||
.nvm_type = IWL_NVM_EXT
|
||||
|
||||
const struct iwl_rf_cfg iwl_rf_fm = {
|
||||
IWL_DEVICE_FM,
|
||||
};
|
||||
|
||||
const struct iwl_rf_cfg iwl_rf_fm_160mhz = {
|
||||
IWL_DEVICE_FM,
|
||||
.bw_limit = 160,
|
||||
};
|
||||
|
||||
const char iwl_killer_be1750s_name[] =
|
||||
"Killer(R) Wi-Fi 7 BE1750s 320MHz Wireless Network Adapter (BE201D2W)";
|
||||
const char iwl_killer_be1750i_name[] =
|
||||
"Killer(R) Wi-Fi 7 BE1750i 320MHz Wireless Network Adapter (BE201NGW)";
|
||||
const char iwl_killer_be1750w_name[] =
|
||||
"Killer(TM) Wi-Fi 7 BE1750w 320MHz Wireless Network Adapter (BE200D2W)";
|
||||
const char iwl_killer_be1750x_name[] =
|
||||
"Killer(TM) Wi-Fi 7 BE1750x 320MHz Wireless Network Adapter (BE200NGW)";
|
||||
const char iwl_killer_be1790s_name[] =
|
||||
"Killer(R) Wi-Fi 7 BE1790s 320MHz Wireless Network Adapter (BE401D2W)";
|
||||
const char iwl_killer_be1790i_name[] =
|
||||
"Killer(R) Wi-Fi 7 BE1790i 320MHz Wireless Network Adapter (BE401NGW)";
|
||||
|
||||
const char iwl_be201_name[] = "Intel(R) Wi-Fi 7 BE201 320MHz";
|
||||
const char iwl_be200_name[] = "Intel(R) Wi-Fi 7 BE200 320MHz";
|
||||
const char iwl_be202_name[] = "Intel(R) Wi-Fi 7 BE202 160MHz";
|
||||
const char iwl_be401_name[] = "Intel(R) Wi-Fi 7 BE401 320MHz";
|
||||
@@ -0,0 +1,73 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018-2025 Intel Corporation
|
||||
*/
|
||||
#include "iwl-config.h"
|
||||
|
||||
/* Highest firmware API version supported */
|
||||
#define IWL_GF_UCODE_API_MAX 100
|
||||
|
||||
/* Lowest firmware API version supported */
|
||||
#define IWL_GF_UCODE_API_MIN 98
|
||||
|
||||
#define IWL_SO_A_GF_A_FW_PRE "iwlwifi-so-a0-gf-a0"
|
||||
#define IWL_TY_A_GF_A_FW_PRE "iwlwifi-ty-a0-gf-a0"
|
||||
#define IWL_MA_A_GF_A_FW_PRE "iwlwifi-ma-a0-gf-a0"
|
||||
#define IWL_MA_B_GF_A_FW_PRE "iwlwifi-ma-b0-gf-a0"
|
||||
#define IWL_SO_A_GF4_A_FW_PRE "iwlwifi-so-a0-gf4-a0"
|
||||
#define IWL_MA_A_GF4_A_FW_PRE "iwlwifi-ma-a0-gf4-a0"
|
||||
#define IWL_MA_B_GF4_A_FW_PRE "iwlwifi-ma-b0-gf4-a0"
|
||||
#define IWL_BZ_A_GF_A_FW_PRE "iwlwifi-bz-a0-gf-a0"
|
||||
#define IWL_BZ_A_GF4_A_FW_PRE "iwlwifi-bz-a0-gf4-a0"
|
||||
#define IWL_SC_A_GF_A_FW_PRE "iwlwifi-sc-a0-gf-a0"
|
||||
#define IWL_SC_A_GF4_A_FW_PRE "iwlwifi-sc-a0-gf4-a0"
|
||||
|
||||
/* NVM versions */
|
||||
#define IWL_GF_NVM_VERSION 0x0a1d
|
||||
|
||||
const struct iwl_rf_cfg iwl_rf_gf = {
|
||||
.uhb_supported = true,
|
||||
.led_mode = IWL_LED_RF_STATE,
|
||||
.non_shared_ant = ANT_B,
|
||||
.vht_mu_mimo_supported = true,
|
||||
.ht_params = {
|
||||
.stbc = true,
|
||||
.ldpc = true,
|
||||
.ht40_bands = BIT(NL80211_BAND_2GHZ) |
|
||||
BIT(NL80211_BAND_5GHZ),
|
||||
},
|
||||
.nvm_ver = IWL_GF_NVM_VERSION,
|
||||
.nvm_type = IWL_NVM_EXT,
|
||||
.num_rbds = IWL_NUM_RBDS_HE,
|
||||
.ucode_api_min = IWL_GF_UCODE_API_MIN,
|
||||
.ucode_api_max = IWL_GF_UCODE_API_MAX,
|
||||
};
|
||||
|
||||
const char iwl_ax210_killer_1675w_name[] =
|
||||
"Killer(R) Wi-Fi 6E AX1675w 160MHz Wireless Network Adapter (210D2W)";
|
||||
const char iwl_ax210_killer_1675x_name[] =
|
||||
"Killer(R) Wi-Fi 6E AX1675x 160MHz Wireless Network Adapter (210NGW)";
|
||||
const char iwl_ax211_killer_1675s_name[] =
|
||||
"Killer(R) Wi-Fi 6E AX1675s 160MHz Wireless Network Adapter (211D2W)";
|
||||
const char iwl_ax211_killer_1675i_name[] =
|
||||
"Killer(R) Wi-Fi 6E AX1675i 160MHz Wireless Network Adapter (211NGW)";
|
||||
const char iwl_ax411_killer_1690s_name[] =
|
||||
"Killer(R) Wi-Fi 6E AX1690s 160MHz Wireless Network Adapter (411D2W)";
|
||||
const char iwl_ax411_killer_1690i_name[] =
|
||||
"Killer(R) Wi-Fi 6E AX1690i 160MHz Wireless Network Adapter (411NGW)";
|
||||
|
||||
const char iwl_ax210_name[] = "Intel(R) Wi-Fi 6E AX210 160MHz";
|
||||
const char iwl_ax211_name[] = "Intel(R) Wi-Fi 6E AX211 160MHz";
|
||||
const char iwl_ax411_name[] = "Intel(R) Wi-Fi 6E AX411 160MHz";
|
||||
|
||||
IWL_FW_AND_PNVM(IWL_SO_A_GF_A_FW_PRE, IWL_GF_UCODE_API_MAX);
|
||||
IWL_FW_AND_PNVM(IWL_TY_A_GF_A_FW_PRE, IWL_GF_UCODE_API_MAX);
|
||||
IWL_FW_AND_PNVM(IWL_MA_A_GF_A_FW_PRE, IWL_GF_UCODE_API_MAX);
|
||||
IWL_FW_AND_PNVM(IWL_MA_B_GF_A_FW_PRE, IWL_GF_UCODE_API_MAX);
|
||||
IWL_FW_AND_PNVM(IWL_MA_A_GF4_A_FW_PRE, IWL_GF_UCODE_API_MAX);
|
||||
IWL_FW_AND_PNVM(IWL_MA_B_GF4_A_FW_PRE, IWL_GF_UCODE_API_MAX);
|
||||
IWL_FW_AND_PNVM(IWL_BZ_A_GF_A_FW_PRE, IWL_GF_UCODE_API_MAX);
|
||||
IWL_FW_AND_PNVM(IWL_BZ_A_GF4_A_FW_PRE, IWL_GF_UCODE_API_MAX);
|
||||
IWL_FW_AND_PNVM(IWL_SC_A_GF_A_FW_PRE, IWL_GF_UCODE_API_MAX);
|
||||
IWL_FW_AND_PNVM(IWL_SC_A_GF4_A_FW_PRE, IWL_GF_UCODE_API_MAX);
|
||||
@@ -0,0 +1,89 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018-2025 Intel Corporation
|
||||
*/
|
||||
#include "iwl-config.h"
|
||||
|
||||
/* Highest firmware API version supported */
|
||||
#define IWL_HR_UCODE_API_MAX 100
|
||||
|
||||
/* Lowest firmware API version supported */
|
||||
#define IWL_HR_UCODE_API_MIN 98
|
||||
|
||||
#define IWL_QU_B_HR_B_FW_PRE "iwlwifi-Qu-b0-hr-b0"
|
||||
#define IWL_QU_C_HR_B_FW_PRE "iwlwifi-Qu-c0-hr-b0"
|
||||
#define IWL_QUZ_A_HR_B_FW_PRE "iwlwifi-QuZ-a0-hr-b0"
|
||||
#define IWL_SO_A_HR_B_FW_PRE "iwlwifi-so-a0-hr-b0"
|
||||
#define IWL_MA_A_HR_B_FW_PRE "iwlwifi-ma-a0-hr-b0"
|
||||
#define IWL_MA_B_HR_B_FW_PRE "iwlwifi-ma-b0-hr-b0"
|
||||
#define IWL_BZ_A_HR_B_FW_PRE "iwlwifi-bz-a0-hr-b0"
|
||||
#define IWL_SC_A_HR_A_FW_PRE "iwlwifi-sc-a0-hr-b0"
|
||||
#define IWL_SC_A_HR_B_FW_PRE "iwlwifi-sc-a0-hr-b0"
|
||||
|
||||
#define IWL_QU_B_HR_B_MODULE_FIRMWARE(api) \
|
||||
IWL_QU_B_HR_B_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_QUZ_A_HR_B_MODULE_FIRMWARE(api) \
|
||||
IWL_QUZ_A_HR_B_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_QU_C_HR_B_MODULE_FIRMWARE(api) \
|
||||
IWL_QU_C_HR_B_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_SO_A_HR_B_MODULE_FIRMWARE(api) \
|
||||
IWL_SO_A_HR_B_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_MA_A_HR_B_FW_MODULE_FIRMWARE(api) \
|
||||
IWL_MA_A_HR_B_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_MA_B_HR_B_FW_MODULE_FIRMWARE(api) \
|
||||
IWL_MA_B_HR_B_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_BZ_A_HR_B_MODULE_FIRMWARE(api) \
|
||||
IWL_BZ_A_HR_B_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_SC_A_HR_A_FW_MODULE_FIRMWARE(api) \
|
||||
IWL_SC_A_HR_A_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_SC_A_HR_B_FW_MODULE_FIRMWARE(api) \
|
||||
IWL_SC_A_HR_B_FW_PRE "-" __stringify(api) ".ucode"
|
||||
|
||||
/* NVM versions */
|
||||
#define IWL_HR_NVM_VERSION 0x0a1d
|
||||
|
||||
#define IWL_DEVICE_HR \
|
||||
.led_mode = IWL_LED_RF_STATE, \
|
||||
.non_shared_ant = ANT_B, \
|
||||
.vht_mu_mimo_supported = true, \
|
||||
.ht_params = { \
|
||||
.stbc = true, \
|
||||
.ldpc = true, \
|
||||
.ht40_bands = BIT(NL80211_BAND_2GHZ) | \
|
||||
BIT(NL80211_BAND_5GHZ), \
|
||||
}, \
|
||||
.num_rbds = IWL_NUM_RBDS_HE, \
|
||||
.nvm_ver = IWL_HR_NVM_VERSION, \
|
||||
.nvm_type = IWL_NVM_EXT, \
|
||||
.ucode_api_min = IWL_HR_UCODE_API_MIN, \
|
||||
.ucode_api_max = IWL_HR_UCODE_API_MAX
|
||||
|
||||
const struct iwl_rf_cfg iwl_rf_hr1 = {
|
||||
IWL_DEVICE_HR,
|
||||
.tx_with_siso_diversity = true,
|
||||
};
|
||||
|
||||
const struct iwl_rf_cfg iwl_rf_hr = {
|
||||
IWL_DEVICE_HR,
|
||||
};
|
||||
|
||||
const struct iwl_rf_cfg iwl_rf_hr_80mhz = {
|
||||
IWL_DEVICE_HR,
|
||||
.bw_limit = 80,
|
||||
};
|
||||
|
||||
const char iwl_ax101_name[] = "Intel(R) Wi-Fi 6 AX101";
|
||||
const char iwl_ax200_name[] = "Intel(R) Wi-Fi 6 AX200 160MHz";
|
||||
const char iwl_ax201_name[] = "Intel(R) Wi-Fi 6 AX201 160MHz";
|
||||
const char iwl_ax203_name[] = "Intel(R) Wi-Fi 6 AX203";
|
||||
|
||||
MODULE_FIRMWARE(IWL_QU_B_HR_B_MODULE_FIRMWARE(IWL_HR_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_QU_C_HR_B_MODULE_FIRMWARE(IWL_HR_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_QUZ_A_HR_B_MODULE_FIRMWARE(IWL_HR_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_SO_A_HR_B_MODULE_FIRMWARE(IWL_HR_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_MA_A_HR_B_FW_MODULE_FIRMWARE(IWL_HR_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_MA_B_HR_B_FW_MODULE_FIRMWARE(IWL_HR_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_BZ_A_HR_B_MODULE_FIRMWARE(IWL_HR_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_SC_A_HR_A_FW_MODULE_FIRMWARE(IWL_HR_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_SC_A_HR_B_FW_MODULE_FIRMWARE(IWL_HR_UCODE_API_MAX));
|
||||
@@ -0,0 +1,111 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018-2021, 2023, 2025 Intel Corporation
|
||||
*/
|
||||
#include "iwl-config.h"
|
||||
|
||||
/* Highest firmware API version supported */
|
||||
#define IWL_JF_UCODE_API_MAX 77
|
||||
|
||||
/* Lowest firmware API version supported */
|
||||
#define IWL_JF_UCODE_API_MIN 77
|
||||
|
||||
#define IWL_QU_B_JF_B_FW_PRE "iwlwifi-Qu-b0-jf-b0"
|
||||
#define IWL_QU_C_JF_B_FW_PRE "iwlwifi-Qu-c0-jf-b0"
|
||||
#define IWL_QUZ_A_JF_B_FW_PRE "iwlwifi-QuZ-a0-jf-b0"
|
||||
#define IWL_SO_A_JF_B_FW_PRE "iwlwifi-so-a0-jf-b0"
|
||||
|
||||
#define IWL_QUZ_A_JF_B_MODULE_FIRMWARE(api) \
|
||||
IWL_QUZ_A_JF_B_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_QU_B_JF_B_MODULE_FIRMWARE(api) \
|
||||
IWL_QU_B_JF_B_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_QU_C_JF_B_MODULE_FIRMWARE(api) \
|
||||
IWL_QU_C_JF_B_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_SO_A_JF_B_MODULE_FIRMWARE(api) \
|
||||
IWL_SO_A_JF_B_FW_PRE "-" __stringify(api) ".ucode"
|
||||
|
||||
/* NVM versions */
|
||||
#define IWL_JF_NVM_VERSION 0x0a1d
|
||||
|
||||
/* Memory offsets and lengths */
|
||||
#define IWL9000_DCCM_OFFSET 0x800000
|
||||
#define IWL9000_DCCM_LEN 0x18000
|
||||
#define IWL9000_DCCM2_OFFSET 0x880000
|
||||
#define IWL9000_DCCM2_LEN 0x8000
|
||||
|
||||
static const struct iwl_tt_params iwl_jf_tt_params = {
|
||||
.ct_kill_entry = 115,
|
||||
.ct_kill_exit = 93,
|
||||
.ct_kill_duration = 5,
|
||||
.dynamic_smps_entry = 111,
|
||||
.dynamic_smps_exit = 107,
|
||||
.tx_protection_entry = 112,
|
||||
.tx_protection_exit = 105,
|
||||
.tx_backoff = {
|
||||
{.temperature = 110, .backoff = 200},
|
||||
{.temperature = 111, .backoff = 600},
|
||||
{.temperature = 112, .backoff = 1200},
|
||||
{.temperature = 113, .backoff = 2000},
|
||||
{.temperature = 114, .backoff = 4000},
|
||||
},
|
||||
.support_ct_kill = true,
|
||||
.support_dynamic_smps = true,
|
||||
.support_tx_protection = true,
|
||||
.support_tx_backoff = true,
|
||||
};
|
||||
|
||||
/* these values are ignored if not with Pu/Th MAC firmware, due to offload */
|
||||
#define IWL_DEVICE_JF_PU \
|
||||
.dccm_offset = IWL9000_DCCM_OFFSET, \
|
||||
.dccm_len = IWL9000_DCCM_LEN, \
|
||||
.dccm2_offset = IWL9000_DCCM2_OFFSET, \
|
||||
.dccm2_len = IWL9000_DCCM2_LEN, \
|
||||
.thermal_params = &iwl_jf_tt_params
|
||||
|
||||
#define IWL_DEVICE_JF \
|
||||
IWL_DEVICE_JF_PU, \
|
||||
.led_mode = IWL_LED_RF_STATE, \
|
||||
.non_shared_ant = ANT_B, \
|
||||
.num_rbds = IWL_NUM_RBDS_NON_HE, \
|
||||
.vht_mu_mimo_supported = true, \
|
||||
.ht_params = { \
|
||||
.stbc = true, \
|
||||
.ldpc = true, \
|
||||
.ht40_bands = BIT(NL80211_BAND_2GHZ) | \
|
||||
BIT(NL80211_BAND_5GHZ), \
|
||||
}, \
|
||||
.nvm_ver = IWL_JF_NVM_VERSION, \
|
||||
.nvm_type = IWL_NVM_EXT, \
|
||||
.ucode_api_min = IWL_JF_UCODE_API_MIN, \
|
||||
.ucode_api_max = IWL_JF_UCODE_API_MAX
|
||||
|
||||
const struct iwl_rf_cfg iwl_rf_jf = {
|
||||
IWL_DEVICE_JF,
|
||||
};
|
||||
|
||||
const struct iwl_rf_cfg iwl_rf_jf_80mhz = {
|
||||
IWL_DEVICE_JF,
|
||||
.bw_limit = 80,
|
||||
};
|
||||
|
||||
const char iwl9260_name[] = "Intel(R) Wireless-AC 9260";
|
||||
const char iwl9461_name[] = "Intel(R) Wireless-AC 9461";
|
||||
const char iwl9462_name[] = "Intel(R) Wireless-AC 9462";
|
||||
const char iwl9560_name[] = "Intel(R) Wireless-AC 9560";
|
||||
const char iwl9260_160_name[] = "Intel(R) Wireless-AC 9260 160MHz";
|
||||
const char iwl9461_160_name[] = "Intel(R) Wireless-AC 9461 160MHz";
|
||||
const char iwl9462_160_name[] = "Intel(R) Wireless-AC 9462 160MHz";
|
||||
const char iwl9560_160_name[] = "Intel(R) Wireless-AC 9560 160MHz";
|
||||
|
||||
const char iwl9260_killer_1550_name[] =
|
||||
"Killer(R) Wireless-AC 1550 Wireless Network Adapter (9260NGW) 160MHz";
|
||||
const char iwl9560_killer_1550i_name[] =
|
||||
"Killer(R) Wireless-AC 1550i Wireless Network Adapter (9560NGW) 160MHz";
|
||||
const char iwl9560_killer_1550s_name[] =
|
||||
"Killer(R) Wireless-AC 1550s Wireless Network Adapter (9560D2W) 160MHz";
|
||||
|
||||
MODULE_FIRMWARE(IWL_QU_B_JF_B_MODULE_FIRMWARE(IWL_JF_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_QU_C_JF_B_MODULE_FIRMWARE(IWL_JF_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_QUZ_A_JF_B_MODULE_FIRMWARE(IWL_JF_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_SO_A_JF_B_MODULE_FIRMWARE(IWL_JF_UCODE_API_MAX));
|
||||
@@ -0,0 +1,16 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2025 Intel Corporation
|
||||
*/
|
||||
#include "iwl-config.h"
|
||||
|
||||
/* currently iwl_rf_wh/iwl_rf_wh_160mhz are just defines for the FM ones */
|
||||
|
||||
const char iwl_killer_bn1850w2_name[] =
|
||||
"Killer(R) Wi-Fi 8 BN1850w2 320MHz Wireless Network Adapter (BN201.D2W)";
|
||||
const char iwl_killer_bn1850i_name[] =
|
||||
"Killer(R) Wi-Fi 8 BN1850i 320MHz Wireless Network Adapter (BN201.NGW)";
|
||||
|
||||
const char iwl_bn201_name[] = "Intel(R) Wi-Fi 8 BN201";
|
||||
const char iwl_be221_name[] = "Intel(R) Wi-Fi 7 BE221";
|
||||
const char iwl_be223_name[] = "Intel(R) Wi-Fi 7 BE223";
|
||||
@@ -0,0 +1,15 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2025 Intel Corporation
|
||||
*/
|
||||
#include "iwl-config.h"
|
||||
|
||||
/* currently iwl_rf_wh/iwl_rf_wh_160mhz are just defines for the FM ones */
|
||||
|
||||
const char iwl_killer_be1775s_name[] =
|
||||
"Killer(R) Wi-Fi 7 BE1775s 320MHz Wireless Network Adapter (BE211D2W)";
|
||||
const char iwl_killer_be1775i_name[] =
|
||||
"Killer(R) Wi-Fi 7 BE1775i 320MHz Wireless Network Adapter (BE211NGW)";
|
||||
|
||||
const char iwl_be211_name[] = "Intel(R) Wi-Fi 7 BE211 320MHz";
|
||||
const char iwl_be213_name[] = "Intel(R) Wi-Fi 7 BE213 160MHz";
|
||||
@@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018-2024 Intel Corporation
|
||||
* Copyright (C) 2018-2025 Intel Corporation
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/stringify.h>
|
||||
@@ -10,59 +10,25 @@
|
||||
#include "fw/api/txq.h"
|
||||
|
||||
/* Highest firmware API version supported */
|
||||
#define IWL_SC_UCODE_API_MAX 92
|
||||
#define IWL_SC_UCODE_API_MAX 102
|
||||
|
||||
/* Lowest firmware API version supported */
|
||||
#define IWL_SC_UCODE_API_MIN 90
|
||||
#define IWL_SC_UCODE_API_MIN 98
|
||||
|
||||
/* NVM versions */
|
||||
#define IWL_SC_NVM_VERSION 0x0a1d
|
||||
|
||||
/* Memory offsets and lengths */
|
||||
#define IWL_SC_DCCM_OFFSET 0x800000 /* LMAC1 */
|
||||
#define IWL_SC_DCCM_LEN 0x10000 /* LMAC1 */
|
||||
#define IWL_SC_DCCM2_OFFSET 0x880000
|
||||
#define IWL_SC_DCCM2_LEN 0x8000
|
||||
#define IWL_SC_SMEM_OFFSET 0x400000
|
||||
#define IWL_SC_SMEM_LEN 0xD0000
|
||||
|
||||
#define IWL_SC_A_FM_B_FW_PRE "iwlwifi-sc-a0-fm-b0"
|
||||
#define IWL_SC_A_FM_C_FW_PRE "iwlwifi-sc-a0-fm-c0"
|
||||
#define IWL_SC_A_HR_A_FW_PRE "iwlwifi-sc-a0-hr-b0"
|
||||
#define IWL_SC_A_HR_B_FW_PRE "iwlwifi-sc-a0-hr-b0"
|
||||
#define IWL_SC_A_GF_A_FW_PRE "iwlwifi-sc-a0-gf-a0"
|
||||
#define IWL_SC_A_GF4_A_FW_PRE "iwlwifi-sc-a0-gf4-a0"
|
||||
#define IWL_SC_A_WH_A_FW_PRE "iwlwifi-sc-a0-wh-a0"
|
||||
#define IWL_SC2_A_FM_C_FW_PRE "iwlwifi-sc2-a0-fm-c0"
|
||||
#define IWL_SC2_A_WH_A_FW_PRE "iwlwifi-sc2-a0-wh-a0"
|
||||
#define IWL_SC2F_A_FM_C_FW_PRE "iwlwifi-sc2f-a0-fm-c0"
|
||||
#define IWL_SC2F_A_WH_A_FW_PRE "iwlwifi-sc2f-a0-wh-a0"
|
||||
|
||||
#define IWL_SC_A_FM_B_FW_MODULE_FIRMWARE(api) \
|
||||
IWL_SC_A_FM_B_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_SC_A_FM_C_FW_MODULE_FIRMWARE(api) \
|
||||
IWL_SC_A_FM_C_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_SC_A_HR_A_FW_MODULE_FIRMWARE(api) \
|
||||
IWL_SC_A_HR_A_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_SC_A_HR_B_FW_MODULE_FIRMWARE(api) \
|
||||
IWL_SC_A_HR_B_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_SC_A_GF_A_FW_MODULE_FIRMWARE(api) \
|
||||
IWL_SC_A_GF_A_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_SC_A_GF4_A_FW_MODULE_FIRMWARE(api) \
|
||||
IWL_SC_A_GF4_A_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_SC_A_WH_A_FW_MODULE_FIRMWARE(api) \
|
||||
IWL_SC_A_WH_A_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_SC2_A_FM_C_FW_MODULE_FIRMWARE(api) \
|
||||
IWL_SC2_A_FM_C_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_SC2_A_WH_A_FW_MODULE_FIRMWARE(api) \
|
||||
IWL_SC2_A_WH_A_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_SC2F_A_FM_C_FW_MODULE_FIRMWARE(api) \
|
||||
IWL_SC2F_A_FM_C_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_SC2F_A_WH_A_FW_MODULE_FIRMWARE(api) \
|
||||
IWL_SC2F_A_WH_A_FW_PRE "-" __stringify(api) ".ucode"
|
||||
|
||||
static const struct iwl_base_params iwl_sc_base_params = {
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE_32K,
|
||||
static const struct iwl_family_base_params iwl_sc_base = {
|
||||
.num_of_queues = 512,
|
||||
.max_tfd_queue_size = 65536,
|
||||
.shadow_ram_support = true,
|
||||
@@ -71,87 +37,55 @@ static const struct iwl_base_params iwl_sc_base_params = {
|
||||
.max_event_log_size = 512,
|
||||
.shadow_reg_enable = true,
|
||||
.pcie_l1_allowed = true,
|
||||
.smem_offset = IWL_SC_SMEM_OFFSET,
|
||||
.smem_len = IWL_SC_SMEM_LEN,
|
||||
.apmg_not_supported = true,
|
||||
.mac_addr_from_csr = 0x30,
|
||||
.min_umac_error_event_table = 0xD0000,
|
||||
.d3_debug_data_base_addr = 0x401000,
|
||||
.d3_debug_data_length = 60 * 1024,
|
||||
.mon_smem_regs = {
|
||||
.write_ptr = {
|
||||
.addr = LDBG_M2S_BUF_WPTR,
|
||||
.mask = LDBG_M2S_BUF_WPTR_VAL_MSK,
|
||||
},
|
||||
.cycle_cnt = {
|
||||
.addr = LDBG_M2S_BUF_WRAP_CNT,
|
||||
.mask = LDBG_M2S_BUF_WRAP_CNT_VAL_MSK,
|
||||
},
|
||||
},
|
||||
.min_txq_size = 128,
|
||||
.gp2_reg_addr = 0xd02c68,
|
||||
.min_ba_txq_size = IWL_DEFAULT_QUEUE_SIZE_EHT,
|
||||
.mon_dram_regs = {
|
||||
.write_ptr = {
|
||||
.addr = DBGC_CUR_DBGBUF_STATUS,
|
||||
.mask = DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK,
|
||||
},
|
||||
.cycle_cnt = {
|
||||
.addr = DBGC_DBGBUF_WRAP_AROUND,
|
||||
.mask = 0xffffffff,
|
||||
},
|
||||
.cur_frag = {
|
||||
.addr = DBGC_CUR_DBGBUF_STATUS,
|
||||
.mask = DBGC_CUR_DBGBUF_STATUS_IDX_MSK,
|
||||
},
|
||||
},
|
||||
.mon_dbgi_regs = {
|
||||
.write_ptr = {
|
||||
.addr = DBGI_SRAM_FIFO_POINTERS,
|
||||
.mask = DBGI_SRAM_FIFO_POINTERS_WR_PTR_MSK,
|
||||
},
|
||||
},
|
||||
.features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
|
||||
.ucode_api_max = IWL_SC_UCODE_API_MAX,
|
||||
.ucode_api_min = IWL_SC_UCODE_API_MIN,
|
||||
};
|
||||
|
||||
#define IWL_DEVICE_BZ_COMMON \
|
||||
.ucode_api_max = IWL_SC_UCODE_API_MAX, \
|
||||
.ucode_api_min = IWL_SC_UCODE_API_MIN, \
|
||||
.led_mode = IWL_LED_RF_STATE, \
|
||||
.nvm_hw_section_num = 10, \
|
||||
.non_shared_ant = ANT_B, \
|
||||
.dccm_offset = IWL_SC_DCCM_OFFSET, \
|
||||
.dccm_len = IWL_SC_DCCM_LEN, \
|
||||
.dccm2_offset = IWL_SC_DCCM2_OFFSET, \
|
||||
.dccm2_len = IWL_SC_DCCM2_LEN, \
|
||||
.smem_offset = IWL_SC_SMEM_OFFSET, \
|
||||
.smem_len = IWL_SC_SMEM_LEN, \
|
||||
.apmg_not_supported = true, \
|
||||
.trans.mq_rx_supported = true, \
|
||||
.vht_mu_mimo_supported = true, \
|
||||
.mac_addr_from_csr = 0x30, \
|
||||
.nvm_ver = IWL_SC_NVM_VERSION, \
|
||||
.trans.rf_id = true, \
|
||||
.trans.gen2 = true, \
|
||||
.nvm_type = IWL_NVM_EXT, \
|
||||
.dbgc_supported = true, \
|
||||
.min_umac_error_event_table = 0xD0000, \
|
||||
.d3_debug_data_base_addr = 0x401000, \
|
||||
.d3_debug_data_length = 60 * 1024, \
|
||||
.mon_smem_regs = { \
|
||||
.write_ptr = { \
|
||||
.addr = LDBG_M2S_BUF_WPTR, \
|
||||
.mask = LDBG_M2S_BUF_WPTR_VAL_MSK, \
|
||||
}, \
|
||||
.cycle_cnt = { \
|
||||
.addr = LDBG_M2S_BUF_WRAP_CNT, \
|
||||
.mask = LDBG_M2S_BUF_WRAP_CNT_VAL_MSK, \
|
||||
}, \
|
||||
}, \
|
||||
.trans.umac_prph_offset = 0x300000, \
|
||||
.trans.device_family = IWL_DEVICE_FAMILY_SC, \
|
||||
.trans.base_params = &iwl_sc_base_params, \
|
||||
.min_txq_size = 128, \
|
||||
.gp2_reg_addr = 0xd02c68, \
|
||||
.min_ba_txq_size = IWL_DEFAULT_QUEUE_SIZE_EHT, \
|
||||
.mon_dram_regs = { \
|
||||
.write_ptr = { \
|
||||
.addr = DBGC_CUR_DBGBUF_STATUS, \
|
||||
.mask = DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK, \
|
||||
}, \
|
||||
.cycle_cnt = { \
|
||||
.addr = DBGC_DBGBUF_WRAP_AROUND, \
|
||||
.mask = 0xffffffff, \
|
||||
}, \
|
||||
.cur_frag = { \
|
||||
.addr = DBGC_CUR_DBGBUF_STATUS, \
|
||||
.mask = DBGC_CUR_DBGBUF_STATUS_IDX_MSK, \
|
||||
}, \
|
||||
}, \
|
||||
.mon_dbgi_regs = { \
|
||||
.write_ptr = { \
|
||||
.addr = DBGI_SRAM_FIFO_POINTERS, \
|
||||
.mask = DBGI_SRAM_FIFO_POINTERS_WR_PTR_MSK, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define IWL_DEVICE_SC \
|
||||
IWL_DEVICE_BZ_COMMON, \
|
||||
.uhb_supported = true, \
|
||||
.features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, \
|
||||
.num_rbds = IWL_NUM_RBDS_SC_EHT, \
|
||||
.ht_params = &iwl_22000_ht_params
|
||||
|
||||
/*
|
||||
* This size was picked according to 8 MSDUs inside 512 A-MSDUs in an
|
||||
* A-MPDU, with additional overhead to account for processing time.
|
||||
*/
|
||||
#define IWL_NUM_RBDS_SC_EHT (512 * 16)
|
||||
|
||||
const struct iwl_cfg_trans_params iwl_sc_trans_cfg = {
|
||||
const struct iwl_mac_cfg iwl_sc_mac_cfg = {
|
||||
.device_family = IWL_DEVICE_FAMILY_SC,
|
||||
.base_params = &iwl_sc_base_params,
|
||||
.base = &iwl_sc_base,
|
||||
.mq_rx_supported = true,
|
||||
.rf_id = true,
|
||||
.gen2 = true,
|
||||
.integrated = true,
|
||||
.umac_prph_offset = 0x300000,
|
||||
@@ -160,35 +94,8 @@ const struct iwl_cfg_trans_params iwl_sc_trans_cfg = {
|
||||
.ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US,
|
||||
};
|
||||
|
||||
const char iwl_sc_name[] = "Intel(R) TBD Sc device";
|
||||
|
||||
const struct iwl_cfg iwl_cfg_sc = {
|
||||
.fw_name_mac = "sc",
|
||||
IWL_DEVICE_SC,
|
||||
};
|
||||
|
||||
const char iwl_sc2_name[] = "Intel(R) TBD Sc2 device";
|
||||
|
||||
const struct iwl_cfg iwl_cfg_sc2 = {
|
||||
.fw_name_mac = "sc2",
|
||||
IWL_DEVICE_SC,
|
||||
};
|
||||
|
||||
const char iwl_sc2f_name[] = "Intel(R) TBD Sc2f device";
|
||||
|
||||
const struct iwl_cfg iwl_cfg_sc2f = {
|
||||
.fw_name_mac = "sc2f",
|
||||
IWL_DEVICE_SC,
|
||||
};
|
||||
|
||||
MODULE_FIRMWARE(IWL_SC_A_FM_B_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_SC_A_FM_C_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_SC_A_HR_A_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_SC_A_HR_B_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_SC_A_GF_A_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_SC_A_GF4_A_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_SC_A_WH_A_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_SC2_A_FM_C_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_SC2_A_WH_A_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_SC2F_A_FM_C_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_SC2F_A_WH_A_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX));
|
||||
IWL_FW_AND_PNVM(IWL_SC_A_FM_B_FW_PRE, IWL_SC_UCODE_API_MAX);
|
||||
IWL_FW_AND_PNVM(IWL_SC_A_FM_C_FW_PRE, IWL_SC_UCODE_API_MAX);
|
||||
IWL_FW_AND_PNVM(IWL_SC_A_WH_A_FW_PRE, IWL_SC_UCODE_API_MAX);
|
||||
IWL_FW_AND_PNVM(IWL_SC2_A_FM_C_FW_PRE, IWL_SC_UCODE_API_MAX);
|
||||
IWL_FW_AND_PNVM(IWL_SC2_A_WH_A_FW_PRE, IWL_SC_UCODE_API_MAX);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2019-2024 Intel Corporation
|
||||
* Copyright (C) 2019-2025 Intel Corporation
|
||||
*/
|
||||
#include <linux/uuid.h>
|
||||
#include "iwl-drv.h"
|
||||
@@ -79,9 +79,9 @@ static void *iwl_acpi_get_object(struct device *dev, acpi_string method)
|
||||
* method (DSM) interface. The returned acpi object must be freed by calling
|
||||
* function.
|
||||
*/
|
||||
static void *iwl_acpi_get_dsm_object(struct device *dev, int rev, int func,
|
||||
union acpi_object *args,
|
||||
const guid_t *guid)
|
||||
union acpi_object *iwl_acpi_get_dsm_object(struct device *dev, int rev,
|
||||
int func, union acpi_object *args,
|
||||
const guid_t *guid)
|
||||
{
|
||||
union acpi_object *obj;
|
||||
|
||||
@@ -108,7 +108,7 @@ static int iwl_acpi_get_dsm_integer(struct device *dev, int rev, int func,
|
||||
size_t expected_size)
|
||||
{
|
||||
union acpi_object *obj;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
obj = iwl_acpi_get_dsm_object(dev, rev, func, NULL, guid);
|
||||
if (IS_ERR(obj)) {
|
||||
@@ -123,8 +123,10 @@ static int iwl_acpi_get_dsm_integer(struct device *dev, int rev, int func,
|
||||
} else if (obj->type == ACPI_TYPE_BUFFER) {
|
||||
__le64 le_value = 0;
|
||||
|
||||
if (WARN_ON_ONCE(expected_size > sizeof(le_value)))
|
||||
return -EINVAL;
|
||||
if (WARN_ON_ONCE(expected_size > sizeof(le_value))) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* if the buffer size doesn't match the expected size */
|
||||
if (obj->buffer.length != expected_size)
|
||||
@@ -145,8 +147,9 @@ static int iwl_acpi_get_dsm_integer(struct device *dev, int rev, int func,
|
||||
}
|
||||
|
||||
IWL_DEBUG_DEV_RADIO(dev,
|
||||
"ACPI: DSM method evaluated: func=%d, ret=%d\n",
|
||||
func, ret);
|
||||
"ACPI: DSM method evaluated: func=%d, value=%lld\n",
|
||||
func, *value);
|
||||
ret = 0;
|
||||
out:
|
||||
ACPI_FREE(obj);
|
||||
return ret;
|
||||
@@ -166,7 +169,7 @@ int iwl_acpi_get_dsm(struct iwl_fw_runtime *fwrt,
|
||||
|
||||
BUILD_BUG_ON(ARRAY_SIZE(acpi_dsm_size) != DSM_FUNC_NUM_FUNCS);
|
||||
|
||||
if (WARN_ON(func >= ARRAY_SIZE(acpi_dsm_size)))
|
||||
if (WARN_ON(func >= ARRAY_SIZE(acpi_dsm_size) || !func))
|
||||
return -EINVAL;
|
||||
|
||||
expected_size = acpi_dsm_size[func];
|
||||
@@ -175,6 +178,29 @@ int iwl_acpi_get_dsm(struct iwl_fw_runtime *fwrt,
|
||||
if (expected_size != sizeof(u8) && expected_size != sizeof(u32))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!fwrt->acpi_dsm_funcs_valid) {
|
||||
ret = iwl_acpi_get_dsm_integer(fwrt->dev, ACPI_DSM_REV,
|
||||
DSM_FUNC_QUERY,
|
||||
&iwl_guid, &tmp,
|
||||
acpi_dsm_size[DSM_FUNC_QUERY]);
|
||||
if (ret) {
|
||||
/* always indicate BIT(0) to avoid re-reading */
|
||||
fwrt->acpi_dsm_funcs_valid = BIT(0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
IWL_DEBUG_RADIO(fwrt, "ACPI DSM validity bitmap 0x%x\n",
|
||||
(u32)tmp);
|
||||
/* always indicate BIT(0) to avoid re-reading */
|
||||
fwrt->acpi_dsm_funcs_valid = tmp | BIT(0);
|
||||
}
|
||||
|
||||
if (!(fwrt->acpi_dsm_funcs_valid & BIT(func))) {
|
||||
IWL_DEBUG_RADIO(fwrt, "ACPI DSM %d not indicated as valid\n",
|
||||
func);
|
||||
return -ENODATA;
|
||||
}
|
||||
|
||||
ret = iwl_acpi_get_dsm_integer(fwrt->dev, ACPI_DSM_REV, func,
|
||||
&iwl_guid, &tmp, expected_size);
|
||||
if (ret)
|
||||
@@ -259,13 +285,14 @@ int iwl_acpi_get_tas_table(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_tas_data *tas_data)
|
||||
{
|
||||
union acpi_object *wifi_pkg, *data;
|
||||
int ret, tbl_rev, i, block_list_size, enabled;
|
||||
int ret, tbl_rev, block_list_size, enabled;
|
||||
u32 tas_selection;
|
||||
|
||||
data = iwl_acpi_get_object(fwrt->dev, ACPI_WTAS_METHOD);
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
|
||||
/* try to read wtas table revision 1 or revision 0*/
|
||||
/* try to read wtas table */
|
||||
wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
|
||||
ACPI_WTAS_WIFI_DATA_SIZE,
|
||||
&tbl_rev);
|
||||
@@ -274,27 +301,23 @@ int iwl_acpi_get_tas_table(struct iwl_fw_runtime *fwrt,
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
if (tbl_rev == 1 && wifi_pkg->package.elements[1].type ==
|
||||
ACPI_TYPE_INTEGER) {
|
||||
u32 tas_selection =
|
||||
(u32)wifi_pkg->package.elements[1].integer.value;
|
||||
|
||||
enabled = iwl_parse_tas_selection(fwrt, tas_data,
|
||||
tas_selection);
|
||||
|
||||
} else if (tbl_rev == 0 &&
|
||||
wifi_pkg->package.elements[1].type == ACPI_TYPE_INTEGER) {
|
||||
enabled = !!wifi_pkg->package.elements[1].integer.value;
|
||||
} else {
|
||||
if (tbl_rev < 0 || tbl_rev > 2 ||
|
||||
wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER) {
|
||||
ret = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
if (!enabled) {
|
||||
IWL_DEBUG_RADIO(fwrt, "TAS not enabled\n");
|
||||
ret = 0;
|
||||
goto out_free;
|
||||
}
|
||||
tas_selection = (u32)wifi_pkg->package.elements[1].integer.value;
|
||||
enabled = tas_selection & IWL_WTAS_ENABLED_MSK;
|
||||
|
||||
IWL_DEBUG_RADIO(fwrt, "TAS selection as read from BIOS: 0x%x\n",
|
||||
tas_selection);
|
||||
tas_data->table_source = BIOS_SOURCE_ACPI;
|
||||
tas_data->table_revision = tbl_rev;
|
||||
tas_data->tas_selection = tas_selection;
|
||||
|
||||
IWL_DEBUG_RADIO(fwrt, "TAS %s enabled\n",
|
||||
enabled ? "is" : "not");
|
||||
|
||||
IWL_DEBUG_RADIO(fwrt, "Reading TAS table revision %d\n", tbl_rev);
|
||||
if (wifi_pkg->package.elements[2].type != ACPI_TYPE_INTEGER ||
|
||||
@@ -305,13 +328,14 @@ int iwl_acpi_get_tas_table(struct iwl_fw_runtime *fwrt,
|
||||
ret = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
block_list_size = wifi_pkg->package.elements[2].integer.value;
|
||||
tas_data->block_list_size = cpu_to_le32(block_list_size);
|
||||
tas_data->block_list_size = block_list_size;
|
||||
|
||||
IWL_DEBUG_RADIO(fwrt, "TAS array size %u\n", block_list_size);
|
||||
|
||||
for (i = 0; i < block_list_size; i++) {
|
||||
u32 country;
|
||||
for (int i = 0; i < block_list_size; i++) {
|
||||
u16 country;
|
||||
|
||||
if (wifi_pkg->package.elements[3 + i].type !=
|
||||
ACPI_TYPE_INTEGER) {
|
||||
@@ -322,11 +346,11 @@ int iwl_acpi_get_tas_table(struct iwl_fw_runtime *fwrt,
|
||||
}
|
||||
|
||||
country = wifi_pkg->package.elements[3 + i].integer.value;
|
||||
tas_data->block_list_array[i] = cpu_to_le32(country);
|
||||
tas_data->block_list_array[i] = country;
|
||||
IWL_DEBUG_RADIO(fwrt, "TAS block list country %d\n", country);
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
ret = enabled;
|
||||
out_free:
|
||||
kfree(data);
|
||||
return ret;
|
||||
@@ -357,6 +381,11 @@ int iwl_acpi_get_mcc(struct iwl_fw_runtime *fwrt, char *mcc)
|
||||
}
|
||||
|
||||
mcc_val = wifi_pkg->package.elements[1].integer.value;
|
||||
if (mcc_val != BIOS_MCC_CHINA) {
|
||||
ret = -EINVAL;
|
||||
IWL_DEBUG_RADIO(fwrt, "ACPI WRDD is supported only for CN\n");
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
mcc[0] = (mcc_val >> 8) & 0xff;
|
||||
mcc[1] = mcc_val & 0xff;
|
||||
@@ -424,38 +453,28 @@ int iwl_acpi_get_eckv(struct iwl_fw_runtime *fwrt, u32 *extl_clk)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int iwl_acpi_sar_set_profile(union acpi_object *table,
|
||||
struct iwl_sar_profile *profile,
|
||||
bool enabled, u8 num_chains,
|
||||
u8 num_sub_bands)
|
||||
static int
|
||||
iwl_acpi_parse_chains_table(union acpi_object *table,
|
||||
struct iwl_sar_profile_chain *chains,
|
||||
u8 num_chains, u8 num_sub_bands)
|
||||
{
|
||||
int i, j, idx = 0;
|
||||
|
||||
/*
|
||||
* The table from ACPI is flat, but we store it in a
|
||||
* structured array.
|
||||
*/
|
||||
for (i = 0; i < BIOS_SAR_MAX_CHAINS_PER_PROFILE; i++) {
|
||||
for (j = 0; j < BIOS_SAR_MAX_SUB_BANDS_NUM; j++) {
|
||||
for (u8 chain = 0; chain < num_chains; chain++) {
|
||||
for (u8 subband = 0; subband < BIOS_SAR_MAX_SUB_BANDS_NUM;
|
||||
subband++) {
|
||||
/* if we don't have the values, use the default */
|
||||
if (i >= num_chains || j >= num_sub_bands) {
|
||||
profile->chains[i].subbands[j] = 0;
|
||||
if (subband >= num_sub_bands) {
|
||||
chains[chain].subbands[subband] = 0;
|
||||
} else if (table->type != ACPI_TYPE_INTEGER ||
|
||||
table->integer.value > U8_MAX) {
|
||||
return -EINVAL;
|
||||
} else {
|
||||
if (table[idx].type != ACPI_TYPE_INTEGER ||
|
||||
table[idx].integer.value > U8_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
profile->chains[i].subbands[j] =
|
||||
table[idx].integer.value;
|
||||
|
||||
idx++;
|
||||
chains[chain].subbands[subband] =
|
||||
table->integer.value;
|
||||
table++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Only if all values were valid can the profile be enabled */
|
||||
profile->enabled = enabled;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -538,9 +557,11 @@ int iwl_acpi_get_wrds_table(struct iwl_fw_runtime *fwrt)
|
||||
/* The profile from WRDS is officially profile 1, but goes
|
||||
* into sar_profiles[0] (because we don't have a profile 0).
|
||||
*/
|
||||
ret = iwl_acpi_sar_set_profile(table, &fwrt->sar_profiles[0],
|
||||
flags & IWL_SAR_ENABLE_MSK,
|
||||
num_chains, num_sub_bands);
|
||||
ret = iwl_acpi_parse_chains_table(table, fwrt->sar_profiles[0].chains,
|
||||
num_chains, num_sub_bands);
|
||||
if (!ret && flags & IWL_SAR_ENABLE_MSK)
|
||||
fwrt->sar_profiles[0].enabled = true;
|
||||
|
||||
out_free:
|
||||
kfree(data);
|
||||
return ret;
|
||||
@@ -552,7 +573,7 @@ int iwl_acpi_get_ewrd_table(struct iwl_fw_runtime *fwrt)
|
||||
bool enabled;
|
||||
int i, n_profiles, tbl_rev, pos;
|
||||
int ret = 0;
|
||||
u8 num_chains, num_sub_bands;
|
||||
u8 num_sub_bands;
|
||||
|
||||
data = iwl_acpi_get_object(fwrt->dev, ACPI_EWRD_METHOD);
|
||||
if (IS_ERR(data))
|
||||
@@ -568,7 +589,6 @@ int iwl_acpi_get_ewrd_table(struct iwl_fw_runtime *fwrt)
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
num_chains = ACPI_SAR_NUM_CHAINS_REV2;
|
||||
num_sub_bands = ACPI_SAR_NUM_SUB_BANDS_REV2;
|
||||
|
||||
goto read_table;
|
||||
@@ -584,7 +604,6 @@ int iwl_acpi_get_ewrd_table(struct iwl_fw_runtime *fwrt)
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
num_chains = ACPI_SAR_NUM_CHAINS_REV1;
|
||||
num_sub_bands = ACPI_SAR_NUM_SUB_BANDS_REV1;
|
||||
|
||||
goto read_table;
|
||||
@@ -600,7 +619,6 @@ int iwl_acpi_get_ewrd_table(struct iwl_fw_runtime *fwrt)
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
num_chains = ACPI_SAR_NUM_CHAINS_REV0;
|
||||
num_sub_bands = ACPI_SAR_NUM_SUB_BANDS_REV0;
|
||||
|
||||
goto read_table;
|
||||
@@ -632,23 +650,54 @@ int iwl_acpi_get_ewrd_table(struct iwl_fw_runtime *fwrt)
|
||||
/* the tables start at element 3 */
|
||||
pos = 3;
|
||||
|
||||
BUILD_BUG_ON(ACPI_SAR_NUM_CHAINS_REV0 != ACPI_SAR_NUM_CHAINS_REV1);
|
||||
BUILD_BUG_ON(ACPI_SAR_NUM_CHAINS_REV2 != 2 * ACPI_SAR_NUM_CHAINS_REV0);
|
||||
|
||||
/* parse non-cdb chains for all profiles */
|
||||
for (i = 0; i < n_profiles; i++) {
|
||||
union acpi_object *table = &wifi_pkg->package.elements[pos];
|
||||
|
||||
/* The EWRD profiles officially go from 2 to 4, but we
|
||||
* save them in sar_profiles[1-3] (because we don't
|
||||
* have profile 0). So in the array we start from 1.
|
||||
*/
|
||||
ret = iwl_acpi_sar_set_profile(table,
|
||||
&fwrt->sar_profiles[i + 1],
|
||||
enabled, num_chains,
|
||||
num_sub_bands);
|
||||
ret = iwl_acpi_parse_chains_table(table,
|
||||
fwrt->sar_profiles[i + 1].chains,
|
||||
ACPI_SAR_NUM_CHAINS_REV0,
|
||||
num_sub_bands);
|
||||
if (ret < 0)
|
||||
break;
|
||||
goto out_free;
|
||||
|
||||
/* go to the next table */
|
||||
pos += num_chains * num_sub_bands;
|
||||
pos += ACPI_SAR_NUM_CHAINS_REV0 * num_sub_bands;
|
||||
}
|
||||
|
||||
/* non-cdb table revisions */
|
||||
if (tbl_rev < 2)
|
||||
goto set_enabled;
|
||||
|
||||
/* parse cdb chains for all profiles */
|
||||
for (i = 0; i < n_profiles; i++) {
|
||||
struct iwl_sar_profile_chain *chains;
|
||||
union acpi_object *table;
|
||||
|
||||
table = &wifi_pkg->package.elements[pos];
|
||||
chains = &fwrt->sar_profiles[i + 1].chains[ACPI_SAR_NUM_CHAINS_REV0];
|
||||
ret = iwl_acpi_parse_chains_table(table,
|
||||
chains,
|
||||
ACPI_SAR_NUM_CHAINS_REV0,
|
||||
num_sub_bands);
|
||||
if (ret < 0)
|
||||
goto out_free;
|
||||
|
||||
/* go to the next table */
|
||||
pos += ACPI_SAR_NUM_CHAINS_REV0 * num_sub_bands;
|
||||
}
|
||||
|
||||
set_enabled:
|
||||
for (i = 0; i < n_profiles; i++)
|
||||
fwrt->sar_profiles[i + 1].enabled = enabled;
|
||||
|
||||
out_free:
|
||||
kfree(data);
|
||||
return ret;
|
||||
@@ -821,12 +870,12 @@ int iwl_acpi_get_ppag_table(struct iwl_fw_runtime *fwrt)
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
|
||||
/* try to read ppag table rev 3, 2 or 1 (all have the same data size) */
|
||||
/* try to read ppag table rev 1 to 4 (all have the same data size) */
|
||||
wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
|
||||
ACPI_PPAG_WIFI_DATA_SIZE_V2, &tbl_rev);
|
||||
|
||||
if (!IS_ERR(wifi_pkg)) {
|
||||
if (tbl_rev >= 1 && tbl_rev <= 3) {
|
||||
if (tbl_rev >= 1 && tbl_rev <= 4) {
|
||||
num_sub_bands = IWL_NUM_SUB_BANDS_V2;
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"Reading PPAG table (tbl_rev=%d)\n",
|
||||
@@ -856,7 +905,7 @@ int iwl_acpi_get_ppag_table(struct iwl_fw_runtime *fwrt)
|
||||
goto out_free;
|
||||
|
||||
read_table:
|
||||
fwrt->ppag_ver = tbl_rev;
|
||||
fwrt->ppag_bios_rev = tbl_rev;
|
||||
flags = &wifi_pkg->package.elements[1];
|
||||
|
||||
if (flags->type != ACPI_TYPE_INTEGER) {
|
||||
@@ -865,7 +914,7 @@ int iwl_acpi_get_ppag_table(struct iwl_fw_runtime *fwrt)
|
||||
}
|
||||
|
||||
fwrt->ppag_flags = iwl_bios_get_ppag_flags(flags->integer.value,
|
||||
fwrt->ppag_ver);
|
||||
fwrt->ppag_bios_rev);
|
||||
|
||||
/*
|
||||
* read, verify gain values and save them into the PPAG table.
|
||||
@@ -886,6 +935,7 @@ int iwl_acpi_get_ppag_table(struct iwl_fw_runtime *fwrt)
|
||||
}
|
||||
}
|
||||
|
||||
fwrt->ppag_bios_source = BIOS_SOURCE_ACPI;
|
||||
ret = 0;
|
||||
|
||||
out_free:
|
||||
@@ -893,40 +943,39 @@ int iwl_acpi_get_ppag_table(struct iwl_fw_runtime *fwrt)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void iwl_acpi_get_phy_filters(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_phy_specific_cfg *filters)
|
||||
int iwl_acpi_get_phy_filters(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
struct iwl_phy_specific_cfg *filters = &fwrt->phy_filters;
|
||||
struct iwl_phy_specific_cfg tmp = {};
|
||||
union acpi_object *wifi_pkg, *data;
|
||||
union acpi_object *wifi_pkg, *data __free(kfree);
|
||||
int tbl_rev, i;
|
||||
|
||||
data = iwl_acpi_get_object(fwrt->dev, ACPI_WPFC_METHOD);
|
||||
if (IS_ERR(data))
|
||||
return;
|
||||
return PTR_ERR(data);
|
||||
|
||||
wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
|
||||
ACPI_WPFC_WIFI_DATA_SIZE,
|
||||
&tbl_rev);
|
||||
if (IS_ERR(wifi_pkg))
|
||||
goto out_free;
|
||||
return PTR_ERR(wifi_pkg);
|
||||
|
||||
if (tbl_rev != 0)
|
||||
goto out_free;
|
||||
return -EINVAL;
|
||||
|
||||
BUILD_BUG_ON(ARRAY_SIZE(filters->filter_cfg_chains) !=
|
||||
ACPI_WPFC_WIFI_DATA_SIZE - 1);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(filters->filter_cfg_chains); i++) {
|
||||
if (wifi_pkg->package.elements[i + 1].type != ACPI_TYPE_INTEGER)
|
||||
goto out_free;
|
||||
return -EINVAL;
|
||||
tmp.filter_cfg_chains[i] =
|
||||
cpu_to_le32(wifi_pkg->package.elements[i + 1].integer.value);
|
||||
}
|
||||
|
||||
IWL_DEBUG_RADIO(fwrt, "Loaded WPFC filter config from ACPI\n");
|
||||
*filters = tmp;
|
||||
out_free:
|
||||
kfree(data);
|
||||
return 0;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_acpi_get_phy_filters);
|
||||
|
||||
@@ -998,3 +1047,37 @@ int iwl_acpi_get_wbem(struct iwl_fw_runtime *fwrt, u32 *value)
|
||||
kfree(data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iwl_acpi_get_dsbr(struct iwl_fw_runtime *fwrt, u32 *value)
|
||||
{
|
||||
union acpi_object *wifi_pkg, *data;
|
||||
int ret = -ENOENT;
|
||||
int tbl_rev;
|
||||
|
||||
data = iwl_acpi_get_object(fwrt->dev, ACPI_DSBR_METHOD);
|
||||
if (IS_ERR(data))
|
||||
return ret;
|
||||
|
||||
wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
|
||||
ACPI_DSBR_WIFI_DATA_SIZE,
|
||||
&tbl_rev);
|
||||
if (IS_ERR(wifi_pkg))
|
||||
goto out_free;
|
||||
|
||||
if (tbl_rev != ACPI_DSBR_WIFI_DATA_REV) {
|
||||
IWL_DEBUG_RADIO(fwrt, "Unsupported ACPI DSBR revision:%d\n",
|
||||
tbl_rev);
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
if (wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER)
|
||||
goto out_free;
|
||||
|
||||
*value = wifi_pkg->package.elements[1].integer.value;
|
||||
IWL_DEBUG_RADIO(fwrt, "Loaded DSBR config from ACPI value: 0x%x\n",
|
||||
*value);
|
||||
ret = 0;
|
||||
out_free:
|
||||
kfree(data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018-2023 Intel Corporation
|
||||
* Copyright (C) 2018-2023, 2025 Intel Corporation
|
||||
*/
|
||||
#ifndef __iwl_fw_acpi__
|
||||
#define __iwl_fw_acpi__
|
||||
@@ -28,6 +28,7 @@
|
||||
#define ACPI_WPFC_METHOD "WPFC"
|
||||
#define ACPI_GLAI_METHOD "GLAI"
|
||||
#define ACPI_WBEM_METHOD "WBEM"
|
||||
#define ACPI_DSBR_METHOD "DSBR"
|
||||
|
||||
#define ACPI_WIFI_DOMAIN (0x07)
|
||||
|
||||
@@ -74,6 +75,13 @@
|
||||
* and one for enablement of Wi-Fi 320MHz per MCC
|
||||
*/
|
||||
#define ACPI_WBEM_WIFI_DATA_SIZE 2
|
||||
/*
|
||||
* One element for domain type,
|
||||
* and one for DSBR response data
|
||||
*/
|
||||
#define ACPI_DSBR_WIFI_DATA_SIZE 2
|
||||
#define ACPI_DSBR_WIFI_DATA_REV 1
|
||||
|
||||
/*
|
||||
* One element for domain type,
|
||||
* and one for the status
|
||||
@@ -101,6 +109,30 @@
|
||||
|
||||
#define ACPI_DSM_REV 0
|
||||
|
||||
#define DSM_INTERNAL_FUNC_GET_PLAT_INFO 1
|
||||
/* TBD: VPRO is BIT(0) in the result, but what's the result? */
|
||||
|
||||
#define DSM_INTERNAL_FUNC_PRODUCT_RESET 2
|
||||
|
||||
/* DSM_INTERNAL_FUNC_PRODUCT_RESET - product reset (aka "PLDR") */
|
||||
enum iwl_dsm_internal_product_reset_cmds {
|
||||
DSM_INTERNAL_PLDR_CMD_GET_MODE = 1,
|
||||
DSM_INTERNAL_PLDR_CMD_SET_MODE = 2,
|
||||
DSM_INTERNAL_PLDR_CMD_GET_STATUS = 3,
|
||||
};
|
||||
|
||||
enum iwl_dsm_internal_product_reset_mode {
|
||||
DSM_INTERNAL_PLDR_MODE_EN_PROD_RESET = BIT(0),
|
||||
DSM_INTERNAL_PLDR_MODE_EN_WIFI_FLR = BIT(1),
|
||||
DSM_INTERNAL_PLDR_MODE_EN_BT_OFF_ON = BIT(2),
|
||||
};
|
||||
|
||||
struct iwl_dsm_internal_product_reset_cmd {
|
||||
/* cmd is from enum iwl_dsm_internal_product_reset_cmds */
|
||||
u16 cmd;
|
||||
u16 value;
|
||||
} __packed;
|
||||
|
||||
#define IWL_ACPI_WBEM_REV0_MASK (BIT(0) | BIT(1))
|
||||
#define IWL_ACPI_WBEM_REVISION 0
|
||||
|
||||
@@ -110,6 +142,10 @@ struct iwl_fw_runtime;
|
||||
|
||||
extern const guid_t iwl_guid;
|
||||
|
||||
union acpi_object *iwl_acpi_get_dsm_object(struct device *dev, int rev,
|
||||
int func, union acpi_object *args,
|
||||
const guid_t *guid);
|
||||
|
||||
/**
|
||||
* iwl_acpi_get_mcc - read MCC from ACPI, if available
|
||||
*
|
||||
@@ -144,8 +180,7 @@ int iwl_acpi_get_tas_table(struct iwl_fw_runtime *fwrt,
|
||||
|
||||
int iwl_acpi_get_ppag_table(struct iwl_fw_runtime *fwrt);
|
||||
|
||||
void iwl_acpi_get_phy_filters(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_phy_specific_cfg *filters);
|
||||
int iwl_acpi_get_phy_filters(struct iwl_fw_runtime *fwrt);
|
||||
|
||||
void iwl_acpi_get_guid_lock_status(struct iwl_fw_runtime *fwrt);
|
||||
|
||||
@@ -153,10 +188,14 @@ int iwl_acpi_get_dsm(struct iwl_fw_runtime *fwrt,
|
||||
enum iwl_dsm_funcs func, u32 *value);
|
||||
|
||||
int iwl_acpi_get_wbem(struct iwl_fw_runtime *fwrt, u32 *value);
|
||||
|
||||
int iwl_acpi_get_dsbr(struct iwl_fw_runtime *fwrt, u32 *value);
|
||||
|
||||
#else /* CONFIG_ACPI */
|
||||
|
||||
static inline void *iwl_acpi_get_dsm_object(struct device *dev, int rev,
|
||||
int func, union acpi_object *args)
|
||||
static inline union acpi_object *
|
||||
iwl_acpi_get_dsm_object(struct device *dev, int rev, int func,
|
||||
union acpi_object *args, const guid_t *guid)
|
||||
{
|
||||
return ERR_PTR(-ENOENT);
|
||||
}
|
||||
@@ -204,8 +243,10 @@ static inline int iwl_acpi_get_ppag_table(struct iwl_fw_runtime *fwrt)
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/* macro since the second argument doesn't always exist */
|
||||
#define iwl_acpi_get_phy_filters(fwrt, filters) do { } while (0)
|
||||
static inline int iwl_acpi_get_phy_filters(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static inline void iwl_acpi_get_guid_lock_status(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
@@ -221,6 +262,11 @@ static inline int iwl_acpi_get_wbem(struct iwl_fw_runtime *fwrt, u32 *value)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static inline int iwl_acpi_get_dsbr(struct iwl_fw_runtime *fwrt, u32 *value)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
#endif /* CONFIG_ACPI */
|
||||
|
||||
#endif /* __iwl_fw_acpi__ */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018, 2020-2021, 2024 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018, 2020-2021, 2024-2025 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
@@ -82,21 +82,6 @@ struct iwl_alive_ntf_v3 {
|
||||
struct iwl_umac_alive umac_data;
|
||||
} __packed; /* UCODE_ALIVE_NTFY_API_S_VER_3 */
|
||||
|
||||
struct iwl_alive_ntf_v4 {
|
||||
__le16 status;
|
||||
__le16 flags;
|
||||
struct iwl_lmac_alive lmac_data[2];
|
||||
struct iwl_umac_alive umac_data;
|
||||
} __packed; /* UCODE_ALIVE_NTFY_API_S_VER_4 */
|
||||
|
||||
struct iwl_alive_ntf_v5 {
|
||||
__le16 status;
|
||||
__le16 flags;
|
||||
struct iwl_lmac_alive lmac_data[2];
|
||||
struct iwl_umac_alive umac_data;
|
||||
struct iwl_sku_id sku_id;
|
||||
} __packed; /* UCODE_ALIVE_NTFY_API_S_VER_5 */
|
||||
|
||||
struct iwl_imr_alive_info {
|
||||
__le64 base_addr;
|
||||
__le32 size;
|
||||
@@ -112,12 +97,22 @@ struct iwl_alive_ntf_v6 {
|
||||
struct iwl_imr_alive_info imr;
|
||||
} __packed; /* UCODE_ALIVE_NTFY_API_S_VER_6 */
|
||||
|
||||
struct iwl_alive_ntf {
|
||||
__le16 status;
|
||||
__le16 flags;
|
||||
struct iwl_lmac_alive lmac_data[2];
|
||||
struct iwl_umac_alive umac_data;
|
||||
struct iwl_sku_id sku_id;
|
||||
struct iwl_imr_alive_info imr;
|
||||
__le64 platform_id;
|
||||
} __packed; /* UCODE_ALIVE_NTFY_API_S_VER_8 */
|
||||
|
||||
/**
|
||||
* enum iwl_extended_cfg_flags - commands driver may send before
|
||||
* finishing init flow
|
||||
* @IWL_INIT_DEBUG_CFG: driver is going to send debug config command
|
||||
* @IWL_INIT_NVM: driver is going to send NVM_ACCESS commands
|
||||
* @IWL_INIT_PHY: driver is going to send PHY_DB commands
|
||||
* @IWL_INIT_PHY: driver is going to send the PHY_CONFIGURATION_CMD
|
||||
*/
|
||||
enum iwl_extended_cfg_flags {
|
||||
IWL_INIT_DEBUG_CFG,
|
||||
|
||||
@@ -56,8 +56,6 @@ struct iwl_binding_cmd {
|
||||
} __packed; /* BINDING_CMD_API_S_VER_2 */
|
||||
|
||||
#define IWL_BINDING_CMD_SIZE_V1 sizeof(struct iwl_binding_cmd_v1)
|
||||
#define IWL_LMAC_24G_INDEX 0
|
||||
#define IWL_LMAC_5G_INDEX 1
|
||||
|
||||
/* The maximal number of fragments in the FW's schedule session */
|
||||
#define IWL_MVM_MAX_QUOTA 128
|
||||
|
||||
@@ -95,7 +95,7 @@ enum iwl_bt_ci_compliance {
|
||||
}; /* BT_COEX_CI_COMPLIENCE_E_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_bt_coex_profile_notif - notification about BT coex
|
||||
* struct iwl_bt_coex_prof_old_notif - notification about BT coex
|
||||
* @mbox_msg: message from BT to WiFi
|
||||
* @msg_idx: the index of the message
|
||||
* @bt_ci_compliance: enum %iwl_bt_ci_compliance
|
||||
@@ -110,7 +110,7 @@ enum iwl_bt_ci_compliance {
|
||||
* @wifi_loss_mid_high_rssi: The predicted lost WiFi rate (% of air time that
|
||||
* BT is utilizing) when the RSSI is mid/high (>= -65 dBm)
|
||||
*/
|
||||
struct iwl_bt_coex_profile_notif {
|
||||
struct iwl_bt_coex_prof_old_notif {
|
||||
__le32 mbox_msg[4];
|
||||
__le32 msg_idx;
|
||||
__le32 bt_ci_compliance;
|
||||
@@ -126,4 +126,29 @@ struct iwl_bt_coex_profile_notif {
|
||||
* BT_COEX_PROFILE_NTFY_API_S_VER_5
|
||||
*/
|
||||
|
||||
/**
|
||||
* enum iwl_bt_coex_subcmd_ids - coex configuration command IDs
|
||||
*/
|
||||
enum iwl_bt_coex_subcmd_ids {
|
||||
/**
|
||||
*@PROFILE_NOTIF: &struct iwl_bt_coex_profile_notif
|
||||
*/
|
||||
PROFILE_NOTIF = 0xFF,
|
||||
};
|
||||
|
||||
#define COEX_NUM_BAND 3
|
||||
#define COEX_NUM_CHAINS 2
|
||||
|
||||
/**
|
||||
* struct iwl_bt_coex_profile_notif - notification about BT coex
|
||||
* @wifi_loss_low_rssi: The predicted lost WiFi rate (% of air time that BT is
|
||||
* utilizing) when the RSSI is low (<= -65 dBm)
|
||||
* @wifi_loss_mid_high_rssi: The predicted lost WiFi rate (% of air time that
|
||||
* BT is utilizing) when the RSSI is mid/high (>= -65 dBm)
|
||||
*/
|
||||
struct iwl_bt_coex_profile_notif {
|
||||
u8 wifi_loss_low_rssi[COEX_NUM_BAND][COEX_NUM_CHAINS];
|
||||
u8 wifi_loss_mid_high_rssi[COEX_NUM_BAND][COEX_NUM_CHAINS];
|
||||
} __packed; /* BT_COEX_BT_PROFILE_NTF_API_S_VER_1 */
|
||||
|
||||
#endif /* __iwl_fw_api_coex_h__ */
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
/*
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018-2022 Intel Corporation
|
||||
* Copyright (C) 2018-2022, 2024-2025 Intel Corporation
|
||||
*/
|
||||
#ifndef __iwl_fw_api_commands_h__
|
||||
#define __iwl_fw_api_commands_h__
|
||||
@@ -25,6 +25,8 @@
|
||||
* @NAN_GROUP: NAN group, uses command IDs from &enum iwl_nan_subcmd_ids
|
||||
* @LOCATION_GROUP: location group, uses command IDs from
|
||||
* &enum iwl_location_subcmd_ids
|
||||
* @BT_COEX_GROUP: bt coex group, uses command IDs from
|
||||
* &enum iwl_bt_coex_subcmd_ids
|
||||
* @PROT_OFFLOAD_GROUP: protocol offload group, uses command IDs from
|
||||
* &enum iwl_prot_offload_subcmd_ids
|
||||
* @REGULATORY_AND_NVM_GROUP: regulatory/NVM group, uses command IDs from
|
||||
@@ -43,6 +45,7 @@ enum iwl_mvm_command_groups {
|
||||
SCAN_GROUP = 0x6,
|
||||
NAN_GROUP = 0x7,
|
||||
LOCATION_GROUP = 0x8,
|
||||
BT_COEX_GROUP = 0x9,
|
||||
PROT_OFFLOAD_GROUP = 0xb,
|
||||
REGULATORY_AND_NVM_GROUP = 0xc,
|
||||
DEBUG_GROUP = 0xf,
|
||||
@@ -142,10 +145,10 @@ enum iwl_legacy_cmds {
|
||||
REMOVE_STA = 0x19,
|
||||
|
||||
/**
|
||||
* @TX_CMD: uses &struct iwl_tx_cmd or &struct iwl_tx_cmd_gen2 or
|
||||
* &struct iwl_tx_cmd_gen3,
|
||||
* response in &struct iwl_mvm_tx_resp or
|
||||
* &struct iwl_mvm_tx_resp_v3
|
||||
* @TX_CMD: uses &struct iwl_tx_cmd_v6 or &struct iwl_tx_cmd_v9 or
|
||||
* &struct iwl_tx_cmd,
|
||||
* response in &struct iwl_tx_resp or
|
||||
* &struct iwl_tx_resp_v3
|
||||
*/
|
||||
TX_CMD = 0x1c,
|
||||
|
||||
@@ -398,7 +401,7 @@ enum iwl_legacy_cmds {
|
||||
REDUCE_TX_POWER_CMD = 0x9f,
|
||||
|
||||
/**
|
||||
* @MISSED_BEACONS_NOTIFICATION: &struct iwl_missed_beacons_notif
|
||||
* @MISSED_BEACONS_NOTIFICATION: &struct iwl_missed_beacons_notif_v4
|
||||
*/
|
||||
MISSED_BEACONS_NOTIFICATION = 0xa2,
|
||||
|
||||
@@ -444,7 +447,7 @@ enum iwl_legacy_cmds {
|
||||
|
||||
/**
|
||||
* @BA_NOTIF:
|
||||
* BlockAck notification, uses &struct iwl_mvm_compressed_ba_notif
|
||||
* BlockAck notification, uses &struct iwl_compressed_ba_notif
|
||||
* or &struct iwl_mvm_ba_notif depending on the HW
|
||||
*/
|
||||
BA_NOTIF = 0xc5,
|
||||
@@ -467,7 +470,7 @@ enum iwl_legacy_cmds {
|
||||
MARKER_CMD = 0xcb,
|
||||
|
||||
/**
|
||||
* @BT_PROFILE_NOTIFICATION: &struct iwl_bt_coex_profile_notif
|
||||
* @BT_PROFILE_NOTIFICATION: &struct iwl_bt_coex_prof_old_notif
|
||||
*/
|
||||
BT_PROFILE_NOTIFICATION = 0xce,
|
||||
|
||||
@@ -499,10 +502,15 @@ enum iwl_legacy_cmds {
|
||||
/**
|
||||
* @DTS_MEASUREMENT_NOTIFICATION:
|
||||
* &struct iwl_dts_measurement_notif_v1 or
|
||||
* &struct iwl_dts_measurement_notif_v2
|
||||
* &struct iwl_dts_measurement_notif
|
||||
*/
|
||||
DTS_MEASUREMENT_NOTIFICATION = 0xdd,
|
||||
|
||||
/**
|
||||
* @DEBUG_HOST_COMMAND: &struct iwl_dhc_cmd
|
||||
*/
|
||||
DEBUG_HOST_COMMAND = 0xf1,
|
||||
|
||||
/**
|
||||
* @LDBG_CONFIG_CMD: configure continuous trace recording
|
||||
*/
|
||||
@@ -565,9 +573,8 @@ enum iwl_legacy_cmds {
|
||||
WOWLAN_KEK_KCK_MATERIAL = 0xe4,
|
||||
|
||||
/**
|
||||
* @WOWLAN_GET_STATUSES: response in &struct iwl_wowlan_status_v6,
|
||||
* &struct iwl_wowlan_status_v7, &struct iwl_wowlan_status_v9 or
|
||||
* &struct iwl_wowlan_status_v12
|
||||
* @WOWLAN_GET_STATUSES: response in &struct iwl_wowlan_status_v6 or
|
||||
* &struct iwl_wowlan_status_v7
|
||||
*/
|
||||
WOWLAN_GET_STATUSES = 0xe5,
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2022 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2022, 2024 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
@@ -14,6 +14,9 @@
|
||||
* @FW_CTXT_COLOR_POS: position of the color
|
||||
* @FW_CTXT_COLOR_MSK: mask of the color
|
||||
* @FW_CTXT_INVALID: value used to indicate unused/invalid
|
||||
* @FW_CTXT_ID_INVALID: value used to indicate unused/invalid. This can be
|
||||
* used with newer firmware which no longer use the color. Typically,
|
||||
* firmware versions supported by iwlmld can use this value.
|
||||
*/
|
||||
enum iwl_ctxt_id_and_color {
|
||||
FW_CTXT_ID_POS = 0,
|
||||
@@ -21,6 +24,7 @@ enum iwl_ctxt_id_and_color {
|
||||
FW_CTXT_COLOR_POS = 8,
|
||||
FW_CTXT_COLOR_MSK = 0xff << FW_CTXT_COLOR_POS,
|
||||
FW_CTXT_INVALID = 0xffffffff,
|
||||
FW_CTXT_ID_INVALID = 0xff,
|
||||
};
|
||||
|
||||
#define FW_CMD_ID_AND_COLOR(_id, _color) (((_id) << FW_CTXT_ID_POS) |\
|
||||
@@ -40,4 +44,7 @@ enum iwl_ctxt_action {
|
||||
FW_CTXT_ACTION_REMOVE,
|
||||
}; /* COMMON_CONTEXT_ACTION_API_E_VER_1 */
|
||||
|
||||
#define IWL_LMAC_24G_INDEX 0
|
||||
#define IWL_LMAC_5G_INDEX 1
|
||||
|
||||
#endif /* __iwl_fw_api_context_h__ */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2024 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2025 Intel Corporation
|
||||
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2015-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
@@ -19,9 +19,11 @@ enum iwl_d0i3_flags {
|
||||
/**
|
||||
* enum iwl_d3_wakeup_flags - D3 manager wakeup flags
|
||||
* @IWL_WAKEUP_D3_CONFIG_FW_ERROR: wake up on firmware sysassert
|
||||
* @IWL_WAKEUP_D3_HOST_TIMER: wake up on host timer expiry
|
||||
*/
|
||||
enum iwl_d3_wakeup_flags {
|
||||
IWL_WAKEUP_D3_CONFIG_FW_ERROR = BIT(0),
|
||||
IWL_WAKEUP_D3_CONFIG_FW_ERROR = BIT(0),
|
||||
IWL_WAKEUP_D3_HOST_TIMER = BIT(1),
|
||||
}; /* D3_MANAGER_WAKEUP_CONFIG_API_E_VER_3 */
|
||||
|
||||
/**
|
||||
@@ -368,7 +370,7 @@ enum iwl_wowlan_flags {
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_wowlan_config_cmd - WoWLAN configuration (versions 5 and 6)
|
||||
* struct iwl_wowlan_config_cmd_v6 - WoWLAN configuration (versions 5 and 6)
|
||||
* @wakeup_filter: filter from &enum iwl_wowlan_wakeup_filters
|
||||
* @non_qos_seq: non-QoS sequence counter to use next.
|
||||
* Reserved if the struct has version >= 6.
|
||||
@@ -380,7 +382,7 @@ enum iwl_wowlan_flags {
|
||||
* @sta_id: station ID for wowlan.
|
||||
* @reserved: reserved
|
||||
*/
|
||||
struct iwl_wowlan_config_cmd {
|
||||
struct iwl_wowlan_config_cmd_v6 {
|
||||
__le32 wakeup_filter;
|
||||
__le16 non_qos_seq;
|
||||
__le16 qos_seq[8];
|
||||
@@ -390,7 +392,27 @@ struct iwl_wowlan_config_cmd {
|
||||
u8 flags;
|
||||
u8 sta_id;
|
||||
u8 reserved;
|
||||
} __packed; /* WOWLAN_CONFIG_API_S_VER_5 */
|
||||
} __packed; /* WOWLAN_CONFIG_API_S_VER_6 */
|
||||
|
||||
/**
|
||||
* struct iwl_wowlan_config_cmd - WoWLAN configuration
|
||||
* @wakeup_filter: filter from &enum iwl_wowlan_wakeup_filters
|
||||
* @wowlan_ba_teardown_tids: bitmap of BA sessions to tear down
|
||||
* @is_11n_connection: indicates HT connection
|
||||
* @offloading_tid: TID reserved for firmware use
|
||||
* @flags: extra flags, see &enum iwl_wowlan_flags
|
||||
* @sta_id: station ID for wowlan.
|
||||
* @reserved: reserved
|
||||
*/
|
||||
struct iwl_wowlan_config_cmd {
|
||||
__le32 wakeup_filter;
|
||||
u8 wowlan_ba_teardown_tids;
|
||||
u8 is_11n_connection;
|
||||
u8 offloading_tid;
|
||||
u8 flags;
|
||||
u8 sta_id;
|
||||
u8 reserved[3];
|
||||
} __packed; /* WOWLAN_CONFIG_API_S_VER_7 */
|
||||
|
||||
#define IWL_NUM_RSC 16
|
||||
#define WOWLAN_KEY_MAX_SIZE 32
|
||||
@@ -434,11 +456,6 @@ struct iwl_wowlan_rsc_tsc_params_cmd_ver_2 {
|
||||
union iwl_all_tsc_rsc all_tsc_rsc;
|
||||
} __packed; /* ALL_TSC_RSC_API_S_VER_2 */
|
||||
|
||||
struct iwl_wowlan_rsc_tsc_params_cmd_v4 {
|
||||
struct iwl_wowlan_rsc_tsc_params_cmd_ver_2 params;
|
||||
__le32 sta_id;
|
||||
} __packed; /* ALL_TSC_RSC_API_S_VER_4 */
|
||||
|
||||
struct iwl_wowlan_rsc_tsc_params_cmd {
|
||||
__le64 ucast_rsc[IWL_MAX_TID_COUNT];
|
||||
__le64 mcast_rsc[WOWLAN_GTK_KEYS_NUM][IWL_MAX_TID_COUNT];
|
||||
@@ -697,82 +714,6 @@ struct iwl_wowlan_status_v7 {
|
||||
u8 wake_packet[]; /* can be truncated from _length to _bufsize */
|
||||
} __packed; /* WOWLAN_STATUSES_API_S_VER_7 */
|
||||
|
||||
/**
|
||||
* struct iwl_wowlan_status_v9 - WoWLAN status (versions 9 and 10)
|
||||
* @gtk: GTK data
|
||||
* @igtk: IGTK data
|
||||
* @replay_ctr: GTK rekey replay counter
|
||||
* @pattern_number: number of the matched pattern
|
||||
* @non_qos_seq_ctr: non-QoS sequence counter to use next.
|
||||
* Reserved if the struct has version >= 10.
|
||||
* @qos_seq_ctr: QoS sequence counters to use next
|
||||
* @wakeup_reasons: wakeup reasons, see &enum iwl_wowlan_wakeup_reason
|
||||
* @num_of_gtk_rekeys: number of GTK rekeys
|
||||
* @transmitted_ndps: number of transmitted neighbor discovery packets
|
||||
* @received_beacons: number of received beacons
|
||||
* @wake_packet_length: wakeup packet length
|
||||
* @wake_packet_bufsize: wakeup packet buffer size
|
||||
* @tid_tear_down: bit mask of tids whose BA sessions were closed
|
||||
* in suspend state
|
||||
* @reserved: unused
|
||||
* @wake_packet: wakeup packet
|
||||
*/
|
||||
struct iwl_wowlan_status_v9 {
|
||||
struct iwl_wowlan_gtk_status_v2 gtk[WOWLAN_GTK_KEYS_NUM];
|
||||
struct iwl_wowlan_igtk_status igtk[WOWLAN_IGTK_KEYS_NUM];
|
||||
__le64 replay_ctr;
|
||||
__le16 pattern_number;
|
||||
__le16 non_qos_seq_ctr;
|
||||
__le16 qos_seq_ctr[8];
|
||||
__le32 wakeup_reasons;
|
||||
__le32 num_of_gtk_rekeys;
|
||||
__le32 transmitted_ndps;
|
||||
__le32 received_beacons;
|
||||
__le32 wake_packet_length;
|
||||
__le32 wake_packet_bufsize;
|
||||
u8 tid_tear_down;
|
||||
u8 reserved[3];
|
||||
u8 wake_packet[]; /* can be truncated from _length to _bufsize */
|
||||
} __packed; /* WOWLAN_STATUSES_RSP_API_S_VER_9 */
|
||||
|
||||
/**
|
||||
* struct iwl_wowlan_status_v12 - WoWLAN status
|
||||
* @gtk: GTK data
|
||||
* @igtk: IGTK data
|
||||
* @replay_ctr: GTK rekey replay counter
|
||||
* @pattern_number: number of the matched pattern
|
||||
* @non_qos_seq_ctr: non-QoS sequence counter to use next.
|
||||
* Reserved if the struct has version >= 10.
|
||||
* @qos_seq_ctr: QoS sequence counters to use next
|
||||
* @wakeup_reasons: wakeup reasons, see &enum iwl_wowlan_wakeup_reason
|
||||
* @num_of_gtk_rekeys: number of GTK rekeys
|
||||
* @transmitted_ndps: number of transmitted neighbor discovery packets
|
||||
* @received_beacons: number of received beacons
|
||||
* @wake_packet_length: wakeup packet length
|
||||
* @wake_packet_bufsize: wakeup packet buffer size
|
||||
* @tid_tear_down: bit mask of tids whose BA sessions were closed
|
||||
* in suspend state
|
||||
* @reserved: unused
|
||||
* @wake_packet: wakeup packet
|
||||
*/
|
||||
struct iwl_wowlan_status_v12 {
|
||||
struct iwl_wowlan_gtk_status_v3 gtk[WOWLAN_GTK_KEYS_NUM];
|
||||
struct iwl_wowlan_igtk_status igtk[WOWLAN_IGTK_KEYS_NUM];
|
||||
__le64 replay_ctr;
|
||||
__le16 pattern_number;
|
||||
__le16 non_qos_seq_ctr;
|
||||
__le16 qos_seq_ctr[8];
|
||||
__le32 wakeup_reasons;
|
||||
__le32 num_of_gtk_rekeys;
|
||||
__le32 transmitted_ndps;
|
||||
__le32 received_beacons;
|
||||
__le32 wake_packet_length;
|
||||
__le32 wake_packet_bufsize;
|
||||
u8 tid_tear_down;
|
||||
u8 reserved[3];
|
||||
u8 wake_packet[]; /* can be truncated from _length to _bufsize */
|
||||
} __packed; /* WOWLAN_STATUSES_RSP_API_S_VER_12 */
|
||||
|
||||
/**
|
||||
* struct iwl_wowlan_info_notif_v1 - WoWLAN information notification
|
||||
* @gtk: GTK data
|
||||
@@ -810,39 +751,6 @@ struct iwl_wowlan_info_notif_v1 {
|
||||
u8 reserved2[2];
|
||||
} __packed; /* WOWLAN_INFO_NTFY_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_wowlan_info_notif_v2 - WoWLAN information notification
|
||||
* @gtk: GTK data
|
||||
* @igtk: IGTK data
|
||||
* @replay_ctr: GTK rekey replay counter
|
||||
* @pattern_number: number of the matched patterns
|
||||
* @reserved1: reserved
|
||||
* @qos_seq_ctr: QoS sequence counters to use next
|
||||
* @wakeup_reasons: wakeup reasons, see &enum iwl_wowlan_wakeup_reason
|
||||
* @num_of_gtk_rekeys: number of GTK rekeys
|
||||
* @transmitted_ndps: number of transmitted neighbor discovery packets
|
||||
* @received_beacons: number of received beacons
|
||||
* @tid_tear_down: bit mask of tids whose BA sessions were closed
|
||||
* in suspend state
|
||||
* @station_id: station id
|
||||
* @reserved2: reserved
|
||||
*/
|
||||
struct iwl_wowlan_info_notif_v2 {
|
||||
struct iwl_wowlan_gtk_status_v3 gtk[WOWLAN_GTK_KEYS_NUM];
|
||||
struct iwl_wowlan_igtk_status igtk[WOWLAN_IGTK_KEYS_NUM];
|
||||
__le64 replay_ctr;
|
||||
__le16 pattern_number;
|
||||
__le16 reserved1;
|
||||
__le16 qos_seq_ctr[8];
|
||||
__le32 wakeup_reasons;
|
||||
__le32 num_of_gtk_rekeys;
|
||||
__le32 transmitted_ndps;
|
||||
__le32 received_beacons;
|
||||
u8 tid_tear_down;
|
||||
u8 station_id;
|
||||
u8 reserved2[2];
|
||||
} __packed; /* WOWLAN_INFO_NTFY_API_S_VER_2 */
|
||||
|
||||
/* MAX MLO keys of non-active links that can arrive in the notification */
|
||||
#define WOWLAN_MAX_MLO_KEYS 18
|
||||
|
||||
@@ -890,7 +798,7 @@ struct iwl_wowlan_mlo_gtk {
|
||||
} __packed; /* WOWLAN_MLO_GTK_KEY_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_wowlan_info_notif - WoWLAN information notification
|
||||
* struct iwl_wowlan_info_notif_v3 - WoWLAN information notification
|
||||
* @gtk: GTK data
|
||||
* @igtk: IGTK data
|
||||
* @bigtk: BIGTK data
|
||||
@@ -905,12 +813,9 @@ struct iwl_wowlan_mlo_gtk {
|
||||
* @tid_tear_down: bit mask of tids whose BA sessions were closed
|
||||
* in suspend state
|
||||
* @station_id: station id
|
||||
* @num_mlo_link_keys: number of &struct iwl_wowlan_mlo_gtk structs
|
||||
* following this notif, or reserved in version < 4
|
||||
* @reserved2: reserved
|
||||
* @mlo_gtks: array of GTKs of size num_mlo_link_keys for version >= 4
|
||||
*/
|
||||
struct iwl_wowlan_info_notif {
|
||||
struct iwl_wowlan_info_notif_v3 {
|
||||
struct iwl_wowlan_gtk_status_v3 gtk[WOWLAN_GTK_KEYS_NUM];
|
||||
struct iwl_wowlan_igtk_status igtk[WOWLAN_IGTK_KEYS_NUM];
|
||||
struct iwl_wowlan_igtk_status bigtk[WOWLAN_BIGTK_KEYS_NUM];
|
||||
@@ -924,10 +829,47 @@ struct iwl_wowlan_info_notif {
|
||||
__le32 received_beacons;
|
||||
u8 tid_tear_down;
|
||||
u8 station_id;
|
||||
u8 reserved2[2];
|
||||
} __packed; /* WOWLAN_INFO_NTFY_API_S_VER_3 */
|
||||
|
||||
/**
|
||||
* struct iwl_wowlan_info_notif - WoWLAN information notification
|
||||
* @gtk: GTK data
|
||||
* @igtk: IGTK data
|
||||
* @bigtk: BIGTK data
|
||||
* @replay_ctr: GTK rekey replay counter
|
||||
* @pattern_number: number of the matched patterns
|
||||
* @qos_seq_ctr: QoS sequence counters to use next
|
||||
* @wakeup_reasons: wakeup reasons, see &enum iwl_wowlan_wakeup_reason
|
||||
* @num_of_gtk_rekeys: number of GTK rekeys
|
||||
* @transmitted_ndps: number of transmitted neighbor discovery packets
|
||||
* @received_beacons: number of received beacons
|
||||
* @tid_tear_down: bit mask of tids whose BA sessions were closed
|
||||
* in suspend state
|
||||
* @station_id: station id
|
||||
* @num_mlo_link_keys: number of &struct iwl_wowlan_mlo_gtk structs
|
||||
* following this notif
|
||||
* @tid_offloaded_tx: tid used by the firmware to transmit data packets
|
||||
* while in wowlan
|
||||
* @mlo_gtks: array of GTKs of size num_mlo_link_keys
|
||||
*/
|
||||
struct iwl_wowlan_info_notif {
|
||||
struct iwl_wowlan_gtk_status_v3 gtk[WOWLAN_GTK_KEYS_NUM];
|
||||
struct iwl_wowlan_igtk_status igtk[WOWLAN_IGTK_KEYS_NUM];
|
||||
struct iwl_wowlan_igtk_status bigtk[WOWLAN_BIGTK_KEYS_NUM];
|
||||
__le64 replay_ctr;
|
||||
__le16 pattern_number;
|
||||
__le16 qos_seq_ctr;
|
||||
__le32 wakeup_reasons;
|
||||
__le32 num_of_gtk_rekeys;
|
||||
__le32 transmitted_ndps;
|
||||
__le32 received_beacons;
|
||||
u8 tid_tear_down;
|
||||
u8 station_id;
|
||||
u8 num_mlo_link_keys;
|
||||
u8 reserved2;
|
||||
u8 tid_offloaded_tx;
|
||||
struct iwl_wowlan_mlo_gtk mlo_gtks[];
|
||||
} __packed; /* WOWLAN_INFO_NTFY_API_S_VER_3, _VER_4 */
|
||||
} __packed; /* WOWLAN_INFO_NTFY_API_S_VER_5 */
|
||||
|
||||
/**
|
||||
* struct iwl_wowlan_wake_pkt_notif - WoWLAN wake packet notification
|
||||
@@ -947,7 +889,7 @@ struct iwl_wowlan_wake_pkt_notif {
|
||||
* struct iwl_mvm_d3_end_notif - d3 end notification
|
||||
* @flags: See &enum iwl_d0i3_flags
|
||||
*/
|
||||
struct iwl_mvm_d3_end_notif {
|
||||
struct iwl_d3_end_notif {
|
||||
__le32 flags;
|
||||
} __packed;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2024 Intel Corporation
|
||||
* Copyright (C) 2024-2025 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2022 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
@@ -92,7 +92,7 @@ enum iwl_data_path_subcmd_ids {
|
||||
|
||||
/**
|
||||
* @ESR_MODE_NOTIF: notification to recommend/force a wanted esr mode,
|
||||
* uses &struct iwl_mvm_esr_mode_notif
|
||||
* uses &struct iwl_esr_mode_notif or &struct iwl_esr_mode_notif_v1
|
||||
*/
|
||||
ESR_MODE_NOTIF = 0xF3,
|
||||
|
||||
@@ -118,6 +118,11 @@ enum iwl_data_path_subcmd_ids {
|
||||
*/
|
||||
TLC_MNG_UPDATE_NOTIF = 0xF7,
|
||||
|
||||
/**
|
||||
* @BEACON_FILTER_IN_NOTIF: &struct iwl_beacon_filter_notif
|
||||
*/
|
||||
BEACON_FILTER_IN_NOTIF = 0xF8,
|
||||
|
||||
/**
|
||||
* @STA_PM_NOTIF: &struct iwl_mvm_pm_state_notification
|
||||
*/
|
||||
@@ -391,7 +396,7 @@ enum iwl_datapath_monitor_notif_type {
|
||||
|
||||
struct iwl_datapath_monitor_notif {
|
||||
__le32 type;
|
||||
u8 mac_id;
|
||||
u8 link_id;
|
||||
u8 reserved[3];
|
||||
} __packed; /* MONITOR_NTF_API_S_VER_1 */
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2018-2024 Intel Corporation
|
||||
* Copyright (C) 2018-2025 Intel Corporation
|
||||
*/
|
||||
#ifndef __iwl_fw_dbg_tlv_h__
|
||||
#define __iwl_fw_dbg_tlv_h__
|
||||
@@ -476,6 +476,8 @@ enum iwl_fw_ini_region_device_memory_subtype {
|
||||
* @IWL_FW_INI_TIME_POINT_PRESET_OVERRIDE_START: start handling override preset
|
||||
* request
|
||||
* @IWL_FW_INI_TIME_SCAN_FAILURE: failed scan channel list
|
||||
* @IWL_FW_INI_TIME_ESR_LINK_UP: EMLSR is active (several links are activated)
|
||||
* @IWL_FW_INI_TIME_ESR_LINK_DOWN: EMLSR is inactive (only one active link left)
|
||||
* @IWL_FW_INI_TIME_POINT_NUM: number of time points
|
||||
*/
|
||||
enum iwl_fw_ini_time_point {
|
||||
@@ -509,6 +511,8 @@ enum iwl_fw_ini_time_point {
|
||||
IWL_FW_INI_TIME_POINT_PRESET_OVERRIDE_EXT_REQ,
|
||||
IWL_FW_INI_TIME_POINT_PRESET_OVERRIDE_START,
|
||||
IWL_FW_INI_TIME_SCAN_FAILURE,
|
||||
IWL_FW_INI_TIME_ESR_LINK_UP,
|
||||
IWL_FW_INI_TIME_ESR_LINK_DOWN,
|
||||
IWL_FW_INI_TIME_POINT_NUM,
|
||||
}; /* FW_TLV_DEBUG_TIME_POINT_API_E */
|
||||
|
||||
@@ -523,6 +527,8 @@ enum iwl_fw_ini_time_point {
|
||||
* @IWL_FW_INI_APPLY_POLICY_OVERRIDE_DATA: override trigger data.
|
||||
* Append otherwise
|
||||
* @IWL_FW_INI_APPLY_POLICY_DUMP_COMPLETE_CMD: send cmd once dump collected
|
||||
* @IWL_FW_INI_APPLY_POLICY_SPLIT_DUMP_RESET: split this dump into regions
|
||||
* before and after the reset handshake
|
||||
*/
|
||||
enum iwl_fw_ini_trigger_apply_policy {
|
||||
IWL_FW_INI_APPLY_POLICY_MATCH_TIME_POINT = BIT(0),
|
||||
@@ -531,6 +537,7 @@ enum iwl_fw_ini_trigger_apply_policy {
|
||||
IWL_FW_INI_APPLY_POLICY_OVERRIDE_CFG = BIT(9),
|
||||
IWL_FW_INI_APPLY_POLICY_OVERRIDE_DATA = BIT(10),
|
||||
IWL_FW_INI_APPLY_POLICY_DUMP_COMPLETE_CMD = BIT(16),
|
||||
IWL_FW_INI_APPLY_POLICY_SPLIT_DUMP_RESET = BIT(17),
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -552,12 +559,14 @@ enum iwl_fw_ini_trigger_reset_fw_policy {
|
||||
* @IWL_FW_INI_DEBUG_DUMP_POLICY_NO_LIMIT: OS has no limit of dump size
|
||||
* @IWL_FW_INI_DEBUG_DUMP_POLICY_MAX_LIMIT_600KB: mini dump only 600KB region dump
|
||||
* @IWL_FW_IWL_DEBUG_DUMP_POLICY_MAX_LIMIT_5MB: mini dump 5MB size dump
|
||||
* @IWL_FW_IWL_DEBUG_DUMP_POLICY_BEFORE_RESET: dump this region before reset
|
||||
* handshake (if requested by %IWL_FW_INI_APPLY_POLICY_SPLIT_DUMP_RESET)
|
||||
*/
|
||||
enum iwl_fw_ini_dump_policy {
|
||||
IWL_FW_INI_DEBUG_DUMP_POLICY_NO_LIMIT = BIT(0),
|
||||
IWL_FW_INI_DEBUG_DUMP_POLICY_MAX_LIMIT_600KB = BIT(1),
|
||||
IWL_FW_IWL_DEBUG_DUMP_POLICY_MAX_LIMIT_5MB = BIT(2),
|
||||
|
||||
IWL_FW_IWL_DEBUG_DUMP_POLICY_BEFORE_RESET = BIT(3),
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2005-2014, 2018-2024 Intel Corporation
|
||||
* Copyright (C) 2005-2014, 2018-2025 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
@@ -51,7 +51,7 @@ enum iwl_debug_cmds {
|
||||
/**
|
||||
* @GET_TAS_STATUS:
|
||||
* sends command to fw to get TAS status
|
||||
* the response is &struct iwl_mvm_tas_status_resp
|
||||
* the response is &struct iwl_tas_status_resp
|
||||
*/
|
||||
GET_TAS_STATUS = 0xA,
|
||||
/**
|
||||
@@ -439,25 +439,20 @@ struct iwl_dbg_dump_complete_cmd {
|
||||
__le32 tp_data;
|
||||
} __packed; /* FW_DUMP_COMPLETE_CMD_API_S_VER_1 */
|
||||
|
||||
#define TAS_LMAC_BAND_HB 0
|
||||
#define TAS_LMAC_BAND_LB 1
|
||||
#define TAS_LMAC_BAND_UHB 2
|
||||
#define TAS_LMAC_BAND_INVALID 3
|
||||
|
||||
/**
|
||||
* struct iwl_mvm_tas_status_per_mac - tas status per lmac
|
||||
* struct iwl_tas_status_per_mac - tas status per lmac
|
||||
* @static_status: tas statically enabled or disabled per lmac - TRUE/FALSE
|
||||
* @static_dis_reason: TAS static disable reason, uses
|
||||
* &enum iwl_mvm_tas_statically_disabled_reason
|
||||
* &enum iwl_tas_statically_disabled_reason
|
||||
* @dynamic_status: Current TAS status. uses
|
||||
* &enum iwl_mvm_tas_dyna_status
|
||||
* &enum iwl_tas_dyna_status
|
||||
* @near_disconnection: is TAS currently near disconnection per lmac? - TRUE/FALSE
|
||||
* @max_reg_pwr_limit: Regulatory power limits in dBm
|
||||
* @sar_limit: SAR limits per lmac in dBm
|
||||
* @band: Band per lmac
|
||||
* @reserved: reserved
|
||||
*/
|
||||
struct iwl_mvm_tas_status_per_mac {
|
||||
struct iwl_tas_status_per_mac {
|
||||
u8 static_status;
|
||||
u8 static_dis_reason;
|
||||
u8 dynamic_status;
|
||||
@@ -466,31 +461,35 @@ struct iwl_mvm_tas_status_per_mac {
|
||||
__le16 sar_limit;
|
||||
u8 band;
|
||||
u8 reserved[3];
|
||||
} __packed; /*DEBUG_GET_TAS_STATUS_PER_MAC_S_VER_1*/
|
||||
} __packed; /* DEBUG_GET_TAS_STATUS_PER_MAC_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_mvm_tas_status_resp - Response to GET_TAS_STATUS
|
||||
* struct iwl_tas_status_resp - Response to GET_TAS_STATUS
|
||||
* @tas_fw_version: TAS FW version
|
||||
* @is_uhb_for_usa_enable: is UHB enabled in USA? - TRUE/FALSE
|
||||
* @curr_mcc: current mcc
|
||||
* @block_list: country block list
|
||||
* @tas_status_mac: TAS status per lmac, uses
|
||||
* &struct iwl_mvm_tas_status_per_mac
|
||||
* &struct iwl_tas_status_per_mac
|
||||
* @in_dual_radio: is TAS in dual radio? - TRUE/FALSE
|
||||
* @uhb_allowed_flags: see &enum iwl_tas_uhb_allowed_flags.
|
||||
* This member is valid only when fw has
|
||||
* %IWL_UCODE_TLV_CAPA_UHB_CANADA_TAS_SUPPORT capability.
|
||||
* @reserved: reserved
|
||||
*/
|
||||
struct iwl_mvm_tas_status_resp {
|
||||
struct iwl_tas_status_resp {
|
||||
u8 tas_fw_version;
|
||||
u8 is_uhb_for_usa_enable;
|
||||
__le16 curr_mcc;
|
||||
__le16 block_list[16];
|
||||
struct iwl_mvm_tas_status_per_mac tas_status_mac[2];
|
||||
struct iwl_tas_status_per_mac tas_status_mac[2];
|
||||
u8 in_dual_radio;
|
||||
u8 reserved[3];
|
||||
} __packed; /*DEBUG_GET_TAS_STATUS_RSP_API_S_VER_3*/
|
||||
u8 uhb_allowed_flags;
|
||||
u8 reserved[2];
|
||||
} __packed; /* DEBUG_GET_TAS_STATUS_RSP_API_S_VER_3 */
|
||||
|
||||
/**
|
||||
* enum iwl_mvm_tas_dyna_status - TAS current running status
|
||||
* enum iwl_tas_dyna_status - TAS current running status
|
||||
* @TAS_DYNA_INACTIVE: TAS status is inactive
|
||||
* @TAS_DYNA_INACTIVE_MVM_MODE: TAS is disabled due because FW is in MVM mode
|
||||
* or is in softap mode.
|
||||
@@ -503,7 +502,7 @@ struct iwl_mvm_tas_status_resp {
|
||||
* @TAS_DYNA_ACTIVE: TAS is currently active
|
||||
* @TAS_DYNA_STATUS_MAX: TAS status max value
|
||||
*/
|
||||
enum iwl_mvm_tas_dyna_status {
|
||||
enum iwl_tas_dyna_status {
|
||||
TAS_DYNA_INACTIVE,
|
||||
TAS_DYNA_INACTIVE_MVM_MODE,
|
||||
TAS_DYNA_INACTIVE_TRIGGER_MODE,
|
||||
@@ -512,19 +511,22 @@ enum iwl_mvm_tas_dyna_status {
|
||||
TAS_DYNA_ACTIVE,
|
||||
|
||||
TAS_DYNA_STATUS_MAX,
|
||||
}; /*_TAS_DYNA_STATUS_E*/
|
||||
};
|
||||
|
||||
/**
|
||||
* enum iwl_mvm_tas_statically_disabled_reason - TAS statically disabled reason
|
||||
* enum iwl_tas_statically_disabled_reason - TAS statically disabled reason
|
||||
* @TAS_DISABLED_DUE_TO_BIOS: TAS is disabled because TAS is disabled in BIOS
|
||||
* @TAS_DISABLED_DUE_TO_SAR_6DBM: TAS is disabled because SAR limit is less than 6 Dbm
|
||||
* @TAS_DISABLED_REASON_INVALID: TAS disable reason is invalid
|
||||
* @TAS_DISABLED_DUE_TO_TABLE_SOURCE_INVALID: TAS is disabled due to
|
||||
* table source invalid
|
||||
* @TAS_DISABLED_REASON_MAX: TAS disable reason max value
|
||||
*/
|
||||
enum iwl_mvm_tas_statically_disabled_reason {
|
||||
enum iwl_tas_statically_disabled_reason {
|
||||
TAS_DISABLED_DUE_TO_BIOS,
|
||||
TAS_DISABLED_DUE_TO_SAR_6DBM,
|
||||
TAS_DISABLED_REASON_INVALID,
|
||||
TAS_DISABLED_DUE_TO_TABLE_SOURCE_INVALID,
|
||||
|
||||
TAS_DISABLED_REASON_MAX,
|
||||
}; /*_TAS_STATICALLY_DISABLED_REASON_E*/
|
||||
|
||||
@@ -0,0 +1,230 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2025 Intel Corporation
|
||||
*/
|
||||
#ifndef __iwl_fw_api_dhc_h__
|
||||
#define __iwl_fw_api_dhc_h__
|
||||
|
||||
#define DHC_TABLE_MASK_POS (28)
|
||||
|
||||
/**
|
||||
* enum iwl_dhc_table_id - DHC table operations index
|
||||
*/
|
||||
enum iwl_dhc_table_id {
|
||||
/**
|
||||
* @DHC_TABLE_INTEGRATION: select the integration table
|
||||
*/
|
||||
DHC_TABLE_INTEGRATION = 2 << DHC_TABLE_MASK_POS,
|
||||
/**
|
||||
* @DHC_TABLE_TOOLS: select the tools table
|
||||
*/
|
||||
DHC_TABLE_TOOLS = 0,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum iwl_dhc_umac_tools_table - tools operations
|
||||
* @DHC_TOOLS_UMAC_GET_TAS_STATUS: Get TAS status.
|
||||
* See @struct iwl_dhc_tas_status_resp
|
||||
*/
|
||||
enum iwl_dhc_umac_tools_table {
|
||||
DHC_TOOLS_UMAC_GET_TAS_STATUS = 0,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum iwl_dhc_umac_integration_table - integration operations
|
||||
*/
|
||||
enum iwl_dhc_umac_integration_table {
|
||||
/**
|
||||
* @DHC_INT_UMAC_TWT_OPERATION: trigger a TWT operation
|
||||
*/
|
||||
DHC_INT_UMAC_TWT_OPERATION = 4,
|
||||
/**
|
||||
* @DHC_INTEGRATION_TLC_DEBUG_CONFIG: TLC debug
|
||||
*/
|
||||
DHC_INTEGRATION_TLC_DEBUG_CONFIG = 1,
|
||||
/**
|
||||
* @DHC_INTEGRATION_MAX: Maximum UMAC integration table entries
|
||||
*/
|
||||
DHC_INTEGRATION_MAX
|
||||
};
|
||||
|
||||
#define DHC_TARGET_UMAC BIT(27)
|
||||
|
||||
/**
|
||||
* struct iwl_dhc_cmd - debug host command
|
||||
* @length: length in DWs of the data structure that is concatenated to the end
|
||||
* of this struct
|
||||
* @index_and_mask: bit 31 is 1 for data set operation else it's 0
|
||||
* bits 28-30 is the index of the table of the operation -
|
||||
* &enum iwl_dhc_table_id *
|
||||
* bit 27 is 0 if the cmd targeted to LMAC and 1 if targeted to UMAC,
|
||||
* (LMAC is 0 for backward compatibility)
|
||||
* bit 26 is 0 if the cmd targeted to LMAC0 and 1 if targeted to LMAC1,
|
||||
* relevant only if bit 27 set to 0
|
||||
* bits 0-25 is a specific entry index in the table specified in bits 28-30
|
||||
*
|
||||
* @data: the concatenated data.
|
||||
*/
|
||||
struct iwl_dhc_cmd {
|
||||
__le32 length;
|
||||
__le32 index_and_mask;
|
||||
#if defined(__linux__)
|
||||
__le32 data[];
|
||||
#elif defined(__FreeBSD__)
|
||||
__le32 data[0];
|
||||
#endif
|
||||
} __packed; /* DHC_CMD_API_S */
|
||||
|
||||
/**
|
||||
* struct iwl_dhc_payload_hdr - DHC payload header
|
||||
* @version: a version of a payload
|
||||
* @reserved: reserved for alignment
|
||||
*/
|
||||
struct iwl_dhc_payload_hdr {
|
||||
u8 version;
|
||||
u8 reserved[3];
|
||||
} __packed; /* DHC_PAYLOAD_HDR_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_dhc_tas_status_per_radio - TAS status per radio
|
||||
* @band: &PHY_BAND_5 for high band, PHY_BAND_24 for low band and
|
||||
* &PHY_BAND_6 for ultra high band.
|
||||
* @static_status: TAS statically enabled or disabled
|
||||
* @static_disable_reason: TAS static disable reason, uses
|
||||
* &enum iwl_tas_statically_disabled_reason
|
||||
* @near_disconnection: is TAS currently near disconnection per radio
|
||||
* @dynamic_status_ant_a: Antenna A current TAS status.
|
||||
* uses &enum iwl_tas_dyna_status
|
||||
* @dynamic_status_ant_b: Antenna B current TAS status.
|
||||
* uses &enum iwl_tas_dyna_status
|
||||
* @max_reg_pwr_limit_ant_a: Antenna A regulatory power limits in dBm
|
||||
* @max_reg_pwr_limit_ant_b: Antenna B regulatory power limits in dBm
|
||||
* @sar_limit_ant_a: Antenna A SAR limit per radio in dBm
|
||||
* @sar_limit_ant_b: Antenna B SAR limit per radio in dBm
|
||||
* @reserved: reserved for alignment
|
||||
*/
|
||||
struct iwl_dhc_tas_status_per_radio {
|
||||
u8 band;
|
||||
u8 static_status;
|
||||
u8 static_disable_reason;
|
||||
u8 near_disconnection;
|
||||
u8 dynamic_status_ant_a;
|
||||
u8 dynamic_status_ant_b;
|
||||
__le16 max_reg_pwr_limit_ant_a;
|
||||
__le16 max_reg_pwr_limit_ant_b;
|
||||
__le16 sar_limit_ant_a;
|
||||
__le16 sar_limit_ant_b;
|
||||
u8 reserved[2];
|
||||
} __packed; /* DHC_TAS_STATUS_PER_RADIO_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_dhc_tas_status_resp - Response to DHC_TOOLS_UMAC_GET_TAS_STATUS
|
||||
* @header: DHC payload header, uses &struct iwl_dhc_payload_hdr
|
||||
* @tas_config_info: see @struct bios_value_u32
|
||||
* @mcc_block_list: block listed country codes
|
||||
* @tas_status_radio: TAS status, uses &struct iwl_dhc_tas_status_per_radio
|
||||
* @curr_mcc: current mcc
|
||||
* @valid_radio_mask: represent entry in tas_status_per_radio is valid.
|
||||
* @reserved: reserved for alignment
|
||||
*/
|
||||
struct iwl_dhc_tas_status_resp {
|
||||
struct iwl_dhc_payload_hdr header;
|
||||
struct bios_value_u32 tas_config_info;
|
||||
__le16 mcc_block_list[IWL_WTAS_BLACK_LIST_MAX];
|
||||
struct iwl_dhc_tas_status_per_radio tas_status_radio[2];
|
||||
__le16 curr_mcc;
|
||||
u8 valid_radio_mask;
|
||||
u8 reserved;
|
||||
} __packed; /* DHC_TAS_STATUS_RSP_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_dhc_cmd_resp_v1 - debug host command response
|
||||
* @status: status of the command
|
||||
* @data: the response data
|
||||
*/
|
||||
struct iwl_dhc_cmd_resp_v1 {
|
||||
__le32 status;
|
||||
__le32 data[];
|
||||
} __packed; /* DHC_RESP_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_dhc_cmd_resp - debug host command response
|
||||
* @status: status of the command
|
||||
* @descriptor: command descriptor (index_and_mask) returned
|
||||
* @data: the response data
|
||||
*/
|
||||
struct iwl_dhc_cmd_resp {
|
||||
__le32 status;
|
||||
__le32 descriptor;
|
||||
__le32 data[];
|
||||
} __packed; /* DHC_RESP_API_S_VER_2 and DHC_RESP_API_S_VER_3 */
|
||||
|
||||
/**
|
||||
* enum iwl_dhc_twt_operation_type - describes the TWT operation type
|
||||
*
|
||||
* @DHC_TWT_REQUEST: Send a Request TWT command
|
||||
* @DHC_TWT_SUGGEST: Send a Suggest TWT command
|
||||
* @DHC_TWT_DEMAND: Send a Demand TWT command
|
||||
* @DHC_TWT_GROUPING: Send a Grouping TWT command
|
||||
* @DHC_TWT_ACCEPT: Send a Accept TWT command
|
||||
* @DHC_TWT_ALTERNATE: Send a Alternate TWT command
|
||||
* @DHC_TWT_DICTATE: Send a Dictate TWT command
|
||||
* @DHC_TWT_REJECT: Send a Reject TWT command
|
||||
* @DHC_TWT_TEARDOWN: Send a TearDown TWT command
|
||||
*/
|
||||
enum iwl_dhc_twt_operation_type {
|
||||
DHC_TWT_REQUEST,
|
||||
DHC_TWT_SUGGEST,
|
||||
DHC_TWT_DEMAND,
|
||||
DHC_TWT_GROUPING,
|
||||
DHC_TWT_ACCEPT,
|
||||
DHC_TWT_ALTERNATE,
|
||||
DHC_TWT_DICTATE,
|
||||
DHC_TWT_REJECT,
|
||||
DHC_TWT_TEARDOWN,
|
||||
}; /* DHC_TWT_OPERATION_TYPE_E */
|
||||
|
||||
/**
|
||||
* struct iwl_dhc_twt_operation - trigger a TWT operation
|
||||
*
|
||||
* @mac_id: the mac Id on which to trigger TWT operation
|
||||
* @twt_operation: see &enum iwl_dhc_twt_operation_type
|
||||
* @target_wake_time: when should we be on channel
|
||||
* @interval_exp: the exponent for the interval
|
||||
* @interval_mantissa: the mantissa for the interval
|
||||
* @min_wake_duration: the minimum duration for the wake period
|
||||
* @trigger: is the TWT triggered or not
|
||||
* @flow_type: is the TWT announced or not
|
||||
* @flow_id: the TWT flow identifier from 0 to 7
|
||||
* @protection: is the TWT protected
|
||||
* @ndo_paging_indicator: is ndo_paging_indicator set
|
||||
* @responder_pm_mode: is responder_pm_mode set
|
||||
* @negotiation_type: if the responder wants to doze outside the TWT SP
|
||||
* @twt_request: 1 for TWT request, 0 otherwise
|
||||
* @implicit: is TWT implicit
|
||||
* @twt_group_assignment: the TWT group assignment
|
||||
* @twt_channel: the TWT channel
|
||||
* @reserved: reserved
|
||||
*/
|
||||
struct iwl_dhc_twt_operation {
|
||||
__le32 mac_id;
|
||||
__le32 twt_operation;
|
||||
__le64 target_wake_time;
|
||||
__le32 interval_exp;
|
||||
__le32 interval_mantissa;
|
||||
__le32 min_wake_duration;
|
||||
u8 trigger;
|
||||
u8 flow_type;
|
||||
u8 flow_id;
|
||||
u8 protection;
|
||||
u8 ndo_paging_indicator;
|
||||
u8 responder_pm_mode;
|
||||
u8 negotiation_type;
|
||||
u8 twt_request;
|
||||
u8 implicit;
|
||||
u8 twt_group_assignment;
|
||||
u8 twt_channel;
|
||||
u8 reserved;
|
||||
}; /* DHC_TWT_OPERATION_API_S */
|
||||
|
||||
#endif /* __iwl_fw_api_dhc_h__ */
|
||||
@@ -2,10 +2,15 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018-2022 Intel Corporation
|
||||
* Copyright (C) 2024 Intel Corporation
|
||||
* Copyright (C) 2024-2025 Intel Corporation
|
||||
*/
|
||||
#ifndef __iwl_fw_api_location_h__
|
||||
#define __iwl_fw_api_location_h__
|
||||
#include <linux/ieee80211.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/bits.h>
|
||||
#include "rs.h"
|
||||
|
||||
/**
|
||||
* enum iwl_location_subcmd_ids - location group command IDs
|
||||
@@ -616,6 +621,9 @@ struct iwl_tof_range_req_ap_entry_v2 {
|
||||
* continue with the session and will provide the LMR feedback.
|
||||
* @IWL_INITIATOR_AP_FLAGS_TEST_INCORRECT_SAC: send an incorrect SAC in the
|
||||
* first NDP exchange. This is used for testing.
|
||||
* @IWL_INITIATOR_AP_FLAGS_TEST_BAD_SLTF: use incorrect secure LTF tx key. This
|
||||
* is used for testing. Only supported from version 15 of the range request
|
||||
* command.
|
||||
*/
|
||||
enum iwl_initiator_ap_flags {
|
||||
IWL_INITIATOR_AP_FLAGS_ASAP = BIT(1),
|
||||
@@ -633,6 +641,7 @@ enum iwl_initiator_ap_flags {
|
||||
IWL_INITIATOR_AP_FLAGS_PMF = BIT(14),
|
||||
IWL_INITIATOR_AP_FLAGS_TERMINATE_ON_LMR_FEEDBACK = BIT(15),
|
||||
IWL_INITIATOR_AP_FLAGS_TEST_INCORRECT_SAC = BIT(16),
|
||||
IWL_INITIATOR_AP_FLAGS_TEST_BAD_SLTF = BIT(17),
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -767,7 +776,7 @@ enum iwl_location_cipher {
|
||||
* @num_of_bursts: Recommended value to be sent to the AP. 2s Exponent of
|
||||
* the number of measurement iterations (min 2^0 = 1, max 2^14)
|
||||
* @sta_id: the station id of the AP. Only relevant when associated to the AP,
|
||||
* otherwise should be set to &IWL_MVM_INVALID_STA.
|
||||
* otherwise should be set to &IWL_INVALID_STA.
|
||||
* @cipher: pairwise cipher suite for secured measurement.
|
||||
* &enum iwl_location_cipher.
|
||||
* @hltk: HLTK to be used for secured 11az measurement
|
||||
@@ -814,7 +823,7 @@ struct iwl_tof_range_req_ap_entry_v6 {
|
||||
* @num_of_bursts: Recommended value to be sent to the AP. 2s Exponent of
|
||||
* the number of measurement iterations (min 2^0 = 1, max 2^14)
|
||||
* @sta_id: the station id of the AP. Only relevant when associated to the AP,
|
||||
* otherwise should be set to &IWL_MVM_INVALID_STA.
|
||||
* otherwise should be set to &IWL_INVALID_STA.
|
||||
* @cipher: pairwise cipher suite for secured measurement.
|
||||
* &enum iwl_location_cipher.
|
||||
* @hltk: HLTK to be used for secured 11az measurement
|
||||
@@ -827,10 +836,10 @@ struct iwl_tof_range_req_ap_entry_v6 {
|
||||
* &IWL_INITIATOR_AP_FLAGS_TB is set.
|
||||
* @rx_pn: the next expected PN for protected management frames Rx. LE byte
|
||||
* order. Only valid if &IWL_INITIATOR_AP_FLAGS_SECURED is set and sta_id
|
||||
* is set to &IWL_MVM_INVALID_STA.
|
||||
* is set to &IWL_INVALID_STA.
|
||||
* @tx_pn: the next PN to use for protected management frames Tx. LE byte
|
||||
* order. Only valid if &IWL_INITIATOR_AP_FLAGS_SECURED is set and sta_id
|
||||
* is set to &IWL_MVM_INVALID_STA.
|
||||
* is set to &IWL_INVALID_STA.
|
||||
*/
|
||||
struct iwl_tof_range_req_ap_entry_v7 {
|
||||
__le32 initiator_ap_flags;
|
||||
@@ -872,7 +881,7 @@ struct iwl_tof_range_req_ap_entry_v7 {
|
||||
* @num_of_bursts: Recommended value to be sent to the AP. 2s Exponent of
|
||||
* the number of measurement iterations (min 2^0 = 1, max 2^14)
|
||||
* @sta_id: the station id of the AP. Only relevant when associated to the AP,
|
||||
* otherwise should be set to &IWL_MVM_INVALID_STA.
|
||||
* otherwise should be set to &IWL_INVALID_STA.
|
||||
* @cipher: pairwise cipher suite for secured measurement.
|
||||
* &enum iwl_location_cipher.
|
||||
* @hltk: HLTK to be used for secured 11az measurement
|
||||
@@ -885,10 +894,10 @@ struct iwl_tof_range_req_ap_entry_v7 {
|
||||
* &IWL_INITIATOR_AP_FLAGS_TB is set.
|
||||
* @rx_pn: the next expected PN for protected management frames Rx. LE byte
|
||||
* order. Only valid if &IWL_INITIATOR_AP_FLAGS_SECURED is set and sta_id
|
||||
* is set to &IWL_MVM_INVALID_STA.
|
||||
* is set to &IWL_INVALID_STA.
|
||||
* @tx_pn: the next PN to use for protected management frames Tx. LE byte
|
||||
* order. Only valid if &IWL_INITIATOR_AP_FLAGS_SECURED is set and sta_id
|
||||
* is set to &IWL_MVM_INVALID_STA.
|
||||
* is set to &IWL_INVALID_STA.
|
||||
* @r2i_ndp_params: parameters for R2I NDP ranging negotiation.
|
||||
* bits 0 - 2: max LTF repetitions
|
||||
* bits 3 - 5: max number of spatial streams
|
||||
@@ -946,7 +955,7 @@ struct iwl_tof_range_req_ap_entry_v8 {
|
||||
* @num_of_bursts: Recommended value to be sent to the AP. 2s Exponent of
|
||||
* the number of measurement iterations (min 2^0 = 1, max 2^14)
|
||||
* @sta_id: the station id of the AP. Only relevant when associated to the AP,
|
||||
* otherwise should be set to &IWL_MVM_INVALID_STA.
|
||||
* otherwise should be set to &IWL_INVALID_STA.
|
||||
* @cipher: pairwise cipher suite for secured measurement.
|
||||
* &enum iwl_location_cipher.
|
||||
* @hltk: HLTK to be used for secured 11az measurement
|
||||
@@ -961,10 +970,10 @@ struct iwl_tof_range_req_ap_entry_v8 {
|
||||
* &IWL_INITIATOR_AP_FLAGS_TB or &IWL_INITIATOR_AP_FLAGS_NON_TB is set.
|
||||
* @rx_pn: the next expected PN for protected management frames Rx. LE byte
|
||||
* order. Only valid if &IWL_INITIATOR_AP_FLAGS_SECURED is set and sta_id
|
||||
* is set to &IWL_MVM_INVALID_STA.
|
||||
* is set to &IWL_INVALID_STA.
|
||||
* @tx_pn: the next PN to use for protected management frames Tx. LE byte
|
||||
* order. Only valid if &IWL_INITIATOR_AP_FLAGS_SECURED is set and sta_id
|
||||
* is set to &IWL_MVM_INVALID_STA.
|
||||
* is set to &IWL_INVALID_STA.
|
||||
* @r2i_ndp_params: parameters for R2I NDP ranging negotiation.
|
||||
* bits 0 - 2: max LTF repetitions
|
||||
* bits 3 - 5: max number of spatial streams
|
||||
@@ -1011,7 +1020,7 @@ struct iwl_tof_range_req_ap_entry_v9 {
|
||||
} __packed; /* LOCATION_RANGE_REQ_AP_ENTRY_CMD_API_S_VER_9 */
|
||||
|
||||
/**
|
||||
* struct iwl_tof_range_req_ap_entry_v10 - AP configuration parameters
|
||||
* struct iwl_tof_range_req_ap_entry - AP configuration parameters
|
||||
* @initiator_ap_flags: see &enum iwl_initiator_ap_flags.
|
||||
* @band: 0 for 5.2 GHz, 1 for 2.4 GHz, 2 for 6GHz
|
||||
* @channel_num: AP Channel number
|
||||
@@ -1029,7 +1038,7 @@ struct iwl_tof_range_req_ap_entry_v9 {
|
||||
* @num_of_bursts: Recommended value to be sent to the AP. 2s Exponent of
|
||||
* the number of measurement iterations (min 2^0 = 1, max 2^14)
|
||||
* @sta_id: the station id of the AP. Only relevant when associated to the AP,
|
||||
* otherwise should be set to &IWL_MVM_INVALID_STA.
|
||||
* otherwise should be set to &IWL_INVALID_STA.
|
||||
* @cipher: pairwise cipher suite for secured measurement.
|
||||
* &enum iwl_location_cipher.
|
||||
* @hltk: HLTK to be used for secured 11az measurement
|
||||
@@ -1042,10 +1051,10 @@ struct iwl_tof_range_req_ap_entry_v9 {
|
||||
* &IWL_INITIATOR_AP_FLAGS_TB is set.
|
||||
* @rx_pn: the next expected PN for protected management frames Rx. LE byte
|
||||
* order. Only valid if &IWL_INITIATOR_AP_FLAGS_SECURED is set and sta_id
|
||||
* is set to &IWL_MVM_INVALID_STA.
|
||||
* is set to &IWL_INVALID_STA.
|
||||
* @tx_pn: the next PN to use for protected management frames Tx. LE byte
|
||||
* order. Only valid if &IWL_INITIATOR_AP_FLAGS_SECURED is set and sta_id
|
||||
* is set to &IWL_MVM_INVALID_STA.
|
||||
* is set to &IWL_INVALID_STA.
|
||||
* @r2i_ndp_params: parameters for R2I NDP ranging negotiation.
|
||||
* bits 0 - 2: max LTF repetitions
|
||||
* bits 3 - 5: max number of spatial streams
|
||||
@@ -1059,7 +1068,7 @@ struct iwl_tof_range_req_ap_entry_v9 {
|
||||
* @min_time_between_msr: For non trigger based NDP ranging, the minimum time
|
||||
* between measurements in units of milliseconds
|
||||
*/
|
||||
struct iwl_tof_range_req_ap_entry_v10 {
|
||||
struct iwl_tof_range_req_ap_entry {
|
||||
__le32 initiator_ap_flags;
|
||||
u8 band;
|
||||
u8 channel_num;
|
||||
@@ -1130,7 +1139,7 @@ enum iwl_tof_initiator_flags {
|
||||
IWL_TOF_INITIATOR_FLAGS_NON_ASAP_SUPPORT = BIT(20),
|
||||
}; /* LOCATION_RANGE_REQ_CMD_API_S_VER_5 */
|
||||
|
||||
#define IWL_MVM_TOF_MAX_APS 5
|
||||
#define IWL_TOF_MAX_APS 5
|
||||
#define IWL_MVM_TOF_MAX_TWO_SIDED_APS 5
|
||||
|
||||
/**
|
||||
@@ -1149,7 +1158,7 @@ enum iwl_tof_initiator_flags {
|
||||
* when the session is done (successfully / partially).
|
||||
* one of iwl_tof_response_mode.
|
||||
* @reserved0: reserved
|
||||
* @num_of_ap: Number of APs to measure (error if > IWL_MVM_TOF_MAX_APS)
|
||||
* @num_of_ap: Number of APs to measure (error if > IWL_TOF_MAX_APS)
|
||||
* @macaddr_random: '0' Use default source MAC address (i.e. p2_p),
|
||||
* '1' Use MAC Address randomization according to the below
|
||||
* @range_req_bssid: ranging request BSSID
|
||||
@@ -1179,7 +1188,7 @@ struct iwl_tof_range_req_cmd_v5 {
|
||||
u8 ftm_tx_chains;
|
||||
__le16 common_calib;
|
||||
__le16 specific_calib;
|
||||
struct iwl_tof_range_req_ap_entry_v2 ap[IWL_MVM_TOF_MAX_APS];
|
||||
struct iwl_tof_range_req_ap_entry_v2 ap[IWL_TOF_MAX_APS];
|
||||
} __packed;
|
||||
/* LOCATION_RANGE_REQ_CMD_API_S_VER_5 */
|
||||
|
||||
@@ -1188,7 +1197,7 @@ struct iwl_tof_range_req_cmd_v5 {
|
||||
* @initiator_flags: see flags @ iwl_tof_initiator_flags
|
||||
* @request_id: A Token incremented per request. The same Token will be
|
||||
* sent back in the range response
|
||||
* @num_of_ap: Number of APs to measure (error if > IWL_MVM_TOF_MAX_APS)
|
||||
* @num_of_ap: Number of APs to measure (error if > IWL_TOF_MAX_APS)
|
||||
* @range_req_bssid: ranging request BSSID
|
||||
* @macaddr_mask: Bits set to 0 shall be copied from the MAC address template.
|
||||
* Bits set to 1 shall be randomized by the UMAC
|
||||
@@ -1212,7 +1221,7 @@ struct iwl_tof_range_req_cmd_v7 {
|
||||
__le32 tsf_mac_id;
|
||||
__le16 common_calib;
|
||||
__le16 specific_calib;
|
||||
struct iwl_tof_range_req_ap_entry_v3 ap[IWL_MVM_TOF_MAX_APS];
|
||||
struct iwl_tof_range_req_ap_entry_v3 ap[IWL_TOF_MAX_APS];
|
||||
} __packed; /* LOCATION_RANGE_REQ_CMD_API_S_VER_7 */
|
||||
|
||||
/**
|
||||
@@ -1220,7 +1229,7 @@ struct iwl_tof_range_req_cmd_v7 {
|
||||
* @initiator_flags: see flags @ iwl_tof_initiator_flags
|
||||
* @request_id: A Token incremented per request. The same Token will be
|
||||
* sent back in the range response
|
||||
* @num_of_ap: Number of APs to measure (error if > IWL_MVM_TOF_MAX_APS)
|
||||
* @num_of_ap: Number of APs to measure (error if > IWL_TOF_MAX_APS)
|
||||
* @range_req_bssid: ranging request BSSID
|
||||
* @macaddr_mask: Bits set to 0 shall be copied from the MAC address template.
|
||||
* Bits set to 1 shall be randomized by the UMAC
|
||||
@@ -1244,7 +1253,7 @@ struct iwl_tof_range_req_cmd_v8 {
|
||||
__le32 tsf_mac_id;
|
||||
__le16 common_calib;
|
||||
__le16 specific_calib;
|
||||
struct iwl_tof_range_req_ap_entry_v4 ap[IWL_MVM_TOF_MAX_APS];
|
||||
struct iwl_tof_range_req_ap_entry_v4 ap[IWL_TOF_MAX_APS];
|
||||
} __packed; /* LOCATION_RANGE_REQ_CMD_API_S_VER_8 */
|
||||
|
||||
/**
|
||||
@@ -1252,7 +1261,7 @@ struct iwl_tof_range_req_cmd_v8 {
|
||||
* @initiator_flags: see flags @ iwl_tof_initiator_flags
|
||||
* @request_id: A Token incremented per request. The same Token will be
|
||||
* sent back in the range response
|
||||
* @num_of_ap: Number of APs to measure (error if > IWL_MVM_TOF_MAX_APS)
|
||||
* @num_of_ap: Number of APs to measure (error if > IWL_TOF_MAX_APS)
|
||||
* @range_req_bssid: ranging request BSSID
|
||||
* @macaddr_mask: Bits set to 0 shall be copied from the MAC address template.
|
||||
* Bits set to 1 shall be randomized by the UMAC
|
||||
@@ -1272,7 +1281,7 @@ struct iwl_tof_range_req_cmd_v9 {
|
||||
u8 macaddr_template[ETH_ALEN];
|
||||
__le32 req_timeout_ms;
|
||||
__le32 tsf_mac_id;
|
||||
struct iwl_tof_range_req_ap_entry_v6 ap[IWL_MVM_TOF_MAX_APS];
|
||||
struct iwl_tof_range_req_ap_entry_v6 ap[IWL_TOF_MAX_APS];
|
||||
} __packed; /* LOCATION_RANGE_REQ_CMD_API_S_VER_9 */
|
||||
|
||||
/**
|
||||
@@ -1280,7 +1289,7 @@ struct iwl_tof_range_req_cmd_v9 {
|
||||
* @initiator_flags: see flags @ iwl_tof_initiator_flags
|
||||
* @request_id: A Token incremented per request. The same Token will be
|
||||
* sent back in the range response
|
||||
* @num_of_ap: Number of APs to measure (error if > IWL_MVM_TOF_MAX_APS)
|
||||
* @num_of_ap: Number of APs to measure (error if > IWL_TOF_MAX_APS)
|
||||
* @range_req_bssid: ranging request BSSID
|
||||
* @macaddr_mask: Bits set to 0 shall be copied from the MAC address template.
|
||||
* Bits set to 1 shall be randomized by the UMAC
|
||||
@@ -1300,7 +1309,7 @@ struct iwl_tof_range_req_cmd_v11 {
|
||||
u8 macaddr_template[ETH_ALEN];
|
||||
__le32 req_timeout_ms;
|
||||
__le32 tsf_mac_id;
|
||||
struct iwl_tof_range_req_ap_entry_v7 ap[IWL_MVM_TOF_MAX_APS];
|
||||
struct iwl_tof_range_req_ap_entry_v7 ap[IWL_TOF_MAX_APS];
|
||||
} __packed; /* LOCATION_RANGE_REQ_CMD_API_S_VER_11 */
|
||||
|
||||
/**
|
||||
@@ -1308,7 +1317,7 @@ struct iwl_tof_range_req_cmd_v11 {
|
||||
* @initiator_flags: see flags @ iwl_tof_initiator_flags
|
||||
* @request_id: A Token incremented per request. The same Token will be
|
||||
* sent back in the range response
|
||||
* @num_of_ap: Number of APs to measure (error if > IWL_MVM_TOF_MAX_APS)
|
||||
* @num_of_ap: Number of APs to measure (error if > IWL_TOF_MAX_APS)
|
||||
* @range_req_bssid: ranging request BSSID
|
||||
* @macaddr_mask: Bits set to 0 shall be copied from the MAC address template.
|
||||
* Bits set to 1 shall be randomized by the UMAC
|
||||
@@ -1328,7 +1337,7 @@ struct iwl_tof_range_req_cmd_v12 {
|
||||
u8 macaddr_template[ETH_ALEN];
|
||||
__le32 req_timeout_ms;
|
||||
__le32 tsf_mac_id;
|
||||
struct iwl_tof_range_req_ap_entry_v8 ap[IWL_MVM_TOF_MAX_APS];
|
||||
struct iwl_tof_range_req_ap_entry_v8 ap[IWL_TOF_MAX_APS];
|
||||
} __packed; /* LOCATION_RANGE_REQ_CMD_API_S_VER_12 */
|
||||
|
||||
/**
|
||||
@@ -1336,7 +1345,7 @@ struct iwl_tof_range_req_cmd_v12 {
|
||||
* @initiator_flags: see flags @ iwl_tof_initiator_flags
|
||||
* @request_id: A Token incremented per request. The same Token will be
|
||||
* sent back in the range response
|
||||
* @num_of_ap: Number of APs to measure (error if > IWL_MVM_TOF_MAX_APS)
|
||||
* @num_of_ap: Number of APs to measure (error if > IWL_TOF_MAX_APS)
|
||||
* @range_req_bssid: ranging request BSSID
|
||||
* @macaddr_mask: Bits set to 0 shall be copied from the MAC address template.
|
||||
* Bits set to 1 shall be randomized by the UMAC
|
||||
@@ -1356,15 +1365,15 @@ struct iwl_tof_range_req_cmd_v13 {
|
||||
u8 macaddr_template[ETH_ALEN];
|
||||
__le32 req_timeout_ms;
|
||||
__le32 tsf_mac_id;
|
||||
struct iwl_tof_range_req_ap_entry_v9 ap[IWL_MVM_TOF_MAX_APS];
|
||||
struct iwl_tof_range_req_ap_entry_v9 ap[IWL_TOF_MAX_APS];
|
||||
} __packed; /* LOCATION_RANGE_REQ_CMD_API_S_VER_13 */
|
||||
|
||||
/**
|
||||
* struct iwl_tof_range_req_cmd_v14 - start measurement cmd
|
||||
* struct iwl_tof_range_req_cmd - start measurement cmd
|
||||
* @initiator_flags: see flags @ iwl_tof_initiator_flags
|
||||
* @request_id: A Token incremented per request. The same Token will be
|
||||
* sent back in the range response
|
||||
* @num_of_ap: Number of APs to measure (error if > IWL_MVM_TOF_MAX_APS)
|
||||
* @num_of_ap: Number of APs to measure (error if > IWL_TOF_MAX_APS)
|
||||
* @range_req_bssid: ranging request BSSID
|
||||
* @macaddr_mask: Bits set to 0 shall be copied from the MAC address template.
|
||||
* Bits set to 1 shall be randomized by the UMAC
|
||||
@@ -1373,9 +1382,9 @@ struct iwl_tof_range_req_cmd_v13 {
|
||||
* This is the session time for completing the measurement.
|
||||
* @tsf_mac_id: report the measurement start time for each ap in terms of the
|
||||
* TSF of this mac id. 0xff to disable TSF reporting.
|
||||
* @ap: per-AP request data, see &struct iwl_tof_range_req_ap_entry_v10.
|
||||
* @ap: per-AP request data, see &struct iwl_tof_range_req_ap_entry.
|
||||
*/
|
||||
struct iwl_tof_range_req_cmd_v14 {
|
||||
struct iwl_tof_range_req_cmd {
|
||||
__le32 initiator_flags;
|
||||
u8 request_id;
|
||||
u8 num_of_ap;
|
||||
@@ -1384,8 +1393,8 @@ struct iwl_tof_range_req_cmd_v14 {
|
||||
u8 macaddr_template[ETH_ALEN];
|
||||
__le32 req_timeout_ms;
|
||||
__le32 tsf_mac_id;
|
||||
struct iwl_tof_range_req_ap_entry_v10 ap[IWL_MVM_TOF_MAX_APS];
|
||||
} __packed; /* LOCATION_RANGE_REQ_CMD_API_S_VER_13 */
|
||||
struct iwl_tof_range_req_ap_entry ap[IWL_TOF_MAX_APS];
|
||||
} __packed; /* LOCATION_RANGE_REQ_CMD_API_S_VER_15 */
|
||||
|
||||
/*
|
||||
* enum iwl_tof_range_request_status - status of the sent request
|
||||
@@ -1605,7 +1614,7 @@ struct iwl_tof_range_rsp_ap_entry_ntfy_v5 {
|
||||
} __packed; /* LOCATION_RANGE_RSP_AP_ETRY_NTFY_API_S_VER_5 */
|
||||
|
||||
/**
|
||||
* struct iwl_tof_range_rsp_ap_entry_ntfy_v6 - AP parameters (response)
|
||||
* struct iwl_tof_range_rsp_ap_entry_ntfy_v7 - AP parameters (response)
|
||||
* @bssid: BSSID of the AP
|
||||
* @measure_status: current APs measurement status, one of
|
||||
* &enum iwl_tof_entry_status.
|
||||
@@ -1641,7 +1650,7 @@ struct iwl_tof_range_rsp_ap_entry_ntfy_v5 {
|
||||
* @tx_pn: the last PN used for this responder Tx in case PMF is configured in
|
||||
* LE byte order.
|
||||
*/
|
||||
struct iwl_tof_range_rsp_ap_entry_ntfy_v6 {
|
||||
struct iwl_tof_range_rsp_ap_entry_ntfy_v7 {
|
||||
u8 bssid[ETH_ALEN];
|
||||
u8 measure_status;
|
||||
u8 measure_bw;
|
||||
@@ -1668,6 +1677,65 @@ struct iwl_tof_range_rsp_ap_entry_ntfy_v6 {
|
||||
} __packed; /* LOCATION_RANGE_RSP_AP_ETRY_NTFY_API_S_VER_6,
|
||||
LOCATION_RANGE_RSP_AP_ETRY_NTFY_API_S_VER_7 */
|
||||
|
||||
/**
|
||||
* struct iwl_tof_range_rsp_ap_entry_ntfy - AP parameters (response)
|
||||
* @bssid: BSSID of the AP
|
||||
* @measure_status: current APs measurement status, one of
|
||||
* &enum iwl_tof_entry_status.
|
||||
* @measure_bw: Current AP Bandwidth: 0 20MHz, 1 40MHz, 2 80MHz
|
||||
* @rtt: The Round Trip Time that took for the last measurement for
|
||||
* current AP [pSec]
|
||||
* @rtt_variance: The Variance of the RTT values measured for current AP
|
||||
* @rtt_spread: The Difference between the maximum and the minimum RTT
|
||||
* values measured for current AP in the current session [pSec]
|
||||
* @rssi: RSSI as uploaded in the Channel Estimation notification
|
||||
* @rssi_spread: The Difference between the maximum and the minimum RSSI values
|
||||
* measured for current AP in the current session
|
||||
* @last_burst: 1 if no more FTM sessions are scheduled for this responder
|
||||
* @refusal_period: refusal period in case of
|
||||
* @IWL_TOF_ENTRY_RESPONDER_CANNOT_COLABORATE [sec]
|
||||
* @timestamp: The GP2 Clock [usec] where Channel Estimation notification was
|
||||
* uploaded by the LMAC
|
||||
* @start_tsf: measurement start time in TSF of the mac specified in the range
|
||||
* request
|
||||
* @reserved1: reserved, for backwards compatibility
|
||||
* @t2t3_initiator: as calculated from the algo in the initiator
|
||||
* @t1t4_responder: as calculated from the algo in the responder
|
||||
* @common_calib: Calib val that was used in for this AP measurement
|
||||
* @specific_calib: val that was used in for this AP measurement
|
||||
* @papd_calib_output: The result of the tof papd calibration that was injected
|
||||
* into the algorithm.
|
||||
* @rttConfidence: a value between 0 - 31 that represents the rtt accuracy.
|
||||
* @reserved: for alignment
|
||||
* @rx_pn: the last PN used for this responder Rx in case PMF is configured in
|
||||
* LE byte order.
|
||||
* @tx_pn: the last PN used for this responder Tx in case PMF is configured in
|
||||
* LE byte order.
|
||||
*/
|
||||
struct iwl_tof_range_rsp_ap_entry_ntfy {
|
||||
u8 bssid[ETH_ALEN];
|
||||
u8 measure_status;
|
||||
u8 measure_bw;
|
||||
__le32 rtt;
|
||||
__le32 rtt_variance;
|
||||
__le32 rtt_spread;
|
||||
s8 rssi;
|
||||
u8 rssi_spread;
|
||||
u8 last_burst;
|
||||
u8 refusal_period;
|
||||
__le32 timestamp;
|
||||
__le32 start_tsf;
|
||||
__le32 reserved1[2];
|
||||
__le32 t2t3_initiator;
|
||||
__le32 t1t4_responder;
|
||||
__le16 common_calib;
|
||||
__le16 specific_calib;
|
||||
__le32 papd_calib_output;
|
||||
u8 rttConfidence;
|
||||
u8 reserved[3];
|
||||
u8 rx_pn[IEEE80211_CCMP_PN_LEN];
|
||||
u8 tx_pn[IEEE80211_CCMP_PN_LEN];
|
||||
} __packed; /* LOCATION_RANGE_RSP_AP_ETRY_NTFY_API_S_VER_8 */
|
||||
|
||||
/**
|
||||
* enum iwl_tof_response_status - tof response status
|
||||
@@ -1691,7 +1759,7 @@ enum iwl_tof_response_status {
|
||||
* @request_status: status of current measurement session, one of
|
||||
* &enum iwl_tof_response_status.
|
||||
* @last_in_batch: reprot policy (when not all responses are uploaded at once)
|
||||
* @num_of_aps: Number of APs to measure (error if > IWL_MVM_TOF_MAX_APS)
|
||||
* @num_of_aps: Number of APs to measure (error if > IWL_TOF_MAX_APS)
|
||||
* @ap: per-AP data
|
||||
*/
|
||||
struct iwl_tof_range_rsp_ntfy_v5 {
|
||||
@@ -1699,7 +1767,7 @@ struct iwl_tof_range_rsp_ntfy_v5 {
|
||||
u8 request_status;
|
||||
u8 last_in_batch;
|
||||
u8 num_of_aps;
|
||||
struct iwl_tof_range_rsp_ap_entry_ntfy_v3 ap[IWL_MVM_TOF_MAX_APS];
|
||||
struct iwl_tof_range_rsp_ap_entry_ntfy_v3 ap[IWL_TOF_MAX_APS];
|
||||
} __packed; /* LOCATION_RANGE_RSP_NTFY_API_S_VER_5 */
|
||||
|
||||
/**
|
||||
@@ -1715,7 +1783,7 @@ struct iwl_tof_range_rsp_ntfy_v6 {
|
||||
u8 num_of_aps;
|
||||
u8 last_report;
|
||||
u8 reserved;
|
||||
struct iwl_tof_range_rsp_ap_entry_ntfy_v4 ap[IWL_MVM_TOF_MAX_APS];
|
||||
struct iwl_tof_range_rsp_ap_entry_ntfy_v4 ap[IWL_TOF_MAX_APS];
|
||||
} __packed; /* LOCATION_RANGE_RSP_NTFY_API_S_VER_6 */
|
||||
|
||||
/**
|
||||
@@ -1731,25 +1799,42 @@ struct iwl_tof_range_rsp_ntfy_v7 {
|
||||
u8 num_of_aps;
|
||||
u8 last_report;
|
||||
u8 reserved;
|
||||
struct iwl_tof_range_rsp_ap_entry_ntfy_v5 ap[IWL_MVM_TOF_MAX_APS];
|
||||
struct iwl_tof_range_rsp_ap_entry_ntfy_v5 ap[IWL_TOF_MAX_APS];
|
||||
} __packed; /* LOCATION_RANGE_RSP_NTFY_API_S_VER_7 */
|
||||
|
||||
/**
|
||||
* struct iwl_tof_range_rsp_ntfy_v8 - ranging response notification
|
||||
* struct iwl_tof_range_rsp_ntfy_v9 - ranging response notification
|
||||
* @request_id: A Token ID of the corresponding Range request
|
||||
* @num_of_aps: Number of APs results
|
||||
* @last_report: 1 if no more FTM sessions are scheduled, 0 otherwise.
|
||||
* @reserved: reserved
|
||||
* @ap: per-AP data
|
||||
*/
|
||||
struct iwl_tof_range_rsp_ntfy_v8 {
|
||||
struct iwl_tof_range_rsp_ntfy_v9 {
|
||||
u8 request_id;
|
||||
u8 num_of_aps;
|
||||
u8 last_report;
|
||||
u8 reserved;
|
||||
struct iwl_tof_range_rsp_ap_entry_ntfy_v6 ap[IWL_MVM_TOF_MAX_APS];
|
||||
struct iwl_tof_range_rsp_ap_entry_ntfy_v7 ap[IWL_TOF_MAX_APS];
|
||||
} __packed; /* LOCATION_RANGE_RSP_NTFY_API_S_VER_8,
|
||||
LOCATION_RANGE_RSP_NTFY_API_S_VER_9 */
|
||||
* LOCATION_RANGE_RSP_NTFY_API_S_VER_9
|
||||
*/
|
||||
|
||||
/**
|
||||
* struct iwl_tof_range_rsp_ntfy - ranging response notification
|
||||
* @request_id: A Token ID of the corresponding Range request
|
||||
* @num_of_aps: Number of APs results
|
||||
* @last_report: 1 if no more FTM sessions are scheduled, 0 otherwise.
|
||||
* @reserved: reserved
|
||||
* @ap: per-AP data
|
||||
*/
|
||||
struct iwl_tof_range_rsp_ntfy {
|
||||
u8 request_id;
|
||||
u8 num_of_aps;
|
||||
u8 last_report;
|
||||
u8 reserved;
|
||||
struct iwl_tof_range_rsp_ap_entry_ntfy ap[IWL_TOF_MAX_APS];
|
||||
} __packed; /* LOCATION_RANGE_RSP_NTFY_API_S_VER_10 */
|
||||
|
||||
#define IWL_MVM_TOF_MCSI_BUF_SIZE (245)
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2019, 2021-2024 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2019, 2021-2025 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
@@ -42,15 +42,15 @@ enum iwl_mac_conf_subcmd_ids {
|
||||
*/
|
||||
LINK_CONFIG_CMD = 0x9,
|
||||
/**
|
||||
* @STA_CONFIG_CMD: &struct iwl_mvm_sta_cfg_cmd
|
||||
* @STA_CONFIG_CMD: &struct iwl_sta_cfg_cmd
|
||||
*/
|
||||
STA_CONFIG_CMD = 0xA,
|
||||
/**
|
||||
* @AUX_STA_CMD: &struct iwl_mvm_aux_sta_cmd
|
||||
* @AUX_STA_CMD: &struct iwl_aux_sta_cmd
|
||||
*/
|
||||
AUX_STA_CMD = 0xB,
|
||||
/**
|
||||
* @STA_REMOVE_CMD: &struct iwl_mvm_remove_sta_cmd
|
||||
* @STA_REMOVE_CMD: &struct iwl_remove_sta_cmd
|
||||
*/
|
||||
STA_REMOVE_CMD = 0xC,
|
||||
/**
|
||||
@@ -61,12 +61,24 @@ enum iwl_mac_conf_subcmd_ids {
|
||||
* @ROC_CMD: &struct iwl_roc_req
|
||||
*/
|
||||
ROC_CMD = 0xE,
|
||||
/**
|
||||
* @TWT_OPERATION_CMD: &struct iwl_twt_operation_cmd
|
||||
*/
|
||||
TWT_OPERATION_CMD = 0x10,
|
||||
/**
|
||||
* @MISSED_BEACONS_NOTIF: &struct iwl_missed_beacons_notif
|
||||
*/
|
||||
MISSED_BEACONS_NOTIF = 0xF6,
|
||||
/**
|
||||
* @EMLSR_TRANS_FAIL_NOTIF: &struct iwl_esr_trans_fail_notif
|
||||
*/
|
||||
EMLSR_TRANS_FAIL_NOTIF = 0xF7,
|
||||
/**
|
||||
* @ROC_NOTIF: &struct iwl_roc_notif
|
||||
*/
|
||||
ROC_NOTIF = 0xF8,
|
||||
/**
|
||||
* @SESSION_PROTECTION_NOTIF: &struct iwl_mvm_session_prot_notif
|
||||
* @SESSION_PROTECTION_NOTIF: &struct iwl_session_prot_notif
|
||||
*/
|
||||
SESSION_PROTECTION_NOTIF = 0xFB,
|
||||
|
||||
@@ -298,9 +310,42 @@ enum iwl_mac_config_filter_flags {
|
||||
MAC_CFG_FILTER_ACCEPT_PROBE_REQ = BIT(5),
|
||||
}; /* MAC_FILTER_FLAGS_MASK_E_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_mac_wifi_gen_support_v2 - parameters of iwl_mac_config_cmd
|
||||
* with support up to eht as in version 2 of the command
|
||||
*
|
||||
* @he_support: does this MAC support HE
|
||||
* @he_ap_support: HE AP enabled, "pseudo HE", no trigger frame handling
|
||||
* @eht_support: does this MAC support EHT. Requires he_support
|
||||
*/
|
||||
struct iwl_mac_wifi_gen_support_v2 {
|
||||
__le16 he_support;
|
||||
__le16 he_ap_support;
|
||||
__le32 eht_support;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_mac_wifi_gen_support - parameters of iwl_mac_config_cmd
|
||||
* with support up to uhr as in version 3 of the command
|
||||
* ( MAC_CONTEXT_CONFIG_CMD = 0x8 )
|
||||
*
|
||||
* @he_support: does this MAC support HE
|
||||
* @he_ap_support: HE AP enabled, "pseudo HE", no trigger frame handling
|
||||
* @eht_support: does this MAC support EHT. Requires he_support
|
||||
* @uhr_support: does this MAC support UHR. Requires eht_support
|
||||
* @reserved: reserved for alignment and to match version 2's size
|
||||
*/
|
||||
struct iwl_mac_wifi_gen_support {
|
||||
u8 he_support;
|
||||
u8 he_ap_support;
|
||||
u8 eht_support;
|
||||
u8 uhr_support;
|
||||
__le32 reserved;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_mac_config_cmd - command structure to configure MAC contexts in
|
||||
* MLD API
|
||||
* MLD API for versions 2 and 3
|
||||
* ( MAC_CONTEXT_CONFIG_CMD = 0x8 )
|
||||
*
|
||||
* @id_and_color: ID and color of the MAC
|
||||
@@ -309,9 +354,8 @@ enum iwl_mac_config_filter_flags {
|
||||
* @local_mld_addr: mld address
|
||||
* @reserved_for_local_mld_addr: reserved
|
||||
* @filter_flags: combination of &enum iwl_mac_config_filter_flags
|
||||
* @he_support: does this MAC support HE
|
||||
* @he_ap_support: HE AP enabled, "pseudo HE", no trigger frame handling
|
||||
* @eht_support: does this MAC support EHT. Requires he_support
|
||||
* @wifi_gen_v2: he/eht parameters as in cmd version 2
|
||||
* @wifi_gen: he/eht/uhr parameters as in cmd version 3
|
||||
* @nic_not_ack_enabled: mark that the NIC doesn't support receiving
|
||||
* ACK-enabled AGG, (i.e. both BACK and non-BACK frames in single AGG).
|
||||
* If the NIC is not ACK_ENABLED it may use the EOF-bit in first non-0
|
||||
@@ -320,7 +364,6 @@ enum iwl_mac_config_filter_flags {
|
||||
* @p2p_dev: mac data for p2p device
|
||||
*/
|
||||
struct iwl_mac_config_cmd {
|
||||
/* COMMON_INDEX_HDR_API_S_VER_1 */
|
||||
__le32 id_and_color;
|
||||
__le32 action;
|
||||
/* MAC_CONTEXT_TYPE_API_E */
|
||||
@@ -328,16 +371,17 @@ struct iwl_mac_config_cmd {
|
||||
u8 local_mld_addr[6];
|
||||
__le16 reserved_for_local_mld_addr;
|
||||
__le32 filter_flags;
|
||||
__le16 he_support;
|
||||
__le16 he_ap_support;
|
||||
__le32 eht_support;
|
||||
union {
|
||||
struct iwl_mac_wifi_gen_support_v2 wifi_gen_v2;
|
||||
struct iwl_mac_wifi_gen_support wifi_gen;
|
||||
};
|
||||
__le32 nic_not_ack_enabled;
|
||||
/* MAC_CONTEXT_CONFIG_SPECIFIC_DATA_API_U_VER_2 */
|
||||
union {
|
||||
struct iwl_mac_client_data client;
|
||||
struct iwl_mac_p2p_dev_data p2p_dev;
|
||||
};
|
||||
} __packed; /* MAC_CONTEXT_CONFIG_CMD_API_S_VER_2 */
|
||||
} __packed; /* MAC_CONTEXT_CONFIG_CMD_API_S_VER_2_VER_3 */
|
||||
|
||||
/**
|
||||
* enum iwl_link_ctx_modify_flags - indicate to the fw what fields are being
|
||||
@@ -374,6 +418,8 @@ struct iwl_mac_config_cmd {
|
||||
* @LINK_CONTEXT_MODIFY_EHT_PARAMS: covers iwl_link_ctx_cfg_cmd::puncture_mask.
|
||||
* This flag can be set only if the MAC that this link relates to has
|
||||
* eht_support set to true. No longer used since _VER_3 of this command.
|
||||
* @LINK_CONTEXT_MODIFY_BANDWIDTH: Covers iwl_link_ctx_cfg_cmd::modify_bandwidth.
|
||||
* Request RX OMI to the AP to modify bandwidth of this link.
|
||||
* @LINK_CONTEXT_MODIFY_ALL: set all above flags
|
||||
*/
|
||||
enum iwl_link_ctx_modify_flags {
|
||||
@@ -385,6 +431,7 @@ enum iwl_link_ctx_modify_flags {
|
||||
LINK_CONTEXT_MODIFY_HE_PARAMS = BIT(5),
|
||||
LINK_CONTEXT_MODIFY_BSS_COLOR_DISABLE = BIT(6),
|
||||
LINK_CONTEXT_MODIFY_EHT_PARAMS = BIT(7),
|
||||
LINK_CONTEXT_MODIFY_BANDWIDTH = BIT(8),
|
||||
LINK_CONTEXT_MODIFY_ALL = 0xff,
|
||||
}; /* LINK_CONTEXT_MODIFY_MASK_E_VER_1 */
|
||||
|
||||
@@ -425,6 +472,40 @@ enum iwl_link_ctx_flags {
|
||||
LINK_FLG_NDP_FEEDBACK_ENABLED = BIT(3),
|
||||
}; /* LINK_CONTEXT_FLAG_E_VER_1 */
|
||||
|
||||
/**
|
||||
* enum iwl_link_modify_bandwidth - link modify (RX OMI) bandwidth
|
||||
* @IWL_LINK_MODIFY_BW_20: request 20 MHz
|
||||
* @IWL_LINK_MODIFY_BW_40: request 40 MHz
|
||||
* @IWL_LINK_MODIFY_BW_80: request 80 MHz
|
||||
* @IWL_LINK_MODIFY_BW_160: request 160 MHz
|
||||
* @IWL_LINK_MODIFY_BW_320: request 320 MHz
|
||||
*/
|
||||
enum iwl_link_modify_bandwidth {
|
||||
IWL_LINK_MODIFY_BW_20,
|
||||
IWL_LINK_MODIFY_BW_40,
|
||||
IWL_LINK_MODIFY_BW_80,
|
||||
IWL_LINK_MODIFY_BW_160,
|
||||
IWL_LINK_MODIFY_BW_320,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_npca_params - NPCA parameters (non-primary channel access)
|
||||
*
|
||||
* @switch_delay: after switch, delay TX according to destination AP
|
||||
* @switch_back_delay: switch back to control channel before OBSS frame end
|
||||
* @min_dur_threshold: minimum PPDU time to switch to the non-primary
|
||||
* NPCA channel
|
||||
* @flags: NPCA flags - bit 0: puncturing allowed, bit 1: new TX allowed
|
||||
* @reserved: reserved for alignment purposes
|
||||
*/
|
||||
struct iwl_npca_params {
|
||||
u8 switch_delay;
|
||||
u8 switch_back_delay;
|
||||
__le16 min_dur_threshold;
|
||||
__le16 flags;
|
||||
__le16 reserved;
|
||||
} __packed; /* NPCA_PARAM_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_link_config_cmd - command structure to configure the LINK context
|
||||
* in MLD API
|
||||
@@ -446,6 +527,11 @@ enum iwl_link_ctx_flags {
|
||||
* @listen_lmac: indicates whether the link should be allocated on the Listen
|
||||
* Lmac or on the Main Lmac. Cannot be changed on an active Link.
|
||||
* Relevant only for eSR.
|
||||
* @block_tx: tell the firmware that this link can't Tx. This should be used
|
||||
* only when a link is de-activated because of CSA with mode = 1.
|
||||
* Available since version 5.
|
||||
* @modify_bandwidth: bandwidth request value for RX OMI (see also
|
||||
* %LINK_CONTEXT_MODIFY_BANDWIDTH), from &enum iwl_link_modify_bandwidth.
|
||||
* @reserved1: in version 2, listen_lmac became reserved
|
||||
* @cck_rates: basic rates available for CCK
|
||||
* @ofdm_rates: basic rates available for OFDM
|
||||
@@ -472,9 +558,13 @@ enum iwl_link_ctx_flags {
|
||||
* @bssid_index: index of the associated VAP
|
||||
* @bss_color: 11ax AP ID that is used in the HE SIG-A to mark inter BSS frame
|
||||
* @spec_link_id: link_id as the AP knows it
|
||||
* @reserved2: alignment
|
||||
* @ul_mu_data_disable: OM Control UL MU Data Disable RX Support (bit 44) in
|
||||
* HE MAC Capabilities information field as defined in figure 9-897 in
|
||||
* IEEE802.11REVme-D5.0
|
||||
* @ibss_bssid_addr: bssid for ibss
|
||||
* @reserved_for_ibss_bssid_addr: reserved
|
||||
* @npca_params: NPCA parameters
|
||||
* @prio_edca_params: priority EDCA parameters for enhanced QoS
|
||||
* @reserved3: reserved for future use
|
||||
*/
|
||||
struct iwl_link_config_cmd {
|
||||
@@ -487,8 +577,12 @@ struct iwl_link_config_cmd {
|
||||
__le32 modify_mask;
|
||||
__le32 active;
|
||||
union {
|
||||
__le32 listen_lmac;
|
||||
__le32 reserved1;
|
||||
__le32 listen_lmac; /* only _VER_1 */
|
||||
struct {
|
||||
u8 block_tx; /* since _VER_5 */
|
||||
u8 modify_bandwidth; /* since _VER_6 */
|
||||
u8 reserved1[2];
|
||||
};
|
||||
};
|
||||
__le32 cck_rates;
|
||||
__le32 ofdm_rates;
|
||||
@@ -508,24 +602,26 @@ struct iwl_link_config_cmd {
|
||||
__le16 puncture_mask; /* removed in _VER_3 */
|
||||
__le16 frame_time_rts_th;
|
||||
__le32 flags;
|
||||
__le32 flags_mask;
|
||||
__le32 flags_mask; /* removed in _VER_6 */
|
||||
/* The below fields are for multi-bssid */
|
||||
u8 ref_bssid_addr[6];
|
||||
__le16 reserved_for_ref_bssid_addr;
|
||||
u8 bssid_index;
|
||||
u8 bss_color;
|
||||
u8 spec_link_id;
|
||||
u8 reserved2;
|
||||
u8 ul_mu_data_disable;
|
||||
u8 ibss_bssid_addr[6];
|
||||
__le16 reserved_for_ibss_bssid_addr;
|
||||
__le32 reserved3[8];
|
||||
} __packed; /* LINK_CONTEXT_CONFIG_CMD_API_S_VER_1, _VER_2, _VER_3 */
|
||||
struct iwl_npca_params npca_params; /* since _VER_7 */
|
||||
struct iwl_ac_qos prio_edca_params; /* since _VER_7 */
|
||||
__le32 reserved3[4];
|
||||
} __packed; /* LINK_CONTEXT_CONFIG_CMD_API_S_VER_1, _VER_2, _VER_3, _VER_4, _VER_5, _VER_6, _VER_7 */
|
||||
|
||||
/* Currently FW supports link ids in the range 0-3 and can have
|
||||
* at most two active links for each vif.
|
||||
*/
|
||||
#define IWL_MVM_FW_MAX_ACTIVE_LINKS_NUM 2
|
||||
#define IWL_MVM_FW_MAX_LINK_ID 3
|
||||
#define IWL_FW_MAX_ACTIVE_LINKS_NUM 2
|
||||
#define IWL_FW_MAX_LINK_ID 3
|
||||
|
||||
/**
|
||||
* enum iwl_fw_sta_type - FW station types
|
||||
@@ -547,7 +643,7 @@ enum iwl_fw_sta_type {
|
||||
}; /* STATION_TYPE_E_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_mvm_sta_cfg_cmd - cmd structure to add a peer sta to the uCode's
|
||||
* struct iwl_sta_cfg_cmd_v1 - cmd structure to add a peer sta to the uCode's
|
||||
* station table
|
||||
* ( STA_CONFIG_CMD = 0xA )
|
||||
*
|
||||
@@ -579,7 +675,7 @@ enum iwl_fw_sta_type {
|
||||
* capa
|
||||
* @htc_flags: which features are supported in HTC
|
||||
*/
|
||||
struct iwl_mvm_sta_cfg_cmd {
|
||||
struct iwl_sta_cfg_cmd_v1 {
|
||||
__le32 sta_id;
|
||||
__le32 link_id;
|
||||
u8 peer_mld_address[ETH_ALEN];
|
||||
@@ -603,7 +699,78 @@ struct iwl_mvm_sta_cfg_cmd {
|
||||
} __packed; /* STA_CMD_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_mvm_aux_sta_cmd - command for AUX STA configuration
|
||||
* struct iwl_sta_cfg_cmd - cmd structure to add a peer sta to the uCode's
|
||||
* station table
|
||||
* ( STA_CONFIG_CMD = 0xA )
|
||||
*
|
||||
* @sta_id: index of station in uCode's station table
|
||||
* @link_id: the id of the link that is used to communicate with this sta
|
||||
* @peer_mld_address: the peers mld address
|
||||
* @reserved_for_peer_mld_address: reserved
|
||||
* @peer_link_address: the address of the link that is used to communicate
|
||||
* with this sta
|
||||
* @reserved_for_peer_link_address: reserved
|
||||
* @station_type: type of this station. See &enum iwl_fw_sta_type
|
||||
* @assoc_id: for GO only
|
||||
* @beamform_flags: beam forming controls
|
||||
* @mfp: indicates whether the STA uses management frame protection or not.
|
||||
* @mimo: indicates whether the sta uses mimo or not
|
||||
* @mimo_protection: indicates whether the sta uses mimo protection or not
|
||||
* @ack_enabled: indicates that the AP supports receiving ACK-
|
||||
* enabled AGG, i.e. both BACK and non-BACK frames in a single AGG
|
||||
* @trig_rnd_alloc: indicates that trigger based random allocation
|
||||
* is enabled according to UORA element existence
|
||||
* @tx_ampdu_spacing: minimum A-MPDU spacing:
|
||||
* 4 - 2us density, 5 - 4us density, 6 - 8us density, 7 - 16us density
|
||||
* @tx_ampdu_max_size: maximum A-MPDU length: 0 - 8K, 1 - 16K, 2 - 32K,
|
||||
* 3 - 64K, 4 - 128K, 5 - 256K, 6 - 512K, 7 - 1024K.
|
||||
* @sp_length: the size of the SP in actual number of frames
|
||||
* @uapsd_acs: 4 LS bits are trigger enabled ACs, 4 MS bits are the deliver
|
||||
* enabled ACs.
|
||||
* @pkt_ext: optional, exists according to PPE-present bit in the HE/EHT-PHY
|
||||
* capa
|
||||
* @htc_flags: which features are supported in HTC
|
||||
* @use_ldpc_x2_cw: Indicates whether to use LDPC with double CW
|
||||
* @use_icf: Indicates whether to use ICF instead of RTS
|
||||
* @dps_pad_time: DPS (Dynamic Power Save) padding delay resolution to ensure
|
||||
* proper timing alignment
|
||||
* @dps_trans_delay: DPS minimal time that takes the peer to return to low power
|
||||
* @mic_prep_pad_delay: MIC prep time padding
|
||||
* @mic_compute_pad_delay: MIC compute time padding
|
||||
* @reserved: Reserved for alignment
|
||||
*/
|
||||
struct iwl_sta_cfg_cmd {
|
||||
__le32 sta_id;
|
||||
__le32 link_id;
|
||||
u8 peer_mld_address[ETH_ALEN];
|
||||
__le16 reserved_for_peer_mld_address;
|
||||
u8 peer_link_address[ETH_ALEN];
|
||||
__le16 reserved_for_peer_link_address;
|
||||
__le32 station_type;
|
||||
__le32 assoc_id;
|
||||
__le32 beamform_flags;
|
||||
__le32 mfp;
|
||||
__le32 mimo;
|
||||
__le32 mimo_protection;
|
||||
__le32 ack_enabled;
|
||||
__le32 trig_rnd_alloc;
|
||||
__le32 tx_ampdu_spacing;
|
||||
__le32 tx_ampdu_max_size;
|
||||
__le32 sp_length;
|
||||
__le32 uapsd_acs;
|
||||
struct iwl_he_pkt_ext_v2 pkt_ext;
|
||||
__le32 htc_flags;
|
||||
u8 use_ldpc_x2_cw;
|
||||
u8 use_icf;
|
||||
u8 dps_pad_time;
|
||||
u8 dps_trans_delay;
|
||||
u8 mic_prep_pad_delay;
|
||||
u8 mic_compute_pad_delay;
|
||||
u8 reserved[2];
|
||||
} __packed; /* STA_CMD_API_S_VER_2 */
|
||||
|
||||
/**
|
||||
* struct iwl_aux_sta_cmd - command for AUX STA configuration
|
||||
* ( AUX_STA_CMD = 0xB )
|
||||
*
|
||||
* @sta_id: index of aux sta to configure
|
||||
@@ -611,7 +778,7 @@ struct iwl_mvm_sta_cfg_cmd {
|
||||
* @mac_addr: mac addr of the auxilary sta
|
||||
* @reserved_for_mac_addr: reserved
|
||||
*/
|
||||
struct iwl_mvm_aux_sta_cmd {
|
||||
struct iwl_aux_sta_cmd {
|
||||
__le32 sta_id;
|
||||
__le32 lmac_id;
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
@@ -620,13 +787,13 @@ struct iwl_mvm_aux_sta_cmd {
|
||||
} __packed; /* AUX_STA_CMD_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_mvm_remove_sta_cmd - a cmd structure to remove a sta added by
|
||||
* struct iwl_remove_sta_cmd - a cmd structure to remove a sta added by
|
||||
* STA_CONFIG_CMD or AUX_STA_CONFIG_CMD
|
||||
* ( STA_REMOVE_CMD = 0xC )
|
||||
*
|
||||
* @sta_id: index of station to remove
|
||||
*/
|
||||
struct iwl_mvm_remove_sta_cmd {
|
||||
struct iwl_remove_sta_cmd {
|
||||
__le32 sta_id;
|
||||
} __packed; /* REMOVE_STA_API_S_VER_1 */
|
||||
|
||||
@@ -644,9 +811,9 @@ struct iwl_mvm_sta_disable_tx_cmd {
|
||||
|
||||
/**
|
||||
* enum iwl_mvm_fw_esr_recommendation - FW recommendation code
|
||||
* @ESR_RECOMMEND_LEAVE: recommendation to leave esr
|
||||
* @ESR_FORCE_LEAVE: force exiting esr
|
||||
* @ESR_RECOMMEND_ENTER: recommendation to enter esr
|
||||
* @ESR_RECOMMEND_LEAVE: recommendation to leave EMLSR
|
||||
* @ESR_FORCE_LEAVE: force exiting EMLSR
|
||||
* @ESR_RECOMMEND_ENTER: recommendation to enter EMLSR
|
||||
*/
|
||||
enum iwl_mvm_fw_esr_recommendation {
|
||||
ESR_RECOMMEND_LEAVE,
|
||||
@@ -655,12 +822,169 @@ enum iwl_mvm_fw_esr_recommendation {
|
||||
}; /* ESR_MODE_RECOMMENDATION_CODE_API_E_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_mvm_esr_mode_notif - FWs recommendation/force for esr mode
|
||||
* struct iwl_esr_mode_notif_v1 - FW recommendation/force for EMLSR mode
|
||||
*
|
||||
* @action: the action to apply on esr state. See &iwl_mvm_fw_esr_recommendation
|
||||
* @action: the action to apply on EMLSR state.
|
||||
* See &iwl_mvm_fw_esr_recommendation
|
||||
*/
|
||||
struct iwl_mvm_esr_mode_notif {
|
||||
struct iwl_esr_mode_notif_v1 {
|
||||
__le32 action;
|
||||
} __packed; /* ESR_MODE_RECOMMENDATION_NTFY_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* enum iwl_esr_leave_reason - reasons for leaving EMLSR mode
|
||||
*
|
||||
* @ESR_LEAVE_REASON_OMI_MU_UL_DISALLOWED: OMI MU UL disallowed
|
||||
* @ESR_LEAVE_REASON_NO_TRIG_FOR_ESR_STA: No trigger for EMLSR station
|
||||
* @ESR_LEAVE_REASON_NO_ESR_STA_IN_MU_DL: No EMLSR station in MU DL
|
||||
* @ESR_LEAVE_REASON_BAD_ACTIV_FRAME_TH: Bad activation frame threshold
|
||||
* @ESR_LEAVE_REASON_RTS_IN_DUAL_LISTEN: RTS in dual listen
|
||||
*/
|
||||
enum iwl_esr_leave_reason {
|
||||
ESR_LEAVE_REASON_OMI_MU_UL_DISALLOWED = BIT(0),
|
||||
ESR_LEAVE_REASON_NO_TRIG_FOR_ESR_STA = BIT(1),
|
||||
ESR_LEAVE_REASON_NO_ESR_STA_IN_MU_DL = BIT(2),
|
||||
ESR_LEAVE_REASON_BAD_ACTIV_FRAME_TH = BIT(3),
|
||||
ESR_LEAVE_REASON_RTS_IN_DUAL_LISTEN = BIT(4),
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_esr_mode_notif - FW recommendation/force for EMLSR mode
|
||||
*
|
||||
* @action: the action to apply on EMLSR state.
|
||||
* See &iwl_mvm_fw_esr_recommendation
|
||||
* @leave_reason_mask: mask for various reasons to leave EMLSR mode.
|
||||
* See &iwl_esr_leave_reason
|
||||
*/
|
||||
struct iwl_esr_mode_notif {
|
||||
__le32 action;
|
||||
__le32 leave_reason_mask;
|
||||
} __packed; /* ESR_MODE_RECOMMENDATION_NTFY_API_S_VER_2 */
|
||||
|
||||
/**
|
||||
* struct iwl_missed_beacons_notif - sent when by the firmware upon beacon loss
|
||||
* ( MISSED_BEACONS_NOTIF = 0xF6 )
|
||||
* @link_id: fw link ID
|
||||
* @consec_missed_beacons_since_last_rx: number of consecutive missed
|
||||
* beacons since last RX.
|
||||
* @consec_missed_beacons: number of consecutive missed beacons
|
||||
* @other_link_id: used in EMLSR only. The fw link ID for
|
||||
* &consec_missed_beacons_other_link. IWL_MVM_FW_LINK_ID_INVALID (0xff) if
|
||||
* invalid.
|
||||
* @consec_missed_beacons_other_link: number of consecutive missed beacons on
|
||||
* &other_link_id.
|
||||
*/
|
||||
struct iwl_missed_beacons_notif {
|
||||
__le32 link_id;
|
||||
__le32 consec_missed_beacons_since_last_rx;
|
||||
__le32 consec_missed_beacons;
|
||||
__le32 other_link_id;
|
||||
__le32 consec_missed_beacons_other_link;
|
||||
} __packed; /* MISSED_BEACON_NTFY_API_S_VER_5 */
|
||||
|
||||
/*
|
||||
* enum iwl_esr_trans_fail_code: to be used to parse the notif below
|
||||
*
|
||||
* @ESR_TRANS_FAILED_TX_STATUS_ERROR: failed to TX EML OMN frame
|
||||
* @ESR_TRANSITION_FAILED_TX_TIMEOUT: timeout on the EML OMN frame
|
||||
* @ESR_TRANSITION_FAILED_BEACONS_NOT_HEARD: can't get a beacon on the new link
|
||||
*/
|
||||
enum iwl_esr_trans_fail_code {
|
||||
ESR_TRANS_FAILED_TX_STATUS_ERROR,
|
||||
ESR_TRANSITION_FAILED_TX_TIMEOUT,
|
||||
ESR_TRANSITION_FAILED_BEACONS_NOT_HEARD,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_esr_trans_fail_notif - FW reports a failure in EMLSR transition
|
||||
*
|
||||
* @link_id: the link_id that still works after the failure
|
||||
* @activation: true if the link was activated, false otherwise
|
||||
* @err_code: see &enum iwl_esr_trans_fail_code
|
||||
*/
|
||||
struct iwl_esr_trans_fail_notif {
|
||||
__le32 link_id;
|
||||
__le32 activation;
|
||||
__le32 err_code;
|
||||
} __packed; /* ESR_TRANSITION_FAILED_NTFY_API_S_VER_1 */
|
||||
|
||||
/*
|
||||
* enum iwl_twt_operation_type: TWT operation in a TWT action frame
|
||||
*
|
||||
* @TWT_OPERATION_REQUEST: TWT Request
|
||||
* @TWT_OPERATION_SUGGEST: TWT Suggest
|
||||
* @TWT_OPERATION_DEMAND: TWT Demand
|
||||
* @TWT_OPERATION_GROUPING: TWT Grouping
|
||||
* @TWT_OPERATION_ACCEPT: TWT Accept
|
||||
* @TWT_OPERATION_ALTERNATE: TWT Alternate
|
||||
* @TWT_OPERATION_DICTATE: TWT Dictate
|
||||
* @TWT_OPERATION_REJECT: TWT Reject
|
||||
* @TWT_OPERATION_TEARDOWN: TWT Teardown
|
||||
* @TWT_OPERATION_UNAVAILABILITY: TWT Unavailability
|
||||
*/
|
||||
enum iwl_twt_operation_type {
|
||||
TWT_OPERATION_REQUEST,
|
||||
TWT_OPERATION_SUGGEST,
|
||||
TWT_OPERATION_DEMAND,
|
||||
TWT_OPERATION_GROUPING,
|
||||
TWT_OPERATION_ACCEPT,
|
||||
TWT_OPERATION_ALTERNATE,
|
||||
TWT_OPERATION_DICTATE,
|
||||
TWT_OPERATION_REJECT,
|
||||
TWT_OPERATION_TEARDOWN,
|
||||
TWT_OPERATION_UNAVAILABILITY,
|
||||
TWT_OPERATION_MAX,
|
||||
}; /* TWT_OPERATION_TYPE_E_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_twt_operation_cmd - initiate a TWT session from driver
|
||||
*
|
||||
* @link_id: FW link id to initiate the TWT
|
||||
* @twt_operation: &enum iwl_twt_operation_type
|
||||
* @target_wake_time: TSF time to start the TWT
|
||||
* @interval_exponent: the exponent for the interval
|
||||
* @interval_mantissa: the mantissa for the interval
|
||||
* @minimum_wake_duration: the minimum duration for the wake period
|
||||
* @trigger: is the TWT triggered or not
|
||||
* @flow_type: is the TWT announced (0) or not (1)
|
||||
* @flow_id: the TWT flow identifier 0 - 7
|
||||
* @twt_protection: is the TWT protected
|
||||
* @ndp_paging_indicator: is ndp paging indicator set
|
||||
* @responder_pm_mode: is responder pm mode set
|
||||
* @negotiation_type: if the responder wants to doze outside the TWT SP
|
||||
* @twt_request: 1 for TWT request (STA), 0 for TWT response (AP)
|
||||
* @implicit: is TWT implicit
|
||||
* @twt_group_assignment: the TWT group assignment
|
||||
* @twt_channel: the TWT channel
|
||||
* @restricted_info_present: is this a restricted TWT
|
||||
* @dl_bitmap_valid: is DL (download) bitmap valid (restricted TWT)
|
||||
* @ul_bitmap_valid: is UL (upload) bitmap valid (restricted TWT)
|
||||
* @dl_tid_bitmap: DL TID bitmap (restricted TWT)
|
||||
* @ul_tid_bitmap: UL TID bitmap (restricted TWT)
|
||||
*/
|
||||
struct iwl_twt_operation_cmd {
|
||||
__le32 link_id;
|
||||
__le32 twt_operation;
|
||||
__le64 target_wake_time;
|
||||
__le32 interval_exponent;
|
||||
__le32 interval_mantissa;
|
||||
__le32 minimum_wake_duration;
|
||||
u8 trigger;
|
||||
u8 flow_type;
|
||||
u8 flow_id;
|
||||
u8 twt_protection;
|
||||
u8 ndp_paging_indicator;
|
||||
u8 responder_pm_mode;
|
||||
u8 negotiation_type;
|
||||
u8 twt_request;
|
||||
u8 implicit;
|
||||
u8 twt_group_assignment;
|
||||
u8 twt_channel;
|
||||
u8 restricted_info_present;
|
||||
u8 dl_bitmap_valid;
|
||||
u8 ul_bitmap_valid;
|
||||
u8 dl_tid_bitmap;
|
||||
u8 ul_tid_bitmap;
|
||||
} __packed; /* TWT_OPERATION_API_S_VER_1 */
|
||||
|
||||
#endif /* __iwl_fw_api_mac_cfg_h__ */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2022, 2024 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2022, 2024-2025 Intel Corporation
|
||||
* Copyright (C) 2017 Intel Deutschland GmbH
|
||||
*/
|
||||
#ifndef __iwl_fw_api_mac_h__
|
||||
@@ -16,8 +16,8 @@
|
||||
#define NUM_MAC_INDEX (NUM_MAC_INDEX_DRIVER + 1)
|
||||
#define NUM_MAC_INDEX_CDB (NUM_MAC_INDEX_DRIVER + 2)
|
||||
|
||||
#define IWL_MVM_STATION_COUNT_MAX 16
|
||||
#define IWL_MVM_INVALID_STA 0xFF
|
||||
#define IWL_STATION_COUNT_MAX 16
|
||||
#define IWL_INVALID_STA 0xFF
|
||||
|
||||
enum iwl_ac {
|
||||
AC_BK,
|
||||
@@ -287,9 +287,9 @@ struct iwl_ac_qos {
|
||||
__le16 cw_min;
|
||||
__le16 cw_max;
|
||||
u8 aifsn;
|
||||
u8 fifos_mask;
|
||||
u8 fifos_mask; /* not in use since _VER_3 */
|
||||
__le16 edca_txop;
|
||||
} __packed; /* AC_QOS_API_S_VER_2 */
|
||||
} __packed; /* AC_QOS_API_S_VER_2, _VER_3 */
|
||||
|
||||
/**
|
||||
* struct iwl_mac_ctx_cmd - command structure to configure MAC contexts
|
||||
@@ -378,7 +378,7 @@ struct iwl_missed_beacons_notif_ver_3 {
|
||||
} __packed; /* MISSED_BEACON_NTFY_API_S_VER_3 */
|
||||
|
||||
/**
|
||||
* struct iwl_missed_beacons_notif - information on missed beacons
|
||||
* struct iwl_missed_beacons_notif_v4 - information on missed beacons
|
||||
* ( MISSED_BEACONS_NOTIFICATION = 0xa2 )
|
||||
* @link_id: fw link ID
|
||||
* @consec_missed_beacons_since_last_rx: number of consecutive missed
|
||||
@@ -387,7 +387,7 @@ struct iwl_missed_beacons_notif_ver_3 {
|
||||
* @num_expected_beacons: number of expected beacons
|
||||
* @num_recvd_beacons: number of received beacons
|
||||
*/
|
||||
struct iwl_missed_beacons_notif {
|
||||
struct iwl_missed_beacons_notif_v4 {
|
||||
__le32 link_id;
|
||||
__le32 consec_missed_beacons_since_last_rx;
|
||||
__le32 consec_missed_beacons;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2024 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2025 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
@@ -463,22 +463,31 @@ struct iwl_tas_config_cmd_v3 {
|
||||
__le16 enable_tas_iec;
|
||||
} __packed; /* TAS_CONFIG_CMD_API_S_VER_3 */
|
||||
|
||||
/**
|
||||
* enum iwl_tas_uhb_allowed_flags - per country TAS UHB allowed flags.
|
||||
* @TAS_UHB_ALLOWED_CANADA: TAS UHB is allowed in Canada. This flag is valid
|
||||
* only when fw has %IWL_UCODE_TLV_CAPA_UHB_CANADA_TAS_SUPPORT capability.
|
||||
*/
|
||||
enum iwl_tas_uhb_allowed_flags {
|
||||
TAS_UHB_ALLOWED_CANADA = BIT(0),
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_tas_config_cmd_v4 - configures the TAS
|
||||
* @override_tas_iec: indicates whether to override default value of IEC regulatory
|
||||
* @enable_tas_iec: in case override_tas_iec is set -
|
||||
* indicates whether IEC regulatory is enabled or disabled
|
||||
* @usa_tas_uhb_allowed: if set, allow TAS UHB in the USA
|
||||
* @reserved: reserved
|
||||
*/
|
||||
* @uhb_allowed_flags: see &enum iwl_tas_uhb_allowed_flags.
|
||||
*/
|
||||
struct iwl_tas_config_cmd_v4 {
|
||||
u8 override_tas_iec;
|
||||
u8 enable_tas_iec;
|
||||
u8 usa_tas_uhb_allowed;
|
||||
u8 reserved;
|
||||
u8 uhb_allowed_flags;
|
||||
} __packed; /* TAS_CONFIG_CMD_API_S_VER_4 */
|
||||
|
||||
struct iwl_tas_config_cmd {
|
||||
struct iwl_tas_config_cmd_v2_v4 {
|
||||
struct iwl_tas_config_cmd_common common;
|
||||
union {
|
||||
struct iwl_tas_config_cmd_v3 v3;
|
||||
@@ -486,6 +495,46 @@ struct iwl_tas_config_cmd {
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* enum bios_source - source of bios data
|
||||
* @BIOS_SOURCE_NONE: BIOS source is not defined
|
||||
* @BIOS_SOURCE_ACPI: BIOS source is ACPI
|
||||
* @BIOS_SOURCE_UEFI: BIOS source is UEFI
|
||||
*/
|
||||
enum bios_source {
|
||||
BIOS_SOURCE_NONE,
|
||||
BIOS_SOURCE_ACPI,
|
||||
BIOS_SOURCE_UEFI,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct bios_value_u32 - BIOS configuration.
|
||||
* @table_source: see &enum bios_source
|
||||
* @table_revision: table revision.
|
||||
* @reserved: reserved
|
||||
* @value: value in bios.
|
||||
*/
|
||||
struct bios_value_u32 {
|
||||
u8 table_source;
|
||||
u8 table_revision;
|
||||
u8 reserved[2];
|
||||
__le32 value;
|
||||
} __packed; /* BIOS_TABLE_SOURCE_U32_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_tas_config_cmd - configures the TAS.
|
||||
* @block_list_size: size of relevant field in block_list_array
|
||||
* @block_list_array: list of countries where TAS must be disabled
|
||||
* @reserved: reserved
|
||||
* @tas_config_info: see @struct bios_value_u32
|
||||
*/
|
||||
struct iwl_tas_config_cmd {
|
||||
__le16 block_list_size;
|
||||
__le16 block_list_array[IWL_WTAS_BLACK_LIST_MAX];
|
||||
u8 reserved[2];
|
||||
struct bios_value_u32 tas_config_info;
|
||||
} __packed; /* TAS_CONFIG_CMD_API_S_VER_5 */
|
||||
|
||||
/**
|
||||
* enum iwl_lari_config_masks - bit masks for the various LARI config operations
|
||||
* @LARI_CONFIG_DISABLE_11AC_UKRAINE_MSK: disable 11ac in ukraine
|
||||
@@ -705,7 +754,7 @@ struct iwl_lari_config_change_cmd_v10 {
|
||||
* according to the BIOS definitions.
|
||||
* For LARI cmd version 11 - bits 0:4 are supported.
|
||||
* For LARI cmd version 12 - bits 0:6 are supported and bits 7:31 are
|
||||
* reserved. No need to mask out the reserved bits.
|
||||
* reserved.
|
||||
* @force_disable_channels_bitmap: Bitmap of disabled bands/channels.
|
||||
* Each bit represents a set of channels in a specific band that should be
|
||||
* disabled
|
||||
@@ -738,6 +787,7 @@ struct iwl_lari_config_change_cmd {
|
||||
/* Activate UNII-1 (5.2GHz) for World Wide */
|
||||
#define ACTIVATE_5G2_IN_WW_MASK BIT(4)
|
||||
#define CHAN_STATE_ACTIVE_BITMAP_CMD_V11 0x1F
|
||||
#define CHAN_STATE_ACTIVE_BITMAP_CMD_V12 0x7F
|
||||
|
||||
/**
|
||||
* struct iwl_pnvm_init_complete_ntfy - PNVM initialization complete
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Copyright (C) 2012-2014 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2021-2024 Intel Corporation
|
||||
* Copyright (C) 2021-2025 Intel Corporation
|
||||
*/
|
||||
#ifndef __iwl_fw_api_offload_h__
|
||||
#define __iwl_fw_api_offload_h__
|
||||
@@ -19,7 +19,7 @@ enum iwl_prot_offload_subcmd_ids {
|
||||
|
||||
/**
|
||||
* @WOWLAN_INFO_NOTIFICATION: Notification in
|
||||
* &struct iwl_wowlan_info_notif_v1, &struct iwl_wowlan_info_notif_v2,
|
||||
* &struct iwl_wowlan_info_notif_v1, iwl_wowlan_info_notif_v3,
|
||||
* or &struct iwl_wowlan_info_notif
|
||||
*/
|
||||
WOWLAN_INFO_NOTIFICATION = 0xFD,
|
||||
@@ -31,7 +31,7 @@ enum iwl_prot_offload_subcmd_ids {
|
||||
|
||||
/**
|
||||
* @STORED_BEACON_NTF: &struct iwl_stored_beacon_notif_v2 or
|
||||
* &struct iwl_stored_beacon_notif_v3
|
||||
* &struct iwl_stored_beacon_notif
|
||||
*/
|
||||
STORED_BEACON_NTF = 0xFF,
|
||||
};
|
||||
@@ -71,18 +71,18 @@ struct iwl_stored_beacon_notif_v2 {
|
||||
} __packed; /* WOWLAN_STROED_BEACON_INFO_S_VER_2 */
|
||||
|
||||
/**
|
||||
* struct iwl_stored_beacon_notif_v3 - Stored beacon notification
|
||||
* struct iwl_stored_beacon_notif - Stored beacon notification
|
||||
*
|
||||
* @common: fields common for all versions
|
||||
* @sta_id: station for which the beacon was received
|
||||
* @reserved: reserved for alignment
|
||||
* @data: beacon data, length in @byte_count
|
||||
*/
|
||||
struct iwl_stored_beacon_notif_v3 {
|
||||
struct iwl_stored_beacon_notif {
|
||||
struct iwl_stored_beacon_notif_common common;
|
||||
u8 sta_id;
|
||||
u8 reserved[3];
|
||||
u8 data[MAX_STORED_BEACON_SIZE];
|
||||
} __packed; /* WOWLAN_STROED_BEACON_INFO_S_VER_3 */
|
||||
} __packed; /* WOWLAN_STROED_BEACON_INFO_S_VER_3, _VER_4 */
|
||||
|
||||
#endif /* __iwl_fw_api_offload_h__ */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018, 2020-2024 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018, 2020-2025 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
@@ -146,6 +146,7 @@ struct iwl_phy_context_cmd_v1 {
|
||||
* @sbb_ctrl_channel_loc: location of the control channel
|
||||
* @puncture_mask: bitmap of punctured subchannels
|
||||
* @dsp_cfg_flags: set to 0
|
||||
* @secondary_ctrl_chnl_loc: location of secondary control channel
|
||||
* @reserved: reserved to align to 64 bit
|
||||
*/
|
||||
struct iwl_phy_context_cmd {
|
||||
@@ -164,11 +165,13 @@ struct iwl_phy_context_cmd {
|
||||
};
|
||||
};
|
||||
__le32 dsp_cfg_flags;
|
||||
__le32 reserved;
|
||||
u8 secondary_ctrl_chnl_loc;
|
||||
u8 reserved[3];
|
||||
} __packed; /* PHY_CONTEXT_CMD_API_VER_3,
|
||||
* PHY_CONTEXT_CMD_API_VER_4,
|
||||
* PHY_CONTEXT_CMD_API_VER_5,
|
||||
* PHY_CONTEXT_CMD_API_VER_6
|
||||
* PHY_CONTEXT_CMD_API_VER_6,
|
||||
* PHY_CONTEXT_CMD_API_S_VER_7
|
||||
*/
|
||||
|
||||
#endif /* __iwl_fw_api_phy_ctxt_h__ */
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2019-2022, 2024 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2019-2022, 2024-2025 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
#ifndef __iwl_fw_api_phy_h__
|
||||
#define __iwl_fw_api_phy_h__
|
||||
#include <linux/types.h>
|
||||
#include <linux/bits.h>
|
||||
#if defined(__FreeBSD__)
|
||||
#include <linux/bitops.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* enum iwl_phy_ops_subcmd_ids - PHY group commands
|
||||
@@ -19,7 +24,7 @@ enum iwl_phy_ops_subcmd_ids {
|
||||
CMD_DTS_MEASUREMENT_TRIGGER_WIDE = 0x0,
|
||||
|
||||
/**
|
||||
* @CTDP_CONFIG_CMD: &struct iwl_mvm_ctdp_cmd
|
||||
* @CTDP_CONFIG_CMD: &struct iwl_ctdp_cmd
|
||||
*/
|
||||
CTDP_CONFIG_CMD = 0x03,
|
||||
|
||||
@@ -55,7 +60,7 @@ enum iwl_phy_ops_subcmd_ids {
|
||||
/**
|
||||
* @DTS_MEASUREMENT_NOTIF_WIDE:
|
||||
* &struct iwl_dts_measurement_notif_v1 or
|
||||
* &struct iwl_dts_measurement_notif_v2
|
||||
* &struct iwl_dts_measurement_notif
|
||||
*/
|
||||
DTS_MEASUREMENT_NOTIF_WIDE = 0xFF,
|
||||
};
|
||||
@@ -152,13 +157,13 @@ struct iwl_dts_measurement_notif_v1 {
|
||||
} __packed; /* TEMPERATURE_MEASUREMENT_TRIGGER_NTFY_S_VER_1*/
|
||||
|
||||
/**
|
||||
* struct iwl_dts_measurement_notif_v2 - measurements notification
|
||||
* struct iwl_dts_measurement_notif - measurements notification
|
||||
*
|
||||
* @temp: the measured temperature
|
||||
* @voltage: the measured voltage
|
||||
* @threshold_idx: the trip index that was crossed
|
||||
*/
|
||||
struct iwl_dts_measurement_notif_v2 {
|
||||
struct iwl_dts_measurement_notif {
|
||||
__le32 temp;
|
||||
__le32 voltage;
|
||||
__le32 threshold_idx;
|
||||
@@ -195,25 +200,25 @@ struct ct_kill_notif {
|
||||
} __packed; /* CT_KILL_NOTIFICATION_API_S_VER_1, CT_KILL_NOTIFICATION_API_S_VER_2 */
|
||||
|
||||
/**
|
||||
* enum iwl_mvm_ctdp_cmd_operation - CTDP command operations
|
||||
* enum iwl_ctdp_cmd_operation - CTDP command operations
|
||||
* @CTDP_CMD_OPERATION_START: update the current budget
|
||||
* @CTDP_CMD_OPERATION_STOP: stop ctdp
|
||||
* @CTDP_CMD_OPERATION_REPORT: get the average budget
|
||||
*/
|
||||
enum iwl_mvm_ctdp_cmd_operation {
|
||||
enum iwl_ctdp_cmd_operation {
|
||||
CTDP_CMD_OPERATION_START = 0x1,
|
||||
CTDP_CMD_OPERATION_STOP = 0x2,
|
||||
CTDP_CMD_OPERATION_REPORT = 0x4,
|
||||
};/* CTDP_CMD_OPERATION_TYPE_E */
|
||||
|
||||
/**
|
||||
* struct iwl_mvm_ctdp_cmd - track and manage the FW power consumption budget
|
||||
* struct iwl_ctdp_cmd - track and manage the FW power consumption budget
|
||||
*
|
||||
* @operation: see &enum iwl_mvm_ctdp_cmd_operation
|
||||
* @operation: see &enum iwl_ctdp_cmd_operation
|
||||
* @budget: the budget in milliwatt
|
||||
* @window_size: defined in API but not used
|
||||
*/
|
||||
struct iwl_mvm_ctdp_cmd {
|
||||
struct iwl_ctdp_cmd {
|
||||
__le32 operation;
|
||||
__le32 budget;
|
||||
__le32 window_size;
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2024 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2025 Intel Corporation
|
||||
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2015-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
#ifndef __iwl_fw_api_power_h__
|
||||
#define __iwl_fw_api_power_h__
|
||||
|
||||
#include "nvm-reg.h"
|
||||
|
||||
/* Power Management Commands, Responses, Notifications */
|
||||
|
||||
/**
|
||||
@@ -54,7 +56,7 @@ struct iwl_ltr_config_cmd_v1 {
|
||||
* @flags: See &enum iwl_ltr_config_flags
|
||||
* @static_long: static LTR Long register value.
|
||||
* @static_short: static LTR Short register value.
|
||||
* @ltr_cfg_values: LTR parameters table values (in usec) in folowing order:
|
||||
* @ltr_cfg_values: LTR parameters table values (in usec) in following order:
|
||||
* TX, RX, Short Idle, Long Idle. Used only if %LTR_CFG_FLAG_UPDATE_VALUES
|
||||
* is set.
|
||||
* @ltr_short_idle_timeout: LTR Short Idle timeout (in usec). Used only if
|
||||
@@ -89,6 +91,7 @@ struct iwl_ltr_config_cmd {
|
||||
* @POWER_FLAGS_LPRX_ENA_MSK: Low Power RX enable.
|
||||
* @POWER_FLAGS_UAPSD_MISBEHAVING_ENA_MSK: AP/GO's uAPSD misbehaving
|
||||
* detection enablement
|
||||
* @POWER_FLAGS_ENABLE_SMPS_MSK: SMPS is allowed for this vif
|
||||
*/
|
||||
enum iwl_power_flags {
|
||||
POWER_FLAGS_POWER_SAVE_ENA_MSK = BIT(0),
|
||||
@@ -99,6 +102,7 @@ enum iwl_power_flags {
|
||||
POWER_FLAGS_ADVANCE_PM_ENA_MSK = BIT(9),
|
||||
POWER_FLAGS_LPRX_ENA_MSK = BIT(11),
|
||||
POWER_FLAGS_UAPSD_MISBEHAVING_ENA_MSK = BIT(12),
|
||||
POWER_FLAGS_ENABLE_SMPS_MSK = BIT(14),
|
||||
};
|
||||
|
||||
#define IWL_POWER_VEC_SIZE 5
|
||||
@@ -216,7 +220,6 @@ struct iwl_mac_power_cmd {
|
||||
/* CONTEXT_DESC_API_T_VER_1 */
|
||||
__le32 id_and_color;
|
||||
|
||||
/* CLIENT_PM_POWER_TABLE_S_VER_1 */
|
||||
__le16 flags;
|
||||
__le16 keep_alive_seconds;
|
||||
__le32 rx_data_timeout;
|
||||
@@ -237,7 +240,7 @@ struct iwl_mac_power_cmd {
|
||||
u8 heavy_rx_thld_percentage;
|
||||
u8 limited_ps_threshold;
|
||||
u8 reserved;
|
||||
} __packed;
|
||||
} __packed; /* CLIENT_PM_POWER_TABLE_S_VER_1, VER_2 */
|
||||
|
||||
/*
|
||||
* struct iwl_uapsd_misbehaving_ap_notif - FW sends this notification when
|
||||
@@ -252,21 +255,8 @@ struct iwl_uapsd_misbehaving_ap_notif {
|
||||
u8 reserved[3];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_reduce_tx_power_cmd - TX power reduction command
|
||||
* REDUCE_TX_POWER_CMD = 0x9f
|
||||
* @flags: (reserved for future implementation)
|
||||
* @mac_context_id: id of the mac ctx for which we are reducing TX power.
|
||||
* @pwr_restriction: TX power restriction in dBms.
|
||||
*/
|
||||
struct iwl_reduce_tx_power_cmd {
|
||||
u8 flags;
|
||||
u8 mac_context_id;
|
||||
__le16 pwr_restriction;
|
||||
} __packed; /* TX_REDUCED_POWER_API_S_VER_1 */
|
||||
|
||||
enum iwl_dev_tx_power_cmd_mode {
|
||||
IWL_TX_POWER_MODE_SET_MAC = 0,
|
||||
IWL_TX_POWER_MODE_SET_LINK = 0,
|
||||
IWL_TX_POWER_MODE_SET_DEVICE = 1,
|
||||
IWL_TX_POWER_MODE_SET_CHAINS = 2,
|
||||
IWL_TX_POWER_MODE_SET_ACK = 3,
|
||||
@@ -283,20 +273,16 @@ enum iwl_dev_tx_power_cmd_mode {
|
||||
/**
|
||||
* struct iwl_dev_tx_power_common - Common part of the TX power reduction cmd
|
||||
* @set_mode: see &enum iwl_dev_tx_power_cmd_mode
|
||||
* @mac_context_id: id of the mac ctx for which we are reducing TX power.
|
||||
* @link_id: id of the link ctx for which we are reducing TX power.
|
||||
* For version 9 / 10, this is the link id. For earlier versions, it is
|
||||
* the mac id.
|
||||
* @pwr_restriction: TX power restriction in 1/8 dBms.
|
||||
* @dev_24: device TX power restriction in 1/8 dBms
|
||||
* @dev_52_low: device TX power restriction upper band - low
|
||||
* @dev_52_high: device TX power restriction upper band - high
|
||||
*/
|
||||
struct iwl_dev_tx_power_common {
|
||||
__le32 set_mode;
|
||||
__le32 mac_context_id;
|
||||
__le32 link_id;
|
||||
__le16 pwr_restriction;
|
||||
__le16 dev_24;
|
||||
__le16 dev_52_low;
|
||||
__le16 dev_52_high;
|
||||
};
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_dev_tx_power_cmd_v3 - TX power reduction command version 3
|
||||
@@ -342,50 +328,6 @@ struct iwl_dev_tx_power_cmd_v5 {
|
||||
__le32 timer_period;
|
||||
} __packed; /* TX_REDUCED_POWER_API_S_VER_5 */
|
||||
|
||||
/**
|
||||
* struct iwl_dev_tx_power_cmd_v6 - TX power reduction command version 6
|
||||
* @per_chain: per chain restrictions
|
||||
* @enable_ack_reduction: enable or disable close range ack TX power
|
||||
* reduction.
|
||||
* @per_chain_restriction_changed: is per_chain_restriction has changed
|
||||
* from last command. used if set_mode is
|
||||
* IWL_TX_POWER_MODE_SET_SAR_TIMER.
|
||||
* note: if not changed, the command is used for keep alive only.
|
||||
* @reserved: reserved (padding)
|
||||
* @timer_period: timer in milliseconds. if expires FW will change to default
|
||||
* BIOS values. relevant if setMode is IWL_TX_POWER_MODE_SET_SAR_TIMER
|
||||
*/
|
||||
struct iwl_dev_tx_power_cmd_v6 {
|
||||
__le16 per_chain[IWL_NUM_CHAIN_TABLES_V2][IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V2];
|
||||
u8 enable_ack_reduction;
|
||||
u8 per_chain_restriction_changed;
|
||||
u8 reserved[2];
|
||||
__le32 timer_period;
|
||||
} __packed; /* TX_REDUCED_POWER_API_S_VER_6 */
|
||||
|
||||
/**
|
||||
* struct iwl_dev_tx_power_cmd_v7 - TX power reduction command version 7
|
||||
* @per_chain: per chain restrictions
|
||||
* @enable_ack_reduction: enable or disable close range ack TX power
|
||||
* reduction.
|
||||
* @per_chain_restriction_changed: is per_chain_restriction has changed
|
||||
* from last command. used if set_mode is
|
||||
* IWL_TX_POWER_MODE_SET_SAR_TIMER.
|
||||
* note: if not changed, the command is used for keep alive only.
|
||||
* @reserved: reserved (padding)
|
||||
* @timer_period: timer in milliseconds. if expires FW will change to default
|
||||
* BIOS values. relevant if setMode is IWL_TX_POWER_MODE_SET_SAR_TIMER
|
||||
* @flags: reduce power flags.
|
||||
*/
|
||||
struct iwl_dev_tx_power_cmd_v7 {
|
||||
__le16 per_chain[IWL_NUM_CHAIN_TABLES_V2][IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V2];
|
||||
u8 enable_ack_reduction;
|
||||
u8 per_chain_restriction_changed;
|
||||
u8 reserved[2];
|
||||
__le32 timer_period;
|
||||
__le32 flags;
|
||||
} __packed; /* TX_REDUCED_POWER_API_S_VER_7 */
|
||||
|
||||
/**
|
||||
* struct iwl_dev_tx_power_cmd_v8 - TX power reduction command version 8
|
||||
* @per_chain: per chain restrictions
|
||||
@@ -412,28 +354,91 @@ struct iwl_dev_tx_power_cmd_v8 {
|
||||
__le32 tpc_vlp_backoff_level;
|
||||
} __packed; /* TX_REDUCED_POWER_API_S_VER_8 */
|
||||
|
||||
/*
|
||||
* @dev_24: device TX power restriction in 1/8 dBms
|
||||
* @dev_52_low: device TX power restriction upper band - low
|
||||
* @dev_52_high: device TX power restriction upper band - high
|
||||
*/
|
||||
struct iwl_dev_tx_power_cmd_per_band {
|
||||
__le16 dev_24;
|
||||
__le16 dev_52_low;
|
||||
__le16 dev_52_high;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_dev_tx_power_cmd - TX power reduction command (multiversion)
|
||||
* struct iwl_dev_tx_power_cmd_v3_v8 - TX power reduction command (multiversion)
|
||||
* @per_band: per band restrictions
|
||||
* @common: common part of the command
|
||||
* @v3: version 3 part of the command
|
||||
* @v4: version 4 part of the command
|
||||
* @v5: version 5 part of the command
|
||||
* @v6: version 6 part of the command
|
||||
* @v7: version 7 part of the command
|
||||
* @v8: version 8 part of the command
|
||||
*/
|
||||
struct iwl_dev_tx_power_cmd {
|
||||
struct iwl_dev_tx_power_cmd_v3_v8 {
|
||||
struct iwl_dev_tx_power_common common;
|
||||
struct iwl_dev_tx_power_cmd_per_band per_band;
|
||||
union {
|
||||
struct iwl_dev_tx_power_cmd_v3 v3;
|
||||
struct iwl_dev_tx_power_cmd_v4 v4;
|
||||
struct iwl_dev_tx_power_cmd_v5 v5;
|
||||
struct iwl_dev_tx_power_cmd_v6 v6;
|
||||
struct iwl_dev_tx_power_cmd_v7 v7;
|
||||
struct iwl_dev_tx_power_cmd_v8 v8;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_dev_tx_power_cmd_v9 - TX power reduction cmd
|
||||
* @reserved: reserved (padding)
|
||||
* @per_chain: per chain restrictions
|
||||
* @per_chain_restriction_changed: is per_chain_restriction has changed
|
||||
* from last command. used if set_mode is
|
||||
* IWL_TX_POWER_MODE_SET_SAR_TIMER.
|
||||
* note: if not changed, the command is used for keep alive only.
|
||||
* @reserved1: reserved (padding)
|
||||
* @timer_period: timer in milliseconds. if expires FW will change to default
|
||||
* BIOS values. relevant if setMode is IWL_TX_POWER_MODE_SET_SAR_TIMER
|
||||
*/
|
||||
struct iwl_dev_tx_power_cmd_v9 {
|
||||
__le16 reserved;
|
||||
__le16 per_chain[IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V1];
|
||||
u8 per_chain_restriction_changed;
|
||||
u8 reserved1[3];
|
||||
__le32 timer_period;
|
||||
} __packed; /* TX_REDUCED_POWER_API_S_VER_9 */
|
||||
|
||||
/**
|
||||
* struct iwl_dev_tx_power_cmd_v10 - TX power reduction cmd
|
||||
* @per_chain: per chain restrictions
|
||||
* @per_chain_restriction_changed: is per_chain_restriction has changed
|
||||
* from last command. used if set_mode is
|
||||
* IWL_TX_POWER_MODE_SET_SAR_TIMER.
|
||||
* note: if not changed, the command is used for keep alive only.
|
||||
* @reserved: reserved (padding)
|
||||
* @timer_period: timer in milliseconds. if expires FW will change to default
|
||||
* BIOS values. relevant if setMode is IWL_TX_POWER_MODE_SET_SAR_TIMER
|
||||
* @flags: reduce power flags.
|
||||
*/
|
||||
struct iwl_dev_tx_power_cmd_v10 {
|
||||
__le16 per_chain[IWL_NUM_CHAIN_TABLES_V2][IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V2];
|
||||
u8 per_chain_restriction_changed;
|
||||
u8 reserved;
|
||||
__le32 timer_period;
|
||||
__le32 flags;
|
||||
} __packed; /* TX_REDUCED_POWER_API_S_VER_10 */
|
||||
|
||||
/*
|
||||
* struct iwl_dev_tx_power_cmd - TX power reduction command (multiversion)
|
||||
* @common: common part of the command
|
||||
* @v9: version 9 part of the command
|
||||
* @v10: version 10 part of the command
|
||||
*/
|
||||
struct iwl_dev_tx_power_cmd {
|
||||
struct iwl_dev_tx_power_common common;
|
||||
union {
|
||||
struct iwl_dev_tx_power_cmd_v9 v9;
|
||||
struct iwl_dev_tx_power_cmd_v10 v10;
|
||||
};
|
||||
} __packed; /* TX_REDUCED_POWER_API_S_VER_9_VER10 */
|
||||
|
||||
#define IWL_NUM_GEO_PROFILES 3
|
||||
#define IWL_NUM_GEO_PROFILES_V3 8
|
||||
#define IWL_NUM_BANDS_PER_CHAIN_V1 2
|
||||
@@ -565,28 +570,37 @@ enum iwl_ppag_flags {
|
||||
|
||||
/**
|
||||
* union iwl_ppag_table_cmd - union for all versions of PPAG command
|
||||
* @v1: version 1
|
||||
* @v2: version 2
|
||||
* version 3, 4, 5 and 6 are the same structure as v2,
|
||||
* @v1: command version 1 structure.
|
||||
* @v2: command version from 2 to 6 are same structure as v2.
|
||||
* but has a different format of the flags bitmap
|
||||
* @v3: command version 7 structure.
|
||||
* @v1.flags: values from &enum iwl_ppag_flags
|
||||
* @v1.gain: table of antenna gain values per chain and sub-band
|
||||
* @v1.reserved: reserved
|
||||
* @v2.flags: values from &enum iwl_ppag_flags
|
||||
* @v2.gain: table of antenna gain values per chain and sub-band
|
||||
* @v2.reserved: reserved
|
||||
* @v3.ppag_config_info: see @struct bios_value_u32
|
||||
* @v3.gain: table of antenna gain values per chain and sub-band
|
||||
* @v3.reserved: reserved
|
||||
*/
|
||||
union iwl_ppag_table_cmd {
|
||||
struct {
|
||||
__le32 flags;
|
||||
s8 gain[IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V1];
|
||||
s8 reserved[2];
|
||||
} v1;
|
||||
} __packed v1; /* PER_PLAT_ANTENNA_GAIN_CMD_API_S_VER_1 */
|
||||
struct {
|
||||
__le32 flags;
|
||||
s8 gain[IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V2];
|
||||
s8 reserved[2];
|
||||
} v2;
|
||||
} __packed v2; /* PER_PLAT_ANTENNA_GAIN_CMD_API_S_VER_2, VER3, VER4,
|
||||
* VER5, VER6
|
||||
*/
|
||||
struct {
|
||||
struct bios_value_u32 ppag_config_info;
|
||||
s8 gain[IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V2];
|
||||
s8 reserved[2];
|
||||
} __packed v3; /* PER_PLAT_ANTENNA_GAIN_CMD_API_S_VER_7 */
|
||||
} __packed;
|
||||
|
||||
#define IWL_PPAG_CMD_V4_MASK (IWL_PPAG_ETSI_MASK | IWL_PPAG_CHINA_MASK)
|
||||
@@ -594,6 +608,15 @@ union iwl_ppag_table_cmd {
|
||||
IWL_PPAG_ETSI_LPI_UHB_MASK | \
|
||||
IWL_PPAG_USA_LPI_UHB_MASK)
|
||||
|
||||
#define IWL_PPAG_CMD_V6_MASK (IWL_PPAG_CMD_V5_MASK | \
|
||||
IWL_PPAG_ETSI_VLP_UHB_MASK | \
|
||||
IWL_PPAG_ETSI_SP_UHB_MASK | \
|
||||
IWL_PPAG_USA_VLP_UHB_MASK | \
|
||||
IWL_PPAG_USA_SP_UHB_MASK | \
|
||||
IWL_PPAG_CANADA_LPI_UHB_MASK | \
|
||||
IWL_PPAG_CANADA_VLP_UHB_MASK | \
|
||||
IWL_PPAG_CANADA_SP_UHB_MASK)
|
||||
|
||||
#define MCC_TO_SAR_OFFSET_TABLE_ROW_SIZE 26
|
||||
#define MCC_TO_SAR_OFFSET_TABLE_COL_SIZE 13
|
||||
|
||||
@@ -627,7 +650,7 @@ struct iwl_sar_offset_mapping_cmd {
|
||||
* Roaming Energy Delta Threshold, otherwise use normal Energy Delta
|
||||
* Threshold. Typical energy threshold is -72dBm.
|
||||
* @bf_temp_threshold: This threshold determines the type of temperature
|
||||
* filtering (Slow or Fast) that is selected (Units are in Celsuis):
|
||||
* filtering (Slow or Fast) that is selected (Units are in Celsius):
|
||||
* If the current temperature is above this threshold - Fast filter
|
||||
* will be used, If the current temperature is below this threshold -
|
||||
* Slow filter will be used.
|
||||
@@ -635,12 +658,12 @@ struct iwl_sar_offset_mapping_cmd {
|
||||
* calculated for this and the last passed beacon is greater than this
|
||||
* threshold. Zero value means that the temperature change is ignored for
|
||||
* beacon filtering; beacons will not be forced to be sent to driver
|
||||
* regardless of whether its temerature has been changed.
|
||||
* regardless of whether its temperature has been changed.
|
||||
* @bf_temp_slow_filter: Send Beacon to driver if delta in temperature values
|
||||
* calculated for this and the last passed beacon is greater than this
|
||||
* threshold. Zero value means that the temperature change is ignored for
|
||||
* beacon filtering; beacons will not be forced to be sent to driver
|
||||
* regardless of whether its temerature has been changed.
|
||||
* regardless of whether its temperature has been changed.
|
||||
* @bf_enable_beacon_filter: 1, beacon filtering is enabled; 0, disabled.
|
||||
* @bf_debug_flag: beacon filtering debug configuration
|
||||
* @bf_escape_timer: Send beacons to to driver if no beacons were passed
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2022, 2024 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2022, 2024-2025 Intel Corporation
|
||||
* Copyright (C) 2017 Intel Deutschland GmbH
|
||||
*/
|
||||
#ifndef __iwl_fw_api_rs_h__
|
||||
#define __iwl_fw_api_rs_h__
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/bits.h>
|
||||
#include "mac.h"
|
||||
|
||||
/**
|
||||
@@ -213,7 +215,8 @@ enum iwl_tlc_update_flags {
|
||||
* @sta_id: station id
|
||||
* @reserved: reserved
|
||||
* @flags: bitmap of notifications reported
|
||||
* @rate: current initial rate
|
||||
* @rate: current initial rate, format depends on the notification
|
||||
* version
|
||||
* @amsdu_size: Max AMSDU size, in bytes
|
||||
* @amsdu_enabled: bitmap for per-TID AMSDU enablement
|
||||
*/
|
||||
@@ -224,8 +227,60 @@ struct iwl_tlc_update_notif {
|
||||
__le32 rate;
|
||||
__le32 amsdu_size;
|
||||
__le32 amsdu_enabled;
|
||||
} __packed; /* TLC_MNG_UPDATE_NTFY_API_S_VER_2 */
|
||||
} __packed; /* TLC_MNG_UPDATE_NTFY_API_S_VER_2, _VER_3, _VER_4 */
|
||||
|
||||
/**
|
||||
* enum iwl_tlc_debug_types - debug options
|
||||
*/
|
||||
enum iwl_tlc_debug_types {
|
||||
/**
|
||||
* @IWL_TLC_DEBUG_FIXED_RATE: set fixed rate for rate scaling
|
||||
*/
|
||||
IWL_TLC_DEBUG_FIXED_RATE,
|
||||
/**
|
||||
* @IWL_TLC_DEBUG_AGG_DURATION_LIM: time limit for a BA
|
||||
* session, in usec
|
||||
*/
|
||||
IWL_TLC_DEBUG_AGG_DURATION_LIM,
|
||||
/**
|
||||
* @IWL_TLC_DEBUG_AGG_FRAME_CNT_LIM: set max number of frames
|
||||
* in an aggregation
|
||||
*/
|
||||
IWL_TLC_DEBUG_AGG_FRAME_CNT_LIM,
|
||||
/**
|
||||
* @IWL_TLC_DEBUG_TPC_ENABLED: enable or disable tpc
|
||||
*/
|
||||
IWL_TLC_DEBUG_TPC_ENABLED,
|
||||
/**
|
||||
* @IWL_TLC_DEBUG_TPC_STATS: get number of frames Tx'ed in each
|
||||
* tpc step
|
||||
*/
|
||||
IWL_TLC_DEBUG_TPC_STATS,
|
||||
/**
|
||||
* @IWL_TLC_DEBUG_RTS_DISABLE: disable RTS (bool true/false).
|
||||
*/
|
||||
IWL_TLC_DEBUG_RTS_DISABLE,
|
||||
/**
|
||||
* @IWL_TLC_DEBUG_PARTIAL_FIXED_RATE: set partial fixed rate to fw
|
||||
*/
|
||||
IWL_TLC_DEBUG_PARTIAL_FIXED_RATE,
|
||||
}; /* TLC_MNG_DEBUG_TYPES_API_E */
|
||||
|
||||
#define MAX_DATA_IN_DHC_TLC_CMD 10
|
||||
|
||||
/**
|
||||
* struct iwl_dhc_tlc_cmd - fixed debug config
|
||||
* @sta_id: bit 0 - enable/disable, bits 1 - 7 hold station id
|
||||
* @reserved1: reserved
|
||||
* @type: type id of %enum iwl_tlc_debug_types
|
||||
* @data: data to send
|
||||
*/
|
||||
struct iwl_dhc_tlc_cmd {
|
||||
u8 sta_id;
|
||||
u8 reserved1[3];
|
||||
__le32 type;
|
||||
__le32 data[MAX_DATA_IN_DHC_TLC_CMD];
|
||||
} __packed; /* TLC_MNG_DEBUG_CMD_S */
|
||||
|
||||
#define IWL_MAX_MCS_DISPLAY_SIZE 12
|
||||
|
||||
@@ -375,6 +430,7 @@ enum {
|
||||
|
||||
/* Bit 4-5: (0) SISO, (1) MIMO2 (2) MIMO3 */
|
||||
#define RATE_VHT_MCS_RATE_CODE_MSK 0xf
|
||||
#define RATE_VHT_MCS_NSS_MSK 0x30
|
||||
|
||||
/*
|
||||
* Legacy OFDM rate format for bits 7:0
|
||||
@@ -489,7 +545,7 @@ enum {
|
||||
#define RATE_MCS_CTS_REQUIRED_POS (31)
|
||||
#define RATE_MCS_CTS_REQUIRED_MSK (0x1 << RATE_MCS_CTS_REQUIRED_POS)
|
||||
|
||||
/* rate_n_flags bit field version 2
|
||||
/* rate_n_flags bit field version 2 and 3
|
||||
*
|
||||
* The 32-bit value has different layouts in the low 8 bits depending on the
|
||||
* format. There are three formats, HT, VHT and legacy (11abg, with subformats
|
||||
@@ -501,23 +557,25 @@ enum {
|
||||
* (0) Legacy CCK (1) Legacy OFDM (2) High-throughput (HT)
|
||||
* (3) Very High-throughput (VHT) (4) High-efficiency (HE)
|
||||
* (5) Extremely High-throughput (EHT)
|
||||
* (6) Ultra High Reliability (UHR) (v3 rate format only)
|
||||
*/
|
||||
#define RATE_MCS_MOD_TYPE_POS 8
|
||||
#define RATE_MCS_MOD_TYPE_MSK (0x7 << RATE_MCS_MOD_TYPE_POS)
|
||||
#define RATE_MCS_CCK_MSK (0 << RATE_MCS_MOD_TYPE_POS)
|
||||
#define RATE_MCS_LEGACY_OFDM_MSK (1 << RATE_MCS_MOD_TYPE_POS)
|
||||
#define RATE_MCS_HT_MSK (2 << RATE_MCS_MOD_TYPE_POS)
|
||||
#define RATE_MCS_VHT_MSK (3 << RATE_MCS_MOD_TYPE_POS)
|
||||
#define RATE_MCS_HE_MSK (4 << RATE_MCS_MOD_TYPE_POS)
|
||||
#define RATE_MCS_EHT_MSK (5 << RATE_MCS_MOD_TYPE_POS)
|
||||
#define RATE_MCS_MOD_TYPE_CCK (0 << RATE_MCS_MOD_TYPE_POS)
|
||||
#define RATE_MCS_MOD_TYPE_LEGACY_OFDM (1 << RATE_MCS_MOD_TYPE_POS)
|
||||
#define RATE_MCS_MOD_TYPE_HT (2 << RATE_MCS_MOD_TYPE_POS)
|
||||
#define RATE_MCS_MOD_TYPE_VHT (3 << RATE_MCS_MOD_TYPE_POS)
|
||||
#define RATE_MCS_MOD_TYPE_HE (4 << RATE_MCS_MOD_TYPE_POS)
|
||||
#define RATE_MCS_MOD_TYPE_EHT (5 << RATE_MCS_MOD_TYPE_POS)
|
||||
#define RATE_MCS_MOD_TYPE_UHR (6 << RATE_MCS_MOD_TYPE_POS)
|
||||
|
||||
/*
|
||||
* Legacy CCK rate format for bits 0:3:
|
||||
*
|
||||
* (0) 0xa - 1 Mbps
|
||||
* (1) 0x14 - 2 Mbps
|
||||
* (2) 0x37 - 5.5 Mbps
|
||||
* (3) 0x6e - 11 nbps
|
||||
* (0) 1 Mbps
|
||||
* (1) 2 Mbps
|
||||
* (2) 5.5 Mbps
|
||||
* (3) 11 Mbps
|
||||
*
|
||||
* Legacy OFDM rate format for bis 3:0:
|
||||
*
|
||||
@@ -534,15 +592,19 @@ enum {
|
||||
#define RATE_LEGACY_RATE_MSK 0x7
|
||||
|
||||
/*
|
||||
* HT, VHT, HE, EHT rate format for bits 3:0
|
||||
* 3-0: MCS
|
||||
*
|
||||
* HT, VHT, HE, EHT, UHR rate format
|
||||
* Version 2: (not applicable for UHR)
|
||||
* 3-0: MCS
|
||||
* 4: NSS==2 indicator
|
||||
* Version 3:
|
||||
* 4-0: MCS
|
||||
* 5: NSS==2 indicator
|
||||
*/
|
||||
#define RATE_HT_MCS_CODE_MSK 0x7
|
||||
#define RATE_MCS_NSS_POS 4
|
||||
#define RATE_MCS_NSS_MSK (1 << RATE_MCS_NSS_POS)
|
||||
#define RATE_MCS_CODE_MSK 0xf
|
||||
#define RATE_HT_MCS_INDEX(r) ((((r) & RATE_MCS_NSS_MSK) >> 1) | \
|
||||
#define RATE_MCS_NSS_MSK_V2 0x10
|
||||
#define RATE_MCS_NSS_MSK 0x20
|
||||
#define RATE_MCS_CODE_MSK 0x1f
|
||||
#define RATE_HT_MCS_INDEX(r) ((((r) & RATE_MCS_NSS_MSK) >> 2) | \
|
||||
((r) & RATE_HT_MCS_CODE_MSK))
|
||||
|
||||
/* Bits 7-5: reserved */
|
||||
@@ -758,11 +820,38 @@ struct iwl_lq_cmd {
|
||||
}; /* LINK_QUALITY_CMD_API_S_VER_1 */
|
||||
|
||||
u8 iwl_fw_rate_idx_to_plcp(int idx);
|
||||
u32 iwl_new_rate_from_v1(u32 rate_v1);
|
||||
const struct iwl_rate_mcs_info *iwl_rate_mcs(int idx);
|
||||
const char *iwl_rs_pretty_ant(u8 ant);
|
||||
const char *iwl_rs_pretty_bw(int bw);
|
||||
int rs_pretty_print_rate(char *buf, int bufsz, const u32 rate);
|
||||
bool iwl_he_is_sgi(u32 rate_n_flags);
|
||||
|
||||
static inline u32 iwl_v3_rate_from_v2_v3(__le32 rate, bool fw_v3)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
if (fw_v3)
|
||||
return le32_to_cpu(rate);
|
||||
|
||||
val = le32_to_cpu(rate) & ~RATE_MCS_NSS_MSK_V2;
|
||||
val |= u32_encode_bits(le32_get_bits(rate, RATE_MCS_NSS_MSK_V2),
|
||||
RATE_MCS_NSS_MSK);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline __le32 iwl_v3_rate_to_v2_v3(u32 rate, bool fw_v3)
|
||||
{
|
||||
__le32 val;
|
||||
|
||||
if (fw_v3)
|
||||
return cpu_to_le32(rate);
|
||||
|
||||
val = cpu_to_le32(rate & ~RATE_MCS_NSS_MSK);
|
||||
val |= le32_encode_bits(u32_get_bits(rate, RATE_MCS_NSS_MSK),
|
||||
RATE_MCS_NSS_MSK_V2);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
#endif /* __iwl_fw_api_rs_h__ */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2024 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2025 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2015-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
@@ -193,10 +193,13 @@ enum iwl_rx_mpdu_amsdu_info {
|
||||
IWL_RX_MPDU_AMSDU_LAST_SUBFRAME = 0x80,
|
||||
};
|
||||
|
||||
#define RX_MPDU_BAND_POS 6
|
||||
#define RX_MPDU_BAND_MASK 0xC0
|
||||
#define BAND_IN_RX_STATUS(_val) \
|
||||
(((_val) & RX_MPDU_BAND_MASK) >> RX_MPDU_BAND_POS)
|
||||
enum iwl_rx_mpdu_mac_phy_band {
|
||||
/* whether or not this is MAC or LINK depends on the API */
|
||||
IWL_RX_MPDU_MAC_PHY_BAND_MAC_MASK = 0x0f,
|
||||
IWL_RX_MPDU_MAC_PHY_BAND_LINK_MASK = 0x0f,
|
||||
IWL_RX_MPDU_MAC_PHY_BAND_PHY_MASK = 0x30,
|
||||
IWL_RX_MPDU_MAC_PHY_BAND_BAND_MASK = 0xc0,
|
||||
};
|
||||
|
||||
enum iwl_rx_l3_proto_values {
|
||||
IWL_RX_L3_TYPE_NONE,
|
||||
@@ -642,7 +645,9 @@ struct iwl_rx_mpdu_desc_v3 {
|
||||
*/
|
||||
__le32 reserved[1];
|
||||
} __packed; /* RX_MPDU_RES_START_API_S_VER_3,
|
||||
RX_MPDU_RES_START_API_S_VER_5 */
|
||||
* RX_MPDU_RES_START_API_S_VER_5,
|
||||
* RX_MPDU_RES_START_API_S_VER_6
|
||||
*/
|
||||
|
||||
/**
|
||||
* struct iwl_rx_mpdu_desc - RX MPDU descriptor
|
||||
@@ -671,9 +676,10 @@ struct iwl_rx_mpdu_desc {
|
||||
*/
|
||||
__le16 phy_info;
|
||||
/**
|
||||
* @mac_phy_idx: MAC/PHY index
|
||||
* @mac_phy_band: MAC/link ID, PHY ID, band;
|
||||
* see &enum iwl_rx_mpdu_mac_phy_band
|
||||
*/
|
||||
u8 mac_phy_idx;
|
||||
u8 mac_phy_band;
|
||||
/* DW4 */
|
||||
union {
|
||||
struct {
|
||||
@@ -725,8 +731,10 @@ struct iwl_rx_mpdu_desc {
|
||||
struct iwl_rx_mpdu_desc_v3 v3;
|
||||
};
|
||||
} __packed; /* RX_MPDU_RES_START_API_S_VER_3,
|
||||
RX_MPDU_RES_START_API_S_VER_4,
|
||||
RX_MPDU_RES_START_API_S_VER_5 */
|
||||
* RX_MPDU_RES_START_API_S_VER_4,
|
||||
* RX_MPDU_RES_START_API_S_VER_5,
|
||||
* RX_MPDU_RES_START_API_S_VER_6
|
||||
*/
|
||||
|
||||
#define IWL_RX_DESC_SIZE_V1 offsetofend(struct iwl_rx_mpdu_desc, v1)
|
||||
|
||||
@@ -822,7 +830,7 @@ struct iwl_rx_no_data {
|
||||
* 15:8 chain-B, measured at FINA time (FINA_ENERGY), 16:23 channel
|
||||
* @on_air_rise_time: GP2 during on air rise
|
||||
* @fr_time: frame time
|
||||
* @rate: rate/mcs of frame
|
||||
* @rate: rate/mcs of frame, format depends on the notification version
|
||||
* @phy_info: &enum iwl_rx_phy_eht_data0 and &enum iwl_rx_phy_info_type
|
||||
* @rx_vec: DW-12:9 raw RX vectors from DSP according to modulation type.
|
||||
* for VHT: OFDM_RX_VECTOR_SIGA1_OUT, OFDM_RX_VECTOR_SIGA2_OUT
|
||||
@@ -838,9 +846,7 @@ struct iwl_rx_no_data_ver_3 {
|
||||
__le32 rate;
|
||||
__le32 phy_info[2];
|
||||
__le32 rx_vec[4];
|
||||
} __packed; /* RX_NO_DATA_NTFY_API_S_VER_1,
|
||||
RX_NO_DATA_NTFY_API_S_VER_2
|
||||
RX_NO_DATA_NTFY_API_S_VER_3 */
|
||||
} __packed; /* RX_NO_DATA_NTFY_API_S_VER_3, _VER_4 */
|
||||
|
||||
struct iwl_frame_release {
|
||||
u8 baid;
|
||||
@@ -1030,4 +1036,24 @@ struct iwl_rfh_queue_config {
|
||||
#endif
|
||||
} __packed; /* RFH_QUEUE_CONFIG_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_beacon_filter_notif_v1 - beacon filter notification
|
||||
* @average_energy: average energy for the received beacon
|
||||
* @mac_id: MAC ID the beacon was received for
|
||||
*/
|
||||
struct iwl_beacon_filter_notif_v1 {
|
||||
__le32 average_energy;
|
||||
__le32 mac_id;
|
||||
} __packed; /* BEACON_FILTER_IN_NTFY_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_beacon_filter_notif - beacon filter notification
|
||||
* @average_energy: average energy for the received beacon
|
||||
* @link_id: link ID the beacon was received for
|
||||
*/
|
||||
struct iwl_beacon_filter_notif {
|
||||
__le32 average_energy;
|
||||
__le32 link_id;
|
||||
} __packed; /* BEACON_FILTER_IN_NTFY_API_S_VER_2 */
|
||||
|
||||
#endif /* __iwl_fw_api_rx_h__ */
|
||||
|
||||
@@ -731,39 +731,46 @@ enum iwl_umac_scan_general_params_flags2 {
|
||||
* struct iwl_scan_channel_cfg_umac
|
||||
* @flags: bitmap - 0-19: directed scan to i'th ssid.
|
||||
* @channel_num: channel number 1-13 etc.
|
||||
* @band: band of channel: 0 for 2GHz, 1 for 5GHz
|
||||
* @iter_count: repetition count for the channel.
|
||||
* @iter_interval: interval between two scan iterations on one channel.
|
||||
* @v1: command version 1
|
||||
* @v1.iter_count: repetition count for the channel.
|
||||
* @v1.iter_interval: interval between two scan iterations on one channel.
|
||||
* @v2: command versions 2-4
|
||||
* @v2.band: band of channel: 0 for 2GHz, 1 for 5GHz
|
||||
* @v2.iter_count: repetition count for the channel.
|
||||
* @v2.iter_interval: interval between two scan iterations on one channel.
|
||||
* @v5: command versions 5 and up
|
||||
* @v5.iter_count: repetition count for the channel.
|
||||
* @v5.iter_interval: interval between two scan iterations on one channel.
|
||||
* @v5.psd_20: highest PSD value for all APs known so far
|
||||
* on this channel.
|
||||
*/
|
||||
struct iwl_scan_channel_cfg_umac {
|
||||
#define IWL_CHAN_CFG_FLAGS_BAND_POS 30
|
||||
__le32 flags;
|
||||
u8 channel_num;
|
||||
|
||||
/* All versions are of the same size, so use a union without adjusting
|
||||
* the command size later
|
||||
*/
|
||||
union {
|
||||
struct {
|
||||
u8 channel_num;
|
||||
u8 iter_count;
|
||||
__le16 iter_interval;
|
||||
} v1; /* SCAN_CHANNEL_CONFIG_API_S_VER_1 */
|
||||
} __packed v1; /* SCAN_CHANNEL_CONFIG_API_S_VER_1 */
|
||||
struct {
|
||||
u8 channel_num;
|
||||
u8 band;
|
||||
u8 iter_count;
|
||||
u8 iter_interval;
|
||||
} v2; /* SCAN_CHANNEL_CONFIG_API_S_VER_2
|
||||
* SCAN_CHANNEL_CONFIG_API_S_VER_3
|
||||
* SCAN_CHANNEL_CONFIG_API_S_VER_4
|
||||
*/
|
||||
} __packed v2; /* SCAN_CHANNEL_CONFIG_API_S_VER_2
|
||||
* SCAN_CHANNEL_CONFIG_API_S_VER_3
|
||||
* SCAN_CHANNEL_CONFIG_API_S_VER_4
|
||||
*/
|
||||
struct {
|
||||
u8 channel_num;
|
||||
u8 psd_20;
|
||||
u8 iter_count;
|
||||
u8 iter_interval;
|
||||
} v5; /* SCAN_CHANNEL_CONFIG_API_S_VER_5 */
|
||||
};
|
||||
} __packed v5; /* SCAN_CHANNEL_CONFIG_API_S_VER_5 */
|
||||
} __packed;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
@@ -1132,6 +1139,19 @@ struct iwl_umac_scan_abort {
|
||||
__le32 flags;
|
||||
} __packed; /* SCAN_ABORT_CMD_UMAC_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* enum iwl_umac_scan_abort_status
|
||||
*
|
||||
* @IWL_UMAC_SCAN_ABORT_STATUS_SUCCESS: scan was successfully aborted
|
||||
* @IWL_UMAC_SCAN_ABORT_STATUS_IN_PROGRESS: scan abort is in progress
|
||||
* @IWL_UMAC_SCAN_ABORT_STATUS_NOT_FOUND: nothing to abort
|
||||
*/
|
||||
enum iwl_umac_scan_abort_status {
|
||||
IWL_UMAC_SCAN_ABORT_STATUS_SUCCESS = 0,
|
||||
IWL_UMAC_SCAN_ABORT_STATUS_IN_PROGRESS,
|
||||
IWL_UMAC_SCAN_ABORT_STATUS_NOT_FOUND,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_umac_scan_complete
|
||||
* @uid: scan id, &enum iwl_umac_scan_uid_offsets
|
||||
|
||||
@@ -191,6 +191,7 @@ enum iwl_sta_sleep_flag {
|
||||
#define STA_KEY_IDX_INVALID (0xff)
|
||||
#define STA_KEY_MAX_DATA_KEY_NUM (4)
|
||||
#define IWL_MAX_GLOBAL_KEYS (4)
|
||||
#define IWL_MAX_NUM_IGTKS 2
|
||||
#define STA_KEY_LEN_WEP40 (5)
|
||||
#define STA_KEY_LEN_WEP104 (13)
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018, 2020 - 2021, 2023 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018, 2020-2021, 2023-2025 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
@@ -327,14 +327,14 @@ struct mvm_statistics_load {
|
||||
__le32 air_time[MAC_INDEX_AUX];
|
||||
__le32 byte_count[MAC_INDEX_AUX];
|
||||
__le32 pkt_count[MAC_INDEX_AUX];
|
||||
u8 avg_energy[IWL_MVM_STATION_COUNT_MAX];
|
||||
u8 avg_energy[IWL_STATION_COUNT_MAX];
|
||||
} __packed; /* STATISTICS_RX_MAC_STATION_S_VER_3 */
|
||||
|
||||
struct mvm_statistics_load_v1 {
|
||||
__le32 air_time[NUM_MAC_INDEX];
|
||||
__le32 byte_count[NUM_MAC_INDEX];
|
||||
__le32 pkt_count[NUM_MAC_INDEX];
|
||||
u8 avg_energy[IWL_MVM_STATION_COUNT_MAX];
|
||||
u8 avg_energy[IWL_STATION_COUNT_MAX];
|
||||
} __packed; /* STATISTICS_RX_MAC_STATION_S_VER_1 */
|
||||
|
||||
struct mvm_statistics_rx {
|
||||
@@ -584,6 +584,9 @@ struct iwl_stats_ntfy_per_phy {
|
||||
__le32 last_tx_ch_width_indx;
|
||||
} __packed; /* STATISTICS_NTFY_PER_PHY_API_S_VER_1 */
|
||||
|
||||
/* unknown channel load (due to not being active on channel) */
|
||||
#define IWL_STATS_UNKNOWN_CHANNEL_LOAD 0xffffffff
|
||||
|
||||
/**
|
||||
* struct iwl_stats_ntfy_per_sta
|
||||
*
|
||||
@@ -594,7 +597,7 @@ struct iwl_stats_ntfy_per_sta {
|
||||
} __packed; /* STATISTICS_NTFY_PER_STA_API_S_VER_1 */
|
||||
|
||||
#define IWL_STATS_MAX_PHY_OPERATIONAL 3
|
||||
#define IWL_STATS_MAX_FW_LINKS (IWL_MVM_FW_MAX_LINK_ID + 1)
|
||||
#define IWL_STATS_MAX_FW_LINKS (IWL_FW_MAX_LINK_ID + 1)
|
||||
|
||||
/**
|
||||
* struct iwl_system_statistics_notif_oper
|
||||
@@ -608,7 +611,7 @@ struct iwl_system_statistics_notif_oper {
|
||||
__le32 time_stamp;
|
||||
struct iwl_stats_ntfy_per_link per_link[IWL_STATS_MAX_FW_LINKS];
|
||||
struct iwl_stats_ntfy_per_phy per_phy[IWL_STATS_MAX_PHY_OPERATIONAL];
|
||||
struct iwl_stats_ntfy_per_sta per_sta[IWL_MVM_STATION_COUNT_MAX];
|
||||
struct iwl_stats_ntfy_per_sta per_sta[IWL_STATION_COUNT_MAX];
|
||||
} __packed; /* STATISTICS_FW_NTFY_OPERATIONAL_API_S_VER_3 */
|
||||
|
||||
/**
|
||||
@@ -651,7 +654,7 @@ struct iwl_statistics_operational_ntfy {
|
||||
__le32 flags;
|
||||
struct iwl_stats_ntfy_per_mac per_mac[MAC_INDEX_AUX];
|
||||
struct iwl_stats_ntfy_per_phy per_phy[IWL_STATS_MAX_PHY_OPERATIONAL];
|
||||
struct iwl_stats_ntfy_per_sta per_sta[IWL_MVM_STATION_COUNT_MAX];
|
||||
struct iwl_stats_ntfy_per_sta per_sta[IWL_STATION_COUNT_MAX];
|
||||
__le64 rx_time;
|
||||
__le64 tx_time;
|
||||
__le64 on_time_rf;
|
||||
@@ -699,7 +702,7 @@ struct iwl_statistics_operational_ntfy_ver_14 {
|
||||
__le64 tx_time;
|
||||
__le64 on_time_rf;
|
||||
__le64 on_time_scan;
|
||||
__le32 average_energy[IWL_MVM_STATION_COUNT_MAX];
|
||||
__le32 average_energy[IWL_STATION_COUNT_MAX];
|
||||
__le32 reserved;
|
||||
} __packed; /* STATISTICS_OPERATIONAL_NTFY_API_S_VER_14 */
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018, 2024-2025 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
@@ -10,7 +10,7 @@
|
||||
#include "fw/api/tx.h"
|
||||
#include "fw/api/phy-ctxt.h"
|
||||
|
||||
#define IWL_MVM_TDLS_STA_COUNT 4
|
||||
#define IWL_TDLS_STA_COUNT 4
|
||||
|
||||
/* Type of TDLS request */
|
||||
enum iwl_tdls_channel_switch_type {
|
||||
@@ -50,7 +50,7 @@ struct iwl_tdls_channel_switch_timing {
|
||||
*/
|
||||
struct iwl_tdls_channel_switch_frame {
|
||||
__le32 switch_time_offset;
|
||||
struct iwl_tx_cmd tx_cmd;
|
||||
struct iwl_tx_cmd_v6_params tx_cmd;
|
||||
u8 data[IWL_TDLS_CH_SW_FRAME_MAX_SIZE];
|
||||
} __packed; /* TDLS_STA_CHANNEL_SWITCH_FRAME_API_S_VER_1 */
|
||||
|
||||
@@ -128,10 +128,10 @@ struct iwl_tdls_config_cmd {
|
||||
u8 tdls_peer_count;
|
||||
u8 tx_to_ap_tid;
|
||||
__le16 tx_to_ap_ssn;
|
||||
struct iwl_tdls_sta_info sta_info[IWL_MVM_TDLS_STA_COUNT];
|
||||
struct iwl_tdls_sta_info sta_info[IWL_TDLS_STA_COUNT];
|
||||
|
||||
__le32 pti_req_data_offset;
|
||||
struct iwl_tx_cmd pti_req_tx_cmd;
|
||||
struct iwl_tx_cmd_v6_params pti_req_tx_cmd;
|
||||
u8 pti_req_template[];
|
||||
} __packed; /* TDLS_CONFIG_CMD_API_S_VER_1 */
|
||||
|
||||
@@ -155,7 +155,7 @@ struct iwl_tdls_config_sta_info_res {
|
||||
*/
|
||||
struct iwl_tdls_config_res {
|
||||
__le32 tx_to_ap_last_seq;
|
||||
struct iwl_tdls_config_sta_info_res sta_info[IWL_MVM_TDLS_STA_COUNT];
|
||||
struct iwl_tdls_config_sta_info_res sta_info[IWL_TDLS_STA_COUNT];
|
||||
} __packed; /* TDLS_CONFIG_RSP_API_S_VER_1 */
|
||||
|
||||
#endif /* __iwl_fw_api_tdls_h__ */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2020, 2022-2024 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2020, 2022-2025 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
@@ -351,7 +351,7 @@ enum iwl_roc_activity {
|
||||
}; /* ROC_ACTIVITY_API_E_VER_1 */
|
||||
|
||||
/*
|
||||
* ROC command
|
||||
* ROC command v5
|
||||
*
|
||||
* Command requests the firmware to remain on a channel for a certain duration.
|
||||
*
|
||||
@@ -366,7 +366,7 @@ enum iwl_roc_activity {
|
||||
* @max_delay: max delay the ROC can start in TU
|
||||
* @duration: remain on channel duration in TU
|
||||
*/
|
||||
struct iwl_roc_req {
|
||||
struct iwl_roc_req_v5 {
|
||||
__le32 action;
|
||||
__le32 activity;
|
||||
__le32 sta_id;
|
||||
@@ -375,7 +375,41 @@ struct iwl_roc_req {
|
||||
__le16 reserved;
|
||||
__le32 max_delay;
|
||||
__le32 duration;
|
||||
} __packed; /* ROC_CMD_API_S_VER_3 */
|
||||
} __packed; /* ROC_CMD_API_S_VER_5 */
|
||||
|
||||
/*
|
||||
* ROC command
|
||||
*
|
||||
* Command requests the firmware to remain on a channel for a certain duration.
|
||||
*
|
||||
* ( MAC_CONF_GROUP 0x3, ROC_CMD 0xE )
|
||||
*
|
||||
* @action: action to perform, see &enum iwl_ctxt_action
|
||||
* @activity: type of activity, see &enum iwl_roc_activity
|
||||
* @sta_id: station id, resumed during "Remain On Channel" activity.
|
||||
* @channel_info: &struct iwl_fw_channel_info
|
||||
* @node_addr: node MAC address for Rx filtering
|
||||
* @reserved1: align to a dword
|
||||
* @max_delay: max delay the ROC can start in TU
|
||||
* @duration: remain on channel duration in TU
|
||||
* @interval: interval between repetitions (when repetitions > 1).
|
||||
* @repetitions: number of repetitions
|
||||
* 0xFF: infinite repetitions. 0 or 1: single repetition.
|
||||
* @reserved2: align to a dword
|
||||
*/
|
||||
struct iwl_roc_req {
|
||||
__le32 action;
|
||||
__le32 activity;
|
||||
__le32 sta_id;
|
||||
struct iwl_fw_channel_info channel_info;
|
||||
u8 node_addr[ETH_ALEN];
|
||||
__le16 reserved1;
|
||||
__le32 max_delay;
|
||||
__le32 duration;
|
||||
__le32 interval;
|
||||
u8 repetitions;
|
||||
u8 reserved2[3];
|
||||
} __packed; /* ROC_CMD_API_S_VER_6 */
|
||||
|
||||
/*
|
||||
* ROC notification
|
||||
@@ -395,7 +429,7 @@ struct iwl_roc_notif {
|
||||
} __packed; /* ROC_NOTIF_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* enum iwl_mvm_session_prot_conf_id - session protection's configurations
|
||||
* enum iwl_session_prot_conf_id - session protection's configurations
|
||||
* @SESSION_PROTECT_CONF_ASSOC: Start a session protection for association.
|
||||
* The firmware will allocate two events.
|
||||
* Valid for BSS_STA and P2P_STA.
|
||||
@@ -418,13 +452,13 @@ struct iwl_roc_notif {
|
||||
* listen mode. Will be fragmented. Valid only on the P2P Device MAC.
|
||||
* Valid only on the P2P Device MAC. The firmware will take into account
|
||||
* the duration, the interval and the repetition count.
|
||||
* @SESSION_PROTECT_CONF_P2P_GO_NEGOTIATION: Schedule the P2P Device to be be
|
||||
* @SESSION_PROTECT_CONF_P2P_GO_NEGOTIATION: Schedule the P2P Device to be
|
||||
* able to run the GO Negotiation. Will not be fragmented and not
|
||||
* repetitive. Valid only on the P2P Device MAC. Only the duration will
|
||||
* be taken into account.
|
||||
* @SESSION_PROTECT_CONF_MAX_ID: not used
|
||||
*/
|
||||
enum iwl_mvm_session_prot_conf_id {
|
||||
enum iwl_session_prot_conf_id {
|
||||
SESSION_PROTECT_CONF_ASSOC,
|
||||
SESSION_PROTECT_CONF_GO_CLIENT_ASSOC,
|
||||
SESSION_PROTECT_CONF_P2P_DEVICE_DISCOV,
|
||||
@@ -433,12 +467,12 @@ enum iwl_mvm_session_prot_conf_id {
|
||||
}; /* SESSION_PROTECTION_CONF_ID_E_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_mvm_session_prot_cmd - configure a session protection
|
||||
* struct iwl_session_prot_cmd - configure a session protection
|
||||
* @id_and_color: the id and color of the link (or mac, for command version 1)
|
||||
* for which this session protection is sent
|
||||
* @action: can be either FW_CTXT_ACTION_ADD or FW_CTXT_ACTION_REMOVE,
|
||||
* see &enum iwl_ctxt_action
|
||||
* @conf_id: see &enum iwl_mvm_session_prot_conf_id
|
||||
* @conf_id: see &enum iwl_session_prot_conf_id
|
||||
* @duration_tu: the duration of the whole protection in TUs.
|
||||
* @repetition_count: not used
|
||||
* @interval: not used
|
||||
@@ -448,7 +482,7 @@ enum iwl_mvm_session_prot_conf_id {
|
||||
* The firmware supports only one concurrent session protection per vif.
|
||||
* Adding a new session protection will remove any currently running session.
|
||||
*/
|
||||
struct iwl_mvm_session_prot_cmd {
|
||||
struct iwl_session_prot_cmd {
|
||||
/* COMMON_INDEX_HDR_API_S_VER_1 hdr */
|
||||
__le32 id_and_color;
|
||||
__le32 action;
|
||||
@@ -462,17 +496,17 @@ struct iwl_mvm_session_prot_cmd {
|
||||
*/
|
||||
|
||||
/**
|
||||
* struct iwl_mvm_session_prot_notif - session protection started / ended
|
||||
* struct iwl_session_prot_notif - session protection started / ended
|
||||
* @mac_link_id: the mac id (or link id, for notif ver > 2) for which the
|
||||
* session protection started / ended
|
||||
* @status: 1 means success, 0 means failure
|
||||
* @start: 1 means the session protection started, 0 means it ended
|
||||
* @conf_id: see &enum iwl_mvm_session_prot_conf_id
|
||||
* @conf_id: see &enum iwl_session_prot_conf_id
|
||||
*
|
||||
* Note that any session protection will always get two notifications: start
|
||||
* and end even the firmware could not schedule it.
|
||||
*/
|
||||
struct iwl_mvm_session_prot_notif {
|
||||
struct iwl_session_prot_notif {
|
||||
__le32 mac_link_id;
|
||||
__le32 status;
|
||||
__le32 start;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2024 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2025 Intel Corporation
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
#ifndef __iwl_fw_api_tx_h__
|
||||
@@ -151,7 +151,7 @@ enum iwl_tx_cmd_sec_ctrl {
|
||||
#define IWL_LOW_RETRY_LIMIT 7
|
||||
|
||||
/**
|
||||
* enum iwl_tx_offload_assist_flags_pos - set %iwl_tx_cmd offload_assist values
|
||||
* enum iwl_tx_offload_assist_flags_pos - set %iwl_tx_cmd_v6 offload_assist values
|
||||
* @TX_CMD_OFFLD_IP_HDR: offset to start of IP header (in words)
|
||||
* from mac header end. For normal case it is 4 words for SNAP.
|
||||
* note: tx_cmd, mac header and pad are not counted in the offset.
|
||||
@@ -181,8 +181,8 @@ enum iwl_tx_offload_assist_flags_pos {
|
||||
|
||||
/* TODO: complete documentation for try_cnt and btkill_cnt */
|
||||
/**
|
||||
* struct iwl_tx_cmd - TX command struct to FW
|
||||
* ( TX_CMD = 0x1c )
|
||||
* struct iwl_tx_cmd_v6_params - parameters of the TX
|
||||
*
|
||||
* @len: in bytes of the payload, see below for details
|
||||
* @offload_assist: TX offload configuration
|
||||
* @tx_flags: combination of TX_CMD_FLG_*, see &enum iwl_tx_flags
|
||||
@@ -191,7 +191,7 @@ enum iwl_tx_offload_assist_flags_pos {
|
||||
* cleared. Combination of RATE_MCS_*
|
||||
* @sta_id: index of destination station in FW station table
|
||||
* @sec_ctl: security control, TX_CMD_SEC_*
|
||||
* @initial_rate_index: index into the the rate table for initial TX attempt.
|
||||
* @initial_rate_index: index into the rate table for initial TX attempt.
|
||||
* Applied if TX_CMD_FLG_STA_RATE_MSK is set, normally 0 for data frames.
|
||||
* @reserved2: reserved
|
||||
* @key: security key
|
||||
@@ -205,8 +205,6 @@ enum iwl_tx_offload_assist_flags_pos {
|
||||
* @tid_tspec: TID/tspec
|
||||
* @pm_frame_timeout: PM TX frame timeout
|
||||
* @reserved4: reserved
|
||||
* @payload: payload (same as @hdr)
|
||||
* @hdr: 802.11 header (same as @payload)
|
||||
*
|
||||
* The byte count (both len and next_frame_len) includes MAC header
|
||||
* (24/26/30/32 bytes)
|
||||
@@ -217,11 +215,8 @@ enum iwl_tx_offload_assist_flags_pos {
|
||||
* It does not include post-MAC padding, i.e.,
|
||||
* MIC (CCM) 8 bytes, ICV (WEP/TKIP/CKIP) 4 bytes, CRC 4 bytes.
|
||||
* Range of len: 14-2342 bytes.
|
||||
*
|
||||
* After the struct fields the MAC header is placed, plus any padding,
|
||||
* and then the actial payload.
|
||||
*/
|
||||
struct iwl_tx_cmd {
|
||||
struct iwl_tx_cmd_v6_params {
|
||||
__le16 len;
|
||||
__le16 offload_assist;
|
||||
__le32 tx_flags;
|
||||
@@ -245,10 +240,20 @@ struct iwl_tx_cmd {
|
||||
u8 tid_tspec;
|
||||
__le16 pm_frame_timeout;
|
||||
__le16 reserved4;
|
||||
union {
|
||||
DECLARE_FLEX_ARRAY(u8, payload);
|
||||
DECLARE_FLEX_ARRAY(struct ieee80211_hdr, hdr);
|
||||
};
|
||||
} __packed; /* TX_CMD_API_S_VER_6 */
|
||||
|
||||
/**
|
||||
* struct iwl_tx_cmd_v6 - TX command struct to FW
|
||||
* ( TX_CMD = 0x1c )
|
||||
* @params: parameters of the TX, see &struct iwl_tx_cmd_v6_tx_params
|
||||
* @hdr: 802.11 header
|
||||
*
|
||||
* After ¶ms, the MAC header is placed, plus any padding,
|
||||
* and then the actual payload.
|
||||
*/
|
||||
struct iwl_tx_cmd_v6 {
|
||||
struct iwl_tx_cmd_v6_params params;
|
||||
struct ieee80211_hdr hdr[];
|
||||
} __packed; /* TX_CMD_API_S_VER_6 */
|
||||
|
||||
struct iwl_dram_sec_info {
|
||||
@@ -258,7 +263,7 @@ struct iwl_dram_sec_info {
|
||||
} __packed; /* DRAM_SEC_INFO_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_tx_cmd_gen2 - TX command struct to FW for 22000 devices
|
||||
* struct iwl_tx_cmd_v9 - TX command struct to FW for 22000 devices
|
||||
* ( TX_CMD = 0x1c )
|
||||
* @len: in bytes of the payload, see below for details
|
||||
* @offload_assist: TX offload configuration
|
||||
@@ -268,7 +273,7 @@ struct iwl_dram_sec_info {
|
||||
* cleared. Combination of RATE_MCS_*
|
||||
* @hdr: 802.11 header
|
||||
*/
|
||||
struct iwl_tx_cmd_gen2 {
|
||||
struct iwl_tx_cmd_v9 {
|
||||
__le16 len;
|
||||
__le16 offload_assist;
|
||||
__le32 flags;
|
||||
@@ -279,18 +284,18 @@ struct iwl_tx_cmd_gen2 {
|
||||
TX_CMD_API_S_VER_9 */
|
||||
|
||||
/**
|
||||
* struct iwl_tx_cmd_gen3 - TX command struct to FW for AX210+ devices
|
||||
* struct iwl_tx_cmd - TX command struct to FW for AX210+ devices
|
||||
* ( TX_CMD = 0x1c )
|
||||
* @len: in bytes of the payload, see below for details
|
||||
* @flags: combination of &enum iwl_tx_cmd_flags
|
||||
* @offload_assist: TX offload configuration
|
||||
* @dram_info: FW internal DRAM storage
|
||||
* @rate_n_flags: rate for *all* Tx attempts, if TX_CMD_FLG_STA_RATE_MSK is
|
||||
* cleared. Combination of RATE_MCS_*
|
||||
* cleared. Combination of RATE_MCS_*; format depends on version
|
||||
* @reserved: reserved
|
||||
* @hdr: 802.11 header
|
||||
*/
|
||||
struct iwl_tx_cmd_gen3 {
|
||||
struct iwl_tx_cmd {
|
||||
__le16 len;
|
||||
__le16 flags;
|
||||
__le32 offload_assist;
|
||||
@@ -298,8 +303,9 @@ struct iwl_tx_cmd_gen3 {
|
||||
__le32 rate_n_flags;
|
||||
u8 reserved[8];
|
||||
struct ieee80211_hdr hdr[];
|
||||
} __packed; /* TX_CMD_API_S_VER_8,
|
||||
TX_CMD_API_S_VER_10 */
|
||||
} __packed; /* TX_CMD_API_S_VER_10,
|
||||
* TX_CMD_API_S_VER_11
|
||||
*/
|
||||
|
||||
/*
|
||||
* TX response related data
|
||||
@@ -482,11 +488,11 @@ struct agg_tx_status {
|
||||
#define TX_RES_RATE_TABLE_COL_GET(_f) (((_f) & TX_RES_RATE_TABLE_COLOR_MSK) >>\
|
||||
TX_RES_RATE_TABLE_COLOR_POS)
|
||||
|
||||
#define IWL_MVM_TX_RES_GET_TID(_ra_tid) ((_ra_tid) & 0x0f)
|
||||
#define IWL_MVM_TX_RES_GET_RA(_ra_tid) ((_ra_tid) >> 4)
|
||||
#define IWL_TX_RES_GET_TID(_ra_tid) ((_ra_tid) & 0x0f)
|
||||
#define IWL_TX_RES_GET_RA(_ra_tid) ((_ra_tid) >> 4)
|
||||
|
||||
/**
|
||||
* struct iwl_mvm_tx_resp_v3 - notifies that fw is TXing a packet
|
||||
* struct iwl_tx_resp_v3 - notifies that fw is TXing a packet
|
||||
* ( REPLY_TX = 0x1c )
|
||||
* @frame_count: 1 no aggregation, >1 aggregation
|
||||
* @bt_kill_count: num of times blocked by bluetooth (unused for agg)
|
||||
@@ -517,7 +523,7 @@ struct agg_tx_status {
|
||||
* After the array of statuses comes the SSN of the SCD. Look at
|
||||
* %iwl_mvm_get_scd_ssn for more details.
|
||||
*/
|
||||
struct iwl_mvm_tx_resp_v3 {
|
||||
struct iwl_tx_resp_v3 {
|
||||
u8 frame_count;
|
||||
u8 bt_kill_count;
|
||||
u8 failure_rts;
|
||||
@@ -543,14 +549,14 @@ struct iwl_mvm_tx_resp_v3 {
|
||||
} __packed; /* TX_RSP_API_S_VER_3 */
|
||||
|
||||
/**
|
||||
* struct iwl_mvm_tx_resp - notifies that fw is TXing a packet
|
||||
* struct iwl_tx_resp - notifies that fw is TXing a packet
|
||||
* ( REPLY_TX = 0x1c )
|
||||
* @frame_count: 1 no aggregation, >1 aggregation
|
||||
* @bt_kill_count: num of times blocked by bluetooth (unused for agg)
|
||||
* @failure_rts: num of failures due to unsuccessful RTS
|
||||
* @failure_frame: num failures due to no ACK (unused for agg)
|
||||
* @initial_rate: for non-agg: rate of the successful Tx. For agg: rate of the
|
||||
* Tx of all the batch. RATE_MCS_*
|
||||
* Tx of all the batch. RATE_MCS_*; format depends on command version
|
||||
* @wireless_media_time: for non-agg: RTS + CTS + frame tx attempts time + ACK.
|
||||
* for agg: RTS + CTS + aggregation tx time + block-ack time.
|
||||
* in usec.
|
||||
@@ -575,7 +581,7 @@ struct iwl_mvm_tx_resp_v3 {
|
||||
* After the array of statuses comes the SSN of the SCD. Look at
|
||||
* %iwl_mvm_get_scd_ssn for more details.
|
||||
*/
|
||||
struct iwl_mvm_tx_resp {
|
||||
struct iwl_tx_resp {
|
||||
u8 frame_count;
|
||||
u8 bt_kill_count;
|
||||
u8 failure_rts;
|
||||
@@ -601,7 +607,10 @@ struct iwl_mvm_tx_resp {
|
||||
__le16 reserved2;
|
||||
struct agg_tx_status status;
|
||||
} __packed; /* TX_RSP_API_S_VER_6,
|
||||
TX_RSP_API_S_VER_7 */
|
||||
* TX_RSP_API_S_VER_7,
|
||||
* TX_RSP_API_S_VER_8,
|
||||
* TX_RSP_API_S_VER_9
|
||||
*/
|
||||
|
||||
/**
|
||||
* struct iwl_mvm_ba_notif - notifies about reception of BA
|
||||
@@ -638,14 +647,14 @@ struct iwl_mvm_ba_notif {
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_mvm_compressed_ba_tfd - progress of a TFD queue
|
||||
* struct iwl_compressed_ba_tfd - progress of a TFD queue
|
||||
* @q_num: TFD queue number
|
||||
* @tfd_index: Index of first un-acked frame in the TFD queue
|
||||
* @scd_queue: For debug only - the physical queue the TFD queue is bound to
|
||||
* @tid: TID of the queue (0-7)
|
||||
* @reserved: reserved for alignment
|
||||
*/
|
||||
struct iwl_mvm_compressed_ba_tfd {
|
||||
struct iwl_compressed_ba_tfd {
|
||||
__le16 q_num;
|
||||
__le16 tfd_index;
|
||||
u8 scd_queue;
|
||||
@@ -654,12 +663,12 @@ struct iwl_mvm_compressed_ba_tfd {
|
||||
} __packed; /* COMPRESSED_BA_TFD_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_mvm_compressed_ba_ratid - progress of a RA TID queue
|
||||
* struct iwl_compressed_ba_ratid - progress of a RA TID queue
|
||||
* @q_num: RA TID queue number
|
||||
* @tid: TID of the queue
|
||||
* @ssn: BA window current SSN
|
||||
*/
|
||||
struct iwl_mvm_compressed_ba_ratid {
|
||||
struct iwl_compressed_ba_ratid {
|
||||
u8 q_num;
|
||||
u8 tid;
|
||||
__le16 ssn;
|
||||
@@ -685,7 +694,7 @@ enum iwl_mvm_ba_resp_flags {
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_mvm_compressed_ba_notif - notifies about reception of BA
|
||||
* struct iwl_compressed_ba_notif - notifies about reception of BA
|
||||
* ( BA_NOTIF = 0xc5 )
|
||||
* @flags: status flag, see the &iwl_mvm_ba_resp_flags
|
||||
* @sta_id: Index of recipient (BA-sending) station in fw's station table
|
||||
@@ -701,15 +710,16 @@ enum iwl_mvm_ba_resp_flags {
|
||||
* @rts_retry_cnt: RTS retry count
|
||||
* @reserved: reserved (for alignment)
|
||||
* @wireless_time: Wireless-media time
|
||||
* @tx_rate: the rate the aggregation was sent at
|
||||
* @tx_rate: the rate the aggregation was sent at. Format depends on command
|
||||
* version.
|
||||
* @tfd_cnt: number of TFD-Q elements
|
||||
* @ra_tid_cnt: number of RATID-Q elements
|
||||
* @tfd: array of TFD queue status updates. See &iwl_mvm_compressed_ba_tfd
|
||||
* @tfd: array of TFD queue status updates. See &iwl_compressed_ba_tfd
|
||||
* for details. Length in @tfd_cnt.
|
||||
* @ra_tid: array of RA-TID queue status updates. For debug purposes only. See
|
||||
* &iwl_mvm_compressed_ba_ratid for more details. Length in @ra_tid_cnt.
|
||||
* &iwl_compressed_ba_ratid for more details. Length in @ra_tid_cnt.
|
||||
*/
|
||||
struct iwl_mvm_compressed_ba_notif {
|
||||
struct iwl_compressed_ba_notif {
|
||||
__le32 flags;
|
||||
u8 sta_id;
|
||||
u8 reduced_txp;
|
||||
@@ -726,11 +736,12 @@ struct iwl_mvm_compressed_ba_notif {
|
||||
__le16 tfd_cnt;
|
||||
__le16 ra_tid_cnt;
|
||||
union {
|
||||
DECLARE_FLEX_ARRAY(struct iwl_mvm_compressed_ba_ratid, ra_tid);
|
||||
DECLARE_FLEX_ARRAY(struct iwl_mvm_compressed_ba_tfd, tfd);
|
||||
DECLARE_FLEX_ARRAY(struct iwl_compressed_ba_ratid, ra_tid);
|
||||
DECLARE_FLEX_ARRAY(struct iwl_compressed_ba_tfd, tfd);
|
||||
};
|
||||
} __packed; /* COMPRESSED_BA_RES_API_S_VER_4,
|
||||
COMPRESSED_BA_RES_API_S_VER_5 */
|
||||
COMPRESSED_BA_RES_API_S_VER_6,
|
||||
COMPRESSED_BA_RES_API_S_VER_7 */
|
||||
|
||||
/**
|
||||
* struct iwl_mac_beacon_cmd_v6 - beacon template command
|
||||
@@ -742,7 +753,7 @@ struct iwl_mvm_compressed_ba_notif {
|
||||
* @frame: the template of the beacon frame
|
||||
*/
|
||||
struct iwl_mac_beacon_cmd_v6 {
|
||||
struct iwl_tx_cmd tx;
|
||||
struct iwl_tx_cmd_v6_params tx;
|
||||
__le32 template_id;
|
||||
__le32 tim_idx;
|
||||
__le32 tim_size;
|
||||
@@ -761,7 +772,7 @@ struct iwl_mac_beacon_cmd_v6 {
|
||||
* @frame: the template of the beacon frame
|
||||
*/
|
||||
struct iwl_mac_beacon_cmd_v7 {
|
||||
struct iwl_tx_cmd tx;
|
||||
struct iwl_tx_cmd_v6_params tx;
|
||||
__le32 template_id;
|
||||
__le32 tim_idx;
|
||||
__le32 tim_size;
|
||||
@@ -823,7 +834,7 @@ struct iwl_mac_beacon_cmd {
|
||||
*/
|
||||
|
||||
struct iwl_beacon_notif {
|
||||
struct iwl_mvm_tx_resp beacon_notify_hdr;
|
||||
struct iwl_tx_resp beacon_notify_hdr;
|
||||
__le64 tsf;
|
||||
__le32 ibss_mgr_status;
|
||||
} __packed;
|
||||
@@ -836,7 +847,7 @@ struct iwl_beacon_notif {
|
||||
* @gp2: last beacon time in gp2
|
||||
*/
|
||||
struct iwl_extended_beacon_notif_v5 {
|
||||
struct iwl_mvm_tx_resp beacon_notify_hdr;
|
||||
struct iwl_tx_resp beacon_notify_hdr;
|
||||
__le64 tsf;
|
||||
__le32 ibss_mgr_status;
|
||||
__le32 gp2;
|
||||
@@ -858,7 +869,7 @@ struct iwl_extended_beacon_notif {
|
||||
|
||||
/**
|
||||
* enum iwl_dump_control - dump (flush) control flags
|
||||
* @DUMP_TX_FIFO_FLUSH: Dump MSDUs until the the FIFO is empty
|
||||
* @DUMP_TX_FIFO_FLUSH: Dump MSDUs until the FIFO is empty
|
||||
* and the TFD queues are empty.
|
||||
*/
|
||||
enum iwl_dump_control {
|
||||
|
||||
+224
-126
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2005-2014, 2018-2024 Intel Corporation
|
||||
* Copyright (C) 2005-2014, 2018-2025 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2015-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
@@ -190,7 +190,7 @@ static void iwl_fw_dump_rxf(struct iwl_fw_runtime *fwrt,
|
||||
/* Pull RXF2 */
|
||||
iwl_fwrt_dump_rxf(fwrt, dump_data, cfg->rxfifo2_size,
|
||||
RXF_DIFF_FROM_PREV +
|
||||
fwrt->trans->trans_cfg->umac_prph_offset, 1);
|
||||
fwrt->trans->mac_cfg->umac_prph_offset, 1);
|
||||
/* Pull LMAC2 RXF1 */
|
||||
if (fwrt->smem_cfg.num_lmacs > 1)
|
||||
iwl_fwrt_dump_rxf(fwrt, dump_data,
|
||||
@@ -561,41 +561,71 @@ static void iwl_dump_prph(struct iwl_fw_runtime *fwrt,
|
||||
}
|
||||
|
||||
/*
|
||||
* alloc_sgtable - allocates scallerlist table in the given size,
|
||||
* fills it with pages and returns it
|
||||
* alloc_sgtable - allocates (chained) scatterlist in the given size,
|
||||
* fills it with pages and returns it
|
||||
* @size: the size (in bytes) of the table
|
||||
*/
|
||||
static struct scatterlist *alloc_sgtable(int size)
|
||||
*/
|
||||
static struct scatterlist *alloc_sgtable(ssize_t size)
|
||||
{
|
||||
int alloc_size, nents, i;
|
||||
struct page *new_page;
|
||||
struct scatterlist *iter;
|
||||
struct scatterlist *table;
|
||||
struct scatterlist *result = NULL, *prev;
|
||||
int nents, i, n_prev;
|
||||
|
||||
nents = DIV_ROUND_UP(size, PAGE_SIZE);
|
||||
table = kcalloc(nents, sizeof(*table), GFP_KERNEL);
|
||||
if (!table)
|
||||
return NULL;
|
||||
sg_init_table(table, nents);
|
||||
iter = table;
|
||||
for_each_sg(table, iter, sg_nents(table), i) {
|
||||
new_page = alloc_page(GFP_KERNEL);
|
||||
if (!new_page) {
|
||||
/* release all previous allocated pages in the table */
|
||||
iter = table;
|
||||
for_each_sg(table, iter, sg_nents(table), i) {
|
||||
new_page = sg_page(iter);
|
||||
if (new_page)
|
||||
__free_page(new_page);
|
||||
}
|
||||
kfree(table);
|
||||
|
||||
#define N_ENTRIES_PER_PAGE (PAGE_SIZE / sizeof(*result))
|
||||
/*
|
||||
* We need an additional entry for table chaining,
|
||||
* this ensures the loop can finish i.e. we can
|
||||
* fit at least two entries per page (obviously,
|
||||
* many more really fit.)
|
||||
*/
|
||||
BUILD_BUG_ON(N_ENTRIES_PER_PAGE < 2);
|
||||
|
||||
while (nents > 0) {
|
||||
struct scatterlist *new, *iter;
|
||||
int n_fill, n_alloc;
|
||||
|
||||
if (nents <= N_ENTRIES_PER_PAGE) {
|
||||
/* last needed table */
|
||||
n_fill = nents;
|
||||
n_alloc = nents;
|
||||
nents = 0;
|
||||
} else {
|
||||
/* fill a page with entries */
|
||||
n_alloc = N_ENTRIES_PER_PAGE;
|
||||
/* reserve one for chaining */
|
||||
n_fill = n_alloc - 1;
|
||||
nents -= n_fill;
|
||||
}
|
||||
|
||||
new = kcalloc(n_alloc, sizeof(*new), GFP_KERNEL);
|
||||
if (!new) {
|
||||
if (result)
|
||||
_devcd_free_sgtable(result);
|
||||
return NULL;
|
||||
}
|
||||
alloc_size = min_t(int, size, PAGE_SIZE);
|
||||
size -= PAGE_SIZE;
|
||||
sg_set_page(iter, new_page, alloc_size, 0);
|
||||
sg_init_table(new, n_alloc);
|
||||
|
||||
if (!result)
|
||||
result = new;
|
||||
else
|
||||
sg_chain(prev, n_prev, new);
|
||||
prev = new;
|
||||
n_prev = n_alloc;
|
||||
|
||||
for_each_sg(new, iter, n_fill, i) {
|
||||
struct page *new_page = alloc_page(GFP_KERNEL);
|
||||
|
||||
if (!new_page) {
|
||||
_devcd_free_sgtable(result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sg_set_page(iter, new_page, PAGE_SIZE, 0);
|
||||
}
|
||||
}
|
||||
return table;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void iwl_fw_get_prph_len(struct iwl_fw_runtime *fwrt,
|
||||
@@ -627,10 +657,10 @@ static void iwl_fw_prph_handler(struct iwl_fw_runtime *fwrt, void *ptr,
|
||||
{
|
||||
u32 range_len;
|
||||
|
||||
if (fwrt->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
|
||||
if (fwrt->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
|
||||
range_len = ARRAY_SIZE(iwl_prph_dump_addr_ax210);
|
||||
handler(fwrt, iwl_prph_dump_addr_ax210, range_len, ptr);
|
||||
} else if (fwrt->trans->trans_cfg->device_family >=
|
||||
} else if (fwrt->trans->mac_cfg->device_family >=
|
||||
IWL_DEVICE_FAMILY_22000) {
|
||||
range_len = ARRAY_SIZE(iwl_prph_dump_addr_22000);
|
||||
handler(fwrt, iwl_prph_dump_addr_22000, range_len, ptr);
|
||||
@@ -638,7 +668,7 @@ static void iwl_fw_prph_handler(struct iwl_fw_runtime *fwrt, void *ptr,
|
||||
range_len = ARRAY_SIZE(iwl_prph_dump_addr_comm);
|
||||
handler(fwrt, iwl_prph_dump_addr_comm, range_len, ptr);
|
||||
|
||||
if (fwrt->trans->trans_cfg->mq_rx_supported) {
|
||||
if (fwrt->trans->mac_cfg->mq_rx_supported) {
|
||||
range_len = ARRAY_SIZE(iwl_prph_dump_addr_9000);
|
||||
handler(fwrt, iwl_prph_dump_addr_9000, range_len, ptr);
|
||||
}
|
||||
@@ -782,13 +812,14 @@ iwl_fw_error_dump_file(struct iwl_fw_runtime *fwrt,
|
||||
const struct iwl_fw_dbg_mem_seg_tlv *fw_mem = fwrt->fw->dbg.mem_tlv;
|
||||
struct iwl_fwrt_shared_mem_cfg *mem_cfg = &fwrt->smem_cfg;
|
||||
u32 file_len, fifo_len = 0, prph_len = 0, radio_len = 0;
|
||||
u32 smem_len = fwrt->fw->dbg.n_mem_tlv ? 0 : fwrt->trans->cfg->smem_len;
|
||||
u32 smem_len = fwrt->fw->dbg.n_mem_tlv ? 0 : fwrt->trans->mac_cfg->base->smem_len;
|
||||
u32 sram2_len = fwrt->fw->dbg.n_mem_tlv ?
|
||||
0 : fwrt->trans->cfg->dccm2_len;
|
||||
int i;
|
||||
|
||||
/* SRAM - include stack CCM if driver knows the values for it */
|
||||
if (!fwrt->trans->cfg->dccm_offset || !fwrt->trans->cfg->dccm_len) {
|
||||
if (!fwrt->trans->cfg->dccm_offset ||
|
||||
!fwrt->trans->cfg->dccm_len) {
|
||||
const struct fw_img *img;
|
||||
|
||||
if (fwrt->cur_fw_img >= IWL_UCODE_TYPE_MAX)
|
||||
@@ -811,7 +842,7 @@ iwl_fw_error_dump_file(struct iwl_fw_runtime *fwrt,
|
||||
iwl_fw_prph_handler(fwrt, &prph_len,
|
||||
iwl_fw_get_prph_len);
|
||||
|
||||
if (fwrt->trans->trans_cfg->device_family ==
|
||||
if (fwrt->trans->mac_cfg->device_family ==
|
||||
IWL_DEVICE_FAMILY_7000 &&
|
||||
iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_RADIO_REG))
|
||||
radio_len = sizeof(*dump_data) + RADIO_REG_MAX_READ;
|
||||
@@ -849,7 +880,7 @@ iwl_fw_error_dump_file(struct iwl_fw_runtime *fwrt,
|
||||
|
||||
if (iwl_fw_dbg_is_d3_debug_enabled(fwrt) && fwrt->dump.d3_debug_data) {
|
||||
file_len += sizeof(*dump_data) +
|
||||
fwrt->trans->cfg->d3_debug_data_length * 2;
|
||||
fwrt->trans->mac_cfg->base->d3_debug_data_length * 2;
|
||||
}
|
||||
|
||||
/* If we only want a monitor dump, reset the file length */
|
||||
@@ -877,13 +908,14 @@ iwl_fw_error_dump_file(struct iwl_fw_runtime *fwrt,
|
||||
dump_data->len = cpu_to_le32(sizeof(*dump_info));
|
||||
dump_info = (void *)dump_data->data;
|
||||
dump_info->hw_type =
|
||||
cpu_to_le32(CSR_HW_REV_TYPE(fwrt->trans->hw_rev));
|
||||
cpu_to_le32(CSR_HW_REV_TYPE(fwrt->trans->info.hw_rev));
|
||||
dump_info->hw_step =
|
||||
cpu_to_le32(fwrt->trans->hw_rev_step);
|
||||
cpu_to_le32(fwrt->trans->info.hw_rev_step);
|
||||
memcpy(dump_info->fw_human_readable, fwrt->fw->human_readable,
|
||||
sizeof(dump_info->fw_human_readable));
|
||||
strscpy_pad(dump_info->dev_human_readable, fwrt->trans->name,
|
||||
sizeof(dump_info->dev_human_readable));
|
||||
strscpy_pad(dump_info->dev_human_readable,
|
||||
fwrt->trans->info.name,
|
||||
sizeof(dump_info->dev_human_readable));
|
||||
#if defined(__linux__)
|
||||
strscpy_pad(dump_info->bus_human_readable, fwrt->dev->bus->name,
|
||||
sizeof(dump_info->bus_human_readable));
|
||||
@@ -974,7 +1006,7 @@ iwl_fw_error_dump_file(struct iwl_fw_runtime *fwrt,
|
||||
}
|
||||
|
||||
iwl_fw_dump_mem(fwrt, &dump_data, smem_len,
|
||||
fwrt->trans->cfg->smem_offset,
|
||||
fwrt->trans->mac_cfg->base->smem_offset,
|
||||
IWL_FW_ERROR_DUMP_MEM_SMEM);
|
||||
|
||||
iwl_fw_dump_mem(fwrt, &dump_data, sram2_len,
|
||||
@@ -983,8 +1015,8 @@ iwl_fw_error_dump_file(struct iwl_fw_runtime *fwrt,
|
||||
}
|
||||
|
||||
if (iwl_fw_dbg_is_d3_debug_enabled(fwrt) && fwrt->dump.d3_debug_data) {
|
||||
u32 addr = fwrt->trans->cfg->d3_debug_data_base_addr;
|
||||
size_t data_size = fwrt->trans->cfg->d3_debug_data_length;
|
||||
u32 addr = fwrt->trans->mac_cfg->base->d3_debug_data_base_addr;
|
||||
size_t data_size = fwrt->trans->mac_cfg->base->d3_debug_data_length;
|
||||
|
||||
dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_D3_DEBUG_DATA);
|
||||
dump_data->len = cpu_to_le32(data_size * 2);
|
||||
@@ -1082,12 +1114,13 @@ static int iwl_dump_ini_prph_phy_iter_common(struct iwl_fw_runtime *fwrt,
|
||||
u32 prph_val;
|
||||
u32 dphy_state;
|
||||
u32 dphy_addr;
|
||||
u32 prph_stts;
|
||||
int i;
|
||||
|
||||
range->internal_base_addr = cpu_to_le32(addr);
|
||||
range->range_data_size = size;
|
||||
|
||||
if (fwrt->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
|
||||
if (fwrt->trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
|
||||
indirect_wr_addr = WMAL_INDRCT_CMD1;
|
||||
|
||||
indirect_wr_addr += le32_to_cpu(offset);
|
||||
@@ -1109,6 +1142,21 @@ static int iwl_dump_ini_prph_phy_iter_common(struct iwl_fw_runtime *fwrt,
|
||||
|
||||
iwl_write_prph_no_grab(fwrt->trans, indirect_wr_addr,
|
||||
WMAL_INDRCT_CMD(addr + i));
|
||||
|
||||
if (fwrt->trans->info.hw_rf_id != IWL_CFG_RF_TYPE_JF1 &&
|
||||
fwrt->trans->info.hw_rf_id != IWL_CFG_RF_TYPE_JF2 &&
|
||||
fwrt->trans->info.hw_rf_id != IWL_CFG_RF_TYPE_HR1 &&
|
||||
fwrt->trans->info.hw_rf_id != IWL_CFG_RF_TYPE_HR2) {
|
||||
udelay(2);
|
||||
prph_stts = iwl_read_prph_no_grab(fwrt->trans,
|
||||
WMAL_MRSPF_STTS);
|
||||
|
||||
/* Abort dump if status is 0xA5A5A5A2 or FIFO1 empty */
|
||||
if (prph_stts == WMAL_TIMEOUT_VAL ||
|
||||
!WMAL_MRSPF_STTS_IS_FIFO1_NOT_EMPTY(prph_stts))
|
||||
break;
|
||||
}
|
||||
|
||||
prph_val = iwl_read_prph_no_grab(fwrt->trans,
|
||||
indirect_rd_addr);
|
||||
*val++ = cpu_to_le32(prph_val);
|
||||
@@ -1244,7 +1292,7 @@ static int iwl_dump_ini_paging_iter(struct iwl_fw_runtime *fwrt,
|
||||
/* all paged index start from 1 to skip CSS section */
|
||||
idx++;
|
||||
|
||||
if (!fwrt->trans->trans_cfg->gen2)
|
||||
if (!fwrt->trans->mac_cfg->gen2)
|
||||
return _iwl_dump_ini_paging_iter(fwrt, range_ptr, range_len, idx);
|
||||
|
||||
range = range_ptr;
|
||||
@@ -1771,7 +1819,7 @@ iwl_dump_ini_mon_fill_header(struct iwl_fw_runtime *fwrt, u32 alloc_id,
|
||||
|
||||
data->write_ptr = iwl_get_mon_reg(fwrt, alloc_id,
|
||||
&addrs->write_ptr);
|
||||
if (fwrt->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
|
||||
if (fwrt->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
|
||||
u32 wrt_ptr = le32_to_cpu(data->write_ptr);
|
||||
|
||||
data->write_ptr = cpu_to_le32(wrt_ptr >> 2);
|
||||
@@ -1798,7 +1846,7 @@ iwl_dump_ini_mon_dram_fill_header(struct iwl_fw_runtime *fwrt,
|
||||
u32 alloc_id = le32_to_cpu(reg->dram_alloc_id);
|
||||
|
||||
return iwl_dump_ini_mon_fill_header(fwrt, alloc_id, mon_dump,
|
||||
&fwrt->trans->cfg->mon_dram_regs);
|
||||
&fwrt->trans->mac_cfg->base->mon_dram_regs);
|
||||
}
|
||||
|
||||
static void *
|
||||
@@ -1811,7 +1859,7 @@ iwl_dump_ini_mon_smem_fill_header(struct iwl_fw_runtime *fwrt,
|
||||
u32 alloc_id = le32_to_cpu(reg->internal_buffer.alloc_id);
|
||||
|
||||
return iwl_dump_ini_mon_fill_header(fwrt, alloc_id, mon_dump,
|
||||
&fwrt->trans->cfg->mon_smem_regs);
|
||||
&fwrt->trans->mac_cfg->base->mon_smem_regs);
|
||||
}
|
||||
|
||||
static void *
|
||||
@@ -1825,7 +1873,7 @@ iwl_dump_ini_mon_dbgi_fill_header(struct iwl_fw_runtime *fwrt,
|
||||
/* no offset calculation later */
|
||||
IWL_FW_INI_ALLOCATION_ID_DBGC1,
|
||||
mon_dump,
|
||||
&fwrt->trans->cfg->mon_dbgi_regs);
|
||||
&fwrt->trans->mac_cfg->base->mon_dbgi_regs);
|
||||
}
|
||||
|
||||
static void *
|
||||
@@ -1890,7 +1938,7 @@ iwl_dump_ini_mem_block_ranges(struct iwl_fw_runtime *fwrt,
|
||||
static u32 iwl_dump_ini_paging_ranges(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_dump_ini_region_data *reg_data)
|
||||
{
|
||||
if (fwrt->trans->trans_cfg->gen2) {
|
||||
if (fwrt->trans->mac_cfg->gen2) {
|
||||
if (fwrt->trans->init_dram.paging_cnt)
|
||||
return fwrt->trans->init_dram.paging_cnt - 1;
|
||||
else
|
||||
@@ -2002,7 +2050,7 @@ iwl_dump_ini_paging_get_size(struct iwl_fw_runtime *fwrt,
|
||||
/* start from 1 to skip CSS section */
|
||||
for (i = 1; i <= iwl_dump_ini_paging_ranges(fwrt, reg_data); i++) {
|
||||
size += range_header_len;
|
||||
if (fwrt->trans->trans_cfg->gen2)
|
||||
if (fwrt->trans->mac_cfg->gen2)
|
||||
size += fwrt->trans->init_dram.paging[i].size;
|
||||
else
|
||||
size += fwrt->fw_paging_db[i].fw_paging_size;
|
||||
@@ -2364,7 +2412,7 @@ static u32 iwl_dump_ini_info(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_fw_ini_dump_cfg_name *cfg_name;
|
||||
u32 size = sizeof(*tlv) + sizeof(*dump);
|
||||
u32 num_of_cfg_names = 0;
|
||||
u32 hw_type;
|
||||
u32 hw_type, is_cdb, is_jacket;
|
||||
|
||||
list_for_each_entry(node, &fwrt->trans->dbg.debug_info_tlv_list, list) {
|
||||
size += sizeof(*cfg_name);
|
||||
@@ -2392,33 +2440,24 @@ static u32 iwl_dump_ini_info(struct iwl_fw_runtime *fwrt,
|
||||
dump->ver_type = cpu_to_le32(fwrt->dump.fw_ver.type);
|
||||
dump->ver_subtype = cpu_to_le32(fwrt->dump.fw_ver.subtype);
|
||||
|
||||
dump->hw_step = cpu_to_le32(fwrt->trans->hw_rev_step);
|
||||
dump->hw_step = cpu_to_le32(fwrt->trans->info.hw_rev_step);
|
||||
|
||||
/*
|
||||
* Several HWs all have type == 0x42, so we'll override this value
|
||||
* according to the detected HW
|
||||
*/
|
||||
hw_type = CSR_HW_REV_TYPE(fwrt->trans->hw_rev);
|
||||
if (hw_type == IWL_AX210_HW_TYPE) {
|
||||
u32 prph_val = iwl_read_umac_prph(fwrt->trans, WFPM_OTP_CFG1_ADDR);
|
||||
u32 is_jacket = !!(prph_val & WFPM_OTP_CFG1_IS_JACKET_BIT);
|
||||
u32 is_cdb = !!(prph_val & WFPM_OTP_CFG1_IS_CDB_BIT);
|
||||
u32 masked_bits = is_jacket | (is_cdb << 1);
|
||||
hw_type = CSR_HW_REV_TYPE(fwrt->trans->info.hw_rev);
|
||||
|
||||
is_cdb = CSR_HW_RFID_IS_CDB(fwrt->trans->info.hw_rf_id);
|
||||
is_jacket = !!(iwl_read_umac_prph(fwrt->trans, WFPM_OTP_CFG1_ADDR) &
|
||||
WFPM_OTP_CFG1_IS_JACKET_BIT);
|
||||
|
||||
/* Use bits 12 and 13 to indicate jacket/CDB, respectively */
|
||||
hw_type |= (is_jacket | (is_cdb << 1)) << IWL_JACKET_CDB_SHIFT;
|
||||
|
||||
/*
|
||||
* The HW type depends on certain bits in this case, so add
|
||||
* these bits to the HW type. We won't have collisions since we
|
||||
* add these bits after the highest possible bit in the mask.
|
||||
*/
|
||||
hw_type |= masked_bits << IWL_AX210_HW_TYPE_ADDITION_SHIFT;
|
||||
}
|
||||
dump->hw_type = cpu_to_le32(hw_type);
|
||||
|
||||
dump->rf_id_flavor =
|
||||
cpu_to_le32(CSR_HW_RFID_FLAVOR(fwrt->trans->hw_rf_id));
|
||||
dump->rf_id_dash = cpu_to_le32(CSR_HW_RFID_DASH(fwrt->trans->hw_rf_id));
|
||||
dump->rf_id_step = cpu_to_le32(CSR_HW_RFID_STEP(fwrt->trans->hw_rf_id));
|
||||
dump->rf_id_type = cpu_to_le32(CSR_HW_RFID_TYPE(fwrt->trans->hw_rf_id));
|
||||
cpu_to_le32(CSR_HW_RFID_FLAVOR(fwrt->trans->info.hw_rf_id));
|
||||
dump->rf_id_dash = cpu_to_le32(CSR_HW_RFID_DASH(fwrt->trans->info.hw_rf_id));
|
||||
dump->rf_id_step = cpu_to_le32(CSR_HW_RFID_STEP(fwrt->trans->info.hw_rf_id));
|
||||
dump->rf_id_type = cpu_to_le32(CSR_HW_RFID_TYPE(fwrt->trans->info.hw_rf_id));
|
||||
|
||||
dump->lmac_major = cpu_to_le32(fwrt->dump.fw_ver.lmac_major);
|
||||
dump->lmac_minor = cpu_to_le32(fwrt->dump.fw_ver.lmac_minor);
|
||||
@@ -2607,29 +2646,34 @@ static const struct iwl_dump_ini_mem_ops iwl_dump_ini_region_ops[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static u32 iwl_dump_ini_trigger(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_fwrt_dump_data *dump_data,
|
||||
struct list_head *list)
|
||||
enum iwl_dump_ini_region_selector {
|
||||
IWL_INI_DUMP_ALL_REGIONS,
|
||||
IWL_INI_DUMP_EARLY_REGIONS,
|
||||
IWL_INI_DUMP_LATE_REGIONS,
|
||||
};
|
||||
|
||||
static bool iwl_dump_due_to_error(enum iwl_fw_ini_time_point tp_id)
|
||||
{
|
||||
return tp_id == IWL_FW_INI_TIME_POINT_FW_ASSERT ||
|
||||
tp_id == IWL_FW_INI_TIME_POINT_FW_HW_ERROR;
|
||||
}
|
||||
|
||||
static u32
|
||||
iwl_dump_ini_dump_regions(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_fwrt_dump_data *dump_data,
|
||||
struct list_head *list,
|
||||
enum iwl_fw_ini_time_point tp_id,
|
||||
u64 regions_mask,
|
||||
struct iwl_dump_ini_region_data *imr_reg_data,
|
||||
enum iwl_dump_ini_region_selector which)
|
||||
{
|
||||
struct iwl_fw_ini_trigger_tlv *trigger = dump_data->trig;
|
||||
enum iwl_fw_ini_time_point tp_id = le32_to_cpu(trigger->time_point);
|
||||
struct iwl_dump_ini_region_data reg_data = {
|
||||
.dump_data = dump_data,
|
||||
};
|
||||
struct iwl_dump_ini_region_data imr_reg_data = {
|
||||
.dump_data = dump_data,
|
||||
};
|
||||
int i;
|
||||
u32 size = 0;
|
||||
u64 regions_mask = le64_to_cpu(trigger->regions_mask) &
|
||||
~(fwrt->trans->dbg.unsupported_region_msk);
|
||||
|
||||
BUILD_BUG_ON(sizeof(trigger->regions_mask) != sizeof(regions_mask));
|
||||
BUILD_BUG_ON((sizeof(trigger->regions_mask) * BITS_PER_BYTE) <
|
||||
ARRAY_SIZE(fwrt->trans->dbg.active_regions));
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(fwrt->trans->dbg.active_regions); i++) {
|
||||
u32 reg_type;
|
||||
for (int i = 0; i < ARRAY_SIZE(fwrt->trans->dbg.active_regions); i++) {
|
||||
struct iwl_dump_ini_region_data reg_data = {
|
||||
.dump_data = dump_data,
|
||||
};
|
||||
u32 reg_type, dp;
|
||||
struct iwl_fw_ini_region_tlv *reg;
|
||||
|
||||
if (!(BIT_ULL(i) & regions_mask))
|
||||
@@ -2647,6 +2691,8 @@ static u32 iwl_dump_ini_trigger(struct iwl_fw_runtime *fwrt,
|
||||
if (reg_type >= ARRAY_SIZE(iwl_dump_ini_region_ops))
|
||||
continue;
|
||||
|
||||
dp = le32_get_bits(reg->id, IWL_FW_INI_REGION_DUMP_POLICY_MASK);
|
||||
|
||||
if ((reg_type == IWL_FW_INI_REGION_PERIPHERY_PHY ||
|
||||
reg_type == IWL_FW_INI_REGION_PERIPHERY_PHY_RANGE ||
|
||||
reg_type == IWL_FW_INI_REGION_PERIPHERY_SNPS_DPHYIP) &&
|
||||
@@ -2656,6 +2702,20 @@ static u32 iwl_dump_ini_trigger(struct iwl_fw_runtime *fwrt,
|
||||
tp_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (which) {
|
||||
case IWL_INI_DUMP_ALL_REGIONS:
|
||||
break;
|
||||
case IWL_INI_DUMP_EARLY_REGIONS:
|
||||
if (!(dp & IWL_FW_IWL_DEBUG_DUMP_POLICY_BEFORE_RESET))
|
||||
continue;
|
||||
break;
|
||||
case IWL_INI_DUMP_LATE_REGIONS:
|
||||
if (dp & IWL_FW_IWL_DEBUG_DUMP_POLICY_BEFORE_RESET)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* DRAM_IMR can be collected only for FW/HW error timepoint
|
||||
* when fw is not alive. In addition, it must be collected
|
||||
@@ -2663,9 +2723,9 @@ static u32 iwl_dump_ini_trigger(struct iwl_fw_runtime *fwrt,
|
||||
* debug data which also need to be collected.
|
||||
*/
|
||||
if (reg_type == IWL_FW_INI_REGION_DRAM_IMR) {
|
||||
if (tp_id == IWL_FW_INI_TIME_POINT_FW_ASSERT ||
|
||||
tp_id == IWL_FW_INI_TIME_POINT_FW_HW_ERROR)
|
||||
imr_reg_data.reg_tlv = fwrt->trans->dbg.active_regions[i];
|
||||
if (iwl_dump_due_to_error(tp_id))
|
||||
imr_reg_data->reg_tlv =
|
||||
fwrt->trans->dbg.active_regions[i];
|
||||
else
|
||||
IWL_INFO(fwrt,
|
||||
"WRT: trying to collect DRAM_IMR at time point: %d, skipping\n",
|
||||
@@ -2678,9 +2738,48 @@ static u32 iwl_dump_ini_trigger(struct iwl_fw_runtime *fwrt,
|
||||
size += iwl_dump_ini_mem(fwrt, list, ®_data,
|
||||
&iwl_dump_ini_region_ops[reg_type]);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static u32 iwl_dump_ini_trigger(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_fwrt_dump_data *dump_data,
|
||||
struct list_head *list)
|
||||
{
|
||||
struct iwl_fw_ini_trigger_tlv *trigger = dump_data->trig;
|
||||
enum iwl_fw_ini_time_point tp_id = le32_to_cpu(trigger->time_point);
|
||||
struct iwl_dump_ini_region_data imr_reg_data = {
|
||||
.dump_data = dump_data,
|
||||
};
|
||||
u32 size = 0;
|
||||
u64 regions_mask = le64_to_cpu(trigger->regions_mask) &
|
||||
~(fwrt->trans->dbg.unsupported_region_msk);
|
||||
|
||||
BUILD_BUG_ON(sizeof(trigger->regions_mask) != sizeof(regions_mask));
|
||||
BUILD_BUG_ON((sizeof(trigger->regions_mask) * BITS_PER_BYTE) <
|
||||
ARRAY_SIZE(fwrt->trans->dbg.active_regions));
|
||||
|
||||
if (trigger->apply_policy &
|
||||
cpu_to_le32(IWL_FW_INI_APPLY_POLICY_SPLIT_DUMP_RESET)) {
|
||||
size += iwl_dump_ini_dump_regions(fwrt, dump_data, list, tp_id,
|
||||
regions_mask, &imr_reg_data,
|
||||
IWL_INI_DUMP_EARLY_REGIONS);
|
||||
iwl_trans_pcie_fw_reset_handshake(fwrt->trans);
|
||||
size += iwl_dump_ini_dump_regions(fwrt, dump_data, list, tp_id,
|
||||
regions_mask, &imr_reg_data,
|
||||
IWL_INI_DUMP_LATE_REGIONS);
|
||||
} else {
|
||||
if (fw_has_capa(&fwrt->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_RESET_DURING_ASSERT) &&
|
||||
iwl_dump_due_to_error(tp_id))
|
||||
iwl_trans_pcie_fw_reset_handshake(fwrt->trans);
|
||||
size += iwl_dump_ini_dump_regions(fwrt, dump_data, list, tp_id,
|
||||
regions_mask, &imr_reg_data,
|
||||
IWL_INI_DUMP_ALL_REGIONS);
|
||||
}
|
||||
/* collect DRAM_IMR region in the last */
|
||||
if (imr_reg_data.reg_tlv)
|
||||
size += iwl_dump_ini_mem(fwrt, list, ®_data,
|
||||
size += iwl_dump_ini_mem(fwrt, list, &imr_reg_data,
|
||||
&iwl_dump_ini_region_ops[IWL_FW_INI_REGION_DRAM_IMR]);
|
||||
|
||||
if (size) {
|
||||
@@ -2902,7 +3001,7 @@ IWL_EXPORT_SYMBOL(iwl_fw_dbg_collect_desc);
|
||||
int iwl_fw_dbg_error_collect(struct iwl_fw_runtime *fwrt,
|
||||
enum iwl_fw_dbg_trigger trig_type)
|
||||
{
|
||||
if (!test_bit(STATUS_DEVICE_ENABLED, &fwrt->trans->status))
|
||||
if (!iwl_trans_device_enabled(fwrt->trans))
|
||||
return -EIO;
|
||||
|
||||
if (iwl_trans_dbg_ini_valid(fwrt->trans)) {
|
||||
@@ -2948,6 +3047,7 @@ int iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_fw_dump_desc *desc;
|
||||
unsigned int delay = 0;
|
||||
bool monitor_only = false;
|
||||
int ret;
|
||||
|
||||
if (trigger) {
|
||||
u16 occurrences = le16_to_cpu(trigger->occurrences) - 1;
|
||||
@@ -2978,7 +3078,11 @@ int iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt,
|
||||
desc->trig_desc.type = cpu_to_le32(trig);
|
||||
memcpy(desc->trig_desc.data, str, len);
|
||||
|
||||
return iwl_fw_dbg_collect_desc(fwrt, desc, monitor_only, delay);
|
||||
ret = iwl_fw_dbg_collect_desc(fwrt, desc, monitor_only, delay);
|
||||
if (ret)
|
||||
kfree(desc);
|
||||
|
||||
return ret;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_fw_dbg_collect);
|
||||
|
||||
@@ -2986,7 +3090,7 @@ int iwl_fw_dbg_collect_trig(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_fw_dbg_trigger_tlv *trigger,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
int ret, len = 0;
|
||||
int len = 0;
|
||||
char buf[64];
|
||||
|
||||
if (iwl_trans_dbg_ini_valid(fwrt->trans))
|
||||
@@ -3008,13 +3112,8 @@ int iwl_fw_dbg_collect_trig(struct iwl_fw_runtime *fwrt,
|
||||
len = strlen(buf) + 1;
|
||||
}
|
||||
|
||||
ret = iwl_fw_dbg_collect(fwrt, le32_to_cpu(trigger->id), buf, len,
|
||||
trigger);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
return iwl_fw_dbg_collect(fwrt, le32_to_cpu(trigger->id), buf, len,
|
||||
trigger);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_fw_dbg_collect_trig);
|
||||
|
||||
@@ -3065,9 +3164,8 @@ int iwl_fw_start_dbg_conf(struct iwl_fw_runtime *fwrt, u8 conf_id)
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_fw_start_dbg_conf);
|
||||
|
||||
void iwl_send_dbg_dump_complete_cmd(struct iwl_fw_runtime *fwrt,
|
||||
u32 timepoint,
|
||||
u32 timepoint_data)
|
||||
static void iwl_send_dbg_dump_complete_cmd(struct iwl_fw_runtime *fwrt,
|
||||
u32 timepoint, u32 timepoint_data)
|
||||
{
|
||||
struct iwl_dbg_dump_complete_cmd hcmd_data;
|
||||
struct iwl_host_cmd hcmd = {
|
||||
@@ -3095,6 +3193,7 @@ static void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt, u8 wk_idx)
|
||||
struct iwl_fw_dbg_params params = {0};
|
||||
struct iwl_fwrt_dump_data *dump_data =
|
||||
&fwrt->dump.wks[wk_idx].dump_data;
|
||||
|
||||
if (!test_bit(wk_idx, &fwrt->dump.active_wks))
|
||||
return;
|
||||
|
||||
@@ -3104,13 +3203,13 @@ static void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt, u8 wk_idx)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!test_bit(STATUS_DEVICE_ENABLED, &fwrt->trans->status)) {
|
||||
if (!iwl_trans_device_enabled(fwrt->trans)) {
|
||||
IWL_ERR(fwrt, "Device is not enabled - cannot dump error\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* there's no point in fw dump if the bus is dead */
|
||||
if (test_bit(STATUS_TRANS_DEAD, &fwrt->trans->status)) {
|
||||
if (iwl_trans_is_dead(fwrt->trans)) {
|
||||
IWL_ERR(fwrt, "Skip fw error dump since bus is dead\n");
|
||||
goto out;
|
||||
}
|
||||
@@ -3119,9 +3218,9 @@ static void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt, u8 wk_idx)
|
||||
|
||||
IWL_DEBUG_FW_INFO(fwrt, "WRT: Data collection start\n");
|
||||
if (iwl_trans_dbg_ini_valid(fwrt->trans))
|
||||
iwl_fw_error_ini_dump(fwrt, &fwrt->dump.wks[wk_idx].dump_data);
|
||||
iwl_fw_error_ini_dump(fwrt, dump_data);
|
||||
else
|
||||
iwl_fw_error_dump(fwrt, &fwrt->dump.wks[wk_idx].dump_data);
|
||||
iwl_fw_error_dump(fwrt, dump_data);
|
||||
IWL_DEBUG_FW_INFO(fwrt, "WRT: Data collection done\n");
|
||||
|
||||
iwl_fw_dbg_stop_restart_recording(fwrt, ¶ms, false);
|
||||
@@ -3138,7 +3237,6 @@ static void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt, u8 wk_idx)
|
||||
|
||||
if (fwrt->trans->dbg.last_tp_resetfw == IWL_FW_INI_RESET_FW_MODE_STOP_FW_ONLY)
|
||||
iwl_force_nmi(fwrt->trans);
|
||||
|
||||
out:
|
||||
if (iwl_trans_dbg_ini_valid(fwrt->trans)) {
|
||||
iwl_fw_error_dump_data_free(dump_data);
|
||||
@@ -3225,13 +3323,13 @@ void iwl_fw_error_dump_wk(struct work_struct *work)
|
||||
|
||||
void iwl_fw_dbg_read_d3_debug_data(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
const struct iwl_cfg *cfg = fwrt->trans->cfg;
|
||||
const struct iwl_mac_cfg *mac_cfg = fwrt->trans->mac_cfg;
|
||||
|
||||
if (!iwl_fw_dbg_is_d3_debug_enabled(fwrt))
|
||||
return;
|
||||
|
||||
if (!fwrt->dump.d3_debug_data) {
|
||||
fwrt->dump.d3_debug_data = kmalloc(cfg->d3_debug_data_length,
|
||||
fwrt->dump.d3_debug_data = kmalloc(mac_cfg->base->d3_debug_data_length,
|
||||
GFP_KERNEL);
|
||||
if (!fwrt->dump.d3_debug_data) {
|
||||
IWL_ERR(fwrt,
|
||||
@@ -3241,15 +3339,15 @@ void iwl_fw_dbg_read_d3_debug_data(struct iwl_fw_runtime *fwrt)
|
||||
}
|
||||
|
||||
/* if the buffer holds previous debug data it is overwritten */
|
||||
iwl_trans_read_mem_bytes(fwrt->trans, cfg->d3_debug_data_base_addr,
|
||||
iwl_trans_read_mem_bytes(fwrt->trans, mac_cfg->base->d3_debug_data_base_addr,
|
||||
fwrt->dump.d3_debug_data,
|
||||
cfg->d3_debug_data_length);
|
||||
mac_cfg->base->d3_debug_data_length);
|
||||
|
||||
if (fwrt->sanitize_ops && fwrt->sanitize_ops->frob_mem)
|
||||
fwrt->sanitize_ops->frob_mem(fwrt->sanitize_ctx,
|
||||
cfg->d3_debug_data_base_addr,
|
||||
mac_cfg->base->d3_debug_data_base_addr,
|
||||
fwrt->dump.d3_debug_data,
|
||||
cfg->d3_debug_data_length);
|
||||
mac_cfg->base->d3_debug_data_length);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_fw_dbg_read_d3_debug_data);
|
||||
|
||||
@@ -3284,7 +3382,7 @@ static int iwl_fw_dbg_suspend_resume_hcmd(struct iwl_trans *trans, bool suspend)
|
||||
static void iwl_fw_dbg_stop_recording(struct iwl_trans *trans,
|
||||
struct iwl_fw_dbg_params *params)
|
||||
{
|
||||
if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_7000) {
|
||||
if (trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_7000) {
|
||||
iwl_set_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x100);
|
||||
return;
|
||||
}
|
||||
@@ -3308,7 +3406,7 @@ static int iwl_fw_dbg_restart_recording(struct iwl_trans *trans,
|
||||
if (!params)
|
||||
return -EIO;
|
||||
|
||||
if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_7000) {
|
||||
if (trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_7000) {
|
||||
iwl_clear_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x100);
|
||||
iwl_clear_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x1);
|
||||
iwl_set_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x1);
|
||||
@@ -3410,7 +3508,7 @@ void iwl_fw_disable_dbg_asserts(struct iwl_fw_runtime *fwrt)
|
||||
GENMASK(31, IWL_FW_DBG_DOMAIN_POS + 1));
|
||||
|
||||
/* supported starting from 9000 devices */
|
||||
if (fwrt->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_9000)
|
||||
if (fwrt->trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_9000)
|
||||
return;
|
||||
|
||||
if (fwrt->trans->dbg.yoyo_bin_loaded || (preset && preset != 1))
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2005-2014, 2018-2019, 2021-2023 Intel Corporation
|
||||
* Copyright (C) 2005-2014, 2018-2019, 2021-2025 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2015-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
@@ -205,7 +205,7 @@ static inline bool iwl_fw_dbg_is_d3_debug_enabled(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
return fw_has_capa(&fwrt->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_D3_DEBUG) &&
|
||||
fwrt->trans->cfg->d3_debug_data_length && fwrt->ops &&
|
||||
fwrt->trans->mac_cfg->base->d3_debug_data_length && fwrt->ops &&
|
||||
fwrt->ops->d3_debug_enable &&
|
||||
fwrt->ops->d3_debug_enable(fwrt->ops_ctx) &&
|
||||
iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_D3_DEBUG_DATA);
|
||||
@@ -214,7 +214,7 @@ static inline bool iwl_fw_dbg_is_d3_debug_enabled(struct iwl_fw_runtime *fwrt)
|
||||
static inline bool iwl_fw_dbg_is_paging_enabled(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
return iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_PAGING) &&
|
||||
!fwrt->trans->trans_cfg->gen2 &&
|
||||
!fwrt->trans->mac_cfg->gen2 &&
|
||||
fwrt->cur_fw_img < IWL_UCODE_TYPE_MAX &&
|
||||
fwrt->fw->img[fwrt->cur_fw_img].paging_mem_size &&
|
||||
fwrt->fw_paging_db[0].fw_paging_block;
|
||||
@@ -291,7 +291,7 @@ static inline void iwl_fw_umac_set_alive_err_table(struct iwl_trans *trans,
|
||||
trans->dbg.umac_error_event_table = umac_error_event_table;
|
||||
}
|
||||
|
||||
static inline void iwl_fw_error_collect(struct iwl_fw_runtime *fwrt, bool sync)
|
||||
static inline void iwl_fw_error_collect(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
enum iwl_fw_ini_time_point tp_id;
|
||||
|
||||
@@ -307,7 +307,7 @@ static inline void iwl_fw_error_collect(struct iwl_fw_runtime *fwrt, bool sync)
|
||||
tp_id = IWL_FW_INI_TIME_POINT_FW_ASSERT;
|
||||
}
|
||||
|
||||
_iwl_dbg_tlv_time_point(fwrt, tp_id, NULL, sync);
|
||||
iwl_dbg_tlv_time_point_sync(fwrt, tp_id, NULL);
|
||||
}
|
||||
|
||||
static inline void iwl_fwrt_update_fw_versions(struct iwl_fw_runtime *fwrt,
|
||||
@@ -328,21 +328,19 @@ static inline void iwl_fwrt_update_fw_versions(struct iwl_fw_runtime *fwrt,
|
||||
}
|
||||
|
||||
void iwl_fwrt_dump_error_logs(struct iwl_fw_runtime *fwrt);
|
||||
void iwl_send_dbg_dump_complete_cmd(struct iwl_fw_runtime *fwrt,
|
||||
u32 timepoint,
|
||||
u32 timepoint_data);
|
||||
bool iwl_fwrt_read_err_table(struct iwl_trans *trans, u32 base, u32 *err_id);
|
||||
void iwl_fw_disable_dbg_asserts(struct iwl_fw_runtime *fwrt);
|
||||
void iwl_fw_dbg_clear_monitor_buf(struct iwl_fw_runtime *fwrt);
|
||||
|
||||
#define IWL_FW_CHECK_FAILED(_obj, _fmt, ...) \
|
||||
IWL_ERR_LIMIT(_obj, _fmt, __VA_ARGS__)
|
||||
#define IWL_FW_CHECK_FAILED(_obj, ...) \
|
||||
IWL_ERR_LIMIT(_obj, __VA_ARGS__)
|
||||
|
||||
#define IWL_FW_CHECK(_obj, _cond, _fmt, ...) \
|
||||
({ \
|
||||
bool __cond = (_cond); \
|
||||
\
|
||||
if (unlikely(__cond)) \
|
||||
IWL_FW_CHECK_FAILED(_obj, _fmt, __VA_ARGS__); \
|
||||
IWL_FW_CHECK_FAILED(_obj, _fmt, ##__VA_ARGS__); \
|
||||
\
|
||||
unlikely(__cond); \
|
||||
})
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2023 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2024 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
@@ -123,6 +123,24 @@ static const struct file_operations iwl_dbgfs_##name##_ops = { \
|
||||
#define FWRT_DEBUGFS_ADD_FILE(name, parent, mode) \
|
||||
FWRT_DEBUGFS_ADD_FILE_ALIAS(#name, name, parent, mode)
|
||||
|
||||
static ssize_t iwl_dbgfs_fw_dbg_collect_write(struct iwl_fw_runtime *fwrt,
|
||||
char *buf, size_t count)
|
||||
{
|
||||
if (count == 0)
|
||||
return 0;
|
||||
|
||||
if (!iwl_trans_fw_running(fwrt->trans))
|
||||
return count;
|
||||
|
||||
iwl_dbg_tlv_time_point(fwrt, IWL_FW_INI_TIME_POINT_USER_TRIGGER, NULL);
|
||||
|
||||
iwl_fw_dbg_collect(fwrt, FW_DBG_TRIGGER_USER, buf, (count - 1), NULL);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
FWRT_DEBUGFS_WRITE_FILE_OPS(fw_dbg_collect, 16);
|
||||
|
||||
static int iwl_dbgfs_enabled_severities_write(struct iwl_fw_runtime *fwrt,
|
||||
char *buf, size_t count)
|
||||
{
|
||||
@@ -180,7 +198,7 @@ void iwl_fw_trigger_timestamp(struct iwl_fw_runtime *fwrt, u32 delay)
|
||||
|
||||
iwl_fw_cancel_timestamp(fwrt);
|
||||
|
||||
fwrt->timestamp.delay = msecs_to_jiffies(delay * 1000);
|
||||
fwrt->timestamp.delay = secs_to_jiffies(delay);
|
||||
|
||||
schedule_delayed_work(&fwrt->timestamp.wk,
|
||||
round_jiffies_relative(fwrt->timestamp.delay));
|
||||
@@ -282,6 +300,26 @@ static ssize_t iwl_dbgfs_fw_dbg_domain_read(struct iwl_fw_runtime *fwrt,
|
||||
|
||||
FWRT_DEBUGFS_READ_FILE_OPS(fw_dbg_domain, 20);
|
||||
|
||||
static ssize_t iwl_dbgfs_fw_ver_read(struct iwl_fw_runtime *fwrt,
|
||||
size_t size, char *buf)
|
||||
{
|
||||
char *pos = buf;
|
||||
char *endpos = buf + size;
|
||||
|
||||
pos += scnprintf(pos, endpos - pos, "FW id: %s\n",
|
||||
fwrt->fw->fw_version);
|
||||
pos += scnprintf(pos, endpos - pos, "FW: %s\n",
|
||||
fwrt->fw->human_readable);
|
||||
pos += scnprintf(pos, endpos - pos, "Device: %s\n",
|
||||
fwrt->trans->info.name);
|
||||
pos += scnprintf(pos, endpos - pos, "Bus: %s\n",
|
||||
fwrt->dev->bus->name);
|
||||
|
||||
return pos - buf;
|
||||
}
|
||||
|
||||
FWRT_DEBUGFS_READ_FILE_OPS(fw_ver, 1024);
|
||||
|
||||
struct iwl_dbgfs_fw_info_priv {
|
||||
struct iwl_fw_runtime *fwrt;
|
||||
};
|
||||
@@ -351,6 +389,12 @@ static int iwl_dbgfs_fw_info_seq_show(struct seq_file *seq, void *v)
|
||||
" %d: %d\n",
|
||||
IWL_UCODE_TLV_CAPA_CHINA_22_REG_SUPPORT,
|
||||
has_capa);
|
||||
has_capa = fw_has_capa(&fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_FW_ACCEPTS_RAW_DSM_TABLE) ? 1 : 0;
|
||||
seq_printf(seq,
|
||||
" %d: %d\n",
|
||||
IWL_UCODE_TLV_CAPA_FW_ACCEPTS_RAW_DSM_TABLE,
|
||||
has_capa);
|
||||
seq_puts(seq, "fw_api_ver:\n");
|
||||
}
|
||||
|
||||
@@ -403,5 +447,7 @@ void iwl_fwrt_dbgfs_register(struct iwl_fw_runtime *fwrt,
|
||||
FWRT_DEBUGFS_ADD_FILE(fw_info, dbgfs_dir, 0200);
|
||||
FWRT_DEBUGFS_ADD_FILE(send_hcmd, dbgfs_dir, 0200);
|
||||
FWRT_DEBUGFS_ADD_FILE(enabled_severities, dbgfs_dir, 0200);
|
||||
FWRT_DEBUGFS_ADD_FILE(fw_dbg_collect, dbgfs_dir, 0200);
|
||||
FWRT_DEBUGFS_ADD_FILE(fw_dbg_domain, dbgfs_dir, 0400);
|
||||
FWRT_DEBUGFS_ADD_FILE(fw_ver, dbgfs_dir, 0400);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2021, 2025 Intel Corporation
|
||||
*/
|
||||
#ifndef __iwl_fw_dhc_utils_h__
|
||||
#define __iwl_fw_dhc_utils_h__
|
||||
|
||||
#include <linux/types.h>
|
||||
#include "fw/img.h"
|
||||
#include "api/commands.h"
|
||||
#include "api/dhc.h"
|
||||
|
||||
/**
|
||||
* iwl_dhc_resp_status - return status of DHC response
|
||||
* @fw: firwmware image information
|
||||
* @pkt: response packet, must not be %NULL
|
||||
*
|
||||
* Returns: the status value of the DHC command or (u32)-1 if the
|
||||
* response was too short.
|
||||
*/
|
||||
static inline u32 iwl_dhc_resp_status(const struct iwl_fw *fw,
|
||||
struct iwl_rx_packet *pkt)
|
||||
{
|
||||
if (iwl_fw_lookup_notif_ver(fw, IWL_ALWAYS_LONG_GROUP,
|
||||
DEBUG_HOST_COMMAND, 1) >= 2) {
|
||||
struct iwl_dhc_cmd_resp *resp = (void *)pkt->data;
|
||||
|
||||
if (iwl_rx_packet_payload_len(pkt) < sizeof(*resp))
|
||||
return (u32)-1;
|
||||
|
||||
return le32_to_cpu(resp->status);
|
||||
} else {
|
||||
struct iwl_dhc_cmd_resp_v1 *resp = (void *)pkt->data;
|
||||
|
||||
if (iwl_rx_packet_payload_len(pkt) < sizeof(*resp))
|
||||
return (u32)-1;
|
||||
|
||||
return le32_to_cpu(resp->status);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl_dhc_resp_data - return data pointer of DHC response
|
||||
* @fw: firwmware image information
|
||||
* @pkt: response packet, must not be %NULL
|
||||
* @len: where to store the length
|
||||
*
|
||||
* Returns: The data pointer, or an ERR_PTR() if the data was
|
||||
* not valid (too short).
|
||||
*/
|
||||
static inline void *iwl_dhc_resp_data(const struct iwl_fw *fw,
|
||||
struct iwl_rx_packet *pkt,
|
||||
unsigned int *len)
|
||||
{
|
||||
if (iwl_fw_lookup_notif_ver(fw, IWL_ALWAYS_LONG_GROUP,
|
||||
DEBUG_HOST_COMMAND, 1) >= 2) {
|
||||
struct iwl_dhc_cmd_resp *resp = (void *)pkt->data;
|
||||
|
||||
if (iwl_rx_packet_payload_len(pkt) < sizeof(*resp))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
*len = iwl_rx_packet_payload_len(pkt) - sizeof(*resp);
|
||||
return (void *)&resp->data;
|
||||
} else {
|
||||
struct iwl_dhc_cmd_resp_v1 *resp = (void *)pkt->data;
|
||||
|
||||
if (iwl_rx_packet_payload_len(pkt) < sizeof(*resp))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
*len = iwl_rx_packet_payload_len(pkt) - sizeof(*resp);
|
||||
return (void *)&resp->data;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* __iwl_fw_dhc_utils_h__ */
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2023 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2025 Intel Corporation
|
||||
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2015-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
@@ -199,7 +199,7 @@ static void iwl_fwrt_dump_lmac_error_log(struct iwl_fw_runtime *fwrt, u8 lmac_nu
|
||||
IWL_ERR(trans, "HW error, resetting before reading\n");
|
||||
|
||||
/* reset the device */
|
||||
err = iwl_trans_sw_reset(trans, true);
|
||||
err = iwl_trans_sw_reset(trans);
|
||||
if (err)
|
||||
return;
|
||||
|
||||
@@ -417,10 +417,10 @@ static void iwl_fwrt_dump_iml_error_log(struct iwl_fw_runtime *fwrt)
|
||||
struct iwl_trans *trans = fwrt->trans;
|
||||
u32 error, data1;
|
||||
|
||||
if (fwrt->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000) {
|
||||
if (fwrt->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_22000) {
|
||||
error = UMAG_SB_CPU_2_STATUS;
|
||||
data1 = UMAG_SB_CPU_1_STATUS;
|
||||
} else if (fwrt->trans->trans_cfg->device_family >=
|
||||
} else if (fwrt->trans->mac_cfg->device_family >=
|
||||
IWL_DEVICE_FAMILY_8000) {
|
||||
error = SB_CPU_2_STATUS;
|
||||
data1 = SB_CPU_1_STATUS;
|
||||
@@ -439,7 +439,7 @@ static void iwl_fwrt_dump_iml_error_log(struct iwl_fw_runtime *fwrt)
|
||||
IWL_ERR(fwrt, "0x%08X | IML/ROM data1\n",
|
||||
iwl_read_umac_prph(trans, data1));
|
||||
|
||||
if (fwrt->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000)
|
||||
if (fwrt->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_22000)
|
||||
IWL_ERR(fwrt, "0x%08X | IML/ROM WFPM_AUTH_KEY_0\n",
|
||||
iwl_read_umac_prph(trans, SB_MODIFY_CFG_FLAG));
|
||||
}
|
||||
@@ -490,7 +490,7 @@ void iwl_fwrt_dump_error_logs(struct iwl_fw_runtime *fwrt)
|
||||
struct iwl_pc_data *pc_data;
|
||||
u8 count;
|
||||
|
||||
if (!test_bit(STATUS_DEVICE_ENABLED, &fwrt->trans->status)) {
|
||||
if (!iwl_trans_device_enabled(fwrt->trans)) {
|
||||
IWL_ERR(fwrt,
|
||||
"DEVICE_ENABLED bit is not set. Aborting dump.\n");
|
||||
return;
|
||||
@@ -508,7 +508,7 @@ void iwl_fwrt_dump_error_logs(struct iwl_fw_runtime *fwrt)
|
||||
iwl_fwrt_dump_rcm_error_log(fwrt, 1);
|
||||
iwl_fwrt_dump_iml_error_log(fwrt);
|
||||
iwl_fwrt_dump_fseq_regs(fwrt);
|
||||
if (fwrt->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000) {
|
||||
if (fwrt->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_22000) {
|
||||
pc_data = fwrt->trans->dbg.pc_data;
|
||||
|
||||
if (!iwl_trans_grab_nic_access(fwrt->trans))
|
||||
@@ -522,7 +522,7 @@ void iwl_fwrt_dump_error_logs(struct iwl_fw_runtime *fwrt)
|
||||
iwl_trans_release_nic_access(fwrt->trans);
|
||||
}
|
||||
|
||||
if (fwrt->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) {
|
||||
if (fwrt->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) {
|
||||
u32 scratch = iwl_read32(fwrt->trans, CSR_FUNC_SCRATCH);
|
||||
|
||||
IWL_ERR(fwrt, "Function Scratch status:\n");
|
||||
@@ -530,3 +530,31 @@ void iwl_fwrt_dump_error_logs(struct iwl_fw_runtime *fwrt)
|
||||
}
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_fwrt_dump_error_logs);
|
||||
|
||||
bool iwl_fwrt_read_err_table(struct iwl_trans *trans, u32 base, u32 *err_id)
|
||||
{
|
||||
struct error_table_start {
|
||||
/* cf. struct iwl_error_event_table */
|
||||
u32 valid;
|
||||
__le32 err_id;
|
||||
} err_info = {};
|
||||
int ret;
|
||||
|
||||
if (err_id)
|
||||
*err_id = 0;
|
||||
|
||||
if (!base)
|
||||
return false;
|
||||
|
||||
ret = iwl_trans_read_mem_bytes(trans, base,
|
||||
&err_info, sizeof(err_info));
|
||||
|
||||
if (ret)
|
||||
return true;
|
||||
|
||||
if (err_info.valid && err_id)
|
||||
*err_id = le32_to_cpu(err_info.err_id);
|
||||
|
||||
return !!err_info.valid;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_fwrt_read_err_table);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2014, 2018-2024 Intel Corporation
|
||||
* Copyright (C) 2014, 2018-2025 Intel Corporation
|
||||
* Copyright (C) 2014-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
@@ -169,7 +169,7 @@ struct iwl_fw_error_dump_info {
|
||||
* @fw_mon_wr_ptr: the position of the write pointer in the cyclic buffer
|
||||
* @fw_mon_base_ptr: base pointer of the data
|
||||
* @fw_mon_cycle_cnt: number of wraparounds
|
||||
* @fw_mon_base_high_ptr: used in AX210 devices, the base adderss is 64 bit
|
||||
* @fw_mon_base_high_ptr: used in AX210 devices, the base address is 64 bit
|
||||
* so fw_mon_base_ptr holds LSB 32 bits and fw_mon_base_high_ptr hold
|
||||
* MSB 32 bits
|
||||
* @reserved: for future use
|
||||
@@ -372,10 +372,7 @@ struct iwl_fw_ini_dump_cfg_name {
|
||||
u8 cfg_name[IWL_FW_INI_MAX_CFG_NAME];
|
||||
} __packed;
|
||||
|
||||
/* AX210's HW type */
|
||||
#define IWL_AX210_HW_TYPE 0x42
|
||||
/* How many bits to roll when adding to the HW type of AX210 HW */
|
||||
#define IWL_AX210_HW_TYPE_ADDITION_SHIFT 12
|
||||
#define IWL_JACKET_CDB_SHIFT 12
|
||||
|
||||
/* struct iwl_fw_ini_dump_info - ini dump information
|
||||
* @version: dump version
|
||||
|
||||
@@ -102,8 +102,13 @@ enum iwl_ucode_tlv_type {
|
||||
IWL_UCODE_TLV_SEC_TABLE_ADDR = 66,
|
||||
IWL_UCODE_TLV_D3_KEK_KCK_ADDR = 67,
|
||||
IWL_UCODE_TLV_CURRENT_PC = 68,
|
||||
IWL_UCODE_TLV_FSEQ_BIN_VERSION = 72,
|
||||
|
||||
/* contains sub-sections like PNVM file does (did) */
|
||||
IWL_UCODE_TLV_PNVM_DATA = 74,
|
||||
|
||||
IWL_UCODE_TLV_FW_NUM_STATIONS = IWL_UCODE_TLV_CONST_BASE + 0,
|
||||
IWL_UCODE_TLV_FW_NUM_LINKS = IWL_UCODE_TLV_CONST_BASE + 1,
|
||||
IWL_UCODE_TLV_FW_NUM_BEACONS = IWL_UCODE_TLV_CONST_BASE + 2,
|
||||
|
||||
IWL_UCODE_TLV_TYPE_DEBUG_INFO = IWL_UCODE_TLV_DEBUG_BASE + 0,
|
||||
@@ -384,7 +389,8 @@ typedef unsigned int __bitwise iwl_ucode_tlv_capa_t;
|
||||
* to report the CSI information with (certain) RX frames
|
||||
* @IWL_UCODE_TLV_CAPA_FTM_CALIBRATED: has FTM calibrated and thus supports both
|
||||
* initiator and responder
|
||||
* @IWL_UCODE_TLV_CAPA_MLME_OFFLOAD: supports MLME offload
|
||||
* @IWL_UCODE_TLV_CAPA_BIOS_OVERRIDE_UNII4_US_CA: supports (de)activating UNII-4
|
||||
* for US/CA/WW from BIOS
|
||||
* @IWL_UCODE_TLV_CAPA_PROTECTED_TWT: Supports protection of TWT action frames
|
||||
* @IWL_UCODE_TLV_CAPA_FW_RESET_HANDSHAKE: Supports the firmware handshake in
|
||||
* reset flow
|
||||
@@ -397,6 +403,12 @@ typedef unsigned int __bitwise iwl_ucode_tlv_capa_t;
|
||||
* @IWL_UCODE_TLV_CAPA_SECURE_LTF_SUPPORT: Support secure LTF measurement.
|
||||
* @IWL_UCODE_TLV_CAPA_MONITOR_PASSIVE_CHANS: Support monitor mode on otherwise
|
||||
* passive channels
|
||||
* @IWL_UCODE_TLV_CAPA_BIOS_OVERRIDE_5G9_FOR_CA: supports (de)activating 5G9
|
||||
* for CA from BIOS.
|
||||
* @IWL_UCODE_TLV_CAPA_UHB_CANADA_TAS_SUPPORT: supports %TAS_UHB_ALLOWED_CANADA
|
||||
* @IWL_UCODE_TLV_CAPA_EXT_FSEQ_IMAGE_SUPPORT: external FSEQ image support
|
||||
* @IWL_UCODE_TLV_CAPA_FW_ACCEPTS_RAW_DSM_TABLE: Firmware has capability of
|
||||
* handling raw DSM table data.
|
||||
*
|
||||
* @NUM_IWL_UCODE_TLV_CAPA: number of bits used
|
||||
*/
|
||||
@@ -474,7 +486,7 @@ enum iwl_ucode_tlv_capa {
|
||||
IWL_UCODE_TLV_CAPA_DBG_BUF_ALLOC_CMD_SUPP = (__force iwl_ucode_tlv_capa_t)93,
|
||||
|
||||
/* set 3 */
|
||||
IWL_UCODE_TLV_CAPA_MLME_OFFLOAD = (__force iwl_ucode_tlv_capa_t)96,
|
||||
IWL_UCODE_TLV_CAPA_BIOS_OVERRIDE_UNII4_US_CA = (__force iwl_ucode_tlv_capa_t)96,
|
||||
|
||||
/*
|
||||
* @IWL_UCODE_TLV_CAPA_PSC_CHAN_SUPPORT: supports PSC channels
|
||||
@@ -497,6 +509,17 @@ enum iwl_ucode_tlv_capa {
|
||||
IWL_UCODE_TLV_CAPA_CHINA_22_REG_SUPPORT = (__force iwl_ucode_tlv_capa_t)117,
|
||||
IWL_UCODE_TLV_CAPA_SECURE_LTF_SUPPORT = (__force iwl_ucode_tlv_capa_t)121,
|
||||
IWL_UCODE_TLV_CAPA_MONITOR_PASSIVE_CHANS = (__force iwl_ucode_tlv_capa_t)122,
|
||||
IWL_UCODE_TLV_CAPA_BIOS_OVERRIDE_5G9_FOR_CA = (__force iwl_ucode_tlv_capa_t)123,
|
||||
IWL_UCODE_TLV_CAPA_UHB_CANADA_TAS_SUPPORT = (__force iwl_ucode_tlv_capa_t)124,
|
||||
IWL_UCODE_TLV_CAPA_EXT_FSEQ_IMAGE_SUPPORT = (__force iwl_ucode_tlv_capa_t)125,
|
||||
|
||||
/* set 4 */
|
||||
/**
|
||||
* @IWL_UCODE_TLV_CAPA_RESET_DURING_ASSERT: FW reset handshake is needed
|
||||
* during assert handling even if the dump isn't split
|
||||
*/
|
||||
IWL_UCODE_TLV_CAPA_RESET_DURING_ASSERT = (__force iwl_ucode_tlv_capa_t)(4 * 32 + 0),
|
||||
IWL_UCODE_TLV_CAPA_FW_ACCEPTS_RAW_DSM_TABLE = (__force iwl_ucode_tlv_capa_t)(4 * 32 + 1),
|
||||
NUM_IWL_UCODE_TLV_CAPA
|
||||
/*
|
||||
* This construction make both sparse (which cannot increment the previous
|
||||
@@ -987,6 +1010,10 @@ struct iwl_fw_dump_exclude {
|
||||
__le32 addr, size;
|
||||
};
|
||||
|
||||
struct iwl_fw_fseq_bin_version {
|
||||
__le32 major, minor;
|
||||
}; /* FW_TLV_FSEQ_BIN_VERSION_S */
|
||||
|
||||
static inline size_t _iwl_tlv_array_len(const struct iwl_ucode_tlv *tlv,
|
||||
size_t fixed_size, size_t var_size)
|
||||
{
|
||||
@@ -1004,4 +1031,18 @@ static inline size_t _iwl_tlv_array_len(const struct iwl_ucode_tlv *tlv,
|
||||
|
||||
#define iwl_tlv_array_len_with_size(_tlv_ptr, _struct_ptr, _size) \
|
||||
_iwl_tlv_array_len((_tlv_ptr), sizeof(*(_struct_ptr)), _size)
|
||||
|
||||
/* external FSEQ file */
|
||||
#define IWL_FSEQ_FILE "intel/fseq-%04x-%04x"
|
||||
#define IWL_FSEQ_MAGIC "INTEL-CNV-FSEQ\n\0"
|
||||
|
||||
struct iwl_fseq_file {
|
||||
char magic[16];
|
||||
char version[16];
|
||||
__le32 bt_len;
|
||||
__le32 wifi_len;
|
||||
u8 reserved[8];
|
||||
u8 data[];
|
||||
} __packed;
|
||||
|
||||
#endif /* __iwl_fw_file_h__ */
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright(c) 2019 - 2021 Intel Corporation
|
||||
* Copyright(c) 2024 Intel Corporation
|
||||
*/
|
||||
#include <fw/api/commands.h>
|
||||
#include "img.h"
|
||||
@@ -75,6 +76,7 @@ static const struct {
|
||||
{ "NMI_INTERRUPT_ACTION_PT", 0x7C },
|
||||
{ "NMI_INTERRUPT_UNKNOWN", 0x84 },
|
||||
{ "NMI_INTERRUPT_INST_ACTION_PT", 0x86 },
|
||||
{ "NMI_INTERRUPT_PREG", 0x88 },
|
||||
{ "PNVM_MISSING", FW_SYSASSERT_PNVM_MISSING },
|
||||
{ "ADVANCED_SYSASSERT", 0 },
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2005-2014, 2018-2023 Intel Corporation
|
||||
* Copyright (C) 2005-2014, 2018-2024 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016 Intel Deutschland GmbH
|
||||
*/
|
||||
@@ -51,9 +51,10 @@ struct iwl_ucode_capabilities {
|
||||
u32 error_log_addr;
|
||||
u32 error_log_size;
|
||||
u32 num_stations;
|
||||
u32 num_links;
|
||||
u32 num_beacons;
|
||||
unsigned long _api[BITS_TO_LONGS(NUM_IWL_UCODE_TLV_API)];
|
||||
unsigned long _capa[BITS_TO_LONGS(NUM_IWL_UCODE_TLV_CAPA)];
|
||||
DECLARE_BITMAP(_api, NUM_IWL_UCODE_TLV_API);
|
||||
DECLARE_BITMAP(_capa, NUM_IWL_UCODE_TLV_CAPA);
|
||||
|
||||
const struct iwl_fw_cmd_version *cmd_versions;
|
||||
u32 n_cmd_versions;
|
||||
@@ -194,6 +195,8 @@ struct iwl_dump_exclude {
|
||||
* @phy_integration_ver_len: length of @phy_integration_ver
|
||||
* @dump_excl: image dump exclusion areas for RT image
|
||||
* @dump_excl_wowlan: image dump exclusion areas for WoWLAN image
|
||||
* @pnvm_data: PNVM data embedded in the .ucode file, if any
|
||||
* @pnvm_size: size of the embedded PNVM data
|
||||
*/
|
||||
struct iwl_fw {
|
||||
u32 ucode_ver;
|
||||
@@ -226,6 +229,9 @@ struct iwl_fw {
|
||||
u32 phy_integration_ver_len;
|
||||
|
||||
struct iwl_dump_exclude dump_excl[2], dump_excl_wowlan[2];
|
||||
|
||||
const void *pnvm_data;
|
||||
u32 pnvm_size;
|
||||
};
|
||||
|
||||
static inline const char *get_fw_dbg_mode_string(int mode)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2019-2021, 2024 Intel Corporation
|
||||
* Copyright (C) 2019-2021, 2024-2025 Intel Corporation
|
||||
*/
|
||||
#include "iwl-drv.h"
|
||||
#include "runtime.h"
|
||||
@@ -39,10 +39,12 @@ void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans,
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_fw_runtime_init);
|
||||
|
||||
/* Assumes the appropriate lock is held by the caller */
|
||||
void iwl_fw_runtime_suspend(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
iwl_fw_suspend_timestamp(fwrt);
|
||||
iwl_dbg_tlv_time_point(fwrt, IWL_FW_INI_TIME_POINT_HOST_D3_START, NULL);
|
||||
iwl_dbg_tlv_time_point_sync(fwrt, IWL_FW_INI_TIME_POINT_HOST_D3_START,
|
||||
NULL);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_fw_runtime_suspend);
|
||||
|
||||
@@ -70,7 +72,7 @@ int iwl_set_soc_latency(struct iwl_fw_runtime *fwrt)
|
||||
* values in VER_1, this is backwards-compatible with VER_2,
|
||||
* as long as we don't set any other bits.
|
||||
*/
|
||||
if (!fwrt->trans->trans_cfg->integrated)
|
||||
if (!fwrt->trans->mac_cfg->integrated)
|
||||
cmd.flags = cpu_to_le32(SOC_CONFIG_CMD_FLAGS_DISCRETE);
|
||||
|
||||
BUILD_BUG_ON(IWL_CFG_TRANS_LTR_DELAY_NONE !=
|
||||
@@ -82,17 +84,17 @@ int iwl_set_soc_latency(struct iwl_fw_runtime *fwrt)
|
||||
BUILD_BUG_ON(IWL_CFG_TRANS_LTR_DELAY_1820US !=
|
||||
SOC_FLAGS_LTR_APPLY_DELAY_1820);
|
||||
|
||||
if (fwrt->trans->trans_cfg->ltr_delay != IWL_CFG_TRANS_LTR_DELAY_NONE &&
|
||||
!WARN_ON(!fwrt->trans->trans_cfg->integrated))
|
||||
cmd.flags |= le32_encode_bits(fwrt->trans->trans_cfg->ltr_delay,
|
||||
if (fwrt->trans->mac_cfg->ltr_delay != IWL_CFG_TRANS_LTR_DELAY_NONE &&
|
||||
!WARN_ON(!fwrt->trans->mac_cfg->integrated))
|
||||
cmd.flags |= le32_encode_bits(fwrt->trans->mac_cfg->ltr_delay,
|
||||
SOC_FLAGS_LTR_APPLY_DELAY_MASK);
|
||||
|
||||
if (iwl_fw_lookup_cmd_ver(fwrt->fw, SCAN_REQ_UMAC,
|
||||
IWL_FW_CMD_VER_UNKNOWN) >= 2 &&
|
||||
fwrt->trans->trans_cfg->low_latency_xtal)
|
||||
fwrt->trans->mac_cfg->low_latency_xtal)
|
||||
cmd.flags |= cpu_to_le32(SOC_CONFIG_CMD_FLAGS_LOW_LATENCY);
|
||||
|
||||
cmd.latency = cpu_to_le32(fwrt->trans->trans_cfg->xtal_latency);
|
||||
cmd.latency = cpu_to_le32(fwrt->trans->mac_cfg->xtal_latency);
|
||||
|
||||
ret = iwl_trans_send_cmd(fwrt->trans, &hcmd);
|
||||
if (ret)
|
||||
@@ -114,14 +116,14 @@ int iwl_configure_rxq(struct iwl_fw_runtime *fwrt)
|
||||
* The default queue is configured via context info, so if we
|
||||
* have a single queue, there's nothing to do here.
|
||||
*/
|
||||
if (fwrt->trans->num_rx_queues == 1)
|
||||
if (fwrt->trans->info.num_rxqs == 1)
|
||||
return 0;
|
||||
|
||||
if (fwrt->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_22000)
|
||||
if (fwrt->trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_22000)
|
||||
return 0;
|
||||
|
||||
/* skip the default queue */
|
||||
num_queues = fwrt->trans->num_rx_queues - 1;
|
||||
num_queues = fwrt->trans->info.num_rxqs - 1;
|
||||
|
||||
size = struct_size(cmd, data, num_queues);
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2019, 2021 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2019, 2021, 2025 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
@@ -249,7 +249,7 @@ static int iwl_send_paging_cmd(struct iwl_fw_runtime *fwrt,
|
||||
};
|
||||
int blk_idx;
|
||||
|
||||
/* loop for for all paging blocks + CSS block */
|
||||
/* loop for all paging blocks + CSS block */
|
||||
for (blk_idx = 0; blk_idx < fwrt->num_of_paging_blk + 1; blk_idx++) {
|
||||
dma_addr_t addr = fwrt->fw_paging_db[blk_idx].fw_paging_phys;
|
||||
__le32 phy_addr;
|
||||
@@ -267,7 +267,7 @@ int iwl_init_paging(struct iwl_fw_runtime *fwrt, enum iwl_ucode_type type)
|
||||
const struct fw_img *fw = &fwrt->fw->img[type];
|
||||
int ret;
|
||||
|
||||
if (fwrt->trans->trans_cfg->gen2)
|
||||
if (fwrt->trans->mac_cfg->gen2)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright(c) 2020-2024 Intel Corporation
|
||||
* Copyright(c) 2020-2025 Intel Corporation
|
||||
*/
|
||||
|
||||
#include "iwl-drv.h"
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "fw/api/nvm-reg.h"
|
||||
#include "fw/api/alive.h"
|
||||
#include "fw/uefi.h"
|
||||
#include "fw/img.h"
|
||||
|
||||
#define IWL_PNVM_REDUCED_CAP_BIT BIT(25)
|
||||
|
||||
@@ -96,8 +97,8 @@ static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data,
|
||||
"Got IWL_UCODE_TLV_HW_TYPE mac_type 0x%0x rf_id 0x%0x\n",
|
||||
mac_type, rf_id);
|
||||
|
||||
if (mac_type == CSR_HW_REV_TYPE(trans->hw_rev) &&
|
||||
rf_id == CSR_HW_RFID_TYPE(trans->hw_rf_id))
|
||||
if (mac_type == CSR_HW_REV_TYPE(trans->info.hw_rev) &&
|
||||
rf_id == CSR_HW_RFID_TYPE(trans->info.hw_rf_id))
|
||||
hw_match = true;
|
||||
break;
|
||||
case IWL_UCODE_TLV_SEC_RT: {
|
||||
@@ -152,8 +153,8 @@ static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data,
|
||||
if (!hw_match) {
|
||||
IWL_DEBUG_FW(trans,
|
||||
"HW mismatch, skipping PNVM section (need mac_type 0x%x rf_id 0x%x)\n",
|
||||
CSR_HW_REV_TYPE(trans->hw_rev),
|
||||
CSR_HW_RFID_TYPE(trans->hw_rf_id));
|
||||
CSR_HW_REV_TYPE(trans->info.hw_rev),
|
||||
CSR_HW_RFID_TYPE(trans->info.hw_rf_id));
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
@@ -167,7 +168,8 @@ static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data,
|
||||
|
||||
static int iwl_pnvm_parse(struct iwl_trans *trans, const u8 *data,
|
||||
size_t len,
|
||||
struct iwl_pnvm_image *pnvm_data)
|
||||
struct iwl_pnvm_image *pnvm_data,
|
||||
__le32 sku_id[3])
|
||||
{
|
||||
const struct iwl_ucode_tlv *tlv;
|
||||
|
||||
@@ -190,23 +192,23 @@ static int iwl_pnvm_parse(struct iwl_trans *trans, const u8 *data,
|
||||
}
|
||||
|
||||
if (tlv_type == IWL_UCODE_TLV_PNVM_SKU) {
|
||||
const struct iwl_sku_id *sku_id =
|
||||
const struct iwl_sku_id *tlv_sku_id =
|
||||
(const void *)(data + sizeof(*tlv));
|
||||
|
||||
IWL_DEBUG_FW(trans,
|
||||
"Got IWL_UCODE_TLV_PNVM_SKU len %d\n",
|
||||
tlv_len);
|
||||
IWL_DEBUG_FW(trans, "sku_id 0x%0x 0x%0x 0x%0x\n",
|
||||
le32_to_cpu(sku_id->data[0]),
|
||||
le32_to_cpu(sku_id->data[1]),
|
||||
le32_to_cpu(sku_id->data[2]));
|
||||
le32_to_cpu(tlv_sku_id->data[0]),
|
||||
le32_to_cpu(tlv_sku_id->data[1]),
|
||||
le32_to_cpu(tlv_sku_id->data[2]));
|
||||
|
||||
data += sizeof(*tlv) + ALIGN(tlv_len, 4);
|
||||
len -= ALIGN(tlv_len, 4);
|
||||
|
||||
trans->reduced_cap_sku = false;
|
||||
rf_type = CSR_HW_RFID_TYPE(trans->hw_rf_id);
|
||||
if ((trans->sku_id[0] & IWL_PNVM_REDUCED_CAP_BIT) &&
|
||||
rf_type = CSR_HW_RFID_TYPE(trans->info.hw_rf_id);
|
||||
if ((sku_id[0] & cpu_to_le32(IWL_PNVM_REDUCED_CAP_BIT)) &&
|
||||
rf_type == IWL_CFG_RF_TYPE_FM)
|
||||
trans->reduced_cap_sku = true;
|
||||
|
||||
@@ -214,9 +216,9 @@ static int iwl_pnvm_parse(struct iwl_trans *trans, const u8 *data,
|
||||
"Reduced SKU device %d\n",
|
||||
trans->reduced_cap_sku);
|
||||
|
||||
if (trans->sku_id[0] == le32_to_cpu(sku_id->data[0]) &&
|
||||
trans->sku_id[1] == le32_to_cpu(sku_id->data[1]) &&
|
||||
trans->sku_id[2] == le32_to_cpu(sku_id->data[2])) {
|
||||
if (sku_id[0] == tlv_sku_id->data[0] &&
|
||||
sku_id[1] == tlv_sku_id->data[1] &&
|
||||
sku_id[2] == tlv_sku_id->data[2]) {
|
||||
int ret;
|
||||
|
||||
ret = iwl_pnvm_handle_section(trans, data, len,
|
||||
@@ -263,13 +265,14 @@ static int iwl_pnvm_get_from_fs(struct iwl_trans *trans, u8 **data, size_t *len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u8 *iwl_get_pnvm_image(struct iwl_trans *trans_p, size_t *len)
|
||||
static const u8 *iwl_get_pnvm_image(struct iwl_trans *trans_p, size_t *len,
|
||||
__le32 sku_id[3], const struct iwl_fw *fw)
|
||||
{
|
||||
struct pnvm_sku_package *package;
|
||||
u8 *image = NULL;
|
||||
|
||||
/* Get PNVM from BIOS for non-Intel SKU */
|
||||
if (trans_p->sku_id[2]) {
|
||||
if (sku_id[2]) {
|
||||
package = iwl_uefi_get_pnvm(trans_p, len);
|
||||
if (!IS_ERR_OR_NULL(package)) {
|
||||
if (*len >= sizeof(*package)) {
|
||||
@@ -288,17 +291,25 @@ static u8 *iwl_get_pnvm_image(struct iwl_trans *trans_p, size_t *len)
|
||||
}
|
||||
}
|
||||
|
||||
if (fw->pnvm_data) {
|
||||
*len = fw->pnvm_size;
|
||||
|
||||
return fw->pnvm_data;
|
||||
}
|
||||
|
||||
/* If it's not available, or for Intel SKU, try from the filesystem */
|
||||
if (iwl_pnvm_get_from_fs(trans_p, &image, len))
|
||||
return NULL;
|
||||
return image;
|
||||
}
|
||||
|
||||
static void iwl_pnvm_load_pnvm_to_trans(struct iwl_trans *trans,
|
||||
const struct iwl_ucode_capabilities *capa)
|
||||
static void
|
||||
iwl_pnvm_load_pnvm_to_trans(struct iwl_trans *trans,
|
||||
const struct iwl_fw *fw,
|
||||
__le32 sku_id[3])
|
||||
{
|
||||
struct iwl_pnvm_image *pnvm_data = NULL;
|
||||
u8 *data = NULL;
|
||||
const u8 *data = NULL;
|
||||
size_t length;
|
||||
int ret;
|
||||
|
||||
@@ -309,7 +320,7 @@ static void iwl_pnvm_load_pnvm_to_trans(struct iwl_trans *trans,
|
||||
if (trans->pnvm_loaded)
|
||||
goto set;
|
||||
|
||||
data = iwl_get_pnvm_image(trans, &length);
|
||||
data = iwl_get_pnvm_image(trans, &length, sku_id, fw);
|
||||
if (!data) {
|
||||
trans->fail_to_parse_pnvm_image = true;
|
||||
return;
|
||||
@@ -319,27 +330,30 @@ static void iwl_pnvm_load_pnvm_to_trans(struct iwl_trans *trans,
|
||||
if (!pnvm_data)
|
||||
goto free;
|
||||
|
||||
ret = iwl_pnvm_parse(trans, data, length, pnvm_data);
|
||||
ret = iwl_pnvm_parse(trans, data, length, pnvm_data, sku_id);
|
||||
if (ret) {
|
||||
trans->fail_to_parse_pnvm_image = true;
|
||||
goto free;
|
||||
}
|
||||
|
||||
ret = iwl_trans_load_pnvm(trans, pnvm_data, capa);
|
||||
ret = iwl_trans_load_pnvm(trans, pnvm_data, &fw->ucode_capa);
|
||||
if (ret)
|
||||
goto free;
|
||||
IWL_INFO(trans, "loaded PNVM version %08x\n", pnvm_data->version);
|
||||
IWL_DEBUG_INFO(trans, "loaded PNVM version %08x\n", pnvm_data->version);
|
||||
|
||||
set:
|
||||
iwl_trans_set_pnvm(trans, capa);
|
||||
iwl_trans_set_pnvm(trans, &fw->ucode_capa);
|
||||
free:
|
||||
kvfree(data);
|
||||
/* free only if it was allocated, i.e. not just embedded PNVM data */
|
||||
if (data != fw->pnvm_data)
|
||||
kvfree(data);
|
||||
kfree(pnvm_data);
|
||||
}
|
||||
|
||||
static void
|
||||
iwl_pnvm_load_reduce_power_to_trans(struct iwl_trans *trans,
|
||||
const struct iwl_ucode_capabilities *capa)
|
||||
const struct iwl_ucode_capabilities *capa,
|
||||
__le32 sku_id[3])
|
||||
{
|
||||
struct iwl_pnvm_image *pnvm_data = NULL;
|
||||
u8 *data = NULL;
|
||||
@@ -362,7 +376,8 @@ iwl_pnvm_load_reduce_power_to_trans(struct iwl_trans *trans,
|
||||
if (!pnvm_data)
|
||||
goto free;
|
||||
|
||||
ret = iwl_uefi_reduce_power_parse(trans, data, length, pnvm_data);
|
||||
ret = iwl_uefi_reduce_power_parse(trans, data, length, pnvm_data,
|
||||
sku_id);
|
||||
if (ret) {
|
||||
trans->failed_to_load_reduce_power_image = true;
|
||||
goto free;
|
||||
@@ -386,18 +401,18 @@ iwl_pnvm_load_reduce_power_to_trans(struct iwl_trans *trans,
|
||||
|
||||
int iwl_pnvm_load(struct iwl_trans *trans,
|
||||
struct iwl_notif_wait_data *notif_wait,
|
||||
const struct iwl_ucode_capabilities *capa)
|
||||
const struct iwl_fw *fw, __le32 sku_id[3])
|
||||
{
|
||||
struct iwl_notification_wait pnvm_wait;
|
||||
static const u16 ntf_cmds[] = { WIDE_ID(REGULATORY_AND_NVM_GROUP,
|
||||
PNVM_INIT_COMPLETE_NTFY) };
|
||||
|
||||
/* if the SKU_ID is empty, there's nothing to do */
|
||||
if (!trans->sku_id[0] && !trans->sku_id[1] && !trans->sku_id[2])
|
||||
if (!sku_id[0] && !sku_id[1] && !sku_id[2])
|
||||
return 0;
|
||||
|
||||
iwl_pnvm_load_pnvm_to_trans(trans, capa);
|
||||
iwl_pnvm_load_reduce_power_to_trans(trans, capa);
|
||||
iwl_pnvm_load_pnvm_to_trans(trans, fw, sku_id);
|
||||
iwl_pnvm_load_reduce_power_to_trans(trans, &fw->ucode_capa, sku_id);
|
||||
|
||||
iwl_init_notification_wait(notif_wait, &pnvm_wait,
|
||||
ntf_cmds, ARRAY_SIZE(ntf_cmds),
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright(c) 2020-2023 Intel Corporation
|
||||
* Copyright(c) 2020-2023, 2025 Intel Corporation
|
||||
*/
|
||||
#ifndef __IWL_PNVM_H__
|
||||
#define __IWL_PNVM_H__
|
||||
|
||||
#include "iwl-drv.h"
|
||||
#include "fw/notif-wait.h"
|
||||
#include "fw/img.h"
|
||||
|
||||
#define MVM_UCODE_PNVM_TIMEOUT (HZ / 4)
|
||||
|
||||
@@ -14,7 +15,7 @@
|
||||
|
||||
int iwl_pnvm_load(struct iwl_trans *trans,
|
||||
struct iwl_notif_wait_data *notif_wait,
|
||||
const struct iwl_ucode_capabilities *capa);
|
||||
const struct iwl_fw *fw, __le32 sku_id[3]);
|
||||
|
||||
static inline
|
||||
void iwl_pnvm_get_fs_name(struct iwl_trans *trans,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2023 Intel Corporation
|
||||
* Copyright (C) 2023, 2025 Intel Corporation
|
||||
*/
|
||||
#if defined(__FreeBSD__)
|
||||
#include <linux/bitfield.h>
|
||||
@@ -37,11 +37,13 @@ IWL_BIOS_TABLE_LOADER(wrds_table);
|
||||
IWL_BIOS_TABLE_LOADER(ewrd_table);
|
||||
IWL_BIOS_TABLE_LOADER(wgds_table);
|
||||
IWL_BIOS_TABLE_LOADER(ppag_table);
|
||||
IWL_BIOS_TABLE_LOADER(phy_filters);
|
||||
IWL_BIOS_TABLE_LOADER_DATA(tas_table, struct iwl_tas_data);
|
||||
IWL_BIOS_TABLE_LOADER_DATA(pwr_limit, u64);
|
||||
IWL_BIOS_TABLE_LOADER_DATA(mcc, char);
|
||||
IWL_BIOS_TABLE_LOADER_DATA(eckv, u32);
|
||||
IWL_BIOS_TABLE_LOADER_DATA(wbem, u32);
|
||||
IWL_BIOS_TABLE_LOADER_DATA(dsbr, u32);
|
||||
|
||||
|
||||
static const struct dmi_system_id dmi_ppag_approved_list[] = {
|
||||
@@ -103,6 +105,11 @@ static const struct dmi_system_id dmi_ppag_approved_list[] = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "HONOR"),
|
||||
},
|
||||
},
|
||||
{ .ident = "WIKO",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "WIKO"),
|
||||
},
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -177,9 +184,9 @@ bool iwl_sar_geo_support(struct iwl_fw_runtime *fwrt)
|
||||
*/
|
||||
return IWL_UCODE_SERIAL(fwrt->fw->ucode_ver) >= 38 ||
|
||||
(IWL_UCODE_SERIAL(fwrt->fw->ucode_ver) == 17 &&
|
||||
fwrt->trans->hw_rev != CSR_HW_REV_TYPE_3160) ||
|
||||
fwrt->trans->info.hw_rev != CSR_HW_REV_TYPE_3160) ||
|
||||
(IWL_UCODE_SERIAL(fwrt->fw->ucode_ver) == 29 &&
|
||||
((fwrt->trans->hw_rev & CSR_HW_REV_TYPE_MSK) ==
|
||||
((fwrt->trans->info.hw_rev & CSR_HW_REV_TYPE_MSK) ==
|
||||
CSR_HW_REV_TYPE_7265D));
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_sar_geo_support);
|
||||
@@ -310,7 +317,7 @@ int iwl_fill_ppag_table(struct iwl_fw_runtime *fwrt,
|
||||
bool send_ppag_always;
|
||||
|
||||
/* many firmware images for JF lie about this */
|
||||
if (CSR_HW_RFID_TYPE(fwrt->trans->hw_rf_id) ==
|
||||
if (CSR_HW_RFID_TYPE(fwrt->trans->info.hw_rf_id) ==
|
||||
CSR_HW_RFID_TYPE(CSR_HW_RF_ID_TYPE_JF))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
@@ -335,31 +342,35 @@ int iwl_fill_ppag_table(struct iwl_fw_runtime *fwrt,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* The 'flags' field is the same in v1 and in v2 so we can just
|
||||
* use v1 to access it.
|
||||
*/
|
||||
cmd->v1.flags = cpu_to_le32(fwrt->ppag_flags);
|
||||
|
||||
IWL_DEBUG_RADIO(fwrt, "PPAG cmd ver is %d\n", cmd_ver);
|
||||
if (cmd_ver == 1) {
|
||||
num_sub_bands = IWL_NUM_SUB_BANDS_V1;
|
||||
gain = cmd->v1.gain[0];
|
||||
*cmd_size = sizeof(cmd->v1);
|
||||
if (fwrt->ppag_ver >= 1) {
|
||||
cmd->v1.flags = cpu_to_le32(fwrt->ppag_flags);
|
||||
if (fwrt->ppag_bios_rev >= 1) {
|
||||
/* in this case FW supports revision 0 */
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"PPAG table rev is %d, send truncated table\n",
|
||||
fwrt->ppag_ver);
|
||||
fwrt->ppag_bios_rev);
|
||||
}
|
||||
} else if (cmd_ver >= 2 && cmd_ver <= 6) {
|
||||
num_sub_bands = IWL_NUM_SUB_BANDS_V2;
|
||||
gain = cmd->v2.gain[0];
|
||||
*cmd_size = sizeof(cmd->v2);
|
||||
if (fwrt->ppag_ver == 0) {
|
||||
cmd->v2.flags = cpu_to_le32(fwrt->ppag_flags);
|
||||
if (fwrt->ppag_bios_rev == 0) {
|
||||
/* in this case FW supports revisions 1,2 or 3 */
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"PPAG table rev is 0, send padded table\n");
|
||||
}
|
||||
} else if (cmd_ver == 7) {
|
||||
num_sub_bands = IWL_NUM_SUB_BANDS_V2;
|
||||
gain = cmd->v3.gain[0];
|
||||
*cmd_size = sizeof(cmd->v3);
|
||||
cmd->v3.ppag_config_info.table_source = fwrt->ppag_bios_source;
|
||||
cmd->v3.ppag_config_info.table_revision = fwrt->ppag_bios_rev;
|
||||
cmd->v3.ppag_config_info.value = cpu_to_le32(fwrt->ppag_flags);
|
||||
} else {
|
||||
IWL_DEBUG_RADIO(fwrt, "Unsupported PPAG command version\n");
|
||||
return -EINVAL;
|
||||
@@ -368,9 +379,11 @@ int iwl_fill_ppag_table(struct iwl_fw_runtime *fwrt,
|
||||
/* ppag mode */
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"PPAG MODE bits were read from bios: %d\n",
|
||||
le32_to_cpu(cmd->v1.flags));
|
||||
fwrt->ppag_flags);
|
||||
|
||||
if (cmd_ver == 5)
|
||||
if (cmd_ver == 6)
|
||||
cmd->v1.flags &= cpu_to_le32(IWL_PPAG_CMD_V6_MASK);
|
||||
else if (cmd_ver == 5)
|
||||
cmd->v1.flags &= cpu_to_le32(IWL_PPAG_CMD_V5_MASK);
|
||||
else if (cmd_ver < 5)
|
||||
cmd->v1.flags &= cpu_to_le32(IWL_PPAG_CMD_V4_MASK);
|
||||
@@ -378,16 +391,20 @@ int iwl_fill_ppag_table(struct iwl_fw_runtime *fwrt,
|
||||
if ((cmd_ver == 1 &&
|
||||
!fw_has_capa(&fwrt->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_PPAG_CHINA_BIOS_SUPPORT)) ||
|
||||
(cmd_ver == 2 && fwrt->ppag_ver >= 2)) {
|
||||
(cmd_ver == 2 && fwrt->ppag_bios_rev >= 2)) {
|
||||
cmd->v1.flags &= cpu_to_le32(IWL_PPAG_ETSI_MASK);
|
||||
IWL_DEBUG_RADIO(fwrt, "masking ppag China bit\n");
|
||||
} else {
|
||||
IWL_DEBUG_RADIO(fwrt, "isn't masking ppag China bit\n");
|
||||
}
|
||||
|
||||
/* The 'flags' field is the same in v1 and v2 so we can just
|
||||
* use v1 to access it.
|
||||
*/
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"PPAG MODE bits going to be sent: %d\n",
|
||||
le32_to_cpu(cmd->v1.flags));
|
||||
(cmd_ver < 7) ? le32_to_cpu(cmd->v1.flags) :
|
||||
le32_to_cpu(cmd->v3.ppag_config_info.value));
|
||||
|
||||
for (i = 0; i < IWL_NUM_CHAIN_LIMITS; i++) {
|
||||
for (j = 0; j < num_sub_bands; j++) {
|
||||
@@ -427,33 +444,57 @@ bool iwl_is_tas_approved(void)
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_is_tas_approved);
|
||||
|
||||
int iwl_parse_tas_selection(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_tas_data *tas_data,
|
||||
const u32 tas_selection)
|
||||
struct iwl_tas_selection_data
|
||||
iwl_parse_tas_selection(const u32 tas_selection_in, const u8 tbl_rev)
|
||||
{
|
||||
u8 override_iec = u32_get_bits(tas_selection,
|
||||
struct iwl_tas_selection_data tas_selection_out = {};
|
||||
u8 override_iec = u32_get_bits(tas_selection_in,
|
||||
IWL_WTAS_OVERRIDE_IEC_MSK);
|
||||
u8 enabled_iec = u32_get_bits(tas_selection, IWL_WTAS_ENABLE_IEC_MSK);
|
||||
u8 usa_tas_uhb = u32_get_bits(tas_selection, IWL_WTAS_USA_UHB_MSK);
|
||||
int enabled = tas_selection & IWL_WTAS_ENABLED_MSK;
|
||||
u8 canada_tas_uhb = u32_get_bits(tas_selection_in,
|
||||
IWL_WTAS_CANADA_UHB_MSK);
|
||||
u8 enabled_iec = u32_get_bits(tas_selection_in,
|
||||
IWL_WTAS_ENABLE_IEC_MSK);
|
||||
u8 usa_tas_uhb = u32_get_bits(tas_selection_in,
|
||||
IWL_WTAS_USA_UHB_MSK);
|
||||
|
||||
IWL_DEBUG_RADIO(fwrt, "TAS selection as read from BIOS: 0x%x\n",
|
||||
tas_selection);
|
||||
if (tbl_rev > 0) {
|
||||
tas_selection_out.usa_tas_uhb_allowed = usa_tas_uhb;
|
||||
tas_selection_out.override_tas_iec = override_iec;
|
||||
tas_selection_out.enable_tas_iec = enabled_iec;
|
||||
}
|
||||
|
||||
tas_data->usa_tas_uhb_allowed = usa_tas_uhb;
|
||||
tas_data->override_tas_iec = override_iec;
|
||||
tas_data->enable_tas_iec = enabled_iec;
|
||||
if (tbl_rev > 1)
|
||||
tas_selection_out.canada_tas_uhb_allowed = canada_tas_uhb;
|
||||
|
||||
return enabled;
|
||||
return tas_selection_out;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_parse_tas_selection);
|
||||
|
||||
static __le32 iwl_get_lari_config_bitmap(struct iwl_fw_runtime *fwrt)
|
||||
bool iwl_add_mcc_to_tas_block_list(u16 *list, u8 *size, u16 mcc)
|
||||
{
|
||||
for (int i = 0; i < *size; i++) {
|
||||
if (list[i] == mcc)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Verify that there is room for another country
|
||||
* If *size == IWL_WTAS_BLACK_LIST_MAX, then the table is full.
|
||||
*/
|
||||
if (*size >= IWL_WTAS_BLACK_LIST_MAX)
|
||||
return false;
|
||||
|
||||
list[*size++] = mcc;
|
||||
return true;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_add_mcc_to_tas_block_list);
|
||||
|
||||
__le32 iwl_get_lari_config_bitmap(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
int ret;
|
||||
u32 val;
|
||||
__le32 config_bitmap = 0;
|
||||
|
||||
switch (CSR_HW_RFID_TYPE(fwrt->trans->hw_rf_id)) {
|
||||
switch (CSR_HW_RFID_TYPE(fwrt->trans->info.hw_rf_id)) {
|
||||
case IWL_CFG_RF_TYPE_HR1:
|
||||
case IWL_CFG_RF_TYPE_HR2:
|
||||
case IWL_CFG_RF_TYPE_JF1:
|
||||
@@ -494,6 +535,7 @@ static __le32 iwl_get_lari_config_bitmap(struct iwl_fw_runtime *fwrt)
|
||||
|
||||
return config_bitmap;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_get_lari_config_bitmap);
|
||||
|
||||
static size_t iwl_get_lari_config_cmd_size(u8 cmd_ver)
|
||||
{
|
||||
@@ -540,34 +582,61 @@ int iwl_fill_lari_config(struct iwl_fw_runtime *fwrt,
|
||||
{
|
||||
int ret;
|
||||
u32 value;
|
||||
bool has_raw_dsm_capa = fw_has_capa(&fwrt->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_FW_ACCEPTS_RAW_DSM_TABLE);
|
||||
u8 cmd_ver = iwl_fw_lookup_cmd_ver(fwrt->fw,
|
||||
WIDE_ID(REGULATORY_AND_NVM_GROUP,
|
||||
LARI_CONFIG_CHANGE), 1);
|
||||
|
||||
if (WARN_ONCE(cmd_ver > 12,
|
||||
"Don't add newer versions to this function\n"))
|
||||
return -EINVAL;
|
||||
|
||||
memset(cmd, 0, sizeof(*cmd));
|
||||
*cmd_size = iwl_get_lari_config_cmd_size(cmd_ver);
|
||||
|
||||
cmd->config_bitmap = iwl_get_lari_config_bitmap(fwrt);
|
||||
|
||||
ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_11AX_ENABLEMENT, &value);
|
||||
if (!ret)
|
||||
if (!ret) {
|
||||
if (!has_raw_dsm_capa)
|
||||
value &= DSM_11AX_ALLOW_BITMAP;
|
||||
cmd->oem_11ax_allow_bitmap = cpu_to_le32(value);
|
||||
}
|
||||
|
||||
ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENABLE_UNII4_CHAN, &value);
|
||||
if (!ret) {
|
||||
if (cmd_ver < 9)
|
||||
value &= DSM_UNII4_ALLOW_BITMAP_CMD_V8;
|
||||
else
|
||||
if (!has_raw_dsm_capa)
|
||||
value &= DSM_UNII4_ALLOW_BITMAP;
|
||||
|
||||
/* Since version 9, bits 4 and 5 are supported
|
||||
* regardless of this capability, By pass this masking
|
||||
* if firmware has capability of accepting raw DSM table.
|
||||
*/
|
||||
if (!has_raw_dsm_capa && cmd_ver < 9 &&
|
||||
!fw_has_capa(&fwrt->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_BIOS_OVERRIDE_5G9_FOR_CA))
|
||||
value &= ~(DSM_VALUE_UNII4_CANADA_OVERRIDE_MSK |
|
||||
DSM_VALUE_UNII4_CANADA_EN_MSK);
|
||||
|
||||
cmd->oem_unii4_allow_bitmap = cpu_to_le32(value);
|
||||
}
|
||||
|
||||
ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ACTIVATE_CHANNEL, &value);
|
||||
if (!ret) {
|
||||
if (cmd_ver < 8)
|
||||
if (!has_raw_dsm_capa)
|
||||
value &= CHAN_STATE_ACTIVE_BITMAP_CMD_V12;
|
||||
|
||||
if (!has_raw_dsm_capa && cmd_ver < 8)
|
||||
value &= ~ACTIVATE_5G2_IN_WW_MASK;
|
||||
if (cmd_ver < 12)
|
||||
|
||||
/* Since version 12, bits 5 and 6 are supported
|
||||
* regardless of this capability, By pass this masking
|
||||
* if firmware has capability of accepting raw DSM table.
|
||||
*/
|
||||
if (!has_raw_dsm_capa && cmd_ver < 12 &&
|
||||
!fw_has_capa(&fwrt->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_BIOS_OVERRIDE_UNII4_US_CA))
|
||||
value &= CHAN_STATE_ACTIVE_BITMAP_CMD_V11;
|
||||
|
||||
cmd->chan_state_active_bitmap = cpu_to_le32(value);
|
||||
@@ -578,13 +647,19 @@ int iwl_fill_lari_config(struct iwl_fw_runtime *fwrt,
|
||||
cmd->oem_uhb_allow_bitmap = cpu_to_le32(value);
|
||||
|
||||
ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_FORCE_DISABLE_CHANNELS, &value);
|
||||
if (!ret)
|
||||
if (!ret) {
|
||||
if (!has_raw_dsm_capa)
|
||||
value &= DSM_FORCE_DISABLE_CHANNELS_ALLOWED_BITMAP;
|
||||
cmd->force_disable_channels_bitmap = cpu_to_le32(value);
|
||||
}
|
||||
|
||||
ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENERGY_DETECTION_THRESHOLD,
|
||||
&value);
|
||||
if (!ret)
|
||||
if (!ret) {
|
||||
if (!has_raw_dsm_capa)
|
||||
value &= DSM_EDT_ALLOWED_BITMAP;
|
||||
cmd->edt_bitmap = cpu_to_le32(value);
|
||||
}
|
||||
|
||||
ret = iwl_bios_get_wbem(fwrt, &value);
|
||||
if (!ret)
|
||||
@@ -637,3 +712,50 @@ int iwl_bios_get_dsm(struct iwl_fw_runtime *fwrt, enum iwl_dsm_funcs func,
|
||||
GET_BIOS_TABLE(dsm, fwrt, func, value);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_bios_get_dsm);
|
||||
|
||||
bool iwl_puncturing_is_allowed_in_bios(u32 puncturing, u16 mcc)
|
||||
{
|
||||
/* Some kind of regulatory mess means we need to currently disallow
|
||||
* puncturing in the US and Canada unless enabled in BIOS.
|
||||
*/
|
||||
switch (mcc) {
|
||||
case IWL_MCC_US:
|
||||
return puncturing & IWL_UEFI_CNV_PUNCTURING_USA_EN_MSK;
|
||||
case IWL_MCC_CANADA:
|
||||
return puncturing & IWL_UEFI_CNV_PUNCTURING_CANADA_EN_MSK;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_puncturing_is_allowed_in_bios);
|
||||
|
||||
bool iwl_rfi_is_enabled_in_bios(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
/* default behaviour is disabled */
|
||||
u32 value = 0;
|
||||
int ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_RFI_CONFIG, &value);
|
||||
|
||||
if (ret < 0) {
|
||||
IWL_DEBUG_RADIO(fwrt, "Failed to get DSM RFI, ret=%d\n", ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
value &= DSM_VALUE_RFI_DISABLE;
|
||||
/* RFI BIOS CONFIG value can be 0 or 3 only.
|
||||
* i.e 0 means DDR and DLVR enabled. 3 means DDR and DLVR disabled.
|
||||
* 1 and 2 are invalid BIOS configurations, So, it's not possible to
|
||||
* disable ddr/dlvr separately.
|
||||
*/
|
||||
if (!value) {
|
||||
IWL_DEBUG_RADIO(fwrt, "DSM RFI is evaluated to enable\n");
|
||||
return true;
|
||||
} else if (value == DSM_VALUE_RFI_DISABLE) {
|
||||
IWL_DEBUG_RADIO(fwrt, "DSM RFI is evaluated to disable\n");
|
||||
} else {
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"DSM RFI got invalid value, value=%d\n", value);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_rfi_is_enabled_in_bios);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2023-2024 Intel Corporation
|
||||
* Copyright (C) 2023-2025 Intel Corporation
|
||||
*/
|
||||
|
||||
#ifndef __fw_regulatory_h__
|
||||
@@ -40,11 +40,21 @@
|
||||
#define IWL_PPAG_ETSI_CHINA_MASK 3
|
||||
#define IWL_PPAG_REV3_MASK 0x7FF
|
||||
|
||||
#define IWL_WTAS_ENABLED_MSK 0x1
|
||||
#define IWL_WTAS_OVERRIDE_IEC_MSK 0x2
|
||||
#define IWL_WTAS_ENABLE_IEC_MSK 0x4
|
||||
#define IWL_WTAS_ENABLED_MSK BIT(0)
|
||||
#define IWL_WTAS_OVERRIDE_IEC_MSK BIT(1)
|
||||
#define IWL_WTAS_ENABLE_IEC_MSK BIT(2)
|
||||
#define IWL_WTAS_CANADA_UHB_MSK BIT(15)
|
||||
#define IWL_WTAS_USA_UHB_MSK BIT(16)
|
||||
|
||||
struct iwl_tas_selection_data {
|
||||
u8 override_tas_iec:1,
|
||||
enable_tas_iec:1,
|
||||
usa_tas_uhb_allowed:1,
|
||||
canada_tas_uhb_allowed:1;
|
||||
};
|
||||
|
||||
#define BIOS_MCC_CHINA 0x434e
|
||||
|
||||
/*
|
||||
* The profile for revision 2 is a superset of revision 1, which is in
|
||||
* turn a superset of revision 0. So we can store all revisions
|
||||
@@ -95,11 +105,11 @@ struct iwl_ppag_chain {
|
||||
};
|
||||
|
||||
struct iwl_tas_data {
|
||||
__le32 block_list_size;
|
||||
__le32 block_list_array[IWL_WTAS_BLACK_LIST_MAX];
|
||||
u8 override_tas_iec;
|
||||
u8 enable_tas_iec;
|
||||
u8 usa_tas_uhb_allowed;
|
||||
u8 block_list_size;
|
||||
u16 block_list_array[IWL_WTAS_BLACK_LIST_MAX];
|
||||
u8 table_source;
|
||||
u8 table_revision;
|
||||
u32 tas_selection;
|
||||
};
|
||||
|
||||
/* For DSM revision 0 and 4 */
|
||||
@@ -142,14 +152,17 @@ enum iwl_dsm_unii4_bitmap {
|
||||
DSM_VALUE_UNII4_CANADA_EN_MSK = BIT(5),
|
||||
};
|
||||
|
||||
#define DSM_UNII4_ALLOW_BITMAP_CMD_V8 (DSM_VALUE_UNII4_US_OVERRIDE_MSK | \
|
||||
DSM_VALUE_UNII4_US_EN_MSK | \
|
||||
DSM_VALUE_UNII4_ETSI_OVERRIDE_MSK | \
|
||||
DSM_VALUE_UNII4_ETSI_EN_MSK)
|
||||
#define DSM_UNII4_ALLOW_BITMAP (DSM_UNII4_ALLOW_BITMAP_CMD_V8 | \
|
||||
DSM_VALUE_UNII4_CANADA_OVERRIDE_MSK | \
|
||||
#define DSM_UNII4_ALLOW_BITMAP (DSM_VALUE_UNII4_US_OVERRIDE_MSK |\
|
||||
DSM_VALUE_UNII4_US_EN_MSK |\
|
||||
DSM_VALUE_UNII4_ETSI_OVERRIDE_MSK |\
|
||||
DSM_VALUE_UNII4_ETSI_EN_MSK |\
|
||||
DSM_VALUE_UNII4_CANADA_OVERRIDE_MSK |\
|
||||
DSM_VALUE_UNII4_CANADA_EN_MSK)
|
||||
|
||||
#define DSM_11AX_ALLOW_BITMAP 0xF
|
||||
#define DSM_EDT_ALLOWED_BITMAP 0x7ffff0
|
||||
#define DSM_FORCE_DISABLE_CHANNELS_ALLOWED_BITMAP 0x7FF
|
||||
|
||||
enum iwl_dsm_values_rfi {
|
||||
DSM_VALUE_RFI_DLVR_DISABLE = BIT(0),
|
||||
DSM_VALUE_RFI_DDR_DISABLE = BIT(1),
|
||||
@@ -158,6 +171,8 @@ enum iwl_dsm_values_rfi {
|
||||
#define DSM_VALUE_RFI_DISABLE (DSM_VALUE_RFI_DLVR_DISABLE |\
|
||||
DSM_VALUE_RFI_DDR_DISABLE)
|
||||
|
||||
bool iwl_rfi_is_enabled_in_bios(struct iwl_fw_runtime *fwrt);
|
||||
|
||||
enum iwl_dsm_masks_reg {
|
||||
DSM_MASK_CHINA_22_REG = BIT(2)
|
||||
};
|
||||
@@ -181,10 +196,10 @@ int iwl_fill_ppag_table(struct iwl_fw_runtime *fwrt,
|
||||
bool iwl_is_ppag_approved(struct iwl_fw_runtime *fwrt);
|
||||
|
||||
bool iwl_is_tas_approved(void);
|
||||
bool iwl_add_mcc_to_tas_block_list(u16 *list, u8 *size, u16 mcc);
|
||||
|
||||
int iwl_parse_tas_selection(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_tas_data *tas_data,
|
||||
const u32 tas_selection);
|
||||
struct iwl_tas_selection_data
|
||||
iwl_parse_tas_selection(const u32 tas_selection, const u8 tbl_rev);
|
||||
|
||||
int iwl_bios_get_wrds_table(struct iwl_fw_runtime *fwrt);
|
||||
|
||||
@@ -204,6 +219,7 @@ int iwl_bios_get_mcc(struct iwl_fw_runtime *fwrt, char *mcc);
|
||||
int iwl_bios_get_eckv(struct iwl_fw_runtime *fwrt, u32 *ext_clk);
|
||||
int iwl_bios_get_wbem(struct iwl_fw_runtime *fwrt, u32 *value);
|
||||
|
||||
__le32 iwl_get_lari_config_bitmap(struct iwl_fw_runtime *fwrt);
|
||||
int iwl_fill_lari_config(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_lari_config_change_cmd *cmd,
|
||||
size_t *cmd_size);
|
||||
@@ -212,9 +228,41 @@ int iwl_bios_get_dsm(struct iwl_fw_runtime *fwrt, enum iwl_dsm_funcs func,
|
||||
u32 *value);
|
||||
|
||||
static inline u32 iwl_bios_get_ppag_flags(const u32 ppag_modes,
|
||||
const u8 ppag_ver)
|
||||
const u8 ppag_bios_rev)
|
||||
{
|
||||
return ppag_modes & (ppag_ver < 3 ? IWL_PPAG_ETSI_CHINA_MASK :
|
||||
IWL_PPAG_REV3_MASK);
|
||||
/* For revision 4 and above driver is pipe */
|
||||
if (ppag_bios_rev >= 4)
|
||||
return ppag_modes;
|
||||
|
||||
return ppag_modes & (ppag_bios_rev < 3 ? IWL_PPAG_ETSI_CHINA_MASK :
|
||||
IWL_PPAG_REV3_MASK);
|
||||
}
|
||||
|
||||
bool iwl_puncturing_is_allowed_in_bios(u32 puncturing, u16 mcc);
|
||||
|
||||
#define IWL_DSBR_FW_MODIFIED_URM_MASK BIT(8)
|
||||
#define IWL_DSBR_PERMANENT_URM_MASK BIT(9)
|
||||
|
||||
int iwl_bios_get_dsbr(struct iwl_fw_runtime *fwrt, u32 *value);
|
||||
int iwl_bios_get_phy_filters(struct iwl_fw_runtime *fwrt);
|
||||
|
||||
static inline void iwl_bios_setup_step(struct iwl_trans *trans,
|
||||
struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
u32 dsbr;
|
||||
|
||||
if (!trans->mac_cfg->integrated)
|
||||
return;
|
||||
|
||||
if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_BZ)
|
||||
return;
|
||||
|
||||
if (iwl_bios_get_dsbr(fwrt, &dsbr))
|
||||
dsbr = 0;
|
||||
|
||||
trans->conf.dsbr_urm_fw_dependent =
|
||||
!!(dsbr & IWL_DSBR_FW_MODIFIED_URM_MASK);
|
||||
trans->conf.dsbr_urm_permanent =
|
||||
!!(dsbr & IWL_DSBR_PERMANENT_URM_MASK);
|
||||
}
|
||||
#endif /* __fw_regulatory_h__ */
|
||||
|
||||
+25
-120
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2021-2022 Intel Corporation
|
||||
* Copyright (C) 2021-2022, 2025 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <net/mac80211.h>
|
||||
@@ -91,104 +91,6 @@ const char *iwl_rs_pretty_bw(int bw)
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_rs_pretty_bw);
|
||||
|
||||
static u32 iwl_legacy_rate_to_fw_idx(u32 rate_n_flags)
|
||||
{
|
||||
int rate = rate_n_flags & RATE_LEGACY_RATE_MSK_V1;
|
||||
int idx;
|
||||
bool ofdm = !(rate_n_flags & RATE_MCS_CCK_MSK_V1);
|
||||
int offset = ofdm ? IWL_FIRST_OFDM_RATE : 0;
|
||||
int last = ofdm ? IWL_RATE_COUNT_LEGACY : IWL_FIRST_OFDM_RATE;
|
||||
|
||||
for (idx = offset; idx < last; idx++)
|
||||
if (iwl_fw_rate_idx_to_plcp(idx) == rate)
|
||||
return idx - offset;
|
||||
return IWL_RATE_INVALID;
|
||||
}
|
||||
|
||||
u32 iwl_new_rate_from_v1(u32 rate_v1)
|
||||
{
|
||||
u32 rate_v2 = 0;
|
||||
u32 dup = 0;
|
||||
|
||||
if (rate_v1 == 0)
|
||||
return rate_v1;
|
||||
/* convert rate */
|
||||
if (rate_v1 & RATE_MCS_HT_MSK_V1) {
|
||||
u32 nss = 0;
|
||||
|
||||
rate_v2 |= RATE_MCS_HT_MSK;
|
||||
rate_v2 |=
|
||||
rate_v1 & RATE_HT_MCS_RATE_CODE_MSK_V1;
|
||||
nss = (rate_v1 & RATE_HT_MCS_MIMO2_MSK) >>
|
||||
RATE_HT_MCS_NSS_POS_V1;
|
||||
rate_v2 |= nss << RATE_MCS_NSS_POS;
|
||||
} else if (rate_v1 & RATE_MCS_VHT_MSK_V1 ||
|
||||
rate_v1 & RATE_MCS_HE_MSK_V1) {
|
||||
rate_v2 |= rate_v1 & RATE_VHT_MCS_RATE_CODE_MSK;
|
||||
|
||||
rate_v2 |= rate_v1 & RATE_MCS_NSS_MSK;
|
||||
|
||||
if (rate_v1 & RATE_MCS_HE_MSK_V1) {
|
||||
u32 he_type_bits = rate_v1 & RATE_MCS_HE_TYPE_MSK_V1;
|
||||
u32 he_type = he_type_bits >> RATE_MCS_HE_TYPE_POS_V1;
|
||||
u32 he_106t = (rate_v1 & RATE_MCS_HE_106T_MSK_V1) >>
|
||||
RATE_MCS_HE_106T_POS_V1;
|
||||
u32 he_gi_ltf = (rate_v1 & RATE_MCS_HE_GI_LTF_MSK_V1) >>
|
||||
RATE_MCS_HE_GI_LTF_POS;
|
||||
|
||||
if ((he_type_bits == RATE_MCS_HE_TYPE_SU ||
|
||||
he_type_bits == RATE_MCS_HE_TYPE_EXT_SU) &&
|
||||
he_gi_ltf == RATE_MCS_HE_SU_4_LTF)
|
||||
/* the new rate have an additional bit to
|
||||
* represent the value 4 rather then using SGI
|
||||
* bit for this purpose - as it was done in the old
|
||||
* rate */
|
||||
he_gi_ltf += (rate_v1 & RATE_MCS_SGI_MSK_V1) >>
|
||||
RATE_MCS_SGI_POS_V1;
|
||||
|
||||
rate_v2 |= he_gi_ltf << RATE_MCS_HE_GI_LTF_POS;
|
||||
rate_v2 |= he_type << RATE_MCS_HE_TYPE_POS;
|
||||
rate_v2 |= he_106t << RATE_MCS_HE_106T_POS;
|
||||
rate_v2 |= rate_v1 & RATE_HE_DUAL_CARRIER_MODE_MSK;
|
||||
rate_v2 |= RATE_MCS_HE_MSK;
|
||||
} else {
|
||||
rate_v2 |= RATE_MCS_VHT_MSK;
|
||||
}
|
||||
/* if legacy format */
|
||||
} else {
|
||||
u32 legacy_rate = iwl_legacy_rate_to_fw_idx(rate_v1);
|
||||
|
||||
if (WARN_ON_ONCE(legacy_rate == IWL_RATE_INVALID))
|
||||
legacy_rate = (rate_v1 & RATE_MCS_CCK_MSK_V1) ?
|
||||
IWL_FIRST_CCK_RATE : IWL_FIRST_OFDM_RATE;
|
||||
|
||||
rate_v2 |= legacy_rate;
|
||||
if (!(rate_v1 & RATE_MCS_CCK_MSK_V1))
|
||||
rate_v2 |= RATE_MCS_LEGACY_OFDM_MSK;
|
||||
}
|
||||
|
||||
/* convert flags */
|
||||
if (rate_v1 & RATE_MCS_LDPC_MSK_V1)
|
||||
rate_v2 |= RATE_MCS_LDPC_MSK;
|
||||
rate_v2 |= (rate_v1 & RATE_MCS_CHAN_WIDTH_MSK_V1) |
|
||||
(rate_v1 & RATE_MCS_ANT_AB_MSK) |
|
||||
(rate_v1 & RATE_MCS_STBC_MSK) |
|
||||
(rate_v1 & RATE_MCS_BF_MSK);
|
||||
|
||||
dup = (rate_v1 & RATE_MCS_DUP_MSK_V1) >> RATE_MCS_DUP_POS_V1;
|
||||
if (dup) {
|
||||
rate_v2 |= RATE_MCS_DUP_MSK;
|
||||
rate_v2 |= dup << RATE_MCS_CHAN_WIDTH_POS;
|
||||
}
|
||||
|
||||
if ((!(rate_v1 & RATE_MCS_HE_MSK_V1)) &&
|
||||
(rate_v1 & RATE_MCS_SGI_MSK_V1))
|
||||
rate_v2 |= RATE_MCS_SGI_MSK;
|
||||
|
||||
return rate_v2;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_new_rate_from_v1);
|
||||
|
||||
int rs_pretty_print_rate(char *buf, int bufsz, const u32 rate)
|
||||
{
|
||||
char *type;
|
||||
@@ -197,37 +99,40 @@ int rs_pretty_print_rate(char *buf, int bufsz, const u32 rate)
|
||||
u32 bw = (rate & RATE_MCS_CHAN_WIDTH_MSK) >>
|
||||
RATE_MCS_CHAN_WIDTH_POS;
|
||||
u32 format = rate & RATE_MCS_MOD_TYPE_MSK;
|
||||
int index = 0;
|
||||
bool sgi;
|
||||
|
||||
if (format == RATE_MCS_CCK_MSK ||
|
||||
format == RATE_MCS_LEGACY_OFDM_MSK) {
|
||||
int legacy_rate = rate & RATE_LEGACY_RATE_MSK;
|
||||
int index = format == RATE_MCS_CCK_MSK ?
|
||||
legacy_rate :
|
||||
legacy_rate + IWL_FIRST_OFDM_RATE;
|
||||
switch (format) {
|
||||
case RATE_MCS_MOD_TYPE_LEGACY_OFDM:
|
||||
index = IWL_FIRST_OFDM_RATE;
|
||||
fallthrough;
|
||||
case RATE_MCS_MOD_TYPE_CCK:
|
||||
index += rate & RATE_LEGACY_RATE_MSK;
|
||||
|
||||
return scnprintf(buf, bufsz, "Legacy | ANT: %s Rate: %s Mbps",
|
||||
iwl_rs_pretty_ant(ant),
|
||||
iwl_rate_mcs(index)->mbps);
|
||||
case RATE_MCS_MOD_TYPE_VHT:
|
||||
type = "VHT";
|
||||
break;
|
||||
case RATE_MCS_MOD_TYPE_HT:
|
||||
type = "HT";
|
||||
break;
|
||||
case RATE_MCS_MOD_TYPE_HE:
|
||||
type = "HE";
|
||||
break;
|
||||
case RATE_MCS_MOD_TYPE_EHT:
|
||||
type = "EHT";
|
||||
break;
|
||||
default:
|
||||
type = "Unknown"; /* shouldn't happen */
|
||||
}
|
||||
|
||||
if (format == RATE_MCS_VHT_MSK)
|
||||
type = "VHT";
|
||||
else if (format == RATE_MCS_HT_MSK)
|
||||
type = "HT";
|
||||
else if (format == RATE_MCS_HE_MSK)
|
||||
type = "HE";
|
||||
else if (format == RATE_MCS_EHT_MSK)
|
||||
type = "EHT";
|
||||
else
|
||||
type = "Unknown"; /* shouldn't happen */
|
||||
|
||||
mcs = format == RATE_MCS_HT_MSK ?
|
||||
mcs = format == RATE_MCS_MOD_TYPE_HT ?
|
||||
RATE_HT_MCS_INDEX(rate) :
|
||||
rate & RATE_MCS_CODE_MSK;
|
||||
nss = ((rate & RATE_MCS_NSS_MSK)
|
||||
>> RATE_MCS_NSS_POS) + 1;
|
||||
sgi = format == RATE_MCS_HE_MSK ?
|
||||
nss = u32_get_bits(rate, RATE_MCS_NSS_MSK);
|
||||
sgi = format == RATE_MCS_MOD_TYPE_HE ?
|
||||
iwl_he_is_sgi(rate) :
|
||||
rate & RATE_MCS_SGI_MSK;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018-2024 Intel Corporation
|
||||
* Copyright (C) 2018-2025 Intel Corporation
|
||||
*/
|
||||
#ifndef __iwl_fw_runtime_h__
|
||||
#define __iwl_fw_runtime_h__
|
||||
@@ -104,11 +104,19 @@ struct iwl_txf_iter_data {
|
||||
* the driver by calling &iwl_fw_set_current_image()
|
||||
* @dump: debug dump data
|
||||
* @uats_table: AP type table
|
||||
* @uats_valid: is AP type table valid
|
||||
* @uefi_tables_lock_status: The status of the WIFI GUID UEFI variables lock:
|
||||
* 0: Unlocked, 1 and 2: Locked.
|
||||
* Only read the UEFI variables if locked.
|
||||
* @sar_profiles: sar profiles as read from WRDS/EWRD BIOS tables
|
||||
* @geo_profiles: geographic profiles as read from WGDS BIOS table
|
||||
* @phy_filters: specific phy filters as read from WPFC BIOS table
|
||||
* @ppag_bios_rev: PPAG BIOS revision
|
||||
* @ppag_bios_source: see &enum bios_source
|
||||
* @acpi_dsm_funcs_valid: bitmap indicating which DSM values are valid,
|
||||
* zero (default initialization) means it hasn't been read yet,
|
||||
* and BIT(0) is set when it has since function 0 also has this
|
||||
* bitmap and is always supported
|
||||
*/
|
||||
struct iwl_fw_runtime {
|
||||
struct iwl_trans *trans;
|
||||
@@ -177,11 +185,18 @@ struct iwl_fw_runtime {
|
||||
bool geo_enabled;
|
||||
struct iwl_ppag_chain ppag_chains[IWL_NUM_CHAIN_LIMITS];
|
||||
u32 ppag_flags;
|
||||
u8 ppag_ver;
|
||||
u8 ppag_bios_rev;
|
||||
u8 ppag_bios_source;
|
||||
struct iwl_sar_offset_mapping_cmd sgom_table;
|
||||
bool sgom_enabled;
|
||||
struct iwl_mcc_allowed_ap_type_cmd uats_table;
|
||||
bool uats_valid;
|
||||
u8 uefi_tables_lock_status;
|
||||
struct iwl_phy_specific_cfg phy_filters;
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
u32 acpi_dsm_funcs_valid;
|
||||
#endif
|
||||
};
|
||||
|
||||
void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2021 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2021, 2025 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
@@ -102,7 +102,7 @@ void iwl_get_shared_mem_conf(struct iwl_fw_runtime *fwrt)
|
||||
}
|
||||
|
||||
pkt = cmd.resp_pkt;
|
||||
if (fwrt->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000)
|
||||
if (fwrt->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_22000)
|
||||
iwl_parse_shared_mem_22000(fwrt, pkt);
|
||||
else
|
||||
iwl_parse_shared_mem(fwrt, pkt);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright(c) 2021-2024 Intel Corporation
|
||||
* Copyright(c) 2021-2025 Intel Corporation
|
||||
*/
|
||||
|
||||
#include "iwl-drv.h"
|
||||
@@ -13,9 +13,12 @@
|
||||
#include <linux/efi.h>
|
||||
#include "fw/runtime.h"
|
||||
|
||||
#define IWL_EFI_VAR_GUID EFI_GUID(0x92daaf2f, 0xc02b, 0x455b, \
|
||||
0xb2, 0xec, 0xf5, 0xa3, \
|
||||
0x59, 0x4f, 0x4a, 0xea)
|
||||
#define IWL_EFI_WIFI_GUID EFI_GUID(0x92daaf2f, 0xc02b, 0x455b, \
|
||||
0xb2, 0xec, 0xf5, 0xa3, \
|
||||
0x59, 0x4f, 0x4a, 0xea)
|
||||
#define IWL_EFI_WIFI_BT_GUID EFI_GUID(0xe65d8884, 0xd4af, 0x4b20, \
|
||||
0x8d, 0x03, 0x77, 0x2e, \
|
||||
0xcc, 0x3d, 0xa5, 0x31)
|
||||
|
||||
struct iwl_uefi_pnvm_mem_desc {
|
||||
__le32 addr;
|
||||
@@ -61,7 +64,7 @@ void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len)
|
||||
|
||||
*len = 0;
|
||||
|
||||
data = iwl_uefi_get_variable(IWL_UEFI_OEM_PNVM_NAME, &IWL_EFI_VAR_GUID,
|
||||
data = iwl_uefi_get_variable(IWL_UEFI_OEM_PNVM_NAME, &IWL_EFI_WIFI_GUID,
|
||||
&package_size);
|
||||
if (IS_ERR(data)) {
|
||||
IWL_DEBUG_FW(trans,
|
||||
@@ -76,18 +79,18 @@ void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len)
|
||||
return data;
|
||||
}
|
||||
|
||||
static
|
||||
void *iwl_uefi_get_verified_variable(struct iwl_trans *trans,
|
||||
efi_char16_t *uefi_var_name,
|
||||
char *var_name,
|
||||
unsigned int expected_size,
|
||||
unsigned long *size)
|
||||
static void *
|
||||
iwl_uefi_get_verified_variable_guid(struct iwl_trans *trans,
|
||||
efi_guid_t *guid,
|
||||
efi_char16_t *uefi_var_name,
|
||||
char *var_name,
|
||||
unsigned int expected_size,
|
||||
unsigned long *size)
|
||||
{
|
||||
void *var;
|
||||
unsigned long var_size;
|
||||
|
||||
var = iwl_uefi_get_variable(uefi_var_name, &IWL_EFI_VAR_GUID,
|
||||
&var_size);
|
||||
var = iwl_uefi_get_variable(uefi_var_name, guid, &var_size);
|
||||
|
||||
if (IS_ERR(var)) {
|
||||
IWL_DEBUG_RADIO(trans,
|
||||
@@ -112,6 +115,18 @@ void *iwl_uefi_get_verified_variable(struct iwl_trans *trans,
|
||||
return var;
|
||||
}
|
||||
|
||||
static void *
|
||||
iwl_uefi_get_verified_variable(struct iwl_trans *trans,
|
||||
efi_char16_t *uefi_var_name,
|
||||
char *var_name,
|
||||
unsigned int expected_size,
|
||||
unsigned long *size)
|
||||
{
|
||||
return iwl_uefi_get_verified_variable_guid(trans, &IWL_EFI_WIFI_GUID,
|
||||
uefi_var_name, var_name,
|
||||
expected_size, size);
|
||||
}
|
||||
|
||||
int iwl_uefi_handle_tlv_mem_desc(struct iwl_trans *trans, const u8 *data,
|
||||
u32 tlv_len, struct iwl_pnvm_image *pnvm_data)
|
||||
{
|
||||
@@ -204,7 +219,8 @@ static int iwl_uefi_reduce_power_section(struct iwl_trans *trans,
|
||||
|
||||
int iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
|
||||
const u8 *data, size_t len,
|
||||
struct iwl_pnvm_image *pnvm_data)
|
||||
struct iwl_pnvm_image *pnvm_data,
|
||||
__le32 sku_id[3])
|
||||
{
|
||||
const struct iwl_ucode_tlv *tlv;
|
||||
|
||||
@@ -226,23 +242,23 @@ int iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
|
||||
}
|
||||
|
||||
if (tlv_type == IWL_UCODE_TLV_PNVM_SKU) {
|
||||
const struct iwl_sku_id *sku_id =
|
||||
const struct iwl_sku_id *tlv_sku_id =
|
||||
(const void *)(data + sizeof(*tlv));
|
||||
|
||||
IWL_DEBUG_FW(trans,
|
||||
"Got IWL_UCODE_TLV_PNVM_SKU len %d\n",
|
||||
tlv_len);
|
||||
IWL_DEBUG_FW(trans, "sku_id 0x%0x 0x%0x 0x%0x\n",
|
||||
le32_to_cpu(sku_id->data[0]),
|
||||
le32_to_cpu(sku_id->data[1]),
|
||||
le32_to_cpu(sku_id->data[2]));
|
||||
le32_to_cpu(tlv_sku_id->data[0]),
|
||||
le32_to_cpu(tlv_sku_id->data[1]),
|
||||
le32_to_cpu(tlv_sku_id->data[2]));
|
||||
|
||||
data += sizeof(*tlv) + ALIGN(tlv_len, 4);
|
||||
len -= ALIGN(tlv_len, 4);
|
||||
|
||||
if (trans->sku_id[0] == le32_to_cpu(sku_id->data[0]) &&
|
||||
trans->sku_id[1] == le32_to_cpu(sku_id->data[1]) &&
|
||||
trans->sku_id[2] == le32_to_cpu(sku_id->data[2])) {
|
||||
if (sku_id[0] == tlv_sku_id->data[0] &&
|
||||
sku_id[1] == tlv_sku_id->data[1] &&
|
||||
sku_id[2] == tlv_sku_id->data[2]) {
|
||||
int ret = iwl_uefi_reduce_power_section(trans,
|
||||
data, len,
|
||||
pnvm_data);
|
||||
@@ -295,11 +311,12 @@ static int iwl_uefi_step_parse(struct uefi_cnv_common_step_data *common_step_dat
|
||||
if (common_step_data->revision != 1)
|
||||
return -EINVAL;
|
||||
|
||||
trans->mbx_addr_0_step = (u32)common_step_data->revision |
|
||||
trans->conf.mbx_addr_0_step =
|
||||
(u32)common_step_data->revision |
|
||||
(u32)common_step_data->cnvi_eq_channel << 8 |
|
||||
(u32)common_step_data->cnvr_eq_channel << 16 |
|
||||
(u32)common_step_data->radio1 << 24;
|
||||
trans->mbx_addr_1_step = (u32)common_step_data->radio2;
|
||||
trans->conf.mbx_addr_1_step = (u32)common_step_data->radio2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -308,11 +325,12 @@ void iwl_uefi_get_step_table(struct iwl_trans *trans)
|
||||
struct uefi_cnv_common_step_data *data;
|
||||
int ret;
|
||||
|
||||
if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
|
||||
if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
|
||||
return;
|
||||
|
||||
data = iwl_uefi_get_verified_variable(trans, IWL_UEFI_STEP_NAME,
|
||||
"STEP", sizeof(*data), NULL);
|
||||
data = iwl_uefi_get_verified_variable_guid(trans, &IWL_EFI_WIFI_BT_GUID,
|
||||
IWL_UEFI_STEP_NAME,
|
||||
"STEP", sizeof(*data), NULL);
|
||||
if (IS_ERR(data))
|
||||
return;
|
||||
|
||||
@@ -386,11 +404,14 @@ static int iwl_uefi_uats_parse(struct uefi_cnv_wlan_uats_data *uats_data,
|
||||
|
||||
memcpy(fwrt->uats_table.offset_map, uats_data->offset_map,
|
||||
sizeof(fwrt->uats_table.offset_map));
|
||||
|
||||
fwrt->uats_valid = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iwl_uefi_get_uats_table(struct iwl_trans *trans,
|
||||
struct iwl_fw_runtime *fwrt)
|
||||
void iwl_uefi_get_uats_table(struct iwl_trans *trans,
|
||||
struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
struct uefi_cnv_wlan_uats_data *data;
|
||||
int ret;
|
||||
@@ -398,17 +419,12 @@ int iwl_uefi_get_uats_table(struct iwl_trans *trans,
|
||||
data = iwl_uefi_get_verified_variable(trans, IWL_UEFI_UATS_NAME,
|
||||
"UATS", sizeof(*data), NULL);
|
||||
if (IS_ERR(data))
|
||||
return -EINVAL;
|
||||
return;
|
||||
|
||||
ret = iwl_uefi_uats_parse(data, fwrt);
|
||||
if (ret < 0) {
|
||||
if (ret < 0)
|
||||
IWL_DEBUG_FW(trans, "Cannot read UATS table. rev is invalid\n");
|
||||
kfree(data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
kfree(data);
|
||||
return 0;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_uefi_get_uats_table);
|
||||
|
||||
@@ -538,13 +554,14 @@ int iwl_uefi_get_ppag_table(struct iwl_fw_runtime *fwrt)
|
||||
goto out;
|
||||
}
|
||||
|
||||
fwrt->ppag_ver = data->revision;
|
||||
fwrt->ppag_bios_rev = data->revision;
|
||||
fwrt->ppag_flags = iwl_bios_get_ppag_flags(data->ppag_modes,
|
||||
fwrt->ppag_ver);
|
||||
fwrt->ppag_bios_rev);
|
||||
|
||||
BUILD_BUG_ON(sizeof(fwrt->ppag_chains) != sizeof(data->ppag_chains));
|
||||
memcpy(&fwrt->ppag_chains, &data->ppag_chains,
|
||||
sizeof(data->ppag_chains));
|
||||
fwrt->ppag_bios_source = BIOS_SOURCE_UEFI;
|
||||
out:
|
||||
kfree(data);
|
||||
return ret;
|
||||
@@ -554,27 +571,31 @@ int iwl_uefi_get_tas_table(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_tas_data *tas_data)
|
||||
{
|
||||
struct uefi_cnv_var_wtas *uefi_tas;
|
||||
int ret = 0, enabled, i;
|
||||
int ret, enabled;
|
||||
|
||||
uefi_tas = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_WTAS_NAME,
|
||||
"WTAS", sizeof(*uefi_tas), NULL);
|
||||
if (IS_ERR(uefi_tas))
|
||||
return -EINVAL;
|
||||
|
||||
if (uefi_tas->revision != IWL_UEFI_WTAS_REVISION) {
|
||||
if (uefi_tas->revision < IWL_UEFI_MIN_WTAS_REVISION ||
|
||||
uefi_tas->revision > IWL_UEFI_MAX_WTAS_REVISION) {
|
||||
ret = -EINVAL;
|
||||
IWL_DEBUG_RADIO(fwrt, "Unsupported UEFI WTAS revision:%d\n",
|
||||
uefi_tas->revision);
|
||||
goto out;
|
||||
}
|
||||
|
||||
enabled = iwl_parse_tas_selection(fwrt, tas_data,
|
||||
uefi_tas->tas_selection);
|
||||
if (!enabled) {
|
||||
IWL_DEBUG_RADIO(fwrt, "TAS not enabled\n");
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
IWL_DEBUG_RADIO(fwrt, "TAS selection as read from BIOS: 0x%x\n",
|
||||
uefi_tas->tas_selection);
|
||||
|
||||
enabled = uefi_tas->tas_selection & IWL_WTAS_ENABLED_MSK;
|
||||
tas_data->table_source = BIOS_SOURCE_UEFI;
|
||||
tas_data->table_revision = uefi_tas->revision;
|
||||
tas_data->tas_selection = uefi_tas->tas_selection;
|
||||
|
||||
IWL_DEBUG_RADIO(fwrt, "TAS %s enabled\n",
|
||||
enabled ? "is" : "not");
|
||||
|
||||
IWL_DEBUG_RADIO(fwrt, "Reading TAS table revision %d\n",
|
||||
uefi_tas->revision);
|
||||
@@ -584,15 +605,16 @@ int iwl_uefi_get_tas_table(struct iwl_fw_runtime *fwrt,
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
tas_data->block_list_size = cpu_to_le32(uefi_tas->black_list_size);
|
||||
|
||||
tas_data->block_list_size = uefi_tas->black_list_size;
|
||||
IWL_DEBUG_RADIO(fwrt, "TAS array size %u\n", uefi_tas->black_list_size);
|
||||
|
||||
for (i = 0; i < uefi_tas->black_list_size; i++) {
|
||||
tas_data->block_list_array[i] =
|
||||
cpu_to_le32(uefi_tas->black_list[i]);
|
||||
for (u8 i = 0; i < uefi_tas->black_list_size; i++) {
|
||||
tas_data->block_list_array[i] = uefi_tas->black_list[i];
|
||||
IWL_DEBUG_RADIO(fwrt, "TAS block list country %d\n",
|
||||
uefi_tas->black_list[i]);
|
||||
}
|
||||
ret = enabled;
|
||||
out:
|
||||
kfree(uefi_tas);
|
||||
return ret;
|
||||
@@ -638,7 +660,7 @@ int iwl_uefi_get_mcc(struct iwl_fw_runtime *fwrt, char *mcc)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (data->mcc != UEFI_MCC_CHINA) {
|
||||
if (data->mcc != BIOS_MCC_CHINA) {
|
||||
ret = -EINVAL;
|
||||
IWL_DEBUG_RADIO(fwrt, "UEFI WRDD is supported only for CN\n");
|
||||
goto out;
|
||||
@@ -657,14 +679,16 @@ int iwl_uefi_get_eckv(struct iwl_fw_runtime *fwrt, u32 *extl_clk)
|
||||
struct uefi_cnv_var_eckv *data;
|
||||
int ret = 0;
|
||||
|
||||
data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_ECKV_NAME,
|
||||
"ECKV", sizeof(*data), NULL);
|
||||
data = iwl_uefi_get_verified_variable_guid(fwrt->trans,
|
||||
&IWL_EFI_WIFI_BT_GUID,
|
||||
IWL_UEFI_ECKV_NAME,
|
||||
"ECKV", sizeof(*data), NULL);
|
||||
if (IS_ERR(data))
|
||||
return -EINVAL;
|
||||
|
||||
if (data->revision != IWL_UEFI_ECKV_REVISION) {
|
||||
ret = -EINVAL;
|
||||
IWL_DEBUG_RADIO(fwrt, "Unsupported UEFI WRDD revision:%d\n",
|
||||
IWL_DEBUG_RADIO(fwrt, "Unsupported UEFI ECKV revision:%d\n",
|
||||
data->revision);
|
||||
goto out;
|
||||
}
|
||||
@@ -723,9 +747,102 @@ int iwl_uefi_get_dsm(struct iwl_fw_runtime *fwrt, enum iwl_dsm_funcs func,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!(data->functions[DSM_FUNC_QUERY] & BIT(func))) {
|
||||
IWL_DEBUG_RADIO(fwrt, "DSM func %d not in 0x%x\n",
|
||||
func, data->functions[DSM_FUNC_QUERY]);
|
||||
goto out;
|
||||
}
|
||||
|
||||
*value = data->functions[func];
|
||||
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"UEFI: DSM func=%d: value=%d\n", func, *value);
|
||||
|
||||
ret = 0;
|
||||
out:
|
||||
kfree(data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iwl_uefi_get_puncturing(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
struct uefi_cnv_var_puncturing_data *data;
|
||||
/* default value is not enabled if there is any issue in reading
|
||||
* uefi variable or revision is not supported
|
||||
*/
|
||||
int puncturing = 0;
|
||||
|
||||
data = iwl_uefi_get_verified_variable(fwrt->trans,
|
||||
IWL_UEFI_PUNCTURING_NAME,
|
||||
"UefiCnvWlanPuncturing",
|
||||
sizeof(*data), NULL);
|
||||
if (IS_ERR(data))
|
||||
return puncturing;
|
||||
|
||||
if (data->revision != IWL_UEFI_PUNCTURING_REVISION) {
|
||||
IWL_DEBUG_RADIO(fwrt, "Unsupported UEFI PUNCTURING rev:%d\n",
|
||||
data->revision);
|
||||
} else {
|
||||
puncturing = data->puncturing & IWL_UEFI_PUNCTURING_REV0_MASK;
|
||||
IWL_DEBUG_RADIO(fwrt, "Loaded puncturing bits from UEFI: %d\n",
|
||||
puncturing);
|
||||
}
|
||||
|
||||
kfree(data);
|
||||
return puncturing;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_uefi_get_puncturing);
|
||||
|
||||
int iwl_uefi_get_dsbr(struct iwl_fw_runtime *fwrt, u32 *value)
|
||||
{
|
||||
struct uefi_cnv_wlan_dsbr_data *data;
|
||||
int ret = 0;
|
||||
|
||||
data = iwl_uefi_get_verified_variable_guid(fwrt->trans,
|
||||
&IWL_EFI_WIFI_BT_GUID,
|
||||
IWL_UEFI_DSBR_NAME, "DSBR",
|
||||
sizeof(*data), NULL);
|
||||
if (IS_ERR(data))
|
||||
return -EINVAL;
|
||||
|
||||
if (data->revision != IWL_UEFI_DSBR_REVISION) {
|
||||
ret = -EINVAL;
|
||||
IWL_DEBUG_RADIO(fwrt, "Unsupported UEFI DSBR revision:%d\n",
|
||||
data->revision);
|
||||
goto out;
|
||||
}
|
||||
*value = data->config;
|
||||
IWL_DEBUG_RADIO(fwrt, "Loaded DSBR config from UEFI value: 0x%x\n",
|
||||
*value);
|
||||
out:
|
||||
kfree(data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iwl_uefi_get_phy_filters(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
struct uefi_cnv_wpfc_data *data __free(kfree);
|
||||
struct iwl_phy_specific_cfg *filters = &fwrt->phy_filters;
|
||||
|
||||
data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_WPFC_NAME,
|
||||
"WPFC", sizeof(*data), NULL);
|
||||
if (IS_ERR(data))
|
||||
return -EINVAL;
|
||||
|
||||
if (data->revision != 0) {
|
||||
IWL_DEBUG_RADIO(fwrt, "Unsupported UEFI WPFC revision:%d\n",
|
||||
data->revision);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
BUILD_BUG_ON(ARRAY_SIZE(filters->filter_cfg_chains) !=
|
||||
ARRAY_SIZE(data->chains));
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(filters->filter_cfg_chains); i++) {
|
||||
filters->filter_cfg_chains[i] = cpu_to_le32(data->chains[i]);
|
||||
IWL_DEBUG_RADIO(fwrt, "WPFC: chain %d: %u\n", i, data->chains[i]);
|
||||
}
|
||||
|
||||
IWL_DEBUG_RADIO(fwrt, "Loaded WPFC config from UEFI\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright(c) 2021-2024 Intel Corporation
|
||||
* Copyright(c) 2021-2025 Intel Corporation
|
||||
*/
|
||||
#ifndef __iwl_fw_uefi__
|
||||
#define __iwl_fw_uefi__
|
||||
@@ -19,9 +19,12 @@
|
||||
#define IWL_UEFI_WTAS_NAME L"UefiCnvWlanWTAS"
|
||||
#define IWL_UEFI_SPLC_NAME L"UefiCnvWlanSPLC"
|
||||
#define IWL_UEFI_WRDD_NAME L"UefiCnvWlanWRDD"
|
||||
#define IWL_UEFI_ECKV_NAME L"UefiCnvWlanECKV"
|
||||
#define IWL_UEFI_ECKV_NAME L"UefiCnvCommonECKV"
|
||||
#define IWL_UEFI_DSM_NAME L"UefiCnvWlanGeneralCfg"
|
||||
#define IWL_UEFI_WBEM_NAME L"UefiCnvWlanWBEM"
|
||||
#define IWL_UEFI_PUNCTURING_NAME L"UefiCnvWlanPuncturing"
|
||||
#define IWL_UEFI_DSBR_NAME L"UefiCnvCommonDSBR"
|
||||
#define IWL_UEFI_WPFC_NAME L"WPFC"
|
||||
|
||||
|
||||
#define IWL_SGOM_MAP_SIZE 339
|
||||
@@ -31,13 +34,16 @@
|
||||
#define IWL_UEFI_EWRD_REVISION 2
|
||||
#define IWL_UEFI_WGDS_REVISION 3
|
||||
#define IWL_UEFI_MIN_PPAG_REV 1
|
||||
#define IWL_UEFI_MAX_PPAG_REV 3
|
||||
#define IWL_UEFI_WTAS_REVISION 1
|
||||
#define IWL_UEFI_MAX_PPAG_REV 4
|
||||
#define IWL_UEFI_MIN_WTAS_REVISION 1
|
||||
#define IWL_UEFI_MAX_WTAS_REVISION 2
|
||||
#define IWL_UEFI_SPLC_REVISION 0
|
||||
#define IWL_UEFI_WRDD_REVISION 0
|
||||
#define IWL_UEFI_ECKV_REVISION 0
|
||||
#define IWL_UEFI_WBEM_REVISION 0
|
||||
#define IWL_UEFI_DSM_REVISION 4
|
||||
#define IWL_UEFI_PUNCTURING_REVISION 0
|
||||
#define IWL_UEFI_DSBR_REVISION 1
|
||||
|
||||
struct pnvm_sku_package {
|
||||
u8 rev;
|
||||
@@ -149,8 +155,6 @@ struct uefi_cnv_var_splc {
|
||||
u32 default_pwr_limit;
|
||||
} __packed;
|
||||
|
||||
#define UEFI_MCC_CHINA 0x434e
|
||||
|
||||
/* struct uefi_cnv_var_wrdd - WRDD table as defined in UEFI
|
||||
* @revision: the revision of the table
|
||||
* @mcc: country identifier as defined in ISO/IEC 3166-1 Alpha 2 code
|
||||
@@ -194,6 +198,51 @@ struct uefi_cnv_wlan_wbem_data {
|
||||
u32 wbem_320mhz_per_mcc;
|
||||
} __packed;
|
||||
|
||||
enum iwl_uefi_cnv_puncturing_flags {
|
||||
IWL_UEFI_CNV_PUNCTURING_USA_EN_MSK = BIT(0),
|
||||
IWL_UEFI_CNV_PUNCTURING_CANADA_EN_MSK = BIT(1),
|
||||
};
|
||||
|
||||
#define IWL_UEFI_PUNCTURING_REV0_MASK (IWL_UEFI_CNV_PUNCTURING_USA_EN_MSK | \
|
||||
IWL_UEFI_CNV_PUNCTURING_CANADA_EN_MSK)
|
||||
/**
|
||||
* struct uefi_cnv_var_puncturing_data - controlling channel
|
||||
* puncturing for few countries.
|
||||
* @revision: the revision of the table
|
||||
* @puncturing: enablement of channel puncturing per mcc
|
||||
* see &enum iwl_uefi_cnv_puncturing_flags.
|
||||
*/
|
||||
struct uefi_cnv_var_puncturing_data {
|
||||
u8 revision;
|
||||
u32 puncturing;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct uefi_cnv_wlan_dsbr_data - BIOS STEP configuration information
|
||||
* @revision: the revision of the table
|
||||
* @config: STEP configuration flags:
|
||||
* bit 8, switch to URM depending on FW setting
|
||||
* bit 9, switch to URM
|
||||
*
|
||||
* Platform information for STEP configuration/workarounds.
|
||||
*/
|
||||
struct uefi_cnv_wlan_dsbr_data {
|
||||
u8 revision;
|
||||
u32 config;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct uefi_cnv_wpfc_data - BIOS Wi-Fi PHY filter Configuration
|
||||
* @revision: the revision of the table
|
||||
* @chains: configuration of each of the chains (a-d)
|
||||
*
|
||||
* specific PHY filter configuration
|
||||
*/
|
||||
struct uefi_cnv_wpfc_data {
|
||||
u8 revision;
|
||||
u32 chains[4];
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* This is known to be broken on v4.19 and to work on v5.4. Until we
|
||||
* figure out why this is the case and how to make it work, simply
|
||||
@@ -204,7 +253,8 @@ void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len);
|
||||
u8 *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len);
|
||||
int iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
|
||||
const u8 *data, size_t len,
|
||||
struct iwl_pnvm_image *pnvm_data);
|
||||
struct iwl_pnvm_image *pnvm_data,
|
||||
__le32 sku_id[3]);
|
||||
void iwl_uefi_get_step_table(struct iwl_trans *trans);
|
||||
int iwl_uefi_handle_tlv_mem_desc(struct iwl_trans *trans, const u8 *data,
|
||||
u32 tlv_len, struct iwl_pnvm_image *pnvm_data);
|
||||
@@ -222,8 +272,11 @@ int iwl_uefi_get_wbem(struct iwl_fw_runtime *fwrt, u32 *value);
|
||||
int iwl_uefi_get_dsm(struct iwl_fw_runtime *fwrt, enum iwl_dsm_funcs func,
|
||||
u32 *value);
|
||||
void iwl_uefi_get_sgom_table(struct iwl_trans *trans, struct iwl_fw_runtime *fwrt);
|
||||
int iwl_uefi_get_uats_table(struct iwl_trans *trans,
|
||||
struct iwl_fw_runtime *fwrt);
|
||||
void iwl_uefi_get_uats_table(struct iwl_trans *trans,
|
||||
struct iwl_fw_runtime *fwrt);
|
||||
int iwl_uefi_get_puncturing(struct iwl_fw_runtime *fwrt);
|
||||
int iwl_uefi_get_dsbr(struct iwl_fw_runtime *fwrt, u32 *value);
|
||||
int iwl_uefi_get_phy_filters(struct iwl_fw_runtime *fwrt);
|
||||
#else /* CONFIG_EFI */
|
||||
static inline void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len)
|
||||
{
|
||||
@@ -233,7 +286,8 @@ static inline void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len)
|
||||
static inline int
|
||||
iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
|
||||
const u8 *data, size_t len,
|
||||
struct iwl_pnvm_image *pnvm_data)
|
||||
struct iwl_pnvm_image *pnvm_data,
|
||||
__le32 sku_id[3])
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
@@ -314,9 +368,13 @@ void iwl_uefi_get_sgom_table(struct iwl_trans *trans, struct iwl_fw_runtime *fwr
|
||||
{
|
||||
}
|
||||
|
||||
static inline void
|
||||
iwl_uefi_get_uats_table(struct iwl_trans *trans, struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
}
|
||||
|
||||
static inline
|
||||
int iwl_uefi_get_uats_table(struct iwl_trans *trans,
|
||||
struct iwl_fw_runtime *fwrt)
|
||||
int iwl_uefi_get_puncturing(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
#if defined(__linux__)
|
||||
return 0;
|
||||
@@ -324,5 +382,16 @@ int iwl_uefi_get_uats_table(struct iwl_trans *trans,
|
||||
return -ENOENT;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline
|
||||
int iwl_uefi_get_dsbr(struct iwl_fw_runtime *fwrt, u32 *value)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static inline int iwl_uefi_get_phy_filters(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
#endif /* CONFIG_EFI */
|
||||
#endif /* __iwl_fw_uefi__ */
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2014, 2018-2021 Intel Corporation
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018-2024 Intel Corporation
|
||||
* Copyright (C) 2018-2025 Intel Corporation
|
||||
*/
|
||||
#ifndef __IWL_CONFIG_H__
|
||||
#define __IWL_CONFIG_H__
|
||||
@@ -38,6 +38,7 @@ enum iwl_device_family {
|
||||
IWL_DEVICE_FAMILY_AX210,
|
||||
IWL_DEVICE_FAMILY_BZ,
|
||||
IWL_DEVICE_FAMILY_SC,
|
||||
IWL_DEVICE_FAMILY_DR,
|
||||
};
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
@@ -138,6 +139,10 @@ enum iwl_nvm_type {
|
||||
#define ANT_ABC (ANT_A | ANT_B | ANT_C)
|
||||
|
||||
|
||||
#define IWL_FW_AND_PNVM(pfx, api) \
|
||||
MODULE_FIRMWARE(pfx "-" __stringify(api) ".ucode"); \
|
||||
MODULE_FIRMWARE(pfx ".pnvm")
|
||||
|
||||
static inline u8 num_of_ant(u8 mask)
|
||||
{
|
||||
return !!((mask) & ANT_A) +
|
||||
@@ -146,7 +151,29 @@ static inline u8 num_of_ant(u8 mask)
|
||||
}
|
||||
|
||||
/**
|
||||
* struct iwl_base_params - params not likely to change within a device family
|
||||
* struct iwl_fw_mon_reg - FW monitor register info
|
||||
* @addr: register address
|
||||
* @mask: register mask
|
||||
*/
|
||||
struct iwl_fw_mon_reg {
|
||||
u32 addr;
|
||||
u32 mask;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_fw_mon_regs - FW monitor registers
|
||||
* @write_ptr: write pointer register
|
||||
* @cycle_cnt: cycle count register
|
||||
* @cur_frag: current fragment in use
|
||||
*/
|
||||
struct iwl_fw_mon_regs {
|
||||
struct iwl_fw_mon_reg write_ptr;
|
||||
struct iwl_fw_mon_reg cycle_cnt;
|
||||
struct iwl_fw_mon_reg cur_frag;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_family_base_params - base parameters for an entire family
|
||||
* @max_ll_items: max number of OTP blocks
|
||||
* @shadow_ram_support: shadow support for OTP memory
|
||||
* @led_compensation: compensate on the led on/off time per HW according
|
||||
@@ -155,12 +182,34 @@ static inline u8 num_of_ant(u8 mask)
|
||||
* @wd_timeout: TX queues watchdog timeout
|
||||
* @max_event_log_size: size of event log buffer size for ucode event logging
|
||||
* @shadow_reg_enable: HW shadow register support
|
||||
* @apmg_not_supported: there's no APMG
|
||||
* @apmg_wake_up_wa: should the MAC access REQ be asserted when a command
|
||||
* is in flight. This is due to a HW bug in 7260, 3160 and 7265.
|
||||
* @scd_chain_ext_wa: should the chain extension feature in SCD be disabled.
|
||||
* @max_tfd_queue_size: max number of entries in tfd queue.
|
||||
* @eeprom_size: EEPROM size
|
||||
* @num_of_queues: number of HW TX queues supported
|
||||
* @pcie_l1_allowed: PCIe L1 state is allowed
|
||||
* @pll_cfg: PLL configuration needed
|
||||
* @nvm_hw_section_num: the ID of the HW NVM section
|
||||
* @features: hw features, any combination of feature_passlist
|
||||
* @smem_offset: offset from which the SMEM begins
|
||||
* @smem_len: the length of SMEM
|
||||
* @mac_addr_from_csr: read HW address from CSR registers at this offset
|
||||
* @d3_debug_data_base_addr: base address where D3 debug data is stored
|
||||
* @d3_debug_data_length: length of the D3 debug data
|
||||
* @min_ba_txq_size: minimum number of slots required in a TX queue used
|
||||
* for aggregation
|
||||
* @min_txq_size: minimum number of slots required in a TX queue
|
||||
* @gp2_reg_addr: GP2 (timer) register address
|
||||
* @min_umac_error_event_table: minimum SMEM location of UMAC error table
|
||||
* @mon_dbgi_regs: monitor DBGI registers
|
||||
* @mon_dram_regs: monitor DRAM registers
|
||||
* @mon_smem_regs: monitor SMEM registers
|
||||
* @ucode_api_max: Highest version of uCode API supported by driver.
|
||||
* @ucode_api_min: Lowest version of uCode API supported by driver.
|
||||
*/
|
||||
struct iwl_base_params {
|
||||
struct iwl_family_base_params {
|
||||
unsigned int wd_timeout;
|
||||
|
||||
u16 eeprom_size;
|
||||
@@ -171,6 +220,7 @@ struct iwl_base_params {
|
||||
shadow_reg_enable:1,
|
||||
pcie_l1_allowed:1,
|
||||
apmg_wake_up_wa:1,
|
||||
apmg_not_supported:1,
|
||||
scd_chain_ext_wa:1;
|
||||
|
||||
u16 num_of_queues; /* def: HW dependent */
|
||||
@@ -178,6 +228,22 @@ struct iwl_base_params {
|
||||
|
||||
u8 max_ll_items;
|
||||
u8 led_compensation;
|
||||
u8 ucode_api_max;
|
||||
u8 ucode_api_min;
|
||||
u32 mac_addr_from_csr:10;
|
||||
u8 nvm_hw_section_num;
|
||||
netdev_features_t features;
|
||||
u32 smem_offset;
|
||||
u32 smem_len;
|
||||
u32 min_umac_error_event_table;
|
||||
u32 d3_debug_data_base_addr;
|
||||
u32 d3_debug_data_length;
|
||||
u32 min_txq_size;
|
||||
u32 gp2_reg_addr;
|
||||
u32 min_ba_txq_size;
|
||||
const struct iwl_fw_mon_regs mon_dram_regs;
|
||||
const struct iwl_fw_mon_regs mon_smem_regs;
|
||||
const struct iwl_fw_mon_regs mon_dbgi_regs;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -269,7 +335,7 @@ struct iwl_pwr_tx_backoff {
|
||||
u32 backoff;
|
||||
};
|
||||
|
||||
enum iwl_cfg_trans_ltr_delay {
|
||||
enum iwl_mac_cfg_ltr_delay {
|
||||
IWL_CFG_TRANS_LTR_DELAY_NONE = 0,
|
||||
IWL_CFG_TRANS_LTR_DELAY_200US = 1,
|
||||
IWL_CFG_TRANS_LTR_DELAY_2500US = 2,
|
||||
@@ -277,35 +343,33 @@ enum iwl_cfg_trans_ltr_delay {
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_cfg_trans_params - information needed to start the trans
|
||||
* struct iwl_mac_cfg - information about the MAC-specific device part
|
||||
*
|
||||
* These values are specific to the device ID and do not change when
|
||||
* multiple configs are used for a single device ID. They values are
|
||||
* used, among other things, to boot the NIC so that the HW REV or
|
||||
* RFID can be read before deciding the remaining parameters to use.
|
||||
*
|
||||
* @base_params: pointer to basic parameters
|
||||
* @base: pointer to basic parameters
|
||||
* @device_family: the device family
|
||||
* @umac_prph_offset: offset to add to UMAC periphery address
|
||||
* @xtal_latency: power up latency to get the xtal stabilized
|
||||
* @extra_phy_cfg_flags: extra configuration flags to pass to the PHY
|
||||
* @rf_id: need to read rf_id to determine the firmware image
|
||||
* @gen2: 22000 and on transport operation
|
||||
* @mq_rx_supported: multi-queue rx support
|
||||
* @integrated: discrete or integrated
|
||||
* @low_latency_xtal: use the low latency xtal if supported
|
||||
* @bisr_workaround: BISR hardware workaround (for 22260 series devices)
|
||||
* @ltr_delay: LTR delay parameter, &enum iwl_cfg_trans_ltr_delay.
|
||||
* @ltr_delay: LTR delay parameter, &enum iwl_mac_cfg_ltr_delay.
|
||||
* @imr_enabled: use the IMR if supported.
|
||||
*/
|
||||
struct iwl_cfg_trans_params {
|
||||
const struct iwl_base_params *base_params;
|
||||
struct iwl_mac_cfg {
|
||||
const struct iwl_family_base_params *base;
|
||||
enum iwl_device_family device_family;
|
||||
u32 umac_prph_offset;
|
||||
u32 xtal_latency;
|
||||
u32 extra_phy_cfg_flags;
|
||||
u32 rf_id:1,
|
||||
gen2:1,
|
||||
u32 gen2:1,
|
||||
mq_rx_supported:1,
|
||||
integrated:1,
|
||||
low_latency_xtal:1,
|
||||
@@ -314,36 +378,21 @@ struct iwl_cfg_trans_params {
|
||||
imr_enabled:1;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_fw_mon_reg - FW monitor register info
|
||||
* @addr: register address
|
||||
* @mask: register mask
|
||||
/*
|
||||
* These sizes were picked according to 8 MSDUs inside 64/256/612 A-MSDUs
|
||||
* in an A-MPDU, with additional overhead to account for processing time.
|
||||
* They will be doubled for MACs starting from So/Ty that don't support
|
||||
* putting multiple frames into a single buffer.
|
||||
*/
|
||||
struct iwl_fw_mon_reg {
|
||||
u32 addr;
|
||||
u32 mask;
|
||||
};
|
||||
#define IWL_NUM_RBDS_NON_HE (64 * 8)
|
||||
#define IWL_NUM_RBDS_HE (256 * 8)
|
||||
#define IWL_NUM_RBDS_EHT (512 * 8)
|
||||
|
||||
/**
|
||||
* struct iwl_fw_mon_regs - FW monitor registers
|
||||
* @write_ptr: write pointer register
|
||||
* @cycle_cnt: cycle count register
|
||||
* @cur_frag: current fragment in use
|
||||
*/
|
||||
struct iwl_fw_mon_regs {
|
||||
struct iwl_fw_mon_reg write_ptr;
|
||||
struct iwl_fw_mon_reg cycle_cnt;
|
||||
struct iwl_fw_mon_reg cur_frag;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_cfg
|
||||
* @trans: the trans-specific configuration part
|
||||
* @name: Official name of the device
|
||||
* struct iwl_rf_cfg
|
||||
* @fw_name_pre: Firmware filename prefix. The api version and extension
|
||||
* (.ucode) will be added to filename before loading from disk. The
|
||||
* filename is constructed as <fw_name_pre>-<api>.ucode.
|
||||
* @fw_name_mac: MAC name for this config, the remaining pieces of the
|
||||
* name will be generated dynamically
|
||||
* @ucode_api_max: Highest version of uCode API supported by driver.
|
||||
* @ucode_api_min: Lowest version of uCode API supported by driver.
|
||||
@@ -354,34 +403,25 @@ struct iwl_fw_mon_regs {
|
||||
* @non_shared_ant: the antenna that is for WiFi only
|
||||
* @nvm_ver: NVM version
|
||||
* @nvm_calib_ver: NVM calibration version
|
||||
* @bw_limit: bandwidth limit for this device, if non-zero
|
||||
* @ht_params: point to ht parameters
|
||||
* @eeprom_params: EEPROM parameters (old devices)
|
||||
* @thermal_params: Thermal throttling parameters
|
||||
* @lp_xtal_workaround: low-power crystal workaround needed
|
||||
* @led_mode: 0=blinking, 1=On(RF On)/Off(RF Off)
|
||||
* @rx_with_siso_diversity: 1x1 device with rx antenna diversity
|
||||
* @tx_with_siso_diversity: 1x1 device with tx antenna diversity
|
||||
* @internal_wimax_coex: internal wifi/wimax combo device
|
||||
* @high_temp: Is this NIC is designated to be in high temperature.
|
||||
* @host_interrupt_operation_mode: device needs host interrupt operation
|
||||
* mode set
|
||||
* @nvm_hw_section_num: the ID of the HW NVM section
|
||||
* @mac_addr_from_csr: read HW address from CSR registers at this offset
|
||||
* @features: hw features, any combination of feature_passlist
|
||||
* @pwr_tx_backoffs: translation table between power limits and backoffs
|
||||
* @max_tx_agg_size: max TX aggregation size of the ADDBA request/response
|
||||
* @dccm_offset: offset from which DCCM begins
|
||||
* @dccm_len: length of DCCM (including runtime stack CCM)
|
||||
* @dccm2_offset: offset from which the second DCCM begins
|
||||
* @dccm2_len: length of the second DCCM
|
||||
* @smem_offset: offset from which the SMEM begins
|
||||
* @smem_len: the length of SMEM
|
||||
* @vht_mu_mimo_supported: VHT MU-MIMO support
|
||||
* @cdb: CDB support
|
||||
* @nvm_type: see &enum iwl_nvm_type
|
||||
* @d3_debug_data_base_addr: base address where D3 debug data is stored
|
||||
* @d3_debug_data_length: length of the D3 debug data
|
||||
* @min_txq_size: minimum number of slots required in a TX queue
|
||||
* @uhb_supported: ultra high band channels supported
|
||||
* @min_ba_txq_size: minimum number of slots required in a TX queue which
|
||||
* based on hardware support (HE - 256, EHT - 1K).
|
||||
* @num_rbds: number of receive buffer descriptors to use
|
||||
* (only used for multi-queue capable devices)
|
||||
*
|
||||
@@ -389,60 +429,38 @@ struct iwl_fw_mon_regs {
|
||||
* API differences in uCode shouldn't be handled here but through TLVs
|
||||
* and/or the uCode API version instead.
|
||||
*/
|
||||
struct iwl_cfg {
|
||||
struct iwl_cfg_trans_params trans;
|
||||
struct iwl_rf_cfg {
|
||||
/* params specific to an individual device within a device family */
|
||||
const char *name;
|
||||
const char *fw_name_pre;
|
||||
const char *fw_name_mac;
|
||||
/* params likely to change within a device family */
|
||||
const struct iwl_ht_params *ht_params;
|
||||
const struct iwl_ht_params ht_params;
|
||||
const struct iwl_eeprom_params *eeprom_params;
|
||||
const struct iwl_pwr_tx_backoff *pwr_tx_backoffs;
|
||||
const char *default_nvm_file_C_step;
|
||||
const struct iwl_tt_params *thermal_params;
|
||||
enum iwl_led_mode led_mode;
|
||||
enum iwl_nvm_type nvm_type;
|
||||
u32 max_data_size;
|
||||
u32 max_inst_size;
|
||||
netdev_features_t features;
|
||||
u32 dccm_offset;
|
||||
u32 dccm_len;
|
||||
u32 dccm2_offset;
|
||||
u32 dccm2_len;
|
||||
u32 smem_offset;
|
||||
u32 smem_len;
|
||||
u16 nvm_ver;
|
||||
u16 nvm_calib_ver;
|
||||
u16 bw_limit;
|
||||
u32 rx_with_siso_diversity:1,
|
||||
tx_with_siso_diversity:1,
|
||||
internal_wimax_coex:1,
|
||||
host_interrupt_operation_mode:1,
|
||||
high_temp:1,
|
||||
mac_addr_from_csr:10,
|
||||
lp_xtal_workaround:1,
|
||||
apmg_not_supported:1,
|
||||
vht_mu_mimo_supported:1,
|
||||
cdb:1,
|
||||
dbgc_supported:1,
|
||||
uhb_supported:1;
|
||||
u8 valid_tx_ant;
|
||||
u8 valid_rx_ant;
|
||||
u8 non_shared_ant;
|
||||
u8 nvm_hw_section_num;
|
||||
u8 max_tx_agg_size;
|
||||
u8 ucode_api_max;
|
||||
u8 ucode_api_min;
|
||||
u16 num_rbds;
|
||||
u32 min_umac_error_event_table;
|
||||
u32 d3_debug_data_base_addr;
|
||||
u32 d3_debug_data_length;
|
||||
u32 min_txq_size;
|
||||
u32 gp2_reg_addr;
|
||||
u32 min_ba_txq_size;
|
||||
const struct iwl_fw_mon_regs mon_dram_regs;
|
||||
const struct iwl_fw_mon_regs mon_smem_regs;
|
||||
const struct iwl_fw_mon_regs mon_dbgi_regs;
|
||||
};
|
||||
|
||||
#define IWL_CFG_ANY (~0)
|
||||
@@ -450,8 +468,10 @@ struct iwl_cfg {
|
||||
#define IWL_CFG_MAC_TYPE_PU 0x31
|
||||
#define IWL_CFG_MAC_TYPE_TH 0x32
|
||||
#define IWL_CFG_MAC_TYPE_QU 0x33
|
||||
#define IWL_CFG_MAC_TYPE_CC 0x34
|
||||
#define IWL_CFG_MAC_TYPE_QUZ 0x35
|
||||
#define IWL_CFG_MAC_TYPE_SO 0x37
|
||||
#define IWL_CFG_MAC_TYPE_TY 0x42
|
||||
#define IWL_CFG_MAC_TYPE_SOF 0x43
|
||||
#define IWL_CFG_MAC_TYPE_MA 0x44
|
||||
#define IWL_CFG_MAC_TYPE_BZ 0x46
|
||||
@@ -460,9 +480,9 @@ struct iwl_cfg {
|
||||
#define IWL_CFG_MAC_TYPE_SC2 0x49
|
||||
#define IWL_CFG_MAC_TYPE_SC2F 0x4A
|
||||
#define IWL_CFG_MAC_TYPE_BZ_W 0x4B
|
||||
#define IWL_CFG_MAC_TYPE_BR 0x4C
|
||||
#define IWL_CFG_MAC_TYPE_DR 0x4D
|
||||
|
||||
#define IWL_CFG_RF_TYPE_TH 0x105
|
||||
#define IWL_CFG_RF_TYPE_TH1 0x108
|
||||
#define IWL_CFG_RF_TYPE_JF2 0x105
|
||||
#define IWL_CFG_RF_TYPE_JF1 0x108
|
||||
#define IWL_CFG_RF_TYPE_HR2 0x10A
|
||||
@@ -470,6 +490,7 @@ struct iwl_cfg {
|
||||
#define IWL_CFG_RF_TYPE_GF 0x10D
|
||||
#define IWL_CFG_RF_TYPE_FM 0x112
|
||||
#define IWL_CFG_RF_TYPE_WH 0x113
|
||||
#define IWL_CFG_RF_TYPE_PE 0x114
|
||||
|
||||
#define IWL_CFG_RF_ID_TH 0x1
|
||||
#define IWL_CFG_RF_ID_TH1 0x1
|
||||
@@ -479,12 +500,6 @@ struct iwl_cfg {
|
||||
#define IWL_CFG_RF_ID_HR 0x7
|
||||
#define IWL_CFG_RF_ID_HR1 0x4
|
||||
|
||||
#define IWL_CFG_NO_160 0x1
|
||||
#define IWL_CFG_160 0x0
|
||||
|
||||
#define IWL_CFG_NO_320 0x1
|
||||
#define IWL_CFG_320 0x0
|
||||
|
||||
#define IWL_CFG_CORES_BT 0x0
|
||||
#define IWL_CFG_CORES_BT_GNSS 0x5
|
||||
|
||||
@@ -495,52 +510,134 @@ struct iwl_cfg {
|
||||
#define IWL_CFG_IS_JACKET 0x1
|
||||
|
||||
#define IWL_SUBDEVICE_RF_ID(subdevice) ((u16)((subdevice) & 0x00F0) >> 4)
|
||||
#define IWL_SUBDEVICE_NO_160(subdevice) ((u16)((subdevice) & 0x0200) >> 9)
|
||||
#define IWL_SUBDEVICE_BW_LIM(subdevice) ((u16)((subdevice) & 0x0200) >> 9)
|
||||
#define IWL_SUBDEVICE_CORES(subdevice) ((u16)((subdevice) & 0x1C00) >> 10)
|
||||
|
||||
struct iwl_dev_info {
|
||||
const struct iwl_rf_cfg *cfg;
|
||||
const char *name;
|
||||
u16 device;
|
||||
u16 subdevice;
|
||||
u16 mac_type;
|
||||
u16 rf_type;
|
||||
u8 mac_step;
|
||||
u8 rf_step;
|
||||
u8 rf_id;
|
||||
u8 no_160;
|
||||
u8 cores;
|
||||
u8 cdb;
|
||||
u8 jacket;
|
||||
const struct iwl_cfg *cfg;
|
||||
const char *name;
|
||||
u32 subdevice_m_l:4,
|
||||
subdevice_m_h:4,
|
||||
match_rf_type:1,
|
||||
rf_type:9,
|
||||
match_bw_limit:1,
|
||||
bw_limit:1,
|
||||
match_discrete:1,
|
||||
discrete:1,
|
||||
match_rf_id:1,
|
||||
rf_id:4,
|
||||
match_cdb:1,
|
||||
cdb:1;
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_IWLWIFI_KUNIT_TESTS)
|
||||
extern const struct iwl_dev_info iwl_dev_info_table[];
|
||||
extern const unsigned int iwl_dev_info_table_size;
|
||||
const struct iwl_dev_info *
|
||||
iwl_pci_find_dev_info(u16 device, u16 subsystem_device,
|
||||
u16 mac_type, u8 mac_step, u16 rf_type, u8 cdb,
|
||||
u8 jacket, u8 rf_id, u8 no_160, u8 cores, u8 rf_step);
|
||||
extern const struct pci_device_id iwl_hw_card_ids[];
|
||||
#endif
|
||||
|
||||
const struct iwl_dev_info *
|
||||
iwl_pci_find_dev_info(u16 device, u16 subsystem_device, u16 rf_type, u8 cdb,
|
||||
u8 rf_id, u8 bw_limit, bool discrete);
|
||||
|
||||
/*
|
||||
* This list declares the config structures for all devices.
|
||||
*/
|
||||
extern const struct iwl_cfg_trans_params iwl9000_trans_cfg;
|
||||
extern const struct iwl_cfg_trans_params iwl9560_trans_cfg;
|
||||
extern const struct iwl_cfg_trans_params iwl9560_long_latency_trans_cfg;
|
||||
extern const struct iwl_cfg_trans_params iwl9560_shared_clk_trans_cfg;
|
||||
extern const struct iwl_cfg_trans_params iwl_qu_trans_cfg;
|
||||
extern const struct iwl_cfg_trans_params iwl_qu_medium_latency_trans_cfg;
|
||||
extern const struct iwl_cfg_trans_params iwl_qu_long_latency_trans_cfg;
|
||||
extern const struct iwl_cfg_trans_params iwl_ax200_trans_cfg;
|
||||
extern const struct iwl_cfg_trans_params iwl_so_trans_cfg;
|
||||
extern const struct iwl_cfg_trans_params iwl_so_long_latency_trans_cfg;
|
||||
extern const struct iwl_cfg_trans_params iwl_so_long_latency_imr_trans_cfg;
|
||||
extern const struct iwl_cfg_trans_params iwl_ma_trans_cfg;
|
||||
extern const struct iwl_cfg_trans_params iwl_bz_trans_cfg;
|
||||
extern const struct iwl_cfg_trans_params iwl_sc_trans_cfg;
|
||||
extern const struct iwl_mac_cfg iwl1000_mac_cfg;
|
||||
extern const struct iwl_mac_cfg iwl5000_mac_cfg;
|
||||
extern const struct iwl_mac_cfg iwl2000_mac_cfg;
|
||||
extern const struct iwl_mac_cfg iwl2030_mac_cfg;
|
||||
extern const struct iwl_mac_cfg iwl105_mac_cfg;
|
||||
extern const struct iwl_mac_cfg iwl135_mac_cfg;
|
||||
extern const struct iwl_mac_cfg iwl5150_mac_cfg;
|
||||
extern const struct iwl_mac_cfg iwl6005_mac_cfg;
|
||||
extern const struct iwl_mac_cfg iwl6030_mac_cfg;
|
||||
extern const struct iwl_mac_cfg iwl6000i_mac_cfg;
|
||||
extern const struct iwl_mac_cfg iwl6050_mac_cfg;
|
||||
extern const struct iwl_mac_cfg iwl6150_mac_cfg;
|
||||
extern const struct iwl_mac_cfg iwl6000_mac_cfg;
|
||||
extern const struct iwl_mac_cfg iwl7000_mac_cfg;
|
||||
extern const struct iwl_mac_cfg iwl8000_mac_cfg;
|
||||
extern const struct iwl_mac_cfg iwl9000_mac_cfg;
|
||||
extern const struct iwl_mac_cfg iwl9560_mac_cfg;
|
||||
extern const struct iwl_mac_cfg iwl9560_long_latency_mac_cfg;
|
||||
extern const struct iwl_mac_cfg iwl9560_shared_clk_mac_cfg;
|
||||
extern const struct iwl_mac_cfg iwl_qu_mac_cfg;
|
||||
extern const struct iwl_mac_cfg iwl_qu_medium_latency_mac_cfg;
|
||||
extern const struct iwl_mac_cfg iwl_qu_long_latency_mac_cfg;
|
||||
extern const struct iwl_mac_cfg iwl_ax200_mac_cfg;
|
||||
extern const struct iwl_mac_cfg iwl_ty_mac_cfg;
|
||||
extern const struct iwl_mac_cfg iwl_so_mac_cfg;
|
||||
extern const struct iwl_mac_cfg iwl_so_long_latency_mac_cfg;
|
||||
extern const struct iwl_mac_cfg iwl_so_long_latency_imr_mac_cfg;
|
||||
extern const struct iwl_mac_cfg iwl_ma_mac_cfg;
|
||||
extern const struct iwl_mac_cfg iwl_bz_mac_cfg;
|
||||
extern const struct iwl_mac_cfg iwl_gl_mac_cfg;
|
||||
extern const struct iwl_mac_cfg iwl_sc_mac_cfg;
|
||||
extern const struct iwl_mac_cfg iwl_dr_mac_cfg;
|
||||
|
||||
extern const char iwl1000_bgn_name[];
|
||||
extern const char iwl1000_bg_name[];
|
||||
extern const char iwl100_bgn_name[];
|
||||
extern const char iwl100_bg_name[];
|
||||
extern const char iwl2000_2bgn_name[];
|
||||
extern const char iwl2000_2bgn_d_name[];
|
||||
extern const char iwl2030_2bgn_name[];
|
||||
extern const char iwl105_bgn_name[];
|
||||
extern const char iwl105_bgn_d_name[];
|
||||
extern const char iwl135_bgn_name[];
|
||||
extern const char iwl5300_agn_name[];
|
||||
extern const char iwl5100_bgn_name[];
|
||||
extern const char iwl5100_abg_name[];
|
||||
extern const char iwl5100_agn_name[];
|
||||
extern const char iwl5350_agn_name[];
|
||||
extern const char iwl5150_agn_name[];
|
||||
extern const char iwl5150_abg_name[];
|
||||
extern const char iwl6005_2agn_name[];
|
||||
extern const char iwl6005_2abg_name[];
|
||||
extern const char iwl6005_2bg_name[];
|
||||
extern const char iwl6005_2agn_sff_name[];
|
||||
extern const char iwl6005_2agn_d_name[];
|
||||
extern const char iwl6005_2agn_mow1_name[];
|
||||
extern const char iwl6005_2agn_mow2_name[];
|
||||
extern const char iwl6030_2agn_name[];
|
||||
extern const char iwl6030_2abg_name[];
|
||||
extern const char iwl6030_2bgn_name[];
|
||||
extern const char iwl6030_2bg_name[];
|
||||
extern const char iwl6035_2agn_name[];
|
||||
extern const char iwl6035_2agn_sff_name[];
|
||||
extern const char iwl1030_bgn_name[];
|
||||
extern const char iwl1030_bg_name[];
|
||||
extern const char iwl130_bgn_name[];
|
||||
extern const char iwl130_bg_name[];
|
||||
extern const char iwl6000i_2agn_name[];
|
||||
extern const char iwl6000i_2abg_name[];
|
||||
extern const char iwl6000i_2bg_name[];
|
||||
extern const char iwl6050_2agn_name[];
|
||||
extern const char iwl6050_2abg_name[];
|
||||
extern const char iwl6150_bgn_name[];
|
||||
extern const char iwl6150_bg_name[];
|
||||
extern const char iwl6000_3agn_name[];
|
||||
extern const char iwl7260_2ac_name[];
|
||||
extern const char iwl7260_2n_name[];
|
||||
extern const char iwl7260_n_name[];
|
||||
extern const char iwl3160_2ac_name[];
|
||||
extern const char iwl3160_2n_name[];
|
||||
extern const char iwl3160_n_name[];
|
||||
extern const char iwl3165_2ac_name[];
|
||||
extern const char iwl3168_2ac_name[];
|
||||
extern const char iwl7265_2ac_name[];
|
||||
extern const char iwl7265_2n_name[];
|
||||
extern const char iwl7265_n_name[];
|
||||
extern const char iwl8260_2n_name[];
|
||||
extern const char iwl8260_2ac_name[];
|
||||
extern const char iwl8265_2ac_name[];
|
||||
extern const char iwl8275_2ac_name[];
|
||||
extern const char iwl4165_2ac_name[];
|
||||
extern const char iwl_killer_1435i_name[];
|
||||
extern const char iwl_killer_1434_kix_name[];
|
||||
extern const char iwl9162_name[];
|
||||
extern const char iwl9260_name[];
|
||||
extern const char iwl9260_1_name[];
|
||||
@@ -559,7 +656,6 @@ extern const char iwl9560_killer_1550i_name[];
|
||||
extern const char iwl9560_killer_1550s_name[];
|
||||
extern const char iwl_ax200_name[];
|
||||
extern const char iwl_ax203_name[];
|
||||
extern const char iwl_ax204_name[];
|
||||
extern const char iwl_ax201_name[];
|
||||
extern const char iwl_ax101_name[];
|
||||
extern const char iwl_ax200_killer_1650w_name[];
|
||||
@@ -574,124 +670,84 @@ extern const char iwl_ax211_killer_1675s_name[];
|
||||
extern const char iwl_ax211_killer_1675i_name[];
|
||||
extern const char iwl_ax411_killer_1690s_name[];
|
||||
extern const char iwl_ax411_killer_1690i_name[];
|
||||
extern const char iwl_ax210_name[];
|
||||
extern const char iwl_ax211_name[];
|
||||
extern const char iwl_ax221_name[];
|
||||
extern const char iwl_ax231_name[];
|
||||
extern const char iwl_ax411_name[];
|
||||
extern const char iwl_bz_name[];
|
||||
extern const char iwl_fm_name[];
|
||||
extern const char iwl_gl_name[];
|
||||
extern const char iwl_mtp_name[];
|
||||
extern const char iwl_sc_name[];
|
||||
extern const char iwl_sc2_name[];
|
||||
extern const char iwl_sc2f_name[];
|
||||
extern const char iwl_killer_be1750s_name[];
|
||||
extern const char iwl_killer_be1750i_name[];
|
||||
extern const char iwl_killer_be1750w_name[];
|
||||
extern const char iwl_killer_be1750x_name[];
|
||||
extern const char iwl_killer_be1790s_name[];
|
||||
extern const char iwl_killer_be1790i_name[];
|
||||
extern const char iwl_be201_name[];
|
||||
extern const char iwl_be200_name[];
|
||||
extern const char iwl_be202_name[];
|
||||
extern const char iwl_be401_name[];
|
||||
extern const char iwl_be213_name[];
|
||||
extern const char iwl_killer_be1775s_name[];
|
||||
extern const char iwl_killer_be1775i_name[];
|
||||
extern const char iwl_be211_name[];
|
||||
extern const char iwl_killer_bn1850w2_name[];
|
||||
extern const char iwl_killer_bn1850i_name[];
|
||||
extern const char iwl_bn201_name[];
|
||||
extern const char iwl_be221_name[];
|
||||
extern const char iwl_be223_name[];
|
||||
#if IS_ENABLED(CONFIG_IWLDVM)
|
||||
extern const struct iwl_cfg iwl5300_agn_cfg;
|
||||
extern const struct iwl_cfg iwl5100_agn_cfg;
|
||||
extern const struct iwl_cfg iwl5350_agn_cfg;
|
||||
extern const struct iwl_cfg iwl5100_bgn_cfg;
|
||||
extern const struct iwl_cfg iwl5100_abg_cfg;
|
||||
extern const struct iwl_cfg iwl5150_agn_cfg;
|
||||
extern const struct iwl_cfg iwl5150_abg_cfg;
|
||||
extern const struct iwl_cfg iwl6005_2agn_cfg;
|
||||
extern const struct iwl_cfg iwl6005_2abg_cfg;
|
||||
extern const struct iwl_cfg iwl6005_2bg_cfg;
|
||||
extern const struct iwl_cfg iwl6005_2agn_sff_cfg;
|
||||
extern const struct iwl_cfg iwl6005_2agn_d_cfg;
|
||||
extern const struct iwl_cfg iwl6005_2agn_mow1_cfg;
|
||||
extern const struct iwl_cfg iwl6005_2agn_mow2_cfg;
|
||||
extern const struct iwl_cfg iwl1030_bgn_cfg;
|
||||
extern const struct iwl_cfg iwl1030_bg_cfg;
|
||||
extern const struct iwl_cfg iwl6030_2agn_cfg;
|
||||
extern const struct iwl_cfg iwl6030_2abg_cfg;
|
||||
extern const struct iwl_cfg iwl6030_2bgn_cfg;
|
||||
extern const struct iwl_cfg iwl6030_2bg_cfg;
|
||||
extern const struct iwl_cfg iwl6000i_2agn_cfg;
|
||||
extern const struct iwl_cfg iwl6000i_2abg_cfg;
|
||||
extern const struct iwl_cfg iwl6000i_2bg_cfg;
|
||||
extern const struct iwl_cfg iwl6000_3agn_cfg;
|
||||
extern const struct iwl_cfg iwl6050_2agn_cfg;
|
||||
extern const struct iwl_cfg iwl6050_2abg_cfg;
|
||||
extern const struct iwl_cfg iwl6150_bgn_cfg;
|
||||
extern const struct iwl_cfg iwl6150_bg_cfg;
|
||||
extern const struct iwl_cfg iwl1000_bgn_cfg;
|
||||
extern const struct iwl_cfg iwl1000_bg_cfg;
|
||||
extern const struct iwl_cfg iwl100_bgn_cfg;
|
||||
extern const struct iwl_cfg iwl100_bg_cfg;
|
||||
extern const struct iwl_cfg iwl130_bgn_cfg;
|
||||
extern const struct iwl_cfg iwl130_bg_cfg;
|
||||
extern const struct iwl_cfg iwl2000_2bgn_cfg;
|
||||
extern const struct iwl_cfg iwl2000_2bgn_d_cfg;
|
||||
extern const struct iwl_cfg iwl2030_2bgn_cfg;
|
||||
extern const struct iwl_cfg iwl6035_2agn_cfg;
|
||||
extern const struct iwl_cfg iwl6035_2agn_sff_cfg;
|
||||
extern const struct iwl_cfg iwl105_bgn_cfg;
|
||||
extern const struct iwl_cfg iwl105_bgn_d_cfg;
|
||||
extern const struct iwl_cfg iwl135_bgn_cfg;
|
||||
extern const struct iwl_rf_cfg iwl5300_agn_cfg;
|
||||
extern const struct iwl_rf_cfg iwl5350_agn_cfg;
|
||||
extern const struct iwl_rf_cfg iwl5100_n_cfg;
|
||||
extern const struct iwl_rf_cfg iwl5100_abg_cfg;
|
||||
extern const struct iwl_rf_cfg iwl5150_agn_cfg;
|
||||
extern const struct iwl_rf_cfg iwl5150_abg_cfg;
|
||||
extern const struct iwl_rf_cfg iwl6005_non_n_cfg;
|
||||
extern const struct iwl_rf_cfg iwl6005_n_cfg;
|
||||
extern const struct iwl_rf_cfg iwl6030_n_cfg;
|
||||
extern const struct iwl_rf_cfg iwl6030_non_n_cfg;
|
||||
extern const struct iwl_rf_cfg iwl6000i_2agn_cfg;
|
||||
extern const struct iwl_rf_cfg iwl6000i_non_n_cfg;
|
||||
extern const struct iwl_rf_cfg iwl6000i_non_n_cfg;
|
||||
extern const struct iwl_rf_cfg iwl6000_3agn_cfg;
|
||||
extern const struct iwl_rf_cfg iwl6050_2agn_cfg;
|
||||
extern const struct iwl_rf_cfg iwl6050_2abg_cfg;
|
||||
extern const struct iwl_rf_cfg iwl6150_bgn_cfg;
|
||||
extern const struct iwl_rf_cfg iwl6150_bg_cfg;
|
||||
extern const struct iwl_rf_cfg iwl1000_bgn_cfg;
|
||||
extern const struct iwl_rf_cfg iwl1000_bg_cfg;
|
||||
extern const struct iwl_rf_cfg iwl100_bgn_cfg;
|
||||
extern const struct iwl_rf_cfg iwl100_bg_cfg;
|
||||
extern const struct iwl_rf_cfg iwl130_bgn_cfg;
|
||||
extern const struct iwl_rf_cfg iwl130_bg_cfg;
|
||||
extern const struct iwl_rf_cfg iwl2000_2bgn_cfg;
|
||||
extern const struct iwl_rf_cfg iwl2030_2bgn_cfg;
|
||||
extern const struct iwl_rf_cfg iwl6035_2agn_cfg;
|
||||
extern const struct iwl_rf_cfg iwl105_bgn_cfg;
|
||||
extern const struct iwl_rf_cfg iwl135_bgn_cfg;
|
||||
#endif /* CONFIG_IWLDVM */
|
||||
#if IS_ENABLED(CONFIG_IWLMVM)
|
||||
extern const struct iwl_ht_params iwl_22000_ht_params;
|
||||
extern const struct iwl_cfg iwl7260_2ac_cfg;
|
||||
extern const struct iwl_cfg iwl7260_2ac_cfg_high_temp;
|
||||
extern const struct iwl_cfg iwl7260_2n_cfg;
|
||||
extern const struct iwl_cfg iwl7260_n_cfg;
|
||||
extern const struct iwl_cfg iwl3160_2ac_cfg;
|
||||
extern const struct iwl_cfg iwl3160_2n_cfg;
|
||||
extern const struct iwl_cfg iwl3160_n_cfg;
|
||||
extern const struct iwl_cfg iwl3165_2ac_cfg;
|
||||
extern const struct iwl_cfg iwl3168_2ac_cfg;
|
||||
extern const struct iwl_cfg iwl7265_2ac_cfg;
|
||||
extern const struct iwl_cfg iwl7265_2n_cfg;
|
||||
extern const struct iwl_cfg iwl7265_n_cfg;
|
||||
extern const struct iwl_cfg iwl7265d_2ac_cfg;
|
||||
extern const struct iwl_cfg iwl7265d_2n_cfg;
|
||||
extern const struct iwl_cfg iwl7265d_n_cfg;
|
||||
extern const struct iwl_cfg iwl8260_2n_cfg;
|
||||
extern const struct iwl_cfg iwl8260_2ac_cfg;
|
||||
extern const struct iwl_cfg iwl8265_2ac_cfg;
|
||||
extern const struct iwl_cfg iwl8275_2ac_cfg;
|
||||
extern const struct iwl_cfg iwl4165_2ac_cfg;
|
||||
extern const struct iwl_cfg iwl9260_2ac_cfg;
|
||||
extern const struct iwl_cfg iwl9560_qu_b0_jf_b0_cfg;
|
||||
extern const struct iwl_cfg iwl9560_qu_c0_jf_b0_cfg;
|
||||
extern const struct iwl_cfg iwl9560_quz_a0_jf_b0_cfg;
|
||||
extern const struct iwl_cfg iwl9560_2ac_cfg_soc;
|
||||
extern const struct iwl_cfg iwl_qu_b0_hr1_b0;
|
||||
extern const struct iwl_cfg iwl_qu_c0_hr1_b0;
|
||||
extern const struct iwl_cfg iwl_quz_a0_hr1_b0;
|
||||
extern const struct iwl_cfg iwl_qu_b0_hr_b0;
|
||||
extern const struct iwl_cfg iwl_qu_c0_hr_b0;
|
||||
extern const struct iwl_cfg iwl_ax200_cfg_cc;
|
||||
extern const struct iwl_cfg iwl_ax201_cfg_qu_hr;
|
||||
extern const struct iwl_cfg iwl_ax201_cfg_qu_c0_hr_b0;
|
||||
extern const struct iwl_cfg iwl_ax201_cfg_quz_hr;
|
||||
extern const struct iwl_cfg iwl_ax1650i_cfg_quz_hr;
|
||||
extern const struct iwl_cfg iwl_ax1650s_cfg_quz_hr;
|
||||
extern const struct iwl_cfg killer1650s_2ax_cfg_qu_b0_hr_b0;
|
||||
extern const struct iwl_cfg killer1650i_2ax_cfg_qu_b0_hr_b0;
|
||||
extern const struct iwl_cfg killer1650s_2ax_cfg_qu_c0_hr_b0;
|
||||
extern const struct iwl_cfg killer1650i_2ax_cfg_qu_c0_hr_b0;
|
||||
extern const struct iwl_cfg killer1650x_2ax_cfg;
|
||||
extern const struct iwl_cfg killer1650w_2ax_cfg;
|
||||
extern const struct iwl_cfg iwlax210_2ax_cfg_so_jf_b0;
|
||||
extern const struct iwl_cfg iwlax211_2ax_cfg_so_gf_a0;
|
||||
extern const struct iwl_cfg iwlax211_2ax_cfg_so_gf_a0_long;
|
||||
extern const struct iwl_cfg iwlax210_2ax_cfg_ty_gf_a0;
|
||||
extern const struct iwl_cfg iwlax411_2ax_cfg_so_gf4_a0;
|
||||
extern const struct iwl_cfg iwlax411_2ax_cfg_so_gf4_a0_long;
|
||||
extern const struct iwl_rf_cfg iwl7260_cfg;
|
||||
extern const struct iwl_rf_cfg iwl7260_high_temp_cfg;
|
||||
extern const struct iwl_rf_cfg iwl3160_cfg;
|
||||
extern const struct iwl_rf_cfg iwl3165_2ac_cfg;
|
||||
extern const struct iwl_rf_cfg iwl3168_2ac_cfg;
|
||||
extern const struct iwl_rf_cfg iwl7265_cfg;
|
||||
extern const struct iwl_rf_cfg iwl7265d_cfg;
|
||||
extern const struct iwl_rf_cfg iwl8260_cfg;
|
||||
extern const struct iwl_rf_cfg iwl8265_cfg;
|
||||
extern const struct iwl_rf_cfg iwl_rf_jf;
|
||||
extern const struct iwl_rf_cfg iwl_rf_jf_80mhz;
|
||||
extern const struct iwl_rf_cfg iwl_rf_hr1;
|
||||
extern const struct iwl_rf_cfg iwl_rf_hr;
|
||||
extern const struct iwl_rf_cfg iwl_rf_hr_80mhz;
|
||||
|
||||
extern const struct iwl_cfg iwl_cfg_ma;
|
||||
|
||||
extern const struct iwl_cfg iwl_cfg_so_a0_hr_a0;
|
||||
extern const struct iwl_cfg iwl_cfg_so_a0_ms_a0;
|
||||
extern const struct iwl_cfg iwl_cfg_quz_a0_hr_b0;
|
||||
|
||||
extern const struct iwl_cfg iwl_cfg_bz;
|
||||
extern const struct iwl_cfg iwl_cfg_gl;
|
||||
|
||||
extern const struct iwl_cfg iwl_cfg_sc;
|
||||
extern const struct iwl_cfg iwl_cfg_sc2;
|
||||
extern const struct iwl_cfg iwl_cfg_sc2f;
|
||||
extern const struct iwl_rf_cfg iwl_rf_gf;
|
||||
#endif /* CONFIG_IWLMVM */
|
||||
|
||||
#if IS_ENABLED(CONFIG_IWLMLD)
|
||||
extern const struct iwl_rf_cfg iwl_rf_fm;
|
||||
extern const struct iwl_rf_cfg iwl_rf_fm_160mhz;
|
||||
#define iwl_rf_wh iwl_rf_fm
|
||||
#define iwl_rf_wh_160mhz iwl_rf_fm_160mhz
|
||||
#define iwl_rf_pe iwl_rf_fm
|
||||
#endif /* CONFIG_IWLMLD */
|
||||
|
||||
#endif /* __IWL_CONFIG_H__ */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2005-2014, 2018-2024 Intel Corporation
|
||||
* Copyright (C) 2005-2014, 2018-2025 Intel Corporation
|
||||
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016 Intel Deutschland GmbH
|
||||
*/
|
||||
@@ -107,6 +107,14 @@
|
||||
/* GIO Chicken Bits (PCI Express bus link power management) */
|
||||
#define CSR_GIO_CHICKEN_BITS (CSR_BASE+0x100)
|
||||
|
||||
#define CSR_IPC_STATE (CSR_BASE + 0x110)
|
||||
#define CSR_IPC_STATE_RESET 0x00000030
|
||||
#define CSR_IPC_STATE_RESET_NONE 0
|
||||
#define CSR_IPC_STATE_RESET_SW_READY 1
|
||||
#define CSR_IPC_STATE_RESET_TOP_READY 2
|
||||
#define CSR_IPC_STATE_RESET_TOP_FOLLOWER 3
|
||||
#define CSR_IPC_STATE_TOP_RESET_REQ BIT(6)
|
||||
|
||||
#define CSR_IPC_SLEEP_CONTROL (CSR_BASE + 0x114)
|
||||
#define CSR_IPC_SLEEP_CONTROL_SUSPEND 0x3
|
||||
#define CSR_IPC_SLEEP_CONTROL_RESUME 0
|
||||
@@ -148,6 +156,7 @@
|
||||
* during a error FW error.
|
||||
*/
|
||||
#define CSR_FUNC_SCRATCH_INIT_VALUE (0x01010101)
|
||||
#define CSR_FUNC_SCRATCH_POWER_OFF_MASK 0xFFFF
|
||||
|
||||
/* Bits for CSR_HW_IF_CONFIG_REG */
|
||||
#define CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP_DASH (0x0000000F)
|
||||
@@ -167,13 +176,15 @@
|
||||
#define CSR_HW_IF_CONFIG_REG_POS_PHY_DASH (12)
|
||||
#define CSR_HW_IF_CONFIG_REG_POS_PHY_STEP (14)
|
||||
|
||||
#define CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A (0x00080000)
|
||||
#define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM (0x00200000)
|
||||
#define CSR_HW_IF_CONFIG_REG_BIT_NIC_READY (0x00400000) /* PCI_OWN_SEM */
|
||||
#define CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE (0x02000000) /* ME_OWN */
|
||||
#define CSR_HW_IF_CONFIG_REG_PREPARE (0x08000000) /* WAKE_ME */
|
||||
#define CSR_HW_IF_CONFIG_REG_ENABLE_PME (0x10000000)
|
||||
#define CSR_HW_IF_CONFIG_REG_PERSIST_MODE (0x40000000) /* PERSISTENCE */
|
||||
#define CSR_HW_IF_CONFIG_REG_HAP_WAKE 0x00080000
|
||||
/* NOTE: EEPROM_OWN_SEM is no longer defined for new HW */
|
||||
#define CSR_HW_IF_CONFIG_REG_EEPROM_OWN_SEM 0x00200000
|
||||
#define CSR_HW_IF_CONFIG_REG_PCI_OWN_SET 0x00400000
|
||||
#define CSR_HW_IF_CONFIG_REG_IAMT_UP 0x01000000
|
||||
#define CSR_HW_IF_CONFIG_REG_ME_OWN 0x02000000
|
||||
#define CSR_HW_IF_CONFIG_REG_WAKE_ME 0x08000000
|
||||
#define CSR_HW_IF_CONFIG_REG_WAKE_ME_PCIE_OWNER_EN 0x10000000
|
||||
#define CSR_HW_IF_CONFIG_REG_PERSISTENCE 0x40000000
|
||||
|
||||
#define CSR_MBOX_SET_REG_OS_ALIVE BIT(5)
|
||||
|
||||
@@ -191,17 +202,19 @@
|
||||
#define CSR_INT_BIT_RF_KILL (1 << 7) /* HW RFKILL switch GP_CNTRL[27] toggled */
|
||||
#define CSR_INT_BIT_CT_KILL (1 << 6) /* Critical temp (chip too hot) rfkill */
|
||||
#define CSR_INT_BIT_SW_RX (1 << 3) /* Rx, command responses */
|
||||
#define CSR_INT_BIT_RESET_DONE (1 << 2) /* reset handshake with firmware is done */
|
||||
#define CSR_INT_BIT_WAKEUP (1 << 1) /* NIC controller waking up (pwr mgmt) */
|
||||
#define CSR_INT_BIT_ALIVE (1 << 0) /* uCode interrupts once it initializes */
|
||||
|
||||
#define CSR_INI_SET_MASK (CSR_INT_BIT_FH_RX | \
|
||||
CSR_INT_BIT_HW_ERR | \
|
||||
CSR_INT_BIT_FH_TX | \
|
||||
CSR_INT_BIT_SW_ERR | \
|
||||
CSR_INT_BIT_RF_KILL | \
|
||||
CSR_INT_BIT_SW_RX | \
|
||||
CSR_INT_BIT_WAKEUP | \
|
||||
CSR_INT_BIT_ALIVE | \
|
||||
#define CSR_INI_SET_MASK (CSR_INT_BIT_FH_RX | \
|
||||
CSR_INT_BIT_HW_ERR | \
|
||||
CSR_INT_BIT_FH_TX | \
|
||||
CSR_INT_BIT_SW_ERR | \
|
||||
CSR_INT_BIT_RF_KILL | \
|
||||
CSR_INT_BIT_SW_RX | \
|
||||
CSR_INT_BIT_WAKEUP | \
|
||||
CSR_INT_BIT_RESET_DONE | \
|
||||
CSR_INT_BIT_ALIVE | \
|
||||
CSR_INT_BIT_RX_PERIODIC)
|
||||
|
||||
/* interrupt flags in FH (flow handler) (PCI busmaster DMA) */
|
||||
@@ -351,7 +364,6 @@ enum {
|
||||
#define CSR_HW_RF_ID_TYPE_HRCDB (0x00109F00)
|
||||
#define CSR_HW_RF_ID_TYPE_GF (0x0010D000)
|
||||
#define CSR_HW_RF_ID_TYPE_GF4 (0x0010E000)
|
||||
#define CSR_HW_RF_ID_TYPE_MS (0x00111000)
|
||||
#define CSR_HW_RF_ID_TYPE_FM (0x00112000)
|
||||
#define CSR_HW_RF_ID_TYPE_WP (0x00113000)
|
||||
|
||||
@@ -639,7 +651,7 @@ enum msix_hw_int_causes {
|
||||
* HW address related registers *
|
||||
*****************************************************************************/
|
||||
|
||||
#define CSR_ADDR_BASE(trans) ((trans)->cfg->mac_addr_from_csr)
|
||||
#define CSR_ADDR_BASE(trans) ((trans)->mac_cfg->base->mac_addr_from_csr)
|
||||
#define CSR_MAC_ADDR0_OTP(trans) (CSR_ADDR_BASE(trans) + 0x00)
|
||||
#define CSR_MAC_ADDR1_OTP(trans) (CSR_ADDR_BASE(trans) + 0x04)
|
||||
#define CSR_MAC_ADDR0_STRAP(trans) (CSR_ADDR_BASE(trans) + 0x08)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2018-2024 Intel Corporation
|
||||
* Copyright (C) 2018-2025 Intel Corporation
|
||||
*/
|
||||
#include <linux/firmware.h>
|
||||
#include "iwl-drv.h"
|
||||
@@ -503,7 +503,7 @@ void iwl_dbg_tlv_load_bin(struct device *dev, struct iwl_trans *trans)
|
||||
int res;
|
||||
|
||||
if (!iwlwifi_mod_params.enable_ini ||
|
||||
trans->trans_cfg->device_family <= IWL_DEVICE_FAMILY_8000)
|
||||
trans->mac_cfg->device_family <= IWL_DEVICE_FAMILY_8000)
|
||||
return;
|
||||
|
||||
res = firmware_request_nowarn(&fw, yoyo_bin, dev);
|
||||
@@ -603,11 +603,11 @@ static int iwl_dbg_tlv_alloc_fragments(struct iwl_fw_runtime *fwrt,
|
||||
return 0;
|
||||
|
||||
num_frags = le32_to_cpu(fw_mon_cfg->max_frags_num);
|
||||
if (fwrt->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210) {
|
||||
if (fwrt->trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210) {
|
||||
if (alloc_id != IWL_FW_INI_ALLOCATION_ID_DBGC1)
|
||||
return -EIO;
|
||||
num_frags = 1;
|
||||
} else if (fwrt->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_BZ &&
|
||||
} else if (fwrt->trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_BZ &&
|
||||
alloc_id > IWL_FW_INI_ALLOCATION_ID_DBGC3) {
|
||||
return -EIO;
|
||||
}
|
||||
@@ -949,7 +949,7 @@ static void iwl_dbg_tlv_apply_config(struct iwl_fw_runtime *fwrt,
|
||||
static void iwl_dbg_tlv_periodic_trig_handler(struct timer_list *t)
|
||||
{
|
||||
struct iwl_dbg_tlv_timer_node *timer_node =
|
||||
from_timer(timer_node, t, timer);
|
||||
timer_container_of(timer_node, t, timer);
|
||||
struct iwl_fwrt_dump_data dump_data = {
|
||||
.trig = (void *)timer_node->tlv->data,
|
||||
};
|
||||
@@ -1241,7 +1241,7 @@ iwl_dbg_tlv_tp_trigger(struct iwl_fw_runtime *fwrt, bool sync,
|
||||
|
||||
fwrt->trans->dbg.restart_required = false;
|
||||
|
||||
if (fwrt->trans->trans_cfg->device_family ==
|
||||
if (fwrt->trans->mac_cfg->device_family ==
|
||||
IWL_DEVICE_FAMILY_9000) {
|
||||
fwrt->trans->dbg.restart_required = true;
|
||||
} else if (tp == IWL_FW_INI_TIME_POINT_FW_ASSERT &&
|
||||
@@ -1372,15 +1372,15 @@ void _iwl_dbg_tlv_time_point(struct iwl_fw_runtime *fwrt,
|
||||
switch (tp_id) {
|
||||
case IWL_FW_INI_TIME_POINT_EARLY:
|
||||
iwl_dbg_tlv_init_cfg(fwrt);
|
||||
iwl_dbg_tlv_apply_config(fwrt, conf_list);
|
||||
iwl_dbg_tlv_update_drams(fwrt);
|
||||
iwl_dbg_tlv_tp_trigger(fwrt, sync, trig_list, tp_data, NULL);
|
||||
iwl_dbg_tlv_apply_config(fwrt, conf_list);
|
||||
break;
|
||||
case IWL_FW_INI_TIME_POINT_AFTER_ALIVE:
|
||||
iwl_dbg_tlv_apply_buffers(fwrt);
|
||||
iwl_dbg_tlv_send_hcmds(fwrt, hcmd_list);
|
||||
iwl_dbg_tlv_apply_config(fwrt, conf_list);
|
||||
iwl_dbg_tlv_tp_trigger(fwrt, sync, trig_list, tp_data, NULL);
|
||||
iwl_dbg_tlv_apply_config(fwrt, conf_list);
|
||||
break;
|
||||
case IWL_FW_INI_TIME_POINT_PERIODIC:
|
||||
iwl_dbg_tlv_set_periodic_trigs(fwrt);
|
||||
@@ -1390,14 +1390,14 @@ void _iwl_dbg_tlv_time_point(struct iwl_fw_runtime *fwrt,
|
||||
case IWL_FW_INI_TIME_POINT_MISSED_BEACONS:
|
||||
case IWL_FW_INI_TIME_POINT_FW_DHC_NOTIFICATION:
|
||||
iwl_dbg_tlv_send_hcmds(fwrt, hcmd_list);
|
||||
iwl_dbg_tlv_apply_config(fwrt, conf_list);
|
||||
iwl_dbg_tlv_tp_trigger(fwrt, sync, trig_list, tp_data,
|
||||
iwl_dbg_tlv_check_fw_pkt);
|
||||
iwl_dbg_tlv_apply_config(fwrt, conf_list);
|
||||
break;
|
||||
default:
|
||||
iwl_dbg_tlv_send_hcmds(fwrt, hcmd_list);
|
||||
iwl_dbg_tlv_apply_config(fwrt, conf_list);
|
||||
iwl_dbg_tlv_tp_trigger(fwrt, sync, trig_list, tp_data, NULL);
|
||||
iwl_dbg_tlv_apply_config(fwrt, conf_list);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ enum iwl_dl {
|
||||
IWL_DL_RX = 0x00080000,
|
||||
IWL_DL_SCAN = 0x00100000,
|
||||
IWL_DL_STATS = 0x00200000,
|
||||
/* = 0x00400000, */
|
||||
IWL_DL_EHT = 0x00400000,
|
||||
IWL_DL_TDLS = 0x00800000,
|
||||
IWL_DL_TE = 0x01000000,
|
||||
IWL_DL_TEMP = 0x02000000,
|
||||
@@ -71,8 +71,7 @@ enum iwl_dl {
|
||||
IWL_DL_TX_QUEUES = 0x10000000,
|
||||
IWL_DL_TX_REPLY = 0x20000000,
|
||||
IWL_DL_WEP = 0x40000000,
|
||||
|
||||
IWL_DL_PCI_RW = 0x80000000,
|
||||
IWL_DL_PTP = 0x80000000,
|
||||
|
||||
IWL_DL_ANY = 0x7fffffff,
|
||||
};
|
||||
@@ -161,6 +160,8 @@ void __iwl_dbg(struct device *, u32, bool, const char *, const char *fmt, ...);
|
||||
IWL_DPRINTF(_subsys, IWL_DL_MAC80211, _fmt, ##__VA_ARGS__)
|
||||
#define IWL_DEBUG_POWER(_subsys, _fmt, ...) \
|
||||
IWL_DPRINTF(_subsys, IWL_DL_POWER, _fmt, ##__VA_ARGS__)
|
||||
#define IWL_DEBUG_DEV_POWER(_dev, _fmt, ...) \
|
||||
IWL_DPRINTF_DEV((_dev), IWL_DL_POWER, _fmt, ##__VA_ARGS__)
|
||||
#define IWL_DEBUG_QUOTA(_subsys, _fmt, ...) \
|
||||
IWL_DPRINTF(_subsys, IWL_DL_QUOTA, _fmt, ##__VA_ARGS__)
|
||||
#define IWL_DEBUG_RADIO(_subsys, _fmt, ...) \
|
||||
@@ -197,8 +198,9 @@ void __iwl_dbg(struct device *, u32, bool, const char *, const char *fmt, ...);
|
||||
IWL_DPRINTF(_subsys, IWL_DL_WOWLAN, _fmt, ##__VA_ARGS__)
|
||||
#define IWL_DEBUG_DEV_RADIO(_dev, _fmt, ...) \
|
||||
IWL_DPRINTF_DEV((_dev), IWL_DL_DEV_RADIO, _fmt, ##__VA_ARGS__)
|
||||
|
||||
#define IWL_DEBUG_PCI_RW(_subsys, _fmt, ...) \
|
||||
IWL_DPRINTF(_subsys, IWL_DL_PCI_RW, _fmt, ##__VA_ARGS__)
|
||||
#define IWL_DEBUG_PTP(_subsys, _fmt, ...) \
|
||||
IWL_DPRINTF(_subsys, IWL_DL_PTP, _fmt, ##__VA_ARGS__)
|
||||
#define IWL_DEBUG_EHT(_subsys, _fmt, ...) \
|
||||
IWL_DPRINTF(_subsys, IWL_DL_EHT, _fmt, ##__VA_ARGS__)
|
||||
|
||||
#endif /* _IWL_DEBUG_H */
|
||||
|
||||
+242
-101
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2005-2014, 2018-2024 Intel Corporation
|
||||
* Copyright (C) 2005-2014, 2018-2025 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "iwl-modparams.h"
|
||||
#include "fw/api/alive.h"
|
||||
#include "fw/api/mac.h"
|
||||
#include "fw/api/mac-cfg.h"
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
@@ -92,6 +93,9 @@ struct iwl_drv {
|
||||
enum {
|
||||
DVM_OP_MODE,
|
||||
MVM_OP_MODE,
|
||||
#if IS_ENABLED(CONFIG_IWLMLD)
|
||||
MLD_OP_MODE,
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Protects the table contents, i.e. the ops pointer & drv list */
|
||||
@@ -103,6 +107,9 @@ static struct iwlwifi_opmode_table {
|
||||
} iwlwifi_opmode_table[] = { /* ops set when driver is initialized */
|
||||
[DVM_OP_MODE] = { .name = "iwldvm", .ops = NULL },
|
||||
[MVM_OP_MODE] = { .name = "iwlmvm", .ops = NULL },
|
||||
#if IS_ENABLED(CONFIG_IWLMLD)
|
||||
[MLD_OP_MODE] = { .name = "iwlmld", .ops = NULL },
|
||||
#endif
|
||||
};
|
||||
|
||||
#define IWL_DEFAULT_SCAN_CHANNELS 40
|
||||
@@ -147,6 +154,9 @@ static void iwl_dealloc_ucode(struct iwl_drv *drv)
|
||||
kfree(drv->fw.phy_integration_ver);
|
||||
kfree(drv->trans->dbg.pc_data);
|
||||
drv->trans->dbg.pc_data = NULL;
|
||||
kvfree(drv->fw.pnvm_data);
|
||||
drv->fw.pnvm_data = NULL;
|
||||
drv->fw.pnvm_size = 0;
|
||||
|
||||
for (i = 0; i < IWL_UCODE_TYPE_MAX; i++)
|
||||
iwl_free_fw_img(drv, drv->fw.img + i);
|
||||
@@ -155,8 +165,7 @@ static void iwl_dealloc_ucode(struct iwl_drv *drv)
|
||||
memset(&drv->fw, 0, sizeof(drv->fw));
|
||||
}
|
||||
|
||||
static int iwl_alloc_fw_desc(struct iwl_drv *drv, struct fw_desc *desc,
|
||||
struct fw_sec *sec)
|
||||
static int iwl_alloc_fw_desc(struct fw_desc *desc, struct fw_sec *sec)
|
||||
{
|
||||
void *data;
|
||||
|
||||
@@ -186,22 +195,87 @@ static inline char iwl_drv_get_step(int step)
|
||||
return 'a' + step;
|
||||
}
|
||||
|
||||
static bool iwl_drv_is_wifi7_supported(struct iwl_trans *trans)
|
||||
{
|
||||
return CSR_HW_RFID_TYPE(trans->info.hw_rf_id) >= IWL_CFG_RF_TYPE_FM;
|
||||
}
|
||||
|
||||
const char *iwl_drv_get_fwname_pre(struct iwl_trans *trans, char *buf)
|
||||
{
|
||||
char mac_step, rf_step;
|
||||
const char *rf, *cdb;
|
||||
const char *mac, *rf, *cdb;
|
||||
|
||||
if (trans->cfg->fw_name_pre)
|
||||
return trans->cfg->fw_name_pre;
|
||||
|
||||
if (WARN_ON(!trans->cfg->fw_name_mac))
|
||||
return "unconfigured";
|
||||
mac_step = iwl_drv_get_step(trans->info.hw_rev_step);
|
||||
|
||||
mac_step = iwl_drv_get_step(trans->hw_rev_step);
|
||||
switch (CSR_HW_REV_TYPE(trans->info.hw_rev)) {
|
||||
case IWL_CFG_MAC_TYPE_PU:
|
||||
mac = "9000-pu";
|
||||
mac_step = 'b';
|
||||
break;
|
||||
case IWL_CFG_MAC_TYPE_TH:
|
||||
mac = "9260-th";
|
||||
mac_step = 'b';
|
||||
break;
|
||||
case IWL_CFG_MAC_TYPE_QU:
|
||||
mac = "Qu";
|
||||
break;
|
||||
case IWL_CFG_MAC_TYPE_CC:
|
||||
/* special case - no RF since it's fixed (discrete) */
|
||||
scnprintf(buf, FW_NAME_PRE_BUFSIZE, "iwlwifi-cc-a0");
|
||||
return buf;
|
||||
case IWL_CFG_MAC_TYPE_QUZ:
|
||||
mac = "QuZ";
|
||||
/* all QuZ use A0 firmware */
|
||||
mac_step = 'a';
|
||||
break;
|
||||
case IWL_CFG_MAC_TYPE_SO:
|
||||
case IWL_CFG_MAC_TYPE_SOF:
|
||||
mac = "so";
|
||||
mac_step = 'a';
|
||||
break;
|
||||
case IWL_CFG_MAC_TYPE_TY:
|
||||
mac = "ty";
|
||||
mac_step = 'a';
|
||||
break;
|
||||
case IWL_CFG_MAC_TYPE_MA:
|
||||
mac = "ma";
|
||||
break;
|
||||
case IWL_CFG_MAC_TYPE_BZ:
|
||||
case IWL_CFG_MAC_TYPE_BZ_W:
|
||||
mac = "bz";
|
||||
break;
|
||||
case IWL_CFG_MAC_TYPE_GL:
|
||||
mac = "gl";
|
||||
break;
|
||||
case IWL_CFG_MAC_TYPE_SC:
|
||||
mac = "sc";
|
||||
break;
|
||||
case IWL_CFG_MAC_TYPE_SC2:
|
||||
/* Uses the same firmware as SC2 */
|
||||
case IWL_CFG_MAC_TYPE_SC2F:
|
||||
mac = "sc2";
|
||||
break;
|
||||
case IWL_CFG_MAC_TYPE_BR:
|
||||
mac = "br";
|
||||
break;
|
||||
case IWL_CFG_MAC_TYPE_DR:
|
||||
mac = "dr";
|
||||
break;
|
||||
default:
|
||||
return "unknown-mac";
|
||||
}
|
||||
|
||||
rf_step = iwl_drv_get_step(CSR_HW_RFID_STEP(trans->hw_rf_id));
|
||||
rf_step = iwl_drv_get_step(CSR_HW_RFID_STEP(trans->info.hw_rf_id));
|
||||
|
||||
switch (CSR_HW_RFID_TYPE(trans->hw_rf_id)) {
|
||||
switch (CSR_HW_RFID_TYPE(trans->info.hw_rf_id)) {
|
||||
case IWL_CFG_RF_TYPE_JF1:
|
||||
case IWL_CFG_RF_TYPE_JF2:
|
||||
rf = "jf";
|
||||
rf_step = 'b';
|
||||
break;
|
||||
case IWL_CFG_RF_TYPE_HR1:
|
||||
case IWL_CFG_RF_TYPE_HR2:
|
||||
rf = "hr";
|
||||
@@ -209,29 +283,26 @@ const char *iwl_drv_get_fwname_pre(struct iwl_trans *trans, char *buf)
|
||||
break;
|
||||
case IWL_CFG_RF_TYPE_GF:
|
||||
rf = "gf";
|
||||
rf_step = 'a';
|
||||
break;
|
||||
case IWL_CFG_RF_TYPE_FM:
|
||||
rf = "fm";
|
||||
break;
|
||||
case IWL_CFG_RF_TYPE_WH:
|
||||
if (SILICON_Z_STEP ==
|
||||
CSR_HW_RFID_STEP(trans->hw_rf_id)) {
|
||||
rf = "whtc";
|
||||
rf_step = 'a';
|
||||
} else {
|
||||
rf = "wh";
|
||||
}
|
||||
rf = "wh";
|
||||
break;
|
||||
case IWL_CFG_RF_TYPE_PE:
|
||||
rf = "pe";
|
||||
break;
|
||||
default:
|
||||
return "unknown-rf";
|
||||
}
|
||||
|
||||
cdb = CSR_HW_RFID_IS_CDB(trans->hw_rf_id) ? "4" : "";
|
||||
cdb = CSR_HW_RFID_IS_CDB(trans->info.hw_rf_id) ? "4" : "";
|
||||
|
||||
scnprintf(buf, FW_NAME_PRE_BUFSIZE,
|
||||
"iwlwifi-%s-%c0-%s%s-%c0",
|
||||
trans->cfg->fw_name_mac, mac_step,
|
||||
rf, cdb, rf_step);
|
||||
mac, mac_step, rf, cdb, rf_step);
|
||||
|
||||
return buf;
|
||||
}
|
||||
@@ -240,39 +311,68 @@ IWL_EXPORT_SYMBOL(iwl_drv_get_fwname_pre);
|
||||
static void iwl_req_fw_callback(const struct firmware *ucode_raw,
|
||||
void *context);
|
||||
|
||||
static void iwl_get_ucode_api_versions(struct iwl_trans *trans,
|
||||
unsigned int *api_min,
|
||||
unsigned int *api_max)
|
||||
{
|
||||
const struct iwl_family_base_params *base = trans->mac_cfg->base;
|
||||
const struct iwl_rf_cfg *cfg = trans->cfg;
|
||||
|
||||
/* if the MAC doesn't have range or if its range it higher than the RF's */
|
||||
if (!base->ucode_api_max ||
|
||||
(cfg->ucode_api_max && base->ucode_api_min > cfg->ucode_api_max)) {
|
||||
*api_min = cfg->ucode_api_min;
|
||||
*api_max = cfg->ucode_api_max;
|
||||
return;
|
||||
}
|
||||
|
||||
/* if the RF doesn't have range or if its range it higher than the MAC's */
|
||||
if (!cfg->ucode_api_max ||
|
||||
(base->ucode_api_max && cfg->ucode_api_min > base->ucode_api_max)) {
|
||||
*api_min = base->ucode_api_min;
|
||||
*api_max = base->ucode_api_max;
|
||||
return;
|
||||
}
|
||||
|
||||
*api_min = max(cfg->ucode_api_min, base->ucode_api_min);
|
||||
*api_max = min(cfg->ucode_api_max, base->ucode_api_max);
|
||||
}
|
||||
|
||||
static int iwl_request_firmware(struct iwl_drv *drv, bool first)
|
||||
{
|
||||
const struct iwl_cfg *cfg = drv->trans->cfg;
|
||||
char _fw_name_pre[FW_NAME_PRE_BUFSIZE];
|
||||
unsigned int ucode_api_max, ucode_api_min;
|
||||
const char *fw_name_pre;
|
||||
|
||||
if (drv->trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_9000 &&
|
||||
(drv->trans->hw_rev_step != SILICON_B_STEP &&
|
||||
drv->trans->hw_rev_step != SILICON_C_STEP)) {
|
||||
iwl_get_ucode_api_versions(drv->trans, &ucode_api_min, &ucode_api_max);
|
||||
|
||||
if (drv->trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_9000 &&
|
||||
(drv->trans->info.hw_rev_step != SILICON_B_STEP &&
|
||||
drv->trans->info.hw_rev_step != SILICON_C_STEP)) {
|
||||
IWL_ERR(drv,
|
||||
"Only HW steps B and C are currently supported (0x%0x)\n",
|
||||
drv->trans->hw_rev);
|
||||
drv->trans->info.hw_rev);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
fw_name_pre = iwl_drv_get_fwname_pre(drv->trans, _fw_name_pre);
|
||||
|
||||
if (first)
|
||||
drv->fw_index = cfg->ucode_api_max;
|
||||
drv->fw_index = ucode_api_max;
|
||||
else
|
||||
drv->fw_index--;
|
||||
|
||||
if (drv->fw_index < cfg->ucode_api_min) {
|
||||
if (drv->fw_index < ucode_api_min) {
|
||||
IWL_ERR(drv, "no suitable firmware found!\n");
|
||||
|
||||
if (cfg->ucode_api_min == cfg->ucode_api_max) {
|
||||
if (ucode_api_min == ucode_api_max) {
|
||||
IWL_ERR(drv, "%s-%d is required\n", fw_name_pre,
|
||||
cfg->ucode_api_max);
|
||||
ucode_api_max);
|
||||
} else {
|
||||
IWL_ERR(drv, "minimum version required: %s-%d\n",
|
||||
fw_name_pre, cfg->ucode_api_min);
|
||||
fw_name_pre, ucode_api_min);
|
||||
IWL_ERR(drv, "maximum version supported: %s-%d\n",
|
||||
fw_name_pre, cfg->ucode_api_max);
|
||||
fw_name_pre, ucode_api_max);
|
||||
}
|
||||
|
||||
IWL_ERR(drv,
|
||||
@@ -337,19 +437,9 @@ struct iwl_firmware_pieces {
|
||||
size_t dbg_trigger_tlv_len[FW_DBG_TRIGGER_MAX];
|
||||
struct iwl_fw_dbg_mem_seg_tlv *dbg_mem_tlv;
|
||||
size_t n_mem_tlv;
|
||||
u32 major;
|
||||
};
|
||||
|
||||
/*
|
||||
* These functions are just to extract uCode section data from the pieces
|
||||
* structure.
|
||||
*/
|
||||
static struct fw_sec *get_sec(struct iwl_firmware_pieces *pieces,
|
||||
enum iwl_ucode_type type,
|
||||
int sec)
|
||||
{
|
||||
return &pieces->img[type].sec[sec];
|
||||
}
|
||||
|
||||
static void alloc_sec_data(struct iwl_firmware_pieces *pieces,
|
||||
enum iwl_ucode_type type,
|
||||
int sec)
|
||||
@@ -410,22 +500,18 @@ static void set_sec_offset(struct iwl_firmware_pieces *pieces,
|
||||
/*
|
||||
* Gets uCode section from tlv.
|
||||
*/
|
||||
static int iwl_store_ucode_sec(struct iwl_firmware_pieces *pieces,
|
||||
const void *data, enum iwl_ucode_type type,
|
||||
int size)
|
||||
static int iwl_store_ucode_sec(struct fw_img_parsing *img,
|
||||
const void *data, int size)
|
||||
{
|
||||
struct fw_img_parsing *img;
|
||||
struct fw_sec *sec;
|
||||
const struct fw_sec_parsing *sec_parse;
|
||||
size_t alloc_size;
|
||||
|
||||
if (WARN_ON(!pieces || !data || type >= IWL_UCODE_TYPE_MAX))
|
||||
return -1;
|
||||
if (WARN_ON(!img || !data))
|
||||
return -EINVAL;
|
||||
|
||||
sec_parse = (const struct fw_sec_parsing *)data;
|
||||
|
||||
img = &pieces->img[type];
|
||||
|
||||
alloc_size = sizeof(*img->sec) * (img->sec_counter + 1);
|
||||
sec = krealloc(img->sec, alloc_size, GFP_KERNEL);
|
||||
if (!sec)
|
||||
@@ -921,18 +1007,18 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
|
||||
le32_to_cpup((const __le32 *)tlv_data);
|
||||
break;
|
||||
case IWL_UCODE_TLV_SEC_RT:
|
||||
iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_REGULAR,
|
||||
tlv_len);
|
||||
iwl_store_ucode_sec(&pieces->img[IWL_UCODE_REGULAR],
|
||||
tlv_data, tlv_len);
|
||||
drv->fw.type = IWL_FW_MVM;
|
||||
break;
|
||||
case IWL_UCODE_TLV_SEC_INIT:
|
||||
iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_INIT,
|
||||
tlv_len);
|
||||
iwl_store_ucode_sec(&pieces->img[IWL_UCODE_INIT],
|
||||
tlv_data, tlv_len);
|
||||
drv->fw.type = IWL_FW_MVM;
|
||||
break;
|
||||
case IWL_UCODE_TLV_SEC_WOWLAN:
|
||||
iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_WOWLAN,
|
||||
tlv_len);
|
||||
iwl_store_ucode_sec(&pieces->img[IWL_UCODE_WOWLAN],
|
||||
tlv_data, tlv_len);
|
||||
drv->fw.type = IWL_FW_MVM;
|
||||
break;
|
||||
case IWL_UCODE_TLV_DEF_CALIB:
|
||||
@@ -953,18 +1039,18 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
|
||||
FW_PHY_CFG_RX_CHAIN_POS;
|
||||
break;
|
||||
case IWL_UCODE_TLV_SECURE_SEC_RT:
|
||||
iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_REGULAR,
|
||||
tlv_len);
|
||||
iwl_store_ucode_sec(&pieces->img[IWL_UCODE_REGULAR],
|
||||
tlv_data, tlv_len);
|
||||
drv->fw.type = IWL_FW_MVM;
|
||||
break;
|
||||
case IWL_UCODE_TLV_SECURE_SEC_INIT:
|
||||
iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_INIT,
|
||||
tlv_len);
|
||||
iwl_store_ucode_sec(&pieces->img[IWL_UCODE_INIT],
|
||||
tlv_data, tlv_len);
|
||||
drv->fw.type = IWL_FW_MVM;
|
||||
break;
|
||||
case IWL_UCODE_TLV_SECURE_SEC_WOWLAN:
|
||||
iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_WOWLAN,
|
||||
tlv_len);
|
||||
iwl_store_ucode_sec(&pieces->img[IWL_UCODE_WOWLAN],
|
||||
tlv_data, tlv_len);
|
||||
drv->fw.type = IWL_FW_MVM;
|
||||
break;
|
||||
case IWL_UCODE_TLV_NUM_OF_CPU:
|
||||
@@ -993,19 +1079,19 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
|
||||
break;
|
||||
case IWL_UCODE_TLV_FW_VERSION: {
|
||||
const __le32 *ptr = (const void *)tlv_data;
|
||||
u32 major, minor;
|
||||
u32 minor;
|
||||
u8 local_comp;
|
||||
|
||||
if (tlv_len != sizeof(u32) * 3)
|
||||
goto invalid_tlv_len;
|
||||
|
||||
major = le32_to_cpup(ptr++);
|
||||
pieces->major = le32_to_cpup(ptr++);
|
||||
minor = le32_to_cpup(ptr++);
|
||||
local_comp = le32_to_cpup(ptr);
|
||||
|
||||
snprintf(drv->fw.fw_version,
|
||||
sizeof(drv->fw.fw_version),
|
||||
"%u.%08x.%u %s", major, minor,
|
||||
"%u.%08x.%u %s", pieces->major, minor,
|
||||
local_comp, iwl_reduced_fw_name(drv));
|
||||
break;
|
||||
}
|
||||
@@ -1131,9 +1217,8 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
|
||||
}
|
||||
case IWL_UCODE_TLV_SEC_RT_USNIFFER:
|
||||
*usniffer_images = true;
|
||||
iwl_store_ucode_sec(pieces, tlv_data,
|
||||
IWL_UCODE_REGULAR_USNIFFER,
|
||||
tlv_len);
|
||||
iwl_store_ucode_sec(&pieces->img[IWL_UCODE_REGULAR_USNIFFER],
|
||||
tlv_data, tlv_len);
|
||||
break;
|
||||
case IWL_UCODE_TLV_PAGING:
|
||||
if (tlv_len != sizeof(u32))
|
||||
@@ -1218,15 +1303,15 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
|
||||
|
||||
if (tlv_len != sizeof(*fseq_ver))
|
||||
goto invalid_tlv_len;
|
||||
IWL_INFO(drv, "TLV_FW_FSEQ_VERSION: %s\n",
|
||||
fseq_ver->version);
|
||||
IWL_DEBUG_INFO(drv, "TLV_FW_FSEQ_VERSION: %.32s\n",
|
||||
fseq_ver->version);
|
||||
}
|
||||
break;
|
||||
case IWL_UCODE_TLV_FW_NUM_STATIONS:
|
||||
if (tlv_len != sizeof(u32))
|
||||
goto invalid_tlv_len;
|
||||
if (le32_to_cpup((const __le32 *)tlv_data) >
|
||||
IWL_MVM_STATION_COUNT_MAX) {
|
||||
IWL_STATION_COUNT_MAX) {
|
||||
IWL_ERR(drv,
|
||||
"%d is an invalid number of station\n",
|
||||
le32_to_cpup((const __le32 *)tlv_data));
|
||||
@@ -1235,6 +1320,19 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
|
||||
capa->num_stations =
|
||||
le32_to_cpup((const __le32 *)tlv_data);
|
||||
break;
|
||||
case IWL_UCODE_TLV_FW_NUM_LINKS:
|
||||
if (tlv_len != sizeof(u32))
|
||||
goto invalid_tlv_len;
|
||||
if (le32_to_cpup((const __le32 *)tlv_data) >
|
||||
IWL_FW_MAX_LINK_ID + 1) {
|
||||
IWL_ERR(drv,
|
||||
"%d is an invalid number of links\n",
|
||||
le32_to_cpup((const __le32 *)tlv_data));
|
||||
goto tlv_error;
|
||||
}
|
||||
capa->num_links =
|
||||
le32_to_cpup((const __le32 *)tlv_data);
|
||||
break;
|
||||
case IWL_UCODE_TLV_FW_NUM_BEACONS:
|
||||
if (tlv_len != sizeof(u32))
|
||||
goto invalid_tlv_len;
|
||||
@@ -1247,7 +1345,7 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
|
||||
|
||||
if (tlv_len != sizeof(*dbg_ptrs))
|
||||
goto invalid_tlv_len;
|
||||
if (drv->trans->trans_cfg->device_family <
|
||||
if (drv->trans->mac_cfg->device_family <
|
||||
IWL_DEVICE_FAMILY_22000)
|
||||
break;
|
||||
drv->trans->dbg.umac_error_event_table =
|
||||
@@ -1263,7 +1361,7 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
|
||||
|
||||
if (tlv_len != sizeof(*dbg_ptrs))
|
||||
goto invalid_tlv_len;
|
||||
if (drv->trans->trans_cfg->device_family <
|
||||
if (drv->trans->mac_cfg->device_family <
|
||||
IWL_DEVICE_FAMILY_22000)
|
||||
break;
|
||||
drv->trans->dbg.lmac_error_event_table[0] =
|
||||
@@ -1329,6 +1427,15 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
|
||||
drv->trans->dbg.num_pc =
|
||||
tlv_len / sizeof(struct iwl_pc_data);
|
||||
break;
|
||||
case IWL_UCODE_TLV_PNVM_DATA:
|
||||
if (drv->fw.pnvm_data)
|
||||
break;
|
||||
drv->fw.pnvm_data =
|
||||
kvmemdup(tlv_data, tlv_len, GFP_KERNEL);
|
||||
if (!drv->fw.pnvm_data)
|
||||
return -ENOMEM;
|
||||
drv->fw.pnvm_size = tlv_len;
|
||||
break;
|
||||
default:
|
||||
IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type);
|
||||
break;
|
||||
@@ -1370,29 +1477,34 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int iwl_alloc_ucode(struct iwl_drv *drv,
|
||||
struct iwl_firmware_pieces *pieces,
|
||||
enum iwl_ucode_type type)
|
||||
static int iwl_alloc_ucode_mem(struct fw_img *out, struct fw_img_parsing *img)
|
||||
{
|
||||
int i;
|
||||
struct fw_desc *sec;
|
||||
|
||||
sec = kcalloc(pieces->img[type].sec_counter, sizeof(*sec), GFP_KERNEL);
|
||||
sec = kcalloc(img->sec_counter, sizeof(*sec), GFP_KERNEL);
|
||||
if (!sec)
|
||||
return -ENOMEM;
|
||||
drv->fw.img[type].sec = sec;
|
||||
drv->fw.img[type].num_sec = pieces->img[type].sec_counter;
|
||||
|
||||
for (i = 0; i < pieces->img[type].sec_counter; i++)
|
||||
if (iwl_alloc_fw_desc(drv, &sec[i], get_sec(pieces, type, i)))
|
||||
out->sec = sec;
|
||||
out->num_sec = img->sec_counter;
|
||||
|
||||
for (int i = 0; i < out->num_sec; i++)
|
||||
if (iwl_alloc_fw_desc(&sec[i], &img->sec[i]))
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwl_alloc_ucode(struct iwl_drv *drv,
|
||||
struct iwl_firmware_pieces *pieces,
|
||||
enum iwl_ucode_type type)
|
||||
{
|
||||
return iwl_alloc_ucode_mem(&drv->fw.img[type], &pieces->img[type]);
|
||||
}
|
||||
|
||||
static int validate_sec_sizes(struct iwl_drv *drv,
|
||||
struct iwl_firmware_pieces *pieces,
|
||||
const struct iwl_cfg *cfg)
|
||||
const struct iwl_rf_cfg *cfg)
|
||||
{
|
||||
IWL_DEBUG_INFO(drv, "f/w package hdr runtime inst size = %zd\n",
|
||||
get_sec_size(pieces, IWL_UCODE_REGULAR,
|
||||
@@ -1446,26 +1558,39 @@ _iwl_op_mode_start(struct iwl_drv *drv, struct iwlwifi_opmode_table *op)
|
||||
const struct iwl_op_mode_ops *ops = op->ops;
|
||||
struct dentry *dbgfs_dir = NULL;
|
||||
struct iwl_op_mode *op_mode = NULL;
|
||||
int retry, max_retry = !!iwlwifi_mod_params.fw_restart * IWL_MAX_INIT_RETRY;
|
||||
|
||||
/* also protects start/stop from racing against each other */
|
||||
lockdep_assert_held(&iwlwifi_opmode_table_mtx);
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
drv->dbgfs_op_mode = debugfs_create_dir(op->name,
|
||||
drv->dbgfs_drv);
|
||||
dbgfs_dir = drv->dbgfs_op_mode;
|
||||
#endif
|
||||
|
||||
op_mode = ops->start(drv->trans, drv->trans->cfg,
|
||||
&drv->fw, dbgfs_dir);
|
||||
if (op_mode)
|
||||
return op_mode;
|
||||
for (retry = 0; retry <= max_retry; retry++) {
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
debugfs_remove_recursive(drv->dbgfs_op_mode);
|
||||
drv->dbgfs_op_mode = NULL;
|
||||
drv->dbgfs_op_mode = debugfs_create_dir(op->name,
|
||||
drv->dbgfs_drv);
|
||||
dbgfs_dir = drv->dbgfs_op_mode;
|
||||
#endif
|
||||
|
||||
op_mode = ops->start(drv->trans, drv->trans->cfg,
|
||||
&drv->fw, dbgfs_dir);
|
||||
|
||||
if (!IS_ERR(op_mode))
|
||||
return op_mode;
|
||||
|
||||
if (iwl_trans_is_dead(drv->trans))
|
||||
break;
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
debugfs_remove_recursive(drv->dbgfs_op_mode);
|
||||
drv->dbgfs_op_mode = NULL;
|
||||
#endif
|
||||
|
||||
if (PTR_ERR(op_mode) != -ETIMEDOUT)
|
||||
break;
|
||||
|
||||
IWL_ERR(drv, "retry init count %d\n", retry);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1486,6 +1611,8 @@ static void _iwl_op_mode_stop(struct iwl_drv *drv)
|
||||
}
|
||||
}
|
||||
|
||||
#define IWL_MLD_SUPPORTED_FW_VERSION 97
|
||||
|
||||
/*
|
||||
* iwl_req_fw_callback - callback when firmware was loaded
|
||||
*
|
||||
@@ -1500,19 +1627,20 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
|
||||
struct iwlwifi_opmode_table *op;
|
||||
int err;
|
||||
struct iwl_firmware_pieces *pieces;
|
||||
const unsigned int api_max = drv->trans->cfg->ucode_api_max;
|
||||
const unsigned int api_min = drv->trans->cfg->ucode_api_min;
|
||||
unsigned int api_min, api_max;
|
||||
size_t trigger_tlv_sz[FW_DBG_TRIGGER_MAX];
|
||||
u32 api_ver;
|
||||
int i;
|
||||
bool usniffer_images = false;
|
||||
bool failure = true;
|
||||
|
||||
iwl_get_ucode_api_versions(drv->trans, &api_min, &api_max);
|
||||
|
||||
fw->ucode_capa.max_probe_length = IWL_DEFAULT_MAX_PROBE_LENGTH;
|
||||
fw->ucode_capa.standard_phy_calibration_size =
|
||||
IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE;
|
||||
fw->ucode_capa.n_scan_channels = IWL_DEFAULT_SCAN_CHANNELS;
|
||||
fw->ucode_capa.num_stations = IWL_MVM_STATION_COUNT_MAX;
|
||||
fw->ucode_capa.num_stations = IWL_STATION_COUNT_MAX;
|
||||
fw->ucode_capa.num_beacons = 1;
|
||||
/* dump all fw memory areas by default */
|
||||
fw->dbg.dump_mask = 0xffffffff;
|
||||
@@ -1701,14 +1829,14 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
|
||||
fw->init_evtlog_size = (pieces->init_evtlog_size - 16)/12;
|
||||
else
|
||||
fw->init_evtlog_size =
|
||||
drv->trans->trans_cfg->base_params->max_event_log_size;
|
||||
drv->trans->mac_cfg->base->max_event_log_size;
|
||||
fw->init_errlog_ptr = pieces->init_errlog_ptr;
|
||||
fw->inst_evtlog_ptr = pieces->inst_evtlog_ptr;
|
||||
if (pieces->inst_evtlog_size)
|
||||
fw->inst_evtlog_size = (pieces->inst_evtlog_size - 16)/12;
|
||||
else
|
||||
fw->inst_evtlog_size =
|
||||
drv->trans->trans_cfg->base_params->max_event_log_size;
|
||||
drv->trans->mac_cfg->base->max_event_log_size;
|
||||
fw->inst_errlog_ptr = pieces->inst_errlog_ptr;
|
||||
|
||||
/*
|
||||
@@ -1738,6 +1866,20 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
|
||||
break;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_IWLMLD)
|
||||
if (pieces->major >= IWL_MLD_SUPPORTED_FW_VERSION &&
|
||||
iwl_drv_is_wifi7_supported(drv->trans))
|
||||
op = &iwlwifi_opmode_table[MLD_OP_MODE];
|
||||
#else
|
||||
if (pieces->major >= IWL_MLD_SUPPORTED_FW_VERSION &&
|
||||
iwl_drv_is_wifi7_supported(drv->trans)) {
|
||||
IWL_ERR(drv,
|
||||
"IWLMLD needs to be compiled to support this firmware\n");
|
||||
mutex_unlock(&iwlwifi_opmode_table_mtx);
|
||||
goto out_unbind;
|
||||
}
|
||||
#endif
|
||||
|
||||
IWL_INFO(drv, "loaded firmware version %s op_mode %s\n",
|
||||
drv->fw.fw_version, op->name);
|
||||
|
||||
@@ -1980,8 +2122,6 @@ static int __init iwl_drv_init(void)
|
||||
for (i = 0; i < ARRAY_SIZE(iwlwifi_opmode_table); i++)
|
||||
INIT_LIST_HEAD(&iwlwifi_opmode_table[i].drv);
|
||||
|
||||
pr_info(DRV_DESCRIPTION "\n");
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
/* Create the root of iwlwifi debugfs subsystem. */
|
||||
iwl_dbgfs_root = debugfs_create_dir(DRV_NAME, NULL);
|
||||
@@ -2004,6 +2144,7 @@ module_init(iwl_drv_init);
|
||||
static void __exit iwl_drv_exit(void)
|
||||
{
|
||||
iwl_pci_unregister_driver();
|
||||
iwl_trans_free_restart_list();
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
debugfs_remove_recursive(iwl_dbgfs_root);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2005-2014, 2020-2021, 2023 Intel Corporation
|
||||
* Copyright (C) 2005-2014, 2020-2021, 2023, 2025 Intel Corporation
|
||||
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
|
||||
*/
|
||||
#ifndef __iwl_drv_h__
|
||||
@@ -53,7 +53,7 @@
|
||||
|
||||
struct iwl_drv;
|
||||
struct iwl_trans;
|
||||
struct iwl_cfg;
|
||||
struct iwl_rf_cfg;
|
||||
/**
|
||||
* iwl_drv_start - start the drv
|
||||
*
|
||||
@@ -85,7 +85,7 @@ void iwl_drv_stop(struct iwl_drv *drv);
|
||||
* everything is built-in, then we can avoid that.
|
||||
*/
|
||||
#ifdef CONFIG_IWLWIFI_OPMODE_MODULAR
|
||||
#define IWL_EXPORT_SYMBOL(sym) EXPORT_SYMBOL_NS_GPL(sym, IWLWIFI)
|
||||
#define IWL_EXPORT_SYMBOL(sym) EXPORT_SYMBOL_NS_GPL(sym, "IWLWIFI")
|
||||
#else
|
||||
#define IWL_EXPORT_SYMBOL(sym)
|
||||
#endif
|
||||
@@ -98,6 +98,9 @@ void iwl_drv_stop(struct iwl_drv *drv);
|
||||
#define VISIBLE_IF_IWLWIFI_KUNIT static
|
||||
#endif
|
||||
|
||||
/* max retry for init flow */
|
||||
#define IWL_MAX_INIT_RETRY 2
|
||||
|
||||
#define FW_NAME_PRE_BUFSIZE 64
|
||||
struct iwl_trans;
|
||||
const char *iwl_drv_get_fwname_pre(struct iwl_trans *trans, char *buf);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2005-2014, 2018-2021, 2023-2024 Intel Corporation
|
||||
* Copyright (C) 2005-2014, 2018-2021, 2023-2025 Intel Corporation
|
||||
* Copyright (C) 2015-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
#ifndef __iwl_fh_h__
|
||||
@@ -71,7 +71,7 @@
|
||||
static inline unsigned int FH_MEM_CBBC_QUEUE(struct iwl_trans *trans,
|
||||
unsigned int chnl)
|
||||
{
|
||||
if (trans->trans_cfg->gen2) {
|
||||
if (trans->mac_cfg->gen2) {
|
||||
WARN_ON_ONCE(chnl >= 64);
|
||||
return TFH_TFDQ_CBB_TABLE + 8 * chnl;
|
||||
}
|
||||
@@ -378,14 +378,14 @@ static inline unsigned int FH_MEM_CBBC_QUEUE(struct iwl_trans *trans,
|
||||
* Once the RXF-to-DRAM DMA is active, this flag is immediately turned off.
|
||||
*/
|
||||
#define RFH_GEN_STATUS 0xA09808
|
||||
#define RFH_GEN_STATUS_GEN3 0xA07824
|
||||
#define RFH_GEN_STATUS_AX210 0xA07824
|
||||
#define RBD_FETCH_IDLE BIT(29)
|
||||
#define SRAM_DMA_IDLE BIT(30)
|
||||
#define RXF_DMA_IDLE BIT(31)
|
||||
|
||||
/* DMA configuration */
|
||||
#define RFH_RXF_DMA_CFG 0xA09820
|
||||
#define RFH_RXF_DMA_CFG_GEN3 0xA07880
|
||||
#define RFH_RXF_DMA_CFG_AX210 0xA07880
|
||||
/* RB size */
|
||||
#define RFH_RXF_DMA_RB_SIZE_MASK (0x000F0000) /* bits 16-19 */
|
||||
#define RFH_RXF_DMA_RB_SIZE_POS 16
|
||||
@@ -588,13 +588,12 @@ struct iwl_rb_status {
|
||||
|
||||
|
||||
#define TFD_QUEUE_SIZE_MAX (256)
|
||||
#define TFD_QUEUE_SIZE_MAX_GEN3 (65536)
|
||||
/* cb size is the exponent - 3 */
|
||||
#define TFD_QUEUE_CB_SIZE(x) (ilog2(x) - 3)
|
||||
#define TFD_QUEUE_SIZE_BC_DUP (64)
|
||||
#define TFD_QUEUE_BC_SIZE (TFD_QUEUE_SIZE_MAX + TFD_QUEUE_SIZE_BC_DUP)
|
||||
#define TFD_QUEUE_BC_SIZE_GEN3_AX210 1024
|
||||
#define TFD_QUEUE_BC_SIZE_GEN3_BZ (1024 * 4)
|
||||
#define TFD_QUEUE_BC_SIZE_AX210 1024
|
||||
#define TFD_QUEUE_BC_SIZE_BZ (1024 * 4)
|
||||
#define IWL_TX_DMA_MASK DMA_BIT_MASK(36)
|
||||
#define IWL_NUM_OF_TBS 20
|
||||
#define IWL_TFH_NUM_TBS 25
|
||||
@@ -717,30 +716,19 @@ struct iwl_tfh_tfd {
|
||||
/* Fixed (non-configurable) rx data from phy */
|
||||
|
||||
/**
|
||||
* struct iwlagn_scd_bc_tbl - scheduler byte count table
|
||||
* struct iwl_bc_tbl_entry - scheduler byte count table entry
|
||||
* base physical address provided by SCD_DRAM_BASE_ADDR
|
||||
* For devices up to 22000:
|
||||
* @tfd_offset:
|
||||
* For devices up to 22000:
|
||||
* 0-12 - tx command byte count
|
||||
* 12-16 - station index
|
||||
* For 22000:
|
||||
* For 22000 and on:
|
||||
* 0-12 - tx command byte count
|
||||
* 12-13 - number of 64 byte chunks
|
||||
* 14-16 - reserved
|
||||
*/
|
||||
struct iwlagn_scd_bc_tbl {
|
||||
__le16 tfd_offset[TFD_QUEUE_BC_SIZE];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_gen3_bc_tbl_entry - scheduler byte count table entry gen3
|
||||
* For AX210 and on:
|
||||
* @tfd_offset: 0-12 - tx command byte count
|
||||
* 12-13 - number of 64 byte chunks
|
||||
* 14-16 - reserved
|
||||
*/
|
||||
struct iwl_gen3_bc_tbl_entry {
|
||||
struct iwl_bc_tbl_entry {
|
||||
__le16 tfd_offset;
|
||||
} __packed;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2003-2014, 2018-2022, 2024 Intel Corporation
|
||||
* Copyright (C) 2003-2014, 2018-2022, 2024-2025 Intel Corporation
|
||||
* Copyright (C) 2015-2016 Intel Deutschland GmbH
|
||||
*/
|
||||
#include <linux/delay.h>
|
||||
@@ -47,21 +47,21 @@ IWL_EXPORT_SYMBOL(iwl_read32);
|
||||
|
||||
#define IWL_POLL_INTERVAL 10 /* microseconds */
|
||||
|
||||
int iwl_poll_bit(struct iwl_trans *trans, u32 addr,
|
||||
u32 bits, u32 mask, int timeout)
|
||||
int iwl_poll_bits_mask(struct iwl_trans *trans, u32 addr,
|
||||
u32 bits, u32 mask, int timeout)
|
||||
{
|
||||
int t = 0;
|
||||
|
||||
do {
|
||||
if ((iwl_read32(trans, addr) & mask) == (bits & mask))
|
||||
return t;
|
||||
return 0;
|
||||
udelay(IWL_POLL_INTERVAL);
|
||||
t += IWL_POLL_INTERVAL;
|
||||
} while (t < timeout);
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_poll_bit);
|
||||
IWL_EXPORT_SYMBOL(iwl_poll_bits_mask);
|
||||
|
||||
u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg)
|
||||
{
|
||||
@@ -75,7 +75,6 @@ u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg)
|
||||
/* return as if we have a HW timeout/failure */
|
||||
return 0x5a5a5a5a;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_read_direct32);
|
||||
|
||||
void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value)
|
||||
{
|
||||
@@ -93,7 +92,6 @@ void iwl_write_direct64(struct iwl_trans *trans, u64 reg, u64 value)
|
||||
iwl_trans_release_nic_access(trans);
|
||||
}
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_write_direct64);
|
||||
|
||||
int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask,
|
||||
int timeout)
|
||||
@@ -109,7 +107,6 @@ int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask,
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_poll_direct_bit);
|
||||
|
||||
u32 iwl_read_prph_no_grab(struct iwl_trans *trans, u32 ofs)
|
||||
{
|
||||
@@ -117,14 +114,12 @@ u32 iwl_read_prph_no_grab(struct iwl_trans *trans, u32 ofs)
|
||||
trace_iwlwifi_dev_ioread_prph32(trans->dev, ofs, val);
|
||||
return val;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_read_prph_no_grab);
|
||||
|
||||
void iwl_write_prph_no_grab(struct iwl_trans *trans, u32 ofs, u32 val)
|
||||
{
|
||||
trace_iwlwifi_dev_iowrite_prph32(trans->dev, ofs, val);
|
||||
iwl_trans_write_prph(trans, ofs, val);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_write_prph_no_grab);
|
||||
|
||||
void iwl_write_prph64_no_grab(struct iwl_trans *trans, u64 ofs, u64 val)
|
||||
{
|
||||
@@ -132,7 +127,6 @@ void iwl_write_prph64_no_grab(struct iwl_trans *trans, u64 ofs, u64 val)
|
||||
iwl_write_prph_no_grab(trans, ofs, val & 0xffffffff);
|
||||
iwl_write_prph_no_grab(trans, ofs + 4, val >> 32);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_write_prph64_no_grab);
|
||||
|
||||
u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs)
|
||||
{
|
||||
@@ -211,13 +205,13 @@ IWL_EXPORT_SYMBOL(iwl_clear_bits_prph);
|
||||
|
||||
void iwl_force_nmi(struct iwl_trans *trans)
|
||||
{
|
||||
if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_9000)
|
||||
if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_9000)
|
||||
iwl_write_prph_delay(trans, DEVICE_SET_NMI_REG,
|
||||
DEVICE_SET_NMI_VAL_DRV, 1);
|
||||
else if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
|
||||
else if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
|
||||
iwl_write_umac_prph(trans, UREG_NIC_SET_NMI_DRIVER,
|
||||
UREG_NIC_SET_NMI_DRIVER_NMI_FROM_DRIVER);
|
||||
else if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_BZ)
|
||||
else if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_BZ)
|
||||
iwl_write_umac_prph(trans, UREG_DOORBELL_TO_ISR6,
|
||||
UREG_DOORBELL_TO_ISR6_NMI_BIT);
|
||||
else
|
||||
@@ -260,7 +254,7 @@ struct reg {
|
||||
static int iwl_dump_rfh(struct iwl_trans *trans, char **buf)
|
||||
{
|
||||
int i, q;
|
||||
int num_q = trans->num_rx_queues;
|
||||
int num_q = trans->info.num_rxqs;
|
||||
static const u32 rfh_tbl[] = {
|
||||
RFH_RXF_DMA_CFG,
|
||||
RFH_GEN_CFG,
|
||||
@@ -368,7 +362,7 @@ int iwl_dump_fh(struct iwl_trans *trans, char **buf)
|
||||
FH_TSSR_TX_ERROR_REG
|
||||
};
|
||||
|
||||
if (trans->trans_cfg->mq_rx_supported)
|
||||
if (trans->mac_cfg->mq_rx_supported)
|
||||
return iwl_dump_rfh(trans, buf);
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
@@ -423,7 +417,7 @@ static void iwl_dump_host_monitor_block(struct iwl_trans *trans,
|
||||
|
||||
static void iwl_dump_host_monitor(struct iwl_trans *trans)
|
||||
{
|
||||
switch (trans->trans_cfg->device_family) {
|
||||
switch (trans->mac_cfg->device_family) {
|
||||
case IWL_DEVICE_FAMILY_22000:
|
||||
case IWL_DEVICE_FAMILY_AX210:
|
||||
IWL_ERR(trans, "CSR_RESET = 0x%x\n",
|
||||
@@ -445,11 +439,11 @@ static void iwl_dump_host_monitor(struct iwl_trans *trans)
|
||||
|
||||
int iwl_finish_nic_init(struct iwl_trans *trans)
|
||||
{
|
||||
const struct iwl_cfg_trans_params *cfg_trans = trans->trans_cfg;
|
||||
const struct iwl_mac_cfg *mac_cfg = trans->mac_cfg;
|
||||
u32 poll_ready;
|
||||
int err;
|
||||
|
||||
if (cfg_trans->bisr_workaround) {
|
||||
if (mac_cfg->bisr_workaround) {
|
||||
/* ensure the TOP FSM isn't still in previous reset */
|
||||
mdelay(2);
|
||||
}
|
||||
@@ -458,7 +452,7 @@ int iwl_finish_nic_init(struct iwl_trans *trans)
|
||||
* Set "initialization complete" bit to move adapter from
|
||||
* D0U* --> D0A* (powered-up active) state.
|
||||
*/
|
||||
if (cfg_trans->device_family >= IWL_DEVICE_FAMILY_BZ) {
|
||||
if (mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) {
|
||||
iwl_set_bit(trans, CSR_GP_CNTRL,
|
||||
CSR_GP_CNTRL_REG_FLAG_BZ_MAC_ACCESS_REQ |
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_INIT);
|
||||
@@ -469,7 +463,7 @@ int iwl_finish_nic_init(struct iwl_trans *trans)
|
||||
poll_ready = CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY;
|
||||
}
|
||||
|
||||
if (cfg_trans->device_family == IWL_DEVICE_FAMILY_8000)
|
||||
if (mac_cfg->device_family == IWL_DEVICE_FAMILY_8000)
|
||||
udelay(2);
|
||||
|
||||
/*
|
||||
@@ -477,14 +471,14 @@ int iwl_finish_nic_init(struct iwl_trans *trans)
|
||||
* device-internal resources is supported, e.g. iwl_write_prph()
|
||||
* and accesses to uCode SRAM.
|
||||
*/
|
||||
err = iwl_poll_bit(trans, CSR_GP_CNTRL, poll_ready, poll_ready, 25000);
|
||||
err = iwl_poll_bits(trans, CSR_GP_CNTRL, poll_ready, 25000);
|
||||
if (err < 0) {
|
||||
IWL_DEBUG_INFO(trans, "Failed to wake NIC\n");
|
||||
|
||||
iwl_dump_host_monitor(trans);
|
||||
}
|
||||
|
||||
if (cfg_trans->bisr_workaround) {
|
||||
if (mac_cfg->bisr_workaround) {
|
||||
/* ensure BISR shift has finished */
|
||||
udelay(200);
|
||||
}
|
||||
@@ -526,5 +520,5 @@ void iwl_trans_sync_nmi_with_addr(struct iwl_trans *trans, u32 inta_addr,
|
||||
if (interrupts_enabled)
|
||||
iwl_trans_interrupts(trans, true);
|
||||
|
||||
iwl_trans_fw_error(trans, false);
|
||||
iwl_trans_fw_error(trans, IWL_ERR_TYPE_NMI_FORCED);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2018-2021 Intel Corporation
|
||||
* Copyright (C) 2018-2021, 2025 Intel Corporation
|
||||
*/
|
||||
#ifndef __iwl_io_h__
|
||||
#define __iwl_io_h__
|
||||
@@ -23,8 +23,13 @@ static inline void iwl_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask)
|
||||
iwl_trans_set_bits_mask(trans, reg, mask, 0);
|
||||
}
|
||||
|
||||
int iwl_poll_bit(struct iwl_trans *trans, u32 addr,
|
||||
u32 bits, u32 mask, int timeout);
|
||||
int iwl_poll_bits_mask(struct iwl_trans *trans, u32 addr,
|
||||
u32 bits, u32 mask, int timeout);
|
||||
static inline int iwl_poll_bits(struct iwl_trans *trans, u32 addr, u32 bits,
|
||||
int timeout)
|
||||
{
|
||||
return iwl_poll_bits_mask(trans, addr, bits, bits, timeout);
|
||||
}
|
||||
int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask,
|
||||
int timeout);
|
||||
|
||||
@@ -64,38 +69,38 @@ int iwl_dump_fh(struct iwl_trans *trans, char **buf);
|
||||
*/
|
||||
static inline u32 iwl_umac_prph(struct iwl_trans *trans, u32 ofs)
|
||||
{
|
||||
return ofs + trans->trans_cfg->umac_prph_offset;
|
||||
return ofs + trans->mac_cfg->umac_prph_offset;
|
||||
}
|
||||
|
||||
static inline u32 iwl_read_umac_prph_no_grab(struct iwl_trans *trans, u32 ofs)
|
||||
{
|
||||
return iwl_read_prph_no_grab(trans, ofs +
|
||||
trans->trans_cfg->umac_prph_offset);
|
||||
trans->mac_cfg->umac_prph_offset);
|
||||
}
|
||||
|
||||
static inline u32 iwl_read_umac_prph(struct iwl_trans *trans, u32 ofs)
|
||||
{
|
||||
return iwl_read_prph(trans, ofs + trans->trans_cfg->umac_prph_offset);
|
||||
return iwl_read_prph(trans, ofs + trans->mac_cfg->umac_prph_offset);
|
||||
}
|
||||
|
||||
static inline void iwl_write_umac_prph_no_grab(struct iwl_trans *trans, u32 ofs,
|
||||
u32 val)
|
||||
{
|
||||
iwl_write_prph_no_grab(trans, ofs + trans->trans_cfg->umac_prph_offset,
|
||||
iwl_write_prph_no_grab(trans, ofs + trans->mac_cfg->umac_prph_offset,
|
||||
val);
|
||||
}
|
||||
|
||||
static inline void iwl_write_umac_prph(struct iwl_trans *trans, u32 ofs,
|
||||
u32 val)
|
||||
{
|
||||
iwl_write_prph(trans, ofs + trans->trans_cfg->umac_prph_offset, val);
|
||||
iwl_write_prph(trans, ofs + trans->mac_cfg->umac_prph_offset, val);
|
||||
}
|
||||
|
||||
static inline int iwl_poll_umac_prph_bit(struct iwl_trans *trans, u32 addr,
|
||||
u32 bits, u32 mask, int timeout)
|
||||
{
|
||||
return iwl_poll_prph_bit(trans, addr +
|
||||
trans->trans_cfg->umac_prph_offset,
|
||||
trans->mac_cfg->umac_prph_offset,
|
||||
bits, mask, timeout);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2005-2014, 2018-2023 Intel Corporation
|
||||
* Copyright (C) 2005-2014, 2018-2023, 2025 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
#include <linux/types.h>
|
||||
#include <linux/fips.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/etherdevice.h>
|
||||
@@ -141,8 +142,13 @@ static struct ieee80211_rate iwl_cfg80211_rates[] = {
|
||||
/**
|
||||
* enum iwl_nvm_channel_flags - channel flags in NVM
|
||||
* @NVM_CHANNEL_VALID: channel is usable for this SKU/geo
|
||||
* @NVM_CHANNEL_IBSS: usable as an IBSS channel
|
||||
* @NVM_CHANNEL_ACTIVE: active scanning allowed
|
||||
* @NVM_CHANNEL_IBSS: usable as an IBSS channel and deprecated
|
||||
* when %IWL_NVM_SBANDS_FLAGS_LAR enabled.
|
||||
* @NVM_CHANNEL_ALLOW_20MHZ_ACTIVITY: active scanning allowed and
|
||||
* AP allowed only in 20 MHz. Valid only
|
||||
* when %IWL_NVM_SBANDS_FLAGS_LAR enabled.
|
||||
* @NVM_CHANNEL_ACTIVE: active scanning allowed and allows IBSS
|
||||
* when %IWL_NVM_SBANDS_FLAGS_LAR enabled.
|
||||
* @NVM_CHANNEL_RADAR: radar detection required
|
||||
* @NVM_CHANNEL_INDOOR_ONLY: only indoor use is allowed
|
||||
* @NVM_CHANNEL_GO_CONCURRENT: GO operation is allowed when connected to BSS
|
||||
@@ -155,22 +161,26 @@ static struct ieee80211_rate iwl_cfg80211_rates[] = {
|
||||
* @NVM_CHANNEL_DC_HIGH: DC HIGH required/allowed (?)
|
||||
* @NVM_CHANNEL_VLP: client support connection to UHB VLP AP
|
||||
* @NVM_CHANNEL_AFC: client support connection to UHB AFC AP
|
||||
* @NVM_CHANNEL_VLP_AP_NOT_ALLOWED: UHB VLP AP not allowed,
|
||||
* Valid only when %NVM_CHANNEL_VLP is enabled.
|
||||
*/
|
||||
enum iwl_nvm_channel_flags {
|
||||
NVM_CHANNEL_VALID = BIT(0),
|
||||
NVM_CHANNEL_IBSS = BIT(1),
|
||||
NVM_CHANNEL_ACTIVE = BIT(3),
|
||||
NVM_CHANNEL_RADAR = BIT(4),
|
||||
NVM_CHANNEL_INDOOR_ONLY = BIT(5),
|
||||
NVM_CHANNEL_GO_CONCURRENT = BIT(6),
|
||||
NVM_CHANNEL_UNIFORM = BIT(7),
|
||||
NVM_CHANNEL_20MHZ = BIT(8),
|
||||
NVM_CHANNEL_40MHZ = BIT(9),
|
||||
NVM_CHANNEL_80MHZ = BIT(10),
|
||||
NVM_CHANNEL_160MHZ = BIT(11),
|
||||
NVM_CHANNEL_DC_HIGH = BIT(12),
|
||||
NVM_CHANNEL_VLP = BIT(13),
|
||||
NVM_CHANNEL_AFC = BIT(14),
|
||||
NVM_CHANNEL_VALID = BIT(0),
|
||||
NVM_CHANNEL_IBSS = BIT(1),
|
||||
NVM_CHANNEL_ALLOW_20MHZ_ACTIVITY = BIT(2),
|
||||
NVM_CHANNEL_ACTIVE = BIT(3),
|
||||
NVM_CHANNEL_RADAR = BIT(4),
|
||||
NVM_CHANNEL_INDOOR_ONLY = BIT(5),
|
||||
NVM_CHANNEL_GO_CONCURRENT = BIT(6),
|
||||
NVM_CHANNEL_UNIFORM = BIT(7),
|
||||
NVM_CHANNEL_20MHZ = BIT(8),
|
||||
NVM_CHANNEL_40MHZ = BIT(9),
|
||||
NVM_CHANNEL_80MHZ = BIT(10),
|
||||
NVM_CHANNEL_160MHZ = BIT(11),
|
||||
NVM_CHANNEL_DC_HIGH = BIT(12),
|
||||
NVM_CHANNEL_VLP = BIT(13),
|
||||
NVM_CHANNEL_AFC = BIT(14),
|
||||
NVM_CHANNEL_VLP_AP_NOT_ALLOWED = BIT(15),
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -330,7 +340,7 @@ static inline void iwl_nvm_print_channel_flags(struct device *dev, u32 level,
|
||||
}
|
||||
|
||||
static u32 iwl_get_channel_flags(u8 ch_num, int ch_idx, enum nl80211_band band,
|
||||
u32 nvm_flags, const struct iwl_cfg *cfg)
|
||||
u32 nvm_flags, const struct iwl_rf_cfg *cfg)
|
||||
{
|
||||
u32 flags = IEEE80211_CHAN_NO_HT40;
|
||||
|
||||
@@ -397,7 +407,7 @@ static int iwl_init_channel_map(struct iwl_trans *trans,
|
||||
const void * const nvm_ch_flags,
|
||||
u32 sbands_flags, bool v4)
|
||||
{
|
||||
const struct iwl_cfg *cfg = trans->cfg;
|
||||
const struct iwl_rf_cfg *cfg = trans->cfg;
|
||||
struct device *dev = trans->dev;
|
||||
int ch_idx;
|
||||
int n_channels = 0;
|
||||
@@ -498,7 +508,7 @@ static void iwl_init_vht_hw_capab(struct iwl_trans *trans,
|
||||
struct ieee80211_sta_vht_cap *vht_cap,
|
||||
u8 tx_chains, u8 rx_chains)
|
||||
{
|
||||
const struct iwl_cfg *cfg = trans->cfg;
|
||||
const struct iwl_rf_cfg *cfg = trans->cfg;
|
||||
int num_rx_ants = num_of_ant(rx_chains);
|
||||
int num_tx_ants = num_of_ant(tx_chains);
|
||||
|
||||
@@ -511,7 +521,7 @@ static void iwl_init_vht_hw_capab(struct iwl_trans *trans,
|
||||
IEEE80211_VHT_MAX_AMPDU_1024K <<
|
||||
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT;
|
||||
|
||||
if (!trans->cfg->ht_params->stbc)
|
||||
if (!trans->cfg->ht_params.stbc)
|
||||
vht_cap->cap &= ~IEEE80211_VHT_CAP_RXSTBC_MASK;
|
||||
|
||||
if (data->vht160_supported)
|
||||
@@ -521,7 +531,7 @@ static void iwl_init_vht_hw_capab(struct iwl_trans *trans,
|
||||
if (cfg->vht_mu_mimo_supported)
|
||||
vht_cap->cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
|
||||
|
||||
if (cfg->ht_params->ldpc)
|
||||
if (cfg->ht_params.ldpc)
|
||||
vht_cap->cap |= IEEE80211_VHT_CAP_RXLDPC;
|
||||
|
||||
if (data->sku_cap_mimo_disabled) {
|
||||
@@ -529,21 +539,27 @@ static void iwl_init_vht_hw_capab(struct iwl_trans *trans,
|
||||
num_tx_ants = 1;
|
||||
}
|
||||
|
||||
if (trans->cfg->ht_params->stbc && num_tx_ants > 1)
|
||||
if (trans->cfg->ht_params.stbc && num_tx_ants > 1)
|
||||
vht_cap->cap |= IEEE80211_VHT_CAP_TXSTBC;
|
||||
else
|
||||
vht_cap->cap |= IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN;
|
||||
|
||||
/*
|
||||
* With fips_enabled crypto is done by software, so the HW cannot
|
||||
* split up A-MSDUs and the real limit that was set applies.
|
||||
* Note that EHT doesn't honour this (HE copies the VHT value),
|
||||
* but EHT is also entirely disabled for fips_enabled.
|
||||
*/
|
||||
switch (iwlwifi_mod_params.amsdu_size) {
|
||||
case IWL_AMSDU_DEF:
|
||||
if (trans->trans_cfg->mq_rx_supported)
|
||||
if (trans->mac_cfg->mq_rx_supported && !fips_enabled)
|
||||
vht_cap->cap |=
|
||||
IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
|
||||
else
|
||||
vht_cap->cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895;
|
||||
break;
|
||||
case IWL_AMSDU_2K:
|
||||
if (trans->trans_cfg->mq_rx_supported)
|
||||
if (trans->mac_cfg->mq_rx_supported && !fips_enabled)
|
||||
vht_cap->cap |=
|
||||
IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
|
||||
else
|
||||
@@ -654,6 +670,8 @@ static const struct ieee80211_sband_iftype_data iwl_he_eht_capa[] = {
|
||||
.phy_cap_info[9] =
|
||||
IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB |
|
||||
IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB |
|
||||
IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU |
|
||||
IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU |
|
||||
(IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_RESERVED <<
|
||||
IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_POS),
|
||||
.phy_cap_info[10] =
|
||||
@@ -682,41 +700,26 @@ static const struct ieee80211_sband_iftype_data iwl_he_eht_capa[] = {
|
||||
.has_eht = true,
|
||||
.eht_cap_elem = {
|
||||
.mac_cap_info[0] =
|
||||
IEEE80211_EHT_MAC_CAP0_OM_CONTROL |
|
||||
IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1 |
|
||||
IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE2 |
|
||||
IEEE80211_EHT_MAC_CAP0_SCS_TRAFFIC_DESC,
|
||||
IEEE80211_EHT_MAC_CAP0_OM_CONTROL,
|
||||
.phy_cap_info[0] =
|
||||
IEEE80211_EHT_PHY_CAP0_242_TONE_RU_GT20MHZ |
|
||||
IEEE80211_EHT_PHY_CAP0_NDP_4_EHT_LFT_32_GI |
|
||||
IEEE80211_EHT_PHY_CAP0_PARTIAL_BW_UL_MU_MIMO |
|
||||
IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMEE |
|
||||
IEEE80211_EHT_PHY_CAP0_BEAMFORMEE_SS_80MHZ_MASK,
|
||||
.phy_cap_info[1] =
|
||||
IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_80MHZ_MASK |
|
||||
IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_160MHZ_MASK,
|
||||
.phy_cap_info[3] =
|
||||
IEEE80211_EHT_PHY_CAP3_NG_16_SU_FEEDBACK |
|
||||
IEEE80211_EHT_PHY_CAP3_NG_16_MU_FEEDBACK |
|
||||
IEEE80211_EHT_PHY_CAP3_CODEBOOK_4_2_SU_FDBK |
|
||||
IEEE80211_EHT_PHY_CAP3_CODEBOOK_7_5_MU_FDBK |
|
||||
IEEE80211_EHT_PHY_CAP3_TRIG_SU_BF_FDBK |
|
||||
IEEE80211_EHT_PHY_CAP3_TRIG_MU_BF_PART_BW_FDBK |
|
||||
IEEE80211_EHT_PHY_CAP3_TRIG_CQI_FDBK,
|
||||
IEEE80211_EHT_PHY_CAP3_TRIG_SU_BF_FDBK,
|
||||
|
||||
.phy_cap_info[4] =
|
||||
IEEE80211_EHT_PHY_CAP4_PART_BW_DL_MU_MIMO |
|
||||
IEEE80211_EHT_PHY_CAP4_POWER_BOOST_FACT_SUPP |
|
||||
IEEE80211_EHT_PHY_CAP4_EHT_MU_PPDU_4_EHT_LTF_08_GI,
|
||||
.phy_cap_info[5] =
|
||||
FIELD_PREP_CONST(IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_MASK,
|
||||
IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_16US) |
|
||||
IEEE80211_EHT_PHY_CAP5_NON_TRIG_CQI_FEEDBACK |
|
||||
IEEE80211_EHT_PHY_CAP5_TX_LESS_242_TONE_RU_SUPP |
|
||||
IEEE80211_EHT_PHY_CAP5_RX_LESS_242_TONE_RU_SUPP,
|
||||
.phy_cap_info[6] =
|
||||
IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_MASK |
|
||||
IEEE80211_EHT_PHY_CAP6_EHT_DUP_6GHZ_SUPP,
|
||||
IEEE80211_EHT_PHY_CAP5_RX_LESS_242_TONE_RU_SUPP |
|
||||
IEEE80211_EHT_PHY_CAP5_SUPP_EXTRA_EHT_LTF,
|
||||
.phy_cap_info[8] =
|
||||
IEEE80211_EHT_PHY_CAP8_RX_1024QAM_WIDER_BW_DL_OFDMA |
|
||||
IEEE80211_EHT_PHY_CAP8_RX_4096QAM_WIDER_BW_DL_OFDMA,
|
||||
@@ -784,6 +787,7 @@ static const struct ieee80211_sband_iftype_data iwl_he_eht_capa[] = {
|
||||
IEEE80211_HE_PHY_CAP8_HE_ER_SU_PPDU_4XLTF_AND_08_US_GI |
|
||||
IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_242,
|
||||
.phy_cap_info[9] =
|
||||
IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU |
|
||||
IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_RESERVED
|
||||
<< IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_POS,
|
||||
},
|
||||
@@ -810,9 +814,7 @@ static const struct ieee80211_sband_iftype_data iwl_he_eht_capa[] = {
|
||||
.has_eht = true,
|
||||
.eht_cap_elem = {
|
||||
.mac_cap_info[0] =
|
||||
IEEE80211_EHT_MAC_CAP0_OM_CONTROL |
|
||||
IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1 |
|
||||
IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE2,
|
||||
IEEE80211_EHT_MAC_CAP0_OM_CONTROL,
|
||||
.phy_cap_info[0] =
|
||||
IEEE80211_EHT_PHY_CAP0_242_TONE_RU_GT20MHZ |
|
||||
IEEE80211_EHT_PHY_CAP0_NDP_4_EHT_LFT_32_GI,
|
||||
@@ -911,13 +913,12 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans,
|
||||
{
|
||||
bool is_ap = iftype_data->types_mask & (BIT(NL80211_IFTYPE_AP) |
|
||||
BIT(NL80211_IFTYPE_P2P_GO));
|
||||
bool no_320;
|
||||
bool slow_pcie = (!trans->mac_cfg->integrated &&
|
||||
trans->info.pcie_link_speed < PCI_EXP_LNKSTA_CLS_8_0GB);
|
||||
|
||||
no_320 = (!trans->trans_cfg->integrated &&
|
||||
trans->pcie_link_speed < PCI_EXP_LNKSTA_CLS_8_0GB) ||
|
||||
trans->reduced_cap_sku;
|
||||
|
||||
if (!data->sku_cap_11be_enable || iwlwifi_mod_params.disable_11be)
|
||||
/* EHT needs WPA3/MFP so cannot do it for fips_enabled */
|
||||
if (!data->sku_cap_11be_enable || iwlwifi_mod_params.disable_11be ||
|
||||
fips_enabled)
|
||||
iftype_data->eht_cap.has_eht = false;
|
||||
|
||||
/* Advertise an A-MPDU exponent extension based on
|
||||
@@ -942,7 +943,8 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans,
|
||||
IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_MASK);
|
||||
break;
|
||||
case NL80211_BAND_6GHZ:
|
||||
if (!no_320) {
|
||||
if (!trans->reduced_cap_sku &&
|
||||
(!trans->cfg->bw_limit || trans->cfg->bw_limit >= 320)) {
|
||||
iftype_data->eht_cap.eht_cap_elem.phy_cap_info[0] |=
|
||||
IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ;
|
||||
iftype_data->eht_cap.eht_cap_elem.phy_cap_info[1] |=
|
||||
@@ -984,6 +986,14 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans,
|
||||
iftype_data->eht_cap.eht_cap_elem.phy_cap_info[4] |= 0x10;
|
||||
}
|
||||
}
|
||||
|
||||
if (slow_pcie) {
|
||||
struct ieee80211_eht_mcs_nss_supp *mcs_nss =
|
||||
&iftype_data->eht_cap.eht_mcs_nss_supp;
|
||||
|
||||
mcs_nss->bw._320.rx_tx_mcs11_max_nss = 0;
|
||||
mcs_nss->bw._320.rx_tx_mcs13_max_nss = 0;
|
||||
}
|
||||
} else {
|
||||
struct ieee80211_he_mcs_nss_supp *he_mcs_nss_supp =
|
||||
&iftype_data->he_cap.he_mcs_nss_supp;
|
||||
@@ -1021,58 +1031,28 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans,
|
||||
cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << 2);
|
||||
}
|
||||
|
||||
if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210 && !is_ap)
|
||||
/* prior RFs don't have HE, HR RF doesn't have this, later have it */
|
||||
if (CSR_HW_RFID_TYPE(trans->info.hw_rf_id) == IWL_CFG_RF_TYPE_HR1 ||
|
||||
CSR_HW_RFID_TYPE(trans->info.hw_rf_id) == IWL_CFG_RF_TYPE_HR2)
|
||||
iftype_data->he_cap.he_cap_elem.phy_cap_info[9] &=
|
||||
~(IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU |
|
||||
IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU);
|
||||
|
||||
if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210 && !is_ap)
|
||||
iftype_data->he_cap.he_cap_elem.phy_cap_info[2] |=
|
||||
IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO;
|
||||
|
||||
switch (CSR_HW_RFID_TYPE(trans->hw_rf_id)) {
|
||||
case IWL_CFG_RF_TYPE_GF:
|
||||
case IWL_CFG_RF_TYPE_FM:
|
||||
case IWL_CFG_RF_TYPE_WH:
|
||||
iftype_data->he_cap.he_cap_elem.phy_cap_info[9] |=
|
||||
IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU;
|
||||
if (!is_ap)
|
||||
iftype_data->he_cap.he_cap_elem.phy_cap_info[9] |=
|
||||
IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU;
|
||||
break;
|
||||
}
|
||||
|
||||
if (CSR_HW_REV_TYPE(trans->hw_rev) == IWL_CFG_MAC_TYPE_GL &&
|
||||
iftype_data->eht_cap.has_eht) {
|
||||
iftype_data->eht_cap.eht_cap_elem.mac_cap_info[0] &=
|
||||
~(IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1 |
|
||||
IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE2);
|
||||
iftype_data->eht_cap.eht_cap_elem.phy_cap_info[3] &=
|
||||
~(IEEE80211_EHT_PHY_CAP0_PARTIAL_BW_UL_MU_MIMO |
|
||||
IEEE80211_EHT_PHY_CAP3_NG_16_SU_FEEDBACK |
|
||||
IEEE80211_EHT_PHY_CAP3_NG_16_MU_FEEDBACK |
|
||||
IEEE80211_EHT_PHY_CAP3_CODEBOOK_4_2_SU_FDBK |
|
||||
IEEE80211_EHT_PHY_CAP3_CODEBOOK_7_5_MU_FDBK |
|
||||
IEEE80211_EHT_PHY_CAP3_TRIG_MU_BF_PART_BW_FDBK |
|
||||
IEEE80211_EHT_PHY_CAP3_TRIG_CQI_FDBK);
|
||||
iftype_data->eht_cap.eht_cap_elem.phy_cap_info[4] &=
|
||||
~(IEEE80211_EHT_PHY_CAP4_PART_BW_DL_MU_MIMO |
|
||||
IEEE80211_EHT_PHY_CAP4_POWER_BOOST_FACT_SUPP);
|
||||
iftype_data->eht_cap.eht_cap_elem.phy_cap_info[5] &=
|
||||
~IEEE80211_EHT_PHY_CAP5_NON_TRIG_CQI_FEEDBACK;
|
||||
iftype_data->eht_cap.eht_cap_elem.phy_cap_info[6] &=
|
||||
~(IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_MASK |
|
||||
IEEE80211_EHT_PHY_CAP6_EHT_DUP_6GHZ_SUPP);
|
||||
iftype_data->eht_cap.eht_cap_elem.phy_cap_info[5] |=
|
||||
IEEE80211_EHT_PHY_CAP5_SUPP_EXTRA_EHT_LTF;
|
||||
}
|
||||
|
||||
if (fw_has_capa(&fw->ucode_capa, IWL_UCODE_TLV_CAPA_BROADCAST_TWT))
|
||||
iftype_data->he_cap.he_cap_elem.mac_cap_info[2] |=
|
||||
IEEE80211_HE_MAC_CAP2_BCAST_TWT;
|
||||
|
||||
if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_22000 &&
|
||||
if (trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_22000 &&
|
||||
!is_ap) {
|
||||
iftype_data->vendor_elems.data = iwl_vendor_caps;
|
||||
iftype_data->vendor_elems.len = ARRAY_SIZE(iwl_vendor_caps);
|
||||
}
|
||||
|
||||
if (!trans->cfg->ht_params->stbc) {
|
||||
if (!trans->cfg->ht_params.stbc) {
|
||||
iftype_data->he_cap.he_cap_elem.phy_cap_info[2] &=
|
||||
~IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ;
|
||||
iftype_data->he_cap.he_cap_elem.phy_cap_info[7] &=
|
||||
@@ -1084,19 +1064,23 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans,
|
||||
iftype_data->eht_cap.eht_mcs_nss_supp.bw._320.rx_tx_mcs13_max_nss = 0;
|
||||
}
|
||||
|
||||
if (trans->no_160)
|
||||
if (trans->cfg->bw_limit && trans->cfg->bw_limit < 160)
|
||||
iftype_data->he_cap.he_cap_elem.phy_cap_info[0] &=
|
||||
~IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G;
|
||||
|
||||
if (trans->reduced_cap_sku) {
|
||||
if ((trans->cfg->bw_limit && trans->cfg->bw_limit < 320) ||
|
||||
trans->reduced_cap_sku) {
|
||||
memset(&iftype_data->eht_cap.eht_mcs_nss_supp.bw._320, 0,
|
||||
sizeof(iftype_data->eht_cap.eht_mcs_nss_supp.bw._320));
|
||||
iftype_data->eht_cap.eht_cap_elem.phy_cap_info[2] &=
|
||||
~IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_320MHZ_MASK;
|
||||
}
|
||||
|
||||
if (trans->reduced_cap_sku) {
|
||||
iftype_data->eht_cap.eht_mcs_nss_supp.bw._80.rx_tx_mcs13_max_nss = 0;
|
||||
iftype_data->eht_cap.eht_mcs_nss_supp.bw._160.rx_tx_mcs13_max_nss = 0;
|
||||
iftype_data->eht_cap.eht_cap_elem.phy_cap_info[8] &=
|
||||
~IEEE80211_EHT_PHY_CAP8_RX_4096QAM_WIDER_BW_DL_OFDMA;
|
||||
iftype_data->eht_cap.eht_cap_elem.phy_cap_info[2] &=
|
||||
~IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_320MHZ_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1222,17 +1206,25 @@ static void iwl_init_sbands(struct iwl_trans *trans,
|
||||
n_used += iwl_init_sband_channels(data, sband, n_channels,
|
||||
NL80211_BAND_6GHZ);
|
||||
|
||||
if (data->sku_cap_11ax_enable && !iwlwifi_mod_params.disable_11ax)
|
||||
/*
|
||||
* 6 GHz requires WPA3 which requires MFP, which FW cannot do
|
||||
* when fips_enabled, so don't advertise any 6 GHz channels to
|
||||
* avoid spending time on scanning those channels and perhaps
|
||||
* even finding APs there that cannot be used.
|
||||
*/
|
||||
if (!fips_enabled && data->sku_cap_11ax_enable &&
|
||||
!iwlwifi_mod_params.disable_11ax)
|
||||
iwl_init_he_hw_capab(trans, data, sband, tx_chains, rx_chains,
|
||||
fw);
|
||||
else
|
||||
sband->n_channels = 0;
|
||||
|
||||
if (n_channels != n_used)
|
||||
IWL_ERR_DEV(dev, "NVM: used only %d of %d channels\n",
|
||||
n_used, n_channels);
|
||||
}
|
||||
|
||||
static int iwl_get_sku(const struct iwl_cfg *cfg, const __le16 *nvm_sw,
|
||||
static int iwl_get_sku(const struct iwl_rf_cfg *cfg, const __le16 *nvm_sw,
|
||||
const __le16 *phy_sku)
|
||||
{
|
||||
if (cfg->nvm_type != IWL_NVM_EXT)
|
||||
@@ -1241,7 +1233,7 @@ static int iwl_get_sku(const struct iwl_cfg *cfg, const __le16 *nvm_sw,
|
||||
return le32_to_cpup((const __le32 *)(phy_sku + SKU_FAMILY_8000));
|
||||
}
|
||||
|
||||
static int iwl_get_nvm_version(const struct iwl_cfg *cfg, const __le16 *nvm_sw)
|
||||
static int iwl_get_nvm_version(const struct iwl_rf_cfg *cfg, const __le16 *nvm_sw)
|
||||
{
|
||||
if (cfg->nvm_type != IWL_NVM_EXT)
|
||||
return le16_to_cpup(nvm_sw + NVM_VERSION);
|
||||
@@ -1250,7 +1242,7 @@ static int iwl_get_nvm_version(const struct iwl_cfg *cfg, const __le16 *nvm_sw)
|
||||
NVM_VERSION_EXT_NVM));
|
||||
}
|
||||
|
||||
static int iwl_get_radio_cfg(const struct iwl_cfg *cfg, const __le16 *nvm_sw,
|
||||
static int iwl_get_radio_cfg(const struct iwl_rf_cfg *cfg, const __le16 *nvm_sw,
|
||||
const __le16 *phy_sku)
|
||||
{
|
||||
if (cfg->nvm_type != IWL_NVM_EXT)
|
||||
@@ -1260,7 +1252,7 @@ static int iwl_get_radio_cfg(const struct iwl_cfg *cfg, const __le16 *nvm_sw,
|
||||
|
||||
}
|
||||
|
||||
static int iwl_get_n_hw_addrs(const struct iwl_cfg *cfg, const __le16 *nvm_sw)
|
||||
static int iwl_get_n_hw_addrs(const struct iwl_rf_cfg *cfg, const __le16 *nvm_sw)
|
||||
{
|
||||
int n_hw_addr;
|
||||
|
||||
@@ -1272,7 +1264,7 @@ static int iwl_get_n_hw_addrs(const struct iwl_cfg *cfg, const __le16 *nvm_sw)
|
||||
return n_hw_addr & N_HW_ADDR_MASK;
|
||||
}
|
||||
|
||||
static void iwl_set_radio_cfg(const struct iwl_cfg *cfg,
|
||||
static void iwl_set_radio_cfg(const struct iwl_rf_cfg *cfg,
|
||||
struct iwl_nvm_data *data,
|
||||
u32 radio_cfg)
|
||||
{
|
||||
@@ -1331,7 +1323,7 @@ static void iwl_set_hw_address_from_csr(struct iwl_trans *trans,
|
||||
}
|
||||
|
||||
static void iwl_set_hw_address_family_8000(struct iwl_trans *trans,
|
||||
const struct iwl_cfg *cfg,
|
||||
const struct iwl_rf_cfg *cfg,
|
||||
struct iwl_nvm_data *data,
|
||||
const __le16 *mac_override,
|
||||
const __be16 *nvm_hw)
|
||||
@@ -1380,11 +1372,12 @@ static void iwl_set_hw_address_family_8000(struct iwl_trans *trans,
|
||||
}
|
||||
|
||||
static int iwl_set_hw_address(struct iwl_trans *trans,
|
||||
const struct iwl_cfg *cfg,
|
||||
const struct iwl_rf_cfg *cfg,
|
||||
struct iwl_nvm_data *data, const __be16 *nvm_hw,
|
||||
const __le16 *mac_override)
|
||||
{
|
||||
if (cfg->mac_addr_from_csr) {
|
||||
const struct iwl_mac_cfg *mac_cfg = trans->mac_cfg;
|
||||
if (mac_cfg->base->mac_addr_from_csr) {
|
||||
iwl_set_hw_address_from_csr(trans, data);
|
||||
} else if (cfg->nvm_type != IWL_NVM_EXT) {
|
||||
const u8 *hw_addr = (const u8 *)(nvm_hw + HW_ADDR);
|
||||
@@ -1419,7 +1412,7 @@ static int iwl_set_hw_address(struct iwl_trans *trans,
|
||||
}
|
||||
|
||||
static bool
|
||||
iwl_nvm_no_wide_in_5ghz(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
||||
iwl_nvm_no_wide_in_5ghz(struct iwl_trans *trans, const struct iwl_rf_cfg *cfg,
|
||||
const __be16 *nvm_hw)
|
||||
{
|
||||
/*
|
||||
@@ -1431,7 +1424,7 @@ iwl_nvm_no_wide_in_5ghz(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
||||
* in 5GHz otherwise the FW will throw a sysassert when we try
|
||||
* to use them.
|
||||
*/
|
||||
if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_7000) {
|
||||
if (trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_7000) {
|
||||
/*
|
||||
* Unlike the other sections in the NVM, the hw
|
||||
* section uses big-endian.
|
||||
@@ -1451,7 +1444,7 @@ iwl_nvm_no_wide_in_5ghz(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
||||
}
|
||||
|
||||
struct iwl_nvm_data *
|
||||
iwl_parse_mei_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
||||
iwl_parse_mei_nvm_data(struct iwl_trans *trans, const struct iwl_rf_cfg *cfg,
|
||||
const struct iwl_mei_nvm *mei_nvm,
|
||||
const struct iwl_fw *fw, u8 tx_ant, u8 rx_ant)
|
||||
{
|
||||
@@ -1515,7 +1508,7 @@ iwl_parse_mei_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
||||
IWL_EXPORT_SYMBOL(iwl_parse_mei_nvm_data);
|
||||
|
||||
struct iwl_nvm_data *
|
||||
iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
||||
iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_rf_cfg *cfg,
|
||||
const struct iwl_fw *fw,
|
||||
const __be16 *nvm_hw, const __le16 *nvm_sw,
|
||||
const __le16 *nvm_calib, const __le16 *regulatory,
|
||||
@@ -1614,8 +1607,7 @@ IWL_EXPORT_SYMBOL(iwl_parse_nvm_data);
|
||||
|
||||
static u32 iwl_nvm_get_regdom_bw_flags(const u16 *nvm_chan,
|
||||
int ch_idx, u16 nvm_flags,
|
||||
struct iwl_reg_capa reg_capa,
|
||||
const struct iwl_cfg *cfg)
|
||||
struct iwl_reg_capa reg_capa)
|
||||
{
|
||||
u32 flags = NL80211_RRF_NO_HT40;
|
||||
|
||||
@@ -1650,6 +1642,10 @@ static u32 iwl_nvm_get_regdom_bw_flags(const u16 *nvm_chan,
|
||||
if (nvm_flags & NVM_CHANNEL_INDOOR_ONLY)
|
||||
flags |= NL80211_RRF_NO_OUTDOOR;
|
||||
|
||||
if (nvm_flags & NVM_CHANNEL_ALLOW_20MHZ_ACTIVITY &&
|
||||
flags & NL80211_RRF_NO_IR)
|
||||
flags |= NL80211_RRF_ALLOW_20MHZ_ACTIVITY;
|
||||
|
||||
/* Set the GO concurrent flag only in case that NO_IR is set.
|
||||
* Otherwise it is meaningless
|
||||
*/
|
||||
@@ -1666,10 +1662,12 @@ static u32 iwl_nvm_get_regdom_bw_flags(const u16 *nvm_chan,
|
||||
}
|
||||
|
||||
/* Set the AP type for the UHB case. */
|
||||
if (nvm_flags & NVM_CHANNEL_VLP)
|
||||
flags |= NL80211_RRF_ALLOW_6GHZ_VLP_AP;
|
||||
else
|
||||
if (nvm_flags & NVM_CHANNEL_VLP) {
|
||||
if (!(nvm_flags & NVM_CHANNEL_VLP_AP_NOT_ALLOWED))
|
||||
flags |= NL80211_RRF_ALLOW_6GHZ_VLP_AP;
|
||||
} else {
|
||||
flags |= NL80211_RRF_NO_6GHZ_VLP_CLIENT;
|
||||
}
|
||||
|
||||
if (!(nvm_flags & NVM_CHANNEL_AFC))
|
||||
flags |= NL80211_RRF_NO_6GHZ_AFC_CLIENT;
|
||||
@@ -1726,10 +1724,12 @@ static struct iwl_reg_capa iwl_get_reg_capa(u32 flags, u8 resp_ver)
|
||||
}
|
||||
|
||||
struct ieee80211_regdomain *
|
||||
iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
|
||||
iwl_parse_nvm_mcc_info(struct iwl_trans *trans,
|
||||
int num_of_ch, __le32 *channels, u16 fw_mcc,
|
||||
u16 geo_info, u32 cap, u8 resp_ver)
|
||||
{
|
||||
const struct iwl_rf_cfg *cfg = trans->cfg;
|
||||
struct device *dev = trans->dev;
|
||||
int ch_idx;
|
||||
u16 ch_flags;
|
||||
u32 reg_rule_flags, prev_reg_rule_flags = 0;
|
||||
@@ -1794,8 +1794,8 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
|
||||
}
|
||||
|
||||
reg_rule_flags = iwl_nvm_get_regdom_bw_flags(nvm_chan, ch_idx,
|
||||
ch_flags, reg_capa,
|
||||
cfg);
|
||||
ch_flags,
|
||||
reg_capa);
|
||||
|
||||
/* we can't continue the same rule */
|
||||
if (ch_idx == 0 || prev_reg_rule_flags != reg_rule_flags ||
|
||||
@@ -1984,8 +1984,8 @@ int iwl_read_external_nvm(struct iwl_trans *trans,
|
||||
le32_to_cpu(dword_buff[3]));
|
||||
|
||||
/* nvm file validation, dword_buff[2] holds the file version */
|
||||
if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_8000 &&
|
||||
trans->hw_rev_step == SILICON_C_STEP &&
|
||||
if (trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_8000 &&
|
||||
trans->info.hw_rev_step == SILICON_C_STEP &&
|
||||
le32_to_cpu(dword_buff[2]) < 0xE4A) {
|
||||
ret = -EFAULT;
|
||||
goto out;
|
||||
@@ -2052,7 +2052,7 @@ int iwl_read_external_nvm(struct iwl_trans *trans,
|
||||
break;
|
||||
}
|
||||
|
||||
iwl_nvm_fixups(trans->hw_id, section_id, temp, section_size);
|
||||
iwl_nvm_fixups(trans->info.hw_id, section_id, temp, section_size);
|
||||
|
||||
kfree(nvm_sections[section_id].data);
|
||||
nvm_sections[section_id].data = temp;
|
||||
@@ -2159,7 +2159,7 @@ struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans,
|
||||
!!(mac_flags & NVM_MAC_SKU_FLAGS_BAND_5_2_ENABLED);
|
||||
nvm->sku_cap_mimo_disabled =
|
||||
!!(mac_flags & NVM_MAC_SKU_FLAGS_MIMO_DISABLED);
|
||||
if (CSR_HW_RFID_TYPE(trans->hw_rf_id) >= IWL_CFG_RF_TYPE_FM)
|
||||
if (CSR_HW_RFID_TYPE(trans->info.hw_rf_id) >= IWL_CFG_RF_TYPE_FM)
|
||||
nvm->sku_cap_11be_enable = true;
|
||||
|
||||
/* Initialize PHY sku data */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2005-2015, 2018-2024 Intel Corporation
|
||||
* Copyright (C) 2005-2015, 2018-2025 Intel Corporation
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
#ifndef __iwl_nvm_parse_h__
|
||||
@@ -30,7 +30,7 @@ enum iwl_nvm_sbands_flags {
|
||||
* later with iwl_free_nvm_data().
|
||||
*/
|
||||
struct iwl_nvm_data *
|
||||
iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
||||
iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_rf_cfg *cfg,
|
||||
const struct iwl_fw *fw,
|
||||
const __be16 *nvm_hw, const __le16 *nvm_sw,
|
||||
const __le16 *nvm_calib, const __le16 *regulatory,
|
||||
@@ -46,9 +46,17 @@ iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
||||
* accordingly. An ERR_PTR is returned on error.
|
||||
* If not given to the regulatory core, the user is responsible for freeing
|
||||
* the regdomain returned here with kfree.
|
||||
*
|
||||
* @trans: the transport
|
||||
* @num_of_ch: the number of channels
|
||||
* @channels: channel map
|
||||
* @fw_mcc: firmware country code
|
||||
* @geo_info: geo info value
|
||||
* @cap: capability
|
||||
* @resp_ver: FW response version
|
||||
*/
|
||||
struct ieee80211_regdomain *
|
||||
iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
|
||||
iwl_parse_nvm_mcc_info(struct iwl_trans *trans,
|
||||
int num_of_ch, __le32 *channels, u16 fw_mcc,
|
||||
u16 geo_info, u32 cap, u8 resp_ver);
|
||||
|
||||
@@ -87,7 +95,7 @@ struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans,
|
||||
* iwl_parse_mei_nvm_data - parse the mei_nvm_data and get an iwl_nvm_data
|
||||
*/
|
||||
struct iwl_nvm_data *
|
||||
iwl_parse_mei_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
||||
iwl_parse_mei_nvm_data(struct iwl_trans *trans, const struct iwl_rf_cfg *cfg,
|
||||
const struct iwl_mei_nvm *mei_nvm,
|
||||
const struct iwl_fw *fw, u8 set_tx_ant, u8 set_rx_ant);
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2005-2014, 2018-2021, 2023 Intel Corporation
|
||||
* Copyright (C) 2005-2014, 2018-2021, 2023, 2025 Intel Corporation
|
||||
* Copyright (C) 2015 Intel Mobile Communications GmbH
|
||||
*/
|
||||
#include <linux/types.h>
|
||||
@@ -42,7 +42,7 @@ void iwl_init_ht_hw_capab(struct iwl_trans *trans,
|
||||
enum nl80211_band band,
|
||||
u8 tx_chains, u8 rx_chains)
|
||||
{
|
||||
const struct iwl_cfg *cfg = trans->cfg;
|
||||
const struct iwl_rf_cfg *cfg = trans->cfg;
|
||||
int max_bit_rate = 0;
|
||||
|
||||
tx_chains = hweight8(tx_chains);
|
||||
@@ -53,7 +53,8 @@ void iwl_init_ht_hw_capab(struct iwl_trans *trans,
|
||||
|
||||
if (!(data->sku_cap_11n_enable) ||
|
||||
(iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_ALL) ||
|
||||
!cfg->ht_params) {
|
||||
/* there are no devices with HT but without HT40 entirely */
|
||||
!cfg->ht_params.ht40_bands) {
|
||||
ht_info->ht_supported = false;
|
||||
return;
|
||||
}
|
||||
@@ -64,17 +65,17 @@ void iwl_init_ht_hw_capab(struct iwl_trans *trans,
|
||||
ht_info->ht_supported = true;
|
||||
ht_info->cap = IEEE80211_HT_CAP_DSSSCCK40;
|
||||
|
||||
if (cfg->ht_params->stbc) {
|
||||
if (cfg->ht_params.stbc) {
|
||||
ht_info->cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
|
||||
|
||||
if (tx_chains > 1)
|
||||
ht_info->cap |= IEEE80211_HT_CAP_TX_STBC;
|
||||
}
|
||||
|
||||
if (cfg->ht_params->ldpc)
|
||||
if (cfg->ht_params.ldpc)
|
||||
ht_info->cap |= IEEE80211_HT_CAP_LDPC_CODING;
|
||||
|
||||
if (trans->trans_cfg->mq_rx_supported ||
|
||||
if (trans->mac_cfg->mq_rx_supported ||
|
||||
iwlwifi_mod_params.amsdu_size >= IWL_AMSDU_8K)
|
||||
ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU;
|
||||
|
||||
@@ -90,13 +91,13 @@ void iwl_init_ht_hw_capab(struct iwl_trans *trans,
|
||||
if (rx_chains >= 3)
|
||||
ht_info->mcs.rx_mask[2] = 0xFF;
|
||||
|
||||
if (cfg->ht_params->ht_greenfield_support)
|
||||
if (cfg->ht_params.ht_greenfield_support)
|
||||
ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD;
|
||||
ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
|
||||
|
||||
max_bit_rate = MAX_BIT_RATE_20_MHZ;
|
||||
|
||||
if (cfg->ht_params->ht40_bands & BIT(band)) {
|
||||
if (cfg->ht_params.ht40_bands & BIT(band)) {
|
||||
ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
|
||||
ht_info->cap |= IEEE80211_HT_CAP_SGI_40;
|
||||
max_bit_rate = MAX_BIT_RATE_40_MHZ;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2005-2014, 2018-2021, 2024 Intel Corporation
|
||||
* Copyright (C) 2005-2014, 2018-2021, 2024-2025 Intel Corporation
|
||||
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2015 Intel Deutschland GmbH
|
||||
*/
|
||||
@@ -17,7 +17,7 @@ struct sk_buff;
|
||||
struct iwl_device_cmd;
|
||||
struct iwl_rx_cmd_buffer;
|
||||
struct iwl_fw;
|
||||
struct iwl_cfg;
|
||||
struct iwl_rf_cfg;
|
||||
|
||||
/**
|
||||
* DOC: Operational mode - what is it ?
|
||||
@@ -44,6 +44,63 @@ struct iwl_cfg;
|
||||
* 5) The driver layer stops the op_mode
|
||||
*/
|
||||
|
||||
/**
|
||||
* enum iwl_fw_error_type - FW error types/sources
|
||||
* @IWL_ERR_TYPE_IRQ: "normal" FW error through an IRQ
|
||||
* @IWL_ERR_TYPE_NMI_FORCED: NMI was forced by driver
|
||||
* @IWL_ERR_TYPE_RESET_HS_TIMEOUT: reset handshake timed out,
|
||||
* any debug collection must happen synchronously as
|
||||
* the device will be shut down
|
||||
* @IWL_ERR_TYPE_CMD_QUEUE_FULL: command queue was full
|
||||
* @IWL_ERR_TYPE_TOP_RESET_BY_BT: TOP reset initiated by BT
|
||||
* @IWL_ERR_TYPE_TOP_FATAL_ERROR: TOP fatal error
|
||||
* @IWL_ERR_TYPE_TOP_RESET_FAILED: TOP reset failed
|
||||
* @IWL_ERR_TYPE_DEBUGFS: error/reset indication from debugfs
|
||||
*/
|
||||
enum iwl_fw_error_type {
|
||||
IWL_ERR_TYPE_IRQ,
|
||||
IWL_ERR_TYPE_NMI_FORCED,
|
||||
IWL_ERR_TYPE_RESET_HS_TIMEOUT,
|
||||
IWL_ERR_TYPE_CMD_QUEUE_FULL,
|
||||
IWL_ERR_TYPE_TOP_RESET_BY_BT,
|
||||
IWL_ERR_TYPE_TOP_FATAL_ERROR,
|
||||
IWL_ERR_TYPE_TOP_RESET_FAILED,
|
||||
IWL_ERR_TYPE_DEBUGFS,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum iwl_fw_error_context - error dump context
|
||||
* @IWL_ERR_CONTEXT_WORKER: regular from worker context,
|
||||
* opmode must acquire locks and must also check
|
||||
* for @IWL_ERR_CONTEXT_ABORT after acquiring locks
|
||||
* @IWL_ERR_CONTEXT_FROM_OPMODE: context is in a call
|
||||
* originating from the opmode, e.g. while resetting
|
||||
* or stopping the device, so opmode must not acquire
|
||||
* any locks
|
||||
* @IWL_ERR_CONTEXT_ABORT: after lock acquisition, indicates
|
||||
* that the dump already happened via another callback
|
||||
* (currently only while stopping the device) via the
|
||||
* @IWL_ERR_CONTEXT_FROM_OPMODE context, and this call
|
||||
* must be aborted
|
||||
*/
|
||||
enum iwl_fw_error_context {
|
||||
IWL_ERR_CONTEXT_WORKER,
|
||||
IWL_ERR_CONTEXT_FROM_OPMODE,
|
||||
IWL_ERR_CONTEXT_ABORT,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_fw_error_dump_mode - error dump mode for callback
|
||||
* @type: The reason for the dump, per &enum iwl_fw_error_type.
|
||||
* @context: The context for the dump, may also indicate this
|
||||
* call needs to be skipped. This MUST be checked before
|
||||
* and after acquiring any locks in the op-mode!
|
||||
*/
|
||||
struct iwl_fw_error_dump_mode {
|
||||
enum iwl_fw_error_type type;
|
||||
enum iwl_fw_error_context context;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_op_mode_ops - op_mode specific operations
|
||||
*
|
||||
@@ -77,10 +134,11 @@ struct iwl_cfg;
|
||||
* reclaimed by the op_mode. This can happen when the driver is freed and
|
||||
* there are Tx packets pending in the transport layer.
|
||||
* Must be atomic
|
||||
* @nic_error: error notification. Must be atomic and must be called with BH
|
||||
* disabled, unless the sync parameter is true.
|
||||
* @cmd_queue_full: Called when the command queue gets full. Must be atomic and
|
||||
* called with BH disabled.
|
||||
* @nic_error: error notification. Must be atomic, the op mode should handle
|
||||
* the error (e.g. abort notification waiters) and print the error if
|
||||
* applicable
|
||||
* @dump_error: NIC error dump collection (can sleep, synchronous)
|
||||
* @sw_reset: (maybe) initiate a software reset, return %true if started
|
||||
* @nic_config: configure NIC, called before firmware is started.
|
||||
* May sleep
|
||||
* @wimax_active: invoked when WiMax becomes active. May sleep
|
||||
@@ -89,10 +147,12 @@ struct iwl_cfg;
|
||||
* Op_mode needs to reset its internal state because the device did not
|
||||
* survive the system state transition. The firmware is no longer running,
|
||||
* etc...
|
||||
* @dump: Op_mode needs to collect the firmware dump upon this handler
|
||||
* being called.
|
||||
*/
|
||||
struct iwl_op_mode_ops {
|
||||
struct iwl_op_mode *(*start)(struct iwl_trans *trans,
|
||||
const struct iwl_cfg *cfg,
|
||||
const struct iwl_rf_cfg *cfg,
|
||||
const struct iwl_fw *fw,
|
||||
struct dentry *dbgfs_dir);
|
||||
void (*stop)(struct iwl_op_mode *op_mode);
|
||||
@@ -104,14 +164,19 @@ struct iwl_op_mode_ops {
|
||||
void (*queue_not_full)(struct iwl_op_mode *op_mode, int queue);
|
||||
bool (*hw_rf_kill)(struct iwl_op_mode *op_mode, bool state);
|
||||
void (*free_skb)(struct iwl_op_mode *op_mode, struct sk_buff *skb);
|
||||
void (*nic_error)(struct iwl_op_mode *op_mode, bool sync);
|
||||
void (*cmd_queue_full)(struct iwl_op_mode *op_mode);
|
||||
void (*nic_error)(struct iwl_op_mode *op_mode,
|
||||
enum iwl_fw_error_type type);
|
||||
void (*dump_error)(struct iwl_op_mode *op_mode,
|
||||
struct iwl_fw_error_dump_mode *mode);
|
||||
bool (*sw_reset)(struct iwl_op_mode *op_mode,
|
||||
enum iwl_fw_error_type type);
|
||||
void (*nic_config)(struct iwl_op_mode *op_mode);
|
||||
void (*wimax_active)(struct iwl_op_mode *op_mode);
|
||||
void (*time_point)(struct iwl_op_mode *op_mode,
|
||||
enum iwl_fw_ini_time_point tp_id,
|
||||
union iwl_dbg_tlv_tp_data *tp_data);
|
||||
void (*device_powered_off)(struct iwl_op_mode *op_mode);
|
||||
void (*dump)(struct iwl_op_mode *op_mode);
|
||||
};
|
||||
|
||||
int iwl_opmode_register(const char *name, const struct iwl_op_mode_ops *ops);
|
||||
@@ -177,14 +242,22 @@ static inline void iwl_op_mode_free_skb(struct iwl_op_mode *op_mode,
|
||||
op_mode->ops->free_skb(op_mode, skb);
|
||||
}
|
||||
|
||||
static inline void iwl_op_mode_nic_error(struct iwl_op_mode *op_mode, bool sync)
|
||||
static inline void iwl_op_mode_nic_error(struct iwl_op_mode *op_mode,
|
||||
enum iwl_fw_error_type type)
|
||||
{
|
||||
op_mode->ops->nic_error(op_mode, sync);
|
||||
op_mode->ops->nic_error(op_mode, type);
|
||||
}
|
||||
|
||||
static inline void iwl_op_mode_cmd_queue_full(struct iwl_op_mode *op_mode)
|
||||
static inline void iwl_op_mode_dump_error(struct iwl_op_mode *op_mode,
|
||||
struct iwl_fw_error_dump_mode *mode)
|
||||
{
|
||||
op_mode->ops->cmd_queue_full(op_mode);
|
||||
might_sleep();
|
||||
|
||||
if (WARN_ON(mode->type == IWL_ERR_TYPE_TOP_RESET_BY_BT))
|
||||
return;
|
||||
|
||||
if (op_mode->ops->dump_error)
|
||||
op_mode->ops->dump_error(op_mode, mode);
|
||||
}
|
||||
|
||||
static inline void iwl_op_mode_nic_config(struct iwl_op_mode *op_mode)
|
||||
@@ -216,4 +289,11 @@ static inline void iwl_op_mode_device_powered_off(struct iwl_op_mode *op_mode)
|
||||
op_mode->ops->device_powered_off(op_mode);
|
||||
}
|
||||
|
||||
static inline void iwl_op_mode_dump(struct iwl_op_mode *op_mode)
|
||||
{
|
||||
if (!op_mode || !op_mode->ops || !op_mode->ops->dump)
|
||||
return;
|
||||
op_mode->ops->dump(op_mode);
|
||||
}
|
||||
|
||||
#endif /* __iwl_op_mode_h__ */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2005-2014, 2018-2024 Intel Corporation
|
||||
* Copyright (C) 2005-2014, 2018-2025 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016 Intel Deutschland GmbH
|
||||
*/
|
||||
@@ -381,6 +381,10 @@ enum {
|
||||
#define CNVR_SCU_SD_REGS_SD_REG_ACTIVE_VDIG_MIRROR 0xA29938
|
||||
#define CNVI_SCU_SEQ_DATA_DW9 0xA27488
|
||||
|
||||
#define CNVI_SCU_REG_FOR_ECO_1 0xA26EF8
|
||||
#define CNVI_SCU_REG_FOR_ECO_1_WIAMT_KNOWN BIT(4)
|
||||
#define CNVI_SCU_REG_FOR_ECO_1_WIAMT_PRESENT BIT(5)
|
||||
|
||||
#define CNVI_PMU_STEP_FLOW 0xA2D588
|
||||
#define CNVI_PMU_STEP_FLOW_FORCE_URM BIT(2)
|
||||
|
||||
@@ -458,6 +462,7 @@ enum {
|
||||
#define REG_CRF_ID_TYPE_GF 0x410
|
||||
#define REG_CRF_ID_TYPE_FM 0x910
|
||||
#define REG_CRF_ID_TYPE_WHP 0xA10
|
||||
#define REG_CRF_ID_TYPE_PE 0xA30
|
||||
|
||||
#define HPM_DEBUG 0xA03440
|
||||
#define PERSISTENCE_BIT BIT(12)
|
||||
@@ -509,6 +514,14 @@ enum {
|
||||
#define WMAL_INDRCT_CMD(addr) \
|
||||
((WMAL_CMD_READ_BURST_ACCESS << WMAL_INDRCT_RD_CMD1_OPMOD_POS) | \
|
||||
((addr) & WMAL_INDRCT_RD_CMD1_BYTE_ADDRESS_MSK))
|
||||
#define WMAL_MRSPF_STTS 0xADFC24
|
||||
#define WMAL_MRSPF_STTS_FIFO1_NOT_EMPTY_POS 15
|
||||
#define WMAL_MRSPF_STTS_FIFO1_NOT_EMPTY_MSK 0x8000
|
||||
#define WMAL_TIMEOUT_VAL 0xA5A5A5A2
|
||||
#define WMAL_MRSPF_STTS_IS_FIFO1_NOT_EMPTY(val) \
|
||||
(((val) >> (WMAL_MRSPF_STTS_FIFO1_NOT_EMPTY_POS)) & \
|
||||
((WMAL_MRSPF_STTS_FIFO1_NOT_EMPTY_MSK) >> \
|
||||
(WMAL_MRSPF_STTS_FIFO1_NOT_EMPTY_POS)))
|
||||
|
||||
#define WFPM_LMAC1_PS_CTL_RW 0xA03380
|
||||
#define WFPM_LMAC2_PS_CTL_RW 0xA033C0
|
||||
|
||||
+375
-113
@@ -2,10 +2,11 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2019-2021, 2023-2024 Intel Corporation
|
||||
* Copyright (C) 2019-2021, 2023-2025 Intel Corporation
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/bsearch.h>
|
||||
#include <linux/list.h>
|
||||
|
||||
#include "fw/api/tx.h"
|
||||
#include "iwl-trans.h"
|
||||
@@ -13,56 +14,283 @@
|
||||
#include "iwl-fh.h"
|
||||
#include <linux/dmapool.h>
|
||||
#include "fw/api/commands.h"
|
||||
#include "pcie/internal.h"
|
||||
#include "iwl-context-info-gen3.h"
|
||||
#include "pcie/gen1_2/internal.h"
|
||||
#include "pcie/iwl-context-info-v2.h"
|
||||
|
||||
struct iwl_trans_dev_restart_data {
|
||||
struct list_head list;
|
||||
unsigned int restart_count;
|
||||
time64_t last_error;
|
||||
bool backoff;
|
||||
char name[];
|
||||
};
|
||||
|
||||
static LIST_HEAD(restart_data_list);
|
||||
static DEFINE_SPINLOCK(restart_data_lock);
|
||||
|
||||
static struct iwl_trans_dev_restart_data *
|
||||
iwl_trans_get_restart_data(struct device *dev)
|
||||
{
|
||||
struct iwl_trans_dev_restart_data *tmp, *data = NULL;
|
||||
const char *name = dev_name(dev);
|
||||
|
||||
spin_lock(&restart_data_lock);
|
||||
list_for_each_entry(tmp, &restart_data_list, list) {
|
||||
if (strcmp(tmp->name, name))
|
||||
continue;
|
||||
data = tmp;
|
||||
break;
|
||||
}
|
||||
spin_unlock(&restart_data_lock);
|
||||
|
||||
if (data)
|
||||
return data;
|
||||
|
||||
data = kzalloc(struct_size(data, name, strlen(name) + 1), GFP_ATOMIC);
|
||||
if (!data)
|
||||
return NULL;
|
||||
|
||||
strcpy(data->name, name);
|
||||
spin_lock(&restart_data_lock);
|
||||
list_add_tail(&data->list, &restart_data_list);
|
||||
spin_unlock(&restart_data_lock);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static void iwl_trans_inc_restart_count(struct device *dev)
|
||||
{
|
||||
struct iwl_trans_dev_restart_data *data;
|
||||
|
||||
data = iwl_trans_get_restart_data(dev);
|
||||
if (data) {
|
||||
data->last_error = ktime_get_boottime_seconds();
|
||||
data->restart_count++;
|
||||
}
|
||||
}
|
||||
|
||||
void iwl_trans_free_restart_list(void)
|
||||
{
|
||||
struct iwl_trans_dev_restart_data *tmp;
|
||||
|
||||
while ((tmp = list_first_entry_or_null(&restart_data_list,
|
||||
typeof(*tmp), list))) {
|
||||
list_del(&tmp->list);
|
||||
kfree(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
struct iwl_trans_reprobe {
|
||||
struct device *dev;
|
||||
struct delayed_work work;
|
||||
};
|
||||
|
||||
static void iwl_trans_reprobe_wk(struct work_struct *wk)
|
||||
{
|
||||
struct iwl_trans_reprobe *reprobe;
|
||||
|
||||
reprobe = container_of(wk, typeof(*reprobe), work.work);
|
||||
|
||||
if (device_reprobe(reprobe->dev))
|
||||
dev_err(reprobe->dev, "reprobe failed!\n");
|
||||
put_device(reprobe->dev);
|
||||
kfree(reprobe);
|
||||
module_put(THIS_MODULE);
|
||||
}
|
||||
|
||||
static void iwl_trans_schedule_reprobe(struct iwl_trans *trans,
|
||||
unsigned int delay_ms)
|
||||
{
|
||||
struct iwl_trans_reprobe *reprobe;
|
||||
|
||||
/*
|
||||
* get a module reference to avoid doing this while unloading
|
||||
* anyway and to avoid scheduling a work with code that's
|
||||
* being removed.
|
||||
*/
|
||||
if (!try_module_get(THIS_MODULE)) {
|
||||
IWL_ERR(trans, "Module is being unloaded - abort\n");
|
||||
return;
|
||||
}
|
||||
|
||||
reprobe = kzalloc(sizeof(*reprobe), GFP_KERNEL);
|
||||
if (!reprobe) {
|
||||
module_put(THIS_MODULE);
|
||||
return;
|
||||
}
|
||||
reprobe->dev = get_device(trans->dev);
|
||||
INIT_DELAYED_WORK(&reprobe->work, iwl_trans_reprobe_wk);
|
||||
schedule_delayed_work(&reprobe->work, msecs_to_jiffies(delay_ms));
|
||||
}
|
||||
|
||||
#define IWL_TRANS_RESET_OK_TIME 7 /* seconds */
|
||||
|
||||
static enum iwl_reset_mode
|
||||
iwl_trans_determine_restart_mode(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_trans_dev_restart_data *data;
|
||||
enum iwl_reset_mode at_least = 0;
|
||||
unsigned int index;
|
||||
static const enum iwl_reset_mode escalation_list_old[] = {
|
||||
IWL_RESET_MODE_SW_RESET,
|
||||
IWL_RESET_MODE_REPROBE,
|
||||
IWL_RESET_MODE_REPROBE,
|
||||
IWL_RESET_MODE_FUNC_RESET,
|
||||
IWL_RESET_MODE_PROD_RESET,
|
||||
};
|
||||
static const enum iwl_reset_mode escalation_list_sc[] = {
|
||||
IWL_RESET_MODE_SW_RESET,
|
||||
IWL_RESET_MODE_REPROBE,
|
||||
IWL_RESET_MODE_REPROBE,
|
||||
IWL_RESET_MODE_FUNC_RESET,
|
||||
IWL_RESET_MODE_TOP_RESET,
|
||||
IWL_RESET_MODE_PROD_RESET,
|
||||
IWL_RESET_MODE_TOP_RESET,
|
||||
IWL_RESET_MODE_PROD_RESET,
|
||||
IWL_RESET_MODE_TOP_RESET,
|
||||
IWL_RESET_MODE_PROD_RESET,
|
||||
};
|
||||
const enum iwl_reset_mode *escalation_list;
|
||||
size_t escalation_list_size;
|
||||
|
||||
/* used by TOP fatal error/TOP reset */
|
||||
if (trans->restart.mode.type == IWL_ERR_TYPE_TOP_RESET_FAILED)
|
||||
return IWL_RESET_MODE_PROD_RESET;
|
||||
|
||||
if (trans->request_top_reset) {
|
||||
trans->request_top_reset = 0;
|
||||
if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_SC)
|
||||
return IWL_RESET_MODE_TOP_RESET;
|
||||
return IWL_RESET_MODE_PROD_RESET;
|
||||
}
|
||||
|
||||
if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_SC) {
|
||||
escalation_list = escalation_list_sc;
|
||||
escalation_list_size = ARRAY_SIZE(escalation_list_sc);
|
||||
} else {
|
||||
escalation_list = escalation_list_old;
|
||||
escalation_list_size = ARRAY_SIZE(escalation_list_old);
|
||||
}
|
||||
|
||||
if (trans->restart.during_reset)
|
||||
at_least = IWL_RESET_MODE_REPROBE;
|
||||
|
||||
data = iwl_trans_get_restart_data(trans->dev);
|
||||
if (!data)
|
||||
return at_least;
|
||||
|
||||
if (!data->backoff &&
|
||||
ktime_get_boottime_seconds() - data->last_error >=
|
||||
IWL_TRANS_RESET_OK_TIME)
|
||||
data->restart_count = 0;
|
||||
|
||||
index = data->restart_count;
|
||||
if (index >= escalation_list_size) {
|
||||
index = escalation_list_size - 1;
|
||||
if (!data->backoff) {
|
||||
data->backoff = true;
|
||||
return IWL_RESET_MODE_BACKOFF;
|
||||
}
|
||||
data->backoff = false;
|
||||
}
|
||||
|
||||
return max(at_least, escalation_list[index]);
|
||||
}
|
||||
|
||||
#define IWL_TRANS_TOP_FOLLOWER_WAIT 180 /* ms */
|
||||
|
||||
#define IWL_TRANS_RESET_DELAY (HZ * 60)
|
||||
|
||||
static void iwl_trans_restart_wk(struct work_struct *wk)
|
||||
{
|
||||
struct iwl_trans *trans = container_of(wk, typeof(*trans),
|
||||
restart.wk.work);
|
||||
enum iwl_reset_mode mode;
|
||||
|
||||
if (trans->restart.mode.type == IWL_ERR_TYPE_TOP_RESET_BY_BT) {
|
||||
iwl_trans_schedule_reprobe(trans, IWL_TRANS_TOP_FOLLOWER_WAIT);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!trans->op_mode)
|
||||
return;
|
||||
|
||||
/* might have been scheduled before marked as dead, re-check */
|
||||
if (test_bit(STATUS_TRANS_DEAD, &trans->status))
|
||||
return;
|
||||
|
||||
iwl_op_mode_dump_error(trans->op_mode, &trans->restart.mode);
|
||||
|
||||
/*
|
||||
* If the opmode stopped the device while we were trying to dump and
|
||||
* reset, then we'll have done the dump already (synchronized by the
|
||||
* opmode lock that it will acquire in iwl_op_mode_dump_error()) and
|
||||
* managed that via trans->restart.mode.
|
||||
* Additionally, make sure that in such a case we won't attempt to do
|
||||
* any resets now, since it's no longer requested.
|
||||
*/
|
||||
if (!test_and_clear_bit(STATUS_RESET_PENDING, &trans->status))
|
||||
return;
|
||||
|
||||
if (!iwlwifi_mod_params.fw_restart)
|
||||
return;
|
||||
|
||||
mode = iwl_trans_determine_restart_mode(trans);
|
||||
if (mode == IWL_RESET_MODE_BACKOFF) {
|
||||
IWL_ERR(trans, "Too many device errors - delay next reset\n");
|
||||
queue_delayed_work(system_unbound_wq, &trans->restart.wk,
|
||||
IWL_TRANS_RESET_DELAY);
|
||||
return;
|
||||
}
|
||||
|
||||
iwl_trans_inc_restart_count(trans->dev);
|
||||
|
||||
switch (mode) {
|
||||
case IWL_RESET_MODE_TOP_RESET:
|
||||
trans->do_top_reset = 1;
|
||||
IWL_ERR(trans, "Device error - TOP reset\n");
|
||||
fallthrough;
|
||||
case IWL_RESET_MODE_SW_RESET:
|
||||
if (mode == IWL_RESET_MODE_SW_RESET)
|
||||
IWL_ERR(trans, "Device error - SW reset\n");
|
||||
iwl_trans_opmode_sw_reset(trans, trans->restart.mode.type);
|
||||
break;
|
||||
case IWL_RESET_MODE_REPROBE:
|
||||
IWL_ERR(trans, "Device error - reprobe!\n");
|
||||
|
||||
iwl_trans_schedule_reprobe(trans, 0);
|
||||
break;
|
||||
default:
|
||||
iwl_trans_pcie_reset(trans, mode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct iwl_trans *iwl_trans_alloc(unsigned int priv_size,
|
||||
struct device *dev,
|
||||
const struct iwl_cfg_trans_params *cfg_trans)
|
||||
const struct iwl_mac_cfg *mac_cfg,
|
||||
unsigned int txcmd_size,
|
||||
unsigned int txcmd_align)
|
||||
{
|
||||
struct iwl_trans *trans;
|
||||
#ifdef CONFIG_LOCKDEP
|
||||
static struct lock_class_key __key;
|
||||
static struct lock_class_key __sync_cmd_key;
|
||||
#endif
|
||||
|
||||
trans = devm_kzalloc(dev, sizeof(*trans) + priv_size, GFP_KERNEL);
|
||||
if (!trans)
|
||||
return NULL;
|
||||
|
||||
trans->trans_cfg = cfg_trans;
|
||||
trans->mac_cfg = mac_cfg;
|
||||
|
||||
#ifdef CONFIG_LOCKDEP
|
||||
lockdep_init_map(&trans->sync_cmd_lockdep_map, "sync_cmd_lockdep_map",
|
||||
&__key, 0);
|
||||
&__sync_cmd_key, 0);
|
||||
#endif
|
||||
|
||||
trans->dev = dev;
|
||||
trans->num_rx_queues = 1;
|
||||
|
||||
return trans;
|
||||
}
|
||||
|
||||
int iwl_trans_init(struct iwl_trans *trans)
|
||||
{
|
||||
int txcmd_size, txcmd_align;
|
||||
|
||||
if (!trans->trans_cfg->gen2) {
|
||||
txcmd_size = sizeof(struct iwl_tx_cmd);
|
||||
txcmd_align = sizeof(void *);
|
||||
} else if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210) {
|
||||
txcmd_size = sizeof(struct iwl_tx_cmd_gen2);
|
||||
txcmd_align = 64;
|
||||
} else {
|
||||
txcmd_size = sizeof(struct iwl_tx_cmd_gen3);
|
||||
txcmd_align = 128;
|
||||
}
|
||||
|
||||
txcmd_size += sizeof(struct iwl_cmd_header);
|
||||
txcmd_size += 36; /* biggest possible 802.11 header */
|
||||
|
||||
/* Ensure device TX cmd cannot reach/cross a page boundary in gen2 */
|
||||
if (WARN_ON(trans->trans_cfg->gen2 && txcmd_size >= txcmd_align))
|
||||
return -EINVAL;
|
||||
INIT_DELAYED_WORK(&trans->restart.wk, iwl_trans_restart_wk);
|
||||
|
||||
snprintf(trans->dev_cmd_pool_name, sizeof(trans->dev_cmd_pool_name),
|
||||
"iwl_cmd_pool:%s", dev_name(trans->dev));
|
||||
@@ -71,16 +299,14 @@ int iwl_trans_init(struct iwl_trans *trans)
|
||||
txcmd_size, txcmd_align,
|
||||
SLAB_HWCACHE_ALIGN, NULL);
|
||||
if (!trans->dev_cmd_pool)
|
||||
return -ENOMEM;
|
||||
return NULL;
|
||||
|
||||
/* Initialize the wait queue for commands */
|
||||
init_waitqueue_head(&trans->wait_command_queue);
|
||||
|
||||
return 0;
|
||||
return trans;
|
||||
}
|
||||
|
||||
void iwl_trans_free(struct iwl_trans *trans)
|
||||
{
|
||||
cancel_delayed_work_sync(&trans->restart.wk);
|
||||
kmem_cache_destroy(trans->dev_cmd_pool);
|
||||
}
|
||||
|
||||
@@ -92,17 +318,7 @@ int iwl_trans_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
|
||||
test_bit(STATUS_RFKILL_OPMODE, &trans->status)))
|
||||
return -ERFKILL;
|
||||
|
||||
/*
|
||||
* We can't test IWL_MVM_STATUS_IN_D3 in mvm->status because this
|
||||
* bit is set early in the D3 flow, before we send all the commands
|
||||
* that configure the firmware for D3 operation (power, patterns, ...)
|
||||
* and we don't want to flag all those with CMD_SEND_IN_D3.
|
||||
* So use the system_pm_mode instead. The only command sent after
|
||||
* we set system_pm_mode is D3_CONFIG_CMD, which we now flag with
|
||||
* CMD_SEND_IN_D3.
|
||||
*/
|
||||
if (unlikely(trans->system_pm_mode == IWL_PLAT_PM_MODE_D3 &&
|
||||
!(cmd->flags & CMD_SEND_IN_D3)))
|
||||
if (unlikely(test_bit(STATUS_SUSPENDED, &trans->status)))
|
||||
return -EHOSTDOWN;
|
||||
|
||||
if (unlikely(test_bit(STATUS_FW_ERROR, &trans->status)))
|
||||
@@ -115,7 +331,7 @@ int iwl_trans_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
|
||||
if (!(cmd->flags & CMD_ASYNC))
|
||||
lock_map_acquire_read(&trans->sync_cmd_lockdep_map);
|
||||
|
||||
if (trans->wide_cmd_header && !iwl_cmd_groupid(cmd->id)) {
|
||||
if (trans->conf.wide_cmd_header && !iwl_cmd_groupid(cmd->id)) {
|
||||
if (cmd->id != REPLY_ERROR)
|
||||
cmd->id = DEF_ID(cmd->id);
|
||||
}
|
||||
@@ -159,11 +375,12 @@ const char *iwl_get_cmd_string(struct iwl_trans *trans, u32 id)
|
||||
grp = iwl_cmd_groupid(id);
|
||||
cmd = iwl_cmd_opcode(id);
|
||||
|
||||
if (!trans->command_groups || grp >= trans->command_groups_size ||
|
||||
!trans->command_groups[grp].arr)
|
||||
if (!trans->conf.command_groups ||
|
||||
grp >= trans->conf.command_groups_size ||
|
||||
!trans->conf.command_groups[grp].arr)
|
||||
return "UNKNOWN";
|
||||
|
||||
arr = &trans->command_groups[grp];
|
||||
arr = &trans->conf.command_groups[grp];
|
||||
ret = bsearch(&cmd, arr->arr, arr->size, size, iwl_hcmd_names_cmp);
|
||||
if (!ret)
|
||||
return "UNKNOWN";
|
||||
@@ -171,37 +388,29 @@ const char *iwl_get_cmd_string(struct iwl_trans *trans, u32 id)
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_get_cmd_string);
|
||||
|
||||
int iwl_cmd_groups_verify_sorted(const struct iwl_trans_config *trans)
|
||||
void iwl_trans_op_mode_enter(struct iwl_trans *trans,
|
||||
struct iwl_op_mode *op_mode)
|
||||
{
|
||||
int i, j;
|
||||
const struct iwl_hcmd_arr *arr;
|
||||
trans->op_mode = op_mode;
|
||||
|
||||
for (i = 0; i < trans->command_groups_size; i++) {
|
||||
arr = &trans->command_groups[i];
|
||||
if (!arr->arr)
|
||||
continue;
|
||||
for (j = 0; j < arr->size - 1; j++)
|
||||
if (arr->arr[j].cmd_id > arr->arr[j + 1].cmd_id)
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
if (WARN_ON(trans->conf.n_no_reclaim_cmds > MAX_NO_RECLAIM_CMDS))
|
||||
trans->conf.n_no_reclaim_cmds =
|
||||
ARRAY_SIZE(trans->conf.no_reclaim_cmds);
|
||||
|
||||
WARN_ON_ONCE(!trans->conf.rx_mpdu_cmd);
|
||||
|
||||
iwl_trans_pcie_op_mode_enter(trans);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_cmd_groups_verify_sorted);
|
||||
|
||||
void iwl_trans_configure(struct iwl_trans *trans,
|
||||
const struct iwl_trans_config *trans_cfg)
|
||||
{
|
||||
trans->op_mode = trans_cfg->op_mode;
|
||||
|
||||
iwl_trans_pcie_configure(trans, trans_cfg);
|
||||
WARN_ON(iwl_cmd_groups_verify_sorted(trans_cfg));
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_configure);
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_op_mode_enter);
|
||||
|
||||
int iwl_trans_start_hw(struct iwl_trans *trans)
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
clear_bit(STATUS_TRANS_RESET_IN_PROGRESS, &trans->status);
|
||||
/* opmode may not resume if it detects errors */
|
||||
clear_bit(STATUS_SUSPENDED, &trans->status);
|
||||
|
||||
return iwl_trans_pcie_start_hw(trans);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_start_hw);
|
||||
@@ -210,9 +419,15 @@ void iwl_trans_op_mode_leave(struct iwl_trans *trans)
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
iwl_trans_pcie_op_mode_leave(trans);
|
||||
if (trans->mac_cfg->gen2)
|
||||
iwl_trans_pcie_gen2_op_mode_leave(trans);
|
||||
else
|
||||
iwl_trans_pcie_op_mode_leave(trans);
|
||||
|
||||
cancel_delayed_work_sync(&trans->restart.wk);
|
||||
|
||||
trans->op_mode = NULL;
|
||||
memset(&trans->conf, 0, sizeof(trans->conf));
|
||||
|
||||
trans->state = IWL_TRANS_NO_FW;
|
||||
}
|
||||
@@ -222,31 +437,26 @@ void iwl_trans_write8(struct iwl_trans *trans, u32 ofs, u8 val)
|
||||
{
|
||||
iwl_trans_pcie_write8(trans, ofs, val);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_write8);
|
||||
|
||||
void iwl_trans_write32(struct iwl_trans *trans, u32 ofs, u32 val)
|
||||
{
|
||||
iwl_trans_pcie_write32(trans, ofs, val);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_write32);
|
||||
|
||||
u32 iwl_trans_read32(struct iwl_trans *trans, u32 ofs)
|
||||
{
|
||||
return iwl_trans_pcie_read32(trans, ofs);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_read32);
|
||||
|
||||
u32 iwl_trans_read_prph(struct iwl_trans *trans, u32 ofs)
|
||||
{
|
||||
return iwl_trans_pcie_read_prph(trans, ofs);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_read_prph);
|
||||
|
||||
void iwl_trans_write_prph(struct iwl_trans *trans, u32 ofs, u32 val)
|
||||
{
|
||||
return iwl_trans_pcie_write_prph(trans, ofs, val);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_write_prph);
|
||||
|
||||
int iwl_trans_read_mem(struct iwl_trans *trans, u32 addr,
|
||||
void *buf, int dwords)
|
||||
@@ -258,7 +468,19 @@ IWL_EXPORT_SYMBOL(iwl_trans_read_mem);
|
||||
int iwl_trans_write_mem(struct iwl_trans *trans, u32 addr,
|
||||
const void *buf, int dwords)
|
||||
{
|
||||
return iwl_trans_pcie_write_mem(trans, addr, buf, dwords);
|
||||
int offs, ret = 0;
|
||||
const u32 *vals = buf;
|
||||
|
||||
if (iwl_trans_grab_nic_access(trans)) {
|
||||
iwl_write32(trans, HBUS_TARG_MEM_WADDR, addr);
|
||||
for (offs = 0; offs < dwords; offs++)
|
||||
iwl_write32(trans, HBUS_TARG_MEM_WDAT,
|
||||
vals ? vals[offs] : 0);
|
||||
iwl_trans_release_nic_access(trans);
|
||||
} else {
|
||||
ret = -EBUSY;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_write_mem);
|
||||
|
||||
@@ -271,11 +493,10 @@ void iwl_trans_set_pmi(struct iwl_trans *trans, bool state)
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_set_pmi);
|
||||
|
||||
int iwl_trans_sw_reset(struct iwl_trans *trans, bool retake_ownership)
|
||||
int iwl_trans_sw_reset(struct iwl_trans *trans)
|
||||
{
|
||||
return iwl_trans_pcie_sw_reset(trans, retake_ownership);
|
||||
return iwl_trans_pcie_sw_reset(trans, true);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_sw_reset);
|
||||
|
||||
struct iwl_trans_dump_data *
|
||||
iwl_trans_dump_data(struct iwl_trans *trans, u32 dump_mask,
|
||||
@@ -285,22 +506,34 @@ iwl_trans_dump_data(struct iwl_trans *trans, u32 dump_mask,
|
||||
return iwl_trans_pcie_dump_data(trans, dump_mask,
|
||||
sanitize_ops, sanitize_ctx);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_dump_data);
|
||||
|
||||
int iwl_trans_d3_suspend(struct iwl_trans *trans, bool test, bool reset)
|
||||
{
|
||||
int err;
|
||||
|
||||
might_sleep();
|
||||
|
||||
return iwl_trans_pcie_d3_suspend(trans, test, reset);
|
||||
err = iwl_trans_pcie_d3_suspend(trans, test, reset);
|
||||
|
||||
if (!err)
|
||||
set_bit(STATUS_SUSPENDED, &trans->status);
|
||||
|
||||
return err;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_d3_suspend);
|
||||
|
||||
int iwl_trans_d3_resume(struct iwl_trans *trans, enum iwl_d3_status *status,
|
||||
bool test, bool reset)
|
||||
{
|
||||
int err;
|
||||
|
||||
might_sleep();
|
||||
|
||||
return iwl_trans_pcie_d3_resume(trans, status, test, reset);
|
||||
err = iwl_trans_pcie_d3_resume(trans, status, test, reset);
|
||||
|
||||
clear_bit(STATUS_SUSPENDED, &trans->status);
|
||||
|
||||
return err;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_d3_resume);
|
||||
|
||||
@@ -308,20 +541,17 @@ void iwl_trans_interrupts(struct iwl_trans *trans, bool enable)
|
||||
{
|
||||
iwl_trans_pci_interrupts(trans, enable);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_interrupts);
|
||||
|
||||
void iwl_trans_sync_nmi(struct iwl_trans *trans)
|
||||
{
|
||||
iwl_trans_pcie_sync_nmi(trans);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_sync_nmi);
|
||||
|
||||
int iwl_trans_write_imr_mem(struct iwl_trans *trans, u32 dst_addr,
|
||||
u64 src_addr, u32 byte_cnt)
|
||||
{
|
||||
return iwl_trans_pcie_copy_imr(trans, dst_addr, src_addr, byte_cnt);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_write_imr_mem);
|
||||
|
||||
void iwl_trans_set_bits_mask(struct iwl_trans *trans, u32 reg,
|
||||
u32 mask, u32 value)
|
||||
@@ -335,7 +565,6 @@ int iwl_trans_read_config32(struct iwl_trans *trans, u32 ofs,
|
||||
{
|
||||
return iwl_trans_pcie_read_config32(trans, ofs, val);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_read_config32);
|
||||
|
||||
bool _iwl_trans_grab_nic_access(struct iwl_trans *trans)
|
||||
{
|
||||
@@ -347,38 +576,42 @@ void __releases(nic_access)
|
||||
iwl_trans_release_nic_access(struct iwl_trans *trans)
|
||||
{
|
||||
iwl_trans_pcie_release_nic_access(trans);
|
||||
__release(nic_access);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_release_nic_access);
|
||||
|
||||
void iwl_trans_fw_alive(struct iwl_trans *trans, u32 scd_addr)
|
||||
void iwl_trans_fw_alive(struct iwl_trans *trans)
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
trans->state = IWL_TRANS_FW_ALIVE;
|
||||
|
||||
if (trans->trans_cfg->gen2)
|
||||
if (trans->mac_cfg->gen2)
|
||||
iwl_trans_pcie_gen2_fw_alive(trans);
|
||||
else
|
||||
iwl_trans_pcie_fw_alive(trans, scd_addr);
|
||||
iwl_trans_pcie_fw_alive(trans);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_fw_alive);
|
||||
|
||||
int iwl_trans_start_fw(struct iwl_trans *trans, const struct fw_img *fw,
|
||||
bool run_in_rfkill)
|
||||
int iwl_trans_start_fw(struct iwl_trans *trans, const struct iwl_fw *fw,
|
||||
enum iwl_ucode_type ucode_type, bool run_in_rfkill)
|
||||
{
|
||||
const struct fw_img *img;
|
||||
int ret;
|
||||
|
||||
might_sleep();
|
||||
|
||||
WARN_ON_ONCE(!trans->rx_mpdu_cmd);
|
||||
img = iwl_get_ucode_image(fw, ucode_type);
|
||||
if (!img)
|
||||
return -EINVAL;
|
||||
|
||||
clear_bit(STATUS_FW_ERROR, &trans->status);
|
||||
|
||||
if (trans->trans_cfg->gen2)
|
||||
ret = iwl_trans_pcie_gen2_start_fw(trans, fw, run_in_rfkill);
|
||||
if (trans->mac_cfg->gen2)
|
||||
ret = iwl_trans_pcie_gen2_start_fw(trans, fw, img,
|
||||
run_in_rfkill);
|
||||
else
|
||||
ret = iwl_trans_pcie_start_fw(trans, fw, run_in_rfkill);
|
||||
ret = iwl_trans_pcie_start_fw(trans, fw, img,
|
||||
run_in_rfkill);
|
||||
|
||||
if (ret == 0)
|
||||
trans->state = IWL_TRANS_FW_STARTED;
|
||||
@@ -391,7 +624,35 @@ void iwl_trans_stop_device(struct iwl_trans *trans)
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
if (trans->trans_cfg->gen2)
|
||||
/*
|
||||
* See also the comment in iwl_trans_restart_wk().
|
||||
*
|
||||
* When the opmode stops the device while a reset is pending, the
|
||||
* worker (iwl_trans_restart_wk) might not have run yet or, more
|
||||
* likely, will be blocked on the opmode lock. Due to the locking,
|
||||
* we can't just flush the worker.
|
||||
*
|
||||
* If this is the case, then the test_and_clear_bit() ensures that
|
||||
* the worker won't attempt to do anything after the stop.
|
||||
*
|
||||
* The trans->restart.mode is a handshake with the opmode, we set
|
||||
* the context there to ABORT so that when the worker can finally
|
||||
* acquire the lock in the opmode, the code there won't attempt to
|
||||
* do any dumps. Since we'd really like to have the dump though,
|
||||
* also do it inline here (with the opmode locks already held),
|
||||
* but use a separate mode struct to avoid races.
|
||||
*/
|
||||
if (test_and_clear_bit(STATUS_RESET_PENDING, &trans->status)) {
|
||||
struct iwl_fw_error_dump_mode mode;
|
||||
|
||||
mode = trans->restart.mode;
|
||||
mode.context = IWL_ERR_CONTEXT_FROM_OPMODE;
|
||||
trans->restart.mode.context = IWL_ERR_CONTEXT_ABORT;
|
||||
|
||||
iwl_op_mode_dump_error(trans->op_mode, &mode);
|
||||
}
|
||||
|
||||
if (trans->mac_cfg->gen2)
|
||||
iwl_trans_pcie_gen2_stop_device(trans);
|
||||
else
|
||||
iwl_trans_pcie_stop_device(trans);
|
||||
@@ -410,7 +671,7 @@ int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb,
|
||||
"bad state = %d\n", trans->state))
|
||||
return -EIO;
|
||||
|
||||
if (trans->trans_cfg->gen2)
|
||||
if (trans->mac_cfg->gen2)
|
||||
return iwl_txq_gen2_tx(trans, skb, dev_cmd, queue);
|
||||
|
||||
return iwl_trans_pcie_tx(trans, skb, dev_cmd, queue);
|
||||
@@ -420,6 +681,9 @@ IWL_EXPORT_SYMBOL(iwl_trans_tx);
|
||||
void iwl_trans_reclaim(struct iwl_trans *trans, int queue, int ssn,
|
||||
struct sk_buff_head *skbs, bool is_flush)
|
||||
{
|
||||
if (unlikely(test_bit(STATUS_FW_ERROR, &trans->status)))
|
||||
return;
|
||||
|
||||
if (WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE,
|
||||
"bad state = %d\n", trans->state))
|
||||
return;
|
||||
@@ -452,6 +716,9 @@ IWL_EXPORT_SYMBOL(iwl_trans_txq_enable_cfg);
|
||||
|
||||
int iwl_trans_wait_txq_empty(struct iwl_trans *trans, int queue)
|
||||
{
|
||||
if (unlikely(test_bit(STATUS_FW_ERROR, &trans->status)))
|
||||
return -EIO;
|
||||
|
||||
if (WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE,
|
||||
"bad state = %d\n", trans->state))
|
||||
return -EIO;
|
||||
@@ -493,7 +760,6 @@ void iwl_trans_debugfs_cleanup(struct iwl_trans *trans)
|
||||
{
|
||||
iwl_trans_pcie_debugfs_cleanup(trans);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_debugfs_cleanup);
|
||||
#endif
|
||||
|
||||
void iwl_trans_set_q_ptrs(struct iwl_trans *trans, int queue, int ptr)
|
||||
@@ -531,35 +797,31 @@ int iwl_trans_get_rxq_dma_data(struct iwl_trans *trans, int queue,
|
||||
{
|
||||
return iwl_trans_pcie_rxq_dma_data(trans, queue, data);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_get_rxq_dma_data);
|
||||
|
||||
int iwl_trans_load_pnvm(struct iwl_trans *trans,
|
||||
const struct iwl_pnvm_image *pnvm_data,
|
||||
const struct iwl_ucode_capabilities *capa)
|
||||
{
|
||||
return iwl_trans_pcie_ctx_info_gen3_load_pnvm(trans, pnvm_data, capa);
|
||||
return iwl_trans_pcie_ctx_info_v2_load_pnvm(trans, pnvm_data, capa);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_load_pnvm);
|
||||
|
||||
void iwl_trans_set_pnvm(struct iwl_trans *trans,
|
||||
const struct iwl_ucode_capabilities *capa)
|
||||
{
|
||||
iwl_trans_pcie_ctx_info_gen3_set_pnvm(trans, capa);
|
||||
iwl_trans_pcie_ctx_info_v2_set_pnvm(trans, capa);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_set_pnvm);
|
||||
|
||||
int iwl_trans_load_reduce_power(struct iwl_trans *trans,
|
||||
const struct iwl_pnvm_image *payloads,
|
||||
const struct iwl_ucode_capabilities *capa)
|
||||
{
|
||||
return iwl_trans_pcie_ctx_info_gen3_load_reduce_power(trans, payloads,
|
||||
return iwl_trans_pcie_ctx_info_v2_load_reduce_power(trans, payloads,
|
||||
capa);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_load_reduce_power);
|
||||
|
||||
void iwl_trans_set_reduce_power(struct iwl_trans *trans,
|
||||
const struct iwl_ucode_capabilities *capa)
|
||||
{
|
||||
iwl_trans_pcie_ctx_info_gen3_set_reduce_power(trans, capa);
|
||||
iwl_trans_pcie_ctx_info_v2_set_reduce_power(trans, capa);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_set_reduce_power);
|
||||
|
||||
+242
-142
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2005-2014, 2018-2023 Intel Corporation
|
||||
* Copyright (C) 2005-2014, 2018-2025 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
@@ -113,16 +113,12 @@ static inline u32 iwl_rx_packet_payload_len(const struct iwl_rx_packet *pkt)
|
||||
* the response. The caller needs to call iwl_free_resp when done.
|
||||
* @CMD_SEND_IN_RFKILL: Send the command even if the NIC is in RF-kill.
|
||||
* @CMD_BLOCK_TXQS: Block TXQs while the comment is executing.
|
||||
* @CMD_SEND_IN_D3: Allow the command to be sent in D3 mode, relevant to
|
||||
* SUSPEND and RESUME commands. We are in D3 mode when we set
|
||||
* trans->system_pm_mode to IWL_PLAT_PM_MODE_D3.
|
||||
*/
|
||||
enum CMD_MODE {
|
||||
CMD_ASYNC = BIT(0),
|
||||
CMD_WANT_SKB = BIT(1),
|
||||
CMD_SEND_IN_RFKILL = BIT(2),
|
||||
CMD_BLOCK_TXQS = BIT(3),
|
||||
CMD_SEND_IN_D3 = BIT(4),
|
||||
};
|
||||
#define CMD_MODE_BITS 5
|
||||
|
||||
@@ -313,6 +309,14 @@ enum iwl_d3_status {
|
||||
* @STATUS_TRANS_DEAD: trans is dead - avoid any read/write operation
|
||||
* @STATUS_SUPPRESS_CMD_ERROR_ONCE: suppress "FW error in SYNC CMD" once,
|
||||
* e.g. for testing
|
||||
* @STATUS_IN_SW_RESET: device is undergoing reset, cleared by opmode
|
||||
* via iwl_trans_finish_sw_reset()
|
||||
* @STATUS_RESET_PENDING: reset worker was scheduled, but didn't dump
|
||||
* the firmware state yet
|
||||
* @STATUS_TRANS_RESET_IN_PROGRESS: reset is still in progress, don't
|
||||
* attempt another reset yet
|
||||
* @STATUS_SUSPENDED: device is suspended, don't send commands that
|
||||
* aren't marked accordingly
|
||||
*/
|
||||
enum iwl_trans_status {
|
||||
STATUS_SYNC_HCMD_ACTIVE,
|
||||
@@ -324,6 +328,10 @@ enum iwl_trans_status {
|
||||
STATUS_FW_ERROR,
|
||||
STATUS_TRANS_DEAD,
|
||||
STATUS_SUPPRESS_CMD_ERROR_ONCE,
|
||||
STATUS_IN_SW_RESET,
|
||||
STATUS_RESET_PENDING,
|
||||
STATUS_TRANS_RESET_IN_PROGRESS,
|
||||
STATUS_SUSPENDED,
|
||||
};
|
||||
|
||||
static inline int
|
||||
@@ -395,11 +403,11 @@ struct iwl_dump_sanitize_ops {
|
||||
/**
|
||||
* struct iwl_trans_config - transport configuration
|
||||
*
|
||||
* @op_mode: pointer to the upper layer.
|
||||
* These values should be set before iwl_trans_op_mode_enter().
|
||||
*
|
||||
* @cmd_queue: the index of the command queue.
|
||||
* Must be set before start_fw.
|
||||
* @cmd_fifo: the fifo for host commands
|
||||
* @cmd_q_wdg_timeout: the timeout of the watchdog timer for the command queue.
|
||||
* @no_reclaim_cmds: Some devices erroneously don't set the
|
||||
* SEQ_RX_FRAME bit on some notifications, this is the
|
||||
* list of such notifications to filter. Max length is
|
||||
@@ -407,8 +415,6 @@ struct iwl_dump_sanitize_ops {
|
||||
* @n_no_reclaim_cmds: # of commands in list
|
||||
* @rx_buf_size: RX buffer size needed for A-MSDUs
|
||||
* if unset 4k will be the RX buffer size
|
||||
* @bc_table_dword: set to true if the BC table expects the byte count to be
|
||||
* in DWORD (as opposed to bytes)
|
||||
* @scd_set_active: should the transport configure the SCD for HCMD queue
|
||||
* @command_groups: array of command groups, each member is an array of the
|
||||
* commands in the group; for debugging only
|
||||
@@ -419,18 +425,24 @@ struct iwl_dump_sanitize_ops {
|
||||
* @queue_alloc_cmd_ver: queue allocation command version, set to 0
|
||||
* for using the older SCD_QUEUE_CFG, set to the version of
|
||||
* SCD_QUEUE_CONFIG_CMD otherwise.
|
||||
* @wide_cmd_header: true when ucode supports wide command header format
|
||||
* @rx_mpdu_cmd: MPDU RX command ID, must be assigned by opmode before
|
||||
* starting the firmware, used for tracing
|
||||
* @rx_mpdu_cmd_hdr_size: used for tracing, amount of data before the
|
||||
* start of the 802.11 header in the @rx_mpdu_cmd
|
||||
* @dsbr_urm_fw_dependent: switch to URM based on fw settings
|
||||
* @dsbr_urm_permanent: switch to URM permanently
|
||||
* @mbx_addr_0_step: step address data 0
|
||||
* @mbx_addr_1_step: step address data 1
|
||||
* @ext_32khz_clock_valid: if true, the external 32 KHz clock can be used
|
||||
*/
|
||||
struct iwl_trans_config {
|
||||
struct iwl_op_mode *op_mode;
|
||||
|
||||
u8 cmd_queue;
|
||||
u8 cmd_fifo;
|
||||
unsigned int cmd_q_wdg_timeout;
|
||||
const u8 *no_reclaim_cmds;
|
||||
unsigned int n_no_reclaim_cmds;
|
||||
u8 n_no_reclaim_cmds;
|
||||
u8 no_reclaim_cmds[MAX_NO_RECLAIM_CMDS];
|
||||
|
||||
enum iwl_amsdu_size rx_buf_size;
|
||||
bool bc_table_dword;
|
||||
bool scd_set_active;
|
||||
const struct iwl_hcmd_arr *command_groups;
|
||||
int command_groups_size;
|
||||
@@ -438,6 +450,16 @@ struct iwl_trans_config {
|
||||
u8 cb_data_offs;
|
||||
bool fw_reset_handshake;
|
||||
u8 queue_alloc_cmd_ver;
|
||||
|
||||
bool wide_cmd_header;
|
||||
u8 rx_mpdu_cmd, rx_mpdu_cmd_hdr_size;
|
||||
|
||||
u8 dsbr_urm_fw_dependent:1,
|
||||
dsbr_urm_permanent:1,
|
||||
ext_32khz_clock_valid:1;
|
||||
|
||||
u32 mbx_addr_0_step;
|
||||
u32 mbx_addr_1_step;
|
||||
};
|
||||
|
||||
struct iwl_trans_dump_data {
|
||||
@@ -522,23 +544,6 @@ enum iwl_trans_state {
|
||||
* be confused with the physical device power state.
|
||||
*/
|
||||
|
||||
/**
|
||||
* enum iwl_plat_pm_mode - platform power management mode
|
||||
*
|
||||
* This enumeration describes the device's platform power management
|
||||
* behavior when in system-wide suspend (i.e WoWLAN).
|
||||
*
|
||||
* @IWL_PLAT_PM_MODE_DISABLED: power management is disabled for this
|
||||
* device. In system-wide suspend mode, it means that the all
|
||||
* connections will be closed automatically by mac80211 before
|
||||
* the platform is suspended.
|
||||
* @IWL_PLAT_PM_MODE_D3: the device goes into D3 mode (i.e. WoWLAN).
|
||||
*/
|
||||
enum iwl_plat_pm_mode {
|
||||
IWL_PLAT_PM_MODE_DISABLED,
|
||||
IWL_PLAT_PM_MODE_D3,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum iwl_ini_cfg_state
|
||||
* @IWL_INI_CFG_STATE_NOT_LOADED: no debug cfg was given
|
||||
@@ -643,8 +648,6 @@ struct iwl_pc_data {
|
||||
* @n_dest_reg: num of reg_ops in %dbg_dest_tlv
|
||||
* @rec_on: true iff there is a fw debug recording currently active
|
||||
* @dest_tlv: points to the destination TLV for debug
|
||||
* @conf_tlv: array of pointers to configuration TLVs for debug
|
||||
* @trigger_tlv: array of pointers to triggers TLVs for debug
|
||||
* @lmac_error_event_table: addrs of lmacs error tables
|
||||
* @umac_error_event_table: addr of umac error table
|
||||
* @tcm_error_event_table: address(es) of TCM error table(s)
|
||||
@@ -679,8 +682,6 @@ struct iwl_trans_debug {
|
||||
bool rec_on;
|
||||
|
||||
const struct iwl_fw_dbg_dest_tlv_v1 *dest_tlv;
|
||||
const struct iwl_fw_dbg_conf_tlv *conf_tlv[FW_DBG_CONF_MAX];
|
||||
struct iwl_fw_dbg_trigger_tlv * const *trigger_tlv;
|
||||
|
||||
u32 lmac_error_event_table[2];
|
||||
u32 umac_error_event_table;
|
||||
@@ -833,77 +834,25 @@ struct iwl_txq {
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_trans - transport common data
|
||||
*
|
||||
* @csme_own: true if we couldn't get ownership on the device
|
||||
* @op_mode: pointer to the op_mode
|
||||
* @trans_cfg: the trans-specific configuration part
|
||||
* @cfg: pointer to the configuration
|
||||
* @drv: pointer to iwl_drv
|
||||
* @state: current device state
|
||||
* @status: a bit-mask of transport status flags
|
||||
* @dev: pointer to struct device * that represents the device
|
||||
* struct iwl_trans_info - transport info for outside use
|
||||
* @name: the device name
|
||||
* @max_skb_frags: maximum number of fragments an SKB can have when transmitted.
|
||||
* 0 indicates that frag SKBs (NETIF_F_SG) aren't supported.
|
||||
* @hw_rf_id: a u32 with the device RF ID
|
||||
* @hw_cnv_id: a u32 with the device CNV ID
|
||||
* @hw_crf_id: a u32 with the device CRF ID
|
||||
* @hw_wfpm_id: a u32 with the device wfpm ID
|
||||
* @hw_id: a u32 with the ID of the device / sub-device.
|
||||
* Set during transport allocation.
|
||||
* @hw_id_str: a string with info about HW ID. Set during transport allocation.
|
||||
* @sku_id: the SKU identifier (for PNVM matching)
|
||||
* @pnvm_loaded: indicates PNVM was loaded
|
||||
* @hw_rev: the revision data of the HW
|
||||
* @hw_rev_step: The mac step of the HW
|
||||
* @pm_support: set to true in start_hw if link pm is supported
|
||||
* @ltr_enabled: set to true if the LTR is enabled
|
||||
* @fail_to_parse_pnvm_image: set to true if pnvm parsing failed
|
||||
* @reduce_power_loaded: indicates reduced power section was loaded
|
||||
* @failed_to_load_reduce_power_image: set to true if pnvm loading failed
|
||||
* @command_groups: pointer to command group name list array
|
||||
* @command_groups_size: array size of @command_groups
|
||||
* @wide_cmd_header: true when ucode supports wide command header format
|
||||
* @wait_command_queue: wait queue for sync commands
|
||||
* @num_rx_queues: number of RX queues allocated by the transport;
|
||||
* the transport must set this before calling iwl_drv_start()
|
||||
* @iml_len: the length of the image loader
|
||||
* @iml: a pointer to the image loader itself
|
||||
* @dev_cmd_pool: pool for Tx cmd allocation - for internal use only.
|
||||
* The user should use iwl_trans_{alloc,free}_tx_cmd.
|
||||
* @dev_cmd_pool_name: name for the TX command allocation pool
|
||||
* @dbgfs_dir: iwlwifi debugfs base dir for this device
|
||||
* @sync_cmd_lockdep_map: lockdep map for checking sync commands
|
||||
* @rx_mpdu_cmd: MPDU RX command ID, must be assigned by opmode before
|
||||
* starting the firmware, used for tracing
|
||||
* @rx_mpdu_cmd_hdr_size: used for tracing, amount of data before the
|
||||
* start of the 802.11 header in the @rx_mpdu_cmd
|
||||
* @dbg: additional debug data, see &struct iwl_trans_debug
|
||||
* @init_dram: FW initialization DMA data
|
||||
* @system_pm_mode: the system-wide power management mode in use.
|
||||
* This mode is set dynamically, depending on the WoWLAN values
|
||||
* configured from the userspace at runtime.
|
||||
* @name: the device name
|
||||
* @mbx_addr_0_step: step address data 0
|
||||
* @mbx_addr_1_step: step address data 1
|
||||
* @hw_rf_id: the device RF ID
|
||||
* @hw_cnv_id: the device CNV ID
|
||||
* @hw_crf_id: the device CRF ID
|
||||
* @hw_wfpm_id: the device wfpm ID
|
||||
* @hw_id: the ID of the device / sub-device
|
||||
* Bits 0:15 represent the sub-device ID
|
||||
* Bits 16:31 represent the device ID.
|
||||
* @pcie_link_speed: current PCIe link speed (%PCI_EXP_LNKSTA_CLS_*),
|
||||
* only valid for discrete (not integrated) NICs
|
||||
* @invalid_tx_cmd: invalid TX command buffer
|
||||
* @reduced_cap_sku: reduced capability supported SKU
|
||||
* @no_160: device not supporting 160 MHz
|
||||
* @step_urm: STEP is in URM, no support for MCS>9 in 320 MHz
|
||||
* @trans_specific: data for the specific transport this is allocated for/with
|
||||
* @num_rxqs: number of RX queues allocated by the transport
|
||||
*/
|
||||
struct iwl_trans {
|
||||
bool csme_own;
|
||||
struct iwl_op_mode *op_mode;
|
||||
const struct iwl_cfg_trans_params *trans_cfg;
|
||||
const struct iwl_cfg *cfg;
|
||||
struct iwl_drv *drv;
|
||||
enum iwl_trans_state state;
|
||||
unsigned long status;
|
||||
|
||||
struct device *dev;
|
||||
struct iwl_trans_info {
|
||||
const char *name;
|
||||
u32 max_skb_frags;
|
||||
u32 hw_rev;
|
||||
u32 hw_rev_step;
|
||||
@@ -912,12 +861,63 @@ struct iwl_trans {
|
||||
u32 hw_cnv_id;
|
||||
u32 hw_wfpm_id;
|
||||
u32 hw_id;
|
||||
char hw_id_str[52];
|
||||
u32 sku_id[3];
|
||||
bool reduced_cap_sku;
|
||||
u8 no_160:1, step_urm:1;
|
||||
u8 pcie_link_speed;
|
||||
u8 num_rxqs;
|
||||
};
|
||||
|
||||
u8 rx_mpdu_cmd, rx_mpdu_cmd_hdr_size;
|
||||
/**
|
||||
* struct iwl_trans - transport common data
|
||||
*
|
||||
* @csme_own: true if we couldn't get ownership on the device
|
||||
* @op_mode: pointer to the op_mode
|
||||
* @mac_cfg: the trans-specific configuration part
|
||||
* @cfg: pointer to the configuration
|
||||
* @drv: pointer to iwl_drv
|
||||
* @conf: configuration set by the opmode before enter
|
||||
* @state: current device state
|
||||
* @status: a bit-mask of transport status flags
|
||||
* @dev: pointer to struct device * that represents the device
|
||||
* @info: device information for use by other layers
|
||||
* @pnvm_loaded: indicates PNVM was loaded
|
||||
* @pm_support: set to true in start_hw if link pm is supported
|
||||
* @ltr_enabled: set to true if the LTR is enabled
|
||||
* @fail_to_parse_pnvm_image: set to true if pnvm parsing failed
|
||||
* @reduce_power_loaded: indicates reduced power section was loaded
|
||||
* @failed_to_load_reduce_power_image: set to true if pnvm loading failed
|
||||
* @dev_cmd_pool: pool for Tx cmd allocation - for internal use only.
|
||||
* The user should use iwl_trans_{alloc,free}_tx_cmd.
|
||||
* @dev_cmd_pool_name: name for the TX command allocation pool
|
||||
* @dbgfs_dir: iwlwifi debugfs base dir for this device
|
||||
* @sync_cmd_lockdep_map: lockdep map for checking sync commands
|
||||
* @dbg: additional debug data, see &struct iwl_trans_debug
|
||||
* @init_dram: FW initialization DMA data
|
||||
* @reduced_cap_sku: reduced capability supported SKU
|
||||
* @step_urm: STEP is in URM, no support for MCS>9 in 320 MHz
|
||||
* @restart: restart worker data
|
||||
* @restart.wk: restart worker
|
||||
* @restart.mode: reset/restart error mode information
|
||||
* @restart.during_reset: error occurred during previous software reset
|
||||
* @trans_specific: data for the specific transport this is allocated for/with
|
||||
* @request_top_reset: TOP reset was requested, used by the reset
|
||||
* worker that should be scheduled (with appropriate reason)
|
||||
* @do_top_reset: indication to the (PCIe) transport/context-info
|
||||
* to do the TOP reset
|
||||
*/
|
||||
struct iwl_trans {
|
||||
bool csme_own;
|
||||
struct iwl_op_mode *op_mode;
|
||||
const struct iwl_mac_cfg *mac_cfg;
|
||||
const struct iwl_rf_cfg *cfg;
|
||||
struct iwl_drv *drv;
|
||||
struct iwl_trans_config conf;
|
||||
enum iwl_trans_state state;
|
||||
unsigned long status;
|
||||
|
||||
struct device *dev;
|
||||
|
||||
const struct iwl_trans_info info;
|
||||
bool reduced_cap_sku;
|
||||
bool step_urm;
|
||||
|
||||
bool pm_support;
|
||||
bool ltr_enabled;
|
||||
@@ -926,16 +926,6 @@ struct iwl_trans {
|
||||
u8 reduce_power_loaded:1;
|
||||
u8 failed_to_load_reduce_power_image:1;
|
||||
|
||||
const struct iwl_hcmd_arr *command_groups;
|
||||
int command_groups_size;
|
||||
bool wide_cmd_header;
|
||||
|
||||
wait_queue_head_t wait_command_queue;
|
||||
u8 num_rx_queues;
|
||||
|
||||
size_t iml_len;
|
||||
u8 *iml;
|
||||
|
||||
/* The following fields are internal only */
|
||||
struct kmem_cache *dev_cmd_pool;
|
||||
char dev_cmd_pool_name[50];
|
||||
@@ -949,15 +939,14 @@ struct iwl_trans {
|
||||
struct iwl_trans_debug dbg;
|
||||
struct iwl_self_init_dram init_dram;
|
||||
|
||||
enum iwl_plat_pm_mode system_pm_mode;
|
||||
struct {
|
||||
struct delayed_work wk;
|
||||
struct iwl_fw_error_dump_mode mode;
|
||||
bool during_reset;
|
||||
} restart;
|
||||
|
||||
const char *name;
|
||||
u32 mbx_addr_0_step;
|
||||
u32 mbx_addr_1_step;
|
||||
|
||||
u8 pcie_link_speed;
|
||||
|
||||
struct iwl_dma_ptr invalid_tx_cmd;
|
||||
u8 request_top_reset:1,
|
||||
do_top_reset:1;
|
||||
|
||||
/* pointer to trans specific struct */
|
||||
/*Ensure that this pointer will always be aligned to sizeof pointer */
|
||||
@@ -965,19 +954,18 @@ struct iwl_trans {
|
||||
};
|
||||
|
||||
const char *iwl_get_cmd_string(struct iwl_trans *trans, u32 id);
|
||||
int iwl_cmd_groups_verify_sorted(const struct iwl_trans_config *trans);
|
||||
|
||||
void iwl_trans_configure(struct iwl_trans *trans,
|
||||
const struct iwl_trans_config *trans_cfg);
|
||||
void iwl_trans_op_mode_enter(struct iwl_trans *trans,
|
||||
struct iwl_op_mode *op_mode);
|
||||
|
||||
int iwl_trans_start_hw(struct iwl_trans *trans);
|
||||
|
||||
void iwl_trans_op_mode_leave(struct iwl_trans *trans);
|
||||
|
||||
void iwl_trans_fw_alive(struct iwl_trans *trans, u32 scd_addr);
|
||||
void iwl_trans_fw_alive(struct iwl_trans *trans);
|
||||
|
||||
int iwl_trans_start_fw(struct iwl_trans *trans, const struct fw_img *fw,
|
||||
bool run_in_rfkill);
|
||||
int iwl_trans_start_fw(struct iwl_trans *trans, const struct iwl_fw *fw,
|
||||
enum iwl_ucode_type ucode_type, bool run_in_rfkill);
|
||||
|
||||
void iwl_trans_stop_device(struct iwl_trans *trans);
|
||||
|
||||
@@ -1089,12 +1077,13 @@ int iwl_trans_read_config32(struct iwl_trans *trans, u32 ofs,
|
||||
void iwl_trans_debugfs_cleanup(struct iwl_trans *trans);
|
||||
#endif
|
||||
|
||||
#define iwl_trans_read_mem_bytes(trans, addr, buf, bufsize) \
|
||||
do { \
|
||||
if (__builtin_constant_p(bufsize)) \
|
||||
BUILD_BUG_ON((bufsize) % sizeof(u32)); \
|
||||
iwl_trans_read_mem(trans, addr, buf, (bufsize) / sizeof(u32));\
|
||||
} while (0)
|
||||
#define iwl_trans_read_mem_bytes(trans, addr, buf, bufsize) \
|
||||
({ \
|
||||
if (__builtin_constant_p(bufsize)) \
|
||||
BUILD_BUG_ON((bufsize) % sizeof(u32)); \
|
||||
iwl_trans_read_mem(trans, addr, buf, \
|
||||
(bufsize) / sizeof(u32)); \
|
||||
})
|
||||
|
||||
int iwl_trans_write_imr_mem(struct iwl_trans *trans, u32 dst_addr,
|
||||
u64 src_addr, u32 byte_cnt);
|
||||
@@ -1120,7 +1109,7 @@ static inline u32 iwl_trans_write_mem32(struct iwl_trans *trans, u32 addr,
|
||||
|
||||
void iwl_trans_set_pmi(struct iwl_trans *trans, bool state);
|
||||
|
||||
int iwl_trans_sw_reset(struct iwl_trans *trans, bool retake_ownership);
|
||||
int iwl_trans_sw_reset(struct iwl_trans *trans);
|
||||
|
||||
void iwl_trans_set_bits_mask(struct iwl_trans *trans, u32 reg,
|
||||
u32 mask, u32 value);
|
||||
@@ -1134,7 +1123,31 @@ bool _iwl_trans_grab_nic_access(struct iwl_trans *trans);
|
||||
void __releases(nic_access)
|
||||
iwl_trans_release_nic_access(struct iwl_trans *trans);
|
||||
|
||||
static inline void iwl_trans_fw_error(struct iwl_trans *trans, bool sync)
|
||||
static inline void iwl_trans_schedule_reset(struct iwl_trans *trans,
|
||||
enum iwl_fw_error_type type)
|
||||
{
|
||||
if (test_bit(STATUS_TRANS_DEAD, &trans->status))
|
||||
return;
|
||||
/* clear this on device init, not cleared on any unbind/reprobe */
|
||||
if (test_and_set_bit(STATUS_TRANS_RESET_IN_PROGRESS, &trans->status))
|
||||
return;
|
||||
|
||||
trans->restart.mode.type = type;
|
||||
trans->restart.mode.context = IWL_ERR_CONTEXT_WORKER;
|
||||
|
||||
set_bit(STATUS_RESET_PENDING, &trans->status);
|
||||
|
||||
/*
|
||||
* keep track of whether or not this happened while resetting,
|
||||
* by the timer the worker runs it might have finished
|
||||
*/
|
||||
trans->restart.during_reset = test_bit(STATUS_IN_SW_RESET,
|
||||
&trans->status);
|
||||
queue_delayed_work(system_unbound_wq, &trans->restart.wk, 0);
|
||||
}
|
||||
|
||||
static inline void iwl_trans_fw_error(struct iwl_trans *trans,
|
||||
enum iwl_fw_error_type type)
|
||||
{
|
||||
if (WARN_ON_ONCE(!trans->op_mode))
|
||||
return;
|
||||
@@ -1142,10 +1155,27 @@ static inline void iwl_trans_fw_error(struct iwl_trans *trans, bool sync)
|
||||
/* prevent double restarts due to the same erroneous FW */
|
||||
if (!test_and_set_bit(STATUS_FW_ERROR, &trans->status)) {
|
||||
trans->state = IWL_TRANS_NO_FW;
|
||||
iwl_op_mode_nic_error(trans->op_mode, sync);
|
||||
iwl_op_mode_nic_error(trans->op_mode, type);
|
||||
iwl_trans_schedule_reset(trans, type);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void iwl_trans_opmode_sw_reset(struct iwl_trans *trans,
|
||||
enum iwl_fw_error_type type)
|
||||
{
|
||||
if (WARN_ON_ONCE(!trans->op_mode))
|
||||
return;
|
||||
|
||||
set_bit(STATUS_IN_SW_RESET, &trans->status);
|
||||
|
||||
if (WARN_ON(type == IWL_ERR_TYPE_TOP_RESET_BY_BT))
|
||||
return;
|
||||
|
||||
if (!trans->op_mode->ops->sw_reset ||
|
||||
!trans->op_mode->ops->sw_reset(trans->op_mode, type))
|
||||
clear_bit(STATUS_IN_SW_RESET, &trans->status);
|
||||
}
|
||||
|
||||
static inline bool iwl_trans_fw_running(struct iwl_trans *trans)
|
||||
{
|
||||
return trans->state == IWL_TRANS_FW_ALIVE;
|
||||
@@ -1178,13 +1208,19 @@ static inline bool iwl_trans_dbg_ini_valid(struct iwl_trans *trans)
|
||||
|
||||
void iwl_trans_interrupts(struct iwl_trans *trans, bool enable);
|
||||
|
||||
static inline void iwl_trans_finish_sw_reset(struct iwl_trans *trans)
|
||||
{
|
||||
clear_bit(STATUS_IN_SW_RESET, &trans->status);
|
||||
}
|
||||
|
||||
/*****************************************************
|
||||
* transport helper functions
|
||||
*****************************************************/
|
||||
struct iwl_trans *iwl_trans_alloc(unsigned int priv_size,
|
||||
struct device *dev,
|
||||
const struct iwl_cfg_trans_params *cfg_trans);
|
||||
int iwl_trans_init(struct iwl_trans *trans);
|
||||
struct device *dev,
|
||||
const struct iwl_mac_cfg *mac_cfg,
|
||||
unsigned int txcmd_size,
|
||||
unsigned int txcmd_align);
|
||||
void iwl_trans_free(struct iwl_trans *trans);
|
||||
|
||||
static inline bool iwl_trans_is_hw_error_value(u32 val)
|
||||
@@ -1192,14 +1228,78 @@ static inline bool iwl_trans_is_hw_error_value(u32 val)
|
||||
return ((val & ~0xf) == 0xa5a5a5a0) || ((val & ~0xf) == 0x5a5a5a50);
|
||||
}
|
||||
|
||||
void iwl_trans_free_restart_list(void);
|
||||
|
||||
static inline u16 iwl_trans_get_num_rbds(struct iwl_trans *trans)
|
||||
{
|
||||
u16 result = trans->cfg->num_rbds;
|
||||
|
||||
/*
|
||||
* Since AX210 family (So/Ty) the device cannot put mutliple
|
||||
* frames into the same buffer, so double the value for them.
|
||||
*/
|
||||
if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
|
||||
return 2 * result;
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline void iwl_trans_suppress_cmd_error_once(struct iwl_trans *trans)
|
||||
{
|
||||
set_bit(STATUS_SUPPRESS_CMD_ERROR_ONCE, &trans->status);
|
||||
}
|
||||
|
||||
static inline bool iwl_trans_device_enabled(struct iwl_trans *trans)
|
||||
{
|
||||
return test_bit(STATUS_DEVICE_ENABLED, &trans->status);
|
||||
}
|
||||
|
||||
static inline bool iwl_trans_is_dead(struct iwl_trans *trans)
|
||||
{
|
||||
return test_bit(STATUS_TRANS_DEAD, &trans->status);
|
||||
}
|
||||
|
||||
/*****************************************************
|
||||
* PCIe handling
|
||||
*****************************************************/
|
||||
int __must_check iwl_pci_register_driver(void);
|
||||
void iwl_pci_unregister_driver(void);
|
||||
void iwl_trans_pcie_remove(struct iwl_trans *trans, bool rescan);
|
||||
|
||||
/* Note: order matters */
|
||||
enum iwl_reset_mode {
|
||||
/* upper level modes: */
|
||||
IWL_RESET_MODE_SW_RESET,
|
||||
IWL_RESET_MODE_REPROBE,
|
||||
/* TOP reset doesn't require PCIe remove */
|
||||
IWL_RESET_MODE_TOP_RESET,
|
||||
/* PCIE level modes: */
|
||||
IWL_RESET_MODE_REMOVE_ONLY,
|
||||
IWL_RESET_MODE_RESCAN,
|
||||
IWL_RESET_MODE_FUNC_RESET,
|
||||
IWL_RESET_MODE_PROD_RESET,
|
||||
|
||||
/* keep last - special backoff value */
|
||||
IWL_RESET_MODE_BACKOFF,
|
||||
};
|
||||
|
||||
void iwl_trans_pcie_reset(struct iwl_trans *trans, enum iwl_reset_mode mode);
|
||||
void iwl_trans_pcie_fw_reset_handshake(struct iwl_trans *trans);
|
||||
|
||||
int iwl_trans_pcie_send_hcmd(struct iwl_trans *trans,
|
||||
struct iwl_host_cmd *cmd);
|
||||
|
||||
/* Internal helper */
|
||||
static inline void iwl_trans_set_info(struct iwl_trans *trans,
|
||||
struct iwl_trans_info *info)
|
||||
{
|
||||
struct iwl_trans_info *write;
|
||||
|
||||
write = (void *)(uintptr_t)&trans->info;
|
||||
*write = *info;
|
||||
}
|
||||
|
||||
static inline u16 iwl_trans_get_device_id(struct iwl_trans *trans)
|
||||
{
|
||||
return u32_get_bits(trans->info.hw_id, GENMASK(31, 16));
|
||||
}
|
||||
|
||||
#endif /* __iwl_trans_h__ */
|
||||
|
||||
@@ -0,0 +1,195 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2024-2025 Intel Corporation
|
||||
*/
|
||||
#include <net/gso.h>
|
||||
#include <linux/ieee80211.h>
|
||||
#include <net/ip.h>
|
||||
|
||||
#include "iwl-drv.h"
|
||||
#include "iwl-utils.h"
|
||||
|
||||
#ifdef CONFIG_INET
|
||||
int iwl_tx_tso_segment(struct sk_buff *skb, unsigned int num_subframes,
|
||||
netdev_features_t netdev_flags,
|
||||
struct sk_buff_head *mpdus_skbs)
|
||||
{
|
||||
struct sk_buff *tmp, *next;
|
||||
struct ieee80211_hdr *hdr = (void *)skb->data;
|
||||
char cb[sizeof(skb->cb)];
|
||||
u16 i = 0;
|
||||
unsigned int tcp_payload_len;
|
||||
unsigned int mss = skb_shinfo(skb)->gso_size;
|
||||
bool ipv4 = (skb->protocol == htons(ETH_P_IP));
|
||||
bool qos = ieee80211_is_data_qos(hdr->frame_control);
|
||||
u16 ip_base_id = ipv4 ? ntohs(ip_hdr(skb)->id) : 0;
|
||||
|
||||
skb_shinfo(skb)->gso_size = num_subframes * mss;
|
||||
memcpy(cb, skb->cb, sizeof(cb));
|
||||
|
||||
next = skb_gso_segment(skb, netdev_flags);
|
||||
skb_shinfo(skb)->gso_size = mss;
|
||||
skb_shinfo(skb)->gso_type = ipv4 ? SKB_GSO_TCPV4 : SKB_GSO_TCPV6;
|
||||
|
||||
if (IS_ERR(next) && PTR_ERR(next) == -ENOMEM)
|
||||
return -ENOMEM;
|
||||
|
||||
if (WARN_ONCE(IS_ERR(next),
|
||||
"skb_gso_segment error: %d\n", (int)PTR_ERR(next)))
|
||||
return PTR_ERR(next);
|
||||
|
||||
if (next)
|
||||
consume_skb(skb);
|
||||
|
||||
skb_list_walk_safe(next, tmp, next) {
|
||||
memcpy(tmp->cb, cb, sizeof(tmp->cb));
|
||||
/*
|
||||
* Compute the length of all the data added for the A-MSDU.
|
||||
* This will be used to compute the length to write in the TX
|
||||
* command. We have: SNAP + IP + TCP for n -1 subframes and
|
||||
* ETH header for n subframes.
|
||||
*/
|
||||
tcp_payload_len = skb_tail_pointer(tmp) -
|
||||
skb_transport_header(tmp) -
|
||||
tcp_hdrlen(tmp) + tmp->data_len;
|
||||
|
||||
if (ipv4)
|
||||
ip_hdr(tmp)->id = htons(ip_base_id + i * num_subframes);
|
||||
|
||||
if (tcp_payload_len > mss) {
|
||||
skb_shinfo(tmp)->gso_size = mss;
|
||||
skb_shinfo(tmp)->gso_type = ipv4 ? SKB_GSO_TCPV4 :
|
||||
SKB_GSO_TCPV6;
|
||||
} else {
|
||||
if (qos) {
|
||||
u8 *qc;
|
||||
|
||||
if (ipv4)
|
||||
ip_send_check(ip_hdr(tmp));
|
||||
|
||||
qc = ieee80211_get_qos_ctl((void *)tmp->data);
|
||||
*qc &= ~IEEE80211_QOS_CTL_A_MSDU_PRESENT;
|
||||
}
|
||||
skb_shinfo(tmp)->gso_size = 0;
|
||||
}
|
||||
|
||||
skb_mark_not_on_list(tmp);
|
||||
__skb_queue_tail(mpdus_skbs, tmp);
|
||||
i++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_tx_tso_segment);
|
||||
#endif /* CONFIG_INET */
|
||||
|
||||
static u32 iwl_div_by_db(u32 value, u8 db)
|
||||
{
|
||||
/*
|
||||
* 2^32 * 10**(i / 10) for i = [1, 10], skipping 0 and simply stopping
|
||||
* at 10 dB and looping instead of using a much larger table.
|
||||
*
|
||||
* Using 64 bit math is overkill, but means the helper does not require
|
||||
* a limit on the input range.
|
||||
*/
|
||||
static const u32 db_to_val[] = {
|
||||
0xcb59185e, 0xa1866ba8, 0x804dce7a, 0x65ea59fe, 0x50f44d89,
|
||||
0x404de61f, 0x331426af, 0x2892c18b, 0x203a7e5b, 0x1999999a,
|
||||
};
|
||||
|
||||
while (value && db > 0) {
|
||||
u8 change = min_t(u8, db, ARRAY_SIZE(db_to_val));
|
||||
|
||||
value = (((u64)value) * db_to_val[change - 1]) >> 32;
|
||||
|
||||
db -= change;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
s8 iwl_average_neg_dbm(const u8 *neg_dbm_values, u8 len)
|
||||
{
|
||||
int average_magnitude;
|
||||
u32 average_factor;
|
||||
int sum_magnitude = -128;
|
||||
u32 sum_factor = 0;
|
||||
int i, count = 0;
|
||||
|
||||
/*
|
||||
* To properly average the decibel values (signal values given in dBm)
|
||||
* we need to do the math in linear space. Doing a linear average of
|
||||
* dB (dBm) values is a bit annoying though due to the large range of
|
||||
* at least -10 to -110 dBm that will not fit into a 32 bit integer.
|
||||
*
|
||||
* A 64 bit integer should be sufficient, but then we still have the
|
||||
* problem that there are no directly usable utility functions
|
||||
* available.
|
||||
*
|
||||
* So, lets not deal with that and instead do much of the calculation
|
||||
* with a 16.16 fixed point integer along with a base in dBm. 16.16 bit
|
||||
* gives us plenty of head-room for adding up a few values and even
|
||||
* doing some math on it. And the tail should be accurate enough too
|
||||
* (1/2^16 is somewhere around -48 dB, so effectively zero).
|
||||
*
|
||||
* i.e. the real value of sum is:
|
||||
* sum = sum_factor / 2^16 * 10^(sum_magnitude / 10) mW
|
||||
*
|
||||
* However, that does mean we need to be able to bring two values to
|
||||
* a common base, so we need a helper for that.
|
||||
*
|
||||
* Note that this function takes an input with unsigned negative dBm
|
||||
* values but returns a signed dBm (i.e. a negative value).
|
||||
*/
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
int val_magnitude;
|
||||
u32 val_factor;
|
||||
|
||||
/* Assume invalid */
|
||||
if (neg_dbm_values[i] == 0xff)
|
||||
continue;
|
||||
|
||||
val_factor = 0x10000;
|
||||
val_magnitude = -neg_dbm_values[i];
|
||||
|
||||
if (val_magnitude <= sum_magnitude) {
|
||||
u8 div_db = sum_magnitude - val_magnitude;
|
||||
|
||||
val_factor = iwl_div_by_db(val_factor, div_db);
|
||||
val_magnitude = sum_magnitude;
|
||||
} else {
|
||||
u8 div_db = val_magnitude - sum_magnitude;
|
||||
|
||||
sum_factor = iwl_div_by_db(sum_factor, div_db);
|
||||
sum_magnitude = val_magnitude;
|
||||
}
|
||||
|
||||
sum_factor += val_factor;
|
||||
count++;
|
||||
}
|
||||
|
||||
/* No valid noise measurement, return a very high noise level */
|
||||
if (count == 0)
|
||||
return 0;
|
||||
|
||||
average_magnitude = sum_magnitude;
|
||||
average_factor = sum_factor / count;
|
||||
|
||||
/*
|
||||
* average_factor will be a number smaller than 1.0 (0x10000) at this
|
||||
* point. What we need to do now is to adjust average_magnitude so that
|
||||
* average_factor is between -0.5 dB and 0.5 dB.
|
||||
*
|
||||
* Just do -1 dB steps and find the point where
|
||||
* -0.5 dB * -i dB = 0x10000 * 10^(-0.5/10) / i dB
|
||||
* = div_by_db(0xe429, i)
|
||||
* is smaller than average_factor.
|
||||
*/
|
||||
for (i = 0; average_factor < iwl_div_by_db(0xe429, i); i++) {
|
||||
/* nothing */
|
||||
}
|
||||
|
||||
return clamp(average_magnitude - i, -128, 0);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_average_neg_dbm);
|
||||
@@ -0,0 +1,58 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2024-2025 Intel Corporation
|
||||
*/
|
||||
#ifndef __iwl_utils_h__
|
||||
#define __iwl_utils_h__
|
||||
|
||||
#include <net/cfg80211.h>
|
||||
|
||||
#ifdef CONFIG_INET
|
||||
/**
|
||||
* iwl_tx_tso_segment - Segments a TSO packet into subframes for A-MSDU.
|
||||
* @skb: buffer to segment.
|
||||
* @num_subframes: number of subframes to create.
|
||||
* @netdev_flags: netdev feature flags.
|
||||
* @mpdus_skbs: list to hold the segmented subframes.
|
||||
*
|
||||
* This function segments a large TCP packet into subframes.
|
||||
* subframes are added to the mpdus_skbs list
|
||||
*
|
||||
* Returns: 0 on success and negative value on failure.
|
||||
*/
|
||||
int iwl_tx_tso_segment(struct sk_buff *skb, unsigned int num_subframes,
|
||||
netdev_features_t netdev_flags,
|
||||
struct sk_buff_head *mpdus_skbs);
|
||||
#else
|
||||
static inline
|
||||
int iwl_tx_tso_segment(struct sk_buff *skb, unsigned int num_subframes,
|
||||
netdev_features_t netdev_flags,
|
||||
struct sk_buff_head *mpdus_skbs)
|
||||
{
|
||||
WARN_ON(1);
|
||||
|
||||
return -1;
|
||||
}
|
||||
#endif /* CONFIG_INET */
|
||||
|
||||
static inline
|
||||
u32 iwl_find_ie_offset(u8 *beacon, u8 eid, u32 frame_size)
|
||||
{
|
||||
struct ieee80211_mgmt *mgmt = (void *)beacon;
|
||||
const u8 *ie;
|
||||
|
||||
if (WARN_ON_ONCE(frame_size <= (mgmt->u.beacon.variable - beacon)))
|
||||
return 0;
|
||||
|
||||
frame_size -= mgmt->u.beacon.variable - beacon;
|
||||
|
||||
ie = cfg80211_find_ie(eid, mgmt->u.beacon.variable, frame_size);
|
||||
if (!ie)
|
||||
return 0;
|
||||
|
||||
return ie - beacon;
|
||||
}
|
||||
|
||||
s8 iwl_average_neg_dbm(const u8 *neg_dbm_values, u8 len);
|
||||
|
||||
#endif /* __iwl_utils_h__ */
|
||||
@@ -0,0 +1,12 @@
|
||||
# SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
obj-$(CONFIG_IWLMLD) += iwlmld.o
|
||||
obj-$(CONFIG_IWLWIFI_KUNIT_TESTS) += tests/
|
||||
|
||||
iwlmld-y += mld.o notif.o mac80211.o fw.o power.o iface.o link.o rx.o mcc.o session-protect.o phy.o
|
||||
iwlmld-y += scan.o sta.o tx.o coex.o tlc.o agg.o key.o regulatory.o ap.o thermal.o roc.o stats.o
|
||||
iwlmld-y += low_latency.o mlo.o ptp.o time_sync.o ftm-initiator.o
|
||||
iwlmld-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o
|
||||
iwlmld-$(CONFIG_IWLWIFI_LEDS) += led.o
|
||||
iwlmld-$(CONFIG_PM_SLEEP) += d3.o
|
||||
|
||||
subdir-ccflags-y += -I$(src)/../
|
||||
@@ -0,0 +1,680 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2024-2025 Intel Corporation
|
||||
*/
|
||||
#include "agg.h"
|
||||
#include "sta.h"
|
||||
#include "hcmd.h"
|
||||
#if defined(__FreeBSD__)
|
||||
#include <linux/cache.h>
|
||||
#endif
|
||||
|
||||
static void
|
||||
iwl_mld_reorder_release_frames(struct iwl_mld *mld, struct ieee80211_sta *sta,
|
||||
struct napi_struct *napi,
|
||||
struct iwl_mld_baid_data *baid_data,
|
||||
struct iwl_mld_reorder_buffer *reorder_buf,
|
||||
u16 nssn)
|
||||
{
|
||||
struct iwl_mld_reorder_buf_entry *entries =
|
||||
&baid_data->entries[reorder_buf->queue *
|
||||
baid_data->entries_per_queue];
|
||||
u16 ssn = reorder_buf->head_sn;
|
||||
|
||||
while (ieee80211_sn_less(ssn, nssn)) {
|
||||
int index = ssn % baid_data->buf_size;
|
||||
struct sk_buff_head *skb_list = &entries[index].frames;
|
||||
struct sk_buff *skb;
|
||||
|
||||
ssn = ieee80211_sn_inc(ssn);
|
||||
|
||||
/* Empty the list. Will have more than one frame for A-MSDU.
|
||||
* Empty list is valid as well since nssn indicates frames were
|
||||
* received.
|
||||
*/
|
||||
while ((skb = __skb_dequeue(skb_list))) {
|
||||
iwl_mld_pass_packet_to_mac80211(mld, napi, skb,
|
||||
reorder_buf->queue,
|
||||
sta);
|
||||
reorder_buf->num_stored--;
|
||||
}
|
||||
}
|
||||
reorder_buf->head_sn = nssn;
|
||||
}
|
||||
|
||||
static void iwl_mld_release_frames_from_notif(struct iwl_mld *mld,
|
||||
struct napi_struct *napi,
|
||||
u8 baid, u16 nssn, int queue)
|
||||
{
|
||||
struct iwl_mld_reorder_buffer *reorder_buf;
|
||||
struct iwl_mld_baid_data *ba_data;
|
||||
struct ieee80211_link_sta *link_sta;
|
||||
u32 sta_id;
|
||||
|
||||
IWL_DEBUG_HT(mld, "Frame release notification for BAID %u, NSSN %d\n",
|
||||
baid, nssn);
|
||||
|
||||
if (WARN_ON_ONCE(baid == IWL_RX_REORDER_DATA_INVALID_BAID ||
|
||||
baid >= ARRAY_SIZE(mld->fw_id_to_ba)))
|
||||
return;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
ba_data = rcu_dereference(mld->fw_id_to_ba[baid]);
|
||||
if (!ba_data) {
|
||||
IWL_DEBUG_HT(mld, "BAID %d not found in map\n", baid);
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
/* pick any STA ID to find the pointer */
|
||||
sta_id = ffs(ba_data->sta_mask) - 1;
|
||||
link_sta = rcu_dereference(mld->fw_id_to_link_sta[sta_id]);
|
||||
if (WARN_ON_ONCE(IS_ERR_OR_NULL(link_sta) || !link_sta->sta))
|
||||
goto out_unlock;
|
||||
|
||||
reorder_buf = &ba_data->reorder_buf[queue];
|
||||
|
||||
iwl_mld_reorder_release_frames(mld, link_sta->sta, napi, ba_data,
|
||||
reorder_buf, nssn);
|
||||
out_unlock:
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
void iwl_mld_handle_frame_release_notif(struct iwl_mld *mld,
|
||||
struct napi_struct *napi,
|
||||
struct iwl_rx_packet *pkt, int queue)
|
||||
{
|
||||
struct iwl_frame_release *release = (void *)pkt->data;
|
||||
u32 pkt_len = iwl_rx_packet_payload_len(pkt);
|
||||
|
||||
if (IWL_FW_CHECK(mld, pkt_len < sizeof(*release),
|
||||
"Unexpected frame release notif size %u (expected %zu)\n",
|
||||
pkt_len, sizeof(*release)))
|
||||
return;
|
||||
|
||||
iwl_mld_release_frames_from_notif(mld, napi, release->baid,
|
||||
le16_to_cpu(release->nssn),
|
||||
queue);
|
||||
}
|
||||
|
||||
void iwl_mld_handle_bar_frame_release_notif(struct iwl_mld *mld,
|
||||
struct napi_struct *napi,
|
||||
struct iwl_rx_packet *pkt,
|
||||
int queue)
|
||||
{
|
||||
struct iwl_bar_frame_release *release = (void *)pkt->data;
|
||||
struct iwl_mld_baid_data *baid_data;
|
||||
unsigned int baid, nssn, sta_id, tid;
|
||||
u32 pkt_len = iwl_rx_packet_payload_len(pkt);
|
||||
|
||||
if (IWL_FW_CHECK(mld, pkt_len < sizeof(*release),
|
||||
"Unexpected frame release notif size %u (expected %zu)\n",
|
||||
pkt_len, sizeof(*release)))
|
||||
return;
|
||||
|
||||
baid = le32_get_bits(release->ba_info,
|
||||
IWL_BAR_FRAME_RELEASE_BAID_MASK);
|
||||
nssn = le32_get_bits(release->ba_info,
|
||||
IWL_BAR_FRAME_RELEASE_NSSN_MASK);
|
||||
sta_id = le32_get_bits(release->sta_tid,
|
||||
IWL_BAR_FRAME_RELEASE_STA_MASK);
|
||||
tid = le32_get_bits(release->sta_tid,
|
||||
IWL_BAR_FRAME_RELEASE_TID_MASK);
|
||||
|
||||
if (IWL_FW_CHECK(mld, baid >= ARRAY_SIZE(mld->fw_id_to_ba),
|
||||
"BAR release: invalid BAID (%x)\n", baid))
|
||||
return;
|
||||
|
||||
rcu_read_lock();
|
||||
baid_data = rcu_dereference(mld->fw_id_to_ba[baid]);
|
||||
if (!baid_data) {
|
||||
IWL_DEBUG_HT(mld,
|
||||
"Got valid BAID %d but not allocated\n",
|
||||
baid);
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
if (IWL_FW_CHECK(mld, tid != baid_data->tid ||
|
||||
sta_id > mld->fw->ucode_capa.num_stations ||
|
||||
!(baid_data->sta_mask & BIT(sta_id)),
|
||||
"BAID 0x%x is mapped to sta_mask:0x%x tid:%d, but BAR release received for sta:%d tid:%d\n",
|
||||
baid, baid_data->sta_mask, baid_data->tid, sta_id,
|
||||
tid))
|
||||
goto out_unlock;
|
||||
|
||||
IWL_DEBUG_DROP(mld, "Received a BAR, expect packet loss: nssn %d\n",
|
||||
nssn);
|
||||
|
||||
iwl_mld_release_frames_from_notif(mld, napi, baid, nssn, queue);
|
||||
out_unlock:
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
void iwl_mld_del_ba(struct iwl_mld *mld, int queue,
|
||||
struct iwl_mld_delba_data *data)
|
||||
{
|
||||
struct iwl_mld_baid_data *ba_data;
|
||||
struct iwl_mld_reorder_buffer *reorder_buf;
|
||||
struct ieee80211_link_sta *link_sta;
|
||||
u8 baid = data->baid;
|
||||
u32 sta_id;
|
||||
|
||||
if (WARN_ONCE(baid >= IWL_MAX_BAID, "invalid BAID: %x\n", baid))
|
||||
return;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
ba_data = rcu_dereference(mld->fw_id_to_ba[baid]);
|
||||
if (WARN_ON_ONCE(!ba_data))
|
||||
goto out_unlock;
|
||||
|
||||
/* pick any STA ID to find the pointer */
|
||||
sta_id = ffs(ba_data->sta_mask) - 1;
|
||||
link_sta = rcu_dereference(mld->fw_id_to_link_sta[sta_id]);
|
||||
if (WARN_ON_ONCE(IS_ERR_OR_NULL(link_sta) || !link_sta->sta))
|
||||
goto out_unlock;
|
||||
|
||||
reorder_buf = &ba_data->reorder_buf[queue];
|
||||
|
||||
/* release all frames that are in the reorder buffer to the stack */
|
||||
iwl_mld_reorder_release_frames(mld, link_sta->sta, NULL,
|
||||
ba_data, reorder_buf,
|
||||
ieee80211_sn_add(reorder_buf->head_sn,
|
||||
ba_data->buf_size));
|
||||
out_unlock:
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
/* Returns true if the MPDU was buffered\dropped, false if it should be passed
|
||||
* to upper layer.
|
||||
*/
|
||||
enum iwl_mld_reorder_result
|
||||
iwl_mld_reorder(struct iwl_mld *mld, struct napi_struct *napi,
|
||||
int queue, struct ieee80211_sta *sta,
|
||||
struct sk_buff *skb, struct iwl_rx_mpdu_desc *desc)
|
||||
{
|
||||
struct ieee80211_hdr *hdr = (void *)skb_mac_header(skb);
|
||||
struct iwl_mld_baid_data *baid_data;
|
||||
struct iwl_mld_reorder_buffer *buffer;
|
||||
struct iwl_mld_reorder_buf_entry *entries;
|
||||
struct iwl_mld_sta *mld_sta = iwl_mld_sta_from_mac80211(sta);
|
||||
struct iwl_mld_link_sta *mld_link_sta;
|
||||
u32 reorder = le32_to_cpu(desc->reorder_data);
|
||||
bool amsdu, last_subframe, is_old_sn, is_dup;
|
||||
u8 tid = ieee80211_get_tid(hdr);
|
||||
u8 baid;
|
||||
u16 nssn, sn;
|
||||
u32 sta_mask = 0;
|
||||
int index;
|
||||
u8 link_id;
|
||||
|
||||
baid = u32_get_bits(reorder, IWL_RX_MPDU_REORDER_BAID_MASK);
|
||||
|
||||
/* This also covers the case of receiving a Block Ack Request
|
||||
* outside a BA session; we'll pass it to mac80211 and that
|
||||
* then sends a delBA action frame.
|
||||
* This also covers pure monitor mode, in which case we won't
|
||||
* have any BA sessions.
|
||||
*/
|
||||
if (baid == IWL_RX_REORDER_DATA_INVALID_BAID)
|
||||
return IWL_MLD_PASS_SKB;
|
||||
|
||||
/* no sta yet */
|
||||
if (WARN_ONCE(!sta,
|
||||
"Got valid BAID without a valid station assigned\n"))
|
||||
return IWL_MLD_PASS_SKB;
|
||||
|
||||
/* not a data packet */
|
||||
if (!ieee80211_is_data_qos(hdr->frame_control) ||
|
||||
is_multicast_ether_addr(hdr->addr1))
|
||||
return IWL_MLD_PASS_SKB;
|
||||
|
||||
if (unlikely(!ieee80211_is_data_present(hdr->frame_control)))
|
||||
return IWL_MLD_PASS_SKB;
|
||||
|
||||
baid_data = rcu_dereference(mld->fw_id_to_ba[baid]);
|
||||
if (!baid_data) {
|
||||
IWL_DEBUG_HT(mld,
|
||||
"Got valid BAID but no baid allocated, bypass re-ordering (BAID=%d reorder=0x%x)\n",
|
||||
baid, reorder);
|
||||
return IWL_MLD_PASS_SKB;
|
||||
}
|
||||
|
||||
for_each_mld_link_sta(mld_sta, mld_link_sta, link_id)
|
||||
sta_mask |= BIT(mld_link_sta->fw_id);
|
||||
|
||||
/* verify the BAID is correctly mapped to the sta and tid */
|
||||
if (IWL_FW_CHECK(mld,
|
||||
tid != baid_data->tid ||
|
||||
!(sta_mask & baid_data->sta_mask),
|
||||
"BAID 0x%x is mapped to sta_mask:0x%x tid:%d, but was received for sta_mask:0x%x tid:%d\n",
|
||||
baid, baid_data->sta_mask, baid_data->tid,
|
||||
sta_mask, tid))
|
||||
return IWL_MLD_PASS_SKB;
|
||||
|
||||
buffer = &baid_data->reorder_buf[queue];
|
||||
entries = &baid_data->entries[queue * baid_data->entries_per_queue];
|
||||
|
||||
is_old_sn = !!(reorder & IWL_RX_MPDU_REORDER_BA_OLD_SN);
|
||||
|
||||
if (!buffer->valid && is_old_sn)
|
||||
return IWL_MLD_PASS_SKB;
|
||||
|
||||
buffer->valid = true;
|
||||
|
||||
is_dup = !!(desc->status & cpu_to_le32(IWL_RX_MPDU_STATUS_DUPLICATE));
|
||||
|
||||
/* drop any duplicated or outdated packets */
|
||||
if (is_dup || is_old_sn)
|
||||
return IWL_MLD_DROP_SKB;
|
||||
|
||||
sn = u32_get_bits(reorder, IWL_RX_MPDU_REORDER_SN_MASK);
|
||||
nssn = u32_get_bits(reorder, IWL_RX_MPDU_REORDER_NSSN_MASK);
|
||||
amsdu = desc->mac_flags2 & IWL_RX_MPDU_MFLG2_AMSDU;
|
||||
last_subframe = desc->amsdu_info & IWL_RX_MPDU_AMSDU_LAST_SUBFRAME;
|
||||
|
||||
/* release immediately if allowed by nssn and no stored frames */
|
||||
if (!buffer->num_stored && ieee80211_sn_less(sn, nssn)) {
|
||||
if (!amsdu || last_subframe)
|
||||
buffer->head_sn = nssn;
|
||||
return IWL_MLD_PASS_SKB;
|
||||
}
|
||||
|
||||
/* release immediately if there are no stored frames, and the sn is
|
||||
* equal to the head.
|
||||
* This can happen due to reorder timer, where NSSN is behind head_sn.
|
||||
* When we released everything, and we got the next frame in the
|
||||
* sequence, according to the NSSN we can't release immediately,
|
||||
* while technically there is no hole and we can move forward.
|
||||
*/
|
||||
if (!buffer->num_stored && sn == buffer->head_sn) {
|
||||
if (!amsdu || last_subframe)
|
||||
buffer->head_sn = ieee80211_sn_inc(buffer->head_sn);
|
||||
return IWL_MLD_PASS_SKB;
|
||||
}
|
||||
|
||||
/* put in reorder buffer */
|
||||
index = sn % baid_data->buf_size;
|
||||
__skb_queue_tail(&entries[index].frames, skb);
|
||||
buffer->num_stored++;
|
||||
|
||||
/* We cannot trust NSSN for AMSDU sub-frames that are not the last. The
|
||||
* reason is that NSSN advances on the first sub-frame, and may cause
|
||||
* the reorder buffer to advance before all the sub-frames arrive.
|
||||
*
|
||||
* Example: reorder buffer contains SN 0 & 2, and we receive AMSDU with
|
||||
* SN 1. NSSN for first sub frame will be 3 with the result of driver
|
||||
* releasing SN 0,1, 2. When sub-frame 1 arrives - reorder buffer is
|
||||
* already ahead and it will be dropped.
|
||||
* If the last sub-frame is not on this queue - we will get frame
|
||||
* release notification with up to date NSSN.
|
||||
* If this is the first frame that is stored in the buffer, the head_sn
|
||||
* may be outdated. Update it based on the last NSSN to make sure it
|
||||
* will be released when the frame release notification arrives.
|
||||
*/
|
||||
if (!amsdu || last_subframe)
|
||||
iwl_mld_reorder_release_frames(mld, sta, napi, baid_data,
|
||||
buffer, nssn);
|
||||
else if (buffer->num_stored == 1)
|
||||
buffer->head_sn = nssn;
|
||||
|
||||
return IWL_MLD_BUFFERED_SKB;
|
||||
}
|
||||
EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_mld_reorder);
|
||||
|
||||
static void iwl_mld_rx_agg_session_expired(struct timer_list *t)
|
||||
{
|
||||
struct iwl_mld_baid_data *data =
|
||||
timer_container_of(data, t, session_timer);
|
||||
struct iwl_mld_baid_data __rcu **rcu_ptr = data->rcu_ptr;
|
||||
struct iwl_mld_baid_data *ba_data;
|
||||
struct ieee80211_link_sta *link_sta;
|
||||
struct iwl_mld_sta *mld_sta;
|
||||
unsigned long timeout;
|
||||
unsigned int sta_id;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
ba_data = rcu_dereference(*rcu_ptr);
|
||||
if (WARN_ON(!ba_data))
|
||||
goto unlock;
|
||||
|
||||
if (WARN_ON(!ba_data->timeout))
|
||||
goto unlock;
|
||||
|
||||
timeout = ba_data->last_rx_timestamp +
|
||||
TU_TO_JIFFIES(ba_data->timeout * 2);
|
||||
if (time_is_after_jiffies(timeout)) {
|
||||
mod_timer(&ba_data->session_timer, timeout);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
/* timer expired, pick any STA ID to find the pointer */
|
||||
sta_id = ffs(ba_data->sta_mask) - 1;
|
||||
link_sta = rcu_dereference(ba_data->mld->fw_id_to_link_sta[sta_id]);
|
||||
|
||||
/* sta should be valid unless the following happens:
|
||||
* The firmware asserts which triggers a reconfig flow, but
|
||||
* the reconfig fails before we set the pointer to sta into
|
||||
* the fw_id_to_link_sta pointer table. mac80211 can't stop
|
||||
* A-MPDU and hence the timer continues to run. Then, the
|
||||
* timer expires and sta is NULL.
|
||||
*/
|
||||
if (IS_ERR_OR_NULL(link_sta) || WARN_ON(!link_sta->sta))
|
||||
goto unlock;
|
||||
|
||||
mld_sta = iwl_mld_sta_from_mac80211(link_sta->sta);
|
||||
ieee80211_rx_ba_timer_expired(mld_sta->vif, link_sta->sta->addr,
|
||||
ba_data->tid);
|
||||
unlock:
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static int
|
||||
iwl_mld_stop_ba_in_fw(struct iwl_mld *mld, struct ieee80211_sta *sta, int tid)
|
||||
{
|
||||
struct iwl_rx_baid_cfg_cmd cmd = {
|
||||
.action = cpu_to_le32(IWL_RX_BAID_ACTION_REMOVE),
|
||||
.remove.sta_id_mask =
|
||||
cpu_to_le32(iwl_mld_fw_sta_id_mask(mld, sta)),
|
||||
.remove.tid = cpu_to_le32(tid),
|
||||
|
||||
};
|
||||
int ret;
|
||||
|
||||
ret = iwl_mld_send_cmd_pdu(mld,
|
||||
WIDE_ID(DATA_PATH_GROUP,
|
||||
RX_BAID_ALLOCATION_CONFIG_CMD),
|
||||
&cmd);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
IWL_DEBUG_HT(mld, "RX BA Session stopped in fw\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
iwl_mld_start_ba_in_fw(struct iwl_mld *mld, struct ieee80211_sta *sta,
|
||||
int tid, u16 ssn, u16 buf_size)
|
||||
{
|
||||
struct iwl_rx_baid_cfg_cmd cmd = {
|
||||
.action = cpu_to_le32(IWL_RX_BAID_ACTION_ADD),
|
||||
.alloc.sta_id_mask =
|
||||
cpu_to_le32(iwl_mld_fw_sta_id_mask(mld, sta)),
|
||||
.alloc.tid = tid,
|
||||
.alloc.ssn = cpu_to_le16(ssn),
|
||||
.alloc.win_size = cpu_to_le16(buf_size),
|
||||
};
|
||||
struct iwl_host_cmd hcmd = {
|
||||
.id = WIDE_ID(DATA_PATH_GROUP, RX_BAID_ALLOCATION_CONFIG_CMD),
|
||||
.flags = CMD_WANT_SKB,
|
||||
.len[0] = sizeof(cmd),
|
||||
.data[0] = &cmd,
|
||||
};
|
||||
struct iwl_rx_baid_cfg_resp *resp;
|
||||
struct iwl_rx_packet *pkt;
|
||||
u32 resp_len;
|
||||
int ret, baid;
|
||||
|
||||
BUILD_BUG_ON(sizeof(*resp) != sizeof(baid));
|
||||
|
||||
ret = iwl_mld_send_cmd(mld, &hcmd);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pkt = hcmd.resp_pkt;
|
||||
|
||||
resp_len = iwl_rx_packet_payload_len(pkt);
|
||||
if (IWL_FW_CHECK(mld, resp_len != sizeof(*resp),
|
||||
"BAID_ALLOC_CMD: unexpected response length %d\n",
|
||||
resp_len)) {
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
IWL_DEBUG_HT(mld, "RX BA Session started in fw\n");
|
||||
|
||||
resp = (void *)pkt->data;
|
||||
baid = le32_to_cpu(resp->baid);
|
||||
|
||||
if (IWL_FW_CHECK(mld, baid < 0 || baid >= ARRAY_SIZE(mld->fw_id_to_ba),
|
||||
"BAID_ALLOC_CMD: invalid BAID response %d\n", baid)) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = baid;
|
||||
out:
|
||||
iwl_free_resp(&hcmd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void iwl_mld_init_reorder_buffer(struct iwl_mld *mld,
|
||||
struct iwl_mld_baid_data *data,
|
||||
u16 ssn)
|
||||
{
|
||||
for (int i = 0; i < mld->trans->info.num_rxqs; i++) {
|
||||
struct iwl_mld_reorder_buffer *reorder_buf =
|
||||
&data->reorder_buf[i];
|
||||
struct iwl_mld_reorder_buf_entry *entries =
|
||||
&data->entries[i * data->entries_per_queue];
|
||||
|
||||
reorder_buf->head_sn = ssn;
|
||||
reorder_buf->queue = i;
|
||||
|
||||
for (int j = 0; j < data->buf_size; j++)
|
||||
__skb_queue_head_init(&entries[j].frames);
|
||||
}
|
||||
}
|
||||
|
||||
static void iwl_mld_free_reorder_buffer(struct iwl_mld *mld,
|
||||
struct iwl_mld_baid_data *data)
|
||||
{
|
||||
struct iwl_mld_delba_data delba_data = {
|
||||
.baid = data->baid,
|
||||
};
|
||||
|
||||
iwl_mld_sync_rx_queues(mld, IWL_MLD_RXQ_NOTIF_DEL_BA,
|
||||
&delba_data, sizeof(delba_data));
|
||||
|
||||
for (int i = 0; i < mld->trans->info.num_rxqs; i++) {
|
||||
struct iwl_mld_reorder_buffer *reorder_buf =
|
||||
&data->reorder_buf[i];
|
||||
struct iwl_mld_reorder_buf_entry *entries =
|
||||
&data->entries[i * data->entries_per_queue];
|
||||
|
||||
if (likely(!reorder_buf->num_stored))
|
||||
continue;
|
||||
|
||||
/* This shouldn't happen in regular DELBA since the RX queues
|
||||
* sync internal DELBA notification should trigger a release
|
||||
* of all frames in the reorder buffer.
|
||||
*/
|
||||
WARN_ON(1);
|
||||
|
||||
for (int j = 0; j < data->buf_size; j++)
|
||||
__skb_queue_purge(&entries[j].frames);
|
||||
}
|
||||
}
|
||||
|
||||
int iwl_mld_ampdu_rx_start(struct iwl_mld *mld, struct ieee80211_sta *sta,
|
||||
int tid, u16 ssn, u16 buf_size, u16 timeout)
|
||||
{
|
||||
struct iwl_mld_sta *mld_sta = iwl_mld_sta_from_mac80211(sta);
|
||||
struct iwl_mld_baid_data *baid_data = NULL;
|
||||
u32 reorder_buf_size = buf_size * sizeof(baid_data->entries[0]);
|
||||
int ret, baid;
|
||||
u32 sta_mask;
|
||||
|
||||
lockdep_assert_wiphy(mld->wiphy);
|
||||
|
||||
if (mld->num_rx_ba_sessions >= IWL_MAX_BAID) {
|
||||
IWL_DEBUG_HT(mld,
|
||||
"Max num of RX BA sessions reached; blocking new session\n");
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
sta_mask = iwl_mld_fw_sta_id_mask(mld, sta);
|
||||
if (WARN_ON(!sta_mask))
|
||||
return -EINVAL;
|
||||
|
||||
/* sparse doesn't like the __align() so don't check */
|
||||
#ifndef __CHECKER__
|
||||
/* The division below will be OK if either the cache line size
|
||||
* can be divided by the entry size (ALIGN will round up) or if
|
||||
* the entry size can be divided by the cache line size, in which
|
||||
* case the ALIGN() will do nothing.
|
||||
*/
|
||||
BUILD_BUG_ON(SMP_CACHE_BYTES % sizeof(baid_data->entries[0]) &&
|
||||
sizeof(baid_data->entries[0]) % SMP_CACHE_BYTES);
|
||||
#endif
|
||||
|
||||
/* Upward align the reorder buffer size to fill an entire cache
|
||||
* line for each queue, to avoid sharing cache lines between
|
||||
* different queues.
|
||||
*/
|
||||
reorder_buf_size = ALIGN(reorder_buf_size, SMP_CACHE_BYTES);
|
||||
|
||||
/* Allocate here so if allocation fails we can bail out early
|
||||
* before starting the BA session in the firmware
|
||||
*/
|
||||
baid_data = kzalloc(sizeof(*baid_data) +
|
||||
mld->trans->info.num_rxqs * reorder_buf_size,
|
||||
GFP_KERNEL);
|
||||
if (!baid_data)
|
||||
return -ENOMEM;
|
||||
|
||||
/* This division is why we need the above BUILD_BUG_ON(),
|
||||
* if that doesn't hold then this will not be right.
|
||||
*/
|
||||
baid_data->entries_per_queue =
|
||||
reorder_buf_size / sizeof(baid_data->entries[0]);
|
||||
|
||||
baid = iwl_mld_start_ba_in_fw(mld, sta, tid, ssn, buf_size);
|
||||
if (baid < 0) {
|
||||
ret = baid;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
mld->num_rx_ba_sessions++;
|
||||
mld_sta->tid_to_baid[tid] = baid;
|
||||
|
||||
baid_data->baid = baid;
|
||||
baid_data->mld = mld;
|
||||
baid_data->tid = tid;
|
||||
baid_data->buf_size = buf_size;
|
||||
baid_data->sta_mask = sta_mask;
|
||||
baid_data->timeout = timeout;
|
||||
baid_data->last_rx_timestamp = jiffies;
|
||||
baid_data->rcu_ptr = &mld->fw_id_to_ba[baid];
|
||||
|
||||
iwl_mld_init_reorder_buffer(mld, baid_data, ssn);
|
||||
|
||||
timer_setup(&baid_data->session_timer, iwl_mld_rx_agg_session_expired,
|
||||
0);
|
||||
if (timeout)
|
||||
mod_timer(&baid_data->session_timer,
|
||||
TU_TO_EXP_TIME(timeout * 2));
|
||||
|
||||
IWL_DEBUG_HT(mld, "STA mask=0x%x (tid=%d) is assigned to BAID %d\n",
|
||||
baid_data->sta_mask, tid, baid);
|
||||
|
||||
/* protect the BA data with RCU to cover a case where our
|
||||
* internal RX sync mechanism will timeout (not that it's
|
||||
* supposed to happen) and we will free the session data while
|
||||
* RX is being processed in parallel
|
||||
*/
|
||||
WARN_ON(rcu_access_pointer(mld->fw_id_to_ba[baid]));
|
||||
rcu_assign_pointer(mld->fw_id_to_ba[baid], baid_data);
|
||||
|
||||
return 0;
|
||||
|
||||
out_free:
|
||||
kfree(baid_data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iwl_mld_ampdu_rx_stop(struct iwl_mld *mld, struct ieee80211_sta *sta,
|
||||
int tid)
|
||||
{
|
||||
struct iwl_mld_sta *mld_sta = iwl_mld_sta_from_mac80211(sta);
|
||||
int baid = mld_sta->tid_to_baid[tid];
|
||||
struct iwl_mld_baid_data *baid_data;
|
||||
int ret;
|
||||
|
||||
lockdep_assert_wiphy(mld->wiphy);
|
||||
|
||||
/* during firmware restart, do not send the command as the firmware no
|
||||
* longer recognizes the session. instead, only clear the driver BA
|
||||
* session data.
|
||||
*/
|
||||
if (!mld->fw_status.in_hw_restart) {
|
||||
ret = iwl_mld_stop_ba_in_fw(mld, sta, tid);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!WARN_ON(mld->num_rx_ba_sessions == 0))
|
||||
mld->num_rx_ba_sessions--;
|
||||
|
||||
baid_data = wiphy_dereference(mld->wiphy, mld->fw_id_to_ba[baid]);
|
||||
if (WARN_ON(!baid_data))
|
||||
return -EINVAL;
|
||||
|
||||
if (timer_pending(&baid_data->session_timer))
|
||||
timer_shutdown_sync(&baid_data->session_timer);
|
||||
|
||||
iwl_mld_free_reorder_buffer(mld, baid_data);
|
||||
|
||||
RCU_INIT_POINTER(mld->fw_id_to_ba[baid], NULL);
|
||||
kfree_rcu(baid_data, rcu_head);
|
||||
|
||||
IWL_DEBUG_HT(mld, "BAID %d is free\n", baid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iwl_mld_update_sta_baids(struct iwl_mld *mld,
|
||||
u32 old_sta_mask,
|
||||
u32 new_sta_mask)
|
||||
{
|
||||
struct iwl_rx_baid_cfg_cmd cmd = {
|
||||
.action = cpu_to_le32(IWL_RX_BAID_ACTION_MODIFY),
|
||||
.modify.old_sta_id_mask = cpu_to_le32(old_sta_mask),
|
||||
.modify.new_sta_id_mask = cpu_to_le32(new_sta_mask),
|
||||
};
|
||||
u32 cmd_id = WIDE_ID(DATA_PATH_GROUP, RX_BAID_ALLOCATION_CONFIG_CMD);
|
||||
int baid;
|
||||
|
||||
/* mac80211 will remove sessions later, but we ignore all that */
|
||||
if (mld->fw_status.in_hw_restart)
|
||||
return 0;
|
||||
|
||||
BUILD_BUG_ON(sizeof(struct iwl_rx_baid_cfg_resp) != sizeof(baid));
|
||||
|
||||
for (baid = 0; baid < ARRAY_SIZE(mld->fw_id_to_ba); baid++) {
|
||||
struct iwl_mld_baid_data *data;
|
||||
int ret;
|
||||
|
||||
data = wiphy_dereference(mld->wiphy, mld->fw_id_to_ba[baid]);
|
||||
if (!data)
|
||||
continue;
|
||||
|
||||
if (!(data->sta_mask & old_sta_mask))
|
||||
continue;
|
||||
|
||||
WARN_ONCE(data->sta_mask != old_sta_mask,
|
||||
"BAID data for %d corrupted - expected 0x%x found 0x%x\n",
|
||||
baid, old_sta_mask, data->sta_mask);
|
||||
|
||||
cmd.modify.tid = cpu_to_le32(data->tid);
|
||||
|
||||
ret = iwl_mld_send_cmd_pdu(mld, cmd_id, &cmd);
|
||||
if (ret)
|
||||
return ret;
|
||||
data->sta_mask = new_sta_mask;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2024 Intel Corporation
|
||||
*/
|
||||
#ifndef __iwl_agg_h__
|
||||
#define __iwl_agg_h__
|
||||
|
||||
#include "mld.h"
|
||||
#include "fw/api/rx.h"
|
||||
|
||||
/**
|
||||
* struct iwl_mld_reorder_buffer - per ra/tid/queue reorder buffer
|
||||
* @head_sn: reorder window head sequence number
|
||||
* @num_stored: number of MPDUs stored in the buffer
|
||||
* @queue: queue of this reorder buffer
|
||||
* @valid: true if reordering is valid for this queue
|
||||
*/
|
||||
struct iwl_mld_reorder_buffer {
|
||||
u16 head_sn;
|
||||
u16 num_stored;
|
||||
int queue;
|
||||
bool valid;
|
||||
} ____cacheline_aligned_in_smp;
|
||||
|
||||
/**
|
||||
* struct iwl_mld_reorder_buf_entry - reorder buffer entry per-queue/per-seqno
|
||||
* @frames: list of skbs stored. a list is necessary because in an A-MSDU,
|
||||
* all sub-frames share the same sequence number, so they are stored
|
||||
* together in the same list.
|
||||
*/
|
||||
struct iwl_mld_reorder_buf_entry {
|
||||
struct sk_buff_head frames;
|
||||
}
|
||||
#ifndef __CHECKER__
|
||||
/* sparse doesn't like this construct: "bad integer constant expression" */
|
||||
__aligned(roundup_pow_of_two(sizeof(struct sk_buff_head)))
|
||||
#endif
|
||||
;
|
||||
|
||||
/**
|
||||
* struct iwl_mld_baid_data - Block Ack session data
|
||||
* @rcu_head: RCU head for freeing this data
|
||||
* @sta_mask: station mask for the BAID
|
||||
* @tid: tid of the session
|
||||
* @baid: baid of the session
|
||||
* @buf_size: the reorder buffer size as set by the last ADDBA request
|
||||
* @entries_per_queue: number of buffers per queue, this actually gets
|
||||
* aligned up to avoid cache line sharing between queues
|
||||
* @timeout: the timeout value specified in the ADDBA request.
|
||||
* @last_rx_timestamp: timestamp of the last received packet (in jiffies). This
|
||||
* value is updated only when the configured @timeout has passed since
|
||||
* the last update to minimize cache bouncing between RX queues.
|
||||
* @session_timer: timer is set to expire after 2 * @timeout (since we want
|
||||
* to minimize the cache bouncing by updating @last_rx_timestamp only once
|
||||
* after @timeout has passed). If no packets are received within this
|
||||
* period, it informs mac80211 to initiate delBA flow, terminating the
|
||||
* BA session.
|
||||
* @rcu_ptr: BA data RCU protected access
|
||||
* @mld: mld pointer, needed for timer context
|
||||
* @reorder_buf: reorder buffer, allocated per queue
|
||||
* @entries: data
|
||||
*/
|
||||
struct iwl_mld_baid_data {
|
||||
struct rcu_head rcu_head;
|
||||
u32 sta_mask;
|
||||
u8 tid;
|
||||
u8 baid;
|
||||
u16 buf_size;
|
||||
u16 entries_per_queue;
|
||||
u16 timeout;
|
||||
struct timer_list session_timer;
|
||||
unsigned long last_rx_timestamp;
|
||||
struct iwl_mld_baid_data __rcu **rcu_ptr;
|
||||
struct iwl_mld *mld;
|
||||
struct iwl_mld_reorder_buffer reorder_buf[IWL_MAX_RX_HW_QUEUES];
|
||||
struct iwl_mld_reorder_buf_entry entries[] ____cacheline_aligned_in_smp;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_mld_delba_data - RX queue sync data for %IWL_MLD_RXQ_NOTIF_DEL_BA
|
||||
*
|
||||
* @baid: Block Ack id, used to identify the BA session to be removed
|
||||
*/
|
||||
struct iwl_mld_delba_data {
|
||||
u32 baid;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* enum iwl_mld_reorder_result - Possible return values for iwl_mld_reorder()
|
||||
* indicating how the caller should handle the skb based on the result.
|
||||
*
|
||||
* @IWL_MLD_PASS_SKB: skb should be passed to upper layer.
|
||||
* @IWL_MLD_BUFFERED_SKB: skb has been buffered, don't pass it to upper layer.
|
||||
* @IWL_MLD_DROP_SKB: skb should be dropped and freed by the caller.
|
||||
*/
|
||||
enum iwl_mld_reorder_result {
|
||||
IWL_MLD_PASS_SKB,
|
||||
IWL_MLD_BUFFERED_SKB,
|
||||
IWL_MLD_DROP_SKB
|
||||
};
|
||||
|
||||
int iwl_mld_ampdu_rx_start(struct iwl_mld *mld, struct ieee80211_sta *sta,
|
||||
int tid, u16 ssn, u16 buf_size, u16 timeout);
|
||||
int iwl_mld_ampdu_rx_stop(struct iwl_mld *mld, struct ieee80211_sta *sta,
|
||||
int tid);
|
||||
|
||||
enum iwl_mld_reorder_result
|
||||
iwl_mld_reorder(struct iwl_mld *mld, struct napi_struct *napi,
|
||||
int queue, struct ieee80211_sta *sta,
|
||||
struct sk_buff *skb, struct iwl_rx_mpdu_desc *desc);
|
||||
|
||||
void iwl_mld_handle_frame_release_notif(struct iwl_mld *mld,
|
||||
struct napi_struct *napi,
|
||||
struct iwl_rx_packet *pkt, int queue);
|
||||
void iwl_mld_handle_bar_frame_release_notif(struct iwl_mld *mld,
|
||||
struct napi_struct *napi,
|
||||
struct iwl_rx_packet *pkt,
|
||||
int queue);
|
||||
|
||||
void iwl_mld_del_ba(struct iwl_mld *mld, int queue,
|
||||
struct iwl_mld_delba_data *data);
|
||||
|
||||
int iwl_mld_update_sta_baids(struct iwl_mld *mld,
|
||||
u32 old_sta_mask,
|
||||
u32 new_sta_mask);
|
||||
|
||||
#endif /* __iwl_agg_h__ */
|
||||
@@ -0,0 +1,363 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2024 Intel Corporation
|
||||
*/
|
||||
#include <linux/crc32.h>
|
||||
|
||||
#include <net/mac80211.h>
|
||||
|
||||
#include "ap.h"
|
||||
#include "hcmd.h"
|
||||
#include "tx.h"
|
||||
#include "power.h"
|
||||
#include "key.h"
|
||||
#include "phy.h"
|
||||
#include "iwl-utils.h"
|
||||
|
||||
#include "fw/api/sta.h"
|
||||
|
||||
void iwl_mld_set_tim_idx(struct iwl_mld *mld, __le32 *tim_index,
|
||||
u8 *beacon, u32 frame_size)
|
||||
{
|
||||
u32 tim_idx;
|
||||
struct ieee80211_mgmt *mgmt = (void *)beacon;
|
||||
|
||||
/* The index is relative to frame start but we start looking at the
|
||||
* variable-length part of the beacon.
|
||||
*/
|
||||
tim_idx = mgmt->u.beacon.variable - beacon;
|
||||
|
||||
/* Parse variable-length elements of beacon to find WLAN_EID_TIM */
|
||||
while ((tim_idx < (frame_size - 2)) &&
|
||||
(beacon[tim_idx] != WLAN_EID_TIM))
|
||||
tim_idx += beacon[tim_idx + 1] + 2;
|
||||
|
||||
/* If TIM field was found, set variables */
|
||||
if ((tim_idx < (frame_size - 1)) && beacon[tim_idx] == WLAN_EID_TIM)
|
||||
*tim_index = cpu_to_le32(tim_idx);
|
||||
else
|
||||
IWL_WARN(mld, "Unable to find TIM Element in beacon\n");
|
||||
}
|
||||
|
||||
u8 iwl_mld_get_rate_flags(struct iwl_mld *mld,
|
||||
struct ieee80211_tx_info *info,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link,
|
||||
enum nl80211_band band)
|
||||
{
|
||||
u32 legacy = link->beacon_tx_rate.control[band].legacy;
|
||||
u32 rate_idx, rate_flags = 0, fw_rate;
|
||||
|
||||
/* if beacon rate was configured try using it */
|
||||
if (hweight32(legacy) == 1) {
|
||||
u32 rate = ffs(legacy) - 1;
|
||||
struct ieee80211_supported_band *sband =
|
||||
mld->hw->wiphy->bands[band];
|
||||
|
||||
rate_idx = sband->bitrates[rate].hw_value;
|
||||
} else {
|
||||
rate_idx = iwl_mld_get_lowest_rate(mld, info, vif);
|
||||
}
|
||||
|
||||
if (rate_idx <= IWL_LAST_CCK_RATE)
|
||||
rate_flags = IWL_MAC_BEACON_CCK;
|
||||
|
||||
/* Legacy rates are indexed as follows:
|
||||
* 0 - 3 for CCK and 0 - 7 for OFDM.
|
||||
*/
|
||||
fw_rate = (rate_idx >= IWL_FIRST_OFDM_RATE ?
|
||||
rate_idx - IWL_FIRST_OFDM_RATE : rate_idx);
|
||||
|
||||
return fw_rate | rate_flags;
|
||||
}
|
||||
|
||||
int iwl_mld_send_beacon_template_cmd(struct iwl_mld *mld,
|
||||
struct sk_buff *beacon,
|
||||
struct iwl_mac_beacon_cmd *cmd)
|
||||
{
|
||||
struct iwl_host_cmd hcmd = {
|
||||
.id = BEACON_TEMPLATE_CMD,
|
||||
};
|
||||
|
||||
hcmd.len[0] = sizeof(*cmd);
|
||||
hcmd.data[0] = cmd;
|
||||
|
||||
hcmd.len[1] = beacon->len;
|
||||
hcmd.data[1] = beacon->data;
|
||||
hcmd.dataflags[1] = IWL_HCMD_DFL_DUP;
|
||||
|
||||
return iwl_mld_send_cmd(mld, &hcmd);
|
||||
}
|
||||
|
||||
static int iwl_mld_fill_beacon_template_cmd(struct iwl_mld *mld,
|
||||
struct ieee80211_vif *vif,
|
||||
struct sk_buff *beacon,
|
||||
struct iwl_mac_beacon_cmd *cmd,
|
||||
struct ieee80211_bss_conf *link)
|
||||
{
|
||||
struct iwl_mld_link *mld_link = iwl_mld_link_from_mac80211(link);
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(beacon);
|
||||
struct ieee80211_chanctx_conf *ctx;
|
||||
bool enable_fils;
|
||||
u16 flags = 0;
|
||||
|
||||
lockdep_assert_wiphy(mld->wiphy);
|
||||
|
||||
if (WARN_ON(!mld_link))
|
||||
return -EINVAL;
|
||||
|
||||
cmd->link_id = cpu_to_le32(mld_link->fw_id);
|
||||
|
||||
ctx = wiphy_dereference(mld->wiphy, link->chanctx_conf);
|
||||
if (WARN_ON(!ctx || !ctx->def.chan))
|
||||
return -EINVAL;
|
||||
|
||||
enable_fils = cfg80211_channel_is_psc(ctx->def.chan) ||
|
||||
(ctx->def.chan->band == NL80211_BAND_6GHZ &&
|
||||
ctx->def.width >= NL80211_CHAN_WIDTH_80);
|
||||
|
||||
if (enable_fils) {
|
||||
flags |= IWL_MAC_BEACON_FILS;
|
||||
cmd->short_ssid = cpu_to_le32(~crc32_le(~0, vif->cfg.ssid,
|
||||
vif->cfg.ssid_len));
|
||||
}
|
||||
|
||||
cmd->byte_cnt = cpu_to_le16((u16)beacon->len);
|
||||
|
||||
flags |= iwl_mld_get_rate_flags(mld, info, vif, link,
|
||||
ctx->def.chan->band);
|
||||
|
||||
cmd->flags = cpu_to_le16(flags);
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_AP) {
|
||||
iwl_mld_set_tim_idx(mld, &cmd->tim_idx,
|
||||
beacon->data, beacon->len);
|
||||
|
||||
cmd->btwt_offset =
|
||||
cpu_to_le32(iwl_find_ie_offset(beacon->data,
|
||||
WLAN_EID_S1G_TWT,
|
||||
beacon->len));
|
||||
}
|
||||
|
||||
cmd->csa_offset =
|
||||
cpu_to_le32(iwl_find_ie_offset(beacon->data,
|
||||
WLAN_EID_CHANNEL_SWITCH,
|
||||
beacon->len));
|
||||
cmd->ecsa_offset =
|
||||
cpu_to_le32(iwl_find_ie_offset(beacon->data,
|
||||
WLAN_EID_EXT_CHANSWITCH_ANN,
|
||||
beacon->len));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The beacon template for the AP/GO/IBSS has changed and needs update */
|
||||
int iwl_mld_update_beacon_template(struct iwl_mld *mld,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf)
|
||||
{
|
||||
struct iwl_mac_beacon_cmd cmd = {};
|
||||
struct sk_buff *beacon;
|
||||
int ret;
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
|
||||
#endif
|
||||
|
||||
WARN_ON(vif->type != NL80211_IFTYPE_AP &&
|
||||
vif->type != NL80211_IFTYPE_ADHOC);
|
||||
|
||||
if (IWL_MLD_NON_TRANSMITTING_AP)
|
||||
return 0;
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
if (mld_vif->beacon_inject_active) {
|
||||
IWL_DEBUG_INFO(mld,
|
||||
"Can't update template, beacon injection's active\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
#endif
|
||||
beacon = ieee80211_beacon_get_template(mld->hw, vif, NULL,
|
||||
link_conf->link_id);
|
||||
if (!beacon)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = iwl_mld_fill_beacon_template_cmd(mld, vif, beacon, &cmd,
|
||||
link_conf);
|
||||
|
||||
if (!ret)
|
||||
ret = iwl_mld_send_beacon_template_cmd(mld, beacon, &cmd);
|
||||
|
||||
dev_kfree_skb(beacon);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void iwl_mld_free_ap_early_key(struct iwl_mld *mld,
|
||||
struct ieee80211_key_conf *key,
|
||||
struct iwl_mld_vif *mld_vif)
|
||||
{
|
||||
struct iwl_mld_link *link;
|
||||
|
||||
if (WARN_ON(key->link_id < 0))
|
||||
return;
|
||||
|
||||
link = iwl_mld_link_dereference_check(mld_vif, key->link_id);
|
||||
if (WARN_ON(!link))
|
||||
return;
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(link->ap_early_keys); i++) {
|
||||
if (link->ap_early_keys[i] != key)
|
||||
continue;
|
||||
/* Those weren't sent to FW, so should be marked as INVALID */
|
||||
if (WARN_ON(key->hw_key_idx != STA_KEY_IDX_INVALID))
|
||||
key->hw_key_idx = STA_KEY_IDX_INVALID;
|
||||
link->ap_early_keys[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int iwl_mld_store_ap_early_key(struct iwl_mld *mld,
|
||||
struct ieee80211_key_conf *key,
|
||||
struct iwl_mld_vif *mld_vif)
|
||||
{
|
||||
struct iwl_mld_link *link;
|
||||
|
||||
if (WARN_ON(key->link_id < 0))
|
||||
return -EINVAL;
|
||||
|
||||
link = iwl_mld_link_dereference_check(mld_vif, key->link_id);
|
||||
if (WARN_ON(!link))
|
||||
return -EINVAL;
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(link->ap_early_keys); i++) {
|
||||
if (!link->ap_early_keys[i]) {
|
||||
link->ap_early_keys[i] = key;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
static int iwl_mld_send_ap_early_keys(struct iwl_mld *mld,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link)
|
||||
{
|
||||
struct iwl_mld_link *mld_link = iwl_mld_link_from_mac80211(link);
|
||||
int ret = 0;
|
||||
|
||||
if (WARN_ON(!link))
|
||||
return -EINVAL;
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(mld_link->ap_early_keys); i++) {
|
||||
struct ieee80211_key_conf *key = mld_link->ap_early_keys[i];
|
||||
|
||||
if (!key)
|
||||
continue;
|
||||
|
||||
mld_link->ap_early_keys[i] = NULL;
|
||||
|
||||
ret = iwl_mld_add_key(mld, vif, NULL, key);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iwl_mld_start_ap_ibss(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link)
|
||||
{
|
||||
struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
|
||||
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
|
||||
struct ieee80211_chanctx_conf *ctx;
|
||||
int ret;
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_AP)
|
||||
iwl_mld_send_ap_tx_power_constraint_cmd(mld, vif, link);
|
||||
|
||||
ret = iwl_mld_update_beacon_template(mld, vif, link);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* the link should be already activated when assigning chan context,
|
||||
* and LINK_CONTEXT_MODIFY_EHT_PARAMS is deprecated
|
||||
*/
|
||||
ret = iwl_mld_change_link_in_fw(mld, link,
|
||||
LINK_CONTEXT_MODIFY_ALL &
|
||||
~(LINK_CONTEXT_MODIFY_ACTIVE |
|
||||
LINK_CONTEXT_MODIFY_EHT_PARAMS));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = iwl_mld_add_mcast_sta(mld, vif, link);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mld_vif->ap_ibss_active = true;
|
||||
|
||||
if (vif->p2p && mld->p2p_device_vif) {
|
||||
ret = iwl_mld_mac_fw_action(mld, mld->p2p_device_vif,
|
||||
FW_CTXT_ACTION_MODIFY);
|
||||
if (ret) {
|
||||
mld_vif->ap_ibss_active = false;
|
||||
goto rm_mcast;
|
||||
}
|
||||
}
|
||||
|
||||
ret = iwl_mld_add_bcast_sta(mld, vif, link);
|
||||
if (ret)
|
||||
goto update_p2p_dev;
|
||||
|
||||
/* Those keys were configured by the upper layers before starting the
|
||||
* AP. Now that it is started and the bcast and mcast sta were added to
|
||||
* the FW, we can add the keys too.
|
||||
*/
|
||||
ret = iwl_mld_send_ap_early_keys(mld, vif, link);
|
||||
if (ret)
|
||||
goto rm_bcast;
|
||||
|
||||
if (ieee80211_vif_type_p2p(vif) == NL80211_IFTYPE_AP)
|
||||
iwl_mld_vif_update_low_latency(mld, vif, true,
|
||||
LOW_LATENCY_VIF_TYPE);
|
||||
|
||||
/* When the channel context was added, the link is not yet active, so
|
||||
* min_def is always used. Update the PHY again here in case def should
|
||||
* actually be used.
|
||||
*/
|
||||
ctx = wiphy_dereference(mld->wiphy, link->chanctx_conf);
|
||||
iwl_mld_update_phy_chandef(mld, ctx);
|
||||
|
||||
return 0;
|
||||
rm_bcast:
|
||||
iwl_mld_remove_bcast_sta(mld, vif, link);
|
||||
update_p2p_dev:
|
||||
mld_vif->ap_ibss_active = false;
|
||||
if (vif->p2p && mld->p2p_device_vif)
|
||||
iwl_mld_mac_fw_action(mld, mld->p2p_device_vif,
|
||||
FW_CTXT_ACTION_MODIFY);
|
||||
rm_mcast:
|
||||
iwl_mld_remove_mcast_sta(mld, vif, link);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void iwl_mld_stop_ap_ibss(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link)
|
||||
{
|
||||
struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
|
||||
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
|
||||
|
||||
mld_vif->ap_ibss_active = false;
|
||||
|
||||
if (vif->p2p && mld->p2p_device_vif)
|
||||
iwl_mld_mac_fw_action(mld, mld->p2p_device_vif,
|
||||
FW_CTXT_ACTION_MODIFY);
|
||||
|
||||
if (ieee80211_vif_type_p2p(vif) == NL80211_IFTYPE_AP)
|
||||
iwl_mld_vif_update_low_latency(mld, vif, false,
|
||||
LOW_LATENCY_VIF_TYPE);
|
||||
|
||||
iwl_mld_remove_bcast_sta(mld, vif, link);
|
||||
|
||||
iwl_mld_remove_mcast_sta(mld, vif, link);
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2024 Intel Corporation
|
||||
*/
|
||||
#ifndef __iwl_ap_h__
|
||||
#define __iwl_ap_h__
|
||||
|
||||
#include "mld.h"
|
||||
#include "iface.h"
|
||||
|
||||
#include "fw/api/tx.h"
|
||||
|
||||
int iwl_mld_update_beacon_template(struct iwl_mld *mld,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf);
|
||||
|
||||
int iwl_mld_start_ap_ibss(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link);
|
||||
|
||||
void iwl_mld_stop_ap_ibss(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link);
|
||||
|
||||
int iwl_mld_store_ap_early_key(struct iwl_mld *mld,
|
||||
struct ieee80211_key_conf *key,
|
||||
struct iwl_mld_vif *mld_vif);
|
||||
|
||||
void iwl_mld_free_ap_early_key(struct iwl_mld *mld,
|
||||
struct ieee80211_key_conf *key,
|
||||
struct iwl_mld_vif *mld_vif);
|
||||
|
||||
u8 iwl_mld_get_rate_flags(struct iwl_mld *mld,
|
||||
struct ieee80211_tx_info *info,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link,
|
||||
enum nl80211_band band);
|
||||
|
||||
void iwl_mld_set_tim_idx(struct iwl_mld *mld, __le32 *tim_index,
|
||||
u8 *beacon, u32 frame_size);
|
||||
|
||||
int iwl_mld_send_beacon_template_cmd(struct iwl_mld *mld,
|
||||
struct sk_buff *beacon,
|
||||
struct iwl_mac_beacon_cmd *cmd);
|
||||
|
||||
#endif /* __iwl_ap_h__ */
|
||||
@@ -0,0 +1,40 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2024-2025 Intel Corporation
|
||||
*/
|
||||
|
||||
#include "fw/api/coex.h"
|
||||
|
||||
#include "coex.h"
|
||||
#include "mld.h"
|
||||
#include "hcmd.h"
|
||||
#include "mlo.h"
|
||||
|
||||
int iwl_mld_send_bt_init_conf(struct iwl_mld *mld)
|
||||
{
|
||||
struct iwl_bt_coex_cmd cmd = {
|
||||
.mode = cpu_to_le32(BT_COEX_NW),
|
||||
.enabled_modules = cpu_to_le32(BT_COEX_MPLUT_ENABLED |
|
||||
BT_COEX_HIGH_BAND_RET),
|
||||
};
|
||||
|
||||
return iwl_mld_send_cmd_pdu(mld, BT_CONFIG, &cmd);
|
||||
}
|
||||
|
||||
void iwl_mld_handle_bt_coex_notif(struct iwl_mld *mld,
|
||||
struct iwl_rx_packet *pkt)
|
||||
{
|
||||
const struct iwl_bt_coex_profile_notif *notif = (void *)pkt->data;
|
||||
const struct iwl_bt_coex_profile_notif zero_notif = {};
|
||||
/* zeroed structure means that BT is OFF */
|
||||
bool bt_is_active = memcmp(notif, &zero_notif, sizeof(*notif));
|
||||
|
||||
if (bt_is_active == mld->bt_is_active)
|
||||
return;
|
||||
|
||||
IWL_DEBUG_INFO(mld, "BT was turned %s\n", bt_is_active ? "ON" : "OFF");
|
||||
|
||||
mld->bt_is_active = bt_is_active;
|
||||
|
||||
iwl_mld_emlsr_check_bt(mld);
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2024 Intel Corporation
|
||||
*/
|
||||
#ifndef __iwl_mld_coex_h__
|
||||
#define __iwl_mld_coex_h__
|
||||
|
||||
#include "mld.h"
|
||||
|
||||
int iwl_mld_send_bt_init_conf(struct iwl_mld *mld);
|
||||
|
||||
void iwl_mld_handle_bt_coex_notif(struct iwl_mld *mld,
|
||||
struct iwl_rx_packet *pkt);
|
||||
|
||||
#endif /* __iwl_mld_coex_h__ */
|
||||
@@ -0,0 +1,79 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2024-2025 Intel Corporation
|
||||
*/
|
||||
#ifndef __iwl_mld_constants_h__
|
||||
#define __iwl_mld_constants_h__
|
||||
|
||||
#define IWL_MLD_MISSED_BEACONS_SINCE_RX_THOLD 4
|
||||
#define IWL_MLD_MISSED_BEACONS_THRESHOLD 8
|
||||
#define IWL_MLD_MISSED_BEACONS_THRESHOLD_LONG 19
|
||||
#define IWL_MLD_BCN_LOSS_EXIT_ESR_THRESH_2_LINKS 5
|
||||
#define IWL_MLD_BCN_LOSS_EXIT_ESR_THRESH 15
|
||||
#define IWL_MLD_BCN_LOSS_EXIT_ESR_THRESH_BSS_PARAM_CHANGED 11
|
||||
#define IWL_MLD_LOW_RSSI_MLO_SCAN_THRESH -72
|
||||
|
||||
#define IWL_MLD_DEFAULT_PS_TX_DATA_TIMEOUT (100 * USEC_PER_MSEC)
|
||||
#define IWL_MLD_DEFAULT_PS_RX_DATA_TIMEOUT (100 * USEC_PER_MSEC)
|
||||
#define IWL_MLD_WOWLAN_PS_TX_DATA_TIMEOUT (10 * USEC_PER_MSEC)
|
||||
#define IWL_MLD_WOWLAN_PS_RX_DATA_TIMEOUT (10 * USEC_PER_MSEC)
|
||||
#define IWL_MLD_SHORT_PS_TX_DATA_TIMEOUT (2 * 1024) /* defined in TU */
|
||||
#define IWL_MLD_SHORT_PS_RX_DATA_TIMEOUT (40 * 1024) /* defined in TU */
|
||||
|
||||
#define IWL_MLD_UAPSD_RX_DATA_TIMEOUT (50 * USEC_PER_MSEC)
|
||||
#define IWL_MLD_UAPSD_TX_DATA_TIMEOUT (50 * USEC_PER_MSEC)
|
||||
|
||||
#define IWL_MLD_PS_SNOOZE_INTERVAL 25
|
||||
#define IWL_MLD_PS_SNOOZE_INTERVAL 25
|
||||
#define IWL_MLD_PS_SNOOZE_WINDOW 50
|
||||
|
||||
#define IWL_MLD_PS_SNOOZE_HEAVY_TX_THLD_PACKETS 30
|
||||
#define IWL_MLD_PS_SNOOZE_HEAVY_RX_THLD_PACKETS 20
|
||||
|
||||
#define IWL_MLD_PS_HEAVY_TX_THLD_PERCENT 50
|
||||
#define IWL_MLD_PS_HEAVY_RX_THLD_PERCENT 50
|
||||
#define IWL_MLD_PS_HEAVY_TX_THLD_PACKETS 20
|
||||
#define IWL_MLD_PS_HEAVY_RX_THLD_PACKETS 8
|
||||
|
||||
#define IWL_MLD_TRIGGER_LINK_SEL_TIME_SEC 30
|
||||
#define IWL_MLD_SCAN_EXPIRE_TIME_SEC 20
|
||||
|
||||
#define IWL_MLD_TPT_COUNT_WINDOW (5 * HZ)
|
||||
|
||||
#define IWL_MLD_DIS_RANDOM_FW_ID false
|
||||
#define IWL_MLD_D3_DEBUG false
|
||||
#define IWL_MLD_NON_TRANSMITTING_AP false
|
||||
#define IWL_MLD_6GHZ_PASSIVE_SCAN_TIMEOUT 3000 /* in seconds */
|
||||
#define IWL_MLD_6GHZ_PASSIVE_SCAN_ASSOC_TIMEOUT 60 /* in seconds */
|
||||
#define IWL_MLD_CONN_LISTEN_INTERVAL 10
|
||||
#define IWL_MLD_ADAPTIVE_DWELL_NUM_APS_OVERRIDE 0
|
||||
#define IWL_MLD_AUTO_EML_ENABLE true
|
||||
|
||||
#define IWL_MLD_HIGH_RSSI_THRESH_20MHZ -67
|
||||
#define IWL_MLD_LOW_RSSI_THRESH_20MHZ -72
|
||||
#define IWL_MLD_HIGH_RSSI_THRESH_40MHZ -64
|
||||
#define IWL_MLD_LOW_RSSI_THRESH_40MHZ -72
|
||||
#define IWL_MLD_HIGH_RSSI_THRESH_80MHZ -61
|
||||
#define IWL_MLD_LOW_RSSI_THRESH_80MHZ -72
|
||||
#define IWL_MLD_HIGH_RSSI_THRESH_160MHZ -58
|
||||
#define IWL_MLD_LOW_RSSI_THRESH_160MHZ -72
|
||||
|
||||
#define IWL_MLD_ENTER_EMLSR_TPT_THRESH 400
|
||||
#define IWL_MLD_EXIT_EMLSR_CHAN_LOAD 2 /* in percentage */
|
||||
|
||||
#define IWL_MLD_FTM_INITIATOR_ALGO IWL_TOF_ALGO_TYPE_MAX_LIKE
|
||||
#define IWL_MLD_FTM_INITIATOR_DYNACK true
|
||||
#define IWL_MLD_FTM_LMR_FEEDBACK_TERMINATE false
|
||||
#define IWL_MLD_FTM_TEST_INCORRECT_SAC false
|
||||
#define IWL_MLD_FTM_R2I_MAX_REP 7
|
||||
#define IWL_MLD_FTM_I2R_MAX_REP 7
|
||||
#define IWL_MLD_FTM_R2I_MAX_STS 1
|
||||
#define IWL_MLD_FTM_I2R_MAX_STS 1
|
||||
#define IWL_MLD_FTM_R2I_MAX_TOTAL_LTF 3
|
||||
#define IWL_MLD_FTM_I2R_MAX_TOTAL_LTF 3
|
||||
#define IWL_MLD_FTM_RESP_NDP_SUPPORT true
|
||||
#define IWL_MLD_FTM_RESP_LMR_FEEDBACK_SUPPORT true
|
||||
#define IWL_MLD_FTM_NON_TB_MIN_TIME_BETWEEN_MSR 7
|
||||
#define IWL_MLD_FTM_NON_TB_MAX_TIME_BETWEEN_MSR 1000
|
||||
|
||||
#endif /* __iwl_mld_constants_h__ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,51 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2024 Intel Corporation
|
||||
*/
|
||||
#ifndef __iwl_mld_d3_h__
|
||||
#define __iwl_mld_d3_h__
|
||||
|
||||
#include "fw/api/d3.h"
|
||||
|
||||
struct iwl_mld_rekey_data {
|
||||
bool valid;
|
||||
u8 kck[NL80211_KCK_EXT_LEN];
|
||||
u8 kek[NL80211_KEK_EXT_LEN];
|
||||
size_t kck_len;
|
||||
size_t kek_len;
|
||||
__le64 replay_ctr;
|
||||
u32 akm;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_mld_wowlan_data - data used by the wowlan suspend flow
|
||||
*
|
||||
* @target_ipv6_addrs: IPv6 addresses on this interface for offload
|
||||
* @tentative_addrs: bitmap of tentative IPv6 addresses in @target_ipv6_addrs
|
||||
* @num_target_ipv6_addrs: number of @target_ipv6_addrs
|
||||
* @rekey_data: security key data used for rekeying during D3
|
||||
*/
|
||||
struct iwl_mld_wowlan_data {
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
struct in6_addr target_ipv6_addrs[IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_MAX];
|
||||
unsigned long tentative_addrs[BITS_TO_LONGS(IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_MAX)];
|
||||
int num_target_ipv6_addrs;
|
||||
#endif
|
||||
struct iwl_mld_rekey_data rekey_data;
|
||||
};
|
||||
|
||||
int iwl_mld_no_wowlan_resume(struct iwl_mld *mld);
|
||||
int iwl_mld_no_wowlan_suspend(struct iwl_mld *mld);
|
||||
int iwl_mld_wowlan_suspend(struct iwl_mld *mld,
|
||||
struct cfg80211_wowlan *wowlan);
|
||||
int iwl_mld_wowlan_resume(struct iwl_mld *mld);
|
||||
void iwl_mld_set_rekey_data(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct cfg80211_gtk_rekey_data *data);
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
void iwl_mld_ipv6_addr_change(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct inet6_dev *idev);
|
||||
#endif
|
||||
|
||||
#endif /* __iwl_mld_d3_h__ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,244 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2024-2025 Intel Corporation
|
||||
*/
|
||||
#include "iface.h"
|
||||
#include "sta.h"
|
||||
|
||||
#define MLD_DEBUGFS_OPEN_WRAPPER(name, buflen, argtype) \
|
||||
struct dbgfs_##name##_data { \
|
||||
argtype *arg; \
|
||||
bool read_done; \
|
||||
ssize_t rlen; \
|
||||
char buf[buflen]; \
|
||||
}; \
|
||||
static int _iwl_dbgfs_##name##_open(struct inode *inode, \
|
||||
struct file *file) \
|
||||
{ \
|
||||
struct dbgfs_##name##_data *data; \
|
||||
\
|
||||
if ((file->f_flags & O_ACCMODE) == O_RDWR) \
|
||||
return -EOPNOTSUPP; \
|
||||
\
|
||||
data = kzalloc(sizeof(*data), GFP_KERNEL); \
|
||||
if (!data) \
|
||||
return -ENOMEM; \
|
||||
\
|
||||
data->read_done = false; \
|
||||
data->arg = inode->i_private; \
|
||||
file->private_data = data; \
|
||||
\
|
||||
return 0; \
|
||||
}
|
||||
|
||||
#define MLD_DEBUGFS_READ_WRAPPER(name) \
|
||||
static ssize_t _iwl_dbgfs_##name##_read(struct file *file, \
|
||||
char __user *user_buf, \
|
||||
size_t count, loff_t *ppos) \
|
||||
{ \
|
||||
struct dbgfs_##name##_data *data = file->private_data; \
|
||||
\
|
||||
if (!data->read_done) { \
|
||||
data->read_done = true; \
|
||||
data->rlen = iwl_dbgfs_##name##_read(data->arg, \
|
||||
sizeof(data->buf),\
|
||||
data->buf); \
|
||||
} \
|
||||
\
|
||||
if (data->rlen < 0) \
|
||||
return data->rlen; \
|
||||
return simple_read_from_buffer(user_buf, count, ppos, \
|
||||
data->buf, data->rlen); \
|
||||
}
|
||||
|
||||
static int _iwl_dbgfs_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
kfree(file->private_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define _MLD_DEBUGFS_READ_FILE_OPS(name, buflen, argtype) \
|
||||
MLD_DEBUGFS_OPEN_WRAPPER(name, buflen, argtype) \
|
||||
MLD_DEBUGFS_READ_WRAPPER(name) \
|
||||
static const struct file_operations iwl_dbgfs_##name##_ops = { \
|
||||
.read = _iwl_dbgfs_##name##_read, \
|
||||
.open = _iwl_dbgfs_##name##_open, \
|
||||
.llseek = generic_file_llseek, \
|
||||
.release = _iwl_dbgfs_release, \
|
||||
}
|
||||
|
||||
#define WIPHY_DEBUGFS_WRITE_HANDLER_WRAPPER(name) \
|
||||
static ssize_t iwl_dbgfs_##name##_write_handler(struct wiphy *wiphy, \
|
||||
struct file *file, char *buf, \
|
||||
size_t count, void *data) \
|
||||
{ \
|
||||
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); \
|
||||
struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw); \
|
||||
return iwl_dbgfs_##name##_write(mld, buf, count, data); \
|
||||
}
|
||||
|
||||
static inline struct iwl_mld *
|
||||
iwl_mld_from_link_sta(struct ieee80211_link_sta *link_sta)
|
||||
{
|
||||
struct ieee80211_vif *vif =
|
||||
iwl_mld_sta_from_mac80211(link_sta->sta)->vif;
|
||||
return iwl_mld_vif_from_mac80211(vif)->mld;
|
||||
}
|
||||
|
||||
static inline struct iwl_mld *
|
||||
iwl_mld_from_bss_conf(struct ieee80211_bss_conf *link)
|
||||
{
|
||||
return iwl_mld_vif_from_mac80211(link->vif)->mld;
|
||||
}
|
||||
|
||||
static inline struct iwl_mld *iwl_mld_from_vif(struct ieee80211_vif *vif)
|
||||
{
|
||||
return iwl_mld_vif_from_mac80211(vif)->mld;
|
||||
}
|
||||
|
||||
#define WIPHY_DEBUGFS_WRITE_WRAPPER(name, bufsz, objtype) \
|
||||
WIPHY_DEBUGFS_WRITE_HANDLER_WRAPPER(name) \
|
||||
static ssize_t __iwl_dbgfs_##name##_write(struct file *file, \
|
||||
const char __user *user_buf, \
|
||||
size_t count, loff_t *ppos) \
|
||||
{ \
|
||||
struct ieee80211_##objtype *arg = file->private_data; \
|
||||
struct iwl_mld *mld = iwl_mld_from_##objtype(arg); \
|
||||
char buf[bufsz] = {}; \
|
||||
\
|
||||
return wiphy_locked_debugfs_write(mld->wiphy, file, \
|
||||
buf, sizeof(buf), \
|
||||
user_buf, count, \
|
||||
iwl_dbgfs_##name##_write_handler, \
|
||||
arg); \
|
||||
}
|
||||
|
||||
#define WIPHY_DEBUGFS_WRITE_FILE_OPS(name, bufsz, objtype) \
|
||||
WIPHY_DEBUGFS_WRITE_WRAPPER(name, bufsz, objtype) \
|
||||
static const struct file_operations iwl_dbgfs_##name##_ops = { \
|
||||
.write = __iwl_dbgfs_##name##_write, \
|
||||
.open = simple_open, \
|
||||
.llseek = generic_file_llseek, \
|
||||
}
|
||||
|
||||
#define WIPHY_DEBUGFS_READ_HANDLER_WRAPPER_MLD(name) \
|
||||
static ssize_t iwl_dbgfs_##name##_read_handler(struct wiphy *wiphy, \
|
||||
struct file *file, char *buf, \
|
||||
size_t count, void *data) \
|
||||
{ \
|
||||
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); \
|
||||
struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw); \
|
||||
return iwl_dbgfs_##name##_read(mld, buf, count); \
|
||||
}
|
||||
|
||||
#define WIPHY_DEBUGFS_WRITE_HANDLER_WRAPPER_MLD(name) \
|
||||
static ssize_t iwl_dbgfs_##name##_write_handler(struct wiphy *wiphy, \
|
||||
struct file *file, char *buf, \
|
||||
size_t count, void *data) \
|
||||
{ \
|
||||
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); \
|
||||
struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw); \
|
||||
return iwl_dbgfs_##name##_write(mld, buf, count); \
|
||||
}
|
||||
|
||||
#define WIPHY_DEBUGFS_WRITE_WRAPPER_MLD(name) \
|
||||
WIPHY_DEBUGFS_WRITE_HANDLER_WRAPPER_MLD(name) \
|
||||
static ssize_t __iwl_dbgfs_##name##_write(struct file *file, \
|
||||
const char __user *user_buf, \
|
||||
size_t count, loff_t *ppos) \
|
||||
{ \
|
||||
struct dbgfs_##name##_data *data = file->private_data; \
|
||||
struct iwl_mld *mld = data->arg; \
|
||||
\
|
||||
return wiphy_locked_debugfs_write(mld->wiphy, file, \
|
||||
data->buf, sizeof(data->buf), \
|
||||
user_buf, count, \
|
||||
iwl_dbgfs_##name##_write_handler, \
|
||||
NULL); \
|
||||
}
|
||||
|
||||
#define WIPHY_DEBUGFS_READ_WRAPPER_MLD(name) \
|
||||
WIPHY_DEBUGFS_READ_HANDLER_WRAPPER_MLD(name) \
|
||||
static ssize_t __iwl_dbgfs_##name##_read(struct file *file, \
|
||||
char __user *user_buf, \
|
||||
size_t count, loff_t *ppos) \
|
||||
{ \
|
||||
struct dbgfs_##name##_data *data = file->private_data; \
|
||||
struct iwl_mld *mld = data->arg; \
|
||||
\
|
||||
if (!data->read_done) { \
|
||||
data->read_done = true; \
|
||||
data->rlen = wiphy_locked_debugfs_read(mld->wiphy, \
|
||||
file, data->buf, sizeof(data->buf), \
|
||||
user_buf, count, ppos, \
|
||||
iwl_dbgfs_##name##_read_handler, NULL); \
|
||||
return data->rlen; \
|
||||
} \
|
||||
\
|
||||
if (data->rlen < 0) \
|
||||
return data->rlen; \
|
||||
return simple_read_from_buffer(user_buf, count, ppos, \
|
||||
data->buf, data->rlen); \
|
||||
}
|
||||
|
||||
#define WIPHY_DEBUGFS_READ_FILE_OPS_MLD(name, bufsz) \
|
||||
MLD_DEBUGFS_OPEN_WRAPPER(name, bufsz, struct iwl_mld) \
|
||||
WIPHY_DEBUGFS_READ_WRAPPER_MLD(name) \
|
||||
static const struct file_operations iwl_dbgfs_##name##_ops = { \
|
||||
.read = __iwl_dbgfs_##name##_read, \
|
||||
.open = _iwl_dbgfs_##name##_open, \
|
||||
.llseek = generic_file_llseek, \
|
||||
.release = _iwl_dbgfs_release, \
|
||||
}
|
||||
|
||||
#define WIPHY_DEBUGFS_WRITE_FILE_OPS_MLD(name, bufsz) \
|
||||
MLD_DEBUGFS_OPEN_WRAPPER(name, bufsz, struct iwl_mld) \
|
||||
WIPHY_DEBUGFS_WRITE_WRAPPER_MLD(name) \
|
||||
static const struct file_operations iwl_dbgfs_##name##_ops = { \
|
||||
.write = __iwl_dbgfs_##name##_write, \
|
||||
.open = _iwl_dbgfs_##name##_open, \
|
||||
.llseek = generic_file_llseek, \
|
||||
.release = _iwl_dbgfs_release, \
|
||||
}
|
||||
|
||||
#define WIPHY_DEBUGFS_READ_WRITE_FILE_OPS_MLD(name, bufsz) \
|
||||
MLD_DEBUGFS_OPEN_WRAPPER(name, bufsz, struct iwl_mld) \
|
||||
WIPHY_DEBUGFS_WRITE_WRAPPER_MLD(name) \
|
||||
WIPHY_DEBUGFS_READ_WRAPPER_MLD(name) \
|
||||
static const struct file_operations iwl_dbgfs_##name##_ops = { \
|
||||
.write = __iwl_dbgfs_##name##_write, \
|
||||
.read = __iwl_dbgfs_##name##_read, \
|
||||
.open = _iwl_dbgfs_##name##_open, \
|
||||
.llseek = generic_file_llseek, \
|
||||
.release = _iwl_dbgfs_release, \
|
||||
}
|
||||
|
||||
#define WIPHY_DEBUGFS_WRITE_WRAPPER_IEEE80211(name, bufsz, objtype) \
|
||||
WIPHY_DEBUGFS_WRITE_HANDLER_WRAPPER(name) \
|
||||
static ssize_t _iwl_dbgfs_##name##_write(struct file *file, \
|
||||
const char __user *user_buf, \
|
||||
size_t count, loff_t *ppos) \
|
||||
{ \
|
||||
struct dbgfs_##name##_data *data = file->private_data; \
|
||||
struct ieee80211_##objtype *arg = data->arg; \
|
||||
struct iwl_mld *mld = iwl_mld_from_##objtype(arg); \
|
||||
char buf[bufsz] = {}; \
|
||||
\
|
||||
return wiphy_locked_debugfs_write(mld->wiphy, file, \
|
||||
buf, sizeof(buf), \
|
||||
user_buf, count, \
|
||||
iwl_dbgfs_##name##_write_handler, \
|
||||
arg); \
|
||||
}
|
||||
|
||||
#define IEEE80211_WIPHY_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, objtype) \
|
||||
MLD_DEBUGFS_OPEN_WRAPPER(name, bufsz, struct ieee80211_##objtype) \
|
||||
WIPHY_DEBUGFS_WRITE_WRAPPER_IEEE80211(name, bufsz, objtype) \
|
||||
MLD_DEBUGFS_READ_WRAPPER(name) \
|
||||
static const struct file_operations iwl_dbgfs_##name##_ops = { \
|
||||
.write = _iwl_dbgfs_##name##_write, \
|
||||
.read = _iwl_dbgfs_##name##_read, \
|
||||
.open = _iwl_dbgfs_##name##_open, \
|
||||
.llseek = generic_file_llseek, \
|
||||
.release = _iwl_dbgfs_release, \
|
||||
}
|
||||
@@ -0,0 +1,451 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2025 Intel Corporation
|
||||
*/
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/math64.h>
|
||||
#include <net/cfg80211.h>
|
||||
#include "mld.h"
|
||||
#include "iface.h"
|
||||
#include "phy.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-prph.h"
|
||||
#include "constants.h"
|
||||
#include "fw/api/location.h"
|
||||
#include "ftm-initiator.h"
|
||||
|
||||
static void iwl_mld_ftm_cmd_common(struct iwl_mld *mld,
|
||||
struct ieee80211_vif *vif,
|
||||
struct iwl_tof_range_req_cmd *cmd,
|
||||
struct cfg80211_pmsr_request *req)
|
||||
{
|
||||
int i;
|
||||
|
||||
cmd->initiator_flags =
|
||||
cpu_to_le32(IWL_TOF_INITIATOR_FLAGS_MACADDR_RANDOM |
|
||||
IWL_TOF_INITIATOR_FLAGS_NON_ASAP_SUPPORT);
|
||||
cmd->request_id = req->cookie;
|
||||
cmd->num_of_ap = req->n_peers;
|
||||
|
||||
/* Use a large value for "no timeout". Don't use the maximum value
|
||||
* because of fw limitations.
|
||||
*/
|
||||
if (req->timeout)
|
||||
cmd->req_timeout_ms = cpu_to_le32(min(req->timeout, 0xfffff));
|
||||
else
|
||||
cmd->req_timeout_ms = cpu_to_le32(0xfffff);
|
||||
|
||||
memcpy(cmd->macaddr_template, req->mac_addr, ETH_ALEN);
|
||||
for (i = 0; i < ETH_ALEN; i++)
|
||||
cmd->macaddr_mask[i] = ~req->mac_addr_mask[i];
|
||||
|
||||
if (vif->cfg.assoc) {
|
||||
memcpy(cmd->range_req_bssid, vif->bss_conf.bssid, ETH_ALEN);
|
||||
|
||||
/* AP's TSF is only relevant if associated */
|
||||
for (i = 0; i < req->n_peers; i++) {
|
||||
if (req->peers[i].report_ap_tsf) {
|
||||
struct iwl_mld_vif *mld_vif =
|
||||
iwl_mld_vif_from_mac80211(vif);
|
||||
|
||||
cmd->tsf_mac_id = cpu_to_le32(mld_vif->fw_id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
eth_broadcast_addr(cmd->range_req_bssid);
|
||||
}
|
||||
|
||||
/* Don't report AP's TSF */
|
||||
cmd->tsf_mac_id = cpu_to_le32(0xff);
|
||||
}
|
||||
|
||||
static int
|
||||
iwl_mld_ftm_set_target_chandef(struct iwl_mld *mld,
|
||||
struct cfg80211_pmsr_request_peer *peer,
|
||||
struct iwl_tof_range_req_ap_entry *target)
|
||||
{
|
||||
u32 freq = peer->chandef.chan->center_freq;
|
||||
|
||||
target->channel_num = ieee80211_frequency_to_channel(freq);
|
||||
|
||||
switch (peer->chandef.width) {
|
||||
case NL80211_CHAN_WIDTH_20_NOHT:
|
||||
target->format_bw = IWL_LOCATION_FRAME_FORMAT_LEGACY;
|
||||
target->format_bw |= IWL_LOCATION_BW_20MHZ << LOCATION_BW_POS;
|
||||
break;
|
||||
case NL80211_CHAN_WIDTH_20:
|
||||
target->format_bw = IWL_LOCATION_FRAME_FORMAT_HT;
|
||||
target->format_bw |= IWL_LOCATION_BW_20MHZ << LOCATION_BW_POS;
|
||||
break;
|
||||
case NL80211_CHAN_WIDTH_40:
|
||||
target->format_bw = IWL_LOCATION_FRAME_FORMAT_HT;
|
||||
target->format_bw |= IWL_LOCATION_BW_40MHZ << LOCATION_BW_POS;
|
||||
break;
|
||||
case NL80211_CHAN_WIDTH_80:
|
||||
target->format_bw = IWL_LOCATION_FRAME_FORMAT_VHT;
|
||||
target->format_bw |= IWL_LOCATION_BW_80MHZ << LOCATION_BW_POS;
|
||||
break;
|
||||
case NL80211_CHAN_WIDTH_160:
|
||||
target->format_bw = IWL_LOCATION_FRAME_FORMAT_HE;
|
||||
target->format_bw |= IWL_LOCATION_BW_160MHZ << LOCATION_BW_POS;
|
||||
break;
|
||||
default:
|
||||
IWL_ERR(mld, "Unsupported BW in FTM request (%d)\n",
|
||||
peer->chandef.width);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* non EDCA based measurement must use HE preamble */
|
||||
if (peer->ftm.trigger_based || peer->ftm.non_trigger_based)
|
||||
target->format_bw |= IWL_LOCATION_FRAME_FORMAT_HE;
|
||||
|
||||
target->ctrl_ch_position =
|
||||
(peer->chandef.width > NL80211_CHAN_WIDTH_20) ?
|
||||
iwl_mld_get_fw_ctrl_pos(&peer->chandef) : 0;
|
||||
|
||||
target->band = iwl_mld_nl80211_band_to_fw(peer->chandef.chan->band);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define FTM_SET_FLAG(flag) (target->initiator_ap_flags |= \
|
||||
cpu_to_le32(IWL_INITIATOR_AP_FLAGS_##flag))
|
||||
|
||||
static void
|
||||
iwl_mld_ftm_set_target_flags(struct iwl_mld *mld,
|
||||
struct cfg80211_pmsr_request_peer *peer,
|
||||
struct iwl_tof_range_req_ap_entry *target)
|
||||
{
|
||||
target->initiator_ap_flags = cpu_to_le32(0);
|
||||
|
||||
if (peer->ftm.asap)
|
||||
FTM_SET_FLAG(ASAP);
|
||||
|
||||
if (peer->ftm.request_lci)
|
||||
FTM_SET_FLAG(LCI_REQUEST);
|
||||
|
||||
if (peer->ftm.request_civicloc)
|
||||
FTM_SET_FLAG(CIVIC_REQUEST);
|
||||
|
||||
if (IWL_MLD_FTM_INITIATOR_DYNACK)
|
||||
FTM_SET_FLAG(DYN_ACK);
|
||||
|
||||
if (IWL_MLD_FTM_INITIATOR_ALGO == IWL_TOF_ALGO_TYPE_LINEAR_REG)
|
||||
FTM_SET_FLAG(ALGO_LR);
|
||||
else if (IWL_MLD_FTM_INITIATOR_ALGO == IWL_TOF_ALGO_TYPE_FFT)
|
||||
FTM_SET_FLAG(ALGO_FFT);
|
||||
|
||||
if (peer->ftm.trigger_based)
|
||||
FTM_SET_FLAG(TB);
|
||||
else if (peer->ftm.non_trigger_based)
|
||||
FTM_SET_FLAG(NON_TB);
|
||||
|
||||
if ((peer->ftm.trigger_based || peer->ftm.non_trigger_based) &&
|
||||
peer->ftm.lmr_feedback)
|
||||
FTM_SET_FLAG(LMR_FEEDBACK);
|
||||
}
|
||||
|
||||
static void iwl_mld_ftm_set_sta(struct iwl_mld *mld, struct ieee80211_vif *vif,
|
||||
struct cfg80211_pmsr_request_peer *peer,
|
||||
struct iwl_tof_range_req_ap_entry *target)
|
||||
{
|
||||
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
|
||||
u32 sta_id_mask;
|
||||
|
||||
target->sta_id = IWL_INVALID_STA;
|
||||
|
||||
/* TODO: add ftm_unprotected debugfs support */
|
||||
|
||||
if (!vif->cfg.assoc || !mld_vif->ap_sta)
|
||||
return;
|
||||
|
||||
sta_id_mask = iwl_mld_fw_sta_id_mask(mld, mld_vif->ap_sta);
|
||||
if (WARN_ON(hweight32(sta_id_mask) != 1))
|
||||
return;
|
||||
|
||||
target->sta_id = __ffs(sta_id_mask);
|
||||
|
||||
if (mld_vif->ap_sta->mfp &&
|
||||
(peer->ftm.trigger_based || peer->ftm.non_trigger_based))
|
||||
FTM_SET_FLAG(PMF);
|
||||
}
|
||||
|
||||
static int
|
||||
iwl_mld_ftm_set_target(struct iwl_mld *mld, struct ieee80211_vif *vif,
|
||||
struct cfg80211_pmsr_request_peer *peer,
|
||||
struct iwl_tof_range_req_ap_entry *target)
|
||||
{
|
||||
u32 i2r_max_sts;
|
||||
int ret;
|
||||
|
||||
ret = iwl_mld_ftm_set_target_chandef(mld, peer, target);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
memcpy(target->bssid, peer->addr, ETH_ALEN);
|
||||
target->burst_period = cpu_to_le16(peer->ftm.burst_period);
|
||||
target->samples_per_burst = peer->ftm.ftms_per_burst;
|
||||
target->num_of_bursts = peer->ftm.num_bursts_exp;
|
||||
iwl_mld_ftm_set_target_flags(mld, peer, target);
|
||||
iwl_mld_ftm_set_sta(mld, vif, peer, target);
|
||||
|
||||
/* TODO: add secured ranging support */
|
||||
|
||||
i2r_max_sts = IWL_MLD_FTM_I2R_MAX_STS > 1 ? 1 :
|
||||
IWL_MLD_FTM_I2R_MAX_STS;
|
||||
|
||||
target->r2i_ndp_params = IWL_MLD_FTM_R2I_MAX_REP |
|
||||
(IWL_MLD_FTM_R2I_MAX_STS << IWL_LOCATION_MAX_STS_POS) |
|
||||
(IWL_MLD_FTM_R2I_MAX_TOTAL_LTF << IWL_LOCATION_TOTAL_LTF_POS);
|
||||
target->i2r_ndp_params = IWL_MLD_FTM_I2R_MAX_REP |
|
||||
(i2r_max_sts << IWL_LOCATION_MAX_STS_POS) |
|
||||
(IWL_MLD_FTM_I2R_MAX_TOTAL_LTF << IWL_LOCATION_TOTAL_LTF_POS);
|
||||
|
||||
if (peer->ftm.non_trigger_based) {
|
||||
target->min_time_between_msr =
|
||||
cpu_to_le16(IWL_MLD_FTM_NON_TB_MIN_TIME_BETWEEN_MSR);
|
||||
target->burst_period =
|
||||
cpu_to_le16(IWL_MLD_FTM_NON_TB_MAX_TIME_BETWEEN_MSR);
|
||||
} else {
|
||||
target->min_time_between_msr = cpu_to_le16(0);
|
||||
}
|
||||
|
||||
/* TODO: Beacon interval is currently unknown, so use the common value
|
||||
* of 100 TUs.
|
||||
*/
|
||||
target->beacon_interval = cpu_to_le16(100);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iwl_mld_ftm_start(struct iwl_mld *mld, struct ieee80211_vif *vif,
|
||||
struct cfg80211_pmsr_request *req)
|
||||
{
|
||||
struct iwl_tof_range_req_cmd cmd;
|
||||
struct iwl_host_cmd hcmd = {
|
||||
.id = WIDE_ID(LOCATION_GROUP, TOF_RANGE_REQ_CMD),
|
||||
.dataflags[0] = IWL_HCMD_DFL_DUP,
|
||||
.data[0] = &cmd,
|
||||
.len[0] = sizeof(cmd),
|
||||
};
|
||||
u8 i;
|
||||
int ret;
|
||||
|
||||
lockdep_assert_wiphy(mld->wiphy);
|
||||
|
||||
if (mld->ftm_initiator.req)
|
||||
return -EBUSY;
|
||||
|
||||
if (req->n_peers > ARRAY_SIZE(cmd.ap))
|
||||
return -EINVAL;
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
|
||||
iwl_mld_ftm_cmd_common(mld, vif, (void *)&cmd, req);
|
||||
|
||||
for (i = 0; i < cmd.num_of_ap; i++) {
|
||||
struct cfg80211_pmsr_request_peer *peer = &req->peers[i];
|
||||
struct iwl_tof_range_req_ap_entry *target = &cmd.ap[i];
|
||||
|
||||
ret = iwl_mld_ftm_set_target(mld, vif, peer, target);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* TODO: get the status from the response*/
|
||||
ret = iwl_mld_send_cmd(mld, &hcmd);
|
||||
if (!ret) {
|
||||
mld->ftm_initiator.req = req;
|
||||
mld->ftm_initiator.req_wdev = ieee80211_vif_to_wdev(vif);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void iwl_mld_ftm_reset(struct iwl_mld *mld)
|
||||
{
|
||||
lockdep_assert_wiphy(mld->wiphy);
|
||||
|
||||
mld->ftm_initiator.req = NULL;
|
||||
mld->ftm_initiator.req_wdev = NULL;
|
||||
memset(mld->ftm_initiator.responses, 0,
|
||||
sizeof(mld->ftm_initiator.responses));
|
||||
}
|
||||
|
||||
static int iwl_mld_ftm_range_resp_valid(struct iwl_mld *mld, u8 request_id,
|
||||
u8 num_of_aps)
|
||||
{
|
||||
if (IWL_FW_CHECK(mld, request_id != (u8)mld->ftm_initiator.req->cookie,
|
||||
"Request ID mismatch, got %u, active %u\n",
|
||||
request_id, (u8)mld->ftm_initiator.req->cookie))
|
||||
return -EINVAL;
|
||||
|
||||
if (IWL_FW_CHECK(mld, num_of_aps > mld->ftm_initiator.req->n_peers ||
|
||||
num_of_aps > IWL_TOF_MAX_APS,
|
||||
"FTM range response: invalid num of APs (%u)\n",
|
||||
num_of_aps))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwl_mld_ftm_find_peer(struct cfg80211_pmsr_request *req,
|
||||
const u8 *addr)
|
||||
{
|
||||
for (int i = 0; i < req->n_peers; i++) {
|
||||
struct cfg80211_pmsr_request_peer *peer = &req->peers[i];
|
||||
|
||||
if (ether_addr_equal_unaligned(peer->addr, addr))
|
||||
return i;
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static void iwl_mld_debug_range_resp(struct iwl_mld *mld, u8 index,
|
||||
struct cfg80211_pmsr_result *res)
|
||||
{
|
||||
s64 rtt_avg = div_s64(res->ftm.rtt_avg * 100, 6666);
|
||||
|
||||
IWL_DEBUG_INFO(mld, "entry %d\n", index);
|
||||
IWL_DEBUG_INFO(mld, "\tstatus: %d\n", res->status);
|
||||
IWL_DEBUG_INFO(mld, "\tBSSID: %pM\n", res->addr);
|
||||
IWL_DEBUG_INFO(mld, "\thost time: %llu\n", res->host_time);
|
||||
IWL_DEBUG_INFO(mld, "\tburst index: %d\n", res->ftm.burst_index);
|
||||
IWL_DEBUG_INFO(mld, "\tsuccess num: %u\n", res->ftm.num_ftmr_successes);
|
||||
IWL_DEBUG_INFO(mld, "\trssi: %d\n", res->ftm.rssi_avg);
|
||||
IWL_DEBUG_INFO(mld, "\trssi spread: %d\n", res->ftm.rssi_spread);
|
||||
IWL_DEBUG_INFO(mld, "\trtt: %lld\n", res->ftm.rtt_avg);
|
||||
IWL_DEBUG_INFO(mld, "\trtt var: %llu\n", res->ftm.rtt_variance);
|
||||
IWL_DEBUG_INFO(mld, "\trtt spread: %llu\n", res->ftm.rtt_spread);
|
||||
IWL_DEBUG_INFO(mld, "\tdistance: %lld\n", rtt_avg);
|
||||
}
|
||||
|
||||
void iwl_mld_handle_ftm_resp_notif(struct iwl_mld *mld,
|
||||
struct iwl_rx_packet *pkt)
|
||||
{
|
||||
struct iwl_tof_range_rsp_ntfy *fw_resp = (void *)pkt->data;
|
||||
u8 num_of_aps, last_in_batch;
|
||||
|
||||
if (IWL_FW_CHECK(mld, !mld->ftm_initiator.req,
|
||||
"FTM response without a pending request\n"))
|
||||
return;
|
||||
|
||||
if (iwl_mld_ftm_range_resp_valid(mld, fw_resp->request_id,
|
||||
fw_resp->num_of_aps))
|
||||
return;
|
||||
|
||||
num_of_aps = fw_resp->num_of_aps;
|
||||
last_in_batch = fw_resp->last_report;
|
||||
|
||||
IWL_DEBUG_INFO(mld, "Range response received\n");
|
||||
IWL_DEBUG_INFO(mld, "request id: %llu, num of entries: %u\n",
|
||||
mld->ftm_initiator.req->cookie, num_of_aps);
|
||||
|
||||
for (int i = 0; i < num_of_aps; i++) {
|
||||
struct cfg80211_pmsr_result result = {};
|
||||
struct iwl_tof_range_rsp_ap_entry_ntfy *fw_ap;
|
||||
int peer_idx;
|
||||
|
||||
fw_ap = &fw_resp->ap[i];
|
||||
result.final = fw_ap->last_burst;
|
||||
result.ap_tsf = le32_to_cpu(fw_ap->start_tsf);
|
||||
result.ap_tsf_valid = 1;
|
||||
|
||||
peer_idx = iwl_mld_ftm_find_peer(mld->ftm_initiator.req,
|
||||
fw_ap->bssid);
|
||||
if (peer_idx < 0) {
|
||||
IWL_WARN(mld,
|
||||
"Unknown address (%pM, target #%d) in FTM response\n",
|
||||
fw_ap->bssid, i);
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (fw_ap->measure_status) {
|
||||
case IWL_TOF_ENTRY_SUCCESS:
|
||||
result.status = NL80211_PMSR_STATUS_SUCCESS;
|
||||
break;
|
||||
case IWL_TOF_ENTRY_TIMING_MEASURE_TIMEOUT:
|
||||
result.status = NL80211_PMSR_STATUS_TIMEOUT;
|
||||
break;
|
||||
case IWL_TOF_ENTRY_NO_RESPONSE:
|
||||
result.status = NL80211_PMSR_STATUS_FAILURE;
|
||||
result.ftm.failure_reason =
|
||||
NL80211_PMSR_FTM_FAILURE_NO_RESPONSE;
|
||||
break;
|
||||
case IWL_TOF_ENTRY_REQUEST_REJECTED:
|
||||
result.status = NL80211_PMSR_STATUS_FAILURE;
|
||||
result.ftm.failure_reason =
|
||||
NL80211_PMSR_FTM_FAILURE_PEER_BUSY;
|
||||
result.ftm.busy_retry_time = fw_ap->refusal_period;
|
||||
break;
|
||||
default:
|
||||
result.status = NL80211_PMSR_STATUS_FAILURE;
|
||||
result.ftm.failure_reason =
|
||||
NL80211_PMSR_FTM_FAILURE_UNSPECIFIED;
|
||||
break;
|
||||
}
|
||||
memcpy(result.addr, fw_ap->bssid, ETH_ALEN);
|
||||
|
||||
/* TODO: convert the timestamp from the result to systime */
|
||||
result.host_time = ktime_get_boottime_ns();
|
||||
|
||||
result.type = NL80211_PMSR_TYPE_FTM;
|
||||
result.ftm.burst_index = mld->ftm_initiator.responses[peer_idx];
|
||||
mld->ftm_initiator.responses[peer_idx]++;
|
||||
result.ftm.rssi_avg = fw_ap->rssi;
|
||||
result.ftm.rssi_avg_valid = 1;
|
||||
result.ftm.rssi_spread = fw_ap->rssi_spread;
|
||||
result.ftm.rssi_spread_valid = 1;
|
||||
result.ftm.rtt_avg = (s32)le32_to_cpu(fw_ap->rtt);
|
||||
result.ftm.rtt_avg_valid = 1;
|
||||
result.ftm.rtt_variance = le32_to_cpu(fw_ap->rtt_variance);
|
||||
result.ftm.rtt_variance_valid = 1;
|
||||
result.ftm.rtt_spread = le32_to_cpu(fw_ap->rtt_spread);
|
||||
result.ftm.rtt_spread_valid = 1;
|
||||
|
||||
cfg80211_pmsr_report(mld->ftm_initiator.req_wdev,
|
||||
mld->ftm_initiator.req,
|
||||
&result, GFP_KERNEL);
|
||||
|
||||
if (fw_has_api(&mld->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_API_FTM_RTT_ACCURACY))
|
||||
IWL_DEBUG_INFO(mld, "RTT confidence: %u\n",
|
||||
fw_ap->rttConfidence);
|
||||
|
||||
iwl_mld_debug_range_resp(mld, i, &result);
|
||||
}
|
||||
|
||||
if (last_in_batch) {
|
||||
cfg80211_pmsr_complete(mld->ftm_initiator.req_wdev,
|
||||
mld->ftm_initiator.req,
|
||||
GFP_KERNEL);
|
||||
iwl_mld_ftm_reset(mld);
|
||||
}
|
||||
}
|
||||
|
||||
void iwl_mld_ftm_restart_cleanup(struct iwl_mld *mld)
|
||||
{
|
||||
struct cfg80211_pmsr_result result = {
|
||||
.status = NL80211_PMSR_STATUS_FAILURE,
|
||||
.final = 1,
|
||||
.host_time = ktime_get_boottime_ns(),
|
||||
.type = NL80211_PMSR_TYPE_FTM,
|
||||
};
|
||||
|
||||
if (!mld->ftm_initiator.req)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < mld->ftm_initiator.req->n_peers; i++) {
|
||||
memcpy(result.addr, mld->ftm_initiator.req->peers[i].addr,
|
||||
ETH_ALEN);
|
||||
|
||||
cfg80211_pmsr_report(mld->ftm_initiator.req_wdev,
|
||||
mld->ftm_initiator.req,
|
||||
&result, GFP_KERNEL);
|
||||
}
|
||||
|
||||
cfg80211_pmsr_complete(mld->ftm_initiator.req_wdev,
|
||||
mld->ftm_initiator.req, GFP_KERNEL);
|
||||
iwl_mld_ftm_reset(mld);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2025 Intel Corporation
|
||||
*/
|
||||
#ifndef __iwl_mld_ftm_initiator_h__
|
||||
#define __iwl_mld_ftm_initiator_h__
|
||||
|
||||
/**
|
||||
* struct ftm_initiator_data - FTM initiator data
|
||||
*
|
||||
* @req: a pointer to cfg80211 FTM request
|
||||
* @req_wdev: a pointer to the wdev that requested the current FTM request
|
||||
* @responses: the number of responses received for the current FTM session.
|
||||
* Used for tracking the burst index in a periodic request.
|
||||
*/
|
||||
struct ftm_initiator_data {
|
||||
struct cfg80211_pmsr_request *req;
|
||||
struct wireless_dev *req_wdev;
|
||||
int responses[IWL_TOF_MAX_APS];
|
||||
};
|
||||
|
||||
int iwl_mld_ftm_start(struct iwl_mld *mld, struct ieee80211_vif *vif,
|
||||
struct cfg80211_pmsr_request *req);
|
||||
|
||||
void iwl_mld_handle_ftm_resp_notif(struct iwl_mld *mld,
|
||||
struct iwl_rx_packet *pkt);
|
||||
void iwl_mld_ftm_restart_cleanup(struct iwl_mld *mld);
|
||||
|
||||
#endif /* __iwl_mld_ftm_initiator_h__ */
|
||||
@@ -0,0 +1,554 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2024-2025 Intel Corporation
|
||||
*/
|
||||
|
||||
#include "mld.h"
|
||||
|
||||
#include "fw/api/alive.h"
|
||||
#include "fw/api/scan.h"
|
||||
#include "fw/api/rx.h"
|
||||
#include "phy.h"
|
||||
#include "fw/dbg.h"
|
||||
#include "fw/pnvm.h"
|
||||
#include "hcmd.h"
|
||||
#include "power.h"
|
||||
#include "mcc.h"
|
||||
#include "led.h"
|
||||
#include "coex.h"
|
||||
#include "regulatory.h"
|
||||
#include "thermal.h"
|
||||
|
||||
static int iwl_mld_send_tx_ant_cfg(struct iwl_mld *mld)
|
||||
{
|
||||
struct iwl_tx_ant_cfg_cmd cmd;
|
||||
|
||||
lockdep_assert_wiphy(mld->wiphy);
|
||||
|
||||
cmd.valid = cpu_to_le32(iwl_mld_get_valid_tx_ant(mld));
|
||||
|
||||
IWL_DEBUG_FW(mld, "select valid tx ant: %u\n", cmd.valid);
|
||||
|
||||
return iwl_mld_send_cmd_pdu(mld, TX_ANT_CONFIGURATION_CMD, &cmd);
|
||||
}
|
||||
|
||||
static int iwl_mld_send_rss_cfg_cmd(struct iwl_mld *mld)
|
||||
{
|
||||
struct iwl_rss_config_cmd cmd = {
|
||||
.flags = cpu_to_le32(IWL_RSS_ENABLE),
|
||||
.hash_mask = BIT(IWL_RSS_HASH_TYPE_IPV4_TCP) |
|
||||
BIT(IWL_RSS_HASH_TYPE_IPV4_UDP) |
|
||||
BIT(IWL_RSS_HASH_TYPE_IPV4_PAYLOAD) |
|
||||
BIT(IWL_RSS_HASH_TYPE_IPV6_TCP) |
|
||||
BIT(IWL_RSS_HASH_TYPE_IPV6_UDP) |
|
||||
BIT(IWL_RSS_HASH_TYPE_IPV6_PAYLOAD),
|
||||
};
|
||||
|
||||
lockdep_assert_wiphy(mld->wiphy);
|
||||
|
||||
/* Do not direct RSS traffic to Q 0 which is our fallback queue */
|
||||
for (int i = 0; i < ARRAY_SIZE(cmd.indirection_table); i++)
|
||||
cmd.indirection_table[i] =
|
||||
1 + (i % (mld->trans->info.num_rxqs - 1));
|
||||
netdev_rss_key_fill(cmd.secret_key, sizeof(cmd.secret_key));
|
||||
|
||||
return iwl_mld_send_cmd_pdu(mld, RSS_CONFIG_CMD, &cmd);
|
||||
}
|
||||
|
||||
static int iwl_mld_config_scan(struct iwl_mld *mld)
|
||||
{
|
||||
struct iwl_scan_config cmd = {
|
||||
.tx_chains = cpu_to_le32(iwl_mld_get_valid_tx_ant(mld)),
|
||||
.rx_chains = cpu_to_le32(iwl_mld_get_valid_rx_ant(mld))
|
||||
};
|
||||
|
||||
return iwl_mld_send_cmd_pdu(mld, WIDE_ID(LONG_GROUP, SCAN_CFG_CMD),
|
||||
&cmd);
|
||||
}
|
||||
|
||||
static void iwl_mld_alive_imr_data(struct iwl_trans *trans,
|
||||
const struct iwl_imr_alive_info *imr_info)
|
||||
{
|
||||
struct iwl_imr_data *imr_data = &trans->dbg.imr_data;
|
||||
|
||||
imr_data->imr_enable = le32_to_cpu(imr_info->enabled);
|
||||
imr_data->imr_size = le32_to_cpu(imr_info->size);
|
||||
imr_data->imr2sram_remainbyte = imr_data->imr_size;
|
||||
imr_data->imr_base_addr = imr_info->base_addr;
|
||||
imr_data->imr_curr_addr = le64_to_cpu(imr_data->imr_base_addr);
|
||||
|
||||
if (imr_data->imr_enable)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(trans->dbg.active_regions); i++) {
|
||||
struct iwl_fw_ini_region_tlv *reg;
|
||||
|
||||
if (!trans->dbg.active_regions[i])
|
||||
continue;
|
||||
|
||||
reg = (void *)trans->dbg.active_regions[i]->data;
|
||||
|
||||
/* We have only one DRAM IMR region, so we
|
||||
* can break as soon as we find the first
|
||||
* one.
|
||||
*/
|
||||
if (reg->type == IWL_FW_INI_REGION_DRAM_IMR) {
|
||||
trans->dbg.unsupported_region_msk |= BIT(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct iwl_mld_alive_data {
|
||||
__le32 sku_id[3];
|
||||
bool valid;
|
||||
};
|
||||
|
||||
static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
|
||||
struct iwl_rx_packet *pkt, void *data)
|
||||
{
|
||||
unsigned int pkt_len = iwl_rx_packet_payload_len(pkt);
|
||||
unsigned int expected_sz;
|
||||
struct iwl_mld *mld =
|
||||
container_of(notif_wait, struct iwl_mld, notif_wait);
|
||||
struct iwl_trans *trans = mld->trans;
|
||||
u32 version = iwl_fw_lookup_notif_ver(mld->fw, LEGACY_GROUP,
|
||||
UCODE_ALIVE_NTFY, 0);
|
||||
struct iwl_mld_alive_data *alive_data = data;
|
||||
struct iwl_alive_ntf *palive;
|
||||
struct iwl_umac_alive *umac;
|
||||
struct iwl_lmac_alive *lmac1;
|
||||
struct iwl_lmac_alive *lmac2 = NULL;
|
||||
u32 lmac_error_event_table;
|
||||
u32 umac_error_table;
|
||||
u16 status;
|
||||
|
||||
switch (version) {
|
||||
case 6:
|
||||
case 7:
|
||||
expected_sz = sizeof(struct iwl_alive_ntf_v6);
|
||||
break;
|
||||
case 8:
|
||||
expected_sz = sizeof(struct iwl_alive_ntf);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pkt_len != expected_sz)
|
||||
return false;
|
||||
|
||||
palive = (void *)pkt->data;
|
||||
|
||||
iwl_mld_alive_imr_data(trans, &palive->imr);
|
||||
|
||||
umac = &palive->umac_data;
|
||||
lmac1 = &palive->lmac_data[0];
|
||||
lmac2 = &palive->lmac_data[1];
|
||||
status = le16_to_cpu(palive->status);
|
||||
|
||||
BUILD_BUG_ON(sizeof(alive_data->sku_id) !=
|
||||
sizeof(palive->sku_id.data));
|
||||
memcpy(alive_data->sku_id, palive->sku_id.data,
|
||||
sizeof(palive->sku_id.data));
|
||||
|
||||
IWL_DEBUG_FW(mld, "Got sku_id: 0x0%x 0x0%x 0x0%x\n",
|
||||
le32_to_cpu(alive_data->sku_id[0]),
|
||||
le32_to_cpu(alive_data->sku_id[1]),
|
||||
le32_to_cpu(alive_data->sku_id[2]));
|
||||
|
||||
lmac_error_event_table =
|
||||
le32_to_cpu(lmac1->dbg_ptrs.error_event_table_ptr);
|
||||
iwl_fw_lmac1_set_alive_err_table(trans, lmac_error_event_table);
|
||||
|
||||
if (lmac2)
|
||||
trans->dbg.lmac_error_event_table[1] =
|
||||
le32_to_cpu(lmac2->dbg_ptrs.error_event_table_ptr);
|
||||
|
||||
umac_error_table = le32_to_cpu(umac->dbg_ptrs.error_info_addr) &
|
||||
~FW_ADDR_CACHE_CONTROL;
|
||||
|
||||
if (umac_error_table >= trans->mac_cfg->base->min_umac_error_event_table)
|
||||
iwl_fw_umac_set_alive_err_table(trans, umac_error_table);
|
||||
else
|
||||
IWL_ERR(mld, "Not valid error log pointer 0x%08X\n",
|
||||
umac_error_table);
|
||||
|
||||
alive_data->valid = status == IWL_ALIVE_STATUS_OK;
|
||||
|
||||
IWL_DEBUG_FW(mld,
|
||||
"Alive ucode status 0x%04x revision 0x%01X 0x%01X\n",
|
||||
status, lmac1->ver_type, lmac1->ver_subtype);
|
||||
|
||||
if (lmac2)
|
||||
IWL_DEBUG_FW(mld, "Alive ucode CDB\n");
|
||||
|
||||
IWL_DEBUG_FW(mld,
|
||||
"UMAC version: Major - 0x%x, Minor - 0x%x\n",
|
||||
le32_to_cpu(umac->umac_major),
|
||||
le32_to_cpu(umac->umac_minor));
|
||||
|
||||
if (version >= 7)
|
||||
IWL_DEBUG_FW(mld, "FW alive flags 0x%x\n",
|
||||
le16_to_cpu(palive->flags));
|
||||
|
||||
if (version >= 8)
|
||||
IWL_DEBUG_FW(mld, "platform_id 0x%llx\n",
|
||||
le64_to_cpu(palive->platform_id));
|
||||
|
||||
iwl_fwrt_update_fw_versions(&mld->fwrt, lmac1, umac);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#define MLD_ALIVE_TIMEOUT (2 * HZ)
|
||||
#define MLD_INIT_COMPLETE_TIMEOUT (2 * HZ)
|
||||
|
||||
static void iwl_mld_print_alive_notif_timeout(struct iwl_mld *mld)
|
||||
{
|
||||
struct iwl_trans *trans = mld->trans;
|
||||
struct iwl_pc_data *pc_data;
|
||||
u8 count;
|
||||
|
||||
IWL_ERR(mld,
|
||||
"SecBoot CPU1 Status: 0x%x, CPU2 Status: 0x%x\n",
|
||||
iwl_read_umac_prph(trans, UMAG_SB_CPU_1_STATUS),
|
||||
iwl_read_umac_prph(trans,
|
||||
UMAG_SB_CPU_2_STATUS));
|
||||
#define IWL_FW_PRINT_REG_INFO(reg_name) \
|
||||
IWL_ERR(mld, #reg_name ": 0x%x\n", iwl_read_umac_prph(trans, reg_name))
|
||||
|
||||
IWL_FW_PRINT_REG_INFO(WFPM_LMAC1_PD_NOTIFICATION);
|
||||
|
||||
IWL_FW_PRINT_REG_INFO(HPM_SECONDARY_DEVICE_STATE);
|
||||
|
||||
/* print OTP info */
|
||||
IWL_FW_PRINT_REG_INFO(WFPM_MAC_OTP_CFG7_ADDR);
|
||||
IWL_FW_PRINT_REG_INFO(WFPM_MAC_OTP_CFG7_DATA);
|
||||
#undef IWL_FW_PRINT_REG_INFO
|
||||
|
||||
pc_data = trans->dbg.pc_data;
|
||||
for (count = 0; count < trans->dbg.num_pc; count++, pc_data++)
|
||||
IWL_ERR(mld, "%s: 0x%x\n", pc_data->pc_name,
|
||||
pc_data->pc_address);
|
||||
}
|
||||
|
||||
static int iwl_mld_load_fw_wait_alive(struct iwl_mld *mld,
|
||||
struct iwl_mld_alive_data *alive_data)
|
||||
{
|
||||
static const u16 alive_cmd[] = { UCODE_ALIVE_NTFY };
|
||||
struct iwl_notification_wait alive_wait;
|
||||
int ret;
|
||||
|
||||
lockdep_assert_wiphy(mld->wiphy);
|
||||
|
||||
iwl_init_notification_wait(&mld->notif_wait, &alive_wait,
|
||||
alive_cmd, ARRAY_SIZE(alive_cmd),
|
||||
iwl_alive_fn, alive_data);
|
||||
|
||||
iwl_dbg_tlv_time_point(&mld->fwrt, IWL_FW_INI_TIME_POINT_EARLY, NULL);
|
||||
|
||||
ret = iwl_trans_start_fw(mld->trans, mld->fw, IWL_UCODE_REGULAR, true);
|
||||
if (ret) {
|
||||
iwl_remove_notification(&mld->notif_wait, &alive_wait);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = iwl_wait_notification(&mld->notif_wait, &alive_wait,
|
||||
MLD_ALIVE_TIMEOUT);
|
||||
|
||||
if (ret) {
|
||||
if (ret == -ETIMEDOUT)
|
||||
iwl_fw_dbg_error_collect(&mld->fwrt,
|
||||
FW_DBG_TRIGGER_ALIVE_TIMEOUT);
|
||||
iwl_mld_print_alive_notif_timeout(mld);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!alive_data->valid) {
|
||||
IWL_ERR(mld, "Loaded firmware is not valid!\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
iwl_trans_fw_alive(mld->trans);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwl_mld_run_fw_init_sequence(struct iwl_mld *mld)
|
||||
{
|
||||
struct iwl_notification_wait init_wait;
|
||||
struct iwl_init_extended_cfg_cmd init_cfg = {
|
||||
.init_flags = cpu_to_le32(BIT(IWL_INIT_PHY)),
|
||||
};
|
||||
struct iwl_mld_alive_data alive_data = {};
|
||||
static const u16 init_complete[] = {
|
||||
INIT_COMPLETE_NOTIF,
|
||||
};
|
||||
int ret;
|
||||
|
||||
lockdep_assert_wiphy(mld->wiphy);
|
||||
|
||||
ret = iwl_mld_load_fw_wait_alive(mld, &alive_data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = iwl_pnvm_load(mld->trans, &mld->notif_wait,
|
||||
mld->fw, alive_data.sku_id);
|
||||
if (ret) {
|
||||
IWL_ERR(mld, "Timeout waiting for PNVM load %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
iwl_dbg_tlv_time_point(&mld->fwrt, IWL_FW_INI_TIME_POINT_AFTER_ALIVE,
|
||||
NULL);
|
||||
|
||||
iwl_init_notification_wait(&mld->notif_wait,
|
||||
&init_wait,
|
||||
init_complete,
|
||||
ARRAY_SIZE(init_complete),
|
||||
NULL, NULL);
|
||||
|
||||
ret = iwl_mld_send_cmd_pdu(mld,
|
||||
WIDE_ID(SYSTEM_GROUP, INIT_EXTENDED_CFG_CMD),
|
||||
&init_cfg);
|
||||
if (ret) {
|
||||
IWL_ERR(mld, "Failed to send init config command: %d\n", ret);
|
||||
iwl_remove_notification(&mld->notif_wait, &init_wait);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = iwl_mld_send_phy_cfg_cmd(mld);
|
||||
if (ret) {
|
||||
IWL_ERR(mld, "Failed to send PHY config command: %d\n", ret);
|
||||
iwl_remove_notification(&mld->notif_wait, &init_wait);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = iwl_wait_notification(&mld->notif_wait, &init_wait,
|
||||
MLD_INIT_COMPLETE_TIMEOUT);
|
||||
if (ret) {
|
||||
IWL_ERR(mld, "Failed to get INIT_COMPLETE %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iwl_mld_load_fw(struct iwl_mld *mld)
|
||||
{
|
||||
int ret;
|
||||
|
||||
lockdep_assert_wiphy(mld->wiphy);
|
||||
|
||||
ret = iwl_trans_start_hw(mld->trans);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = iwl_mld_run_fw_init_sequence(mld);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
mld->fw_status.running = true;
|
||||
|
||||
return 0;
|
||||
err:
|
||||
iwl_mld_stop_fw(mld);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void iwl_mld_stop_fw(struct iwl_mld *mld)
|
||||
{
|
||||
lockdep_assert_wiphy(mld->wiphy);
|
||||
|
||||
iwl_abort_notification_waits(&mld->notif_wait);
|
||||
|
||||
iwl_fw_dbg_stop_sync(&mld->fwrt);
|
||||
|
||||
iwl_trans_stop_device(mld->trans);
|
||||
|
||||
/* HW is stopped, no more coming RX. Cancel all notifications in
|
||||
* case they were sent just before stopping the HW.
|
||||
*/
|
||||
iwl_mld_cancel_async_notifications(mld);
|
||||
|
||||
mld->fw_status.running = false;
|
||||
}
|
||||
|
||||
static void iwl_mld_restart_disconnect_iter(void *data, u8 *mac,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
if (vif->type == NL80211_IFTYPE_STATION)
|
||||
ieee80211_hw_restart_disconnect(vif);
|
||||
}
|
||||
|
||||
void iwl_mld_send_recovery_cmd(struct iwl_mld *mld, u32 flags)
|
||||
{
|
||||
u32 error_log_size = mld->fw->ucode_capa.error_log_size;
|
||||
struct iwl_fw_error_recovery_cmd recovery_cmd = {
|
||||
.flags = cpu_to_le32(flags),
|
||||
};
|
||||
struct iwl_host_cmd cmd = {
|
||||
.id = WIDE_ID(SYSTEM_GROUP, FW_ERROR_RECOVERY_CMD),
|
||||
.flags = CMD_WANT_SKB,
|
||||
.data = {&recovery_cmd, },
|
||||
.len = {sizeof(recovery_cmd), },
|
||||
};
|
||||
int ret;
|
||||
|
||||
/* no error log was defined in TLV */
|
||||
if (!error_log_size)
|
||||
return;
|
||||
|
||||
if (flags & ERROR_RECOVERY_UPDATE_DB) {
|
||||
/* no buf was allocated upon NIC error */
|
||||
if (!mld->error_recovery_buf)
|
||||
return;
|
||||
|
||||
cmd.data[1] = mld->error_recovery_buf;
|
||||
cmd.len[1] = error_log_size;
|
||||
cmd.dataflags[1] = IWL_HCMD_DFL_NOCOPY;
|
||||
recovery_cmd.buf_size = cpu_to_le32(error_log_size);
|
||||
}
|
||||
|
||||
ret = iwl_mld_send_cmd(mld, &cmd);
|
||||
|
||||
/* we no longer need the recovery buffer */
|
||||
kfree(mld->error_recovery_buf);
|
||||
mld->error_recovery_buf = NULL;
|
||||
|
||||
if (ret) {
|
||||
IWL_ERR(mld, "Failed to send recovery cmd %d\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
if (flags & ERROR_RECOVERY_UPDATE_DB) {
|
||||
struct iwl_rx_packet *pkt = cmd.resp_pkt;
|
||||
u32 pkt_len = iwl_rx_packet_payload_len(pkt);
|
||||
u32 resp;
|
||||
|
||||
if (IWL_FW_CHECK(mld, pkt_len != sizeof(resp),
|
||||
"Unexpected recovery cmd response size %u (expected %zu)\n",
|
||||
pkt_len, sizeof(resp)))
|
||||
goto out;
|
||||
|
||||
resp = le32_to_cpup((__le32 *)cmd.resp_pkt->data);
|
||||
if (!resp)
|
||||
goto out;
|
||||
|
||||
IWL_ERR(mld,
|
||||
"Failed to send recovery cmd blob was invalid %d\n",
|
||||
resp);
|
||||
|
||||
ieee80211_iterate_interfaces(mld->hw, 0,
|
||||
iwl_mld_restart_disconnect_iter,
|
||||
NULL);
|
||||
}
|
||||
|
||||
out:
|
||||
iwl_free_resp(&cmd);
|
||||
}
|
||||
|
||||
static int iwl_mld_config_fw(struct iwl_mld *mld)
|
||||
{
|
||||
int ret;
|
||||
|
||||
lockdep_assert_wiphy(mld->wiphy);
|
||||
|
||||
iwl_fw_disable_dbg_asserts(&mld->fwrt);
|
||||
iwl_get_shared_mem_conf(&mld->fwrt);
|
||||
|
||||
ret = iwl_mld_send_tx_ant_cfg(mld);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = iwl_mld_send_bt_init_conf(mld);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = iwl_set_soc_latency(&mld->fwrt);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
iwl_mld_configure_lari(mld);
|
||||
|
||||
ret = iwl_mld_config_temp_report_ths(mld);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
#ifdef CONFIG_THERMAL
|
||||
ret = iwl_mld_config_ctdp(mld, mld->cooling_dev.cur_state,
|
||||
CTDP_CMD_OPERATION_START);
|
||||
if (ret)
|
||||
return ret;
|
||||
#endif
|
||||
|
||||
ret = iwl_configure_rxq(&mld->fwrt);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = iwl_mld_send_rss_cfg_cmd(mld);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = iwl_mld_config_scan(mld);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = iwl_mld_update_device_power(mld, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (mld->fw_status.in_hw_restart) {
|
||||
iwl_mld_send_recovery_cmd(mld, ERROR_RECOVERY_UPDATE_DB);
|
||||
iwl_mld_time_sync_fw_config(mld);
|
||||
}
|
||||
|
||||
iwl_mld_led_config_fw(mld);
|
||||
|
||||
ret = iwl_mld_init_ppag(mld);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = iwl_mld_init_sar(mld);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = iwl_mld_init_sgom(mld);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
iwl_mld_init_tas(mld);
|
||||
iwl_mld_init_uats(mld);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iwl_mld_start_fw(struct iwl_mld *mld)
|
||||
{
|
||||
int ret;
|
||||
|
||||
lockdep_assert_wiphy(mld->wiphy);
|
||||
|
||||
ret = iwl_mld_load_fw(mld);
|
||||
if (IWL_FW_CHECK(mld, ret, "Failed to start firmware %d\n", ret)) {
|
||||
iwl_fw_dbg_error_collect(&mld->fwrt, FW_DBG_TRIGGER_DRIVER);
|
||||
return ret;
|
||||
}
|
||||
|
||||
IWL_DEBUG_INFO(mld, "uCode started.\n");
|
||||
|
||||
ret = iwl_mld_config_fw(mld);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
ret = iwl_mld_init_mcc(mld);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
iwl_mld_stop_fw(mld);
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2024-2025 Intel Corporation
|
||||
*/
|
||||
#ifndef __iwl_mld_hcmd_h__
|
||||
#define __iwl_mld_hcmd_h__
|
||||
|
||||
static inline int iwl_mld_send_cmd(struct iwl_mld *mld, struct iwl_host_cmd *cmd)
|
||||
{
|
||||
/* No commands, including the d3 related commands, should be sent
|
||||
* after entering d3
|
||||
*/
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
if (WARN_ON(mld->fw_status.in_d3))
|
||||
return -EIO;
|
||||
#endif
|
||||
|
||||
if (!(cmd->flags & CMD_ASYNC))
|
||||
lockdep_assert_wiphy(mld->wiphy);
|
||||
|
||||
/* Devices that need to shutdown immediately on rfkill are not
|
||||
* supported, so we can send all the cmds in rfkill
|
||||
*/
|
||||
cmd->flags |= CMD_SEND_IN_RFKILL;
|
||||
|
||||
return iwl_trans_send_cmd(mld->trans, cmd);
|
||||
}
|
||||
|
||||
static inline int
|
||||
__iwl_mld_send_cmd_with_flags_pdu(struct iwl_mld *mld, u32 id,
|
||||
u32 flags, const void *data, u16 len)
|
||||
{
|
||||
struct iwl_host_cmd cmd = {
|
||||
.id = id,
|
||||
.len = { data ? len : 0, },
|
||||
.data = { data, },
|
||||
.flags = flags,
|
||||
};
|
||||
|
||||
return iwl_mld_send_cmd(mld, &cmd);
|
||||
}
|
||||
|
||||
#define _iwl_mld_send_cmd_with_flags_pdu(mld, id, flags, data, len, \
|
||||
ignored...) \
|
||||
__iwl_mld_send_cmd_with_flags_pdu(mld, id, flags, data, len)
|
||||
#define iwl_mld_send_cmd_with_flags_pdu(mld, id, flags, data, len...) \
|
||||
_iwl_mld_send_cmd_with_flags_pdu(mld, id, flags, data, ##len, \
|
||||
sizeof(*(data)))
|
||||
|
||||
#define iwl_mld_send_cmd_pdu(mld, id, ...) \
|
||||
iwl_mld_send_cmd_with_flags_pdu(mld, id, 0, __VA_ARGS__)
|
||||
|
||||
#define iwl_mld_send_cmd_empty(mld, id) \
|
||||
iwl_mld_send_cmd_with_flags_pdu(mld, id, 0, NULL, 0)
|
||||
|
||||
#endif /* __iwl_mld_hcmd_h__ */
|
||||
@@ -0,0 +1,707 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2024-2025 Intel Corporation
|
||||
*/
|
||||
#include <net/cfg80211.h>
|
||||
|
||||
#include "iface.h"
|
||||
#include "hcmd.h"
|
||||
#include "key.h"
|
||||
#include "mlo.h"
|
||||
#include "mac80211.h"
|
||||
|
||||
#include "fw/api/context.h"
|
||||
#include "fw/api/mac.h"
|
||||
#include "fw/api/time-event.h"
|
||||
#include "fw/api/datapath.h"
|
||||
|
||||
/* Cleanup function for struct iwl_mld_vif, will be called in restart */
|
||||
void iwl_mld_cleanup_vif(void *data, u8 *mac, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
|
||||
struct iwl_mld *mld = mld_vif->mld;
|
||||
struct iwl_mld_link *link;
|
||||
|
||||
mld_vif->emlsr.blocked_reasons &= ~IWL_MLD_EMLSR_BLOCKED_ROC;
|
||||
|
||||
if (mld_vif->aux_sta.sta_id != IWL_INVALID_STA)
|
||||
iwl_mld_free_internal_sta(mld, &mld_vif->aux_sta);
|
||||
|
||||
/* EMLSR is turned back on during recovery */
|
||||
vif->driver_flags &= ~IEEE80211_VIF_EML_ACTIVE;
|
||||
|
||||
if (mld_vif->roc_activity != ROC_NUM_ACTIVITIES)
|
||||
ieee80211_remain_on_channel_expired(mld->hw);
|
||||
|
||||
mld_vif->roc_activity = ROC_NUM_ACTIVITIES;
|
||||
|
||||
for_each_mld_vif_valid_link(mld_vif, link) {
|
||||
iwl_mld_cleanup_link(mld_vif->mld, link);
|
||||
|
||||
/* Correctly allocated primary link in non-MLO mode */
|
||||
if (!ieee80211_vif_is_mld(vif) &&
|
||||
link_id == 0 && link == &mld_vif->deflink)
|
||||
continue;
|
||||
|
||||
if (vif->active_links & BIT(link_id))
|
||||
continue;
|
||||
|
||||
/* Should not happen as link removal should always succeed */
|
||||
WARN_ON(1);
|
||||
if (link != &mld_vif->deflink)
|
||||
kfree_rcu(link, rcu_head);
|
||||
RCU_INIT_POINTER(mld_vif->link[link_id], NULL);
|
||||
}
|
||||
|
||||
ieee80211_iter_keys(mld->hw, vif, iwl_mld_cleanup_keys_iter, NULL);
|
||||
|
||||
wiphy_delayed_work_cancel(mld->wiphy, &mld_vif->mlo_scan_start_wk);
|
||||
|
||||
CLEANUP_STRUCT(mld_vif);
|
||||
}
|
||||
|
||||
static int iwl_mld_send_mac_cmd(struct iwl_mld *mld,
|
||||
struct iwl_mac_config_cmd *cmd)
|
||||
{
|
||||
int ret;
|
||||
|
||||
lockdep_assert_wiphy(mld->wiphy);
|
||||
|
||||
ret = iwl_mld_send_cmd_pdu(mld,
|
||||
WIDE_ID(MAC_CONF_GROUP, MAC_CONFIG_CMD),
|
||||
cmd);
|
||||
if (ret)
|
||||
IWL_ERR(mld, "Failed to send MAC_CONFIG_CMD ret = %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iwl_mld_mac80211_iftype_to_fw(const struct ieee80211_vif *vif)
|
||||
{
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
return vif->p2p ? FW_MAC_TYPE_P2P_STA : FW_MAC_TYPE_BSS_STA;
|
||||
case NL80211_IFTYPE_AP:
|
||||
return FW_MAC_TYPE_GO;
|
||||
case NL80211_IFTYPE_MONITOR:
|
||||
return FW_MAC_TYPE_LISTENER;
|
||||
case NL80211_IFTYPE_P2P_DEVICE:
|
||||
return FW_MAC_TYPE_P2P_DEVICE;
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
return FW_MAC_TYPE_IBSS;
|
||||
default:
|
||||
WARN_ON_ONCE(1);
|
||||
}
|
||||
return FW_MAC_TYPE_BSS_STA;
|
||||
}
|
||||
|
||||
static bool iwl_mld_is_nic_ack_enabled(struct iwl_mld *mld,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
const struct ieee80211_supported_band *sband;
|
||||
const struct ieee80211_sta_he_cap *own_he_cap;
|
||||
|
||||
lockdep_assert_wiphy(mld->wiphy);
|
||||
|
||||
/* This capability is the same for all bands,
|
||||
* so take it from one of them.
|
||||
*/
|
||||
sband = mld->hw->wiphy->bands[NL80211_BAND_2GHZ];
|
||||
own_he_cap = ieee80211_get_he_iftype_cap_vif(sband, vif);
|
||||
|
||||
return own_he_cap && (own_he_cap->he_cap_elem.mac_cap_info[2] &
|
||||
IEEE80211_HE_MAC_CAP2_ACK_EN);
|
||||
}
|
||||
|
||||
static void iwl_mld_set_he_support(struct iwl_mld *mld,
|
||||
struct ieee80211_vif *vif,
|
||||
struct iwl_mac_config_cmd *cmd,
|
||||
int cmd_ver)
|
||||
{
|
||||
if (vif->type == NL80211_IFTYPE_AP) {
|
||||
if (cmd_ver == 2)
|
||||
cmd->wifi_gen_v2.he_ap_support = cpu_to_le16(1);
|
||||
else
|
||||
cmd->wifi_gen.he_ap_support = 1;
|
||||
} else {
|
||||
if (cmd_ver == 2)
|
||||
cmd->wifi_gen_v2.he_support = cpu_to_le16(1);
|
||||
else
|
||||
cmd->wifi_gen.he_support = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* fill the common part for all interface types */
|
||||
static void iwl_mld_mac_cmd_fill_common(struct iwl_mld *mld,
|
||||
struct ieee80211_vif *vif,
|
||||
struct iwl_mac_config_cmd *cmd,
|
||||
u32 action)
|
||||
{
|
||||
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
|
||||
struct ieee80211_bss_conf *link_conf;
|
||||
unsigned int link_id;
|
||||
int cmd_ver = iwl_fw_lookup_cmd_ver(mld->fw,
|
||||
WIDE_ID(MAC_CONF_GROUP,
|
||||
MAC_CONFIG_CMD), 0);
|
||||
|
||||
lockdep_assert_wiphy(mld->wiphy);
|
||||
|
||||
cmd->id_and_color = cpu_to_le32(mld_vif->fw_id);
|
||||
cmd->action = cpu_to_le32(action);
|
||||
|
||||
cmd->mac_type =
|
||||
cpu_to_le32(iwl_mld_mac80211_iftype_to_fw(vif));
|
||||
|
||||
memcpy(cmd->local_mld_addr, vif->addr, ETH_ALEN);
|
||||
|
||||
if (iwlwifi_mod_params.disable_11ax)
|
||||
return;
|
||||
|
||||
cmd->nic_not_ack_enabled =
|
||||
cpu_to_le32(!iwl_mld_is_nic_ack_enabled(mld, vif));
|
||||
|
||||
/* If we have MLO enabled, then the firmware needs to enable
|
||||
* address translation for the station(s) we add. That depends
|
||||
* on having EHT enabled in firmware, which in turn depends on
|
||||
* mac80211 in the code below.
|
||||
* However, mac80211 doesn't enable HE/EHT until it has parsed
|
||||
* the association response successfully, so just skip all that
|
||||
* and enable both when we have MLO.
|
||||
*/
|
||||
if (ieee80211_vif_is_mld(vif)) {
|
||||
iwl_mld_set_he_support(mld, vif, cmd, cmd_ver);
|
||||
if (cmd_ver == 2)
|
||||
cmd->wifi_gen_v2.eht_support = cpu_to_le32(1);
|
||||
else
|
||||
cmd->wifi_gen.eht_support = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
for_each_vif_active_link(vif, link_conf, link_id) {
|
||||
if (!link_conf->he_support)
|
||||
continue;
|
||||
|
||||
iwl_mld_set_he_support(mld, vif, cmd, cmd_ver);
|
||||
|
||||
/* EHT, if supported, was already set above */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void iwl_mld_fill_mac_cmd_sta(struct iwl_mld *mld,
|
||||
struct ieee80211_vif *vif, u32 action,
|
||||
struct iwl_mac_config_cmd *cmd)
|
||||
{
|
||||
struct ieee80211_bss_conf *link;
|
||||
u32 twt_policy = 0;
|
||||
int link_id;
|
||||
|
||||
lockdep_assert_wiphy(mld->wiphy);
|
||||
|
||||
WARN_ON(vif->type != NL80211_IFTYPE_STATION);
|
||||
|
||||
/* We always want to hear MCAST frames, if we're not authorized yet,
|
||||
* we'll drop them.
|
||||
*/
|
||||
cmd->filter_flags |= cpu_to_le32(MAC_CFG_FILTER_ACCEPT_GRP);
|
||||
|
||||
/* Adding a MAC ctxt with is_assoc set is not allowed in fw
|
||||
* (and shouldn't happen)
|
||||
*/
|
||||
if (vif->cfg.assoc && action != FW_CTXT_ACTION_ADD) {
|
||||
cmd->client.is_assoc = 1;
|
||||
|
||||
if (!iwl_mld_vif_from_mac80211(vif)->authorized)
|
||||
cmd->client.data_policy |=
|
||||
cpu_to_le16(COEX_HIGH_PRIORITY_ENABLE);
|
||||
} else {
|
||||
/* Allow beacons to pass through as long as we are not
|
||||
* associated
|
||||
*/
|
||||
cmd->filter_flags |= cpu_to_le32(MAC_CFG_FILTER_ACCEPT_BEACON);
|
||||
}
|
||||
|
||||
cmd->client.assoc_id = cpu_to_le16(vif->cfg.aid);
|
||||
|
||||
if (ieee80211_vif_is_mld(vif)) {
|
||||
u16 esr_transition_timeout =
|
||||
u16_get_bits(vif->cfg.eml_cap,
|
||||
IEEE80211_EML_CAP_TRANSITION_TIMEOUT);
|
||||
|
||||
cmd->client.esr_transition_timeout =
|
||||
min_t(u16, IEEE80211_EML_CAP_TRANSITION_TIMEOUT_128TU,
|
||||
esr_transition_timeout);
|
||||
cmd->client.medium_sync_delay =
|
||||
cpu_to_le16(vif->cfg.eml_med_sync_delay);
|
||||
}
|
||||
|
||||
for_each_vif_active_link(vif, link, link_id) {
|
||||
if (!link->he_support)
|
||||
continue;
|
||||
|
||||
if (link->twt_requester)
|
||||
twt_policy |= TWT_SUPPORTED;
|
||||
if (link->twt_protected)
|
||||
twt_policy |= PROTECTED_TWT_SUPPORTED;
|
||||
if (link->twt_broadcast)
|
||||
twt_policy |= BROADCAST_TWT_SUPPORTED;
|
||||
}
|
||||
|
||||
if (!iwlwifi_mod_params.disable_11ax)
|
||||
cmd->client.data_policy |= cpu_to_le16(twt_policy);
|
||||
|
||||
if (vif->probe_req_reg && vif->cfg.assoc && vif->p2p)
|
||||
cmd->filter_flags |=
|
||||
cpu_to_le32(MAC_CFG_FILTER_ACCEPT_PROBE_REQ);
|
||||
}
|
||||
|
||||
static void iwl_mld_fill_mac_cmd_ap(struct iwl_mld *mld,
|
||||
struct ieee80211_vif *vif,
|
||||
struct iwl_mac_config_cmd *cmd)
|
||||
{
|
||||
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
|
||||
|
||||
lockdep_assert_wiphy(mld->wiphy);
|
||||
|
||||
WARN_ON(vif->type != NL80211_IFTYPE_AP);
|
||||
|
||||
cmd->filter_flags |= cpu_to_le32(MAC_CFG_FILTER_ACCEPT_PROBE_REQ);
|
||||
|
||||
/* in AP mode, pass beacons from other APs (needed for ht protection).
|
||||
* When there're no any associated station, which means that we are not
|
||||
* TXing anyway, don't ask FW to pass beacons to prevent unnecessary
|
||||
* wake-ups.
|
||||
*/
|
||||
if (mld_vif->num_associated_stas)
|
||||
cmd->filter_flags |= cpu_to_le32(MAC_CFG_FILTER_ACCEPT_BEACON);
|
||||
}
|
||||
|
||||
static void iwl_mld_go_iterator(void *_data, u8 *mac, struct ieee80211_vif *vif)
|
||||
{
|
||||
bool *go_active = _data;
|
||||
|
||||
if (ieee80211_vif_type_p2p(vif) == NL80211_IFTYPE_P2P_GO &&
|
||||
iwl_mld_vif_from_mac80211(vif)->ap_ibss_active)
|
||||
*go_active = true;
|
||||
}
|
||||
|
||||
static bool iwl_mld_p2p_dev_has_extended_disc(struct iwl_mld *mld)
|
||||
{
|
||||
bool go_active = false;
|
||||
|
||||
/* This flag should be set to true when the P2P Device is
|
||||
* discoverable and there is at least a P2P GO. Setting
|
||||
* this flag will allow the P2P Device to be discoverable on other
|
||||
* channels in addition to its listen channel.
|
||||
* Note that this flag should not be set in other cases as it opens the
|
||||
* Rx filters on all MAC and increases the number of interrupts.
|
||||
*/
|
||||
ieee80211_iterate_active_interfaces(mld->hw,
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
iwl_mld_go_iterator, &go_active);
|
||||
|
||||
return go_active;
|
||||
}
|
||||
|
||||
static void iwl_mld_fill_mac_cmd_p2p_dev(struct iwl_mld *mld,
|
||||
struct ieee80211_vif *vif,
|
||||
struct iwl_mac_config_cmd *cmd)
|
||||
{
|
||||
bool ext_disc = iwl_mld_p2p_dev_has_extended_disc(mld);
|
||||
|
||||
lockdep_assert_wiphy(mld->wiphy);
|
||||
|
||||
/* Override the filter flags to accept all management frames. This is
|
||||
* needed to support both P2P device discovery using probe requests and
|
||||
* P2P service discovery using action frames
|
||||
*/
|
||||
cmd->filter_flags = cpu_to_le32(MAC_CFG_FILTER_ACCEPT_CONTROL_AND_MGMT);
|
||||
|
||||
if (ext_disc)
|
||||
cmd->p2p_dev.is_disc_extended = cpu_to_le32(1);
|
||||
}
|
||||
|
||||
static void iwl_mld_fill_mac_cmd_ibss(struct iwl_mld *mld,
|
||||
struct ieee80211_vif *vif,
|
||||
struct iwl_mac_config_cmd *cmd)
|
||||
{
|
||||
lockdep_assert_wiphy(mld->wiphy);
|
||||
|
||||
WARN_ON(vif->type != NL80211_IFTYPE_ADHOC);
|
||||
|
||||
cmd->filter_flags |= cpu_to_le32(MAC_CFG_FILTER_ACCEPT_BEACON |
|
||||
MAC_CFG_FILTER_ACCEPT_PROBE_REQ |
|
||||
MAC_CFG_FILTER_ACCEPT_GRP);
|
||||
}
|
||||
|
||||
static int
|
||||
iwl_mld_rm_mac_from_fw(struct iwl_mld *mld, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
|
||||
struct iwl_mac_config_cmd cmd = {
|
||||
.action = cpu_to_le32(FW_CTXT_ACTION_REMOVE),
|
||||
.id_and_color = cpu_to_le32(mld_vif->fw_id),
|
||||
};
|
||||
|
||||
return iwl_mld_send_mac_cmd(mld, &cmd);
|
||||
}
|
||||
|
||||
int iwl_mld_mac_fw_action(struct iwl_mld *mld, struct ieee80211_vif *vif,
|
||||
u32 action)
|
||||
{
|
||||
struct iwl_mac_config_cmd cmd = {};
|
||||
|
||||
lockdep_assert_wiphy(mld->wiphy);
|
||||
|
||||
if (action == FW_CTXT_ACTION_REMOVE)
|
||||
return iwl_mld_rm_mac_from_fw(mld, vif);
|
||||
|
||||
iwl_mld_mac_cmd_fill_common(mld, vif, &cmd, action);
|
||||
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
iwl_mld_fill_mac_cmd_sta(mld, vif, action, &cmd);
|
||||
break;
|
||||
case NL80211_IFTYPE_AP:
|
||||
iwl_mld_fill_mac_cmd_ap(mld, vif, &cmd);
|
||||
break;
|
||||
case NL80211_IFTYPE_MONITOR:
|
||||
cmd.filter_flags =
|
||||
cpu_to_le32(MAC_CFG_FILTER_PROMISC |
|
||||
MAC_CFG_FILTER_ACCEPT_CONTROL_AND_MGMT |
|
||||
MAC_CFG_FILTER_ACCEPT_BEACON |
|
||||
MAC_CFG_FILTER_ACCEPT_PROBE_REQ |
|
||||
MAC_CFG_FILTER_ACCEPT_GRP);
|
||||
break;
|
||||
case NL80211_IFTYPE_P2P_DEVICE:
|
||||
iwl_mld_fill_mac_cmd_p2p_dev(mld, vif, &cmd);
|
||||
break;
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
iwl_mld_fill_mac_cmd_ibss(mld, vif, &cmd);
|
||||
break;
|
||||
default:
|
||||
WARN(1, "not supported yet\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
return iwl_mld_send_mac_cmd(mld, &cmd);
|
||||
}
|
||||
|
||||
static void iwl_mld_mlo_scan_start_wk(struct wiphy *wiphy,
|
||||
struct wiphy_work *wk)
|
||||
{
|
||||
struct iwl_mld_vif *mld_vif = container_of(wk, struct iwl_mld_vif,
|
||||
mlo_scan_start_wk.work);
|
||||
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
|
||||
struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
|
||||
|
||||
iwl_mld_int_mlo_scan(mld, iwl_mld_vif_to_mac80211(mld_vif));
|
||||
}
|
||||
|
||||
IWL_MLD_ALLOC_FN(vif, vif)
|
||||
|
||||
/* Constructor function for struct iwl_mld_vif */
|
||||
static int
|
||||
iwl_mld_init_vif(struct iwl_mld *mld, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
|
||||
int ret;
|
||||
|
||||
lockdep_assert_wiphy(mld->wiphy);
|
||||
|
||||
mld_vif->mld = mld;
|
||||
mld_vif->roc_activity = ROC_NUM_ACTIVITIES;
|
||||
|
||||
ret = iwl_mld_allocate_vif_fw_id(mld, &mld_vif->fw_id, vif);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!mld->fw_status.in_hw_restart) {
|
||||
wiphy_work_init(&mld_vif->emlsr.unblock_tpt_wk,
|
||||
iwl_mld_emlsr_unblock_tpt_wk);
|
||||
wiphy_delayed_work_init(&mld_vif->emlsr.check_tpt_wk,
|
||||
iwl_mld_emlsr_check_tpt);
|
||||
wiphy_delayed_work_init(&mld_vif->emlsr.prevent_done_wk,
|
||||
iwl_mld_emlsr_prevent_done_wk);
|
||||
wiphy_delayed_work_init(&mld_vif->emlsr.tmp_non_bss_done_wk,
|
||||
iwl_mld_emlsr_tmp_non_bss_done_wk);
|
||||
wiphy_delayed_work_init(&mld_vif->mlo_scan_start_wk,
|
||||
iwl_mld_mlo_scan_start_wk);
|
||||
}
|
||||
iwl_mld_init_internal_sta(&mld_vif->aux_sta);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iwl_mld_add_vif(struct iwl_mld *mld, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
|
||||
int ret;
|
||||
|
||||
lockdep_assert_wiphy(mld->wiphy);
|
||||
|
||||
ret = iwl_mld_init_vif(mld, vif);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = iwl_mld_mac_fw_action(mld, vif, FW_CTXT_ACTION_ADD);
|
||||
if (ret)
|
||||
RCU_INIT_POINTER(mld->fw_id_to_vif[mld_vif->fw_id], NULL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iwl_mld_rm_vif(struct iwl_mld *mld, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
|
||||
int ret;
|
||||
|
||||
lockdep_assert_wiphy(mld->wiphy);
|
||||
|
||||
ret = iwl_mld_mac_fw_action(mld, vif, FW_CTXT_ACTION_REMOVE);
|
||||
|
||||
if (WARN_ON(mld_vif->fw_id >= ARRAY_SIZE(mld->fw_id_to_vif)))
|
||||
return -EINVAL;
|
||||
|
||||
RCU_INIT_POINTER(mld->fw_id_to_vif[mld_vif->fw_id], NULL);
|
||||
|
||||
iwl_mld_cancel_notifications_of_object(mld, IWL_MLD_OBJECT_TYPE_VIF,
|
||||
mld_vif->fw_id);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void iwl_mld_set_vif_associated(struct iwl_mld *mld,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ieee80211_bss_conf *link;
|
||||
unsigned int link_id;
|
||||
|
||||
for_each_vif_active_link(vif, link, link_id) {
|
||||
if (iwl_mld_link_set_associated(mld, vif, link))
|
||||
IWL_ERR(mld, "failed to update link %d\n", link_id);
|
||||
}
|
||||
|
||||
iwl_mld_recalc_multicast_filter(mld);
|
||||
}
|
||||
|
||||
static void iwl_mld_get_fw_id_bss_bitmap_iter(void *_data, u8 *mac,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
u8 *fw_id_bitmap = _data;
|
||||
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
|
||||
|
||||
if (ieee80211_vif_type_p2p(vif) != NL80211_IFTYPE_STATION)
|
||||
return;
|
||||
|
||||
*fw_id_bitmap |= BIT(mld_vif->fw_id);
|
||||
}
|
||||
|
||||
u8 iwl_mld_get_fw_bss_vifs_ids(struct iwl_mld *mld)
|
||||
{
|
||||
u8 fw_id_bitmap = 0;
|
||||
|
||||
ieee80211_iterate_active_interfaces_mtx(mld->hw,
|
||||
IEEE80211_IFACE_SKIP_SDATA_NOT_IN_DRIVER,
|
||||
iwl_mld_get_fw_id_bss_bitmap_iter,
|
||||
&fw_id_bitmap);
|
||||
|
||||
return fw_id_bitmap;
|
||||
}
|
||||
|
||||
void iwl_mld_handle_probe_resp_data_notif(struct iwl_mld *mld,
|
||||
struct iwl_rx_packet *pkt)
|
||||
{
|
||||
const struct iwl_probe_resp_data_notif *notif = (void *)pkt->data;
|
||||
struct iwl_probe_resp_data *old_data, *new_data;
|
||||
struct ieee80211_vif *vif;
|
||||
struct iwl_mld_link *mld_link;
|
||||
|
||||
IWL_DEBUG_INFO(mld, "Probe response data notif: noa %d, csa %d\n",
|
||||
notif->noa_active, notif->csa_counter);
|
||||
|
||||
if (IWL_FW_CHECK(mld, le32_to_cpu(notif->mac_id) >=
|
||||
ARRAY_SIZE(mld->fw_id_to_vif),
|
||||
"mac id is invalid: %d\n",
|
||||
le32_to_cpu(notif->mac_id)))
|
||||
return;
|
||||
|
||||
vif = wiphy_dereference(mld->wiphy,
|
||||
mld->fw_id_to_vif[le32_to_cpu(notif->mac_id)]);
|
||||
|
||||
/* the firmware gives us the mac_id (and not the link_id), mac80211
|
||||
* gets a vif and not a link, bottom line, this flow is not MLD ready
|
||||
* yet.
|
||||
*/
|
||||
if (WARN_ON(!vif) || ieee80211_vif_is_mld(vif))
|
||||
return;
|
||||
|
||||
if (notif->csa_counter != IWL_PROBE_RESP_DATA_NO_CSA &&
|
||||
notif->csa_counter >= 1)
|
||||
ieee80211_beacon_set_cntdwn(vif, notif->csa_counter);
|
||||
|
||||
if (!vif->p2p)
|
||||
return;
|
||||
|
||||
mld_link = &iwl_mld_vif_from_mac80211(vif)->deflink;
|
||||
|
||||
new_data = kzalloc(sizeof(*new_data), GFP_KERNEL);
|
||||
if (!new_data)
|
||||
return;
|
||||
|
||||
memcpy(&new_data->notif, notif, sizeof(new_data->notif));
|
||||
|
||||
/* noa_attr contains 1 reserved byte, need to substruct it */
|
||||
new_data->noa_len = sizeof(struct ieee80211_vendor_ie) +
|
||||
sizeof(new_data->notif.noa_attr) - 1;
|
||||
|
||||
/*
|
||||
* If it's a one time NoA, only one descriptor is needed,
|
||||
* adjust the length according to len_low.
|
||||
*/
|
||||
if (new_data->notif.noa_attr.len_low ==
|
||||
sizeof(struct ieee80211_p2p_noa_desc) + 2)
|
||||
new_data->noa_len -= sizeof(struct ieee80211_p2p_noa_desc);
|
||||
|
||||
old_data = wiphy_dereference(mld->wiphy, mld_link->probe_resp_data);
|
||||
rcu_assign_pointer(mld_link->probe_resp_data, new_data);
|
||||
|
||||
if (old_data)
|
||||
kfree_rcu(old_data, rcu_head);
|
||||
}
|
||||
|
||||
void iwl_mld_handle_uapsd_misbehaving_ap_notif(struct iwl_mld *mld,
|
||||
struct iwl_rx_packet *pkt)
|
||||
{
|
||||
struct iwl_uapsd_misbehaving_ap_notif *notif = (void *)pkt->data;
|
||||
struct ieee80211_vif *vif;
|
||||
|
||||
if (IWL_FW_CHECK(mld, notif->mac_id >= ARRAY_SIZE(mld->fw_id_to_vif),
|
||||
"mac id is invalid: %d\n", notif->mac_id))
|
||||
return;
|
||||
|
||||
vif = wiphy_dereference(mld->wiphy, mld->fw_id_to_vif[notif->mac_id]);
|
||||
|
||||
if (WARN_ON(!vif) || ieee80211_vif_is_mld(vif))
|
||||
return;
|
||||
|
||||
IWL_WARN(mld, "uapsd misbehaving AP: %pM\n", vif->bss_conf.bssid);
|
||||
}
|
||||
|
||||
void iwl_mld_handle_datapath_monitor_notif(struct iwl_mld *mld,
|
||||
struct iwl_rx_packet *pkt)
|
||||
{
|
||||
struct iwl_datapath_monitor_notif *notif = (void *)pkt->data;
|
||||
struct ieee80211_bss_conf *link;
|
||||
struct ieee80211_supported_band *sband;
|
||||
const struct ieee80211_sta_he_cap *he_cap;
|
||||
struct ieee80211_vif *vif;
|
||||
struct iwl_mld_vif *mld_vif;
|
||||
|
||||
if (notif->type != cpu_to_le32(IWL_DP_MON_NOTIF_TYPE_EXT_CCA))
|
||||
return;
|
||||
|
||||
link = iwl_mld_fw_id_to_link_conf(mld, notif->link_id);
|
||||
if (WARN_ON(!link))
|
||||
return;
|
||||
|
||||
vif = link->vif;
|
||||
if (WARN_ON(!vif) || vif->type != NL80211_IFTYPE_STATION ||
|
||||
!vif->cfg.assoc)
|
||||
return;
|
||||
|
||||
if (!link->chanreq.oper.chan ||
|
||||
link->chanreq.oper.chan->band != NL80211_BAND_2GHZ ||
|
||||
link->chanreq.oper.width < NL80211_CHAN_WIDTH_40)
|
||||
return;
|
||||
|
||||
mld_vif = iwl_mld_vif_from_mac80211(vif);
|
||||
|
||||
/* this shouldn't happen *again*, ignore it */
|
||||
if (mld_vif->cca_40mhz_workaround != CCA_40_MHZ_WA_NONE)
|
||||
return;
|
||||
|
||||
mld_vif->cca_40mhz_workaround = CCA_40_MHZ_WA_RECONNECT;
|
||||
|
||||
/*
|
||||
* This capability manipulation isn't really ideal, but it's the
|
||||
* easiest choice - otherwise we'd have to do some major changes
|
||||
* in mac80211 to support this, which isn't worth it. This does
|
||||
* mean that userspace may have outdated information, but that's
|
||||
* actually not an issue at all.
|
||||
*/
|
||||
sband = mld->wiphy->bands[NL80211_BAND_2GHZ];
|
||||
|
||||
WARN_ON(!sband->ht_cap.ht_supported);
|
||||
WARN_ON(!(sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40));
|
||||
sband->ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
|
||||
|
||||
he_cap = ieee80211_get_he_iftype_cap_vif(sband, vif);
|
||||
|
||||
if (he_cap) {
|
||||
/* we know that ours is writable */
|
||||
struct ieee80211_sta_he_cap *he = (void *)(uintptr_t)he_cap;
|
||||
|
||||
WARN_ON(!he->has_he);
|
||||
WARN_ON(!(he->he_cap_elem.phy_cap_info[0] &
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G));
|
||||
he->he_cap_elem.phy_cap_info[0] &=
|
||||
~IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G;
|
||||
}
|
||||
|
||||
ieee80211_disconnect(vif, true);
|
||||
}
|
||||
|
||||
void iwl_mld_reset_cca_40mhz_workaround(struct iwl_mld *mld,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ieee80211_supported_band *sband;
|
||||
const struct ieee80211_sta_he_cap *he_cap;
|
||||
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
|
||||
|
||||
if (vif->type != NL80211_IFTYPE_STATION)
|
||||
return;
|
||||
|
||||
if (mld_vif->cca_40mhz_workaround == CCA_40_MHZ_WA_NONE)
|
||||
return;
|
||||
|
||||
/* Now we are just reconnecting with the new capabilities,
|
||||
* but remember to reset the capabilities when we disconnect for real
|
||||
*/
|
||||
if (mld_vif->cca_40mhz_workaround == CCA_40_MHZ_WA_RECONNECT) {
|
||||
mld_vif->cca_40mhz_workaround = CCA_40_MHZ_WA_RESET;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Now cca_40mhz_workaround == CCA_40_MHZ_WA_RESET */
|
||||
|
||||
sband = mld->wiphy->bands[NL80211_BAND_2GHZ];
|
||||
|
||||
sband->ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
|
||||
|
||||
he_cap = ieee80211_get_he_iftype_cap_vif(sband, vif);
|
||||
|
||||
if (he_cap) {
|
||||
/* we know that ours is writable */
|
||||
struct ieee80211_sta_he_cap *he = (void *)(uintptr_t)he_cap;
|
||||
|
||||
he->he_cap_elem.phy_cap_info[0] |=
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G;
|
||||
}
|
||||
|
||||
mld_vif->cca_40mhz_workaround = CCA_40_MHZ_WA_NONE;
|
||||
}
|
||||
|
||||
struct ieee80211_vif *iwl_mld_get_bss_vif(struct iwl_mld *mld)
|
||||
{
|
||||
unsigned long fw_id_bitmap = iwl_mld_get_fw_bss_vifs_ids(mld);
|
||||
int fw_id;
|
||||
|
||||
if (hweight8(fw_id_bitmap) != 1)
|
||||
return NULL;
|
||||
|
||||
fw_id = __ffs(fw_id_bitmap);
|
||||
|
||||
return wiphy_dereference(mld->wiphy,
|
||||
mld->fw_id_to_vif[fw_id]);
|
||||
}
|
||||
@@ -0,0 +1,253 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2024-2025 Intel Corporation
|
||||
*/
|
||||
#ifndef __iwl_mld_iface_h__
|
||||
#define __iwl_mld_iface_h__
|
||||
|
||||
#include <net/mac80211.h>
|
||||
|
||||
#include "link.h"
|
||||
#include "session-protect.h"
|
||||
#include "d3.h"
|
||||
#include "fw/api/time-event.h"
|
||||
|
||||
enum iwl_mld_cca_40mhz_wa_status {
|
||||
CCA_40_MHZ_WA_NONE,
|
||||
CCA_40_MHZ_WA_RESET,
|
||||
CCA_40_MHZ_WA_RECONNECT,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum iwl_mld_emlsr_blocked - defines reasons for which EMLSR is blocked
|
||||
*
|
||||
* These blocks are applied/stored per-VIF.
|
||||
*
|
||||
* @IWL_MLD_EMLSR_BLOCKED_PREVENTION: Prevent repeated EMLSR enter/exit
|
||||
* @IWL_MLD_EMLSR_BLOCKED_WOWLAN: WOWLAN is preventing EMLSR
|
||||
* @IWL_MLD_EMLSR_BLOCKED_ROC: remain-on-channel is preventing EMLSR
|
||||
* @IWL_MLD_EMLSR_BLOCKED_NON_BSS: An active non-BSS interface's link is
|
||||
* preventing EMLSR
|
||||
* @IWL_MLD_EMLSR_BLOCKED_TMP_NON_BSS: An expected active non-BSS interface's
|
||||
* link is preventing EMLSR. This is a temporary blocking that is set when
|
||||
* there is an indication that a non-BSS interface is to be added.
|
||||
* @IWL_MLD_EMLSR_BLOCKED_TPT: throughput is too low to make EMLSR worthwhile
|
||||
*/
|
||||
enum iwl_mld_emlsr_blocked {
|
||||
IWL_MLD_EMLSR_BLOCKED_PREVENTION = 0x1,
|
||||
IWL_MLD_EMLSR_BLOCKED_WOWLAN = 0x2,
|
||||
IWL_MLD_EMLSR_BLOCKED_ROC = 0x4,
|
||||
IWL_MLD_EMLSR_BLOCKED_NON_BSS = 0x8,
|
||||
IWL_MLD_EMLSR_BLOCKED_TMP_NON_BSS = 0x10,
|
||||
IWL_MLD_EMLSR_BLOCKED_TPT = 0x20,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum iwl_mld_emlsr_exit - defines reasons for exiting EMLSR
|
||||
*
|
||||
* Reasons to exit EMLSR may be either link specific or even specific to a
|
||||
* combination of links.
|
||||
*
|
||||
* @IWL_MLD_EMLSR_EXIT_BLOCK: Exit due to a block reason being set
|
||||
* @IWL_MLD_EMLSR_EXIT_MISSED_BEACON: Exit due to missed beacons
|
||||
* @IWL_MLD_EMLSR_EXIT_FAIL_ENTRY: FW failed to enter EMLSR
|
||||
* @IWL_MLD_EMLSR_EXIT_CSA: EMLSR prevented due to channel switch on link
|
||||
* @IWL_MLD_EMLSR_EXIT_EQUAL_BAND: EMLSR prevented as both links share the band
|
||||
* @IWL_MLD_EMLSR_EXIT_LOW_RSSI: Link RSSI is unsuitable for EMLSR
|
||||
* @IWL_MLD_EMLSR_EXIT_LINK_USAGE: Exit EMLSR due to low TPT on secondary link
|
||||
* @IWL_MLD_EMLSR_EXIT_BT_COEX: Exit EMLSR due to BT coexistence
|
||||
* @IWL_MLD_EMLSR_EXIT_CHAN_LOAD: Exit EMLSR because the primary channel is not
|
||||
* loaded enough to justify EMLSR.
|
||||
* @IWL_MLD_EMLSR_EXIT_RFI: Exit EMLSR due to RFI
|
||||
* @IWL_MLD_EMLSR_EXIT_FW_REQUEST: Exit EMLSR because the FW requested it
|
||||
* @IWL_MLD_EMLSR_EXIT_INVALID: internal exit reason due to invalid data
|
||||
*/
|
||||
enum iwl_mld_emlsr_exit {
|
||||
IWL_MLD_EMLSR_EXIT_BLOCK = 0x1,
|
||||
IWL_MLD_EMLSR_EXIT_MISSED_BEACON = 0x2,
|
||||
IWL_MLD_EMLSR_EXIT_FAIL_ENTRY = 0x4,
|
||||
IWL_MLD_EMLSR_EXIT_CSA = 0x8,
|
||||
IWL_MLD_EMLSR_EXIT_EQUAL_BAND = 0x10,
|
||||
IWL_MLD_EMLSR_EXIT_LOW_RSSI = 0x20,
|
||||
IWL_MLD_EMLSR_EXIT_LINK_USAGE = 0x40,
|
||||
IWL_MLD_EMLSR_EXIT_BT_COEX = 0x80,
|
||||
IWL_MLD_EMLSR_EXIT_CHAN_LOAD = 0x100,
|
||||
IWL_MLD_EMLSR_EXIT_RFI = 0x200,
|
||||
IWL_MLD_EMLSR_EXIT_FW_REQUEST = 0x400,
|
||||
IWL_MLD_EMLSR_EXIT_INVALID = 0x800,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_mld_emlsr - per-VIF data about EMLSR operation
|
||||
*
|
||||
* @primary: The current primary link
|
||||
* @selected_primary: Primary link as selected during the last link selection
|
||||
* @selected_links: Links as selected during the last link selection
|
||||
* @blocked_reasons: Reasons preventing EMLSR from being enabled
|
||||
* @last_exit_reason: Reason for the last EMLSR exit
|
||||
* @last_exit_ts: Time of the last EMLSR exit (if @last_exit_reason is non-zero)
|
||||
* @exit_repeat_count: Number of times EMLSR was exited for the same reason
|
||||
* @last_entry_ts: the time of the last EMLSR entry (if iwl_mld_emlsr_active()
|
||||
* is true)
|
||||
* @unblock_tpt_wk: Unblock EMLSR because the throughput limit was reached
|
||||
* @check_tpt_wk: a worker to check if IWL_MLD_EMLSR_BLOCKED_TPT should be
|
||||
* added, for example if there is no longer enough traffic.
|
||||
* @prevent_done_wk: Worker to remove %IWL_MLD_EMLSR_BLOCKED_PREVENTION
|
||||
* @tmp_non_bss_done_wk: Worker to remove %IWL_MLD_EMLSR_BLOCKED_TMP_NON_BSS
|
||||
*/
|
||||
struct iwl_mld_emlsr {
|
||||
struct_group(zeroed_on_not_authorized,
|
||||
u8 primary;
|
||||
|
||||
u8 selected_primary;
|
||||
u16 selected_links;
|
||||
|
||||
enum iwl_mld_emlsr_blocked blocked_reasons;
|
||||
|
||||
enum iwl_mld_emlsr_exit last_exit_reason;
|
||||
unsigned long last_exit_ts;
|
||||
u8 exit_repeat_count;
|
||||
unsigned long last_entry_ts;
|
||||
);
|
||||
|
||||
struct wiphy_work unblock_tpt_wk;
|
||||
struct wiphy_delayed_work check_tpt_wk;
|
||||
|
||||
struct wiphy_delayed_work prevent_done_wk;
|
||||
struct wiphy_delayed_work tmp_non_bss_done_wk;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_mld_vif - virtual interface (MAC context) configuration parameters
|
||||
*
|
||||
* @fw_id: fw id of the mac context.
|
||||
* @session_protect: session protection parameters
|
||||
* @ap_sta: pointer to AP sta, for easier access to it.
|
||||
* Relevant only for STA vifs.
|
||||
* @authorized: indicates the AP station was set to authorized
|
||||
* @bigtks: BIGTKs of the AP, for beacon protection.
|
||||
* Only valid for STA. (FIXME: needs to be per link)
|
||||
* @num_associated_stas: number of associated STAs. Relevant only for AP mode.
|
||||
* @ap_ibss_active: whether the AP/IBSS was started
|
||||
* @cca_40mhz_workaround: When we are connected in 2.4 GHz and 40 MHz, and the
|
||||
* environment is too loaded, we work around this by reconnecting to the
|
||||
* same AP with 20 MHz. This manages the status of the workaround.
|
||||
* @beacon_inject_active: indicates an active debugfs beacon ie injection
|
||||
* @low_latency_causes: bit flags, indicating the causes for low-latency,
|
||||
* see @iwl_mld_low_latency_cause.
|
||||
* @ps_disabled: indicates that PS is disabled for this interface
|
||||
* @last_link_activation_time: last time a link was activated, for
|
||||
* deferring MLO scans (to make them more reliable)
|
||||
* @mld: pointer to the mld structure.
|
||||
* @deflink: default link data, for use in non-MLO,
|
||||
* @link: reference to link data for each valid link, for use in MLO.
|
||||
* @emlsr: information related to EMLSR
|
||||
* @wowlan_data: data used by the wowlan suspend flow
|
||||
* @use_ps_poll: use ps_poll frames
|
||||
* @disable_bf: disable beacon filter
|
||||
* @dbgfs_slink: debugfs symlink for this interface
|
||||
* @roc_activity: the id of the roc_activity running. Relevant for STA and
|
||||
* p2p device only. Set to %ROC_NUM_ACTIVITIES when not in use.
|
||||
* @aux_sta: station used for remain on channel. Used in P2P device.
|
||||
* @mlo_scan_start_wk: worker to start a deferred MLO scan
|
||||
*/
|
||||
struct iwl_mld_vif {
|
||||
/* Add here fields that need clean up on restart */
|
||||
struct_group(zeroed_on_hw_restart,
|
||||
u8 fw_id;
|
||||
struct iwl_mld_session_protect session_protect;
|
||||
struct ieee80211_sta *ap_sta;
|
||||
bool authorized;
|
||||
struct ieee80211_key_conf __rcu *bigtks[2];
|
||||
u8 num_associated_stas;
|
||||
bool ap_ibss_active;
|
||||
enum iwl_mld_cca_40mhz_wa_status cca_40mhz_workaround;
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
bool beacon_inject_active;
|
||||
#endif
|
||||
u8 low_latency_causes;
|
||||
bool ps_disabled;
|
||||
time64_t last_link_activation_time;
|
||||
);
|
||||
/* And here fields that survive a fw restart */
|
||||
struct iwl_mld *mld;
|
||||
struct iwl_mld_link deflink;
|
||||
struct iwl_mld_link __rcu *link[IEEE80211_MLD_MAX_NUM_LINKS];
|
||||
|
||||
struct iwl_mld_emlsr emlsr;
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
struct iwl_mld_wowlan_data wowlan_data;
|
||||
#endif
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
bool use_ps_poll;
|
||||
bool disable_bf;
|
||||
struct dentry *dbgfs_slink;
|
||||
#endif
|
||||
enum iwl_roc_activity roc_activity;
|
||||
struct iwl_mld_int_sta aux_sta;
|
||||
|
||||
struct wiphy_delayed_work mlo_scan_start_wk;
|
||||
};
|
||||
|
||||
static inline struct iwl_mld_vif *
|
||||
iwl_mld_vif_from_mac80211(struct ieee80211_vif *vif)
|
||||
{
|
||||
return (void *)vif->drv_priv;
|
||||
}
|
||||
|
||||
static inline struct ieee80211_vif *
|
||||
iwl_mld_vif_to_mac80211(struct iwl_mld_vif *mld_vif)
|
||||
{
|
||||
return container_of((void *)mld_vif, struct ieee80211_vif, drv_priv);
|
||||
}
|
||||
|
||||
#define iwl_mld_link_dereference_check(mld_vif, link_id) \
|
||||
rcu_dereference_check((mld_vif)->link[link_id], \
|
||||
lockdep_is_held(&mld_vif->mld->wiphy->mtx))
|
||||
|
||||
#define for_each_mld_vif_valid_link(mld_vif, mld_link) \
|
||||
for (int link_id = 0; link_id < ARRAY_SIZE((mld_vif)->link); \
|
||||
link_id++) \
|
||||
if ((mld_link = iwl_mld_link_dereference_check(mld_vif, link_id)))
|
||||
|
||||
/* Retrieve pointer to mld link from mac80211 structures */
|
||||
static inline struct iwl_mld_link *
|
||||
iwl_mld_link_from_mac80211(struct ieee80211_bss_conf *bss_conf)
|
||||
{
|
||||
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(bss_conf->vif);
|
||||
|
||||
return iwl_mld_link_dereference_check(mld_vif, bss_conf->link_id);
|
||||
}
|
||||
|
||||
int iwl_mld_mac80211_iftype_to_fw(const struct ieee80211_vif *vif);
|
||||
|
||||
/* Cleanup function for struct iwl_mld_vif, will be called in restart */
|
||||
void iwl_mld_cleanup_vif(void *data, u8 *mac, struct ieee80211_vif *vif);
|
||||
int iwl_mld_mac_fw_action(struct iwl_mld *mld, struct ieee80211_vif *vif,
|
||||
u32 action);
|
||||
int iwl_mld_add_vif(struct iwl_mld *mld, struct ieee80211_vif *vif);
|
||||
int iwl_mld_rm_vif(struct iwl_mld *mld, struct ieee80211_vif *vif);
|
||||
void iwl_mld_set_vif_associated(struct iwl_mld *mld,
|
||||
struct ieee80211_vif *vif);
|
||||
u8 iwl_mld_get_fw_bss_vifs_ids(struct iwl_mld *mld);
|
||||
void iwl_mld_handle_probe_resp_data_notif(struct iwl_mld *mld,
|
||||
struct iwl_rx_packet *pkt);
|
||||
|
||||
void iwl_mld_handle_datapath_monitor_notif(struct iwl_mld *mld,
|
||||
struct iwl_rx_packet *pkt);
|
||||
|
||||
void iwl_mld_handle_uapsd_misbehaving_ap_notif(struct iwl_mld *mld,
|
||||
struct iwl_rx_packet *pkt);
|
||||
|
||||
void iwl_mld_reset_cca_40mhz_workaround(struct iwl_mld *mld,
|
||||
struct ieee80211_vif *vif);
|
||||
|
||||
static inline bool iwl_mld_vif_low_latency(const struct iwl_mld_vif *mld_vif)
|
||||
{
|
||||
return !!mld_vif->low_latency_causes;
|
||||
}
|
||||
|
||||
struct ieee80211_vif *iwl_mld_get_bss_vif(struct iwl_mld *mld);
|
||||
|
||||
#endif /* __iwl_mld_iface_h__ */
|
||||
@@ -0,0 +1,370 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2024 Intel Corporation
|
||||
*/
|
||||
#include "key.h"
|
||||
#include "iface.h"
|
||||
#include "sta.h"
|
||||
#include "fw/api/datapath.h"
|
||||
|
||||
static u32 iwl_mld_get_key_flags(struct iwl_mld *mld,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *key)
|
||||
{
|
||||
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
|
||||
bool pairwise = key->flags & IEEE80211_KEY_FLAG_PAIRWISE;
|
||||
bool igtk = key->keyidx == 4 || key->keyidx == 5;
|
||||
u32 flags = 0;
|
||||
|
||||
if (!pairwise)
|
||||
flags |= IWL_SEC_KEY_FLAG_MCAST_KEY;
|
||||
|
||||
switch (key->cipher) {
|
||||
case WLAN_CIPHER_SUITE_TKIP:
|
||||
flags |= IWL_SEC_KEY_FLAG_CIPHER_TKIP;
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_AES_CMAC:
|
||||
case WLAN_CIPHER_SUITE_CCMP:
|
||||
flags |= IWL_SEC_KEY_FLAG_CIPHER_CCMP;
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_GCMP_256:
|
||||
case WLAN_CIPHER_SUITE_BIP_GMAC_256:
|
||||
flags |= IWL_SEC_KEY_FLAG_KEY_SIZE;
|
||||
fallthrough;
|
||||
case WLAN_CIPHER_SUITE_GCMP:
|
||||
case WLAN_CIPHER_SUITE_BIP_GMAC_128:
|
||||
flags |= IWL_SEC_KEY_FLAG_CIPHER_GCMP;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!sta && vif->type == NL80211_IFTYPE_STATION)
|
||||
sta = mld_vif->ap_sta;
|
||||
|
||||
/* If we are installing an iGTK (in AP or STA mode), we need to tell
|
||||
* the firmware this key will en/decrypt MGMT frames.
|
||||
* Same goes if we are installing a pairwise key for an MFP station.
|
||||
* In case we're installing a groupwise key (which is not an iGTK),
|
||||
* then, we will not use this key for MGMT frames.
|
||||
*/
|
||||
if ((sta && sta->mfp && pairwise) || igtk)
|
||||
flags |= IWL_SEC_KEY_FLAG_MFP;
|
||||
|
||||
if (key->flags & IEEE80211_KEY_FLAG_SPP_AMSDU)
|
||||
flags |= IWL_SEC_KEY_FLAG_SPP_AMSDU;
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
static u32 iwl_mld_get_key_sta_mask(struct iwl_mld *mld,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *key)
|
||||
{
|
||||
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
|
||||
struct ieee80211_link_sta *link_sta;
|
||||
int sta_id;
|
||||
|
||||
lockdep_assert_wiphy(mld->wiphy);
|
||||
|
||||
/* AP group keys are per link and should be on the mcast/bcast STA */
|
||||
if (vif->type == NL80211_IFTYPE_AP &&
|
||||
!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
|
||||
struct iwl_mld_link *link = NULL;
|
||||
|
||||
if (key->link_id >= 0)
|
||||
link = iwl_mld_link_dereference_check(mld_vif,
|
||||
key->link_id);
|
||||
|
||||
if (WARN_ON(!link))
|
||||
return 0;
|
||||
|
||||
/* In this stage we should have both the bcast and mcast STAs */
|
||||
if (WARN_ON(link->bcast_sta.sta_id == IWL_INVALID_STA ||
|
||||
link->mcast_sta.sta_id == IWL_INVALID_STA))
|
||||
return 0;
|
||||
|
||||
/* IGTK/BIGTK to bcast STA */
|
||||
if (key->keyidx >= 4)
|
||||
return BIT(link->bcast_sta.sta_id);
|
||||
|
||||
/* GTK for data to mcast STA */
|
||||
return BIT(link->mcast_sta.sta_id);
|
||||
}
|
||||
|
||||
/* for client mode use the AP STA also for group keys */
|
||||
if (!sta && vif->type == NL80211_IFTYPE_STATION)
|
||||
sta = mld_vif->ap_sta;
|
||||
|
||||
/* STA should be non-NULL now */
|
||||
if (WARN_ON(!sta))
|
||||
return 0;
|
||||
|
||||
/* Key is not per-link, get the full sta mask */
|
||||
if (key->link_id < 0)
|
||||
return iwl_mld_fw_sta_id_mask(mld, sta);
|
||||
|
||||
/* The link_sta shouldn't be NULL now, but this is checked in
|
||||
* iwl_mld_fw_sta_id_mask
|
||||
*/
|
||||
link_sta = link_sta_dereference_check(sta, key->link_id);
|
||||
|
||||
sta_id = iwl_mld_fw_sta_id_from_link_sta(mld, link_sta);
|
||||
if (sta_id < 0)
|
||||
return 0;
|
||||
|
||||
return BIT(sta_id);
|
||||
}
|
||||
|
||||
static int iwl_mld_add_key_to_fw(struct iwl_mld *mld, u32 sta_mask,
|
||||
u32 key_flags, struct ieee80211_key_conf *key)
|
||||
{
|
||||
struct iwl_sec_key_cmd cmd = {
|
||||
.action = cpu_to_le32(FW_CTXT_ACTION_ADD),
|
||||
.u.add.sta_mask = cpu_to_le32(sta_mask),
|
||||
.u.add.key_id = cpu_to_le32(key->keyidx),
|
||||
.u.add.key_flags = cpu_to_le32(key_flags),
|
||||
.u.add.tx_seq = cpu_to_le64(atomic64_read(&key->tx_pn)),
|
||||
};
|
||||
bool tkip = key->cipher == WLAN_CIPHER_SUITE_TKIP;
|
||||
int max_key_len = sizeof(cmd.u.add.key);
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
/* If there was a rekey in wowlan, FW already has the key */
|
||||
if (mld->fw_status.resuming)
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
if (WARN_ON(!sta_mask))
|
||||
return -EINVAL;
|
||||
|
||||
if (WARN_ON(key->keylen > max_key_len))
|
||||
return -EINVAL;
|
||||
|
||||
memcpy(cmd.u.add.key, key->key, key->keylen);
|
||||
|
||||
if (tkip) {
|
||||
memcpy(cmd.u.add.tkip_mic_rx_key,
|
||||
key->key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY,
|
||||
8);
|
||||
memcpy(cmd.u.add.tkip_mic_tx_key,
|
||||
key->key + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY,
|
||||
8);
|
||||
}
|
||||
|
||||
return iwl_mld_send_cmd_pdu(mld, WIDE_ID(DATA_PATH_GROUP, SEC_KEY_CMD),
|
||||
&cmd);
|
||||
}
|
||||
|
||||
static void iwl_mld_remove_key_from_fw(struct iwl_mld *mld, u32 sta_mask,
|
||||
u32 key_flags, u32 keyidx)
|
||||
{
|
||||
struct iwl_sec_key_cmd cmd = {
|
||||
.action = cpu_to_le32(FW_CTXT_ACTION_REMOVE),
|
||||
.u.remove.sta_mask = cpu_to_le32(sta_mask),
|
||||
.u.remove.key_id = cpu_to_le32(keyidx),
|
||||
.u.remove.key_flags = cpu_to_le32(key_flags),
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
/* If there was a rekey in wowlan, FW already removed the key */
|
||||
if (mld->fw_status.resuming)
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (WARN_ON(!sta_mask))
|
||||
return;
|
||||
|
||||
iwl_mld_send_cmd_pdu(mld, WIDE_ID(DATA_PATH_GROUP, SEC_KEY_CMD), &cmd);
|
||||
}
|
||||
|
||||
void iwl_mld_remove_key(struct iwl_mld *mld, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *key)
|
||||
{
|
||||
u32 sta_mask = iwl_mld_get_key_sta_mask(mld, vif, sta, key);
|
||||
u32 key_flags = iwl_mld_get_key_flags(mld, vif, sta, key);
|
||||
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
|
||||
|
||||
lockdep_assert_wiphy(mld->wiphy);
|
||||
|
||||
if (!sta_mask)
|
||||
return;
|
||||
|
||||
if (key->keyidx == 4 || key->keyidx == 5) {
|
||||
struct iwl_mld_link *mld_link;
|
||||
unsigned int link_id = 0;
|
||||
|
||||
/* set to -1 for non-MLO right now */
|
||||
if (key->link_id >= 0)
|
||||
link_id = key->link_id;
|
||||
|
||||
mld_link = iwl_mld_link_dereference_check(mld_vif, link_id);
|
||||
if (WARN_ON(!mld_link))
|
||||
return;
|
||||
|
||||
if (mld_link->igtk == key)
|
||||
mld_link->igtk = NULL;
|
||||
|
||||
mld->num_igtks--;
|
||||
}
|
||||
|
||||
iwl_mld_remove_key_from_fw(mld, sta_mask, key_flags, key->keyidx);
|
||||
|
||||
/* no longer in HW */
|
||||
key->hw_key_idx = STA_KEY_IDX_INVALID;
|
||||
}
|
||||
|
||||
int iwl_mld_add_key(struct iwl_mld *mld,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *key)
|
||||
{
|
||||
u32 sta_mask = iwl_mld_get_key_sta_mask(mld, vif, sta, key);
|
||||
u32 key_flags = iwl_mld_get_key_flags(mld, vif, sta, key);
|
||||
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
|
||||
struct iwl_mld_link *mld_link = NULL;
|
||||
bool igtk = key->keyidx == 4 || key->keyidx == 5;
|
||||
int ret;
|
||||
|
||||
lockdep_assert_wiphy(mld->wiphy);
|
||||
|
||||
if (!sta_mask)
|
||||
return -EINVAL;
|
||||
|
||||
if (igtk) {
|
||||
if (mld->num_igtks == IWL_MAX_NUM_IGTKS)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
u8 link_id = 0;
|
||||
|
||||
/* set to -1 for non-MLO right now */
|
||||
if (key->link_id >= 0)
|
||||
link_id = key->link_id;
|
||||
|
||||
mld_link = iwl_mld_link_dereference_check(mld_vif, link_id);
|
||||
|
||||
if (WARN_ON(!mld_link))
|
||||
return -EINVAL;
|
||||
|
||||
if (mld_link->igtk) {
|
||||
IWL_DEBUG_MAC80211(mld, "remove old IGTK %d\n",
|
||||
mld_link->igtk->keyidx);
|
||||
iwl_mld_remove_key(mld, vif, sta, mld_link->igtk);
|
||||
}
|
||||
|
||||
WARN_ON(mld_link->igtk);
|
||||
}
|
||||
|
||||
ret = iwl_mld_add_key_to_fw(mld, sta_mask, key_flags, key);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (mld_link) {
|
||||
mld_link->igtk = key;
|
||||
mld->num_igtks++;
|
||||
}
|
||||
|
||||
/* We don't really need this, but need it to be not invalid,
|
||||
* so we will know if the key is in fw.
|
||||
*/
|
||||
key->hw_key_idx = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct remove_ap_keys_iter_data {
|
||||
u8 link_id;
|
||||
struct ieee80211_sta *sta;
|
||||
};
|
||||
|
||||
static void iwl_mld_remove_ap_keys_iter(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *key,
|
||||
void *_data)
|
||||
{
|
||||
struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
|
||||
struct remove_ap_keys_iter_data *data = _data;
|
||||
|
||||
if (key->hw_key_idx == STA_KEY_IDX_INVALID)
|
||||
return;
|
||||
|
||||
/* All the pairwise keys should have been removed by now */
|
||||
if (WARN_ON(sta))
|
||||
return;
|
||||
|
||||
if (key->link_id >= 0 && key->link_id != data->link_id)
|
||||
return;
|
||||
|
||||
iwl_mld_remove_key(mld, vif, data->sta, key);
|
||||
}
|
||||
|
||||
void iwl_mld_remove_ap_keys(struct iwl_mld *mld, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, unsigned int link_id)
|
||||
{
|
||||
struct remove_ap_keys_iter_data iter_data = {
|
||||
.link_id = link_id,
|
||||
.sta = sta,
|
||||
};
|
||||
|
||||
if (WARN_ON_ONCE(vif->type != NL80211_IFTYPE_STATION))
|
||||
return;
|
||||
|
||||
ieee80211_iter_keys(mld->hw, vif,
|
||||
iwl_mld_remove_ap_keys_iter,
|
||||
&iter_data);
|
||||
}
|
||||
|
||||
struct iwl_mvm_sta_key_update_data {
|
||||
struct ieee80211_sta *sta;
|
||||
u32 old_sta_mask;
|
||||
u32 new_sta_mask;
|
||||
int err;
|
||||
};
|
||||
|
||||
static void iwl_mld_update_sta_key_iter(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *key,
|
||||
void *_data)
|
||||
{
|
||||
struct iwl_mvm_sta_key_update_data *data = _data;
|
||||
struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
|
||||
struct iwl_sec_key_cmd cmd = {
|
||||
.action = cpu_to_le32(FW_CTXT_ACTION_MODIFY),
|
||||
.u.modify.old_sta_mask = cpu_to_le32(data->old_sta_mask),
|
||||
.u.modify.new_sta_mask = cpu_to_le32(data->new_sta_mask),
|
||||
.u.modify.key_id = cpu_to_le32(key->keyidx),
|
||||
.u.modify.key_flags =
|
||||
cpu_to_le32(iwl_mld_get_key_flags(mld, vif, sta, key)),
|
||||
};
|
||||
int err;
|
||||
|
||||
/* only need to do this for pairwise keys (link_id == -1) */
|
||||
if (sta != data->sta || key->link_id >= 0)
|
||||
return;
|
||||
|
||||
err = iwl_mld_send_cmd_pdu(mld, WIDE_ID(DATA_PATH_GROUP, SEC_KEY_CMD),
|
||||
&cmd);
|
||||
|
||||
if (err)
|
||||
data->err = err;
|
||||
}
|
||||
|
||||
int iwl_mld_update_sta_keys(struct iwl_mld *mld,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
u32 old_sta_mask,
|
||||
u32 new_sta_mask)
|
||||
{
|
||||
struct iwl_mvm_sta_key_update_data data = {
|
||||
.sta = sta,
|
||||
.old_sta_mask = old_sta_mask,
|
||||
.new_sta_mask = new_sta_mask,
|
||||
};
|
||||
|
||||
ieee80211_iter_keys(mld->hw, vif, iwl_mld_update_sta_key_iter,
|
||||
&data);
|
||||
return data.err;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2024 Intel Corporation
|
||||
*/
|
||||
#ifndef __iwl_mld_key_h__
|
||||
#define __iwl_mld_key_h__
|
||||
|
||||
#include "mld.h"
|
||||
#include <net/mac80211.h>
|
||||
#include "fw/api/sta.h"
|
||||
|
||||
void iwl_mld_remove_key(struct iwl_mld *mld,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *key);
|
||||
int iwl_mld_add_key(struct iwl_mld *mld,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *key);
|
||||
void iwl_mld_remove_ap_keys(struct iwl_mld *mld,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
unsigned int link_id);
|
||||
|
||||
int iwl_mld_update_sta_keys(struct iwl_mld *mld,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
u32 old_sta_mask,
|
||||
u32 new_sta_mask);
|
||||
|
||||
static inline void
|
||||
iwl_mld_cleanup_keys_iter(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *key, void *data)
|
||||
{
|
||||
key->hw_key_idx = STA_KEY_IDX_INVALID;
|
||||
}
|
||||
|
||||
#endif /* __iwl_mld_key_h__ */
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user