Commit 7c530588 authored by Miri Korenblit's avatar Miri Korenblit Committed by Luca Coelho

iwlwifi: mvm: support revision 1 of WTAS table

A new revision of WTAS was added in order to support
IEC optimisation. Add support for reading the new revision from ACPI and
passing it to the FW.
Signed-off-by: default avatarMiri Korenblit <miriam.rachel.korenblit@intel.com>
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
Link: https://lore.kernel.org/r/iwlwifi.20211210090244.ff455b9d66bd.Ic7c1460e89f6b22101f3c5a2ea438031c7f11771@changeidSigned-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
parent f1c0bb74
...@@ -242,17 +242,16 @@ union acpi_object *iwl_acpi_get_wifi_pkg_range(struct device *dev, ...@@ -242,17 +242,16 @@ union acpi_object *iwl_acpi_get_wifi_pkg_range(struct device *dev,
IWL_EXPORT_SYMBOL(iwl_acpi_get_wifi_pkg_range); IWL_EXPORT_SYMBOL(iwl_acpi_get_wifi_pkg_range);
int iwl_acpi_get_tas(struct iwl_fw_runtime *fwrt, int iwl_acpi_get_tas(struct iwl_fw_runtime *fwrt,
__le32 *block_list_array, struct iwl_tas_config_cmd_v3 *cmd)
int *block_list_size)
{ {
union acpi_object *wifi_pkg, *data; union acpi_object *wifi_pkg, *data;
int ret, tbl_rev, i; int ret, tbl_rev, i, block_list_size, enabled;
bool enabled;
data = iwl_acpi_get_object(fwrt->dev, ACPI_WTAS_METHOD); data = iwl_acpi_get_object(fwrt->dev, ACPI_WTAS_METHOD);
if (IS_ERR(data)) if (IS_ERR(data))
return PTR_ERR(data); return PTR_ERR(data);
/* try to read wtas table revision 1 or revision 0*/
wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data, wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
ACPI_WTAS_WIFI_DATA_SIZE, ACPI_WTAS_WIFI_DATA_SIZE,
&tbl_rev); &tbl_rev);
...@@ -261,40 +260,54 @@ int iwl_acpi_get_tas(struct iwl_fw_runtime *fwrt, ...@@ -261,40 +260,54 @@ int iwl_acpi_get_tas(struct iwl_fw_runtime *fwrt,
goto out_free; goto out_free;
} }
if (wifi_pkg->package.elements[0].type != ACPI_TYPE_INTEGER || if (tbl_rev == 1 && wifi_pkg->package.elements[1].type ==
tbl_rev != 0) { ACPI_TYPE_INTEGER) {
u32 tas_selection =
(u32)wifi_pkg->package.elements[1].integer.value;
u16 override_iec =
(tas_selection & ACPI_WTAS_OVERRIDE_IEC_MSK) >> ACPI_WTAS_OVERRIDE_IEC_POS;
u16 enabled_iec = (tas_selection & ACPI_WTAS_ENABLE_IEC_MSK) >>
ACPI_WTAS_ENABLE_IEC_POS;
enabled = tas_selection & ACPI_WTAS_ENABLED_MSK;
cmd->override_tas_iec = cpu_to_le16(override_iec);
cmd->enable_tas_iec = cpu_to_le16(enabled_iec);
} else if (tbl_rev == 0 &&
wifi_pkg->package.elements[1].type == ACPI_TYPE_INTEGER) {
enabled = !!wifi_pkg->package.elements[1].integer.value;
} else {
ret = -EINVAL; ret = -EINVAL;
goto out_free; goto out_free;
} }
enabled = !!wifi_pkg->package.elements[1].integer.value;
if (!enabled) { if (!enabled) {
*block_list_size = -1;
IWL_DEBUG_RADIO(fwrt, "TAS not enabled\n"); IWL_DEBUG_RADIO(fwrt, "TAS not enabled\n");
ret = 0; ret = 0;
goto out_free; goto out_free;
} }
IWL_DEBUG_RADIO(fwrt, "Reading TAS table revision %d\n", tbl_rev);
if (wifi_pkg->package.elements[2].type != ACPI_TYPE_INTEGER || if (wifi_pkg->package.elements[2].type != ACPI_TYPE_INTEGER ||
wifi_pkg->package.elements[2].integer.value > wifi_pkg->package.elements[2].integer.value >
APCI_WTAS_BLACK_LIST_MAX) { APCI_WTAS_BLACK_LIST_MAX) {
IWL_DEBUG_RADIO(fwrt, "TAS invalid array size %llu\n", IWL_DEBUG_RADIO(fwrt, "TAS invalid array size %llu\n",
wifi_pkg->package.elements[1].integer.value); wifi_pkg->package.elements[2].integer.value);
ret = -EINVAL; ret = -EINVAL;
goto out_free; goto out_free;
} }
*block_list_size = wifi_pkg->package.elements[2].integer.value; block_list_size = wifi_pkg->package.elements[2].integer.value;
cmd->block_list_size = cpu_to_le32(block_list_size);
IWL_DEBUG_RADIO(fwrt, "TAS array size %d\n", *block_list_size); IWL_DEBUG_RADIO(fwrt, "TAS array size %u\n", block_list_size);
if (*block_list_size > APCI_WTAS_BLACK_LIST_MAX) { if (block_list_size > APCI_WTAS_BLACK_LIST_MAX) {
IWL_DEBUG_RADIO(fwrt, "TAS invalid array size value %u\n", IWL_DEBUG_RADIO(fwrt, "TAS invalid array size value %u\n",
*block_list_size); block_list_size);
ret = -EINVAL; ret = -EINVAL;
goto out_free; goto out_free;
} }
for (i = 0; i < *block_list_size; i++) { for (i = 0; i < block_list_size; i++) {
u32 country; u32 country;
if (wifi_pkg->package.elements[3 + i].type != if (wifi_pkg->package.elements[3 + i].type !=
...@@ -306,11 +319,11 @@ int iwl_acpi_get_tas(struct iwl_fw_runtime *fwrt, ...@@ -306,11 +319,11 @@ int iwl_acpi_get_tas(struct iwl_fw_runtime *fwrt,
} }
country = wifi_pkg->package.elements[3 + i].integer.value; country = wifi_pkg->package.elements[3 + i].integer.value;
block_list_array[i] = cpu_to_le32(country); cmd->block_list_array[i] = cpu_to_le32(country);
IWL_DEBUG_RADIO(fwrt, "TAS block list country %d\n", country); IWL_DEBUG_RADIO(fwrt, "TAS block list country %d\n", country);
} }
ret = 0; ret = 1;
out_free: out_free:
kfree(data); kfree(data);
return ret; return ret;
......
...@@ -65,10 +65,19 @@ ...@@ -65,10 +65,19 @@
#define ACPI_ECKV_WIFI_DATA_SIZE 2 #define ACPI_ECKV_WIFI_DATA_SIZE 2
/* /*
* 1 type, 1 enabled, 1 block list size, 16 block list array * TAS size: 1 elelment for type,
* 1 element for enabled field,
* 1 element for block list size,
* 16 elements for block list array
*/ */
#define APCI_WTAS_BLACK_LIST_MAX 16 #define APCI_WTAS_BLACK_LIST_MAX 16
#define ACPI_WTAS_WIFI_DATA_SIZE (3 + APCI_WTAS_BLACK_LIST_MAX) #define ACPI_WTAS_WIFI_DATA_SIZE (3 + APCI_WTAS_BLACK_LIST_MAX)
#define ACPI_WTAS_ENABLED_MSK 0x1
#define ACPI_WTAS_OVERRIDE_IEC_MSK 0x2
#define ACPI_WTAS_ENABLE_IEC_MSK 0x4
#define ACPI_WTAS_OVERRIDE_IEC_POS 0x1
#define ACPI_WTAS_ENABLE_IEC_POS 0x2
#define ACPI_PPAG_WIFI_DATA_SIZE_V1 ((IWL_NUM_CHAIN_LIMITS * \ #define ACPI_PPAG_WIFI_DATA_SIZE_V1 ((IWL_NUM_CHAIN_LIMITS * \
IWL_NUM_SUB_BANDS_V1) + 2) IWL_NUM_SUB_BANDS_V1) + 2)
...@@ -198,8 +207,8 @@ int iwl_sar_geo_init(struct iwl_fw_runtime *fwrt, ...@@ -198,8 +207,8 @@ int iwl_sar_geo_init(struct iwl_fw_runtime *fwrt,
struct iwl_per_chain_offset *table, struct iwl_per_chain_offset *table,
u32 n_bands, u32 n_profiles); u32 n_bands, u32 n_profiles);
int iwl_acpi_get_tas(struct iwl_fw_runtime *fwrt, __le32 *block_list_array, int iwl_acpi_get_tas(struct iwl_fw_runtime *fwrt,
int *block_list_size); struct iwl_tas_config_cmd_v3 *cmd);
__le32 iwl_acpi_get_lari_config_bitmap(struct iwl_fw_runtime *fwrt); __le32 iwl_acpi_get_lari_config_bitmap(struct iwl_fw_runtime *fwrt);
...@@ -280,8 +289,7 @@ static inline bool iwl_sar_geo_support(struct iwl_fw_runtime *fwrt) ...@@ -280,8 +289,7 @@ static inline bool iwl_sar_geo_support(struct iwl_fw_runtime *fwrt)
} }
static inline int iwl_acpi_get_tas(struct iwl_fw_runtime *fwrt, static inline int iwl_acpi_get_tas(struct iwl_fw_runtime *fwrt,
__le32 *block_list_array, struct iwl_tas_config_cmd_v3 *cmd)
int *block_list_size)
{ {
return -ENOENT; return -ENOENT;
} }
......
...@@ -393,17 +393,32 @@ enum iwl_mcc_source { ...@@ -393,17 +393,32 @@ enum iwl_mcc_source {
MCC_SOURCE_GETTING_MCC_TEST_MODE = 0x11, MCC_SOURCE_GETTING_MCC_TEST_MODE = 0x11,
}; };
#define IWL_TAS_BLACK_LIST_MAX 16 #define IWL_TAS_BLOCK_LIST_MAX 16
/** /**
* struct iwl_tas_config_cmd - configures the TAS * struct iwl_tas_config_cmd_v2 - configures the TAS
* @block_list_size: size of relevant field in block_list_array * @block_list_size: size of relevant field in block_list_array
* @block_list_array: block list countries (without TAS) * @block_list_array: list of countries where TAS must be disabled
*/ */
struct iwl_tas_config_cmd { struct iwl_tas_config_cmd_v2 {
__le32 block_list_size; __le32 block_list_size;
__le32 block_list_array[IWL_TAS_BLACK_LIST_MAX]; __le32 block_list_array[IWL_TAS_BLOCK_LIST_MAX];
} __packed; /* TAS_CONFIG_CMD_API_S_VER_2 */ } __packed; /* TAS_CONFIG_CMD_API_S_VER_2 */
/**
* struct iwl_tas_config_cmd_v3 - configures the TAS
* @block_list_size: size of relevant field in block_list_array
* @block_list_array: list of countries where TAS must be disabled
* @override_tas_iec: indicates whether to override default value of IEC regulatory
* @enable_tas_iec: in case override_tas_iec is set -
* indicates whether IEC regulatory is enabled or disabled
*/
struct iwl_tas_config_cmd_v3 {
__le32 block_list_size;
__le32 block_list_array[IWL_TAS_BLOCK_LIST_MAX];
__le16 override_tas_iec;
__le16 enable_tas_iec;
} __packed; /* TAS_CONFIG_CMD_API_S_VER_3 */
/** /**
* enum iwl_lari_configs - bit masks for the various LARI config operations * enum iwl_lari_configs - bit masks for the various LARI config operations
* @LARI_CONFIG_DISABLE_11AC_UKRAINE_MSK: disable 11ac in ukraine * @LARI_CONFIG_DISABLE_11AC_UKRAINE_MSK: disable 11ac in ukraine
......
...@@ -1156,8 +1156,8 @@ static int iwl_mvm_ppag_init(struct iwl_mvm *mvm) ...@@ -1156,8 +1156,8 @@ static int iwl_mvm_ppag_init(struct iwl_mvm *mvm)
static void iwl_mvm_tas_init(struct iwl_mvm *mvm) static void iwl_mvm_tas_init(struct iwl_mvm *mvm)
{ {
int ret; int ret;
struct iwl_tas_config_cmd cmd = {}; struct iwl_tas_config_cmd_v3 cmd = {};
int list_size; int cmd_size;
BUILD_BUG_ON(ARRAY_SIZE(cmd.block_list_array) < BUILD_BUG_ON(ARRAY_SIZE(cmd.block_list_array) <
APCI_WTAS_BLACK_LIST_MAX); APCI_WTAS_BLACK_LIST_MAX);
...@@ -1167,7 +1167,7 @@ static void iwl_mvm_tas_init(struct iwl_mvm *mvm) ...@@ -1167,7 +1167,7 @@ static void iwl_mvm_tas_init(struct iwl_mvm *mvm)
return; return;
} }
ret = iwl_acpi_get_tas(&mvm->fwrt, cmd.block_list_array, &list_size); ret = iwl_acpi_get_tas(&mvm->fwrt, &cmd);
if (ret < 0) { if (ret < 0) {
IWL_DEBUG_RADIO(mvm, IWL_DEBUG_RADIO(mvm,
"TAS table invalid or unavailable. (%d)\n", "TAS table invalid or unavailable. (%d)\n",
...@@ -1175,15 +1175,18 @@ static void iwl_mvm_tas_init(struct iwl_mvm *mvm) ...@@ -1175,15 +1175,18 @@ static void iwl_mvm_tas_init(struct iwl_mvm *mvm)
return; return;
} }
if (list_size < 0) if (ret == 0)
return; return;
/* list size if TAS enabled can only be non-negative */ cmd_size = iwl_fw_lookup_cmd_ver(mvm->fw, REGULATORY_AND_NVM_GROUP,
cmd.block_list_size = cpu_to_le32((u32)list_size); TAS_CONFIG,
IWL_FW_CMD_VER_UNKNOWN) < 3 ?
sizeof(struct iwl_tas_config_cmd_v2) :
sizeof(struct iwl_tas_config_cmd_v3);
ret = iwl_mvm_send_cmd_pdu(mvm, WIDE_ID(REGULATORY_AND_NVM_GROUP, ret = iwl_mvm_send_cmd_pdu(mvm, WIDE_ID(REGULATORY_AND_NVM_GROUP,
TAS_CONFIG), TAS_CONFIG),
0, sizeof(cmd), &cmd); 0, cmd_size, &cmd);
if (ret < 0) if (ret < 0)
IWL_DEBUG_RADIO(mvm, "failed to send TAS_CONFIG (%d)\n", ret); IWL_DEBUG_RADIO(mvm, "failed to send TAS_CONFIG (%d)\n", ret);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment