diff options
author | David S. Miller <davem@davemloft.net> | 2019-05-05 19:20:53 +0200 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2019-05-05 19:20:53 +0200 |
commit | 6ffe0acc935f344eb0b35da07c034d5122222e77 (patch) | |
tree | e9aa88316da2f2c7b4685308a5e3b88154bf5620 /drivers/net/wireless/intel/iwlwifi | |
parent | drivers: net: davinci_mdio: fix return value check in davinci_mdio_probe() (diff) | |
parent | rtw88: add license for Makefile (diff) | |
download | linux-6ffe0acc935f344eb0b35da07c034d5122222e77.tar.xz linux-6ffe0acc935f344eb0b35da07c034d5122222e77.zip |
Merge tag 'wireless-drivers-next-for-davem-2019-05-03' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next
Kalle Valo says:
====================
wireless-drivers-next patches for 5.2
Most likely the last patchset of new feature for 5.2, and this time we
have quite a lot of new features. Most obvious being rtw88 from
Realtek which supports RTL8822BE and RTL8822CE 802.11ac devices. We
have also new hardware support for existing drivers and improvements.
There's one conflict in iwlwifi, my example conflict resolution below.
Major changes:
iwlwifi
* bump the 20000-series FW API version
* work on new hardware continues
* RTT confidence indication support for Fine Timing Measurement (FTM)
* an improvement in HE (802.11ax) rate-scaling
* add command version parsing from the fimware TLVs
* add support for a new WoWLAN patterns firmware API
rsi
* add support for rs9116
mwifiex
* add support for SD8987
brcmfmac
* add quirk for ACEPC T8 and T11 mini PCs
rt2x00
* add RT3883 support
qtnfmac
* fix debugfs interface to support multiple cards
rtw88
* new driver
mt76
* share more code across drivers
* add support for MT7615 chipset
* rework DMA API
* tx/rx performance optimizations
* use NAPI for tx cleanup on mt76x02
* AP mode support for USB devices
* USB stability fixes
* tx power handling fixes for 76x2
* endian fixes
Conflicts:
There's a trivial conflict in
drivers/net/wireless/intel/iwlwifi/fw/file.h, just leave
IWL_UCODE_TLV_FW_FSEQ_VERSION to the file. 'git diff' output should be
just empty:
diff --cc drivers/net/wireless/intel/iwlwifi/fw/file.h
index cd622af90077,b0671e16e1ce..000000000000
--- a/drivers/net/wireless/intel/iwlwifi/fw/file.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/file.h
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi')
33 files changed, 591 insertions, 122 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c index 17b34f6e4515..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-" @@ -105,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) \ @@ -420,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, @@ -471,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/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 af1e3d08c179..f4202bc231a6 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h @@ -473,6 +473,8 @@ enum iwl_fw_ini_debug_flow { * @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 { @@ -490,6 +492,8 @@ enum iwl_fw_ini_region_type { 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/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 be72529cc789..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); @@ -909,11 +917,8 @@ iwl_fw_error_dump_file(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, @@ -1685,6 +1690,9 @@ iwl_dump_ini_mem(struct iwl_fw_runtime *fwrt, !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); @@ -1698,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; @@ -1708,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; @@ -1734,7 +1744,15 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt, 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; + } + + /* 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)) { @@ -1743,6 +1761,8 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt, case IWL_FW_INI_REGION_PERIPHERY_PHY: case IWL_FW_INI_REGION_PERIPHERY_AUX: 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: @@ -1804,6 +1824,8 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt, switch (le32_to_cpu(reg->region_type)) { case IWL_FW_INI_REGION_DEVICE_MEMORY: + 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; @@ -2108,6 +2130,12 @@ int _iwl_fw_dbg_ini_collect(struct iwl_fw_runtime *fwrt, if (test_and_set_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status)) return -EBUSY; + 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); @@ -2117,14 +2145,17 @@ int _iwl_fw_dbg_ini_collect(struct iwl_fw_runtime *fwrt, 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; } + if (test_and_set_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status)) + return -EBUSY; + fwrt->dump.ini_trig_id = id; - IWL_WARN(fwrt, "Collecting data: ini trigger %d fired.\n", id); + IWL_WARN(fwrt, "WRT: collecting data: ini trigger %d fired.\n", id); schedule_delayed_work(&fwrt->dump.wk, usecs_to_jiffies(delay)); @@ -2262,12 +2293,12 @@ void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt) iwl_fw_dbg_stop_recording(fwrt, ¶ms); - IWL_DEBUG_INFO(fwrt, "WRT dump start\n"); + 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_INFO(fwrt, "WRT dump done\n"); + 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) && @@ -2337,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, @@ -2365,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; } @@ -2388,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); @@ -2399,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; @@ -2415,6 +2456,10 @@ static void iwl_fw_dbg_send_hcmd(struct iwl_fw_runtime *fwrt, 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); } @@ -2424,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; @@ -2449,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); @@ -2468,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; @@ -2492,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]; @@ -2500,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; @@ -2518,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; } @@ -2528,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); @@ -2541,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; @@ -2570,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); @@ -2585,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: @@ -2599,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; @@ -2617,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 cccf91db74c4..2a9e560a906b 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h @@ -385,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); } @@ -468,4 +470,5 @@ static inline void iwl_fw_error_collect(struct iwl_fw_runtime *fwrt) } } +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 260097c75427..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]; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/file.h b/drivers/net/wireless/intel/iwlwifi/fw/file.h index cd622af90077..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, @@ -314,6 +316,8 @@ enum iwl_ucode_tlv_api { 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__ @@ -940,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 88a558e082a3..a6402a0b3854 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h @@ -146,6 +146,7 @@ struct iwl_fw_runtime { 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 0a93383791f3..f3e69edf8907 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h @@ -578,7 +578,6 @@ 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; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h index 2b98ecdcf301..553554846009 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h @@ -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) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c index 0e8664375298..ba66f7fba064 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c @@ -139,7 +139,7 @@ void iwl_alloc_dbg_tlv(struct iwl_trans *trans, size_t len, const u8 *data, if (le32_to_cpu(hdr->tlv_version) != 1) continue; - IWL_DEBUG_FW(trans, "Read TLV %x, apply point %d\n", + 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 40985dc552b8..d87a6bb3e456 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c @@ -1496,7 +1496,7 @@ struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans, (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, v4); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c index 83fd7f93d9f5..60f5d337f16d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c @@ -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; 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 fcec25b7b679..53c217af13c8 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c @@ -1570,7 +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_sync(&mvmvif->csa_work); + cancel_delayed_work(&mvmvif->csa_work); ieee80211_chswitch_done(vif, true); break; default: diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index 8da9e5572fcf..acd2fda12466 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -1261,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 diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c index 79f9eaf8dd1b..659e21b2d4e7 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c @@ -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); @@ -383,13 +414,13 @@ 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)), .sgi_ch_width_supp = rs_fw_sgi_cw_support(sta), .max_mpdu_len = cpu_to_le16(max_amsdu_len), @@ -402,7 +433,6 @@ 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); /* diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index eb452e9dce05..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); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c index 50314018d157..4d34e5ab1bff 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c @@ -234,7 +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_sync(&mvmvif->csa_work); + cancel_delayed_work(&mvmvif->csa_work); ieee80211_chswitch_done(te_data->vif, true); break; default: 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 70d0fa0eae2f..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)}, diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h index 4bf745c7bd6c..b513037dc066 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h @@ -290,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. @@ -540,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; @@ -986,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) & diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c index 69fcfa930791..31b3591f71d1 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c @@ -434,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"); @@ -1429,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 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 cccb8bbd7ea7..b55fa9efa1e3 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); @@ -2686,16 +2688,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; @@ -3419,7 +3422,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) { /* diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c index 4a9522fb682f..fa4245d0d4a8 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c @@ -996,10 +996,10 @@ 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 = max_t(u32, 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], @@ -1050,10 +1050,10 @@ 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 = max_t(u32, 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); |