iwlwifi: import Intel's iwlwifi/mvm driver.

Over the past few months we published multiple snapshots for this
Linux derived driver and it has become fairly stable in terms of
minimal local changes needed for new updates.

The current version is based on iwlwifi-next update at
cbaa6aeedee5f92dafa5982eceea2a1f98ce4f7d with the addition of
a hand full of files replaced for FreeBSD.

Given the lack of full license texts on non-local files this is
imported under the draft policy for handling SPDX files (D29226). [1]

Do not yet hook this to the build until the remaining compat code
is all in.  Along with the firmware import this will make publishing
the last bits and final testing a lot easier.

Sponsored by:   The FreeBSD Foundation
Approved by:    core (imp) [1]
MFC after:      10 days
This commit is contained in:
Bjoern A. Zeeb 2021-11-28 18:35:53 +00:00
parent f4c129f5fb
commit bfcc09ddd4
133 changed files with 86183 additions and 0 deletions

View File

@ -0,0 +1,909 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2015-2017 Intel Deutschland GmbH
* Copyright (C) 2018-2021 Intel Corporation
*/
#include <linux/module.h>
#include <linux/stringify.h>
#include "iwl-config.h"
#include "iwl-prph.h"
/* Highest firmware API version supported */
#define IWL_22000_UCODE_API_MAX 67
/* Lowest firmware API version supported */
#define IWL_22000_UCODE_API_MIN 39
/* 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_QNJ_B_HR_B_FW_PRE "iwlwifi-QuQnj-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_QNJ_B_JF_B_FW_PRE "iwlwifi-QuQnj-b0-jf-b0-"
#define IWL_CC_A_FW_PRE "iwlwifi-cc-a0-"
#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_SNJ_A_GF4_A_FW_PRE "iwlwifi-SoSnj-a0-gf4-a0-"
#define IWL_SNJ_A_GF_A_FW_PRE "iwlwifi-SoSnj-a0-gf-a0-"
#define IWL_SNJ_A_HR_B_FW_PRE "iwlwifi-SoSnj-a0-hr-b0-"
#define IWL_SNJ_A_JF_B_FW_PRE "iwlwifi-SoSnj-a0-jf-b0-"
#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_A_FM_A_FW_PRE "iwlwifi-ma-a0-fm-a0-"
#define IWL_SNJ_A_MR_A_FW_PRE "iwlwifi-SoSnj-a0-mr-a0-"
#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_MR_A_FW_PRE "iwlwifi-bz-a0-mr-a0-"
#define IWL_BZ_A_FM_A_FW_PRE "iwlwifi-bz-a0-fm-a0-"
#define IWL_GL_A_FM_A_FW_PRE "iwlwifi-gl-a0-fm7-a0-"
#define IWL_QU_B_HR_B_MODULE_FIRMWARE(api) \
IWL_QU_B_HR_B_FW_PRE __stringify(api) ".ucode"
#define IWL_QNJ_B_HR_B_MODULE_FIRMWARE(api) \
IWL_QNJ_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_QNJ_B_JF_B_MODULE_FIRMWARE(api) \
IWL_QNJ_B_JF_B_FW_PRE __stringify(api) ".ucode"
#define IWL_CC_A_MODULE_FIRMWARE(api) \
IWL_CC_A_FW_PRE __stringify(api) ".ucode"
#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_SNJ_A_GF4_A_MODULE_FIRMWARE(api) \
IWL_SNJ_A_GF4_A_FW_PRE __stringify(api) ".ucode"
#define IWL_SNJ_A_GF_A_MODULE_FIRMWARE(api) \
IWL_SNJ_A_GF_A_FW_PRE __stringify(api) ".ucode"
#define IWL_SNJ_A_HR_B_MODULE_FIRMWARE(api) \
IWL_SNJ_A_HR_B_FW_PRE __stringify(api) ".ucode"
#define IWL_SNJ_A_JF_B_MODULE_FIRMWARE(api) \
IWL_SNJ_A_JF_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_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_A_FM_A_FW_MODULE_FIRMWARE(api) \
IWL_MA_A_FM_A_FW_PRE __stringify(api) ".ucode"
#define IWL_SNJ_A_MR_A_MODULE_FIRMWARE(api) \
IWL_SNJ_A_MR_A_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_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_MR_A_MODULE_FIRMWARE(api) \
IWL_BZ_A_MR_A_FW_PRE __stringify(api) ".ucode"
#define IWL_BZ_A_FM_A_MODULE_FIRMWARE(api) \
IWL_BZ_A_FM_A_FW_PRE __stringify(api) ".ucode"
#define IWL_GL_A_FM_A_MODULE_FIRMWARE(api) \
IWL_GL_A_FM_A_FW_PRE __stringify(api) ".ucode"
static const struct iwl_base_params iwl_22000_base_params = {
.eeprom_size = OTP_LOW_IMAGE_SIZE_32K,
.num_of_queues = 512,
.max_tfd_queue_size = 256,
.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,
};
static const struct iwl_base_params iwl_ax210_base_params = {
.eeprom_size = OTP_LOW_IMAGE_SIZE_32K,
.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,
};
static 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_max = IWL_22000_UCODE_API_MAX, \
.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.use_tfh = true, \
.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, \
.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, \
}, \
}
#define IWL_DEVICE_AX210 \
IWL_DEVICE_22000_COMMON, \
.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_256_ba_txq_size = 1024, \
.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, \
}, \
}
#define IWL_DEVICE_BZ_COMMON \
.ucode_api_max = IWL_22000_UCODE_API_MAX, \
.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 = 0x30, \
.ht_params = &iwl_22000_ht_params, \
.nvm_ver = IWL_22000_NVM_VERSION, \
.trans.use_tfh = true, \
.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_BZ \
IWL_DEVICE_BZ_COMMON, \
.trans.umac_prph_offset = 0x300000, \
.trans.device_family = IWL_DEVICE_FAMILY_BZ, \
.trans.base_params = &iwl_ax210_base_params, \
.min_txq_size = 128, \
.gp2_reg_addr = 0xd02c68, \
.min_256_ba_txq_size = 1024, \
.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_qnj_trans_cfg = {
.mq_rx_supported = true,
.use_tfh = true,
.rf_id = true,
.gen2 = true,
.device_family = IWL_DEVICE_FAMILY_22000,
.base_params = &iwl_22000_base_params,
};
const struct iwl_cfg_trans_params iwl_qu_trans_cfg = {
.mq_rx_supported = true,
.use_tfh = true,
.rf_id = true,
.gen2 = true,
.device_family = IWL_DEVICE_FAMILY_22000,
.base_params = &iwl_22000_base_params,
.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 = {
.mq_rx_supported = true,
.use_tfh = true,
.rf_id = true,
.gen2 = true,
.device_family = IWL_DEVICE_FAMILY_22000,
.base_params = &iwl_22000_base_params,
.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 = {
.mq_rx_supported = true,
.use_tfh = true,
.rf_id = true,
.gen2 = true,
.device_family = IWL_DEVICE_FAMILY_22000,
.base_params = &iwl_22000_base_params,
.integrated = true,
.xtal_latency = 12000,
.low_latency_xtal = true,
.ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US,
};
const struct iwl_cfg_trans_params iwl_snj_trans_cfg = {
.mq_rx_supported = true,
.use_tfh = true,
.rf_id = true,
.gen2 = true,
.device_family = IWL_DEVICE_FAMILY_AX210,
.base_params = &iwl_ax210_base_params,
.umac_prph_offset = 0x300000,
};
const struct iwl_cfg_trans_params iwl_so_trans_cfg = {
.mq_rx_supported = true,
.use_tfh = true,
.rf_id = true,
.gen2 = true,
.device_family = IWL_DEVICE_FAMILY_AX210,
.base_params = &iwl_ax210_base_params,
.umac_prph_offset = 0x300000,
.integrated = true,
/* TODO: the following values need to be checked */
.xtal_latency = 500,
.ltr_delay = IWL_CFG_TRANS_LTR_DELAY_200US,
};
const struct iwl_cfg_trans_params iwl_so_long_latency_trans_cfg = {
.mq_rx_supported = true,
.use_tfh = true,
.rf_id = true,
.gen2 = true,
.device_family = IWL_DEVICE_FAMILY_AX210,
.base_params = &iwl_ax210_base_params,
.umac_prph_offset = 0x300000,
.integrated = true,
.low_latency_xtal = true,
.xtal_latency = 12000,
.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
#define IWL_NUM_RBDS_AX210_HE 4096
/*
* 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 iwl9560_qnj_b0_jf_b0_cfg = {
.fw_name_pre = IWL_QNJ_B_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 = {
.device_family = IWL_DEVICE_FAMILY_22000,
.base_params = &iwl_22000_base_params,
.mq_rx_supported = true,
.use_tfh = true,
.rf_id = true,
.gen2 = true,
.bisr_workaround = 1,
};
const struct iwl_cfg_trans_params iwl_ma_trans_cfg = {
.device_family = IWL_DEVICE_FAMILY_AX210,
.base_params = &iwl_ax210_base_params,
.mq_rx_supported = true,
.use_tfh = true,
.rf_id = true,
.gen2 = true,
.integrated = true,
.umac_prph_offset = 0x300000
};
const struct iwl_cfg_trans_params iwl_bz_trans_cfg = {
.device_family = IWL_DEVICE_FAMILY_BZ,
.base_params = &iwl_ax210_base_params,
.mq_rx_supported = true,
.use_tfh = true,
.rf_id = true,
.gen2 = true,
.integrated = true,
.umac_prph_offset = 0x300000,
.xtal_latency = 12000,
.low_latency_xtal = true,
.ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US,
};
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_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_bz_name[] = "Intel(R) TBD Bz device";
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[] =
"Killer(R) Wi-Fi 6 AX1650x 160MHz Wireless Network Adapter (200NGW)";
const char iwl_ax201_killer_1650s_name[] =
"Killer(R) Wi-Fi 6 AX1650s 160MHz Wireless Network Adapter (201D2W)";
const char iwl_ax201_killer_1650i_name[] =
"Killer(R) Wi-Fi 6 AX1650i 160MHz Wireless Network Adapter (201NGW)";
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 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 AX1650i 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 AX1650s 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 AX1650i 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 AX1650s 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_qnj_b0_hr_b0_cfg = {
.fw_name_pre = IWL_QNJ_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 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 iwlax210_2ax_cfg_so_hr_a0 = {
.name = "Intel(R) Wi-Fi 6 AX210 160MHz",
.fw_name_pre = IWL_SO_A_HR_B_FW_PRE,
IWL_DEVICE_AX210,
.num_rbds = IWL_NUM_RBDS_AX210_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 iwlax411_2ax_cfg_sosnj_gf4_a0 = {
.name = iwl_ax411_name,
.fw_name_pre = IWL_SNJ_A_GF4_A_FW_PRE,
.uhb_supported = true,
IWL_DEVICE_AX210,
.num_rbds = IWL_NUM_RBDS_AX210_HE,
};
const struct iwl_cfg iwlax211_cfg_snj_gf_a0 = {
.name = iwl_ax211_name,
.fw_name_pre = IWL_SNJ_A_GF_A_FW_PRE,
.uhb_supported = true,
IWL_DEVICE_AX210,
.num_rbds = IWL_NUM_RBDS_AX210_HE,
};
const struct iwl_cfg iwl_cfg_snj_hr_b0 = {
.fw_name_pre = IWL_SNJ_A_HR_B_FW_PRE,
.uhb_supported = true,
IWL_DEVICE_AX210,
.num_rbds = IWL_NUM_RBDS_AX210_HE,
};
const struct iwl_cfg iwl_cfg_snj_a0_jf_b0 = {
.fw_name_pre = IWL_SNJ_A_JF_B_FW_PRE,
.uhb_supported = true,
IWL_DEVICE_AX210,
.num_rbds = IWL_NUM_RBDS_AX210_HE,
};
const struct iwl_cfg iwl_cfg_ma_a0_hr_b0 = {
.fw_name_pre = IWL_MA_A_HR_B_FW_PRE,
.uhb_supported = true,
IWL_DEVICE_AX210,
.num_rbds = IWL_NUM_RBDS_AX210_HE,
};
const struct iwl_cfg iwl_cfg_ma_a0_gf_a0 = {
.fw_name_pre = IWL_MA_A_GF_A_FW_PRE,
.uhb_supported = true,
IWL_DEVICE_AX210,
.num_rbds = IWL_NUM_RBDS_AX210_HE,
};
const struct iwl_cfg iwl_cfg_ma_a0_gf4_a0 = {
.fw_name_pre = IWL_MA_A_GF4_A_FW_PRE,
.uhb_supported = true,
IWL_DEVICE_AX210,
.num_rbds = IWL_NUM_RBDS_AX210_HE,
};
const struct iwl_cfg iwl_cfg_ma_a0_mr_a0 = {
.fw_name_pre = IWL_MA_A_MR_A_FW_PRE,
.uhb_supported = true,
IWL_DEVICE_AX210,
.num_rbds = IWL_NUM_RBDS_AX210_HE,
};
const struct iwl_cfg iwl_cfg_ma_a0_fm_a0 = {
.fw_name_pre = IWL_MA_A_FM_A_FW_PRE,
.uhb_supported = true,
IWL_DEVICE_AX210,
.num_rbds = IWL_NUM_RBDS_AX210_HE,
};
const struct iwl_cfg iwl_cfg_snj_a0_mr_a0 = {
.fw_name_pre = IWL_SNJ_A_MR_A_FW_PRE,
.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,
};
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,
};
const struct iwl_cfg iwl_cfg_bz_a0_hr_b0 = {
.fw_name_pre = IWL_BZ_A_HR_B_FW_PRE,
.uhb_supported = true,
IWL_DEVICE_BZ,
.num_rbds = IWL_NUM_RBDS_AX210_HE,
};
const struct iwl_cfg iwl_cfg_bz_a0_gf_a0 = {
.fw_name_pre = IWL_BZ_A_GF_A_FW_PRE,
.uhb_supported = true,
IWL_DEVICE_BZ,
.num_rbds = IWL_NUM_RBDS_AX210_HE,
};
const struct iwl_cfg iwl_cfg_bz_a0_gf4_a0 = {
.fw_name_pre = IWL_BZ_A_GF4_A_FW_PRE,
.uhb_supported = true,
IWL_DEVICE_BZ,
.num_rbds = IWL_NUM_RBDS_AX210_HE,
};
const struct iwl_cfg iwl_cfg_bz_a0_mr_a0 = {
.fw_name_pre = IWL_BZ_A_MR_A_FW_PRE,
.uhb_supported = true,
IWL_DEVICE_BZ,
.num_rbds = IWL_NUM_RBDS_AX210_HE,
};
const struct iwl_cfg iwl_cfg_bz_a0_fm_a0 = {
.fw_name_pre = IWL_BZ_A_FM_A_FW_PRE,
.uhb_supported = true,
IWL_DEVICE_BZ,
.num_rbds = IWL_NUM_RBDS_AX210_HE,
};
const struct iwl_cfg iwl_cfg_gl_a0_fm_a0 = {
.fw_name_pre = IWL_GL_A_FM_A_FW_PRE,
.uhb_supported = true,
IWL_DEVICE_BZ,
.num_rbds = IWL_NUM_RBDS_AX210_HE,
};
MODULE_FIRMWARE(IWL_QU_B_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_QNJ_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_QNJ_B_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_CC_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_SO_A_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_SO_A_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_SO_A_GF_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_TY_A_GF_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_SNJ_A_GF4_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_SNJ_A_GF_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_SNJ_A_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_SNJ_A_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_MA_A_HR_B_FW_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_MA_A_GF_A_FW_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_MA_A_GF4_A_FW_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_MA_A_MR_A_FW_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_MA_A_FM_A_FW_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_SNJ_A_MR_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_BZ_A_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_BZ_A_GF_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_BZ_A_GF4_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_BZ_A_MR_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_BZ_A_FM_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_GL_A_FM_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));

View File

@ -0,0 +1,298 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2012-2014, 2018-2020 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2015 Intel Deutschland GmbH
*/
#include <linux/module.h>
#include <linux/stringify.h>
#include "iwl-config.h"
/* Highest firmware API version supported */
#define IWL7260_UCODE_API_MAX 17
#define IWL7265_UCODE_API_MAX 17
#define IWL7265D_UCODE_API_MAX 29
#define IWL3168_UCODE_API_MAX 29
/* Lowest firmware API version supported */
#define IWL7260_UCODE_API_MIN 17
#define IWL7265_UCODE_API_MIN 17
#define IWL7265D_UCODE_API_MIN 22
#define IWL3168_UCODE_API_MIN 22
/* NVM versions */
#define IWL7260_NVM_VERSION 0x0a1d
#define IWL3160_NVM_VERSION 0x709
#define IWL3165_NVM_VERSION 0x709
#define IWL3168_NVM_VERSION 0xd01
#define IWL7265_NVM_VERSION 0x0a1d
#define IWL7265D_NVM_VERSION 0x0c11
/* DCCM offsets and lengths */
#define IWL7000_DCCM_OFFSET 0x800000
#define IWL7260_DCCM_LEN 0x14000
#define IWL3160_DCCM_LEN 0x10000
#define IWL7265_DCCM_LEN 0x17A00
#define IWL7260_FW_PRE "iwlwifi-7260-"
#define IWL7260_MODULE_FIRMWARE(api) IWL7260_FW_PRE __stringify(api) ".ucode"
#define IWL3160_FW_PRE "iwlwifi-3160-"
#define IWL3160_MODULE_FIRMWARE(api) IWL3160_FW_PRE __stringify(api) ".ucode"
#define IWL3168_FW_PRE "iwlwifi-3168-"
#define IWL3168_MODULE_FIRMWARE(api) IWL3168_FW_PRE __stringify(api) ".ucode"
#define IWL7265_FW_PRE "iwlwifi-7265-"
#define IWL7265_MODULE_FIRMWARE(api) IWL7265_FW_PRE __stringify(api) ".ucode"
#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 = {
.eeprom_size = OTP_LOW_IMAGE_SIZE_16K,
.num_of_queues = 31,
.max_tfd_queue_size = 256,
.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,
.apmg_wake_up_wa = true,
};
static const struct iwl_tt_params iwl7000_high_temp_tt_params = {
.ct_kill_entry = 118,
.ct_kill_exit = 96,
.ct_kill_duration = 5,
.dynamic_smps_entry = 114,
.dynamic_smps_exit = 110,
.tx_protection_entry = 114,
.tx_protection_exit = 108,
.tx_backoff = {
{.temperature = 112, .backoff = 300},
{.temperature = 113, .backoff = 800},
{.temperature = 114, .backoff = 1500},
{.temperature = 115, .backoff = 3000},
{.temperature = 116, .backoff = 5000},
{.temperature = 117, .backoff = 10000},
},
.support_ct_kill = true,
.support_dynamic_smps = true,
.support_tx_protection = true,
.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),
};
#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
#define IWL_DEVICE_7000 \
IWL_DEVICE_7000_COMMON, \
.ucode_api_max = IWL7260_UCODE_API_MAX, \
.ucode_api_min = IWL7260_UCODE_API_MIN
#define IWL_DEVICE_7005 \
IWL_DEVICE_7000_COMMON, \
.ucode_api_max = IWL7265_UCODE_API_MAX, \
.ucode_api_min = IWL7265_UCODE_API_MIN
#define IWL_DEVICE_3008 \
IWL_DEVICE_7000_COMMON, \
.ucode_api_max = IWL3168_UCODE_API_MAX, \
.ucode_api_min = IWL3168_UCODE_API_MIN
#define IWL_DEVICE_7005D \
IWL_DEVICE_7000_COMMON, \
.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",
.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_2ac_cfg_high_temp = {
.name = "Intel(R) Dual Band Wireless AC 7260",
.fw_name_pre = IWL7260_FW_PRE,
IWL_DEVICE_7000,
.ht_params = &iwl7000_ht_params,
.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",
.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,
.nvm_ver = IWL3160_NVM_VERSION,
.host_interrupt_operation_mode = true,
.dccm_len = IWL3160_DCCM_LEN,
};
static const struct iwl_pwr_tx_backoff iwl7265_pwr_tx_backoffs[] = {
{.pwr = 1600, .backoff = 0},
{.pwr = 1300, .backoff = 467},
{.pwr = 900, .backoff = 1900},
{.pwr = 800, .backoff = 2630},
{.pwr = 700, .backoff = 3720},
{.pwr = 600, .backoff = 5550},
{.pwr = 500, .backoff = 9350},
{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",
.fw_name_pre = IWL7265D_FW_PRE,
IWL_DEVICE_7005D,
.ht_params = &iwl7000_ht_params,
.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",
.fw_name_pre = IWL3168_FW_PRE,
IWL_DEVICE_3008,
.ht_params = &iwl7000_ht_params,
.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",
.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_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",
.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,
.nvm_ver = IWL7265D_NVM_VERSION,
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
.dccm_len = IWL7265_DCCM_LEN,
};
MODULE_FIRMWARE(IWL7260_MODULE_FIRMWARE(IWL7260_UCODE_API_MAX));
MODULE_FIRMWARE(IWL3160_MODULE_FIRMWARE(IWL7260_UCODE_API_MAX));
MODULE_FIRMWARE(IWL3168_MODULE_FIRMWARE(IWL3168_UCODE_API_MAX));
MODULE_FIRMWARE(IWL7265_MODULE_FIRMWARE(IWL7265_UCODE_API_MAX));
MODULE_FIRMWARE(IWL7265D_MODULE_FIRMWARE(IWL7265D_UCODE_API_MAX));

View File

@ -0,0 +1,157 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2014, 2018-2020 Intel Corporation
* Copyright (C) 2014-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016 Intel Deutschland GmbH
*/
#include <linux/module.h>
#include <linux/stringify.h>
#include "iwl-config.h"
/* Highest firmware API version supported */
#define IWL8000_UCODE_API_MAX 36
#define IWL8265_UCODE_API_MAX 36
/* Lowest firmware API version supported */
#define IWL8000_UCODE_API_MIN 22
#define IWL8265_UCODE_API_MIN 22
/* NVM versions */
#define IWL8000_NVM_VERSION 0x0a1d
/* Memory offsets and lengths */
#define IWL8260_DCCM_OFFSET 0x800000
#define IWL8260_DCCM_LEN 0x18000
#define IWL8260_DCCM2_OFFSET 0x880000
#define IWL8260_DCCM2_LEN 0x8000
#define IWL8260_SMEM_OFFSET 0x400000
#define IWL8260_SMEM_LEN 0x68000
#define IWL8000_FW_PRE "iwlwifi-8000C-"
#define IWL8000_MODULE_FIRMWARE(api) \
IWL8000_FW_PRE __stringify(api) ".ucode"
#define IWL8265_FW_PRE "iwlwifi-8265-"
#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 = {
.eeprom_size = OTP_LOW_IMAGE_SIZE_32K,
.num_of_queues = 31,
.max_tfd_queue_size = 256,
.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,
};
static const struct iwl_ht_params iwl8000_ht_params = {
.stbc = true,
.ldpc = true,
.ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
};
static const struct iwl_tt_params iwl8000_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,
};
#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 \
#define IWL_DEVICE_8260 \
IWL_DEVICE_8000_COMMON, \
.ucode_api_max = IWL8000_UCODE_API_MAX, \
.ucode_api_min = IWL8000_UCODE_API_MIN \
#define IWL_DEVICE_8265 \
IWL_DEVICE_8000_COMMON, \
.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",
.fw_name_pre = IWL8000_FW_PRE,
IWL_DEVICE_8260,
.ht_params = &iwl8000_ht_params,
.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",
.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 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));

View File

@ -0,0 +1,192 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2015-2017 Intel Deutschland GmbH
* Copyright (C) 2018-2021 Intel Corporation
*/
#include <linux/module.h>
#include <linux/stringify.h>
#include "iwl-config.h"
#include "fw/file.h"
#include "iwl-prph.h"
/* Highest firmware API version supported */
#define IWL9000_UCODE_API_MAX 46
/* 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
#define IWL9000_FW_PRE "iwlwifi-9000-pu-b0-jf-b0-"
#define IWL9260_FW_PRE "iwlwifi-9260-th-b0-jf-b0-"
#define IWL9000_MODULE_FIRMWARE(api) \
IWL9000_FW_PRE __stringify(api) ".ucode"
#define IWL9260_MODULE_FIRMWARE(api) \
IWL9260_FW_PRE __stringify(api) ".ucode"
static const struct iwl_base_params iwl9000_base_params = {
.eeprom_size = OTP_LOW_IMAGE_SIZE_32K,
.num_of_queues = 31,
.max_tfd_queue_size = 256,
.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,
};
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},
},
.support_ct_kill = true,
.support_dynamic_smps = true,
.support_tx_protection = true,
.support_tx_backoff = true,
};
#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 = {
.device_family = IWL_DEVICE_FAMILY_9000,
.base_params = &iwl9000_base_params,
.mq_rx_supported = true,
.rf_id = true,
};
const struct iwl_cfg_trans_params iwl9560_trans_cfg = {
.device_family = IWL_DEVICE_FAMILY_9000,
.base_params = &iwl9000_base_params,
.mq_rx_supported = true,
.rf_id = true,
.integrated = true,
.xtal_latency = 650,
};
const struct iwl_cfg_trans_params iwl9560_long_latency_trans_cfg = {
.device_family = IWL_DEVICE_FAMILY_9000,
.base_params = &iwl9000_base_params,
.mq_rx_supported = true,
.rf_id = true,
.integrated = true,
.xtal_latency = 2820,
};
const struct iwl_cfg_trans_params iwl9560_shared_clk_trans_cfg = {
.device_family = IWL_DEVICE_FAMILY_9000,
.base_params = &iwl9000_base_params,
.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));

View File

@ -0,0 +1,305 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2017 Intel Deutschland GmbH
* Copyright (C) 2018-2021 Intel Corporation
*/
#ifndef __iwl_fw_acpi__
#define __iwl_fw_acpi__
#include <linux/acpi.h>
#include "fw/api/commands.h"
#include "fw/api/power.h"
#include "fw/api/phy.h"
#include "fw/api/nvm-reg.h"
#include "fw/img.h"
#include "iwl-trans.h"
#define ACPI_WRDS_METHOD "WRDS"
#define ACPI_EWRD_METHOD "EWRD"
#define ACPI_WGDS_METHOD "WGDS"
#define ACPI_WRDD_METHOD "WRDD"
#define ACPI_SPLC_METHOD "SPLC"
#define ACPI_ECKV_METHOD "ECKV"
#define ACPI_PPAG_METHOD "PPAG"
#define ACPI_WTAS_METHOD "WTAS"
#define ACPI_WIFI_DOMAIN (0x07)
#define ACPI_SAR_PROFILE_NUM 4
#define ACPI_NUM_GEO_PROFILES 3
#define ACPI_NUM_GEO_PROFILES_REV3 8
#define ACPI_GEO_PER_CHAIN_SIZE 3
#define ACPI_SAR_NUM_CHAINS_REV0 2
#define ACPI_SAR_NUM_CHAINS_REV1 2
#define ACPI_SAR_NUM_CHAINS_REV2 4
#define ACPI_SAR_NUM_SUB_BANDS_REV0 5
#define ACPI_SAR_NUM_SUB_BANDS_REV1 11
#define ACPI_SAR_NUM_SUB_BANDS_REV2 11
#define ACPI_WRDS_WIFI_DATA_SIZE_REV0 (ACPI_SAR_NUM_CHAINS_REV0 * \
ACPI_SAR_NUM_SUB_BANDS_REV0 + 2)
#define ACPI_WRDS_WIFI_DATA_SIZE_REV1 (ACPI_SAR_NUM_CHAINS_REV1 * \
ACPI_SAR_NUM_SUB_BANDS_REV1 + 2)
#define ACPI_WRDS_WIFI_DATA_SIZE_REV2 (ACPI_SAR_NUM_CHAINS_REV2 * \
ACPI_SAR_NUM_SUB_BANDS_REV2 + 2)
#define ACPI_EWRD_WIFI_DATA_SIZE_REV0 ((ACPI_SAR_PROFILE_NUM - 1) * \
ACPI_SAR_NUM_CHAINS_REV0 * \
ACPI_SAR_NUM_SUB_BANDS_REV0 + 3)
#define ACPI_EWRD_WIFI_DATA_SIZE_REV1 ((ACPI_SAR_PROFILE_NUM - 1) * \
ACPI_SAR_NUM_CHAINS_REV1 * \
ACPI_SAR_NUM_SUB_BANDS_REV1 + 3)
#define ACPI_EWRD_WIFI_DATA_SIZE_REV2 ((ACPI_SAR_PROFILE_NUM - 1) * \
ACPI_SAR_NUM_CHAINS_REV2 * \
ACPI_SAR_NUM_SUB_BANDS_REV2 + 3)
/* revision 0 and 1 are identical, except for the semantics in the FW */
#define ACPI_GEO_NUM_BANDS_REV0 2
#define ACPI_GEO_NUM_BANDS_REV2 3
#define ACPI_GEO_NUM_CHAINS 2
#define ACPI_WRDD_WIFI_DATA_SIZE 2
#define ACPI_SPLC_WIFI_DATA_SIZE 2
#define ACPI_ECKV_WIFI_DATA_SIZE 2
/*
* 1 type, 1 enabled, 1 block list size, 16 block list array
*/
#define APCI_WTAS_BLACK_LIST_MAX 16
#define ACPI_WTAS_WIFI_DATA_SIZE (3 + APCI_WTAS_BLACK_LIST_MAX)
#define ACPI_PPAG_WIFI_DATA_SIZE_V1 ((IWL_NUM_CHAIN_LIMITS * \
IWL_NUM_SUB_BANDS_V1) + 2)
#define ACPI_PPAG_WIFI_DATA_SIZE_V2 ((IWL_NUM_CHAIN_LIMITS * \
IWL_NUM_SUB_BANDS_V2) + 2)
/* PPAG gain value bounds in 1/8 dBm */
#define ACPI_PPAG_MIN_LB -16
#define ACPI_PPAG_MAX_LB 24
#define ACPI_PPAG_MIN_HB -16
#define ACPI_PPAG_MAX_HB 40
/*
* 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
* inside revision 2, which is what we represent here.
*/
struct iwl_sar_profile_chain {
u8 subbands[ACPI_SAR_NUM_SUB_BANDS_REV2];
};
struct iwl_sar_profile {
bool enabled;
struct iwl_sar_profile_chain chains[ACPI_SAR_NUM_CHAINS_REV2];
};
/* Same thing as with SAR, all revisions fit in revision 2 */
struct iwl_geo_profile_band {
u8 max;
u8 chains[ACPI_GEO_NUM_CHAINS];
};
struct iwl_geo_profile {
struct iwl_geo_profile_band bands[ACPI_GEO_NUM_BANDS_REV2];
};
enum iwl_dsm_funcs_rev_0 {
DSM_FUNC_QUERY = 0,
DSM_FUNC_DISABLE_SRD = 1,
DSM_FUNC_ENABLE_INDONESIA_5G2 = 2,
DSM_FUNC_ENABLE_6E = 3,
DSM_FUNC_11AX_ENABLEMENT = 6,
DSM_FUNC_ENABLE_UNII4_CHAN = 7,
DSM_FUNC_ACTIVATE_CHANNEL = 8
};
enum iwl_dsm_values_srd {
DSM_VALUE_SRD_ACTIVE,
DSM_VALUE_SRD_PASSIVE,
DSM_VALUE_SRD_DISABLE,
DSM_VALUE_SRD_MAX
};
enum iwl_dsm_values_indonesia {
DSM_VALUE_INDONESIA_DISABLE,
DSM_VALUE_INDONESIA_ENABLE,
DSM_VALUE_INDONESIA_RESERVED,
DSM_VALUE_INDONESIA_MAX
};
/* DSM RFI uses a different GUID, so need separate definitions */
#define DSM_RFI_FUNC_ENABLE 3
enum iwl_dsm_values_rfi {
DSM_VALUE_RFI_ENABLE,
DSM_VALUE_RFI_DISABLE,
DSM_VALUE_RFI_MAX
};
#ifdef CONFIG_ACPI
struct iwl_fw_runtime;
extern const guid_t iwl_guid;
extern const guid_t iwl_rfi_guid;
void *iwl_acpi_get_object(struct device *dev, acpi_string method);
int iwl_acpi_get_dsm_u8(struct device *dev, int rev, int func,
const guid_t *guid, u8 *value);
int iwl_acpi_get_dsm_u32(struct device *dev, int rev, int func,
const guid_t *guid, u32 *value);
union acpi_object *iwl_acpi_get_wifi_pkg_range(struct device *dev,
union acpi_object *data,
int min_data_size,
int max_data_size,
int *tbl_rev);
/**
* iwl_acpi_get_mcc - read MCC from ACPI, if available
*
* @dev: the struct device
* @mcc: output buffer (3 bytes) that will get the MCC
*
* This function tries to read the current MCC from ACPI if available.
*/
int iwl_acpi_get_mcc(struct device *dev, char *mcc);
u64 iwl_acpi_get_pwr_limit(struct device *dev);
/*
* iwl_acpi_get_eckv - read external clock validation from ACPI, if available
*
* @dev: the struct device
* @extl_clk: output var (2 bytes) that will get the clk indication.
*
* This function tries to read the external clock indication
* from ACPI if available.
*/
int iwl_acpi_get_eckv(struct device *dev, u32 *extl_clk);
int iwl_sar_select_profile(struct iwl_fw_runtime *fwrt,
__le16 *per_chain, u32 n_tables, u32 n_subbands,
int prof_a, int prof_b);
int iwl_sar_get_wrds_table(struct iwl_fw_runtime *fwrt);
int iwl_sar_get_ewrd_table(struct iwl_fw_runtime *fwrt);
int iwl_sar_get_wgds_table(struct iwl_fw_runtime *fwrt);
bool iwl_sar_geo_support(struct iwl_fw_runtime *fwrt);
int iwl_sar_geo_init(struct iwl_fw_runtime *fwrt,
struct iwl_per_chain_offset *table,
u32 n_bands, u32 n_profiles);
int iwl_acpi_get_tas(struct iwl_fw_runtime *fwrt, __le32 *block_list_array,
int *block_list_size);
__le32 iwl_acpi_get_lari_config_bitmap(struct iwl_fw_runtime *fwrt);
#else /* CONFIG_ACPI */
static inline void *iwl_acpi_get_object(struct device *dev, acpi_string method)
{
return ERR_PTR(-ENOENT);
}
static inline void *iwl_acpi_get_dsm_object(struct device *dev, int rev,
int func, union acpi_object *args)
{
return ERR_PTR(-ENOENT);
}
static inline int iwl_acpi_get_dsm_u8(struct device *dev, int rev, int func,
const guid_t *guid, u8 *value)
{
return -ENOENT;
}
static inline int iwl_acpi_get_dsm_u32(struct device *dev, int rev, int func,
const guid_t *guid, u32 *value)
{
return -ENOENT;
}
static inline union acpi_object *
iwl_acpi_get_wifi_pkg_range(struct device *dev,
union acpi_object *data,
int min_data_size, int max_data_size,
int *tbl_rev)
{
return ERR_PTR(-ENOENT);
}
static inline int iwl_acpi_get_mcc(struct device *dev, char *mcc)
{
return -ENOENT;
}
static inline u64 iwl_acpi_get_pwr_limit(struct device *dev)
{
return 0;
}
static inline int iwl_acpi_get_eckv(struct device *dev, u32 *extl_clk)
{
return -ENOENT;
}
static inline int iwl_sar_select_profile(struct iwl_fw_runtime *fwrt,
__le16 *per_chain, u32 n_tables, u32 n_subbands,
int prof_a, int prof_b)
{
return -ENOENT;
}
static inline int iwl_sar_get_wrds_table(struct iwl_fw_runtime *fwrt)
{
return -ENOENT;
}
static inline int iwl_sar_get_ewrd_table(struct iwl_fw_runtime *fwrt)
{
return -ENOENT;
}
static inline int iwl_sar_get_wgds_table(struct iwl_fw_runtime *fwrt)
{
return 1;
}
static inline bool iwl_sar_geo_support(struct iwl_fw_runtime *fwrt)
{
return false;
}
static inline int iwl_acpi_get_tas(struct iwl_fw_runtime *fwrt,
__le32 *block_list_array,
int *block_list_size)
{
return -ENOENT;
}
static inline __le32 iwl_acpi_get_lari_config_bitmap(struct iwl_fw_runtime *fwrt)
{
return 0;
}
#endif /* CONFIG_ACPI */
static inline union acpi_object *
iwl_acpi_get_wifi_pkg(struct device *dev,
union acpi_object *data,
int data_size, int *tbl_rev)
{
return iwl_acpi_get_wifi_pkg_range(dev, data, data_size, data_size,
tbl_rev);
}
#endif /* __iwl_fw_acpi__ */

View File

@ -0,0 +1,174 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2012-2014, 2018, 2020 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
#ifndef __iwl_fw_api_alive_h__
#define __iwl_fw_api_alive_h__
/* alive response is_valid values */
#define ALIVE_RESP_UCODE_OK BIT(0)
#define ALIVE_RESP_RFKILL BIT(1)
/* alive response ver_type values */
enum {
FW_TYPE_HW = 0,
FW_TYPE_PROT = 1,
FW_TYPE_AP = 2,
FW_TYPE_WOWLAN = 3,
FW_TYPE_TIMING = 4,
FW_TYPE_WIPAN = 5
};
/* alive response ver_subtype values */
enum {
FW_SUBTYPE_FULL_FEATURE = 0,
FW_SUBTYPE_BOOTSRAP = 1, /* Not valid */
FW_SUBTYPE_REDUCED = 2,
FW_SUBTYPE_ALIVE_ONLY = 3,
FW_SUBTYPE_WOWLAN = 4,
FW_SUBTYPE_AP_SUBTYPE = 5,
FW_SUBTYPE_WIPAN = 6,
FW_SUBTYPE_INITIALIZE = 9
};
#define IWL_ALIVE_STATUS_ERR 0xDEAD
#define IWL_ALIVE_STATUS_OK 0xCAFE
#define IWL_ALIVE_FLG_RFKILL BIT(0)
struct iwl_lmac_debug_addrs {
__le32 error_event_table_ptr; /* SRAM address for error log */
__le32 log_event_table_ptr; /* SRAM address for LMAC event log */
__le32 cpu_register_ptr;
__le32 dbgm_config_ptr;
__le32 alive_counter_ptr;
__le32 scd_base_ptr; /* SRAM address for SCD */
__le32 st_fwrd_addr; /* pointer to Store and forward */
__le32 st_fwrd_size;
} __packed; /* UCODE_DEBUG_ADDRS_API_S_VER_2 */
struct iwl_lmac_alive {
__le32 ucode_major;
__le32 ucode_minor;
u8 ver_subtype;
u8 ver_type;
u8 mac;
u8 opt;
__le32 timestamp;
struct iwl_lmac_debug_addrs dbg_ptrs;
} __packed; /* UCODE_ALIVE_NTFY_API_S_VER_3 */
struct iwl_umac_debug_addrs {
__le32 error_info_addr; /* SRAM address for UMAC error log */
__le32 dbg_print_buff_addr;
} __packed; /* UMAC_DEBUG_ADDRS_API_S_VER_1 */
struct iwl_umac_alive {
__le32 umac_major; /* UMAC version: major */
__le32 umac_minor; /* UMAC version: minor */
struct iwl_umac_debug_addrs dbg_ptrs;
} __packed; /* UMAC_ALIVE_DATA_API_S_VER_2 */
struct iwl_sku_id {
__le32 data[3];
} __packed; /* SKU_ID_API_S_VER_1 */
struct iwl_alive_ntf_v3 {
__le16 status;
__le16 flags;
struct iwl_lmac_alive lmac_data;
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 */
/**
* enum iwl_extended_cfg_flag - 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
*/
enum iwl_extended_cfg_flags {
IWL_INIT_DEBUG_CFG,
IWL_INIT_NVM,
IWL_INIT_PHY,
};
/**
* struct iwl_extended_cfg_cmd - mark what commands ucode should wait for
* before finishing init flows
* @init_flags: values from iwl_extended_cfg_flags
*/
struct iwl_init_extended_cfg_cmd {
__le32 init_flags;
} __packed; /* INIT_EXTENDED_CFG_CMD_API_S_VER_1 */
/**
* struct iwl_radio_version_notif - information on the radio version
* ( RADIO_VERSION_NOTIFICATION = 0x68 )
* @radio_flavor: radio flavor
* @radio_step: radio version step
* @radio_dash: radio version dash
*/
struct iwl_radio_version_notif {
__le32 radio_flavor;
__le32 radio_step;
__le32 radio_dash;
} __packed; /* RADIO_VERSION_NOTOFICATION_S_VER_1 */
enum iwl_card_state_flags {
CARD_ENABLED = 0x00,
HW_CARD_DISABLED = 0x01,
SW_CARD_DISABLED = 0x02,
CT_KILL_CARD_DISABLED = 0x04,
HALT_CARD_DISABLED = 0x08,
CARD_DISABLED_MSK = 0x0f,
CARD_IS_RX_ON = 0x10,
};
/**
* struct iwl_radio_version_notif - information on the card state
* ( CARD_STATE_NOTIFICATION = 0xa1 )
* @flags: &enum iwl_card_state_flags
*/
struct iwl_card_state_notif {
__le32 flags;
} __packed; /* CARD_STATE_NTFY_API_S_VER_1 */
/**
* enum iwl_error_recovery_flags - flags for error recovery cmd
* @ERROR_RECOVERY_UPDATE_DB: update db from blob sent
* @ERROR_RECOVERY_END_OF_RECOVERY: end of recovery
*/
enum iwl_error_recovery_flags {
ERROR_RECOVERY_UPDATE_DB = BIT(0),
ERROR_RECOVERY_END_OF_RECOVERY = BIT(1),
};
/**
* struct iwl_fw_error_recovery_cmd - recovery cmd sent upon assert
* @flags: &enum iwl_error_recovery_flags
* @buf_size: db buffer size in bytes
*/
struct iwl_fw_error_recovery_cmd {
__le32 flags;
__le32 buf_size;
} __packed; /* ERROR_RECOVERY_CMD_HDR_API_S_VER_1 */
#endif /* __iwl_fw_api_alive_h__ */

View File

@ -0,0 +1,134 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2012-2014, 2020 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
#ifndef __iwl_fw_api_binding_h__
#define __iwl_fw_api_binding_h__
#include <fw/file.h>
#include <fw/img.h>
#define MAX_MACS_IN_BINDING (3)
#define MAX_BINDINGS (4)
/**
* struct iwl_binding_cmd_v1 - configuring bindings
* ( BINDING_CONTEXT_CMD = 0x2b )
* @id_and_color: ID and color of the relevant Binding,
* &enum iwl_ctxt_id_and_color
* @action: action to perform, one of FW_CTXT_ACTION_*
* @macs: array of MAC id and colors which belong to the binding,
* &enum iwl_ctxt_id_and_color
* @phy: PHY id and color which belongs to the binding,
* &enum iwl_ctxt_id_and_color
*/
struct iwl_binding_cmd_v1 {
/* COMMON_INDEX_HDR_API_S_VER_1 */
__le32 id_and_color;
__le32 action;
/* BINDING_DATA_API_S_VER_1 */
__le32 macs[MAX_MACS_IN_BINDING];
__le32 phy;
} __packed; /* BINDING_CMD_API_S_VER_1 */
/**
* struct iwl_binding_cmd - configuring bindings
* ( BINDING_CONTEXT_CMD = 0x2b )
* @id_and_color: ID and color of the relevant Binding,
* &enum iwl_ctxt_id_and_color
* @action: action to perform, one of FW_CTXT_ACTION_*
* @macs: array of MAC id and colors which belong to the binding
* &enum iwl_ctxt_id_and_color
* @phy: PHY id and color which belongs to the binding
* &enum iwl_ctxt_id_and_color
* @lmac_id: the lmac id the binding belongs to
*/
struct iwl_binding_cmd {
/* COMMON_INDEX_HDR_API_S_VER_1 */
__le32 id_and_color;
__le32 action;
/* BINDING_DATA_API_S_VER_1 */
__le32 macs[MAX_MACS_IN_BINDING];
__le32 phy;
__le32 lmac_id;
} __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
static inline u32 iwl_mvm_get_lmac_id(const struct iwl_fw *fw,
enum nl80211_band band){
if (!fw_has_capa(&fw->ucode_capa, IWL_UCODE_TLV_CAPA_CDB_SUPPORT) ||
band == NL80211_BAND_2GHZ)
return IWL_LMAC_24G_INDEX;
return IWL_LMAC_5G_INDEX;
}
/* The maximal number of fragments in the FW's schedule session */
#define IWL_MVM_MAX_QUOTA 128
/**
* struct iwl_time_quota_data_v1 - configuration of time quota per binding
* @id_and_color: ID and color of the relevant Binding,
* &enum iwl_ctxt_id_and_color
* @quota: absolute time quota in TU. The scheduler will try to divide the
* remainig quota (after Time Events) according to this quota.
* @max_duration: max uninterrupted context duration in TU
*/
struct iwl_time_quota_data_v1 {
__le32 id_and_color;
__le32 quota;
__le32 max_duration;
} __packed; /* TIME_QUOTA_DATA_API_S_VER_1 */
/**
* struct iwl_time_quota_cmd - configuration of time quota between bindings
* ( TIME_QUOTA_CMD = 0x2c )
* @quotas: allocations per binding
* Note: on non-CDB the fourth one is the auxilary mac and is
* essentially zero.
* On CDB the fourth one is a regular binding.
*/
struct iwl_time_quota_cmd_v1 {
struct iwl_time_quota_data_v1 quotas[MAX_BINDINGS];
} __packed; /* TIME_QUOTA_ALLOCATION_CMD_API_S_VER_1 */
enum iwl_quota_low_latency {
IWL_QUOTA_LOW_LATENCY_NONE = 0,
IWL_QUOTA_LOW_LATENCY_TX = BIT(0),
IWL_QUOTA_LOW_LATENCY_RX = BIT(1),
IWL_QUOTA_LOW_LATENCY_TX_RX =
IWL_QUOTA_LOW_LATENCY_TX | IWL_QUOTA_LOW_LATENCY_RX,
};
/**
* struct iwl_time_quota_data - configuration of time quota per binding
* @id_and_color: ID and color of the relevant Binding.
* @quota: absolute time quota in TU. The scheduler will try to divide the
* remainig quota (after Time Events) according to this quota.
* @max_duration: max uninterrupted context duration in TU
* @low_latency: low latency status, &enum iwl_quota_low_latency
*/
struct iwl_time_quota_data {
__le32 id_and_color;
__le32 quota;
__le32 max_duration;
__le32 low_latency;
} __packed; /* TIME_QUOTA_DATA_API_S_VER_2 */
/**
* struct iwl_time_quota_cmd - configuration of time quota between bindings
* ( TIME_QUOTA_CMD = 0x2c )
* Note: on non-CDB the fourth one is the auxilary mac and is essentially zero.
* On CDB the fourth one is a regular binding.
*
* @quotas: allocations per binding
*/
struct iwl_time_quota_cmd {
struct iwl_time_quota_data quotas[MAX_BINDINGS];
} __packed; /* TIME_QUOTA_ALLOCATION_CMD_API_S_VER_2 */
#endif /* __iwl_fw_api_binding_h__ */

View File

@ -0,0 +1,156 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2005-2014 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
#ifndef __iwl_fw_api_cmdhdr_h__
#define __iwl_fw_api_cmdhdr_h__
/**
* DOC: Host command section
*
* A host command is a command issued by the upper layer to the fw. There are
* several versions of fw that have several APIs. The transport layer is
* completely agnostic to these differences.
* The transport does provide helper functionality (i.e. SYNC / ASYNC mode),
*/
#define SEQ_TO_QUEUE(s) (((s) >> 8) & 0x1f)
#define QUEUE_TO_SEQ(q) (((q) & 0x1f) << 8)
#define SEQ_TO_INDEX(s) ((s) & 0xff)
#define INDEX_TO_SEQ(i) ((i) & 0xff)
#define SEQ_RX_FRAME cpu_to_le16(0x8000)
/*
* those functions retrieve specific information from
* the id field in the iwl_host_cmd struct which contains
* the command id, the group id and the version of the command
* and vice versa
*/
static inline u8 iwl_cmd_opcode(u32 cmdid)
{
return cmdid & 0xFF;
}
static inline u8 iwl_cmd_groupid(u32 cmdid)
{
return ((cmdid & 0xFF00) >> 8);
}
static inline u8 iwl_cmd_version(u32 cmdid)
{
return ((cmdid & 0xFF0000) >> 16);
}
static inline u32 iwl_cmd_id(u8 opcode, u8 groupid, u8 version)
{
return opcode + (groupid << 8) + (version << 16);
}
/* make u16 wide id out of u8 group and opcode */
#define WIDE_ID(grp, opcode) (((grp) << 8) | (opcode))
#define DEF_ID(opcode) ((1 << 8) | (opcode))
/* due to the conversion, this group is special; new groups
* should be defined in the appropriate fw-api header files
*/
#define IWL_ALWAYS_LONG_GROUP 1
/**
* struct iwl_cmd_header - (short) command header format
*
* This header format appears in the beginning of each command sent from the
* driver, and each response/notification received from uCode.
*/
struct iwl_cmd_header {
/**
* @cmd: Command ID: REPLY_RXON, etc.
*/
u8 cmd;
/**
* @group_id: group ID, for commands with groups
*/
u8 group_id;
/**
* @sequence:
* Sequence number for the command.
*
* The driver sets up the sequence number to values of its choosing.
* uCode does not use this value, but passes it back to the driver
* when sending the response to each driver-originated command, so
* the driver can match the response to the command. Since the values
* don't get used by uCode, the driver may set up an arbitrary format.
*
* There is one exception: uCode sets bit 15 when it originates
* the response/notification, i.e. when the response/notification
* is not a direct response to a command sent by the driver. For
* example, uCode issues REPLY_RX when it sends a received frame
* to the driver; it is not a direct response to any driver command.
*
* The Linux driver uses the following format:
*
* 0:7 tfd index - position within TX queue
* 8:12 TX queue id
* 13:14 reserved
* 15 unsolicited RX or uCode-originated notification
*/
__le16 sequence;
} __packed;
/**
* struct iwl_cmd_header_wide
*
* This header format appears in the beginning of each command sent from the
* driver, and each response/notification received from uCode.
* this is the wide version that contains more information about the command
* like length, version and command type
*
* @cmd: command ID, like in &struct iwl_cmd_header
* @group_id: group ID, like in &struct iwl_cmd_header
* @sequence: sequence, like in &struct iwl_cmd_header
* @length: length of the command
* @reserved: reserved
* @version: command version
*/
struct iwl_cmd_header_wide {
u8 cmd;
u8 group_id;
__le16 sequence;
__le16 length;
u8 reserved;
u8 version;
} __packed;
/**
* struct iwl_calib_res_notif_phy_db - Receive phy db chunk after calibrations
* @type: type of the result - mostly ignored
* @length: length of the data
* @data: data, length in @length
*/
struct iwl_calib_res_notif_phy_db {
__le16 type;
__le16 length;
u8 data[];
} __packed;
/**
* struct iwl_phy_db_cmd - configure operational ucode
* @type: type of the data
* @length: length of the data
* @data: data, length in @length
*/
struct iwl_phy_db_cmd {
__le16 type;
__le16 length;
u8 data[];
} __packed;
/**
* struct iwl_cmd_response - generic response struct for most commands
* @status: status of the command asked, changes for each one
*/
struct iwl_cmd_response {
__le32 status;
};
#endif /* __iwl_fw_api_cmdhdr_h__ */

View File

@ -0,0 +1,188 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2013-2014, 2018-2019 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2017 Intel Deutschland GmbH
*/
#ifndef __iwl_fw_api_coex_h__
#define __iwl_fw_api_coex_h__
#include <linux/types.h>
#include <linux/bitops.h>
#define BITS(nb) (BIT(nb) - 1)
enum iwl_bt_coex_lut_type {
BT_COEX_TIGHT_LUT = 0,
BT_COEX_LOOSE_LUT,
BT_COEX_TX_DIS_LUT,
BT_COEX_MAX_LUT,
BT_COEX_INVALID_LUT = 0xff,
}; /* BT_COEX_DECISION_LUT_INDEX_API_E_VER_1 */
#define BT_REDUCED_TX_POWER_BIT BIT(7)
enum iwl_bt_coex_mode {
BT_COEX_DISABLE = 0x0,
BT_COEX_NW = 0x1,
BT_COEX_BT = 0x2,
BT_COEX_WIFI = 0x3,
}; /* BT_COEX_MODES_E */
enum iwl_bt_coex_enabled_modules {
BT_COEX_MPLUT_ENABLED = BIT(0),
BT_COEX_MPLUT_BOOST_ENABLED = BIT(1),
BT_COEX_SYNC2SCO_ENABLED = BIT(2),
BT_COEX_CORUN_ENABLED = BIT(3),
BT_COEX_HIGH_BAND_RET = BIT(4),
}; /* BT_COEX_MODULES_ENABLE_E_VER_1 */
/**
* struct iwl_bt_coex_cmd - bt coex configuration command
* @mode: &enum iwl_bt_coex_mode
* @enabled_modules: &enum iwl_bt_coex_enabled_modules
*
* The structure is used for the BT_COEX command.
*/
struct iwl_bt_coex_cmd {
__le32 mode;
__le32 enabled_modules;
} __packed; /* BT_COEX_CMD_API_S_VER_6 */
/**
* struct iwl_bt_coex_reduced_txp_update_cmd
* @reduced_txp: bit BT_REDUCED_TX_POWER_BIT to enable / disable, rest of the
* bits are the sta_id (value)
*/
struct iwl_bt_coex_reduced_txp_update_cmd {
__le32 reduced_txp;
} __packed; /* BT_COEX_UPDATE_REDUCED_TX_POWER_API_S_VER_1 */
/**
* struct iwl_bt_coex_ci_cmd - bt coex channel inhibition command
* @bt_primary_ci: primary channel inhibition bitmap
* @primary_ch_phy_id: primary channel PHY ID
* @bt_secondary_ci: secondary channel inhibition bitmap
* @secondary_ch_phy_id: secondary channel PHY ID
*
* Used for BT_COEX_CI command
*/
struct iwl_bt_coex_ci_cmd {
__le64 bt_primary_ci;
__le32 primary_ch_phy_id;
__le64 bt_secondary_ci;
__le32 secondary_ch_phy_id;
} __packed; /* BT_CI_MSG_API_S_VER_2 */
#define BT_MBOX(n_dw, _msg, _pos, _nbits) \
BT_MBOX##n_dw##_##_msg##_POS = (_pos), \
BT_MBOX##n_dw##_##_msg = BITS(_nbits) << BT_MBOX##n_dw##_##_msg##_POS
enum iwl_bt_mxbox_dw0 {
BT_MBOX(0, LE_SLAVE_LAT, 0, 3),
BT_MBOX(0, LE_PROF1, 3, 1),
BT_MBOX(0, LE_PROF2, 4, 1),
BT_MBOX(0, LE_PROF_OTHER, 5, 1),
BT_MBOX(0, CHL_SEQ_N, 8, 4),
BT_MBOX(0, INBAND_S, 13, 1),
BT_MBOX(0, LE_MIN_RSSI, 16, 4),
BT_MBOX(0, LE_SCAN, 20, 1),
BT_MBOX(0, LE_ADV, 21, 1),
BT_MBOX(0, LE_MAX_TX_POWER, 24, 4),
BT_MBOX(0, OPEN_CON_1, 28, 2),
};
enum iwl_bt_mxbox_dw1 {
BT_MBOX(1, BR_MAX_TX_POWER, 0, 4),
BT_MBOX(1, IP_SR, 4, 1),
BT_MBOX(1, LE_MSTR, 5, 1),
BT_MBOX(1, AGGR_TRFC_LD, 8, 6),
BT_MBOX(1, MSG_TYPE, 16, 3),
BT_MBOX(1, SSN, 19, 2),
};
enum iwl_bt_mxbox_dw2 {
BT_MBOX(2, SNIFF_ACT, 0, 3),
BT_MBOX(2, PAG, 3, 1),
BT_MBOX(2, INQUIRY, 4, 1),
BT_MBOX(2, CONN, 5, 1),
BT_MBOX(2, SNIFF_INTERVAL, 8, 5),
BT_MBOX(2, DISC, 13, 1),
BT_MBOX(2, SCO_TX_ACT, 16, 2),
BT_MBOX(2, SCO_RX_ACT, 18, 2),
BT_MBOX(2, ESCO_RE_TX, 20, 2),
BT_MBOX(2, SCO_DURATION, 24, 6),
};
enum iwl_bt_mxbox_dw3 {
BT_MBOX(3, SCO_STATE, 0, 1),
BT_MBOX(3, SNIFF_STATE, 1, 1),
BT_MBOX(3, A2DP_STATE, 2, 1),
BT_MBOX(3, ACL_STATE, 3, 1),
BT_MBOX(3, MSTR_STATE, 4, 1),
BT_MBOX(3, OBX_STATE, 5, 1),
BT_MBOX(3, A2DP_SRC, 6, 1),
BT_MBOX(3, OPEN_CON_2, 8, 2),
BT_MBOX(3, TRAFFIC_LOAD, 10, 2),
BT_MBOX(3, CHL_SEQN_LSB, 12, 1),
BT_MBOX(3, INBAND_P, 13, 1),
BT_MBOX(3, MSG_TYPE_2, 16, 3),
BT_MBOX(3, SSN_2, 19, 2),
BT_MBOX(3, UPDATE_REQUEST, 21, 1),
};
#define BT_MBOX_MSG(_notif, _num, _field) \
((le32_to_cpu((_notif)->mbox_msg[(_num)]) & BT_MBOX##_num##_##_field)\
>> BT_MBOX##_num##_##_field##_POS)
#define BT_MBOX_PRINT(_num, _field, _end) \
pos += scnprintf(buf + pos, bufsz - pos, \
"\t%s: %d%s", \
#_field, \
BT_MBOX_MSG(notif, _num, _field), \
true ? "\n" : ", ")
enum iwl_bt_activity_grading {
BT_OFF = 0,
BT_ON_NO_CONNECTION = 1,
BT_LOW_TRAFFIC = 2,
BT_HIGH_TRAFFIC = 3,
BT_VERY_HIGH_TRAFFIC = 4,
BT_MAX_AG,
}; /* BT_COEX_BT_ACTIVITY_GRADING_API_E_VER_1 */
enum iwl_bt_ci_compliance {
BT_CI_COMPLIANCE_NONE = 0,
BT_CI_COMPLIANCE_PRIMARY = 1,
BT_CI_COMPLIANCE_SECONDARY = 2,
BT_CI_COMPLIANCE_BOTH = 3,
}; /* BT_COEX_CI_COMPLIENCE_E_VER_1 */
/**
* struct iwl_bt_coex_profile_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
* @primary_ch_lut: LUT used for primary channel &enum iwl_bt_coex_lut_type
* @secondary_ch_lut: LUT used for secondary channel &enum iwl_bt_coex_lut_type
* @bt_activity_grading: the activity of BT &enum iwl_bt_activity_grading
* @ttc_status: is TTC enabled - one bit per PHY
* @rrc_status: is RRC enabled - one bit per PHY
* @reserved: reserved
*/
struct iwl_bt_coex_profile_notif {
__le32 mbox_msg[4];
__le32 msg_idx;
__le32 bt_ci_compliance;
__le32 primary_ch_lut;
__le32 secondary_ch_lut;
__le32 bt_activity_grading;
u8 ttc_status;
u8 rrc_status;
__le16 reserved;
} __packed; /* BT_COEX_PROFILE_NTFY_API_S_VER_4 */
#endif /* __iwl_fw_api_coex_h__ */

View File

@ -0,0 +1,617 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
* Copyright (C) 2018-2020 Intel Corporation
*/
#ifndef __iwl_fw_api_commands_h__
#define __iwl_fw_api_commands_h__
/**
* enum iwl_mvm_command_groups - command groups for the firmware
* @LEGACY_GROUP: legacy group, uses command IDs from &enum iwl_legacy_cmds
* @LONG_GROUP: legacy group with long header, also uses command IDs
* from &enum iwl_legacy_cmds
* @SYSTEM_GROUP: system group, uses command IDs from
* &enum iwl_system_subcmd_ids
* @MAC_CONF_GROUP: MAC configuration group, uses command IDs from
* &enum iwl_mac_conf_subcmd_ids
* @PHY_OPS_GROUP: PHY operations group, uses command IDs from
* &enum iwl_phy_ops_subcmd_ids
* @DATA_PATH_GROUP: data path group, uses command IDs from
* &enum iwl_data_path_subcmd_ids
* @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
* @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
* &enum iwl_regulatory_and_nvm_subcmd_ids
* @DEBUG_GROUP: Debug group, uses command IDs from &enum iwl_debug_cmds
*/
enum iwl_mvm_command_groups {
LEGACY_GROUP = 0x0,
LONG_GROUP = 0x1,
SYSTEM_GROUP = 0x2,
MAC_CONF_GROUP = 0x3,
PHY_OPS_GROUP = 0x4,
DATA_PATH_GROUP = 0x5,
NAN_GROUP = 0x7,
LOCATION_GROUP = 0x8,
PROT_OFFLOAD_GROUP = 0xb,
REGULATORY_AND_NVM_GROUP = 0xc,
DEBUG_GROUP = 0xf,
};
/**
* enum iwl_legacy_cmds - legacy group command IDs
*/
enum iwl_legacy_cmds {
/**
* @UCODE_ALIVE_NTFY:
* Alive data from the firmware, as described in
* &struct iwl_alive_ntf_v3 or &struct iwl_alive_ntf_v4 or
* &struct iwl_alive_ntf_v5.
*/
UCODE_ALIVE_NTFY = 0x1,
/**
* @REPLY_ERROR: Cause an error in the firmware, for testing purposes.
*/
REPLY_ERROR = 0x2,
/**
* @ECHO_CMD: Send data to the device to have it returned immediately.
*/
ECHO_CMD = 0x3,
/**
* @INIT_COMPLETE_NOTIF: Notification that initialization is complete.
*/
INIT_COMPLETE_NOTIF = 0x4,
/**
* @PHY_CONTEXT_CMD:
* Add/modify/remove a PHY context, using &struct iwl_phy_context_cmd.
*/
PHY_CONTEXT_CMD = 0x8,
/**
* @DBG_CFG: Debug configuration command.
*/
DBG_CFG = 0x9,
/**
* @SCAN_ITERATION_COMPLETE_UMAC:
* Firmware indicates a scan iteration completed, using
* &struct iwl_umac_scan_iter_complete_notif.
*/
SCAN_ITERATION_COMPLETE_UMAC = 0xb5,
/**
* @SCAN_CFG_CMD:
* uses &struct iwl_scan_config_v1 or &struct iwl_scan_config
*/
SCAN_CFG_CMD = 0xc,
/**
* @SCAN_REQ_UMAC: uses &struct iwl_scan_req_umac
*/
SCAN_REQ_UMAC = 0xd,
/**
* @SCAN_ABORT_UMAC: uses &struct iwl_umac_scan_abort
*/
SCAN_ABORT_UMAC = 0xe,
/**
* @SCAN_COMPLETE_UMAC: uses &struct iwl_umac_scan_complete
*/
SCAN_COMPLETE_UMAC = 0xf,
/**
* @BA_WINDOW_STATUS_NOTIFICATION_ID:
* uses &struct iwl_ba_window_status_notif
*/
BA_WINDOW_STATUS_NOTIFICATION_ID = 0x13,
/**
* @ADD_STA_KEY:
* &struct iwl_mvm_add_sta_key_cmd_v1 or
* &struct iwl_mvm_add_sta_key_cmd.
*/
ADD_STA_KEY = 0x17,
/**
* @ADD_STA:
* &struct iwl_mvm_add_sta_cmd or &struct iwl_mvm_add_sta_cmd_v7.
*/
ADD_STA = 0x18,
/**
* @REMOVE_STA: &struct iwl_mvm_rm_sta_cmd
*/
REMOVE_STA = 0x19,
/**
* @FW_GET_ITEM_CMD: uses &struct iwl_fw_get_item_cmd
*/
FW_GET_ITEM_CMD = 0x1a,
/**
* @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 = 0x1c,
/**
* @TXPATH_FLUSH: &struct iwl_tx_path_flush_cmd
*/
TXPATH_FLUSH = 0x1e,
/**
* @MGMT_MCAST_KEY:
* &struct iwl_mvm_mgmt_mcast_key_cmd or
* &struct iwl_mvm_mgmt_mcast_key_cmd_v1
*/
MGMT_MCAST_KEY = 0x1f,
/* scheduler config */
/**
* @SCD_QUEUE_CFG: &struct iwl_scd_txq_cfg_cmd for older hardware,
* &struct iwl_tx_queue_cfg_cmd with &struct iwl_tx_queue_cfg_rsp
* for newer (22000) hardware.
*/
SCD_QUEUE_CFG = 0x1d,
/**
* @WEP_KEY: uses &struct iwl_mvm_wep_key_cmd
*/
WEP_KEY = 0x20,
/**
* @SHARED_MEM_CFG:
* retrieve shared memory configuration - response in
* &struct iwl_shared_mem_cfg
*/
SHARED_MEM_CFG = 0x25,
/**
* @TDLS_CHANNEL_SWITCH_CMD: uses &struct iwl_tdls_channel_switch_cmd
*/
TDLS_CHANNEL_SWITCH_CMD = 0x27,
/**
* @TDLS_CHANNEL_SWITCH_NOTIFICATION:
* uses &struct iwl_tdls_channel_switch_notif
*/
TDLS_CHANNEL_SWITCH_NOTIFICATION = 0xaa,
/**
* @TDLS_CONFIG_CMD:
* &struct iwl_tdls_config_cmd, response in &struct iwl_tdls_config_res
*/
TDLS_CONFIG_CMD = 0xa7,
/**
* @MAC_CONTEXT_CMD: &struct iwl_mac_ctx_cmd
*/
MAC_CONTEXT_CMD = 0x28,
/**
* @TIME_EVENT_CMD:
* &struct iwl_time_event_cmd, response in &struct iwl_time_event_resp
*/
TIME_EVENT_CMD = 0x29, /* both CMD and response */
/**
* @TIME_EVENT_NOTIFICATION: &struct iwl_time_event_notif
*/
TIME_EVENT_NOTIFICATION = 0x2a,
/**
* @BINDING_CONTEXT_CMD:
* &struct iwl_binding_cmd or &struct iwl_binding_cmd_v1
*/
BINDING_CONTEXT_CMD = 0x2b,
/**
* @TIME_QUOTA_CMD: &struct iwl_time_quota_cmd
*/
TIME_QUOTA_CMD = 0x2c,
/**
* @NON_QOS_TX_COUNTER_CMD:
* command is &struct iwl_nonqos_seq_query_cmd
*/
NON_QOS_TX_COUNTER_CMD = 0x2d,
/**
* @LEDS_CMD: command is &struct iwl_led_cmd
*/
LEDS_CMD = 0x48,
/**
* @LQ_CMD: using &struct iwl_lq_cmd
*/
LQ_CMD = 0x4e,
/**
* @FW_PAGING_BLOCK_CMD:
* &struct iwl_fw_paging_cmd
*/
FW_PAGING_BLOCK_CMD = 0x4f,
/**
* @SCAN_OFFLOAD_REQUEST_CMD: uses &struct iwl_scan_req_lmac
*/
SCAN_OFFLOAD_REQUEST_CMD = 0x51,
/**
* @SCAN_OFFLOAD_ABORT_CMD: abort the scan - no further contents
*/
SCAN_OFFLOAD_ABORT_CMD = 0x52,
/**
* @HOT_SPOT_CMD: uses &struct iwl_hs20_roc_req
*/
HOT_SPOT_CMD = 0x53,
/**
* @SCAN_OFFLOAD_COMPLETE:
* notification, &struct iwl_periodic_scan_complete
*/
SCAN_OFFLOAD_COMPLETE = 0x6D,
/**
* @SCAN_OFFLOAD_UPDATE_PROFILES_CMD:
* update scan offload (scheduled scan) profiles/blocklist/etc.
*/
SCAN_OFFLOAD_UPDATE_PROFILES_CMD = 0x6E,
/**
* @MATCH_FOUND_NOTIFICATION: scan match found
*/
MATCH_FOUND_NOTIFICATION = 0xd9,
/**
* @SCAN_ITERATION_COMPLETE:
* uses &struct iwl_lmac_scan_complete_notif
*/
SCAN_ITERATION_COMPLETE = 0xe7,
/* Phy */
/**
* @PHY_CONFIGURATION_CMD: &struct iwl_phy_cfg_cmd_v1 or &struct iwl_phy_cfg_cmd_v3
*/
PHY_CONFIGURATION_CMD = 0x6a,
/**
* @CALIB_RES_NOTIF_PHY_DB: &struct iwl_calib_res_notif_phy_db
*/
CALIB_RES_NOTIF_PHY_DB = 0x6b,
/**
* @PHY_DB_CMD: &struct iwl_phy_db_cmd
*/
PHY_DB_CMD = 0x6c,
/**
* @POWER_TABLE_CMD: &struct iwl_device_power_cmd
*/
POWER_TABLE_CMD = 0x77,
/**
* @PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION:
* &struct iwl_uapsd_misbehaving_ap_notif
*/
PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION = 0x78,
/**
* @LTR_CONFIG: &struct iwl_ltr_config_cmd
*/
LTR_CONFIG = 0xee,
/**
* @REPLY_THERMAL_MNG_BACKOFF:
* Thermal throttling command
*/
REPLY_THERMAL_MNG_BACKOFF = 0x7e,
/**
* @DC2DC_CONFIG_CMD:
* Set/Get DC2DC frequency tune
* Command is &struct iwl_dc2dc_config_cmd,
* response is &struct iwl_dc2dc_config_resp
*/
DC2DC_CONFIG_CMD = 0x83,
/**
* @NVM_ACCESS_CMD: using &struct iwl_nvm_access_cmd
*/
NVM_ACCESS_CMD = 0x88,
/**
* @BEACON_NOTIFICATION: &struct iwl_extended_beacon_notif
*/
BEACON_NOTIFICATION = 0x90,
/**
* @BEACON_TEMPLATE_CMD:
* Uses one of &struct iwl_mac_beacon_cmd_v6,
* &struct iwl_mac_beacon_cmd_v7 or &struct iwl_mac_beacon_cmd
* depending on the device version.
*/
BEACON_TEMPLATE_CMD = 0x91,
/**
* @TX_ANT_CONFIGURATION_CMD: &struct iwl_tx_ant_cfg_cmd
*/
TX_ANT_CONFIGURATION_CMD = 0x98,
/**
* @STATISTICS_CMD:
* one of &struct iwl_statistics_cmd,
* &struct iwl_notif_statistics_v11,
* &struct iwl_notif_statistics_v10,
* &struct iwl_notif_statistics,
* &struct iwl_statistics_operational_ntfy
*/
STATISTICS_CMD = 0x9c,
/**
* @STATISTICS_NOTIFICATION:
* one of &struct iwl_notif_statistics_v10,
* &struct iwl_notif_statistics_v11,
* &struct iwl_notif_statistic,
* &struct iwl_statistics_operational_ntfy
*/
STATISTICS_NOTIFICATION = 0x9d,
/**
* @EOSP_NOTIFICATION:
* Notify that a service period ended,
* &struct iwl_mvm_eosp_notification
*/
EOSP_NOTIFICATION = 0x9e,
/**
* @REDUCE_TX_POWER_CMD:
* &struct iwl_dev_tx_power_cmd
*/
REDUCE_TX_POWER_CMD = 0x9f,
/**
* @CARD_STATE_NOTIFICATION:
* Card state (RF/CT kill) notification,
* uses &struct iwl_card_state_notif
*/
CARD_STATE_NOTIFICATION = 0xa1,
/**
* @MISSED_BEACONS_NOTIFICATION: &struct iwl_missed_beacons_notif
*/
MISSED_BEACONS_NOTIFICATION = 0xa2,
/**
* @MAC_PM_POWER_TABLE: using &struct iwl_mac_power_cmd
*/
MAC_PM_POWER_TABLE = 0xa9,
/**
* @MFUART_LOAD_NOTIFICATION: &struct iwl_mfuart_load_notif
*/
MFUART_LOAD_NOTIFICATION = 0xb1,
/**
* @RSS_CONFIG_CMD: &struct iwl_rss_config_cmd
*/
RSS_CONFIG_CMD = 0xb3,
/**
* @REPLY_RX_PHY_CMD: &struct iwl_rx_phy_info
*/
REPLY_RX_PHY_CMD = 0xc0,
/**
* @REPLY_RX_MPDU_CMD:
* &struct iwl_rx_mpdu_res_start or &struct iwl_rx_mpdu_desc
*/
REPLY_RX_MPDU_CMD = 0xc1,
/**
* @BAR_FRAME_RELEASE: Frame release from BAR notification, used for
* multi-TID BAR (previously, the BAR frame itself was reported
* instead). Uses &struct iwl_bar_frame_release.
*/
BAR_FRAME_RELEASE = 0xc2,
/**
* @FRAME_RELEASE:
* Frame release (reorder helper) notification, uses
* &struct iwl_frame_release
*/
FRAME_RELEASE = 0xc3,
/**
* @BA_NOTIF:
* BlockAck notification, uses &struct iwl_mvm_compressed_ba_notif
* or &struct iwl_mvm_ba_notif depending on the HW
*/
BA_NOTIF = 0xc5,
/* Location Aware Regulatory */
/**
* @MCC_UPDATE_CMD: using &struct iwl_mcc_update_cmd
*/
MCC_UPDATE_CMD = 0xc8,
/**
* @MCC_CHUB_UPDATE_CMD: using &struct iwl_mcc_chub_notif
*/
MCC_CHUB_UPDATE_CMD = 0xc9,
/**
* @MARKER_CMD: trace marker command, uses &struct iwl_mvm_marker
* with &struct iwl_mvm_marker_rsp
*/
MARKER_CMD = 0xcb,
/**
* @BT_PROFILE_NOTIFICATION: &struct iwl_bt_coex_profile_notif
*/
BT_PROFILE_NOTIFICATION = 0xce,
/**
* @BT_CONFIG: &struct iwl_bt_coex_cmd
*/
BT_CONFIG = 0x9b,
/**
* @BT_COEX_UPDATE_REDUCED_TXP:
* &struct iwl_bt_coex_reduced_txp_update_cmd
*/
BT_COEX_UPDATE_REDUCED_TXP = 0x5c,
/**
* @BT_COEX_CI: &struct iwl_bt_coex_ci_cmd
*/
BT_COEX_CI = 0x5d,
/**
* @REPLY_SF_CFG_CMD: &struct iwl_sf_cfg_cmd
*/
REPLY_SF_CFG_CMD = 0xd1,
/**
* @REPLY_BEACON_FILTERING_CMD: &struct iwl_beacon_filter_cmd
*/
REPLY_BEACON_FILTERING_CMD = 0xd2,
/**
* @DTS_MEASUREMENT_NOTIFICATION:
* &struct iwl_dts_measurement_notif_v1 or
* &struct iwl_dts_measurement_notif_v2
*/
DTS_MEASUREMENT_NOTIFICATION = 0xdd,
/**
* @LDBG_CONFIG_CMD: configure continuous trace recording
*/
LDBG_CONFIG_CMD = 0xf6,
/**
* @DEBUG_LOG_MSG: Debugging log data from firmware
*/
DEBUG_LOG_MSG = 0xf7,
/**
* @BCAST_FILTER_CMD: &struct iwl_bcast_filter_cmd
*/
BCAST_FILTER_CMD = 0xcf,
/**
* @MCAST_FILTER_CMD: &struct iwl_mcast_filter_cmd
*/
MCAST_FILTER_CMD = 0xd0,
/**
* @D3_CONFIG_CMD: &struct iwl_d3_manager_config
*/
D3_CONFIG_CMD = 0xd3,
/**
* @PROT_OFFLOAD_CONFIG_CMD: Depending on firmware, uses one of
* &struct iwl_proto_offload_cmd_v1, &struct iwl_proto_offload_cmd_v2,
* &struct iwl_proto_offload_cmd_v3_small,
* &struct iwl_proto_offload_cmd_v3_large
*/
PROT_OFFLOAD_CONFIG_CMD = 0xd4,
/**
* @OFFLOADS_QUERY_CMD:
* No data in command, response in &struct iwl_wowlan_status
*/
OFFLOADS_QUERY_CMD = 0xd5,
/**
* @D0I3_END_CMD: End D0i3/D3 state, no command data
*/
D0I3_END_CMD = 0xed,
/**
* @WOWLAN_PATTERNS: &struct iwl_wowlan_patterns_cmd
*/
WOWLAN_PATTERNS = 0xe0,
/**
* @WOWLAN_CONFIGURATION: &struct iwl_wowlan_config_cmd
*/
WOWLAN_CONFIGURATION = 0xe1,
/**
* @WOWLAN_TSC_RSC_PARAM: &struct iwl_wowlan_rsc_tsc_params_cmd_v4,
* &struct iwl_wowlan_rsc_tsc_params_cmd
*/
WOWLAN_TSC_RSC_PARAM = 0xe2,
/**
* @WOWLAN_TKIP_PARAM: &struct iwl_wowlan_tkip_params_cmd
*/
WOWLAN_TKIP_PARAM = 0xe3,
/**
* @WOWLAN_KEK_KCK_MATERIAL: &struct iwl_wowlan_kek_kck_material_cmd
*/
WOWLAN_KEK_KCK_MATERIAL = 0xe4,
/**
* @WOWLAN_GET_STATUSES: response in &struct iwl_wowlan_status
*/
WOWLAN_GET_STATUSES = 0xe5,
/**
* @SCAN_OFFLOAD_PROFILES_QUERY_CMD:
* No command data, response is &struct iwl_scan_offload_profiles_query
*/
SCAN_OFFLOAD_PROFILES_QUERY_CMD = 0x56,
};
/**
* enum iwl_system_subcmd_ids - system group command IDs
*/
enum iwl_system_subcmd_ids {
/**
* @SHARED_MEM_CFG_CMD:
* response in &struct iwl_shared_mem_cfg or
* &struct iwl_shared_mem_cfg_v2
*/
SHARED_MEM_CFG_CMD = 0x0,
/**
* @SOC_CONFIGURATION_CMD: &struct iwl_soc_configuration_cmd
*/
SOC_CONFIGURATION_CMD = 0x01,
/**
* @INIT_EXTENDED_CFG_CMD: &struct iwl_init_extended_cfg_cmd
*/
INIT_EXTENDED_CFG_CMD = 0x03,
/**
* @FW_ERROR_RECOVERY_CMD: &struct iwl_fw_error_recovery_cmd
*/
FW_ERROR_RECOVERY_CMD = 0x7,
/**
* @RFI_CONFIG_CMD: &struct iwl_rfi_config_cmd
*/
RFI_CONFIG_CMD = 0xb,
/**
* @RFI_GET_FREQ_TABLE_CMD: &struct iwl_rfi_config_cmd
*/
RFI_GET_FREQ_TABLE_CMD = 0xc,
};
#endif /* __iwl_fw_api_commands_h__ */

View File

@ -0,0 +1,150 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2012-2014, 2018-2019 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
#ifndef __iwl_fw_api_config_h__
#define __iwl_fw_api_config_h__
/*
* struct iwl_dqa_enable_cmd
* @cmd_queue: the TXQ number of the command queue
*/
struct iwl_dqa_enable_cmd {
__le32 cmd_queue;
} __packed; /* DQA_CONTROL_CMD_API_S_VER_1 */
/*
* struct iwl_tx_ant_cfg_cmd
* @valid: valid antenna configuration
*/
struct iwl_tx_ant_cfg_cmd {
__le32 valid;
} __packed;
/**
* struct iwl_calib_ctrl - Calibration control struct.
* Sent as part of the phy configuration command.
* @flow_trigger: bitmap for which calibrations to perform according to
* flow triggers, using &enum iwl_calib_cfg
* @event_trigger: bitmap for which calibrations to perform according to
* event triggers, using &enum iwl_calib_cfg
*/
struct iwl_calib_ctrl {
__le32 flow_trigger;
__le32 event_trigger;
} __packed;
/* This enum defines the bitmap of various calibrations to enable in both
* init ucode and runtime ucode through CALIBRATION_CFG_CMD.
*/
enum iwl_calib_cfg {
IWL_CALIB_CFG_XTAL_IDX = BIT(0),
IWL_CALIB_CFG_TEMPERATURE_IDX = BIT(1),
IWL_CALIB_CFG_VOLTAGE_READ_IDX = BIT(2),
IWL_CALIB_CFG_PAPD_IDX = BIT(3),
IWL_CALIB_CFG_TX_PWR_IDX = BIT(4),
IWL_CALIB_CFG_DC_IDX = BIT(5),
IWL_CALIB_CFG_BB_FILTER_IDX = BIT(6),
IWL_CALIB_CFG_LO_LEAKAGE_IDX = BIT(7),
IWL_CALIB_CFG_TX_IQ_IDX = BIT(8),
IWL_CALIB_CFG_TX_IQ_SKEW_IDX = BIT(9),
IWL_CALIB_CFG_RX_IQ_IDX = BIT(10),
IWL_CALIB_CFG_RX_IQ_SKEW_IDX = BIT(11),
IWL_CALIB_CFG_SENSITIVITY_IDX = BIT(12),
IWL_CALIB_CFG_CHAIN_NOISE_IDX = BIT(13),
IWL_CALIB_CFG_DISCONNECTED_ANT_IDX = BIT(14),
IWL_CALIB_CFG_ANT_COUPLING_IDX = BIT(15),
IWL_CALIB_CFG_DAC_IDX = BIT(16),
IWL_CALIB_CFG_ABS_IDX = BIT(17),
IWL_CALIB_CFG_AGC_IDX = BIT(18),
};
/**
* struct iwl_phy_specific_cfg - specific PHY filter configuration
*
* Sent as part of the phy configuration command (v3) to configure specific FW
* defined PHY filters that can be applied to each antenna.
*
* @filter_cfg_chain_a: filter config id for LMAC1 chain A
* @filter_cfg_chain_b: filter config id for LMAC1 chain B
* @filter_cfg_chain_c: filter config id for LMAC2 chain A
* @filter_cfg_chain_d: filter config id for LMAC2 chain B
* values: 0 - no filter; 0xffffffff - reserved; otherwise - filter id
*/
struct iwl_phy_specific_cfg {
__le32 filter_cfg_chain_a;
__le32 filter_cfg_chain_b;
__le32 filter_cfg_chain_c;
__le32 filter_cfg_chain_d;
} __packed; /* PHY_SPECIFIC_CONFIGURATION_API_VER_1*/
/**
* struct iwl_phy_cfg_cmd - Phy configuration command
*
* @phy_cfg: PHY configuration value, uses &enum iwl_fw_phy_cfg
* @calib_control: calibration control data
*/
struct iwl_phy_cfg_cmd_v1 {
__le32 phy_cfg;
struct iwl_calib_ctrl calib_control;
} __packed;
/**
* struct iwl_phy_cfg_cmd_v3 - Phy configuration command (v3)
*
* @phy_cfg: PHY configuration value, uses &enum iwl_fw_phy_cfg
* @calib_control: calibration control data
* @phy_specific_cfg: configure predefined PHY filters
*/
struct iwl_phy_cfg_cmd_v3 {
__le32 phy_cfg;
struct iwl_calib_ctrl calib_control;
struct iwl_phy_specific_cfg phy_specific_cfg;
} __packed; /* PHY_CONFIGURATION_CMD_API_S_VER_3 */
/*
* enum iwl_dc2dc_config_id - flag ids
*
* Ids of dc2dc configuration flags
*/
enum iwl_dc2dc_config_id {
DCDC_LOW_POWER_MODE_MSK_SET = 0x1, /* not used */
DCDC_FREQ_TUNE_SET = 0x2,
}; /* MARKER_ID_API_E_VER_1 */
/**
* struct iwl_dc2dc_config_cmd - configure dc2dc values
*
* (DC2DC_CONFIG_CMD = 0x83)
*
* Set/Get & configure dc2dc values.
* The command always returns the current dc2dc values.
*
* @flags: set/get dc2dc
* @enable_low_power_mode: not used.
* @dc2dc_freq_tune0: frequency divider - digital domain
* @dc2dc_freq_tune1: frequency divider - analog domain
*/
struct iwl_dc2dc_config_cmd {
__le32 flags;
__le32 enable_low_power_mode; /* not used */
__le32 dc2dc_freq_tune0;
__le32 dc2dc_freq_tune1;
} __packed; /* DC2DC_CONFIG_CMD_API_S_VER_1 */
/**
* struct iwl_dc2dc_config_resp - response for iwl_dc2dc_config_cmd
*
* Current dc2dc values returned by the FW.
*
* @dc2dc_freq_tune0: frequency divider - digital domain
* @dc2dc_freq_tune1: frequency divider - analog domain
*/
struct iwl_dc2dc_config_resp {
__le32 dc2dc_freq_tune0;
__le32 dc2dc_freq_tune1;
} __packed; /* DC2DC_CONFIG_RESP_API_S_VER_1 */
#endif /* __iwl_fw_api_config_h__ */

View File

@ -0,0 +1,38 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2012-2014 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
#ifndef __iwl_fw_api_context_h__
#define __iwl_fw_api_context_h__
/**
* enum iwl_ctxt_id_and_color - ID and color fields in context dword
* @FW_CTXT_ID_POS: position of the ID
* @FW_CTXT_ID_MSK: mask of the ID
* @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
*/
enum iwl_ctxt_id_and_color {
FW_CTXT_ID_POS = 0,
FW_CTXT_ID_MSK = 0xff << FW_CTXT_ID_POS,
FW_CTXT_COLOR_POS = 8,
FW_CTXT_COLOR_MSK = 0xff << FW_CTXT_COLOR_POS,
FW_CTXT_INVALID = 0xffffffff,
};
#define FW_CMD_ID_AND_COLOR(_id, _color) (((_id) << FW_CTXT_ID_POS) |\
((_color) << FW_CTXT_COLOR_POS))
/* Possible actions on PHYs, MACs and Bindings */
enum iwl_ctxt_action {
FW_CTXT_ACTION_STUB = 0,
FW_CTXT_ACTION_ADD,
FW_CTXT_ACTION_MODIFY,
FW_CTXT_ACTION_REMOVE,
FW_CTXT_ACTION_NUM
}; /* COMMON_CONTEXT_ACTION_API_E_VER_1 */
#endif /* __iwl_fw_api_context_h__ */

View File

@ -0,0 +1,698 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2012-2014, 2018-2021 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2015-2017 Intel Deutschland GmbH
*/
#ifndef __iwl_fw_api_d3_h__
#define __iwl_fw_api_d3_h__
#include <iwl-trans.h>
/**
* enum iwl_d0i3_flags - d0i3 flags
* @IWL_D0I3_RESET_REQUIRE: FW require reset upon resume
*/
enum iwl_d0i3_flags {
IWL_D0I3_RESET_REQUIRE = BIT(0),
};
/**
* enum iwl_d3_wakeup_flags - D3 manager wakeup flags
* @IWL_WAKEUP_D3_CONFIG_FW_ERROR: wake up on firmware sysassert
*/
enum iwl_d3_wakeup_flags {
IWL_WAKEUP_D3_CONFIG_FW_ERROR = BIT(0),
}; /* D3_MANAGER_WAKEUP_CONFIG_API_E_VER_3 */
/**
* struct iwl_d3_manager_config - D3 manager configuration command
* @min_sleep_time: minimum sleep time (in usec)
* @wakeup_flags: wakeup flags, see &enum iwl_d3_wakeup_flags
* @wakeup_host_timer: force wakeup after this many seconds
*
* The structure is used for the D3_CONFIG_CMD command.
*/
struct iwl_d3_manager_config {
__le32 min_sleep_time;
__le32 wakeup_flags;
__le32 wakeup_host_timer;
} __packed; /* D3_MANAGER_CONFIG_CMD_S_VER_4 */
/* TODO: OFFLOADS_QUERY_API_S_VER_1 */
/**
* enum iwl_d3_proto_offloads - enabled protocol offloads
* @IWL_D3_PROTO_OFFLOAD_ARP: ARP data is enabled
* @IWL_D3_PROTO_OFFLOAD_NS: NS (Neighbor Solicitation) is enabled
* @IWL_D3_PROTO_IPV4_VALID: IPv4 data is valid
* @IWL_D3_PROTO_IPV6_VALID: IPv6 data is valid
*/
enum iwl_proto_offloads {
IWL_D3_PROTO_OFFLOAD_ARP = BIT(0),
IWL_D3_PROTO_OFFLOAD_NS = BIT(1),
IWL_D3_PROTO_IPV4_VALID = BIT(2),
IWL_D3_PROTO_IPV6_VALID = BIT(3),
};
#define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V1 2
#define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V2 6
#define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V3L 12
#define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V3S 4
#define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_MAX 12
#define IWL_PROTO_OFFLOAD_NUM_NS_CONFIG_V3L 4
#define IWL_PROTO_OFFLOAD_NUM_NS_CONFIG_V3S 2
/**
* struct iwl_proto_offload_cmd_common - ARP/NS offload common part
* @enabled: enable flags
* @remote_ipv4_addr: remote address to answer to (or zero if all)
* @host_ipv4_addr: our IPv4 address to respond to queries for
* @arp_mac_addr: our MAC address for ARP responses
* @reserved: unused
*/
struct iwl_proto_offload_cmd_common {
__le32 enabled;
__be32 remote_ipv4_addr;
__be32 host_ipv4_addr;
u8 arp_mac_addr[ETH_ALEN];
__le16 reserved;
} __packed;
/**
* struct iwl_proto_offload_cmd_v1 - ARP/NS offload configuration
* @common: common/IPv4 configuration
* @remote_ipv6_addr: remote address to answer to (or zero if all)
* @solicited_node_ipv6_addr: broken -- solicited node address exists
* for each target address
* @target_ipv6_addr: our target addresses
* @ndp_mac_addr: neighbor solicitation response MAC address
* @reserved2: reserved
*/
struct iwl_proto_offload_cmd_v1 {
struct iwl_proto_offload_cmd_common common;
u8 remote_ipv6_addr[16];
u8 solicited_node_ipv6_addr[16];
u8 target_ipv6_addr[IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V1][16];
u8 ndp_mac_addr[ETH_ALEN];
__le16 reserved2;
} __packed; /* PROT_OFFLOAD_CONFIG_CMD_DB_S_VER_1 */
/**
* struct iwl_proto_offload_cmd_v2 - ARP/NS offload configuration
* @common: common/IPv4 configuration
* @remote_ipv6_addr: remote address to answer to (or zero if all)
* @solicited_node_ipv6_addr: broken -- solicited node address exists
* for each target address
* @target_ipv6_addr: our target addresses
* @ndp_mac_addr: neighbor solicitation response MAC address
* @num_valid_ipv6_addrs: number of valid IPv6 addresses
* @reserved2: reserved
*/
struct iwl_proto_offload_cmd_v2 {
struct iwl_proto_offload_cmd_common common;
u8 remote_ipv6_addr[16];
u8 solicited_node_ipv6_addr[16];
u8 target_ipv6_addr[IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V2][16];
u8 ndp_mac_addr[ETH_ALEN];
u8 num_valid_ipv6_addrs;
u8 reserved2[3];
} __packed; /* PROT_OFFLOAD_CONFIG_CMD_DB_S_VER_2 */
struct iwl_ns_config {
struct in6_addr source_ipv6_addr;
struct in6_addr dest_ipv6_addr;
u8 target_mac_addr[ETH_ALEN];
__le16 reserved;
} __packed; /* NS_OFFLOAD_CONFIG */
struct iwl_targ_addr {
struct in6_addr addr;
__le32 config_num;
} __packed; /* TARGET_IPV6_ADDRESS */
/**
* struct iwl_proto_offload_cmd_v3_small - ARP/NS offload configuration
* @common: common/IPv4 configuration
* @num_valid_ipv6_addrs: number of valid IPv6 addresses
* @targ_addrs: target IPv6 addresses
* @ns_config: NS offload configurations
*/
struct iwl_proto_offload_cmd_v3_small {
struct iwl_proto_offload_cmd_common common;
__le32 num_valid_ipv6_addrs;
struct iwl_targ_addr targ_addrs[IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V3S];
struct iwl_ns_config ns_config[IWL_PROTO_OFFLOAD_NUM_NS_CONFIG_V3S];
} __packed; /* PROT_OFFLOAD_CONFIG_CMD_DB_S_VER_3 */
/**
* struct iwl_proto_offload_cmd_v3_large - ARP/NS offload configuration
* @common: common/IPv4 configuration
* @num_valid_ipv6_addrs: number of valid IPv6 addresses
* @targ_addrs: target IPv6 addresses
* @ns_config: NS offload configurations
*/
struct iwl_proto_offload_cmd_v3_large {
struct iwl_proto_offload_cmd_common common;
__le32 num_valid_ipv6_addrs;
struct iwl_targ_addr targ_addrs[IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V3L];
struct iwl_ns_config ns_config[IWL_PROTO_OFFLOAD_NUM_NS_CONFIG_V3L];
} __packed; /* PROT_OFFLOAD_CONFIG_CMD_DB_S_VER_3 */
/**
* struct iwl_proto_offload_cmd_v4 - ARP/NS offload configuration
* @sta_id: station id
* @common: common/IPv4 configuration
* @num_valid_ipv6_addrs: number of valid IPv6 addresses
* @targ_addrs: target IPv6 addresses
* @ns_config: NS offload configurations
*/
struct iwl_proto_offload_cmd_v4 {
__le32 sta_id;
struct iwl_proto_offload_cmd_common common;
__le32 num_valid_ipv6_addrs;
struct iwl_targ_addr targ_addrs[IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V3L];
struct iwl_ns_config ns_config[IWL_PROTO_OFFLOAD_NUM_NS_CONFIG_V3L];
} __packed; /* PROT_OFFLOAD_CONFIG_CMD_DB_S_VER_4 */
/*
* WOWLAN_PATTERNS
*/
#define IWL_WOWLAN_MIN_PATTERN_LEN 16
#define IWL_WOWLAN_MAX_PATTERN_LEN 128
struct iwl_wowlan_pattern_v1 {
u8 mask[IWL_WOWLAN_MAX_PATTERN_LEN / 8];
u8 pattern[IWL_WOWLAN_MAX_PATTERN_LEN];
u8 mask_size;
u8 pattern_size;
__le16 reserved;
} __packed; /* WOWLAN_PATTERN_API_S_VER_1 */
#define IWL_WOWLAN_MAX_PATTERNS 20
/**
* struct iwl_wowlan_patterns_cmd - WoWLAN wakeup patterns
*/
struct iwl_wowlan_patterns_cmd_v1 {
/**
* @n_patterns: number of patterns
*/
__le32 n_patterns;
/**
* @patterns: the patterns, array length in @n_patterns
*/
struct iwl_wowlan_pattern_v1 patterns[];
} __packed; /* WOWLAN_PATTERN_ARRAY_API_S_VER_1 */
#define IPV4_ADDR_SIZE 4
#define IPV6_ADDR_SIZE 16
enum iwl_wowlan_pattern_type {
WOWLAN_PATTERN_TYPE_BITMASK,
WOWLAN_PATTERN_TYPE_IPV4_TCP_SYN,
WOWLAN_PATTERN_TYPE_IPV6_TCP_SYN,
WOWLAN_PATTERN_TYPE_IPV4_TCP_SYN_WILDCARD,
WOWLAN_PATTERN_TYPE_IPV6_TCP_SYN_WILDCARD,
}; /* WOWLAN_PATTERN_TYPE_API_E_VER_1 */
/**
* struct iwl_wowlan_ipv4_tcp_syn - WoWLAN IPv4 TCP SYN pattern data
*/
struct iwl_wowlan_ipv4_tcp_syn {
/**
* @src_addr: source IP address to match
*/
u8 src_addr[IPV4_ADDR_SIZE];
/**
* @dst_addr: destination IP address to match
*/
u8 dst_addr[IPV4_ADDR_SIZE];
/**
* @src_port: source TCP port to match
*/
__le16 src_port;
/**
* @dst_port: destination TCP port to match
*/
__le16 dst_port;
} __packed; /* WOWLAN_IPV4_TCP_SYN_API_S_VER_1 */
/**
* struct iwl_wowlan_ipv6_tcp_syn - WoWLAN Ipv6 TCP SYN pattern data
*/
struct iwl_wowlan_ipv6_tcp_syn {
/**
* @src_addr: source IP address to match
*/
u8 src_addr[IPV6_ADDR_SIZE];
/**
* @dst_addr: destination IP address to match
*/
u8 dst_addr[IPV6_ADDR_SIZE];
/**
* @src_port: source TCP port to match
*/
__le16 src_port;
/**
* @dst_port: destination TCP port to match
*/
__le16 dst_port;
} __packed; /* WOWLAN_IPV6_TCP_SYN_API_S_VER_1 */
/**
* union iwl_wowlan_pattern_data - Data for the different pattern types
*
* If wildcard addresses/ports are to be used, the union can be left
* undefined.
*/
union iwl_wowlan_pattern_data {
/**
* @bitmask: bitmask pattern data
*/
struct iwl_wowlan_pattern_v1 bitmask;
/**
* @ipv4_tcp_syn: IPv4 TCP SYN pattern data
*/
struct iwl_wowlan_ipv4_tcp_syn ipv4_tcp_syn;
/**
* @ipv6_tcp_syn: IPv6 TCP SYN pattern data
*/
struct iwl_wowlan_ipv6_tcp_syn ipv6_tcp_syn;
}; /* WOWLAN_PATTERN_API_U_VER_1 */
/**
* struct iwl_wowlan_pattern_v2 - Pattern entry for the WoWLAN wakeup patterns
*/
struct iwl_wowlan_pattern_v2 {
/**
* @pattern_type: defines the struct type to be used in the union
*/
u8 pattern_type;
/**
* @reserved: reserved for alignment
*/
u8 reserved[3];
/**
* @u: the union containing the match data, or undefined for
* wildcard matches
*/
union iwl_wowlan_pattern_data u;
} __packed; /* WOWLAN_PATTERN_API_S_VER_2 */
/**
* struct iwl_wowlan_patterns_cmd - WoWLAN wakeup patterns command
*/
struct iwl_wowlan_patterns_cmd {
/**
* @n_patterns: number of patterns
*/
u8 n_patterns;
/**
* @n_patterns: sta_id
*/
u8 sta_id;
/**
* @reserved: reserved for alignment
*/
__le16 reserved;
/**
* @patterns: the patterns, array length in @n_patterns
*/
struct iwl_wowlan_pattern_v2 patterns[];
} __packed; /* WOWLAN_PATTERN_ARRAY_API_S_VER_3 */
enum iwl_wowlan_wakeup_filters {
IWL_WOWLAN_WAKEUP_MAGIC_PACKET = BIT(0),
IWL_WOWLAN_WAKEUP_PATTERN_MATCH = BIT(1),
IWL_WOWLAN_WAKEUP_BEACON_MISS = BIT(2),
IWL_WOWLAN_WAKEUP_LINK_CHANGE = BIT(3),
IWL_WOWLAN_WAKEUP_GTK_REKEY_FAIL = BIT(4),
IWL_WOWLAN_WAKEUP_EAP_IDENT_REQ = BIT(5),
IWL_WOWLAN_WAKEUP_4WAY_HANDSHAKE = BIT(6),
IWL_WOWLAN_WAKEUP_ENABLE_NET_DETECT = BIT(7),
IWL_WOWLAN_WAKEUP_RF_KILL_DEASSERT = BIT(8),
IWL_WOWLAN_WAKEUP_REMOTE_LINK_LOSS = BIT(9),
IWL_WOWLAN_WAKEUP_REMOTE_SIGNATURE_TABLE = BIT(10),
IWL_WOWLAN_WAKEUP_REMOTE_TCP_EXTERNAL = BIT(11),
IWL_WOWLAN_WAKEUP_REMOTE_WAKEUP_PACKET = BIT(12),
IWL_WOWLAN_WAKEUP_IOAC_MAGIC_PACKET = BIT(13),
IWL_WOWLAN_WAKEUP_HOST_TIMER = BIT(14),
IWL_WOWLAN_WAKEUP_RX_FRAME = BIT(15),
IWL_WOWLAN_WAKEUP_BCN_FILTERING = BIT(16),
}; /* WOWLAN_WAKEUP_FILTER_API_E_VER_4 */
enum iwl_wowlan_flags {
IS_11W_ASSOC = BIT(0),
ENABLE_L3_FILTERING = BIT(1),
ENABLE_NBNS_FILTERING = BIT(2),
ENABLE_DHCP_FILTERING = BIT(3),
ENABLE_STORE_BEACON = BIT(4),
};
/**
* struct iwl_wowlan_config_cmd - 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.
* @qos_seq: QoS sequence counters to use next
* @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;
__le16 non_qos_seq;
__le16 qos_seq[8];
u8 wowlan_ba_teardown_tids;
u8 is_11n_connection;
u8 offloading_tid;
u8 flags;
u8 sta_id;
u8 reserved;
} __packed; /* WOWLAN_CONFIG_API_S_VER_5 */
#define IWL_NUM_RSC 16
#define WOWLAN_KEY_MAX_SIZE 32
#define WOWLAN_GTK_KEYS_NUM 2
#define WOWLAN_IGTK_KEYS_NUM 2
/*
* WOWLAN_TSC_RSC_PARAMS
*/
struct tkip_sc {
__le16 iv16;
__le16 pad;
__le32 iv32;
} __packed; /* TKIP_SC_API_U_VER_1 */
struct iwl_tkip_rsc_tsc {
struct tkip_sc unicast_rsc[IWL_NUM_RSC];
struct tkip_sc multicast_rsc[IWL_NUM_RSC];
struct tkip_sc tsc;
} __packed; /* TKIP_TSC_RSC_API_S_VER_1 */
struct aes_sc {
__le64 pn;
} __packed; /* TKIP_AES_SC_API_U_VER_1 */
struct iwl_aes_rsc_tsc {
struct aes_sc unicast_rsc[IWL_NUM_RSC];
struct aes_sc multicast_rsc[IWL_NUM_RSC];
struct aes_sc tsc;
} __packed; /* AES_TSC_RSC_API_S_VER_1 */
union iwl_all_tsc_rsc {
struct iwl_tkip_rsc_tsc tkip;
struct iwl_aes_rsc_tsc aes;
}; /* ALL_TSC_RSC_API_S_VER_2 */
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];
__le32 sta_id;
#define IWL_MCAST_KEY_MAP_INVALID 0xff
u8 mcast_key_id_map[4];
} __packed; /* ALL_TSC_RSC_API_S_VER_5 */
#define IWL_MIC_KEY_SIZE 8
struct iwl_mic_keys {
u8 tx[IWL_MIC_KEY_SIZE];
u8 rx_unicast[IWL_MIC_KEY_SIZE];
u8 rx_mcast[IWL_MIC_KEY_SIZE];
} __packed; /* MIC_KEYS_API_S_VER_1 */
#define IWL_P1K_SIZE 5
struct iwl_p1k_cache {
__le16 p1k[IWL_P1K_SIZE];
} __packed;
#define IWL_NUM_RX_P1K_CACHE 2
struct iwl_wowlan_tkip_params_cmd_ver_1 {
struct iwl_mic_keys mic_keys;
struct iwl_p1k_cache tx;
struct iwl_p1k_cache rx_uni[IWL_NUM_RX_P1K_CACHE];
struct iwl_p1k_cache rx_multi[IWL_NUM_RX_P1K_CACHE];
} __packed; /* WOWLAN_TKIP_SETTING_API_S_VER_1 */
struct iwl_wowlan_tkip_params_cmd {
struct iwl_mic_keys mic_keys;
struct iwl_p1k_cache tx;
struct iwl_p1k_cache rx_uni[IWL_NUM_RX_P1K_CACHE];
struct iwl_p1k_cache rx_multi[IWL_NUM_RX_P1K_CACHE];
u8 reversed[2];
__le32 sta_id;
} __packed; /* WOWLAN_TKIP_SETTING_API_S_VER_2 */
#define IWL_KCK_MAX_SIZE 32
#define IWL_KEK_MAX_SIZE 32
struct iwl_wowlan_kek_kck_material_cmd_v2 {
u8 kck[IWL_KCK_MAX_SIZE];
u8 kek[IWL_KEK_MAX_SIZE];
__le16 kck_len;
__le16 kek_len;
__le64 replay_ctr;
} __packed; /* KEK_KCK_MATERIAL_API_S_VER_2 */
struct iwl_wowlan_kek_kck_material_cmd_v3 {
u8 kck[IWL_KCK_MAX_SIZE];
u8 kek[IWL_KEK_MAX_SIZE];
__le16 kck_len;
__le16 kek_len;
__le64 replay_ctr;
__le32 akm;
__le32 gtk_cipher;
__le32 igtk_cipher;
__le32 bigtk_cipher;
} __packed; /* KEK_KCK_MATERIAL_API_S_VER_3 */
struct iwl_wowlan_kek_kck_material_cmd_v4 {
__le32 sta_id;
u8 kck[IWL_KCK_MAX_SIZE];
u8 kek[IWL_KEK_MAX_SIZE];
__le16 kck_len;
__le16 kek_len;
__le64 replay_ctr;
__le32 akm;
__le32 gtk_cipher;
__le32 igtk_cipher;
__le32 bigtk_cipher;
} __packed; /* KEK_KCK_MATERIAL_API_S_VER_4 */
struct iwl_wowlan_get_status_cmd {
__le32 sta_id;
} __packed; /* WOWLAN_GET_STATUSES_CMD_API_S_VER_1 */
#define RF_KILL_INDICATOR_FOR_WOWLAN 0x87
enum iwl_wowlan_rekey_status {
IWL_WOWLAN_REKEY_POST_REKEY = 0,
IWL_WOWLAN_REKEY_WHILE_REKEY = 1,
}; /* WOWLAN_REKEY_STATUS_API_E_VER_1 */
enum iwl_wowlan_wakeup_reason {
IWL_WOWLAN_WAKEUP_BY_NON_WIRELESS = 0,
IWL_WOWLAN_WAKEUP_BY_MAGIC_PACKET = BIT(0),
IWL_WOWLAN_WAKEUP_BY_PATTERN = BIT(1),
IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_MISSED_BEACON = BIT(2),
IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_DEAUTH = BIT(3),
IWL_WOWLAN_WAKEUP_BY_GTK_REKEY_FAILURE = BIT(4),
IWL_WOWLAN_WAKEUP_BY_RFKILL_DEASSERTED = BIT(5),
IWL_WOWLAN_WAKEUP_BY_UCODE_ERROR = BIT(6),
IWL_WOWLAN_WAKEUP_BY_EAPOL_REQUEST = BIT(7),
IWL_WOWLAN_WAKEUP_BY_FOUR_WAY_HANDSHAKE = BIT(8),
IWL_WOWLAN_WAKEUP_BY_REM_WAKE_LINK_LOSS = BIT(9),
IWL_WOWLAN_WAKEUP_BY_REM_WAKE_SIGNATURE_TABLE = BIT(10),
IWL_WOWLAN_WAKEUP_BY_REM_WAKE_TCP_EXTERNAL = BIT(11),
IWL_WOWLAN_WAKEUP_BY_REM_WAKE_WAKEUP_PACKET = BIT(12),
IWL_WOWLAN_WAKEUP_BY_IOAC_MAGIC_PACKET = BIT(13),
IWL_WOWLAN_WAKEUP_BY_D3_WAKEUP_HOST_TIMER = BIT(14),
IWL_WOWLAN_WAKEUP_BY_RXFRAME_FILTERED_IN = BIT(15),
IWL_WOWLAN_WAKEUP_BY_BEACON_FILTERED_IN = BIT(16),
IWL_WAKEUP_BY_11W_UNPROTECTED_DEAUTH_OR_DISASSOC = BIT(17),
IWL_WAKEUP_BY_PATTERN_IPV4_TCP_SYN = BIT(18),
IWL_WAKEUP_BY_PATTERN_IPV4_TCP_SYN_WILDCARD = BIT(19),
IWL_WAKEUP_BY_PATTERN_IPV6_TCP_SYN = BIT(20),
IWL_WAKEUP_BY_PATTERN_IPV6_TCP_SYN_WILDCARD = BIT(21),
}; /* WOWLAN_WAKE_UP_REASON_API_E_VER_2 */
struct iwl_wowlan_gtk_status_v1 {
u8 key_index;
u8 reserved[3];
u8 decrypt_key[16];
u8 tkip_mic_key[8];
struct iwl_wowlan_rsc_tsc_params_cmd_ver_2 rsc;
} __packed; /* WOWLAN_GTK_MATERIAL_VER_1 */
/**
* struct iwl_wowlan_gtk_status - GTK status
* @key: GTK material
* @key_len: GTK legth, if set to 0, the key is not available
* @key_flags: information about the key:
* bits[0:1]: key index assigned by the AP
* bits[2:6]: GTK index of the key in the internal DB
* bit[7]: Set iff this is the currently used GTK
* @reserved: padding
* @tkip_mic_key: TKIP RX MIC key
* @rsc: TSC RSC counters
*/
struct iwl_wowlan_gtk_status {
u8 key[WOWLAN_KEY_MAX_SIZE];
u8 key_len;
u8 key_flags;
u8 reserved[2];
u8 tkip_mic_key[8];
struct iwl_wowlan_rsc_tsc_params_cmd_ver_2 rsc;
} __packed; /* WOWLAN_GTK_MATERIAL_VER_2 */
#define IWL_WOWLAN_GTK_IDX_MASK (BIT(0) | BIT(1))
/**
* struct iwl_wowlan_igtk_status - IGTK status
* @key: IGTK material
* @ipn: the IGTK packet number (replay counter)
* @key_len: IGTK length, if set to 0, the key is not available
* @key_flags: information about the key:
* bits[0]: key index assigned by the AP (0: index 4, 1: index 5)
* bits[1:5]: IGTK index of the key in the internal DB
* bit[6]: Set iff this is the currently used IGTK
*/
struct iwl_wowlan_igtk_status {
u8 key[WOWLAN_KEY_MAX_SIZE];
u8 ipn[6];
u8 key_len;
u8 key_flags;
} __packed; /* WOWLAN_IGTK_MATERIAL_VER_1 */
/**
* struct iwl_wowlan_status_v6 - WoWLAN status
* @gtk: GTK 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
* @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
* @wake_packet: wakeup packet
*/
struct iwl_wowlan_status_v6 {
struct iwl_wowlan_gtk_status_v1 gtk;
__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 wake_packet[]; /* can be truncated from _length to _bufsize */
} __packed; /* WOWLAN_STATUSES_API_S_VER_6 */
/**
* struct iwl_wowlan_status_v7 - 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
* @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
* @wake_packet: wakeup packet
*/
struct iwl_wowlan_status_v7 {
struct iwl_wowlan_gtk_status 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 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 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 */
/* TODO: NetDetect API */
#endif /* __iwl_fw_api_d3_h__ */

View File

@ -0,0 +1,198 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2012-2014, 2018-2020 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
#ifndef __iwl_fw_api_datapath_h__
#define __iwl_fw_api_datapath_h__
/**
* enum iwl_data_path_subcmd_ids - data path group commands
*/
enum iwl_data_path_subcmd_ids {
/**
* @DQA_ENABLE_CMD: &struct iwl_dqa_enable_cmd
*/
DQA_ENABLE_CMD = 0x0,
/**
* @UPDATE_MU_GROUPS_CMD: &struct iwl_mu_group_mgmt_cmd
*/
UPDATE_MU_GROUPS_CMD = 0x1,
/**
* @TRIGGER_RX_QUEUES_NOTIF_CMD: &struct iwl_rxq_sync_cmd
*/
TRIGGER_RX_QUEUES_NOTIF_CMD = 0x2,
/**
* @STA_HE_CTXT_CMD: &struct iwl_he_sta_context_cmd
*/
STA_HE_CTXT_CMD = 0x7,
/**
* @RFH_QUEUE_CONFIG_CMD: &struct iwl_rfh_queue_config
*/
RFH_QUEUE_CONFIG_CMD = 0xD,
/**
* @TLC_MNG_CONFIG_CMD: &struct iwl_tlc_config_cmd
*/
TLC_MNG_CONFIG_CMD = 0xF,
/**
* @HE_AIR_SNIFFER_CONFIG_CMD: &struct iwl_he_monitor_cmd
*/
HE_AIR_SNIFFER_CONFIG_CMD = 0x13,
/**
* @CHEST_COLLECTOR_FILTER_CONFIG_CMD: Configure the CSI
* matrix collection, uses &struct iwl_channel_estimation_cfg
*/
CHEST_COLLECTOR_FILTER_CONFIG_CMD = 0x14,
/**
* @MONITOR_NOTIF: Datapath monitoring notification, using
* &struct iwl_datapath_monitor_notif
*/
MONITOR_NOTIF = 0xF4,
/**
* @RX_NO_DATA_NOTIF: &struct iwl_rx_no_data
*/
RX_NO_DATA_NOTIF = 0xF5,
/**
* @THERMAL_DUAL_CHAIN_DISABLE_REQ: firmware request for SMPS mode,
* &struct iwl_thermal_dual_chain_request
*/
THERMAL_DUAL_CHAIN_REQUEST = 0xF6,
/**
* @TLC_MNG_UPDATE_NOTIF: &struct iwl_tlc_update_notif
*/
TLC_MNG_UPDATE_NOTIF = 0xF7,
/**
* @STA_PM_NOTIF: &struct iwl_mvm_pm_state_notification
*/
STA_PM_NOTIF = 0xFD,
/**
* @MU_GROUP_MGMT_NOTIF: &struct iwl_mu_group_mgmt_notif
*/
MU_GROUP_MGMT_NOTIF = 0xFE,
/**
* @RX_QUEUES_NOTIFICATION: &struct iwl_rxq_sync_notification
*/
RX_QUEUES_NOTIFICATION = 0xFF,
};
/**
* struct iwl_mu_group_mgmt_cmd - VHT MU-MIMO group configuration
*
* @reserved: reserved
* @membership_status: a bitmap of MU groups
* @user_position:the position of station in a group. If the station is in the
* group then bits (group * 2) is the position -1
*/
struct iwl_mu_group_mgmt_cmd {
__le32 reserved;
__le32 membership_status[2];
__le32 user_position[4];
} __packed; /* MU_GROUP_ID_MNG_TABLE_API_S_VER_1 */
/**
* struct iwl_mu_group_mgmt_notif - VHT MU-MIMO group id notification
*
* @membership_status: a bitmap of MU groups
* @user_position: the position of station in a group. If the station is in the
* group then bits (group * 2) is the position -1
*/
struct iwl_mu_group_mgmt_notif {
__le32 membership_status[2];
__le32 user_position[4];
} __packed; /* MU_GROUP_MNG_NTFY_API_S_VER_1 */
enum iwl_channel_estimation_flags {
IWL_CHANNEL_ESTIMATION_ENABLE = BIT(0),
IWL_CHANNEL_ESTIMATION_TIMER = BIT(1),
IWL_CHANNEL_ESTIMATION_COUNTER = BIT(2),
};
/**
* struct iwl_channel_estimation_cfg - channel estimation reporting config
*/
struct iwl_channel_estimation_cfg {
/**
* @flags: flags, see &enum iwl_channel_estimation_flags
*/
__le32 flags;
/**
* @timer: if enabled via flags, automatically disable after this many
* microseconds
*/
__le32 timer;
/**
* @count: if enabled via flags, automatically disable after this many
* frames with channel estimation matrix were captured
*/
__le32 count;
/**
* @rate_n_flags_mask: only try to record the channel estimation matrix
* if the rate_n_flags value for the received frame (let's call
* that rx_rnf) matches the mask/value given here like this:
* (rx_rnf & rate_n_flags_mask) == rate_n_flags_val.
*/
__le32 rate_n_flags_mask;
/**
* @rate_n_flags_val: see @rate_n_flags_mask
*/
__le32 rate_n_flags_val;
/**
* @reserved: reserved (for alignment)
*/
__le32 reserved;
/**
* @frame_types: bitmap of frame types to capture, the received frame's
* subtype|type takes 6 bits in the frame and the corresponding bit
* in this field must be set to 1 to capture channel estimation for
* that frame type. Set to all-ones to enable capturing for all
* frame types.
*/
__le64 frame_types;
} __packed; /* CHEST_COLLECTOR_FILTER_CMD_API_S_VER_1 */
enum iwl_datapath_monitor_notif_type {
IWL_DP_MON_NOTIF_TYPE_EXT_CCA,
};
struct iwl_datapath_monitor_notif {
__le32 type;
u8 mac_id;
u8 reserved[3];
} __packed; /* MONITOR_NTF_API_S_VER_1 */
/**
* enum iwl_thermal_dual_chain_req_events - firmware SMPS request event
* @THERMAL_DUAL_CHAIN_REQ_ENABLE: (re-)enable dual-chain operation
* (subject to other constraints)
* @THERMAL_DUAL_CHAIN_REQ_DISABLE: disable dual-chain operation
* (static SMPS)
*/
enum iwl_thermal_dual_chain_req_events {
THERMAL_DUAL_CHAIN_REQ_ENABLE,
THERMAL_DUAL_CHAIN_REQ_DISABLE,
}; /* THERMAL_DUAL_CHAIN_DISABLE_STATE_API_E_VER_1 */
/**
* struct iwl_thermal_dual_chain_request - SMPS request
* @event: the type of request, see &enum iwl_thermal_dual_chain_req_events
*/
struct iwl_thermal_dual_chain_request {
__le32 event;
} __packed; /* THERMAL_DUAL_CHAIN_DISABLE_REQ_NTFY_API_S_VER_1 */
#endif /* __iwl_fw_api_datapath_h__ */

View File

@ -0,0 +1,468 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2018-2021 Intel Corporation
*/
#ifndef __iwl_fw_dbg_tlv_h__
#define __iwl_fw_dbg_tlv_h__
#include <linux/bitops.h>
#define IWL_FW_INI_HW_SMEM_REGION_ID 15
#define IWL_FW_INI_MAX_REGION_ID 64
#define IWL_FW_INI_MAX_NAME 32
#define IWL_FW_INI_MAX_CFG_NAME 64
#define IWL_FW_INI_DOMAIN_ALWAYS_ON 0
#define IWL_FW_INI_REGION_V2_MASK 0x0000FFFF
/**
* struct iwl_fw_ini_hcmd
*
* @id: the debug configuration command type for instance: 0xf6 / 0xf5 / DHC
* @group: the desired cmd group
* @reserved: to align to FW struct
* @data: all of the relevant command data to be sent
*/
struct iwl_fw_ini_hcmd {
u8 id;
u8 group;
__le16 reserved;
u8 data[0];
} __packed; /* FW_DEBUG_TLV_HCMD_DATA_API_S_VER_1 */
/**
* struct iwl_fw_ini_header - Common Header for all ini debug TLV's structures
*
* @version: TLV version
* @domain: domain of the TLV. One of &enum iwl_fw_ini_dbg_domain
*/
struct iwl_fw_ini_header {
__le32 version;
__le32 domain;
/* followed by the data */
} __packed; /* FW_TLV_DEBUG_HEADER_S_VER_1 */
/**
* struct iwl_fw_ini_region_dev_addr - Configuration to read device addresses
*
* @size: size of each memory chunk
* @offset: offset to add to the base address of each chunk
*/
struct iwl_fw_ini_region_dev_addr {
__le32 size;
__le32 offset;
} __packed; /* FW_TLV_DEBUG_DEVICE_ADDR_API_S_VER_1 */
/**
* struct iwl_fw_ini_region_fifos - Configuration to read Tx/Rx fifos
*
* @fid: fifos ids array. Used to determine what fifos to collect
* @hdr_only: if non zero, collect only the registers
* @offset: offset to add to the registers addresses
*/
struct iwl_fw_ini_region_fifos {
__le32 fid[2];
__le32 hdr_only;
__le32 offset;
} __packed; /* FW_TLV_DEBUG_REGION_FIFOS_API_S_VER_1 */
/**
* struct iwl_fw_ini_region_err_table - error table region data
*
* Configuration to read Umac/Lmac error table
*
* @version: version of the error table
* @base_addr: base address of the error table
* @size: size of the error table
* @offset: offset to add to &base_addr
*/
struct iwl_fw_ini_region_err_table {
__le32 version;
__le32 base_addr;
__le32 size;
__le32 offset;
} __packed; /* FW_TLV_DEBUG_REGION_ERROR_TABLE_API_S_VER_1 */
/**
* struct iwl_fw_ini_region_special_device_memory - special device memory
*
* Configuration to read a special memory
*
* @type: type of the special memory
* @version: version of the special memory
* @base_addr: base address of the error table
* @size: size of the error table
* @offset: offset to add to &base_addr
*/
struct iwl_fw_ini_region_special_device_memory {
__le16 type;
__le16 version;
__le32 base_addr;
__le32 size;
__le32 offset;
} __packed; /* FW_TLV_DEBUG_REGION_SPECIAL_DEVICE_ADDR_API_S_VER_1 */
/**
* struct iwl_fw_ini_region_internal_buffer - internal buffer region data
*
* Configuration to read internal monitor buffer
*
* @alloc_id: allocation id one of &enum iwl_fw_ini_allocation_id
* @base_addr: internal buffer base address
* @size: size internal buffer size
*/
struct iwl_fw_ini_region_internal_buffer {
__le32 alloc_id;
__le32 base_addr;
__le32 size;
} __packed; /* FW_TLV_DEBUG_REGION_INTERNAL_BUFFER_API_S_VER_1 */
/**
* struct iwl_fw_ini_region_tlv - region TLV
*
* Configures parameters for region data collection
*
* @hdr: debug header
* @id: region id. Max id is &IWL_FW_INI_MAX_REGION_ID
* @type: region type. One of &enum iwl_fw_ini_region_type
* @name: region name
* @dev_addr: device address configuration. Used by
* &IWL_FW_INI_REGION_DEVICE_MEMORY, &IWL_FW_INI_REGION_PERIPHERY_MAC,
* &IWL_FW_INI_REGION_PERIPHERY_PHY, &IWL_FW_INI_REGION_PERIPHERY_AUX,
* &IWL_FW_INI_REGION_PAGING, &IWL_FW_INI_REGION_CSR,
* &IWL_FW_INI_REGION_DRAM_IMR and &IWL_FW_INI_REGION_PCI_IOSF_CONFIG
* &IWL_FW_INI_REGION_DBGI_SRAM, &FW_TLV_DEBUG_REGION_TYPE_DBGI_SRAM,
* @fifos: fifos configuration. Used by &IWL_FW_INI_REGION_TXF and
* &IWL_FW_INI_REGION_RXF
* @err_table: error table configuration. Used by
* IWL_FW_INI_REGION_LMAC_ERROR_TABLE and
* IWL_FW_INI_REGION_UMAC_ERROR_TABLE
* @internal_buffer: internal monitor buffer configuration. Used by
* &IWL_FW_INI_REGION_INTERNAL_BUFFER
* @dram_alloc_id: dram allocation id. One of &enum iwl_fw_ini_allocation_id.
* Used by &IWL_FW_INI_REGION_DRAM_BUFFER
* @tlv_mask: tlv collection mask. Used by &IWL_FW_INI_REGION_TLV
* @addrs: array of addresses attached to the end of the region tlv
*/
struct iwl_fw_ini_region_tlv {
struct iwl_fw_ini_header hdr;
__le32 id;
__le32 type;
u8 name[IWL_FW_INI_MAX_NAME];
union {
struct iwl_fw_ini_region_dev_addr dev_addr;
struct iwl_fw_ini_region_fifos fifos;
struct iwl_fw_ini_region_err_table err_table;
struct iwl_fw_ini_region_internal_buffer internal_buffer;
struct iwl_fw_ini_region_special_device_memory special_mem;
__le32 dram_alloc_id;
__le32 tlv_mask;
}; /* FW_TLV_DEBUG_REGION_CONF_PARAMS_API_U_VER_1 */
__le32 addrs[];
} __packed; /* FW_TLV_DEBUG_REGION_API_S_VER_1 */
/**
* struct iwl_fw_ini_debug_info_tlv
*
* debug configuration name for a specific image
*
* @hdr: debug header
* @image_type: image type
* @debug_cfg_name: debug configuration name
*/
struct iwl_fw_ini_debug_info_tlv {
struct iwl_fw_ini_header hdr;
__le32 image_type;
u8 debug_cfg_name[IWL_FW_INI_MAX_CFG_NAME];
} __packed; /* FW_TLV_DEBUG_INFO_API_S_VER_1 */
/**
* struct iwl_fw_ini_allocation_tlv - Allocates DRAM buffers
*
* @hdr: debug header
* @alloc_id: allocation id. One of &enum iwl_fw_ini_allocation_id
* @buf_location: buffer location. One of &enum iwl_fw_ini_buffer_location
* @req_size: requested buffer size
* @max_frags_num: maximum number of fragments
* @min_size: minimum buffer size
*/
struct iwl_fw_ini_allocation_tlv {
struct iwl_fw_ini_header hdr;
__le32 alloc_id;
__le32 buf_location;
__le32 req_size;
__le32 max_frags_num;
__le32 min_size;
} __packed; /* FW_TLV_DEBUG_BUFFER_ALLOCATION_API_S_VER_1 */
/**
* struct iwl_fw_ini_trigger_tlv - trigger TLV
*
* Trigger that upon firing, determines what regions to collect
*
* @hdr: debug header
* @time_point: time point. One of &enum iwl_fw_ini_time_point
* @trigger_reason: trigger reason
* @apply_policy: uses &enum iwl_fw_ini_trigger_apply_policy
* @dump_delay: delay from trigger fire to dump, in usec
* @occurrences: max trigger fire occurrences allowed
* @reserved: unused
* @ignore_consec: ignore consecutive triggers, in usec
* @reset_fw: if non zero, will reset and reload the FW
* @multi_dut: initiate debug dump data on several DUTs
* @regions_mask: mask of regions to collect
* @data: trigger data
*/
struct iwl_fw_ini_trigger_tlv {
struct iwl_fw_ini_header hdr;
__le32 time_point;
__le32 trigger_reason;
__le32 apply_policy;
__le32 dump_delay;
__le32 occurrences;
__le32 reserved;
__le32 ignore_consec;
__le32 reset_fw;
__le32 multi_dut;
__le64 regions_mask;
__le32 data[];
} __packed; /* FW_TLV_DEBUG_TRIGGER_API_S_VER_1 */
/**
* struct iwl_fw_ini_hcmd_tlv - Generic Host command pass through TLV
*
* @hdr: debug header
* @time_point: time point. One of &enum iwl_fw_ini_time_point
* @period_msec: interval at which the hcmd will be sent to the FW.
* Measured in msec (0 = one time command)
* @hcmd: a variable length host-command to be sent to apply the configuration
*/
struct iwl_fw_ini_hcmd_tlv {
struct iwl_fw_ini_header hdr;
__le32 time_point;
__le32 period_msec;
struct iwl_fw_ini_hcmd hcmd;
} __packed; /* FW_TLV_DEBUG_HCMD_API_S_VER_1 */
/**
* struct iwl_fw_ini_conf_tlv - preset configuration TLV
*
* @address: the base address
* @value: value to set at address
*/
struct iwl_fw_ini_addr_val {
__le32 address;
__le32 value;
} __packed; /* FW_TLV_DEBUG_ADDR_VALUE_VER_1 */
/**
* struct iwl_fw_ini_conf_tlv - configuration TLV to set register/memory.
*
* @hdr: debug header
* @time_point: time point to apply config. One of &enum iwl_fw_ini_time_point
* @set_type: write access type preset token for time point.
* one of &enum iwl_fw_ini_config_set_type
* @addr_offset: the offset to add to any item in address[0] field
* @addr_val: address value pair
*/
struct iwl_fw_ini_conf_set_tlv {
struct iwl_fw_ini_header hdr;
__le32 time_point;
__le32 set_type;
__le32 addr_offset;
struct iwl_fw_ini_addr_val addr_val[0];
} __packed; /* FW_TLV_DEBUG_CONFIG_SET_API_S_VER_1 */
/**
* enum iwl_fw_ini_config_set_type
*
* @IWL_FW_INI_CONFIG_SET_TYPE_INVALID: invalid config set
* @IWL_FW_INI_CONFIG_SET_TYPE_DEVICE_PERIPHERY_MAC: for PERIPHERY MAC configuration
* @IWL_FW_INI_CONFIG_SET_TYPE_DEVICE_PERIPHERY_PHY: for PERIPHERY PHY configuration
* @IWL_FW_INI_CONFIG_SET_TYPE_DEVICE_PERIPHERY_AUX: for PERIPHERY AUX configuration
* @IWL_FW_INI_CONFIG_SET_TYPE_DEVICE_MEMORY: for DEVICE MEMORY configuration
* @IWL_FW_INI_CONFIG_SET_TYPE_CSR: for CSR configuration
* @IWL_FW_INI_CONFIG_SET_TYPE_DBGC_DRAM_ADDR: for DBGC_DRAM_ADDR configuration
* @IWL_FW_INI_CONFIG_SET_TYPE_PERIPH_SCRATCH_HWM: for PERIPH SCRATCH HWM configuration
* @IWL_FW_INI_ALLOCATION_NUM: max number of configuration supported
*/
enum iwl_fw_ini_config_set_type {
IWL_FW_INI_CONFIG_SET_TYPE_INVALID = 0,
IWL_FW_INI_CONFIG_SET_TYPE_DEVICE_PERIPHERY_MAC,
IWL_FW_INI_CONFIG_SET_TYPE_DEVICE_PERIPHERY_PHY,
IWL_FW_INI_CONFIG_SET_TYPE_DEVICE_PERIPHERY_AUX,
IWL_FW_INI_CONFIG_SET_TYPE_DEVICE_MEMORY,
IWL_FW_INI_CONFIG_SET_TYPE_CSR,
IWL_FW_INI_CONFIG_SET_TYPE_DBGC_DRAM_ADDR,
IWL_FW_INI_CONFIG_SET_TYPE_PERIPH_SCRATCH_HWM,
IWL_FW_INI_CONFIG_SET_TYPE_MAX_NUM,
} __packed;
/**
* enum iwl_fw_ini_allocation_id
*
* @IWL_FW_INI_ALLOCATION_INVALID: invalid
* @IWL_FW_INI_ALLOCATION_ID_DBGC1: allocation meant for DBGC1 configuration
* @IWL_FW_INI_ALLOCATION_ID_DBGC2: allocation meant for DBGC2 configuration
* @IWL_FW_INI_ALLOCATION_ID_DBGC3: allocation meant for DBGC3 configuration
* @IWL_FW_INI_ALLOCATION_NUM: number of allocation ids
*/
enum iwl_fw_ini_allocation_id {
IWL_FW_INI_ALLOCATION_INVALID,
IWL_FW_INI_ALLOCATION_ID_DBGC1,
IWL_FW_INI_ALLOCATION_ID_DBGC2,
IWL_FW_INI_ALLOCATION_ID_DBGC3,
IWL_FW_INI_ALLOCATION_NUM,
}; /* FW_DEBUG_TLV_ALLOCATION_ID_E_VER_1 */
/**
* enum iwl_fw_ini_buffer_location
*
* @IWL_FW_INI_LOCATION_INVALID: invalid
* @IWL_FW_INI_LOCATION_SRAM_PATH: SRAM location
* @IWL_FW_INI_LOCATION_DRAM_PATH: DRAM location
* @IWL_FW_INI_LOCATION_NPK_PATH: NPK location
*/
enum iwl_fw_ini_buffer_location {
IWL_FW_INI_LOCATION_INVALID,
IWL_FW_INI_LOCATION_SRAM_PATH,
IWL_FW_INI_LOCATION_DRAM_PATH,
IWL_FW_INI_LOCATION_NPK_PATH,
IWL_FW_INI_LOCATION_NUM,
}; /* FW_DEBUG_TLV_BUFFER_LOCATION_E_VER_1 */
/**
* enum iwl_fw_ini_region_type
*
* @IWL_FW_INI_REGION_INVALID: invalid
* @IWL_FW_INI_REGION_TLV: uCode and debug TLVs
* @IWL_FW_INI_REGION_INTERNAL_BUFFER: monitor SMEM buffer
* @IWL_FW_INI_REGION_DRAM_BUFFER: monitor DRAM buffer
* @IWL_FW_INI_REGION_TXF: TX fifos
* @IWL_FW_INI_REGION_RXF: RX fifo
* @IWL_FW_INI_REGION_LMAC_ERROR_TABLE: lmac error table
* @IWL_FW_INI_REGION_UMAC_ERROR_TABLE: umac error table
* @IWL_FW_INI_REGION_RSP_OR_NOTIF: FW response or notification data
* @IWL_FW_INI_REGION_DEVICE_MEMORY: device internal memory
* @IWL_FW_INI_REGION_PERIPHERY_MAC: periphery registers of MAC
* @IWL_FW_INI_REGION_PERIPHERY_PHY: periphery registers of PHY
* @IWL_FW_INI_REGION_PERIPHERY_AUX: periphery registers of AUX
* @IWL_FW_INI_REGION_PAGING: paging memory
* @IWL_FW_INI_REGION_CSR: CSR registers
* @IWL_FW_INI_REGION_DRAM_IMR: IMR memory
* @IWL_FW_INI_REGION_PCI_IOSF_CONFIG: PCI/IOSF config
* @IWL_FW_INI_REGION_SPECIAL_DEVICE_MEMORY: special device memory
* @IWL_FW_INI_REGION_DBGI_SRAM: periphery registers of DBGI SRAM
* @IWL_FW_INI_REGION_NUM: number of region types
*/
enum iwl_fw_ini_region_type {
IWL_FW_INI_REGION_INVALID,
IWL_FW_INI_REGION_TLV,
IWL_FW_INI_REGION_INTERNAL_BUFFER,
IWL_FW_INI_REGION_DRAM_BUFFER,
IWL_FW_INI_REGION_TXF,
IWL_FW_INI_REGION_RXF,
IWL_FW_INI_REGION_LMAC_ERROR_TABLE,
IWL_FW_INI_REGION_UMAC_ERROR_TABLE,
IWL_FW_INI_REGION_RSP_OR_NOTIF,
IWL_FW_INI_REGION_DEVICE_MEMORY,
IWL_FW_INI_REGION_PERIPHERY_MAC,
IWL_FW_INI_REGION_PERIPHERY_PHY,
IWL_FW_INI_REGION_PERIPHERY_AUX,
IWL_FW_INI_REGION_PAGING,
IWL_FW_INI_REGION_CSR,
IWL_FW_INI_REGION_DRAM_IMR,
IWL_FW_INI_REGION_PCI_IOSF_CONFIG,
IWL_FW_INI_REGION_SPECIAL_DEVICE_MEMORY,
IWL_FW_INI_REGION_DBGI_SRAM,
IWL_FW_INI_REGION_NUM
}; /* FW_TLV_DEBUG_REGION_TYPE_API_E */
/**
* enum iwl_fw_ini_time_point
*
* Hard coded time points in which the driver can send hcmd or perform dump
* collection
*
* @IWL_FW_INI_TIME_POINT_EARLY: pre loading the FW
* @IWL_FW_INI_TIME_POINT_AFTER_ALIVE: first cmd from host after alive notif
* @IWL_FW_INI_TIME_POINT_POST_INIT: last cmd in series of init sequence
* @IWL_FW_INI_TIME_POINT_FW_ASSERT: FW assert
* @IWL_FW_INI_TIME_POINT_FW_HW_ERROR: FW HW error
* @IWL_FW_INI_TIME_POINT_FW_TFD_Q_HANG: TFD queue hang
* @IWL_FW_INI_TIME_POINT_FW_DHC_NOTIFICATION: DHC cmd response and notif
* @IWL_FW_INI_TIME_POINT_FW_RSP_OR_NOTIF: FW response or notification.
* data field holds id and group
* @IWL_FW_INI_TIME_POINT_USER_TRIGGER: user trigger time point
* @IWL_FW_INI_TIME_POINT_PERIODIC: periodic timepoint that fires in constant
* intervals. data field holds the interval time in msec
* @IWL_FW_INI_TIME_POINT_RESERVED: reserved
* @IWL_FW_INI_TIME_POINT_HOST_ASSERT: Unused
* @IWL_FW_INI_TIME_POINT_HOST_ALIVE_TIMEOUT: alive timeout
* @IWL_FW_INI_TIME_POINT_HOST_DEVICE_ENABLE: device enable
* @IWL_FW_INI_TIME_POINT_HOST_DEVICE_DISABLE: device disable
* @IWL_FW_INI_TIME_POINT_HOST_D3_START: D3 start
* @IWL_FW_INI_TIME_POINT_HOST_D3_END: D3 end
* @IWL_FW_INI_TIME_POINT_MISSED_BEACONS: missed beacons
* @IWL_FW_INI_TIME_POINT_ASSOC_FAILED: association failure
* @IWL_FW_INI_TIME_POINT_TX_FAILED: Tx frame failed
* @IWL_FW_INI_TIME_POINT_TX_WFD_ACTION_FRAME_FAILED: wifi direct action
* frame failed
* @IWL_FW_INI_TIME_POINT_TX_LATENCY_THRESHOLD: Tx latency threshold
* @IWL_FW_INI_TIME_POINT_HANG_OCCURRED: hang occurred
* @IWL_FW_INI_TIME_POINT_EAPOL_FAILED: EAPOL failed
* @IWL_FW_INI_TIME_POINT_FAKE_TX: fake Tx
* @IWL_FW_INI_TIME_POINT_DEASSOC: de association
* @IWL_FW_INI_TIME_POINT_NUM: number of time points
*/
enum iwl_fw_ini_time_point {
IWL_FW_INI_TIME_POINT_INVALID,
IWL_FW_INI_TIME_POINT_EARLY,
IWL_FW_INI_TIME_POINT_AFTER_ALIVE,
IWL_FW_INI_TIME_POINT_POST_INIT,
IWL_FW_INI_TIME_POINT_FW_ASSERT,
IWL_FW_INI_TIME_POINT_FW_HW_ERROR,
IWL_FW_INI_TIME_POINT_FW_TFD_Q_HANG,
IWL_FW_INI_TIME_POINT_FW_DHC_NOTIFICATION,
IWL_FW_INI_TIME_POINT_FW_RSP_OR_NOTIF,
IWL_FW_INI_TIME_POINT_USER_TRIGGER,
IWL_FW_INI_TIME_POINT_PERIODIC,
IWL_FW_INI_TIME_POINT_RESERVED,
IWL_FW_INI_TIME_POINT_HOST_ASSERT,
IWL_FW_INI_TIME_POINT_HOST_ALIVE_TIMEOUT,
IWL_FW_INI_TIME_POINT_HOST_DEVICE_ENABLE,
IWL_FW_INI_TIME_POINT_HOST_DEVICE_DISABLE,
IWL_FW_INI_TIME_POINT_HOST_D3_START,
IWL_FW_INI_TIME_POINT_HOST_D3_END,
IWL_FW_INI_TIME_POINT_MISSED_BEACONS,
IWL_FW_INI_TIME_POINT_ASSOC_FAILED,
IWL_FW_INI_TIME_POINT_TX_FAILED,
IWL_FW_INI_TIME_POINT_TX_WFD_ACTION_FRAME_FAILED,
IWL_FW_INI_TIME_POINT_TX_LATENCY_THRESHOLD,
IWL_FW_INI_TIME_POINT_HANG_OCCURRED,
IWL_FW_INI_TIME_POINT_EAPOL_FAILED,
IWL_FW_INI_TIME_POINT_FAKE_TX,
IWL_FW_INI_TIME_POINT_DEASSOC,
IWL_FW_INI_TIME_POINT_NUM,
}; /* FW_TLV_DEBUG_TIME_POINT_API_E */
/**
* enum iwl_fw_ini_trigger_apply_policy - Determines how to apply triggers
*
* @IWL_FW_INI_APPLY_POLICY_MATCH_TIME_POINT: match by time point
* @IWL_FW_INI_APPLY_POLICY_MATCH_DATA: match by trigger data
* @IWL_FW_INI_APPLY_POLICY_OVERRIDE_REGIONS: override regions mask.
* Append otherwise
* @IWL_FW_INI_APPLY_POLICY_OVERRIDE_CFG: override trigger configuration
* @IWL_FW_INI_APPLY_POLICY_OVERRIDE_DATA: override trigger data.
* Append otherwise
*/
enum iwl_fw_ini_trigger_apply_policy {
IWL_FW_INI_APPLY_POLICY_MATCH_TIME_POINT = BIT(0),
IWL_FW_INI_APPLY_POLICY_MATCH_DATA = BIT(1),
IWL_FW_INI_APPLY_POLICY_OVERRIDE_REGIONS = BIT(8),
IWL_FW_INI_APPLY_POLICY_OVERRIDE_CFG = BIT(9),
IWL_FW_INI_APPLY_POLICY_OVERRIDE_DATA = BIT(10),
};
#endif

View File

@ -0,0 +1,407 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2005-2014, 2018-2020 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
#ifndef __iwl_fw_api_debug_h__
#define __iwl_fw_api_debug_h__
/**
* enum iwl_debug_cmds - debug commands
*/
enum iwl_debug_cmds {
/**
* @LMAC_RD_WR:
* LMAC memory read/write, using &struct iwl_dbg_mem_access_cmd and
* &struct iwl_dbg_mem_access_rsp
*/
LMAC_RD_WR = 0x0,
/**
* @UMAC_RD_WR:
* UMAC memory read/write, using &struct iwl_dbg_mem_access_cmd and
* &struct iwl_dbg_mem_access_rsp
*/
UMAC_RD_WR = 0x1,
/**
* @HOST_EVENT_CFG:
* updates the enabled event severities
* &struct iwl_dbg_host_event_cfg_cmd
*/
HOST_EVENT_CFG = 0x3,
/**
* @DBGC_SUSPEND_RESUME:
* DBGC suspend/resume commad. Uses a single dword as data:
* 0 - resume DBGC recording
* 1 - suspend DBGC recording
*/
DBGC_SUSPEND_RESUME = 0x7,
/**
* @BUFFER_ALLOCATION:
* passes DRAM buffers to a DBGC
* &struct iwl_buf_alloc_cmd
*/
BUFFER_ALLOCATION = 0x8,
/**
* @MFU_ASSERT_DUMP_NTF:
* &struct iwl_mfu_assert_dump_notif
*/
MFU_ASSERT_DUMP_NTF = 0xFE,
};
/* Error response/notification */
enum {
FW_ERR_UNKNOWN_CMD = 0x0,
FW_ERR_INVALID_CMD_PARAM = 0x1,
FW_ERR_SERVICE = 0x2,
FW_ERR_ARC_MEMORY = 0x3,
FW_ERR_ARC_CODE = 0x4,
FW_ERR_WATCH_DOG = 0x5,
FW_ERR_WEP_GRP_KEY_INDX = 0x10,
FW_ERR_WEP_KEY_SIZE = 0x11,
FW_ERR_OBSOLETE_FUNC = 0x12,
FW_ERR_UNEXPECTED = 0xFE,
FW_ERR_FATAL = 0xFF
};
/** enum iwl_dbg_suspend_resume_cmds - dbgc suspend resume operations
* dbgc suspend resume command operations
* @DBGC_RESUME_CMD: resume dbgc recording
* @DBGC_SUSPEND_CMD: stop dbgc recording
*/
enum iwl_dbg_suspend_resume_cmds {
DBGC_RESUME_CMD,
DBGC_SUSPEND_CMD,
};
/**
* struct iwl_error_resp - FW error indication
* ( REPLY_ERROR = 0x2 )
* @error_type: one of FW_ERR_*
* @cmd_id: the command ID for which the error occurred
* @reserved1: reserved
* @bad_cmd_seq_num: sequence number of the erroneous command
* @error_service: which service created the error, applicable only if
* error_type = 2, otherwise 0
* @timestamp: TSF in usecs.
*/
struct iwl_error_resp {
__le32 error_type;
u8 cmd_id;
u8 reserved1;
__le16 bad_cmd_seq_num;
__le32 error_service;
__le64 timestamp;
} __packed;
#define TX_FIFO_MAX_NUM_9000 8
#define TX_FIFO_MAX_NUM 15
#define RX_FIFO_MAX_NUM 2
#define TX_FIFO_INTERNAL_MAX_NUM 6
/**
* struct iwl_shared_mem_cfg_v2 - Shared memory configuration information
*
* @shared_mem_addr: shared memory addr (pre 8000 HW set to 0x0 as MARBH is not
* accessible)
* @shared_mem_size: shared memory size
* @sample_buff_addr: internal sample (mon/adc) buff addr (pre 8000 HW set to
* 0x0 as accessible only via DBGM RDAT)
* @sample_buff_size: internal sample buff size
* @txfifo_addr: start addr of TXF0 (excluding the context table 0.5KB), (pre
* 8000 HW set to 0x0 as not accessible)
* @txfifo_size: size of TXF0 ... TXF7
* @rxfifo_size: RXF1, RXF2 sizes. If there is no RXF2, it'll have a value of 0
* @page_buff_addr: used by UMAC and performance debug (page miss analysis),
* when paging is not supported this should be 0
* @page_buff_size: size of %page_buff_addr
* @rxfifo_addr: Start address of rxFifo
* @internal_txfifo_addr: start address of internalFifo
* @internal_txfifo_size: internal fifos' size
*
* NOTE: on firmware that don't have IWL_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG
* set, the last 3 members don't exist.
*/
struct iwl_shared_mem_cfg_v2 {
__le32 shared_mem_addr;
__le32 shared_mem_size;
__le32 sample_buff_addr;
__le32 sample_buff_size;
__le32 txfifo_addr;
__le32 txfifo_size[TX_FIFO_MAX_NUM_9000];
__le32 rxfifo_size[RX_FIFO_MAX_NUM];
__le32 page_buff_addr;
__le32 page_buff_size;
__le32 rxfifo_addr;
__le32 internal_txfifo_addr;
__le32 internal_txfifo_size[TX_FIFO_INTERNAL_MAX_NUM];
} __packed; /* SHARED_MEM_ALLOC_API_S_VER_2 */
/**
* struct iwl_shared_mem_lmac_cfg - LMAC shared memory configuration
*
* @txfifo_addr: start addr of TXF0 (excluding the context table 0.5KB)
* @txfifo_size: size of TX FIFOs
* @rxfifo1_addr: RXF1 addr
* @rxfifo1_size: RXF1 size
*/
struct iwl_shared_mem_lmac_cfg {
__le32 txfifo_addr;
__le32 txfifo_size[TX_FIFO_MAX_NUM];
__le32 rxfifo1_addr;
__le32 rxfifo1_size;
} __packed; /* SHARED_MEM_ALLOC_LMAC_API_S_VER_1 */
/**
* struct iwl_shared_mem_cfg - Shared memory configuration information
*
* @shared_mem_addr: shared memory address
* @shared_mem_size: shared memory size
* @sample_buff_addr: internal sample (mon/adc) buff addr
* @sample_buff_size: internal sample buff size
* @rxfifo2_addr: start addr of RXF2
* @rxfifo2_size: size of RXF2
* @page_buff_addr: used by UMAC and performance debug (page miss analysis),
* when paging is not supported this should be 0
* @page_buff_size: size of %page_buff_addr
* @lmac_num: number of LMACs (1 or 2)
* @lmac_smem: per - LMAC smem data
* @rxfifo2_control_addr: start addr of RXF2C
* @rxfifo2_control_size: size of RXF2C
*/
struct iwl_shared_mem_cfg {
__le32 shared_mem_addr;
__le32 shared_mem_size;
__le32 sample_buff_addr;
__le32 sample_buff_size;
__le32 rxfifo2_addr;
__le32 rxfifo2_size;
__le32 page_buff_addr;
__le32 page_buff_size;
__le32 lmac_num;
struct iwl_shared_mem_lmac_cfg lmac_smem[3];
__le32 rxfifo2_control_addr;
__le32 rxfifo2_control_size;
} __packed; /* SHARED_MEM_ALLOC_API_S_VER_4 */
/**
* struct iwl_mfuart_load_notif_v1 - mfuart image version & status
* ( MFUART_LOAD_NOTIFICATION = 0xb1 )
* @installed_ver: installed image version
* @external_ver: external image version
* @status: MFUART loading status
* @duration: MFUART loading time
*/
struct iwl_mfuart_load_notif_v1 {
__le32 installed_ver;
__le32 external_ver;
__le32 status;
__le32 duration;
} __packed; /* MFU_LOADER_NTFY_API_S_VER_1 */
/**
* struct iwl_mfuart_load_notif - mfuart image version & status
* ( MFUART_LOAD_NOTIFICATION = 0xb1 )
* @installed_ver: installed image version
* @external_ver: external image version
* @status: MFUART loading status
* @duration: MFUART loading time
* @image_size: MFUART image size in bytes
*/
struct iwl_mfuart_load_notif {
__le32 installed_ver;
__le32 external_ver;
__le32 status;
__le32 duration;
/* image size valid only in v2 of the command */
__le32 image_size;
} __packed; /* MFU_LOADER_NTFY_API_S_VER_2 */
/**
* struct iwl_mfu_assert_dump_notif - mfuart dump logs
* ( MFU_ASSERT_DUMP_NTF = 0xfe )
* @assert_id: mfuart assert id that cause the notif
* @curr_reset_num: number of asserts since uptime
* @index_num: current chunk id
* @parts_num: total number of chunks
* @data_size: number of data bytes sent
* @data: data buffer
*/
struct iwl_mfu_assert_dump_notif {
__le32 assert_id;
__le32 curr_reset_num;
__le16 index_num;
__le16 parts_num;
__le32 data_size;
__le32 data[0];
} __packed; /* MFU_DUMP_ASSERT_API_S_VER_1 */
/**
* enum iwl_mvm_marker_id - marker ids
*
* The ids for different type of markers to insert into the usniffer logs
*
* @MARKER_ID_TX_FRAME_LATENCY: TX latency marker
* @MARKER_ID_SYNC_CLOCK: sync FW time and systime
*/
enum iwl_mvm_marker_id {
MARKER_ID_TX_FRAME_LATENCY = 1,
MARKER_ID_SYNC_CLOCK = 2,
}; /* MARKER_ID_API_E_VER_2 */
/**
* struct iwl_mvm_marker - mark info into the usniffer logs
*
* (MARKER_CMD = 0xcb)
*
* Mark the UTC time stamp into the usniffer logs together with additional
* metadata, so the usniffer output can be parsed.
* In the command response the ucode will return the GP2 time.
*
* @dw_len: The amount of dwords following this byte including this byte.
* @marker_id: A unique marker id (iwl_mvm_marker_id).
* @reserved: reserved.
* @timestamp: in milliseconds since 1970-01-01 00:00:00 UTC
* @metadata: additional meta data that will be written to the unsiffer log
*/
struct iwl_mvm_marker {
u8 dw_len;
u8 marker_id;
__le16 reserved;
__le64 timestamp;
__le32 metadata[0];
} __packed; /* MARKER_API_S_VER_1 */
/**
* struct iwl_mvm_marker_rsp - Response to marker cmd
*
* @gp2: The gp2 clock value in the FW
*/
struct iwl_mvm_marker_rsp {
__le32 gp2;
} __packed;
/* Operation types for the debug mem access */
enum {
DEBUG_MEM_OP_READ = 0,
DEBUG_MEM_OP_WRITE = 1,
DEBUG_MEM_OP_WRITE_BYTES = 2,
};
#define DEBUG_MEM_MAX_SIZE_DWORDS 32
/**
* struct iwl_dbg_mem_access_cmd - Request the device to read/write memory
* @op: DEBUG_MEM_OP_*
* @addr: address to read/write from/to
* @len: in dwords, to read/write
* @data: for write opeations, contains the source buffer
*/
struct iwl_dbg_mem_access_cmd {
__le32 op;
__le32 addr;
__le32 len;
__le32 data[];
} __packed; /* DEBUG_(U|L)MAC_RD_WR_CMD_API_S_VER_1 */
/* Status responses for the debug mem access */
enum {
DEBUG_MEM_STATUS_SUCCESS = 0x0,
DEBUG_MEM_STATUS_FAILED = 0x1,
DEBUG_MEM_STATUS_LOCKED = 0x2,
DEBUG_MEM_STATUS_HIDDEN = 0x3,
DEBUG_MEM_STATUS_LENGTH = 0x4,
};
/**
* struct iwl_dbg_mem_access_rsp - Response to debug mem commands
* @status: DEBUG_MEM_STATUS_*
* @len: read dwords (0 for write operations)
* @data: contains the read DWs
*/
struct iwl_dbg_mem_access_rsp {
__le32 status;
__le32 len;
__le32 data[];
} __packed; /* DEBUG_(U|L)MAC_RD_WR_RSP_API_S_VER_1 */
/**
* struct iwl_dbg_suspend_resume_cmd - dbgc suspend resume command
* @operation: suspend or resume operation, uses
* &enum iwl_dbg_suspend_resume_cmds
*/
struct iwl_dbg_suspend_resume_cmd {
__le32 operation;
} __packed;
#define BUF_ALLOC_MAX_NUM_FRAGS 16
/**
* struct iwl_buf_alloc_frag - a DBGC fragment
* @addr: base address of the fragment
* @size: size of the fragment
*/
struct iwl_buf_alloc_frag {
__le64 addr;
__le32 size;
} __packed; /* FRAGMENT_STRUCTURE_API_S_VER_1 */
/**
* struct iwl_buf_alloc_cmd - buffer allocation command
* @alloc_id: &enum iwl_fw_ini_allocation_id
* @buf_location: &enum iwl_fw_ini_buffer_location
* @num_frags: number of fragments
* @frags: fragments array
*/
struct iwl_buf_alloc_cmd {
__le32 alloc_id;
__le32 buf_location;
__le32 num_frags;
struct iwl_buf_alloc_frag frags[BUF_ALLOC_MAX_NUM_FRAGS];
} __packed; /* BUFFER_ALLOCATION_CMD_API_S_VER_2 */
#define DRAM_INFO_FIRST_MAGIC_WORD 0x76543210
#define DRAM_INFO_SECOND_MAGIC_WORD 0x89ABCDEF
/**
* struct iwL_dram_info - DRAM fragments allocation struct
*
* Driver will fill in the first 1K(+) of the pointed DRAM fragment
*
* @first_word: magic word value
* @second_word: magic word value
* @framfrags: DRAM fragmentaion detail
*/
struct iwl_dram_info {
__le32 first_word;
__le32 second_word;
struct iwl_buf_alloc_cmd dram_frags[IWL_FW_INI_ALLOCATION_NUM - 1];
} __packed; /* INIT_DRAM_FRAGS_ALLOCATIONS_S_VER_1 */
/**
* struct iwl_dbgc1_info - DBGC1 address and size
*
* Driver will fill the dbcg1 address and size at address based on config TLV.
*
* @first_word: all 0 set as identifier
* @dbgc1_add_lsb: LSB bits of DBGC1 physical address
* @dbgc1_add_msb: MSB bits of DBGC1 physical address
* @dbgc1_size: DBGC1 size
*/
struct iwl_dbgc1_info {
__le32 first_word;
__le32 dbgc1_add_lsb;
__le32 dbgc1_add_msb;
__le32 dbgc1_size;
} __packed; /* INIT_DRAM_FRAGS_ALLOCATIONS_S_VER_1 */
/**
* struct iwl_dbg_host_event_cfg_cmd
* @enabled_severities: enabled severities
*/
struct iwl_dbg_host_event_cfg_cmd {
__le32 enabled_severities;
} __packed; /* DEBUG_HOST_EVENT_CFG_CMD_API_S_VER_1 */
#endif /* __iwl_fw_api_debug_h__ */

View File

@ -0,0 +1,127 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2012-2014 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
#ifndef __iwl_fw_api_filter_h__
#define __iwl_fw_api_filter_h__
#include "fw/api/mac.h"
#define MAX_PORT_ID_NUM 2
#define MAX_MCAST_FILTERING_ADDRESSES 256
/**
* struct iwl_mcast_filter_cmd - configure multicast filter.
* @filter_own: Set 1 to filter out multicast packets sent by station itself
* @port_id: Multicast MAC addresses array specifier. This is a strange way
* to identify network interface adopted in host-device IF.
* It is used by FW as index in array of addresses. This array has
* MAX_PORT_ID_NUM members.
* @count: Number of MAC addresses in the array
* @pass_all: Set 1 to pass all multicast packets.
* @bssid: current association BSSID.
* @reserved: reserved
* @addr_list: Place holder for array of MAC addresses.
* IMPORTANT: add padding if necessary to ensure DWORD alignment.
*/
struct iwl_mcast_filter_cmd {
u8 filter_own;
u8 port_id;
u8 count;
u8 pass_all;
u8 bssid[6];
u8 reserved[2];
u8 addr_list[0];
} __packed; /* MCAST_FILTERING_CMD_API_S_VER_1 */
#define MAX_BCAST_FILTERS 8
#define MAX_BCAST_FILTER_ATTRS 2
/**
* enum iwl_mvm_bcast_filter_attr_offset - written by fw for each Rx packet
* @BCAST_FILTER_OFFSET_PAYLOAD_START: offset is from payload start.
* @BCAST_FILTER_OFFSET_IP_END: offset is from ip header end (i.e.
* start of ip payload).
*/
enum iwl_mvm_bcast_filter_attr_offset {
BCAST_FILTER_OFFSET_PAYLOAD_START = 0,
BCAST_FILTER_OFFSET_IP_END = 1,
};
/**
* struct iwl_fw_bcast_filter_attr - broadcast filter attribute
* @offset_type: &enum iwl_mvm_bcast_filter_attr_offset.
* @offset: starting offset of this pattern.
* @reserved1: reserved
* @val: value to match - big endian (MSB is the first
* byte to match from offset pos).
* @mask: mask to match (big endian).
*/
struct iwl_fw_bcast_filter_attr {
u8 offset_type;
u8 offset;
__le16 reserved1;
__be32 val;
__be32 mask;
} __packed; /* BCAST_FILTER_ATT_S_VER_1 */
/**
* enum iwl_mvm_bcast_filter_frame_type - filter frame type
* @BCAST_FILTER_FRAME_TYPE_ALL: consider all frames.
* @BCAST_FILTER_FRAME_TYPE_IPV4: consider only ipv4 frames
*/
enum iwl_mvm_bcast_filter_frame_type {
BCAST_FILTER_FRAME_TYPE_ALL = 0,
BCAST_FILTER_FRAME_TYPE_IPV4 = 1,
};
/**
* struct iwl_fw_bcast_filter - broadcast filter
* @discard: discard frame (1) or let it pass (0).
* @frame_type: &enum iwl_mvm_bcast_filter_frame_type.
* @reserved1: reserved
* @num_attrs: number of valid attributes in this filter.
* @attrs: attributes of this filter. a filter is considered matched
* only when all its attributes are matched (i.e. AND relationship)
*/
struct iwl_fw_bcast_filter {
u8 discard;
u8 frame_type;
u8 num_attrs;
u8 reserved1;
struct iwl_fw_bcast_filter_attr attrs[MAX_BCAST_FILTER_ATTRS];
} __packed; /* BCAST_FILTER_S_VER_1 */
/**
* struct iwl_fw_bcast_mac - per-mac broadcast filtering configuration.
* @default_discard: default action for this mac (discard (1) / pass (0)).
* @reserved1: reserved
* @attached_filters: bitmap of relevant filters for this mac.
*/
struct iwl_fw_bcast_mac {
u8 default_discard;
u8 reserved1;
__le16 attached_filters;
} __packed; /* BCAST_MAC_CONTEXT_S_VER_1 */
/**
* struct iwl_bcast_filter_cmd - broadcast filtering configuration
* @disable: enable (0) / disable (1)
* @max_bcast_filters: max number of filters (MAX_BCAST_FILTERS)
* @max_macs: max number of macs (NUM_MAC_INDEX_DRIVER)
* @reserved1: reserved
* @filters: broadcast filters
* @macs: broadcast filtering configuration per-mac
*/
struct iwl_bcast_filter_cmd {
u8 disable;
u8 max_bcast_filters;
u8 max_macs;
u8 reserved1;
struct iwl_fw_bcast_filter filters[MAX_BCAST_FILTERS];
struct iwl_fw_bcast_mac macs[NUM_MAC_INDEX_DRIVER];
} __packed; /* BCAST_FILTERING_HCMD_API_S_VER_1 */
#endif /* __iwl_fw_api_filter_h__ */

View File

@ -0,0 +1,17 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2017 Intel Deutschland GmbH
*/
#ifndef __iwl_fw_api_led_h__
#define __iwl_fw_api_led_h__
/**
* struct iwl_led_cmd - LED switching command
*
* @status: LED status (on/off)
*/
struct iwl_led_cmd {
__le32 status;
} __packed; /* LEDS_CMD_API_S_VER_2 */
#endif /* __iwl_fw_api_led_h__ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,151 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2012-2014, 2018-2019, 2021 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
#ifndef __iwl_fw_api_mac_cfg_h__
#define __iwl_fw_api_mac_cfg_h__
/**
* enum iwl_mac_conf_subcmd_ids - mac configuration command IDs
*/
enum iwl_mac_conf_subcmd_ids {
/**
* @LOW_LATENCY_CMD: &struct iwl_mac_low_latency_cmd
*/
LOW_LATENCY_CMD = 0x3,
/**
* @CHANNEL_SWITCH_TIME_EVENT_CMD: &struct iwl_chan_switch_te_cmd
*/
CHANNEL_SWITCH_TIME_EVENT_CMD = 0x4,
/**
* @MISSED_VAP_NOTIF: &struct iwl_missed_vap_notif
*/
MISSED_VAP_NOTIF = 0xFA,
/**
* @SESSION_PROTECTION_CMD: &struct iwl_mvm_session_prot_cmd
*/
SESSION_PROTECTION_CMD = 0x5,
/**
* @SESSION_PROTECTION_NOTIF: &struct iwl_mvm_session_prot_notif
*/
SESSION_PROTECTION_NOTIF = 0xFB,
/**
* @PROBE_RESPONSE_DATA_NOTIF: &struct iwl_probe_resp_data_notif
*/
PROBE_RESPONSE_DATA_NOTIF = 0xFC,
/**
* @CHANNEL_SWITCH_START_NOTIF: &struct iwl_channel_switch_start_notif
*/
CHANNEL_SWITCH_START_NOTIF = 0xFF,
};
#define IWL_P2P_NOA_DESC_COUNT (2)
/**
* struct iwl_p2p_noa_attr - NOA attr contained in probe resp FW notification
*
* @id: attribute id
* @len_low: length low half
* @len_high: length high half
* @idx: instance of NoA timing
* @ctwin: GO's ct window and pwer save capability
* @desc: NoA descriptor
* @reserved: reserved for alignment purposes
*/
struct iwl_p2p_noa_attr {
u8 id;
u8 len_low;
u8 len_high;
u8 idx;
u8 ctwin;
struct ieee80211_p2p_noa_desc desc[IWL_P2P_NOA_DESC_COUNT];
u8 reserved;
} __packed;
#define IWL_PROBE_RESP_DATA_NO_CSA (0xff)
/**
* struct iwl_probe_resp_data_notif - notification with NOA and CSA counter
*
* @mac_id: the mac which should send the probe response
* @noa_active: notifies if the noa attribute should be handled
* @noa_attr: P2P NOA attribute
* @csa_counter: current csa counter
* @reserved: reserved for alignment purposes
*/
struct iwl_probe_resp_data_notif {
__le32 mac_id;
__le32 noa_active;
struct iwl_p2p_noa_attr noa_attr;
u8 csa_counter;
u8 reserved[3];
} __packed; /* PROBE_RESPONSE_DATA_NTFY_API_S_VER_1 */
/**
* struct iwl_missed_vap_notif - notification of missing vap detection
*
* @mac_id: the mac for which the ucode sends the notification for
* @num_beacon_intervals_elapsed: beacons elpased with no vap profile inside
* @profile_periodicity: beacons period to have our profile inside
* @reserved: reserved for alignment purposes
*/
struct iwl_missed_vap_notif {
__le32 mac_id;
u8 num_beacon_intervals_elapsed;
u8 profile_periodicity;
u8 reserved[2];
} __packed; /* MISSED_VAP_NTFY_API_S_VER_1 */
/**
* struct iwl_channel_switch_start_notif - Channel switch start notification
*
* @id_and_color: ID and color of the MAC
*/
struct iwl_channel_switch_start_notif {
__le32 id_and_color;
} __packed; /* CHANNEL_SWITCH_START_NTFY_API_S_VER_1 */
/**
* struct iwl_chan_switch_te_cmd - Channel Switch Time Event command
*
* @mac_id: MAC ID for channel switch
* @action: action to perform, one of FW_CTXT_ACTION_*
* @tsf: beacon tsf
* @cs_count: channel switch count from CSA/eCSA IE
* @cs_delayed_bcn_count: if set to N (!= 0) GO/AP can delay N beacon intervals
* at the new channel after the channel switch, otherwise (N == 0) expect
* beacon right after the channel switch.
* @cs_mode: 1 - quiet, 0 - otherwise
* @reserved: reserved for alignment purposes
*/
struct iwl_chan_switch_te_cmd {
__le32 mac_id;
__le32 action;
__le32 tsf;
u8 cs_count;
u8 cs_delayed_bcn_count;
u8 cs_mode;
u8 reserved;
} __packed; /* MAC_CHANNEL_SWITCH_TIME_EVENT_S_VER_2 */
/**
* struct iwl_mac_low_latency_cmd - set/clear mac to 'low-latency mode'
*
* @mac_id: MAC ID to whom to apply the low-latency configurations
* @low_latency_rx: 1/0 to set/clear Rx low latency direction
* @low_latency_tx: 1/0 to set/clear Tx low latency direction
* @reserved: reserved for alignment purposes
*/
struct iwl_mac_low_latency_cmd {
__le32 mac_id;
u8 low_latency_rx;
u8 low_latency_tx;
__le16 reserved;
} __packed; /* MAC_LOW_LATENCY_API_S_VER_1 */
#endif /* __iwl_fw_api_mac_cfg_h__ */

View File

@ -0,0 +1,659 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2012-2014, 2018-2021 Intel Corporation
* Copyright (C) 2017 Intel Deutschland GmbH
*/
#ifndef __iwl_fw_api_mac_h__
#define __iwl_fw_api_mac_h__
/*
* The first MAC indices (starting from 0) are available to the driver,
* AUX indices follows - 1 for non-CDB, 2 for CDB.
*/
#define MAC_INDEX_AUX 4
#define MAC_INDEX_MIN_DRIVER 0
#define NUM_MAC_INDEX_DRIVER MAC_INDEX_AUX
#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
enum iwl_ac {
AC_BK,
AC_BE,
AC_VI,
AC_VO,
AC_NUM,
};
/**
* enum iwl_mac_protection_flags - MAC context flags
* @MAC_PROT_FLG_TGG_PROTECT: 11g protection when transmitting OFDM frames,
* this will require CCK RTS/CTS2self.
* RTS/CTS will protect full burst time.
* @MAC_PROT_FLG_HT_PROT: enable HT protection
* @MAC_PROT_FLG_FAT_PROT: protect 40 MHz transmissions
* @MAC_PROT_FLG_SELF_CTS_EN: allow CTS2self
*/
enum iwl_mac_protection_flags {
MAC_PROT_FLG_TGG_PROTECT = BIT(3),
MAC_PROT_FLG_HT_PROT = BIT(23),
MAC_PROT_FLG_FAT_PROT = BIT(24),
MAC_PROT_FLG_SELF_CTS_EN = BIT(30),
};
#define MAC_FLG_SHORT_SLOT BIT(4)
#define MAC_FLG_SHORT_PREAMBLE BIT(5)
/**
* enum iwl_mac_types - Supported MAC types
* @FW_MAC_TYPE_FIRST: lowest supported MAC type
* @FW_MAC_TYPE_AUX: Auxiliary MAC (internal)
* @FW_MAC_TYPE_LISTENER: monitor MAC type (?)
* @FW_MAC_TYPE_PIBSS: Pseudo-IBSS
* @FW_MAC_TYPE_IBSS: IBSS
* @FW_MAC_TYPE_BSS_STA: BSS (managed) station
* @FW_MAC_TYPE_P2P_DEVICE: P2P Device
* @FW_MAC_TYPE_P2P_STA: P2P client
* @FW_MAC_TYPE_GO: P2P GO
* @FW_MAC_TYPE_TEST: ?
* @FW_MAC_TYPE_MAX: highest support MAC type
*/
enum iwl_mac_types {
FW_MAC_TYPE_FIRST = 1,
FW_MAC_TYPE_AUX = FW_MAC_TYPE_FIRST,
FW_MAC_TYPE_LISTENER,
FW_MAC_TYPE_PIBSS,
FW_MAC_TYPE_IBSS,
FW_MAC_TYPE_BSS_STA,
FW_MAC_TYPE_P2P_DEVICE,
FW_MAC_TYPE_P2P_STA,
FW_MAC_TYPE_GO,
FW_MAC_TYPE_TEST,
FW_MAC_TYPE_MAX = FW_MAC_TYPE_TEST
}; /* MAC_CONTEXT_TYPE_API_E_VER_1 */
/**
* enum iwl_tsf_id - TSF hw timer ID
* @TSF_ID_A: use TSF A
* @TSF_ID_B: use TSF B
* @TSF_ID_C: use TSF C
* @TSF_ID_D: use TSF D
* @NUM_TSF_IDS: number of TSF timers available
*/
enum iwl_tsf_id {
TSF_ID_A = 0,
TSF_ID_B = 1,
TSF_ID_C = 2,
TSF_ID_D = 3,
NUM_TSF_IDS = 4,
}; /* TSF_ID_API_E_VER_1 */
/**
* struct iwl_mac_data_ap - configuration data for AP MAC context
* @beacon_time: beacon transmit time in system time
* @beacon_tsf: beacon transmit time in TSF
* @bi: beacon interval in TU
* @reserved1: reserved
* @dtim_interval: dtim transmit time in TU
* @reserved2: reserved
* @mcast_qid: queue ID for multicast traffic.
* NOTE: obsolete from VER2 and on
* @beacon_template: beacon template ID
*/
struct iwl_mac_data_ap {
__le32 beacon_time;
__le64 beacon_tsf;
__le32 bi;
__le32 reserved1;
__le32 dtim_interval;
__le32 reserved2;
__le32 mcast_qid;
__le32 beacon_template;
} __packed; /* AP_MAC_DATA_API_S_VER_2 */
/**
* struct iwl_mac_data_ibss - configuration data for IBSS MAC context
* @beacon_time: beacon transmit time in system time
* @beacon_tsf: beacon transmit time in TSF
* @bi: beacon interval in TU
* @reserved: reserved
* @beacon_template: beacon template ID
*/
struct iwl_mac_data_ibss {
__le32 beacon_time;
__le64 beacon_tsf;
__le32 bi;
__le32 reserved;
__le32 beacon_template;
} __packed; /* IBSS_MAC_DATA_API_S_VER_1 */
/**
* enum iwl_mac_data_policy - policy of the data path for this MAC
* @TWT_SUPPORTED: twt is supported
* @MORE_DATA_ACK_SUPPORTED: AP supports More Data Ack according to
* paragraph 9.4.1.17 in P802.11ax_D4 specification. Used for TWT
* early termination detection.
* @FLEXIBLE_TWT_SUPPORTED: AP supports flexible TWT schedule
* @PROTECTED_TWT_SUPPORTED: AP supports protected TWT frames (with 11w)
* @BROADCAST_TWT_SUPPORTED: AP and STA support broadcast TWT
* @COEX_HIGH_PRIORITY_ENABLE: high priority mode for BT coex, to be used
* during 802.1X negotiation (and allowed during 4-way-HS)
*/
enum iwl_mac_data_policy {
TWT_SUPPORTED = BIT(0),
MORE_DATA_ACK_SUPPORTED = BIT(1),
FLEXIBLE_TWT_SUPPORTED = BIT(2),
PROTECTED_TWT_SUPPORTED = BIT(3),
BROADCAST_TWT_SUPPORTED = BIT(4),
COEX_HIGH_PRIORITY_ENABLE = BIT(5),
};
/**
* struct iwl_mac_data_sta - configuration data for station MAC context
* @is_assoc: 1 for associated state, 0 otherwise
* @dtim_time: DTIM arrival time in system time
* @dtim_tsf: DTIM arrival time in TSF
* @bi: beacon interval in TU, applicable only when associated
* @reserved1: reserved
* @dtim_interval: DTIM interval in TU, applicable only when associated
* @data_policy: see &enum iwl_mac_data_policy
* @listen_interval: in beacon intervals, applicable only when associated
* @assoc_id: unique ID assigned by the AP during association
* @assoc_beacon_arrive_time: TSF of first beacon after association
*/
struct iwl_mac_data_sta {
__le32 is_assoc;
__le32 dtim_time;
__le64 dtim_tsf;
__le32 bi;
__le32 reserved1;
__le32 dtim_interval;
__le32 data_policy;
__le32 listen_interval;
__le32 assoc_id;
__le32 assoc_beacon_arrive_time;
} __packed; /* STA_MAC_DATA_API_S_VER_2 */
/**
* struct iwl_mac_data_go - configuration data for P2P GO MAC context
* @ap: iwl_mac_data_ap struct with most config data
* @ctwin: client traffic window in TU (period after TBTT when GO is present).
* 0 indicates that there is no CT window.
* @opp_ps_enabled: indicate that opportunistic PS allowed
*/
struct iwl_mac_data_go {
struct iwl_mac_data_ap ap;
__le32 ctwin;
__le32 opp_ps_enabled;
} __packed; /* GO_MAC_DATA_API_S_VER_1 */
/**
* struct iwl_mac_data_p2p_sta - configuration data for P2P client MAC context
* @sta: iwl_mac_data_sta struct with most config data
* @ctwin: client traffic window in TU (period after TBTT when GO is present).
* 0 indicates that there is no CT window.
*/
struct iwl_mac_data_p2p_sta {
struct iwl_mac_data_sta sta;
__le32 ctwin;
} __packed; /* P2P_STA_MAC_DATA_API_S_VER_2 */
/**
* struct iwl_mac_data_pibss - Pseudo IBSS config data
* @stats_interval: interval in TU between statistics notifications to host.
*/
struct iwl_mac_data_pibss {
__le32 stats_interval;
} __packed; /* PIBSS_MAC_DATA_API_S_VER_1 */
/*
* struct iwl_mac_data_p2p_dev - configuration data for the P2P Device MAC
* context.
* @is_disc_extended: if set to true, P2P Device discoverability is enabled on
* other channels as well. This should be to true only in case that the
* device is discoverable and there is an active GO. Note that setting this
* field when not needed, will increase the number of interrupts and have
* effect on the platform power, as this setting opens the Rx filters on
* all macs.
*/
struct iwl_mac_data_p2p_dev {
__le32 is_disc_extended;
} __packed; /* _P2P_DEV_MAC_DATA_API_S_VER_1 */
/**
* enum iwl_mac_filter_flags - MAC context filter flags
* @MAC_FILTER_IN_PROMISC: accept all data frames
* @MAC_FILTER_IN_CONTROL_AND_MGMT: pass all management and
* control frames to the host
* @MAC_FILTER_ACCEPT_GRP: accept multicast frames
* @MAC_FILTER_DIS_DECRYPT: don't decrypt unicast frames
* @MAC_FILTER_DIS_GRP_DECRYPT: don't decrypt multicast frames
* @MAC_FILTER_IN_BEACON: transfer foreign BSS's beacons to host
* (in station mode when associated)
* @MAC_FILTER_OUT_BCAST: filter out all broadcast frames
* @MAC_FILTER_IN_CRC32: extract FCS and append it to frames
* @MAC_FILTER_IN_PROBE_REQUEST: pass probe requests to host
*/
enum iwl_mac_filter_flags {
MAC_FILTER_IN_PROMISC = BIT(0),
MAC_FILTER_IN_CONTROL_AND_MGMT = BIT(1),
MAC_FILTER_ACCEPT_GRP = BIT(2),
MAC_FILTER_DIS_DECRYPT = BIT(3),
MAC_FILTER_DIS_GRP_DECRYPT = BIT(4),
MAC_FILTER_IN_BEACON = BIT(6),
MAC_FILTER_OUT_BCAST = BIT(8),
MAC_FILTER_IN_CRC32 = BIT(11),
MAC_FILTER_IN_PROBE_REQUEST = BIT(12),
/**
* @MAC_FILTER_IN_11AX: mark BSS as supporting 802.11ax
*/
MAC_FILTER_IN_11AX = BIT(14),
};
/**
* enum iwl_mac_qos_flags - QoS flags
* @MAC_QOS_FLG_UPDATE_EDCA: ?
* @MAC_QOS_FLG_TGN: HT is enabled
* @MAC_QOS_FLG_TXOP_TYPE: ?
*
*/
enum iwl_mac_qos_flags {
MAC_QOS_FLG_UPDATE_EDCA = BIT(0),
MAC_QOS_FLG_TGN = BIT(1),
MAC_QOS_FLG_TXOP_TYPE = BIT(4),
};
/**
* struct iwl_ac_qos - QOS timing params for MAC_CONTEXT_CMD
* @cw_min: Contention window, start value in numbers of slots.
* Should be a power-of-2, minus 1. Device's default is 0x0f.
* @cw_max: Contention window, max value in numbers of slots.
* Should be a power-of-2, minus 1. Device's default is 0x3f.
* @aifsn: Number of slots in Arbitration Interframe Space (before
* performing random backoff timing prior to Tx). Device default 1.
* @fifos_mask: FIFOs used by this MAC for this AC
* @edca_txop: Length of Tx opportunity, in uSecs. Device default is 0.
*
* One instance of this config struct for each of 4 EDCA access categories
* in struct iwl_qosparam_cmd.
*
* Device will automatically increase contention window by (2*CW) + 1 for each
* transmission retry. Device uses cw_max as a bit mask, ANDed with new CW
* value, to cap the CW value.
*/
struct iwl_ac_qos {
__le16 cw_min;
__le16 cw_max;
u8 aifsn;
u8 fifos_mask;
__le16 edca_txop;
} __packed; /* AC_QOS_API_S_VER_2 */
/**
* struct iwl_mac_ctx_cmd - command structure to configure MAC contexts
* ( MAC_CONTEXT_CMD = 0x28 )
* @id_and_color: ID and color of the MAC
* @action: action to perform, one of FW_CTXT_ACTION_*
* @mac_type: one of &enum iwl_mac_types
* @tsf_id: TSF HW timer, one of &enum iwl_tsf_id
* @node_addr: MAC address
* @reserved_for_node_addr: reserved
* @bssid_addr: BSSID
* @reserved_for_bssid_addr: reserved
* @cck_rates: basic rates available for CCK
* @ofdm_rates: basic rates available for OFDM
* @protection_flags: combination of &enum iwl_mac_protection_flags
* @cck_short_preamble: 0x20 for enabling short preamble, 0 otherwise
* @short_slot: 0x10 for enabling short slots, 0 otherwise
* @filter_flags: combination of &enum iwl_mac_filter_flags
* @qos_flags: from &enum iwl_mac_qos_flags
* @ac: one iwl_mac_qos configuration for each AC
*/
struct iwl_mac_ctx_cmd {
/* COMMON_INDEX_HDR_API_S_VER_1 */
__le32 id_and_color;
__le32 action;
/* MAC_CONTEXT_COMMON_DATA_API_S_VER_1 */
__le32 mac_type;
__le32 tsf_id;
u8 node_addr[6];
__le16 reserved_for_node_addr;
u8 bssid_addr[6];
__le16 reserved_for_bssid_addr;
__le32 cck_rates;
__le32 ofdm_rates;
__le32 protection_flags;
__le32 cck_short_preamble;
__le32 short_slot;
__le32 filter_flags;
/* MAC_QOS_PARAM_API_S_VER_1 */
__le32 qos_flags;
struct iwl_ac_qos ac[AC_NUM+1];
/* MAC_CONTEXT_COMMON_DATA_API_S */
union {
struct iwl_mac_data_ap ap;
struct iwl_mac_data_go go;
struct iwl_mac_data_sta sta;
struct iwl_mac_data_p2p_sta p2p_sta;
struct iwl_mac_data_p2p_dev p2p_dev;
struct iwl_mac_data_pibss pibss;
struct iwl_mac_data_ibss ibss;
};
} __packed; /* MAC_CONTEXT_CMD_API_S_VER_1 */
#define IWL_NONQOS_SEQ_GET 0x1
#define IWL_NONQOS_SEQ_SET 0x2
struct iwl_nonqos_seq_query_cmd {
__le32 get_set_flag;
__le32 mac_id_n_color;
__le16 value;
__le16 reserved;
} __packed; /* NON_QOS_TX_COUNTER_GET_SET_API_S_VER_1 */
/**
* struct iwl_missed_beacons_notif - information on missed beacons
* ( MISSED_BEACONS_NOTIFICATION = 0xa2 )
* @mac_id: interface ID
* @consec_missed_beacons_since_last_rx: number of consecutive missed
* beacons since last RX.
* @consec_missed_beacons: number of consecutive missed beacons
* @num_expected_beacons: number of expected beacons
* @num_recvd_beacons: number of received beacons
*/
struct iwl_missed_beacons_notif {
__le32 mac_id;
__le32 consec_missed_beacons_since_last_rx;
__le32 consec_missed_beacons;
__le32 num_expected_beacons;
__le32 num_recvd_beacons;
} __packed; /* MISSED_BEACON_NTFY_API_S_VER_3 */
/**
* struct iwl_he_backoff_conf - used for backoff configuration
* Per each trigger-based AC, (set by MU EDCA Parameter set info-element)
* used for backoff configuration of TXF5..TXF8 trigger based.
* The MU-TIMER is reloaded w/ MU_TIME each time a frame from the AC is sent via
* trigger-based TX.
* @cwmin: CW min
* @cwmax: CW max
* @aifsn: AIFSN
* AIFSN=0, means that no backoff from the specified TRIG-BASED AC is
* allowed till the MU-TIMER is 0
* @mu_time: MU time in 8TU units
*/
struct iwl_he_backoff_conf {
__le16 cwmin;
__le16 cwmax;
__le16 aifsn;
__le16 mu_time;
} __packed; /* AC_QOS_DOT11AX_API_S */
/**
* enum iwl_he_pkt_ext_constellations - PPE constellation indices
* @IWL_HE_PKT_EXT_BPSK: BPSK
* @IWL_HE_PKT_EXT_QPSK: QPSK
* @IWL_HE_PKT_EXT_16QAM: 16-QAM
* @IWL_HE_PKT_EXT_64QAM: 64-QAM
* @IWL_HE_PKT_EXT_256QAM: 256-QAM
* @IWL_HE_PKT_EXT_1024QAM: 1024-QAM
* @IWL_HE_PKT_EXT_RESERVED: reserved value
* @IWL_HE_PKT_EXT_NONE: not defined
*/
enum iwl_he_pkt_ext_constellations {
IWL_HE_PKT_EXT_BPSK = 0,
IWL_HE_PKT_EXT_QPSK,
IWL_HE_PKT_EXT_16QAM,
IWL_HE_PKT_EXT_64QAM,
IWL_HE_PKT_EXT_256QAM,
IWL_HE_PKT_EXT_1024QAM,
IWL_HE_PKT_EXT_RESERVED,
IWL_HE_PKT_EXT_NONE,
};
#define MAX_HE_SUPP_NSS 2
#define MAX_HE_CHANNEL_BW_INDX 4
/**
* struct iwl_he_pkt_ext - QAM thresholds
* The required PPE is set via HE Capabilities IE, per Nss x BW x MCS
* The IE is organized in the following way:
* Support for Nss x BW (or RU) matrix:
* (0=SISO, 1=MIMO2) x (0-20MHz, 1-40MHz, 2-80MHz, 3-160MHz)
* Each entry contains 2 QAM thresholds for 8us and 16us:
* 0=BPSK, 1=QPSK, 2=16QAM, 3=64QAM, 4=256QAM, 5=1024QAM, 6=RES, 7=NONE
* i.e. QAM_th1 < QAM_th2 such if TX uses QAM_tx:
* QAM_tx < QAM_th1 --> PPE=0us
* QAM_th1 <= QAM_tx < QAM_th2 --> PPE=8us
* QAM_th2 <= QAM_tx --> PPE=16us
* @pkt_ext_qam_th: QAM thresholds
* For each Nss/Bw define 2 QAM thrsholds (0..5)
* For rates below the low_th, no need for PPE
* For rates between low_th and high_th, need 8us PPE
* For rates equal or higher then the high_th, need 16us PPE
* Nss (0-siso, 1-mimo2) x BW (0-20MHz, 1-40MHz, 2-80MHz, 3-160MHz) x
* (0-low_th, 1-high_th)
*/
struct iwl_he_pkt_ext {
u8 pkt_ext_qam_th[MAX_HE_SUPP_NSS][MAX_HE_CHANNEL_BW_INDX][2];
} __packed; /* PKT_EXT_DOT11AX_API_S */
/**
* enum iwl_he_sta_ctxt_flags - HE STA context flags
* @STA_CTXT_HE_REF_BSSID_VALID: ref bssid addr valid (for receiving specific
* control frames such as TRIG, NDPA, BACK)
* @STA_CTXT_HE_BSS_COLOR_DIS: BSS color disable, don't use the BSS
* color for RX filter but use MAC header
* @STA_CTXT_HE_PARTIAL_BSS_COLOR: partial BSS color allocation
* @STA_CTXT_HE_32BIT_BA_BITMAP: indicates the receiver supports BA bitmap
* of 32-bits
* @STA_CTXT_HE_PACKET_EXT: indicates that the packet-extension info is valid
* and should be used
* @STA_CTXT_HE_TRIG_RND_ALLOC: indicates that trigger based random allocation
* is enabled according to UORA element existence
* @STA_CTXT_HE_CONST_TRIG_RND_ALLOC: used for AV testing
* @STA_CTXT_HE_ACK_ENABLED: indicates that the AP supports receiving ACK-
* enabled AGG, i.e. both BACK and non-BACK frames in a single AGG
* @STA_CTXT_HE_MU_EDCA_CW: indicates that there is an element of MU EDCA
* parameter set, i.e. the backoff counters for trig-based ACs
* @STA_CTXT_HE_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
* len delim to determine if AGG or single.
* @STA_CTXT_HE_RU_2MHZ_BLOCK: indicates that 26-tone RU OFDMA transmission are
* not allowed (as there are OBSS that might classify such transmissions as
* radar pulses).
*/
enum iwl_he_sta_ctxt_flags {
STA_CTXT_HE_REF_BSSID_VALID = BIT(4),
STA_CTXT_HE_BSS_COLOR_DIS = BIT(5),
STA_CTXT_HE_PARTIAL_BSS_COLOR = BIT(6),
STA_CTXT_HE_32BIT_BA_BITMAP = BIT(7),
STA_CTXT_HE_PACKET_EXT = BIT(8),
STA_CTXT_HE_TRIG_RND_ALLOC = BIT(9),
STA_CTXT_HE_CONST_TRIG_RND_ALLOC = BIT(10),
STA_CTXT_HE_ACK_ENABLED = BIT(11),
STA_CTXT_HE_MU_EDCA_CW = BIT(12),
STA_CTXT_HE_NIC_NOT_ACK_ENABLED = BIT(13),
STA_CTXT_HE_RU_2MHZ_BLOCK = BIT(14),
};
/**
* enum iwl_he_htc_flags - HE HTC support flags
* @IWL_HE_HTC_SUPPORT: HE-HTC support
* @IWL_HE_HTC_UL_MU_RESP_SCHED: HE UL MU response schedule
* support via A-control field
* @IWL_HE_HTC_BSR_SUPP: BSR support in A-control field
* @IWL_HE_HTC_OMI_SUPP: A-OMI support in A-control field
* @IWL_HE_HTC_BQR_SUPP: A-BQR support in A-control field
*/
enum iwl_he_htc_flags {
IWL_HE_HTC_SUPPORT = BIT(0),
IWL_HE_HTC_UL_MU_RESP_SCHED = BIT(3),
IWL_HE_HTC_BSR_SUPP = BIT(4),
IWL_HE_HTC_OMI_SUPP = BIT(5),
IWL_HE_HTC_BQR_SUPP = BIT(6),
};
/*
* @IWL_HE_HTC_LINK_ADAP_NO_FEEDBACK: the STA does not provide HE MFB
* @IWL_HE_HTC_LINK_ADAP_UNSOLICITED: the STA provides only unsolicited HE MFB
* @IWL_HE_HTC_LINK_ADAP_BOTH: the STA is capable of providing HE MFB in
* response to HE MRQ and if the STA provides unsolicited HE MFB
*/
#define IWL_HE_HTC_LINK_ADAP_POS (1)
#define IWL_HE_HTC_LINK_ADAP_NO_FEEDBACK (0)
#define IWL_HE_HTC_LINK_ADAP_UNSOLICITED (2 << IWL_HE_HTC_LINK_ADAP_POS)
#define IWL_HE_HTC_LINK_ADAP_BOTH (3 << IWL_HE_HTC_LINK_ADAP_POS)
/**
* struct iwl_he_sta_context_cmd_v1 - configure FW to work with HE AP
* @sta_id: STA id
* @tid_limit: max num of TIDs in TX HE-SU multi-TID agg
* 0 - bad value, 1 - multi-tid not supported, 2..8 - tid limit
* @reserved1: reserved byte for future use
* @reserved2: reserved byte for future use
* @flags: see %iwl_11ax_sta_ctxt_flags
* @ref_bssid_addr: reference BSSID used by the AP
* @reserved0: reserved 2 bytes for aligning the ref_bssid_addr field to 8 bytes
* @htc_flags: which features are supported in HTC
* @frag_flags: frag support in A-MSDU
* @frag_level: frag support level
* @frag_max_num: max num of "open" MSDUs in the receiver (in power of 2)
* @frag_min_size: min frag size (except last frag)
* @pkt_ext: optional, exists according to PPE-present bit in the HE-PHY capa
* @bss_color: 11ax AP ID that is used in the HE SIG-A to mark inter BSS frame
* @htc_trig_based_pkt_ext: default PE in 4us units
* @frame_time_rts_th: HE duration RTS threshold, in units of 32us
* @rand_alloc_ecwmin: random CWmin = 2**ECWmin-1
* @rand_alloc_ecwmax: random CWmax = 2**ECWmax-1
* @reserved3: reserved byte for future use
* @trig_based_txf: MU EDCA Parameter set for the trigger based traffic queues
*/
struct iwl_he_sta_context_cmd_v1 {
u8 sta_id;
u8 tid_limit;
u8 reserved1;
u8 reserved2;
__le32 flags;
/* The below fields are set via Multiple BSSID IE */
u8 ref_bssid_addr[6];
__le16 reserved0;
/* The below fields are set via HE-capabilities IE */
__le32 htc_flags;
u8 frag_flags;
u8 frag_level;
u8 frag_max_num;
u8 frag_min_size;
/* The below fields are set via PPE thresholds element */
struct iwl_he_pkt_ext pkt_ext;
/* The below fields are set via HE-Operation IE */
u8 bss_color;
u8 htc_trig_based_pkt_ext;
__le16 frame_time_rts_th;
/* Random access parameter set (i.e. RAPS) */
u8 rand_alloc_ecwmin;
u8 rand_alloc_ecwmax;
__le16 reserved3;
/* The below fields are set via MU EDCA parameter set element */
struct iwl_he_backoff_conf trig_based_txf[AC_NUM];
} __packed; /* STA_CONTEXT_DOT11AX_API_S_VER_1 */
/**
* struct iwl_he_sta_context_cmd - configure FW to work with HE AP
* @sta_id: STA id
* @tid_limit: max num of TIDs in TX HE-SU multi-TID agg
* 0 - bad value, 1 - multi-tid not supported, 2..8 - tid limit
* @reserved1: reserved byte for future use
* @reserved2: reserved byte for future use
* @flags: see %iwl_11ax_sta_ctxt_flags
* @ref_bssid_addr: reference BSSID used by the AP
* @reserved0: reserved 2 bytes for aligning the ref_bssid_addr field to 8 bytes
* @htc_flags: which features are supported in HTC
* @frag_flags: frag support in A-MSDU
* @frag_level: frag support level
* @frag_max_num: max num of "open" MSDUs in the receiver (in power of 2)
* @frag_min_size: min frag size (except last frag)
* @pkt_ext: optional, exists according to PPE-present bit in the HE-PHY capa
* @bss_color: 11ax AP ID that is used in the HE SIG-A to mark inter BSS frame
* @htc_trig_based_pkt_ext: default PE in 4us units
* @frame_time_rts_th: HE duration RTS threshold, in units of 32us
* @rand_alloc_ecwmin: random CWmin = 2**ECWmin-1
* @rand_alloc_ecwmax: random CWmax = 2**ECWmax-1
* @reserved3: reserved byte for future use
* @trig_based_txf: MU EDCA Parameter set for the trigger based traffic queues
* @max_bssid_indicator: indicator of the max bssid supported on the associated
* bss
* @bssid_index: index of the associated VAP
* @ema_ap: AP supports enhanced Multi BSSID advertisement
* @profile_periodicity: number of Beacon periods that are needed to receive the
* complete VAPs info
* @bssid_count: actual number of VAPs in the MultiBSS Set
* @reserved4: alignment
*/
struct iwl_he_sta_context_cmd {
u8 sta_id;
u8 tid_limit;
u8 reserved1;
u8 reserved2;
__le32 flags;
/* The below fields are set via Multiple BSSID IE */
u8 ref_bssid_addr[6];
__le16 reserved0;
/* The below fields are set via HE-capabilities IE */
__le32 htc_flags;
u8 frag_flags;
u8 frag_level;
u8 frag_max_num;
u8 frag_min_size;
/* The below fields are set via PPE thresholds element */
struct iwl_he_pkt_ext pkt_ext;
/* The below fields are set via HE-Operation IE */
u8 bss_color;
u8 htc_trig_based_pkt_ext;
__le16 frame_time_rts_th;
/* Random access parameter set (i.e. RAPS) */
u8 rand_alloc_ecwmin;
u8 rand_alloc_ecwmax;
__le16 reserved3;
/* The below fields are set via MU EDCA parameter set element */
struct iwl_he_backoff_conf trig_based_txf[AC_NUM];
u8 max_bssid_indicator;
u8 bssid_index;
u8 ema_ap;
u8 profile_periodicity;
u8 bssid_count;
u8 reserved4[3];
} __packed; /* STA_CONTEXT_DOT11AX_API_S_VER_2 */
/**
* struct iwl_he_monitor_cmd - configure air sniffer for HE
* @bssid: the BSSID to sniff for
* @reserved1: reserved for dword alignment
* @aid: the AID to track on for HE MU
* @reserved2: reserved for future use
*/
struct iwl_he_monitor_cmd {
u8 bssid[6];
__le16 reserved1;
__le16 aid;
u8 reserved2[6];
} __packed; /* HE_AIR_SNIFFER_CONFIG_CMD_API_S_VER_1 */
#endif /* __iwl_fw_api_mac_h__ */

View File

@ -0,0 +1,505 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2012-2014, 2018-2021 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
#ifndef __iwl_fw_api_nvm_reg_h__
#define __iwl_fw_api_nvm_reg_h__
/**
* enum iwl_regulatory_and_nvm_subcmd_ids - regulatory/NVM commands
*/
enum iwl_regulatory_and_nvm_subcmd_ids {
/**
* @NVM_ACCESS_COMPLETE: &struct iwl_nvm_access_complete_cmd
*/
NVM_ACCESS_COMPLETE = 0x0,
/**
* @LARI_CONFIG_CHANGE: &struct iwl_lari_config_change_cmd
*/
LARI_CONFIG_CHANGE = 0x1,
/**
* @NVM_GET_INFO:
* Command is &struct iwl_nvm_get_info,
* response is &struct iwl_nvm_get_info_rsp
*/
NVM_GET_INFO = 0x2,
/**
* @TAS_CONFIG: &struct iwl_tas_config_cmd
*/
TAS_CONFIG = 0x3,
/**
* @PNVM_INIT_COMPLETE_NTFY: &struct iwl_pnvm_init_complete_ntfy
*/
PNVM_INIT_COMPLETE_NTFY = 0xFE,
};
/**
* enum iwl_nvm_access_op - NVM access opcode
* @IWL_NVM_READ: read NVM
* @IWL_NVM_WRITE: write NVM
*/
enum iwl_nvm_access_op {
IWL_NVM_READ = 0,
IWL_NVM_WRITE = 1,
};
/**
* enum iwl_nvm_access_target - target of the NVM_ACCESS_CMD
* @NVM_ACCESS_TARGET_CACHE: access the cache
* @NVM_ACCESS_TARGET_OTP: access the OTP
* @NVM_ACCESS_TARGET_EEPROM: access the EEPROM
*/
enum iwl_nvm_access_target {
NVM_ACCESS_TARGET_CACHE = 0,
NVM_ACCESS_TARGET_OTP = 1,
NVM_ACCESS_TARGET_EEPROM = 2,
};
/**
* enum iwl_nvm_section_type - section types for NVM_ACCESS_CMD
* @NVM_SECTION_TYPE_SW: software section
* @NVM_SECTION_TYPE_REGULATORY: regulatory section
* @NVM_SECTION_TYPE_CALIBRATION: calibration section
* @NVM_SECTION_TYPE_PRODUCTION: production section
* @NVM_SECTION_TYPE_REGULATORY_SDP: regulatory section used by 3168 series
* @NVM_SECTION_TYPE_MAC_OVERRIDE: MAC override section
* @NVM_SECTION_TYPE_PHY_SKU: PHY SKU section
* @NVM_MAX_NUM_SECTIONS: number of sections
*/
enum iwl_nvm_section_type {
NVM_SECTION_TYPE_SW = 1,
NVM_SECTION_TYPE_REGULATORY = 3,
NVM_SECTION_TYPE_CALIBRATION = 4,
NVM_SECTION_TYPE_PRODUCTION = 5,
NVM_SECTION_TYPE_REGULATORY_SDP = 8,
NVM_SECTION_TYPE_MAC_OVERRIDE = 11,
NVM_SECTION_TYPE_PHY_SKU = 12,
NVM_MAX_NUM_SECTIONS = 13,
};
/**
* struct iwl_nvm_access_cmd - Request the device to send an NVM section
* @op_code: &enum iwl_nvm_access_op
* @target: &enum iwl_nvm_access_target
* @type: &enum iwl_nvm_section_type
* @offset: offset in bytes into the section
* @length: in bytes, to read/write
* @data: if write operation, the data to write. On read its empty
*/
struct iwl_nvm_access_cmd {
u8 op_code;
u8 target;
__le16 type;
__le16 offset;
__le16 length;
u8 data[];
} __packed; /* NVM_ACCESS_CMD_API_S_VER_2 */
/**
* struct iwl_nvm_access_resp_ver2 - response to NVM_ACCESS_CMD
* @offset: offset in bytes into the section
* @length: in bytes, either how much was written or read
* @type: NVM_SECTION_TYPE_*
* @status: 0 for success, fail otherwise
* @data: if read operation, the data returned. Empty on write.
*/
struct iwl_nvm_access_resp {
__le16 offset;
__le16 length;
__le16 type;
__le16 status;
u8 data[];
} __packed; /* NVM_ACCESS_CMD_RESP_API_S_VER_2 */
/*
* struct iwl_nvm_get_info - request to get NVM data
*/
struct iwl_nvm_get_info {
__le32 reserved;
} __packed; /* REGULATORY_NVM_GET_INFO_CMD_API_S_VER_1 */
/**
* enum iwl_nvm_info_general_flags - flags in NVM_GET_INFO resp
* @NVM_GENERAL_FLAGS_EMPTY_OTP: 1 if OTP is empty
*/
enum iwl_nvm_info_general_flags {
NVM_GENERAL_FLAGS_EMPTY_OTP = BIT(0),
};
/**
* struct iwl_nvm_get_info_general - general NVM data
* @flags: bit 0: 1 - empty, 0 - non-empty
* @nvm_version: nvm version
* @board_type: board type
* @n_hw_addrs: number of reserved MAC addresses
*/
struct iwl_nvm_get_info_general {
__le32 flags;
__le16 nvm_version;
u8 board_type;
u8 n_hw_addrs;
} __packed; /* REGULATORY_NVM_GET_INFO_GENERAL_S_VER_2 */
/**
* enum iwl_nvm_mac_sku_flags - flags in &iwl_nvm_get_info_sku
* @NVM_MAC_SKU_FLAGS_BAND_2_4_ENABLED: true if 2.4 band enabled
* @NVM_MAC_SKU_FLAGS_BAND_5_2_ENABLED: true if 5.2 band enabled
* @NVM_MAC_SKU_FLAGS_802_11N_ENABLED: true if 11n enabled
* @NVM_MAC_SKU_FLAGS_802_11AC_ENABLED: true if 11ac enabled
* @NVM_MAC_SKU_FLAGS_MIMO_DISABLED: true if MIMO disabled
* @NVM_MAC_SKU_FLAGS_WAPI_ENABLED: true if WAPI enabled
* @NVM_MAC_SKU_FLAGS_REG_CHECK_ENABLED: true if regulatory checker enabled
* @NVM_MAC_SKU_FLAGS_API_LOCK_ENABLED: true if API lock enabled
*/
enum iwl_nvm_mac_sku_flags {
NVM_MAC_SKU_FLAGS_BAND_2_4_ENABLED = BIT(0),
NVM_MAC_SKU_FLAGS_BAND_5_2_ENABLED = BIT(1),
NVM_MAC_SKU_FLAGS_802_11N_ENABLED = BIT(2),
NVM_MAC_SKU_FLAGS_802_11AC_ENABLED = BIT(3),
/**
* @NVM_MAC_SKU_FLAGS_802_11AX_ENABLED: true if 11ax enabled
*/
NVM_MAC_SKU_FLAGS_802_11AX_ENABLED = BIT(4),
NVM_MAC_SKU_FLAGS_MIMO_DISABLED = BIT(5),
NVM_MAC_SKU_FLAGS_WAPI_ENABLED = BIT(8),
NVM_MAC_SKU_FLAGS_REG_CHECK_ENABLED = BIT(14),
NVM_MAC_SKU_FLAGS_API_LOCK_ENABLED = BIT(15),
};
/**
* struct iwl_nvm_get_info_sku - mac information
* @mac_sku_flags: flags for SKU, see &enum iwl_nvm_mac_sku_flags
*/
struct iwl_nvm_get_info_sku {
__le32 mac_sku_flags;
} __packed; /* REGULATORY_NVM_GET_INFO_MAC_SKU_SECTION_S_VER_2 */
/**
* struct iwl_nvm_get_info_phy - phy information
* @tx_chains: BIT 0 chain A, BIT 1 chain B
* @rx_chains: BIT 0 chain A, BIT 1 chain B
*/
struct iwl_nvm_get_info_phy {
__le32 tx_chains;
__le32 rx_chains;
} __packed; /* REGULATORY_NVM_GET_INFO_PHY_SKU_SECTION_S_VER_1 */
#define IWL_NUM_CHANNELS_V1 51
#define IWL_NUM_CHANNELS 110
/**
* struct iwl_nvm_get_info_regulatory - regulatory information
* @lar_enabled: is LAR enabled
* @channel_profile: regulatory data of this channel
* @reserved: reserved
*/
struct iwl_nvm_get_info_regulatory_v1 {
__le32 lar_enabled;
__le16 channel_profile[IWL_NUM_CHANNELS_V1];
__le16 reserved;
} __packed; /* REGULATORY_NVM_GET_INFO_REGULATORY_S_VER_1 */
/**
* struct iwl_nvm_get_info_regulatory - regulatory information
* @lar_enabled: is LAR enabled
* @n_channels: number of valid channels in the array
* @channel_profile: regulatory data of this channel
*/
struct iwl_nvm_get_info_regulatory {
__le32 lar_enabled;
__le32 n_channels;
__le32 channel_profile[IWL_NUM_CHANNELS];
} __packed; /* REGULATORY_NVM_GET_INFO_REGULATORY_S_VER_2 */
/**
* struct iwl_nvm_get_info_rsp_v3 - response to get NVM data
* @general: general NVM data
* @mac_sku: data relating to MAC sku
* @phy_sku: data relating to PHY sku
* @regulatory: regulatory data
*/
struct iwl_nvm_get_info_rsp_v3 {
struct iwl_nvm_get_info_general general;
struct iwl_nvm_get_info_sku mac_sku;
struct iwl_nvm_get_info_phy phy_sku;
struct iwl_nvm_get_info_regulatory_v1 regulatory;
} __packed; /* REGULATORY_NVM_GET_INFO_RSP_API_S_VER_3 */
/**
* struct iwl_nvm_get_info_rsp - response to get NVM data
* @general: general NVM data
* @mac_sku: data relating to MAC sku
* @phy_sku: data relating to PHY sku
* @regulatory: regulatory data
*/
struct iwl_nvm_get_info_rsp {
struct iwl_nvm_get_info_general general;
struct iwl_nvm_get_info_sku mac_sku;
struct iwl_nvm_get_info_phy phy_sku;
struct iwl_nvm_get_info_regulatory regulatory;
} __packed; /* REGULATORY_NVM_GET_INFO_RSP_API_S_VER_4 */
/**
* struct iwl_nvm_access_complete_cmd - NVM_ACCESS commands are completed
* @reserved: reserved
*/
struct iwl_nvm_access_complete_cmd {
__le32 reserved;
} __packed; /* NVM_ACCESS_COMPLETE_CMD_API_S_VER_1 */
/**
* struct iwl_mcc_update_cmd - Request the device to update geographic
* regulatory profile according to the given MCC (Mobile Country Code).
* The MCC is two letter-code, ascii upper case[A-Z] or '00' for world domain.
* 'ZZ' MCC will be used to switch to NVM default profile; in this case, the
* MCC in the cmd response will be the relevant MCC in the NVM.
* @mcc: given mobile country code
* @source_id: the source from where we got the MCC, see iwl_mcc_source
* @reserved: reserved for alignment
* @key: integrity key for MCC API OEM testing
* @reserved2: reserved
*/
struct iwl_mcc_update_cmd {
__le16 mcc;
u8 source_id;
u8 reserved;
__le32 key;
u8 reserved2[20];
} __packed; /* LAR_UPDATE_MCC_CMD_API_S_VER_2 */
/**
* enum iwl_geo_information - geographic information.
* @GEO_NO_INFO: no special info for this geo profile.
* @GEO_WMM_ETSI_5GHZ_INFO: this geo profile limits the WMM params
* for the 5 GHz band.
*/
enum iwl_geo_information {
GEO_NO_INFO = 0,
GEO_WMM_ETSI_5GHZ_INFO = BIT(0),
};
/**
* struct iwl_mcc_update_resp_v3 - response to MCC_UPDATE_CMD.
* Contains the new channel control profile map, if changed, and the new MCC
* (mobile country code).
* The new MCC may be different than what was requested in MCC_UPDATE_CMD.
* @status: see &enum iwl_mcc_update_status
* @mcc: the new applied MCC
* @cap: capabilities for all channels which matches the MCC
* @source_id: the MCC source, see iwl_mcc_source
* @time: time elapsed from the MCC test start (in units of 30 seconds)
* @geo_info: geographic specific profile information
* see &enum iwl_geo_information.
* @n_channels: number of channels in @channels_data.
* @channels: channel control data map, DWORD for each channel. Only the first
* 16bits are used.
*/
struct iwl_mcc_update_resp_v3 {
__le32 status;
__le16 mcc;
u8 cap;
u8 source_id;
__le16 time;
__le16 geo_info;
__le32 n_channels;
__le32 channels[];
} __packed; /* LAR_UPDATE_MCC_CMD_RESP_S_VER_3 */
/**
* struct iwl_mcc_update_resp - response to MCC_UPDATE_CMD.
* Contains the new channel control profile map, if changed, and the new MCC
* (mobile country code).
* The new MCC may be different than what was requested in MCC_UPDATE_CMD.
* @status: see &enum iwl_mcc_update_status
* @mcc: the new applied MCC
* @cap: capabilities for all channels which matches the MCC
* @time: time elapsed from the MCC test start (in units of 30 seconds)
* @geo_info: geographic specific profile information
* see &enum iwl_geo_information.
* @source_id: the MCC source, see iwl_mcc_source
* @reserved: for four bytes alignment.
* @n_channels: number of channels in @channels_data.
* @channels: channel control data map, DWORD for each channel. Only the first
* 16bits are used.
*/
struct iwl_mcc_update_resp {
__le32 status;
__le16 mcc;
__le16 cap;
__le16 time;
__le16 geo_info;
u8 source_id;
u8 reserved[3];
__le32 n_channels;
__le32 channels[];
} __packed; /* LAR_UPDATE_MCC_CMD_RESP_S_VER_4 */
/**
* struct iwl_mcc_chub_notif - chub notifies of mcc change
* (MCC_CHUB_UPDATE_CMD = 0xc9)
* The Chub (Communication Hub, CommsHUB) is a HW component that connects to
* the cellular and connectivity cores that gets updates of the mcc, and
* notifies the ucode directly of any mcc change.
* The ucode requests the driver to request the device to update geographic
* regulatory profile according to the given MCC (Mobile Country Code).
* The MCC is two letter-code, ascii upper case[A-Z] or '00' for world domain.
* 'ZZ' MCC will be used to switch to NVM default profile; in this case, the
* MCC in the cmd response will be the relevant MCC in the NVM.
* @mcc: given mobile country code
* @source_id: identity of the change originator, see iwl_mcc_source
* @reserved1: reserved for alignment
*/
struct iwl_mcc_chub_notif {
__le16 mcc;
u8 source_id;
u8 reserved1;
} __packed; /* LAR_MCC_NOTIFY_S */
enum iwl_mcc_update_status {
MCC_RESP_NEW_CHAN_PROFILE,
MCC_RESP_SAME_CHAN_PROFILE,
MCC_RESP_INVALID,
MCC_RESP_NVM_DISABLED,
MCC_RESP_ILLEGAL,
MCC_RESP_LOW_PRIORITY,
MCC_RESP_TEST_MODE_ACTIVE,
MCC_RESP_TEST_MODE_NOT_ACTIVE,
MCC_RESP_TEST_MODE_DENIAL_OF_SERVICE,
};
enum iwl_mcc_source {
MCC_SOURCE_OLD_FW = 0,
MCC_SOURCE_ME = 1,
MCC_SOURCE_BIOS = 2,
MCC_SOURCE_3G_LTE_HOST = 3,
MCC_SOURCE_3G_LTE_DEVICE = 4,
MCC_SOURCE_WIFI = 5,
MCC_SOURCE_RESERVED = 6,
MCC_SOURCE_DEFAULT = 7,
MCC_SOURCE_UNINITIALIZED = 8,
MCC_SOURCE_MCC_API = 9,
MCC_SOURCE_GET_CURRENT = 0x10,
MCC_SOURCE_GETTING_MCC_TEST_MODE = 0x11,
};
#define IWL_TAS_BLACK_LIST_MAX 16
/**
* struct iwl_tas_config_cmd - configures the TAS
* @block_list_size: size of relevant field in block_list_array
* @block_list_array: block list countries (without TAS)
*/
struct iwl_tas_config_cmd {
__le32 block_list_size;
__le32 block_list_array[IWL_TAS_BLACK_LIST_MAX];
} __packed; /* TAS_CONFIG_CMD_API_S_VER_2 */
/**
* enum iwl_lari_configs - bit masks for the various LARI config operations
* @LARI_CONFIG_DISABLE_11AC_UKRAINE_MSK: disable 11ac in ukraine
* @LARI_CONFIG_CHANGE_ETSI_TO_PASSIVE_MSK: ETSI 5.8GHz SRD passive scan
* @LARI_CONFIG_CHANGE_ETSI_TO_DISABLED_MSK: ETSI 5.8GHz SRD disabled
* @LARI_CONFIG_ENABLE_5G2_IN_INDONESIA_MSK: enable 5.15/5.35GHz bands in
* Indonesia
*/
enum iwl_lari_config_masks {
LARI_CONFIG_DISABLE_11AC_UKRAINE_MSK = BIT(0),
LARI_CONFIG_CHANGE_ETSI_TO_PASSIVE_MSK = BIT(1),
LARI_CONFIG_CHANGE_ETSI_TO_DISABLED_MSK = BIT(2),
LARI_CONFIG_ENABLE_5G2_IN_INDONESIA_MSK = BIT(3),
};
#define IWL_11AX_UKRAINE_MASK 3
#define IWL_11AX_UKRAINE_SHIFT 8
/**
* struct iwl_lari_config_change_cmd_v1 - change LARI configuration
* @config_bitmap: bit map of the config commands. each bit will trigger a
* different predefined FW config operation
*/
struct iwl_lari_config_change_cmd_v1 {
__le32 config_bitmap;
} __packed; /* LARI_CHANGE_CONF_CMD_S_VER_1 */
/**
* struct iwl_lari_config_change_cmd_v2 - change LARI configuration
* @config_bitmap: bit map of the config commands. each bit will trigger a
* different predefined FW config operation
* @oem_uhb_allow_bitmap: bitmap of UHB enabled MCC sets
*/
struct iwl_lari_config_change_cmd_v2 {
__le32 config_bitmap;
__le32 oem_uhb_allow_bitmap;
} __packed; /* LARI_CHANGE_CONF_CMD_S_VER_2 */
/**
* struct iwl_lari_config_change_cmd_v3 - change LARI configuration
* @config_bitmap: bit map of the config commands. each bit will trigger a
* different predefined FW config operation
* @oem_uhb_allow_bitmap: bitmap of UHB enabled MCC sets
* @oem_11ax_allow_bitmap: bitmap of 11ax allowed MCCs.
* For each supported country, a pair of regulatory override bit and 11ax mode exist
* in the bit field.
*/
struct iwl_lari_config_change_cmd_v3 {
__le32 config_bitmap;
__le32 oem_uhb_allow_bitmap;
__le32 oem_11ax_allow_bitmap;
} __packed; /* LARI_CHANGE_CONF_CMD_S_VER_3 */
/**
* struct iwl_lari_config_change_cmd_v4 - change LARI configuration
* @config_bitmap: Bitmap of the config commands. Each bit will trigger a
* different predefined FW config operation.
* @oem_uhb_allow_bitmap: Bitmap of UHB enabled MCC sets.
* @oem_11ax_allow_bitmap: Bitmap of 11ax allowed MCCs. There are two bits
* per country, one to indicate whether to override and the other to
* indicate the value to use.
* @oem_unii4_allow_bitmap: Bitmap of unii4 allowed MCCs.There are two bits
* per country, one to indicate whether to override and the other to
* indicate allow/disallow unii4 channels.
*/
struct iwl_lari_config_change_cmd_v4 {
__le32 config_bitmap;
__le32 oem_uhb_allow_bitmap;
__le32 oem_11ax_allow_bitmap;
__le32 oem_unii4_allow_bitmap;
} __packed; /* LARI_CHANGE_CONF_CMD_S_VER_4 */
/**
* struct iwl_lari_config_change_cmd_v5 - change LARI configuration
* @config_bitmap: Bitmap of the config commands. Each bit will trigger a
* different predefined FW config operation.
* @oem_uhb_allow_bitmap: Bitmap of UHB enabled MCC sets.
* @oem_11ax_allow_bitmap: Bitmap of 11ax allowed MCCs. There are two bits
* per country, one to indicate whether to override and the other to
* indicate the value to use.
* @oem_unii4_allow_bitmap: Bitmap of unii4 allowed MCCs.There are two bits
* per country, one to indicate whether to override and the other to
* indicate allow/disallow unii4 channels.
* @chan_state_active_bitmap: Bitmap for overriding channel state to active.
* Each bit represents a country or region to activate, according to the BIOS
* definitions.
*/
struct iwl_lari_config_change_cmd_v5 {
__le32 config_bitmap;
__le32 oem_uhb_allow_bitmap;
__le32 oem_11ax_allow_bitmap;
__le32 oem_unii4_allow_bitmap;
__le32 chan_state_active_bitmap;
} __packed; /* LARI_CHANGE_CONF_CMD_S_VER_5 */
/**
* struct iwl_pnvm_init_complete_ntfy - PNVM initialization complete
* @status: PNVM image loading status
*/
struct iwl_pnvm_init_complete_ntfy {
__le32 status;
} __packed; /* PNVM_INIT_COMPLETE_NTFY_S_VER_1 */
#endif /* __iwl_fw_api_nvm_reg_h__ */

View File

@ -0,0 +1,70 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2012-2014 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
* Copyright (C) 2021 Intel Corporation
*/
#ifndef __iwl_fw_api_offload_h__
#define __iwl_fw_api_offload_h__
/**
* enum iwl_prot_offload_subcmd_ids - protocol offload commands
*/
enum iwl_prot_offload_subcmd_ids {
/**
* @STORED_BEACON_NTF: &struct iwl_stored_beacon_notif
*/
STORED_BEACON_NTF = 0xFF,
};
#define MAX_STORED_BEACON_SIZE 600
/**
* struct iwl_stored_beacon_notif_common - Stored beacon notif common fields
*
* @system_time: system time on air rise
* @tsf: TSF on air rise
* @beacon_timestamp: beacon on air rise
* @band: band, matches &RX_RES_PHY_FLAGS_BAND_24 definition
* @channel: channel this beacon was received on
* @rates: rate in ucode internal format
* @byte_count: frame's byte count
*/
struct iwl_stored_beacon_notif_common {
__le32 system_time;
__le64 tsf;
__le32 beacon_timestamp;
__le16 band;
__le16 channel;
__le32 rates;
__le32 byte_count;
} __packed;
/**
* struct iwl_stored_beacon_notif - Stored beacon notification
*
* @common: fields common for all versions
* @data: beacon data, length in @byte_count
*/
struct iwl_stored_beacon_notif_v2 {
struct iwl_stored_beacon_notif_common common;
u8 data[MAX_STORED_BEACON_SIZE];
} __packed; /* WOWLAN_STROED_BEACON_INFO_S_VER_2 */
/**
* struct iwl_stored_beacon_notif_v3 - 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_common common;
u8 sta_id;
u8 reserved[3];
u8 data[MAX_STORED_BEACON_SIZE];
} __packed; /* WOWLAN_STROED_BEACON_INFO_S_VER_3 */
#endif /* __iwl_fw_api_offload_h__ */

View File

@ -0,0 +1,29 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2005-2014 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
#ifndef __iwl_fw_api_paging_h__
#define __iwl_fw_api_paging_h__
#define NUM_OF_FW_PAGING_BLOCKS 33 /* 32 for data and 1 block for CSS */
/**
* struct iwl_fw_paging_cmd - paging layout
*
* Send to FW the paging layout in the driver.
*
* @flags: various flags for the command
* @block_size: the block size in powers of 2
* @block_num: number of blocks specified in the command.
* @device_phy_addr: virtual addresses from device side
*/
struct iwl_fw_paging_cmd {
__le32 flags;
__le32 block_size;
__le32 block_num;
__le32 device_phy_addr[NUM_OF_FW_PAGING_BLOCKS];
} __packed; /* FW_PAGING_BLOCK_CMD_API_S_VER_1 */
#endif /* __iwl_fw_api_paging_h__ */

View File

@ -0,0 +1,160 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2012-2014, 2018, 2020 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
#ifndef __iwl_fw_api_phy_ctxt_h__
#define __iwl_fw_api_phy_ctxt_h__
/* Supported bands */
#define PHY_BAND_5 (0)
#define PHY_BAND_24 (1)
#define PHY_BAND_6 (2)
/* Supported channel width, vary if there is VHT support */
#define PHY_VHT_CHANNEL_MODE20 (0x0)
#define PHY_VHT_CHANNEL_MODE40 (0x1)
#define PHY_VHT_CHANNEL_MODE80 (0x2)
#define PHY_VHT_CHANNEL_MODE160 (0x3)
/*
* Control channel position:
* For legacy set bit means upper channel, otherwise lower.
* For VHT - bit-2 marks if the control is lower/upper relative to center-freq
* bits-1:0 mark the distance from the center freq. for 20Mhz, offset is 0.
* center_freq
* |
* 40Mhz |_______|_______|
* 80Mhz |_______|_______|_______|_______|
* 160Mhz |_______|_______|_______|_______|_______|_______|_______|_______|
* code 011 010 001 000 | 100 101 110 111
*/
#define PHY_VHT_CTRL_POS_1_BELOW (0x0)
#define PHY_VHT_CTRL_POS_2_BELOW (0x1)
#define PHY_VHT_CTRL_POS_3_BELOW (0x2)
#define PHY_VHT_CTRL_POS_4_BELOW (0x3)
#define PHY_VHT_CTRL_POS_1_ABOVE (0x4)
#define PHY_VHT_CTRL_POS_2_ABOVE (0x5)
#define PHY_VHT_CTRL_POS_3_ABOVE (0x6)
#define PHY_VHT_CTRL_POS_4_ABOVE (0x7)
/*
* struct iwl_fw_channel_info_v1 - channel information
*
* @band: PHY_BAND_*
* @channel: channel number
* @width: PHY_[VHT|LEGACY]_CHANNEL_*
* @ctrl channel: PHY_[VHT|LEGACY]_CTRL_*
*/
struct iwl_fw_channel_info_v1 {
u8 band;
u8 channel;
u8 width;
u8 ctrl_pos;
} __packed; /* CHANNEL_CONFIG_API_S_VER_1 */
/*
* struct iwl_fw_channel_info - channel information
*
* @channel: channel number
* @band: PHY_BAND_*
* @width: PHY_[VHT|LEGACY]_CHANNEL_*
* @ctrl channel: PHY_[VHT|LEGACY]_CTRL_*
* @reserved: for future use and alignment
*/
struct iwl_fw_channel_info {
__le32 channel;
u8 band;
u8 width;
u8 ctrl_pos;
u8 reserved;
} __packed; /*CHANNEL_CONFIG_API_S_VER_2 */
#define PHY_RX_CHAIN_DRIVER_FORCE_POS (0)
#define PHY_RX_CHAIN_DRIVER_FORCE_MSK \
(0x1 << PHY_RX_CHAIN_DRIVER_FORCE_POS)
#define PHY_RX_CHAIN_VALID_POS (1)
#define PHY_RX_CHAIN_VALID_MSK \
(0x7 << PHY_RX_CHAIN_VALID_POS)
#define PHY_RX_CHAIN_FORCE_SEL_POS (4)
#define PHY_RX_CHAIN_FORCE_SEL_MSK \
(0x7 << PHY_RX_CHAIN_FORCE_SEL_POS)
#define PHY_RX_CHAIN_FORCE_MIMO_SEL_POS (7)
#define PHY_RX_CHAIN_FORCE_MIMO_SEL_MSK \
(0x7 << PHY_RX_CHAIN_FORCE_MIMO_SEL_POS)
#define PHY_RX_CHAIN_CNT_POS (10)
#define PHY_RX_CHAIN_CNT_MSK \
(0x3 << PHY_RX_CHAIN_CNT_POS)
#define PHY_RX_CHAIN_MIMO_CNT_POS (12)
#define PHY_RX_CHAIN_MIMO_CNT_MSK \
(0x3 << PHY_RX_CHAIN_MIMO_CNT_POS)
#define PHY_RX_CHAIN_MIMO_FORCE_POS (14)
#define PHY_RX_CHAIN_MIMO_FORCE_MSK \
(0x1 << PHY_RX_CHAIN_MIMO_FORCE_POS)
/* TODO: fix the value, make it depend on firmware at runtime? */
#define NUM_PHY_CTX 3
/* TODO: complete missing documentation */
/**
* struct iwl_phy_context_cmd_tail - tail of iwl_phy_ctx_cmd for alignment with
* various channel structures.
*
* @txchain_info: ???
* @rxchain_info: ???
* @acquisition_data: ???
* @dsp_cfg_flags: set to 0
*/
struct iwl_phy_context_cmd_tail {
__le32 txchain_info;
__le32 rxchain_info;
__le32 acquisition_data;
__le32 dsp_cfg_flags;
} __packed;
/**
* struct iwl_phy_context_cmd - config of the PHY context
* ( PHY_CONTEXT_CMD = 0x8 )
* @id_and_color: ID and color of the relevant Binding
* @action: action to perform, one of FW_CTXT_ACTION_*
* @apply_time: 0 means immediate apply and context switch.
* other value means apply new params after X usecs
* @tx_param_color: ???
* @ci: channel info
* @tail: command tail
*/
struct iwl_phy_context_cmd_v1 {
/* COMMON_INDEX_HDR_API_S_VER_1 */
__le32 id_and_color;
__le32 action;
/* PHY_CONTEXT_DATA_API_S_VER_3 */
__le32 apply_time;
__le32 tx_param_color;
struct iwl_fw_channel_info ci;
struct iwl_phy_context_cmd_tail tail;
} __packed; /* PHY_CONTEXT_CMD_API_VER_1 */
/**
* struct iwl_phy_context_cmd - config of the PHY context
* ( PHY_CONTEXT_CMD = 0x8 )
* @id_and_color: ID and color of the relevant Binding
* @action: action to perform, one of FW_CTXT_ACTION_*
* @lmac_id: the lmac id the phy context belongs to
* @ci: channel info
* @rxchain_info: ???
* @dsp_cfg_flags: set to 0
* @reserved: reserved to align to 64 bit
*/
struct iwl_phy_context_cmd {
/* COMMON_INDEX_HDR_API_S_VER_1 */
__le32 id_and_color;
__le32 action;
/* PHY_CONTEXT_DATA_API_S_VER_3 */
struct iwl_fw_channel_info ci;
__le32 lmac_id;
__le32 rxchain_info;
__le32 dsp_cfg_flags;
__le32 reserved;
} __packed; /* PHY_CONTEXT_CMD_API_VER_3 */
#endif /* __iwl_fw_api_phy_ctxt_h__ */

View File

@ -0,0 +1,216 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2012-2014, 2019-2021 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__
/**
* enum iwl_phy_ops_subcmd_ids - PHY group commands
*/
enum iwl_phy_ops_subcmd_ids {
/**
* @CMD_DTS_MEASUREMENT_TRIGGER_WIDE:
* Uses either &struct iwl_dts_measurement_cmd or
* &struct iwl_ext_dts_measurement_cmd
*/
CMD_DTS_MEASUREMENT_TRIGGER_WIDE = 0x0,
/**
* @CTDP_CONFIG_CMD: &struct iwl_mvm_ctdp_cmd
*/
CTDP_CONFIG_CMD = 0x03,
/**
* @TEMP_REPORTING_THRESHOLDS_CMD: &struct temp_report_ths_cmd
*/
TEMP_REPORTING_THRESHOLDS_CMD = 0x04,
/**
* @PER_CHAIN_LIMIT_OFFSET_CMD: &struct iwl_geo_tx_power_profiles_cmd
*/
PER_CHAIN_LIMIT_OFFSET_CMD = 0x05,
/**
* @PER_PLATFORM_ANT_GAIN_CMD: &struct iwl_ppag_table_cmd
*/
PER_PLATFORM_ANT_GAIN_CMD = 0x07,
/**
* @CT_KILL_NOTIFICATION: &struct ct_kill_notif
*/
CT_KILL_NOTIFICATION = 0xFE,
/**
* @DTS_MEASUREMENT_NOTIF_WIDE:
* &struct iwl_dts_measurement_notif_v1 or
* &struct iwl_dts_measurement_notif_v2
*/
DTS_MEASUREMENT_NOTIF_WIDE = 0xFF,
};
/* DTS measurements */
enum iwl_dts_measurement_flags {
DTS_TRIGGER_CMD_FLAGS_TEMP = BIT(0),
DTS_TRIGGER_CMD_FLAGS_VOLT = BIT(1),
};
/**
* struct iwl_dts_measurement_cmd - request DTS temp and/or voltage measurements
*
* @flags: indicates which measurements we want as specified in
* &enum iwl_dts_measurement_flags
*/
struct iwl_dts_measurement_cmd {
__le32 flags;
} __packed; /* TEMPERATURE_MEASUREMENT_TRIGGER_CMD_S */
/**
* enum iwl_dts_control_measurement_mode - DTS measurement type
* @DTS_AUTOMATIC: Automatic mode (full SW control). Provide temperature read
* back (latest value. Not waiting for new value). Use automatic
* SW DTS configuration.
* @DTS_REQUEST_READ: Request DTS read. Configure DTS with manual settings,
* trigger DTS reading and provide read back temperature read
* when available.
* @DTS_OVER_WRITE: over-write the DTS temperatures in the SW until next read
* @DTS_DIRECT_WITHOUT_MEASURE: DTS returns its latest temperature result,
* without measurement trigger.
*/
enum iwl_dts_control_measurement_mode {
DTS_AUTOMATIC = 0,
DTS_REQUEST_READ = 1,
DTS_OVER_WRITE = 2,
DTS_DIRECT_WITHOUT_MEASURE = 3,
};
/**
* enum iwl_dts_used - DTS to use or used for measurement in the DTS request
* @DTS_USE_TOP: Top
* @DTS_USE_CHAIN_A: chain A
* @DTS_USE_CHAIN_B: chain B
* @DTS_USE_CHAIN_C: chain C
* @XTAL_TEMPERATURE: read temperature from xtal
*/
enum iwl_dts_used {
DTS_USE_TOP = 0,
DTS_USE_CHAIN_A = 1,
DTS_USE_CHAIN_B = 2,
DTS_USE_CHAIN_C = 3,
XTAL_TEMPERATURE = 4,
};
/**
* enum iwl_dts_bit_mode - bit-mode to use in DTS request read mode
* @DTS_BIT6_MODE: bit 6 mode
* @DTS_BIT8_MODE: bit 8 mode
*/
enum iwl_dts_bit_mode {
DTS_BIT6_MODE = 0,
DTS_BIT8_MODE = 1,
};
/**
* struct iwl_ext_dts_measurement_cmd - request extended DTS temp measurements
* @control_mode: see &enum iwl_dts_control_measurement_mode
* @temperature: used when over write DTS mode is selected
* @sensor: set temperature sensor to use. See &enum iwl_dts_used
* @avg_factor: average factor to DTS in request DTS read mode
* @bit_mode: value defines the DTS bit mode to use. See &enum iwl_dts_bit_mode
* @step_duration: step duration for the DTS
*/
struct iwl_ext_dts_measurement_cmd {
__le32 control_mode;
__le32 temperature;
__le32 sensor;
__le32 avg_factor;
__le32 bit_mode;
__le32 step_duration;
} __packed; /* XVT_FW_DTS_CONTROL_MEASUREMENT_REQUEST_API_S */
/**
* struct iwl_dts_measurement_notif_v1 - measurements notification
*
* @temp: the measured temperature
* @voltage: the measured voltage
*/
struct iwl_dts_measurement_notif_v1 {
__le32 temp;
__le32 voltage;
} __packed; /* TEMPERATURE_MEASUREMENT_TRIGGER_NTFY_S_VER_1*/
/**
* struct iwl_dts_measurement_notif_v2 - measurements notification
*
* @temp: the measured temperature
* @voltage: the measured voltage
* @threshold_idx: the trip index that was crossed
*/
struct iwl_dts_measurement_notif_v2 {
__le32 temp;
__le32 voltage;
__le32 threshold_idx;
} __packed; /* TEMPERATURE_MEASUREMENT_TRIGGER_NTFY_S_VER_2 */
/**
* struct iwl_dts_measurement_resp - measurements response
*
* @temp: the measured temperature
*/
struct iwl_dts_measurement_resp {
__le32 temp;
} __packed; /* CMD_DTS_MEASUREMENT_RSP_API_S_VER_1 */
/**
* struct ct_kill_notif - CT-kill entry notification
*
* @temperature: the current temperature in celsius
* @reserved: reserved
*/
struct ct_kill_notif {
__le16 temperature;
__le16 reserved;
} __packed; /* GRP_PHY_CT_KILL_NTF */
/**
* enum 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 {
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
*
* @operation: see &enum iwl_mvm_ctdp_cmd_operation
* @budget: the budget in milliwatt
* @window_size: defined in API but not used
*/
struct iwl_mvm_ctdp_cmd {
__le32 operation;
__le32 budget;
__le32 window_size;
} __packed;
#define IWL_MAX_DTS_TRIPS 8
/**
* struct temp_report_ths_cmd - set temperature thresholds
*
* @num_temps: number of temperature thresholds passed
* @thresholds: array with the thresholds to be configured
*/
struct temp_report_ths_cmd {
__le32 num_temps;
__le16 thresholds[IWL_MAX_DTS_TRIPS];
} __packed; /* GRP_PHY_TEMP_REPORTING_THRESHOLDS_CMD */
#endif /* __iwl_fw_api_phy_h__ */

View File

@ -0,0 +1,633 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2012-2014, 2018-2021 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__
/* Power Management Commands, Responses, Notifications */
/**
* enum iwl_ltr_config_flags - masks for LTR config command flags
* @LTR_CFG_FLAG_FEATURE_ENABLE: Feature operational status
* @LTR_CFG_FLAG_HW_DIS_ON_SHADOW_REG_ACCESS: allow LTR change on shadow
* memory access
* @LTR_CFG_FLAG_HW_EN_SHRT_WR_THROUGH: allow LTR msg send on ANY LTR
* reg change
* @LTR_CFG_FLAG_HW_DIS_ON_D0_2_D3: allow LTR msg send on transition from
* D0 to D3
* @LTR_CFG_FLAG_SW_SET_SHORT: fixed static short LTR register
* @LTR_CFG_FLAG_SW_SET_LONG: fixed static short LONG register
* @LTR_CFG_FLAG_DENIE_C10_ON_PD: allow going into C10 on PD
* @LTR_CFG_FLAG_UPDATE_VALUES: update config values and short
* idle timeout
*/
enum iwl_ltr_config_flags {
LTR_CFG_FLAG_FEATURE_ENABLE = BIT(0),
LTR_CFG_FLAG_HW_DIS_ON_SHADOW_REG_ACCESS = BIT(1),
LTR_CFG_FLAG_HW_EN_SHRT_WR_THROUGH = BIT(2),
LTR_CFG_FLAG_HW_DIS_ON_D0_2_D3 = BIT(3),
LTR_CFG_FLAG_SW_SET_SHORT = BIT(4),
LTR_CFG_FLAG_SW_SET_LONG = BIT(5),
LTR_CFG_FLAG_DENIE_C10_ON_PD = BIT(6),
LTR_CFG_FLAG_UPDATE_VALUES = BIT(7),
};
/**
* struct iwl_ltr_config_cmd_v1 - configures the LTR
* @flags: See &enum iwl_ltr_config_flags
* @static_long: static LTR Long register value.
* @static_short: static LTR Short register value.
*/
struct iwl_ltr_config_cmd_v1 {
__le32 flags;
__le32 static_long;
__le32 static_short;
} __packed; /* LTR_CAPABLE_API_S_VER_1 */
#define LTR_VALID_STATES_NUM 4
/**
* struct iwl_ltr_config_cmd - configures the LTR
* @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:
* 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
* %LTR_CFG_FLAG_UPDATE_VALUES is set.
*/
struct iwl_ltr_config_cmd {
__le32 flags;
__le32 static_long;
__le32 static_short;
__le32 ltr_cfg_values[LTR_VALID_STATES_NUM];
__le32 ltr_short_idle_timeout;
} __packed; /* LTR_CAPABLE_API_S_VER_2 */
/* Radio LP RX Energy Threshold measured in dBm */
#define POWER_LPRX_RSSI_THRESHOLD 75
#define POWER_LPRX_RSSI_THRESHOLD_MAX 94
#define POWER_LPRX_RSSI_THRESHOLD_MIN 30
/**
* enum iwl_power_flags - masks for power table command flags
* @POWER_FLAGS_POWER_SAVE_ENA_MSK: '1' Allow to save power by turning off
* receiver and transmitter. '0' - does not allow.
* @POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK: '0' Driver disables power management,
* '1' Driver enables PM (use rest of parameters)
* @POWER_FLAGS_SKIP_OVER_DTIM_MSK: '0' PM have to walk up every DTIM,
* '1' PM could sleep over DTIM till listen Interval.
* @POWER_FLAGS_SNOOZE_ENA_MSK: Enable snoozing only if uAPSD is enabled and all
* access categories are both delivery and trigger enabled.
* @POWER_FLAGS_BT_SCO_ENA: Enable BT SCO coex only if uAPSD and
* PBW Snoozing enabled
* @POWER_FLAGS_ADVANCE_PM_ENA_MSK: Advanced PM (uAPSD) enable mask
* @POWER_FLAGS_LPRX_ENA_MSK: Low Power RX enable.
* @POWER_FLAGS_UAPSD_MISBEHAVING_ENA_MSK: AP/GO's uAPSD misbehaving
* detection enablement
*/
enum iwl_power_flags {
POWER_FLAGS_POWER_SAVE_ENA_MSK = BIT(0),
POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK = BIT(1),
POWER_FLAGS_SKIP_OVER_DTIM_MSK = BIT(2),
POWER_FLAGS_SNOOZE_ENA_MSK = BIT(5),
POWER_FLAGS_BT_SCO_ENA = BIT(8),
POWER_FLAGS_ADVANCE_PM_ENA_MSK = BIT(9),
POWER_FLAGS_LPRX_ENA_MSK = BIT(11),
POWER_FLAGS_UAPSD_MISBEHAVING_ENA_MSK = BIT(12),
};
#define IWL_POWER_VEC_SIZE 5
/**
* struct iwl_powertable_cmd - legacy power command. Beside old API support this
* is used also with a new power API for device wide power settings.
* POWER_TABLE_CMD = 0x77 (command, has simple generic response)
*
* @flags: Power table command flags from POWER_FLAGS_*
* @keep_alive_seconds: Keep alive period in seconds. Default - 25 sec.
* Minimum allowed:- 3 * DTIM. Keep alive period must be
* set regardless of power scheme or current power state.
* FW use this value also when PM is disabled.
* @debug_flags: debug flags
* @rx_data_timeout: Minimum time (usec) from last Rx packet for AM to
* PSM transition - legacy PM
* @tx_data_timeout: Minimum time (usec) from last Tx packet for AM to
* PSM transition - legacy PM
* @sleep_interval: not in use
* @skip_dtim_periods: Number of DTIM periods to skip if Skip over DTIM flag
* is set. For example, if it is required to skip over
* one DTIM, this value need to be set to 2 (DTIM periods).
* @lprx_rssi_threshold: Signal strength up to which LP RX can be enabled.
* Default: 80dbm
*/
struct iwl_powertable_cmd {
/* PM_POWER_TABLE_CMD_API_S_VER_6 */
__le16 flags;
u8 keep_alive_seconds;
u8 debug_flags;
__le32 rx_data_timeout;
__le32 tx_data_timeout;
__le32 sleep_interval[IWL_POWER_VEC_SIZE];
__le32 skip_dtim_periods;
__le32 lprx_rssi_threshold;
} __packed;
/**
* enum iwl_device_power_flags - masks for device power command flags
* @DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK:
* '1' Allow to save power by turning off
* receiver and transmitter. '0' - does not allow.
* @DEVICE_POWER_FLAGS_ALLOW_MEM_RETENTION_MSK:
* Device Retention indication, '1' indicate retention is enabled.
* @DEVICE_POWER_FLAGS_32K_CLK_VALID_MSK:
* 32Khz external slow clock valid indication, '1' indicate cloack is
* valid.
*/
enum iwl_device_power_flags {
DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK = BIT(0),
DEVICE_POWER_FLAGS_ALLOW_MEM_RETENTION_MSK = BIT(1),
DEVICE_POWER_FLAGS_32K_CLK_VALID_MSK = BIT(12),
};
/**
* struct iwl_device_power_cmd - device wide power command.
* DEVICE_POWER_CMD = 0x77 (command, has simple generic response)
*
* @flags: Power table command flags from &enum iwl_device_power_flags
* @reserved: reserved (padding)
*/
struct iwl_device_power_cmd {
/* PM_POWER_TABLE_CMD_API_S_VER_6 */
__le16 flags;
__le16 reserved;
} __packed;
/**
* struct iwl_mac_power_cmd - New power command containing uAPSD support
* MAC_PM_POWER_TABLE = 0xA9 (command, has simple generic response)
* @id_and_color: MAC contex identifier, &enum iwl_ctxt_id_and_color
* @flags: Power table command flags from POWER_FLAGS_*
* @keep_alive_seconds: Keep alive period in seconds. Default - 25 sec.
* Minimum allowed:- 3 * DTIM. Keep alive period must be
* set regardless of power scheme or current power state.
* FW use this value also when PM is disabled.
* @rx_data_timeout: Minimum time (usec) from last Rx packet for AM to
* PSM transition - legacy PM
* @tx_data_timeout: Minimum time (usec) from last Tx packet for AM to
* PSM transition - legacy PM
* @skip_dtim_periods: Number of DTIM periods to skip if Skip over DTIM flag
* is set. For example, if it is required to skip over
* one DTIM, this value need to be set to 2 (DTIM periods).
* @rx_data_timeout_uapsd: Minimum time (usec) from last Rx packet for AM to
* PSM transition - uAPSD
* @tx_data_timeout_uapsd: Minimum time (usec) from last Tx packet for AM to
* PSM transition - uAPSD
* @lprx_rssi_threshold: Signal strength up to which LP RX can be enabled.
* Default: 80dbm
* @snooze_interval: Maximum time between attempts to retrieve buffered data
* from the AP [msec]
* @snooze_window: A window of time in which PBW snoozing insures that all
* packets received. It is also the minimum time from last
* received unicast RX packet, before client stops snoozing
* for data. [msec]
* @snooze_step: TBD
* @qndp_tid: TID client shall use for uAPSD QNDP triggers
* @uapsd_ac_flags: Set trigger-enabled and delivery-enabled indication for
* each corresponding AC.
* Use IEEE80211_WMM_IE_STA_QOSINFO_AC* for correct values.
* @uapsd_max_sp: Use IEEE80211_WMM_IE_STA_QOSINFO_SP_* for correct
* values.
* @heavy_tx_thld_packets: TX threshold measured in number of packets
* @heavy_rx_thld_packets: RX threshold measured in number of packets
* @heavy_tx_thld_percentage: TX threshold measured in load's percentage
* @heavy_rx_thld_percentage: RX threshold measured in load's percentage
* @limited_ps_threshold: (unused)
* @reserved: reserved (padding)
*/
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;
__le32 tx_data_timeout;
__le32 rx_data_timeout_uapsd;
__le32 tx_data_timeout_uapsd;
u8 lprx_rssi_threshold;
u8 skip_dtim_periods;
__le16 snooze_interval;
__le16 snooze_window;
u8 snooze_step;
u8 qndp_tid;
u8 uapsd_ac_flags;
u8 uapsd_max_sp;
u8 heavy_tx_thld_packets;
u8 heavy_rx_thld_packets;
u8 heavy_tx_thld_percentage;
u8 heavy_rx_thld_percentage;
u8 limited_ps_threshold;
u8 reserved;
} __packed;
/*
* struct iwl_uapsd_misbehaving_ap_notif - FW sends this notification when
* associated AP is identified as improperly implementing uAPSD protocol.
* PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION = 0x78
* @sta_id: index of station in uCode's station table - associated AP ID in
* this context.
*/
struct iwl_uapsd_misbehaving_ap_notif {
__le32 sta_id;
u8 mac_id;
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_DEVICE = 1,
IWL_TX_POWER_MODE_SET_CHAINS = 2,
IWL_TX_POWER_MODE_SET_ACK = 3,
IWL_TX_POWER_MODE_SET_SAR_TIMER = 4,
IWL_TX_POWER_MODE_SET_SAR_TIMER_DEFAULT_TABLE = 5,
}; /* TX_POWER_REDUCED_FLAGS_TYPE_API_E_VER_5 */;
#define IWL_NUM_CHAIN_TABLES 1
#define IWL_NUM_CHAIN_TABLES_V2 2
#define IWL_NUM_CHAIN_LIMITS 2
#define IWL_NUM_SUB_BANDS_V1 5
#define IWL_NUM_SUB_BANDS_V2 11
/**
* 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.
* @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;
__le16 pwr_restriction;
__le16 dev_24;
__le16 dev_52_low;
__le16 dev_52_high;
};
/**
* struct iwl_dev_tx_power_cmd_v3 - TX power reduction command version 3
* @per_chain: per chain restrictions
*/
struct iwl_dev_tx_power_cmd_v3 {
__le16 per_chain[IWL_NUM_CHAIN_TABLES][IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V1];
} __packed; /* TX_REDUCED_POWER_API_S_VER_3 */
#define IWL_DEV_MAX_TX_POWER 0x7FFF
/**
* struct iwl_dev_tx_power_cmd_v4 - TX power reduction command version 4
* @per_chain: per chain restrictions
* @enable_ack_reduction: enable or disable close range ack TX power
* reduction.
* @reserved: reserved (padding)
*/
struct iwl_dev_tx_power_cmd_v4 {
__le16 per_chain[IWL_NUM_CHAIN_TABLES][IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V1];
u8 enable_ack_reduction;
u8 reserved[3];
} __packed; /* TX_REDUCED_POWER_API_S_VER_4 */
/**
* struct iwl_dev_tx_power_cmd_v5 - TX power reduction command version 5
* @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_v5 {
__le16 per_chain[IWL_NUM_CHAIN_TABLES][IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V1];
u8 enable_ack_reduction;
u8 per_chain_restriction_changed;
u8 reserved[2];
__le32 timer_period;
} __packed; /* TX_REDUCED_POWER_API_S_VER_5 */
/**
* struct iwl_dev_tx_power_cmd_v5 - TX power reduction command version 5
* @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 - TX power reduction command (multiversion)
* @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
*/
struct iwl_dev_tx_power_cmd {
struct iwl_dev_tx_power_common common;
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;
};
};
#define IWL_NUM_GEO_PROFILES 3
#define IWL_NUM_GEO_PROFILES_V3 8
#define IWL_NUM_BANDS_PER_CHAIN_V1 2
#define IWL_NUM_BANDS_PER_CHAIN_V2 3
/**
* enum iwl_geo_per_chain_offset_operation - type of operation
* @IWL_PER_CHAIN_OFFSET_SET_TABLES: send the tables from the host to the FW.
* @IWL_PER_CHAIN_OFFSET_GET_CURRENT_TABLE: retrieve the last configured table.
*/
enum iwl_geo_per_chain_offset_operation {
IWL_PER_CHAIN_OFFSET_SET_TABLES,
IWL_PER_CHAIN_OFFSET_GET_CURRENT_TABLE,
}; /* PER_CHAIN_OFFSET_OPERATION_E */
/**
* struct iwl_per_chain_offset - embedded struct for PER_CHAIN_LIMIT_OFFSET_CMD.
* @max_tx_power: maximum allowed tx power.
* @chain_a: tx power offset for chain a.
* @chain_b: tx power offset for chain b.
*/
struct iwl_per_chain_offset {
__le16 max_tx_power;
u8 chain_a;
u8 chain_b;
} __packed; /* PER_CHAIN_LIMIT_OFFSET_PER_CHAIN_S_VER_1 */
/**
* struct iwl_geo_tx_power_profile_cmd_v1 - struct for PER_CHAIN_LIMIT_OFFSET_CMD cmd.
* @ops: operations, value from &enum iwl_geo_per_chain_offset_operation
* @table: offset profile per band.
*/
struct iwl_geo_tx_power_profiles_cmd_v1 {
__le32 ops;
struct iwl_per_chain_offset table[IWL_NUM_GEO_PROFILES][IWL_NUM_BANDS_PER_CHAIN_V1];
} __packed; /* PER_CHAIN_LIMIT_OFFSET_CMD_VER_1 */
/**
* struct iwl_geo_tx_power_profile_cmd_v2 - struct for PER_CHAIN_LIMIT_OFFSET_CMD cmd.
* @ops: operations, value from &enum iwl_geo_per_chain_offset_operation
* @table: offset profile per band.
* @table_revision: BIOS table revision.
*/
struct iwl_geo_tx_power_profiles_cmd_v2 {
__le32 ops;
struct iwl_per_chain_offset table[IWL_NUM_GEO_PROFILES][IWL_NUM_BANDS_PER_CHAIN_V1];
__le32 table_revision;
} __packed; /* PER_CHAIN_LIMIT_OFFSET_CMD_VER_2 */
/**
* struct iwl_geo_tx_power_profile_cmd_v3 - struct for PER_CHAIN_LIMIT_OFFSET_CMD cmd.
* @ops: operations, value from &enum iwl_geo_per_chain_offset_operation
* @table: offset profile per band.
* @table_revision: BIOS table revision.
*/
struct iwl_geo_tx_power_profiles_cmd_v3 {
__le32 ops;
struct iwl_per_chain_offset table[IWL_NUM_GEO_PROFILES][IWL_NUM_BANDS_PER_CHAIN_V2];
__le32 table_revision;
} __packed; /* PER_CHAIN_LIMIT_OFFSET_CMD_VER_3 */
/**
* struct iwl_geo_tx_power_profile_cmd_v4 - struct for PER_CHAIN_LIMIT_OFFSET_CMD cmd.
* @ops: operations, value from &enum iwl_geo_per_chain_offset_operation
* @table: offset profile per band.
* @table_revision: BIOS table revision.
*/
struct iwl_geo_tx_power_profiles_cmd_v4 {
__le32 ops;
struct iwl_per_chain_offset table[IWL_NUM_GEO_PROFILES_V3][IWL_NUM_BANDS_PER_CHAIN_V1];
__le32 table_revision;
} __packed; /* PER_CHAIN_LIMIT_OFFSET_CMD_VER_4 */
/**
* struct iwl_geo_tx_power_profile_cmd_v5 - struct for PER_CHAIN_LIMIT_OFFSET_CMD cmd.
* @ops: operations, value from &enum iwl_geo_per_chain_offset_operation
* @table: offset profile per band.
* @table_revision: BIOS table revision.
*/
struct iwl_geo_tx_power_profiles_cmd_v5 {
__le32 ops;
struct iwl_per_chain_offset table[IWL_NUM_GEO_PROFILES_V3][IWL_NUM_BANDS_PER_CHAIN_V2];
__le32 table_revision;
} __packed; /* PER_CHAIN_LIMIT_OFFSET_CMD_VER_5 */
union iwl_geo_tx_power_profiles_cmd {
struct iwl_geo_tx_power_profiles_cmd_v1 v1;
struct iwl_geo_tx_power_profiles_cmd_v2 v2;
struct iwl_geo_tx_power_profiles_cmd_v3 v3;
struct iwl_geo_tx_power_profiles_cmd_v4 v4;
struct iwl_geo_tx_power_profiles_cmd_v5 v5;
};
/**
* struct iwl_geo_tx_power_profiles_resp - response to PER_CHAIN_LIMIT_OFFSET_CMD cmd
* @profile_idx: current geo profile in use
*/
struct iwl_geo_tx_power_profiles_resp {
__le32 profile_idx;
} __packed; /* PER_CHAIN_LIMIT_OFFSET_RSP */
/**
* union iwl_ppag_table_cmd - union for all versions of PPAG command
* @v1: version 1
* @v2: version 2
*
* @flags: bit 0 - indicates enablement of PPAG for ETSI
* bit 1 - indicates enablement of PPAG for CHINA BIOS
* bit 1 can be used only in v3 (identical to v2)
* @gain: table of antenna gain values per chain and sub-band
* @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;
struct {
__le32 flags;
s8 gain[IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V2];
s8 reserved[2];
} v2;
} __packed;
/**
* struct iwl_beacon_filter_cmd
* REPLY_BEACON_FILTERING_CMD = 0xd2 (command)
* @bf_energy_delta: Used for RSSI filtering, if in 'normal' state. Send beacon
* to driver if delta in Energy values calculated for this and last
* passed beacon is greater than this threshold. Zero value means that
* the Energy change is ignored for beacon filtering, and beacon will
* not be forced to be sent to driver regardless of this delta. Typical
* energy delta 5dB.
* @bf_roaming_energy_delta: Used for RSSI filtering, if in 'roaming' state.
* Send beacon to driver if delta in Energy values calculated for this
* and last passed beacon is greater than this threshold. Zero value
* means that the Energy change is ignored for beacon filtering while in
* Roaming state, typical energy delta 1dB.
* @bf_roaming_state: Used for RSSI filtering. If absolute Energy values
* calculated for current beacon is less than the threshold, use
* 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):
* 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.
* @bf_temp_fast_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.
* @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.
* @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
* for a specific period of time. Units: Beacons.
* @ba_escape_timer: Fully receive and parse beacon if no beacons were passed
* for a longer period of time then this escape-timeout. Units: Beacons.
* @ba_enable_beacon_abort: 1, beacon abort is enabled; 0, disabled.
* @bf_threshold_absolute_low: See below.
* @bf_threshold_absolute_high: Send Beacon to driver if Energy value calculated
* for this beacon crossed this absolute threshold. For the 'Increase'
* direction the bf_energy_absolute_low[i] is used. For the 'Decrease'
* direction the bf_energy_absolute_high[i] is used. Zero value means
* that this specific threshold is ignored for beacon filtering, and
* beacon will not be forced to be sent to driver due to this setting.
*/
struct iwl_beacon_filter_cmd {
__le32 bf_energy_delta;
__le32 bf_roaming_energy_delta;
__le32 bf_roaming_state;
__le32 bf_temp_threshold;
__le32 bf_temp_fast_filter;
__le32 bf_temp_slow_filter;
__le32 bf_enable_beacon_filter;
__le32 bf_debug_flag;
__le32 bf_escape_timer;
__le32 ba_escape_timer;
__le32 ba_enable_beacon_abort;
__le32 bf_threshold_absolute_low[2];
__le32 bf_threshold_absolute_high[2];
} __packed; /* BEACON_FILTER_CONFIG_API_S_VER_4 */
/* Beacon filtering and beacon abort */
#define IWL_BF_ENERGY_DELTA_DEFAULT 5
#define IWL_BF_ENERGY_DELTA_D0I3 20
#define IWL_BF_ENERGY_DELTA_MAX 255
#define IWL_BF_ENERGY_DELTA_MIN 0
#define IWL_BF_ROAMING_ENERGY_DELTA_DEFAULT 1
#define IWL_BF_ROAMING_ENERGY_DELTA_D0I3 20
#define IWL_BF_ROAMING_ENERGY_DELTA_MAX 255
#define IWL_BF_ROAMING_ENERGY_DELTA_MIN 0
#define IWL_BF_ROAMING_STATE_DEFAULT 72
#define IWL_BF_ROAMING_STATE_D0I3 72
#define IWL_BF_ROAMING_STATE_MAX 255
#define IWL_BF_ROAMING_STATE_MIN 0
#define IWL_BF_TEMP_THRESHOLD_DEFAULT 112
#define IWL_BF_TEMP_THRESHOLD_D0I3 112
#define IWL_BF_TEMP_THRESHOLD_MAX 255
#define IWL_BF_TEMP_THRESHOLD_MIN 0
#define IWL_BF_TEMP_FAST_FILTER_DEFAULT 1
#define IWL_BF_TEMP_FAST_FILTER_D0I3 1
#define IWL_BF_TEMP_FAST_FILTER_MAX 255
#define IWL_BF_TEMP_FAST_FILTER_MIN 0
#define IWL_BF_TEMP_SLOW_FILTER_DEFAULT 5
#define IWL_BF_TEMP_SLOW_FILTER_D0I3 20
#define IWL_BF_TEMP_SLOW_FILTER_MAX 255
#define IWL_BF_TEMP_SLOW_FILTER_MIN 0
#define IWL_BF_ENABLE_BEACON_FILTER_DEFAULT 1
#define IWL_BF_DEBUG_FLAG_DEFAULT 0
#define IWL_BF_DEBUG_FLAG_D0I3 0
#define IWL_BF_ESCAPE_TIMER_DEFAULT 0
#define IWL_BF_ESCAPE_TIMER_D0I3 0
#define IWL_BF_ESCAPE_TIMER_MAX 1024
#define IWL_BF_ESCAPE_TIMER_MIN 0
#define IWL_BA_ESCAPE_TIMER_DEFAULT 6
#define IWL_BA_ESCAPE_TIMER_D0I3 6
#define IWL_BA_ESCAPE_TIMER_D3 9
#define IWL_BA_ESCAPE_TIMER_MAX 1024
#define IWL_BA_ESCAPE_TIMER_MIN 0
#define IWL_BA_ENABLE_BEACON_ABORT_DEFAULT 1
#define IWL_BF_CMD_CONFIG(mode) \
.bf_energy_delta = cpu_to_le32(IWL_BF_ENERGY_DELTA ## mode), \
.bf_roaming_energy_delta = \
cpu_to_le32(IWL_BF_ROAMING_ENERGY_DELTA ## mode), \
.bf_roaming_state = cpu_to_le32(IWL_BF_ROAMING_STATE ## mode), \
.bf_temp_threshold = cpu_to_le32(IWL_BF_TEMP_THRESHOLD ## mode), \
.bf_temp_fast_filter = cpu_to_le32(IWL_BF_TEMP_FAST_FILTER ## mode), \
.bf_temp_slow_filter = cpu_to_le32(IWL_BF_TEMP_SLOW_FILTER ## mode), \
.bf_debug_flag = cpu_to_le32(IWL_BF_DEBUG_FLAG ## mode), \
.bf_escape_timer = cpu_to_le32(IWL_BF_ESCAPE_TIMER ## mode), \
.ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER ## mode)
#define IWL_BF_CMD_CONFIG_DEFAULTS IWL_BF_CMD_CONFIG(_DEFAULT)
#define IWL_BF_CMD_CONFIG_D0I3 IWL_BF_CMD_CONFIG(_D0I3)
#endif /* __iwl_fw_api_power_h__ */

View File

@ -0,0 +1,60 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2020 Intel Corporation
*/
#ifndef __iwl_fw_api_rfi_h__
#define __iwl_fw_api_rfi_h__
#define IWL_RFI_LUT_ENTRY_CHANNELS_NUM 15
#define IWL_RFI_LUT_SIZE 24
#define IWL_RFI_LUT_INSTALLED_SIZE 4
/**
* struct iwl_rfi_lut_entry - an entry in the RFI frequency LUT.
*
* @freq: frequency
* @channels: channels that can be interfered at frequency freq (at most 15)
* @bands: the corresponding bands
*/
struct iwl_rfi_lut_entry {
__le16 freq;
u8 channels[IWL_RFI_LUT_ENTRY_CHANNELS_NUM];
u8 bands[IWL_RFI_LUT_ENTRY_CHANNELS_NUM];
} __packed;
/**
* struct iwl_rfi_config_cmd - RFI configuration table
*
* @entry: a table can have 24 frequency/channel mappings
* @oem: specifies if this is the default table or set by OEM
*/
struct iwl_rfi_config_cmd {
struct iwl_rfi_lut_entry table[IWL_RFI_LUT_SIZE];
u8 oem;
u8 reserved[3];
} __packed; /* RFI_CONFIG_CMD_API_S_VER_1 */
/**
* iwl_rfi_freq_table_status - status of the frequency table query
* @RFI_FREQ_TABLE_OK: can be used
* @RFI_FREQ_TABLE_DVFS_NOT_READY: DVFS is not ready yet, should try later
* @RFI_FREQ_TABLE_DISABLED: the feature is disabled in FW
*/
enum iwl_rfi_freq_table_status {
RFI_FREQ_TABLE_OK,
RFI_FREQ_TABLE_DVFS_NOT_READY,
RFI_FREQ_TABLE_DISABLED,
};
/**
* struct iwl_rfi_freq_table_resp_cmd - get the rfi freq table used by FW
*
* @table: table used by FW
* @status: see &iwl_rfi_freq_table_status
*/
struct iwl_rfi_freq_table_resp_cmd {
struct iwl_rfi_lut_entry table[IWL_RFI_LUT_INSTALLED_SIZE];
__le32 status;
} __packed; /* RFI_CONFIG_CMD_API_S_VER_1 */
#endif /* __iwl_fw_api_rfi_h__ */

View File

@ -0,0 +1,720 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2012-2014, 2018-2020 Intel Corporation
* Copyright (C) 2017 Intel Deutschland GmbH
*/
#ifndef __iwl_fw_api_rs_h__
#define __iwl_fw_api_rs_h__
#include "mac.h"
/**
* enum iwl_tlc_mng_cfg_flags_enum - options for TLC config flags
* @IWL_TLC_MNG_CFG_FLAGS_STBC_MSK: enable STBC. For HE this enables STBC for
* bandwidths <= 80MHz
* @IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK: enable LDPC
* @IWL_TLC_MNG_CFG_FLAGS_HE_STBC_160MHZ_MSK: enable STBC in HE at 160MHz
* bandwidth
* @IWL_TLC_MNG_CFG_FLAGS_HE_DCM_NSS_1_MSK: enable HE Dual Carrier Modulation
* for BPSK (MCS 0) with 1 spatial
* stream
* @IWL_TLC_MNG_CFG_FLAGS_HE_DCM_NSS_2_MSK: enable HE Dual Carrier Modulation
* for BPSK (MCS 0) with 2 spatial
* streams
*/
enum iwl_tlc_mng_cfg_flags {
IWL_TLC_MNG_CFG_FLAGS_STBC_MSK = BIT(0),
IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK = BIT(1),
IWL_TLC_MNG_CFG_FLAGS_HE_STBC_160MHZ_MSK = BIT(2),
IWL_TLC_MNG_CFG_FLAGS_HE_DCM_NSS_1_MSK = BIT(3),
IWL_TLC_MNG_CFG_FLAGS_HE_DCM_NSS_2_MSK = BIT(4),
};
/**
* enum iwl_tlc_mng_cfg_cw - channel width options
* @IWL_TLC_MNG_CH_WIDTH_20MHZ: 20MHZ channel
* @IWL_TLC_MNG_CH_WIDTH_40MHZ: 40MHZ channel
* @IWL_TLC_MNG_CH_WIDTH_80MHZ: 80MHZ channel
* @IWL_TLC_MNG_CH_WIDTH_160MHZ: 160MHZ channel
* @IWL_TLC_MNG_CH_WIDTH_LAST: maximum value
*/
enum iwl_tlc_mng_cfg_cw {
IWL_TLC_MNG_CH_WIDTH_20MHZ,
IWL_TLC_MNG_CH_WIDTH_40MHZ,
IWL_TLC_MNG_CH_WIDTH_80MHZ,
IWL_TLC_MNG_CH_WIDTH_160MHZ,
IWL_TLC_MNG_CH_WIDTH_LAST = IWL_TLC_MNG_CH_WIDTH_160MHZ,
};
/**
* enum iwl_tlc_mng_cfg_chains - possible chains
* @IWL_TLC_MNG_CHAIN_A_MSK: chain A
* @IWL_TLC_MNG_CHAIN_B_MSK: chain B
*/
enum iwl_tlc_mng_cfg_chains {
IWL_TLC_MNG_CHAIN_A_MSK = BIT(0),
IWL_TLC_MNG_CHAIN_B_MSK = BIT(1),
};
/**
* enum iwl_tlc_mng_cfg_mode - supported modes
* @IWL_TLC_MNG_MODE_CCK: enable CCK
* @IWL_TLC_MNG_MODE_OFDM_NON_HT: enable OFDM (non HT)
* @IWL_TLC_MNG_MODE_NON_HT: enable non HT
* @IWL_TLC_MNG_MODE_HT: enable HT
* @IWL_TLC_MNG_MODE_VHT: enable VHT
* @IWL_TLC_MNG_MODE_HE: enable HE
* @IWL_TLC_MNG_MODE_INVALID: invalid value
* @IWL_TLC_MNG_MODE_NUM: a count of possible modes
*/
enum iwl_tlc_mng_cfg_mode {
IWL_TLC_MNG_MODE_CCK = 0,
IWL_TLC_MNG_MODE_OFDM_NON_HT = IWL_TLC_MNG_MODE_CCK,
IWL_TLC_MNG_MODE_NON_HT = IWL_TLC_MNG_MODE_CCK,
IWL_TLC_MNG_MODE_HT,
IWL_TLC_MNG_MODE_VHT,
IWL_TLC_MNG_MODE_HE,
IWL_TLC_MNG_MODE_INVALID,
IWL_TLC_MNG_MODE_NUM = IWL_TLC_MNG_MODE_INVALID,
};
/**
* enum iwl_tlc_mng_ht_rates - HT/VHT/HE rates
* @IWL_TLC_MNG_HT_RATE_MCS0: index of MCS0
* @IWL_TLC_MNG_HT_RATE_MCS1: index of MCS1
* @IWL_TLC_MNG_HT_RATE_MCS2: index of MCS2
* @IWL_TLC_MNG_HT_RATE_MCS3: index of MCS3
* @IWL_TLC_MNG_HT_RATE_MCS4: index of MCS4
* @IWL_TLC_MNG_HT_RATE_MCS5: index of MCS5
* @IWL_TLC_MNG_HT_RATE_MCS6: index of MCS6
* @IWL_TLC_MNG_HT_RATE_MCS7: index of MCS7
* @IWL_TLC_MNG_HT_RATE_MCS8: index of MCS8
* @IWL_TLC_MNG_HT_RATE_MCS9: index of MCS9
* @IWL_TLC_MNG_HT_RATE_MCS10: index of MCS10
* @IWL_TLC_MNG_HT_RATE_MCS11: index of MCS11
* @IWL_TLC_MNG_HT_RATE_MAX: maximal rate for HT/VHT
*/
enum iwl_tlc_mng_ht_rates {
IWL_TLC_MNG_HT_RATE_MCS0 = 0,
IWL_TLC_MNG_HT_RATE_MCS1,
IWL_TLC_MNG_HT_RATE_MCS2,
IWL_TLC_MNG_HT_RATE_MCS3,
IWL_TLC_MNG_HT_RATE_MCS4,
IWL_TLC_MNG_HT_RATE_MCS5,
IWL_TLC_MNG_HT_RATE_MCS6,
IWL_TLC_MNG_HT_RATE_MCS7,
IWL_TLC_MNG_HT_RATE_MCS8,
IWL_TLC_MNG_HT_RATE_MCS9,
IWL_TLC_MNG_HT_RATE_MCS10,
IWL_TLC_MNG_HT_RATE_MCS11,
IWL_TLC_MNG_HT_RATE_MAX = IWL_TLC_MNG_HT_RATE_MCS11,
};
enum IWL_TLC_MNG_NSS {
IWL_TLC_NSS_1,
IWL_TLC_NSS_2,
IWL_TLC_NSS_MAX
};
enum IWL_TLC_HT_BW_RATES {
IWL_TLC_HT_BW_NONE_160,
IWL_TLC_HT_BW_160,
};
/**
* struct tlc_config_cmd - TLC configuration
* @sta_id: station id
* @reserved1: reserved
* @max_ch_width: max supported channel width from @enum iwl_tlc_mng_cfg_cw
* @mode: &enum iwl_tlc_mng_cfg_mode
* @chains: bitmask of &enum iwl_tlc_mng_cfg_chains
* @amsdu: TX amsdu is supported
* @flags: bitmask of &enum iwl_tlc_mng_cfg_flags
* @non_ht_rates: bitmap of supported legacy rates
* @ht_rates: bitmap of &enum iwl_tlc_mng_ht_rates, per <nss, channel-width>
* pair (0 - 80mhz width and below, 1 - 160mhz).
* @max_mpdu_len: max MPDU length, in bytes
* @sgi_ch_width_supp: bitmap of SGI support per channel width
* use BIT(@enum iwl_tlc_mng_cfg_cw)
* @reserved2: reserved
* @max_tx_op: max TXOP in uSecs for all AC (BK, BE, VO, VI),
* set zero for no limit.
*/
struct iwl_tlc_config_cmd {
u8 sta_id;
u8 reserved1[3];
u8 max_ch_width;
u8 mode;
u8 chains;
u8 amsdu;
__le16 flags;
__le16 non_ht_rates;
__le16 ht_rates[IWL_TLC_NSS_MAX][2];
__le16 max_mpdu_len;
u8 sgi_ch_width_supp;
u8 reserved2;
__le32 max_tx_op;
} __packed; /* TLC_MNG_CONFIG_CMD_API_S_VER_3 */
/**
* enum iwl_tlc_update_flags - updated fields
* @IWL_TLC_NOTIF_FLAG_RATE: last initial rate update
* @IWL_TLC_NOTIF_FLAG_AMSDU: umsdu parameters update
*/
enum iwl_tlc_update_flags {
IWL_TLC_NOTIF_FLAG_RATE = BIT(0),
IWL_TLC_NOTIF_FLAG_AMSDU = BIT(1),
};
/**
* struct iwl_tlc_update_notif - TLC notification from FW
* @sta_id: station id
* @reserved: reserved
* @flags: bitmap of notifications reported
* @rate: current initial rate
* @amsdu_size: Max AMSDU size, in bytes
* @amsdu_enabled: bitmap for per-TID AMSDU enablement
*/
struct iwl_tlc_update_notif {
u8 sta_id;
u8 reserved[3];
__le32 flags;
__le32 rate;
__le32 amsdu_size;
__le32 amsdu_enabled;
} __packed; /* TLC_MNG_UPDATE_NTFY_API_S_VER_2 */
#define IWL_MAX_MCS_DISPLAY_SIZE 12
struct iwl_rate_mcs_info {
char mbps[IWL_MAX_MCS_DISPLAY_SIZE];
char mcs[IWL_MAX_MCS_DISPLAY_SIZE];
};
/*
* These serve as indexes into
* struct iwl_rate_info fw_rate_idx_to_plcp[IWL_RATE_COUNT];
* TODO: avoid overlap between legacy and HT rates
*/
enum {
IWL_RATE_1M_INDEX = 0,
IWL_FIRST_CCK_RATE = IWL_RATE_1M_INDEX,
IWL_RATE_2M_INDEX,
IWL_RATE_5M_INDEX,
IWL_RATE_11M_INDEX,
IWL_LAST_CCK_RATE = IWL_RATE_11M_INDEX,
IWL_RATE_6M_INDEX,
IWL_FIRST_OFDM_RATE = IWL_RATE_6M_INDEX,
IWL_RATE_MCS_0_INDEX = IWL_RATE_6M_INDEX,
IWL_FIRST_HT_RATE = IWL_RATE_MCS_0_INDEX,
IWL_FIRST_VHT_RATE = IWL_RATE_MCS_0_INDEX,
IWL_RATE_9M_INDEX,
IWL_RATE_12M_INDEX,
IWL_RATE_MCS_1_INDEX = IWL_RATE_12M_INDEX,
IWL_RATE_18M_INDEX,
IWL_RATE_MCS_2_INDEX = IWL_RATE_18M_INDEX,
IWL_RATE_24M_INDEX,
IWL_RATE_MCS_3_INDEX = IWL_RATE_24M_INDEX,
IWL_RATE_36M_INDEX,
IWL_RATE_MCS_4_INDEX = IWL_RATE_36M_INDEX,
IWL_RATE_48M_INDEX,
IWL_RATE_MCS_5_INDEX = IWL_RATE_48M_INDEX,
IWL_RATE_54M_INDEX,
IWL_RATE_MCS_6_INDEX = IWL_RATE_54M_INDEX,
IWL_LAST_NON_HT_RATE = IWL_RATE_54M_INDEX,
IWL_RATE_60M_INDEX,
IWL_RATE_MCS_7_INDEX = IWL_RATE_60M_INDEX,
IWL_LAST_HT_RATE = IWL_RATE_MCS_7_INDEX,
IWL_RATE_MCS_8_INDEX,
IWL_RATE_MCS_9_INDEX,
IWL_LAST_VHT_RATE = IWL_RATE_MCS_9_INDEX,
IWL_RATE_MCS_10_INDEX,
IWL_RATE_MCS_11_INDEX,
IWL_LAST_HE_RATE = IWL_RATE_MCS_11_INDEX,
IWL_RATE_COUNT_LEGACY = IWL_LAST_NON_HT_RATE + 1,
IWL_RATE_COUNT = IWL_LAST_HE_RATE + 1,
IWL_RATE_INVM_INDEX = IWL_RATE_COUNT,
IWL_RATE_INVALID = IWL_RATE_COUNT,
};
#define IWL_RATE_BIT_MSK(r) BIT(IWL_RATE_##r##M_INDEX)
/* fw API values for legacy bit rates, both OFDM and CCK */
enum {
IWL_RATE_6M_PLCP = 13,
IWL_RATE_9M_PLCP = 15,
IWL_RATE_12M_PLCP = 5,
IWL_RATE_18M_PLCP = 7,
IWL_RATE_24M_PLCP = 9,
IWL_RATE_36M_PLCP = 11,
IWL_RATE_48M_PLCP = 1,
IWL_RATE_54M_PLCP = 3,
IWL_RATE_1M_PLCP = 10,
IWL_RATE_2M_PLCP = 20,
IWL_RATE_5M_PLCP = 55,
IWL_RATE_11M_PLCP = 110,
IWL_RATE_INVM_PLCP = -1,
};
/*
* rate_n_flags bit fields version 1
*
* The 32-bit value has different layouts in the low 8 bites depending on the
* format. There are three formats, HT, VHT and legacy (11abg, with subformats
* for CCK and OFDM).
*
* High-throughput (HT) rate format
* bit 8 is 1, bit 26 is 0, bit 9 is 0 (OFDM)
* Very High-throughput (VHT) rate format
* bit 8 is 0, bit 26 is 1, bit 9 is 0 (OFDM)
* Legacy OFDM rate format for bits 7:0
* bit 8 is 0, bit 26 is 0, bit 9 is 0 (OFDM)
* Legacy CCK rate format for bits 7:0:
* bit 8 is 0, bit 26 is 0, bit 9 is 1 (CCK)
*/
/* Bit 8: (1) HT format, (0) legacy or VHT format */
#define RATE_MCS_HT_POS 8
#define RATE_MCS_HT_MSK_V1 BIT(RATE_MCS_HT_POS)
/* Bit 9: (1) CCK, (0) OFDM. HT (bit 8) must be "0" for this bit to be valid */
#define RATE_MCS_CCK_POS_V1 9
#define RATE_MCS_CCK_MSK_V1 BIT(RATE_MCS_CCK_POS_V1)
/* Bit 26: (1) VHT format, (0) legacy format in bits 8:0 */
#define RATE_MCS_VHT_POS_V1 26
#define RATE_MCS_VHT_MSK_V1 BIT(RATE_MCS_VHT_POS_V1)
/*
* High-throughput (HT) rate format for bits 7:0
*
* 2-0: MCS rate base
* 0) 6 Mbps
* 1) 12 Mbps
* 2) 18 Mbps
* 3) 24 Mbps
* 4) 36 Mbps
* 5) 48 Mbps
* 6) 54 Mbps
* 7) 60 Mbps
* 4-3: 0) Single stream (SISO)
* 1) Dual stream (MIMO)
* 2) Triple stream (MIMO)
* 5: Value of 0x20 in bits 7:0 indicates 6 Mbps HT40 duplicate data
* (bits 7-6 are zero)
*
* Together the low 5 bits work out to the MCS index because we don't
* support MCSes above 15/23, and 0-7 have one stream, 8-15 have two
* streams and 16-23 have three streams. We could also support MCS 32
* which is the duplicate 20 MHz MCS (bit 5 set, all others zero.)
*/
#define RATE_HT_MCS_RATE_CODE_MSK_V1 0x7
#define RATE_HT_MCS_NSS_POS_V1 3
#define RATE_HT_MCS_NSS_MSK_V1 (3 << RATE_HT_MCS_NSS_POS_V1)
#define RATE_HT_MCS_MIMO2_MSK BIT(RATE_HT_MCS_NSS_POS_V1)
/* Bit 10: (1) Use Green Field preamble */
#define RATE_HT_MCS_GF_POS 10
#define RATE_HT_MCS_GF_MSK (1 << RATE_HT_MCS_GF_POS)
#define RATE_HT_MCS_INDEX_MSK_V1 0x3f
/*
* Very High-throughput (VHT) rate format for bits 7:0
*
* 3-0: VHT MCS (0-9)
* 5-4: number of streams - 1:
* 0) Single stream (SISO)
* 1) Dual stream (MIMO)
* 2) Triple stream (MIMO)
*/
/* Bit 4-5: (0) SISO, (1) MIMO2 (2) MIMO3 */
#define RATE_VHT_MCS_RATE_CODE_MSK 0xf
#define RATE_VHT_MCS_NSS_POS 4
#define RATE_VHT_MCS_NSS_MSK (3 << RATE_VHT_MCS_NSS_POS)
#define RATE_VHT_MCS_MIMO2_MSK BIT(RATE_VHT_MCS_NSS_POS)
/*
* Legacy OFDM rate format for bits 7:0
*
* 3-0: 0xD) 6 Mbps
* 0xF) 9 Mbps
* 0x5) 12 Mbps
* 0x7) 18 Mbps
* 0x9) 24 Mbps
* 0xB) 36 Mbps
* 0x1) 48 Mbps
* 0x3) 54 Mbps
* (bits 7-4 are 0)
*
* Legacy CCK rate format for bits 7:0:
* bit 8 is 0, bit 26 is 0, bit 9 is 1 (CCK):
*
* 6-0: 10) 1 Mbps
* 20) 2 Mbps
* 55) 5.5 Mbps
* 110) 11 Mbps
* (bit 7 is 0)
*/
#define RATE_LEGACY_RATE_MSK_V1 0xff
/* Bit 10 - OFDM HE */
#define RATE_MCS_HE_POS_V1 10
#define RATE_MCS_HE_MSK_V1 BIT(RATE_MCS_HE_POS_V1)
/*
* Bit 11-12: (0) 20MHz, (1) 40MHz, (2) 80MHz, (3) 160MHz
* 0 and 1 are valid for HT and VHT, 2 and 3 only for VHT
*/
#define RATE_MCS_CHAN_WIDTH_POS 11
#define RATE_MCS_CHAN_WIDTH_MSK_V1 (3 << RATE_MCS_CHAN_WIDTH_POS)
/* Bit 13: (1) Short guard interval (0.4 usec), (0) normal GI (0.8 usec) */
#define RATE_MCS_SGI_POS_V1 13
#define RATE_MCS_SGI_MSK_V1 BIT(RATE_MCS_SGI_POS_V1)
/* Bit 14-16: Antenna selection (1) Ant A, (2) Ant B, (4) Ant C */
#define RATE_MCS_ANT_POS 14
#define RATE_MCS_ANT_A_MSK (1 << RATE_MCS_ANT_POS)
#define RATE_MCS_ANT_B_MSK (2 << RATE_MCS_ANT_POS)
#define RATE_MCS_ANT_AB_MSK (RATE_MCS_ANT_A_MSK | \
RATE_MCS_ANT_B_MSK)
#define RATE_MCS_ANT_MSK RATE_MCS_ANT_AB_MSK
/* Bit 17: (0) SS, (1) SS*2 */
#define RATE_MCS_STBC_POS 17
#define RATE_MCS_STBC_MSK BIT(RATE_MCS_STBC_POS)
/* Bit 18: OFDM-HE dual carrier mode */
#define RATE_HE_DUAL_CARRIER_MODE 18
#define RATE_HE_DUAL_CARRIER_MODE_MSK BIT(RATE_HE_DUAL_CARRIER_MODE)
/* Bit 19: (0) Beamforming is off, (1) Beamforming is on */
#define RATE_MCS_BF_POS 19
#define RATE_MCS_BF_MSK (1 << RATE_MCS_BF_POS)
/*
* Bit 20-21: HE LTF type and guard interval
* HE (ext) SU:
* 0 1xLTF+0.8us
* 1 2xLTF+0.8us
* 2 2xLTF+1.6us
* 3 & SGI (bit 13) clear 4xLTF+3.2us
* 3 & SGI (bit 13) set 4xLTF+0.8us
* HE MU:
* 0 4xLTF+0.8us
* 1 2xLTF+0.8us
* 2 2xLTF+1.6us
* 3 4xLTF+3.2us
* HE TRIG:
* 0 1xLTF+1.6us
* 1 2xLTF+1.6us
* 2 4xLTF+3.2us
* 3 (does not occur)
*/
#define RATE_MCS_HE_GI_LTF_POS 20
#define RATE_MCS_HE_GI_LTF_MSK_V1 (3 << RATE_MCS_HE_GI_LTF_POS)
/* Bit 22-23: HE type. (0) SU, (1) SU_EXT, (2) MU, (3) trigger based */
#define RATE_MCS_HE_TYPE_POS_V1 22
#define RATE_MCS_HE_TYPE_SU_V1 (0 << RATE_MCS_HE_TYPE_POS_V1)
#define RATE_MCS_HE_TYPE_EXT_SU_V1 BIT(RATE_MCS_HE_TYPE_POS_V1)
#define RATE_MCS_HE_TYPE_MU_V1 (2 << RATE_MCS_HE_TYPE_POS_V1)
#define RATE_MCS_HE_TYPE_TRIG_V1 (3 << RATE_MCS_HE_TYPE_POS_V1)
#define RATE_MCS_HE_TYPE_MSK_V1 (3 << RATE_MCS_HE_TYPE_POS_V1)
/* Bit 24-25: (0) 20MHz (no dup), (1) 2x20MHz, (2) 4x20MHz, 3 8x20MHz */
#define RATE_MCS_DUP_POS_V1 24
#define RATE_MCS_DUP_MSK_V1 (3 << RATE_MCS_DUP_POS_V1)
/* Bit 27: (1) LDPC enabled, (0) LDPC disabled */
#define RATE_MCS_LDPC_POS_V1 27
#define RATE_MCS_LDPC_MSK_V1 BIT(RATE_MCS_LDPC_POS_V1)
/* Bit 28: (1) 106-tone RX (8 MHz RU), (0) normal bandwidth */
#define RATE_MCS_HE_106T_POS_V1 28
#define RATE_MCS_HE_106T_MSK_V1 BIT(RATE_MCS_HE_106T_POS_V1)
/* Bit 30-31: (1) RTS, (2) CTS */
#define RATE_MCS_RTS_REQUIRED_POS (30)
#define RATE_MCS_RTS_REQUIRED_MSK (0x1 << RATE_MCS_RTS_REQUIRED_POS)
#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
*
* 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
* for CCK and OFDM).
*
*/
/* Bits 10-8: rate format
* (0) Legacy CCK (1) Legacy OFDM (2) High-throughput (HT)
* (3) Very High-throughput (VHT) (4) High-efficiency (HE)
* (5) Extremely High-throughput (EHT)
*/
#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)
/*
* 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
*
* Legacy OFDM rate format for bis 3:0:
*
* (0) 6 Mbps
* (1) 9 Mbps
* (2) 12 Mbps
* (3) 18 Mbps
* (4) 24 Mbps
* (5) 36 Mbps
* (6) 48 Mbps
* (7) 54 Mbps
*
*/
#define RATE_LEGACY_RATE_MSK 0x7
/*
* HT, VHT, HE, EHT rate format for bits 3:0
* 3-0: MCS
*
*/
#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) | \
((r) & RATE_HT_MCS_CODE_MSK))
/* Bits 7-5: reserved */
/*
* Bits 13-11: (0) 20MHz, (1) 40MHz, (2) 80MHz, (3) 160MHz, (4) 320MHz
*/
#define RATE_MCS_CHAN_WIDTH_MSK (0x7 << RATE_MCS_CHAN_WIDTH_POS)
#define RATE_MCS_CHAN_WIDTH_20 (0 << RATE_MCS_CHAN_WIDTH_POS)
#define RATE_MCS_CHAN_WIDTH_40 (1 << RATE_MCS_CHAN_WIDTH_POS)
#define RATE_MCS_CHAN_WIDTH_80 (2 << RATE_MCS_CHAN_WIDTH_POS)
#define RATE_MCS_CHAN_WIDTH_160 (3 << RATE_MCS_CHAN_WIDTH_POS)
#define RATE_MCS_CHAN_WIDTH_320 (4 << RATE_MCS_CHAN_WIDTH_POS)
/* Bit 15-14: Antenna selection:
* Bit 14: Ant A active
* Bit 15: Ant B active
*
* All relevant definitions are same as in v1
*/
/* Bit 16 (1) LDPC enables, (0) LDPC disabled */
#define RATE_MCS_LDPC_POS 16
#define RATE_MCS_LDPC_MSK (1 << RATE_MCS_LDPC_POS)
/* Bit 17: (0) SS, (1) SS*2 (same as v1) */
/* Bit 18: OFDM-HE dual carrier mode (same as v1) */
/* Bit 19: (0) Beamforming is off, (1) Beamforming is on (same as v1) */
/*
* Bit 22-20: HE LTF type and guard interval
* CCK:
* 0 long preamble
* 1 short preamble
* HT/VHT:
* 0 0.8us
* 1 0.4us
* HE (ext) SU:
* 0 1xLTF+0.8us
* 1 2xLTF+0.8us
* 2 2xLTF+1.6us
* 3 4xLTF+3.2us
* 4 4xLTF+0.8us
* HE MU:
* 0 4xLTF+0.8us
* 1 2xLTF+0.8us
* 2 2xLTF+1.6us
* 3 4xLTF+3.2us
* HE TRIG:
* 0 1xLTF+1.6us
* 1 2xLTF+1.6us
* 2 4xLTF+3.2us
* */
#define RATE_MCS_HE_GI_LTF_MSK (0x7 << RATE_MCS_HE_GI_LTF_POS)
#define RATE_MCS_SGI_POS RATE_MCS_HE_GI_LTF_POS
#define RATE_MCS_SGI_MSK (1 << RATE_MCS_SGI_POS)
#define RATE_MCS_HE_SU_4_LTF 3
#define RATE_MCS_HE_SU_4_LTF_08_GI 4
/* Bit 24-23: HE type. (0) SU, (1) SU_EXT, (2) MU, (3) trigger based */
#define RATE_MCS_HE_TYPE_POS 23
#define RATE_MCS_HE_TYPE_SU (0 << RATE_MCS_HE_TYPE_POS)
#define RATE_MCS_HE_TYPE_EXT_SU (1 << RATE_MCS_HE_TYPE_POS)
#define RATE_MCS_HE_TYPE_MU (2 << RATE_MCS_HE_TYPE_POS)
#define RATE_MCS_HE_TYPE_TRIG (3 << RATE_MCS_HE_TYPE_POS)
#define RATE_MCS_HE_TYPE_MSK (3 << RATE_MCS_HE_TYPE_POS)
/* Bit 25: duplicate channel enabled
*
* if this bit is set, duplicate is according to BW (bits 11-13):
*
* CCK: 2x 20MHz
* OFDM Legacy: N x 20Mhz, (N = BW \ 2 , either 2, 4, 8, 16)
* EHT: 2 x BW/2, (80 - 2x40, 160 - 2x80, 320 - 2x160)
* */
#define RATE_MCS_DUP_POS 25
#define RATE_MCS_DUP_MSK (1 << RATE_MCS_DUP_POS)
/* Bit 26: (1) 106-tone RX (8 MHz RU), (0) normal bandwidth */
#define RATE_MCS_HE_106T_POS 26
#define RATE_MCS_HE_106T_MSK (1 << RATE_MCS_HE_106T_POS)
/* Bit 27: EHT extra LTF:
* instead of 1 LTF for SISO use 2 LTFs,
* instead of 2 LTFs for NSTS=2 use 4 LTFs*/
#define RATE_MCS_EHT_EXTRA_LTF_POS 27
#define RATE_MCS_EHT_EXTRA_LTF_MSK (1 << RATE_MCS_EHT_EXTRA_LTF_POS)
/* Bit 31-28: reserved */
/* Link Quality definitions */
/* # entries in rate scale table to support Tx retries */
#define LQ_MAX_RETRY_NUM 16
/* Link quality command flags bit fields */
/* Bit 0: (0) Don't use RTS (1) Use RTS */
#define LQ_FLAG_USE_RTS_POS 0
#define LQ_FLAG_USE_RTS_MSK (1 << LQ_FLAG_USE_RTS_POS)
/* Bit 1-3: LQ command color. Used to match responses to LQ commands */
#define LQ_FLAG_COLOR_POS 1
#define LQ_FLAG_COLOR_MSK (7 << LQ_FLAG_COLOR_POS)
#define LQ_FLAG_COLOR_GET(_f) (((_f) & LQ_FLAG_COLOR_MSK) >>\
LQ_FLAG_COLOR_POS)
#define LQ_FLAGS_COLOR_INC(_c) ((((_c) + 1) << LQ_FLAG_COLOR_POS) &\
LQ_FLAG_COLOR_MSK)
#define LQ_FLAG_COLOR_SET(_f, _c) ((_c) | ((_f) & ~LQ_FLAG_COLOR_MSK))
/* Bit 4-5: Tx RTS BW Signalling
* (0) No RTS BW signalling
* (1) Static BW signalling
* (2) Dynamic BW signalling
*/
#define LQ_FLAG_RTS_BW_SIG_POS 4
#define LQ_FLAG_RTS_BW_SIG_NONE (0 << LQ_FLAG_RTS_BW_SIG_POS)
#define LQ_FLAG_RTS_BW_SIG_STATIC (1 << LQ_FLAG_RTS_BW_SIG_POS)
#define LQ_FLAG_RTS_BW_SIG_DYNAMIC (2 << LQ_FLAG_RTS_BW_SIG_POS)
/* Bit 6: (0) No dynamic BW selection (1) Allow dynamic BW selection
* Dyanmic BW selection allows Tx with narrower BW then requested in rates
*/
#define LQ_FLAG_DYNAMIC_BW_POS 6
#define LQ_FLAG_DYNAMIC_BW_MSK (1 << LQ_FLAG_DYNAMIC_BW_POS)
/* Single Stream Tx Parameters (lq_cmd->ss_params)
* Flags to control a smart FW decision about whether BFER/STBC/SISO will be
* used for single stream Tx.
*/
/* Bit 0-1: Max STBC streams allowed. Can be 0-3.
* (0) - No STBC allowed
* (1) - 2x1 STBC allowed (HT/VHT)
* (2) - 4x2 STBC allowed (HT/VHT)
* (3) - 3x2 STBC allowed (HT only)
* All our chips are at most 2 antennas so only (1) is valid for now.
*/
#define LQ_SS_STBC_ALLOWED_POS 0
#define LQ_SS_STBC_ALLOWED_MSK (3 << LQ_SS_STBC_ALLOWED_MSK)
/* 2x1 STBC is allowed */
#define LQ_SS_STBC_1SS_ALLOWED (1 << LQ_SS_STBC_ALLOWED_POS)
/* Bit 2: Beamformer (VHT only) is allowed */
#define LQ_SS_BFER_ALLOWED_POS 2
#define LQ_SS_BFER_ALLOWED (1 << LQ_SS_BFER_ALLOWED_POS)
/* Bit 3: Force BFER or STBC for testing
* If this is set:
* If BFER is allowed then force the ucode to choose BFER else
* If STBC is allowed then force the ucode to choose STBC over SISO
*/
#define LQ_SS_FORCE_POS 3
#define LQ_SS_FORCE (1 << LQ_SS_FORCE_POS)
/* Bit 31: ss_params field is valid. Used for FW backward compatibility
* with other drivers which don't support the ss_params API yet
*/
#define LQ_SS_PARAMS_VALID_POS 31
#define LQ_SS_PARAMS_VALID (1 << LQ_SS_PARAMS_VALID_POS)
/**
* struct iwl_lq_cmd - link quality command
* @sta_id: station to update
* @reduced_tpc: reduced transmit power control value
* @control: not used
* @flags: combination of LQ_FLAG_*
* @mimo_delim: the first SISO index in rs_table, which separates MIMO
* and SISO rates
* @single_stream_ant_msk: best antenna for SISO (can be dual in CDD).
* Should be ANT_[ABC]
* @dual_stream_ant_msk: best antennas for MIMO, combination of ANT_[ABC]
* @initial_rate_index: first index from rs_table per AC category
* @agg_time_limit: aggregation max time threshold in usec/100, meaning
* value of 100 is one usec. Range is 100 to 8000
* @agg_disable_start_th: try-count threshold for starting aggregation.
* If a frame has higher try-count, it should not be selected for
* starting an aggregation sequence.
* @agg_frame_cnt_limit: max frame count in an aggregation.
* 0: no limit
* 1: no aggregation (one frame per aggregation)
* 2 - 0x3f: maximal number of frames (up to 3f == 63)
* @reserved2: reserved
* @rs_table: array of rates for each TX try, each is rate_n_flags,
* meaning it is a combination of RATE_MCS_* and IWL_RATE_*_PLCP
* @ss_params: single stream features. declare whether STBC or BFER are allowed.
*/
struct iwl_lq_cmd {
u8 sta_id;
u8 reduced_tpc;
__le16 control;
/* LINK_QUAL_GENERAL_PARAMS_API_S_VER_1 */
u8 flags;
u8 mimo_delim;
u8 single_stream_ant_msk;
u8 dual_stream_ant_msk;
u8 initial_rate_index[AC_NUM];
/* LINK_QUAL_AGG_PARAMS_API_S_VER_1 */
__le16 agg_time_limit;
u8 agg_disable_start_th;
u8 agg_frame_cnt_limit;
__le32 reserved2;
__le32 rs_table[LQ_MAX_RETRY_NUM];
__le32 ss_params;
}; /* 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);
u32 iwl_legacy_rate_to_fw_idx(u32 rate_n_flags);
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);
#endif /* __iwl_fw_api_rs_h__ */

View File

@ -0,0 +1,852 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2012-2014, 2018-2021 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2015-2017 Intel Deutschland GmbH
*/
#ifndef __iwl_fw_api_rx_h__
#define __iwl_fw_api_rx_h__
/* API for pre-9000 hardware */
#define IWL_RX_INFO_PHY_CNT 8
#define IWL_RX_INFO_ENERGY_ANT_ABC_IDX 1
#define IWL_RX_INFO_ENERGY_ANT_A_MSK 0x000000ff
#define IWL_RX_INFO_ENERGY_ANT_B_MSK 0x0000ff00
#define IWL_RX_INFO_ENERGY_ANT_A_POS 0
#define IWL_RX_INFO_ENERGY_ANT_B_POS 8
#define IWL_RX_INFO_ENERGY_ANT_C_POS 16
enum iwl_mac_context_info {
MAC_CONTEXT_INFO_NONE,
MAC_CONTEXT_INFO_GSCAN,
};
/**
* struct iwl_rx_phy_info - phy info
* (REPLY_RX_PHY_CMD = 0xc0)
* @non_cfg_phy_cnt: non configurable DSP phy data byte count
* @cfg_phy_cnt: configurable DSP phy data byte count
* @stat_id: configurable DSP phy data set ID
* @reserved1: reserved
* @system_timestamp: GP2 at on air rise
* @timestamp: TSF at on air rise
* @beacon_time_stamp: beacon at on-air rise
* @phy_flags: general phy flags: band, modulation, ...
* @channel: channel number
* @non_cfg_phy: for various implementations of non_cfg_phy
* @rate_n_flags: RATE_MCS_*
* @byte_count: frame's byte-count
* @frame_time: frame's time on the air, based on byte count and frame rate
* calculation
* @mac_active_msk: what MACs were active when the frame was received
* @mac_context_info: additional info on the context in which the frame was
* received as defined in &enum iwl_mac_context_info
*
* Before each Rx, the device sends this data. It contains PHY information
* about the reception of the packet.
*/
struct iwl_rx_phy_info {
u8 non_cfg_phy_cnt;
u8 cfg_phy_cnt;
u8 stat_id;
u8 reserved1;
__le32 system_timestamp;
__le64 timestamp;
__le32 beacon_time_stamp;
__le16 phy_flags;
__le16 channel;
__le32 non_cfg_phy[IWL_RX_INFO_PHY_CNT];
__le32 rate_n_flags;
__le32 byte_count;
u8 mac_active_msk;
u8 mac_context_info;
__le16 frame_time;
} __packed;
/*
* TCP offload Rx assist info
*
* bits 0:3 - reserved
* bits 4:7 - MIC CRC length
* bits 8:12 - MAC header length
* bit 13 - Padding indication
* bit 14 - A-AMSDU indication
* bit 15 - Offload enabled
*/
enum iwl_csum_rx_assist_info {
CSUM_RXA_RESERVED_MASK = 0x000f,
CSUM_RXA_MICSIZE_MASK = 0x00f0,
CSUM_RXA_HEADERLEN_MASK = 0x1f00,
CSUM_RXA_PADD = BIT(13),
CSUM_RXA_AMSDU = BIT(14),
CSUM_RXA_ENA = BIT(15)
};
/**
* struct iwl_rx_mpdu_res_start - phy info
* @byte_count: byte count of the frame
* @assist: see &enum iwl_csum_rx_assist_info
*/
struct iwl_rx_mpdu_res_start {
__le16 byte_count;
__le16 assist;
} __packed; /* _RX_MPDU_RES_START_API_S_VER_2 */
/**
* enum iwl_rx_phy_flags - to parse %iwl_rx_phy_info phy_flags
* @RX_RES_PHY_FLAGS_BAND_24: true if the packet was received on 2.4 band
* @RX_RES_PHY_FLAGS_MOD_CCK: modulation is CCK
* @RX_RES_PHY_FLAGS_SHORT_PREAMBLE: true if packet's preamble was short
* @RX_RES_PHY_FLAGS_NARROW_BAND: narrow band (<20 MHz) receive
* @RX_RES_PHY_FLAGS_ANTENNA: antenna on which the packet was received
* @RX_RES_PHY_FLAGS_ANTENNA_POS: antenna bit position
* @RX_RES_PHY_FLAGS_AGG: set if the packet was part of an A-MPDU
* @RX_RES_PHY_FLAGS_OFDM_HT: The frame was an HT frame
* @RX_RES_PHY_FLAGS_OFDM_GF: The frame used GF preamble
* @RX_RES_PHY_FLAGS_OFDM_VHT: The frame was a VHT frame
*/
enum iwl_rx_phy_flags {
RX_RES_PHY_FLAGS_BAND_24 = BIT(0),
RX_RES_PHY_FLAGS_MOD_CCK = BIT(1),
RX_RES_PHY_FLAGS_SHORT_PREAMBLE = BIT(2),
RX_RES_PHY_FLAGS_NARROW_BAND = BIT(3),
RX_RES_PHY_FLAGS_ANTENNA = (0x7 << 4),
RX_RES_PHY_FLAGS_ANTENNA_POS = 4,
RX_RES_PHY_FLAGS_AGG = BIT(7),
RX_RES_PHY_FLAGS_OFDM_HT = BIT(8),
RX_RES_PHY_FLAGS_OFDM_GF = BIT(9),
RX_RES_PHY_FLAGS_OFDM_VHT = BIT(10),
};
/**
* enum iwl_mvm_rx_status - written by fw for each Rx packet
* @RX_MPDU_RES_STATUS_CRC_OK: CRC is fine
* @RX_MPDU_RES_STATUS_OVERRUN_OK: there was no RXE overflow
* @RX_MPDU_RES_STATUS_SRC_STA_FOUND: station was found
* @RX_MPDU_RES_STATUS_KEY_VALID: key was valid
* @RX_MPDU_RES_STATUS_ICV_OK: ICV is fine, if not, the packet is destroyed
* @RX_MPDU_RES_STATUS_MIC_OK: used for CCM alg only. TKIP MIC is checked
* in the driver.
* @RX_MPDU_RES_STATUS_TTAK_OK: TTAK is fine
* @RX_MPDU_RES_STATUS_MNG_FRAME_REPLAY_ERR: valid for alg = CCM_CMAC or
* alg = CCM only. Checks replay attack for 11w frames.
* @RX_MPDU_RES_STATUS_SEC_NO_ENC: this frame is not encrypted
* @RX_MPDU_RES_STATUS_SEC_WEP_ENC: this frame is encrypted using WEP
* @RX_MPDU_RES_STATUS_SEC_CCM_ENC: this frame is encrypted using CCM
* @RX_MPDU_RES_STATUS_SEC_TKIP_ENC: this frame is encrypted using TKIP
* @RX_MPDU_RES_STATUS_SEC_EXT_ENC: this frame is encrypted using extension
* algorithm
* @RX_MPDU_RES_STATUS_SEC_CMAC_GMAC_ENC: this frame is protected using
* CMAC or GMAC
* @RX_MPDU_RES_STATUS_SEC_ENC_ERR: this frame couldn't be decrypted
* @RX_MPDU_RES_STATUS_SEC_ENC_MSK: bitmask of the encryption algorithm
* @RX_MPDU_RES_STATUS_DEC_DONE: this frame has been successfully decrypted
* @RX_MPDU_RES_STATUS_CSUM_DONE: checksum was done by the hw
* @RX_MPDU_RES_STATUS_CSUM_OK: checksum found no errors
* @RX_MPDU_RES_STATUS_STA_ID_MSK: station ID mask
* @RX_MDPU_RES_STATUS_STA_ID_SHIFT: station ID bit shift
*/
enum iwl_mvm_rx_status {
RX_MPDU_RES_STATUS_CRC_OK = BIT(0),
RX_MPDU_RES_STATUS_OVERRUN_OK = BIT(1),
RX_MPDU_RES_STATUS_SRC_STA_FOUND = BIT(2),
RX_MPDU_RES_STATUS_KEY_VALID = BIT(3),
RX_MPDU_RES_STATUS_ICV_OK = BIT(5),
RX_MPDU_RES_STATUS_MIC_OK = BIT(6),
RX_MPDU_RES_STATUS_TTAK_OK = BIT(7),
RX_MPDU_RES_STATUS_MNG_FRAME_REPLAY_ERR = BIT(7),
RX_MPDU_RES_STATUS_SEC_NO_ENC = (0 << 8),
RX_MPDU_RES_STATUS_SEC_WEP_ENC = (1 << 8),
RX_MPDU_RES_STATUS_SEC_CCM_ENC = (2 << 8),
RX_MPDU_RES_STATUS_SEC_TKIP_ENC = (3 << 8),
RX_MPDU_RES_STATUS_SEC_EXT_ENC = (4 << 8),
RX_MPDU_RES_STATUS_SEC_CMAC_GMAC_ENC = (6 << 8),
RX_MPDU_RES_STATUS_SEC_ENC_ERR = (7 << 8),
RX_MPDU_RES_STATUS_SEC_ENC_MSK = (7 << 8),
RX_MPDU_RES_STATUS_DEC_DONE = BIT(11),
RX_MPDU_RES_STATUS_CSUM_DONE = BIT(16),
RX_MPDU_RES_STATUS_CSUM_OK = BIT(17),
RX_MDPU_RES_STATUS_STA_ID_SHIFT = 24,
RX_MPDU_RES_STATUS_STA_ID_MSK = 0x1f << RX_MDPU_RES_STATUS_STA_ID_SHIFT,
};
/* 9000 series API */
enum iwl_rx_mpdu_mac_flags1 {
IWL_RX_MDPU_MFLG1_ADDRTYPE_MASK = 0x03,
IWL_RX_MPDU_MFLG1_MIC_CRC_LEN_MASK = 0xf0,
/* shift should be 4, but the length is measured in 2-byte
* words, so shifting only by 3 gives a byte result
*/
IWL_RX_MPDU_MFLG1_MIC_CRC_LEN_SHIFT = 3,
};
enum iwl_rx_mpdu_mac_flags2 {
/* in 2-byte words */
IWL_RX_MPDU_MFLG2_HDR_LEN_MASK = 0x1f,
IWL_RX_MPDU_MFLG2_PAD = 0x20,
IWL_RX_MPDU_MFLG2_AMSDU = 0x40,
};
enum iwl_rx_mpdu_amsdu_info {
IWL_RX_MPDU_AMSDU_SUBFRAME_IDX_MASK = 0x7f,
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_l3_proto_values {
IWL_RX_L3_TYPE_NONE,
IWL_RX_L3_TYPE_IPV4,
IWL_RX_L3_TYPE_IPV4_FRAG,
IWL_RX_L3_TYPE_IPV6_FRAG,
IWL_RX_L3_TYPE_IPV6,
IWL_RX_L3_TYPE_IPV6_IN_IPV4,
IWL_RX_L3_TYPE_ARP,
IWL_RX_L3_TYPE_EAPOL,
};
#define IWL_RX_L3_PROTO_POS 4
enum iwl_rx_l3l4_flags {
IWL_RX_L3L4_IP_HDR_CSUM_OK = BIT(0),
IWL_RX_L3L4_TCP_UDP_CSUM_OK = BIT(1),
IWL_RX_L3L4_TCP_FIN_SYN_RST_PSH = BIT(2),
IWL_RX_L3L4_TCP_ACK = BIT(3),
IWL_RX_L3L4_L3_PROTO_MASK = 0xf << IWL_RX_L3_PROTO_POS,
IWL_RX_L3L4_L4_PROTO_MASK = 0xf << 8,
IWL_RX_L3L4_RSS_HASH_MASK = 0xf << 12,
};
enum iwl_rx_mpdu_status {
IWL_RX_MPDU_STATUS_CRC_OK = BIT(0),
IWL_RX_MPDU_STATUS_OVERRUN_OK = BIT(1),
IWL_RX_MPDU_STATUS_SRC_STA_FOUND = BIT(2),
IWL_RX_MPDU_STATUS_KEY_VALID = BIT(3),
IWL_RX_MPDU_STATUS_ICV_OK = BIT(5),
IWL_RX_MPDU_STATUS_MIC_OK = BIT(6),
IWL_RX_MPDU_RES_STATUS_TTAK_OK = BIT(7),
/* overlayed since IWL_UCODE_TLV_API_DEPRECATE_TTAK */
IWL_RX_MPDU_STATUS_REPLAY_ERROR = BIT(7),
IWL_RX_MPDU_STATUS_SEC_MASK = 0x7 << 8,
IWL_RX_MPDU_STATUS_SEC_UNKNOWN = IWL_RX_MPDU_STATUS_SEC_MASK,
IWL_RX_MPDU_STATUS_SEC_NONE = 0x0 << 8,
IWL_RX_MPDU_STATUS_SEC_WEP = 0x1 << 8,
IWL_RX_MPDU_STATUS_SEC_CCM = 0x2 << 8,
IWL_RX_MPDU_STATUS_SEC_TKIP = 0x3 << 8,
IWL_RX_MPDU_STATUS_SEC_EXT_ENC = 0x4 << 8,
IWL_RX_MPDU_STATUS_SEC_GCM = 0x5 << 8,
#if defined(__FreeBSD__)
IWL_RX_MPDU_STATUS_SEC_ENC_ERR = 0x7 << 8,
#endif
IWL_RX_MPDU_STATUS_DECRYPTED = BIT(11),
IWL_RX_MPDU_STATUS_ROBUST_MNG_FRAME = BIT(15),
IWL_RX_MPDU_STATUS_DUPLICATE = BIT(22),
IWL_RX_MPDU_STATUS_STA_ID = 0x1f000000,
};
#define IWL_RX_REORDER_DATA_INVALID_BAID 0x7f
enum iwl_rx_mpdu_reorder_data {
IWL_RX_MPDU_REORDER_NSSN_MASK = 0x00000fff,
IWL_RX_MPDU_REORDER_SN_MASK = 0x00fff000,
IWL_RX_MPDU_REORDER_SN_SHIFT = 12,
IWL_RX_MPDU_REORDER_BAID_MASK = 0x7f000000,
IWL_RX_MPDU_REORDER_BAID_SHIFT = 24,
IWL_RX_MPDU_REORDER_BA_OLD_SN = 0x80000000,
};
enum iwl_rx_mpdu_phy_info {
IWL_RX_MPDU_PHY_AMPDU = BIT(5),
IWL_RX_MPDU_PHY_AMPDU_TOGGLE = BIT(6),
IWL_RX_MPDU_PHY_SHORT_PREAMBLE = BIT(7),
/* short preamble is only for CCK, for non-CCK overridden by this */
IWL_RX_MPDU_PHY_NCCK_ADDTL_NTFY = BIT(7),
IWL_RX_MPDU_PHY_TSF_OVERLOAD = BIT(8),
};
enum iwl_rx_mpdu_mac_info {
IWL_RX_MPDU_PHY_MAC_INDEX_MASK = 0x0f,
IWL_RX_MPDU_PHY_PHY_INDEX_MASK = 0xf0,
};
/* TSF overload low dword */
enum iwl_rx_phy_data0 {
/* info type: HE any */
IWL_RX_PHY_DATA0_HE_BEAM_CHNG = 0x00000001,
IWL_RX_PHY_DATA0_HE_UPLINK = 0x00000002,
IWL_RX_PHY_DATA0_HE_BSS_COLOR_MASK = 0x000000fc,
IWL_RX_PHY_DATA0_HE_SPATIAL_REUSE_MASK = 0x00000f00,
/* 1 bit reserved */
IWL_RX_PHY_DATA0_HE_TXOP_DUR_MASK = 0x000fe000,
IWL_RX_PHY_DATA0_HE_LDPC_EXT_SYM = 0x00100000,
IWL_RX_PHY_DATA0_HE_PRE_FEC_PAD_MASK = 0x00600000,
IWL_RX_PHY_DATA0_HE_PE_DISAMBIG = 0x00800000,
IWL_RX_PHY_DATA0_HE_DOPPLER = 0x01000000,
/* 6 bits reserved */
IWL_RX_PHY_DATA0_HE_DELIM_EOF = 0x80000000,
};
enum iwl_rx_phy_info_type {
IWL_RX_PHY_INFO_TYPE_NONE = 0,
IWL_RX_PHY_INFO_TYPE_CCK = 1,
IWL_RX_PHY_INFO_TYPE_OFDM_LGCY = 2,
IWL_RX_PHY_INFO_TYPE_HT = 3,
IWL_RX_PHY_INFO_TYPE_VHT_SU = 4,
IWL_RX_PHY_INFO_TYPE_VHT_MU = 5,
IWL_RX_PHY_INFO_TYPE_HE_SU = 6,
IWL_RX_PHY_INFO_TYPE_HE_MU = 7,
IWL_RX_PHY_INFO_TYPE_HE_TB = 8,
IWL_RX_PHY_INFO_TYPE_HE_MU_EXT = 9,
IWL_RX_PHY_INFO_TYPE_HE_TB_EXT = 10,
};
/* TSF overload high dword */
enum iwl_rx_phy_data1 {
/*
* check this first - if TSF overload is set,
* see &enum iwl_rx_phy_info_type
*/
IWL_RX_PHY_DATA1_INFO_TYPE_MASK = 0xf0000000,
/* info type: HT/VHT/HE any */
IWL_RX_PHY_DATA1_LSIG_LEN_MASK = 0x0fff0000,
/* info type: HE MU/MU-EXT */
IWL_RX_PHY_DATA1_HE_MU_SIGB_COMPRESSION = 0x00000001,
IWL_RX_PHY_DATA1_HE_MU_SIBG_SYM_OR_USER_NUM_MASK = 0x0000001e,
/* info type: HE any */
IWL_RX_PHY_DATA1_HE_LTF_NUM_MASK = 0x000000e0,
IWL_RX_PHY_DATA1_HE_RU_ALLOC_SEC80 = 0x00000100,
/* trigger encoded */
IWL_RX_PHY_DATA1_HE_RU_ALLOC_MASK = 0x0000fe00,
/* info type: HE TB/TX-EXT */
IWL_RX_PHY_DATA1_HE_TB_PILOT_TYPE = 0x00000001,
IWL_RX_PHY_DATA1_HE_TB_LOW_SS_MASK = 0x0000000e,
};
/* goes into Metadata DW 7 */
enum iwl_rx_phy_data2 {
/* info type: HE MU-EXT */
/* the a1/a2/... is what the PHY/firmware calls the values */
IWL_RX_PHY_DATA2_HE_MU_EXT_CH1_RU0 = 0x000000ff, /* a1 */
IWL_RX_PHY_DATA2_HE_MU_EXT_CH1_RU2 = 0x0000ff00, /* a2 */
IWL_RX_PHY_DATA2_HE_MU_EXT_CH2_RU0 = 0x00ff0000, /* b1 */
IWL_RX_PHY_DATA2_HE_MU_EXT_CH2_RU2 = 0xff000000, /* b2 */
/* info type: HE TB-EXT */
IWL_RX_PHY_DATA2_HE_TB_EXT_SPTL_REUSE1 = 0x0000000f,
IWL_RX_PHY_DATA2_HE_TB_EXT_SPTL_REUSE2 = 0x000000f0,
IWL_RX_PHY_DATA2_HE_TB_EXT_SPTL_REUSE3 = 0x00000f00,
IWL_RX_PHY_DATA2_HE_TB_EXT_SPTL_REUSE4 = 0x0000f000,
};
/* goes into Metadata DW 8 */
enum iwl_rx_phy_data3 {
/* info type: HE MU-EXT */
IWL_RX_PHY_DATA3_HE_MU_EXT_CH1_RU1 = 0x000000ff, /* c1 */
IWL_RX_PHY_DATA3_HE_MU_EXT_CH1_RU3 = 0x0000ff00, /* c2 */
IWL_RX_PHY_DATA3_HE_MU_EXT_CH2_RU1 = 0x00ff0000, /* d1 */
IWL_RX_PHY_DATA3_HE_MU_EXT_CH2_RU3 = 0xff000000, /* d2 */
};
/* goes into Metadata DW 4 high 16 bits */
enum iwl_rx_phy_data4 {
/* info type: HE MU-EXT */
IWL_RX_PHY_DATA4_HE_MU_EXT_CH1_CTR_RU = 0x0001,
IWL_RX_PHY_DATA4_HE_MU_EXT_CH2_CTR_RU = 0x0002,
IWL_RX_PHY_DATA4_HE_MU_EXT_CH1_CRC_OK = 0x0004,
IWL_RX_PHY_DATA4_HE_MU_EXT_CH2_CRC_OK = 0x0008,
IWL_RX_PHY_DATA4_HE_MU_EXT_SIGB_MCS_MASK = 0x00f0,
IWL_RX_PHY_DATA4_HE_MU_EXT_SIGB_DCM = 0x0100,
IWL_RX_PHY_DATA4_HE_MU_EXT_PREAMBLE_PUNC_TYPE_MASK = 0x0600,
};
/**
* struct iwl_rx_mpdu_desc_v1 - RX MPDU descriptor
*/
struct iwl_rx_mpdu_desc_v1 {
/* DW7 - carries rss_hash only when rpa_en == 1 */
union {
/**
* @rss_hash: RSS hash value
*/
__le32 rss_hash;
/**
* @phy_data2: depends on info type (see @phy_data1)
*/
__le32 phy_data2;
};
/* DW8 - carries filter_match only when rpa_en == 1 */
union {
/**
* @filter_match: filter match value
*/
__le32 filter_match;
/**
* @phy_data3: depends on info type (see @phy_data1)
*/
__le32 phy_data3;
};
/* DW9 */
/**
* @rate_n_flags: RX rate/flags encoding
*/
__le32 rate_n_flags;
/* DW10 */
/**
* @energy_a: energy chain A
*/
u8 energy_a;
/**
* @energy_b: energy chain B
*/
u8 energy_b;
/**
* @channel: channel number
*/
u8 channel;
/**
* @mac_context: MAC context mask
*/
u8 mac_context;
/* DW11 */
/**
* @gp2_on_air_rise: GP2 timer value on air rise (INA)
*/
__le32 gp2_on_air_rise;
/* DW12 & DW13 */
union {
/**
* @tsf_on_air_rise:
* TSF value on air rise (INA), only valid if
* %IWL_RX_MPDU_PHY_TSF_OVERLOAD isn't set
*/
__le64 tsf_on_air_rise;
struct {
/**
* @phy_data0: depends on info_type, see @phy_data1
*/
__le32 phy_data0;
/**
* @phy_data1: valid only if
* %IWL_RX_MPDU_PHY_TSF_OVERLOAD is set,
* see &enum iwl_rx_phy_data1.
*/
__le32 phy_data1;
};
};
} __packed; /* RX_MPDU_RES_START_API_S_VER_4 */
/**
* struct iwl_rx_mpdu_desc_v3 - RX MPDU descriptor
*/
struct iwl_rx_mpdu_desc_v3 {
/* DW7 - carries filter_match only when rpa_en == 1 */
union {
/**
* @filter_match: filter match value
*/
__le32 filter_match;
/**
* @phy_data3: depends on info type (see @phy_data1)
*/
__le32 phy_data3;
};
/* DW8 - carries rss_hash only when rpa_en == 1 */
union {
/**
* @rss_hash: RSS hash value
*/
__le32 rss_hash;
/**
* @phy_data2: depends on info type (see @phy_data1)
*/
__le32 phy_data2;
};
/* DW9 */
/**
* @partial_hash: 31:0 ip/tcp header hash
* w/o some fields (such as IP SRC addr)
*/
__le32 partial_hash;
/* DW10 */
/**
* @raw_xsum: raw xsum value
*/
__be16 raw_xsum;
/**
* @reserved_xsum: reserved high bits in the raw checksum
*/
__le16 reserved_xsum;
/* DW11 */
/**
* @rate_n_flags: RX rate/flags encoding
*/
__le32 rate_n_flags;
/* DW12 */
/**
* @energy_a: energy chain A
*/
u8 energy_a;
/**
* @energy_b: energy chain B
*/
u8 energy_b;
/**
* @channel: channel number
*/
u8 channel;
/**
* @mac_context: MAC context mask
*/
u8 mac_context;
/* DW13 */
/**
* @gp2_on_air_rise: GP2 timer value on air rise (INA)
*/
__le32 gp2_on_air_rise;
/* DW14 & DW15 */
union {
/**
* @tsf_on_air_rise:
* TSF value on air rise (INA), only valid if
* %IWL_RX_MPDU_PHY_TSF_OVERLOAD isn't set
*/
__le64 tsf_on_air_rise;
struct {
/**
* @phy_data0: depends on info_type, see @phy_data1
*/
__le32 phy_data0;
/**
* @phy_data1: valid only if
* %IWL_RX_MPDU_PHY_TSF_OVERLOAD is set,
* see &enum iwl_rx_phy_data1.
*/
__le32 phy_data1;
};
};
/* DW16 & DW17 */
/**
* @reserved: reserved
*/
__le32 reserved[2];
} __packed; /* RX_MPDU_RES_START_API_S_VER_3,
RX_MPDU_RES_START_API_S_VER_5 */
/**
* struct iwl_rx_mpdu_desc - RX MPDU descriptor
*/
struct iwl_rx_mpdu_desc {
/* DW2 */
/**
* @mpdu_len: MPDU length
*/
__le16 mpdu_len;
/**
* @mac_flags1: &enum iwl_rx_mpdu_mac_flags1
*/
u8 mac_flags1;
/**
* @mac_flags2: &enum iwl_rx_mpdu_mac_flags2
*/
u8 mac_flags2;
/* DW3 */
/**
* @amsdu_info: &enum iwl_rx_mpdu_amsdu_info
*/
u8 amsdu_info;
/**
* @phy_info: &enum iwl_rx_mpdu_phy_info
*/
__le16 phy_info;
/**
* @mac_phy_idx: MAC/PHY index
*/
u8 mac_phy_idx;
/* DW4 - carries csum data only when rpa_en == 1 */
/**
* @raw_csum: raw checksum (alledgedly unreliable)
*/
__le16 raw_csum;
union {
/**
* @l3l4_flags: &enum iwl_rx_l3l4_flags
*/
__le16 l3l4_flags;
/**
* @phy_data4: depends on info type, see phy_data1
*/
__le16 phy_data4;
};
/* DW5 */
/**
* @status: &enum iwl_rx_mpdu_status
*/
__le32 status;
/* DW6 */
/**
* @reorder_data: &enum iwl_rx_mpdu_reorder_data
*/
__le32 reorder_data;
union {
struct iwl_rx_mpdu_desc_v1 v1;
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 */
#define IWL_RX_DESC_SIZE_V1 offsetofend(struct iwl_rx_mpdu_desc, v1)
#define RX_NO_DATA_CHAIN_A_POS 0
#define RX_NO_DATA_CHAIN_A_MSK (0xff << RX_NO_DATA_CHAIN_A_POS)
#define RX_NO_DATA_CHAIN_B_POS 8
#define RX_NO_DATA_CHAIN_B_MSK (0xff << RX_NO_DATA_CHAIN_B_POS)
#define RX_NO_DATA_CHANNEL_POS 16
#define RX_NO_DATA_CHANNEL_MSK (0xff << RX_NO_DATA_CHANNEL_POS)
#define RX_NO_DATA_INFO_TYPE_POS 0
#define RX_NO_DATA_INFO_TYPE_MSK (0xff << RX_NO_DATA_INFO_TYPE_POS)
#define RX_NO_DATA_INFO_TYPE_NONE 0
#define RX_NO_DATA_INFO_TYPE_RX_ERR 1
#define RX_NO_DATA_INFO_TYPE_NDP 2
#define RX_NO_DATA_INFO_TYPE_MU_UNMATCHED 3
#define RX_NO_DATA_INFO_TYPE_HE_TB_UNMATCHED 4
#define RX_NO_DATA_INFO_ERR_POS 8
#define RX_NO_DATA_INFO_ERR_MSK (0xff << RX_NO_DATA_INFO_ERR_POS)
#define RX_NO_DATA_INFO_ERR_NONE 0
#define RX_NO_DATA_INFO_ERR_BAD_PLCP 1
#define RX_NO_DATA_INFO_ERR_UNSUPPORTED_RATE 2
#define RX_NO_DATA_INFO_ERR_NO_DELIM 3
#define RX_NO_DATA_INFO_ERR_BAD_MAC_HDR 4
#define RX_NO_DATA_FRAME_TIME_POS 0
#define RX_NO_DATA_FRAME_TIME_MSK (0xfffff << RX_NO_DATA_FRAME_TIME_POS)
#define RX_NO_DATA_RX_VEC0_HE_NSTS_MSK 0x03800000
#define RX_NO_DATA_RX_VEC0_VHT_NSTS_MSK 0x38000000
/**
* struct iwl_rx_no_data - RX no data descriptor
* @info: 7:0 frame type, 15:8 RX error type
* @rssi: 7:0 energy chain-A,
* 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
* @phy_info: &enum iwl_rx_phy_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
* for HE: OFDM_RX_VECTOR_HE_SIGA1_OUT, OFDM_RX_VECTOR_HE_SIGA2_OUT
*/
struct iwl_rx_no_data {
__le32 info;
__le32 rssi;
__le32 on_air_rise_time;
__le32 fr_time;
__le32 rate;
__le32 phy_info[2];
__le32 rx_vec[2];
} __packed; /* RX_NO_DATA_NTFY_API_S_VER_1,
TX_NO_DATA_NTFY_API_S_VER_2 */
struct iwl_frame_release {
u8 baid;
u8 reserved;
__le16 nssn;
};
/**
* enum iwl_bar_frame_release_sta_tid - STA/TID information for BAR release
* @IWL_BAR_FRAME_RELEASE_TID_MASK: TID mask
* @IWL_BAR_FRAME_RELEASE_STA_MASK: STA mask
*/
enum iwl_bar_frame_release_sta_tid {
IWL_BAR_FRAME_RELEASE_TID_MASK = 0x0000000f,
IWL_BAR_FRAME_RELEASE_STA_MASK = 0x000001f0,
};
/**
* enum iwl_bar_frame_release_ba_info - BA information for BAR release
* @IWL_BAR_FRAME_RELEASE_NSSN_MASK: NSSN mask
* @IWL_BAR_FRAME_RELEASE_SN_MASK: SN mask (ignored by driver)
* @IWL_BAR_FRAME_RELEASE_BAID_MASK: BAID mask
*/
enum iwl_bar_frame_release_ba_info {
IWL_BAR_FRAME_RELEASE_NSSN_MASK = 0x00000fff,
IWL_BAR_FRAME_RELEASE_SN_MASK = 0x00fff000,
IWL_BAR_FRAME_RELEASE_BAID_MASK = 0x3f000000,
};
/**
* struct iwl_bar_frame_release - frame release from BAR info
* @sta_tid: STA & TID information, see &enum iwl_bar_frame_release_sta_tid.
* @ba_info: BA information, see &enum iwl_bar_frame_release_ba_info.
*/
struct iwl_bar_frame_release {
__le32 sta_tid;
__le32 ba_info;
} __packed; /* RX_BAR_TO_FRAME_RELEASE_API_S_VER_1 */
enum iwl_rss_hash_func_en {
IWL_RSS_HASH_TYPE_IPV4_TCP,
IWL_RSS_HASH_TYPE_IPV4_UDP,
IWL_RSS_HASH_TYPE_IPV4_PAYLOAD,
IWL_RSS_HASH_TYPE_IPV6_TCP,
IWL_RSS_HASH_TYPE_IPV6_UDP,
IWL_RSS_HASH_TYPE_IPV6_PAYLOAD,
};
#define IWL_RSS_HASH_KEY_CNT 10
#define IWL_RSS_INDIRECTION_TABLE_SIZE 128
#define IWL_RSS_ENABLE 1
/**
* struct iwl_rss_config_cmd - RSS (Receive Side Scaling) configuration
*
* @flags: 1 - enable, 0 - disable
* @hash_mask: Type of RSS to use. Values are from %iwl_rss_hash_func_en
* @reserved: reserved
* @secret_key: 320 bit input of random key configuration from driver
* @indirection_table: indirection table
*/
struct iwl_rss_config_cmd {
__le32 flags;
u8 hash_mask;
u8 reserved[3];
__le32 secret_key[IWL_RSS_HASH_KEY_CNT];
u8 indirection_table[IWL_RSS_INDIRECTION_TABLE_SIZE];
} __packed; /* RSS_CONFIG_CMD_API_S_VER_1 */
#define IWL_MULTI_QUEUE_SYNC_SENDER_POS 0
#define IWL_MULTI_QUEUE_SYNC_SENDER_MSK 0xf
/**
* struct iwl_rxq_sync_cmd - RXQ notification trigger
*
* @flags: flags of the notification. bit 0:3 are the sender queue
* @rxq_mask: rx queues to send the notification on
* @count: number of bytes in payload, should be DWORD aligned
* @payload: data to send to rx queues
*/
struct iwl_rxq_sync_cmd {
__le32 flags;
__le32 rxq_mask;
__le32 count;
u8 payload[0];
} __packed; /* MULTI_QUEUE_DRV_SYNC_HDR_CMD_API_S_VER_1 */
/**
* struct iwl_rxq_sync_notification - Notification triggered by RXQ
* sync command
*
* @count: number of bytes in payload
* @payload: data to send to rx queues
*/
struct iwl_rxq_sync_notification {
__le32 count;
u8 payload[0];
} __packed; /* MULTI_QUEUE_DRV_SYNC_HDR_CMD_API_S_VER_1 */
/**
* enum iwl_mvm_pm_event - type of station PM event
* @IWL_MVM_PM_EVENT_AWAKE: station woke up
* @IWL_MVM_PM_EVENT_ASLEEP: station went to sleep
* @IWL_MVM_PM_EVENT_UAPSD: station sent uAPSD trigger
* @IWL_MVM_PM_EVENT_PS_POLL: station sent PS-Poll
*/
enum iwl_mvm_pm_event {
IWL_MVM_PM_EVENT_AWAKE,
IWL_MVM_PM_EVENT_ASLEEP,
IWL_MVM_PM_EVENT_UAPSD,
IWL_MVM_PM_EVENT_PS_POLL,
}; /* PEER_PM_NTFY_API_E_VER_1 */
/**
* struct iwl_mvm_pm_state_notification - station PM state notification
* @sta_id: station ID of the station changing state
* @type: the new powersave state, see &enum iwl_mvm_pm_event
*/
struct iwl_mvm_pm_state_notification {
u8 sta_id;
u8 type;
/* private: */
__le16 reserved;
} __packed; /* PEER_PM_NTFY_API_S_VER_1 */
#define BA_WINDOW_STREAMS_MAX 16
#define BA_WINDOW_STATUS_TID_MSK 0x000F
#define BA_WINDOW_STATUS_STA_ID_POS 4
#define BA_WINDOW_STATUS_STA_ID_MSK 0x01F0
#define BA_WINDOW_STATUS_VALID_MSK BIT(9)
/**
* struct iwl_ba_window_status_notif - reordering window's status notification
* @bitmap: bitmap of received frames [start_seq_num + 0]..[start_seq_num + 63]
* @ra_tid: bit 3:0 - TID, bit 8:4 - STA_ID, bit 9 - valid
* @start_seq_num: the start sequence number of the bitmap
* @mpdu_rx_count: the number of received MPDUs since entering D0i3
*/
struct iwl_ba_window_status_notif {
__le64 bitmap[BA_WINDOW_STREAMS_MAX];
__le16 ra_tid[BA_WINDOW_STREAMS_MAX];
__le32 start_seq_num[BA_WINDOW_STREAMS_MAX];
__le16 mpdu_rx_count[BA_WINDOW_STREAMS_MAX];
} __packed; /* BA_WINDOW_STATUS_NTFY_API_S_VER_1 */
/**
* struct iwl_rfh_queue_config - RX queue configuration
* @q_num: Q num
* @enable: enable queue
* @reserved: alignment
* @urbd_stts_wrptr: DMA address of urbd_stts_wrptr
* @fr_bd_cb: DMA address of freeRB table
* @ur_bd_cb: DMA address of used RB table
* @fr_bd_wid: Initial index of the free table
*/
struct iwl_rfh_queue_data {
u8 q_num;
u8 enable;
__le16 reserved;
__le64 urbd_stts_wrptr;
__le64 fr_bd_cb;
__le64 ur_bd_cb;
__le32 fr_bd_wid;
} __packed; /* RFH_QUEUE_CONFIG_S_VER_1 */
/**
* struct iwl_rfh_queue_config - RX queue configuration
* @num_queues: number of queues configured
* @reserved: alignment
* @data: DMA addresses per-queue
*/
struct iwl_rfh_queue_config {
u8 num_queues;
u8 reserved[3];
struct iwl_rfh_queue_data data[0];
} __packed; /* RFH_QUEUE_CONFIG_API_S_VER_1 */
#endif /* __iwl_fw_api_rx_h__ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,82 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2012-2014 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
#ifndef __iwl_fw_api_sf_h__
#define __iwl_fw_api_sf_h__
/* Smart Fifo state */
enum iwl_sf_state {
SF_LONG_DELAY_ON = 0, /* should never be called by driver */
SF_FULL_ON,
SF_UNINIT,
SF_INIT_OFF,
SF_HW_NUM_STATES
};
/* Smart Fifo possible scenario */
enum iwl_sf_scenario {
SF_SCENARIO_SINGLE_UNICAST,
SF_SCENARIO_AGG_UNICAST,
SF_SCENARIO_MULTICAST,
SF_SCENARIO_BA_RESP,
SF_SCENARIO_TX_RESP,
SF_NUM_SCENARIO
};
#define SF_TRANSIENT_STATES_NUMBER 2 /* SF_LONG_DELAY_ON and SF_FULL_ON */
#define SF_NUM_TIMEOUT_TYPES 2 /* Aging timer and Idle timer */
/* smart FIFO default values */
#define SF_W_MARK_SISO 6144
#define SF_W_MARK_MIMO2 8192
#define SF_W_MARK_MIMO3 6144
#define SF_W_MARK_LEGACY 4096
#define SF_W_MARK_SCAN 4096
/* SF Scenarios timers for default configuration (aligned to 32 uSec) */
#define SF_SINGLE_UNICAST_IDLE_TIMER_DEF 160 /* 150 uSec */
#define SF_SINGLE_UNICAST_AGING_TIMER_DEF 400 /* 0.4 mSec */
#define SF_AGG_UNICAST_IDLE_TIMER_DEF 160 /* 150 uSec */
#define SF_AGG_UNICAST_AGING_TIMER_DEF 400 /* 0.4 mSec */
#define SF_MCAST_IDLE_TIMER_DEF 160 /* 150 mSec */
#define SF_MCAST_AGING_TIMER_DEF 400 /* 0.4 mSec */
#define SF_BA_IDLE_TIMER_DEF 160 /* 150 uSec */
#define SF_BA_AGING_TIMER_DEF 400 /* 0.4 mSec */
#define SF_TX_RE_IDLE_TIMER_DEF 160 /* 150 uSec */
#define SF_TX_RE_AGING_TIMER_DEF 400 /* 0.4 mSec */
/* SF Scenarios timers for BSS MAC configuration (aligned to 32 uSec) */
#define SF_SINGLE_UNICAST_IDLE_TIMER 320 /* 300 uSec */
#define SF_SINGLE_UNICAST_AGING_TIMER 2016 /* 2 mSec */
#define SF_AGG_UNICAST_IDLE_TIMER 320 /* 300 uSec */
#define SF_AGG_UNICAST_AGING_TIMER 2016 /* 2 mSec */
#define SF_MCAST_IDLE_TIMER 2016 /* 2 mSec */
#define SF_MCAST_AGING_TIMER 10016 /* 10 mSec */
#define SF_BA_IDLE_TIMER 320 /* 300 uSec */
#define SF_BA_AGING_TIMER 2016 /* 2 mSec */
#define SF_TX_RE_IDLE_TIMER 320 /* 300 uSec */
#define SF_TX_RE_AGING_TIMER 2016 /* 2 mSec */
#define SF_LONG_DELAY_AGING_TIMER 1000000 /* 1 Sec */
#define SF_CFG_DUMMY_NOTIF_OFF BIT(16)
/**
* struct iwl_sf_cfg_cmd - Smart Fifo configuration command.
* @state: smart fifo state, types listed in &enum iwl_sf_state.
* @watermark: Minimum allowed available free space in RXF for transient state.
* @long_delay_timeouts: aging and idle timer values for each scenario
* in long delay state.
* @full_on_timeouts: timer values for each scenario in full on state.
*/
struct iwl_sf_cfg_cmd {
__le32 state;
__le32 watermark[SF_TRANSIENT_STATES_NUMBER];
__le32 long_delay_timeouts[SF_NUM_SCENARIO][SF_NUM_TIMEOUT_TYPES];
__le32 full_on_timeouts[SF_NUM_SCENARIO][SF_NUM_TIMEOUT_TYPES];
} __packed; /* SF_CFG_API_S_VER_2 */
#endif /* __iwl_fw_api_sf_h__ */

View File

@ -0,0 +1,35 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2012-2014, 2019-2020 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
#ifndef __iwl_fw_api_soc_h__
#define __iwl_fw_api_soc_h__
#define SOC_CONFIG_CMD_FLAGS_DISCRETE BIT(0)
#define SOC_CONFIG_CMD_FLAGS_LOW_LATENCY BIT(1)
#define SOC_FLAGS_LTR_APPLY_DELAY_MASK 0xc
#define SOC_FLAGS_LTR_APPLY_DELAY_NONE 0
#define SOC_FLAGS_LTR_APPLY_DELAY_200 1
#define SOC_FLAGS_LTR_APPLY_DELAY_2500 2
#define SOC_FLAGS_LTR_APPLY_DELAY_1820 3
/**
* struct iwl_soc_configuration_cmd - Set device stabilization latency
*
* @flags: soc settings flags. In VER_1, we can only set the DISCRETE
* flag, because the FW treats the whole value as an integer. In
* VER_2, we can set the bits independently.
* @latency: time for SOC to ensure stable power & XTAL
*/
struct iwl_soc_configuration_cmd {
__le32 flags;
__le32 latency;
} __packed; /*
* SOC_CONFIGURATION_CMD_S_VER_1 (see description above)
* SOC_CONFIGURATION_CMD_S_VER_2
*/
#endif /* __iwl_fw_api_soc_h__ */

View File

@ -0,0 +1,494 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2012-2014, 2018-2021 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
#ifndef __iwl_fw_api_sta_h__
#define __iwl_fw_api_sta_h__
/**
* enum iwl_sta_flags - flags for the ADD_STA host command
* @STA_FLG_REDUCED_TX_PWR_CTRL: reduced TX power (control frames)
* @STA_FLG_REDUCED_TX_PWR_DATA: reduced TX power (data frames)
* @STA_FLG_DISABLE_TX: set if TX should be disabled
* @STA_FLG_PS: set if STA is in Power Save
* @STA_FLG_DRAIN_FLOW: drain flow
* @STA_FLG_PAN: STA is for PAN interface
* @STA_FLG_CLASS_AUTH: station is authenticated
* @STA_FLG_CLASS_ASSOC: station is associated
* @STA_FLG_RTS_MIMO_PROT: station requires RTS MIMO protection (dynamic SMPS)
* @STA_FLG_MAX_AGG_SIZE_MSK: maximal size for A-MPDU (mask)
* @STA_FLG_MAX_AGG_SIZE_SHIFT: maximal size for A-MPDU (bit shift)
* @STA_FLG_MAX_AGG_SIZE_8K: maximal size for A-MPDU (8k supported)
* @STA_FLG_MAX_AGG_SIZE_16K: maximal size for A-MPDU (16k supported)
* @STA_FLG_MAX_AGG_SIZE_32K: maximal size for A-MPDU (32k supported)
* @STA_FLG_MAX_AGG_SIZE_64K: maximal size for A-MPDU (64k supported)
* @STA_FLG_MAX_AGG_SIZE_128K: maximal size for A-MPDU (128k supported)
* @STA_FLG_MAX_AGG_SIZE_256K: maximal size for A-MPDU (256k supported)
* @STA_FLG_MAX_AGG_SIZE_512K: maximal size for A-MPDU (512k supported)
* @STA_FLG_MAX_AGG_SIZE_1024K: maximal size for A-MPDU (1024k supported)
* @STA_FLG_MAX_AGG_SIZE_2M: maximal size for A-MPDU (2M supported)
* @STA_FLG_MAX_AGG_SIZE_4M: maximal size for A-MPDU (4M supported)
* @STA_FLG_AGG_MPDU_DENS_MSK: maximal MPDU density for Tx aggregation
* @STA_FLG_FAT_EN_MSK: support for channel width (for Tx). This flag is
* initialised by driver and can be updated by fw upon reception of
* action frames that can change the channel width. When cleared the fw
* will send all the frames in 20MHz even when FAT channel is requested.
* @STA_FLG_FAT_EN_20MHZ: no wide channels are supported, only 20 MHz
* @STA_FLG_FAT_EN_40MHZ: wide channels up to 40 MHz supported
* @STA_FLG_FAT_EN_80MHZ: wide channels up to 80 MHz supported
* @STA_FLG_FAT_EN_160MHZ: wide channels up to 160 MHz supported
* @STA_FLG_MIMO_EN_MSK: support for MIMO. This flag is initialised by the
* driver and can be updated by fw upon reception of action frames.
* @STA_FLG_MIMO_EN_SISO: no support for MIMO
* @STA_FLG_MIMO_EN_MIMO2: 2 streams supported
* @STA_FLG_MIMO_EN_MIMO3: 3 streams supported
* @STA_FLG_AGG_MPDU_DENS_MSK: A-MPDU density (mask)
* @STA_FLG_AGG_MPDU_DENS_SHIFT: A-MPDU density (bit shift)
* @STA_FLG_AGG_MPDU_DENS_2US: A-MPDU density (2 usec gap)
* @STA_FLG_AGG_MPDU_DENS_4US: A-MPDU density (4 usec gap)
* @STA_FLG_AGG_MPDU_DENS_8US: A-MPDU density (8 usec gap)
* @STA_FLG_AGG_MPDU_DENS_16US: A-MPDU density (16 usec gap)
*/
enum iwl_sta_flags {
STA_FLG_REDUCED_TX_PWR_CTRL = BIT(3),
STA_FLG_REDUCED_TX_PWR_DATA = BIT(6),
STA_FLG_DISABLE_TX = BIT(4),
STA_FLG_PS = BIT(8),
STA_FLG_DRAIN_FLOW = BIT(12),
STA_FLG_PAN = BIT(13),
STA_FLG_CLASS_AUTH = BIT(14),
STA_FLG_CLASS_ASSOC = BIT(15),
STA_FLG_RTS_MIMO_PROT = BIT(17),
STA_FLG_MAX_AGG_SIZE_SHIFT = 19,
STA_FLG_MAX_AGG_SIZE_8K = (0 << STA_FLG_MAX_AGG_SIZE_SHIFT),
STA_FLG_MAX_AGG_SIZE_16K = (1 << STA_FLG_MAX_AGG_SIZE_SHIFT),
STA_FLG_MAX_AGG_SIZE_32K = (2 << STA_FLG_MAX_AGG_SIZE_SHIFT),
STA_FLG_MAX_AGG_SIZE_64K = (3 << STA_FLG_MAX_AGG_SIZE_SHIFT),
STA_FLG_MAX_AGG_SIZE_128K = (4 << STA_FLG_MAX_AGG_SIZE_SHIFT),
STA_FLG_MAX_AGG_SIZE_256K = (5 << STA_FLG_MAX_AGG_SIZE_SHIFT),
STA_FLG_MAX_AGG_SIZE_512K = (6 << STA_FLG_MAX_AGG_SIZE_SHIFT),
STA_FLG_MAX_AGG_SIZE_1024K = (7 << STA_FLG_MAX_AGG_SIZE_SHIFT),
STA_FLG_MAX_AGG_SIZE_2M = (8 << STA_FLG_MAX_AGG_SIZE_SHIFT),
STA_FLG_MAX_AGG_SIZE_4M = (9 << STA_FLG_MAX_AGG_SIZE_SHIFT),
STA_FLG_MAX_AGG_SIZE_MSK = (0xf << STA_FLG_MAX_AGG_SIZE_SHIFT),
STA_FLG_AGG_MPDU_DENS_SHIFT = 23,
STA_FLG_AGG_MPDU_DENS_2US = (4 << STA_FLG_AGG_MPDU_DENS_SHIFT),
STA_FLG_AGG_MPDU_DENS_4US = (5 << STA_FLG_AGG_MPDU_DENS_SHIFT),
STA_FLG_AGG_MPDU_DENS_8US = (6 << STA_FLG_AGG_MPDU_DENS_SHIFT),
STA_FLG_AGG_MPDU_DENS_16US = (7 << STA_FLG_AGG_MPDU_DENS_SHIFT),
STA_FLG_AGG_MPDU_DENS_MSK = (7 << STA_FLG_AGG_MPDU_DENS_SHIFT),
STA_FLG_FAT_EN_20MHZ = (0 << 26),
STA_FLG_FAT_EN_40MHZ = (1 << 26),
STA_FLG_FAT_EN_80MHZ = (2 << 26),
STA_FLG_FAT_EN_160MHZ = (3 << 26),
STA_FLG_FAT_EN_MSK = (3 << 26),
STA_FLG_MIMO_EN_SISO = (0 << 28),
STA_FLG_MIMO_EN_MIMO2 = (1 << 28),
STA_FLG_MIMO_EN_MIMO3 = (2 << 28),
STA_FLG_MIMO_EN_MSK = (3 << 28),
};
/**
* enum iwl_sta_key_flag - key flags for the ADD_STA host command
* @STA_KEY_FLG_NO_ENC: no encryption
* @STA_KEY_FLG_WEP: WEP encryption algorithm
* @STA_KEY_FLG_CCM: CCMP encryption algorithm
* @STA_KEY_FLG_TKIP: TKIP encryption algorithm
* @STA_KEY_FLG_EXT: extended cipher algorithm (depends on the FW support)
* @STA_KEY_FLG_GCMP: GCMP encryption algorithm
* @STA_KEY_FLG_CMAC: CMAC encryption algorithm
* @STA_KEY_FLG_ENC_UNKNOWN: unknown encryption algorithm
* @STA_KEY_FLG_EN_MSK: mask for encryption algorithmi value
* @STA_KEY_FLG_WEP_KEY_MAP: wep is either a group key (0 - legacy WEP) or from
* station info array (1 - n 1X mode)
* @STA_KEY_FLG_KEYID_MSK: the index of the key
* @STA_KEY_FLG_KEYID_POS: key index bit position
* @STA_KEY_NOT_VALID: key is invalid
* @STA_KEY_FLG_WEP_13BYTES: set for 13 bytes WEP key
* @STA_KEY_FLG_KEY_32BYTES: for non-wep key set for 32 bytes key
* @STA_KEY_MULTICAST: set for multical key
* @STA_KEY_MFP: key is used for Management Frame Protection
*/
enum iwl_sta_key_flag {
STA_KEY_FLG_NO_ENC = (0 << 0),
STA_KEY_FLG_WEP = (1 << 0),
STA_KEY_FLG_CCM = (2 << 0),
STA_KEY_FLG_TKIP = (3 << 0),
STA_KEY_FLG_EXT = (4 << 0),
STA_KEY_FLG_GCMP = (5 << 0),
STA_KEY_FLG_CMAC = (6 << 0),
STA_KEY_FLG_ENC_UNKNOWN = (7 << 0),
STA_KEY_FLG_EN_MSK = (7 << 0),
STA_KEY_FLG_WEP_KEY_MAP = BIT(3),
STA_KEY_FLG_KEYID_POS = 8,
STA_KEY_FLG_KEYID_MSK = (3 << STA_KEY_FLG_KEYID_POS),
STA_KEY_NOT_VALID = BIT(11),
STA_KEY_FLG_WEP_13BYTES = BIT(12),
STA_KEY_FLG_KEY_32BYTES = BIT(12),
STA_KEY_MULTICAST = BIT(14),
STA_KEY_MFP = BIT(15),
};
/**
* enum iwl_sta_modify_flag - indicate to the fw what flag are being changed
* @STA_MODIFY_QUEUE_REMOVAL: this command removes a queue
* @STA_MODIFY_TID_DISABLE_TX: this command modifies %tid_disable_tx
* @STA_MODIFY_UAPSD_ACS: this command modifies %uapsd_acs
* @STA_MODIFY_ADD_BA_TID: this command modifies %add_immediate_ba_tid
* @STA_MODIFY_REMOVE_BA_TID: this command modifies %remove_immediate_ba_tid
* @STA_MODIFY_SLEEPING_STA_TX_COUNT: this command modifies %sleep_tx_count
* @STA_MODIFY_PROT_TH: modify RTS threshold
* @STA_MODIFY_QUEUES: modify the queues used by this station
*/
enum iwl_sta_modify_flag {
STA_MODIFY_QUEUE_REMOVAL = BIT(0),
STA_MODIFY_TID_DISABLE_TX = BIT(1),
STA_MODIFY_UAPSD_ACS = BIT(2),
STA_MODIFY_ADD_BA_TID = BIT(3),
STA_MODIFY_REMOVE_BA_TID = BIT(4),
STA_MODIFY_SLEEPING_STA_TX_COUNT = BIT(5),
STA_MODIFY_PROT_TH = BIT(6),
STA_MODIFY_QUEUES = BIT(7),
};
/**
* enum iwl_sta_mode - station command mode
* @STA_MODE_ADD: add new station
* @STA_MODE_MODIFY: modify the station
*/
enum iwl_sta_mode {
STA_MODE_ADD = 0,
STA_MODE_MODIFY = 1,
};
/**
* enum iwl_sta_sleep_flag - type of sleep of the station
* @STA_SLEEP_STATE_AWAKE: station is awake
* @STA_SLEEP_STATE_PS_POLL: station is PS-polling
* @STA_SLEEP_STATE_UAPSD: station uses U-APSD
* @STA_SLEEP_STATE_MOREDATA: set more-data bit on
* (last) released frame
*/
enum iwl_sta_sleep_flag {
STA_SLEEP_STATE_AWAKE = 0,
STA_SLEEP_STATE_PS_POLL = BIT(0),
STA_SLEEP_STATE_UAPSD = BIT(1),
STA_SLEEP_STATE_MOREDATA = BIT(2),
};
#define STA_KEY_MAX_NUM (16)
#define STA_KEY_IDX_INVALID (0xff)
#define STA_KEY_MAX_DATA_KEY_NUM (4)
#define IWL_MAX_GLOBAL_KEYS (4)
#define STA_KEY_LEN_WEP40 (5)
#define STA_KEY_LEN_WEP104 (13)
#define IWL_ADD_STA_STATUS_MASK 0xFF
#define IWL_ADD_STA_BAID_VALID_MASK 0x8000
#define IWL_ADD_STA_BAID_MASK 0x7F00
#define IWL_ADD_STA_BAID_SHIFT 8
/**
* struct iwl_mvm_add_sta_cmd_v7 - Add/modify a station in the fw's sta table.
* ( REPLY_ADD_STA = 0x18 )
* @add_modify: see &enum iwl_sta_mode
* @awake_acs: ACs to transmit data on while station is sleeping (for U-APSD)
* @tid_disable_tx: is tid BIT(tid) enabled for Tx. Clear BIT(x) to enable
* AMPDU for tid x. Set %STA_MODIFY_TID_DISABLE_TX to change this field.
* @mac_id_n_color: the Mac context this station belongs to,
* see &enum iwl_ctxt_id_and_color
* @addr: station's MAC address
* @reserved2: reserved
* @sta_id: index of station in uCode's station table
* @modify_mask: from &enum iwl_sta_modify_flag, selects what to change
* @reserved3: reserved
* @station_flags: look at &enum iwl_sta_flags
* @station_flags_msk: what of %station_flags have changed,
* also &enum iwl_sta_flags
* @add_immediate_ba_tid: tid for which to add block-ack support (Rx)
* Set %STA_MODIFY_ADD_BA_TID to use this field, and also set
* add_immediate_ba_ssn.
* @remove_immediate_ba_tid: tid for which to remove block-ack support (Rx)
* Set %STA_MODIFY_REMOVE_BA_TID to use this field
* @add_immediate_ba_ssn: ssn for the Rx block-ack session. Used together with
* add_immediate_ba_tid.
* @sleep_tx_count: number of packets to transmit to station even though it is
* asleep. Used to synchronise PS-poll and u-APSD responses while ucode
* keeps track of STA sleep state.
* @sleep_state_flags: Look at &enum iwl_sta_sleep_flag.
* @assoc_id: assoc_id to be sent in VHT PLCP (9-bit), for grp use 0, for AP
* mac-addr.
* @beamform_flags: beam forming controls
* @tfd_queue_msk: tfd queues used by this station
*
* The device contains an internal table of per-station information, with info
* on security keys, aggregation parameters, and Tx rates for initial Tx
* attempt and any retries (set by REPLY_TX_LINK_QUALITY_CMD).
*
* ADD_STA sets up the table entry for one station, either creating a new
* entry, or modifying a pre-existing one.
*/
struct iwl_mvm_add_sta_cmd_v7 {
u8 add_modify;
u8 awake_acs;
__le16 tid_disable_tx;
__le32 mac_id_n_color;
u8 addr[ETH_ALEN]; /* _STA_ID_MODIFY_INFO_API_S_VER_1 */
__le16 reserved2;
u8 sta_id;
u8 modify_mask;
__le16 reserved3;
__le32 station_flags;
__le32 station_flags_msk;
u8 add_immediate_ba_tid;
u8 remove_immediate_ba_tid;
__le16 add_immediate_ba_ssn;
__le16 sleep_tx_count;
__le16 sleep_state_flags;
__le16 assoc_id;
__le16 beamform_flags;
__le32 tfd_queue_msk;
} __packed; /* ADD_STA_CMD_API_S_VER_7 */
/**
* enum iwl_sta_type - FW station types
* ( REPLY_ADD_STA = 0x18 )
* @IWL_STA_LINK: Link station - normal RX and TX traffic.
* @IWL_STA_GENERAL_PURPOSE: General purpose. In AP mode used for beacons
* and probe responses.
* @IWL_STA_MULTICAST: multicast traffic,
* @IWL_STA_TDLS_LINK: TDLS link station
* @IWL_STA_AUX_ACTIVITY: auxilary station (scan, ROC and so on).
*/
enum iwl_sta_type {
IWL_STA_LINK,
IWL_STA_GENERAL_PURPOSE,
IWL_STA_MULTICAST,
IWL_STA_TDLS_LINK,
IWL_STA_AUX_ACTIVITY,
};
/**
* struct iwl_mvm_add_sta_cmd - Add/modify a station in the fw's sta table.
* ( REPLY_ADD_STA = 0x18 )
* @add_modify: see &enum iwl_sta_mode
* @awake_acs: ACs to transmit data on while station is sleeping (for U-APSD)
* @tid_disable_tx: is tid BIT(tid) enabled for Tx. Clear BIT(x) to enable
* AMPDU for tid x. Set %STA_MODIFY_TID_DISABLE_TX to change this field.
* @mac_id_n_color: the Mac context this station belongs to,
* see &enum iwl_ctxt_id_and_color
* @addr: station's MAC address
* @reserved2: reserved
* @sta_id: index of station in uCode's station table
* @modify_mask: from &enum iwl_sta_modify_flag, selects what to change
* @reserved3: reserved
* @station_flags: look at &enum iwl_sta_flags
* @station_flags_msk: what of %station_flags have changed,
* also &enum iwl_sta_flags
* @add_immediate_ba_tid: tid for which to add block-ack support (Rx)
* Set %STA_MODIFY_ADD_BA_TID to use this field, and also set
* add_immediate_ba_ssn.
* @remove_immediate_ba_tid: tid for which to remove block-ack support (Rx)
* Set %STA_MODIFY_REMOVE_BA_TID to use this field
* @add_immediate_ba_ssn: ssn for the Rx block-ack session. Used together with
* add_immediate_ba_tid.
* @sleep_tx_count: number of packets to transmit to station even though it is
* asleep. Used to synchronise PS-poll and u-APSD responses while ucode
* keeps track of STA sleep state.
* @station_type: type of this station. See &enum iwl_sta_type.
* @sleep_state_flags: Look at &enum iwl_sta_sleep_flag.
* @assoc_id: assoc_id to be sent in VHT PLCP (9-bit), for grp use 0, for AP
* mac-addr.
* @beamform_flags: beam forming controls
* @tfd_queue_msk: tfd queues used by this station.
* Obselete for new TX API (9 and above).
* @rx_ba_window: aggregation window size
* @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.
*
* The device contains an internal table of per-station information, with info
* on security keys, aggregation parameters, and Tx rates for initial Tx
* attempt and any retries (set by REPLY_TX_LINK_QUALITY_CMD).
*
* ADD_STA sets up the table entry for one station, either creating a new
* entry, or modifying a pre-existing one.
*/
struct iwl_mvm_add_sta_cmd {
u8 add_modify;
u8 awake_acs;
__le16 tid_disable_tx;
__le32 mac_id_n_color; /* can be used for lmac id when using cmd v12 */
u8 addr[ETH_ALEN]; /* _STA_ID_MODIFY_INFO_API_S_VER_1 */
__le16 reserved2;
u8 sta_id;
u8 modify_mask;
__le16 reserved3;
__le32 station_flags;
__le32 station_flags_msk;
u8 add_immediate_ba_tid;
u8 remove_immediate_ba_tid;
__le16 add_immediate_ba_ssn;
__le16 sleep_tx_count;
u8 sleep_state_flags;
u8 station_type;
__le16 assoc_id;
__le16 beamform_flags;
__le32 tfd_queue_msk;
__le16 rx_ba_window;
u8 sp_length;
u8 uapsd_acs;
} __packed; /* ADD_STA_CMD_API_S_VER_10 */
/**
* struct iwl_mvm_add_sta_key_common - add/modify sta key common part
* ( REPLY_ADD_STA_KEY = 0x17 )
* @sta_id: index of station in uCode's station table
* @key_offset: key offset in key storage
* @key_flags: type &enum iwl_sta_key_flag
* @key: key material data
* @rx_secur_seq_cnt: RX security sequence counter for the key
*/
struct iwl_mvm_add_sta_key_common {
u8 sta_id;
u8 key_offset;
__le16 key_flags;
u8 key[32];
u8 rx_secur_seq_cnt[16];
} __packed;
/**
* struct iwl_mvm_add_sta_key_cmd_v1 - add/modify sta key
* @common: see &struct iwl_mvm_add_sta_key_common
* @tkip_rx_tsc_byte2: TSC[2] for key mix ph1 detection
* @reserved: reserved
* @tkip_rx_ttak: 10-byte unicast TKIP TTAK for Rx
*/
struct iwl_mvm_add_sta_key_cmd_v1 {
struct iwl_mvm_add_sta_key_common common;
u8 tkip_rx_tsc_byte2;
u8 reserved;
__le16 tkip_rx_ttak[5];
} __packed; /* ADD_MODIFY_STA_KEY_API_S_VER_1 */
/**
* struct iwl_mvm_add_sta_key_cmd - add/modify sta key
* @common: see &struct iwl_mvm_add_sta_key_common
* @rx_mic_key: TKIP RX unicast or multicast key
* @tx_mic_key: TKIP TX key
* @transmit_seq_cnt: TSC, transmit packet number
*
* Note: This is used for both v2 and v3, the difference being
* in the way the common.rx_secur_seq_cnt is used, in v2 that's
* the strange hole format, in v3 it's just a u64.
*/
struct iwl_mvm_add_sta_key_cmd {
struct iwl_mvm_add_sta_key_common common;
__le64 rx_mic_key;
__le64 tx_mic_key;
__le64 transmit_seq_cnt;
} __packed; /* ADD_MODIFY_STA_KEY_API_S_VER_2, ADD_MODIFY_STA_KEY_API_S_VER_3 */
/**
* enum iwl_mvm_add_sta_rsp_status - status in the response to ADD_STA command
* @ADD_STA_SUCCESS: operation was executed successfully
* @ADD_STA_STATIONS_OVERLOAD: no room left in the fw's station table
* @ADD_STA_IMMEDIATE_BA_FAILURE: can't add Rx block ack session
* @ADD_STA_MODIFY_NON_EXISTING_STA: driver requested to modify a station that
* doesn't exist.
*/
enum iwl_mvm_add_sta_rsp_status {
ADD_STA_SUCCESS = 0x1,
ADD_STA_STATIONS_OVERLOAD = 0x2,
ADD_STA_IMMEDIATE_BA_FAILURE = 0x4,
ADD_STA_MODIFY_NON_EXISTING_STA = 0x8,
};
/**
* struct iwl_mvm_rm_sta_cmd - Add / modify a station in the fw's station table
* ( REMOVE_STA = 0x19 )
* @sta_id: the station id of the station to be removed
* @reserved: reserved
*/
struct iwl_mvm_rm_sta_cmd {
u8 sta_id;
u8 reserved[3];
} __packed; /* REMOVE_STA_CMD_API_S_VER_2 */
/**
* struct iwl_mvm_mgmt_mcast_key_cmd_v1
* ( MGMT_MCAST_KEY = 0x1f )
* @ctrl_flags: &enum iwl_sta_key_flag
* @igtk: IGTK key material
* @k1: unused
* @k2: unused
* @sta_id: station ID that support IGTK
* @key_id: key ID
* @receive_seq_cnt: initial RSC/PN needed for replay check
*/
struct iwl_mvm_mgmt_mcast_key_cmd_v1 {
__le32 ctrl_flags;
u8 igtk[16];
u8 k1[16];
u8 k2[16];
__le32 key_id;
__le32 sta_id;
__le64 receive_seq_cnt;
} __packed; /* SEC_MGMT_MULTICAST_KEY_CMD_API_S_VER_1 */
/**
* struct iwl_mvm_mgmt_mcast_key_cmd
* ( MGMT_MCAST_KEY = 0x1f )
* @ctrl_flags: &enum iwl_sta_key_flag
* @igtk: IGTK master key
* @sta_id: station ID that support IGTK
* @key_id: key ID
* @receive_seq_cnt: initial RSC/PN needed for replay check
*/
struct iwl_mvm_mgmt_mcast_key_cmd {
__le32 ctrl_flags;
u8 igtk[32];
__le32 key_id;
__le32 sta_id;
__le64 receive_seq_cnt;
} __packed; /* SEC_MGMT_MULTICAST_KEY_CMD_API_S_VER_2 */
struct iwl_mvm_wep_key {
u8 key_index;
u8 key_offset;
__le16 reserved1;
u8 key_size;
u8 reserved2[3];
u8 key[16];
} __packed;
struct iwl_mvm_wep_key_cmd {
__le32 mac_id_n_color;
u8 num_keys;
u8 decryption_type;
u8 flags;
u8 reserved;
struct iwl_mvm_wep_key wep_key[0];
} __packed; /* SEC_CURR_WEP_KEY_CMD_API_S_VER_2 */
/**
* struct iwl_mvm_eosp_notification - EOSP notification from firmware
* @remain_frame_count: # of frames remaining, non-zero if SP was cut
* short by GO absence
* @sta_id: station ID
*/
struct iwl_mvm_eosp_notification {
__le32 remain_frame_count;
__le32 sta_id;
} __packed; /* UAPSD_EOSP_NTFY_API_S_VER_1 */
#endif /* __iwl_fw_api_sta_h__ */

View File

@ -0,0 +1,873 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2012-2014, 2018, 2020 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
#ifndef __iwl_fw_api_stats_h__
#define __iwl_fw_api_stats_h__
#include "mac.h"
struct mvm_statistics_dbg {
__le32 burst_check;
__le32 burst_count;
__le32 wait_for_silence_timeout_cnt;
u8 reserved[12];
} __packed; /* STATISTICS_DEBUG_API_S_VER_2 */
struct mvm_statistics_div {
__le32 tx_on_a;
__le32 tx_on_b;
__le32 exec_time;
__le32 probe_time;
__le32 rssi_ant;
__le32 reserved2;
} __packed; /* STATISTICS_SLOW_DIV_API_S_VER_2 */
/**
* struct mvm_statistics_rx_non_phy
* @bogus_cts: CTS received when not expecting CTS
* @bogus_ack: ACK received when not expecting ACK
* @non_channel_beacons: beacons with our bss id but not on our serving channel
* @channel_beacons: beacons with our bss id and in our serving channel
* @num_missed_bcon: number of missed beacons
* @adc_rx_saturation_time: count in 0.8us units the time the ADC was in
* saturation
* @ina_detection_search_time: total time (in 0.8us) searched for INA
* @beacon_silence_rssi_a: RSSI silence after beacon frame
* @beacon_silence_rssi_b: RSSI silence after beacon frame
* @beacon_silence_rssi_c: RSSI silence after beacon frame
* @interference_data_flag: flag for interference data availability. 1 when data
* is available.
* @channel_load: counts RX Enable time in uSec
* @beacon_rssi_a: beacon RSSI on antenna A
* @beacon_rssi_b: beacon RSSI on antenna B
* @beacon_rssi_c: beacon RSSI on antenna C
* @beacon_energy_a: beacon energy on antenna A
* @beacon_energy_b: beacon energy on antenna B
* @beacon_energy_c: beacon energy on antenna C
* @num_bt_kills: number of BT "kills" (frame TX aborts)
* @mac_id: mac ID
*/
struct mvm_statistics_rx_non_phy {
__le32 bogus_cts;
__le32 bogus_ack;
__le32 non_channel_beacons;
__le32 channel_beacons;
__le32 num_missed_bcon;
__le32 adc_rx_saturation_time;
__le32 ina_detection_search_time;
__le32 beacon_silence_rssi_a;
__le32 beacon_silence_rssi_b;
__le32 beacon_silence_rssi_c;
__le32 interference_data_flag;
__le32 channel_load;
__le32 beacon_rssi_a;
__le32 beacon_rssi_b;
__le32 beacon_rssi_c;
__le32 beacon_energy_a;
__le32 beacon_energy_b;
__le32 beacon_energy_c;
__le32 num_bt_kills;
__le32 mac_id;
} __packed; /* STATISTICS_RX_NON_PHY_API_S_VER_4 */
struct mvm_statistics_rx_non_phy_v3 {
__le32 bogus_cts; /* CTS received when not expecting CTS */
__le32 bogus_ack; /* ACK received when not expecting ACK */
__le32 non_bssid_frames; /* number of frames with BSSID that
* doesn't belong to the STA BSSID */
__le32 filtered_frames; /* count frames that were dumped in the
* filtering process */
__le32 non_channel_beacons; /* beacons with our bss id but not on
* our serving channel */
__le32 channel_beacons; /* beacons with our bss id and in our
* serving channel */
__le32 num_missed_bcon; /* number of missed beacons */
__le32 adc_rx_saturation_time; /* count in 0.8us units the time the
* ADC was in saturation */
__le32 ina_detection_search_time;/* total time (in 0.8us) searched
* for INA */
__le32 beacon_silence_rssi_a; /* RSSI silence after beacon frame */
__le32 beacon_silence_rssi_b; /* RSSI silence after beacon frame */
__le32 beacon_silence_rssi_c; /* RSSI silence after beacon frame */
__le32 interference_data_flag; /* flag for interference data
* availability. 1 when data is
* available. */
__le32 channel_load; /* counts RX Enable time in uSec */
__le32 dsp_false_alarms; /* DSP false alarm (both OFDM
* and CCK) counter */
__le32 beacon_rssi_a;
__le32 beacon_rssi_b;
__le32 beacon_rssi_c;
__le32 beacon_energy_a;
__le32 beacon_energy_b;
__le32 beacon_energy_c;
__le32 num_bt_kills;
__le32 mac_id;
__le32 directed_data_mpdu;
} __packed; /* STATISTICS_RX_NON_PHY_API_S_VER_3 */
struct mvm_statistics_rx_phy {
__le32 unresponded_rts;
__le32 rxe_frame_lmt_overrun;
__le32 sent_ba_rsp_cnt;
__le32 dsp_self_kill;
__le32 reserved;
} __packed; /* STATISTICS_RX_PHY_API_S_VER_3 */
struct mvm_statistics_rx_phy_v2 {
__le32 ina_cnt;
__le32 fina_cnt;
__le32 plcp_err;
__le32 crc32_err;
__le32 overrun_err;
__le32 early_overrun_err;
__le32 crc32_good;
__le32 false_alarm_cnt;
__le32 fina_sync_err_cnt;
__le32 sfd_timeout;
__le32 fina_timeout;
__le32 unresponded_rts;
__le32 rxe_frame_lmt_overrun;
__le32 sent_ack_cnt;
__le32 sent_cts_cnt;
__le32 sent_ba_rsp_cnt;
__le32 dsp_self_kill;
__le32 mh_format_err;
__le32 re_acq_main_rssi_sum;
__le32 reserved;
} __packed; /* STATISTICS_RX_PHY_API_S_VER_2 */
struct mvm_statistics_rx_ht_phy_v1 {
__le32 plcp_err;
__le32 overrun_err;
__le32 early_overrun_err;
__le32 crc32_good;
__le32 crc32_err;
__le32 mh_format_err;
__le32 agg_crc32_good;
__le32 agg_mpdu_cnt;
__le32 agg_cnt;
__le32 unsupport_mcs;
} __packed; /* STATISTICS_HT_RX_PHY_API_S_VER_1 */
struct mvm_statistics_rx_ht_phy {
__le32 mh_format_err;
__le32 agg_mpdu_cnt;
__le32 agg_cnt;
__le32 unsupport_mcs;
} __packed; /* STATISTICS_HT_RX_PHY_API_S_VER_2 */
struct mvm_statistics_tx_non_phy_v3 {
__le32 preamble_cnt;
__le32 rx_detected_cnt;
__le32 bt_prio_defer_cnt;
__le32 bt_prio_kill_cnt;
__le32 few_bytes_cnt;
__le32 cts_timeout;
__le32 ack_timeout;
__le32 expected_ack_cnt;
__le32 actual_ack_cnt;
__le32 dump_msdu_cnt;
__le32 burst_abort_next_frame_mismatch_cnt;
__le32 burst_abort_missing_next_frame_cnt;
__le32 cts_timeout_collision;
__le32 ack_or_ba_timeout_collision;
} __packed; /* STATISTICS_TX_NON_PHY_API_S_VER_3 */
struct mvm_statistics_tx_non_phy {
__le32 bt_prio_defer_cnt;
__le32 bt_prio_kill_cnt;
__le32 few_bytes_cnt;
__le32 cts_timeout;
__le32 ack_timeout;
__le32 dump_msdu_cnt;
__le32 burst_abort_next_frame_mismatch_cnt;
__le32 burst_abort_missing_next_frame_cnt;
__le32 cts_timeout_collision;
__le32 ack_or_ba_timeout_collision;
} __packed; /* STATISTICS_TX_NON_PHY_API_S_VER_4 */
#define MAX_CHAINS 3
struct mvm_statistics_tx_non_phy_agg {
__le32 ba_timeout;
__le32 ba_reschedule_frames;
__le32 scd_query_agg_frame_cnt;
__le32 scd_query_no_agg;
__le32 scd_query_agg;
__le32 scd_query_mismatch;
__le32 frame_not_ready;
__le32 underrun;
__le32 bt_prio_kill;
__le32 rx_ba_rsp_cnt;
__s8 txpower[MAX_CHAINS];
__s8 reserved;
__le32 reserved2;
} __packed; /* STATISTICS_TX_NON_PHY_AGG_API_S_VER_1 */
struct mvm_statistics_tx_channel_width {
__le32 ext_cca_narrow_ch20[1];
__le32 ext_cca_narrow_ch40[2];
__le32 ext_cca_narrow_ch80[3];
__le32 ext_cca_narrow_ch160[4];
__le32 last_tx_ch_width_indx;
__le32 rx_detected_per_ch_width[4];
__le32 success_per_ch_width[4];
__le32 fail_per_ch_width[4];
}; /* STATISTICS_TX_CHANNEL_WIDTH_API_S_VER_1 */
struct mvm_statistics_tx_v4 {
struct mvm_statistics_tx_non_phy_v3 general;
struct mvm_statistics_tx_non_phy_agg agg;
struct mvm_statistics_tx_channel_width channel_width;
} __packed; /* STATISTICS_TX_API_S_VER_4 */
struct mvm_statistics_tx {
struct mvm_statistics_tx_non_phy general;
struct mvm_statistics_tx_non_phy_agg agg;
struct mvm_statistics_tx_channel_width channel_width;
} __packed; /* STATISTICS_TX_API_S_VER_5 */
struct mvm_statistics_bt_activity {
__le32 hi_priority_tx_req_cnt;
__le32 hi_priority_tx_denied_cnt;
__le32 lo_priority_tx_req_cnt;
__le32 lo_priority_tx_denied_cnt;
__le32 hi_priority_rx_req_cnt;
__le32 hi_priority_rx_denied_cnt;
__le32 lo_priority_rx_req_cnt;
__le32 lo_priority_rx_denied_cnt;
} __packed; /* STATISTICS_BT_ACTIVITY_API_S_VER_1 */
struct mvm_statistics_general_common_v19 {
__le32 radio_temperature;
__le32 radio_voltage;
struct mvm_statistics_dbg dbg;
__le32 sleep_time;
__le32 slots_out;
__le32 slots_idle;
__le32 ttl_timestamp;
struct mvm_statistics_div slow_div;
__le32 rx_enable_counter;
/*
* num_of_sos_states:
* count the number of times we have to re-tune
* in order to get out of bad PHY status
*/
__le32 num_of_sos_states;
__le32 beacon_filtered;
__le32 missed_beacons;
u8 beacon_filter_average_energy;
u8 beacon_filter_reason;
u8 beacon_filter_current_energy;
u8 beacon_filter_reserved;
__le32 beacon_filter_delta_time;
struct mvm_statistics_bt_activity bt_activity;
__le64 rx_time;
__le64 on_time_rf;
__le64 on_time_scan;
__le64 tx_time;
} __packed;
struct mvm_statistics_general_common {
__le32 radio_temperature;
struct mvm_statistics_dbg dbg;
__le32 sleep_time;
__le32 slots_out;
__le32 slots_idle;
__le32 ttl_timestamp;
struct mvm_statistics_div slow_div;
__le32 rx_enable_counter;
/*
* num_of_sos_states:
* count the number of times we have to re-tune
* in order to get out of bad PHY status
*/
__le32 num_of_sos_states;
__le32 beacon_filtered;
__le32 missed_beacons;
u8 beacon_filter_average_energy;
u8 beacon_filter_reason;
u8 beacon_filter_current_energy;
u8 beacon_filter_reserved;
__le32 beacon_filter_delta_time;
struct mvm_statistics_bt_activity bt_activity;
__le64 rx_time;
__le64 on_time_rf;
__le64 on_time_scan;
__le64 tx_time;
} __packed; /* STATISTICS_GENERAL_API_S_VER_10 */
struct mvm_statistics_general_v8 {
struct mvm_statistics_general_common_v19 common;
__le32 beacon_counter[NUM_MAC_INDEX];
u8 beacon_average_energy[NUM_MAC_INDEX];
u8 reserved[4 - (NUM_MAC_INDEX % 4)];
} __packed; /* STATISTICS_GENERAL_API_S_VER_8 */
struct mvm_statistics_general {
struct mvm_statistics_general_common common;
__le32 beacon_counter[MAC_INDEX_AUX];
u8 beacon_average_energy[MAC_INDEX_AUX];
u8 reserved[8 - MAC_INDEX_AUX];
} __packed; /* STATISTICS_GENERAL_API_S_VER_10 */
/**
* struct mvm_statistics_load - RX statistics for multi-queue devices
* @air_time: accumulated air time, per mac
* @byte_count: accumulated byte count, per mac
* @pkt_count: accumulated packet count, per mac
* @avg_energy: average RSSI, per station
*/
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];
} __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];
} __packed; /* STATISTICS_RX_MAC_STATION_S_VER_1 */
struct mvm_statistics_rx {
struct mvm_statistics_rx_phy ofdm;
struct mvm_statistics_rx_phy cck;
struct mvm_statistics_rx_non_phy general;
struct mvm_statistics_rx_ht_phy ofdm_ht;
} __packed; /* STATISTICS_RX_API_S_VER_4 */
struct mvm_statistics_rx_v3 {
struct mvm_statistics_rx_phy_v2 ofdm;
struct mvm_statistics_rx_phy_v2 cck;
struct mvm_statistics_rx_non_phy_v3 general;
struct mvm_statistics_rx_ht_phy_v1 ofdm_ht;
} __packed; /* STATISTICS_RX_API_S_VER_3 */
/*
* STATISTICS_NOTIFICATION = 0x9d (notification only, not a command)
*
* By default, uCode issues this notification after receiving a beacon
* while associated. To disable this behavior, set DISABLE_NOTIF flag in the
* STATISTICS_CMD (0x9c), below.
*/
struct iwl_notif_statistics_v10 {
__le32 flag;
struct mvm_statistics_rx_v3 rx;
struct mvm_statistics_tx_v4 tx;
struct mvm_statistics_general_v8 general;
} __packed; /* STATISTICS_NTFY_API_S_VER_10 */
struct iwl_notif_statistics_v11 {
__le32 flag;
struct mvm_statistics_rx_v3 rx;
struct mvm_statistics_tx_v4 tx;
struct mvm_statistics_general_v8 general;
struct mvm_statistics_load_v1 load_stats;
} __packed; /* STATISTICS_NTFY_API_S_VER_11 */
struct iwl_notif_statistics {
__le32 flag;
struct mvm_statistics_rx rx;
struct mvm_statistics_tx tx;
struct mvm_statistics_general general;
struct mvm_statistics_load load_stats;
} __packed; /* STATISTICS_NTFY_API_S_VER_13 */
/**
* enum iwl_statistics_notif_flags - flags used in statistics notification
* @IWL_STATISTICS_REPLY_FLG_CLEAR: statistics were cleared after this report
*/
enum iwl_statistics_notif_flags {
IWL_STATISTICS_REPLY_FLG_CLEAR = 0x1,
};
/**
* enum iwl_statistics_cmd_flags - flags used in statistics command
* @IWL_STATISTICS_FLG_CLEAR: request to clear statistics after the report
* that's sent after this command
* @IWL_STATISTICS_FLG_DISABLE_NOTIF: disable unilateral statistics
* notifications
*/
enum iwl_statistics_cmd_flags {
IWL_STATISTICS_FLG_CLEAR = 0x1,
IWL_STATISTICS_FLG_DISABLE_NOTIF = 0x2,
};
/**
* struct iwl_statistics_cmd - statistics config command
* @flags: flags from &enum iwl_statistics_cmd_flags
*/
struct iwl_statistics_cmd {
__le32 flags;
} __packed; /* STATISTICS_CMD_API_S_VER_1 */
#define MAX_BCAST_FILTER_NUM 8
/**
* enum iwl_fw_statistics_type
*
* @FW_STATISTICS_OPERATIONAL: operational statistics
* @FW_STATISTICS_PHY: phy statistics
* @FW_STATISTICS_MAC: mac statistics
* @FW_STATISTICS_RX: rx statistics
* @FW_STATISTICS_TX: tx statistics
* @FW_STATISTICS_DURATION: duration statistics
* @FW_STATISTICS_HE: he statistics
*/
enum iwl_fw_statistics_type {
FW_STATISTICS_OPERATIONAL,
FW_STATISTICS_PHY,
FW_STATISTICS_MAC,
FW_STATISTICS_RX,
FW_STATISTICS_TX,
FW_STATISTICS_DURATION,
FW_STATISTICS_HE,
}; /* FW_STATISTICS_TYPE_API_E_VER_1 */
/**
* struct iwl_statistics_ntfy_hdr
*
* @type: struct type
* @version: version of the struct
* @size: size in bytes
*/
struct iwl_statistics_ntfy_hdr {
u8 type;
u8 version;
__le16 size;
}; /* STATISTICS_NTFY_HDR_API_S_VER_1 */
/**
* struct iwl_statistics_operational_ntfy
*
* @hdr: general statistics header
* @flags: bitmap of possible notification structures
* @mac_id: mac on which the beacon was received
* @beacon_filter_average_energy: Average energy [-dBm] of the 2
* antennas.
* @beacon_filter_reason: beacon filter reason
* @radio_temperature: radio temperature
* @air_time: air time
* @beacon_counter: all beacons (both filtered and not filtered)
* @beacon_average_energy: all beacons (both filtered and not
* filtered)
* @beacon_rssi_a: beacon RSSI on antenna A
* @beacon_rssi_b: beacon RSSI on antenna B
* @rx_bytes: per MAC RX byte count
* @rx_time: rx time
* @tx_time: usec the radio is transmitting.
* @on_time_rf: The total time in usec the RF is awake.
* @on_time_scan: usec the radio is awake due to scan.
* @average_energy: in fact it is minus the energy..
* @reserved: reserved
*/
struct iwl_statistics_operational_ntfy {
struct iwl_statistics_ntfy_hdr hdr;
__le32 flags;
__le32 mac_id;
__le32 beacon_filter_average_energy;
__le32 beacon_filter_reason;
__le32 radio_temperature;
__le32 air_time[MAC_INDEX_AUX];
__le32 beacon_counter[MAC_INDEX_AUX];
__le32 beacon_average_energy[MAC_INDEX_AUX];
__le32 beacon_rssi_a;
__le32 beacon_rssi_b;
__le32 rx_bytes[MAC_INDEX_AUX];
__le64 rx_time;
__le64 tx_time;
__le64 on_time_rf;
__le64 on_time_scan;
__le32 average_energy[IWL_MVM_STATION_COUNT_MAX];
__le32 reserved;
} __packed; /* STATISTICS_OPERATIONAL_NTFY_API_S_VER_14 */
/**
* struct iwl_statistics_phy_ntfy
*
* @hdr: general statistics header
* RX PHY related statistics
* @energy_and_config: ???
* @rssi_band: @31:24 rssiAllBand_B, 23:16 rssiInBand_B, 15:8
* rssiAllBand_A, 7:0 rssiInBand_A
* @agc_word: @31:16 agcWord_B, 15:0 agcWord_A
* @agc_gain: @19:10 agcGain_B, 9:0 agcGain_A
* @dfe_gain: @19:10 dfeGain_B, 9:0 dfeGain_A
* @snr_calc_main: @18:0 snrCalcMain
* @energy_calc_main: @18:0 energyCalcMain
* @snr_calc_aux: @18:0 snrCalcAux
* @dsp_dc_estim_a: @27:14 dspDcEstimQA, 13:0 dspDcEstimIA
* @dsp_dc_estim_b: @27:14 dspDcEstimQB, 13:0 dspDcEstimIB
* @ina_detec_type_and_ofdm_corr_comb: @31:31 inaDetectCckMrc,
* 30:27 inaDetectType, 26:0 ofdmCorrComb
* @cw_corr_comb: @26:0 cwCorrComb
* @rssi_comb: @25:0 rssiComb
* @auto_corr_cck: @23:12 autoCck, 11:00 crossCck
* @ofdm_fine_freq_and_pina_freq_err: @18:7 ofdmFineFreq, 6:0
* ofdmPinaFreqErr
* @snrm_evm_main: @31:0 snrmEvmMain
* @snrm_evm_aux: @31:0 snrmEvmAux
* @rx_rate: @31:0 rate
* TX PHY related statistics
* @per_chain_enums_and_dsp_atten_a: @perChainEnumsAndDspAtten
* (per version)
* @target_power_and_power_meas_a: @31:16 targetPower_A, 15:0
* powerMeasuredCalc_A
* @tx_config_as_i_and_ac_a: @31:16 txConfigAsI_A, 15:0
* txConfigAc_A
* @predist_dcq_and_dci_a: @31:16 predist_dci_A, 15:0
* predist_dcq_A
* @per_chain_enums_and_dsp_atten_b: @perChainEnumsAndDspAtten
* (per version)
* @target_power_and_power_meas_b: @31:16 targetPower_B, 15:0
* powerMeasuredCalc_B
* @tx_config_as_i_and_ac_b: @31:16 txConfigAsI_B, 15:0
* txConfigAc_B
* @predist_dcq_and_dci_b: @31:16 predist_dci_B, 15:0
* predist_dcq_B
* @tx_rate: @31:0 rate
* @tlc_backoff: @31:0 tlcBackoff
* @mpapd_calib_mode_mpapd_calib_type_a: @31:16
* mpapdCalibMode_A, 15:0 mpapdCalibType_A
* @psat_and_phy_power_limit_a: @31:16 psat_A, 15:0
* phyPowerLimit_A
* @sar_and_regulatory_power_limit_a: @31:16 sarPowerLimit_A,
* 15:0 regulatoryPowerLimit_A
* @mpapd_calib_mode_mpapd_calib_type_b: @31:16
* mpapdCalibMode_B, 15:0 mpapdCalibType_B
* @psat_and_phy_power_limit_b: @31:16 psat_B, 15:0
* phyPowerLimit_B
* @sar_and_regulatory_power_limit_b: @31:16 sarPowerLimit_B,
* 15:0 regulatoryPowerLimit_B
* @srd_and_driver_power_limits: @31:16 srdPowerLimit, 15:0
* driverPowerLimit
* @reserved: reserved
*/
struct iwl_statistics_phy_ntfy {
struct iwl_statistics_ntfy_hdr hdr;
__le32 energy_and_config;
__le32 rssi_band;
__le32 agc_word;
__le32 agc_gain;
__le32 dfe_gain;
__le32 snr_calc_main;
__le32 energy_calc_main;
__le32 snr_calc_aux;
__le32 dsp_dc_estim_a;
__le32 dsp_dc_estim_b;
__le32 ina_detec_type_and_ofdm_corr_comb;
__le32 cw_corr_comb;
__le32 rssi_comb;
__le32 auto_corr_cck;
__le32 ofdm_fine_freq_and_pina_freq_err;
__le32 snrm_evm_main;
__le32 snrm_evm_aux;
__le32 rx_rate;
__le32 per_chain_enums_and_dsp_atten_a;
__le32 target_power_and_power_meas_a;
__le32 tx_config_as_i_and_ac_a;
__le32 predist_dcq_and_dci_a;
__le32 per_chain_enums_and_dsp_atten_b;
__le32 target_power_and_power_meas_b;
__le32 tx_config_as_i_and_ac_b;
__le32 predist_dcq_and_dci_b;
__le32 tx_rate;
__le32 tlc_backoff;
__le32 mpapd_calib_mode_mpapd_calib_type_a;
__le32 psat_and_phy_power_limit_a;
__le32 sar_and_regulatory_power_limit_a;
__le32 mpapd_calib_mode_mpapd_calib_type_b;
__le32 psat_and_phy_power_limit_b;
__le32 sar_and_regulatory_power_limit_b;
__le32 srd_and_driver_power_limits;
__le32 reserved;
} __packed; /* STATISTICS_PHY_NTFY_API_S_VER_1 */
/**
* struct iwl_statistics_mac_ntfy
*
* @hdr: general statistics header
* @bcast_filter_passed_per_mac: bcast filter passed per mac
* @bcast_filter_dropped_per_mac: bcast filter dropped per mac
* @bcast_filter_passed_per_filter: bcast filter passed per filter
* @bcast_filter_dropped_per_filter: bcast filter dropped per filter
* @reserved: reserved
*/
struct iwl_statistics_mac_ntfy {
struct iwl_statistics_ntfy_hdr hdr;
__le32 bcast_filter_passed_per_mac[NUM_MAC_INDEX_CDB];
__le32 bcast_filter_dropped_per_mac[NUM_MAC_INDEX_CDB];
__le32 bcast_filter_passed_per_filter[MAX_BCAST_FILTER_NUM];
__le32 bcast_filter_dropped_per_filter[MAX_BCAST_FILTER_NUM];
__le32 reserved;
} __packed; /* STATISTICS_MAC_NTFY_API_S_VER_1 */
/**
* struct iwl_statistics_rx_ntfy
*
* @hdr: general statistics header
* @rx_agg_mpdu_cnt: aggregation frame count (number of
* delimiters)
* @rx_agg_cnt: number of RX Aggregations
* @unsupported_mcs: number of PLCP headers that have rate which
* is unsupported by DSP
* @bogus_cts: CTS received when not expecting CTS
* @bogus_ack: ACK received when not expecting ACK
* @rx_byte_count: ???
* @rx_packet_count: ???
* @missed_beacons: ???
* @unresponded_rts: un-responded RTS, due to NAV not zero
* @rxe_frame_limit_overrun: RXE got frame limit overrun
* @sent_ba_rsp_cnt: BA response TX count
* @late_rx_handle: count the number of times the RX path was
* aborted due to late entry
* @num_bt_kills: ???
* @reserved: reserved
*/
struct iwl_statistics_rx_ntfy {
struct iwl_statistics_ntfy_hdr hdr;
__le32 rx_agg_mpdu_cnt;
__le32 rx_agg_cnt;
__le32 unsupported_mcs;
__le32 bogus_cts;
__le32 bogus_ack;
__le32 rx_byte_count[MAC_INDEX_AUX];
__le32 rx_packet_count[MAC_INDEX_AUX];
__le32 missed_beacons;
__le32 unresponded_rts;
__le32 rxe_frame_limit_overrun;
__le32 sent_ba_rsp_cnt;
__le32 late_rx_handle;
__le32 num_bt_kills;
__le32 reserved;
} __packed; /* STATISTICS_RX_NTFY_API_S_VER_1 */
/**
* struct iwl_statistics_tx_ntfy
*
* @hdr: general statistics header
* @cts_timeout: timeout when waiting for CTS
* @ack_timeout: timeout when waiting for ACK
* @dump_msdu_cnt: number of MSDUs that were dumped due to any
* reason
* @burst_abort_missing_next_frame_cnt: number of times a burst
* was aborted due to missing next frame bytes in txfifo
* number of times got timeout when waiting for CTS/ACK/BA and energy was
* detected just after sending the RTS/DATA. this statistics may help getting
* interesting indicators, like the likelihood of collision (so the benefit of
* protection may be estimated Vs. its cost). Or how many of the failures are
* due to collision and how many due to SNR.
* For Link-quality the CTS collision indication is more reliable then the ACK
* collision indication as the RTS frame is short and has more chance that the
* frame/s which caused the collision continue after the RTS was sent.
* @cts_timeout_collision: ???
* ACK/BA failed and energy as detected after DATA
* Note: to get the collision ratio need to:
* ackOrBaTimeoutCollision / (ack_timeout + ba_timeout)
* @ack_or_ba_timeout_collision: ???
* @ba_timeout: timeout when waiting for immediate BA response
* @ba_reschedule_frames: failed to get BA response and
* rescheduled all the non-ACKed frames
* gives the avarage number of frames inside aggregation
* @scd_query_agg_frame_cnt: ???
* @scd_query_no_agg: scheduler query prevented aggregation
* @scd_query_agg: scheduler query allowed aggregation
* @scd_query_mismatch: scheduler query inaccurate, either too
* short or too long
* @agg_terminated_underrun: aggregation was terminated due to
* underrun
* @agg_terminated_bt_prio_kill: aggregation was terminated due
* to BT
* @tx_kill_on_long_retry: count the tx frames dropped due to
* long retry limit (DATA frame failed)
* @tx_kill_on_short_retry: count the tx frames dropped due to
* short retry limit (RTS frame failed)
* TX deffer on energy. This counter is reset on each successful transmit.
* When timer exceed TX deffer limit than will be uCode assert.
* @tx_deffer_counter: ???
* @tx_deffer_base_time: Keep the time of the last successful
* transmit
* @tx_underrun: TX killed due to underrun
* @bt_defer: TX deferred due to BT priority, so probably TX was
* not started.
* @tx_kill_on_dsp_timeout: TX killed on DSP problem detected
* @tx_kill_on_immediate_quiet: TX killed due to immediate quiet
* @kill_ba_cnt: number of times sending BA failed
* @kill_ack_cnt: number of times sending ACK failed
* @kill_cts_cnt: number of times sending CTS failed
* @burst_terminated: Count burst or fragmentation termination
* occurrence
* @late_tx_vec_wr_cnt: ???
* TX is not sent because ucode failed to notify the TRM in SIFS-delta from
* ON_AIR deassertion.
* @late_rx2_tx_cnt: ???
* @scd_query_cnt: count the times SCD query was done to check
* for TX AGG
* @tx_frames_acked_in_agg: count the number of frames
* transmitted inside AGG and were successful
* @last_tx_ch_width_indx: ???
* number of deferred TX per channel width, 0 - 20, 1/2/3 - 40/80/160
* @rx_detected_per_ch_width: ???
* @success_per_ch_width: ???
* @fail_per_ch_width: ???
* @reserved: reserved
*/
struct iwl_statistics_tx_ntfy {
struct iwl_statistics_ntfy_hdr hdr;
__le32 cts_timeout;
__le32 ack_timeout;
__le32 dump_msdu_cnt;
__le32 burst_abort_missing_next_frame_cnt;
__le32 cts_timeout_collision;
__le32 ack_or_ba_timeout_collision;
__le32 ba_timeout;
__le32 ba_reschedule_frames;
__le32 scd_query_agg_frame_cnt;
__le32 scd_query_no_agg;
__le32 scd_query_agg;
__le32 scd_query_mismatch;
__le32 agg_terminated_underrun;
__le32 agg_terminated_bt_prio_kill;
__le32 tx_kill_on_long_retry;
__le32 tx_kill_on_short_retry;
__le32 tx_deffer_counter;
__le32 tx_deffer_base_time;
__le32 tx_underrun;
__le32 bt_defer;
__le32 tx_kill_on_dsp_timeout;
__le32 tx_kill_on_immediate_quiet;
__le32 kill_ba_cnt;
__le32 kill_ack_cnt;
__le32 kill_cts_cnt;
__le32 burst_terminated;
__le32 late_tx_vec_wr_cnt;
__le32 late_rx2_tx_cnt;
__le32 scd_query_cnt;
__le32 tx_frames_acked_in_agg;
__le32 last_tx_ch_width_indx;
__le32 rx_detected_per_ch_width[4];
__le32 success_per_ch_width[4];
__le32 fail_per_ch_width[4];
__le32 reserved;
} __packed; /* STATISTICS_TX_NTFY_API_S_VER_1 */
/**
* struct iwl_statistics_duration_ntfy
*
* @hdr: general statistics header
* @cont_burst_chk_cnt: number of times continuation or
* fragmentation or bursting was checked
* @cont_burst_cnt: number of times continuation or fragmentation
* or bursting was successful
* @wait_for_silence_timeout_cnt: ???
* @reserved: reserved
*/
struct iwl_statistics_duration_ntfy {
struct iwl_statistics_ntfy_hdr hdr;
__le32 cont_burst_chk_cnt;
__le32 cont_burst_cnt;
__le32 wait_for_silence_timeout_cnt;
__le32 reserved;
} __packed; /* STATISTICS_DURATION_NTFY_API_S_VER_1 */
/**
* struct iwl_statistics_he_ntfy
*
* @hdr: general statistics header
* received HE frames
* @rx_siga_valid_cnt: rx HE SIG-A valid
* @rx_siga_invalid_cnt: rx HE SIG-A invalid
* received HE frames w/ valid Sig-A
* @rx_trig_based_frame_cnt: rx HE-TB (trig-based)
* @rx_su_frame_cnt: rx HE-SU
* @rx_sigb_invalid_cnt: rx (suspected) HE-MU w/ bad SIG-B
* @rx_our_bss_color_cnt: rx valid HE SIG-A w/ our BSS color
* @rx_other_bss_color_cnt: rx valid HE SIG-A w/ other BSS color
* @rx_zero_bss_color_cnt: ???
* received HE-MU frames w/ good Sig-B
* @rx_mu_for_us_cnt: match AID
* @rx_mu_not_for_us_cnt: no matched AID
* received HE-MU frames for us (w/ our AID)
* @rx_mu_nss_ar: 0 - SISO, 1 - MIMO2
* @rx_mu_mimo_cnt: full BW RU, compressed SIG-B
* @rx_mu_ru_bw_ar: MU alloc, MHz: 0 - 2, 1 - 5, 2 - 10, 3 - 20,
* 4 - 40, 5 - 80, 6 - 160
* received trigger frames
* @rx_trig_for_us_cnt: ???
* @rx_trig_not_for_us_cnt: ???
* trigger for us
* @rx_trig_with_cs_req_cnt: ???
* @rx_trig_type_ar: ???
* @rx_trig_in_agg_cnt: ???
* basic trigger for us allocations
* @rx_basic_trig_alloc_nss_ar: ???
* @rx_basic_trig_alloc_mu_mimo_cnt: ???
* @rx_basic_trig_alloc_ru_bw_ar: ???
* @rx_basic_trig_total_byte_cnt: ???
* trig-based TX
* @tx_trig_based_cs_req_fail_cnt: ???
* @tx_trig_based_sifs_ok_cnt: ???
* @tx_trig_based_sifs_fail_cnt: ???
* @tx_trig_based_byte_cnt: ???
* @tx_trig_based_pad_byte_cnt: ???
* @tx_trig_based_frame_cnt: ???
* @tx_trig_based_acked_frame_cnt: ???
* @tx_trig_based_ack_timeout_cnt: ???
* HE-SU TX
* @tx_su_frame_cnt: ???
* EDCA <--> MU-EDCA transitions
* @tx_edca_to_mu_edca_cnt: ???
* @tx_mu_edca_to_edca_by_timeout_cnt: ???
* @tx_mu_edca_to_edca_by_ack_fail_cnt: ???
* @tx_mu_edca_to_edca_by_small_alloc_cnt: ???
* @reserved: reserved
*/
struct iwl_statistics_he_ntfy {
struct iwl_statistics_ntfy_hdr hdr;
__le32 rx_siga_valid_cnt;
__le32 rx_siga_invalid_cnt;
__le32 rx_trig_based_frame_cnt;
__le32 rx_su_frame_cnt;
__le32 rx_sigb_invalid_cnt;
__le32 rx_our_bss_color_cnt;
__le32 rx_other_bss_color_cnt;
__le32 rx_zero_bss_color_cnt;
__le32 rx_mu_for_us_cnt;
__le32 rx_mu_not_for_us_cnt;
__le32 rx_mu_nss_ar[2];
__le32 rx_mu_mimo_cnt;
__le32 rx_mu_ru_bw_ar[7];
__le32 rx_trig_for_us_cnt;
__le32 rx_trig_not_for_us_cnt;
__le32 rx_trig_with_cs_req_cnt;
__le32 rx_trig_type_ar[8 + 1];
__le32 rx_trig_in_agg_cnt;
__le32 rx_basic_trig_alloc_nss_ar[2];
__le32 rx_basic_trig_alloc_mu_mimo_cnt;
__le32 rx_basic_trig_alloc_ru_bw_ar[7];
__le32 rx_basic_trig_total_byte_cnt;
__le32 tx_trig_based_cs_req_fail_cnt;
__le32 tx_trig_based_sifs_ok_cnt;
__le32 tx_trig_based_sifs_fail_cnt;
__le32 tx_trig_based_byte_cnt;
__le32 tx_trig_based_pad_byte_cnt;
__le32 tx_trig_based_frame_cnt;
__le32 tx_trig_based_acked_frame_cnt;
__le32 tx_trig_based_ack_timeout_cnt;
__le32 tx_su_frame_cnt;
__le32 tx_edca_to_mu_edca_cnt;
__le32 tx_mu_edca_to_edca_by_timeout_cnt;
__le32 tx_mu_edca_to_edca_by_ack_fail_cnt;
__le32 tx_mu_edca_to_edca_by_small_alloc_cnt;
__le32 reserved;
} __packed; /* STATISTICS_HE_NTFY_API_S_VER_1 */
#endif /* __iwl_fw_api_stats_h__ */

View File

@ -0,0 +1,161 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2012-2014, 2018 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
#ifndef __iwl_fw_api_tdls_h__
#define __iwl_fw_api_tdls_h__
#include "fw/api/tx.h"
#include "fw/api/phy-ctxt.h"
#define IWL_MVM_TDLS_STA_COUNT 4
/* Type of TDLS request */
enum iwl_tdls_channel_switch_type {
TDLS_SEND_CHAN_SW_REQ = 0,
TDLS_SEND_CHAN_SW_RESP_AND_MOVE_CH,
TDLS_MOVE_CH,
}; /* TDLS_STA_CHANNEL_SWITCH_CMD_TYPE_API_E_VER_1 */
/**
* struct iwl_tdls_channel_switch_timing - Switch timing in TDLS channel-switch
* @frame_timestamp: GP2 timestamp of channel-switch request/response packet
* received from peer
* @max_offchan_duration: What amount of microseconds out of a DTIM is given
* to the TDLS off-channel communication. For instance if the DTIM is
* 200TU and the TDLS peer is to be given 25% of the time, the value
* given will be 50TU, or 50 * 1024 if translated into microseconds.
* @switch_time: switch time the peer sent in its channel switch timing IE
* @switch_timeout: switch timeout the peer sent in its channel switch timing IE
*/
struct iwl_tdls_channel_switch_timing {
__le32 frame_timestamp; /* GP2 time of peer packet Rx */
__le32 max_offchan_duration; /* given in micro-seconds */
__le32 switch_time; /* given in micro-seconds */
__le32 switch_timeout; /* given in micro-seconds */
} __packed; /* TDLS_STA_CHANNEL_SWITCH_TIMING_DATA_API_S_VER_1 */
#define IWL_TDLS_CH_SW_FRAME_MAX_SIZE 200
/**
* struct iwl_tdls_channel_switch_frame - TDLS channel switch frame template
*
* A template representing a TDLS channel-switch request or response frame
*
* @switch_time_offset: offset to the channel switch timing IE in the template
* @tx_cmd: Tx parameters for the frame
* @data: frame data
*/
struct iwl_tdls_channel_switch_frame {
__le32 switch_time_offset;
struct iwl_tx_cmd tx_cmd;
u8 data[IWL_TDLS_CH_SW_FRAME_MAX_SIZE];
} __packed; /* TDLS_STA_CHANNEL_SWITCH_FRAME_API_S_VER_1 */
/**
* struct iwl_tdls_channel_switch_cmd_tail - tail of iwl_tdls_channel_switch_cmd
*
* @timing: timing related data for command
* @frame: channel-switch request/response template, depending to switch_type
*/
struct iwl_tdls_channel_switch_cmd_tail {
struct iwl_tdls_channel_switch_timing timing;
struct iwl_tdls_channel_switch_frame frame;
} __packed;
/**
* struct iwl_tdls_channel_switch_cmd - TDLS channel switch command
*
* The command is sent to initiate a channel switch and also in response to
* incoming TDLS channel-switch request/response packets from remote peers.
*
* @switch_type: see &enum iwl_tdls_channel_switch_type
* @peer_sta_id: station id of TDLS peer
* @ci: channel we switch to
* @tail: command tail
*/
struct iwl_tdls_channel_switch_cmd {
u8 switch_type;
__le32 peer_sta_id;
struct iwl_fw_channel_info ci;
struct iwl_tdls_channel_switch_cmd_tail tail;
} __packed; /* TDLS_STA_CHANNEL_SWITCH_CMD_API_S_VER_1 */
/**
* struct iwl_tdls_channel_switch_notif - TDLS channel switch start notification
*
* @status: non-zero on success
* @offchannel_duration: duration given in microseconds
* @sta_id: peer currently performing the channel-switch with
*/
struct iwl_tdls_channel_switch_notif {
__le32 status;
__le32 offchannel_duration;
__le32 sta_id;
} __packed; /* TDLS_STA_CHANNEL_SWITCH_NTFY_API_S_VER_1 */
/**
* struct iwl_tdls_sta_info - TDLS station info
*
* @sta_id: station id of the TDLS peer
* @tx_to_peer_tid: TID reserved vs. the peer for FW based Tx
* @tx_to_peer_ssn: initial SSN the FW should use for Tx on its TID vs the peer
* @is_initiator: 1 if the peer is the TDLS link initiator, 0 otherwise
*/
struct iwl_tdls_sta_info {
u8 sta_id;
u8 tx_to_peer_tid;
__le16 tx_to_peer_ssn;
__le32 is_initiator;
} __packed; /* TDLS_STA_INFO_VER_1 */
/**
* struct iwl_tdls_config_cmd - TDLS basic config command
*
* @id_and_color: MAC id and color being configured
* @tdls_peer_count: amount of currently connected TDLS peers
* @tx_to_ap_tid: TID reverved vs. the AP for FW based Tx
* @tx_to_ap_ssn: initial SSN the FW should use for Tx on its TID vs. the AP
* @sta_info: per-station info. Only the first tdls_peer_count entries are set
* @pti_req_data_offset: offset of network-level data for the PTI template
* @pti_req_tx_cmd: Tx parameters for PTI request template
* @pti_req_template: PTI request template data
*/
struct iwl_tdls_config_cmd {
__le32 id_and_color; /* mac id and color */
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];
__le32 pti_req_data_offset;
struct iwl_tx_cmd pti_req_tx_cmd;
u8 pti_req_template[0];
} __packed; /* TDLS_CONFIG_CMD_API_S_VER_1 */
/**
* struct iwl_tdls_config_sta_info_res - TDLS per-station config information
*
* @sta_id: station id of the TDLS peer
* @tx_to_peer_last_seq: last sequence number used by FW during FW-based Tx to
* the peer
*/
struct iwl_tdls_config_sta_info_res {
__le16 sta_id;
__le16 tx_to_peer_last_seq;
} __packed; /* TDLS_STA_INFO_RSP_VER_1 */
/**
* struct iwl_tdls_config_res - TDLS config information from FW
*
* @tx_to_ap_last_seq: last sequence number used by FW during FW-based Tx to AP
* @sta_info: per-station TDLS config information
*/
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];
} __packed; /* TDLS_CONFIG_RSP_API_S_VER_1 */
#endif /* __iwl_fw_api_tdls_h__ */

View File

@ -0,0 +1,418 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2012-2014, 2018-2020 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
#ifndef __iwl_fw_api_time_event_h__
#define __iwl_fw_api_time_event_h__
#include "fw/api/phy-ctxt.h"
/* Time Event types, according to MAC type */
enum iwl_time_event_type {
/* BSS Station Events */
TE_BSS_STA_AGGRESSIVE_ASSOC,
TE_BSS_STA_ASSOC,
TE_BSS_EAP_DHCP_PROT,
TE_BSS_QUIET_PERIOD,
/* P2P Device Events */
TE_P2P_DEVICE_DISCOVERABLE,
TE_P2P_DEVICE_LISTEN,
TE_P2P_DEVICE_ACTION_SCAN,
TE_P2P_DEVICE_FULL_SCAN,
/* P2P Client Events */
TE_P2P_CLIENT_AGGRESSIVE_ASSOC,
TE_P2P_CLIENT_ASSOC,
TE_P2P_CLIENT_QUIET_PERIOD,
/* P2P GO Events */
TE_P2P_GO_ASSOC_PROT,
TE_P2P_GO_REPETITIVET_NOA,
TE_P2P_GO_CT_WINDOW,
/* WiDi Sync Events */
TE_WIDI_TX_SYNC,
/* Channel Switch NoA */
TE_CHANNEL_SWITCH_PERIOD,
TE_MAX
}; /* MAC_EVENT_TYPE_API_E_VER_1 */
/* Time event - defines for command API v1 */
/*
* @TE_V1_FRAG_NONE: fragmentation of the time event is NOT allowed.
* @TE_V1_FRAG_SINGLE: fragmentation of the time event is allowed, but only
* the first fragment is scheduled.
* @TE_V1_FRAG_DUAL: fragmentation of the time event is allowed, but only
* the first 2 fragments are scheduled.
* @TE_V1_FRAG_ENDLESS: fragmentation of the time event is allowed, and any
* number of fragments are valid.
*
* Other than the constant defined above, specifying a fragmentation value 'x'
* means that the event can be fragmented but only the first 'x' will be
* scheduled.
*/
enum {
TE_V1_FRAG_NONE = 0,
TE_V1_FRAG_SINGLE = 1,
TE_V1_FRAG_DUAL = 2,
TE_V1_FRAG_ENDLESS = 0xffffffff
};
/* If a Time Event can be fragmented, this is the max number of fragments */
#define TE_V1_FRAG_MAX_MSK 0x0fffffff
/* Repeat the time event endlessly (until removed) */
#define TE_V1_REPEAT_ENDLESS 0xffffffff
/* If a Time Event has bounded repetitions, this is the maximal value */
#define TE_V1_REPEAT_MAX_MSK_V1 0x0fffffff
/* Time Event dependencies: none, on another TE, or in a specific time */
enum {
TE_V1_INDEPENDENT = 0,
TE_V1_DEP_OTHER = BIT(0),
TE_V1_DEP_TSF = BIT(1),
TE_V1_EVENT_SOCIOPATHIC = BIT(2),
}; /* MAC_EVENT_DEPENDENCY_POLICY_API_E_VER_2 */
/*
* @TE_V1_NOTIF_NONE: no notifications
* @TE_V1_NOTIF_HOST_EVENT_START: request/receive notification on event start
* @TE_V1_NOTIF_HOST_EVENT_END:request/receive notification on event end
* @TE_V1_NOTIF_INTERNAL_EVENT_START: internal FW use
* @TE_V1_NOTIF_INTERNAL_EVENT_END: internal FW use.
* @TE_V1_NOTIF_HOST_FRAG_START: request/receive notification on frag start
* @TE_V1_NOTIF_HOST_FRAG_END:request/receive notification on frag end
* @TE_V1_NOTIF_INTERNAL_FRAG_START: internal FW use.
* @TE_V1_NOTIF_INTERNAL_FRAG_END: internal FW use.
*
* Supported Time event notifications configuration.
* A notification (both event and fragment) includes a status indicating weather
* the FW was able to schedule the event or not. For fragment start/end
* notification the status is always success. There is no start/end fragment
* notification for monolithic events.
*/
enum {
TE_V1_NOTIF_NONE = 0,
TE_V1_NOTIF_HOST_EVENT_START = BIT(0),
TE_V1_NOTIF_HOST_EVENT_END = BIT(1),
TE_V1_NOTIF_INTERNAL_EVENT_START = BIT(2),
TE_V1_NOTIF_INTERNAL_EVENT_END = BIT(3),
TE_V1_NOTIF_HOST_FRAG_START = BIT(4),
TE_V1_NOTIF_HOST_FRAG_END = BIT(5),
TE_V1_NOTIF_INTERNAL_FRAG_START = BIT(6),
TE_V1_NOTIF_INTERNAL_FRAG_END = BIT(7),
}; /* MAC_EVENT_ACTION_API_E_VER_2 */
/* Time event - defines for command API */
/*
* @TE_V2_FRAG_NONE: fragmentation of the time event is NOT allowed.
* @TE_V2_FRAG_SINGLE: fragmentation of the time event is allowed, but only
* the first fragment is scheduled.
* @TE_V2_FRAG_DUAL: fragmentation of the time event is allowed, but only
* the first 2 fragments are scheduled.
* @TE_V2_FRAG_ENDLESS: fragmentation of the time event is allowed, and any
* number of fragments are valid.
*
* Other than the constant defined above, specifying a fragmentation value 'x'
* means that the event can be fragmented but only the first 'x' will be
* scheduled.
*/
enum {
TE_V2_FRAG_NONE = 0,
TE_V2_FRAG_SINGLE = 1,
TE_V2_FRAG_DUAL = 2,
TE_V2_FRAG_MAX = 0xfe,
TE_V2_FRAG_ENDLESS = 0xff
};
/* Repeat the time event endlessly (until removed) */
#define TE_V2_REPEAT_ENDLESS 0xff
/* If a Time Event has bounded repetitions, this is the maximal value */
#define TE_V2_REPEAT_MAX 0xfe
#define TE_V2_PLACEMENT_POS 12
#define TE_V2_ABSENCE_POS 15
/**
* enum iwl_time_event_policy - Time event policy values
* A notification (both event and fragment) includes a status indicating weather
* the FW was able to schedule the event or not. For fragment start/end
* notification the status is always success. There is no start/end fragment
* notification for monolithic events.
*
* @TE_V2_DEFAULT_POLICY: independent, social, present, unoticable
* @TE_V2_NOTIF_HOST_EVENT_START: request/receive notification on event start
* @TE_V2_NOTIF_HOST_EVENT_END:request/receive notification on event end
* @TE_V2_NOTIF_INTERNAL_EVENT_START: internal FW use
* @TE_V2_NOTIF_INTERNAL_EVENT_END: internal FW use.
* @TE_V2_NOTIF_HOST_FRAG_START: request/receive notification on frag start
* @TE_V2_NOTIF_HOST_FRAG_END:request/receive notification on frag end
* @TE_V2_NOTIF_INTERNAL_FRAG_START: internal FW use.
* @TE_V2_NOTIF_INTERNAL_FRAG_END: internal FW use.
* @TE_V2_START_IMMEDIATELY: start time event immediately
* @TE_V2_DEP_OTHER: depends on another time event
* @TE_V2_DEP_TSF: depends on a specific time
* @TE_V2_EVENT_SOCIOPATHIC: can't co-exist with other events of tha same MAC
* @TE_V2_ABSENCE: are we present or absent during the Time Event.
*/
enum iwl_time_event_policy {
TE_V2_DEFAULT_POLICY = 0x0,
/* notifications (event start/stop, fragment start/stop) */
TE_V2_NOTIF_HOST_EVENT_START = BIT(0),
TE_V2_NOTIF_HOST_EVENT_END = BIT(1),
TE_V2_NOTIF_INTERNAL_EVENT_START = BIT(2),
TE_V2_NOTIF_INTERNAL_EVENT_END = BIT(3),
TE_V2_NOTIF_HOST_FRAG_START = BIT(4),
TE_V2_NOTIF_HOST_FRAG_END = BIT(5),
TE_V2_NOTIF_INTERNAL_FRAG_START = BIT(6),
TE_V2_NOTIF_INTERNAL_FRAG_END = BIT(7),
TE_V2_START_IMMEDIATELY = BIT(11),
/* placement characteristics */
TE_V2_DEP_OTHER = BIT(TE_V2_PLACEMENT_POS),
TE_V2_DEP_TSF = BIT(TE_V2_PLACEMENT_POS + 1),
TE_V2_EVENT_SOCIOPATHIC = BIT(TE_V2_PLACEMENT_POS + 2),
/* are we present or absent during the Time Event. */
TE_V2_ABSENCE = BIT(TE_V2_ABSENCE_POS),
};
/**
* struct iwl_time_event_cmd - configuring Time Events
* with struct MAC_TIME_EVENT_DATA_API_S_VER_2 (see also
* with version 1. determined by IWL_UCODE_TLV_FLAGS)
* ( TIME_EVENT_CMD = 0x29 )
* @id_and_color: ID and color of the relevant MAC,
* &enum iwl_ctxt_id_and_color
* @action: action to perform, one of &enum iwl_ctxt_action
* @id: this field has two meanings, depending on the action:
* If the action is ADD, then it means the type of event to add.
* For all other actions it is the unique event ID assigned when the
* event was added by the FW.
* @apply_time: When to start the Time Event (in GP2)
* @max_delay: maximum delay to event's start (apply time), in TU
* @depends_on: the unique ID of the event we depend on (if any)
* @interval: interval between repetitions, in TU
* @duration: duration of event in TU
* @repeat: how many repetitions to do, can be TE_REPEAT_ENDLESS
* @max_frags: maximal number of fragments the Time Event can be divided to
* @policy: defines whether uCode shall notify the host or other uCode modules
* on event and/or fragment start and/or end
* using one of TE_INDEPENDENT, TE_DEP_OTHER, TE_DEP_TSF
* TE_EVENT_SOCIOPATHIC
* using TE_ABSENCE and using TE_NOTIF_*,
* &enum iwl_time_event_policy
*/
struct iwl_time_event_cmd {
/* COMMON_INDEX_HDR_API_S_VER_1 */
__le32 id_and_color;
__le32 action;
__le32 id;
/* MAC_TIME_EVENT_DATA_API_S_VER_2 */
__le32 apply_time;
__le32 max_delay;
__le32 depends_on;
__le32 interval;
__le32 duration;
u8 repeat;
u8 max_frags;
__le16 policy;
} __packed; /* MAC_TIME_EVENT_CMD_API_S_VER_2 */
/**
* struct iwl_time_event_resp - response structure to iwl_time_event_cmd
* @status: bit 0 indicates success, all others specify errors
* @id: the Time Event type
* @unique_id: the unique ID assigned (in ADD) or given (others) to the TE
* @id_and_color: ID and color of the relevant MAC,
* &enum iwl_ctxt_id_and_color
*/
struct iwl_time_event_resp {
__le32 status;
__le32 id;
__le32 unique_id;
__le32 id_and_color;
} __packed; /* MAC_TIME_EVENT_RSP_API_S_VER_1 */
/**
* struct iwl_time_event_notif - notifications of time event start/stop
* ( TIME_EVENT_NOTIFICATION = 0x2a )
* @timestamp: action timestamp in GP2
* @session_id: session's unique id
* @unique_id: unique id of the Time Event itself
* @id_and_color: ID and color of the relevant MAC
* @action: &enum iwl_time_event_policy
* @status: true if scheduled, false otherwise (not executed)
*/
struct iwl_time_event_notif {
__le32 timestamp;
__le32 session_id;
__le32 unique_id;
__le32 id_and_color;
__le32 action;
__le32 status;
} __packed; /* MAC_TIME_EVENT_NTFY_API_S_VER_1 */
/*
* struct iwl_hs20_roc_req_tail - tail of iwl_hs20_roc_req
*
* @node_addr: Our MAC Address
* @reserved: reserved for alignment
* @apply_time: GP2 value to start (should always be the current GP2 value)
* @apply_time_max_delay: Maximum apply time delay value in TU. Defines max
* time by which start of the event is allowed to be postponed.
* @duration: event duration in TU To calculate event duration:
* timeEventDuration = min(duration, remainingQuota)
*/
struct iwl_hs20_roc_req_tail {
u8 node_addr[ETH_ALEN];
__le16 reserved;
__le32 apply_time;
__le32 apply_time_max_delay;
__le32 duration;
} __packed;
/*
* Aux ROC command
*
* Command requests the firmware to create a time event for a certain duration
* and remain on the given channel. This is done by using the Aux framework in
* the FW.
* The command was first used for Hot Spot issues - but can be used regardless
* to Hot Spot.
*
* ( HOT_SPOT_CMD 0x53 )
*
* @id_and_color: ID and color of the MAC
* @action: action to perform, one of FW_CTXT_ACTION_*
* @event_unique_id: If the action FW_CTXT_ACTION_REMOVE then the
* event_unique_id should be the id of the time event assigned by ucode.
* Otherwise ignore the event_unique_id.
* @sta_id_and_color: station id and color, resumed during "Remain On Channel"
* activity.
* @channel_info: channel info
*/
struct iwl_hs20_roc_req {
/* COMMON_INDEX_HDR_API_S_VER_1 hdr */
__le32 id_and_color;
__le32 action;
__le32 event_unique_id;
__le32 sta_id_and_color;
struct iwl_fw_channel_info channel_info;
struct iwl_hs20_roc_req_tail tail;
} __packed; /* HOT_SPOT_CMD_API_S_VER_1 */
/*
* values for AUX ROC result values
*/
enum iwl_mvm_hot_spot {
HOT_SPOT_RSP_STATUS_OK,
HOT_SPOT_RSP_STATUS_TOO_MANY_EVENTS,
HOT_SPOT_MAX_NUM_OF_SESSIONS,
};
/*
* Aux ROC command response
*
* In response to iwl_hs20_roc_req the FW sends this command to notify the
* driver the uid of the timevent.
*
* ( HOT_SPOT_CMD 0x53 )
*
* @event_unique_id: Unique ID of time event assigned by ucode
* @status: Return status 0 is success, all the rest used for specific errors
*/
struct iwl_hs20_roc_res {
__le32 event_unique_id;
__le32 status;
} __packed; /* HOT_SPOT_RSP_API_S_VER_1 */
/**
* enum iwl_mvm_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.
* * A rather short event that can't be fragmented and with a very
* high priority. If every goes well (99% of the cases) the
* association should complete within this first event. During
* that event, no other activity will happen in the firmware,
* which is why it can't be too long.
* The length of this event is hard-coded in the firmware: 300TUs.
* * Another event which can be much longer (it's duration is
* configurable by the driver) which has a slightly lower
* priority and that can be fragmented allowing other activities
* to run while this event is running.
* The firmware will automatically remove both events once the driver sets
* the BSS MAC as associated. Neither of the events will be removed
* for the P2P_STA MAC.
* Only the duration is configurable for this protection.
* @SESSION_PROTECT_CONF_GO_CLIENT_ASSOC: not used
* @SESSION_PROTECT_CONF_P2P_DEVICE_DISCOV: Schedule the P2P Device to be in
* 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
* 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 {
SESSION_PROTECT_CONF_ASSOC,
SESSION_PROTECT_CONF_GO_CLIENT_ASSOC,
SESSION_PROTECT_CONF_P2P_DEVICE_DISCOV,
SESSION_PROTECT_CONF_P2P_GO_NEGOTIATION,
SESSION_PROTECT_CONF_MAX_ID,
}; /* SESSION_PROTECTION_CONF_ID_E_VER_1 */
/**
* struct iwl_mvm_session_prot_cmd - configure a session protection
* @id_and_color: the id and color of the mac for which this session protection
* is sent
* @action: can be either FW_CTXT_ACTION_ADD or FW_CTXT_ACTION_REMOVE
* @conf_id: see &enum iwl_mvm_session_prot_conf_id
* @duration_tu: the duration of the whole protection in TUs.
* @repetition_count: not used
* @interval: not used
*
* Note: the session protection will always be scheduled to start as
* early as possible, but the maximum delay is configuration dependent.
* 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 {
/* COMMON_INDEX_HDR_API_S_VER_1 hdr */
__le32 id_and_color;
__le32 action;
__le32 conf_id;
__le32 duration_tu;
__le32 repetition_count;
__le32 interval;
} __packed; /* SESSION_PROTECTION_CMD_API_S_VER_1 */
/**
* struct iwl_mvm_session_prot_notif - session protection started / ended
* @mac_id: the mac id 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
*
* 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 {
__le32 mac_id;
__le32 status;
__le32 start;
__le32 conf_id;
} __packed; /* SESSION_PROTECTION_NOTIFICATION_API_S_VER_2 */
#endif /* __iwl_fw_api_time_event_h__ */

View File

@ -0,0 +1,952 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2012-2014, 2018-2021 Intel Corporation
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
#ifndef __iwl_fw_api_tx_h__
#define __iwl_fw_api_tx_h__
#include <linux/ieee80211.h>
/**
* enum iwl_tx_flags - bitmasks for tx_flags in TX command
* @TX_CMD_FLG_PROT_REQUIRE: use RTS or CTS-to-self to protect the frame
* @TX_CMD_FLG_WRITE_TX_POWER: update current tx power value in the mgmt frame
* @TX_CMD_FLG_ACK: expect ACK from receiving station
* @TX_CMD_FLG_STA_RATE: use RS table with initial index from the TX command.
* Otherwise, use rate_n_flags from the TX command
* @TX_CMD_FLG_BAR: this frame is a BA request, immediate BAR is expected
* Must set TX_CMD_FLG_ACK with this flag.
* @TX_CMD_FLG_TXOP_PROT: TXOP protection requested
* @TX_CMD_FLG_VHT_NDPA: mark frame is NDPA for VHT beamformer sequence
* @TX_CMD_FLG_HT_NDPA: mark frame is NDPA for HT beamformer sequence
* @TX_CMD_FLG_CSI_FDBK2HOST: mark to send feedback to host (only if good CRC)
* @TX_CMD_FLG_BT_PRIO_MASK: BT priority value
* @TX_CMD_FLG_BT_PRIO_POS: the position of the BT priority (bit 11 is ignored
* on old firmwares).
* @TX_CMD_FLG_BT_DIS: disable BT priority for this frame
* @TX_CMD_FLG_SEQ_CTL: set if FW should override the sequence control.
* Should be set for mgmt, non-QOS data, mcast, bcast and in scan command
* @TX_CMD_FLG_MORE_FRAG: this frame is non-last MPDU
* @TX_CMD_FLG_TSF: FW should calculate and insert TSF in the frame
* Should be set for beacons and probe responses
* @TX_CMD_FLG_CALIB: activate PA TX power calibrations
* @TX_CMD_FLG_KEEP_SEQ_CTL: if seq_ctl is set, don't increase inner seq count
* @TX_CMD_FLG_MH_PAD: driver inserted 2 byte padding after MAC header.
* Should be set for 26/30 length MAC headers
* @TX_CMD_FLG_RESP_TO_DRV: zero this if the response should go only to FW
* @TX_CMD_FLG_TKIP_MIC_DONE: FW already performed TKIP MIC calculation
* @TX_CMD_FLG_DUR: disable duration overwriting used in PS-Poll Assoc-id
* @TX_CMD_FLG_FW_DROP: FW should mark frame to be dropped
* @TX_CMD_FLG_EXEC_PAPD: execute PAPD
* @TX_CMD_FLG_PAPD_TYPE: 0 for reference power, 1 for nominal power
* @TX_CMD_FLG_HCCA_CHUNK: mark start of TSPEC chunk
*/
enum iwl_tx_flags {
TX_CMD_FLG_PROT_REQUIRE = BIT(0),
TX_CMD_FLG_WRITE_TX_POWER = BIT(1),
TX_CMD_FLG_ACK = BIT(3),
TX_CMD_FLG_STA_RATE = BIT(4),
TX_CMD_FLG_BAR = BIT(6),
TX_CMD_FLG_TXOP_PROT = BIT(7),
TX_CMD_FLG_VHT_NDPA = BIT(8),
TX_CMD_FLG_HT_NDPA = BIT(9),
TX_CMD_FLG_CSI_FDBK2HOST = BIT(10),
TX_CMD_FLG_BT_PRIO_POS = 11,
TX_CMD_FLG_BT_PRIO_MASK = BIT(11) | BIT(12),
TX_CMD_FLG_BT_DIS = BIT(12),
TX_CMD_FLG_SEQ_CTL = BIT(13),
TX_CMD_FLG_MORE_FRAG = BIT(14),
TX_CMD_FLG_TSF = BIT(16),
TX_CMD_FLG_CALIB = BIT(17),
TX_CMD_FLG_KEEP_SEQ_CTL = BIT(18),
TX_CMD_FLG_MH_PAD = BIT(20),
TX_CMD_FLG_RESP_TO_DRV = BIT(21),
TX_CMD_FLG_TKIP_MIC_DONE = BIT(23),
TX_CMD_FLG_DUR = BIT(25),
TX_CMD_FLG_FW_DROP = BIT(26),
TX_CMD_FLG_EXEC_PAPD = BIT(27),
TX_CMD_FLG_PAPD_TYPE = BIT(28),
TX_CMD_FLG_HCCA_CHUNK = BIT(31)
}; /* TX_FLAGS_BITS_API_S_VER_1 */
/**
* enum iwl_tx_cmd_flags - bitmasks for tx_flags in TX command for 22000
* @IWL_TX_FLAGS_CMD_RATE: use rate from the TX command
* @IWL_TX_FLAGS_ENCRYPT_DIS: frame should not be encrypted, even if it belongs
* to a secured STA
* @IWL_TX_FLAGS_HIGH_PRI: high priority frame (like EAPOL) - can affect rate
* selection, retry limits and BT kill
*/
enum iwl_tx_cmd_flags {
IWL_TX_FLAGS_CMD_RATE = BIT(0),
IWL_TX_FLAGS_ENCRYPT_DIS = BIT(1),
IWL_TX_FLAGS_HIGH_PRI = BIT(2),
/* Use these flags only from
* TX_FLAGS_BITS_API_S_VER_4 and above */
IWL_TX_FLAGS_RTS = BIT(3),
IWL_TX_FLAGS_CTS = BIT(4),
}; /* TX_FLAGS_BITS_API_S_VER_3 */
/**
* enum iwl_tx_pm_timeouts - pm timeout values in TX command
* @PM_FRAME_NONE: no need to suspend sleep mode
* @PM_FRAME_MGMT: fw suspend sleep mode for 100TU
* @PM_FRAME_ASSOC: fw suspend sleep mode for 10sec
*/
enum iwl_tx_pm_timeouts {
PM_FRAME_NONE = 0,
PM_FRAME_MGMT = 2,
PM_FRAME_ASSOC = 3,
};
#define TX_CMD_SEC_MSK 0x07
#define TX_CMD_SEC_WEP_KEY_IDX_POS 6
#define TX_CMD_SEC_WEP_KEY_IDX_MSK 0xc0
/**
* enum iwl_tx_cmd_sec_ctrl - bitmasks for security control in TX command
* @TX_CMD_SEC_WEP: WEP encryption algorithm.
* @TX_CMD_SEC_CCM: CCM encryption algorithm.
* @TX_CMD_SEC_TKIP: TKIP encryption algorithm.
* @TX_CMD_SEC_EXT: extended cipher algorithm.
* @TX_CMD_SEC_GCMP: GCMP encryption algorithm.
* @TX_CMD_SEC_KEY128: set for 104 bits WEP key.
* @TX_CMD_SEC_KEY_FROM_TABLE: for a non-WEP key, set if the key should be taken
* from the table instead of from the TX command.
* If the key is taken from the key table its index should be given by the
* first byte of the TX command key field.
*/
enum iwl_tx_cmd_sec_ctrl {
TX_CMD_SEC_WEP = 0x01,
TX_CMD_SEC_CCM = 0x02,
TX_CMD_SEC_TKIP = 0x03,
TX_CMD_SEC_EXT = 0x04,
TX_CMD_SEC_GCMP = 0x05,
TX_CMD_SEC_KEY128 = 0x08,
TX_CMD_SEC_KEY_FROM_TABLE = 0x10,
};
/*
* TX command Frame life time in us - to be written in pm_frame_timeout
*/
#define TX_CMD_LIFE_TIME_INFINITE 0xFFFFFFFF
#define TX_CMD_LIFE_TIME_DEFAULT 2000000 /* 2000 ms*/
#define TX_CMD_LIFE_TIME_PROBE_RESP 40000 /* 40 ms */
#define TX_CMD_LIFE_TIME_EXPIRED_FRAME 0
/*
* TID for non QoS frames - to be written in tid_tspec
*/
#define IWL_TID_NON_QOS 0
/*
* Limits on the retransmissions - to be written in {data,rts}_retry_limit
*/
#define IWL_DEFAULT_TX_RETRY 15
#define IWL_MGMT_DFAULT_RETRY_LIMIT 3
#define IWL_RTS_DFAULT_RETRY_LIMIT 60
#define IWL_BAR_DFAULT_RETRY_LIMIT 60
#define IWL_LOW_RETRY_LIMIT 7
/**
* enum iwl_tx_offload_assist_flags_pos - set %iwl_tx_cmd 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.
* This is used to help the offload in case there is tunneling such as
* IPv6 in IPv4, in such case the ip header offset should point to the
* inner ip header and IPv4 checksum of the external header should be
* calculated by driver.
* @TX_CMD_OFFLD_L4_EN: enable TCP/UDP checksum
* @TX_CMD_OFFLD_L3_EN: enable IP header checksum
* @TX_CMD_OFFLD_MH_SIZE: size of the mac header in words. Includes the IV
* field. Doesn't include the pad.
* @TX_CMD_OFFLD_PAD: mark 2-byte pad was inserted after the mac header for
* alignment
* @TX_CMD_OFFLD_AMSDU: mark TX command is A-MSDU
*/
enum iwl_tx_offload_assist_flags_pos {
TX_CMD_OFFLD_IP_HDR = 0,
TX_CMD_OFFLD_L4_EN = 6,
TX_CMD_OFFLD_L3_EN = 7,
TX_CMD_OFFLD_MH_SIZE = 8,
TX_CMD_OFFLD_PAD = 13,
TX_CMD_OFFLD_AMSDU = 14,
};
#define IWL_TX_CMD_OFFLD_MH_MASK 0x1f
#define IWL_TX_CMD_OFFLD_IP_HDR_MASK 0x3f
/* TODO: complete documentation for try_cnt and btkill_cnt */
/**
* struct iwl_tx_cmd - TX command struct to FW
* ( TX_CMD = 0x1c )
* @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
* @scratch: scratch buffer used by the device
* @rate_n_flags: rate for *all* Tx attempts, if TX_CMD_FLG_STA_RATE_MSK is
* 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.
* Applied if TX_CMD_FLG_STA_RATE_MSK is set, normally 0 for data frames.
* @reserved2: reserved
* @key: security key
* @reserved3: reserved
* @life_time: frame life time (usecs??)
* @dram_lsb_ptr: Physical address of scratch area in the command (try_cnt +
* btkill_cnd + reserved), first 32 bits. "0" disables usage.
* @dram_msb_ptr: upper bits of the scratch physical address
* @rts_retry_limit: max attempts for RTS
* @data_retry_limit: max attempts to send the data packet
* @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)
* + 2 bytes pad if 26/30 header size
* + 8 byte IV for CCM or TKIP (not used for WEP)
* + Data payload
* + 8-byte MIC (not used for CCM/WEP)
* 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 {
__le16 len;
__le16 offload_assist;
__le32 tx_flags;
struct {
u8 try_cnt;
u8 btkill_cnt;
__le16 reserved;
} scratch; /* DRAM_SCRATCH_API_U_VER_1 */
__le32 rate_n_flags;
u8 sta_id;
u8 sec_ctl;
u8 initial_rate_index;
u8 reserved2;
u8 key[16];
__le32 reserved3;
__le32 life_time;
__le32 dram_lsb_ptr;
u8 dram_msb_ptr;
u8 rts_retry_limit;
u8 data_retry_limit;
u8 tid_tspec;
__le16 pm_frame_timeout;
__le16 reserved4;
u8 payload[0];
struct ieee80211_hdr hdr[0];
} __packed; /* TX_CMD_API_S_VER_6 */
struct iwl_dram_sec_info {
__le32 pn_low;
__le16 pn_high;
__le16 aux_info;
} __packed; /* DRAM_SEC_INFO_API_S_VER_1 */
/**
* struct iwl_tx_cmd_gen2 - 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
* @flags: combination of &enum iwl_tx_cmd_flags
* @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_*
* @hdr: 802.11 header
*/
struct iwl_tx_cmd_gen2 {
__le16 len;
__le16 offload_assist;
__le32 flags;
struct iwl_dram_sec_info dram_info;
__le32 rate_n_flags;
struct ieee80211_hdr hdr[];
} __packed; /* TX_CMD_API_S_VER_7,
TX_CMD_API_S_VER_9 */
/**
* struct iwl_tx_cmd_gen3 - 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_*
* @ttl: time to live - packet lifetime limit. The FW should drop if
* passed.
* @hdr: 802.11 header
*/
struct iwl_tx_cmd_gen3 {
__le16 len;
__le16 flags;
__le32 offload_assist;
struct iwl_dram_sec_info dram_info;
__le32 rate_n_flags;
__le64 ttl;
struct ieee80211_hdr hdr[];
} __packed; /* TX_CMD_API_S_VER_8,
TX_CMD_API_S_VER_10 */
/*
* TX response related data
*/
/*
* enum iwl_tx_status - status that is returned by the fw after attempts to Tx
* @TX_STATUS_SUCCESS:
* @TX_STATUS_DIRECT_DONE:
* @TX_STATUS_POSTPONE_DELAY:
* @TX_STATUS_POSTPONE_FEW_BYTES:
* @TX_STATUS_POSTPONE_BT_PRIO:
* @TX_STATUS_POSTPONE_QUIET_PERIOD:
* @TX_STATUS_POSTPONE_CALC_TTAK:
* @TX_STATUS_FAIL_INTERNAL_CROSSED_RETRY:
* @TX_STATUS_FAIL_SHORT_LIMIT:
* @TX_STATUS_FAIL_LONG_LIMIT:
* @TX_STATUS_FAIL_UNDERRUN:
* @TX_STATUS_FAIL_DRAIN_FLOW:
* @TX_STATUS_FAIL_RFKILL_FLUSH:
* @TX_STATUS_FAIL_LIFE_EXPIRE:
* @TX_STATUS_FAIL_DEST_PS:
* @TX_STATUS_FAIL_HOST_ABORTED:
* @TX_STATUS_FAIL_BT_RETRY:
* @TX_STATUS_FAIL_STA_INVALID:
* @TX_TATUS_FAIL_FRAG_DROPPED:
* @TX_STATUS_FAIL_TID_DISABLE:
* @TX_STATUS_FAIL_FIFO_FLUSHED:
* @TX_STATUS_FAIL_SMALL_CF_POLL:
* @TX_STATUS_FAIL_FW_DROP:
* @TX_STATUS_FAIL_STA_COLOR_MISMATCH: mismatch between color of Tx cmd and
* STA table
* @TX_FRAME_STATUS_INTERNAL_ABORT:
* @TX_MODE_MSK:
* @TX_MODE_NO_BURST:
* @TX_MODE_IN_BURST_SEQ:
* @TX_MODE_FIRST_IN_BURST:
* @TX_QUEUE_NUM_MSK:
*
* Valid only if frame_count =1
* TODO: complete documentation
*/
enum iwl_tx_status {
TX_STATUS_MSK = 0x000000ff,
TX_STATUS_SUCCESS = 0x01,
TX_STATUS_DIRECT_DONE = 0x02,
/* postpone TX */
TX_STATUS_POSTPONE_DELAY = 0x40,
TX_STATUS_POSTPONE_FEW_BYTES = 0x41,
TX_STATUS_POSTPONE_BT_PRIO = 0x42,
TX_STATUS_POSTPONE_QUIET_PERIOD = 0x43,
TX_STATUS_POSTPONE_CALC_TTAK = 0x44,
/* abort TX */
TX_STATUS_FAIL_INTERNAL_CROSSED_RETRY = 0x81,
TX_STATUS_FAIL_SHORT_LIMIT = 0x82,
TX_STATUS_FAIL_LONG_LIMIT = 0x83,
TX_STATUS_FAIL_UNDERRUN = 0x84,
TX_STATUS_FAIL_DRAIN_FLOW = 0x85,
TX_STATUS_FAIL_RFKILL_FLUSH = 0x86,
TX_STATUS_FAIL_LIFE_EXPIRE = 0x87,
TX_STATUS_FAIL_DEST_PS = 0x88,
TX_STATUS_FAIL_HOST_ABORTED = 0x89,
TX_STATUS_FAIL_BT_RETRY = 0x8a,
TX_STATUS_FAIL_STA_INVALID = 0x8b,
TX_STATUS_FAIL_FRAG_DROPPED = 0x8c,
TX_STATUS_FAIL_TID_DISABLE = 0x8d,
TX_STATUS_FAIL_FIFO_FLUSHED = 0x8e,
TX_STATUS_FAIL_SMALL_CF_POLL = 0x8f,
TX_STATUS_FAIL_FW_DROP = 0x90,
TX_STATUS_FAIL_STA_COLOR_MISMATCH = 0x91,
TX_STATUS_INTERNAL_ABORT = 0x92,
TX_MODE_MSK = 0x00000f00,
TX_MODE_NO_BURST = 0x00000000,
TX_MODE_IN_BURST_SEQ = 0x00000100,
TX_MODE_FIRST_IN_BURST = 0x00000200,
TX_QUEUE_NUM_MSK = 0x0001f000,
TX_NARROW_BW_MSK = 0x00060000,
TX_NARROW_BW_1DIV2 = 0x00020000,
TX_NARROW_BW_1DIV4 = 0x00040000,
TX_NARROW_BW_1DIV8 = 0x00060000,
};
/*
* enum iwl_tx_agg_status - TX aggregation status
* @AGG_TX_STATE_STATUS_MSK:
* @AGG_TX_STATE_TRANSMITTED:
* @AGG_TX_STATE_UNDERRUN:
* @AGG_TX_STATE_BT_PRIO:
* @AGG_TX_STATE_FEW_BYTES:
* @AGG_TX_STATE_ABORT:
* @AGG_TX_STATE_TX_ON_AIR_DROP: TX_ON_AIR signal drop without underrun or
* BT detection
* @AGG_TX_STATE_LAST_SENT_TRY_CNT:
* @AGG_TX_STATE_LAST_SENT_BT_KILL:
* @AGG_TX_STATE_SCD_QUERY:
* @AGG_TX_STATE_TEST_BAD_CRC32:
* @AGG_TX_STATE_RESPONSE:
* @AGG_TX_STATE_DUMP_TX:
* @AGG_TX_STATE_DELAY_TX:
* @AGG_TX_STATE_TRY_CNT_MSK: Retry count for 1st frame in aggregation (retries
* occur if tx failed for this frame when it was a member of a previous
* aggregation block). If rate scaling is used, retry count indicates the
* rate table entry used for all frames in the new agg.
* @AGG_TX_STATE_SEQ_NUM_MSK: Command ID and sequence number of Tx command for
* this frame
*
* TODO: complete documentation
*/
enum iwl_tx_agg_status {
AGG_TX_STATE_STATUS_MSK = 0x00fff,
AGG_TX_STATE_TRANSMITTED = 0x000,
AGG_TX_STATE_UNDERRUN = 0x001,
AGG_TX_STATE_BT_PRIO = 0x002,
AGG_TX_STATE_FEW_BYTES = 0x004,
AGG_TX_STATE_ABORT = 0x008,
AGG_TX_STATE_TX_ON_AIR_DROP = 0x010,
AGG_TX_STATE_LAST_SENT_TRY_CNT = 0x020,
AGG_TX_STATE_LAST_SENT_BT_KILL = 0x040,
AGG_TX_STATE_SCD_QUERY = 0x080,
AGG_TX_STATE_TEST_BAD_CRC32 = 0x0100,
AGG_TX_STATE_RESPONSE = 0x1ff,
AGG_TX_STATE_DUMP_TX = 0x200,
AGG_TX_STATE_DELAY_TX = 0x400,
AGG_TX_STATE_TRY_CNT_POS = 12,
AGG_TX_STATE_TRY_CNT_MSK = 0xf << AGG_TX_STATE_TRY_CNT_POS,
};
/*
* The mask below describes a status where we are absolutely sure that the MPDU
* wasn't sent. For BA/Underrun we cannot be that sure. All we know that we've
* written the bytes to the TXE, but we know nothing about what the DSP did.
*/
#define AGG_TX_STAT_FRAME_NOT_SENT (AGG_TX_STATE_FEW_BYTES | \
AGG_TX_STATE_ABORT | \
AGG_TX_STATE_SCD_QUERY)
/*
* REPLY_TX = 0x1c (response)
*
* This response may be in one of two slightly different formats, indicated
* by the frame_count field:
*
* 1) No aggregation (frame_count == 1). This reports Tx results for a single
* frame. Multiple attempts, at various bit rates, may have been made for
* this frame.
*
* 2) Aggregation (frame_count > 1). This reports Tx results for two or more
* frames that used block-acknowledge. All frames were transmitted at
* same rate. Rate scaling may have been used if first frame in this new
* agg block failed in previous agg block(s).
*
* Note that, for aggregation, ACK (block-ack) status is not delivered
* here; block-ack has not been received by the time the device records
* this status.
* This status relates to reasons the tx might have been blocked or aborted
* within the device, rather than whether it was received successfully by
* the destination station.
*/
/**
* struct agg_tx_status - per packet TX aggregation status
* @status: See &enum iwl_tx_agg_status
* @sequence: Sequence # for this frame's Tx cmd (not SSN!)
*/
struct agg_tx_status {
__le16 status;
__le16 sequence;
} __packed;
/*
* definitions for initial rate index field
* bits [3:0] initial rate index
* bits [6:4] rate table color, used for the initial rate
* bit-7 invalid rate indication
*/
#define TX_RES_INIT_RATE_INDEX_MSK 0x0f
#define TX_RES_RATE_TABLE_COLOR_POS 4
#define TX_RES_RATE_TABLE_COLOR_MSK 0x70
#define TX_RES_INV_RATE_INDEX_MSK 0x80
#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)
/**
* struct iwl_mvm_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)
* @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_*
* @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.
* @pa_status: tx power info
* @pa_integ_res_a: tx power info
* @pa_integ_res_b: tx power info
* @pa_integ_res_c: tx power info
* @measurement_req_id: tx power info
* @reduced_tpc: transmit power reduction used
* @reserved: reserved
* @tfd_info: TFD information set by the FH
* @seq_ctl: sequence control from the Tx cmd
* @byte_cnt: byte count from the Tx cmd
* @tlc_info: TLC rate info
* @ra_tid: bits [3:0] = ra, bits [7:4] = tid
* @frame_ctrl: frame control
* @status: for non-agg: frame status TX_STATUS_*
* for agg: status of 1st frame, AGG_TX_STATE_*; other frame status fields
* follow this one, up to frame_count. Length in @frame_count.
*
* 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 {
u8 frame_count;
u8 bt_kill_count;
u8 failure_rts;
u8 failure_frame;
__le32 initial_rate;
__le16 wireless_media_time;
u8 pa_status;
u8 pa_integ_res_a[3];
u8 pa_integ_res_b[3];
u8 pa_integ_res_c[3];
__le16 measurement_req_id;
u8 reduced_tpc;
u8 reserved;
__le32 tfd_info;
__le16 seq_ctl;
__le16 byte_cnt;
u8 tlc_info;
u8 ra_tid;
__le16 frame_ctrl;
struct agg_tx_status status[];
} __packed; /* TX_RSP_API_S_VER_3 */
/**
* struct iwl_mvm_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_*
* @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.
* @pa_status: tx power info
* @pa_integ_res_a: tx power info
* @pa_integ_res_b: tx power info
* @pa_integ_res_c: tx power info
* @measurement_req_id: tx power info
* @reduced_tpc: transmit power reduction used
* @reserved: reserved
* @tfd_info: TFD information set by the FH
* @seq_ctl: sequence control from the Tx cmd
* @byte_cnt: byte count from the Tx cmd
* @tlc_info: TLC rate info
* @ra_tid: bits [3:0] = ra, bits [7:4] = tid
* @frame_ctrl: frame control
* @tx_queue: TX queue for this response
* @reserved2: reserved for padding/alignment
* @status: for non-agg: frame status TX_STATUS_*
* For version 6 TX response isn't received for aggregation at all.
*
* 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 {
u8 frame_count;
u8 bt_kill_count;
u8 failure_rts;
u8 failure_frame;
__le32 initial_rate;
__le16 wireless_media_time;
u8 pa_status;
u8 pa_integ_res_a[3];
u8 pa_integ_res_b[3];
u8 pa_integ_res_c[3];
__le16 measurement_req_id;
u8 reduced_tpc;
u8 reserved;
__le32 tfd_info;
__le16 seq_ctl;
__le16 byte_cnt;
u8 tlc_info;
u8 ra_tid;
__le16 frame_ctrl;
__le16 tx_queue;
__le16 reserved2;
struct agg_tx_status status;
} __packed; /* TX_RSP_API_S_VER_6,
TX_RSP_API_S_VER_7 */
/**
* struct iwl_mvm_ba_notif - notifies about reception of BA
* ( BA_NOTIF = 0xc5 )
* @sta_addr: MAC address
* @reserved: reserved
* @sta_id: Index of recipient (BA-sending) station in fw's station table
* @tid: tid of the session
* @seq_ctl: sequence control field
* @bitmap: the bitmap of the BA notification as seen in the air
* @scd_flow: the tx queue this BA relates to
* @scd_ssn: the index of the last contiguously sent packet
* @txed: number of Txed frames in this batch
* @txed_2_done: number of Acked frames in this batch
* @reduced_txp: power reduced according to TPC. This is the actual value and
* not a copy from the LQ command. Thus, if not the first rate was used
* for Tx-ing then this value will be set to 0 by FW.
* @reserved1: reserved
*/
struct iwl_mvm_ba_notif {
u8 sta_addr[ETH_ALEN];
__le16 reserved;
u8 sta_id;
u8 tid;
__le16 seq_ctl;
__le64 bitmap;
__le16 scd_flow;
__le16 scd_ssn;
u8 txed;
u8 txed_2_done;
u8 reduced_txp;
u8 reserved1;
} __packed;
/**
* struct iwl_mvm_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 {
__le16 q_num;
__le16 tfd_index;
u8 scd_queue;
u8 tid;
u8 reserved[2];
} __packed; /* COMPRESSED_BA_TFD_API_S_VER_1 */
/**
* struct iwl_mvm_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 {
u8 q_num;
u8 tid;
__le16 ssn;
} __packed; /* COMPRESSED_BA_RATID_API_S_VER_1 */
/*
* enum iwl_mvm_ba_resp_flags - TX aggregation status
* @IWL_MVM_BA_RESP_TX_AGG: generated due to BA
* @IWL_MVM_BA_RESP_TX_BAR: generated due to BA after BAR
* @IWL_MVM_BA_RESP_TX_AGG_FAIL: aggregation didn't receive BA
* @IWL_MVM_BA_RESP_TX_UNDERRUN: aggregation got underrun
* @IWL_MVM_BA_RESP_TX_BT_KILL: aggregation got BT-kill
* @IWL_MVM_BA_RESP_TX_DSP_TIMEOUT: aggregation didn't finish within the
* expected time
*/
enum iwl_mvm_ba_resp_flags {
IWL_MVM_BA_RESP_TX_AGG,
IWL_MVM_BA_RESP_TX_BAR,
IWL_MVM_BA_RESP_TX_AGG_FAIL,
IWL_MVM_BA_RESP_TX_UNDERRUN,
IWL_MVM_BA_RESP_TX_BT_KILL,
IWL_MVM_BA_RESP_TX_DSP_TIMEOUT
};
/**
* struct iwl_mvm_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
* @reduced_txp: power reduced according to TPC. This is the actual value and
* not a copy from the LQ command. Thus, if not the first rate was used
* for Tx-ing then this value will be set to 0 by FW.
* @tlc_rate_info: TLC rate info, initial rate index, TLC table color
* @retry_cnt: retry count
* @query_byte_cnt: SCD query byte count
* @query_frame_cnt: SCD query frame count
* @txed: number of frames sent in the aggregation (all-TIDs)
* @done: number of frames that were Acked by the BA (all-TIDs)
* @reserved: reserved (for alignment)
* @wireless_time: Wireless-media time
* @tx_rate: the rate the aggregation was sent at
* @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
* 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.
*/
struct iwl_mvm_compressed_ba_notif {
__le32 flags;
u8 sta_id;
u8 reduced_txp;
u8 tlc_rate_info;
u8 retry_cnt;
__le32 query_byte_cnt;
__le16 query_frame_cnt;
__le16 txed;
__le16 done;
__le16 reserved;
__le32 wireless_time;
__le32 tx_rate;
__le16 tfd_cnt;
__le16 ra_tid_cnt;
struct iwl_mvm_compressed_ba_ratid ra_tid[0];
struct iwl_mvm_compressed_ba_tfd tfd[];
} __packed; /* COMPRESSED_BA_RES_API_S_VER_4,
COMPRESSED_BA_RES_API_S_VER_5 */
/**
* struct iwl_mac_beacon_cmd_v6 - beacon template command
* @tx: the tx commands associated with the beacon frame
* @template_id: currently equal to the mac context id of the coresponding
* mac.
* @tim_idx: the offset of the tim IE in the beacon
* @tim_size: the length of the tim IE
* @frame: the template of the beacon frame
*/
struct iwl_mac_beacon_cmd_v6 {
struct iwl_tx_cmd tx;
__le32 template_id;
__le32 tim_idx;
__le32 tim_size;
struct ieee80211_hdr frame[];
} __packed; /* BEACON_TEMPLATE_CMD_API_S_VER_6 */
/**
* struct iwl_mac_beacon_cmd_v7 - beacon template command with offloaded CSA
* @tx: the tx commands associated with the beacon frame
* @template_id: currently equal to the mac context id of the coresponding
* mac.
* @tim_idx: the offset of the tim IE in the beacon
* @tim_size: the length of the tim IE
* @ecsa_offset: offset to the ECSA IE if present
* @csa_offset: offset to the CSA IE if present
* @frame: the template of the beacon frame
*/
struct iwl_mac_beacon_cmd_v7 {
struct iwl_tx_cmd tx;
__le32 template_id;
__le32 tim_idx;
__le32 tim_size;
__le32 ecsa_offset;
__le32 csa_offset;
struct ieee80211_hdr frame[];
} __packed; /* BEACON_TEMPLATE_CMD_API_S_VER_7 */
/* Bit flags for BEACON_TEMPLATE_CMD_API until version 10 */
enum iwl_mac_beacon_flags_v1 {
IWL_MAC_BEACON_CCK_V1 = BIT(8),
IWL_MAC_BEACON_ANT_A_V1 = BIT(9),
IWL_MAC_BEACON_ANT_B_V1 = BIT(10),
IWL_MAC_BEACON_FILS_V1 = BIT(12),
};
/* Bit flags for BEACON_TEMPLATE_CMD_API version 11 and above */
enum iwl_mac_beacon_flags {
IWL_MAC_BEACON_CCK = BIT(5),
IWL_MAC_BEACON_ANT_A = BIT(6),
IWL_MAC_BEACON_ANT_B = BIT(7),
IWL_MAC_BEACON_FILS = BIT(8),
};
/**
* struct iwl_mac_beacon_cmd - beacon template command with offloaded CSA
* @byte_cnt: byte count of the beacon frame.
* @flags: least significant byte for rate code. The most significant byte
* is &enum iwl_mac_beacon_flags.
* @short_ssid: Short SSID
* @reserved: reserved
* @template_id: currently equal to the mac context id of the coresponding mac.
* @tim_idx: the offset of the tim IE in the beacon
* @tim_size: the length of the tim IE
* @ecsa_offset: offset to the ECSA IE if present
* @csa_offset: offset to the CSA IE if present
* @frame: the template of the beacon frame
*/
struct iwl_mac_beacon_cmd {
__le16 byte_cnt;
__le16 flags;
__le32 short_ssid;
__le32 reserved;
__le32 template_id;
__le32 tim_idx;
__le32 tim_size;
__le32 ecsa_offset;
__le32 csa_offset;
struct ieee80211_hdr frame[];
} __packed; /* BEACON_TEMPLATE_CMD_API_S_VER_10,
BEACON_TEMPLATE_CMD_API_S_VER_11,
BEACON_TEMPLATE_CMD_API_S_VER_12 */
struct iwl_beacon_notif {
struct iwl_mvm_tx_resp beacon_notify_hdr;
__le64 tsf;
__le32 ibss_mgr_status;
} __packed;
/**
* struct iwl_extended_beacon_notif_v5 - notifies about beacon transmission
* @beacon_notify_hdr: tx response command associated with the beacon
* @tsf: last beacon tsf
* @ibss_mgr_status: whether IBSS is manager
* @gp2: last beacon time in gp2
*/
struct iwl_extended_beacon_notif_v5 {
struct iwl_mvm_tx_resp beacon_notify_hdr;
__le64 tsf;
__le32 ibss_mgr_status;
__le32 gp2;
} __packed; /* BEACON_NTFY_API_S_VER_5 */
/**
* struct iwl_extended_beacon_notif - notifies about beacon transmission
* @status: the status of the Tx response of the beacon
* @tsf: last beacon tsf
* @ibss_mgr_status: whether IBSS is manager
* @gp2: last beacon time in gp2
*/
struct iwl_extended_beacon_notif {
__le32 status;
__le64 tsf;
__le32 ibss_mgr_status;
__le32 gp2;
} __packed; /* BEACON_NTFY_API_S_VER_6_ */
/**
* enum iwl_dump_control - dump (flush) control flags
* @DUMP_TX_FIFO_FLUSH: Dump MSDUs until the the FIFO is empty
* and the TFD queues are empty.
*/
enum iwl_dump_control {
DUMP_TX_FIFO_FLUSH = BIT(1),
};
/**
* struct iwl_tx_path_flush_cmd -- queue/FIFO flush command
* @queues_ctl: bitmap of queues to flush
* @flush_ctl: control flags
* @reserved: reserved
*/
struct iwl_tx_path_flush_cmd_v1 {
__le32 queues_ctl;
__le16 flush_ctl;
__le16 reserved;
} __packed; /* TX_PATH_FLUSH_CMD_API_S_VER_1 */
/**
* struct iwl_tx_path_flush_cmd -- queue/FIFO flush command
* @sta_id: station ID to flush
* @tid_mask: TID mask to flush
* @reserved: reserved
*/
struct iwl_tx_path_flush_cmd {
__le32 sta_id;
__le16 tid_mask;
__le16 reserved;
} __packed; /* TX_PATH_FLUSH_CMD_API_S_VER_2 */
#define IWL_TX_FLUSH_QUEUE_RSP 16
/**
* struct iwl_flush_queue_info - virtual flush queue info
* @queue_num: virtual queue id
* @read_before_flush: read pointer before flush
* @read_after_flush: read pointer after flush
*/
struct iwl_flush_queue_info {
__le16 tid;
__le16 queue_num;
__le16 read_before_flush;
__le16 read_after_flush;
} __packed; /* TFDQ_FLUSH_INFO_API_S_VER_1 */
/**
* struct iwl_tx_path_flush_cmd_rsp -- queue/FIFO flush command response
* @num_flushed_queues: number of queues in queues array
* @queues: all flushed queues
*/
struct iwl_tx_path_flush_cmd_rsp {
__le16 sta_id;
__le16 num_flushed_queues;
struct iwl_flush_queue_info queues[IWL_TX_FLUSH_QUEUE_RSP];
} __packed; /* TX_PATH_FLUSH_CMD_RSP_API_S_VER_1 */
/* Available options for the SCD_QUEUE_CFG HCMD */
enum iwl_scd_cfg_actions {
SCD_CFG_DISABLE_QUEUE = 0x0,
SCD_CFG_ENABLE_QUEUE = 0x1,
SCD_CFG_UPDATE_QUEUE_TID = 0x2,
};
/**
* struct iwl_scd_txq_cfg_cmd - New txq hw scheduler config command
* @token: unused
* @sta_id: station id
* @tid: TID
* @scd_queue: scheduler queue to confiug
* @action: 1 queue enable, 0 queue disable, 2 change txq's tid owner
* Value is one of &enum iwl_scd_cfg_actions options
* @aggregate: 1 aggregated queue, 0 otherwise
* @tx_fifo: &enum iwl_mvm_tx_fifo
* @window: BA window size
* @ssn: SSN for the BA agreement
* @reserved: reserved
*/
struct iwl_scd_txq_cfg_cmd {
u8 token;
u8 sta_id;
u8 tid;
u8 scd_queue;
u8 action;
u8 aggregate;
u8 tx_fifo;
u8 window;
__le16 ssn;
__le16 reserved;
} __packed; /* SCD_QUEUE_CFG_CMD_API_S_VER_1 */
/**
* struct iwl_scd_txq_cfg_rsp
* @token: taken from the command
* @sta_id: station id from the command
* @tid: tid from the command
* @scd_queue: scd_queue from the command
*/
struct iwl_scd_txq_cfg_rsp {
u8 token;
u8 sta_id;
u8 tid;
u8 scd_queue;
} __packed; /* SCD_QUEUE_CFG_RSP_API_S_VER_1 */
#endif /* __iwl_fw_api_tx_h__ */

View File

@ -0,0 +1,115 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2005-2014, 2019-2020 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
#ifndef __iwl_fw_api_txq_h__
#define __iwl_fw_api_txq_h__
/*
* DQA queue numbers
*
* @IWL_MVM_DQA_CMD_QUEUE: a queue reserved for sending HCMDs to the FW
* @IWL_MVM_DQA_AUX_QUEUE: a queue reserved for aux frames
* @IWL_MVM_DQA_P2P_DEVICE_QUEUE: a queue reserved for P2P device frames
* @IWL_MVM_DQA_INJECT_MONITOR_QUEUE: a queue reserved for injection using
* monitor mode. Note this queue is the same as the queue for P2P device
* but we can't have active monitor mode along with P2P device anyway.
* @IWL_MVM_DQA_GCAST_QUEUE: a queue reserved for P2P GO/SoftAP GCAST frames
* @IWL_MVM_DQA_BSS_CLIENT_QUEUE: a queue reserved for BSS activity, to ensure
* that we are never left without the possibility to connect to an AP.
* @IWL_MVM_DQA_MIN_MGMT_QUEUE: first TXQ in pool for MGMT and non-QOS frames.
* Each MGMT queue is mapped to a single STA
* MGMT frames are frames that return true on ieee80211_is_mgmt()
* @IWL_MVM_DQA_MAX_MGMT_QUEUE: last TXQ in pool for MGMT frames
* @IWL_MVM_DQA_AP_PROBE_RESP_QUEUE: a queue reserved for P2P GO/SoftAP probe
* responses
* @IWL_MVM_DQA_MIN_DATA_QUEUE: first TXQ in pool for DATA frames.
* DATA frames are intended for !ieee80211_is_mgmt() frames, but if
* the MGMT TXQ pool is exhausted, mgmt frames can be sent on DATA queues
* as well
* @IWL_MVM_DQA_MAX_DATA_QUEUE: last TXQ in pool for DATA frames
*/
enum iwl_mvm_dqa_txq {
IWL_MVM_DQA_CMD_QUEUE = 0,
IWL_MVM_DQA_AUX_QUEUE = 1,
IWL_MVM_DQA_P2P_DEVICE_QUEUE = 2,
IWL_MVM_DQA_INJECT_MONITOR_QUEUE = 2,
IWL_MVM_DQA_GCAST_QUEUE = 3,
IWL_MVM_DQA_BSS_CLIENT_QUEUE = 4,
IWL_MVM_DQA_MIN_MGMT_QUEUE = 5,
IWL_MVM_DQA_MAX_MGMT_QUEUE = 8,
IWL_MVM_DQA_AP_PROBE_RESP_QUEUE = 9,
IWL_MVM_DQA_MIN_DATA_QUEUE = 10,
IWL_MVM_DQA_MAX_DATA_QUEUE = 30,
};
enum iwl_mvm_tx_fifo {
IWL_MVM_TX_FIFO_BK = 0,
IWL_MVM_TX_FIFO_BE,
IWL_MVM_TX_FIFO_VI,
IWL_MVM_TX_FIFO_VO,
IWL_MVM_TX_FIFO_MCAST = 5,
IWL_MVM_TX_FIFO_CMD = 7,
};
enum iwl_gen2_tx_fifo {
IWL_GEN2_TX_FIFO_CMD = 0,
IWL_GEN2_EDCA_TX_FIFO_BK,
IWL_GEN2_EDCA_TX_FIFO_BE,
IWL_GEN2_EDCA_TX_FIFO_VI,
IWL_GEN2_EDCA_TX_FIFO_VO,
IWL_GEN2_TRIG_TX_FIFO_BK,
IWL_GEN2_TRIG_TX_FIFO_BE,
IWL_GEN2_TRIG_TX_FIFO_VI,
IWL_GEN2_TRIG_TX_FIFO_VO,
};
/**
* enum iwl_tx_queue_cfg_actions - TXQ config options
* @TX_QUEUE_CFG_ENABLE_QUEUE: enable a queue
* @TX_QUEUE_CFG_TFD_SHORT_FORMAT: use short TFD format
*/
enum iwl_tx_queue_cfg_actions {
TX_QUEUE_CFG_ENABLE_QUEUE = BIT(0),
TX_QUEUE_CFG_TFD_SHORT_FORMAT = BIT(1),
};
#define IWL_DEFAULT_QUEUE_SIZE 256
#define IWL_MGMT_QUEUE_SIZE 16
#define IWL_CMD_QUEUE_SIZE 32
/**
* struct iwl_tx_queue_cfg_cmd - txq hw scheduler config command
* @sta_id: station id
* @tid: tid of the queue
* @flags: see &enum iwl_tx_queue_cfg_actions
* @cb_size: size of TFD cyclic buffer. Value is exponent - 3.
* Minimum value 0 (8 TFDs), maximum value 5 (256 TFDs)
* @byte_cnt_addr: address of byte count table
* @tfdq_addr: address of TFD circular buffer
*/
struct iwl_tx_queue_cfg_cmd {
u8 sta_id;
u8 tid;
__le16 flags;
__le32 cb_size;
__le64 byte_cnt_addr;
__le64 tfdq_addr;
} __packed; /* TX_QUEUE_CFG_CMD_API_S_VER_2 */
/**
* struct iwl_tx_queue_cfg_rsp - response to txq hw scheduler config
* @queue_number: queue number assigned to this RA -TID
* @flags: set on failure
* @write_pointer: initial value for write pointer
* @reserved: reserved
*/
struct iwl_tx_queue_cfg_rsp {
__le16 queue_number;
__le16 flags;
__le16 write_pointer;
__le16 reserved;
} __packed; /* TX_QUEUE_CFG_RSP_API_S_VER_2 */
#endif /* __iwl_fw_api_txq_h__ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,327 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2005-2014, 2018-2019, 2021 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2015-2017 Intel Deutschland GmbH
*/
#ifndef __iwl_fw_dbg_h__
#define __iwl_fw_dbg_h__
#include <linux/workqueue.h>
#include <net/cfg80211.h>
#include "runtime.h"
#include "iwl-prph.h"
#include "iwl-io.h"
#include "file.h"
#include "error-dump.h"
#include "api/commands.h"
#include "api/dbg-tlv.h"
#include "api/alive.h"
/**
* struct iwl_fw_dump_desc - describes the dump
* @len: length of trig_desc->data
* @trig_desc: the description of the dump
*/
struct iwl_fw_dump_desc {
size_t len;
/* must be last */
struct iwl_fw_error_dump_trigger_desc trig_desc;
};
/**
* struct iwl_fw_dbg_params - register values to restore
* @in_sample: DBGC_IN_SAMPLE value
* @out_ctrl: DBGC_OUT_CTRL value
*/
struct iwl_fw_dbg_params {
u32 in_sample;
u32 out_ctrl;
};
extern const struct iwl_fw_dump_desc iwl_dump_desc_assert;
int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt,
const struct iwl_fw_dump_desc *desc,
bool monitor_only, unsigned int delay);
int iwl_fw_dbg_error_collect(struct iwl_fw_runtime *fwrt,
enum iwl_fw_dbg_trigger trig_type);
int iwl_fw_dbg_ini_collect(struct iwl_fw_runtime *fwrt,
struct iwl_fwrt_dump_data *dump_data,
bool sync);
int iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt,
enum iwl_fw_dbg_trigger trig, const char *str,
size_t len, struct iwl_fw_dbg_trigger_tlv *trigger);
int iwl_fw_dbg_collect_trig(struct iwl_fw_runtime *fwrt,
struct iwl_fw_dbg_trigger_tlv *trigger,
const char *fmt, ...) __printf(3, 4);
int iwl_fw_start_dbg_conf(struct iwl_fw_runtime *fwrt, u8 id);
#define iwl_fw_dbg_trigger_enabled(fw, id) ({ \
void *__dbg_trigger = (fw)->dbg.trigger_tlv[(id)]; \
unlikely(__dbg_trigger); \
})
static inline struct iwl_fw_dbg_trigger_tlv*
_iwl_fw_dbg_get_trigger(const struct iwl_fw *fw, enum iwl_fw_dbg_trigger id)
{
return fw->dbg.trigger_tlv[id];
}
#define iwl_fw_dbg_get_trigger(fw, id) ({ \
BUILD_BUG_ON(!__builtin_constant_p(id)); \
BUILD_BUG_ON((id) >= FW_DBG_TRIGGER_MAX); \
_iwl_fw_dbg_get_trigger((fw), (id)); \
})
static inline bool
iwl_fw_dbg_trigger_vif_match(struct iwl_fw_dbg_trigger_tlv *trig,
struct wireless_dev *wdev)
{
u32 trig_vif = le32_to_cpu(trig->vif_type);
return trig_vif == IWL_FW_DBG_CONF_VIF_ANY ||
wdev->iftype == trig_vif;
}
static inline bool
iwl_fw_dbg_trigger_stop_conf_match(struct iwl_fw_runtime *fwrt,
struct iwl_fw_dbg_trigger_tlv *trig)
{
return ((trig->mode & IWL_FW_DBG_TRIGGER_STOP) &&
(fwrt->dump.conf == FW_DBG_INVALID ||
(BIT(fwrt->dump.conf) & le32_to_cpu(trig->stop_conf_ids))));
}
static inline bool
iwl_fw_dbg_no_trig_window(struct iwl_fw_runtime *fwrt, u32 id, u32 dis_usec)
{
unsigned long wind_jiff = usecs_to_jiffies(dis_usec);
/* If this is the first event checked, jump to update start ts */
if (fwrt->dump.non_collect_ts_start[id] &&
(time_after(fwrt->dump.non_collect_ts_start[id] + wind_jiff,
jiffies)))
return true;
fwrt->dump.non_collect_ts_start[id] = jiffies;
return false;
}
static inline bool
iwl_fw_dbg_trigger_check_stop(struct iwl_fw_runtime *fwrt,
struct wireless_dev *wdev,
struct iwl_fw_dbg_trigger_tlv *trig)
{
u32 usec = le16_to_cpu(trig->trig_dis_ms) * USEC_PER_MSEC;
if (wdev && !iwl_fw_dbg_trigger_vif_match(trig, wdev))
return false;
if (iwl_fw_dbg_no_trig_window(fwrt, le32_to_cpu(trig->id), usec)) {
IWL_WARN(fwrt, "Trigger %d occurred while no-collect window.\n",
trig->id);
return false;
}
return iwl_fw_dbg_trigger_stop_conf_match(fwrt, trig);
}
static inline struct iwl_fw_dbg_trigger_tlv*
_iwl_fw_dbg_trigger_on(struct iwl_fw_runtime *fwrt,
struct wireless_dev *wdev,
const enum iwl_fw_dbg_trigger id)
{
struct iwl_fw_dbg_trigger_tlv *trig;
if (iwl_trans_dbg_ini_valid(fwrt->trans))
return NULL;
if (!iwl_fw_dbg_trigger_enabled(fwrt->fw, id))
return NULL;
trig = _iwl_fw_dbg_get_trigger(fwrt->fw, id);
if (!iwl_fw_dbg_trigger_check_stop(fwrt, wdev, trig))
return NULL;
return trig;
}
#define iwl_fw_dbg_trigger_on(fwrt, wdev, id) ({ \
BUILD_BUG_ON(!__builtin_constant_p(id)); \
BUILD_BUG_ON((id) >= FW_DBG_TRIGGER_MAX); \
_iwl_fw_dbg_trigger_on((fwrt), (wdev), (id)); \
})
static inline void
_iwl_fw_dbg_trigger_simple_stop(struct iwl_fw_runtime *fwrt,
struct wireless_dev *wdev,
struct iwl_fw_dbg_trigger_tlv *trigger)
{
if (!trigger)
return;
if (!iwl_fw_dbg_trigger_check_stop(fwrt, wdev, trigger))
return;
iwl_fw_dbg_collect_trig(fwrt, trigger, NULL);
}
#define iwl_fw_dbg_trigger_simple_stop(fwrt, wdev, trig) \
_iwl_fw_dbg_trigger_simple_stop((fwrt), (wdev), \
iwl_fw_dbg_get_trigger((fwrt)->fw,\
(trig)))
void iwl_fw_dbg_stop_restart_recording(struct iwl_fw_runtime *fwrt,
struct iwl_fw_dbg_params *params,
bool stop);
#ifdef CONFIG_IWLWIFI_DEBUGFS
static inline void iwl_fw_set_dbg_rec_on(struct iwl_fw_runtime *fwrt)
{
if (fwrt->cur_fw_img == IWL_UCODE_REGULAR &&
(fwrt->fw->dbg.dest_tlv ||
fwrt->trans->dbg.ini_dest != IWL_FW_INI_LOCATION_INVALID))
fwrt->trans->dbg.rec_on = true;
}
#endif
static inline void iwl_fw_dump_conf_clear(struct iwl_fw_runtime *fwrt)
{
fwrt->dump.conf = FW_DBG_INVALID;
}
void iwl_fw_error_dump_wk(struct work_struct *work);
static inline bool iwl_fw_dbg_type_on(struct iwl_fw_runtime *fwrt, u32 type)
{
return (fwrt->fw->dbg.dump_mask & BIT(type));
}
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->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);
}
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->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;
}
void iwl_fw_dbg_read_d3_debug_data(struct iwl_fw_runtime *fwrt);
static inline void iwl_fw_flush_dumps(struct iwl_fw_runtime *fwrt)
{
int i;
iwl_dbg_tlv_del_timers(fwrt->trans);
for (i = 0; i < IWL_FW_RUNTIME_DUMP_WK_NUM; i++)
flush_delayed_work(&fwrt->dump.wks[i].wk);
}
#ifdef CONFIG_IWLWIFI_DEBUGFS
static inline void iwl_fw_cancel_timestamp(struct iwl_fw_runtime *fwrt)
{
fwrt->timestamp.delay = 0;
cancel_delayed_work_sync(&fwrt->timestamp.wk);
}
void iwl_fw_trigger_timestamp(struct iwl_fw_runtime *fwrt, u32 delay);
static inline void iwl_fw_suspend_timestamp(struct iwl_fw_runtime *fwrt)
{
cancel_delayed_work_sync(&fwrt->timestamp.wk);
}
static inline void iwl_fw_resume_timestamp(struct iwl_fw_runtime *fwrt)
{
if (!fwrt->timestamp.delay)
return;
schedule_delayed_work(&fwrt->timestamp.wk,
round_jiffies_relative(fwrt->timestamp.delay));
}
#else
static inline void iwl_fw_cancel_timestamp(struct iwl_fw_runtime *fwrt) {}
static inline void iwl_fw_trigger_timestamp(struct iwl_fw_runtime *fwrt,
u32 delay) {}
static inline void iwl_fw_suspend_timestamp(struct iwl_fw_runtime *fwrt) {}
static inline void iwl_fw_resume_timestamp(struct iwl_fw_runtime *fwrt) {}
#endif /* CONFIG_IWLWIFI_DEBUGFS */
void iwl_fw_dbg_stop_sync(struct iwl_fw_runtime *fwrt);
static inline void iwl_fw_lmac1_set_alive_err_table(struct iwl_trans *trans,
u32 lmac_error_event_table)
{
if (!(trans->dbg.error_event_table_tlv_status &
IWL_ERROR_EVENT_TABLE_LMAC1) ||
WARN_ON(trans->dbg.lmac_error_event_table[0] !=
lmac_error_event_table))
trans->dbg.lmac_error_event_table[0] = lmac_error_event_table;
}
static inline void iwl_fw_umac_set_alive_err_table(struct iwl_trans *trans,
u32 umac_error_event_table)
{
if (!(trans->dbg.error_event_table_tlv_status &
IWL_ERROR_EVENT_TABLE_UMAC) ||
WARN_ON(trans->dbg.umac_error_event_table !=
umac_error_event_table))
trans->dbg.umac_error_event_table = umac_error_event_table;
}
static inline void iwl_fw_error_collect(struct iwl_fw_runtime *fwrt, bool sync)
{
enum iwl_fw_ini_time_point tp_id;
if (!iwl_trans_dbg_ini_valid(fwrt->trans)) {
iwl_fw_dbg_collect_desc(fwrt, &iwl_dump_desc_assert, false, 0);
return;
}
if (fwrt->trans->dbg.hw_error) {
tp_id = IWL_FW_INI_TIME_POINT_FW_HW_ERROR;
fwrt->trans->dbg.hw_error = false;
} else {
tp_id = IWL_FW_INI_TIME_POINT_FW_ASSERT;
}
_iwl_dbg_tlv_time_point(fwrt, tp_id, NULL, sync);
}
void iwl_fw_error_print_fseq_regs(struct iwl_fw_runtime *fwrt);
static inline void iwl_fwrt_update_fw_versions(struct iwl_fw_runtime *fwrt,
struct iwl_lmac_alive *lmac,
struct iwl_umac_alive *umac)
{
if (lmac) {
fwrt->dump.fw_ver.type = lmac->ver_type;
fwrt->dump.fw_ver.subtype = lmac->ver_subtype;
fwrt->dump.fw_ver.lmac_major = le32_to_cpu(lmac->ucode_major);
fwrt->dump.fw_ver.lmac_minor = le32_to_cpu(lmac->ucode_minor);
}
if (umac) {
fwrt->dump.fw_ver.umac_major = le32_to_cpu(umac->umac_major);
fwrt->dump.fw_ver.umac_minor = le32_to_cpu(umac->umac_minor);
}
}
void iwl_fwrt_dump_error_logs(struct iwl_fw_runtime *fwrt);
#endif /* __iwl_fw_dbg_h__ */

View File

@ -0,0 +1,17 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2012-2014 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
#include "runtime.h"
#ifdef CONFIG_IWLWIFI_DEBUGFS
void iwl_fwrt_dbgfs_register(struct iwl_fw_runtime *fwrt,
struct dentry *dbgfs_dir);
#else
static inline void iwl_fwrt_dbgfs_register(struct iwl_fw_runtime *fwrt,
struct dentry *dbgfs_dir) { }
#endif /* CONFIG_IWLWIFI_DEBUGFS */

View File

@ -0,0 +1,425 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2012-2014, 2018-2021 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2015-2017 Intel Deutschland GmbH
*/
#include <linux/devcoredump.h>
#include "iwl-drv.h"
#include "runtime.h"
#include "dbg.h"
#include "debugfs.h"
#include "iwl-io.h"
#include "iwl-prph.h"
#include "iwl-csr.h"
/*
* Note: This structure is read from the device with IO accesses,
* and the reading already does the endian conversion. As it is
* read with u32-sized accesses, any members with a different size
* need to be ordered correctly though!
*/
struct iwl_error_event_table_v1 {
u32 valid; /* (nonzero) valid, (0) log is empty */
u32 error_id; /* type of error */
u32 pc; /* program counter */
u32 blink1; /* branch link */
u32 blink2; /* branch link */
u32 ilink1; /* interrupt link */
u32 ilink2; /* interrupt link */
u32 data1; /* error-specific data */
u32 data2; /* error-specific data */
u32 data3; /* error-specific data */
u32 bcon_time; /* beacon timer */
u32 tsf_low; /* network timestamp function timer */
u32 tsf_hi; /* network timestamp function timer */
u32 gp1; /* GP1 timer register */
u32 gp2; /* GP2 timer register */
u32 gp3; /* GP3 timer register */
u32 ucode_ver; /* uCode version */
u32 hw_ver; /* HW Silicon version */
u32 brd_ver; /* HW board version */
u32 log_pc; /* log program counter */
u32 frame_ptr; /* frame pointer */
u32 stack_ptr; /* stack pointer */
u32 hcmd; /* last host command header */
u32 isr0; /* isr status register LMPM_NIC_ISR0:
* rxtx_flag */
u32 isr1; /* isr status register LMPM_NIC_ISR1:
* host_flag */
u32 isr2; /* isr status register LMPM_NIC_ISR2:
* enc_flag */
u32 isr3; /* isr status register LMPM_NIC_ISR3:
* time_flag */
u32 isr4; /* isr status register LMPM_NIC_ISR4:
* wico interrupt */
u32 isr_pref; /* isr status register LMPM_NIC_PREF_STAT */
u32 wait_event; /* wait event() caller address */
u32 l2p_control; /* L2pControlField */
u32 l2p_duration; /* L2pDurationField */
u32 l2p_mhvalid; /* L2pMhValidBits */
u32 l2p_addr_match; /* L2pAddrMatchStat */
u32 lmpm_pmg_sel; /* indicate which clocks are turned on
* (LMPM_PMG_SEL) */
u32 u_timestamp; /* indicate when the date and time of the
* compilation */
u32 flow_handler; /* FH read/write pointers, RX credit */
} __packed /* LOG_ERROR_TABLE_API_S_VER_1 */;
struct iwl_error_event_table {
u32 valid; /* (nonzero) valid, (0) log is empty */
u32 error_id; /* type of error */
u32 trm_hw_status0; /* TRM HW status */
u32 trm_hw_status1; /* TRM HW status */
u32 blink2; /* branch link */
u32 ilink1; /* interrupt link */
u32 ilink2; /* interrupt link */
u32 data1; /* error-specific data */
u32 data2; /* error-specific data */
u32 data3; /* error-specific data */
u32 bcon_time; /* beacon timer */
u32 tsf_low; /* network timestamp function timer */
u32 tsf_hi; /* network timestamp function timer */
u32 gp1; /* GP1 timer register */
u32 gp2; /* GP2 timer register */
u32 fw_rev_type; /* firmware revision type */
u32 major; /* uCode version major */
u32 minor; /* uCode version minor */
u32 hw_ver; /* HW Silicon version */
u32 brd_ver; /* HW board version */
u32 log_pc; /* log program counter */
u32 frame_ptr; /* frame pointer */
u32 stack_ptr; /* stack pointer */
u32 hcmd; /* last host command header */
u32 isr0; /* isr status register LMPM_NIC_ISR0:
* rxtx_flag */
u32 isr1; /* isr status register LMPM_NIC_ISR1:
* host_flag */
u32 isr2; /* isr status register LMPM_NIC_ISR2:
* enc_flag */
u32 isr3; /* isr status register LMPM_NIC_ISR3:
* time_flag */
u32 isr4; /* isr status register LMPM_NIC_ISR4:
* wico interrupt */
u32 last_cmd_id; /* last HCMD id handled by the firmware */
u32 wait_event; /* wait event() caller address */
u32 l2p_control; /* L2pControlField */
u32 l2p_duration; /* L2pDurationField */
u32 l2p_mhvalid; /* L2pMhValidBits */
u32 l2p_addr_match; /* L2pAddrMatchStat */
u32 lmpm_pmg_sel; /* indicate which clocks are turned on
* (LMPM_PMG_SEL) */
u32 u_timestamp; /* indicate when the date and time of the
* compilation */
u32 flow_handler; /* FH read/write pointers, RX credit */
} __packed /* LOG_ERROR_TABLE_API_S_VER_3 */;
/*
* UMAC error struct - relevant starting from family 8000 chip.
* Note: This structure is read from the device with IO accesses,
* and the reading already does the endian conversion. As it is
* read with u32-sized accesses, any members with a different size
* need to be ordered correctly though!
*/
struct iwl_umac_error_event_table {
u32 valid; /* (nonzero) valid, (0) log is empty */
u32 error_id; /* type of error */
u32 blink1; /* branch link */
u32 blink2; /* branch link */
u32 ilink1; /* interrupt link */
u32 ilink2; /* interrupt link */
u32 data1; /* error-specific data */
u32 data2; /* error-specific data */
u32 data3; /* error-specific data */
u32 umac_major;
u32 umac_minor;
u32 frame_pointer; /* core register 27*/
u32 stack_pointer; /* core register 28 */
u32 cmd_header; /* latest host cmd sent to UMAC */
u32 nic_isr_pref; /* ISR status register */
} __packed;
#define ERROR_START_OFFSET (1 * sizeof(u32))
#define ERROR_ELEM_SIZE (7 * sizeof(u32))
static void iwl_fwrt_dump_umac_error_log(struct iwl_fw_runtime *fwrt)
{
struct iwl_trans *trans = fwrt->trans;
struct iwl_umac_error_event_table table = {};
u32 base = fwrt->trans->dbg.umac_error_event_table;
if (!base &&
!(fwrt->trans->dbg.error_event_table_tlv_status &
IWL_ERROR_EVENT_TABLE_UMAC))
return;
iwl_trans_read_mem_bytes(trans, base, &table, sizeof(table));
if (table.valid)
fwrt->dump.umac_err_id = table.error_id;
if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) {
IWL_ERR(trans, "Start IWL Error Log Dump:\n");
IWL_ERR(trans, "Transport status: 0x%08lX, valid: %d\n",
fwrt->trans->status, table.valid);
}
IWL_ERR(fwrt, "0x%08X | %s\n", table.error_id,
iwl_fw_lookup_assert_desc(table.error_id));
IWL_ERR(fwrt, "0x%08X | umac branchlink1\n", table.blink1);
IWL_ERR(fwrt, "0x%08X | umac branchlink2\n", table.blink2);
IWL_ERR(fwrt, "0x%08X | umac interruptlink1\n", table.ilink1);
IWL_ERR(fwrt, "0x%08X | umac interruptlink2\n", table.ilink2);
IWL_ERR(fwrt, "0x%08X | umac data1\n", table.data1);
IWL_ERR(fwrt, "0x%08X | umac data2\n", table.data2);
IWL_ERR(fwrt, "0x%08X | umac data3\n", table.data3);
IWL_ERR(fwrt, "0x%08X | umac major\n", table.umac_major);
IWL_ERR(fwrt, "0x%08X | umac minor\n", table.umac_minor);
IWL_ERR(fwrt, "0x%08X | frame pointer\n", table.frame_pointer);
IWL_ERR(fwrt, "0x%08X | stack pointer\n", table.stack_pointer);
IWL_ERR(fwrt, "0x%08X | last host cmd\n", table.cmd_header);
IWL_ERR(fwrt, "0x%08X | isr status reg\n", table.nic_isr_pref);
}
static void iwl_fwrt_dump_lmac_error_log(struct iwl_fw_runtime *fwrt, u8 lmac_num)
{
struct iwl_trans *trans = fwrt->trans;
struct iwl_error_event_table table = {};
u32 val, base = fwrt->trans->dbg.lmac_error_event_table[lmac_num];
if (fwrt->cur_fw_img == IWL_UCODE_INIT) {
if (!base)
base = fwrt->fw->init_errlog_ptr;
} else {
if (!base)
base = fwrt->fw->inst_errlog_ptr;
}
if (base < 0x400000) {
IWL_ERR(fwrt,
"Not valid error log pointer 0x%08X for %s uCode\n",
base,
(fwrt->cur_fw_img == IWL_UCODE_INIT)
? "Init" : "RT");
return;
}
/* check if there is a HW error */
val = iwl_trans_read_mem32(trans, base);
if (((val & ~0xf) == 0xa5a5a5a0) || ((val & ~0xf) == 0x5a5a5a50)) {
int err;
IWL_ERR(trans, "HW error, resetting before reading\n");
/* reset the device */
iwl_trans_sw_reset(trans);
err = iwl_finish_nic_init(trans);
if (err)
return;
}
iwl_trans_read_mem_bytes(trans, base, &table, sizeof(table));
if (table.valid)
fwrt->dump.lmac_err_id[lmac_num] = table.error_id;
if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) {
IWL_ERR(trans, "Start IWL Error Log Dump:\n");
IWL_ERR(trans, "Transport status: 0x%08lX, valid: %d\n",
fwrt->trans->status, table.valid);
}
/* Do not change this output - scripts rely on it */
IWL_ERR(fwrt, "Loaded firmware version: %s\n", fwrt->fw->fw_version);
IWL_ERR(fwrt, "0x%08X | %-28s\n", table.error_id,
iwl_fw_lookup_assert_desc(table.error_id));
IWL_ERR(fwrt, "0x%08X | trm_hw_status0\n", table.trm_hw_status0);
IWL_ERR(fwrt, "0x%08X | trm_hw_status1\n", table.trm_hw_status1);
IWL_ERR(fwrt, "0x%08X | branchlink2\n", table.blink2);
IWL_ERR(fwrt, "0x%08X | interruptlink1\n", table.ilink1);
IWL_ERR(fwrt, "0x%08X | interruptlink2\n", table.ilink2);
IWL_ERR(fwrt, "0x%08X | data1\n", table.data1);
IWL_ERR(fwrt, "0x%08X | data2\n", table.data2);
IWL_ERR(fwrt, "0x%08X | data3\n", table.data3);
IWL_ERR(fwrt, "0x%08X | beacon time\n", table.bcon_time);
IWL_ERR(fwrt, "0x%08X | tsf low\n", table.tsf_low);
IWL_ERR(fwrt, "0x%08X | tsf hi\n", table.tsf_hi);
IWL_ERR(fwrt, "0x%08X | time gp1\n", table.gp1);
IWL_ERR(fwrt, "0x%08X | time gp2\n", table.gp2);
IWL_ERR(fwrt, "0x%08X | uCode revision type\n", table.fw_rev_type);
IWL_ERR(fwrt, "0x%08X | uCode version major\n", table.major);
IWL_ERR(fwrt, "0x%08X | uCode version minor\n", table.minor);
IWL_ERR(fwrt, "0x%08X | hw version\n", table.hw_ver);
IWL_ERR(fwrt, "0x%08X | board version\n", table.brd_ver);
IWL_ERR(fwrt, "0x%08X | hcmd\n", table.hcmd);
IWL_ERR(fwrt, "0x%08X | isr0\n", table.isr0);
IWL_ERR(fwrt, "0x%08X | isr1\n", table.isr1);
IWL_ERR(fwrt, "0x%08X | isr2\n", table.isr2);
IWL_ERR(fwrt, "0x%08X | isr3\n", table.isr3);
IWL_ERR(fwrt, "0x%08X | isr4\n", table.isr4);
IWL_ERR(fwrt, "0x%08X | last cmd Id\n", table.last_cmd_id);
IWL_ERR(fwrt, "0x%08X | wait_event\n", table.wait_event);
IWL_ERR(fwrt, "0x%08X | l2p_control\n", table.l2p_control);
IWL_ERR(fwrt, "0x%08X | l2p_duration\n", table.l2p_duration);
IWL_ERR(fwrt, "0x%08X | l2p_mhvalid\n", table.l2p_mhvalid);
IWL_ERR(fwrt, "0x%08X | l2p_addr_match\n", table.l2p_addr_match);
IWL_ERR(fwrt, "0x%08X | lmpm_pmg_sel\n", table.lmpm_pmg_sel);
IWL_ERR(fwrt, "0x%08X | timestamp\n", table.u_timestamp);
IWL_ERR(fwrt, "0x%08X | flow_handler\n", table.flow_handler);
}
/*
* TCM error struct.
* Note: This structure is read from the device with IO accesses,
* and the reading already does the endian conversion. As it is
* read with u32-sized accesses, any members with a different size
* need to be ordered correctly though!
*/
struct iwl_tcm_error_event_table {
u32 valid;
u32 error_id;
u32 blink2;
u32 ilink1;
u32 ilink2;
u32 data1, data2, data3;
u32 logpc;
u32 frame_pointer;
u32 stack_pointer;
u32 msgid;
u32 isr;
u32 hw_status[5];
u32 sw_status[1];
u32 reserved[4];
} __packed; /* TCM_LOG_ERROR_TABLE_API_S_VER_1 */
static void iwl_fwrt_dump_tcm_error_log(struct iwl_fw_runtime *fwrt)
{
struct iwl_trans *trans = fwrt->trans;
struct iwl_tcm_error_event_table table = {};
u32 base = fwrt->trans->dbg.tcm_error_event_table;
int i;
if (!base ||
!(fwrt->trans->dbg.error_event_table_tlv_status &
IWL_ERROR_EVENT_TABLE_TCM))
return;
iwl_trans_read_mem_bytes(trans, base, &table, sizeof(table));
IWL_ERR(fwrt, "TCM status:\n");
IWL_ERR(fwrt, "0x%08X | error ID\n", table.error_id);
IWL_ERR(fwrt, "0x%08X | tcm branchlink2\n", table.blink2);
IWL_ERR(fwrt, "0x%08X | tcm interruptlink1\n", table.ilink1);
IWL_ERR(fwrt, "0x%08X | tcm interruptlink2\n", table.ilink2);
IWL_ERR(fwrt, "0x%08X | tcm data1\n", table.data1);
IWL_ERR(fwrt, "0x%08X | tcm data2\n", table.data2);
IWL_ERR(fwrt, "0x%08X | tcm data3\n", table.data3);
IWL_ERR(fwrt, "0x%08X | tcm log PC\n", table.logpc);
IWL_ERR(fwrt, "0x%08X | tcm frame pointer\n", table.frame_pointer);
IWL_ERR(fwrt, "0x%08X | tcm stack pointer\n", table.stack_pointer);
IWL_ERR(fwrt, "0x%08X | tcm msg ID\n", table.msgid);
IWL_ERR(fwrt, "0x%08X | tcm ISR status\n", table.isr);
for (i = 0; i < ARRAY_SIZE(table.hw_status); i++)
IWL_ERR(fwrt, "0x%08X | tcm HW status[%d]\n",
table.hw_status[i], i);
for (i = 0; i < ARRAY_SIZE(table.sw_status); i++)
IWL_ERR(fwrt, "0x%08X | tcm SW status[%d]\n",
table.sw_status[i], i);
if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) {
u32 scratch = iwl_read32(trans, CSR_FUNC_SCRATCH);
IWL_ERR(fwrt, "Function Scratch status:\n");
IWL_ERR(fwrt, "0x%08X | Func Scratch\n", scratch);
}
}
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) {
error = UMAG_SB_CPU_2_STATUS;
data1 = UMAG_SB_CPU_1_STATUS;
} else if (fwrt->trans->trans_cfg->device_family >=
IWL_DEVICE_FAMILY_8000) {
error = SB_CPU_2_STATUS;
data1 = SB_CPU_1_STATUS;
} else {
return;
}
error = iwl_read_umac_prph(trans, UMAG_SB_CPU_2_STATUS);
IWL_ERR(trans, "IML/ROM dump:\n");
if (error & 0xFFFF0000)
IWL_ERR(trans, "0x%04X | IML/ROM SYSASSERT\n", error >> 16);
IWL_ERR(fwrt, "0x%08X | IML/ROM error/state\n", error);
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)
IWL_ERR(fwrt, "0x%08X | IML/ROM WFPM_AUTH_KEY_0\n",
iwl_read_umac_prph(trans, SB_MODIFY_CFG_FLAG));
}
#define FSEQ_REG(x) { .addr = (x), .str = #x, }
static void iwl_fwrt_dump_fseq_regs(struct iwl_fw_runtime *fwrt)
{
struct iwl_trans *trans = fwrt->trans;
int i;
struct {
u32 addr;
const char *str;
} fseq_regs[] = {
FSEQ_REG(FSEQ_ERROR_CODE),
FSEQ_REG(FSEQ_TOP_INIT_VERSION),
FSEQ_REG(FSEQ_CNVIO_INIT_VERSION),
FSEQ_REG(FSEQ_OTP_VERSION),
FSEQ_REG(FSEQ_TOP_CONTENT_VERSION),
FSEQ_REG(FSEQ_ALIVE_TOKEN),
FSEQ_REG(FSEQ_CNVI_ID),
FSEQ_REG(FSEQ_CNVR_ID),
FSEQ_REG(CNVI_AUX_MISC_CHIP),
FSEQ_REG(CNVR_AUX_MISC_CHIP),
FSEQ_REG(CNVR_SCU_SD_REGS_SD_REG_DIG_DCDC_VTRIM),
FSEQ_REG(CNVR_SCU_SD_REGS_SD_REG_ACTIVE_VDIG_MIRROR),
};
if (!iwl_trans_grab_nic_access(trans))
return;
IWL_ERR(fwrt, "Fseq Registers:\n");
for (i = 0; i < ARRAY_SIZE(fseq_regs); i++)
IWL_ERR(fwrt, "0x%08X | %s\n",
iwl_read_prph_no_grab(trans, fseq_regs[i].addr),
fseq_regs[i].str);
iwl_trans_release_nic_access(trans);
}
void iwl_fwrt_dump_error_logs(struct iwl_fw_runtime *fwrt)
{
if (!test_bit(STATUS_DEVICE_ENABLED, &fwrt->trans->status)) {
IWL_ERR(fwrt,
"DEVICE_ENABLED bit is not set. Aborting dump.\n");
return;
}
iwl_fwrt_dump_lmac_error_log(fwrt, 0);
if (fwrt->trans->dbg.lmac_error_event_table[1])
iwl_fwrt_dump_lmac_error_log(fwrt, 1);
iwl_fwrt_dump_umac_error_log(fwrt);
iwl_fwrt_dump_tcm_error_log(fwrt);
iwl_fwrt_dump_iml_error_log(fwrt);
iwl_fwrt_dump_fseq_regs(fwrt);
}
IWL_EXPORT_SYMBOL(iwl_fwrt_dump_error_logs);

View File

@ -0,0 +1,542 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2014, 2018-2021 Intel Corporation
* Copyright (C) 2014-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
#ifndef __fw_error_dump_h__
#define __fw_error_dump_h__
#include <linux/types.h>
#include "fw/api/cmdhdr.h"
#define IWL_FW_ERROR_DUMP_BARKER 0x14789632
#define IWL_FW_INI_ERROR_DUMP_BARKER 0x14789633
/**
* enum iwl_fw_error_dump_type - types of data in the dump file
* @IWL_FW_ERROR_DUMP_CSR: Control Status Registers - from offset 0
* @IWL_FW_ERROR_DUMP_RXF:
* @IWL_FW_ERROR_DUMP_TXCMD: last TX command data, structured as
* &struct iwl_fw_error_dump_txcmd packets
* @IWL_FW_ERROR_DUMP_DEV_FW_INFO: struct %iwl_fw_error_dump_info
* info on the device / firmware.
* @IWL_FW_ERROR_DUMP_FW_MONITOR: firmware monitor
* @IWL_FW_ERROR_DUMP_PRPH: range of periphery registers - there can be several
* sections like this in a single file.
* @IWL_FW_ERROR_DUMP_FH_REGS: range of FH registers
* @IWL_FW_ERROR_DUMP_MEM: chunk of memory
* @IWL_FW_ERROR_DUMP_ERROR_INFO: description of what triggered this dump.
* Structured as &struct iwl_fw_error_dump_trigger_desc.
* @IWL_FW_ERROR_DUMP_RB: the content of an RB structured as
* &struct iwl_fw_error_dump_rb
* @IWL_FW_ERROR_PAGING: UMAC's image memory segments which were
* paged to the DRAM.
* @IWL_FW_ERROR_DUMP_RADIO_REG: Dump the radio registers.
* @IWL_FW_ERROR_DUMP_EXTERNAL: used only by external code utilities, and
* for that reason is not in use in any other place in the Linux Wi-Fi
* stack.
* @IWL_FW_ERROR_DUMP_MEM_CFG: the addresses and sizes of fifos in the smem,
* which we get from the fw after ALIVE. The content is structured as
* &struct iwl_fw_error_dump_smem_cfg.
*/
enum iwl_fw_error_dump_type {
/* 0 is deprecated */
IWL_FW_ERROR_DUMP_CSR = 1,
IWL_FW_ERROR_DUMP_RXF = 2,
IWL_FW_ERROR_DUMP_TXCMD = 3,
IWL_FW_ERROR_DUMP_DEV_FW_INFO = 4,
IWL_FW_ERROR_DUMP_FW_MONITOR = 5,
IWL_FW_ERROR_DUMP_PRPH = 6,
IWL_FW_ERROR_DUMP_TXF = 7,
IWL_FW_ERROR_DUMP_FH_REGS = 8,
IWL_FW_ERROR_DUMP_MEM = 9,
IWL_FW_ERROR_DUMP_ERROR_INFO = 10,
IWL_FW_ERROR_DUMP_RB = 11,
IWL_FW_ERROR_DUMP_PAGING = 12,
IWL_FW_ERROR_DUMP_RADIO_REG = 13,
IWL_FW_ERROR_DUMP_INTERNAL_TXF = 14,
IWL_FW_ERROR_DUMP_EXTERNAL = 15, /* Do not move */
IWL_FW_ERROR_DUMP_MEM_CFG = 16,
IWL_FW_ERROR_DUMP_D3_DEBUG_DATA = 17,
IWL_FW_ERROR_DUMP_MAX,
};
/**
* struct iwl_fw_error_dump_data - data for one type
* @type: &enum iwl_fw_error_dump_type
* @len: the length starting from %data
* @data: the data itself
*/
struct iwl_fw_error_dump_data {
__le32 type;
__le32 len;
__u8 data[];
} __packed;
/**
* struct iwl_fw_error_dump_file - the layout of the header of the file
* @barker: must be %IWL_FW_ERROR_DUMP_BARKER
* @file_len: the length of all the file starting from %barker
* @data: array of &struct iwl_fw_error_dump_data
*/
struct iwl_fw_error_dump_file {
__le32 barker;
__le32 file_len;
u8 data[0];
} __packed;
/**
* struct iwl_fw_error_dump_txcmd - TX command data
* @cmdlen: original length of command
* @caplen: captured length of command (may be less)
* @data: captured command data, @caplen bytes
*/
struct iwl_fw_error_dump_txcmd {
__le32 cmdlen;
__le32 caplen;
u8 data[];
} __packed;
/**
* struct iwl_fw_error_dump_fifo - RX/TX FIFO data
* @fifo_num: number of FIFO (starting from 0)
* @available_bytes: num of bytes available in FIFO (may be less than FIFO size)
* @wr_ptr: position of write pointer
* @rd_ptr: position of read pointer
* @fence_ptr: position of fence pointer
* @fence_mode: the current mode of the fence (before locking) -
* 0=follow RD pointer ; 1 = freeze
* @data: all of the FIFO's data
*/
struct iwl_fw_error_dump_fifo {
__le32 fifo_num;
__le32 available_bytes;
__le32 wr_ptr;
__le32 rd_ptr;
__le32 fence_ptr;
__le32 fence_mode;
u8 data[];
} __packed;
enum iwl_fw_error_dump_family {
IWL_FW_ERROR_DUMP_FAMILY_7 = 7,
IWL_FW_ERROR_DUMP_FAMILY_8 = 8,
};
#define MAX_NUM_LMAC 2
/**
* struct iwl_fw_error_dump_info - info on the device / firmware
* @hw_type: the type of the device
* @hw_step: the step of the device
* @fw_human_readable: human readable FW version
* @dev_human_readable: name of the device
* @bus_human_readable: name of the bus used
* @num_of_lmacs: the number of lmacs
* @lmac_err_id: the lmac 0/1 error_id/rt_status that triggered the latest dump
* if the dump collection was not initiated by an assert, the value is 0
* @umac_err_id: the umac error_id/rt_status that triggered the latest dump
* if the dump collection was not initiated by an assert, the value is 0
*/
struct iwl_fw_error_dump_info {
__le32 hw_type;
__le32 hw_step;
u8 fw_human_readable[FW_VER_HUMAN_READABLE_SZ];
u8 dev_human_readable[64];
u8 bus_human_readable[8];
u8 num_of_lmacs;
__le32 umac_err_id;
__le32 lmac_err_id[MAX_NUM_LMAC];
} __packed;
/**
* struct iwl_fw_error_dump_fw_mon - FW monitor data
* @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
* so fw_mon_base_ptr holds LSB 32 bits and fw_mon_base_high_ptr hold
* MSB 32 bits
* @reserved: for future use
* @data: captured data
*/
struct iwl_fw_error_dump_fw_mon {
__le32 fw_mon_wr_ptr;
__le32 fw_mon_base_ptr;
__le32 fw_mon_cycle_cnt;
__le32 fw_mon_base_high_ptr;
__le32 reserved[2];
u8 data[];
} __packed;
#define MAX_NUM_LMAC 2
#define TX_FIFO_INTERNAL_MAX_NUM 6
#define TX_FIFO_MAX_NUM 15
/**
* struct iwl_fw_error_dump_smem_cfg - Dump SMEM configuration
* This must follow &struct iwl_fwrt_shared_mem_cfg.
* @num_lmacs: number of lmacs
* @num_txfifo_entries: number of tx fifos
* @lmac: sizes of lmacs txfifos and rxfifo1
* @rxfifo2_size: size of rxfifo2
* @internal_txfifo_addr: address of internal tx fifo
* @internal_txfifo_size: size of internal tx fifo
*/
struct iwl_fw_error_dump_smem_cfg {
__le32 num_lmacs;
__le32 num_txfifo_entries;
struct {
__le32 txfifo_size[TX_FIFO_MAX_NUM];
__le32 rxfifo1_size;
} lmac[MAX_NUM_LMAC];
__le32 rxfifo2_size;
__le32 internal_txfifo_addr;
__le32 internal_txfifo_size[TX_FIFO_INTERNAL_MAX_NUM];
} __packed;
/**
* struct iwl_fw_error_dump_prph - periphery registers data
* @prph_start: address of the first register in this chunk
* @data: the content of the registers
*/
struct iwl_fw_error_dump_prph {
__le32 prph_start;
__le32 data[];
};
enum iwl_fw_error_dump_mem_type {
IWL_FW_ERROR_DUMP_MEM_SRAM,
IWL_FW_ERROR_DUMP_MEM_SMEM,
IWL_FW_ERROR_DUMP_MEM_NAMED_MEM = 10,
};
/**
* struct iwl_fw_error_dump_mem - chunk of memory
* @type: &enum iwl_fw_error_dump_mem_type
* @offset: the offset from which the memory was read
* @data: the content of the memory
*/
struct iwl_fw_error_dump_mem {
__le32 type;
__le32 offset;
u8 data[];
};
/* Dump version, used by the dump parser to differentiate between
* different dump formats
*/
#define IWL_INI_DUMP_VER 1
/* Use bit 31 as dump info type to avoid colliding with region types */
#define IWL_INI_DUMP_INFO_TYPE BIT(31)
/**
* struct iwl_fw_ini_dump_entry
* @list: list of dump entries
* @size: size of the data
* @data: entry data
*/
struct iwl_fw_ini_dump_entry {
struct list_head list;
u32 size;
u8 data[];
} __packed;
/**
* struct iwl_fw_error_dump_file - header of dump file
* @barker: must be %IWL_FW_INI_ERROR_DUMP_BARKER
* @file_len: the length of all the file including the header
*/
struct iwl_fw_ini_dump_file_hdr {
__le32 barker;
__le32 file_len;
} __packed;
/**
* struct iwl_fw_ini_fifo_hdr - fifo range header
* @fifo_num: the fifo number. In case of umac rx fifo, set BIT(31) to
* distinguish between lmac and umac rx fifos
* @num_of_registers: num of registers to dump, dword size each
*/
struct iwl_fw_ini_fifo_hdr {
__le32 fifo_num;
__le32 num_of_registers;
} __packed;
/**
* struct iwl_fw_ini_error_dump_range - range of memory
* @range_data_size: the size of this range, in bytes
* @internal_base_addr: base address of internal memory range
* @dram_base_addr: base address of dram monitor range
* @page_num: page number of memory range
* @fifo_hdr: fifo header of memory range
* @fw_pkt: FW packet header of memory range
* @data: the actual memory
*/
struct iwl_fw_ini_error_dump_range {
__le32 range_data_size;
union {
__le32 internal_base_addr;
__le64 dram_base_addr;
__le32 page_num;
struct iwl_fw_ini_fifo_hdr fifo_hdr;
struct iwl_cmd_header fw_pkt_hdr;
};
__le32 data[];
} __packed;
/**
* struct iwl_fw_ini_error_dump_header - ini region dump header
* @version: dump version
* @region_id: id of the region
* @num_of_ranges: number of ranges in this region
* @name_len: number of bytes allocated to the name string of this region
* @name: name of the region
*/
struct iwl_fw_ini_error_dump_header {
__le32 version;
__le32 region_id;
__le32 num_of_ranges;
__le32 name_len;
u8 name[IWL_FW_INI_MAX_NAME];
};
/**
* struct iwl_fw_ini_error_dump - ini region dump
* @header: the header of this region
* @data: data of memory ranges in this region,
* see &struct iwl_fw_ini_error_dump_range
*/
struct iwl_fw_ini_error_dump {
struct iwl_fw_ini_error_dump_header header;
u8 data[];
} __packed;
/* This bit is used to differentiate between lmac and umac rxf */
#define IWL_RXF_UMAC_BIT BIT(31)
/**
* struct iwl_fw_ini_error_dump_register - ini register dump
* @addr: address of the register
* @data: data of the register
*/
struct iwl_fw_ini_error_dump_register {
__le32 addr;
__le32 data;
} __packed;
/**
* struct iwl_fw_ini_dump_cfg_name - configuration name
* @image_type: image type the configuration is related to
* @cfg_name_len: length of the configuration name
* @cfg_name: name of the configuraiton
*/
struct iwl_fw_ini_dump_cfg_name {
__le32 image_type;
__le32 cfg_name_len;
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
/* struct iwl_fw_ini_dump_info - ini dump information
* @version: dump version
* @time_point: time point that caused the dump collection
* @trigger_reason: reason of the trigger
* @external_cfg_state: &enum iwl_ini_cfg_state
* @ver_type: FW version type
* @ver_subtype: FW version subype
* @hw_step: HW step
* @hw_type: HW type
* @rf_id_flavor: HW RF id flavor
* @rf_id_dash: HW RF id dash
* @rf_id_step: HW RF id step
* @rf_id_type: HW RF id type
* @lmac_major: lmac major version
* @lmac_minor: lmac minor version
* @umac_major: umac major version
* @umac_minor: umac minor version
* @fw_mon_mode: FW monitor mode &enum iwl_fw_ini_buffer_location
* @regions_mask: bitmap mask of regions ids in the dump
* @build_tag_len: length of the build tag
* @build_tag: build tag string
* @num_of_cfg_names: number of configuration name structs
* @cfg_names: configuration names
*/
struct iwl_fw_ini_dump_info {
__le32 version;
__le32 time_point;
__le32 trigger_reason;
__le32 external_cfg_state;
__le32 ver_type;
__le32 ver_subtype;
__le32 hw_step;
__le32 hw_type;
__le32 rf_id_flavor;
__le32 rf_id_dash;
__le32 rf_id_step;
__le32 rf_id_type;
__le32 lmac_major;
__le32 lmac_minor;
__le32 umac_major;
__le32 umac_minor;
__le32 fw_mon_mode;
__le64 regions_mask;
__le32 build_tag_len;
u8 build_tag[FW_VER_HUMAN_READABLE_SZ];
__le32 num_of_cfg_names;
struct iwl_fw_ini_dump_cfg_name cfg_names[];
} __packed;
/**
* struct iwl_fw_ini_err_table_dump - ini error table dump
* @header: header of the region
* @version: error table version
* @data: data of memory ranges in this region,
* see &struct iwl_fw_ini_error_dump_range
*/
struct iwl_fw_ini_err_table_dump {
struct iwl_fw_ini_error_dump_header header;
__le32 version;
u8 data[];
} __packed;
/**
* struct iwl_fw_error_dump_rb - content of an Receive Buffer
* @index: the index of the Receive Buffer in the Rx queue
* @rxq: the RB's Rx queue
* @reserved:
* @data: the content of the Receive Buffer
*/
struct iwl_fw_error_dump_rb {
__le32 index;
__le32 rxq;
__le32 reserved;
u8 data[];
};
/**
* struct iwl_fw_ini_monitor_dump - ini monitor dump
* @header: header of the region
* @write_ptr: write pointer position in the buffer
* @cycle_cnt: cycles count
* @cur_frag: current fragment in use
* @data: data of memory ranges in this region,
* see &struct iwl_fw_ini_error_dump_range
*/
struct iwl_fw_ini_monitor_dump {
struct iwl_fw_ini_error_dump_header header;
__le32 write_ptr;
__le32 cycle_cnt;
__le32 cur_frag;
u8 data[];
} __packed;
/**
* struct iwl_fw_ini_special_device_memory - special device memory
* @header: header of the region
* @type: type of special memory
* @version: struct special memory version
* @data: data of memory ranges in this region,
* see &struct iwl_fw_ini_error_dump_range
*/
struct iwl_fw_ini_special_device_memory {
struct iwl_fw_ini_error_dump_header header;
__le16 type;
__le16 version;
u8 data[];
} __packed;
/**
* struct iwl_fw_error_dump_paging - content of the UMAC's image page
* block on DRAM
* @index: the index of the page block
* @reserved:
* @data: the content of the page block
*/
struct iwl_fw_error_dump_paging {
__le32 index;
__le32 reserved;
u8 data[];
};
/**
* iwl_fw_error_next_data - advance fw error dump data pointer
* @data: previous data block
* Returns: next data block
*/
static inline struct iwl_fw_error_dump_data *
iwl_fw_error_next_data(struct iwl_fw_error_dump_data *data)
{
return (void *)(data->data + le32_to_cpu(data->len));
}
/**
* enum iwl_fw_dbg_trigger - triggers available
*
* @FW_DBG_TRIGGER_USER: trigger log collection by user
* This should not be defined as a trigger to the driver, but a value the
* driver should set to indicate that the trigger was initiated by the
* user.
* @FW_DBG_TRIGGER_FW_ASSERT: trigger log collection when the firmware asserts
* @FW_DBG_TRIGGER_MISSED_BEACONS: trigger log collection when beacons are
* missed.
* @FW_DBG_TRIGGER_CHANNEL_SWITCH: trigger log collection upon channel switch.
* @FW_DBG_TRIGGER_FW_NOTIF: trigger log collection when the firmware sends a
* command response or a notification.
* @FW_DBG_TRIGGER_MLME: trigger log collection upon MLME event.
* @FW_DBG_TRIGGER_STATS: trigger log collection upon statistics threshold.
* @FW_DBG_TRIGGER_RSSI: trigger log collection when the rssi of the beacon
* goes below a threshold.
* @FW_DBG_TRIGGER_TXQ_TIMERS: configures the timers for the Tx queue hang
* detection.
* @FW_DBG_TRIGGER_TIME_EVENT: trigger log collection upon time events related
* events.
* @FW_DBG_TRIGGER_BA: trigger log collection upon BlockAck related events.
* @FW_DBG_TX_LATENCY: trigger log collection when the tx latency goes above a
* threshold.
* @FW_DBG_TDLS: trigger log collection upon TDLS related events.
* @FW_DBG_TRIGGER_TX_STATUS: trigger log collection upon tx status when
* the firmware sends a tx reply.
* @FW_DBG_TRIGGER_ALIVE_TIMEOUT: trigger log collection if alive flow timeouts
* @FW_DBG_TRIGGER_DRIVER: trigger log collection upon a flow failure
* in the driver.
*/
enum iwl_fw_dbg_trigger {
FW_DBG_TRIGGER_INVALID = 0,
FW_DBG_TRIGGER_USER,
FW_DBG_TRIGGER_FW_ASSERT,
FW_DBG_TRIGGER_MISSED_BEACONS,
FW_DBG_TRIGGER_CHANNEL_SWITCH,
FW_DBG_TRIGGER_FW_NOTIF,
FW_DBG_TRIGGER_MLME,
FW_DBG_TRIGGER_STATS,
FW_DBG_TRIGGER_RSSI,
FW_DBG_TRIGGER_TXQ_TIMERS,
FW_DBG_TRIGGER_TIME_EVENT,
FW_DBG_TRIGGER_BA,
FW_DBG_TRIGGER_TX_LATENCY,
FW_DBG_TRIGGER_TDLS,
FW_DBG_TRIGGER_TX_STATUS,
FW_DBG_TRIGGER_ALIVE_TIMEOUT,
FW_DBG_TRIGGER_DRIVER,
/* must be last */
FW_DBG_TRIGGER_MAX,
};
/**
* struct iwl_fw_error_dump_trigger_desc - describes the trigger condition
* @type: &enum iwl_fw_dbg_trigger
* @data: raw data about what happened
*/
struct iwl_fw_error_dump_trigger_desc {
__le32 type;
u8 data[];
};
#endif /* __fw_error_dump_h__ */

View File

@ -0,0 +1,984 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2008-2014, 2018-2021 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
#ifndef __iwl_fw_file_h__
#define __iwl_fw_file_h__
#include <linux/netdevice.h>
#include <linux/nl80211.h>
/* v1/v2 uCode file layout */
struct iwl_ucode_header {
__le32 ver; /* major/minor/API/serial */
union {
struct {
__le32 inst_size; /* bytes of runtime code */
__le32 data_size; /* bytes of runtime data */
__le32 init_size; /* bytes of init code */
__le32 init_data_size; /* bytes of init data */
__le32 boot_size; /* bytes of bootstrap code */
u8 data[0]; /* in same order as sizes */
} v1;
struct {
__le32 build; /* build number */
__le32 inst_size; /* bytes of runtime code */
__le32 data_size; /* bytes of runtime data */
__le32 init_size; /* bytes of init code */
__le32 init_data_size; /* bytes of init data */
__le32 boot_size; /* bytes of bootstrap code */
u8 data[0]; /* in same order as sizes */
} v2;
} u;
};
#define IWL_UCODE_TLV_DEBUG_BASE 0x1000005
#define IWL_UCODE_TLV_CONST_BASE 0x100
/*
* new TLV uCode file layout
*
* The new TLV file format contains TLVs, that each specify
* some piece of data.
*/
enum iwl_ucode_tlv_type {
IWL_UCODE_TLV_INVALID = 0, /* unused */
IWL_UCODE_TLV_INST = 1,
IWL_UCODE_TLV_DATA = 2,
IWL_UCODE_TLV_INIT = 3,
IWL_UCODE_TLV_INIT_DATA = 4,
IWL_UCODE_TLV_BOOT = 5,
IWL_UCODE_TLV_PROBE_MAX_LEN = 6, /* a u32 value */
IWL_UCODE_TLV_PAN = 7, /* deprecated -- only used in DVM */
IWL_UCODE_TLV_MEM_DESC = 7, /* replaces PAN in non-DVM */
IWL_UCODE_TLV_RUNT_EVTLOG_PTR = 8,
IWL_UCODE_TLV_RUNT_EVTLOG_SIZE = 9,
IWL_UCODE_TLV_RUNT_ERRLOG_PTR = 10,
IWL_UCODE_TLV_INIT_EVTLOG_PTR = 11,
IWL_UCODE_TLV_INIT_EVTLOG_SIZE = 12,
IWL_UCODE_TLV_INIT_ERRLOG_PTR = 13,
IWL_UCODE_TLV_ENHANCE_SENS_TBL = 14,
IWL_UCODE_TLV_PHY_CALIBRATION_SIZE = 15,
IWL_UCODE_TLV_WOWLAN_INST = 16,
IWL_UCODE_TLV_WOWLAN_DATA = 17,
IWL_UCODE_TLV_FLAGS = 18,
IWL_UCODE_TLV_SEC_RT = 19,
IWL_UCODE_TLV_SEC_INIT = 20,
IWL_UCODE_TLV_SEC_WOWLAN = 21,
IWL_UCODE_TLV_DEF_CALIB = 22,
IWL_UCODE_TLV_PHY_SKU = 23,
IWL_UCODE_TLV_SECURE_SEC_RT = 24,
IWL_UCODE_TLV_SECURE_SEC_INIT = 25,
IWL_UCODE_TLV_SECURE_SEC_WOWLAN = 26,
IWL_UCODE_TLV_NUM_OF_CPU = 27,
IWL_UCODE_TLV_CSCHEME = 28,
IWL_UCODE_TLV_API_CHANGES_SET = 29,
IWL_UCODE_TLV_ENABLED_CAPABILITIES = 30,
IWL_UCODE_TLV_N_SCAN_CHANNELS = 31,
IWL_UCODE_TLV_PAGING = 32,
IWL_UCODE_TLV_SEC_RT_USNIFFER = 34,
/* 35 is unused */
IWL_UCODE_TLV_FW_VERSION = 36,
IWL_UCODE_TLV_FW_DBG_DEST = 38,
IWL_UCODE_TLV_FW_DBG_CONF = 39,
IWL_UCODE_TLV_FW_DBG_TRIGGER = 40,
IWL_UCODE_TLV_CMD_VERSIONS = 48,
IWL_UCODE_TLV_FW_GSCAN_CAPA = 50,
IWL_UCODE_TLV_FW_MEM_SEG = 51,
IWL_UCODE_TLV_IML = 52,
IWL_UCODE_TLV_UMAC_DEBUG_ADDRS = 54,
IWL_UCODE_TLV_LMAC_DEBUG_ADDRS = 55,
IWL_UCODE_TLV_FW_RECOVERY_INFO = 57,
IWL_UCODE_TLV_HW_TYPE = 58,
IWL_UCODE_TLV_FW_FSEQ_VERSION = 60,
IWL_UCODE_TLV_PHY_INTEGRATION_VERSION = 61,
IWL_UCODE_TLV_PNVM_VERSION = 62,
IWL_UCODE_TLV_PNVM_SKU = 64,
IWL_UCODE_TLV_TCM_DEBUG_ADDRS = 65,
IWL_UCODE_TLV_SEC_TABLE_ADDR = 66,
IWL_UCODE_TLV_D3_KEK_KCK_ADDR = 67,
IWL_UCODE_TLV_FW_NUM_STATIONS = IWL_UCODE_TLV_CONST_BASE + 0,
IWL_UCODE_TLV_TYPE_DEBUG_INFO = IWL_UCODE_TLV_DEBUG_BASE + 0,
IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION = IWL_UCODE_TLV_DEBUG_BASE + 1,
IWL_UCODE_TLV_TYPE_HCMD = IWL_UCODE_TLV_DEBUG_BASE + 2,
IWL_UCODE_TLV_TYPE_REGIONS = IWL_UCODE_TLV_DEBUG_BASE + 3,
IWL_UCODE_TLV_TYPE_TRIGGERS = IWL_UCODE_TLV_DEBUG_BASE + 4,
IWL_UCODE_TLV_TYPE_CONF_SET = IWL_UCODE_TLV_DEBUG_BASE + 5,
IWL_UCODE_TLV_DEBUG_MAX = IWL_UCODE_TLV_TYPE_TRIGGERS,
/* TLVs 0x1000-0x2000 are for internal driver usage */
IWL_UCODE_TLV_FW_DBG_DUMP_LST = 0x1000,
};
struct iwl_ucode_tlv {
__le32 type; /* see above */
__le32 length; /* not including type/length fields */
u8 data[0];
};
#define IWL_TLV_UCODE_MAGIC 0x0a4c5749
#define FW_VER_HUMAN_READABLE_SZ 64
struct iwl_tlv_ucode_header {
/*
* The TLV style ucode header is distinguished from
* the v1/v2 style header by first four bytes being
* zero, as such is an invalid combination of
* major/minor/API/serial versions.
*/
__le32 zero;
__le32 magic;
u8 human_readable[FW_VER_HUMAN_READABLE_SZ];
/* major/minor/API/serial or major in new format */
__le32 ver;
__le32 build;
__le64 ignore;
/*
* The data contained herein has a TLV layout,
* see above for the TLV header and types.
* Note that each TLV is padded to a length
* that is a multiple of 4 for alignment.
*/
u8 data[0];
};
/*
* ucode TLVs
*
* ability to get extension for: flags & capabilities from ucode binaries files
*/
struct iwl_ucode_api {
__le32 api_index;
__le32 api_flags;
} __packed;
struct iwl_ucode_capa {
__le32 api_index;
__le32 api_capa;
} __packed;
/**
* enum iwl_ucode_tlv_flag - ucode API flags
* @IWL_UCODE_TLV_FLAGS_PAN: This is PAN capable microcode; this previously
* was a separate TLV but moved here to save space.
* @IWL_UCODE_TLV_FLAGS_NEWSCAN: new uCode scan behavior on hidden SSID,
* treats good CRC threshold as a boolean
* @IWL_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w).
* @IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT: This uCode image supports uAPSD
* @IWL_UCODE_TLV_FLAGS_SHORT_BL: 16 entries of block list instead of 64 in scan
* offload profile config command.
* @IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS: D3 image supports up to six
* (rather than two) IPv6 addresses
* @IWL_UCODE_TLV_FLAGS_NO_BASIC_SSID: not sending a probe with the SSID element
* from the probe request template.
* @IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL: new NS offload (small version)
* @IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_LARGE: new NS offload (large version)
* @IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT: General support for uAPSD
* @IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD: P2P client supports uAPSD power save
* @IWL_UCODE_TLV_FLAGS_BCAST_FILTERING: uCode supports broadcast filtering.
* @IWL_UCODE_TLV_FLAGS_EBS_SUPPORT: this uCode image supports EBS.
*/
enum iwl_ucode_tlv_flag {
IWL_UCODE_TLV_FLAGS_PAN = BIT(0),
IWL_UCODE_TLV_FLAGS_NEWSCAN = BIT(1),
IWL_UCODE_TLV_FLAGS_MFP = BIT(2),
IWL_UCODE_TLV_FLAGS_SHORT_BL = BIT(7),
IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS = BIT(10),
IWL_UCODE_TLV_FLAGS_NO_BASIC_SSID = BIT(12),
IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL = BIT(15),
IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_LARGE = BIT(16),
IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT = BIT(24),
IWL_UCODE_TLV_FLAGS_EBS_SUPPORT = BIT(25),
IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD = BIT(26),
IWL_UCODE_TLV_FLAGS_BCAST_FILTERING = BIT(29),
};
typedef unsigned int __bitwise iwl_ucode_tlv_api_t;
/**
* enum iwl_ucode_tlv_api - ucode api
* @IWL_UCODE_TLV_API_FRAGMENTED_SCAN: This ucode supports active dwell time
* longer than the passive one, which is essential for fragmented scan.
* @IWL_UCODE_TLV_API_WIFI_MCC_UPDATE: ucode supports MCC updates with source.
* @IWL_UCODE_TLV_API_LQ_SS_PARAMS: Configure STBC/BFER via LQ CMD ss_params
* @IWL_UCODE_TLV_API_NEW_VERSION: new versioning format
* @IWL_UCODE_TLV_API_SCAN_TSF_REPORT: Scan start time reported in scan
* iteration complete notification, and the timestamp reported for RX
* received during scan, are reported in TSF of the mac specified in the
* scan request.
* @IWL_UCODE_TLV_API_TKIP_MIC_KEYS: This ucode supports version 2 of
* ADD_MODIFY_STA_KEY_API_S_VER_2.
* @IWL_UCODE_TLV_API_STA_TYPE: This ucode supports station type assignement.
* @IWL_UCODE_TLV_API_NAN2_VER2: This ucode supports NAN API version 2
* @IWL_UCODE_TLV_API_NEW_RX_STATS: should new RX STATISTICS API be used
* @IWL_UCODE_TLV_API_QUOTA_LOW_LATENCY: Quota command includes a field
* indicating low latency direction.
* @IWL_UCODE_TLV_API_DEPRECATE_TTAK: RX status flag TTAK ok (bit 7) is
* deprecated.
* @IWL_UCODE_TLV_API_ADAPTIVE_DWELL_V2: This ucode supports version 8
* of scan request: SCAN_REQUEST_CMD_UMAC_API_S_VER_8
* @IWL_UCODE_TLV_API_FRAG_EBS: This ucode supports fragmented EBS
* @IWL_UCODE_TLV_API_REDUCE_TX_POWER: This ucode supports v5 of
* the REDUCE_TX_POWER_CMD.
* @IWL_UCODE_TLV_API_SHORT_BEACON_NOTIF: This ucode supports the short
* version of the beacon notification.
* @IWL_UCODE_TLV_API_BEACON_FILTER_V4: This ucode supports v4 of
* BEACON_FILTER_CONFIG_API_S_VER_4.
* @IWL_UCODE_TLV_API_REGULATORY_NVM_INFO: This ucode supports v4 of
* REGULATORY_NVM_GET_INFO_RSP_API_S.
* @IWL_UCODE_TLV_API_FTM_NEW_RANGE_REQ: This ucode supports v7 of
* LOCATION_RANGE_REQ_CMD_API_S and v6 of LOCATION_RANGE_RESP_NTFY_API_S.
* @IWL_UCODE_TLV_API_SCAN_OFFLOAD_CHANS: This ucode supports v2 of
* SCAN_OFFLOAD_PROFILE_MATCH_RESULTS_S and v3 of
* SCAN_OFFLOAD_PROFILES_QUERY_RSP_S.
* @IWL_UCODE_TLV_API_MBSSID_HE: This ucode supports v2 of
* STA_CONTEXT_DOT11AX_API_S
* @IWL_UCODE_TLV_API_SAR_TABLE_VER: This ucode supports different sar
* version tables.
* @IWL_UCODE_TLV_API_REDUCED_SCAN_CONFIG: This ucode supports v3 of
* SCAN_CONFIG_DB_CMD_API_S.
*
* @NUM_IWL_UCODE_TLV_API: number of bits used
*/
enum iwl_ucode_tlv_api {
/* API Set 0 */
IWL_UCODE_TLV_API_FRAGMENTED_SCAN = (__force iwl_ucode_tlv_api_t)8,
IWL_UCODE_TLV_API_WIFI_MCC_UPDATE = (__force iwl_ucode_tlv_api_t)9,
IWL_UCODE_TLV_API_LQ_SS_PARAMS = (__force iwl_ucode_tlv_api_t)18,
IWL_UCODE_TLV_API_NEW_VERSION = (__force iwl_ucode_tlv_api_t)20,
IWL_UCODE_TLV_API_SCAN_TSF_REPORT = (__force iwl_ucode_tlv_api_t)28,
IWL_UCODE_TLV_API_TKIP_MIC_KEYS = (__force iwl_ucode_tlv_api_t)29,
IWL_UCODE_TLV_API_STA_TYPE = (__force iwl_ucode_tlv_api_t)30,
IWL_UCODE_TLV_API_NAN2_VER2 = (__force iwl_ucode_tlv_api_t)31,
/* API Set 1 */
IWL_UCODE_TLV_API_ADAPTIVE_DWELL = (__force iwl_ucode_tlv_api_t)32,
IWL_UCODE_TLV_API_OCE = (__force iwl_ucode_tlv_api_t)33,
IWL_UCODE_TLV_API_NEW_BEACON_TEMPLATE = (__force iwl_ucode_tlv_api_t)34,
IWL_UCODE_TLV_API_NEW_RX_STATS = (__force iwl_ucode_tlv_api_t)35,
IWL_UCODE_TLV_API_WOWLAN_KEY_MATERIAL = (__force iwl_ucode_tlv_api_t)36,
IWL_UCODE_TLV_API_QUOTA_LOW_LATENCY = (__force iwl_ucode_tlv_api_t)38,
IWL_UCODE_TLV_API_DEPRECATE_TTAK = (__force iwl_ucode_tlv_api_t)41,
IWL_UCODE_TLV_API_ADAPTIVE_DWELL_V2 = (__force iwl_ucode_tlv_api_t)42,
IWL_UCODE_TLV_API_FRAG_EBS = (__force iwl_ucode_tlv_api_t)44,
IWL_UCODE_TLV_API_REDUCE_TX_POWER = (__force iwl_ucode_tlv_api_t)45,
IWL_UCODE_TLV_API_SHORT_BEACON_NOTIF = (__force iwl_ucode_tlv_api_t)46,
IWL_UCODE_TLV_API_BEACON_FILTER_V4 = (__force iwl_ucode_tlv_api_t)47,
IWL_UCODE_TLV_API_REGULATORY_NVM_INFO = (__force iwl_ucode_tlv_api_t)48,
IWL_UCODE_TLV_API_FTM_NEW_RANGE_REQ = (__force iwl_ucode_tlv_api_t)49,
IWL_UCODE_TLV_API_SCAN_OFFLOAD_CHANS = (__force iwl_ucode_tlv_api_t)50,
IWL_UCODE_TLV_API_MBSSID_HE = (__force iwl_ucode_tlv_api_t)52,
IWL_UCODE_TLV_API_WOWLAN_TCP_SYN_WAKE = (__force iwl_ucode_tlv_api_t)53,
IWL_UCODE_TLV_API_FTM_RTT_ACCURACY = (__force iwl_ucode_tlv_api_t)54,
IWL_UCODE_TLV_API_SAR_TABLE_VER = (__force iwl_ucode_tlv_api_t)55,
IWL_UCODE_TLV_API_REDUCED_SCAN_CONFIG = (__force iwl_ucode_tlv_api_t)56,
IWL_UCODE_TLV_API_ADWELL_HB_DEF_N_AP = (__force iwl_ucode_tlv_api_t)57,
IWL_UCODE_TLV_API_SCAN_EXT_CHAN_VER = (__force iwl_ucode_tlv_api_t)58,
IWL_UCODE_TLV_API_BAND_IN_RX_DATA = (__force iwl_ucode_tlv_api_t)59,
#ifdef __CHECKER__
/* sparse says it cannot increment the previous enum member */
#define NUM_IWL_UCODE_TLV_API 128
#else
NUM_IWL_UCODE_TLV_API
#endif
};
typedef unsigned int __bitwise iwl_ucode_tlv_capa_t;
/**
* enum iwl_ucode_tlv_capa - ucode capabilities
* @IWL_UCODE_TLV_CAPA_D0I3_SUPPORT: supports D0i3
* @IWL_UCODE_TLV_CAPA_LAR_SUPPORT: supports Location Aware Regulatory
* @IWL_UCODE_TLV_CAPA_UMAC_SCAN: supports UMAC scan.
* @IWL_UCODE_TLV_CAPA_BEAMFORMER: supports Beamformer
* @IWL_UCODE_TLV_CAPA_TDLS_SUPPORT: support basic TDLS functionality
* @IWL_UCODE_TLV_CAPA_TXPOWER_INSERTION_SUPPORT: supports insertion of current
* tx power value into TPC Report action frame and Link Measurement Report
* action frame
* @IWL_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT: supports updating current
* channel in DS parameter set element in probe requests.
* @IWL_UCODE_TLV_CAPA_WFA_TPC_REP_IE_SUPPORT: supports adding TPC Report IE in
* probe requests.
* @IWL_UCODE_TLV_CAPA_QUIET_PERIOD_SUPPORT: supports Quiet Period requests
* @IWL_UCODE_TLV_CAPA_DQA_SUPPORT: supports dynamic queue allocation (DQA),
* which also implies support for the scheduler configuration command
* @IWL_UCODE_TLV_CAPA_TDLS_CHANNEL_SWITCH: supports TDLS channel switching
* @IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG: Consolidated D3-D0 image
* @IWL_UCODE_TLV_CAPA_HOTSPOT_SUPPORT: supports Hot Spot Command
* @IWL_UCODE_TLV_CAPA_DC2DC_SUPPORT: supports DC2DC Command
* @IWL_UCODE_TLV_CAPA_CSUM_SUPPORT: supports TCP Checksum Offload
* @IWL_UCODE_TLV_CAPA_RADIO_BEACON_STATS: support radio and beacon statistics
* @IWL_UCODE_TLV_CAPA_P2P_SCM_UAPSD: supports U-APSD on p2p interface when it
* is standalone or with a BSS station interface in the same binding.
* @IWL_UCODE_TLV_CAPA_BT_COEX_PLCR: enabled BT Coex packet level co-running
* @IWL_UCODE_TLV_CAPA_LAR_MULTI_MCC: ucode supports LAR updates with different
* sources for the MCC. This TLV bit is a future replacement to
* IWL_UCODE_TLV_API_WIFI_MCC_UPDATE. When either is set, multi-source LAR
* is supported.
* @IWL_UCODE_TLV_CAPA_BT_COEX_RRC: supports BT Coex RRC
* @IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT: supports gscan (no longer used)
* @IWL_UCODE_TLV_CAPA_SOC_LATENCY_SUPPORT: the firmware supports setting
* stabilization latency for SoCs.
* @IWL_UCODE_TLV_CAPA_STA_PM_NOTIF: firmware will send STA PM notification
* @IWL_UCODE_TLV_CAPA_TLC_OFFLOAD: firmware implements rate scaling algorithm
* @IWL_UCODE_TLV_CAPA_DYNAMIC_QUOTA: firmware implements quota related
* @IWL_UCODE_TLV_CAPA_COEX_SCHEMA_2: firmware implements Coex Schema 2
* IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD: firmware supports CSA command
* @IWL_UCODE_TLV_CAPA_ULTRA_HB_CHANNELS: firmware supports ultra high band
* (6 GHz).
* @IWL_UCODE_TLV_CAPA_CS_MODIFY: firmware supports modify action CSA command
* @IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE: extended DTS measurement
* @IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS: supports short PM timeouts
* @IWL_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT: supports bt-coex Multi-priority LUT
* @IWL_UCODE_TLV_CAPA_CSA_AND_TBTT_OFFLOAD: the firmware supports CSA
* countdown offloading. Beacon notifications are not sent to the host.
* The fw also offloads TBTT alignment.
* @IWL_UCODE_TLV_CAPA_BEACON_ANT_SELECTION: firmware will decide on what
* antenna the beacon should be transmitted
* @IWL_UCODE_TLV_CAPA_BEACON_STORING: firmware will store the latest beacon
* from AP and will send it upon d0i3 exit.
* @IWL_UCODE_TLV_CAPA_LAR_SUPPORT_V3: support LAR API V3
* @IWL_UCODE_TLV_CAPA_CT_KILL_BY_FW: firmware responsible for CT-kill
* @IWL_UCODE_TLV_CAPA_TEMP_THS_REPORT_SUPPORT: supports temperature
* thresholds reporting
* @IWL_UCODE_TLV_CAPA_CTDP_SUPPORT: supports cTDP command
* @IWL_UCODE_TLV_CAPA_USNIFFER_UNIFIED: supports usniffer enabled in
* regular image.
* @IWL_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG: support getting more shared
* memory addresses from the firmware.
* @IWL_UCODE_TLV_CAPA_LQM_SUPPORT: supports Link Quality Measurement
* @IWL_UCODE_TLV_CAPA_TX_POWER_ACK: reduced TX power API has larger
* command size (command version 4) that supports toggling ACK TX
* power reduction.
* @IWL_UCODE_TLV_CAPA_D3_DEBUG: supports debug recording during D3
* @IWL_UCODE_TLV_CAPA_MCC_UPDATE_11AX_SUPPORT: MCC response support 11ax
* capability.
* @IWL_UCODE_TLV_CAPA_CSI_REPORTING: firmware is capable of being configured
* 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_PROTECTED_TWT: Supports protection of TWT action frames
* @IWL_UCODE_TLV_CAPA_FW_RESET_HANDSHAKE: Supports the firmware handshake in
* reset flow
* @IWL_UCODE_TLV_CAPA_PASSIVE_6GHZ_SCAN: Support for passive scan on 6GHz PSC
* channels even when these are not enabled.
*
* @NUM_IWL_UCODE_TLV_CAPA: number of bits used
*/
enum iwl_ucode_tlv_capa {
/* set 0 */
IWL_UCODE_TLV_CAPA_D0I3_SUPPORT = (__force iwl_ucode_tlv_capa_t)0,
IWL_UCODE_TLV_CAPA_LAR_SUPPORT = (__force iwl_ucode_tlv_capa_t)1,
IWL_UCODE_TLV_CAPA_UMAC_SCAN = (__force iwl_ucode_tlv_capa_t)2,
IWL_UCODE_TLV_CAPA_BEAMFORMER = (__force iwl_ucode_tlv_capa_t)3,
IWL_UCODE_TLV_CAPA_TDLS_SUPPORT = (__force iwl_ucode_tlv_capa_t)6,
IWL_UCODE_TLV_CAPA_TXPOWER_INSERTION_SUPPORT = (__force iwl_ucode_tlv_capa_t)8,
IWL_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT = (__force iwl_ucode_tlv_capa_t)9,
IWL_UCODE_TLV_CAPA_WFA_TPC_REP_IE_SUPPORT = (__force iwl_ucode_tlv_capa_t)10,
IWL_UCODE_TLV_CAPA_QUIET_PERIOD_SUPPORT = (__force iwl_ucode_tlv_capa_t)11,
IWL_UCODE_TLV_CAPA_DQA_SUPPORT = (__force iwl_ucode_tlv_capa_t)12,
IWL_UCODE_TLV_CAPA_TDLS_CHANNEL_SWITCH = (__force iwl_ucode_tlv_capa_t)13,
IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG = (__force iwl_ucode_tlv_capa_t)17,
IWL_UCODE_TLV_CAPA_HOTSPOT_SUPPORT = (__force iwl_ucode_tlv_capa_t)18,
IWL_UCODE_TLV_CAPA_DC2DC_CONFIG_SUPPORT = (__force iwl_ucode_tlv_capa_t)19,
IWL_UCODE_TLV_CAPA_CSUM_SUPPORT = (__force iwl_ucode_tlv_capa_t)21,
IWL_UCODE_TLV_CAPA_RADIO_BEACON_STATS = (__force iwl_ucode_tlv_capa_t)22,
IWL_UCODE_TLV_CAPA_P2P_SCM_UAPSD = (__force iwl_ucode_tlv_capa_t)26,
IWL_UCODE_TLV_CAPA_BT_COEX_PLCR = (__force iwl_ucode_tlv_capa_t)28,
IWL_UCODE_TLV_CAPA_LAR_MULTI_MCC = (__force iwl_ucode_tlv_capa_t)29,
IWL_UCODE_TLV_CAPA_BT_COEX_RRC = (__force iwl_ucode_tlv_capa_t)30,
IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT = (__force iwl_ucode_tlv_capa_t)31,
/* set 1 */
IWL_UCODE_TLV_CAPA_SOC_LATENCY_SUPPORT = (__force iwl_ucode_tlv_capa_t)37,
IWL_UCODE_TLV_CAPA_STA_PM_NOTIF = (__force iwl_ucode_tlv_capa_t)38,
IWL_UCODE_TLV_CAPA_BINDING_CDB_SUPPORT = (__force iwl_ucode_tlv_capa_t)39,
IWL_UCODE_TLV_CAPA_CDB_SUPPORT = (__force iwl_ucode_tlv_capa_t)40,
IWL_UCODE_TLV_CAPA_D0I3_END_FIRST = (__force iwl_ucode_tlv_capa_t)41,
IWL_UCODE_TLV_CAPA_TLC_OFFLOAD = (__force iwl_ucode_tlv_capa_t)43,
IWL_UCODE_TLV_CAPA_DYNAMIC_QUOTA = (__force iwl_ucode_tlv_capa_t)44,
IWL_UCODE_TLV_CAPA_COEX_SCHEMA_2 = (__force iwl_ucode_tlv_capa_t)45,
IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD = (__force iwl_ucode_tlv_capa_t)46,
IWL_UCODE_TLV_CAPA_FTM_CALIBRATED = (__force iwl_ucode_tlv_capa_t)47,
IWL_UCODE_TLV_CAPA_ULTRA_HB_CHANNELS = (__force iwl_ucode_tlv_capa_t)48,
IWL_UCODE_TLV_CAPA_CS_MODIFY = (__force iwl_ucode_tlv_capa_t)49,
IWL_UCODE_TLV_CAPA_SET_LTR_GEN2 = (__force iwl_ucode_tlv_capa_t)50,
IWL_UCODE_TLV_CAPA_SET_PPAG = (__force iwl_ucode_tlv_capa_t)52,
IWL_UCODE_TLV_CAPA_TAS_CFG = (__force iwl_ucode_tlv_capa_t)53,
IWL_UCODE_TLV_CAPA_SESSION_PROT_CMD = (__force iwl_ucode_tlv_capa_t)54,
IWL_UCODE_TLV_CAPA_PROTECTED_TWT = (__force iwl_ucode_tlv_capa_t)56,
IWL_UCODE_TLV_CAPA_FW_RESET_HANDSHAKE = (__force iwl_ucode_tlv_capa_t)57,
IWL_UCODE_TLV_CAPA_PASSIVE_6GHZ_SCAN = (__force iwl_ucode_tlv_capa_t)58,
IWL_UCODE_TLV_CAPA_HIDDEN_6GHZ_SCAN = (__force iwl_ucode_tlv_capa_t)59,
IWL_UCODE_TLV_CAPA_BROADCAST_TWT = (__force iwl_ucode_tlv_capa_t)60,
IWL_UCODE_TLV_CAPA_COEX_HIGH_PRIO = (__force iwl_ucode_tlv_capa_t)61,
IWL_UCODE_TLV_CAPA_RFIM_SUPPORT = (__force iwl_ucode_tlv_capa_t)62,
/* set 2 */
IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE = (__force iwl_ucode_tlv_capa_t)64,
IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS = (__force iwl_ucode_tlv_capa_t)65,
IWL_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT = (__force iwl_ucode_tlv_capa_t)67,
IWL_UCODE_TLV_CAPA_MULTI_QUEUE_RX_SUPPORT = (__force iwl_ucode_tlv_capa_t)68,
IWL_UCODE_TLV_CAPA_CSA_AND_TBTT_OFFLOAD = (__force iwl_ucode_tlv_capa_t)70,
IWL_UCODE_TLV_CAPA_BEACON_ANT_SELECTION = (__force iwl_ucode_tlv_capa_t)71,
IWL_UCODE_TLV_CAPA_BEACON_STORING = (__force iwl_ucode_tlv_capa_t)72,
IWL_UCODE_TLV_CAPA_LAR_SUPPORT_V3 = (__force iwl_ucode_tlv_capa_t)73,
IWL_UCODE_TLV_CAPA_CT_KILL_BY_FW = (__force iwl_ucode_tlv_capa_t)74,
IWL_UCODE_TLV_CAPA_TEMP_THS_REPORT_SUPPORT = (__force iwl_ucode_tlv_capa_t)75,
IWL_UCODE_TLV_CAPA_CTDP_SUPPORT = (__force iwl_ucode_tlv_capa_t)76,
IWL_UCODE_TLV_CAPA_USNIFFER_UNIFIED = (__force iwl_ucode_tlv_capa_t)77,
IWL_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG = (__force iwl_ucode_tlv_capa_t)80,
IWL_UCODE_TLV_CAPA_LQM_SUPPORT = (__force iwl_ucode_tlv_capa_t)81,
IWL_UCODE_TLV_CAPA_TX_POWER_ACK = (__force iwl_ucode_tlv_capa_t)84,
IWL_UCODE_TLV_CAPA_D3_DEBUG = (__force iwl_ucode_tlv_capa_t)87,
IWL_UCODE_TLV_CAPA_LED_CMD_SUPPORT = (__force iwl_ucode_tlv_capa_t)88,
IWL_UCODE_TLV_CAPA_MCC_UPDATE_11AX_SUPPORT = (__force iwl_ucode_tlv_capa_t)89,
IWL_UCODE_TLV_CAPA_CSI_REPORTING = (__force iwl_ucode_tlv_capa_t)90,
IWL_UCODE_TLV_CAPA_DBG_SUSPEND_RESUME_CMD_SUPP = (__force iwl_ucode_tlv_capa_t)92,
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_PSC_CHAN_SUPPORT: supports PSC channels
*/
IWL_UCODE_TLV_CAPA_PSC_CHAN_SUPPORT = (__force iwl_ucode_tlv_capa_t)98,
IWL_UCODE_TLV_CAPA_BIGTK_SUPPORT = (__force iwl_ucode_tlv_capa_t)100,
IWL_UCODE_TLV_CAPA_DRAM_FRAG_SUPPORT = (__force iwl_ucode_tlv_capa_t)104,
#ifdef __CHECKER__
/* sparse says it cannot increment the previous enum member */
#define NUM_IWL_UCODE_TLV_CAPA 128
#else
NUM_IWL_UCODE_TLV_CAPA
#endif
};
/* The default calibrate table size if not specified by firmware file */
#define IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE 18
#define IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE 19
#define IWL_MAX_PHY_CALIBRATE_TBL_SIZE 253
/* The default max probe length if not specified by the firmware file */
#define IWL_DEFAULT_MAX_PROBE_LENGTH 200
/*
* For 16.0 uCode and above, there is no differentiation between sections,
* just an offset to the HW address.
*/
#define CPU1_CPU2_SEPARATOR_SECTION 0xFFFFCCCC
#define PAGING_SEPARATOR_SECTION 0xAAAABBBB
/* uCode version contains 4 values: Major/Minor/API/Serial */
#define IWL_UCODE_MAJOR(ver) (((ver) & 0xFF000000) >> 24)
#define IWL_UCODE_MINOR(ver) (((ver) & 0x00FF0000) >> 16)
#define IWL_UCODE_API(ver) (((ver) & 0x0000FF00) >> 8)
#define IWL_UCODE_SERIAL(ver) ((ver) & 0x000000FF)
/**
* struct iwl_tlv_calib_ctrl - Calibration control struct.
* Sent as part of the phy configuration command.
* @flow_trigger: bitmap for which calibrations to perform according to
* flow triggers.
* @event_trigger: bitmap for which calibrations to perform according to
* event triggers.
*/
struct iwl_tlv_calib_ctrl {
__le32 flow_trigger;
__le32 event_trigger;
} __packed;
enum iwl_fw_phy_cfg {
FW_PHY_CFG_RADIO_TYPE_POS = 0,
FW_PHY_CFG_RADIO_TYPE = 0x3 << FW_PHY_CFG_RADIO_TYPE_POS,
FW_PHY_CFG_RADIO_STEP_POS = 2,
FW_PHY_CFG_RADIO_STEP = 0x3 << FW_PHY_CFG_RADIO_STEP_POS,
FW_PHY_CFG_RADIO_DASH_POS = 4,
FW_PHY_CFG_RADIO_DASH = 0x3 << FW_PHY_CFG_RADIO_DASH_POS,
FW_PHY_CFG_TX_CHAIN_POS = 16,
FW_PHY_CFG_TX_CHAIN = 0xf << FW_PHY_CFG_TX_CHAIN_POS,
FW_PHY_CFG_RX_CHAIN_POS = 20,
FW_PHY_CFG_RX_CHAIN = 0xf << FW_PHY_CFG_RX_CHAIN_POS,
FW_PHY_CFG_CHAIN_SAD_POS = 23,
FW_PHY_CFG_CHAIN_SAD_ENABLED = 0x1 << FW_PHY_CFG_CHAIN_SAD_POS,
FW_PHY_CFG_CHAIN_SAD_ANT_A = 0x2 << FW_PHY_CFG_CHAIN_SAD_POS,
FW_PHY_CFG_CHAIN_SAD_ANT_B = 0x4 << FW_PHY_CFG_CHAIN_SAD_POS,
FW_PHY_CFG_SHARED_CLK = BIT(31),
};
#define IWL_UCODE_MAX_CS 1
/**
* struct iwl_fw_cipher_scheme - a cipher scheme supported by FW.
* @cipher: a cipher suite selector
* @flags: cipher scheme flags (currently reserved for a future use)
* @hdr_len: a size of MPDU security header
* @pn_len: a size of PN
* @pn_off: an offset of pn from the beginning of the security header
* @key_idx_off: an offset of key index byte in the security header
* @key_idx_mask: a bit mask of key_idx bits
* @key_idx_shift: bit shift needed to get key_idx
* @mic_len: mic length in bytes
* @hw_cipher: a HW cipher index used in host commands
*/
struct iwl_fw_cipher_scheme {
__le32 cipher;
u8 flags;
u8 hdr_len;
u8 pn_len;
u8 pn_off;
u8 key_idx_off;
u8 key_idx_mask;
u8 key_idx_shift;
u8 mic_len;
u8 hw_cipher;
} __packed;
enum iwl_fw_dbg_reg_operator {
CSR_ASSIGN,
CSR_SETBIT,
CSR_CLEARBIT,
PRPH_ASSIGN,
PRPH_SETBIT,
PRPH_CLEARBIT,
INDIRECT_ASSIGN,
INDIRECT_SETBIT,
INDIRECT_CLEARBIT,
PRPH_BLOCKBIT,
};
/**
* struct iwl_fw_dbg_reg_op - an operation on a register
*
* @op: &enum iwl_fw_dbg_reg_operator
* @addr: offset of the register
* @val: value
*/
struct iwl_fw_dbg_reg_op {
u8 op;
u8 reserved[3];
__le32 addr;
__le32 val;
} __packed;
/**
* enum iwl_fw_dbg_monitor_mode - available monitor recording modes
*
* @SMEM_MODE: monitor stores the data in SMEM
* @EXTERNAL_MODE: monitor stores the data in allocated DRAM
* @MARBH_MODE: monitor stores the data in MARBH buffer
* @MIPI_MODE: monitor outputs the data through the MIPI interface
*/
enum iwl_fw_dbg_monitor_mode {
SMEM_MODE = 0,
EXTERNAL_MODE = 1,
MARBH_MODE = 2,
MIPI_MODE = 3,
};
/**
* struct iwl_fw_dbg_mem_seg_tlv - configures the debug data memory segments
*
* @data_type: the memory segment type to record
* @ofs: the memory segment offset
* @len: the memory segment length, in bytes
*
* This parses IWL_UCODE_TLV_FW_MEM_SEG
*/
struct iwl_fw_dbg_mem_seg_tlv {
__le32 data_type;
__le32 ofs;
__le32 len;
} __packed;
/**
* struct iwl_fw_dbg_dest_tlv_v1 - configures the destination of the debug data
*
* @version: version of the TLV - currently 0
* @monitor_mode: &enum iwl_fw_dbg_monitor_mode
* @size_power: buffer size will be 2^(size_power + 11)
* @base_reg: addr of the base addr register (PRPH)
* @end_reg: addr of the end addr register (PRPH)
* @write_ptr_reg: the addr of the reg of the write pointer
* @wrap_count: the addr of the reg of the wrap_count
* @base_shift: shift right of the base addr reg
* @end_shift: shift right of the end addr reg
* @reg_ops: array of registers operations
*
* This parses IWL_UCODE_TLV_FW_DBG_DEST
*/
struct iwl_fw_dbg_dest_tlv_v1 {
u8 version;
u8 monitor_mode;
u8 size_power;
u8 reserved;
__le32 base_reg;
__le32 end_reg;
__le32 write_ptr_reg;
__le32 wrap_count;
u8 base_shift;
u8 end_shift;
struct iwl_fw_dbg_reg_op reg_ops[0];
} __packed;
/* Mask of the register for defining the LDBG MAC2SMEM buffer SMEM size */
#define IWL_LDBG_M2S_BUF_SIZE_MSK 0x0fff0000
/* Mask of the register for defining the LDBG MAC2SMEM SMEM base address */
#define IWL_LDBG_M2S_BUF_BA_MSK 0x00000fff
/* The smem buffer chunks are in units of 256 bits */
#define IWL_M2S_UNIT_SIZE 0x100
struct iwl_fw_dbg_dest_tlv {
u8 version;
u8 monitor_mode;
u8 size_power;
u8 reserved;
__le32 cfg_reg;
__le32 write_ptr_reg;
__le32 wrap_count;
u8 base_shift;
u8 size_shift;
struct iwl_fw_dbg_reg_op reg_ops[0];
} __packed;
struct iwl_fw_dbg_conf_hcmd {
u8 id;
u8 reserved;
__le16 len;
u8 data[0];
} __packed;
/**
* enum iwl_fw_dbg_trigger_mode - triggers functionalities
*
* @IWL_FW_DBG_TRIGGER_START: when trigger occurs re-conf the dbg mechanism
* @IWL_FW_DBG_TRIGGER_STOP: when trigger occurs pull the dbg data
* @IWL_FW_DBG_TRIGGER_MONITOR_ONLY: when trigger occurs trigger is set to
* collect only monitor data
*/
enum iwl_fw_dbg_trigger_mode {
IWL_FW_DBG_TRIGGER_START = BIT(0),
IWL_FW_DBG_TRIGGER_STOP = BIT(1),
IWL_FW_DBG_TRIGGER_MONITOR_ONLY = BIT(2),
};
/**
* enum iwl_fw_dbg_trigger_flags - the flags supported by wrt triggers
* @IWL_FW_DBG_FORCE_RESTART: force a firmware restart
*/
enum iwl_fw_dbg_trigger_flags {
IWL_FW_DBG_FORCE_RESTART = BIT(0),
};
/**
* enum iwl_fw_dbg_trigger_vif_type - define the VIF type for a trigger
* @IWL_FW_DBG_CONF_VIF_ANY: any vif type
* @IWL_FW_DBG_CONF_VIF_IBSS: IBSS mode
* @IWL_FW_DBG_CONF_VIF_STATION: BSS mode
* @IWL_FW_DBG_CONF_VIF_AP: AP mode
* @IWL_FW_DBG_CONF_VIF_P2P_CLIENT: P2P Client mode
* @IWL_FW_DBG_CONF_VIF_P2P_GO: P2P GO mode
* @IWL_FW_DBG_CONF_VIF_P2P_DEVICE: P2P device
*/
enum iwl_fw_dbg_trigger_vif_type {
IWL_FW_DBG_CONF_VIF_ANY = NL80211_IFTYPE_UNSPECIFIED,
IWL_FW_DBG_CONF_VIF_IBSS = NL80211_IFTYPE_ADHOC,
IWL_FW_DBG_CONF_VIF_STATION = NL80211_IFTYPE_STATION,
IWL_FW_DBG_CONF_VIF_AP = NL80211_IFTYPE_AP,
IWL_FW_DBG_CONF_VIF_P2P_CLIENT = NL80211_IFTYPE_P2P_CLIENT,
IWL_FW_DBG_CONF_VIF_P2P_GO = NL80211_IFTYPE_P2P_GO,
IWL_FW_DBG_CONF_VIF_P2P_DEVICE = NL80211_IFTYPE_P2P_DEVICE,
};
/**
* struct iwl_fw_dbg_trigger_tlv - a TLV that describes the trigger
* @id: &enum iwl_fw_dbg_trigger
* @vif_type: &enum iwl_fw_dbg_trigger_vif_type
* @stop_conf_ids: bitmap of configurations this trigger relates to.
* if the mode is %IWL_FW_DBG_TRIGGER_STOP, then if the bit corresponding
* to the currently running configuration is set, the data should be
* collected.
* @stop_delay: how many milliseconds to wait before collecting the data
* after the STOP trigger fires.
* @mode: &enum iwl_fw_dbg_trigger_mode - can be stop / start of both
* @start_conf_id: if mode is %IWL_FW_DBG_TRIGGER_START, this defines what
* configuration should be applied when the triggers kicks in.
* @occurrences: number of occurrences. 0 means the trigger will never fire.
* @trig_dis_ms: the time, in milliseconds, after an occurrence of this
* trigger in which another occurrence should be ignored.
* @flags: &enum iwl_fw_dbg_trigger_flags
*/
struct iwl_fw_dbg_trigger_tlv {
__le32 id;
__le32 vif_type;
__le32 stop_conf_ids;
__le32 stop_delay;
u8 mode;
u8 start_conf_id;
__le16 occurrences;
__le16 trig_dis_ms;
u8 flags;
u8 reserved[5];
u8 data[0];
} __packed;
#define FW_DBG_START_FROM_ALIVE 0
#define FW_DBG_CONF_MAX 32
#define FW_DBG_INVALID 0xff
/**
* struct iwl_fw_dbg_trigger_missed_bcon - configures trigger for missed beacons
* @stop_consec_missed_bcon: stop recording if threshold is crossed.
* @stop_consec_missed_bcon_since_rx: stop recording if threshold is crossed.
* @start_consec_missed_bcon: start recording if threshold is crossed.
* @start_consec_missed_bcon_since_rx: start recording if threshold is crossed.
* @reserved1: reserved
* @reserved2: reserved
*/
struct iwl_fw_dbg_trigger_missed_bcon {
__le32 stop_consec_missed_bcon;
__le32 stop_consec_missed_bcon_since_rx;
__le32 reserved2[2];
__le32 start_consec_missed_bcon;
__le32 start_consec_missed_bcon_since_rx;
__le32 reserved1[2];
} __packed;
/**
* struct iwl_fw_dbg_trigger_cmd - configures trigger for messages from FW.
* cmds: the list of commands to trigger the collection on
*/
struct iwl_fw_dbg_trigger_cmd {
struct cmd {
u8 cmd_id;
u8 group_id;
} __packed cmds[16];
} __packed;
/**
* iwl_fw_dbg_trigger_stats - configures trigger for statistics
* @stop_offset: the offset of the value to be monitored
* @stop_threshold: the threshold above which to collect
* @start_offset: the offset of the value to be monitored
* @start_threshold: the threshold above which to start recording
*/
struct iwl_fw_dbg_trigger_stats {
__le32 stop_offset;
__le32 stop_threshold;
__le32 start_offset;
__le32 start_threshold;
} __packed;
/**
* struct iwl_fw_dbg_trigger_low_rssi - trigger for low beacon RSSI
* @rssi: RSSI value to trigger at
*/
struct iwl_fw_dbg_trigger_low_rssi {
__le32 rssi;
} __packed;
/**
* struct iwl_fw_dbg_trigger_mlme - configures trigger for mlme events
* @stop_auth_denied: number of denied authentication to collect
* @stop_auth_timeout: number of authentication timeout to collect
* @stop_rx_deauth: number of Rx deauth before to collect
* @stop_tx_deauth: number of Tx deauth before to collect
* @stop_assoc_denied: number of denied association to collect
* @stop_assoc_timeout: number of association timeout to collect
* @stop_connection_loss: number of connection loss to collect
* @start_auth_denied: number of denied authentication to start recording
* @start_auth_timeout: number of authentication timeout to start recording
* @start_rx_deauth: number of Rx deauth to start recording
* @start_tx_deauth: number of Tx deauth to start recording
* @start_assoc_denied: number of denied association to start recording
* @start_assoc_timeout: number of association timeout to start recording
* @start_connection_loss: number of connection loss to start recording
*/
struct iwl_fw_dbg_trigger_mlme {
u8 stop_auth_denied;
u8 stop_auth_timeout;
u8 stop_rx_deauth;
u8 stop_tx_deauth;
u8 stop_assoc_denied;
u8 stop_assoc_timeout;
u8 stop_connection_loss;
u8 reserved;
u8 start_auth_denied;
u8 start_auth_timeout;
u8 start_rx_deauth;
u8 start_tx_deauth;
u8 start_assoc_denied;
u8 start_assoc_timeout;
u8 start_connection_loss;
u8 reserved2;
} __packed;
/**
* struct iwl_fw_dbg_trigger_txq_timer - configures the Tx queue's timer
* @command_queue: timeout for the command queue in ms
* @bss: timeout for the queues of a BSS (except for TDLS queues) in ms
* @softap: timeout for the queues of a softAP in ms
* @p2p_go: timeout for the queues of a P2P GO in ms
* @p2p_client: timeout for the queues of a P2P client in ms
* @p2p_device: timeout for the queues of a P2P device in ms
* @ibss: timeout for the queues of an IBSS in ms
* @tdls: timeout for the queues of a TDLS station in ms
*/
struct iwl_fw_dbg_trigger_txq_timer {
__le32 command_queue;
__le32 bss;
__le32 softap;
__le32 p2p_go;
__le32 p2p_client;
__le32 p2p_device;
__le32 ibss;
__le32 tdls;
__le32 reserved[4];
} __packed;
/**
* struct iwl_fw_dbg_trigger_time_event - configures a time event trigger
* time_Events: a list of tuples <id, action_bitmap>. The driver will issue a
* trigger each time a time event notification that relates to time event
* id with one of the actions in the bitmap is received and
* BIT(notif->status) is set in status_bitmap.
*
*/
struct iwl_fw_dbg_trigger_time_event {
struct {
__le32 id;
__le32 action_bitmap;
__le32 status_bitmap;
} __packed time_events[16];
} __packed;
/**
* struct iwl_fw_dbg_trigger_ba - configures BlockAck related trigger
* rx_ba_start: tid bitmap to configure on what tid the trigger should occur
* when an Rx BlockAck session is started.
* rx_ba_stop: tid bitmap to configure on what tid the trigger should occur
* when an Rx BlockAck session is stopped.
* tx_ba_start: tid bitmap to configure on what tid the trigger should occur
* when a Tx BlockAck session is started.
* tx_ba_stop: tid bitmap to configure on what tid the trigger should occur
* when a Tx BlockAck session is stopped.
* rx_bar: tid bitmap to configure on what tid the trigger should occur
* when a BAR is received (for a Tx BlockAck session).
* tx_bar: tid bitmap to configure on what tid the trigger should occur
* when a BAR is send (for an Rx BlocAck session).
* frame_timeout: tid bitmap to configure on what tid the trigger should occur
* when a frame times out in the reordering buffer.
*/
struct iwl_fw_dbg_trigger_ba {
__le16 rx_ba_start;
__le16 rx_ba_stop;
__le16 tx_ba_start;
__le16 tx_ba_stop;
__le16 rx_bar;
__le16 tx_bar;
__le16 frame_timeout;
} __packed;
/**
* struct iwl_fw_dbg_trigger_tdls - configures trigger for TDLS events.
* @action_bitmap: the TDLS action to trigger the collection upon
* @peer_mode: trigger on specific peer or all
* @peer: the TDLS peer to trigger the collection on
*/
struct iwl_fw_dbg_trigger_tdls {
u8 action_bitmap;
u8 peer_mode;
u8 peer[ETH_ALEN];
u8 reserved[4];
} __packed;
/**
* struct iwl_fw_dbg_trigger_tx_status - configures trigger for tx response
* status.
* @statuses: the list of statuses to trigger the collection on
*/
struct iwl_fw_dbg_trigger_tx_status {
struct tx_status {
u8 status;
u8 reserved[3];
} __packed statuses[16];
__le32 reserved[2];
} __packed;
/**
* struct iwl_fw_dbg_conf_tlv - a TLV that describes a debug configuration.
* @id: conf id
* @usniffer: should the uSniffer image be used
* @num_of_hcmds: how many HCMDs to send are present here
* @hcmd: a variable length host command to be sent to apply the configuration.
* If there is more than one HCMD to send, they will appear one after the
* other and be sent in the order that they appear in.
* This parses IWL_UCODE_TLV_FW_DBG_CONF. The user can add up-to
* %FW_DBG_CONF_MAX configuration per run.
*/
struct iwl_fw_dbg_conf_tlv {
u8 id;
u8 usniffer;
u8 reserved;
u8 num_of_hcmds;
struct iwl_fw_dbg_conf_hcmd hcmd;
} __packed;
#define IWL_FW_CMD_VER_UNKNOWN 99
/**
* struct iwl_fw_cmd_version - firmware command version entry
* @cmd: command ID
* @group: group ID
* @cmd_ver: command version
* @notif_ver: notification version
*/
struct iwl_fw_cmd_version {
u8 cmd;
u8 group;
u8 cmd_ver;
u8 notif_ver;
} __packed;
struct iwl_fw_tcm_error_addr {
__le32 addr;
}; /* FW_TLV_TCM_ERROR_INFO_ADDRS_S */
struct iwl_fw_dump_exclude {
__le32 addr, size;
};
static inline size_t _iwl_tlv_array_len(const struct iwl_ucode_tlv *tlv,
size_t fixed_size, size_t var_size)
{
size_t var_len = le32_to_cpu(tlv->length) - fixed_size;
if (WARN_ON(var_len % var_size))
return 0;
return var_len / var_size;
}
#define iwl_tlv_array_len(_tlv_ptr, _struct_ptr, _memb) \
_iwl_tlv_array_len((_tlv_ptr), sizeof(*(_struct_ptr)), \
sizeof(_struct_ptr->_memb[0]))
#endif /* __iwl_fw_file_h__ */

View File

@ -0,0 +1,90 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright(c) 2019 - 2020 Intel Corporation
*/
#include "img.h"
u8 iwl_fw_lookup_cmd_ver(const struct iwl_fw *fw, u8 grp, u8 cmd, u8 def)
{
const struct iwl_fw_cmd_version *entry;
unsigned int i;
if (!fw->ucode_capa.cmd_versions ||
!fw->ucode_capa.n_cmd_versions)
return def;
entry = fw->ucode_capa.cmd_versions;
for (i = 0; i < fw->ucode_capa.n_cmd_versions; i++, entry++) {
if (entry->group == grp && entry->cmd == cmd) {
if (entry->cmd_ver == IWL_FW_CMD_VER_UNKNOWN)
return def;
return entry->cmd_ver;
}
}
return def;
}
EXPORT_SYMBOL_GPL(iwl_fw_lookup_cmd_ver);
u8 iwl_fw_lookup_notif_ver(const struct iwl_fw *fw, u8 grp, u8 cmd, u8 def)
{
const struct iwl_fw_cmd_version *entry;
unsigned int i;
if (!fw->ucode_capa.cmd_versions ||
!fw->ucode_capa.n_cmd_versions)
return def;
entry = fw->ucode_capa.cmd_versions;
for (i = 0; i < fw->ucode_capa.n_cmd_versions; i++, entry++) {
if (entry->group == grp && entry->cmd == cmd) {
if (entry->notif_ver == IWL_FW_CMD_VER_UNKNOWN)
return def;
return entry->notif_ver;
}
}
return def;
}
EXPORT_SYMBOL_GPL(iwl_fw_lookup_notif_ver);
#define FW_SYSASSERT_CPU_MASK 0xf0000000
static const struct {
const char *name;
u8 num;
} advanced_lookup[] = {
{ "NMI_INTERRUPT_WDG", 0x34 },
{ "SYSASSERT", 0x35 },
{ "UCODE_VERSION_MISMATCH", 0x37 },
{ "BAD_COMMAND", 0x38 },
{ "BAD_COMMAND", 0x39 },
{ "NMI_INTERRUPT_DATA_ACTION_PT", 0x3C },
{ "FATAL_ERROR", 0x3D },
{ "NMI_TRM_HW_ERR", 0x46 },
{ "NMI_INTERRUPT_TRM", 0x4C },
{ "NMI_INTERRUPT_BREAK_POINT", 0x54 },
{ "NMI_INTERRUPT_WDG_RXF_FULL", 0x5C },
{ "NMI_INTERRUPT_WDG_NO_RBD_RXF_FULL", 0x64 },
{ "NMI_INTERRUPT_HOST", 0x66 },
{ "NMI_INTERRUPT_LMAC_FATAL", 0x70 },
{ "NMI_INTERRUPT_UMAC_FATAL", 0x71 },
{ "NMI_INTERRUPT_OTHER_LMAC_FATAL", 0x73 },
{ "NMI_INTERRUPT_ACTION_PT", 0x7C },
{ "NMI_INTERRUPT_UNKNOWN", 0x84 },
{ "NMI_INTERRUPT_INST_ACTION_PT", 0x86 },
{ "ADVANCED_SYSASSERT", 0 },
};
const char *iwl_fw_lookup_assert_desc(u32 num)
{
int i;
for (i = 0; i < ARRAY_SIZE(advanced_lookup) - 1; i++)
if (advanced_lookup[i].num == (num & ~FW_SYSASSERT_CPU_MASK))
return advanced_lookup[i].name;
/* No entry matches 'num', so it is the last: ADVANCED_SYSASSERT */
return advanced_lookup[i].name;
}
EXPORT_SYMBOL_GPL(iwl_fw_lookup_assert_desc);

View File

@ -0,0 +1,282 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2005-2014, 2018-2021 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016 Intel Deutschland GmbH
*/
#ifndef __iwl_fw_img_h__
#define __iwl_fw_img_h__
#include <linux/types.h>
#include "api/dbg-tlv.h"
#include "file.h"
#include "error-dump.h"
/**
* enum iwl_ucode_type
*
* The type of ucode.
*
* @IWL_UCODE_REGULAR: Normal runtime ucode
* @IWL_UCODE_INIT: Initial ucode
* @IWL_UCODE_WOWLAN: Wake on Wireless enabled ucode
* @IWL_UCODE_REGULAR_USNIFFER: Normal runtime ucode when using usniffer image
*/
enum iwl_ucode_type {
IWL_UCODE_REGULAR,
IWL_UCODE_INIT,
IWL_UCODE_WOWLAN,
IWL_UCODE_REGULAR_USNIFFER,
IWL_UCODE_TYPE_MAX,
};
/*
* enumeration of ucode section.
* This enumeration is used directly for older firmware (before 16.0).
* For new firmware, there can be up to 4 sections (see below) but the
* first one packaged into the firmware file is the DATA section and
* some debugging code accesses that.
*/
enum iwl_ucode_sec {
IWL_UCODE_SECTION_DATA,
IWL_UCODE_SECTION_INST,
};
struct iwl_ucode_capabilities {
u32 max_probe_length;
u32 n_scan_channels;
u32 standard_phy_calibration_size;
u32 flags;
u32 error_log_addr;
u32 error_log_size;
u32 num_stations;
unsigned long _api[BITS_TO_LONGS(NUM_IWL_UCODE_TLV_API)];
unsigned long _capa[BITS_TO_LONGS(NUM_IWL_UCODE_TLV_CAPA)];
const struct iwl_fw_cmd_version *cmd_versions;
u32 n_cmd_versions;
};
static inline bool
fw_has_api(const struct iwl_ucode_capabilities *capabilities,
iwl_ucode_tlv_api_t api)
{
return test_bit((__force long)api, capabilities->_api);
}
static inline bool
fw_has_capa(const struct iwl_ucode_capabilities *capabilities,
iwl_ucode_tlv_capa_t capa)
{
return test_bit((__force long)capa, capabilities->_capa);
}
/* one for each uCode image (inst/data, init/runtime/wowlan) */
struct fw_desc {
const void *data; /* vmalloc'ed data */
u32 len; /* size in bytes */
u32 offset; /* offset in the device */
};
struct fw_img {
struct fw_desc *sec;
int num_sec;
bool is_dual_cpus;
u32 paging_mem_size;
};
/*
* Block paging calculations
*/
#define PAGE_2_EXP_SIZE 12 /* 4K == 2^12 */
#define FW_PAGING_SIZE BIT(PAGE_2_EXP_SIZE) /* page size is 4KB */
#define PAGE_PER_GROUP_2_EXP_SIZE 3
/* 8 pages per group */
#define NUM_OF_PAGE_PER_GROUP BIT(PAGE_PER_GROUP_2_EXP_SIZE)
/* don't change, support only 32KB size */
#define PAGING_BLOCK_SIZE (NUM_OF_PAGE_PER_GROUP * FW_PAGING_SIZE)
/* 32K == 2^15 */
#define BLOCK_2_EXP_SIZE (PAGE_2_EXP_SIZE + PAGE_PER_GROUP_2_EXP_SIZE)
/*
* Image paging calculations
*/
#define BLOCK_PER_IMAGE_2_EXP_SIZE 5
/* 2^5 == 32 blocks per image */
#define NUM_OF_BLOCK_PER_IMAGE BIT(BLOCK_PER_IMAGE_2_EXP_SIZE)
/* maximum image size 1024KB */
#define MAX_PAGING_IMAGE_SIZE (NUM_OF_BLOCK_PER_IMAGE * PAGING_BLOCK_SIZE)
/* Virtual address signature */
#define PAGING_ADDR_SIG 0xAA000000
#define PAGING_CMD_IS_SECURED BIT(9)
#define PAGING_CMD_IS_ENABLED BIT(8)
#define PAGING_CMD_NUM_OF_PAGES_IN_LAST_GRP_POS 0
#define PAGING_TLV_SECURE_MASK 1
/* FW MSB Mask for regions/cache_control */
#define FW_ADDR_CACHE_CONTROL 0xC0000000UL
/**
* struct iwl_fw_paging
* @fw_paging_phys: page phy pointer
* @fw_paging_block: pointer to the allocated block
* @fw_paging_size: page size
* @fw_offs: offset in the device
*/
struct iwl_fw_paging {
dma_addr_t fw_paging_phys;
struct page *fw_paging_block;
u32 fw_paging_size;
u32 fw_offs;
};
/**
* struct iwl_fw_cscheme_list - a cipher scheme list
* @size: a number of entries
* @cs: cipher scheme entries
*/
struct iwl_fw_cscheme_list {
u8 size;
struct iwl_fw_cipher_scheme cs[];
} __packed;
/**
* enum iwl_fw_type - iwlwifi firmware type
* @IWL_FW_DVM: DVM firmware
* @IWL_FW_MVM: MVM firmware
*/
enum iwl_fw_type {
IWL_FW_DVM,
IWL_FW_MVM,
};
/**
* struct iwl_fw_dbg - debug data
*
* @dest_tlv: points to debug destination TLV (typically SRAM or DRAM)
* @n_dest_reg: num of reg_ops in dest_tlv
* @conf_tlv: array of pointers to configuration HCMDs
* @trigger_tlv: array of pointers to triggers TLVs
* @trigger_tlv_len: lengths of the @dbg_trigger_tlv entries
* @mem_tlv: Runtime addresses to dump
* @n_mem_tlv: number of runtime addresses
* @dump_mask: bitmask of dump regions
*/
struct iwl_fw_dbg {
struct iwl_fw_dbg_dest_tlv_v1 *dest_tlv;
u8 n_dest_reg;
struct iwl_fw_dbg_conf_tlv *conf_tlv[FW_DBG_CONF_MAX];
struct iwl_fw_dbg_trigger_tlv *trigger_tlv[FW_DBG_TRIGGER_MAX];
size_t trigger_tlv_len[FW_DBG_TRIGGER_MAX];
struct iwl_fw_dbg_mem_seg_tlv *mem_tlv;
size_t n_mem_tlv;
u32 dump_mask;
};
struct iwl_dump_exclude {
u32 addr, size;
};
/**
* struct iwl_fw - variables associated with the firmware
*
* @ucode_ver: ucode version from the ucode file
* @fw_version: firmware version string
* @img: ucode image like ucode_rt, ucode_init, ucode_wowlan.
* @iml_len: length of the image loader image
* @iml: image loader fw image
* @ucode_capa: capabilities parsed from the ucode file.
* @enhance_sensitivity_table: device can do enhanced sensitivity.
* @init_evtlog_ptr: event log offset for init ucode.
* @init_evtlog_size: event log size for init ucode.
* @init_errlog_ptr: error log offfset for init ucode.
* @inst_evtlog_ptr: event log offset for runtime ucode.
* @inst_evtlog_size: event log size for runtime ucode.
* @inst_errlog_ptr: error log offfset for runtime ucode.
* @type: firmware type (&enum iwl_fw_type)
* @cipher_scheme: optional external cipher scheme.
* @human_readable: human readable version
* we get the ALIVE from the uCode
* @phy_integration_ver: PHY integration version string
* @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
*/
struct iwl_fw {
u32 ucode_ver;
char fw_version[64];
/* ucode images */
struct fw_img img[IWL_UCODE_TYPE_MAX];
size_t iml_len;
u8 *iml;
struct iwl_ucode_capabilities ucode_capa;
bool enhance_sensitivity_table;
u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr;
u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr;
struct iwl_tlv_calib_ctrl default_calib[IWL_UCODE_TYPE_MAX];
u32 phy_config;
u8 valid_tx_ant;
u8 valid_rx_ant;
enum iwl_fw_type type;
struct iwl_fw_cipher_scheme cs[IWL_UCODE_MAX_CS];
u8 human_readable[FW_VER_HUMAN_READABLE_SZ];
struct iwl_fw_dbg dbg;
u8 *phy_integration_ver;
u32 phy_integration_ver_len;
struct iwl_dump_exclude dump_excl[2], dump_excl_wowlan[2];
};
static inline const char *get_fw_dbg_mode_string(int mode)
{
switch (mode) {
case SMEM_MODE:
return "SMEM";
case EXTERNAL_MODE:
return "EXTERNAL_DRAM";
case MARBH_MODE:
return "MARBH";
case MIPI_MODE:
return "MIPI";
default:
return "UNKNOWN";
}
}
static inline bool
iwl_fw_dbg_conf_usniffer(const struct iwl_fw *fw, u8 id)
{
const struct iwl_fw_dbg_conf_tlv *conf_tlv = fw->dbg.conf_tlv[id];
if (!conf_tlv)
return false;
return conf_tlv->usniffer;
}
static inline const struct fw_img *
iwl_get_ucode_image(const struct iwl_fw *fw, enum iwl_ucode_type ucode_type)
{
if (ucode_type >= IWL_UCODE_TYPE_MAX)
return NULL;
return &fw->img[ucode_type];
}
u8 iwl_fw_lookup_cmd_ver(const struct iwl_fw *fw, u8 grp, u8 cmd, u8 def);
u8 iwl_fw_lookup_notif_ver(const struct iwl_fw *fw, u8 grp, u8 cmd, u8 def);
const char *iwl_fw_lookup_assert_desc(u32 num);
#endif /* __iwl_fw_img_h__ */

View File

@ -0,0 +1,160 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2017 Intel Deutschland GmbH
* Copyright (C) 2019-2021 Intel Corporation
*/
#include "iwl-drv.h"
#include "runtime.h"
#include "dbg.h"
#include "debugfs.h"
#include "fw/api/soc.h"
#include "fw/api/commands.h"
#include "fw/api/rx.h"
#include "fw/api/datapath.h"
void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans,
const struct iwl_fw *fw,
const struct iwl_fw_runtime_ops *ops, void *ops_ctx,
const struct iwl_dump_sanitize_ops *sanitize_ops,
void *sanitize_ctx,
struct dentry *dbgfs_dir)
{
int i;
memset(fwrt, 0, sizeof(*fwrt));
fwrt->trans = trans;
fwrt->fw = fw;
fwrt->dev = trans->dev;
fwrt->dump.conf = FW_DBG_INVALID;
fwrt->ops = ops;
fwrt->sanitize_ops = sanitize_ops;
fwrt->sanitize_ctx = sanitize_ctx;
fwrt->ops_ctx = ops_ctx;
for (i = 0; i < IWL_FW_RUNTIME_DUMP_WK_NUM; i++) {
fwrt->dump.wks[i].idx = i;
INIT_DELAYED_WORK(&fwrt->dump.wks[i].wk, iwl_fw_error_dump_wk);
}
iwl_fwrt_dbgfs_register(fwrt, dbgfs_dir);
}
IWL_EXPORT_SYMBOL(iwl_fw_runtime_init);
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_EXPORT_SYMBOL(iwl_fw_runtime_suspend);
void iwl_fw_runtime_resume(struct iwl_fw_runtime *fwrt)
{
iwl_dbg_tlv_time_point(fwrt, IWL_FW_INI_TIME_POINT_HOST_D3_END, NULL);
iwl_fw_resume_timestamp(fwrt);
}
IWL_EXPORT_SYMBOL(iwl_fw_runtime_resume);
/* set device type and latency */
int iwl_set_soc_latency(struct iwl_fw_runtime *fwrt)
{
struct iwl_soc_configuration_cmd cmd = {};
struct iwl_host_cmd hcmd = {
.id = iwl_cmd_id(SOC_CONFIGURATION_CMD, SYSTEM_GROUP, 0),
.data[0] = &cmd,
.len[0] = sizeof(cmd),
};
int ret;
/*
* In VER_1 of this command, the discrete value is considered
* an integer; In VER_2, it's a bitmask. Since we have only 2
* 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)
cmd.flags = cpu_to_le32(SOC_CONFIG_CMD_FLAGS_DISCRETE);
BUILD_BUG_ON(IWL_CFG_TRANS_LTR_DELAY_NONE !=
SOC_FLAGS_LTR_APPLY_DELAY_NONE);
BUILD_BUG_ON(IWL_CFG_TRANS_LTR_DELAY_200US !=
SOC_FLAGS_LTR_APPLY_DELAY_200);
BUILD_BUG_ON(IWL_CFG_TRANS_LTR_DELAY_2500US !=
SOC_FLAGS_LTR_APPLY_DELAY_2500);
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,
SOC_FLAGS_LTR_APPLY_DELAY_MASK);
if (iwl_fw_lookup_cmd_ver(fwrt->fw, IWL_ALWAYS_LONG_GROUP,
SCAN_REQ_UMAC,
IWL_FW_CMD_VER_UNKNOWN) >= 2 &&
fwrt->trans->trans_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);
ret = iwl_trans_send_cmd(fwrt->trans, &hcmd);
if (ret)
IWL_ERR(fwrt, "Failed to set soc latency: %d\n", ret);
return ret;
}
IWL_EXPORT_SYMBOL(iwl_set_soc_latency);
int iwl_configure_rxq(struct iwl_fw_runtime *fwrt)
{
int i, num_queues, size, ret;
struct iwl_rfh_queue_config *cmd;
struct iwl_host_cmd hcmd = {
.id = WIDE_ID(DATA_PATH_GROUP, RFH_QUEUE_CONFIG_CMD),
.dataflags[0] = IWL_HCMD_DFL_NOCOPY,
};
/*
* 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)
return 0;
if (fwrt->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_22000)
return 0;
/* skip the default queue */
num_queues = fwrt->trans->num_rx_queues - 1;
size = struct_size(cmd, data, num_queues);
cmd = kzalloc(size, GFP_KERNEL);
if (!cmd)
return -ENOMEM;
cmd->num_queues = num_queues;
for (i = 0; i < num_queues; i++) {
struct iwl_trans_rxq_dma_data data;
cmd->data[i].q_num = i + 1;
iwl_trans_get_rxq_dma_data(fwrt->trans, i + 1, &data);
cmd->data[i].fr_bd_cb = cpu_to_le64(data.fr_bd_cb);
cmd->data[i].urbd_stts_wrptr =
cpu_to_le64(data.urbd_stts_wrptr);
cmd->data[i].ur_bd_cb = cpu_to_le64(data.ur_bd_cb);
cmd->data[i].fr_bd_wid = cpu_to_le32(data.fr_bd_wid);
}
hcmd.data[0] = cmd;
hcmd.len[0] = size;
ret = iwl_trans_send_cmd(fwrt->trans, &hcmd);
kfree(cmd);
if (ret)
IWL_ERR(fwrt, "Failed to configure RX queues: %d\n", ret);
return ret;
}
IWL_EXPORT_SYMBOL(iwl_configure_rxq);

View File

@ -0,0 +1,135 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2005-2014, 2021 Intel Corporation
* Copyright (C) 2015-2017 Intel Deutschland GmbH
*/
#include <linux/sched.h>
#include <linux/export.h>
#include "iwl-drv.h"
#include "notif-wait.h"
void iwl_notification_wait_init(struct iwl_notif_wait_data *notif_wait)
{
spin_lock_init(&notif_wait->notif_wait_lock);
INIT_LIST_HEAD(&notif_wait->notif_waits);
init_waitqueue_head(&notif_wait->notif_waitq);
}
IWL_EXPORT_SYMBOL(iwl_notification_wait_init);
bool iwl_notification_wait(struct iwl_notif_wait_data *notif_wait,
struct iwl_rx_packet *pkt)
{
bool triggered = false;
if (!list_empty(&notif_wait->notif_waits)) {
struct iwl_notification_wait *w;
spin_lock_bh(&notif_wait->notif_wait_lock);
list_for_each_entry(w, &notif_wait->notif_waits, list) {
int i;
bool found = false;
/*
* If it already finished (triggered) or has been
* aborted then don't evaluate it again to avoid races,
* Otherwise the function could be called again even
* though it returned true before
*/
if (w->triggered || w->aborted)
continue;
for (i = 0; i < w->n_cmds; i++) {
u16 rec_id = WIDE_ID(pkt->hdr.group_id,
pkt->hdr.cmd);
if (w->cmds[i] == rec_id ||
(!iwl_cmd_groupid(w->cmds[i]) &&
DEF_ID(w->cmds[i]) == rec_id)) {
found = true;
break;
}
}
if (!found)
continue;
if (!w->fn || w->fn(notif_wait, pkt, w->fn_data)) {
w->triggered = true;
triggered = true;
}
}
spin_unlock_bh(&notif_wait->notif_wait_lock);
}
return triggered;
}
IWL_EXPORT_SYMBOL(iwl_notification_wait);
void iwl_abort_notification_waits(struct iwl_notif_wait_data *notif_wait)
{
struct iwl_notification_wait *wait_entry;
spin_lock_bh(&notif_wait->notif_wait_lock);
list_for_each_entry(wait_entry, &notif_wait->notif_waits, list)
wait_entry->aborted = true;
spin_unlock_bh(&notif_wait->notif_wait_lock);
wake_up_all(&notif_wait->notif_waitq);
}
IWL_EXPORT_SYMBOL(iwl_abort_notification_waits);
void
iwl_init_notification_wait(struct iwl_notif_wait_data *notif_wait,
struct iwl_notification_wait *wait_entry,
const u16 *cmds, int n_cmds,
bool (*fn)(struct iwl_notif_wait_data *notif_wait,
struct iwl_rx_packet *pkt, void *data),
void *fn_data)
{
if (WARN_ON(n_cmds > MAX_NOTIF_CMDS))
n_cmds = MAX_NOTIF_CMDS;
wait_entry->fn = fn;
wait_entry->fn_data = fn_data;
wait_entry->n_cmds = n_cmds;
memcpy(wait_entry->cmds, cmds, n_cmds * sizeof(u16));
wait_entry->triggered = false;
wait_entry->aborted = false;
spin_lock_bh(&notif_wait->notif_wait_lock);
list_add(&wait_entry->list, &notif_wait->notif_waits);
spin_unlock_bh(&notif_wait->notif_wait_lock);
}
IWL_EXPORT_SYMBOL(iwl_init_notification_wait);
void iwl_remove_notification(struct iwl_notif_wait_data *notif_wait,
struct iwl_notification_wait *wait_entry)
{
spin_lock_bh(&notif_wait->notif_wait_lock);
list_del(&wait_entry->list);
spin_unlock_bh(&notif_wait->notif_wait_lock);
}
IWL_EXPORT_SYMBOL(iwl_remove_notification);
int iwl_wait_notification(struct iwl_notif_wait_data *notif_wait,
struct iwl_notification_wait *wait_entry,
unsigned long timeout)
{
int ret;
ret = wait_event_timeout(notif_wait->notif_waitq,
wait_entry->triggered || wait_entry->aborted,
timeout);
iwl_remove_notification(notif_wait, wait_entry);
if (wait_entry->aborted)
return -EIO;
/* return value is always >= 0 */
if (ret <= 0)
return -ETIMEDOUT;
return 0;
}
IWL_EXPORT_SYMBOL(iwl_wait_notification);

View File

@ -0,0 +1,96 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2005-2014 Intel Corporation
* Copyright (C) 2015-2017 Intel Deutschland GmbH
*/
#ifndef __iwl_notif_wait_h__
#define __iwl_notif_wait_h__
#include <linux/wait.h>
#include "iwl-trans.h"
struct iwl_notif_wait_data {
struct list_head notif_waits;
spinlock_t notif_wait_lock;
wait_queue_head_t notif_waitq;
};
#define MAX_NOTIF_CMDS 5
/**
* struct iwl_notification_wait - notification wait entry
* @list: list head for global list
* @fn: Function called with the notification. If the function
* returns true, the wait is over, if it returns false then
* the waiter stays blocked. If no function is given, any
* of the listed commands will unblock the waiter.
* @cmds: command IDs
* @n_cmds: number of command IDs
* @triggered: waiter should be woken up
* @aborted: wait was aborted
*
* This structure is not used directly, to wait for a
* notification declare it on the stack, and call
* iwl_init_notification_wait() with appropriate
* parameters. Then do whatever will cause the ucode
* to notify the driver, and to wait for that then
* call iwl_wait_notification().
*
* Each notification is one-shot. If at some point we
* need to support multi-shot notifications (which
* can't be allocated on the stack) we need to modify
* the code for them.
*/
struct iwl_notification_wait {
struct list_head list;
bool (*fn)(struct iwl_notif_wait_data *notif_data,
struct iwl_rx_packet *pkt, void *data);
void *fn_data;
u16 cmds[MAX_NOTIF_CMDS];
u8 n_cmds;
bool triggered, aborted;
};
/* caller functions */
void iwl_notification_wait_init(struct iwl_notif_wait_data *notif_data);
bool iwl_notification_wait(struct iwl_notif_wait_data *notif_data,
struct iwl_rx_packet *pkt);
void iwl_abort_notification_waits(struct iwl_notif_wait_data *notif_data);
static inline void
iwl_notification_notify(struct iwl_notif_wait_data *notif_data)
{
wake_up_all(&notif_data->notif_waitq);
}
static inline void
iwl_notification_wait_notify(struct iwl_notif_wait_data *notif_data,
struct iwl_rx_packet *pkt)
{
if (iwl_notification_wait(notif_data, pkt))
iwl_notification_notify(notif_data);
}
/* user functions */
void __acquires(wait_entry)
iwl_init_notification_wait(struct iwl_notif_wait_data *notif_data,
struct iwl_notification_wait *wait_entry,
const u16 *cmds, int n_cmds,
bool (*fn)(struct iwl_notif_wait_data *notif_data,
struct iwl_rx_packet *pkt, void *data),
void *fn_data);
int __must_check __releases(wait_entry)
iwl_wait_notification(struct iwl_notif_wait_data *notif_data,
struct iwl_notification_wait *wait_entry,
unsigned long timeout);
void __releases(wait_entry)
iwl_remove_notification(struct iwl_notif_wait_data *notif_data,
struct iwl_notification_wait *wait_entry);
#endif /* __iwl_notif_wait_h__ */

View File

@ -0,0 +1,296 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2012-2014, 2018-2019, 2021 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
#include "iwl-drv.h"
#include "runtime.h"
#include "fw/api/commands.h"
void iwl_free_fw_paging(struct iwl_fw_runtime *fwrt)
{
int i;
if (!fwrt->fw_paging_db[0].fw_paging_block)
return;
for (i = 0; i < NUM_OF_FW_PAGING_BLOCKS; i++) {
struct iwl_fw_paging *paging = &fwrt->fw_paging_db[i];
if (!paging->fw_paging_block) {
IWL_DEBUG_FW(fwrt,
"Paging: block %d already freed, continue to next page\n",
i);
continue;
}
dma_unmap_page(fwrt->trans->dev, paging->fw_paging_phys,
paging->fw_paging_size, DMA_BIDIRECTIONAL);
__free_pages(paging->fw_paging_block,
get_order(paging->fw_paging_size));
paging->fw_paging_block = NULL;
}
memset(fwrt->fw_paging_db, 0, sizeof(fwrt->fw_paging_db));
}
IWL_EXPORT_SYMBOL(iwl_free_fw_paging);
static int iwl_alloc_fw_paging_mem(struct iwl_fw_runtime *fwrt,
const struct fw_img *image)
{
struct page *block;
dma_addr_t phys = 0;
int blk_idx, order, num_of_pages, size;
if (fwrt->fw_paging_db[0].fw_paging_block)
return 0;
/* ensure BLOCK_2_EXP_SIZE is power of 2 of PAGING_BLOCK_SIZE */
BUILD_BUG_ON(BIT(BLOCK_2_EXP_SIZE) != PAGING_BLOCK_SIZE);
num_of_pages = image->paging_mem_size / FW_PAGING_SIZE;
fwrt->num_of_paging_blk =
DIV_ROUND_UP(num_of_pages, NUM_OF_PAGE_PER_GROUP);
fwrt->num_of_pages_in_last_blk =
num_of_pages -
NUM_OF_PAGE_PER_GROUP * (fwrt->num_of_paging_blk - 1);
IWL_DEBUG_FW(fwrt,
"Paging: allocating mem for %d paging blocks, each block holds 8 pages, last block holds %d pages\n",
fwrt->num_of_paging_blk,
fwrt->num_of_pages_in_last_blk);
/*
* Allocate CSS and paging blocks in dram.
*/
for (blk_idx = 0; blk_idx < fwrt->num_of_paging_blk + 1; blk_idx++) {
/* For CSS allocate 4KB, for others PAGING_BLOCK_SIZE (32K) */
size = blk_idx ? PAGING_BLOCK_SIZE : FW_PAGING_SIZE;
order = get_order(size);
block = alloc_pages(GFP_KERNEL, order);
if (!block) {
/* free all the previous pages since we failed */
iwl_free_fw_paging(fwrt);
return -ENOMEM;
}
fwrt->fw_paging_db[blk_idx].fw_paging_block = block;
fwrt->fw_paging_db[blk_idx].fw_paging_size = size;
phys = dma_map_page(fwrt->trans->dev, block, 0,
PAGE_SIZE << order,
DMA_BIDIRECTIONAL);
if (dma_mapping_error(fwrt->trans->dev, phys)) {
/*
* free the previous pages and the current one
* since we failed to map_page.
*/
iwl_free_fw_paging(fwrt);
return -ENOMEM;
}
fwrt->fw_paging_db[blk_idx].fw_paging_phys = phys;
if (!blk_idx)
IWL_DEBUG_FW(fwrt,
"Paging: allocated 4K(CSS) bytes (order %d) for firmware paging.\n",
order);
else
IWL_DEBUG_FW(fwrt,
"Paging: allocated 32K bytes (order %d) for firmware paging.\n",
order);
}
return 0;
}
static int iwl_fill_paging_mem(struct iwl_fw_runtime *fwrt,
const struct fw_img *image)
{
int sec_idx, idx, ret;
u32 offset = 0;
/*
* find where is the paging image start point:
* if CPU2 exist and it's in paging format, then the image looks like:
* CPU1 sections (2 or more)
* CPU1_CPU2_SEPARATOR_SECTION delimiter - separate between CPU1 to CPU2
* CPU2 sections (not paged)
* PAGING_SEPARATOR_SECTION delimiter - separate between CPU2
* non paged to CPU2 paging sec
* CPU2 paging CSS
* CPU2 paging image (including instruction and data)
*/
for (sec_idx = 0; sec_idx < image->num_sec; sec_idx++) {
if (image->sec[sec_idx].offset == PAGING_SEPARATOR_SECTION) {
sec_idx++;
break;
}
}
/*
* If paging is enabled there should be at least 2 more sections left
* (one for CSS and one for Paging data)
*/
if (sec_idx >= image->num_sec - 1) {
IWL_ERR(fwrt, "Paging: Missing CSS and/or paging sections\n");
ret = -EINVAL;
goto err;
}
/* copy the CSS block to the dram */
IWL_DEBUG_FW(fwrt, "Paging: load paging CSS to FW, sec = %d\n",
sec_idx);
if (image->sec[sec_idx].len > fwrt->fw_paging_db[0].fw_paging_size) {
IWL_ERR(fwrt, "CSS block is larger than paging size\n");
ret = -EINVAL;
goto err;
}
memcpy(page_address(fwrt->fw_paging_db[0].fw_paging_block),
image->sec[sec_idx].data,
image->sec[sec_idx].len);
fwrt->fw_paging_db[0].fw_offs = image->sec[sec_idx].offset;
dma_sync_single_for_device(fwrt->trans->dev,
fwrt->fw_paging_db[0].fw_paging_phys,
fwrt->fw_paging_db[0].fw_paging_size,
DMA_BIDIRECTIONAL);
IWL_DEBUG_FW(fwrt,
"Paging: copied %d CSS bytes to first block\n",
fwrt->fw_paging_db[0].fw_paging_size);
sec_idx++;
/*
* Copy the paging blocks to the dram. The loop index starts
* from 1 since the CSS block (index 0) was already copied to
* dram. We use num_of_paging_blk + 1 to account for that.
*/
for (idx = 1; idx < fwrt->num_of_paging_blk + 1; idx++) {
struct iwl_fw_paging *block = &fwrt->fw_paging_db[idx];
int remaining = image->sec[sec_idx].len - offset;
int len = block->fw_paging_size;
/*
* For the last block, we copy all that is remaining,
* for all other blocks, we copy fw_paging_size at a
* time. */
if (idx == fwrt->num_of_paging_blk) {
len = remaining;
if (remaining !=
fwrt->num_of_pages_in_last_blk * FW_PAGING_SIZE) {
IWL_ERR(fwrt,
"Paging: last block contains more data than expected %d\n",
remaining);
ret = -EINVAL;
goto err;
}
} else if (block->fw_paging_size > remaining) {
IWL_ERR(fwrt,
"Paging: not enough data in other in block %d (%d)\n",
idx, remaining);
ret = -EINVAL;
goto err;
}
memcpy(page_address(block->fw_paging_block),
(const u8 *)image->sec[sec_idx].data + offset, len);
block->fw_offs = image->sec[sec_idx].offset + offset;
dma_sync_single_for_device(fwrt->trans->dev,
block->fw_paging_phys,
block->fw_paging_size,
DMA_BIDIRECTIONAL);
IWL_DEBUG_FW(fwrt,
"Paging: copied %d paging bytes to block %d\n",
len, idx);
offset += block->fw_paging_size;
}
return 0;
err:
iwl_free_fw_paging(fwrt);
return ret;
}
static int iwl_save_fw_paging(struct iwl_fw_runtime *fwrt,
const struct fw_img *fw)
{
int ret;
ret = iwl_alloc_fw_paging_mem(fwrt, fw);
if (ret)
return ret;
return iwl_fill_paging_mem(fwrt, fw);
}
/* send paging cmd to FW in case CPU2 has paging image */
static int iwl_send_paging_cmd(struct iwl_fw_runtime *fwrt,
const struct fw_img *fw)
{
struct iwl_fw_paging_cmd paging_cmd = {
.flags = cpu_to_le32(PAGING_CMD_IS_SECURED |
PAGING_CMD_IS_ENABLED |
(fwrt->num_of_pages_in_last_blk <<
PAGING_CMD_NUM_OF_PAGES_IN_LAST_GRP_POS)),
.block_size = cpu_to_le32(BLOCK_2_EXP_SIZE),
.block_num = cpu_to_le32(fwrt->num_of_paging_blk),
};
struct iwl_host_cmd hcmd = {
.id = iwl_cmd_id(FW_PAGING_BLOCK_CMD, IWL_ALWAYS_LONG_GROUP, 0),
.len = { sizeof(paging_cmd), },
.data = { &paging_cmd, },
};
int blk_idx;
/* loop for 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;
addr = addr >> PAGE_2_EXP_SIZE;
phy_addr = cpu_to_le32(addr);
paging_cmd.device_phy_addr[blk_idx] = phy_addr;
}
return iwl_trans_send_cmd(fwrt->trans, &hcmd);
}
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)
return 0;
/*
* Configure and operate fw paging mechanism.
* The driver configures the paging flow only once.
* The CPU2 paging image is included in the IWL_UCODE_INIT image.
*/
if (!fw->paging_mem_size)
return 0;
ret = iwl_save_fw_paging(fwrt, fw);
if (ret) {
IWL_ERR(fwrt, "failed to save the FW paging image\n");
return ret;
}
ret = iwl_send_paging_cmd(fwrt, fw);
if (ret) {
IWL_ERR(fwrt, "failed to send the paging cmd\n");
iwl_free_fw_paging(fwrt);
return ret;
}
return 0;
}
IWL_EXPORT_SYMBOL(iwl_init_paging);

View File

@ -0,0 +1,356 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright(c) 2020-2021 Intel Corporation
*/
#include "iwl-drv.h"
#include "pnvm.h"
#include "iwl-prph.h"
#include "iwl-io.h"
#include "fw/api/commands.h"
#include "fw/api/nvm-reg.h"
#include "fw/api/alive.h"
#include "fw/uefi.h"
struct iwl_pnvm_section {
__le32 offset;
const u8 data[];
} __packed;
static bool iwl_pnvm_complete_fn(struct iwl_notif_wait_data *notif_wait,
struct iwl_rx_packet *pkt, void *data)
{
struct iwl_trans *trans = (struct iwl_trans *)data;
struct iwl_pnvm_init_complete_ntfy *pnvm_ntf = (void *)pkt->data;
IWL_DEBUG_FW(trans,
"PNVM complete notification received with status 0x%0x\n",
le32_to_cpu(pnvm_ntf->status));
return true;
}
static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data,
size_t len)
{
const struct iwl_ucode_tlv *tlv;
u32 sha1 = 0;
u16 mac_type = 0, rf_id = 0;
u8 *pnvm_data = NULL, *tmp;
bool hw_match = false;
u32 size = 0;
int ret;
IWL_DEBUG_FW(trans, "Handling PNVM section\n");
while (len >= sizeof(*tlv)) {
u32 tlv_len, tlv_type;
len -= sizeof(*tlv);
tlv = (const void *)data;
tlv_len = le32_to_cpu(tlv->length);
tlv_type = le32_to_cpu(tlv->type);
if (len < tlv_len) {
IWL_ERR(trans, "invalid TLV len: %zd/%u\n",
len, tlv_len);
ret = -EINVAL;
goto out;
}
data += sizeof(*tlv);
switch (tlv_type) {
case IWL_UCODE_TLV_PNVM_VERSION:
if (tlv_len < sizeof(__le32)) {
IWL_DEBUG_FW(trans,
"Invalid size for IWL_UCODE_TLV_PNVM_VERSION (expected %zd, got %d)\n",
sizeof(__le32), tlv_len);
break;
}
sha1 = le32_to_cpup((const __le32 *)data);
IWL_DEBUG_FW(trans,
"Got IWL_UCODE_TLV_PNVM_VERSION %0x\n",
sha1);
break;
case IWL_UCODE_TLV_HW_TYPE:
if (tlv_len < 2 * sizeof(__le16)) {
IWL_DEBUG_FW(trans,
"Invalid size for IWL_UCODE_TLV_HW_TYPE (expected %zd, got %d)\n",
2 * sizeof(__le16), tlv_len);
break;
}
if (hw_match)
break;
mac_type = le16_to_cpup((const __le16 *)data);
rf_id = le16_to_cpup((const __le16 *)(data + sizeof(__le16)));
IWL_DEBUG_FW(trans,
"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))
hw_match = true;
break;
case IWL_UCODE_TLV_SEC_RT: {
const struct iwl_pnvm_section *section = (const void *)data;
u32 data_len = tlv_len - sizeof(*section);
IWL_DEBUG_FW(trans,
"Got IWL_UCODE_TLV_SEC_RT len %d\n",
tlv_len);
/* TODO: remove, this is a deprecated separator */
if (le32_to_cpup((const __le32 *)data) == 0xddddeeee) {
IWL_DEBUG_FW(trans, "Ignoring separator.\n");
break;
}
IWL_DEBUG_FW(trans, "Adding data (size %d)\n",
data_len);
tmp = krealloc(pnvm_data, size + data_len, GFP_KERNEL);
if (!tmp) {
IWL_DEBUG_FW(trans,
"Couldn't allocate (more) pnvm_data\n");
ret = -ENOMEM;
goto out;
}
pnvm_data = tmp;
memcpy(pnvm_data + size, section->data, data_len);
size += data_len;
break;
}
case IWL_UCODE_TLV_PNVM_SKU:
IWL_DEBUG_FW(trans,
"New PNVM section started, stop parsing.\n");
goto done;
default:
IWL_DEBUG_FW(trans, "Found TLV 0x%0x, len %d\n",
tlv_type, tlv_len);
break;
}
len -= ALIGN(tlv_len, 4);
data += ALIGN(tlv_len, 4);
}
done:
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));
ret = -ENOENT;
goto out;
}
if (!size) {
IWL_DEBUG_FW(trans, "Empty PNVM, skipping.\n");
ret = -ENOENT;
goto out;
}
IWL_INFO(trans, "loaded PNVM version %08x\n", sha1);
ret = iwl_trans_set_pnvm(trans, pnvm_data, size);
out:
kfree(pnvm_data);
return ret;
}
static int iwl_pnvm_parse(struct iwl_trans *trans, const u8 *data,
size_t len)
{
const struct iwl_ucode_tlv *tlv;
IWL_DEBUG_FW(trans, "Parsing PNVM file\n");
while (len >= sizeof(*tlv)) {
u32 tlv_len, tlv_type;
len -= sizeof(*tlv);
tlv = (const void *)data;
tlv_len = le32_to_cpu(tlv->length);
tlv_type = le32_to_cpu(tlv->type);
if (len < tlv_len) {
IWL_ERR(trans, "invalid TLV len: %zd/%u\n",
len, tlv_len);
return -EINVAL;
}
if (tlv_type == IWL_UCODE_TLV_PNVM_SKU) {
const struct iwl_sku_id *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]));
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])) {
int ret;
ret = iwl_pnvm_handle_section(trans, data, len);
if (!ret)
return 0;
} else {
IWL_DEBUG_FW(trans, "SKU ID didn't match!\n");
}
} else {
data += sizeof(*tlv) + ALIGN(tlv_len, 4);
len -= ALIGN(tlv_len, 4);
}
}
return -ENOENT;
}
static int iwl_pnvm_get_from_fs(struct iwl_trans *trans, u8 **data, size_t *len)
{
const struct firmware *pnvm;
char pnvm_name[MAX_PNVM_NAME];
size_t new_len;
int ret;
iwl_pnvm_get_fs_name(trans, pnvm_name, sizeof(pnvm_name));
ret = firmware_request_nowarn(&pnvm, pnvm_name, trans->dev);
if (ret) {
IWL_DEBUG_FW(trans, "PNVM file %s not found %d\n",
pnvm_name, ret);
return ret;
}
new_len = pnvm->size;
*data = kmemdup(pnvm->data, pnvm->size, GFP_KERNEL);
release_firmware(pnvm);
if (!*data)
return -ENOMEM;
*len = new_len;
return 0;
}
int iwl_pnvm_load(struct iwl_trans *trans,
struct iwl_notif_wait_data *notif_wait)
{
u8 *data;
size_t len;
struct pnvm_sku_package *package;
struct iwl_notification_wait pnvm_wait;
static const u16 ntf_cmds[] = { WIDE_ID(REGULATORY_AND_NVM_GROUP,
PNVM_INIT_COMPLETE_NTFY) };
int ret;
/* if the SKU_ID is empty, there's nothing to do */
if (!trans->sku_id[0] && !trans->sku_id[1] && !trans->sku_id[2])
return 0;
/*
* If we already loaded (or tried to load) it before, we just
* need to set it again.
*/
if (trans->pnvm_loaded) {
ret = iwl_trans_set_pnvm(trans, NULL, 0);
if (ret)
return ret;
goto skip_parse;
}
/* First attempt to get the PNVM from BIOS */
package = iwl_uefi_get_pnvm(trans, &len);
if (!IS_ERR_OR_NULL(package)) {
if (len >= sizeof(*package)) {
/* we need only the data */
len -= sizeof(*package);
data = kmemdup(package->data, len, GFP_KERNEL);
} else {
data = NULL;
}
/* free package regardless of whether kmemdup succeeded */
kfree(package);
if (data)
goto parse;
}
/* If it's not available, try from the filesystem */
ret = iwl_pnvm_get_from_fs(trans, &data, &len);
if (ret) {
/*
* Pretend we've loaded it - at least we've tried and
* couldn't load it at all, so there's no point in
* trying again over and over.
*/
trans->pnvm_loaded = true;
goto skip_parse;
}
parse:
iwl_pnvm_parse(trans, data, len);
kfree(data);
skip_parse:
data = NULL;
/* now try to get the reduce power table, if not loaded yet */
if (!trans->reduce_power_loaded) {
data = iwl_uefi_get_reduced_power(trans, &len);
if (IS_ERR_OR_NULL(data)) {
/*
* Pretend we've loaded it - at least we've tried and
* couldn't load it at all, so there's no point in
* trying again over and over.
*/
trans->reduce_power_loaded = true;
goto skip_reduce_power;
}
}
ret = iwl_trans_set_reduce_power(trans, data, len);
if (ret)
IWL_DEBUG_FW(trans,
"Failed to set reduce power table %d\n",
ret);
kfree(data);
skip_reduce_power:
iwl_init_notification_wait(notif_wait, &pnvm_wait,
ntf_cmds, ARRAY_SIZE(ntf_cmds),
iwl_pnvm_complete_fn, trans);
/* kick the doorbell */
iwl_write_umac_prph(trans, UREG_DOORBELL_TO_ISR6,
UREG_DOORBELL_TO_ISR6_PNVM);
return iwl_wait_notification(notif_wait, &pnvm_wait,
MVM_UCODE_PNVM_TIMEOUT);
}
IWL_EXPORT_SYMBOL(iwl_pnvm_load);

View File

@ -0,0 +1,38 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/******************************************************************************
*
* Copyright(c) 2020-2021 Intel Corporation
*
*****************************************************************************/
#ifndef __IWL_PNVM_H__
#define __IWL_PNVM_H__
#include "fw/notif-wait.h"
#define MVM_UCODE_PNVM_TIMEOUT (HZ / 4)
#define MAX_PNVM_NAME 64
int iwl_pnvm_load(struct iwl_trans *trans,
struct iwl_notif_wait_data *notif_wait);
static inline
void iwl_pnvm_get_fs_name(struct iwl_trans *trans,
u8 *pnvm_name, size_t max_len)
{
int pre_len;
/*
* The prefix unfortunately includes a hyphen at the end, so
* don't add the dot here...
*/
snprintf(pnvm_name, max_len, "%spnvm", trans->cfg->fw_name_pre);
/* ...but replace the hyphen with the dot here. */
pre_len = strlen(trans->cfg->fw_name_pre);
if (pre_len < max_len && pre_len > 0)
pnvm_name[pre_len - 1] = '.';
}
#endif /* __IWL_PNVM_H__ */

View File

@ -0,0 +1,252 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2021 Intel Corporation
*/
#include <net/mac80211.h>
#include "fw/api/rs.h"
#include "iwl-drv.h"
#include "iwl-config.h"
#define IWL_DECLARE_RATE_INFO(r) \
[IWL_RATE_##r##M_INDEX] = IWL_RATE_##r##M_PLCP
/*
* Translate from fw_rate_index (IWL_RATE_XXM_INDEX) to PLCP
* */
static const u8 fw_rate_idx_to_plcp[IWL_RATE_COUNT] = {
IWL_DECLARE_RATE_INFO(1),
IWL_DECLARE_RATE_INFO(2),
IWL_DECLARE_RATE_INFO(5),
IWL_DECLARE_RATE_INFO(11),
IWL_DECLARE_RATE_INFO(6),
IWL_DECLARE_RATE_INFO(9),
IWL_DECLARE_RATE_INFO(12),
IWL_DECLARE_RATE_INFO(18),
IWL_DECLARE_RATE_INFO(24),
IWL_DECLARE_RATE_INFO(36),
IWL_DECLARE_RATE_INFO(48),
IWL_DECLARE_RATE_INFO(54),
};
/* mbps, mcs */
static const struct iwl_rate_mcs_info rate_mcs[IWL_RATE_COUNT] = {
{ "1", "BPSK DSSS"},
{ "2", "QPSK DSSS"},
{"5.5", "BPSK CCK"},
{ "11", "QPSK CCK"},
{ "6", "BPSK 1/2"},
{ "9", "BPSK 1/2"},
{ "12", "QPSK 1/2"},
{ "18", "QPSK 3/4"},
{ "24", "16QAM 1/2"},
{ "36", "16QAM 3/4"},
{ "48", "64QAM 2/3"},
{ "54", "64QAM 3/4"},
{ "60", "64QAM 5/6"},
};
static const char * const ant_name[] = {
[ANT_NONE] = "None",
[ANT_A] = "A",
[ANT_B] = "B",
[ANT_AB] = "AB",
};
static const char * const pretty_bw[] = {
"20Mhz",
"40Mhz",
"80Mhz",
"160 Mhz",
"320Mhz",
};
u8 iwl_fw_rate_idx_to_plcp(int idx)
{
return fw_rate_idx_to_plcp[idx];
}
IWL_EXPORT_SYMBOL(iwl_fw_rate_idx_to_plcp);
const struct iwl_rate_mcs_info *iwl_rate_mcs(int idx)
{
return &rate_mcs[idx];
}
IWL_EXPORT_SYMBOL(iwl_rate_mcs);
const char *iwl_rs_pretty_ant(u8 ant)
{
if (ant >= ARRAY_SIZE(ant_name))
return "UNKNOWN";
return ant_name[ant];
}
IWL_EXPORT_SYMBOL(iwl_rs_pretty_ant);
const char *iwl_rs_pretty_bw(int bw)
{
if (bw >= ARRAY_SIZE(pretty_bw))
return "unknown bw";
return pretty_bw[bw];
}
IWL_EXPORT_SYMBOL(iwl_rs_pretty_bw);
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_VHT_MCS_MIMO2_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);
WARN_ON(legacy_rate < 0);
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);
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 -1;
}
int rs_pretty_print_rate(char *buf, int bufsz, const u32 rate)
{
char *type;
u8 mcs = 0, nss = 0;
u8 ant = (rate & RATE_MCS_ANT_AB_MSK) >> RATE_MCS_ANT_POS;
u32 bw = (rate & RATE_MCS_CHAN_WIDTH_MSK) >>
RATE_MCS_CHAN_WIDTH_POS;
u32 format = rate & RATE_MCS_MOD_TYPE_MSK;
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;
return scnprintf(buf, bufsz, "Legacy | ANT: %s Rate: %s Mbps",
iwl_rs_pretty_ant(ant),
index == IWL_RATE_INVALID ? "BAD" :
iwl_rate_mcs(index)->mbps);
}
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
type = "Unknown"; /* shouldn't happen */
mcs = format == RATE_MCS_HT_MSK ?
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 ?
iwl_he_is_sgi(rate) :
rate & RATE_MCS_SGI_MSK;
return scnprintf(buf, bufsz,
"0x%x: %s | ANT: %s BW: %s MCS: %d NSS: %d %s%s%s%s%s",
rate, type, iwl_rs_pretty_ant(ant), iwl_rs_pretty_bw(bw), mcs, nss,
(sgi) ? "SGI " : "NGI ",
(rate & RATE_MCS_STBC_MSK) ? "STBC " : "",
(rate & RATE_MCS_LDPC_MSK) ? "LDPC " : "",
(rate & RATE_HE_DUAL_CARRIER_MODE_MSK) ? "DCM " : "",
(rate & RATE_MCS_BF_MSK) ? "BF " : "");
}
IWL_EXPORT_SYMBOL(rs_pretty_print_rate);
bool iwl_he_is_sgi(u32 rate_n_flags)
{
u32 type = rate_n_flags & RATE_MCS_HE_TYPE_MSK;
u32 ltf_gi = rate_n_flags & RATE_MCS_HE_GI_LTF_MSK;
if (type == RATE_MCS_HE_TYPE_SU ||
type == RATE_MCS_HE_TYPE_EXT_SU)
return ltf_gi == RATE_MCS_HE_SU_4_LTF_08_GI;
return false;
}
IWL_EXPORT_SYMBOL(iwl_he_is_sgi);

View File

@ -0,0 +1,200 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2017 Intel Deutschland GmbH
* Copyright (C) 2018-2020 Intel Corporation
*/
#ifndef __iwl_fw_runtime_h__
#define __iwl_fw_runtime_h__
#include "iwl-config.h"
#include "iwl-trans.h"
#include "img.h"
#include "fw/api/debug.h"
#include "fw/api/paging.h"
#include "fw/api/power.h"
#include "iwl-eeprom-parse.h"
#include "fw/acpi.h"
struct iwl_fw_runtime_ops {
int (*dump_start)(void *ctx);
void (*dump_end)(void *ctx);
bool (*fw_running)(void *ctx);
int (*send_hcmd)(void *ctx, struct iwl_host_cmd *host_cmd);
bool (*d3_debug_enable)(void *ctx);
};
#define MAX_NUM_LMAC 2
struct iwl_fwrt_shared_mem_cfg {
int num_lmacs;
int num_txfifo_entries;
struct {
u32 txfifo_size[TX_FIFO_MAX_NUM];
u32 rxfifo1_size;
} lmac[MAX_NUM_LMAC];
u32 rxfifo2_size;
u32 rxfifo2_control_size;
u32 internal_txfifo_addr;
u32 internal_txfifo_size[TX_FIFO_INTERNAL_MAX_NUM];
};
#define IWL_FW_RUNTIME_DUMP_WK_NUM 5
/**
* struct iwl_fwrt_dump_data - dump data
* @trig: trigger the worker was scheduled upon
* @fw_pkt: packet received from FW
*/
struct iwl_fwrt_dump_data {
union {
struct {
struct iwl_fw_ini_trigger_tlv *trig;
struct iwl_rx_packet *fw_pkt;
};
struct {
const struct iwl_fw_dump_desc *desc;
bool monitor_only;
};
};
};
/**
* struct iwl_fwrt_wk_data - dump worker data struct
* @idx: index of the worker
* @wk: worker
*/
struct iwl_fwrt_wk_data {
u8 idx;
struct delayed_work wk;
struct iwl_fwrt_dump_data dump_data;
};
/**
* struct iwl_txf_iter_data - Tx fifo iterator data struct
* @fifo: fifo number
* @lmac: lmac number
* @fifo_size: fifo size
* @internal_txf: non zero if fifo is internal Tx fifo
*/
struct iwl_txf_iter_data {
int fifo;
int lmac;
u32 fifo_size;
u8 internal_txf;
};
/**
* struct iwl_fw_runtime - runtime data for firmware
* @fw: firmware image
* @cfg: NIC configuration
* @dev: device pointer
* @ops: user ops
* @ops_ctx: user ops context
* @fw_paging_db: paging database
* @num_of_paging_blk: number of paging blocks
* @num_of_pages_in_last_blk: number of pages in the last block
* @smem_cfg: saved firmware SMEM configuration
* @cur_fw_img: current firmware image, must be maintained by
* the driver by calling &iwl_fw_set_current_image()
* @dump: debug dump data
*/
struct iwl_fw_runtime {
struct iwl_trans *trans;
const struct iwl_fw *fw;
struct device *dev;
const struct iwl_fw_runtime_ops *ops;
void *ops_ctx;
const struct iwl_dump_sanitize_ops *sanitize_ops;
void *sanitize_ctx;
/* Paging */
struct iwl_fw_paging fw_paging_db[NUM_OF_FW_PAGING_BLOCKS];
u16 num_of_paging_blk;
u16 num_of_pages_in_last_blk;
enum iwl_ucode_type cur_fw_img;
/* memory configuration */
struct iwl_fwrt_shared_mem_cfg smem_cfg;
/* debug */
struct {
struct iwl_fwrt_wk_data wks[IWL_FW_RUNTIME_DUMP_WK_NUM];
unsigned long active_wks;
u8 conf;
/* ts of the beginning of a non-collect fw dbg data period */
unsigned long non_collect_ts_start[IWL_FW_INI_TIME_POINT_NUM];
u32 *d3_debug_data;
u32 lmac_err_id[MAX_NUM_LMAC];
u32 umac_err_id;
struct iwl_txf_iter_data txf_iter_data;
struct {
u8 type;
u8 subtype;
u32 lmac_major;
u32 lmac_minor;
u32 umac_major;
u32 umac_minor;
} fw_ver;
} dump;
#ifdef CONFIG_IWLWIFI_DEBUGFS
struct {
struct delayed_work wk;
u32 delay;
u64 seq;
} timestamp;
bool tpc_enabled;
#endif /* CONFIG_IWLWIFI_DEBUGFS */
#ifdef CONFIG_ACPI
struct iwl_sar_profile sar_profiles[ACPI_SAR_PROFILE_NUM];
u8 sar_chain_a_profile;
u8 sar_chain_b_profile;
struct iwl_geo_profile geo_profiles[ACPI_NUM_GEO_PROFILES_REV3];
u32 geo_rev;
union iwl_ppag_table_cmd ppag_table;
u32 ppag_ver;
#endif
};
void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans,
const struct iwl_fw *fw,
const struct iwl_fw_runtime_ops *ops, void *ops_ctx,
const struct iwl_dump_sanitize_ops *sanitize_ops,
void *sanitize_ctx,
struct dentry *dbgfs_dir);
static inline void iwl_fw_runtime_free(struct iwl_fw_runtime *fwrt)
{
int i;
kfree(fwrt->dump.d3_debug_data);
fwrt->dump.d3_debug_data = NULL;
iwl_dbg_tlv_del_timers(fwrt->trans);
for (i = 0; i < IWL_FW_RUNTIME_DUMP_WK_NUM; i++)
cancel_delayed_work_sync(&fwrt->dump.wks[i].wk);
}
void iwl_fw_runtime_suspend(struct iwl_fw_runtime *fwrt);
void iwl_fw_runtime_resume(struct iwl_fw_runtime *fwrt);
static inline void iwl_fw_set_current_image(struct iwl_fw_runtime *fwrt,
enum iwl_ucode_type cur_fw_img)
{
fwrt->cur_fw_img = cur_fw_img;
}
int iwl_init_paging(struct iwl_fw_runtime *fwrt, enum iwl_ucode_type type);
void iwl_free_fw_paging(struct iwl_fw_runtime *fwrt);
void iwl_get_shared_mem_conf(struct iwl_fw_runtime *fwrt);
int iwl_set_soc_latency(struct iwl_fw_runtime *fwrt);
int iwl_configure_rxq(struct iwl_fw_runtime *fwrt);
#endif /* __iwl_fw_runtime_h__ */

View File

@ -0,0 +1,114 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2012-2014, 2018-2020 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
#include "iwl-drv.h"
#include "runtime.h"
#include "fw/api/commands.h"
static void iwl_parse_shared_mem_22000(struct iwl_fw_runtime *fwrt,
struct iwl_rx_packet *pkt)
{
struct iwl_shared_mem_cfg *mem_cfg = (void *)pkt->data;
int i, lmac;
int lmac_num = le32_to_cpu(mem_cfg->lmac_num);
u8 api_ver = iwl_fw_lookup_notif_ver(fwrt->fw, SYSTEM_GROUP,
SHARED_MEM_CFG_CMD, 0);
if (WARN_ON(lmac_num > ARRAY_SIZE(mem_cfg->lmac_smem)))
return;
fwrt->smem_cfg.num_lmacs = lmac_num;
fwrt->smem_cfg.num_txfifo_entries =
ARRAY_SIZE(mem_cfg->lmac_smem[0].txfifo_size);
fwrt->smem_cfg.rxfifo2_size = le32_to_cpu(mem_cfg->rxfifo2_size);
if (api_ver >= 4 &&
!WARN_ON_ONCE(iwl_rx_packet_payload_len(pkt) < sizeof(*mem_cfg))) {
fwrt->smem_cfg.rxfifo2_control_size =
le32_to_cpu(mem_cfg->rxfifo2_control_size);
}
for (lmac = 0; lmac < lmac_num; lmac++) {
struct iwl_shared_mem_lmac_cfg *lmac_cfg =
&mem_cfg->lmac_smem[lmac];
for (i = 0; i < ARRAY_SIZE(lmac_cfg->txfifo_size); i++)
fwrt->smem_cfg.lmac[lmac].txfifo_size[i] =
le32_to_cpu(lmac_cfg->txfifo_size[i]);
fwrt->smem_cfg.lmac[lmac].rxfifo1_size =
le32_to_cpu(lmac_cfg->rxfifo1_size);
}
}
static void iwl_parse_shared_mem(struct iwl_fw_runtime *fwrt,
struct iwl_rx_packet *pkt)
{
struct iwl_shared_mem_cfg_v2 *mem_cfg = (void *)pkt->data;
int i;
fwrt->smem_cfg.num_lmacs = 1;
fwrt->smem_cfg.num_txfifo_entries = ARRAY_SIZE(mem_cfg->txfifo_size);
for (i = 0; i < ARRAY_SIZE(mem_cfg->txfifo_size); i++)
fwrt->smem_cfg.lmac[0].txfifo_size[i] =
le32_to_cpu(mem_cfg->txfifo_size[i]);
fwrt->smem_cfg.lmac[0].rxfifo1_size =
le32_to_cpu(mem_cfg->rxfifo_size[0]);
fwrt->smem_cfg.rxfifo2_size = le32_to_cpu(mem_cfg->rxfifo_size[1]);
/* new API has more data, from rxfifo_addr field and on */
if (fw_has_capa(&fwrt->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG)) {
BUILD_BUG_ON(sizeof(fwrt->smem_cfg.internal_txfifo_size) !=
sizeof(mem_cfg->internal_txfifo_size));
fwrt->smem_cfg.internal_txfifo_addr =
le32_to_cpu(mem_cfg->internal_txfifo_addr);
for (i = 0;
i < ARRAY_SIZE(fwrt->smem_cfg.internal_txfifo_size);
i++)
fwrt->smem_cfg.internal_txfifo_size[i] =
le32_to_cpu(mem_cfg->internal_txfifo_size[i]);
}
}
void iwl_get_shared_mem_conf(struct iwl_fw_runtime *fwrt)
{
struct iwl_host_cmd cmd = {
.flags = CMD_WANT_SKB,
.data = { NULL, },
.len = { 0, },
};
struct iwl_rx_packet *pkt;
int ret;
if (fw_has_capa(&fwrt->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG))
cmd.id = iwl_cmd_id(SHARED_MEM_CFG_CMD, SYSTEM_GROUP, 0);
else
cmd.id = SHARED_MEM_CFG;
ret = iwl_trans_send_cmd(fwrt->trans, &cmd);
if (ret) {
WARN(ret != -ERFKILL,
"Could not send the SMEM command: %d\n", ret);
return;
}
pkt = cmd.resp_pkt;
if (fwrt->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000)
iwl_parse_shared_mem_22000(fwrt, pkt);
else
iwl_parse_shared_mem(fwrt, pkt);
IWL_DEBUG_INFO(fwrt, "SHARED MEM CFG: got memory offsets/sizes\n");
iwl_free_resp(&cmd);
}
IWL_EXPORT_SYMBOL(iwl_get_shared_mem_conf);

View File

@ -0,0 +1,262 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright(c) 2021 Intel Corporation
*/
#include "iwl-drv.h"
#include "pnvm.h"
#include "iwl-prph.h"
#include "iwl-io.h"
#include "fw/uefi.h"
#include "fw/api/alive.h"
#include <linux/efi.h>
#define IWL_EFI_VAR_GUID EFI_GUID(0x92daaf2f, 0xc02b, 0x455b, \
0xb2, 0xec, 0xf5, 0xa3, \
0x59, 0x4f, 0x4a, 0xea)
void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len)
{
struct efivar_entry *pnvm_efivar;
void *data;
unsigned long package_size;
int err;
*len = 0;
pnvm_efivar = kzalloc(sizeof(*pnvm_efivar), GFP_KERNEL);
if (!pnvm_efivar)
return ERR_PTR(-ENOMEM);
memcpy(&pnvm_efivar->var.VariableName, IWL_UEFI_OEM_PNVM_NAME,
sizeof(IWL_UEFI_OEM_PNVM_NAME));
pnvm_efivar->var.VendorGuid = IWL_EFI_VAR_GUID;
/*
* TODO: we hardcode a maximum length here, because reading
* from the UEFI is not working. To implement this properly,
* we have to call efivar_entry_size().
*/
package_size = IWL_HARDCODED_PNVM_SIZE;
data = kmalloc(package_size, GFP_KERNEL);
if (!data) {
data = ERR_PTR(-ENOMEM);
goto out;
}
err = efivar_entry_get(pnvm_efivar, NULL, &package_size, data);
if (err) {
IWL_DEBUG_FW(trans,
"PNVM UEFI variable not found %d (len %lu)\n",
err, package_size);
kfree(data);
data = ERR_PTR(err);
goto out;
}
IWL_DEBUG_FW(trans, "Read PNVM from UEFI with size %lu\n", package_size);
*len = package_size;
out:
kfree(pnvm_efivar);
return data;
}
static void *iwl_uefi_reduce_power_section(struct iwl_trans *trans,
const u8 *data, size_t len)
{
struct iwl_ucode_tlv *tlv;
u8 *reduce_power_data = NULL, *tmp;
u32 size = 0;
IWL_DEBUG_FW(trans, "Handling REDUCE_POWER section\n");
while (len >= sizeof(*tlv)) {
u32 tlv_len, tlv_type;
len -= sizeof(*tlv);
tlv = (void *)data;
tlv_len = le32_to_cpu(tlv->length);
tlv_type = le32_to_cpu(tlv->type);
if (len < tlv_len) {
IWL_ERR(trans, "invalid TLV len: %zd/%u\n",
len, tlv_len);
reduce_power_data = ERR_PTR(-EINVAL);
goto out;
}
data += sizeof(*tlv);
switch (tlv_type) {
case IWL_UCODE_TLV_MEM_DESC: {
IWL_DEBUG_FW(trans,
"Got IWL_UCODE_TLV_MEM_DESC len %d\n",
tlv_len);
IWL_DEBUG_FW(trans, "Adding data (size %d)\n", tlv_len);
tmp = krealloc(reduce_power_data, size + tlv_len, GFP_KERNEL);
if (!tmp) {
IWL_DEBUG_FW(trans,
"Couldn't allocate (more) reduce_power_data\n");
reduce_power_data = ERR_PTR(-ENOMEM);
goto out;
}
reduce_power_data = tmp;
memcpy(reduce_power_data + size, data, tlv_len);
size += tlv_len;
break;
}
case IWL_UCODE_TLV_PNVM_SKU:
IWL_DEBUG_FW(trans,
"New REDUCE_POWER section started, stop parsing.\n");
goto done;
default:
IWL_DEBUG_FW(trans, "Found TLV 0x%0x, len %d\n",
tlv_type, tlv_len);
break;
}
len -= ALIGN(tlv_len, 4);
data += ALIGN(tlv_len, 4);
}
done:
if (!size) {
IWL_DEBUG_FW(trans, "Empty REDUCE_POWER, skipping.\n");
reduce_power_data = ERR_PTR(-ENOENT);
goto out;
}
IWL_INFO(trans, "loaded REDUCE_POWER\n");
out:
return reduce_power_data;
}
static void *iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
const u8 *data, size_t len)
{
struct iwl_ucode_tlv *tlv;
void *sec_data;
IWL_DEBUG_FW(trans, "Parsing REDUCE_POWER data\n");
while (len >= sizeof(*tlv)) {
u32 tlv_len, tlv_type;
len -= sizeof(*tlv);
tlv = (void *)data;
tlv_len = le32_to_cpu(tlv->length);
tlv_type = le32_to_cpu(tlv->type);
if (len < tlv_len) {
IWL_ERR(trans, "invalid TLV len: %zd/%u\n",
len, tlv_len);
return ERR_PTR(-EINVAL);
}
if (tlv_type == IWL_UCODE_TLV_PNVM_SKU) {
struct iwl_sku_id *sku_id =
(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]));
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])) {
sec_data = iwl_uefi_reduce_power_section(trans,
data,
len);
if (!IS_ERR(sec_data))
return sec_data;
} else {
IWL_DEBUG_FW(trans, "SKU ID didn't match!\n");
}
} else {
data += sizeof(*tlv) + ALIGN(tlv_len, 4);
len -= ALIGN(tlv_len, 4);
}
}
return ERR_PTR(-ENOENT);
}
void *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len)
{
struct efivar_entry *reduce_power_efivar;
struct pnvm_sku_package *package;
void *data = NULL;
unsigned long package_size;
int err;
*len = 0;
reduce_power_efivar = kzalloc(sizeof(*reduce_power_efivar), GFP_KERNEL);
if (!reduce_power_efivar)
return ERR_PTR(-ENOMEM);
memcpy(&reduce_power_efivar->var.VariableName, IWL_UEFI_REDUCED_POWER_NAME,
sizeof(IWL_UEFI_REDUCED_POWER_NAME));
reduce_power_efivar->var.VendorGuid = IWL_EFI_VAR_GUID;
/*
* TODO: we hardcode a maximum length here, because reading
* from the UEFI is not working. To implement this properly,
* we have to call efivar_entry_size().
*/
package_size = IWL_HARDCODED_REDUCE_POWER_SIZE;
package = kmalloc(package_size, GFP_KERNEL);
if (!package) {
package = ERR_PTR(-ENOMEM);
goto out;
}
err = efivar_entry_get(reduce_power_efivar, NULL, &package_size, package);
if (err) {
IWL_DEBUG_FW(trans,
"Reduced Power UEFI variable not found %d (len %lu)\n",
err, package_size);
kfree(package);
data = ERR_PTR(err);
goto out;
}
IWL_DEBUG_FW(trans, "Read reduced power from UEFI with size %lu\n",
package_size);
*len = package_size;
IWL_DEBUG_FW(trans, "rev %d, total_size %d, n_skus %d\n",
package->rev, package->total_size, package->n_skus);
data = iwl_uefi_reduce_power_parse(trans, package->data,
*len - sizeof(*package));
kfree(package);
out:
kfree(reduce_power_efivar);
return data;
}

View File

@ -0,0 +1,45 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright(c) 2021 Intel Corporation
*/
#ifndef __iwl_fw_uefi__
#define __iwl_fw_uefi__
#define IWL_UEFI_OEM_PNVM_NAME L"UefiCnvWlanOemSignedPnvm"
#define IWL_UEFI_REDUCED_POWER_NAME L"UefiCnvWlanReducedPower"
/*
* TODO: we have these hardcoded values that the caller must pass,
* because reading from the UEFI is not working. To implement this
* properly, we have to change iwl_pnvm_get_from_uefi() to call
* efivar_entry_size() and return the value to the caller instead.
*/
#define IWL_HARDCODED_PNVM_SIZE 4096
#define IWL_HARDCODED_REDUCE_POWER_SIZE 32768
struct pnvm_sku_package {
u8 rev;
u32 total_size;
u8 n_skus;
u32 reserved[2];
u8 data[];
} __packed;
#ifdef CONFIG_EFI
void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len);
void *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len);
#else /* CONFIG_EFI */
static inline
void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len)
{
return ERR_PTR(-EOPNOTSUPP);
}
static inline
void *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len)
{
return ERR_PTR(-EOPNOTSUPP);
}
#endif /* CONFIG_EFI */
#endif /* __iwl_fw_uefi__ */

View File

@ -0,0 +1,59 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2005-2014 Intel Corporation
*/
/*
* Please use this file (iwl-agn-hw.h) only for hardware-related definitions.
*/
#ifndef __iwl_agn_hw_h__
#define __iwl_agn_hw_h__
#define IWLAGN_RTC_INST_LOWER_BOUND (0x000000)
#define IWLAGN_RTC_INST_UPPER_BOUND (0x020000)
#define IWLAGN_RTC_DATA_LOWER_BOUND (0x800000)
#define IWLAGN_RTC_DATA_UPPER_BOUND (0x80C000)
#define IWLAGN_RTC_INST_SIZE (IWLAGN_RTC_INST_UPPER_BOUND - \
IWLAGN_RTC_INST_LOWER_BOUND)
#define IWLAGN_RTC_DATA_SIZE (IWLAGN_RTC_DATA_UPPER_BOUND - \
IWLAGN_RTC_DATA_LOWER_BOUND)
#define IWL60_RTC_INST_LOWER_BOUND (0x000000)
#define IWL60_RTC_INST_UPPER_BOUND (0x040000)
#define IWL60_RTC_DATA_LOWER_BOUND (0x800000)
#define IWL60_RTC_DATA_UPPER_BOUND (0x814000)
#define IWL60_RTC_INST_SIZE \
(IWL60_RTC_INST_UPPER_BOUND - IWL60_RTC_INST_LOWER_BOUND)
#define IWL60_RTC_DATA_SIZE \
(IWL60_RTC_DATA_UPPER_BOUND - IWL60_RTC_DATA_LOWER_BOUND)
/* RSSI to dBm */
#define IWLAGN_RSSI_OFFSET 44
#define IWLAGN_DEFAULT_TX_RETRY 15
#define IWLAGN_MGMT_DFAULT_RETRY_LIMIT 3
#define IWLAGN_RTS_DFAULT_RETRY_LIMIT 60
#define IWLAGN_BAR_DFAULT_RETRY_LIMIT 60
#define IWLAGN_LOW_RETRY_LIMIT 7
/* Limit range of txpower output target to be between these values */
#define IWLAGN_TX_POWER_TARGET_POWER_MIN (0) /* 0 dBm: 1 milliwatt */
#define IWLAGN_TX_POWER_TARGET_POWER_MAX (16) /* 16 dBm */
/* EEPROM */
#define IWLAGN_EEPROM_IMG_SIZE 2048
/* high blocks contain PAPD data */
#define OTP_HIGH_IMAGE_SIZE_6x00 (6 * 512 * sizeof(u16)) /* 6 KB */
#define OTP_HIGH_IMAGE_SIZE_1000 (0x200 * sizeof(u16)) /* 1024 bytes */
#define OTP_MAX_LL_ITEMS_1000 (3) /* OTP blocks for 1000 */
#define OTP_MAX_LL_ITEMS_6x00 (4) /* OTP blocks for 6x00 */
#define OTP_MAX_LL_ITEMS_6x50 (7) /* OTP blocks for 6x50 */
#define OTP_MAX_LL_ITEMS_2x00 (4) /* OTP blocks for 2x00 */
#define IWLAGN_NUM_QUEUES 20
#endif /* __iwl_agn_hw_h__ */

View File

@ -0,0 +1,639 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2005-2014, 2018-2021 Intel Corporation
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
#ifndef __IWL_CONFIG_H__
#define __IWL_CONFIG_H__
#include <linux/types.h>
#include <linux/netdevice.h>
#include <linux/ieee80211.h>
#include <linux/nl80211.h>
#include "iwl-csr.h"
enum iwl_device_family {
IWL_DEVICE_FAMILY_UNDEFINED,
IWL_DEVICE_FAMILY_1000,
IWL_DEVICE_FAMILY_100,
IWL_DEVICE_FAMILY_2000,
IWL_DEVICE_FAMILY_2030,
IWL_DEVICE_FAMILY_105,
IWL_DEVICE_FAMILY_135,
IWL_DEVICE_FAMILY_5000,
IWL_DEVICE_FAMILY_5150,
IWL_DEVICE_FAMILY_6000,
IWL_DEVICE_FAMILY_6000i,
IWL_DEVICE_FAMILY_6005,
IWL_DEVICE_FAMILY_6030,
IWL_DEVICE_FAMILY_6050,
IWL_DEVICE_FAMILY_6150,
IWL_DEVICE_FAMILY_7000,
IWL_DEVICE_FAMILY_8000,
IWL_DEVICE_FAMILY_9000,
IWL_DEVICE_FAMILY_22000,
IWL_DEVICE_FAMILY_AX210,
IWL_DEVICE_FAMILY_BZ,
};
/*
* LED mode
* IWL_LED_DEFAULT: use device default
* IWL_LED_RF_STATE: turn LED on/off based on RF state
* LED ON = RF ON
* LED OFF = RF OFF
* IWL_LED_BLINK: adjust led blink rate based on blink table
* IWL_LED_DISABLE: led disabled
*/
enum iwl_led_mode {
IWL_LED_DEFAULT,
IWL_LED_RF_STATE,
IWL_LED_BLINK,
IWL_LED_DISABLE,
};
/**
* enum iwl_nvm_type - nvm formats
* @IWL_NVM: the regular format
* @IWL_NVM_EXT: extended NVM format
* @IWL_NVM_SDP: NVM format used by 3168 series
*/
enum iwl_nvm_type {
IWL_NVM,
IWL_NVM_EXT,
IWL_NVM_SDP,
};
/*
* This is the threshold value of plcp error rate per 100mSecs. It is
* used to set and check for the validity of plcp_delta.
*/
#define IWL_MAX_PLCP_ERR_THRESHOLD_MIN 1
#define IWL_MAX_PLCP_ERR_THRESHOLD_DEF 50
#define IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF 100
#define IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF 200
#define IWL_MAX_PLCP_ERR_THRESHOLD_MAX 255
#define IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE 0
/* TX queue watchdog timeouts in mSecs */
#define IWL_WATCHDOG_DISABLED 0
#define IWL_DEF_WD_TIMEOUT 2500
#define IWL_LONG_WD_TIMEOUT 10000
#define IWL_MAX_WD_TIMEOUT 120000
#define IWL_DEFAULT_MAX_TX_POWER 22
#define IWL_TX_CSUM_NETIF_FLAGS (NETIF_F_IPV6_CSUM | NETIF_F_IP_CSUM |\
NETIF_F_TSO | NETIF_F_TSO6)
/* Antenna presence definitions */
#define ANT_NONE 0x0
#define ANT_INVALID 0xff
#define ANT_A BIT(0)
#define ANT_B BIT(1)
#define ANT_C BIT(2)
#define ANT_AB (ANT_A | ANT_B)
#define ANT_AC (ANT_A | ANT_C)
#define ANT_BC (ANT_B | ANT_C)
#define ANT_ABC (ANT_A | ANT_B | ANT_C)
static inline u8 num_of_ant(u8 mask)
{
return !!((mask) & ANT_A) +
!!((mask) & ANT_B) +
!!((mask) & ANT_C);
}
/**
* struct iwl_base_params - params not likely to change within a device 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
* to the deviation to achieve the desired led frequency.
* The detail algorithm is described in iwl-led.c
* @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_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.
*/
struct iwl_base_params {
unsigned int wd_timeout;
u16 eeprom_size;
u16 max_event_log_size;
u8 pll_cfg:1, /* for iwl_pcie_apm_init() */
shadow_ram_support:1,
shadow_reg_enable:1,
pcie_l1_allowed:1,
apmg_wake_up_wa:1,
scd_chain_ext_wa:1;
u16 num_of_queues; /* def: HW dependent */
u32 max_tfd_queue_size; /* def: HW dependent */
u8 max_ll_items;
u8 led_compensation;
};
/*
* @stbc: support Tx STBC and 1*SS Rx STBC
* @ldpc: support Tx/Rx with LDPC
* @use_rts_for_aggregation: use rts/cts protection for HT traffic
* @ht40_bands: bitmap of bands (using %NL80211_BAND_*) that support HT40
*/
struct iwl_ht_params {
u8 ht_greenfield_support:1,
stbc:1,
ldpc:1,
use_rts_for_aggregation:1;
u8 ht40_bands;
};
/*
* Tx-backoff threshold
* @temperature: The threshold in Celsius
* @backoff: The tx-backoff in uSec
*/
struct iwl_tt_tx_backoff {
s32 temperature;
u32 backoff;
};
#define TT_TX_BACKOFF_SIZE 6
/**
* struct iwl_tt_params - thermal throttling parameters
* @ct_kill_entry: CT Kill entry threshold
* @ct_kill_exit: CT Kill exit threshold
* @ct_kill_duration: The time intervals (in uSec) in which the driver needs
* to checks whether to exit CT Kill.
* @dynamic_smps_entry: Dynamic SMPS entry threshold
* @dynamic_smps_exit: Dynamic SMPS exit threshold
* @tx_protection_entry: TX protection entry threshold
* @tx_protection_exit: TX protection exit threshold
* @tx_backoff: Array of thresholds for tx-backoff , in ascending order.
* @support_ct_kill: Support CT Kill?
* @support_dynamic_smps: Support dynamic SMPS?
* @support_tx_protection: Support tx protection?
* @support_tx_backoff: Support tx-backoff?
*/
struct iwl_tt_params {
u32 ct_kill_entry;
u32 ct_kill_exit;
u32 ct_kill_duration;
u32 dynamic_smps_entry;
u32 dynamic_smps_exit;
u32 tx_protection_entry;
u32 tx_protection_exit;
struct iwl_tt_tx_backoff tx_backoff[TT_TX_BACKOFF_SIZE];
u8 support_ct_kill:1,
support_dynamic_smps:1,
support_tx_protection:1,
support_tx_backoff:1;
};
/*
* information on how to parse the EEPROM
*/
#define EEPROM_REG_BAND_1_CHANNELS 0x08
#define EEPROM_REG_BAND_2_CHANNELS 0x26
#define EEPROM_REG_BAND_3_CHANNELS 0x42
#define EEPROM_REG_BAND_4_CHANNELS 0x5C
#define EEPROM_REG_BAND_5_CHANNELS 0x74
#define EEPROM_REG_BAND_24_HT40_CHANNELS 0x82
#define EEPROM_REG_BAND_52_HT40_CHANNELS 0x92
#define EEPROM_6000_REG_BAND_24_HT40_CHANNELS 0x80
#define EEPROM_REGULATORY_BAND_NO_HT40 0
/* lower blocks contain EEPROM image and calibration data */
#define OTP_LOW_IMAGE_SIZE_2K (2 * 512 * sizeof(u16)) /* 2 KB */
#define OTP_LOW_IMAGE_SIZE_16K (16 * 512 * sizeof(u16)) /* 16 KB */
#define OTP_LOW_IMAGE_SIZE_32K (32 * 512 * sizeof(u16)) /* 32 KB */
struct iwl_eeprom_params {
const u8 regulatory_bands[7];
bool enhanced_txpower;
};
/* Tx-backoff power threshold
* @pwr: The power limit in mw
* @backoff: The tx-backoff in uSec
*/
struct iwl_pwr_tx_backoff {
u32 pwr;
u32 backoff;
};
enum iwl_cfg_trans_ltr_delay {
IWL_CFG_TRANS_LTR_DELAY_NONE = 0,
IWL_CFG_TRANS_LTR_DELAY_200US = 1,
IWL_CFG_TRANS_LTR_DELAY_2500US = 2,
IWL_CFG_TRANS_LTR_DELAY_1820US = 3,
};
/**
* struct iwl_cfg_trans - information needed to start the trans
*
* 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
* @csr: csr flags and addresses that are different across devices
* @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
* @use_tfh: use TFH
* @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
* @ltr_delay: LTR delay parameter, &enum iwl_cfg_trans_ltr_delay.
*/
struct iwl_cfg_trans_params {
const struct iwl_base_params *base_params;
enum iwl_device_family device_family;
u32 umac_prph_offset;
u32 xtal_latency;
u32 extra_phy_cfg_flags;
u32 rf_id:1,
use_tfh:1,
gen2:1,
mq_rx_supported:1,
integrated:1,
low_latency_xtal:1,
bisr_workaround:1,
ltr_delay:2;
};
/**
* 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_cfg
* @trans: the trans-specific configuration part
* @name: Official name of the device
* @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.
* @ucode_api_max: Highest version of uCode API supported by driver.
* @ucode_api_min: Lowest version of uCode API supported by driver.
* @max_inst_size: The maximal length of the fw inst section (only DVM)
* @max_data_size: The maximal length of the fw data section (only DVM)
* @valid_tx_ant: valid transmit antenna
* @valid_rx_ant: valid receive antenna
* @non_shared_ant: the antenna that is for WiFi only
* @nvm_ver: NVM version
* @nvm_calib_ver: NVM calibration version
* @lib: pointer to the lib ops
* @ht_params: point to ht parameters
* @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
* @bisr_workaround: BISR hardware workaround (for 22260 series devices)
* @min_txq_size: minimum number of slots required in a TX queue
* @uhb_supported: ultra high band channels supported
* @min_256_ba_txq_size: minimum number of slots required in a TX queue which
* supports 256 BA aggregation
* @num_rbds: number of receive buffer descriptors to use
* (only used for multi-queue capable devices)
* @mac_addr_csr_base: CSR base register for MAC address access, if not set
* assume 0x380
*
* We enable the driver to be backward compatible wrt. hardware features.
* 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;
/* params specific to an individual device within a device family */
const char *name;
const char *fw_name_pre;
/* params likely to change within a device family */
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;
u32 rx_with_siso_diversity:1,
tx_with_siso_diversity:1,
bt_shared_single_ant:1,
internal_wimax_coex:1,
host_interrupt_operation_mode:1,
high_temp:1,
mac_addr_from_csr:10,
lp_xtal_workaround:1,
disable_dummy_notification: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_256_ba_txq_size;
const struct iwl_fw_mon_regs mon_dram_regs;
const struct iwl_fw_mon_regs mon_smem_regs;
};
#define IWL_CFG_ANY (~0)
#define IWL_CFG_MAC_TYPE_PU 0x31
#define IWL_CFG_MAC_TYPE_PNJ 0x32
#define IWL_CFG_MAC_TYPE_TH 0x32
#define IWL_CFG_MAC_TYPE_QU 0x33
#define IWL_CFG_MAC_TYPE_QUZ 0x35
#define IWL_CFG_MAC_TYPE_QNJ 0x36
#define IWL_CFG_MAC_TYPE_SO 0x37
#define IWL_CFG_MAC_TYPE_SNJ 0x42
#define IWL_CFG_MAC_TYPE_SOF 0x43
#define IWL_CFG_MAC_TYPE_MA 0x44
#define IWL_CFG_MAC_TYPE_BZ 0x46
#define IWL_CFG_MAC_TYPE_GL 0x47
#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
#define IWL_CFG_RF_TYPE_HR1 0x10C
#define IWL_CFG_RF_TYPE_GF 0x10D
#define IWL_CFG_RF_TYPE_MR 0x110
#define IWL_CFG_RF_TYPE_FM 0x112
#define IWL_CFG_RF_ID_TH 0x1
#define IWL_CFG_RF_ID_TH1 0x1
#define IWL_CFG_RF_ID_JF 0x3
#define IWL_CFG_RF_ID_JF1 0x6
#define IWL_CFG_RF_ID_JF1_DIV 0xA
#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_CORES_BT 0x0
#define IWL_CFG_CORES_BT_GNSS 0x5
#define IWL_CFG_NO_CDB 0x0
#define IWL_CFG_CDB 0x1
#define IWL_SUBDEVICE_RF_ID(subdevice) ((u16)((subdevice) & 0x00F0) >> 4)
#define IWL_SUBDEVICE_NO_160(subdevice) ((u16)((subdevice) & 0x0200) >> 9)
#define IWL_SUBDEVICE_CORES(subdevice) ((u16)((subdevice) & 0x1C00) >> 10)
struct iwl_dev_info {
u16 device;
u16 subdevice;
u16 mac_type;
u16 rf_type;
u8 mac_step;
u8 rf_id;
u8 no_160;
u8 cores;
u8 cdb;
const struct iwl_cfg *cfg;
const char *name;
};
/*
* 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_qnj_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_snj_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_ma_trans_cfg;
extern const struct iwl_cfg_trans_params iwl_bz_trans_cfg;
extern const char iwl9162_name[];
extern const char iwl9260_name[];
extern const char iwl9260_1_name[];
extern const char iwl9270_name[];
extern const char iwl9461_name[];
extern const char iwl9462_name[];
extern const char iwl9560_name[];
extern const char iwl9162_160_name[];
extern const char iwl9260_160_name[];
extern const char iwl9270_160_name[];
extern const char iwl9461_160_name[];
extern const char iwl9462_160_name[];
extern const char iwl9560_160_name[];
extern const char iwl9260_killer_1550_name[];
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_ax201_name[];
extern const char iwl_ax101_name[];
extern const char iwl_ax200_killer_1650w_name[];
extern const char iwl_ax200_killer_1650x_name[];
extern const char iwl_ax201_killer_1650s_name[];
extern const char iwl_ax201_killer_1650i_name[];
extern const char iwl_ax210_killer_1675w_name[];
extern const char iwl_ax210_killer_1675x_name[];
extern const char iwl9560_killer_1550i_160_name[];
extern const char iwl9560_killer_1550s_160_name[];
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_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[];
#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;
#endif /* CONFIG_IWLDVM */
#if IS_ENABLED(CONFIG_IWLMVM)
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_qnj_b0_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 iwl_qnj_b0_hr_b0_cfg;
extern const struct iwl_cfg iwlax210_2ax_cfg_so_jf_b0;
extern const struct iwl_cfg iwlax210_2ax_cfg_so_hr_a0;
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_cfg iwlax411_2ax_cfg_sosnj_gf4_a0;
extern const struct iwl_cfg iwlax211_cfg_snj_gf_a0;
extern const struct iwl_cfg iwl_cfg_snj_hr_b0;
extern const struct iwl_cfg iwl_cfg_snj_a0_jf_b0;
extern const struct iwl_cfg iwl_cfg_ma_a0_hr_b0;
extern const struct iwl_cfg iwl_cfg_ma_a0_gf_a0;
extern const struct iwl_cfg iwl_cfg_ma_a0_gf4_a0;
extern const struct iwl_cfg iwl_cfg_ma_a0_mr_a0;
extern const struct iwl_cfg iwl_cfg_ma_a0_fm_a0;
extern const struct iwl_cfg iwl_cfg_snj_a0_mr_a0;
extern const struct iwl_cfg iwl_cfg_so_a0_hr_a0;
extern const struct iwl_cfg iwl_cfg_quz_a0_hr_b0;
extern const struct iwl_cfg iwl_cfg_bz_a0_hr_b0;
extern const struct iwl_cfg iwl_cfg_bz_a0_gf_a0;
extern const struct iwl_cfg iwl_cfg_bz_a0_gf4_a0;
extern const struct iwl_cfg iwl_cfg_bz_a0_mr_a0;
extern const struct iwl_cfg iwl_cfg_bz_a0_fm_a0;
extern const struct iwl_cfg iwl_cfg_gl_a0_fm_a0;
#endif /* CONFIG_IWLMVM */
#endif /* __IWL_CONFIG_H__ */

View File

@ -0,0 +1,267 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2018, 2020-2021 Intel Corporation
*/
#ifndef __iwl_context_info_file_gen3_h__
#define __iwl_context_info_file_gen3_h__
#include "iwl-context-info.h"
#define CSR_CTXT_INFO_BOOT_CTRL 0x0
#define CSR_CTXT_INFO_ADDR 0x118
#define CSR_IML_DATA_ADDR 0x120
#define CSR_IML_SIZE_ADDR 0x128
#define CSR_IML_RESP_ADDR 0x12c
/* Set bit for enabling automatic function boot */
#define CSR_AUTO_FUNC_BOOT_ENA BIT(1)
/* Set bit for initiating function boot */
#define CSR_AUTO_FUNC_INIT BIT(7)
/**
* enum iwl_prph_scratch_mtr_format - tfd size configuration
* @IWL_PRPH_MTR_FORMAT_16B: 16 bit tfd
* @IWL_PRPH_MTR_FORMAT_32B: 32 bit tfd
* @IWL_PRPH_MTR_FORMAT_64B: 64 bit tfd
* @IWL_PRPH_MTR_FORMAT_256B: 256 bit tfd
*/
enum iwl_prph_scratch_mtr_format {
IWL_PRPH_MTR_FORMAT_16B = 0x0,
IWL_PRPH_MTR_FORMAT_32B = 0x40000,
IWL_PRPH_MTR_FORMAT_64B = 0x80000,
IWL_PRPH_MTR_FORMAT_256B = 0xC0000,
};
/**
* enum iwl_prph_scratch_flags - PRPH scratch control flags
* @IWL_PRPH_SCRATCH_EARLY_DEBUG_EN: enable early debug conf
* @IWL_PRPH_SCRATCH_EDBG_DEST_DRAM: use DRAM, with size allocated
* in hwm config.
* @IWL_PRPH_SCRATCH_EDBG_DEST_INTERNAL: use buffer on SRAM
* @IWL_PRPH_SCRATCH_EDBG_DEST_ST_ARBITER: use st arbiter, mainly for
* multicomm.
* @IWL_PRPH_SCRATCH_EDBG_DEST_TB22DTF: route debug data to SoC HW
* @IWL_PRPH_SCTATCH_RB_SIZE_4K: Use 4K RB size (the default is 2K)
* @IWL_PRPH_SCRATCH_MTR_MODE: format used for completion - 0: for
* completion descriptor, 1 for responses (legacy)
* @IWL_PRPH_SCRATCH_MTR_FORMAT: a mask for the size of the tfd.
* There are 4 optional values: 0: 16 bit, 1: 32 bit, 2: 64 bit,
* 3: 256 bit.
* @IWL_PRPH_SCRATCH_RB_SIZE_EXT_MASK: RB size full information, ignored
* by older firmware versions, so set IWL_PRPH_SCRATCH_RB_SIZE_4K
* appropriately; use the below values for this.
* @IWL_PRPH_SCRATCH_RB_SIZE_EXT_8K: 8kB RB size
* @IWL_PRPH_SCRATCH_RB_SIZE_EXT_12K: 12kB RB size
* @IWL_PRPH_SCRATCH_RB_SIZE_EXT_16K: 16kB RB size
*/
enum iwl_prph_scratch_flags {
IWL_PRPH_SCRATCH_EARLY_DEBUG_EN = BIT(4),
IWL_PRPH_SCRATCH_EDBG_DEST_DRAM = BIT(8),
IWL_PRPH_SCRATCH_EDBG_DEST_INTERNAL = BIT(9),
IWL_PRPH_SCRATCH_EDBG_DEST_ST_ARBITER = BIT(10),
IWL_PRPH_SCRATCH_EDBG_DEST_TB22DTF = BIT(11),
IWL_PRPH_SCRATCH_RB_SIZE_4K = BIT(16),
IWL_PRPH_SCRATCH_MTR_MODE = BIT(17),
IWL_PRPH_SCRATCH_MTR_FORMAT = BIT(18) | BIT(19),
IWL_PRPH_SCRATCH_RB_SIZE_EXT_MASK = 0xf << 20,
IWL_PRPH_SCRATCH_RB_SIZE_EXT_8K = 8 << 20,
IWL_PRPH_SCRATCH_RB_SIZE_EXT_12K = 9 << 20,
IWL_PRPH_SCRATCH_RB_SIZE_EXT_16K = 10 << 20,
};
/*
* struct iwl_prph_scratch_version - version structure
* @mac_id: SKU and revision id
* @version: prph scratch information version id
* @size: the size of the context information in DWs
* @reserved: reserved
*/
struct iwl_prph_scratch_version {
__le16 mac_id;
__le16 version;
__le16 size;
__le16 reserved;
} __packed; /* PERIPH_SCRATCH_VERSION_S */
/*
* struct iwl_prph_scratch_control - control structure
* @control_flags: context information flags see &enum iwl_prph_scratch_flags
* @reserved: reserved
*/
struct iwl_prph_scratch_control {
__le32 control_flags;
__le32 reserved;
} __packed; /* PERIPH_SCRATCH_CONTROL_S */
/*
* struct iwl_prph_scratch_pnvm_cfg - ror config
* @pnvm_base_addr: PNVM start address
* @pnvm_size: PNVM size in DWs
* @reserved: reserved
*/
struct iwl_prph_scratch_pnvm_cfg {
__le64 pnvm_base_addr;
__le32 pnvm_size;
__le32 reserved;
} __packed; /* PERIPH_SCRATCH_PNVM_CFG_S */
/*
* struct iwl_prph_scratch_hwm_cfg - hwm config
* @hwm_base_addr: hwm start address
* @hwm_size: hwm size in DWs
* @debug_token_config: debug preset
*/
struct iwl_prph_scratch_hwm_cfg {
__le64 hwm_base_addr;
__le32 hwm_size;
__le32 debug_token_config;
} __packed; /* PERIPH_SCRATCH_HWM_CFG_S */
/*
* struct iwl_prph_scratch_rbd_cfg - RBDs configuration
* @free_rbd_addr: default queue free RB CB base address
* @reserved: reserved
*/
struct iwl_prph_scratch_rbd_cfg {
__le64 free_rbd_addr;
__le32 reserved;
} __packed; /* PERIPH_SCRATCH_RBD_CFG_S */
/*
* struct iwl_prph_scratch_uefi_cfg - prph scratch reduce power table
* @base_addr: reduce power table address
* @size: table size in dwords
*/
struct iwl_prph_scratch_uefi_cfg {
__le64 base_addr;
__le32 size;
__le32 reserved;
} __packed; /* PERIPH_SCRATCH_UEFI_CFG_S */
/*
* struct iwl_prph_scratch_ctrl_cfg - prph scratch ctrl and config
* @version: version information of context info and HW
* @control: control flags of FH configurations
* @pnvm_cfg: ror configuration
* @hwm_cfg: hwm configuration
* @rbd_cfg: default RX queue configuration
*/
struct iwl_prph_scratch_ctrl_cfg {
struct iwl_prph_scratch_version version;
struct iwl_prph_scratch_control control;
struct iwl_prph_scratch_pnvm_cfg pnvm_cfg;
struct iwl_prph_scratch_hwm_cfg hwm_cfg;
struct iwl_prph_scratch_rbd_cfg rbd_cfg;
struct iwl_prph_scratch_uefi_cfg reduce_power_cfg;
} __packed; /* PERIPH_SCRATCH_CTRL_CFG_S */
/*
* struct iwl_prph_scratch - peripheral scratch mapping
* @ctrl_cfg: control and configuration of prph scratch
* @dram: firmware images addresses in DRAM
* @reserved: reserved
*/
struct iwl_prph_scratch {
struct iwl_prph_scratch_ctrl_cfg ctrl_cfg;
__le32 reserved[12];
struct iwl_context_info_dram dram;
} __packed; /* PERIPH_SCRATCH_S */
/*
* struct iwl_prph_info - peripheral information
* @boot_stage_mirror: reflects the value in the Boot Stage CSR register
* @ipc_status_mirror: reflects the value in the IPC Status CSR register
* @sleep_notif: indicates the peripheral sleep status
* @reserved: reserved
*/
struct iwl_prph_info {
__le32 boot_stage_mirror;
__le32 ipc_status_mirror;
__le32 sleep_notif;
__le32 reserved;
} __packed; /* PERIPH_INFO_S */
/*
* struct iwl_context_info_gen3 - device INIT configuration
* @version: version of the context information
* @size: size of context information in DWs
* @config: context in which the peripheral would execute - a subset of
* capability csr register published by the peripheral
* @prph_info_base_addr: the peripheral information structure start address
* @cr_head_idx_arr_base_addr: the completion ring head index array
* start address
* @tr_tail_idx_arr_base_addr: the transfer ring tail index array
* start address
* @cr_tail_idx_arr_base_addr: the completion ring tail index array
* start address
* @tr_head_idx_arr_base_addr: the transfer ring head index array
* start address
* @cr_idx_arr_size: number of entries in the completion ring index array
* @tr_idx_arr_size: number of entries in the transfer ring index array
* @mtr_base_addr: the message transfer ring start address
* @mcr_base_addr: the message completion ring start address
* @mtr_size: number of entries which the message transfer ring can hold
* @mcr_size: number of entries which the message completion ring can hold
* @mtr_doorbell_vec: the doorbell vector associated with the message
* transfer ring
* @mcr_doorbell_vec: the doorbell vector associated with the message
* completion ring
* @mtr_msi_vec: the MSI which shall be generated by the peripheral after
* completing a transfer descriptor in the message transfer ring
* @mcr_msi_vec: the MSI which shall be generated by the peripheral after
* completing a completion descriptor in the message completion ring
* @mtr_opt_header_size: the size of the optional header in the transfer
* descriptor associated with the message transfer ring in DWs
* @mtr_opt_footer_size: the size of the optional footer in the transfer
* descriptor associated with the message transfer ring in DWs
* @mcr_opt_header_size: the size of the optional header in the completion
* descriptor associated with the message completion ring in DWs
* @mcr_opt_footer_size: the size of the optional footer in the completion
* descriptor associated with the message completion ring in DWs
* @msg_rings_ctrl_flags: message rings control flags
* @prph_info_msi_vec: the MSI which shall be generated by the peripheral
* after updating the Peripheral Information structure
* @prph_scratch_base_addr: the peripheral scratch structure start address
* @prph_scratch_size: the size of the peripheral scratch structure in DWs
* @reserved: reserved
*/
struct iwl_context_info_gen3 {
__le16 version;
__le16 size;
__le32 config;
__le64 prph_info_base_addr;
__le64 cr_head_idx_arr_base_addr;
__le64 tr_tail_idx_arr_base_addr;
__le64 cr_tail_idx_arr_base_addr;
__le64 tr_head_idx_arr_base_addr;
__le16 cr_idx_arr_size;
__le16 tr_idx_arr_size;
__le64 mtr_base_addr;
__le64 mcr_base_addr;
__le16 mtr_size;
__le16 mcr_size;
__le16 mtr_doorbell_vec;
__le16 mcr_doorbell_vec;
__le16 mtr_msi_vec;
__le16 mcr_msi_vec;
u8 mtr_opt_header_size;
u8 mtr_opt_footer_size;
u8 mcr_opt_header_size;
u8 mcr_opt_footer_size;
__le16 msg_rings_ctrl_flags;
__le16 prph_info_msi_vec;
__le64 prph_scratch_base_addr;
__le32 prph_scratch_size;
__le32 reserved;
} __packed; /* IPC_CONTEXT_INFO_S */
int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans,
const struct fw_img *fw);
void iwl_pcie_ctxt_info_gen3_free(struct iwl_trans *trans, bool alive);
int iwl_trans_pcie_ctx_info_gen3_set_pnvm(struct iwl_trans *trans,
const void *data, u32 len);
int iwl_trans_pcie_ctx_info_gen3_set_reduce_power(struct iwl_trans *trans,
const void *data, u32 len);
#endif /* __iwl_context_info_file_gen3_h__ */

View File

@ -0,0 +1,184 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2017 Intel Deutschland GmbH
* Copyright (C) 2018-2020 Intel Corporation
*/
#ifndef __iwl_context_info_file_h__
#define __iwl_context_info_file_h__
/* maximmum number of DRAM map entries supported by FW */
#define IWL_MAX_DRAM_ENTRY 64
#define CSR_CTXT_INFO_BA 0x40
/**
* enum iwl_context_info_flags - Context information control flags
* @IWL_CTXT_INFO_AUTO_FUNC_INIT: If set, FW will not wait before interrupting
* the init done for driver command that configures several system modes
* @IWL_CTXT_INFO_EARLY_DEBUG: enable early debug
* @IWL_CTXT_INFO_ENABLE_CDMP: enable core dump
* @IWL_CTXT_INFO_RB_CB_SIZE: mask of the RBD Cyclic Buffer Size
* exponent, the actual size is 2**value, valid sizes are 8-2048.
* The value is four bits long. Maximum valid exponent is 12
* @IWL_CTXT_INFO_TFD_FORMAT_LONG: use long TFD Format (the
* default is short format - not supported by the driver)
* @IWL_CTXT_INFO_RB_SIZE: RB size mask
* (values are IWL_CTXT_INFO_RB_SIZE_*K)
* @IWL_CTXT_INFO_RB_SIZE_1K: Value for 1K RB size
* @IWL_CTXT_INFO_RB_SIZE_2K: Value for 2K RB size
* @IWL_CTXT_INFO_RB_SIZE_4K: Value for 4K RB size
* @IWL_CTXT_INFO_RB_SIZE_8K: Value for 8K RB size
* @IWL_CTXT_INFO_RB_SIZE_12K: Value for 12K RB size
* @IWL_CTXT_INFO_RB_SIZE_16K: Value for 16K RB size
* @IWL_CTXT_INFO_RB_SIZE_20K: Value for 20K RB size
* @IWL_CTXT_INFO_RB_SIZE_24K: Value for 24K RB size
* @IWL_CTXT_INFO_RB_SIZE_28K: Value for 28K RB size
* @IWL_CTXT_INFO_RB_SIZE_32K: Value for 32K RB size
*/
enum iwl_context_info_flags {
IWL_CTXT_INFO_AUTO_FUNC_INIT = 0x0001,
IWL_CTXT_INFO_EARLY_DEBUG = 0x0002,
IWL_CTXT_INFO_ENABLE_CDMP = 0x0004,
IWL_CTXT_INFO_RB_CB_SIZE = 0x00f0,
IWL_CTXT_INFO_TFD_FORMAT_LONG = 0x0100,
IWL_CTXT_INFO_RB_SIZE = 0x1e00,
IWL_CTXT_INFO_RB_SIZE_1K = 0x1,
IWL_CTXT_INFO_RB_SIZE_2K = 0x2,
IWL_CTXT_INFO_RB_SIZE_4K = 0x4,
IWL_CTXT_INFO_RB_SIZE_8K = 0x8,
IWL_CTXT_INFO_RB_SIZE_12K = 0x9,
IWL_CTXT_INFO_RB_SIZE_16K = 0xa,
IWL_CTXT_INFO_RB_SIZE_20K = 0xb,
IWL_CTXT_INFO_RB_SIZE_24K = 0xc,
IWL_CTXT_INFO_RB_SIZE_28K = 0xd,
IWL_CTXT_INFO_RB_SIZE_32K = 0xe,
};
/*
* struct iwl_context_info_version - version structure
* @mac_id: SKU and revision id
* @version: context information version id
* @size: the size of the context information in DWs
*/
struct iwl_context_info_version {
__le16 mac_id;
__le16 version;
__le16 size;
__le16 reserved;
} __packed;
/*
* struct iwl_context_info_control - version structure
* @control_flags: context information flags see &enum iwl_context_info_flags
*/
struct iwl_context_info_control {
__le32 control_flags;
__le32 reserved;
} __packed;
/*
* struct iwl_context_info_dram - images DRAM map
* each entry in the map represents a DRAM chunk of up to 32 KB
* @umac_img: UMAC image DRAM map
* @lmac_img: LMAC image DRAM map
* @virtual_img: paged image DRAM map
*/
struct iwl_context_info_dram {
__le64 umac_img[IWL_MAX_DRAM_ENTRY];
__le64 lmac_img[IWL_MAX_DRAM_ENTRY];
__le64 virtual_img[IWL_MAX_DRAM_ENTRY];
} __packed;
/*
* struct iwl_context_info_rbd_cfg - RBDs configuration
* @free_rbd_addr: default queue free RB CB base address
* @used_rbd_addr: default queue used RB CB base address
* @status_wr_ptr: default queue used RB status write pointer
*/
struct iwl_context_info_rbd_cfg {
__le64 free_rbd_addr;
__le64 used_rbd_addr;
__le64 status_wr_ptr;
} __packed;
/*
* struct iwl_context_info_hcmd_cfg - command queue configuration
* @cmd_queue_addr: address of command queue
* @cmd_queue_size: number of entries
*/
struct iwl_context_info_hcmd_cfg {
__le64 cmd_queue_addr;
u8 cmd_queue_size;
u8 reserved[7];
} __packed;
/*
* struct iwl_context_info_dump_cfg - Core Dump configuration
* @core_dump_addr: core dump (debug DRAM address) start address
* @core_dump_size: size, in DWs
*/
struct iwl_context_info_dump_cfg {
__le64 core_dump_addr;
__le32 core_dump_size;
__le32 reserved;
} __packed;
/*
* struct iwl_context_info_pnvm_cfg - platform NVM data configuration
* @platform_nvm_addr: Platform NVM data start address
* @platform_nvm_size: size in DWs
*/
struct iwl_context_info_pnvm_cfg {
__le64 platform_nvm_addr;
__le32 platform_nvm_size;
__le32 reserved;
} __packed;
/*
* struct iwl_context_info_early_dbg_cfg - early debug configuration for
* dumping DRAM addresses
* @early_debug_addr: early debug start address
* @early_debug_size: size in DWs
*/
struct iwl_context_info_early_dbg_cfg {
__le64 early_debug_addr;
__le32 early_debug_size;
__le32 reserved;
} __packed;
/*
* struct iwl_context_info - device INIT configuration
* @version: version information of context info and HW
* @control: control flags of FH configurations
* @rbd_cfg: default RX queue configuration
* @hcmd_cfg: command queue configuration
* @dump_cfg: core dump data
* @edbg_cfg: early debug configuration
* @pnvm_cfg: platform nvm configuration
* @dram: firmware image addresses in DRAM
*/
struct iwl_context_info {
struct iwl_context_info_version version;
struct iwl_context_info_control control;
__le64 reserved0;
struct iwl_context_info_rbd_cfg rbd_cfg;
struct iwl_context_info_hcmd_cfg hcmd_cfg;
__le32 reserved1[4];
struct iwl_context_info_dump_cfg dump_cfg;
struct iwl_context_info_early_dbg_cfg edbg_cfg;
struct iwl_context_info_pnvm_cfg pnvm_cfg;
__le32 reserved2[16];
struct iwl_context_info_dram dram;
__le32 reserved3[16];
} __packed;
int iwl_pcie_ctxt_info_init(struct iwl_trans *trans, const struct fw_img *fw);
void iwl_pcie_ctxt_info_free(struct iwl_trans *trans);
void iwl_pcie_ctxt_info_free_paging(struct iwl_trans *trans);
int iwl_pcie_init_fw_sec(struct iwl_trans *trans,
const struct fw_img *fw,
struct iwl_context_info_dram *ctxt_dram);
int iwl_pcie_ctxt_info_alloc_dma(struct iwl_trans *trans,
const void *data, u32 len,
struct iwl_dram_data *dram);
#endif /* __iwl_context_info_file_h__ */

View File

@ -0,0 +1,633 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2005-2014, 2018-2021 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2016 Intel Deutschland GmbH
*/
#ifndef __iwl_csr_h__
#define __iwl_csr_h__
/*
* CSR (control and status registers)
*
* CSR registers are mapped directly into PCI bus space, and are accessible
* whenever platform supplies power to device, even when device is in
* low power states due to driver-invoked device resets
* (e.g. CSR_RESET_REG_FLAG_SW_RESET) or uCode-driven power-saving modes.
*
* Use iwl_write32() and iwl_read32() family to access these registers;
* these provide simple PCI bus access, without waking up the MAC.
* Do not use iwl_write_direct32() family for these registers;
* no need to "grab nic access" via CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ.
* The MAC (uCode processor, etc.) does not need to be powered up for accessing
* the CSR registers.
*
* NOTE: Device does need to be awake in order to read this memory
* via CSR_EEPROM and CSR_OTP registers
*/
#define CSR_BASE (0x000)
#define CSR_HW_IF_CONFIG_REG (CSR_BASE+0x000) /* hardware interface config */
#define CSR_INT_COALESCING (CSR_BASE+0x004) /* accum ints, 32-usec units */
#define CSR_INT (CSR_BASE+0x008) /* host interrupt status/ack */
#define CSR_INT_MASK (CSR_BASE+0x00c) /* host interrupt enable */
#define CSR_FH_INT_STATUS (CSR_BASE+0x010) /* busmaster int status/ack*/
#define CSR_GPIO_IN (CSR_BASE+0x018) /* read external chip pins */
#define CSR_RESET (CSR_BASE+0x020) /* busmaster enable, NMI, etc*/
#define CSR_GP_CNTRL (CSR_BASE+0x024)
#define CSR_FUNC_SCRATCH (CSR_BASE+0x02c) /* Scratch register - used for FW dbg */
/* 2nd byte of CSR_INT_COALESCING, not accessible via iwl_write32()! */
#define CSR_INT_PERIODIC_REG (CSR_BASE+0x005)
/*
* Hardware revision info
* Bit fields:
* 31-16: Reserved
* 15-4: Type of device: see CSR_HW_REV_TYPE_xxx definitions
* 3-2: Revision step: 0 = A, 1 = B, 2 = C, 3 = D
* 1-0: "Dash" (-) value, as in A-1, etc.
*/
#define CSR_HW_REV (CSR_BASE+0x028)
/*
* RF ID revision info
* Bit fields:
* 31:24: Reserved (set to 0x0)
* 23:12: Type
* 11:8: Step (A - 0x0, B - 0x1, etc)
* 7:4: Dash
* 3:0: Flavor
*/
#define CSR_HW_RF_ID (CSR_BASE+0x09c)
/*
* EEPROM and OTP (one-time-programmable) memory reads
*
* NOTE: Device must be awake, initialized via apm_ops.init(),
* in order to read.
*/
#define CSR_EEPROM_REG (CSR_BASE+0x02c)
#define CSR_EEPROM_GP (CSR_BASE+0x030)
#define CSR_OTP_GP_REG (CSR_BASE+0x034)
#define CSR_GIO_REG (CSR_BASE+0x03C)
#define CSR_GP_UCODE_REG (CSR_BASE+0x048)
#define CSR_GP_DRIVER_REG (CSR_BASE+0x050)
/*
* UCODE-DRIVER GP (general purpose) mailbox registers.
* SET/CLR registers set/clear bit(s) if "1" is written.
*/
#define CSR_UCODE_DRV_GP1 (CSR_BASE+0x054)
#define CSR_UCODE_DRV_GP1_SET (CSR_BASE+0x058)
#define CSR_UCODE_DRV_GP1_CLR (CSR_BASE+0x05c)
#define CSR_UCODE_DRV_GP2 (CSR_BASE+0x060)
#define CSR_MBOX_SET_REG (CSR_BASE + 0x88)
#define CSR_LED_REG (CSR_BASE+0x094)
#define CSR_DRAM_INT_TBL_REG (CSR_BASE+0x0A0)
#define CSR_MAC_SHADOW_REG_CTRL (CSR_BASE + 0x0A8) /* 6000 and up */
#define CSR_MAC_SHADOW_REG_CTRL_RX_WAKE BIT(20)
#define CSR_MAC_SHADOW_REG_CTL2 (CSR_BASE + 0x0AC)
#define CSR_MAC_SHADOW_REG_CTL2_RX_WAKE 0xFFFF
/* LTR control (since IWL_DEVICE_FAMILY_22000) */
#define CSR_LTR_LONG_VAL_AD (CSR_BASE + 0x0D4)
#define CSR_LTR_LONG_VAL_AD_NO_SNOOP_REQ 0x80000000
#define CSR_LTR_LONG_VAL_AD_NO_SNOOP_SCALE 0x1c000000
#define CSR_LTR_LONG_VAL_AD_NO_SNOOP_VAL 0x03ff0000
#define CSR_LTR_LONG_VAL_AD_SNOOP_REQ 0x00008000
#define CSR_LTR_LONG_VAL_AD_SNOOP_SCALE 0x00001c00
#define CSR_LTR_LONG_VAL_AD_SNOOP_VAL 0x000003ff
#define CSR_LTR_LONG_VAL_AD_SCALE_USEC 2
/* GIO Chicken Bits (PCI Express bus link power management) */
#define CSR_GIO_CHICKEN_BITS (CSR_BASE+0x100)
/* Doorbell NMI (since Bz) */
#define CSR_DOORBELL_VECTOR (CSR_BASE + 0x130)
#define CSR_DOORBELL_VECTOR_NMI BIT(1)
/* host chicken bits */
#define CSR_HOST_CHICKEN (CSR_BASE + 0x204)
#define CSR_HOST_CHICKEN_PM_IDLE_SRC_DIS_SB_PME BIT(19)
/* Analog phase-lock-loop configuration */
#define CSR_ANA_PLL_CFG (CSR_BASE+0x20c)
/*
* CSR HW resources monitor registers
*/
#define CSR_MONITOR_CFG_REG (CSR_BASE+0x214)
#define CSR_MONITOR_STATUS_REG (CSR_BASE+0x228)
#define CSR_MONITOR_XTAL_RESOURCES (0x00000010)
/*
* CSR Hardware Revision Workaround Register. Indicates hardware rev;
* "step" determines CCK backoff for txpower calculation.
* See also CSR_HW_REV register.
* Bit fields:
* 3-2: 0 = A, 1 = B, 2 = C, 3 = D step
* 1-0: "Dash" (-) value, as in C-1, etc.
*/
#define CSR_HW_REV_WA_REG (CSR_BASE+0x22C)
#define CSR_DBG_HPET_MEM_REG (CSR_BASE+0x240)
#define CSR_DBG_LINK_PWR_MGMT_REG (CSR_BASE+0x250)
/*
* Scratch register initial configuration - this is set on init, and read
* during a error FW error.
*/
#define CSR_FUNC_SCRATCH_INIT_VALUE (0x01010101)
/* Bits for CSR_HW_IF_CONFIG_REG */
#define CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH (0x00000003)
#define CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP (0x0000000C)
#define CSR_HW_IF_CONFIG_REG_BIT_MONITOR_SRAM (0x00000080)
#define CSR_HW_IF_CONFIG_REG_MSK_BOARD_VER (0x000000C0)
#define CSR_HW_IF_CONFIG_REG_BIT_MAC_SI (0x00000100)
#define CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI (0x00000200)
#define CSR_HW_IF_CONFIG_REG_D3_DEBUG (0x00000200)
#define CSR_HW_IF_CONFIG_REG_MSK_PHY_TYPE (0x00000C00)
#define CSR_HW_IF_CONFIG_REG_MSK_PHY_DASH (0x00003000)
#define CSR_HW_IF_CONFIG_REG_MSK_PHY_STEP (0x0000C000)
#define CSR_HW_IF_CONFIG_REG_POS_MAC_DASH (0)
#define CSR_HW_IF_CONFIG_REG_POS_MAC_STEP (2)
#define CSR_HW_IF_CONFIG_REG_POS_BOARD_VER (6)
#define CSR_HW_IF_CONFIG_REG_POS_PHY_TYPE (10)
#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_MBOX_SET_REG_OS_ALIVE BIT(5)
#define CSR_INT_PERIODIC_DIS (0x00) /* disable periodic int*/
#define CSR_INT_PERIODIC_ENA (0xFF) /* 255*32 usec ~ 8 msec*/
/* interrupt flags in INTA, set by uCode or hardware (e.g. dma),
* acknowledged (reset) by host writing "1" to flagged bits. */
#define CSR_INT_BIT_FH_RX (1 << 31) /* Rx DMA, cmd responses, FH_INT[17:16] */
#define CSR_INT_BIT_HW_ERR (1 << 29) /* DMA hardware error FH_INT[31] */
#define CSR_INT_BIT_RX_PERIODIC (1 << 28) /* Rx periodic */
#define CSR_INT_BIT_FH_TX (1 << 27) /* Tx DMA FH_INT[1:0] */
#define CSR_INT_BIT_SCD (1 << 26) /* TXQ pointer advanced */
#define CSR_INT_BIT_SW_ERR (1 << 25) /* uCode error */
#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_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 | \
CSR_INT_BIT_RX_PERIODIC)
/* interrupt flags in FH (flow handler) (PCI busmaster DMA) */
#define CSR_FH_INT_BIT_ERR (1 << 31) /* Error */
#define CSR_FH_INT_BIT_HI_PRIOR (1 << 30) /* High priority Rx, bypass coalescing */
#define CSR_FH_INT_BIT_RX_CHNL1 (1 << 17) /* Rx channel 1 */
#define CSR_FH_INT_BIT_RX_CHNL0 (1 << 16) /* Rx channel 0 */
#define CSR_FH_INT_BIT_TX_CHNL1 (1 << 1) /* Tx channel 1 */
#define CSR_FH_INT_BIT_TX_CHNL0 (1 << 0) /* Tx channel 0 */
#define CSR_FH_INT_RX_MASK (CSR_FH_INT_BIT_HI_PRIOR | \
CSR_FH_INT_BIT_RX_CHNL1 | \
CSR_FH_INT_BIT_RX_CHNL0)
#define CSR_FH_INT_TX_MASK (CSR_FH_INT_BIT_TX_CHNL1 | \
CSR_FH_INT_BIT_TX_CHNL0)
/* GPIO */
#define CSR_GPIO_IN_BIT_AUX_POWER (0x00000200)
#define CSR_GPIO_IN_VAL_VAUX_PWR_SRC (0x00000000)
#define CSR_GPIO_IN_VAL_VMAIN_PWR_SRC (0x00000200)
/* RESET */
#define CSR_RESET_REG_FLAG_NEVO_RESET (0x00000001)
#define CSR_RESET_REG_FLAG_FORCE_NMI (0x00000002)
#define CSR_RESET_REG_FLAG_SW_RESET (0x00000080)
#define CSR_RESET_REG_FLAG_MASTER_DISABLED (0x00000100)
#define CSR_RESET_REG_FLAG_STOP_MASTER (0x00000200)
#define CSR_RESET_LINK_PWR_MGMT_DISABLED (0x80000000)
/*
* GP (general purpose) CONTROL REGISTER
* Bit fields:
* 27: HW_RF_KILL_SW
* Indicates state of (platform's) hardware RF-Kill switch
* 26-24: POWER_SAVE_TYPE
* Indicates current power-saving mode:
* 000 -- No power saving
* 001 -- MAC power-down
* 010 -- PHY (radio) power-down
* 011 -- Error
* 10: XTAL ON request
* 9-6: SYS_CONFIG
* Indicates current system configuration, reflecting pins on chip
* as forced high/low by device circuit board.
* 4: GOING_TO_SLEEP
* Indicates MAC is entering a power-saving sleep power-down.
* Not a good time to access device-internal resources.
* 3: MAC_ACCESS_REQ
* Host sets this to request and maintain MAC wakeup, to allow host
* access to device-internal resources. Host must wait for
* MAC_CLOCK_READY (and !GOING_TO_SLEEP) before accessing non-CSR
* device registers.
* 2: INIT_DONE
* Host sets this to put device into fully operational D0 power mode.
* Host resets this after SW_RESET to put device into low power mode.
* 0: MAC_CLOCK_READY
* Indicates MAC (ucode processor, etc.) is powered up and can run.
* Internal resources are accessible.
* NOTE: This does not indicate that the processor is actually running.
* NOTE: This does not indicate that device has completed
* init or post-power-down restore of internal SRAM memory.
* Use CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP as indication that
* SRAM is restored and uCode is in normal operation mode.
* Later devices (5xxx/6xxx/1xxx) use non-volatile SRAM, and
* do not need to save/restore it.
* NOTE: After device reset, this bit remains "0" until host sets
* INIT_DONE
*/
#define CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY (0x00000001)
#define CSR_GP_CNTRL_REG_FLAG_INIT_DONE (0x00000004)
#define CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ (0x00000008)
#define CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP (0x00000010)
#define CSR_GP_CNTRL_REG_FLAG_XTAL_ON (0x00000400)
#define CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN (0x00000001)
#define CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE (0x07000000)
#define CSR_GP_CNTRL_REG_FLAG_RFKILL_WAKE_L1A_EN (0x04000000)
#define CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW (0x08000000)
/* From Bz we use these instead during init/reset flow */
#define CSR_GP_CNTRL_REG_FLAG_MAC_INIT BIT(6)
#define CSR_GP_CNTRL_REG_FLAG_ROM_START BIT(7)
#define CSR_GP_CNTRL_REG_FLAG_MAC_STATUS BIT(20)
#define CSR_GP_CNTRL_REG_FLAG_BZ_MAC_ACCESS_REQ BIT(21)
#define CSR_GP_CNTRL_REG_FLAG_BUS_MASTER_DISABLE_STATUS BIT(28)
#define CSR_GP_CNTRL_REG_FLAG_BUS_MASTER_DISABLE_REQ BIT(29)
#define CSR_GP_CNTRL_REG_FLAG_SW_RESET BIT(31)
/* HW REV */
#define CSR_HW_REV_DASH(_val) (((_val) & 0x0000003) >> 0)
#define CSR_HW_REV_STEP(_val) (((_val) & 0x000000C) >> 2)
#define CSR_HW_REV_TYPE(_val) (((_val) & 0x000FFF0) >> 4)
/* HW RFID */
#define CSR_HW_RFID_FLAVOR(_val) (((_val) & 0x000000F) >> 0)
#define CSR_HW_RFID_DASH(_val) (((_val) & 0x00000F0) >> 4)
#define CSR_HW_RFID_STEP(_val) (((_val) & 0x0000F00) >> 8)
#define CSR_HW_RFID_TYPE(_val) (((_val) & 0x0FFF000) >> 12)
#define CSR_HW_RFID_IS_CDB(_val) (((_val) & 0x10000000) >> 28)
#define CSR_HW_RFID_IS_JACKET(_val) (((_val) & 0x20000000) >> 29)
/**
* hw_rev values
*/
enum {
SILICON_A_STEP = 0,
SILICON_B_STEP,
SILICON_C_STEP,
};
#define CSR_HW_REV_TYPE_MSK (0x000FFF0)
#define CSR_HW_REV_TYPE_5300 (0x0000020)
#define CSR_HW_REV_TYPE_5350 (0x0000030)
#define CSR_HW_REV_TYPE_5100 (0x0000050)
#define CSR_HW_REV_TYPE_5150 (0x0000040)
#define CSR_HW_REV_TYPE_1000 (0x0000060)
#define CSR_HW_REV_TYPE_6x00 (0x0000070)
#define CSR_HW_REV_TYPE_6x50 (0x0000080)
#define CSR_HW_REV_TYPE_6150 (0x0000084)
#define CSR_HW_REV_TYPE_6x05 (0x00000B0)
#define CSR_HW_REV_TYPE_6x30 CSR_HW_REV_TYPE_6x05
#define CSR_HW_REV_TYPE_6x35 CSR_HW_REV_TYPE_6x05
#define CSR_HW_REV_TYPE_2x30 (0x00000C0)
#define CSR_HW_REV_TYPE_2x00 (0x0000100)
#define CSR_HW_REV_TYPE_105 (0x0000110)
#define CSR_HW_REV_TYPE_135 (0x0000120)
#define CSR_HW_REV_TYPE_7265D (0x0000210)
#define CSR_HW_REV_TYPE_NONE (0x00001F0)
#define CSR_HW_REV_TYPE_QNJ (0x0000360)
#define CSR_HW_REV_TYPE_QNJ_B0 (0x0000364)
#define CSR_HW_REV_TYPE_QU_B0 (0x0000334)
#define CSR_HW_REV_TYPE_QU_C0 (0x0000338)
#define CSR_HW_REV_TYPE_QUZ (0x0000354)
#define CSR_HW_REV_TYPE_HR_CDB (0x0000340)
#define CSR_HW_REV_TYPE_SO (0x0000370)
#define CSR_HW_REV_TYPE_TY (0x0000420)
/* RF_ID value */
#define CSR_HW_RF_ID_TYPE_JF (0x00105100)
#define CSR_HW_RF_ID_TYPE_HR (0x0010A000)
#define CSR_HW_RF_ID_TYPE_HR1 (0x0010c100)
#define CSR_HW_RF_ID_TYPE_HRCDB (0x00109F00)
#define CSR_HW_RF_ID_TYPE_GF (0x0010D000)
#define CSR_HW_RF_ID_TYPE_GF4 (0x0010E000)
/* HW_RF CHIP STEP */
#define CSR_HW_RF_STEP(_val) (((_val) >> 8) & 0xF)
/* EEPROM REG */
#define CSR_EEPROM_REG_READ_VALID_MSK (0x00000001)
#define CSR_EEPROM_REG_BIT_CMD (0x00000002)
#define CSR_EEPROM_REG_MSK_ADDR (0x0000FFFC)
#define CSR_EEPROM_REG_MSK_DATA (0xFFFF0000)
/* EEPROM GP */
#define CSR_EEPROM_GP_VALID_MSK (0x00000007) /* signature */
#define CSR_EEPROM_GP_IF_OWNER_MSK (0x00000180)
#define CSR_EEPROM_GP_BAD_SIGNATURE_BOTH_EEP_AND_OTP (0x00000000)
#define CSR_EEPROM_GP_BAD_SIG_EEP_GOOD_SIG_OTP (0x00000001)
#define CSR_EEPROM_GP_GOOD_SIG_EEP_LESS_THAN_4K (0x00000002)
#define CSR_EEPROM_GP_GOOD_SIG_EEP_MORE_THAN_4K (0x00000004)
/* One-time-programmable memory general purpose reg */
#define CSR_OTP_GP_REG_DEVICE_SELECT (0x00010000) /* 0 - EEPROM, 1 - OTP */
#define CSR_OTP_GP_REG_OTP_ACCESS_MODE (0x00020000) /* 0 - absolute, 1 - relative */
#define CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK (0x00100000) /* bit 20 */
#define CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK (0x00200000) /* bit 21 */
/* GP REG */
#define CSR_GP_REG_POWER_SAVE_STATUS_MSK (0x03000000) /* bit 24/25 */
#define CSR_GP_REG_NO_POWER_SAVE (0x00000000)
#define CSR_GP_REG_MAC_POWER_SAVE (0x01000000)
#define CSR_GP_REG_PHY_POWER_SAVE (0x02000000)
#define CSR_GP_REG_POWER_SAVE_ERROR (0x03000000)
/* CSR GIO */
#define CSR_GIO_REG_VAL_L0S_DISABLED (0x00000002)
/*
* UCODE-DRIVER GP (general purpose) mailbox register 1
* Host driver and uCode write and/or read this register to communicate with
* each other.
* Bit fields:
* 4: UCODE_DISABLE
* Host sets this to request permanent halt of uCode, same as
* sending CARD_STATE command with "halt" bit set.
* 3: CT_KILL_EXIT
* Host sets this to request exit from CT_KILL state, i.e. host thinks
* device temperature is low enough to continue normal operation.
* 2: CMD_BLOCKED
* Host sets this during RF KILL power-down sequence (HW, SW, CT KILL)
* to release uCode to clear all Tx and command queues, enter
* unassociated mode, and power down.
* NOTE: Some devices also use HBUS_TARG_MBX_C register for this bit.
* 1: SW_BIT_RFKILL
* Host sets this when issuing CARD_STATE command to request
* device sleep.
* 0: MAC_SLEEP
* uCode sets this when preparing a power-saving power-down.
* uCode resets this when power-up is complete and SRAM is sane.
* NOTE: device saves internal SRAM data to host when powering down,
* and must restore this data after powering back up.
* MAC_SLEEP is the best indication that restore is complete.
* Later devices (5xxx/6xxx/1xxx) use non-volatile SRAM, and
* do not need to save/restore it.
*/
#define CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP (0x00000001)
#define CSR_UCODE_SW_BIT_RFKILL (0x00000002)
#define CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED (0x00000004)
#define CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT (0x00000008)
#define CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE (0x00000020)
/* GP Driver */
#define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_MSK (0x00000003)
#define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_3x3_HYB (0x00000000)
#define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_HYB (0x00000001)
#define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA (0x00000002)
#define CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6 (0x00000004)
#define CSR_GP_DRIVER_REG_BIT_6050_1x2 (0x00000008)
#define CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER (0x00000080)
/* GIO Chicken Bits (PCI Express bus link power management) */
#define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX (0x00800000)
#define CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER (0x20000000)
/* LED */
#define CSR_LED_BSM_CTRL_MSK (0xFFFFFFDF)
#define CSR_LED_REG_TURN_ON (0x60)
#define CSR_LED_REG_TURN_OFF (0x20)
/* ANA_PLL */
#define CSR50_ANA_PLL_CFG_VAL (0x00880300)
/* HPET MEM debug */
#define CSR_DBG_HPET_MEM_REG_VAL (0xFFFF0000)
/* DRAM INT TABLE */
#define CSR_DRAM_INT_TBL_ENABLE (1 << 31)
#define CSR_DRAM_INIT_TBL_WRITE_POINTER (1 << 28)
#define CSR_DRAM_INIT_TBL_WRAP_CHECK (1 << 27)
/*
* SHR target access (Shared block memory space)
*
* Shared internal registers can be accessed directly from PCI bus through SHR
* arbiter without need for the MAC HW to be powered up. This is possible due to
* indirect read/write via HEEP_CTRL_WRD_PCIEX_CTRL (0xEC) and
* HEEP_CTRL_WRD_PCIEX_DATA (0xF4) registers.
*
* Use iwl_write32()/iwl_read32() family to access these registers. The MAC HW
* need not be powered up so no "grab inc access" is required.
*/
/*
* Registers for accessing shared registers (e.g. SHR_APMG_GP1,
* SHR_APMG_XTAL_CFG). For example, to read from SHR_APMG_GP1 register (0x1DC),
* first, write to the control register:
* HEEP_CTRL_WRD_PCIEX_CTRL[15:0] = 0x1DC (offset of the SHR_APMG_GP1 register)
* HEEP_CTRL_WRD_PCIEX_CTRL[29:28] = 2 (read access)
* second, read from the data register HEEP_CTRL_WRD_PCIEX_DATA[31:0].
*
* To write the register, first, write to the data register
* HEEP_CTRL_WRD_PCIEX_DATA[31:0] and then:
* HEEP_CTRL_WRD_PCIEX_CTRL[15:0] = 0x1DC (offset of the SHR_APMG_GP1 register)
* HEEP_CTRL_WRD_PCIEX_CTRL[29:28] = 3 (write access)
*/
#define HEEP_CTRL_WRD_PCIEX_CTRL_REG (CSR_BASE+0x0ec)
#define HEEP_CTRL_WRD_PCIEX_DATA_REG (CSR_BASE+0x0f4)
/*
* HBUS (Host-side Bus)
*
* HBUS registers are mapped directly into PCI bus space, but are used
* to indirectly access device's internal memory or registers that
* may be powered-down.
*
* Use iwl_write_direct32()/iwl_read_direct32() family for these registers;
* host must "grab nic access" via CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ
* to make sure the MAC (uCode processor, etc.) is powered up for accessing
* internal resources.
*
* Do not use iwl_write32()/iwl_read32() family to access these registers;
* these provide only simple PCI bus access, without waking up the MAC.
*/
#define HBUS_BASE (0x400)
/*
* Registers for accessing device's internal SRAM memory (e.g. SCD SRAM
* structures, error log, event log, verifying uCode load).
* First write to address register, then read from or write to data register
* to complete the job. Once the address register is set up, accesses to
* data registers auto-increment the address by one dword.
* Bit usage for address registers (read or write):
* 0-31: memory address within device
*/
#define HBUS_TARG_MEM_RADDR (HBUS_BASE+0x00c)
#define HBUS_TARG_MEM_WADDR (HBUS_BASE+0x010)
#define HBUS_TARG_MEM_WDAT (HBUS_BASE+0x018)
#define HBUS_TARG_MEM_RDAT (HBUS_BASE+0x01c)
/* Mailbox C, used as workaround alternative to CSR_UCODE_DRV_GP1 mailbox */
#define HBUS_TARG_MBX_C (HBUS_BASE+0x030)
#define HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED (0x00000004)
/*
* Registers for accessing device's internal peripheral registers
* (e.g. SCD, BSM, etc.). First write to address register,
* then read from or write to data register to complete the job.
* Bit usage for address registers (read or write):
* 0-15: register address (offset) within device
* 24-25: (# bytes - 1) to read or write (e.g. 3 for dword)
*/
#define HBUS_TARG_PRPH_WADDR (HBUS_BASE+0x044)
#define HBUS_TARG_PRPH_RADDR (HBUS_BASE+0x048)
#define HBUS_TARG_PRPH_WDAT (HBUS_BASE+0x04c)
#define HBUS_TARG_PRPH_RDAT (HBUS_BASE+0x050)
/* Used to enable DBGM */
#define HBUS_TARG_TEST_REG (HBUS_BASE+0x05c)
/*
* Per-Tx-queue write pointer (index, really!)
* Indicates index to next TFD that driver will fill (1 past latest filled).
* Bit usage:
* 0-7: queue write index
* 11-8: queue selector
*/
#define HBUS_TARG_WRPTR (HBUS_BASE+0x060)
/**********************************************************
* CSR values
**********************************************************/
/*
* host interrupt timeout value
* used with setting interrupt coalescing timer
* the CSR_INT_COALESCING is an 8 bit register in 32-usec unit
*
* default interrupt coalescing timer is 64 x 32 = 2048 usecs
*/
#define IWL_HOST_INT_TIMEOUT_MAX (0xFF)
#define IWL_HOST_INT_TIMEOUT_DEF (0x40)
#define IWL_HOST_INT_TIMEOUT_MIN (0x0)
#define IWL_HOST_INT_OPER_MODE BIT(31)
/*****************************************************************************
* 7000/3000 series SHR DTS addresses *
*****************************************************************************/
/* Diode Results Register Structure: */
enum dtd_diode_reg {
DTS_DIODE_REG_DIG_VAL = 0x000000FF, /* bits [7:0] */
DTS_DIODE_REG_VREF_LOW = 0x0000FF00, /* bits [15:8] */
DTS_DIODE_REG_VREF_HIGH = 0x00FF0000, /* bits [23:16] */
DTS_DIODE_REG_VREF_ID = 0x03000000, /* bits [25:24] */
DTS_DIODE_REG_PASS_ONCE = 0x80000000, /* bits [31:31] */
DTS_DIODE_REG_FLAGS_MSK = 0xFF000000, /* bits [31:24] */
/* Those are the masks INSIDE the flags bit-field: */
DTS_DIODE_REG_FLAGS_VREFS_ID_POS = 0,
DTS_DIODE_REG_FLAGS_VREFS_ID = 0x00000003, /* bits [1:0] */
DTS_DIODE_REG_FLAGS_PASS_ONCE_POS = 7,
DTS_DIODE_REG_FLAGS_PASS_ONCE = 0x00000080, /* bits [7:7] */
};
/*****************************************************************************
* MSIX related registers *
*****************************************************************************/
#define CSR_MSIX_BASE (0x2000)
#define CSR_MSIX_FH_INT_CAUSES_AD (CSR_MSIX_BASE + 0x800)
#define CSR_MSIX_FH_INT_MASK_AD (CSR_MSIX_BASE + 0x804)
#define CSR_MSIX_HW_INT_CAUSES_AD (CSR_MSIX_BASE + 0x808)
#define CSR_MSIX_HW_INT_MASK_AD (CSR_MSIX_BASE + 0x80C)
#define CSR_MSIX_AUTOMASK_ST_AD (CSR_MSIX_BASE + 0x810)
#define CSR_MSIX_RX_IVAR_AD_REG (CSR_MSIX_BASE + 0x880)
#define CSR_MSIX_IVAR_AD_REG (CSR_MSIX_BASE + 0x890)
#define CSR_MSIX_PENDING_PBA_AD (CSR_MSIX_BASE + 0x1000)
#define CSR_MSIX_RX_IVAR(cause) (CSR_MSIX_RX_IVAR_AD_REG + (cause))
#define CSR_MSIX_IVAR(cause) (CSR_MSIX_IVAR_AD_REG + (cause))
#define MSIX_FH_INT_CAUSES_Q(q) (q)
/*
* Causes for the FH register interrupts
*/
enum msix_fh_int_causes {
MSIX_FH_INT_CAUSES_Q0 = BIT(0),
MSIX_FH_INT_CAUSES_Q1 = BIT(1),
MSIX_FH_INT_CAUSES_D2S_CH0_NUM = BIT(16),
MSIX_FH_INT_CAUSES_D2S_CH1_NUM = BIT(17),
MSIX_FH_INT_CAUSES_S2D = BIT(19),
MSIX_FH_INT_CAUSES_FH_ERR = BIT(21),
};
/* The low 16 bits are for rx data queue indication */
#define MSIX_FH_INT_CAUSES_DATA_QUEUE 0xffff
/*
* Causes for the HW register interrupts
*/
enum msix_hw_int_causes {
MSIX_HW_INT_CAUSES_REG_ALIVE = BIT(0),
MSIX_HW_INT_CAUSES_REG_WAKEUP = BIT(1),
MSIX_HW_INT_CAUSES_REG_IML = BIT(1),
MSIX_HW_INT_CAUSES_REG_RESET_DONE = BIT(2),
MSIX_HW_INT_CAUSES_REG_SW_ERR_BZ = BIT(5),
MSIX_HW_INT_CAUSES_REG_CT_KILL = BIT(6),
MSIX_HW_INT_CAUSES_REG_RF_KILL = BIT(7),
MSIX_HW_INT_CAUSES_REG_PERIODIC = BIT(8),
MSIX_HW_INT_CAUSES_REG_SW_ERR = BIT(25),
MSIX_HW_INT_CAUSES_REG_SCD = BIT(26),
MSIX_HW_INT_CAUSES_REG_FH_TX = BIT(27),
MSIX_HW_INT_CAUSES_REG_HW_ERR = BIT(29),
MSIX_HW_INT_CAUSES_REG_HAP = BIT(30),
};
#define MSIX_MIN_INTERRUPT_VECTORS 2
#define MSIX_AUTO_CLEAR_CAUSE 0
#define MSIX_NON_AUTO_CLEAR_CAUSE BIT(7)
/*****************************************************************************
* HW address related registers *
*****************************************************************************/
#define CSR_ADDR_BASE(trans) ((trans)->cfg->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)
#define CSR_MAC_ADDR1_STRAP(trans) (CSR_ADDR_BASE(trans) + 0x0c)
#endif /* !__iwl_csr_h__ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,74 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2018-2021 Intel Corporation
*/
#ifndef __iwl_dbg_tlv_h__
#define __iwl_dbg_tlv_h__
#include <linux/device.h>
#include <linux/types.h>
#include <fw/file.h>
#include <fw/api/dbg-tlv.h>
/**
* struct iwl_dbg_tlv_node - debug TLV node
* @list: list of &struct iwl_dbg_tlv_node
* @tlv: debug TLV
*/
struct iwl_dbg_tlv_node {
struct list_head list;
struct iwl_ucode_tlv tlv;
};
/**
* union iwl_dbg_tlv_tp_data - data that is given in a time point
* @fw_pkt: a packet received from the FW
*/
union iwl_dbg_tlv_tp_data {
struct iwl_rx_packet *fw_pkt;
};
/**
* struct iwl_dbg_tlv_time_point_data
* @trig_list: list of triggers
* @active_trig_list: list of active triggers
* @hcmd_list: list of host commands
* @config_list: list of configuration
*/
struct iwl_dbg_tlv_time_point_data {
struct list_head trig_list;
struct list_head active_trig_list;
struct list_head hcmd_list;
struct list_head config_list;
};
struct iwl_trans;
struct iwl_fw_runtime;
void iwl_dbg_tlv_load_bin(struct device *dev, struct iwl_trans *trans);
void iwl_dbg_tlv_free(struct iwl_trans *trans);
void iwl_dbg_tlv_alloc(struct iwl_trans *trans, const struct iwl_ucode_tlv *tlv,
bool ext);
void iwl_dbg_tlv_init(struct iwl_trans *trans);
void _iwl_dbg_tlv_time_point(struct iwl_fw_runtime *fwrt,
enum iwl_fw_ini_time_point tp_id,
union iwl_dbg_tlv_tp_data *tp_data,
bool sync);
static inline void iwl_dbg_tlv_time_point(struct iwl_fw_runtime *fwrt,
enum iwl_fw_ini_time_point tp_id,
union iwl_dbg_tlv_tp_data *tp_data)
{
_iwl_dbg_tlv_time_point(fwrt, tp_id, tp_data, false);
}
static inline void iwl_dbg_tlv_time_point_sync(struct iwl_fw_runtime *fwrt,
enum iwl_fw_ini_time_point tp_id,
union iwl_dbg_tlv_tp_data *tp_data)
{
_iwl_dbg_tlv_time_point(fwrt, tp_id, tp_data, true);
}
void iwl_dbg_tlv_del_timers(struct iwl_trans *trans);
#endif /* __iwl_dbg_tlv_h__*/

View File

@ -0,0 +1,163 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2005-2011, 2021 Intel Corporation
*/
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/export.h>
#if defined(CONFIG_IWLWIFI_DEBUG)
#include <linux/net.h>
#endif
#include "iwl-drv.h"
#include "iwl-debug.h"
#include "iwl-modparams.h"
#include "iwl-devtrace.h"
#if defined(__FreeBSD__)
#if defined(CONFIG_IWLWIFI_DEBUG)
#include <sys/systm.h> /* hexdump(9) */
#include <linux/preempt.h>
#endif
#endif
#if defined(__linux__)
#define __iwl_fn(fn) \
void __iwl_ ##fn(struct device *dev, const char *fmt, ...) \
{ \
struct va_format vaf = { \
.fmt = fmt, \
}; \
va_list args; \
\
va_start(args, fmt); \
vaf.va = &args; \
dev_ ##fn(dev, "%pV", &vaf); \
trace_iwlwifi_ ##fn(&vaf); \
va_end(args); \
}
#elif defined(__FreeBSD__)
#define __iwl_fn(fn) \
void __iwl_ ##fn(struct device *dev, const char *fmt, ...) \
{ \
struct va_format vaf = { \
.fmt = fmt, \
}; \
va_list args; \
char *str; \
\
va_start(args, fmt); \
vaf.va = &args; \
vasprintf(&str, M_KMALLOC, fmt, args); \
dev_ ##fn(dev, "%s", str); \
trace_iwlwifi_ ##fn(&vaf); \
free(str, M_KMALLOC); \
va_end(args); \
}
#endif
__iwl_fn(warn)
IWL_EXPORT_SYMBOL(__iwl_warn);
__iwl_fn(info)
IWL_EXPORT_SYMBOL(__iwl_info);
__iwl_fn(crit)
IWL_EXPORT_SYMBOL(__iwl_crit);
void __iwl_err(struct device *dev, enum iwl_err_mode mode, const char *fmt, ...)
{
struct va_format vaf = {
.fmt = fmt,
};
va_list args, args2;
va_start(args, fmt);
switch (mode) {
case IWL_ERR_MODE_RATELIMIT:
if (net_ratelimit())
break;
fallthrough;
case IWL_ERR_MODE_REGULAR:
case IWL_ERR_MODE_RFKILL:
va_copy(args2, args);
vaf.va = &args2;
#if defined(__linux_)
if (mode == IWL_ERR_MODE_RFKILL)
dev_err(dev, "(RFKILL) %pV", &vaf);
else
dev_err(dev, "%pV", &vaf);
#elif defined(__FreeBSD__)
char *str;
vasprintf(&str, M_KMALLOC, fmt, args2);
dev_err(dev, "%s%s", (mode == IWL_ERR_MODE_RFKILL) ? "(RFKILL)" : "", str);
free(str, M_KMALLOC);
#endif
va_end(args2);
break;
default:
break;
}
trace_iwlwifi_err(&vaf);
va_end(args);
}
IWL_EXPORT_SYMBOL(__iwl_err);
#if defined(CONFIG_IWLWIFI_DEBUG) || defined(CONFIG_IWLWIFI_DEVICE_TRACING)
#ifdef CONFIG_IWLWIFI_DEBUG
bool
iwl_have_debug_level(enum iwl_dl level)
{
return (iwlwifi_mod_params.debug_level & level || level == IWL_DL_ANY);
}
/* Passing the iwl_drv * in seems pointless. */
void
iwl_print_hex_dump(void *drv __unused, enum iwl_dl level,
const char *prefix, uint8_t *data, size_t len)
{
/* Given we have a level, check for it. */
if (!iwl_have_debug_level(level))
return;
#if defined(__linux_)
/* XXX I am cluseless in my editor. pcie/trans.c to the rescue. */
print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET,
32, 4, data, len, 0);
#elif defined(__FreeBSD__)
hexdump(data, len, prefix, 0);
#endif
}
#endif
void __iwl_dbg(struct device *dev,
u32 level, bool limit, const char *function,
const char *fmt, ...)
{
struct va_format vaf = {
.fmt = fmt,
};
va_list args;
va_start(args, fmt);
vaf.va = &args;
#if defined(CONFIG_IWLWIFI_DEBUG)
if (iwl_have_debug_level(level) &&
(!limit || net_ratelimit())) {
#if defined(__linux_)
dev_printk(KERN_DEBUG, dev, "%s %pV", function, &vaf);
#elif defined(__FreeBSD__)
char *str;
vasprintf(&str, M_KMALLOC, fmt, args);
dev_printk(KERN_DEBUG, dev, "%d %u %s %s",
curthread->td_tid, (unsigned int)ticks, function, str);
free(str, M_KMALLOC);
#endif
}
#endif
trace_iwlwifi_dbg(level, function, &vaf);
va_end(args);
}
IWL_EXPORT_SYMBOL(__iwl_dbg);
#endif

View File

@ -0,0 +1,193 @@
/*-
* Copyright (c) 2020-2021 The FreeBSD Foundation
*
* This software was developed by Björn Zeeb under sponsorship from
* the FreeBSD Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef _IWL_DEBUG_H
#define _IWL_DEBUG_H
#if defined(__FreeBSD__)
#ifdef CONFIG_IWLWIFI_DEBUG
#include <sys/types.h>
#endif
#endif
#include <linux/device.h>
enum iwl_dl {
IWL_DL_ASSOC = 0x00000001,
IWL_DL_CALIB = 0x00000002,
IWL_DL_COEX = 0x00000004,
IWL_DL_WOWLAN = 0x00000008,
IWL_DL_DROP = 0x00000010,
IWL_DL_EEPROM = 0x00000020,
IWL_DL_FW = 0x00000040,
/* = 0x00000080, */
IWL_DL_HC = 0x00000100,
IWL_DL_HT = 0x00000200,
IWL_DL_INFO = 0x00000400,
IWL_DL_ISR = 0x00000800,
IWL_DL_LAR = 0x00001000,
IWL_DL_MAC80211 = 0x00002000,
IWL_DL_POWER = 0x00004000,
IWL_DL_QUOTA = 0x00008000,
IWL_DL_RADIO = 0x00010000,
IWL_DL_RATE = 0x00020000,
IWL_DL_RF_KILL = 0x00040000,
IWL_DL_RX = 0x00080000,
IWL_DL_SCAN = 0x00100000,
IWL_DL_STATS = 0x00200000,
/* = 0x00400000, */
IWL_DL_TDLS = 0x00800000,
IWL_DL_TE = 0x01000000,
IWL_DL_TEMP = 0x02000000,
IWL_DL_TPT = 0x04000000,
IWL_DL_TX = 0x08000000,
IWL_DL_TX_QUEUES = 0x10000000,
IWL_DL_TX_REPLY = 0x20000000,
IWL_DL_WEP = 0x40000000,
IWL_DL_PCI_RW = 0x80000000,
IWL_DL_ANY = 0x7fffffff,
};
enum iwl_err_mode {
IWL_ERR_MODE_RATELIMIT,
IWL_ERR_MODE_REGULAR,
IWL_ERR_MODE_RFKILL, /* XXX we do not pass that from anywhere? */
};
void __iwl_crit(struct device *, const char *, ...);
void __iwl_info(struct device *, const char *, ...);
void __iwl_warn(struct device *, const char *, ...);
void __iwl_err(struct device *, enum iwl_err_mode, const char *, ...);
#define IWL_CRIT(_subsys, _fmt, ...) \
__iwl_crit((_subsys)->dev, (_fmt), ##__VA_ARGS__)
#define IWL_INFO(_subsys, _fmt, ...) \
__iwl_info((_subsys)->dev, (_fmt), ##__VA_ARGS__)
#define IWL_WARN(_subsys, _fmt, ...) \
__iwl_warn((_subsys)->dev, (_fmt), ##__VA_ARGS__)
/* XXX Not sure what the two bools are good for if never passed. */
#define __IWL_ERR_DEV(_dev, _mode, _fmt, ...) \
__iwl_err((_dev), IWL_ERR_MODE_REGULAR, _fmt, ##__VA_ARGS__)
#define IWL_ERR_DEV(_dev, _fmt, ...) \
__IWL_ERR_DEV(_dev, IWL_ERR_MODE_REGULAR, _fmt, ##__VA_ARGS__)
#define IWL_ERR(_subsys, _fmt, ...) \
IWL_ERR_DEV((_subsys)->dev, _fmt, ##__VA_ARGS__)
#define IWL_ERR_LIMIT(_subsys, _fmt, ...) \
__IWL_ERR_DEV((_subsys)->dev, IWL_ERR_MODE_RATELIMIT, \
_fmt, ##__VA_ARGS__)
#define iwl_print_hex_error(_subsys, _pkt, _n) /* XXX-BZ TODO */
#ifdef CONFIG_IWLWIFI_DEBUG
bool iwl_have_debug_level(enum iwl_dl);
void iwl_print_hex_dump(void *, enum iwl_dl, const char *, uint8_t *, size_t);
void __iwl_dbg(struct device *, u32, bool, const char *, const char *fmt, ...);
#define IWL_DPRINTF_DEV(_dev, _e, _fmt, ...) \
__iwl_dbg((_dev), (_e), false, __func__, (_fmt), ##__VA_ARGS__)
#define IWL_DPRINTF(_subsys, _e, _fmt, ...) \
IWL_DPRINTF_DEV((_subsys)->dev, (_e), (_fmt), ##__VA_ARGS__)
#else /* !CONFIG_IWLWIFI_DEBUG */
#define IWL_DPRINTF_DEV(_dev, _e, _fmt, ...)
#define IWL_DPRINTF(_subsys, _e, _fmt, ...)
#endif /* CONFIG_IWLWIFI_DEBUG */
#define IWL_DEBUG_ASSOC(_subsys, _fmt, ...) \
IWL_DPRINTF((_subsys), IWL_DL_ASSOC, (_fmt), ##__VA_ARGS__)
#define IWL_DEBUG_CALIB(_subsys, _fmt, ...) \
IWL_DPRINTF((_subsys), IWL_DL_CALIB, (_fmt), ##__VA_ARGS__)
#define IWL_DEBUG_COEX(_subsys, _fmt, ...) \
IWL_DPRINTF((_subsys), IWL_DL_COEX, (_fmt), ##__VA_ARGS__)
#define IWL_DEBUG_DEV(_dev, _level, _fmt, ...) \
IWL_DPRINTF_DEV((_dev), (_level), (_fmt), ##__VA_ARGS__)
#define IWL_DEBUG_DROP(_subsys, _fmt, ...) \
IWL_DPRINTF((_subsys), IWL_DL_DROP, (_fmt), ##__VA_ARGS__)
#define IWL_DEBUG_EEPROM(_dev, _fmt, ...) \
IWL_DPRINTF_DEV((_dev), IWL_DL_EEPROM, (_fmt), ##__VA_ARGS__)
#define IWL_DEBUG_FW(_subsys, _fmt, ...) \
IWL_DPRINTF((_subsys), IWL_DL_FW, (_fmt), ##__VA_ARGS__)
#define IWL_DEBUG_FW_INFO(_subsys, _fmt, ...) \
IWL_DPRINTF((_subsys), IWL_DL_FW | IWL_DL_INFO, (_fmt), ##__VA_ARGS__)
#define IWL_DEBUG_HC(_subsys, _fmt, ...) \
IWL_DPRINTF((_subsys), IWL_DL_HC, (_fmt), ##__VA_ARGS__)
#define IWL_DEBUG_HT(_subsys, _fmt, ...) \
IWL_DPRINTF((_subsys), IWL_DL_HT, (_fmt), ##__VA_ARGS__)
#define IWL_DEBUG_INFO(_subsys, _fmt, ...) \
IWL_DPRINTF((_subsys), IWL_DL_INFO, (_fmt), ##__VA_ARGS__)
#define IWL_DEBUG_ISR(_subsys, _fmt, ...) \
IWL_DPRINTF((_subsys), IWL_DL_ISR, (_fmt), ##__VA_ARGS__)
#define IWL_DEBUG_LAR(_subsys, _fmt, ...) \
IWL_DPRINTF((_subsys), IWL_DL_LAR, (_fmt), ##__VA_ARGS__)
#define IWL_DEBUG_MAC80211(_subsys, _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_QUOTA(_subsys, _fmt, ...) \
IWL_DPRINTF((_subsys), IWL_DL_QUOTA, (_fmt), ##__VA_ARGS__)
#define IWL_DEBUG_RADIO(_subsys, _fmt, ...) \
IWL_DPRINTF((_subsys), IWL_DL_RADIO, (_fmt), ##__VA_ARGS__)
#define IWL_DEBUG_RATE(_subsys, _fmt, ...) \
IWL_DPRINTF((_subsys), IWL_DL_RATE, (_fmt), ##__VA_ARGS__)
#define IWL_DEBUG_RF_KILL(_subsys, _fmt, ...) \
IWL_DPRINTF((_subsys), IWL_DL_RF_KILL, (_fmt), ##__VA_ARGS__)
#define IWL_DEBUG_RX(_subsys, _fmt, ...) \
IWL_DPRINTF((_subsys), IWL_DL_RX, (_fmt), ##__VA_ARGS__)
#define IWL_DEBUG_SCAN(_subsys, _fmt, ...) \
IWL_DPRINTF((_subsys), IWL_DL_SCAN, (_fmt), ##__VA_ARGS__)
#define IWL_DEBUG_STATS(_subsys, _fmt, ...) \
IWL_DPRINTF((_subsys), IWL_DL_STATS, (_fmt), ##__VA_ARGS__)
#define IWL_DEBUG_STATS_LIMIT(_subsys, _fmt, ...) \
IWL_DPRINTF((_subsys), IWL_DL_STATS, (_fmt), ##__VA_ARGS__)
#define IWL_DEBUG_TDLS(_subsys, _fmt, ...) \
IWL_DPRINTF((_subsys), IWL_DL_TDLS, (_fmt), ##__VA_ARGS__)
#define IWL_DEBUG_TE(_subsys, _fmt, ...) \
IWL_DPRINTF((_subsys), IWL_DL_TE, (_fmt), ##__VA_ARGS__)
#define IWL_DEBUG_TEMP(_subsys, _fmt, ...) \
IWL_DPRINTF((_subsys), IWL_DL_TEMP, (_fmt), ##__VA_ARGS__)
#define IWL_DEBUG_TPT(_subsys, _fmt, ...) \
IWL_DPRINTF((_subsys), IWL_DL_TPT, (_fmt), ##__VA_ARGS__)
#define IWL_DEBUG_TX(_subsys, _fmt, ...) \
IWL_DPRINTF((_subsys), IWL_DL_TX, (_fmt), ##__VA_ARGS__)
#define IWL_DEBUG_TX_QUEUES(_subsys, _fmt, ...) \
IWL_DPRINTF((_subsys), IWL_DL_TX_QUEUES, (_fmt), ##__VA_ARGS__)
#define IWL_DEBUG_TX_REPLY(_subsys, _fmt, ...) \
IWL_DPRINTF((_subsys), IWL_DL_TX_REPLY, (_fmt), ##__VA_ARGS__)
#define IWL_DEBUG_WEP(_subsys, _fmt, ...) \
IWL_DPRINTF((_subsys), IWL_DL_WEP, (_fmt), ##__VA_ARGS__)
#define IWL_DEBUG_WOWLAN(_subsys, _fmt, ...) \
IWL_DPRINTF((_subsys), IWL_DL_WOWLAN, (_fmt), ##__VA_ARGS__)
#define IWL_DEBUG_PCI_RW(_subsys, _fmt, ...) \
IWL_DPRINTF((_subsys), IWL_DL_PCI_RW, (_fmt), ##__VA_ARGS__)
#endif /* _IWL_DEBUG_H */

View File

@ -0,0 +1,82 @@
/*-
* Copyright (c) 2021 The FreeBSD Foundation
*
* This software was developed by Björn Zeeb under sponsorship from
* the FreeBSD Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "iwl-devtrace.h"
#include <sys/sdt.h>
SDT_PROVIDER_DEFINE(iwlwifi);
SDT_PROBE_DEFINE4(iwlwifi, trace, dev_hcmd, ,
"const struct device *dev",
"struct iwl_host_cmd *", "uint16_t",
"struct iwl_cmd_header_wide *");
void
trace_iwlwifi_dev_hcmd(const struct device *dev,
struct iwl_host_cmd *cmd, uint16_t cmd_size,
struct iwl_cmd_header_wide *hdr_wide)
{
SDT_PROBE4(iwlwifi, trace, dev_hcmd, ,
dev, cmd, cmd_size, hdr_wide);
}
SDT_PROBE_DEFINE4(iwlwifi, trace, dev_rx, ,
"const struct device *dev",
"const struct iwl_trans *",
"struct iwl_rx_packet *", "size_t");
void
trace_iwlwifi_dev_rx(const struct device *dev,
const struct iwl_trans *trans,
struct iwl_rx_packet *pkt, size_t len)
{
SDT_PROBE4(iwlwifi, trace, dev_rx, ,
dev, trans, pkt, len);
}
SDT_PROBE_DEFINE4(iwlwifi, trace, dev_rx_data, ,
"const struct device *dev",
"const struct iwl_trans *",
"struct iwl_rx_packet *", "size_t");
void
trace_iwlwifi_dev_rx_data(const struct device *dev,
const struct iwl_trans *trans,
struct iwl_rx_packet *pkt, size_t len)
{
SDT_PROBE4(iwlwifi, trace, dev_rx_data, ,
dev, trans, pkt, len);
}

View File

@ -0,0 +1,70 @@
/*-
* Copyright (c) 2020-2021 The FreeBSD Foundation
*
* This software was developed by Björn Zeeb under sponsorship from
* the FreeBSD Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef _IWL_DEVTRACE_H
#define _IWL_DEVTRACE_H
#include <linux/types.h>
#include <linux/device.h>
#include "iwl-trans.h"
void trace_iwlwifi_dev_hcmd(const struct device *,
struct iwl_host_cmd *, uint16_t,
struct iwl_cmd_header_wide *);
void trace_iwlwifi_dev_rx(const struct device *,
const struct iwl_trans *,
struct iwl_rx_packet *, size_t);
void trace_iwlwifi_dev_rx_data(const struct device *,
const struct iwl_trans *,
struct iwl_rx_packet *, size_t);
#define trace_iwlwifi_dev_ict_read(...)
#define trace_iwlwifi_dev_ioread32(...)
#define trace_iwlwifi_dev_ioread_prph32(...)
#define trace_iwlwifi_dev_iowrite32(...)
#define trace_iwlwifi_dev_iowrite64(...)
#define trace_iwlwifi_dev_iowrite8(...)
#define trace_iwlwifi_dev_iowrite_prph32(...)
#define trace_iwlwifi_dev_iowrite_prph64(...)
#define trace_iwlwifi_dev_irq(...)
#define trace_iwlwifi_dev_irq_msix(...)
#define trace_iwlwifi_dev_tx(...)
#define trace_iwlwifi_dev_tx_tb(...)
#define trace_iwlwifi_crit(...)
#define trace_iwlwifi_dbg(...)
#define trace_iwlwifi_err(...)
#define trace_iwlwifi_info(...)
#define trace_iwlwifi_warn(...)
#endif /* _IWL_DEVTRACE_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,92 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2005-2014, 2020-2021 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
*/
#ifndef __iwl_drv_h__
#define __iwl_drv_h__
#include <linux/export.h>
/* for all modules */
#define DRV_NAME "iwlwifi"
/* radio config bits (actual values from NVM definition) */
#define NVM_RF_CFG_DASH_MSK(x) (x & 0x3) /* bits 0-1 */
#define NVM_RF_CFG_STEP_MSK(x) ((x >> 2) & 0x3) /* bits 2-3 */
#define NVM_RF_CFG_TYPE_MSK(x) ((x >> 4) & 0x3) /* bits 4-5 */
#define NVM_RF_CFG_PNUM_MSK(x) ((x >> 6) & 0x3) /* bits 6-7 */
#define NVM_RF_CFG_TX_ANT_MSK(x) ((x >> 8) & 0xF) /* bits 8-11 */
#define NVM_RF_CFG_RX_ANT_MSK(x) ((x >> 12) & 0xF) /* bits 12-15 */
#define EXT_NVM_RF_CFG_FLAVOR_MSK(x) ((x) & 0xF)
#define EXT_NVM_RF_CFG_DASH_MSK(x) (((x) >> 4) & 0xF)
#define EXT_NVM_RF_CFG_STEP_MSK(x) (((x) >> 8) & 0xF)
#define EXT_NVM_RF_CFG_TYPE_MSK(x) (((x) >> 12) & 0xFFF)
#define EXT_NVM_RF_CFG_TX_ANT_MSK(x) (((x) >> 24) & 0xF)
#define EXT_NVM_RF_CFG_RX_ANT_MSK(x) (((x) >> 28) & 0xF)
/**
* DOC: Driver system flows - drv component
*
* This component implements the system flows such as bus enumeration, bus
* removal. Bus dependent parts of system flows (such as iwl_pci_probe) are in
* bus specific files (transport files). This is the code that is common among
* different buses.
*
* This component is also in charge of managing the several implementations of
* the wifi flows: it will allow to have several fw API implementation. These
* different implementations will differ in the way they implement mac80211's
* handlers too.
* The init flow wrt to the drv component looks like this:
* 1) The bus specific component is called from module_init
* 2) The bus specific component registers the bus driver
* 3) The bus driver calls the probe function
* 4) The bus specific component configures the bus
* 5) The bus specific component calls to the drv bus agnostic part
* (iwl_drv_start)
* 6) iwl_drv_start fetches the fw ASYNC, iwl_req_fw_callback
* 7) iwl_req_fw_callback parses the fw file
* 8) iwl_req_fw_callback starts the wifi implementation to matches the fw
*/
struct iwl_drv;
struct iwl_trans;
struct iwl_cfg;
/**
* iwl_drv_start - start the drv
*
* @trans_ops: the ops of the transport
*
* starts the driver: fetches the firmware. This should be called by bus
* specific system flows implementations. For example, the bus specific probe
* function should do bus related operations only, and then call to this
* function. It returns the driver object or %NULL if an error occurred.
*/
struct iwl_drv *iwl_drv_start(struct iwl_trans *trans);
/**
* iwl_drv_stop - stop the drv
*
* @drv:
*
* Stop the driver. This should be called by bus specific system flows
* implementations. For example, the bus specific remove function should first
* call this function and then do the bus related operations only.
*/
void iwl_drv_stop(struct iwl_drv *drv);
/*
* exported symbol management
*
* The driver can be split into multiple modules, in which case some symbols
* must be exported for the sub-modules. However, if it's not split and
* everything is built-in, then we can avoid that.
*/
#ifdef CONFIG_IWLWIFI_OPMODE_MODULAR
#define IWL_EXPORT_SYMBOL(sym) EXPORT_SYMBOL_GPL(sym)
#else
#define IWL_EXPORT_SYMBOL(sym)
#endif
#endif /* __iwl_drv_h__ */

View File

@ -0,0 +1,879 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2005-2014, 2018-2020 Intel Corporation
* Copyright (C) 2015 Intel Mobile Communications GmbH
*/
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/export.h>
#include "iwl-drv.h"
#include "iwl-modparams.h"
#include "iwl-eeprom-parse.h"
#if IS_ENABLED(CONFIG_IWLDVM)
/* EEPROM offset definitions */
/* indirect access definitions */
#define ADDRESS_MSK 0x0000FFFF
#define INDIRECT_TYPE_MSK 0x000F0000
#define INDIRECT_HOST 0x00010000
#define INDIRECT_GENERAL 0x00020000
#define INDIRECT_REGULATORY 0x00030000
#define INDIRECT_CALIBRATION 0x00040000
#define INDIRECT_PROCESS_ADJST 0x00050000
#define INDIRECT_OTHERS 0x00060000
#define INDIRECT_TXP_LIMIT 0x00070000
#define INDIRECT_TXP_LIMIT_SIZE 0x00080000
#define INDIRECT_ADDRESS 0x00100000
/* corresponding link offsets in EEPROM */
#define EEPROM_LINK_HOST (2*0x64)
#define EEPROM_LINK_GENERAL (2*0x65)
#define EEPROM_LINK_REGULATORY (2*0x66)
#define EEPROM_LINK_CALIBRATION (2*0x67)
#define EEPROM_LINK_PROCESS_ADJST (2*0x68)
#define EEPROM_LINK_OTHERS (2*0x69)
#define EEPROM_LINK_TXP_LIMIT (2*0x6a)
#define EEPROM_LINK_TXP_LIMIT_SIZE (2*0x6b)
/* General */
#define EEPROM_DEVICE_ID (2*0x08) /* 2 bytes */
#define EEPROM_SUBSYSTEM_ID (2*0x0A) /* 2 bytes */
#define EEPROM_MAC_ADDRESS (2*0x15) /* 6 bytes */
#define EEPROM_BOARD_REVISION (2*0x35) /* 2 bytes */
#define EEPROM_BOARD_PBA_NUMBER (2*0x3B+1) /* 9 bytes */
#define EEPROM_VERSION (2*0x44) /* 2 bytes */
#define EEPROM_SKU_CAP (2*0x45) /* 2 bytes */
#define EEPROM_OEM_MODE (2*0x46) /* 2 bytes */
#define EEPROM_RADIO_CONFIG (2*0x48) /* 2 bytes */
#define EEPROM_NUM_MAC_ADDRESS (2*0x4C) /* 2 bytes */
/* calibration */
struct iwl_eeprom_calib_hdr {
u8 version;
u8 pa_type;
__le16 voltage;
} __packed;
#define EEPROM_CALIB_ALL (INDIRECT_ADDRESS | INDIRECT_CALIBRATION)
#define EEPROM_XTAL ((2*0x128) | EEPROM_CALIB_ALL)
/* temperature */
#define EEPROM_KELVIN_TEMPERATURE ((2*0x12A) | EEPROM_CALIB_ALL)
#define EEPROM_RAW_TEMPERATURE ((2*0x12B) | EEPROM_CALIB_ALL)
/* SKU Capabilities (actual values from EEPROM definition) */
enum eeprom_sku_bits {
EEPROM_SKU_CAP_BAND_24GHZ = BIT(4),
EEPROM_SKU_CAP_BAND_52GHZ = BIT(5),
EEPROM_SKU_CAP_11N_ENABLE = BIT(6),
EEPROM_SKU_CAP_AMT_ENABLE = BIT(7),
EEPROM_SKU_CAP_IPAN_ENABLE = BIT(8)
};
/* radio config bits (actual values from EEPROM definition) */
#define EEPROM_RF_CFG_TYPE_MSK(x) (x & 0x3) /* bits 0-1 */
#define EEPROM_RF_CFG_STEP_MSK(x) ((x >> 2) & 0x3) /* bits 2-3 */
#define EEPROM_RF_CFG_DASH_MSK(x) ((x >> 4) & 0x3) /* bits 4-5 */
#define EEPROM_RF_CFG_PNUM_MSK(x) ((x >> 6) & 0x3) /* bits 6-7 */
#define EEPROM_RF_CFG_TX_ANT_MSK(x) ((x >> 8) & 0xF) /* bits 8-11 */
#define EEPROM_RF_CFG_RX_ANT_MSK(x) ((x >> 12) & 0xF) /* bits 12-15 */
/*
* EEPROM bands
* These are the channel numbers from each band in the order
* that they are stored in the EEPROM band information. Note
* that EEPROM bands aren't the same as mac80211 bands, and
* there are even special "ht40 bands" in the EEPROM.
*/
static const u8 iwl_eeprom_band_1[14] = { /* 2.4 GHz */
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
};
static const u8 iwl_eeprom_band_2[] = { /* 4915-5080MHz */
183, 184, 185, 187, 188, 189, 192, 196, 7, 8, 11, 12, 16
};
static const u8 iwl_eeprom_band_3[] = { /* 5170-5320MHz */
34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64
};
static const u8 iwl_eeprom_band_4[] = { /* 5500-5700MHz */
100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140
};
static const u8 iwl_eeprom_band_5[] = { /* 5725-5825MHz */
145, 149, 153, 157, 161, 165
};
static const u8 iwl_eeprom_band_6[] = { /* 2.4 ht40 channel */
1, 2, 3, 4, 5, 6, 7
};
static const u8 iwl_eeprom_band_7[] = { /* 5.2 ht40 channel */
36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157
};
#define IWL_NUM_CHANNELS (ARRAY_SIZE(iwl_eeprom_band_1) + \
ARRAY_SIZE(iwl_eeprom_band_2) + \
ARRAY_SIZE(iwl_eeprom_band_3) + \
ARRAY_SIZE(iwl_eeprom_band_4) + \
ARRAY_SIZE(iwl_eeprom_band_5))
/* rate data (static) */
static struct ieee80211_rate iwl_cfg80211_rates[] = {
{ .bitrate = 1 * 10, .hw_value = 0, .hw_value_short = 0, },
{ .bitrate = 2 * 10, .hw_value = 1, .hw_value_short = 1,
.flags = IEEE80211_RATE_SHORT_PREAMBLE, },
{ .bitrate = 5.5 * 10, .hw_value = 2, .hw_value_short = 2,
.flags = IEEE80211_RATE_SHORT_PREAMBLE, },
{ .bitrate = 11 * 10, .hw_value = 3, .hw_value_short = 3,
.flags = IEEE80211_RATE_SHORT_PREAMBLE, },
{ .bitrate = 6 * 10, .hw_value = 4, .hw_value_short = 4, },
{ .bitrate = 9 * 10, .hw_value = 5, .hw_value_short = 5, },
{ .bitrate = 12 * 10, .hw_value = 6, .hw_value_short = 6, },
{ .bitrate = 18 * 10, .hw_value = 7, .hw_value_short = 7, },
{ .bitrate = 24 * 10, .hw_value = 8, .hw_value_short = 8, },
{ .bitrate = 36 * 10, .hw_value = 9, .hw_value_short = 9, },
{ .bitrate = 48 * 10, .hw_value = 10, .hw_value_short = 10, },
{ .bitrate = 54 * 10, .hw_value = 11, .hw_value_short = 11, },
};
#define RATES_24_OFFS 0
#define N_RATES_24 ARRAY_SIZE(iwl_cfg80211_rates)
#define RATES_52_OFFS 4
#define N_RATES_52 (N_RATES_24 - RATES_52_OFFS)
/* EEPROM reading functions */
static u16 iwl_eeprom_query16(const u8 *eeprom, size_t eeprom_size, int offset)
{
if (WARN_ON(offset + sizeof(u16) > eeprom_size))
return 0;
return le16_to_cpup((__le16 *)(eeprom + offset));
}
static u32 eeprom_indirect_address(const u8 *eeprom, size_t eeprom_size,
u32 address)
{
u16 offset = 0;
if ((address & INDIRECT_ADDRESS) == 0)
return address;
switch (address & INDIRECT_TYPE_MSK) {
case INDIRECT_HOST:
offset = iwl_eeprom_query16(eeprom, eeprom_size,
EEPROM_LINK_HOST);
break;
case INDIRECT_GENERAL:
offset = iwl_eeprom_query16(eeprom, eeprom_size,
EEPROM_LINK_GENERAL);
break;
case INDIRECT_REGULATORY:
offset = iwl_eeprom_query16(eeprom, eeprom_size,
EEPROM_LINK_REGULATORY);
break;
case INDIRECT_TXP_LIMIT:
offset = iwl_eeprom_query16(eeprom, eeprom_size,
EEPROM_LINK_TXP_LIMIT);
break;
case INDIRECT_TXP_LIMIT_SIZE:
offset = iwl_eeprom_query16(eeprom, eeprom_size,
EEPROM_LINK_TXP_LIMIT_SIZE);
break;
case INDIRECT_CALIBRATION:
offset = iwl_eeprom_query16(eeprom, eeprom_size,
EEPROM_LINK_CALIBRATION);
break;
case INDIRECT_PROCESS_ADJST:
offset = iwl_eeprom_query16(eeprom, eeprom_size,
EEPROM_LINK_PROCESS_ADJST);
break;
case INDIRECT_OTHERS:
offset = iwl_eeprom_query16(eeprom, eeprom_size,
EEPROM_LINK_OTHERS);
break;
default:
WARN_ON(1);
break;
}
/* translate the offset from words to byte */
return (address & ADDRESS_MSK) + (offset << 1);
}
static const u8 *iwl_eeprom_query_addr(const u8 *eeprom, size_t eeprom_size,
u32 offset)
{
u32 address = eeprom_indirect_address(eeprom, eeprom_size, offset);
if (WARN_ON(address >= eeprom_size))
return NULL;
return &eeprom[address];
}
static int iwl_eeprom_read_calib(const u8 *eeprom, size_t eeprom_size,
struct iwl_nvm_data *data)
{
struct iwl_eeprom_calib_hdr *hdr;
hdr = (void *)iwl_eeprom_query_addr(eeprom, eeprom_size,
EEPROM_CALIB_ALL);
if (!hdr)
return -ENODATA;
data->calib_version = hdr->version;
data->calib_voltage = hdr->voltage;
return 0;
}
/**
* enum iwl_eeprom_channel_flags - channel flags in EEPROM
* @EEPROM_CHANNEL_VALID: channel is usable for this SKU/geo
* @EEPROM_CHANNEL_IBSS: usable as an IBSS channel
* @EEPROM_CHANNEL_ACTIVE: active scanning allowed
* @EEPROM_CHANNEL_RADAR: radar detection required
* @EEPROM_CHANNEL_WIDE: 20 MHz channel okay (?)
* @EEPROM_CHANNEL_DFS: dynamic freq selection candidate
*/
enum iwl_eeprom_channel_flags {
EEPROM_CHANNEL_VALID = BIT(0),
EEPROM_CHANNEL_IBSS = BIT(1),
EEPROM_CHANNEL_ACTIVE = BIT(3),
EEPROM_CHANNEL_RADAR = BIT(4),
EEPROM_CHANNEL_WIDE = BIT(5),
EEPROM_CHANNEL_DFS = BIT(7),
};
/**
* struct iwl_eeprom_channel - EEPROM channel data
* @flags: %EEPROM_CHANNEL_* flags
* @max_power_avg: max power (in dBm) on this channel, at most 31 dBm
*/
struct iwl_eeprom_channel {
u8 flags;
s8 max_power_avg;
} __packed;
enum iwl_eeprom_enhanced_txpwr_flags {
IWL_EEPROM_ENH_TXP_FL_VALID = BIT(0),
IWL_EEPROM_ENH_TXP_FL_BAND_52G = BIT(1),
IWL_EEPROM_ENH_TXP_FL_OFDM = BIT(2),
IWL_EEPROM_ENH_TXP_FL_40MHZ = BIT(3),
IWL_EEPROM_ENH_TXP_FL_HT_AP = BIT(4),
IWL_EEPROM_ENH_TXP_FL_RES1 = BIT(5),
IWL_EEPROM_ENH_TXP_FL_RES2 = BIT(6),
IWL_EEPROM_ENH_TXP_FL_COMMON_TYPE = BIT(7),
};
/**
* struct iwl_eeprom_enhanced_txpwr
* @flags: entry flags
* @channel: channel number
* @chain_a_max: chain a max power in 1/2 dBm
* @chain_b_max: chain b max power in 1/2 dBm
* @chain_c_max: chain c max power in 1/2 dBm
* @delta_20_in_40: 20-in-40 deltas (hi/lo)
* @mimo2_max: mimo2 max power in 1/2 dBm
* @mimo3_max: mimo3 max power in 1/2 dBm
*
* This structure presents the enhanced regulatory tx power limit layout
* in an EEPROM image.
*/
struct iwl_eeprom_enhanced_txpwr {
u8 flags;
u8 channel;
s8 chain_a_max;
s8 chain_b_max;
s8 chain_c_max;
u8 delta_20_in_40;
s8 mimo2_max;
s8 mimo3_max;
} __packed;
static s8 iwl_get_max_txpwr_half_dbm(const struct iwl_nvm_data *data,
struct iwl_eeprom_enhanced_txpwr *txp)
{
s8 result = 0; /* (.5 dBm) */
/* Take the highest tx power from any valid chains */
if (data->valid_tx_ant & ANT_A && txp->chain_a_max > result)
result = txp->chain_a_max;
if (data->valid_tx_ant & ANT_B && txp->chain_b_max > result)
result = txp->chain_b_max;
if (data->valid_tx_ant & ANT_C && txp->chain_c_max > result)
result = txp->chain_c_max;
if ((data->valid_tx_ant == ANT_AB ||
data->valid_tx_ant == ANT_BC ||
data->valid_tx_ant == ANT_AC) && txp->mimo2_max > result)
result = txp->mimo2_max;
if (data->valid_tx_ant == ANT_ABC && txp->mimo3_max > result)
result = txp->mimo3_max;
return result;
}
#define EEPROM_TXP_OFFS (0x00 | INDIRECT_ADDRESS | INDIRECT_TXP_LIMIT)
#define EEPROM_TXP_ENTRY_LEN sizeof(struct iwl_eeprom_enhanced_txpwr)
#define EEPROM_TXP_SZ_OFFS (0x00 | INDIRECT_ADDRESS | INDIRECT_TXP_LIMIT_SIZE)
#define TXP_CHECK_AND_PRINT(x) \
((txp->flags & IWL_EEPROM_ENH_TXP_FL_##x) ? # x " " : "")
static void
iwl_eeprom_enh_txp_read_element(struct iwl_nvm_data *data,
struct iwl_eeprom_enhanced_txpwr *txp,
int n_channels, s8 max_txpower_avg)
{
int ch_idx;
enum nl80211_band band;
band = txp->flags & IWL_EEPROM_ENH_TXP_FL_BAND_52G ?
NL80211_BAND_5GHZ : NL80211_BAND_2GHZ;
for (ch_idx = 0; ch_idx < n_channels; ch_idx++) {
struct ieee80211_channel *chan = &data->channels[ch_idx];
/* update matching channel or from common data only */
if (txp->channel != 0 && chan->hw_value != txp->channel)
continue;
/* update matching band only */
if (band != chan->band)
continue;
if (chan->max_power < max_txpower_avg &&
!(txp->flags & IWL_EEPROM_ENH_TXP_FL_40MHZ))
chan->max_power = max_txpower_avg;
}
}
static void iwl_eeprom_enhanced_txpower(struct device *dev,
struct iwl_nvm_data *data,
const u8 *eeprom, size_t eeprom_size,
int n_channels)
{
struct iwl_eeprom_enhanced_txpwr *txp_array, *txp;
int idx, entries;
__le16 *txp_len;
s8 max_txp_avg_halfdbm;
BUILD_BUG_ON(sizeof(struct iwl_eeprom_enhanced_txpwr) != 8);
/* the length is in 16-bit words, but we want entries */
txp_len = (__le16 *)iwl_eeprom_query_addr(eeprom, eeprom_size,
EEPROM_TXP_SZ_OFFS);
entries = le16_to_cpup(txp_len) * 2 / EEPROM_TXP_ENTRY_LEN;
txp_array = (void *)iwl_eeprom_query_addr(eeprom, eeprom_size,
EEPROM_TXP_OFFS);
for (idx = 0; idx < entries; idx++) {
txp = &txp_array[idx];
/* skip invalid entries */
if (!(txp->flags & IWL_EEPROM_ENH_TXP_FL_VALID))
continue;
IWL_DEBUG_EEPROM(dev, "%s %d:\t %s%s%s%s%s%s%s%s (0x%02x)\n",
(txp->channel && (txp->flags &
IWL_EEPROM_ENH_TXP_FL_COMMON_TYPE)) ?
"Common " : (txp->channel) ?
"Channel" : "Common",
(txp->channel),
TXP_CHECK_AND_PRINT(VALID),
TXP_CHECK_AND_PRINT(BAND_52G),
TXP_CHECK_AND_PRINT(OFDM),
TXP_CHECK_AND_PRINT(40MHZ),
TXP_CHECK_AND_PRINT(HT_AP),
TXP_CHECK_AND_PRINT(RES1),
TXP_CHECK_AND_PRINT(RES2),
TXP_CHECK_AND_PRINT(COMMON_TYPE),
txp->flags);
IWL_DEBUG_EEPROM(dev,
"\t\t chain_A: %d chain_B: %d chain_C: %d\n",
txp->chain_a_max, txp->chain_b_max,
txp->chain_c_max);
IWL_DEBUG_EEPROM(dev,
"\t\t MIMO2: %d MIMO3: %d High 20_on_40: 0x%02x Low 20_on_40: 0x%02x\n",
txp->mimo2_max, txp->mimo3_max,
((txp->delta_20_in_40 & 0xf0) >> 4),
(txp->delta_20_in_40 & 0x0f));
max_txp_avg_halfdbm = iwl_get_max_txpwr_half_dbm(data, txp);
iwl_eeprom_enh_txp_read_element(data, txp, n_channels,
DIV_ROUND_UP(max_txp_avg_halfdbm, 2));
if (max_txp_avg_halfdbm > data->max_tx_pwr_half_dbm)
data->max_tx_pwr_half_dbm = max_txp_avg_halfdbm;
}
}
static void iwl_init_band_reference(const struct iwl_cfg *cfg,
const u8 *eeprom, size_t eeprom_size,
int eeprom_band, int *eeprom_ch_count,
const struct iwl_eeprom_channel **ch_info,
const u8 **eeprom_ch_array)
{
u32 offset = cfg->eeprom_params->regulatory_bands[eeprom_band - 1];
offset |= INDIRECT_ADDRESS | INDIRECT_REGULATORY;
*ch_info = (void *)iwl_eeprom_query_addr(eeprom, eeprom_size, offset);
switch (eeprom_band) {
case 1: /* 2.4GHz band */
*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_1);
*eeprom_ch_array = iwl_eeprom_band_1;
break;
case 2: /* 4.9GHz band */
*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_2);
*eeprom_ch_array = iwl_eeprom_band_2;
break;
case 3: /* 5.2GHz band */
*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_3);
*eeprom_ch_array = iwl_eeprom_band_3;
break;
case 4: /* 5.5GHz band */
*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_4);
*eeprom_ch_array = iwl_eeprom_band_4;
break;
case 5: /* 5.7GHz band */
*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_5);
*eeprom_ch_array = iwl_eeprom_band_5;
break;
case 6: /* 2.4GHz ht40 channels */
*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_6);
*eeprom_ch_array = iwl_eeprom_band_6;
break;
case 7: /* 5 GHz ht40 channels */
*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_7);
*eeprom_ch_array = iwl_eeprom_band_7;
break;
default:
*eeprom_ch_count = 0;
*eeprom_ch_array = NULL;
WARN_ON(1);
}
}
#define CHECK_AND_PRINT(x) \
((eeprom_ch->flags & EEPROM_CHANNEL_##x) ? # x " " : "")
static void iwl_mod_ht40_chan_info(struct device *dev,
struct iwl_nvm_data *data, int n_channels,
enum nl80211_band band, u16 channel,
const struct iwl_eeprom_channel *eeprom_ch,
u8 clear_ht40_extension_channel)
{
struct ieee80211_channel *chan = NULL;
int i;
for (i = 0; i < n_channels; i++) {
if (data->channels[i].band != band)
continue;
if (data->channels[i].hw_value != channel)
continue;
chan = &data->channels[i];
break;
}
if (!chan)
return;
IWL_DEBUG_EEPROM(dev,
"HT40 Ch. %d [%sGHz] %s%s%s%s%s(0x%02x %ddBm): Ad-Hoc %ssupported\n",
channel,
band == NL80211_BAND_5GHZ ? "5.2" : "2.4",
CHECK_AND_PRINT(IBSS),
CHECK_AND_PRINT(ACTIVE),
CHECK_AND_PRINT(RADAR),
CHECK_AND_PRINT(WIDE),
CHECK_AND_PRINT(DFS),
eeprom_ch->flags,
eeprom_ch->max_power_avg,
((eeprom_ch->flags & EEPROM_CHANNEL_IBSS) &&
!(eeprom_ch->flags & EEPROM_CHANNEL_RADAR)) ? ""
: "not ");
if (eeprom_ch->flags & EEPROM_CHANNEL_VALID)
chan->flags &= ~clear_ht40_extension_channel;
}
#define CHECK_AND_PRINT_I(x) \
((eeprom_ch_info[ch_idx].flags & EEPROM_CHANNEL_##x) ? # x " " : "")
static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
struct iwl_nvm_data *data,
const u8 *eeprom, size_t eeprom_size)
{
int band, ch_idx;
const struct iwl_eeprom_channel *eeprom_ch_info;
const u8 *eeprom_ch_array;
int eeprom_ch_count;
int n_channels = 0;
/*
* Loop through the 5 EEPROM bands and add them to the parse list
*/
for (band = 1; band <= 5; band++) {
struct ieee80211_channel *channel;
iwl_init_band_reference(cfg, eeprom, eeprom_size, band,
&eeprom_ch_count, &eeprom_ch_info,
&eeprom_ch_array);
/* Loop through each band adding each of the channels */
for (ch_idx = 0; ch_idx < eeprom_ch_count; ch_idx++) {
const struct iwl_eeprom_channel *eeprom_ch;
eeprom_ch = &eeprom_ch_info[ch_idx];
if (!(eeprom_ch->flags & EEPROM_CHANNEL_VALID)) {
IWL_DEBUG_EEPROM(dev,
"Ch. %d Flags %x [%sGHz] - No traffic\n",
eeprom_ch_array[ch_idx],
eeprom_ch_info[ch_idx].flags,
(band != 1) ? "5.2" : "2.4");
continue;
}
channel = &data->channels[n_channels];
n_channels++;
channel->hw_value = eeprom_ch_array[ch_idx];
channel->band = (band == 1) ? NL80211_BAND_2GHZ
: NL80211_BAND_5GHZ;
channel->center_freq =
ieee80211_channel_to_frequency(
channel->hw_value, channel->band);
/* set no-HT40, will enable as appropriate later */
channel->flags = IEEE80211_CHAN_NO_HT40;
if (!(eeprom_ch->flags & EEPROM_CHANNEL_IBSS))
channel->flags |= IEEE80211_CHAN_NO_IR;
if (!(eeprom_ch->flags & EEPROM_CHANNEL_ACTIVE))
channel->flags |= IEEE80211_CHAN_NO_IR;
if (eeprom_ch->flags & EEPROM_CHANNEL_RADAR)
channel->flags |= IEEE80211_CHAN_RADAR;
/* Initialize regulatory-based run-time data */
channel->max_power =
eeprom_ch_info[ch_idx].max_power_avg;
IWL_DEBUG_EEPROM(dev,
"Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x %ddBm): Ad-Hoc %ssupported\n",
channel->hw_value,
(band != 1) ? "5.2" : "2.4",
CHECK_AND_PRINT_I(VALID),
CHECK_AND_PRINT_I(IBSS),
CHECK_AND_PRINT_I(ACTIVE),
CHECK_AND_PRINT_I(RADAR),
CHECK_AND_PRINT_I(WIDE),
CHECK_AND_PRINT_I(DFS),
eeprom_ch_info[ch_idx].flags,
eeprom_ch_info[ch_idx].max_power_avg,
((eeprom_ch_info[ch_idx].flags &
EEPROM_CHANNEL_IBSS) &&
!(eeprom_ch_info[ch_idx].flags &
EEPROM_CHANNEL_RADAR))
? "" : "not ");
}
}
if (cfg->eeprom_params->enhanced_txpower) {
/*
* for newer device (6000 series and up)
* EEPROM contain enhanced tx power information
* driver need to process addition information
* to determine the max channel tx power limits
*/
iwl_eeprom_enhanced_txpower(dev, data, eeprom, eeprom_size,
n_channels);
} else {
/* All others use data from channel map */
int i;
data->max_tx_pwr_half_dbm = -128;
for (i = 0; i < n_channels; i++)
data->max_tx_pwr_half_dbm =
max_t(s8, data->max_tx_pwr_half_dbm,
data->channels[i].max_power * 2);
}
/* Check if we do have HT40 channels */
if (cfg->eeprom_params->regulatory_bands[5] ==
EEPROM_REGULATORY_BAND_NO_HT40 &&
cfg->eeprom_params->regulatory_bands[6] ==
EEPROM_REGULATORY_BAND_NO_HT40)
return n_channels;
/* Two additional EEPROM bands for 2.4 and 5 GHz HT40 channels */
for (band = 6; band <= 7; band++) {
enum nl80211_band ieeeband;
iwl_init_band_reference(cfg, eeprom, eeprom_size, band,
&eeprom_ch_count, &eeprom_ch_info,
&eeprom_ch_array);
/* EEPROM band 6 is 2.4, band 7 is 5 GHz */
ieeeband = (band == 6) ? NL80211_BAND_2GHZ
: NL80211_BAND_5GHZ;
/* Loop through each band adding each of the channels */
for (ch_idx = 0; ch_idx < eeprom_ch_count; ch_idx++) {
/* Set up driver's info for lower half */
iwl_mod_ht40_chan_info(dev, data, n_channels, ieeeband,
eeprom_ch_array[ch_idx],
&eeprom_ch_info[ch_idx],
IEEE80211_CHAN_NO_HT40PLUS);
/* Set up driver's info for upper half */
iwl_mod_ht40_chan_info(dev, data, n_channels, ieeeband,
eeprom_ch_array[ch_idx] + 4,
&eeprom_ch_info[ch_idx],
IEEE80211_CHAN_NO_HT40MINUS);
}
}
return n_channels;
}
#endif
int iwl_init_sband_channels(struct iwl_nvm_data *data,
struct ieee80211_supported_band *sband,
int n_channels, enum nl80211_band band)
{
struct ieee80211_channel *chan = &data->channels[0];
int n = 0, idx = 0;
while (idx < n_channels && chan->band != band)
chan = &data->channels[++idx];
sband->channels = &data->channels[idx];
while (idx < n_channels && chan->band == band) {
chan = &data->channels[++idx];
n++;
}
sband->n_channels = n;
return n;
}
#define MAX_BIT_RATE_40_MHZ 150 /* Mbps */
#define MAX_BIT_RATE_20_MHZ 72 /* Mbps */
void iwl_init_ht_hw_capab(struct iwl_trans *trans,
struct iwl_nvm_data *data,
struct ieee80211_sta_ht_cap *ht_info,
enum nl80211_band band,
u8 tx_chains, u8 rx_chains)
{
const struct iwl_cfg *cfg = trans->cfg;
int max_bit_rate = 0;
tx_chains = hweight8(tx_chains);
if (cfg->rx_with_siso_diversity)
rx_chains = 1;
else
rx_chains = hweight8(rx_chains);
if (!(data->sku_cap_11n_enable) ||
(iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_ALL) ||
!cfg->ht_params) {
ht_info->ht_supported = false;
return;
}
if (data->sku_cap_mimo_disabled)
rx_chains = 1;
ht_info->ht_supported = true;
ht_info->cap = IEEE80211_HT_CAP_DSSSCCK40;
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)
ht_info->cap |= IEEE80211_HT_CAP_LDPC_CODING;
if (trans->trans_cfg->mq_rx_supported ||
iwlwifi_mod_params.amsdu_size >= IWL_AMSDU_8K)
ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU;
ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_4;
ht_info->mcs.rx_mask[0] = 0xFF;
if (rx_chains >= 2)
ht_info->mcs.rx_mask[1] = 0xFF;
if (rx_chains >= 3)
ht_info->mcs.rx_mask[2] = 0xFF;
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)) {
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;
}
/* Highest supported Rx data rate */
max_bit_rate *= rx_chains;
WARN_ON(max_bit_rate & ~IEEE80211_HT_MCS_RX_HIGHEST_MASK);
ht_info->mcs.rx_highest = cpu_to_le16(max_bit_rate);
/* Tx MCS capabilities */
ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
if (tx_chains != rx_chains) {
ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF;
ht_info->mcs.tx_params |= ((tx_chains - 1) <<
IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT);
}
}
#if IS_ENABLED(CONFIG_IWLDVM)
static void iwl_init_sbands(struct iwl_trans *trans, const struct iwl_cfg *cfg,
struct iwl_nvm_data *data,
const u8 *eeprom, size_t eeprom_size)
{
struct device *dev = trans->dev;
int n_channels = iwl_init_channel_map(dev, cfg, data,
eeprom, eeprom_size);
int n_used = 0;
struct ieee80211_supported_band *sband;
sband = &data->bands[NL80211_BAND_2GHZ];
sband->band = NL80211_BAND_2GHZ;
sband->bitrates = &iwl_cfg80211_rates[RATES_24_OFFS];
sband->n_bitrates = N_RATES_24;
n_used += iwl_init_sband_channels(data, sband, n_channels,
NL80211_BAND_2GHZ);
iwl_init_ht_hw_capab(trans, data, &sband->ht_cap, NL80211_BAND_2GHZ,
data->valid_tx_ant, data->valid_rx_ant);
sband = &data->bands[NL80211_BAND_5GHZ];
sband->band = NL80211_BAND_5GHZ;
sband->bitrates = &iwl_cfg80211_rates[RATES_52_OFFS];
sband->n_bitrates = N_RATES_52;
n_used += iwl_init_sband_channels(data, sband, n_channels,
NL80211_BAND_5GHZ);
iwl_init_ht_hw_capab(trans, data, &sband->ht_cap, NL80211_BAND_5GHZ,
data->valid_tx_ant, data->valid_rx_ant);
if (n_channels != n_used)
IWL_ERR_DEV(dev, "EEPROM: used only %d of %d channels\n",
n_used, n_channels);
}
/* EEPROM data functions */
struct iwl_nvm_data *
iwl_parse_eeprom_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
const u8 *eeprom, size_t eeprom_size)
{
struct iwl_nvm_data *data;
struct device *dev = trans->dev;
const void *tmp;
u16 radio_cfg, sku;
if (WARN_ON(!cfg || !cfg->eeprom_params))
return NULL;
data = kzalloc(struct_size(data, channels, IWL_NUM_CHANNELS),
GFP_KERNEL);
if (!data)
return NULL;
/* get MAC address(es) */
tmp = iwl_eeprom_query_addr(eeprom, eeprom_size, EEPROM_MAC_ADDRESS);
if (!tmp)
goto err_free;
memcpy(data->hw_addr, tmp, ETH_ALEN);
data->n_hw_addrs = iwl_eeprom_query16(eeprom, eeprom_size,
EEPROM_NUM_MAC_ADDRESS);
if (iwl_eeprom_read_calib(eeprom, eeprom_size, data))
goto err_free;
tmp = iwl_eeprom_query_addr(eeprom, eeprom_size, EEPROM_XTAL);
if (!tmp)
goto err_free;
memcpy(data->xtal_calib, tmp, sizeof(data->xtal_calib));
tmp = iwl_eeprom_query_addr(eeprom, eeprom_size,
EEPROM_RAW_TEMPERATURE);
if (!tmp)
goto err_free;
data->raw_temperature = *(__le16 *)tmp;
tmp = iwl_eeprom_query_addr(eeprom, eeprom_size,
EEPROM_KELVIN_TEMPERATURE);
if (!tmp)
goto err_free;
data->kelvin_temperature = *(__le16 *)tmp;
data->kelvin_voltage = *((__le16 *)tmp + 1);
radio_cfg = iwl_eeprom_query16(eeprom, eeprom_size,
EEPROM_RADIO_CONFIG);
data->radio_cfg_dash = EEPROM_RF_CFG_DASH_MSK(radio_cfg);
data->radio_cfg_pnum = EEPROM_RF_CFG_PNUM_MSK(radio_cfg);
data->radio_cfg_step = EEPROM_RF_CFG_STEP_MSK(radio_cfg);
data->radio_cfg_type = EEPROM_RF_CFG_TYPE_MSK(radio_cfg);
data->valid_rx_ant = EEPROM_RF_CFG_RX_ANT_MSK(radio_cfg);
data->valid_tx_ant = EEPROM_RF_CFG_TX_ANT_MSK(radio_cfg);
sku = iwl_eeprom_query16(eeprom, eeprom_size,
EEPROM_SKU_CAP);
data->sku_cap_11n_enable = sku & EEPROM_SKU_CAP_11N_ENABLE;
data->sku_cap_amt_enable = sku & EEPROM_SKU_CAP_AMT_ENABLE;
data->sku_cap_band_24ghz_enable = sku & EEPROM_SKU_CAP_BAND_24GHZ;
data->sku_cap_band_52ghz_enable = sku & EEPROM_SKU_CAP_BAND_52GHZ;
data->sku_cap_ipan_enable = sku & EEPROM_SKU_CAP_IPAN_ENABLE;
if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_ALL)
data->sku_cap_11n_enable = false;
data->nvm_version = iwl_eeprom_query16(eeprom, eeprom_size,
EEPROM_VERSION);
/* check overrides (some devices have wrong EEPROM) */
if (cfg->valid_tx_ant)
data->valid_tx_ant = cfg->valid_tx_ant;
if (cfg->valid_rx_ant)
data->valid_rx_ant = cfg->valid_rx_ant;
if (!data->valid_tx_ant || !data->valid_rx_ant) {
IWL_ERR_DEV(dev, "invalid antennas (0x%x, 0x%x)\n",
data->valid_tx_ant, data->valid_rx_ant);
goto err_free;
}
iwl_init_sbands(trans, cfg, data, eeprom, eeprom_size);
return data;
err_free:
kfree(data);
return NULL;
}
IWL_EXPORT_SYMBOL(iwl_parse_eeprom_data);
#endif

View File

@ -0,0 +1,88 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2005-2014, 2018 Intel Corporation
* Copyright (C) 2015 Intel Mobile Communications GmbH
*/
#ifndef __iwl_eeprom_parse_h__
#define __iwl_eeprom_parse_h__
#include <linux/types.h>
#include <linux/if_ether.h>
#include <net/cfg80211.h>
#include "iwl-trans.h"
struct iwl_nvm_data {
int n_hw_addrs;
u8 hw_addr[ETH_ALEN];
u8 calib_version;
__le16 calib_voltage;
__le16 raw_temperature;
__le16 kelvin_temperature;
__le16 kelvin_voltage;
__le16 xtal_calib[2];
bool sku_cap_band_24ghz_enable;
bool sku_cap_band_52ghz_enable;
bool sku_cap_11n_enable;
bool sku_cap_11ac_enable;
bool sku_cap_11ax_enable;
bool sku_cap_amt_enable;
bool sku_cap_ipan_enable;
bool sku_cap_mimo_disabled;
u16 radio_cfg_type;
u8 radio_cfg_step;
u8 radio_cfg_dash;
u8 radio_cfg_pnum;
u8 valid_tx_ant, valid_rx_ant;
u32 nvm_version;
s8 max_tx_pwr_half_dbm;
bool lar_enabled;
bool vht160_supported;
struct ieee80211_supported_band bands[NUM_NL80211_BANDS];
/*
* iftype data for low (2.4 GHz) and high (5 and 6 GHz) bands,
* we can use the same for 5 and 6 GHz bands because they have
* the same data
*/
struct {
struct ieee80211_sband_iftype_data low[2];
struct ieee80211_sband_iftype_data high[2];
} iftd;
struct ieee80211_channel channels[];
};
/**
* iwl_parse_eeprom_data - parse EEPROM data and return values
*
* @dev: device pointer we're parsing for, for debug only
* @cfg: device configuration for parsing and overrides
* @eeprom: the EEPROM data
* @eeprom_size: length of the EEPROM data
*
* This function parses all EEPROM values we need and then
* returns a (newly allocated) struct containing all the
* relevant values for driver use. The struct must be freed
* later with iwl_free_nvm_data().
*/
struct iwl_nvm_data *
iwl_parse_eeprom_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
const u8 *eeprom, size_t eeprom_size);
int iwl_init_sband_channels(struct iwl_nvm_data *data,
struct ieee80211_supported_band *sband,
int n_channels, enum nl80211_band band);
void iwl_init_ht_hw_capab(struct iwl_trans *trans,
struct iwl_nvm_data *data,
struct ieee80211_sta_ht_cap *ht_info,
enum nl80211_band band,
u8 tx_chains, u8 rx_chains);
#endif /* __iwl_eeprom_parse_h__ */

View File

@ -0,0 +1,401 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2005-2014, 2018-2019, 2021 Intel Corporation
*/
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/export.h>
#if defined(__FreeBSD__)
#include <linux/delay.h>
#endif
#include "iwl-drv.h"
#include "iwl-debug.h"
#include "iwl-eeprom-read.h"
#include "iwl-io.h"
#include "iwl-prph.h"
#include "iwl-csr.h"
/*
* EEPROM access time values:
*
* Driver initiates EEPROM read by writing byte address << 1 to CSR_EEPROM_REG.
* Driver then polls CSR_EEPROM_REG for CSR_EEPROM_REG_READ_VALID_MSK (0x1).
* When polling, wait 10 uSec between polling loops, up to a maximum 5000 uSec.
* Driver reads 16-bit value from bits 31-16 of CSR_EEPROM_REG.
*/
#define IWL_EEPROM_ACCESS_TIMEOUT 5000 /* uSec */
#define IWL_EEPROM_SEM_TIMEOUT 10 /* microseconds */
#define IWL_EEPROM_SEM_RETRY_LIMIT 1000 /* number of attempts (not time) */
/*
* The device's EEPROM semaphore prevents conflicts between driver and uCode
* when accessing the EEPROM; each access is a series of pulses to/from the
* EEPROM chip, not a single event, so even reads could conflict if they
* weren't arbitrated by the semaphore.
*/
#define EEPROM_SEM_TIMEOUT 10 /* milliseconds */
#define EEPROM_SEM_RETRY_LIMIT 1000 /* number of attempts (not time) */
static int iwl_eeprom_acquire_semaphore(struct iwl_trans *trans)
{
u16 count;
int ret;
for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) {
/* Request semaphore */
iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG,
CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
/* See if we got it */
ret = iwl_poll_bit(trans, CSR_HW_IF_CONFIG_REG,
CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
EEPROM_SEM_TIMEOUT);
if (ret >= 0) {
IWL_DEBUG_EEPROM(trans->dev,
"Acquired semaphore after %d tries.\n",
count+1);
return ret;
}
}
return ret;
}
static void iwl_eeprom_release_semaphore(struct iwl_trans *trans)
{
iwl_clear_bit(trans, CSR_HW_IF_CONFIG_REG,
CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
}
static int iwl_eeprom_verify_signature(struct iwl_trans *trans, bool nvm_is_otp)
{
u32 gp = iwl_read32(trans, CSR_EEPROM_GP) & CSR_EEPROM_GP_VALID_MSK;
IWL_DEBUG_EEPROM(trans->dev, "EEPROM signature=0x%08x\n", gp);
switch (gp) {
case CSR_EEPROM_GP_BAD_SIG_EEP_GOOD_SIG_OTP:
if (!nvm_is_otp) {
IWL_ERR(trans, "EEPROM with bad signature: 0x%08x\n",
gp);
return -ENOENT;
}
return 0;
case CSR_EEPROM_GP_GOOD_SIG_EEP_LESS_THAN_4K:
case CSR_EEPROM_GP_GOOD_SIG_EEP_MORE_THAN_4K:
if (nvm_is_otp) {
IWL_ERR(trans, "OTP with bad signature: 0x%08x\n", gp);
return -ENOENT;
}
return 0;
case CSR_EEPROM_GP_BAD_SIGNATURE_BOTH_EEP_AND_OTP:
default:
IWL_ERR(trans,
"bad EEPROM/OTP signature, type=%s, EEPROM_GP=0x%08x\n",
nvm_is_otp ? "OTP" : "EEPROM", gp);
return -ENOENT;
}
}
/******************************************************************************
*
* OTP related functions
*
******************************************************************************/
static void iwl_set_otp_access_absolute(struct iwl_trans *trans)
{
iwl_read32(trans, CSR_OTP_GP_REG);
iwl_clear_bit(trans, CSR_OTP_GP_REG,
CSR_OTP_GP_REG_OTP_ACCESS_MODE);
}
static int iwl_nvm_is_otp(struct iwl_trans *trans)
{
u32 otpgp;
/* OTP only valid for CP/PP and after */
switch (trans->hw_rev & CSR_HW_REV_TYPE_MSK) {
case CSR_HW_REV_TYPE_NONE:
IWL_ERR(trans, "Unknown hardware type\n");
return -EIO;
case CSR_HW_REV_TYPE_5300:
case CSR_HW_REV_TYPE_5350:
case CSR_HW_REV_TYPE_5100:
case CSR_HW_REV_TYPE_5150:
return 0;
default:
otpgp = iwl_read32(trans, CSR_OTP_GP_REG);
if (otpgp & CSR_OTP_GP_REG_DEVICE_SELECT)
return 1;
return 0;
}
}
static int iwl_init_otp_access(struct iwl_trans *trans)
{
int ret;
ret = iwl_finish_nic_init(trans);
if (ret)
return ret;
iwl_set_bits_prph(trans, APMG_PS_CTRL_REG,
APMG_PS_CTRL_VAL_RESET_REQ);
udelay(5);
iwl_clear_bits_prph(trans, APMG_PS_CTRL_REG,
APMG_PS_CTRL_VAL_RESET_REQ);
/*
* CSR auto clock gate disable bit -
* this is only applicable for HW with OTP shadow RAM
*/
if (trans->trans_cfg->base_params->shadow_ram_support)
iwl_set_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG,
CSR_RESET_LINK_PWR_MGMT_DISABLED);
return 0;
}
static int iwl_read_otp_word(struct iwl_trans *trans, u16 addr,
__le16 *eeprom_data)
{
int ret = 0;
u32 r;
u32 otpgp;
iwl_write32(trans, CSR_EEPROM_REG,
CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
ret = iwl_poll_bit(trans, CSR_EEPROM_REG,
CSR_EEPROM_REG_READ_VALID_MSK,
CSR_EEPROM_REG_READ_VALID_MSK,
IWL_EEPROM_ACCESS_TIMEOUT);
if (ret < 0) {
IWL_ERR(trans, "Time out reading OTP[%d]\n", addr);
return ret;
}
r = iwl_read32(trans, CSR_EEPROM_REG);
/* check for ECC errors: */
otpgp = iwl_read32(trans, CSR_OTP_GP_REG);
if (otpgp & CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK) {
/* stop in this case */
/* set the uncorrectable OTP ECC bit for acknowledgment */
iwl_set_bit(trans, CSR_OTP_GP_REG,
CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK);
IWL_ERR(trans, "Uncorrectable OTP ECC error, abort OTP read\n");
return -EINVAL;
}
if (otpgp & CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK) {
/* continue in this case */
/* set the correctable OTP ECC bit for acknowledgment */
iwl_set_bit(trans, CSR_OTP_GP_REG,
CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK);
IWL_ERR(trans, "Correctable OTP ECC error, continue read\n");
}
*eeprom_data = cpu_to_le16(r >> 16);
return 0;
}
/*
* iwl_is_otp_empty: check for empty OTP
*/
static bool iwl_is_otp_empty(struct iwl_trans *trans)
{
u16 next_link_addr = 0;
__le16 link_value;
bool is_empty = false;
/* locate the beginning of OTP link list */
if (!iwl_read_otp_word(trans, next_link_addr, &link_value)) {
if (!link_value) {
IWL_ERR(trans, "OTP is empty\n");
is_empty = true;
}
} else {
IWL_ERR(trans, "Unable to read first block of OTP list.\n");
is_empty = true;
}
return is_empty;
}
/*
* iwl_find_otp_image: find EEPROM image in OTP
* finding the OTP block that contains the EEPROM image.
* the last valid block on the link list (the block _before_ the last block)
* is the block we should read and used to configure the device.
* If all the available OTP blocks are full, the last block will be the block
* we should read and used to configure the device.
* only perform this operation if shadow RAM is disabled
*/
static int iwl_find_otp_image(struct iwl_trans *trans,
u16 *validblockaddr)
{
u16 next_link_addr = 0, valid_addr;
__le16 link_value = 0;
int usedblocks = 0;
/* set addressing mode to absolute to traverse the link list */
iwl_set_otp_access_absolute(trans);
/* checking for empty OTP or error */
if (iwl_is_otp_empty(trans))
return -EINVAL;
/*
* start traverse link list
* until reach the max number of OTP blocks
* different devices have different number of OTP blocks
*/
do {
/* save current valid block address
* check for more block on the link list
*/
valid_addr = next_link_addr;
next_link_addr = le16_to_cpu(link_value) * sizeof(u16);
IWL_DEBUG_EEPROM(trans->dev, "OTP blocks %d addr 0x%x\n",
usedblocks, next_link_addr);
if (iwl_read_otp_word(trans, next_link_addr, &link_value))
return -EINVAL;
if (!link_value) {
/*
* reach the end of link list, return success and
* set address point to the starting address
* of the image
*/
*validblockaddr = valid_addr;
/* skip first 2 bytes (link list pointer) */
*validblockaddr += 2;
return 0;
}
/* more in the link list, continue */
usedblocks++;
} while (usedblocks <= trans->trans_cfg->base_params->max_ll_items);
/* OTP has no valid blocks */
IWL_DEBUG_EEPROM(trans->dev, "OTP has no valid blocks\n");
return -EINVAL;
}
/*
* iwl_read_eeprom - read EEPROM contents
*
* Load the EEPROM contents from adapter and return it
* and its size.
*
* NOTE: This routine uses the non-debug IO access functions.
*/
int iwl_read_eeprom(struct iwl_trans *trans, u8 **eeprom, size_t *eeprom_size)
{
__le16 *e;
u32 gp = iwl_read32(trans, CSR_EEPROM_GP);
int sz;
int ret;
u16 addr;
u16 validblockaddr = 0;
u16 cache_addr = 0;
int nvm_is_otp;
if (!eeprom || !eeprom_size)
return -EINVAL;
nvm_is_otp = iwl_nvm_is_otp(trans);
if (nvm_is_otp < 0)
return nvm_is_otp;
sz = trans->trans_cfg->base_params->eeprom_size;
IWL_DEBUG_EEPROM(trans->dev, "NVM size = %d\n", sz);
e = kmalloc(sz, GFP_KERNEL);
if (!e)
return -ENOMEM;
ret = iwl_eeprom_verify_signature(trans, nvm_is_otp);
if (ret < 0) {
IWL_ERR(trans, "EEPROM not found, EEPROM_GP=0x%08x\n", gp);
goto err_free;
}
/* Make sure driver (instead of uCode) is allowed to read EEPROM */
ret = iwl_eeprom_acquire_semaphore(trans);
if (ret < 0) {
IWL_ERR(trans, "Failed to acquire EEPROM semaphore.\n");
goto err_free;
}
if (nvm_is_otp) {
ret = iwl_init_otp_access(trans);
if (ret) {
IWL_ERR(trans, "Failed to initialize OTP access.\n");
goto err_unlock;
}
iwl_write32(trans, CSR_EEPROM_GP,
iwl_read32(trans, CSR_EEPROM_GP) &
~CSR_EEPROM_GP_IF_OWNER_MSK);
iwl_set_bit(trans, CSR_OTP_GP_REG,
CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK |
CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK);
/* traversing the linked list if no shadow ram supported */
if (!trans->trans_cfg->base_params->shadow_ram_support) {
ret = iwl_find_otp_image(trans, &validblockaddr);
if (ret)
goto err_unlock;
}
for (addr = validblockaddr; addr < validblockaddr + sz;
addr += sizeof(u16)) {
__le16 eeprom_data;
ret = iwl_read_otp_word(trans, addr, &eeprom_data);
if (ret)
goto err_unlock;
e[cache_addr / 2] = eeprom_data;
cache_addr += sizeof(u16);
}
} else {
/* eeprom is an array of 16bit values */
for (addr = 0; addr < sz; addr += sizeof(u16)) {
u32 r;
iwl_write32(trans, CSR_EEPROM_REG,
CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
ret = iwl_poll_bit(trans, CSR_EEPROM_REG,
CSR_EEPROM_REG_READ_VALID_MSK,
CSR_EEPROM_REG_READ_VALID_MSK,
IWL_EEPROM_ACCESS_TIMEOUT);
if (ret < 0) {
IWL_ERR(trans,
"Time out reading EEPROM[%d]\n", addr);
goto err_unlock;
}
r = iwl_read32(trans, CSR_EEPROM_REG);
e[addr / 2] = cpu_to_le16(r >> 16);
}
}
IWL_DEBUG_EEPROM(trans->dev, "NVM Type: %s\n",
nvm_is_otp ? "OTP" : "EEPROM");
iwl_eeprom_release_semaphore(trans);
*eeprom_size = sz;
*eeprom = (u8 *)e;
return 0;
err_unlock:
iwl_eeprom_release_semaphore(trans);
err_free:
kfree(e);
return ret;
}
IWL_EXPORT_SYMBOL(iwl_read_eeprom);

View File

@ -0,0 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2005-2014 Intel Corporation
*/
#ifndef __iwl_eeprom_h__
#define __iwl_eeprom_h__
#include "iwl-trans.h"
int iwl_read_eeprom(struct iwl_trans *trans, u8 **eeprom, size_t *eeprom_size);
#endif /* __iwl_eeprom_h__ */

View File

@ -0,0 +1,720 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2005-2014, 2018-2020 Intel Corporation
* Copyright (C) 2015-2017 Intel Deutschland GmbH
*/
#ifndef __iwl_fh_h__
#define __iwl_fh_h__
#include <linux/types.h>
#include <linux/bitfield.h>
#include "iwl-trans.h"
/****************************/
/* Flow Handler Definitions */
/****************************/
/**
* This I/O area is directly read/writable by driver (e.g. Linux uses writel())
* Addresses are offsets from device's PCI hardware base address.
*/
#define FH_MEM_LOWER_BOUND (0x1000)
#define FH_MEM_UPPER_BOUND (0x2000)
#define FH_MEM_LOWER_BOUND_GEN2 (0xa06000)
#define FH_MEM_UPPER_BOUND_GEN2 (0xa08000)
/**
* Keep-Warm (KW) buffer base address.
*
* Driver must allocate a 4KByte buffer that is for keeping the
* host DRAM powered on (via dummy accesses to DRAM) to maintain low-latency
* DRAM access when doing Txing or Rxing. The dummy accesses prevent host
* from going into a power-savings mode that would cause higher DRAM latency,
* and possible data over/under-runs, before all Tx/Rx is complete.
*
* Driver loads FH_KW_MEM_ADDR_REG with the physical address (bits 35:4)
* of the buffer, which must be 4K aligned. Once this is set up, the device
* automatically invokes keep-warm accesses when normal accesses might not
* be sufficient to maintain fast DRAM response.
*
* Bit fields:
* 31-0: Keep-warm buffer physical base address [35:4], must be 4K aligned
*/
#define FH_KW_MEM_ADDR_REG (FH_MEM_LOWER_BOUND + 0x97C)
/**
* TFD Circular Buffers Base (CBBC) addresses
*
* Device has 16 base pointer registers, one for each of 16 host-DRAM-resident
* circular buffers (CBs/queues) containing Transmit Frame Descriptors (TFDs)
* (see struct iwl_tfd_frame). These 16 pointer registers are offset by 0x04
* bytes from one another. Each TFD circular buffer in DRAM must be 256-byte
* aligned (address bits 0-7 must be 0).
* Later devices have 20 (5000 series) or 30 (higher) queues, but the registers
* for them are in different places.
*
* Bit fields in each pointer register:
* 27-0: TFD CB physical base address [35:8], must be 256-byte aligned
*/
#define FH_MEM_CBBC_0_15_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0x9D0)
#define FH_MEM_CBBC_0_15_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xA10)
#define FH_MEM_CBBC_16_19_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0xBF0)
#define FH_MEM_CBBC_16_19_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xC00)
#define FH_MEM_CBBC_20_31_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0xB20)
#define FH_MEM_CBBC_20_31_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xB80)
/* 22000 TFD table address, 64 bit */
#define TFH_TFDQ_CBB_TABLE (0x1C00)
/* Find TFD CB base pointer for given queue */
static inline unsigned int FH_MEM_CBBC_QUEUE(struct iwl_trans *trans,
unsigned int chnl)
{
if (trans->trans_cfg->use_tfh) {
WARN_ON_ONCE(chnl >= 64);
return TFH_TFDQ_CBB_TABLE + 8 * chnl;
}
if (chnl < 16)
return FH_MEM_CBBC_0_15_LOWER_BOUND + 4 * chnl;
if (chnl < 20)
return FH_MEM_CBBC_16_19_LOWER_BOUND + 4 * (chnl - 16);
WARN_ON_ONCE(chnl >= 32);
return FH_MEM_CBBC_20_31_LOWER_BOUND + 4 * (chnl - 20);
}
/* 22000 configuration registers */
/*
* TFH Configuration register.
*
* BIT fields:
*
* Bits 3:0:
* Define the maximum number of pending read requests.
* Maximum configuration value allowed is 0xC
* Bits 9:8:
* Define the maximum transfer size. (64 / 128 / 256)
* Bit 10:
* When bit is set and transfer size is set to 128B, the TFH will enable
* reading chunks of more than 64B only if the read address is aligned to 128B.
* In case of DRAM read address which is not aligned to 128B, the TFH will
* enable transfer size which doesn't cross 64B DRAM address boundary.
*/
#define TFH_TRANSFER_MODE (0x1F40)
#define TFH_TRANSFER_MAX_PENDING_REQ 0xc
#define TFH_CHUNK_SIZE_128 BIT(8)
#define TFH_CHUNK_SPLIT_MODE BIT(10)
/*
* Defines the offset address in dwords referring from the beginning of the
* Tx CMD which will be updated in DRAM.
* Note that the TFH offset address for Tx CMD update is always referring to
* the start of the TFD first TB.
* In case of a DRAM Tx CMD update the TFH will update PN and Key ID
*/
#define TFH_TXCMD_UPDATE_CFG (0x1F48)
/*
* Controls TX DMA operation
*
* BIT fields:
*
* Bits 31:30: Enable the SRAM DMA channel.
* Turning on bit 31 will kick the SRAM2DRAM DMA.
* Note that the sram2dram may be enabled only after configuring the DRAM and
* SRAM addresses registers and the byte count register.
* Bits 25:24: Defines the interrupt target upon dram2sram transfer done. When
* set to 1 - interrupt is sent to the driver
* Bit 0: Indicates the snoop configuration
*/
#define TFH_SRV_DMA_CHNL0_CTRL (0x1F60)
#define TFH_SRV_DMA_SNOOP BIT(0)
#define TFH_SRV_DMA_TO_DRIVER BIT(24)
#define TFH_SRV_DMA_START BIT(31)
/* Defines the DMA SRAM write start address to transfer a data block */
#define TFH_SRV_DMA_CHNL0_SRAM_ADDR (0x1F64)
/* Defines the 64bits DRAM start address to read the DMA data block from */
#define TFH_SRV_DMA_CHNL0_DRAM_ADDR (0x1F68)
/*
* Defines the number of bytes to transfer from DRAM to SRAM.
* Note that this register may be configured with non-dword aligned size.
*/
#define TFH_SRV_DMA_CHNL0_BC (0x1F70)
/**
* Rx SRAM Control and Status Registers (RSCSR)
*
* These registers provide handshake between driver and device for the Rx queue
* (this queue handles *all* command responses, notifications, Rx data, etc.
* sent from uCode to host driver). Unlike Tx, there is only one Rx
* queue, and only one Rx DMA/FIFO channel. Also unlike Tx, which can
* concatenate up to 20 DRAM buffers to form a Tx frame, each Receive Buffer
* Descriptor (RBD) points to only one Rx Buffer (RB); there is a 1:1
* mapping between RBDs and RBs.
*
* Driver must allocate host DRAM memory for the following, and set the
* physical address of each into device registers:
*
* 1) Receive Buffer Descriptor (RBD) circular buffer (CB), typically with 256
* entries (although any power of 2, up to 4096, is selectable by driver).
* Each entry (1 dword) points to a receive buffer (RB) of consistent size
* (typically 4K, although 8K or 16K are also selectable by driver).
* Driver sets up RB size and number of RBDs in the CB via Rx config
* register FH_MEM_RCSR_CHNL0_CONFIG_REG.
*
* Bit fields within one RBD:
* 27-0: Receive Buffer physical address bits [35:8], 256-byte aligned
*
* Driver sets physical address [35:8] of base of RBD circular buffer
* into FH_RSCSR_CHNL0_RBDCB_BASE_REG [27:0].
*
* 2) Rx status buffer, 8 bytes, in which uCode indicates which Rx Buffers
* (RBs) have been filled, via a "write pointer", actually the index of
* the RB's corresponding RBD within the circular buffer. Driver sets
* physical address [35:4] into FH_RSCSR_CHNL0_STTS_WPTR_REG [31:0].
*
* Bit fields in lower dword of Rx status buffer (upper dword not used
* by driver:
* 31-12: Not used by driver
* 11- 0: Index of last filled Rx buffer descriptor
* (device writes, driver reads this value)
*
* As the driver prepares Receive Buffers (RBs) for device to fill, driver must
* enter pointers to these RBs into contiguous RBD circular buffer entries,
* and update the device's "write" index register,
* FH_RSCSR_CHNL0_RBDCB_WPTR_REG.
*
* This "write" index corresponds to the *next* RBD that the driver will make
* available, i.e. one RBD past the tail of the ready-to-fill RBDs within
* the circular buffer. This value should initially be 0 (before preparing any
* RBs), should be 8 after preparing the first 8 RBs (for example), and must
* wrap back to 0 at the end of the circular buffer (but don't wrap before
* "read" index has advanced past 1! See below).
* NOTE: DEVICE EXPECTS THE WRITE INDEX TO BE INCREMENTED IN MULTIPLES OF 8.
*
* As the device fills RBs (referenced from contiguous RBDs within the circular
* buffer), it updates the Rx status buffer in host DRAM, 2) described above,
* to tell the driver the index of the latest filled RBD. The driver must
* read this "read" index from DRAM after receiving an Rx interrupt from device
*
* The driver must also internally keep track of a third index, which is the
* next RBD to process. When receiving an Rx interrupt, driver should process
* all filled but unprocessed RBs up to, but not including, the RB
* corresponding to the "read" index. For example, if "read" index becomes "1",
* driver may process the RB pointed to by RBD 0. Depending on volume of
* traffic, there may be many RBs to process.
*
* If read index == write index, device thinks there is no room to put new data.
* Due to this, the maximum number of filled RBs is 255, instead of 256. To
* be safe, make sure that there is a gap of at least 2 RBDs between "write"
* and "read" indexes; that is, make sure that there are no more than 254
* buffers waiting to be filled.
*/
#define FH_MEM_RSCSR_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0xBC0)
#define FH_MEM_RSCSR_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xC00)
#define FH_MEM_RSCSR_CHNL0 (FH_MEM_RSCSR_LOWER_BOUND)
/**
* Physical base address of 8-byte Rx Status buffer.
* Bit fields:
* 31-0: Rx status buffer physical base address [35:4], must 16-byte aligned.
*/
#define FH_RSCSR_CHNL0_STTS_WPTR_REG (FH_MEM_RSCSR_CHNL0)
/**
* Physical base address of Rx Buffer Descriptor Circular Buffer.
* Bit fields:
* 27-0: RBD CD physical base address [35:8], must be 256-byte aligned.
*/
#define FH_RSCSR_CHNL0_RBDCB_BASE_REG (FH_MEM_RSCSR_CHNL0 + 0x004)
/**
* Rx write pointer (index, really!).
* Bit fields:
* 11-0: Index of driver's most recent prepared-to-be-filled RBD, + 1.
* NOTE: For 256-entry circular buffer, use only bits [7:0].
*/
#define FH_RSCSR_CHNL0_RBDCB_WPTR_REG (FH_MEM_RSCSR_CHNL0 + 0x008)
#define FH_RSCSR_CHNL0_WPTR (FH_RSCSR_CHNL0_RBDCB_WPTR_REG)
#define FW_RSCSR_CHNL0_RXDCB_RDPTR_REG (FH_MEM_RSCSR_CHNL0 + 0x00c)
#define FH_RSCSR_CHNL0_RDPTR FW_RSCSR_CHNL0_RXDCB_RDPTR_REG
/**
* Rx Config/Status Registers (RCSR)
* Rx Config Reg for channel 0 (only channel used)
*
* Driver must initialize FH_MEM_RCSR_CHNL0_CONFIG_REG as follows for
* normal operation (see bit fields).
*
* Clearing FH_MEM_RCSR_CHNL0_CONFIG_REG to 0 turns off Rx DMA.
* Driver should poll FH_MEM_RSSR_RX_STATUS_REG for
* FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE (bit 24) before continuing.
*
* Bit fields:
* 31-30: Rx DMA channel enable: '00' off/pause, '01' pause at end of frame,
* '10' operate normally
* 29-24: reserved
* 23-20: # RBDs in circular buffer = 2^value; use "8" for 256 RBDs (normal),
* min "5" for 32 RBDs, max "12" for 4096 RBDs.
* 19-18: reserved
* 17-16: size of each receive buffer; '00' 4K (normal), '01' 8K,
* '10' 12K, '11' 16K.
* 15-14: reserved
* 13-12: IRQ destination; '00' none, '01' host driver (normal operation)
* 11- 4: timeout for closing Rx buffer and interrupting host (units 32 usec)
* typical value 0x10 (about 1/2 msec)
* 3- 0: reserved
*/
#define FH_MEM_RCSR_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0xC00)
#define FH_MEM_RCSR_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xCC0)
#define FH_MEM_RCSR_CHNL0 (FH_MEM_RCSR_LOWER_BOUND)
#define FH_MEM_RCSR_CHNL0_CONFIG_REG (FH_MEM_RCSR_CHNL0)
#define FH_MEM_RCSR_CHNL0_RBDCB_WPTR (FH_MEM_RCSR_CHNL0 + 0x8)
#define FH_MEM_RCSR_CHNL0_FLUSH_RB_REQ (FH_MEM_RCSR_CHNL0 + 0x10)
#define FH_RCSR_CHNL0_RX_CONFIG_RB_TIMEOUT_MSK (0x00000FF0) /* bits 4-11 */
#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_MSK (0x00001000) /* bits 12 */
#define FH_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME_MSK (0x00008000) /* bit 15 */
#define FH_RCSR_CHNL0_RX_CONFIG_RB_SIZE_MSK (0x00030000) /* bits 16-17 */
#define FH_RCSR_CHNL0_RX_CONFIG_RBDBC_SIZE_MSK (0x00F00000) /* bits 20-23 */
#define FH_RCSR_CHNL0_RX_CONFIG_DMA_CHNL_EN_MSK (0xC0000000) /* bits 30-31*/
#define FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS (20)
#define FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS (4)
#define RX_RB_TIMEOUT (0x11)
#define FH_RCSR_RX_CONFIG_CHNL_EN_PAUSE_VAL (0x00000000)
#define FH_RCSR_RX_CONFIG_CHNL_EN_PAUSE_EOF_VAL (0x40000000)
#define FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL (0x80000000)
#define FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K (0x00000000)
#define FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K (0x00010000)
#define FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_12K (0x00020000)
#define FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_16K (0x00030000)
#define FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY (0x00000004)
#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_NO_INT_VAL (0x00000000)
#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL (0x00001000)
/**
* Rx Shared Status Registers (RSSR)
*
* After stopping Rx DMA channel (writing 0 to
* FH_MEM_RCSR_CHNL0_CONFIG_REG), driver must poll
* FH_MEM_RSSR_RX_STATUS_REG until Rx channel is idle.
*
* Bit fields:
* 24: 1 = Channel 0 is idle
*
* FH_MEM_RSSR_SHARED_CTRL_REG and FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV
* contain default values that should not be altered by the driver.
*/
#define FH_MEM_RSSR_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0xC40)
#define FH_MEM_RSSR_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xD00)
#define FH_MEM_RSSR_SHARED_CTRL_REG (FH_MEM_RSSR_LOWER_BOUND)
#define FH_MEM_RSSR_RX_STATUS_REG (FH_MEM_RSSR_LOWER_BOUND + 0x004)
#define FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV\
(FH_MEM_RSSR_LOWER_BOUND + 0x008)
#define FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE (0x01000000)
#define FH_MEM_TFDIB_REG1_ADDR_BITSHIFT 28
#define FH_MEM_TB_MAX_LENGTH (0x00020000)
/* 9000 rx series registers */
#define RFH_Q0_FRBDCB_BA_LSB 0xA08000 /* 64 bit address */
#define RFH_Q_FRBDCB_BA_LSB(q) (RFH_Q0_FRBDCB_BA_LSB + (q) * 8)
/* Write index table */
#define RFH_Q0_FRBDCB_WIDX 0xA08080
#define RFH_Q_FRBDCB_WIDX(q) (RFH_Q0_FRBDCB_WIDX + (q) * 4)
/* Write index table - shadow registers */
#define RFH_Q0_FRBDCB_WIDX_TRG 0x1C80
#define RFH_Q_FRBDCB_WIDX_TRG(q) (RFH_Q0_FRBDCB_WIDX_TRG + (q) * 4)
/* Read index table */
#define RFH_Q0_FRBDCB_RIDX 0xA080C0
#define RFH_Q_FRBDCB_RIDX(q) (RFH_Q0_FRBDCB_RIDX + (q) * 4)
/* Used list table */
#define RFH_Q0_URBDCB_BA_LSB 0xA08100 /* 64 bit address */
#define RFH_Q_URBDCB_BA_LSB(q) (RFH_Q0_URBDCB_BA_LSB + (q) * 8)
/* Write index table */
#define RFH_Q0_URBDCB_WIDX 0xA08180
#define RFH_Q_URBDCB_WIDX(q) (RFH_Q0_URBDCB_WIDX + (q) * 4)
#define RFH_Q0_URBDCB_VAID 0xA081C0
#define RFH_Q_URBDCB_VAID(q) (RFH_Q0_URBDCB_VAID + (q) * 4)
/* stts */
#define RFH_Q0_URBD_STTS_WPTR_LSB 0xA08200 /*64 bits address */
#define RFH_Q_URBD_STTS_WPTR_LSB(q) (RFH_Q0_URBD_STTS_WPTR_LSB + (q) * 8)
#define RFH_Q0_ORB_WPTR_LSB 0xA08280
#define RFH_Q_ORB_WPTR_LSB(q) (RFH_Q0_ORB_WPTR_LSB + (q) * 8)
#define RFH_RBDBUF_RBD0_LSB 0xA08300
#define RFH_RBDBUF_RBD_LSB(q) (RFH_RBDBUF_RBD0_LSB + (q) * 8)
/**
* RFH Status Register
*
* Bit fields:
*
* Bit 29: RBD_FETCH_IDLE
* This status flag is set by the RFH when there is no active RBD fetch from
* DRAM.
* Once the RFH RBD controller starts fetching (or when there is a pending
* RBD read response from DRAM), this flag is immediately turned off.
*
* Bit 30: SRAM_DMA_IDLE
* This status flag is set by the RFH when there is no active transaction from
* SRAM to DRAM.
* Once the SRAM to DRAM DMA is active, this flag is immediately turned off.
*
* Bit 31: RXF_DMA_IDLE
* This status flag is set by the RFH when there is no active transaction from
* RXF to DRAM.
* 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 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
/* RB size */
#define RFH_RXF_DMA_RB_SIZE_MASK (0x000F0000) /* bits 16-19 */
#define RFH_RXF_DMA_RB_SIZE_POS 16
#define RFH_RXF_DMA_RB_SIZE_1K (0x1 << RFH_RXF_DMA_RB_SIZE_POS)
#define RFH_RXF_DMA_RB_SIZE_2K (0x2 << RFH_RXF_DMA_RB_SIZE_POS)
#define RFH_RXF_DMA_RB_SIZE_4K (0x4 << RFH_RXF_DMA_RB_SIZE_POS)
#define RFH_RXF_DMA_RB_SIZE_8K (0x8 << RFH_RXF_DMA_RB_SIZE_POS)
#define RFH_RXF_DMA_RB_SIZE_12K (0x9 << RFH_RXF_DMA_RB_SIZE_POS)
#define RFH_RXF_DMA_RB_SIZE_16K (0xA << RFH_RXF_DMA_RB_SIZE_POS)
#define RFH_RXF_DMA_RB_SIZE_20K (0xB << RFH_RXF_DMA_RB_SIZE_POS)
#define RFH_RXF_DMA_RB_SIZE_24K (0xC << RFH_RXF_DMA_RB_SIZE_POS)
#define RFH_RXF_DMA_RB_SIZE_28K (0xD << RFH_RXF_DMA_RB_SIZE_POS)
#define RFH_RXF_DMA_RB_SIZE_32K (0xE << RFH_RXF_DMA_RB_SIZE_POS)
/* RB Circular Buffer size:defines the table sizes in RBD units */
#define RFH_RXF_DMA_RBDCB_SIZE_MASK (0x00F00000) /* bits 20-23 */
#define RFH_RXF_DMA_RBDCB_SIZE_POS 20
#define RFH_RXF_DMA_RBDCB_SIZE_8 (0x3 << RFH_RXF_DMA_RBDCB_SIZE_POS)
#define RFH_RXF_DMA_RBDCB_SIZE_16 (0x4 << RFH_RXF_DMA_RBDCB_SIZE_POS)
#define RFH_RXF_DMA_RBDCB_SIZE_32 (0x5 << RFH_RXF_DMA_RBDCB_SIZE_POS)
#define RFH_RXF_DMA_RBDCB_SIZE_64 (0x7 << RFH_RXF_DMA_RBDCB_SIZE_POS)
#define RFH_RXF_DMA_RBDCB_SIZE_128 (0x7 << RFH_RXF_DMA_RBDCB_SIZE_POS)
#define RFH_RXF_DMA_RBDCB_SIZE_256 (0x8 << RFH_RXF_DMA_RBDCB_SIZE_POS)
#define RFH_RXF_DMA_RBDCB_SIZE_512 (0x9 << RFH_RXF_DMA_RBDCB_SIZE_POS)
#define RFH_RXF_DMA_RBDCB_SIZE_1024 (0xA << RFH_RXF_DMA_RBDCB_SIZE_POS)
#define RFH_RXF_DMA_RBDCB_SIZE_2048 (0xB << RFH_RXF_DMA_RBDCB_SIZE_POS)
#define RFH_RXF_DMA_MIN_RB_SIZE_MASK (0x03000000) /* bit 24-25 */
#define RFH_RXF_DMA_MIN_RB_SIZE_POS 24
#define RFH_RXF_DMA_MIN_RB_4_8 (3 << RFH_RXF_DMA_MIN_RB_SIZE_POS)
#define RFH_RXF_DMA_DROP_TOO_LARGE_MASK (0x04000000) /* bit 26 */
#define RFH_RXF_DMA_SINGLE_FRAME_MASK (0x20000000) /* bit 29 */
#define RFH_DMA_EN_MASK (0xC0000000) /* bits 30-31*/
#define RFH_DMA_EN_ENABLE_VAL BIT(31)
#define RFH_RXF_RXQ_ACTIVE 0xA0980C
#define RFH_GEN_CFG 0xA09800
#define RFH_GEN_CFG_SERVICE_DMA_SNOOP BIT(0)
#define RFH_GEN_CFG_RFH_DMA_SNOOP BIT(1)
#define RFH_GEN_CFG_RB_CHUNK_SIZE BIT(4)
#define RFH_GEN_CFG_RB_CHUNK_SIZE_128 1
#define RFH_GEN_CFG_RB_CHUNK_SIZE_64 0
/* the driver assumes everywhere that the default RXQ is 0 */
#define RFH_GEN_CFG_DEFAULT_RXQ_NUM 0xF00
#define RFH_GEN_CFG_VAL(_n, _v) FIELD_PREP(RFH_GEN_CFG_ ## _n, _v)
/* end of 9000 rx series registers */
/* TFDB Area - TFDs buffer table */
#define FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK (0xFFFFFFFF)
#define FH_TFDIB_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0x900)
#define FH_TFDIB_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0x958)
#define FH_TFDIB_CTRL0_REG(_chnl) (FH_TFDIB_LOWER_BOUND + 0x8 * (_chnl))
#define FH_TFDIB_CTRL1_REG(_chnl) (FH_TFDIB_LOWER_BOUND + 0x8 * (_chnl) + 0x4)
/**
* Transmit DMA Channel Control/Status Registers (TCSR)
*
* Device has one configuration register for each of 8 Tx DMA/FIFO channels
* supported in hardware (don't confuse these with the 16 Tx queues in DRAM,
* which feed the DMA/FIFO channels); config regs are separated by 0x20 bytes.
*
* To use a Tx DMA channel, driver must initialize its
* FH_TCSR_CHNL_TX_CONFIG_REG(chnl) with:
*
* FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
* FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL
*
* All other bits should be 0.
*
* Bit fields:
* 31-30: Tx DMA channel enable: '00' off/pause, '01' pause at end of frame,
* '10' operate normally
* 29- 4: Reserved, set to "0"
* 3: Enable internal DMA requests (1, normal operation), disable (0)
* 2- 0: Reserved, set to "0"
*/
#define FH_TCSR_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0xD00)
#define FH_TCSR_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xE60)
/* Find Control/Status reg for given Tx DMA/FIFO channel */
#define FH_TCSR_CHNL_NUM (8)
/* TCSR: tx_config register values */
#define FH_TCSR_CHNL_TX_CONFIG_REG(_chnl) \
(FH_TCSR_LOWER_BOUND + 0x20 * (_chnl))
#define FH_TCSR_CHNL_TX_CREDIT_REG(_chnl) \
(FH_TCSR_LOWER_BOUND + 0x20 * (_chnl) + 0x4)
#define FH_TCSR_CHNL_TX_BUF_STS_REG(_chnl) \
(FH_TCSR_LOWER_BOUND + 0x20 * (_chnl) + 0x8)
#define FH_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_TXF (0x00000000)
#define FH_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_DRV (0x00000001)
#define FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE (0x00000000)
#define FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE (0x00000008)
#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_NOINT (0x00000000)
#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD (0x00100000)
#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_IFTFD (0x00200000)
#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_NOINT (0x00000000)
#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_ENDTFD (0x00400000)
#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_IFTFD (0x00800000)
#define FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE (0x00000000)
#define FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE_EOF (0x40000000)
#define FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE (0x80000000)
#define FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_EMPTY (0x00000000)
#define FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_WAIT (0x00002000)
#define FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID (0x00000003)
#define FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM (20)
#define FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX (12)
/**
* Tx Shared Status Registers (TSSR)
*
* After stopping Tx DMA channel (writing 0 to
* FH_TCSR_CHNL_TX_CONFIG_REG(chnl)), driver must poll
* FH_TSSR_TX_STATUS_REG until selected Tx channel is idle
* (channel's buffers empty | no pending requests).
*
* Bit fields:
* 31-24: 1 = Channel buffers empty (channel 7:0)
* 23-16: 1 = No pending requests (channel 7:0)
*/
#define FH_TSSR_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0xEA0)
#define FH_TSSR_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xEC0)
#define FH_TSSR_TX_STATUS_REG (FH_TSSR_LOWER_BOUND + 0x010)
/**
* Bit fields for TSSR(Tx Shared Status & Control) error status register:
* 31: Indicates an address error when accessed to internal memory
* uCode/driver must write "1" in order to clear this flag
* 30: Indicates that Host did not send the expected number of dwords to FH
* uCode/driver must write "1" in order to clear this flag
* 16-9:Each status bit is for one channel. Indicates that an (Error) ActDMA
* command was received from the scheduler while the TRB was already full
* with previous command
* uCode/driver must write "1" in order to clear this flag
* 7-0: Each status bit indicates a channel's TxCredit error. When an error
* bit is set, it indicates that the FH has received a full indication
* from the RTC TxFIFO and the current value of the TxCredit counter was
* not equal to zero. This mean that the credit mechanism was not
* synchronized to the TxFIFO status
* uCode/driver must write "1" in order to clear this flag
*/
#define FH_TSSR_TX_ERROR_REG (FH_TSSR_LOWER_BOUND + 0x018)
#define FH_TSSR_TX_MSG_CONFIG_REG (FH_TSSR_LOWER_BOUND + 0x008)
#define FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(_chnl) ((1 << (_chnl)) << 16)
/* Tx service channels */
#define FH_SRVC_CHNL (9)
#define FH_SRVC_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0x9C8)
#define FH_SRVC_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0x9D0)
#define FH_SRVC_CHNL_SRAM_ADDR_REG(_chnl) \
(FH_SRVC_LOWER_BOUND + ((_chnl) - 9) * 0x4)
#define FH_TX_CHICKEN_BITS_REG (FH_MEM_LOWER_BOUND + 0xE98)
#define FH_TX_TRB_REG(_chan) (FH_MEM_LOWER_BOUND + 0x958 + (_chan) * 4)
/* Instruct FH to increment the retry count of a packet when
* it is brought from the memory to TX-FIFO
*/
#define FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN (0x00000002)
#define RX_POOL_SIZE(rbds) ((rbds) - 1 + \
IWL_MAX_RX_HW_QUEUES * \
(RX_CLAIM_REQ_ALLOC - RX_POST_REQ_ALLOC))
/* cb size is the exponent */
#define RX_QUEUE_CB_SIZE(x) ilog2(x)
#define RX_QUEUE_SIZE 256
#define RX_QUEUE_MASK 255
#define RX_QUEUE_SIZE_LOG 8
/**
* struct iwl_rb_status - reserve buffer status
* host memory mapped FH registers
* @closed_rb_num [0:11] - Indicates the index of the RB which was closed
* @closed_fr_num [0:11] - Indicates the index of the RX Frame which was closed
* @finished_rb_num [0:11] - Indicates the index of the current RB
* in which the last frame was written to
* @finished_fr_num [0:11] - Indicates the index of the RX Frame
* which was transferred
*/
struct iwl_rb_status {
__le16 closed_rb_num;
__le16 closed_fr_num;
__le16 finished_rb_num;
__le16 finished_fr_nam;
__le32 spare;
} __packed;
#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 1024
#define IWL_TX_DMA_MASK DMA_BIT_MASK(36)
#define IWL_NUM_OF_TBS 20
#define IWL_TFH_NUM_TBS 25
static inline u8 iwl_get_dma_hi_addr(dma_addr_t addr)
{
return (sizeof(addr) > sizeof(u32) ? upper_32_bits(addr) : 0) & 0xF;
}
/**
* enum iwl_tfd_tb_hi_n_len - TB hi_n_len bits
* @TB_HI_N_LEN_ADDR_HI_MSK: high 4 bits (to make it 36) of DMA address
* @TB_HI_N_LEN_LEN_MSK: length of the TB
*/
enum iwl_tfd_tb_hi_n_len {
TB_HI_N_LEN_ADDR_HI_MSK = 0xf,
TB_HI_N_LEN_LEN_MSK = 0xfff0,
};
/**
* struct iwl_tfd_tb transmit buffer descriptor within transmit frame descriptor
*
* This structure contains dma address and length of transmission address
*
* @lo: low [31:0] portion of the dma address of TX buffer
* every even is unaligned on 16 bit boundary
* @hi_n_len: &enum iwl_tfd_tb_hi_n_len
*/
struct iwl_tfd_tb {
__le32 lo;
__le16 hi_n_len;
} __packed;
/**
* struct iwl_tfh_tb transmit buffer descriptor within transmit frame descriptor
*
* This structure contains dma address and length of transmission address
*
* @tb_len length of the tx buffer
* @addr 64 bits dma address
*/
struct iwl_tfh_tb {
__le16 tb_len;
__le64 addr;
} __packed;
/**
* Each Tx queue uses a circular buffer of 256 TFDs stored in host DRAM.
* Both driver and device share these circular buffers, each of which must be
* contiguous 256 TFDs.
* For pre 22000 HW it is 256 x 128 bytes-per-TFD = 32 KBytes
* For 22000 HW and on it is 256 x 256 bytes-per-TFD = 65 KBytes
*
* Driver must indicate the physical address of the base of each
* circular buffer via the FH_MEM_CBBC_QUEUE registers.
*
* Each TFD contains pointer/size information for up to 20 / 25 data buffers
* in host DRAM. These buffers collectively contain the (one) frame described
* by the TFD. Each buffer must be a single contiguous block of memory within
* itself, but buffers may be scattered in host DRAM. Each buffer has max size
* of (4K - 4). The concatenates all of a TFD's buffers into a single
* Tx frame, up to 8 KBytes in size.
*
* A maximum of 255 (not 256!) TFDs may be on a queue waiting for Tx.
*/
/**
* struct iwl_tfd - Transmit Frame Descriptor (TFD)
* @ __reserved1[3] reserved
* @ num_tbs 0-4 number of active tbs
* 5 reserved
* 6-7 padding (not used)
* @ tbs[20] transmit frame buffer descriptors
* @ __pad padding
*/
struct iwl_tfd {
u8 __reserved1[3];
u8 num_tbs;
struct iwl_tfd_tb tbs[IWL_NUM_OF_TBS];
__le32 __pad;
} __packed;
/**
* struct iwl_tfh_tfd - Transmit Frame Descriptor (TFD)
* @ num_tbs 0-4 number of active tbs
* 5 -15 reserved
* @ tbs[25] transmit frame buffer descriptors
* @ __pad padding
*/
struct iwl_tfh_tfd {
__le16 num_tbs;
struct iwl_tfh_tb tbs[IWL_TFH_NUM_TBS];
__le32 __pad;
} __packed;
/* Keep Warm Size */
#define IWL_KW_SIZE 0x1000 /* 4k */
/* Fixed (non-configurable) rx data from phy */
/**
* struct iwlagn_schedq_bc_tbl scheduler byte count table
* base physical address provided by SCD_DRAM_BASE_ADDR
* For devices up to 22000:
* @tfd_offset 0-12 - tx command byte count
* 12-16 - station index
* For 22000:
* @tfd_offset 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 scheduler byte count table 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 {
__le16 tfd_offset[TFD_QUEUE_BC_SIZE_GEN3];
} __packed;
#endif /* !__iwl_fh_h__ */

View File

@ -0,0 +1,526 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2003-2014, 2018-2021 Intel Corporation
* Copyright (C) 2015-2016 Intel Deutschland GmbH
*/
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/export.h>
#include "iwl-drv.h"
#include "iwl-io.h"
#include "iwl-csr.h"
#include "iwl-debug.h"
#include "iwl-prph.h"
#include "iwl-fh.h"
void iwl_write8(struct iwl_trans *trans, u32 ofs, u8 val)
{
trace_iwlwifi_dev_iowrite8(trans->dev, ofs, val);
iwl_trans_write8(trans, ofs, val);
}
IWL_EXPORT_SYMBOL(iwl_write8);
void iwl_write32(struct iwl_trans *trans, u32 ofs, u32 val)
{
trace_iwlwifi_dev_iowrite32(trans->dev, ofs, val);
iwl_trans_write32(trans, ofs, val);
}
IWL_EXPORT_SYMBOL(iwl_write32);
void iwl_write64(struct iwl_trans *trans, u64 ofs, u64 val)
{
trace_iwlwifi_dev_iowrite64(trans->dev, ofs, val);
iwl_trans_write32(trans, ofs, lower_32_bits(val));
iwl_trans_write32(trans, ofs + 4, upper_32_bits(val));
}
IWL_EXPORT_SYMBOL(iwl_write64);
u32 iwl_read32(struct iwl_trans *trans, u32 ofs)
{
u32 val = iwl_trans_read32(trans, ofs);
trace_iwlwifi_dev_ioread32(trans->dev, ofs, val);
return val;
}
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 t = 0;
do {
if ((iwl_read32(trans, addr) & mask) == (bits & mask))
return t;
udelay(IWL_POLL_INTERVAL);
t += IWL_POLL_INTERVAL;
} while (t < timeout);
return -ETIMEDOUT;
}
IWL_EXPORT_SYMBOL(iwl_poll_bit);
u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg)
{
u32 value = 0x5a5a5a5a;
if (iwl_trans_grab_nic_access(trans)) {
value = iwl_read32(trans, reg);
iwl_trans_release_nic_access(trans);
}
return value;
}
IWL_EXPORT_SYMBOL(iwl_read_direct32);
void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value)
{
if (iwl_trans_grab_nic_access(trans)) {
iwl_write32(trans, reg, value);
iwl_trans_release_nic_access(trans);
}
}
IWL_EXPORT_SYMBOL(iwl_write_direct32);
void iwl_write_direct64(struct iwl_trans *trans, u64 reg, u64 value)
{
if (iwl_trans_grab_nic_access(trans)) {
iwl_write64(trans, reg, 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)
{
int t = 0;
do {
if ((iwl_read_direct32(trans, addr) & mask) == mask)
return t;
udelay(IWL_POLL_INTERVAL);
t += IWL_POLL_INTERVAL;
} while (t < timeout);
return -ETIMEDOUT;
}
IWL_EXPORT_SYMBOL(iwl_poll_direct_bit);
u32 iwl_read_prph_no_grab(struct iwl_trans *trans, u32 ofs)
{
u32 val = iwl_trans_read_prph(trans, 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)
{
trace_iwlwifi_dev_iowrite_prph64(trans->dev, ofs, 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)
{
u32 val = 0x5a5a5a5a;
if (iwl_trans_grab_nic_access(trans)) {
val = iwl_read_prph_no_grab(trans, ofs);
iwl_trans_release_nic_access(trans);
}
return val;
}
IWL_EXPORT_SYMBOL(iwl_read_prph);
void iwl_write_prph_delay(struct iwl_trans *trans, u32 ofs, u32 val, u32 delay_ms)
{
if (iwl_trans_grab_nic_access(trans)) {
mdelay(delay_ms);
iwl_write_prph_no_grab(trans, ofs, val);
iwl_trans_release_nic_access(trans);
}
}
IWL_EXPORT_SYMBOL(iwl_write_prph_delay);
int iwl_poll_prph_bit(struct iwl_trans *trans, u32 addr,
u32 bits, u32 mask, int timeout)
{
int t = 0;
do {
if ((iwl_read_prph(trans, addr) & mask) == (bits & mask))
return t;
udelay(IWL_POLL_INTERVAL);
t += IWL_POLL_INTERVAL;
} while (t < timeout);
return -ETIMEDOUT;
}
void iwl_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask)
{
if (iwl_trans_grab_nic_access(trans)) {
iwl_write_prph_no_grab(trans, ofs,
iwl_read_prph_no_grab(trans, ofs) |
mask);
iwl_trans_release_nic_access(trans);
}
}
IWL_EXPORT_SYMBOL(iwl_set_bits_prph);
void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs,
u32 bits, u32 mask)
{
if (iwl_trans_grab_nic_access(trans)) {
iwl_write_prph_no_grab(trans, ofs,
(iwl_read_prph_no_grab(trans, ofs) &
mask) | bits);
iwl_trans_release_nic_access(trans);
}
}
IWL_EXPORT_SYMBOL(iwl_set_bits_mask_prph);
void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask)
{
u32 val;
if (iwl_trans_grab_nic_access(trans)) {
val = iwl_read_prph_no_grab(trans, ofs);
iwl_write_prph_no_grab(trans, ofs, (val & ~mask));
iwl_trans_release_nic_access(trans);
}
}
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)
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)
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)
iwl_write_umac_prph(trans, UREG_DOORBELL_TO_ISR6,
UREG_DOORBELL_TO_ISR6_NMI_BIT);
else
iwl_write32(trans, CSR_DOORBELL_VECTOR,
CSR_DOORBELL_VECTOR_NMI);
}
IWL_EXPORT_SYMBOL(iwl_force_nmi);
static const char *get_rfh_string(int cmd)
{
#define IWL_CMD(x) case x: return #x
#define IWL_CMD_MQ(arg, reg, q) { if (arg == reg(q)) return #reg; }
int i;
for (i = 0; i < IWL_MAX_RX_HW_QUEUES; i++) {
IWL_CMD_MQ(cmd, RFH_Q_FRBDCB_BA_LSB, i);
IWL_CMD_MQ(cmd, RFH_Q_FRBDCB_WIDX, i);
IWL_CMD_MQ(cmd, RFH_Q_FRBDCB_RIDX, i);
IWL_CMD_MQ(cmd, RFH_Q_URBD_STTS_WPTR_LSB, i);
}
switch (cmd) {
IWL_CMD(RFH_RXF_DMA_CFG);
IWL_CMD(RFH_GEN_CFG);
IWL_CMD(RFH_GEN_STATUS);
IWL_CMD(FH_TSSR_TX_STATUS_REG);
IWL_CMD(FH_TSSR_TX_ERROR_REG);
default:
return "UNKNOWN";
}
#undef IWL_CMD_MQ
}
struct reg {
u32 addr;
bool is64;
};
static int iwl_dump_rfh(struct iwl_trans *trans, char **buf)
{
int i, q;
int num_q = trans->num_rx_queues;
static const u32 rfh_tbl[] = {
RFH_RXF_DMA_CFG,
RFH_GEN_CFG,
RFH_GEN_STATUS,
FH_TSSR_TX_STATUS_REG,
FH_TSSR_TX_ERROR_REG,
};
static const struct reg rfh_mq_tbl[] = {
{ RFH_Q0_FRBDCB_BA_LSB, true },
{ RFH_Q0_FRBDCB_WIDX, false },
{ RFH_Q0_FRBDCB_RIDX, false },
{ RFH_Q0_URBD_STTS_WPTR_LSB, true },
};
#ifdef CONFIG_IWLWIFI_DEBUGFS
if (buf) {
int pos = 0;
/*
* Register (up to 34 for name + 8 blank/q for MQ): 40 chars
* Colon + space: 2 characters
* 0X%08x: 10 characters
* New line: 1 character
* Total of 53 characters
*/
size_t bufsz = ARRAY_SIZE(rfh_tbl) * 53 +
ARRAY_SIZE(rfh_mq_tbl) * 53 * num_q + 40;
*buf = kmalloc(bufsz, GFP_KERNEL);
if (!*buf)
return -ENOMEM;
pos += scnprintf(*buf + pos, bufsz - pos,
"RFH register values:\n");
for (i = 0; i < ARRAY_SIZE(rfh_tbl); i++)
pos += scnprintf(*buf + pos, bufsz - pos,
"%40s: 0X%08x\n",
get_rfh_string(rfh_tbl[i]),
iwl_read_prph(trans, rfh_tbl[i]));
for (i = 0; i < ARRAY_SIZE(rfh_mq_tbl); i++)
for (q = 0; q < num_q; q++) {
u32 addr = rfh_mq_tbl[i].addr;
addr += q * (rfh_mq_tbl[i].is64 ? 8 : 4);
pos += scnprintf(*buf + pos, bufsz - pos,
"%34s(q %2d): 0X%08x\n",
get_rfh_string(addr), q,
iwl_read_prph(trans, addr));
}
return pos;
}
#endif
IWL_ERR(trans, "RFH register values:\n");
for (i = 0; i < ARRAY_SIZE(rfh_tbl); i++)
IWL_ERR(trans, " %34s: 0X%08x\n",
get_rfh_string(rfh_tbl[i]),
iwl_read_prph(trans, rfh_tbl[i]));
for (i = 0; i < ARRAY_SIZE(rfh_mq_tbl); i++)
for (q = 0; q < num_q; q++) {
u32 addr = rfh_mq_tbl[i].addr;
addr += q * (rfh_mq_tbl[i].is64 ? 8 : 4);
IWL_ERR(trans, " %34s(q %d): 0X%08x\n",
get_rfh_string(addr), q,
iwl_read_prph(trans, addr));
}
return 0;
}
static const char *get_fh_string(int cmd)
{
switch (cmd) {
IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG);
IWL_CMD(FH_RSCSR_CHNL0_RBDCB_BASE_REG);
IWL_CMD(FH_RSCSR_CHNL0_WPTR);
IWL_CMD(FH_MEM_RCSR_CHNL0_CONFIG_REG);
IWL_CMD(FH_MEM_RSSR_SHARED_CTRL_REG);
IWL_CMD(FH_MEM_RSSR_RX_STATUS_REG);
IWL_CMD(FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV);
IWL_CMD(FH_TSSR_TX_STATUS_REG);
IWL_CMD(FH_TSSR_TX_ERROR_REG);
default:
return "UNKNOWN";
}
#undef IWL_CMD
}
int iwl_dump_fh(struct iwl_trans *trans, char **buf)
{
int i;
static const u32 fh_tbl[] = {
FH_RSCSR_CHNL0_STTS_WPTR_REG,
FH_RSCSR_CHNL0_RBDCB_BASE_REG,
FH_RSCSR_CHNL0_WPTR,
FH_MEM_RCSR_CHNL0_CONFIG_REG,
FH_MEM_RSSR_SHARED_CTRL_REG,
FH_MEM_RSSR_RX_STATUS_REG,
FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV,
FH_TSSR_TX_STATUS_REG,
FH_TSSR_TX_ERROR_REG
};
if (trans->trans_cfg->mq_rx_supported)
return iwl_dump_rfh(trans, buf);
#ifdef CONFIG_IWLWIFI_DEBUGFS
if (buf) {
int pos = 0;
size_t bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40;
*buf = kmalloc(bufsz, GFP_KERNEL);
if (!*buf)
return -ENOMEM;
pos += scnprintf(*buf + pos, bufsz - pos,
"FH register values:\n");
for (i = 0; i < ARRAY_SIZE(fh_tbl); i++)
pos += scnprintf(*buf + pos, bufsz - pos,
" %34s: 0X%08x\n",
get_fh_string(fh_tbl[i]),
iwl_read_direct32(trans, fh_tbl[i]));
return pos;
}
#endif
IWL_ERR(trans, "FH register values:\n");
for (i = 0; i < ARRAY_SIZE(fh_tbl); i++)
IWL_ERR(trans, " %34s: 0X%08x\n",
get_fh_string(fh_tbl[i]),
iwl_read_direct32(trans, fh_tbl[i]));
return 0;
}
#define IWL_HOST_MON_BLOCK_PEMON 0x00
#define IWL_HOST_MON_BLOCK_HIPM 0x22
#define IWL_HOST_MON_BLOCK_PEMON_VEC0 0x00
#define IWL_HOST_MON_BLOCK_PEMON_VEC1 0x01
#define IWL_HOST_MON_BLOCK_PEMON_WFPM 0x06
static void iwl_dump_host_monitor_block(struct iwl_trans *trans,
u32 block, u32 vec, u32 iter)
{
int i;
IWL_ERR(trans, "Host monitor block 0x%x vector 0x%x\n", block, vec);
iwl_write32(trans, CSR_MONITOR_CFG_REG, (block << 8) | vec);
for (i = 0; i < iter; i++)
IWL_ERR(trans, " value [iter %d]: 0x%08x\n",
i, iwl_read32(trans, CSR_MONITOR_STATUS_REG));
}
static void iwl_dump_host_monitor(struct iwl_trans *trans)
{
switch (trans->trans_cfg->device_family) {
case IWL_DEVICE_FAMILY_22000:
case IWL_DEVICE_FAMILY_AX210:
IWL_ERR(trans, "CSR_RESET = 0x%x\n",
iwl_read32(trans, CSR_RESET));
iwl_dump_host_monitor_block(trans, IWL_HOST_MON_BLOCK_PEMON,
IWL_HOST_MON_BLOCK_PEMON_VEC0, 15);
iwl_dump_host_monitor_block(trans, IWL_HOST_MON_BLOCK_PEMON,
IWL_HOST_MON_BLOCK_PEMON_VEC1, 15);
iwl_dump_host_monitor_block(trans, IWL_HOST_MON_BLOCK_PEMON,
IWL_HOST_MON_BLOCK_PEMON_WFPM, 15);
iwl_dump_host_monitor_block(trans, IWL_HOST_MON_BLOCK_HIPM,
IWL_HOST_MON_BLOCK_PEMON_VEC0, 1);
break;
default:
/* not supported yet */
return;
}
}
int iwl_finish_nic_init(struct iwl_trans *trans)
{
const struct iwl_cfg_trans_params *cfg_trans = trans->trans_cfg;
u32 poll_ready;
int err;
if (cfg_trans->bisr_workaround) {
/* ensure the TOP FSM isn't still in previous reset */
mdelay(2);
}
/*
* Set "initialization complete" bit to move adapter from
* D0U* --> D0A* (powered-up active) state.
*/
if (cfg_trans->device_family >= IWL_DEVICE_FAMILY_BZ) {
iwl_set_bit(trans, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
CSR_GP_CNTRL_REG_FLAG_MAC_INIT);
poll_ready = CSR_GP_CNTRL_REG_FLAG_MAC_STATUS;
} else {
iwl_set_bit(trans, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
poll_ready = CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY;
}
if (cfg_trans->device_family == IWL_DEVICE_FAMILY_8000)
udelay(2);
/*
* Wait for clock stabilization; once stabilized, access to
* 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);
if (err < 0) {
IWL_DEBUG_INFO(trans, "Failed to wake NIC\n");
iwl_dump_host_monitor(trans);
}
if (cfg_trans->bisr_workaround) {
/* ensure BISR shift has finished */
udelay(200);
}
return err < 0 ? err : 0;
}
IWL_EXPORT_SYMBOL(iwl_finish_nic_init);
void iwl_trans_sync_nmi_with_addr(struct iwl_trans *trans, u32 inta_addr,
u32 sw_err_bit)
{
unsigned long timeout = jiffies + IWL_TRANS_NMI_TIMEOUT;
bool interrupts_enabled = test_bit(STATUS_INT_ENABLED, &trans->status);
/* if the interrupts were already disabled, there is no point in
* calling iwl_disable_interrupts
*/
if (interrupts_enabled)
iwl_trans_interrupts(trans, false);
iwl_force_nmi(trans);
while (time_after(timeout, jiffies)) {
u32 inta_hw = iwl_read32(trans, inta_addr);
/* Error detected by uCode */
if (inta_hw & sw_err_bit) {
/* Clear causes register */
iwl_write32(trans, inta_addr, inta_hw & sw_err_bit);
break;
}
mdelay(1);
}
/* enable interrupts only if there were already enabled before this
* function to avoid a case were the driver enable interrupts before
* proper configurations were made
*/
if (interrupts_enabled)
iwl_trans_interrupts(trans, true);
iwl_trans_fw_error(trans, false);
}

View File

@ -0,0 +1,102 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2018-2021 Intel Corporation
*/
#ifndef __iwl_io_h__
#define __iwl_io_h__
#include "iwl-devtrace.h"
#include "iwl-trans.h"
void iwl_write8(struct iwl_trans *trans, u32 ofs, u8 val);
void iwl_write32(struct iwl_trans *trans, u32 ofs, u32 val);
void iwl_write64(struct iwl_trans *trans, u64 ofs, u64 val);
u32 iwl_read32(struct iwl_trans *trans, u32 ofs);
static inline void iwl_set_bit(struct iwl_trans *trans, u32 reg, u32 mask)
{
iwl_trans_set_bits_mask(trans, reg, mask, mask);
}
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_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask,
int timeout);
u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg);
void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value);
void iwl_write_direct64(struct iwl_trans *trans, u64 reg, u64 value);
u32 iwl_read_prph_no_grab(struct iwl_trans *trans, u32 ofs);
u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs);
void iwl_write_prph_no_grab(struct iwl_trans *trans, u32 ofs, u32 val);
void iwl_write_prph64_no_grab(struct iwl_trans *trans, u64 ofs, u64 val);
void iwl_write_prph_delay(struct iwl_trans *trans, u32 ofs,
u32 val, u32 delay_ms);
static inline void iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val)
{
iwl_write_prph_delay(trans, ofs, val, 0);
}
int iwl_poll_prph_bit(struct iwl_trans *trans, u32 addr,
u32 bits, u32 mask, int timeout);
void iwl_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask);
void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs,
u32 bits, u32 mask);
void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask);
void iwl_force_nmi(struct iwl_trans *trans);
int iwl_finish_nic_init(struct iwl_trans *trans);
/* Error handling */
int iwl_dump_fh(struct iwl_trans *trans, char **buf);
/*
* UMAC periphery address space changed from 0xA00000 to 0xD00000 starting from
* device family AX200. So peripheries used in families above and below AX200
* should go through iwl_..._umac_..._prph.
*/
static inline u32 iwl_umac_prph(struct iwl_trans *trans, u32 ofs)
{
return ofs + trans->trans_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);
}
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);
}
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,
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);
}
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,
bits, mask, timeout);
}
#endif

View File

@ -0,0 +1,110 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2005-2014, 2018-2020 Intel Corporation
*/
#ifndef __iwl_modparams_h__
#define __iwl_modparams_h__
#include <linux/types.h>
#include <linux/spinlock.h>
#include <linux/gfp.h>
#ifdef CONFIG_IWLWIFI_DEBUG
#include "iwl-debug.h"
#endif
extern struct iwl_mod_params iwlwifi_mod_params;
enum iwl_power_level {
IWL_POWER_INDEX_1,
IWL_POWER_INDEX_2,
IWL_POWER_INDEX_3,
IWL_POWER_INDEX_4,
IWL_POWER_INDEX_5,
IWL_POWER_NUM
};
enum iwl_disable_11n {
IWL_DISABLE_HT_ALL = BIT(0),
IWL_DISABLE_HT_TXAGG = BIT(1),
IWL_DISABLE_HT_RXAGG = BIT(2),
IWL_ENABLE_HT_TXAGG = BIT(3),
};
enum iwl_amsdu_size {
IWL_AMSDU_DEF = 0,
IWL_AMSDU_4K = 1,
IWL_AMSDU_8K = 2,
IWL_AMSDU_12K = 3,
/* Add 2K at the end to avoid breaking current API */
IWL_AMSDU_2K = 4,
};
enum iwl_uapsd_disable {
IWL_DISABLE_UAPSD_BSS = BIT(0),
IWL_DISABLE_UAPSD_P2P_CLIENT = BIT(1),
};
/**
* struct iwl_mod_params
*
* Holds the module parameters
*
* @swcrypto: using hardware encryption, default = 0
* @disable_11n: disable 11n capabilities, default = 0,
* use IWL_[DIS,EN]ABLE_HT_* constants
* @amsdu_size: See &enum iwl_amsdu_size.
* @fw_restart: restart firmware, default = 1
* @bt_coex_active: enable bt coex, default = true
* @led_mode: system default, default = 0
* @power_save: enable power save, default = false
* @power_level: power level, default = 1
* @debug_level: levels are IWL_DL_*
* @nvm_file: specifies a external NVM file
* @uapsd_disable: disable U-APSD, see &enum iwl_uapsd_disable, default =
* IWL_DISABLE_UAPSD_BSS | IWL_DISABLE_UAPSD_P2P_CLIENT
* @disable_11ac: disable VHT capabilities, default = false.
* @remove_when_gone: remove an inaccessible device from the PCIe bus.
* @enable_ini: enable new FW debug infratructure (INI TLVs)
*/
struct iwl_mod_params {
int swcrypto;
unsigned int disable_11n;
int amsdu_size;
bool fw_restart;
bool bt_coex_active;
int led_mode;
bool power_save;
int power_level;
#ifdef CONFIG_IWLWIFI_DEBUG
enum iwl_dl debug_level;
#endif
char *nvm_file;
u32 uapsd_disable;
bool disable_11ac;
/**
* @disable_11ax: disable HE capabilities, default = false
*/
bool disable_11ax;
bool remove_when_gone;
bool enable_ini;
};
static inline bool iwl_enable_rx_ampdu(void)
{
if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_RXAGG)
return false;
return true;
}
static inline bool iwl_enable_tx_ampdu(void)
{
if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG)
return false;
if (iwlwifi_mod_params.disable_11n & IWL_ENABLE_HT_TXAGG)
return true;
/* enabled by default */
return true;
}
#endif /* #__iwl_modparams_h__ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,84 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2005-2015, 2018-2020 Intel Corporation
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
#ifndef __iwl_nvm_parse_h__
#define __iwl_nvm_parse_h__
#include <net/cfg80211.h>
#include "iwl-eeprom-parse.h"
/**
* enum iwl_nvm_sbands_flags - modification flags for the channel profiles
*
* @IWL_NVM_SBANDS_FLAGS_LAR: LAR is enabled
* @IWL_NVM_SBANDS_FLAGS_NO_WIDE_IN_5GHZ: disallow 40, 80 and 160MHz on 5GHz
*/
enum iwl_nvm_sbands_flags {
IWL_NVM_SBANDS_FLAGS_LAR = BIT(0),
IWL_NVM_SBANDS_FLAGS_NO_WIDE_IN_5GHZ = BIT(1),
};
/**
* iwl_parse_nvm_data - parse NVM data and return values
*
* This function parses all NVM values we need and then
* returns a (newly allocated) struct containing all the
* relevant values for driver use. The struct must be freed
* later with iwl_free_nvm_data().
*/
struct iwl_nvm_data *
iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
const struct iwl_fw *fw,
const __be16 *nvm_hw, const __le16 *nvm_sw,
const __le16 *nvm_calib, const __le16 *regulatory,
const __le16 *mac_override, const __le16 *phy_sku,
u8 tx_chains, u8 rx_chains);
/**
* iwl_parse_mcc_info - parse MCC (mobile country code) info coming from FW
*
* This function parses the regulatory channel data received as a
* MCC_UPDATE_CMD command. It returns a newly allocation regulatory domain,
* to be fed into the regulatory core. In case the geo_info is set handle
* 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.
*/
struct ieee80211_regdomain *
iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
int num_of_ch, __le32 *channels, u16 fw_mcc,
u16 geo_info, u16 cap, u8 resp_ver);
/**
* struct iwl_nvm_section - describes an NVM section in memory.
*
* This struct holds an NVM section read from the NIC using NVM_ACCESS_CMD,
* and saved for later use by the driver. Not all NVM sections are saved
* this way, only the needed ones.
*/
struct iwl_nvm_section {
u16 length;
const u8 *data;
};
/**
* iwl_read_external_nvm - Reads external NVM from a file into nvm_sections
*/
int iwl_read_external_nvm(struct iwl_trans *trans,
const char *nvm_file_name,
struct iwl_nvm_section *nvm_sections);
void iwl_nvm_fixups(u32 hw_id, unsigned int section, u8 *data,
unsigned int len);
/**
* iwl_get_nvm - retrieve NVM data from firmware
*
* Allocates a new iwl_nvm_data structure, fills it with
* NVM data, and returns it to caller.
*/
struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans,
const struct iwl_fw *fw);
#endif /* __iwl_nvm_parse_h__ */

View File

@ -0,0 +1,215 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2005-2014, 2018-2021 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2015 Intel Deutschland GmbH
*/
#ifndef __iwl_op_mode_h__
#define __iwl_op_mode_h__
#include <linux/netdevice.h>
#include <linux/debugfs.h>
#include "iwl-dbg-tlv.h"
struct iwl_op_mode;
struct iwl_trans;
struct sk_buff;
struct iwl_device_cmd;
struct iwl_rx_cmd_buffer;
struct iwl_fw;
struct iwl_cfg;
/**
* DOC: Operational mode - what is it ?
*
* The operational mode (a.k.a. op_mode) is the layer that implements
* mac80211's handlers. It knows two APIs: mac80211's and the fw's. It uses
* the transport API to access the HW. The op_mode doesn't need to know how the
* underlying HW works, since the transport layer takes care of that.
*
* There can be several op_mode: i.e. different fw APIs will require two
* different op_modes. This is why the op_mode is virtualized.
*/
/**
* DOC: Life cycle of the Operational mode
*
* The operational mode has a very simple life cycle.
*
* 1) The driver layer (iwl-drv.c) chooses the op_mode based on the
* capabilities advertised by the fw file (in TLV format).
* 2) The driver layer starts the op_mode (ops->start)
* 3) The op_mode registers mac80211
* 4) The op_mode is governed by mac80211
* 5) The driver layer stops the op_mode
*/
/**
* struct iwl_op_mode_ops - op_mode specific operations
*
* The op_mode exports its ops so that external components can start it and
* interact with it. The driver layer typically calls the start and stop
* handlers, the transport layer calls the others.
*
* All the handlers MUST be implemented, except @rx_rss which can be left
* out *iff* the opmode will never run on hardware with multi-queue capability.
*
* @start: start the op_mode. The transport layer is already allocated.
* May sleep
* @stop: stop the op_mode. Must free all the memory allocated.
* May sleep
* @rx: Rx notification to the op_mode. rxb is the Rx buffer itself. Cmd is the
* HCMD this Rx responds to. Can't sleep.
* @rx_rss: data queue RX notification to the op_mode, for (data) notifications
* received on the RSS queue(s). The queue parameter indicates which of the
* RSS queues received this frame; it will always be non-zero.
* This method must not sleep.
* @async_cb: called when an ASYNC command with CMD_WANT_ASYNC_CALLBACK set
* completes. Must be atomic.
* @queue_full: notifies that a HW queue is full.
* Must be atomic and called with BH disabled.
* @queue_not_full: notifies that a HW queue is not full any more.
* Must be atomic and called with BH disabled.
* @hw_rf_kill:notifies of a change in the HW rf kill switch. True means that
* the radio is killed. Return %true if the device should be stopped by
* the transport immediately after the call. May sleep.
* @free_skb: allows the transport layer to free skbs that haven't been
* 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_config: configure NIC, called before firmware is started.
* May sleep
* @wimax_active: invoked when WiMax becomes active. May sleep
* @time_point: called when transport layer wants to collect debug data
*/
struct iwl_op_mode_ops {
struct iwl_op_mode *(*start)(struct iwl_trans *trans,
const struct iwl_cfg *cfg,
const struct iwl_fw *fw,
struct dentry *dbgfs_dir);
void (*stop)(struct iwl_op_mode *op_mode);
void (*rx)(struct iwl_op_mode *op_mode, struct napi_struct *napi,
struct iwl_rx_cmd_buffer *rxb);
void (*rx_rss)(struct iwl_op_mode *op_mode, struct napi_struct *napi,
struct iwl_rx_cmd_buffer *rxb, unsigned int queue);
void (*async_cb)(struct iwl_op_mode *op_mode,
const struct iwl_device_cmd *cmd);
void (*queue_full)(struct iwl_op_mode *op_mode, int queue);
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_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);
};
int iwl_opmode_register(const char *name, const struct iwl_op_mode_ops *ops);
void iwl_opmode_deregister(const char *name);
/**
* struct iwl_op_mode - operational mode
* @ops: pointer to its own ops
*
* This holds an implementation of the mac80211 / fw API.
*/
struct iwl_op_mode {
const struct iwl_op_mode_ops *ops;
char op_mode_specific[] __aligned(sizeof(void *));
};
static inline void iwl_op_mode_stop(struct iwl_op_mode *op_mode)
{
might_sleep();
op_mode->ops->stop(op_mode);
}
static inline void iwl_op_mode_rx(struct iwl_op_mode *op_mode,
struct napi_struct *napi,
struct iwl_rx_cmd_buffer *rxb)
{
return op_mode->ops->rx(op_mode, napi, rxb);
}
static inline void iwl_op_mode_rx_rss(struct iwl_op_mode *op_mode,
struct napi_struct *napi,
struct iwl_rx_cmd_buffer *rxb,
unsigned int queue)
{
op_mode->ops->rx_rss(op_mode, napi, rxb, queue);
}
static inline void iwl_op_mode_async_cb(struct iwl_op_mode *op_mode,
const struct iwl_device_cmd *cmd)
{
if (op_mode->ops->async_cb)
op_mode->ops->async_cb(op_mode, cmd);
}
static inline void iwl_op_mode_queue_full(struct iwl_op_mode *op_mode,
int queue)
{
op_mode->ops->queue_full(op_mode, queue);
}
static inline void iwl_op_mode_queue_not_full(struct iwl_op_mode *op_mode,
int queue)
{
op_mode->ops->queue_not_full(op_mode, queue);
}
static inline bool __must_check
iwl_op_mode_hw_rf_kill(struct iwl_op_mode *op_mode, bool state)
{
might_sleep();
return op_mode->ops->hw_rf_kill(op_mode, state);
}
static inline void iwl_op_mode_free_skb(struct iwl_op_mode *op_mode,
struct sk_buff *skb)
{
if (WARN_ON_ONCE(!op_mode))
return;
op_mode->ops->free_skb(op_mode, skb);
}
static inline void iwl_op_mode_nic_error(struct iwl_op_mode *op_mode, bool sync)
{
op_mode->ops->nic_error(op_mode, sync);
}
static inline void iwl_op_mode_cmd_queue_full(struct iwl_op_mode *op_mode)
{
op_mode->ops->cmd_queue_full(op_mode);
}
static inline void iwl_op_mode_nic_config(struct iwl_op_mode *op_mode)
{
might_sleep();
op_mode->ops->nic_config(op_mode);
}
static inline void iwl_op_mode_wimax_active(struct iwl_op_mode *op_mode)
{
might_sleep();
op_mode->ops->wimax_active(op_mode);
}
static inline void iwl_op_mode_time_point(struct iwl_op_mode *op_mode,
enum iwl_fw_ini_time_point tp_id,
union iwl_dbg_tlv_tp_data *tp_data)
{
if (!op_mode || !op_mode->ops || !op_mode->ops->time_point)
return;
op_mode->ops->time_point(op_mode, tp_id, tp_data);
}
#endif /* __iwl_op_mode_h__ */

View File

@ -0,0 +1,440 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2005-2014, 2020 Intel Corporation
* Copyright (C) 2016 Intel Deutschland GmbH
*/
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/export.h>
#include "iwl-drv.h"
#include "iwl-phy-db.h"
#include "iwl-debug.h"
#include "iwl-op-mode.h"
#include "iwl-trans.h"
#define CHANNEL_NUM_SIZE 4 /* num of channels in calib_ch size */
struct iwl_phy_db_entry {
u16 size;
u8 *data;
};
/**
* struct iwl_phy_db - stores phy configuration and calibration data.
*
* @cfg: phy configuration.
* @calib_nch: non channel specific calibration data.
* @n_group_papd: number of entries in papd channel group.
* @calib_ch_group_papd: calibration data related to papd channel group.
* @n_group_txp: number of entries in tx power channel group.
* @calib_ch_group_txp: calibration data related to tx power chanel group.
* @trans: transport layer
*/
struct iwl_phy_db {
struct iwl_phy_db_entry cfg;
struct iwl_phy_db_entry calib_nch;
int n_group_papd;
struct iwl_phy_db_entry *calib_ch_group_papd;
int n_group_txp;
struct iwl_phy_db_entry *calib_ch_group_txp;
struct iwl_trans *trans;
};
enum iwl_phy_db_section_type {
IWL_PHY_DB_CFG = 1,
IWL_PHY_DB_CALIB_NCH,
IWL_PHY_DB_UNUSED,
IWL_PHY_DB_CALIB_CHG_PAPD,
IWL_PHY_DB_CALIB_CHG_TXP,
IWL_PHY_DB_MAX
};
#define PHY_DB_CMD 0x6c
/* for parsing of tx power channel group data that comes from the firmware*/
struct iwl_phy_db_chg_txp {
__le32 space;
__le16 max_channel_idx;
} __packed;
struct iwl_phy_db *iwl_phy_db_init(struct iwl_trans *trans)
{
struct iwl_phy_db *phy_db = kzalloc(sizeof(struct iwl_phy_db),
GFP_KERNEL);
if (!phy_db)
return phy_db;
phy_db->trans = trans;
phy_db->n_group_txp = -1;
phy_db->n_group_papd = -1;
/* TODO: add default values of the phy db. */
return phy_db;
}
IWL_EXPORT_SYMBOL(iwl_phy_db_init);
/*
* get phy db section: returns a pointer to a phy db section specified by
* type and channel group id.
*/
static struct iwl_phy_db_entry *
iwl_phy_db_get_section(struct iwl_phy_db *phy_db,
enum iwl_phy_db_section_type type,
u16 chg_id)
{
if (!phy_db || type >= IWL_PHY_DB_MAX)
return NULL;
switch (type) {
case IWL_PHY_DB_CFG:
return &phy_db->cfg;
case IWL_PHY_DB_CALIB_NCH:
return &phy_db->calib_nch;
case IWL_PHY_DB_CALIB_CHG_PAPD:
if (chg_id >= phy_db->n_group_papd)
return NULL;
return &phy_db->calib_ch_group_papd[chg_id];
case IWL_PHY_DB_CALIB_CHG_TXP:
if (chg_id >= phy_db->n_group_txp)
return NULL;
return &phy_db->calib_ch_group_txp[chg_id];
default:
return NULL;
}
return NULL;
}
static void iwl_phy_db_free_section(struct iwl_phy_db *phy_db,
enum iwl_phy_db_section_type type,
u16 chg_id)
{
struct iwl_phy_db_entry *entry =
iwl_phy_db_get_section(phy_db, type, chg_id);
if (!entry)
return;
kfree(entry->data);
entry->data = NULL;
entry->size = 0;
}
void iwl_phy_db_free(struct iwl_phy_db *phy_db)
{
int i;
if (!phy_db)
return;
iwl_phy_db_free_section(phy_db, IWL_PHY_DB_CFG, 0);
iwl_phy_db_free_section(phy_db, IWL_PHY_DB_CALIB_NCH, 0);
for (i = 0; i < phy_db->n_group_papd; i++)
iwl_phy_db_free_section(phy_db, IWL_PHY_DB_CALIB_CHG_PAPD, i);
kfree(phy_db->calib_ch_group_papd);
for (i = 0; i < phy_db->n_group_txp; i++)
iwl_phy_db_free_section(phy_db, IWL_PHY_DB_CALIB_CHG_TXP, i);
kfree(phy_db->calib_ch_group_txp);
kfree(phy_db);
}
IWL_EXPORT_SYMBOL(iwl_phy_db_free);
int iwl_phy_db_set_section(struct iwl_phy_db *phy_db,
struct iwl_rx_packet *pkt)
{
unsigned int pkt_len = iwl_rx_packet_payload_len(pkt);
struct iwl_calib_res_notif_phy_db *phy_db_notif =
(struct iwl_calib_res_notif_phy_db *)pkt->data;
enum iwl_phy_db_section_type type;
u16 size;
struct iwl_phy_db_entry *entry;
u16 chg_id = 0;
if (pkt_len < sizeof(*phy_db_notif))
return -EINVAL;
type = le16_to_cpu(phy_db_notif->type);
size = le16_to_cpu(phy_db_notif->length);
if (pkt_len < sizeof(*phy_db_notif) + size)
return -EINVAL;
if (!phy_db)
return -EINVAL;
if (type == IWL_PHY_DB_CALIB_CHG_PAPD) {
chg_id = le16_to_cpup((__le16 *)phy_db_notif->data);
if (phy_db && !phy_db->calib_ch_group_papd) {
/*
* Firmware sends the largest index first, so we can use
* it to know how much we should allocate.
*/
phy_db->calib_ch_group_papd = kcalloc(chg_id + 1,
sizeof(struct iwl_phy_db_entry),
GFP_ATOMIC);
if (!phy_db->calib_ch_group_papd)
return -ENOMEM;
phy_db->n_group_papd = chg_id + 1;
}
} else if (type == IWL_PHY_DB_CALIB_CHG_TXP) {
chg_id = le16_to_cpup((__le16 *)phy_db_notif->data);
if (phy_db && !phy_db->calib_ch_group_txp) {
/*
* Firmware sends the largest index first, so we can use
* it to know how much we should allocate.
*/
phy_db->calib_ch_group_txp = kcalloc(chg_id + 1,
sizeof(struct iwl_phy_db_entry),
GFP_ATOMIC);
if (!phy_db->calib_ch_group_txp)
return -ENOMEM;
phy_db->n_group_txp = chg_id + 1;
}
}
entry = iwl_phy_db_get_section(phy_db, type, chg_id);
if (!entry)
return -EINVAL;
kfree(entry->data);
entry->data = kmemdup(phy_db_notif->data, size, GFP_ATOMIC);
if (!entry->data) {
entry->size = 0;
return -ENOMEM;
}
entry->size = size;
IWL_DEBUG_INFO(phy_db->trans,
"%s(%d): [PHYDB]SET: Type %d , Size: %d\n",
__func__, __LINE__, type, size);
return 0;
}
IWL_EXPORT_SYMBOL(iwl_phy_db_set_section);
static int is_valid_channel(u16 ch_id)
{
if (ch_id <= 14 ||
(36 <= ch_id && ch_id <= 64 && ch_id % 4 == 0) ||
(100 <= ch_id && ch_id <= 140 && ch_id % 4 == 0) ||
(145 <= ch_id && ch_id <= 165 && ch_id % 4 == 1))
return 1;
return 0;
}
static u8 ch_id_to_ch_index(u16 ch_id)
{
if (WARN_ON(!is_valid_channel(ch_id)))
return 0xff;
if (ch_id <= 14)
return ch_id - 1;
if (ch_id <= 64)
return (ch_id + 20) / 4;
if (ch_id <= 140)
return (ch_id - 12) / 4;
return (ch_id - 13) / 4;
}
static u16 channel_id_to_papd(u16 ch_id)
{
if (WARN_ON(!is_valid_channel(ch_id)))
return 0xff;
if (1 <= ch_id && ch_id <= 14)
return 0;
if (36 <= ch_id && ch_id <= 64)
return 1;
if (100 <= ch_id && ch_id <= 140)
return 2;
return 3;
}
static u16 channel_id_to_txp(struct iwl_phy_db *phy_db, u16 ch_id)
{
struct iwl_phy_db_chg_txp *txp_chg;
int i;
u8 ch_index = ch_id_to_ch_index(ch_id);
if (ch_index == 0xff)
return 0xff;
for (i = 0; i < phy_db->n_group_txp; i++) {
txp_chg = (void *)phy_db->calib_ch_group_txp[i].data;
if (!txp_chg)
return 0xff;
/*
* Looking for the first channel group that its max channel is
* higher then wanted channel.
*/
if (le16_to_cpu(txp_chg->max_channel_idx) >= ch_index)
return i;
}
return 0xff;
}
static
int iwl_phy_db_get_section_data(struct iwl_phy_db *phy_db,
u32 type, u8 **data, u16 *size, u16 ch_id)
{
struct iwl_phy_db_entry *entry;
u16 ch_group_id = 0;
if (!phy_db)
return -EINVAL;
/* find wanted channel group */
if (type == IWL_PHY_DB_CALIB_CHG_PAPD)
ch_group_id = channel_id_to_papd(ch_id);
else if (type == IWL_PHY_DB_CALIB_CHG_TXP)
ch_group_id = channel_id_to_txp(phy_db, ch_id);
entry = iwl_phy_db_get_section(phy_db, type, ch_group_id);
if (!entry)
return -EINVAL;
*data = entry->data;
*size = entry->size;
IWL_DEBUG_INFO(phy_db->trans,
"%s(%d): [PHYDB] GET: Type %d , Size: %d\n",
__func__, __LINE__, type, *size);
return 0;
}
static int iwl_send_phy_db_cmd(struct iwl_phy_db *phy_db, u16 type,
u16 length, void *data)
{
struct iwl_phy_db_cmd phy_db_cmd;
struct iwl_host_cmd cmd = {
.id = PHY_DB_CMD,
};
IWL_DEBUG_INFO(phy_db->trans,
"Sending PHY-DB hcmd of type %d, of length %d\n",
type, length);
/* Set phy db cmd variables */
phy_db_cmd.type = cpu_to_le16(type);
phy_db_cmd.length = cpu_to_le16(length);
/* Set hcmd variables */
cmd.data[0] = &phy_db_cmd;
cmd.len[0] = sizeof(struct iwl_phy_db_cmd);
cmd.data[1] = data;
cmd.len[1] = length;
cmd.dataflags[1] = IWL_HCMD_DFL_NOCOPY;
return iwl_trans_send_cmd(phy_db->trans, &cmd);
}
static int iwl_phy_db_send_all_channel_groups(
struct iwl_phy_db *phy_db,
enum iwl_phy_db_section_type type,
u8 max_ch_groups)
{
u16 i;
int err;
struct iwl_phy_db_entry *entry;
/* Send all the channel specific groups to operational fw */
for (i = 0; i < max_ch_groups; i++) {
entry = iwl_phy_db_get_section(phy_db,
type,
i);
if (!entry)
return -EINVAL;
if (!entry->size)
continue;
/* Send the requested PHY DB section */
err = iwl_send_phy_db_cmd(phy_db,
type,
entry->size,
entry->data);
if (err) {
IWL_ERR(phy_db->trans,
"Can't SEND phy_db section %d (%d), err %d\n",
type, i, err);
return err;
}
IWL_DEBUG_INFO(phy_db->trans,
"Sent PHY_DB HCMD, type = %d num = %d\n",
type, i);
}
return 0;
}
int iwl_send_phy_db_data(struct iwl_phy_db *phy_db)
{
u8 *data = NULL;
u16 size = 0;
int err;
IWL_DEBUG_INFO(phy_db->trans,
"Sending phy db data and configuration to runtime image\n");
/* Send PHY DB CFG section */
err = iwl_phy_db_get_section_data(phy_db, IWL_PHY_DB_CFG,
&data, &size, 0);
if (err) {
IWL_ERR(phy_db->trans, "Cannot get Phy DB cfg section\n");
return err;
}
err = iwl_send_phy_db_cmd(phy_db, IWL_PHY_DB_CFG, size, data);
if (err) {
IWL_ERR(phy_db->trans,
"Cannot send HCMD of Phy DB cfg section\n");
return err;
}
err = iwl_phy_db_get_section_data(phy_db, IWL_PHY_DB_CALIB_NCH,
&data, &size, 0);
if (err) {
IWL_ERR(phy_db->trans,
"Cannot get Phy DB non specific channel section\n");
return err;
}
err = iwl_send_phy_db_cmd(phy_db, IWL_PHY_DB_CALIB_NCH, size, data);
if (err) {
IWL_ERR(phy_db->trans,
"Cannot send HCMD of Phy DB non specific channel section\n");
return err;
}
/* Send all the TXP channel specific data */
err = iwl_phy_db_send_all_channel_groups(phy_db,
IWL_PHY_DB_CALIB_CHG_PAPD,
phy_db->n_group_papd);
if (err) {
IWL_ERR(phy_db->trans,
"Cannot send channel specific PAPD groups\n");
return err;
}
/* Send all the TXP channel specific data */
err = iwl_phy_db_send_all_channel_groups(phy_db,
IWL_PHY_DB_CALIB_CHG_TXP,
phy_db->n_group_txp);
if (err) {
IWL_ERR(phy_db->trans,
"Cannot send channel specific TX power groups\n");
return err;
}
IWL_DEBUG_INFO(phy_db->trans,
"Finished sending phy db non channel data\n");
return 0;
}
IWL_EXPORT_SYMBOL(iwl_send_phy_db_data);

View File

@ -0,0 +1,23 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2005-2014 Intel Corporation
*/
#ifndef __IWL_PHYDB_H__
#define __IWL_PHYDB_H__
#include <linux/types.h>
#include "iwl-op-mode.h"
#include "iwl-trans.h"
struct iwl_phy_db *iwl_phy_db_init(struct iwl_trans *trans);
void iwl_phy_db_free(struct iwl_phy_db *phy_db);
int iwl_phy_db_set_section(struct iwl_phy_db *phy_db,
struct iwl_rx_packet *pkt);
int iwl_send_phy_db_data(struct iwl_phy_db *phy_db);
#endif /* __IWL_PHYDB_H__ */

View File

@ -0,0 +1,489 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2005-2014, 2018-2021 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016 Intel Deutschland GmbH
*/
#ifndef __iwl_prph_h__
#define __iwl_prph_h__
#include <linux/bitfield.h>
/*
* Registers in this file are internal, not PCI bus memory mapped.
* Driver accesses these via HBUS_TARG_PRPH_* registers.
*/
#define PRPH_BASE (0x00000)
#define PRPH_END (0xFFFFF)
/* APMG (power management) constants */
#define APMG_BASE (PRPH_BASE + 0x3000)
#define APMG_CLK_CTRL_REG (APMG_BASE + 0x0000)
#define APMG_CLK_EN_REG (APMG_BASE + 0x0004)
#define APMG_CLK_DIS_REG (APMG_BASE + 0x0008)
#define APMG_PS_CTRL_REG (APMG_BASE + 0x000c)
#define APMG_PCIDEV_STT_REG (APMG_BASE + 0x0010)
#define APMG_RFKILL_REG (APMG_BASE + 0x0014)
#define APMG_RTC_INT_STT_REG (APMG_BASE + 0x001c)
#define APMG_RTC_INT_MSK_REG (APMG_BASE + 0x0020)
#define APMG_DIGITAL_SVR_REG (APMG_BASE + 0x0058)
#define APMG_ANALOG_SVR_REG (APMG_BASE + 0x006C)
#define APMS_CLK_VAL_MRB_FUNC_MODE (0x00000001)
#define APMG_CLK_VAL_DMA_CLK_RQT (0x00000200)
#define APMG_CLK_VAL_BSM_CLK_RQT (0x00000800)
#define APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS (0x00400000)
#define APMG_PS_CTRL_VAL_RESET_REQ (0x04000000)
#define APMG_PS_CTRL_MSK_PWR_SRC (0x03000000)
#define APMG_PS_CTRL_VAL_PWR_SRC_VMAIN (0x00000000)
#define APMG_PS_CTRL_VAL_PWR_SRC_VAUX (0x02000000)
#define APMG_SVR_VOLTAGE_CONFIG_BIT_MSK (0x000001E0) /* bit 8:5 */
#define APMG_SVR_DIGITAL_VOLTAGE_1_32 (0x00000060)
#define APMG_PCIDEV_STT_VAL_PERSIST_DIS (0x00000200)
#define APMG_PCIDEV_STT_VAL_L1_ACT_DIS (0x00000800)
#define APMG_PCIDEV_STT_VAL_WAKE_ME (0x00004000)
#define APMG_RTC_INT_STT_RFKILL (0x10000000)
/* Device system time */
#define DEVICE_SYSTEM_TIME_REG 0xA0206C
/* Device NMI register and value for 8000 family and lower hw's */
#define DEVICE_SET_NMI_REG 0x00a01c30
#define DEVICE_SET_NMI_VAL_DRV BIT(7)
/* Device NMI register and value for 9000 family and above hw's */
#define UREG_NIC_SET_NMI_DRIVER 0x00a05c10
#define UREG_NIC_SET_NMI_DRIVER_NMI_FROM_DRIVER BIT(24)
#define UREG_NIC_SET_NMI_DRIVER_RESET_HANDSHAKE (BIT(24) | BIT(25))
/* Shared registers (0x0..0x3ff, via target indirect or periphery */
#define SHR_BASE 0x00a10000
/* Shared GP1 register */
#define SHR_APMG_GP1_REG 0x01dc
#define SHR_APMG_GP1_REG_PRPH (SHR_BASE + SHR_APMG_GP1_REG)
#define SHR_APMG_GP1_WF_XTAL_LP_EN 0x00000004
#define SHR_APMG_GP1_CHICKEN_BIT_SELECT 0x80000000
/* Shared DL_CFG register */
#define SHR_APMG_DL_CFG_REG 0x01c4
#define SHR_APMG_DL_CFG_REG_PRPH (SHR_BASE + SHR_APMG_DL_CFG_REG)
#define SHR_APMG_DL_CFG_RTCS_CLK_SELECTOR_MSK 0x000000c0
#define SHR_APMG_DL_CFG_RTCS_CLK_INTERNAL_XTAL 0x00000080
#define SHR_APMG_DL_CFG_DL_CLOCK_POWER_UP 0x00000100
/* Shared APMG_XTAL_CFG register */
#define SHR_APMG_XTAL_CFG_REG 0x1c0
#define SHR_APMG_XTAL_CFG_XTAL_ON_REQ 0x80000000
/*
* Device reset for family 8000
* write to bit 24 in order to reset the CPU
*/
#define RELEASE_CPU_RESET (0x300C)
#define RELEASE_CPU_RESET_BIT BIT(24)
/*****************************************************************************
* 7000/3000 series SHR DTS addresses *
*****************************************************************************/
#define SHR_MISC_WFM_DTS_EN (0x00a10024)
#define DTSC_CFG_MODE (0x00a10604)
#define DTSC_VREF_AVG (0x00a10648)
#define DTSC_VREF5_AVG (0x00a1064c)
#define DTSC_CFG_MODE_PERIODIC (0x2)
#define DTSC_PTAT_AVG (0x00a10650)
/**
* Tx Scheduler
*
* The Tx Scheduler selects the next frame to be transmitted, choosing TFDs
* (Transmit Frame Descriptors) from up to 16 circular Tx queues resident in
* host DRAM. It steers each frame's Tx command (which contains the frame
* data) into one of up to 7 prioritized Tx DMA FIFO channels within the
* device. A queue maps to only one (selectable by driver) Tx DMA channel,
* but one DMA channel may take input from several queues.
*
* Tx DMA FIFOs have dedicated purposes.
*
* For 5000 series and up, they are used differently
* (cf. iwl5000_default_queue_to_tx_fifo in iwl-5000.c):
*
* 0 -- EDCA BK (background) frames, lowest priority
* 1 -- EDCA BE (best effort) frames, normal priority
* 2 -- EDCA VI (video) frames, higher priority
* 3 -- EDCA VO (voice) and management frames, highest priority
* 4 -- unused
* 5 -- unused
* 6 -- unused
* 7 -- Commands
*
* Driver should normally map queues 0-6 to Tx DMA/FIFO channels 0-6.
* In addition, driver can map the remaining queues to Tx DMA/FIFO
* channels 0-3 to support 11n aggregation via EDCA DMA channels.
*
* The driver sets up each queue to work in one of two modes:
*
* 1) Scheduler-Ack, in which the scheduler automatically supports a
* block-ack (BA) window of up to 64 TFDs. In this mode, each queue
* contains TFDs for a unique combination of Recipient Address (RA)
* and Traffic Identifier (TID), that is, traffic of a given
* Quality-Of-Service (QOS) priority, destined for a single station.
*
* In scheduler-ack mode, the scheduler keeps track of the Tx status of
* each frame within the BA window, including whether it's been transmitted,
* and whether it's been acknowledged by the receiving station. The device
* automatically processes block-acks received from the receiving STA,
* and reschedules un-acked frames to be retransmitted (successful
* Tx completion may end up being out-of-order).
*
* The driver must maintain the queue's Byte Count table in host DRAM
* for this mode.
* This mode does not support fragmentation.
*
* 2) FIFO (a.k.a. non-Scheduler-ACK), in which each TFD is processed in order.
* The device may automatically retry Tx, but will retry only one frame
* at a time, until receiving ACK from receiving station, or reaching
* retry limit and giving up.
*
* The command queue (#4/#9) must use this mode!
* This mode does not require use of the Byte Count table in host DRAM.
*
* Driver controls scheduler operation via 3 means:
* 1) Scheduler registers
* 2) Shared scheduler data base in internal SRAM
* 3) Shared data in host DRAM
*
* Initialization:
*
* When loading, driver should allocate memory for:
* 1) 16 TFD circular buffers, each with space for (typically) 256 TFDs.
* 2) 16 Byte Count circular buffers in 16 KBytes contiguous memory
* (1024 bytes for each queue).
*
* After receiving "Alive" response from uCode, driver must initialize
* the scheduler (especially for queue #4/#9, the command queue, otherwise
* the driver can't issue commands!):
*/
#define SCD_MEM_LOWER_BOUND (0x0000)
/**
* Max Tx window size is the max number of contiguous TFDs that the scheduler
* can keep track of at one time when creating block-ack chains of frames.
* Note that "64" matches the number of ack bits in a block-ack packet.
*/
#define SCD_WIN_SIZE 64
#define SCD_FRAME_LIMIT 64
#define SCD_TXFIFO_POS_TID (0)
#define SCD_TXFIFO_POS_RA (4)
#define SCD_QUEUE_RA_TID_MAP_RATID_MSK (0x01FF)
/* agn SCD */
#define SCD_QUEUE_STTS_REG_POS_TXF (0)
#define SCD_QUEUE_STTS_REG_POS_ACTIVE (3)
#define SCD_QUEUE_STTS_REG_POS_WSL (4)
#define SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN (19)
#define SCD_QUEUE_STTS_REG_MSK (0x017F0000)
#define SCD_QUEUE_CTX_REG1_CREDIT (0x00FFFF00)
#define SCD_QUEUE_CTX_REG1_SUPER_CREDIT (0xFF000000)
#define SCD_QUEUE_CTX_REG1_VAL(_n, _v) FIELD_PREP(SCD_QUEUE_CTX_REG1_ ## _n, _v)
#define SCD_QUEUE_CTX_REG2_WIN_SIZE (0x0000007F)
#define SCD_QUEUE_CTX_REG2_FRAME_LIMIT (0x007F0000)
#define SCD_QUEUE_CTX_REG2_VAL(_n, _v) FIELD_PREP(SCD_QUEUE_CTX_REG2_ ## _n, _v)
#define SCD_GP_CTRL_ENABLE_31_QUEUES BIT(0)
#define SCD_GP_CTRL_AUTO_ACTIVE_MODE BIT(18)
/* Context Data */
#define SCD_CONTEXT_MEM_LOWER_BOUND (SCD_MEM_LOWER_BOUND + 0x600)
#define SCD_CONTEXT_MEM_UPPER_BOUND (SCD_MEM_LOWER_BOUND + 0x6A0)
/* Tx status */
#define SCD_TX_STTS_MEM_LOWER_BOUND (SCD_MEM_LOWER_BOUND + 0x6A0)
#define SCD_TX_STTS_MEM_UPPER_BOUND (SCD_MEM_LOWER_BOUND + 0x7E0)
/* Translation Data */
#define SCD_TRANS_TBL_MEM_LOWER_BOUND (SCD_MEM_LOWER_BOUND + 0x7E0)
#define SCD_TRANS_TBL_MEM_UPPER_BOUND (SCD_MEM_LOWER_BOUND + 0x808)
#define SCD_CONTEXT_QUEUE_OFFSET(x)\
(SCD_CONTEXT_MEM_LOWER_BOUND + ((x) * 8))
#define SCD_TX_STTS_QUEUE_OFFSET(x)\
(SCD_TX_STTS_MEM_LOWER_BOUND + ((x) * 16))
#define SCD_TRANS_TBL_OFFSET_QUEUE(x) \
((SCD_TRANS_TBL_MEM_LOWER_BOUND + ((x) * 2)) & 0xfffc)
#define SCD_BASE (PRPH_BASE + 0xa02c00)
#define SCD_SRAM_BASE_ADDR (SCD_BASE + 0x0)
#define SCD_DRAM_BASE_ADDR (SCD_BASE + 0x8)
#define SCD_AIT (SCD_BASE + 0x0c)
#define SCD_TXFACT (SCD_BASE + 0x10)
#define SCD_ACTIVE (SCD_BASE + 0x14)
#define SCD_QUEUECHAIN_SEL (SCD_BASE + 0xe8)
#define SCD_CHAINEXT_EN (SCD_BASE + 0x244)
#define SCD_AGGR_SEL (SCD_BASE + 0x248)
#define SCD_INTERRUPT_MASK (SCD_BASE + 0x108)
#define SCD_GP_CTRL (SCD_BASE + 0x1a8)
#define SCD_EN_CTRL (SCD_BASE + 0x254)
/*********************** END TX SCHEDULER *************************************/
/* Oscillator clock */
#define OSC_CLK (0xa04068)
#define OSC_CLK_FORCE_CONTROL (0x8)
#define FH_UCODE_LOAD_STATUS (0x1AF0)
/*
* Replacing FH_UCODE_LOAD_STATUS
* This register is writen by driver and is read by uCode during boot flow.
* Note this address is cleared after MAC reset.
*/
#define UREG_UCODE_LOAD_STATUS (0xa05c40)
#define UREG_CPU_INIT_RUN (0xa05c44)
#define LMPM_SECURE_UCODE_LOAD_CPU1_HDR_ADDR (0x1E78)
#define LMPM_SECURE_UCODE_LOAD_CPU2_HDR_ADDR (0x1E7C)
#define LMPM_SECURE_CPU1_HDR_MEM_SPACE (0x420000)
#define LMPM_SECURE_CPU2_HDR_MEM_SPACE (0x420400)
#define LMAC2_PRPH_OFFSET (0x100000)
/* Rx FIFO */
#define RXF_SIZE_ADDR (0xa00c88)
#define RXF_RD_D_SPACE (0xa00c40)
#define RXF_RD_WR_PTR (0xa00c50)
#define RXF_RD_RD_PTR (0xa00c54)
#define RXF_RD_FENCE_PTR (0xa00c4c)
#define RXF_SET_FENCE_MODE (0xa00c14)
#define RXF_LD_WR2FENCE (0xa00c1c)
#define RXF_FIFO_RD_FENCE_INC (0xa00c68)
#define RXF_SIZE_BYTE_CND_POS (7)
#define RXF_SIZE_BYTE_CNT_MSK (0x3ff << RXF_SIZE_BYTE_CND_POS)
#define RXF_DIFF_FROM_PREV (0x200)
#define RXF2C_DIFF_FROM_PREV (0x4e00)
#define RXF_LD_FENCE_OFFSET_ADDR (0xa00c10)
#define RXF_FIFO_RD_FENCE_ADDR (0xa00c0c)
/* Tx FIFO */
#define TXF_FIFO_ITEM_CNT (0xa00438)
#define TXF_WR_PTR (0xa00414)
#define TXF_RD_PTR (0xa00410)
#define TXF_FENCE_PTR (0xa00418)
#define TXF_LOCK_FENCE (0xa00424)
#define TXF_LARC_NUM (0xa0043c)
#define TXF_READ_MODIFY_DATA (0xa00448)
#define TXF_READ_MODIFY_ADDR (0xa0044c)
/* UMAC Internal Tx Fifo */
#define TXF_CPU2_FIFO_ITEM_CNT (0xA00538)
#define TXF_CPU2_WR_PTR (0xA00514)
#define TXF_CPU2_RD_PTR (0xA00510)
#define TXF_CPU2_FENCE_PTR (0xA00518)
#define TXF_CPU2_LOCK_FENCE (0xA00524)
#define TXF_CPU2_NUM (0xA0053C)
#define TXF_CPU2_READ_MODIFY_DATA (0xA00548)
#define TXF_CPU2_READ_MODIFY_ADDR (0xA0054C)
/* Radio registers access */
#define RSP_RADIO_CMD (0xa02804)
#define RSP_RADIO_RDDAT (0xa02814)
#define RADIO_RSP_ADDR_POS (6)
#define RADIO_RSP_RD_CMD (3)
/* LTR control (Qu only) */
#define HPM_MAC_LTR_CSR 0xa0348c
#define HPM_MAC_LRT_ENABLE_ALL 0xf
/* also uses CSR_LTR_* for values */
#define HPM_UMAC_LTR 0xa03480
/* FW monitor */
#define MON_BUFF_SAMPLE_CTL (0xa03c00)
#define MON_BUFF_BASE_ADDR (0xa03c1c)
#define MON_BUFF_END_ADDR (0xa03c40)
#define MON_BUFF_WRPTR (0xa03c44)
#define MON_BUFF_CYCLE_CNT (0xa03c48)
/* FW monitor family 8000 and on */
#define MON_BUFF_BASE_ADDR_VER2 (0xa03c1c)
#define MON_BUFF_END_ADDR_VER2 (0xa03c20)
#define MON_BUFF_WRPTR_VER2 (0xa03c24)
#define MON_BUFF_CYCLE_CNT_VER2 (0xa03c28)
#define MON_BUFF_SHIFT_VER2 (0x8)
/* FW monitor familiy AX210 and on */
#define DBGC_CUR_DBGBUF_BASE_ADDR_LSB (0xd03c20)
#define DBGC_CUR_DBGBUF_BASE_ADDR_MSB (0xd03c24)
#define DBGC_CUR_DBGBUF_STATUS (0xd03c1c)
#define DBGC_DBGBUF_WRAP_AROUND (0xd03c2c)
#define DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK (0x00ffffff)
#define DBGC_CUR_DBGBUF_STATUS_IDX_MSK (0x0f000000)
#define MON_DMARB_RD_CTL_ADDR (0xa03c60)
#define MON_DMARB_RD_DATA_ADDR (0xa03c5c)
#define DBGC_IN_SAMPLE (0xa03c00)
#define DBGC_OUT_CTRL (0xa03c0c)
/* M2S registers */
#define LDBG_M2S_BUF_WPTR (0xa0476c)
#define LDBG_M2S_BUF_WRAP_CNT (0xa04774)
#define LDBG_M2S_BUF_WPTR_VAL_MSK (0x000fffff)
#define LDBG_M2S_BUF_WRAP_CNT_VAL_MSK (0x000fffff)
/* enable the ID buf for read */
#define WFPM_PS_CTL_CLR 0xA0300C
#define WFMP_MAC_ADDR_0 0xA03080
#define WFMP_MAC_ADDR_1 0xA03084
#define LMPM_PMG_EN 0xA01CEC
#define RADIO_REG_SYS_MANUAL_DFT_0 0xAD4078
#define RFIC_REG_RD 0xAD0470
#define WFPM_CTRL_REG 0xA03030
#define WFPM_CTRL_REG_GEN2 0xd03030
#define WFPM_OTP_CFG1_ADDR 0x00a03098
#define WFPM_OTP_CFG1_ADDR_GEN2 0x00d03098
#define WFPM_OTP_CFG1_IS_JACKET_BIT BIT(4)
#define WFPM_OTP_CFG1_IS_CDB_BIT BIT(5)
#define WFPM_GP2 0xA030B4
/* DBGI SRAM Register details */
#define DBGI_SRAM_TARGET_ACCESS_CFG 0x00A2E14C
#define DBGI_SRAM_TARGET_ACCESS_CFG_RESET_ADDRESS_MSK 0x10000
#define DBGI_SRAM_TARGET_ACCESS_RDATA_LSB 0x00A2E154
#define DBGI_SRAM_TARGET_ACCESS_RDATA_MSB 0x00A2E158
enum {
ENABLE_WFPM = BIT(31),
WFPM_AUX_CTL_AUX_IF_MAC_OWNER_MSK = 0x80000000,
};
#define CNVI_AUX_MISC_CHIP 0xA200B0
#define CNVR_AUX_MISC_CHIP 0xA2B800
#define CNVR_SCU_SD_REGS_SD_REG_DIG_DCDC_VTRIM 0xA29890
#define CNVR_SCU_SD_REGS_SD_REG_ACTIVE_VDIG_MIRROR 0xA29938
#define PREG_AUX_BUS_WPROT_0 0xA04CC0
/* device family 9000 WPROT register */
#define PREG_PRPH_WPROT_9000 0xA04CE0
/* device family 22000 WPROT register */
#define PREG_PRPH_WPROT_22000 0xA04D00
#define SB_MODIFY_CFG_FLAG 0xA03088
#define SB_CPU_1_STATUS 0xA01E30
#define SB_CPU_2_STATUS 0xA01E34
#define UMAG_SB_CPU_1_STATUS 0xA038C0
#define UMAG_SB_CPU_2_STATUS 0xA038C4
#define UMAG_GEN_HW_STATUS 0xA038C8
#define UREG_UMAC_CURRENT_PC 0xa05c18
#define UREG_LMAC1_CURRENT_PC 0xa05c1c
#define UREG_LMAC2_CURRENT_PC 0xa05c20
/* For UMAG_GEN_HW_STATUS reg check */
enum {
UMAG_GEN_HW_IS_FPGA = BIT(1),
};
/* FW chicken bits */
#define LMPM_CHICK 0xA01FF8
enum {
LMPM_CHICK_EXTENDED_ADDR_SPACE = BIT(0),
};
/* FW chicken bits */
#define LMPM_PAGE_PASS_NOTIF 0xA03824
enum {
LMPM_PAGE_PASS_NOTIF_POS = BIT(20),
};
/*
* CRF ID register
*
* type: bits 0-11
* reserved: bits 12-18
* slave_exist: bit 19
* dash: bits 20-23
* step: bits 24-26
* flavor: bits 27-31
*/
#define REG_CRF_ID_TYPE(val) (((val) & 0x00000FFF) >> 0)
#define REG_CRF_ID_SLAVE(val) (((val) & 0x00080000) >> 19)
#define REG_CRF_ID_DASH(val) (((val) & 0x00F00000) >> 20)
#define REG_CRF_ID_STEP(val) (((val) & 0x07000000) >> 24)
#define REG_CRF_ID_FLAVOR(val) (((val) & 0xF8000000) >> 27)
#define UREG_CHICK (0xA05C00)
#define UREG_CHICK_MSI_ENABLE BIT(24)
#define UREG_CHICK_MSIX_ENABLE BIT(25)
#define SD_REG_VER 0xa29600
#define SD_REG_VER_GEN2 0x00a2b800
#define REG_CRF_ID_TYPE_JF_1 0x201
#define REG_CRF_ID_TYPE_JF_2 0x202
#define REG_CRF_ID_TYPE_HR_CDB 0x503
#define REG_CRF_ID_TYPE_HR_NONE_CDB 0x504
#define REG_CRF_ID_TYPE_HR_NONE_CDB_1X1 0x501
#define REG_CRF_ID_TYPE_HR_NONE_CDB_CCP 0x532
#define REG_CRF_ID_TYPE_GF 0x410
#define REG_CRF_ID_TYPE_GF_TC 0xF08
#define REG_CRF_ID_TYPE_MR 0x810
#define REG_CRF_ID_TYPE_FM 0x910
#define HPM_DEBUG 0xA03440
#define PERSISTENCE_BIT BIT(12)
#define PREG_WFPM_ACCESS BIT(12)
#define HPM_HIPM_GEN_CFG 0xA03458
#define HPM_HIPM_GEN_CFG_CR_PG_EN BIT(0)
#define HPM_HIPM_GEN_CFG_CR_SLP_EN BIT(1)
#define HPM_HIPM_GEN_CFG_CR_FORCE_ACTIVE BIT(10)
#define UREG_DOORBELL_TO_ISR6 0xA05C04
#define UREG_DOORBELL_TO_ISR6_NMI_BIT BIT(0)
#define UREG_DOORBELL_TO_ISR6_RESET_HANDSHAKE (BIT(0) | BIT(1))
#define UREG_DOORBELL_TO_ISR6_SUSPEND BIT(18)
#define UREG_DOORBELL_TO_ISR6_RESUME BIT(19)
#define UREG_DOORBELL_TO_ISR6_PNVM BIT(20)
#define CNVI_MBOX_C 0xA3400C
#define FSEQ_ERROR_CODE 0xA340C8
#define FSEQ_TOP_INIT_VERSION 0xA34038
#define FSEQ_CNVIO_INIT_VERSION 0xA3403C
#define FSEQ_OTP_VERSION 0xA340FC
#define FSEQ_TOP_CONTENT_VERSION 0xA340F4
#define FSEQ_ALIVE_TOKEN 0xA340F0
#define FSEQ_CNVI_ID 0xA3408C
#define FSEQ_CNVR_ID 0xA34090
#define IWL_D3_SLEEP_STATUS_SUSPEND 0xD3
#define IWL_D3_SLEEP_STATUS_RESUME 0xD0
#define WMAL_INDRCT_RD_CMD1_OPMOD_POS 28
#define WMAL_INDRCT_RD_CMD1_BYTE_ADDRESS_MSK 0xFFFFF
#define WMAL_CMD_READ_BURST_ACCESS 2
#define WMAL_MRSPF_1 0xADFC20
#define WMAL_INDRCT_RD_CMD1 0xADFD44
#define WMAL_INDRCT_CMD1 0xADFC14
#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 WFPM_LMAC1_PS_CTL_RW 0xA03380
#define WFPM_LMAC2_PS_CTL_RW 0xA033C0
#define WFPM_PS_CTL_RW_PHYRF_PD_FSM_CURSTATE_MSK 0x0000000F
#define WFPM_PHYRF_STATE_ON 5
#define HBUS_TIMEOUT 0xA5A5A5A1
#define WFPM_DPHY_OFF 0xDF10FF
#endif /* __iwl_prph_h__ */

View File

@ -0,0 +1,84 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2014 Intel Mobile Communications GmbH
*/
#ifndef __iwl_scd_h__
#define __iwl_scd_h__
#include "iwl-trans.h"
#include "iwl-io.h"
#include "iwl-prph.h"
static inline void iwl_scd_txq_set_chain(struct iwl_trans *trans,
u16 txq_id)
{
iwl_set_bits_prph(trans, SCD_QUEUECHAIN_SEL, BIT(txq_id));
}
static inline void iwl_scd_txq_enable_agg(struct iwl_trans *trans,
u16 txq_id)
{
iwl_set_bits_prph(trans, SCD_AGGR_SEL, BIT(txq_id));
}
static inline void iwl_scd_txq_disable_agg(struct iwl_trans *trans,
u16 txq_id)
{
iwl_clear_bits_prph(trans, SCD_AGGR_SEL, BIT(txq_id));
}
static inline void iwl_scd_disable_agg(struct iwl_trans *trans)
{
iwl_set_bits_prph(trans, SCD_AGGR_SEL, 0);
}
static inline void iwl_scd_activate_fifos(struct iwl_trans *trans)
{
iwl_write_prph(trans, SCD_TXFACT, IWL_MASK(0, 7));
}
static inline void iwl_scd_deactivate_fifos(struct iwl_trans *trans)
{
iwl_write_prph(trans, SCD_TXFACT, 0);
}
static inline void iwl_scd_enable_set_active(struct iwl_trans *trans,
u32 value)
{
iwl_write_prph(trans, SCD_EN_CTRL, value);
}
static inline unsigned int SCD_QUEUE_WRPTR(unsigned int chnl)
{
if (chnl < 20)
return SCD_BASE + 0x18 + chnl * 4;
WARN_ON_ONCE(chnl >= 32);
return SCD_BASE + 0x284 + (chnl - 20) * 4;
}
static inline unsigned int SCD_QUEUE_RDPTR(unsigned int chnl)
{
if (chnl < 20)
return SCD_BASE + 0x68 + chnl * 4;
WARN_ON_ONCE(chnl >= 32);
return SCD_BASE + 0x2B4 + chnl * 4;
}
static inline unsigned int SCD_QUEUE_STATUS_BITS(unsigned int chnl)
{
if (chnl < 20)
return SCD_BASE + 0x10c + chnl * 4;
WARN_ON_ONCE(chnl >= 32);
return SCD_BASE + 0x334 + chnl * 4;
}
static inline void iwl_scd_txq_set_inactive(struct iwl_trans *trans,
u16 txq_id)
{
iwl_write_prph(trans, SCD_QUEUE_STATUS_BITS(txq_id),
(0 << SCD_QUEUE_STTS_REG_POS_ACTIVE)|
(1 << SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN));
}
#endif

View File

@ -0,0 +1,253 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
* Copyright (C) 2019-2021 Intel Corporation
*/
#include <linux/kernel.h>
#include <linux/bsearch.h>
#include "fw/api/tx.h"
#include "iwl-trans.h"
#include "iwl-drv.h"
#include "iwl-fh.h"
#include "queue/tx.h"
#include <linux/dmapool.h>
#include "fw/api/commands.h"
struct iwl_trans *iwl_trans_alloc(unsigned int priv_size,
struct device *dev,
const struct iwl_trans_ops *ops,
const struct iwl_cfg_trans_params *cfg_trans)
{
struct iwl_trans *trans;
#ifdef CONFIG_LOCKDEP
static struct lock_class_key __key;
#endif
trans = devm_kzalloc(dev, sizeof(*trans) + priv_size, GFP_KERNEL);
if (!trans)
return NULL;
trans->trans_cfg = cfg_trans;
#ifdef CONFIG_LOCKDEP
lockdep_init_map(&trans->sync_cmd_lockdep_map, "sync_cmd_lockdep_map",
&__key, 0);
#endif
trans->dev = dev;
trans->ops = ops;
trans->num_rx_queues = 1;
WARN_ON(!ops->wait_txq_empty && !ops->wait_tx_queues_empty);
if (trans->trans_cfg->use_tfh) {
trans->txqs.tfd.addr_size = 64;
trans->txqs.tfd.max_tbs = IWL_TFH_NUM_TBS;
trans->txqs.tfd.size = sizeof(struct iwl_tfh_tfd);
} else {
trans->txqs.tfd.addr_size = 36;
trans->txqs.tfd.max_tbs = IWL_NUM_OF_TBS;
trans->txqs.tfd.size = sizeof(struct iwl_tfd);
}
trans->max_skb_frags = IWL_TRANS_MAX_FRAGS(trans);
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;
if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
trans->txqs.bc_tbl_size = sizeof(struct iwl_gen3_bc_tbl);
else
trans->txqs.bc_tbl_size = sizeof(struct iwlagn_scd_bc_tbl);
/*
* For gen2 devices, we use a single allocation for each byte-count
* table, but they're pretty small (1k) so use a DMA pool that we
* allocate here.
*/
if (trans->trans_cfg->gen2) {
trans->txqs.bc_pool = dmam_pool_create("iwlwifi:bc", trans->dev,
trans->txqs.bc_tbl_size,
256, 0);
if (!trans->txqs.bc_pool)
return -ENOMEM;
}
/* Some things must not change even if the config does */
WARN_ON(trans->txqs.tfd.addr_size !=
(trans->trans_cfg->use_tfh ? 64 : 36));
snprintf(trans->dev_cmd_pool_name, sizeof(trans->dev_cmd_pool_name),
"iwl_cmd_pool:%s", dev_name(trans->dev));
trans->dev_cmd_pool =
kmem_cache_create(trans->dev_cmd_pool_name,
txcmd_size, txcmd_align,
SLAB_HWCACHE_ALIGN, NULL);
if (!trans->dev_cmd_pool)
return -ENOMEM;
#ifdef CONFIG_INET
trans->txqs.tso_hdr_page = alloc_percpu(struct iwl_tso_hdr_page);
if (!trans->txqs.tso_hdr_page) {
kmem_cache_destroy(trans->dev_cmd_pool);
return -ENOMEM;
}
#endif
/* Initialize the wait queue for commands */
init_waitqueue_head(&trans->wait_command_queue);
return 0;
}
void iwl_trans_free(struct iwl_trans *trans)
{
#ifdef CONFIG_INET
int i;
if (trans->txqs.tso_hdr_page) {
for_each_possible_cpu(i) {
struct iwl_tso_hdr_page *p =
per_cpu_ptr(trans->txqs.tso_hdr_page, i);
if (p && p->page)
__free_page(p->page);
}
free_percpu(trans->txqs.tso_hdr_page);
}
#endif
kmem_cache_destroy(trans->dev_cmd_pool);
}
int iwl_trans_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
{
int ret;
if (unlikely(!(cmd->flags & CMD_SEND_IN_RFKILL) &&
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)))
return -EHOSTDOWN;
if (unlikely(test_bit(STATUS_FW_ERROR, &trans->status)))
return -EIO;
if (unlikely(trans->state != IWL_TRANS_FW_ALIVE)) {
IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state);
return -EIO;
}
if (WARN_ON((cmd->flags & CMD_WANT_ASYNC_CALLBACK) &&
!(cmd->flags & CMD_ASYNC)))
return -EINVAL;
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 (cmd->id != REPLY_ERROR)
cmd->id = DEF_ID(cmd->id);
}
ret = iwl_trans_txq_send_hcmd(trans, cmd);
if (!(cmd->flags & CMD_ASYNC))
lock_map_release(&trans->sync_cmd_lockdep_map);
if (WARN_ON((cmd->flags & CMD_WANT_SKB) && !ret && !cmd->resp_pkt))
return -EIO;
return ret;
}
IWL_EXPORT_SYMBOL(iwl_trans_send_cmd);
/* Comparator for struct iwl_hcmd_names.
* Used in the binary search over a list of host commands.
*
* @key: command_id that we're looking for.
* @elt: struct iwl_hcmd_names candidate for match.
*
* @return 0 iff equal.
*/
static int iwl_hcmd_names_cmp(const void *key, const void *elt)
{
const struct iwl_hcmd_names *name = elt;
const u8 *cmd1 = key;
u8 cmd2 = name->cmd_id;
return (*cmd1 - cmd2);
}
const char *iwl_get_cmd_string(struct iwl_trans *trans, u32 id)
{
u8 grp, cmd;
struct iwl_hcmd_names *ret;
const struct iwl_hcmd_arr *arr;
size_t size = sizeof(struct iwl_hcmd_names);
grp = iwl_cmd_groupid(id);
cmd = iwl_cmd_opcode(id);
if (!trans->command_groups || grp >= trans->command_groups_size ||
!trans->command_groups[grp].arr)
return "UNKNOWN";
arr = &trans->command_groups[grp];
ret = bsearch(&cmd, arr->arr, arr->size, size, iwl_hcmd_names_cmp);
if (!ret)
return "UNKNOWN";
return ret->cmd_name;
}
IWL_EXPORT_SYMBOL(iwl_get_cmd_string);
int iwl_cmd_groups_verify_sorted(const struct iwl_trans_config *trans)
{
int i, j;
const struct iwl_hcmd_arr *arr;
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;
}
IWL_EXPORT_SYMBOL(iwl_cmd_groups_verify_sorted);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,163 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2012-2014, 2020 Intel Corporation
* Copyright (C) 2016 Intel Deutschland GmbH
*/
#include <net/mac80211.h>
#include "fw-api.h"
#include "mvm.h"
struct iwl_mvm_iface_iterator_data {
struct ieee80211_vif *ignore_vif;
int idx;
struct iwl_mvm_phy_ctxt *phyctxt;
u16 ids[MAX_MACS_IN_BINDING];
u16 colors[MAX_MACS_IN_BINDING];
};
static int iwl_mvm_binding_cmd(struct iwl_mvm *mvm, u32 action,
struct iwl_mvm_iface_iterator_data *data)
{
struct iwl_binding_cmd cmd;
struct iwl_mvm_phy_ctxt *phyctxt = data->phyctxt;
int i, ret;
u32 status;
int size;
memset(&cmd, 0, sizeof(cmd));
if (fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_BINDING_CDB_SUPPORT)) {
size = sizeof(cmd);
cmd.lmac_id = cpu_to_le32(iwl_mvm_get_lmac_id(mvm->fw,
phyctxt->channel->band));
} else {
size = IWL_BINDING_CMD_SIZE_V1;
}
cmd.id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(phyctxt->id,
phyctxt->color));
cmd.action = cpu_to_le32(action);
cmd.phy = cpu_to_le32(FW_CMD_ID_AND_COLOR(phyctxt->id,
phyctxt->color));
for (i = 0; i < MAX_MACS_IN_BINDING; i++)
cmd.macs[i] = cpu_to_le32(FW_CTXT_INVALID);
for (i = 0; i < data->idx; i++)
cmd.macs[i] = cpu_to_le32(FW_CMD_ID_AND_COLOR(data->ids[i],
data->colors[i]));
status = 0;
ret = iwl_mvm_send_cmd_pdu_status(mvm, BINDING_CONTEXT_CMD,
size, &cmd, &status);
if (ret) {
IWL_ERR(mvm, "Failed to send binding (action:%d): %d\n",
action, ret);
return ret;
}
if (status) {
IWL_ERR(mvm, "Binding command failed: %u\n", status);
ret = -EIO;
}
return ret;
}
static void iwl_mvm_iface_iterator(void *_data, u8 *mac,
struct ieee80211_vif *vif)
{
struct iwl_mvm_iface_iterator_data *data = _data;
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
if (vif == data->ignore_vif)
return;
if (mvmvif->phy_ctxt != data->phyctxt)
return;
if (WARN_ON_ONCE(data->idx >= MAX_MACS_IN_BINDING))
return;
data->ids[data->idx] = mvmvif->id;
data->colors[data->idx] = mvmvif->color;
data->idx++;
}
static int iwl_mvm_binding_update(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct iwl_mvm_phy_ctxt *phyctxt,
bool add)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm_iface_iterator_data data = {
.ignore_vif = vif,
.phyctxt = phyctxt,
};
u32 action = FW_CTXT_ACTION_MODIFY;
lockdep_assert_held(&mvm->mutex);
ieee80211_iterate_active_interfaces_atomic(mvm->hw,
IEEE80211_IFACE_ITER_NORMAL,
iwl_mvm_iface_iterator,
&data);
/*
* If there are no other interfaces yet we
* need to create a new binding.
*/
if (data.idx == 0) {
if (add)
action = FW_CTXT_ACTION_ADD;
else
action = FW_CTXT_ACTION_REMOVE;
}
if (add) {
if (WARN_ON_ONCE(data.idx >= MAX_MACS_IN_BINDING))
return -EINVAL;
data.ids[data.idx] = mvmvif->id;
data.colors[data.idx] = mvmvif->color;
data.idx++;
}
return iwl_mvm_binding_cmd(mvm, action, &data);
}
int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
if (WARN_ON_ONCE(!mvmvif->phy_ctxt))
return -EINVAL;
/*
* Update SF - Disable if needed. if this fails, SF might still be on
* while many macs are bound, which is forbidden - so fail the binding.
*/
if (iwl_mvm_sf_update(mvm, vif, false))
return -EINVAL;
return iwl_mvm_binding_update(mvm, vif, mvmvif->phy_ctxt, true);
}
int iwl_mvm_binding_remove_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
int ret;
if (WARN_ON_ONCE(!mvmvif->phy_ctxt))
return -EINVAL;
ret = iwl_mvm_binding_update(mvm, vif, mvmvif->phy_ctxt, false);
if (!ret)
if (iwl_mvm_sf_update(mvm, vif, true))
IWL_ERR(mvm, "Failed to update SF state\n");
return ret;
}

View File

@ -0,0 +1,685 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2013-2014, 2018-2020 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
*/
#include <linux/ieee80211.h>
#include <linux/etherdevice.h>
#include <net/mac80211.h>
#include "fw/api/coex.h"
#include "iwl-modparams.h"
#include "mvm.h"
#include "iwl-debug.h"
/* 20MHz / 40MHz below / 40Mhz above*/
static const __le64 iwl_ci_mask[][3] = {
/* dummy entry for channel 0 */
{cpu_to_le64(0), cpu_to_le64(0), cpu_to_le64(0)},
{
cpu_to_le64(0x0000001FFFULL),
cpu_to_le64(0x0ULL),
cpu_to_le64(0x00007FFFFFULL),
},
{
cpu_to_le64(0x000000FFFFULL),
cpu_to_le64(0x0ULL),
cpu_to_le64(0x0003FFFFFFULL),
},
{
cpu_to_le64(0x000003FFFCULL),
cpu_to_le64(0x0ULL),
cpu_to_le64(0x000FFFFFFCULL),
},
{
cpu_to_le64(0x00001FFFE0ULL),
cpu_to_le64(0x0ULL),
cpu_to_le64(0x007FFFFFE0ULL),
},
{
cpu_to_le64(0x00007FFF80ULL),
cpu_to_le64(0x00007FFFFFULL),
cpu_to_le64(0x01FFFFFF80ULL),
},
{
cpu_to_le64(0x0003FFFC00ULL),
cpu_to_le64(0x0003FFFFFFULL),
cpu_to_le64(0x0FFFFFFC00ULL),
},
{
cpu_to_le64(0x000FFFF000ULL),
cpu_to_le64(0x000FFFFFFCULL),
cpu_to_le64(0x3FFFFFF000ULL),
},
{
cpu_to_le64(0x007FFF8000ULL),
cpu_to_le64(0x007FFFFFE0ULL),
cpu_to_le64(0xFFFFFF8000ULL),
},
{
cpu_to_le64(0x01FFFE0000ULL),
cpu_to_le64(0x01FFFFFF80ULL),
cpu_to_le64(0xFFFFFE0000ULL),
},
{
cpu_to_le64(0x0FFFF00000ULL),
cpu_to_le64(0x0FFFFFFC00ULL),
cpu_to_le64(0x0ULL),
},
{
cpu_to_le64(0x3FFFC00000ULL),
cpu_to_le64(0x3FFFFFF000ULL),
cpu_to_le64(0x0)
},
{
cpu_to_le64(0xFFFE000000ULL),
cpu_to_le64(0xFFFFFF8000ULL),
cpu_to_le64(0x0)
},
{
cpu_to_le64(0xFFF8000000ULL),
cpu_to_le64(0xFFFFFE0000ULL),
cpu_to_le64(0x0)
},
{
cpu_to_le64(0xFE00000000ULL),
cpu_to_le64(0x0ULL),
cpu_to_le64(0x0ULL)
},
};
static enum iwl_bt_coex_lut_type
iwl_get_coex_type(struct iwl_mvm *mvm, const struct ieee80211_vif *vif)
{
struct ieee80211_chanctx_conf *chanctx_conf;
enum iwl_bt_coex_lut_type ret;
u16 phy_ctx_id;
u32 primary_ch_phy_id, secondary_ch_phy_id;
/*
* Checking that we hold mvm->mutex is a good idea, but the rate
* control can't acquire the mutex since it runs in Tx path.
* So this is racy in that case, but in the worst case, the AMPDU
* size limit will be wrong for a short time which is not a big
* issue.
*/
rcu_read_lock();
chanctx_conf = rcu_dereference(vif->chanctx_conf);
if (!chanctx_conf ||
chanctx_conf->def.chan->band != NL80211_BAND_2GHZ) {
rcu_read_unlock();
return BT_COEX_INVALID_LUT;
}
ret = BT_COEX_TX_DIS_LUT;
if (mvm->cfg->bt_shared_single_ant) {
rcu_read_unlock();
return ret;
}
phy_ctx_id = *((u16 *)chanctx_conf->drv_priv);
primary_ch_phy_id = le32_to_cpu(mvm->last_bt_ci_cmd.primary_ch_phy_id);
secondary_ch_phy_id =
le32_to_cpu(mvm->last_bt_ci_cmd.secondary_ch_phy_id);
if (primary_ch_phy_id == phy_ctx_id)
ret = le32_to_cpu(mvm->last_bt_notif.primary_ch_lut);
else if (secondary_ch_phy_id == phy_ctx_id)
ret = le32_to_cpu(mvm->last_bt_notif.secondary_ch_lut);
/* else - default = TX TX disallowed */
rcu_read_unlock();
return ret;
}
int iwl_mvm_send_bt_init_conf(struct iwl_mvm *mvm)
{
struct iwl_bt_coex_cmd bt_cmd = {};
u32 mode;
lockdep_assert_held(&mvm->mutex);
if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS)) {
switch (mvm->bt_force_ant_mode) {
case BT_FORCE_ANT_BT:
mode = BT_COEX_BT;
break;
case BT_FORCE_ANT_WIFI:
mode = BT_COEX_WIFI;
break;
default:
WARN_ON(1);
mode = 0;
}
bt_cmd.mode = cpu_to_le32(mode);
goto send_cmd;
}
bt_cmd.mode = cpu_to_le32(BT_COEX_NW);
if (IWL_MVM_BT_COEX_SYNC2SCO)
bt_cmd.enabled_modules |=
cpu_to_le32(BT_COEX_SYNC2SCO_ENABLED);
if (iwl_mvm_is_mplut_supported(mvm))
bt_cmd.enabled_modules |= cpu_to_le32(BT_COEX_MPLUT_ENABLED);
bt_cmd.enabled_modules |= cpu_to_le32(BT_COEX_HIGH_BAND_RET);
send_cmd:
memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif));
memset(&mvm->last_bt_ci_cmd, 0, sizeof(mvm->last_bt_ci_cmd));
return iwl_mvm_send_cmd_pdu(mvm, BT_CONFIG, 0, sizeof(bt_cmd), &bt_cmd);
}
static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id,
bool enable)
{
struct iwl_bt_coex_reduced_txp_update_cmd cmd = {};
struct iwl_mvm_sta *mvmsta;
u32 value;
mvmsta = iwl_mvm_sta_from_staid_protected(mvm, sta_id);
if (!mvmsta)
return 0;
/* nothing to do */
if (mvmsta->bt_reduced_txpower == enable)
return 0;
value = mvmsta->sta_id;
if (enable)
value |= BT_REDUCED_TX_POWER_BIT;
IWL_DEBUG_COEX(mvm, "%sable reduced Tx Power for sta %d\n",
enable ? "en" : "dis", sta_id);
cmd.reduced_txp = cpu_to_le32(value);
mvmsta->bt_reduced_txpower = enable;
return iwl_mvm_send_cmd_pdu(mvm, BT_COEX_UPDATE_REDUCED_TXP,
CMD_ASYNC, sizeof(cmd), &cmd);
}
struct iwl_bt_iterator_data {
struct iwl_bt_coex_profile_notif *notif;
struct iwl_mvm *mvm;
struct ieee80211_chanctx_conf *primary;
struct ieee80211_chanctx_conf *secondary;
bool primary_ll;
u8 primary_load;
u8 secondary_load;
};
static inline
void iwl_mvm_bt_coex_enable_rssi_event(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
bool enable, int rssi)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
mvmvif->bf_data.last_bt_coex_event = rssi;
mvmvif->bf_data.bt_coex_max_thold =
enable ? -IWL_MVM_BT_COEX_EN_RED_TXP_THRESH : 0;
mvmvif->bf_data.bt_coex_min_thold =
enable ? -IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH : 0;
}
#define MVM_COEX_TCM_PERIOD (HZ * 10)
static void iwl_mvm_bt_coex_tcm_based_ci(struct iwl_mvm *mvm,
struct iwl_bt_iterator_data *data)
{
unsigned long now = jiffies;
if (!time_after(now, mvm->bt_coex_last_tcm_ts + MVM_COEX_TCM_PERIOD))
return;
mvm->bt_coex_last_tcm_ts = now;
/* We assume here that we don't have more than 2 vifs on 2.4GHz */
/* if the primary is low latency, it will stay primary */
if (data->primary_ll)
return;
if (data->primary_load >= data->secondary_load)
return;
swap(data->primary, data->secondary);
}
/* must be called under rcu_read_lock */
static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
struct ieee80211_vif *vif)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_bt_iterator_data *data = _data;
struct iwl_mvm *mvm = data->mvm;
struct ieee80211_chanctx_conf *chanctx_conf;
/* default smps_mode is AUTOMATIC - only used for client modes */
enum ieee80211_smps_mode smps_mode = IEEE80211_SMPS_AUTOMATIC;
u32 bt_activity_grading, min_ag_for_static_smps;
int ave_rssi;
lockdep_assert_held(&mvm->mutex);
switch (vif->type) {
case NL80211_IFTYPE_STATION:
break;
case NL80211_IFTYPE_AP:
if (!mvmvif->ap_ibss_active)
return;
break;
default:
return;
}
chanctx_conf = rcu_dereference(vif->chanctx_conf);
/* If channel context is invalid or not on 2.4GHz .. */
if ((!chanctx_conf ||
chanctx_conf->def.chan->band != NL80211_BAND_2GHZ)) {
if (vif->type == NL80211_IFTYPE_STATION) {
/* ... relax constraints and disable rssi events */
iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
smps_mode);
iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id,
false);
iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0);
}
return;
}
if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_COEX_SCHEMA_2))
min_ag_for_static_smps = BT_VERY_HIGH_TRAFFIC;
else
min_ag_for_static_smps = BT_HIGH_TRAFFIC;
bt_activity_grading = le32_to_cpu(data->notif->bt_activity_grading);
if (bt_activity_grading >= min_ag_for_static_smps)
smps_mode = IEEE80211_SMPS_STATIC;
else if (bt_activity_grading >= BT_LOW_TRAFFIC)
smps_mode = IEEE80211_SMPS_DYNAMIC;
/* relax SMPS constraints for next association */
if (!vif->bss_conf.assoc)
smps_mode = IEEE80211_SMPS_AUTOMATIC;
if (mvmvif->phy_ctxt &&
(mvm->last_bt_notif.rrc_status & BIT(mvmvif->phy_ctxt->id)))
smps_mode = IEEE80211_SMPS_AUTOMATIC;
IWL_DEBUG_COEX(data->mvm,
"mac %d: bt_activity_grading %d smps_req %d\n",
mvmvif->id, bt_activity_grading, smps_mode);
if (vif->type == NL80211_IFTYPE_STATION)
iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
smps_mode);
/* low latency is always primary */
if (iwl_mvm_vif_low_latency(mvmvif)) {
data->primary_ll = true;
data->secondary = data->primary;
data->primary = chanctx_conf;
}
if (vif->type == NL80211_IFTYPE_AP) {
if (!mvmvif->ap_ibss_active)
return;
if (chanctx_conf == data->primary)
return;
if (!data->primary_ll) {
/*
* downgrade the current primary no matter what its
* type is.
*/
data->secondary = data->primary;
data->primary = chanctx_conf;
} else {
/* there is low latency vif - we will be secondary */
data->secondary = chanctx_conf;
}
if (data->primary == chanctx_conf)
data->primary_load = mvm->tcm.result.load[mvmvif->id];
else if (data->secondary == chanctx_conf)
data->secondary_load = mvm->tcm.result.load[mvmvif->id];
return;
}
/*
* STA / P2P Client, try to be primary if first vif. If we are in low
* latency mode, we are already in primary and just don't do much
*/
if (!data->primary || data->primary == chanctx_conf)
data->primary = chanctx_conf;
else if (!data->secondary)
/* if secondary is not NULL, it might be a GO */
data->secondary = chanctx_conf;
if (data->primary == chanctx_conf)
data->primary_load = mvm->tcm.result.load[mvmvif->id];
else if (data->secondary == chanctx_conf)
data->secondary_load = mvm->tcm.result.load[mvmvif->id];
/*
* don't reduce the Tx power if one of these is true:
* we are in LOOSE
* single share antenna product
* BT is inactive
* we are not associated
*/
if (iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT ||
mvm->cfg->bt_shared_single_ant || !vif->bss_conf.assoc ||
le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) == BT_OFF) {
iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false);
iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0);
return;
}
/* try to get the avg rssi from fw */
ave_rssi = mvmvif->bf_data.ave_beacon_signal;
/* if the RSSI isn't valid, fake it is very low */
if (!ave_rssi)
ave_rssi = -100;
if (ave_rssi > -IWL_MVM_BT_COEX_EN_RED_TXP_THRESH) {
if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, true))
IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n");
} else if (ave_rssi < -IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH) {
if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false))
IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n");
}
/* Begin to monitor the RSSI: it may influence the reduced Tx power */
iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, true, ave_rssi);
}
static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm)
{
struct iwl_bt_iterator_data data = {
.mvm = mvm,
.notif = &mvm->last_bt_notif,
};
struct iwl_bt_coex_ci_cmd cmd = {};
u8 ci_bw_idx;
/* Ignore updates if we are in force mode */
if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS))
return;
rcu_read_lock();
ieee80211_iterate_active_interfaces_atomic(
mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
iwl_mvm_bt_notif_iterator, &data);
iwl_mvm_bt_coex_tcm_based_ci(mvm, &data);
if (data.primary) {
struct ieee80211_chanctx_conf *chan = data.primary;
if (WARN_ON(!chan->def.chan)) {
rcu_read_unlock();
return;
}
if (chan->def.width < NL80211_CHAN_WIDTH_40) {
ci_bw_idx = 0;
} else {
if (chan->def.center_freq1 >
chan->def.chan->center_freq)
ci_bw_idx = 2;
else
ci_bw_idx = 1;
}
cmd.bt_primary_ci =
iwl_ci_mask[chan->def.chan->hw_value][ci_bw_idx];
cmd.primary_ch_phy_id =
cpu_to_le32(*((u16 *)data.primary->drv_priv));
}
if (data.secondary) {
struct ieee80211_chanctx_conf *chan = data.secondary;
if (WARN_ON(!data.secondary->def.chan)) {
rcu_read_unlock();
return;
}
if (chan->def.width < NL80211_CHAN_WIDTH_40) {
ci_bw_idx = 0;
} else {
if (chan->def.center_freq1 >
chan->def.chan->center_freq)
ci_bw_idx = 2;
else
ci_bw_idx = 1;
}
cmd.bt_secondary_ci =
iwl_ci_mask[chan->def.chan->hw_value][ci_bw_idx];
cmd.secondary_ch_phy_id =
cpu_to_le32(*((u16 *)data.secondary->drv_priv));
}
rcu_read_unlock();
/* Don't spam the fw with the same command over and over */
if (memcmp(&cmd, &mvm->last_bt_ci_cmd, sizeof(cmd))) {
if (iwl_mvm_send_cmd_pdu(mvm, BT_COEX_CI, 0,
sizeof(cmd), &cmd))
IWL_ERR(mvm, "Failed to send BT_CI cmd\n");
memcpy(&mvm->last_bt_ci_cmd, &cmd, sizeof(cmd));
}
}
void iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
struct iwl_bt_coex_profile_notif *notif = (void *)pkt->data;
IWL_DEBUG_COEX(mvm, "BT Coex Notification received\n");
IWL_DEBUG_COEX(mvm, "\tBT ci compliance %d\n", notif->bt_ci_compliance);
IWL_DEBUG_COEX(mvm, "\tBT primary_ch_lut %d\n",
le32_to_cpu(notif->primary_ch_lut));
IWL_DEBUG_COEX(mvm, "\tBT secondary_ch_lut %d\n",
le32_to_cpu(notif->secondary_ch_lut));
IWL_DEBUG_COEX(mvm, "\tBT activity grading %d\n",
le32_to_cpu(notif->bt_activity_grading));
/* remember this notification for future use: rssi fluctuations */
memcpy(&mvm->last_bt_notif, notif, sizeof(mvm->last_bt_notif));
iwl_mvm_bt_coex_notif_handle(mvm);
}
void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
enum ieee80211_rssi_event_data rssi_event)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
int ret;
lockdep_assert_held(&mvm->mutex);
/* Ignore updates if we are in force mode */
if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS))
return;
/*
* Rssi update while not associated - can happen since the statistics
* are handled asynchronously
*/
if (mvmvif->ap_sta_id == IWL_MVM_INVALID_STA)
return;
/* No BT - reports should be disabled */
if (le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) == BT_OFF)
return;
IWL_DEBUG_COEX(mvm, "RSSI for %pM is now %s\n", vif->bss_conf.bssid,
rssi_event == RSSI_EVENT_HIGH ? "HIGH" : "LOW");
/*
* Check if rssi is good enough for reduced Tx power, but not in loose
* scheme.
*/
if (rssi_event == RSSI_EVENT_LOW || mvm->cfg->bt_shared_single_ant ||
iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT)
ret = iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id,
false);
else
ret = iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, true);
if (ret)
IWL_ERR(mvm, "couldn't send BT_CONFIG HCMD upon RSSI event\n");
}
#define LINK_QUAL_AGG_TIME_LIMIT_DEF (4000)
#define LINK_QUAL_AGG_TIME_LIMIT_BT_ACT (1200)
u16 iwl_mvm_coex_agg_time_limit(struct iwl_mvm *mvm,
struct ieee80211_sta *sta)
{
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(mvmsta->vif);
struct iwl_mvm_phy_ctxt *phy_ctxt = mvmvif->phy_ctxt;
enum iwl_bt_coex_lut_type lut_type;
if (mvm->last_bt_notif.ttc_status & BIT(phy_ctxt->id))
return LINK_QUAL_AGG_TIME_LIMIT_DEF;
if (le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) <
BT_HIGH_TRAFFIC)
return LINK_QUAL_AGG_TIME_LIMIT_DEF;
lut_type = iwl_get_coex_type(mvm, mvmsta->vif);
if (lut_type == BT_COEX_LOOSE_LUT || lut_type == BT_COEX_INVALID_LUT)
return LINK_QUAL_AGG_TIME_LIMIT_DEF;
/* tight coex, high bt traffic, reduce AGG time limit */
return LINK_QUAL_AGG_TIME_LIMIT_BT_ACT;
}
bool iwl_mvm_bt_coex_is_mimo_allowed(struct iwl_mvm *mvm,
struct ieee80211_sta *sta)
{
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(mvmsta->vif);
struct iwl_mvm_phy_ctxt *phy_ctxt = mvmvif->phy_ctxt;
enum iwl_bt_coex_lut_type lut_type;
if (mvm->last_bt_notif.ttc_status & BIT(phy_ctxt->id))
return true;
if (le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) <
BT_HIGH_TRAFFIC)
return true;
/*
* In Tight / TxTxDis, BT can't Rx while we Tx, so use both antennas
* since BT is already killed.
* In Loose, BT can Rx while we Tx, so forbid MIMO to let BT Rx while
* we Tx.
* When we are in 5GHz, we'll get BT_COEX_INVALID_LUT allowing MIMO.
*/
lut_type = iwl_get_coex_type(mvm, mvmsta->vif);
return lut_type != BT_COEX_LOOSE_LUT;
}
bool iwl_mvm_bt_coex_is_ant_avail(struct iwl_mvm *mvm, u8 ant)
{
/* there is no other antenna, shared antenna is always available */
if (mvm->cfg->bt_shared_single_ant)
return true;
if (ant & mvm->cfg->non_shared_ant)
return true;
return le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) <
BT_HIGH_TRAFFIC;
}
bool iwl_mvm_bt_coex_is_shared_ant_avail(struct iwl_mvm *mvm)
{
/* there is no other antenna, shared antenna is always available */
if (mvm->cfg->bt_shared_single_ant)
return true;
return le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) < BT_HIGH_TRAFFIC;
}
bool iwl_mvm_bt_coex_is_tpc_allowed(struct iwl_mvm *mvm,
enum nl80211_band band)
{
u32 bt_activity = le32_to_cpu(mvm->last_bt_notif.bt_activity_grading);
if (band != NL80211_BAND_2GHZ)
return false;
return bt_activity >= BT_LOW_TRAFFIC;
}
u8 iwl_mvm_bt_coex_get_single_ant_msk(struct iwl_mvm *mvm, u8 enabled_ants)
{
if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_COEX_SCHEMA_2) &&
(mvm->cfg->non_shared_ant & enabled_ants))
return mvm->cfg->non_shared_ant;
return first_antenna(enabled_ants);
}
u8 iwl_mvm_bt_coex_tx_prio(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr,
struct ieee80211_tx_info *info, u8 ac)
{
__le16 fc = hdr->frame_control;
bool mplut_enabled = iwl_mvm_is_mplut_supported(mvm);
if (info->band != NL80211_BAND_2GHZ)
return 0;
if (unlikely(mvm->bt_tx_prio))
return mvm->bt_tx_prio - 1;
if (likely(ieee80211_is_data(fc))) {
if (likely(ieee80211_is_data_qos(fc))) {
switch (ac) {
case IEEE80211_AC_BE:
return mplut_enabled ? 1 : 0;
case IEEE80211_AC_VI:
return mplut_enabled ? 2 : 3;
case IEEE80211_AC_VO:
return 3;
default:
return 0;
}
} else if (is_multicast_ether_addr(hdr->addr1)) {
return 3;
} else
return 0;
} else if (ieee80211_is_mgmt(fc)) {
return ieee80211_is_disassoc(fc) ? 0 : 3;
} else if (ieee80211_is_ctl(fc)) {
/* ignore cfend and cfendack frames as we never send those */
return 3;
}
return 0;
}
void iwl_mvm_bt_coex_vif_change(struct iwl_mvm *mvm)
{
iwl_mvm_bt_coex_notif_handle(mvm);
}

View File

@ -0,0 +1,126 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2013-2014, 2018-2021 Intel Corporation
* Copyright (C) 2015 Intel Deutschland GmbH
*/
#ifndef __MVM_CONSTANTS_H
#define __MVM_CONSTANTS_H
#include <linux/ieee80211.h>
#include "fw-api.h"
#define IWL_MVM_UAPSD_NOAGG_BSSIDS_NUM 20
#define IWL_MVM_DEFAULT_PS_TX_DATA_TIMEOUT (100 * USEC_PER_MSEC)
#define IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT (100 * USEC_PER_MSEC)
#define IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT (10 * USEC_PER_MSEC)
#define IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT (10 * USEC_PER_MSEC)
#define IWL_MVM_SHORT_PS_TX_DATA_TIMEOUT (2 * 1024) /* defined in TU */
#define IWL_MVM_SHORT_PS_RX_DATA_TIMEOUT (40 * 1024) /* defined in TU */
#define IWL_MVM_P2P_LOWLATENCY_PS_ENABLE 0
#define IWL_MVM_UAPSD_RX_DATA_TIMEOUT (50 * USEC_PER_MSEC)
#define IWL_MVM_UAPSD_TX_DATA_TIMEOUT (50 * USEC_PER_MSEC)
#define IWL_MVM_UAPSD_QUEUES (IEEE80211_WMM_IE_STA_QOSINFO_AC_VO |\
IEEE80211_WMM_IE_STA_QOSINFO_AC_VI |\
IEEE80211_WMM_IE_STA_QOSINFO_AC_BK |\
IEEE80211_WMM_IE_STA_QOSINFO_AC_BE)
#define IWL_MVM_PS_HEAVY_TX_THLD_PACKETS 20
#define IWL_MVM_PS_HEAVY_RX_THLD_PACKETS 8
#define IWL_MVM_PS_SNOOZE_HEAVY_TX_THLD_PACKETS 30
#define IWL_MVM_PS_SNOOZE_HEAVY_RX_THLD_PACKETS 20
#define IWL_MVM_PS_HEAVY_TX_THLD_PERCENT 50
#define IWL_MVM_PS_HEAVY_RX_THLD_PERCENT 50
#define IWL_MVM_PS_SNOOZE_INTERVAL 25
#define IWL_MVM_PS_SNOOZE_WINDOW 50
#define IWL_MVM_WOWLAN_PS_SNOOZE_WINDOW 25
#define IWL_MVM_LOWLAT_QUOTA_MIN_PERCENT 64
#define IWL_MVM_BT_COEX_EN_RED_TXP_THRESH 62
#define IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH 65
#define IWL_MVM_BT_COEX_SYNC2SCO 1
#define IWL_MVM_BT_COEX_MPLUT 1
#define IWL_MVM_BT_COEX_RRC 1
#define IWL_MVM_BT_COEX_TTC 1
#define IWL_MVM_BT_COEX_MPLUT_REG0 0x22002200
#define IWL_MVM_BT_COEX_MPLUT_REG1 0x11118451
#define IWL_MVM_BT_COEX_ANTENNA_COUPLING_THRS 30
#define IWL_MVM_FW_MCAST_FILTER_PASS_ALL 0
#define IWL_MVM_FW_BCAST_FILTER_PASS_ALL 0
#define IWL_MVM_QUOTA_THRESHOLD 4
#define IWL_MVM_RS_RSSI_BASED_INIT_RATE 0
#define IWL_MVM_RS_80_20_FAR_RANGE_TWEAK 1
#define IWL_MVM_TOF_IS_RESPONDER 0
#define IWL_MVM_HW_CSUM_DISABLE 0
#define IWL_MVM_PARSE_NVM 0
#define IWL_MVM_ADWELL_ENABLE 1
#define IWL_MVM_ADWELL_MAX_BUDGET 0
#define IWL_MVM_TCM_LOAD_MEDIUM_THRESH 10 /* percentage */
#define IWL_MVM_TCM_LOAD_HIGH_THRESH 50 /* percentage */
#define IWL_MVM_TCM_LOWLAT_ENABLE_THRESH 100 /* packets/10 seconds */
#define IWL_MVM_UAPSD_NONAGG_PERIOD 5000 /* msecs */
#define IWL_MVM_UAPSD_NOAGG_LIST_LEN IWL_MVM_UAPSD_NOAGG_BSSIDS_NUM
#define IWL_MVM_NON_TRANSMITTING_AP 0
#define IWL_MVM_RS_NUM_TRY_BEFORE_ANT_TOGGLE 1
#define IWL_MVM_RS_HT_VHT_RETRIES_PER_RATE 2
#define IWL_MVM_RS_HT_VHT_RETRIES_PER_RATE_TW 1
#define IWL_MVM_RS_INITIAL_MIMO_NUM_RATES 3
#define IWL_MVM_RS_INITIAL_SISO_NUM_RATES 3
#define IWL_MVM_RS_INITIAL_LEGACY_NUM_RATES 2
#define IWL_MVM_RS_INITIAL_LEGACY_RETRIES 2
#define IWL_MVM_RS_SECONDARY_LEGACY_RETRIES 1
#define IWL_MVM_RS_SECONDARY_LEGACY_NUM_RATES 16
#define IWL_MVM_RS_SECONDARY_SISO_NUM_RATES 3
#define IWL_MVM_RS_SECONDARY_SISO_RETRIES 1
#define IWL_MVM_RS_RATE_MIN_FAILURE_TH 3
#define IWL_MVM_RS_RATE_MIN_SUCCESS_TH 8
#define IWL_MVM_RS_STAY_IN_COLUMN_TIMEOUT 5 /* Seconds */
#define IWL_MVM_RS_IDLE_TIMEOUT 5 /* Seconds */
#define IWL_MVM_RS_MISSED_RATE_MAX 15
#define IWL_MVM_RS_LEGACY_FAILURE_LIMIT 160
#define IWL_MVM_RS_LEGACY_SUCCESS_LIMIT 480
#define IWL_MVM_RS_LEGACY_TABLE_COUNT 160
#define IWL_MVM_RS_NON_LEGACY_FAILURE_LIMIT 400
#define IWL_MVM_RS_NON_LEGACY_SUCCESS_LIMIT 4500
#define IWL_MVM_RS_NON_LEGACY_TABLE_COUNT 1500
#define IWL_MVM_RS_SR_FORCE_DECREASE 15 /* percent */
#define IWL_MVM_RS_SR_NO_DECREASE 85 /* percent */
#define IWL_MVM_RS_AGG_TIME_LIMIT 4000 /* 4 msecs. valid 100-8000 */
#define IWL_MVM_RS_AGG_DISABLE_START 3
#define IWL_MVM_RS_AGG_START_THRESHOLD 10 /* num frames per second */
#define IWL_MVM_RS_TPC_SR_FORCE_INCREASE 75 /* percent */
#define IWL_MVM_RS_TPC_SR_NO_INCREASE 85 /* percent */
#define IWL_MVM_RS_TPC_TX_POWER_STEP 3
#define IWL_MVM_ENABLE_EBS 1
#define IWL_MVM_FTM_INITIATOR_ALGO IWL_TOF_ALGO_TYPE_MAX_LIKE
#define IWL_MVM_FTM_INITIATOR_DYNACK true
#define IWL_MVM_FTM_LMR_FEEDBACK_TERMINATE false
#define IWL_MVM_FTM_R2I_MAX_REP 7
#define IWL_MVM_FTM_I2R_MAX_REP 7
#define IWL_MVM_FTM_R2I_MAX_STS 1
#define IWL_MVM_FTM_I2R_MAX_STS 1
#define IWL_MVM_FTM_R2I_MAX_TOTAL_LTF 3
#define IWL_MVM_FTM_I2R_MAX_TOTAL_LTF 3
#define IWL_MVM_FTM_INITIATOR_SECURE_LTF false
#define IWL_MVM_FTM_RESP_NDP_SUPPORT true
#define IWL_MVM_FTM_RESP_LMR_FEEDBACK_SUPPORT true
#define IWL_MVM_FTM_NON_TB_MIN_TIME_BETWEEN_MSR 5
#define IWL_MVM_FTM_NON_TB_MAX_TIME_BETWEEN_MSR 1000
#define IWL_MVM_D3_DEBUG false
#define IWL_MVM_USE_TWT true
#define IWL_MVM_AMPDU_CONSEC_DROPS_DELBA 10
#define IWL_MVM_USE_NSSN_SYNC 0
#define IWL_MVM_PHY_FILTER_CHAIN_A 0
#define IWL_MVM_PHY_FILTER_CHAIN_B 0
#define IWL_MVM_PHY_FILTER_CHAIN_C 0
#define IWL_MVM_PHY_FILTER_CHAIN_D 0
#define IWL_MVM_FTM_INITIATOR_ENABLE_SMOOTH false
#define IWL_MVM_FTM_INITIATOR_SMOOTH_ALPHA 40
/* 20016 pSec is 6 meter RTT, meaning 3 meter range */
#define IWL_MVM_FTM_INITIATOR_SMOOTH_UNDERSHOOT 20016
#define IWL_MVM_FTM_INITIATOR_SMOOTH_OVERSHOOT 20016
#define IWL_MVM_FTM_INITIATOR_SMOOTH_AGE_SEC 2
#define IWL_MVM_DISABLE_AP_FILS false
#define IWL_MVM_6GHZ_PASSIVE_SCAN_TIMEOUT 3000 /* in seconds */
#define IWL_MVM_6GHZ_PASSIVE_SCAN_ASSOC_TIMEOUT 60 /* in seconds */
#endif /* __MVM_CONSTANTS_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,481 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2015-2017 Intel Deutschland GmbH
* Copyright (C) 2018-2021 Intel Corporation
*/
#include <net/cfg80211.h>
#include <linux/etherdevice.h>
#include "mvm.h"
#include "constants.h"
struct iwl_mvm_pasn_sta {
struct list_head list;
struct iwl_mvm_int_sta int_sta;
u8 addr[ETH_ALEN];
};
struct iwl_mvm_pasn_hltk_data {
u8 *addr;
u8 cipher;
u8 *hltk;
};
static int iwl_mvm_ftm_responder_set_bw_v1(struct cfg80211_chan_def *chandef,
u8 *bw, u8 *ctrl_ch_position)
{
switch (chandef->width) {
case NL80211_CHAN_WIDTH_20_NOHT:
*bw = IWL_TOF_BW_20_LEGACY;
break;
case NL80211_CHAN_WIDTH_20:
*bw = IWL_TOF_BW_20_HT;
break;
case NL80211_CHAN_WIDTH_40:
*bw = IWL_TOF_BW_40;
*ctrl_ch_position = iwl_mvm_get_ctrl_pos(chandef);
break;
case NL80211_CHAN_WIDTH_80:
*bw = IWL_TOF_BW_80;
*ctrl_ch_position = iwl_mvm_get_ctrl_pos(chandef);
break;
default:
return -ENOTSUPP;
}
return 0;
}
static int iwl_mvm_ftm_responder_set_bw_v2(struct cfg80211_chan_def *chandef,
u8 *format_bw, u8 *ctrl_ch_position,
u8 cmd_ver)
{
switch (chandef->width) {
case NL80211_CHAN_WIDTH_20_NOHT:
*format_bw = IWL_LOCATION_FRAME_FORMAT_LEGACY;
*format_bw |= IWL_LOCATION_BW_20MHZ << LOCATION_BW_POS;
break;
case NL80211_CHAN_WIDTH_20:
*format_bw = IWL_LOCATION_FRAME_FORMAT_HT;
*format_bw |= IWL_LOCATION_BW_20MHZ << LOCATION_BW_POS;
break;
case NL80211_CHAN_WIDTH_40:
*format_bw = IWL_LOCATION_FRAME_FORMAT_HT;
*format_bw |= IWL_LOCATION_BW_40MHZ << LOCATION_BW_POS;
*ctrl_ch_position = iwl_mvm_get_ctrl_pos(chandef);
break;
case NL80211_CHAN_WIDTH_80:
*format_bw = IWL_LOCATION_FRAME_FORMAT_VHT;
*format_bw |= IWL_LOCATION_BW_80MHZ << LOCATION_BW_POS;
*ctrl_ch_position = iwl_mvm_get_ctrl_pos(chandef);
break;
case NL80211_CHAN_WIDTH_160:
if (cmd_ver >= 9) {
*format_bw = IWL_LOCATION_FRAME_FORMAT_HE;
*format_bw |= IWL_LOCATION_BW_160MHZ << LOCATION_BW_POS;
*ctrl_ch_position = iwl_mvm_get_ctrl_pos(chandef);
break;
}
fallthrough;
default:
return -ENOTSUPP;
}
return 0;
}
static void
iwl_mvm_ftm_responder_set_ndp(struct iwl_mvm *mvm,
struct iwl_tof_responder_config_cmd_v9 *cmd)
{
/* Up to 2 R2I STS are allowed on the responder */
u32 r2i_max_sts = IWL_MVM_FTM_R2I_MAX_STS < 2 ?
IWL_MVM_FTM_R2I_MAX_STS : 1;
cmd->r2i_ndp_params = IWL_MVM_FTM_R2I_MAX_REP |
(r2i_max_sts << IWL_RESPONDER_STS_POS) |
(IWL_MVM_FTM_R2I_MAX_TOTAL_LTF << IWL_RESPONDER_TOTAL_LTF_POS);
cmd->i2r_ndp_params = IWL_MVM_FTM_I2R_MAX_REP |
(IWL_MVM_FTM_I2R_MAX_STS << IWL_RESPONDER_STS_POS) |
(IWL_MVM_FTM_I2R_MAX_TOTAL_LTF << IWL_RESPONDER_TOTAL_LTF_POS);
cmd->cmd_valid_fields |=
cpu_to_le32(IWL_TOF_RESPONDER_CMD_VALID_NDP_PARAMS);
}
static int
iwl_mvm_ftm_responder_cmd(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct cfg80211_chan_def *chandef)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
/*
* The command structure is the same for versions 6, 7 and 8 (only the
* field interpretation is different), so the same struct can be use
* for all cases.
*/
struct iwl_tof_responder_config_cmd_v9 cmd = {
.channel_num = chandef->chan->hw_value,
.cmd_valid_fields =
cpu_to_le32(IWL_TOF_RESPONDER_CMD_VALID_CHAN_INFO |
IWL_TOF_RESPONDER_CMD_VALID_BSSID |
IWL_TOF_RESPONDER_CMD_VALID_STA_ID),
.sta_id = mvmvif->bcast_sta.sta_id,
};
u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, LOCATION_GROUP,
TOF_RESPONDER_CONFIG_CMD, 6);
int err;
int cmd_size;
lockdep_assert_held(&mvm->mutex);
/* Use a default of bss_color=1 for now */
if (cmd_ver == 9) {
cmd.cmd_valid_fields |=
cpu_to_le32(IWL_TOF_RESPONDER_CMD_VALID_BSS_COLOR |
IWL_TOF_RESPONDER_CMD_VALID_MIN_MAX_TIME_BETWEEN_MSR);
cmd.bss_color = 1;
cmd.min_time_between_msr =
cpu_to_le16(IWL_MVM_FTM_NON_TB_MIN_TIME_BETWEEN_MSR);
cmd.max_time_between_msr =
cpu_to_le16(IWL_MVM_FTM_NON_TB_MAX_TIME_BETWEEN_MSR);
cmd_size = sizeof(struct iwl_tof_responder_config_cmd_v9);
} else {
/* All versions up to version 8 have the same size */
cmd_size = sizeof(struct iwl_tof_responder_config_cmd_v8);
}
if (cmd_ver >= 8)
iwl_mvm_ftm_responder_set_ndp(mvm, &cmd);
if (cmd_ver >= 7)
err = iwl_mvm_ftm_responder_set_bw_v2(chandef, &cmd.format_bw,
&cmd.ctrl_ch_position,
cmd_ver);
else
err = iwl_mvm_ftm_responder_set_bw_v1(chandef, &cmd.format_bw,
&cmd.ctrl_ch_position);
if (err) {
IWL_ERR(mvm, "Failed to set responder bandwidth\n");
return err;
}
memcpy(cmd.bssid, vif->addr, ETH_ALEN);
return iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(TOF_RESPONDER_CONFIG_CMD,
LOCATION_GROUP, 0),
0, cmd_size, &cmd);
}
static int
iwl_mvm_ftm_responder_dyn_cfg_v2(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct ieee80211_ftm_responder_params *params)
{
struct iwl_tof_responder_dyn_config_cmd_v2 cmd = {
.lci_len = cpu_to_le32(params->lci_len + 2),
.civic_len = cpu_to_le32(params->civicloc_len + 2),
};
u8 data[IWL_LCI_CIVIC_IE_MAX_SIZE] = {0};
struct iwl_host_cmd hcmd = {
.id = iwl_cmd_id(TOF_RESPONDER_DYN_CONFIG_CMD,
LOCATION_GROUP, 0),
.data[0] = &cmd,
.len[0] = sizeof(cmd),
.data[1] = &data,
/* .len[1] set later */
/* may not be able to DMA from stack */
.dataflags[1] = IWL_HCMD_DFL_DUP,
};
u32 aligned_lci_len = ALIGN(params->lci_len + 2, 4);
u32 aligned_civicloc_len = ALIGN(params->civicloc_len + 2, 4);
u8 *pos = data;
lockdep_assert_held(&mvm->mutex);
if (aligned_lci_len + aligned_civicloc_len > sizeof(data)) {
IWL_ERR(mvm, "LCI/civicloc data too big (%zd + %zd)\n",
params->lci_len, params->civicloc_len);
return -ENOBUFS;
}
pos[0] = WLAN_EID_MEASURE_REPORT;
pos[1] = params->lci_len;
memcpy(pos + 2, params->lci, params->lci_len);
pos += aligned_lci_len;
pos[0] = WLAN_EID_MEASURE_REPORT;
pos[1] = params->civicloc_len;
memcpy(pos + 2, params->civicloc, params->civicloc_len);
hcmd.len[1] = aligned_lci_len + aligned_civicloc_len;
return iwl_mvm_send_cmd(mvm, &hcmd);
}
static int
iwl_mvm_ftm_responder_dyn_cfg_v3(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct ieee80211_ftm_responder_params *params,
struct iwl_mvm_pasn_hltk_data *hltk_data)
{
struct iwl_tof_responder_dyn_config_cmd cmd;
struct iwl_host_cmd hcmd = {
.id = iwl_cmd_id(TOF_RESPONDER_DYN_CONFIG_CMD,
LOCATION_GROUP, 0),
.data[0] = &cmd,
.len[0] = sizeof(cmd),
/* may not be able to DMA from stack */
.dataflags[0] = IWL_HCMD_DFL_DUP,
};
lockdep_assert_held(&mvm->mutex);
cmd.valid_flags = 0;
if (params) {
if (params->lci_len + 2 > sizeof(cmd.lci_buf) ||
params->civicloc_len + 2 > sizeof(cmd.civic_buf)) {
IWL_ERR(mvm,
"LCI/civic data too big (lci=%zd, civic=%zd)\n",
params->lci_len, params->civicloc_len);
return -ENOBUFS;
}
cmd.lci_buf[0] = WLAN_EID_MEASURE_REPORT;
cmd.lci_buf[1] = params->lci_len;
memcpy(cmd.lci_buf + 2, params->lci, params->lci_len);
cmd.lci_len = params->lci_len + 2;
cmd.civic_buf[0] = WLAN_EID_MEASURE_REPORT;
cmd.civic_buf[1] = params->civicloc_len;
memcpy(cmd.civic_buf + 2, params->civicloc,
params->civicloc_len);
cmd.civic_len = params->civicloc_len + 2;
cmd.valid_flags |= IWL_RESPONDER_DYN_CFG_VALID_LCI |
IWL_RESPONDER_DYN_CFG_VALID_CIVIC;
}
if (hltk_data) {
if (hltk_data->cipher > IWL_LOCATION_CIPHER_GCMP_256) {
IWL_ERR(mvm, "invalid cipher: %u\n",
hltk_data->cipher);
return -EINVAL;
}
cmd.cipher = hltk_data->cipher;
memcpy(cmd.addr, hltk_data->addr, sizeof(cmd.addr));
memcpy(cmd.hltk_buf, hltk_data->hltk, sizeof(cmd.hltk_buf));
cmd.valid_flags |= IWL_RESPONDER_DYN_CFG_VALID_PASN_STA;
}
return iwl_mvm_send_cmd(mvm, &hcmd);
}
static int
iwl_mvm_ftm_responder_dyn_cfg_cmd(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct ieee80211_ftm_responder_params *params)
{
int ret;
u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, LOCATION_GROUP,
TOF_RESPONDER_DYN_CONFIG_CMD, 2);
switch (cmd_ver) {
case 2:
ret = iwl_mvm_ftm_responder_dyn_cfg_v2(mvm, vif,
params);
break;
case 3:
ret = iwl_mvm_ftm_responder_dyn_cfg_v3(mvm, vif,
params, NULL);
break;
default:
IWL_ERR(mvm, "Unsupported DYN_CONFIG_CMD version %u\n",
cmd_ver);
ret = -ENOTSUPP;
}
return ret;
}
static void iwl_mvm_resp_del_pasn_sta(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct iwl_mvm_pasn_sta *sta)
{
list_del(&sta->list);
iwl_mvm_rm_sta_id(mvm, vif, sta->int_sta.sta_id);
iwl_mvm_dealloc_int_sta(mvm, &sta->int_sta);
kfree(sta);
}
int iwl_mvm_ftm_respoder_add_pasn_sta(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
u8 *addr, u32 cipher, u8 *tk, u32 tk_len,
u8 *hltk, u32 hltk_len)
{
int ret;
struct iwl_mvm_pasn_sta *sta = NULL;
struct iwl_mvm_pasn_hltk_data hltk_data = {
.addr = addr,
.hltk = hltk,
};
u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, LOCATION_GROUP,
TOF_RESPONDER_DYN_CONFIG_CMD, 2);
lockdep_assert_held(&mvm->mutex);
if (cmd_ver < 3) {
IWL_ERR(mvm, "Adding PASN station not supported by FW\n");
return -ENOTSUPP;
}
hltk_data.cipher = iwl_mvm_cipher_to_location_cipher(cipher);
if (hltk_data.cipher == IWL_LOCATION_CIPHER_INVALID) {
IWL_ERR(mvm, "invalid cipher: %u\n", cipher);
return -EINVAL;
}
if (tk && tk_len) {
sta = kzalloc(sizeof(*sta), GFP_KERNEL);
if (!sta)
return -ENOBUFS;
ret = iwl_mvm_add_pasn_sta(mvm, vif, &sta->int_sta, addr,
cipher, tk, tk_len);
if (ret) {
kfree(sta);
return ret;
}
memcpy(sta->addr, addr, ETH_ALEN);
list_add_tail(&sta->list, &mvm->resp_pasn_list);
}
ret = iwl_mvm_ftm_responder_dyn_cfg_v3(mvm, vif, NULL, &hltk_data);
if (ret && sta)
iwl_mvm_resp_del_pasn_sta(mvm, vif, sta);
return ret;
}
int iwl_mvm_ftm_resp_remove_pasn_sta(struct iwl_mvm *mvm,
struct ieee80211_vif *vif, u8 *addr)
{
struct iwl_mvm_pasn_sta *sta, *prev;
lockdep_assert_held(&mvm->mutex);
list_for_each_entry_safe(sta, prev, &mvm->resp_pasn_list, list) {
if (!memcmp(sta->addr, addr, ETH_ALEN)) {
iwl_mvm_resp_del_pasn_sta(mvm, vif, sta);
return 0;
}
}
IWL_ERR(mvm, "FTM: PASN station %pM not found\n", addr);
return -EINVAL;
}
int iwl_mvm_ftm_start_responder(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct ieee80211_ftm_responder_params *params;
struct ieee80211_chanctx_conf ctx, *pctx;
u16 *phy_ctxt_id;
struct iwl_mvm_phy_ctxt *phy_ctxt;
int ret;
params = vif->bss_conf.ftmr_params;
lockdep_assert_held(&mvm->mutex);
if (WARN_ON_ONCE(!vif->bss_conf.ftm_responder))
return -EINVAL;
if (vif->p2p || vif->type != NL80211_IFTYPE_AP ||
!mvmvif->ap_ibss_active) {
IWL_ERR(mvm, "Cannot start responder, not in AP mode\n");
return -EIO;
}
rcu_read_lock();
pctx = rcu_dereference(vif->chanctx_conf);
/* Copy the ctx to unlock the rcu and send the phy ctxt. We don't care
* about changes in the ctx after releasing the lock because the driver
* is still protected by the mutex. */
ctx = *pctx;
phy_ctxt_id = (u16 *)pctx->drv_priv;
rcu_read_unlock();
phy_ctxt = &mvm->phy_ctxts[*phy_ctxt_id];
ret = iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &ctx.def,
ctx.rx_chains_static,
ctx.rx_chains_dynamic);
if (ret)
return ret;
ret = iwl_mvm_ftm_responder_cmd(mvm, vif, &ctx.def);
if (ret)
return ret;
if (params)
ret = iwl_mvm_ftm_responder_dyn_cfg_cmd(mvm, vif, params);
return ret;
}
void iwl_mvm_ftm_responder_clear(struct iwl_mvm *mvm,
struct ieee80211_vif *vif)
{
struct iwl_mvm_pasn_sta *sta, *prev;
lockdep_assert_held(&mvm->mutex);
list_for_each_entry_safe(sta, prev, &mvm->resp_pasn_list, list)
iwl_mvm_resp_del_pasn_sta(mvm, vif, sta);
}
void iwl_mvm_ftm_restart_responder(struct iwl_mvm *mvm,
struct ieee80211_vif *vif)
{
if (!vif->bss_conf.ftm_responder)
return;
iwl_mvm_ftm_responder_clear(mvm, vif);
iwl_mvm_ftm_start_responder(mvm, vif);
}
void iwl_mvm_ftm_responder_stats(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
struct iwl_ftm_responder_stats *resp = (void *)pkt->data;
struct cfg80211_ftm_responder_stats *stats = &mvm->ftm_resp_stats;
u32 flags = le32_to_cpu(resp->flags);
if (resp->success_ftm == resp->ftm_per_burst)
stats->success_num++;
else if (resp->success_ftm >= 2)
stats->partial_num++;
else
stats->failed_num++;
if ((flags & FTM_RESP_STAT_ASAP_REQ) &&
(flags & FTM_RESP_STAT_ASAP_RESP))
stats->asap_num++;
if (flags & FTM_RESP_STAT_NON_ASAP_RESP)
stats->non_asap_num++;
stats->total_duration_ms += le32_to_cpu(resp->duration) / USEC_PER_MSEC;
if (flags & FTM_RESP_STAT_TRIGGER_UNKNOWN)
stats->unknown_triggers_num++;
if (flags & FTM_RESP_STAT_DUP)
stats->reschedule_requests_num++;
if (flags & FTM_RESP_STAT_NON_ASAP_OUT_WIN)
stats->out_of_window_triggers_num++;
}

View File

@ -0,0 +1,41 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2012-2014, 2018, 2020 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
#ifndef __fw_api_h__
#define __fw_api_h__
#include "fw/api/tdls.h"
#include "fw/api/mac-cfg.h"
#include "fw/api/offload.h"
#include "fw/api/context.h"
#include "fw/api/time-event.h"
#include "fw/api/datapath.h"
#include "fw/api/phy.h"
#include "fw/api/config.h"
#include "fw/api/soc.h"
#include "fw/api/alive.h"
#include "fw/api/binding.h"
#include "fw/api/cmdhdr.h"
#include "fw/api/coex.h"
#include "fw/api/commands.h"
#include "fw/api/d3.h"
#include "fw/api/filter.h"
#include "fw/api/led.h"
#include "fw/api/mac.h"
#include "fw/api/nvm-reg.h"
#include "fw/api/phy-ctxt.h"
#include "fw/api/power.h"
#include "fw/api/rs.h"
#include "fw/api/rx.h"
#include "fw/api/scan.h"
#include "fw/api/sf.h"
#include "fw/api/sta.h"
#include "fw/api/stats.h"
#include "fw/api/location.h"
#include "fw/api/tx.h"
#include "fw/api/rfi.h"
#endif /* __fw_api_h__ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,119 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2012-2014, 2018-2019 Intel Corporation
* Copyright (C) 2017 Intel Deutschland GmbH
*/
#include <linux/leds.h>
#include "iwl-io.h"
#include "iwl-csr.h"
#include "mvm.h"
static void iwl_mvm_send_led_fw_cmd(struct iwl_mvm *mvm, bool on)
{
struct iwl_led_cmd led_cmd = {
.status = cpu_to_le32(on),
};
struct iwl_host_cmd cmd = {
.id = WIDE_ID(LONG_GROUP, LEDS_CMD),
.len = { sizeof(led_cmd), },
.data = { &led_cmd, },
.flags = CMD_ASYNC,
};
int err;
if (!iwl_mvm_firmware_running(mvm))
return;
err = iwl_mvm_send_cmd(mvm, &cmd);
if (err)
IWL_WARN(mvm, "LED command failed: %d\n", err);
}
static void iwl_mvm_led_set(struct iwl_mvm *mvm, bool on)
{
if (fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_LED_CMD_SUPPORT)) {
iwl_mvm_send_led_fw_cmd(mvm, on);
return;
}
iwl_write32(mvm->trans, CSR_LED_REG,
on ? CSR_LED_REG_TURN_ON : CSR_LED_REG_TURN_OFF);
}
static void iwl_led_brightness_set(struct led_classdev *led_cdev,
enum led_brightness brightness)
{
struct iwl_mvm *mvm = container_of(led_cdev, struct iwl_mvm, led);
iwl_mvm_led_set(mvm, brightness > 0);
}
int iwl_mvm_leds_init(struct iwl_mvm *mvm)
{
int mode = iwlwifi_mod_params.led_mode;
int ret;
switch (mode) {
case IWL_LED_BLINK:
IWL_ERR(mvm, "Blink led mode not supported, used default\n");
fallthrough;
case IWL_LED_DEFAULT:
case IWL_LED_RF_STATE:
mode = IWL_LED_RF_STATE;
break;
case IWL_LED_DISABLE:
IWL_INFO(mvm, "Led disabled\n");
return 0;
default:
return -EINVAL;
}
mvm->led.name = kasprintf(GFP_KERNEL, "%s-led",
wiphy_name(mvm->hw->wiphy));
if (!mvm->led.name)
return -ENOMEM;
mvm->led.brightness_set = iwl_led_brightness_set;
mvm->led.max_brightness = 1;
if (mode == IWL_LED_RF_STATE)
mvm->led.default_trigger =
ieee80211_get_radio_led_name(mvm->hw);
ret = led_classdev_register(mvm->trans->dev, &mvm->led);
if (ret) {
kfree(mvm->led.name);
IWL_INFO(mvm, "Failed to enable led\n");
return ret;
}
mvm->init_status |= IWL_MVM_INIT_STATUS_LEDS_INIT_COMPLETE;
return 0;
}
void iwl_mvm_leds_sync(struct iwl_mvm *mvm)
{
if (!(mvm->init_status & IWL_MVM_INIT_STATUS_LEDS_INIT_COMPLETE))
return;
/*
* if we control through the register, we're doing it
* even when the firmware isn't up, so no need to sync
*/
if (mvm->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_8000)
return;
iwl_mvm_led_set(mvm, mvm->led.brightness > 0);
}
void iwl_mvm_leds_exit(struct iwl_mvm *mvm)
{
if (!(mvm->init_status & IWL_MVM_INIT_STATUS_LEDS_INIT_COMPLETE))
return;
led_classdev_unregister(&mvm->led);
kfree(mvm->led.name);
mvm->init_status &= ~IWL_MVM_INIT_STATUS_LEDS_INIT_COMPLETE;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,598 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2012-2014, 2018-2019, 2021 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
#include <linux/firmware.h>
#if defined(__linux__)
#include <linux/rtnetlink.h>
#endif
#include "iwl-trans.h"
#include "iwl-csr.h"
#include "mvm.h"
#include "iwl-eeprom-parse.h"
#include "iwl-eeprom-read.h"
#include "iwl-nvm-parse.h"
#include "iwl-prph.h"
#include "fw/acpi.h"
/* Default NVM size to read */
#define IWL_NVM_DEFAULT_CHUNK_SIZE (2 * 1024)
#define NVM_WRITE_OPCODE 1
#define NVM_READ_OPCODE 0
/* load nvm chunk response */
enum {
READ_NVM_CHUNK_SUCCEED = 0,
READ_NVM_CHUNK_NOT_VALID_ADDRESS = 1
};
/*
* prepare the NVM host command w/ the pointers to the nvm buffer
* and send it to fw
*/
static int iwl_nvm_write_chunk(struct iwl_mvm *mvm, u16 section,
u16 offset, u16 length, const u8 *data)
{
struct iwl_nvm_access_cmd nvm_access_cmd = {
.offset = cpu_to_le16(offset),
.length = cpu_to_le16(length),
.type = cpu_to_le16(section),
.op_code = NVM_WRITE_OPCODE,
};
struct iwl_host_cmd cmd = {
.id = NVM_ACCESS_CMD,
.len = { sizeof(struct iwl_nvm_access_cmd), length },
.flags = CMD_WANT_SKB | CMD_SEND_IN_RFKILL,
.data = { &nvm_access_cmd, data },
/* data may come from vmalloc, so use _DUP */
.dataflags = { 0, IWL_HCMD_DFL_DUP },
};
struct iwl_rx_packet *pkt;
struct iwl_nvm_access_resp *nvm_resp;
int ret;
ret = iwl_mvm_send_cmd(mvm, &cmd);
if (ret)
return ret;
pkt = cmd.resp_pkt;
/* Extract & check NVM write response */
nvm_resp = (void *)pkt->data;
if (le16_to_cpu(nvm_resp->status) != READ_NVM_CHUNK_SUCCEED) {
IWL_ERR(mvm,
"NVM access write command failed for section %u (status = 0x%x)\n",
section, le16_to_cpu(nvm_resp->status));
ret = -EIO;
}
iwl_free_resp(&cmd);
return ret;
}
static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section,
u16 offset, u16 length, u8 *data)
{
struct iwl_nvm_access_cmd nvm_access_cmd = {
.offset = cpu_to_le16(offset),
.length = cpu_to_le16(length),
.type = cpu_to_le16(section),
.op_code = NVM_READ_OPCODE,
};
struct iwl_nvm_access_resp *nvm_resp;
struct iwl_rx_packet *pkt;
struct iwl_host_cmd cmd = {
.id = NVM_ACCESS_CMD,
.flags = CMD_WANT_SKB | CMD_SEND_IN_RFKILL,
.data = { &nvm_access_cmd, },
};
int ret, bytes_read, offset_read;
u8 *resp_data;
cmd.len[0] = sizeof(struct iwl_nvm_access_cmd);
ret = iwl_mvm_send_cmd(mvm, &cmd);
if (ret)
return ret;
pkt = cmd.resp_pkt;
/* Extract NVM response */
nvm_resp = (void *)pkt->data;
ret = le16_to_cpu(nvm_resp->status);
bytes_read = le16_to_cpu(nvm_resp->length);
offset_read = le16_to_cpu(nvm_resp->offset);
resp_data = nvm_resp->data;
if (ret) {
if ((offset != 0) &&
(ret == READ_NVM_CHUNK_NOT_VALID_ADDRESS)) {
/*
* meaning of NOT_VALID_ADDRESS:
* driver try to read chunk from address that is
* multiple of 2K and got an error since addr is empty.
* meaning of (offset != 0): driver already
* read valid data from another chunk so this case
* is not an error.
*/
IWL_DEBUG_EEPROM(mvm->trans->dev,
"NVM access command failed on offset 0x%x since that section size is multiple 2K\n",
offset);
ret = 0;
} else {
IWL_DEBUG_EEPROM(mvm->trans->dev,
"NVM access command failed with status %d (device: %s)\n",
ret, mvm->trans->name);
ret = -ENODATA;
}
goto exit;
}
if (offset_read != offset) {
IWL_ERR(mvm, "NVM ACCESS response with invalid offset %d\n",
offset_read);
ret = -EINVAL;
goto exit;
}
/* Write data to NVM */
memcpy(data + offset, resp_data, bytes_read);
ret = bytes_read;
exit:
iwl_free_resp(&cmd);
return ret;
}
static int iwl_nvm_write_section(struct iwl_mvm *mvm, u16 section,
const u8 *data, u16 length)
{
int offset = 0;
/* copy data in chunks of 2k (and remainder if any) */
while (offset < length) {
int chunk_size, ret;
chunk_size = min(IWL_NVM_DEFAULT_CHUNK_SIZE,
length - offset);
ret = iwl_nvm_write_chunk(mvm, section, offset,
chunk_size, data + offset);
if (ret < 0)
return ret;
offset += chunk_size;
}
return 0;
}
/*
* Reads an NVM section completely.
* NICs prior to 7000 family doesn't have a real NVM, but just read
* section 0 which is the EEPROM. Because the EEPROM reading is unlimited
* by uCode, we need to manually check in this case that we don't
* overflow and try to read more than the EEPROM size.
* For 7000 family NICs, we supply the maximal size we can read, and
* the uCode fills the response with as much data as we can,
* without overflowing, so no check is needed.
*/
static int iwl_nvm_read_section(struct iwl_mvm *mvm, u16 section,
u8 *data, u32 size_read)
{
u16 length, offset = 0;
int ret;
/* Set nvm section read length */
length = IWL_NVM_DEFAULT_CHUNK_SIZE;
ret = length;
/* Read the NVM until exhausted (reading less than requested) */
while (ret == length) {
/* Check no memory assumptions fail and cause an overflow */
if ((size_read + offset + length) >
mvm->trans->trans_cfg->base_params->eeprom_size) {
IWL_ERR(mvm, "EEPROM size is too small for NVM\n");
return -ENOBUFS;
}
ret = iwl_nvm_read_chunk(mvm, section, offset, length, data);
if (ret < 0) {
IWL_DEBUG_EEPROM(mvm->trans->dev,
"Cannot read NVM from section %d offset %d, length %d\n",
section, offset, length);
return ret;
}
offset += ret;
}
iwl_nvm_fixups(mvm->trans->hw_id, section, data, offset);
IWL_DEBUG_EEPROM(mvm->trans->dev,
"NVM section %d read completed\n", section);
return offset;
}
static struct iwl_nvm_data *
iwl_parse_nvm_sections(struct iwl_mvm *mvm)
{
struct iwl_nvm_section *sections = mvm->nvm_sections;
const __be16 *hw;
const __le16 *sw, *calib, *regulatory, *mac_override, *phy_sku;
int regulatory_type;
/* Checking for required sections */
if (mvm->trans->cfg->nvm_type == IWL_NVM) {
if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data ||
!mvm->nvm_sections[mvm->cfg->nvm_hw_section_num].data) {
IWL_ERR(mvm, "Can't parse empty OTP/NVM sections\n");
return NULL;
}
} else {
if (mvm->trans->cfg->nvm_type == IWL_NVM_SDP)
regulatory_type = NVM_SECTION_TYPE_REGULATORY_SDP;
else
regulatory_type = NVM_SECTION_TYPE_REGULATORY;
/* SW and REGULATORY sections are mandatory */
if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data ||
!mvm->nvm_sections[regulatory_type].data) {
IWL_ERR(mvm,
"Can't parse empty family 8000 OTP/NVM sections\n");
return NULL;
}
/* MAC_OVERRIDE or at least HW section must exist */
if (!mvm->nvm_sections[mvm->cfg->nvm_hw_section_num].data &&
!mvm->nvm_sections[NVM_SECTION_TYPE_MAC_OVERRIDE].data) {
IWL_ERR(mvm,
"Can't parse mac_address, empty sections\n");
return NULL;
}
/* PHY_SKU section is mandatory in B0 */
if (mvm->trans->cfg->nvm_type == IWL_NVM_EXT &&
!mvm->nvm_sections[NVM_SECTION_TYPE_PHY_SKU].data) {
IWL_ERR(mvm,
"Can't parse phy_sku in B0, empty sections\n");
return NULL;
}
}
hw = (const __be16 *)sections[mvm->cfg->nvm_hw_section_num].data;
sw = (const __le16 *)sections[NVM_SECTION_TYPE_SW].data;
calib = (const __le16 *)sections[NVM_SECTION_TYPE_CALIBRATION].data;
mac_override =
(const __le16 *)sections[NVM_SECTION_TYPE_MAC_OVERRIDE].data;
phy_sku = (const __le16 *)sections[NVM_SECTION_TYPE_PHY_SKU].data;
regulatory = mvm->trans->cfg->nvm_type == IWL_NVM_SDP ?
(const __le16 *)sections[NVM_SECTION_TYPE_REGULATORY_SDP].data :
(const __le16 *)sections[NVM_SECTION_TYPE_REGULATORY].data;
return iwl_parse_nvm_data(mvm->trans, mvm->cfg, mvm->fw, hw, sw, calib,
regulatory, mac_override, phy_sku,
mvm->fw->valid_tx_ant, mvm->fw->valid_rx_ant);
}
/* Loads the NVM data stored in mvm->nvm_sections into the NIC */
int iwl_mvm_load_nvm_to_nic(struct iwl_mvm *mvm)
{
int i, ret = 0;
struct iwl_nvm_section *sections = mvm->nvm_sections;
IWL_DEBUG_EEPROM(mvm->trans->dev, "'Write to NVM\n");
for (i = 0; i < ARRAY_SIZE(mvm->nvm_sections); i++) {
if (!mvm->nvm_sections[i].data || !mvm->nvm_sections[i].length)
continue;
ret = iwl_nvm_write_section(mvm, i, sections[i].data,
sections[i].length);
if (ret < 0) {
IWL_ERR(mvm, "iwl_mvm_send_cmd failed: %d\n", ret);
break;
}
}
return ret;
}
int iwl_nvm_init(struct iwl_mvm *mvm)
{
int ret, section;
u32 size_read = 0;
u8 *nvm_buffer, *temp;
const char *nvm_file_C = mvm->cfg->default_nvm_file_C_step;
if (WARN_ON_ONCE(mvm->cfg->nvm_hw_section_num >= NVM_MAX_NUM_SECTIONS))
return -EINVAL;
/* load NVM values from nic */
/* Read From FW NVM */
IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from NVM\n");
nvm_buffer = kmalloc(mvm->trans->trans_cfg->base_params->eeprom_size,
GFP_KERNEL);
if (!nvm_buffer)
return -ENOMEM;
for (section = 0; section < NVM_MAX_NUM_SECTIONS; section++) {
/* we override the constness for initial read */
ret = iwl_nvm_read_section(mvm, section, nvm_buffer,
size_read);
if (ret == -ENODATA) {
ret = 0;
continue;
}
if (ret < 0)
break;
size_read += ret;
temp = kmemdup(nvm_buffer, ret, GFP_KERNEL);
if (!temp) {
ret = -ENOMEM;
break;
}
iwl_nvm_fixups(mvm->trans->hw_id, section, temp, ret);
mvm->nvm_sections[section].data = temp;
mvm->nvm_sections[section].length = ret;
#ifdef CONFIG_IWLWIFI_DEBUGFS
switch (section) {
case NVM_SECTION_TYPE_SW:
mvm->nvm_sw_blob.data = temp;
mvm->nvm_sw_blob.size = ret;
break;
case NVM_SECTION_TYPE_CALIBRATION:
mvm->nvm_calib_blob.data = temp;
mvm->nvm_calib_blob.size = ret;
break;
case NVM_SECTION_TYPE_PRODUCTION:
mvm->nvm_prod_blob.data = temp;
mvm->nvm_prod_blob.size = ret;
break;
case NVM_SECTION_TYPE_PHY_SKU:
mvm->nvm_phy_sku_blob.data = temp;
mvm->nvm_phy_sku_blob.size = ret;
break;
case NVM_SECTION_TYPE_REGULATORY_SDP:
case NVM_SECTION_TYPE_REGULATORY:
mvm->nvm_reg_blob.data = temp;
mvm->nvm_reg_blob.size = ret;
break;
default:
if (section == mvm->cfg->nvm_hw_section_num) {
mvm->nvm_hw_blob.data = temp;
mvm->nvm_hw_blob.size = ret;
break;
}
}
#endif
}
if (!size_read)
IWL_ERR(mvm, "OTP is blank\n");
kfree(nvm_buffer);
/* Only if PNVM selected in the mod param - load external NVM */
if (mvm->nvm_file_name) {
/* read External NVM file from the mod param */
ret = iwl_read_external_nvm(mvm->trans, mvm->nvm_file_name,
mvm->nvm_sections);
if (ret) {
mvm->nvm_file_name = nvm_file_C;
if ((ret == -EFAULT || ret == -ENOENT) &&
mvm->nvm_file_name) {
/* in case nvm file was failed try again */
ret = iwl_read_external_nvm(mvm->trans,
mvm->nvm_file_name,
mvm->nvm_sections);
if (ret)
return ret;
} else {
return ret;
}
}
}
/* parse the relevant nvm sections */
mvm->nvm_data = iwl_parse_nvm_sections(mvm);
if (!mvm->nvm_data)
return -ENODATA;
IWL_DEBUG_EEPROM(mvm->trans->dev, "nvm version = %x\n",
mvm->nvm_data->nvm_version);
return ret < 0 ? ret : 0;
}
struct iwl_mcc_update_resp *
iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2,
enum iwl_mcc_source src_id)
{
struct iwl_mcc_update_cmd mcc_update_cmd = {
.mcc = cpu_to_le16(alpha2[0] << 8 | alpha2[1]),
.source_id = (u8)src_id,
};
struct iwl_mcc_update_resp *resp_cp;
struct iwl_rx_packet *pkt;
struct iwl_host_cmd cmd = {
.id = MCC_UPDATE_CMD,
.flags = CMD_WANT_SKB | CMD_SEND_IN_RFKILL,
.data = { &mcc_update_cmd },
};
int ret;
u32 status;
int resp_len, n_channels;
u16 mcc;
if (WARN_ON_ONCE(!iwl_mvm_is_lar_supported(mvm)))
return ERR_PTR(-EOPNOTSUPP);
cmd.len[0] = sizeof(struct iwl_mcc_update_cmd);
IWL_DEBUG_LAR(mvm, "send MCC update to FW with '%c%c' src = %d\n",
alpha2[0], alpha2[1], src_id);
ret = iwl_mvm_send_cmd(mvm, &cmd);
if (ret)
return ERR_PTR(ret);
pkt = cmd.resp_pkt;
/* Extract MCC response */
if (fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_MCC_UPDATE_11AX_SUPPORT)) {
struct iwl_mcc_update_resp *mcc_resp = (void *)pkt->data;
n_channels = __le32_to_cpu(mcc_resp->n_channels);
resp_len = sizeof(struct iwl_mcc_update_resp) +
n_channels * sizeof(__le32);
resp_cp = kmemdup(mcc_resp, resp_len, GFP_KERNEL);
if (!resp_cp) {
resp_cp = ERR_PTR(-ENOMEM);
goto exit;
}
} else {
struct iwl_mcc_update_resp_v3 *mcc_resp_v3 = (void *)pkt->data;
n_channels = __le32_to_cpu(mcc_resp_v3->n_channels);
resp_len = sizeof(struct iwl_mcc_update_resp) +
n_channels * sizeof(__le32);
resp_cp = kzalloc(resp_len, GFP_KERNEL);
if (!resp_cp) {
resp_cp = ERR_PTR(-ENOMEM);
goto exit;
}
resp_cp->status = mcc_resp_v3->status;
resp_cp->mcc = mcc_resp_v3->mcc;
resp_cp->cap = cpu_to_le16(mcc_resp_v3->cap);
resp_cp->source_id = mcc_resp_v3->source_id;
resp_cp->time = mcc_resp_v3->time;
resp_cp->geo_info = mcc_resp_v3->geo_info;
resp_cp->n_channels = mcc_resp_v3->n_channels;
memcpy(resp_cp->channels, mcc_resp_v3->channels,
n_channels * sizeof(__le32));
}
status = le32_to_cpu(resp_cp->status);
mcc = le16_to_cpu(resp_cp->mcc);
/* W/A for a FW/NVM issue - returns 0x00 for the world domain */
if (mcc == 0) {
mcc = 0x3030; /* "00" - world */
resp_cp->mcc = cpu_to_le16(mcc);
}
IWL_DEBUG_LAR(mvm,
"MCC response status: 0x%x. new MCC: 0x%x ('%c%c') n_chans: %d\n",
status, mcc, mcc >> 8, mcc & 0xff, n_channels);
exit:
iwl_free_resp(&cmd);
return resp_cp;
}
int iwl_mvm_init_mcc(struct iwl_mvm *mvm)
{
bool tlv_lar;
bool nvm_lar;
int retval;
struct ieee80211_regdomain *regd;
char mcc[3];
if (mvm->cfg->nvm_type == IWL_NVM_EXT) {
tlv_lar = fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_LAR_SUPPORT);
nvm_lar = mvm->nvm_data->lar_enabled;
if (tlv_lar != nvm_lar)
IWL_INFO(mvm,
"Conflict between TLV & NVM regarding enabling LAR (TLV = %s NVM =%s)\n",
tlv_lar ? "enabled" : "disabled",
nvm_lar ? "enabled" : "disabled");
}
if (!iwl_mvm_is_lar_supported(mvm))
return 0;
/*
* try to replay the last set MCC to FW. If it doesn't exist,
* queue an update to cfg80211 to retrieve the default alpha2 from FW.
*/
retval = iwl_mvm_init_fw_regd(mvm);
if (retval != -ENOENT)
return retval;
/*
* Driver regulatory hint for initial update, this also informs the
* firmware we support wifi location updates.
* Disallow scans that might crash the FW while the LAR regdomain
* is not set.
*/
mvm->lar_regdom_set = false;
regd = iwl_mvm_get_current_regdomain(mvm, NULL);
if (IS_ERR_OR_NULL(regd))
return -EIO;
if (iwl_mvm_is_wifi_mcc_supported(mvm) &&
!iwl_acpi_get_mcc(mvm->dev, mcc)) {
kfree(regd);
regd = iwl_mvm_get_regdomain(mvm->hw->wiphy, mcc,
MCC_SOURCE_BIOS, NULL);
if (IS_ERR_OR_NULL(regd))
return -EIO;
}
retval = regulatory_set_wiphy_regd_sync(mvm->hw->wiphy, regd);
kfree(regd);
return retval;
}
void iwl_mvm_rx_chub_update_mcc(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
struct iwl_mcc_chub_notif *notif = (void *)pkt->data;
enum iwl_mcc_source src;
char mcc[3];
struct ieee80211_regdomain *regd;
int wgds_tbl_idx;
lockdep_assert_held(&mvm->mutex);
if (iwl_mvm_is_vif_assoc(mvm) && notif->source_id == MCC_SOURCE_WIFI) {
IWL_DEBUG_LAR(mvm, "Ignore mcc update while associated\n");
return;
}
if (WARN_ON_ONCE(!iwl_mvm_is_lar_supported(mvm)))
return;
mcc[0] = le16_to_cpu(notif->mcc) >> 8;
mcc[1] = le16_to_cpu(notif->mcc) & 0xff;
mcc[2] = '\0';
src = notif->source_id;
IWL_DEBUG_LAR(mvm,
"RX: received chub update mcc cmd (mcc '%s' src %d)\n",
mcc, src);
regd = iwl_mvm_get_regdomain(mvm->hw->wiphy, mcc, src, NULL);
if (IS_ERR_OR_NULL(regd))
return;
wgds_tbl_idx = iwl_mvm_get_sar_geo_profile(mvm);
if (wgds_tbl_idx < 1)
IWL_DEBUG_INFO(mvm,
"SAR WGDS is disabled or error received (%d)\n",
wgds_tbl_idx);
else
IWL_DEBUG_INFO(mvm, "SAR WGDS: geo profile %d is configured\n",
wgds_tbl_idx);
regulatory_set_wiphy_regd(mvm->hw->wiphy, regd);
kfree(regd);
}

Some files were not shown because too many files have changed in this diff Show More