aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2014-07-23 13:06:17 -0400
committerJohn W. Linville <linville@tuxdriver.com>2014-07-23 13:06:17 -0400
commitd878b3af675da14917a249e33addb789d54d3094 (patch)
tree10c02a67e231993f74ab32bc0cdb51a74643b48e /drivers/net/wireless
parent16e754535a69152c12494da18eb3ea7947f5a434 (diff)
parentf697267f827516fba4d0c325ed1db1e72f402f11 (diff)
Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/iwlwifi/Kconfig25
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-8000.c4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-config.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h17
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-modparams.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans.h21
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/coex.c193
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/coex_legacy.c119
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/debugfs.c104
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api.h67
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c15
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mac80211.c383
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mvm.h52
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/nvm.c4
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/ops.c14
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/sta.c24
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/time-event.c89
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/tt.c12
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/tx.c10
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/trans.c202
21 files changed, 966 insertions, 395 deletions
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
index 7fd50428b934..6451d2b6abcf 100644
--- a/drivers/net/wireless/iwlwifi/Kconfig
+++ b/drivers/net/wireless/iwlwifi/Kconfig
@@ -20,16 +20,17 @@ config IWLWIFI
20 Intel 2000 Series Wi-Fi Adapters 20 Intel 2000 Series Wi-Fi Adapters
21 Intel 7260 Wi-Fi Adapter 21 Intel 7260 Wi-Fi Adapter
22 Intel 3160 Wi-Fi Adapter 22 Intel 3160 Wi-Fi Adapter
23 Intel 7265 Wi-Fi Adapter
23 24
24 25
25 This driver uses the kernel's mac80211 subsystem. 26 This driver uses the kernel's mac80211 subsystem.
26 27
27 In order to use this driver, you will need a microcode (uCode) 28 In order to use this driver, you will need a firmware
28 image for it. You can obtain the microcode from: 29 image for it. You can obtain the microcode from:
29 30
30 <http://intellinuxwireless.org/>. 31 <http://wireless.kernel.org/en/users/Drivers/iwlwifi>.
31 32
32 The microcode is typically installed in /lib/firmware. You can 33 The firmware is typically installed in /lib/firmware. You can
33 look in the hotplug script /etc/hotplug/firmware.agent to 34 look in the hotplug script /etc/hotplug/firmware.agent to
34 determine which directory FIRMWARE_DIR is set to when the script 35 determine which directory FIRMWARE_DIR is set to when the script
35 runs. 36 runs.
@@ -39,9 +40,10 @@ config IWLWIFI
39 say M here and read <file:Documentation/kbuild/modules.txt>. The 40 say M here and read <file:Documentation/kbuild/modules.txt>. The
40 module will be called iwlwifi. 41 module will be called iwlwifi.
41 42
43if IWLWIFI
44
42config IWLWIFI_LEDS 45config IWLWIFI_LEDS
43 bool 46 bool
44 depends on IWLWIFI
45 depends on LEDS_CLASS=y || LEDS_CLASS=IWLWIFI 47 depends on LEDS_CLASS=y || LEDS_CLASS=IWLWIFI
46 select LEDS_TRIGGERS 48 select LEDS_TRIGGERS
47 select MAC80211_LEDS 49 select MAC80211_LEDS
@@ -49,7 +51,7 @@ config IWLWIFI_LEDS
49 51
50config IWLDVM 52config IWLDVM
51 tristate "Intel Wireless WiFi DVM Firmware support" 53 tristate "Intel Wireless WiFi DVM Firmware support"
52 depends on IWLWIFI 54 depends on m
53 default IWLWIFI 55 default IWLWIFI
54 help 56 help
55 This is the driver that supports the DVM firmware which is 57 This is the driver that supports the DVM firmware which is
@@ -58,7 +60,7 @@ config IWLDVM
58 60
59config IWLMVM 61config IWLMVM
60 tristate "Intel Wireless WiFi MVM Firmware support" 62 tristate "Intel Wireless WiFi MVM Firmware support"
61 depends on IWLWIFI 63 depends on m
62 help 64 help
63 This is the driver that supports the MVM firmware which is 65 This is the driver that supports the MVM firmware which is
64 currently only available for 7260 and 3160 devices. 66 currently only available for 7260 and 3160 devices.
@@ -70,7 +72,7 @@ config IWLWIFI_OPMODE_MODULAR
70 default y if IWLMVM=m 72 default y if IWLMVM=m
71 73
72comment "WARNING: iwlwifi is useless without IWLDVM or IWLMVM" 74comment "WARNING: iwlwifi is useless without IWLDVM or IWLMVM"
73 depends on IWLWIFI && IWLDVM=n && IWLMVM=n 75 depends on IWLDVM=n && IWLMVM=n
74 76
75config IWLWIFI_BCAST_FILTERING 77config IWLWIFI_BCAST_FILTERING
76 bool "Enable broadcast filtering" 78 bool "Enable broadcast filtering"
@@ -86,11 +88,9 @@ config IWLWIFI_BCAST_FILTERING
86 expect incoming broadcasts for their normal operations. 88 expect incoming broadcasts for their normal operations.
87 89
88menu "Debugging Options" 90menu "Debugging Options"
89 depends on IWLWIFI
90 91
91config IWLWIFI_DEBUG 92config IWLWIFI_DEBUG
92 bool "Enable full debugging output in the iwlwifi driver" 93 bool "Enable full debugging output in the iwlwifi driver"
93 depends on IWLWIFI
94 ---help--- 94 ---help---
95 This option will enable debug tracing output for the iwlwifi drivers 95 This option will enable debug tracing output for the iwlwifi drivers
96 96
@@ -115,7 +115,7 @@ config IWLWIFI_DEBUG
115 115
116config IWLWIFI_DEBUGFS 116config IWLWIFI_DEBUGFS
117 bool "iwlwifi debugfs support" 117 bool "iwlwifi debugfs support"
118 depends on IWLWIFI && MAC80211_DEBUGFS 118 depends on MAC80211_DEBUGFS
119 ---help--- 119 ---help---
120 Enable creation of debugfs files for the iwlwifi drivers. This 120 Enable creation of debugfs files for the iwlwifi drivers. This
121 is a low-impact option that allows getting insight into the 121 is a low-impact option that allows getting insight into the
@@ -123,13 +123,12 @@ config IWLWIFI_DEBUGFS
123 123
124config IWLWIFI_DEBUG_EXPERIMENTAL_UCODE 124config IWLWIFI_DEBUG_EXPERIMENTAL_UCODE
125 bool "Experimental uCode support" 125 bool "Experimental uCode support"
126 depends on IWLWIFI && IWLWIFI_DEBUG 126 depends on IWLWIFI_DEBUG
127 ---help--- 127 ---help---
128 Enable use of experimental ucode for testing and debugging. 128 Enable use of experimental ucode for testing and debugging.
129 129
130config IWLWIFI_DEVICE_TRACING 130config IWLWIFI_DEVICE_TRACING
131 bool "iwlwifi device access tracing" 131 bool "iwlwifi device access tracing"
132 depends on IWLWIFI
133 depends on EVENT_TRACING 132 depends on EVENT_TRACING
134 help 133 help
135 Say Y here to trace all commands, including TX frames and IO 134 Say Y here to trace all commands, including TX frames and IO
@@ -145,3 +144,5 @@ config IWLWIFI_DEVICE_TRACING
145 If unsure, say Y so we can help you better when problems 144 If unsure, say Y so we can help you better when problems
146 occur. 145 occur.
147endmenu 146endmenu
147
148endif
diff --git a/drivers/net/wireless/iwlwifi/iwl-8000.c b/drivers/net/wireless/iwlwifi/iwl-8000.c
index 51486cc9d943..44b19e015102 100644
--- a/drivers/net/wireless/iwlwifi/iwl-8000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-8000.c
@@ -85,6 +85,9 @@
85#define NVM_HW_SECTION_NUM_FAMILY_8000 10 85#define NVM_HW_SECTION_NUM_FAMILY_8000 10
86#define DEFAULT_NVM_FILE_FAMILY_8000 "iwl_nvm_8000.bin" 86#define DEFAULT_NVM_FILE_FAMILY_8000 "iwl_nvm_8000.bin"
87 87
88/* Max SDIO RX aggregation size of the ADDBA request/response */
89#define MAX_RX_AGG_SIZE_8260_SDIO 28
90
88static const struct iwl_base_params iwl8000_base_params = { 91static const struct iwl_base_params iwl8000_base_params = {
89 .eeprom_size = OTP_LOW_IMAGE_SIZE_FAMILY_8000, 92 .eeprom_size = OTP_LOW_IMAGE_SIZE_FAMILY_8000,
90 .num_of_queues = IWLAGN_NUM_QUEUES, 93 .num_of_queues = IWLAGN_NUM_QUEUES,
@@ -129,6 +132,7 @@ const struct iwl_cfg iwl8260_2ac_sdio_cfg = {
129 .nvm_ver = IWL8000_NVM_VERSION, 132 .nvm_ver = IWL8000_NVM_VERSION,
130 .nvm_calib_ver = IWL8000_TX_POWER_VERSION, 133 .nvm_calib_ver = IWL8000_TX_POWER_VERSION,
131 .default_nvm_file = DEFAULT_NVM_FILE_FAMILY_8000, 134 .default_nvm_file = DEFAULT_NVM_FILE_FAMILY_8000,
135 .max_rx_agg_size = MAX_RX_AGG_SIZE_8260_SDIO,
132}; 136};
133 137
134MODULE_FIRMWARE(IWL8000_MODULE_FIRMWARE(IWL8000_UCODE_API_OK)); 138MODULE_FIRMWARE(IWL8000_MODULE_FIRMWARE(IWL8000_UCODE_API_OK));
diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h
index 034c2fc4b69f..8da596db9abe 100644
--- a/drivers/net/wireless/iwlwifi/iwl-config.h
+++ b/drivers/net/wireless/iwlwifi/iwl-config.h
@@ -240,6 +240,7 @@ struct iwl_pwr_tx_backoff {
240 * @d0i3: device uses d0i3 instead of d3 240 * @d0i3: device uses d0i3 instead of d3
241 * @nvm_hw_section_num: the ID of the HW NVM section 241 * @nvm_hw_section_num: the ID of the HW NVM section
242 * @pwr_tx_backoffs: translation table between power limits and backoffs 242 * @pwr_tx_backoffs: translation table between power limits and backoffs
243 * @max_rx_agg_size: max RX aggregation size of the ADDBA request/response
243 * 244 *
244 * We enable the driver to be backward compatible wrt. hardware features. 245 * We enable the driver to be backward compatible wrt. hardware features.
245 * API differences in uCode shouldn't be handled here but through TLVs 246 * API differences in uCode shouldn't be handled here but through TLVs
@@ -276,6 +277,7 @@ struct iwl_cfg {
276 const struct iwl_pwr_tx_backoff *pwr_tx_backoffs; 277 const struct iwl_pwr_tx_backoff *pwr_tx_backoffs;
277 bool no_power_up_nic_in_init; 278 bool no_power_up_nic_in_init;
278 const char *default_nvm_file; 279 const char *default_nvm_file;
280 unsigned int max_rx_agg_size;
279}; 281};
280 282
281/* 283/*
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h b/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h
index c39a0b899e83..de5994a776c7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h
@@ -70,21 +70,24 @@
70/** 70/**
71 * enum iwl_fw_error_dump_type - types of data in the dump file 71 * enum iwl_fw_error_dump_type - types of data in the dump file
72 * @IWL_FW_ERROR_DUMP_SRAM: 72 * @IWL_FW_ERROR_DUMP_SRAM:
73 * @IWL_FW_ERROR_DUMP_REG: 73 * @IWL_FW_ERROR_DUMP_CSR: Control Status Registers - from offset 0
74 * @IWL_FW_ERROR_DUMP_RXF: 74 * @IWL_FW_ERROR_DUMP_RXF:
75 * @IWL_FW_ERROR_DUMP_TXCMD: last TX command data, structured as 75 * @IWL_FW_ERROR_DUMP_TXCMD: last TX command data, structured as
76 * &struct iwl_fw_error_dump_txcmd packets 76 * &struct iwl_fw_error_dump_txcmd packets
77 * @IWL_FW_ERROR_DUMP_DEV_FW_INFO: struct %iwl_fw_error_dump_info 77 * @IWL_FW_ERROR_DUMP_DEV_FW_INFO: struct %iwl_fw_error_dump_info
78 * info on the device / firmware. 78 * info on the device / firmware.
79 * @IWL_FW_ERROR_DUMP_FW_MONITOR: firmware monitor 79 * @IWL_FW_ERROR_DUMP_FW_MONITOR: firmware monitor
80 * @IWL_FW_ERROR_DUMP_PRPH: range of periphery registers - there can be several
81 * sections like this in a single file.
80 */ 82 */
81enum iwl_fw_error_dump_type { 83enum iwl_fw_error_dump_type {
82 IWL_FW_ERROR_DUMP_SRAM = 0, 84 IWL_FW_ERROR_DUMP_SRAM = 0,
83 IWL_FW_ERROR_DUMP_REG = 1, 85 IWL_FW_ERROR_DUMP_CSR = 1,
84 IWL_FW_ERROR_DUMP_RXF = 2, 86 IWL_FW_ERROR_DUMP_RXF = 2,
85 IWL_FW_ERROR_DUMP_TXCMD = 3, 87 IWL_FW_ERROR_DUMP_TXCMD = 3,
86 IWL_FW_ERROR_DUMP_DEV_FW_INFO = 4, 88 IWL_FW_ERROR_DUMP_DEV_FW_INFO = 4,
87 IWL_FW_ERROR_DUMP_FW_MONITOR = 5, 89 IWL_FW_ERROR_DUMP_FW_MONITOR = 5,
90 IWL_FW_ERROR_DUMP_PRPH = 6,
88 91
89 IWL_FW_ERROR_DUMP_MAX, 92 IWL_FW_ERROR_DUMP_MAX,
90}; 93};
@@ -163,6 +166,16 @@ struct iwl_fw_error_dump_fw_mon {
163} __packed; 166} __packed;
164 167
165/** 168/**
169 * struct iwl_fw_error_dump_prph - periphery registers data
170 * @prph_start: address of the first register in this chunk
171 * @data: the content of the registers
172 */
173struct iwl_fw_error_dump_prph {
174 __le32 prph_start;
175 __le32 data[];
176};
177
178/**
166 * iwl_fw_error_next_data - advance fw error dump data pointer 179 * iwl_fw_error_next_data - advance fw error dump data pointer
167 * @data: previous data block 180 * @data: previous data block
168 * Returns: next data block 181 * Returns: next data block
diff --git a/drivers/net/wireless/iwlwifi/iwl-modparams.h b/drivers/net/wireless/iwlwifi/iwl-modparams.h
index f2d39cb011fc..71507cf490e6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-modparams.h
+++ b/drivers/net/wireless/iwlwifi/iwl-modparams.h
@@ -99,7 +99,7 @@ enum iwl_disable_11n {
99 * @wd_disable: disable stuck queue check, default = 1 99 * @wd_disable: disable stuck queue check, default = 1
100 * @bt_coex_active: enable bt coex, default = true 100 * @bt_coex_active: enable bt coex, default = true
101 * @led_mode: system default, default = 0 101 * @led_mode: system default, default = 0
102 * @power_save: disable power save, default = false 102 * @power_save: enable power save, default = false
103 * @power_level: power level, default = 1 103 * @power_level: power level, default = 1
104 * @debug_level: levels are IWL_DL_* 104 * @debug_level: levels are IWL_DL_*
105 * @ant_coupling: antenna coupling in dB, default = 0 105 * @ant_coupling: antenna coupling in dB, default = 0
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h
index 34d49e171fb4..656371a668da 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.h
@@ -394,6 +394,11 @@ struct iwl_trans_config {
394 const char *const *command_names; 394 const char *const *command_names;
395}; 395};
396 396
397struct iwl_trans_dump_data {
398 u32 len;
399 u8 data[];
400};
401
397struct iwl_trans; 402struct iwl_trans;
398 403
399/** 404/**
@@ -461,10 +466,8 @@ struct iwl_trans;
461 * @unref: release a reference previously taken with @ref. Note that 466 * @unref: release a reference previously taken with @ref. Note that
462 * initially the reference count is 1, making an initial @unref 467 * initially the reference count is 1, making an initial @unref
463 * necessary to allow low power states. 468 * necessary to allow low power states.
464 * @dump_data: fill a data dump with debug data, maybe containing last 469 * @dump_data: return a vmalloc'ed buffer with debug data, maybe containing last
465 * TX'ed commands and similar. When called with a NULL buffer and 470 * TX'ed commands and similar. The buffer will be vfree'd by the caller.
466 * zero buffer length, provide only the (estimated) required buffer
467 * length. Return the used buffer length.
468 * Note that the transport must fill in the proper file headers. 471 * Note that the transport must fill in the proper file headers.
469 */ 472 */
470struct iwl_trans_ops { 473struct iwl_trans_ops {
@@ -518,7 +521,7 @@ struct iwl_trans_ops {
518 void (*unref)(struct iwl_trans *trans); 521 void (*unref)(struct iwl_trans *trans);
519 522
520#ifdef CONFIG_IWLWIFI_DEBUGFS 523#ifdef CONFIG_IWLWIFI_DEBUGFS
521 u32 (*dump_data)(struct iwl_trans *trans, void *buf, u32 buflen); 524 struct iwl_trans_dump_data *(*dump_data)(struct iwl_trans *trans);
522#endif 525#endif
523}; 526};
524 527
@@ -685,12 +688,12 @@ static inline void iwl_trans_unref(struct iwl_trans *trans)
685} 688}
686 689
687#ifdef CONFIG_IWLWIFI_DEBUGFS 690#ifdef CONFIG_IWLWIFI_DEBUGFS
688static inline u32 iwl_trans_dump_data(struct iwl_trans *trans, 691static inline struct iwl_trans_dump_data *
689 void *buf, u32 buflen) 692iwl_trans_dump_data(struct iwl_trans *trans)
690{ 693{
691 if (!trans->ops->dump_data) 694 if (!trans->ops->dump_data)
692 return 0; 695 return NULL;
693 return trans->ops->dump_data(trans, buf, buflen); 696 return trans->ops->dump_data(trans);
694} 697}
695#endif 698#endif
696 699
diff --git a/drivers/net/wireless/iwlwifi/mvm/coex.c b/drivers/net/wireless/iwlwifi/mvm/coex.c
index 8110fe00bf55..2291bbcaaeab 100644
--- a/drivers/net/wireless/iwlwifi/mvm/coex.c
+++ b/drivers/net/wireless/iwlwifi/mvm/coex.c
@@ -72,16 +72,56 @@
72 72
73#define BT_ANTENNA_COUPLING_THRESHOLD (30) 73#define BT_ANTENNA_COUPLING_THRESHOLD (30)
74 74
75const u32 iwl_bt_ack_kill_msk[BT_KILL_MSK_MAX] = { 75const u32 iwl_bt_ctl_kill_msk[BT_KILL_MSK_MAX] = {
76 [BT_KILL_MSK_DEFAULT] = 0xffff0000, 76 [BT_KILL_MSK_DEFAULT] = 0xfffffc00,
77 [BT_KILL_MSK_SCO_HID_A2DP] = 0xffffffff, 77 [BT_KILL_MSK_NEVER] = 0xffffffff,
78 [BT_KILL_MSK_REDUCED_TXPOW] = 0, 78 [BT_KILL_MSK_ALWAYS] = 0,
79}; 79};
80 80
81const u32 iwl_bt_cts_kill_msk[BT_KILL_MSK_MAX] = { 81const u8 iwl_bt_cts_kill_msk[BT_MAX_AG][BT_COEX_MAX_LUT] = {
82 [BT_KILL_MSK_DEFAULT] = 0xffff0000, 82 {
83 [BT_KILL_MSK_SCO_HID_A2DP] = 0xffffffff, 83 BT_KILL_MSK_ALWAYS,
84 [BT_KILL_MSK_REDUCED_TXPOW] = 0, 84 BT_KILL_MSK_ALWAYS,
85 BT_KILL_MSK_ALWAYS,
86 },
87 {
88 BT_KILL_MSK_NEVER,
89 BT_KILL_MSK_NEVER,
90 BT_KILL_MSK_NEVER,
91 },
92 {
93 BT_KILL_MSK_NEVER,
94 BT_KILL_MSK_NEVER,
95 BT_KILL_MSK_NEVER,
96 },
97 {
98 BT_KILL_MSK_DEFAULT,
99 BT_KILL_MSK_NEVER,
100 BT_KILL_MSK_DEFAULT,
101 },
102};
103
104const u8 iwl_bt_ack_kill_msk[BT_MAX_AG][BT_COEX_MAX_LUT] = {
105 {
106 BT_KILL_MSK_ALWAYS,
107 BT_KILL_MSK_ALWAYS,
108 BT_KILL_MSK_ALWAYS,
109 },
110 {
111 BT_KILL_MSK_ALWAYS,
112 BT_KILL_MSK_ALWAYS,
113 BT_KILL_MSK_ALWAYS,
114 },
115 {
116 BT_KILL_MSK_ALWAYS,
117 BT_KILL_MSK_ALWAYS,
118 BT_KILL_MSK_ALWAYS,
119 },
120 {
121 BT_KILL_MSK_DEFAULT,
122 BT_KILL_MSK_ALWAYS,
123 BT_KILL_MSK_DEFAULT,
124 },
85}; 125};
86 126
87static const __le32 iwl_bt_prio_boost[BT_COEX_BOOST_SIZE] = { 127static const __le32 iwl_bt_prio_boost[BT_COEX_BOOST_SIZE] = {
@@ -611,54 +651,43 @@ send_cmd:
611 return ret; 651 return ret;
612} 652}
613 653
614static int iwl_mvm_bt_udpate_sw_boost(struct iwl_mvm *mvm, 654static int iwl_mvm_bt_udpate_sw_boost(struct iwl_mvm *mvm)
615 bool reduced_tx_power)
616{ 655{
617 enum iwl_bt_kill_msk bt_kill_msk;
618 struct iwl_bt_coex_sw_boost_update_cmd cmd = {};
619 struct iwl_bt_coex_profile_notif *notif = &mvm->last_bt_notif; 656 struct iwl_bt_coex_profile_notif *notif = &mvm->last_bt_notif;
657 u32 primary_lut = le32_to_cpu(notif->primary_ch_lut);
658 u32 secondary_lut = le32_to_cpu(notif->secondary_ch_lut);
659 u32 ag = le32_to_cpu(notif->bt_activity_grading);
660 struct iwl_bt_coex_sw_boost_update_cmd cmd = {};
661 u8 ack_kill_msk[NUM_PHY_CTX] = {};
662 u8 cts_kill_msk[NUM_PHY_CTX] = {};
663 int i;
620 664
621 lockdep_assert_held(&mvm->mutex); 665 lockdep_assert_held(&mvm->mutex);
622 666
623 if (reduced_tx_power) { 667 ack_kill_msk[0] = iwl_bt_ack_kill_msk[ag][primary_lut];
624 /* Reduced Tx power has precedence on the type of the profile */ 668 cts_kill_msk[0] = iwl_bt_cts_kill_msk[ag][primary_lut];
625 bt_kill_msk = BT_KILL_MSK_REDUCED_TXPOW;
626 } else {
627 /* Low latency BT profile is active: give higher prio to BT */
628 if (BT_MBOX_MSG(notif, 3, SCO_STATE) ||
629 BT_MBOX_MSG(notif, 3, A2DP_STATE) ||
630 BT_MBOX_MSG(notif, 3, SNIFF_STATE))
631 bt_kill_msk = BT_KILL_MSK_SCO_HID_A2DP;
632 else
633 bt_kill_msk = BT_KILL_MSK_DEFAULT;
634 }
635 669
636 IWL_DEBUG_COEX(mvm, 670 ack_kill_msk[1] = iwl_bt_ack_kill_msk[ag][secondary_lut];
637 "Update kill_msk: %d - SCO %sactive A2DP %sactive SNIFF %sactive\n", 671 cts_kill_msk[1] = iwl_bt_cts_kill_msk[ag][secondary_lut];
638 bt_kill_msk,
639 BT_MBOX_MSG(notif, 3, SCO_STATE) ? "" : "in",
640 BT_MBOX_MSG(notif, 3, A2DP_STATE) ? "" : "in",
641 BT_MBOX_MSG(notif, 3, SNIFF_STATE) ? "" : "in");
642 672
643 /* Don't send HCMD if there is no update */ 673 /* Don't send HCMD if there is no update */
644 if (bt_kill_msk == mvm->bt_kill_msk) 674 if (!memcmp(ack_kill_msk, mvm->bt_ack_kill_msk, sizeof(ack_kill_msk)) ||
675 !memcmp(cts_kill_msk, mvm->bt_cts_kill_msk, sizeof(cts_kill_msk)))
645 return 0; 676 return 0;
646 677
647 mvm->bt_kill_msk = bt_kill_msk; 678 memcpy(mvm->bt_ack_kill_msk, ack_kill_msk,
679 sizeof(mvm->bt_ack_kill_msk));
680 memcpy(mvm->bt_cts_kill_msk, cts_kill_msk,
681 sizeof(mvm->bt_cts_kill_msk));
648 682
649 cmd.boost_values[0].kill_ack_msk = 683 BUILD_BUG_ON(ARRAY_SIZE(ack_kill_msk) < ARRAY_SIZE(cmd.boost_values));
650 cpu_to_le32(iwl_bt_ack_kill_msk[bt_kill_msk]);
651 cmd.boost_values[0].kill_cts_msk =
652 cpu_to_le32(iwl_bt_cts_kill_msk[bt_kill_msk]);
653 684
654 cmd.boost_values[1].kill_ack_msk = cmd.boost_values[0].kill_ack_msk; 685 for (i = 0; i < ARRAY_SIZE(cmd.boost_values); i++) {
655 cmd.boost_values[2].kill_cts_msk = cmd.boost_values[0].kill_cts_msk; 686 cmd.boost_values[i].kill_ack_msk =
656 cmd.boost_values[1].kill_ack_msk = cmd.boost_values[0].kill_ack_msk; 687 cpu_to_le32(iwl_bt_ctl_kill_msk[ack_kill_msk[i]]);
657 cmd.boost_values[2].kill_cts_msk = cmd.boost_values[0].kill_cts_msk; 688 cmd.boost_values[i].kill_cts_msk =
658 689 cpu_to_le32(iwl_bt_ctl_kill_msk[cts_kill_msk[i]]);
659 IWL_DEBUG_COEX(mvm, "ACK Kill msk = 0x%08x, CTS Kill msk = 0x%08x\n", 690 }
660 iwl_bt_ack_kill_msk[bt_kill_msk],
661 iwl_bt_cts_kill_msk[bt_kill_msk]);
662 691
663 return iwl_mvm_send_cmd_pdu(mvm, BT_COEX_UPDATE_SW_BOOST, 0, 692 return iwl_mvm_send_cmd_pdu(mvm, BT_COEX_UPDATE_SW_BOOST, 0,
664 sizeof(cmd), &cmd); 693 sizeof(cmd), &cmd);
@@ -700,8 +729,6 @@ static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id,
700struct iwl_bt_iterator_data { 729struct iwl_bt_iterator_data {
701 struct iwl_bt_coex_profile_notif *notif; 730 struct iwl_bt_coex_profile_notif *notif;
702 struct iwl_mvm *mvm; 731 struct iwl_mvm *mvm;
703 u32 num_bss_ifaces;
704 bool reduced_tx_power;
705 struct ieee80211_chanctx_conf *primary; 732 struct ieee80211_chanctx_conf *primary;
706 struct ieee80211_chanctx_conf *secondary; 733 struct ieee80211_chanctx_conf *secondary;
707 bool primary_ll; 734 bool primary_ll;
@@ -737,22 +764,12 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
737 764
738 switch (vif->type) { 765 switch (vif->type) {
739 case NL80211_IFTYPE_STATION: 766 case NL80211_IFTYPE_STATION:
740 /* Count BSSes vifs */
741 data->num_bss_ifaces++;
742 /* default smps_mode for BSS / P2P client is AUTOMATIC */ 767 /* default smps_mode for BSS / P2P client is AUTOMATIC */
743 smps_mode = IEEE80211_SMPS_AUTOMATIC; 768 smps_mode = IEEE80211_SMPS_AUTOMATIC;
744 break; 769 break;
745 case NL80211_IFTYPE_AP: 770 case NL80211_IFTYPE_AP:
746 /* default smps_mode for AP / GO is OFF */ 771 if (!mvmvif->ap_ibss_active)
747 smps_mode = IEEE80211_SMPS_OFF;
748 if (!mvmvif->ap_ibss_active) {
749 iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
750 smps_mode);
751 return; 772 return;
752 }
753
754 /* the Ack / Cts kill mask must be default if AP / GO */
755 data->reduced_tx_power = false;
756 break; 773 break;
757 default: 774 default:
758 return; 775 return;
@@ -763,11 +780,10 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
763 /* If channel context is invalid or not on 2.4GHz .. */ 780 /* If channel context is invalid or not on 2.4GHz .. */
764 if ((!chanctx_conf || 781 if ((!chanctx_conf ||
765 chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ)) { 782 chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ)) {
766 /* ... relax constraints and disable rssi events */
767 iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
768 smps_mode);
769 data->reduced_tx_power = false;
770 if (vif->type == NL80211_IFTYPE_STATION) { 783 if (vif->type == NL80211_IFTYPE_STATION) {
784 /* ... relax constraints and disable rssi events */
785 iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
786 smps_mode);
771 iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, 787 iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id,
772 false); 788 false);
773 iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0); 789 iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0);
@@ -779,9 +795,7 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
779 if (bt_activity_grading >= BT_HIGH_TRAFFIC) 795 if (bt_activity_grading >= BT_HIGH_TRAFFIC)
780 smps_mode = IEEE80211_SMPS_STATIC; 796 smps_mode = IEEE80211_SMPS_STATIC;
781 else if (bt_activity_grading >= BT_LOW_TRAFFIC) 797 else if (bt_activity_grading >= BT_LOW_TRAFFIC)
782 smps_mode = vif->type == NL80211_IFTYPE_AP ? 798 smps_mode = IEEE80211_SMPS_DYNAMIC;
783 IEEE80211_SMPS_OFF :
784 IEEE80211_SMPS_DYNAMIC;
785 799
786 /* relax SMPS contraints for next association */ 800 /* relax SMPS contraints for next association */
787 if (!vif->bss_conf.assoc) 801 if (!vif->bss_conf.assoc)
@@ -795,7 +809,9 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
795 "mac %d: bt_activity_grading %d smps_req %d\n", 809 "mac %d: bt_activity_grading %d smps_req %d\n",
796 mvmvif->id, bt_activity_grading, smps_mode); 810 mvmvif->id, bt_activity_grading, smps_mode);
797 811
798 iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, smps_mode); 812 if (vif->type == NL80211_IFTYPE_STATION)
813 iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
814 smps_mode);
799 815
800 /* low latency is always primary */ 816 /* low latency is always primary */
801 if (iwl_mvm_vif_low_latency(mvmvif)) { 817 if (iwl_mvm_vif_low_latency(mvmvif)) {
@@ -846,7 +862,6 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
846 if (iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT || 862 if (iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT ||
847 mvm->cfg->bt_shared_single_ant || !vif->bss_conf.assoc || 863 mvm->cfg->bt_shared_single_ant || !vif->bss_conf.assoc ||
848 le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) == BT_OFF) { 864 le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) == BT_OFF) {
849 data->reduced_tx_power = false;
850 iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false); 865 iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false);
851 iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0); 866 iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0);
852 return; 867 return;
@@ -861,23 +876,9 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
861 if (ave_rssi > -IWL_MVM_BT_COEX_EN_RED_TXP_THRESH) { 876 if (ave_rssi > -IWL_MVM_BT_COEX_EN_RED_TXP_THRESH) {
862 if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, true)) 877 if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, true))
863 IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n"); 878 IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n");
864
865 /*
866 * bt_kill_msk can be BT_KILL_MSK_REDUCED_TXPOW only if all the
867 * BSS / P2P clients have rssi above threshold.
868 * We set the bt_kill_msk to BT_KILL_MSK_REDUCED_TXPOW before
869 * the iteration, if one interface's rssi isn't good enough,
870 * bt_kill_msk will be set to default values.
871 */
872 } else if (ave_rssi < -IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH) { 879 } else if (ave_rssi < -IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH) {
873 if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false)) 880 if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false))
874 IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n"); 881 IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n");
875
876 /*
877 * One interface hasn't rssi above threshold, bt_kill_msk must
878 * be set to default values.
879 */
880 data->reduced_tx_power = false;
881 } 882 }
882 883
883 /* Begin to monitor the RSSI: it may influence the reduced Tx power */ 884 /* Begin to monitor the RSSI: it may influence the reduced Tx power */
@@ -889,7 +890,6 @@ static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm)
889 struct iwl_bt_iterator_data data = { 890 struct iwl_bt_iterator_data data = {
890 .mvm = mvm, 891 .mvm = mvm,
891 .notif = &mvm->last_bt_notif, 892 .notif = &mvm->last_bt_notif,
892 .reduced_tx_power = true,
893 }; 893 };
894 struct iwl_bt_coex_ci_cmd cmd = {}; 894 struct iwl_bt_coex_ci_cmd cmd = {};
895 u8 ci_bw_idx; 895 u8 ci_bw_idx;
@@ -959,14 +959,7 @@ static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm)
959 memcpy(&mvm->last_bt_ci_cmd, &cmd, sizeof(cmd)); 959 memcpy(&mvm->last_bt_ci_cmd, &cmd, sizeof(cmd));
960 } 960 }
961 961
962 /* 962 if (iwl_mvm_bt_udpate_sw_boost(mvm))
963 * If there are no BSS / P2P client interfaces, reduced Tx Power is
964 * irrelevant since it is based on the RSSI coming from the beacon.
965 * Use BT_KILL_MSK_DEFAULT in that case.
966 */
967 data.reduced_tx_power = data.reduced_tx_power && data.num_bss_ifaces;
968
969 if (iwl_mvm_bt_udpate_sw_boost(mvm, data.reduced_tx_power))
970 IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n"); 963 IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n");
971} 964}
972 965
@@ -1035,16 +1028,6 @@ static void iwl_mvm_bt_rssi_iterator(void *_data, u8 *mac,
1035 return; 1028 return;
1036 1029
1037 mvmsta = iwl_mvm_sta_from_mac80211(sta); 1030 mvmsta = iwl_mvm_sta_from_mac80211(sta);
1038
1039 data->num_bss_ifaces++;
1040
1041 /*
1042 * This interface doesn't support reduced Tx power (because of low
1043 * RSSI probably), then set bt_kill_msk to default values.
1044 */
1045 if (!mvmsta->bt_reduced_txpower)
1046 data->reduced_tx_power = false;
1047 /* else - possibly leave it to BT_KILL_MSK_REDUCED_TXPOW */
1048} 1031}
1049 1032
1050void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 1033void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
@@ -1053,7 +1036,6 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
1053 struct iwl_mvm_vif *mvmvif = (void *)vif->drv_priv; 1036 struct iwl_mvm_vif *mvmvif = (void *)vif->drv_priv;
1054 struct iwl_bt_iterator_data data = { 1037 struct iwl_bt_iterator_data data = {
1055 .mvm = mvm, 1038 .mvm = mvm,
1056 .reduced_tx_power = true,
1057 }; 1039 };
1058 int ret; 1040 int ret;
1059 1041
@@ -1100,14 +1082,7 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
1100 mvm->hw, IEEE80211_IFACE_ITER_NORMAL, 1082 mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
1101 iwl_mvm_bt_rssi_iterator, &data); 1083 iwl_mvm_bt_rssi_iterator, &data);
1102 1084
1103 /* 1085 if (iwl_mvm_bt_udpate_sw_boost(mvm))
1104 * If there are no BSS / P2P client interfaces, reduced Tx Power is
1105 * irrelevant since it is based on the RSSI coming from the beacon.
1106 * Use BT_KILL_MSK_DEFAULT in that case.
1107 */
1108 data.reduced_tx_power = data.reduced_tx_power && data.num_bss_ifaces;
1109
1110 if (iwl_mvm_bt_udpate_sw_boost(mvm, data.reduced_tx_power))
1111 IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n"); 1086 IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n");
1112} 1087}
1113 1088
@@ -1150,7 +1125,7 @@ bool iwl_mvm_bt_coex_is_mimo_allowed(struct iwl_mvm *mvm,
1150 enum iwl_bt_coex_lut_type lut_type; 1125 enum iwl_bt_coex_lut_type lut_type;
1151 1126
1152 if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT)) 1127 if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT))
1153 return iwl_mvm_coex_agg_time_limit_old(mvm, sta); 1128 return iwl_mvm_bt_coex_is_mimo_allowed_old(mvm, sta);
1154 1129
1155 if (IWL_COEX_IS_TTC_ON(mvm->last_bt_notif.ttc_rrc_status, phy_ctxt->id)) 1130 if (IWL_COEX_IS_TTC_ON(mvm->last_bt_notif.ttc_rrc_status, phy_ctxt->id))
1156 return true; 1131 return true;
diff --git a/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c b/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c
index ce50363d314b..a3be33359927 100644
--- a/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c
+++ b/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c
@@ -649,10 +649,6 @@ int iwl_send_bt_init_conf_old(struct iwl_mvm *mvm)
649 sizeof(iwl_bt_prio_boost)); 649 sizeof(iwl_bt_prio_boost));
650 memcpy(&bt_cmd->bt4_multiprio_lut, iwl_bt_mprio_lut, 650 memcpy(&bt_cmd->bt4_multiprio_lut, iwl_bt_mprio_lut,
651 sizeof(iwl_bt_mprio_lut)); 651 sizeof(iwl_bt_mprio_lut));
652 bt_cmd->kill_ack_msk =
653 cpu_to_le32(iwl_bt_ack_kill_msk[BT_KILL_MSK_DEFAULT]);
654 bt_cmd->kill_cts_msk =
655 cpu_to_le32(iwl_bt_cts_kill_msk[BT_KILL_MSK_DEFAULT]);
656 652
657send_cmd: 653send_cmd:
658 memset(&mvm->last_bt_notif_old, 0, sizeof(mvm->last_bt_notif_old)); 654 memset(&mvm->last_bt_notif_old, 0, sizeof(mvm->last_bt_notif_old));
@@ -664,12 +660,13 @@ send_cmd:
664 return ret; 660 return ret;
665} 661}
666 662
667static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm, 663static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm)
668 bool reduced_tx_power)
669{ 664{
670 enum iwl_bt_kill_msk bt_kill_msk;
671 struct iwl_bt_coex_cmd_old *bt_cmd;
672 struct iwl_bt_coex_profile_notif_old *notif = &mvm->last_bt_notif_old; 665 struct iwl_bt_coex_profile_notif_old *notif = &mvm->last_bt_notif_old;
666 u32 primary_lut = le32_to_cpu(notif->primary_ch_lut);
667 u32 ag = le32_to_cpu(notif->bt_activity_grading);
668 struct iwl_bt_coex_cmd_old *bt_cmd;
669 u8 ack_kill_msk, cts_kill_msk;
673 struct iwl_host_cmd cmd = { 670 struct iwl_host_cmd cmd = {
674 .id = BT_CONFIG, 671 .id = BT_CONFIG,
675 .data[0] = &bt_cmd, 672 .data[0] = &bt_cmd,
@@ -680,31 +677,15 @@ static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm,
680 677
681 lockdep_assert_held(&mvm->mutex); 678 lockdep_assert_held(&mvm->mutex);
682 679
683 if (reduced_tx_power) { 680 ack_kill_msk = iwl_bt_ack_kill_msk[ag][primary_lut];
684 /* Reduced Tx power has precedence on the type of the profile */ 681 cts_kill_msk = iwl_bt_cts_kill_msk[ag][primary_lut];
685 bt_kill_msk = BT_KILL_MSK_REDUCED_TXPOW;
686 } else {
687 /* Low latency BT profile is active: give higher prio to BT */
688 if (BT_MBOX_MSG(notif, 3, SCO_STATE) ||
689 BT_MBOX_MSG(notif, 3, A2DP_STATE) ||
690 BT_MBOX_MSG(notif, 3, SNIFF_STATE))
691 bt_kill_msk = BT_KILL_MSK_SCO_HID_A2DP;
692 else
693 bt_kill_msk = BT_KILL_MSK_DEFAULT;
694 }
695
696 IWL_DEBUG_COEX(mvm,
697 "Update kill_msk: %d - SCO %sactive A2DP %sactive SNIFF %sactive\n",
698 bt_kill_msk,
699 BT_MBOX_MSG(notif, 3, SCO_STATE) ? "" : "in",
700 BT_MBOX_MSG(notif, 3, A2DP_STATE) ? "" : "in",
701 BT_MBOX_MSG(notif, 3, SNIFF_STATE) ? "" : "in");
702 682
703 /* Don't send HCMD if there is no update */ 683 if (mvm->bt_ack_kill_msk[0] == ack_kill_msk &&
704 if (bt_kill_msk == mvm->bt_kill_msk) 684 mvm->bt_cts_kill_msk[0] == cts_kill_msk)
705 return 0; 685 return 0;
706 686
707 mvm->bt_kill_msk = bt_kill_msk; 687 mvm->bt_ack_kill_msk[0] = ack_kill_msk;
688 mvm->bt_cts_kill_msk[0] = cts_kill_msk;
708 689
709 bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL); 690 bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL);
710 if (!bt_cmd) 691 if (!bt_cmd)
@@ -712,16 +693,12 @@ static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm,
712 cmd.data[0] = bt_cmd; 693 cmd.data[0] = bt_cmd;
713 bt_cmd->flags = cpu_to_le32(BT_COEX_NW_OLD); 694 bt_cmd->flags = cpu_to_le32(BT_COEX_NW_OLD);
714 695
715 bt_cmd->kill_ack_msk = cpu_to_le32(iwl_bt_ack_kill_msk[bt_kill_msk]); 696 bt_cmd->kill_ack_msk = cpu_to_le32(iwl_bt_ctl_kill_msk[ack_kill_msk]);
716 bt_cmd->kill_cts_msk = cpu_to_le32(iwl_bt_cts_kill_msk[bt_kill_msk]); 697 bt_cmd->kill_cts_msk = cpu_to_le32(iwl_bt_ctl_kill_msk[cts_kill_msk]);
717 bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_ENABLE | 698 bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_ENABLE |
718 BT_VALID_KILL_ACK | 699 BT_VALID_KILL_ACK |
719 BT_VALID_KILL_CTS); 700 BT_VALID_KILL_CTS);
720 701
721 IWL_DEBUG_COEX(mvm, "ACK Kill msk = 0x%08x, CTS Kill msk = 0x%08x\n",
722 iwl_bt_ack_kill_msk[bt_kill_msk],
723 iwl_bt_cts_kill_msk[bt_kill_msk]);
724
725 ret = iwl_mvm_send_cmd(mvm, &cmd); 702 ret = iwl_mvm_send_cmd(mvm, &cmd);
726 703
727 kfree(bt_cmd); 704 kfree(bt_cmd);
@@ -777,8 +754,6 @@ static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id,
777struct iwl_bt_iterator_data { 754struct iwl_bt_iterator_data {
778 struct iwl_bt_coex_profile_notif_old *notif; 755 struct iwl_bt_coex_profile_notif_old *notif;
779 struct iwl_mvm *mvm; 756 struct iwl_mvm *mvm;
780 u32 num_bss_ifaces;
781 bool reduced_tx_power;
782 struct ieee80211_chanctx_conf *primary; 757 struct ieee80211_chanctx_conf *primary;
783 struct ieee80211_chanctx_conf *secondary; 758 struct ieee80211_chanctx_conf *secondary;
784 bool primary_ll; 759 bool primary_ll;
@@ -814,22 +789,12 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
814 789
815 switch (vif->type) { 790 switch (vif->type) {
816 case NL80211_IFTYPE_STATION: 791 case NL80211_IFTYPE_STATION:
817 /* Count BSSes vifs */
818 data->num_bss_ifaces++;
819 /* default smps_mode for BSS / P2P client is AUTOMATIC */ 792 /* default smps_mode for BSS / P2P client is AUTOMATIC */
820 smps_mode = IEEE80211_SMPS_AUTOMATIC; 793 smps_mode = IEEE80211_SMPS_AUTOMATIC;
821 break; 794 break;
822 case NL80211_IFTYPE_AP: 795 case NL80211_IFTYPE_AP:
823 /* default smps_mode for AP / GO is OFF */ 796 if (!mvmvif->ap_ibss_active)
824 smps_mode = IEEE80211_SMPS_OFF;
825 if (!mvmvif->ap_ibss_active) {
826 iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
827 smps_mode);
828 return; 797 return;
829 }
830
831 /* the Ack / Cts kill mask must be default if AP / GO */
832 data->reduced_tx_power = false;
833 break; 798 break;
834 default: 799 default:
835 return; 800 return;
@@ -840,11 +805,10 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
840 /* If channel context is invalid or not on 2.4GHz .. */ 805 /* If channel context is invalid or not on 2.4GHz .. */
841 if ((!chanctx_conf || 806 if ((!chanctx_conf ||
842 chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ)) { 807 chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ)) {
843 /* ... relax constraints and disable rssi events */
844 iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
845 smps_mode);
846 data->reduced_tx_power = false;
847 if (vif->type == NL80211_IFTYPE_STATION) { 808 if (vif->type == NL80211_IFTYPE_STATION) {
809 /* ... relax constraints and disable rssi events */
810 iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
811 smps_mode);
848 iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, 812 iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id,
849 false); 813 false);
850 iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0); 814 iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0);
@@ -869,7 +833,9 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
869 mvmvif->id, data->notif->bt_status, bt_activity_grading, 833 mvmvif->id, data->notif->bt_status, bt_activity_grading,
870 smps_mode); 834 smps_mode);
871 835
872 iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, smps_mode); 836 if (vif->type == NL80211_IFTYPE_STATION)
837 iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
838 smps_mode);
873 839
874 /* low latency is always primary */ 840 /* low latency is always primary */
875 if (iwl_mvm_vif_low_latency(mvmvif)) { 841 if (iwl_mvm_vif_low_latency(mvmvif)) {
@@ -920,7 +886,6 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
920 if (iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT || 886 if (iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT ||
921 mvm->cfg->bt_shared_single_ant || !vif->bss_conf.assoc || 887 mvm->cfg->bt_shared_single_ant || !vif->bss_conf.assoc ||
922 !data->notif->bt_status) { 888 !data->notif->bt_status) {
923 data->reduced_tx_power = false;
924 iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false); 889 iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false);
925 iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0); 890 iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0);
926 return; 891 return;
@@ -935,23 +900,9 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
935 if (ave_rssi > -IWL_MVM_BT_COEX_EN_RED_TXP_THRESH) { 900 if (ave_rssi > -IWL_MVM_BT_COEX_EN_RED_TXP_THRESH) {
936 if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, true)) 901 if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, true))
937 IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n"); 902 IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n");
938
939 /*
940 * bt_kill_msk can be BT_KILL_MSK_REDUCED_TXPOW only if all the
941 * BSS / P2P clients have rssi above threshold.
942 * We set the bt_kill_msk to BT_KILL_MSK_REDUCED_TXPOW before
943 * the iteration, if one interface's rssi isn't good enough,
944 * bt_kill_msk will be set to default values.
945 */
946 } else if (ave_rssi < -IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH) { 903 } else if (ave_rssi < -IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH) {
947 if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false)) 904 if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false))
948 IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n"); 905 IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n");
949
950 /*
951 * One interface hasn't rssi above threshold, bt_kill_msk must
952 * be set to default values.
953 */
954 data->reduced_tx_power = false;
955 } 906 }
956 907
957 /* Begin to monitor the RSSI: it may influence the reduced Tx power */ 908 /* Begin to monitor the RSSI: it may influence the reduced Tx power */
@@ -963,7 +914,6 @@ static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm)
963 struct iwl_bt_iterator_data data = { 914 struct iwl_bt_iterator_data data = {
964 .mvm = mvm, 915 .mvm = mvm,
965 .notif = &mvm->last_bt_notif_old, 916 .notif = &mvm->last_bt_notif_old,
966 .reduced_tx_power = true,
967 }; 917 };
968 struct iwl_bt_coex_ci_cmd_old cmd = {}; 918 struct iwl_bt_coex_ci_cmd_old cmd = {};
969 u8 ci_bw_idx; 919 u8 ci_bw_idx;
@@ -1037,14 +987,7 @@ static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm)
1037 memcpy(&mvm->last_bt_ci_cmd_old, &cmd, sizeof(cmd)); 987 memcpy(&mvm->last_bt_ci_cmd_old, &cmd, sizeof(cmd));
1038 } 988 }
1039 989
1040 /* 990 if (iwl_mvm_bt_udpate_ctrl_kill_msk(mvm))
1041 * If there are no BSS / P2P client interfaces, reduced Tx Power is
1042 * irrelevant since it is based on the RSSI coming from the beacon.
1043 * Use BT_KILL_MSK_DEFAULT in that case.
1044 */
1045 data.reduced_tx_power = data.reduced_tx_power && data.num_bss_ifaces;
1046
1047 if (iwl_mvm_bt_udpate_ctrl_kill_msk(mvm, data.reduced_tx_power))
1048 IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n"); 991 IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n");
1049} 992}
1050 993
@@ -1115,16 +1058,6 @@ static void iwl_mvm_bt_rssi_iterator(void *_data, u8 *mac,
1115 return; 1058 return;
1116 1059
1117 mvmsta = iwl_mvm_sta_from_mac80211(sta); 1060 mvmsta = iwl_mvm_sta_from_mac80211(sta);
1118
1119 data->num_bss_ifaces++;
1120
1121 /*
1122 * This interface doesn't support reduced Tx power (because of low
1123 * RSSI probably), then set bt_kill_msk to default values.
1124 */
1125 if (!mvmsta->bt_reduced_txpower)
1126 data->reduced_tx_power = false;
1127 /* else - possibly leave it to BT_KILL_MSK_REDUCED_TXPOW */
1128} 1061}
1129 1062
1130void iwl_mvm_bt_rssi_event_old(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 1063void iwl_mvm_bt_rssi_event_old(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
@@ -1133,7 +1066,6 @@ void iwl_mvm_bt_rssi_event_old(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
1133 struct iwl_mvm_vif *mvmvif = (void *)vif->drv_priv; 1066 struct iwl_mvm_vif *mvmvif = (void *)vif->drv_priv;
1134 struct iwl_bt_iterator_data data = { 1067 struct iwl_bt_iterator_data data = {
1135 .mvm = mvm, 1068 .mvm = mvm,
1136 .reduced_tx_power = true,
1137 }; 1069 };
1138 int ret; 1070 int ret;
1139 1071
@@ -1175,14 +1107,7 @@ void iwl_mvm_bt_rssi_event_old(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
1175 mvm->hw, IEEE80211_IFACE_ITER_NORMAL, 1107 mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
1176 iwl_mvm_bt_rssi_iterator, &data); 1108 iwl_mvm_bt_rssi_iterator, &data);
1177 1109
1178 /* 1110 if (iwl_mvm_bt_udpate_ctrl_kill_msk(mvm))
1179 * If there are no BSS / P2P client interfaces, reduced Tx Power is
1180 * irrelevant since it is based on the RSSI coming from the beacon.
1181 * Use BT_KILL_MSK_DEFAULT in that case.
1182 */
1183 data.reduced_tx_power = data.reduced_tx_power && data.num_bss_ifaces;
1184
1185 if (iwl_mvm_bt_udpate_ctrl_kill_msk(mvm, data.reduced_tx_power))
1186 IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n"); 1111 IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n");
1187} 1112}
1188 1113
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
index f131ef0ec5b3..7d18f466fbb3 100644
--- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
@@ -146,17 +146,47 @@ static ssize_t iwl_dbgfs_fw_error_dump_read(struct file *file,
146 char __user *user_buf, 146 char __user *user_buf,
147 size_t count, loff_t *ppos) 147 size_t count, loff_t *ppos)
148{ 148{
149 struct iwl_fw_error_dump_file *dump_file = file->private_data; 149 struct iwl_mvm_dump_ptrs *dump_ptrs = (void *)file->private_data;
150 ssize_t bytes_read = 0;
151 ssize_t bytes_read_trans = 0;
152
153 if (*ppos < dump_ptrs->op_mode_len)
154 bytes_read +=
155 simple_read_from_buffer(user_buf, count, ppos,
156 dump_ptrs->op_mode_ptr,
157 dump_ptrs->op_mode_len);
158
159 if (bytes_read < 0 || *ppos < dump_ptrs->op_mode_len)
160 return bytes_read;
161
162 if (dump_ptrs->trans_ptr) {
163 *ppos -= dump_ptrs->op_mode_len;
164 bytes_read_trans =
165 simple_read_from_buffer(user_buf + bytes_read,
166 count - bytes_read, ppos,
167 dump_ptrs->trans_ptr->data,
168 dump_ptrs->trans_ptr->len);
169 *ppos += dump_ptrs->op_mode_len;
170
171 if (bytes_read_trans >= 0)
172 bytes_read += bytes_read_trans;
173 else if (!bytes_read)
174 /* propagate the failure */
175 return bytes_read_trans;
176 }
177
178 return bytes_read;
150 179
151 return simple_read_from_buffer(user_buf, count, ppos,
152 dump_file,
153 le32_to_cpu(dump_file->file_len));
154} 180}
155 181
156static int iwl_dbgfs_fw_error_dump_release(struct inode *inode, 182static int iwl_dbgfs_fw_error_dump_release(struct inode *inode,
157 struct file *file) 183 struct file *file)
158{ 184{
159 vfree(file->private_data); 185 struct iwl_mvm_dump_ptrs *dump_ptrs = (void *)file->private_data;
186
187 vfree(dump_ptrs->op_mode_ptr);
188 vfree(dump_ptrs->trans_ptr);
189 kfree(dump_ptrs);
160 190
161 return 0; 191 return 0;
162} 192}
@@ -514,9 +544,9 @@ static ssize_t iwl_dbgfs_bt_cmd_read(struct file *file, char __user *user_buf,
514 544
515 pos += scnprintf(buf+pos, bufsz-pos, "BT Configuration CMD\n"); 545 pos += scnprintf(buf+pos, bufsz-pos, "BT Configuration CMD\n");
516 pos += scnprintf(buf+pos, bufsz-pos, "\tACK Kill Mask 0x%08x\n", 546 pos += scnprintf(buf+pos, bufsz-pos, "\tACK Kill Mask 0x%08x\n",
517 iwl_bt_ack_kill_msk[mvm->bt_kill_msk]); 547 iwl_bt_ctl_kill_msk[mvm->bt_ack_kill_msk[0]]);
518 pos += scnprintf(buf+pos, bufsz-pos, "\tCTS Kill Mask 0x%08x\n", 548 pos += scnprintf(buf+pos, bufsz-pos, "\tCTS Kill Mask 0x%08x\n",
519 iwl_bt_cts_kill_msk[mvm->bt_kill_msk]); 549 iwl_bt_ctl_kill_msk[mvm->bt_cts_kill_msk[0]]);
520 550
521 } else { 551 } else {
522 struct iwl_bt_coex_ci_cmd *cmd = &mvm->last_bt_ci_cmd; 552 struct iwl_bt_coex_ci_cmd *cmd = &mvm->last_bt_ci_cmd;
@@ -531,10 +561,19 @@ static ssize_t iwl_dbgfs_bt_cmd_read(struct file *file, char __user *user_buf,
531 le64_to_cpu(cmd->bt_secondary_ci)); 561 le64_to_cpu(cmd->bt_secondary_ci));
532 562
533 pos += scnprintf(buf+pos, bufsz-pos, "BT Configuration CMD\n"); 563 pos += scnprintf(buf+pos, bufsz-pos, "BT Configuration CMD\n");
534 pos += scnprintf(buf+pos, bufsz-pos, "\tACK Kill Mask 0x%08x\n", 564 pos += scnprintf(buf+pos, bufsz-pos,
535 iwl_bt_ack_kill_msk[mvm->bt_kill_msk]); 565 "\tPrimary: ACK Kill Mask 0x%08x\n",
536 pos += scnprintf(buf+pos, bufsz-pos, "\tCTS Kill Mask 0x%08x\n", 566 iwl_bt_ctl_kill_msk[mvm->bt_ack_kill_msk[0]]);
537 iwl_bt_cts_kill_msk[mvm->bt_kill_msk]); 567 pos += scnprintf(buf+pos, bufsz-pos,
568 "\tPrimary: CTS Kill Mask 0x%08x\n",
569 iwl_bt_ctl_kill_msk[mvm->bt_cts_kill_msk[0]]);
570 pos += scnprintf(buf+pos, bufsz-pos,
571 "\tSecondary: ACK Kill Mask 0x%08x\n",
572 iwl_bt_ctl_kill_msk[mvm->bt_ack_kill_msk[1]]);
573 pos += scnprintf(buf+pos, bufsz-pos,
574 "\tSecondary: CTS Kill Mask 0x%08x\n",
575 iwl_bt_ctl_kill_msk[mvm->bt_cts_kill_msk[1]]);
576
538 } 577 }
539 578
540 mutex_unlock(&mvm->mutex); 579 mutex_unlock(&mvm->mutex);
@@ -830,8 +869,14 @@ static ssize_t iwl_dbgfs_fw_restart_write(struct iwl_mvm *mvm, char *buf,
830static ssize_t iwl_dbgfs_fw_nmi_write(struct iwl_mvm *mvm, char *buf, 869static ssize_t iwl_dbgfs_fw_nmi_write(struct iwl_mvm *mvm, char *buf,
831 size_t count, loff_t *ppos) 870 size_t count, loff_t *ppos)
832{ 871{
872 int ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_NMI);
873 if (ret)
874 return ret;
875
833 iwl_force_nmi(mvm->trans); 876 iwl_force_nmi(mvm->trans);
834 877
878 iwl_mvm_unref(mvm, IWL_MVM_REF_NMI);
879
835 return count; 880 return count;
836} 881}
837 882
@@ -1115,11 +1160,11 @@ static ssize_t iwl_dbgfs_d3_sram_read(struct file *file, char __user *user_buf,
1115} 1160}
1116#endif 1161#endif
1117 1162
1118#define PRINT_MVM_REF(ref) do { \ 1163#define PRINT_MVM_REF(ref) do { \
1119 if (test_bit(ref, mvm->ref_bitmap)) \ 1164 if (mvm->refs[ref]) \
1120 pos += scnprintf(buf + pos, bufsz - pos, \ 1165 pos += scnprintf(buf + pos, bufsz - pos, \
1121 "\t(0x%lx) %s\n", \ 1166 "\t(0x%lx): %d %s\n", \
1122 BIT(ref), #ref); \ 1167 BIT(ref), mvm->refs[ref], #ref); \
1123} while (0) 1168} while (0)
1124 1169
1125static ssize_t iwl_dbgfs_d0i3_refs_read(struct file *file, 1170static ssize_t iwl_dbgfs_d0i3_refs_read(struct file *file,
@@ -1127,12 +1172,17 @@ static ssize_t iwl_dbgfs_d0i3_refs_read(struct file *file,
1127 size_t count, loff_t *ppos) 1172 size_t count, loff_t *ppos)
1128{ 1173{
1129 struct iwl_mvm *mvm = file->private_data; 1174 struct iwl_mvm *mvm = file->private_data;
1130 int pos = 0; 1175 int i, pos = 0;
1131 char buf[256]; 1176 char buf[256];
1132 const size_t bufsz = sizeof(buf); 1177 const size_t bufsz = sizeof(buf);
1178 u32 refs = 0;
1133 1179
1134 pos += scnprintf(buf + pos, bufsz - pos, "taken mvm refs: 0x%lx\n", 1180 for (i = 0; i < IWL_MVM_REF_COUNT; i++)
1135 mvm->ref_bitmap[0]); 1181 if (mvm->refs[i])
1182 refs |= BIT(i);
1183
1184 pos += scnprintf(buf + pos, bufsz - pos, "taken mvm refs: 0x%x\n",
1185 refs);
1136 1186
1137 PRINT_MVM_REF(IWL_MVM_REF_UCODE_DOWN); 1187 PRINT_MVM_REF(IWL_MVM_REF_UCODE_DOWN);
1138 PRINT_MVM_REF(IWL_MVM_REF_SCAN); 1188 PRINT_MVM_REF(IWL_MVM_REF_SCAN);
@@ -1158,7 +1208,7 @@ static ssize_t iwl_dbgfs_d0i3_refs_write(struct iwl_mvm *mvm, char *buf,
1158 1208
1159 mutex_lock(&mvm->mutex); 1209 mutex_lock(&mvm->mutex);
1160 1210
1161 taken = test_bit(IWL_MVM_REF_USER, mvm->ref_bitmap); 1211 taken = mvm->refs[IWL_MVM_REF_USER];
1162 if (value == 1 && !taken) 1212 if (value == 1 && !taken)
1163 iwl_mvm_ref(mvm, IWL_MVM_REF_USER); 1213 iwl_mvm_ref(mvm, IWL_MVM_REF_USER);
1164 else if (value == 0 && taken) 1214 else if (value == 0 && taken)
@@ -1194,14 +1244,21 @@ iwl_dbgfs_prph_reg_read(struct file *file,
1194 int pos = 0; 1244 int pos = 0;
1195 char buf[32]; 1245 char buf[32];
1196 const size_t bufsz = sizeof(buf); 1246 const size_t bufsz = sizeof(buf);
1247 int ret;
1197 1248
1198 if (!mvm->dbgfs_prph_reg_addr) 1249 if (!mvm->dbgfs_prph_reg_addr)
1199 return -EINVAL; 1250 return -EINVAL;
1200 1251
1252 ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PRPH_READ);
1253 if (ret)
1254 return ret;
1255
1201 pos += scnprintf(buf + pos, bufsz - pos, "Reg 0x%x: (0x%x)\n", 1256 pos += scnprintf(buf + pos, bufsz - pos, "Reg 0x%x: (0x%x)\n",
1202 mvm->dbgfs_prph_reg_addr, 1257 mvm->dbgfs_prph_reg_addr,
1203 iwl_read_prph(mvm->trans, mvm->dbgfs_prph_reg_addr)); 1258 iwl_read_prph(mvm->trans, mvm->dbgfs_prph_reg_addr));
1204 1259
1260 iwl_mvm_unref(mvm, IWL_MVM_REF_PRPH_READ);
1261
1205 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1262 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1206} 1263}
1207 1264
@@ -1211,6 +1268,7 @@ iwl_dbgfs_prph_reg_write(struct iwl_mvm *mvm, char *buf,
1211{ 1268{
1212 u8 args; 1269 u8 args;
1213 u32 value; 1270 u32 value;
1271 int ret;
1214 1272
1215 args = sscanf(buf, "%i %i", &mvm->dbgfs_prph_reg_addr, &value); 1273 args = sscanf(buf, "%i %i", &mvm->dbgfs_prph_reg_addr, &value);
1216 /* if we only want to set the reg address - nothing more to do */ 1274 /* if we only want to set the reg address - nothing more to do */
@@ -1221,7 +1279,13 @@ iwl_dbgfs_prph_reg_write(struct iwl_mvm *mvm, char *buf,
1221 if (args != 2) 1279 if (args != 2)
1222 return -EINVAL; 1280 return -EINVAL;
1223 1281
1282 ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PRPH_WRITE);
1283 if (ret)
1284 return ret;
1285
1224 iwl_write_prph(mvm->trans, mvm->dbgfs_prph_reg_addr, value); 1286 iwl_write_prph(mvm->trans, mvm->dbgfs_prph_reg_addr, value);
1287
1288 iwl_mvm_unref(mvm, IWL_MVM_REF_PRPH_WRITE);
1225out: 1289out:
1226 return count; 1290 return count;
1227} 1291}
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h
index ab12aaa43034..69875716dcdb 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h
@@ -385,6 +385,8 @@ enum iwl_bt_activity_grading {
385 BT_ON_NO_CONNECTION = 1, 385 BT_ON_NO_CONNECTION = 1,
386 BT_LOW_TRAFFIC = 2, 386 BT_LOW_TRAFFIC = 2,
387 BT_HIGH_TRAFFIC = 3, 387 BT_HIGH_TRAFFIC = 3,
388
389 BT_MAX_AG,
388}; /* BT_COEX_BT_ACTIVITY_GRADING_API_E_VER_1 */ 390}; /* BT_COEX_BT_ACTIVITY_GRADING_API_E_VER_1 */
389 391
390enum iwl_bt_ci_compliance { 392enum iwl_bt_ci_compliance {
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h
index b8e4e78d601b..95f5b3274efb 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h
@@ -133,6 +133,7 @@ enum {
133 /* Scan offload */ 133 /* Scan offload */
134 SCAN_OFFLOAD_REQUEST_CMD = 0x51, 134 SCAN_OFFLOAD_REQUEST_CMD = 0x51,
135 SCAN_OFFLOAD_ABORT_CMD = 0x52, 135 SCAN_OFFLOAD_ABORT_CMD = 0x52,
136 HOT_SPOT_CMD = 0x53,
136 SCAN_OFFLOAD_COMPLETE = 0x6D, 137 SCAN_OFFLOAD_COMPLETE = 0x6D,
137 SCAN_OFFLOAD_UPDATE_PROFILES_CMD = 0x6E, 138 SCAN_OFFLOAD_UPDATE_PROFILES_CMD = 0x6E,
138 SCAN_OFFLOAD_CONFIG_CMD = 0x6f, 139 SCAN_OFFLOAD_CONFIG_CMD = 0x6f,
@@ -910,6 +911,72 @@ struct iwl_phy_context_cmd {
910 __le32 dsp_cfg_flags; 911 __le32 dsp_cfg_flags;
911} __packed; /* PHY_CONTEXT_CMD_API_VER_1 */ 912} __packed; /* PHY_CONTEXT_CMD_API_VER_1 */
912 913
914/*
915 * Aux ROC command
916 *
917 * Command requests the firmware to create a time event for a certain duration
918 * and remain on the given channel. This is done by using the Aux framework in
919 * the FW.
920 * The command was first used for Hot Spot issues - but can be used regardless
921 * to Hot Spot.
922 *
923 * ( HOT_SPOT_CMD 0x53 )
924 *
925 * @id_and_color: ID and color of the MAC
926 * @action: action to perform, one of FW_CTXT_ACTION_*
927 * @event_unique_id: If the action FW_CTXT_ACTION_REMOVE then the
928 * event_unique_id should be the id of the time event assigned by ucode.
929 * Otherwise ignore the event_unique_id.
930 * @sta_id_and_color: station id and color, resumed during "Remain On Channel"
931 * activity.
932 * @channel_info: channel info
933 * @node_addr: Our MAC Address
934 * @reserved: reserved for alignment
935 * @apply_time: GP2 value to start (should always be the current GP2 value)
936 * @apply_time_max_delay: Maximum apply time delay value in TU. Defines max
937 * time by which start of the event is allowed to be postponed.
938 * @duration: event duration in TU To calculate event duration:
939 * timeEventDuration = min(duration, remainingQuota)
940 */
941struct iwl_hs20_roc_req {
942 /* COMMON_INDEX_HDR_API_S_VER_1 hdr */
943 __le32 id_and_color;
944 __le32 action;
945 __le32 event_unique_id;
946 __le32 sta_id_and_color;
947 struct iwl_fw_channel_info channel_info;
948 u8 node_addr[ETH_ALEN];
949 __le16 reserved;
950 __le32 apply_time;
951 __le32 apply_time_max_delay;
952 __le32 duration;
953} __packed; /* HOT_SPOT_CMD_API_S_VER_1 */
954
955/*
956 * values for AUX ROC result values
957 */
958enum iwl_mvm_hot_spot {
959 HOT_SPOT_RSP_STATUS_OK,
960 HOT_SPOT_RSP_STATUS_TOO_MANY_EVENTS,
961 HOT_SPOT_MAX_NUM_OF_SESSIONS,
962};
963
964/*
965 * Aux ROC command response
966 *
967 * In response to iwl_hs20_roc_req the FW sends this command to notify the
968 * driver the uid of the timevent.
969 *
970 * ( HOT_SPOT_CMD 0x53 )
971 *
972 * @event_unique_id: Unique ID of time event assigned by ucode
973 * @status: Return status 0 is success, all the rest used for specific errors
974 */
975struct iwl_hs20_roc_res {
976 __le32 event_unique_id;
977 __le32 status;
978} __packed; /* HOT_SPOT_RSP_API_S_VER_1 */
979
913#define IWL_RX_INFO_PHY_CNT 8 980#define IWL_RX_INFO_PHY_CNT 8
914#define IWL_RX_INFO_ENERGY_ANT_ABC_IDX 1 981#define IWL_RX_INFO_ENERGY_ANT_ABC_IDX 1
915#define IWL_RX_INFO_ENERGY_ANT_A_MSK 0x000000ff 982#define IWL_RX_INFO_ENERGY_ANT_A_MSK 0x000000ff
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
index 96b9cf8137e7..0e523e28cabf 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
@@ -1074,8 +1074,12 @@ static int iwl_mvm_mac_ctxt_cmd_ap(struct iwl_mvm *mvm,
1074 /* Fill the common data for all mac context types */ 1074 /* Fill the common data for all mac context types */
1075 iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action); 1075 iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
1076 1076
1077 /* Also enable probe requests to pass */ 1077 /*
1078 cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST); 1078 * pass probe requests and beacons from other APs (needed
1079 * for ht protection)
1080 */
1081 cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST |
1082 MAC_FILTER_IN_BEACON);
1079 1083
1080 /* Fill the data specific for ap mode */ 1084 /* Fill the data specific for ap mode */
1081 iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.ap, 1085 iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.ap,
@@ -1096,6 +1100,13 @@ static int iwl_mvm_mac_ctxt_cmd_go(struct iwl_mvm *mvm,
1096 /* Fill the common data for all mac context types */ 1100 /* Fill the common data for all mac context types */
1097 iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action); 1101 iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
1098 1102
1103 /*
1104 * pass probe requests and beacons from other APs (needed
1105 * for ht protection)
1106 */
1107 cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST |
1108 MAC_FILTER_IN_BEACON);
1109
1099 /* Fill the data specific for GO mode */ 1110 /* Fill the data specific for GO mode */
1100 iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.go.ap, 1111 iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.go.ap,
1101 action == FW_CTXT_ACTION_ADD); 1112 action == FW_CTXT_ACTION_ADD);
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
index 2eb6ebee4467..0d6a8b768a68 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
@@ -211,7 +211,9 @@ void iwl_mvm_ref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type)
211 return; 211 return;
212 212
213 IWL_DEBUG_RPM(mvm, "Take mvm reference - type %d\n", ref_type); 213 IWL_DEBUG_RPM(mvm, "Take mvm reference - type %d\n", ref_type);
214 WARN_ON(test_and_set_bit(ref_type, mvm->ref_bitmap)); 214 spin_lock_bh(&mvm->refs_lock);
215 mvm->refs[ref_type]++;
216 spin_unlock_bh(&mvm->refs_lock);
215 iwl_trans_ref(mvm->trans); 217 iwl_trans_ref(mvm->trans);
216} 218}
217 219
@@ -221,29 +223,35 @@ void iwl_mvm_unref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type)
221 return; 223 return;
222 224
223 IWL_DEBUG_RPM(mvm, "Leave mvm reference - type %d\n", ref_type); 225 IWL_DEBUG_RPM(mvm, "Leave mvm reference - type %d\n", ref_type);
224 WARN_ON(!test_and_clear_bit(ref_type, mvm->ref_bitmap)); 226 spin_lock_bh(&mvm->refs_lock);
227 WARN_ON(!mvm->refs[ref_type]--);
228 spin_unlock_bh(&mvm->refs_lock);
225 iwl_trans_unref(mvm->trans); 229 iwl_trans_unref(mvm->trans);
226} 230}
227 231
228static void 232static void iwl_mvm_unref_all_except(struct iwl_mvm *mvm,
229iwl_mvm_unref_all_except(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref) 233 enum iwl_mvm_ref_type except_ref)
230{ 234{
231 int i; 235 int i, j;
232 236
233 if (!iwl_mvm_is_d0i3_supported(mvm)) 237 if (!iwl_mvm_is_d0i3_supported(mvm))
234 return; 238 return;
235 239
236 for_each_set_bit(i, mvm->ref_bitmap, IWL_MVM_REF_COUNT) { 240 spin_lock_bh(&mvm->refs_lock);
237 if (ref == i) 241 for (i = 0; i < IWL_MVM_REF_COUNT; i++) {
242 if (except_ref == i || !mvm->refs[i])
238 continue; 243 continue;
239 244
240 IWL_DEBUG_RPM(mvm, "Cleanup: remove mvm ref type %d\n", i); 245 IWL_DEBUG_RPM(mvm, "Cleanup: remove mvm ref type %d (%d)\n",
241 clear_bit(i, mvm->ref_bitmap); 246 i, mvm->refs[i]);
242 iwl_trans_unref(mvm->trans); 247 for (j = 0; j < mvm->refs[i]; j++)
248 iwl_trans_unref(mvm->trans);
249 mvm->refs[i] = 0;
243 } 250 }
251 spin_unlock_bh(&mvm->refs_lock);
244} 252}
245 253
246static int iwl_mvm_ref_sync(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type) 254int iwl_mvm_ref_sync(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type)
247{ 255{
248 iwl_mvm_ref(mvm, ref_type); 256 iwl_mvm_ref(mvm, ref_type);
249 257
@@ -321,13 +329,6 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
321 hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP; 329 hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP;
322 } 330 }
323 331
324 if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT &&
325 !iwlwifi_mod_params.uapsd_disable) {
326 hw->flags |= IEEE80211_HW_SUPPORTS_UAPSD;
327 hw->uapsd_queues = IWL_UAPSD_AC_INFO;
328 hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP;
329 }
330
331 if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN) 332 if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)
332 hw->flags |= IEEE80211_SINGLE_HW_SCAN_ON_ALL_BANDS; 333 hw->flags |= IEEE80211_SINGLE_HW_SCAN_ON_ALL_BANDS;
333 334
@@ -660,6 +661,7 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac,
660 spin_unlock_bh(&mvm->time_event_lock); 661 spin_unlock_bh(&mvm->time_event_lock);
661 662
662 mvmvif->phy_ctxt = NULL; 663 mvmvif->phy_ctxt = NULL;
664 memset(&mvmvif->bf_data, 0, sizeof(mvmvif->bf_data));
663} 665}
664 666
665#ifdef CONFIG_IWLWIFI_DEBUGFS 667#ifdef CONFIG_IWLWIFI_DEBUGFS
@@ -668,11 +670,11 @@ static void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
668 struct iwl_fw_error_dump_file *dump_file; 670 struct iwl_fw_error_dump_file *dump_file;
669 struct iwl_fw_error_dump_data *dump_data; 671 struct iwl_fw_error_dump_data *dump_data;
670 struct iwl_fw_error_dump_info *dump_info; 672 struct iwl_fw_error_dump_info *dump_info;
673 struct iwl_mvm_dump_ptrs *fw_error_dump;
671 const struct fw_img *img; 674 const struct fw_img *img;
672 u32 sram_len, sram_ofs; 675 u32 sram_len, sram_ofs;
673 u32 file_len, rxf_len; 676 u32 file_len, rxf_len;
674 unsigned long flags; 677 unsigned long flags;
675 u32 trans_len;
676 int reg_val; 678 int reg_val;
677 679
678 lockdep_assert_held(&mvm->mutex); 680 lockdep_assert_held(&mvm->mutex);
@@ -680,6 +682,10 @@ static void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
680 if (mvm->fw_error_dump) 682 if (mvm->fw_error_dump)
681 return; 683 return;
682 684
685 fw_error_dump = kzalloc(sizeof(*mvm->fw_error_dump), GFP_KERNEL);
686 if (!fw_error_dump)
687 return;
688
683 img = &mvm->fw->img[mvm->cur_ucode]; 689 img = &mvm->fw->img[mvm->cur_ucode];
684 sram_ofs = img->sec[IWL_UCODE_SECTION_DATA].offset; 690 sram_ofs = img->sec[IWL_UCODE_SECTION_DATA].offset;
685 sram_len = img->sec[IWL_UCODE_SECTION_DATA].len; 691 sram_len = img->sec[IWL_UCODE_SECTION_DATA].len;
@@ -697,18 +703,15 @@ static void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
697 rxf_len + 703 rxf_len +
698 sizeof(*dump_info); 704 sizeof(*dump_info);
699 705
700 trans_len = iwl_trans_dump_data(mvm->trans, NULL, 0);
701 if (trans_len)
702 file_len += trans_len;
703
704 dump_file = vzalloc(file_len); 706 dump_file = vzalloc(file_len);
705 if (!dump_file) 707 if (!dump_file) {
708 kfree(fw_error_dump);
706 return; 709 return;
710 }
707 711
708 mvm->fw_error_dump = dump_file; 712 fw_error_dump->op_mode_ptr = dump_file;
709 713
710 dump_file->barker = cpu_to_le32(IWL_FW_ERROR_DUMP_BARKER); 714 dump_file->barker = cpu_to_le32(IWL_FW_ERROR_DUMP_BARKER);
711 dump_file->file_len = cpu_to_le32(file_len);
712 dump_data = (void *)dump_file->data; 715 dump_data = (void *)dump_file->data;
713 716
714 dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_DEV_FW_INFO); 717 dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_DEV_FW_INFO);
@@ -749,14 +752,12 @@ static void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
749 iwl_trans_read_mem_bytes(mvm->trans, sram_ofs, dump_data->data, 752 iwl_trans_read_mem_bytes(mvm->trans, sram_ofs, dump_data->data,
750 sram_len); 753 sram_len);
751 754
752 if (trans_len) { 755 fw_error_dump->trans_ptr = iwl_trans_dump_data(mvm->trans);
753 void *buf = iwl_fw_error_next_data(dump_data); 756 fw_error_dump->op_mode_len = file_len;
754 u32 real_trans_len = iwl_trans_dump_data(mvm->trans, buf, 757 if (fw_error_dump->trans_ptr)
755 trans_len); 758 file_len += fw_error_dump->trans_ptr->len;
756 dump_data = (void *)((u8 *)buf + real_trans_len); 759 dump_file->file_len = cpu_to_le32(file_len);
757 dump_file->file_len = 760 mvm->fw_error_dump = fw_error_dump;
758 cpu_to_le32(file_len - trans_len + real_trans_len);
759 }
760} 761}
761#endif 762#endif
762 763
@@ -788,6 +789,12 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
788 iwl_mvm_reset_phy_ctxts(mvm); 789 iwl_mvm_reset_phy_ctxts(mvm);
789 memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table)); 790 memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table));
790 memset(mvm->sta_drained, 0, sizeof(mvm->sta_drained)); 791 memset(mvm->sta_drained, 0, sizeof(mvm->sta_drained));
792 memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif));
793 memset(&mvm->last_bt_notif_old, 0, sizeof(mvm->last_bt_notif_old));
794 memset(&mvm->last_bt_ci_cmd, 0, sizeof(mvm->last_bt_ci_cmd));
795 memset(&mvm->last_bt_ci_cmd_old, 0, sizeof(mvm->last_bt_ci_cmd_old));
796 memset(&mvm->bt_ack_kill_msk, 0, sizeof(mvm->bt_ack_kill_msk));
797 memset(&mvm->bt_cts_kill_msk, 0, sizeof(mvm->bt_cts_kill_msk));
791 798
792 ieee80211_wake_queues(mvm->hw); 799 ieee80211_wake_queues(mvm->hw);
793 800
@@ -1399,6 +1406,28 @@ static inline int iwl_mvm_configure_bcast_filter(struct iwl_mvm *mvm,
1399} 1406}
1400#endif 1407#endif
1401 1408
1409static void iwl_mvm_teardown_tdls_peers(struct iwl_mvm *mvm)
1410{
1411 struct ieee80211_sta *sta;
1412 struct iwl_mvm_sta *mvmsta;
1413 int i;
1414
1415 lockdep_assert_held(&mvm->mutex);
1416
1417 for (i = 0; i < IWL_MVM_STATION_COUNT; i++) {
1418 sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
1419 lockdep_is_held(&mvm->mutex));
1420 if (!sta || IS_ERR(sta) || !sta->tdls)
1421 continue;
1422
1423 mvmsta = iwl_mvm_sta_from_mac80211(sta);
1424 ieee80211_tdls_oper_request(mvmsta->vif, sta->addr,
1425 NL80211_TDLS_TEARDOWN,
1426 WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED,
1427 GFP_KERNEL);
1428 }
1429}
1430
1402static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, 1431static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
1403 struct ieee80211_vif *vif, 1432 struct ieee80211_vif *vif,
1404 struct ieee80211_bss_conf *bss_conf, 1433 struct ieee80211_bss_conf *bss_conf,
@@ -1494,14 +1523,18 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
1494 */ 1523 */
1495 iwl_mvm_remove_time_event(mvm, mvmvif, 1524 iwl_mvm_remove_time_event(mvm, mvmvif,
1496 &mvmvif->time_event_data); 1525 &mvmvif->time_event_data);
1497 iwl_mvm_sf_update(mvm, vif, false);
1498 WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0));
1499 } else if (changes & (BSS_CHANGED_PS | BSS_CHANGED_P2P_PS | 1526 } else if (changes & (BSS_CHANGED_PS | BSS_CHANGED_P2P_PS |
1500 BSS_CHANGED_QOS)) { 1527 BSS_CHANGED_QOS)) {
1501 ret = iwl_mvm_power_update_mac(mvm); 1528 ret = iwl_mvm_power_update_mac(mvm);
1502 if (ret) 1529 if (ret)
1503 IWL_ERR(mvm, "failed to update power mode\n"); 1530 IWL_ERR(mvm, "failed to update power mode\n");
1504 } 1531 }
1532
1533 if (changes & BSS_CHANGED_BEACON_INFO) {
1534 iwl_mvm_sf_update(mvm, vif, false);
1535 WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0));
1536 }
1537
1505 if (changes & BSS_CHANGED_TXPOWER) { 1538 if (changes & BSS_CHANGED_TXPOWER) {
1506 IWL_DEBUG_CALIB(mvm, "Changing TX Power to %d\n", 1539 IWL_DEBUG_CALIB(mvm, "Changing TX Power to %d\n",
1507 bss_conf->txpower); 1540 bss_conf->txpower);
@@ -1533,6 +1566,14 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
1533 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 1566 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1534 int ret; 1567 int ret;
1535 1568
1569 /*
1570 * iwl_mvm_mac_ctxt_add() might read directly from the device
1571 * (the system time), so make sure it is available.
1572 */
1573 ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_START_AP);
1574 if (ret)
1575 return ret;
1576
1536 mutex_lock(&mvm->mutex); 1577 mutex_lock(&mvm->mutex);
1537 1578
1538 /* Send the beacon template */ 1579 /* Send the beacon template */
@@ -1581,6 +1622,10 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
1581 1622
1582 iwl_mvm_bt_coex_vif_change(mvm); 1623 iwl_mvm_bt_coex_vif_change(mvm);
1583 1624
1625 /* we don't support TDLS during DCM */
1626 if (iwl_mvm_phy_ctx_count(mvm) > 1)
1627 iwl_mvm_teardown_tdls_peers(mvm);
1628
1584 mutex_unlock(&mvm->mutex); 1629 mutex_unlock(&mvm->mutex);
1585 return 0; 1630 return 0;
1586 1631
@@ -1594,6 +1639,7 @@ out_remove:
1594 iwl_mvm_mac_ctxt_remove(mvm, vif); 1639 iwl_mvm_mac_ctxt_remove(mvm, vif);
1595out_unlock: 1640out_unlock:
1596 mutex_unlock(&mvm->mutex); 1641 mutex_unlock(&mvm->mutex);
1642 iwl_mvm_unref(mvm, IWL_MVM_REF_START_AP);
1597 return ret; 1643 return ret;
1598} 1644}
1599 1645
@@ -1671,6 +1717,14 @@ static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw,
1671{ 1717{
1672 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); 1718 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
1673 1719
1720 /*
1721 * iwl_mvm_bss_info_changed_station() might call
1722 * iwl_mvm_protect_session(), which reads directly from
1723 * the device (the system time), so make sure it is available.
1724 */
1725 if (iwl_mvm_ref_sync(mvm, IWL_MVM_REF_BSS_CHANGED))
1726 return;
1727
1674 mutex_lock(&mvm->mutex); 1728 mutex_lock(&mvm->mutex);
1675 1729
1676 if (changes & BSS_CHANGED_IDLE && !bss_conf->idle) 1730 if (changes & BSS_CHANGED_IDLE && !bss_conf->idle)
@@ -1690,8 +1744,50 @@ static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw,
1690 } 1744 }
1691 1745
1692 mutex_unlock(&mvm->mutex); 1746 mutex_unlock(&mvm->mutex);
1747 iwl_mvm_unref(mvm, IWL_MVM_REF_BSS_CHANGED);
1693} 1748}
1694 1749
1750static int iwl_mvm_cancel_scan_wait_notif(struct iwl_mvm *mvm,
1751 enum iwl_scan_status scan_type)
1752{
1753 int ret;
1754 bool wait_for_handlers = false;
1755
1756 mutex_lock(&mvm->mutex);
1757
1758 if (mvm->scan_status != scan_type) {
1759 ret = 0;
1760 /* make sure there are no pending notifications */
1761 wait_for_handlers = true;
1762 goto out;
1763 }
1764
1765 switch (scan_type) {
1766 case IWL_MVM_SCAN_SCHED:
1767 ret = iwl_mvm_scan_offload_stop(mvm, true);
1768 break;
1769 case IWL_MVM_SCAN_OS:
1770 ret = iwl_mvm_cancel_scan(mvm);
1771 break;
1772 case IWL_MVM_SCAN_NONE:
1773 default:
1774 WARN_ON_ONCE(1);
1775 ret = -EINVAL;
1776 break;
1777 }
1778 if (ret)
1779 goto out;
1780
1781 wait_for_handlers = true;
1782out:
1783 mutex_unlock(&mvm->mutex);
1784
1785 /* make sure we consume the completion notification */
1786 if (wait_for_handlers)
1787 iwl_mvm_wait_for_async_handlers(mvm);
1788
1789 return ret;
1790}
1695static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw, 1791static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw,
1696 struct ieee80211_vif *vif, 1792 struct ieee80211_vif *vif,
1697 struct ieee80211_scan_request *hw_req) 1793 struct ieee80211_scan_request *hw_req)
@@ -1704,19 +1800,13 @@ static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw,
1704 req->n_channels > mvm->fw->ucode_capa.n_scan_channels) 1800 req->n_channels > mvm->fw->ucode_capa.n_scan_channels)
1705 return -EINVAL; 1801 return -EINVAL;
1706 1802
1803 ret = iwl_mvm_cancel_scan_wait_notif(mvm, IWL_MVM_SCAN_SCHED);
1804 if (ret)
1805 return ret;
1806
1707 mutex_lock(&mvm->mutex); 1807 mutex_lock(&mvm->mutex);
1708 1808
1709 switch (mvm->scan_status) { 1809 if (mvm->scan_status != IWL_MVM_SCAN_NONE) {
1710 case IWL_MVM_SCAN_SCHED:
1711 ret = iwl_mvm_scan_offload_stop(mvm, true);
1712 if (ret) {
1713 ret = -EBUSY;
1714 goto out;
1715 }
1716 break;
1717 case IWL_MVM_SCAN_NONE:
1718 break;
1719 default:
1720 ret = -EBUSY; 1810 ret = -EBUSY;
1721 goto out; 1811 goto out;
1722 } 1812 }
@@ -1732,8 +1822,6 @@ static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw,
1732 iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); 1822 iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
1733out: 1823out:
1734 mutex_unlock(&mvm->mutex); 1824 mutex_unlock(&mvm->mutex);
1735 /* make sure to flush the Rx handler before the next scan arrives */
1736 iwl_mvm_wait_for_async_handlers(mvm);
1737 return ret; 1825 return ret;
1738} 1826}
1739 1827
@@ -1885,28 +1973,6 @@ static void iwl_mvm_recalc_tdls_state(struct iwl_mvm *mvm,
1885 iwl_mvm_power_update_mac(mvm); 1973 iwl_mvm_power_update_mac(mvm);
1886} 1974}
1887 1975
1888static void iwl_mvm_teardown_tdls_peers(struct iwl_mvm *mvm)
1889{
1890 struct ieee80211_sta *sta;
1891 struct iwl_mvm_sta *mvmsta;
1892 int i;
1893
1894 lockdep_assert_held(&mvm->mutex);
1895
1896 for (i = 0; i < IWL_MVM_STATION_COUNT; i++) {
1897 sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
1898 lockdep_is_held(&mvm->mutex));
1899 if (!sta || IS_ERR(sta) || !sta->tdls)
1900 continue;
1901
1902 mvmsta = iwl_mvm_sta_from_mac80211(sta);
1903 ieee80211_tdls_oper_request(mvmsta->vif, sta->addr,
1904 NL80211_TDLS_TEARDOWN,
1905 WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED,
1906 GFP_KERNEL);
1907 }
1908}
1909
1910static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, 1976static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
1911 struct ieee80211_vif *vif, 1977 struct ieee80211_vif *vif,
1912 struct ieee80211_sta *sta, 1978 struct ieee80211_sta *sta,
@@ -2065,10 +2131,19 @@ static void iwl_mvm_mac_mgd_prepare_tx(struct ieee80211_hw *hw,
2065 if (WARN_ON_ONCE(vif->bss_conf.assoc)) 2131 if (WARN_ON_ONCE(vif->bss_conf.assoc))
2066 return; 2132 return;
2067 2133
2134 /*
2135 * iwl_mvm_protect_session() reads directly from the device
2136 * (the system time), so make sure it is available.
2137 */
2138 if (iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PREPARE_TX))
2139 return;
2140
2068 mutex_lock(&mvm->mutex); 2141 mutex_lock(&mvm->mutex);
2069 /* Try really hard to protect the session and hear a beacon */ 2142 /* Try really hard to protect the session and hear a beacon */
2070 iwl_mvm_protect_session(mvm, vif, duration, min_duration, 500); 2143 iwl_mvm_protect_session(mvm, vif, duration, min_duration, 500);
2071 mutex_unlock(&mvm->mutex); 2144 mutex_unlock(&mvm->mutex);
2145
2146 iwl_mvm_unref(mvm, IWL_MVM_REF_PREPARE_TX);
2072} 2147}
2073 2148
2074static void iwl_mvm_mac_mgd_protect_tdls_discover(struct ieee80211_hw *hw, 2149static void iwl_mvm_mac_mgd_protect_tdls_discover(struct ieee80211_hw *hw,
@@ -2077,10 +2152,19 @@ static void iwl_mvm_mac_mgd_protect_tdls_discover(struct ieee80211_hw *hw,
2077 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); 2152 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
2078 u32 duration = 2 * vif->bss_conf.dtim_period * vif->bss_conf.beacon_int; 2153 u32 duration = 2 * vif->bss_conf.dtim_period * vif->bss_conf.beacon_int;
2079 2154
2155 /*
2156 * iwl_mvm_protect_session() reads directly from the device
2157 * (the system time), so make sure it is available.
2158 */
2159 if (iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PROTECT_TDLS))
2160 return;
2161
2080 mutex_lock(&mvm->mutex); 2162 mutex_lock(&mvm->mutex);
2081 /* Protect the session to hear the TDLS setup response on the channel */ 2163 /* Protect the session to hear the TDLS setup response on the channel */
2082 iwl_mvm_protect_session(mvm, vif, duration, duration, 100); 2164 iwl_mvm_protect_session(mvm, vif, duration, duration, 100);
2083 mutex_unlock(&mvm->mutex); 2165 mutex_unlock(&mvm->mutex);
2166
2167 iwl_mvm_unref(mvm, IWL_MVM_REF_PROTECT_TDLS);
2084} 2168}
2085 2169
2086static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw, 2170static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw,
@@ -2091,6 +2175,10 @@ static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw,
2091 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); 2175 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
2092 int ret; 2176 int ret;
2093 2177
2178 ret = iwl_mvm_cancel_scan_wait_notif(mvm, IWL_MVM_SCAN_OS);
2179 if (ret)
2180 return ret;
2181
2094 mutex_lock(&mvm->mutex); 2182 mutex_lock(&mvm->mutex);
2095 2183
2096 if (!iwl_mvm_is_idle(mvm)) { 2184 if (!iwl_mvm_is_idle(mvm)) {
@@ -2098,26 +2186,7 @@ static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw,
2098 goto out; 2186 goto out;
2099 } 2187 }
2100 2188
2101 switch (mvm->scan_status) { 2189 if (mvm->scan_status != IWL_MVM_SCAN_NONE) {
2102 case IWL_MVM_SCAN_OS:
2103 IWL_DEBUG_SCAN(mvm, "Stopping previous scan for sched_scan\n");
2104 ret = iwl_mvm_cancel_scan(mvm);
2105 if (ret) {
2106 ret = -EBUSY;
2107 goto out;
2108 }
2109
2110 /*
2111 * iwl_mvm_rx_scan_complete() will be called soon but will
2112 * not reset the scan status as it won't be IWL_MVM_SCAN_OS
2113 * any more since we queue the next scan immediately (below).
2114 * We make sure it is called before the next scan starts by
2115 * flushing the async-handlers work.
2116 */
2117 break;
2118 case IWL_MVM_SCAN_NONE:
2119 break;
2120 default:
2121 ret = -EBUSY; 2190 ret = -EBUSY;
2122 goto out; 2191 goto out;
2123 } 2192 }
@@ -2145,8 +2214,6 @@ err:
2145 mvm->scan_status = IWL_MVM_SCAN_NONE; 2214 mvm->scan_status = IWL_MVM_SCAN_NONE;
2146out: 2215out:
2147 mutex_unlock(&mvm->mutex); 2216 mutex_unlock(&mvm->mutex);
2148 /* make sure to flush the Rx handler before the next scan arrives */
2149 iwl_mvm_wait_for_async_handlers(mvm);
2150 return ret; 2217 return ret;
2151} 2218}
2152 2219
@@ -2266,6 +2333,119 @@ static void iwl_mvm_mac_update_tkip_key(struct ieee80211_hw *hw,
2266} 2333}
2267 2334
2268 2335
2336static bool iwl_mvm_rx_aux_roc(struct iwl_notif_wait_data *notif_wait,
2337 struct iwl_rx_packet *pkt, void *data)
2338{
2339 struct iwl_mvm *mvm =
2340 container_of(notif_wait, struct iwl_mvm, notif_wait);
2341 struct iwl_hs20_roc_res *resp;
2342 int resp_len = iwl_rx_packet_payload_len(pkt);
2343 struct iwl_mvm_time_event_data *te_data = data;
2344
2345 if (WARN_ON(pkt->hdr.cmd != HOT_SPOT_CMD))
2346 return true;
2347
2348 if (WARN_ON_ONCE(resp_len != sizeof(*resp))) {
2349 IWL_ERR(mvm, "Invalid HOT_SPOT_CMD response\n");
2350 return true;
2351 }
2352
2353 resp = (void *)pkt->data;
2354
2355 IWL_DEBUG_TE(mvm,
2356 "Aux ROC: Recieved response from ucode: status=%d uid=%d\n",
2357 resp->status, resp->event_unique_id);
2358
2359 te_data->uid = le32_to_cpu(resp->event_unique_id);
2360 IWL_DEBUG_TE(mvm, "TIME_EVENT_CMD response - UID = 0x%x\n",
2361 te_data->uid);
2362
2363 spin_lock_bh(&mvm->time_event_lock);
2364 list_add_tail(&te_data->list, &mvm->aux_roc_te_list);
2365 spin_unlock_bh(&mvm->time_event_lock);
2366
2367 return true;
2368}
2369
2370#define AUX_ROC_MAX_DELAY_ON_CHANNEL 5000
2371static int iwl_mvm_send_aux_roc_cmd(struct iwl_mvm *mvm,
2372 struct ieee80211_channel *channel,
2373 struct ieee80211_vif *vif,
2374 int duration)
2375{
2376 int res, time_reg = DEVICE_SYSTEM_TIME_REG;
2377 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
2378 struct iwl_mvm_time_event_data *te_data = &mvmvif->hs_time_event_data;
2379 static const u8 time_event_response[] = { HOT_SPOT_CMD };
2380 struct iwl_notification_wait wait_time_event;
2381 struct iwl_hs20_roc_req aux_roc_req = {
2382 .action = cpu_to_le32(FW_CTXT_ACTION_ADD),
2383 .id_and_color =
2384 cpu_to_le32(FW_CMD_ID_AND_COLOR(MAC_INDEX_AUX, 0)),
2385 .sta_id_and_color = cpu_to_le32(mvm->aux_sta.sta_id),
2386 /* Set the channel info data */
2387 .channel_info.band = (channel->band == IEEE80211_BAND_2GHZ) ?
2388 PHY_BAND_24 : PHY_BAND_5,
2389 .channel_info.channel = channel->hw_value,
2390 .channel_info.width = PHY_VHT_CHANNEL_MODE20,
2391 /* Set the time and duration */
2392 .apply_time = cpu_to_le32(iwl_read_prph(mvm->trans, time_reg)),
2393 .apply_time_max_delay =
2394 cpu_to_le32(MSEC_TO_TU(AUX_ROC_MAX_DELAY_ON_CHANNEL)),
2395 .duration = cpu_to_le32(MSEC_TO_TU(duration)),
2396 };
2397
2398 /* Set the node address */
2399 memcpy(aux_roc_req.node_addr, vif->addr, ETH_ALEN);
2400
2401 te_data->vif = vif;
2402 te_data->duration = duration;
2403 te_data->id = HOT_SPOT_CMD;
2404
2405 lockdep_assert_held(&mvm->mutex);
2406
2407 spin_lock_bh(&mvm->time_event_lock);
2408 list_add_tail(&te_data->list, &mvm->time_event_list);
2409 spin_unlock_bh(&mvm->time_event_lock);
2410
2411 /*
2412 * Use a notification wait, which really just processes the
2413 * command response and doesn't wait for anything, in order
2414 * to be able to process the response and get the UID inside
2415 * the RX path. Using CMD_WANT_SKB doesn't work because it
2416 * stores the buffer and then wakes up this thread, by which
2417 * time another notification (that the time event started)
2418 * might already be processed unsuccessfully.
2419 */
2420 iwl_init_notification_wait(&mvm->notif_wait, &wait_time_event,
2421 time_event_response,
2422 ARRAY_SIZE(time_event_response),
2423 iwl_mvm_rx_aux_roc, te_data);
2424
2425 res = iwl_mvm_send_cmd_pdu(mvm, HOT_SPOT_CMD, 0, sizeof(aux_roc_req),
2426 &aux_roc_req);
2427
2428 if (res) {
2429 IWL_ERR(mvm, "Couldn't send HOT_SPOT_CMD: %d\n", res);
2430 iwl_remove_notification(&mvm->notif_wait, &wait_time_event);
2431 goto out_clear_te;
2432 }
2433
2434 /* No need to wait for anything, so just pass 1 (0 isn't valid) */
2435 res = iwl_wait_notification(&mvm->notif_wait, &wait_time_event, 1);
2436 /* should never fail */
2437 WARN_ON_ONCE(res);
2438
2439 if (res) {
2440 out_clear_te:
2441 spin_lock_bh(&mvm->time_event_lock);
2442 iwl_mvm_te_clear_data(mvm, te_data);
2443 spin_unlock_bh(&mvm->time_event_lock);
2444 }
2445
2446 return res;
2447}
2448
2269static int iwl_mvm_roc(struct ieee80211_hw *hw, 2449static int iwl_mvm_roc(struct ieee80211_hw *hw,
2270 struct ieee80211_vif *vif, 2450 struct ieee80211_vif *vif,
2271 struct ieee80211_channel *channel, 2451 struct ieee80211_channel *channel,
@@ -2281,8 +2461,17 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw,
2281 IWL_DEBUG_MAC80211(mvm, "enter (%d, %d, %d)\n", channel->hw_value, 2461 IWL_DEBUG_MAC80211(mvm, "enter (%d, %d, %d)\n", channel->hw_value,
2282 duration, type); 2462 duration, type);
2283 2463
2284 if (vif->type != NL80211_IFTYPE_P2P_DEVICE) { 2464 switch (vif->type) {
2285 IWL_ERR(mvm, "vif isn't a P2P_DEVICE: %d\n", vif->type); 2465 case NL80211_IFTYPE_STATION:
2466 /* Use aux roc framework (HS20) */
2467 ret = iwl_mvm_send_aux_roc_cmd(mvm, channel,
2468 vif, duration);
2469 return ret;
2470 case NL80211_IFTYPE_P2P_DEVICE:
2471 /* handle below */
2472 break;
2473 default:
2474 IWL_ERR(mvm, "vif isn't P2P_DEVICE: %d\n", vif->type);
2286 return -EINVAL; 2475 return -EINVAL;
2287 } 2476 }
2288 2477
@@ -2661,6 +2850,10 @@ static int iwl_mvm_switch_vif_chanctx(struct ieee80211_hw *hw,
2661 goto out_remove; 2850 goto out_remove;
2662 } 2851 }
2663 2852
2853 /* we don't support TDLS during DCM - can be caused by channel switch */
2854 if (iwl_mvm_phy_ctx_count(mvm) > 1)
2855 iwl_mvm_teardown_tdls_peers(mvm);
2856
2664 goto out; 2857 goto out;
2665 2858
2666out_remove: 2859out_remove:
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h
index 785e5232c757..2e73d3bd7757 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h
@@ -82,6 +82,8 @@
82/* RSSI offset for WkP */ 82/* RSSI offset for WkP */
83#define IWL_RSSI_OFFSET 50 83#define IWL_RSSI_OFFSET 50
84#define IWL_MVM_MISSED_BEACONS_THRESHOLD 8 84#define IWL_MVM_MISSED_BEACONS_THRESHOLD 8
85/* A TimeUnit is 1024 microsecond */
86#define MSEC_TO_TU(_msec) (_msec*1000/1024)
85 87
86/* 88/*
87 * The CSA NoA is scheduled IWL_MVM_CHANNEL_SWITCH_TIME TUs before "beacon 0" 89 * The CSA NoA is scheduled IWL_MVM_CHANNEL_SWITCH_TIME TUs before "beacon 0"
@@ -126,6 +128,21 @@ struct iwl_mvm_mod_params {
126}; 128};
127extern struct iwl_mvm_mod_params iwlmvm_mod_params; 129extern struct iwl_mvm_mod_params iwlmvm_mod_params;
128 130
131/**
132 * struct iwl_mvm_dump_ptrs - set of pointers needed for the fw-error-dump
133 *
134 * @op_mode_ptr: pointer to the buffer coming from the mvm op_mode
135 * @trans_ptr: pointer to struct %iwl_trans_dump_data which contains the
136 * transport's data.
137 * @trans_len: length of the valid data in trans_ptr
138 * @op_mode_len: length of the valid data in op_mode_ptr
139 */
140struct iwl_mvm_dump_ptrs {
141 struct iwl_trans_dump_data *trans_ptr;
142 void *op_mode_ptr;
143 u32 op_mode_len;
144};
145
129struct iwl_mvm_phy_ctxt { 146struct iwl_mvm_phy_ctxt {
130 u16 id; 147 u16 id;
131 u16 color; 148 u16 color;
@@ -249,6 +266,15 @@ enum iwl_mvm_ref_type {
249 IWL_MVM_REF_TX, 266 IWL_MVM_REF_TX,
250 IWL_MVM_REF_TX_AGG, 267 IWL_MVM_REF_TX_AGG,
251 IWL_MVM_REF_ADD_IF, 268 IWL_MVM_REF_ADD_IF,
269 IWL_MVM_REF_START_AP,
270 IWL_MVM_REF_BSS_CHANGED,
271 IWL_MVM_REF_PREPARE_TX,
272 IWL_MVM_REF_PROTECT_TDLS,
273 IWL_MVM_REF_CHECK_CTKILL,
274 IWL_MVM_REF_PRPH_READ,
275 IWL_MVM_REF_PRPH_WRITE,
276 IWL_MVM_REF_NMI,
277 IWL_MVM_REF_TM_CMD,
252 IWL_MVM_REF_EXIT_WORK, 278 IWL_MVM_REF_EXIT_WORK,
253 279
254 IWL_MVM_REF_COUNT, 280 IWL_MVM_REF_COUNT,
@@ -327,6 +353,7 @@ struct iwl_mvm_vif {
327 */ 353 */
328 struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS]; 354 struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS];
329 struct iwl_mvm_time_event_data time_event_data; 355 struct iwl_mvm_time_event_data time_event_data;
356 struct iwl_mvm_time_event_data hs_time_event_data;
330 357
331 struct iwl_mvm_int_sta bcast_sta; 358 struct iwl_mvm_int_sta bcast_sta;
332 359
@@ -606,14 +633,15 @@ struct iwl_mvm {
606 */ 633 */
607 unsigned long fw_key_table[BITS_TO_LONGS(STA_KEY_MAX_NUM)]; 634 unsigned long fw_key_table[BITS_TO_LONGS(STA_KEY_MAX_NUM)];
608 635
609 /* A bitmap of reference types taken by the driver. */ 636 /* references taken by the driver and spinlock protecting them */
610 unsigned long ref_bitmap[BITS_TO_LONGS(IWL_MVM_REF_COUNT)]; 637 spinlock_t refs_lock;
638 u8 refs[IWL_MVM_REF_COUNT];
611 639
612 u8 vif_count; 640 u8 vif_count;
613 641
614 /* -1 for always, 0 for never, >0 for that many times */ 642 /* -1 for always, 0 for never, >0 for that many times */
615 s8 restart_fw; 643 s8 restart_fw;
616 void *fw_error_dump; 644 struct iwl_mvm_dump_ptrs *fw_error_dump;
617 645
618#ifdef CONFIG_IWLWIFI_LEDS 646#ifdef CONFIG_IWLWIFI_LEDS
619 struct led_classdev led; 647 struct led_classdev led;
@@ -647,7 +675,8 @@ struct iwl_mvm {
647 wait_queue_head_t d0i3_exit_waitq; 675 wait_queue_head_t d0i3_exit_waitq;
648 676
649 /* BT-Coex */ 677 /* BT-Coex */
650 u8 bt_kill_msk; 678 u8 bt_ack_kill_msk[NUM_PHY_CTX];
679 u8 bt_cts_kill_msk[NUM_PHY_CTX];
651 680
652 struct iwl_bt_coex_profile_notif_old last_bt_notif_old; 681 struct iwl_bt_coex_profile_notif_old last_bt_notif_old;
653 struct iwl_bt_coex_ci_cmd_old last_bt_ci_cmd_old; 682 struct iwl_bt_coex_ci_cmd_old last_bt_ci_cmd_old;
@@ -659,6 +688,9 @@ struct iwl_mvm {
659 u8 bt_tx_prio; 688 u8 bt_tx_prio;
660 enum iwl_bt_force_ant_mode bt_force_ant_mode; 689 enum iwl_bt_force_ant_mode bt_force_ant_mode;
661 690
691 /* Aux ROC */
692 struct list_head aux_roc_te_list;
693
662 /* Thermal Throttling and CTkill */ 694 /* Thermal Throttling and CTkill */
663 struct iwl_mvm_tt_mgmt thermal_throttle; 695 struct iwl_mvm_tt_mgmt thermal_throttle;
664 s32 temperature; /* Celsius */ 696 s32 temperature; /* Celsius */
@@ -697,6 +729,7 @@ enum iwl_mvm_status {
697 IWL_MVM_STATUS_ROC_RUNNING, 729 IWL_MVM_STATUS_ROC_RUNNING,
698 IWL_MVM_STATUS_IN_HW_RESTART, 730 IWL_MVM_STATUS_IN_HW_RESTART,
699 IWL_MVM_STATUS_IN_D0I3, 731 IWL_MVM_STATUS_IN_D0I3,
732 IWL_MVM_STATUS_ROC_AUX_RUNNING,
700}; 733};
701 734
702static inline bool iwl_mvm_is_radio_killed(struct iwl_mvm *mvm) 735static inline bool iwl_mvm_is_radio_killed(struct iwl_mvm *mvm)
@@ -988,6 +1021,7 @@ int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm,
988/* D0i3 */ 1021/* D0i3 */
989void iwl_mvm_ref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type); 1022void iwl_mvm_ref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type);
990void iwl_mvm_unref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type); 1023void iwl_mvm_unref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type);
1024int iwl_mvm_ref_sync(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type);
991void iwl_mvm_d0i3_enable_tx(struct iwl_mvm *mvm, __le16 *qos_seq); 1025void iwl_mvm_d0i3_enable_tx(struct iwl_mvm *mvm, __le16 *qos_seq);
992int _iwl_mvm_exit_d0i3(struct iwl_mvm *mvm); 1026int _iwl_mvm_exit_d0i3(struct iwl_mvm *mvm);
993 1027
@@ -1029,12 +1063,14 @@ int iwl_mvm_rx_ant_coupling_notif_old(struct iwl_mvm *mvm,
1029 1063
1030enum iwl_bt_kill_msk { 1064enum iwl_bt_kill_msk {
1031 BT_KILL_MSK_DEFAULT, 1065 BT_KILL_MSK_DEFAULT,
1032 BT_KILL_MSK_SCO_HID_A2DP, 1066 BT_KILL_MSK_NEVER,
1033 BT_KILL_MSK_REDUCED_TXPOW, 1067 BT_KILL_MSK_ALWAYS,
1034 BT_KILL_MSK_MAX, 1068 BT_KILL_MSK_MAX,
1035}; 1069};
1036extern const u32 iwl_bt_ack_kill_msk[BT_KILL_MSK_MAX]; 1070
1037extern const u32 iwl_bt_cts_kill_msk[BT_KILL_MSK_MAX]; 1071extern const u8 iwl_bt_ack_kill_msk[BT_MAX_AG][BT_COEX_MAX_LUT];
1072extern const u8 iwl_bt_cts_kill_msk[BT_MAX_AG][BT_COEX_MAX_LUT];
1073extern const u32 iwl_bt_ctl_kill_msk[BT_KILL_MSK_MAX];
1038 1074
1039/* beacon filtering */ 1075/* beacon filtering */
1040#ifdef CONFIG_IWLWIFI_DEBUGFS 1076#ifdef CONFIG_IWLWIFI_DEBUGFS
diff --git a/drivers/net/wireless/iwlwifi/mvm/nvm.c b/drivers/net/wireless/iwlwifi/mvm/nvm.c
index b04805ccb443..cfdd314fdd5d 100644
--- a/drivers/net/wireless/iwlwifi/mvm/nvm.c
+++ b/drivers/net/wireless/iwlwifi/mvm/nvm.c
@@ -265,7 +265,7 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm)
265 if (mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) { 265 if (mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) {
266 if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data || 266 if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data ||
267 !mvm->nvm_sections[mvm->cfg->nvm_hw_section_num].data) { 267 !mvm->nvm_sections[mvm->cfg->nvm_hw_section_num].data) {
268 IWL_ERR(mvm, "Can't parse empty NVM sections\n"); 268 IWL_ERR(mvm, "Can't parse empty OTP/NVM sections\n");
269 return NULL; 269 return NULL;
270 } 270 }
271 } else { 271 } else {
@@ -273,7 +273,7 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm)
273 if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data || 273 if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data ||
274 !mvm->nvm_sections[NVM_SECTION_TYPE_REGULATORY].data) { 274 !mvm->nvm_sections[NVM_SECTION_TYPE_REGULATORY].data) {
275 IWL_ERR(mvm, 275 IWL_ERR(mvm,
276 "Can't parse empty family 8000 NVM sections\n"); 276 "Can't parse empty family 8000 OTP/NVM sections\n");
277 return NULL; 277 return NULL;
278 } 278 }
279 /* MAC_OVERRIDE or at least HW section must exist */ 279 /* MAC_OVERRIDE or at least HW section must exist */
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c
index 7d7b2fbe7cd1..610dbcb0dc27 100644
--- a/drivers/net/wireless/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/iwlwifi/mvm/ops.c
@@ -289,6 +289,7 @@ static const char *const iwl_mvm_cmd_strings[REPLY_MAX] = {
289 CMD(MATCH_FOUND_NOTIFICATION), 289 CMD(MATCH_FOUND_NOTIFICATION),
290 CMD(SCAN_OFFLOAD_REQUEST_CMD), 290 CMD(SCAN_OFFLOAD_REQUEST_CMD),
291 CMD(SCAN_OFFLOAD_ABORT_CMD), 291 CMD(SCAN_OFFLOAD_ABORT_CMD),
292 CMD(HOT_SPOT_CMD),
292 CMD(SCAN_OFFLOAD_COMPLETE), 293 CMD(SCAN_OFFLOAD_COMPLETE),
293 CMD(SCAN_OFFLOAD_UPDATE_PROFILES_CMD), 294 CMD(SCAN_OFFLOAD_UPDATE_PROFILES_CMD),
294 CMD(SCAN_ITERATION_COMPLETE), 295 CMD(SCAN_ITERATION_COMPLETE),
@@ -391,6 +392,9 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
391 if (!hw) 392 if (!hw)
392 return NULL; 393 return NULL;
393 394
395 if (cfg->max_rx_agg_size)
396 hw->max_rx_aggregation_subframes = cfg->max_rx_agg_size;
397
394 op_mode = hw->priv; 398 op_mode = hw->priv;
395 op_mode->ops = &iwl_mvm_ops; 399 op_mode->ops = &iwl_mvm_ops;
396 400
@@ -416,6 +420,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
416 mutex_init(&mvm->d0i3_suspend_mutex); 420 mutex_init(&mvm->d0i3_suspend_mutex);
417 spin_lock_init(&mvm->async_handlers_lock); 421 spin_lock_init(&mvm->async_handlers_lock);
418 INIT_LIST_HEAD(&mvm->time_event_list); 422 INIT_LIST_HEAD(&mvm->time_event_list);
423 INIT_LIST_HEAD(&mvm->aux_roc_te_list);
419 INIT_LIST_HEAD(&mvm->async_handlers_list); 424 INIT_LIST_HEAD(&mvm->async_handlers_list);
420 spin_lock_init(&mvm->time_event_lock); 425 spin_lock_init(&mvm->time_event_lock);
421 426
@@ -425,6 +430,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
425 INIT_WORK(&mvm->d0i3_exit_work, iwl_mvm_d0i3_exit_work); 430 INIT_WORK(&mvm->d0i3_exit_work, iwl_mvm_d0i3_exit_work);
426 431
427 spin_lock_init(&mvm->d0i3_tx_lock); 432 spin_lock_init(&mvm->d0i3_tx_lock);
433 spin_lock_init(&mvm->refs_lock);
428 skb_queue_head_init(&mvm->d0i3_tx); 434 skb_queue_head_init(&mvm->d0i3_tx);
429 init_waitqueue_head(&mvm->d0i3_exit_waitq); 435 init_waitqueue_head(&mvm->d0i3_exit_waitq);
430 436
@@ -539,7 +545,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
539 memset(&mvm->rx_stats, 0, sizeof(struct mvm_statistics_rx)); 545 memset(&mvm->rx_stats, 0, sizeof(struct mvm_statistics_rx));
540 546
541 /* rpm starts with a taken ref. only set the appropriate bit here. */ 547 /* rpm starts with a taken ref. only set the appropriate bit here. */
542 set_bit(IWL_MVM_REF_UCODE_DOWN, mvm->ref_bitmap); 548 mvm->refs[IWL_MVM_REF_UCODE_DOWN] = 1;
543 549
544 return op_mode; 550 return op_mode;
545 551
@@ -567,7 +573,11 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode)
567 ieee80211_unregister_hw(mvm->hw); 573 ieee80211_unregister_hw(mvm->hw);
568 574
569 kfree(mvm->scan_cmd); 575 kfree(mvm->scan_cmd);
570 vfree(mvm->fw_error_dump); 576 if (mvm->fw_error_dump) {
577 vfree(mvm->fw_error_dump->op_mode_ptr);
578 vfree(mvm->fw_error_dump->trans_ptr);
579 kfree(mvm->fw_error_dump);
580 }
571 kfree(mvm->mcast_filter_cmd); 581 kfree(mvm->mcast_filter_cmd);
572 mvm->mcast_filter_cmd = NULL; 582 mvm->mcast_filter_cmd = NULL;
573 583
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c
index 812813964847..763548880399 100644
--- a/drivers/net/wireless/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/iwlwifi/mvm/sta.c
@@ -98,23 +98,21 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
98 bool update) 98 bool update)
99{ 99{
100 struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv; 100 struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv;
101 struct iwl_mvm_add_sta_cmd add_sta_cmd; 101 struct iwl_mvm_add_sta_cmd add_sta_cmd = {
102 .sta_id = mvm_sta->sta_id,
103 .mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color),
104 .add_modify = update ? 1 : 0,
105 .station_flags_msk = cpu_to_le32(STA_FLG_FAT_EN_MSK |
106 STA_FLG_MIMO_EN_MSK),
107 };
102 int ret; 108 int ret;
103 u32 status; 109 u32 status;
104 u32 agg_size = 0, mpdu_dens = 0; 110 u32 agg_size = 0, mpdu_dens = 0;
105 111
106 memset(&add_sta_cmd, 0, sizeof(add_sta_cmd));
107
108 add_sta_cmd.sta_id = mvm_sta->sta_id;
109 add_sta_cmd.mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color);
110 if (!update) { 112 if (!update) {
111 add_sta_cmd.tfd_queue_msk = cpu_to_le32(mvm_sta->tfd_queue_msk); 113 add_sta_cmd.tfd_queue_msk = cpu_to_le32(mvm_sta->tfd_queue_msk);
112 memcpy(&add_sta_cmd.addr, sta->addr, ETH_ALEN); 114 memcpy(&add_sta_cmd.addr, sta->addr, ETH_ALEN);
113 } 115 }
114 add_sta_cmd.add_modify = update ? 1 : 0;
115
116 add_sta_cmd.station_flags_msk |= cpu_to_le32(STA_FLG_FAT_EN_MSK |
117 STA_FLG_MIMO_EN_MSK);
118 116
119 switch (sta->bandwidth) { 117 switch (sta->bandwidth) {
120 case IEEE80211_STA_RX_BW_160: 118 case IEEE80211_STA_RX_BW_160:
@@ -528,8 +526,12 @@ int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm)
528 526
529 lockdep_assert_held(&mvm->mutex); 527 lockdep_assert_held(&mvm->mutex);
530 528
531 /* Add the aux station, but without any queues */ 529 /* Map Aux queue to fifo - needs to happen before adding Aux station */
532 ret = iwl_mvm_allocate_int_sta(mvm, &mvm->aux_sta, 0, 530 iwl_trans_ac_txq_enable(mvm->trans, mvm->aux_queue,
531 IWL_MVM_TX_FIFO_MCAST);
532
533 /* Allocate aux station and assign to it the aux queue */
534 ret = iwl_mvm_allocate_int_sta(mvm, &mvm->aux_sta, BIT(mvm->aux_queue),
533 NL80211_IFTYPE_UNSPECIFIED); 535 NL80211_IFTYPE_UNSPECIFIED);
534 if (ret) 536 if (ret)
535 return ret; 537 return ret;
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.c b/drivers/net/wireless/iwlwifi/mvm/time-event.c
index ae52613b97f2..33e5041f1efc 100644
--- a/drivers/net/wireless/iwlwifi/mvm/time-event.c
+++ b/drivers/net/wireless/iwlwifi/mvm/time-event.c
@@ -72,9 +72,6 @@
72#include "iwl-io.h" 72#include "iwl-io.h"
73#include "iwl-prph.h" 73#include "iwl-prph.h"
74 74
75/* A TimeUnit is 1024 microsecond */
76#define MSEC_TO_TU(_msec) (_msec*1000/1024)
77
78/* 75/*
79 * For the high priority TE use a time event type that has similar priority to 76 * For the high priority TE use a time event type that has similar priority to
80 * the FW's action scan priority. 77 * the FW's action scan priority.
@@ -100,6 +97,21 @@ void iwl_mvm_te_clear_data(struct iwl_mvm *mvm,
100void iwl_mvm_roc_done_wk(struct work_struct *wk) 97void iwl_mvm_roc_done_wk(struct work_struct *wk)
101{ 98{
102 struct iwl_mvm *mvm = container_of(wk, struct iwl_mvm, roc_done_wk); 99 struct iwl_mvm *mvm = container_of(wk, struct iwl_mvm, roc_done_wk);
100 u32 queues = 0;
101
102 /*
103 * Clear the ROC_RUNNING /ROC_AUX_RUNNING status bit.
104 * This will cause the TX path to drop offchannel transmissions.
105 * That would also be done by mac80211, but it is racy, in particular
106 * in the case that the time event actually completed in the firmware
107 * (which is handled in iwl_mvm_te_handle_notif).
108 */
109 if (test_and_clear_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status))
110 queues |= BIT(IWL_MVM_OFFCHANNEL_QUEUE);
111 if (test_and_clear_bit(IWL_MVM_STATUS_ROC_AUX_RUNNING, &mvm->status))
112 queues |= BIT(mvm->aux_queue);
113
114 iwl_mvm_unref(mvm, IWL_MVM_REF_ROC);
103 115
104 synchronize_net(); 116 synchronize_net();
105 117
@@ -113,22 +125,12 @@ void iwl_mvm_roc_done_wk(struct work_struct *wk)
113 * issue as it will have to complete before the next command is 125 * issue as it will have to complete before the next command is
114 * executed, and a new time event means a new command. 126 * executed, and a new time event means a new command.
115 */ 127 */
116 iwl_mvm_flush_tx_path(mvm, BIT(IWL_MVM_OFFCHANNEL_QUEUE), false); 128 iwl_mvm_flush_tx_path(mvm, queues, false);
117} 129}
118 130
119static void iwl_mvm_roc_finished(struct iwl_mvm *mvm) 131static void iwl_mvm_roc_finished(struct iwl_mvm *mvm)
120{ 132{
121 /* 133 /*
122 * First, clear the ROC_RUNNING status bit. This will cause the TX
123 * path to drop offchannel transmissions. That would also be done
124 * by mac80211, but it is racy, in particular in the case that the
125 * time event actually completed in the firmware (which is handled
126 * in iwl_mvm_te_handle_notif).
127 */
128 clear_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status);
129 iwl_mvm_unref(mvm, IWL_MVM_REF_ROC);
130
131 /*
132 * Of course, our status bit is just as racy as mac80211, so in 134 * Of course, our status bit is just as racy as mac80211, so in
133 * addition, fire off the work struct which will drop all frames 135 * addition, fire off the work struct which will drop all frames
134 * from the hardware queues that made it through the race. First 136 * from the hardware queues that made it through the race. First
@@ -263,6 +265,60 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm,
263} 265}
264 266
265/* 267/*
268 * Handle A Aux ROC time event
269 */
270static int iwl_mvm_aux_roc_te_handle_notif(struct iwl_mvm *mvm,
271 struct iwl_time_event_notif *notif)
272{
273 struct iwl_mvm_time_event_data *te_data, *tmp;
274 bool aux_roc_te = false;
275
276 list_for_each_entry_safe(te_data, tmp, &mvm->aux_roc_te_list, list) {
277 if (le32_to_cpu(notif->unique_id) == te_data->uid) {
278 aux_roc_te = true;
279 break;
280 }
281 }
282 if (!aux_roc_te) /* Not a Aux ROC time event */
283 return -EINVAL;
284
285 if (!le32_to_cpu(notif->status)) {
286 IWL_DEBUG_TE(mvm,
287 "ERROR: Aux ROC Time Event %s notification failure\n",
288 (le32_to_cpu(notif->action) &
289 TE_V2_NOTIF_HOST_EVENT_START) ? "start" : "end");
290 return -EINVAL;
291 }
292
293 IWL_DEBUG_TE(mvm,
294 "Aux ROC time event notification - UID = 0x%x action %d\n",
295 le32_to_cpu(notif->unique_id),
296 le32_to_cpu(notif->action));
297
298 if (le32_to_cpu(notif->action) == TE_V2_NOTIF_HOST_EVENT_END) {
299 /* End TE, notify mac80211 */
300 ieee80211_remain_on_channel_expired(mvm->hw);
301 iwl_mvm_roc_finished(mvm); /* flush aux queue */
302 list_del(&te_data->list); /* remove from list */
303 te_data->running = false;
304 te_data->vif = NULL;
305 te_data->uid = 0;
306 } else if (le32_to_cpu(notif->action) == TE_V2_NOTIF_HOST_EVENT_START) {
307 set_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status);
308 set_bit(IWL_MVM_STATUS_ROC_AUX_RUNNING, &mvm->status);
309 te_data->running = true;
310 ieee80211_ready_on_channel(mvm->hw); /* Start TE */
311 } else {
312 IWL_DEBUG_TE(mvm,
313 "ERROR: Unknown Aux ROC Time Event (action = %d)\n",
314 le32_to_cpu(notif->action));
315 return -EINVAL;
316 }
317
318 return 0;
319}
320
321/*
266 * The Rx handler for time event notifications 322 * The Rx handler for time event notifications
267 */ 323 */
268int iwl_mvm_rx_time_event_notif(struct iwl_mvm *mvm, 324int iwl_mvm_rx_time_event_notif(struct iwl_mvm *mvm,
@@ -278,10 +334,15 @@ int iwl_mvm_rx_time_event_notif(struct iwl_mvm *mvm,
278 le32_to_cpu(notif->action)); 334 le32_to_cpu(notif->action));
279 335
280 spin_lock_bh(&mvm->time_event_lock); 336 spin_lock_bh(&mvm->time_event_lock);
337 /* This time event is triggered for Aux ROC request */
338 if (!iwl_mvm_aux_roc_te_handle_notif(mvm, notif))
339 goto unlock;
340
281 list_for_each_entry_safe(te_data, tmp, &mvm->time_event_list, list) { 341 list_for_each_entry_safe(te_data, tmp, &mvm->time_event_list, list) {
282 if (le32_to_cpu(notif->unique_id) == te_data->uid) 342 if (le32_to_cpu(notif->unique_id) == te_data->uid)
283 iwl_mvm_te_handle_notif(mvm, te_data, notif); 343 iwl_mvm_te_handle_notif(mvm, te_data, notif);
284 } 344 }
345unlock:
285 spin_unlock_bh(&mvm->time_event_lock); 346 spin_unlock_bh(&mvm->time_event_lock);
286 347
287 return 0; 348 return 0;
diff --git a/drivers/net/wireless/iwlwifi/mvm/tt.c b/drivers/net/wireless/iwlwifi/mvm/tt.c
index 868561512783..0464599c111e 100644
--- a/drivers/net/wireless/iwlwifi/mvm/tt.c
+++ b/drivers/net/wireless/iwlwifi/mvm/tt.c
@@ -140,9 +140,9 @@ static u16 iwl_mvm_dts_get_ptat_deviation_offset(struct iwl_mvm *mvm)
140 140
141 /* TODO: move parsing to NVM code */ 141 /* TODO: move parsing to NVM code */
142 calib = mvm->nvm_sections[NVM_SECTION_TYPE_CALIBRATION].data; 142 calib = mvm->nvm_sections[NVM_SECTION_TYPE_CALIBRATION].data;
143 ptat = calib[OTP_DTS_DIODE_DEVIATION]; 143 ptat = calib[OTP_DTS_DIODE_DEVIATION * 2];
144 pa1 = calib[OTP_DTS_DIODE_DEVIATION + 1]; 144 pa1 = calib[OTP_DTS_DIODE_DEVIATION * 2 + 1];
145 pa2 = calib[OTP_DTS_DIODE_DEVIATION + 2]; 145 pa2 = calib[OTP_DTS_DIODE_DEVIATION * 2 + 2];
146 146
147 /* get the median: */ 147 /* get the median: */
148 if (ptat > pa1) { 148 if (ptat > pa1) {
@@ -338,10 +338,16 @@ static void check_exit_ctkill(struct work_struct *work)
338 338
339 duration = tt->params->ct_kill_duration; 339 duration = tt->params->ct_kill_duration;
340 340
341 /* make sure the device is available for direct read/writes */
342 if (iwl_mvm_ref_sync(mvm, IWL_MVM_REF_CHECK_CTKILL))
343 goto reschedule;
344
341 iwl_trans_start_hw(mvm->trans); 345 iwl_trans_start_hw(mvm->trans);
342 temp = check_nic_temperature(mvm); 346 temp = check_nic_temperature(mvm);
343 iwl_trans_stop_device(mvm->trans); 347 iwl_trans_stop_device(mvm->trans);
344 348
349 iwl_mvm_unref(mvm, IWL_MVM_REF_CHECK_CTKILL);
350
345 if (temp < MIN_TEMPERATURE || temp > MAX_TEMPERATURE) { 351 if (temp < MIN_TEMPERATURE || temp > MAX_TEMPERATURE) {
346 IWL_DEBUG_TEMP(mvm, "Failed to measure NIC temperature\n"); 352 IWL_DEBUG_TEMP(mvm, "Failed to measure NIC temperature\n");
347 goto reschedule; 353 goto reschedule;
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c
index e9ff38635c21..dbc870713882 100644
--- a/drivers/net/wireless/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/iwlwifi/mvm/tx.c
@@ -311,6 +311,16 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
311 return -1; 311 return -1;
312 312
313 /* 313 /*
314 * IWL_MVM_OFFCHANNEL_QUEUE is used for ROC packets that can be used
315 * in 2 different types of vifs, P2P & STATION. P2P uses the offchannel
316 * queue. STATION (HS2.0) uses the auxiliary context of the FW,
317 * and hence needs to be sent on the aux queue
318 */
319 if (IEEE80211_SKB_CB(skb)->hw_queue == IWL_MVM_OFFCHANNEL_QUEUE &&
320 info->control.vif->type == NL80211_IFTYPE_STATION)
321 IEEE80211_SKB_CB(skb)->hw_queue = mvm->aux_queue;
322
323 /*
314 * If the interface on which frame is sent is the P2P_DEVICE 324 * If the interface on which frame is sent is the P2P_DEVICE
315 * or an AP/GO interface use the broadcast station associated 325 * or an AP/GO interface use the broadcast station associated
316 * with it; otherwise use the AUX station. 326 * with it; otherwise use the AUX station.
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c
index 5b5b0d8c6f60..06e04aaf61ee 100644
--- a/drivers/net/wireless/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/iwlwifi/pcie/trans.c
@@ -67,6 +67,7 @@
67#include <linux/sched.h> 67#include <linux/sched.h>
68#include <linux/bitops.h> 68#include <linux/bitops.h>
69#include <linux/gfp.h> 69#include <linux/gfp.h>
70#include <linux/vmalloc.h>
70 71
71#include "iwl-drv.h" 72#include "iwl-drv.h"
72#include "iwl-trans.h" 73#include "iwl-trans.h"
@@ -1773,28 +1774,207 @@ static u32 iwl_trans_pcie_get_cmdlen(struct iwl_tfd *tfd)
1773 return cmdlen; 1774 return cmdlen;
1774} 1775}
1775 1776
1776static u32 iwl_trans_pcie_dump_data(struct iwl_trans *trans, 1777static const struct {
1777 void *buf, u32 buflen) 1778 u32 start, end;
1779} iwl_prph_dump_addr[] = {
1780 { .start = 0x00a00000, .end = 0x00a00000 },
1781 { .start = 0x00a0000c, .end = 0x00a00024 },
1782 { .start = 0x00a0002c, .end = 0x00a0003c },
1783 { .start = 0x00a00410, .end = 0x00a00418 },
1784 { .start = 0x00a00420, .end = 0x00a00420 },
1785 { .start = 0x00a00428, .end = 0x00a00428 },
1786 { .start = 0x00a00430, .end = 0x00a0043c },
1787 { .start = 0x00a00444, .end = 0x00a00444 },
1788 { .start = 0x00a004c0, .end = 0x00a004cc },
1789 { .start = 0x00a004d8, .end = 0x00a004d8 },
1790 { .start = 0x00a004e0, .end = 0x00a004f0 },
1791 { .start = 0x00a00840, .end = 0x00a00840 },
1792 { .start = 0x00a00850, .end = 0x00a00858 },
1793 { .start = 0x00a01004, .end = 0x00a01008 },
1794 { .start = 0x00a01010, .end = 0x00a01010 },
1795 { .start = 0x00a01018, .end = 0x00a01018 },
1796 { .start = 0x00a01024, .end = 0x00a01024 },
1797 { .start = 0x00a0102c, .end = 0x00a01034 },
1798 { .start = 0x00a0103c, .end = 0x00a01040 },
1799 { .start = 0x00a01048, .end = 0x00a01094 },
1800 { .start = 0x00a01c00, .end = 0x00a01c20 },
1801 { .start = 0x00a01c58, .end = 0x00a01c58 },
1802 { .start = 0x00a01c7c, .end = 0x00a01c7c },
1803 { .start = 0x00a01c28, .end = 0x00a01c54 },
1804 { .start = 0x00a01c5c, .end = 0x00a01c5c },
1805 { .start = 0x00a01c84, .end = 0x00a01c84 },
1806 { .start = 0x00a01ce0, .end = 0x00a01d0c },
1807 { .start = 0x00a01d18, .end = 0x00a01d20 },
1808 { .start = 0x00a01d2c, .end = 0x00a01d30 },
1809 { .start = 0x00a01d40, .end = 0x00a01d5c },
1810 { .start = 0x00a01d80, .end = 0x00a01d80 },
1811 { .start = 0x00a01d98, .end = 0x00a01d98 },
1812 { .start = 0x00a01dc0, .end = 0x00a01dfc },
1813 { .start = 0x00a01e00, .end = 0x00a01e2c },
1814 { .start = 0x00a01e40, .end = 0x00a01e60 },
1815 { .start = 0x00a01e84, .end = 0x00a01e90 },
1816 { .start = 0x00a01e9c, .end = 0x00a01ec4 },
1817 { .start = 0x00a01ed0, .end = 0x00a01ed0 },
1818 { .start = 0x00a01f00, .end = 0x00a01f14 },
1819 { .start = 0x00a01f44, .end = 0x00a01f58 },
1820 { .start = 0x00a01f80, .end = 0x00a01fa8 },
1821 { .start = 0x00a01fb0, .end = 0x00a01fbc },
1822 { .start = 0x00a01ff8, .end = 0x00a01ffc },
1823 { .start = 0x00a02000, .end = 0x00a02048 },
1824 { .start = 0x00a02068, .end = 0x00a020f0 },
1825 { .start = 0x00a02100, .end = 0x00a02118 },
1826 { .start = 0x00a02140, .end = 0x00a0214c },
1827 { .start = 0x00a02168, .end = 0x00a0218c },
1828 { .start = 0x00a021c0, .end = 0x00a021c0 },
1829 { .start = 0x00a02400, .end = 0x00a02410 },
1830 { .start = 0x00a02418, .end = 0x00a02420 },
1831 { .start = 0x00a02428, .end = 0x00a0242c },
1832 { .start = 0x00a02434, .end = 0x00a02434 },
1833 { .start = 0x00a02440, .end = 0x00a02460 },
1834 { .start = 0x00a02468, .end = 0x00a024b0 },
1835 { .start = 0x00a024c8, .end = 0x00a024cc },
1836 { .start = 0x00a02500, .end = 0x00a02504 },
1837 { .start = 0x00a0250c, .end = 0x00a02510 },
1838 { .start = 0x00a02540, .end = 0x00a02554 },
1839 { .start = 0x00a02580, .end = 0x00a025f4 },
1840 { .start = 0x00a02600, .end = 0x00a0260c },
1841 { .start = 0x00a02648, .end = 0x00a02650 },
1842 { .start = 0x00a02680, .end = 0x00a02680 },
1843 { .start = 0x00a026c0, .end = 0x00a026d0 },
1844 { .start = 0x00a02700, .end = 0x00a0270c },
1845 { .start = 0x00a02804, .end = 0x00a02804 },
1846 { .start = 0x00a02818, .end = 0x00a0281c },
1847 { .start = 0x00a02c00, .end = 0x00a02db4 },
1848 { .start = 0x00a02df4, .end = 0x00a02fb0 },
1849 { .start = 0x00a03000, .end = 0x00a03014 },
1850 { .start = 0x00a0301c, .end = 0x00a0302c },
1851 { .start = 0x00a03034, .end = 0x00a03038 },
1852 { .start = 0x00a03040, .end = 0x00a03048 },
1853 { .start = 0x00a03060, .end = 0x00a03068 },
1854 { .start = 0x00a03070, .end = 0x00a03074 },
1855 { .start = 0x00a0307c, .end = 0x00a0307c },
1856 { .start = 0x00a03080, .end = 0x00a03084 },
1857 { .start = 0x00a0308c, .end = 0x00a03090 },
1858 { .start = 0x00a03098, .end = 0x00a03098 },
1859 { .start = 0x00a030a0, .end = 0x00a030a0 },
1860 { .start = 0x00a030a8, .end = 0x00a030b4 },
1861 { .start = 0x00a030bc, .end = 0x00a030bc },
1862 { .start = 0x00a030c0, .end = 0x00a0312c },
1863 { .start = 0x00a03c00, .end = 0x00a03c5c },
1864 { .start = 0x00a04400, .end = 0x00a04454 },
1865 { .start = 0x00a04460, .end = 0x00a04474 },
1866 { .start = 0x00a044c0, .end = 0x00a044ec },
1867 { .start = 0x00a04500, .end = 0x00a04504 },
1868 { .start = 0x00a04510, .end = 0x00a04538 },
1869 { .start = 0x00a04540, .end = 0x00a04548 },
1870 { .start = 0x00a04560, .end = 0x00a0457c },
1871 { .start = 0x00a04590, .end = 0x00a04598 },
1872 { .start = 0x00a045c0, .end = 0x00a045f4 },
1873};
1874
1875static u32 iwl_trans_pcie_dump_prph(struct iwl_trans *trans,
1876 struct iwl_fw_error_dump_data **data)
1877{
1878 struct iwl_fw_error_dump_prph *prph;
1879 unsigned long flags;
1880 u32 prph_len = 0, i;
1881
1882 if (!iwl_trans_grab_nic_access(trans, false, &flags))
1883 return 0;
1884
1885 for (i = 0; i < ARRAY_SIZE(iwl_prph_dump_addr); i++) {
1886 /* The range includes both boundaries */
1887 int num_bytes_in_chunk = iwl_prph_dump_addr[i].end -
1888 iwl_prph_dump_addr[i].start + 4;
1889 int reg;
1890 __le32 *val;
1891
1892 prph_len += sizeof(*data) + sizeof(*prph) +
1893 num_bytes_in_chunk;
1894
1895 (*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PRPH);
1896 (*data)->len = cpu_to_le32(sizeof(*prph) +
1897 num_bytes_in_chunk);
1898 prph = (void *)(*data)->data;
1899 prph->prph_start = cpu_to_le32(iwl_prph_dump_addr[i].start);
1900 val = (void *)prph->data;
1901
1902 for (reg = iwl_prph_dump_addr[i].start;
1903 reg <= iwl_prph_dump_addr[i].end;
1904 reg += 4)
1905 *val++ = cpu_to_le32(iwl_trans_pcie_read_prph(trans,
1906 reg));
1907 *data = iwl_fw_error_next_data(*data);
1908 }
1909
1910 iwl_trans_release_nic_access(trans, &flags);
1911
1912 return prph_len;
1913}
1914
1915#define IWL_CSR_TO_DUMP (0x250)
1916
1917static u32 iwl_trans_pcie_dump_csr(struct iwl_trans *trans,
1918 struct iwl_fw_error_dump_data **data)
1919{
1920 u32 csr_len = sizeof(**data) + IWL_CSR_TO_DUMP;
1921 __le32 *val;
1922 int i;
1923
1924 (*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_CSR);
1925 (*data)->len = cpu_to_le32(IWL_CSR_TO_DUMP);
1926 val = (void *)(*data)->data;
1927
1928 for (i = 0; i < IWL_CSR_TO_DUMP; i += 4)
1929 *val++ = cpu_to_le32(iwl_trans_pcie_read32(trans, i));
1930
1931 *data = iwl_fw_error_next_data(*data);
1932
1933 return csr_len;
1934}
1935
1936static
1937struct iwl_trans_dump_data *iwl_trans_pcie_dump_data(struct iwl_trans *trans)
1778{ 1938{
1779 struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 1939 struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
1780 struct iwl_fw_error_dump_data *data; 1940 struct iwl_fw_error_dump_data *data;
1781 struct iwl_txq *cmdq = &trans_pcie->txq[trans_pcie->cmd_queue]; 1941 struct iwl_txq *cmdq = &trans_pcie->txq[trans_pcie->cmd_queue];
1782 struct iwl_fw_error_dump_txcmd *txcmd; 1942 struct iwl_fw_error_dump_txcmd *txcmd;
1943 struct iwl_trans_dump_data *dump_data;
1783 u32 len; 1944 u32 len;
1784 int i, ptr; 1945 int i, ptr;
1785 1946
1786 len = sizeof(*data) + 1947 /* transport dump header */
1948 len = sizeof(*dump_data);
1949
1950 /* host commands */
1951 len += sizeof(*data) +
1787 cmdq->q.n_window * (sizeof(*txcmd) + TFD_MAX_PAYLOAD_SIZE); 1952 cmdq->q.n_window * (sizeof(*txcmd) + TFD_MAX_PAYLOAD_SIZE);
1788 1953
1954 /* CSR registers */
1955 len += sizeof(*data) + IWL_CSR_TO_DUMP;
1956
1957 /* PRPH registers */
1958 for (i = 0; i < ARRAY_SIZE(iwl_prph_dump_addr); i++) {
1959 /* The range includes both boundaries */
1960 int num_bytes_in_chunk = iwl_prph_dump_addr[i].end -
1961 iwl_prph_dump_addr[i].start + 4;
1962
1963 len += sizeof(*data) + sizeof(struct iwl_fw_error_dump_prph) +
1964 num_bytes_in_chunk;
1965 }
1966
1967 /* FW monitor */
1789 if (trans_pcie->fw_mon_page) 1968 if (trans_pcie->fw_mon_page)
1790 len += sizeof(*data) + sizeof(struct iwl_fw_error_dump_fw_mon) + 1969 len += sizeof(*data) + sizeof(struct iwl_fw_error_dump_fw_mon) +
1791 trans_pcie->fw_mon_size; 1970 trans_pcie->fw_mon_size;
1792 1971
1793 if (!buf) 1972 dump_data = vzalloc(len);
1794 return len; 1973 if (!dump_data)
1974 return NULL;
1795 1975
1796 len = 0; 1976 len = 0;
1797 data = buf; 1977 data = (void *)dump_data->data;
1798 data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_TXCMD); 1978 data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_TXCMD);
1799 txcmd = (void *)data->data; 1979 txcmd = (void *)data->data;
1800 spin_lock_bh(&cmdq->lock); 1980 spin_lock_bh(&cmdq->lock);
@@ -1820,11 +2000,15 @@ static u32 iwl_trans_pcie_dump_data(struct iwl_trans *trans,
1820 2000
1821 data->len = cpu_to_le32(len); 2001 data->len = cpu_to_le32(len);
1822 len += sizeof(*data); 2002 len += sizeof(*data);
2003 data = iwl_fw_error_next_data(data);
2004
2005 len += iwl_trans_pcie_dump_prph(trans, &data);
2006 len += iwl_trans_pcie_dump_csr(trans, &data);
2007 /* data is already pointing to the next section */
1823 2008
1824 if (trans_pcie->fw_mon_page) { 2009 if (trans_pcie->fw_mon_page) {
1825 struct iwl_fw_error_dump_fw_mon *fw_mon_data; 2010 struct iwl_fw_error_dump_fw_mon *fw_mon_data;
1826 2011
1827 data = iwl_fw_error_next_data(data);
1828 data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_FW_MONITOR); 2012 data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_FW_MONITOR);
1829 data->len = cpu_to_le32(trans_pcie->fw_mon_size + 2013 data->len = cpu_to_le32(trans_pcie->fw_mon_size +
1830 sizeof(*fw_mon_data)); 2014 sizeof(*fw_mon_data));
@@ -1852,7 +2036,9 @@ static u32 iwl_trans_pcie_dump_data(struct iwl_trans *trans,
1852 trans_pcie->fw_mon_size; 2036 trans_pcie->fw_mon_size;
1853 } 2037 }
1854 2038
1855 return len; 2039 dump_data->len = len;
2040
2041 return dump_data;
1856} 2042}
1857#else 2043#else
1858static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans, 2044static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans,