diff options
author | Emmanuel Grumbach <emmanuel.grumbach@intel.com> | 2016-02-25 03:59:41 -0500 |
---|---|---|
committer | Emmanuel Grumbach <emmanuel.grumbach@intel.com> | 2016-02-27 14:59:52 -0500 |
commit | 3cce9bb07b5d40a3f8a10a1148f10896a7a42f5a (patch) | |
tree | 87acd4a0b68aa8326844685c252e90b7efe4d2f2 /drivers/net/wireless/intel/iwlwifi | |
parent | dd4d3161d0f229031914f403721ced8cb64d4d52 (diff) | |
parent | 20aa99bbddae74bded68338f9ba200ccae02858b (diff) |
Merge tag 'iwlwifi-for-kalle-2016-02-15' into HEAD
These are a few fixes for the current cycle.
3 out of the 5 patches fix a bugzilla.
* fix a race that users reported when we try to load the firmware
and the hardware rfkill interrupt triggers at the same time.
* Luca fixes a very visible bug in scheduled scan: our firmware
doesn't support scheduled scan with no profile configured and
the supplicant sometimes requests such scheduled scans.
* build system fix
* firmware name update for 8265
* typo fix in return value
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi')
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/Kconfig | 1 | ||||
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/iwl-7000.c | 23 | ||||
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/iwl-8000.c | 42 | ||||
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/iwl-drv.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h | 6 | ||||
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/rs.c | 74 | ||||
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/scan.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 5 | ||||
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/pcie/internal.h | 9 | ||||
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/pcie/rx.c | 8 | ||||
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 188 |
12 files changed, 243 insertions, 127 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/Kconfig b/drivers/net/wireless/intel/iwlwifi/Kconfig index 11932d53ea24..16c4f383488f 100644 --- a/drivers/net/wireless/intel/iwlwifi/Kconfig +++ b/drivers/net/wireless/intel/iwlwifi/Kconfig | |||
@@ -53,7 +53,6 @@ config IWLWIFI_LEDS | |||
53 | 53 | ||
54 | config IWLDVM | 54 | config IWLDVM |
55 | tristate "Intel Wireless WiFi DVM Firmware support" | 55 | tristate "Intel Wireless WiFi DVM Firmware support" |
56 | depends on m | ||
57 | help | 56 | help |
58 | This is the driver that supports the DVM firmware. The list | 57 | This is the driver that supports the DVM firmware. The list |
59 | of the devices that use this firmware is available here: | 58 | of the devices that use this firmware is available here: |
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-7000.c b/drivers/net/wireless/intel/iwlwifi/iwl-7000.c index e60cf141ed79..fa41a5e1c890 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-7000.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-7000.c | |||
@@ -74,16 +74,19 @@ | |||
74 | #define IWL7260_UCODE_API_MAX 17 | 74 | #define IWL7260_UCODE_API_MAX 17 |
75 | #define IWL7265_UCODE_API_MAX 17 | 75 | #define IWL7265_UCODE_API_MAX 17 |
76 | #define IWL7265D_UCODE_API_MAX 20 | 76 | #define IWL7265D_UCODE_API_MAX 20 |
77 | #define IWL3168_UCODE_API_MAX 20 | ||
77 | 78 | ||
78 | /* Oldest version we won't warn about */ | 79 | /* Oldest version we won't warn about */ |
79 | #define IWL7260_UCODE_API_OK 13 | 80 | #define IWL7260_UCODE_API_OK 13 |
80 | #define IWL7265_UCODE_API_OK 13 | 81 | #define IWL7265_UCODE_API_OK 13 |
81 | #define IWL7265D_UCODE_API_OK 13 | 82 | #define IWL7265D_UCODE_API_OK 13 |
83 | #define IWL3168_UCODE_API_OK 20 | ||
82 | 84 | ||
83 | /* Lowest firmware API version supported */ | 85 | /* Lowest firmware API version supported */ |
84 | #define IWL7260_UCODE_API_MIN 13 | 86 | #define IWL7260_UCODE_API_MIN 13 |
85 | #define IWL7265_UCODE_API_MIN 13 | 87 | #define IWL7265_UCODE_API_MIN 13 |
86 | #define IWL7265D_UCODE_API_MIN 13 | 88 | #define IWL7265D_UCODE_API_MIN 13 |
89 | #define IWL3168_UCODE_API_MIN 20 | ||
87 | 90 | ||
88 | /* NVM versions */ | 91 | /* NVM versions */ |
89 | #define IWL7260_NVM_VERSION 0x0a1d | 92 | #define IWL7260_NVM_VERSION 0x0a1d |
@@ -92,6 +95,8 @@ | |||
92 | #define IWL3160_TX_POWER_VERSION 0xffff /* meaningless */ | 95 | #define IWL3160_TX_POWER_VERSION 0xffff /* meaningless */ |
93 | #define IWL3165_NVM_VERSION 0x709 | 96 | #define IWL3165_NVM_VERSION 0x709 |
94 | #define IWL3165_TX_POWER_VERSION 0xffff /* meaningless */ | 97 | #define IWL3165_TX_POWER_VERSION 0xffff /* meaningless */ |
98 | #define IWL3168_NVM_VERSION 0xd01 | ||
99 | #define IWL3168_TX_POWER_VERSION 0xffff /* meaningless */ | ||
95 | #define IWL7265_NVM_VERSION 0x0a1d | 100 | #define IWL7265_NVM_VERSION 0x0a1d |
96 | #define IWL7265_TX_POWER_VERSION 0xffff /* meaningless */ | 101 | #define IWL7265_TX_POWER_VERSION 0xffff /* meaningless */ |
97 | #define IWL7265D_NVM_VERSION 0x0c11 | 102 | #define IWL7265D_NVM_VERSION 0x0c11 |
@@ -109,6 +114,9 @@ | |||
109 | #define IWL3160_FW_PRE "iwlwifi-3160-" | 114 | #define IWL3160_FW_PRE "iwlwifi-3160-" |
110 | #define IWL3160_MODULE_FIRMWARE(api) IWL3160_FW_PRE __stringify(api) ".ucode" | 115 | #define IWL3160_MODULE_FIRMWARE(api) IWL3160_FW_PRE __stringify(api) ".ucode" |
111 | 116 | ||
117 | #define IWL3168_FW_PRE "iwlwifi-3168-" | ||
118 | #define IWL3168_MODULE_FIRMWARE(api) IWL3168_FW_PRE __stringify(api) ".ucode" | ||
119 | |||
112 | #define IWL7265_FW_PRE "iwlwifi-7265-" | 120 | #define IWL7265_FW_PRE "iwlwifi-7265-" |
113 | #define IWL7265_MODULE_FIRMWARE(api) IWL7265_FW_PRE __stringify(api) ".ucode" | 121 | #define IWL7265_MODULE_FIRMWARE(api) IWL7265_FW_PRE __stringify(api) ".ucode" |
114 | 122 | ||
@@ -180,6 +188,12 @@ static const struct iwl_ht_params iwl7000_ht_params = { | |||
180 | .ucode_api_ok = IWL7265_UCODE_API_OK, \ | 188 | .ucode_api_ok = IWL7265_UCODE_API_OK, \ |
181 | .ucode_api_min = IWL7265_UCODE_API_MIN | 189 | .ucode_api_min = IWL7265_UCODE_API_MIN |
182 | 190 | ||
191 | #define IWL_DEVICE_3008 \ | ||
192 | IWL_DEVICE_7000_COMMON, \ | ||
193 | .ucode_api_max = IWL3168_UCODE_API_MAX, \ | ||
194 | .ucode_api_ok = IWL3168_UCODE_API_OK, \ | ||
195 | .ucode_api_min = IWL3168_UCODE_API_MIN | ||
196 | |||
183 | #define IWL_DEVICE_7005D \ | 197 | #define IWL_DEVICE_7005D \ |
184 | IWL_DEVICE_7000_COMMON, \ | 198 | IWL_DEVICE_7000_COMMON, \ |
185 | .ucode_api_max = IWL7265D_UCODE_API_MAX, \ | 199 | .ucode_api_max = IWL7265D_UCODE_API_MAX, \ |
@@ -299,11 +313,11 @@ const struct iwl_cfg iwl3165_2ac_cfg = { | |||
299 | 313 | ||
300 | const struct iwl_cfg iwl3168_2ac_cfg = { | 314 | const struct iwl_cfg iwl3168_2ac_cfg = { |
301 | .name = "Intel(R) Dual Band Wireless AC 3168", | 315 | .name = "Intel(R) Dual Band Wireless AC 3168", |
302 | .fw_name_pre = IWL7265D_FW_PRE, | 316 | .fw_name_pre = IWL3168_FW_PRE, |
303 | IWL_DEVICE_7000, | 317 | IWL_DEVICE_3008, |
304 | .ht_params = &iwl7000_ht_params, | 318 | .ht_params = &iwl7000_ht_params, |
305 | .nvm_ver = IWL3165_NVM_VERSION, | 319 | .nvm_ver = IWL3168_NVM_VERSION, |
306 | .nvm_calib_ver = IWL3165_TX_POWER_VERSION, | 320 | .nvm_calib_ver = IWL3168_TX_POWER_VERSION, |
307 | .pwr_tx_backoffs = iwl7265_pwr_tx_backoffs, | 321 | .pwr_tx_backoffs = iwl7265_pwr_tx_backoffs, |
308 | .dccm_len = IWL7265_DCCM_LEN, | 322 | .dccm_len = IWL7265_DCCM_LEN, |
309 | }; | 323 | }; |
@@ -376,5 +390,6 @@ const struct iwl_cfg iwl7265d_n_cfg = { | |||
376 | 390 | ||
377 | MODULE_FIRMWARE(IWL7260_MODULE_FIRMWARE(IWL7260_UCODE_API_OK)); | 391 | MODULE_FIRMWARE(IWL7260_MODULE_FIRMWARE(IWL7260_UCODE_API_OK)); |
378 | MODULE_FIRMWARE(IWL3160_MODULE_FIRMWARE(IWL7260_UCODE_API_OK)); | 392 | MODULE_FIRMWARE(IWL3160_MODULE_FIRMWARE(IWL7260_UCODE_API_OK)); |
393 | MODULE_FIRMWARE(IWL3168_MODULE_FIRMWARE(IWL3168_UCODE_API_OK)); | ||
379 | MODULE_FIRMWARE(IWL7265_MODULE_FIRMWARE(IWL7265_UCODE_API_OK)); | 394 | MODULE_FIRMWARE(IWL7265_MODULE_FIRMWARE(IWL7265_UCODE_API_OK)); |
380 | MODULE_FIRMWARE(IWL7265D_MODULE_FIRMWARE(IWL7265D_UCODE_API_OK)); | 395 | MODULE_FIRMWARE(IWL7265D_MODULE_FIRMWARE(IWL7265D_UCODE_API_OK)); |
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-8000.c b/drivers/net/wireless/intel/iwlwifi/iwl-8000.c index c84a0299d43e..bce9b3420a13 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-8000.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-8000.c | |||
@@ -7,6 +7,7 @@ | |||
7 | * | 7 | * |
8 | * Copyright(c) 2014 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2014 Intel Corporation. All rights reserved. |
9 | * Copyright(c) 2014 - 2015 Intel Mobile Communications GmbH | 9 | * Copyright(c) 2014 - 2015 Intel Mobile Communications GmbH |
10 | * Copyright(c) 2016 Intel Deutschland GmbH | ||
10 | * | 11 | * |
11 | * This program is free software; you can redistribute it and/or modify | 12 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of version 2 of the GNU General Public License as | 13 | * it under the terms of version 2 of the GNU General Public License as |
@@ -70,12 +71,15 @@ | |||
70 | 71 | ||
71 | /* Highest firmware API version supported */ | 72 | /* Highest firmware API version supported */ |
72 | #define IWL8000_UCODE_API_MAX 20 | 73 | #define IWL8000_UCODE_API_MAX 20 |
74 | #define IWL8265_UCODE_API_MAX 20 | ||
73 | 75 | ||
74 | /* Oldest version we won't warn about */ | 76 | /* Oldest version we won't warn about */ |
75 | #define IWL8000_UCODE_API_OK 13 | 77 | #define IWL8000_UCODE_API_OK 13 |
78 | #define IWL8265_UCODE_API_OK 20 | ||
76 | 79 | ||
77 | /* Lowest firmware API version supported */ | 80 | /* Lowest firmware API version supported */ |
78 | #define IWL8000_UCODE_API_MIN 13 | 81 | #define IWL8000_UCODE_API_MIN 13 |
82 | #define IWL8265_UCODE_API_MIN 20 | ||
79 | 83 | ||
80 | /* NVM versions */ | 84 | /* NVM versions */ |
81 | #define IWL8000_NVM_VERSION 0x0a1d | 85 | #define IWL8000_NVM_VERSION 0x0a1d |
@@ -93,6 +97,10 @@ | |||
93 | #define IWL8000_MODULE_FIRMWARE(api) \ | 97 | #define IWL8000_MODULE_FIRMWARE(api) \ |
94 | IWL8000_FW_PRE "-" __stringify(api) ".ucode" | 98 | IWL8000_FW_PRE "-" __stringify(api) ".ucode" |
95 | 99 | ||
100 | #define IWL8265_FW_PRE "iwlwifi-8265-" | ||
101 | #define IWL8265_MODULE_FIRMWARE(api) \ | ||
102 | IWL8265_FW_PRE __stringify(api) ".ucode" | ||
103 | |||
96 | #define NVM_HW_SECTION_NUM_FAMILY_8000 10 | 104 | #define NVM_HW_SECTION_NUM_FAMILY_8000 10 |
97 | #define DEFAULT_NVM_FILE_FAMILY_8000B "nvmData-8000B" | 105 | #define DEFAULT_NVM_FILE_FAMILY_8000B "nvmData-8000B" |
98 | #define DEFAULT_NVM_FILE_FAMILY_8000C "nvmData-8000C" | 106 | #define DEFAULT_NVM_FILE_FAMILY_8000C "nvmData-8000C" |
@@ -144,10 +152,7 @@ static const struct iwl_tt_params iwl8000_tt_params = { | |||
144 | .support_tx_backoff = true, | 152 | .support_tx_backoff = true, |
145 | }; | 153 | }; |
146 | 154 | ||
147 | #define IWL_DEVICE_8000 \ | 155 | #define IWL_DEVICE_8000_COMMON \ |
148 | .ucode_api_max = IWL8000_UCODE_API_MAX, \ | ||
149 | .ucode_api_ok = IWL8000_UCODE_API_OK, \ | ||
150 | .ucode_api_min = IWL8000_UCODE_API_MIN, \ | ||
151 | .device_family = IWL_DEVICE_FAMILY_8000, \ | 156 | .device_family = IWL_DEVICE_FAMILY_8000, \ |
152 | .max_inst_size = IWL60_RTC_INST_SIZE, \ | 157 | .max_inst_size = IWL60_RTC_INST_SIZE, \ |
153 | .max_data_size = IWL60_RTC_DATA_SIZE, \ | 158 | .max_data_size = IWL60_RTC_DATA_SIZE, \ |
@@ -167,10 +172,28 @@ static const struct iwl_tt_params iwl8000_tt_params = { | |||
167 | .thermal_params = &iwl8000_tt_params, \ | 172 | .thermal_params = &iwl8000_tt_params, \ |
168 | .apmg_not_supported = true | 173 | .apmg_not_supported = true |
169 | 174 | ||
175 | #define IWL_DEVICE_8000 \ | ||
176 | IWL_DEVICE_8000_COMMON, \ | ||
177 | .ucode_api_max = IWL8000_UCODE_API_MAX, \ | ||
178 | .ucode_api_ok = IWL8000_UCODE_API_OK, \ | ||
179 | .ucode_api_min = IWL8000_UCODE_API_MIN \ | ||
180 | |||
181 | #define IWL_DEVICE_8260 \ | ||
182 | IWL_DEVICE_8000_COMMON, \ | ||
183 | .ucode_api_max = IWL8000_UCODE_API_MAX, \ | ||
184 | .ucode_api_ok = IWL8000_UCODE_API_OK, \ | ||
185 | .ucode_api_min = IWL8000_UCODE_API_MIN \ | ||
186 | |||
187 | #define IWL_DEVICE_8265 \ | ||
188 | IWL_DEVICE_8000_COMMON, \ | ||
189 | .ucode_api_max = IWL8265_UCODE_API_MAX, \ | ||
190 | .ucode_api_ok = IWL8265_UCODE_API_OK, \ | ||
191 | .ucode_api_min = IWL8265_UCODE_API_MIN \ | ||
192 | |||
170 | const struct iwl_cfg iwl8260_2n_cfg = { | 193 | const struct iwl_cfg iwl8260_2n_cfg = { |
171 | .name = "Intel(R) Dual Band Wireless N 8260", | 194 | .name = "Intel(R) Dual Band Wireless N 8260", |
172 | .fw_name_pre = IWL8000_FW_PRE, | 195 | .fw_name_pre = IWL8000_FW_PRE, |
173 | IWL_DEVICE_8000, | 196 | IWL_DEVICE_8260, |
174 | .ht_params = &iwl8000_ht_params, | 197 | .ht_params = &iwl8000_ht_params, |
175 | .nvm_ver = IWL8000_NVM_VERSION, | 198 | .nvm_ver = IWL8000_NVM_VERSION, |
176 | .nvm_calib_ver = IWL8000_TX_POWER_VERSION, | 199 | .nvm_calib_ver = IWL8000_TX_POWER_VERSION, |
@@ -179,7 +202,7 @@ const struct iwl_cfg iwl8260_2n_cfg = { | |||
179 | const struct iwl_cfg iwl8260_2ac_cfg = { | 202 | const struct iwl_cfg iwl8260_2ac_cfg = { |
180 | .name = "Intel(R) Dual Band Wireless AC 8260", | 203 | .name = "Intel(R) Dual Band Wireless AC 8260", |
181 | .fw_name_pre = IWL8000_FW_PRE, | 204 | .fw_name_pre = IWL8000_FW_PRE, |
182 | IWL_DEVICE_8000, | 205 | IWL_DEVICE_8260, |
183 | .ht_params = &iwl8000_ht_params, | 206 | .ht_params = &iwl8000_ht_params, |
184 | .nvm_ver = IWL8000_NVM_VERSION, | 207 | .nvm_ver = IWL8000_NVM_VERSION, |
185 | .nvm_calib_ver = IWL8000_TX_POWER_VERSION, | 208 | .nvm_calib_ver = IWL8000_TX_POWER_VERSION, |
@@ -188,8 +211,8 @@ const struct iwl_cfg iwl8260_2ac_cfg = { | |||
188 | 211 | ||
189 | const struct iwl_cfg iwl8265_2ac_cfg = { | 212 | const struct iwl_cfg iwl8265_2ac_cfg = { |
190 | .name = "Intel(R) Dual Band Wireless AC 8265", | 213 | .name = "Intel(R) Dual Band Wireless AC 8265", |
191 | .fw_name_pre = IWL8000_FW_PRE, | 214 | .fw_name_pre = IWL8265_FW_PRE, |
192 | IWL_DEVICE_8000, | 215 | IWL_DEVICE_8265, |
193 | .ht_params = &iwl8000_ht_params, | 216 | .ht_params = &iwl8000_ht_params, |
194 | .nvm_ver = IWL8000_NVM_VERSION, | 217 | .nvm_ver = IWL8000_NVM_VERSION, |
195 | .nvm_calib_ver = IWL8000_TX_POWER_VERSION, | 218 | .nvm_calib_ver = IWL8000_TX_POWER_VERSION, |
@@ -209,7 +232,7 @@ const struct iwl_cfg iwl4165_2ac_cfg = { | |||
209 | const struct iwl_cfg iwl8260_2ac_sdio_cfg = { | 232 | const struct iwl_cfg iwl8260_2ac_sdio_cfg = { |
210 | .name = "Intel(R) Dual Band Wireless-AC 8260", | 233 | .name = "Intel(R) Dual Band Wireless-AC 8260", |
211 | .fw_name_pre = IWL8000_FW_PRE, | 234 | .fw_name_pre = IWL8000_FW_PRE, |
212 | IWL_DEVICE_8000, | 235 | IWL_DEVICE_8260, |
213 | .ht_params = &iwl8000_ht_params, | 236 | .ht_params = &iwl8000_ht_params, |
214 | .nvm_ver = IWL8000_NVM_VERSION, | 237 | .nvm_ver = IWL8000_NVM_VERSION, |
215 | .nvm_calib_ver = IWL8000_TX_POWER_VERSION, | 238 | .nvm_calib_ver = IWL8000_TX_POWER_VERSION, |
@@ -236,3 +259,4 @@ const struct iwl_cfg iwl4165_2ac_sdio_cfg = { | |||
236 | }; | 259 | }; |
237 | 260 | ||
238 | MODULE_FIRMWARE(IWL8000_MODULE_FIRMWARE(IWL8000_UCODE_API_OK)); | 261 | MODULE_FIRMWARE(IWL8000_MODULE_FIRMWARE(IWL8000_UCODE_API_OK)); |
262 | MODULE_FIRMWARE(IWL8265_MODULE_FIRMWARE(IWL8265_UCODE_API_OK)); | ||
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c index 7acb49075683..ab4c2a0470b2 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c | |||
@@ -243,8 +243,10 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first) | |||
243 | if (drv->trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) { | 243 | if (drv->trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) { |
244 | char rev_step = 'A' + CSR_HW_REV_STEP(drv->trans->hw_rev); | 244 | char rev_step = 'A' + CSR_HW_REV_STEP(drv->trans->hw_rev); |
245 | 245 | ||
246 | snprintf(drv->firmware_name, sizeof(drv->firmware_name), | 246 | if (rev_step != 'A') |
247 | "%s%c-%s.ucode", name_pre, rev_step, tag); | 247 | snprintf(drv->firmware_name, |
248 | sizeof(drv->firmware_name), "%s%c-%s.ucode", | ||
249 | name_pre, rev_step, tag); | ||
248 | } | 250 | } |
249 | 251 | ||
250 | IWL_DEBUG_INFO(drv, "attempting to load firmware %s'%s'\n", | 252 | IWL_DEBUG_INFO(drv, "attempting to load firmware %s'%s'\n", |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h index 0036d18334af..ba3f0bbddde8 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h | |||
@@ -510,6 +510,9 @@ struct iwl_mvm_tx_resp { | |||
510 | * @scd_ssn: the index of the last contiguously sent packet | 510 | * @scd_ssn: the index of the last contiguously sent packet |
511 | * @txed: number of Txed frames in this batch | 511 | * @txed: number of Txed frames in this batch |
512 | * @txed_2_done: number of Acked frames in this batch | 512 | * @txed_2_done: number of Acked frames in this batch |
513 | * @reduced_txp: power reduced according to TPC. This is the actual value and | ||
514 | * not a copy from the LQ command. Thus, if not the first rate was used | ||
515 | * for Tx-ing then this value will be set to 0 by FW. | ||
513 | */ | 516 | */ |
514 | struct iwl_mvm_ba_notif { | 517 | struct iwl_mvm_ba_notif { |
515 | __le32 sta_addr_lo32; | 518 | __le32 sta_addr_lo32; |
@@ -524,7 +527,8 @@ struct iwl_mvm_ba_notif { | |||
524 | __le16 scd_ssn; | 527 | __le16 scd_ssn; |
525 | u8 txed; | 528 | u8 txed; |
526 | u8 txed_2_done; | 529 | u8 txed_2_done; |
527 | __le16 reserved1; | 530 | u8 reduced_txp; |
531 | u8 reserved1; | ||
528 | } __packed; | 532 | } __packed; |
529 | 533 | ||
530 | /* | 534 | /* |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c index 986e12ab9dc2..6e7e78a37879 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * | 2 | * |
3 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
4 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 4 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
5 | * Copyright(c) 2016 Intel Deutschland GmbH | ||
5 | * | 6 | * |
6 | * This program is free software; you can redistribute it and/or modify it | 7 | * This program is free software; you can redistribute it and/or modify it |
7 | * under the terms of version 2 of the GNU General Public License as | 8 | * under the terms of version 2 of the GNU General Public License as |
@@ -724,14 +725,28 @@ static int _rs_collect_tx_data(struct iwl_mvm *mvm, | |||
724 | return 0; | 725 | return 0; |
725 | } | 726 | } |
726 | 727 | ||
727 | static int rs_collect_tx_data(struct iwl_mvm *mvm, | 728 | static int rs_collect_tpc_data(struct iwl_mvm *mvm, |
728 | struct iwl_lq_sta *lq_sta, | 729 | struct iwl_lq_sta *lq_sta, |
729 | struct iwl_scale_tbl_info *tbl, | 730 | struct iwl_scale_tbl_info *tbl, |
730 | int scale_index, int attempts, int successes, | 731 | int scale_index, int attempts, int successes, |
731 | u8 reduced_txp) | 732 | u8 reduced_txp) |
733 | { | ||
734 | struct iwl_rate_scale_data *window = NULL; | ||
735 | |||
736 | if (WARN_ON_ONCE(reduced_txp > TPC_MAX_REDUCTION)) | ||
737 | return -EINVAL; | ||
738 | |||
739 | window = &tbl->tpc_win[reduced_txp]; | ||
740 | return _rs_collect_tx_data(mvm, tbl, scale_index, attempts, successes, | ||
741 | window); | ||
742 | } | ||
743 | |||
744 | static int rs_collect_tlc_data(struct iwl_mvm *mvm, | ||
745 | struct iwl_lq_sta *lq_sta, | ||
746 | struct iwl_scale_tbl_info *tbl, | ||
747 | int scale_index, int attempts, int successes) | ||
732 | { | 748 | { |
733 | struct iwl_rate_scale_data *window = NULL; | 749 | struct iwl_rate_scale_data *window = NULL; |
734 | int ret; | ||
735 | 750 | ||
736 | if (scale_index < 0 || scale_index >= IWL_RATE_COUNT) | 751 | if (scale_index < 0 || scale_index >= IWL_RATE_COUNT) |
737 | return -EINVAL; | 752 | return -EINVAL; |
@@ -745,16 +760,6 @@ static int rs_collect_tx_data(struct iwl_mvm *mvm, | |||
745 | 760 | ||
746 | /* Select window for current tx bit rate */ | 761 | /* Select window for current tx bit rate */ |
747 | window = &(tbl->win[scale_index]); | 762 | window = &(tbl->win[scale_index]); |
748 | |||
749 | ret = _rs_collect_tx_data(mvm, tbl, scale_index, attempts, successes, | ||
750 | window); | ||
751 | if (ret) | ||
752 | return ret; | ||
753 | |||
754 | if (WARN_ON_ONCE(reduced_txp > TPC_MAX_REDUCTION)) | ||
755 | return -EINVAL; | ||
756 | |||
757 | window = &tbl->tpc_win[reduced_txp]; | ||
758 | return _rs_collect_tx_data(mvm, tbl, scale_index, attempts, successes, | 763 | return _rs_collect_tx_data(mvm, tbl, scale_index, attempts, successes, |
759 | window); | 764 | window); |
760 | } | 765 | } |
@@ -1301,17 +1306,30 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
1301 | * first index into rate scale table. | 1306 | * first index into rate scale table. |
1302 | */ | 1307 | */ |
1303 | if (info->flags & IEEE80211_TX_STAT_AMPDU) { | 1308 | if (info->flags & IEEE80211_TX_STAT_AMPDU) { |
1304 | /* ampdu_ack_len = 0 marks no BA was received. In this case | 1309 | rs_collect_tpc_data(mvm, lq_sta, curr_tbl, lq_rate.index, |
1305 | * treat it as a single frame loss as we don't want the success | 1310 | info->status.ampdu_len, |
1306 | * ratio to dip too quickly because a BA wasn't received | 1311 | info->status.ampdu_ack_len, |
1312 | reduced_txp); | ||
1313 | |||
1314 | /* ampdu_ack_len = 0 marks no BA was received. For TLC, treat | ||
1315 | * it as a single frame loss as we don't want the success ratio | ||
1316 | * to dip too quickly because a BA wasn't received. | ||
1317 | * For TPC, there's no need for this optimisation since we want | ||
1318 | * to recover very quickly from a bad power reduction and, | ||
1319 | * therefore we'd like the success ratio to get an immediate hit | ||
1320 | * when failing to get a BA, so we'd switch back to a lower or | ||
1321 | * zero power reduction. When FW transmits agg with a rate | ||
1322 | * different from the initial rate, it will not use reduced txp | ||
1323 | * and will send BA notification twice (one empty with reduced | ||
1324 | * txp equal to the value from LQ and one with reduced txp 0). | ||
1325 | * We need to update counters for each txp level accordingly. | ||
1307 | */ | 1326 | */ |
1308 | if (info->status.ampdu_ack_len == 0) | 1327 | if (info->status.ampdu_ack_len == 0) |
1309 | info->status.ampdu_len = 1; | 1328 | info->status.ampdu_len = 1; |
1310 | 1329 | ||
1311 | rs_collect_tx_data(mvm, lq_sta, curr_tbl, lq_rate.index, | 1330 | rs_collect_tlc_data(mvm, lq_sta, curr_tbl, lq_rate.index, |
1312 | info->status.ampdu_len, | 1331 | info->status.ampdu_len, |
1313 | info->status.ampdu_ack_len, | 1332 | info->status.ampdu_ack_len); |
1314 | reduced_txp); | ||
1315 | 1333 | ||
1316 | /* Update success/fail counts if not searching for new mode */ | 1334 | /* Update success/fail counts if not searching for new mode */ |
1317 | if (lq_sta->rs_state == RS_STATE_STAY_IN_COLUMN) { | 1335 | if (lq_sta->rs_state == RS_STATE_STAY_IN_COLUMN) { |
@@ -1344,9 +1362,13 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
1344 | else | 1362 | else |
1345 | continue; | 1363 | continue; |
1346 | 1364 | ||
1347 | rs_collect_tx_data(mvm, lq_sta, tmp_tbl, lq_rate.index, | 1365 | rs_collect_tpc_data(mvm, lq_sta, tmp_tbl, |
1348 | 1, i < retries ? 0 : legacy_success, | 1366 | lq_rate.index, 1, |
1349 | reduced_txp); | 1367 | i < retries ? 0 : legacy_success, |
1368 | reduced_txp); | ||
1369 | rs_collect_tlc_data(mvm, lq_sta, tmp_tbl, | ||
1370 | lq_rate.index, 1, | ||
1371 | i < retries ? 0 : legacy_success); | ||
1350 | } | 1372 | } |
1351 | 1373 | ||
1352 | /* Update success/fail counts if not searching for new mode */ | 1374 | /* Update success/fail counts if not searching for new mode */ |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c index 1e1ab9daaec9..aa6d8074f63a 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c | |||
@@ -1301,6 +1301,10 @@ int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm, | |||
1301 | return -EBUSY; | 1301 | return -EBUSY; |
1302 | } | 1302 | } |
1303 | 1303 | ||
1304 | /* we don't support "match all" in the firmware */ | ||
1305 | if (!req->n_match_sets) | ||
1306 | return -EOPNOTSUPP; | ||
1307 | |||
1304 | ret = iwl_mvm_check_running_scans(mvm, type); | 1308 | ret = iwl_mvm_check_running_scans(mvm, type); |
1305 | if (ret) | 1309 | if (ret) |
1306 | return ret; | 1310 | return ret; |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c index caec54ba617a..4fbaadda4e99 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c | |||
@@ -1064,7 +1064,6 @@ static void iwl_mvm_rx_tx_cmd_agg(struct iwl_mvm *mvm, | |||
1064 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); | 1064 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); |
1065 | mvmsta->tid_data[tid].rate_n_flags = | 1065 | mvmsta->tid_data[tid].rate_n_flags = |
1066 | le32_to_cpu(tx_resp->initial_rate); | 1066 | le32_to_cpu(tx_resp->initial_rate); |
1067 | mvmsta->tid_data[tid].reduced_tpc = tx_resp->reduced_tpc; | ||
1068 | mvmsta->tid_data[tid].tx_time = | 1067 | mvmsta->tid_data[tid].tx_time = |
1069 | le16_to_cpu(tx_resp->wireless_media_time); | 1068 | le16_to_cpu(tx_resp->wireless_media_time); |
1070 | } | 1069 | } |
@@ -1095,7 +1094,7 @@ static void iwl_mvm_tx_info_from_ba_notif(struct ieee80211_tx_info *info, | |||
1095 | /* TODO: not accounted if the whole A-MPDU failed */ | 1094 | /* TODO: not accounted if the whole A-MPDU failed */ |
1096 | info->status.tx_time = tid_data->tx_time; | 1095 | info->status.tx_time = tid_data->tx_time; |
1097 | info->status.status_driver_data[0] = | 1096 | info->status.status_driver_data[0] = |
1098 | (void *)(uintptr_t)tid_data->reduced_tpc; | 1097 | (void *)(uintptr_t)ba_notif->reduced_txp; |
1099 | info->status.status_driver_data[1] = | 1098 | info->status.status_driver_data[1] = |
1100 | (void *)(uintptr_t)tid_data->rate_n_flags; | 1099 | (void *)(uintptr_t)tid_data->rate_n_flags; |
1101 | } | 1100 | } |
@@ -1168,6 +1167,8 @@ void iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb) | |||
1168 | scd_flow, ba_resp_scd_ssn, ba_notif->txed, | 1167 | scd_flow, ba_resp_scd_ssn, ba_notif->txed, |
1169 | ba_notif->txed_2_done); | 1168 | ba_notif->txed_2_done); |
1170 | 1169 | ||
1170 | IWL_DEBUG_TX_REPLY(mvm, "reduced txp from ba notif %d\n", | ||
1171 | ba_notif->reduced_txp); | ||
1171 | tid_data->next_reclaimed = ba_resp_scd_ssn; | 1172 | tid_data->next_reclaimed = ba_resp_scd_ssn; |
1172 | 1173 | ||
1173 | iwl_mvm_check_ratid_empty(mvm, sta, tid); | 1174 | iwl_mvm_check_ratid_empty(mvm, sta, tid); |
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index 762e7c4d96b6..753ec6785912 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c | |||
@@ -380,7 +380,10 @@ static const struct pci_device_id iwl_hw_card_ids[] = { | |||
380 | {IWL_PCI_DEVICE(0x3165, 0x8110, iwl3165_2ac_cfg)}, | 380 | {IWL_PCI_DEVICE(0x3165, 0x8110, iwl3165_2ac_cfg)}, |
381 | 381 | ||
382 | /* 3168 Series */ | 382 | /* 3168 Series */ |
383 | {IWL_PCI_DEVICE(0x24FB, 0x2010, iwl3168_2ac_cfg)}, | ||
383 | {IWL_PCI_DEVICE(0x24FB, 0x2110, iwl3168_2ac_cfg)}, | 384 | {IWL_PCI_DEVICE(0x24FB, 0x2110, iwl3168_2ac_cfg)}, |
385 | {IWL_PCI_DEVICE(0x24FB, 0x2050, iwl3168_2ac_cfg)}, | ||
386 | {IWL_PCI_DEVICE(0x24FB, 0x2150, iwl3168_2ac_cfg)}, | ||
384 | {IWL_PCI_DEVICE(0x24FB, 0x0000, iwl3168_2ac_cfg)}, | 387 | {IWL_PCI_DEVICE(0x24FB, 0x0000, iwl3168_2ac_cfg)}, |
385 | 388 | ||
386 | /* 7265 Series */ | 389 | /* 7265 Series */ |
@@ -477,6 +480,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = { | |||
477 | {IWL_PCI_DEVICE(0x24F3, 0x0000, iwl8265_2ac_cfg)}, | 480 | {IWL_PCI_DEVICE(0x24F3, 0x0000, iwl8265_2ac_cfg)}, |
478 | {IWL_PCI_DEVICE(0x24FD, 0x0010, iwl8265_2ac_cfg)}, | 481 | {IWL_PCI_DEVICE(0x24FD, 0x0010, iwl8265_2ac_cfg)}, |
479 | {IWL_PCI_DEVICE(0x24FD, 0x8010, iwl8265_2ac_cfg)}, | 482 | {IWL_PCI_DEVICE(0x24FD, 0x8010, iwl8265_2ac_cfg)}, |
483 | {IWL_PCI_DEVICE(0x24FD, 0x0810, iwl8265_2ac_cfg)}, | ||
480 | 484 | ||
481 | /* 9000 Series */ | 485 | /* 9000 Series */ |
482 | {IWL_PCI_DEVICE(0x9DF0, 0x2A10, iwl5165_2ac_cfg)}, | 486 | {IWL_PCI_DEVICE(0x9DF0, 0x2A10, iwl5165_2ac_cfg)}, |
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h index 2f959162d045..542bbc5e2b24 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h | |||
@@ -507,6 +507,15 @@ static inline void iwl_enable_interrupts(struct iwl_trans *trans) | |||
507 | iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask); | 507 | iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask); |
508 | } | 508 | } |
509 | 509 | ||
510 | static inline void iwl_enable_fw_load_int(struct iwl_trans *trans) | ||
511 | { | ||
512 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
513 | |||
514 | IWL_DEBUG_ISR(trans, "Enabling FW load interrupt\n"); | ||
515 | trans_pcie->inta_mask = CSR_INT_BIT_FH_TX; | ||
516 | iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask); | ||
517 | } | ||
518 | |||
510 | static inline void iwl_enable_rfkill_int(struct iwl_trans *trans) | 519 | static inline void iwl_enable_rfkill_int(struct iwl_trans *trans) |
511 | { | 520 | { |
512 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 521 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c index 51314e56209d..07973ef826c1 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c | |||
@@ -1614,9 +1614,11 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id) | |||
1614 | inta & ~trans_pcie->inta_mask); | 1614 | inta & ~trans_pcie->inta_mask); |
1615 | } | 1615 | } |
1616 | 1616 | ||
1617 | /* Re-enable all interrupts */ | 1617 | /* we are loading the firmware, enable FH_TX interrupt only */ |
1618 | /* only Re-enable if disabled by irq */ | 1618 | if (handled & CSR_INT_BIT_FH_TX) |
1619 | if (test_bit(STATUS_INT_ENABLED, &trans->status)) | 1619 | iwl_enable_fw_load_int(trans); |
1620 | /* only Re-enable all interrupt if disabled by irq */ | ||
1621 | else if (test_bit(STATUS_INT_ENABLED, &trans->status)) | ||
1620 | iwl_enable_interrupts(trans); | 1622 | iwl_enable_interrupts(trans); |
1621 | /* Re-enable RF_KILL if it occurred */ | 1623 | /* Re-enable RF_KILL if it occurred */ |
1622 | else if (handled & CSR_INT_BIT_RF_KILL) | 1624 | else if (handled & CSR_INT_BIT_RF_KILL) |
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index b796952da644..58591ca051fd 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c | |||
@@ -1022,82 +1022,6 @@ static int iwl_pcie_load_given_ucode_8000(struct iwl_trans *trans, | |||
1022 | &first_ucode_section); | 1022 | &first_ucode_section); |
1023 | } | 1023 | } |
1024 | 1024 | ||
1025 | static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, | ||
1026 | const struct fw_img *fw, bool run_in_rfkill) | ||
1027 | { | ||
1028 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
1029 | bool hw_rfkill; | ||
1030 | int ret; | ||
1031 | |||
1032 | mutex_lock(&trans_pcie->mutex); | ||
1033 | |||
1034 | /* Someone called stop_device, don't try to start_fw */ | ||
1035 | if (trans_pcie->is_down) { | ||
1036 | IWL_WARN(trans, | ||
1037 | "Can't start_fw since the HW hasn't been started\n"); | ||
1038 | ret = EIO; | ||
1039 | goto out; | ||
1040 | } | ||
1041 | |||
1042 | /* This may fail if AMT took ownership of the device */ | ||
1043 | if (iwl_pcie_prepare_card_hw(trans)) { | ||
1044 | IWL_WARN(trans, "Exit HW not ready\n"); | ||
1045 | ret = -EIO; | ||
1046 | goto out; | ||
1047 | } | ||
1048 | |||
1049 | iwl_enable_rfkill_int(trans); | ||
1050 | |||
1051 | /* If platform's RF_KILL switch is NOT set to KILL */ | ||
1052 | hw_rfkill = iwl_is_rfkill_set(trans); | ||
1053 | if (hw_rfkill) | ||
1054 | set_bit(STATUS_RFKILL, &trans->status); | ||
1055 | else | ||
1056 | clear_bit(STATUS_RFKILL, &trans->status); | ||
1057 | iwl_trans_pcie_rf_kill(trans, hw_rfkill); | ||
1058 | if (hw_rfkill && !run_in_rfkill) { | ||
1059 | ret = -ERFKILL; | ||
1060 | goto out; | ||
1061 | } | ||
1062 | |||
1063 | iwl_write32(trans, CSR_INT, 0xFFFFFFFF); | ||
1064 | |||
1065 | ret = iwl_pcie_nic_init(trans); | ||
1066 | if (ret) { | ||
1067 | IWL_ERR(trans, "Unable to init nic\n"); | ||
1068 | goto out; | ||
1069 | } | ||
1070 | |||
1071 | /* make sure rfkill handshake bits are cleared */ | ||
1072 | iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); | ||
1073 | iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, | ||
1074 | CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); | ||
1075 | |||
1076 | /* clear (again), then enable host interrupts */ | ||
1077 | iwl_write32(trans, CSR_INT, 0xFFFFFFFF); | ||
1078 | iwl_enable_interrupts(trans); | ||
1079 | |||
1080 | /* really make sure rfkill handshake bits are cleared */ | ||
1081 | iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); | ||
1082 | iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); | ||
1083 | |||
1084 | /* Load the given image to the HW */ | ||
1085 | if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) | ||
1086 | ret = iwl_pcie_load_given_ucode_8000(trans, fw); | ||
1087 | else | ||
1088 | ret = iwl_pcie_load_given_ucode(trans, fw); | ||
1089 | |||
1090 | out: | ||
1091 | mutex_unlock(&trans_pcie->mutex); | ||
1092 | return ret; | ||
1093 | } | ||
1094 | |||
1095 | static void iwl_trans_pcie_fw_alive(struct iwl_trans *trans, u32 scd_addr) | ||
1096 | { | ||
1097 | iwl_pcie_reset_ict(trans); | ||
1098 | iwl_pcie_tx_start(trans, scd_addr); | ||
1099 | } | ||
1100 | |||
1101 | static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power) | 1025 | static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power) |
1102 | { | 1026 | { |
1103 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 1027 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
@@ -1128,7 +1052,8 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power) | |||
1128 | * already dead. | 1052 | * already dead. |
1129 | */ | 1053 | */ |
1130 | if (test_and_clear_bit(STATUS_DEVICE_ENABLED, &trans->status)) { | 1054 | if (test_and_clear_bit(STATUS_DEVICE_ENABLED, &trans->status)) { |
1131 | IWL_DEBUG_INFO(trans, "DEVICE_ENABLED bit was set and is now cleared\n"); | 1055 | IWL_DEBUG_INFO(trans, |
1056 | "DEVICE_ENABLED bit was set and is now cleared\n"); | ||
1132 | iwl_pcie_tx_stop(trans); | 1057 | iwl_pcie_tx_stop(trans); |
1133 | iwl_pcie_rx_stop(trans); | 1058 | iwl_pcie_rx_stop(trans); |
1134 | 1059 | ||
@@ -1162,7 +1087,6 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power) | |||
1162 | iwl_disable_interrupts(trans); | 1087 | iwl_disable_interrupts(trans); |
1163 | spin_unlock(&trans_pcie->irq_lock); | 1088 | spin_unlock(&trans_pcie->irq_lock); |
1164 | 1089 | ||
1165 | |||
1166 | /* clear all status bits */ | 1090 | /* clear all status bits */ |
1167 | clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status); | 1091 | clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status); |
1168 | clear_bit(STATUS_INT_ENABLED, &trans->status); | 1092 | clear_bit(STATUS_INT_ENABLED, &trans->status); |
@@ -1195,10 +1119,116 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power) | |||
1195 | if (hw_rfkill != was_hw_rfkill) | 1119 | if (hw_rfkill != was_hw_rfkill) |
1196 | iwl_trans_pcie_rf_kill(trans, hw_rfkill); | 1120 | iwl_trans_pcie_rf_kill(trans, hw_rfkill); |
1197 | 1121 | ||
1198 | /* re-take ownership to prevent other users from stealing the deivce */ | 1122 | /* re-take ownership to prevent other users from stealing the device */ |
1199 | iwl_pcie_prepare_card_hw(trans); | 1123 | iwl_pcie_prepare_card_hw(trans); |
1200 | } | 1124 | } |
1201 | 1125 | ||
1126 | static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, | ||
1127 | const struct fw_img *fw, bool run_in_rfkill) | ||
1128 | { | ||
1129 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
1130 | bool hw_rfkill; | ||
1131 | int ret; | ||
1132 | |||
1133 | /* This may fail if AMT took ownership of the device */ | ||
1134 | if (iwl_pcie_prepare_card_hw(trans)) { | ||
1135 | IWL_WARN(trans, "Exit HW not ready\n"); | ||
1136 | ret = -EIO; | ||
1137 | goto out; | ||
1138 | } | ||
1139 | |||
1140 | iwl_enable_rfkill_int(trans); | ||
1141 | |||
1142 | iwl_write32(trans, CSR_INT, 0xFFFFFFFF); | ||
1143 | |||
1144 | /* | ||
1145 | * We enabled the RF-Kill interrupt and the handler may very | ||
1146 | * well be running. Disable the interrupts to make sure no other | ||
1147 | * interrupt can be fired. | ||
1148 | */ | ||
1149 | iwl_disable_interrupts(trans); | ||
1150 | |||
1151 | /* Make sure it finished running */ | ||
1152 | synchronize_irq(trans_pcie->pci_dev->irq); | ||
1153 | |||
1154 | mutex_lock(&trans_pcie->mutex); | ||
1155 | |||
1156 | /* If platform's RF_KILL switch is NOT set to KILL */ | ||
1157 | hw_rfkill = iwl_is_rfkill_set(trans); | ||
1158 | if (hw_rfkill) | ||
1159 | set_bit(STATUS_RFKILL, &trans->status); | ||
1160 | else | ||
1161 | clear_bit(STATUS_RFKILL, &trans->status); | ||
1162 | iwl_trans_pcie_rf_kill(trans, hw_rfkill); | ||
1163 | if (hw_rfkill && !run_in_rfkill) { | ||
1164 | ret = -ERFKILL; | ||
1165 | goto out; | ||
1166 | } | ||
1167 | |||
1168 | /* Someone called stop_device, don't try to start_fw */ | ||
1169 | if (trans_pcie->is_down) { | ||
1170 | IWL_WARN(trans, | ||
1171 | "Can't start_fw since the HW hasn't been started\n"); | ||
1172 | ret = -EIO; | ||
1173 | goto out; | ||
1174 | } | ||
1175 | |||
1176 | /* make sure rfkill handshake bits are cleared */ | ||
1177 | iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); | ||
1178 | iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, | ||
1179 | CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); | ||
1180 | |||
1181 | /* clear (again), then enable host interrupts */ | ||
1182 | iwl_write32(trans, CSR_INT, 0xFFFFFFFF); | ||
1183 | |||
1184 | ret = iwl_pcie_nic_init(trans); | ||
1185 | if (ret) { | ||
1186 | IWL_ERR(trans, "Unable to init nic\n"); | ||
1187 | goto out; | ||
1188 | } | ||
1189 | |||
1190 | /* | ||
1191 | * Now, we load the firmware and don't want to be interrupted, even | ||
1192 | * by the RF-Kill interrupt (hence mask all the interrupt besides the | ||
1193 | * FH_TX interrupt which is needed to load the firmware). If the | ||
1194 | * RF-Kill switch is toggled, we will find out after having loaded | ||
1195 | * the firmware and return the proper value to the caller. | ||
1196 | */ | ||
1197 | iwl_enable_fw_load_int(trans); | ||
1198 | |||
1199 | /* really make sure rfkill handshake bits are cleared */ | ||
1200 | iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); | ||
1201 | iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); | ||
1202 | |||
1203 | /* Load the given image to the HW */ | ||
1204 | if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) | ||
1205 | ret = iwl_pcie_load_given_ucode_8000(trans, fw); | ||
1206 | else | ||
1207 | ret = iwl_pcie_load_given_ucode(trans, fw); | ||
1208 | iwl_enable_interrupts(trans); | ||
1209 | |||
1210 | /* re-check RF-Kill state since we may have missed the interrupt */ | ||
1211 | hw_rfkill = iwl_is_rfkill_set(trans); | ||
1212 | if (hw_rfkill) | ||
1213 | set_bit(STATUS_RFKILL, &trans->status); | ||
1214 | else | ||
1215 | clear_bit(STATUS_RFKILL, &trans->status); | ||
1216 | |||
1217 | iwl_trans_pcie_rf_kill(trans, hw_rfkill); | ||
1218 | if (hw_rfkill && !run_in_rfkill) | ||
1219 | ret = -ERFKILL; | ||
1220 | |||
1221 | out: | ||
1222 | mutex_unlock(&trans_pcie->mutex); | ||
1223 | return ret; | ||
1224 | } | ||
1225 | |||
1226 | static void iwl_trans_pcie_fw_alive(struct iwl_trans *trans, u32 scd_addr) | ||
1227 | { | ||
1228 | iwl_pcie_reset_ict(trans); | ||
1229 | iwl_pcie_tx_start(trans, scd_addr); | ||
1230 | } | ||
1231 | |||
1202 | static void iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power) | 1232 | static void iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power) |
1203 | { | 1233 | { |
1204 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 1234 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |