diff options
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/fw')
23 files changed, 458 insertions, 149 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c index 0bc32291815e..efa7b673ebc7 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c @@ -79,9 +79,9 @@ static void *iwl_acpi_get_object(struct device *dev, acpi_string method) * method (DSM) interface. The returned acpi object must be freed by calling * function. */ -static void *iwl_acpi_get_dsm_object(struct device *dev, int rev, int func, - union acpi_object *args, - const guid_t *guid) +union acpi_object *iwl_acpi_get_dsm_object(struct device *dev, int rev, + int func, union acpi_object *args, + const guid_t *guid) { union acpi_object *obj; @@ -108,7 +108,7 @@ static int iwl_acpi_get_dsm_integer(struct device *dev, int rev, int func, size_t expected_size) { union acpi_object *obj; - int ret = 0; + int ret; obj = iwl_acpi_get_dsm_object(dev, rev, func, NULL, guid); if (IS_ERR(obj)) { @@ -123,8 +123,10 @@ static int iwl_acpi_get_dsm_integer(struct device *dev, int rev, int func, } else if (obj->type == ACPI_TYPE_BUFFER) { __le64 le_value = 0; - if (WARN_ON_ONCE(expected_size > sizeof(le_value))) - return -EINVAL; + if (WARN_ON_ONCE(expected_size > sizeof(le_value))) { + ret = -EINVAL; + goto out; + } /* if the buffer size doesn't match the expected size */ if (obj->buffer.length != expected_size) @@ -145,8 +147,9 @@ static int iwl_acpi_get_dsm_integer(struct device *dev, int rev, int func, } IWL_DEBUG_DEV_RADIO(dev, - "ACPI: DSM method evaluated: func=%d, ret=%d\n", - func, ret); + "ACPI: DSM method evaluated: func=%d, value=%lld\n", + func, *value); + ret = 0; out: ACPI_FREE(obj); return ret; @@ -259,13 +262,14 @@ int iwl_acpi_get_tas_table(struct iwl_fw_runtime *fwrt, struct iwl_tas_data *tas_data) { union acpi_object *wifi_pkg, *data; - int ret, tbl_rev, i, block_list_size, enabled; + int ret, tbl_rev, block_list_size, enabled; + u32 tas_selection; data = iwl_acpi_get_object(fwrt->dev, ACPI_WTAS_METHOD); if (IS_ERR(data)) return PTR_ERR(data); - /* try to read wtas table revision 1 or revision 0*/ + /* try to read wtas table */ wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data, ACPI_WTAS_WIFI_DATA_SIZE, &tbl_rev); @@ -274,27 +278,23 @@ int iwl_acpi_get_tas_table(struct iwl_fw_runtime *fwrt, goto out_free; } - if (tbl_rev == 1 && wifi_pkg->package.elements[1].type == - ACPI_TYPE_INTEGER) { - u32 tas_selection = - (u32)wifi_pkg->package.elements[1].integer.value; - - enabled = iwl_parse_tas_selection(fwrt, tas_data, - tas_selection); - - } else if (tbl_rev == 0 && - wifi_pkg->package.elements[1].type == ACPI_TYPE_INTEGER) { - enabled = !!wifi_pkg->package.elements[1].integer.value; - } else { + if (tbl_rev < 0 || tbl_rev > 2 || + wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER) { ret = -EINVAL; goto out_free; } - if (!enabled) { - IWL_DEBUG_RADIO(fwrt, "TAS not enabled\n"); - ret = 0; - goto out_free; - } + tas_selection = (u32)wifi_pkg->package.elements[1].integer.value; + enabled = tas_selection & IWL_WTAS_ENABLED_MSK; + + IWL_DEBUG_RADIO(fwrt, "TAS selection as read from BIOS: 0x%x\n", + tas_selection); + tas_data->table_source = BIOS_SOURCE_ACPI; + tas_data->table_revision = tbl_rev; + tas_data->tas_selection = tas_selection; + + IWL_DEBUG_RADIO(fwrt, "TAS %s enabled\n", + enabled ? "is" : "not"); IWL_DEBUG_RADIO(fwrt, "Reading TAS table revision %d\n", tbl_rev); if (wifi_pkg->package.elements[2].type != ACPI_TYPE_INTEGER || @@ -305,13 +305,14 @@ int iwl_acpi_get_tas_table(struct iwl_fw_runtime *fwrt, ret = -EINVAL; goto out_free; } + block_list_size = wifi_pkg->package.elements[2].integer.value; - tas_data->block_list_size = cpu_to_le32(block_list_size); + tas_data->block_list_size = block_list_size; IWL_DEBUG_RADIO(fwrt, "TAS array size %u\n", block_list_size); - for (i = 0; i < block_list_size; i++) { - u32 country; + for (int i = 0; i < block_list_size; i++) { + u16 country; if (wifi_pkg->package.elements[3 + i].type != ACPI_TYPE_INTEGER) { @@ -322,11 +323,11 @@ int iwl_acpi_get_tas_table(struct iwl_fw_runtime *fwrt, } country = wifi_pkg->package.elements[3 + i].integer.value; - tas_data->block_list_array[i] = cpu_to_le32(country); + tas_data->block_list_array[i] = country; IWL_DEBUG_RADIO(fwrt, "TAS block list country %d\n", country); } - ret = 1; + ret = enabled; out_free: kfree(data); return ret; @@ -1023,3 +1024,37 @@ out_free: kfree(data); return ret; } + +int iwl_acpi_get_dsbr(struct iwl_fw_runtime *fwrt, u32 *value) +{ + union acpi_object *wifi_pkg, *data; + int ret = -ENOENT; + int tbl_rev; + + data = iwl_acpi_get_object(fwrt->dev, ACPI_DSBR_METHOD); + if (IS_ERR(data)) + return ret; + + wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data, + ACPI_DSBR_WIFI_DATA_SIZE, + &tbl_rev); + if (IS_ERR(wifi_pkg)) + goto out_free; + + if (tbl_rev != ACPI_DSBR_WIFI_DATA_REV) { + IWL_DEBUG_RADIO(fwrt, "Unsupported ACPI DSBR revision:%d\n", + tbl_rev); + goto out_free; + } + + if (wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER) + goto out_free; + + *value = wifi_pkg->package.elements[1].integer.value; + IWL_DEBUG_RADIO(fwrt, "Loaded DSBR config from ACPI value: 0x%x\n", + *value); + ret = 0; +out_free: + kfree(data); + return ret; +} diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.h b/drivers/net/wireless/intel/iwlwifi/fw/acpi.h index bb88398a6987..e50b93472dd2 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.h @@ -28,6 +28,7 @@ #define ACPI_WPFC_METHOD "WPFC" #define ACPI_GLAI_METHOD "GLAI" #define ACPI_WBEM_METHOD "WBEM" +#define ACPI_DSBR_METHOD "DSBR" #define ACPI_WIFI_DOMAIN (0x07) @@ -76,6 +77,13 @@ #define ACPI_WBEM_WIFI_DATA_SIZE 2 /* * One element for domain type, + * and one for DSBR response data + */ +#define ACPI_DSBR_WIFI_DATA_SIZE 2 +#define ACPI_DSBR_WIFI_DATA_REV 1 + +/* + * One element for domain type, * and one for the status */ #define ACPI_GLAI_WIFI_DATA_SIZE 2 @@ -101,6 +109,30 @@ #define ACPI_DSM_REV 0 +#define DSM_INTERNAL_FUNC_GET_PLAT_INFO 1 +/* TBD: VPRO is BIT(0) in the result, but what's the result? */ + +#define DSM_INTERNAL_FUNC_PRODUCT_RESET 2 + +/* DSM_INTERNAL_FUNC_PRODUCT_RESET - product reset (aka "PLDR") */ +enum iwl_dsm_internal_product_reset_cmds { + DSM_INTERNAL_PLDR_CMD_GET_MODE = 1, + DSM_INTERNAL_PLDR_CMD_SET_MODE = 2, + DSM_INTERNAL_PLDR_CMD_GET_STATUS = 3, +}; + +enum iwl_dsm_internal_product_reset_mode { + DSM_INTERNAL_PLDR_MODE_EN_PROD_RESET = BIT(0), + DSM_INTERNAL_PLDR_MODE_EN_WIFI_FLR = BIT(1), + DSM_INTERNAL_PLDR_MODE_EN_BT_OFF_ON = BIT(2), +}; + +struct iwl_dsm_internal_product_reset_cmd { + /* cmd is from enum iwl_dsm_internal_product_reset_cmds */ + u16 cmd; + u16 value; +} __packed; + #define IWL_ACPI_WBEM_REV0_MASK (BIT(0) | BIT(1)) #define IWL_ACPI_WBEM_REVISION 0 @@ -110,6 +142,10 @@ struct iwl_fw_runtime; extern const guid_t iwl_guid; +union acpi_object *iwl_acpi_get_dsm_object(struct device *dev, int rev, + int func, union acpi_object *args, + const guid_t *guid); + /** * iwl_acpi_get_mcc - read MCC from ACPI, if available * @@ -153,10 +189,14 @@ int iwl_acpi_get_dsm(struct iwl_fw_runtime *fwrt, enum iwl_dsm_funcs func, u32 *value); int iwl_acpi_get_wbem(struct iwl_fw_runtime *fwrt, u32 *value); + +int iwl_acpi_get_dsbr(struct iwl_fw_runtime *fwrt, u32 *value); + #else /* CONFIG_ACPI */ -static inline void *iwl_acpi_get_dsm_object(struct device *dev, int rev, - int func, union acpi_object *args) +static inline union acpi_object * +iwl_acpi_get_dsm_object(struct device *dev, int rev, int func, + union acpi_object *args, const guid_t *guid) { return ERR_PTR(-ENOENT); } @@ -221,6 +261,11 @@ static inline int iwl_acpi_get_wbem(struct iwl_fw_runtime *fwrt, u32 *value) { return -ENOENT; } + +static inline int iwl_acpi_get_dsbr(struct iwl_fw_runtime *fwrt, u32 *value) +{ + return -ENOENT; +} #endif /* CONFIG_ACPI */ #endif /* __iwl_fw_acpi__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h b/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h index 2f40e69db318..34a1f97653c0 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h @@ -447,7 +447,7 @@ enum iwl_legacy_cmds { /** * @BA_NOTIF: - * BlockAck notification, uses &struct iwl_mvm_compressed_ba_notif + * BlockAck notification, uses &struct iwl_compressed_ba_notif * or &struct iwl_mvm_ba_notif depending on the HW */ BA_NOTIF = 0xc5, diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h b/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h index 2ab38eaeb290..570a3f722510 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h @@ -391,7 +391,7 @@ enum iwl_datapath_monitor_notif_type { struct iwl_datapath_monitor_notif { __le32 type; - u8 mac_id; + u8 link_id; u8 reserved[3]; } __packed; /* MONITOR_NTF_API_S_VER_1 */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/debug.h b/drivers/net/wireless/intel/iwlwifi/fw/api/debug.h index bea0f4668cc8..aa88e91d117e 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/debug.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/debug.h @@ -477,6 +477,9 @@ struct iwl_mvm_tas_status_per_mac { * @tas_status_mac: TAS status per lmac, uses * &struct iwl_mvm_tas_status_per_mac * @in_dual_radio: is TAS in dual radio? - TRUE/FALSE + * @uhb_allowed_flags: see &enum iwl_tas_uhb_allowed_flags. + * This member is valid only when fw has + * %IWL_UCODE_TLV_CAPA_UHB_CANADA_TAS_SUPPORT capability. * @reserved: reserved */ struct iwl_mvm_tas_status_resp { @@ -486,7 +489,8 @@ struct iwl_mvm_tas_status_resp { __le16 block_list[16]; struct iwl_mvm_tas_status_per_mac tas_status_mac[2]; u8 in_dual_radio; - u8 reserved[3]; + u8 uhb_allowed_flags; + u8 reserved[2]; } __packed; /*DEBUG_GET_TAS_STATUS_RSP_API_S_VER_3*/ /** diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h index b23d5fc4bbe6..37bb7002c1c9 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h @@ -74,7 +74,7 @@ enum iwl_mac_conf_subcmd_ids { */ ROC_NOTIF = 0xF8, /** - * @SESSION_PROTECTION_NOTIF: &struct iwl_mvm_session_prot_notif + * @SESSION_PROTECTION_NOTIF: &struct iwl_session_prot_notif */ SESSION_PROTECTION_NOTIF = 0xFB, diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h b/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h index d424d0126367..5cdc09d465d4 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h @@ -464,21 +464,30 @@ struct iwl_tas_config_cmd_v3 { } __packed; /* TAS_CONFIG_CMD_API_S_VER_3 */ /** + * enum iwl_tas_uhb_allowed_flags - per country TAS UHB allowed flags. + * @TAS_UHB_ALLOWED_CANADA: TAS UHB is allowed in Canada. This flag is valid + * only when fw has %IWL_UCODE_TLV_CAPA_UHB_CANADA_TAS_SUPPORT capability. + */ +enum iwl_tas_uhb_allowed_flags { + TAS_UHB_ALLOWED_CANADA = BIT(0), +}; + +/** * struct iwl_tas_config_cmd_v4 - configures the TAS * @override_tas_iec: indicates whether to override default value of IEC regulatory * @enable_tas_iec: in case override_tas_iec is set - * indicates whether IEC regulatory is enabled or disabled * @usa_tas_uhb_allowed: if set, allow TAS UHB in the USA - * @reserved: reserved -*/ + * @uhb_allowed_flags: see &enum iwl_tas_uhb_allowed_flags. + */ struct iwl_tas_config_cmd_v4 { u8 override_tas_iec; u8 enable_tas_iec; u8 usa_tas_uhb_allowed; - u8 reserved; + u8 uhb_allowed_flags; } __packed; /* TAS_CONFIG_CMD_API_S_VER_4 */ -struct iwl_tas_config_cmd { +struct iwl_tas_config_cmd_v2_v4 { struct iwl_tas_config_cmd_common common; union { struct iwl_tas_config_cmd_v3 v3; @@ -487,6 +496,46 @@ struct iwl_tas_config_cmd { }; /** + * enum bios_source - source of bios data + * @BIOS_SOURCE_NONE: BIOS source is not defined + * @BIOS_SOURCE_ACPI: BIOS source is ACPI + * @BIOS_SOURCE_UEFI: BIOS source is UEFI + */ +enum bios_source { + BIOS_SOURCE_NONE, + BIOS_SOURCE_ACPI, + BIOS_SOURCE_UEFI, +}; + +/** + * struct bios_value_u32 - BIOS configuration. + * @table_source: see &enum bios_source + * @table_revision: table revision. + * @reserved: reserved + * @value: value in bios. + */ +struct bios_value_u32 { + u8 table_source; + u8 table_revision; + u8 reserved[2]; + __le32 value; +} __packed; /* BIOS_TABLE_SOURCE_U32_S_VER_1 */ + +/** + * struct iwl_tas_config_cmd - configures the TAS. + * @block_list_size: size of relevant field in block_list_array + * @block_list_array: list of countries where TAS must be disabled + * @reserved: reserved + * @tas_config_info: see @struct bios_value_u32 + */ +struct iwl_tas_config_cmd { + __le16 block_list_size; + __le16 block_list_array[IWL_WTAS_BLACK_LIST_MAX]; + u8 reserved[2]; + struct bios_value_u32 tas_config_info; +} __packed; /* TAS_CONFIG_CMD_API_S_VER_5 */ + +/** * enum iwl_lari_config_masks - bit masks for the various LARI config operations * @LARI_CONFIG_DISABLE_11AC_UKRAINE_MSK: disable 11ac in ukraine * @LARI_CONFIG_CHANGE_ETSI_TO_PASSIVE_MSK: ETSI 5.8GHz SRD passive scan diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/offload.h b/drivers/net/wireless/intel/iwlwifi/fw/api/offload.h index 6a7bbfd6b2b7..9b09b835560b 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/offload.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/offload.h @@ -31,7 +31,7 @@ enum iwl_prot_offload_subcmd_ids { /** * @STORED_BEACON_NTF: &struct iwl_stored_beacon_notif_v2 or - * &struct iwl_stored_beacon_notif_v3 + * &struct iwl_stored_beacon_notif */ STORED_BEACON_NTF = 0xFF, }; @@ -71,18 +71,18 @@ struct iwl_stored_beacon_notif_v2 { } __packed; /* WOWLAN_STROED_BEACON_INFO_S_VER_2 */ /** - * struct iwl_stored_beacon_notif_v3 - Stored beacon notification + * struct iwl_stored_beacon_notif - Stored beacon notification * * @common: fields common for all versions * @sta_id: station for which the beacon was received * @reserved: reserved for alignment * @data: beacon data, length in @byte_count */ -struct iwl_stored_beacon_notif_v3 { +struct iwl_stored_beacon_notif { struct iwl_stored_beacon_notif_common common; u8 sta_id; u8 reserved[3]; u8 data[MAX_STORED_BEACON_SIZE]; -} __packed; /* WOWLAN_STROED_BEACON_INFO_S_VER_3 */ +} __packed; /* WOWLAN_STROED_BEACON_INFO_S_VER_3, _VER_4 */ #endif /* __iwl_fw_api_offload_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/power.h b/drivers/net/wireless/intel/iwlwifi/fw/api/power.h index df0680eae30c..37ec26596ee7 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/power.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/power.h @@ -266,7 +266,7 @@ struct iwl_reduce_tx_power_cmd { } __packed; /* TX_REDUCED_POWER_API_S_VER_1 */ enum iwl_dev_tx_power_cmd_mode { - IWL_TX_POWER_MODE_SET_MAC = 0, + IWL_TX_POWER_MODE_SET_LINK = 0, IWL_TX_POWER_MODE_SET_DEVICE = 1, IWL_TX_POWER_MODE_SET_CHAINS = 2, IWL_TX_POWER_MODE_SET_ACK = 3, @@ -283,12 +283,14 @@ enum iwl_dev_tx_power_cmd_mode { /** * struct iwl_dev_tx_power_common - Common part of the TX power reduction cmd * @set_mode: see &enum iwl_dev_tx_power_cmd_mode - * @mac_context_id: id of the mac ctx for which we are reducing TX power. + * @link_id: id of the link ctx for which we are reducing TX power. + * For version 9 / 10, this is the link id. For earlier versions, it is + * the mac id. * @pwr_restriction: TX power restriction in 1/8 dBms. */ struct iwl_dev_tx_power_common { __le32 set_mode; - __le32 mac_context_id; + __le32 link_id; __le16 pwr_restriction; } __packed; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/tdls.h b/drivers/net/wireless/intel/iwlwifi/fw/api/tdls.h index 893438aadab0..cfa6532a3cdd 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/tdls.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/tdls.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2012-2014, 2018 Intel Corporation + * Copyright (C) 2012-2014, 2018, 2024 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -10,7 +10,7 @@ #include "fw/api/tx.h" #include "fw/api/phy-ctxt.h" -#define IWL_MVM_TDLS_STA_COUNT 4 +#define IWL_TDLS_STA_COUNT 4 /* Type of TDLS request */ enum iwl_tdls_channel_switch_type { @@ -128,7 +128,7 @@ struct iwl_tdls_config_cmd { u8 tdls_peer_count; u8 tx_to_ap_tid; __le16 tx_to_ap_ssn; - struct iwl_tdls_sta_info sta_info[IWL_MVM_TDLS_STA_COUNT]; + struct iwl_tdls_sta_info sta_info[IWL_TDLS_STA_COUNT]; __le32 pti_req_data_offset; struct iwl_tx_cmd pti_req_tx_cmd; @@ -155,7 +155,7 @@ struct iwl_tdls_config_sta_info_res { */ struct iwl_tdls_config_res { __le32 tx_to_ap_last_seq; - struct iwl_tdls_config_sta_info_res sta_info[IWL_MVM_TDLS_STA_COUNT]; + struct iwl_tdls_config_sta_info_res sta_info[IWL_TDLS_STA_COUNT]; } __packed; /* TDLS_CONFIG_RSP_API_S_VER_1 */ #endif /* __iwl_fw_api_tdls_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/time-event.h b/drivers/net/wireless/intel/iwlwifi/fw/api/time-event.h index f4b827b58bd3..18d030334a6a 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/time-event.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/time-event.h @@ -395,7 +395,7 @@ struct iwl_roc_notif { } __packed; /* ROC_NOTIF_API_S_VER_1 */ /** - * enum iwl_mvm_session_prot_conf_id - session protection's configurations + * enum iwl_session_prot_conf_id - session protection's configurations * @SESSION_PROTECT_CONF_ASSOC: Start a session protection for association. * The firmware will allocate two events. * Valid for BSS_STA and P2P_STA. @@ -424,7 +424,7 @@ struct iwl_roc_notif { * be taken into account. * @SESSION_PROTECT_CONF_MAX_ID: not used */ -enum iwl_mvm_session_prot_conf_id { +enum iwl_session_prot_conf_id { SESSION_PROTECT_CONF_ASSOC, SESSION_PROTECT_CONF_GO_CLIENT_ASSOC, SESSION_PROTECT_CONF_P2P_DEVICE_DISCOV, @@ -433,12 +433,12 @@ enum iwl_mvm_session_prot_conf_id { }; /* SESSION_PROTECTION_CONF_ID_E_VER_1 */ /** - * struct iwl_mvm_session_prot_cmd - configure a session protection + * struct iwl_session_prot_cmd - configure a session protection * @id_and_color: the id and color of the link (or mac, for command version 1) * for which this session protection is sent * @action: can be either FW_CTXT_ACTION_ADD or FW_CTXT_ACTION_REMOVE, * see &enum iwl_ctxt_action - * @conf_id: see &enum iwl_mvm_session_prot_conf_id + * @conf_id: see &enum iwl_session_prot_conf_id * @duration_tu: the duration of the whole protection in TUs. * @repetition_count: not used * @interval: not used @@ -448,7 +448,7 @@ enum iwl_mvm_session_prot_conf_id { * The firmware supports only one concurrent session protection per vif. * Adding a new session protection will remove any currently running session. */ -struct iwl_mvm_session_prot_cmd { +struct iwl_session_prot_cmd { /* COMMON_INDEX_HDR_API_S_VER_1 hdr */ __le32 id_and_color; __le32 action; @@ -462,17 +462,17 @@ struct iwl_mvm_session_prot_cmd { */ /** - * struct iwl_mvm_session_prot_notif - session protection started / ended + * struct iwl_session_prot_notif - session protection started / ended * @mac_link_id: the mac id (or link id, for notif ver > 2) for which the * session protection started / ended * @status: 1 means success, 0 means failure * @start: 1 means the session protection started, 0 means it ended - * @conf_id: see &enum iwl_mvm_session_prot_conf_id + * @conf_id: see &enum iwl_session_prot_conf_id * * Note that any session protection will always get two notifications: start * and end even the firmware could not schedule it. */ -struct iwl_mvm_session_prot_notif { +struct iwl_session_prot_notif { __le32 mac_link_id; __le32 status; __le32 start; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h b/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h index f3bf2e087a40..0a39e4b6eb62 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h @@ -191,7 +191,7 @@ enum iwl_tx_offload_assist_flags_pos { * cleared. Combination of RATE_MCS_* * @sta_id: index of destination station in FW station table * @sec_ctl: security control, TX_CMD_SEC_* - * @initial_rate_index: index into the the rate table for initial TX attempt. + * @initial_rate_index: index into the rate table for initial TX attempt. * Applied if TX_CMD_FLG_STA_RATE_MSK is set, normally 0 for data frames. * @reserved2: reserved * @key: security key @@ -298,8 +298,7 @@ struct iwl_tx_cmd_gen3 { __le32 rate_n_flags; u8 reserved[8]; struct ieee80211_hdr hdr[]; -} __packed; /* TX_CMD_API_S_VER_8, - TX_CMD_API_S_VER_10 */ +} __packed; /* TX_CMD_API_S_VER_8, TX_CMD_API_S_VER_10 */ /* * TX response related data @@ -482,8 +481,8 @@ struct agg_tx_status { #define TX_RES_RATE_TABLE_COL_GET(_f) (((_f) & TX_RES_RATE_TABLE_COLOR_MSK) >>\ TX_RES_RATE_TABLE_COLOR_POS) -#define IWL_MVM_TX_RES_GET_TID(_ra_tid) ((_ra_tid) & 0x0f) -#define IWL_MVM_TX_RES_GET_RA(_ra_tid) ((_ra_tid) >> 4) +#define IWL_TX_RES_GET_TID(_ra_tid) ((_ra_tid) & 0x0f) +#define IWL_TX_RES_GET_RA(_ra_tid) ((_ra_tid) >> 4) /** * struct iwl_tx_resp_v3 - notifies that fw is TXing a packet @@ -601,7 +600,8 @@ struct iwl_tx_resp { __le16 reserved2; struct agg_tx_status status; } __packed; /* TX_RSP_API_S_VER_6, - TX_RSP_API_S_VER_7 */ + TX_RSP_API_S_VER_7, + TX_RSP_API_S_VER_8 */ /** * struct iwl_mvm_ba_notif - notifies about reception of BA @@ -638,14 +638,14 @@ struct iwl_mvm_ba_notif { } __packed; /** - * struct iwl_mvm_compressed_ba_tfd - progress of a TFD queue + * struct iwl_compressed_ba_tfd - progress of a TFD queue * @q_num: TFD queue number * @tfd_index: Index of first un-acked frame in the TFD queue * @scd_queue: For debug only - the physical queue the TFD queue is bound to * @tid: TID of the queue (0-7) * @reserved: reserved for alignment */ -struct iwl_mvm_compressed_ba_tfd { +struct iwl_compressed_ba_tfd { __le16 q_num; __le16 tfd_index; u8 scd_queue; @@ -654,12 +654,12 @@ struct iwl_mvm_compressed_ba_tfd { } __packed; /* COMPRESSED_BA_TFD_API_S_VER_1 */ /** - * struct iwl_mvm_compressed_ba_ratid - progress of a RA TID queue + * struct iwl_compressed_ba_ratid - progress of a RA TID queue * @q_num: RA TID queue number * @tid: TID of the queue * @ssn: BA window current SSN */ -struct iwl_mvm_compressed_ba_ratid { +struct iwl_compressed_ba_ratid { u8 q_num; u8 tid; __le16 ssn; @@ -685,7 +685,7 @@ enum iwl_mvm_ba_resp_flags { }; /** - * struct iwl_mvm_compressed_ba_notif - notifies about reception of BA + * struct iwl_compressed_ba_notif - notifies about reception of BA * ( BA_NOTIF = 0xc5 ) * @flags: status flag, see the &iwl_mvm_ba_resp_flags * @sta_id: Index of recipient (BA-sending) station in fw's station table @@ -704,12 +704,12 @@ enum iwl_mvm_ba_resp_flags { * @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 + * @tfd: array of TFD queue status updates. See &iwl_compressed_ba_tfd * for details. Length in @tfd_cnt. * @ra_tid: array of RA-TID queue status updates. For debug purposes only. See - * &iwl_mvm_compressed_ba_ratid for more details. Length in @ra_tid_cnt. + * &iwl_compressed_ba_ratid for more details. Length in @ra_tid_cnt. */ -struct iwl_mvm_compressed_ba_notif { +struct iwl_compressed_ba_notif { __le32 flags; u8 sta_id; u8 reduced_txp; @@ -726,8 +726,8 @@ struct iwl_mvm_compressed_ba_notif { __le16 tfd_cnt; __le16 ra_tid_cnt; union { - DECLARE_FLEX_ARRAY(struct iwl_mvm_compressed_ba_ratid, ra_tid); - DECLARE_FLEX_ARRAY(struct iwl_mvm_compressed_ba_tfd, tfd); + DECLARE_FLEX_ARRAY(struct iwl_compressed_ba_ratid, ra_tid); + DECLARE_FLEX_ARRAY(struct iwl_compressed_ba_tfd, tfd); }; } __packed; /* COMPRESSED_BA_RES_API_S_VER_4, COMPRESSED_BA_RES_API_S_VER_5 */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h index f4803b55adb9..87998374f459 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h @@ -287,7 +287,7 @@ static inline void iwl_fw_umac_set_alive_err_table(struct iwl_trans *trans, trans->dbg.umac_error_event_table = umac_error_event_table; } -static inline void iwl_fw_error_collect(struct iwl_fw_runtime *fwrt, bool sync) +static inline void iwl_fw_error_collect(struct iwl_fw_runtime *fwrt) { enum iwl_fw_ini_time_point tp_id; @@ -303,7 +303,7 @@ static inline void iwl_fw_error_collect(struct iwl_fw_runtime *fwrt, bool sync) tp_id = IWL_FW_INI_TIME_POINT_FW_ASSERT; } - _iwl_dbg_tlv_time_point(fwrt, tp_id, NULL, sync); + iwl_dbg_tlv_time_point_sync(fwrt, tp_id, NULL); } static inline void iwl_fwrt_update_fw_versions(struct iwl_fw_runtime *fwrt, diff --git a/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c b/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c index 893b21fcaf87..f0c813d675f4 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2012-2014, 2018-2023 Intel Corporation + * Copyright (C) 2012-2014, 2018-2024 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -123,6 +123,24 @@ static const struct file_operations iwl_dbgfs_##name##_ops = { \ #define FWRT_DEBUGFS_ADD_FILE(name, parent, mode) \ FWRT_DEBUGFS_ADD_FILE_ALIAS(#name, name, parent, mode) +static ssize_t iwl_dbgfs_fw_dbg_collect_write(struct iwl_fw_runtime *fwrt, + char *buf, size_t count) +{ + if (count == 0) + return 0; + + if (!iwl_trans_fw_running(fwrt->trans)) + return count; + + iwl_dbg_tlv_time_point(fwrt, IWL_FW_INI_TIME_POINT_USER_TRIGGER, NULL); + + iwl_fw_dbg_collect(fwrt, FW_DBG_TRIGGER_USER, buf, (count - 1), NULL); + + return count; +} + +FWRT_DEBUGFS_WRITE_FILE_OPS(fw_dbg_collect, 16); + static int iwl_dbgfs_enabled_severities_write(struct iwl_fw_runtime *fwrt, char *buf, size_t count) { @@ -282,6 +300,26 @@ static ssize_t iwl_dbgfs_fw_dbg_domain_read(struct iwl_fw_runtime *fwrt, FWRT_DEBUGFS_READ_FILE_OPS(fw_dbg_domain, 20); +static ssize_t iwl_dbgfs_fw_ver_read(struct iwl_fw_runtime *fwrt, + size_t size, char *buf) +{ + char *pos = buf; + char *endpos = buf + size; + + pos += scnprintf(pos, endpos - pos, "FW id: %s\n", + fwrt->fw->fw_version); + pos += scnprintf(pos, endpos - pos, "FW: %s\n", + fwrt->fw->human_readable); + pos += scnprintf(pos, endpos - pos, "Device: %s\n", + fwrt->trans->name); + pos += scnprintf(pos, endpos - pos, "Bus: %s\n", + fwrt->dev->bus->name); + + return pos - buf; +} + +FWRT_DEBUGFS_READ_FILE_OPS(fw_ver, 1024); + struct iwl_dbgfs_fw_info_priv { struct iwl_fw_runtime *fwrt; }; @@ -403,5 +441,7 @@ void iwl_fwrt_dbgfs_register(struct iwl_fw_runtime *fwrt, FWRT_DEBUGFS_ADD_FILE(fw_info, dbgfs_dir, 0200); FWRT_DEBUGFS_ADD_FILE(send_hcmd, dbgfs_dir, 0200); FWRT_DEBUGFS_ADD_FILE(enabled_severities, dbgfs_dir, 0200); + FWRT_DEBUGFS_ADD_FILE(fw_dbg_collect, dbgfs_dir, 0200); FWRT_DEBUGFS_ADD_FILE(fw_dbg_domain, dbgfs_dir, 0400); + FWRT_DEBUGFS_ADD_FILE(fw_ver, dbgfs_dir, 0400); } diff --git a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h index e63b08b7d336..3af275133da0 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h @@ -169,7 +169,7 @@ struct iwl_fw_error_dump_info { * @fw_mon_wr_ptr: the position of the write pointer in the cyclic buffer * @fw_mon_base_ptr: base pointer of the data * @fw_mon_cycle_cnt: number of wraparounds - * @fw_mon_base_high_ptr: used in AX210 devices, the base adderss is 64 bit + * @fw_mon_base_high_ptr: used in AX210 devices, the base address is 64 bit * so fw_mon_base_ptr holds LSB 32 bits and fw_mon_base_high_ptr hold * MSB 32 bits * @reserved: for future use diff --git a/drivers/net/wireless/intel/iwlwifi/fw/file.h b/drivers/net/wireless/intel/iwlwifi/fw/file.h index ae05227b6153..9860903ecd3f 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/file.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/file.h @@ -104,6 +104,7 @@ enum iwl_ucode_tlv_type { IWL_UCODE_TLV_CURRENT_PC = 68, IWL_UCODE_TLV_FW_NUM_STATIONS = IWL_UCODE_TLV_CONST_BASE + 0, + IWL_UCODE_TLV_FW_NUM_LINKS = IWL_UCODE_TLV_CONST_BASE + 1, IWL_UCODE_TLV_FW_NUM_BEACONS = IWL_UCODE_TLV_CONST_BASE + 2, IWL_UCODE_TLV_TYPE_DEBUG_INFO = IWL_UCODE_TLV_DEBUG_BASE + 0, @@ -384,7 +385,8 @@ typedef unsigned int __bitwise iwl_ucode_tlv_capa_t; * to report the CSI information with (certain) RX frames * @IWL_UCODE_TLV_CAPA_FTM_CALIBRATED: has FTM calibrated and thus supports both * initiator and responder - * @IWL_UCODE_TLV_CAPA_MLME_OFFLOAD: supports MLME offload + * @IWL_UCODE_TLV_CAPA_BIOS_OVERRIDE_UNII4_US_CA: supports (de)activating UNII-4 + * for US/CA/WW from BIOS * @IWL_UCODE_TLV_CAPA_PROTECTED_TWT: Supports protection of TWT action frames * @IWL_UCODE_TLV_CAPA_FW_RESET_HANDSHAKE: Supports the firmware handshake in * reset flow @@ -397,6 +399,9 @@ typedef unsigned int __bitwise iwl_ucode_tlv_capa_t; * @IWL_UCODE_TLV_CAPA_SECURE_LTF_SUPPORT: Support secure LTF measurement. * @IWL_UCODE_TLV_CAPA_MONITOR_PASSIVE_CHANS: Support monitor mode on otherwise * passive channels + * @IWL_UCODE_TLV_CAPA_BIOS_OVERRIDE_5G9_FOR_CA: supports (de)activating 5G9 + * for CA from BIOS. + * @IWL_UCODE_TLV_CAPA_UHB_CANADA_TAS_SUPPORT: supports %TAS_UHB_ALLOWED_CANADA * * @NUM_IWL_UCODE_TLV_CAPA: number of bits used */ @@ -474,7 +479,7 @@ enum iwl_ucode_tlv_capa { IWL_UCODE_TLV_CAPA_DBG_BUF_ALLOC_CMD_SUPP = (__force iwl_ucode_tlv_capa_t)93, /* set 3 */ - IWL_UCODE_TLV_CAPA_MLME_OFFLOAD = (__force iwl_ucode_tlv_capa_t)96, + IWL_UCODE_TLV_CAPA_BIOS_OVERRIDE_UNII4_US_CA = (__force iwl_ucode_tlv_capa_t)96, /* * @IWL_UCODE_TLV_CAPA_PSC_CHAN_SUPPORT: supports PSC channels @@ -497,6 +502,8 @@ enum iwl_ucode_tlv_capa { IWL_UCODE_TLV_CAPA_CHINA_22_REG_SUPPORT = (__force iwl_ucode_tlv_capa_t)117, IWL_UCODE_TLV_CAPA_SECURE_LTF_SUPPORT = (__force iwl_ucode_tlv_capa_t)121, IWL_UCODE_TLV_CAPA_MONITOR_PASSIVE_CHANS = (__force iwl_ucode_tlv_capa_t)122, + IWL_UCODE_TLV_CAPA_BIOS_OVERRIDE_5G9_FOR_CA = (__force iwl_ucode_tlv_capa_t)123, + IWL_UCODE_TLV_CAPA_UHB_CANADA_TAS_SUPPORT = (__force iwl_ucode_tlv_capa_t)124, NUM_IWL_UCODE_TLV_CAPA /* * This construction make both sparse (which cannot increment the previous diff --git a/drivers/net/wireless/intel/iwlwifi/fw/img.c b/drivers/net/wireless/intel/iwlwifi/fw/img.c index b7deca05a953..c2f4fc83a22c 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/img.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/img.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* * Copyright(c) 2019 - 2021 Intel Corporation + * Copyright(c) 2024 Intel Corporation */ #include <fw/api/commands.h> #include "img.h" @@ -75,6 +76,7 @@ static const struct { { "NMI_INTERRUPT_ACTION_PT", 0x7C }, { "NMI_INTERRUPT_UNKNOWN", 0x84 }, { "NMI_INTERRUPT_INST_ACTION_PT", 0x86 }, + { "NMI_INTERRUPT_PREG", 0x88 }, { "PNVM_MISSING", FW_SYSASSERT_PNVM_MISSING }, { "ADVANCED_SYSASSERT", 0 }, }; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/img.h b/drivers/net/wireless/intel/iwlwifi/fw/img.h index 96bda80632f3..f9de139561a0 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/img.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/img.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2005-2014, 2018-2023 Intel Corporation + * Copyright (C) 2005-2014, 2018-2024 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016 Intel Deutschland GmbH */ @@ -51,6 +51,7 @@ struct iwl_ucode_capabilities { u32 error_log_addr; u32 error_log_size; u32 num_stations; + u32 num_links; u32 num_beacons; unsigned long _api[BITS_TO_LONGS(NUM_IWL_UCODE_TLV_API)]; unsigned long _capa[BITS_TO_LONGS(NUM_IWL_UCODE_TLV_CAPA)]; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/paging.c b/drivers/net/wireless/intel/iwlwifi/fw/paging.c index 945bc4160cc9..a7b7cae874a2 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/paging.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/paging.c @@ -249,7 +249,7 @@ static int iwl_send_paging_cmd(struct iwl_fw_runtime *fwrt, }; int blk_idx; - /* loop for for all paging blocks + CSS block */ + /* loop for all paging blocks + CSS block */ for (blk_idx = 0; blk_idx < fwrt->num_of_paging_blk + 1; blk_idx++) { dma_addr_t addr = fwrt->fw_paging_db[blk_idx].fw_paging_phys; __le32 phy_addr; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c index 4d9a1f83ef8c..ea435ee94312 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c @@ -39,6 +39,7 @@ IWL_BIOS_TABLE_LOADER_DATA(pwr_limit, u64); IWL_BIOS_TABLE_LOADER_DATA(mcc, char); IWL_BIOS_TABLE_LOADER_DATA(eckv, u32); IWL_BIOS_TABLE_LOADER_DATA(wbem, u32); +IWL_BIOS_TABLE_LOADER_DATA(dsbr, u32); static const struct dmi_system_id dmi_ppag_approved_list[] = { @@ -100,6 +101,11 @@ static const struct dmi_system_id dmi_ppag_approved_list[] = { DMI_MATCH(DMI_SYS_VENDOR, "HONOR"), }, }, + { .ident = "WIKO", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "WIKO"), + }, + }, {} }; @@ -424,25 +430,31 @@ bool iwl_is_tas_approved(void) } IWL_EXPORT_SYMBOL(iwl_is_tas_approved); -int iwl_parse_tas_selection(struct iwl_fw_runtime *fwrt, - struct iwl_tas_data *tas_data, - const u32 tas_selection) +struct iwl_tas_selection_data +iwl_parse_tas_selection(const u32 tas_selection_in, const u8 tbl_rev) { - u8 override_iec = u32_get_bits(tas_selection, + struct iwl_tas_selection_data tas_selection_out = {}; + u8 override_iec = u32_get_bits(tas_selection_in, IWL_WTAS_OVERRIDE_IEC_MSK); - u8 enabled_iec = u32_get_bits(tas_selection, IWL_WTAS_ENABLE_IEC_MSK); - u8 usa_tas_uhb = u32_get_bits(tas_selection, IWL_WTAS_USA_UHB_MSK); - int enabled = tas_selection & IWL_WTAS_ENABLED_MSK; - - IWL_DEBUG_RADIO(fwrt, "TAS selection as read from BIOS: 0x%x\n", - tas_selection); + u8 canada_tas_uhb = u32_get_bits(tas_selection_in, + IWL_WTAS_CANADA_UHB_MSK); + u8 enabled_iec = u32_get_bits(tas_selection_in, + IWL_WTAS_ENABLE_IEC_MSK); + u8 usa_tas_uhb = u32_get_bits(tas_selection_in, + IWL_WTAS_USA_UHB_MSK); + + if (tbl_rev > 0) { + tas_selection_out.usa_tas_uhb_allowed = usa_tas_uhb; + tas_selection_out.override_tas_iec = override_iec; + tas_selection_out.enable_tas_iec = enabled_iec; + } - tas_data->usa_tas_uhb_allowed = usa_tas_uhb; - tas_data->override_tas_iec = override_iec; - tas_data->enable_tas_iec = enabled_iec; + if (tbl_rev > 1) + tas_selection_out.canada_tas_uhb_allowed = canada_tas_uhb; - return enabled; + return tas_selection_out; } +IWL_EXPORT_SYMBOL(iwl_parse_tas_selection); static __le32 iwl_get_lari_config_bitmap(struct iwl_fw_runtime *fwrt) { @@ -552,10 +564,16 @@ int iwl_fill_lari_config(struct iwl_fw_runtime *fwrt, ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENABLE_UNII4_CHAN, &value); if (!ret) { - if (cmd_ver < 9) - value &= DSM_UNII4_ALLOW_BITMAP_CMD_V8; - else - value &= DSM_UNII4_ALLOW_BITMAP; + value &= DSM_UNII4_ALLOW_BITMAP; + + /* Since version 9, bits 4 and 5 are supported + * regardless of this capability. + */ + if (cmd_ver < 9 && + !fw_has_capa(&fwrt->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_BIOS_OVERRIDE_5G9_FOR_CA)) + value &= ~(DSM_VALUE_UNII4_CANADA_OVERRIDE_MSK | + DSM_VALUE_UNII4_CANADA_EN_MSK); cmd->oem_unii4_allow_bitmap = cpu_to_le32(value); } @@ -564,7 +582,13 @@ int iwl_fill_lari_config(struct iwl_fw_runtime *fwrt, if (!ret) { if (cmd_ver < 8) value &= ~ACTIVATE_5G2_IN_WW_MASK; - if (cmd_ver < 12) + + /* Since version 12, bits 5 and 6 are supported + * regardless of this capability. + */ + if (cmd_ver < 12 && + !fw_has_capa(&fwrt->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_BIOS_OVERRIDE_UNII4_US_CA)) value &= CHAN_STATE_ACTIVE_BITMAP_CMD_V11; cmd->chan_state_active_bitmap = cpu_to_le32(value); diff --git a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h index 81787501d4a4..b355d7bef14c 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h @@ -40,11 +40,19 @@ #define IWL_PPAG_ETSI_CHINA_MASK 3 #define IWL_PPAG_REV3_MASK 0x7FF -#define IWL_WTAS_ENABLED_MSK 0x1 -#define IWL_WTAS_OVERRIDE_IEC_MSK 0x2 -#define IWL_WTAS_ENABLE_IEC_MSK 0x4 +#define IWL_WTAS_ENABLED_MSK BIT(0) +#define IWL_WTAS_OVERRIDE_IEC_MSK BIT(1) +#define IWL_WTAS_ENABLE_IEC_MSK BIT(2) +#define IWL_WTAS_CANADA_UHB_MSK BIT(15) #define IWL_WTAS_USA_UHB_MSK BIT(16) +struct iwl_tas_selection_data { + u8 override_tas_iec:1, + enable_tas_iec:1, + usa_tas_uhb_allowed:1, + canada_tas_uhb_allowed:1; +}; + #define BIOS_MCC_CHINA 0x434e /* @@ -97,11 +105,11 @@ struct iwl_ppag_chain { }; struct iwl_tas_data { - __le32 block_list_size; - __le32 block_list_array[IWL_WTAS_BLACK_LIST_MAX]; - u8 override_tas_iec; - u8 enable_tas_iec; - u8 usa_tas_uhb_allowed; + u8 block_list_size; + u16 block_list_array[IWL_WTAS_BLACK_LIST_MAX]; + u8 table_source; + u8 table_revision; + u32 tas_selection; }; /* For DSM revision 0 and 4 */ @@ -144,12 +152,11 @@ enum iwl_dsm_unii4_bitmap { DSM_VALUE_UNII4_CANADA_EN_MSK = BIT(5), }; -#define DSM_UNII4_ALLOW_BITMAP_CMD_V8 (DSM_VALUE_UNII4_US_OVERRIDE_MSK | \ - DSM_VALUE_UNII4_US_EN_MSK | \ - DSM_VALUE_UNII4_ETSI_OVERRIDE_MSK | \ - DSM_VALUE_UNII4_ETSI_EN_MSK) -#define DSM_UNII4_ALLOW_BITMAP (DSM_UNII4_ALLOW_BITMAP_CMD_V8 | \ - DSM_VALUE_UNII4_CANADA_OVERRIDE_MSK | \ +#define DSM_UNII4_ALLOW_BITMAP (DSM_VALUE_UNII4_US_OVERRIDE_MSK |\ + DSM_VALUE_UNII4_US_EN_MSK |\ + DSM_VALUE_UNII4_ETSI_OVERRIDE_MSK |\ + DSM_VALUE_UNII4_ETSI_EN_MSK |\ + DSM_VALUE_UNII4_CANADA_OVERRIDE_MSK |\ DSM_VALUE_UNII4_CANADA_EN_MSK) enum iwl_dsm_values_rfi { @@ -184,9 +191,8 @@ bool iwl_is_ppag_approved(struct iwl_fw_runtime *fwrt); bool iwl_is_tas_approved(void); -int iwl_parse_tas_selection(struct iwl_fw_runtime *fwrt, - struct iwl_tas_data *tas_data, - const u32 tas_selection); +struct iwl_tas_selection_data +iwl_parse_tas_selection(const u32 tas_selection, const u8 tbl_rev); int iwl_bios_get_wrds_table(struct iwl_fw_runtime *fwrt); @@ -221,4 +227,27 @@ static inline u32 iwl_bios_get_ppag_flags(const u32 ppag_modes, } bool iwl_puncturing_is_allowed_in_bios(u32 puncturing, u16 mcc); + +#define IWL_DSBR_FW_MODIFIED_URM_MASK BIT(8) +#define IWL_DSBR_PERMANENT_URM_MASK BIT(9) + +int iwl_bios_get_dsbr(struct iwl_fw_runtime *fwrt, u32 *value); + +static inline void iwl_bios_setup_step(struct iwl_trans *trans, + struct iwl_fw_runtime *fwrt) +{ + u32 dsbr; + + if (!trans->trans_cfg->integrated) + return; + + if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_BZ) + return; + + if (iwl_bios_get_dsbr(fwrt, &dsbr)) + dsbr = 0; + + trans->dsbr_urm_fw_dependent = !!(dsbr & IWL_DSBR_FW_MODIFIED_URM_MASK); + trans->dsbr_urm_permanent = !!(dsbr & IWL_DSBR_PERMANENT_URM_MASK); +} #endif /* __fw_regulatory_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c index 091fb6fd7c78..434eed4130b9 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c @@ -13,9 +13,12 @@ #include <linux/efi.h> #include "fw/runtime.h" -#define IWL_EFI_VAR_GUID EFI_GUID(0x92daaf2f, 0xc02b, 0x455b, \ - 0xb2, 0xec, 0xf5, 0xa3, \ - 0x59, 0x4f, 0x4a, 0xea) +#define IWL_EFI_WIFI_GUID EFI_GUID(0x92daaf2f, 0xc02b, 0x455b, \ + 0xb2, 0xec, 0xf5, 0xa3, \ + 0x59, 0x4f, 0x4a, 0xea) +#define IWL_EFI_WIFI_BT_GUID EFI_GUID(0xe65d8884, 0xd4af, 0x4b20, \ + 0x8d, 0x03, 0x77, 0x2e, \ + 0xcc, 0x3d, 0xa5, 0x31) struct iwl_uefi_pnvm_mem_desc { __le32 addr; @@ -61,7 +64,7 @@ void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len) *len = 0; - data = iwl_uefi_get_variable(IWL_UEFI_OEM_PNVM_NAME, &IWL_EFI_VAR_GUID, + data = iwl_uefi_get_variable(IWL_UEFI_OEM_PNVM_NAME, &IWL_EFI_WIFI_GUID, &package_size); if (IS_ERR(data)) { IWL_DEBUG_FW(trans, @@ -76,18 +79,18 @@ void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len) return data; } -static -void *iwl_uefi_get_verified_variable(struct iwl_trans *trans, - efi_char16_t *uefi_var_name, - char *var_name, - unsigned int expected_size, - unsigned long *size) +static void * +iwl_uefi_get_verified_variable_guid(struct iwl_trans *trans, + efi_guid_t *guid, + efi_char16_t *uefi_var_name, + char *var_name, + unsigned int expected_size, + unsigned long *size) { void *var; unsigned long var_size; - var = iwl_uefi_get_variable(uefi_var_name, &IWL_EFI_VAR_GUID, - &var_size); + var = iwl_uefi_get_variable(uefi_var_name, guid, &var_size); if (IS_ERR(var)) { IWL_DEBUG_RADIO(trans, @@ -112,6 +115,18 @@ void *iwl_uefi_get_verified_variable(struct iwl_trans *trans, return var; } +static void * +iwl_uefi_get_verified_variable(struct iwl_trans *trans, + efi_char16_t *uefi_var_name, + char *var_name, + unsigned int expected_size, + unsigned long *size) +{ + return iwl_uefi_get_verified_variable_guid(trans, &IWL_EFI_WIFI_GUID, + uefi_var_name, var_name, + expected_size, size); +} + int iwl_uefi_handle_tlv_mem_desc(struct iwl_trans *trans, const u8 *data, u32 tlv_len, struct iwl_pnvm_image *pnvm_data) { @@ -311,8 +326,9 @@ void iwl_uefi_get_step_table(struct iwl_trans *trans) if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210) return; - data = iwl_uefi_get_verified_variable(trans, IWL_UEFI_STEP_NAME, - "STEP", sizeof(*data), NULL); + data = iwl_uefi_get_verified_variable_guid(trans, &IWL_EFI_WIFI_BT_GUID, + IWL_UEFI_STEP_NAME, + "STEP", sizeof(*data), NULL); if (IS_ERR(data)) return; @@ -554,27 +570,31 @@ int iwl_uefi_get_tas_table(struct iwl_fw_runtime *fwrt, struct iwl_tas_data *tas_data) { struct uefi_cnv_var_wtas *uefi_tas; - int ret = 0, enabled, i; + int ret, enabled; uefi_tas = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_WTAS_NAME, "WTAS", sizeof(*uefi_tas), NULL); if (IS_ERR(uefi_tas)) return -EINVAL; - if (uefi_tas->revision != IWL_UEFI_WTAS_REVISION) { + if (uefi_tas->revision < IWL_UEFI_MIN_WTAS_REVISION || + uefi_tas->revision > IWL_UEFI_MAX_WTAS_REVISION) { ret = -EINVAL; IWL_DEBUG_RADIO(fwrt, "Unsupported UEFI WTAS revision:%d\n", uefi_tas->revision); goto out; } - enabled = iwl_parse_tas_selection(fwrt, tas_data, - uefi_tas->tas_selection); - if (!enabled) { - IWL_DEBUG_RADIO(fwrt, "TAS not enabled\n"); - ret = 0; - goto out; - } + IWL_DEBUG_RADIO(fwrt, "TAS selection as read from BIOS: 0x%x\n", + uefi_tas->tas_selection); + + enabled = uefi_tas->tas_selection & IWL_WTAS_ENABLED_MSK; + tas_data->table_source = BIOS_SOURCE_UEFI; + tas_data->table_revision = uefi_tas->revision; + tas_data->tas_selection = uefi_tas->tas_selection; + + IWL_DEBUG_RADIO(fwrt, "TAS %s enabled\n", + enabled ? "is" : "not"); IWL_DEBUG_RADIO(fwrt, "Reading TAS table revision %d\n", uefi_tas->revision); @@ -584,15 +604,16 @@ int iwl_uefi_get_tas_table(struct iwl_fw_runtime *fwrt, ret = -EINVAL; goto out; } - tas_data->block_list_size = cpu_to_le32(uefi_tas->black_list_size); + + tas_data->block_list_size = uefi_tas->black_list_size; IWL_DEBUG_RADIO(fwrt, "TAS array size %u\n", uefi_tas->black_list_size); - for (i = 0; i < uefi_tas->black_list_size; i++) { - tas_data->block_list_array[i] = - cpu_to_le32(uefi_tas->black_list[i]); + for (u8 i = 0; i < uefi_tas->black_list_size; i++) { + tas_data->block_list_array[i] = uefi_tas->black_list[i]; IWL_DEBUG_RADIO(fwrt, "TAS block list country %d\n", uefi_tas->black_list[i]); } + ret = enabled; out: kfree(uefi_tas); return ret; @@ -758,3 +779,29 @@ int iwl_uefi_get_puncturing(struct iwl_fw_runtime *fwrt) return puncturing; } IWL_EXPORT_SYMBOL(iwl_uefi_get_puncturing); + +int iwl_uefi_get_dsbr(struct iwl_fw_runtime *fwrt, u32 *value) +{ + struct uefi_cnv_wlan_dsbr_data *data; + int ret = 0; + + data = iwl_uefi_get_verified_variable_guid(fwrt->trans, + &IWL_EFI_WIFI_BT_GUID, + IWL_UEFI_DSBR_NAME, "DSBR", + sizeof(*data), NULL); + if (IS_ERR(data)) + return -EINVAL; + + if (data->revision != IWL_UEFI_DSBR_REVISION) { + ret = -EINVAL; + IWL_DEBUG_RADIO(fwrt, "Unsupported UEFI DSBR revision:%d\n", + data->revision); + goto out; + } + *value = data->config; + IWL_DEBUG_RADIO(fwrt, "Loaded DSBR config from UEFI value: 0x%x\n", + *value); +out: + kfree(data); + return ret; +} diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.h b/drivers/net/wireless/intel/iwlwifi/fw/uefi.h index e525d449e656..0c8943a8bd01 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.h @@ -23,6 +23,7 @@ #define IWL_UEFI_DSM_NAME L"UefiCnvWlanGeneralCfg" #define IWL_UEFI_WBEM_NAME L"UefiCnvWlanWBEM" #define IWL_UEFI_PUNCTURING_NAME L"UefiCnvWlanPuncturing" +#define IWL_UEFI_DSBR_NAME L"UefiCnvCommonDSBR" #define IWL_SGOM_MAP_SIZE 339 @@ -33,13 +34,15 @@ #define IWL_UEFI_WGDS_REVISION 3 #define IWL_UEFI_MIN_PPAG_REV 1 #define IWL_UEFI_MAX_PPAG_REV 3 -#define IWL_UEFI_WTAS_REVISION 1 +#define IWL_UEFI_MIN_WTAS_REVISION 1 +#define IWL_UEFI_MAX_WTAS_REVISION 2 #define IWL_UEFI_SPLC_REVISION 0 #define IWL_UEFI_WRDD_REVISION 0 #define IWL_UEFI_ECKV_REVISION 0 #define IWL_UEFI_WBEM_REVISION 0 #define IWL_UEFI_DSM_REVISION 4 #define IWL_UEFI_PUNCTURING_REVISION 0 +#define IWL_UEFI_DSBR_REVISION 1 struct pnvm_sku_package { u8 rev; @@ -213,6 +216,20 @@ struct uefi_cnv_var_puncturing_data { u32 puncturing; } __packed; +/** + * struct uefi_cnv_wlan_dsbr_data - BIOS STEP configuration information + * @revision: the revision of the table + * @config: STEP configuration flags: + * bit 8, switch to URM depending on FW setting + * bit 9, switch to URM + * + * Platform information for STEP configuration/workarounds. + */ +struct uefi_cnv_wlan_dsbr_data { + u8 revision; + u32 config; +} __packed; + /* * This is known to be broken on v4.19 and to work on v5.4. Until we * figure out why this is the case and how to make it work, simply @@ -244,6 +261,7 @@ void iwl_uefi_get_sgom_table(struct iwl_trans *trans, struct iwl_fw_runtime *fwr int iwl_uefi_get_uats_table(struct iwl_trans *trans, struct iwl_fw_runtime *fwrt); int iwl_uefi_get_puncturing(struct iwl_fw_runtime *fwrt); +int iwl_uefi_get_dsbr(struct iwl_fw_runtime *fwrt, u32 *value); #else /* CONFIG_EFI */ static inline void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len) { @@ -346,5 +364,11 @@ int iwl_uefi_get_puncturing(struct iwl_fw_runtime *fwrt) { return 0; } + +static inline +int iwl_uefi_get_dsbr(struct iwl_fw_runtime *fwrt, u32 *value) +{ + return -ENOENT; +} #endif /* CONFIG_EFI */ #endif /* __iwl_fw_uefi__ */ |