summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/22000.c76
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/9000.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/dvm/main.c4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/dvm/rx.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/acpi.c304
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/acpi.h66
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/coex.h2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/commands.h3
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/d3.h22
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h8
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/location.h189
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/mac.h4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/offload.h31
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/scan.h6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/sta.h8
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/dbg.c144
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/dbg.h7
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/error-dump.h22
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/file.h1
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/pnvm.c15
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/pnvm.h20
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-config.h8
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-csr.h22
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c34
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.h24
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-drv.c4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-io.c26
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c40
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-op-mode.h8
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-prph.h7
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-trans.h6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/constants.h5
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/d3.c580
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c11
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c85
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c27
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw.c108
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c44
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c35
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mvm.h3
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/nvm.c4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ops.c74
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rfi.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c45
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/scan.c93
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/sta.c120
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/time-event.c41
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/drv.c8
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/internal.h24
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/rx.c17
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c53
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/trans.c49
52 files changed, 1850 insertions, 693 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c
index 7f1faa9d97b4..52d1d391f4c6 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c
@@ -9,7 +9,7 @@
#include "iwl-prph.h"
/* Highest firmware API version supported */
-#define IWL_22000_UCODE_API_MAX 64
+#define IWL_22000_UCODE_API_MAX 65
/* Lowest firmware API version supported */
#define IWL_22000_UCODE_API_MIN 39
@@ -154,7 +154,7 @@ static const struct iwl_ht_params iwl_22000_ht_params = {
.apmg_not_supported = true, \
.trans.mq_rx_supported = true, \
.vht_mu_mimo_supported = true, \
- .mac_addr_from_csr = true, \
+ .mac_addr_from_csr = 0x380, \
.ht_params = &iwl_22000_ht_params, \
.nvm_ver = IWL_22000_NVM_VERSION, \
.trans.use_tfh = true, \
@@ -215,6 +215,67 @@ static const struct iwl_ht_params iwl_22000_ht_params = {
}, \
}
+#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,
@@ -373,7 +434,7 @@ const struct iwl_cfg_trans_params iwl_ma_trans_cfg = {
};
const struct iwl_cfg_trans_params iwl_bz_trans_cfg = {
- .device_family = IWL_DEVICE_FAMILY_AX210,
+ .device_family = IWL_DEVICE_FAMILY_BZ,
.base_params = &iwl_ax210_base_params,
.mq_rx_supported = true,
.use_tfh = true,
@@ -394,6 +455,7 @@ 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)";
@@ -763,28 +825,28 @@ const struct iwl_cfg iwl_cfg_quz_a0_hr_b0 = {
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_AX210,
+ 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_AX210,
+ 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_AX210,
+ 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_AX210,
+ IWL_DEVICE_BZ,
.num_rbds = IWL_NUM_RBDS_AX210_HE,
};
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c
index 871533beff30..7a7ca06d46c1 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c
@@ -89,7 +89,7 @@ static const struct iwl_tt_params iwl9000_tt_params = {
.apmg_not_supported = true, \
.num_rbds = 512, \
.vht_mu_mimo_supported = true, \
- .mac_addr_from_csr = true, \
+ .mac_addr_from_csr = 0x380, \
.nvm_type = IWL_NVM_EXT, \
.dbgc_supported = true, \
.min_umac_error_event_table = 0x800000, \
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/main.c b/drivers/net/wireless/intel/iwlwifi/dvm/main.c
index c01523f64bfc..cc7b69fd14d3 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/main.c
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/main.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/******************************************************************************
*
- * Copyright(c) 2003 - 2014, 2018 - 2020 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2014, 2018 - 2021 Intel Corporation. All rights reserved.
* Copyright(c) 2015 Intel Deutschland GmbH
*
* Portions of this file are derived from the ipw3945 project, as well
@@ -1950,7 +1950,7 @@ static void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
}
}
-static void iwl_nic_error(struct iwl_op_mode *op_mode)
+static void iwl_nic_error(struct iwl_op_mode *op_mode, bool sync)
{
struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/rx.c b/drivers/net/wireless/intel/iwlwifi/dvm/rx.c
index 80475c7a6fba..3cd7b423c588 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/rx.c
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/rx.c
@@ -318,7 +318,7 @@ iwlagn_accumulative_statistics(struct iwl_priv *priv,
(__le32 *)&priv->delta_stats._name, \
(__le32 *)&priv->max_delta_stats._name, \
(__le32 *)&priv->accum_stats._name, \
- sizeof(*_name));
+ sizeof(*_name))
ACCUM(common);
ACCUM(rx_non_phy);
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c
index 34933f133a0a..1efac0b2a94d 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c
@@ -264,7 +264,7 @@ int iwl_acpi_get_tas(struct iwl_fw_runtime *fwrt,
goto out_free;
}
- enabled = !!wifi_pkg->package.elements[0].integer.value;
+ enabled = !!wifi_pkg->package.elements[1].integer.value;
if (!enabled) {
*block_list_size = -1;
@@ -273,15 +273,15 @@ int iwl_acpi_get_tas(struct iwl_fw_runtime *fwrt,
goto out_free;
}
- if (wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER ||
- wifi_pkg->package.elements[1].integer.value >
+ if (wifi_pkg->package.elements[2].type != ACPI_TYPE_INTEGER ||
+ wifi_pkg->package.elements[2].integer.value >
APCI_WTAS_BLACK_LIST_MAX) {
IWL_DEBUG_RADIO(fwrt, "TAS invalid array size %llu\n",
wifi_pkg->package.elements[1].integer.value);
ret = -EINVAL;
goto out_free;
}
- *block_list_size = wifi_pkg->package.elements[1].integer.value;
+ *block_list_size = wifi_pkg->package.elements[2].integer.value;
IWL_DEBUG_RADIO(fwrt, "TAS array size %d\n", *block_list_size);
if (*block_list_size > APCI_WTAS_BLACK_LIST_MAX) {
@@ -294,15 +294,15 @@ int iwl_acpi_get_tas(struct iwl_fw_runtime *fwrt,
for (i = 0; i < *block_list_size; i++) {
u32 country;
- if (wifi_pkg->package.elements[2 + i].type !=
+ if (wifi_pkg->package.elements[3 + i].type !=
ACPI_TYPE_INTEGER) {
IWL_DEBUG_RADIO(fwrt,
- "TAS invalid array elem %d\n", 2 + i);
+ "TAS invalid array elem %d\n", 3 + i);
ret = -EINVAL;
goto out_free;
}
- country = wifi_pkg->package.elements[2 + i].integer.value;
+ country = wifi_pkg->package.elements[3 + i].integer.value;
block_list_array[i] = cpu_to_le32(country);
IWL_DEBUG_RADIO(fwrt, "TAS block list country %d\n", country);
}
@@ -412,20 +412,35 @@ IWL_EXPORT_SYMBOL(iwl_acpi_get_eckv);
static int iwl_sar_set_profile(union acpi_object *table,
struct iwl_sar_profile *profile,
- bool enabled)
+ bool enabled, u8 num_chains, u8 num_sub_bands)
{
- int i;
-
- profile->enabled = enabled;
-
- for (i = 0; i < ACPI_SAR_TABLE_SIZE; i++) {
- if (table[i].type != ACPI_TYPE_INTEGER ||
- table[i].integer.value > U8_MAX)
- return -EINVAL;
+ int i, j, idx = 0;
- profile->table[i] = table[i].integer.value;
+ /*
+ * The table from ACPI is flat, but we store it in a
+ * structured array.
+ */
+ for (i = 0; i < ACPI_SAR_NUM_CHAINS_REV2; i++) {
+ for (j = 0; j < ACPI_SAR_NUM_SUB_BANDS_REV2; j++) {
+ /* if we don't have the values, use the default */
+ if (i >= num_chains || j >= num_sub_bands) {
+ profile->chains[i].subbands[j] = 0;
+ } else {
+ if (table[idx].type != ACPI_TYPE_INTEGER ||
+ table[idx].integer.value > U8_MAX)
+ return -EINVAL;
+
+ profile->chains[i].subbands[j] =
+ table[idx].integer.value;
+
+ idx++;
+ }
+ }
}
+ /* Only if all values were valid can the profile be enabled */
+ profile->enabled = enabled;
+
return 0;
}
@@ -433,10 +448,10 @@ static int iwl_sar_fill_table(struct iwl_fw_runtime *fwrt,
__le16 *per_chain, u32 n_subbands,
int prof_a, int prof_b)
{
- int profs[ACPI_SAR_NUM_CHAIN_LIMITS] = { prof_a, prof_b };
- int i, j, idx;
+ int profs[ACPI_SAR_NUM_CHAINS_REV0] = { prof_a, prof_b };
+ int i, j;
- for (i = 0; i < ACPI_SAR_NUM_CHAIN_LIMITS; i++) {
+ for (i = 0; i < ACPI_SAR_NUM_CHAINS_REV0; i++) {
struct iwl_sar_profile *prof;
/* don't allow SAR to be disabled (profile 0 means disable) */
@@ -467,11 +482,10 @@ static int iwl_sar_fill_table(struct iwl_fw_runtime *fwrt,
i, profs[i]);
IWL_DEBUG_RADIO(fwrt, " Chain[%d]:\n", i);
for (j = 0; j < n_subbands; j++) {
- idx = i * ACPI_SAR_NUM_SUB_BANDS + j;
per_chain[i * n_subbands + j] =
- cpu_to_le16(prof->table[idx]);
+ cpu_to_le16(prof->chains[i].subbands[j]);
IWL_DEBUG_RADIO(fwrt, " Band[%d] = %d * .125dBm\n",
- j, prof->table[idx]);
+ j, prof->chains[i].subbands[j]);
}
}
@@ -486,7 +500,7 @@ int iwl_sar_select_profile(struct iwl_fw_runtime *fwrt,
for (i = 0; i < n_tables; i++) {
ret = iwl_sar_fill_table(fwrt,
- &per_chain[i * n_subbands * ACPI_SAR_NUM_CHAIN_LIMITS],
+ &per_chain[i * n_subbands * ACPI_SAR_NUM_CHAINS_REV0],
n_subbands, prof_a, prof_b);
if (ret)
break;
@@ -501,28 +515,71 @@ int iwl_sar_get_wrds_table(struct iwl_fw_runtime *fwrt)
union acpi_object *wifi_pkg, *table, *data;
bool enabled;
int ret, tbl_rev;
+ u8 num_chains, num_sub_bands;
data = iwl_acpi_get_object(fwrt->dev, ACPI_WRDS_METHOD);
if (IS_ERR(data))
return PTR_ERR(data);
+ /* start by trying to read revision 2 */
wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
- ACPI_WRDS_WIFI_DATA_SIZE, &tbl_rev);
- if (IS_ERR(wifi_pkg)) {
- ret = PTR_ERR(wifi_pkg);
- goto out_free;
+ ACPI_WRDS_WIFI_DATA_SIZE_REV2,
+ &tbl_rev);
+ if (!IS_ERR(wifi_pkg)) {
+ if (tbl_rev != 2) {
+ ret = PTR_ERR(wifi_pkg);
+ goto out_free;
+ }
+
+ num_chains = ACPI_SAR_NUM_CHAINS_REV2;
+ num_sub_bands = ACPI_SAR_NUM_SUB_BANDS_REV2;
+
+ goto read_table;
}
- if (tbl_rev != 0) {
- ret = -EINVAL;
- goto out_free;
+ /* then try revision 1 */
+ wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
+ ACPI_WRDS_WIFI_DATA_SIZE_REV1,
+ &tbl_rev);
+ if (!IS_ERR(wifi_pkg)) {
+ if (tbl_rev != 1) {
+ ret = PTR_ERR(wifi_pkg);
+ goto out_free;
+ }
+
+ num_chains = ACPI_SAR_NUM_CHAINS_REV1;
+ num_sub_bands = ACPI_SAR_NUM_SUB_BANDS_REV1;
+
+ goto read_table;
+ }
+
+ /* then finally revision 0 */
+ wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
+ ACPI_WRDS_WIFI_DATA_SIZE_REV0,
+ &tbl_rev);
+ if (!IS_ERR(wifi_pkg)) {
+ if (tbl_rev != 0) {
+ ret = PTR_ERR(wifi_pkg);
+ goto out_free;
+ }
+
+ num_chains = ACPI_SAR_NUM_CHAINS_REV0;
+ num_sub_bands = ACPI_SAR_NUM_SUB_BANDS_REV0;
+
+ goto read_table;
}
+ ret = PTR_ERR(wifi_pkg);
+ goto out_free;
+
+read_table:
if (wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER) {
ret = -EINVAL;
goto out_free;
}
+ IWL_DEBUG_RADIO(fwrt, "Reading WRDS tbl_rev=%d\n", tbl_rev);
+
enabled = !!(wifi_pkg->package.elements[1].integer.value);
/* position of the actual table */
@@ -531,7 +588,8 @@ int iwl_sar_get_wrds_table(struct iwl_fw_runtime *fwrt)
/* The profile from WRDS is officially profile 1, but goes
* into sar_profiles[0] (because we don't have a profile 0).
*/
- ret = iwl_sar_set_profile(table, &fwrt->sar_profiles[0], enabled);
+ ret = iwl_sar_set_profile(table, &fwrt->sar_profiles[0], enabled,
+ num_chains, num_sub_bands);
out_free:
kfree(data);
return ret;
@@ -544,23 +602,64 @@ int iwl_sar_get_ewrd_table(struct iwl_fw_runtime *fwrt)
bool enabled;
int i, n_profiles, tbl_rev, pos;
int ret = 0;
+ u8 num_chains, num_sub_bands;
data = iwl_acpi_get_object(fwrt->dev, ACPI_EWRD_METHOD);
if (IS_ERR(data))
return PTR_ERR(data);
+ /* start by trying to read revision 2 */
wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
- ACPI_EWRD_WIFI_DATA_SIZE, &tbl_rev);
- if (IS_ERR(wifi_pkg)) {
- ret = PTR_ERR(wifi_pkg);
- goto out_free;
+ ACPI_EWRD_WIFI_DATA_SIZE_REV2,
+ &tbl_rev);
+ if (!IS_ERR(wifi_pkg)) {
+ if (tbl_rev != 2) {
+ ret = PTR_ERR(wifi_pkg);
+ goto out_free;
+ }
+
+ num_chains = ACPI_SAR_NUM_CHAINS_REV2;
+ num_sub_bands = ACPI_SAR_NUM_SUB_BANDS_REV2;
+
+ goto read_table;
}
- if (tbl_rev != 0) {
- ret = -EINVAL;
- goto out_free;
+ /* then try revision 1 */
+ wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
+ ACPI_EWRD_WIFI_DATA_SIZE_REV1,
+ &tbl_rev);
+ if (!IS_ERR(wifi_pkg)) {
+ if (tbl_rev != 1) {
+ ret = PTR_ERR(wifi_pkg);
+ goto out_free;
+ }
+
+ num_chains = ACPI_SAR_NUM_CHAINS_REV1;
+ num_sub_bands = ACPI_SAR_NUM_SUB_BANDS_REV1;
+
+ goto read_table;
+ }
+
+ /* then finally revision 0 */
+ wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
+ ACPI_EWRD_WIFI_DATA_SIZE_REV0,
+ &tbl_rev);
+ if (!IS_ERR(wifi_pkg)) {
+ if (tbl_rev != 0) {
+ ret = PTR_ERR(wifi_pkg);
+ goto out_free;
+ }
+
+ num_chains = ACPI_SAR_NUM_CHAINS_REV0;
+ num_sub_bands = ACPI_SAR_NUM_SUB_BANDS_REV0;
+
+ goto read_table;
}
+ ret = PTR_ERR(wifi_pkg);
+ goto out_free;
+
+read_table:
if (wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER ||
wifi_pkg->package.elements[2].type != ACPI_TYPE_INTEGER) {
ret = -EINVAL;
@@ -589,13 +688,13 @@ int iwl_sar_get_ewrd_table(struct iwl_fw_runtime *fwrt)
* have profile 0). So in the array we start from 1.
*/
ret = iwl_sar_set_profile(&wifi_pkg->package.elements[pos],
- &fwrt->sar_profiles[i + 1],
- enabled);
+ &fwrt->sar_profiles[i + 1], enabled,
+ num_chains, num_sub_bands);
if (ret < 0)
break;
/* go to the next table */
- pos += ACPI_SAR_TABLE_SIZE;
+ pos += num_chains * num_sub_bands;
}
out_free:
@@ -607,41 +706,93 @@ IWL_EXPORT_SYMBOL(iwl_sar_get_ewrd_table);
int iwl_sar_get_wgds_table(struct iwl_fw_runtime *fwrt)
{
union acpi_object *wifi_pkg, *data;
- int i, j, ret, tbl_rev;
- int idx = 1;
+ int i, j, k, ret, tbl_rev;
+ int idx = 1; /* start from one to skip the domain */
+ u8 num_bands;
data = iwl_acpi_get_object(fwrt->dev, ACPI_WGDS_METHOD);
if (IS_ERR(data))
return PTR_ERR(data);
+ /* start by trying to read revision 2 */
wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
- ACPI_WGDS_WIFI_DATA_SIZE, &tbl_rev);
+ ACPI_WGDS_WIFI_DATA_SIZE_REV2,
+ &tbl_rev);
+ if (!IS_ERR(wifi_pkg)) {
+ if (tbl_rev != 2) {
+ ret = PTR_ERR(wifi_pkg);
+ goto out_free;
+ }
- if (IS_ERR(wifi_pkg)) {
- ret = PTR_ERR(wifi_pkg);
- goto out_free;
+ num_bands = ACPI_GEO_NUM_BANDS_REV2;
+
+ goto read_table;
}
- if (tbl_rev > 1) {
- ret = -EINVAL;
- goto out_free;
+ /* then try revision 0 (which is the same as 1) */
+ wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
+ ACPI_WGDS_WIFI_DATA_SIZE_REV0,
+ &tbl_rev);
+ if (!IS_ERR(wifi_pkg)) {
+ if (tbl_rev != 0 && tbl_rev != 1) {
+ ret = PTR_ERR(wifi_pkg);
+ goto out_free;
+ }
+
+ num_bands = ACPI_GEO_NUM_BANDS_REV0;
+
+ goto read_table;
}
+ ret = PTR_ERR(wifi_pkg);
+ goto out_free;
+
+read_table:
fwrt->geo_rev = tbl_rev;
for (i = 0; i < ACPI_NUM_GEO_PROFILES; i++) {
- for (j = 0; j < ACPI_GEO_TABLE_SIZE; j++) {
+ for (j = 0; j < ACPI_GEO_NUM_BANDS_REV2; j++) {
union acpi_object *entry;
- entry = &wifi_pkg->package.elements[idx++];
- if (entry->type != ACPI_TYPE_INTEGER ||
- entry->integer.value > U8_MAX) {
- ret = -EINVAL;
- goto out_free;
+ /*
+ * num_bands is either 2 or 3, if it's only 2 then
+ * fill the third band (6 GHz) with the values from
+ * 5 GHz (second band)
+ */
+ if (j >= num_bands) {
+ fwrt->geo_profiles[i].bands[j].max =
+ fwrt->geo_profiles[i].bands[1].max;
+ } else {
+ entry = &wifi_pkg->package.elements[idx++];
+ if (entry->type != ACPI_TYPE_INTEGER ||
+ entry->integer.value > U8_MAX) {
+ ret = -EINVAL;
+ goto out_free;
+ }
+
+ fwrt->geo_profiles[i].bands[j].max =
+ entry->integer.value;
}
- fwrt->geo_profiles[i].values[j] = entry->integer.value;
+ for (k = 0; k < ACPI_GEO_NUM_CHAINS; k++) {
+ /* same here as above */
+ if (j >= num_bands) {
+ fwrt->geo_profiles[i].bands[j].chains[k] =
+ fwrt->geo_profiles[i].bands[1].chains[k];
+ } else {
+ entry = &wifi_pkg->package.elements[idx++];
+ if (entry->type != ACPI_TYPE_INTEGER ||
+ entry->integer.value > U8_MAX) {
+ ret = -EINVAL;
+ goto out_free;
+ }
+
+ fwrt->geo_profiles[i].bands[j].chains[k] =
+ entry->integer.value;
+ }
+ }
}
}
+
ret = 0;
out_free:
kfree(data);
@@ -673,43 +824,26 @@ IWL_EXPORT_SYMBOL(iwl_sar_geo_support);
int iwl_sar_geo_init(struct iwl_fw_runtime *fwrt,
struct iwl_per_chain_offset *table, u32 n_bands)
{
- int ret, i, j;
+ int i, j;
if (!iwl_sar_geo_support(fwrt))
return -EOPNOTSUPP;
- ret = iwl_sar_get_wgds_table(fwrt);
- if (ret < 0) {
- IWL_DEBUG_RADIO(fwrt,
- "Geo SAR BIOS table invalid or unavailable. (%d)\n",
- ret);
- /* we don't fail if the table is not available */
- return -ENOENT;
- }
-
for (i = 0; i < ACPI_NUM_GEO_PROFILES; i++) {
for (j = 0; j < n_bands; j++) {
struct iwl_per_chain_offset *chain =
&table[i * n_bands + j];
- u8 *value;
-
- if (j * ACPI_GEO_PER_CHAIN_SIZE >=
- ARRAY_SIZE(fwrt->geo_profiles[0].values))
- /*
- * Currently we only store lb an hb values, and
- * don't have any special ones for uhb. So leave
- * those empty for the time being
- */
- break;
-
- value = &fwrt->geo_profiles[i].values[j *
- ACPI_GEO_PER_CHAIN_SIZE];
- chain->max_tx_power = cpu_to_le16(value[0]);
- chain->chain_a = value[1];
- chain->chain_b = value[2];
+
+ chain->max_tx_power =
+ cpu_to_le16(fwrt->geo_profiles[i].bands[j].max);
+ chain->chain_a = fwrt->geo_profiles[i].bands[j].chains[0];
+ chain->chain_b = fwrt->geo_profiles[i].bands[j].chains[1];
IWL_DEBUG_RADIO(fwrt,
"SAR geographic profile[%d] Band[%d]: chain A = %d chain B = %d max_tx_power = %d\n",
- i, j, value[1], value[2], value[0]);
+ i, j,
+ fwrt->geo_profiles[i].bands[j].chains[0],
+ fwrt->geo_profiles[i].bands[j].chains[1],
+ fwrt->geo_profiles[i].bands[j].max);
}
}
diff --git a/d