aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/intel
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/intel')
-rw-r--r--drivers/net/wireless/intel/iwlegacy/3945-debug.c8
-rw-r--r--drivers/net/wireless/intel/iwlegacy/4965.c1
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/22000.c41
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/9000.c10
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/d3.h136
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h181
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/location.h77
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/mac.h77
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h39
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/rx.h67
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/scan.h54
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/txq.h3
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/dbg.c605
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/dbg.h30
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/error-dump.h43
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/file.h32
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/img.h7
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/init.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/runtime.h2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-config.h14
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-csr.h6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c12
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-debug.h2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-drv.c26
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c148
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-prph.h6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-trans.h3
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/d3.c148
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c11
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c91
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c33
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c47
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c232
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mvm.h32
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ops.c24
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c94
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rs.c8
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c31
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/scan.c25
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/sta.c14
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/tdls.c7
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/time-event.c5
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/utils.c12
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c3
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/drv.c14
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/internal.h45
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/rx.c23
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c7
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/trans.c61
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/tx.c10
51 files changed, 1795 insertions, 820 deletions
diff --git a/drivers/net/wireless/intel/iwlegacy/3945-debug.c b/drivers/net/wireless/intel/iwlegacy/3945-debug.c
index a2960032be81..4b912e707f38 100644
--- a/drivers/net/wireless/intel/iwlegacy/3945-debug.c
+++ b/drivers/net/wireless/intel/iwlegacy/3945-debug.c
@@ -185,7 +185,7 @@ il3945_ucode_rx_stats_read(struct file *file, char __user *user_buf,
pos +=
scnprintf(buf + pos, bufsz - pos,
"%-32s current"
- "acumulative delta max\n",
+ "accumulative delta max\n",
"Statistics_Rx - CCK:");
pos +=
scnprintf(buf + pos, bufsz - pos,
@@ -273,7 +273,7 @@ il3945_ucode_rx_stats_read(struct file *file, char __user *user_buf,
pos +=
scnprintf(buf + pos, bufsz - pos,
"%-32s current"
- "acumulative delta max\n",
+ "accumulative delta max\n",
"Statistics_Rx - GENERAL:");
pos +=
scnprintf(buf + pos, bufsz - pos,
@@ -346,7 +346,7 @@ il3945_ucode_tx_stats_read(struct file *file, char __user *user_buf,
pos +=
scnprintf(buf + pos, bufsz - pos,
"%-32s current"
- "acumulative delta max\n",
+ "accumulative delta max\n",
"Statistics_Tx:");
pos +=
scnprintf(buf + pos, bufsz - pos,
@@ -447,7 +447,7 @@ il3945_ucode_general_stats_read(struct file *file, char __user *user_buf,
pos +=
scnprintf(buf + pos, bufsz - pos,
"%-32s current"
- "acumulative delta max\n",
+ "accumulative delta max\n",
"Statistics_General:");
pos +=
scnprintf(buf + pos, bufsz - pos,
diff --git a/drivers/net/wireless/intel/iwlegacy/4965.c b/drivers/net/wireless/intel/iwlegacy/4965.c
index ce4144a89217..a20b6c885047 100644
--- a/drivers/net/wireless/intel/iwlegacy/4965.c
+++ b/drivers/net/wireless/intel/iwlegacy/4965.c
@@ -577,7 +577,6 @@ il4965_math_div_round(s32 num, s32 denom, s32 * res)
sign = -sign;
denom = -denom;
}
- *res = 1;
*res = ((num * 2 + denom) / (denom * 2)) * sign;
return 1;
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c
index 0a87d87fbb4f..a9c846c59289 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c
@@ -56,7 +56,7 @@
#include "iwl-config.h"
/* Highest firmware API version supported */
-#define IWL_22000_UCODE_API_MAX 46
+#define IWL_22000_UCODE_API_MAX 48
/* Lowest firmware API version supported */
#define IWL_22000_UCODE_API_MIN 39
@@ -80,7 +80,6 @@
#define IWL_22000_QU_B_HR_B_FW_PRE "iwlwifi-Qu-b0-hr-b0-"
#define IWL_22000_HR_B_FW_PRE "iwlwifi-QuQnj-b0-hr-b0-"
#define IWL_22000_HR_A0_FW_PRE "iwlwifi-QuQnj-a0-hr-a0-"
-#define IWL_22000_SU_Z0_FW_PRE "iwlwifi-su-z0-"
#define IWL_QU_B_JF_B_FW_PRE "iwlwifi-Qu-b0-jf-b0-"
#define IWL_QUZ_A_HR_B_FW_PRE "iwlwifi-QuZ-a0-hr-b0-"
#define IWL_QNJ_B_JF_B_FW_PRE "iwlwifi-QuQnj-b0-jf-b0-"
@@ -89,6 +88,7 @@
#define IWL_22000_SO_A_HR_B_FW_PRE "iwlwifi-so-a0-hr-b0-"
#define IWL_22000_SO_A_GF_A_FW_PRE "iwlwifi-so-a0-gf-a0-"
#define IWL_22000_TY_A_GF_A_FW_PRE "iwlwifi-ty-a0-gf-a0-"
+#define IWL_22000_SO_A_GF4_A_FW_PRE "iwlwifi-so-a0-gf4-a0-"
#define IWL_22000_HR_MODULE_FIRMWARE(api) \
IWL_22000_HR_FW_PRE __stringify(api) ".ucode"
@@ -104,8 +104,6 @@
IWL_22000_HR_B_FW_PRE __stringify(api) ".ucode"
#define IWL_22000_HR_A0_QNJ_MODULE_FIRMWARE(api) \
IWL_22000_HR_A0_FW_PRE __stringify(api) ".ucode"
-#define IWL_22000_SU_Z0_MODULE_FIRMWARE(api) \
- IWL_22000_SU_Z0_FW_PRE __stringify(api) ".ucode"
#define IWL_QUZ_A_HR_B_MODULE_FIRMWARE(api) \
IWL_QUZ_A_HR_B_FW_PRE __stringify(api) ".ucode"
#define IWL_QU_B_JF_B_MODULE_FIRMWARE(api) \
@@ -180,7 +178,11 @@ static const struct iwl_ht_params iwl_22000_ht_params = {
.dbgc_supported = true, \
.min_umac_error_event_table = 0x400000, \
.d3_debug_data_base_addr = 0x401000, \
- .d3_debug_data_length = 60 * 1024
+ .d3_debug_data_length = 60 * 1024, \
+ .fw_mon_smem_write_ptr_addr = 0xa0c16c, \
+ .fw_mon_smem_write_ptr_msk = 0xfffff, \
+ .fw_mon_smem_cycle_cnt_ptr_addr = 0xa0c174, \
+ .fw_mon_smem_cycle_cnt_ptr_msk = 0xfffff
#define IWL_DEVICE_AX200_COMMON \
IWL_DEVICE_22000_COMMON, \
@@ -190,7 +192,8 @@ static const struct iwl_ht_params iwl_22000_ht_params = {
IWL_DEVICE_22000_COMMON, \
.device_family = IWL_DEVICE_FAMILY_22000, \
.base_params = &iwl_22000_base_params, \
- .csr = &iwl_csr_v1
+ .csr = &iwl_csr_v1, \
+ .gp2_reg_addr = 0xa02c68
#define IWL_DEVICE_22560 \
IWL_DEVICE_22000_COMMON, \
@@ -203,7 +206,9 @@ static const struct iwl_ht_params iwl_22000_ht_params = {
.device_family = IWL_DEVICE_FAMILY_AX210, \
.base_params = &iwl_22560_base_params, \
.csr = &iwl_csr_v1, \
- .min_txq_size = 128
+ .min_txq_size = 128, \
+ .gp2_reg_addr = 0xd02c68, \
+ .min_256_ba_txq_size = 512
const struct iwl_cfg iwl22000_2ac_cfg_hr = {
.name = "Intel(R) Dual Band Wireless AC 22000",
@@ -412,19 +417,6 @@ const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_a0 = {
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
};
-const struct iwl_cfg iwl22560_2ax_cfg_su_cdb = {
- .name = "Intel(R) Dual Band Wireless AX 22560",
- .fw_name_pre = IWL_22000_SU_Z0_FW_PRE,
- IWL_DEVICE_22560,
- .cdb = true,
- /*
- * This device doesn't support receiving BlockAck with a large bitmap
- * so we need to restrict the size of transmitted aggregation to the
- * HT size; mac80211 would otherwise pick the HE max (256) by default.
- */
- .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
-};
-
const struct iwl_cfg iwlax210_2ax_cfg_so_jf_a0 = {
.name = "Intel(R) Wireless-AC 9560 160MHz",
.fw_name_pre = IWL_22000_SO_A_JF_B_FW_PRE,
@@ -440,12 +432,20 @@ const struct iwl_cfg iwlax210_2ax_cfg_so_hr_a0 = {
const struct iwl_cfg iwlax210_2ax_cfg_so_gf_a0 = {
.name = "Intel(R) Wi-Fi 7 AX211 160MHz",
.fw_name_pre = IWL_22000_SO_A_GF_A_FW_PRE,
+ .uhb_supported = true,
IWL_DEVICE_AX210,
};
const struct iwl_cfg iwlax210_2ax_cfg_ty_gf_a0 = {
.name = "Intel(R) Wi-Fi 7 AX210 160MHz",
.fw_name_pre = IWL_22000_TY_A_GF_A_FW_PRE,
+ .uhb_supported = true,
+ IWL_DEVICE_AX210,
+};
+
+const struct iwl_cfg iwlax210_2ax_cfg_so_gf4_a0 = {
+ .name = "Intel(R) Wi-Fi 7 AX210 160MHz",
+ .fw_name_pre = IWL_22000_SO_A_GF4_A_FW_PRE,
IWL_DEVICE_AX210,
};
@@ -455,7 +455,6 @@ MODULE_FIRMWARE(IWL_22000_HR_A_F0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_22000_HR_B_F0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_22000_HR_B_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_22000_HR_A0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_22000_SU_Z0_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_QU_B_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_QUZ_A_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_QNJ_B_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c
index 3225b64eb845..41bdd0eaf62c 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c
@@ -6,7 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2015-2017 Intel Deutschland GmbH
- * Copyright (C) 2018 Intel Corporation
+ * Copyright (C) 2018 - 2019 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -20,7 +20,7 @@
* BSD LICENSE
*
* Copyright(c) 2015-2017 Intel Deutschland GmbH
- * Copyright (C) 2018 Intel Corporation
+ * Copyright (C) 2018 - 2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -148,7 +148,11 @@ static const struct iwl_tt_params iwl9000_tt_params = {
.d3_debug_data_length = 92 * 1024, \
.ht_params = &iwl9000_ht_params, \
.nvm_ver = IWL9000_NVM_VERSION, \
- .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K
+ .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \
+ .fw_mon_smem_write_ptr_addr = 0xa0476c, \
+ .fw_mon_smem_write_ptr_msk = 0xfffff, \
+ .fw_mon_smem_cycle_cnt_ptr_addr = 0xa04774, \
+ .fw_mon_smem_cycle_cnt_ptr_msk = 0xfffff
const struct iwl_cfg iwl9160_2ac_cfg = {
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h b/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h
index 86ea0784e1a3..31231b223aae 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h
@@ -8,7 +8,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,7 +31,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -214,7 +214,7 @@ struct iwl_proto_offload_cmd_v3_large {
#define IWL_WOWLAN_MIN_PATTERN_LEN 16
#define IWL_WOWLAN_MAX_PATTERN_LEN 128
-struct iwl_wowlan_pattern {
+struct iwl_wowlan_pattern_v1 {
u8 mask[IWL_WOWLAN_MAX_PATTERN_LEN / 8];
u8 pattern[IWL_WOWLAN_MAX_PATTERN_LEN];
u8 mask_size;
@@ -227,7 +227,7 @@ struct iwl_wowlan_pattern {
/**
* struct iwl_wowlan_patterns_cmd - WoWLAN wakeup patterns
*/
-struct iwl_wowlan_patterns_cmd {
+struct iwl_wowlan_patterns_cmd_v1 {
/**
* @n_patterns: number of patterns
*/
@@ -236,9 +236,129 @@ struct iwl_wowlan_patterns_cmd {
/**
* @patterns: the patterns, array length in @n_patterns
*/
- struct iwl_wowlan_pattern patterns[];
+ struct iwl_wowlan_pattern_v1 patterns[];
} __packed; /* WOWLAN_PATTERN_ARRAY_API_S_VER_1 */
+#define IPV4_ADDR_SIZE 4
+#define IPV6_ADDR_SIZE 16
+
+enum iwl_wowlan_pattern_type {
+ WOWLAN_PATTERN_TYPE_BITMASK,
+ WOWLAN_PATTERN_TYPE_IPV4_TCP_SYN,
+ WOWLAN_PATTERN_TYPE_IPV6_TCP_SYN,
+ WOWLAN_PATTERN_TYPE_IPV4_TCP_SYN_WILDCARD,
+ WOWLAN_PATTERN_TYPE_IPV6_TCP_SYN_WILDCARD,
+}; /* WOWLAN_PATTERN_TYPE_API_E_VER_1 */
+
+/**
+ * struct iwl_wowlan_ipv4_tcp_syn - WoWLAN IPv4 TCP SYN pattern data
+ */
+struct iwl_wowlan_ipv4_tcp_syn {
+ /**
+ * @src_addr: source IP address to match
+ */
+ u8 src_addr[IPV4_ADDR_SIZE];
+
+ /**
+ * @dst_addr: destination IP address to match
+ */
+ u8 dst_addr[IPV4_ADDR_SIZE];
+
+ /**
+ * @src_port: source TCP port to match
+ */
+ __le16 src_port;
+
+ /**
+ * @dst_port: destination TCP port to match
+ */
+ __le16 dst_port;
+} __packed; /* WOWLAN_IPV4_TCP_SYN_API_S_VER_1 */
+
+/**
+ * struct iwl_wowlan_ipv6_tcp_syn - WoWLAN Ipv6 TCP SYN pattern data
+ */
+struct iwl_wowlan_ipv6_tcp_syn {
+ /**
+ * @src_addr: source IP address to match
+ */
+ u8 src_addr[IPV6_ADDR_SIZE];
+
+ /**
+ * @dst_addr: destination IP address to match
+ */
+ u8 dst_addr[IPV6_ADDR_SIZE];
+
+ /**
+ * @src_port: source TCP port to match
+ */
+ __le16 src_port;
+
+ /**
+ * @dst_port: destination TCP port to match
+ */
+ __le16 dst_port;
+} __packed; /* WOWLAN_IPV6_TCP_SYN_API_S_VER_1 */
+
+/**
+ * union iwl_wowlan_pattern_data - Data for the different pattern types
+ *
+ * If wildcard addresses/ports are to be used, the union can be left
+ * undefined.
+ */
+union iwl_wowlan_pattern_data {
+ /**
+ * @bitmask: bitmask pattern data
+ */
+ struct iwl_wowlan_pattern_v1 bitmask;
+
+ /**
+ * @ipv4_tcp_syn: IPv4 TCP SYN pattern data
+ */
+ struct iwl_wowlan_ipv4_tcp_syn ipv4_tcp_syn;
+
+ /**
+ * @ipv6_tcp_syn: IPv6 TCP SYN pattern data
+ */
+ struct iwl_wowlan_ipv6_tcp_syn ipv6_tcp_syn;
+}; /* WOWLAN_PATTERN_API_U_VER_1 */
+
+/**
+ * struct iwl_wowlan_pattern_v2 - Pattern entry for the WoWLAN wakeup patterns
+ */
+struct iwl_wowlan_pattern_v2 {
+ /**
+ * @pattern_type: defines the struct type to be used in the union
+ */
+ u8 pattern_type;
+
+ /**
+ * @reserved: reserved for alignment
+ */
+ u8 reserved[3];
+
+ /**
+ * @u: the union containing the match data, or undefined for
+ * wildcard matches
+ */
+ union iwl_wowlan_pattern_data u;
+} __packed; /* WOWLAN_PATTERN_API_S_VER_2 */
+
+/**
+ * struct iwl_wowlan_patterns_cmd - WoWLAN wakeup patterns command
+ */
+struct iwl_wowlan_patterns_cmd {
+ /**
+ * @n_patterns: number of patterns
+ */
+ __le32 n_patterns;
+
+ /**
+ * @patterns: the patterns, array length in @n_patterns
+ */
+ struct iwl_wowlan_pattern_v2 patterns[];
+} __packed; /* WOWLAN_PATTERN_ARRAY_API_S_VER_2 */
+
enum iwl_wowlan_wakeup_filters {
IWL_WOWLAN_WAKEUP_MAGIC_PACKET = BIT(0),
IWL_WOWLAN_WAKEUP_PATTERN_MATCH = BIT(1),
@@ -383,7 +503,11 @@ enum iwl_wowlan_wakeup_reason {
IWL_WOWLAN_WAKEUP_BY_D3_WAKEUP_HOST_TIMER = BIT(14),
IWL_WOWLAN_WAKEUP_BY_RXFRAME_FILTERED_IN = BIT(15),
IWL_WOWLAN_WAKEUP_BY_BEACON_FILTERED_IN = BIT(16),
-
+ IWL_WAKEUP_BY_11W_UNPROTECTED_DEAUTH_OR_DISASSOC = BIT(17),
+ IWL_WAKEUP_BY_PATTERN_IPV4_TCP_SYN = BIT(18),
+ IWL_WAKEUP_BY_PATTERN_IPV4_TCP_SYN_WILDCARD = BIT(19),
+ IWL_WAKEUP_BY_PATTERN_IPV6_TCP_SYN = BIT(20),
+ IWL_WAKEUP_BY_PATTERN_IPV6_TCP_SYN_WILDCARD = BIT(21),
}; /* WOWLAN_WAKE_UP_REASON_API_E_VER_2 */
struct iwl_wowlan_gtk_status_v1 {
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h b/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h
index 33858787817b..f4202bc231a6 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h
@@ -60,12 +60,13 @@
#include <linux/bitops.h>
-/*
+/**
* struct iwl_fw_ini_header: Common Header for all debug group TLV's structures
+ *
* @tlv_version: version info
* @apply_point: &enum iwl_fw_ini_apply_point
* @data: TLV data followed
- **/
+ */
struct iwl_fw_ini_header {
__le32 tlv_version;
__le32 apply_point;
@@ -73,7 +74,7 @@ struct iwl_fw_ini_header {
} __packed; /* FW_DEBUG_TLV_HEADER_S */
/**
- * struct iwl_fw_ini_allocation_tlv - (IWL_FW_INI_TLV_TYPE_BUFFER_ALLOCATION)
+ * struct iwl_fw_ini_allocation_tlv - (IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION)
* buffer allocation TLV - for debug
*
* @iwl_fw_ini_header: header
@@ -84,7 +85,7 @@ struct iwl_fw_ini_header {
* @max_fragments: the maximum allowed fragmentation in the desired memory
* allocation above
* @min_frag_size: the minimum allowed fragmentation size in bytes
-*/
+ */
struct iwl_fw_ini_allocation_tlv {
struct iwl_fw_ini_header header;
__le32 allocation_id;
@@ -95,33 +96,52 @@ struct iwl_fw_ini_allocation_tlv {
} __packed; /* FW_DEBUG_TLV_BUFFER_ALLOCATION_TLV_S_VER_1 */
/**
- * struct iwl_fw_ini_hcmd (IWL_FW_INI_TLV_TYPE_HCMD)
- * Generic Host command pass through TLV
+ * enum iwl_fw_ini_dbg_domain - debug domains
+ * allows to send host cmd or collect memory region if a given domain is enabled
+ *
+ * @IWL_FW_INI_DBG_DOMAIN_ALWAYS_ON: the default domain, always on
+ * @IWL_FW_INI_DBG_DOMAIN_REPORT_PS: power save domain
+ */
+enum iwl_fw_ini_dbg_domain {
+ IWL_FW_INI_DBG_DOMAIN_ALWAYS_ON = 0,
+ IWL_FW_INI_DBG_DOMAIN_REPORT_PS,
+}; /* FW_DEBUG_TLV_DOMAIN_API_E_VER_1 */
+
+/**
+ * struct iwl_fw_ini_hcmd
*
* @id: the debug configuration command type for instance: 0xf6 / 0xf5 / DHC
* @group: the desired cmd group
- * @padding: all zeros for dword alignment
- * @data: all of the relevant command (0xf6/0xf5) to be sent
-*/
+ * @reserved: to align to FW struct
+ * @data: all of the relevant command data to be sent
+ */
struct iwl_fw_ini_hcmd {
u8 id;
u8 group;
- __le16 padding;
+ __le16 reserved;
u8 data[0];
-} __packed; /* FW_DEBUG_TLV_HCMD_DATA_S */
+} __packed; /* FW_DEBUG_TLV_HCMD_DATA_API_S_VER_1 */
/**
- * struct iwl_fw_ini_hcmd_tlv
+ * struct iwl_fw_ini_hcmd_tlv - (IWL_UCODE_TLV_TYPE_HCMD)
+ * Generic Host command pass through TLV
+ *
* @header: header
+ * @domain: send command only if the specific domain is enabled
+ * &enum iwl_fw_ini_dbg_domain
+ * @period_msec: period in which the hcmd will be sent to FW. Measured in msec
+ * (0 = one time command).
* @hcmd: a variable length host-command to be sent to apply the configuration.
*/
struct iwl_fw_ini_hcmd_tlv {
struct iwl_fw_ini_header header;
+ __le32 domain;
+ __le32 period_msec;
struct iwl_fw_ini_hcmd hcmd;
-} __packed; /* FW_DEBUG_TLV_HCMD_S_VER_1 */
+} __packed; /* FW_DEBUG_TLV_HCMD_API_S_VER_1 */
-/*
- * struct iwl_fw_ini_debug_flow_tlv (IWL_FW_INI_TLV_TYPE_DEBUG_FLOW)
+/**
+ * struct iwl_fw_ini_debug_flow_tlv - (IWL_UCODE_TLV_TYPE_DEBUG_FLOW)
*
* @header: header
* @debug_flow_cfg: &enum iwl_fw_ini_debug_flow
@@ -135,7 +155,19 @@ struct iwl_fw_ini_debug_flow_tlv {
#define IWL_FW_INI_MAX_NAME 32
/**
+ * struct iwl_fw_ini_region_cfg_dhc - defines dhc response to dump.
+ *
+ * @id_and_grp: id and group of dhc response.
+ * @desc: dhc response descriptor.
+ */
+struct iwl_fw_ini_region_cfg_dhc {
+ __le32 id_and_grp;
+ __le32 desc;
+} __packed; /* FW_DEBUG_TLV_REGION_DHC_API_S_VER_1 */
+
+/**
* struct iwl_fw_ini_region_cfg_internal - meta data of internal memory region
+ *
* @num_of_range: the amount of ranges in the region
* @range_data_size: size of the data to read per range, in bytes.
*/
@@ -146,6 +178,7 @@ struct iwl_fw_ini_region_cfg_internal {
/**
* struct iwl_fw_ini_region_cfg_fifos - meta data of fifos region
+ *
* @fid1: fifo id 1 - bitmap of lmac tx/rx fifos to include in the region
* @fid2: fifo id 2 - bitmap of umac rx fifos to include in the region.
* It is unused for tx.
@@ -163,34 +196,43 @@ struct iwl_fw_ini_region_cfg_fifos {
/**
* struct iwl_fw_ini_region_cfg
+ *
* @region_id: ID of this dump configuration
* @region_type: &enum iwl_fw_ini_region_type
- * @num_regions: amount of regions in the address array.
+ * @domain: dump this region only if the specific domain is enabled
+ * &enum iwl_fw_ini_dbg_domain
* @name_len: name length
* @name: file name to use for this region
* @internal: used in case the region uses internal memory.
* @allocation_id: For DRAM type field substitutes for allocation_id
* @fifos: used in case of fifos region.
+ * @dhc_desc: dhc response descriptor.
+ * @notif_id_and_grp: dump this region only if the specific notification
+ * occurred.
* @offset: offset to use for each memory base address
* @start_addr: array of addresses.
*/
struct iwl_fw_ini_region_cfg {
__le32 region_id;
__le32 region_type;
+ __le32 domain;
__le32 name_len;
u8 name[IWL_FW_INI_MAX_NAME];
union {
struct iwl_fw_ini_region_cfg_internal internal;
__le32 allocation_id;
struct iwl_fw_ini_region_cfg_fifos fifos;
- };
+ struct iwl_fw_ini_region_cfg_dhc dhc_desc;
+ __le32 notif_id_and_grp;
+ }; /* FW_DEBUG_TLV_REGION_EXT_INT_PARAMS_API_U_VER_1 */
__le32 offset;
__le32 start_addr[];
-} __packed; /* FW_DEBUG_TLV_REGION_CONFIG_S */
+} __packed; /* FW_DEBUG_TLV_REGION_CONFIG_API_S_VER_1 */
/**
- * struct iwl_fw_ini_region_tlv - (IWL_FW_INI_TLV_TYPE_REGION_CFG)
- * DUMP sections define IDs and triggers that use those IDs TLV
+ * struct iwl_fw_ini_region_tlv - (IWL_UCODE_TLV_TYPE_REGIONS)
+ * defines memory regions to dump
+ *
* @header: header
* @num_regions: how many different region section and IDs are coming next
* @region_config: list of dump configurations
@@ -199,13 +241,12 @@ struct iwl_fw_ini_region_tlv {
struct iwl_fw_ini_header header;
__le32 num_regions;
struct iwl_fw_ini_region_cfg region_config[];
-} __packed; /* FW_DEBUG_TLV_REGIONS_S_VER_1 */
+} __packed; /* FW_DEBUG_TLV_REGIONS_API_S_VER_1 */
/**
- * struct iwl_fw_ini_trigger - (IWL_FW_INI_TLV_TYPE_DUMP_CFG)
- * Region sections define IDs and triggers that use those IDs TLV
+ * struct iwl_fw_ini_trigger
*
- * @trigger_id: enum &iwl_fw_ini_tigger_id
+ * @trigger_id: &enum iwl_fw_ini_trigger_id
* @override_trig: determines how apply trigger in case a trigger with the
* same id is already in use. Using the first 2 bytes:
* Byte 0: if 0, override trigger configuration, otherwise use the
@@ -214,6 +255,7 @@ struct iwl_fw_ini_region_tlv {
* existing trigger.
* @dump_delay: delay from trigger fire to dump, in usec
* @occurrences: max amount of times to be fired
+ * @reserved: to align to FW struct
* @ignore_consec: ignore consecutive triggers, in usec
* @force_restart: force FW restart
* @multi_dut: initiate debug dump data on several DUTs
@@ -226,17 +268,18 @@ struct iwl_fw_ini_trigger {
__le32 override_trig;
__le32 dump_delay;
__le32 occurrences;
+ __le32 reserved;
__le32 ignore_consec;
__le32 force_restart;
__le32 multi_dut;
__le32 trigger_data;
__le32 num_regions;
__le32 data[];
-} __packed; /* FW_TLV_DEBUG_TRIGGER_CONFIG_S */
+} __packed; /* FW_TLV_DEBUG_TRIGGER_CONFIG_API_S_VER_1 */
/**
- * struct iwl_fw_ini_trigger_tlv - (IWL_FW_INI_TLV_TYPE_TRIGGERS_CFG)
- * DUMP sections define IDs and triggers that use those IDs TLV
+ * struct iwl_fw_ini_trigger_tlv - (IWL_UCODE_TLV_TYPE_TRIGGERS)
+ * Triggers that hold memory regions to dump in case a trigger fires
*
* @header: header
* @num_triggers: how many different triggers section and IDs are coming next
@@ -246,16 +289,18 @@ struct iwl_fw_ini_trigger_tlv {
struct iwl_fw_ini_header header;
__le32 num_triggers;
struct iwl_fw_ini_trigger trigger_config[];
-} __packed; /* FW_TLV_DEBUG_TRIGGERS_S_VER_1 */
+} __packed; /* FW_TLV_DEBUG_TRIGGERS_API_S_VER_1 */
/**
* enum iwl_fw_ini_trigger_id
+ *
* @IWL_FW_TRIGGER_ID_FW_ASSERT: FW assert
* @IWL_FW_TRIGGER_ID_FW_HW_ERROR: HW assert
* @IWL_FW_TRIGGER_ID_FW_TFD_Q_HANG: TFD queue hang
* @IWL_FW_TRIGGER_ID_FW_DEBUG_HOST_TRIGGER: FW debug notification
- * @IWL_FW_TRIGGER_ID_FW_GENERIC_NOTIFOCATION: FW generic notification
+ * @IWL_FW_TRIGGER_ID_FW_GENERIC_NOTIFICATION: FW generic notification
* @IWL_FW_TRIGGER_ID_USER_TRIGGER: User trigger
+ * @IWL_FW_TRIGGER_ID_PERIODIC_TRIGGER: triggers periodically
* @IWL_FW_TRIGGER_ID_HOST_PEER_CLIENT_INACTIVITY: peer inactivity
* @IWL_FW_TRIGGER_ID_HOST_TX_LATENCY_THRESHOLD_CROSSED: TX latency
* threshold was crossed
@@ -299,47 +344,51 @@ enum iwl_fw_ini_trigger_id {
/* FW triggers */
IWL_FW_TRIGGER_ID_FW_DEBUG_HOST_TRIGGER = 4,
- IWL_FW_TRIGGER_ID_FW_GENERIC_NOTIFOCATION = 5,
+ IWL_FW_TRIGGER_ID_FW_GENERIC_NOTIFICATION = 5,
/* User trigger */
IWL_FW_TRIGGER_ID_USER_TRIGGER = 6,
+ /* periodic uses the data field for the interval time */
+ IWL_FW_TRIGGER_ID_PERIODIC_TRIGGER = 7,
+
/* Host triggers */
- IWL_FW_TRIGGER_ID_HOST_PEER_CLIENT_INACTIVITY = 7,
- IWL_FW_TRIGGER_ID_HOST_TX_LATENCY_THRESHOLD_CROSSED = 8,
- IWL_FW_TRIGGER_ID_HOST_TX_RESPONSE_STATUS_FAILED = 9,
- IWL_FW_TRIGGER_ID_HOST_OS_REQ_DEAUTH_PEER = 10,
- IWL_FW_TRIGGER_ID_HOST_STOP_GO_REQUEST = 11,
- IWL_FW_TRIGGER_ID_HOST_START_GO_REQUEST = 12,
- IWL_FW_TRIGGER_ID_HOST_JOIN_GROUP_REQUEST = 13,
- IWL_FW_TRIGGER_ID_HOST_SCAN_START = 14,
- IWL_FW_TRIGGER_ID_HOST_SCAN_SUBMITTED = 15,
- IWL_FW_TRIGGER_ID_HOST_SCAN_PARAMS = 16,
- IWL_FW_TRIGGER_ID_HOST_CHECK_FOR_HANG = 17,
- IWL_FW_TRIGGER_ID_HOST_BAR_RECEIVED = 18,
- IWL_FW_TRIGGER_ID_HOST_AGG_TX_RESPONSE_STATUS_FAILED = 19,
- IWL_FW_TRIGGER_ID_HOST_EAPOL_TX_RESPONSE_FAILED = 20,
- IWL_FW_TRIGGER_ID_HOST_FAKE_TX_RESPONSE_SUSPECTED = 21,
- IWL_FW_TRIGGER_ID_HOST_AUTH_REQ_FROM_ASSOC_CLIENT = 22,
- IWL_FW_TRIGGER_ID_HOST_ROAM_COMPLETE = 23,
- IWL_FW_TRIGGER_ID_HOST_AUTH_ASSOC_FAST_FAILED = 24,
- IWL_FW_TRIGGER_ID_HOST_D3_START = 25,
- IWL_FW_TRIGGER_ID_HOST_D3_END = 26,
- IWL_FW_TRIGGER_ID_HOST_BSS_MISSED_BEACONS = 27,
- IWL_FW_TRIGGER_ID_HOST_P2P_CLIENT_MISSED_BEACONS = 28,
- IWL_FW_TRIGGER_ID_HOST_PEER_CLIENT_TX_FAILURES = 29,
- IWL_FW_TRIGGER_ID_HOST_TX_WFD_ACTION_FRAME_FAILED = 30,
- IWL_FW_TRIGGER_ID_HOST_AUTH_ASSOC_FAILED = 31,
- IWL_FW_TRIGGER_ID_HOST_SCAN_COMPLETE = 32,
- IWL_FW_TRIGGER_ID_HOST_SCAN_ABORT = 33,
- IWL_FW_TRIGGER_ID_HOST_NIC_ALIVE = 34,
- IWL_FW_TRIGGER_ID_HOST_CHANNEL_SWITCH_COMPLETE = 35,
+ IWL_FW_TRIGGER_ID_HOST_PEER_CLIENT_INACTIVITY = 8,
+ IWL_FW_TRIGGER_ID_HOST_TX_LATENCY_THRESHOLD_CROSSED = 9,
+ IWL_FW_TRIGGER_ID_HOST_TX_RESPONSE_STATUS_FAILED = 10,
+ IWL_FW_TRIGGER_ID_HOST_OS_REQ_DEAUTH_PEER = 11,
+ IWL_FW_TRIGGER_ID_HOST_STOP_GO_REQUEST = 12,
+ IWL_FW_TRIGGER_ID_HOST_START_GO_REQUEST = 13,
+ IWL_FW_TRIGGER_ID_HOST_JOIN_GROUP_REQUEST = 14,
+ IWL_FW_TRIGGER_ID_HOST_SCAN_START = 15,
+ IWL_FW_TRIGGER_ID_HOST_SCAN_SUBMITTED = 16,
+ IWL_FW_TRIGGER_ID_HOST_SCAN_PARAMS = 17,
+ IWL_FW_TRIGGER_ID_HOST_CHECK_FOR_HANG = 18,
+ IWL_FW_TRIGGER_ID_HOST_BAR_RECEIVED = 19,
+ IWL_FW_TRIGGER_ID_HOST_AGG_TX_RESPONSE_STATUS_FAILED = 20,
+ IWL_FW_TRIGGER_ID_HOST_EAPOL_TX_RESPONSE_FAILED = 21,
+ IWL_FW_TRIGGER_ID_HOST_FAKE_TX_RESPONSE_SUSPECTED = 22,
+ IWL_FW_TRIGGER_ID_HOST_AUTH_REQ_FROM_ASSOC_CLIENT = 23,
+ IWL_FW_TRIGGER_ID_HOST_ROAM_COMPLETE = 24,
+ IWL_FW_TRIGGER_ID_HOST_AUTH_ASSOC_FAST_FAILED = 25,
+ IWL_FW_TRIGGER_ID_HOST_D3_START = 26,
+ IWL_FW_TRIGGER_ID_HOST_D3_END = 27,
+ IWL_FW_TRIGGER_ID_HOST_BSS_MISSED_BEACONS = 28,
+ IWL_FW_TRIGGER_ID_HOST_P2P_CLIENT_MISSED_BEACONS = 29,
+ IWL_FW_TRIGGER_ID_HOST_PEER_CLIENT_TX_FAILURES = 30,
+ IWL_FW_TRIGGER_ID_HOST_TX_WFD_ACTION_FRAME_FAILED = 31,
+ IWL_FW_TRIGGER_ID_HOST_AUTH_ASSOC_FAILED = 32,
+ IWL_FW_TRIGGER_ID_HOST_SCAN_COMPLETE = 33,
+ IWL_FW_TRIGGER_ID_HOST_SCAN_ABORT = 34,
+ IWL_FW_TRIGGER_ID_HOST_NIC_ALIVE = 35,
+ IWL_FW_TRIGGER_ID_HOST_CHANNEL_SWITCH_COMPLETE = 36,
IWL_FW_TRIGGER_ID_NUM,
}; /* FW_DEBUG_TLV_TRIGGER_ID_E_VER_1 */
/**
* enum iwl_fw_ini_apply_point
+ *
* @IWL_FW_INI_APPLY_INVALID: invalid
* @IWL_FW_INI_APPLY_EARLY: pre loading FW
* @IWL_FW_INI_APPLY_AFTER_ALIVE: first cmd from host after alive
@@ -360,6 +409,7 @@ enum iwl_fw_ini_apply_point {
/**
* enum iwl_fw_ini_allocation_id
+ *
* @IWL_FW_INI_ALLOCATION_INVALID: invalid
* @IWL_FW_INI_ALLOCATION_ID_DBGC1: allocation meant for DBGC1 configuration
* @IWL_FW_INI_ALLOCATION_ID_DBGC2: allocation meant for DBGC2 configuration
@@ -380,18 +430,22 @@ enum iwl_fw_ini_allocation_id {
/**
* enum iwl_fw_ini_buffer_location
+ *
* @IWL_FW_INI_LOCATION_INVALID: invalid
* @IWL_FW_INI_LOCATION_SRAM_PATH: SRAM location
* @IWL_FW_INI_LOCATION_DRAM_PATH: DRAM location
+ * @IWL_FW_INI_LOCATION_NPK_PATH: NPK location
*/
enum iwl_fw_ini_buffer_location {
IWL_FW_INI_LOCATION_INVALID,
IWL_FW_INI_LOCATION_SRAM_PATH,
IWL_FW_INI_LOCATION_DRAM_PATH,
+ IWL_FW_INI_LOCATION_NPK_PATH,
}; /* FW_DEBUG_TLV_BUFFER_LOCATION_E_VER_1 */
/**
* enum iwl_fw_ini_debug_flow
+ *
* @IWL_FW_INI_DEBUG_INVALID: invalid
* @IWL_FW_INI_DEBUG_DBTR_FLOW: undefined
* @IWL_FW_INI_DEBUG_TB2DTF_FLOW: undefined
@@ -404,6 +458,7 @@ enum iwl_fw_ini_debug_flow {
/**
* enum iwl_fw_ini_region_type
+ *
* @IWL_FW_INI_REGION_INVALID: invalid
* @IWL_FW_INI_REGION_DEVICE_MEMORY: device internal memory
* @IWL_FW_INI_REGION_PERIPHERY_MAC: periphery registers of MAC
@@ -416,6 +471,10 @@ enum iwl_fw_ini_debug_flow {
* @IWL_FW_INI_REGION_RXF: RX fifo
* @IWL_FW_INI_REGION_PAGING: paging memory
* @IWL_FW_INI_REGION_CSR: CSR registers
+ * @IWL_FW_INI_REGION_NOTIFICATION: FW notification data
+ * @IWL_FW_INI_REGION_DHC: dhc response to dump
+ * @IWL_FW_INI_REGION_LMAC_ERROR_TABLE: lmac error table
+ * @IWL_FW_INI_REGION_UMAC_ERROR_TABLE: umac error table
* @IWL_FW_INI_REGION_NUM: number of region types
*/
enum iwl_fw_ini_region_type {
@@ -431,6 +490,10 @@ enum iwl_fw_ini_region_type {
IWL_FW_INI_REGION_RXF,
IWL_FW_INI_REGION_PAGING,
IWL_FW_INI_REGION_CSR,
+ IWL_FW_INI_REGION_NOTIFICATION,
+ IWL_FW_INI_REGION_DHC,
+ IWL_FW_INI_REGION_LMAC_ERROR_TABLE,
+ IWL_FW_INI_REGION_UMAC_ERROR_TABLE,
IWL_FW_INI_REGION_NUM
}; /* FW_DEBUG_TLV_REGION_TYPE_E_VER_1 */
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/location.h b/drivers/net/wireless/intel/iwlwifi/fw/api/location.h
index 5dddb21c1c4d..8d78b0e671c0 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/location.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/location.h
@@ -675,6 +675,59 @@ struct iwl_tof_range_rsp_ap_entry_ntfy_v3 {
} __packed; /* LOCATION_RANGE_RSP_AP_ETRY_NTFY_API_S_VER_3 */
/**
+ * struct iwl_tof_range_rsp_ap_entry_ntfy_v4 - AP parameters (response)
+ * @bssid: BSSID of the AP
+ * @measure_status: current APs measurement status, one of
+ * &enum iwl_tof_entry_status.
+ * @measure_bw: Current AP Bandwidth: 0 20MHz, 1 40MHz, 2 80MHz
+ * @rtt: The Round Trip Time that took for the last measurement for
+ * current AP [pSec]
+ * @rtt_variance: The Variance of the RTT values measured for current AP
+ * @rtt_spread: The Difference between the maximum and the minimum RTT
+ * values measured for current AP in the current session [pSec]
+ * @rssi: RSSI as uploaded in the Channel Estimation notification
+ * @rssi_spread: The Difference between the maximum and the minimum RSSI values
+ * measured for current AP in the current session
+ * @last_burst: 1 if no more FTM sessions are scheduled for this responder
+ * @refusal_period: refusal period in case of
+ * @IWL_TOF_ENTRY_RESPONDER_CANNOT_COLABORATE [sec]
+ * @timestamp: The GP2 Clock [usec] where Channel Estimation notification was
+ * uploaded by the LMAC
+ * @start_tsf: measurement start time in TSF of the mac specified in the range
+ * request
+ * @rx_rate_n_flags: rate and flags of the last FTM frame received from this
+ * responder
+ * @tx_rate_n_flags: rate and flags of the last ack sent to this responder
+ * @t2t3_initiator: as calculated from the algo in the initiator
+ * @t1t4_responder: as calculated from the algo in the responder
+ * @common_calib: Calib val that was used in for this AP measurement
+ * @specific_calib: val that was used in for this AP measurement
+ * @papd_calib_output: The result of the tof papd calibration that was injected
+ * into the algorithm.
+ */
+struct iwl_tof_range_rsp_ap_entry_ntfy_v4 {
+ u8 bssid[ETH_ALEN];
+ u8 measure_status;
+ u8 measure_bw;
+ __le32 rtt;
+ __le32 rtt_variance;
+ __le32 rtt_spread;
+ s8 rssi;
+ u8 rssi_spread;
+ u8 last_burst;
+ u8 refusal_period;
+ __le32 timestamp;
+ __le32 start_tsf;
+ __le32 rx_rate_n_flags;
+ __le32 tx_rate_n_flags;
+ __le32 t2t3_initiator;
+ __le32 t1t4_responder;
+ __le16 common_calib;
+ __le16 specific_calib;
+ __le32 papd_calib_output;
+} __packed; /* LOCATION_RANGE_RSP_AP_ETRY_NTFY_API_S_VER_4 */
+
+/**
* struct iwl_tof_range_rsp_ap_entry_ntfy - AP parameters (response)
* @bssid: BSSID of the AP
* @measure_status: current APs measurement status, one of
@@ -704,6 +757,8 @@ struct iwl_tof_range_rsp_ap_entry_ntfy_v3 {
* @specific_calib: val that was used in for this AP measurement
* @papd_calib_output: The result of the tof papd calibration that was injected
* into the algorithm.
+ * @rttConfidence: a value between 0 - 31 that represents the rtt accuracy.
+ * @reserved: for alignment
*/
struct iwl_tof_range_rsp_ap_entry_ntfy {
u8 bssid[ETH_ALEN];
@@ -725,7 +780,9 @@ struct iwl_tof_range_rsp_ap_entry_ntfy {
__le16 common_calib;
__le16 specific_calib;
__le32 papd_calib_output;
-} __packed; /* LOCATION_RANGE_RSP_AP_ETRY_NTFY_API_S_VER_4 */
+ u8 rttConfidence;
+ u8 reserved[3];
+} __packed; /* LOCATION_RANGE_RSP_AP_ETRY_NTFY_API_S_VER_5 */
/**
* enum iwl_tof_response_status - tof response status
@@ -761,6 +818,22 @@ struct iwl_tof_range_rsp_ntfy_v5 {
} __packed; /* LOCATION_RANGE_RSP_NTFY_API_S_VER_5 */
/**
+ * struct iwl_tof_range_rsp_ntfy_v6 - ranging response notification
+ * @request_id: A Token ID of the corresponding Range request
+ * @num_of_aps: Number of APs results
+ * @last_report: 1 if no more FTM sessions are scheduled, 0 otherwise.
+ * @reserved: reserved
+ * @ap: per-AP data
+ */
+struct iwl_tof_range_rsp_ntfy_v6 {
+ u8 request_id;
+ u8 num_of_aps;
+ u8 last_report;
+ u8 reserved;
+ struct iwl_tof_range_rsp_ap_entry_ntfy_v4 ap[IWL_MVM_TOF_MAX_APS];
+} __packed; /* LOCATION_RANGE_RSP_NTFY_API_S_VER_6 */
+
+/**
* struct iwl_tof_range_rsp_ntfy - ranging response notification
* @request_id: A Token ID of the corresponding Range request
* @num_of_aps: Number of APs results
@@ -774,7 +847,7 @@ struct iwl_tof_range_rsp_ntfy {
u8 last_report;
u8 reserved;
struct iwl_tof_range_rsp_ap_entry_ntfy ap[IWL_MVM_TOF_MAX_APS];
-} __packed; /* LOCATION_RANGE_RSP_NTFY_API_S_VER_6 */
+} __packed; /* LOCATION_RANGE_RSP_NTFY_API_S_VER_7 */
#define IWL_MVM_TOF_MCSI_BUF_SIZE (245)
/**
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h b/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h
index 941c50477003..85c5e367cbf1 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h
@@ -542,6 +542,66 @@ enum iwl_he_htc_flags {
#define IWL_HE_HTC_LINK_ADAP_BOTH (3 << IWL_HE_HTC_LINK_ADAP_POS)
/**
+ * struct iwl_he_sta_context_cmd_v1 - configure FW to work with HE AP
+ * @sta_id: STA id
+ * @tid_limit: max num of TIDs in TX HE-SU multi-TID agg
+ * 0 - bad value, 1 - multi-tid not supported, 2..8 - tid limit
+ * @reserved1: reserved byte for future use
+ * @reserved2: reserved byte for future use
+ * @flags: see %iwl_11ax_sta_ctxt_flags
+ * @ref_bssid_addr: reference BSSID used by the AP
+ * @reserved0: reserved 2 bytes for aligning the ref_bssid_addr field to 8 bytes
+ * @htc_flags: which features are supported in HTC
+ * @frag_flags: frag support in A-MSDU
+ * @frag_level: frag support level
+ * @frag_max_num: max num of "open" MSDUs in the receiver (in power of 2)
+ * @frag_min_size: min frag size (except last frag)
+ * @pkt_ext: optional, exists according to PPE-present bit in the HE-PHY capa
+ * @bss_color: 11ax AP ID that is used in the HE SIG-A to mark inter BSS frame
+ * @htc_trig_based_pkt_ext: default PE in 4us units
+ * @frame_time_rts_th: HE duration RTS threshold, in units of 32us
+ * @rand_alloc_ecwmin: random CWmin = 2**ECWmin-1
+ * @rand_alloc_ecwmax: random CWmax = 2**ECWmax-1
+ * @reserved3: reserved byte for future use
+ * @trig_based_txf: MU EDCA Parameter set for the trigger based traffic queues
+ */
+struct iwl_he_sta_context_cmd_v1 {
+ u8 sta_id;
+ u8 tid_limit;
+ u8 reserved1;
+ u8 reserved2;
+ __le32 flags;
+
+ /* The below fields are set via Multiple BSSID IE */
+ u8 ref_bssid_addr[6];
+ __le16 reserved0;
+
+ /* The below fields are set via HE-capabilities IE */
+ __le32 htc_flags;
+
+ u8 frag_flags;
+ u8 frag_level;
+ u8 frag_max_num;
+ u8 frag_min_size;
+
+ /* The below fields are set via PPE thresholds element */
+ struct iwl_he_pkt_ext pkt_ext;
+
+ /* The below fields are set via HE-Operation IE */
+ u8 bss_color;
+ u8 htc_trig_based_pkt_ext;
+ __le16 frame_time_rts_th;
+
+ /* Random access parameter set (i.e. RAPS) */
+ u8 rand_alloc_ecwmin;
+ u8 rand_alloc_ecwmax;
+ __le16 reserved3;
+
+ /* The below fields are set via MU EDCA parameter set element */
+ struct iwl_he_backoff_conf trig_based_txf[AC_NUM];
+} __packed; /* STA_CONTEXT_DOT11AX_API_S_VER_1 */
+
+/**
* struct iwl_he_sta_context_cmd - configure FW to work with HE AP
* @sta_id: STA id
* @tid_limit: max num of TIDs in TX HE-SU multi-TID agg
@@ -564,6 +624,14 @@ enum iwl_he_htc_flags {
* @rand_alloc_ecwmax: random CWmax = 2**ECWmax-1
* @reserved3: reserved byte for future use
* @trig_based_txf: MU EDCA Parameter set for the trigger based traffic queues
+ * @max_bssid_indicator: indicator of the max bssid supported on the associated
+ * bss
+ * @bssid_index: index of the associated VAP
+ * @ema_ap: AP supports enhanced Multi BSSID advertisement
+ * @profile_periodicity: number of Beacon periods that are needed to receive the
+ * complete VAPs info
+ * @bssid_count: actual number of VAPs in the MultiBSS Set
+ * @reserved4: alignment
*/
struct iwl_he_sta_context_cmd {
u8 sta_id;
@@ -599,7 +667,14 @@ struct iwl_he_sta_context_cmd {
/* The below fields are set via MU EDCA parameter set element */
struct iwl_he_backoff_conf trig_based_txf[AC_NUM];
-} __packed; /* STA_CONTEXT_DOT11AX_API_S */
+
+ u8 max_bssid_indicator;
+ u8 bssid_index;
+ u8 ema_ap;
+ u8 profile_periodicity;
+ u8 bssid_count;
+ u8 reserved4[3];
+} __packed; /* STA_CONTEXT_DOT11AX_API_S_VER_2 */
/**
* struct iwl_he_monitor_cmd - configure air sniffer for HE
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h b/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h
index 93b392f0c6a4..97b49843e318 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h
@@ -8,7 +8,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright (C) 2018 Intel Corporation
+ * Copyright(C) 2018 - 2019 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,7 +31,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright (C) 2018 Intel Corporation
+ * Copyright(C) 2018 - 2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -233,7 +233,8 @@ struct iwl_nvm_get_info_phy {
__le32 rx_chains;
} __packed; /* REGULATORY_NVM_GET_INFO_PHY_SKU_SECTION_S_VER_1 */
-#define IWL_NUM_CHANNELS (51)
+#define IWL_NUM_CHANNELS_V1 51
+#define IWL_NUM_CHANNELS 110
/**
* struct iwl_nvm_get_info_regulatory - regulatory information
@@ -241,13 +242,39 @@ struct iwl_nvm_get_info_phy {
* @channel_profile: regulatory data of this channel
* @reserved: reserved
*/
-struct iwl_nvm_get_info_regulatory {
+struct iwl_nvm_get_info_regulatory_v1 {
__le32 lar_enabled;
- __le16 channel_profile[IWL_NUM_CHANNELS];
+ __le16 channel_profile[IWL_NUM_CHANNELS_V1];
__le16 reserved;
} __packed; /* REGULATORY_NVM_GET_INFO_REGULATORY_S_VER_1 */
/**
+ * struct iwl_nvm_get_info_regulatory - regulatory information
+ * @lar_enabled: is LAR enabled
+ * @n_channels: number of valid channels in the array
+ * @channel_profile: regulatory data of this channel
+ */
+struct iwl_nvm_get_info_regulatory {
+ __le32 lar_enabled;
+ __le32 n_channels;
+ __le32 channel_profile[IWL_NUM_CHANNELS];
+} __packed; /* REGULATORY_NVM_GET_INFO_REGULATORY_S_VER_2 */
+
+/**
+ * struct iwl_nvm_get_info_rsp_v3 - response to get NVM data
+ * @general: general NVM data
+ * @mac_sku: data relating to MAC sku
+ * @phy_sku: data relating to PHY sku
+ * @regulatory: regulatory data
+ */
+struct iwl_nvm_get_info_rsp_v3 {
+ struct iwl_nvm_get_info_general general;
+ struct iwl_nvm_get_info_sku mac_sku;
+ struct iwl_nvm_get_info_phy phy_sku;
+ struct iwl_nvm_get_info_regulatory_v1 regulatory;
+} __packed; /* REGULATORY_NVM_GET_INFO_RSP_API_S_VER_3 */
+
+/**
* struct iwl_nvm_get_info_rsp - response to get NVM data
* @general: general NVM data
* @mac_sku: data relating to MAC sku
@@ -259,7 +286,7 @@ struct iwl_nvm_get_info_rsp {
struct iwl_nvm_get_info_sku mac_sku;
struct iwl_nvm_get_info_phy phy_sku;
struct iwl_nvm_get_info_regulatory regulatory;
-} __packed; /* REGULATORY_NVM_GET_INFO_RSP_API_S_VER_3 */
+} __packed; /* REGULATORY_NVM_GET_INFO_RSP_API_S_VER_4 */
/**
* struct iwl_nvm_access_complete_cmd - NVM_ACCESS commands are completed
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h b/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h
index 6e8224ce8906..d55312ef58c9 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h
@@ -8,7 +8,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,7 +31,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -688,13 +688,6 @@ struct iwl_rx_mpdu_desc {
#define IWL_RX_DESC_SIZE_V1 offsetofend(struct iwl_rx_mpdu_desc, v1)
-#define IWL_CD_STTS_OPTIMIZED_POS 0
-#define IWL_CD_STTS_OPTIMIZED_MSK 0x01
-#define IWL_CD_STTS_TRANSFER_STATUS_POS 1
-#define IWL_CD_STTS_TRANSFER_STATUS_MSK 0x0E
-#define IWL_CD_STTS_WIFI_STATUS_POS 4
-#define IWL_CD_STTS_WIFI_STATUS_MSK 0xF0
-
#define RX_NO_DATA_CHAIN_A_POS 0
#define RX_NO_DATA_CHAIN_A_MSK (0xff << RX_NO_DATA_CHAIN_A_POS)
#define RX_NO_DATA_CHAIN_B_POS 8
@@ -747,62 +740,6 @@ struct iwl_rx_no_data {
__le32 rx_vec[2];
} __packed; /* RX_NO_DATA_NTFY_API_S_VER_1 */
-/**
- * enum iwl_completion_desc_transfer_status - transfer status (bits 1-3)
- * @IWL_CD_STTS_UNUSED: unused
- * @IWL_CD_STTS_UNUSED_2: unused
- * @IWL_CD_STTS_END_TRANSFER: successful transfer complete.
- * In sniffer mode, when split is used, set in last CD completion. (RX)
- * @IWL_CD_STTS_OVERFLOW: In sniffer mode, when using split - used for
- * all CD completion. (RX)
- * @IWL_CD_STTS_ABORTED: CR abort / close flow. (RX)
- * @IWL_CD_STTS_ERROR: general error (RX)
- */
-enum iwl_completion_desc_transfer_status {
- IWL_CD_STTS_UNUSED,
- IWL_CD_STTS_UNUSED_2,
- IWL_CD_STTS_END_TRANSFER,
- IWL_CD_STTS_OVERFLOW,
- IWL_CD_STTS_ABORTED,
- IWL_CD_STTS_ERROR,
-};
-
-/**
- * enum iwl_completion_desc_wifi_status - wifi status (bits 4-7)
- * @IWL_CD_STTS_VALID: the packet is valid (RX)
- * @IWL_CD_STTS_FCS_ERR: frame check sequence error (RX)
- * @IWL_CD_STTS_SEC_KEY_ERR: error handling the security key of rx (RX)
- * @IWL_CD_STTS_DECRYPTION_ERR: error decrypting the frame (RX)
- * @IWL_CD_STTS_DUP: duplicate packet (RX)
- * @IWL_CD_STTS_ICV_MIC_ERR: MIC error (RX)
- * @IWL_CD_STTS_INTERNAL_SNAP_ERR: problems removing the snap (RX)
- * @IWL_CD_STTS_SEC_PORT_FAIL: security port fail (RX)
- * @IWL_CD_STTS_BA_OLD_SN: block ack received old SN (RX)
- * @IWL_CD_STTS_QOS_NULL: QoS null packet (RX)
- * @IWL_CD_STTS_MAC_HDR_ERR: MAC header conversion error (RX)
- * @IWL_CD_STTS_MAX_RETRANS: reached max number of retransmissions (TX)
- * @IWL_CD_STTS_EX_LIFETIME: exceeded lifetime (TX)
- * @IWL_CD_STTS_NOT_USED: completed but not used (RX)
- * @IWL_CD_STTS_REPLAY_ERR: pn check failed, replay error (RX)
- */
-enum iwl_completion_desc_wifi_status {
- IWL_CD_STTS_VALID,
- IWL_CD_STTS_FCS_ERR,
- IWL_CD_STTS_SEC_KEY_ERR,
- IWL_CD_STTS_DECRYPTION_ERR,
- IWL_CD_STTS_DUP,
- IWL_CD_STTS_ICV_MIC_ERR,
- IWL_CD_STTS_INTERNAL_SNAP_ERR,
- IWL_CD_STTS_SEC_PORT_FAIL,
- IWL_CD_STTS_BA_OLD_SN,
- IWL_CD_STTS_QOS_NULL,
- IWL_CD_STTS_MAC_HDR_ERR,
- IWL_CD_STTS_MAX_RETRANS,
- IWL_CD_STTS_EX_LIFETIME,
- IWL_CD_STTS_NOT_USED,
- IWL_CD_STTS_REPLAY_ERR,
-};
-
struct iwl_frame_release {
u8 baid;
u8 reserved;
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h b/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h
index 890a939c463d..1a67a2a439ab 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h
@@ -788,7 +788,53 @@ struct iwl_umac_scan_complete {
__le32 reserved;
} __packed; /* SCAN_COMPLETE_NTF_UMAC_API_S_VER_1 */
-#define SCAN_OFFLOAD_MATCHING_CHANNELS_LEN 5
+#define SCAN_OFFLOAD_MATCHING_CHANNELS_LEN_V1 5
+#define SCAN_OFFLOAD_MATCHING_CHANNELS_LEN 7
+
+/**
+ * struct iwl_scan_offload_profile_match_v1 - match information
+ * @bssid: matched bssid
+ * @reserved: reserved
+ * @channel: channel where the match occurred
+ * @energy: energy
+ * @matching_feature: feature matches
+ * @matching_channels: bitmap of channels that matched, referencing
+ * the channels passed in the scan offload request.
+ */
+struct iwl_scan_offload_profile_match_v1 {
+ u8 bssid[ETH_ALEN];
+ __le16 reserved;
+ u8 channel;
+ u8 energy;
+ u8 matching_feature;
+ u8 matching_channels[SCAN_OFFLOAD_MATCHING_CHANNELS_LEN_V1];
+} __packed; /* SCAN_OFFLOAD_PROFILE_MATCH_RESULTS_S_VER_1 */
+
+/**
+ * struct iwl_scan_offload_profiles_query_v1 - match results query response
+ * @matched_profiles: bitmap of matched profiles, referencing the
+ * matches passed in the scan offload request
+ * @last_scan_age: age of the last offloaded scan
+ * @n_scans_done: number of offloaded scans done
+ * @gp2_d0u: GP2 when D0U occurred
+ * @gp2_invoked: GP2 when scan offload was invoked
+ * @resume_while_scanning: not used
+ * @self_recovery: obsolete
+ * @reserved: reserved
+ * @matches: array of match information, one for each match
+ */
+struct iwl_scan_offload_profiles_query_v1 {
+ __le32 matched_profiles;
+ __le32 last_scan_age;
+ __le32 n_scans_done;
+ __le32 gp2_d0u;
+ __le32 gp2_invoked;
+ u8 resume_while_scanning;
+ u8 self_recovery;
+ __le16 reserved;
+ struct iwl_scan_offload_profile_match_v1 matches[IWL_SCAN_MAX_PROFILES];
+} __packed; /* SCAN_OFFLOAD_PROFILES_QUERY_RSP_S_VER_2 */
+
/**
* struct iwl_scan_offload_profile_match - match information
* @bssid: matched bssid
@@ -797,7 +843,7 @@ struct iwl_umac_scan_complete {
* @energy: energy
* @matching_feature: feature matches
* @matching_channels: bitmap of channels that matched, referencing
- * the channels passed in tue scan offload request
+ * the channels passed in the scan offload request.
*/
struct iwl_scan_offload_profile_match {
u8 bssid[ETH_ALEN];
@@ -806,7 +852,7 @@ struct iwl_scan_offload_profile_match {
u8 energy;
u8 matching_feature;
u8 matching_channels[SCAN_OFFLOAD_MATCHING_CHANNELS_LEN];
-} __packed; /* SCAN_OFFLOAD_PROFILE_MATCH_RESULTS_S_VER_1 */
+} __packed; /* SCAN_OFFLOAD_PROFILE_MATCH_RESULTS_S_VER_2 */
/**
* struct iwl_scan_offload_profiles_query - match results query response
@@ -831,7 +877,7 @@ struct iwl_scan_offload_profiles_query {
u8 self_recovery;
__le16 reserved;
struct iwl_scan_offload_profile_match matches[IWL_SCAN_MAX_PROFILES];
-} __packed; /* SCAN_OFFLOAD_PROFILES_QUERY_RSP_S_VER_2 */
+} __packed; /* SCAN_OFFLOAD_PROFILES_QUERY_RSP_S_VER_3 */
/**
* struct iwl_umac_scan_iter_complete_notif - notifies end of scanning iteration
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/txq.h b/drivers/net/wireless/intel/iwlwifi/fw/api/txq.h
index 6ac240b6eace..73196cbc7fbe 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/txq.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/txq.h
@@ -8,6 +8,7 @@
* Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
+ * Copyright(c) 2019 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -30,6 +31,7 @@
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
+ * Copyright(c) 2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -133,6 +135,7 @@ enum iwl_tx_queue_cfg_actions {
#define IWL_DEFAULT_QUEUE_SIZE 256
#define IWL_MGMT_QUEUE_SIZE 16
+#define IWL_CMD_QUEUE_SIZE 32
/**
* struct iwl_tx_queue_cfg_cmd - txq hw scheduler config command
* @sta_id: station id
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
index d7380016f1c0..5f52e40a2903 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
@@ -545,6 +545,7 @@ static const struct iwl_prph_range iwl_prph_dump_addr_22000[] = {
{ .start = 0x00a04590, .end = 0x00a04590 },
{ .start = 0x00a04598, .end = 0x00a04598 },
{ .start = 0x00a045c0, .end = 0x00a045f4 },
+ { .start = 0x00a05c18, .end = 0x00a05c1c },
{ .start = 0x00a0c000, .end = 0x00a0c018 },
{ .start = 0x00a0c020, .end = 0x00a0c028 },
{ .start = 0x00a0c038, .end = 0x00a0c094 },
@@ -557,6 +558,12 @@ static const struct iwl_prph_range iwl_prph_dump_addr_22000[] = {
{ .start = 0x00a0c1b0, .end = 0x00a0c1b8 },
};
+static const struct iwl_prph_range iwl_prph_dump_addr_ax210[] = {
+ { .start = 0x00d03c00, .end = 0x00d03c64 },
+ { .start = 0x00d05c18, .end = 0x00d05c1c },
+ { .start = 0x00d0c000, .end = 0x00d0c174 },
+};
+
static void iwl_read_prph_block(struct iwl_trans *trans, u32 start,
u32 len_bytes, __le32 *data)
{
@@ -675,7 +682,8 @@ static void iwl_fw_prph_handler(struct iwl_fw_runtime *fwrt, void *ptr,
u32 range_len;
if (fwrt->trans->cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
- /* TODO */
+ range_len = ARRAY_SIZE(iwl_prph_dump_addr_ax210);
+ handler(fwrt, iwl_prph_dump_addr_ax210, range_len, ptr);
} else if (fwrt->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22000) {
range_len = ARRAY_SIZE(iwl_prph_dump_addr_22000);
handler(fwrt, iwl_prph_dump_addr_22000, range_len, ptr);
@@ -804,8 +812,8 @@ static void iwl_dump_paging(struct iwl_fw_runtime *fwrt,
}
static struct iwl_fw_error_dump_file *
-_iwl_fw_error_dump(struct iwl_fw_runtime *fwrt,
- struct iwl_fw_dump_ptrs *fw_error_dump)
+iwl_fw_error_dump_file(struct iwl_fw_runtime *fwrt,
+ struct iwl_fw_dump_ptrs *fw_error_dump)
{
struct iwl_fw_error_dump_file *dump_file;
struct iwl_fw_error_dump_data *dump_data;
@@ -909,11 +917,8 @@ _iwl_fw_error_dump(struct iwl_fw_runtime *fwrt,
dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_DEV_FW_INFO);
dump_data->len = cpu_to_le32(sizeof(*dump_info));
dump_info = (void *)dump_data->data;
- dump_info->device_family =
- fwrt->trans->cfg->device_family ==
- IWL_DEVICE_FAMILY_7000 ?
- cpu_to_le32(IWL_FW_ERROR_DUMP_FAMILY_7) :
- cpu_to_le32(IWL_FW_ERROR_DUMP_FAMILY_8);
+ 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));
memcpy(dump_info->fw_human_readable, fwrt->fw->human_readable,
@@ -967,10 +972,11 @@ _iwl_fw_error_dump(struct iwl_fw_runtime *fwrt,
if (fifo_len) {
iwl_fw_dump_rxf(fwrt, &dump_data);
iwl_fw_dump_txf(fwrt, &dump_data);
- if (radio_len)
- iwl_read_radio_regs(fwrt, &dump_data);
}
+ if (radio_len)
+ iwl_read_radio_regs(fwrt, &dump_data);
+
if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_ERROR_INFO) &&
fwrt->dump.desc) {
dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_ERROR_INFO);
@@ -1049,14 +1055,14 @@ static int iwl_dump_ini_prph_iter(struct iwl_fw_runtime *fwrt,
{
struct iwl_fw_ini_error_dump_range *range = range_ptr;
__le32 *val = range->data;
- u32 addr, prph_val, offset = le32_to_cpu(reg->offset);
+ u32 prph_val;
+ u32 addr = le32_to_cpu(reg->start_addr[idx]) + le32_to_cpu(reg->offset);
int i;
- range->start_addr = reg->start_addr[idx];
+ range->start_addr = cpu_to_le64(addr);
range->range_data_size = reg->internal.range_data_size;
for (i = 0; i < le32_to_cpu(reg->internal.range_data_size); i += 4) {
- addr = le32_to_cpu(range->start_addr) + i;
- prph_val = iwl_read_prph(fwrt->trans, addr + offset);
+ prph_val = iwl_read_prph(fwrt->trans, addr + i);
if (prph_val == 0x5a5a5a5a)
return -EBUSY;
*val++ = cpu_to_le32(prph_val);
@@ -1071,16 +1077,13 @@ static int iwl_dump_ini_csr_iter(struct iwl_fw_runtime *fwrt,
{
struct iwl_fw_ini_error_dump_range *range = range_ptr;
__le32 *val = range->data;
- u32 addr, offset = le32_to_cpu(reg->offset);
+ u32 addr = le32_to_cpu(reg->start_addr[idx]) + le32_to_cpu(reg->offset);
int i;
- range->start_addr = reg->start_addr[idx];
+ range->start_addr = cpu_to_le64(addr);
range->range_data_size = reg->internal.range_data_size;
- for (i = 0; i < le32_to_cpu(reg->internal.range_data_size); i += 4) {
- addr = le32_to_cpu(range->start_addr) + i;
- *val++ = cpu_to_le32(iwl_trans_read32(fwrt->trans,
- addr + offset));
- }
+ for (i = 0; i < le32_to_cpu(reg->internal.range_data_size); i += 4)
+ *val++ = cpu_to_le32(iwl_trans_read32(fwrt->trans, addr + i));
return sizeof(*range) + le32_to_cpu(range->range_data_size);
}
@@ -1090,12 +1093,11 @@ static int iwl_dump_ini_dev_mem_iter(struct iwl_fw_runtime *fwrt,
void *range_ptr, int idx)
{
struct iwl_fw_ini_error_dump_range *range = range_ptr;
- u32 addr = le32_to_cpu(range->start_addr);
- u32 offset = le32_to_cpu(reg->offset);
+ u32 addr = le32_to_cpu(reg->start_addr[idx]) + le32_to_cpu(reg->offset);
- range->start_addr = reg->start_addr[idx];
+ range->start_addr = cpu_to_le64(addr);
range->range_data_size = reg->internal.range_data_size;
- iwl_trans_read_mem_bytes(fwrt->trans, addr + offset, range->data,
+ iwl_trans_read_mem_bytes(fwrt->trans, addr, range->data,
le32_to_cpu(reg->internal.range_data_size));
return sizeof(*range) + le32_to_cpu(range->range_data_size);
@@ -1109,7 +1111,7 @@ iwl_dump_ini_paging_gen2_iter(struct iwl_fw_runtime *fwrt,
struct iwl_fw_ini_error_dump_range *range = range_ptr;
u32 page_size = fwrt->trans->init_dram.paging[idx].size;
- range->start_addr = cpu_to_le32(idx);
+ range->start_addr = cpu_to_le64(idx);
range->range_data_size = cpu_to_le32(page_size);
memcpy(range->data, fwrt->trans->init_dram.paging[idx].block,
page_size);
@@ -1129,7 +1131,7 @@ static int iwl_dump_ini_paging_iter(struct iwl_fw_runtime *fwrt,
dma_addr_t addr = fwrt->fw_paging_db[idx].fw_paging_phys;
u32 page_size = fwrt->fw_paging_db[idx].fw_paging_size;
- range->start_addr = cpu_to_le32(idx);
+ range->start_addr = cpu_to_le64(idx);
range->range_data_size = cpu_to_le32(page_size);
dma_sync_single_for_cpu(fwrt->trans->dev, addr, page_size,
DMA_BIDIRECTIONAL);
@@ -1152,7 +1154,7 @@ iwl_dump_ini_mon_dram_iter(struct iwl_fw_runtime *fwrt,
if (start_addr == 0x5a5a5a5a)
return -EBUSY;
- range->start_addr = cpu_to_le32(start_addr);
+ range->start_addr = cpu_to_le64(start_addr);
range->range_data_size = cpu_to_le32(fwrt->trans->fw_mon[idx].size);
memcpy(range->data, fwrt->trans->fw_mon[idx].block,
@@ -1228,10 +1230,11 @@ static int iwl_dump_ini_txf_iter(struct iwl_fw_runtime *fwrt,
{
struct iwl_fw_ini_fifo_error_dump_range *range = range_ptr;
struct iwl_ini_txf_iter_data *iter;
+ struct iwl_fw_ini_error_dump_register *reg_dump = (void *)range->data;
u32 offs = le32_to_cpu(reg->offset), addr;
u32 registers_size =
- le32_to_cpu(reg->fifos.num_of_registers) * sizeof(__le32);
- __le32 *val = range->data;
+ le32_to_cpu(reg->fifos.num_of_registers) * sizeof(*reg_dump);
+ __le32 *data;
unsigned long flags;
int i;
@@ -1249,11 +1252,18 @@ static int iwl_dump_ini_txf_iter(struct iwl_fw_runtime *fwrt,
iwl_write_prph_no_grab(fwrt->trans, TXF_LARC_NUM + offs, iter->fifo);
- /* read txf registers */
+ /*
+ * read txf registers. for each register, write to the dump the
+ * register address and its value
+ */
for (i = 0; i < le32_to_cpu(reg->fifos.num_of_registers); i++) {
addr = le32_to_cpu(reg->start_addr[i]) + offs;
- *val++ = cpu_to_le32(iwl_read_prph_no_grab(fwrt->trans, addr));
+ reg_dump->addr = cpu_to_le32(addr);
+ reg_dump->data = cpu_to_le32(iwl_read_prph_no_grab(fwrt->trans,
+ addr));
+
+ reg_dump++;
}
if (reg->fifos.header_only) {
@@ -1270,8 +1280,9 @@ static int iwl_dump_ini_txf_iter(struct iwl_fw_runtime *fwrt,
/* Read FIFO */
addr = TXF_READ_MODIFY_DATA + offs;
- for (i = 0; i < iter->fifo_size; i += sizeof(__le32))
- *val++ = cpu_to_le32(iwl_read_prph_no_grab(fwrt->trans, addr));
+ data = (void *)reg_dump;
+ for (i = 0; i < iter->fifo_size; i += sizeof(*data))
+ *data++ = cpu_to_le32(iwl_read_prph_no_grab(fwrt->trans, addr));
out:
iwl_trans_release_nic_access(fwrt->trans, &flags);
@@ -1327,10 +1338,11 @@ static int iwl_dump_ini_rxf_iter(struct iwl_fw_runtime *fwrt,
{
struct iwl_fw_ini_fifo_error_dump_range *range = range_ptr;
struct iwl_ini_rxf_data rxf_data;
+ struct iwl_fw_ini_error_dump_register *reg_dump = (void *)range->data;
u32 offs = le32_to_cpu(reg->offset), addr;
u32 registers_size =
- le32_to_cpu(reg->fifos.num_of_registers) * sizeof(__le32);
- __le32 *val = range->data;
+ le32_to_cpu(reg->fifos.num_of_registers) * sizeof(*reg_dump);
+ __le32 *data;
unsigned long flags;
int i;
@@ -1341,17 +1353,22 @@ static int iwl_dump_ini_rxf_iter(struct iwl_fw_runtime *fwrt,
if (!iwl_trans_grab_nic_access(fwrt->trans, &flags))
return -EBUSY;
- offs += rxf_data.offset;
-
range->fifo_num = cpu_to_le32(rxf_data.fifo_num);
range->num_of_registers = reg->fifos.num_of_registers;
range->range_data_size = cpu_to_le32(rxf_data.size + registers_size);
- /* read rxf registers */
+ /*
+ * read rxf registers. for each register, write to the dump the
+ * register address and its value
+ */
for (i = 0; i < le32_to_cpu(reg->fifos.num_of_registers); i++) {
addr = le32_to_cpu(reg->start_addr[i]) + offs;
- *val++ = cpu_to_le32(iwl_read_prph_no_grab(fwrt->trans, addr));
+ reg_dump->addr = cpu_to_le32(addr);
+ reg_dump->data = cpu_to_le32(iwl_read_prph_no_grab(fwrt->trans,
+ addr));
+
+ reg_dump++;
}
if (reg->fifos.header_only) {
@@ -1359,6 +1376,12 @@ static int iwl_dump_ini_rxf_iter(struct iwl_fw_runtime *fwrt,
goto out;
}
+ /*
+ * region register have absolute value so apply rxf offset after
+ * reading the registers
+ */
+ offs += rxf_data.offset;
+
/* Lock fence */
iwl_write_prph_no_grab(fwrt->trans, RXF_SET_FENCE_MODE + offs, 0x1);
/* Set fence pointer to the same place like WR pointer */
@@ -1369,8 +1392,9 @@ static int iwl_dump_ini_rxf_iter(struct iwl_fw_runtime *fwrt,
/* Read FIFO */
addr = RXF_FIFO_RD_FENCE_INC + offs;
- for (i = 0; i < rxf_data.size; i += sizeof(__le32))
- *val++ = cpu_to_le32(iwl_read_prph_no_grab(fwrt->trans, addr));
+ data = (void *)reg_dump;
+ for (i = 0; i < rxf_data.size; i += sizeof(*data))
+ *data++ = cpu_to_le32(iwl_read_prph_no_grab(fwrt->trans, addr));
out:
iwl_trans_release_nic_access(fwrt->trans, &flags);
@@ -1384,32 +1408,86 @@ static void *iwl_dump_ini_mem_fill_header(struct iwl_fw_runtime *fwrt,
{
struct iwl_fw_ini_error_dump *dump = data;
+ dump->header.version = cpu_to_le32(IWL_INI_DUMP_MEM_VER);
+
return dump->ranges;
}
static void
-*iwl_dump_ini_mon_dram_fill_header(struct iwl_fw_runtime *fwrt,
- struct iwl_fw_ini_region_cfg *reg,
- void *data)
+*iwl_dump_ini_mon_fill_header(struct iwl_fw_runtime *fwrt,
+ struct iwl_fw_ini_region_cfg *reg,
+ struct iwl_fw_ini_monitor_dump *data,
+ u32 write_ptr_addr, u32 write_ptr_msk,
+ u32 cycle_cnt_addr, u32 cycle_cnt_msk)
{
- struct iwl_fw_ini_monitor_dram_dump *mon_dump = (void *)data;
u32 write_ptr, cycle_cnt;
unsigned long flags;
if (!iwl_trans_grab_nic_access(fwrt->trans, &flags)) {
- IWL_ERR(fwrt, "Failed to get DRAM monitor header\n");
+ IWL_ERR(fwrt, "Failed to get monitor header\n");
return NULL;
}
- write_ptr = iwl_read_umac_prph_no_grab(fwrt->trans,
- MON_BUFF_WRPTR_VER2);
- cycle_cnt = iwl_read_umac_prph_no_grab(fwrt->trans,
- MON_BUFF_CYCLE_CNT_VER2);
+
+ write_ptr = iwl_read_prph_no_grab(fwrt->trans, write_ptr_addr);
+ cycle_cnt = iwl_read_prph_no_grab(fwrt->trans, cycle_cnt_addr);
+
iwl_trans_release_nic_access(fwrt->trans, &flags);
- mon_dump->write_ptr = cpu_to_le32(write_ptr);
- mon_dump->cycle_cnt = cpu_to_le32(cycle_cnt);
+ data->header.version = cpu_to_le32(IWL_INI_DUMP_MONITOR_VER);
+ data->write_ptr = cpu_to_le32(write_ptr & write_ptr_msk);
+ data->cycle_cnt = cpu_to_le32(cycle_cnt & cycle_cnt_msk);
+
+ return data->ranges;
+}
+
+static void
+*iwl_dump_ini_mon_dram_fill_header(struct iwl_fw_runtime *fwrt,
+ struct iwl_fw_ini_region_cfg *reg,
+ void *data)
+{
+ struct iwl_fw_ini_monitor_dump *mon_dump = (void *)data;
+ u32 write_ptr_addr, write_ptr_msk, cycle_cnt_addr, cycle_cnt_msk;
+
+ switch (fwrt->trans->cfg->device_family) {
+ case IWL_DEVICE_FAMILY_9000:
+ case IWL_DEVICE_FAMILY_22000:
+ write_ptr_addr = MON_BUFF_WRPTR_VER2;
+ write_ptr_msk = -1;
+ cycle_cnt_addr = MON_BUFF_CYCLE_CNT_VER2;
+ cycle_cnt_msk = -1;
+ break;
+ default:
+ IWL_ERR(fwrt, "Unsupported device family %d\n",
+ fwrt->trans->cfg->device_family);
+ return NULL;
+ }
+
+ return iwl_dump_ini_mon_fill_header(fwrt, reg, mon_dump, write_ptr_addr,
+ write_ptr_msk, cycle_cnt_addr,
+ cycle_cnt_msk);
+}
+
+static void
+*iwl_dump_ini_mon_smem_fill_header(struct iwl_fw_runtime *fwrt,
+ struct iwl_fw_ini_region_cfg *reg,
+ void *data)
+{
+ struct iwl_fw_ini_monitor_dump *mon_dump = (void *)data;
+ const struct iwl_cfg *cfg = fwrt->trans->cfg;
+
+ if (fwrt->trans->cfg->device_family != IWL_DEVICE_FAMILY_9000 &&
+ fwrt->trans->cfg->device_family != IWL_DEVICE_FAMILY_22000) {
+ IWL_ERR(fwrt, "Unsupported device family %d\n",
+ fwrt->trans->cfg->device_family);
+ return NULL;
+ }
+
+ return iwl_dump_ini_mon_fill_header(fwrt, reg, mon_dump,
+ cfg->fw_mon_smem_write_ptr_addr,
+ cfg->fw_mon_smem_write_ptr_msk,
+ cfg->fw_mon_smem_cycle_cnt_ptr_addr,
+ cfg->fw_mon_smem_cycle_cnt_ptr_msk);
- return mon_dump->ranges;
}
static void *iwl_dump_ini_fifo_fill_header(struct iwl_fw_runtime *fwrt,
@@ -1418,6 +1496,8 @@ static void *iwl_dump_ini_fifo_fill_header(struct iwl_fw_runtime *fwrt,
{
struct iwl_fw_ini_fifo_error_dump *dump = data;
+ dump->header.version = cpu_to_le32(IWL_INI_DUMP_FIFO_VER);
+
return dump->ranges;
}
@@ -1509,7 +1589,8 @@ static u32 iwl_dump_ini_paging_get_size(struct iwl_fw_runtime *fwrt,
static u32 iwl_dump_ini_mon_dram_get_size(struct iwl_fw_runtime *fwrt,
struct iwl_fw_ini_region_cfg *reg)
{
- u32 size = sizeof(struct iwl_fw_ini_monitor_dram_dump);
+ u32 size = sizeof(struct iwl_fw_ini_monitor_dump) +
+ sizeof(struct iwl_fw_ini_error_dump_range);
if (fwrt->trans->num_blocks)
size += fwrt->trans->fw_mon[0].size;
@@ -1517,6 +1598,15 @@ static u32 iwl_dump_ini_mon_dram_get_size(struct iwl_fw_runtime *fwrt,
return size;
}
+static u32 iwl_dump_ini_mon_smem_get_size(struct iwl_fw_runtime *fwrt,
+ struct iwl_fw_ini_region_cfg *reg)
+{
+ return sizeof(struct iwl_fw_ini_monitor_dump) +
+ iwl_dump_ini_mem_ranges(fwrt, reg) *
+ (sizeof(struct iwl_fw_ini_error_dump_range) +
+ le32_to_cpu(reg->internal.range_data_size));
+}
+
static u32 iwl_dump_ini_txf_get_size(struct iwl_fw_runtime *fwrt,
struct iwl_fw_ini_region_cfg *reg)
{
@@ -1524,7 +1614,7 @@ static u32 iwl_dump_ini_txf_get_size(struct iwl_fw_runtime *fwrt,
void *fifo_iter = fwrt->dump.fifo_iter;
u32 size = 0;
u32 fifo_hdr = sizeof(struct iwl_fw_ini_fifo_error_dump_range) +
- le32_to_cpu(reg->fifos.num_of_registers) * sizeof(__le32);
+ le32_to_cpu(reg->fifos.num_of_registers) * sizeof(__le32) * 2;
fwrt->dump.fifo_iter = &iter;
while (iwl_ini_txf_iter(fwrt, reg)) {
@@ -1547,7 +1637,7 @@ static u32 iwl_dump_ini_rxf_get_size(struct iwl_fw_runtime *fwrt,
struct iwl_ini_rxf_data rx_data;
u32 size = sizeof(struct iwl_fw_ini_fifo_error_dump) +
sizeof(struct iwl_fw_ini_fifo_error_dump_range) +
- le32_to_cpu(reg->fifos.num_of_registers) * sizeof(__le32);
+ le32_to_cpu(reg->fifos.num_of_registers) * sizeof(__le32) * 2;
if (reg->fifos.header_only)
return size;
@@ -1584,27 +1674,31 @@ struct iwl_dump_ini_mem_ops {
* @fwrt: fw runtime struct.
* @data: dump memory data.
* @reg: region to copy to the dump.
+ * @ops: memory dump operations.
*/
static void
iwl_dump_ini_mem(struct iwl_fw_runtime *fwrt,
- enum iwl_fw_ini_region_type type,
struct iwl_fw_error_dump_data **data,
struct iwl_fw_ini_region_cfg *reg,
struct iwl_dump_ini_mem_ops *ops)
{
struct iwl_fw_ini_error_dump_header *header = (void *)(*data)->data;
+ u32 num_of_ranges, i, type = le32_to_cpu(reg->region_type);
void *range;
- u32 num_of_ranges, i;
if (WARN_ON(!ops || !ops->get_num_of_ranges || !ops->get_size ||
!ops->fill_mem_hdr || !ops->fill_range))
return;
+ IWL_DEBUG_FW(fwrt, "WRT: collecting region: id=%d, type=%d\n",
+ le32_to_cpu(reg->region_id), type);
+
num_of_ranges = ops->get_num_of_ranges(fwrt, reg);
(*data)->type = cpu_to_le32(type | INI_DUMP_BIT);
(*data)->len = cpu_to_le32(ops->get_size(fwrt, reg));
+ header->region_id = reg->region_id;
header->num_of_ranges = cpu_to_le32(num_of_ranges);
header->name_len = cpu_to_le32(min_t(int, IWL_FW_INI_MAX_NAME,
le32_to_cpu(reg->name_len)));
@@ -1612,7 +1706,8 @@ iwl_dump_ini_mem(struct iwl_fw_runtime *fwrt,
range = ops->fill_mem_hdr(fwrt, reg, header);
if (!range) {
- IWL_ERR(fwrt, "Failed to fill region header: id=%d, type=%d\n",
+ IWL_ERR(fwrt,
+ "WRT: failed to fill region header: id=%d, type=%d\n",
le32_to_cpu(reg->region_id), type);
memset(*data, 0, le32_to_cpu((*data)->len));
return;
@@ -1622,7 +1717,8 @@ iwl_dump_ini_mem(struct iwl_fw_runtime *fwrt,
int range_size = ops->fill_range(fwrt, reg, range, i);
if (range_size < 0) {
- IWL_ERR(fwrt, "Failed to dump region: id=%d, type=%d\n",
+ IWL_ERR(fwrt,
+ "WRT: failed to dump region: id=%d, type=%d\n",
le32_to_cpu(reg->region_id), type);
memset(*data, 0, le32_to_cpu((*data)->len));
return;
@@ -1643,23 +1739,30 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt,
for (i = 0; i < le32_to_cpu(trigger->num_regions); i++) {
u32 reg_id = le32_to_cpu(trigger->data[i]);
struct iwl_fw_ini_region_cfg *reg;
- enum iwl_fw_ini_region_type type;
if (WARN_ON(reg_id >= ARRAY_SIZE(fwrt->dump.active_regs)))
continue;
reg = fwrt->dump.active_regs[reg_id];
- if (WARN(!reg, "Unassigned region %d\n", reg_id))
+ if (!reg) {
+ IWL_WARN(fwrt,
+ "WRT: unassigned region id %d, skipping\n",
+ reg_id);
continue;
+ }
- type = le32_to_cpu(reg->region_type);
- switch (type) {
+ /* currently the driver supports always on domain only */
+ if (le32_to_cpu(reg->domain) != IWL_FW_INI_DBG_DOMAIN_ALWAYS_ON)
+ continue;
+
+ switch (le32_to_cpu(reg->region_type)) {
case IWL_FW_INI_REGION_DEVICE_MEMORY:
case IWL_FW_INI_REGION_PERIPHERY_MAC:
case IWL_FW_INI_REGION_PERIPHERY_PHY:
case IWL_FW_INI_REGION_PERIPHERY_AUX:
- case IWL_FW_INI_REGION_INTERNAL_BUFFER:
case IWL_FW_INI_REGION_CSR:
+ case IWL_FW_INI_REGION_LMAC_ERROR_TABLE:
+ case IWL_FW_INI_REGION_UMAC_ERROR_TABLE:
size += hdr_len + iwl_dump_ini_mem_get_size(fwrt, reg);
break;
case IWL_FW_INI_REGION_TXF:
@@ -1668,7 +1771,7 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt,
case IWL_FW_INI_REGION_RXF:
size += hdr_len + iwl_dump_ini_rxf_get_size(fwrt, reg);
break;
- case IWL_FW_INI_REGION_PAGING: {
+ case IWL_FW_INI_REGION_PAGING:
size += hdr_len;
if (iwl_fw_dbg_is_paging_enabled(fwrt)) {
size += iwl_dump_ini_paging_get_size(fwrt, reg);
@@ -1677,13 +1780,16 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt,
reg);
}
break;
- }
case IWL_FW_INI_REGION_DRAM_BUFFER:
if (!fwrt->trans->num_blocks)
break;
size += hdr_len +
iwl_dump_ini_mon_dram_get_size(fwrt, reg);
break;
+ case IWL_FW_INI_REGION_INTERNAL_BUFFER:
+ size += hdr_len +
+ iwl_dump_ini_mon_smem_get_size(fwrt, reg);
+ break;
case IWL_FW_INI_REGION_DRAM_IMR:
/* Undefined yet */
default:
@@ -1701,7 +1807,6 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt,
for (i = 0; i < num; i++) {
u32 reg_id = le32_to_cpu(trigger->data[i]);
- enum iwl_fw_ini_region_type type;
struct iwl_fw_ini_region_cfg *reg;
struct iwl_dump_ini_mem_ops ops;
@@ -1713,15 +1818,19 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt,
if (!reg)
continue;
- type = le32_to_cpu(reg->region_type);
- switch (type) {
+ /* currently the driver supports always on domain only */
+ if (le32_to_cpu(reg->domain) != IWL_FW_INI_DBG_DOMAIN_ALWAYS_ON)
+ continue;
+
+ switch (le32_to_cpu(reg->region_type)) {
case IWL_FW_INI_REGION_DEVICE_MEMORY:
- case IWL_FW_INI_REGION_INTERNAL_BUFFER:
+ case IWL_FW_INI_REGION_LMAC_ERROR_TABLE:
+ case IWL_FW_INI_REGION_UMAC_ERROR_TABLE:
ops.get_num_of_ranges = iwl_dump_ini_mem_ranges;
ops.get_size = iwl_dump_ini_mem_get_size;
ops.fill_mem_hdr = iwl_dump_ini_mem_fill_header;
ops.fill_range = iwl_dump_ini_dev_mem_iter;
- iwl_dump_ini_mem(fwrt, type, data, reg, &ops);
+ iwl_dump_ini_mem(fwrt, data, reg, &ops);
break;
case IWL_FW_INI_REGION_PERIPHERY_MAC:
case IWL_FW_INI_REGION_PERIPHERY_PHY:
@@ -1730,16 +1839,23 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt,
ops.get_size = iwl_dump_ini_mem_get_size;
ops.fill_mem_hdr = iwl_dump_ini_mem_fill_header;
ops.fill_range = iwl_dump_ini_prph_iter;
- iwl_dump_ini_mem(fwrt, type, data, reg, &ops);
+ iwl_dump_ini_mem(fwrt, data, reg, &ops);
break;
case IWL_FW_INI_REGION_DRAM_BUFFER:
ops.get_num_of_ranges = iwl_dump_ini_mon_dram_ranges;
ops.get_size = iwl_dump_ini_mon_dram_get_size;
ops.fill_mem_hdr = iwl_dump_ini_mon_dram_fill_header;
ops.fill_range = iwl_dump_ini_mon_dram_iter;
- iwl_dump_ini_mem(fwrt, type, data, reg, &ops);
+ iwl_dump_ini_mem(fwrt, data, reg, &ops);
+ break;
+ case IWL_FW_INI_REGION_INTERNAL_BUFFER:
+ ops.get_num_of_ranges = iwl_dump_ini_mem_ranges;
+ ops.get_size = iwl_dump_ini_mon_smem_get_size;
+ ops.fill_mem_hdr = iwl_dump_ini_mon_smem_fill_header;
+ ops.fill_range = iwl_dump_ini_dev_mem_iter;
+ iwl_dump_ini_mem(fwrt, data, reg, &ops);
break;
- case IWL_FW_INI_REGION_PAGING: {
+ case IWL_FW_INI_REGION_PAGING:
ops.fill_mem_hdr = iwl_dump_ini_mem_fill_header;
if (iwl_fw_dbg_is_paging_enabled(fwrt)) {
ops.get_num_of_ranges =
@@ -1754,9 +1870,8 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt,
ops.fill_range = iwl_dump_ini_paging_gen2_iter;
}
- iwl_dump_ini_mem(fwrt, type, data, reg, &ops);
+ iwl_dump_ini_mem(fwrt, data, reg, &ops);
break;
- }
case IWL_FW_INI_REGION_TXF: {
struct iwl_ini_txf_iter_data iter = { .init = true };
void *fifo_iter = fwrt->dump.fifo_iter;
@@ -1766,7 +1881,7 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt,
ops.get_size = iwl_dump_ini_txf_get_size;
ops.fill_mem_hdr = iwl_dump_ini_fifo_fill_header;
ops.fill_range = iwl_dump_ini_txf_iter;
- iwl_dump_ini_mem(fwrt, type, data, reg, &ops);
+ iwl_dump_ini_mem(fwrt, data, reg, &ops);
fwrt->dump.fifo_iter = fifo_iter;
break;
}
@@ -1775,14 +1890,14 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt,
ops.get_size = iwl_dump_ini_rxf_get_size;
ops.fill_mem_hdr = iwl_dump_ini_fifo_fill_header;
ops.fill_range = iwl_dump_ini_rxf_iter;
- iwl_dump_ini_mem(fwrt, type, data, reg, &ops);
+ iwl_dump_ini_mem(fwrt, data, reg, &ops);
break;
case IWL_FW_INI_REGION_CSR:
ops.get_num_of_ranges = iwl_dump_ini_mem_ranges;
ops.get_size = iwl_dump_ini_mem_get_size;
ops.fill_mem_hdr = iwl_dump_ini_mem_fill_header;
ops.fill_range = iwl_dump_ini_csr_iter;
- iwl_dump_ini_mem(fwrt, type, data, reg, &ops);
+ iwl_dump_ini_mem(fwrt, data, reg, &ops);
break;
case IWL_FW_INI_REGION_DRAM_IMR:
/* This is undefined yet */
@@ -1793,16 +1908,13 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt,
}
static struct iwl_fw_error_dump_file *
-_iwl_fw_error_ini_dump(struct iwl_fw_runtime *fwrt,
- struct iwl_fw_dump_ptrs *fw_error_dump)
+iwl_fw_error_ini_dump_file(struct iwl_fw_runtime *fwrt)
{
- int size, id = le32_to_cpu(fwrt->dump.desc->trig_desc.type);
+ int size;
struct iwl_fw_error_dump_data *dump_data;
struct iwl_fw_error_dump_file *dump_file;
struct iwl_fw_ini_trigger *trigger;
-
- if (id == FW_DBG_TRIGGER_FW_ASSERT)
- id = IWL_FW_TRIGGER_ID_FW_ASSERT;
+ enum iwl_fw_ini_trigger_id id = fwrt->dump.ini_trig_id;
if (!iwl_fw_ini_trigger_on(fwrt, id))
return NULL;
@@ -1819,8 +1931,6 @@ _iwl_fw_error_ini_dump(struct iwl_fw_runtime *fwrt,
if (!dump_file)
return NULL;
- fw_error_dump->fwrt_ptr = dump_file;
-
dump_file->barker = cpu_to_le32(IWL_FW_ERROR_DUMP_BARKER);
dump_data = (void *)dump_file->data;
dump_file->file_len = cpu_to_le32(size);
@@ -1830,47 +1940,27 @@ _iwl_fw_error_ini_dump(struct iwl_fw_runtime *fwrt,
return dump_file;
}
-void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
+static void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
{
- struct iwl_fw_dump_ptrs *fw_error_dump;
+ struct iwl_fw_dump_ptrs fw_error_dump = {};
struct iwl_fw_error_dump_file *dump_file;
struct scatterlist *sg_dump_data;
u32 file_len;
u32 dump_mask = fwrt->fw->dbg.dump_mask;
- IWL_DEBUG_INFO(fwrt, "WRT dump start\n");
-
- /* there's no point in fw dump if the bus is dead */
- if (test_bit(STATUS_TRANS_DEAD, &fwrt->trans->status)) {
- IWL_ERR(fwrt, "Skip fw error dump since bus is dead\n");
- goto out;
- }
-
- fw_error_dump = kzalloc(sizeof(*fw_error_dump), GFP_KERNEL);
- if (!fw_error_dump)
- goto out;
-
- if (fwrt->trans->ini_valid)
- dump_file = _iwl_fw_error_ini_dump(fwrt, fw_error_dump);
- else
- dump_file = _iwl_fw_error_dump(fwrt, fw_error_dump);
-
- if (!dump_file) {
- kfree(fw_error_dump);
+ dump_file = iwl_fw_error_dump_file(fwrt, &fw_error_dump);
+ if (!dump_file)
goto out;
- }
if (!fwrt->trans->ini_valid && fwrt->dump.monitor_only)
dump_mask &= IWL_FW_ERROR_DUMP_FW_MONITOR;
- if (!fwrt->trans->ini_valid)
- fw_error_dump->trans_ptr =
- iwl_trans_dump_data(fwrt->trans, dump_mask);
-
+ fw_error_dump.trans_ptr = iwl_trans_dump_data(fwrt->trans, dump_mask);
file_len = le32_to_cpu(dump_file->file_len);
- fw_error_dump->fwrt_len = file_len;
- if (fw_error_dump->trans_ptr) {
- file_len += fw_error_dump->trans_ptr->len;
+ fw_error_dump.fwrt_len = file_len;
+
+ if (fw_error_dump.trans_ptr) {
+ file_len += fw_error_dump.trans_ptr->len;
dump_file->file_len = cpu_to_le32(file_len);
}
@@ -1878,27 +1968,49 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
if (sg_dump_data) {
sg_pcopy_from_buffer(sg_dump_data,
sg_nents(sg_dump_data),
- fw_error_dump->fwrt_ptr,
- fw_error_dump->fwrt_len, 0);
- if (fw_error_dump->trans_ptr)
+ fw_error_dump.fwrt_ptr,
+ fw_error_dump.fwrt_len, 0);
+ if (fw_error_dump.trans_ptr)
sg_pcopy_from_buffer(sg_dump_data,
sg_nents(sg_dump_data),
- fw_error_dump->trans_ptr->data,
- fw_error_dump->trans_ptr->len,
- fw_error_dump->fwrt_len);
+ fw_error_dump.trans_ptr->data,
+ fw_error_dump.trans_ptr->len,
+ fw_error_dump.fwrt_len);
dev_coredumpsg(fwrt->trans->dev, sg_dump_data, file_len,
GFP_KERNEL);
}
- vfree(fw_error_dump->fwrt_ptr);
- vfree(fw_error_dump->trans_ptr);
- kfree(fw_error_dump);
+ vfree(fw_error_dump.fwrt_ptr);
+ vfree(fw_error_dump.trans_ptr);
out:
iwl_fw_free_dump_desc(fwrt);
clear_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status);
- IWL_DEBUG_INFO(fwrt, "WRT dump done\n");
}
-IWL_EXPORT_SYMBOL(iwl_fw_error_dump);
+
+static void iwl_fw_error_ini_dump(struct iwl_fw_runtime *fwrt)
+{
+ struct iwl_fw_error_dump_file *dump_file;
+ struct scatterlist *sg_dump_data;
+ u32 file_len;
+
+ dump_file = iwl_fw_error_ini_dump_file(fwrt);
+ if (!dump_file)
+ goto out;
+
+ file_len = le32_to_cpu(dump_file->file_len);
+
+ sg_dump_data = alloc_sgtable(file_len);
+ if (sg_dump_data) {
+ sg_pcopy_from_buffer(sg_dump_data, sg_nents(sg_dump_data),
+ dump_file, file_len, 0);
+ dev_coredumpsg(fwrt->trans->dev, sg_dump_data, file_len,
+ GFP_KERNEL);
+ }
+ vfree(dump_file);
+out:
+ fwrt->dump.ini_trig_id = IWL_FW_TRIGGER_ID_INVALID;
+ clear_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status);
+}
const struct iwl_fw_dump_desc iwl_dump_desc_assert = {
.trig_desc = {
@@ -1912,6 +2024,17 @@ int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt,
bool monitor_only,
unsigned int delay)
{
+ u32 trig_type = le32_to_cpu(desc->trig_desc.type);
+ int ret;
+
+ if (fwrt->trans->ini_valid) {
+ ret = iwl_fw_dbg_ini_collect(fwrt, trig_type);
+ if (!ret)
+ iwl_fw_free_dump_desc(fwrt);
+
+ return ret;
+ }
+
if (test_and_set_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status))
return -EBUSY;
@@ -1953,10 +2076,10 @@ int iwl_fw_dbg_error_collect(struct iwl_fw_runtime *fwrt,
}
IWL_EXPORT_SYMBOL(iwl_fw_dbg_error_collect);
-int _iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt,
- enum iwl_fw_dbg_trigger trig,
- const char *str, size_t len,
- struct iwl_fw_dbg_trigger_tlv *trigger)
+int iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt,
+ enum iwl_fw_dbg_trigger trig,
+ const char *str, size_t len,
+ struct iwl_fw_dbg_trigger_tlv *trigger)
{
struct iwl_fw_dump_desc *desc;
unsigned int delay = 0;
@@ -1993,50 +2116,73 @@ int _iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt,
return iwl_fw_dbg_collect_desc(fwrt, desc, monitor_only, delay);
}
-IWL_EXPORT_SYMBOL(_iwl_fw_dbg_collect);
+IWL_EXPORT_SYMBOL(iwl_fw_dbg_collect);
-int iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt,
- u32 id, const char *str, size_t len)
+int _iwl_fw_dbg_ini_collect(struct iwl_fw_runtime *fwrt,
+ enum iwl_fw_ini_trigger_id id)
{
- struct iwl_fw_dump_desc *desc;
struct iwl_fw_ini_active_triggers *active;
u32 occur, delay;
- if (!fwrt->trans->ini_valid)
- return _iwl_fw_dbg_collect(fwrt, id, str, len, NULL);
-
- if (id == FW_DBG_TRIGGER_USER)
- id = IWL_FW_TRIGGER_ID_USER_TRIGGER;
+ if (WARN_ON(!iwl_fw_ini_trigger_on(fwrt, id)))
+ return -EINVAL;
- active = &fwrt->dump.active_trigs[id];
+ if (test_and_set_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status))
+ return -EBUSY;
- if (WARN_ON(!active->active))
+ if (!iwl_fw_ini_trigger_on(fwrt, id)) {
+ IWL_WARN(fwrt, "WRT: Trigger %d is not active, aborting dump\n",
+ id);
return -EINVAL;
+ }
+ active = &fwrt->dump.active_trigs[id];
delay = le32_to_cpu(active->trig->dump_delay);
occur = le32_to_cpu(active->trig->occurrences);
if (!occur)
return 0;
+ active->trig->occurrences = cpu_to_le32(--occur);
+
if (le32_to_cpu(active->trig->force_restart)) {
- IWL_WARN(fwrt, "Force restart: trigger %d fired.\n", id);
+ IWL_WARN(fwrt, "WRT: force restart: trigger %d fired.\n", id);
iwl_force_nmi(fwrt->trans);
return 0;
}
- desc = kzalloc(sizeof(*desc) + len, GFP_ATOMIC);
- if (!desc)
- return -ENOMEM;
+ if (test_and_set_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status))
+ return -EBUSY;
- active->trig->occurrences = cpu_to_le32(--occur);
+ fwrt->dump.ini_trig_id = id;
- desc->len = len;
- desc->trig_desc.type = cpu_to_le32(id);
- memcpy(desc->trig_desc.data, str, len);
+ IWL_WARN(fwrt, "WRT: collecting data: ini trigger %d fired.\n", id);
+
+ schedule_delayed_work(&fwrt->dump.wk, usecs_to_jiffies(delay));
- return iwl_fw_dbg_collect_desc(fwrt, desc, true, delay);
+ return 0;
}
-IWL_EXPORT_SYMBOL(iwl_fw_dbg_collect);
+IWL_EXPORT_SYMBOL(_iwl_fw_dbg_ini_collect);
+
+int iwl_fw_dbg_ini_collect(struct iwl_fw_runtime *fwrt, u32 legacy_trigger_id)
+{
+ int id;
+
+ switch (legacy_trigger_id) {
+ case FW_DBG_TRIGGER_FW_ASSERT:
+ case FW_DBG_TRIGGER_ALIVE_TIMEOUT:
+ case FW_DBG_TRIGGER_DRIVER:
+ id = IWL_FW_TRIGGER_ID_FW_ASSERT;
+ break;
+ case FW_DBG_TRIGGER_USER:
+ id = IWL_FW_TRIGGER_ID_USER_TRIGGER;
+ break;
+ default:
+ return -EIO;
+ }
+
+ return _iwl_fw_dbg_ini_collect(fwrt, id);
+}
+IWL_EXPORT_SYMBOL(iwl_fw_dbg_ini_collect);
int iwl_fw_dbg_collect_trig(struct iwl_fw_runtime *fwrt,
struct iwl_fw_dbg_trigger_tlv *trigger,
@@ -2064,8 +2210,8 @@ int iwl_fw_dbg_collect_trig(struct iwl_fw_runtime *fwrt,
len = strlen(buf) + 1;
}
- ret = _iwl_fw_dbg_collect(fwrt, le32_to_cpu(trigger->id), buf, len,
- trigger);
+ ret = iwl_fw_dbg_collect(fwrt, le32_to_cpu(trigger->id), buf, len,
+ trigger);
if (ret)
return ret;
@@ -2139,9 +2285,20 @@ void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt)
return;
}
+ /* there's no point in fw dump if the bus is dead */
+ if (test_bit(STATUS_TRANS_DEAD, &fwrt->trans->status)) {
+ IWL_ERR(fwrt, "Skip fw error dump since bus is dead\n");
+ return;
+ }
+
iwl_fw_dbg_stop_recording(fwrt, &params);
- iwl_fw_error_dump(fwrt);
+ IWL_DEBUG_FW_INFO(fwrt, "WRT: data collection start\n");
+ if (fwrt->trans->ini_valid)
+ iwl_fw_error_ini_dump(fwrt);
+ else
+ iwl_fw_error_dump(fwrt);
+ IWL_DEBUG_FW_INFO(fwrt, "WRT: data collection done\n");
/* start recording again if the firmware is not crashed */
if (!test_bit(STATUS_FW_ERROR, &fwrt->trans->status) &&
@@ -2211,12 +2368,14 @@ iwl_fw_dbg_buffer_allocation(struct iwl_fw_runtime *fwrt, u32 size)
if (!virtual_addr)
IWL_ERR(fwrt, "Failed to allocate debug memory\n");
+ IWL_DEBUG_FW(trans,
+ "Allocated DRAM buffer[%d], size=0x%x\n",
+ trans->num_blocks, size);
+
trans->fw_mon[trans->num_blocks].block = virtual_addr;
trans->fw_mon[trans->num_blocks].physical = phys_addr;
trans->fw_mon[trans->num_blocks].size = size;
trans->num_blocks++;
-
- IWL_DEBUG_FW(trans, "Allocated debug block of size %d\n", size);
}
static void iwl_fw_dbg_buffer_apply(struct iwl_fw_runtime *fwrt,
@@ -2239,11 +2398,15 @@ static void iwl_fw_dbg_buffer_apply(struct iwl_fw_runtime *fwrt,
if (buf_location == IWL_FW_INI_LOCATION_SRAM_PATH) {
if (!WARN(pnt != IWL_FW_INI_APPLY_EARLY,
- "Invalid apply point %d for SMEM buffer allocation",
- pnt))
+ "WRT: Invalid apply point %d for SMEM buffer allocation, aborting\n",
+ pnt)) {
+ IWL_DEBUG_FW(trans,
+ "WRT: applying SMEM buffer destination\n");
+
/* set sram monitor by enabling bit 7 */
iwl_set_bit(fwrt->trans, CSR_HW_IF_CONFIG_REG,
CSR_HW_IF_CONFIG_REG_BIT_MONITOR_SRAM);
+ }
return;
}
@@ -2262,6 +2425,9 @@ static void iwl_fw_dbg_buffer_apply(struct iwl_fw_runtime *fwrt,
if (trans->num_blocks == 1)
return;
+ IWL_DEBUG_FW(trans,
+ "WRT: applying DRAM buffer[%d] destination\n", block_idx);
+
cmd->num_frags = cpu_to_le32(1);
cmd->fragments[0].address =
cpu_to_le64(trans->fw_mon[block_idx].physical);
@@ -2273,7 +2439,8 @@ static void iwl_fw_dbg_buffer_apply(struct iwl_fw_runtime *fwrt,
}
static void iwl_fw_dbg_send_hcmd(struct iwl_fw_runtime *fwrt,
- struct iwl_ucode_tlv *tlv)
+ struct iwl_ucode_tlv *tlv,
+ bool ext)
{
struct iwl_fw_ini_hcmd_tlv *hcmd_tlv = (void *)&tlv->data[0];
struct iwl_fw_ini_hcmd *data = &hcmd_tlv->hcmd;
@@ -2285,6 +2452,14 @@ static void iwl_fw_dbg_send_hcmd(struct iwl_fw_runtime *fwrt,
.data = { data->data, },
};
+ /* currently the driver supports always on domain only */
+ if (le32_to_cpu(hcmd_tlv->domain) != IWL_FW_INI_DBG_DOMAIN_ALWAYS_ON)
+ return;
+
+ IWL_DEBUG_FW(fwrt,
+ "WRT: ext=%d. Sending host command id=0x%x, group=0x%x\n",
+ ext, data->id, data->group);
+
iwl_trans_send_cmd(fwrt->trans, &hcmd);
}
@@ -2294,24 +2469,32 @@ static void iwl_fw_dbg_update_regions(struct iwl_fw_runtime *fwrt,
{
void *iter = (void *)tlv->region_config;
int i, size = le32_to_cpu(tlv->num_regions);
+ const char *err_st =
+ "WRT: ext=%d. Invalid region %s %d for apply point %d\n";
for (i = 0; i < size; i++) {
struct iwl_fw_ini_region_cfg *reg = iter, **active;
int id = le32_to_cpu(reg->region_id);
u32 type = le32_to_cpu(reg->region_type);
- if (WARN(id >= ARRAY_SIZE(fwrt->dump.active_regs),
- "Invalid region id %d for apply point %d\n", id, pnt))
+ if (WARN(id >= ARRAY_SIZE(fwrt->dump.active_regs), err_st, ext,
+ "id", id, pnt))
+ break;
+
+ if (WARN(type == 0 || type >= IWL_FW_INI_REGION_NUM, err_st,
+ ext, "type", type, pnt))
break;
active = &fwrt->dump.active_regs[id];
if (*active)
- IWL_WARN(fwrt->trans, "region TLV %d override\n", id);
+ IWL_WARN(fwrt->trans,
+ "WRT: ext=%d. Region id %d override\n",
+ ext, id);
IWL_DEBUG_FW(fwrt,
- "%s: apply point %d, activating region ID %d\n",
- __func__, pnt, id);
+ "WRT: ext=%d. Activating region id %d\n",
+ ext, id);
*active = reg;
@@ -2319,7 +2502,15 @@ static void iwl_fw_dbg_update_regions(struct iwl_fw_runtime *fwrt,
type == IWL_FW_INI_REGION_RXF)
iter += le32_to_cpu(reg->fifos.num_of_registers) *
sizeof(__le32);
- else if (type != IWL_FW_INI_REGION_DRAM_BUFFER)
+ else if (type == IWL_FW_INI_REGION_DEVICE_MEMORY ||
+ type == IWL_FW_INI_REGION_PERIPHERY_MAC ||
+ type == IWL_FW_INI_REGION_PERIPHERY_PHY ||
+ type == IWL_FW_INI_REGION_PERIPHERY_AUX ||
+ type == IWL_FW_INI_REGION_INTERNAL_BUFFER ||
+ type == IWL_FW_INI_REGION_PAGING ||
+ type == IWL_FW_INI_REGION_CSR ||
+ type == IWL_FW_INI_REGION_LMAC_ERROR_TABLE ||
+ type == IWL_FW_INI_REGION_UMAC_ERROR_TABLE)
iter += le32_to_cpu(reg->internal.num_of_ranges) *
sizeof(__le32);
@@ -2338,7 +2529,8 @@ static int iwl_fw_dbg_trig_realloc(struct iwl_fw_runtime *fwrt,
ptr = krealloc(active->trig, size, GFP_KERNEL);
if (!ptr) {
- IWL_ERR(fwrt, "Failed to allocate memory for trigger %d\n", id);
+ IWL_ERR(fwrt, "WRT: Failed to allocate memory for trigger %d\n",
+ id);
return -ENOMEM;
}
active->trig = ptr;
@@ -2362,7 +2554,9 @@ static void iwl_fw_dbg_update_triggers(struct iwl_fw_runtime *fwrt,
u32 trig_regs_size = le32_to_cpu(trig->num_regions) *
sizeof(__le32);
- if (WARN_ON(id >= ARRAY_SIZE(fwrt->dump.active_trigs)))
+ if (WARN(id >= ARRAY_SIZE(fwrt->dump.active_trigs),
+ "WRT: ext=%d. Invalid trigger id %d for apply point %d\n",
+ ext, id, apply_point))
break;
active = &fwrt->dump.active_trigs[id];
@@ -2370,6 +2564,10 @@ static void iwl_fw_dbg_update_triggers(struct iwl_fw_runtime *fwrt,
if (!active->active) {
size_t trig_size = sizeof(*trig) + trig_regs_size;
+ IWL_DEBUG_FW(fwrt,
+ "WRT: ext=%d. Activating trigger %d\n",
+ ext, id);
+
if (iwl_fw_dbg_trig_realloc(fwrt, active, id,
trig_size))
goto next;
@@ -2388,8 +2586,16 @@ static void iwl_fw_dbg_update_triggers(struct iwl_fw_runtime *fwrt,
int mem_to_add = trig_regs_size;
if (region_override) {
+ IWL_DEBUG_FW(fwrt,
+ "WRT: ext=%d. Trigger %d regions override\n",
+ ext, id);
+
mem_to_add -= active_regs * sizeof(__le32);
} else {
+ IWL_DEBUG_FW(fwrt,
+ "WRT: ext=%d. Trigger %d regions appending\n",
+ ext, id);
+
offset += active_regs;
new_regs += active_regs;
}
@@ -2398,8 +2604,13 @@ static void iwl_fw_dbg_update_triggers(struct iwl_fw_runtime *fwrt,
active->size + mem_to_add))
goto next;
- if (conf_override)
+ if (conf_override) {
+ IWL_DEBUG_FW(fwrt,
+ "WRT: ext=%d. Trigger %d configuration override\n",
+ ext, id);
+
memcpy(active->trig, trig, sizeof(*trig));
+ }
memcpy(active->trig->data + offset, trig->data,
trig_regs_size);
@@ -2411,6 +2622,20 @@ static void iwl_fw_dbg_update_triggers(struct iwl_fw_runtime *fwrt,
active->trig->occurrences = cpu_to_le32(-1);
active->active = true;
+
+ if (id == IWL_FW_TRIGGER_ID_PERIODIC_TRIGGER) {
+ u32 collect_interval = le32_to_cpu(trig->trigger_data);
+
+ /* the minimum allowed interval is 50ms */
+ if (collect_interval < 50) {
+ collect_interval = 50;
+ trig->trigger_data =
+ cpu_to_le32(collect_interval);
+ }
+
+ mod_timer(&fwrt->dump.periodic_trig,
+ jiffies + msecs_to_jiffies(collect_interval));
+ }
next:
iter += sizeof(*trig) + trig_regs_size;
@@ -2440,11 +2665,11 @@ static void _iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt,
case IWL_UCODE_TLV_TYPE_HCMD:
if (pnt < IWL_FW_INI_APPLY_AFTER_ALIVE) {
IWL_ERR(fwrt,
- "Invalid apply point %x for host command\n",
- pnt);
+ "WRT: ext=%d. Invalid apply point %d for host command\n",
+ ext, pnt);
goto next;
}
- iwl_fw_dbg_send_hcmd(fwrt, tlv);
+ iwl_fw_dbg_send_hcmd(fwrt, tlv, ext);
break;
case IWL_UCODE_TLV_TYPE_REGIONS:
iwl_fw_dbg_update_regions(fwrt, ini_tlv, ext, pnt);
@@ -2455,7 +2680,9 @@ static void _iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt,
case IWL_UCODE_TLV_TYPE_DEBUG_FLOW:
break;
default:
- WARN_ONCE(1, "Invalid TLV %x for apply point\n", type);
+ WARN_ONCE(1,
+ "WRT: ext=%d. Invalid TLV 0x%x for apply point\n",
+ ext, type);
break;
}
next:
@@ -2469,6 +2696,8 @@ void iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt,
void *data = &fwrt->trans->apply_points[apply_point];
int i;
+ IWL_DEBUG_FW(fwrt, "WRT: enabling apply point %d\n", apply_point);
+
if (apply_point == IWL_FW_INI_APPLY_EARLY) {
for (i = 0; i < IWL_FW_INI_MAX_REGION_ID; i++)
fwrt->dump.active_regs[i] = NULL;
@@ -2487,8 +2716,34 @@ IWL_EXPORT_SYMBOL(iwl_fw_dbg_apply_point);
void iwl_fwrt_stop_device(struct iwl_fw_runtime *fwrt)
{
+ del_timer(&fwrt->dump.periodic_trig);
iwl_fw_dbg_collect_sync(fwrt);
iwl_trans_stop_device(fwrt->trans);
}
IWL_EXPORT_SYMBOL(iwl_fwrt_stop_device);
+
+void iwl_fw_dbg_periodic_trig_handler(struct timer_list *t)
+{
+ struct iwl_fw_runtime *fwrt;
+ enum iwl_fw_ini_trigger_id id = IWL_FW_TRIGGER_ID_PERIODIC_TRIGGER;
+ int ret;
+ typeof(fwrt->dump) *dump_ptr = container_of(t, typeof(fwrt->dump),
+ periodic_trig);
+
+ fwrt = container_of(dump_ptr, typeof(*fwrt), dump);
+
+ ret = _iwl_fw_dbg_ini_collect(fwrt, id);
+ if (!ret || ret == -EBUSY) {
+ struct iwl_fw_ini_trigger *trig =
+ fwrt->dump.active_trigs[id].trig;
+ u32 occur = le32_to_cpu(trig->occurrences);
+ u32 collect_interval = le32_to_cpu(trig->trigger_data);
+
+ if (!occur)
+ return;
+
+ mod_timer(&fwrt->dump.periodic_trig,
+ jiffies + msecs_to_jiffies(collect_interval));
+ }
+}
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h
index a199056234d3..2a9e560a906b 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h
@@ -108,18 +108,17 @@ static inline void iwl_fw_free_dump_desc(struct iwl_fw_runtime *fwrt)
fwrt->dump.umac_err_id = 0;
}
-void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt);
int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt,
const struct iwl_fw_dump_desc *desc,
bool monitor_only, unsigned int delay);
int iwl_fw_dbg_error_collect(struct iwl_fw_runtime *fwrt,
enum iwl_fw_dbg_trigger trig_type);
-int _iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt,
- enum iwl_fw_dbg_trigger trig,
- const char *str, size_t len,
- struct iwl_fw_dbg_trigger_tlv *trigger);
+int _iwl_fw_dbg_ini_collect(struct iwl_fw_runtime *fwrt,
+ enum iwl_fw_ini_trigger_id id);
+int iwl_fw_dbg_ini_collect(struct iwl_fw_runtime *fwrt, u32 legacy_trigger_id);
int iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt,
- u32 id, const char *str, size_t len);
+ enum iwl_fw_dbg_trigger trig, const char *str,
+ size_t len, struct iwl_fw_dbg_trigger_tlv *trigger);
int iwl_fw_dbg_collect_trig(struct iwl_fw_runtime *fwrt,
struct iwl_fw_dbg_trigger_tlv *trigger,
const char *fmt, ...) __printf(3, 4);
@@ -229,10 +228,8 @@ iwl_fw_ini_trigger_on(struct iwl_fw_runtime *fwrt,
struct iwl_fw_ini_trigger *trig;
u32 usec;
-
-
- if (!fwrt->trans->ini_valid || id >= IWL_FW_TRIGGER_ID_NUM ||
- !fwrt->dump.active_trigs[id].active)
+ if (!fwrt->trans->ini_valid || id == IWL_FW_TRIGGER_ID_INVALID ||
+ id >= IWL_FW_TRIGGER_ID_NUM || !fwrt->dump.active_trigs[id].active)
return false;
trig = fwrt->dump.active_trigs[id].trig;
@@ -388,11 +385,13 @@ void iwl_fw_dbg_read_d3_debug_data(struct iwl_fw_runtime *fwrt);
static inline void iwl_fw_flush_dump(struct iwl_fw_runtime *fwrt)
{
+ del_timer(&fwrt->dump.periodic_trig);
flush_delayed_work(&fwrt->dump.wk);
}
static inline void iwl_fw_cancel_dump(struct iwl_fw_runtime *fwrt)
{
+ del_timer(&fwrt->dump.periodic_trig);
cancel_delayed_work_sync(&fwrt->dump.wk);
}
@@ -461,4 +460,15 @@ static inline void iwl_fw_umac_set_alive_err_table(struct iwl_trans *trans,
/* This bit is used to differentiate the legacy dump from the ini dump */
#define INI_DUMP_BIT BIT(31)
+static inline void iwl_fw_error_collect(struct iwl_fw_runtime *fwrt)
+{
+ if (fwrt->trans->ini_valid && fwrt->trans->hw_error) {
+ _iwl_fw_dbg_ini_collect(fwrt, IWL_FW_TRIGGER_ID_FW_HW_ERROR);
+ fwrt->trans->hw_error = false;
+ } else {
+ iwl_fw_dbg_collect_desc(fwrt, &iwl_dump_desc_assert, false, 0);
+ }
+}
+
+void iwl_fw_dbg_periodic_trig_handler(struct timer_list *t);
#endif /* __iwl_fw_dbg_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h
index 9b5077bd46c3..0feff4c33e39 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h
@@ -184,7 +184,7 @@ enum iwl_fw_error_dump_family {
/**
* struct iwl_fw_error_dump_info - info on the device / firmware
- * @device_family: the family of the device (7 / 8)
+ * @hw_type: the type of the device
* @hw_step: the step of the device
* @fw_human_readable: human readable FW version
* @dev_human_readable: name of the device
@@ -196,7 +196,7 @@ enum iwl_fw_error_dump_family {
* if the dump collection was not initiated by an assert, the value is 0
*/
struct iwl_fw_error_dump_info {
- __le32 device_family;
+ __le32 hw_type;
__le32 hw_step;
u8 fw_human_readable[FW_VER_HUMAN_READABLE_SZ];
u8 dev_human_readable[64];
@@ -211,6 +211,9 @@ struct iwl_fw_error_dump_info {
* @fw_mon_wr_ptr: the position of the write pointer in the cyclic buffer
* @fw_mon_base_ptr: base pointer of the data
* @fw_mon_cycle_cnt: number of wraparounds
+ * @fw_mon_base_high_ptr: used in AX210 devices, the base adderss is 64 bit
+ * so fw_mon_base_ptr holds LSB 32 bits and fw_mon_base_high_ptr hold
+ * MSB 32 bits
* @reserved: for future use
* @data: captured data
*/
@@ -218,7 +221,8 @@ struct iwl_fw_error_dump_fw_mon {
__le32 fw_mon_wr_ptr;
__le32 fw_mon_base_ptr;
__le32 fw_mon_cycle_cnt;
- __le32 reserved[3];
+ __le32 fw_mon_base_high_ptr;
+ __le32 reserved[2];
u8 data[];
} __packed;
@@ -274,25 +278,33 @@ struct iwl_fw_error_dump_mem {
u8 data[];
};
+#define IWL_INI_DUMP_MEM_VER 1
+#define IWL_INI_DUMP_MONITOR_VER 1
+#define IWL_INI_DUMP_FIFO_VER 1
+
/**
* struct iwl_fw_ini_error_dump_range - range of memory
- * @start_addr: the start address of this range
* @range_data_size: the size of this range, in bytes
+ * @start_addr: the start address of this range
* @data: the actual memory
*/
struct iwl_fw_ini_error_dump_range {
- __le32 start_addr;
__le32 range_data_size;
+ __le64 start_addr;
__le32 data[];
} __packed;
/**
* struct iwl_fw_ini_error_dump_header - ini region dump header
+ * @version: dump version
+ * @region_id: id of the region
* @num_of_ranges: number of ranges in this region
* @name_len: number of bytes allocated to the name string of this region
* @name: name of the region
*/
struct iwl_fw_ini_error_dump_header {
+ __le32 version;
+ __le32 region_id;
__le32 num_of_ranges;
__le32 name_len;
u8 name[IWL_FW_INI_MAX_NAME];
@@ -312,12 +324,23 @@ struct iwl_fw_ini_error_dump {
#define IWL_RXF_UMAC_BIT BIT(31)
/**
+ * struct iwl_fw_ini_error_dump_register - ini register dump
+ * @addr: address of the register
+ * @data: data of the register
+ */
+struct iwl_fw_ini_error_dump_register {
+ __le32 addr;
+ __le32 data;
+} __packed;
+
+/**
* struct iwl_fw_ini_fifo_error_dump_range - ini fifo range dump
* @fifo_num: the fifo num. In case of rxf and umac rxf, set BIT(31) to
* distinguish between lmac and umac
* @num_of_registers: num of registers to dump, dword size each
- * @range_data_size: the size of the registers and fifo data
- * @data: fifo data
+ * @range_data_size: the size of the data
+ * @data: consist of
+ * num_of_registers * (register address + register value) + fifo data
*/
struct iwl_fw_ini_fifo_error_dump_range {
__le32 fifo_num;
@@ -351,13 +374,13 @@ struct iwl_fw_error_dump_rb {
};
/**
- * struct iwl_fw_ini_monitor_dram_dump - ini dram monitor dump
+ * struct iwl_fw_ini_monitor_dump - ini monitor dump
* @header - header of the region
- * @write_ptr - write pointer position in the dram
+ * @write_ptr - write pointer position in the buffer
* @cycle_cnt - cycles count
* @ranges - the memory ranges of this this region
*/
-struct iwl_fw_ini_monitor_dram_dump {
+struct iwl_fw_ini_monitor_dump {
struct iwl_fw_ini_error_dump_header header;
__le32 write_ptr;
__le32 cycle_cnt;
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/file.h b/drivers/net/wireless/intel/iwlwifi/fw/file.h
index e06407dc088b..de9243d30135 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/file.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/file.h
@@ -142,12 +142,14 @@ enum iwl_ucode_tlv_type {
IWL_UCODE_TLV_FW_DBG_DEST = 38,
IWL_UCODE_TLV_FW_DBG_CONF = 39,
IWL_UCODE_TLV_FW_DBG_TRIGGER = 40,
+ IWL_UCODE_TLV_CMD_VERSIONS = 48,
IWL_UCODE_TLV_FW_GSCAN_CAPA = 50,
IWL_UCODE_TLV_FW_MEM_SEG = 51,
IWL_UCODE_TLV_IML = 52,
IWL_UCODE_TLV_UMAC_DEBUG_ADDRS = 54,
IWL_UCODE_TLV_LMAC_DEBUG_ADDRS = 55,
IWL_UCODE_TLV_FW_RECOVERY_INFO = 57,
+ IWL_UCODE_TLV_FW_FSEQ_VERSION = 60,
IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION = IWL_UCODE_INI_TLV_GROUP + 0x1,
IWL_UCODE_TLV_DEBUG_BASE = IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION,
@@ -275,8 +277,15 @@ typedef unsigned int __bitwise iwl_ucode_tlv_api_t;
* version of the beacon notification.
* @IWL_UCODE_TLV_API_BEACON_FILTER_V4: This ucode supports v4 of
* BEACON_FILTER_CONFIG_API_S_VER_4.
+ * @IWL_UCODE_TLV_API_REGULATORY_NVM_INFO: This ucode supports v4 of
+ * REGULATORY_NVM_GET_INFO_RSP_API_S.
* @IWL_UCODE_TLV_API_FTM_NEW_RANGE_REQ: This ucode supports v7 of
* LOCATION_RANGE_REQ_CMD_API_S and v6 of LOCATION_RANGE_RESP_NTFY_API_S.
+ * @IWL_UCODE_TLV_API_SCAN_OFFLOAD_CHANS: This ucode supports v2 of
+ * SCAN_OFFLOAD_PROFILE_MATCH_RESULTS_S and v3 of
+ * SCAN_OFFLOAD_PROFILES_QUERY_RSP_S.
+ * @IWL_UCODE_TLV_API_MBSSID_HE: This ucode supports v2 of
+ * STA_CONTEXT_DOT11AX_API_S
*
* @NUM_IWL_UCODE_TLV_API: number of bits used
*/
@@ -303,7 +312,12 @@ enum iwl_ucode_tlv_api {
IWL_UCODE_TLV_API_REDUCE_TX_POWER = (__force iwl_ucode_tlv_api_t)45,
IWL_UCODE_TLV_API_SHORT_BEACON_NOTIF = (__force iwl_ucode_tlv_api_t)46,
IWL_UCODE_TLV_API_BEACON_FILTER_V4 = (__force iwl_ucode_tlv_api_t)47,
+ IWL_UCODE_TLV_API_REGULATORY_NVM_INFO = (__force iwl_ucode_tlv_api_t)48,
IWL_UCODE_TLV_API_FTM_NEW_RANGE_REQ = (__force iwl_ucode_tlv_api_t)49,
+ IWL_UCODE_TLV_API_SCAN_OFFLOAD_CHANS = (__force iwl_ucode_tlv_api_t)50,
+ IWL_UCODE_TLV_API_MBSSID_HE = (__force iwl_ucode_tlv_api_t)52,
+ IWL_UCODE_TLV_API_WOWLAN_TCP_SYN_WAKE = (__force iwl_ucode_tlv_api_t)53,
+ IWL_UCODE_TLV_API_FTM_RTT_ACCURACY = (__force iwl_ucode_tlv_api_t)54,
NUM_IWL_UCODE_TLV_API
#ifdef __CHECKER__
@@ -353,6 +367,7 @@ typedef unsigned int __bitwise iwl_ucode_tlv_capa_t;
* IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD: firmware supports CSA command
* @IWL_UCODE_TLV_CAPA_ULTRA_HB_CHANNELS: firmware supports ultra high band
* (6 GHz).
+ * @IWL_UCODE_TLV_CAPA_CS_MODIFY: firmware supports modify action CSA command
* @IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE: extended DTS measurement
* @IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS: supports short PM timeouts
* @IWL_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT: supports bt-coex Multi-priority LUT
@@ -423,6 +438,7 @@ enum iwl_ucode_tlv_capa {
IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD = (__force iwl_ucode_tlv_capa_t)46,
IWL_UCODE_TLV_CAPA_ULTRA_HB_CHANNELS = (__force iwl_ucode_tlv_capa_t)48,
IWL_UCODE_TLV_CAPA_FTM_CALIBRATED = (__force iwl_ucode_tlv_capa_t)47,
+ IWL_UCODE_TLV_CAPA_CS_MODIFY = (__force iwl_ucode_tlv_capa_t)49,
/* set 2 */
IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE = (__force iwl_ucode_tlv_capa_t)64,
@@ -928,4 +944,20 @@ struct iwl_fw_dbg_conf_tlv {
struct iwl_fw_dbg_conf_hcmd hcmd;
} __packed;
+#define IWL_FW_CMD_VER_UNKNOWN 99
+
+/**
+ * struct iwl_fw_cmd_version - firmware command version entry
+ * @cmd: command ID
+ * @group: group ID
+ * @cmd_ver: command version
+ * @notif_ver: notification version
+ */
+struct iwl_fw_cmd_version {
+ u8 cmd;
+ u8 group;
+ u8 cmd_ver;
+ u8 notif_ver;
+} __packed;
+
#endif /* __iwl_fw_file_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/img.h b/drivers/net/wireless/intel/iwlwifi/fw/img.h
index f4c5a4d73206..18ca5f152be6 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/img.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/img.h
@@ -8,7 +8,7 @@
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,7 +31,7 @@
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -109,6 +109,9 @@ struct iwl_ucode_capabilities {
u32 error_log_size;
unsigned long _api[BITS_TO_LONGS(NUM_IWL_UCODE_TLV_API)];
unsigned long _capa[BITS_TO_LONGS(NUM_IWL_UCODE_TLV_CAPA)];
+
+ const struct iwl_fw_cmd_version *cmd_versions;
+ u32 n_cmd_versions;
};
static inline bool
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/init.c b/drivers/net/wireless/intel/iwlwifi/fw/init.c
index 12310e3d2fc5..4435c0ce3013 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/init.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/init.c
@@ -76,6 +76,8 @@ void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans,
fwrt->ops_ctx = ops_ctx;
INIT_DELAYED_WORK(&fwrt->dump.wk, iwl_fw_error_dump_wk);
iwl_fwrt_dbgfs_register(fwrt, dbgfs_dir);
+ timer_setup(&fwrt->dump.periodic_trig,
+ iwl_fw_dbg_periodic_trig_handler, 0);
}
IWL_EXPORT_SYMBOL(iwl_fw_runtime_init);
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h
index a5fe1a8ca426..a6402a0b3854 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h
@@ -145,6 +145,8 @@ struct iwl_fw_runtime {
u32 lmac_err_id[MAX_NUM_LMAC];
u32 umac_err_id;
void *fifo_iter;
+ enum iwl_fw_ini_trigger_id ini_trig_id;
+ struct timer_list periodic_trig;
} dump;
#ifdef CONFIG_IWLWIFI_DEBUGFS
struct {
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h
index 93070848280a..f3e69edf8907 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h
@@ -383,6 +383,9 @@ struct iwl_csr_params {
* @bisr_workaround: BISR hardware workaround (for 22260 series devices)
* @min_txq_size: minimum number of slots required in a TX queue
* @umac_prph_offset: offset to add to UMAC periphery address
+ * @uhb_supported: ultra high band channels supported
+ * @min_256_ba_txq_size: minimum number of slots required in a TX queue which
+ * supports 256 BA aggregation
*
* We enable the driver to be backward compatible wrt. hardware features.
* API differences in uCode shouldn't be handled here but through TLVs
@@ -433,7 +436,8 @@ struct iwl_cfg {
gen2:1,
cdb:1,
dbgc_supported:1,
- bisr_workaround:1;
+ bisr_workaround:1,
+ uhb_supported:1;
u8 valid_tx_ant;
u8 valid_rx_ant;
u8 non_shared_ant;
@@ -450,6 +454,12 @@ struct iwl_cfg {
u32 d3_debug_data_length;
u32 min_txq_size;
u32 umac_prph_offset;
+ u32 fw_mon_smem_write_ptr_addr;
+ u32 fw_mon_smem_write_ptr_msk;
+ u32 fw_mon_smem_cycle_cnt_ptr_addr;
+ u32 fw_mon_smem_cycle_cnt_ptr_msk;
+ u32 gp2_reg_addr;
+ u32 min_256_ba_txq_size;
};
extern const struct iwl_csr_params iwl_csr_v1;
@@ -568,11 +578,11 @@ extern const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_b0_f0;
extern const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_b0;
extern const struct iwl_cfg iwl9560_2ac_cfg_qnj_jf_b0;
extern const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_a0;
-extern const struct iwl_cfg iwl22560_2ax_cfg_su_cdb;
extern const struct iwl_cfg iwlax210_2ax_cfg_so_jf_a0;
extern const struct iwl_cfg iwlax210_2ax_cfg_so_hr_a0;
extern const struct iwl_cfg iwlax210_2ax_cfg_so_gf_a0;
extern const struct iwl_cfg iwlax210_2ax_cfg_ty_gf_a0;
+extern const struct iwl_cfg iwlax210_2ax_cfg_so_gf4_a0;
#endif /* CPTCFG_IWLMVM || CPTCFG_IWLFMAC */
#endif /* __IWL_CONFIG_H__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h
index e539bc94eff7..553554846009 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h
@@ -8,7 +8,7 @@
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2016 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -30,7 +30,7 @@
*
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -290,6 +290,7 @@
/* HW REV */
#define CSR_HW_REV_DASH(_val) (((_val) & 0x0000003) >> 0)
#define CSR_HW_REV_STEP(_val) (((_val) & 0x000000C) >> 2)
+#define CSR_HW_REV_TYPE(_val) (((_val) & 0x000FFF0) >> 4)
/* HW RFID */
#define CSR_HW_RFID_FLAVOR(_val) (((_val) & 0x000000F) >> 0)
@@ -337,6 +338,7 @@ enum {
#define CSR_HW_RF_ID_TYPE_HR (0x0010A000)
#define CSR_HW_RF_ID_TYPE_HRCDB (0x00109F00)
#define CSR_HW_RF_ID_TYPE_GF (0x0010D000)
+#define CSR_HW_RF_ID_TYPE_GF4 (0x0010E000)
/* HW_RF CHIP ID */
#define CSR_HW_RF_ID_TYPE_CHIP_ID(_val) (((_val) >> 12) & 0xFFF)
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c
index c7070760a10a..ba66f7fba064 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c
@@ -5,7 +5,7 @@
*
* GPL LICENSE SUMMARY
*
- * Copyright (C) 2018 Intel Corporation
+ * Copyright (C) 2018 - 2019 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -28,7 +28,7 @@
*
* BSD LICENSE
*
- * Copyright (C) 2018 Intel Corporation
+ * Copyright (C) 2018 - 2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -73,6 +73,9 @@ void iwl_fw_dbg_copy_tlv(struct iwl_trans *trans, struct iwl_ucode_tlv *tlv,
int copy_size = le32_to_cpu(tlv->length) + sizeof(*tlv);
int offset_size = copy_size;
+ if (le32_to_cpu(header->tlv_version) != 1)
+ return;
+
if (WARN_ONCE(apply_point >= IWL_FW_INI_APPLY_NUM,
"Invalid apply point id %d\n", apply_point))
return;
@@ -133,7 +136,10 @@ void iwl_alloc_dbg_tlv(struct iwl_trans *trans, size_t len, const u8 *data,
hdr = (void *)&tlv->data[0];
apply = le32_to_cpu(hdr->apply_point);
- IWL_DEBUG_FW(trans, "Read TLV %x, apply point %d\n",
+ if (le32_to_cpu(hdr->tlv_version) != 1)
+ continue;
+
+ IWL_DEBUG_FW(trans, "WRT: read TLV 0x%x, apply point %d\n",
le32_to_cpu(tlv->type), apply);
if (WARN_ON(apply >= IWL_FW_INI_APPLY_NUM))
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-debug.h b/drivers/net/wireless/intel/iwlwifi/iwl-debug.h
index 655ff5694560..d3ba6a1422ee 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-debug.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-debug.h
@@ -218,5 +218,7 @@ do { \
#define IWL_DEBUG_TPT(p, f, a...) IWL_DEBUG(p, IWL_DL_TPT, f, ## a)
#define IWL_DEBUG_RPM(p, f, a...) IWL_DEBUG(p, IWL_DL_RPM, f, ## a)
#define IWL_DEBUG_LAR(p, f, a...) IWL_DEBUG(p, IWL_DL_LAR, f, ## a)
+#define IWL_DEBUG_FW_INFO(p, f, a...) \
+ IWL_DEBUG(p, IWL_DL_INFO | IWL_DL_FW, f, ## a)
#endif
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
index 689a65b11cc3..852d3cbfc719 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
@@ -179,6 +179,7 @@ static void iwl_dealloc_ucode(struct iwl_drv *drv)
kfree(drv->fw.dbg.trigger_tlv[i]);
kfree(drv->fw.dbg.mem_tlv);
kfree(drv->fw.iml);
+ kfree(drv->fw.ucode_capa.cmd_versions);
for (i = 0; i < IWL_UCODE_TYPE_MAX; i++)
iwl_free_fw_img(drv, drv->fw.img + i);
@@ -252,8 +253,8 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first)
snprintf(drv->firmware_name, sizeof(drv->firmware_name), "%s%s.ucode",
cfg->fw_name_pre, tag);
- IWL_DEBUG_INFO(drv, "attempting to load firmware '%s'\n",
- drv->firmware_name);
+ IWL_DEBUG_FW_INFO(drv, "attempting to load firmware '%s'\n",
+ drv->firmware_name);
return request_firmware_nowait(THIS_MODULE, 1, drv->firmware_name,
drv->trans->dev,
@@ -1144,6 +1145,23 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
if (iwlwifi_mod_params.enable_ini)
iwl_fw_dbg_copy_tlv(drv->trans, tlv, false);
break;
+ case IWL_UCODE_TLV_CMD_VERSIONS:
+ if (tlv_len % sizeof(struct iwl_fw_cmd_version)) {
+ IWL_ERR(drv,
+ "Invalid length for command versions: %u\n",
+ tlv_len);
+ tlv_len /= sizeof(struct iwl_fw_cmd_version);
+ tlv_len *= sizeof(struct iwl_fw_cmd_version);
+ }
+ if (WARN_ON(capa->cmd_versions))
+ return -EINVAL;
+ capa->cmd_versions = kmemdup(tlv_data, tlv_len,
+ GFP_KERNEL);
+ if (!capa->cmd_versions)
+ return -ENOMEM;
+ capa->n_cmd_versions =
+ tlv_len / sizeof(struct iwl_fw_cmd_version);
+ break;
default:
IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type);
break;
@@ -1318,8 +1336,8 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
if (!ucode_raw)
goto try_again;
- IWL_DEBUG_INFO(drv, "Loaded firmware file '%s' (%zd bytes).\n",
- drv->firmware_name, ucode_raw->size);
+ IWL_DEBUG_FW_INFO(drv, "Loaded firmware file '%s' (%zd bytes).\n",
+ drv->firmware_name, ucode_raw->size);
/* Make sure that we got at least the API version number */
if (ucode_raw->size < 4) {
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
index 87d6de7efdd2..d87a6bb3e456 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
@@ -130,7 +130,7 @@ enum nvm_sku_bits {
/*
* These are the channel numbers in the order that they are stored in the NVM
*/
-static const u8 iwl_nvm_channels[] = {
+static const u16 iwl_nvm_channels[] = {
/* 2.4 GHz */
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
/* 5 GHz */
@@ -139,7 +139,7 @@ static const u8 iwl_nvm_channels[] = {
149, 153, 157, 161, 165
};
-static const u8 iwl_ext_nvm_channels[] = {
+static const u16 iwl_ext_nvm_channels[] = {
/* 2.4 GHz */
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
/* 5 GHz */
@@ -148,14 +148,27 @@ static const u8 iwl_ext_nvm_channels[] = {
149, 153, 157, 161, 165, 169, 173, 177, 181
};
+static const u16 iwl_uhb_nvm_channels[] = {
+ /* 2.4 GHz */
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ /* 5 GHz */
+ 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92,
+ 96, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144,
+ 149, 153, 157, 161, 165, 169, 173, 177, 181,
+ /* 6-7 GHz */
+ 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 237, 241,
+ 245, 249, 253, 257, 261, 265, 269, 273, 277, 281, 285, 289, 293, 297,
+ 301, 305, 309, 313, 317, 321, 325, 329, 333, 337, 341, 345, 349, 353,
+ 357, 361, 365, 369, 373, 377, 381, 385, 389, 393, 397, 401, 405, 409,
+ 413, 417, 421
+};
+
#define IWL_NVM_NUM_CHANNELS ARRAY_SIZE(iwl_nvm_channels)
#define IWL_NVM_NUM_CHANNELS_EXT ARRAY_SIZE(iwl_ext_nvm_channels)
+#define IWL_NVM_NUM_CHANNELS_UHB ARRAY_SIZE(iwl_uhb_nvm_channels)
#define NUM_2GHZ_CHANNELS 14
-#define NUM_2GHZ_CHANNELS_EXT 14
#define FIRST_2GHZ_HT_MINUS 5
#define LAST_2GHZ_HT_PLUS 9
-#define LAST_5GHZ_HT 165
-#define LAST_5GHZ_HT_FAMILY_8000 181
#define N_HW_ADDR_MASK 0xF
/* rate data (static) */
@@ -213,7 +226,7 @@ enum iwl_nvm_channel_flags {
};
static inline void iwl_nvm_print_channel_flags(struct device *dev, u32 level,
- int chan, u16 flags)
+ int chan, u32 flags)
{
#define CHECK_AND_PRINT_I(x) \
((flags & NVM_CHANNEL_##x) ? " " #x : "")
@@ -244,20 +257,16 @@ static inline void iwl_nvm_print_channel_flags(struct device *dev, u32 level,
}
static u32 iwl_get_channel_flags(u8 ch_num, int ch_idx, bool is_5ghz,
- u16 nvm_flags, const struct iwl_cfg *cfg)
+ u32 nvm_flags, const struct iwl_cfg *cfg)
{
u32 flags = IEEE80211_CHAN_NO_HT40;
- u32 last_5ghz_ht = LAST_5GHZ_HT;
-
- if (cfg->nvm_type == IWL_NVM_EXT)
- last_5ghz_ht = LAST_5GHZ_HT_FAMILY_8000;
if (!is_5ghz && (nvm_flags & NVM_CHANNEL_40MHZ)) {
if (ch_num <= LAST_2GHZ_HT_PLUS)
flags &= ~IEEE80211_CHAN_NO_HT40PLUS;
if (ch_num >= FIRST_2GHZ_HT_MINUS)
flags &= ~IEEE80211_CHAN_NO_HT40MINUS;
- } else if (ch_num <= last_5ghz_ht && (nvm_flags & NVM_CHANNEL_40MHZ)) {
+ } else if (nvm_flags & NVM_CHANNEL_40MHZ) {
if ((ch_idx - NUM_2GHZ_CHANNELS) % 2 == 0)
flags &= ~IEEE80211_CHAN_NO_HT40PLUS;
else
@@ -292,30 +301,36 @@ static u32 iwl_get_channel_flags(u8 ch_num, int ch_idx, bool is_5ghz,
static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
struct iwl_nvm_data *data,
- const __le16 * const nvm_ch_flags,
- u32 sbands_flags)
+ const void * const nvm_ch_flags,
+ u32 sbands_flags, bool v4)
{
int ch_idx;
int n_channels = 0;
struct ieee80211_channel *channel;
- u16 ch_flags;
- int num_of_ch, num_2ghz_channels;
- const u8 *nvm_chan;
-
- if (cfg->nvm_type != IWL_NVM_EXT) {
- num_of_ch = IWL_NVM_NUM_CHANNELS;
- nvm_chan = &iwl_nvm_channels[0];
- num_2ghz_channels = NUM_2GHZ_CHANNELS;
- } else {
+ u32 ch_flags;
+ int num_of_ch, num_2ghz_channels = NUM_2GHZ_CHANNELS;
+ const u16 *nvm_chan;
+
+ if (cfg->uhb_supported) {
+ num_of_ch = IWL_NVM_NUM_CHANNELS_UHB;
+ nvm_chan = iwl_uhb_nvm_channels;
+ } else if (cfg->nvm_type == IWL_NVM_EXT) {
num_of_ch = IWL_NVM_NUM_CHANNELS_EXT;
- nvm_chan = &iwl_ext_nvm_channels[0];
- num_2ghz_channels = NUM_2GHZ_CHANNELS_EXT;
+ nvm_chan = iwl_ext_nvm_channels;
+ } else {
+ num_of_ch = IWL_NVM_NUM_CHANNELS;
+ nvm_chan = iwl_nvm_channels;
}
for (ch_idx = 0; ch_idx < num_of_ch; ch_idx++) {
bool is_5ghz = (ch_idx >= num_2ghz_channels);
- ch_flags = __le16_to_cpup(nvm_ch_flags + ch_idx);
+ if (v4)
+ ch_flags =
+ __le32_to_cpup((__le32 *)nvm_ch_flags + ch_idx);
+ else
+ ch_flags =
+ __le16_to_cpup((__le16 *)nvm_ch_flags + ch_idx);
if (is_5ghz && !data->sku_cap_band_52ghz_enable)
continue;
@@ -636,12 +651,7 @@ static struct ieee80211_sband_iftype_data iwl_he_capa[] = {
static void iwl_init_he_hw_capab(struct ieee80211_supported_band *sband,
u8 tx_chains, u8 rx_chains)
{
- if (sband->band == NL80211_BAND_2GHZ ||
- sband->band == NL80211_BAND_5GHZ)
- sband->iftype_data = iwl_he_capa;
- else
- return;
-
+ sband->iftype_data = iwl_he_capa;
sband->n_iftype_data = ARRAY_SIZE(iwl_he_capa);
/* If not 2x2, we need to indicate 1x1 in the Midamble RX Max NSTS */
@@ -661,15 +671,15 @@ static void iwl_init_he_hw_capab(struct ieee80211_supported_band *sband,
static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg,
struct iwl_nvm_data *data,
- const __le16 *nvm_ch_flags, u8 tx_chains,
- u8 rx_chains, u32 sbands_flags)
+ const void *nvm_ch_flags, u8 tx_chains,
+ u8 rx_chains, u32 sbands_flags, bool v4)
{
int n_channels;
int n_used = 0;
struct ieee80211_supported_band *sband;
n_channels = iwl_init_channel_map(dev, cfg, data, nvm_ch_flags,
- sbands_flags);
+ sbands_flags, v4);
sband = &data->bands[NL80211_BAND_2GHZ];
sband->band = NL80211_BAND_2GHZ;
sband->bitrates = &iwl_cfg80211_rates[RATES_24_OFFS];
@@ -1006,22 +1016,18 @@ iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
sbands_flags |= IWL_NVM_SBANDS_FLAGS_NO_WIDE_IN_5GHZ;
iwl_init_sbands(dev, cfg, data, ch_section, tx_chains, rx_chains,
- sbands_flags);
+ sbands_flags, false);
data->calib_version = 255;
return data;
}
IWL_EXPORT_SYMBOL(iwl_parse_nvm_data);
-static u32 iwl_nvm_get_regdom_bw_flags(const u8 *nvm_chan,
+static u32 iwl_nvm_get_regdom_bw_flags(const u16 *nvm_chan,
int ch_idx, u16 nvm_flags,
const struct iwl_cfg *cfg)
{
u32 flags = NL80211_RRF_NO_HT40;
- u32 last_5ghz_ht = LAST_5GHZ_HT;
-
- if (cfg->nvm_type == IWL_NVM_EXT)
- last_5ghz_ht = LAST_5GHZ_HT_FAMILY_8000;
if (ch_idx < NUM_2GHZ_CHANNELS &&
(nvm_flags & NVM_CHANNEL_40MHZ)) {
@@ -1029,8 +1035,7 @@ static u32 iwl_nvm_get_regdom_bw_flags(const u8 *nvm_chan,
flags &= ~NL80211_RRF_NO_HT40PLUS;
if (nvm_chan[ch_idx] >= FIRST_2GHZ_HT_MINUS)
flags &= ~NL80211_RRF_NO_HT40MINUS;
- } else if (nvm_chan[ch_idx] <= last_5ghz_ht &&
- (nvm_flags & NVM_CHANNEL_40MHZ)) {
+ } else if (nvm_flags & NVM_CHANNEL_40MHZ) {
if ((ch_idx - NUM_2GHZ_CHANNELS) % 2 == 0)
flags &= ~NL80211_RRF_NO_HT40PLUS;
else
@@ -1074,18 +1079,26 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
int ch_idx;
u16 ch_flags;
u32 reg_rule_flags, prev_reg_rule_flags = 0;
- const u8 *nvm_chan = cfg->nvm_type == IWL_NVM_EXT ?
- iwl_ext_nvm_channels : iwl_nvm_channels;
+ const u16 *nvm_chan;
struct ieee80211_regdomain *regd, *copy_rd;
- int size_of_regd, regd_to_copy;
struct ieee80211_reg_rule *rule;
struct regdb_ptrs *regdb_ptrs;
enum nl80211_band band;
int center_freq, prev_center_freq = 0;
int valid_rules = 0;
bool new_rule;
- int max_num_ch = cfg->nvm_type == IWL_NVM_EXT ?
- IWL_NVM_NUM_CHANNELS_EXT : IWL_NVM_NUM_CHANNELS;
+ int max_num_ch;
+
+ if (cfg->uhb_supported) {
+ max_num_ch = IWL_NVM_NUM_CHANNELS_UHB;
+ nvm_chan = iwl_uhb_nvm_channels;
+ } else if (cfg->nvm_type == IWL_NVM_EXT) {
+ max_num_ch = IWL_NVM_NUM_CHANNELS_EXT;
+ nvm_chan = iwl_ext_nvm_channels;
+ } else {
+ max_num_ch = IWL_NVM_NUM_CHANNELS;
+ nvm_chan = iwl_nvm_channels;
+ }
if (WARN_ON(num_of_ch > max_num_ch))
num_of_ch = max_num_ch;
@@ -1097,11 +1110,7 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
num_of_ch);
/* build a regdomain rule for every valid channel */
- size_of_regd =
- sizeof(struct ieee80211_regdomain) +
- num_of_ch * sizeof(struct ieee80211_reg_rule);
-
- regd = kzalloc(size_of_regd, GFP_KERNEL);
+ regd = kzalloc(struct_size(regd, reg_rules, num_of_ch), GFP_KERNEL);
if (!regd)
return ERR_PTR(-ENOMEM);
@@ -1177,14 +1186,10 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
* Narrow down regdom for unused regulatory rules to prevent hole
* between reg rules to wmm rules.
*/
- regd_to_copy = sizeof(struct ieee80211_regdomain) +
- valid_rules * sizeof(struct ieee80211_reg_rule);
-
- copy_rd = kmemdup(regd, regd_to_copy, GFP_KERNEL);
- if (!copy_rd) {
+ copy_rd = kmemdup(regd, struct_size(regd, reg_rules, valid_rules),
+ GFP_KERNEL);
+ if (!copy_rd)
copy_rd = ERR_PTR(-ENOMEM);
- goto out;
- }
out:
kfree(regdb_ptrs);
@@ -1393,7 +1398,6 @@ struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans,
const struct iwl_fw *fw)
{
struct iwl_nvm_get_info cmd = {};
- struct iwl_nvm_get_info_rsp *rsp;
struct iwl_nvm_data *nvm;
struct iwl_host_cmd hcmd = {
.flags = CMD_WANT_SKB | CMD_SEND_IN_RFKILL,
@@ -1408,12 +1412,24 @@ struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans,
bool empty_otp;
u32 mac_flags;
u32 sbands_flags = 0;
+ /*
+ * All the values in iwl_nvm_get_info_rsp v4 are the same as
+ * in v3, except for the channel profile part of the
+ * regulatory. So we can just access the new struct, with the
+ * exception of the latter.
+ */
+ struct iwl_nvm_get_info_rsp *rsp;
+ struct iwl_nvm_get_info_rsp_v3 *rsp_v3;
+ bool v4 = fw_has_api(&fw->ucode_capa,
+ IWL_UCODE_TLV_API_REGULATORY_NVM_INFO);
+ size_t rsp_size = v4 ? sizeof(*rsp) : sizeof(*rsp_v3);
+ void *channel_profile;
ret = iwl_trans_send_cmd(trans, &hcmd);
if (ret)
return ERR_PTR(ret);
- if (WARN(iwl_rx_packet_payload_len(hcmd.resp_pkt) != sizeof(*rsp),
+ if (WARN(iwl_rx_packet_payload_len(hcmd.resp_pkt) != rsp_size,
"Invalid payload len in NVM response from FW %d",
iwl_rx_packet_payload_len(hcmd.resp_pkt))) {
ret = -EINVAL;
@@ -1475,11 +1491,15 @@ struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans,
sbands_flags |= IWL_NVM_SBANDS_FLAGS_LAR;
}
+ rsp_v3 = (void *)rsp;
+ channel_profile = v4 ? (void *)rsp->regulatory.channel_profile :
+ (void *)rsp_v3->regulatory.channel_profile;
+
iwl_init_sbands(trans->dev, trans->cfg, nvm,
- rsp->regulatory.channel_profile,
+ channel_profile,
nvm->valid_tx_ant & fw->valid_tx_ant,
nvm->valid_rx_ant & fw->valid_rx_ant,
- sbands_flags);
+ sbands_flags, v4);
iwl_free_resp(&hcmd);
return nvm;
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h
index 1af9f9e1ecd4..8e6a0c363c0d 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h
@@ -368,6 +368,12 @@
#define MON_BUFF_WRPTR_VER2 (0xa03c24)
#define MON_BUFF_CYCLE_CNT_VER2 (0xa03c28)
#define MON_BUFF_SHIFT_VER2 (0x8)
+/* FW monitor familiy AX210 and on */
+#define DBGC_CUR_DBGBUF_BASE_ADDR_LSB (0xd03c20)
+#define DBGC_CUR_DBGBUF_BASE_ADDR_MSB (0xd03c24)
+#define DBGC_CUR_DBGBUF_STATUS (0xd03c1c)
+#define DBGC_DBGBUF_WRAP_AROUND (0xd03c2c)
+#define DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK (0x00ffffff)
#define MON_DMARB_RD_CTL_ADDR (0xa03c60)
#define MON_DMARB_RD_DATA_ADDR (0xa03c5c)
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
index d8690acee40c..1e4c9ef548cc 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
@@ -274,7 +274,6 @@ struct iwl_rx_cmd_buffer {
bool _page_stolen;
u32 _rx_page_order;
unsigned int truesize;
- u8 status;
};
static inline void *rxb_addr(struct iwl_rx_cmd_buffer *r)
@@ -768,6 +767,7 @@ struct iwl_self_init_dram {
* @umac_error_event_table: addr of umac error table
* @error_event_table_tlv_status: bitmap that indicates what error table
* pointers was recevied via TLV. use enum &iwl_error_event_table_status
+ * @hw_error: equals true if hw error interrupt was received from the FW
*/
struct iwl_trans {
const struct iwl_trans_ops *ops;
@@ -830,6 +830,7 @@ struct iwl_trans {
u32 lmac_error_event_table[2];
u32 umac_error_event_table;
unsigned int error_event_table_tlv_status;
+ bool hw_error;
/* pointer to trans specific struct */
/*Ensure that this pointer will always be aligned to sizeof pointer */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
index 808bc6f363d0..60f5d337f16d 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
@@ -8,7 +8,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,7 +31,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -385,10 +385,10 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw,
}
}
-static int iwl_mvm_send_patterns(struct iwl_mvm *mvm,
- struct cfg80211_wowlan *wowlan)
+static int iwl_mvm_send_patterns_v1(struct iwl_mvm *mvm,
+ struct cfg80211_wowlan *wowlan)
{
- struct iwl_wowlan_patterns_cmd *pattern_cmd;
+ struct iwl_wowlan_patterns_cmd_v1 *pattern_cmd;
struct iwl_host_cmd cmd = {
.id = WOWLAN_PATTERNS,
.dataflags[0] = IWL_HCMD_DFL_NOCOPY,
@@ -399,7 +399,7 @@ static int iwl_mvm_send_patterns(struct iwl_mvm *mvm,
return 0;
cmd.len[0] = sizeof(*pattern_cmd) +
- wowlan->n_patterns * sizeof(struct iwl_wowlan_pattern);
+ wowlan->n_patterns * sizeof(struct iwl_wowlan_pattern_v1);
pattern_cmd = kmalloc(cmd.len[0], GFP_KERNEL);
if (!pattern_cmd)
@@ -426,6 +426,50 @@ static int iwl_mvm_send_patterns(struct iwl_mvm *mvm,
return err;
}
+static int iwl_mvm_send_patterns(struct iwl_mvm *mvm,
+ struct cfg80211_wowlan *wowlan)
+{
+ struct iwl_wowlan_patterns_cmd *pattern_cmd;
+ struct iwl_host_cmd cmd = {
+ .id = WOWLAN_PATTERNS,
+ .dataflags[0] = IWL_HCMD_DFL_NOCOPY,
+ };
+ int i, err;
+
+ if (!wowlan->n_patterns)
+ return 0;
+
+ cmd.len[0] = sizeof(*pattern_cmd) +
+ wowlan->n_patterns * sizeof(struct iwl_wowlan_pattern_v2);
+
+ pattern_cmd = kmalloc(cmd.len[0], GFP_KERNEL);
+ if (!pattern_cmd)
+ return -ENOMEM;
+
+ pattern_cmd->n_patterns = cpu_to_le32(wowlan->n_patterns);
+
+ for (i = 0; i < wowlan->n_patterns; i++) {
+ int mask_len = DIV_ROUND_UP(wowlan->patterns[i].pattern_len, 8);
+
+ pattern_cmd->patterns[i].pattern_type =
+ WOWLAN_PATTERN_TYPE_BITMASK;
+
+ memcpy(&pattern_cmd->patterns[i].u.bitmask.mask,
+ wowlan->patterns[i].mask, mask_len);
+ memcpy(&pattern_cmd->patterns[i].u.bitmask.pattern,
+ wowlan->patterns[i].pattern,
+ wowlan->patterns[i].pattern_len);
+ pattern_cmd->patterns[i].u.bitmask.mask_size = mask_len;
+ pattern_cmd->patterns[i].u.bitmask.pattern_size =
+ wowlan->patterns[i].pattern_len;
+ }
+
+ cmd.data[0] = pattern_cmd;
+ err = iwl_mvm_send_cmd(mvm, &cmd);
+ kfree(pattern_cmd);
+ return err;
+}
+
static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct ieee80211_sta *ap_sta)
{
@@ -851,7 +895,11 @@ iwl_mvm_wowlan_config(struct iwl_mvm *mvm,
if (ret)
return ret;
- ret = iwl_mvm_send_patterns(mvm, wowlan);
+ if (fw_has_api(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_API_WOWLAN_TCP_SYN_WAKE))
+ ret = iwl_mvm_send_patterns(mvm, wowlan);
+ else
+ ret = iwl_mvm_send_patterns_v1(mvm, wowlan);
if (ret)
return ret;
@@ -1728,9 +1776,12 @@ void iwl_mvm_d0i3_update_keys(struct iwl_mvm *mvm,
iwl_mvm_iter_d0i3_ap_keys(mvm, vif, iwl_mvm_d3_update_keys, &gtkdata);
}
+#define ND_QUERY_BUF_LEN (sizeof(struct iwl_scan_offload_profile_match) * \
+ IWL_SCAN_MAX_PROFILES)
+
struct iwl_mvm_nd_query_results {
u32 matched_profiles;
- struct iwl_scan_offload_profile_match matches[IWL_SCAN_MAX_PROFILES];
+ u8 matches[ND_QUERY_BUF_LEN];
};
static int
@@ -1743,6 +1794,7 @@ iwl_mvm_netdetect_query_results(struct iwl_mvm *mvm,
.flags = CMD_WANT_SKB,
};
int ret, len;
+ size_t query_len, matches_len;
ret = iwl_mvm_send_cmd(mvm, &cmd);
if (ret) {
@@ -1750,8 +1802,19 @@ iwl_mvm_netdetect_query_results(struct iwl_mvm *mvm,
return ret;
}
+ if (fw_has_api(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_API_SCAN_OFFLOAD_CHANS)) {
+ query_len = sizeof(struct iwl_scan_offload_profiles_query);
+ matches_len = sizeof(struct iwl_scan_offload_profile_match) *
+ IWL_SCAN_MAX_PROFILES;
+ } else {
+ query_len = sizeof(struct iwl_scan_offload_profiles_query_v1);
+ matches_len = sizeof(struct iwl_scan_offload_profile_match_v1) *
+ IWL_SCAN_MAX_PROFILES;
+ }
+
len = iwl_rx_packet_payload_len(cmd.resp_pkt);
- if (len < sizeof(*query)) {
+ if (len < query_len) {
IWL_ERR(mvm, "Invalid scan offload profiles query response!\n");
ret = -EIO;
goto out_free_resp;
@@ -1760,7 +1823,7 @@ iwl_mvm_netdetect_query_results(struct iwl_mvm *mvm,
query = (void *)cmd.resp_pkt->data;
results->matched_profiles = le32_to_cpu(query->matched_profiles);
- memcpy(results->matches, query->matches, sizeof(results->matches));
+ memcpy(results->matches, query->matches, matches_len);
#ifdef CONFIG_IWLWIFI_DEBUGFS
mvm->last_netdetect_scans = le32_to_cpu(query->n_scans_done);
@@ -1771,6 +1834,57 @@ out_free_resp:
return ret;
}
+static int iwl_mvm_query_num_match_chans(struct iwl_mvm *mvm,
+ struct iwl_mvm_nd_query_results *query,
+ int idx)
+{
+ int n_chans = 0, i;
+
+ if (fw_has_api(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_API_SCAN_OFFLOAD_CHANS)) {
+ struct iwl_scan_offload_profile_match *matches =
+ (struct iwl_scan_offload_profile_match *)query->matches;
+
+ for (i = 0; i < SCAN_OFFLOAD_MATCHING_CHANNELS_LEN; i++)
+ n_chans += hweight8(matches[idx].matching_channels[i]);
+ } else {
+ struct iwl_scan_offload_profile_match_v1 *matches =
+ (struct iwl_scan_offload_profile_match_v1 *)query->matches;
+
+ for (i = 0; i < SCAN_OFFLOAD_MATCHING_CHANNELS_LEN_V1; i++)
+ n_chans += hweight8(matches[idx].matching_channels[i]);
+ }
+
+ return n_chans;
+}
+
+static void iwl_mvm_query_set_freqs(struct iwl_mvm *mvm,
+ struct iwl_mvm_nd_query_results *query,
+ struct cfg80211_wowlan_nd_match *match,
+ int idx)
+{
+ int i;
+
+ if (fw_has_api(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_API_SCAN_OFFLOAD_CHANS)) {
+ struct iwl_scan_offload_profile_match *matches =
+ (struct iwl_scan_offload_profile_match *)query->matches;
+
+ for (i = 0; i < SCAN_OFFLOAD_MATCHING_CHANNELS_LEN * 8; i++)
+ if (matches[idx].matching_channels[i / 8] & (BIT(i % 8)))
+ match->channels[match->n_channels++] =
+ mvm->nd_channels[i]->center_freq;
+ } else {
+ struct iwl_scan_offload_profile_match_v1 *matches =
+ (struct iwl_scan_offload_profile_match_v1 *)query->matches;
+
+ for (i = 0; i < SCAN_OFFLOAD_MATCHING_CHANNELS_LEN_V1 * 8; i++)
+ if (matches[idx].matching_channels[i / 8] & (BIT(i % 8)))
+ match->channels[match->n_channels++] =
+ mvm->nd_channels[i]->center_freq;
+ }
+}
+
static void iwl_mvm_query_netdetect_reasons(struct iwl_mvm *mvm,
struct ieee80211_vif *vif)
{
@@ -1783,7 +1897,7 @@ static void iwl_mvm_query_netdetect_reasons(struct iwl_mvm *mvm,
struct iwl_wowlan_status *fw_status;
unsigned long matched_profiles;
u32 reasons = 0;
- int i, j, n_matches, ret;
+ int i, n_matches, ret;
fw_status = iwl_mvm_get_wakeup_status(mvm);
if (!IS_ERR_OR_NULL(fw_status)) {
@@ -1817,14 +1931,10 @@ static void iwl_mvm_query_netdetect_reasons(struct iwl_mvm *mvm,
goto out_report_nd;
for_each_set_bit(i, &matched_profiles, mvm->n_nd_match_sets) {
- struct iwl_scan_offload_profile_match *fw_match;
struct cfg80211_wowlan_nd_match *match;
int idx, n_channels = 0;
- fw_match = &query.matches[i];
-
- for (j = 0; j < SCAN_OFFLOAD_MATCHING_CHANNELS_LEN; j++)
- n_channels += hweight8(fw_match->matching_channels[j]);
+ n_channels = iwl_mvm_query_num_match_chans(mvm, &query, i);
match = kzalloc(struct_size(match, channels, n_channels),
GFP_KERNEL);
@@ -1844,10 +1954,7 @@ static void iwl_mvm_query_netdetect_reasons(struct iwl_mvm *mvm,
if (mvm->n_nd_channels < n_channels)
continue;
- for (j = 0; j < SCAN_OFFLOAD_MATCHING_CHANNELS_LEN * 8; j++)
- if (fw_match->matching_channels[j / 8] & (BIT(j % 8)))
- match->channels[match->n_channels++] =
- mvm->nd_channels[j]->center_freq;
+ iwl_mvm_query_set_freqs(mvm, &query, match, i);
}
out_report_nd:
@@ -2030,7 +2137,6 @@ out:
* 2. We are using a unified image but had an error while exiting D3
*/
set_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status);
- set_bit(IWL_MVM_STATUS_D3_RECONFIG, &mvm->status);
/*
* When switching images we return 1, which causes mac80211
* to do a reconfig with IEEE80211_RECONFIG_TYPE_RESTART.
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c
index 6925527d8457..f043eefabb4e 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c
@@ -743,9 +743,8 @@ static ssize_t iwl_dbgfs_quota_min_read(struct file *file,
#define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \
_MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, struct ieee80211_vif)
#define MVM_DEBUGFS_ADD_FILE_VIF(name, parent, mode) do { \
- if (!debugfs_create_file(#name, mode, parent, vif, \
- &iwl_dbgfs_##name##_ops)) \
- goto err; \
+ debugfs_create_file(#name, mode, parent, vif, \
+ &iwl_dbgfs_##name##_ops); \
} while (0)
MVM_DEBUGFS_READ_FILE_OPS(mac_params);
@@ -811,12 +810,6 @@ void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
mvmvif->dbgfs_slink = debugfs_create_symlink(dbgfs_dir->d_name.name,
mvm->debugfs_dir, buf);
- if (!mvmvif->dbgfs_slink)
- IWL_ERR(mvm, "Can't create debugfs symbolic link under %pd\n",
- dbgfs_dir);
- return;
-err:
- IWL_ERR(mvm, "Can't create debugfs entity\n");
}
void iwl_mvm_vif_dbgfs_clean(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
index 776b24f54200..d4ff6b44de2c 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
@@ -1349,7 +1349,7 @@ static ssize_t iwl_dbgfs_fw_dbg_collect_write(struct iwl_mvm *mvm,
return 0;
iwl_fw_dbg_collect(&mvm->fwrt, FW_DBG_TRIGGER_USER, buf,
- (count - 1));
+ (count - 1), NULL);
iwl_mvm_unref(mvm, IWL_MVM_REF_PRPH_WRITE);
@@ -1696,9 +1696,8 @@ static ssize_t iwl_dbgfs_d0i3_refs_write(struct iwl_mvm *mvm, char *buf,
#define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \
_MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, struct iwl_mvm)
#define MVM_DEBUGFS_ADD_FILE_ALIAS(alias, name, parent, mode) do { \
- if (!debugfs_create_file(alias, mode, parent, mvm, \
- &iwl_dbgfs_##name##_ops)) \
- goto err; \
+ debugfs_create_file(alias, mode, parent, mvm, \
+ &iwl_dbgfs_##name##_ops); \
} while (0)
#define MVM_DEBUGFS_ADD_FILE(name, parent, mode) \
MVM_DEBUGFS_ADD_FILE_ALIAS(#name, name, parent, mode)
@@ -1709,9 +1708,8 @@ static ssize_t iwl_dbgfs_d0i3_refs_write(struct iwl_mvm *mvm, char *buf,
_MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, struct ieee80211_sta)
#define MVM_DEBUGFS_ADD_STA_FILE_ALIAS(alias, name, parent, mode) do { \
- if (!debugfs_create_file(alias, mode, parent, sta, \
- &iwl_dbgfs_##name##_ops)) \
- goto err; \
+ debugfs_create_file(alias, mode, parent, sta, \
+ &iwl_dbgfs_##name##_ops); \
} while (0)
#define MVM_DEBUGFS_ADD_STA_FILE(name, parent, mode) \
MVM_DEBUGFS_ADD_STA_FILE_ALIAS(#name, name, parent, mode)
@@ -2092,13 +2090,9 @@ void iwl_mvm_sta_add_debugfs(struct ieee80211_hw *hw,
if (iwl_mvm_has_tlc_offload(mvm))
MVM_DEBUGFS_ADD_STA_FILE(rs_data, dir, 0400);
-
- return;
-err:
- IWL_ERR(mvm, "Can't create the mvm station debugfs entry\n");
}
-int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
+void iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
{
struct dentry *bcast_dir __maybe_unused;
char buf[100];
@@ -2142,14 +2136,10 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
#endif
MVM_DEBUGFS_ADD_FILE(he_sniffer_params, mvm->debugfs_dir, 0600);
- if (!debugfs_create_bool("enable_scan_iteration_notif",
- 0600,
- mvm->debugfs_dir,
- &mvm->scan_iter_notif_enabled))
- goto err;
- if (!debugfs_create_bool("drop_bcn_ap_mode", 0600,
- mvm->debugfs_dir, &mvm->drop_bcn_ap_mode))
- goto err;
+ debugfs_create_bool("enable_scan_iteration_notif", 0600,
+ mvm->debugfs_dir, &mvm->scan_iter_notif_enabled);
+ debugfs_create_bool("drop_bcn_ap_mode", 0600, mvm->debugfs_dir,
+ &mvm->drop_bcn_ap_mode);
MVM_DEBUGFS_ADD_FILE(uapsd_noagg_bssids, mvm->debugfs_dir, S_IRUSR);
@@ -2157,13 +2147,9 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BCAST_FILTERING) {
bcast_dir = debugfs_create_dir("bcast_filtering",
mvm->debugfs_dir);
- if (!bcast_dir)
- goto err;
- if (!debugfs_create_bool("override", 0600,
- bcast_dir,
- &mvm->dbgfs_bcast_filtering.override))
- goto err;
+ debugfs_create_bool("override", 0600, bcast_dir,
+ &mvm->dbgfs_bcast_filtering.override);
MVM_DEBUGFS_ADD_FILE_ALIAS("filters", bcast_filters,
bcast_dir, 0600);
@@ -2175,35 +2161,26 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
#ifdef CONFIG_PM_SLEEP
MVM_DEBUGFS_ADD_FILE(d3_sram, mvm->debugfs_dir, 0600);
MVM_DEBUGFS_ADD_FILE(d3_test, mvm->debugfs_dir, 0400);
- if (!debugfs_create_bool("d3_wake_sysassert", 0600,
- mvm->debugfs_dir, &mvm->d3_wake_sysassert))
- goto err;
- if (!debugfs_create_u32("last_netdetect_scans", 0400,
- mvm->debugfs_dir, &mvm->last_netdetect_scans))
- goto err;
+ debugfs_create_bool("d3_wake_sysassert", 0600, mvm->debugfs_dir,
+ &mvm->d3_wake_sysassert);
+ debugfs_create_u32("last_netdetect_scans", 0400, mvm->debugfs_dir,
+ &mvm->last_netdetect_scans);
#endif
- if (!debugfs_create_u8("ps_disabled", 0400,
- mvm->debugfs_dir, &mvm->ps_disabled))
- goto err;
- if (!debugfs_create_blob("nvm_hw", 0400,
- mvm->debugfs_dir, &mvm->nvm_hw_blob))
- goto err;
- if (!debugfs_create_blob("nvm_sw", 0400,
- mvm->debugfs_dir, &mvm->nvm_sw_blob))
- goto err;
- if (!debugfs_create_blob("nvm_calib", 0400,
- mvm->debugfs_dir, &mvm->nvm_calib_blob))
- goto err;
- if (!debugfs_create_blob("nvm_prod", 0400,
- mvm->debugfs_dir, &mvm->nvm_prod_blob))
- goto err;
- if (!debugfs_create_blob("nvm_phy_sku", 0400,
- mvm->debugfs_dir, &mvm->nvm_phy_sku_blob))
- goto err;
- if (!debugfs_create_blob("nvm_reg", S_IRUSR,
- mvm->debugfs_dir, &mvm->nvm_reg_blob))
- goto err;
+ debugfs_create_u8("ps_disabled", 0400, mvm->debugfs_dir,
+ &mvm->ps_disabled);
+ debugfs_create_blob("nvm_hw", 0400, mvm->debugfs_dir,
+ &mvm->nvm_hw_blob);
+ debugfs_create_blob("nvm_sw", 0400, mvm->debugfs_dir,
+ &mvm->nvm_sw_blob);
+ debugfs_create_blob("nvm_calib", 0400, mvm->debugfs_dir,
+ &mvm->nvm_calib_blob);
+ debugfs_create_blob("nvm_prod", 0400, mvm->debugfs_dir,
+ &mvm->nvm_prod_blob);
+ debugfs_create_blob("nvm_phy_sku", 0400, mvm->debugfs_dir,
+ &mvm->nvm_phy_sku_blob);
+ debugfs_create_blob("nvm_reg", S_IRUSR,
+ mvm->debugfs_dir, &mvm->nvm_reg_blob);
debugfs_create_file("mem", 0600, dbgfs_dir, mvm, &iwl_dbgfs_mem_ops);
@@ -2212,11 +2189,5 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
* exists (before the opmode exists which removes the target.)
*/
snprintf(buf, 100, "../../%pd2", dbgfs_dir->d_parent);
- if (!debugfs_create_symlink("iwlwifi", mvm->hw->wiphy->debugfsdir, buf))
- goto err;
-
- return 0;
-err:
- IWL_ERR(mvm, "Can't create the mvm debugfs directory\n");
- return -ENOMEM;
+ debugfs_create_symlink("iwlwifi", mvm->hw->wiphy->debugfsdir, buf);
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
index 94132cfd1f56..fec38a47696e 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
@@ -187,12 +187,24 @@ static void iwl_mvm_ftm_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
for (i = 0; i < ETH_ALEN; i++)
cmd->macaddr_mask[i] = ~req->mac_addr_mask[i];
- if (vif->bss_conf.assoc)
+ if (vif->bss_conf.assoc) {
memcpy(cmd->range_req_bssid, vif->bss_conf.bssid, ETH_ALEN);
- else
+
+ /* AP's TSF is only relevant if associated */
+ for (i = 0; i < req->n_peers; i++) {
+ if (req->peers[i].report_ap_tsf) {
+ struct iwl_mvm_vif *mvmvif =
+ iwl_mvm_vif_from_mac80211(vif);
+
+ cmd->tsf_mac_id = cpu_to_le32(mvmvif->id);
+ return;
+ }
+ }
+ } else {
eth_broadcast_addr(cmd->range_req_bssid);
+ }
- /* TODO: fill in tsf_mac_id if needed */
+ /* Don't report AP's TSF */
cmd->tsf_mac_id = cpu_to_le32(0xff);
}
@@ -480,6 +492,7 @@ void iwl_mvm_ftm_range_resp(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
struct iwl_tof_range_rsp_ntfy_v5 *fw_resp_v5 = (void *)pkt->data;
+ struct iwl_tof_range_rsp_ntfy_v6 *fw_resp_v6 = (void *)pkt->data;
struct iwl_tof_range_rsp_ntfy *fw_resp = (void *)pkt->data;
int i;
bool new_api = fw_has_api(&mvm->fw->ucode_capa,
@@ -519,8 +532,15 @@ void iwl_mvm_ftm_range_resp(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb)
int peer_idx;
if (new_api) {
- fw_ap = &fw_resp->ap[i];
+ if (fw_has_api(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_API_FTM_RTT_ACCURACY))
+ fw_ap = &fw_resp->ap[i];
+ else
+ fw_ap = (void *)&fw_resp_v6->ap[i];
+
result.final = fw_resp->ap[i].last_burst;
+ result.ap_tsf = le32_to_cpu(fw_ap->start_tsf);
+ result.ap_tsf_valid = 1;
} else {
/* the first part is the same for old and new APIs */
fw_ap = (void *)&fw_resp_v5->ap[i];
@@ -588,6 +608,11 @@ void iwl_mvm_ftm_range_resp(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb)
mvm->ftm_initiator.req,
&result, GFP_KERNEL);
+ if (fw_has_api(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_API_FTM_RTT_ACCURACY))
+ IWL_DEBUG_INFO(mvm, "RTT confidence: %hhu\n",
+ fw_ap->rttConfidence);
+
iwl_mvm_debug_range_resp(mvm, i, &result);
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
index 6a70dece447d..53c217af13c8 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
@@ -8,7 +8,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,7 +31,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -262,9 +262,7 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
.preferred_tsf = NUM_TSF_IDS,
.found_vif = false,
};
- u32 ac;
- int ret, i, queue_limit;
- unsigned long used_hw_queues;
+ int ret, i;
lockdep_assert_held(&mvm->mutex);
@@ -341,37 +339,9 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
INIT_LIST_HEAD(&mvmvif->time_event_data.list);
mvmvif->time_event_data.id = TE_MAX;
- /* No need to allocate data queues to P2P Device MAC.*/
- if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
- for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
- vif->hw_queue[ac] = IEEE80211_INVAL_HW_QUEUE;
-
+ /* No need to allocate data queues to P2P Device MAC and NAN.*/
+ if (vif->type == NL80211_IFTYPE_P2P_DEVICE)
return 0;
- }
-
- /*
- * queues in mac80211 almost entirely independent of
- * the ones here - no real limit
- */
- queue_limit = IEEE80211_MAX_QUEUES;
-
- /*
- * Find available queues, and allocate them to the ACs. When in
- * DQA-mode they aren't really used, and this is done only so the
- * mac80211 ieee80211_check_queues() function won't fail
- */
- for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
- u8 queue = find_first_zero_bit(&used_hw_queues, queue_limit);
-
- if (queue >= queue_limit) {
- IWL_ERR(mvm, "Failed to allocate queue\n");
- ret = -EIO;
- goto exit_fail;
- }
-
- __set_bit(queue, &used_hw_queues);
- vif->hw_queue[ac] = queue;
- }
/* Allocate the CAB queue for softAP and GO interfaces */
if (vif->type == NL80211_IFTYPE_AP ||
@@ -1143,9 +1113,7 @@ static void iwl_mvm_mac_ctxt_cmd_fill_ap(struct iwl_mvm *mvm,
ieee80211_tu_to_usec(data.beacon_int * rand /
100);
} else {
- mvmvif->ap_beacon_time =
- iwl_read_prph(mvm->trans,
- DEVICE_SYSTEM_TIME_REG);
+ mvmvif->ap_beacon_time = iwl_mvm_get_systime(mvm);
}
}
@@ -1573,6 +1541,7 @@ void iwl_mvm_channel_switch_noa_notif(struct iwl_mvm *mvm,
rcu_read_lock();
vif = rcu_dereference(mvm->vif_id_to_mac[mac_id]);
+ mvmvif = iwl_mvm_vif_from_mac80211(vif);
switch (vif->type) {
case NL80211_IFTYPE_AP:
@@ -1581,7 +1550,6 @@ void iwl_mvm_channel_switch_noa_notif(struct iwl_mvm *mvm,
csa_vif != vif))
goto out_unlock;
- mvmvif = iwl_mvm_vif_from_mac80211(csa_vif);
csa_id = FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color);
if (WARN(csa_id != id_n_color,
"channel switch noa notification on unexpected vif (csa_vif=%d, notif=%d)",
@@ -1602,6 +1570,7 @@ void iwl_mvm_channel_switch_noa_notif(struct iwl_mvm *mvm,
return;
case NL80211_IFTYPE_STATION:
iwl_mvm_csa_client_absent(mvm, vif);
+ cancel_delayed_work(&mvmvif->csa_work);
ieee80211_chswitch_done(vif, true);
break;
default:
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 6a3b11dd2edf..5c52469288be 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -8,7 +8,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,7 +31,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -420,6 +420,7 @@ int iwl_mvm_init_fw_regd(struct iwl_mvm *mvm)
const static u8 he_if_types_ext_capa_sta[] = {
[0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,
+ [2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT,
[7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,
[9] = WLAN_EXT_CAPA10_TWT_REQUESTER_SUPPORT,
};
@@ -597,6 +598,9 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
BIT(NL80211_IFTYPE_ADHOC);
hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
+ wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
+ hw->wiphy->features |= NL80211_FEATURE_HT_IBSS;
+
hw->wiphy->regulatory_flags |= REGULATORY_ENABLE_RELAX_NO_IR;
if (iwl_mvm_is_lar_supported(mvm))
hw->wiphy->regulatory_flags |= REGULATORY_WIPHY_SELF_MANAGED;
@@ -732,6 +736,9 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
hw->wiphy->iftype_ext_capab = he_iftypes_ext_capa;
hw->wiphy->num_iftype_ext_capab =
ARRAY_SIZE(he_iftypes_ext_capa);
+
+ ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID);
+ ieee80211_hw_set(hw, SUPPORTS_ONLY_HE_MULTI_BSSID);
}
mvm->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
@@ -1191,15 +1198,6 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac,
static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
{
- /* clear the D3 reconfig, we only need it to avoid dumping a
- * firmware coredump on reconfiguration, we shouldn't do that
- * on D3->D0 transition
- */
- if (!test_and_clear_bit(IWL_MVM_STATUS_D3_RECONFIG, &mvm->status)) {
- mvm->fwrt.dump.desc = &iwl_dump_desc_assert;
- iwl_fw_error_dump(&mvm->fwrt);
- }
-
/* cleanup all stale references (scan, roc), but keep the
* ucode_down ref until reconfig is complete
*/
@@ -1500,6 +1498,91 @@ static int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
return iwl_mvm_send_cmd_pdu(mvm, REDUCE_TX_POWER_CMD, 0, len, &cmd);
}
+static int iwl_mvm_post_channel_switch(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
+{
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+ int ret;
+
+ mutex_lock(&mvm->mutex);
+
+ if (mvmvif->csa_failed) {
+ mvmvif->csa_failed = false;
+ ret = -EIO;
+ goto out_unlock;
+ }
+
+ if (vif->type == NL80211_IFTYPE_STATION) {
+ struct iwl_mvm_sta *mvmsta;
+
+ mvmvif->csa_bcn_pending = false;
+ mvmsta = iwl_mvm_sta_from_staid_protected(mvm,
+ mvmvif->ap_sta_id);
+
+ if (WARN_ON(!mvmsta)) {
+ ret = -EIO;
+ goto out_unlock;
+ }
+
+ iwl_mvm_sta_modify_disable_tx(mvm, mvmsta, false);
+
+ iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
+
+ ret = iwl_mvm_enable_beacon_filter(mvm, vif, 0);
+ if (ret)
+ goto out_unlock;
+
+ iwl_mvm_stop_session_protection(mvm, vif);
+ }
+
+ mvmvif->ps_disabled = false;
+
+ ret = iwl_mvm_power_update_ps(mvm);
+
+out_unlock:
+ mutex_unlock(&mvm->mutex);
+
+ return ret;
+}
+
+static void iwl_mvm_abort_channel_switch(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
+{
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct iwl_chan_switch_te_cmd cmd = {
+ .mac_id = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
+ mvmvif->color)),
+ .action = cpu_to_le32(FW_CTXT_ACTION_REMOVE),
+ };
+
+ IWL_DEBUG_MAC80211(mvm, "Abort CSA on mac %d\n", mvmvif->id);
+
+ mutex_lock(&mvm->mutex);
+ WARN_ON(iwl_mvm_send_cmd_pdu(mvm,
+ WIDE_ID(MAC_CONF_GROUP,
+ CHANNEL_SWITCH_TIME_EVENT_CMD),
+ 0, sizeof(cmd), &cmd));
+ mutex_unlock(&mvm->mutex);
+
+ WARN_ON(iwl_mvm_post_channel_switch(hw, vif));
+}
+
+static void iwl_mvm_channel_switch_disconnect_wk(struct work_struct *wk)
+{
+ struct iwl_mvm *mvm;
+ struct iwl_mvm_vif *mvmvif;
+ struct ieee80211_vif *vif;
+
+ mvmvif = container_of(wk, struct iwl_mvm_vif, csa_work.work);
+ vif = container_of((void *)mvmvif, struct ieee80211_vif, drv_priv);
+ mvm = mvmvif->mvm;
+
+ iwl_mvm_abort_channel_switch(mvm->hw, vif);
+ ieee80211_chswitch_done(vif, false);
+}
+
static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
@@ -1626,6 +1709,8 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
}
iwl_mvm_tcm_add_vif(mvm, vif);
+ INIT_DELAYED_WORK(&mvmvif->csa_work,
+ iwl_mvm_channel_switch_disconnect_wk);
if (vif->type == NL80211_IFTYPE_MONITOR)
mvm->monitor_on = true;
@@ -2127,6 +2212,10 @@ static void iwl_mvm_cfg_he_sta(struct iwl_mvm *mvm,
.frame_time_rts_th =
cpu_to_le16(vif->bss_conf.frame_time_rts_th),
};
+ int size = fw_has_api(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_API_MBSSID_HE) ?
+ sizeof(sta_ctxt_cmd) :
+ sizeof(struct iwl_he_sta_context_cmd_v1);
struct ieee80211_sta *sta;
u32 flags;
int i;
@@ -2254,16 +2343,18 @@ static void iwl_mvm_cfg_he_sta(struct iwl_mvm *mvm,
/* Set the PPE thresholds accordingly */
if (low_th >= 0 && high_th >= 0) {
- u8 ***pkt_ext_qam =
- (void *)sta_ctxt_cmd.pkt_ext.pkt_ext_qam_th;
+ struct iwl_he_pkt_ext *pkt_ext =
+ (struct iwl_he_pkt_ext *)&sta_ctxt_cmd.pkt_ext;
for (i = 0; i < MAX_HE_SUPP_NSS; i++) {
u8 bw;
for (bw = 0; bw < MAX_HE_CHANNEL_BW_INDX;
bw++) {
- pkt_ext_qam[i][bw][0] = low_th;
- pkt_ext_qam[i][bw][1] = high_th;
+ pkt_ext->pkt_ext_qam_th[i][bw][0] =
+ low_th;
+ pkt_ext->pkt_ext_qam_th[i][bw][1] =
+ high_th;
}
}
@@ -2308,13 +2399,23 @@ static void iwl_mvm_cfg_he_sta(struct iwl_mvm *mvm,
(vif->bss_conf.uora_ocw_range >> 3) & 0x7;
}
- /* TODO: support Multi BSSID IE */
+ if (vif->bss_conf.nontransmitted) {
+ flags |= STA_CTXT_HE_REF_BSSID_VALID;
+ ether_addr_copy(sta_ctxt_cmd.ref_bssid_addr,
+ vif->bss_conf.transmitter_bssid);
+ sta_ctxt_cmd.max_bssid_indicator =
+ vif->bss_conf.bssid_indicator;
+ sta_ctxt_cmd.bssid_index = vif->bss_conf.bssid_index;
+ sta_ctxt_cmd.ema_ap = vif->bss_conf.ema_ap;
+ sta_ctxt_cmd.profile_periodicity =
+ vif->bss_conf.profile_periodicity;
+ }
sta_ctxt_cmd.flags = cpu_to_le32(flags);
if (iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(STA_HE_CTXT_CMD,
DATA_PATH_GROUP, 0),
- 0, sizeof(sta_ctxt_cmd), &sta_ctxt_cmd))
+ 0, size, &sta_ctxt_cmd))
IWL_ERR(mvm, "Failed to config FW to work HE!\n");
}
@@ -3612,7 +3713,7 @@ static int iwl_mvm_send_aux_roc_cmd(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
int duration)
{
- int res, time_reg = DEVICE_SYSTEM_TIME_REG;
+ int res;
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm_time_event_data *te_data = &mvmvif->hs_time_event_data;
static const u16 time_event_response[] = { HOT_SPOT_CMD };
@@ -3638,7 +3739,7 @@ static int iwl_mvm_send_aux_roc_cmd(struct iwl_mvm *mvm,
0);
/* Set the time and duration */
- tail->apply_time = cpu_to_le32(iwl_read_prph(mvm->trans, time_reg));
+ tail->apply_time = cpu_to_le32(iwl_mvm_get_systime(mvm));
delay = AUX_ROC_MIN_DELAY;
req_dur = MSEC_TO_TU(duration);
@@ -4364,8 +4465,8 @@ static int __iwl_mvm_mac_testmode_cmd(struct iwl_mvm *mvm,
int err;
u32 noa_duration;
- err = nla_parse(tb, IWL_MVM_TM_ATTR_MAX, data, len, iwl_mvm_tm_policy,
- NULL);
+ err = nla_parse_deprecated(tb, IWL_MVM_TM_ATTR_MAX, data, len,
+ iwl_mvm_tm_policy, NULL);
if (err)
return err;
@@ -4442,16 +4543,22 @@ static int iwl_mvm_schedule_client_csa(struct iwl_mvm *mvm,
.action = cpu_to_le32(FW_CTXT_ACTION_ADD),
.tsf = cpu_to_le32(chsw->timestamp),
.cs_count = chsw->count,
+ .cs_mode = chsw->block_tx,
};
lockdep_assert_held(&mvm->mutex);
+ if (chsw->delay)
+ cmd.cs_delayed_bcn_count =
+ DIV_ROUND_UP(chsw->delay, vif->bss_conf.beacon_int);
+
return iwl_mvm_send_cmd_pdu(mvm,
WIDE_ID(MAC_CONF_GROUP,
CHANNEL_SWITCH_TIME_EVENT_CMD),
0, sizeof(cmd), &cmd);
}
+#define IWL_MAX_CSA_BLOCK_TX 1500
static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_channel_switch *chsw)
@@ -4516,8 +4623,18 @@ static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw,
((vif->bss_conf.beacon_int * (chsw->count - 1) -
IWL_MVM_CHANNEL_SWITCH_TIME_CLIENT) * 1024);
- if (chsw->block_tx)
+ if (chsw->block_tx) {
iwl_mvm_csa_client_absent(mvm, vif);
+ /*
+ * In case of undetermined / long time with immediate
+ * quiet monitor status to gracefully disconnect
+ */
+ if (!chsw->count ||
+ chsw->count * vif->bss_conf.beacon_int >
+ IWL_MAX_CSA_BLOCK_TX)
+ schedule_delayed_work(&mvmvif->csa_work,
+ msecs_to_jiffies(IWL_MAX_CSA_BLOCK_TX));
+ }
if (mvmvif->bf_data.bf_enabled) {
ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0);
@@ -4532,6 +4649,9 @@ static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw,
iwl_mvm_schedule_csa_period(mvm, vif,
vif->bss_conf.beacon_int,
apply_time);
+
+ mvmvif->csa_count = chsw->count;
+ mvmvif->csa_misbehave = false;
break;
default:
break;
@@ -4552,52 +4672,42 @@ out_unlock:
return ret;
}
-static int iwl_mvm_post_channel_switch(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+static void iwl_mvm_channel_switch_rx_beacon(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_channel_switch *chsw)
{
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
- int ret;
-
- mutex_lock(&mvm->mutex);
-
- if (mvmvif->csa_failed) {
- mvmvif->csa_failed = false;
- ret = -EIO;
- goto out_unlock;
- }
-
- if (vif->type == NL80211_IFTYPE_STATION) {
- struct iwl_mvm_sta *mvmsta;
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct iwl_chan_switch_te_cmd cmd = {
+ .mac_id = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
+ mvmvif->color)),
+ .action = cpu_to_le32(FW_CTXT_ACTION_MODIFY),
+ .tsf = cpu_to_le32(chsw->timestamp),
+ .cs_count = chsw->count,
+ .cs_mode = chsw->block_tx,
+ };
- mvmvif->csa_bcn_pending = false;
- mvmsta = iwl_mvm_sta_from_staid_protected(mvm,
- mvmvif->ap_sta_id);
+ if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_CS_MODIFY))
+ return;
- if (WARN_ON(!mvmsta)) {
- ret = -EIO;
- goto out_unlock;
+ if (chsw->count >= mvmvif->csa_count && chsw->block_tx) {
+ if (mvmvif->csa_misbehave) {
+ /* Second time, give up on this AP*/
+ iwl_mvm_abort_channel_switch(hw, vif);
+ ieee80211_chswitch_done(vif, false);
+ mvmvif->csa_misbehave = false;
+ return;
}
-
- iwl_mvm_sta_modify_disable_tx(mvm, mvmsta, false);
-
- iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
-
- ret = iwl_mvm_enable_beacon_filter(mvm, vif, 0);
- if (ret)
- goto out_unlock;
-
- iwl_mvm_stop_session_protection(mvm, vif);
+ mvmvif->csa_misbehave = true;
}
+ mvmvif->csa_count = chsw->count;
- mvmvif->ps_disabled = false;
-
- ret = iwl_mvm_power_update_ps(mvm);
-
-out_unlock:
- mutex_unlock(&mvm->mutex);
+ IWL_DEBUG_MAC80211(mvm, "Modify CSA on mac %d\n", mvmvif->id);
- return ret;
+ WARN_ON(iwl_mvm_send_cmd_pdu(mvm,
+ WIDE_ID(MAC_CONF_GROUP,
+ CHANNEL_SWITCH_TIME_EVENT_CMD),
+ CMD_ASYNC, sizeof(cmd), &cmd));
}
static void iwl_mvm_flush_no_vif(struct iwl_mvm *mvm, u32 queues, bool drop)
@@ -5056,6 +5166,8 @@ const struct ieee80211_ops iwl_mvm_hw_ops = {
.channel_switch = iwl_mvm_channel_switch,
.pre_channel_switch = iwl_mvm_pre_channel_switch,
.post_channel_switch = iwl_mvm_post_channel_switch,
+ .abort_channel_switch = iwl_mvm_abort_channel_switch,
+ .channel_switch_rx_beacon = iwl_mvm_channel_switch_rx_beacon,
.tdls_channel_switch = iwl_mvm_tdls_channel_switch,
.tdls_cancel_channel_switch = iwl_mvm_tdls_cancel_channel_switch,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index a50dc53df086..8dc2a9850bc5 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -8,7 +8,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,7 +31,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -490,6 +490,9 @@ struct iwl_mvm_vif {
bool csa_countdown;
bool csa_failed;
u16 csa_target_freq;
+ u16 csa_count;
+ u16 csa_misbehave;
+ struct delayed_work csa_work;
/* Indicates that we are waiting for a beacon on a new channel */
bool csa_bcn_pending;
@@ -1199,7 +1202,6 @@ struct iwl_mvm {
* @IWL_MVM_STATUS_IN_HW_RESTART: HW restart is active
* @IWL_MVM_STATUS_IN_D0I3: NIC is in D0i3
* @IWL_MVM_STATUS_ROC_AUX_RUNNING: AUX remain-on-channel is running
- * @IWL_MVM_STATUS_D3_RECONFIG: D3 reconfiguration is being done
* @IWL_MVM_STATUS_FIRMWARE_RUNNING: firmware is running
* @IWL_MVM_STATUS_NEED_FLUSH_P2P: need to flush P2P bcast STA
*/
@@ -1211,7 +1213,6 @@ enum iwl_mvm_status {
IWL_MVM_STATUS_IN_HW_RESTART,
IWL_MVM_STATUS_IN_D0I3,
IWL_MVM_STATUS_ROC_AUX_RUNNING,
- IWL_MVM_STATUS_D3_RECONFIG,
IWL_MVM_STATUS_FIRMWARE_RUNNING,
IWL_MVM_STATUS_NEED_FLUSH_P2P,
};
@@ -1537,6 +1538,7 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm);
u8 first_antenna(u8 mask);
u8 iwl_mvm_next_antenna(struct iwl_mvm *mvm, u8 valid, u8 last_idx);
void iwl_mvm_get_sync_time(struct iwl_mvm *mvm, u32 *gp2, u64 *boottime);
+u32 iwl_mvm_get_systime(struct iwl_mvm *mvm);
/* Tx / Host Commands */
int __must_check iwl_mvm_send_cmd(struct iwl_mvm *mvm,
@@ -1649,8 +1651,8 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi,
struct iwl_rx_cmd_buffer *rxb);
void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
struct iwl_rx_cmd_buffer *rxb, int queue);
-void iwl_mvm_rx_monitor_ndp(struct iwl_mvm *mvm, struct napi_struct *napi,
- struct iwl_rx_cmd_buffer *rxb, int queue);
+void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi,
+ struct iwl_rx_cmd_buffer *rxb, int queue);
void iwl_mvm_rx_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi,
struct iwl_rx_cmd_buffer *rxb, int queue);
int iwl_mvm_notify_rx_queue(struct iwl_mvm *mvm, u32 rxq_mask,
@@ -1784,14 +1786,13 @@ void iwl_mvm_rx_umac_scan_iter_complete_notif(struct iwl_mvm *mvm,
/* MVM debugfs */
#ifdef CONFIG_IWLWIFI_DEBUGFS
-int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir);
+void iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir);
void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
void iwl_mvm_vif_dbgfs_clean(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
#else
-static inline int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm,
- struct dentry *dbgfs_dir)
+static inline void iwl_mvm_dbgfs_register(struct iwl_mvm *mvm,
+ struct dentry *dbgfs_dir)
{
- return 0;
}
static inline void
iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
@@ -2023,17 +2024,6 @@ static inline u32 iwl_mvm_flushable_queues(struct iwl_mvm *mvm)
static inline void iwl_mvm_stop_device(struct iwl_mvm *mvm)
{
lockdep_assert_held(&mvm->mutex);
- /* If IWL_MVM_STATUS_HW_RESTART_REQUESTED bit is set then we received
- * an assert. Since we failed to bring the interface up, mac80211
- * will not attempt to reconfig the device,
- * which handles the dump collection in assert flow,
- * so trigger dump collection here.
- */
- if (test_and_clear_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED,
- &mvm->status))
- iwl_fw_dbg_collect_desc(&mvm->fwrt, &iwl_dump_desc_assert,
- false, 0);
-
iwl_fw_cancel_timestamp(&mvm->fwrt);
clear_bit(IWL_MVM_STATUS_FIRMWARE_RUNNING, &mvm->status);
iwl_fwrt_stop_device(&mvm->fwrt);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
index 13681b03c10e..acd2fda12466 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
@@ -8,7 +8,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,7 +31,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -862,9 +862,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
min_backoff = iwl_mvm_min_backoff(mvm);
iwl_mvm_thermal_initialize(mvm, min_backoff);
- err = iwl_mvm_dbgfs_register(mvm, dbgfs_dir);
- if (err)
- goto out_unregister;
+ iwl_mvm_dbgfs_register(mvm, dbgfs_dir);
if (!iwl_mvm_has_new_rx_stats_api(mvm))
memset(&mvm->rx_stats_v3, 0,
@@ -881,14 +879,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
return op_mode;
- out_unregister:
- if (iwlmvm_mod_params.init_dbg)
- return op_mode;
-
- ieee80211_unregister_hw(mvm->hw);
- mvm->hw_registered = false;
- iwl_mvm_leds_exit(mvm);
- iwl_mvm_thermal_exit(mvm);
out_free:
iwl_fw_flush_dump(&mvm->fwrt);
iwl_fw_runtime_free(&mvm->fwrt);
@@ -1105,7 +1095,7 @@ static void iwl_mvm_rx_mq(struct iwl_op_mode *op_mode,
else if (cmd == WIDE_ID(LEGACY_GROUP, FRAME_RELEASE))
iwl_mvm_rx_frame_release(mvm, napi, rxb, 0);
else if (cmd == WIDE_ID(DATA_PATH_GROUP, RX_NO_DATA_NOTIF))
- iwl_mvm_rx_monitor_ndp(mvm, napi, rxb, 0);
+ iwl_mvm_rx_monitor_no_data(mvm, napi, rxb, 0);
else
iwl_mvm_rx_common(mvm, rxb, pkt);
}
@@ -1271,6 +1261,7 @@ static void iwl_mvm_reprobe_wk(struct work_struct *wk)
void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error)
{
iwl_abort_notification_waits(&mvm->notif_wait);
+ del_timer(&mvm->fwrt.dump.periodic_trig);
/*
* This is a bit racy, but worst case we tell mac80211 about
@@ -1291,8 +1282,7 @@ void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error)
* can't recover this since we're already half suspended.
*/
if (!mvm->fw_restart && fw_error) {
- iwl_fw_dbg_collect_desc(&mvm->fwrt, &iwl_dump_desc_assert,
- false, 0);
+ iwl_fw_error_collect(&mvm->fwrt);
} else if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
struct iwl_mvm_reprobe *reprobe;
@@ -1340,6 +1330,8 @@ void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error)
}
}
+ iwl_fw_error_collect(&mvm->fwrt);
+
if (fw_error && mvm->fw_restart > 0)
mvm->fw_restart--;
set_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
index a28283ff7295..659e21b2d4e7 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
@@ -6,7 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -27,7 +27,7 @@
* BSD LICENSE
*
* Copyright(c) 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -116,8 +116,9 @@ static u8 rs_fw_sgi_cw_support(struct ieee80211_sta *sta)
return supp;
}
-static u16 rs_fw_set_config_flags(struct iwl_mvm *mvm,
- struct ieee80211_sta *sta)
+static u16 rs_fw_get_config_flags(struct iwl_mvm *mvm,
+ struct ieee80211_sta *sta,
+ struct ieee80211_supported_band *sband)
{
struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap;
@@ -147,6 +148,12 @@ static u16 rs_fw_set_config_flags(struct iwl_mvm *mvm,
(vht_ena && (vht_cap->cap & IEEE80211_VHT_CAP_RXLDPC))))
flags |= IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK;
+ /* consider our LDPC support in case of HE */
+ if (sband->iftype_data && sband->iftype_data->he_cap.has_he &&
+ !(sband->iftype_data->he_cap.he_cap_elem.phy_cap_info[1] &
+ IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD))
+ flags &= ~IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK;
+
if (he_cap && he_cap->has_he &&
(he_cap->he_cap_elem.phy_cap_info[3] &
IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_MASK))
@@ -223,19 +230,43 @@ static u16 rs_fw_he_ieee80211_mcs_to_rs_mcs(u16 mcs)
static void
rs_fw_he_set_enabled_rates(const struct ieee80211_sta *sta,
- const struct ieee80211_sta_he_cap *he_cap,
+ struct ieee80211_supported_band *sband,
struct iwl_tlc_config_cmd *cmd)
{
- u16 mcs_160 = le16_to_cpu(sta->he_cap.he_mcs_nss_supp.rx_mcs_160);
- u16 mcs_80 = le16_to_cpu(sta->he_cap.he_mcs_nss_supp.rx_mcs_80);
+ const struct ieee80211_sta_he_cap *he_cap = &sta->he_cap;
+ u16 mcs_160 = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_160);
+ u16 mcs_80 = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_80);
+ u16 tx_mcs_80 =
+ le16_to_cpu(sband->iftype_data->he_cap.he_mcs_nss_supp.tx_mcs_80);
+ u16 tx_mcs_160 =
+ le16_to_cpu(sband->iftype_data->he_cap.he_mcs_nss_supp.tx_mcs_160);
int i;
for (i = 0; i < sta->rx_nss && i < MAX_NSS; i++) {
u16 _mcs_160 = (mcs_160 >> (2 * i)) & 0x3;
u16 _mcs_80 = (mcs_80 >> (2 * i)) & 0x3;
-
+ u16 _tx_mcs_160 = (tx_mcs_160 >> (2 * i)) & 0x3;
+ u16 _tx_mcs_80 = (tx_mcs_80 >> (2 * i)) & 0x3;
+
+ /* If one side doesn't support - mark both as not supporting */
+ if (_mcs_80 == IEEE80211_HE_MCS_NOT_SUPPORTED ||
+ _tx_mcs_80 == IEEE80211_HE_MCS_NOT_SUPPORTED) {
+ _mcs_80 = IEEE80211_HE_MCS_NOT_SUPPORTED;
+ _tx_mcs_80 = IEEE80211_HE_MCS_NOT_SUPPORTED;
+ }
+ if (_mcs_80 > _tx_mcs_80)
+ _mcs_80 = _tx_mcs_80;
cmd->ht_rates[i][0] =
cpu_to_le16(rs_fw_he_ieee80211_mcs_to_rs_mcs(_mcs_80));
+
+ /* If one side doesn't support - mark both as not supporting */
+ if (_mcs_160 == IEEE80211_HE_MCS_NOT_SUPPORTED ||
+ _tx_mcs_160 == IEEE80211_HE_MCS_NOT_SUPPORTED) {
+ _mcs_160 = IEEE80211_HE_MCS_NOT_SUPPORTED;
+ _tx_mcs_160 = IEEE80211_HE_MCS_NOT_SUPPORTED;
+ }
+ if (_mcs_160 > _tx_mcs_160)
+ _mcs_160 = _tx_mcs_160;
cmd->ht_rates[i][1] =
cpu_to_le16(rs_fw_he_ieee80211_mcs_to_rs_mcs(_mcs_160));
}
@@ -264,7 +295,7 @@ static void rs_fw_set_supp_rates(struct ieee80211_sta *sta,
/* HT/VHT rates */
if (he_cap && he_cap->has_he) {
cmd->mode = IWL_TLC_MNG_MODE_HE;
- rs_fw_he_set_enabled_rates(sta, he_cap, cmd);
+ rs_fw_he_set_enabled_rates(sta, sband, cmd);
} else if (vht_cap && vht_cap->vht_supported) {
cmd->mode = IWL_TLC_MNG_MODE_VHT;
rs_fw_vht_set_enabled_rates(sta, vht_cap, cmd);
@@ -345,6 +376,37 @@ out:
rcu_read_unlock();
}
+static u16 rs_fw_get_max_amsdu_len(struct ieee80211_sta *sta)
+{
+ const struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap;
+ const struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
+
+ if (vht_cap && vht_cap->vht_supported) {
+ switch (vht_cap->cap & IEEE80211_VHT_CAP_MAX_MPDU_MASK) {
+ case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454:
+ return IEEE80211_MAX_MPDU_LEN_VHT_11454;
+ case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991:
+ return IEEE80211_MAX_MPDU_LEN_VHT_7991;
+ default:
+ return IEEE80211_MAX_MPDU_LEN_VHT_3895;
+ }
+
+ } else if (ht_cap && ht_cap->ht_supported) {
+ if (ht_cap->cap & IEEE80211_HT_CAP_MAX_AMSDU)
+ /*
+ * agg is offloaded so we need to assume that agg
+ * are enabled and max mpdu in ampdu is 4095
+ * (spec 802.11-2016 9.3.2.1)
+ */
+ return IEEE80211_MAX_MPDU_LEN_HT_BA;
+ else
+ return IEEE80211_MAX_MPDU_LEN_HT_3839;
+ }
+
+ /* in legacy mode no amsdu is enabled so return zero */
+ return 0;
+}
+
void rs_fw_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
enum nl80211_band band, bool update)
{
@@ -352,15 +414,16 @@ void rs_fw_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
struct iwl_lq_sta_rs_fw *lq_sta = &mvmsta->lq_sta.rs_fw;
u32 cmd_id = iwl_cmd_id(TLC_MNG_CONFIG_CMD, DATA_PATH_GROUP, 0);
- struct ieee80211_supported_band *sband;
+ struct ieee80211_supported_band *sband = hw->wiphy->bands[band];
+ u16 max_amsdu_len = rs_fw_get_max_amsdu_len(sta);
struct iwl_tlc_config_cmd cfg_cmd = {
.sta_id = mvmsta->sta_id,
.max_ch_width = update ?
rs_fw_bw_from_sta_bw(sta) : RATE_MCS_CHAN_WIDTH_20,
- .flags = cpu_to_le16(rs_fw_set_config_flags(mvm, sta)),
+ .flags = cpu_to_le16(rs_fw_get_config_flags(mvm, sta, sband)),
.chains = rs_fw_set_active_chains(iwl_mvm_get_valid_tx_ant(mvm)),
- .max_mpdu_len = cpu_to_le16(sta->max_amsdu_len),
.sgi_ch_width_supp = rs_fw_sgi_cw_support(sta),
+ .max_mpdu_len = cpu_to_le16(max_amsdu_len),
.amsdu = iwl_mvm_is_csum_supported(mvm),
};
int ret;
@@ -370,9 +433,14 @@ void rs_fw_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
#ifdef CONFIG_IWLWIFI_DEBUGFS
iwl_mvm_reset_frame_stats(mvm);
#endif
- sband = hw->wiphy->bands[band];
rs_fw_set_supp_rates(sta, sband, &cfg_cmd);
+ /*
+ * since TLC offload works with one mode we can assume
+ * that only vht/ht is used and also set it as station max amsdu
+ */
+ sta->max_amsdu_len = max_amsdu_len;
+
ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, sizeof(cfg_cmd), &cfg_cmd);
if (ret)
IWL_ERR(mvm, "Failed to send rate scale config (%d)\n", ret);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
index e231a44d2423..c182821ab22b 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
@@ -4078,9 +4078,8 @@ static ssize_t iwl_dbgfs_ss_force_write(struct iwl_lq_sta *lq_sta, char *buf,
#define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \
_MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, struct iwl_lq_sta)
#define MVM_DEBUGFS_ADD_FILE_RS(name, parent, mode) do { \
- if (!debugfs_create_file(#name, mode, parent, lq_sta, \
- &iwl_dbgfs_##name##_ops)) \
- goto err; \
+ debugfs_create_file(#name, mode, parent, lq_sta, \
+ &iwl_dbgfs_##name##_ops); \
} while (0)
MVM_DEBUGFS_READ_WRITE_FILE_OPS(ss_force, 32);
@@ -4108,9 +4107,6 @@ static void rs_drv_add_sta_debugfs(void *mvm, void *priv_sta,
&lq_sta->pers.dbg_fixed_txp_reduction);
MVM_DEBUGFS_ADD_FILE_RS(ss_force, dir, 0600);
- return;
-err:
- IWL_ERR((struct iwl_mvm *)mvm, "Can't create debugfs entity\n");
}
void rs_remove_sta_debugfs(void *mvm, void *mvm_sta)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
index b516fd1867ec..1824566d08fc 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
@@ -8,7 +8,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,7 +31,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -1699,8 +1699,8 @@ out:
rcu_read_unlock();
}
-void iwl_mvm_rx_monitor_ndp(struct iwl_mvm *mvm, struct napi_struct *napi,
- struct iwl_rx_cmd_buffer *rxb, int queue)
+void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi,
+ struct iwl_rx_cmd_buffer *rxb, int queue)
{
struct ieee80211_rx_status *rx_status;
struct iwl_rx_packet *pkt = rxb_addr(rxb);
@@ -1721,10 +1721,6 @@ void iwl_mvm_rx_monitor_ndp(struct iwl_mvm *mvm, struct napi_struct *napi,
if (unlikely(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)))
return;
- /* Currently only NDP type is supported */
- if (info_type != RX_NO_DATA_INFO_TYPE_NDP)
- return;
-
energy_a = (rssi & RX_NO_DATA_CHAIN_A_MSK) >> RX_NO_DATA_CHAIN_A_POS;
energy_b = (rssi & RX_NO_DATA_CHAIN_B_MSK) >> RX_NO_DATA_CHAIN_B_POS;
channel = (rssi & RX_NO_DATA_CHANNEL_MSK) >> RX_NO_DATA_CHANNEL_POS;
@@ -1746,9 +1742,22 @@ void iwl_mvm_rx_monitor_ndp(struct iwl_mvm *mvm, struct napi_struct *napi,
/* 0-length PSDU */
rx_status->flag |= RX_FLAG_NO_PSDU;
- /* currently this is the only type for which we get this notif */
- rx_status->zero_length_psdu_type =
- IEEE80211_RADIOTAP_ZERO_LEN_PSDU_SOUNDING;
+
+ switch (info_type) {
+ case RX_NO_DATA_INFO_TYPE_NDP:
+ rx_status->zero_length_psdu_type =
+ IEEE80211_RADIOTAP_ZERO_LEN_PSDU_SOUNDING;
+ break;
+ case RX_NO_DATA_INFO_TYPE_MU_UNMATCHED:
+ case RX_NO_DATA_INFO_TYPE_HE_TB_UNMATCHED:
+ rx_status->zero_length_psdu_type =
+ IEEE80211_RADIOTAP_ZERO_LEN_PSDU_NOT_CAPTURED;
+ break;
+ default:
+ rx_status->zero_length_psdu_type =
+ IEEE80211_RADIOTAP_ZERO_LEN_PSDU_VENDOR;
+ break;
+ }
/* This may be overridden by iwl_mvm_rx_he() to HE_RU */
switch (rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK) {
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
index 78694bc38e76..d9ddf9ff6428 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
@@ -1082,21 +1082,23 @@ static void iwl_mvm_fill_scan_dwell(struct iwl_mvm *mvm,
dwell->extended = IWL_SCAN_DWELL_EXTENDED;
}
-static void iwl_mvm_fill_channels(struct iwl_mvm *mvm, u8 *channels)
+static void iwl_mvm_fill_channels(struct iwl_mvm *mvm, u8 *channels,
+ u32 max_channels)
{
struct ieee80211_supported_band *band;
int i, j = 0;
band = &mvm->nvm_data->bands[NL80211_BAND_2GHZ];
- for (i = 0; i < band->n_channels; i++, j++)
+ for (i = 0; i < band->n_channels && j < max_channels; i++, j++)
channels[j] = band->channels[i].hw_value;
band = &mvm->nvm_data->bands[NL80211_BAND_5GHZ];
- for (i = 0; i < band->n_channels; i++, j++)
+ for (i = 0; i < band->n_channels && j < max_channels; i++, j++)
channels[j] = band->channels[i].hw_value;
}
static void iwl_mvm_fill_scan_config_v1(struct iwl_mvm *mvm, void *config,
- u32 flags, u8 channel_flags)
+ u32 flags, u8 channel_flags,
+ u32 max_channels)
{
enum iwl_mvm_scan_type type = iwl_mvm_get_scan_type(mvm, NULL);
struct iwl_scan_config_v1 *cfg = config;
@@ -1115,11 +1117,12 @@ static void iwl_mvm_fill_scan_config_v1(struct iwl_mvm *mvm, void *config,
cfg->bcast_sta_id = mvm->aux_sta.sta_id;
cfg->channel_flags = channel_flags;
- iwl_mvm_fill_channels(mvm, cfg->channel_array);
+ iwl_mvm_fill_channels(mvm, cfg->channel_array, max_channels);
}
static void iwl_mvm_fill_scan_config(struct iwl_mvm *mvm, void *config,
- u32 flags, u8 channel_flags)
+ u32 flags, u8 channel_flags,
+ u32 max_channels)
{
struct iwl_scan_config *cfg = config;
@@ -1162,7 +1165,7 @@ static void iwl_mvm_fill_scan_config(struct iwl_mvm *mvm, void *config,
cfg->bcast_sta_id = mvm->aux_sta.sta_id;
cfg->channel_flags = channel_flags;
- iwl_mvm_fill_channels(mvm, cfg->channel_array);
+ iwl_mvm_fill_channels(mvm, cfg->channel_array, max_channels);
}
int iwl_mvm_config_scan(struct iwl_mvm *mvm)
@@ -1181,7 +1184,7 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm)
u8 channel_flags;
if (WARN_ON(num_channels > mvm->fw->ucode_capa.n_scan_channels))
- return -ENOBUFS;
+ num_channels = mvm->fw->ucode_capa.n_scan_channels;
if (iwl_mvm_is_cdb_supported(mvm)) {
type = iwl_mvm_get_scan_type_band(mvm, NULL,
@@ -1234,9 +1237,11 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm)
flags |= (iwl_mvm_is_scan_fragmented(hb_type)) ?
SCAN_CONFIG_FLAG_SET_LMAC2_FRAGMENTED :
SCAN_CONFIG_FLAG_CLEAR_LMAC2_FRAGMENTED;
- iwl_mvm_fill_scan_config(mvm, cfg, flags, channel_flags);
+ iwl_mvm_fill_scan_config(mvm, cfg, flags, channel_flags,
+ num_channels);
} else {
- iwl_mvm_fill_scan_config_v1(mvm, cfg, flags, channel_flags);
+ iwl_mvm_fill_scan_config_v1(mvm, cfg, flags, channel_flags,
+ num_channels);
}
cmd.data[0] = cfg;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
index 98d123dd7177..f545a737a92d 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
@@ -746,7 +746,8 @@ static int iwl_mvm_find_free_queue(struct iwl_mvm *mvm, u8 sta_id,
static int iwl_mvm_tvqm_enable_txq(struct iwl_mvm *mvm,
u8 sta_id, u8 tid, unsigned int timeout)
{
- int queue, size = IWL_DEFAULT_QUEUE_SIZE;
+ int queue, size = max_t(u32, IWL_DEFAULT_QUEUE_SIZE,
+ mvm->trans->cfg->min_256_ba_txq_size);
if (tid == IWL_MAX_TID_COUNT) {
tid = IWL_MGMT_TID;
@@ -2109,12 +2110,14 @@ int iwl_mvm_send_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
if (!iwl_mvm_has_new_tx_api(mvm)) {
if (vif->type == NL80211_IFTYPE_AP ||
- vif->type == NL80211_IFTYPE_ADHOC)
+ vif->type == NL80211_IFTYPE_ADHOC) {
queue = mvm->probe_queue;
- else if (vif->type == NL80211_IFTYPE_P2P_DEVICE)
+ } else if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
queue = mvm->p2p_dev_queue;
- else if (WARN(1, "Missing required TXQ for adding bcast STA\n"))
+ } else {
+ WARN(1, "Missing required TXQ for adding bcast STA\n");
return -EINVAL;
+ }
bsta->tfd_queue_msk |= BIT(queue);
@@ -2277,7 +2280,8 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
static const u8 _maddr[] = {0x03, 0x00, 0x00, 0x00, 0x00, 0x00};
const u8 *maddr = _maddr;
struct iwl_trans_txq_scd_cfg cfg = {
- .fifo = IWL_MVM_TX_FIFO_MCAST,
+ .fifo = vif->type == NL80211_IFTYPE_AP ?
+ IWL_MVM_TX_FIFO_MCAST : IWL_MVM_TX_FIFO_BE,
.sta_id = msta->sta_id,
.tid = 0,
.aggregate = false,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c b/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c
index 859aa5a4e6b5..9df21a8d1fc1 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c
@@ -7,7 +7,7 @@
*
* Copyright(c) 2014 Intel Mobile Communications GmbH
* Copyright(c) 2017 Intel Deutschland GmbH
- * Copyright(C) 2018 Intel Corporation
+ * Copyright(C) 2018 - 2019 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -29,7 +29,7 @@
*
* Copyright(c) 2014 Intel Mobile Communications GmbH
* Copyright(c) 2017 Intel Deutschland GmbH
- * Copyright(C) 2018 Intel Corporation
+ * Copyright(C) 2018 - 2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -252,8 +252,7 @@ static void iwl_mvm_tdls_update_cs_state(struct iwl_mvm *mvm,
/* we only send requests to our switching peer - update sent time */
if (state == IWL_MVM_TDLS_SW_REQ_SENT)
- mvm->tdls_cs.peer.sent_timestamp =
- iwl_read_prph(mvm->trans, DEVICE_SYSTEM_TIME_REG);
+ mvm->tdls_cs.peer.sent_timestamp = iwl_mvm_get_systime(mvm);
if (state == IWL_MVM_TDLS_SW_IDLE)
mvm->tdls_cs.cur_sta_id = IWL_MVM_INVALID_STA;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
index 9693fa4cdc39..4d34e5ab1bff 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
@@ -8,7 +8,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,7 +31,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -234,6 +234,7 @@ iwl_mvm_te_handle_notify_csa(struct iwl_mvm *mvm,
break;
}
iwl_mvm_csa_client_absent(mvm, te_data->vif);
+ cancel_delayed_work(&mvmvif->csa_work);
ieee80211_chswitch_done(te_data->vif, true);
break;
default:
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
index 4649327abb45..b9914efc55c4 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
@@ -1418,6 +1418,16 @@ void iwl_mvm_tcm_rm_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
cancel_delayed_work_sync(&mvmvif->uapsd_nonagg_detected_wk);
}
+u32 iwl_mvm_get_systime(struct iwl_mvm *mvm)
+{
+ u32 reg_addr = DEVICE_SYSTEM_TIME_REG;
+
+ if (mvm->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22000 &&
+ mvm->trans->cfg->gp2_reg_addr)
+ reg_addr = mvm->trans->cfg->gp2_reg_addr;
+
+ return iwl_read_prph(mvm->trans, reg_addr);
+}
void iwl_mvm_get_sync_time(struct iwl_mvm *mvm, u32 *gp2, u64 *boottime)
{
@@ -1432,7 +1442,7 @@ void iwl_mvm_get_sync_time(struct iwl_mvm *mvm, u32 *gp2, u64 *boottime)
iwl_mvm_power_update_device(mvm);
}
- *gp2 = iwl_read_prph(mvm->trans, DEVICE_SYSTEM_TIME_REG);
+ *gp2 = iwl_mvm_get_systime(mvm);
*boottime = ktime_get_boot_ns();
if (!ps_disabled) {
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c
index 1e36459948db..f496d1bcb643 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c
@@ -66,7 +66,8 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans,
void *iml_img;
u32 control_flags = 0;
int ret;
- int cmdq_size = max_t(u32, TFD_CMD_SLOTS, trans->cfg->min_txq_size);
+ int cmdq_size = max_t(u32, IWL_CMD_QUEUE_SIZE,
+ trans->cfg->min_txq_size);
/* Allocate prph scratch */
prph_scratch = dma_alloc_coherent(trans->dev, sizeof(*prph_scratch),
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c
index 9274e317cc77..8969b47bacf2 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c
@@ -6,7 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -20,7 +20,7 @@
* BSD LICENSE
*
* Copyright(c) 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -210,7 +210,7 @@ int iwl_pcie_ctxt_info_init(struct iwl_trans *trans,
ctxt_info->hcmd_cfg.cmd_queue_addr =
cpu_to_le64(trans_pcie->txq[trans_pcie->cmd_queue]->dma_addr);
ctxt_info->hcmd_cfg.cmd_queue_size =
- TFD_QUEUE_CB_SIZE(TFD_CMD_SLOTS);
+ TFD_QUEUE_CB_SIZE(IWL_CMD_QUEUE_SIZE);
/* allocate ucode sections in dram and set addresses */
ret = iwl_pcie_init_fw_sec(trans, fw, &ctxt_info->dram);
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
index 9f1af8da9dc1..cd035061cdd5 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
@@ -928,11 +928,6 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
{IWL_PCI_DEVICE(0x34F0, 0x1651, killer1650s_2ax_cfg_qu_b0_hr_b0)},
{IWL_PCI_DEVICE(0x34F0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0)},
{IWL_PCI_DEVICE(0x34F0, 0x4070, iwl_ax101_cfg_qu_hr)},
- {IWL_PCI_DEVICE(0x40C0, 0x0000, iwl22560_2ax_cfg_su_cdb)},
- {IWL_PCI_DEVICE(0x40C0, 0x0010, iwl22560_2ax_cfg_su_cdb)},
- {IWL_PCI_DEVICE(0x40c0, 0x0090, iwl22560_2ax_cfg_su_cdb)},
- {IWL_PCI_DEVICE(0x40C0, 0x0310, iwl22560_2ax_cfg_su_cdb)},
- {IWL_PCI_DEVICE(0x40C0, 0x0A10, iwl22560_2ax_cfg_su_cdb)},
{IWL_PCI_DEVICE(0x43F0, 0x0040, iwl_ax101_cfg_qu_hr)},
{IWL_PCI_DEVICE(0x43F0, 0x0070, iwl_ax101_cfg_qu_hr)},
{IWL_PCI_DEVICE(0x43F0, 0x0074, iwl_ax101_cfg_qu_hr)},
@@ -963,9 +958,6 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
{IWL_PCI_DEVICE(0x2723, 0x4080, iwl_ax200_cfg_cc)},
{IWL_PCI_DEVICE(0x2723, 0x4088, iwl_ax200_cfg_cc)},
- {IWL_PCI_DEVICE(0x1a56, 0x1653, killer1650w_2ax_cfg)},
- {IWL_PCI_DEVICE(0x1a56, 0x1654, killer1650x_2ax_cfg)},
-
{IWL_PCI_DEVICE(0x2725, 0x0090, iwlax210_2ax_cfg_so_hr_a0)},
{IWL_PCI_DEVICE(0x7A70, 0x0090, iwlax210_2ax_cfg_so_hr_a0)},
{IWL_PCI_DEVICE(0x7A70, 0x0310, iwlax210_2ax_cfg_so_hr_a0)},
@@ -1047,9 +1039,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
}
/* register transport layer debugfs here */
- ret = iwl_trans_pcie_dbgfs_register(iwl_trans);
- if (ret)
- goto out_free_drv;
+ iwl_trans_pcie_dbgfs_register(iwl_trans);
/* if RTPM is in use, enable it in our device */
if (iwl_trans->runtime_pm_mode != IWL_PLAT_PM_MODE_DISABLED) {
@@ -1078,8 +1068,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
return 0;
-out_free_drv:
- iwl_drv_stop(iwl_trans->drv);
out_free_trans:
iwl_trans_pcie_free(iwl_trans);
return ret;
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
index 59213164f35e..b513037dc066 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
@@ -106,7 +106,6 @@ struct iwl_host_cmd;
* @page: driver's pointer to the rxb page
* @invalid: rxb is in driver ownership - not owned by HW
* @vid: index of this rxb in the global table
- * @size: size used from the buffer
*/
struct iwl_rx_mem_buffer {
dma_addr_t page_dma;
@@ -114,7 +113,6 @@ struct iwl_rx_mem_buffer {
u16 vid;
bool invalid;
struct list_head list;
- u32 size;
};
/**
@@ -135,46 +133,32 @@ struct isr_statistics {
u32 unhandled;
};
-#define IWL_RX_TD_TYPE_MSK 0xff000000
-#define IWL_RX_TD_SIZE_MSK 0x00ffffff
-#define IWL_RX_TD_SIZE_2K BIT(11)
-#define IWL_RX_TD_TYPE 0
-
/**
* struct iwl_rx_transfer_desc - transfer descriptor
- * @type_n_size: buffer type (bit 0: external buff valid,
- * bit 1: optional footer valid, bit 2-7: reserved)
- * and buffer size
* @addr: ptr to free buffer start address
* @rbid: unique tag of the buffer
* @reserved: reserved
*/
struct iwl_rx_transfer_desc {
- __le32 type_n_size;
- __le64 addr;
__le16 rbid;
- __le16 reserved;
+ __le16 reserved[3];
+ __le64 addr;
} __packed;
-#define IWL_RX_CD_SIZE 0xffffff00
+#define IWL_RX_CD_FLAGS_FRAGMENTED BIT(0)
/**
* struct iwl_rx_completion_desc - completion descriptor
- * @type: buffer type (bit 0: external buff valid,
- * bit 1: optional footer valid, bit 2-7: reserved)
- * @status: status of the completion
* @reserved1: reserved
* @rbid: unique tag of the received buffer
- * @size: buffer size, masked by IWL_RX_CD_SIZE
+ * @flags: flags (0: fragmented, all others: reserved)
* @reserved2: reserved
*/
struct iwl_rx_completion_desc {
- u8 type;
- u8 status;
- __le16 reserved1;
+ __le32 reserved1;
__le16 rbid;
- __le32 size;
- u8 reserved2[22];
+ u8 flags;
+ u8 reserved2[25];
} __packed;
/**
@@ -306,10 +290,6 @@ struct iwl_cmd_meta {
u32 tbs;
};
-
-#define TFD_TX_CMD_SLOTS 256
-#define TFD_CMD_SLOTS 32
-
/*
* The FH will write back to the first TB only, so we need to copy some data
* into the buffer regardless of whether it should be mapped or not.
@@ -556,7 +536,7 @@ struct iwl_trans_pcie {
int ict_index;
bool use_ict;
bool is_down, opmode_down;
- bool debug_rfkill;
+ s8 debug_rfkill;
struct isr_statistics isr_stats;
spinlock_t irq_lock;
@@ -1002,7 +982,7 @@ static inline bool iwl_is_rfkill_set(struct iwl_trans *trans)
lockdep_assert_held(&trans_pcie->mutex);
- if (trans_pcie->debug_rfkill)
+ if (trans_pcie->debug_rfkill == 1)
return true;
return !(iwl_read32(trans, CSR_GP_CNTRL) &
@@ -1046,12 +1026,9 @@ void iwl_trans_pcie_dump_regs(struct iwl_trans *trans);
void iwl_trans_pcie_sync_nmi(struct iwl_trans *trans);
#ifdef CONFIG_IWLWIFI_DEBUGFS
-int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans);
+void iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans);
#else
-static inline int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans)
-{
- return 0;
-}
+static inline void iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans) { }
#endif
int iwl_pci_fw_exit_d0i3(struct iwl_trans *trans);
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c
index 8d4f0628622b..31b3591f71d1 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c
@@ -282,9 +282,8 @@ static void iwl_pcie_restock_bd(struct iwl_trans *trans,
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) {
struct iwl_rx_transfer_desc *bd = rxq->bd;
- bd[rxq->write].type_n_size =
- cpu_to_le32((IWL_RX_TD_TYPE & IWL_RX_TD_TYPE_MSK) |
- ((IWL_RX_TD_SIZE_2K >> 8) & IWL_RX_TD_SIZE_MSK));
+ BUILD_BUG_ON(sizeof(*bd) != 2 * sizeof(u64));
+
bd[rxq->write].addr = cpu_to_le64(rxb->page_dma);
bd[rxq->write].rbid = cpu_to_le16(rxb->vid);
} else {
@@ -435,7 +434,7 @@ static struct page *iwl_pcie_rx_alloc_page(struct iwl_trans *trans,
/*
* Issue an error if we don't have enough pre-allocated
* buffers.
-` */
+ */
if (!(gfp_mask & __GFP_NOWARN) && net_ratelimit())
IWL_CRIT(trans,
"Failed to alloc_pages\n");
@@ -1265,9 +1264,6 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans,
.truesize = max_len,
};
- if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560)
- rxcb.status = rxq->cd[i].status;
-
pkt = rxb_addr(&rxcb);
if (pkt->len_n_flags == cpu_to_le32(FH_RSCSR_FRAME_INVALID)) {
@@ -1394,6 +1390,8 @@ static struct iwl_rx_mem_buffer *iwl_pcie_get_rxb(struct iwl_trans *trans,
struct iwl_rx_mem_buffer *rxb;
u16 vid;
+ BUILD_BUG_ON(sizeof(struct iwl_rx_completion_desc) != 32);
+
if (!trans->cfg->mq_rx_supported) {
rxb = rxq->queue[i];
rxq->queue[i] = NULL;
@@ -1415,9 +1413,6 @@ static struct iwl_rx_mem_buffer *iwl_pcie_get_rxb(struct iwl_trans *trans,
IWL_DEBUG_RX(trans, "Got virtual RB ID %u\n", (u32)rxb->vid);
- if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560)
- rxb->size = le32_to_cpu(rxq->cd[i].size) & IWL_RX_CD_SIZE;
-
rxb->invalid = true;
return rxb;
@@ -1434,10 +1429,15 @@ out_err:
static void iwl_pcie_rx_handle(struct iwl_trans *trans, int queue)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwl_rxq *rxq = &trans_pcie->rxq[queue];
+ struct iwl_rxq *rxq;
u32 r, i, count = 0;
bool emergency = false;
+ if (WARN_ON_ONCE(!trans_pcie->rxq || !trans_pcie->rxq[queue].bd))
+ return;
+
+ rxq = &trans_pcie->rxq[queue];
+
restart:
spin_lock(&rxq->lock);
/* uCode's read index (stored in shared DRAM) indicates the last Rx
@@ -2212,6 +2212,7 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id)
"Hardware error detected. Restarting.\n");
isr_stats->hw++;
+ trans->hw_error = true;
iwl_pcie_irq_handle_error(trans);
}
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c
index 9c203ca75de9..8507a7bdcfdd 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c
@@ -6,7 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -20,7 +20,7 @@
* BSD LICENSE
*
* Copyright(c) 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -234,7 +234,8 @@ void iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans, bool low_power)
static int iwl_pcie_gen2_nic_init(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- int queue_size = max_t(u32, TFD_CMD_SLOTS, trans->cfg->min_txq_size);
+ int queue_size = max_t(u32, IWL_CMD_QUEUE_SIZE,
+ trans->cfg->min_txq_size);
/* TODO: most of the logic can be removed in A0 - but not in Z0 */
spin_lock(&trans_pcie->irq_lock);
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
index 4f5eec7e44bd..803fcbac4152 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
@@ -896,6 +896,8 @@ void iwl_pcie_apply_destination(struct iwl_trans *trans)
if (!trans->num_blocks)
return;
+ IWL_DEBUG_FW(trans,
+ "WRT: applying DRAM buffer[0] destination\n");
iwl_write_umac_prph(trans, MON_BUFF_BASE_ADDR_VER2,
trans->fw_mon[0].physical >>
MON_BUFF_SHIFT_VER2);
@@ -2441,9 +2443,8 @@ void iwl_pcie_dump_csr(struct iwl_trans *trans)
#ifdef CONFIG_IWLWIFI_DEBUGFS
/* create and remove of files */
#define DEBUGFS_ADD_FILE(name, parent, mode) do { \
- if (!debugfs_create_file(#name, mode, parent, trans, \
- &iwl_dbgfs_##name##_ops)) \
- goto err; \
+ debugfs_create_file(#name, mode, parent, trans, \
+ &iwl_dbgfs_##name##_ops); \
} while (0)
/* file operation */
@@ -2686,16 +2687,17 @@ static ssize_t iwl_dbgfs_rfkill_write(struct file *file,
{
struct iwl_trans *trans = file->private_data;
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- bool old = trans_pcie->debug_rfkill;
+ bool new_value;
int ret;
- ret = kstrtobool_from_user(user_buf, count, &trans_pcie->debug_rfkill);
+ ret = kstrtobool_from_user(user_buf, count, &new_value);
if (ret)
return ret;
- if (old == trans_pcie->debug_rfkill)
+ if (new_value == trans_pcie->debug_rfkill)
return count;
IWL_WARN(trans, "changing debug rfkill %d->%d\n",
- old, trans_pcie->debug_rfkill);
+ trans_pcie->debug_rfkill, new_value);
+ trans_pcie->debug_rfkill = new_value;
iwl_pcie_handle_rfkill_irq(trans);
return count;
@@ -2846,7 +2848,7 @@ static const struct file_operations iwl_dbgfs_monitor_data_ops = {
};
/* Create the debugfs files and directories */
-int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans)
+void iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans)
{
struct dentry *dir = trans->dbgfs_dir;
@@ -2857,11 +2859,6 @@ int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans)
DEBUGFS_ADD_FILE(fh_reg, dir, 0400);
DEBUGFS_ADD_FILE(rfkill, dir, 0600);
DEBUGFS_ADD_FILE(monitor_data, dir, 0400);
- return 0;
-
-err:
- IWL_ERR(trans, "failed to create the trans debugfs entry\n");
- return -ENOMEM;
}
static void iwl_trans_pcie_debugfs_cleanup(struct iwl_trans *trans)
@@ -3011,10 +3008,14 @@ static void
iwl_trans_pcie_dump_pointers(struct iwl_trans *trans,
struct iwl_fw_error_dump_fw_mon *fw_mon_data)
{
- u32 base, write_ptr, wrap_cnt;
+ u32 base, base_high, write_ptr, write_ptr_val, wrap_cnt;
- /* If there was a dest TLV - use the values from there */
- if (trans->ini_valid) {
+ if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
+ base = DBGC_CUR_DBGBUF_BASE_ADDR_LSB;
+ base_high = DBGC_CUR_DBGBUF_BASE_ADDR_MSB;
+ write_ptr = DBGC_CUR_DBGBUF_STATUS;
+ wrap_cnt = DBGC_DBGBUF_WRAP_AROUND;
+ } else if (trans->ini_valid) {
base = iwl_umac_prph(trans, MON_BUFF_BASE_ADDR_VER2);
write_ptr = iwl_umac_prph(trans, MON_BUFF_WRPTR_VER2);
wrap_cnt = iwl_umac_prph(trans, MON_BUFF_CYCLE_CNT_VER2);
@@ -3027,12 +3028,18 @@ iwl_trans_pcie_dump_pointers(struct iwl_trans *trans,
write_ptr = MON_BUFF_WRPTR;
wrap_cnt = MON_BUFF_CYCLE_CNT;
}
- fw_mon_data->fw_mon_wr_ptr =
- cpu_to_le32(iwl_read_prph(trans, write_ptr));
+
+ write_ptr_val = iwl_read_prph(trans, write_ptr);
fw_mon_data->fw_mon_cycle_cnt =
cpu_to_le32(iwl_read_prph(trans, wrap_cnt));
fw_mon_data->fw_mon_base_ptr =
cpu_to_le32(iwl_read_prph(trans, base));
+ if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
+ fw_mon_data->fw_mon_base_high_ptr =
+ cpu_to_le32(iwl_read_prph(trans, base_high));
+ write_ptr_val &= DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK;
+ }
+ fw_mon_data->fw_mon_wr_ptr = cpu_to_le32(write_ptr_val);
}
static u32
@@ -3043,9 +3050,10 @@ iwl_trans_pcie_dump_monitor(struct iwl_trans *trans,
u32 len = 0;
if ((trans->num_blocks &&
- trans->cfg->device_family == IWL_DEVICE_FAMILY_7000) ||
- (trans->dbg_dest_tlv && !trans->ini_valid) ||
- (trans->ini_valid && trans->num_blocks)) {
+ (trans->cfg->device_family == IWL_DEVICE_FAMILY_7000 ||
+ trans->cfg->device_family >= IWL_DEVICE_FAMILY_AX210 ||
+ trans->ini_valid)) ||
+ (trans->dbg_dest_tlv && !trans->ini_valid)) {
struct iwl_fw_error_dump_fw_mon *fw_mon_data;
(*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_FW_MONITOR);
@@ -3164,8 +3172,10 @@ static struct iwl_trans_dump_data
len = sizeof(*dump_data);
/* host commands */
- len += sizeof(*data) +
- cmdq->n_window * (sizeof(*txcmd) + TFD_MAX_PAYLOAD_SIZE);
+ if (dump_mask & BIT(IWL_FW_ERROR_DUMP_TXCMD))
+ len += sizeof(*data) +
+ cmdq->n_window * (sizeof(*txcmd) +
+ TFD_MAX_PAYLOAD_SIZE);
/* FW monitor */
if (dump_mask & BIT(IWL_FW_ERROR_DUMP_FW_MONITOR))
@@ -3411,7 +3421,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
ret = -ENOMEM;
goto out_no_pci;
}
-
+ trans_pcie->debug_rfkill = -1;
if (!cfg->base_params->pcie_l1_allowed) {
/*
@@ -3539,6 +3549,9 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
} else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) ==
CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_GF)) {
trans->cfg = &iwlax210_2ax_cfg_so_gf_a0;
+ } else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) ==
+ CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_GF4)) {
+ trans->cfg = &iwlax210_2ax_cfg_so_gf4_a0;
}
} else if (cfg == &iwl_ax101_cfg_qu_hr) {
if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) ==
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c
index 7be73e2c4681..fa4245d0d4a8 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c
@@ -996,10 +996,11 @@ static int iwl_pcie_tx_alloc(struct iwl_trans *trans)
bool cmd_queue = (txq_id == trans_pcie->cmd_queue);
if (cmd_queue)
- slots_num = max_t(u32, TFD_CMD_SLOTS,
+ slots_num = max_t(u32, IWL_CMD_QUEUE_SIZE,
trans->cfg->min_txq_size);
else
- slots_num = TFD_TX_CMD_SLOTS;
+ slots_num = max_t(u32, IWL_DEFAULT_QUEUE_SIZE,
+ trans->cfg->min_256_ba_txq_size);
trans_pcie->txq[txq_id] = &trans_pcie->txq_memory[txq_id];
ret = iwl_pcie_txq_alloc(trans, trans_pcie->txq[txq_id],
slots_num, cmd_queue);
@@ -1049,10 +1050,11 @@ int iwl_pcie_tx_init(struct iwl_trans *trans)
bool cmd_queue = (txq_id == trans_pcie->cmd_queue);
if (cmd_queue)
- slots_num = max_t(u32, TFD_CMD_SLOTS,
+ slots_num = max_t(u32, IWL_CMD_QUEUE_SIZE,
trans->cfg->min_txq_size);
else
- slots_num = TFD_TX_CMD_SLOTS;
+ slots_num = max_t(u32, IWL_DEFAULT_QUEUE_SIZE,
+ trans->cfg->min_256_ba_txq_size);
ret = iwl_pcie_txq_init(trans, trans_pcie->txq[txq_id],
slots_num, cmd_queue);
if (ret) {