Commit aee7c86a authored by Kalle Valo's avatar Kalle Valo
Browse files

Merge commit 'e257d969' of...

Merge commit 'e257d969' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next

I think last commits in tag iwlwifi-next-for-kalle-2021-08-26 are not
ready yet so I'm skipping those and pulling an earlier commit. I
modified Luca's description below to not include the skipped commits.

iwlwifi patches for v5.15

* Support scanning hidden 6GHz networks;
* Some improvements in the FW error dumps;
* Add some HE capability flags
* A bunch of janitorial clean-ups;
* Clean-ups in the TX code;
* Small fix for SMPS;
* Support for a new hardware family (Bz);
* Small fix in the scan code;
* A bunch of changes in the D3 code, including new FW API;
* Finalize the refactoring of 6GHz scan;
* Initial changes in the SAR profile code;
* Fix reading one of our ACPI tables (WTAS);
* Support some new ACPI table revisions;
* Support new API of the WoWlan status FW notification;
* Fixes in SAR ACPI tables handling;
* Some debugging improvements;
* Fix in ROC;
* Support for new FW API versions;
* Support new FW command versions;
* Some other small fixes, clean-ups and improvements.
parents a0929621 e257d969
Loading
Loading
Loading
Loading
+69 −7
Original line number Diff line number Diff line
@@ -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,
};

+1 −1
Original line number Diff line number Diff line
@@ -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,				\
+2 −2
Original line number Diff line number Diff line
// 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);

+1 −1
Original line number Diff line number Diff line
@@ -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);
+219 −85
Original line number Diff line number Diff line
@@ -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;
	int i, j, idx = 0;

	for (i = 0; i < ACPI_SAR_TABLE_SIZE; i++) {
		if (table[i].type != ACPI_TYPE_INTEGER ||
		    table[i].integer.value > U8_MAX)
	/*
	 * 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->table[i] = table[i].integer.value;
				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)) {
					 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;
	}

	/* 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 = -EINVAL;
			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)) {
					 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;
	}

	/* 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 = -EINVAL;
			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,31 +706,62 @@ 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);

	if (IS_ERR(wifi_pkg)) {
					 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 (tbl_rev > 1) {
		ret = -EINVAL;
		num_bands = ACPI_GEO_NUM_BANDS_REV2;

		goto read_table;
	}

	/* 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;

			/*
			 * 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) {
@@ -639,9 +769,30 @@ int iwl_sar_get_wgds_table(struct iwl_fw_runtime *fwrt)
					goto out_free;
				}

			fwrt->geo_profiles[i].values[j] = entry->integer.value;
				fwrt->geo_profiles[i].bands[j].max =
					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);
		}
	}

Loading