mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-18 01:34:14 +08:00
iwlwifi patches for v5.16
* Support a new ACPI table revision; * Improvements in the device selection code; * New HW support; * Some fixes in the Geographic SAR implementation; * Support for WiFi 6E enablement via BIOS; * Support FW API version 67; * Improve debugging support; * Some fixes in session protection; * Some other small fixes, clean-ups and improvements. -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEF3LNfgb2BPWm68smoUecoho8xfoFAmF6aT8ACgkQoUecoho8 xfrpxhAAsHd1SHUxr+CcNaGHQeqS7Duus3PQFYRH72OVQLIkGQG90mbYcRRo+5Zv S1bMLct1rhM3y1XIPq6f5Afo89Pyh3TpR21RyI5/lvpBcZrtMl5RCHnQWZxz6roj lfhlrCjRPtp89I218x1v/GgmjgsAXZQksLIq0HC4Sh+z8UTXlTvACsIMnujkzbfA dEN26nMqLtVbPXoCbDOiX96359LBQaRN8gdo2CUsbJIUUmC0Yt8tfutrKg+Wqjvh pH/xL9lvf7oQRvQeg5Olwq1EC9twu4j5u57ci0rc9J/BCgnwYx0xWMzXe4Q4c4Fy 4Q5dsAgZi71PvwpCaDs2wc501pizDCuxnEMRwUtoIV/WtIerF2VVDhkZnlMDzFSA ixRN411s81O3a5uw8H2WxQv92L15c4l7gDv1QQZtarT4GIyHTn2bzC/FoeQO+UHE ezN8GWVE83YI2rfYgFVZSk/MhblmIADABF4sEYBNdhSb3iMOoknRrKL81H7PS7Cp QXuX88IhZX8NiWkmiRkZftO8gcoDV3CB8SlTkGi7M+DXGULu1W0wwoaQJenYz/q1 9mfE300AgsvyAatKVbAN9OOOoZjKmb5OPlAekK5lK8jcNR5RgZw/tkvj6SAbFrQx Ag/WGOnMmL8p8sVuj72FDe6n2IlNLKlSzr+3M3oNZJjroSej3w4= =LcUq -----END PGP SIGNATURE----- Merge tag 'iwlwifi-next-for-kalle-2021-10-28' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next iwlwifi patches for v5.16 * Support a new ACPI table revision; * Improvements in the device selection code; * New HW support; * Some fixes in the Geographic SAR implementation; * Support for WiFi 6E enablement via BIOS; * Support FW API version 67; * Improve debugging support; * Some fixes in session protection; * Some other small fixes, clean-ups and improvements. # gpg: Signature made Thu 28 Oct 2021 12:11:27 PM EEST # gpg: using RSA key 1772CD7E06F604F5A6EBCB26A1479CA21A3CC5FA # gpg: Good signature from "Luciano Roth Coelho (Luca) <luca@coelho.fi>" [full] # gpg: aka "Luciano Roth Coelho (Intel) <luciano.coelho@intel.com>" [full]
This commit is contained in:
commit
2619f904b2
@ -9,7 +9,7 @@
|
||||
#include "iwl-prph.h"
|
||||
|
||||
/* Highest firmware API version supported */
|
||||
#define IWL_22000_UCODE_API_MAX 66
|
||||
#define IWL_22000_UCODE_API_MAX 67
|
||||
|
||||
/* Lowest firmware API version supported */
|
||||
#define IWL_22000_UCODE_API_MIN 39
|
||||
|
@ -184,9 +184,11 @@ int iwl_acpi_get_dsm_u32(struct device *dev, int rev, int func,
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_acpi_get_dsm_u32);
|
||||
|
||||
union acpi_object *iwl_acpi_get_wifi_pkg(struct device *dev,
|
||||
union acpi_object *data,
|
||||
int data_size, int *tbl_rev)
|
||||
union acpi_object *iwl_acpi_get_wifi_pkg_range(struct device *dev,
|
||||
union acpi_object *data,
|
||||
int min_data_size,
|
||||
int max_data_size,
|
||||
int *tbl_rev)
|
||||
{
|
||||
int i;
|
||||
union acpi_object *wifi_pkg;
|
||||
@ -196,7 +198,7 @@ union acpi_object *iwl_acpi_get_wifi_pkg(struct device *dev,
|
||||
* describes the domain, and one more entry, otherwise there's
|
||||
* no point in reading it.
|
||||
*/
|
||||
if (WARN_ON_ONCE(data_size < 2))
|
||||
if (WARN_ON_ONCE(min_data_size < 2 || min_data_size > max_data_size))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
/*
|
||||
@ -222,7 +224,8 @@ union acpi_object *iwl_acpi_get_wifi_pkg(struct device *dev,
|
||||
|
||||
/* skip entries that are not a package with the right size */
|
||||
if (wifi_pkg->type != ACPI_TYPE_PACKAGE ||
|
||||
wifi_pkg->package.count != data_size)
|
||||
wifi_pkg->package.count < min_data_size ||
|
||||
wifi_pkg->package.count > max_data_size)
|
||||
continue;
|
||||
|
||||
domain = &wifi_pkg->package.elements[0];
|
||||
@ -236,7 +239,7 @@ union acpi_object *iwl_acpi_get_wifi_pkg(struct device *dev,
|
||||
found:
|
||||
return wifi_pkg;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_acpi_get_wifi_pkg);
|
||||
IWL_EXPORT_SYMBOL(iwl_acpi_get_wifi_pkg_range);
|
||||
|
||||
int iwl_acpi_get_tas(struct iwl_fw_runtime *fwrt,
|
||||
__le32 *block_list_array,
|
||||
@ -707,49 +710,103 @@ int iwl_sar_get_wgds_table(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
union acpi_object *wifi_pkg, *data;
|
||||
int i, j, k, ret, tbl_rev;
|
||||
int idx = 1; /* start from one to skip the domain */
|
||||
u8 num_bands;
|
||||
u8 num_bands, num_profiles;
|
||||
static const struct {
|
||||
u8 revisions;
|
||||
u8 bands;
|
||||
u8 profiles;
|
||||
u8 min_profiles;
|
||||
} rev_data[] = {
|
||||
{
|
||||
.revisions = BIT(3),
|
||||
.bands = ACPI_GEO_NUM_BANDS_REV2,
|
||||
.profiles = ACPI_NUM_GEO_PROFILES_REV3,
|
||||
.min_profiles = 3,
|
||||
},
|
||||
{
|
||||
.revisions = BIT(2),
|
||||
.bands = ACPI_GEO_NUM_BANDS_REV2,
|
||||
.profiles = ACPI_NUM_GEO_PROFILES,
|
||||
},
|
||||
{
|
||||
.revisions = BIT(0) | BIT(1),
|
||||
.bands = ACPI_GEO_NUM_BANDS_REV0,
|
||||
.profiles = ACPI_NUM_GEO_PROFILES,
|
||||
},
|
||||
};
|
||||
int idx;
|
||||
/* start from one to skip the domain */
|
||||
int entry_idx = 1;
|
||||
|
||||
BUILD_BUG_ON(ACPI_NUM_GEO_PROFILES_REV3 != IWL_NUM_GEO_PROFILES_V3);
|
||||
BUILD_BUG_ON(ACPI_NUM_GEO_PROFILES != IWL_NUM_GEO_PROFILES);
|
||||
|
||||
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_REV2,
|
||||
&tbl_rev);
|
||||
if (!IS_ERR(wifi_pkg)) {
|
||||
if (tbl_rev != 2) {
|
||||
ret = PTR_ERR(wifi_pkg);
|
||||
goto out_free;
|
||||
/* read the highest revision we understand first */
|
||||
for (idx = 0; idx < ARRAY_SIZE(rev_data); idx++) {
|
||||
/* min_profiles != 0 requires num_profiles header */
|
||||
u32 hdr_size = 1 + !!rev_data[idx].min_profiles;
|
||||
u32 profile_size = ACPI_GEO_PER_CHAIN_SIZE *
|
||||
rev_data[idx].bands;
|
||||
u32 max_size = hdr_size + profile_size * rev_data[idx].profiles;
|
||||
u32 min_size;
|
||||
|
||||
if (!rev_data[idx].min_profiles)
|
||||
min_size = max_size;
|
||||
else
|
||||
min_size = hdr_size +
|
||||
profile_size * rev_data[idx].min_profiles;
|
||||
|
||||
wifi_pkg = iwl_acpi_get_wifi_pkg_range(fwrt->dev, data,
|
||||
min_size, max_size,
|
||||
&tbl_rev);
|
||||
if (!IS_ERR(wifi_pkg)) {
|
||||
if (!(BIT(tbl_rev) & rev_data[idx].revisions))
|
||||
continue;
|
||||
|
||||
num_bands = rev_data[idx].bands;
|
||||
num_profiles = rev_data[idx].profiles;
|
||||
|
||||
if (rev_data[idx].min_profiles) {
|
||||
/* read header that says # of profiles */
|
||||
union acpi_object *entry;
|
||||
|
||||
entry = &wifi_pkg->package.elements[entry_idx];
|
||||
entry_idx++;
|
||||
if (entry->type != ACPI_TYPE_INTEGER ||
|
||||
entry->integer.value > num_profiles) {
|
||||
ret = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
num_profiles = entry->integer.value;
|
||||
|
||||
/*
|
||||
* this also validates >= min_profiles since we
|
||||
* otherwise wouldn't have gotten the data when
|
||||
* looking up in ACPI
|
||||
*/
|
||||
if (wifi_pkg->package.count !=
|
||||
min_size + profile_size * num_profiles) {
|
||||
ret = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
}
|
||||
goto read_table;
|
||||
}
|
||||
|
||||
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);
|
||||
if (idx < ARRAY_SIZE(rev_data))
|
||||
ret = PTR_ERR(wifi_pkg);
|
||||
else
|
||||
ret = -ENOENT;
|
||||
goto out_free;
|
||||
|
||||
read_table:
|
||||
fwrt->geo_rev = tbl_rev;
|
||||
for (i = 0; i < ACPI_NUM_GEO_PROFILES; i++) {
|
||||
for (i = 0; i < num_profiles; i++) {
|
||||
for (j = 0; j < ACPI_GEO_NUM_BANDS_REV2; j++) {
|
||||
union acpi_object *entry;
|
||||
|
||||
@ -762,7 +819,8 @@ read_table:
|
||||
fwrt->geo_profiles[i].bands[j].max =
|
||||
fwrt->geo_profiles[i].bands[1].max;
|
||||
} else {
|
||||
entry = &wifi_pkg->package.elements[idx++];
|
||||
entry = &wifi_pkg->package.elements[entry_idx];
|
||||
entry_idx++;
|
||||
if (entry->type != ACPI_TYPE_INTEGER ||
|
||||
entry->integer.value > U8_MAX) {
|
||||
ret = -EINVAL;
|
||||
@ -779,7 +837,8 @@ read_table:
|
||||
fwrt->geo_profiles[i].bands[j].chains[k] =
|
||||
fwrt->geo_profiles[i].bands[1].chains[k];
|
||||
} else {
|
||||
entry = &wifi_pkg->package.elements[idx++];
|
||||
entry = &wifi_pkg->package.elements[entry_idx];
|
||||
entry_idx++;
|
||||
if (entry->type != ACPI_TYPE_INTEGER ||
|
||||
entry->integer.value > U8_MAX) {
|
||||
ret = -EINVAL;
|
||||
@ -803,10 +862,10 @@ IWL_EXPORT_SYMBOL(iwl_sar_get_wgds_table);
|
||||
bool iwl_sar_geo_support(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
/*
|
||||
* The GEO_TX_POWER_LIMIT command is not supported on earlier
|
||||
* firmware versions. Unfortunately, we don't have a TLV API
|
||||
* flag to rely on, so rely on the major version which is in
|
||||
* the first byte of ucode_ver. This was implemented
|
||||
* The PER_CHAIN_LIMIT_OFFSET_CMD command is not supported on
|
||||
* earlier firmware versions. Unfortunately, we don't have a
|
||||
* TLV API flag to rely on, so rely on the major version which
|
||||
* is in the first byte of ucode_ver. This was implemented
|
||||
* initially on version 38 and then backported to 17. It was
|
||||
* also backported to 29, but only for 7265D devices. The
|
||||
* intention was to have it in 36 as well, but not all 8000
|
||||
@ -822,14 +881,15 @@ bool iwl_sar_geo_support(struct iwl_fw_runtime *fwrt)
|
||||
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)
|
||||
struct iwl_per_chain_offset *table,
|
||||
u32 n_bands, u32 n_profiles)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
if (!iwl_sar_geo_support(fwrt))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
for (i = 0; i < ACPI_NUM_GEO_PROFILES; i++) {
|
||||
for (i = 0; i < n_profiles; i++) {
|
||||
for (j = 0; j < n_bands; j++) {
|
||||
struct iwl_per_chain_offset *chain =
|
||||
&table[i * n_bands + j];
|
||||
|
@ -29,6 +29,7 @@
|
||||
#define ACPI_SAR_PROFILE_NUM 4
|
||||
|
||||
#define ACPI_NUM_GEO_PROFILES 3
|
||||
#define ACPI_NUM_GEO_PROFILES_REV3 8
|
||||
#define ACPI_GEO_PER_CHAIN_SIZE 3
|
||||
|
||||
#define ACPI_SAR_NUM_CHAINS_REV0 2
|
||||
@ -59,13 +60,6 @@
|
||||
#define ACPI_GEO_NUM_BANDS_REV2 3
|
||||
#define ACPI_GEO_NUM_CHAINS 2
|
||||
|
||||
#define ACPI_WGDS_WIFI_DATA_SIZE_REV0 (ACPI_NUM_GEO_PROFILES * \
|
||||
ACPI_GEO_NUM_BANDS_REV0 * \
|
||||
ACPI_GEO_PER_CHAIN_SIZE + 1)
|
||||
#define ACPI_WGDS_WIFI_DATA_SIZE_REV2 (ACPI_NUM_GEO_PROFILES * \
|
||||
ACPI_GEO_NUM_BANDS_REV2 * \
|
||||
ACPI_GEO_PER_CHAIN_SIZE + 1)
|
||||
|
||||
#define ACPI_WRDD_WIFI_DATA_SIZE 2
|
||||
#define ACPI_SPLC_WIFI_DATA_SIZE 2
|
||||
#define ACPI_ECKV_WIFI_DATA_SIZE 2
|
||||
@ -115,6 +109,7 @@ enum iwl_dsm_funcs_rev_0 {
|
||||
DSM_FUNC_QUERY = 0,
|
||||
DSM_FUNC_DISABLE_SRD = 1,
|
||||
DSM_FUNC_ENABLE_INDONESIA_5G2 = 2,
|
||||
DSM_FUNC_ENABLE_6E = 3,
|
||||
DSM_FUNC_11AX_ENABLEMENT = 6,
|
||||
DSM_FUNC_ENABLE_UNII4_CHAN = 7,
|
||||
DSM_FUNC_ACTIVATE_CHANNEL = 8
|
||||
@ -159,10 +154,11 @@ int iwl_acpi_get_dsm_u8(struct device *dev, int rev, int func,
|
||||
int iwl_acpi_get_dsm_u32(struct device *dev, int rev, int func,
|
||||
const guid_t *guid, u32 *value);
|
||||
|
||||
union acpi_object *iwl_acpi_get_wifi_pkg(struct device *dev,
|
||||
union acpi_object *data,
|
||||
int data_size, int *tbl_rev);
|
||||
|
||||
union acpi_object *iwl_acpi_get_wifi_pkg_range(struct device *dev,
|
||||
union acpi_object *data,
|
||||
int min_data_size,
|
||||
int max_data_size,
|
||||
int *tbl_rev);
|
||||
/**
|
||||
* iwl_acpi_get_mcc - read MCC from ACPI, if available
|
||||
*
|
||||
@ -199,7 +195,8 @@ int iwl_sar_get_wgds_table(struct iwl_fw_runtime *fwrt);
|
||||
bool iwl_sar_geo_support(struct iwl_fw_runtime *fwrt);
|
||||
|
||||
int iwl_sar_geo_init(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_per_chain_offset *table, u32 n_bands);
|
||||
struct iwl_per_chain_offset *table,
|
||||
u32 n_bands, u32 n_profiles);
|
||||
|
||||
int iwl_acpi_get_tas(struct iwl_fw_runtime *fwrt, __le32 *block_list_array,
|
||||
int *block_list_size);
|
||||
@ -231,10 +228,11 @@ static inline int iwl_acpi_get_dsm_u32(struct device *dev, int rev, int func,
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static inline union acpi_object *iwl_acpi_get_wifi_pkg(struct device *dev,
|
||||
union acpi_object *data,
|
||||
int data_size,
|
||||
int *tbl_rev)
|
||||
static inline union acpi_object *
|
||||
iwl_acpi_get_wifi_pkg_range(struct device *dev,
|
||||
union acpi_object *data,
|
||||
int min_data_size, int max_data_size,
|
||||
int *tbl_rev)
|
||||
{
|
||||
return ERR_PTR(-ENOENT);
|
||||
}
|
||||
@ -294,4 +292,14 @@ static inline __le32 iwl_acpi_get_lari_config_bitmap(struct iwl_fw_runtime *fwrt
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ACPI */
|
||||
|
||||
static inline union acpi_object *
|
||||
iwl_acpi_get_wifi_pkg(struct device *dev,
|
||||
union acpi_object *data,
|
||||
int data_size, int *tbl_rev)
|
||||
{
|
||||
return iwl_acpi_get_wifi_pkg_range(dev, data, data_size, data_size,
|
||||
tbl_rev);
|
||||
}
|
||||
|
||||
#endif /* __iwl_fw_acpi__ */
|
||||
|
@ -693,49 +693,6 @@ struct iwl_wowlan_status_v9 {
|
||||
u8 wake_packet[]; /* can be truncated from _length to _bufsize */
|
||||
} __packed; /* WOWLAN_STATUSES_RSP_API_S_VER_9 */
|
||||
|
||||
/**
|
||||
* struct iwl_wowlan_status - WoWLAN status
|
||||
* @gtk: GTK data
|
||||
* @igtk: IGTK data
|
||||
* @bigtk: BIGTK data
|
||||
* @replay_ctr: GTK rekey replay counter
|
||||
* @pattern_number: number of the matched pattern
|
||||
* @non_qos_seq_ctr: non-QoS sequence counter to use next
|
||||
* @qos_seq_ctr: QoS sequence counters to use next
|
||||
* @wakeup_reasons: wakeup reasons, see &enum iwl_wowlan_wakeup_reason
|
||||
* @num_of_gtk_rekeys: number of GTK rekeys
|
||||
* @tid_tear_down: bitmap of TIDs torn down
|
||||
* @reserved: reserved
|
||||
* @received_beacons: number of received beacons
|
||||
* @wake_packet_length: wakeup packet length
|
||||
* @wake_packet_bufsize: wakeup packet buffer size
|
||||
* @tid_tear_down: bit mask of tids whose BA sessions were closed
|
||||
* in suspend state
|
||||
* @wake_packet: wakeup packet
|
||||
*/
|
||||
struct iwl_wowlan_status {
|
||||
struct iwl_wowlan_gtk_status gtk[1];
|
||||
struct iwl_wowlan_igtk_status igtk[1];
|
||||
struct iwl_wowlan_igtk_status bigtk[WOWLAN_IGTK_KEYS_NUM];
|
||||
__le64 replay_ctr;
|
||||
__le16 pattern_number;
|
||||
__le16 non_qos_seq_ctr;
|
||||
__le16 qos_seq_ctr[8];
|
||||
__le32 wakeup_reasons;
|
||||
__le32 num_of_gtk_rekeys;
|
||||
u8 tid_tear_down;
|
||||
u8 reserved[3];
|
||||
__le32 received_beacons;
|
||||
__le32 wake_packet_length;
|
||||
__le32 wake_packet_bufsize;
|
||||
u8 wake_packet[]; /* can be truncated from _length to _bufsize */
|
||||
} __packed; /* WOWLAN_STATUSES_API_S_VER_11 */
|
||||
|
||||
static inline u8 iwlmvm_wowlan_gtk_idx(struct iwl_wowlan_gtk_status *gtk)
|
||||
{
|
||||
return gtk->key_flags & IWL_WOWLAN_GTK_IDX_MASK;
|
||||
}
|
||||
|
||||
/* TODO: NetDetect API */
|
||||
|
||||
#endif /* __iwl_fw_api_d3_h__ */
|
||||
|
@ -379,6 +379,23 @@ struct iwl_dram_info {
|
||||
struct iwl_buf_alloc_cmd dram_frags[IWL_FW_INI_ALLOCATION_NUM - 1];
|
||||
} __packed; /* INIT_DRAM_FRAGS_ALLOCATIONS_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_dbgc1_info - DBGC1 address and size
|
||||
*
|
||||
* Driver will fill the dbcg1 address and size at address based on config TLV.
|
||||
*
|
||||
* @first_word: all 0 set as identifier
|
||||
* @dbgc1_add_lsb: LSB bits of DBGC1 physical address
|
||||
* @dbgc1_add_msb: MSB bits of DBGC1 physical address
|
||||
* @dbgc1_size: DBGC1 size
|
||||
*/
|
||||
struct iwl_dbgc1_info {
|
||||
__le32 first_word;
|
||||
__le32 dbgc1_add_lsb;
|
||||
__le32 dbgc1_add_msb;
|
||||
__le32 dbgc1_size;
|
||||
} __packed; /* INIT_DRAM_FRAGS_ALLOCATIONS_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_dbg_host_event_cfg_cmd
|
||||
* @enabled_severities: enabled severities
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2019 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2019, 2021 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
@ -39,9 +39,9 @@ enum iwl_mac_conf_subcmd_ids {
|
||||
PROBE_RESPONSE_DATA_NOTIF = 0xFC,
|
||||
|
||||
/**
|
||||
* @CHANNEL_SWITCH_NOA_NOTIF: &struct iwl_channel_switch_noa_notif
|
||||
* @CHANNEL_SWITCH_START_NOTIF: &struct iwl_channel_switch_start_notif
|
||||
*/
|
||||
CHANNEL_SWITCH_NOA_NOTIF = 0xFF,
|
||||
CHANNEL_SWITCH_START_NOTIF = 0xFF,
|
||||
};
|
||||
|
||||
#define IWL_P2P_NOA_DESC_COUNT (2)
|
||||
@ -102,11 +102,11 @@ struct iwl_missed_vap_notif {
|
||||
} __packed; /* MISSED_VAP_NTFY_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_channel_switch_noa_notif - Channel switch NOA notification
|
||||
* struct iwl_channel_switch_start_notif - Channel switch start notification
|
||||
*
|
||||
* @id_and_color: ID and color of the MAC
|
||||
*/
|
||||
struct iwl_channel_switch_noa_notif {
|
||||
struct iwl_channel_switch_start_notif {
|
||||
__le32 id_and_color;
|
||||
} __packed; /* CHANNEL_SWITCH_START_NTFY_API_S_VER_1 */
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2019-2020 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2019-2021 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
@ -29,9 +29,9 @@ enum iwl_phy_ops_subcmd_ids {
|
||||
TEMP_REPORTING_THRESHOLDS_CMD = 0x04,
|
||||
|
||||
/**
|
||||
* @GEO_TX_POWER_LIMIT: &struct iwl_geo_tx_power_profiles_cmd
|
||||
* @PER_CHAIN_LIMIT_OFFSET_CMD: &struct iwl_geo_tx_power_profiles_cmd
|
||||
*/
|
||||
GEO_TX_POWER_LIMIT = 0x05,
|
||||
PER_CHAIN_LIMIT_OFFSET_CMD = 0x05,
|
||||
|
||||
/**
|
||||
* @PER_PLATFORM_ANT_GAIN_CMD: &struct iwl_ppag_table_cmd
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2020 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2021 Intel Corporation
|
||||
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2015-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
@ -378,9 +378,10 @@ struct iwl_dev_tx_power_cmd {
|
||||
};
|
||||
};
|
||||
|
||||
#define IWL_NUM_GEO_PROFILES 3
|
||||
#define IWL_NUM_BANDS_PER_CHAIN_V1 2
|
||||
#define IWL_NUM_BANDS_PER_CHAIN_V2 3
|
||||
#define IWL_NUM_GEO_PROFILES 3
|
||||
#define IWL_NUM_GEO_PROFILES_V3 8
|
||||
#define IWL_NUM_BANDS_PER_CHAIN_V1 2
|
||||
#define IWL_NUM_BANDS_PER_CHAIN_V2 3
|
||||
|
||||
/**
|
||||
* enum iwl_geo_per_chain_offset_operation - type of operation
|
||||
@ -390,10 +391,10 @@ struct iwl_dev_tx_power_cmd {
|
||||
enum iwl_geo_per_chain_offset_operation {
|
||||
IWL_PER_CHAIN_OFFSET_SET_TABLES,
|
||||
IWL_PER_CHAIN_OFFSET_GET_CURRENT_TABLE,
|
||||
}; /* GEO_TX_POWER_LIMIT FLAGS TYPE */
|
||||
}; /* PER_CHAIN_OFFSET_OPERATION_E */
|
||||
|
||||
/**
|
||||
* struct iwl_per_chain_offset - embedded struct for GEO_TX_POWER_LIMIT.
|
||||
* struct iwl_per_chain_offset - embedded struct for PER_CHAIN_LIMIT_OFFSET_CMD.
|
||||
* @max_tx_power: maximum allowed tx power.
|
||||
* @chain_a: tx power offset for chain a.
|
||||
* @chain_b: tx power offset for chain b.
|
||||
@ -405,17 +406,17 @@ struct iwl_per_chain_offset {
|
||||
} __packed; /* PER_CHAIN_LIMIT_OFFSET_PER_CHAIN_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_geo_tx_power_profile_cmd_v1 - struct for GEO_TX_POWER_LIMIT cmd.
|
||||
* struct iwl_geo_tx_power_profile_cmd_v1 - struct for PER_CHAIN_LIMIT_OFFSET_CMD cmd.
|
||||
* @ops: operations, value from &enum iwl_geo_per_chain_offset_operation
|
||||
* @table: offset profile per band.
|
||||
*/
|
||||
struct iwl_geo_tx_power_profiles_cmd_v1 {
|
||||
__le32 ops;
|
||||
struct iwl_per_chain_offset table[IWL_NUM_GEO_PROFILES][IWL_NUM_BANDS_PER_CHAIN_V1];
|
||||
} __packed; /* GEO_TX_POWER_LIMIT_VER_1 */
|
||||
} __packed; /* PER_CHAIN_LIMIT_OFFSET_CMD_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_geo_tx_power_profile_cmd_v2 - struct for GEO_TX_POWER_LIMIT cmd.
|
||||
* struct iwl_geo_tx_power_profile_cmd_v2 - struct for PER_CHAIN_LIMIT_OFFSET_CMD cmd.
|
||||
* @ops: operations, value from &enum iwl_geo_per_chain_offset_operation
|
||||
* @table: offset profile per band.
|
||||
* @table_revision: BIOS table revision.
|
||||
@ -424,10 +425,10 @@ struct iwl_geo_tx_power_profiles_cmd_v2 {
|
||||
__le32 ops;
|
||||
struct iwl_per_chain_offset table[IWL_NUM_GEO_PROFILES][IWL_NUM_BANDS_PER_CHAIN_V1];
|
||||
__le32 table_revision;
|
||||
} __packed; /* GEO_TX_POWER_LIMIT_VER_2 */
|
||||
} __packed; /* PER_CHAIN_LIMIT_OFFSET_CMD_VER_2 */
|
||||
|
||||
/**
|
||||
* struct iwl_geo_tx_power_profile_cmd_v3 - struct for GEO_TX_POWER_LIMIT cmd.
|
||||
* struct iwl_geo_tx_power_profile_cmd_v3 - struct for PER_CHAIN_LIMIT_OFFSET_CMD cmd.
|
||||
* @ops: operations, value from &enum iwl_geo_per_chain_offset_operation
|
||||
* @table: offset profile per band.
|
||||
* @table_revision: BIOS table revision.
|
||||
@ -436,21 +437,47 @@ struct iwl_geo_tx_power_profiles_cmd_v3 {
|
||||
__le32 ops;
|
||||
struct iwl_per_chain_offset table[IWL_NUM_GEO_PROFILES][IWL_NUM_BANDS_PER_CHAIN_V2];
|
||||
__le32 table_revision;
|
||||
} __packed; /* GEO_TX_POWER_LIMIT_VER_3 */
|
||||
} __packed; /* PER_CHAIN_LIMIT_OFFSET_CMD_VER_3 */
|
||||
|
||||
/**
|
||||
* struct iwl_geo_tx_power_profile_cmd_v4 - struct for PER_CHAIN_LIMIT_OFFSET_CMD cmd.
|
||||
* @ops: operations, value from &enum iwl_geo_per_chain_offset_operation
|
||||
* @table: offset profile per band.
|
||||
* @table_revision: BIOS table revision.
|
||||
*/
|
||||
struct iwl_geo_tx_power_profiles_cmd_v4 {
|
||||
__le32 ops;
|
||||
struct iwl_per_chain_offset table[IWL_NUM_GEO_PROFILES_V3][IWL_NUM_BANDS_PER_CHAIN_V1];
|
||||
__le32 table_revision;
|
||||
} __packed; /* PER_CHAIN_LIMIT_OFFSET_CMD_VER_4 */
|
||||
|
||||
/**
|
||||
* struct iwl_geo_tx_power_profile_cmd_v5 - struct for PER_CHAIN_LIMIT_OFFSET_CMD cmd.
|
||||
* @ops: operations, value from &enum iwl_geo_per_chain_offset_operation
|
||||
* @table: offset profile per band.
|
||||
* @table_revision: BIOS table revision.
|
||||
*/
|
||||
struct iwl_geo_tx_power_profiles_cmd_v5 {
|
||||
__le32 ops;
|
||||
struct iwl_per_chain_offset table[IWL_NUM_GEO_PROFILES_V3][IWL_NUM_BANDS_PER_CHAIN_V2];
|
||||
__le32 table_revision;
|
||||
} __packed; /* PER_CHAIN_LIMIT_OFFSET_CMD_VER_5 */
|
||||
|
||||
union iwl_geo_tx_power_profiles_cmd {
|
||||
struct iwl_geo_tx_power_profiles_cmd_v1 v1;
|
||||
struct iwl_geo_tx_power_profiles_cmd_v2 v2;
|
||||
struct iwl_geo_tx_power_profiles_cmd_v3 v3;
|
||||
struct iwl_geo_tx_power_profiles_cmd_v4 v4;
|
||||
struct iwl_geo_tx_power_profiles_cmd_v5 v5;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_geo_tx_power_profiles_resp - response to GEO_TX_POWER_LIMIT cmd
|
||||
* struct iwl_geo_tx_power_profiles_resp - response to PER_CHAIN_LIMIT_OFFSET_CMD cmd
|
||||
* @profile_idx: current geo profile in use
|
||||
*/
|
||||
struct iwl_geo_tx_power_profiles_resp {
|
||||
__le32 profile_idx;
|
||||
} __packed; /* GEO_TX_POWER_LIMIT_RESP */
|
||||
} __packed; /* PER_CHAIN_LIMIT_OFFSET_RSP */
|
||||
|
||||
/**
|
||||
* union iwl_ppag_table_cmd - union for all versions of PPAG command
|
||||
|
@ -28,6 +28,8 @@
|
||||
* @STA_FLG_MAX_AGG_SIZE_256K: maximal size for A-MPDU (256k supported)
|
||||
* @STA_FLG_MAX_AGG_SIZE_512K: maximal size for A-MPDU (512k supported)
|
||||
* @STA_FLG_MAX_AGG_SIZE_1024K: maximal size for A-MPDU (1024k supported)
|
||||
* @STA_FLG_MAX_AGG_SIZE_2M: maximal size for A-MPDU (2M supported)
|
||||
* @STA_FLG_MAX_AGG_SIZE_4M: maximal size for A-MPDU (4M supported)
|
||||
* @STA_FLG_AGG_MPDU_DENS_MSK: maximal MPDU density for Tx aggregation
|
||||
* @STA_FLG_FAT_EN_MSK: support for channel width (for Tx). This flag is
|
||||
* initialised by driver and can be updated by fw upon reception of
|
||||
|
@ -421,6 +421,7 @@ enum iwl_ucode_tlv_capa {
|
||||
IWL_UCODE_TLV_CAPA_HIDDEN_6GHZ_SCAN = (__force iwl_ucode_tlv_capa_t)59,
|
||||
IWL_UCODE_TLV_CAPA_BROADCAST_TWT = (__force iwl_ucode_tlv_capa_t)60,
|
||||
IWL_UCODE_TLV_CAPA_COEX_HIGH_PRIO = (__force iwl_ucode_tlv_capa_t)61,
|
||||
IWL_UCODE_TLV_CAPA_RFIM_SUPPORT = (__force iwl_ucode_tlv_capa_t)62,
|
||||
|
||||
/* set 2 */
|
||||
IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE = (__force iwl_ucode_tlv_capa_t)64,
|
||||
@ -454,7 +455,6 @@ enum iwl_ucode_tlv_capa {
|
||||
IWL_UCODE_TLV_CAPA_PSC_CHAN_SUPPORT = (__force iwl_ucode_tlv_capa_t)98,
|
||||
|
||||
IWL_UCODE_TLV_CAPA_BIGTK_SUPPORT = (__force iwl_ucode_tlv_capa_t)100,
|
||||
IWL_UCODE_TLV_CAPA_RFIM_SUPPORT = (__force iwl_ucode_tlv_capa_t)102,
|
||||
IWL_UCODE_TLV_CAPA_DRAM_FRAG_SUPPORT = (__force iwl_ucode_tlv_capa_t)104,
|
||||
|
||||
#ifdef __CHECKER__
|
||||
|
@ -154,7 +154,7 @@ struct iwl_fw_runtime {
|
||||
struct iwl_sar_profile sar_profiles[ACPI_SAR_PROFILE_NUM];
|
||||
u8 sar_chain_a_profile;
|
||||
u8 sar_chain_b_profile;
|
||||
struct iwl_geo_profile geo_profiles[ACPI_NUM_GEO_PROFILES];
|
||||
struct iwl_geo_profile geo_profiles[ACPI_NUM_GEO_PROFILES_REV3];
|
||||
u32 geo_rev;
|
||||
union iwl_ppag_table_cmd ppag_table;
|
||||
u32 ppag_ver;
|
||||
|
@ -2,7 +2,8 @@
|
||||
/*
|
||||
* Copyright(c) 2021 Intel Corporation
|
||||
*/
|
||||
|
||||
#ifndef __iwl_fw_uefi__
|
||||
#define __iwl_fw_uefi__
|
||||
|
||||
#define IWL_UEFI_OEM_PNVM_NAME L"UefiCnvWlanOemSignedPnvm"
|
||||
#define IWL_UEFI_REDUCED_POWER_NAME L"UefiCnvWlanReducedPower"
|
||||
@ -40,3 +41,5 @@ void *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len)
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
}
|
||||
#endif /* CONFIG_EFI */
|
||||
|
||||
#endif /* __iwl_fw_uefi__ */
|
||||
|
@ -605,6 +605,7 @@ enum msix_hw_int_causes {
|
||||
MSIX_HW_INT_CAUSES_REG_WAKEUP = BIT(1),
|
||||
MSIX_HW_INT_CAUSES_REG_IML = BIT(1),
|
||||
MSIX_HW_INT_CAUSES_REG_RESET_DONE = BIT(2),
|
||||
MSIX_HW_INT_CAUSES_REG_SW_ERR_BZ = BIT(5),
|
||||
MSIX_HW_INT_CAUSES_REG_CT_KILL = BIT(6),
|
||||
MSIX_HW_INT_CAUSES_REG_RF_KILL = BIT(7),
|
||||
MSIX_HW_INT_CAUSES_REG_PERIODIC = BIT(8),
|
||||
|
@ -284,13 +284,6 @@ static int iwl_dbg_tlv_config_set(struct iwl_trans *trans,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (type != IWL_FW_INI_CONFIG_SET_TYPE_PERIPH_SCRATCH_HWM ||
|
||||
trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210) {
|
||||
IWL_DEBUG_FW(trans,
|
||||
"WRT: Config set type %u is not supported\n", type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return iwl_dbg_tlv_add(tlv, &trans->dbg.time_point[tp].config_list);
|
||||
}
|
||||
|
||||
@ -812,18 +805,84 @@ static void iwl_dbg_tlv_apply_config(struct iwl_fw_runtime *fwrt,
|
||||
|
||||
list_for_each_entry(node, config_list, list) {
|
||||
struct iwl_fw_ini_conf_set_tlv *config_list = (void *)node->tlv.data;
|
||||
u32 count, address, value;
|
||||
u32 len = (le32_to_cpu(node->tlv.length) - sizeof(*config_list)) / 8;
|
||||
u32 type = le32_to_cpu(config_list->set_type);
|
||||
u32 offset = le32_to_cpu(config_list->addr_offset);
|
||||
|
||||
switch (type) {
|
||||
case IWL_FW_INI_CONFIG_SET_TYPE_PERIPH_SCRATCH_HWM: {
|
||||
u32 debug_token_config =
|
||||
le32_to_cpu(config_list->addr_val[0].value);
|
||||
|
||||
IWL_DEBUG_FW(fwrt, "WRT: Setting HWM debug token config: %u\n",
|
||||
debug_token_config);
|
||||
fwrt->trans->dbg.ucode_preset = debug_token_config;
|
||||
break;
|
||||
case IWL_FW_INI_CONFIG_SET_TYPE_DEVICE_PERIPHERY_MAC: {
|
||||
if (!iwl_trans_grab_nic_access(fwrt->trans)) {
|
||||
IWL_DEBUG_FW(fwrt, "WRT: failed to get nic access\n");
|
||||
IWL_DEBUG_FW(fwrt, "WRT: skipping MAC PERIPHERY config\n");
|
||||
continue;
|
||||
}
|
||||
IWL_DEBUG_FW(fwrt, "WRT: MAC PERIPHERY config len: len %u\n", len);
|
||||
for (count = 0; count < len; count++) {
|
||||
address = le32_to_cpu(config_list->addr_val[count].address);
|
||||
value = le32_to_cpu(config_list->addr_val[count].value);
|
||||
iwl_trans_write_prph(fwrt->trans, address + offset, value);
|
||||
}
|
||||
iwl_trans_release_nic_access(fwrt->trans);
|
||||
break;
|
||||
}
|
||||
case IWL_FW_INI_CONFIG_SET_TYPE_DEVICE_MEMORY: {
|
||||
for (count = 0; count < len; count++) {
|
||||
address = le32_to_cpu(config_list->addr_val[count].address);
|
||||
value = le32_to_cpu(config_list->addr_val[count].value);
|
||||
iwl_trans_write_mem32(fwrt->trans, address + offset, value);
|
||||
IWL_DEBUG_FW(fwrt, "WRT: DEV_MEM: count %u, add: %u val: %u\n",
|
||||
count, address, value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IWL_FW_INI_CONFIG_SET_TYPE_CSR: {
|
||||
for (count = 0; count < len; count++) {
|
||||
address = le32_to_cpu(config_list->addr_val[count].address);
|
||||
value = le32_to_cpu(config_list->addr_val[count].value);
|
||||
iwl_write32(fwrt->trans, address + offset, value);
|
||||
IWL_DEBUG_FW(fwrt, "WRT: CSR: count %u, add: %u val: %u\n",
|
||||
count, address, value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IWL_FW_INI_CONFIG_SET_TYPE_DBGC_DRAM_ADDR: {
|
||||
struct iwl_dbgc1_info dram_info = {};
|
||||
struct iwl_dram_data *frags = &fwrt->trans->dbg.fw_mon_ini[1].frags[0];
|
||||
__le64 dram_base_addr = cpu_to_le64(frags->physical);
|
||||
__le32 dram_size = cpu_to_le32(frags->size);
|
||||
u64 dram_addr = le64_to_cpu(dram_base_addr);
|
||||
u32 ret;
|
||||
|
||||
IWL_DEBUG_FW(fwrt, "WRT: dram_base_addr 0x%016llx, dram_size 0x%x\n",
|
||||
dram_base_addr, dram_size);
|
||||
IWL_DEBUG_FW(fwrt, "WRT: config_list->addr_offset: %u\n",
|
||||
le32_to_cpu(config_list->addr_offset));
|
||||
for (count = 0; count < len; count++) {
|
||||
address = le32_to_cpu(config_list->addr_val[count].address);
|
||||
dram_info.dbgc1_add_lsb =
|
||||
cpu_to_le32((dram_addr & 0x00000000FFFFFFFFULL) + 0x400);
|
||||
dram_info.dbgc1_add_msb =
|
||||
cpu_to_le32((dram_addr & 0xFFFFFFFF00000000ULL) >> 32);
|
||||
dram_info.dbgc1_size = cpu_to_le32(le32_to_cpu(dram_size) - 0x400);
|
||||
ret = iwl_trans_write_mem(fwrt->trans,
|
||||
address + offset, &dram_info, 4);
|
||||
if (ret) {
|
||||
IWL_ERR(fwrt, "Failed to write dram_info to HW_SMEM\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IWL_FW_INI_CONFIG_SET_TYPE_PERIPH_SCRATCH_HWM: {
|
||||
u32 debug_token_config =
|
||||
le32_to_cpu(config_list->addr_val[0].value);
|
||||
|
||||
IWL_DEBUG_FW(fwrt, "WRT: Setting HWM debug token config: %u\n",
|
||||
debug_token_config);
|
||||
fwrt->trans->dbg.ucode_preset = debug_token_config;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -1229,6 +1288,7 @@ void _iwl_dbg_tlv_time_point(struct iwl_fw_runtime *fwrt,
|
||||
case IWL_FW_INI_TIME_POINT_AFTER_ALIVE:
|
||||
iwl_dbg_tlv_apply_buffers(fwrt);
|
||||
iwl_dbg_tlv_send_hcmds(fwrt, hcmd_list);
|
||||
iwl_dbg_tlv_apply_config(fwrt, conf_list);
|
||||
iwl_dbg_tlv_tp_trigger(fwrt, sync, trig_list, tp_data, NULL);
|
||||
break;
|
||||
case IWL_FW_INI_TIME_POINT_PERIODIC:
|
||||
@ -1239,11 +1299,13 @@ void _iwl_dbg_tlv_time_point(struct iwl_fw_runtime *fwrt,
|
||||
case IWL_FW_INI_TIME_POINT_MISSED_BEACONS:
|
||||
case IWL_FW_INI_TIME_POINT_FW_DHC_NOTIFICATION:
|
||||
iwl_dbg_tlv_send_hcmds(fwrt, hcmd_list);
|
||||
iwl_dbg_tlv_apply_config(fwrt, conf_list);
|
||||
iwl_dbg_tlv_tp_trigger(fwrt, sync, trig_list, tp_data,
|
||||
iwl_dbg_tlv_check_fw_pkt);
|
||||
break;
|
||||
default:
|
||||
iwl_dbg_tlv_send_hcmds(fwrt, hcmd_list);
|
||||
iwl_dbg_tlv_apply_config(fwrt, conf_list);
|
||||
iwl_dbg_tlv_tp_trigger(fwrt, sync, trig_list, tp_data, NULL);
|
||||
break;
|
||||
}
|
||||
|
@ -398,6 +398,47 @@ int iwl_dump_fh(struct iwl_trans *trans, char **buf)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define IWL_HOST_MON_BLOCK_PEMON 0x00
|
||||
#define IWL_HOST_MON_BLOCK_HIPM 0x22
|
||||
|
||||
#define IWL_HOST_MON_BLOCK_PEMON_VEC0 0x00
|
||||
#define IWL_HOST_MON_BLOCK_PEMON_VEC1 0x01
|
||||
#define IWL_HOST_MON_BLOCK_PEMON_WFPM 0x06
|
||||
|
||||
static void iwl_dump_host_monitor_block(struct iwl_trans *trans,
|
||||
u32 block, u32 vec, u32 iter)
|
||||
{
|
||||
int i;
|
||||
|
||||
IWL_ERR(trans, "Host monitor block 0x%x vector 0x%x\n", block, vec);
|
||||
iwl_write32(trans, CSR_MONITOR_CFG_REG, (block << 8) | vec);
|
||||
for (i = 0; i < iter; i++)
|
||||
IWL_ERR(trans, " value [iter %d]: 0x%08x\n",
|
||||
i, iwl_read32(trans, CSR_MONITOR_STATUS_REG));
|
||||
}
|
||||
|
||||
static void iwl_dump_host_monitor(struct iwl_trans *trans)
|
||||
{
|
||||
switch (trans->trans_cfg->device_family) {
|
||||
case IWL_DEVICE_FAMILY_22000:
|
||||
case IWL_DEVICE_FAMILY_AX210:
|
||||
IWL_ERR(trans, "CSR_RESET = 0x%x\n",
|
||||
iwl_read32(trans, CSR_RESET));
|
||||
iwl_dump_host_monitor_block(trans, IWL_HOST_MON_BLOCK_PEMON,
|
||||
IWL_HOST_MON_BLOCK_PEMON_VEC0, 15);
|
||||
iwl_dump_host_monitor_block(trans, IWL_HOST_MON_BLOCK_PEMON,
|
||||
IWL_HOST_MON_BLOCK_PEMON_VEC1, 15);
|
||||
iwl_dump_host_monitor_block(trans, IWL_HOST_MON_BLOCK_PEMON,
|
||||
IWL_HOST_MON_BLOCK_PEMON_WFPM, 15);
|
||||
iwl_dump_host_monitor_block(trans, IWL_HOST_MON_BLOCK_HIPM,
|
||||
IWL_HOST_MON_BLOCK_PEMON_VEC0, 1);
|
||||
break;
|
||||
default:
|
||||
/* not supported yet */
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int iwl_finish_nic_init(struct iwl_trans *trans)
|
||||
{
|
||||
const struct iwl_cfg_trans_params *cfg_trans = trans->trans_cfg;
|
||||
@ -433,9 +474,12 @@ int iwl_finish_nic_init(struct iwl_trans *trans)
|
||||
* and accesses to uCode SRAM.
|
||||
*/
|
||||
err = iwl_poll_bit(trans, CSR_GP_CNTRL, poll_ready, poll_ready, 25000);
|
||||
if (err < 0)
|
||||
if (err < 0) {
|
||||
IWL_DEBUG_INFO(trans, "Failed to wake NIC\n");
|
||||
|
||||
iwl_dump_host_monitor(trans);
|
||||
}
|
||||
|
||||
if (cfg_trans->bisr_workaround) {
|
||||
/* ensure BISR shift has finished */
|
||||
udelay(200);
|
||||
|
@ -1379,12 +1379,49 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
|
||||
|
||||
/* converted data from the different status responses */
|
||||
struct iwl_wowlan_status_data {
|
||||
u16 pattern_number;
|
||||
u16 qos_seq_ctr[8];
|
||||
u64 replay_ctr;
|
||||
u32 num_of_gtk_rekeys;
|
||||
u32 received_beacons;
|
||||
u32 wakeup_reasons;
|
||||
u32 wake_packet_length;
|
||||
u32 wake_packet_bufsize;
|
||||
const u8 *wake_packet;
|
||||
u16 pattern_number;
|
||||
u16 non_qos_seq_ctr;
|
||||
u16 qos_seq_ctr[8];
|
||||
u8 tid_tear_down;
|
||||
|
||||
struct {
|
||||
/*
|
||||
* We store both the TKIP and AES representations
|
||||
* coming from the firmware because we decode the
|
||||
* data from there before we iterate the keys and
|
||||
* know which one we need.
|
||||
*/
|
||||
struct {
|
||||
struct ieee80211_key_seq seq[IWL_MAX_TID_COUNT];
|
||||
} tkip, aes;
|
||||
/* including RX MIC key for TKIP */
|
||||
u8 key[WOWLAN_KEY_MAX_SIZE];
|
||||
u8 len;
|
||||
u8 flags;
|
||||
} gtk;
|
||||
|
||||
struct {
|
||||
/* Same as above */
|
||||
struct {
|
||||
struct ieee80211_key_seq seq[IWL_MAX_TID_COUNT];
|
||||
u64 tx_pn;
|
||||
} tkip, aes;
|
||||
} ptk;
|
||||
|
||||
struct {
|
||||
u64 ipn;
|
||||
u8 key[WOWLAN_KEY_MAX_SIZE];
|
||||
u8 len;
|
||||
u8 flags;
|
||||
} igtk;
|
||||
|
||||
u8 wake_packet[];
|
||||
};
|
||||
|
||||
static void iwl_mvm_report_wakeup_reasons(struct iwl_mvm *mvm,
|
||||
@ -1540,77 +1577,90 @@ static void iwl_mvm_tkip_sc_to_seq(struct tkip_sc *sc,
|
||||
seq->tkip.iv16 = le16_to_cpu(sc->iv16);
|
||||
}
|
||||
|
||||
static void iwl_mvm_set_aes_rx_seq(struct iwl_mvm *mvm, struct aes_sc *scs,
|
||||
struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *key)
|
||||
static void iwl_mvm_set_key_rx_seq_tids(struct ieee80211_key_conf *key,
|
||||
struct ieee80211_key_seq *seq)
|
||||
{
|
||||
int tid;
|
||||
|
||||
BUILD_BUG_ON(IWL_NUM_RSC != IEEE80211_NUM_TIDS);
|
||||
|
||||
if (sta && iwl_mvm_has_new_rx_api(mvm)) {
|
||||
struct iwl_mvm_sta *mvmsta;
|
||||
struct iwl_mvm_key_pn *ptk_pn;
|
||||
|
||||
mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
|
||||
rcu_read_lock();
|
||||
ptk_pn = rcu_dereference(mvmsta->ptk_pn[key->keyidx]);
|
||||
if (WARN_ON(!ptk_pn)) {
|
||||
rcu_read_unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) {
|
||||
struct ieee80211_key_seq seq = {};
|
||||
int i;
|
||||
|
||||
iwl_mvm_aes_sc_to_seq(&scs[tid], &seq);
|
||||
ieee80211_set_key_rx_seq(key, tid, &seq);
|
||||
for (i = 1; i < mvm->trans->num_rx_queues; i++)
|
||||
memcpy(ptk_pn->q[i].pn[tid],
|
||||
seq.ccmp.pn, IEEE80211_CCMP_PN_LEN);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
} else {
|
||||
for (tid = 0; tid < IWL_NUM_RSC; tid++) {
|
||||
struct ieee80211_key_seq seq = {};
|
||||
|
||||
iwl_mvm_aes_sc_to_seq(&scs[tid], &seq);
|
||||
ieee80211_set_key_rx_seq(key, tid, &seq);
|
||||
}
|
||||
}
|
||||
for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++)
|
||||
ieee80211_set_key_rx_seq(key, tid, &seq[tid]);
|
||||
}
|
||||
|
||||
static void iwl_mvm_set_tkip_rx_seq(struct tkip_sc *scs,
|
||||
struct ieee80211_key_conf *key)
|
||||
static void iwl_mvm_set_aes_ptk_rx_seq(struct iwl_mvm *mvm,
|
||||
struct iwl_wowlan_status_data *status,
|
||||
struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *key)
|
||||
{
|
||||
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
struct iwl_mvm_key_pn *ptk_pn;
|
||||
int tid;
|
||||
|
||||
BUILD_BUG_ON(IWL_NUM_RSC != IEEE80211_NUM_TIDS);
|
||||
iwl_mvm_set_key_rx_seq_tids(key, status->ptk.aes.seq);
|
||||
|
||||
for (tid = 0; tid < IWL_NUM_RSC; tid++) {
|
||||
struct ieee80211_key_seq seq = {};
|
||||
if (!iwl_mvm_has_new_rx_api(mvm))
|
||||
return;
|
||||
|
||||
iwl_mvm_tkip_sc_to_seq(&scs[tid], &seq);
|
||||
ieee80211_set_key_rx_seq(key, tid, &seq);
|
||||
|
||||
rcu_read_lock();
|
||||
ptk_pn = rcu_dereference(mvmsta->ptk_pn[key->keyidx]);
|
||||
if (WARN_ON(!ptk_pn)) {
|
||||
rcu_read_unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) {
|
||||
int i;
|
||||
|
||||
for (i = 1; i < mvm->trans->num_rx_queues; i++)
|
||||
memcpy(ptk_pn->q[i].pn[tid],
|
||||
status->ptk.aes.seq[tid].ccmp.pn,
|
||||
IEEE80211_CCMP_PN_LEN);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static void iwl_mvm_convert_key_counters(struct iwl_wowlan_status_data *status,
|
||||
union iwl_all_tsc_rsc *sc)
|
||||
{
|
||||
int i;
|
||||
|
||||
BUILD_BUG_ON(IWL_MAX_TID_COUNT > IWL_MAX_TID_COUNT);
|
||||
BUILD_BUG_ON(IWL_MAX_TID_COUNT > IWL_NUM_RSC);
|
||||
|
||||
/* GTK RX counters */
|
||||
for (i = 0; i < IWL_MAX_TID_COUNT; i++) {
|
||||
iwl_mvm_tkip_sc_to_seq(&sc->tkip.multicast_rsc[i],
|
||||
&status->gtk.tkip.seq[i]);
|
||||
iwl_mvm_aes_sc_to_seq(&sc->aes.multicast_rsc[i],
|
||||
&status->gtk.aes.seq[i]);
|
||||
}
|
||||
|
||||
/* PTK TX counter */
|
||||
status->ptk.tkip.tx_pn = (u64)le16_to_cpu(sc->tkip.tsc.iv16) |
|
||||
((u64)le32_to_cpu(sc->tkip.tsc.iv32) << 16);
|
||||
status->ptk.aes.tx_pn = le64_to_cpu(sc->aes.tsc.pn);
|
||||
|
||||
/* PTK RX counters */
|
||||
for (i = 0; i < IWL_MAX_TID_COUNT; i++) {
|
||||
iwl_mvm_tkip_sc_to_seq(&sc->tkip.unicast_rsc[i],
|
||||
&status->ptk.tkip.seq[i]);
|
||||
iwl_mvm_aes_sc_to_seq(&sc->aes.unicast_rsc[i],
|
||||
&status->ptk.aes.seq[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void iwl_mvm_set_key_rx_seq(struct iwl_mvm *mvm,
|
||||
struct ieee80211_key_conf *key,
|
||||
struct iwl_wowlan_status *status)
|
||||
struct iwl_wowlan_status_data *status)
|
||||
{
|
||||
union iwl_all_tsc_rsc *rsc = &status->gtk[0].rsc.all_tsc_rsc;
|
||||
|
||||
switch (key->cipher) {
|
||||
case WLAN_CIPHER_SUITE_CCMP:
|
||||
case WLAN_CIPHER_SUITE_GCMP:
|
||||
case WLAN_CIPHER_SUITE_GCMP_256:
|
||||
iwl_mvm_set_aes_rx_seq(mvm, rsc->aes.multicast_rsc, NULL, key);
|
||||
iwl_mvm_set_key_rx_seq_tids(key, status->gtk.aes.seq);
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_TKIP:
|
||||
iwl_mvm_set_tkip_rx_seq(rsc->tkip.multicast_rsc, key);
|
||||
iwl_mvm_set_key_rx_seq_tids(key, status->gtk.tkip.seq);
|
||||
break;
|
||||
default:
|
||||
WARN_ON(1);
|
||||
@ -1619,7 +1669,7 @@ static void iwl_mvm_set_key_rx_seq(struct iwl_mvm *mvm,
|
||||
|
||||
struct iwl_mvm_d3_gtk_iter_data {
|
||||
struct iwl_mvm *mvm;
|
||||
struct iwl_wowlan_status *status;
|
||||
struct iwl_wowlan_status_data *status;
|
||||
void *last_gtk;
|
||||
u32 cipher;
|
||||
bool find_phase, unhandled_cipher;
|
||||
@ -1633,6 +1683,7 @@ static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw,
|
||||
void *_data)
|
||||
{
|
||||
struct iwl_mvm_d3_gtk_iter_data *data = _data;
|
||||
struct iwl_wowlan_status_data *status = data->status;
|
||||
|
||||
if (data->unhandled_cipher)
|
||||
return;
|
||||
@ -1661,10 +1712,6 @@ static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw,
|
||||
* note that this assumes no TDLS sessions are active
|
||||
*/
|
||||
if (sta) {
|
||||
struct ieee80211_key_seq seq = {};
|
||||
union iwl_all_tsc_rsc *sc =
|
||||
&data->status->gtk[0].rsc.all_tsc_rsc;
|
||||
|
||||
if (data->find_phase)
|
||||
return;
|
||||
|
||||
@ -1672,16 +1719,12 @@ static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw,
|
||||
case WLAN_CIPHER_SUITE_CCMP:
|
||||
case WLAN_CIPHER_SUITE_GCMP:
|
||||
case WLAN_CIPHER_SUITE_GCMP_256:
|
||||
iwl_mvm_set_aes_rx_seq(data->mvm, sc->aes.unicast_rsc,
|
||||
sta, key);
|
||||
atomic64_set(&key->tx_pn, le64_to_cpu(sc->aes.tsc.pn));
|
||||
atomic64_set(&key->tx_pn, status->ptk.aes.tx_pn);
|
||||
iwl_mvm_set_aes_ptk_rx_seq(data->mvm, status, sta, key);
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_TKIP:
|
||||
iwl_mvm_tkip_sc_to_seq(&sc->tkip.tsc, &seq);
|
||||
iwl_mvm_set_tkip_rx_seq(sc->tkip.unicast_rsc, key);
|
||||
atomic64_set(&key->tx_pn,
|
||||
(u64)seq.tkip.iv16 |
|
||||
((u64)seq.tkip.iv32 << 16));
|
||||
atomic64_set(&key->tx_pn, status->ptk.tkip.tx_pn);
|
||||
iwl_mvm_set_key_rx_seq_tids(key, status->ptk.tkip.seq);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1703,7 +1746,7 @@ static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw,
|
||||
|
||||
static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct iwl_wowlan_status *status)
|
||||
struct iwl_wowlan_status_data *status)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_mvm_d3_gtk_iter_data gtkdata = {
|
||||
@ -1717,7 +1760,7 @@ static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,
|
||||
if (!status || !vif->bss_conf.bssid)
|
||||
return false;
|
||||
|
||||
if (le32_to_cpu(status->wakeup_reasons) & disconnection_reasons)
|
||||
if (status->wakeup_reasons & disconnection_reasons)
|
||||
return false;
|
||||
|
||||
/* find last GTK that we used initially, if any */
|
||||
@ -1741,7 +1784,7 @@ static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,
|
||||
iwl_mvm_d3_update_keys, >kdata);
|
||||
|
||||
IWL_DEBUG_WOWLAN(mvm, "num of GTK rekeying %d\n",
|
||||
le32_to_cpu(status->num_of_gtk_rekeys));
|
||||
status->num_of_gtk_rekeys);
|
||||
if (status->num_of_gtk_rekeys) {
|
||||
struct ieee80211_key_conf *key;
|
||||
struct {
|
||||
@ -1750,36 +1793,32 @@ static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,
|
||||
} conf = {
|
||||
.conf.cipher = gtkdata.cipher,
|
||||
.conf.keyidx =
|
||||
iwlmvm_wowlan_gtk_idx(&status->gtk[0]),
|
||||
status->gtk.flags & IWL_WOWLAN_GTK_IDX_MASK,
|
||||
};
|
||||
__be64 replay_ctr;
|
||||
|
||||
IWL_DEBUG_WOWLAN(mvm,
|
||||
"Received from FW GTK cipher %d, key index %d\n",
|
||||
conf.conf.cipher, conf.conf.keyidx);
|
||||
|
||||
BUILD_BUG_ON(WLAN_KEY_LEN_CCMP != WLAN_KEY_LEN_GCMP);
|
||||
BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_CCMP);
|
||||
BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_GCMP_256);
|
||||
BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_TKIP);
|
||||
BUILD_BUG_ON(sizeof(conf.key) < sizeof(status->gtk.key));
|
||||
|
||||
memcpy(conf.conf.key, status->gtk.key, sizeof(status->gtk.key));
|
||||
|
||||
switch (gtkdata.cipher) {
|
||||
case WLAN_CIPHER_SUITE_CCMP:
|
||||
case WLAN_CIPHER_SUITE_GCMP:
|
||||
BUILD_BUG_ON(WLAN_KEY_LEN_CCMP != WLAN_KEY_LEN_GCMP);
|
||||
BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_CCMP);
|
||||
conf.conf.keylen = WLAN_KEY_LEN_CCMP;
|
||||
memcpy(conf.conf.key, status->gtk[0].key,
|
||||
WLAN_KEY_LEN_CCMP);
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_GCMP_256:
|
||||
BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_GCMP_256);
|
||||
conf.conf.keylen = WLAN_KEY_LEN_GCMP_256;
|
||||
memcpy(conf.conf.key, status->gtk[0].key,
|
||||
WLAN_KEY_LEN_GCMP_256);
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_TKIP:
|
||||
BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_TKIP);
|
||||
conf.conf.keylen = WLAN_KEY_LEN_TKIP;
|
||||
memcpy(conf.conf.key, status->gtk[0].key, 16);
|
||||
/* leave TX MIC key zeroed, we don't use it anyway */
|
||||
memcpy(conf.conf.key +
|
||||
NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY,
|
||||
status->gtk[0].tkip_mic_key, 8);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1788,8 +1827,7 @@ static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,
|
||||
return false;
|
||||
iwl_mvm_set_key_rx_seq(mvm, key, status);
|
||||
|
||||
replay_ctr =
|
||||
cpu_to_be64(le64_to_cpu(status->replay_ctr));
|
||||
replay_ctr = cpu_to_be64(status->replay_ctr);
|
||||
|
||||
ieee80211_gtk_rekey_notify(vif, vif->bss_conf.bssid,
|
||||
(void *)&replay_ctr, GFP_KERNEL);
|
||||
@ -1800,7 +1838,7 @@ out:
|
||||
WOWLAN_GET_STATUSES, 0) < 10) {
|
||||
mvmvif->seqno_valid = true;
|
||||
/* +0x10 because the set API expects next-to-use, not last-used */
|
||||
mvmvif->seqno = le16_to_cpu(status->non_qos_seq_ctr) + 0x10;
|
||||
mvmvif->seqno = status->non_qos_seq_ctr + 0x10;
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -1808,13 +1846,13 @@ out:
|
||||
|
||||
/* Occasionally, templates would be nice. This is one of those times ... */
|
||||
#define iwl_mvm_parse_wowlan_status_common(_ver) \
|
||||
static struct iwl_wowlan_status * \
|
||||
static struct iwl_wowlan_status_data * \
|
||||
iwl_mvm_parse_wowlan_status_common_ ## _ver(struct iwl_mvm *mvm, \
|
||||
void *_data, int len) \
|
||||
struct iwl_wowlan_status_ ##_ver *data,\
|
||||
int len) \
|
||||
{ \
|
||||
struct iwl_wowlan_status *status; \
|
||||
struct iwl_wowlan_status_ ##_ver *data = _data; \
|
||||
int data_size; \
|
||||
struct iwl_wowlan_status_data *status; \
|
||||
int data_size, i; \
|
||||
\
|
||||
if (len < sizeof(*data)) { \
|
||||
IWL_ERR(mvm, "Invalid WoWLAN status response!\n"); \
|
||||
@ -1832,18 +1870,22 @@ iwl_mvm_parse_wowlan_status_common_ ## _ver(struct iwl_mvm *mvm, \
|
||||
return ERR_PTR(-ENOMEM); \
|
||||
\
|
||||
/* copy all the common fields */ \
|
||||
status->replay_ctr = data->replay_ctr; \
|
||||
status->pattern_number = data->pattern_number; \
|
||||
status->non_qos_seq_ctr = data->non_qos_seq_ctr; \
|
||||
memcpy(status->qos_seq_ctr, data->qos_seq_ctr, \
|
||||
sizeof(status->qos_seq_ctr)); \
|
||||
status->wakeup_reasons = data->wakeup_reasons; \
|
||||
status->num_of_gtk_rekeys = data->num_of_gtk_rekeys; \
|
||||
status->received_beacons = data->received_beacons; \
|
||||
status->wake_packet_length = data->wake_packet_length; \
|
||||
status->wake_packet_bufsize = data->wake_packet_bufsize; \
|
||||
status->replay_ctr = le64_to_cpu(data->replay_ctr); \
|
||||
status->pattern_number = le16_to_cpu(data->pattern_number); \
|
||||
status->non_qos_seq_ctr = le16_to_cpu(data->non_qos_seq_ctr); \
|
||||
for (i = 0; i < 8; i++) \
|
||||
status->qos_seq_ctr[i] = \
|
||||
le16_to_cpu(data->qos_seq_ctr[i]); \
|
||||
status->wakeup_reasons = le32_to_cpu(data->wakeup_reasons); \
|
||||
status->num_of_gtk_rekeys = \
|
||||
le32_to_cpu(data->num_of_gtk_rekeys); \
|
||||
status->received_beacons = le32_to_cpu(data->received_beacons); \
|
||||
status->wake_packet_length = \
|
||||
le32_to_cpu(data->wake_packet_length); \
|
||||
status->wake_packet_bufsize = \
|
||||
le32_to_cpu(data->wake_packet_bufsize); \
|
||||
memcpy(status->wake_packet, data->wake_packet, \
|
||||
le32_to_cpu(status->wake_packet_bufsize)); \
|
||||
status->wake_packet_bufsize); \
|
||||
\
|
||||
return status; \
|
||||
}
|
||||
@ -1852,10 +1894,49 @@ iwl_mvm_parse_wowlan_status_common(v6)
|
||||
iwl_mvm_parse_wowlan_status_common(v7)
|
||||
iwl_mvm_parse_wowlan_status_common(v9)
|
||||
|
||||
static struct iwl_wowlan_status *
|
||||
static void iwl_mvm_convert_gtk(struct iwl_wowlan_status_data *status,
|
||||
struct iwl_wowlan_gtk_status *data)
|
||||
{
|
||||
BUILD_BUG_ON(sizeof(status->gtk.key) < sizeof(data->key));
|
||||
BUILD_BUG_ON(NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY +
|
||||
sizeof(data->tkip_mic_key) >
|
||||
sizeof(status->gtk.key));
|
||||
|
||||
status->gtk.len = data->key_len;
|
||||
status->gtk.flags = data->key_flags;
|
||||
|
||||
memcpy(status->gtk.key, data->key, sizeof(data->key));
|
||||
|
||||
/* if it's as long as the TKIP encryption key, copy MIC key */
|
||||
if (status->gtk.len == NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY)
|
||||
memcpy(status->gtk.key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY,
|
||||
data->tkip_mic_key, sizeof(data->tkip_mic_key));
|
||||
}
|
||||
|
||||
static void iwl_mvm_convert_igtk(struct iwl_wowlan_status_data *status,
|
||||
struct iwl_wowlan_igtk_status *data)
|
||||
{
|
||||
const u8 *ipn = data->ipn;
|
||||
|
||||
BUILD_BUG_ON(sizeof(status->igtk.key) < sizeof(data->key));
|
||||
|
||||
status->igtk.len = data->key_len;
|
||||
status->igtk.flags = data->key_flags;
|
||||
|
||||
memcpy(status->igtk.key, data->key, sizeof(data->key));
|
||||
|
||||
status->igtk.ipn = ((u64)ipn[5] << 0) |
|
||||
((u64)ipn[4] << 8) |
|
||||
((u64)ipn[3] << 16) |
|
||||
((u64)ipn[2] << 24) |
|
||||
((u64)ipn[1] << 32) |
|
||||
((u64)ipn[0] << 40);
|
||||
}
|
||||
|
||||
static struct iwl_wowlan_status_data *
|
||||
iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id)
|
||||
{
|
||||
struct iwl_wowlan_status *status;
|
||||
struct iwl_wowlan_status_data *status;
|
||||
struct iwl_wowlan_get_status_cmd get_status_cmd = {
|
||||
.sta_id = cpu_to_le32(sta_id),
|
||||
};
|
||||
@ -1895,59 +1976,57 @@ iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id)
|
||||
IWL_UCODE_TLV_API_WOWLAN_KEY_MATERIAL)) {
|
||||
struct iwl_wowlan_status_v6 *v6 = (void *)cmd.resp_pkt->data;
|
||||
|
||||
status = iwl_mvm_parse_wowlan_status_common_v6(mvm,
|
||||
cmd.resp_pkt->data,
|
||||
len);
|
||||
status = iwl_mvm_parse_wowlan_status_common_v6(mvm, v6, len);
|
||||
if (IS_ERR(status))
|
||||
goto out_free_resp;
|
||||
|
||||
BUILD_BUG_ON(sizeof(v6->gtk.decrypt_key) >
|
||||
sizeof(status->gtk[0].key));
|
||||
BUILD_BUG_ON(sizeof(v6->gtk.tkip_mic_key) >
|
||||
sizeof(status->gtk[0].tkip_mic_key));
|
||||
sizeof(status->gtk.key));
|
||||
BUILD_BUG_ON(NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY +
|
||||
sizeof(v6->gtk.tkip_mic_key) >
|
||||
sizeof(status->gtk.key));
|
||||
|
||||
/* copy GTK info to the right place */
|
||||
memcpy(status->gtk[0].key, v6->gtk.decrypt_key,
|
||||
memcpy(status->gtk.key, v6->gtk.decrypt_key,
|
||||
sizeof(v6->gtk.decrypt_key));
|
||||
memcpy(status->gtk[0].tkip_mic_key, v6->gtk.tkip_mic_key,
|
||||
memcpy(status->gtk.key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY,
|
||||
v6->gtk.tkip_mic_key,
|
||||
sizeof(v6->gtk.tkip_mic_key));
|
||||
memcpy(&status->gtk[0].rsc, &v6->gtk.rsc,
|
||||
sizeof(status->gtk[0].rsc));
|
||||
|
||||
iwl_mvm_convert_key_counters(status, &v6->gtk.rsc.all_tsc_rsc);
|
||||
|
||||
/* hardcode the key length to 16 since v6 only supports 16 */
|
||||
status->gtk[0].key_len = 16;
|
||||
status->gtk.len = 16;
|
||||
|
||||
/*
|
||||
* The key index only uses 2 bits (values 0 to 3) and
|
||||
* we always set bit 7 which means this is the
|
||||
* currently used key.
|
||||
*/
|
||||
status->gtk[0].key_flags = v6->gtk.key_index | BIT(7);
|
||||
status->gtk.flags = v6->gtk.key_index | BIT(7);
|
||||
} else if (notif_ver == 7) {
|
||||
struct iwl_wowlan_status_v7 *v7 = (void *)cmd.resp_pkt->data;
|
||||
|
||||
status = iwl_mvm_parse_wowlan_status_common_v7(mvm,
|
||||
cmd.resp_pkt->data,
|
||||
len);
|
||||
status = iwl_mvm_parse_wowlan_status_common_v7(mvm, v7, len);
|
||||
if (IS_ERR(status))
|
||||
goto out_free_resp;
|
||||
|
||||
status->gtk[0] = v7->gtk[0];
|
||||
status->igtk[0] = v7->igtk[0];
|
||||
iwl_mvm_convert_key_counters(status, &v7->gtk[0].rsc.all_tsc_rsc);
|
||||
iwl_mvm_convert_gtk(status, &v7->gtk[0]);
|
||||
iwl_mvm_convert_igtk(status, &v7->igtk[0]);
|
||||
} else if (notif_ver == 9 || notif_ver == 10 || notif_ver == 11) {
|
||||
struct iwl_wowlan_status_v9 *v9 = (void *)cmd.resp_pkt->data;
|
||||
|
||||
/* these three command versions have same layout and size, the
|
||||
* difference is only in a few not used (reserved) fields.
|
||||
*/
|
||||
status = iwl_mvm_parse_wowlan_status_common_v9(mvm,
|
||||
cmd.resp_pkt->data,
|
||||
len);
|
||||
status = iwl_mvm_parse_wowlan_status_common_v9(mvm, v9, len);
|
||||
if (IS_ERR(status))
|
||||
goto out_free_resp;
|
||||
|
||||
status->gtk[0] = v9->gtk[0];
|
||||
status->igtk[0] = v9->igtk[0];
|
||||
iwl_mvm_convert_key_counters(status, &v9->gtk[0].rsc.all_tsc_rsc);
|
||||
iwl_mvm_convert_gtk(status, &v9->gtk[0]);
|
||||
iwl_mvm_convert_igtk(status, &v9->igtk[0]);
|
||||
|
||||
status->tid_tear_down = v9->tid_tear_down;
|
||||
} else {
|
||||
@ -1962,7 +2041,7 @@ out_free_resp:
|
||||
return status;
|
||||
}
|
||||
|
||||
static struct iwl_wowlan_status *
|
||||
static struct iwl_wowlan_status_data *
|
||||
iwl_mvm_get_wakeup_status(struct iwl_mvm *mvm, u8 sta_id)
|
||||
{
|
||||
u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, LONG_GROUP,
|
||||
@ -1987,29 +2066,17 @@ static bool iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_wowlan_status_data status;
|
||||
struct iwl_wowlan_status *fw_status;
|
||||
struct iwl_wowlan_status_data *status;
|
||||
int i;
|
||||
bool keep;
|
||||
struct iwl_mvm_sta *mvm_ap_sta;
|
||||
|
||||
fw_status = iwl_mvm_get_wakeup_status(mvm, mvmvif->ap_sta_id);
|
||||
if (IS_ERR_OR_NULL(fw_status))
|
||||
status = iwl_mvm_get_wakeup_status(mvm, mvmvif->ap_sta_id);
|
||||
if (IS_ERR(status))
|
||||
goto out_unlock;
|
||||
|
||||
IWL_DEBUG_WOWLAN(mvm, "wakeup reason 0x%x\n",
|
||||
le32_to_cpu(fw_status->wakeup_reasons));
|
||||
|
||||
status.pattern_number = le16_to_cpu(fw_status->pattern_number);
|
||||
for (i = 0; i < 8; i++)
|
||||
status.qos_seq_ctr[i] =
|
||||
le16_to_cpu(fw_status->qos_seq_ctr[i]);
|
||||
status.wakeup_reasons = le32_to_cpu(fw_status->wakeup_reasons);
|
||||
status.wake_packet_length =
|
||||
le32_to_cpu(fw_status->wake_packet_length);
|
||||
status.wake_packet_bufsize =
|
||||
le32_to_cpu(fw_status->wake_packet_bufsize);
|
||||
status.wake_packet = fw_status->wake_packet;
|
||||
status->wakeup_reasons);
|
||||
|
||||
/* still at hard-coded place 0 for D3 image */
|
||||
mvm_ap_sta = iwl_mvm_sta_from_staid_protected(mvm, 0);
|
||||
@ -2017,7 +2084,7 @@ static bool iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,
|
||||
goto out_free;
|
||||
|
||||
for (i = 0; i < IWL_MAX_TID_COUNT; i++) {
|
||||
u16 seq = status.qos_seq_ctr[i];
|
||||
u16 seq = status->qos_seq_ctr[i];
|
||||
/* firmware stores last-used value, we store next value */
|
||||
seq += 0x10;
|
||||
mvm_ap_sta->tid_data[i].seq_number = seq;
|
||||
@ -2033,15 +2100,15 @@ static bool iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,
|
||||
/* now we have all the data we need, unlock to avoid mac80211 issues */
|
||||
mutex_unlock(&mvm->mutex);
|
||||
|
||||
iwl_mvm_report_wakeup_reasons(mvm, vif, &status);
|
||||
iwl_mvm_report_wakeup_reasons(mvm, vif, status);
|
||||
|
||||
keep = iwl_mvm_setup_connection_keep(mvm, vif, fw_status);
|
||||
keep = iwl_mvm_setup_connection_keep(mvm, vif, status);
|
||||
|
||||
kfree(fw_status);
|
||||
kfree(status);
|
||||
return keep;
|
||||
|
||||
out_free:
|
||||
kfree(fw_status);
|
||||
kfree(status);
|
||||
out_unlock:
|
||||
mutex_unlock(&mvm->mutex);
|
||||
return false;
|
||||
@ -2165,16 +2232,16 @@ static void iwl_mvm_query_netdetect_reasons(struct iwl_mvm *mvm,
|
||||
.pattern_idx = -1,
|
||||
};
|
||||
struct cfg80211_wowlan_wakeup *wakeup_report = &wakeup;
|
||||
struct iwl_wowlan_status_data *status;
|
||||
struct iwl_mvm_nd_query_results query;
|
||||
struct iwl_wowlan_status *fw_status;
|
||||
unsigned long matched_profiles;
|
||||
u32 reasons = 0;
|
||||
int i, n_matches, ret;
|
||||
|
||||
fw_status = iwl_mvm_get_wakeup_status(mvm, IWL_MVM_INVALID_STA);
|
||||
if (!IS_ERR_OR_NULL(fw_status)) {
|
||||
reasons = le32_to_cpu(fw_status->wakeup_reasons);
|
||||
kfree(fw_status);
|
||||
status = iwl_mvm_get_wakeup_status(mvm, IWL_MVM_INVALID_STA);
|
||||
if (!IS_ERR(status)) {
|
||||
reasons = status->wakeup_reasons;
|
||||
kfree(status);
|
||||
}
|
||||
|
||||
if (reasons & IWL_WOWLAN_WAKEUP_BY_RFKILL_DEASSERTED)
|
||||
|
@ -769,14 +769,18 @@ int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm)
|
||||
int ret;
|
||||
struct iwl_host_cmd cmd;
|
||||
u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, PHY_OPS_GROUP,
|
||||
GEO_TX_POWER_LIMIT,
|
||||
PER_CHAIN_LIMIT_OFFSET_CMD,
|
||||
IWL_FW_CMD_VER_UNKNOWN);
|
||||
|
||||
/* the ops field is at the same spot for all versions, so set in v1 */
|
||||
geo_tx_cmd.v1.ops =
|
||||
cpu_to_le32(IWL_PER_CHAIN_OFFSET_GET_CURRENT_TABLE);
|
||||
|
||||
if (cmd_ver == 3)
|
||||
if (cmd_ver == 5)
|
||||
len = sizeof(geo_tx_cmd.v5);
|
||||
else if (cmd_ver == 4)
|
||||
len = sizeof(geo_tx_cmd.v4);
|
||||
else if (cmd_ver == 3)
|
||||
len = sizeof(geo_tx_cmd.v3);
|
||||
else if (fw_has_api(&mvm->fwrt.fw->ucode_capa,
|
||||
IWL_UCODE_TLV_API_SAR_TABLE_VER))
|
||||
@ -788,7 +792,7 @@ int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
cmd = (struct iwl_host_cmd){
|
||||
.id = WIDE_ID(PHY_OPS_GROUP, GEO_TX_POWER_LIMIT),
|
||||
.id = WIDE_ID(PHY_OPS_GROUP, PER_CHAIN_LIMIT_OFFSET_CMD),
|
||||
.len = { len, },
|
||||
.flags = CMD_WANT_SKB,
|
||||
.data = { &geo_tx_cmd },
|
||||
@ -803,7 +807,7 @@ int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm)
|
||||
resp = (void *)cmd.resp_pkt->data;
|
||||
ret = le32_to_cpu(resp->profile_idx);
|
||||
|
||||
if (WARN_ON(ret > ACPI_NUM_GEO_PROFILES))
|
||||
if (WARN_ON(ret > ACPI_NUM_GEO_PROFILES_REV3))
|
||||
ret = -EIO;
|
||||
|
||||
iwl_free_resp(&cmd);
|
||||
@ -815,36 +819,58 @@ static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm)
|
||||
union iwl_geo_tx_power_profiles_cmd cmd;
|
||||
u16 len;
|
||||
u32 n_bands;
|
||||
u32 n_profiles;
|
||||
int ret;
|
||||
u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, PHY_OPS_GROUP,
|
||||
GEO_TX_POWER_LIMIT,
|
||||
PER_CHAIN_LIMIT_OFFSET_CMD,
|
||||
IWL_FW_CMD_VER_UNKNOWN);
|
||||
|
||||
BUILD_BUG_ON(offsetof(struct iwl_geo_tx_power_profiles_cmd_v1, ops) !=
|
||||
offsetof(struct iwl_geo_tx_power_profiles_cmd_v2, ops) ||
|
||||
offsetof(struct iwl_geo_tx_power_profiles_cmd_v2, ops) !=
|
||||
offsetof(struct iwl_geo_tx_power_profiles_cmd_v3, ops));
|
||||
offsetof(struct iwl_geo_tx_power_profiles_cmd_v3, ops) ||
|
||||
offsetof(struct iwl_geo_tx_power_profiles_cmd_v3, ops) !=
|
||||
offsetof(struct iwl_geo_tx_power_profiles_cmd_v4, ops) ||
|
||||
offsetof(struct iwl_geo_tx_power_profiles_cmd_v4, ops) !=
|
||||
offsetof(struct iwl_geo_tx_power_profiles_cmd_v5, ops));
|
||||
|
||||
/* the ops field is at the same spot for all versions, so set in v1 */
|
||||
cmd.v1.ops = cpu_to_le32(IWL_PER_CHAIN_OFFSET_SET_TABLES);
|
||||
|
||||
if (cmd_ver == 3) {
|
||||
if (cmd_ver == 5) {
|
||||
len = sizeof(cmd.v5);
|
||||
n_bands = ARRAY_SIZE(cmd.v5.table[0]);
|
||||
n_profiles = ACPI_NUM_GEO_PROFILES_REV3;
|
||||
} else if (cmd_ver == 4) {
|
||||
len = sizeof(cmd.v4);
|
||||
n_bands = ARRAY_SIZE(cmd.v4.table[0]);
|
||||
n_profiles = ACPI_NUM_GEO_PROFILES_REV3;
|
||||
} else if (cmd_ver == 3) {
|
||||
len = sizeof(cmd.v3);
|
||||
n_bands = ARRAY_SIZE(cmd.v3.table[0]);
|
||||
n_profiles = ACPI_NUM_GEO_PROFILES;
|
||||
} else if (fw_has_api(&mvm->fwrt.fw->ucode_capa,
|
||||
IWL_UCODE_TLV_API_SAR_TABLE_VER)) {
|
||||
len = sizeof(cmd.v2);
|
||||
n_bands = ARRAY_SIZE(cmd.v2.table[0]);
|
||||
n_profiles = ACPI_NUM_GEO_PROFILES;
|
||||
} else {
|
||||
len = sizeof(cmd.v1);
|
||||
n_bands = ARRAY_SIZE(cmd.v1.table[0]);
|
||||
n_profiles = ACPI_NUM_GEO_PROFILES;
|
||||
}
|
||||
|
||||
BUILD_BUG_ON(offsetof(struct iwl_geo_tx_power_profiles_cmd_v1, table) !=
|
||||
offsetof(struct iwl_geo_tx_power_profiles_cmd_v2, table) ||
|
||||
offsetof(struct iwl_geo_tx_power_profiles_cmd_v2, table) !=
|
||||
offsetof(struct iwl_geo_tx_power_profiles_cmd_v3, table));
|
||||
offsetof(struct iwl_geo_tx_power_profiles_cmd_v3, table) ||
|
||||
offsetof(struct iwl_geo_tx_power_profiles_cmd_v3, table) !=
|
||||
offsetof(struct iwl_geo_tx_power_profiles_cmd_v4, table) ||
|
||||
offsetof(struct iwl_geo_tx_power_profiles_cmd_v4, table) !=
|
||||
offsetof(struct iwl_geo_tx_power_profiles_cmd_v5, table));
|
||||
/* the table is at the same position for all versions, so set use v1 */
|
||||
ret = iwl_sar_geo_init(&mvm->fwrt, &cmd.v1.table[0][0], n_bands);
|
||||
ret = iwl_sar_geo_init(&mvm->fwrt, &cmd.v1.table[0][0],
|
||||
n_bands, n_profiles);
|
||||
|
||||
/*
|
||||
* It is a valid scenario to not support SAR, or miss wgds table,
|
||||
@ -857,14 +883,19 @@ static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm)
|
||||
* Set the revision on versions that contain it.
|
||||
* This must be done after calling iwl_sar_geo_init().
|
||||
*/
|
||||
if (cmd_ver == 3)
|
||||
if (cmd_ver == 5)
|
||||
cmd.v5.table_revision = cpu_to_le32(mvm->fwrt.geo_rev);
|
||||
else if (cmd_ver == 4)
|
||||
cmd.v4.table_revision = cpu_to_le32(mvm->fwrt.geo_rev);
|
||||
else if (cmd_ver == 3)
|
||||
cmd.v3.table_revision = cpu_to_le32(mvm->fwrt.geo_rev);
|
||||
else if (fw_has_api(&mvm->fwrt.fw->ucode_capa,
|
||||
IWL_UCODE_TLV_API_SAR_TABLE_VER))
|
||||
cmd.v2.table_revision = cpu_to_le32(mvm->fwrt.geo_rev);
|
||||
|
||||
return iwl_mvm_send_cmd_pdu(mvm,
|
||||
WIDE_ID(PHY_OPS_GROUP, GEO_TX_POWER_LIMIT),
|
||||
WIDE_ID(PHY_OPS_GROUP,
|
||||
PER_CHAIN_LIMIT_OFFSET_CMD),
|
||||
0, len, &cmd);
|
||||
}
|
||||
|
||||
@ -1114,7 +1145,7 @@ static void iwl_mvm_tas_init(struct iwl_mvm *mvm)
|
||||
static u8 iwl_mvm_eval_dsm_rfi(struct iwl_mvm *mvm)
|
||||
{
|
||||
u8 value;
|
||||
int ret = iwl_acpi_get_dsm_u8((&mvm->fwrt)->dev, 0, DSM_RFI_FUNC_ENABLE,
|
||||
int ret = iwl_acpi_get_dsm_u8(mvm->fwrt.dev, 0, DSM_RFI_FUNC_ENABLE,
|
||||
&iwl_rfi_guid, &value);
|
||||
|
||||
if (ret < 0) {
|
||||
@ -1143,25 +1174,31 @@ static void iwl_mvm_lari_cfg(struct iwl_mvm *mvm)
|
||||
|
||||
cmd.config_bitmap = iwl_acpi_get_lari_config_bitmap(&mvm->fwrt);
|
||||
|
||||
ret = iwl_acpi_get_dsm_u32((&mvm->fwrt)->dev, 0, DSM_FUNC_11AX_ENABLEMENT,
|
||||
ret = iwl_acpi_get_dsm_u32(mvm->fwrt.dev, 0, DSM_FUNC_11AX_ENABLEMENT,
|
||||
&iwl_guid, &value);
|
||||
if (!ret)
|
||||
cmd.oem_11ax_allow_bitmap = cpu_to_le32(value);
|
||||
/* apply more config masks here */
|
||||
|
||||
ret = iwl_acpi_get_dsm_u32((&mvm->fwrt)->dev, 0,
|
||||
ret = iwl_acpi_get_dsm_u32(mvm->fwrt.dev, 0,
|
||||
DSM_FUNC_ENABLE_UNII4_CHAN,
|
||||
&iwl_guid, &value);
|
||||
if (!ret)
|
||||
cmd.oem_unii4_allow_bitmap = cpu_to_le32(value);
|
||||
|
||||
ret = iwl_acpi_get_dsm_u32((&mvm->fwrt)->dev, 0,
|
||||
ret = iwl_acpi_get_dsm_u32(mvm->fwrt.dev, 0,
|
||||
DSM_FUNC_ACTIVATE_CHANNEL,
|
||||
&iwl_guid, &value);
|
||||
if (!ret)
|
||||
cmd.chan_state_active_bitmap = cpu_to_le32(value);
|
||||
|
||||
ret = iwl_acpi_get_dsm_u32(mvm->fwrt.dev, 0,
|
||||
DSM_FUNC_ENABLE_6E,
|
||||
&iwl_guid, &value);
|
||||
if (!ret)
|
||||
cmd.oem_uhb_allow_bitmap = cpu_to_le32(value);
|
||||
|
||||
if (cmd.config_bitmap ||
|
||||
cmd.oem_uhb_allow_bitmap ||
|
||||
cmd.oem_11ax_allow_bitmap ||
|
||||
cmd.oem_unii4_allow_bitmap ||
|
||||
cmd.chan_state_active_bitmap) {
|
||||
@ -1189,6 +1226,9 @@ static void iwl_mvm_lari_cfg(struct iwl_mvm *mvm)
|
||||
le32_to_cpu(cmd.oem_unii4_allow_bitmap),
|
||||
le32_to_cpu(cmd.chan_state_active_bitmap),
|
||||
cmd_ver);
|
||||
IWL_DEBUG_RADIO(mvm,
|
||||
"sending LARI_CONFIG_CHANGE, oem_uhb_allow_bitmap=0x%x\n",
|
||||
le32_to_cpu(cmd.oem_uhb_allow_bitmap));
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm,
|
||||
WIDE_ID(REGULATORY_AND_NVM_GROUP,
|
||||
LARI_CONFIG_CHANGE),
|
||||
|
@ -1557,11 +1557,11 @@ void iwl_mvm_probe_resp_data_notif(struct iwl_mvm *mvm,
|
||||
ieee80211_beacon_set_cntdwn(vif, notif->csa_counter);
|
||||
}
|
||||
|
||||
void iwl_mvm_channel_switch_noa_notif(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_cmd_buffer *rxb)
|
||||
void iwl_mvm_channel_switch_start_notif(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_cmd_buffer *rxb)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_channel_switch_noa_notif *notif = (void *)pkt->data;
|
||||
struct iwl_channel_switch_start_notif *notif = (void *)pkt->data;
|
||||
struct ieee80211_vif *csa_vif, *vif;
|
||||
struct iwl_mvm_vif *mvmvif;
|
||||
u32 id_n_color, csa_id, mac_id;
|
||||
|
@ -2236,6 +2236,34 @@ static void iwl_mvm_cfg_he_sta(struct iwl_mvm *mvm,
|
||||
IWL_ERR(mvm, "Failed to config FW to work HE!\n");
|
||||
}
|
||||
|
||||
static void iwl_mvm_protect_assoc(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
u32 duration_override)
|
||||
{
|
||||
u32 duration = IWL_MVM_TE_SESSION_PROTECTION_MAX_TIME_MS;
|
||||
u32 min_duration = IWL_MVM_TE_SESSION_PROTECTION_MIN_TIME_MS;
|
||||
|
||||
if (duration_override > duration)
|
||||
duration = duration_override;
|
||||
|
||||
/* Try really hard to protect the session and hear a beacon
|
||||
* The new session protection command allows us to protect the
|
||||
* session for a much longer time since the firmware will internally
|
||||
* create two events: a 300TU one with a very high priority that
|
||||
* won't be fragmented which should be enough for 99% of the cases,
|
||||
* and another one (which we configure here to be 900TU long) which
|
||||
* will have a slightly lower priority, but more importantly, can be
|
||||
* fragmented so that it'll allow other activities to run.
|
||||
*/
|
||||
if (fw_has_capa(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_SESSION_PROT_CMD))
|
||||
iwl_mvm_schedule_session_protection(mvm, vif, 900,
|
||||
min_duration, false);
|
||||
else
|
||||
iwl_mvm_protect_session(mvm, vif, duration,
|
||||
min_duration, 500, false);
|
||||
}
|
||||
|
||||
static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *bss_conf,
|
||||
@ -2319,6 +2347,20 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
|
||||
u32 dur = (11 * vif->bss_conf.beacon_int) / 10;
|
||||
iwl_mvm_protect_session(mvm, vif, dur, dur,
|
||||
5 * dur, false);
|
||||
} else if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART,
|
||||
&mvm->status) &&
|
||||
!vif->bss_conf.dtim_period) {
|
||||
/*
|
||||
* If we're not restarting and still haven't
|
||||
* heard a beacon (dtim period unknown) then
|
||||
* make sure we still have enough minimum time
|
||||
* remaining in the time event, since the auth
|
||||
* might actually have taken quite a while
|
||||
* (especially for SAE) and so the remaining
|
||||
* time could be small without us having heard
|
||||
* a beacon yet.
|
||||
*/
|
||||
iwl_mvm_protect_assoc(mvm, vif, 0);
|
||||
}
|
||||
|
||||
iwl_mvm_sf_update(mvm, vif, false);
|
||||
@ -3237,6 +3279,9 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
|
||||
if (vif->type == NL80211_IFTYPE_AP) {
|
||||
mvmvif->ap_assoc_sta_count--;
|
||||
iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
|
||||
} else if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) {
|
||||
/* remove session protection if still running */
|
||||
iwl_mvm_stop_session_protection(mvm, vif);
|
||||
}
|
||||
ret = 0;
|
||||
} else if (old_state == IEEE80211_STA_AUTH &&
|
||||
@ -3329,29 +3374,9 @@ static void iwl_mvm_mac_mgd_prepare_tx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_prep_tx_info *info)
|
||||
{
|
||||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
u32 duration = IWL_MVM_TE_SESSION_PROTECTION_MAX_TIME_MS;
|
||||
u32 min_duration = IWL_MVM_TE_SESSION_PROTECTION_MIN_TIME_MS;
|
||||
|
||||
if (info->duration > duration)
|
||||
duration = info->duration;
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
/* Try really hard to protect the session and hear a beacon
|
||||
* The new session protection command allows us to protect the
|
||||
* session for a much longer time since the firmware will internally
|
||||
* create two events: a 300TU one with a very high priority that
|
||||
* won't be fragmented which should be enough for 99% of the cases,
|
||||
* and another one (which we configure here to be 900TU long) which
|
||||
* will have a slightly lower priority, but more importantly, can be
|
||||
* fragmented so that it'll allow other activities to run.
|
||||
*/
|
||||
if (fw_has_capa(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_SESSION_PROT_CMD))
|
||||
iwl_mvm_schedule_session_protection(mvm, vif, 900,
|
||||
min_duration, false);
|
||||
else
|
||||
iwl_mvm_protect_session(mvm, vif, duration,
|
||||
min_duration, 500, false);
|
||||
iwl_mvm_protect_assoc(mvm, vif, info->duration);
|
||||
mutex_unlock(&mvm->mutex);
|
||||
}
|
||||
|
||||
|
@ -1658,8 +1658,8 @@ void iwl_mvm_probe_resp_data_notif(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_cmd_buffer *rxb);
|
||||
void iwl_mvm_rx_missed_vap_notif(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_cmd_buffer *rxb);
|
||||
void iwl_mvm_channel_switch_noa_notif(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_cmd_buffer *rxb);
|
||||
void iwl_mvm_channel_switch_start_notif(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_cmd_buffer *rxb);
|
||||
/* Bindings */
|
||||
int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
||||
int iwl_mvm_binding_remove_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
||||
|
@ -583,8 +583,9 @@ void iwl_mvm_rx_chub_update_mcc(struct iwl_mvm *mvm,
|
||||
return;
|
||||
|
||||
wgds_tbl_idx = iwl_mvm_get_sar_geo_profile(mvm);
|
||||
if (wgds_tbl_idx < 0)
|
||||
IWL_DEBUG_INFO(mvm, "SAR WGDS is disabled (%d)\n",
|
||||
if (wgds_tbl_idx < 1)
|
||||
IWL_DEBUG_INFO(mvm,
|
||||
"SAR WGDS is disabled or error received (%d)\n",
|
||||
wgds_tbl_idx);
|
||||
else
|
||||
IWL_DEBUG_INFO(mvm, "SAR WGDS: geo profile %d is configured\n",
|
||||
|
@ -383,9 +383,9 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
|
||||
iwl_mvm_probe_resp_data_notif,
|
||||
RX_HANDLER_ASYNC_LOCKED,
|
||||
struct iwl_probe_resp_data_notif),
|
||||
RX_HANDLER_GRP(MAC_CONF_GROUP, CHANNEL_SWITCH_NOA_NOTIF,
|
||||
iwl_mvm_channel_switch_noa_notif,
|
||||
RX_HANDLER_SYNC, struct iwl_channel_switch_noa_notif),
|
||||
RX_HANDLER_GRP(MAC_CONF_GROUP, CHANNEL_SWITCH_START_NOTIF,
|
||||
iwl_mvm_channel_switch_start_notif,
|
||||
RX_HANDLER_SYNC, struct iwl_channel_switch_start_notif),
|
||||
RX_HANDLER_GRP(DATA_PATH_GROUP, MONITOR_NOTIF,
|
||||
iwl_mvm_rx_monitor_notif, RX_HANDLER_ASYNC_LOCKED,
|
||||
struct iwl_datapath_monitor_notif),
|
||||
@ -511,7 +511,7 @@ static const struct iwl_hcmd_names iwl_mvm_mac_conf_names[] = {
|
||||
HCMD_NAME(CHANNEL_SWITCH_TIME_EVENT_CMD),
|
||||
HCMD_NAME(SESSION_PROTECTION_CMD),
|
||||
HCMD_NAME(SESSION_PROTECTION_NOTIF),
|
||||
HCMD_NAME(CHANNEL_SWITCH_NOA_NOTIF),
|
||||
HCMD_NAME(CHANNEL_SWITCH_START_NOTIF),
|
||||
};
|
||||
|
||||
/* Please keep this array *SORTED* by hex value.
|
||||
@ -521,7 +521,7 @@ static const struct iwl_hcmd_names iwl_mvm_phy_names[] = {
|
||||
HCMD_NAME(CMD_DTS_MEASUREMENT_TRIGGER_WIDE),
|
||||
HCMD_NAME(CTDP_CONFIG_CMD),
|
||||
HCMD_NAME(TEMP_REPORTING_THRESHOLDS_CMD),
|
||||
HCMD_NAME(GEO_TX_POWER_LIMIT),
|
||||
HCMD_NAME(PER_CHAIN_LIMIT_OFFSET_CMD),
|
||||
HCMD_NAME(CT_KILL_NOTIFICATION),
|
||||
HCMD_NAME(DTS_MEASUREMENT_NOTIF_WIDE),
|
||||
};
|
||||
|
@ -1995,8 +1995,16 @@ static u16 iwl_mvm_scan_umac_flags_v2(struct iwl_mvm *mvm,
|
||||
{
|
||||
u16 flags = 0;
|
||||
|
||||
/*
|
||||
* If no direct SSIDs are provided perform a passive scan. Otherwise,
|
||||
* if there is a single SSID which is not the broadcast SSID, assume
|
||||
* that the scan is intended for roaming purposes and thus enable Rx on
|
||||
* all chains to improve chances of hearing the beacons/probe responses.
|
||||
*/
|
||||
if (params->n_ssids == 0)
|
||||
flags |= IWL_UMAC_SCAN_GEN_FLAGS_V2_FORCE_PASSIVE;
|
||||
else if (params->n_ssids == 1 && params->ssids[0].ssid_len)
|
||||
flags |= IWL_UMAC_SCAN_GEN_FLAGS_V2_USE_ALL_RX_CHAINS;
|
||||
|
||||
if (iwl_mvm_is_scan_fragmented(params->type))
|
||||
flags |= IWL_UMAC_SCAN_GEN_FLAGS_V2_FRAGMENTED_LMAC1;
|
||||
|
@ -519,7 +519,7 @@ MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids);
|
||||
#define IWL_DEV_INFO(_device, _subdevice, _cfg, _name) \
|
||||
_IWL_DEV_INFO(_device, _subdevice, IWL_CFG_ANY, IWL_CFG_ANY, \
|
||||
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY, \
|
||||
IWL_CFG_NO_CDB, _cfg, _name)
|
||||
IWL_CFG_ANY, _cfg, _name)
|
||||
|
||||
static const struct iwl_dev_info iwl_dev_info_table[] = {
|
||||
#if IS_ENABLED(CONFIG_IWLMVM)
|
||||
@ -549,9 +549,9 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
|
||||
IWL_DEV_INFO(0x7E40, 0x1692, iwl_cfg_ma_a0_gf4_a0, iwl_ax411_killer_1690i_name),
|
||||
|
||||
/* AX200 */
|
||||
IWL_DEV_INFO(0x2723, IWL_CFG_ANY, iwl_ax200_cfg_cc, iwl_ax200_name),
|
||||
IWL_DEV_INFO(0x2723, 0x1653, iwl_ax200_cfg_cc, iwl_ax200_killer_1650w_name),
|
||||
IWL_DEV_INFO(0x2723, 0x1654, iwl_ax200_cfg_cc, iwl_ax200_killer_1650x_name),
|
||||
IWL_DEV_INFO(0x2723, IWL_CFG_ANY, iwl_ax200_cfg_cc, iwl_ax200_name),
|
||||
|
||||
/* Qu with Hr */
|
||||
IWL_DEV_INFO(0x43F0, 0x0070, iwl_ax201_cfg_qu_hr, NULL),
|
||||
@ -725,17 +725,6 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
|
||||
IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
|
||||
iwl9260_2ac_cfg, iwl9462_name),
|
||||
|
||||
_IWL_DEV_INFO(0x2526, IWL_CFG_ANY,
|
||||
IWL_CFG_MAC_TYPE_PNJ, IWL_CFG_ANY,
|
||||
IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,
|
||||
IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
|
||||
iwl9260_2ac_cfg, iwl9560_160_name),
|
||||
_IWL_DEV_INFO(0x2526, IWL_CFG_ANY,
|
||||
IWL_CFG_MAC_TYPE_PNJ, IWL_CFG_ANY,
|
||||
IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,
|
||||
IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
|
||||
iwl9260_2ac_cfg, iwl9560_name),
|
||||
|
||||
_IWL_DEV_INFO(0x2526, IWL_CFG_ANY,
|
||||
IWL_CFG_MAC_TYPE_TH, IWL_CFG_ANY,
|
||||
IWL_CFG_RF_TYPE_TH, IWL_CFG_ANY,
|
||||
@ -1074,11 +1063,6 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
|
||||
IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY,
|
||||
IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
|
||||
iwl_cfg_so_a0_hr_a0, iwl_ax203_name),
|
||||
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
|
||||
IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
|
||||
IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY,
|
||||
IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
|
||||
iwl_cfg_so_a0_hr_a0, iwl_ax203_name),
|
||||
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
|
||||
IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
|
||||
IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY,
|
||||
@ -1146,6 +1130,39 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
|
||||
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB,
|
||||
iwl_cfg_gl_a0_fm_a0, iwl_bz_name),
|
||||
|
||||
/* SoF with JF2 */
|
||||
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
|
||||
IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
|
||||
IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,
|
||||
IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
|
||||
iwlax210_2ax_cfg_so_jf_b0, iwl9560_160_name),
|
||||
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
|
||||
IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
|
||||
IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,
|
||||
IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
|
||||
iwlax210_2ax_cfg_so_jf_b0, iwl9560_name),
|
||||
|
||||
/* SoF with JF */
|
||||
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
|
||||
IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
|
||||
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1,
|
||||
IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
|
||||
iwlax210_2ax_cfg_so_jf_b0, iwl9461_160_name),
|
||||
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
|
||||
IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
|
||||
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV,
|
||||
IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
|
||||
iwlax210_2ax_cfg_so_jf_b0, iwl9462_160_name),
|
||||
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
|
||||
IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
|
||||
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1,
|
||||
IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
|
||||
iwlax210_2ax_cfg_so_jf_b0, iwl9461_name),
|
||||
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
|
||||
IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
|
||||
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV,
|
||||
IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
|
||||
iwlax210_2ax_cfg_so_jf_b0, iwl9462_name),
|
||||
|
||||
/* SoF with JF2 */
|
||||
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
|
||||
@ -1317,13 +1334,66 @@ out:
|
||||
/* PCI registers */
|
||||
#define PCI_CFG_RETRY_TIMEOUT 0x041
|
||||
|
||||
static const struct iwl_dev_info *
|
||||
iwl_pci_find_dev_info(u16 device, u16 subsystem_device,
|
||||
u16 mac_type, u8 mac_step,
|
||||
u16 rf_type, u8 cdb, u8 rf_id, u8 no_160, u8 cores)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = ARRAY_SIZE(iwl_dev_info_table) - 1; i >= 0; i--) {
|
||||
const struct iwl_dev_info *dev_info = &iwl_dev_info_table[i];
|
||||
|
||||
if (dev_info->device != (u16)IWL_CFG_ANY &&
|
||||
dev_info->device != device)
|
||||
continue;
|
||||
|
||||
if (dev_info->subdevice != (u16)IWL_CFG_ANY &&
|
||||
dev_info->subdevice != subsystem_device)
|
||||
continue;
|
||||
|
||||
if (dev_info->mac_type != (u16)IWL_CFG_ANY &&
|
||||
dev_info->mac_type != mac_type)
|
||||
continue;
|
||||
|
||||
if (dev_info->mac_step != (u8)IWL_CFG_ANY &&
|
||||
dev_info->mac_step != mac_step)
|
||||
continue;
|
||||
|
||||
if (dev_info->rf_type != (u16)IWL_CFG_ANY &&
|
||||
dev_info->rf_type != rf_type)
|
||||
continue;
|
||||
|
||||
if (dev_info->cdb != (u8)IWL_CFG_ANY &&
|
||||
dev_info->cdb != cdb)
|
||||
continue;
|
||||
|
||||
if (dev_info->rf_id != (u8)IWL_CFG_ANY &&
|
||||
dev_info->rf_id != rf_id)
|
||||
continue;
|
||||
|
||||
if (dev_info->no_160 != (u8)IWL_CFG_ANY &&
|
||||
dev_info->no_160 != no_160)
|
||||
continue;
|
||||
|
||||
if (dev_info->cores != (u8)IWL_CFG_ANY &&
|
||||
dev_info->cores != cores)
|
||||
continue;
|
||||
|
||||
return dev_info;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
{
|
||||
const struct iwl_cfg_trans_params *trans;
|
||||
const struct iwl_cfg *cfg_7265d __maybe_unused = NULL;
|
||||
const struct iwl_dev_info *dev_info;
|
||||
struct iwl_trans *iwl_trans;
|
||||
struct iwl_trans_pcie *trans_pcie;
|
||||
int i, ret;
|
||||
int ret;
|
||||
const struct iwl_cfg *cfg;
|
||||
|
||||
trans = (void *)(ent->driver_data & ~TRANS_CFG_MARKER);
|
||||
@ -1375,35 +1445,18 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
!CSR_HW_RFID_TYPE(iwl_trans->hw_rf_id) && get_crf_id(iwl_trans))
|
||||
goto out_free_trans;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(iwl_dev_info_table); i++) {
|
||||
const struct iwl_dev_info *dev_info = &iwl_dev_info_table[i];
|
||||
if ((dev_info->device == (u16)IWL_CFG_ANY ||
|
||||
dev_info->device == pdev->device) &&
|
||||
(dev_info->subdevice == (u16)IWL_CFG_ANY ||
|
||||
dev_info->subdevice == pdev->subsystem_device) &&
|
||||
(dev_info->mac_type == (u16)IWL_CFG_ANY ||
|
||||
dev_info->mac_type ==
|
||||
CSR_HW_REV_TYPE(iwl_trans->hw_rev)) &&
|
||||
(dev_info->mac_step == (u8)IWL_CFG_ANY ||
|
||||
dev_info->mac_step ==
|
||||
CSR_HW_REV_STEP(iwl_trans->hw_rev)) &&
|
||||
(dev_info->rf_type == (u16)IWL_CFG_ANY ||
|
||||
dev_info->rf_type ==
|
||||
CSR_HW_RFID_TYPE(iwl_trans->hw_rf_id)) &&
|
||||
(dev_info->cdb == IWL_CFG_NO_CDB ||
|
||||
CSR_HW_RFID_IS_CDB(iwl_trans->hw_rf_id)) &&
|
||||
(dev_info->rf_id == (u8)IWL_CFG_ANY ||
|
||||
dev_info->rf_id ==
|
||||
IWL_SUBDEVICE_RF_ID(pdev->subsystem_device)) &&
|
||||
(dev_info->no_160 == (u8)IWL_CFG_ANY ||
|
||||
dev_info->no_160 ==
|
||||
IWL_SUBDEVICE_NO_160(pdev->subsystem_device)) &&
|
||||
(dev_info->cores == (u8)IWL_CFG_ANY ||
|
||||
dev_info->cores ==
|
||||
IWL_SUBDEVICE_CORES(pdev->subsystem_device))) {
|
||||
iwl_trans->cfg = dev_info->cfg;
|
||||
iwl_trans->name = dev_info->name;
|
||||
}
|
||||
dev_info = iwl_pci_find_dev_info(pdev->device, pdev->subsystem_device,
|
||||
CSR_HW_REV_TYPE(iwl_trans->hw_rev),
|
||||
CSR_HW_REV_STEP(iwl_trans->hw_rev),
|
||||
CSR_HW_RFID_TYPE(iwl_trans->hw_rf_id),
|
||||
CSR_HW_RFID_IS_CDB(iwl_trans->hw_rf_id),
|
||||
IWL_SUBDEVICE_RF_ID(pdev->subsystem_device),
|
||||
IWL_SUBDEVICE_NO_160(pdev->subsystem_device),
|
||||
IWL_SUBDEVICE_CORES(pdev->subsystem_device));
|
||||
|
||||
if (dev_info) {
|
||||
iwl_trans->cfg = dev_info->cfg;
|
||||
iwl_trans->name = dev_info->name;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_IWLMVM)
|
||||
|
@ -2149,6 +2149,7 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id)
|
||||
u32 inta_fh_msk = ~MSIX_FH_INT_CAUSES_DATA_QUEUE;
|
||||
u32 inta_fh, inta_hw;
|
||||
bool polling = false;
|
||||
bool sw_err;
|
||||
|
||||
if (trans_pcie->shared_vec_mask & IWL_SHARED_IRQ_NON_RX)
|
||||
inta_fh_msk |= MSIX_FH_INT_CAUSES_Q0;
|
||||
@ -2221,9 +2222,13 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id)
|
||||
wake_up(&trans_pcie->ucode_write_waitq);
|
||||
}
|
||||
|
||||
if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
|
||||
sw_err = inta_hw & MSIX_HW_INT_CAUSES_REG_SW_ERR_BZ;
|
||||
else
|
||||
sw_err = inta_hw & MSIX_HW_INT_CAUSES_REG_SW_ERR;
|
||||
|
||||
/* Error detected by uCode */
|
||||
if ((inta_fh & MSIX_FH_INT_CAUSES_FH_ERR) ||
|
||||
(inta_hw & MSIX_HW_INT_CAUSES_REG_SW_ERR)) {
|
||||
if ((inta_fh & MSIX_FH_INT_CAUSES_FH_ERR) || sw_err) {
|
||||
IWL_ERR(trans,
|
||||
"Microcode SW error detected. Restarting 0x%X.\n",
|
||||
inta_fh);
|
||||
|
@ -1062,7 +1062,7 @@ struct iwl_causes_list {
|
||||
u8 addr;
|
||||
};
|
||||
|
||||
static struct iwl_causes_list causes_list[] = {
|
||||
static const struct iwl_causes_list causes_list_common[] = {
|
||||
{MSIX_FH_INT_CAUSES_D2S_CH0_NUM, CSR_MSIX_FH_INT_MASK_AD, 0},
|
||||
{MSIX_FH_INT_CAUSES_D2S_CH1_NUM, CSR_MSIX_FH_INT_MASK_AD, 0x1},
|
||||
{MSIX_FH_INT_CAUSES_S2D, CSR_MSIX_FH_INT_MASK_AD, 0x3},
|
||||
@ -1073,25 +1073,26 @@ static struct iwl_causes_list causes_list[] = {
|
||||
{MSIX_HW_INT_CAUSES_REG_CT_KILL, CSR_MSIX_HW_INT_MASK_AD, 0x16},
|
||||
{MSIX_HW_INT_CAUSES_REG_RF_KILL, CSR_MSIX_HW_INT_MASK_AD, 0x17},
|
||||
{MSIX_HW_INT_CAUSES_REG_PERIODIC, CSR_MSIX_HW_INT_MASK_AD, 0x18},
|
||||
{MSIX_HW_INT_CAUSES_REG_SW_ERR, CSR_MSIX_HW_INT_MASK_AD, 0x29},
|
||||
{MSIX_HW_INT_CAUSES_REG_SCD, CSR_MSIX_HW_INT_MASK_AD, 0x2A},
|
||||
{MSIX_HW_INT_CAUSES_REG_FH_TX, CSR_MSIX_HW_INT_MASK_AD, 0x2B},
|
||||
{MSIX_HW_INT_CAUSES_REG_HW_ERR, CSR_MSIX_HW_INT_MASK_AD, 0x2D},
|
||||
{MSIX_HW_INT_CAUSES_REG_HAP, CSR_MSIX_HW_INT_MASK_AD, 0x2E},
|
||||
};
|
||||
|
||||
static void iwl_pcie_map_non_rx_causes(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
int val = trans_pcie->def_irq | MSIX_NON_AUTO_CLEAR_CAUSE;
|
||||
int i, arr_size = ARRAY_SIZE(causes_list);
|
||||
struct iwl_causes_list *causes = causes_list;
|
||||
static const struct iwl_causes_list causes_list_pre_bz[] = {
|
||||
{MSIX_HW_INT_CAUSES_REG_SW_ERR, CSR_MSIX_HW_INT_MASK_AD, 0x29},
|
||||
};
|
||||
|
||||
static const struct iwl_causes_list causes_list_bz[] = {
|
||||
{MSIX_HW_INT_CAUSES_REG_SW_ERR_BZ, CSR_MSIX_HW_INT_MASK_AD, 0x29},
|
||||
};
|
||||
|
||||
static void iwl_pcie_map_list(struct iwl_trans *trans,
|
||||
const struct iwl_causes_list *causes,
|
||||
int arr_size, int val)
|
||||
{
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Access all non RX causes and map them to the default irq.
|
||||
* In case we are missing at least one interrupt vector,
|
||||
* the first interrupt vector will serve non-RX and FBQ causes.
|
||||
*/
|
||||
for (i = 0; i < arr_size; i++) {
|
||||
iwl_write8(trans, CSR_MSIX_IVAR(causes[i].addr), val);
|
||||
iwl_clear_bit(trans, causes[i].mask_reg,
|
||||
@ -1099,6 +1100,25 @@ static void iwl_pcie_map_non_rx_causes(struct iwl_trans *trans)
|
||||
}
|
||||
}
|
||||
|
||||
static void iwl_pcie_map_non_rx_causes(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
int val = trans_pcie->def_irq | MSIX_NON_AUTO_CLEAR_CAUSE;
|
||||
/*
|
||||
* Access all non RX causes and map them to the default irq.
|
||||
* In case we are missing at least one interrupt vector,
|
||||
* the first interrupt vector will serve non-RX and FBQ causes.
|
||||
*/
|
||||
iwl_pcie_map_list(trans, causes_list_common,
|
||||
ARRAY_SIZE(causes_list_common), val);
|
||||
if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
|
||||
iwl_pcie_map_list(trans, causes_list_bz,
|
||||
ARRAY_SIZE(causes_list_bz), val);
|
||||
else
|
||||
iwl_pcie_map_list(trans, causes_list_pre_bz,
|
||||
ARRAY_SIZE(causes_list_pre_bz), val);
|
||||
}
|
||||
|
||||
static void iwl_pcie_map_rx_causes(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
@ -3384,7 +3404,10 @@ static void iwl_trans_pcie_sync_nmi(struct iwl_trans *trans)
|
||||
|
||||
if (trans_pcie->msix_enabled) {
|
||||
inta_addr = CSR_MSIX_HW_INT_CAUSES_AD;
|
||||
sw_err_bit = MSIX_HW_INT_CAUSES_REG_SW_ERR;
|
||||
if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
|
||||
sw_err_bit = MSIX_HW_INT_CAUSES_REG_SW_ERR_BZ;
|
||||
else
|
||||
sw_err_bit = MSIX_HW_INT_CAUSES_REG_SW_ERR;
|
||||
} else {
|
||||
inta_addr = CSR_INT;
|
||||
sw_err_bit = CSR_INT_BIT_SW_ERR;
|
||||
|
Loading…
Reference in New Issue
Block a user