first set of iwlwifi patches for v5.17
* A few mei fixes; * Some improvements in D3; * Support for new FW API commands; * Fixes and cleanups in device configurations; * Support some new FW API command versions; * Fix WGDS revision 3 reading bug; * Some firmware debugging improvements; * Fixes for in device configuration structures; * Improvements in the session protection code; * Support SAR GEO Offset Mapping (SGOM) via BIOS; * Continued work on the new Bz device family; * Some more firmware debugging improvements; * Support new FW API version 68; * Add some new device IDs; * Some other small fixes, clean-ups and improvements. -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEF3LNfgb2BPWm68smoUecoho8xfoFAmGwdr4ACgkQoUecoho8 xfrRjg/9Ffb5e5xIaRW01WCYuF+KUes9fxVTYmniv/5LiN5cUOADUXx5EkkBiM2v TbHOLil1YvUgpfdGk75Hp2QwGLuEvhiLBxenCPKDKiWb3cCoB/0X3R0PglBGkCuT jGSQF6kVnws6acobUozgua7iuBrng2kWgCZ50LpmxOjWYteBA1SYqIP9ywVLEHLi G0MX23gbVwsUKgukyfS2C5vRpUnYoyZ585vztUY7+527MM/07l9srDYUZ1hHW8hR ypXN44h+2zyeoufXmob8KY3noCp+h6KE8wlv5qVQjgwY+Zp2UfIGGnHR06fk2O3i 01JKFxlCx+6AyU7wJHvHlPd12EtiCwRdDey+29/QKxuU6jpV1k11sNxXoKQeP4Ol 5sSh1p1r9AVzo9F3wNkmyEukYyrMe52f+cP44Zvo5+GoMeSvp1VbNpxcVMQLSBIA ZR4MInMaFi6YeWknNll/hzeQEhOlo/QpPhnENeN9K3i5Aa8af9sOIR14CBDi27Ed FcQz83SxC0hmkepLaibEO8QHHFBNOHm2/iugSoUrKj0cmsyUuDthxPCo5FrJTS+k KJbtH7OS5wXWCz0lML+uNCGcZXszV12malaedTtqtgl9Q3/mPuCQy1tRmVpQ/kTE aMcxIX9MsPy8534x2kdpcpWwwi3iWLafl7QuMiHMjhRG+Thg+5U= =tgbw -----END PGP SIGNATURE----- Merge tag 'iwlwifi-next-for-kalle-2021-12-08' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next first set of iwlwifi patches for v5.17 * A few mei fixes; * Some improvements in D3; * Support for new FW API commands; * Fixes and cleanups in device configurations; * Support some new FW API command versions; * Fix WGDS revision 3 reading bug; * Some firmware debugging improvements; * Fixes for in device configuration structures; * Improvements in the session protection code; * Support SAR GEO Offset Mapping (SGOM) via BIOS; * Continued work on the new Bz device family; * Some more firmware debugging improvements; * Support new FW API version 68; * Add some new device IDs; * Some other small fixes, clean-ups and improvements.
This commit is contained in:
Коммит
f06bd8a147
|
@ -2,6 +2,7 @@
|
|||
config IWLWIFI
|
||||
tristate "Intel Wireless WiFi Next Gen AGN - Wireless-N/Advanced-N/Ultimate-N (iwlwifi) "
|
||||
depends on PCI && HAS_IOMEM && CFG80211
|
||||
depends on IWLMEI || !IWLMEI
|
||||
select FW_LOADER
|
||||
help
|
||||
Select to build the driver supporting the:
|
||||
|
@ -92,32 +93,6 @@ config IWLWIFI_BCAST_FILTERING
|
|||
If unsure, don't enable this option, as some programs might
|
||||
expect incoming broadcasts for their normal operations.
|
||||
|
||||
config IWLMEI
|
||||
tristate "Intel Management Engine communication over WLAN"
|
||||
depends on INTEL_MEI
|
||||
depends on PM
|
||||
depends on IWLMVM
|
||||
help
|
||||
Enables the iwlmei kernel module.
|
||||
|
||||
CSME stands for Converged Security and Management Engine. It is a CPU
|
||||
on the chipset and runs a dedicated firmware. AMT (Active Management
|
||||
Technology) is one of the applications that run on that CPU. AMT
|
||||
allows to control the platform remotely.
|
||||
|
||||
This kernel module allows to communicate with the Intel Management
|
||||
Engine over Wifi. This is supported starting from Tiger Lake
|
||||
platforms and has been tested on 9260 devices only.
|
||||
If AMT is configured not to use the wireless device, this module is
|
||||
harmless (and useless).
|
||||
Enabling this option on a platform that has a different device and
|
||||
has Wireless enabled on AMT can prevent WiFi from working correctly.
|
||||
|
||||
For more information see
|
||||
<https://software.intel.com/en-us/manageability/>
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
menu "Debugging Options"
|
||||
|
||||
config IWLWIFI_DEBUG
|
||||
|
@ -172,3 +147,28 @@ config IWLWIFI_DEVICE_TRACING
|
|||
endmenu
|
||||
|
||||
endif
|
||||
|
||||
config IWLMEI
|
||||
tristate "Intel Management Engine communication over WLAN"
|
||||
depends on INTEL_MEI
|
||||
depends on PM
|
||||
help
|
||||
Enables the iwlmei kernel module.
|
||||
|
||||
CSME stands for Converged Security and Management Engine. It is a CPU
|
||||
on the chipset and runs a dedicated firmware. AMT (Active Management
|
||||
Technology) is one of the applications that run on that CPU. AMT
|
||||
allows to control the platform remotely.
|
||||
|
||||
This kernel module allows to communicate with the Intel Management
|
||||
Engine over Wifi. This is supported starting from Tiger Lake
|
||||
platforms and has been tested on 9260 devices only.
|
||||
If AMT is configured not to use the wireless device, this module is
|
||||
harmless (and useless).
|
||||
Enabling this option on a platform that has a different device and
|
||||
has Wireless enabled on AMT can prevent WiFi from working correctly.
|
||||
|
||||
For more information see
|
||||
<https://software.intel.com/en-us/manageability/>
|
||||
|
||||
If unsure, say N.
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include "iwl-prph.h"
|
||||
|
||||
/* Highest firmware API version supported */
|
||||
#define IWL_22000_UCODE_API_MAX 67
|
||||
#define IWL_22000_UCODE_API_MAX 68
|
||||
|
||||
/* Lowest firmware API version supported */
|
||||
#define IWL_22000_UCODE_API_MIN 39
|
||||
|
@ -54,7 +54,8 @@
|
|||
#define IWL_BZ_A_GF4_A_FW_PRE "iwlwifi-bz-a0-gf4-a0-"
|
||||
#define IWL_BZ_A_MR_A_FW_PRE "iwlwifi-bz-a0-mr-a0-"
|
||||
#define IWL_BZ_A_FM_A_FW_PRE "iwlwifi-bz-a0-fm-a0-"
|
||||
#define IWL_GL_A_FM_A_FW_PRE "iwlwifi-gl-a0-fm7-a0-"
|
||||
#define IWL_GL_A_FM_A_FW_PRE "iwlwifi-gl-a0-fm-a0-"
|
||||
#define IWL_BZ_Z_GF_A_FW_PRE "iwlwifi-bz-z0-gf-a0-"
|
||||
|
||||
|
||||
#define IWL_QU_B_HR_B_MODULE_FIRMWARE(api) \
|
||||
|
@ -113,6 +114,8 @@
|
|||
IWL_BZ_A_FM_A_FW_PRE __stringify(api) ".ucode"
|
||||
#define IWL_GL_A_FM_A_MODULE_FIRMWARE(api) \
|
||||
IWL_GL_A_FM_A_FW_PRE __stringify(api) ".ucode"
|
||||
#define IWL_BZ_Z_GF_A_MODULE_FIRMWARE(api) \
|
||||
IWL_BZ_Z_GF_A_FW_PRE __stringify(api) ".ucode"
|
||||
|
||||
static const struct iwl_base_params iwl_22000_base_params = {
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE_32K,
|
||||
|
@ -626,7 +629,7 @@ const struct iwl_cfg iwl_ax200_cfg_cc = {
|
|||
};
|
||||
|
||||
const struct iwl_cfg killer1650s_2ax_cfg_qu_b0_hr_b0 = {
|
||||
.name = "Killer(R) Wi-Fi 6 AX1650i 160MHz Wireless Network Adapter (201NGW)",
|
||||
.name = "Killer(R) Wi-Fi 6 AX1650s 160MHz Wireless Network Adapter (201NGW)",
|
||||
.fw_name_pre = IWL_QU_B_HR_B_FW_PRE,
|
||||
IWL_DEVICE_22500,
|
||||
/*
|
||||
|
@ -639,7 +642,7 @@ const struct iwl_cfg killer1650s_2ax_cfg_qu_b0_hr_b0 = {
|
|||
};
|
||||
|
||||
const struct iwl_cfg killer1650i_2ax_cfg_qu_b0_hr_b0 = {
|
||||
.name = "Killer(R) Wi-Fi 6 AX1650s 160MHz Wireless Network Adapter (201D2W)",
|
||||
.name = "Killer(R) Wi-Fi 6 AX1650i 160MHz Wireless Network Adapter (201D2W)",
|
||||
.fw_name_pre = IWL_QU_B_HR_B_FW_PRE,
|
||||
IWL_DEVICE_22500,
|
||||
/*
|
||||
|
@ -652,7 +655,7 @@ const struct iwl_cfg killer1650i_2ax_cfg_qu_b0_hr_b0 = {
|
|||
};
|
||||
|
||||
const struct iwl_cfg killer1650s_2ax_cfg_qu_c0_hr_b0 = {
|
||||
.name = "Killer(R) Wi-Fi 6 AX1650i 160MHz Wireless Network Adapter (201NGW)",
|
||||
.name = "Killer(R) Wi-Fi 6 AX1650s 160MHz Wireless Network Adapter (201NGW)",
|
||||
.fw_name_pre = IWL_QU_C_HR_B_FW_PRE,
|
||||
IWL_DEVICE_22500,
|
||||
/*
|
||||
|
@ -665,7 +668,7 @@ const struct iwl_cfg killer1650s_2ax_cfg_qu_c0_hr_b0 = {
|
|||
};
|
||||
|
||||
const struct iwl_cfg killer1650i_2ax_cfg_qu_c0_hr_b0 = {
|
||||
.name = "Killer(R) Wi-Fi 6 AX1650s 160MHz Wireless Network Adapter (201D2W)",
|
||||
.name = "Killer(R) Wi-Fi 6 AX1650i 160MHz Wireless Network Adapter (201D2W)",
|
||||
.fw_name_pre = IWL_QU_C_HR_B_FW_PRE,
|
||||
IWL_DEVICE_22500,
|
||||
/*
|
||||
|
@ -696,13 +699,6 @@ const struct iwl_cfg iwlax210_2ax_cfg_so_jf_b0 = {
|
|||
.num_rbds = IWL_NUM_RBDS_NON_HE,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwlax210_2ax_cfg_so_hr_a0 = {
|
||||
.name = "Intel(R) Wi-Fi 6 AX210 160MHz",
|
||||
.fw_name_pre = IWL_SO_A_HR_B_FW_PRE,
|
||||
IWL_DEVICE_AX210,
|
||||
.num_rbds = IWL_NUM_RBDS_AX210_HE,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwlax211_2ax_cfg_so_gf_a0 = {
|
||||
.name = iwl_ax211_name,
|
||||
.fw_name_pre = IWL_SO_A_GF_A_FW_PRE,
|
||||
|
@ -879,6 +875,13 @@ const struct iwl_cfg iwl_cfg_gl_a0_fm_a0 = {
|
|||
.num_rbds = IWL_NUM_RBDS_AX210_HE,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl_cfg_bz_z0_gf_a0 = {
|
||||
.fw_name_pre = IWL_BZ_Z_GF_A_FW_PRE,
|
||||
.uhb_supported = true,
|
||||
IWL_DEVICE_BZ,
|
||||
.num_rbds = IWL_NUM_RBDS_AX210_HE,
|
||||
};
|
||||
|
||||
MODULE_FIRMWARE(IWL_QU_B_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_QNJ_B_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_QU_C_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
|
|
|
@ -1974,12 +1974,8 @@ static void iwl_nic_config(struct iwl_op_mode *op_mode)
|
|||
|
||||
/* SKU Control */
|
||||
iwl_trans_set_bits_mask(priv->trans, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH |
|
||||
CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP,
|
||||
(CSR_HW_REV_STEP(priv->trans->hw_rev) <<
|
||||
CSR_HW_IF_CONFIG_REG_POS_MAC_STEP) |
|
||||
(CSR_HW_REV_DASH(priv->trans->hw_rev) <<
|
||||
CSR_HW_IF_CONFIG_REG_POS_MAC_DASH));
|
||||
CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP_DASH,
|
||||
CSR_HW_REV_STEP_DASH(priv->trans->hw_rev));
|
||||
|
||||
/* write radio config values to register */
|
||||
if (priv->nvm_data->radio_cfg_type <= EEPROM_RF_CONFIG_TYPE_MAX) {
|
||||
|
|
|
@ -789,7 +789,7 @@ int iwl_sar_get_wgds_table(struct iwl_fw_runtime *fwrt)
|
|||
* looking up in ACPI
|
||||
*/
|
||||
if (wifi_pkg->package.count !=
|
||||
min_size + profile_size * num_profiles) {
|
||||
hdr_size + profile_size * num_profiles) {
|
||||
ret = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
|
@ -852,6 +852,8 @@ read_table:
|
|||
}
|
||||
}
|
||||
|
||||
fwrt->geo_num_profiles = num_profiles;
|
||||
fwrt->geo_enabled = true;
|
||||
ret = 0;
|
||||
out_free:
|
||||
kfree(data);
|
||||
|
|
|
@ -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, 2020-2021 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
|
@ -97,6 +97,21 @@ struct iwl_alive_ntf_v5 {
|
|||
struct iwl_sku_id sku_id;
|
||||
} __packed; /* UCODE_ALIVE_NTFY_API_S_VER_5 */
|
||||
|
||||
struct iwl_imr_alive_info {
|
||||
__le64 base_addr;
|
||||
__le32 size;
|
||||
__le32 enabled;
|
||||
} __packed; /* IMR_ALIVE_INFO_API_S_VER_1 */
|
||||
|
||||
struct iwl_alive_ntf_v6 {
|
||||
__le16 status;
|
||||
__le16 flags;
|
||||
struct iwl_lmac_alive lmac_data[2];
|
||||
struct iwl_umac_alive umac_data;
|
||||
struct iwl_sku_id sku_id;
|
||||
struct iwl_imr_alive_info imr;
|
||||
} __packed; /* UCODE_ALIVE_NTFY_API_S_VER_6 */
|
||||
|
||||
/**
|
||||
* enum iwl_extended_cfg_flag - commands driver may send before
|
||||
* finishing init flow
|
||||
|
|
|
@ -51,7 +51,7 @@ enum iwl_legacy_cmds {
|
|||
* @UCODE_ALIVE_NTFY:
|
||||
* Alive data from the firmware, as described in
|
||||
* &struct iwl_alive_ntf_v3 or &struct iwl_alive_ntf_v4 or
|
||||
* &struct iwl_alive_ntf_v5.
|
||||
* &struct iwl_alive_ntf_v5 or &struct iwl_alive_ntf_v6.
|
||||
*/
|
||||
UCODE_ALIVE_NTFY = 0x1,
|
||||
|
||||
|
@ -72,7 +72,8 @@ enum iwl_legacy_cmds {
|
|||
|
||||
/**
|
||||
* @PHY_CONTEXT_CMD:
|
||||
* Add/modify/remove a PHY context, using &struct iwl_phy_context_cmd.
|
||||
* Add/modify/remove a PHY context, using &struct iwl_phy_context_cmd
|
||||
* or &struct iwl_phy_context_cmd_v1.
|
||||
*/
|
||||
PHY_CONTEXT_CMD = 0x8,
|
||||
|
||||
|
@ -356,7 +357,7 @@ enum iwl_legacy_cmds {
|
|||
* &struct iwl_notif_statistics_v11,
|
||||
* &struct iwl_notif_statistics_v10,
|
||||
* &struct iwl_notif_statistics,
|
||||
* &struct iwl_statistics_operational_ntfy
|
||||
* &struct iwl_statistics_operational_ntfy_ver_14
|
||||
*/
|
||||
STATISTICS_CMD = 0x9c,
|
||||
|
||||
|
@ -365,6 +366,7 @@ enum iwl_legacy_cmds {
|
|||
* one of &struct iwl_notif_statistics_v10,
|
||||
* &struct iwl_notif_statistics_v11,
|
||||
* &struct iwl_notif_statistic,
|
||||
* &struct iwl_statistics_operational_ntfy_ver_14
|
||||
* &struct iwl_statistics_operational_ntfy
|
||||
*/
|
||||
STATISTICS_NOTIFICATION = 0x9d,
|
||||
|
@ -612,6 +614,11 @@ enum iwl_system_subcmd_ids {
|
|||
* @RFI_GET_FREQ_TABLE_CMD: &struct iwl_rfi_config_cmd
|
||||
*/
|
||||
RFI_GET_FREQ_TABLE_CMD = 0xc,
|
||||
|
||||
/**
|
||||
* @SYSTEM_FEATURES_CONTROL_CMD: &struct iwl_system_features_control_cmd
|
||||
*/
|
||||
SYSTEM_FEATURES_CONTROL_CMD = 0xd,
|
||||
};
|
||||
|
||||
#endif /* __iwl_fw_api_commands_h__ */
|
||||
|
|
|
@ -554,7 +554,7 @@ struct iwl_wowlan_gtk_status_v1 {
|
|||
} __packed; /* WOWLAN_GTK_MATERIAL_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_wowlan_gtk_status - GTK status
|
||||
* struct iwl_wowlan_gtk_status_v2 - GTK status
|
||||
* @key: GTK material
|
||||
* @key_len: GTK legth, if set to 0, the key is not available
|
||||
* @key_flags: information about the key:
|
||||
|
@ -565,7 +565,7 @@ struct iwl_wowlan_gtk_status_v1 {
|
|||
* @tkip_mic_key: TKIP RX MIC key
|
||||
* @rsc: TSC RSC counters
|
||||
*/
|
||||
struct iwl_wowlan_gtk_status {
|
||||
struct iwl_wowlan_gtk_status_v2 {
|
||||
u8 key[WOWLAN_KEY_MAX_SIZE];
|
||||
u8 key_len;
|
||||
u8 key_flags;
|
||||
|
@ -574,6 +574,41 @@ struct iwl_wowlan_gtk_status {
|
|||
struct iwl_wowlan_rsc_tsc_params_cmd_ver_2 rsc;
|
||||
} __packed; /* WOWLAN_GTK_MATERIAL_VER_2 */
|
||||
|
||||
/**
|
||||
* struct iwl_wowlan_all_rsc_tsc_v5 - key counters
|
||||
* @ucast_rsc: unicast RSC values
|
||||
* @mcast_rsc: multicast RSC values (per key map value)
|
||||
* @sta_id: station ID
|
||||
* @mcast_key_id_map: map of key id to @mcast_rsc entry
|
||||
*/
|
||||
struct iwl_wowlan_all_rsc_tsc_v5 {
|
||||
__le64 ucast_rsc[IWL_MAX_TID_COUNT];
|
||||
__le64 mcast_rsc[2][IWL_MAX_TID_COUNT];
|
||||
__le32 sta_id;
|
||||
u8 mcast_key_id_map[4];
|
||||
} __packed; /* ALL_TSC_RSC_API_S_VER_5 */
|
||||
|
||||
/**
|
||||
* struct iwl_wowlan_gtk_status_v3 - GTK status
|
||||
* @key: GTK material
|
||||
* @key_len: GTK length, if set to 0, the key is not available
|
||||
* @key_flags: information about the key:
|
||||
* bits[0:1]: key index assigned by the AP
|
||||
* bits[2:6]: GTK index of the key in the internal DB
|
||||
* bit[7]: Set iff this is the currently used GTK
|
||||
* @reserved: padding
|
||||
* @tkip_mic_key: TKIP RX MIC key
|
||||
* @sc: RSC/TSC counters
|
||||
*/
|
||||
struct iwl_wowlan_gtk_status_v3 {
|
||||
u8 key[WOWLAN_KEY_MAX_SIZE];
|
||||
u8 key_len;
|
||||
u8 key_flags;
|
||||
u8 reserved[2];
|
||||
u8 tkip_mic_key[IWL_MIC_KEY_SIZE];
|
||||
struct iwl_wowlan_all_rsc_tsc_v5 sc;
|
||||
} __packed; /* WOWLAN_GTK_MATERIAL_VER_3 */
|
||||
|
||||
#define IWL_WOWLAN_GTK_IDX_MASK (BIT(0) | BIT(1))
|
||||
|
||||
/**
|
||||
|
@ -640,7 +675,7 @@ struct iwl_wowlan_status_v6 {
|
|||
* @wake_packet: wakeup packet
|
||||
*/
|
||||
struct iwl_wowlan_status_v7 {
|
||||
struct iwl_wowlan_gtk_status gtk[WOWLAN_GTK_KEYS_NUM];
|
||||
struct iwl_wowlan_gtk_status_v2 gtk[WOWLAN_GTK_KEYS_NUM];
|
||||
struct iwl_wowlan_igtk_status igtk[WOWLAN_IGTK_KEYS_NUM];
|
||||
__le64 replay_ctr;
|
||||
__le16 pattern_number;
|
||||
|
@ -676,7 +711,7 @@ struct iwl_wowlan_status_v7 {
|
|||
* @wake_packet: wakeup packet
|
||||
*/
|
||||
struct iwl_wowlan_status_v9 {
|
||||
struct iwl_wowlan_gtk_status gtk[WOWLAN_GTK_KEYS_NUM];
|
||||
struct iwl_wowlan_gtk_status_v2 gtk[WOWLAN_GTK_KEYS_NUM];
|
||||
struct iwl_wowlan_igtk_status igtk[WOWLAN_IGTK_KEYS_NUM];
|
||||
__le64 replay_ctr;
|
||||
__le16 pattern_number;
|
||||
|
@ -693,6 +728,44 @@ 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_v12 - WoWLAN status
|
||||
* @gtk: GTK data
|
||||
* @igtk: IGTK 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.
|
||||
* Reserved if the struct has version >= 10.
|
||||
* @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
|
||||
* @transmitted_ndps: number of transmitted neighbor discovery packets
|
||||
* @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
|
||||
* @reserved: unused
|
||||
* @wake_packet: wakeup packet
|
||||
*/
|
||||
struct iwl_wowlan_status_v12 {
|
||||
struct iwl_wowlan_gtk_status_v3 gtk[WOWLAN_GTK_KEYS_NUM];
|
||||
struct iwl_wowlan_igtk_status igtk[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;
|
||||
__le32 transmitted_ndps;
|
||||
__le32 received_beacons;
|
||||
__le32 wake_packet_length;
|
||||
__le32 wake_packet_bufsize;
|
||||
u8 tid_tear_down;
|
||||
u8 reserved[3];
|
||||
u8 wake_packet[]; /* can be truncated from _length to _bufsize */
|
||||
} __packed; /* WOWLAN_STATUSES_RSP_API_S_VER_12 */
|
||||
|
||||
/* TODO: NetDetect API */
|
||||
|
||||
#endif /* __iwl_fw_api_d3_h__ */
|
||||
|
|
|
@ -31,6 +31,11 @@ enum iwl_data_path_subcmd_ids {
|
|||
*/
|
||||
STA_HE_CTXT_CMD = 0x7,
|
||||
|
||||
/**
|
||||
* @RLC_CONFIG_CMD: &struct iwl_rlc_config_cmd
|
||||
*/
|
||||
RLC_CONFIG_CMD = 0x8,
|
||||
|
||||
/**
|
||||
* @RFH_QUEUE_CONFIG_CMD: &struct iwl_rfh_queue_config
|
||||
*/
|
||||
|
@ -195,4 +200,61 @@ struct iwl_thermal_dual_chain_request {
|
|||
__le32 event;
|
||||
} __packed; /* THERMAL_DUAL_CHAIN_DISABLE_REQ_NTFY_API_S_VER_1 */
|
||||
|
||||
enum iwl_rlc_chain_info {
|
||||
IWL_RLC_CHAIN_INFO_DRIVER_FORCE = BIT(0),
|
||||
IWL_RLC_CHAIN_INFO_VALID = 0x000e,
|
||||
IWL_RLC_CHAIN_INFO_FORCE = 0x0070,
|
||||
IWL_RLC_CHAIN_INFO_FORCE_MIMO = 0x0380,
|
||||
IWL_RLC_CHAIN_INFO_COUNT = 0x0c00,
|
||||
IWL_RLC_CHAIN_INFO_MIMO_COUNT = 0x3000,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_rlc_properties - RLC properties
|
||||
* @rx_chain_info: RX chain info, &enum iwl_rlc_chain_info
|
||||
* @reserved: reserved
|
||||
*/
|
||||
struct iwl_rlc_properties {
|
||||
__le32 rx_chain_info;
|
||||
__le32 reserved;
|
||||
} __packed; /* RLC_PROPERTIES_S_VER_1 */
|
||||
|
||||
enum iwl_sad_mode {
|
||||
IWL_SAD_MODE_ENABLED = BIT(0),
|
||||
IWL_SAD_MODE_DEFAULT_ANT_MSK = 0x6,
|
||||
IWL_SAD_MODE_DEFAULT_ANT_FW = 0x0,
|
||||
IWL_SAD_MODE_DEFAULT_ANT_A = 0x2,
|
||||
IWL_SAD_MODE_DEFAULT_ANT_B = 0x4,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_sad_properties - SAD properties
|
||||
* @chain_a_sad_mode: chain A SAD mode, &enum iwl_sad_mode
|
||||
* @chain_b_sad_mode: chain B SAD mode, &enum iwl_sad_mode
|
||||
* @mac_id: MAC index
|
||||
* @reserved: reserved
|
||||
*/
|
||||
struct iwl_sad_properties {
|
||||
__le32 chain_a_sad_mode;
|
||||
__le32 chain_b_sad_mode;
|
||||
__le32 mac_id;
|
||||
__le32 reserved;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_rlc_config_cmd - RLC configuration
|
||||
* @phy_id: PHY index
|
||||
* @rlc: RLC properties, &struct iwl_rlc_properties
|
||||
* @sad: SAD (single antenna diversity) options, &struct iwl_sad_properties
|
||||
* @flags: flags, &enum iwl_rlc_flags
|
||||
* @reserved: reserved
|
||||
*/
|
||||
struct iwl_rlc_config_cmd {
|
||||
__le32 phy_id;
|
||||
struct iwl_rlc_properties rlc;
|
||||
struct iwl_sad_properties sad;
|
||||
u8 flags;
|
||||
u8 reserved[3];
|
||||
} __packed; /* RLC_CONFIG_CMD_API_S_VER_2 */
|
||||
|
||||
#endif /* __iwl_fw_api_datapath_h__ */
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
#include <linux/bitops.h>
|
||||
|
||||
#define IWL_FW_INI_HW_SMEM_REGION_ID 15
|
||||
#define IWL_FW_INI_MAX_REGION_ID 64
|
||||
#define IWL_FW_INI_MAX_NAME 32
|
||||
#define IWL_FW_INI_MAX_CFG_NAME 64
|
||||
|
@ -124,6 +123,9 @@ struct iwl_fw_ini_region_internal_buffer {
|
|||
* @hdr: debug header
|
||||
* @id: region id. Max id is &IWL_FW_INI_MAX_REGION_ID
|
||||
* @type: region type. One of &enum iwl_fw_ini_region_type
|
||||
* @sub_type: region sub type
|
||||
* @sub_type_ver: region sub type
|
||||
* @reserved: not in use
|
||||
* @name: region name
|
||||
* @dev_addr: device address configuration. Used by
|
||||
* &IWL_FW_INI_REGION_DEVICE_MEMORY, &IWL_FW_INI_REGION_PERIPHERY_MAC,
|
||||
|
@ -146,7 +148,10 @@ struct iwl_fw_ini_region_internal_buffer {
|
|||
struct iwl_fw_ini_region_tlv {
|
||||
struct iwl_fw_ini_header hdr;
|
||||
__le32 id;
|
||||
__le32 type;
|
||||
u8 type;
|
||||
u8 sub_type;
|
||||
u8 sub_type_ver;
|
||||
u8 reserved;
|
||||
u8 name[IWL_FW_INI_MAX_NAME];
|
||||
union {
|
||||
struct iwl_fw_ini_region_dev_addr dev_addr;
|
||||
|
@ -306,6 +311,7 @@ enum iwl_fw_ini_config_set_type {
|
|||
* @IWL_FW_INI_ALLOCATION_ID_DBGC1: allocation meant for DBGC1 configuration
|
||||
* @IWL_FW_INI_ALLOCATION_ID_DBGC2: allocation meant for DBGC2 configuration
|
||||
* @IWL_FW_INI_ALLOCATION_ID_DBGC3: allocation meant for DBGC3 configuration
|
||||
* @IWL_FW_INI_ALLOCATION_ID_DBGC4: allocation meant for DBGC4 configuration
|
||||
* @IWL_FW_INI_ALLOCATION_NUM: number of allocation ids
|
||||
*/
|
||||
enum iwl_fw_ini_allocation_id {
|
||||
|
@ -313,6 +319,7 @@ enum iwl_fw_ini_allocation_id {
|
|||
IWL_FW_INI_ALLOCATION_ID_DBGC1,
|
||||
IWL_FW_INI_ALLOCATION_ID_DBGC2,
|
||||
IWL_FW_INI_ALLOCATION_ID_DBGC3,
|
||||
IWL_FW_INI_ALLOCATION_ID_DBGC4,
|
||||
IWL_FW_INI_ALLOCATION_NUM,
|
||||
}; /* FW_DEBUG_TLV_ALLOCATION_ID_E_VER_1 */
|
||||
|
||||
|
@ -379,6 +386,8 @@ enum iwl_fw_ini_region_type {
|
|||
IWL_FW_INI_REGION_NUM
|
||||
}; /* FW_TLV_DEBUG_REGION_TYPE_API_E */
|
||||
|
||||
#define IWL_FW_INI_REGION_DEVICE_MEMORY_SUBTYPE_HW_SMEM 1
|
||||
|
||||
/**
|
||||
* enum iwl_fw_ini_time_point
|
||||
*
|
||||
|
|
|
@ -33,6 +33,11 @@ enum iwl_regulatory_and_nvm_subcmd_ids {
|
|||
*/
|
||||
TAS_CONFIG = 0x3,
|
||||
|
||||
/**
|
||||
* @SAR_OFFSET_MAPPING_TABLE_CMD: &iwl_sar_offset_mapping_cmd
|
||||
*/
|
||||
SAR_OFFSET_MAPPING_TABLE_CMD = 0x4,
|
||||
|
||||
/**
|
||||
* @PNVM_INIT_COMPLETE_NTFY: &struct iwl_pnvm_init_complete_ntfy
|
||||
*/
|
||||
|
|
|
@ -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, 2020-2021 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
|
@ -150,11 +150,12 @@ struct iwl_phy_context_cmd {
|
|||
/* COMMON_INDEX_HDR_API_S_VER_1 */
|
||||
__le32 id_and_color;
|
||||
__le32 action;
|
||||
/* PHY_CONTEXT_DATA_API_S_VER_3 */
|
||||
/* PHY_CONTEXT_DATA_API_S_VER_3, PHY_CONTEXT_DATA_API_S_VER_4 */
|
||||
struct iwl_fw_channel_info ci;
|
||||
__le32 lmac_id;
|
||||
__le32 rxchain_info;
|
||||
__le32 rxchain_info; /* reserved in _VER_4 */
|
||||
__le32 dsp_cfg_flags;
|
||||
__le32 reserved;
|
||||
} __packed; /* PHY_CONTEXT_CMD_API_VER_3 */
|
||||
} __packed; /* PHY_CONTEXT_CMD_API_VER_3, PHY_CONTEXT_CMD_API_VER_4 */
|
||||
|
||||
#endif /* __iwl_fw_api_phy_ctxt_h__ */
|
||||
|
|
|
@ -503,6 +503,20 @@ union iwl_ppag_table_cmd {
|
|||
} v2;
|
||||
} __packed;
|
||||
|
||||
#define MCC_TO_SAR_OFFSET_TABLE_ROW_SIZE 26
|
||||
#define MCC_TO_SAR_OFFSET_TABLE_COL_SIZE 13
|
||||
|
||||
/**
|
||||
* struct iwl_sar_offset_mapping_cmd - struct for SAR_OFFSET_MAPPING_TABLE_CMD
|
||||
* @offset_map: mapping a mcc to a geo sar group
|
||||
* @reserved: reserved
|
||||
*/
|
||||
struct iwl_sar_offset_mapping_cmd {
|
||||
u8 offset_map[MCC_TO_SAR_OFFSET_TABLE_ROW_SIZE]
|
||||
[MCC_TO_SAR_OFFSET_TABLE_COL_SIZE];
|
||||
u16 reserved;
|
||||
} __packed; /*SAR_OFFSET_MAPPING_TABLE_CMD_API_S*/
|
||||
|
||||
/**
|
||||
* struct iwl_beacon_filter_cmd
|
||||
* REPLY_BEACON_FILTERING_CMD = 0xd2 (command)
|
||||
|
|
|
@ -659,6 +659,19 @@ enum iwl_umac_scan_general_flags_v2 {
|
|||
IWL_UMAC_SCAN_GEN_FLAGS_V2_6GHZ_PASSIVE_SCAN_FILTER_IN = BIT(14),
|
||||
};
|
||||
|
||||
/**
|
||||
* enum iwl_umac_scan_general_params_flags2 - UMAC scan general flags2
|
||||
*
|
||||
* @IWL_UMAC_SCAN_GEN_PARAMS_FLAGS2_RESPECT_P2P_GO_LB: scan event scheduling
|
||||
* should be aware of a P2P GO operation on the 2GHz band.
|
||||
* @IWL_UMAC_SCAN_GEN_PARAMS_FLAGS2_RESPECT_P2P_GO_HB: scan event scheduling
|
||||
* should be aware of a P2P GO operation on the 5GHz or 6GHz band.
|
||||
*/
|
||||
enum iwl_umac_scan_general_params_flags2 {
|
||||
IWL_UMAC_SCAN_GEN_PARAMS_FLAGS2_RESPECT_P2P_GO_LB = BIT(0),
|
||||
IWL_UMAC_SCAN_GEN_PARAMS_FLAGS2_RESPECT_P2P_GO_HB = BIT(1),
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_scan_channel_cfg_umac
|
||||
* @flags: bitmap - 0-19: directed scan to i'th ssid.
|
||||
|
@ -941,8 +954,8 @@ struct iwl_scan_channel_params_v6 {
|
|||
} __packed; /* SCAN_CHANNEL_PARAMS_API_S_VER_6 */
|
||||
|
||||
/**
|
||||
* struct iwl_scan_general_params_v10
|
||||
* @flags: &enum iwl_umac_scan_flags
|
||||
* struct iwl_scan_general_params_v11
|
||||
* @flags: &enum iwl_umac_scan_general_flags_v2
|
||||
* @reserved: reserved for future
|
||||
* @scan_start_mac_id: report the scan start TSF time according to this mac TSF
|
||||
* @active_dwell: dwell time for active scan per LMAC
|
||||
|
@ -952,7 +965,8 @@ struct iwl_scan_channel_params_v6 {
|
|||
* for 5GHz channels
|
||||
* @adwell_default_social_chn: adaptive dwell default number of
|
||||
* APs per social channel
|
||||
* @reserved1: reserved for future
|
||||
* @flags2: for version 11 see &enum iwl_umac_scan_general_params_flags2.
|
||||
* Otherwise reserved.
|
||||
* @adwell_max_budget: the maximal number of TUs that adaptive dwell
|
||||
* can add to the total scan time
|
||||
* @max_out_of_time: max out of serving channel time, per LMAC
|
||||
|
@ -963,7 +977,7 @@ struct iwl_scan_channel_params_v6 {
|
|||
* @num_of_fragments: number of fragments needed for full fragmented
|
||||
* scan coverage.
|
||||
*/
|
||||
struct iwl_scan_general_params_v10 {
|
||||
struct iwl_scan_general_params_v11 {
|
||||
__le16 flags;
|
||||
u8 reserved;
|
||||
u8 scan_start_mac_id;
|
||||
|
@ -971,14 +985,14 @@ struct iwl_scan_general_params_v10 {
|
|||
u8 adwell_default_2g;
|
||||
u8 adwell_default_5g;
|
||||
u8 adwell_default_social_chn;
|
||||
u8 reserved1;
|
||||
u8 flags2;
|
||||
__le16 adwell_max_budget;
|
||||
__le32 max_out_of_time[SCAN_TWO_LMACS];
|
||||
__le32 suspend_time[SCAN_TWO_LMACS];
|
||||
__le32 scan_priority;
|
||||
u8 passive_dwell[SCAN_TWO_LMACS];
|
||||
u8 num_of_fragments[SCAN_TWO_LMACS];
|
||||
} __packed; /* SCAN_GENERAL_PARAMS_API_S_VER_10 */
|
||||
} __packed; /* SCAN_GENERAL_PARAMS_API_S_VER_11 and *_VER_10 */
|
||||
|
||||
/**
|
||||
* struct iwl_scan_periodic_parms_v1
|
||||
|
@ -994,31 +1008,31 @@ struct iwl_scan_periodic_parms_v1 {
|
|||
|
||||
/**
|
||||
* struct iwl_scan_req_params_v12
|
||||
* @general_params: &struct iwl_scan_general_params_v10
|
||||
* @general_params: &struct iwl_scan_general_params_v11
|
||||
* @channel_params: &struct iwl_scan_channel_params_v4
|
||||
* @periodic_params: &struct iwl_scan_periodic_parms_v1
|
||||
* @probe_params: &struct iwl_scan_probe_params_v3
|
||||
*/
|
||||
struct iwl_scan_req_params_v12 {
|
||||
struct iwl_scan_general_params_v10 general_params;
|
||||
struct iwl_scan_general_params_v11 general_params;
|
||||
struct iwl_scan_channel_params_v4 channel_params;
|
||||
struct iwl_scan_periodic_parms_v1 periodic_params;
|
||||
struct iwl_scan_probe_params_v3 probe_params;
|
||||
} __packed; /* SCAN_REQUEST_PARAMS_API_S_VER_12 */
|
||||
|
||||
/**
|
||||
* struct iwl_scan_req_params_v14
|
||||
* @general_params: &struct iwl_scan_general_params_v10
|
||||
* struct iwl_scan_req_params_v15
|
||||
* @general_params: &struct iwl_scan_general_params_v11
|
||||
* @channel_params: &struct iwl_scan_channel_params_v6
|
||||
* @periodic_params: &struct iwl_scan_periodic_parms_v1
|
||||
* @probe_params: &struct iwl_scan_probe_params_v4
|
||||
*/
|
||||
struct iwl_scan_req_params_v14 {
|
||||
struct iwl_scan_general_params_v10 general_params;
|
||||
struct iwl_scan_req_params_v15 {
|
||||
struct iwl_scan_general_params_v11 general_params;
|
||||
struct iwl_scan_channel_params_v6 channel_params;
|
||||
struct iwl_scan_periodic_parms_v1 periodic_params;
|
||||
struct iwl_scan_probe_params_v4 probe_params;
|
||||
} __packed; /* SCAN_REQUEST_PARAMS_API_S_VER_14 */
|
||||
} __packed; /* SCAN_REQUEST_PARAMS_API_S_VER_15 and *_VER_14 */
|
||||
|
||||
/**
|
||||
* struct iwl_scan_req_umac_v12
|
||||
|
@ -1033,16 +1047,16 @@ struct iwl_scan_req_umac_v12 {
|
|||
} __packed; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_12 */
|
||||
|
||||
/**
|
||||
* struct iwl_scan_req_umac_v14
|
||||
* struct iwl_scan_req_umac_v15
|
||||
* @uid: scan id, &enum iwl_umac_scan_uid_offsets
|
||||
* @ooc_priority: out of channel priority - &enum iwl_scan_priority
|
||||
* @scan_params: scan parameters
|
||||
*/
|
||||
struct iwl_scan_req_umac_v14 {
|
||||
struct iwl_scan_req_umac_v15 {
|
||||
__le32 uid;
|
||||
__le32 ooc_priority;
|
||||
struct iwl_scan_req_params_v14 scan_params;
|
||||
} __packed; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_14 */
|
||||
struct iwl_scan_req_params_v15 scan_params;
|
||||
} __packed; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_15 and *_VER_14 */
|
||||
|
||||
/**
|
||||
* struct iwl_umac_scan_abort
|
||||
|
|
|
@ -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, 2020 - 2021 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
|
@ -432,6 +432,7 @@ enum iwl_fw_statistics_type {
|
|||
FW_STATISTICS_HE,
|
||||
}; /* FW_STATISTICS_TYPE_API_E_VER_1 */
|
||||
|
||||
#define IWL_STATISTICS_TYPE_MSK 0x7f
|
||||
/**
|
||||
* struct iwl_statistics_ntfy_hdr
|
||||
*
|
||||
|
@ -445,11 +446,98 @@ struct iwl_statistics_ntfy_hdr {
|
|||
__le16 size;
|
||||
}; /* STATISTICS_NTFY_HDR_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_statistics_ntfy_per_mac
|
||||
*
|
||||
* @beacon_filter_average_energy: Average energy [-dBm] of the 2
|
||||
* antennas.
|
||||
* @air_time: air time
|
||||
* @beacon_counter: all beacons (both filtered and not filtered)
|
||||
* @beacon_average_energy: all beacons (both filtered and not
|
||||
* filtered)
|
||||
* @beacon_rssi_a: beacon RSSI on antenna A
|
||||
* @beacon_rssi_b: beacon RSSI on antenna B
|
||||
* @rx_bytes: RX byte count
|
||||
*/
|
||||
struct iwl_statistics_ntfy_per_mac {
|
||||
__le32 beacon_filter_average_energy;
|
||||
__le32 air_time;
|
||||
__le32 beacon_counter;
|
||||
__le32 beacon_average_energy;
|
||||
__le32 beacon_rssi_a;
|
||||
__le32 beacon_rssi_b;
|
||||
__le32 rx_bytes;
|
||||
} __packed; /* STATISTICS_NTFY_PER_MAC_API_S_VER_1 */
|
||||
|
||||
#define IWL_STATS_MAX_BW_INDEX 5
|
||||
/** struct iwl_statistics_ntfy_per_phy
|
||||
* @channel_load: channel load
|
||||
* @channel_load_by_us: device contribution to MCLM
|
||||
* @channel_load_not_by_us: other devices' contribution to MCLM
|
||||
* @clt: CLT HW timer (TIM_CH_LOAD2)
|
||||
* @act: active accumulator SW
|
||||
* @elp: elapsed time accumulator SW
|
||||
* @rx_detected_per_ch_width: number of deferred TX per channel width,
|
||||
* 0 - 20, 1/2/3 - 40/80/160
|
||||
* @success_per_ch_width: number of frames that got ACK/BACK/CTS
|
||||
* per channel BW. note, BACK counted as 1
|
||||
* @fail_per_ch_width: number of frames that didn't get ACK/BACK/CTS
|
||||
* per channel BW. note BACK counted as 1
|
||||
* @last_tx_ch_width_indx: last txed frame channel width index
|
||||
*/
|
||||
struct iwl_statistics_ntfy_per_phy {
|
||||
__le32 channel_load;
|
||||
__le32 channel_load_by_us;
|
||||
__le32 channel_load_not_by_us;
|
||||
__le32 clt;
|
||||
__le32 act;
|
||||
__le32 elp;
|
||||
__le32 rx_detected_per_ch_width[IWL_STATS_MAX_BW_INDEX];
|
||||
__le32 success_per_ch_width[IWL_STATS_MAX_BW_INDEX];
|
||||
__le32 fail_per_ch_width[IWL_STATS_MAX_BW_INDEX];
|
||||
__le32 last_tx_ch_width_indx;
|
||||
} __packed; /* STATISTICS_NTFY_PER_PHY_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_statistics_ntfy_per_sta
|
||||
*
|
||||
* @average_energy: in fact it is minus the energy..
|
||||
*/
|
||||
struct iwl_statistics_ntfy_per_sta {
|
||||
__le32 average_energy;
|
||||
} __packed; /* STATISTICS_NTFY_PER_STA_API_S_VER_1 */
|
||||
|
||||
#define IWL_STATS_MAX_PHY_OPERTINAL 3
|
||||
/**
|
||||
* struct iwl_statistics_operational_ntfy
|
||||
*
|
||||
* @hdr: general statistics header
|
||||
* @flags: bitmap of possible notification structures
|
||||
* @per_mac_stats: per mac statistics, &struct iwl_statistics_ntfy_per_mac
|
||||
* @per_phy_stats: per phy statistics, &struct iwl_statistics_ntfy_per_phy
|
||||
* @per_sta_stats: per sta statistics, &struct iwl_statistics_ntfy_per_sta
|
||||
* @rx_time: rx time
|
||||
* @tx_time: usec the radio is transmitting.
|
||||
* @on_time_rf: The total time in usec the RF is awake.
|
||||
* @on_time_scan: usec the radio is awake due to scan.
|
||||
*/
|
||||
struct iwl_statistics_operational_ntfy {
|
||||
struct iwl_statistics_ntfy_hdr hdr;
|
||||
__le32 flags;
|
||||
struct iwl_statistics_ntfy_per_mac per_mac_stats[MAC_INDEX_AUX];
|
||||
struct iwl_statistics_ntfy_per_phy per_phy_stats[IWL_STATS_MAX_PHY_OPERTINAL];
|
||||
struct iwl_statistics_ntfy_per_sta per_sta_stats[IWL_MVM_STATION_COUNT_MAX];
|
||||
__le64 rx_time;
|
||||
__le64 tx_time;
|
||||
__le64 on_time_rf;
|
||||
__le64 on_time_scan;
|
||||
} __packed; /* STATISTICS_OPERATIONAL_NTFY_API_S_VER_15 */
|
||||
|
||||
/**
|
||||
* struct iwl_statistics_operational_ntfy_ver_14
|
||||
*
|
||||
* @hdr: general statistics header
|
||||
* @flags: bitmap of possible notification structures
|
||||
* @mac_id: mac on which the beacon was received
|
||||
* @beacon_filter_average_energy: Average energy [-dBm] of the 2
|
||||
* antennas.
|
||||
|
@ -469,7 +557,7 @@ struct iwl_statistics_ntfy_hdr {
|
|||
* @average_energy: in fact it is minus the energy..
|
||||
* @reserved: reserved
|
||||
*/
|
||||
struct iwl_statistics_operational_ntfy {
|
||||
struct iwl_statistics_operational_ntfy_ver_14 {
|
||||
struct iwl_statistics_ntfy_hdr hdr;
|
||||
__le32 flags;
|
||||
__le32 mac_id;
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/* 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
|
||||
*/
|
||||
#ifndef __iwl_fw_api_soc_h__
|
||||
#define __iwl_fw_api_soc_h__
|
||||
#ifndef __iwl_fw_api_system_h__
|
||||
#define __iwl_fw_api_system_h__
|
||||
|
||||
#define SOC_CONFIG_CMD_FLAGS_DISCRETE BIT(0)
|
||||
#define SOC_CONFIG_CMD_FLAGS_LOW_LATENCY BIT(1)
|
||||
|
@ -32,4 +32,12 @@ struct iwl_soc_configuration_cmd {
|
|||
* SOC_CONFIGURATION_CMD_S_VER_2
|
||||
*/
|
||||
|
||||
#endif /* __iwl_fw_api_soc_h__ */
|
||||
/**
|
||||
* struct iwl_system_features_control_cmd - system features control command
|
||||
* @features: bitmap of features to disable
|
||||
*/
|
||||
struct iwl_system_features_control_cmd {
|
||||
__le32 features[4];
|
||||
} __packed; /* SYSTEM_FEATURES_CONTROL_CMD_API_S_VER_1 */
|
||||
|
||||
#endif /* __iwl_fw_api_system_h__ */
|
|
@ -880,7 +880,7 @@ iwl_fw_error_dump_file(struct iwl_fw_runtime *fwrt,
|
|||
dump_info->hw_type =
|
||||
cpu_to_le32(CSR_HW_REV_TYPE(fwrt->trans->hw_rev));
|
||||
dump_info->hw_step =
|
||||
cpu_to_le32(CSR_HW_REV_STEP(fwrt->trans->hw_rev));
|
||||
cpu_to_le32(fwrt->trans->hw_rev_step);
|
||||
memcpy(dump_info->fw_human_readable, fwrt->fw->human_readable,
|
||||
sizeof(dump_info->fw_human_readable));
|
||||
strncpy(dump_info->dev_human_readable, fwrt->trans->name,
|
||||
|
@ -1165,8 +1165,7 @@ static int iwl_dump_ini_dev_mem_iter(struct iwl_fw_runtime *fwrt,
|
|||
iwl_trans_read_mem_bytes(fwrt->trans, addr, range->data,
|
||||
le32_to_cpu(reg->dev_addr.size));
|
||||
|
||||
if ((le32_to_cpu(reg->id) & IWL_FW_INI_REGION_V2_MASK) ==
|
||||
IWL_FW_INI_HW_SMEM_REGION_ID &&
|
||||
if (reg->sub_type == IWL_FW_INI_REGION_DEVICE_MEMORY_SUBTYPE_HW_SMEM &&
|
||||
fwrt->sanitize_ops && fwrt->sanitize_ops->frob_txf)
|
||||
fwrt->sanitize_ops->frob_txf(fwrt->sanitize_ctx,
|
||||
range->data,
|
||||
|
@ -1988,17 +1987,18 @@ static u32 iwl_dump_ini_mem(struct iwl_fw_runtime *fwrt, struct list_head *list,
|
|||
{
|
||||
struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
|
||||
struct iwl_fw_ini_dump_entry *entry;
|
||||
struct iwl_fw_error_dump_data *tlv;
|
||||
struct iwl_fw_ini_error_dump_data *tlv;
|
||||
struct iwl_fw_ini_error_dump_header *header;
|
||||
u32 type = le32_to_cpu(reg->type), id = le32_to_cpu(reg->id);
|
||||
u32 type = reg->type;
|
||||
u32 id = le32_to_cpu(reg->id);
|
||||
u32 num_of_ranges, i, size;
|
||||
void *range;
|
||||
|
||||
/*
|
||||
* The higher part of the ID in version 2 is irrelevant for
|
||||
* The higher part of the ID from 2 is irrelevant for
|
||||
* us, so mask it out.
|
||||
*/
|
||||
if (le32_to_cpu(reg->hdr.version) == 2)
|
||||
if (le32_to_cpu(reg->hdr.version) >= 2)
|
||||
id &= IWL_FW_INI_REGION_V2_MASK;
|
||||
|
||||
if (!ops->get_num_of_ranges || !ops->get_size || !ops->fill_mem_hdr ||
|
||||
|
@ -2017,6 +2017,9 @@ static u32 iwl_dump_ini_mem(struct iwl_fw_runtime *fwrt, struct list_head *list,
|
|||
|
||||
tlv = (void *)entry->data;
|
||||
tlv->type = reg->type;
|
||||
tlv->sub_type = reg->sub_type;
|
||||
tlv->sub_type_ver = reg->sub_type_ver;
|
||||
tlv->reserved = reg->reserved;
|
||||
tlv->len = cpu_to_le32(size);
|
||||
|
||||
IWL_DEBUG_FW(fwrt, "WRT: Collecting region: id=%d, type=%d\n", id,
|
||||
|
@ -2099,7 +2102,7 @@ static u32 iwl_dump_ini_info(struct iwl_fw_runtime *fwrt,
|
|||
dump->ver_type = cpu_to_le32(fwrt->dump.fw_ver.type);
|
||||
dump->ver_subtype = cpu_to_le32(fwrt->dump.fw_ver.subtype);
|
||||
|
||||
dump->hw_step = cpu_to_le32(CSR_HW_REV_STEP(fwrt->trans->hw_rev));
|
||||
dump->hw_step = cpu_to_le32(fwrt->trans->hw_rev_step);
|
||||
|
||||
/*
|
||||
* Several HWs all have type == 0x42, so we'll override this value
|
||||
|
@ -2291,7 +2294,7 @@ static u32 iwl_dump_ini_trigger(struct iwl_fw_runtime *fwrt,
|
|||
}
|
||||
|
||||
reg = (void *)reg_data.reg_tlv->data;
|
||||
reg_type = le32_to_cpu(reg->type);
|
||||
reg_type = reg->type;
|
||||
if (reg_type >= ARRAY_SIZE(iwl_dump_ini_region_ops))
|
||||
continue;
|
||||
|
||||
|
|
|
@ -212,7 +212,9 @@ static void iwl_fwrt_dump_lmac_error_log(struct iwl_fw_runtime *fwrt, u8 lmac_nu
|
|||
IWL_ERR(trans, "HW error, resetting before reading\n");
|
||||
|
||||
/* reset the device */
|
||||
iwl_trans_sw_reset(trans);
|
||||
err = iwl_trans_sw_reset(trans, true);
|
||||
if (err)
|
||||
return;
|
||||
|
||||
err = iwl_finish_nic_init(trans);
|
||||
if (err)
|
||||
|
|
|
@ -231,6 +231,24 @@ struct iwl_fw_error_dump_mem {
|
|||
/* Use bit 31 as dump info type to avoid colliding with region types */
|
||||
#define IWL_INI_DUMP_INFO_TYPE BIT(31)
|
||||
|
||||
/**
|
||||
* struct iwl_fw_error_dump_data - data for one type
|
||||
* @type: &enum iwl_fw_ini_region_type
|
||||
* @sub_type: sub type id
|
||||
* @sub_type_ver: sub type version
|
||||
* @reserved: not in use
|
||||
* @len: the length starting from %data
|
||||
* @data: the data itself
|
||||
*/
|
||||
struct iwl_fw_ini_error_dump_data {
|
||||
u8 type;
|
||||
u8 sub_type;
|
||||
u8 sub_type_ver;
|
||||
u8 reserved;
|
||||
__le32 len;
|
||||
__u8 data[];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_fw_ini_dump_entry
|
||||
* @list: list of dump entries
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include "dbg.h"
|
||||
#include "debugfs.h"
|
||||
|
||||
#include "fw/api/soc.h"
|
||||
#include "fw/api/system.h"
|
||||
#include "fw/api/commands.h"
|
||||
#include "fw/api/rx.h"
|
||||
#include "fw/api/datapath.h"
|
||||
|
|
|
@ -156,8 +156,12 @@ struct iwl_fw_runtime {
|
|||
u8 sar_chain_b_profile;
|
||||
struct iwl_geo_profile geo_profiles[ACPI_NUM_GEO_PROFILES_REV3];
|
||||
u32 geo_rev;
|
||||
u32 geo_num_profiles;
|
||||
bool geo_enabled;
|
||||
union iwl_ppag_table_cmd ppag_table;
|
||||
u32 ppag_ver;
|
||||
struct iwl_sar_offset_mapping_cmd sgom_table;
|
||||
bool sgom_enabled;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "fw/uefi.h"
|
||||
#include "fw/api/alive.h"
|
||||
#include <linux/efi.h>
|
||||
#include "fw/runtime.h"
|
||||
|
||||
#define IWL_EFI_VAR_GUID EFI_GUID(0x92daaf2f, 0xc02b, 0x455b, \
|
||||
0xb2, 0xec, 0xf5, 0xa3, \
|
||||
|
@ -266,3 +267,90 @@ out:
|
|||
|
||||
return data;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
static int iwl_uefi_sgom_parse(struct uefi_cnv_wlan_sgom_data *sgom_data,
|
||||
struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
if (sgom_data->revision != 1)
|
||||
return -EINVAL;
|
||||
|
||||
memcpy(fwrt->sgom_table.offset_map, sgom_data->offset_map,
|
||||
sizeof(fwrt->sgom_table.offset_map));
|
||||
|
||||
for (i = 0; i < MCC_TO_SAR_OFFSET_TABLE_ROW_SIZE; i++) {
|
||||
for (j = 0; j < MCC_TO_SAR_OFFSET_TABLE_COL_SIZE; j++) {
|
||||
/* since each byte is composed of to values, */
|
||||
/* one for each letter, */
|
||||
/* extract and check each of them separately */
|
||||
u8 value = fwrt->sgom_table.offset_map[i][j];
|
||||
u8 low = value & 0xF;
|
||||
u8 high = (value & 0xF0) >> 4;
|
||||
|
||||
if (high > fwrt->geo_num_profiles)
|
||||
high = 0;
|
||||
if (low > fwrt->geo_num_profiles)
|
||||
low = 0;
|
||||
fwrt->sgom_table.offset_map[i][j] = (high << 4) | low;
|
||||
}
|
||||
}
|
||||
|
||||
fwrt->sgom_enabled = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void iwl_uefi_get_sgom_table(struct iwl_trans *trans,
|
||||
struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
struct efivar_entry *sgom_efivar;
|
||||
struct uefi_cnv_wlan_sgom_data *data;
|
||||
unsigned long package_size;
|
||||
int err, ret;
|
||||
|
||||
if (!fwrt->geo_enabled)
|
||||
return;
|
||||
|
||||
sgom_efivar = kzalloc(sizeof(*sgom_efivar), GFP_KERNEL);
|
||||
if (!sgom_efivar)
|
||||
return;
|
||||
|
||||
memcpy(&sgom_efivar->var.VariableName, IWL_UEFI_SGOM_NAME,
|
||||
sizeof(IWL_UEFI_SGOM_NAME));
|
||||
sgom_efivar->var.VendorGuid = IWL_EFI_VAR_GUID;
|
||||
|
||||
/* TODO: we hardcode a maximum length here, because reading
|
||||
* from the UEFI is not working. To implement this properly,
|
||||
* we have to call efivar_entry_size().
|
||||
*/
|
||||
package_size = IWL_HARDCODED_SGOM_SIZE;
|
||||
|
||||
data = kmalloc(package_size, GFP_KERNEL);
|
||||
if (!data) {
|
||||
data = ERR_PTR(-ENOMEM);
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = efivar_entry_get(sgom_efivar, NULL, &package_size, data);
|
||||
if (err) {
|
||||
IWL_DEBUG_FW(trans,
|
||||
"SGOM UEFI variable not found %d\n", err);
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
IWL_DEBUG_FW(trans, "Read SGOM from UEFI with size %lu\n",
|
||||
package_size);
|
||||
|
||||
ret = iwl_uefi_sgom_parse(data, fwrt);
|
||||
if (ret < 0)
|
||||
IWL_DEBUG_FW(trans, "Cannot read SGOM tables. rev is invalid\n");
|
||||
|
||||
out_free:
|
||||
kfree(data);
|
||||
|
||||
out:
|
||||
kfree(sgom_efivar);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_uefi_get_sgom_table);
|
||||
#endif /* CONFIG_ACPI */
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
#define IWL_UEFI_OEM_PNVM_NAME L"UefiCnvWlanOemSignedPnvm"
|
||||
#define IWL_UEFI_REDUCED_POWER_NAME L"UefiCnvWlanReducedPower"
|
||||
#define IWL_UEFI_SGOM_NAME L"UefiCnvWlanSarGeoOffsetMapping"
|
||||
|
||||
/*
|
||||
* TODO: we have these hardcoded values that the caller must pass,
|
||||
|
@ -16,6 +17,7 @@
|
|||
*/
|
||||
#define IWL_HARDCODED_PNVM_SIZE 4096
|
||||
#define IWL_HARDCODED_REDUCE_POWER_SIZE 32768
|
||||
#define IWL_HARDCODED_SGOM_SIZE 339
|
||||
|
||||
struct pnvm_sku_package {
|
||||
u8 rev;
|
||||
|
@ -25,6 +27,16 @@ struct pnvm_sku_package {
|
|||
u8 data[];
|
||||
} __packed;
|
||||
|
||||
struct uefi_cnv_wlan_sgom_data {
|
||||
u8 revision;
|
||||
u8 offset_map[IWL_HARDCODED_SGOM_SIZE - 1];
|
||||
} __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
|
||||
* disable the feature in old kernels.
|
||||
*/
|
||||
#ifdef CONFIG_EFI
|
||||
void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len);
|
||||
void *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len);
|
||||
|
@ -42,4 +54,12 @@ void *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len)
|
|||
}
|
||||
#endif /* CONFIG_EFI */
|
||||
|
||||
#if defined(CONFIG_EFI) && defined(CONFIG_ACPI)
|
||||
void iwl_uefi_get_sgom_table(struct iwl_trans *trans, struct iwl_fw_runtime *fwrt);
|
||||
#else
|
||||
static inline
|
||||
void iwl_uefi_get_sgom_table(struct iwl_trans *trans, struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
#endif /* __iwl_fw_uefi__ */
|
||||
|
|
|
@ -610,7 +610,6 @@ extern const struct iwl_cfg killer1650x_2ax_cfg;
|
|||
extern const struct iwl_cfg killer1650w_2ax_cfg;
|
||||
extern const struct iwl_cfg iwl_qnj_b0_hr_b0_cfg;
|
||||
extern const struct iwl_cfg iwlax210_2ax_cfg_so_jf_b0;
|
||||
extern const struct iwl_cfg iwlax210_2ax_cfg_so_hr_a0;
|
||||
extern const struct iwl_cfg iwlax211_2ax_cfg_so_gf_a0;
|
||||
extern const struct iwl_cfg iwlax211_2ax_cfg_so_gf_a0_long;
|
||||
extern const struct iwl_cfg iwlax210_2ax_cfg_ty_gf_a0;
|
||||
|
@ -634,6 +633,7 @@ extern const struct iwl_cfg iwl_cfg_bz_a0_gf4_a0;
|
|||
extern const struct iwl_cfg iwl_cfg_bz_a0_mr_a0;
|
||||
extern const struct iwl_cfg iwl_cfg_bz_a0_fm_a0;
|
||||
extern const struct iwl_cfg iwl_cfg_gl_a0_fm_a0;
|
||||
extern const struct iwl_cfg iwl_cfg_bz_z0_gf_a0;
|
||||
#endif /* CONFIG_IWLMVM */
|
||||
|
||||
#endif /* __IWL_CONFIG_H__ */
|
||||
|
|
|
@ -105,6 +105,10 @@
|
|||
/* GIO Chicken Bits (PCI Express bus link power management) */
|
||||
#define CSR_GIO_CHICKEN_BITS (CSR_BASE+0x100)
|
||||
|
||||
#define CSR_IPC_SLEEP_CONTROL (CSR_BASE + 0x114)
|
||||
#define CSR_IPC_SLEEP_CONTROL_SUSPEND 0x3
|
||||
#define CSR_IPC_SLEEP_CONTROL_RESUME 0
|
||||
|
||||
/* Doorbell NMI (since Bz) */
|
||||
#define CSR_DOORBELL_VECTOR (CSR_BASE + 0x130)
|
||||
#define CSR_DOORBELL_VECTOR_NMI BIT(1)
|
||||
|
@ -143,8 +147,7 @@
|
|||
#define CSR_FUNC_SCRATCH_INIT_VALUE (0x01010101)
|
||||
|
||||
/* Bits for CSR_HW_IF_CONFIG_REG */
|
||||
#define CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH (0x00000003)
|
||||
#define CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP (0x0000000C)
|
||||
#define CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP_DASH (0x0000000F)
|
||||
#define CSR_HW_IF_CONFIG_REG_BIT_MONITOR_SRAM (0x00000080)
|
||||
#define CSR_HW_IF_CONFIG_REG_MSK_BOARD_VER (0x000000C0)
|
||||
#define CSR_HW_IF_CONFIG_REG_BIT_MAC_SI (0x00000100)
|
||||
|
@ -287,8 +290,7 @@
|
|||
#define CSR_GP_CNTRL_REG_FLAG_SW_RESET BIT(31)
|
||||
|
||||
/* HW REV */
|
||||
#define CSR_HW_REV_DASH(_val) (((_val) & 0x0000003) >> 0)
|
||||
#define CSR_HW_REV_STEP(_val) (((_val) & 0x000000C) >> 2)
|
||||
#define CSR_HW_REV_STEP_DASH(_val) ((_val) & CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP_DASH)
|
||||
#define CSR_HW_REV_TYPE(_val) (((_val) & 0x000FFF0) >> 4)
|
||||
|
||||
/* HW RFID */
|
||||
|
@ -306,6 +308,7 @@ enum {
|
|||
SILICON_A_STEP = 0,
|
||||
SILICON_B_STEP,
|
||||
SILICON_C_STEP,
|
||||
SILICON_Z_STEP = 0xf,
|
||||
};
|
||||
|
||||
|
||||
|
@ -328,10 +331,10 @@ enum {
|
|||
#define CSR_HW_REV_TYPE_7265D (0x0000210)
|
||||
#define CSR_HW_REV_TYPE_NONE (0x00001F0)
|
||||
#define CSR_HW_REV_TYPE_QNJ (0x0000360)
|
||||
#define CSR_HW_REV_TYPE_QNJ_B0 (0x0000364)
|
||||
#define CSR_HW_REV_TYPE_QU_B0 (0x0000334)
|
||||
#define CSR_HW_REV_TYPE_QU_C0 (0x0000338)
|
||||
#define CSR_HW_REV_TYPE_QUZ (0x0000354)
|
||||
#define CSR_HW_REV_TYPE_QNJ_B0 (0x0000361)
|
||||
#define CSR_HW_REV_TYPE_QU_B0 (0x0000331)
|
||||
#define CSR_HW_REV_TYPE_QU_C0 (0x0000332)
|
||||
#define CSR_HW_REV_TYPE_QUZ (0x0000351)
|
||||
#define CSR_HW_REV_TYPE_HR_CDB (0x0000340)
|
||||
#define CSR_HW_REV_TYPE_SO (0x0000370)
|
||||
#define CSR_HW_REV_TYPE_TY (0x0000420)
|
||||
|
|
|
@ -59,7 +59,7 @@ dbg_ver_table[IWL_DBG_TLV_TYPE_NUM] = {
|
|||
[IWL_DBG_TLV_TYPE_DEBUG_INFO] = {.min_ver = 1, .max_ver = 1,},
|
||||
[IWL_DBG_TLV_TYPE_BUF_ALLOC] = {.min_ver = 1, .max_ver = 1,},
|
||||
[IWL_DBG_TLV_TYPE_HCMD] = {.min_ver = 1, .max_ver = 1,},
|
||||
[IWL_DBG_TLV_TYPE_REGION] = {.min_ver = 1, .max_ver = 2,},
|
||||
[IWL_DBG_TLV_TYPE_REGION] = {.min_ver = 1, .max_ver = 3,},
|
||||
[IWL_DBG_TLV_TYPE_TRIGGER] = {.min_ver = 1, .max_ver = 1,},
|
||||
[IWL_DBG_TLV_TYPE_CONF_SET] = {.min_ver = 1, .max_ver = 1,},
|
||||
};
|
||||
|
@ -177,14 +177,14 @@ static int iwl_dbg_tlv_alloc_region(struct iwl_trans *trans,
|
|||
const struct iwl_fw_ini_region_tlv *reg = (const void *)tlv->data;
|
||||
struct iwl_ucode_tlv **active_reg;
|
||||
u32 id = le32_to_cpu(reg->id);
|
||||
u32 type = le32_to_cpu(reg->type);
|
||||
u8 type = reg->type;
|
||||
u32 tlv_len = sizeof(*tlv) + le32_to_cpu(tlv->length);
|
||||
|
||||
/*
|
||||
* The higher part of the ID in version 2 is irrelevant for
|
||||
* The higher part of the ID in from version 2 is irrelevant for
|
||||
* us, so mask it out.
|
||||
*/
|
||||
if (le32_to_cpu(reg->hdr.version) == 2)
|
||||
if (le32_to_cpu(reg->hdr.version) >= 2)
|
||||
id &= IWL_FW_INI_REGION_V2_MASK;
|
||||
|
||||
if (le32_to_cpu(tlv->length) < sizeof(*reg))
|
||||
|
@ -473,7 +473,7 @@ void iwl_dbg_tlv_load_bin(struct device *dev, struct iwl_trans *trans)
|
|||
int res;
|
||||
|
||||
if (!iwlwifi_mod_params.enable_ini ||
|
||||
trans->trans_cfg->device_family <= IWL_DEVICE_FAMILY_9000)
|
||||
trans->trans_cfg->device_family <= IWL_DEVICE_FAMILY_8000)
|
||||
return;
|
||||
|
||||
res = firmware_request_nowarn(&fw, yoyo_bin, dev);
|
||||
|
@ -1244,7 +1244,7 @@ static void iwl_dbg_tlv_init_cfg(struct iwl_fw_runtime *fwrt)
|
|||
}
|
||||
|
||||
reg = (void *)(*active_reg)->data;
|
||||
reg_type = le32_to_cpu(reg->type);
|
||||
reg_type = reg->type;
|
||||
|
||||
if (reg_type != IWL_FW_INI_REGION_DRAM_BUFFER ||
|
||||
!(BIT(le32_to_cpu(reg->dram_alloc_id)) & failed_alloc))
|
||||
|
|
|
@ -163,8 +163,8 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first)
|
|||
char tag[8];
|
||||
|
||||
if (drv->trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_9000 &&
|
||||
(CSR_HW_REV_STEP(drv->trans->hw_rev) != SILICON_B_STEP &&
|
||||
CSR_HW_REV_STEP(drv->trans->hw_rev) != SILICON_C_STEP)) {
|
||||
(drv->trans->hw_rev_step != SILICON_B_STEP &&
|
||||
drv->trans->hw_rev_step != SILICON_C_STEP)) {
|
||||
IWL_ERR(drv,
|
||||
"Only HW steps B and C are currently supported (0x%0x)\n",
|
||||
drv->trans->hw_rev);
|
||||
|
|
|
@ -1609,7 +1609,7 @@ int iwl_read_external_nvm(struct iwl_trans *trans,
|
|||
|
||||
/* nvm file validation, dword_buff[2] holds the file version */
|
||||
if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_8000 &&
|
||||
CSR_HW_REV_STEP(trans->hw_rev) == SILICON_C_STEP &&
|
||||
trans->hw_rev_step == SILICON_C_STEP &&
|
||||
le32_to_cpu(dword_buff[2]) < 0xE4A) {
|
||||
ret = -EFAULT;
|
||||
goto out;
|
||||
|
|
|
@ -455,6 +455,13 @@ enum {
|
|||
#define UREG_DOORBELL_TO_ISR6_RESUME BIT(19)
|
||||
#define UREG_DOORBELL_TO_ISR6_PNVM BIT(20)
|
||||
|
||||
/*
|
||||
* From BZ family driver triggers this bit for suspend and resume
|
||||
* The driver should update CSR_IPC_SLEEP_CONTROL before triggering
|
||||
* this interrupt with suspend/resume value
|
||||
*/
|
||||
#define UREG_DOORBELL_TO_ISR6_SLEEP_CTRL BIT(31)
|
||||
|
||||
#define CNVI_MBOX_C 0xA3400C
|
||||
|
||||
#define FSEQ_ERROR_CODE 0xA340C8
|
||||
|
|
|
@ -296,6 +296,8 @@ enum iwl_d3_status {
|
|||
* are sent
|
||||
* @STATUS_TRANS_IDLE: the trans is idle - general commands are not to be sent
|
||||
* @STATUS_TRANS_DEAD: trans is dead - avoid any read/write operation
|
||||
* @STATUS_SUPPRESS_CMD_ERROR_ONCE: suppress "FW error in SYNC CMD" once,
|
||||
* e.g. for testing
|
||||
*/
|
||||
enum iwl_trans_status {
|
||||
STATUS_SYNC_HCMD_ACTIVE,
|
||||
|
@ -308,6 +310,7 @@ enum iwl_trans_status {
|
|||
STATUS_TRANS_GOING_IDLE,
|
||||
STATUS_TRANS_IDLE,
|
||||
STATUS_TRANS_DEAD,
|
||||
STATUS_SUPPRESS_CMD_ERROR_ONCE,
|
||||
};
|
||||
|
||||
static inline int
|
||||
|
@ -593,7 +596,7 @@ struct iwl_trans_ops {
|
|||
void (*configure)(struct iwl_trans *trans,
|
||||
const struct iwl_trans_config *trans_cfg);
|
||||
void (*set_pmi)(struct iwl_trans *trans, bool state);
|
||||
void (*sw_reset)(struct iwl_trans *trans);
|
||||
int (*sw_reset)(struct iwl_trans *trans, bool retake_ownership);
|
||||
bool (*grab_nic_access)(struct iwl_trans *trans);
|
||||
void (*release_nic_access)(struct iwl_trans *trans);
|
||||
void (*set_bits_mask)(struct iwl_trans *trans, u32 reg, u32 mask,
|
||||
|
@ -938,6 +941,7 @@ struct iwl_trans_txqs {
|
|||
* @hw_id: a u32 with the ID of the device / sub-device.
|
||||
* Set during transport allocation.
|
||||
* @hw_id_str: a string with info about HW ID. Set during transport allocation.
|
||||
* @hw_rev_step: The mac step of the HW
|
||||
* @pm_support: set to true in start_hw if link pm is supported
|
||||
* @ltr_enabled: set to true if the LTR is enabled
|
||||
* @wide_cmd_header: true when ucode supports wide command header format
|
||||
|
@ -971,6 +975,7 @@ struct iwl_trans {
|
|||
struct device *dev;
|
||||
u32 max_skb_frags;
|
||||
u32 hw_rev;
|
||||
u32 hw_rev_step;
|
||||
u32 hw_rf_id;
|
||||
u32 hw_id;
|
||||
char hw_id_str[52];
|
||||
|
@ -1384,10 +1389,12 @@ static inline void iwl_trans_set_pmi(struct iwl_trans *trans, bool state)
|
|||
trans->ops->set_pmi(trans, state);
|
||||
}
|
||||
|
||||
static inline void iwl_trans_sw_reset(struct iwl_trans *trans)
|
||||
static inline int iwl_trans_sw_reset(struct iwl_trans *trans,
|
||||
bool retake_ownership)
|
||||
{
|
||||
if (trans->ops->sw_reset)
|
||||
trans->ops->sw_reset(trans);
|
||||
return trans->ops->sw_reset(trans, retake_ownership);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
|
|
@ -119,6 +119,7 @@ struct iwl_sap_shared_mem_ctrl_blk {
|
|||
struct iwl_mei_shared_mem_ptrs {
|
||||
struct iwl_sap_shared_mem_ctrl_blk *ctrl;
|
||||
void *q_head[SAP_DIRECTION_MAX][SAP_QUEUE_IDX_MAX];
|
||||
size_t q_size[SAP_DIRECTION_MAX][SAP_QUEUE_IDX_MAX];
|
||||
};
|
||||
|
||||
struct iwl_mei_filters {
|
||||
|
@ -209,7 +210,7 @@ static void iwl_mei_free_shared_mem(struct mei_cl_device *cldev)
|
|||
struct iwl_mei *mei = mei_cldev_get_drvdata(cldev);
|
||||
|
||||
if (mei_cldev_dma_unmap(cldev))
|
||||
dev_err(&cldev->dev, "Coudln't unmap the shared mem properly\n");
|
||||
dev_err(&cldev->dev, "Couldn't unmap the shared mem properly\n");
|
||||
memset(&mei->shared_mem, 0, sizeof(mei->shared_mem));
|
||||
}
|
||||
|
||||
|
@ -271,6 +272,8 @@ static void iwl_mei_init_shared_mem(struct iwl_mei *mei)
|
|||
mem->q_head[dir][queue] = q_head;
|
||||
q_head +=
|
||||
le32_to_cpu(mem->ctrl->dir[dir].q_ctrl_blk[queue].size);
|
||||
mem->q_size[dir][queue] =
|
||||
le32_to_cpu(mem->ctrl->dir[dir].q_ctrl_blk[queue].size);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -280,11 +283,11 @@ static void iwl_mei_init_shared_mem(struct iwl_mei *mei)
|
|||
static ssize_t iwl_mei_write_cyclic_buf(struct mei_cl_device *cldev,
|
||||
struct iwl_sap_q_ctrl_blk *notif_q,
|
||||
u8 *q_head,
|
||||
const struct iwl_sap_hdr *hdr)
|
||||
const struct iwl_sap_hdr *hdr,
|
||||
u32 q_sz)
|
||||
{
|
||||
u32 rd = le32_to_cpu(READ_ONCE(notif_q->rd_ptr));
|
||||
u32 wr = le32_to_cpu(READ_ONCE(notif_q->wr_ptr));
|
||||
u32 q_sz = le32_to_cpu(notif_q->size);
|
||||
size_t room_in_buf;
|
||||
size_t tx_sz = sizeof(*hdr) + le16_to_cpu(hdr->len);
|
||||
|
||||
|
@ -382,6 +385,7 @@ static int iwl_mei_send_sap_msg_payload(struct mei_cl_device *cldev,
|
|||
struct iwl_sap_q_ctrl_blk *notif_q;
|
||||
struct iwl_sap_dir *dir;
|
||||
void *q_head;
|
||||
u32 q_sz;
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&iwl_mei_mutex);
|
||||
|
@ -404,7 +408,8 @@ static int iwl_mei_send_sap_msg_payload(struct mei_cl_device *cldev,
|
|||
dir = &mei->shared_mem.ctrl->dir[SAP_DIRECTION_HOST_TO_ME];
|
||||
notif_q = &dir->q_ctrl_blk[SAP_QUEUE_IDX_NOTIF];
|
||||
q_head = mei->shared_mem.q_head[SAP_DIRECTION_HOST_TO_ME][SAP_QUEUE_IDX_NOTIF];
|
||||
ret = iwl_mei_write_cyclic_buf(q_head, notif_q, q_head, hdr);
|
||||
q_sz = mei->shared_mem.q_size[SAP_DIRECTION_HOST_TO_ME][SAP_QUEUE_IDX_NOTIF];
|
||||
ret = iwl_mei_write_cyclic_buf(q_head, notif_q, q_head, hdr, q_sz);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
@ -454,10 +459,10 @@ void iwl_mei_add_data_to_ring(struct sk_buff *skb, bool cb_tx)
|
|||
dir = &mei->shared_mem.ctrl->dir[SAP_DIRECTION_HOST_TO_ME];
|
||||
notif_q = &dir->q_ctrl_blk[SAP_QUEUE_IDX_DATA];
|
||||
q_head = mei->shared_mem.q_head[SAP_DIRECTION_HOST_TO_ME][SAP_QUEUE_IDX_DATA];
|
||||
q_sz = mei->shared_mem.q_size[SAP_DIRECTION_HOST_TO_ME][SAP_QUEUE_IDX_DATA];
|
||||
|
||||
rd = le32_to_cpu(READ_ONCE(notif_q->rd_ptr));
|
||||
wr = le32_to_cpu(READ_ONCE(notif_q->wr_ptr));
|
||||
q_sz = le32_to_cpu(notif_q->size);
|
||||
hdr_sz = cb_tx ? sizeof(struct iwl_sap_cb_data) :
|
||||
sizeof(struct iwl_sap_hdr);
|
||||
tx_sz = skb->len + hdr_sz;
|
||||
|
@ -627,6 +632,8 @@ static void iwl_mei_handle_csme_filters(struct mei_cl_device *cldev,
|
|||
lockdep_is_held(&iwl_mei_mutex));
|
||||
|
||||
new_filters = kzalloc(sizeof(*new_filters), GFP_KERNEL);
|
||||
if (!new_filters)
|
||||
return;
|
||||
|
||||
/* Copy the OOB filters */
|
||||
new_filters->filters = filters->filters;
|
||||
|
@ -1074,11 +1081,11 @@ static void iwl_mei_handle_sap_rx_cmd(struct mei_cl_device *cldev,
|
|||
static void iwl_mei_handle_sap_rx(struct mei_cl_device *cldev,
|
||||
struct iwl_sap_q_ctrl_blk *notif_q,
|
||||
const u8 *q_head,
|
||||
struct sk_buff_head *skbs)
|
||||
struct sk_buff_head *skbs,
|
||||
u32 q_sz)
|
||||
{
|
||||
u32 rd = le32_to_cpu(READ_ONCE(notif_q->rd_ptr));
|
||||
u32 wr = le32_to_cpu(READ_ONCE(notif_q->wr_ptr));
|
||||
u32 q_sz = le32_to_cpu(notif_q->size);
|
||||
ssize_t valid_rx_sz;
|
||||
|
||||
if (rd > q_sz || wr > q_sz) {
|
||||
|
@ -1110,6 +1117,7 @@ static void iwl_mei_handle_check_shared_area(struct mei_cl_device *cldev)
|
|||
struct sk_buff_head tx_skbs;
|
||||
struct iwl_sap_dir *dir;
|
||||
void *q_head;
|
||||
u32 q_sz;
|
||||
|
||||
if (!mei->shared_mem.ctrl)
|
||||
return;
|
||||
|
@ -1117,22 +1125,24 @@ static void iwl_mei_handle_check_shared_area(struct mei_cl_device *cldev)
|
|||
dir = &mei->shared_mem.ctrl->dir[SAP_DIRECTION_ME_TO_HOST];
|
||||
notif_q = &dir->q_ctrl_blk[SAP_QUEUE_IDX_NOTIF];
|
||||
q_head = mei->shared_mem.q_head[SAP_DIRECTION_ME_TO_HOST][SAP_QUEUE_IDX_NOTIF];
|
||||
q_sz = mei->shared_mem.q_size[SAP_DIRECTION_ME_TO_HOST][SAP_QUEUE_IDX_NOTIF];
|
||||
|
||||
/*
|
||||
* Do not hold the mutex here, but rather each and every message
|
||||
* handler takes it.
|
||||
* This allows message handlers to take it at a certain time.
|
||||
*/
|
||||
iwl_mei_handle_sap_rx(cldev, notif_q, q_head, NULL);
|
||||
iwl_mei_handle_sap_rx(cldev, notif_q, q_head, NULL, q_sz);
|
||||
|
||||
mutex_lock(&iwl_mei_mutex);
|
||||
dir = &mei->shared_mem.ctrl->dir[SAP_DIRECTION_ME_TO_HOST];
|
||||
notif_q = &dir->q_ctrl_blk[SAP_QUEUE_IDX_DATA];
|
||||
q_head = mei->shared_mem.q_head[SAP_DIRECTION_ME_TO_HOST][SAP_QUEUE_IDX_DATA];
|
||||
q_sz = mei->shared_mem.q_size[SAP_DIRECTION_ME_TO_HOST][SAP_QUEUE_IDX_DATA];
|
||||
|
||||
__skb_queue_head_init(&tx_skbs);
|
||||
|
||||
iwl_mei_handle_sap_rx(cldev, notif_q, q_head, &tx_skbs);
|
||||
iwl_mei_handle_sap_rx(cldev, notif_q, q_head, &tx_skbs, q_sz);
|
||||
|
||||
if (skb_queue_empty(&tx_skbs)) {
|
||||
mutex_unlock(&iwl_mei_mutex);
|
||||
|
@ -1754,7 +1764,7 @@ static void iwl_mei_dbgfs_register(struct iwl_mei *mei)
|
|||
mei->dbgfs_dir, &iwl_mei_status);
|
||||
debugfs_create_file("send_start_message", S_IWUSR, mei->dbgfs_dir,
|
||||
mei, &iwl_mei_dbgfs_send_start_message_ops);
|
||||
debugfs_create_file("req_ownserhip", S_IWUSR, mei->dbgfs_dir,
|
||||
debugfs_create_file("req_ownership", S_IWUSR, mei->dbgfs_dir,
|
||||
mei, &iwl_mei_dbgfs_req_ownership_ops);
|
||||
}
|
||||
|
||||
|
|
|
@ -1390,6 +1390,13 @@ struct iwl_wowlan_status_data {
|
|||
u16 qos_seq_ctr[8];
|
||||
u8 tid_tear_down;
|
||||
|
||||
struct {
|
||||
/* including RX MIC key for TKIP */
|
||||
u8 key[WOWLAN_KEY_MAX_SIZE];
|
||||
u8 len;
|
||||
u8 flags;
|
||||
} gtk;
|
||||
|
||||
struct {
|
||||
/*
|
||||
* We store both the TKIP and AES representations
|
||||
|
@ -1400,11 +1407,15 @@ struct iwl_wowlan_status_data {
|
|||
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;
|
||||
|
||||
/*
|
||||
* We use -1 for when we have valid data but don't know
|
||||
* the key ID from firmware, and thus it needs to be
|
||||
* installed with the last key (depending on rekeying).
|
||||
*/
|
||||
s8 key_id;
|
||||
bool valid;
|
||||
} gtk_seq[2];
|
||||
|
||||
struct {
|
||||
/* Same as above */
|
||||
|
@ -1556,12 +1567,10 @@ static void iwl_mvm_report_wakeup_reasons(struct iwl_mvm *mvm,
|
|||
kfree_skb(pkt);
|
||||
}
|
||||
|
||||
static void iwl_mvm_aes_sc_to_seq(struct aes_sc *sc,
|
||||
struct ieee80211_key_seq *seq)
|
||||
static void iwl_mvm_le64_to_aes_seq(__le64 le_pn, struct ieee80211_key_seq *seq)
|
||||
{
|
||||
u64 pn;
|
||||
u64 pn = le64_to_cpu(le_pn);
|
||||
|
||||
pn = le64_to_cpu(sc->pn);
|
||||
seq->ccmp.pn[0] = pn >> 40;
|
||||
seq->ccmp.pn[1] = pn >> 32;
|
||||
seq->ccmp.pn[2] = pn >> 24;
|
||||
|
@ -1570,6 +1579,20 @@ static void iwl_mvm_aes_sc_to_seq(struct aes_sc *sc,
|
|||
seq->ccmp.pn[5] = pn;
|
||||
}
|
||||
|
||||
static void iwl_mvm_aes_sc_to_seq(struct aes_sc *sc,
|
||||
struct ieee80211_key_seq *seq)
|
||||
{
|
||||
iwl_mvm_le64_to_aes_seq(sc->pn, seq);
|
||||
}
|
||||
|
||||
static void iwl_mvm_le64_to_tkip_seq(__le64 le_pn, struct ieee80211_key_seq *seq)
|
||||
{
|
||||
u64 pn = le64_to_cpu(le_pn);
|
||||
|
||||
seq->tkip.iv16 = (u16)pn;
|
||||
seq->tkip.iv32 = (u32)(pn >> 16);
|
||||
}
|
||||
|
||||
static void iwl_mvm_tkip_sc_to_seq(struct tkip_sc *sc,
|
||||
struct ieee80211_key_seq *seq)
|
||||
{
|
||||
|
@ -1630,10 +1653,12 @@ static void iwl_mvm_convert_key_counters(struct iwl_wowlan_status_data *status,
|
|||
/* 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]);
|
||||
&status->gtk_seq[0].tkip.seq[i]);
|
||||
iwl_mvm_aes_sc_to_seq(&sc->aes.multicast_rsc[i],
|
||||
&status->gtk.aes.seq[i]);
|
||||
&status->gtk_seq[0].aes.seq[i]);
|
||||
}
|
||||
status->gtk_seq[0].valid = true;
|
||||
status->gtk_seq[0].key_id = -1;
|
||||
|
||||
/* PTK TX counter */
|
||||
status->ptk.tkip.tx_pn = (u64)le16_to_cpu(sc->tkip.tsc.iv16) |
|
||||
|
@ -1649,24 +1674,103 @@ static void iwl_mvm_convert_key_counters(struct iwl_wowlan_status_data *status,
|
|||
}
|
||||
}
|
||||
|
||||
static void iwl_mvm_set_key_rx_seq(struct iwl_mvm *mvm,
|
||||
struct ieee80211_key_conf *key,
|
||||
struct iwl_wowlan_status_data *status)
|
||||
static void
|
||||
iwl_mvm_convert_key_counters_v5_gtk_seq(struct iwl_wowlan_status_data *status,
|
||||
struct iwl_wowlan_all_rsc_tsc_v5 *sc,
|
||||
unsigned int idx, unsigned int key_id)
|
||||
{
|
||||
int tid;
|
||||
|
||||
for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) {
|
||||
iwl_mvm_le64_to_tkip_seq(sc->mcast_rsc[idx][tid],
|
||||
&status->gtk_seq[idx].tkip.seq[tid]);
|
||||
iwl_mvm_le64_to_aes_seq(sc->mcast_rsc[idx][tid],
|
||||
&status->gtk_seq[idx].aes.seq[tid]);
|
||||
}
|
||||
|
||||
status->gtk_seq[idx].valid = true;
|
||||
status->gtk_seq[idx].key_id = key_id;
|
||||
}
|
||||
|
||||
static void
|
||||
iwl_mvm_convert_key_counters_v5(struct iwl_wowlan_status_data *status,
|
||||
struct iwl_wowlan_all_rsc_tsc_v5 *sc)
|
||||
{
|
||||
int i, tid;
|
||||
|
||||
BUILD_BUG_ON(IWL_MAX_TID_COUNT > IWL_MAX_TID_COUNT);
|
||||
BUILD_BUG_ON(IWL_MAX_TID_COUNT > IWL_NUM_RSC);
|
||||
BUILD_BUG_ON(ARRAY_SIZE(sc->mcast_rsc) != ARRAY_SIZE(status->gtk_seq));
|
||||
|
||||
/* GTK RX counters */
|
||||
for (i = 0; i < ARRAY_SIZE(sc->mcast_key_id_map); i++) {
|
||||
u8 entry = sc->mcast_key_id_map[i];
|
||||
|
||||
if (entry < ARRAY_SIZE(sc->mcast_rsc))
|
||||
iwl_mvm_convert_key_counters_v5_gtk_seq(status, sc,
|
||||
entry, i);
|
||||
}
|
||||
|
||||
/* PTK TX counters not needed, assigned in device */
|
||||
|
||||
/* PTK RX counters */
|
||||
for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) {
|
||||
iwl_mvm_le64_to_tkip_seq(sc->ucast_rsc[tid],
|
||||
&status->ptk.tkip.seq[tid]);
|
||||
iwl_mvm_le64_to_aes_seq(sc->ucast_rsc[tid],
|
||||
&status->ptk.aes.seq[tid]);
|
||||
}
|
||||
}
|
||||
|
||||
static void iwl_mvm_set_key_rx_seq_idx(struct ieee80211_key_conf *key,
|
||||
struct iwl_wowlan_status_data *status,
|
||||
int idx)
|
||||
{
|
||||
switch (key->cipher) {
|
||||
case WLAN_CIPHER_SUITE_CCMP:
|
||||
case WLAN_CIPHER_SUITE_GCMP:
|
||||
case WLAN_CIPHER_SUITE_GCMP_256:
|
||||
iwl_mvm_set_key_rx_seq_tids(key, status->gtk.aes.seq);
|
||||
iwl_mvm_set_key_rx_seq_tids(key, status->gtk_seq[idx].aes.seq);
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_TKIP:
|
||||
iwl_mvm_set_key_rx_seq_tids(key, status->gtk.tkip.seq);
|
||||
iwl_mvm_set_key_rx_seq_tids(key, status->gtk_seq[idx].tkip.seq);
|
||||
break;
|
||||
default:
|
||||
WARN_ON(1);
|
||||
}
|
||||
}
|
||||
|
||||
static void iwl_mvm_set_key_rx_seq(struct ieee80211_key_conf *key,
|
||||
struct iwl_wowlan_status_data *status,
|
||||
bool installed)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(status->gtk_seq); i++) {
|
||||
if (!status->gtk_seq[i].valid)
|
||||
continue;
|
||||
|
||||
/* Handle the case where we know the key ID */
|
||||
if (status->gtk_seq[i].key_id == key->keyidx) {
|
||||
s8 new_key_id = -1;
|
||||
|
||||
if (status->num_of_gtk_rekeys)
|
||||
new_key_id = status->gtk.flags &
|
||||
IWL_WOWLAN_GTK_IDX_MASK;
|
||||
|
||||
/* Don't install a new key's value to an old key */
|
||||
if (new_key_id != key->keyidx)
|
||||
iwl_mvm_set_key_rx_seq_idx(key, status, i);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* handle the case where we didn't, last key only */
|
||||
if (status->gtk_seq[i].key_id == -1 &&
|
||||
(!status->num_of_gtk_rekeys || installed))
|
||||
iwl_mvm_set_key_rx_seq_idx(key, status, i);
|
||||
}
|
||||
}
|
||||
|
||||
struct iwl_mvm_d3_gtk_iter_data {
|
||||
struct iwl_mvm *mvm;
|
||||
struct iwl_wowlan_status_data *status;
|
||||
|
@ -1740,8 +1844,9 @@ static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw,
|
|||
|
||||
if (data->status->num_of_gtk_rekeys)
|
||||
ieee80211_remove_key(key);
|
||||
else if (data->last_gtk == key)
|
||||
iwl_mvm_set_key_rx_seq(data->mvm, key, data->status);
|
||||
|
||||
if (data->last_gtk == key)
|
||||
iwl_mvm_set_key_rx_seq(key, data->status, false);
|
||||
}
|
||||
|
||||
static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,
|
||||
|
@ -1825,7 +1930,7 @@ static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,
|
|||
key = ieee80211_gtk_rekey_add(vif, &conf.conf);
|
||||
if (IS_ERR(key))
|
||||
return false;
|
||||
iwl_mvm_set_key_rx_seq(mvm, key, status);
|
||||
iwl_mvm_set_key_rx_seq(key, status, true);
|
||||
|
||||
replay_ctr = cpu_to_be64(status->replay_ctr);
|
||||
|
||||
|
@ -1893,9 +1998,10 @@ iwl_mvm_parse_wowlan_status_common_ ## _ver(struct iwl_mvm *mvm, \
|
|||
iwl_mvm_parse_wowlan_status_common(v6)
|
||||
iwl_mvm_parse_wowlan_status_common(v7)
|
||||
iwl_mvm_parse_wowlan_status_common(v9)
|
||||
iwl_mvm_parse_wowlan_status_common(v12)
|
||||
|
||||
static void iwl_mvm_convert_gtk(struct iwl_wowlan_status_data *status,
|
||||
struct iwl_wowlan_gtk_status *data)
|
||||
static void iwl_mvm_convert_gtk_v2(struct iwl_wowlan_status_data *status,
|
||||
struct iwl_wowlan_gtk_status_v2 *data)
|
||||
{
|
||||
BUILD_BUG_ON(sizeof(status->gtk.key) < sizeof(data->key));
|
||||
BUILD_BUG_ON(NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY +
|
||||
|
@ -1913,6 +2019,26 @@ static void iwl_mvm_convert_gtk(struct iwl_wowlan_status_data *status,
|
|||
data->tkip_mic_key, sizeof(data->tkip_mic_key));
|
||||
}
|
||||
|
||||
static void iwl_mvm_convert_gtk_v3(struct iwl_wowlan_status_data *status,
|
||||
struct iwl_wowlan_gtk_status_v3 *data)
|
||||
{
|
||||
/* The parts we need are identical in v2 and v3 */
|
||||
#define CHECK(_f) do { \
|
||||
BUILD_BUG_ON(offsetof(struct iwl_wowlan_gtk_status_v2, _f) != \
|
||||
offsetof(struct iwl_wowlan_gtk_status_v3, _f)); \
|
||||
BUILD_BUG_ON(offsetofend(struct iwl_wowlan_gtk_status_v2, _f) !=\
|
||||
offsetofend(struct iwl_wowlan_gtk_status_v3, _f)); \
|
||||
} while (0)
|
||||
|
||||
CHECK(key);
|
||||
CHECK(key_len);
|
||||
CHECK(key_flags);
|
||||
CHECK(tkip_mic_key);
|
||||
#undef CHECK
|
||||
|
||||
iwl_mvm_convert_gtk_v2(status, (void *)data);
|
||||
}
|
||||
|
||||
static void iwl_mvm_convert_igtk(struct iwl_wowlan_status_data *status,
|
||||
struct iwl_wowlan_igtk_status *data)
|
||||
{
|
||||
|
@ -2012,7 +2138,7 @@ iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id)
|
|||
goto out_free_resp;
|
||||
|
||||
iwl_mvm_convert_key_counters(status, &v7->gtk[0].rsc.all_tsc_rsc);
|
||||
iwl_mvm_convert_gtk(status, &v7->gtk[0]);
|
||||
iwl_mvm_convert_gtk_v2(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;
|
||||
|
@ -2025,10 +2151,22 @@ iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id)
|
|||
goto out_free_resp;
|
||||
|
||||
iwl_mvm_convert_key_counters(status, &v9->gtk[0].rsc.all_tsc_rsc);
|
||||
iwl_mvm_convert_gtk(status, &v9->gtk[0]);
|
||||
iwl_mvm_convert_gtk_v2(status, &v9->gtk[0]);
|
||||
iwl_mvm_convert_igtk(status, &v9->igtk[0]);
|
||||
|
||||
status->tid_tear_down = v9->tid_tear_down;
|
||||
} else if (notif_ver == 12) {
|
||||
struct iwl_wowlan_status_v12 *v12 = (void *)cmd.resp_pkt->data;
|
||||
|
||||
status = iwl_mvm_parse_wowlan_status_common_v12(mvm, v12, len);
|
||||
if (IS_ERR(status))
|
||||
goto out_free_resp;
|
||||
|
||||
iwl_mvm_convert_key_counters_v5(status, &v12->gtk[0].sc);
|
||||
iwl_mvm_convert_gtk_v3(status, &v12->gtk[0]);
|
||||
iwl_mvm_convert_igtk(status, &v12->igtk[0]);
|
||||
|
||||
status->tid_tear_down = v12->tid_tear_down;
|
||||
} else {
|
||||
IWL_ERR(mvm,
|
||||
"Firmware advertises unknown WoWLAN status response %d!\n",
|
||||
|
|
|
@ -1022,6 +1022,11 @@ static ssize_t iwl_dbgfs_fw_restart_write(struct iwl_mvm *mvm, char *buf,
|
|||
if (mvm->fw_restart >= 0)
|
||||
mvm->fw_restart++;
|
||||
|
||||
if (count == 6 && !strcmp(buf, "nolog\n")) {
|
||||
set_bit(IWL_MVM_STATUS_SUPPRESS_ERROR_LOG_ONCE, &mvm->status);
|
||||
set_bit(STATUS_SUPPRESS_CMD_ERROR_ONCE, &mvm->trans->status);
|
||||
}
|
||||
|
||||
/* take the return value to make compiler happy - it will fail anyway */
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm,
|
||||
WIDE_ID(LONG_GROUP, REPLY_ERROR),
|
||||
|
@ -1038,6 +1043,9 @@ static ssize_t iwl_dbgfs_fw_nmi_write(struct iwl_mvm *mvm, char *buf,
|
|||
if (!iwl_mvm_firmware_running(mvm))
|
||||
return -EIO;
|
||||
|
||||
if (count == 6 && !strcmp(buf, "nolog\n"))
|
||||
set_bit(IWL_MVM_STATUS_SUPPRESS_ERROR_LOG_ONCE, &mvm->status);
|
||||
|
||||
iwl_force_nmi(mvm->trans);
|
||||
|
||||
return count;
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
#include "fw/api/datapath.h"
|
||||
#include "fw/api/phy.h"
|
||||
#include "fw/api/config.h"
|
||||
#include "fw/api/soc.h"
|
||||
#include "fw/api/system.h"
|
||||
#include "fw/api/alive.h"
|
||||
#include "fw/api/binding.h"
|
||||
#include "fw/api/cmdhdr.h"
|
||||
|
|
|
@ -123,13 +123,15 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
|
|||
struct iwl_lmac_alive *lmac2 = NULL;
|
||||
u16 status;
|
||||
u32 lmac_error_event_table, umac_error_table;
|
||||
u32 version = iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP,
|
||||
UCODE_ALIVE_NTFY, 0);
|
||||
|
||||
/*
|
||||
* For v5 and above, we can check the version, for older
|
||||
* versions we need to check the size.
|
||||
*/
|
||||
if (iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP,
|
||||
UCODE_ALIVE_NTFY, 0) == 5) {
|
||||
if (version == 5 || version == 6) {
|
||||
/* v5 and v6 are compatible (only IMR addition) */
|
||||
struct iwl_alive_ntf_v5 *palive;
|
||||
|
||||
if (pkt_len < sizeof(*palive))
|
||||
|
@ -516,7 +518,6 @@ static void iwl_mvm_phy_filter_init(struct iwl_mvm *mvm,
|
|||
cpu_to_le32(IWL_MVM_PHY_FILTER_CHAIN_D);
|
||||
}
|
||||
}
|
||||
|
||||
#else /* CONFIG_ACPI */
|
||||
|
||||
static void iwl_mvm_phy_filter_init(struct iwl_mvm *mvm,
|
||||
|
@ -525,6 +526,49 @@ static void iwl_mvm_phy_filter_init(struct iwl_mvm *mvm,
|
|||
}
|
||||
#endif /* CONFIG_ACPI */
|
||||
|
||||
#if defined(CONFIG_ACPI) && defined(CONFIG_EFI)
|
||||
static int iwl_mvm_sgom_init(struct iwl_mvm *mvm)
|
||||
{
|
||||
u8 cmd_ver;
|
||||
int ret;
|
||||
struct iwl_host_cmd cmd = {
|
||||
.id = WIDE_ID(REGULATORY_AND_NVM_GROUP,
|
||||
SAR_OFFSET_MAPPING_TABLE_CMD),
|
||||
.flags = 0,
|
||||
.data[0] = &mvm->fwrt.sgom_table,
|
||||
.len[0] = sizeof(mvm->fwrt.sgom_table),
|
||||
.dataflags[0] = IWL_HCMD_DFL_NOCOPY,
|
||||
};
|
||||
|
||||
if (!mvm->fwrt.sgom_enabled) {
|
||||
IWL_DEBUG_RADIO(mvm, "SGOM table is disabled\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, REGULATORY_AND_NVM_GROUP,
|
||||
SAR_OFFSET_MAPPING_TABLE_CMD,
|
||||
IWL_FW_CMD_VER_UNKNOWN);
|
||||
|
||||
if (cmd_ver != 2) {
|
||||
IWL_DEBUG_RADIO(mvm, "command version is unsupported. version = %d\n",
|
||||
cmd_ver);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = iwl_mvm_send_cmd(mvm, &cmd);
|
||||
if (ret < 0)
|
||||
IWL_ERR(mvm, "failed to send SAR_OFFSET_MAPPING_CMD (%d)\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
|
||||
static int iwl_mvm_sgom_init(struct iwl_mvm *mvm)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm)
|
||||
{
|
||||
struct iwl_phy_cfg_cmd_v3 phy_cfg_cmd;
|
||||
|
@ -1338,6 +1382,7 @@ static u8 iwl_mvm_eval_dsm_rfi(struct iwl_mvm *mvm)
|
|||
void iwl_mvm_get_acpi_tables(struct iwl_mvm *mvm)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ACPI */
|
||||
|
||||
void iwl_mvm_send_recovery_cmd(struct iwl_mvm *mvm, u32 flags)
|
||||
|
@ -1632,6 +1677,10 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
|
|||
else if (ret < 0)
|
||||
goto error;
|
||||
|
||||
ret = iwl_mvm_sgom_init(mvm);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
iwl_mvm_tas_init(mvm);
|
||||
iwl_mvm_leds_sync(mvm);
|
||||
|
||||
|
|
|
@ -1732,6 +1732,7 @@ static void iwl_mvm_recalc_multicast(struct iwl_mvm *mvm)
|
|||
struct iwl_mvm_mc_iter_data iter_data = {
|
||||
.mvm = mvm,
|
||||
};
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
|
@ -1741,6 +1742,22 @@ static void iwl_mvm_recalc_multicast(struct iwl_mvm *mvm)
|
|||
ieee80211_iterate_active_interfaces_atomic(
|
||||
mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
|
||||
iwl_mvm_mc_iface_iterator, &iter_data);
|
||||
|
||||
/*
|
||||
* Send a (synchronous) ech command so that we wait for the
|
||||
* multiple asynchronous MCAST_FILTER_CMD commands sent by
|
||||
* the interface iterator. Otherwise, we might get here over
|
||||
* and over again (by userspace just sending a lot of these)
|
||||
* and the CPU can send them faster than the firmware can
|
||||
* process them.
|
||||
* Note that the CPU is still faster - but with this we'll
|
||||
* actually send fewer commands overall because the CPU will
|
||||
* not schedule the work in mac80211 as frequently if it's
|
||||
* still running when rescheduled (possibly multiple times).
|
||||
*/
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, ECHO_CMD, 0, 0, NULL);
|
||||
if (ret)
|
||||
IWL_ERR(mvm, "Failed to synchronize multicast groups update\n");
|
||||
}
|
||||
|
||||
static u64 iwl_mvm_prepare_multicast(struct ieee80211_hw *hw,
|
||||
|
@ -3388,6 +3405,11 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
|
|||
true);
|
||||
} else if (old_state == IEEE80211_STA_AUTHORIZED &&
|
||||
new_state == IEEE80211_STA_ASSOC) {
|
||||
/* once we move into assoc state, need to update rate scale to
|
||||
* disable using wide bandwidth
|
||||
*/
|
||||
iwl_mvm_rs_rate_init(mvm, sta, mvmvif->phy_ctxt->channel->band,
|
||||
false);
|
||||
if (!sta->tdls) {
|
||||
/* Multicast data frames are no longer allowed */
|
||||
iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
|
||||
|
@ -3410,16 +3432,16 @@ 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 */
|
||||
} else if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
|
||||
iwl_mvm_stop_session_protection(mvm, vif);
|
||||
}
|
||||
ret = 0;
|
||||
} else if (old_state == IEEE80211_STA_AUTH &&
|
||||
new_state == IEEE80211_STA_NONE) {
|
||||
ret = 0;
|
||||
} else if (old_state == IEEE80211_STA_NONE &&
|
||||
new_state == IEEE80211_STA_NOTEXIST) {
|
||||
if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
|
||||
iwl_mvm_stop_session_protection(mvm, vif);
|
||||
ret = iwl_mvm_rm_sta(mvm, vif, sta);
|
||||
if (sta->tdls) {
|
||||
iwl_mvm_recalc_tdls_state(mvm, vif, false);
|
||||
|
@ -3585,13 +3607,14 @@ static int __iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
|
|||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
struct iwl_mvm_sta *mvmsta;
|
||||
struct iwl_mvm_sta *mvmsta = NULL;
|
||||
struct iwl_mvm_key_pn *ptk_pn;
|
||||
int keyidx = key->keyidx;
|
||||
int ret, i;
|
||||
u8 key_offset;
|
||||
|
||||
mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
if (sta)
|
||||
mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
|
||||
switch (key->cipher) {
|
||||
case WLAN_CIPHER_SUITE_TKIP:
|
||||
|
@ -3693,7 +3716,7 @@ static int __iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
|
|||
}
|
||||
|
||||
if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) &&
|
||||
sta && iwl_mvm_has_new_rx_api(mvm) &&
|
||||
mvmsta && iwl_mvm_has_new_rx_api(mvm) &&
|
||||
key->flags & IEEE80211_KEY_FLAG_PAIRWISE &&
|
||||
(key->cipher == WLAN_CIPHER_SUITE_CCMP ||
|
||||
key->cipher == WLAN_CIPHER_SUITE_GCMP ||
|
||||
|
@ -3727,7 +3750,7 @@ static int __iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
|
|||
else
|
||||
key_offset = STA_KEY_IDX_INVALID;
|
||||
|
||||
if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
|
||||
if (mvmsta && key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
|
||||
mvmsta->pairwise_cipher = key->cipher;
|
||||
|
||||
IWL_DEBUG_MAC80211(mvm, "set hwcrypto key\n");
|
||||
|
@ -3770,7 +3793,7 @@ static int __iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
|
|||
break;
|
||||
}
|
||||
|
||||
if (sta && iwl_mvm_has_new_rx_api(mvm) &&
|
||||
if (mvmsta && iwl_mvm_has_new_rx_api(mvm) &&
|
||||
key->flags & IEEE80211_KEY_FLAG_PAIRWISE &&
|
||||
(key->cipher == WLAN_CIPHER_SUITE_CCMP ||
|
||||
key->cipher == WLAN_CIPHER_SUITE_GCMP ||
|
||||
|
|
|
@ -94,11 +94,10 @@ struct iwl_mvm_phy_ctxt {
|
|||
|
||||
enum nl80211_chan_width width;
|
||||
|
||||
/*
|
||||
* TODO: This should probably be removed. Currently here only for rate
|
||||
* scaling algorithm
|
||||
*/
|
||||
struct ieee80211_channel *channel;
|
||||
|
||||
/* track for RLC config command */
|
||||
u32 center_freq1;
|
||||
};
|
||||
|
||||
struct iwl_mvm_time_event_data {
|
||||
|
@ -1138,6 +1137,8 @@ struct iwl_mvm {
|
|||
* @IWL_MVM_STATUS_FIRMWARE_RUNNING: firmware is running
|
||||
* @IWL_MVM_STATUS_NEED_FLUSH_P2P: need to flush P2P bcast STA
|
||||
* @IWL_MVM_STATUS_IN_D3: in D3 (or at least about to go into it)
|
||||
* @IWL_MVM_STATUS_SUPPRESS_ERROR_LOG_ONCE: suppress one error log
|
||||
* if this is set, when intentionally triggered
|
||||
* @IWL_MVM_STATUS_STARTING: starting mac,
|
||||
* used to disable restart flow while in STARTING state
|
||||
*/
|
||||
|
@ -1151,6 +1152,7 @@ enum iwl_mvm_status {
|
|||
IWL_MVM_STATUS_FIRMWARE_RUNNING,
|
||||
IWL_MVM_STATUS_NEED_FLUSH_P2P,
|
||||
IWL_MVM_STATUS_IN_D3,
|
||||
IWL_MVM_STATUS_SUPPRESS_ERROR_LOG_ONCE,
|
||||
IWL_MVM_STATUS_STARTING,
|
||||
};
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "time-event.h"
|
||||
#include "fw-api.h"
|
||||
#include "fw/acpi.h"
|
||||
#include "fw/uefi.h"
|
||||
|
||||
#define DRV_DESCRIPTION "The new Intel(R) wireless AGN driver for Linux"
|
||||
MODULE_DESCRIPTION(DRV_DESCRIPTION);
|
||||
|
@ -78,7 +79,7 @@ static void iwl_mvm_nic_config(struct iwl_op_mode *op_mode)
|
|||
{
|
||||
struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
|
||||
u8 radio_cfg_type, radio_cfg_step, radio_cfg_dash;
|
||||
u32 reg_val = 0;
|
||||
u32 reg_val;
|
||||
u32 phy_config = iwl_mvm_get_phy_config(mvm);
|
||||
|
||||
radio_cfg_type = (phy_config & FW_PHY_CFG_RADIO_TYPE) >>
|
||||
|
@ -89,10 +90,7 @@ static void iwl_mvm_nic_config(struct iwl_op_mode *op_mode)
|
|||
FW_PHY_CFG_RADIO_DASH_POS;
|
||||
|
||||
/* SKU control */
|
||||
reg_val |= CSR_HW_REV_STEP(mvm->trans->hw_rev) <<
|
||||
CSR_HW_IF_CONFIG_REG_POS_MAC_STEP;
|
||||
reg_val |= CSR_HW_REV_DASH(mvm->trans->hw_rev) <<
|
||||
CSR_HW_IF_CONFIG_REG_POS_MAC_DASH;
|
||||
reg_val = CSR_HW_REV_STEP_DASH(mvm->trans->hw_rev);
|
||||
|
||||
/* radio configuration */
|
||||
reg_val |= radio_cfg_type << CSR_HW_IF_CONFIG_REG_POS_PHY_TYPE;
|
||||
|
@ -117,8 +115,7 @@ static void iwl_mvm_nic_config(struct iwl_op_mode *op_mode)
|
|||
reg_val |= CSR_HW_IF_CONFIG_REG_D3_DEBUG;
|
||||
|
||||
iwl_trans_set_bits_mask(mvm->trans, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH |
|
||||
CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP |
|
||||
CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP_DASH |
|
||||
CSR_HW_IF_CONFIG_REG_MSK_PHY_TYPE |
|
||||
CSR_HW_IF_CONFIG_REG_MSK_PHY_STEP |
|
||||
CSR_HW_IF_CONFIG_REG_MSK_PHY_DASH |
|
||||
|
@ -502,6 +499,9 @@ static const struct iwl_hcmd_names iwl_mvm_system_names[] = {
|
|||
HCMD_NAME(SHARED_MEM_CFG_CMD),
|
||||
HCMD_NAME(INIT_EXTENDED_CFG_CMD),
|
||||
HCMD_NAME(FW_ERROR_RECOVERY_CMD),
|
||||
HCMD_NAME(RFI_CONFIG_CMD),
|
||||
HCMD_NAME(RFI_GET_FREQ_TABLE_CMD),
|
||||
HCMD_NAME(SYSTEM_FEATURES_CONTROL_CMD),
|
||||
};
|
||||
|
||||
/* Please keep this array *SORTED* by hex value.
|
||||
|
@ -534,6 +534,7 @@ static const struct iwl_hcmd_names iwl_mvm_data_path_names[] = {
|
|||
HCMD_NAME(UPDATE_MU_GROUPS_CMD),
|
||||
HCMD_NAME(TRIGGER_RX_QUEUES_NOTIF_CMD),
|
||||
HCMD_NAME(STA_HE_CTXT_CMD),
|
||||
HCMD_NAME(RLC_CONFIG_CMD),
|
||||
HCMD_NAME(RFH_QUEUE_CONFIG_CMD),
|
||||
HCMD_NAME(TLC_MNG_CONFIG_CMD),
|
||||
HCMD_NAME(CHEST_COLLECTOR_FILTER_CONFIG_CMD),
|
||||
|
@ -1057,7 +1058,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
|||
};
|
||||
int scan_size;
|
||||
u32 min_backoff;
|
||||
enum iwl_amsdu_size rb_size_default;
|
||||
struct iwl_mvm_csme_conn_info *csme_conn_info __maybe_unused;
|
||||
|
||||
/*
|
||||
|
@ -1097,6 +1097,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
|||
&iwl_mvm_sanitize_ops, mvm, dbgfs_dir);
|
||||
|
||||
iwl_mvm_get_acpi_tables(mvm);
|
||||
iwl_uefi_get_sgom_table(trans, &mvm->fwrt);
|
||||
|
||||
mvm->init_status = 0;
|
||||
|
||||
|
@ -1200,14 +1201,9 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
|||
trans_cfg.no_reclaim_cmds = no_reclaim_cmds;
|
||||
trans_cfg.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds);
|
||||
|
||||
if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
|
||||
rb_size_default = IWL_AMSDU_2K;
|
||||
else
|
||||
rb_size_default = IWL_AMSDU_4K;
|
||||
|
||||
switch (iwlwifi_mod_params.amsdu_size) {
|
||||
case IWL_AMSDU_DEF:
|
||||
trans_cfg.rx_buf_size = rb_size_default;
|
||||
trans_cfg.rx_buf_size = IWL_AMSDU_4K;
|
||||
break;
|
||||
case IWL_AMSDU_4K:
|
||||
trans_cfg.rx_buf_size = IWL_AMSDU_4K;
|
||||
|
@ -1221,7 +1217,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
|||
default:
|
||||
pr_err("%s: Unsupported amsdu_size: %d\n", KBUILD_MODNAME,
|
||||
iwlwifi_mod_params.amsdu_size);
|
||||
trans_cfg.rx_buf_size = rb_size_default;
|
||||
trans_cfg.rx_buf_size = IWL_AMSDU_4K;
|
||||
}
|
||||
|
||||
trans->wide_cmd_header = true;
|
||||
|
@ -1850,7 +1846,9 @@ static void iwl_mvm_nic_error(struct iwl_op_mode *op_mode, bool sync)
|
|||
{
|
||||
struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
|
||||
|
||||
if (!test_bit(STATUS_TRANS_DEAD, &mvm->trans->status))
|
||||
if (!test_bit(STATUS_TRANS_DEAD, &mvm->trans->status) &&
|
||||
!test_and_clear_bit(IWL_MVM_STATUS_SUPPRESS_ERROR_LOG_ONCE,
|
||||
&mvm->status))
|
||||
iwl_mvm_dump_nic_error_log(mvm);
|
||||
|
||||
if (sync) {
|
||||
|
|
|
@ -157,8 +157,43 @@ static void iwl_mvm_phy_ctxt_cmd_data(struct iwl_mvm *mvm,
|
|||
/* Set the channel info data */
|
||||
iwl_mvm_set_chan_info_chandef(mvm, &cmd->ci, chandef);
|
||||
|
||||
iwl_mvm_phy_ctxt_set_rxchain(mvm, ctxt, &cmd->rxchain_info,
|
||||
/* we only support RLC command version 2 */
|
||||
if (iwl_fw_lookup_cmd_ver(mvm->fw, DATA_PATH_GROUP,
|
||||
RLC_CONFIG_CMD, 0) < 2)
|
||||
iwl_mvm_phy_ctxt_set_rxchain(mvm, ctxt, &cmd->rxchain_info,
|
||||
chains_static, chains_dynamic);
|
||||
}
|
||||
|
||||
static int iwl_mvm_phy_send_rlc(struct iwl_mvm *mvm,
|
||||
struct iwl_mvm_phy_ctxt *ctxt,
|
||||
u8 chains_static, u8 chains_dynamic)
|
||||
{
|
||||
struct iwl_rlc_config_cmd cmd = {
|
||||
.phy_id = cpu_to_le32(ctxt->id),
|
||||
};
|
||||
|
||||
if (iwl_fw_lookup_cmd_ver(mvm->fw, DATA_PATH_GROUP,
|
||||
RLC_CONFIG_CMD, 0) < 2)
|
||||
return 0;
|
||||
|
||||
BUILD_BUG_ON(IWL_RLC_CHAIN_INFO_DRIVER_FORCE !=
|
||||
PHY_RX_CHAIN_DRIVER_FORCE_MSK);
|
||||
BUILD_BUG_ON(IWL_RLC_CHAIN_INFO_VALID !=
|
||||
PHY_RX_CHAIN_VALID_MSK);
|
||||
BUILD_BUG_ON(IWL_RLC_CHAIN_INFO_FORCE !=
|
||||
PHY_RX_CHAIN_FORCE_SEL_MSK);
|
||||
BUILD_BUG_ON(IWL_RLC_CHAIN_INFO_FORCE_MIMO !=
|
||||
PHY_RX_CHAIN_FORCE_MIMO_SEL_MSK);
|
||||
BUILD_BUG_ON(IWL_RLC_CHAIN_INFO_COUNT != PHY_RX_CHAIN_CNT_MSK);
|
||||
BUILD_BUG_ON(IWL_RLC_CHAIN_INFO_MIMO_COUNT !=
|
||||
PHY_RX_CHAIN_MIMO_CNT_MSK);
|
||||
|
||||
iwl_mvm_phy_ctxt_set_rxchain(mvm, ctxt, &cmd.rlc.rx_chain_info,
|
||||
chains_static, chains_dynamic);
|
||||
|
||||
return iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(RLC_CONFIG_CMD,
|
||||
DATA_PATH_GROUP, 2),
|
||||
0, sizeof(cmd), &cmd);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -177,7 +212,7 @@ static int iwl_mvm_phy_ctxt_apply(struct iwl_mvm *mvm,
|
|||
int ver = iwl_fw_lookup_cmd_ver(mvm->fw, IWL_ALWAYS_LONG_GROUP,
|
||||
PHY_CONTEXT_CMD, 1);
|
||||
|
||||
if (ver == 3) {
|
||||
if (ver == 3 || ver == 4) {
|
||||
struct iwl_phy_context_cmd cmd = {};
|
||||
|
||||
/* Set the command header fields */
|
||||
|
@ -211,9 +246,16 @@ static int iwl_mvm_phy_ctxt_apply(struct iwl_mvm *mvm,
|
|||
}
|
||||
|
||||
|
||||
if (ret)
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "PHY ctxt cmd error. ret=%d\n", ret);
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (action != FW_CTXT_ACTION_REMOVE)
|
||||
return iwl_mvm_phy_send_rlc(mvm, ctxt, chains_static,
|
||||
chains_dynamic);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -228,6 +270,8 @@ int iwl_mvm_phy_ctxt_add(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt,
|
|||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
ctxt->channel = chandef->chan;
|
||||
ctxt->width = chandef->width;
|
||||
ctxt->center_freq1 = chandef->center_freq1;
|
||||
|
||||
return iwl_mvm_phy_ctxt_apply(mvm, ctxt, chandef,
|
||||
chains_static, chains_dynamic,
|
||||
|
@ -257,6 +301,14 @@ int iwl_mvm_phy_ctxt_changed(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt,
|
|||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
if (iwl_fw_lookup_cmd_ver(mvm->fw, DATA_PATH_GROUP,
|
||||
RLC_CONFIG_CMD, 0) >= 2 &&
|
||||
ctxt->channel == chandef->chan &&
|
||||
ctxt->width == chandef->width &&
|
||||
ctxt->center_freq1 == chandef->center_freq1)
|
||||
return iwl_mvm_phy_send_rlc(mvm, ctxt, chains_static,
|
||||
chains_dynamic);
|
||||
|
||||
if (fw_has_capa(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_BINDING_CDB_SUPPORT) &&
|
||||
ctxt->channel->band != chandef->chan->band) {
|
||||
|
@ -275,6 +327,8 @@ int iwl_mvm_phy_ctxt_changed(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt,
|
|||
|
||||
ctxt->channel = chandef->chan;
|
||||
ctxt->width = chandef->width;
|
||||
ctxt->center_freq1 = chandef->center_freq1;
|
||||
|
||||
return iwl_mvm_phy_ctxt_apply(mvm, ctxt, chandef,
|
||||
chains_static, chains_dynamic,
|
||||
action);
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include "fw/api/commands.h"
|
||||
#include "fw/api/phy-ctxt.h"
|
||||
|
||||
/**
|
||||
/*
|
||||
* DDR needs frequency in units of 16.666MHz, so provide FW with the
|
||||
* frequency values in the adjusted format.
|
||||
*/
|
||||
|
|
|
@ -291,8 +291,12 @@ void iwl_mvm_tlc_update_notif(struct iwl_mvm *mvm,
|
|||
notif = (void *)pkt->data;
|
||||
sta = rcu_dereference(mvm->fw_id_to_mac_id[notif->sta_id]);
|
||||
if (IS_ERR_OR_NULL(sta)) {
|
||||
IWL_ERR(mvm, "Invalid sta id (%d) in FW TLC notification\n",
|
||||
notif->sta_id);
|
||||
/* can happen in remove station flow where mvm removed internally
|
||||
* the station before removing from FW
|
||||
*/
|
||||
IWL_DEBUG_RATE(mvm,
|
||||
"Invalid mvm RCU pointer for sta id (%d) in TLC notification\n",
|
||||
notif->sta_id);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
|
|
@ -527,40 +527,19 @@ struct iwl_mvm_stat_data {
|
|||
u8 *beacon_average_energy;
|
||||
};
|
||||
|
||||
static void iwl_mvm_stat_iterator(void *_data, u8 *mac,
|
||||
struct ieee80211_vif *vif)
|
||||
struct iwl_mvm_stat_data_all_macs {
|
||||
struct iwl_mvm *mvm;
|
||||
__le32 flags;
|
||||
struct iwl_statistics_ntfy_per_mac *per_mac_stats;
|
||||
};
|
||||
|
||||
static void iwl_mvm_update_vif_sig(struct ieee80211_vif *vif, int sig)
|
||||
{
|
||||
struct iwl_mvm_stat_data *data = _data;
|
||||
struct iwl_mvm *mvm = data->mvm;
|
||||
int sig = -data->beacon_filter_average_energy;
|
||||
int last_event;
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_mvm *mvm = mvmvif->mvm;
|
||||
int thold = vif->bss_conf.cqm_rssi_thold;
|
||||
int hyst = vif->bss_conf.cqm_rssi_hyst;
|
||||
u16 id = le32_to_cpu(data->mac_id);
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
u16 vif_id = mvmvif->id;
|
||||
|
||||
/* This doesn't need the MAC ID check since it's not taking the
|
||||
* data copied into the "data" struct, but rather the data from
|
||||
* the notification directly.
|
||||
*/
|
||||
mvmvif->beacon_stats.num_beacons =
|
||||
le32_to_cpu(data->beacon_counter[vif_id]);
|
||||
mvmvif->beacon_stats.avg_signal =
|
||||
-data->beacon_average_energy[vif_id];
|
||||
|
||||
/* make sure that beacon statistics don't go backwards with TCM
|
||||
* request to clear statistics
|
||||
*/
|
||||
if (le32_to_cpu(data->flags) & IWL_STATISTICS_REPLY_FLG_CLEAR)
|
||||
mvmvif->beacon_stats.accu_num_beacons +=
|
||||
mvmvif->beacon_stats.num_beacons;
|
||||
|
||||
if (mvmvif->id != id)
|
||||
return;
|
||||
|
||||
if (vif->type != NL80211_IFTYPE_STATION)
|
||||
return;
|
||||
int last_event;
|
||||
|
||||
if (sig == 0) {
|
||||
IWL_DEBUG_RX(mvm, "RSSI is 0 - skip signal based decision\n");
|
||||
|
@ -618,6 +597,73 @@ static void iwl_mvm_stat_iterator(void *_data, u8 *mac,
|
|||
}
|
||||
}
|
||||
|
||||
static void iwl_mvm_stat_iterator(void *_data, u8 *mac,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_mvm_stat_data *data = _data;
|
||||
int sig = -data->beacon_filter_average_energy;
|
||||
u16 id = le32_to_cpu(data->mac_id);
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
u16 vif_id = mvmvif->id;
|
||||
|
||||
/* This doesn't need the MAC ID check since it's not taking the
|
||||
* data copied into the "data" struct, but rather the data from
|
||||
* the notification directly.
|
||||
*/
|
||||
mvmvif->beacon_stats.num_beacons =
|
||||
le32_to_cpu(data->beacon_counter[vif_id]);
|
||||
mvmvif->beacon_stats.avg_signal =
|
||||
-data->beacon_average_energy[vif_id];
|
||||
|
||||
if (mvmvif->id != id)
|
||||
return;
|
||||
|
||||
if (vif->type != NL80211_IFTYPE_STATION)
|
||||
return;
|
||||
|
||||
/* make sure that beacon statistics don't go backwards with TCM
|
||||
* request to clear statistics
|
||||
*/
|
||||
if (le32_to_cpu(data->flags) & IWL_STATISTICS_REPLY_FLG_CLEAR)
|
||||
mvmvif->beacon_stats.accu_num_beacons +=
|
||||
mvmvif->beacon_stats.num_beacons;
|
||||
|
||||
iwl_mvm_update_vif_sig(vif, sig);
|
||||
}
|
||||
|
||||
static void iwl_mvm_stat_iterator_all_macs(void *_data, u8 *mac,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_mvm_stat_data_all_macs *data = _data;
|
||||
struct iwl_statistics_ntfy_per_mac *mac_stats;
|
||||
int sig;
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
u16 vif_id = mvmvif->id;
|
||||
|
||||
if (WARN_ONCE(vif_id > MAC_INDEX_AUX, "invalid vif id: %d", vif_id))
|
||||
return;
|
||||
|
||||
if (vif->type != NL80211_IFTYPE_STATION)
|
||||
return;
|
||||
|
||||
mac_stats = &data->per_mac_stats[vif_id];
|
||||
|
||||
mvmvif->beacon_stats.num_beacons =
|
||||
le32_to_cpu(mac_stats->beacon_counter);
|
||||
mvmvif->beacon_stats.avg_signal =
|
||||
-le32_to_cpu(mac_stats->beacon_average_energy);
|
||||
|
||||
/* make sure that beacon statistics don't go backwards with TCM
|
||||
* request to clear statistics
|
||||
*/
|
||||
if (le32_to_cpu(data->flags) & IWL_STATISTICS_REPLY_FLG_CLEAR)
|
||||
mvmvif->beacon_stats.accu_num_beacons +=
|
||||
mvmvif->beacon_stats.num_beacons;
|
||||
|
||||
sig = -le32_to_cpu(mac_stats->beacon_filter_average_energy);
|
||||
iwl_mvm_update_vif_sig(vif, sig);
|
||||
}
|
||||
|
||||
static inline void
|
||||
iwl_mvm_rx_stats_check_trigger(struct iwl_mvm *mvm, struct iwl_rx_packet *pkt)
|
||||
{
|
||||
|
@ -684,47 +730,41 @@ iwl_mvm_update_tcm_from_stats(struct iwl_mvm *mvm, __le32 *air_time_le,
|
|||
}
|
||||
|
||||
static void
|
||||
iwl_mvm_handle_rx_statistics_tlv(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_packet *pkt)
|
||||
iwl_mvm_stats_ver_15(struct iwl_mvm *mvm,
|
||||
struct iwl_statistics_operational_ntfy *stats)
|
||||
{
|
||||
struct iwl_mvm_stat_data_all_macs data = {
|
||||
.mvm = mvm,
|
||||
.flags = stats->flags,
|
||||
.per_mac_stats = stats->per_mac_stats,
|
||||
};
|
||||
|
||||
ieee80211_iterate_active_interfaces(mvm->hw,
|
||||
IEEE80211_IFACE_ITER_NORMAL,
|
||||
iwl_mvm_stat_iterator_all_macs,
|
||||
&data);
|
||||
}
|
||||
|
||||
static void
|
||||
iwl_mvm_stats_ver_14(struct iwl_mvm *mvm,
|
||||
struct iwl_statistics_operational_ntfy_ver_14 *stats)
|
||||
{
|
||||
struct iwl_mvm_stat_data data = {
|
||||
.mvm = mvm,
|
||||
};
|
||||
|
||||
u8 beacon_average_energy[MAC_INDEX_AUX];
|
||||
u8 average_energy[IWL_MVM_STATION_COUNT_MAX];
|
||||
struct iwl_statistics_operational_ntfy *stats;
|
||||
int expected_size;
|
||||
__le32 flags;
|
||||
int i;
|
||||
|
||||
expected_size = sizeof(*stats);
|
||||
if (WARN_ONCE(iwl_rx_packet_payload_len(pkt) < expected_size,
|
||||
"received invalid statistics size (%d)!, expected_size: %d\n",
|
||||
iwl_rx_packet_payload_len(pkt), expected_size))
|
||||
return;
|
||||
|
||||
stats = (void *)&pkt->data;
|
||||
|
||||
if (WARN_ONCE(stats->hdr.type != FW_STATISTICS_OPERATIONAL ||
|
||||
stats->hdr.version !=
|
||||
iwl_fw_lookup_notif_ver(mvm->fw, LONG_GROUP, STATISTICS_CMD, 0),
|
||||
"received unsupported hdr type %d, version %d\n",
|
||||
stats->hdr.type, stats->hdr.version))
|
||||
return;
|
||||
|
||||
flags = stats->flags;
|
||||
mvm->radio_stats.rx_time = le64_to_cpu(stats->rx_time);
|
||||
mvm->radio_stats.tx_time = le64_to_cpu(stats->tx_time);
|
||||
mvm->radio_stats.on_time_rf = le64_to_cpu(stats->on_time_rf);
|
||||
mvm->radio_stats.on_time_scan = le64_to_cpu(stats->on_time_scan);
|
||||
|
||||
iwl_mvm_rx_stats_check_trigger(mvm, pkt);
|
||||
|
||||
data.mac_id = stats->mac_id;
|
||||
data.beacon_filter_average_energy =
|
||||
le32_to_cpu(stats->beacon_filter_average_energy);
|
||||
data.flags = flags;
|
||||
data.beacon_counter = stats->beacon_counter;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(beacon_average_energy); i++)
|
||||
beacon_average_energy[i] =
|
||||
le32_to_cpu(stats->beacon_average_energy[i]);
|
||||
|
@ -735,9 +775,105 @@ iwl_mvm_handle_rx_statistics_tlv(struct iwl_mvm *mvm,
|
|||
IEEE80211_IFACE_ITER_NORMAL,
|
||||
iwl_mvm_stat_iterator,
|
||||
&data);
|
||||
}
|
||||
|
||||
static bool iwl_mvm_verify_stats_len(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_packet *pkt,
|
||||
u32 expected_size)
|
||||
{
|
||||
struct iwl_statistics_ntfy_hdr *hdr;
|
||||
|
||||
if (WARN_ONCE(iwl_rx_packet_payload_len(pkt) < expected_size,
|
||||
"received invalid statistics size (%d)!, expected_size: %d\n",
|
||||
iwl_rx_packet_payload_len(pkt), expected_size))
|
||||
return false;
|
||||
|
||||
hdr = (void *)&pkt->data;
|
||||
|
||||
if (WARN_ONCE((hdr->type & IWL_STATISTICS_TYPE_MSK) != FW_STATISTICS_OPERATIONAL ||
|
||||
hdr->version !=
|
||||
iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP, STATISTICS_NOTIFICATION, 0),
|
||||
"received unsupported hdr type %d, version %d\n",
|
||||
hdr->type, hdr->version))
|
||||
return false;
|
||||
|
||||
if (WARN_ONCE(le16_to_cpu(hdr->size) != expected_size,
|
||||
"received invalid statistics size in header (%d)!, expected_size: %d\n",
|
||||
le16_to_cpu(hdr->size), expected_size))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
iwl_mvm_handle_rx_statistics_tlv(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_packet *pkt)
|
||||
{
|
||||
u8 average_energy[IWL_MVM_STATION_COUNT_MAX];
|
||||
__le32 air_time[MAC_INDEX_AUX];
|
||||
__le32 rx_bytes[MAC_INDEX_AUX];
|
||||
__le32 flags = 0;
|
||||
int i;
|
||||
u32 notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP,
|
||||
STATISTICS_NOTIFICATION, 0);
|
||||
|
||||
if (WARN_ONCE(notif_ver > 15,
|
||||
"invalid statistics version id: %d\n", notif_ver))
|
||||
return;
|
||||
|
||||
if (notif_ver == 14) {
|
||||
struct iwl_statistics_operational_ntfy_ver_14 *stats =
|
||||
(void *)pkt->data;
|
||||
|
||||
if (!iwl_mvm_verify_stats_len(mvm, pkt, sizeof(*stats)))
|
||||
return;
|
||||
|
||||
iwl_mvm_stats_ver_14(mvm, stats);
|
||||
|
||||
flags = stats->flags;
|
||||
mvm->radio_stats.rx_time = le64_to_cpu(stats->rx_time);
|
||||
mvm->radio_stats.tx_time = le64_to_cpu(stats->tx_time);
|
||||
mvm->radio_stats.on_time_rf = le64_to_cpu(stats->on_time_rf);
|
||||
mvm->radio_stats.on_time_scan =
|
||||
le64_to_cpu(stats->on_time_scan);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(average_energy); i++)
|
||||
average_energy[i] = le32_to_cpu(stats->average_energy[i]);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(air_time); i++) {
|
||||
air_time[i] = stats->air_time[i];
|
||||
rx_bytes[i] = stats->rx_bytes[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (notif_ver == 15) {
|
||||
struct iwl_statistics_operational_ntfy *stats =
|
||||
(void *)pkt->data;
|
||||
|
||||
if (!iwl_mvm_verify_stats_len(mvm, pkt, sizeof(*stats)))
|
||||
return;
|
||||
|
||||
iwl_mvm_stats_ver_15(mvm, stats);
|
||||
|
||||
flags = stats->flags;
|
||||
mvm->radio_stats.rx_time = le64_to_cpu(stats->rx_time);
|
||||
mvm->radio_stats.tx_time = le64_to_cpu(stats->tx_time);
|
||||
mvm->radio_stats.on_time_rf = le64_to_cpu(stats->on_time_rf);
|
||||
mvm->radio_stats.on_time_scan =
|
||||
le64_to_cpu(stats->on_time_scan);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(average_energy); i++)
|
||||
average_energy[i] =
|
||||
le32_to_cpu(stats->per_sta_stats[i].average_energy);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(air_time); i++) {
|
||||
air_time[i] = stats->per_mac_stats[i].air_time;
|
||||
rx_bytes[i] = stats->per_mac_stats[i].rx_bytes;
|
||||
}
|
||||
}
|
||||
|
||||
iwl_mvm_rx_stats_check_trigger(mvm, pkt);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(average_energy); i++)
|
||||
average_energy[i] = le32_to_cpu(stats->average_energy[i]);
|
||||
ieee80211_iterate_stations_atomic(mvm->hw, iwl_mvm_stats_energy_iter,
|
||||
average_energy);
|
||||
/*
|
||||
|
@ -746,8 +882,7 @@ iwl_mvm_handle_rx_statistics_tlv(struct iwl_mvm *mvm,
|
|||
* request and once in statistics notification.
|
||||
*/
|
||||
if (le32_to_cpu(flags) & IWL_STATISTICS_REPLY_FLG_CLEAR)
|
||||
iwl_mvm_update_tcm_from_stats(mvm, stats->air_time,
|
||||
stats->rx_bytes);
|
||||
iwl_mvm_update_tcm_from_stats(mvm, air_time, rx_bytes);
|
||||
}
|
||||
|
||||
void iwl_mvm_handle_rx_statistics(struct iwl_mvm *mvm,
|
||||
|
@ -761,8 +896,8 @@ void iwl_mvm_handle_rx_statistics(struct iwl_mvm *mvm,
|
|||
u8 *energy;
|
||||
|
||||
/* From ver 14 and up we use TLV statistics format */
|
||||
if (iwl_fw_lookup_notif_ver(mvm->fw, LONG_GROUP,
|
||||
STATISTICS_CMD, 0) >= 14)
|
||||
if (iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP,
|
||||
STATISTICS_NOTIFICATION, 0) >= 14)
|
||||
return iwl_mvm_handle_rx_statistics_tlv(mvm, pkt);
|
||||
|
||||
if (!iwl_mvm_has_new_rx_stats_api(mvm)) {
|
||||
|
|
|
@ -766,8 +766,11 @@ static void iwl_mvm_release_frames_from_notif(struct iwl_mvm *mvm,
|
|||
rcu_read_lock();
|
||||
|
||||
ba_data = rcu_dereference(mvm->baid_map[baid]);
|
||||
if (WARN_ON_ONCE(!ba_data))
|
||||
if (!ba_data) {
|
||||
WARN(!(flags & IWL_MVM_RELEASE_FROM_RSS_SYNC),
|
||||
"BAID %d not found in map\n", baid);
|
||||
goto out;
|
||||
}
|
||||
|
||||
sta = rcu_dereference(mvm->fw_id_to_mac_id[ba_data->sta_id]);
|
||||
if (WARN_ON_ONCE(IS_ERR_OR_NULL(sta)))
|
||||
|
|
|
@ -1394,8 +1394,8 @@ static u32 iwl_mvm_scan_umac_ooc_priority(struct iwl_mvm_scan_params *params)
|
|||
}
|
||||
|
||||
static void
|
||||
iwl_mvm_scan_umac_dwell_v10(struct iwl_mvm *mvm,
|
||||
struct iwl_scan_general_params_v10 *general_params,
|
||||
iwl_mvm_scan_umac_dwell_v11(struct iwl_mvm *mvm,
|
||||
struct iwl_scan_general_params_v11 *general_params,
|
||||
struct iwl_mvm_scan_params *params)
|
||||
{
|
||||
struct iwl_mvm_scan_timing_params *timing, *hb_timing;
|
||||
|
@ -2238,15 +2238,15 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
}
|
||||
|
||||
static void
|
||||
iwl_mvm_scan_umac_fill_general_p_v10(struct iwl_mvm *mvm,
|
||||
iwl_mvm_scan_umac_fill_general_p_v11(struct iwl_mvm *mvm,
|
||||
struct iwl_mvm_scan_params *params,
|
||||
struct ieee80211_vif *vif,
|
||||
struct iwl_scan_general_params_v10 *gp,
|
||||
struct iwl_scan_general_params_v11 *gp,
|
||||
u16 gen_flags)
|
||||
{
|
||||
struct iwl_mvm_vif *scan_vif = iwl_mvm_vif_from_mac80211(vif);
|
||||
|
||||
iwl_mvm_scan_umac_dwell_v10(mvm, gp, params);
|
||||
iwl_mvm_scan_umac_dwell_v11(mvm, gp, params);
|
||||
|
||||
gp->flags = cpu_to_le16(gen_flags);
|
||||
|
||||
|
@ -2350,7 +2350,7 @@ static int iwl_mvm_scan_umac_v12(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
cmd->uid = cpu_to_le32(uid);
|
||||
|
||||
gen_flags = iwl_mvm_scan_umac_flags_v2(mvm, params, vif, type);
|
||||
iwl_mvm_scan_umac_fill_general_p_v10(mvm, params, vif,
|
||||
iwl_mvm_scan_umac_fill_general_p_v11(mvm, params, vif,
|
||||
&scan_p->general_params,
|
||||
gen_flags);
|
||||
|
||||
|
@ -2367,12 +2367,13 @@ static int iwl_mvm_scan_umac_v12(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int iwl_mvm_scan_umac_v14(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct iwl_mvm_scan_params *params, int type,
|
||||
int uid)
|
||||
static int iwl_mvm_scan_umac_v14_and_above(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct iwl_mvm_scan_params *params,
|
||||
int type, int uid, u32 version)
|
||||
{
|
||||
struct iwl_scan_req_umac_v14 *cmd = mvm->scan_cmd;
|
||||
struct iwl_scan_req_params_v14 *scan_p = &cmd->scan_params;
|
||||
struct iwl_scan_req_umac_v15 *cmd = mvm->scan_cmd;
|
||||
struct iwl_scan_req_params_v15 *scan_p = &cmd->scan_params;
|
||||
struct iwl_scan_channel_params_v6 *cp = &scan_p->channel_params;
|
||||
struct iwl_scan_probe_params_v4 *pb = &scan_p->probe_params;
|
||||
int ret;
|
||||
|
@ -2385,7 +2386,7 @@ static int iwl_mvm_scan_umac_v14(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
cmd->uid = cpu_to_le32(uid);
|
||||
|
||||
gen_flags = iwl_mvm_scan_umac_flags_v2(mvm, params, vif, type);
|
||||
iwl_mvm_scan_umac_fill_general_p_v10(mvm, params, vif,
|
||||
iwl_mvm_scan_umac_fill_general_p_v11(mvm, params, vif,
|
||||
&scan_p->general_params,
|
||||
gen_flags);
|
||||
|
||||
|
@ -2425,6 +2426,20 @@ static int iwl_mvm_scan_umac_v14(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int iwl_mvm_scan_umac_v14(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct iwl_mvm_scan_params *params, int type,
|
||||
int uid)
|
||||
{
|
||||
return iwl_mvm_scan_umac_v14_and_above(mvm, vif, params, type, uid, 14);
|
||||
}
|
||||
|
||||
static int iwl_mvm_scan_umac_v15(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct iwl_mvm_scan_params *params, int type,
|
||||
int uid)
|
||||
{
|
||||
return iwl_mvm_scan_umac_v14_and_above(mvm, vif, params, type, uid, 15);
|
||||
}
|
||||
|
||||
static int iwl_mvm_num_scans(struct iwl_mvm *mvm)
|
||||
{
|
||||
return hweight32(mvm->scan_status & IWL_MVM_SCAN_MASK);
|
||||
|
@ -2540,6 +2555,7 @@ struct iwl_scan_umac_handler {
|
|||
|
||||
static const struct iwl_scan_umac_handler iwl_scan_umac_handlers[] = {
|
||||
/* set the newest version first to shorten the list traverse time */
|
||||
IWL_SCAN_UMAC_HANDLER(15),
|
||||
IWL_SCAN_UMAC_HANDLER(14),
|
||||
IWL_SCAN_UMAC_HANDLER(12),
|
||||
};
|
||||
|
@ -2940,15 +2956,14 @@ static int iwl_mvm_scan_stop_wait(struct iwl_mvm *mvm, int type)
|
|||
1 * HZ);
|
||||
}
|
||||
|
||||
#define IWL_SCAN_REQ_UMAC_HANDLE_SIZE(_ver) { \
|
||||
case (_ver): return sizeof(struct iwl_scan_req_umac_v##_ver); \
|
||||
}
|
||||
|
||||
static int iwl_scan_req_umac_get_size(u8 scan_ver)
|
||||
{
|
||||
switch (scan_ver) {
|
||||
IWL_SCAN_REQ_UMAC_HANDLE_SIZE(14);
|
||||
IWL_SCAN_REQ_UMAC_HANDLE_SIZE(12);
|
||||
case 12:
|
||||
return sizeof(struct iwl_scan_req_umac_v12);
|
||||
case 14:
|
||||
case 15:
|
||||
return sizeof(struct iwl_scan_req_umac_v15);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -2684,6 +2684,16 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
|||
RCU_INIT_POINTER(mvm->baid_map[baid], NULL);
|
||||
kfree_rcu(baid_data, rcu_head);
|
||||
IWL_DEBUG_HT(mvm, "BAID %d is free\n", baid);
|
||||
|
||||
/*
|
||||
* After we've deleted it, do another queue sync
|
||||
* so if an IWL_MVM_RXQ_NSSN_SYNC was concurrently
|
||||
* running it won't find a new session in the old
|
||||
* BAID. It can find the NULL pointer for the BAID,
|
||||
* but we must not have it find a different session.
|
||||
*/
|
||||
iwl_mvm_sync_rx_queues_internal(mvm, IWL_MVM_RXQ_EMPTY,
|
||||
true, NULL, 0);
|
||||
}
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -1158,15 +1158,10 @@ void iwl_mvm_schedule_session_protection(struct iwl_mvm *mvm,
|
|||
cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
|
||||
mvmvif->color)),
|
||||
.action = cpu_to_le32(FW_CTXT_ACTION_ADD),
|
||||
.conf_id = cpu_to_le32(SESSION_PROTECT_CONF_ASSOC),
|
||||
.duration_tu = cpu_to_le32(MSEC_TO_TU(duration)),
|
||||
};
|
||||
|
||||
/* The time_event_data.id field is reused to save session
|
||||
* protection's configuration.
|
||||
*/
|
||||
mvmvif->time_event_data.id = SESSION_PROTECT_CONF_ASSOC;
|
||||
cmd.conf_id = cpu_to_le32(mvmvif->time_event_data.id);
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
spin_lock_bh(&mvm->time_event_lock);
|
||||
|
@ -1180,6 +1175,11 @@ void iwl_mvm_schedule_session_protection(struct iwl_mvm *mvm,
|
|||
}
|
||||
|
||||
iwl_mvm_te_clear_data(mvm, te_data);
|
||||
/*
|
||||
* The time_event_data.id field is reused to save session
|
||||
* protection's configuration.
|
||||
*/
|
||||
te_data->id = le32_to_cpu(cmd.conf_id);
|
||||
te_data->duration = le32_to_cpu(cmd.duration_tu);
|
||||
te_data->vif = vif;
|
||||
spin_unlock_bh(&mvm->time_event_lock);
|
||||
|
|
|
@ -340,25 +340,64 @@ void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
ieee80211_request_smps(vif, smps_mode);
|
||||
}
|
||||
|
||||
static bool iwl_wait_stats_complete(struct iwl_notif_wait_data *notif_wait,
|
||||
struct iwl_rx_packet *pkt, void *data)
|
||||
{
|
||||
WARN_ON(pkt->hdr.cmd != STATISTICS_NOTIFICATION);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int iwl_mvm_request_statistics(struct iwl_mvm *mvm, bool clear)
|
||||
{
|
||||
struct iwl_statistics_cmd scmd = {
|
||||
.flags = clear ? cpu_to_le32(IWL_STATISTICS_FLG_CLEAR) : 0,
|
||||
};
|
||||
|
||||
struct iwl_host_cmd cmd = {
|
||||
.id = STATISTICS_CMD,
|
||||
.len[0] = sizeof(scmd),
|
||||
.data[0] = &scmd,
|
||||
.flags = CMD_WANT_SKB,
|
||||
};
|
||||
int ret;
|
||||
|
||||
ret = iwl_mvm_send_cmd(mvm, &cmd);
|
||||
if (ret)
|
||||
return ret;
|
||||
/* From version 15 - STATISTICS_NOTIFICATION, the reply for
|
||||
* STATISTICS_CMD is empty, and the response is with
|
||||
* STATISTICS_NOTIFICATION notification
|
||||
*/
|
||||
if (iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP,
|
||||
STATISTICS_NOTIFICATION, 0) < 15) {
|
||||
cmd.flags = CMD_WANT_SKB;
|
||||
|
||||
iwl_mvm_handle_rx_statistics(mvm, cmd.resp_pkt);
|
||||
iwl_free_resp(&cmd);
|
||||
ret = iwl_mvm_send_cmd(mvm, &cmd);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
iwl_mvm_handle_rx_statistics(mvm, cmd.resp_pkt);
|
||||
iwl_free_resp(&cmd);
|
||||
} else {
|
||||
struct iwl_notification_wait stats_wait;
|
||||
static const u16 stats_complete[] = {
|
||||
STATISTICS_NOTIFICATION,
|
||||
};
|
||||
|
||||
iwl_init_notification_wait(&mvm->notif_wait, &stats_wait,
|
||||
stats_complete, ARRAY_SIZE(stats_complete),
|
||||
iwl_wait_stats_complete, NULL);
|
||||
|
||||
ret = iwl_mvm_send_cmd(mvm, &cmd);
|
||||
if (ret) {
|
||||
iwl_remove_notification(&mvm->notif_wait, &stats_wait);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* 200ms should be enough for FW to collect data from all
|
||||
* LMACs and send STATISTICS_NOTIFICATION to host
|
||||
*/
|
||||
ret = iwl_wait_notification(&mvm->notif_wait, &stats_wait, HZ / 5);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (clear)
|
||||
iwl_mvm_accu_radio_stats(mvm);
|
||||
|
|
|
@ -562,6 +562,7 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
|
|||
IWL_DEV_INFO(0x43F0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0, iwl_ax201_killer_1650i_name),
|
||||
IWL_DEV_INFO(0x43F0, 0x2074, iwl_ax201_cfg_qu_hr, NULL),
|
||||
IWL_DEV_INFO(0x43F0, 0x4070, iwl_ax201_cfg_qu_hr, NULL),
|
||||
IWL_DEV_INFO(0x43F0, 0x1651, killer1650s_2ax_cfg_qu_b0_hr_b0, iwl_ax201_killer_1650s_name),
|
||||
IWL_DEV_INFO(0xA0F0, 0x0070, iwl_ax201_cfg_qu_hr, NULL),
|
||||
IWL_DEV_INFO(0xA0F0, 0x0074, iwl_ax201_cfg_qu_hr, NULL),
|
||||
IWL_DEV_INFO(0xA0F0, 0x0078, iwl_ax201_cfg_qu_hr, NULL),
|
||||
|
@ -959,6 +960,11 @@ 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_qu_c0_hr_b0, iwl_ax203_name),
|
||||
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
|
||||
IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP,
|
||||
IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY,
|
||||
IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
|
||||
iwl_qu_c0_hr_b0, iwl_ax201_name),
|
||||
|
||||
/* QuZ */
|
||||
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
|
||||
|
@ -1097,6 +1103,11 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
|
|||
IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY,
|
||||
IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
|
||||
iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_name),
|
||||
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
|
||||
IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
|
||||
IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY,
|
||||
IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_CDB,
|
||||
iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_name),
|
||||
|
||||
/* Bz */
|
||||
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
|
||||
|
@ -1130,6 +1141,13 @@ 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),
|
||||
|
||||
/* BZ Z step */
|
||||
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
|
||||
IWL_CFG_MAC_TYPE_BZ, SILICON_Z_STEP,
|
||||
IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY,
|
||||
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB,
|
||||
iwl_cfg_bz_z0_gf_a0, iwl_bz_name),
|
||||
|
||||
/* SoF with JF2 */
|
||||
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
|
||||
IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
|
||||
|
@ -1204,6 +1222,11 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
|
|||
IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY,
|
||||
IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
|
||||
iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_name),
|
||||
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
|
||||
IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
|
||||
IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY,
|
||||
IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_CDB,
|
||||
iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_name),
|
||||
|
||||
/* So with JF2 */
|
||||
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
|
||||
|
@ -1456,7 +1479,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
|
||||
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),
|
||||
iwl_trans->hw_rev_step,
|
||||
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),
|
||||
|
@ -1497,21 +1520,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
(iwl_trans->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_7265D)
|
||||
iwl_trans->cfg = cfg_7265d;
|
||||
|
||||
if (cfg == &iwlax210_2ax_cfg_so_hr_a0) {
|
||||
if (iwl_trans->hw_rev == CSR_HW_REV_TYPE_TY) {
|
||||
iwl_trans->cfg = &iwlax210_2ax_cfg_ty_gf_a0;
|
||||
} else if (CSR_HW_RFID_TYPE(iwl_trans->hw_rf_id) ==
|
||||
CSR_HW_RFID_TYPE(CSR_HW_RF_ID_TYPE_JF)) {
|
||||
iwl_trans->cfg = &iwlax210_2ax_cfg_so_jf_b0;
|
||||
} else if (CSR_HW_RFID_TYPE(iwl_trans->hw_rf_id) ==
|
||||
CSR_HW_RFID_TYPE(CSR_HW_RF_ID_TYPE_GF)) {
|
||||
iwl_trans->cfg = &iwlax211_2ax_cfg_so_gf_a0;
|
||||
} else if (CSR_HW_RFID_TYPE(iwl_trans->hw_rf_id) ==
|
||||
CSR_HW_RFID_TYPE(CSR_HW_RF_ID_TYPE_GF4)) {
|
||||
iwl_trans->cfg = &iwlax411_2ax_cfg_so_gf4_a0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a hack to switch from Qu B0 to Qu C0. We need to
|
||||
* do this for all cfgs that use Qu B0, except for those using
|
||||
|
|
|
@ -81,7 +81,7 @@ static void iwl_pcie_gen2_apm_stop(struct iwl_trans *trans, bool op_mode_leave)
|
|||
/* Stop device's DMA activity */
|
||||
iwl_pcie_apm_stop_master(trans);
|
||||
|
||||
iwl_trans_sw_reset(trans);
|
||||
iwl_trans_sw_reset(trans, false);
|
||||
|
||||
/*
|
||||
* Clear "initialization complete" bit to move adapter from
|
||||
|
@ -105,9 +105,12 @@ static void iwl_trans_pcie_fw_reset_handshake(struct iwl_trans *trans)
|
|||
if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
|
||||
iwl_write_umac_prph(trans, UREG_NIC_SET_NMI_DRIVER,
|
||||
UREG_NIC_SET_NMI_DRIVER_RESET_HANDSHAKE);
|
||||
else
|
||||
else if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_AX210)
|
||||
iwl_write_umac_prph(trans, UREG_DOORBELL_TO_ISR6,
|
||||
UREG_DOORBELL_TO_ISR6_RESET_HANDSHAKE);
|
||||
else
|
||||
iwl_write32(trans, CSR_DOORBELL_VECTOR,
|
||||
UREG_DOORBELL_TO_ISR6_RESET_HANDSHAKE);
|
||||
|
||||
/* wait 200ms */
|
||||
ret = wait_event_timeout(trans_pcie->fw_reset_waitq,
|
||||
|
@ -166,7 +169,8 @@ void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans)
|
|||
/* Stop the device, and put it in low power state */
|
||||
iwl_pcie_gen2_apm_stop(trans, false);
|
||||
|
||||
iwl_trans_sw_reset(trans);
|
||||
/* re-take ownership to prevent other users from stealing the device */
|
||||
iwl_trans_sw_reset(trans, true);
|
||||
|
||||
/*
|
||||
* Upon stop, the IVAR table gets erased, so msi-x won't
|
||||
|
@ -196,9 +200,6 @@ void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans)
|
|||
* interrupt
|
||||
*/
|
||||
iwl_enable_rfkill_int(trans);
|
||||
|
||||
/* re-take ownership to prevent other users from stealing the device */
|
||||
iwl_pcie_prepare_card_hw(trans);
|
||||
}
|
||||
|
||||
void iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans)
|
||||
|
|
|
@ -127,7 +127,8 @@ out:
|
|||
kfree(buf);
|
||||
}
|
||||
|
||||
static void iwl_trans_pcie_sw_reset(struct iwl_trans *trans)
|
||||
static int iwl_trans_pcie_sw_reset(struct iwl_trans *trans,
|
||||
bool retake_ownership)
|
||||
{
|
||||
/* Reset entire device - do controller reset (results in SHRD_HW_RST) */
|
||||
if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
|
||||
|
@ -137,6 +138,11 @@ static void iwl_trans_pcie_sw_reset(struct iwl_trans *trans)
|
|||
iwl_set_bit(trans, CSR_RESET,
|
||||
CSR_RESET_REG_FLAG_SW_RESET);
|
||||
usleep_range(5000, 6000);
|
||||
|
||||
if (retake_ownership)
|
||||
return iwl_pcie_prepare_card_hw(trans);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void iwl_pcie_free_fw_monitor(struct iwl_trans *trans)
|
||||
|
@ -382,9 +388,11 @@ static void iwl_pcie_apm_lp_xtal_enable(struct iwl_trans *trans)
|
|||
__iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL,
|
||||
CSR_GP_CNTRL_REG_FLAG_XTAL_ON);
|
||||
|
||||
iwl_trans_pcie_sw_reset(trans);
|
||||
ret = iwl_trans_pcie_sw_reset(trans, true);
|
||||
|
||||
if (!ret)
|
||||
ret = iwl_finish_nic_init(trans);
|
||||
|
||||
ret = iwl_finish_nic_init(trans);
|
||||
if (WARN_ON(ret)) {
|
||||
/* Release XTAL ON request */
|
||||
__iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL,
|
||||
|
@ -409,7 +417,10 @@ static void iwl_pcie_apm_lp_xtal_enable(struct iwl_trans *trans)
|
|||
apmg_xtal_cfg_reg |
|
||||
SHR_APMG_XTAL_CFG_XTAL_ON_REQ);
|
||||
|
||||
iwl_trans_pcie_sw_reset(trans);
|
||||
ret = iwl_trans_pcie_sw_reset(trans, true);
|
||||
if (ret)
|
||||
IWL_ERR(trans,
|
||||
"iwl_pcie_apm_lp_xtal_enable: failed to retake NIC ownership\n");
|
||||
|
||||
/* Enable LP XTAL by indirect access through CSR */
|
||||
apmg_gp1_reg = iwl_trans_pcie_read_shr(trans, SHR_APMG_GP1_REG);
|
||||
|
@ -515,7 +526,7 @@ static void iwl_pcie_apm_stop(struct iwl_trans *trans, bool op_mode_leave)
|
|||
return;
|
||||
}
|
||||
|
||||
iwl_trans_pcie_sw_reset(trans);
|
||||
iwl_trans_pcie_sw_reset(trans, false);
|
||||
|
||||
/*
|
||||
* Clear "initialization complete" bit to move adapter from
|
||||
|
@ -1261,7 +1272,8 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans)
|
|||
/* Stop the device, and put it in low power state */
|
||||
iwl_pcie_apm_stop(trans, false);
|
||||
|
||||
iwl_trans_pcie_sw_reset(trans);
|
||||
/* re-take ownership to prevent other users from stealing the device */
|
||||
iwl_trans_pcie_sw_reset(trans, true);
|
||||
|
||||
/*
|
||||
* Upon stop, the IVAR table gets erased, so msi-x won't
|
||||
|
@ -1291,9 +1303,6 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans)
|
|||
* interrupt
|
||||
*/
|
||||
iwl_enable_rfkill_int(trans);
|
||||
|
||||
/* re-take ownership to prevent other users from stealing the device */
|
||||
iwl_pcie_prepare_card_hw(trans);
|
||||
}
|
||||
|
||||
void iwl_pcie_synchronize_irqs(struct iwl_trans *trans)
|
||||
|
@ -1499,33 +1508,54 @@ void iwl_pcie_d3_complete_suspend(struct iwl_trans *trans,
|
|||
iwl_pcie_set_pwr(trans, true);
|
||||
}
|
||||
|
||||
static int iwl_pcie_d3_handshake(struct iwl_trans *trans, bool suspend)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
int ret;
|
||||
|
||||
if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_AX210) {
|
||||
iwl_write_umac_prph(trans, UREG_DOORBELL_TO_ISR6,
|
||||
suspend ? UREG_DOORBELL_TO_ISR6_SUSPEND :
|
||||
UREG_DOORBELL_TO_ISR6_RESUME);
|
||||
} else if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) {
|
||||
iwl_write32(trans, CSR_IPC_SLEEP_CONTROL,
|
||||
suspend ? CSR_IPC_SLEEP_CONTROL_SUSPEND :
|
||||
CSR_IPC_SLEEP_CONTROL_RESUME);
|
||||
iwl_write_umac_prph(trans, UREG_DOORBELL_TO_ISR6,
|
||||
UREG_DOORBELL_TO_ISR6_SLEEP_CTRL);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = wait_event_timeout(trans_pcie->sx_waitq,
|
||||
trans_pcie->sx_complete, 2 * HZ);
|
||||
|
||||
/* Invalidate it toward next suspend or resume */
|
||||
trans_pcie->sx_complete = false;
|
||||
|
||||
if (!ret) {
|
||||
IWL_ERR(trans, "Timeout %s D3\n",
|
||||
suspend ? "entering" : "exiting");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool test,
|
||||
bool reset)
|
||||
{
|
||||
int ret;
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
|
||||
if (!reset)
|
||||
/* Enable persistence mode to avoid reset */
|
||||
iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_PERSIST_MODE);
|
||||
|
||||
if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
|
||||
iwl_write_umac_prph(trans, UREG_DOORBELL_TO_ISR6,
|
||||
UREG_DOORBELL_TO_ISR6_SUSPEND);
|
||||
ret = iwl_pcie_d3_handshake(trans, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = wait_event_timeout(trans_pcie->sx_waitq,
|
||||
trans_pcie->sx_complete, 2 * HZ);
|
||||
/*
|
||||
* Invalidate it toward resume.
|
||||
*/
|
||||
trans_pcie->sx_complete = false;
|
||||
|
||||
if (!ret) {
|
||||
IWL_ERR(trans, "Timeout entering D3\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
iwl_pcie_d3_complete_suspend(trans, test, reset);
|
||||
|
||||
return 0;
|
||||
|
@ -1542,6 +1572,7 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans,
|
|||
if (test) {
|
||||
iwl_enable_interrupts(trans);
|
||||
*status = IWL_D3_STATUS_ALIVE;
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -1590,25 +1621,10 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans,
|
|||
*status = IWL_D3_STATUS_ALIVE;
|
||||
|
||||
out:
|
||||
if (*status == IWL_D3_STATUS_ALIVE &&
|
||||
trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
|
||||
trans_pcie->sx_complete = false;
|
||||
iwl_write_umac_prph(trans, UREG_DOORBELL_TO_ISR6,
|
||||
UREG_DOORBELL_TO_ISR6_RESUME);
|
||||
if (*status == IWL_D3_STATUS_ALIVE)
|
||||
ret = iwl_pcie_d3_handshake(trans, false);
|
||||
|
||||
ret = wait_event_timeout(trans_pcie->sx_waitq,
|
||||
trans_pcie->sx_complete, 2 * HZ);
|
||||
/*
|
||||
* Invalidate it toward next suspend.
|
||||
*/
|
||||
trans_pcie->sx_complete = false;
|
||||
|
||||
if (!ret) {
|
||||
IWL_ERR(trans, "Timeout exiting D3\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1795,9 +1811,7 @@ static int iwl_pcie_gen2_force_power_gating(struct iwl_trans *trans)
|
|||
iwl_clear_bits_prph(trans, HPM_HIPM_GEN_CFG,
|
||||
HPM_HIPM_GEN_CFG_CR_FORCE_ACTIVE);
|
||||
|
||||
iwl_trans_pcie_sw_reset(trans);
|
||||
|
||||
return 0;
|
||||
return iwl_trans_pcie_sw_reset(trans, true);
|
||||
}
|
||||
|
||||
static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans)
|
||||
|
@ -1817,7 +1831,9 @@ static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans)
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
iwl_trans_pcie_sw_reset(trans);
|
||||
err = iwl_trans_pcie_sw_reset(trans, true);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_22000 &&
|
||||
trans->trans_cfg->integrated) {
|
||||
|
@ -3616,8 +3632,9 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
|
|||
* in the old format.
|
||||
*/
|
||||
if (cfg_trans->device_family >= IWL_DEVICE_FAMILY_8000)
|
||||
trans->hw_rev = (trans->hw_rev & 0xfff0) |
|
||||
(CSR_HW_REV_STEP(trans->hw_rev << 2) << 2);
|
||||
trans->hw_rev_step = trans->hw_rev & 0xF;
|
||||
else
|
||||
trans->hw_rev_step = (trans->hw_rev & 0xC) >> 2;
|
||||
|
||||
IWL_DEBUG_INFO(trans, "HW REV: 0x%0x\n", trans->hw_rev);
|
||||
|
||||
|
|
|
@ -1072,6 +1072,7 @@ int iwl_txq_alloc(struct iwl_trans *trans, struct iwl_txq *txq, int slots_num,
|
|||
return 0;
|
||||
err_free_tfds:
|
||||
dma_free_coherent(trans->dev, tfd_sz, txq->tfds, txq->dma_addr);
|
||||
txq->tfds = NULL;
|
||||
error:
|
||||
if (txq->entries && cmd_queue)
|
||||
for (i = 0; i < slots_num; i++)
|
||||
|
@ -1752,8 +1753,11 @@ static int iwl_trans_txq_send_hcmd_sync(struct iwl_trans *trans,
|
|||
}
|
||||
|
||||
if (test_bit(STATUS_FW_ERROR, &trans->status)) {
|
||||
IWL_ERR(trans, "FW error in SYNC CMD %s\n", cmd_str);
|
||||
dump_stack();
|
||||
if (!test_and_clear_bit(STATUS_SUPPRESS_CMD_ERROR_ONCE,
|
||||
&trans->status)) {
|
||||
IWL_ERR(trans, "FW error in SYNC CMD %s\n", cmd_str);
|
||||
dump_stack();
|
||||
}
|
||||
ret = -EIO;
|
||||
goto cancel;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче