diff options
Diffstat (limited to 'drivers/net/wireless/intel')
71 files changed, 4090 insertions, 1154 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c index eb93711d474b..fdc56f821b5a 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2015-2017 Intel Deutschland GmbH | 8 | * Copyright(c) 2015-2017 Intel Deutschland GmbH |
| 9 | * Copyright (C) 2018 Intel Corporation | 9 | * Copyright (C) 2018-2019 Intel Corporation |
| 10 | * | 10 | * |
| 11 | * This program is free software; you can redistribute it and/or modify | 11 | * 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 | 12 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -20,7 +20,7 @@ | |||
| 20 | * BSD LICENSE | 20 | * BSD LICENSE |
| 21 | * | 21 | * |
| 22 | * Copyright(c) 2015-2017 Intel Deutschland GmbH | 22 | * Copyright(c) 2015-2017 Intel Deutschland GmbH |
| 23 | * Copyright (C) 2018 Intel Corporation | 23 | * Copyright (C) 2018-2019 Intel Corporation |
| 24 | * All rights reserved. | 24 | * All rights reserved. |
| 25 | * | 25 | * |
| 26 | * Redistribution and use in source and binary forms, with or without | 26 | * Redistribution and use in source and binary forms, with or without |
| @@ -56,7 +56,7 @@ | |||
| 56 | #include "iwl-config.h" | 56 | #include "iwl-config.h" |
| 57 | 57 | ||
| 58 | /* Highest firmware API version supported */ | 58 | /* Highest firmware API version supported */ |
| 59 | #define IWL_22000_UCODE_API_MAX 43 | 59 | #define IWL_22000_UCODE_API_MAX 46 |
| 60 | 60 | ||
| 61 | /* Lowest firmware API version supported */ | 61 | /* Lowest firmware API version supported */ |
| 62 | #define IWL_22000_UCODE_API_MIN 39 | 62 | #define IWL_22000_UCODE_API_MIN 39 |
| @@ -79,11 +79,15 @@ | |||
| 79 | #define IWL_22000_HR_B_F0_FW_PRE "iwlwifi-Qu-b0-hr-b0-" | 79 | #define IWL_22000_HR_B_F0_FW_PRE "iwlwifi-Qu-b0-hr-b0-" |
| 80 | #define IWL_22000_QU_B_HR_B_FW_PRE "iwlwifi-Qu-b0-hr-b0-" | 80 | #define IWL_22000_QU_B_HR_B_FW_PRE "iwlwifi-Qu-b0-hr-b0-" |
| 81 | #define IWL_22000_HR_B_FW_PRE "iwlwifi-QuQnj-b0-hr-b0-" | 81 | #define IWL_22000_HR_B_FW_PRE "iwlwifi-QuQnj-b0-hr-b0-" |
| 82 | #define IWL_22000_JF_B0_FW_PRE "iwlwifi-QuQnj-a0-jf-b0-" | ||
| 83 | #define IWL_22000_HR_A0_FW_PRE "iwlwifi-QuQnj-a0-hr-a0-" | 82 | #define IWL_22000_HR_A0_FW_PRE "iwlwifi-QuQnj-a0-hr-a0-" |
| 84 | #define IWL_22000_SU_Z0_FW_PRE "iwlwifi-su-z0-" | 83 | #define IWL_22000_SU_Z0_FW_PRE "iwlwifi-su-z0-" |
| 85 | #define IWL_QU_B_JF_B_FW_PRE "iwlwifi-Qu-b0-jf-b0-" | 84 | #define IWL_QU_B_JF_B_FW_PRE "iwlwifi-Qu-b0-jf-b0-" |
| 85 | #define IWL_QNJ_B_JF_B_FW_PRE "iwlwifi-QuQnj-b0-jf-b0-" | ||
| 86 | #define IWL_CC_A_FW_PRE "iwlwifi-cc-a0-" | 86 | #define IWL_CC_A_FW_PRE "iwlwifi-cc-a0-" |
| 87 | #define IWL_22000_SO_A_JF_B_FW_PRE "iwlwifi-so-a0-jf-b0-" | ||
| 88 | #define IWL_22000_SO_A_HR_B_FW_PRE "iwlwifi-so-a0-hr-b0-" | ||
| 89 | #define IWL_22000_SO_A_GF_A_FW_PRE "iwlwifi-so-a0-gf-a0-" | ||
| 90 | #define IWL_22000_TY_A_GF_A_FW_PRE "iwlwifi-ty-a0-gf-a0-" | ||
| 87 | 91 | ||
| 88 | #define IWL_22000_HR_MODULE_FIRMWARE(api) \ | 92 | #define IWL_22000_HR_MODULE_FIRMWARE(api) \ |
| 89 | IWL_22000_HR_FW_PRE __stringify(api) ".ucode" | 93 | IWL_22000_HR_FW_PRE __stringify(api) ".ucode" |
| @@ -97,16 +101,26 @@ | |||
| 97 | IWL_22000_QU_B_HR_B_FW_PRE __stringify(api) ".ucode" | 101 | IWL_22000_QU_B_HR_B_FW_PRE __stringify(api) ".ucode" |
| 98 | #define IWL_22000_HR_B_QNJ_MODULE_FIRMWARE(api) \ | 102 | #define IWL_22000_HR_B_QNJ_MODULE_FIRMWARE(api) \ |
| 99 | IWL_22000_HR_B_FW_PRE __stringify(api) ".ucode" | 103 | IWL_22000_HR_B_FW_PRE __stringify(api) ".ucode" |
| 100 | #define IWL_22000_JF_B0_QNJ_MODULE_FIRMWARE(api) \ | ||
| 101 | IWL_22000_JF_B0_FW_PRE __stringify(api) ".ucode" | ||
| 102 | #define IWL_22000_HR_A0_QNJ_MODULE_FIRMWARE(api) \ | 104 | #define IWL_22000_HR_A0_QNJ_MODULE_FIRMWARE(api) \ |
| 103 | IWL_22000_HR_A0_FW_PRE __stringify(api) ".ucode" | 105 | IWL_22000_HR_A0_FW_PRE __stringify(api) ".ucode" |
| 104 | #define IWL_22000_SU_Z0_MODULE_FIRMWARE(api) \ | 106 | #define IWL_22000_SU_Z0_MODULE_FIRMWARE(api) \ |
| 105 | IWL_22000_SU_Z0_FW_PRE __stringify(api) ".ucode" | 107 | IWL_22000_SU_Z0_FW_PRE __stringify(api) ".ucode" |
| 106 | #define IWL_QU_B_JF_B_MODULE_FIRMWARE(api) \ | 108 | #define IWL_QU_B_JF_B_MODULE_FIRMWARE(api) \ |
| 107 | IWL_QU_B_JF_B_FW_PRE __stringify(api) ".ucode" | 109 | IWL_QU_B_JF_B_FW_PRE __stringify(api) ".ucode" |
| 108 | #define IWL_CC_A_MODULE_FIRMWARE(api) \ | 110 | #define IWL_QU_B_JF_B_MODULE_FIRMWARE(api) \ |
| 111 | IWL_QU_B_JF_B_FW_PRE __stringify(api) ".ucode" | ||
| 112 | #define IWL_QNJ_B_JF_B_MODULE_FIRMWARE(api) \ | ||
| 113 | IWL_QNJ_B_JF_B_FW_PRE __stringify(api) ".ucode" | ||
| 114 | #define IWL_CC_A_MODULE_FIRMWARE(api) \ | ||
| 109 | IWL_CC_A_FW_PRE __stringify(api) ".ucode" | 115 | IWL_CC_A_FW_PRE __stringify(api) ".ucode" |
| 116 | #define IWL_22000_SO_A_JF_B_MODULE_FIRMWARE(api) \ | ||
| 117 | IWL_22000_SO_A_JF_B_FW_PRE __stringify(api) ".ucode" | ||
| 118 | #define IWL_22000_SO_A_HR_B_MODULE_FIRMWARE(api) \ | ||
| 119 | IWL_22000_SO_A_HR_B_FW_PRE __stringify(api) ".ucode" | ||
| 120 | #define IWL_22000_SO_A_GF_A_MODULE_FIRMWARE(api) \ | ||
| 121 | IWL_22000_SO_A_GF_A_FW_PRE __stringify(api) ".ucode" | ||
| 122 | #define IWL_22000_TY_A_GF_A_MODULE_FIRMWARE(api) \ | ||
| 123 | IWL_22000_TY_A_GF_A_FW_PRE __stringify(api) ".ucode" | ||
| 110 | 124 | ||
| 111 | static const struct iwl_base_params iwl_22000_base_params = { | 125 | static const struct iwl_base_params iwl_22000_base_params = { |
| 112 | .eeprom_size = OTP_LOW_IMAGE_SIZE_32K, | 126 | .eeprom_size = OTP_LOW_IMAGE_SIZE_32K, |
| @@ -167,6 +181,10 @@ static const struct iwl_ht_params iwl_22000_ht_params = { | |||
| 167 | .d3_debug_data_base_addr = 0x401000, \ | 181 | .d3_debug_data_base_addr = 0x401000, \ |
| 168 | .d3_debug_data_length = 60 * 1024 | 182 | .d3_debug_data_length = 60 * 1024 |
| 169 | 183 | ||
| 184 | #define IWL_DEVICE_AX200_COMMON \ | ||
| 185 | IWL_DEVICE_22000_COMMON, \ | ||
| 186 | .umac_prph_offset = 0x300000 | ||
| 187 | |||
| 170 | #define IWL_DEVICE_22500 \ | 188 | #define IWL_DEVICE_22500 \ |
| 171 | IWL_DEVICE_22000_COMMON, \ | 189 | IWL_DEVICE_22000_COMMON, \ |
| 172 | .device_family = IWL_DEVICE_FAMILY_22000, \ | 190 | .device_family = IWL_DEVICE_FAMILY_22000, \ |
| @@ -179,6 +197,13 @@ static const struct iwl_ht_params iwl_22000_ht_params = { | |||
| 179 | .base_params = &iwl_22560_base_params, \ | 197 | .base_params = &iwl_22560_base_params, \ |
| 180 | .csr = &iwl_csr_v2 | 198 | .csr = &iwl_csr_v2 |
| 181 | 199 | ||
| 200 | #define IWL_DEVICE_AX210 \ | ||
| 201 | IWL_DEVICE_AX200_COMMON, \ | ||
| 202 | .device_family = IWL_DEVICE_FAMILY_AX210, \ | ||
| 203 | .base_params = &iwl_22000_base_params, \ | ||
| 204 | .csr = &iwl_csr_v1, \ | ||
| 205 | .min_txq_size = 128 | ||
| 206 | |||
| 182 | const struct iwl_cfg iwl22000_2ac_cfg_hr = { | 207 | const struct iwl_cfg iwl22000_2ac_cfg_hr = { |
| 183 | .name = "Intel(R) Dual Band Wireless AC 22000", | 208 | .name = "Intel(R) Dual Band Wireless AC 22000", |
| 184 | .fw_name_pre = IWL_22000_HR_FW_PRE, | 209 | .fw_name_pre = IWL_22000_HR_FW_PRE, |
| @@ -198,8 +223,8 @@ const struct iwl_cfg iwl22000_2ac_cfg_jf = { | |||
| 198 | IWL_DEVICE_22500, | 223 | IWL_DEVICE_22500, |
| 199 | }; | 224 | }; |
| 200 | 225 | ||
| 201 | const struct iwl_cfg iwl22560_2ax_cfg_hr = { | 226 | const struct iwl_cfg iwl_ax101_cfg_qu_hr = { |
| 202 | .name = "Intel(R) Wireless-AX 22560", | 227 | .name = "Intel(R) Wi-Fi 6 AX101", |
| 203 | .fw_name_pre = IWL_22000_QU_B_HR_B_FW_PRE, | 228 | .fw_name_pre = IWL_22000_QU_B_HR_B_FW_PRE, |
| 204 | IWL_DEVICE_22500, | 229 | IWL_DEVICE_22500, |
| 205 | /* | 230 | /* |
| @@ -220,10 +245,11 @@ const struct iwl_cfg iwl22260_2ax_cfg = { | |||
| 220 | * HT size; mac80211 would otherwise pick the HE max (256) by default. | 245 | * HT size; mac80211 would otherwise pick the HE max (256) by default. |
| 221 | */ | 246 | */ |
| 222 | .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, | 247 | .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, |
| 248 | .bisr_workaround = 1, | ||
| 223 | }; | 249 | }; |
| 224 | 250 | ||
| 225 | const struct iwl_cfg killer1650x_2ax_cfg = { | 251 | const struct iwl_cfg killer1650x_2ax_cfg = { |
| 226 | .name = "Killer(R) Wireless-AX 1650x Wireless Network Adapter (22260NGW)", | 252 | .name = "Killer(R) Wireless-AX 1650x Wireless Network Adapter (200NGW)", |
| 227 | .fw_name_pre = IWL_CC_A_FW_PRE, | 253 | .fw_name_pre = IWL_CC_A_FW_PRE, |
| 228 | IWL_DEVICE_22500, | 254 | IWL_DEVICE_22500, |
| 229 | /* | 255 | /* |
| @@ -232,10 +258,11 @@ const struct iwl_cfg killer1650x_2ax_cfg = { | |||
| 232 | * HT size; mac80211 would otherwise pick the HE max (256) by default. | 258 | * HT size; mac80211 would otherwise pick the HE max (256) by default. |
| 233 | */ | 259 | */ |
| 234 | .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, | 260 | .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, |
| 261 | .bisr_workaround = 1, | ||
| 235 | }; | 262 | }; |
| 236 | 263 | ||
| 237 | const struct iwl_cfg killer1650w_2ax_cfg = { | 264 | const struct iwl_cfg killer1650w_2ax_cfg = { |
| 238 | .name = "Killer(R) Wireless-AX 1650w Wireless Network Adapter (22260D2W)", | 265 | .name = "Killer(R) Wireless-AX 1650w Wireless Network Adapter (200D2W)", |
| 239 | .fw_name_pre = IWL_CC_A_FW_PRE, | 266 | .fw_name_pre = IWL_CC_A_FW_PRE, |
| 240 | IWL_DEVICE_22500, | 267 | IWL_DEVICE_22500, |
| 241 | /* | 268 | /* |
| @@ -244,6 +271,7 @@ const struct iwl_cfg killer1650w_2ax_cfg = { | |||
| 244 | * HT size; mac80211 would otherwise pick the HE max (256) by default. | 271 | * HT size; mac80211 would otherwise pick the HE max (256) by default. |
| 245 | */ | 272 | */ |
| 246 | .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, | 273 | .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, |
| 274 | .bisr_workaround = 1, | ||
| 247 | }; | 275 | }; |
| 248 | 276 | ||
| 249 | /* | 277 | /* |
| @@ -275,6 +303,18 @@ const struct iwl_cfg iwl9560_2ac_160_cfg_qu_b0_jf_b0 = { | |||
| 275 | IWL_DEVICE_22500, | 303 | IWL_DEVICE_22500, |
| 276 | }; | 304 | }; |
| 277 | 305 | ||
| 306 | const struct iwl_cfg iwl9560_2ac_cfg_qnj_jf_b0 = { | ||
| 307 | .name = "Intel(R) Wireless-AC 9560 160MHz", | ||
| 308 | .fw_name_pre = IWL_QNJ_B_JF_B_FW_PRE, | ||
| 309 | IWL_DEVICE_22500, | ||
| 310 | /* | ||
| 311 | * This device doesn't support receiving BlockAck with a large bitmap | ||
| 312 | * so we need to restrict the size of transmitted aggregation to the | ||
| 313 | * HT size; mac80211 would otherwise pick the HE max (256) by default. | ||
| 314 | */ | ||
| 315 | .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, | ||
| 316 | }; | ||
| 317 | |||
| 278 | const struct iwl_cfg killer1550i_2ac_cfg_qu_b0_jf_b0 = { | 318 | const struct iwl_cfg killer1550i_2ac_cfg_qu_b0_jf_b0 = { |
| 279 | .name = "Killer (R) Wireless-AC 1550i Wireless Network Adapter (9560NGW)", | 319 | .name = "Killer (R) Wireless-AC 1550i Wireless Network Adapter (9560NGW)", |
| 280 | .fw_name_pre = IWL_QU_B_JF_B_FW_PRE, | 320 | .fw_name_pre = IWL_QU_B_JF_B_FW_PRE, |
| @@ -347,18 +387,6 @@ const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_b0 = { | |||
| 347 | .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, | 387 | .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, |
| 348 | }; | 388 | }; |
| 349 | 389 | ||
| 350 | const struct iwl_cfg iwl22000_2ax_cfg_qnj_jf_b0 = { | ||
| 351 | .name = "Intel(R) Dual Band Wireless AX 22000", | ||
| 352 | .fw_name_pre = IWL_22000_JF_B0_FW_PRE, | ||
| 353 | IWL_DEVICE_22500, | ||
| 354 | /* | ||
| 355 | * This device doesn't support receiving BlockAck with a large bitmap | ||
| 356 | * so we need to restrict the size of transmitted aggregation to the | ||
| 357 | * HT size; mac80211 would otherwise pick the HE max (256) by default. | ||
| 358 | */ | ||
| 359 | .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, | ||
| 360 | }; | ||
| 361 | |||
| 362 | const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_a0 = { | 390 | const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_a0 = { |
| 363 | .name = "Intel(R) Dual Band Wireless AX 22000", | 391 | .name = "Intel(R) Dual Band Wireless AX 22000", |
| 364 | .fw_name_pre = IWL_22000_HR_A0_FW_PRE, | 392 | .fw_name_pre = IWL_22000_HR_A0_FW_PRE, |
| @@ -384,13 +412,41 @@ const struct iwl_cfg iwl22560_2ax_cfg_su_cdb = { | |||
| 384 | .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, | 412 | .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, |
| 385 | }; | 413 | }; |
| 386 | 414 | ||
| 415 | const struct iwl_cfg iwlax210_2ax_cfg_so_jf_a0 = { | ||
| 416 | .name = "Intel(R) Wireless-AC 9560 160MHz", | ||
| 417 | .fw_name_pre = IWL_22000_SO_A_JF_B_FW_PRE, | ||
| 418 | IWL_DEVICE_AX210, | ||
| 419 | }; | ||
| 420 | |||
| 421 | const struct iwl_cfg iwlax210_2ax_cfg_so_hr_a0 = { | ||
| 422 | .name = "Intel(R) Wi-Fi 6 AX201 160MHz", | ||
| 423 | .fw_name_pre = IWL_22000_SO_A_HR_B_FW_PRE, | ||
| 424 | IWL_DEVICE_AX210, | ||
| 425 | }; | ||
| 426 | |||
| 427 | const struct iwl_cfg iwlax210_2ax_cfg_so_gf_a0 = { | ||
| 428 | .name = "Intel(R) Wi-Fi 7 AX211 160MHz", | ||
| 429 | .fw_name_pre = IWL_22000_SO_A_GF_A_FW_PRE, | ||
| 430 | IWL_DEVICE_AX210, | ||
| 431 | }; | ||
| 432 | |||
| 433 | const struct iwl_cfg iwlax210_2ax_cfg_ty_gf_a0 = { | ||
| 434 | .name = "Intel(R) Wi-Fi 7 AX210 160MHz", | ||
| 435 | .fw_name_pre = IWL_22000_TY_A_GF_A_FW_PRE, | ||
| 436 | IWL_DEVICE_AX210, | ||
| 437 | }; | ||
| 438 | |||
| 387 | MODULE_FIRMWARE(IWL_22000_HR_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); | 439 | MODULE_FIRMWARE(IWL_22000_HR_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); |
| 388 | MODULE_FIRMWARE(IWL_22000_JF_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); | 440 | MODULE_FIRMWARE(IWL_22000_JF_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); |
| 389 | MODULE_FIRMWARE(IWL_22000_HR_A_F0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); | 441 | MODULE_FIRMWARE(IWL_22000_HR_A_F0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); |
| 390 | MODULE_FIRMWARE(IWL_22000_HR_B_F0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); | 442 | MODULE_FIRMWARE(IWL_22000_HR_B_F0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); |
| 391 | MODULE_FIRMWARE(IWL_22000_HR_B_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); | 443 | MODULE_FIRMWARE(IWL_22000_HR_B_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); |
| 392 | MODULE_FIRMWARE(IWL_22000_JF_B0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); | ||
| 393 | MODULE_FIRMWARE(IWL_22000_HR_A0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); | 444 | MODULE_FIRMWARE(IWL_22000_HR_A0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); |
| 394 | MODULE_FIRMWARE(IWL_22000_SU_Z0_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); | 445 | MODULE_FIRMWARE(IWL_22000_SU_Z0_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); |
| 395 | MODULE_FIRMWARE(IWL_QU_B_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); | 446 | MODULE_FIRMWARE(IWL_QU_B_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); |
| 447 | MODULE_FIRMWARE(IWL_QNJ_B_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); | ||
| 396 | MODULE_FIRMWARE(IWL_CC_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); | 448 | MODULE_FIRMWARE(IWL_CC_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); |
| 449 | MODULE_FIRMWARE(IWL_22000_SO_A_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); | ||
| 450 | MODULE_FIRMWARE(IWL_22000_SO_A_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); | ||
| 451 | MODULE_FIRMWARE(IWL_22000_SO_A_GF_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); | ||
| 452 | MODULE_FIRMWARE(IWL_22000_TY_A_GF_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); | ||
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c index 113bcf7735a0..3225b64eb845 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c | |||
| @@ -57,7 +57,7 @@ | |||
| 57 | #include "fw/file.h" | 57 | #include "fw/file.h" |
| 58 | 58 | ||
| 59 | /* Highest firmware API version supported */ | 59 | /* Highest firmware API version supported */ |
| 60 | #define IWL9000_UCODE_API_MAX 43 | 60 | #define IWL9000_UCODE_API_MAX 46 |
| 61 | 61 | ||
| 62 | /* Lowest firmware API version supported */ | 62 | /* Lowest firmware API version supported */ |
| 63 | #define IWL9000_UCODE_API_MIN 30 | 63 | #define IWL9000_UCODE_API_MIN 30 |
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/agn.h b/drivers/net/wireless/intel/iwlwifi/dvm/agn.h index 431e13c6ee35..254a5ce52456 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/agn.h +++ b/drivers/net/wireless/intel/iwlwifi/dvm/agn.h | |||
| @@ -439,13 +439,10 @@ static inline void iwl_dvm_set_pmi(struct iwl_priv *priv, bool state) | |||
| 439 | } | 439 | } |
| 440 | 440 | ||
| 441 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 441 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
| 442 | int iwl_dbgfs_register(struct iwl_priv *priv, struct dentry *dbgfs_dir); | 442 | void iwl_dbgfs_register(struct iwl_priv *priv, struct dentry *dbgfs_dir); |
| 443 | #else | 443 | #else |
| 444 | static inline int iwl_dbgfs_register(struct iwl_priv *priv, | 444 | static inline void iwl_dbgfs_register(struct iwl_priv *priv, |
| 445 | struct dentry *dbgfs_dir) | 445 | struct dentry *dbgfs_dir) { } |
| 446 | { | ||
| 447 | return 0; | ||
| 448 | } | ||
| 449 | #endif /* CONFIG_IWLWIFI_DEBUGFS */ | 446 | #endif /* CONFIG_IWLWIFI_DEBUGFS */ |
| 450 | 447 | ||
| 451 | #ifdef CONFIG_IWLWIFI_DEBUG | 448 | #ifdef CONFIG_IWLWIFI_DEBUG |
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c index 3d2e44a642de..d4b19673b06a 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | * GPL LICENSE SUMMARY | 3 | * GPL LICENSE SUMMARY |
| 4 | * | 4 | * |
| 5 | * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. | 5 | * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. |
| 6 | * Copyright (C) 2018 Intel Corporation | ||
| 6 | * | 7 | * |
| 7 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
| 8 | * it under the terms of version 2 of the GNU General Public License as | 9 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -36,31 +37,8 @@ | |||
| 36 | 37 | ||
| 37 | /* create and remove of files */ | 38 | /* create and remove of files */ |
| 38 | #define DEBUGFS_ADD_FILE(name, parent, mode) do { \ | 39 | #define DEBUGFS_ADD_FILE(name, parent, mode) do { \ |
| 39 | if (!debugfs_create_file(#name, mode, parent, priv, \ | 40 | debugfs_create_file(#name, mode, parent, priv, \ |
| 40 | &iwl_dbgfs_##name##_ops)) \ | 41 | &iwl_dbgfs_##name##_ops); \ |
| 41 | goto err; \ | ||
| 42 | } while (0) | ||
| 43 | |||
| 44 | #define DEBUGFS_ADD_BOOL(name, parent, ptr) do { \ | ||
| 45 | struct dentry *__tmp; \ | ||
| 46 | __tmp = debugfs_create_bool(#name, 0600, parent, ptr); \ | ||
| 47 | if (IS_ERR(__tmp) || !__tmp) \ | ||
| 48 | goto err; \ | ||
| 49 | } while (0) | ||
| 50 | |||
| 51 | #define DEBUGFS_ADD_X32(name, parent, ptr) do { \ | ||
| 52 | struct dentry *__tmp; \ | ||
| 53 | __tmp = debugfs_create_x32(#name, 0600, parent, ptr); \ | ||
| 54 | if (IS_ERR(__tmp) || !__tmp) \ | ||
| 55 | goto err; \ | ||
| 56 | } while (0) | ||
| 57 | |||
| 58 | #define DEBUGFS_ADD_U32(name, parent, ptr, mode) do { \ | ||
| 59 | struct dentry *__tmp; \ | ||
| 60 | __tmp = debugfs_create_u32(#name, mode, \ | ||
| 61 | parent, ptr); \ | ||
| 62 | if (IS_ERR(__tmp) || !__tmp) \ | ||
| 63 | goto err; \ | ||
| 64 | } while (0) | 42 | } while (0) |
| 65 | 43 | ||
| 66 | /* file operation */ | 44 | /* file operation */ |
| @@ -2238,7 +2216,7 @@ static ssize_t iwl_dbgfs_log_event_write(struct file *file, | |||
| 2238 | buf_size = min(count, sizeof(buf) - 1); | 2216 | buf_size = min(count, sizeof(buf) - 1); |
| 2239 | if (copy_from_user(buf, user_buf, buf_size)) | 2217 | if (copy_from_user(buf, user_buf, buf_size)) |
| 2240 | return -EFAULT; | 2218 | return -EFAULT; |
| 2241 | if (sscanf(buf, "%d", &event_log_flag) != 1) | 2219 | if (sscanf(buf, "%u", &event_log_flag) != 1) |
| 2242 | return -EFAULT; | 2220 | return -EFAULT; |
| 2243 | if (event_log_flag == 1) | 2221 | if (event_log_flag == 1) |
| 2244 | iwl_dump_nic_event_log(priv, true, NULL); | 2222 | iwl_dump_nic_event_log(priv, true, NULL); |
| @@ -2347,21 +2325,15 @@ DEBUGFS_READ_WRITE_FILE_OPS(calib_disabled); | |||
| 2347 | * Create the debugfs files and directories | 2325 | * Create the debugfs files and directories |
| 2348 | * | 2326 | * |
| 2349 | */ | 2327 | */ |
| 2350 | int iwl_dbgfs_register(struct iwl_priv *priv, struct dentry *dbgfs_dir) | 2328 | void iwl_dbgfs_register(struct iwl_priv *priv, struct dentry *dbgfs_dir) |
| 2351 | { | 2329 | { |
| 2352 | struct dentry *dir_data, *dir_rf, *dir_debug; | 2330 | struct dentry *dir_data, *dir_rf, *dir_debug; |
| 2353 | 2331 | ||
| 2354 | priv->debugfs_dir = dbgfs_dir; | 2332 | priv->debugfs_dir = dbgfs_dir; |
| 2355 | 2333 | ||
| 2356 | dir_data = debugfs_create_dir("data", dbgfs_dir); | 2334 | dir_data = debugfs_create_dir("data", dbgfs_dir); |
| 2357 | if (!dir_data) | ||
| 2358 | goto err; | ||
| 2359 | dir_rf = debugfs_create_dir("rf", dbgfs_dir); | 2335 | dir_rf = debugfs_create_dir("rf", dbgfs_dir); |
| 2360 | if (!dir_rf) | ||
| 2361 | goto err; | ||
| 2362 | dir_debug = debugfs_create_dir("debug", dbgfs_dir); | 2336 | dir_debug = debugfs_create_dir("debug", dbgfs_dir); |
| 2363 | if (!dir_debug) | ||
| 2364 | goto err; | ||
| 2365 | 2337 | ||
| 2366 | DEBUGFS_ADD_FILE(nvm, dir_data, 0400); | 2338 | DEBUGFS_ADD_FILE(nvm, dir_data, 0400); |
| 2367 | DEBUGFS_ADD_FILE(sram, dir_data, 0600); | 2339 | DEBUGFS_ADD_FILE(sram, dir_data, 0600); |
| @@ -2421,13 +2393,6 @@ int iwl_dbgfs_register(struct iwl_priv *priv, struct dentry *dbgfs_dir) | |||
| 2421 | 2393 | ||
| 2422 | snprintf(buf, 100, "../../%pd2", dev_dir); | 2394 | snprintf(buf, 100, "../../%pd2", dev_dir); |
| 2423 | 2395 | ||
| 2424 | if (!debugfs_create_symlink("iwlwifi", mac80211_dir, buf)) | 2396 | debugfs_create_symlink("iwlwifi", mac80211_dir, buf); |
| 2425 | goto err; | ||
| 2426 | } | 2397 | } |
| 2427 | |||
| 2428 | return 0; | ||
| 2429 | |||
| 2430 | err: | ||
| 2431 | IWL_ERR(priv, "failed to create the dvm debugfs entries\n"); | ||
| 2432 | return -ENOMEM; | ||
| 2433 | } | 2398 | } |
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/main.c b/drivers/net/wireless/intel/iwlwifi/dvm/main.c index bd3c3b921d4c..7c68a86ed9e1 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/main.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/main.c | |||
| @@ -1509,13 +1509,10 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, | |||
| 1509 | if (iwlagn_mac_setup_register(priv, &fw->ucode_capa)) | 1509 | if (iwlagn_mac_setup_register(priv, &fw->ucode_capa)) |
| 1510 | goto out_destroy_workqueue; | 1510 | goto out_destroy_workqueue; |
| 1511 | 1511 | ||
| 1512 | if (iwl_dbgfs_register(priv, dbgfs_dir)) | 1512 | iwl_dbgfs_register(priv, dbgfs_dir); |
| 1513 | goto out_mac80211_unregister; | ||
| 1514 | 1513 | ||
| 1515 | return op_mode; | 1514 | return op_mode; |
| 1516 | 1515 | ||
| 1517 | out_mac80211_unregister: | ||
| 1518 | iwlagn_mac_unregister(priv); | ||
| 1519 | out_destroy_workqueue: | 1516 | out_destroy_workqueue: |
| 1520 | iwl_tt_exit(priv); | 1517 | iwl_tt_exit(priv); |
| 1521 | iwl_cancel_deferred_work(priv); | 1518 | iwl_cancel_deferred_work(priv); |
| @@ -1881,7 +1878,7 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, | |||
| 1881 | return pos; | 1878 | return pos; |
| 1882 | } | 1879 | } |
| 1883 | 1880 | ||
| 1884 | if (!(iwl_have_debug_level(IWL_DL_FW_ERRORS)) && !full_log) | 1881 | if (!(iwl_have_debug_level(IWL_DL_FW)) && !full_log) |
| 1885 | size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES) | 1882 | size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES) |
| 1886 | ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size; | 1883 | ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size; |
| 1887 | IWL_ERR(priv, "Start IWL Event Log Dump: display last %u entries\n", | 1884 | IWL_ERR(priv, "Start IWL Event Log Dump: display last %u entries\n", |
| @@ -1897,7 +1894,7 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, | |||
| 1897 | if (!*buf) | 1894 | if (!*buf) |
| 1898 | return -ENOMEM; | 1895 | return -ENOMEM; |
| 1899 | } | 1896 | } |
| 1900 | if (iwl_have_debug_level(IWL_DL_FW_ERRORS) || full_log) { | 1897 | if (iwl_have_debug_level(IWL_DL_FW) || full_log) { |
| 1901 | /* | 1898 | /* |
| 1902 | * if uCode has wrapped back to top of log, | 1899 | * if uCode has wrapped back to top of log, |
| 1903 | * start at the oldest entry, | 1900 | * start at the oldest entry, |
| @@ -1927,7 +1924,7 @@ static void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) | |||
| 1927 | unsigned int reload_msec; | 1924 | unsigned int reload_msec; |
| 1928 | unsigned long reload_jiffies; | 1925 | unsigned long reload_jiffies; |
| 1929 | 1926 | ||
| 1930 | if (iwl_have_debug_level(IWL_DL_FW_ERRORS)) | 1927 | if (iwl_have_debug_level(IWL_DL_FW)) |
| 1931 | iwl_print_rx_config_cmd(priv, IWL_RXON_CTX_BSS); | 1928 | iwl_print_rx_config_cmd(priv, IWL_RXON_CTX_BSS); |
| 1932 | 1929 | ||
| 1933 | /* uCode is no longer loaded. */ | 1930 | /* uCode is no longer loaded. */ |
| @@ -1965,12 +1962,12 @@ static void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) | |||
| 1965 | 1962 | ||
| 1966 | if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) { | 1963 | if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) { |
| 1967 | if (iwlwifi_mod_params.fw_restart) { | 1964 | if (iwlwifi_mod_params.fw_restart) { |
| 1968 | IWL_DEBUG_FW_ERRORS(priv, | 1965 | IWL_DEBUG_FW(priv, |
| 1969 | "Restarting adapter due to uCode error.\n"); | 1966 | "Restarting adapter due to uCode error.\n"); |
| 1970 | queue_work(priv->workqueue, &priv->restart); | 1967 | queue_work(priv->workqueue, &priv->restart); |
| 1971 | } else | 1968 | } else |
| 1972 | IWL_DEBUG_FW_ERRORS(priv, | 1969 | IWL_DEBUG_FW(priv, |
| 1973 | "Detected FW error, but not restarting\n"); | 1970 | "Detected FW error, but not restarting\n"); |
| 1974 | } | 1971 | } |
| 1975 | } | 1972 | } |
| 1976 | 1973 | ||
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/rx.c b/drivers/net/wireless/intel/iwlwifi/dvm/rx.c index 6f17a5e24e82..e224b23f0ba8 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/rx.c | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | * | 2 | * |
| 3 | * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. |
| 4 | * Copyright(c) 2015 Intel Deutschland GmbH | 4 | * Copyright(c) 2015 Intel Deutschland GmbH |
| 5 | * Copyright(c) 2018 Intel Corporation | ||
| 5 | * | 6 | * |
| 6 | * Portions of this file are derived from the ipw3945 project, as well | 7 | * Portions of this file are derived from the ipw3945 project, as well |
| 7 | * as portionhelp of the ieee80211 subsystem header files. | 8 | * as portionhelp of the ieee80211 subsystem header files. |
| @@ -592,7 +593,7 @@ static int iwlagn_set_decrypted_flag(struct iwl_priv *priv, | |||
| 592 | if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) == | 593 | if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) == |
| 593 | RX_RES_STATUS_BAD_KEY_TTAK) | 594 | RX_RES_STATUS_BAD_KEY_TTAK) |
| 594 | break; | 595 | break; |
| 595 | 596 | /* fall through */ | |
| 596 | case RX_RES_STATUS_SEC_TYPE_WEP: | 597 | case RX_RES_STATUS_SEC_TYPE_WEP: |
| 597 | if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) == | 598 | if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) == |
| 598 | RX_RES_STATUS_BAD_ICV_MIC) { | 599 | RX_RES_STATUS_BAD_ICV_MIC) { |
| @@ -601,6 +602,7 @@ static int iwlagn_set_decrypted_flag(struct iwl_priv *priv, | |||
| 601 | IWL_DEBUG_RX(priv, "Packet destroyed\n"); | 602 | IWL_DEBUG_RX(priv, "Packet destroyed\n"); |
| 602 | return -1; | 603 | return -1; |
| 603 | } | 604 | } |
| 605 | /* fall through */ | ||
| 604 | case RX_RES_STATUS_SEC_TYPE_CCMP: | 606 | case RX_RES_STATUS_SEC_TYPE_CCMP: |
| 605 | if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) == | 607 | if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) == |
| 606 | RX_RES_STATUS_DECRYPT_OK) { | 608 | RX_RES_STATUS_DECRYPT_OK) { |
| @@ -729,7 +731,7 @@ static u32 iwlagn_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in) | |||
| 729 | decrypt_out |= RX_RES_STATUS_BAD_KEY_TTAK; | 731 | decrypt_out |= RX_RES_STATUS_BAD_KEY_TTAK; |
| 730 | break; | 732 | break; |
| 731 | } | 733 | } |
| 732 | /* fall through if TTAK OK */ | 734 | /* fall through */ |
| 733 | default: | 735 | default: |
| 734 | if (!(decrypt_in & RX_MPDU_RES_STATUS_ICV_OK)) | 736 | if (!(decrypt_in & RX_MPDU_RES_STATUS_ICV_OK)) |
| 735 | decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC; | 737 | decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC; |
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/scan.c b/drivers/net/wireless/intel/iwlwifi/dvm/scan.c index 8d7aafb4d9e9..f190f7beb3a8 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/scan.c | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | * GPL LICENSE SUMMARY | 3 | * GPL LICENSE SUMMARY |
| 4 | * | 4 | * |
| 5 | * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. | 5 | * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. |
| 6 | * Copyright(c) 2018 Intel Corporation | ||
| 6 | * | 7 | * |
| 7 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
| 8 | * it under the terms of version 2 of the GNU General Public License as | 9 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -418,7 +419,7 @@ static u16 iwl_limit_dwell(struct iwl_priv *priv, u16 dwell_time) | |||
| 418 | limit = (limits[1] * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2; | 419 | limit = (limits[1] * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2; |
| 419 | limit /= 2; | 420 | limit /= 2; |
| 420 | dwell_time = min(limit, dwell_time); | 421 | dwell_time = min(limit, dwell_time); |
| 421 | /* fall through to limit further */ | 422 | /* fall through */ |
| 422 | case 1: | 423 | case 1: |
| 423 | limit = (limits[0] * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2; | 424 | limit = (limits[0] * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2; |
| 424 | limit /= n_active; | 425 | limit /= n_active; |
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c index 32d000cffe9f..405038ce98d6 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2017 Intel Deutschland GmbH | 8 | * Copyright(c) 2017 Intel Deutschland GmbH |
| 9 | * Copyright (C) 2019 Intel Corporation | ||
| 9 | * | 10 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 11 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 12 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -26,6 +27,7 @@ | |||
| 26 | * BSD LICENSE | 27 | * BSD LICENSE |
| 27 | * | 28 | * |
| 28 | * Copyright(c) 2017 Intel Deutschland GmbH | 29 | * Copyright(c) 2017 Intel Deutschland GmbH |
| 30 | * Copyright (C) 2019 Intel Corporation | ||
| 29 | * All rights reserved. | 31 | * All rights reserved. |
| 30 | * | 32 | * |
| 31 | * Redistribution and use in source and binary forms, with or without | 33 | * Redistribution and use in source and binary forms, with or without |
| @@ -205,3 +207,33 @@ out: | |||
| 205 | return dflt_pwr_limit; | 207 | return dflt_pwr_limit; |
| 206 | } | 208 | } |
| 207 | IWL_EXPORT_SYMBOL(iwl_acpi_get_pwr_limit); | 209 | IWL_EXPORT_SYMBOL(iwl_acpi_get_pwr_limit); |
| 210 | |||
| 211 | int iwl_acpi_get_eckv(struct device *dev, u32 *extl_clk) | ||
| 212 | { | ||
| 213 | union acpi_object *wifi_pkg, *data; | ||
| 214 | int ret; | ||
| 215 | |||
| 216 | data = iwl_acpi_get_object(dev, ACPI_ECKV_METHOD); | ||
| 217 | if (IS_ERR(data)) | ||
| 218 | return PTR_ERR(data); | ||
| 219 | |||
| 220 | wifi_pkg = iwl_acpi_get_wifi_pkg(dev, data, ACPI_ECKV_WIFI_DATA_SIZE); | ||
| 221 | if (IS_ERR(wifi_pkg)) { | ||
| 222 | ret = PTR_ERR(wifi_pkg); | ||
| 223 | goto out_free; | ||
| 224 | } | ||
| 225 | |||
| 226 | if (wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER) { | ||
| 227 | ret = -EINVAL; | ||
| 228 | goto out_free; | ||
| 229 | } | ||
| 230 | |||
| 231 | *extl_clk = wifi_pkg->package.elements[1].integer.value; | ||
| 232 | |||
| 233 | ret = 0; | ||
| 234 | |||
| 235 | out_free: | ||
| 236 | kfree(data); | ||
| 237 | return ret; | ||
| 238 | } | ||
| 239 | IWL_EXPORT_SYMBOL(iwl_acpi_get_eckv); | ||
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.h b/drivers/net/wireless/intel/iwlwifi/fw/acpi.h index 7492dfb6729b..f5704e16643f 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.h | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2017 Intel Deutschland GmbH | 8 | * Copyright(c) 2017 Intel Deutschland GmbH |
| 9 | * Copyright(c) 2018 Intel Corporation | 9 | * Copyright(c) 2018 - 2019 Intel Corporation |
| 10 | * | 10 | * |
| 11 | * This program is free software; you can redistribute it and/or modify | 11 | * 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 | 12 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -27,7 +27,7 @@ | |||
| 27 | * BSD LICENSE | 27 | * BSD LICENSE |
| 28 | * | 28 | * |
| 29 | * Copyright(c) 2017 Intel Deutschland GmbH | 29 | * Copyright(c) 2017 Intel Deutschland GmbH |
| 30 | * Copyright(c) 2018 Intel Corporation | 30 | * Copyright(c) 2018 - 2019 Intel Corporation |
| 31 | * All rights reserved. | 31 | * All rights reserved. |
| 32 | * | 32 | * |
| 33 | * Redistribution and use in source and binary forms, with or without | 33 | * Redistribution and use in source and binary forms, with or without |
| @@ -67,6 +67,7 @@ | |||
| 67 | #define ACPI_WGDS_METHOD "WGDS" | 67 | #define ACPI_WGDS_METHOD "WGDS" |
| 68 | #define ACPI_WRDD_METHOD "WRDD" | 68 | #define ACPI_WRDD_METHOD "WRDD" |
| 69 | #define ACPI_SPLC_METHOD "SPLC" | 69 | #define ACPI_SPLC_METHOD "SPLC" |
| 70 | #define ACPI_ECKV_METHOD "ECKV" | ||
| 70 | 71 | ||
| 71 | #define ACPI_WIFI_DOMAIN (0x07) | 72 | #define ACPI_WIFI_DOMAIN (0x07) |
| 72 | 73 | ||
| @@ -86,6 +87,7 @@ | |||
| 86 | #define ACPI_WGDS_WIFI_DATA_SIZE 19 | 87 | #define ACPI_WGDS_WIFI_DATA_SIZE 19 |
| 87 | #define ACPI_WRDD_WIFI_DATA_SIZE 2 | 88 | #define ACPI_WRDD_WIFI_DATA_SIZE 2 |
| 88 | #define ACPI_SPLC_WIFI_DATA_SIZE 2 | 89 | #define ACPI_SPLC_WIFI_DATA_SIZE 2 |
| 90 | #define ACPI_ECKV_WIFI_DATA_SIZE 2 | ||
| 89 | 91 | ||
| 90 | #define ACPI_WGDS_NUM_BANDS 2 | 92 | #define ACPI_WGDS_NUM_BANDS 2 |
| 91 | #define ACPI_WGDS_TABLE_SIZE 3 | 93 | #define ACPI_WGDS_TABLE_SIZE 3 |
| @@ -109,6 +111,17 @@ int iwl_acpi_get_mcc(struct device *dev, char *mcc); | |||
| 109 | 111 | ||
| 110 | u64 iwl_acpi_get_pwr_limit(struct device *dev); | 112 | u64 iwl_acpi_get_pwr_limit(struct device *dev); |
| 111 | 113 | ||
| 114 | /* | ||
| 115 | * iwl_acpi_get_eckv - read external clock validation from ACPI, if available | ||
| 116 | * | ||
| 117 | * @dev: the struct device | ||
| 118 | * @extl_clk: output var (2 bytes) that will get the clk indication. | ||
| 119 | * | ||
| 120 | * This function tries to read the external clock indication | ||
| 121 | * from ACPI if available. | ||
| 122 | */ | ||
| 123 | int iwl_acpi_get_eckv(struct device *dev, u32 *extl_clk); | ||
| 124 | |||
| 112 | #else /* CONFIG_ACPI */ | 125 | #else /* CONFIG_ACPI */ |
| 113 | 126 | ||
| 114 | static inline void *iwl_acpi_get_object(struct device *dev, acpi_string method) | 127 | static inline void *iwl_acpi_get_object(struct device *dev, acpi_string method) |
| @@ -133,5 +146,10 @@ static inline u64 iwl_acpi_get_pwr_limit(struct device *dev) | |||
| 133 | return 0; | 146 | return 0; |
| 134 | } | 147 | } |
| 135 | 148 | ||
| 149 | static inline int iwl_acpi_get_eckv(struct device *dev, u32 *extl_clk) | ||
| 150 | { | ||
| 151 | return -ENOENT; | ||
| 152 | } | ||
| 153 | |||
| 136 | #endif /* CONFIG_ACPI */ | 154 | #endif /* CONFIG_ACPI */ |
| 137 | #endif /* __iwl_fw_acpi__ */ | 155 | #endif /* __iwl_fw_acpi__ */ |
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/alive.h b/drivers/net/wireless/intel/iwlwifi/fw/api/alive.h index 08d3d8a190f6..df1bd0d2450e 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/alive.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/alive.h | |||
| @@ -96,14 +96,7 @@ enum { | |||
| 96 | 96 | ||
| 97 | #define IWL_ALIVE_FLG_RFKILL BIT(0) | 97 | #define IWL_ALIVE_FLG_RFKILL BIT(0) |
| 98 | 98 | ||
| 99 | struct iwl_lmac_alive { | 99 | struct iwl_lmac_debug_addrs { |
| 100 | __le32 ucode_major; | ||
| 101 | __le32 ucode_minor; | ||
| 102 | u8 ver_subtype; | ||
| 103 | u8 ver_type; | ||
| 104 | u8 mac; | ||
| 105 | u8 opt; | ||
| 106 | __le32 timestamp; | ||
| 107 | __le32 error_event_table_ptr; /* SRAM address for error log */ | 100 | __le32 error_event_table_ptr; /* SRAM address for error log */ |
| 108 | __le32 log_event_table_ptr; /* SRAM address for LMAC event log */ | 101 | __le32 log_event_table_ptr; /* SRAM address for LMAC event log */ |
| 109 | __le32 cpu_register_ptr; | 102 | __le32 cpu_register_ptr; |
| @@ -112,13 +105,28 @@ struct iwl_lmac_alive { | |||
| 112 | __le32 scd_base_ptr; /* SRAM address for SCD */ | 105 | __le32 scd_base_ptr; /* SRAM address for SCD */ |
| 113 | __le32 st_fwrd_addr; /* pointer to Store and forward */ | 106 | __le32 st_fwrd_addr; /* pointer to Store and forward */ |
| 114 | __le32 st_fwrd_size; | 107 | __le32 st_fwrd_size; |
| 108 | } __packed; /* UCODE_DEBUG_ADDRS_API_S_VER_2 */ | ||
| 109 | |||
| 110 | struct iwl_lmac_alive { | ||
| 111 | __le32 ucode_major; | ||
| 112 | __le32 ucode_minor; | ||
| 113 | u8 ver_subtype; | ||
| 114 | u8 ver_type; | ||
| 115 | u8 mac; | ||
| 116 | u8 opt; | ||
| 117 | __le32 timestamp; | ||
| 118 | struct iwl_lmac_debug_addrs dbg_ptrs; | ||
| 115 | } __packed; /* UCODE_ALIVE_NTFY_API_S_VER_3 */ | 119 | } __packed; /* UCODE_ALIVE_NTFY_API_S_VER_3 */ |
| 116 | 120 | ||
| 121 | struct iwl_umac_debug_addrs { | ||
| 122 | __le32 error_info_addr; /* SRAM address for UMAC error log */ | ||
| 123 | __le32 dbg_print_buff_addr; | ||
| 124 | } __packed; /* UMAC_DEBUG_ADDRS_API_S_VER_1 */ | ||
| 125 | |||
| 117 | struct iwl_umac_alive { | 126 | struct iwl_umac_alive { |
| 118 | __le32 umac_major; /* UMAC version: major */ | 127 | __le32 umac_major; /* UMAC version: major */ |
| 119 | __le32 umac_minor; /* UMAC version: minor */ | 128 | __le32 umac_minor; /* UMAC version: minor */ |
| 120 | __le32 error_info_addr; /* SRAM address for UMAC error log */ | 129 | struct iwl_umac_debug_addrs dbg_ptrs; |
| 121 | __le32 dbg_print_buff_addr; | ||
| 122 | } __packed; /* UMAC_ALIVE_DATA_API_S_VER_2 */ | 130 | } __packed; /* UMAC_ALIVE_DATA_API_S_VER_2 */ |
| 123 | 131 | ||
| 124 | struct mvm_alive_resp_v3 { | 132 | struct mvm_alive_resp_v3 { |
| @@ -189,4 +197,24 @@ struct iwl_card_state_notif { | |||
| 189 | __le32 flags; | 197 | __le32 flags; |
| 190 | } __packed; /* CARD_STATE_NTFY_API_S_VER_1 */ | 198 | } __packed; /* CARD_STATE_NTFY_API_S_VER_1 */ |
| 191 | 199 | ||
| 200 | /** | ||
| 201 | * enum iwl_error_recovery_flags - flags for error recovery cmd | ||
| 202 | * @ERROR_RECOVERY_UPDATE_DB: update db from blob sent | ||
| 203 | * @ERROR_RECOVERY_END_OF_RECOVERY: end of recovery | ||
| 204 | */ | ||
| 205 | enum iwl_error_recovery_flags { | ||
| 206 | ERROR_RECOVERY_UPDATE_DB = BIT(0), | ||
| 207 | ERROR_RECOVERY_END_OF_RECOVERY = BIT(1), | ||
| 208 | }; | ||
| 209 | |||
| 210 | /** | ||
| 211 | * struct iwl_fw_error_recovery_cmd - recovery cmd sent upon assert | ||
| 212 | * @flags: &enum iwl_error_recovery_flags | ||
| 213 | * @buf_size: db buffer size in bytes | ||
| 214 | */ | ||
| 215 | struct iwl_fw_error_recovery_cmd { | ||
| 216 | __le32 flags; | ||
| 217 | __le32 buf_size; | ||
| 218 | } __packed; /* ERROR_RECOVERY_CMD_HDR_API_S_VER_1 */ | ||
| 219 | |||
| 192 | #endif /* __iwl_fw_api_alive_h__ */ | 220 | #endif /* __iwl_fw_api_alive_h__ */ |
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h b/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h index 0290b333d860..4d2274bcc0b5 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h | |||
| @@ -643,6 +643,11 @@ enum iwl_system_subcmd_ids { | |||
| 643 | * @INIT_EXTENDED_CFG_CMD: &struct iwl_init_extended_cfg_cmd | 643 | * @INIT_EXTENDED_CFG_CMD: &struct iwl_init_extended_cfg_cmd |
| 644 | */ | 644 | */ |
| 645 | INIT_EXTENDED_CFG_CMD = 0x03, | 645 | INIT_EXTENDED_CFG_CMD = 0x03, |
| 646 | |||
| 647 | /** | ||
| 648 | * @FW_ERROR_RECOVERY_CMD: &struct iwl_fw_error_recovery_cmd | ||
| 649 | */ | ||
| 650 | FW_ERROR_RECOVERY_CMD = 0x7, | ||
| 646 | }; | 651 | }; |
| 647 | 652 | ||
| 648 | #endif /* __iwl_fw_api_commands_h__ */ | 653 | #endif /* __iwl_fw_api_commands_h__ */ |
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h b/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h index ab82b7a67967..33858787817b 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright (C) 2018 Intel Corporation | 8 | * Copyright (C) 2018 - 2019 Intel Corporation |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -25,7 +25,7 @@ | |||
| 25 | * | 25 | * |
| 26 | * BSD LICENSE | 26 | * BSD LICENSE |
| 27 | * | 27 | * |
| 28 | * Copyright (C) 2018 Intel Corporation | 28 | * Copyright (C) 2018 - 2019 Intel Corporation |
| 29 | * All rights reserved. | 29 | * All rights reserved. |
| 30 | * | 30 | * |
| 31 | * Redistribution and use in source and binary forms, with or without | 31 | * Redistribution and use in source and binary forms, with or without |
| @@ -70,7 +70,7 @@ struct iwl_fw_ini_header { | |||
| 70 | __le32 tlv_version; | 70 | __le32 tlv_version; |
| 71 | __le32 apply_point; | 71 | __le32 apply_point; |
| 72 | u8 data[]; | 72 | u8 data[]; |
| 73 | } __packed; /* FW_INI_HEADER_TLV_S */ | 73 | } __packed; /* FW_DEBUG_TLV_HEADER_S */ |
| 74 | 74 | ||
| 75 | /** | 75 | /** |
| 76 | * struct iwl_fw_ini_allocation_tlv - (IWL_FW_INI_TLV_TYPE_BUFFER_ALLOCATION) | 76 | * struct iwl_fw_ini_allocation_tlv - (IWL_FW_INI_TLV_TYPE_BUFFER_ALLOCATION) |
| @@ -92,7 +92,7 @@ struct iwl_fw_ini_allocation_tlv { | |||
| 92 | __le32 size; | 92 | __le32 size; |
| 93 | __le32 max_fragments; | 93 | __le32 max_fragments; |
| 94 | __le32 min_frag_size; | 94 | __le32 min_frag_size; |
| 95 | } __packed; /* FW_INI_BUFFER_ALLOCATION_TLV_S_VER_1 */ | 95 | } __packed; /* FW_DEBUG_TLV_BUFFER_ALLOCATION_TLV_S_VER_1 */ |
| 96 | 96 | ||
| 97 | /** | 97 | /** |
| 98 | * struct iwl_fw_ini_hcmd (IWL_FW_INI_TLV_TYPE_HCMD) | 98 | * struct iwl_fw_ini_hcmd (IWL_FW_INI_TLV_TYPE_HCMD) |
| @@ -108,7 +108,7 @@ struct iwl_fw_ini_hcmd { | |||
| 108 | u8 group; | 108 | u8 group; |
| 109 | __le16 padding; | 109 | __le16 padding; |
| 110 | u8 data[0]; | 110 | u8 data[0]; |
| 111 | } __packed; /* FW_INI_HCMD_S */ | 111 | } __packed; /* FW_DEBUG_TLV_HCMD_DATA_S */ |
| 112 | 112 | ||
| 113 | /** | 113 | /** |
| 114 | * struct iwl_fw_ini_hcmd_tlv | 114 | * struct iwl_fw_ini_hcmd_tlv |
| @@ -118,7 +118,7 @@ struct iwl_fw_ini_hcmd { | |||
| 118 | struct iwl_fw_ini_hcmd_tlv { | 118 | struct iwl_fw_ini_hcmd_tlv { |
| 119 | struct iwl_fw_ini_header header; | 119 | struct iwl_fw_ini_header header; |
| 120 | struct iwl_fw_ini_hcmd hcmd; | 120 | struct iwl_fw_ini_hcmd hcmd; |
| 121 | } __packed; /* FW_INI_HCMD_TLV_S_VER_1 */ | 121 | } __packed; /* FW_DEBUG_TLV_HCMD_S_VER_1 */ |
| 122 | 122 | ||
| 123 | /* | 123 | /* |
| 124 | * struct iwl_fw_ini_debug_flow_tlv (IWL_FW_INI_TLV_TYPE_DEBUG_FLOW) | 124 | * struct iwl_fw_ini_debug_flow_tlv (IWL_FW_INI_TLV_TYPE_DEBUG_FLOW) |
| @@ -129,20 +129,50 @@ struct iwl_fw_ini_hcmd_tlv { | |||
| 129 | struct iwl_fw_ini_debug_flow_tlv { | 129 | struct iwl_fw_ini_debug_flow_tlv { |
| 130 | struct iwl_fw_ini_header header; | 130 | struct iwl_fw_ini_header header; |
| 131 | __le32 debug_flow_cfg; | 131 | __le32 debug_flow_cfg; |
| 132 | } __packed; /* FW_INI_DEBUG_FLOW_TLV_S_VER_1 */ | 132 | } __packed; /* FW_DEBUG_TLV_FLOW_TLV_S_VER_1 */ |
| 133 | 133 | ||
| 134 | #define IWL_FW_INI_MAX_REGION_ID 20 | 134 | #define IWL_FW_INI_MAX_REGION_ID 64 |
| 135 | #define IWL_FW_INI_MAX_NAME 32 | 135 | #define IWL_FW_INI_MAX_NAME 32 |
| 136 | |||
| 137 | /** | ||
| 138 | * struct iwl_fw_ini_region_cfg_internal - meta data of internal memory region | ||
| 139 | * @num_of_range: the amount of ranges in the region | ||
| 140 | * @range_data_size: size of the data to read per range, in bytes. | ||
| 141 | */ | ||
| 142 | struct iwl_fw_ini_region_cfg_internal { | ||
| 143 | __le32 num_of_ranges; | ||
| 144 | __le32 range_data_size; | ||
| 145 | } __packed; /* FW_DEBUG_TLV_REGION_NIC_INTERNAL_RANGES_S */ | ||
| 146 | |||
| 147 | /** | ||
| 148 | * struct iwl_fw_ini_region_cfg_fifos - meta data of fifos region | ||
| 149 | * @fid1: fifo id 1 - bitmap of lmac tx/rx fifos to include in the region | ||
| 150 | * @fid2: fifo id 2 - bitmap of umac rx fifos to include in the region. | ||
| 151 | * It is unused for tx. | ||
| 152 | * @num_of_registers: number of prph registers in the region, each register is | ||
| 153 | * 4 bytes size. | ||
| 154 | * @header_only: none zero value indicates that this region does not include | ||
| 155 | * fifo data and includes only the given registers. | ||
| 156 | */ | ||
| 157 | struct iwl_fw_ini_region_cfg_fifos { | ||
| 158 | __le32 fid1; | ||
| 159 | __le32 fid2; | ||
| 160 | __le32 num_of_registers; | ||
| 161 | __le32 header_only; | ||
| 162 | } __packed; /* FW_DEBUG_TLV_REGION_FIFOS_S */ | ||
| 163 | |||
| 136 | /** | 164 | /** |
| 137 | * struct iwl_fw_ini_region_cfg | 165 | * struct iwl_fw_ini_region_cfg |
| 138 | * @region_id: ID of this dump configuration | 166 | * @region_id: ID of this dump configuration |
| 139 | * @region_type: &enum iwl_fw_ini_region_type | 167 | * @region_type: &enum iwl_fw_ini_region_type |
| 140 | * @num_regions: amount of regions in the address array. | 168 | * @num_regions: amount of regions in the address array. |
| 141 | * @allocation_id: For DRAM type field substitutes for allocation_id. | ||
| 142 | * @name_len: name length | 169 | * @name_len: name length |
| 143 | * @name: file name to use for this region | 170 | * @name: file name to use for this region |
| 144 | * @size: size of the data, in bytes.(unused for IWL_FW_INI_REGION_DRAM_BUFFER) | 171 | * @internal: used in case the region uses internal memory. |
| 145 | * @start_addr: array of addresses. (unused for IWL_FW_INI_REGION_DRAM_BUFFER) | 172 | * @allocation_id: For DRAM type field substitutes for allocation_id |
| 173 | * @fifos: used in case of fifos region. | ||
| 174 | * @offset: offset to use for each memory base address | ||
| 175 | * @start_addr: array of addresses. | ||
| 146 | */ | 176 | */ |
| 147 | struct iwl_fw_ini_region_cfg { | 177 | struct iwl_fw_ini_region_cfg { |
| 148 | __le32 region_id; | 178 | __le32 region_id; |
| @@ -150,32 +180,38 @@ struct iwl_fw_ini_region_cfg { | |||
| 150 | __le32 name_len; | 180 | __le32 name_len; |
| 151 | u8 name[IWL_FW_INI_MAX_NAME]; | 181 | u8 name[IWL_FW_INI_MAX_NAME]; |
| 152 | union { | 182 | union { |
| 153 | __le32 num_regions; | 183 | struct iwl_fw_ini_region_cfg_internal internal; |
| 154 | __le32 allocation_id; | 184 | __le32 allocation_id; |
| 185 | struct iwl_fw_ini_region_cfg_fifos fifos; | ||
| 155 | }; | 186 | }; |
| 156 | __le32 size; | 187 | __le32 offset; |
| 157 | __le32 start_addr[]; | 188 | __le32 start_addr[]; |
| 158 | } __packed; /* FW_INI_REGION_CONFIG_S */ | 189 | } __packed; /* FW_DEBUG_TLV_REGION_CONFIG_S */ |
| 159 | 190 | ||
| 160 | /** | 191 | /** |
| 161 | * struct iwl_fw_ini_region_tlv - (IWL_FW_INI_TLV_TYPE_REGION_CFG) | 192 | * struct iwl_fw_ini_region_tlv - (IWL_FW_INI_TLV_TYPE_REGION_CFG) |
| 162 | * DUMP sections define IDs and triggers that use those IDs TLV | 193 | * DUMP sections define IDs and triggers that use those IDs TLV |
| 163 | * @header: header | 194 | * @header: header |
| 164 | * @num_regions: how many different region section and IDs are coming next | 195 | * @num_regions: how many different region section and IDs are coming next |
| 165 | * @iwl_fw_ini_dump dump_config: list of dump configurations | 196 | * @region_config: list of dump configurations |
| 166 | */ | 197 | */ |
| 167 | struct iwl_fw_ini_region_tlv { | 198 | struct iwl_fw_ini_region_tlv { |
| 168 | struct iwl_fw_ini_header header; | 199 | struct iwl_fw_ini_header header; |
| 169 | __le32 num_regions; | 200 | __le32 num_regions; |
| 170 | struct iwl_fw_ini_region_cfg region_config[]; | 201 | struct iwl_fw_ini_region_cfg region_config[]; |
| 171 | } __packed; /* FW_INI_REGION_CFG_S */ | 202 | } __packed; /* FW_DEBUG_TLV_REGIONS_S_VER_1 */ |
| 172 | 203 | ||
| 173 | /** | 204 | /** |
| 174 | * struct iwl_fw_ini_trigger - (IWL_FW_INI_TLV_TYPE_DUMP_CFG) | 205 | * struct iwl_fw_ini_trigger - (IWL_FW_INI_TLV_TYPE_DUMP_CFG) |
| 175 | * Region sections define IDs and triggers that use those IDs TLV | 206 | * Region sections define IDs and triggers that use those IDs TLV |
| 176 | * | 207 | * |
| 177 | * @trigger_id: enum &iwl_fw_ini_tigger_id | 208 | * @trigger_id: enum &iwl_fw_ini_tigger_id |
| 178 | * @ignore_default: override FW TLV with binary TLV | 209 | * @override_trig: determines how apply trigger in case a trigger with the |
| 210 | * same id is already in use. Using the first 2 bytes: | ||
| 211 | * Byte 0: if 0, override trigger configuration, otherwise use the | ||
| 212 | * existing configuration. | ||
| 213 | * Byte 1: if 0, override trigger regions, otherwise append regions to | ||
| 214 | * existing trigger. | ||
| 179 | * @dump_delay: delay from trigger fire to dump, in usec | 215 | * @dump_delay: delay from trigger fire to dump, in usec |
| 180 | * @occurrences: max amount of times to be fired | 216 | * @occurrences: max amount of times to be fired |
| 181 | * @ignore_consec: ignore consecutive triggers, in usec | 217 | * @ignore_consec: ignore consecutive triggers, in usec |
| @@ -187,7 +223,7 @@ struct iwl_fw_ini_region_tlv { | |||
| 187 | */ | 223 | */ |
| 188 | struct iwl_fw_ini_trigger { | 224 | struct iwl_fw_ini_trigger { |
| 189 | __le32 trigger_id; | 225 | __le32 trigger_id; |
| 190 | __le32 ignore_default; | 226 | __le32 override_trig; |
| 191 | __le32 dump_delay; | 227 | __le32 dump_delay; |
| 192 | __le32 occurrences; | 228 | __le32 occurrences; |
| 193 | __le32 ignore_consec; | 229 | __le32 ignore_consec; |
| @@ -196,7 +232,7 @@ struct iwl_fw_ini_trigger { | |||
| 196 | __le32 trigger_data; | 232 | __le32 trigger_data; |
| 197 | __le32 num_regions; | 233 | __le32 num_regions; |
| 198 | __le32 data[]; | 234 | __le32 data[]; |
| 199 | } __packed; /* FW_INI_TRIGGER_CONFIG_S */ | 235 | } __packed; /* FW_TLV_DEBUG_TRIGGER_CONFIG_S */ |
| 200 | 236 | ||
| 201 | /** | 237 | /** |
| 202 | * struct iwl_fw_ini_trigger_tlv - (IWL_FW_INI_TLV_TYPE_TRIGGERS_CFG) | 238 | * struct iwl_fw_ini_trigger_tlv - (IWL_FW_INI_TLV_TYPE_TRIGGERS_CFG) |
| @@ -210,20 +246,17 @@ struct iwl_fw_ini_trigger_tlv { | |||
| 210 | struct iwl_fw_ini_header header; | 246 | struct iwl_fw_ini_header header; |
| 211 | __le32 num_triggers; | 247 | __le32 num_triggers; |
| 212 | struct iwl_fw_ini_trigger trigger_config[]; | 248 | struct iwl_fw_ini_trigger trigger_config[]; |
| 213 | } __packed; /* FW_INI_TRIGGER_CFG_S */ | 249 | } __packed; /* FW_TLV_DEBUG_TRIGGERS_S_VER_1 */ |
| 214 | 250 | ||
| 215 | /** | 251 | /** |
| 216 | * enum iwl_fw_ini_trigger_id | 252 | * enum iwl_fw_ini_trigger_id |
| 217 | * @IWL_FW_TRIGGER_ID_FW_ASSERT: FW assert | 253 | * @IWL_FW_TRIGGER_ID_FW_ASSERT: FW assert |
| 218 | * @IWL_FW_TRIGGER_ID_FW_TFD_Q_HANG: TFD queue hang | ||
| 219 | * @IWL_FW_TRIGGER_ID_FW_HW_ERROR: HW assert | 254 | * @IWL_FW_TRIGGER_ID_FW_HW_ERROR: HW assert |
| 220 | * @IWL_FW_TRIGGER_ID_FW_TRIGGER_ERROR: FW error notification | 255 | * @IWL_FW_TRIGGER_ID_FW_TFD_Q_HANG: TFD queue hang |
| 221 | * @IWL_FW_TRIGGER_ID_FW_TRIGGER_WARNING: FW warning notification | 256 | * @IWL_FW_TRIGGER_ID_FW_DEBUG_HOST_TRIGGER: FW debug notification |
| 222 | * @IWL_FW_TRIGGER_ID_FW_TRIGGER_INFO: FW info notification | 257 | * @IWL_FW_TRIGGER_ID_FW_GENERIC_NOTIFOCATION: FW generic notification |
| 223 | * @IWL_FW_TRIGGER_ID_FW_TRIGGER_DEBUG: FW debug notification | ||
| 224 | * @IWL_FW_TRIGGER_ID_USER_TRIGGER: User trigger | 258 | * @IWL_FW_TRIGGER_ID_USER_TRIGGER: User trigger |
| 225 | * @IWL_FW_TRIGGER_ID_HOST_PEER_CLIENT_INACTIVITY: peer inactivity | 259 | * @IWL_FW_TRIGGER_ID_HOST_PEER_CLIENT_INACTIVITY: peer inactivity |
| 226 | * @FW_DEBUG_TLV_TRIGGER_ID_HOST_DID_INITIATED_EVENT: undefined | ||
| 227 | * @IWL_FW_TRIGGER_ID_HOST_TX_LATENCY_THRESHOLD_CROSSED: TX latency | 260 | * @IWL_FW_TRIGGER_ID_HOST_TX_LATENCY_THRESHOLD_CROSSED: TX latency |
| 228 | * threshold was crossed | 261 | * threshold was crossed |
| 229 | * @IWL_FW_TRIGGER_ID_HOST_TX_RESPONSE_STATUS_FAILED: TX failed | 262 | * @IWL_FW_TRIGGER_ID_HOST_TX_RESPONSE_STATUS_FAILED: TX failed |
| @@ -257,50 +290,53 @@ struct iwl_fw_ini_trigger_tlv { | |||
| 257 | * @IWL_FW_TRIGGER_ID_NUM: number of trigger IDs | 290 | * @IWL_FW_TRIGGER_ID_NUM: number of trigger IDs |
| 258 | */ | 291 | */ |
| 259 | enum iwl_fw_ini_trigger_id { | 292 | enum iwl_fw_ini_trigger_id { |
| 293 | IWL_FW_TRIGGER_ID_INVALID = 0, | ||
| 294 | |||
| 260 | /* Errors triggers */ | 295 | /* Errors triggers */ |
| 261 | IWL_FW_TRIGGER_ID_FW_ASSERT = 1, | 296 | IWL_FW_TRIGGER_ID_FW_ASSERT = 1, |
| 262 | IWL_FW_TRIGGER_ID_FW_TFD_Q_HANG = 2, | 297 | IWL_FW_TRIGGER_ID_FW_HW_ERROR = 2, |
| 263 | IWL_FW_TRIGGER_ID_FW_HW_ERROR = 3, | 298 | IWL_FW_TRIGGER_ID_FW_TFD_Q_HANG = 3, |
| 264 | /* Generic triggers */ | 299 | |
| 265 | IWL_FW_TRIGGER_ID_FW_TRIGGER_ERROR = 4, | 300 | /* FW triggers */ |
| 266 | IWL_FW_TRIGGER_ID_FW_TRIGGER_WARNING = 5, | 301 | IWL_FW_TRIGGER_ID_FW_DEBUG_HOST_TRIGGER = 4, |
| 267 | IWL_FW_TRIGGER_ID_FW_TRIGGER_INFO = 6, | 302 | IWL_FW_TRIGGER_ID_FW_GENERIC_NOTIFOCATION = 5, |
| 268 | IWL_FW_TRIGGER_ID_FW_TRIGGER_DEBUG = 7, | 303 | |
| 269 | /* User Trigger */ | 304 | /* User trigger */ |
| 270 | IWL_FW_TRIGGER_ID_USER_TRIGGER = 8, | 305 | IWL_FW_TRIGGER_ID_USER_TRIGGER = 6, |
| 306 | |||
| 271 | /* Host triggers */ | 307 | /* Host triggers */ |
| 272 | IWL_FW_TRIGGER_ID_HOST_PEER_CLIENT_INACTIVITY = 9, | 308 | IWL_FW_TRIGGER_ID_HOST_PEER_CLIENT_INACTIVITY = 7, |
| 273 | IWL_FW_TRIGGER_ID_HOST_DID_INITIATED_EVENT = 10, | 309 | IWL_FW_TRIGGER_ID_HOST_TX_LATENCY_THRESHOLD_CROSSED = 8, |
| 274 | IWL_FW_TRIGGER_ID_HOST_TX_LATENCY_THRESHOLD_CROSSED = 11, | 310 | IWL_FW_TRIGGER_ID_HOST_TX_RESPONSE_STATUS_FAILED = 9, |
| 275 | IWL_FW_TRIGGER_ID_HOST_TX_RESPONSE_STATUS_FAILED = 12, | 311 | IWL_FW_TRIGGER_ID_HOST_OS_REQ_DEAUTH_PEER = 10, |
| 276 | IWL_FW_TRIGGER_ID_HOST_OS_REQ_DEAUTH_PEER = 13, | 312 | IWL_FW_TRIGGER_ID_HOST_STOP_GO_REQUEST = 11, |
| 277 | IWL_FW_TRIGGER_ID_HOST_STOP_GO_REQUEST = 14, | 313 | IWL_FW_TRIGGER_ID_HOST_START_GO_REQUEST = 12, |
| 278 | IWL_FW_TRIGGER_ID_HOST_START_GO_REQUEST = 15, | 314 | IWL_FW_TRIGGER_ID_HOST_JOIN_GROUP_REQUEST = 13, |
| 279 | IWL_FW_TRIGGER_ID_HOST_JOIN_GROUP_REQUEST = 16, | 315 | IWL_FW_TRIGGER_ID_HOST_SCAN_START = 14, |
| 280 | IWL_FW_TRIGGER_ID_HOST_SCAN_START = 17, | 316 | IWL_FW_TRIGGER_ID_HOST_SCAN_SUBMITTED = 15, |
| 281 | IWL_FW_TRIGGER_ID_HOST_SCAN_SUBITTED = 18, | 317 | IWL_FW_TRIGGER_ID_HOST_SCAN_PARAMS = 16, |
| 282 | IWL_FW_TRIGGER_ID_HOST_SCAN_PARAMS = 19, | 318 | IWL_FW_TRIGGER_ID_HOST_CHECK_FOR_HANG = 17, |
| 283 | IWL_FW_TRIGGER_ID_HOST_CHECK_FOR_HANG = 20, | 319 | IWL_FW_TRIGGER_ID_HOST_BAR_RECEIVED = 18, |
| 284 | IWL_FW_TRIGGER_ID_HOST_BAR_RECEIVED = 21, | 320 | IWL_FW_TRIGGER_ID_HOST_AGG_TX_RESPONSE_STATUS_FAILED = 19, |
| 285 | IWL_FW_TRIGGER_ID_HOST_AGG_TX_RESPONSE_STATUS_FAILED = 22, | 321 | IWL_FW_TRIGGER_ID_HOST_EAPOL_TX_RESPONSE_FAILED = 20, |
| 286 | IWL_FW_TRIGGER_ID_HOST_EAPOL_TX_RESPONSE_FAILED = 23, | 322 | IWL_FW_TRIGGER_ID_HOST_FAKE_TX_RESPONSE_SUSPECTED = 21, |
| 287 | IWL_FW_TRIGGER_ID_HOST_FAKE_TX_RESPONSE_SUSPECTED = 24, | 323 | IWL_FW_TRIGGER_ID_HOST_AUTH_REQ_FROM_ASSOC_CLIENT = 22, |
| 288 | IWL_FW_TRIGGER_ID_HOST_AUTH_REQ_FROM_ASSOC_CLIENT = 25, | 324 | IWL_FW_TRIGGER_ID_HOST_ROAM_COMPLETE = 23, |
| 289 | IWL_FW_TRIGGER_ID_HOST_ROAM_COMPLETE = 26, | 325 | IWL_FW_TRIGGER_ID_HOST_AUTH_ASSOC_FAST_FAILED = 24, |
| 290 | IWL_FW_TRIGGER_ID_HOST_AUTH_ASSOC_FAST_FAILED = 27, | 326 | IWL_FW_TRIGGER_ID_HOST_D3_START = 25, |
| 291 | IWL_FW_TRIGGER_ID_HOST_D3_START = 28, | 327 | IWL_FW_TRIGGER_ID_HOST_D3_END = 26, |
| 292 | IWL_FW_TRIGGER_ID_HOST_D3_END = 29, | 328 | IWL_FW_TRIGGER_ID_HOST_BSS_MISSED_BEACONS = 27, |
| 293 | IWL_FW_TRIGGER_ID_HOST_BSS_MISSED_BEACONS = 30, | 329 | IWL_FW_TRIGGER_ID_HOST_P2P_CLIENT_MISSED_BEACONS = 28, |
| 294 | IWL_FW_TRIGGER_ID_HOST_P2P_CLIENT_MISSED_BEACONS = 31, | 330 | IWL_FW_TRIGGER_ID_HOST_PEER_CLIENT_TX_FAILURES = 29, |
| 295 | IWL_FW_TRIGGER_ID_HOST_PEER_CLIENT_TX_FAILURES = 32, | 331 | IWL_FW_TRIGGER_ID_HOST_TX_WFD_ACTION_FRAME_FAILED = 30, |
| 296 | IWL_FW_TRIGGER_ID_HOST_TX_WFD_ACTION_FRAME_FAILED = 33, | 332 | IWL_FW_TRIGGER_ID_HOST_AUTH_ASSOC_FAILED = 31, |
| 297 | IWL_FW_TRIGGER_ID_HOST_AUTH_ASSOC_FAILED = 34, | 333 | IWL_FW_TRIGGER_ID_HOST_SCAN_COMPLETE = 32, |
| 298 | IWL_FW_TRIGGER_ID_HOST_SCAN_COMPLETE = 35, | 334 | IWL_FW_TRIGGER_ID_HOST_SCAN_ABORT = 33, |
| 299 | IWL_FW_TRIGGER_ID_HOST_SCAN_ABORT = 36, | 335 | IWL_FW_TRIGGER_ID_HOST_NIC_ALIVE = 34, |
| 300 | IWL_FW_TRIGGER_ID_HOST_NIC_ALIVE = 37, | 336 | IWL_FW_TRIGGER_ID_HOST_CHANNEL_SWITCH_COMPLETE = 35, |
| 301 | IWL_FW_TRIGGER_ID_HOST_CHANNEL_SWITCH_COMPLETE = 38, | 337 | |
| 302 | IWL_FW_TRIGGER_ID_NUM, | 338 | IWL_FW_TRIGGER_ID_NUM, |
| 303 | }; /* FW_INI_TRIGGER_ID_E_VER_1 */ | 339 | }; /* FW_DEBUG_TLV_TRIGGER_ID_E_VER_1 */ |
| 304 | 340 | ||
| 305 | /** | 341 | /** |
| 306 | * enum iwl_fw_ini_apply_point | 342 | * enum iwl_fw_ini_apply_point |
| @@ -320,7 +356,7 @@ enum iwl_fw_ini_apply_point { | |||
| 320 | IWL_FW_INI_APPLY_MISSED_BEACONS, | 356 | IWL_FW_INI_APPLY_MISSED_BEACONS, |
| 321 | IWL_FW_INI_APPLY_SCAN_COMPLETE, | 357 | IWL_FW_INI_APPLY_SCAN_COMPLETE, |
| 322 | IWL_FW_INI_APPLY_NUM, | 358 | IWL_FW_INI_APPLY_NUM, |
| 323 | }; /* FW_INI_APPLY_POINT_E_VER_1 */ | 359 | }; /* FW_DEBUG_TLV_APPLY_POINT_E_VER_1 */ |
| 324 | 360 | ||
| 325 | /** | 361 | /** |
| 326 | * enum iwl_fw_ini_allocation_id | 362 | * enum iwl_fw_ini_allocation_id |
| @@ -340,7 +376,7 @@ enum iwl_fw_ini_allocation_id { | |||
| 340 | IWL_FW_INI_ALLOCATION_ID_SDFX, | 376 | IWL_FW_INI_ALLOCATION_ID_SDFX, |
| 341 | IWL_FW_INI_ALLOCATION_ID_FW_DUMP, | 377 | IWL_FW_INI_ALLOCATION_ID_FW_DUMP, |
| 342 | IWL_FW_INI_ALLOCATION_ID_USER_DEFINED, | 378 | IWL_FW_INI_ALLOCATION_ID_USER_DEFINED, |
| 343 | }; /* FW_INI_ALLOCATION_ID_E_VER_1 */ | 379 | }; /* FW_DEBUG_TLV_ALLOCATION_ID_E_VER_1 */ |
| 344 | 380 | ||
| 345 | /** | 381 | /** |
| 346 | * enum iwl_fw_ini_buffer_location | 382 | * enum iwl_fw_ini_buffer_location |
| @@ -349,10 +385,10 @@ enum iwl_fw_ini_allocation_id { | |||
| 349 | * @IWL_FW_INI_LOCATION_DRAM_PATH: DRAM location | 385 | * @IWL_FW_INI_LOCATION_DRAM_PATH: DRAM location |
| 350 | */ | 386 | */ |
| 351 | enum iwl_fw_ini_buffer_location { | 387 | enum iwl_fw_ini_buffer_location { |
| 352 | IWL_FW_INI_LOCATION_SRAM_INVALID, | 388 | IWL_FW_INI_LOCATION_INVALID, |
| 353 | IWL_FW_INI_LOCATION_SRAM_PATH, | 389 | IWL_FW_INI_LOCATION_SRAM_PATH, |
| 354 | IWL_FW_INI_LOCATION_DRAM_PATH, | 390 | IWL_FW_INI_LOCATION_DRAM_PATH, |
| 355 | }; /* FW_INI_BUFFER_LOCATION_E_VER_1 */ | 391 | }; /* FW_DEBUG_TLV_BUFFER_LOCATION_E_VER_1 */ |
| 356 | 392 | ||
| 357 | /** | 393 | /** |
| 358 | * enum iwl_fw_ini_debug_flow | 394 | * enum iwl_fw_ini_debug_flow |
| @@ -364,7 +400,7 @@ enum iwl_fw_ini_debug_flow { | |||
| 364 | IWL_FW_INI_DEBUG_INVALID, | 400 | IWL_FW_INI_DEBUG_INVALID, |
| 365 | IWL_FW_INI_DEBUG_DBTR_FLOW, | 401 | IWL_FW_INI_DEBUG_DBTR_FLOW, |
| 366 | IWL_FW_INI_DEBUG_TB2DTF_FLOW, | 402 | IWL_FW_INI_DEBUG_TB2DTF_FLOW, |
| 367 | }; /* FW_INI_DEBUG_FLOW_E_VER_1 */ | 403 | }; /* FW_DEBUG_TLV_FLOW_E_VER_1 */ |
| 368 | 404 | ||
| 369 | /** | 405 | /** |
| 370 | * enum iwl_fw_ini_region_type | 406 | * enum iwl_fw_ini_region_type |
| @@ -396,6 +432,6 @@ enum iwl_fw_ini_region_type { | |||
| 396 | IWL_FW_INI_REGION_PAGING, | 432 | IWL_FW_INI_REGION_PAGING, |
| 397 | IWL_FW_INI_REGION_CSR, | 433 | IWL_FW_INI_REGION_CSR, |
| 398 | IWL_FW_INI_REGION_NUM | 434 | IWL_FW_INI_REGION_NUM |
| 399 | }; /* FW_INI_REGION_TYPE_E_VER_1*/ | 435 | }; /* FW_DEBUG_TLV_REGION_TYPE_E_VER_1 */ |
| 400 | 436 | ||
| 401 | #endif | 437 | #endif |
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/location.h b/drivers/net/wireless/intel/iwlwifi/fw/api/location.h index 6da91ec0df55..5dddb21c1c4d 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/location.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/location.h | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2015 - 2017 Intel Deutschland GmbH | 8 | * Copyright(c) 2015 - 2017 Intel Deutschland GmbH |
| 9 | * Copyright (C) 2018 Intel Corporation | 9 | * Copyright (C) 2018 Intel Corporation |
| 10 | * Copyright (C) 2019 Intel Corporation | ||
| 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 |
| @@ -28,6 +29,7 @@ | |||
| 28 | * | 29 | * |
| 29 | * Copyright(c) 2015 - 2017 Intel Deutschland GmbH | 30 | * Copyright(c) 2015 - 2017 Intel Deutschland GmbH |
| 30 | * Copyright (C) 2018 Intel Corporation | 31 | * Copyright (C) 2018 Intel Corporation |
| 32 | * Copyright (C) 2019 Intel Corporation | ||
| 31 | * All rights reserved. | 33 | * All rights reserved. |
| 32 | * | 34 | * |
| 33 | * Redistribution and use in source and binary forms, with or without | 35 | * Redistribution and use in source and binary forms, with or without |
| @@ -322,7 +324,7 @@ enum iwl_tof_location_query { | |||
| 322 | }; | 324 | }; |
| 323 | 325 | ||
| 324 | /** | 326 | /** |
| 325 | * struct iwl_tof_range_req_ap_entry - AP configuration parameters | 327 | * struct iwl_tof_range_req_ap_entry_v2 - AP configuration parameters |
| 326 | * @channel_num: Current AP Channel | 328 | * @channel_num: Current AP Channel |
| 327 | * @bandwidth: Current AP Bandwidth. One of iwl_tof_bandwidth. | 329 | * @bandwidth: Current AP Bandwidth. One of iwl_tof_bandwidth. |
| 328 | * @tsf_delta_direction: TSF relatively to the subject AP | 330 | * @tsf_delta_direction: TSF relatively to the subject AP |
| @@ -355,7 +357,7 @@ enum iwl_tof_location_query { | |||
| 355 | * @notify_mcsi: &enum iwl_tof_mcsi_ntfy. | 357 | * @notify_mcsi: &enum iwl_tof_mcsi_ntfy. |
| 356 | * @reserved: For alignment and future use | 358 | * @reserved: For alignment and future use |
| 357 | */ | 359 | */ |
| 358 | struct iwl_tof_range_req_ap_entry { | 360 | struct iwl_tof_range_req_ap_entry_v2 { |
| 359 | u8 channel_num; | 361 | u8 channel_num; |
| 360 | u8 bandwidth; | 362 | u8 bandwidth; |
| 361 | u8 tsf_delta_direction; | 363 | u8 tsf_delta_direction; |
| @@ -374,6 +376,62 @@ struct iwl_tof_range_req_ap_entry { | |||
| 374 | u8 algo_type; | 376 | u8 algo_type; |
| 375 | u8 notify_mcsi; | 377 | u8 notify_mcsi; |
| 376 | __le16 reserved; | 378 | __le16 reserved; |
| 379 | } __packed; /* LOCATION_RANGE_REQ_AP_ENTRY_CMD_API_S_VER_2 */ | ||
| 380 | |||
| 381 | /** | ||
| 382 | * enum iwl_initiator_ap_flags - per responder FTM configuration flags | ||
| 383 | * @IWL_INITIATOR_AP_FLAGS_ASAP: Request for ASAP measurement. | ||
| 384 | * @IWL_INITIATOR_AP_FLAGS_LCI_REQUEST: Request for LCI information | ||
| 385 | * @IWL_INITIATOR_AP_FLAGS_CIVIC_REQUEST: Request for CIVIC information | ||
| 386 | * @IWL_INITIATOR_AP_FLAGS_DYN_ACK: Send HT/VHT ack for FTM frames. If not set, | ||
| 387 | * 20Mhz dup acks will be sent. | ||
| 388 | * @IWL_INITIATOR_AP_FLAGS_ALGO_LR: Use LR algo type for rtt calculation. | ||
| 389 | * Default algo type is ML. | ||
| 390 | * @IWL_INITIATOR_AP_FLAGS_ALGO_FFT: Use FFT algo type for rtt calculation. | ||
| 391 | * Default algo type is ML. | ||
| 392 | * @IWL_INITIATOR_AP_FLAGS_MCSI_REPORT: Send the MCSI for each FTM frame to the | ||
| 393 | * driver. | ||
| 394 | */ | ||
| 395 | enum iwl_initiator_ap_flags { | ||
| 396 | IWL_INITIATOR_AP_FLAGS_ASAP = BIT(1), | ||
| 397 | IWL_INITIATOR_AP_FLAGS_LCI_REQUEST = BIT(2), | ||
| 398 | IWL_INITIATOR_AP_FLAGS_CIVIC_REQUEST = BIT(3), | ||
| 399 | IWL_INITIATOR_AP_FLAGS_DYN_ACK = BIT(4), | ||
| 400 | IWL_INITIATOR_AP_FLAGS_ALGO_LR = BIT(5), | ||
| 401 | IWL_INITIATOR_AP_FLAGS_ALGO_FFT = BIT(6), | ||
| 402 | IWL_INITIATOR_AP_FLAGS_MCSI_REPORT = BIT(8), | ||
| 403 | }; | ||
| 404 | |||
| 405 | /** | ||
| 406 | * struct iwl_tof_range_req_ap_entry - AP configuration parameters | ||
| 407 | * @initiator_ap_flags: see &enum iwl_initiator_ap_flags. | ||
| 408 | * @channel_num: AP Channel number | ||
| 409 | * @bandwidth: AP bandwidth. One of iwl_tof_bandwidth. | ||
| 410 | * @ctrl_ch_position: Coding of the control channel position relative to the | ||
| 411 | * center frequency, see iwl_mvm_get_ctrl_pos(). | ||
| 412 | * @ftmr_max_retries: Max number of retries to send the FTMR in case of no | ||
| 413 | * reply from the AP. | ||
| 414 | * @bssid: AP's BSSID | ||
| 415 | * @burst_period: Recommended value to be sent to the AP. Measurement | ||
| 416 | * periodicity In units of 100ms. ignored if num_of_bursts_exp = 0 | ||
| 417 | * @samples_per_burst: the number of FTMs pairs in single Burst (1-31); | ||
| 418 | * @num_of_bursts: Recommended value to be sent to the AP. 2s Exponent of | ||
| 419 | * the number of measurement iterations (min 2^0 = 1, max 2^14) | ||
| 420 | * @reserved: For alignment and future use | ||
| 421 | * @tsf_delta: not in use | ||
| 422 | */ | ||
| 423 | struct iwl_tof_range_req_ap_entry { | ||
| 424 | __le32 initiator_ap_flags; | ||
| 425 | u8 channel_num; | ||
| 426 | u8 bandwidth; | ||
| 427 | u8 ctrl_ch_position; | ||
| 428 | u8 ftmr_max_retries; | ||
| 429 | u8 bssid[ETH_ALEN]; | ||
| 430 | __le16 burst_period; | ||
| 431 | u8 samples_per_burst; | ||
| 432 | u8 num_of_bursts; | ||
| 433 | __le16 reserved; | ||
| 434 | __le32 tsf_delta; | ||
| 377 | } __packed; /* LOCATION_RANGE_REQ_AP_ENTRY_CMD_API_S_VER_3 */ | 435 | } __packed; /* LOCATION_RANGE_REQ_AP_ENTRY_CMD_API_S_VER_3 */ |
| 378 | 436 | ||
| 379 | /** | 437 | /** |
| @@ -403,7 +461,12 @@ enum iwl_tof_response_mode { | |||
| 403 | * @IWL_TOF_INITIATOR_FLAGS_TX_CHAIN_SEL_A: use antenna A fo TX ACKs during FTM | 461 | * @IWL_TOF_INITIATOR_FLAGS_TX_CHAIN_SEL_A: use antenna A fo TX ACKs during FTM |
| 404 | * @IWL_TOF_INITIATOR_FLAGS_TX_CHAIN_SEL_B: use antenna B fo TX ACKs during FTM | 462 | * @IWL_TOF_INITIATOR_FLAGS_TX_CHAIN_SEL_B: use antenna B fo TX ACKs during FTM |
| 405 | * @IWL_TOF_INITIATOR_FLAGS_TX_CHAIN_SEL_C: use antenna C fo TX ACKs during FTM | 463 | * @IWL_TOF_INITIATOR_FLAGS_TX_CHAIN_SEL_C: use antenna C fo TX ACKs during FTM |
| 406 | * @IWL_TOF_INITIATOR_FLAGS_MINDELTA_NO_PREF: no preference for minDeltaFTM | 464 | * @IWL_TOF_INITIATOR_FLAGS_MACADDR_RANDOM: use random mac address for FTM |
| 465 | * @IWL_TOF_INITIATOR_FLAGS_SPECIFIC_CALIB: use the specific calib value from | ||
| 466 | * the range request command | ||
| 467 | * @IWL_TOF_INITIATOR_FLAGS_COMMON_CALIB: use the common calib value from the | ||
| 468 | * ragne request command | ||
| 469 | * @IWL_TOF_INITIATOR_FLAGS_NON_ASAP_SUPPORT: support non-asap measurements | ||
| 407 | */ | 470 | */ |
| 408 | enum iwl_tof_initiator_flags { | 471 | enum iwl_tof_initiator_flags { |
| 409 | IWL_TOF_INITIATOR_FLAGS_FAST_ALGO_DISABLED = BIT(0), | 472 | IWL_TOF_INITIATOR_FLAGS_FAST_ALGO_DISABLED = BIT(0), |
| @@ -413,14 +476,17 @@ enum iwl_tof_initiator_flags { | |||
| 413 | IWL_TOF_INITIATOR_FLAGS_TX_CHAIN_SEL_A = BIT(4), | 476 | IWL_TOF_INITIATOR_FLAGS_TX_CHAIN_SEL_A = BIT(4), |
| 414 | IWL_TOF_INITIATOR_FLAGS_TX_CHAIN_SEL_B = BIT(5), | 477 | IWL_TOF_INITIATOR_FLAGS_TX_CHAIN_SEL_B = BIT(5), |
| 415 | IWL_TOF_INITIATOR_FLAGS_TX_CHAIN_SEL_C = BIT(6), | 478 | IWL_TOF_INITIATOR_FLAGS_TX_CHAIN_SEL_C = BIT(6), |
| 416 | IWL_TOF_INITIATOR_FLAGS_MINDELTA_NO_PREF = BIT(7), | 479 | IWL_TOF_INITIATOR_FLAGS_MACADDR_RANDOM = BIT(7), |
| 480 | IWL_TOF_INITIATOR_FLAGS_SPECIFIC_CALIB = BIT(15), | ||
| 481 | IWL_TOF_INITIATOR_FLAGS_COMMON_CALIB = BIT(16), | ||
| 482 | IWL_TOF_INITIATOR_FLAGS_NON_ASAP_SUPPORT = BIT(20), | ||
| 417 | }; /* LOCATION_RANGE_REQ_CMD_API_S_VER_5 */ | 483 | }; /* LOCATION_RANGE_REQ_CMD_API_S_VER_5 */ |
| 418 | 484 | ||
| 419 | #define IWL_MVM_TOF_MAX_APS 5 | 485 | #define IWL_MVM_TOF_MAX_APS 5 |
| 420 | #define IWL_MVM_TOF_MAX_TWO_SIDED_APS 5 | 486 | #define IWL_MVM_TOF_MAX_TWO_SIDED_APS 5 |
| 421 | 487 | ||
| 422 | /** | 488 | /** |
| 423 | * struct iwl_tof_range_req_cmd - start measurement cmd | 489 | * struct iwl_tof_range_req_cmd_v5 - start measurement cmd |
| 424 | * @initiator_flags: see flags @ iwl_tof_initiator_flags | 490 | * @initiator_flags: see flags @ iwl_tof_initiator_flags |
| 425 | * @request_id: A Token incremented per request. The same Token will be | 491 | * @request_id: A Token incremented per request. The same Token will be |
| 426 | * sent back in the range response | 492 | * sent back in the range response |
| @@ -448,7 +514,7 @@ enum iwl_tof_initiator_flags { | |||
| 448 | * @specific_calib: The specific calib value to inject to this measurement calc | 514 | * @specific_calib: The specific calib value to inject to this measurement calc |
| 449 | * @ap: per-AP request data | 515 | * @ap: per-AP request data |
| 450 | */ | 516 | */ |
| 451 | struct iwl_tof_range_req_cmd { | 517 | struct iwl_tof_range_req_cmd_v5 { |
| 452 | __le32 initiator_flags; | 518 | __le32 initiator_flags; |
| 453 | u8 request_id; | 519 | u8 request_id; |
| 454 | u8 initiator; | 520 | u8 initiator; |
| @@ -465,10 +531,42 @@ struct iwl_tof_range_req_cmd { | |||
| 465 | u8 ftm_tx_chains; | 531 | u8 ftm_tx_chains; |
| 466 | __le16 common_calib; | 532 | __le16 common_calib; |
| 467 | __le16 specific_calib; | 533 | __le16 specific_calib; |
| 468 | struct iwl_tof_range_req_ap_entry ap[IWL_MVM_TOF_MAX_APS]; | 534 | struct iwl_tof_range_req_ap_entry_v2 ap[IWL_MVM_TOF_MAX_APS]; |
| 469 | } __packed; | 535 | } __packed; |
| 470 | /* LOCATION_RANGE_REQ_CMD_API_S_VER_5 */ | 536 | /* LOCATION_RANGE_REQ_CMD_API_S_VER_5 */ |
| 471 | 537 | ||
| 538 | /** | ||
| 539 | * struct iwl_tof_range_req_cmd - start measurement cmd | ||
| 540 | * @initiator_flags: see flags @ iwl_tof_initiator_flags | ||
| 541 | * @request_id: A Token incremented per request. The same Token will be | ||
| 542 | * sent back in the range response | ||
| 543 | * @num_of_ap: Number of APs to measure (error if > IWL_MVM_TOF_MAX_APS) | ||
| 544 | * @range_req_bssid: ranging request BSSID | ||
| 545 | * @macaddr_mask: Bits set to 0 shall be copied from the MAC address template. | ||
| 546 | * Bits set to 1 shall be randomized by the UMAC | ||
| 547 | * @macaddr_template: MAC address template to use for non-randomized bits | ||
| 548 | * @req_timeout_ms: Requested timeout of the response in units of milliseconds. | ||
| 549 | * This is the session time for completing the measurement. | ||
| 550 | * @tsf_mac_id: report the measurement start time for each ap in terms of the | ||
| 551 | * TSF of this mac id. 0xff to disable TSF reporting. | ||
| 552 | * @common_calib: The common calib value to inject to this measurement calc | ||
| 553 | * @specific_calib: The specific calib value to inject to this measurement calc | ||
| 554 | * @ap: per-AP request data, see &struct iwl_tof_range_req_ap_entry_v2. | ||
| 555 | */ | ||
| 556 | struct iwl_tof_range_req_cmd { | ||
| 557 | __le32 initiator_flags; | ||
| 558 | u8 request_id; | ||
| 559 | u8 num_of_ap; | ||
| 560 | u8 range_req_bssid[ETH_ALEN]; | ||
| 561 | u8 macaddr_mask[ETH_ALEN]; | ||
| 562 | u8 macaddr_template[ETH_ALEN]; | ||
| 563 | __le32 req_timeout_ms; | ||
| 564 | __le32 tsf_mac_id; | ||
| 565 | __le16 common_calib; | ||
| 566 | __le16 specific_calib; | ||
| 567 | struct iwl_tof_range_req_ap_entry ap[IWL_MVM_TOF_MAX_APS]; | ||
| 568 | } __packed; /* LOCATION_RANGE_REQ_CMD_API_S_VER_7 */ | ||
| 569 | |||
| 472 | /* | 570 | /* |
| 473 | * enum iwl_tof_range_request_status - status of the sent request | 571 | * enum iwl_tof_range_request_status - status of the sent request |
| 474 | * @IWL_TOF_RANGE_REQUEST_STATUS_SUCCESSFUL - FW successfully received the | 572 | * @IWL_TOF_RANGE_REQUEST_STATUS_SUCCESSFUL - FW successfully received the |
| @@ -528,7 +626,7 @@ enum iwl_tof_entry_status { | |||
| 528 | }; /* LOCATION_RANGE_RSP_AP_ENTRY_NTFY_API_S_VER_2 */ | 626 | }; /* LOCATION_RANGE_RSP_AP_ENTRY_NTFY_API_S_VER_2 */ |
| 529 | 627 | ||
| 530 | /** | 628 | /** |
| 531 | * struct iwl_tof_range_rsp_ap_entry_ntfy - AP parameters (response) | 629 | * struct iwl_tof_range_rsp_ap_entry_ntfy_v3 - AP parameters (response) |
| 532 | * @bssid: BSSID of the AP | 630 | * @bssid: BSSID of the AP |
| 533 | * @measure_status: current APs measurement status, one of | 631 | * @measure_status: current APs measurement status, one of |
| 534 | * &enum iwl_tof_entry_status. | 632 | * &enum iwl_tof_entry_status. |
| @@ -555,7 +653,7 @@ enum iwl_tof_entry_status { | |||
| 555 | * @papd_calib_output: The result of the tof papd calibration that was injected | 653 | * @papd_calib_output: The result of the tof papd calibration that was injected |
| 556 | * into the algorithm. | 654 | * into the algorithm. |
| 557 | */ | 655 | */ |
| 558 | struct iwl_tof_range_rsp_ap_entry_ntfy { | 656 | struct iwl_tof_range_rsp_ap_entry_ntfy_v3 { |
| 559 | u8 bssid[ETH_ALEN]; | 657 | u8 bssid[ETH_ALEN]; |
| 560 | u8 measure_status; | 658 | u8 measure_status; |
| 561 | u8 measure_bw; | 659 | u8 measure_bw; |
| @@ -577,6 +675,59 @@ struct iwl_tof_range_rsp_ap_entry_ntfy { | |||
| 577 | } __packed; /* LOCATION_RANGE_RSP_AP_ETRY_NTFY_API_S_VER_3 */ | 675 | } __packed; /* LOCATION_RANGE_RSP_AP_ETRY_NTFY_API_S_VER_3 */ |
| 578 | 676 | ||
| 579 | /** | 677 | /** |
| 678 | * struct iwl_tof_range_rsp_ap_entry_ntfy - AP parameters (response) | ||
| 679 | * @bssid: BSSID of the AP | ||
| 680 | * @measure_status: current APs measurement status, one of | ||
| 681 | * &enum iwl_tof_entry_status. | ||
| 682 | * @measure_bw: Current AP Bandwidth: 0 20MHz, 1 40MHz, 2 80MHz | ||
| 683 | * @rtt: The Round Trip Time that took for the last measurement for | ||
| 684 | * current AP [pSec] | ||
| 685 | * @rtt_variance: The Variance of the RTT values measured for current AP | ||
| 686 | * @rtt_spread: The Difference between the maximum and the minimum RTT | ||
| 687 | * values measured for current AP in the current session [pSec] | ||
| 688 | * @rssi: RSSI as uploaded in the Channel Estimation notification | ||
| 689 | * @rssi_spread: The Difference between the maximum and the minimum RSSI values | ||
| 690 | * measured for current AP in the current session | ||
| 691 | * @last_burst: 1 if no more FTM sessions are scheduled for this responder | ||
| 692 | * @refusal_period: refusal period in case of | ||
| 693 | * @IWL_TOF_ENTRY_RESPONDER_CANNOT_COLABORATE [sec] | ||
| 694 | * @timestamp: The GP2 Clock [usec] where Channel Estimation notification was | ||
| 695 | * uploaded by the LMAC | ||
| 696 | * @start_tsf: measurement start time in TSF of the mac specified in the range | ||
| 697 | * request | ||
| 698 | * @rx_rate_n_flags: rate and flags of the last FTM frame received from this | ||
| 699 | * responder | ||
| 700 | * @tx_rate_n_flags: rate and flags of the last ack sent to this responder | ||
| 701 | * @t2t3_initiator: as calculated from the algo in the initiator | ||
| 702 | * @t1t4_responder: as calculated from the algo in the responder | ||
| 703 | * @common_calib: Calib val that was used in for this AP measurement | ||
| 704 | * @specific_calib: val that was used in for this AP measurement | ||
| 705 | * @papd_calib_output: The result of the tof papd calibration that was injected | ||
| 706 | * into the algorithm. | ||
| 707 | */ | ||
| 708 | struct iwl_tof_range_rsp_ap_entry_ntfy { | ||
| 709 | u8 bssid[ETH_ALEN]; | ||
| 710 | u8 measure_status; | ||
| 711 | u8 measure_bw; | ||
| 712 | __le32 rtt; | ||
| 713 | __le32 rtt_variance; | ||
| 714 | __le32 rtt_spread; | ||
| 715 | s8 rssi; | ||
| 716 | u8 rssi_spread; | ||
| 717 | u8 last_burst; | ||
| 718 | u8 refusal_period; | ||
| 719 | __le32 timestamp; | ||
| 720 | __le32 start_tsf; | ||
| 721 | __le32 rx_rate_n_flags; | ||
| 722 | __le32 tx_rate_n_flags; | ||
| 723 | __le32 t2t3_initiator; | ||
| 724 | __le32 t1t4_responder; | ||
| 725 | __le16 common_calib; | ||
| 726 | __le16 specific_calib; | ||
| 727 | __le32 papd_calib_output; | ||
| 728 | } __packed; /* LOCATION_RANGE_RSP_AP_ETRY_NTFY_API_S_VER_4 */ | ||
| 729 | |||
| 730 | /** | ||
| 580 | * enum iwl_tof_response_status - tof response status | 731 | * enum iwl_tof_response_status - tof response status |
| 581 | * | 732 | * |
| 582 | * @IWL_TOF_RESPONSE_SUCCESS: successful range. | 733 | * @IWL_TOF_RESPONSE_SUCCESS: successful range. |
| @@ -593,7 +744,7 @@ enum iwl_tof_response_status { | |||
| 593 | }; /* LOCATION_RNG_RSP_STATUS */ | 744 | }; /* LOCATION_RNG_RSP_STATUS */ |
| 594 | 745 | ||
| 595 | /** | 746 | /** |
| 596 | * struct iwl_tof_range_rsp_ntfy - ranging response notification | 747 | * struct iwl_tof_range_rsp_ntfy_v5 - ranging response notification |
| 597 | * @request_id: A Token ID of the corresponding Range request | 748 | * @request_id: A Token ID of the corresponding Range request |
| 598 | * @request_status: status of current measurement session, one of | 749 | * @request_status: status of current measurement session, one of |
| 599 | * &enum iwl_tof_response_status. | 750 | * &enum iwl_tof_response_status. |
| @@ -601,13 +752,29 @@ enum iwl_tof_response_status { | |||
| 601 | * @num_of_aps: Number of APs to measure (error if > IWL_MVM_TOF_MAX_APS) | 752 | * @num_of_aps: Number of APs to measure (error if > IWL_MVM_TOF_MAX_APS) |
| 602 | * @ap: per-AP data | 753 | * @ap: per-AP data |
| 603 | */ | 754 | */ |
| 604 | struct iwl_tof_range_rsp_ntfy { | 755 | struct iwl_tof_range_rsp_ntfy_v5 { |
| 605 | u8 request_id; | 756 | u8 request_id; |
| 606 | u8 request_status; | 757 | u8 request_status; |
| 607 | u8 last_in_batch; | 758 | u8 last_in_batch; |
| 608 | u8 num_of_aps; | 759 | u8 num_of_aps; |
| 760 | struct iwl_tof_range_rsp_ap_entry_ntfy_v3 ap[IWL_MVM_TOF_MAX_APS]; | ||
| 761 | } __packed; /* LOCATION_RANGE_RSP_NTFY_API_S_VER_5 */ | ||
| 762 | |||
| 763 | /** | ||
| 764 | * struct iwl_tof_range_rsp_ntfy - ranging response notification | ||
| 765 | * @request_id: A Token ID of the corresponding Range request | ||
| 766 | * @num_of_aps: Number of APs results | ||
| 767 | * @last_report: 1 if no more FTM sessions are scheduled, 0 otherwise. | ||
| 768 | * @reserved: reserved | ||
| 769 | * @ap: per-AP data | ||
| 770 | */ | ||
| 771 | struct iwl_tof_range_rsp_ntfy { | ||
| 772 | u8 request_id; | ||
| 773 | u8 num_of_aps; | ||
| 774 | u8 last_report; | ||
| 775 | u8 reserved; | ||
| 609 | struct iwl_tof_range_rsp_ap_entry_ntfy ap[IWL_MVM_TOF_MAX_APS]; | 776 | struct iwl_tof_range_rsp_ap_entry_ntfy ap[IWL_MVM_TOF_MAX_APS]; |
| 610 | } __packed; | 777 | } __packed; /* LOCATION_RANGE_RSP_NTFY_API_S_VER_6 */ |
| 611 | 778 | ||
| 612 | #define IWL_MVM_TOF_MCSI_BUF_SIZE (245) | 779 | #define IWL_MVM_TOF_MCSI_BUF_SIZE (245) |
| 613 | /** | 780 | /** |
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h index ca49db786ed6..6b4d59daacd6 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h | |||
| @@ -74,6 +74,10 @@ enum iwl_mac_conf_subcmd_ids { | |||
| 74 | */ | 74 | */ |
| 75 | LOW_LATENCY_CMD = 0x3, | 75 | LOW_LATENCY_CMD = 0x3, |
| 76 | /** | 76 | /** |
| 77 | * @CHANNEL_SWITCH_TIME_EVENT_CMD: &struct iwl_chan_switch_te_cmd | ||
| 78 | */ | ||
| 79 | CHANNEL_SWITCH_TIME_EVENT_CMD = 0x4, | ||
| 80 | /** | ||
| 77 | * @PROBE_RESPONSE_DATA_NOTIF: &struct iwl_probe_resp_data_notif | 81 | * @PROBE_RESPONSE_DATA_NOTIF: &struct iwl_probe_resp_data_notif |
| 78 | */ | 82 | */ |
| 79 | PROBE_RESPONSE_DATA_NOTIF = 0xFC, | 83 | PROBE_RESPONSE_DATA_NOTIF = 0xFC, |
| @@ -136,6 +140,29 @@ struct iwl_channel_switch_noa_notif { | |||
| 136 | } __packed; /* CHANNEL_SWITCH_START_NTFY_API_S_VER_1 */ | 140 | } __packed; /* CHANNEL_SWITCH_START_NTFY_API_S_VER_1 */ |
| 137 | 141 | ||
| 138 | /** | 142 | /** |
| 143 | * struct iwl_chan_switch_te_cmd - Channel Switch Time Event command | ||
| 144 | * | ||
| 145 | * @mac_id: MAC ID for channel switch | ||
| 146 | * @action: action to perform, one of FW_CTXT_ACTION_* | ||
| 147 | * @tsf: beacon tsf | ||
| 148 | * @cs_count: channel switch count from CSA/eCSA IE | ||
| 149 | * @cs_delayed_bcn_count: if set to N (!= 0) GO/AP can delay N beacon intervals | ||
| 150 | * at the new channel after the channel switch, otherwise (N == 0) expect | ||
| 151 | * beacon right after the channel switch. | ||
| 152 | * @cs_mode: 1 - quiet, 0 - otherwise | ||
| 153 | * @reserved: reserved for alignment purposes | ||
| 154 | */ | ||
| 155 | struct iwl_chan_switch_te_cmd { | ||
| 156 | __le32 mac_id; | ||
| 157 | __le32 action; | ||
| 158 | __le32 tsf; | ||
| 159 | u8 cs_count; | ||
| 160 | u8 cs_delayed_bcn_count; | ||
| 161 | u8 cs_mode; | ||
| 162 | u8 reserved; | ||
| 163 | } __packed; /* MAC_CHANNEL_SWITCH_TIME_EVENT_S_VER_2 */ | ||
| 164 | |||
| 165 | /** | ||
| 139 | * struct iwl_mac_low_latency_cmd - set/clear mac to 'low-latency mode' | 166 | * struct iwl_mac_low_latency_cmd - set/clear mac to 'low-latency mode' |
| 140 | * | 167 | * |
| 141 | * @mac_id: MAC ID to whom to apply the low-latency configurations | 168 | * @mac_id: MAC ID to whom to apply the low-latency configurations |
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/power.h b/drivers/net/wireless/intel/iwlwifi/fw/api/power.h index 286a22da232d..01f003c6cff9 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/power.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/power.h | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 9 | * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH | 9 | * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH |
| 10 | * Copyright(c) 2015 - 2017 Intel Deutschland GmbH | 10 | * Copyright(c) 2015 - 2017 Intel Deutschland GmbH |
| 11 | * Copyright (C) 2018 Intel Corporation | 11 | * Copyright (C) 2018 - 2019 Intel Corporation |
| 12 | * | 12 | * |
| 13 | * This program is free software; you can redistribute it and/or modify | 13 | * This program is free software; you can redistribute it and/or modify |
| 14 | * it under the terms of version 2 of the GNU General Public License as | 14 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -31,7 +31,7 @@ | |||
| 31 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. | 31 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 32 | * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH | 32 | * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH |
| 33 | * Copyright(c) 2015 - 2017 Intel Deutschland GmbH | 33 | * Copyright(c) 2015 - 2017 Intel Deutschland GmbH |
| 34 | * Copyright (C) 2018 Intel Corporation | 34 | * Copyright (C) 2018 - 2019 Intel Corporation |
| 35 | * All rights reserved. | 35 | * All rights reserved. |
| 36 | * | 36 | * |
| 37 | * Redistribution and use in source and binary forms, with or without | 37 | * Redistribution and use in source and binary forms, with or without |
| @@ -200,9 +200,16 @@ struct iwl_powertable_cmd { | |||
| 200 | * @DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK: | 200 | * @DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK: |
| 201 | * '1' Allow to save power by turning off | 201 | * '1' Allow to save power by turning off |
| 202 | * receiver and transmitter. '0' - does not allow. | 202 | * receiver and transmitter. '0' - does not allow. |
| 203 | * @DEVICE_POWER_FLAGS_ALLOW_MEM_RETENTION_MSK: | ||
| 204 | * Device Retention indication, '1' indicate retention is enabled. | ||
| 205 | * @DEVICE_POWER_FLAGS_32K_CLK_VALID_MSK: | ||
| 206 | * 32Khz external slow clock valid indication, '1' indicate cloack is | ||
| 207 | * valid. | ||
| 203 | */ | 208 | */ |
| 204 | enum iwl_device_power_flags { | 209 | enum iwl_device_power_flags { |
| 205 | DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK = BIT(0), | 210 | DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK = BIT(0), |
| 211 | DEVICE_POWER_FLAGS_ALLOW_MEM_RETENTION_MSK = BIT(1), | ||
| 212 | DEVICE_POWER_FLAGS_32K_CLK_VALID_MSK = BIT(12), | ||
| 206 | }; | 213 | }; |
| 207 | 214 | ||
| 208 | /** | 215 | /** |
| @@ -470,6 +477,13 @@ struct iwl_geo_tx_power_profiles_resp { | |||
| 470 | * @ba_escape_timer: Fully receive and parse beacon if no beacons were passed | 477 | * @ba_escape_timer: Fully receive and parse beacon if no beacons were passed |
| 471 | * for a longer period of time then this escape-timeout. Units: Beacons. | 478 | * for a longer period of time then this escape-timeout. Units: Beacons. |
| 472 | * @ba_enable_beacon_abort: 1, beacon abort is enabled; 0, disabled. | 479 | * @ba_enable_beacon_abort: 1, beacon abort is enabled; 0, disabled. |
| 480 | * @bf_threshold_absolute_low: See below. | ||
| 481 | * @bf_threshold_absolute_high: Send Beacon to driver if Energy value calculated | ||
| 482 | * for this beacon crossed this absolute threshold. For the 'Increase' | ||
| 483 | * direction the bf_energy_absolute_low[i] is used. For the 'Decrease' | ||
| 484 | * direction the bf_energy_absolute_high[i] is used. Zero value means | ||
| 485 | * that this specific threshold is ignored for beacon filtering, and | ||
| 486 | * beacon will not be forced to be sent to driver due to this setting. | ||
| 473 | */ | 487 | */ |
| 474 | struct iwl_beacon_filter_cmd { | 488 | struct iwl_beacon_filter_cmd { |
| 475 | __le32 bf_energy_delta; | 489 | __le32 bf_energy_delta; |
| @@ -483,7 +497,9 @@ struct iwl_beacon_filter_cmd { | |||
| 483 | __le32 bf_escape_timer; | 497 | __le32 bf_escape_timer; |
| 484 | __le32 ba_escape_timer; | 498 | __le32 ba_escape_timer; |
| 485 | __le32 ba_enable_beacon_abort; | 499 | __le32 ba_enable_beacon_abort; |
| 486 | } __packed; | 500 | __le32 bf_threshold_absolute_low[2]; |
| 501 | __le32 bf_threshold_absolute_high[2]; | ||
| 502 | } __packed; /* BEACON_FILTER_CONFIG_API_S_VER_4 */ | ||
| 487 | 503 | ||
| 488 | /* Beacon filtering and beacon abort */ | 504 | /* Beacon filtering and beacon abort */ |
| 489 | #define IWL_BF_ENERGY_DELTA_DEFAULT 5 | 505 | #define IWL_BF_ENERGY_DELTA_DEFAULT 5 |
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h b/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h index 18741889ec30..890a939c463d 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
| 10 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH | 10 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH |
| 11 | * Copyright(c) 2018 Intel Corporation | 11 | * Copyright(c) 2018 - 2019 Intel Corporation |
| 12 | * | 12 | * |
| 13 | * This program is free software; you can redistribute it and/or modify | 13 | * This program is free software; you can redistribute it and/or modify |
| 14 | * it under the terms of version 2 of the GNU General Public License as | 14 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -31,7 +31,7 @@ | |||
| 31 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. | 31 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 32 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 32 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
| 33 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH | 33 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH |
| 34 | * Copyright(c) 2018 Intel Corporation | 34 | * Copyright(c) 2018 - 2019 Intel Corporation |
| 35 | * All rights reserved. | 35 | * All rights reserved. |
| 36 | * | 36 | * |
| 37 | * Redistribution and use in source and binary forms, with or without | 37 | * Redistribution and use in source and binary forms, with or without |
| @@ -434,7 +434,7 @@ struct iwl_periodic_scan_complete { | |||
| 434 | /* The maximum of either of these cannot exceed 8, because we use an | 434 | /* The maximum of either of these cannot exceed 8, because we use an |
| 435 | * 8-bit mask (see IWL_MVM_SCAN_MASK in mvm.h). | 435 | * 8-bit mask (see IWL_MVM_SCAN_MASK in mvm.h). |
| 436 | */ | 436 | */ |
| 437 | #define IWL_MVM_MAX_UMAC_SCANS 8 | 437 | #define IWL_MVM_MAX_UMAC_SCANS 4 |
| 438 | #define IWL_MVM_MAX_LMAC_SCANS 1 | 438 | #define IWL_MVM_MAX_LMAC_SCANS 1 |
| 439 | 439 | ||
| 440 | enum scan_config_flags { | 440 | enum scan_config_flags { |
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h b/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h index 358bdf051e83..8511e735c374 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h | |||
| @@ -847,13 +847,13 @@ struct iwl_beacon_notif { | |||
| 847 | } __packed; | 847 | } __packed; |
| 848 | 848 | ||
| 849 | /** | 849 | /** |
| 850 | * struct iwl_extended_beacon_notif - notifies about beacon transmission | 850 | * struct iwl_extended_beacon_notif_v5 - notifies about beacon transmission |
| 851 | * @beacon_notify_hdr: tx response command associated with the beacon | 851 | * @beacon_notify_hdr: tx response command associated with the beacon |
| 852 | * @tsf: last beacon tsf | 852 | * @tsf: last beacon tsf |
| 853 | * @ibss_mgr_status: whether IBSS is manager | 853 | * @ibss_mgr_status: whether IBSS is manager |
| 854 | * @gp2: last beacon time in gp2 | 854 | * @gp2: last beacon time in gp2 |
| 855 | */ | 855 | */ |
| 856 | struct iwl_extended_beacon_notif { | 856 | struct iwl_extended_beacon_notif_v5 { |
| 857 | struct iwl_mvm_tx_resp beacon_notify_hdr; | 857 | struct iwl_mvm_tx_resp beacon_notify_hdr; |
| 858 | __le64 tsf; | 858 | __le64 tsf; |
| 859 | __le32 ibss_mgr_status; | 859 | __le32 ibss_mgr_status; |
| @@ -861,6 +861,20 @@ struct iwl_extended_beacon_notif { | |||
| 861 | } __packed; /* BEACON_NTFY_API_S_VER_5 */ | 861 | } __packed; /* BEACON_NTFY_API_S_VER_5 */ |
| 862 | 862 | ||
| 863 | /** | 863 | /** |
| 864 | * struct iwl_extended_beacon_notif - notifies about beacon transmission | ||
| 865 | * @status: the status of the Tx response of the beacon | ||
| 866 | * @tsf: last beacon tsf | ||
| 867 | * @ibss_mgr_status: whether IBSS is manager | ||
| 868 | * @gp2: last beacon time in gp2 | ||
| 869 | */ | ||
| 870 | struct iwl_extended_beacon_notif { | ||
| 871 | __le32 status; | ||
| 872 | __le64 tsf; | ||
| 873 | __le32 ibss_mgr_status; | ||
| 874 | __le32 gp2; | ||
| 875 | } __packed; /* BEACON_NTFY_API_S_VER_6_ */ | ||
| 876 | |||
| 877 | /** | ||
| 864 | * enum iwl_dump_control - dump (flush) control flags | 878 | * enum iwl_dump_control - dump (flush) control flags |
| 865 | * @DUMP_TX_FIFO_FLUSH: Dump MSDUs until the the FIFO is empty | 879 | * @DUMP_TX_FIFO_FLUSH: Dump MSDUs until the the FIFO is empty |
| 866 | * and the TFD queues are empty. | 880 | * and the TFD queues are empty. |
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 22efd94da6d3..f119c49cd39c 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. |
| 9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
| 10 | * Copyright(c) 2015 - 2017 Intel Deutschland GmbH | 10 | * Copyright(c) 2015 - 2017 Intel Deutschland GmbH |
| 11 | * Copyright(c) 2018 Intel Corporation | 11 | * Copyright(c) 2018 - 2019 Intel Corporation |
| 12 | * | 12 | * |
| 13 | * This program is free software; you can redistribute it and/or modify | 13 | * This program is free software; you can redistribute it and/or modify |
| 14 | * it under the terms of version 2 of the GNU General Public License as | 14 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -31,7 +31,7 @@ | |||
| 31 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. | 31 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
| 32 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 32 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
| 33 | * Copyright(c) 2015 - 2017 Intel Deutschland GmbH | 33 | * Copyright(c) 2015 - 2017 Intel Deutschland GmbH |
| 34 | * Copyright(c) 2018 Intel Corporation | 34 | * Copyright(c) 2018 - 2019 Intel Corporation |
| 35 | * All rights reserved. | 35 | * All rights reserved. |
| 36 | * | 36 | * |
| 37 | * Redistribution and use in source and binary forms, with or without | 37 | * Redistribution and use in source and binary forms, with or without |
| @@ -242,7 +242,8 @@ static void iwl_fw_dump_rxf(struct iwl_fw_runtime *fwrt, | |||
| 242 | cfg->lmac[0].rxfifo1_size, 0, 0); | 242 | cfg->lmac[0].rxfifo1_size, 0, 0); |
| 243 | /* Pull RXF2 */ | 243 | /* Pull RXF2 */ |
| 244 | iwl_fwrt_dump_rxf(fwrt, dump_data, cfg->rxfifo2_size, | 244 | iwl_fwrt_dump_rxf(fwrt, dump_data, cfg->rxfifo2_size, |
| 245 | RXF_DIFF_FROM_PREV, 1); | 245 | RXF_DIFF_FROM_PREV + |
| 246 | fwrt->trans->cfg->umac_prph_offset, 1); | ||
| 246 | /* Pull LMAC2 RXF1 */ | 247 | /* Pull LMAC2 RXF1 */ |
| 247 | if (fwrt->smem_cfg.num_lmacs > 1) | 248 | if (fwrt->smem_cfg.num_lmacs > 1) |
| 248 | iwl_fwrt_dump_rxf(fwrt, dump_data, | 249 | iwl_fwrt_dump_rxf(fwrt, dump_data, |
| @@ -673,7 +674,9 @@ static void iwl_fw_prph_handler(struct iwl_fw_runtime *fwrt, void *ptr, | |||
| 673 | { | 674 | { |
| 674 | u32 range_len; | 675 | u32 range_len; |
| 675 | 676 | ||
| 676 | if (fwrt->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22000) { | 677 | if (fwrt->trans->cfg->device_family >= IWL_DEVICE_FAMILY_AX210) { |
| 678 | /* TODO */ | ||
| 679 | } else if (fwrt->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22000) { | ||
| 677 | range_len = ARRAY_SIZE(iwl_prph_dump_addr_22000); | 680 | range_len = ARRAY_SIZE(iwl_prph_dump_addr_22000); |
| 678 | handler(fwrt, iwl_prph_dump_addr_22000, range_len, ptr); | 681 | handler(fwrt, iwl_prph_dump_addr_22000, range_len, ptr); |
| 679 | } else { | 682 | } else { |
| @@ -707,28 +710,6 @@ static void iwl_fw_dump_mem(struct iwl_fw_runtime *fwrt, | |||
| 707 | IWL_DEBUG_INFO(fwrt, "WRT memory dump. Type=%u\n", dump_mem->type); | 710 | IWL_DEBUG_INFO(fwrt, "WRT memory dump. Type=%u\n", dump_mem->type); |
| 708 | } | 711 | } |
| 709 | 712 | ||
| 710 | static void iwl_fw_dump_named_mem(struct iwl_fw_runtime *fwrt, | ||
| 711 | struct iwl_fw_error_dump_data **dump_data, | ||
| 712 | u32 len, u32 ofs, u8 *name, u8 name_len) | ||
| 713 | { | ||
| 714 | struct iwl_fw_error_dump_named_mem *dump_mem; | ||
| 715 | |||
| 716 | if (!len) | ||
| 717 | return; | ||
| 718 | |||
| 719 | (*dump_data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM); | ||
| 720 | (*dump_data)->len = cpu_to_le32(len + sizeof(*dump_mem)); | ||
| 721 | dump_mem = (void *)(*dump_data)->data; | ||
| 722 | dump_mem->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM_NAMED_MEM); | ||
| 723 | dump_mem->offset = cpu_to_le32(ofs); | ||
| 724 | dump_mem->name_len = name_len; | ||
| 725 | memcpy(dump_mem->name, name, name_len); | ||
| 726 | iwl_trans_read_mem_bytes(fwrt->trans, ofs, dump_mem->data, len); | ||
| 727 | *dump_data = iwl_fw_error_next_data(*dump_data); | ||
| 728 | |||
| 729 | IWL_DEBUG_INFO(fwrt, "WRT memory dump. Type=%u\n", dump_mem->type); | ||
| 730 | } | ||
| 731 | |||
| 732 | #define ADD_LEN(len, item_len, const_len) \ | 713 | #define ADD_LEN(len, item_len, const_len) \ |
| 733 | do {size_t item = item_len; len += (!!item) * const_len + item; } \ | 714 | do {size_t item = item_len; len += (!!item) * const_len + item; } \ |
| 734 | while (0) | 715 | while (0) |
| @@ -815,6 +796,9 @@ static void iwl_dump_paging(struct iwl_fw_runtime *fwrt, | |||
| 815 | DMA_BIDIRECTIONAL); | 796 | DMA_BIDIRECTIONAL); |
| 816 | memcpy(paging->data, page_address(pages), | 797 | memcpy(paging->data, page_address(pages), |
| 817 | PAGING_BLOCK_SIZE); | 798 | PAGING_BLOCK_SIZE); |
| 799 | dma_sync_single_for_device(fwrt->trans->dev, addr, | ||
| 800 | PAGING_BLOCK_SIZE, | ||
| 801 | DMA_BIDIRECTIONAL); | ||
| 818 | (*data) = iwl_fw_error_next_data(*data); | 802 | (*data) = iwl_fw_error_next_data(*data); |
| 819 | } | 803 | } |
| 820 | } | 804 | } |
| @@ -1059,117 +1043,645 @@ out: | |||
| 1059 | return dump_file; | 1043 | return dump_file; |
| 1060 | } | 1044 | } |
| 1061 | 1045 | ||
| 1062 | static void iwl_dump_prph_ini(struct iwl_trans *trans, | 1046 | static int iwl_dump_ini_prph_iter(struct iwl_fw_runtime *fwrt, |
| 1063 | struct iwl_fw_error_dump_data **data, | 1047 | struct iwl_fw_ini_region_cfg *reg, |
| 1064 | struct iwl_fw_ini_region_cfg *reg) | 1048 | void *range_ptr, int idx) |
| 1065 | { | 1049 | { |
| 1066 | struct iwl_fw_error_dump_prph *prph; | 1050 | struct iwl_fw_ini_error_dump_range *range = range_ptr; |
| 1051 | __le32 *val = range->data; | ||
| 1052 | u32 addr, prph_val, offset = le32_to_cpu(reg->offset); | ||
| 1053 | int i; | ||
| 1054 | |||
| 1055 | range->start_addr = reg->start_addr[idx]; | ||
| 1056 | range->range_data_size = reg->internal.range_data_size; | ||
| 1057 | for (i = 0; i < le32_to_cpu(reg->internal.range_data_size); i += 4) { | ||
| 1058 | addr = le32_to_cpu(range->start_addr) + i; | ||
| 1059 | prph_val = iwl_read_prph(fwrt->trans, addr + offset); | ||
| 1060 | if (prph_val == 0x5a5a5a5a) | ||
| 1061 | return -EBUSY; | ||
| 1062 | *val++ = cpu_to_le32(prph_val); | ||
| 1063 | } | ||
| 1064 | |||
| 1065 | return sizeof(*range) + le32_to_cpu(range->range_data_size); | ||
| 1066 | } | ||
| 1067 | |||
| 1068 | static int iwl_dump_ini_csr_iter(struct iwl_fw_runtime *fwrt, | ||
| 1069 | struct iwl_fw_ini_region_cfg *reg, | ||
| 1070 | void *range_ptr, int idx) | ||
| 1071 | { | ||
| 1072 | struct iwl_fw_ini_error_dump_range *range = range_ptr; | ||
| 1073 | __le32 *val = range->data; | ||
| 1074 | u32 addr, offset = le32_to_cpu(reg->offset); | ||
| 1075 | int i; | ||
| 1076 | |||
| 1077 | range->start_addr = reg->start_addr[idx]; | ||
| 1078 | range->range_data_size = reg->internal.range_data_size; | ||
| 1079 | for (i = 0; i < le32_to_cpu(reg->internal.range_data_size); i += 4) { | ||
| 1080 | addr = le32_to_cpu(range->start_addr) + i; | ||
| 1081 | *val++ = cpu_to_le32(iwl_trans_read32(fwrt->trans, | ||
| 1082 | addr + offset)); | ||
| 1083 | } | ||
| 1084 | |||
| 1085 | return sizeof(*range) + le32_to_cpu(range->range_data_size); | ||
| 1086 | } | ||
| 1087 | |||
| 1088 | static int iwl_dump_ini_dev_mem_iter(struct iwl_fw_runtime *fwrt, | ||
| 1089 | struct iwl_fw_ini_region_cfg *reg, | ||
| 1090 | void *range_ptr, int idx) | ||
| 1091 | { | ||
| 1092 | struct iwl_fw_ini_error_dump_range *range = range_ptr; | ||
| 1093 | u32 addr = le32_to_cpu(range->start_addr); | ||
| 1094 | u32 offset = le32_to_cpu(reg->offset); | ||
| 1095 | |||
| 1096 | range->start_addr = reg->start_addr[idx]; | ||
| 1097 | range->range_data_size = reg->internal.range_data_size; | ||
| 1098 | iwl_trans_read_mem_bytes(fwrt->trans, addr + offset, range->data, | ||
| 1099 | le32_to_cpu(reg->internal.range_data_size)); | ||
| 1100 | |||
| 1101 | return sizeof(*range) + le32_to_cpu(range->range_data_size); | ||
| 1102 | } | ||
| 1103 | |||
| 1104 | static int | ||
| 1105 | iwl_dump_ini_paging_gen2_iter(struct iwl_fw_runtime *fwrt, | ||
| 1106 | struct iwl_fw_ini_region_cfg *reg, | ||
| 1107 | void *range_ptr, int idx) | ||
| 1108 | { | ||
| 1109 | struct iwl_fw_ini_error_dump_range *range = range_ptr; | ||
| 1110 | u32 page_size = fwrt->trans->init_dram.paging[idx].size; | ||
| 1111 | |||
| 1112 | range->start_addr = cpu_to_le32(idx); | ||
| 1113 | range->range_data_size = cpu_to_le32(page_size); | ||
| 1114 | memcpy(range->data, fwrt->trans->init_dram.paging[idx].block, | ||
| 1115 | page_size); | ||
| 1116 | |||
| 1117 | return sizeof(*range) + le32_to_cpu(range->range_data_size); | ||
| 1118 | } | ||
| 1119 | |||
| 1120 | static int iwl_dump_ini_paging_iter(struct iwl_fw_runtime *fwrt, | ||
| 1121 | struct iwl_fw_ini_region_cfg *reg, | ||
| 1122 | void *range_ptr, int idx) | ||
| 1123 | { | ||
| 1124 | /* increase idx by 1 since the pages are from 1 to | ||
| 1125 | * fwrt->num_of_paging_blk + 1 | ||
| 1126 | */ | ||
| 1127 | struct page *page = fwrt->fw_paging_db[++idx].fw_paging_block; | ||
| 1128 | struct iwl_fw_ini_error_dump_range *range = range_ptr; | ||
| 1129 | dma_addr_t addr = fwrt->fw_paging_db[idx].fw_paging_phys; | ||
| 1130 | u32 page_size = fwrt->fw_paging_db[idx].fw_paging_size; | ||
| 1131 | |||
| 1132 | range->start_addr = cpu_to_le32(idx); | ||
| 1133 | range->range_data_size = cpu_to_le32(page_size); | ||
| 1134 | dma_sync_single_for_cpu(fwrt->trans->dev, addr, page_size, | ||
| 1135 | DMA_BIDIRECTIONAL); | ||
| 1136 | memcpy(range->data, page_address(page), page_size); | ||
| 1137 | dma_sync_single_for_device(fwrt->trans->dev, addr, page_size, | ||
| 1138 | DMA_BIDIRECTIONAL); | ||
| 1139 | |||
| 1140 | return sizeof(*range) + le32_to_cpu(range->range_data_size); | ||
| 1141 | } | ||
| 1142 | |||
| 1143 | static int | ||
| 1144 | iwl_dump_ini_mon_dram_iter(struct iwl_fw_runtime *fwrt, | ||
| 1145 | struct iwl_fw_ini_region_cfg *reg, void *range_ptr, | ||
| 1146 | int idx) | ||
| 1147 | { | ||
| 1148 | struct iwl_fw_ini_error_dump_range *range = range_ptr; | ||
| 1149 | u32 start_addr = iwl_read_umac_prph(fwrt->trans, | ||
| 1150 | MON_BUFF_BASE_ADDR_VER2); | ||
| 1151 | |||
| 1152 | if (start_addr == 0x5a5a5a5a) | ||
| 1153 | return -EBUSY; | ||
| 1154 | |||
| 1155 | range->start_addr = cpu_to_le32(start_addr); | ||
| 1156 | range->range_data_size = cpu_to_le32(fwrt->trans->fw_mon[idx].size); | ||
| 1157 | |||
| 1158 | memcpy(range->data, fwrt->trans->fw_mon[idx].block, | ||
| 1159 | fwrt->trans->fw_mon[idx].size); | ||
| 1160 | |||
| 1161 | return sizeof(*range) + le32_to_cpu(range->range_data_size); | ||
| 1162 | } | ||
| 1163 | |||
| 1164 | struct iwl_ini_txf_iter_data { | ||
| 1165 | int fifo; | ||
| 1166 | int lmac; | ||
| 1167 | u32 fifo_size; | ||
| 1168 | bool internal_txf; | ||
| 1169 | bool init; | ||
| 1170 | }; | ||
| 1171 | |||
| 1172 | static bool iwl_ini_txf_iter(struct iwl_fw_runtime *fwrt, | ||
| 1173 | struct iwl_fw_ini_region_cfg *reg) | ||
| 1174 | { | ||
| 1175 | struct iwl_ini_txf_iter_data *iter = fwrt->dump.fifo_iter; | ||
| 1176 | struct iwl_fwrt_shared_mem_cfg *cfg = &fwrt->smem_cfg; | ||
| 1177 | int txf_num = cfg->num_txfifo_entries; | ||
| 1178 | int int_txf_num = ARRAY_SIZE(cfg->internal_txfifo_size); | ||
| 1179 | u32 lmac_bitmap = le32_to_cpu(reg->fifos.fid1); | ||
| 1180 | |||
| 1181 | if (!iter) | ||
| 1182 | return false; | ||
| 1183 | |||
| 1184 | if (iter->init) { | ||
| 1185 | if (le32_to_cpu(reg->offset) && | ||
| 1186 | WARN_ONCE(cfg->num_lmacs == 1, | ||
| 1187 | "Invalid lmac offset: 0x%x\n", | ||
| 1188 | le32_to_cpu(reg->offset))) | ||
| 1189 | return false; | ||
| 1190 | |||
| 1191 | iter->init = false; | ||
| 1192 | iter->internal_txf = false; | ||
| 1193 | iter->fifo_size = 0; | ||
| 1194 | iter->fifo = -1; | ||
| 1195 | if (le32_to_cpu(reg->offset)) | ||
| 1196 | iter->lmac = 1; | ||
| 1197 | else | ||
| 1198 | iter->lmac = 0; | ||
| 1199 | } | ||
| 1200 | |||
| 1201 | if (!iter->internal_txf) | ||
| 1202 | for (iter->fifo++; iter->fifo < txf_num; iter->fifo++) { | ||
| 1203 | iter->fifo_size = | ||
| 1204 | cfg->lmac[iter->lmac].txfifo_size[iter->fifo]; | ||
| 1205 | if (iter->fifo_size && (lmac_bitmap & BIT(iter->fifo))) | ||
| 1206 | return true; | ||
| 1207 | } | ||
| 1208 | |||
| 1209 | iter->internal_txf = true; | ||
| 1210 | |||
| 1211 | if (!fw_has_capa(&fwrt->fw->ucode_capa, | ||
| 1212 | IWL_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG)) | ||
| 1213 | return false; | ||
| 1214 | |||
| 1215 | for (iter->fifo++; iter->fifo < int_txf_num + txf_num; iter->fifo++) { | ||
| 1216 | iter->fifo_size = | ||
| 1217 | cfg->internal_txfifo_size[iter->fifo - txf_num]; | ||
| 1218 | if (iter->fifo_size && (lmac_bitmap & BIT(iter->fifo))) | ||
| 1219 | return true; | ||
| 1220 | } | ||
| 1221 | |||
| 1222 | return false; | ||
| 1223 | } | ||
| 1224 | |||
| 1225 | static int iwl_dump_ini_txf_iter(struct iwl_fw_runtime *fwrt, | ||
| 1226 | struct iwl_fw_ini_region_cfg *reg, | ||
| 1227 | void *range_ptr, int idx) | ||
| 1228 | { | ||
| 1229 | struct iwl_fw_ini_fifo_error_dump_range *range = range_ptr; | ||
| 1230 | struct iwl_ini_txf_iter_data *iter; | ||
| 1231 | u32 offs = le32_to_cpu(reg->offset), addr; | ||
| 1232 | u32 registers_size = | ||
| 1233 | le32_to_cpu(reg->fifos.num_of_registers) * sizeof(__le32); | ||
| 1234 | __le32 *val = range->data; | ||
| 1067 | unsigned long flags; | 1235 | unsigned long flags; |
| 1068 | u32 i, size = le32_to_cpu(reg->num_regions); | 1236 | int i; |
| 1069 | 1237 | ||
| 1070 | IWL_DEBUG_INFO(trans, "WRT PRPH dump\n"); | 1238 | if (!iwl_ini_txf_iter(fwrt, reg)) |
| 1239 | return -EIO; | ||
| 1071 | 1240 | ||
| 1072 | if (!iwl_trans_grab_nic_access(trans, &flags)) | 1241 | if (!iwl_trans_grab_nic_access(fwrt->trans, &flags)) |
| 1242 | return -EBUSY; | ||
| 1243 | |||
| 1244 | iter = fwrt->dump.fifo_iter; | ||
| 1245 | |||
| 1246 | range->fifo_num = cpu_to_le32(iter->fifo); | ||
| 1247 | range->num_of_registers = reg->fifos.num_of_registers; | ||
| 1248 | range->range_data_size = cpu_to_le32(iter->fifo_size + registers_size); | ||
| 1249 | |||
| 1250 | iwl_write_prph_no_grab(fwrt->trans, TXF_LARC_NUM + offs, iter->fifo); | ||
| 1251 | |||
| 1252 | /* read txf registers */ | ||
| 1253 | for (i = 0; i < le32_to_cpu(reg->fifos.num_of_registers); i++) { | ||
| 1254 | addr = le32_to_cpu(reg->start_addr[i]) + offs; | ||
| 1255 | |||
| 1256 | *val++ = cpu_to_le32(iwl_read_prph_no_grab(fwrt->trans, addr)); | ||
| 1257 | } | ||
| 1258 | |||
| 1259 | if (reg->fifos.header_only) { | ||
| 1260 | range->range_data_size = cpu_to_le32(registers_size); | ||
| 1261 | goto out; | ||
| 1262 | } | ||
| 1263 | |||
| 1264 | /* Set the TXF_READ_MODIFY_ADDR to TXF_WR_PTR */ | ||
| 1265 | iwl_write_prph_no_grab(fwrt->trans, TXF_READ_MODIFY_ADDR + offs, | ||
| 1266 | TXF_WR_PTR + offs); | ||
| 1267 | |||
| 1268 | /* Dummy-read to advance the read pointer to the head */ | ||
| 1269 | iwl_read_prph_no_grab(fwrt->trans, TXF_READ_MODIFY_DATA + offs); | ||
| 1270 | |||
| 1271 | /* Read FIFO */ | ||
| 1272 | addr = TXF_READ_MODIFY_DATA + offs; | ||
| 1273 | for (i = 0; i < iter->fifo_size; i += sizeof(__le32)) | ||
| 1274 | *val++ = cpu_to_le32(iwl_read_prph_no_grab(fwrt->trans, addr)); | ||
| 1275 | |||
| 1276 | out: | ||
| 1277 | iwl_trans_release_nic_access(fwrt->trans, &flags); | ||
| 1278 | |||
| 1279 | return sizeof(*range) + le32_to_cpu(range->range_data_size); | ||
| 1280 | } | ||
| 1281 | |||
| 1282 | struct iwl_ini_rxf_data { | ||
| 1283 | u32 fifo_num; | ||
| 1284 | u32 size; | ||
| 1285 | u32 offset; | ||
| 1286 | }; | ||
| 1287 | |||
| 1288 | static void iwl_ini_get_rxf_data(struct iwl_fw_runtime *fwrt, | ||
| 1289 | struct iwl_fw_ini_region_cfg *reg, | ||
| 1290 | struct iwl_ini_rxf_data *data) | ||
| 1291 | { | ||
| 1292 | u32 fid1 = le32_to_cpu(reg->fifos.fid1); | ||
| 1293 | u32 fid2 = le32_to_cpu(reg->fifos.fid2); | ||
| 1294 | u32 fifo_idx; | ||
| 1295 | |||
| 1296 | if (!data) | ||
| 1073 | return; | 1297 | return; |
| 1074 | 1298 | ||
| 1075 | for (i = 0; i < size; i++) { | 1299 | memset(data, 0, sizeof(*data)); |
| 1076 | (*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PRPH); | 1300 | |
| 1077 | (*data)->len = cpu_to_le32(le32_to_cpu(reg->size) + | 1301 | if (WARN_ON_ONCE((fid1 && fid2) || (!fid1 && !fid2))) |
| 1078 | sizeof(*prph)); | 1302 | return; |
| 1079 | prph = (void *)(*data)->data; | 1303 | |
| 1080 | prph->prph_start = reg->start_addr[i]; | 1304 | fifo_idx = ffs(fid1) - 1; |
| 1081 | prph->data[0] = cpu_to_le32(iwl_read_prph_no_grab(trans, | 1305 | if (fid1 && !WARN_ON_ONCE((~BIT(fifo_idx) & fid1) || |
| 1082 | le32_to_cpu(prph->prph_start))); | 1306 | fifo_idx >= MAX_NUM_LMAC)) { |
| 1083 | *data = iwl_fw_error_next_data(*data); | 1307 | data->size = fwrt->smem_cfg.lmac[fifo_idx].rxfifo1_size; |
| 1308 | data->fifo_num = fifo_idx; | ||
| 1309 | return; | ||
| 1310 | } | ||
| 1311 | |||
| 1312 | fifo_idx = ffs(fid2) - 1; | ||
| 1313 | if (fid2 && !WARN_ON_ONCE(fifo_idx != 0)) { | ||
| 1314 | data->size = fwrt->smem_cfg.rxfifo2_size; | ||
| 1315 | data->offset = RXF_DIFF_FROM_PREV; | ||
| 1316 | /* use bit 31 to distinguish between umac and lmac rxf while | ||
| 1317 | * parsing the dump | ||
| 1318 | */ | ||
| 1319 | data->fifo_num = fifo_idx | IWL_RXF_UMAC_BIT; | ||
| 1320 | return; | ||
| 1084 | } | 1321 | } |
| 1085 | iwl_trans_release_nic_access(trans, &flags); | ||
| 1086 | } | 1322 | } |
| 1087 | 1323 | ||
| 1088 | static void iwl_dump_csr_ini(struct iwl_trans *trans, | 1324 | static int iwl_dump_ini_rxf_iter(struct iwl_fw_runtime *fwrt, |
| 1089 | struct iwl_fw_error_dump_data **data, | 1325 | struct iwl_fw_ini_region_cfg *reg, |
| 1090 | struct iwl_fw_ini_region_cfg *reg) | 1326 | void *range_ptr, int idx) |
| 1091 | { | 1327 | { |
| 1092 | int i, num = le32_to_cpu(reg->num_regions); | 1328 | struct iwl_fw_ini_fifo_error_dump_range *range = range_ptr; |
| 1093 | u32 size = le32_to_cpu(reg->size); | 1329 | struct iwl_ini_rxf_data rxf_data; |
| 1330 | u32 offs = le32_to_cpu(reg->offset), addr; | ||
| 1331 | u32 registers_size = | ||
| 1332 | le32_to_cpu(reg->fifos.num_of_registers) * sizeof(__le32); | ||
| 1333 | __le32 *val = range->data; | ||
| 1334 | unsigned long flags; | ||
| 1335 | int i; | ||
| 1336 | |||
| 1337 | iwl_ini_get_rxf_data(fwrt, reg, &rxf_data); | ||
| 1338 | if (!rxf_data.size) | ||
| 1339 | return -EIO; | ||
| 1094 | 1340 | ||
| 1095 | IWL_DEBUG_INFO(trans, "WRT CSR dump\n"); | 1341 | if (!iwl_trans_grab_nic_access(fwrt->trans, &flags)) |
| 1342 | return -EBUSY; | ||
| 1096 | 1343 | ||
| 1097 | for (i = 0; i < num; i++) { | 1344 | offs += rxf_data.offset; |
| 1098 | u32 add = le32_to_cpu(reg->start_addr[i]); | ||
| 1099 | __le32 *val; | ||
| 1100 | int j; | ||
| 1101 | 1345 | ||
| 1102 | (*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_CSR); | 1346 | range->fifo_num = cpu_to_le32(rxf_data.fifo_num); |
| 1103 | (*data)->len = cpu_to_le32(size); | 1347 | range->num_of_registers = reg->fifos.num_of_registers; |
| 1104 | val = (void *)(*data)->data; | 1348 | range->range_data_size = cpu_to_le32(rxf_data.size + registers_size); |
| 1105 | 1349 | ||
| 1106 | for (j = 0; j < size; j += 4) | 1350 | /* read rxf registers */ |
| 1107 | *val++ = cpu_to_le32(iwl_trans_read32(trans, j + add)); | 1351 | for (i = 0; i < le32_to_cpu(reg->fifos.num_of_registers); i++) { |
| 1352 | addr = le32_to_cpu(reg->start_addr[i]) + offs; | ||
| 1108 | 1353 | ||
| 1109 | *data = iwl_fw_error_next_data(*data); | 1354 | *val++ = cpu_to_le32(iwl_read_prph_no_grab(fwrt->trans, addr)); |
| 1355 | } | ||
| 1356 | |||
| 1357 | if (reg->fifos.header_only) { | ||
| 1358 | range->range_data_size = cpu_to_le32(registers_size); | ||
| 1359 | goto out; | ||
| 1360 | } | ||
| 1361 | |||
| 1362 | /* Lock fence */ | ||
| 1363 | iwl_write_prph_no_grab(fwrt->trans, RXF_SET_FENCE_MODE + offs, 0x1); | ||
| 1364 | /* Set fence pointer to the same place like WR pointer */ | ||
| 1365 | iwl_write_prph_no_grab(fwrt->trans, RXF_LD_WR2FENCE + offs, 0x1); | ||
| 1366 | /* Set fence offset */ | ||
| 1367 | iwl_write_prph_no_grab(fwrt->trans, RXF_LD_FENCE_OFFSET_ADDR + offs, | ||
| 1368 | 0x0); | ||
| 1369 | |||
| 1370 | /* Read FIFO */ | ||
| 1371 | addr = RXF_FIFO_RD_FENCE_INC + offs; | ||
| 1372 | for (i = 0; i < rxf_data.size; i += sizeof(__le32)) | ||
| 1373 | *val++ = cpu_to_le32(iwl_read_prph_no_grab(fwrt->trans, addr)); | ||
| 1374 | |||
| 1375 | out: | ||
| 1376 | iwl_trans_release_nic_access(fwrt->trans, &flags); | ||
| 1377 | |||
| 1378 | return sizeof(*range) + le32_to_cpu(range->range_data_size); | ||
| 1379 | } | ||
| 1380 | |||
| 1381 | static void *iwl_dump_ini_mem_fill_header(struct iwl_fw_runtime *fwrt, | ||
| 1382 | struct iwl_fw_ini_region_cfg *reg, | ||
| 1383 | void *data) | ||
| 1384 | { | ||
| 1385 | struct iwl_fw_ini_error_dump *dump = data; | ||
| 1386 | |||
| 1387 | return dump->ranges; | ||
| 1388 | } | ||
| 1389 | |||
| 1390 | static void | ||
| 1391 | *iwl_dump_ini_mon_dram_fill_header(struct iwl_fw_runtime *fwrt, | ||
| 1392 | struct iwl_fw_ini_region_cfg *reg, | ||
| 1393 | void *data) | ||
| 1394 | { | ||
| 1395 | struct iwl_fw_ini_monitor_dram_dump *mon_dump = (void *)data; | ||
| 1396 | u32 write_ptr, cycle_cnt; | ||
| 1397 | unsigned long flags; | ||
| 1398 | |||
| 1399 | if (!iwl_trans_grab_nic_access(fwrt->trans, &flags)) { | ||
| 1400 | IWL_ERR(fwrt, "Failed to get DRAM monitor header\n"); | ||
| 1401 | return NULL; | ||
| 1110 | } | 1402 | } |
| 1403 | write_ptr = iwl_read_umac_prph_no_grab(fwrt->trans, | ||
| 1404 | MON_BUFF_WRPTR_VER2); | ||
| 1405 | cycle_cnt = iwl_read_umac_prph_no_grab(fwrt->trans, | ||
| 1406 | MON_BUFF_CYCLE_CNT_VER2); | ||
| 1407 | iwl_trans_release_nic_access(fwrt->trans, &flags); | ||
| 1408 | |||
| 1409 | mon_dump->write_ptr = cpu_to_le32(write_ptr); | ||
| 1410 | mon_dump->cycle_cnt = cpu_to_le32(cycle_cnt); | ||
| 1411 | |||
| 1412 | return mon_dump->ranges; | ||
| 1413 | } | ||
| 1414 | |||
| 1415 | static void *iwl_dump_ini_fifo_fill_header(struct iwl_fw_runtime *fwrt, | ||
| 1416 | struct iwl_fw_ini_region_cfg *reg, | ||
| 1417 | void *data) | ||
| 1418 | { | ||
| 1419 | struct iwl_fw_ini_fifo_error_dump *dump = data; | ||
| 1420 | |||
| 1421 | return dump->ranges; | ||
| 1422 | } | ||
| 1423 | |||
| 1424 | static u32 iwl_dump_ini_mem_ranges(struct iwl_fw_runtime *fwrt, | ||
| 1425 | struct iwl_fw_ini_region_cfg *reg) | ||
| 1426 | { | ||
| 1427 | return le32_to_cpu(reg->internal.num_of_ranges); | ||
| 1428 | } | ||
| 1429 | |||
| 1430 | static u32 iwl_dump_ini_paging_gen2_ranges(struct iwl_fw_runtime *fwrt, | ||
| 1431 | struct iwl_fw_ini_region_cfg *reg) | ||
| 1432 | { | ||
| 1433 | return fwrt->trans->init_dram.paging_cnt; | ||
| 1434 | } | ||
| 1435 | |||
| 1436 | static u32 iwl_dump_ini_paging_ranges(struct iwl_fw_runtime *fwrt, | ||
| 1437 | struct iwl_fw_ini_region_cfg *reg) | ||
| 1438 | { | ||
| 1439 | return fwrt->num_of_paging_blk; | ||
| 1440 | } | ||
| 1441 | |||
| 1442 | static u32 iwl_dump_ini_mon_dram_ranges(struct iwl_fw_runtime *fwrt, | ||
| 1443 | struct iwl_fw_ini_region_cfg *reg) | ||
| 1444 | { | ||
| 1445 | return 1; | ||
| 1446 | } | ||
| 1447 | |||
| 1448 | static u32 iwl_dump_ini_txf_ranges(struct iwl_fw_runtime *fwrt, | ||
| 1449 | struct iwl_fw_ini_region_cfg *reg) | ||
| 1450 | { | ||
| 1451 | struct iwl_ini_txf_iter_data iter = { .init = true }; | ||
| 1452 | void *fifo_iter = fwrt->dump.fifo_iter; | ||
| 1453 | u32 num_of_fifos = 0; | ||
| 1454 | |||
| 1455 | fwrt->dump.fifo_iter = &iter; | ||
| 1456 | while (iwl_ini_txf_iter(fwrt, reg)) | ||
| 1457 | num_of_fifos++; | ||
| 1458 | |||
| 1459 | fwrt->dump.fifo_iter = fifo_iter; | ||
| 1460 | |||
| 1461 | return num_of_fifos; | ||
| 1462 | } | ||
| 1463 | |||
| 1464 | static u32 iwl_dump_ini_rxf_ranges(struct iwl_fw_runtime *fwrt, | ||
| 1465 | struct iwl_fw_ini_region_cfg *reg) | ||
| 1466 | { | ||
| 1467 | /* Each Rx fifo needs a different offset and therefore, it's | ||
| 1468 | * region can contain only one fifo, i.e. 1 memory range. | ||
| 1469 | */ | ||
| 1470 | return 1; | ||
| 1471 | } | ||
| 1472 | |||
| 1473 | static u32 iwl_dump_ini_mem_get_size(struct iwl_fw_runtime *fwrt, | ||
| 1474 | struct iwl_fw_ini_region_cfg *reg) | ||
| 1475 | { | ||
| 1476 | return sizeof(struct iwl_fw_ini_error_dump) + | ||
| 1477 | iwl_dump_ini_mem_ranges(fwrt, reg) * | ||
| 1478 | (sizeof(struct iwl_fw_ini_error_dump_range) + | ||
| 1479 | le32_to_cpu(reg->internal.range_data_size)); | ||
| 1480 | } | ||
| 1481 | |||
| 1482 | static u32 iwl_dump_ini_paging_gen2_get_size(struct iwl_fw_runtime *fwrt, | ||
| 1483 | struct iwl_fw_ini_region_cfg *reg) | ||
| 1484 | { | ||
| 1485 | int i; | ||
| 1486 | u32 range_header_len = sizeof(struct iwl_fw_ini_error_dump_range); | ||
| 1487 | u32 size = sizeof(struct iwl_fw_ini_error_dump); | ||
| 1488 | |||
| 1489 | for (i = 0; i < iwl_dump_ini_paging_gen2_ranges(fwrt, reg); i++) | ||
| 1490 | size += range_header_len + | ||
| 1491 | fwrt->trans->init_dram.paging[i].size; | ||
| 1492 | |||
| 1493 | return size; | ||
| 1494 | } | ||
| 1495 | |||
| 1496 | static u32 iwl_dump_ini_paging_get_size(struct iwl_fw_runtime *fwrt, | ||
| 1497 | struct iwl_fw_ini_region_cfg *reg) | ||
| 1498 | { | ||
| 1499 | int i; | ||
| 1500 | u32 range_header_len = sizeof(struct iwl_fw_ini_error_dump_range); | ||
| 1501 | u32 size = sizeof(struct iwl_fw_ini_error_dump); | ||
| 1502 | |||
| 1503 | for (i = 1; i <= iwl_dump_ini_paging_ranges(fwrt, reg); i++) | ||
| 1504 | size += range_header_len + fwrt->fw_paging_db[i].fw_paging_size; | ||
| 1505 | |||
| 1506 | return size; | ||
| 1507 | } | ||
| 1508 | |||
| 1509 | static u32 iwl_dump_ini_mon_dram_get_size(struct iwl_fw_runtime *fwrt, | ||
| 1510 | struct iwl_fw_ini_region_cfg *reg) | ||
| 1511 | { | ||
| 1512 | u32 size = sizeof(struct iwl_fw_ini_monitor_dram_dump); | ||
| 1513 | |||
| 1514 | if (fwrt->trans->num_blocks) | ||
| 1515 | size += fwrt->trans->fw_mon[0].size; | ||
| 1516 | |||
| 1517 | return size; | ||
| 1518 | } | ||
| 1519 | |||
| 1520 | static u32 iwl_dump_ini_txf_get_size(struct iwl_fw_runtime *fwrt, | ||
| 1521 | struct iwl_fw_ini_region_cfg *reg) | ||
| 1522 | { | ||
| 1523 | struct iwl_ini_txf_iter_data iter = { .init = true }; | ||
| 1524 | void *fifo_iter = fwrt->dump.fifo_iter; | ||
| 1525 | u32 size = 0; | ||
| 1526 | u32 fifo_hdr = sizeof(struct iwl_fw_ini_fifo_error_dump_range) + | ||
| 1527 | le32_to_cpu(reg->fifos.num_of_registers) * sizeof(__le32); | ||
| 1528 | |||
| 1529 | fwrt->dump.fifo_iter = &iter; | ||
| 1530 | while (iwl_ini_txf_iter(fwrt, reg)) { | ||
| 1531 | size += fifo_hdr; | ||
| 1532 | if (!reg->fifos.header_only) | ||
| 1533 | size += iter.fifo_size; | ||
| 1534 | } | ||
| 1535 | |||
| 1536 | if (size) | ||
| 1537 | size += sizeof(struct iwl_fw_ini_fifo_error_dump); | ||
| 1538 | |||
| 1539 | fwrt->dump.fifo_iter = fifo_iter; | ||
| 1540 | |||
| 1541 | return size; | ||
| 1542 | } | ||
| 1543 | |||
| 1544 | static u32 iwl_dump_ini_rxf_get_size(struct iwl_fw_runtime *fwrt, | ||
| 1545 | struct iwl_fw_ini_region_cfg *reg) | ||
| 1546 | { | ||
| 1547 | struct iwl_ini_rxf_data rx_data; | ||
| 1548 | u32 size = sizeof(struct iwl_fw_ini_fifo_error_dump) + | ||
| 1549 | sizeof(struct iwl_fw_ini_fifo_error_dump_range) + | ||
| 1550 | le32_to_cpu(reg->fifos.num_of_registers) * sizeof(__le32); | ||
| 1551 | |||
| 1552 | if (reg->fifos.header_only) | ||
| 1553 | return size; | ||
| 1554 | |||
| 1555 | iwl_ini_get_rxf_data(fwrt, reg, &rx_data); | ||
| 1556 | size += rx_data.size; | ||
| 1557 | |||
| 1558 | return size; | ||
| 1559 | } | ||
| 1560 | |||
| 1561 | /** | ||
| 1562 | * struct iwl_dump_ini_mem_ops - ini memory dump operations | ||
| 1563 | * @get_num_of_ranges: returns the number of memory ranges in the region. | ||
| 1564 | * @get_size: returns the total size of the region. | ||
| 1565 | * @fill_mem_hdr: fills region type specific headers and returns pointer to | ||
| 1566 | * the first range or NULL if failed to fill headers. | ||
| 1567 | * @fill_range: copies a given memory range into the dump. | ||
| 1568 | * Returns the size of the range or negative error value otherwise. | ||
| 1569 | */ | ||
| 1570 | struct iwl_dump_ini_mem_ops { | ||
| 1571 | u32 (*get_num_of_ranges)(struct iwl_fw_runtime *fwrt, | ||
| 1572 | struct iwl_fw_ini_region_cfg *reg); | ||
| 1573 | u32 (*get_size)(struct iwl_fw_runtime *fwrt, | ||
| 1574 | struct iwl_fw_ini_region_cfg *reg); | ||
| 1575 | void *(*fill_mem_hdr)(struct iwl_fw_runtime *fwrt, | ||
| 1576 | struct iwl_fw_ini_region_cfg *reg, void *data); | ||
| 1577 | int (*fill_range)(struct iwl_fw_runtime *fwrt, | ||
| 1578 | struct iwl_fw_ini_region_cfg *reg, void *range, | ||
| 1579 | int idx); | ||
| 1580 | }; | ||
| 1581 | |||
| 1582 | /** | ||
| 1583 | * iwl_dump_ini_mem - copy a memory region into the dump | ||
| 1584 | * @fwrt: fw runtime struct. | ||
| 1585 | * @data: dump memory data. | ||
| 1586 | * @reg: region to copy to the dump. | ||
| 1587 | */ | ||
| 1588 | static void | ||
| 1589 | iwl_dump_ini_mem(struct iwl_fw_runtime *fwrt, | ||
| 1590 | enum iwl_fw_ini_region_type type, | ||
| 1591 | struct iwl_fw_error_dump_data **data, | ||
| 1592 | struct iwl_fw_ini_region_cfg *reg, | ||
| 1593 | struct iwl_dump_ini_mem_ops *ops) | ||
| 1594 | { | ||
| 1595 | struct iwl_fw_ini_error_dump_header *header = (void *)(*data)->data; | ||
| 1596 | void *range; | ||
| 1597 | u32 num_of_ranges, i; | ||
| 1598 | |||
| 1599 | if (WARN_ON(!ops || !ops->get_num_of_ranges || !ops->get_size || | ||
| 1600 | !ops->fill_mem_hdr || !ops->fill_range)) | ||
| 1601 | return; | ||
| 1602 | |||
| 1603 | num_of_ranges = ops->get_num_of_ranges(fwrt, reg); | ||
| 1604 | |||
| 1605 | (*data)->type = cpu_to_le32(type | INI_DUMP_BIT); | ||
| 1606 | (*data)->len = cpu_to_le32(ops->get_size(fwrt, reg)); | ||
| 1607 | |||
| 1608 | header->num_of_ranges = cpu_to_le32(num_of_ranges); | ||
| 1609 | header->name_len = cpu_to_le32(min_t(int, IWL_FW_INI_MAX_NAME, | ||
| 1610 | le32_to_cpu(reg->name_len))); | ||
| 1611 | memcpy(header->name, reg->name, le32_to_cpu(header->name_len)); | ||
| 1612 | |||
| 1613 | range = ops->fill_mem_hdr(fwrt, reg, header); | ||
| 1614 | if (!range) { | ||
| 1615 | IWL_ERR(fwrt, "Failed to fill region header: id=%d, type=%d\n", | ||
| 1616 | le32_to_cpu(reg->region_id), type); | ||
| 1617 | return; | ||
| 1618 | } | ||
| 1619 | |||
| 1620 | for (i = 0; i < num_of_ranges; i++) { | ||
| 1621 | int range_size = ops->fill_range(fwrt, reg, range, i); | ||
| 1622 | |||
| 1623 | if (range_size < 0) { | ||
| 1624 | IWL_ERR(fwrt, "Failed to dump region: id=%d, type=%d\n", | ||
| 1625 | le32_to_cpu(reg->region_id), type); | ||
| 1626 | return; | ||
| 1627 | } | ||
| 1628 | range = range + range_size; | ||
| 1629 | } | ||
| 1630 | *data = iwl_fw_error_next_data(*data); | ||
| 1111 | } | 1631 | } |
| 1112 | 1632 | ||
| 1113 | static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt, | 1633 | static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt, |
| 1114 | struct iwl_fw_ini_trigger *trigger) | 1634 | struct iwl_fw_ini_trigger *trigger) |
| 1115 | { | 1635 | { |
| 1116 | int i, num, size = 0, hdr_len = sizeof(struct iwl_fw_error_dump_data); | 1636 | int i, size = 0, hdr_len = sizeof(struct iwl_fw_error_dump_data); |
| 1117 | 1637 | ||
| 1118 | if (!trigger || !trigger->num_regions) | 1638 | if (!trigger || !trigger->num_regions) |
| 1119 | return 0; | 1639 | return 0; |
| 1120 | 1640 | ||
| 1121 | num = le32_to_cpu(trigger->num_regions); | 1641 | for (i = 0; i < le32_to_cpu(trigger->num_regions); i++) { |
| 1122 | for (i = 0; i < num; i++) { | ||
| 1123 | u32 reg_id = le32_to_cpu(trigger->data[i]); | 1642 | u32 reg_id = le32_to_cpu(trigger->data[i]); |
| 1124 | struct iwl_fw_ini_region_cfg *reg; | 1643 | struct iwl_fw_ini_region_cfg *reg; |
| 1125 | enum iwl_fw_ini_region_type type; | 1644 | enum iwl_fw_ini_region_type type; |
| 1126 | u32 num_entries; | ||
| 1127 | 1645 | ||
| 1128 | if (WARN_ON(reg_id >= ARRAY_SIZE(fwrt->dump.active_regs))) | 1646 | if (WARN_ON(reg_id >= ARRAY_SIZE(fwrt->dump.active_regs))) |
| 1129 | continue; | 1647 | continue; |
| 1130 | 1648 | ||
| 1131 | reg = fwrt->dump.active_regs[reg_id].reg; | 1649 | reg = fwrt->dump.active_regs[reg_id]; |
| 1132 | if (WARN(!reg, "Unassigned region %d\n", reg_id)) | 1650 | if (WARN(!reg, "Unassigned region %d\n", reg_id)) |
| 1133 | continue; | 1651 | continue; |
| 1134 | 1652 | ||
| 1135 | type = le32_to_cpu(reg->region_type); | 1653 | type = le32_to_cpu(reg->region_type); |
| 1136 | num_entries = le32_to_cpu(reg->num_regions); | ||
| 1137 | |||
| 1138 | switch (type) { | 1654 | switch (type) { |
| 1139 | case IWL_FW_INI_REGION_DEVICE_MEMORY: | 1655 | case IWL_FW_INI_REGION_DEVICE_MEMORY: |
| 1140 | size += hdr_len + | ||
| 1141 | sizeof(struct iwl_fw_error_dump_named_mem) + | ||
| 1142 | le32_to_cpu(reg->size); | ||
| 1143 | break; | ||
| 1144 | case IWL_FW_INI_REGION_PERIPHERY_MAC: | 1656 | case IWL_FW_INI_REGION_PERIPHERY_MAC: |
| 1145 | case IWL_FW_INI_REGION_PERIPHERY_PHY: | 1657 | case IWL_FW_INI_REGION_PERIPHERY_PHY: |
| 1146 | case IWL_FW_INI_REGION_PERIPHERY_AUX: | 1658 | case IWL_FW_INI_REGION_PERIPHERY_AUX: |
| 1147 | size += num_entries * | 1659 | case IWL_FW_INI_REGION_INTERNAL_BUFFER: |
| 1148 | (hdr_len + | 1660 | case IWL_FW_INI_REGION_CSR: |
| 1149 | sizeof(struct iwl_fw_error_dump_prph) + | 1661 | size += hdr_len + iwl_dump_ini_mem_get_size(fwrt, reg); |
| 1150 | sizeof(u32)); | ||
| 1151 | break; | 1662 | break; |
| 1152 | case IWL_FW_INI_REGION_TXF: | 1663 | case IWL_FW_INI_REGION_TXF: |
| 1153 | size += iwl_fw_txf_len(fwrt, &fwrt->smem_cfg); | 1664 | size += hdr_len + iwl_dump_ini_txf_get_size(fwrt, reg); |
| 1154 | break; | 1665 | break; |
| 1155 | case IWL_FW_INI_REGION_RXF: | 1666 | case IWL_FW_INI_REGION_RXF: |
| 1156 | size += iwl_fw_rxf_len(fwrt, &fwrt->smem_cfg); | 1667 | size += hdr_len + iwl_dump_ini_rxf_get_size(fwrt, reg); |
| 1157 | break; | 1668 | break; |
| 1158 | case IWL_FW_INI_REGION_PAGING: | 1669 | case IWL_FW_INI_REGION_PAGING: { |
| 1159 | if (!iwl_fw_dbg_is_paging_enabled(fwrt)) | 1670 | size += hdr_len; |
| 1160 | break; | 1671 | if (iwl_fw_dbg_is_paging_enabled(fwrt)) { |
| 1161 | size += fwrt->num_of_paging_blk * | 1672 | size += iwl_dump_ini_paging_get_size(fwrt, reg); |
| 1162 | (hdr_len + | 1673 | } else { |
| 1163 | sizeof(struct iwl_fw_error_dump_paging) + | 1674 | size += iwl_dump_ini_paging_gen2_get_size(fwrt, |
| 1164 | PAGING_BLOCK_SIZE); | 1675 | reg); |
| 1165 | break; | 1676 | } |
| 1166 | case IWL_FW_INI_REGION_CSR: | ||
| 1167 | size += num_entries * | ||
| 1168 | (hdr_len + le32_to_cpu(reg->size)); | ||
| 1169 | break; | 1677 | break; |
| 1678 | } | ||
| 1170 | case IWL_FW_INI_REGION_DRAM_BUFFER: | 1679 | case IWL_FW_INI_REGION_DRAM_BUFFER: |
| 1171 | /* Transport takes care of DRAM dumping */ | 1680 | if (!fwrt->trans->num_blocks) |
| 1172 | case IWL_FW_INI_REGION_INTERNAL_BUFFER: | 1681 | break; |
| 1682 | size += hdr_len + | ||
| 1683 | iwl_dump_ini_mon_dram_get_size(fwrt, reg); | ||
| 1684 | break; | ||
| 1173 | case IWL_FW_INI_REGION_DRAM_IMR: | 1685 | case IWL_FW_INI_REGION_DRAM_IMR: |
| 1174 | /* Undefined yet */ | 1686 | /* Undefined yet */ |
| 1175 | default: | 1687 | default: |
| @@ -1181,8 +1693,7 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt, | |||
| 1181 | 1693 | ||
| 1182 | static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt, | 1694 | static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt, |
| 1183 | struct iwl_fw_ini_trigger *trigger, | 1695 | struct iwl_fw_ini_trigger *trigger, |
| 1184 | struct iwl_fw_error_dump_data **data, | 1696 | struct iwl_fw_error_dump_data **data) |
| 1185 | u32 *dump_mask) | ||
| 1186 | { | 1697 | { |
| 1187 | int i, num = le32_to_cpu(trigger->num_regions); | 1698 | int i, num = le32_to_cpu(trigger->num_regions); |
| 1188 | 1699 | ||
| @@ -1190,11 +1701,12 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt, | |||
| 1190 | u32 reg_id = le32_to_cpu(trigger->data[i]); | 1701 | u32 reg_id = le32_to_cpu(trigger->data[i]); |
| 1191 | enum iwl_fw_ini_region_type type; | 1702 | enum iwl_fw_ini_region_type type; |
| 1192 | struct iwl_fw_ini_region_cfg *reg; | 1703 | struct iwl_fw_ini_region_cfg *reg; |
| 1704 | struct iwl_dump_ini_mem_ops ops; | ||
| 1193 | 1705 | ||
| 1194 | if (reg_id >= ARRAY_SIZE(fwrt->dump.active_regs)) | 1706 | if (reg_id >= ARRAY_SIZE(fwrt->dump.active_regs)) |
| 1195 | continue; | 1707 | continue; |
| 1196 | 1708 | ||
| 1197 | reg = fwrt->dump.active_regs[reg_id].reg; | 1709 | reg = fwrt->dump.active_regs[reg_id]; |
| 1198 | /* Don't warn, get_trigger_len already warned */ | 1710 | /* Don't warn, get_trigger_len already warned */ |
| 1199 | if (!reg) | 1711 | if (!reg) |
| 1200 | continue; | 1712 | continue; |
| @@ -1202,39 +1714,75 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt, | |||
| 1202 | type = le32_to_cpu(reg->region_type); | 1714 | type = le32_to_cpu(reg->region_type); |
| 1203 | switch (type) { | 1715 | switch (type) { |
| 1204 | case IWL_FW_INI_REGION_DEVICE_MEMORY: | 1716 | case IWL_FW_INI_REGION_DEVICE_MEMORY: |
| 1205 | if (WARN_ON(le32_to_cpu(reg->num_regions) > 1)) | 1717 | case IWL_FW_INI_REGION_INTERNAL_BUFFER: |
| 1206 | continue; | 1718 | ops.get_num_of_ranges = iwl_dump_ini_mem_ranges; |
| 1207 | iwl_fw_dump_named_mem(fwrt, data, | 1719 | ops.get_size = iwl_dump_ini_mem_get_size; |
| 1208 | le32_to_cpu(reg->size), | 1720 | ops.fill_mem_hdr = iwl_dump_ini_mem_fill_header; |
| 1209 | le32_to_cpu(reg->start_addr[0]), | 1721 | ops.fill_range = iwl_dump_ini_dev_mem_iter; |
| 1210 | reg->name, | 1722 | iwl_dump_ini_mem(fwrt, type, data, reg, &ops); |
| 1211 | le32_to_cpu(reg->name_len)); | ||
| 1212 | break; | 1723 | break; |
| 1213 | case IWL_FW_INI_REGION_PERIPHERY_MAC: | 1724 | case IWL_FW_INI_REGION_PERIPHERY_MAC: |
| 1214 | case IWL_FW_INI_REGION_PERIPHERY_PHY: | 1725 | case IWL_FW_INI_REGION_PERIPHERY_PHY: |
| 1215 | case IWL_FW_INI_REGION_PERIPHERY_AUX: | 1726 | case IWL_FW_INI_REGION_PERIPHERY_AUX: |
| 1216 | iwl_dump_prph_ini(fwrt->trans, data, reg); | 1727 | ops.get_num_of_ranges = iwl_dump_ini_mem_ranges; |
| 1728 | ops.get_size = iwl_dump_ini_mem_get_size; | ||
| 1729 | ops.fill_mem_hdr = iwl_dump_ini_mem_fill_header; | ||
| 1730 | ops.fill_range = iwl_dump_ini_prph_iter; | ||
| 1731 | iwl_dump_ini_mem(fwrt, type, data, reg, &ops); | ||
| 1217 | break; | 1732 | break; |
| 1218 | case IWL_FW_INI_REGION_DRAM_BUFFER: | 1733 | case IWL_FW_INI_REGION_DRAM_BUFFER: |
| 1219 | *dump_mask |= BIT(IWL_FW_ERROR_DUMP_FW_MONITOR); | 1734 | ops.get_num_of_ranges = iwl_dump_ini_mon_dram_ranges; |
| 1735 | ops.get_size = iwl_dump_ini_mon_dram_get_size; | ||
| 1736 | ops.fill_mem_hdr = iwl_dump_ini_mon_dram_fill_header; | ||
| 1737 | ops.fill_range = iwl_dump_ini_mon_dram_iter; | ||
| 1738 | iwl_dump_ini_mem(fwrt, type, data, reg, &ops); | ||
| 1220 | break; | 1739 | break; |
| 1221 | case IWL_FW_INI_REGION_PAGING: | 1740 | case IWL_FW_INI_REGION_PAGING: { |
| 1222 | if (iwl_fw_dbg_is_paging_enabled(fwrt)) | 1741 | ops.fill_mem_hdr = iwl_dump_ini_mem_fill_header; |
| 1223 | iwl_dump_paging(fwrt, data); | 1742 | if (iwl_fw_dbg_is_paging_enabled(fwrt)) { |
| 1224 | else | 1743 | ops.get_num_of_ranges = |
| 1225 | *dump_mask |= BIT(IWL_FW_ERROR_DUMP_PAGING); | 1744 | iwl_dump_ini_paging_ranges; |
| 1745 | ops.get_size = iwl_dump_ini_paging_get_size; | ||
| 1746 | ops.fill_range = iwl_dump_ini_paging_iter; | ||
| 1747 | } else { | ||
| 1748 | ops.get_num_of_ranges = | ||
| 1749 | iwl_dump_ini_paging_gen2_ranges; | ||
| 1750 | ops.get_size = | ||
| 1751 | iwl_dump_ini_paging_gen2_get_size; | ||
| 1752 | ops.fill_range = iwl_dump_ini_paging_gen2_iter; | ||
| 1753 | } | ||
| 1754 | |||
| 1755 | iwl_dump_ini_mem(fwrt, type, data, reg, &ops); | ||
| 1226 | break; | 1756 | break; |
| 1227 | case IWL_FW_INI_REGION_TXF: | 1757 | } |
| 1228 | iwl_fw_dump_txf(fwrt, data); | 1758 | case IWL_FW_INI_REGION_TXF: { |
| 1759 | struct iwl_ini_txf_iter_data iter = { .init = true }; | ||
| 1760 | void *fifo_iter = fwrt->dump.fifo_iter; | ||
| 1761 | |||
| 1762 | fwrt->dump.fifo_iter = &iter; | ||
| 1763 | ops.get_num_of_ranges = iwl_dump_ini_txf_ranges; | ||
| 1764 | ops.get_size = iwl_dump_ini_txf_get_size; | ||
| 1765 | ops.fill_mem_hdr = iwl_dump_ini_fifo_fill_header; | ||
| 1766 | ops.fill_range = iwl_dump_ini_txf_iter; | ||
| 1767 | iwl_dump_ini_mem(fwrt, type, data, reg, &ops); | ||
| 1768 | fwrt->dump.fifo_iter = fifo_iter; | ||
| 1229 | break; | 1769 | break; |
| 1770 | } | ||
| 1230 | case IWL_FW_INI_REGION_RXF: | 1771 | case IWL_FW_INI_REGION_RXF: |
| 1231 | iwl_fw_dump_rxf(fwrt, data); | 1772 | ops.get_num_of_ranges = iwl_dump_ini_rxf_ranges; |
| 1773 | ops.get_size = iwl_dump_ini_rxf_get_size; | ||
| 1774 | ops.fill_mem_hdr = iwl_dump_ini_fifo_fill_header; | ||
| 1775 | ops.fill_range = iwl_dump_ini_rxf_iter; | ||
| 1776 | iwl_dump_ini_mem(fwrt, type, data, reg, &ops); | ||
| 1232 | break; | 1777 | break; |
| 1233 | case IWL_FW_INI_REGION_CSR: | 1778 | case IWL_FW_INI_REGION_CSR: |
| 1234 | iwl_dump_csr_ini(fwrt->trans, data, reg); | 1779 | ops.get_num_of_ranges = iwl_dump_ini_mem_ranges; |
| 1780 | ops.get_size = iwl_dump_ini_mem_get_size; | ||
| 1781 | ops.fill_mem_hdr = iwl_dump_ini_mem_fill_header; | ||
| 1782 | ops.fill_range = iwl_dump_ini_csr_iter; | ||
| 1783 | iwl_dump_ini_mem(fwrt, type, data, reg, &ops); | ||
| 1235 | break; | 1784 | break; |
| 1236 | case IWL_FW_INI_REGION_DRAM_IMR: | 1785 | case IWL_FW_INI_REGION_DRAM_IMR: |
| 1237 | case IWL_FW_INI_REGION_INTERNAL_BUFFER: | ||
| 1238 | /* This is undefined yet */ | 1786 | /* This is undefined yet */ |
| 1239 | default: | 1787 | default: |
| 1240 | break; | 1788 | break; |
| @@ -1244,26 +1792,23 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt, | |||
| 1244 | 1792 | ||
| 1245 | static struct iwl_fw_error_dump_file * | 1793 | static struct iwl_fw_error_dump_file * |
| 1246 | _iwl_fw_error_ini_dump(struct iwl_fw_runtime *fwrt, | 1794 | _iwl_fw_error_ini_dump(struct iwl_fw_runtime *fwrt, |
| 1247 | struct iwl_fw_dump_ptrs *fw_error_dump, | 1795 | struct iwl_fw_dump_ptrs *fw_error_dump) |
| 1248 | u32 *dump_mask) | ||
| 1249 | { | 1796 | { |
| 1250 | int size, id = le32_to_cpu(fwrt->dump.desc->trig_desc.type); | 1797 | int size, id = le32_to_cpu(fwrt->dump.desc->trig_desc.type); |
| 1251 | struct iwl_fw_error_dump_data *dump_data; | 1798 | struct iwl_fw_error_dump_data *dump_data; |
| 1252 | struct iwl_fw_error_dump_file *dump_file; | 1799 | struct iwl_fw_error_dump_file *dump_file; |
| 1253 | struct iwl_fw_ini_trigger *trigger, *ext; | 1800 | struct iwl_fw_ini_trigger *trigger; |
| 1254 | 1801 | ||
| 1255 | if (id == FW_DBG_TRIGGER_FW_ASSERT) | 1802 | if (id == FW_DBG_TRIGGER_FW_ASSERT) |
| 1256 | id = IWL_FW_TRIGGER_ID_FW_ASSERT; | 1803 | id = IWL_FW_TRIGGER_ID_FW_ASSERT; |
| 1257 | 1804 | ||
| 1258 | if (WARN_ON(id >= ARRAY_SIZE(fwrt->dump.active_trigs))) | 1805 | if (!iwl_fw_ini_trigger_on(fwrt, id)) |
| 1259 | return NULL; | 1806 | return NULL; |
| 1260 | 1807 | ||
| 1261 | trigger = fwrt->dump.active_trigs[id].conf; | 1808 | trigger = fwrt->dump.active_trigs[id].trig; |
| 1262 | ext = fwrt->dump.active_trigs[id].conf_ext; | ||
| 1263 | 1809 | ||
| 1264 | size = sizeof(*dump_file); | 1810 | size = sizeof(*dump_file); |
| 1265 | size += iwl_fw_ini_get_trigger_len(fwrt, trigger); | 1811 | size += iwl_fw_ini_get_trigger_len(fwrt, trigger); |
| 1266 | size += iwl_fw_ini_get_trigger_len(fwrt, ext); | ||
| 1267 | 1812 | ||
| 1268 | if (!size) | 1813 | if (!size) |
| 1269 | return NULL; | 1814 | return NULL; |
| @@ -1278,11 +1823,7 @@ _iwl_fw_error_ini_dump(struct iwl_fw_runtime *fwrt, | |||
| 1278 | dump_data = (void *)dump_file->data; | 1823 | dump_data = (void *)dump_file->data; |
| 1279 | dump_file->file_len = cpu_to_le32(size); | 1824 | dump_file->file_len = cpu_to_le32(size); |
| 1280 | 1825 | ||
| 1281 | *dump_mask = 0; | 1826 | iwl_fw_ini_dump_trigger(fwrt, trigger, &dump_data); |
| 1282 | if (trigger) | ||
| 1283 | iwl_fw_ini_dump_trigger(fwrt, trigger, &dump_data, dump_mask); | ||
| 1284 | if (ext) | ||
| 1285 | iwl_fw_ini_dump_trigger(fwrt, ext, &dump_data, dump_mask); | ||
| 1286 | 1827 | ||
| 1287 | return dump_file; | 1828 | return dump_file; |
| 1288 | } | 1829 | } |
| @@ -1308,8 +1849,7 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt) | |||
| 1308 | goto out; | 1849 | goto out; |
| 1309 | 1850 | ||
| 1310 | if (fwrt->trans->ini_valid) | 1851 | if (fwrt->trans->ini_valid) |
| 1311 | dump_file = _iwl_fw_error_ini_dump(fwrt, fw_error_dump, | 1852 | dump_file = _iwl_fw_error_ini_dump(fwrt, fw_error_dump); |
| 1312 | &dump_mask); | ||
| 1313 | else | 1853 | else |
| 1314 | dump_file = _iwl_fw_error_dump(fwrt, fw_error_dump); | 1854 | dump_file = _iwl_fw_error_dump(fwrt, fw_error_dump); |
| 1315 | 1855 | ||
| @@ -1321,7 +1861,10 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt) | |||
| 1321 | if (!fwrt->trans->ini_valid && fwrt->dump.monitor_only) | 1861 | if (!fwrt->trans->ini_valid && fwrt->dump.monitor_only) |
| 1322 | dump_mask &= IWL_FW_ERROR_DUMP_FW_MONITOR; | 1862 | dump_mask &= IWL_FW_ERROR_DUMP_FW_MONITOR; |
| 1323 | 1863 | ||
| 1324 | fw_error_dump->trans_ptr = iwl_trans_dump_data(fwrt->trans, dump_mask); | 1864 | if (!fwrt->trans->ini_valid) |
| 1865 | fw_error_dump->trans_ptr = | ||
| 1866 | iwl_trans_dump_data(fwrt->trans, dump_mask); | ||
| 1867 | |||
| 1325 | file_len = le32_to_cpu(dump_file->file_len); | 1868 | file_len = le32_to_cpu(dump_file->file_len); |
| 1326 | fw_error_dump->fwrt_len = file_len; | 1869 | fw_error_dump->fwrt_len = file_len; |
| 1327 | if (fw_error_dump->trans_ptr) { | 1870 | if (fw_error_dump->trans_ptr) { |
| @@ -1362,61 +1905,12 @@ const struct iwl_fw_dump_desc iwl_dump_desc_assert = { | |||
| 1362 | }; | 1905 | }; |
| 1363 | IWL_EXPORT_SYMBOL(iwl_dump_desc_assert); | 1906 | IWL_EXPORT_SYMBOL(iwl_dump_desc_assert); |
| 1364 | 1907 | ||
| 1365 | void iwl_fw_assert_error_dump(struct iwl_fw_runtime *fwrt) | ||
| 1366 | { | ||
| 1367 | IWL_INFO(fwrt, "error dump due to fw assert\n"); | ||
| 1368 | fwrt->dump.desc = &iwl_dump_desc_assert; | ||
| 1369 | iwl_fw_error_dump(fwrt); | ||
| 1370 | } | ||
| 1371 | IWL_EXPORT_SYMBOL(iwl_fw_assert_error_dump); | ||
| 1372 | |||
| 1373 | void iwl_fw_alive_error_dump(struct iwl_fw_runtime *fwrt) | ||
| 1374 | { | ||
| 1375 | struct iwl_fw_dump_desc *iwl_dump_desc_no_alive = | ||
| 1376 | kmalloc(sizeof(*iwl_dump_desc_no_alive), GFP_KERNEL); | ||
| 1377 | |||
| 1378 | if (!iwl_dump_desc_no_alive) | ||
| 1379 | return; | ||
| 1380 | |||
| 1381 | iwl_dump_desc_no_alive->trig_desc.type = | ||
| 1382 | cpu_to_le32(FW_DBG_TRIGGER_NO_ALIVE); | ||
| 1383 | iwl_dump_desc_no_alive->len = 0; | ||
| 1384 | |||
| 1385 | if (WARN_ON(fwrt->dump.desc)) | ||
| 1386 | iwl_fw_free_dump_desc(fwrt); | ||
| 1387 | |||
| 1388 | IWL_WARN(fwrt, "Collecting data: trigger %d fired.\n", | ||
| 1389 | FW_DBG_TRIGGER_NO_ALIVE); | ||
| 1390 | |||
| 1391 | fwrt->dump.desc = iwl_dump_desc_no_alive; | ||
| 1392 | iwl_fw_error_dump(fwrt); | ||
| 1393 | clear_bit(IWL_FWRT_STATUS_WAIT_ALIVE, &fwrt->status); | ||
| 1394 | } | ||
| 1395 | IWL_EXPORT_SYMBOL(iwl_fw_alive_error_dump); | ||
| 1396 | |||
| 1397 | int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt, | 1908 | int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt, |
| 1398 | const struct iwl_fw_dump_desc *desc, | 1909 | const struct iwl_fw_dump_desc *desc, |
| 1399 | bool monitor_only, | 1910 | bool monitor_only, |
| 1400 | unsigned int delay) | 1911 | unsigned int delay) |
| 1401 | { | 1912 | { |
| 1402 | /* | 1913 | if (test_and_set_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status)) |
| 1403 | * If the loading of the FW completed successfully, the next step is to | ||
| 1404 | * get the SMEM config data. Thus, if fwrt->smem_cfg.num_lmacs is non | ||
| 1405 | * zero, the FW was already loaded successully. If the state is "NO_FW" | ||
| 1406 | * in such a case - exit, since FW may be dead. Otherwise, we | ||
| 1407 | * can try to collect the data, since FW might just not be fully | ||
| 1408 | * loaded (no "ALIVE" yet), and the debug data is accessible. | ||
| 1409 | * | ||
| 1410 | * Corner case: got the FW alive but crashed before getting the SMEM | ||
| 1411 | * config. In such a case, due to HW access problems, we might | ||
| 1412 | * collect garbage. | ||
| 1413 | */ | ||
| 1414 | if (fwrt->trans->state == IWL_TRANS_NO_FW && | ||
| 1415 | fwrt->smem_cfg.num_lmacs) | ||
| 1416 | return -EIO; | ||
| 1417 | |||
| 1418 | if (test_and_set_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status) || | ||
| 1419 | test_bit(IWL_FWRT_STATUS_WAIT_ALIVE, &fwrt->status)) | ||
| 1420 | return -EBUSY; | 1914 | return -EBUSY; |
| 1421 | 1915 | ||
| 1422 | if (WARN_ON(fwrt->dump.desc)) | 1916 | if (WARN_ON(fwrt->dump.desc)) |
| @@ -1428,12 +1922,39 @@ int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt, | |||
| 1428 | fwrt->dump.desc = desc; | 1922 | fwrt->dump.desc = desc; |
| 1429 | fwrt->dump.monitor_only = monitor_only; | 1923 | fwrt->dump.monitor_only = monitor_only; |
| 1430 | 1924 | ||
| 1431 | schedule_delayed_work(&fwrt->dump.wk, delay); | 1925 | schedule_delayed_work(&fwrt->dump.wk, usecs_to_jiffies(delay)); |
| 1432 | 1926 | ||
| 1433 | return 0; | 1927 | return 0; |
| 1434 | } | 1928 | } |
| 1435 | IWL_EXPORT_SYMBOL(iwl_fw_dbg_collect_desc); | 1929 | IWL_EXPORT_SYMBOL(iwl_fw_dbg_collect_desc); |
| 1436 | 1930 | ||
| 1931 | int iwl_fw_dbg_error_collect(struct iwl_fw_runtime *fwrt, | ||
| 1932 | enum iwl_fw_dbg_trigger trig_type) | ||
| 1933 | { | ||
| 1934 | int ret; | ||
| 1935 | struct iwl_fw_dump_desc *iwl_dump_error_desc = | ||
| 1936 | kmalloc(sizeof(*iwl_dump_error_desc), GFP_KERNEL); | ||
| 1937 | |||
| 1938 | if (!iwl_dump_error_desc) | ||
| 1939 | return -ENOMEM; | ||
| 1940 | |||
| 1941 | iwl_dump_error_desc->trig_desc.type = cpu_to_le32(trig_type); | ||
| 1942 | iwl_dump_error_desc->len = 0; | ||
| 1943 | |||
| 1944 | ret = iwl_fw_dbg_collect_desc(fwrt, iwl_dump_error_desc, false, 0); | ||
| 1945 | if (ret) { | ||
| 1946 | kfree(iwl_dump_error_desc); | ||
| 1947 | } else { | ||
| 1948 | set_bit(STATUS_FW_WAIT_DUMP, &fwrt->trans->status); | ||
| 1949 | |||
| 1950 | /* trigger nmi to halt the fw */ | ||
| 1951 | iwl_force_nmi(fwrt->trans); | ||
| 1952 | } | ||
| 1953 | |||
| 1954 | return ret; | ||
| 1955 | } | ||
| 1956 | IWL_EXPORT_SYMBOL(iwl_fw_dbg_error_collect); | ||
| 1957 | |||
| 1437 | int _iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt, | 1958 | int _iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt, |
| 1438 | enum iwl_fw_dbg_trigger trig, | 1959 | enum iwl_fw_dbg_trigger trig, |
| 1439 | const char *str, size_t len, | 1960 | const char *str, size_t len, |
| @@ -1457,8 +1978,10 @@ int _iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt, | |||
| 1457 | } | 1978 | } |
| 1458 | 1979 | ||
| 1459 | trigger->occurrences = cpu_to_le16(occurrences); | 1980 | trigger->occurrences = cpu_to_le16(occurrences); |
| 1460 | delay = le16_to_cpu(trigger->trig_dis_ms); | ||
| 1461 | monitor_only = trigger->mode & IWL_FW_DBG_TRIGGER_MONITOR_ONLY; | 1981 | monitor_only = trigger->mode & IWL_FW_DBG_TRIGGER_MONITOR_ONLY; |
| 1982 | |||
| 1983 | /* convert msec to usec */ | ||
| 1984 | delay = le32_to_cpu(trigger->stop_delay) * USEC_PER_MSEC; | ||
| 1462 | } | 1985 | } |
| 1463 | 1986 | ||
| 1464 | desc = kzalloc(sizeof(*desc) + len, GFP_ATOMIC); | 1987 | desc = kzalloc(sizeof(*desc) + len, GFP_ATOMIC); |
| @@ -1478,6 +2001,7 @@ int iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt, | |||
| 1478 | u32 id, const char *str, size_t len) | 2001 | u32 id, const char *str, size_t len) |
| 1479 | { | 2002 | { |
| 1480 | struct iwl_fw_dump_desc *desc; | 2003 | struct iwl_fw_dump_desc *desc; |
| 2004 | struct iwl_fw_ini_active_triggers *active; | ||
| 1481 | u32 occur, delay; | 2005 | u32 occur, delay; |
| 1482 | 2006 | ||
| 1483 | if (!fwrt->trans->ini_valid) | 2007 | if (!fwrt->trans->ini_valid) |
| @@ -1486,15 +2010,17 @@ int iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt, | |||
| 1486 | if (id == FW_DBG_TRIGGER_USER) | 2010 | if (id == FW_DBG_TRIGGER_USER) |
| 1487 | id = IWL_FW_TRIGGER_ID_USER_TRIGGER; | 2011 | id = IWL_FW_TRIGGER_ID_USER_TRIGGER; |
| 1488 | 2012 | ||
| 1489 | if (WARN_ON(!fwrt->dump.active_trigs[id].active)) | 2013 | active = &fwrt->dump.active_trigs[id]; |
| 2014 | |||
| 2015 | if (WARN_ON(!active->active)) | ||
| 1490 | return -EINVAL; | 2016 | return -EINVAL; |
| 1491 | 2017 | ||
| 1492 | delay = le32_to_cpu(fwrt->dump.active_trigs[id].conf->dump_delay); | 2018 | delay = le32_to_cpu(active->trig->dump_delay); |
| 1493 | occur = le32_to_cpu(fwrt->dump.active_trigs[id].conf->occurrences); | 2019 | occur = le32_to_cpu(active->trig->occurrences); |
| 1494 | if (!occur) | 2020 | if (!occur) |
| 1495 | return 0; | 2021 | return 0; |
| 1496 | 2022 | ||
| 1497 | if (le32_to_cpu(fwrt->dump.active_trigs[id].conf->force_restart)) { | 2023 | if (le32_to_cpu(active->trig->force_restart)) { |
| 1498 | IWL_WARN(fwrt, "Force restart: trigger %d fired.\n", id); | 2024 | IWL_WARN(fwrt, "Force restart: trigger %d fired.\n", id); |
| 1499 | iwl_force_nmi(fwrt->trans); | 2025 | iwl_force_nmi(fwrt->trans); |
| 1500 | return 0; | 2026 | return 0; |
| @@ -1504,8 +2030,7 @@ int iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt, | |||
| 1504 | if (!desc) | 2030 | if (!desc) |
| 1505 | return -ENOMEM; | 2031 | return -ENOMEM; |
| 1506 | 2032 | ||
| 1507 | occur--; | 2033 | active->trig->occurrences = cpu_to_le32(--occur); |
| 1508 | fwrt->dump.active_trigs[id].conf->occurrences = cpu_to_le32(occur); | ||
| 1509 | 2034 | ||
| 1510 | desc->len = len; | 2035 | desc->len = len; |
| 1511 | desc->trig_desc.type = cpu_to_le32(id); | 2036 | desc->trig_desc.type = cpu_to_le32(id); |
| @@ -1670,27 +2195,13 @@ void iwl_fw_dbg_read_d3_debug_data(struct iwl_fw_runtime *fwrt) | |||
| 1670 | IWL_EXPORT_SYMBOL(iwl_fw_dbg_read_d3_debug_data); | 2195 | IWL_EXPORT_SYMBOL(iwl_fw_dbg_read_d3_debug_data); |
| 1671 | 2196 | ||
| 1672 | static void | 2197 | static void |
| 1673 | iwl_fw_dbg_buffer_allocation(struct iwl_fw_runtime *fwrt, | 2198 | iwl_fw_dbg_buffer_allocation(struct iwl_fw_runtime *fwrt, u32 size) |
| 1674 | struct iwl_fw_ini_allocation_tlv *alloc) | ||
| 1675 | { | 2199 | { |
| 1676 | struct iwl_trans *trans = fwrt->trans; | 2200 | struct iwl_trans *trans = fwrt->trans; |
| 1677 | struct iwl_ldbg_config_cmd ldbg_cmd = { | ||
| 1678 | .type = cpu_to_le32(BUFFER_ALLOCATION), | ||
| 1679 | }; | ||
| 1680 | struct iwl_buffer_allocation_cmd *cmd = &ldbg_cmd.buffer_allocation; | ||
| 1681 | struct iwl_host_cmd hcmd = { | ||
| 1682 | .id = LDBG_CONFIG_CMD, | ||
| 1683 | .flags = CMD_ASYNC, | ||
| 1684 | .data[0] = &ldbg_cmd, | ||
| 1685 | .len[0] = sizeof(ldbg_cmd), | ||
| 1686 | }; | ||
| 1687 | void *virtual_addr = NULL; | 2201 | void *virtual_addr = NULL; |
| 1688 | u32 size = le32_to_cpu(alloc->size); | ||
| 1689 | dma_addr_t phys_addr; | 2202 | dma_addr_t phys_addr; |
| 1690 | 2203 | ||
| 1691 | if (!trans->num_blocks && | 2204 | if (WARN_ON_ONCE(trans->num_blocks == ARRAY_SIZE(trans->fw_mon))) |
| 1692 | le32_to_cpu(alloc->buffer_location) != | ||
| 1693 | IWL_FW_INI_LOCATION_DRAM_PATH) | ||
| 1694 | return; | 2205 | return; |
| 1695 | 2206 | ||
| 1696 | virtual_addr = | 2207 | virtual_addr = |
| @@ -1702,25 +2213,63 @@ iwl_fw_dbg_buffer_allocation(struct iwl_fw_runtime *fwrt, | |||
| 1702 | if (!virtual_addr) | 2213 | if (!virtual_addr) |
| 1703 | IWL_ERR(fwrt, "Failed to allocate debug memory\n"); | 2214 | IWL_ERR(fwrt, "Failed to allocate debug memory\n"); |
| 1704 | 2215 | ||
| 1705 | if (WARN_ON_ONCE(trans->num_blocks == ARRAY_SIZE(trans->fw_mon))) | ||
| 1706 | return; | ||
| 1707 | |||
| 1708 | trans->fw_mon[trans->num_blocks].block = virtual_addr; | 2216 | trans->fw_mon[trans->num_blocks].block = virtual_addr; |
| 1709 | trans->fw_mon[trans->num_blocks].physical = phys_addr; | 2217 | trans->fw_mon[trans->num_blocks].physical = phys_addr; |
| 1710 | trans->fw_mon[trans->num_blocks].size = size; | 2218 | trans->fw_mon[trans->num_blocks].size = size; |
| 1711 | trans->num_blocks++; | 2219 | trans->num_blocks++; |
| 1712 | 2220 | ||
| 1713 | IWL_DEBUG_FW(trans, "Allocated debug block of size %d\n", size); | 2221 | IWL_DEBUG_FW(trans, "Allocated debug block of size %d\n", size); |
| 2222 | } | ||
| 2223 | |||
| 2224 | static void iwl_fw_dbg_buffer_apply(struct iwl_fw_runtime *fwrt, | ||
| 2225 | struct iwl_fw_ini_allocation_data *alloc, | ||
| 2226 | enum iwl_fw_ini_apply_point pnt) | ||
| 2227 | { | ||
| 2228 | struct iwl_trans *trans = fwrt->trans; | ||
| 2229 | struct iwl_ldbg_config_cmd ldbg_cmd = { | ||
| 2230 | .type = cpu_to_le32(BUFFER_ALLOCATION), | ||
| 2231 | }; | ||
| 2232 | struct iwl_buffer_allocation_cmd *cmd = &ldbg_cmd.buffer_allocation; | ||
| 2233 | struct iwl_host_cmd hcmd = { | ||
| 2234 | .id = LDBG_CONFIG_CMD, | ||
| 2235 | .flags = CMD_ASYNC, | ||
| 2236 | .data[0] = &ldbg_cmd, | ||
| 2237 | .len[0] = sizeof(ldbg_cmd), | ||
| 2238 | }; | ||
| 2239 | int block_idx = trans->num_blocks; | ||
| 2240 | u32 buf_location = le32_to_cpu(alloc->tlv.buffer_location); | ||
| 2241 | |||
| 2242 | if (buf_location == IWL_FW_INI_LOCATION_SRAM_PATH) { | ||
| 2243 | if (!WARN(pnt != IWL_FW_INI_APPLY_EARLY, | ||
| 2244 | "Invalid apply point %d for SMEM buffer allocation", | ||
| 2245 | pnt)) | ||
| 2246 | /* set sram monitor by enabling bit 7 */ | ||
| 2247 | iwl_set_bit(fwrt->trans, CSR_HW_IF_CONFIG_REG, | ||
| 2248 | CSR_HW_IF_CONFIG_REG_BIT_MONITOR_SRAM); | ||
| 2249 | return; | ||
| 2250 | } | ||
| 2251 | |||
| 2252 | if (buf_location != IWL_FW_INI_LOCATION_DRAM_PATH) | ||
| 2253 | return; | ||
| 2254 | |||
| 2255 | if (!alloc->is_alloc) { | ||
| 2256 | iwl_fw_dbg_buffer_allocation(fwrt, | ||
| 2257 | le32_to_cpu(alloc->tlv.size)); | ||
| 2258 | if (block_idx == trans->num_blocks) | ||
| 2259 | return; | ||
| 2260 | alloc->is_alloc = 1; | ||
| 2261 | } | ||
| 1714 | 2262 | ||
| 1715 | /* First block is assigned via registers / context info */ | 2263 | /* First block is assigned via registers / context info */ |
| 1716 | if (trans->num_blocks == 1) | 2264 | if (trans->num_blocks == 1) |
| 1717 | return; | 2265 | return; |
| 1718 | 2266 | ||
| 1719 | cmd->num_frags = cpu_to_le32(1); | 2267 | cmd->num_frags = cpu_to_le32(1); |
| 1720 | cmd->fragments[0].address = cpu_to_le64(phys_addr); | 2268 | cmd->fragments[0].address = |
| 1721 | cmd->fragments[0].size = alloc->size; | 2269 | cpu_to_le64(trans->fw_mon[block_idx].physical); |
| 1722 | cmd->allocation_id = alloc->allocation_id; | 2270 | cmd->fragments[0].size = alloc->tlv.size; |
| 1723 | cmd->buffer_location = alloc->buffer_location; | 2271 | cmd->allocation_id = alloc->tlv.allocation_id; |
| 2272 | cmd->buffer_location = alloc->tlv.buffer_location; | ||
| 1724 | 2273 | ||
| 1725 | iwl_trans_send_cmd(trans, &hcmd); | 2274 | iwl_trans_send_cmd(trans, &hcmd); |
| 1726 | } | 2275 | } |
| @@ -1749,9 +2298,9 @@ static void iwl_fw_dbg_update_regions(struct iwl_fw_runtime *fwrt, | |||
| 1749 | int i, size = le32_to_cpu(tlv->num_regions); | 2298 | int i, size = le32_to_cpu(tlv->num_regions); |
| 1750 | 2299 | ||
| 1751 | for (i = 0; i < size; i++) { | 2300 | for (i = 0; i < size; i++) { |
| 1752 | struct iwl_fw_ini_region_cfg *reg = iter; | 2301 | struct iwl_fw_ini_region_cfg *reg = iter, **active; |
| 1753 | int id = le32_to_cpu(reg->region_id); | 2302 | int id = le32_to_cpu(reg->region_id); |
| 1754 | struct iwl_fw_ini_active_regs *active; | 2303 | u32 type = le32_to_cpu(reg->region_type); |
| 1755 | 2304 | ||
| 1756 | if (WARN(id >= ARRAY_SIZE(fwrt->dump.active_regs), | 2305 | if (WARN(id >= ARRAY_SIZE(fwrt->dump.active_regs), |
| 1757 | "Invalid region id %d for apply point %d\n", id, pnt)) | 2306 | "Invalid region id %d for apply point %d\n", id, pnt)) |
| @@ -1759,26 +2308,47 @@ static void iwl_fw_dbg_update_regions(struct iwl_fw_runtime *fwrt, | |||
| 1759 | 2308 | ||
| 1760 | active = &fwrt->dump.active_regs[id]; | 2309 | active = &fwrt->dump.active_regs[id]; |
| 1761 | 2310 | ||
| 1762 | if (ext && active->apply_point == pnt) | 2311 | if (*active) |
| 1763 | IWL_WARN(fwrt->trans, | 2312 | IWL_WARN(fwrt->trans, "region TLV %d override\n", id); |
| 1764 | "External region TLV overrides FW default %x\n", | ||
| 1765 | id); | ||
| 1766 | 2313 | ||
| 1767 | IWL_DEBUG_FW(fwrt, | 2314 | IWL_DEBUG_FW(fwrt, |
| 1768 | "%s: apply point %d, activating region ID %d\n", | 2315 | "%s: apply point %d, activating region ID %d\n", |
| 1769 | __func__, pnt, id); | 2316 | __func__, pnt, id); |
| 1770 | 2317 | ||
| 1771 | active->reg = reg; | 2318 | *active = reg; |
| 1772 | active->apply_point = pnt; | ||
| 1773 | 2319 | ||
| 1774 | if (le32_to_cpu(reg->region_type) != | 2320 | if (type == IWL_FW_INI_REGION_TXF || |
| 1775 | IWL_FW_INI_REGION_DRAM_BUFFER) | 2321 | type == IWL_FW_INI_REGION_RXF) |
| 1776 | iter += le32_to_cpu(reg->num_regions) * sizeof(__le32); | 2322 | iter += le32_to_cpu(reg->fifos.num_of_registers) * |
| 2323 | sizeof(__le32); | ||
| 2324 | else if (type != IWL_FW_INI_REGION_DRAM_BUFFER) | ||
| 2325 | iter += le32_to_cpu(reg->internal.num_of_ranges) * | ||
| 2326 | sizeof(__le32); | ||
| 1777 | 2327 | ||
| 1778 | iter += sizeof(*reg); | 2328 | iter += sizeof(*reg); |
| 1779 | } | 2329 | } |
| 1780 | } | 2330 | } |
| 1781 | 2331 | ||
| 2332 | static int iwl_fw_dbg_trig_realloc(struct iwl_fw_runtime *fwrt, | ||
| 2333 | struct iwl_fw_ini_active_triggers *active, | ||
| 2334 | u32 id, int size) | ||
| 2335 | { | ||
| 2336 | void *ptr; | ||
| 2337 | |||
| 2338 | if (size <= active->size) | ||
| 2339 | return 0; | ||
| 2340 | |||
| 2341 | ptr = krealloc(active->trig, size, GFP_KERNEL); | ||
| 2342 | if (!ptr) { | ||
| 2343 | IWL_ERR(fwrt, "Failed to allocate memory for trigger %d\n", id); | ||
| 2344 | return -ENOMEM; | ||
| 2345 | } | ||
| 2346 | active->trig = ptr; | ||
| 2347 | active->size = size; | ||
| 2348 | |||
| 2349 | return 0; | ||
| 2350 | } | ||
| 2351 | |||
| 1782 | static void iwl_fw_dbg_update_triggers(struct iwl_fw_runtime *fwrt, | 2352 | static void iwl_fw_dbg_update_triggers(struct iwl_fw_runtime *fwrt, |
| 1783 | struct iwl_fw_ini_trigger_tlv *tlv, | 2353 | struct iwl_fw_ini_trigger_tlv *tlv, |
| 1784 | bool ext, | 2354 | bool ext, |
| @@ -1791,43 +2361,61 @@ static void iwl_fw_dbg_update_triggers(struct iwl_fw_runtime *fwrt, | |||
| 1791 | struct iwl_fw_ini_trigger *trig = iter; | 2361 | struct iwl_fw_ini_trigger *trig = iter; |
| 1792 | struct iwl_fw_ini_active_triggers *active; | 2362 | struct iwl_fw_ini_active_triggers *active; |
| 1793 | int id = le32_to_cpu(trig->trigger_id); | 2363 | int id = le32_to_cpu(trig->trigger_id); |
| 1794 | u32 num; | 2364 | u32 trig_regs_size = le32_to_cpu(trig->num_regions) * |
| 2365 | sizeof(__le32); | ||
| 1795 | 2366 | ||
| 1796 | if (WARN_ON(id >= ARRAY_SIZE(fwrt->dump.active_trigs))) | 2367 | if (WARN_ON(id >= ARRAY_SIZE(fwrt->dump.active_trigs))) |
| 1797 | break; | 2368 | break; |
| 1798 | 2369 | ||
| 1799 | active = &fwrt->dump.active_trigs[id]; | 2370 | active = &fwrt->dump.active_trigs[id]; |
| 1800 | 2371 | ||
| 1801 | if (active->apply_point != apply_point) { | 2372 | if (!active->active) { |
| 1802 | active->conf = NULL; | 2373 | size_t trig_size = sizeof(*trig) + trig_regs_size; |
| 1803 | active->conf_ext = NULL; | ||
| 1804 | } | ||
| 1805 | 2374 | ||
| 1806 | num = le32_to_cpu(trig->num_regions); | 2375 | if (iwl_fw_dbg_trig_realloc(fwrt, active, id, |
| 2376 | trig_size)) | ||
| 2377 | goto next; | ||
| 1807 | 2378 | ||
| 1808 | if (ext && active->apply_point == apply_point) { | 2379 | memcpy(active->trig, trig, trig_size); |
| 1809 | num += le32_to_cpu(active->conf->num_regions); | 2380 | |
| 1810 | if (trig->ignore_default) { | 2381 | } else { |
| 1811 | active->conf_ext = active->conf; | 2382 | u32 conf_override = |
| 1812 | active->conf = trig; | 2383 | !(le32_to_cpu(trig->override_trig) & 0xff); |
| 2384 | u32 region_override = | ||
| 2385 | !(le32_to_cpu(trig->override_trig) & 0xff00); | ||
| 2386 | u32 offset = 0; | ||
| 2387 | u32 active_regs = | ||
| 2388 | le32_to_cpu(active->trig->num_regions); | ||
| 2389 | u32 new_regs = le32_to_cpu(trig->num_regions); | ||
| 2390 | int mem_to_add = trig_regs_size; | ||
| 2391 | |||
| 2392 | if (region_override) { | ||
| 2393 | mem_to_add -= active_regs * sizeof(__le32); | ||
| 1813 | } else { | 2394 | } else { |
| 1814 | active->conf_ext = trig; | 2395 | offset += active_regs; |
| 2396 | new_regs += active_regs; | ||
| 1815 | } | 2397 | } |
| 1816 | } else { | 2398 | |
| 1817 | active->conf = trig; | 2399 | if (iwl_fw_dbg_trig_realloc(fwrt, active, id, |
| 2400 | active->size + mem_to_add)) | ||
| 2401 | goto next; | ||
| 2402 | |||
| 2403 | if (conf_override) | ||
| 2404 | memcpy(active->trig, trig, sizeof(*trig)); | ||
| 2405 | |||
| 2406 | memcpy(active->trig->data + offset, trig->data, | ||
| 2407 | trig_regs_size); | ||
| 2408 | active->trig->num_regions = cpu_to_le32(new_regs); | ||
| 1818 | } | 2409 | } |
| 1819 | 2410 | ||
| 1820 | /* Since zero means infinity - just set to -1 */ | 2411 | /* Since zero means infinity - just set to -1 */ |
| 1821 | if (!le32_to_cpu(trig->occurrences)) | 2412 | if (!le32_to_cpu(active->trig->occurrences)) |
| 1822 | trig->occurrences = cpu_to_le32(-1); | 2413 | active->trig->occurrences = cpu_to_le32(-1); |
| 1823 | if (!le32_to_cpu(trig->ignore_consec)) | ||
| 1824 | trig->ignore_consec = cpu_to_le32(-1); | ||
| 1825 | 2414 | ||
| 1826 | iter += sizeof(*trig) + | 2415 | active->active = true; |
| 1827 | le32_to_cpu(trig->num_regions) * sizeof(__le32); | 2416 | next: |
| 2417 | iter += sizeof(*trig) + trig_regs_size; | ||
| 1828 | 2418 | ||
| 1829 | active->active = num; | ||
| 1830 | active->apply_point = apply_point; | ||
| 1831 | } | 2419 | } |
| 1832 | } | 2420 | } |
| 1833 | 2421 | ||
| @@ -1844,9 +2432,13 @@ static void _iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt, | |||
| 1844 | u32 type = le32_to_cpu(tlv->type); | 2432 | u32 type = le32_to_cpu(tlv->type); |
| 1845 | 2433 | ||
| 1846 | switch (type) { | 2434 | switch (type) { |
| 1847 | case IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION: | 2435 | case IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION: { |
| 1848 | iwl_fw_dbg_buffer_allocation(fwrt, ini_tlv); | 2436 | struct iwl_fw_ini_allocation_data *buf_alloc = ini_tlv; |
| 2437 | |||
| 2438 | iwl_fw_dbg_buffer_apply(fwrt, ini_tlv, pnt); | ||
| 2439 | iter += sizeof(buf_alloc->is_alloc); | ||
| 1849 | break; | 2440 | break; |
| 2441 | } | ||
| 1850 | case IWL_UCODE_TLV_TYPE_HCMD: | 2442 | case IWL_UCODE_TLV_TYPE_HCMD: |
| 1851 | if (pnt < IWL_FW_INI_APPLY_AFTER_ALIVE) { | 2443 | if (pnt < IWL_FW_INI_APPLY_AFTER_ALIVE) { |
| 1852 | IWL_ERR(fwrt, | 2444 | IWL_ERR(fwrt, |
| @@ -1877,6 +2469,16 @@ void iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt, | |||
| 1877 | enum iwl_fw_ini_apply_point apply_point) | 2469 | enum iwl_fw_ini_apply_point apply_point) |
| 1878 | { | 2470 | { |
| 1879 | void *data = &fwrt->trans->apply_points[apply_point]; | 2471 | void *data = &fwrt->trans->apply_points[apply_point]; |
| 2472 | int i; | ||
| 2473 | |||
| 2474 | if (apply_point == IWL_FW_INI_APPLY_EARLY) { | ||
| 2475 | for (i = 0; i < IWL_FW_INI_MAX_REGION_ID; i++) | ||
| 2476 | fwrt->dump.active_regs[i] = NULL; | ||
| 2477 | |||
| 2478 | /* disable the triggers, used in recovery flow */ | ||
| 2479 | for (i = 0; i < IWL_FW_TRIGGER_ID_NUM; i++) | ||
| 2480 | fwrt->dump.active_trigs[i].active = false; | ||
| 2481 | } | ||
| 1880 | 2482 | ||
| 1881 | _iwl_fw_dbg_apply_point(fwrt, data, apply_point, false); | 2483 | _iwl_fw_dbg_apply_point(fwrt, data, apply_point, false); |
| 1882 | 2484 | ||
| @@ -1884,3 +2486,27 @@ void iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt, | |||
| 1884 | _iwl_fw_dbg_apply_point(fwrt, data, apply_point, true); | 2486 | _iwl_fw_dbg_apply_point(fwrt, data, apply_point, true); |
| 1885 | } | 2487 | } |
| 1886 | IWL_EXPORT_SYMBOL(iwl_fw_dbg_apply_point); | 2488 | IWL_EXPORT_SYMBOL(iwl_fw_dbg_apply_point); |
| 2489 | |||
| 2490 | void iwl_fwrt_stop_device(struct iwl_fw_runtime *fwrt) | ||
| 2491 | { | ||
| 2492 | /* if the wait event timeout elapses instead of wake up then | ||
| 2493 | * the driver did not receive NMI interrupt and can not assume the FW | ||
| 2494 | * is halted | ||
| 2495 | */ | ||
| 2496 | int ret = wait_event_timeout(fwrt->trans->fw_halt_waitq, | ||
| 2497 | !test_bit(STATUS_FW_WAIT_DUMP, | ||
| 2498 | &fwrt->trans->status), | ||
| 2499 | msecs_to_jiffies(2000)); | ||
| 2500 | if (!ret) { | ||
| 2501 | /* failed to receive NMI interrupt, assuming the FW is stuck */ | ||
| 2502 | set_bit(STATUS_FW_ERROR, &fwrt->trans->status); | ||
| 2503 | |||
| 2504 | clear_bit(STATUS_FW_WAIT_DUMP, &fwrt->trans->status); | ||
| 2505 | } | ||
| 2506 | |||
| 2507 | /* Assuming the op mode mutex is held at this point */ | ||
| 2508 | iwl_fw_dbg_collect_sync(fwrt); | ||
| 2509 | |||
| 2510 | iwl_trans_stop_device(fwrt->trans); | ||
| 2511 | } | ||
| 2512 | IWL_EXPORT_SYMBOL(iwl_fwrt_stop_device); | ||
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h index 330229d2a61d..a199056234d3 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. |
| 9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
| 10 | * Copyright(c) 2015 - 2017 Intel Deutschland GmbH | 10 | * Copyright(c) 2015 - 2017 Intel Deutschland GmbH |
| 11 | * Copyright(c) 2018 Intel Corporation | 11 | * Copyright(c) 2018 - 2019 Intel Corporation |
| 12 | * | 12 | * |
| 13 | * This program is free software; you can redistribute it and/or modify | 13 | * This program is free software; you can redistribute it and/or modify |
| 14 | * it under the terms of version 2 of the GNU General Public License as | 14 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -31,7 +31,7 @@ | |||
| 31 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. | 31 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
| 32 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 32 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
| 33 | * Copyright(c) 2015 - 2017 Intel Deutschland GmbH | 33 | * Copyright(c) 2015 - 2017 Intel Deutschland GmbH |
| 34 | * Copyright(c) 2018 Intel Corporation | 34 | * Copyright(c) 2018 - 2019 Intel Corporation |
| 35 | * All rights reserved. | 35 | * All rights reserved. |
| 36 | * | 36 | * |
| 37 | * Redistribution and use in source and binary forms, with or without | 37 | * Redistribution and use in source and binary forms, with or without |
| @@ -112,6 +112,8 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt); | |||
| 112 | int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt, | 112 | int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt, |
| 113 | const struct iwl_fw_dump_desc *desc, | 113 | const struct iwl_fw_dump_desc *desc, |
| 114 | bool monitor_only, unsigned int delay); | 114 | bool monitor_only, unsigned int delay); |
| 115 | int iwl_fw_dbg_error_collect(struct iwl_fw_runtime *fwrt, | ||
| 116 | enum iwl_fw_dbg_trigger trig_type); | ||
| 115 | int _iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt, | 117 | int _iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt, |
| 116 | enum iwl_fw_dbg_trigger trig, | 118 | enum iwl_fw_dbg_trigger trig, |
| 117 | const char *str, size_t len, | 119 | const char *str, size_t len, |
| @@ -160,9 +162,9 @@ iwl_fw_dbg_trigger_stop_conf_match(struct iwl_fw_runtime *fwrt, | |||
| 160 | } | 162 | } |
| 161 | 163 | ||
| 162 | static inline bool | 164 | static inline bool |
| 163 | iwl_fw_dbg_no_trig_window(struct iwl_fw_runtime *fwrt, u32 id, u32 dis_ms) | 165 | iwl_fw_dbg_no_trig_window(struct iwl_fw_runtime *fwrt, u32 id, u32 dis_usec) |
| 164 | { | 166 | { |
| 165 | unsigned long wind_jiff = msecs_to_jiffies(dis_ms); | 167 | unsigned long wind_jiff = usecs_to_jiffies(dis_usec); |
| 166 | 168 | ||
| 167 | /* If this is the first event checked, jump to update start ts */ | 169 | /* If this is the first event checked, jump to update start ts */ |
| 168 | if (fwrt->dump.non_collect_ts_start[id] && | 170 | if (fwrt->dump.non_collect_ts_start[id] && |
| @@ -179,11 +181,12 @@ iwl_fw_dbg_trigger_check_stop(struct iwl_fw_runtime *fwrt, | |||
| 179 | struct wireless_dev *wdev, | 181 | struct wireless_dev *wdev, |
| 180 | struct iwl_fw_dbg_trigger_tlv *trig) | 182 | struct iwl_fw_dbg_trigger_tlv *trig) |
| 181 | { | 183 | { |
| 184 | u32 usec = le16_to_cpu(trig->trig_dis_ms) * USEC_PER_MSEC; | ||
| 185 | |||
| 182 | if (wdev && !iwl_fw_dbg_trigger_vif_match(trig, wdev)) | 186 | if (wdev && !iwl_fw_dbg_trigger_vif_match(trig, wdev)) |
| 183 | return false; | 187 | return false; |
| 184 | 188 | ||
| 185 | if (iwl_fw_dbg_no_trig_window(fwrt, le32_to_cpu(trig->id), | 189 | if (iwl_fw_dbg_no_trig_window(fwrt, le32_to_cpu(trig->id), usec)) { |
| 186 | le16_to_cpu(trig->trig_dis_ms))) { | ||
| 187 | IWL_WARN(fwrt, "Trigger %d occurred while no-collect window.\n", | 190 | IWL_WARN(fwrt, "Trigger %d occurred while no-collect window.\n", |
| 188 | trig->id); | 191 | trig->id); |
| 189 | return false; | 192 | return false; |
| @@ -220,23 +223,22 @@ _iwl_fw_dbg_trigger_on(struct iwl_fw_runtime *fwrt, | |||
| 220 | }) | 223 | }) |
| 221 | 224 | ||
| 222 | static inline bool | 225 | static inline bool |
| 223 | _iwl_fw_ini_trigger_on(struct iwl_fw_runtime *fwrt, | 226 | iwl_fw_ini_trigger_on(struct iwl_fw_runtime *fwrt, |
| 224 | const enum iwl_fw_dbg_trigger id) | 227 | enum iwl_fw_ini_trigger_id id) |
| 225 | { | 228 | { |
| 226 | struct iwl_fw_ini_active_triggers *trig = &fwrt->dump.active_trigs[id]; | 229 | struct iwl_fw_ini_trigger *trig; |
| 227 | u32 ms; | 230 | u32 usec; |
| 231 | |||
| 228 | 232 | ||
| 229 | if (!fwrt->trans->ini_valid) | ||
| 230 | return false; | ||
| 231 | 233 | ||
| 232 | if (!trig || !trig->active) | 234 | if (!fwrt->trans->ini_valid || id >= IWL_FW_TRIGGER_ID_NUM || |
| 235 | !fwrt->dump.active_trigs[id].active) | ||
| 233 | return false; | 236 | return false; |
| 234 | 237 | ||
| 235 | ms = le32_to_cpu(trig->conf->ignore_consec); | 238 | trig = fwrt->dump.active_trigs[id].trig; |
| 236 | if (ms) | 239 | usec = le32_to_cpu(trig->ignore_consec); |
| 237 | ms /= USEC_PER_MSEC; | ||
| 238 | 240 | ||
| 239 | if (iwl_fw_dbg_no_trig_window(fwrt, id, ms)) { | 241 | if (iwl_fw_dbg_no_trig_window(fwrt, id, usec)) { |
| 240 | IWL_WARN(fwrt, "Trigger %d fired in no-collect window\n", id); | 242 | IWL_WARN(fwrt, "Trigger %d fired in no-collect window\n", id); |
| 241 | return false; | 243 | return false; |
| 242 | } | 244 | } |
| @@ -244,12 +246,6 @@ _iwl_fw_ini_trigger_on(struct iwl_fw_runtime *fwrt, | |||
| 244 | return true; | 246 | return true; |
| 245 | } | 247 | } |
| 246 | 248 | ||
| 247 | #define iwl_fw_ini_trigger_on(fwrt, wdev, id) ({ \ | ||
| 248 | BUILD_BUG_ON(!__builtin_constant_p(id)); \ | ||
| 249 | BUILD_BUG_ON((id) >= IWL_FW_TRIGGER_ID_NUM); \ | ||
| 250 | _iwl_fw_ini_trigger_on((fwrt), (wdev), (id)); \ | ||
| 251 | }) | ||
| 252 | |||
| 253 | static inline void | 249 | static inline void |
| 254 | _iwl_fw_dbg_trigger_simple_stop(struct iwl_fw_runtime *fwrt, | 250 | _iwl_fw_dbg_trigger_simple_stop(struct iwl_fw_runtime *fwrt, |
| 255 | struct wireless_dev *wdev, | 251 | struct wireless_dev *wdev, |
| @@ -296,13 +292,13 @@ _iwl_fw_dbg_stop_recording(struct iwl_trans *trans, | |||
| 296 | } | 292 | } |
| 297 | 293 | ||
| 298 | if (params) { | 294 | if (params) { |
| 299 | params->in_sample = iwl_read_prph(trans, DBGC_IN_SAMPLE); | 295 | params->in_sample = iwl_read_umac_prph(trans, DBGC_IN_SAMPLE); |
| 300 | params->out_ctrl = iwl_read_prph(trans, DBGC_OUT_CTRL); | 296 | params->out_ctrl = iwl_read_umac_prph(trans, DBGC_OUT_CTRL); |
| 301 | } | 297 | } |
| 302 | 298 | ||
| 303 | iwl_write_prph(trans, DBGC_IN_SAMPLE, 0); | 299 | iwl_write_umac_prph(trans, DBGC_IN_SAMPLE, 0); |
| 304 | udelay(100); | 300 | udelay(100); |
| 305 | iwl_write_prph(trans, DBGC_OUT_CTRL, 0); | 301 | iwl_write_umac_prph(trans, DBGC_OUT_CTRL, 0); |
| 306 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 302 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
| 307 | trans->dbg_rec_on = false; | 303 | trans->dbg_rec_on = false; |
| 308 | #endif | 304 | #endif |
| @@ -330,9 +326,9 @@ _iwl_fw_dbg_restart_recording(struct iwl_trans *trans, | |||
| 330 | iwl_clear_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x1); | 326 | iwl_clear_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x1); |
| 331 | iwl_set_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x1); | 327 | iwl_set_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x1); |
| 332 | } else { | 328 | } else { |
| 333 | iwl_write_prph(trans, DBGC_IN_SAMPLE, params->in_sample); | 329 | iwl_write_umac_prph(trans, DBGC_IN_SAMPLE, params->in_sample); |
| 334 | udelay(100); | 330 | udelay(100); |
| 335 | iwl_write_prph(trans, DBGC_OUT_CTRL, params->out_ctrl); | 331 | iwl_write_umac_prph(trans, DBGC_OUT_CTRL, params->out_ctrl); |
| 336 | } | 332 | } |
| 337 | } | 333 | } |
| 338 | 334 | ||
| @@ -373,7 +369,9 @@ static inline bool iwl_fw_dbg_is_d3_debug_enabled(struct iwl_fw_runtime *fwrt) | |||
| 373 | { | 369 | { |
| 374 | return fw_has_capa(&fwrt->fw->ucode_capa, | 370 | return fw_has_capa(&fwrt->fw->ucode_capa, |
| 375 | IWL_UCODE_TLV_CAPA_D3_DEBUG) && | 371 | IWL_UCODE_TLV_CAPA_D3_DEBUG) && |
| 376 | fwrt->trans->cfg->d3_debug_data_length && | 372 | fwrt->trans->cfg->d3_debug_data_length && fwrt->ops && |
| 373 | fwrt->ops->d3_debug_enable && | ||
| 374 | fwrt->ops->d3_debug_enable(fwrt->ops_ctx) && | ||
| 377 | iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_D3_DEBUG_DATA); | 375 | iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_D3_DEBUG_DATA); |
| 378 | } | 376 | } |
| 379 | 377 | ||
| @@ -434,10 +432,33 @@ static inline void iwl_fw_resume_timestamp(struct iwl_fw_runtime *fwrt) {} | |||
| 434 | 432 | ||
| 435 | #endif /* CONFIG_IWLWIFI_DEBUGFS */ | 433 | #endif /* CONFIG_IWLWIFI_DEBUGFS */ |
| 436 | 434 | ||
| 437 | void iwl_fw_assert_error_dump(struct iwl_fw_runtime *fwrt); | ||
| 438 | void iwl_fw_alive_error_dump(struct iwl_fw_runtime *fwrt); | ||
| 439 | void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt); | 435 | void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt); |
| 440 | void iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt, | 436 | void iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt, |
| 441 | enum iwl_fw_ini_apply_point apply_point); | 437 | enum iwl_fw_ini_apply_point apply_point); |
| 442 | 438 | ||
| 439 | void iwl_fwrt_stop_device(struct iwl_fw_runtime *fwrt); | ||
| 440 | |||
| 441 | static inline void iwl_fw_lmac1_set_alive_err_table(struct iwl_trans *trans, | ||
| 442 | u32 lmac_error_event_table) | ||
| 443 | { | ||
| 444 | if (!(trans->error_event_table_tlv_status & | ||
| 445 | IWL_ERROR_EVENT_TABLE_LMAC1) || | ||
| 446 | WARN_ON(trans->lmac_error_event_table[0] != | ||
| 447 | lmac_error_event_table)) | ||
| 448 | trans->lmac_error_event_table[0] = lmac_error_event_table; | ||
| 449 | } | ||
| 450 | |||
| 451 | static inline void iwl_fw_umac_set_alive_err_table(struct iwl_trans *trans, | ||
| 452 | u32 umac_error_event_table) | ||
| 453 | { | ||
| 454 | if (!(trans->error_event_table_tlv_status & | ||
| 455 | IWL_ERROR_EVENT_TABLE_UMAC) || | ||
| 456 | WARN_ON(trans->umac_error_event_table != | ||
| 457 | umac_error_event_table)) | ||
| 458 | trans->umac_error_event_table = umac_error_event_table; | ||
| 459 | } | ||
| 460 | |||
| 461 | /* This bit is used to differentiate the legacy dump from the ini dump */ | ||
| 462 | #define INI_DUMP_BIT BIT(31) | ||
| 463 | |||
| 443 | #endif /* __iwl_fw_dbg_h__ */ | 464 | #endif /* __iwl_fw_dbg_h__ */ |
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c b/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c index 3e120dd47305..c1aa4360736b 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c | |||
| @@ -173,9 +173,8 @@ static const struct file_operations iwl_dbgfs_##name##_ops = { \ | |||
| 173 | _FWRT_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, struct iwl_fw_runtime) | 173 | _FWRT_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, struct iwl_fw_runtime) |
| 174 | 174 | ||
| 175 | #define FWRT_DEBUGFS_ADD_FILE_ALIAS(alias, name, parent, mode) do { \ | 175 | #define FWRT_DEBUGFS_ADD_FILE_ALIAS(alias, name, parent, mode) do { \ |
| 176 | if (!debugfs_create_file(alias, mode, parent, fwrt, \ | 176 | debugfs_create_file(alias, mode, parent, fwrt, \ |
| 177 | &iwl_dbgfs_##name##_ops)) \ | 177 | &iwl_dbgfs_##name##_ops); \ |
| 178 | goto err; \ | ||
| 179 | } while (0) | 178 | } while (0) |
| 180 | #define FWRT_DEBUGFS_ADD_FILE(name, parent, mode) \ | 179 | #define FWRT_DEBUGFS_ADD_FILE(name, parent, mode) \ |
| 181 | FWRT_DEBUGFS_ADD_FILE_ALIAS(#name, name, parent, mode) | 180 | FWRT_DEBUGFS_ADD_FILE_ALIAS(#name, name, parent, mode) |
| @@ -321,14 +320,10 @@ out: | |||
| 321 | 320 | ||
| 322 | FWRT_DEBUGFS_WRITE_FILE_OPS(send_hcmd, 512); | 321 | FWRT_DEBUGFS_WRITE_FILE_OPS(send_hcmd, 512); |
| 323 | 322 | ||
| 324 | int iwl_fwrt_dbgfs_register(struct iwl_fw_runtime *fwrt, | 323 | void iwl_fwrt_dbgfs_register(struct iwl_fw_runtime *fwrt, |
| 325 | struct dentry *dbgfs_dir) | 324 | struct dentry *dbgfs_dir) |
| 326 | { | 325 | { |
| 327 | INIT_DELAYED_WORK(&fwrt->timestamp.wk, iwl_fw_timestamp_marker_wk); | 326 | INIT_DELAYED_WORK(&fwrt->timestamp.wk, iwl_fw_timestamp_marker_wk); |
| 328 | FWRT_DEBUGFS_ADD_FILE(timestamp_marker, dbgfs_dir, 0200); | 327 | FWRT_DEBUGFS_ADD_FILE(timestamp_marker, dbgfs_dir, 0200); |
| 329 | FWRT_DEBUGFS_ADD_FILE(send_hcmd, dbgfs_dir, 0200); | 328 | FWRT_DEBUGFS_ADD_FILE(send_hcmd, dbgfs_dir, 0200); |
| 330 | return 0; | ||
| 331 | err: | ||
| 332 | IWL_ERR(fwrt, "Can't create the fwrt debugfs directory\n"); | ||
| 333 | return -ENOMEM; | ||
| 334 | } | 329 | } |
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/debugfs.h b/drivers/net/wireless/intel/iwlwifi/fw/debugfs.h index 88255035e8ef..fde40ff88451 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/debugfs.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/debugfs.h | |||
| @@ -63,14 +63,11 @@ | |||
| 63 | #include "runtime.h" | 63 | #include "runtime.h" |
| 64 | 64 | ||
| 65 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 65 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
| 66 | int iwl_fwrt_dbgfs_register(struct iwl_fw_runtime *fwrt, | 66 | void iwl_fwrt_dbgfs_register(struct iwl_fw_runtime *fwrt, |
| 67 | struct dentry *dbgfs_dir); | 67 | struct dentry *dbgfs_dir); |
| 68 | 68 | ||
| 69 | #else | 69 | #else |
| 70 | static inline int iwl_fwrt_dbgfs_register(struct iwl_fw_runtime *fwrt, | 70 | static inline void iwl_fwrt_dbgfs_register(struct iwl_fw_runtime *fwrt, |
| 71 | struct dentry *dbgfs_dir) | 71 | struct dentry *dbgfs_dir) { } |
| 72 | { | ||
| 73 | return 0; | ||
| 74 | } | ||
| 75 | 72 | ||
| 76 | #endif /* CONFIG_IWLWIFI_DEBUGFS */ | 73 | #endif /* CONFIG_IWLWIFI_DEBUGFS */ |
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h index c02425a1e64f..9b5077bd46c3 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h | |||
| @@ -8,7 +8,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 - 2017 Intel Deutschland GmbH | 10 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH |
| 11 | * Copyright (C) 2018 Intel Corporation | 11 | * Copyright (C) 2018 - 2019 Intel Corporation |
| 12 | * | 12 | * |
| 13 | * This program is free software; you can redistribute it and/or modify | 13 | * This program is free software; you can redistribute it and/or modify |
| 14 | * it under the terms of version 2 of the GNU General Public License as | 14 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -31,7 +31,7 @@ | |||
| 31 | * Copyright(c) 2014 Intel Corporation. All rights reserved. | 31 | * Copyright(c) 2014 Intel Corporation. All rights reserved. |
| 32 | * Copyright(c) 2014 - 2015 Intel Mobile Communications GmbH | 32 | * Copyright(c) 2014 - 2015 Intel Mobile Communications GmbH |
| 33 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH | 33 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH |
| 34 | * Copyright (C) 2018 Intel Corporation | 34 | * Copyright (C) 2018 - 2019 Intel Corporation |
| 35 | * All rights reserved. | 35 | * All rights reserved. |
| 36 | * | 36 | * |
| 37 | * Redistribution and use in source and binary forms, with or without | 37 | * Redistribution and use in source and binary forms, with or without |
| @@ -275,22 +275,68 @@ struct iwl_fw_error_dump_mem { | |||
| 275 | }; | 275 | }; |
| 276 | 276 | ||
| 277 | /** | 277 | /** |
| 278 | * struct iwl_fw_error_dump_named_mem - chunk of memory | 278 | * struct iwl_fw_ini_error_dump_range - range of memory |
| 279 | * @type: &enum iwl_fw_error_dump_mem_type | 279 | * @start_addr: the start address of this range |
| 280 | * @offset: the offset from which the memory was read | 280 | * @range_data_size: the size of this range, in bytes |
| 281 | * @name_len: name length | 281 | * @data: the actual memory |
| 282 | * @name: file name | ||
| 283 | * @data: the content of the memory | ||
| 284 | */ | 282 | */ |
| 285 | struct iwl_fw_error_dump_named_mem { | 283 | struct iwl_fw_ini_error_dump_range { |
| 286 | __le32 type; | 284 | __le32 start_addr; |
| 287 | __le32 offset; | 285 | __le32 range_data_size; |
| 288 | u8 name_len; | 286 | __le32 data[]; |
| 289 | u8 name[32]; | 287 | } __packed; |
| 290 | u8 data[]; | 288 | |
| 289 | /** | ||
| 290 | * struct iwl_fw_ini_error_dump_header - ini region dump header | ||
| 291 | * @num_of_ranges: number of ranges in this region | ||
| 292 | * @name_len: number of bytes allocated to the name string of this region | ||
| 293 | * @name: name of the region | ||
| 294 | */ | ||
| 295 | struct iwl_fw_ini_error_dump_header { | ||
| 296 | __le32 num_of_ranges; | ||
| 297 | __le32 name_len; | ||
| 298 | u8 name[IWL_FW_INI_MAX_NAME]; | ||
| 291 | }; | 299 | }; |
| 292 | 300 | ||
| 293 | /** | 301 | /** |
| 302 | * struct iwl_fw_ini_error_dump - ini region dump | ||
| 303 | * @header: the header of this region | ||
| 304 | * @ranges: the memory ranges of this region | ||
| 305 | */ | ||
| 306 | struct iwl_fw_ini_error_dump { | ||
| 307 | struct iwl_fw_ini_error_dump_header header; | ||
| 308 | struct iwl_fw_ini_error_dump_range ranges[]; | ||
| 309 | } __packed; | ||
| 310 | |||
| 311 | /* This bit is used to differentiate between lmac and umac rxf */ | ||
| 312 | #define IWL_RXF_UMAC_BIT BIT(31) | ||
| 313 | |||
| 314 | /** | ||
| 315 | * struct iwl_fw_ini_fifo_error_dump_range - ini fifo range dump | ||
| 316 | * @fifo_num: the fifo num. In case of rxf and umac rxf, set BIT(31) to | ||
| 317 | * distinguish between lmac and umac | ||
| 318 | * @num_of_registers: num of registers to dump, dword size each | ||
| 319 | * @range_data_size: the size of the registers and fifo data | ||
| 320 | * @data: fifo data | ||
| 321 | */ | ||
| 322 | struct iwl_fw_ini_fifo_error_dump_range { | ||
| 323 | __le32 fifo_num; | ||
| 324 | __le32 num_of_registers; | ||
| 325 | __le32 range_data_size; | ||
| 326 | __le32 data[]; | ||
| 327 | } __packed; | ||
| 328 | |||
| 329 | /** | ||
| 330 | * struct iwl_fw_ini_fifo_error_dump - ini fifo region dump | ||
| 331 | * @header: the header of this region | ||
| 332 | * @ranges: the memory ranges of this region | ||
| 333 | */ | ||
| 334 | struct iwl_fw_ini_fifo_error_dump { | ||
| 335 | struct iwl_fw_ini_error_dump_header header; | ||
| 336 | struct iwl_fw_ini_fifo_error_dump_range ranges[]; | ||
| 337 | } __packed; | ||
| 338 | |||
| 339 | /** | ||
| 294 | * struct iwl_fw_error_dump_rb - content of an Receive Buffer | 340 | * struct iwl_fw_error_dump_rb - content of an Receive Buffer |
| 295 | * @index: the index of the Receive Buffer in the Rx queue | 341 | * @index: the index of the Receive Buffer in the Rx queue |
| 296 | * @rxq: the RB's Rx queue | 342 | * @rxq: the RB's Rx queue |
| @@ -305,6 +351,20 @@ struct iwl_fw_error_dump_rb { | |||
| 305 | }; | 351 | }; |
| 306 | 352 | ||
| 307 | /** | 353 | /** |
| 354 | * struct iwl_fw_ini_monitor_dram_dump - ini dram monitor dump | ||
| 355 | * @header - header of the region | ||
| 356 | * @write_ptr - write pointer position in the dram | ||
| 357 | * @cycle_cnt - cycles count | ||
| 358 | * @ranges - the memory ranges of this this region | ||
| 359 | */ | ||
| 360 | struct iwl_fw_ini_monitor_dram_dump { | ||
| 361 | struct iwl_fw_ini_error_dump_header header; | ||
| 362 | __le32 write_ptr; | ||
| 363 | __le32 cycle_cnt; | ||
| 364 | struct iwl_fw_ini_error_dump_range ranges[]; | ||
| 365 | } __packed; | ||
| 366 | |||
| 367 | /** | ||
| 308 | * struct iwl_fw_error_dump_paging - content of the UMAC's image page | 368 | * struct iwl_fw_error_dump_paging - content of the UMAC's image page |
| 309 | * block on DRAM | 369 | * block on DRAM |
| 310 | * @index: the index of the page block | 370 | * @index: the index of the page block |
| @@ -355,7 +415,9 @@ iwl_fw_error_next_data(struct iwl_fw_error_dump_data *data) | |||
| 355 | * @FW_DBG_TDLS: trigger log collection upon TDLS related events. | 415 | * @FW_DBG_TDLS: trigger log collection upon TDLS related events. |
| 356 | * @FW_DBG_TRIGGER_TX_STATUS: trigger log collection upon tx status when | 416 | * @FW_DBG_TRIGGER_TX_STATUS: trigger log collection upon tx status when |
| 357 | * the firmware sends a tx reply. | 417 | * the firmware sends a tx reply. |
| 358 | * @FW_DBG_TRIGGER_NO_ALIVE: trigger log collection if alive flow fails | 418 | * @FW_DBG_TRIGGER_ALIVE_TIMEOUT: trigger log collection if alive flow timeouts |
| 419 | * @FW_DBG_TRIGGER_DRIVER: trigger log collection upon a flow failure | ||
| 420 | * in the driver. | ||
| 359 | */ | 421 | */ |
| 360 | enum iwl_fw_dbg_trigger { | 422 | enum iwl_fw_dbg_trigger { |
| 361 | FW_DBG_TRIGGER_INVALID = 0, | 423 | FW_DBG_TRIGGER_INVALID = 0, |
| @@ -373,7 +435,8 @@ enum iwl_fw_dbg_trigger { | |||
| 373 | FW_DBG_TRIGGER_TX_LATENCY, | 435 | FW_DBG_TRIGGER_TX_LATENCY, |
| 374 | FW_DBG_TRIGGER_TDLS, | 436 | FW_DBG_TRIGGER_TDLS, |
| 375 | FW_DBG_TRIGGER_TX_STATUS, | 437 | FW_DBG_TRIGGER_TX_STATUS, |
| 376 | FW_DBG_TRIGGER_NO_ALIVE, | 438 | FW_DBG_TRIGGER_ALIVE_TIMEOUT, |
| 439 | FW_DBG_TRIGGER_DRIVER, | ||
| 377 | 440 | ||
| 378 | /* must be last */ | 441 | /* must be last */ |
| 379 | FW_DBG_TRIGGER_MAX, | 442 | FW_DBG_TRIGGER_MAX, |
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/file.h b/drivers/net/wireless/intel/iwlwifi/fw/file.h index e8b00b795cbb..641c95d03b15 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/file.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/file.h | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
| 10 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH | 10 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH |
| 11 | * Copyright(c) 2018 Intel Corporation | 11 | * Copyright(c) 2018 Intel Corporation |
| 12 | * Copyright(c) 2019 Intel Corporation | ||
| 12 | * | 13 | * |
| 13 | * This program is free software; you can redistribute it and/or modify | 14 | * This program is free software; you can redistribute it and/or modify |
| 14 | * it under the terms of version 2 of the GNU General Public License as | 15 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -32,6 +33,7 @@ | |||
| 32 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 33 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
| 33 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH | 34 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH |
| 34 | * Copyright(c) 2018 Intel Corporation | 35 | * Copyright(c) 2018 Intel Corporation |
| 36 | * Copyright(c) 2019 Intel Corporation | ||
| 35 | * All rights reserved. | 37 | * All rights reserved. |
| 36 | * | 38 | * |
| 37 | * Redistribution and use in source and binary forms, with or without | 39 | * Redistribution and use in source and binary forms, with or without |
| @@ -143,6 +145,9 @@ enum iwl_ucode_tlv_type { | |||
| 143 | IWL_UCODE_TLV_FW_GSCAN_CAPA = 50, | 145 | IWL_UCODE_TLV_FW_GSCAN_CAPA = 50, |
| 144 | IWL_UCODE_TLV_FW_MEM_SEG = 51, | 146 | IWL_UCODE_TLV_FW_MEM_SEG = 51, |
| 145 | IWL_UCODE_TLV_IML = 52, | 147 | IWL_UCODE_TLV_IML = 52, |
| 148 | IWL_UCODE_TLV_UMAC_DEBUG_ADDRS = 54, | ||
| 149 | IWL_UCODE_TLV_LMAC_DEBUG_ADDRS = 55, | ||
| 150 | IWL_UCODE_TLV_FW_RECOVERY_INFO = 57, | ||
| 146 | IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION = IWL_UCODE_INI_TLV_GROUP | 0x1, | 151 | IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION = IWL_UCODE_INI_TLV_GROUP | 0x1, |
| 147 | IWL_UCODE_TLV_TYPE_HCMD = IWL_UCODE_INI_TLV_GROUP | 0x2, | 152 | IWL_UCODE_TLV_TYPE_HCMD = IWL_UCODE_INI_TLV_GROUP | 0x2, |
| 148 | IWL_UCODE_TLV_TYPE_REGIONS = IWL_UCODE_INI_TLV_GROUP | 0x3, | 153 | IWL_UCODE_TLV_TYPE_REGIONS = IWL_UCODE_INI_TLV_GROUP | 0x3, |
| @@ -263,6 +268,12 @@ typedef unsigned int __bitwise iwl_ucode_tlv_api_t; | |||
| 263 | * @IWL_UCODE_TLV_API_FRAG_EBS: This ucode supports fragmented EBS | 268 | * @IWL_UCODE_TLV_API_FRAG_EBS: This ucode supports fragmented EBS |
| 264 | * @IWL_UCODE_TLV_API_REDUCE_TX_POWER: This ucode supports v5 of | 269 | * @IWL_UCODE_TLV_API_REDUCE_TX_POWER: This ucode supports v5 of |
| 265 | * the REDUCE_TX_POWER_CMD. | 270 | * the REDUCE_TX_POWER_CMD. |
| 271 | * @IWL_UCODE_TLV_API_SHORT_BEACON_NOTIF: This ucode supports the short | ||
| 272 | * version of the beacon notification. | ||
| 273 | * @IWL_UCODE_TLV_API_BEACON_FILTER_V4: This ucode supports v4 of | ||
| 274 | * BEACON_FILTER_CONFIG_API_S_VER_4. | ||
| 275 | * @IWL_UCODE_TLV_API_FTM_NEW_RANGE_REQ: This ucode supports v7 of | ||
| 276 | * LOCATION_RANGE_REQ_CMD_API_S and v6 of LOCATION_RANGE_RESP_NTFY_API_S. | ||
| 266 | * | 277 | * |
| 267 | * @NUM_IWL_UCODE_TLV_API: number of bits used | 278 | * @NUM_IWL_UCODE_TLV_API: number of bits used |
| 268 | */ | 279 | */ |
| @@ -287,6 +298,9 @@ enum iwl_ucode_tlv_api { | |||
| 287 | IWL_UCODE_TLV_API_ADAPTIVE_DWELL_V2 = (__force iwl_ucode_tlv_api_t)42, | 298 | IWL_UCODE_TLV_API_ADAPTIVE_DWELL_V2 = (__force iwl_ucode_tlv_api_t)42, |
| 288 | IWL_UCODE_TLV_API_FRAG_EBS = (__force iwl_ucode_tlv_api_t)44, | 299 | IWL_UCODE_TLV_API_FRAG_EBS = (__force iwl_ucode_tlv_api_t)44, |
| 289 | IWL_UCODE_TLV_API_REDUCE_TX_POWER = (__force iwl_ucode_tlv_api_t)45, | 300 | IWL_UCODE_TLV_API_REDUCE_TX_POWER = (__force iwl_ucode_tlv_api_t)45, |
| 301 | IWL_UCODE_TLV_API_SHORT_BEACON_NOTIF = (__force iwl_ucode_tlv_api_t)46, | ||
| 302 | IWL_UCODE_TLV_API_BEACON_FILTER_V4 = (__force iwl_ucode_tlv_api_t)47, | ||
| 303 | IWL_UCODE_TLV_API_FTM_NEW_RANGE_REQ = (__force iwl_ucode_tlv_api_t)49, | ||
| 290 | 304 | ||
| 291 | NUM_IWL_UCODE_TLV_API | 305 | NUM_IWL_UCODE_TLV_API |
| 292 | #ifdef __CHECKER__ | 306 | #ifdef __CHECKER__ |
| @@ -333,6 +347,7 @@ typedef unsigned int __bitwise iwl_ucode_tlv_capa_t; | |||
| 333 | * @IWL_UCODE_TLV_CAPA_TLC_OFFLOAD: firmware implements rate scaling algorithm | 347 | * @IWL_UCODE_TLV_CAPA_TLC_OFFLOAD: firmware implements rate scaling algorithm |
| 334 | * @IWL_UCODE_TLV_CAPA_DYNAMIC_QUOTA: firmware implements quota related | 348 | * @IWL_UCODE_TLV_CAPA_DYNAMIC_QUOTA: firmware implements quota related |
| 335 | * @IWL_UCODE_TLV_CAPA_COEX_SCHEMA_2: firmware implements Coex Schema 2 | 349 | * @IWL_UCODE_TLV_CAPA_COEX_SCHEMA_2: firmware implements Coex Schema 2 |
| 350 | * IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD: firmware supports CSA command | ||
| 336 | * @IWL_UCODE_TLV_CAPA_ULTRA_HB_CHANNELS: firmware supports ultra high band | 351 | * @IWL_UCODE_TLV_CAPA_ULTRA_HB_CHANNELS: firmware supports ultra high band |
| 337 | * (6 GHz). | 352 | * (6 GHz). |
| 338 | * @IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE: extended DTS measurement | 353 | * @IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE: extended DTS measurement |
| @@ -363,12 +378,15 @@ typedef unsigned int __bitwise iwl_ucode_tlv_capa_t; | |||
| 363 | * capability. | 378 | * capability. |
| 364 | * @IWL_UCODE_TLV_CAPA_CSI_REPORTING: firmware is capable of being configured | 379 | * @IWL_UCODE_TLV_CAPA_CSI_REPORTING: firmware is capable of being configured |
| 365 | * to report the CSI information with (certain) RX frames | 380 | * to report the CSI information with (certain) RX frames |
| 381 | * @IWL_UCODE_TLV_CAPA_FTM_CALIBRATED: has FTM calibrated and thus supports both | ||
| 382 | * initiator and responder | ||
| 366 | * | 383 | * |
| 367 | * @IWL_UCODE_TLV_CAPA_MLME_OFFLOAD: supports MLME offload | 384 | * @IWL_UCODE_TLV_CAPA_MLME_OFFLOAD: supports MLME offload |
| 368 | * | 385 | * |
| 369 | * @NUM_IWL_UCODE_TLV_CAPA: number of bits used | 386 | * @NUM_IWL_UCODE_TLV_CAPA: number of bits used |
| 370 | */ | 387 | */ |
| 371 | enum iwl_ucode_tlv_capa { | 388 | enum iwl_ucode_tlv_capa { |
| 389 | /* set 0 */ | ||
| 372 | IWL_UCODE_TLV_CAPA_D0I3_SUPPORT = (__force iwl_ucode_tlv_capa_t)0, | 390 | IWL_UCODE_TLV_CAPA_D0I3_SUPPORT = (__force iwl_ucode_tlv_capa_t)0, |
| 373 | IWL_UCODE_TLV_CAPA_LAR_SUPPORT = (__force iwl_ucode_tlv_capa_t)1, | 391 | IWL_UCODE_TLV_CAPA_LAR_SUPPORT = (__force iwl_ucode_tlv_capa_t)1, |
| 374 | IWL_UCODE_TLV_CAPA_UMAC_SCAN = (__force iwl_ucode_tlv_capa_t)2, | 392 | IWL_UCODE_TLV_CAPA_UMAC_SCAN = (__force iwl_ucode_tlv_capa_t)2, |
| @@ -390,6 +408,8 @@ enum iwl_ucode_tlv_capa { | |||
| 390 | IWL_UCODE_TLV_CAPA_LAR_MULTI_MCC = (__force iwl_ucode_tlv_capa_t)29, | 408 | IWL_UCODE_TLV_CAPA_LAR_MULTI_MCC = (__force iwl_ucode_tlv_capa_t)29, |
| 391 | IWL_UCODE_TLV_CAPA_BT_COEX_RRC = (__force iwl_ucode_tlv_capa_t)30, | 409 | IWL_UCODE_TLV_CAPA_BT_COEX_RRC = (__force iwl_ucode_tlv_capa_t)30, |
| 392 | IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT = (__force iwl_ucode_tlv_capa_t)31, | 410 | IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT = (__force iwl_ucode_tlv_capa_t)31, |
| 411 | |||
| 412 | /* set 1 */ | ||
| 393 | IWL_UCODE_TLV_CAPA_STA_PM_NOTIF = (__force iwl_ucode_tlv_capa_t)38, | 413 | IWL_UCODE_TLV_CAPA_STA_PM_NOTIF = (__force iwl_ucode_tlv_capa_t)38, |
| 394 | IWL_UCODE_TLV_CAPA_BINDING_CDB_SUPPORT = (__force iwl_ucode_tlv_capa_t)39, | 414 | IWL_UCODE_TLV_CAPA_BINDING_CDB_SUPPORT = (__force iwl_ucode_tlv_capa_t)39, |
| 395 | IWL_UCODE_TLV_CAPA_CDB_SUPPORT = (__force iwl_ucode_tlv_capa_t)40, | 415 | IWL_UCODE_TLV_CAPA_CDB_SUPPORT = (__force iwl_ucode_tlv_capa_t)40, |
| @@ -397,7 +417,11 @@ enum iwl_ucode_tlv_capa { | |||
| 397 | IWL_UCODE_TLV_CAPA_TLC_OFFLOAD = (__force iwl_ucode_tlv_capa_t)43, | 417 | IWL_UCODE_TLV_CAPA_TLC_OFFLOAD = (__force iwl_ucode_tlv_capa_t)43, |
| 398 | IWL_UCODE_TLV_CAPA_DYNAMIC_QUOTA = (__force iwl_ucode_tlv_capa_t)44, | 418 | IWL_UCODE_TLV_CAPA_DYNAMIC_QUOTA = (__force iwl_ucode_tlv_capa_t)44, |
| 399 | IWL_UCODE_TLV_CAPA_COEX_SCHEMA_2 = (__force iwl_ucode_tlv_capa_t)45, | 419 | IWL_UCODE_TLV_CAPA_COEX_SCHEMA_2 = (__force iwl_ucode_tlv_capa_t)45, |
| 420 | IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD = (__force iwl_ucode_tlv_capa_t)46, | ||
| 400 | IWL_UCODE_TLV_CAPA_ULTRA_HB_CHANNELS = (__force iwl_ucode_tlv_capa_t)48, | 421 | IWL_UCODE_TLV_CAPA_ULTRA_HB_CHANNELS = (__force iwl_ucode_tlv_capa_t)48, |
| 422 | IWL_UCODE_TLV_CAPA_FTM_CALIBRATED = (__force iwl_ucode_tlv_capa_t)47, | ||
| 423 | |||
| 424 | /* set 2 */ | ||
| 401 | IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE = (__force iwl_ucode_tlv_capa_t)64, | 425 | IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE = (__force iwl_ucode_tlv_capa_t)64, |
| 402 | IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS = (__force iwl_ucode_tlv_capa_t)65, | 426 | IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS = (__force iwl_ucode_tlv_capa_t)65, |
| 403 | IWL_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT = (__force iwl_ucode_tlv_capa_t)67, | 427 | IWL_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT = (__force iwl_ucode_tlv_capa_t)67, |
| @@ -418,6 +442,7 @@ enum iwl_ucode_tlv_capa { | |||
| 418 | IWL_UCODE_TLV_CAPA_MCC_UPDATE_11AX_SUPPORT = (__force iwl_ucode_tlv_capa_t)89, | 442 | IWL_UCODE_TLV_CAPA_MCC_UPDATE_11AX_SUPPORT = (__force iwl_ucode_tlv_capa_t)89, |
| 419 | IWL_UCODE_TLV_CAPA_CSI_REPORTING = (__force iwl_ucode_tlv_capa_t)90, | 443 | IWL_UCODE_TLV_CAPA_CSI_REPORTING = (__force iwl_ucode_tlv_capa_t)90, |
| 420 | 444 | ||
| 445 | /* set 3 */ | ||
| 421 | IWL_UCODE_TLV_CAPA_MLME_OFFLOAD = (__force iwl_ucode_tlv_capa_t)96, | 446 | IWL_UCODE_TLV_CAPA_MLME_OFFLOAD = (__force iwl_ucode_tlv_capa_t)96, |
| 422 | 447 | ||
| 423 | NUM_IWL_UCODE_TLV_CAPA | 448 | NUM_IWL_UCODE_TLV_CAPA |
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/img.h b/drivers/net/wireless/intel/iwlwifi/fw/img.h index 12333167ea23..f4c5a4d73206 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/img.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/img.h | |||
| @@ -105,6 +105,8 @@ struct iwl_ucode_capabilities { | |||
| 105 | u32 n_scan_channels; | 105 | u32 n_scan_channels; |
| 106 | u32 standard_phy_calibration_size; | 106 | u32 standard_phy_calibration_size; |
| 107 | u32 flags; | 107 | u32 flags; |
| 108 | u32 error_log_addr; | ||
| 109 | u32 error_log_size; | ||
| 108 | unsigned long _api[BITS_TO_LONGS(NUM_IWL_UCODE_TLV_API)]; | 110 | unsigned long _api[BITS_TO_LONGS(NUM_IWL_UCODE_TLV_API)]; |
| 109 | unsigned long _capa[BITS_TO_LONGS(NUM_IWL_UCODE_TLV_CAPA)]; | 111 | unsigned long _capa[BITS_TO_LONGS(NUM_IWL_UCODE_TLV_CAPA)]; |
| 110 | }; | 112 | }; |
| @@ -223,27 +225,24 @@ struct iwl_fw_dbg { | |||
| 223 | }; | 225 | }; |
| 224 | 226 | ||
| 225 | /** | 227 | /** |
| 228 | * @tlv: the buffer allocation tlv | ||
| 229 | * @is_alloc: indicates if the buffer was already allocated | ||
| 230 | */ | ||
| 231 | struct iwl_fw_ini_allocation_data { | ||
| 232 | struct iwl_fw_ini_allocation_tlv tlv; | ||
| 233 | u32 is_alloc; | ||
| 234 | } __packed; | ||
| 235 | |||
| 236 | /** | ||
| 226 | * struct iwl_fw_ini_active_triggers | 237 | * struct iwl_fw_ini_active_triggers |
| 227 | * @active: is this trigger active | 238 | * @active: is this trigger active |
| 228 | * @apply_point: last apply point that updated this trigger | 239 | * @size: allocated memory size of the trigger |
| 229 | * @conf: active trigger | 240 | * @trig: trigger |
| 230 | * @conf_ext: second trigger, contains extra regions to dump | ||
| 231 | */ | 241 | */ |
| 232 | struct iwl_fw_ini_active_triggers { | 242 | struct iwl_fw_ini_active_triggers { |
| 233 | bool active; | 243 | bool active; |
| 234 | enum iwl_fw_ini_apply_point apply_point; | 244 | size_t size; |
| 235 | struct iwl_fw_ini_trigger *conf; | 245 | struct iwl_fw_ini_trigger *trig; |
| 236 | struct iwl_fw_ini_trigger *conf_ext; | ||
| 237 | }; | ||
| 238 | |||
| 239 | /** | ||
| 240 | * struct iwl_fw_ini_active_regs | ||
| 241 | * @reg: active region from TLV | ||
| 242 | * @apply_point: apply point where it became active | ||
| 243 | */ | ||
| 244 | struct iwl_fw_ini_active_regs { | ||
| 245 | struct iwl_fw_ini_region_cfg *reg; | ||
| 246 | enum iwl_fw_ini_apply_point apply_point; | ||
| 247 | }; | 246 | }; |
| 248 | 247 | ||
| 249 | /** | 248 | /** |
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/init.c b/drivers/net/wireless/intel/iwlwifi/fw/init.c index 2efac307909e..7adf4e4e841a 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/init.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/init.c | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2017 Intel Deutschland GmbH | 8 | * Copyright(c) 2017 Intel Deutschland GmbH |
| 9 | * Copyright(c) 2019 Intel Corporation | ||
| 9 | * | 10 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 11 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 12 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -26,6 +27,7 @@ | |||
| 26 | * BSD LICENSE | 27 | * BSD LICENSE |
| 27 | * | 28 | * |
| 28 | * Copyright(c) 2017 Intel Deutschland GmbH | 29 | * Copyright(c) 2017 Intel Deutschland GmbH |
| 30 | * Copyright(c) 2019 Intel Corporation | ||
| 29 | * All rights reserved. | 31 | * All rights reserved. |
| 30 | * | 32 | * |
| 31 | * Redistribution and use in source and binary forms, with or without | 33 | * Redistribution and use in source and binary forms, with or without |
| @@ -74,6 +76,7 @@ void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans, | |||
| 74 | fwrt->ops_ctx = ops_ctx; | 76 | fwrt->ops_ctx = ops_ctx; |
| 75 | INIT_DELAYED_WORK(&fwrt->dump.wk, iwl_fw_error_dump_wk); | 77 | INIT_DELAYED_WORK(&fwrt->dump.wk, iwl_fw_error_dump_wk); |
| 76 | iwl_fwrt_dbgfs_register(fwrt, dbgfs_dir); | 78 | iwl_fwrt_dbgfs_register(fwrt, dbgfs_dir); |
| 79 | init_waitqueue_head(&fwrt->trans->fw_halt_waitq); | ||
| 77 | } | 80 | } |
| 78 | IWL_EXPORT_SYMBOL(iwl_fw_runtime_init); | 81 | IWL_EXPORT_SYMBOL(iwl_fw_runtime_init); |
| 79 | 82 | ||
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h index a0fcbb28114b..a5fe1a8ca426 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2017 Intel Deutschland GmbH | 8 | * Copyright(c) 2017 Intel Deutschland GmbH |
| 9 | * Copyright(c) 2018 Intel Corporation | 9 | * Copyright (C) 2018-2019 Intel Corporation |
| 10 | * | 10 | * |
| 11 | * This program is free software; you can redistribute it and/or modify | 11 | * 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 | 12 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -27,7 +27,7 @@ | |||
| 27 | * BSD LICENSE | 27 | * BSD LICENSE |
| 28 | * | 28 | * |
| 29 | * Copyright(c) 2017 Intel Deutschland GmbH | 29 | * Copyright(c) 2017 Intel Deutschland GmbH |
| 30 | * Copyright(c) 2018 Intel Corporation | 30 | * Copyright (C) 2018-2019 Intel Corporation |
| 31 | * All rights reserved. | 31 | * All rights reserved. |
| 32 | * | 32 | * |
| 33 | * Redistribution and use in source and binary forms, with or without | 33 | * Redistribution and use in source and binary forms, with or without |
| @@ -73,6 +73,7 @@ struct iwl_fw_runtime_ops { | |||
| 73 | void (*dump_end)(void *ctx); | 73 | void (*dump_end)(void *ctx); |
| 74 | bool (*fw_running)(void *ctx); | 74 | bool (*fw_running)(void *ctx); |
| 75 | int (*send_hcmd)(void *ctx, struct iwl_host_cmd *host_cmd); | 75 | int (*send_hcmd)(void *ctx, struct iwl_host_cmd *host_cmd); |
| 76 | bool (*d3_debug_enable)(void *ctx); | ||
| 76 | }; | 77 | }; |
| 77 | 78 | ||
| 78 | #define MAX_NUM_LMAC 2 | 79 | #define MAX_NUM_LMAC 2 |
| @@ -90,7 +91,6 @@ struct iwl_fwrt_shared_mem_cfg { | |||
| 90 | 91 | ||
| 91 | enum iwl_fw_runtime_status { | 92 | enum iwl_fw_runtime_status { |
| 92 | IWL_FWRT_STATUS_DUMPING = 0, | 93 | IWL_FWRT_STATUS_DUMPING = 0, |
| 93 | IWL_FWRT_STATUS_WAIT_ALIVE, | ||
| 94 | }; | 94 | }; |
| 95 | 95 | ||
| 96 | /** | 96 | /** |
| @@ -138,12 +138,13 @@ struct iwl_fw_runtime { | |||
| 138 | u8 conf; | 138 | u8 conf; |
| 139 | 139 | ||
| 140 | /* ts of the beginning of a non-collect fw dbg data period */ | 140 | /* ts of the beginning of a non-collect fw dbg data period */ |
| 141 | unsigned long non_collect_ts_start[IWL_FW_TRIGGER_ID_NUM - 1]; | 141 | unsigned long non_collect_ts_start[IWL_FW_TRIGGER_ID_NUM]; |
| 142 | u32 *d3_debug_data; | 142 | u32 *d3_debug_data; |
| 143 | struct iwl_fw_ini_active_regs active_regs[IWL_FW_INI_MAX_REGION_ID]; | 143 | struct iwl_fw_ini_region_cfg *active_regs[IWL_FW_INI_MAX_REGION_ID]; |
| 144 | struct iwl_fw_ini_active_triggers active_trigs[IWL_FW_TRIGGER_ID_NUM]; | 144 | struct iwl_fw_ini_active_triggers active_trigs[IWL_FW_TRIGGER_ID_NUM]; |
| 145 | u32 lmac_err_id[MAX_NUM_LMAC]; | 145 | u32 lmac_err_id[MAX_NUM_LMAC]; |
| 146 | u32 umac_err_id; | 146 | u32 umac_err_id; |
| 147 | void *fifo_iter; | ||
| 147 | } dump; | 148 | } dump; |
| 148 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 149 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
| 149 | struct { | 150 | struct { |
| @@ -161,8 +162,20 @@ void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans, | |||
| 161 | 162 | ||
| 162 | static inline void iwl_fw_runtime_free(struct iwl_fw_runtime *fwrt) | 163 | static inline void iwl_fw_runtime_free(struct iwl_fw_runtime *fwrt) |
| 163 | { | 164 | { |
| 165 | int i; | ||
| 166 | |||
| 164 | kfree(fwrt->dump.d3_debug_data); | 167 | kfree(fwrt->dump.d3_debug_data); |
| 165 | fwrt->dump.d3_debug_data = NULL; | 168 | fwrt->dump.d3_debug_data = NULL; |
| 169 | |||
| 170 | for (i = 0; i < IWL_FW_TRIGGER_ID_NUM; i++) { | ||
| 171 | struct iwl_fw_ini_active_triggers *active = | ||
| 172 | &fwrt->dump.active_trigs[i]; | ||
| 173 | |||
| 174 | active->active = false; | ||
| 175 | active->size = 0; | ||
| 176 | kfree(active->trig); | ||
| 177 | active->trig = NULL; | ||
| 178 | } | ||
| 166 | } | 179 | } |
| 167 | 180 | ||
| 168 | void iwl_fw_runtime_suspend(struct iwl_fw_runtime *fwrt); | 181 | void iwl_fw_runtime_suspend(struct iwl_fw_runtime *fwrt); |
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h index ff942532fac3..f5f87773667b 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. |
| 9 | * Copyright (C) 2016 - 2017 Intel Deutschland GmbH | 9 | * Copyright (C) 2016 - 2017 Intel Deutschland GmbH |
| 10 | * Copyright(c) 2018 Intel Corporation | 10 | * Copyright(c) 2018 - 2019 Intel Corporation |
| 11 | * | 11 | * |
| 12 | * 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 |
| 13 | * 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 |
| @@ -29,7 +29,7 @@ | |||
| 29 | * | 29 | * |
| 30 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. | 30 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
| 31 | * Copyright (C) 2016 - 2017 Intel Deutschland GmbH | 31 | * Copyright (C) 2016 - 2017 Intel Deutschland GmbH |
| 32 | * Copyright(c) 2018 Intel Corporation | 32 | * Copyright(c) 2018 - 2019 Intel Corporation |
| 33 | * All rights reserved. | 33 | * All rights reserved. |
| 34 | * | 34 | * |
| 35 | * Redistribution and use in source and binary forms, with or without | 35 | * Redistribution and use in source and binary forms, with or without |
| @@ -89,6 +89,7 @@ enum iwl_device_family { | |||
| 89 | IWL_DEVICE_FAMILY_9000, | 89 | IWL_DEVICE_FAMILY_9000, |
| 90 | IWL_DEVICE_FAMILY_22000, | 90 | IWL_DEVICE_FAMILY_22000, |
| 91 | IWL_DEVICE_FAMILY_22560, | 91 | IWL_DEVICE_FAMILY_22560, |
| 92 | IWL_DEVICE_FAMILY_AX210, | ||
| 92 | }; | 93 | }; |
| 93 | 94 | ||
| 94 | /* | 95 | /* |
| @@ -379,6 +380,9 @@ struct iwl_csr_params { | |||
| 379 | * @nvm_type: see &enum iwl_nvm_type | 380 | * @nvm_type: see &enum iwl_nvm_type |
| 380 | * @d3_debug_data_base_addr: base address where D3 debug data is stored | 381 | * @d3_debug_data_base_addr: base address where D3 debug data is stored |
| 381 | * @d3_debug_data_length: length of the D3 debug data | 382 | * @d3_debug_data_length: length of the D3 debug data |
| 383 | * @bisr_workaround: BISR hardware workaround (for 22260 series devices) | ||
| 384 | * @min_txq_size: minimum number of slots required in a TX queue | ||
| 385 | * @umac_prph_offset: offset to add to UMAC periphery address | ||
| 382 | * | 386 | * |
| 383 | * We enable the driver to be backward compatible wrt. hardware features. | 387 | * We enable the driver to be backward compatible wrt. hardware features. |
| 384 | * API differences in uCode shouldn't be handled here but through TLVs | 388 | * API differences in uCode shouldn't be handled here but through TLVs |
| @@ -428,7 +432,8 @@ struct iwl_cfg { | |||
| 428 | use_tfh:1, | 432 | use_tfh:1, |
| 429 | gen2:1, | 433 | gen2:1, |
| 430 | cdb:1, | 434 | cdb:1, |
| 431 | dbgc_supported:1; | 435 | dbgc_supported:1, |
| 436 | bisr_workaround:1; | ||
| 432 | u8 valid_tx_ant; | 437 | u8 valid_tx_ant; |
| 433 | u8 valid_rx_ant; | 438 | u8 valid_rx_ant; |
| 434 | u8 non_shared_ant; | 439 | u8 non_shared_ant; |
| @@ -443,37 +448,12 @@ struct iwl_cfg { | |||
| 443 | u32 extra_phy_cfg_flags; | 448 | u32 extra_phy_cfg_flags; |
| 444 | u32 d3_debug_data_base_addr; | 449 | u32 d3_debug_data_base_addr; |
| 445 | u32 d3_debug_data_length; | 450 | u32 d3_debug_data_length; |
| 451 | u32 min_txq_size; | ||
| 452 | u32 umac_prph_offset; | ||
| 446 | }; | 453 | }; |
| 447 | 454 | ||
| 448 | static const struct iwl_csr_params iwl_csr_v1 = { | 455 | extern const struct iwl_csr_params iwl_csr_v1; |
| 449 | .flag_mac_clock_ready = 0, | 456 | extern const struct iwl_csr_params iwl_csr_v2; |
| 450 | .flag_val_mac_access_en = 0, | ||
| 451 | .flag_init_done = 2, | ||
| 452 | .flag_mac_access_req = 3, | ||
| 453 | .flag_sw_reset = 7, | ||
| 454 | .flag_master_dis = 8, | ||
| 455 | .flag_stop_master = 9, | ||
| 456 | .addr_sw_reset = (CSR_BASE + 0x020), | ||
| 457 | .mac_addr0_otp = 0x380, | ||
| 458 | .mac_addr1_otp = 0x384, | ||
| 459 | .mac_addr0_strap = 0x388, | ||
| 460 | .mac_addr1_strap = 0x38C | ||
| 461 | }; | ||
| 462 | |||
| 463 | static const struct iwl_csr_params iwl_csr_v2 = { | ||
| 464 | .flag_init_done = 6, | ||
| 465 | .flag_mac_clock_ready = 20, | ||
| 466 | .flag_val_mac_access_en = 20, | ||
| 467 | .flag_mac_access_req = 21, | ||
| 468 | .flag_master_dis = 28, | ||
| 469 | .flag_stop_master = 29, | ||
| 470 | .flag_sw_reset = 31, | ||
| 471 | .addr_sw_reset = (CSR_BASE + 0x024), | ||
| 472 | .mac_addr0_otp = 0x30, | ||
| 473 | .mac_addr1_otp = 0x34, | ||
| 474 | .mac_addr0_strap = 0x38, | ||
| 475 | .mac_addr1_strap = 0x3C | ||
| 476 | }; | ||
| 477 | 457 | ||
| 478 | /* | 458 | /* |
| 479 | * This list declares the config structures for all devices. | 459 | * This list declares the config structures for all devices. |
| @@ -568,7 +548,7 @@ extern const struct iwl_cfg iwl9560_killer_s_2ac_cfg_shared_clk; | |||
| 568 | extern const struct iwl_cfg iwl22000_2ac_cfg_hr; | 548 | extern const struct iwl_cfg iwl22000_2ac_cfg_hr; |
| 569 | extern const struct iwl_cfg iwl22000_2ac_cfg_hr_cdb; | 549 | extern const struct iwl_cfg iwl22000_2ac_cfg_hr_cdb; |
| 570 | extern const struct iwl_cfg iwl22000_2ac_cfg_jf; | 550 | extern const struct iwl_cfg iwl22000_2ac_cfg_jf; |
| 571 | extern const struct iwl_cfg iwl22560_2ax_cfg_hr; | 551 | extern const struct iwl_cfg iwl_ax101_cfg_qu_hr; |
| 572 | extern const struct iwl_cfg iwl22000_2ax_cfg_hr; | 552 | extern const struct iwl_cfg iwl22000_2ax_cfg_hr; |
| 573 | extern const struct iwl_cfg iwl22260_2ax_cfg; | 553 | extern const struct iwl_cfg iwl22260_2ax_cfg; |
| 574 | extern const struct iwl_cfg killer1650s_2ax_cfg_qu_b0_hr_b0; | 554 | extern const struct iwl_cfg killer1650s_2ax_cfg_qu_b0_hr_b0; |
| @@ -585,9 +565,13 @@ extern const struct iwl_cfg iwl22000_2ax_cfg_jf; | |||
| 585 | extern const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_a0_f0; | 565 | extern const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_a0_f0; |
| 586 | extern const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_b0_f0; | 566 | extern const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_b0_f0; |
| 587 | extern const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_b0; | 567 | extern const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_b0; |
| 588 | extern const struct iwl_cfg iwl22000_2ax_cfg_qnj_jf_b0; | 568 | extern const struct iwl_cfg iwl9560_2ac_cfg_qnj_jf_b0; |
| 589 | extern const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_a0; | 569 | extern const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_a0; |
| 590 | extern const struct iwl_cfg iwl22560_2ax_cfg_su_cdb; | 570 | extern const struct iwl_cfg iwl22560_2ax_cfg_su_cdb; |
| 571 | extern const struct iwl_cfg iwlax210_2ax_cfg_so_jf_a0; | ||
| 572 | extern const struct iwl_cfg iwlax210_2ax_cfg_so_hr_a0; | ||
| 573 | extern const struct iwl_cfg iwlax210_2ax_cfg_so_gf_a0; | ||
| 574 | extern const struct iwl_cfg iwlax210_2ax_cfg_ty_gf_a0; | ||
| 591 | #endif /* CPTCFG_IWLMVM || CPTCFG_IWLFMAC */ | 575 | #endif /* CPTCFG_IWLMVM || CPTCFG_IWLFMAC */ |
| 592 | 576 | ||
| 593 | #endif /* __IWL_CONFIG_H__ */ | 577 | #endif /* __IWL_CONFIG_H__ */ |
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h index 42af421bbc3c..aea6d03e545a 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h | |||
| @@ -180,6 +180,7 @@ | |||
| 180 | /* Bits for CSR_HW_IF_CONFIG_REG */ | 180 | /* Bits for CSR_HW_IF_CONFIG_REG */ |
| 181 | #define CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH (0x00000003) | 181 | #define CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH (0x00000003) |
| 182 | #define CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP (0x0000000C) | 182 | #define CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP (0x0000000C) |
| 183 | #define CSR_HW_IF_CONFIG_REG_BIT_MONITOR_SRAM (0x00000080) | ||
| 183 | #define CSR_HW_IF_CONFIG_REG_MSK_BOARD_VER (0x000000C0) | 184 | #define CSR_HW_IF_CONFIG_REG_MSK_BOARD_VER (0x000000C0) |
| 184 | #define CSR_HW_IF_CONFIG_REG_BIT_MAC_SI (0x00000100) | 185 | #define CSR_HW_IF_CONFIG_REG_BIT_MAC_SI (0x00000100) |
| 185 | #define CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI (0x00000200) | 186 | #define CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI (0x00000200) |
| @@ -327,11 +328,14 @@ enum { | |||
| 327 | #define CSR_HW_REV_TYPE_QNJ (0x0000360) | 328 | #define CSR_HW_REV_TYPE_QNJ (0x0000360) |
| 328 | #define CSR_HW_REV_TYPE_QNJ_B0 (0x0000364) | 329 | #define CSR_HW_REV_TYPE_QNJ_B0 (0x0000364) |
| 329 | #define CSR_HW_REV_TYPE_HR_CDB (0x0000340) | 330 | #define CSR_HW_REV_TYPE_HR_CDB (0x0000340) |
| 331 | #define CSR_HW_REV_TYPE_SO (0x0000370) | ||
| 332 | #define CSR_HW_REV_TYPE_TY (0x0000420) | ||
| 330 | 333 | ||
| 331 | /* RF_ID value */ | 334 | /* RF_ID value */ |
| 332 | #define CSR_HW_RF_ID_TYPE_JF (0x00105100) | 335 | #define CSR_HW_RF_ID_TYPE_JF (0x00105100) |
| 333 | #define CSR_HW_RF_ID_TYPE_HR (0x0010A000) | 336 | #define CSR_HW_RF_ID_TYPE_HR (0x0010A000) |
| 334 | #define CSR_HW_RF_ID_TYPE_HRCDB (0x00109F00) | 337 | #define CSR_HW_RF_ID_TYPE_HRCDB (0x00109F00) |
| 338 | #define CSR_HW_RF_ID_TYPE_GF (0x0010D000) | ||
| 335 | 339 | ||
| 336 | /* HW_RF CHIP ID */ | 340 | /* HW_RF CHIP ID */ |
| 337 | #define CSR_HW_RF_ID_TYPE_CHIP_ID(_val) (((_val) >> 12) & 0xFFF) | 341 | #define CSR_HW_RF_ID_TYPE_CHIP_ID(_val) (((_val) >> 12) & 0xFFF) |
| @@ -593,6 +597,7 @@ enum msix_hw_int_causes { | |||
| 593 | MSIX_HW_INT_CAUSES_REG_ALIVE = BIT(0), | 597 | MSIX_HW_INT_CAUSES_REG_ALIVE = BIT(0), |
| 594 | MSIX_HW_INT_CAUSES_REG_WAKEUP = BIT(1), | 598 | MSIX_HW_INT_CAUSES_REG_WAKEUP = BIT(1), |
| 595 | MSIX_HW_INT_CAUSES_REG_IPC = BIT(1), | 599 | MSIX_HW_INT_CAUSES_REG_IPC = BIT(1), |
| 600 | MSIX_HW_INT_CAUSES_REG_IML = BIT(2), | ||
| 596 | MSIX_HW_INT_CAUSES_REG_SW_ERR_V2 = BIT(5), | 601 | MSIX_HW_INT_CAUSES_REG_SW_ERR_V2 = BIT(5), |
| 597 | MSIX_HW_INT_CAUSES_REG_CT_KILL = BIT(6), | 602 | MSIX_HW_INT_CAUSES_REG_CT_KILL = BIT(6), |
| 598 | MSIX_HW_INT_CAUSES_REG_RF_KILL = BIT(7), | 603 | MSIX_HW_INT_CAUSES_REG_RF_KILL = BIT(7), |
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c index 43d815cb3ce9..5798f434f68f 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c | |||
| @@ -71,6 +71,7 @@ void iwl_fw_dbg_copy_tlv(struct iwl_trans *trans, struct iwl_ucode_tlv *tlv, | |||
| 71 | u32 apply_point = le32_to_cpu(header->apply_point); | 71 | u32 apply_point = le32_to_cpu(header->apply_point); |
| 72 | 72 | ||
| 73 | int copy_size = le32_to_cpu(tlv->length) + sizeof(*tlv); | 73 | int copy_size = le32_to_cpu(tlv->length) + sizeof(*tlv); |
| 74 | int offset_size = copy_size; | ||
| 74 | 75 | ||
| 75 | if (WARN_ONCE(apply_point >= IWL_FW_INI_APPLY_NUM, | 76 | if (WARN_ONCE(apply_point >= IWL_FW_INI_APPLY_NUM, |
| 76 | "Invalid apply point id %d\n", apply_point)) | 77 | "Invalid apply point id %d\n", apply_point)) |
| @@ -81,17 +82,25 @@ void iwl_fw_dbg_copy_tlv(struct iwl_trans *trans, struct iwl_ucode_tlv *tlv, | |||
| 81 | else | 82 | else |
| 82 | data = &trans->apply_points[apply_point]; | 83 | data = &trans->apply_points[apply_point]; |
| 83 | 84 | ||
| 85 | /* add room for is_alloc field in &iwl_fw_ini_allocation_data struct */ | ||
| 86 | if (le32_to_cpu(tlv->type) == IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION) { | ||
| 87 | struct iwl_fw_ini_allocation_data *buf_alloc = | ||
| 88 | (void *)tlv->data; | ||
| 89 | |||
| 90 | offset_size += sizeof(buf_alloc->is_alloc); | ||
| 91 | } | ||
| 92 | |||
| 84 | /* | 93 | /* |
| 85 | * Make sure we still have room to copy this TLV. Offset points to the | 94 | * Make sure we still have room to copy this TLV. Offset points to the |
| 86 | * location the last copy ended. | 95 | * location the last copy ended. |
| 87 | */ | 96 | */ |
| 88 | if (WARN_ONCE(data->offset + copy_size > data->size, | 97 | if (WARN_ONCE(data->offset + offset_size > data->size, |
| 89 | "Not enough memory for apply point %d\n", | 98 | "Not enough memory for apply point %d\n", |
| 90 | apply_point)) | 99 | apply_point)) |
| 91 | return; | 100 | return; |
| 92 | 101 | ||
| 93 | memcpy(data->data + data->offset, (void *)tlv, copy_size); | 102 | memcpy(data->data + data->offset, (void *)tlv, copy_size); |
| 94 | data->offset += copy_size; | 103 | data->offset += offset_size; |
| 95 | } | 104 | } |
| 96 | 105 | ||
| 97 | void iwl_alloc_dbg_tlv(struct iwl_trans *trans, size_t len, const u8 *data, | 106 | void iwl_alloc_dbg_tlv(struct iwl_trans *trans, size_t len, const u8 *data, |
| @@ -129,6 +138,16 @@ void iwl_alloc_dbg_tlv(struct iwl_trans *trans, size_t len, const u8 *data, | |||
| 129 | if (WARN_ON(apply >= IWL_FW_INI_APPLY_NUM)) | 138 | if (WARN_ON(apply >= IWL_FW_INI_APPLY_NUM)) |
| 130 | continue; | 139 | continue; |
| 131 | 140 | ||
| 141 | /* add room for is_alloc field in &iwl_fw_ini_allocation_data | ||
| 142 | * struct | ||
| 143 | */ | ||
| 144 | if (tlv_type == IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION) { | ||
| 145 | struct iwl_fw_ini_allocation_data *buf_alloc = | ||
| 146 | (void *)tlv->data; | ||
| 147 | |||
| 148 | size[apply] += sizeof(buf_alloc->is_alloc); | ||
| 149 | } | ||
| 150 | |||
| 132 | size[apply] += sizeof(*tlv) + tlv_len; | 151 | size[apply] += sizeof(*tlv) + tlv_len; |
| 133 | } | 152 | } |
| 134 | 153 | ||
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-debug.h b/drivers/net/wireless/intel/iwlwifi/iwl-debug.h index a2af68a0d34b..655ff5694560 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-debug.h | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | /****************************************************************************** | 1 | /****************************************************************************** |
| 2 | * | 2 | * |
| 3 | * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. |
| 4 | * Copyright (C) 2018 Intel Corporation | ||
| 4 | * | 5 | * |
| 5 | * Portions of this file are derived from the ipw3945 project. | 6 | * Portions of this file are derived from the ipw3945 project. |
| 6 | * | 7 | * |
| @@ -159,7 +160,7 @@ do { \ | |||
| 159 | /* 0x000F0000 - 0x00010000 */ | 160 | /* 0x000F0000 - 0x00010000 */ |
| 160 | #define IWL_DL_FW 0x00010000 | 161 | #define IWL_DL_FW 0x00010000 |
| 161 | #define IWL_DL_RF_KILL 0x00020000 | 162 | #define IWL_DL_RF_KILL 0x00020000 |
| 162 | #define IWL_DL_FW_ERRORS 0x00040000 | 163 | #define IWL_DL_TPT 0x00040000 |
| 163 | /* 0x00F00000 - 0x00100000 */ | 164 | /* 0x00F00000 - 0x00100000 */ |
| 164 | #define IWL_DL_RATE 0x00100000 | 165 | #define IWL_DL_RATE 0x00100000 |
| 165 | #define IWL_DL_CALIB 0x00200000 | 166 | #define IWL_DL_CALIB 0x00200000 |
| @@ -193,7 +194,6 @@ do { \ | |||
| 193 | #define IWL_DEBUG_CALIB(p, f, a...) IWL_DEBUG(p, IWL_DL_CALIB, f, ## a) | 194 | #define IWL_DEBUG_CALIB(p, f, a...) IWL_DEBUG(p, IWL_DL_CALIB, f, ## a) |
| 194 | #define IWL_DEBUG_FW(p, f, a...) IWL_DEBUG(p, IWL_DL_FW, f, ## a) | 195 | #define IWL_DEBUG_FW(p, f, a...) IWL_DEBUG(p, IWL_DL_FW, f, ## a) |
| 195 | #define IWL_DEBUG_RF_KILL(p, f, a...) IWL_DEBUG(p, IWL_DL_RF_KILL, f, ## a) | 196 | #define IWL_DEBUG_RF_KILL(p, f, a...) IWL_DEBUG(p, IWL_DL_RF_KILL, f, ## a) |
| 196 | #define IWL_DEBUG_FW_ERRORS(p, f, a...) IWL_DEBUG(p, IWL_DL_FW_ERRORS, f, ## a) | ||
| 197 | #define IWL_DEBUG_DROP(p, f, a...) IWL_DEBUG(p, IWL_DL_DROP, f, ## a) | 197 | #define IWL_DEBUG_DROP(p, f, a...) IWL_DEBUG(p, IWL_DL_DROP, f, ## a) |
| 198 | #define IWL_DEBUG_DROP_LIMIT(p, f, a...) \ | 198 | #define IWL_DEBUG_DROP_LIMIT(p, f, a...) \ |
| 199 | IWL_DEBUG_LIMIT(p, IWL_DL_DROP, f, ## a) | 199 | IWL_DEBUG_LIMIT(p, IWL_DL_DROP, f, ## a) |
| @@ -215,6 +215,7 @@ do { \ | |||
| 215 | #define IWL_DEBUG_DEV_RADIO(p, f, a...) IWL_DEBUG_DEV(p, IWL_DL_RADIO, f, ## a) | 215 | #define IWL_DEBUG_DEV_RADIO(p, f, a...) IWL_DEBUG_DEV(p, IWL_DL_RADIO, f, ## a) |
| 216 | #define IWL_DEBUG_POWER(p, f, a...) IWL_DEBUG(p, IWL_DL_POWER, f, ## a) | 216 | #define IWL_DEBUG_POWER(p, f, a...) IWL_DEBUG(p, IWL_DL_POWER, f, ## a) |
| 217 | #define IWL_DEBUG_11H(p, f, a...) IWL_DEBUG(p, IWL_DL_11H, f, ## a) | 217 | #define IWL_DEBUG_11H(p, f, a...) IWL_DEBUG(p, IWL_DL_11H, f, ## a) |
| 218 | #define IWL_DEBUG_TPT(p, f, a...) IWL_DEBUG(p, IWL_DL_TPT, f, ## a) | ||
| 218 | #define IWL_DEBUG_RPM(p, f, a...) IWL_DEBUG(p, IWL_DL_RPM, f, ## a) | 219 | #define IWL_DEBUG_RPM(p, f, a...) IWL_DEBUG(p, IWL_DL_RPM, f, ## a) |
| 219 | #define IWL_DEBUG_LAR(p, f, a...) IWL_DEBUG(p, IWL_DL_LAR, f, ## a) | 220 | #define IWL_DEBUG_LAR(p, f, a...) IWL_DEBUG(p, IWL_DL_LAR, f, ## a) |
| 220 | 221 | ||
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c index 2efa1dfe9b4c..689a65b11cc3 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. |
| 9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
| 10 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH | 10 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH |
| 11 | * Copyright(c) 2018 - 2019 Intel Corporation | ||
| 11 | * | 12 | * |
| 12 | * This program is free software; you can redistribute it and/or modify | 13 | * This program is free software; you can redistribute it and/or modify |
| 13 | * it under the terms of version 2 of the GNU General Public License as | 14 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,6 +31,7 @@ | |||
| 30 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. | 31 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
| 31 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 32 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
| 32 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH | 33 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH |
| 34 | * Copyright(c) 2018 - 2019 Intel Corporation | ||
| 33 | * All rights reserved. | 35 | * All rights reserved. |
| 34 | * | 36 | * |
| 35 | * Redistribution and use in source and binary forms, with or without | 37 | * Redistribution and use in source and binary forms, with or without |
| @@ -75,6 +77,7 @@ | |||
| 75 | #include "iwl-dbg-tlv.h" | 77 | #include "iwl-dbg-tlv.h" |
| 76 | #include "iwl-config.h" | 78 | #include "iwl-config.h" |
| 77 | #include "iwl-modparams.h" | 79 | #include "iwl-modparams.h" |
| 80 | #include "fw/api/alive.h" | ||
| 78 | 81 | ||
| 79 | /****************************************************************************** | 82 | /****************************************************************************** |
| 80 | * | 83 | * |
| @@ -588,6 +591,8 @@ static int iwl_parse_v1_v2_firmware(struct iwl_drv *drv, | |||
| 588 | return 0; | 591 | return 0; |
| 589 | } | 592 | } |
| 590 | 593 | ||
| 594 | #define FW_ADDR_CACHE_CONTROL 0xC0000000 | ||
| 595 | |||
| 591 | static int iwl_parse_tlv_firmware(struct iwl_drv *drv, | 596 | static int iwl_parse_tlv_firmware(struct iwl_drv *drv, |
| 592 | const struct firmware *ucode_raw, | 597 | const struct firmware *ucode_raw, |
| 593 | struct iwl_firmware_pieces *pieces, | 598 | struct iwl_firmware_pieces *pieces, |
| @@ -1085,6 +1090,52 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, | |||
| 1085 | return -ENOMEM; | 1090 | return -ENOMEM; |
| 1086 | break; | 1091 | break; |
| 1087 | } | 1092 | } |
| 1093 | case IWL_UCODE_TLV_FW_RECOVERY_INFO: { | ||
| 1094 | struct { | ||
| 1095 | __le32 buf_addr; | ||
| 1096 | __le32 buf_size; | ||
| 1097 | } *recov_info = (void *)tlv_data; | ||
| 1098 | |||
| 1099 | if (tlv_len != sizeof(*recov_info)) | ||
| 1100 | goto invalid_tlv_len; | ||
| 1101 | capa->error_log_addr = | ||
| 1102 | le32_to_cpu(recov_info->buf_addr); | ||
| 1103 | capa->error_log_size = | ||
| 1104 | le32_to_cpu(recov_info->buf_size); | ||
| 1105 | } | ||
| 1106 | break; | ||
| 1107 | case IWL_UCODE_TLV_UMAC_DEBUG_ADDRS: { | ||
| 1108 | struct iwl_umac_debug_addrs *dbg_ptrs = | ||
| 1109 | (void *)tlv_data; | ||
| 1110 | |||
| 1111 | if (tlv_len != sizeof(*dbg_ptrs)) | ||
| 1112 | goto invalid_tlv_len; | ||
| 1113 | if (drv->trans->cfg->device_family < | ||
| 1114 | IWL_DEVICE_FAMILY_22000) | ||
| 1115 | break; | ||
| 1116 | drv->trans->umac_error_event_table = | ||
| 1117 | le32_to_cpu(dbg_ptrs->error_info_addr) & | ||
| 1118 | ~FW_ADDR_CACHE_CONTROL; | ||
| 1119 | drv->trans->error_event_table_tlv_status |= | ||
| 1120 | IWL_ERROR_EVENT_TABLE_UMAC; | ||
| 1121 | break; | ||
| 1122 | } | ||
| 1123 | case IWL_UCODE_TLV_LMAC_DEBUG_ADDRS: { | ||
| 1124 | struct iwl_lmac_debug_addrs *dbg_ptrs = | ||
| 1125 | (void *)tlv_data; | ||
| 1126 | |||
| 1127 | if (tlv_len != sizeof(*dbg_ptrs)) | ||
| 1128 | goto invalid_tlv_len; | ||
| 1129 | if (drv->trans->cfg->device_family < | ||
| 1130 | IWL_DEVICE_FAMILY_22000) | ||
| 1131 | break; | ||
| 1132 | drv->trans->lmac_error_event_table[0] = | ||
| 1133 | le32_to_cpu(dbg_ptrs->error_event_table_ptr) & | ||
| 1134 | ~FW_ADDR_CACHE_CONTROL; | ||
| 1135 | drv->trans->error_event_table_tlv_status |= | ||
| 1136 | IWL_ERROR_EVENT_TABLE_LMAC1; | ||
| 1137 | break; | ||
| 1138 | } | ||
| 1088 | case IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION: | 1139 | case IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION: |
| 1089 | case IWL_UCODE_TLV_TYPE_HCMD: | 1140 | case IWL_UCODE_TLV_TYPE_HCMD: |
| 1090 | case IWL_UCODE_TLV_TYPE_REGIONS: | 1141 | case IWL_UCODE_TLV_TYPE_REGIONS: |
| @@ -1202,11 +1253,6 @@ _iwl_op_mode_start(struct iwl_drv *drv, struct iwlwifi_opmode_table *op) | |||
| 1202 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 1253 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
| 1203 | drv->dbgfs_op_mode = debugfs_create_dir(op->name, | 1254 | drv->dbgfs_op_mode = debugfs_create_dir(op->name, |
| 1204 | drv->dbgfs_drv); | 1255 | drv->dbgfs_drv); |
| 1205 | if (!drv->dbgfs_op_mode) { | ||
| 1206 | IWL_ERR(drv, | ||
| 1207 | "failed to create opmode debugfs directory\n"); | ||
| 1208 | return op_mode; | ||
| 1209 | } | ||
| 1210 | dbgfs_dir = drv->dbgfs_op_mode; | 1256 | dbgfs_dir = drv->dbgfs_op_mode; |
| 1211 | #endif | 1257 | #endif |
| 1212 | 1258 | ||
| @@ -1262,8 +1308,8 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) | |||
| 1262 | fw->ucode_capa.standard_phy_calibration_size = | 1308 | fw->ucode_capa.standard_phy_calibration_size = |
| 1263 | IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE; | 1309 | IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE; |
| 1264 | fw->ucode_capa.n_scan_channels = IWL_DEFAULT_SCAN_CHANNELS; | 1310 | fw->ucode_capa.n_scan_channels = IWL_DEFAULT_SCAN_CHANNELS; |
| 1265 | /* dump all fw memory areas by default except d3 debug data */ | 1311 | /* dump all fw memory areas by default */ |
| 1266 | fw->dbg.dump_mask = 0xfffdffff; | 1312 | fw->dbg.dump_mask = 0xffffffff; |
| 1267 | 1313 | ||
| 1268 | pieces = kzalloc(sizeof(*pieces), GFP_KERNEL); | 1314 | pieces = kzalloc(sizeof(*pieces), GFP_KERNEL); |
| 1269 | if (!pieces) | 1315 | if (!pieces) |
| @@ -1569,20 +1615,8 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans) | |||
| 1569 | drv->dbgfs_drv = debugfs_create_dir(dev_name(trans->dev), | 1615 | drv->dbgfs_drv = debugfs_create_dir(dev_name(trans->dev), |
| 1570 | iwl_dbgfs_root); | 1616 | iwl_dbgfs_root); |
| 1571 | 1617 | ||
| 1572 | if (!drv->dbgfs_drv) { | ||
| 1573 | IWL_ERR(drv, "failed to create debugfs directory\n"); | ||
| 1574 | ret = -ENOMEM; | ||
| 1575 | goto err_free_tlv; | ||
| 1576 | } | ||
| 1577 | |||
| 1578 | /* Create transport layer debugfs dir */ | 1618 | /* Create transport layer debugfs dir */ |
| 1579 | drv->trans->dbgfs_dir = debugfs_create_dir("trans", drv->dbgfs_drv); | 1619 | drv->trans->dbgfs_dir = debugfs_create_dir("trans", drv->dbgfs_drv); |
| 1580 | |||
| 1581 | if (!drv->trans->dbgfs_dir) { | ||
| 1582 | IWL_ERR(drv, "failed to create transport debugfs directory\n"); | ||
| 1583 | ret = -ENOMEM; | ||
| 1584 | goto err_free_dbgfs; | ||
| 1585 | } | ||
| 1586 | #endif | 1620 | #endif |
| 1587 | 1621 | ||
| 1588 | ret = iwl_request_firmware(drv, true); | 1622 | ret = iwl_request_firmware(drv, true); |
| @@ -1595,9 +1629,7 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans) | |||
| 1595 | 1629 | ||
| 1596 | err_fw: | 1630 | err_fw: |
| 1597 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 1631 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
| 1598 | err_free_dbgfs: | ||
| 1599 | debugfs_remove_recursive(drv->dbgfs_drv); | 1632 | debugfs_remove_recursive(drv->dbgfs_drv); |
| 1600 | err_free_tlv: | ||
| 1601 | iwl_fw_dbg_free(drv->trans); | 1633 | iwl_fw_dbg_free(drv->trans); |
| 1602 | #endif | 1634 | #endif |
| 1603 | kfree(drv); | 1635 | kfree(drv); |
| @@ -1708,9 +1740,6 @@ static int __init iwl_drv_init(void) | |||
| 1708 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 1740 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
| 1709 | /* Create the root of iwlwifi debugfs subsystem. */ | 1741 | /* Create the root of iwlwifi debugfs subsystem. */ |
| 1710 | iwl_dbgfs_root = debugfs_create_dir(DRV_NAME, NULL); | 1742 | iwl_dbgfs_root = debugfs_create_dir(DRV_NAME, NULL); |
| 1711 | |||
| 1712 | if (!iwl_dbgfs_root) | ||
| 1713 | return -EFAULT; | ||
| 1714 | #endif | 1743 | #endif |
| 1715 | 1744 | ||
| 1716 | return iwl_pci_register_driver(); | 1745 | return iwl_pci_register_driver(); |
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-parse.c index 75940ac406b9..04338c3a6205 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-parse.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-parse.c | |||
| @@ -850,8 +850,7 @@ iwl_parse_eeprom_data(struct device *dev, const struct iwl_cfg *cfg, | |||
| 850 | if (WARN_ON(!cfg || !cfg->eeprom_params)) | 850 | if (WARN_ON(!cfg || !cfg->eeprom_params)) |
| 851 | return NULL; | 851 | return NULL; |
| 852 | 852 | ||
| 853 | data = kzalloc(sizeof(*data) + | 853 | data = kzalloc(struct_size(data, channels, IWL_NUM_CHANNELS), |
| 854 | sizeof(struct ieee80211_channel) * IWL_NUM_CHANNELS, | ||
| 855 | GFP_KERNEL); | 854 | GFP_KERNEL); |
| 856 | if (!data) | 855 | if (!data) |
| 857 | return NULL; | 856 | return NULL; |
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-read.c b/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-read.c index a6db6a814257..82e87192119e 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-read.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-read.c | |||
| @@ -193,34 +193,25 @@ static int iwl_init_otp_access(struct iwl_trans *trans) | |||
| 193 | { | 193 | { |
| 194 | int ret; | 194 | int ret; |
| 195 | 195 | ||
| 196 | /* Enable 40MHz radio clock */ | 196 | ret = iwl_finish_nic_init(trans); |
| 197 | iwl_write32(trans, CSR_GP_CNTRL, | 197 | if (ret) |
| 198 | iwl_read32(trans, CSR_GP_CNTRL) | | 198 | return ret; |
| 199 | BIT(trans->cfg->csr->flag_init_done)); | 199 | |
| 200 | 200 | iwl_set_bits_prph(trans, APMG_PS_CTRL_REG, | |
| 201 | /* wait for clock to be ready */ | 201 | APMG_PS_CTRL_VAL_RESET_REQ); |
| 202 | ret = iwl_poll_bit(trans, CSR_GP_CNTRL, | 202 | udelay(5); |
| 203 | BIT(trans->cfg->csr->flag_mac_clock_ready), | 203 | iwl_clear_bits_prph(trans, APMG_PS_CTRL_REG, |
| 204 | BIT(trans->cfg->csr->flag_mac_clock_ready), | 204 | APMG_PS_CTRL_VAL_RESET_REQ); |
| 205 | 25000); | 205 | |
| 206 | if (ret < 0) { | 206 | /* |
| 207 | IWL_ERR(trans, "Time out access OTP\n"); | 207 | * CSR auto clock gate disable bit - |
| 208 | } else { | 208 | * this is only applicable for HW with OTP shadow RAM |
| 209 | iwl_set_bits_prph(trans, APMG_PS_CTRL_REG, | 209 | */ |
| 210 | APMG_PS_CTRL_VAL_RESET_REQ); | 210 | if (trans->cfg->base_params->shadow_ram_support) |
| 211 | udelay(5); | 211 | iwl_set_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG, |
| 212 | iwl_clear_bits_prph(trans, APMG_PS_CTRL_REG, | 212 | CSR_RESET_LINK_PWR_MGMT_DISABLED); |
| 213 | APMG_PS_CTRL_VAL_RESET_REQ); | 213 | |
| 214 | 214 | return 0; | |
| 215 | /* | ||
| 216 | * CSR auto clock gate disable bit - | ||
| 217 | * this is only applicable for HW with OTP shadow RAM | ||
| 218 | */ | ||
| 219 | if (trans->cfg->base_params->shadow_ram_support) | ||
| 220 | iwl_set_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG, | ||
| 221 | CSR_RESET_LINK_PWR_MGMT_DISABLED); | ||
| 222 | } | ||
| 223 | return ret; | ||
| 224 | } | 215 | } |
| 225 | 216 | ||
| 226 | static int iwl_read_otp_word(struct iwl_trans *trans, u16 addr, | 217 | static int iwl_read_otp_word(struct iwl_trans *trans, u16 addr, |
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.c b/drivers/net/wireless/intel/iwlwifi/iwl-io.c index ffd1e649bfa0..a704e25af810 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-io.c | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. |
| 9 | * Copyright(c) 2015 - 2016 Intel Deutschland GmbH | 9 | * Copyright(c) 2015 - 2016 Intel Deutschland GmbH |
| 10 | * Copyright(C) 2018 - 2019 Intel Corporation | ||
| 10 | * | 11 | * |
| 11 | * This program is free software; you can redistribute it and/or modify it | 12 | * This program is free software; you can redistribute it and/or modify it |
| 12 | * under the terms of version 2 of the GNU General Public License as | 13 | * under the terms of version 2 of the GNU General Public License as |
| @@ -28,6 +29,7 @@ | |||
| 28 | * | 29 | * |
| 29 | * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. | 30 | * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. |
| 30 | * Copyright(c) 2015 - 2016 Intel Deutschland GmbH | 31 | * Copyright(c) 2015 - 2016 Intel Deutschland GmbH |
| 32 | * Copyright (C) 2018 - 2019 Intel Corporation | ||
| 31 | * All rights reserved. | 33 | * All rights reserved. |
| 32 | * | 34 | * |
| 33 | * Redistribution and use in source and binary forms, with or without | 35 | * Redistribution and use in source and binary forms, with or without |
| @@ -68,6 +70,36 @@ | |||
| 68 | #include "iwl-prph.h" | 70 | #include "iwl-prph.h" |
| 69 | #include "iwl-fh.h" | 71 | #include "iwl-fh.h" |
| 70 | 72 | ||
| 73 | const struct iwl_csr_params iwl_csr_v1 = { | ||
| 74 | .flag_mac_clock_ready = 0, | ||
| 75 | .flag_val_mac_access_en = 0, | ||
| 76 | .flag_init_done = 2, | ||
| 77 | .flag_mac_access_req = 3, | ||
| 78 | .flag_sw_reset = 7, | ||
| 79 | .flag_master_dis = 8, | ||
| 80 | .flag_stop_master = 9, | ||
| 81 | .addr_sw_reset = CSR_BASE + 0x020, | ||
| 82 | .mac_addr0_otp = 0x380, | ||
| 83 | .mac_addr1_otp = 0x384, | ||
| 84 | .mac_addr0_strap = 0x388, | ||
| 85 | .mac_addr1_strap = 0x38C | ||
| 86 | }; | ||
| 87 | |||
| 88 | const struct iwl_csr_params iwl_csr_v2 = { | ||
| 89 | .flag_init_done = 6, | ||
| 90 | .flag_mac_clock_ready = 20, | ||
| 91 | .flag_val_mac_access_en = 20, | ||
| 92 | .flag_mac_access_req = 21, | ||
| 93 | .flag_master_dis = 28, | ||
| 94 | .flag_stop_master = 29, | ||
| 95 | .flag_sw_reset = 31, | ||
| 96 | .addr_sw_reset = CSR_BASE + 0x024, | ||
| 97 | .mac_addr0_otp = 0x30, | ||
| 98 | .mac_addr1_otp = 0x34, | ||
| 99 | .mac_addr0_strap = 0x38, | ||
| 100 | .mac_addr1_strap = 0x3C | ||
| 101 | }; | ||
| 102 | |||
| 71 | void iwl_write8(struct iwl_trans *trans, u32 ofs, u8 val) | 103 | void iwl_write8(struct iwl_trans *trans, u32 ofs, u8 val) |
| 72 | { | 104 | { |
| 73 | trace_iwlwifi_dev_iowrite8(trans->dev, ofs, val); | 105 | trace_iwlwifi_dev_iowrite8(trans->dev, ofs, val); |
| @@ -275,9 +307,12 @@ void iwl_force_nmi(struct iwl_trans *trans) | |||
| 275 | if (trans->cfg->device_family < IWL_DEVICE_FAMILY_9000) | 307 | if (trans->cfg->device_family < IWL_DEVICE_FAMILY_9000) |
| 276 | iwl_write_prph(trans, DEVICE_SET_NMI_REG, | 308 | iwl_write_prph(trans, DEVICE_SET_NMI_REG, |
| 277 | DEVICE_SET_NMI_VAL_DRV); | 309 | DEVICE_SET_NMI_VAL_DRV); |
| 310 | else if (trans->cfg->device_family < IWL_DEVICE_FAMILY_AX210) | ||
| 311 | iwl_write_umac_prph(trans, UREG_NIC_SET_NMI_DRIVER, | ||
| 312 | UREG_NIC_SET_NMI_DRIVER_NMI_FROM_DRIVER_MSK); | ||
| 278 | else | 313 | else |
| 279 | iwl_write_prph(trans, UREG_NIC_SET_NMI_DRIVER, | 314 | iwl_write_umac_prph(trans, UREG_DOORBELL_TO_ISR6, |
| 280 | UREG_NIC_SET_NMI_DRIVER_NMI_FROM_DRIVER_MSK); | 315 | UREG_DOORBELL_TO_ISR6_NMI_BIT); |
| 281 | } | 316 | } |
| 282 | IWL_EXPORT_SYMBOL(iwl_force_nmi); | 317 | IWL_EXPORT_SYMBOL(iwl_force_nmi); |
| 283 | 318 | ||
| @@ -456,3 +491,43 @@ int iwl_dump_fh(struct iwl_trans *trans, char **buf) | |||
| 456 | 491 | ||
| 457 | return 0; | 492 | return 0; |
| 458 | } | 493 | } |
| 494 | |||
| 495 | int iwl_finish_nic_init(struct iwl_trans *trans) | ||
| 496 | { | ||
| 497 | int err; | ||
| 498 | |||
| 499 | if (trans->cfg->bisr_workaround) { | ||
| 500 | /* ensure the TOP FSM isn't still in previous reset */ | ||
| 501 | mdelay(2); | ||
| 502 | } | ||
| 503 | |||
| 504 | /* | ||
| 505 | * Set "initialization complete" bit to move adapter from | ||
| 506 | * D0U* --> D0A* (powered-up active) state. | ||
| 507 | */ | ||
| 508 | iwl_set_bit(trans, CSR_GP_CNTRL, | ||
| 509 | BIT(trans->cfg->csr->flag_init_done)); | ||
| 510 | |||
| 511 | if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) | ||
| 512 | udelay(2); | ||
| 513 | |||
| 514 | /* | ||
| 515 | * Wait for clock stabilization; once stabilized, access to | ||
| 516 | * device-internal resources is supported, e.g. iwl_write_prph() | ||
| 517 | * and accesses to uCode SRAM. | ||
| 518 | */ | ||
| 519 | err = iwl_poll_bit(trans, CSR_GP_CNTRL, | ||
| 520 | BIT(trans->cfg->csr->flag_mac_clock_ready), | ||
| 521 | BIT(trans->cfg->csr->flag_mac_clock_ready), | ||
| 522 | 25000); | ||
| 523 | if (err < 0) | ||
| 524 | IWL_DEBUG_INFO(trans, "Failed to wake NIC\n"); | ||
| 525 | |||
| 526 | if (trans->cfg->bisr_workaround) { | ||
| 527 | /* ensure BISR shift has finished */ | ||
| 528 | udelay(200); | ||
| 529 | } | ||
| 530 | |||
| 531 | return err < 0 ? err : 0; | ||
| 532 | } | ||
| 533 | IWL_EXPORT_SYMBOL(iwl_finish_nic_init); | ||
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.h b/drivers/net/wireless/intel/iwlwifi/iwl-io.h index 61477e58352d..920e2146ea3f 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-io.h | |||
| @@ -5,6 +5,8 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright (C) 2018 - 2019 Intel Corporation | ||
| 9 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify it | 10 | * This program is free software; you can redistribute it and/or modify it |
| 9 | * under the terms of version 2 of the GNU General Public License as | 11 | * under the terms of version 2 of the GNU General Public License as |
| 10 | * published by the Free Software Foundation. | 12 | * published by the Free Software Foundation. |
| @@ -23,6 +25,7 @@ | |||
| 23 | * | 25 | * |
| 24 | * BSD LICENSE | 26 | * BSD LICENSE |
| 25 | * | 27 | * |
| 28 | * Copyright (C) 2018 - 2019 Intel Corporation | ||
| 26 | * All rights reserved. | 29 | * All rights reserved. |
| 27 | * | 30 | * |
| 28 | * Redistribution and use in source and binary forms, with or without | 31 | * Redistribution and use in source and binary forms, with or without |
| @@ -96,7 +99,48 @@ void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs, | |||
| 96 | void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask); | 99 | void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask); |
| 97 | void iwl_force_nmi(struct iwl_trans *trans); | 100 | void iwl_force_nmi(struct iwl_trans *trans); |
| 98 | 101 | ||
| 102 | int iwl_finish_nic_init(struct iwl_trans *trans); | ||
| 103 | |||
| 99 | /* Error handling */ | 104 | /* Error handling */ |
| 100 | int iwl_dump_fh(struct iwl_trans *trans, char **buf); | 105 | int iwl_dump_fh(struct iwl_trans *trans, char **buf); |
| 101 | 106 | ||
| 107 | /* | ||
| 108 | * UMAC periphery address space changed from 0xA00000 to 0xD00000 starting from | ||
| 109 | * device family AX200. So peripheries used in families above and below AX200 | ||
| 110 | * should go through iwl_..._umac_..._prph. | ||
| 111 | */ | ||
| 112 | static inline u32 iwl_umac_prph(struct iwl_trans *trans, u32 ofs) | ||
| 113 | { | ||
| 114 | return ofs + trans->cfg->umac_prph_offset; | ||
| 115 | } | ||
| 116 | |||
| 117 | static inline u32 iwl_read_umac_prph_no_grab(struct iwl_trans *trans, u32 ofs) | ||
| 118 | { | ||
| 119 | return iwl_read_prph_no_grab(trans, ofs + trans->cfg->umac_prph_offset); | ||
| 120 | } | ||
| 121 | |||
| 122 | static inline u32 iwl_read_umac_prph(struct iwl_trans *trans, u32 ofs) | ||
| 123 | { | ||
| 124 | return iwl_read_prph(trans, ofs + trans->cfg->umac_prph_offset); | ||
| 125 | } | ||
| 126 | |||
| 127 | static inline void iwl_write_umac_prph_no_grab(struct iwl_trans *trans, u32 ofs, | ||
| 128 | u32 val) | ||
| 129 | { | ||
| 130 | iwl_write_prph_no_grab(trans, ofs + trans->cfg->umac_prph_offset, val); | ||
| 131 | } | ||
| 132 | |||
| 133 | static inline void iwl_write_umac_prph(struct iwl_trans *trans, u32 ofs, | ||
| 134 | u32 val) | ||
| 135 | { | ||
| 136 | iwl_write_prph(trans, ofs + trans->cfg->umac_prph_offset, val); | ||
| 137 | } | ||
| 138 | |||
| 139 | static inline int iwl_poll_umac_prph_bit(struct iwl_trans *trans, u32 addr, | ||
| 140 | u32 bits, u32 mask, int timeout) | ||
| 141 | { | ||
| 142 | return iwl_poll_prph_bit(trans, addr + trans->cfg->umac_prph_offset, | ||
| 143 | bits, mask, timeout); | ||
| 144 | } | ||
| 145 | |||
| 102 | #endif | 146 | #endif |
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c index 63c081e5c63a..87d6de7efdd2 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. |
| 9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
| 10 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH | 10 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH |
| 11 | * Copyright(c) 2018 Intel Corporation | 11 | * Copyright(c) 2018 - 2019 Intel Corporation |
| 12 | * | 12 | * |
| 13 | * This program is free software; you can redistribute it and/or modify | 13 | * This program is free software; you can redistribute it and/or modify |
| 14 | * it under the terms of version 2 of the GNU General Public License as | 14 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -31,7 +31,7 @@ | |||
| 31 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. | 31 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
| 32 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 32 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
| 33 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH | 33 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH |
| 34 | * Copyright(c) 2018 Intel Corporation | 34 | * Copyright(c) 2018 - 2019 Intel Corporation |
| 35 | * All rights reserved. | 35 | * All rights reserved. |
| 36 | * | 36 | * |
| 37 | * Redistribution and use in source and binary forms, with or without | 37 | * Redistribution and use in source and binary forms, with or without |
| @@ -463,6 +463,9 @@ static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg, | |||
| 463 | } | 463 | } |
| 464 | 464 | ||
| 465 | vht_cap->vht_mcs.tx_mcs_map = vht_cap->vht_mcs.rx_mcs_map; | 465 | vht_cap->vht_mcs.tx_mcs_map = vht_cap->vht_mcs.rx_mcs_map; |
| 466 | |||
| 467 | vht_cap->vht_mcs.tx_highest |= | ||
| 468 | cpu_to_le16(IEEE80211_VHT_EXT_NSS_BW_CAPABLE); | ||
| 466 | } | 469 | } |
| 467 | 470 | ||
| 468 | static struct ieee80211_sband_iftype_data iwl_he_capa[] = { | 471 | static struct ieee80211_sband_iftype_data iwl_he_capa[] = { |
| @@ -930,15 +933,13 @@ iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
| 930 | const __le16 *ch_section; | 933 | const __le16 *ch_section; |
| 931 | 934 | ||
| 932 | if (cfg->nvm_type != IWL_NVM_EXT) | 935 | if (cfg->nvm_type != IWL_NVM_EXT) |
| 933 | data = kzalloc(sizeof(*data) + | 936 | data = kzalloc(struct_size(data, channels, |
| 934 | sizeof(struct ieee80211_channel) * | 937 | IWL_NVM_NUM_CHANNELS), |
| 935 | IWL_NVM_NUM_CHANNELS, | 938 | GFP_KERNEL); |
| 936 | GFP_KERNEL); | ||
| 937 | else | 939 | else |
| 938 | data = kzalloc(sizeof(*data) + | 940 | data = kzalloc(struct_size(data, channels, |
| 939 | sizeof(struct ieee80211_channel) * | 941 | IWL_NVM_NUM_CHANNELS_EXT), |
| 940 | IWL_NVM_NUM_CHANNELS_EXT, | 942 | GFP_KERNEL); |
| 941 | GFP_KERNEL); | ||
| 942 | if (!data) | 943 | if (!data) |
| 943 | return NULL; | 944 | return NULL; |
| 944 | 945 | ||
| @@ -1086,12 +1087,12 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg, | |||
| 1086 | int max_num_ch = cfg->nvm_type == IWL_NVM_EXT ? | 1087 | int max_num_ch = cfg->nvm_type == IWL_NVM_EXT ? |
| 1087 | IWL_NVM_NUM_CHANNELS_EXT : IWL_NVM_NUM_CHANNELS; | 1088 | IWL_NVM_NUM_CHANNELS_EXT : IWL_NVM_NUM_CHANNELS; |
| 1088 | 1089 | ||
| 1089 | if (WARN_ON_ONCE(num_of_ch > NL80211_MAX_SUPP_REG_RULES)) | ||
| 1090 | return ERR_PTR(-EINVAL); | ||
| 1091 | |||
| 1092 | if (WARN_ON(num_of_ch > max_num_ch)) | 1090 | if (WARN_ON(num_of_ch > max_num_ch)) |
| 1093 | num_of_ch = max_num_ch; | 1091 | num_of_ch = max_num_ch; |
| 1094 | 1092 | ||
| 1093 | if (WARN_ON_ONCE(num_of_ch > NL80211_MAX_SUPP_REG_RULES)) | ||
| 1094 | return ERR_PTR(-EINVAL); | ||
| 1095 | |||
| 1095 | IWL_DEBUG_DEV(dev, IWL_DL_LAR, "building regdom for %d channels\n", | 1096 | IWL_DEBUG_DEV(dev, IWL_DL_LAR, "building regdom for %d channels\n", |
| 1096 | num_of_ch); | 1097 | num_of_ch); |
| 1097 | 1098 | ||
| @@ -1425,9 +1426,7 @@ struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans, | |||
| 1425 | if (empty_otp) | 1426 | if (empty_otp) |
| 1426 | IWL_INFO(trans, "OTP is empty\n"); | 1427 | IWL_INFO(trans, "OTP is empty\n"); |
| 1427 | 1428 | ||
| 1428 | nvm = kzalloc(sizeof(*nvm) + | 1429 | nvm = kzalloc(struct_size(nvm, channels, IWL_NUM_CHANNELS), GFP_KERNEL); |
| 1429 | sizeof(struct ieee80211_channel) * IWL_NUM_CHANNELS, | ||
| 1430 | GFP_KERNEL); | ||
| 1431 | if (!nvm) { | 1430 | if (!nvm) { |
| 1432 | ret = -ENOMEM; | 1431 | ret = -ENOMEM; |
| 1433 | goto out; | 1432 | goto out; |
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h index 3aaa5f06461c..1af9f9e1ecd4 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
| 9 | * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH | 9 | * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH |
| 10 | * Copyright(c) 2016 Intel Deutschland GmbH | 10 | * Copyright(c) 2016 Intel Deutschland GmbH |
| 11 | * Copyright (C) 2018 Intel Corporation | 11 | * Copyright (C) 2018 - 2019 Intel Corporation |
| 12 | * | 12 | * |
| 13 | * This program is free software; you can redistribute it and/or modify | 13 | * This program is free software; you can redistribute it and/or modify |
| 14 | * it under the terms of version 2 of the GNU General Public License as | 14 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -31,7 +31,7 @@ | |||
| 31 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. | 31 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
| 32 | * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH | 32 | * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH |
| 33 | * Copyright(c) 2016 Intel Deutschland GmbH | 33 | * Copyright(c) 2016 Intel Deutschland GmbH |
| 34 | * Copyright (C) 2018 Intel Corporation | 34 | * Copyright (C) 2018 - 2019 Intel Corporation |
| 35 | * All rights reserved. | 35 | * All rights reserved. |
| 36 | * | 36 | * |
| 37 | * Redistribution and use in source and binary forms, with or without | 37 | * Redistribution and use in source and binary forms, with or without |
| @@ -433,4 +433,7 @@ enum { | |||
| 433 | #define HPM_DEBUG 0xA03440 | 433 | #define HPM_DEBUG 0xA03440 |
| 434 | #define PERSISTENCE_BIT BIT(12) | 434 | #define PERSISTENCE_BIT BIT(12) |
| 435 | #define PREG_WFPM_ACCESS BIT(12) | 435 | #define PREG_WFPM_ACCESS BIT(12) |
| 436 | |||
| 437 | #define UREG_DOORBELL_TO_ISR6 0xA05C04 | ||
| 438 | #define UREG_DOORBELL_TO_ISR6_NMI_BIT BIT(0) | ||
| 436 | #endif /* __iwl_prph_h__ */ | 439 | #endif /* __iwl_prph_h__ */ |
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index a7009cd4232d..bbebbf3efd57 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. |
| 9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
| 10 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH | 10 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH |
| 11 | * Copyright(c) 2018 - 2019 Intel Corporation | ||
| 11 | * | 12 | * |
| 12 | * This program is free software; you can redistribute it and/or modify | 13 | * This program is free software; you can redistribute it and/or modify |
| 13 | * it under the terms of version 2 of the GNU General Public License as | 14 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,6 +31,7 @@ | |||
| 30 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. | 31 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
| 31 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 32 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
| 32 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH | 33 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH |
| 34 | * Copyright(c) 2018 - 2019 Intel Corporation | ||
| 33 | * All rights reserved. | 35 | * All rights reserved. |
| 34 | * | 36 | * |
| 35 | * Redistribution and use in source and binary forms, with or without | 37 | * Redistribution and use in source and binary forms, with or without |
| @@ -230,6 +232,12 @@ enum iwl_hcmd_dataflag { | |||
| 230 | IWL_HCMD_DFL_DUP = BIT(1), | 232 | IWL_HCMD_DFL_DUP = BIT(1), |
| 231 | }; | 233 | }; |
| 232 | 234 | ||
| 235 | enum iwl_error_event_table_status { | ||
| 236 | IWL_ERROR_EVENT_TABLE_LMAC1 = BIT(0), | ||
| 237 | IWL_ERROR_EVENT_TABLE_LMAC2 = BIT(1), | ||
| 238 | IWL_ERROR_EVENT_TABLE_UMAC = BIT(2), | ||
| 239 | }; | ||
| 240 | |||
| 233 | /** | 241 | /** |
| 234 | * struct iwl_host_cmd - Host command to the uCode | 242 | * struct iwl_host_cmd - Host command to the uCode |
| 235 | * | 243 | * |
| @@ -330,6 +338,7 @@ enum iwl_d3_status { | |||
| 330 | * are sent | 338 | * are sent |
| 331 | * @STATUS_TRANS_IDLE: the trans is idle - general commands are not to be sent | 339 | * @STATUS_TRANS_IDLE: the trans is idle - general commands are not to be sent |
| 332 | * @STATUS_TRANS_DEAD: trans is dead - avoid any read/write operation | 340 | * @STATUS_TRANS_DEAD: trans is dead - avoid any read/write operation |
| 341 | * @STATUS_FW_WAIT_DUMP: if set, wait until cleared before collecting dump | ||
| 333 | */ | 342 | */ |
| 334 | enum iwl_trans_status { | 343 | enum iwl_trans_status { |
| 335 | STATUS_SYNC_HCMD_ACTIVE, | 344 | STATUS_SYNC_HCMD_ACTIVE, |
| @@ -342,6 +351,7 @@ enum iwl_trans_status { | |||
| 342 | STATUS_TRANS_GOING_IDLE, | 351 | STATUS_TRANS_GOING_IDLE, |
| 343 | STATUS_TRANS_IDLE, | 352 | STATUS_TRANS_IDLE, |
| 344 | STATUS_TRANS_DEAD, | 353 | STATUS_TRANS_DEAD, |
| 354 | STATUS_FW_WAIT_DUMP, | ||
| 345 | }; | 355 | }; |
| 346 | 356 | ||
| 347 | static inline int | 357 | static inline int |
| @@ -684,6 +694,9 @@ enum iwl_plat_pm_mode { | |||
| 684 | */ | 694 | */ |
| 685 | #define IWL_TRANS_IDLE_TIMEOUT 2000 | 695 | #define IWL_TRANS_IDLE_TIMEOUT 2000 |
| 686 | 696 | ||
| 697 | /* Max time to wait for nmi interrupt */ | ||
| 698 | #define IWL_TRANS_NMI_TIMEOUT (HZ / 4) | ||
| 699 | |||
| 687 | /** | 700 | /** |
| 688 | * struct iwl_dram_data | 701 | * struct iwl_dram_data |
| 689 | * @physical: page phy pointer | 702 | * @physical: page phy pointer |
| @@ -697,6 +710,20 @@ struct iwl_dram_data { | |||
| 697 | }; | 710 | }; |
| 698 | 711 | ||
| 699 | /** | 712 | /** |
| 713 | * struct iwl_self_init_dram - dram data used by self init process | ||
| 714 | * @fw: lmac and umac dram data | ||
| 715 | * @fw_cnt: total number of items in array | ||
| 716 | * @paging: paging dram data | ||
| 717 | * @paging_cnt: total number of items in array | ||
| 718 | */ | ||
| 719 | struct iwl_self_init_dram { | ||
| 720 | struct iwl_dram_data *fw; | ||
| 721 | int fw_cnt; | ||
| 722 | struct iwl_dram_data *paging; | ||
| 723 | int paging_cnt; | ||
| 724 | }; | ||
| 725 | |||
| 726 | /** | ||
| 700 | * struct iwl_trans - transport common data | 727 | * struct iwl_trans - transport common data |
| 701 | * | 728 | * |
| 702 | * @ops - pointer to iwl_trans_ops | 729 | * @ops - pointer to iwl_trans_ops |
| @@ -738,6 +765,10 @@ struct iwl_dram_data { | |||
| 738 | * mode is set during the initialization phase and is not | 765 | * mode is set during the initialization phase and is not |
| 739 | * supposed to change during runtime. | 766 | * supposed to change during runtime. |
| 740 | * @dbg_rec_on: true iff there is a fw debug recording currently active | 767 | * @dbg_rec_on: true iff there is a fw debug recording currently active |
| 768 | * @lmac_error_event_table: addrs of lmacs error tables | ||
| 769 | * @umac_error_event_table: addr of umac error table | ||
| 770 | * @error_event_table_tlv_status: bitmap that indicates what error table | ||
| 771 | * pointers was recevied via TLV. use enum &iwl_error_event_table_status | ||
| 741 | */ | 772 | */ |
| 742 | struct iwl_trans { | 773 | struct iwl_trans { |
| 743 | const struct iwl_trans_ops *ops; | 774 | const struct iwl_trans_ops *ops; |
| @@ -790,12 +821,18 @@ struct iwl_trans { | |||
| 790 | u8 dbg_n_dest_reg; | 821 | u8 dbg_n_dest_reg; |
| 791 | int num_blocks; | 822 | int num_blocks; |
| 792 | struct iwl_dram_data fw_mon[IWL_FW_INI_APPLY_NUM]; | 823 | struct iwl_dram_data fw_mon[IWL_FW_INI_APPLY_NUM]; |
| 824 | struct iwl_self_init_dram init_dram; | ||
| 793 | 825 | ||
| 794 | enum iwl_plat_pm_mode system_pm_mode; | 826 | enum iwl_plat_pm_mode system_pm_mode; |
| 795 | enum iwl_plat_pm_mode runtime_pm_mode; | 827 | enum iwl_plat_pm_mode runtime_pm_mode; |
| 796 | bool suspending; | 828 | bool suspending; |
| 797 | bool dbg_rec_on; | 829 | bool dbg_rec_on; |
| 798 | 830 | ||
| 831 | u32 lmac_error_event_table[2]; | ||
| 832 | u32 umac_error_event_table; | ||
| 833 | unsigned int error_event_table_tlv_status; | ||
| 834 | wait_queue_head_t fw_halt_waitq; | ||
| 835 | |||
| 799 | /* pointer to trans specific struct */ | 836 | /* pointer to trans specific struct */ |
| 800 | /*Ensure that this pointer will always be aligned to sizeof pointer */ | 837 | /*Ensure that this pointer will always be aligned to sizeof pointer */ |
| 801 | char trans_specific[0] __aligned(sizeof(void *)); | 838 | char trans_specific[0] __aligned(sizeof(void *)); |
| @@ -1202,6 +1239,10 @@ static inline void iwl_trans_fw_error(struct iwl_trans *trans) | |||
| 1202 | /* prevent double restarts due to the same erroneous FW */ | 1239 | /* prevent double restarts due to the same erroneous FW */ |
| 1203 | if (!test_and_set_bit(STATUS_FW_ERROR, &trans->status)) | 1240 | if (!test_and_set_bit(STATUS_FW_ERROR, &trans->status)) |
| 1204 | iwl_op_mode_nic_error(trans->op_mode); | 1241 | iwl_op_mode_nic_error(trans->op_mode); |
| 1242 | |||
| 1243 | if (test_and_clear_bit(STATUS_FW_WAIT_DUMP, &trans->status)) | ||
| 1244 | wake_up(&trans->fw_halt_waitq); | ||
| 1245 | |||
| 1205 | } | 1246 | } |
| 1206 | 1247 | ||
| 1207 | /***************************************************** | 1248 | /***************************************************** |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/Makefile b/drivers/net/wireless/intel/iwlwifi/mvm/Makefile index 30cbd981efbd..dd268c4bd371 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/Makefile +++ b/drivers/net/wireless/intel/iwlwifi/mvm/Makefile | |||
| @@ -5,6 +5,7 @@ iwlmvm-y += utils.o rx.o rxmq.o tx.o binding.o quota.o sta.o sf.o | |||
| 5 | iwlmvm-y += scan.o time-event.o rs.o rs-fw.o | 5 | iwlmvm-y += scan.o time-event.o rs.o rs-fw.o |
| 6 | iwlmvm-y += power.o coex.o | 6 | iwlmvm-y += power.o coex.o |
| 7 | iwlmvm-y += tt.o offloading.o tdls.o | 7 | iwlmvm-y += tt.o offloading.o tdls.o |
| 8 | iwlmvm-y += ftm-responder.o ftm-initiator.o | ||
| 8 | iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o debugfs-vif.o | 9 | iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o debugfs-vif.o |
| 9 | iwlmvm-$(CONFIG_IWLWIFI_LEDS) += led.o | 10 | iwlmvm-$(CONFIG_IWLWIFI_LEDS) += led.o |
| 10 | iwlmvm-$(CONFIG_PM) += d3.o | 11 | iwlmvm-$(CONFIG_PM) += d3.o |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/coex.c b/drivers/net/wireless/intel/iwlwifi/mvm/coex.c index 730e37744dc0..3d2abbc5c76c 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/coex.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/coex.c | |||
| @@ -241,7 +241,6 @@ static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id, | |||
| 241 | struct iwl_bt_coex_reduced_txp_update_cmd cmd = {}; | 241 | struct iwl_bt_coex_reduced_txp_update_cmd cmd = {}; |
| 242 | struct iwl_mvm_sta *mvmsta; | 242 | struct iwl_mvm_sta *mvmsta; |
| 243 | u32 value; | 243 | u32 value; |
| 244 | int ret; | ||
| 245 | 244 | ||
| 246 | mvmsta = iwl_mvm_sta_from_staid_protected(mvm, sta_id); | 245 | mvmsta = iwl_mvm_sta_from_staid_protected(mvm, sta_id); |
| 247 | if (!mvmsta) | 246 | if (!mvmsta) |
| @@ -262,10 +261,8 @@ static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id, | |||
| 262 | cmd.reduced_txp = cpu_to_le32(value); | 261 | cmd.reduced_txp = cpu_to_le32(value); |
| 263 | mvmsta->bt_reduced_txpower = enable; | 262 | mvmsta->bt_reduced_txpower = enable; |
| 264 | 263 | ||
| 265 | ret = iwl_mvm_send_cmd_pdu(mvm, BT_COEX_UPDATE_REDUCED_TXP, CMD_ASYNC, | 264 | return iwl_mvm_send_cmd_pdu(mvm, BT_COEX_UPDATE_REDUCED_TXP, |
| 266 | sizeof(cmd), &cmd); | 265 | CMD_ASYNC, sizeof(cmd), &cmd); |
| 267 | |||
| 268 | return ret; | ||
| 269 | } | 266 | } |
| 270 | 267 | ||
| 271 | struct iwl_bt_iterator_data { | 268 | struct iwl_bt_iterator_data { |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h index d96ada3c06fc..dff14f1ec55f 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved. |
| 9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
| 10 | * Copyright(c) 2015 Intel Deutschland GmbH | 10 | * Copyright(c) 2015 Intel Deutschland GmbH |
| 11 | * Copyright(c) 2018 - 2019 Intel Corporation | ||
| 11 | * | 12 | * |
| 12 | * This program is free software; you can redistribute it and/or modify | 13 | * This program is free software; you can redistribute it and/or modify |
| 13 | * it under the terms of version 2 of the GNU General Public License as | 14 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,6 +31,7 @@ | |||
| 30 | * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved. | 31 | * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved. |
| 31 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 32 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
| 32 | * Copyright(c) 2015 Intel Deutschland GmbH | 33 | * Copyright(c) 2015 Intel Deutschland GmbH |
| 34 | * Copyright(c) 2018 - 2019 Intel Corporation | ||
| 33 | * All rights reserved. | 35 | * All rights reserved. |
| 34 | * | 36 | * |
| 35 | * Redistribution and use in source and binary forms, with or without | 37 | * Redistribution and use in source and binary forms, with or without |
| @@ -63,6 +65,7 @@ | |||
| 63 | #define __MVM_CONSTANTS_H | 65 | #define __MVM_CONSTANTS_H |
| 64 | 66 | ||
| 65 | #include <linux/ieee80211.h> | 67 | #include <linux/ieee80211.h> |
| 68 | #include "fw-api.h" | ||
| 66 | 69 | ||
| 67 | #define IWL_MVM_UAPSD_NOAGG_BSSIDS_NUM 20 | 70 | #define IWL_MVM_UAPSD_NOAGG_BSSIDS_NUM 20 |
| 68 | 71 | ||
| @@ -114,6 +117,7 @@ | |||
| 114 | #define IWL_MVM_TCM_LOWLAT_ENABLE_THRESH 100 /* packets/10 seconds */ | 117 | #define IWL_MVM_TCM_LOWLAT_ENABLE_THRESH 100 /* packets/10 seconds */ |
| 115 | #define IWL_MVM_UAPSD_NONAGG_PERIOD 5000 /* msecs */ | 118 | #define IWL_MVM_UAPSD_NONAGG_PERIOD 5000 /* msecs */ |
| 116 | #define IWL_MVM_UAPSD_NOAGG_LIST_LEN IWL_MVM_UAPSD_NOAGG_BSSIDS_NUM | 119 | #define IWL_MVM_UAPSD_NOAGG_LIST_LEN IWL_MVM_UAPSD_NOAGG_BSSIDS_NUM |
| 120 | #define IWL_MVM_NON_TRANSMITTING_AP 0 | ||
| 117 | #define IWL_MVM_RS_NUM_TRY_BEFORE_ANT_TOGGLE 1 | 121 | #define IWL_MVM_RS_NUM_TRY_BEFORE_ANT_TOGGLE 1 |
| 118 | #define IWL_MVM_RS_HT_VHT_RETRIES_PER_RATE 2 | 122 | #define IWL_MVM_RS_HT_VHT_RETRIES_PER_RATE 2 |
| 119 | #define IWL_MVM_RS_HT_VHT_RETRIES_PER_RATE_TW 1 | 123 | #define IWL_MVM_RS_HT_VHT_RETRIES_PER_RATE_TW 1 |
| @@ -145,5 +149,8 @@ | |||
| 145 | #define IWL_MVM_RS_TPC_SR_NO_INCREASE 85 /* percent */ | 149 | #define IWL_MVM_RS_TPC_SR_NO_INCREASE 85 /* percent */ |
| 146 | #define IWL_MVM_RS_TPC_TX_POWER_STEP 3 | 150 | #define IWL_MVM_RS_TPC_TX_POWER_STEP 3 |
| 147 | #define IWL_MVM_ENABLE_EBS 1 | 151 | #define IWL_MVM_ENABLE_EBS 1 |
| 152 | #define IWL_MVM_FTM_INITIATOR_ALGO IWL_TOF_ALGO_TYPE_MAX_LIKE | ||
| 153 | #define IWL_MVM_FTM_INITIATOR_DYNACK true | ||
| 154 | #define IWL_MVM_D3_DEBUG false | ||
| 148 | 155 | ||
| 149 | #endif /* __MVM_CONSTANTS_H */ | 156 | #endif /* __MVM_CONSTANTS_H */ |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c index 36ed7d6fc971..808bc6f363d0 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c | |||
| @@ -1899,7 +1899,7 @@ static void iwl_mvm_d3_disconnect_iter(void *data, u8 *mac, | |||
| 1899 | static int iwl_mvm_check_rt_status(struct iwl_mvm *mvm, | 1899 | static int iwl_mvm_check_rt_status(struct iwl_mvm *mvm, |
| 1900 | struct ieee80211_vif *vif) | 1900 | struct ieee80211_vif *vif) |
| 1901 | { | 1901 | { |
| 1902 | u32 base = mvm->error_event_table[0]; | 1902 | u32 base = mvm->trans->lmac_error_event_table[0]; |
| 1903 | struct error_table_start { | 1903 | struct error_table_start { |
| 1904 | /* cf. struct iwl_error_event_table */ | 1904 | /* cf. struct iwl_error_event_table */ |
| 1905 | u32 valid; | 1905 | u32 valid; |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c index e136475a34f6..776b24f54200 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
| 10 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH | 10 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH |
| 11 | * Copyright(c) 2018 Intel Corporation | 11 | * Copyright(c) 2018 - 2019 Intel Corporation |
| 12 | * | 12 | * |
| 13 | * This program is free software; you can redistribute it and/or modify | 13 | * This program is free software; you can redistribute it and/or modify |
| 14 | * it under the terms of version 2 of the GNU General Public License as | 14 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -31,7 +31,7 @@ | |||
| 31 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. | 31 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 32 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 32 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
| 33 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH | 33 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH |
| 34 | * Copyright(c) 2018 Intel Corporation | 34 | * Copyright(c) 2018 - 2019 Intel Corporation |
| 35 | * All rights reserved. | 35 | * All rights reserved. |
| 36 | * | 36 | * |
| 37 | * Redistribution and use in source and binary forms, with or without | 37 | * Redistribution and use in source and binary forms, with or without |
| @@ -1188,6 +1188,111 @@ out: | |||
| 1188 | return ret ?: count; | 1188 | return ret ?: count; |
| 1189 | } | 1189 | } |
| 1190 | 1190 | ||
| 1191 | static int _iwl_dbgfs_inject_beacon_ie(struct iwl_mvm *mvm, char *bin, int len) | ||
| 1192 | { | ||
| 1193 | struct ieee80211_vif *vif; | ||
| 1194 | struct iwl_mvm_vif *mvmvif; | ||
| 1195 | struct sk_buff *beacon; | ||
| 1196 | struct ieee80211_tx_info *info; | ||
| 1197 | struct iwl_mac_beacon_cmd beacon_cmd = {}; | ||
| 1198 | u8 rate; | ||
| 1199 | u16 flags; | ||
| 1200 | int i; | ||
| 1201 | |||
| 1202 | len /= 2; | ||
| 1203 | |||
| 1204 | /* Element len should be represented by u8 */ | ||
| 1205 | if (len >= U8_MAX) | ||
| 1206 | return -EINVAL; | ||
| 1207 | |||
| 1208 | if (!iwl_mvm_firmware_running(mvm)) | ||
| 1209 | return -EIO; | ||
| 1210 | |||
| 1211 | if (!iwl_mvm_has_new_tx_api(mvm) && | ||
| 1212 | !fw_has_api(&mvm->fw->ucode_capa, | ||
| 1213 | IWL_UCODE_TLV_API_NEW_BEACON_TEMPLATE)) | ||
| 1214 | return -EINVAL; | ||
| 1215 | |||
| 1216 | rcu_read_lock(); | ||
| 1217 | |||
| 1218 | for (i = 0; i < NUM_MAC_INDEX_DRIVER; i++) { | ||
| 1219 | vif = iwl_mvm_rcu_dereference_vif_id(mvm, i, true); | ||
| 1220 | if (!vif) | ||
| 1221 | continue; | ||
| 1222 | |||
| 1223 | if (vif->type == NL80211_IFTYPE_AP) | ||
| 1224 | break; | ||
| 1225 | } | ||
| 1226 | |||
| 1227 | if (i == NUM_MAC_INDEX_DRIVER || !vif) | ||
| 1228 | goto out_err; | ||
| 1229 | |||
| 1230 | mvm->hw->extra_beacon_tailroom = len; | ||
| 1231 | |||
| 1232 | beacon = ieee80211_beacon_get_template(mvm->hw, vif, NULL); | ||
| 1233 | if (!beacon) | ||
| 1234 | goto out_err; | ||
| 1235 | |||
| 1236 | if (len && hex2bin(skb_put_zero(beacon, len), bin, len)) { | ||
| 1237 | dev_kfree_skb(beacon); | ||
| 1238 | goto out_err; | ||
| 1239 | } | ||
| 1240 | |||
| 1241 | mvm->beacon_inject_active = true; | ||
| 1242 | |||
| 1243 | mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
| 1244 | info = IEEE80211_SKB_CB(beacon); | ||
| 1245 | rate = iwl_mvm_mac_ctxt_get_lowest_rate(info, vif); | ||
| 1246 | flags = iwl_mvm_mac80211_idx_to_hwrate(rate); | ||
| 1247 | |||
| 1248 | if (rate == IWL_FIRST_CCK_RATE) | ||
| 1249 | flags |= IWL_MAC_BEACON_CCK; | ||
| 1250 | |||
| 1251 | beacon_cmd.flags = cpu_to_le16(flags); | ||
| 1252 | beacon_cmd.byte_cnt = cpu_to_le16((u16)beacon->len); | ||
| 1253 | beacon_cmd.template_id = cpu_to_le32((u32)mvmvif->id); | ||
| 1254 | |||
| 1255 | iwl_mvm_mac_ctxt_set_tim(mvm, &beacon_cmd.tim_idx, | ||
| 1256 | &beacon_cmd.tim_size, | ||
| 1257 | beacon->data, beacon->len); | ||
| 1258 | |||
| 1259 | mutex_lock(&mvm->mutex); | ||
| 1260 | iwl_mvm_mac_ctxt_send_beacon_cmd(mvm, beacon, &beacon_cmd, | ||
| 1261 | sizeof(beacon_cmd)); | ||
| 1262 | mutex_unlock(&mvm->mutex); | ||
| 1263 | |||
| 1264 | dev_kfree_skb(beacon); | ||
| 1265 | |||
| 1266 | rcu_read_unlock(); | ||
| 1267 | return 0; | ||
| 1268 | |||
| 1269 | out_err: | ||
| 1270 | rcu_read_unlock(); | ||
| 1271 | return -EINVAL; | ||
| 1272 | } | ||
| 1273 | |||
| 1274 | static ssize_t iwl_dbgfs_inject_beacon_ie_write(struct iwl_mvm *mvm, | ||
| 1275 | char *buf, size_t count, | ||
| 1276 | loff_t *ppos) | ||
| 1277 | { | ||
| 1278 | int ret = _iwl_dbgfs_inject_beacon_ie(mvm, buf, count); | ||
| 1279 | |||
| 1280 | mvm->hw->extra_beacon_tailroom = 0; | ||
| 1281 | return ret ?: count; | ||
| 1282 | } | ||
| 1283 | |||
| 1284 | static ssize_t iwl_dbgfs_inject_beacon_ie_restore_write(struct iwl_mvm *mvm, | ||
| 1285 | char *buf, | ||
| 1286 | size_t count, | ||
| 1287 | loff_t *ppos) | ||
| 1288 | { | ||
| 1289 | int ret = _iwl_dbgfs_inject_beacon_ie(mvm, NULL, 0); | ||
| 1290 | |||
| 1291 | mvm->hw->extra_beacon_tailroom = 0; | ||
| 1292 | mvm->beacon_inject_active = false; | ||
| 1293 | return ret ?: count; | ||
| 1294 | } | ||
| 1295 | |||
| 1191 | static ssize_t iwl_dbgfs_fw_dbg_conf_read(struct file *file, | 1296 | static ssize_t iwl_dbgfs_fw_dbg_conf_read(struct file *file, |
| 1192 | char __user *user_buf, | 1297 | char __user *user_buf, |
| 1193 | size_t count, loff_t *ppos) | 1298 | size_t count, loff_t *ppos) |
| @@ -1684,6 +1789,7 @@ iwl_dbgfs_send_echo_cmd_write(struct iwl_mvm *mvm, char *buf, | |||
| 1684 | 1789 | ||
| 1685 | struct iwl_mvm_sniffer_apply { | 1790 | struct iwl_mvm_sniffer_apply { |
| 1686 | struct iwl_mvm *mvm; | 1791 | struct iwl_mvm *mvm; |
| 1792 | u8 *bssid; | ||
| 1687 | u16 aid; | 1793 | u16 aid; |
| 1688 | }; | 1794 | }; |
| 1689 | 1795 | ||
| @@ -1693,6 +1799,8 @@ static bool iwl_mvm_sniffer_apply(struct iwl_notif_wait_data *notif_data, | |||
| 1693 | struct iwl_mvm_sniffer_apply *apply = data; | 1799 | struct iwl_mvm_sniffer_apply *apply = data; |
| 1694 | 1800 | ||
| 1695 | apply->mvm->cur_aid = cpu_to_le16(apply->aid); | 1801 | apply->mvm->cur_aid = cpu_to_le16(apply->aid); |
| 1802 | memcpy(apply->mvm->cur_bssid, apply->bssid, | ||
| 1803 | sizeof(apply->mvm->cur_bssid)); | ||
| 1696 | 1804 | ||
| 1697 | return true; | 1805 | return true; |
| 1698 | } | 1806 | } |
| @@ -1725,6 +1833,7 @@ iwl_dbgfs_he_sniffer_params_write(struct iwl_mvm *mvm, char *buf, | |||
| 1725 | he_mon_cmd.aid = cpu_to_le16(aid); | 1833 | he_mon_cmd.aid = cpu_to_le16(aid); |
| 1726 | 1834 | ||
| 1727 | apply.aid = aid; | 1835 | apply.aid = aid; |
| 1836 | apply.bssid = (void *)he_mon_cmd.bssid; | ||
| 1728 | 1837 | ||
| 1729 | mutex_lock(&mvm->mutex); | 1838 | mutex_lock(&mvm->mutex); |
| 1730 | 1839 | ||
| @@ -1754,6 +1863,23 @@ iwl_dbgfs_he_sniffer_params_write(struct iwl_mvm *mvm, char *buf, | |||
| 1754 | } | 1863 | } |
| 1755 | 1864 | ||
| 1756 | static ssize_t | 1865 | static ssize_t |
| 1866 | iwl_dbgfs_he_sniffer_params_read(struct file *file, char __user *user_buf, | ||
| 1867 | size_t count, loff_t *ppos) | ||
| 1868 | { | ||
| 1869 | struct iwl_mvm *mvm = file->private_data; | ||
| 1870 | u8 buf[32]; | ||
| 1871 | int len; | ||
| 1872 | |||
| 1873 | len = scnprintf(buf, sizeof(buf), | ||
| 1874 | "%d %02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx\n", | ||
| 1875 | le16_to_cpu(mvm->cur_aid), mvm->cur_bssid[0], | ||
| 1876 | mvm->cur_bssid[1], mvm->cur_bssid[2], mvm->cur_bssid[3], | ||
| 1877 | mvm->cur_bssid[4], mvm->cur_bssid[5]); | ||
| 1878 | |||
| 1879 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
| 1880 | } | ||
| 1881 | |||
| 1882 | static ssize_t | ||
| 1757 | iwl_dbgfs_uapsd_noagg_bssids_read(struct file *file, char __user *user_buf, | 1883 | iwl_dbgfs_uapsd_noagg_bssids_read(struct file *file, char __user *user_buf, |
| 1758 | size_t count, loff_t *ppos) | 1884 | size_t count, loff_t *ppos) |
| 1759 | { | 1885 | { |
| @@ -1806,6 +1932,8 @@ MVM_DEBUGFS_WRITE_FILE_OPS(max_amsdu_len, 8); | |||
| 1806 | MVM_DEBUGFS_WRITE_FILE_OPS(indirection_tbl, | 1932 | MVM_DEBUGFS_WRITE_FILE_OPS(indirection_tbl, |
| 1807 | (IWL_RSS_INDIRECTION_TABLE_SIZE * 2)); | 1933 | (IWL_RSS_INDIRECTION_TABLE_SIZE * 2)); |
| 1808 | MVM_DEBUGFS_WRITE_FILE_OPS(inject_packet, 512); | 1934 | MVM_DEBUGFS_WRITE_FILE_OPS(inject_packet, 512); |
| 1935 | MVM_DEBUGFS_WRITE_FILE_OPS(inject_beacon_ie, 512); | ||
| 1936 | MVM_DEBUGFS_WRITE_FILE_OPS(inject_beacon_ie_restore, 512); | ||
| 1809 | 1937 | ||
| 1810 | MVM_DEBUGFS_READ_FILE_OPS(uapsd_noagg_bssids); | 1938 | MVM_DEBUGFS_READ_FILE_OPS(uapsd_noagg_bssids); |
| 1811 | 1939 | ||
| @@ -1821,7 +1949,7 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram, 8); | |||
| 1821 | MVM_DEBUGFS_READ_FILE_OPS(sar_geo_profile); | 1949 | MVM_DEBUGFS_READ_FILE_OPS(sar_geo_profile); |
| 1822 | #endif | 1950 | #endif |
| 1823 | 1951 | ||
| 1824 | MVM_DEBUGFS_WRITE_FILE_OPS(he_sniffer_params, 32); | 1952 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(he_sniffer_params, 32); |
| 1825 | 1953 | ||
| 1826 | static ssize_t iwl_dbgfs_mem_read(struct file *file, char __user *user_buf, | 1954 | static ssize_t iwl_dbgfs_mem_read(struct file *file, char __user *user_buf, |
| 1827 | size_t count, loff_t *ppos) | 1955 | size_t count, loff_t *ppos) |
| @@ -2007,10 +2135,12 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) | |||
| 2007 | MVM_DEBUGFS_ADD_FILE(send_echo_cmd, mvm->debugfs_dir, 0200); | 2135 | MVM_DEBUGFS_ADD_FILE(send_echo_cmd, mvm->debugfs_dir, 0200); |
| 2008 | MVM_DEBUGFS_ADD_FILE(indirection_tbl, mvm->debugfs_dir, 0200); | 2136 | MVM_DEBUGFS_ADD_FILE(indirection_tbl, mvm->debugfs_dir, 0200); |
| 2009 | MVM_DEBUGFS_ADD_FILE(inject_packet, mvm->debugfs_dir, 0200); | 2137 | MVM_DEBUGFS_ADD_FILE(inject_packet, mvm->debugfs_dir, 0200); |
| 2138 | MVM_DEBUGFS_ADD_FILE(inject_beacon_ie, mvm->debugfs_dir, 0200); | ||
| 2139 | MVM_DEBUGFS_ADD_FILE(inject_beacon_ie_restore, mvm->debugfs_dir, 0200); | ||
| 2010 | #ifdef CONFIG_ACPI | 2140 | #ifdef CONFIG_ACPI |
| 2011 | MVM_DEBUGFS_ADD_FILE(sar_geo_profile, dbgfs_dir, 0400); | 2141 | MVM_DEBUGFS_ADD_FILE(sar_geo_profile, dbgfs_dir, 0400); |
| 2012 | #endif | 2142 | #endif |
| 2013 | MVM_DEBUGFS_ADD_FILE(he_sniffer_params, mvm->debugfs_dir, 0200); | 2143 | MVM_DEBUGFS_ADD_FILE(he_sniffer_params, mvm->debugfs_dir, 0600); |
| 2014 | 2144 | ||
| 2015 | if (!debugfs_create_bool("enable_scan_iteration_notif", | 2145 | if (!debugfs_create_bool("enable_scan_iteration_notif", |
| 2016 | 0600, | 2146 | 0600, |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c new file mode 100644 index 000000000000..e9822a3ec373 --- /dev/null +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c | |||
| @@ -0,0 +1,654 @@ | |||
| 1 | /****************************************************************************** | ||
| 2 | * | ||
| 3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
| 4 | * redistributing this file, you may do so under either license. | ||
| 5 | * | ||
| 6 | * GPL LICENSE SUMMARY | ||
| 7 | * | ||
| 8 | * Copyright(c) 2015 - 2017 Intel Deutschland GmbH | ||
| 9 | * Copyright (C) 2018 Intel Corporation | ||
| 10 | * Copyright (C) 2019 Intel Corporation | ||
| 11 | * | ||
| 12 | * This program is free software; you can redistribute it and/or modify | ||
| 13 | * it under the terms of version 2 of the GNU General Public License as | ||
| 14 | * published by the Free Software Foundation. | ||
| 15 | * | ||
| 16 | * This program is distributed in the hope that it will be useful, but | ||
| 17 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 19 | * General Public License for more details. | ||
| 20 | * | ||
| 21 | * The full GNU General Public License is included in this distribution | ||
| 22 | * in the file called COPYING. | ||
| 23 | * | ||
| 24 | * Contact Information: | ||
| 25 | * Intel Linux Wireless <linuxwifi@intel.com> | ||
| 26 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
| 27 | * | ||
| 28 | * BSD LICENSE | ||
| 29 | * | ||
| 30 | * Copyright(c) 2015 - 2017 Intel Deutschland GmbH | ||
| 31 | * Copyright (C) 2018 Intel Corporation | ||
| 32 | * Copyright (C) 2019 Intel Corporation | ||
| 33 | * All rights reserved. | ||
| 34 | * | ||
| 35 | * Redistribution and use in source and binary forms, with or without | ||
| 36 | * modification, are permitted provided that the following conditions | ||
| 37 | * are met: | ||
| 38 | * | ||
| 39 | * * Redistributions of source code must retain the above copyright | ||
| 40 | * notice, this list of conditions and the following disclaimer. | ||
| 41 | * * Redistributions in binary form must reproduce the above copyright | ||
| 42 | * notice, this list of conditions and the following disclaimer in | ||
| 43 | * the documentation and/or other materials provided with the | ||
| 44 | * distribution. | ||
| 45 | * * Neither the name Intel Corporation nor the names of its | ||
| 46 | * contributors may be used to endorse or promote products derived | ||
| 47 | * from this software without specific prior written permission. | ||
| 48 | * | ||
| 49 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
| 50 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
| 51 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
| 52 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
| 53 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
| 54 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
| 55 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
| 56 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
| 57 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
| 58 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
| 59 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 60 | * | ||
| 61 | *****************************************************************************/ | ||
| 62 | #include <linux/etherdevice.h> | ||
| 63 | #include <linux/math64.h> | ||
| 64 | #include <net/cfg80211.h> | ||
| 65 | #include "mvm.h" | ||
| 66 | #include "iwl-io.h" | ||
| 67 | #include "iwl-prph.h" | ||
| 68 | #include "constants.h" | ||
| 69 | |||
| 70 | struct iwl_mvm_loc_entry { | ||
| 71 | struct list_head list; | ||
| 72 | u8 addr[ETH_ALEN]; | ||
| 73 | u8 lci_len, civic_len; | ||
| 74 | u8 buf[]; | ||
| 75 | }; | ||
| 76 | |||
| 77 | static void iwl_mvm_ftm_reset(struct iwl_mvm *mvm) | ||
| 78 | { | ||
| 79 | struct iwl_mvm_loc_entry *e, *t; | ||
| 80 | |||
| 81 | mvm->ftm_initiator.req = NULL; | ||
| 82 | mvm->ftm_initiator.req_wdev = NULL; | ||
| 83 | memset(mvm->ftm_initiator.responses, 0, | ||
| 84 | sizeof(mvm->ftm_initiator.responses)); | ||
| 85 | list_for_each_entry_safe(e, t, &mvm->ftm_initiator.loc_list, list) { | ||
| 86 | list_del(&e->list); | ||
| 87 | kfree(e); | ||
| 88 | } | ||
| 89 | } | ||
| 90 | |||
| 91 | void iwl_mvm_ftm_restart(struct iwl_mvm *mvm) | ||
| 92 | { | ||
| 93 | struct cfg80211_pmsr_result result = { | ||
| 94 | .status = NL80211_PMSR_STATUS_FAILURE, | ||
| 95 | .final = 1, | ||
| 96 | .host_time = ktime_get_boot_ns(), | ||
| 97 | .type = NL80211_PMSR_TYPE_FTM, | ||
| 98 | }; | ||
| 99 | int i; | ||
| 100 | |||
| 101 | lockdep_assert_held(&mvm->mutex); | ||
| 102 | |||
| 103 | if (!mvm->ftm_initiator.req) | ||
| 104 | return; | ||
| 105 | |||
| 106 | for (i = 0; i < mvm->ftm_initiator.req->n_peers; i++) { | ||
| 107 | memcpy(result.addr, mvm->ftm_initiator.req->peers[i].addr, | ||
| 108 | ETH_ALEN); | ||
| 109 | result.ftm.burst_index = mvm->ftm_initiator.responses[i]; | ||
| 110 | |||
| 111 | cfg80211_pmsr_report(mvm->ftm_initiator.req_wdev, | ||
| 112 | mvm->ftm_initiator.req, | ||
| 113 | &result, GFP_KERNEL); | ||
| 114 | } | ||
| 115 | |||
| 116 | cfg80211_pmsr_complete(mvm->ftm_initiator.req_wdev, | ||
| 117 | mvm->ftm_initiator.req, GFP_KERNEL); | ||
| 118 | iwl_mvm_ftm_reset(mvm); | ||
| 119 | } | ||
| 120 | |||
| 121 | static int | ||
| 122 | iwl_ftm_range_request_status_to_err(enum iwl_tof_range_request_status s) | ||
| 123 | { | ||
| 124 | switch (s) { | ||
| 125 | case IWL_TOF_RANGE_REQUEST_STATUS_SUCCESS: | ||
| 126 | return 0; | ||
| 127 | case IWL_TOF_RANGE_REQUEST_STATUS_BUSY: | ||
| 128 | return -EBUSY; | ||
| 129 | default: | ||
| 130 | WARN_ON_ONCE(1); | ||
| 131 | return -EIO; | ||
| 132 | } | ||
| 133 | } | ||
| 134 | |||
| 135 | static void iwl_mvm_ftm_cmd_v5(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | ||
| 136 | struct iwl_tof_range_req_cmd_v5 *cmd, | ||
| 137 | struct cfg80211_pmsr_request *req) | ||
| 138 | { | ||
| 139 | int i; | ||
| 140 | |||
| 141 | cmd->request_id = req->cookie; | ||
| 142 | cmd->num_of_ap = req->n_peers; | ||
| 143 | |||
| 144 | /* use maximum for "no timeout" or bigger than what we can do */ | ||
| 145 | if (!req->timeout || req->timeout > 255 * 100) | ||
| 146 | cmd->req_timeout = 255; | ||
| 147 | else | ||
| 148 | cmd->req_timeout = DIV_ROUND_UP(req->timeout, 100); | ||
| 149 | |||
| 150 | /* | ||
| 151 | * We treat it always as random, since if not we'll | ||
| 152 | * have filled our local address there instead. | ||
| 153 | */ | ||
| 154 | cmd->macaddr_random = 1; | ||
| 155 | memcpy(cmd->macaddr_template, req->mac_addr, ETH_ALEN); | ||
| 156 | for (i = 0; i < ETH_ALEN; i++) | ||
| 157 | cmd->macaddr_mask[i] = ~req->mac_addr_mask[i]; | ||
| 158 | |||
| 159 | if (vif->bss_conf.assoc) | ||
| 160 | memcpy(cmd->range_req_bssid, vif->bss_conf.bssid, ETH_ALEN); | ||
| 161 | else | ||
| 162 | eth_broadcast_addr(cmd->range_req_bssid); | ||
| 163 | } | ||
| 164 | |||
| 165 | static void iwl_mvm_ftm_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | ||
| 166 | struct iwl_tof_range_req_cmd *cmd, | ||
| 167 | struct cfg80211_pmsr_request *req) | ||
| 168 | { | ||
| 169 | int i; | ||
| 170 | |||
| 171 | cmd->initiator_flags = | ||
| 172 | cpu_to_le32(IWL_TOF_INITIATOR_FLAGS_MACADDR_RANDOM | | ||
| 173 | IWL_TOF_INITIATOR_FLAGS_NON_ASAP_SUPPORT); | ||
| 174 | cmd->request_id = req->cookie; | ||
| 175 | cmd->num_of_ap = req->n_peers; | ||
| 176 | |||
| 177 | /* | ||
| 178 | * Use a large value for "no timeout". Don't use the maximum value | ||
| 179 | * because of fw limitations. | ||
| 180 | */ | ||
| 181 | if (req->timeout) | ||
| 182 | cmd->req_timeout_ms = cpu_to_le32(req->timeout); | ||
| 183 | else | ||
| 184 | cmd->req_timeout_ms = cpu_to_le32(0xfffff); | ||
| 185 | |||
| 186 | memcpy(cmd->macaddr_template, req->mac_addr, ETH_ALEN); | ||
| 187 | for (i = 0; i < ETH_ALEN; i++) | ||
| 188 | cmd->macaddr_mask[i] = ~req->mac_addr_mask[i]; | ||
| 189 | |||
| 190 | if (vif->bss_conf.assoc) | ||
| 191 | memcpy(cmd->range_req_bssid, vif->bss_conf.bssid, ETH_ALEN); | ||
| 192 | else | ||
| 193 | eth_broadcast_addr(cmd->range_req_bssid); | ||
| 194 | |||
| 195 | /* TODO: fill in tsf_mac_id if needed */ | ||
| 196 | cmd->tsf_mac_id = cpu_to_le32(0xff); | ||
| 197 | } | ||
| 198 | |||
| 199 | static int iwl_mvm_ftm_target_chandef(struct iwl_mvm *mvm, | ||
| 200 | struct cfg80211_pmsr_request_peer *peer, | ||
| 201 | u8 *channel, u8 *bandwidth, | ||
| 202 | u8 *ctrl_ch_position) | ||
| 203 | { | ||
| 204 | u32 freq = peer->chandef.chan->center_freq; | ||
| 205 | |||
| 206 | *channel = ieee80211_frequency_to_channel(freq); | ||
| 207 | |||
| 208 | switch (peer->chandef.width) { | ||
| 209 | case NL80211_CHAN_WIDTH_20_NOHT: | ||
| 210 | *bandwidth = IWL_TOF_BW_20_LEGACY; | ||
| 211 | break; | ||
| 212 | case NL80211_CHAN_WIDTH_20: | ||
| 213 | *bandwidth = IWL_TOF_BW_20_HT; | ||
| 214 | break; | ||
| 215 | case NL80211_CHAN_WIDTH_40: | ||
| 216 | *bandwidth = IWL_TOF_BW_40; | ||
| 217 | break; | ||
| 218 | case NL80211_CHAN_WIDTH_80: | ||
| 219 | *bandwidth = IWL_TOF_BW_80; | ||
| 220 | break; | ||
| 221 | default: | ||
| 222 | IWL_ERR(mvm, "Unsupported BW in FTM request (%d)\n", | ||
| 223 | peer->chandef.width); | ||
| 224 | return -EINVAL; | ||
| 225 | } | ||
| 226 | |||
| 227 | *ctrl_ch_position = (peer->chandef.width > NL80211_CHAN_WIDTH_20) ? | ||
| 228 | iwl_mvm_get_ctrl_pos(&peer->chandef) : 0; | ||
| 229 | |||
| 230 | return 0; | ||
| 231 | } | ||
| 232 | |||
| 233 | static int | ||
| 234 | iwl_mvm_ftm_put_target_v2(struct iwl_mvm *mvm, | ||
| 235 | struct cfg80211_pmsr_request_peer *peer, | ||
| 236 | struct iwl_tof_range_req_ap_entry_v2 *target) | ||
| 237 | { | ||
| 238 | int ret; | ||
| 239 | |||
| 240 | ret = iwl_mvm_ftm_target_chandef(mvm, peer, &target->channel_num, | ||
| 241 | &target->bandwidth, | ||
| 242 | &target->ctrl_ch_position); | ||
| 243 | if (ret) | ||
| 244 | return ret; | ||
| 245 | |||
| 246 | memcpy(target->bssid, peer->addr, ETH_ALEN); | ||
| 247 | target->burst_period = | ||
| 248 | cpu_to_le16(peer->ftm.burst_period); | ||
| 249 | target->samples_per_burst = peer->ftm.ftms_per_burst; | ||
| 250 | target->num_of_bursts = peer->ftm.num_bursts_exp; | ||
| 251 | target->measure_type = 0; /* regular two-sided FTM */ | ||
| 252 | target->retries_per_sample = peer->ftm.ftmr_retries; | ||
| 253 | target->asap_mode = peer->ftm.asap; | ||
| 254 | target->enable_dyn_ack = IWL_MVM_FTM_INITIATOR_DYNACK; | ||
| 255 | |||
| 256 | if (peer->ftm.request_lci) | ||
| 257 | target->location_req |= IWL_TOF_LOC_LCI; | ||
| 258 | if (peer->ftm.request_civicloc) | ||
| 259 | target->location_req |= IWL_TOF_LOC_CIVIC; | ||
| 260 | |||
| 261 | target->algo_type = IWL_MVM_FTM_INITIATOR_ALGO; | ||
| 262 | |||
| 263 | return 0; | ||
| 264 | } | ||
| 265 | |||
| 266 | #define FTM_PUT_FLAG(flag) (target->initiator_ap_flags |= \ | ||
| 267 | cpu_to_le32(IWL_INITIATOR_AP_FLAGS_##flag)) | ||
| 268 | |||
| 269 | static int iwl_mvm_ftm_put_target(struct iwl_mvm *mvm, | ||
| 270 | struct cfg80211_pmsr_request_peer *peer, | ||
| 271 | struct iwl_tof_range_req_ap_entry *target) | ||
| 272 | { | ||
| 273 | int ret; | ||
| 274 | |||
| 275 | ret = iwl_mvm_ftm_target_chandef(mvm, peer, &target->channel_num, | ||
| 276 | &target->bandwidth, | ||
| 277 | &target->ctrl_ch_position); | ||
| 278 | if (ret) | ||
| 279 | return ret; | ||
| 280 | |||
| 281 | memcpy(target->bssid, peer->addr, ETH_ALEN); | ||
| 282 | target->burst_period = | ||
| 283 | cpu_to_le16(peer->ftm.burst_period); | ||
| 284 | target->samples_per_burst = peer->ftm.ftms_per_burst; | ||
| 285 | target->num_of_bursts = peer->ftm.num_bursts_exp; | ||
| 286 | target->ftmr_max_retries = peer->ftm.ftmr_retries; | ||
| 287 | target->initiator_ap_flags = cpu_to_le32(0); | ||
| 288 | |||
| 289 | if (peer->ftm.asap) | ||
| 290 | FTM_PUT_FLAG(ASAP); | ||
| 291 | |||
| 292 | if (peer->ftm.request_lci) | ||
| 293 | FTM_PUT_FLAG(LCI_REQUEST); | ||
| 294 | |||
| 295 | if (peer->ftm.request_civicloc) | ||
| 296 | FTM_PUT_FLAG(CIVIC_REQUEST); | ||
| 297 | |||
| 298 | if (IWL_MVM_FTM_INITIATOR_DYNACK) | ||
| 299 | FTM_PUT_FLAG(DYN_ACK); | ||
| 300 | |||
| 301 | if (IWL_MVM_FTM_INITIATOR_ALGO == IWL_TOF_ALGO_TYPE_LINEAR_REG) | ||
| 302 | FTM_PUT_FLAG(ALGO_LR); | ||
| 303 | else if (IWL_MVM_FTM_INITIATOR_ALGO == IWL_TOF_ALGO_TYPE_FFT) | ||
| 304 | FTM_PUT_FLAG(ALGO_FFT); | ||
| 305 | |||
| 306 | return 0; | ||
| 307 | } | ||
| 308 | |||
| 309 | int iwl_mvm_ftm_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | ||
| 310 | struct cfg80211_pmsr_request *req) | ||
| 311 | { | ||
| 312 | struct iwl_tof_range_req_cmd_v5 cmd_v5; | ||
| 313 | struct iwl_tof_range_req_cmd cmd; | ||
| 314 | bool new_api = fw_has_api(&mvm->fw->ucode_capa, | ||
| 315 | IWL_UCODE_TLV_API_FTM_NEW_RANGE_REQ); | ||
| 316 | u8 num_of_ap; | ||
| 317 | struct iwl_host_cmd hcmd = { | ||
| 318 | .id = iwl_cmd_id(TOF_RANGE_REQ_CMD, LOCATION_GROUP, 0), | ||
| 319 | .dataflags[0] = IWL_HCMD_DFL_DUP, | ||
| 320 | }; | ||
| 321 | u32 status = 0; | ||
| 322 | int err, i; | ||
| 323 | |||
| 324 | lockdep_assert_held(&mvm->mutex); | ||
| 325 | |||
| 326 | if (mvm->ftm_initiator.req) | ||
| 327 | return -EBUSY; | ||
| 328 | |||
| 329 | if (new_api) { | ||
| 330 | iwl_mvm_ftm_cmd(mvm, vif, &cmd, req); | ||
| 331 | hcmd.data[0] = &cmd; | ||
| 332 | hcmd.len[0] = sizeof(cmd); | ||
| 333 | num_of_ap = cmd.num_of_ap; | ||
| 334 | } else { | ||
| 335 | iwl_mvm_ftm_cmd_v5(mvm, vif, &cmd_v5, req); | ||
| 336 | hcmd.data[0] = &cmd_v5; | ||
| 337 | hcmd.len[0] = sizeof(cmd_v5); | ||
| 338 | num_of_ap = cmd_v5.num_of_ap; | ||
| 339 | } | ||
| 340 | |||
| 341 | for (i = 0; i < num_of_ap; i++) { | ||
| 342 | struct cfg80211_pmsr_request_peer *peer = &req->peers[i]; | ||
| 343 | |||
| 344 | if (new_api) | ||
| 345 | err = iwl_mvm_ftm_put_target(mvm, peer, &cmd.ap[i]); | ||
| 346 | else | ||
| 347 | err = iwl_mvm_ftm_put_target_v2(mvm, peer, | ||
| 348 | &cmd_v5.ap[i]); | ||
| 349 | |||
| 350 | if (err) | ||
| 351 | return err; | ||
| 352 | } | ||
| 353 | |||
| 354 | err = iwl_mvm_send_cmd_status(mvm, &hcmd, &status); | ||
| 355 | if (!err && status) { | ||
| 356 | IWL_ERR(mvm, "FTM range request command failure, status: %u\n", | ||
| 357 | status); | ||
| 358 | err = iwl_ftm_range_request_status_to_err(status); | ||
| 359 | } | ||
| 360 | |||
| 361 | if (!err) { | ||
| 362 | mvm->ftm_initiator.req = req; | ||
| 363 | mvm->ftm_initiator.req_wdev = ieee80211_vif_to_wdev(vif); | ||
| 364 | } | ||
| 365 | |||
| 366 | return err; | ||
| 367 | } | ||
| 368 | |||
| 369 | void iwl_mvm_ftm_abort(struct iwl_mvm *mvm, struct cfg80211_pmsr_request *req) | ||
| 370 | { | ||
| 371 | struct iwl_tof_range_abort_cmd cmd = { | ||
| 372 | .request_id = req->cookie, | ||
| 373 | }; | ||
| 374 | |||
| 375 | lockdep_assert_held(&mvm->mutex); | ||
| 376 | |||
| 377 | if (req != mvm->ftm_initiator.req) | ||
| 378 | return; | ||
| 379 | |||
| 380 | if (iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(TOF_RANGE_ABORT_CMD, | ||
| 381 | LOCATION_GROUP, 0), | ||
| 382 | 0, sizeof(cmd), &cmd)) | ||
| 383 | IWL_ERR(mvm, "failed to abort FTM process\n"); | ||
| 384 | } | ||
| 385 | |||
| 386 | static int iwl_mvm_ftm_find_peer(struct cfg80211_pmsr_request *req, | ||
| 387 | const u8 *addr) | ||
| 388 | { | ||
| 389 | int i; | ||
| 390 | |||
| 391 | for (i = 0; i < req->n_peers; i++) { | ||
| 392 | struct cfg80211_pmsr_request_peer *peer = &req->peers[i]; | ||
| 393 | |||
| 394 | if (ether_addr_equal_unaligned(peer->addr, addr)) | ||
| 395 | return i; | ||
| 396 | } | ||
| 397 | |||
| 398 | return -ENOENT; | ||
| 399 | } | ||
| 400 | |||
| 401 | static u64 iwl_mvm_ftm_get_host_time(struct iwl_mvm *mvm, __le32 fw_gp2_ts) | ||
| 402 | { | ||
| 403 | u32 gp2_ts = le32_to_cpu(fw_gp2_ts); | ||
| 404 | u32 curr_gp2, diff; | ||
| 405 | u64 now_from_boot_ns; | ||
| 406 | |||
| 407 | iwl_mvm_get_sync_time(mvm, &curr_gp2, &now_from_boot_ns); | ||
| 408 | |||
| 409 | if (curr_gp2 >= gp2_ts) | ||
| 410 | diff = curr_gp2 - gp2_ts; | ||
| 411 | else | ||
| 412 | diff = curr_gp2 + (U32_MAX - gp2_ts + 1); | ||
| 413 | |||
| 414 | return now_from_boot_ns - (u64)diff * 1000; | ||
| 415 | } | ||
| 416 | |||
| 417 | static void iwl_mvm_ftm_get_lci_civic(struct iwl_mvm *mvm, | ||
| 418 | struct cfg80211_pmsr_result *res) | ||
| 419 | { | ||
| 420 | struct iwl_mvm_loc_entry *entry; | ||
| 421 | |||
| 422 | list_for_each_entry(entry, &mvm->ftm_initiator.loc_list, list) { | ||
| 423 | if (!ether_addr_equal_unaligned(res->addr, entry->addr)) | ||
| 424 | continue; | ||
| 425 | |||
| 426 | if (entry->lci_len) { | ||
| 427 | res->ftm.lci_len = entry->lci_len; | ||
| 428 | res->ftm.lci = entry->buf; | ||
| 429 | } | ||
| 430 | |||
| 431 | if (entry->civic_len) { | ||
| 432 | res->ftm.civicloc_len = entry->civic_len; | ||
| 433 | res->ftm.civicloc = entry->buf + entry->lci_len; | ||
| 434 | } | ||
| 435 | |||
| 436 | /* we found the entry we needed */ | ||
| 437 | break; | ||
| 438 | } | ||
| 439 | } | ||
| 440 | |||
| 441 | static int iwl_mvm_ftm_range_resp_valid(struct iwl_mvm *mvm, u8 request_id, | ||
| 442 | u8 num_of_aps) | ||
| 443 | { | ||
| 444 | lockdep_assert_held(&mvm->mutex); | ||
| 445 | |||
| 446 | if (request_id != (u8)mvm->ftm_initiator.req->cookie) { | ||
| 447 | IWL_ERR(mvm, "Request ID mismatch, got %u, active %u\n", | ||
| 448 | request_id, (u8)mvm->ftm_initiator.req->cookie); | ||
| 449 | return -EINVAL; | ||
| 450 | } | ||
| 451 | |||
| 452 | if (num_of_aps > mvm->ftm_initiator.req->n_peers) { | ||
| 453 | IWL_ERR(mvm, "FTM range response invalid\n"); | ||
| 454 | return -EINVAL; | ||
| 455 | } | ||
| 456 | |||
| 457 | return 0; | ||
| 458 | } | ||
| 459 | |||
| 460 | static void iwl_mvm_debug_range_resp(struct iwl_mvm *mvm, u8 index, | ||
| 461 | struct cfg80211_pmsr_result *res) | ||
| 462 | { | ||
| 463 | s64 rtt_avg = res->ftm.rtt_avg * 100; | ||
| 464 | |||
| 465 | do_div(rtt_avg, 6666); | ||
| 466 | |||
| 467 | IWL_DEBUG_INFO(mvm, "entry %d\n", index); | ||
| 468 | IWL_DEBUG_INFO(mvm, "\tstatus: %d\n", res->status); | ||
| 469 | IWL_DEBUG_INFO(mvm, "\tBSSID: %pM\n", res->addr); | ||
| 470 | IWL_DEBUG_INFO(mvm, "\thost time: %llu\n", res->host_time); | ||
| 471 | IWL_DEBUG_INFO(mvm, "\tburst index: %hhu\n", res->ftm.burst_index); | ||
| 472 | IWL_DEBUG_INFO(mvm, "\tsuccess num: %u\n", res->ftm.num_ftmr_successes); | ||
| 473 | IWL_DEBUG_INFO(mvm, "\trssi: %d\n", res->ftm.rssi_avg); | ||
| 474 | IWL_DEBUG_INFO(mvm, "\trssi spread: %hhu\n", res->ftm.rssi_spread); | ||
| 475 | IWL_DEBUG_INFO(mvm, "\trtt: %lld\n", res->ftm.rtt_avg); | ||
| 476 | IWL_DEBUG_INFO(mvm, "\trtt var: %llu\n", res->ftm.rtt_variance); | ||
| 477 | IWL_DEBUG_INFO(mvm, "\trtt spread: %llu\n", res->ftm.rtt_spread); | ||
| 478 | IWL_DEBUG_INFO(mvm, "\tdistance: %lld\n", rtt_avg); | ||
| 479 | } | ||
| 480 | |||
| 481 | void iwl_mvm_ftm_range_resp(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb) | ||
| 482 | { | ||
| 483 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
| 484 | struct iwl_tof_range_rsp_ntfy_v5 *fw_resp_v5 = (void *)pkt->data; | ||
| 485 | struct iwl_tof_range_rsp_ntfy *fw_resp = (void *)pkt->data; | ||
| 486 | int i; | ||
| 487 | bool new_api = fw_has_api(&mvm->fw->ucode_capa, | ||
| 488 | IWL_UCODE_TLV_API_FTM_NEW_RANGE_REQ); | ||
| 489 | u8 num_of_aps, last_in_batch; | ||
| 490 | |||
| 491 | lockdep_assert_held(&mvm->mutex); | ||
| 492 | |||
| 493 | if (!mvm->ftm_initiator.req) { | ||
| 494 | IWL_ERR(mvm, "Got FTM response but have no request?\n"); | ||
| 495 | return; | ||
| 496 | } | ||
| 497 | |||
| 498 | if (new_api) { | ||
| 499 | if (iwl_mvm_ftm_range_resp_valid(mvm, fw_resp->request_id, | ||
| 500 | fw_resp->num_of_aps)) | ||
| 501 | return; | ||
| 502 | |||
| 503 | num_of_aps = fw_resp->num_of_aps; | ||
| 504 | last_in_batch = fw_resp->last_report; | ||
| 505 | } else { | ||
| 506 | if (iwl_mvm_ftm_range_resp_valid(mvm, fw_resp_v5->request_id, | ||
| 507 | fw_resp_v5->num_of_aps)) | ||
| 508 | return; | ||
| 509 | |||
| 510 | num_of_aps = fw_resp_v5->num_of_aps; | ||
| 511 | last_in_batch = fw_resp_v5->last_in_batch; | ||
| 512 | } | ||
| 513 | |||
| 514 | IWL_DEBUG_INFO(mvm, "Range response received\n"); | ||
| 515 | IWL_DEBUG_INFO(mvm, "request id: %lld, num of entries: %hhu\n", | ||
| 516 | mvm->ftm_initiator.req->cookie, num_of_aps); | ||
| 517 | |||
| 518 | for (i = 0; i < num_of_aps && i < IWL_MVM_TOF_MAX_APS; i++) { | ||
| 519 | struct cfg80211_pmsr_result result = {}; | ||
| 520 | struct iwl_tof_range_rsp_ap_entry_ntfy *fw_ap; | ||
| 521 | int peer_idx; | ||
| 522 | |||
| 523 | if (new_api) { | ||
| 524 | fw_ap = &fw_resp->ap[i]; | ||
| 525 | result.final = fw_resp->ap[i].last_burst; | ||
| 526 | } else { | ||
| 527 | /* the first part is the same for old and new APIs */ | ||
| 528 | fw_ap = (void *)&fw_resp_v5->ap[i]; | ||
| 529 | /* | ||
| 530 | * FIXME: the firmware needs to report this, we don't | ||
| 531 | * even know the number of bursts the responder picked | ||
| 532 | * (if we asked it to) | ||
| 533 | */ | ||
| 534 | result.final = 0; | ||
| 535 | } | ||
| 536 | |||
| 537 | peer_idx = iwl_mvm_ftm_find_peer(mvm->ftm_initiator.req, | ||
| 538 | fw_ap->bssid); | ||
| 539 | if (peer_idx < 0) { | ||
| 540 | IWL_WARN(mvm, | ||
| 541 | "Unknown address (%pM, target #%d) in FTM response\n", | ||
| 542 | fw_ap->bssid, i); | ||
| 543 | continue; | ||
| 544 | } | ||
| 545 | |||
| 546 | switch (fw_ap->measure_status) { | ||
| 547 | case IWL_TOF_ENTRY_SUCCESS: | ||
| 548 | result.status = NL80211_PMSR_STATUS_SUCCESS; | ||
| 549 | break; | ||
| 550 | case IWL_TOF_ENTRY_TIMING_MEASURE_TIMEOUT: | ||
| 551 | result.status = NL80211_PMSR_STATUS_TIMEOUT; | ||
| 552 | break; | ||
| 553 | case IWL_TOF_ENTRY_NO_RESPONSE: | ||
| 554 | result.status = NL80211_PMSR_STATUS_FAILURE; | ||
| 555 | result.ftm.failure_reason = | ||
| 556 | NL80211_PMSR_FTM_FAILURE_NO_RESPONSE; | ||
| 557 | break; | ||
| 558 | case IWL_TOF_ENTRY_REQUEST_REJECTED: | ||
| 559 | result.status = NL80211_PMSR_STATUS_FAILURE; | ||
| 560 | result.ftm.failure_reason = | ||
| 561 | NL80211_PMSR_FTM_FAILURE_PEER_BUSY; | ||
| 562 | result.ftm.busy_retry_time = fw_ap->refusal_period; | ||
| 563 | break; | ||
| 564 | default: | ||
| 565 | result.status = NL80211_PMSR_STATUS_FAILURE; | ||
| 566 | result.ftm.failure_reason = | ||
| 567 | NL80211_PMSR_FTM_FAILURE_UNSPECIFIED; | ||
| 568 | break; | ||
| 569 | } | ||
| 570 | memcpy(result.addr, fw_ap->bssid, ETH_ALEN); | ||
| 571 | result.host_time = iwl_mvm_ftm_get_host_time(mvm, | ||
| 572 | fw_ap->timestamp); | ||
| 573 | result.type = NL80211_PMSR_TYPE_FTM; | ||
| 574 | result.ftm.burst_index = mvm->ftm_initiator.responses[peer_idx]; | ||
| 575 | mvm->ftm_initiator.responses[peer_idx]++; | ||
| 576 | result.ftm.rssi_avg = fw_ap->rssi; | ||
| 577 | result.ftm.rssi_avg_valid = 1; | ||
| 578 | result.ftm.rssi_spread = fw_ap->rssi_spread; | ||
| 579 | result.ftm.rssi_spread_valid = 1; | ||
| 580 | result.ftm.rtt_avg = (s32)le32_to_cpu(fw_ap->rtt); | ||
| 581 | result.ftm.rtt_avg_valid = 1; | ||
| 582 | result.ftm.rtt_variance = le32_to_cpu(fw_ap->rtt_variance); | ||
| 583 | result.ftm.rtt_variance_valid = 1; | ||
| 584 | result.ftm.rtt_spread = le32_to_cpu(fw_ap->rtt_spread); | ||
| 585 | result.ftm.rtt_spread_valid = 1; | ||
| 586 | |||
| 587 | iwl_mvm_ftm_get_lci_civic(mvm, &result); | ||
| 588 | |||
| 589 | cfg80211_pmsr_report(mvm->ftm_initiator.req_wdev, | ||
| 590 | mvm->ftm_initiator.req, | ||
| 591 | &result, GFP_KERNEL); | ||
| 592 | |||
| 593 | iwl_mvm_debug_range_resp(mvm, i, &result); | ||
| 594 | } | ||
| 595 | |||
| 596 | if (last_in_batch) { | ||
| 597 | cfg80211_pmsr_complete(mvm->ftm_initiator.req_wdev, | ||
| 598 | mvm->ftm_initiator.req, | ||
| 599 | GFP_KERNEL); | ||
| 600 | iwl_mvm_ftm_reset(mvm); | ||
| 601 | } | ||
| 602 | } | ||
| 603 | |||
| 604 | void iwl_mvm_ftm_lc_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb) | ||
| 605 | { | ||
| 606 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
| 607 | const struct ieee80211_mgmt *mgmt = (void *)pkt->data; | ||
| 608 | size_t len = iwl_rx_packet_payload_len(pkt); | ||
| 609 | struct iwl_mvm_loc_entry *entry; | ||
| 610 | const u8 *ies, *lci, *civic, *msr_ie; | ||
| 611 | size_t ies_len, lci_len = 0, civic_len = 0; | ||
| 612 | size_t baselen = IEEE80211_MIN_ACTION_SIZE + | ||
| 613 | sizeof(mgmt->u.action.u.ftm); | ||
| 614 | static const u8 rprt_type_lci = IEEE80211_SPCT_MSR_RPRT_TYPE_LCI; | ||
| 615 | static const u8 rprt_type_civic = IEEE80211_SPCT_MSR_RPRT_TYPE_CIVIC; | ||
| 616 | |||
| 617 | if (len <= baselen) | ||
| 618 | return; | ||
| 619 | |||
| 620 | lockdep_assert_held(&mvm->mutex); | ||
| 621 | |||
| 622 | ies = mgmt->u.action.u.ftm.variable; | ||
| 623 | ies_len = len - baselen; | ||
| 624 | |||
| 625 | msr_ie = cfg80211_find_ie_match(WLAN_EID_MEASURE_REPORT, ies, ies_len, | ||
| 626 | &rprt_type_lci, 1, 4); | ||
| 627 | if (msr_ie) { | ||
| 628 | lci = msr_ie + 2; | ||
| 629 | lci_len = msr_ie[1]; | ||
| 630 | } | ||
| 631 | |||
| 632 | msr_ie = cfg80211_find_ie_match(WLAN_EID_MEASURE_REPORT, ies, ies_len, | ||
| 633 | &rprt_type_civic, 1, 4); | ||
| 634 | if (msr_ie) { | ||
| 635 | civic = msr_ie + 2; | ||
| 636 | civic_len = msr_ie[1]; | ||
| 637 | } | ||
| 638 | |||
| 639 | entry = kmalloc(sizeof(*entry) + lci_len + civic_len, GFP_KERNEL); | ||
| 640 | if (!entry) | ||
| 641 | return; | ||
| 642 | |||
| 643 | memcpy(entry->addr, mgmt->bssid, ETH_ALEN); | ||
| 644 | |||
| 645 | entry->lci_len = lci_len; | ||
| 646 | if (lci_len) | ||
| 647 | memcpy(entry->buf, lci, lci_len); | ||
| 648 | |||
| 649 | entry->civic_len = civic_len; | ||
| 650 | if (civic_len) | ||
| 651 | memcpy(entry->buf + lci_len, civic, civic_len); | ||
| 652 | |||
| 653 | list_add_tail(&entry->list, &mvm->ftm_initiator.loc_list); | ||
| 654 | } | ||
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c new file mode 100644 index 000000000000..1513b8b4062f --- /dev/null +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c | |||
| @@ -0,0 +1,244 @@ | |||
| 1 | /****************************************************************************** | ||
| 2 | * | ||
| 3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
| 4 | * redistributing this file, you may do so under either license. | ||
| 5 | * | ||
| 6 | * GPL LICENSE SUMMARY | ||
| 7 | * | ||
| 8 | * Copyright(c) 2015 - 2017 Intel Deutschland GmbH | ||
| 9 | * Copyright (C) 2018 Intel Corporation | ||
| 10 | * | ||
| 11 | * 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 | * published by the Free Software Foundation. | ||
| 14 | * | ||
| 15 | * This program is distributed in the hope that it will be useful, but | ||
| 16 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 18 | * General Public License for more details. | ||
| 19 | * | ||
| 20 | * The full GNU General Public License is included in this distribution | ||
| 21 | * in the file called COPYING. | ||
| 22 | * | ||
| 23 | * Contact Information: | ||
| 24 | * Intel Linux Wireless <linuxwifi@intel.com> | ||
| 25 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
| 26 | * | ||
| 27 | * BSD LICENSE | ||
| 28 | * | ||
| 29 | * Copyright(c) 2015 - 2017 Intel Deutschland GmbH | ||
| 30 | * Copyright (C) 2018 Intel Corporation | ||
| 31 | * All rights reserved. | ||
| 32 | * | ||
| 33 | * Redistribution and use in source and binary forms, with or without | ||
| 34 | * modification, are permitted provided that the following conditions | ||
| 35 | * are met: | ||
| 36 | * | ||
| 37 | * * Redistributions of source code must retain the above copyright | ||
| 38 | * notice, this list of conditions and the following disclaimer. | ||
| 39 | * * Redistributions in binary form must reproduce the above copyright | ||
| 40 | * notice, this list of conditions and the following disclaimer in | ||
| 41 | * the documentation and/or other materials provided with the | ||
| 42 | * distribution. | ||
| 43 | * * Neither the name Intel Corporation nor the names of its | ||
| 44 | * contributors may be used to endorse or promote products derived | ||
| 45 | * from this software without specific prior written permission. | ||
| 46 | * | ||
| 47 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
| 48 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
| 49 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
| 50 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
| 51 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
| 52 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
| 53 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
| 54 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
| 55 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
| 56 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
| 57 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 58 | * | ||
| 59 | *****************************************************************************/ | ||
| 60 | #include <net/cfg80211.h> | ||
| 61 | #include <linux/etherdevice.h> | ||
| 62 | #include "mvm.h" | ||
| 63 | #include "constants.h" | ||
| 64 | |||
| 65 | static int | ||
| 66 | iwl_mvm_ftm_responder_cmd(struct iwl_mvm *mvm, | ||
| 67 | struct ieee80211_vif *vif, | ||
| 68 | struct cfg80211_chan_def *chandef) | ||
| 69 | { | ||
| 70 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
| 71 | struct iwl_tof_responder_config_cmd cmd = { | ||
| 72 | .channel_num = chandef->chan->hw_value, | ||
| 73 | .cmd_valid_fields = | ||
| 74 | cpu_to_le32(IWL_TOF_RESPONDER_CMD_VALID_CHAN_INFO | | ||
| 75 | IWL_TOF_RESPONDER_CMD_VALID_BSSID | | ||
| 76 | IWL_TOF_RESPONDER_CMD_VALID_STA_ID), | ||
| 77 | .sta_id = mvmvif->bcast_sta.sta_id, | ||
| 78 | }; | ||
| 79 | |||
| 80 | lockdep_assert_held(&mvm->mutex); | ||
| 81 | |||
| 82 | switch (chandef->width) { | ||
| 83 | case NL80211_CHAN_WIDTH_20_NOHT: | ||
| 84 | cmd.bandwidth = IWL_TOF_BW_20_LEGACY; | ||
| 85 | break; | ||
| 86 | case NL80211_CHAN_WIDTH_20: | ||
| 87 | cmd.bandwidth = IWL_TOF_BW_20_HT; | ||
| 88 | break; | ||
| 89 | case NL80211_CHAN_WIDTH_40: | ||
| 90 | cmd.bandwidth = IWL_TOF_BW_40; | ||
| 91 | cmd.ctrl_ch_position = iwl_mvm_get_ctrl_pos(chandef); | ||
| 92 | break; | ||
| 93 | case NL80211_CHAN_WIDTH_80: | ||
| 94 | cmd.bandwidth = IWL_TOF_BW_80; | ||
| 95 | cmd.ctrl_ch_position = iwl_mvm_get_ctrl_pos(chandef); | ||
| 96 | break; | ||
| 97 | default: | ||
| 98 | WARN_ON(1); | ||
| 99 | return -EINVAL; | ||
| 100 | } | ||
| 101 | |||
| 102 | memcpy(cmd.bssid, vif->addr, ETH_ALEN); | ||
| 103 | |||
| 104 | return iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(TOF_RESPONDER_CONFIG_CMD, | ||
| 105 | LOCATION_GROUP, 0), | ||
| 106 | 0, sizeof(cmd), &cmd); | ||
| 107 | } | ||
| 108 | |||
| 109 | static int | ||
| 110 | iwl_mvm_ftm_responder_dyn_cfg_cmd(struct iwl_mvm *mvm, | ||
| 111 | struct ieee80211_vif *vif, | ||
| 112 | struct ieee80211_ftm_responder_params *params) | ||
| 113 | { | ||
| 114 | struct iwl_tof_responder_dyn_config_cmd cmd = { | ||
| 115 | .lci_len = cpu_to_le32(params->lci_len + 2), | ||
| 116 | .civic_len = cpu_to_le32(params->civicloc_len + 2), | ||
| 117 | }; | ||
| 118 | u8 data[IWL_LCI_CIVIC_IE_MAX_SIZE] = {0}; | ||
| 119 | struct iwl_host_cmd hcmd = { | ||
| 120 | .id = iwl_cmd_id(TOF_RESPONDER_DYN_CONFIG_CMD, | ||
| 121 | LOCATION_GROUP, 0), | ||
| 122 | .data[0] = &cmd, | ||
| 123 | .len[0] = sizeof(cmd), | ||
| 124 | .data[1] = &data, | ||
| 125 | /* .len[1] set later */ | ||
| 126 | /* may not be able to DMA from stack */ | ||
| 127 | .dataflags[1] = IWL_HCMD_DFL_DUP, | ||
| 128 | }; | ||
| 129 | u32 aligned_lci_len = ALIGN(params->lci_len + 2, 4); | ||
| 130 | u32 aligned_civicloc_len = ALIGN(params->civicloc_len + 2, 4); | ||
| 131 | u8 *pos = data; | ||
| 132 | |||
| 133 | lockdep_assert_held(&mvm->mutex); | ||
| 134 | |||
| 135 | if (aligned_lci_len + aligned_civicloc_len > sizeof(data)) { | ||
| 136 | IWL_ERR(mvm, "LCI/civicloc data too big (%zd + %zd)\n", | ||
| 137 | params->lci_len, params->civicloc_len); | ||
| 138 | return -ENOBUFS; | ||
| 139 | } | ||
| 140 | |||
| 141 | pos[0] = WLAN_EID_MEASURE_REPORT; | ||
| 142 | pos[1] = params->lci_len; | ||
| 143 | memcpy(pos + 2, params->lci, params->lci_len); | ||
| 144 | |||
| 145 | pos += aligned_lci_len; | ||
| 146 | pos[0] = WLAN_EID_MEASURE_REPORT; | ||
| 147 | pos[1] = params->civicloc_len; | ||
| 148 | memcpy(pos + 2, params->civicloc, params->civicloc_len); | ||
| 149 | |||
| 150 | hcmd.len[1] = aligned_lci_len + aligned_civicloc_len; | ||
| 151 | |||
| 152 | return iwl_mvm_send_cmd(mvm, &hcmd); | ||
| 153 | } | ||
| 154 | |||
| 155 | int iwl_mvm_ftm_start_responder(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | ||
| 156 | { | ||
| 157 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
| 158 | struct ieee80211_ftm_responder_params *params; | ||
| 159 | struct ieee80211_chanctx_conf ctx, *pctx; | ||
| 160 | u16 *phy_ctxt_id; | ||
| 161 | struct iwl_mvm_phy_ctxt *phy_ctxt; | ||
| 162 | int ret; | ||
| 163 | |||
| 164 | params = vif->bss_conf.ftmr_params; | ||
| 165 | |||
| 166 | lockdep_assert_held(&mvm->mutex); | ||
| 167 | |||
| 168 | if (WARN_ON_ONCE(!vif->bss_conf.ftm_responder)) | ||
| 169 | return -EINVAL; | ||
| 170 | |||
| 171 | if (vif->p2p || vif->type != NL80211_IFTYPE_AP || | ||
| 172 | !mvmvif->ap_ibss_active) { | ||
| 173 | IWL_ERR(mvm, "Cannot start responder, not in AP mode\n"); | ||
| 174 | return -EIO; | ||
| 175 | } | ||
| 176 | |||
| 177 | rcu_read_lock(); | ||
| 178 | pctx = rcu_dereference(vif->chanctx_conf); | ||
| 179 | /* Copy the ctx to unlock the rcu and send the phy ctxt. We don't care | ||
| 180 | * about changes in the ctx after releasing the lock because the driver | ||
| 181 | * is still protected by the mutex. */ | ||
| 182 | ctx = *pctx; | ||
| 183 | phy_ctxt_id = (u16 *)pctx->drv_priv; | ||
| 184 | rcu_read_unlock(); | ||
| 185 | |||
| 186 | phy_ctxt = &mvm->phy_ctxts[*phy_ctxt_id]; | ||
| 187 | ret = iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &ctx.def, | ||
| 188 | ctx.rx_chains_static, | ||
| 189 | ctx.rx_chains_dynamic); | ||
| 190 | if (ret) | ||
| 191 | return ret; | ||
| 192 | |||
| 193 | ret = iwl_mvm_ftm_responder_cmd(mvm, vif, &ctx.def); | ||
| 194 | if (ret) | ||
| 195 | return ret; | ||
| 196 | |||
| 197 | if (params) | ||
| 198 | ret = iwl_mvm_ftm_responder_dyn_cfg_cmd(mvm, vif, params); | ||
| 199 | |||
| 200 | return ret; | ||
| 201 | } | ||
| 202 | |||
| 203 | void iwl_mvm_ftm_restart_responder(struct iwl_mvm *mvm, | ||
| 204 | struct ieee80211_vif *vif) | ||
| 205 | { | ||
| 206 | if (!vif->bss_conf.ftm_responder) | ||
| 207 | return; | ||
| 208 | |||
| 209 | iwl_mvm_ftm_start_responder(mvm, vif); | ||
| 210 | } | ||
| 211 | |||
| 212 | void iwl_mvm_ftm_responder_stats(struct iwl_mvm *mvm, | ||
| 213 | struct iwl_rx_cmd_buffer *rxb) | ||
| 214 | { | ||
| 215 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
| 216 | struct iwl_ftm_responder_stats *resp = (void *)pkt->data; | ||
| 217 | struct cfg80211_ftm_responder_stats *stats = &mvm->ftm_resp_stats; | ||
| 218 | u32 flags = le32_to_cpu(resp->flags); | ||
| 219 | |||
| 220 | if (resp->success_ftm == resp->ftm_per_burst) | ||
| 221 | stats->success_num++; | ||
| 222 | else if (resp->success_ftm >= 2) | ||
| 223 | stats->partial_num++; | ||
| 224 | else | ||
| 225 | stats->failed_num++; | ||
| 226 | |||
| 227 | if ((flags & FTM_RESP_STAT_ASAP_REQ) && | ||
| 228 | (flags & FTM_RESP_STAT_ASAP_RESP)) | ||
| 229 | stats->asap_num++; | ||
| 230 | |||
| 231 | if (flags & FTM_RESP_STAT_NON_ASAP_RESP) | ||
| 232 | stats->non_asap_num++; | ||
| 233 | |||
| 234 | stats->total_duration_ms += le32_to_cpu(resp->duration) / USEC_PER_MSEC; | ||
| 235 | |||
| 236 | if (flags & FTM_RESP_STAT_TRIGGER_UNKNOWN) | ||
| 237 | stats->unknown_triggers_num++; | ||
| 238 | |||
| 239 | if (flags & FTM_RESP_STAT_DUP) | ||
| 240 | stats->reschedule_requests_num++; | ||
| 241 | |||
| 242 | if (flags & FTM_RESP_STAT_NON_ASAP_OUT_WIN) | ||
| 243 | stats->out_of_window_triggers_num++; | ||
| 244 | } | ||
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index d3dc9d276e0f..00a47f6f1d81 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
| 10 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH | 10 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH |
| 11 | * Copyright(c) 2018 Intel Corporation | 11 | * Copyright(c) 2018 - 2019 Intel Corporation |
| 12 | * | 12 | * |
| 13 | * This program is free software; you can redistribute it and/or modify | 13 | * This program is free software; you can redistribute it and/or modify |
| 14 | * it under the terms of version 2 of the GNU General Public License as | 14 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -31,7 +31,7 @@ | |||
| 31 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. | 31 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 32 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 32 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
| 33 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH | 33 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH |
| 34 | * Copyright(c) 2018 Intel Corporation | 34 | * Copyright(c) 2018 - 2019 Intel Corporation |
| 35 | * All rights reserved. | 35 | * All rights reserved. |
| 36 | * | 36 | * |
| 37 | * Redistribution and use in source and binary forms, with or without | 37 | * Redistribution and use in source and binary forms, with or without |
| @@ -105,12 +105,12 @@ static int iwl_send_rss_cfg_cmd(struct iwl_mvm *mvm) | |||
| 105 | int i; | 105 | int i; |
| 106 | struct iwl_rss_config_cmd cmd = { | 106 | struct iwl_rss_config_cmd cmd = { |
| 107 | .flags = cpu_to_le32(IWL_RSS_ENABLE), | 107 | .flags = cpu_to_le32(IWL_RSS_ENABLE), |
| 108 | .hash_mask = IWL_RSS_HASH_TYPE_IPV4_TCP | | 108 | .hash_mask = BIT(IWL_RSS_HASH_TYPE_IPV4_TCP) | |
| 109 | IWL_RSS_HASH_TYPE_IPV4_UDP | | 109 | BIT(IWL_RSS_HASH_TYPE_IPV4_UDP) | |
| 110 | IWL_RSS_HASH_TYPE_IPV4_PAYLOAD | | 110 | BIT(IWL_RSS_HASH_TYPE_IPV4_PAYLOAD) | |
| 111 | IWL_RSS_HASH_TYPE_IPV6_TCP | | 111 | BIT(IWL_RSS_HASH_TYPE_IPV6_TCP) | |
| 112 | IWL_RSS_HASH_TYPE_IPV6_UDP | | 112 | BIT(IWL_RSS_HASH_TYPE_IPV6_UDP) | |
| 113 | IWL_RSS_HASH_TYPE_IPV6_PAYLOAD, | 113 | BIT(IWL_RSS_HASH_TYPE_IPV6_PAYLOAD), |
| 114 | }; | 114 | }; |
| 115 | 115 | ||
| 116 | if (mvm->trans->num_rx_queues == 1) | 116 | if (mvm->trans->num_rx_queues == 1) |
| @@ -127,13 +127,17 @@ static int iwl_send_rss_cfg_cmd(struct iwl_mvm *mvm) | |||
| 127 | 127 | ||
| 128 | static int iwl_configure_rxq(struct iwl_mvm *mvm) | 128 | static int iwl_configure_rxq(struct iwl_mvm *mvm) |
| 129 | { | 129 | { |
| 130 | int i, num_queues, size; | 130 | int i, num_queues, size, ret; |
| 131 | struct iwl_rfh_queue_config *cmd; | 131 | struct iwl_rfh_queue_config *cmd; |
| 132 | struct iwl_host_cmd hcmd = { | ||
| 133 | .id = WIDE_ID(DATA_PATH_GROUP, RFH_QUEUE_CONFIG_CMD), | ||
| 134 | .dataflags[0] = IWL_HCMD_DFL_NOCOPY, | ||
| 135 | }; | ||
| 132 | 136 | ||
| 133 | /* Do not configure default queue, it is configured via context info */ | 137 | /* Do not configure default queue, it is configured via context info */ |
| 134 | num_queues = mvm->trans->num_rx_queues - 1; | 138 | num_queues = mvm->trans->num_rx_queues - 1; |
| 135 | 139 | ||
| 136 | size = sizeof(*cmd) + num_queues * sizeof(struct iwl_rfh_queue_data); | 140 | size = struct_size(cmd, data, num_queues); |
| 137 | 141 | ||
| 138 | cmd = kzalloc(size, GFP_KERNEL); | 142 | cmd = kzalloc(size, GFP_KERNEL); |
| 139 | if (!cmd) | 143 | if (!cmd) |
| @@ -154,10 +158,14 @@ static int iwl_configure_rxq(struct iwl_mvm *mvm) | |||
| 154 | cmd->data[i].fr_bd_wid = cpu_to_le32(data.fr_bd_wid); | 158 | cmd->data[i].fr_bd_wid = cpu_to_le32(data.fr_bd_wid); |
| 155 | } | 159 | } |
| 156 | 160 | ||
| 157 | return iwl_mvm_send_cmd_pdu(mvm, | 161 | hcmd.data[0] = cmd; |
| 158 | WIDE_ID(DATA_PATH_GROUP, | 162 | hcmd.len[0] = size; |
| 159 | RFH_QUEUE_CONFIG_CMD), | 163 | |
| 160 | 0, size, cmd); | 164 | ret = iwl_mvm_send_cmd(mvm, &hcmd); |
| 165 | |||
| 166 | kfree(cmd); | ||
| 167 | |||
| 168 | return ret; | ||
| 161 | } | 169 | } |
| 162 | 170 | ||
| 163 | static int iwl_mvm_send_dqa_cmd(struct iwl_mvm *mvm) | 171 | static int iwl_mvm_send_dqa_cmd(struct iwl_mvm *mvm) |
| @@ -210,7 +218,7 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait, | |||
| 210 | struct iwl_lmac_alive *lmac1; | 218 | struct iwl_lmac_alive *lmac1; |
| 211 | struct iwl_lmac_alive *lmac2 = NULL; | 219 | struct iwl_lmac_alive *lmac2 = NULL; |
| 212 | u16 status; | 220 | u16 status; |
| 213 | u32 umac_error_event_table; | 221 | u32 lmac_error_event_table, umac_error_event_table; |
| 214 | 222 | ||
| 215 | if (iwl_rx_packet_payload_len(pkt) == sizeof(*palive)) { | 223 | if (iwl_rx_packet_payload_len(pkt) == sizeof(*palive)) { |
| 216 | palive = (void *)pkt->data; | 224 | palive = (void *)pkt->data; |
| @@ -225,30 +233,35 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait, | |||
| 225 | status = le16_to_cpu(palive3->status); | 233 | status = le16_to_cpu(palive3->status); |
| 226 | } | 234 | } |
| 227 | 235 | ||
| 228 | mvm->error_event_table[0] = le32_to_cpu(lmac1->error_event_table_ptr); | 236 | lmac_error_event_table = |
| 237 | le32_to_cpu(lmac1->dbg_ptrs.error_event_table_ptr); | ||
| 238 | iwl_fw_lmac1_set_alive_err_table(mvm->trans, lmac_error_event_table); | ||
| 239 | |||
| 229 | if (lmac2) | 240 | if (lmac2) |
| 230 | mvm->error_event_table[1] = | 241 | mvm->trans->lmac_error_event_table[1] = |
| 231 | le32_to_cpu(lmac2->error_event_table_ptr); | 242 | le32_to_cpu(lmac2->dbg_ptrs.error_event_table_ptr); |
| 232 | mvm->log_event_table = le32_to_cpu(lmac1->log_event_table_ptr); | ||
| 233 | 243 | ||
| 234 | umac_error_event_table = le32_to_cpu(umac->error_info_addr); | 244 | umac_error_event_table = le32_to_cpu(umac->dbg_ptrs.error_info_addr); |
| 235 | 245 | ||
| 236 | if (!umac_error_event_table) { | 246 | if (!umac_error_event_table) { |
| 237 | mvm->support_umac_log = false; | 247 | mvm->support_umac_log = false; |
| 238 | } else if (umac_error_event_table >= | 248 | } else if (umac_error_event_table >= |
| 239 | mvm->trans->cfg->min_umac_error_event_table) { | 249 | mvm->trans->cfg->min_umac_error_event_table) { |
| 240 | mvm->support_umac_log = true; | 250 | mvm->support_umac_log = true; |
| 241 | mvm->umac_error_event_table = umac_error_event_table; | ||
| 242 | } else { | 251 | } else { |
| 243 | IWL_ERR(mvm, | 252 | IWL_ERR(mvm, |
| 244 | "Not valid error log pointer 0x%08X for %s uCode\n", | 253 | "Not valid error log pointer 0x%08X for %s uCode\n", |
| 245 | mvm->umac_error_event_table, | 254 | umac_error_event_table, |
| 246 | (mvm->fwrt.cur_fw_img == IWL_UCODE_INIT) ? | 255 | (mvm->fwrt.cur_fw_img == IWL_UCODE_INIT) ? |
| 247 | "Init" : "RT"); | 256 | "Init" : "RT"); |
| 248 | mvm->support_umac_log = false; | 257 | mvm->support_umac_log = false; |
| 249 | } | 258 | } |
| 250 | 259 | ||
| 251 | alive_data->scd_base_addr = le32_to_cpu(lmac1->scd_base_ptr); | 260 | if (mvm->support_umac_log) |
| 261 | iwl_fw_umac_set_alive_err_table(mvm->trans, | ||
| 262 | umac_error_event_table); | ||
| 263 | |||
| 264 | alive_data->scd_base_addr = le32_to_cpu(lmac1->dbg_ptrs.scd_base_ptr); | ||
| 252 | alive_data->valid = status == IWL_ALIVE_STATUS_OK; | 265 | alive_data->valid = status == IWL_ALIVE_STATUS_OK; |
| 253 | 266 | ||
| 254 | IWL_DEBUG_FW(mvm, | 267 | IWL_DEBUG_FW(mvm, |
| @@ -299,7 +312,6 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm, | |||
| 299 | enum iwl_ucode_type old_type = mvm->fwrt.cur_fw_img; | 312 | enum iwl_ucode_type old_type = mvm->fwrt.cur_fw_img; |
| 300 | static const u16 alive_cmd[] = { MVM_ALIVE }; | 313 | static const u16 alive_cmd[] = { MVM_ALIVE }; |
| 301 | 314 | ||
| 302 | set_bit(IWL_FWRT_STATUS_WAIT_ALIVE, &mvm->fwrt.status); | ||
| 303 | if (ucode_type == IWL_UCODE_REGULAR && | 315 | if (ucode_type == IWL_UCODE_REGULAR && |
| 304 | iwl_fw_dbg_conf_usniffer(mvm->fw, FW_DBG_START_FROM_ALIVE) && | 316 | iwl_fw_dbg_conf_usniffer(mvm->fw, FW_DBG_START_FROM_ALIVE) && |
| 305 | !(fw_has_capa(&mvm->fw->ucode_capa, | 317 | !(fw_has_capa(&mvm->fw->ucode_capa, |
| @@ -332,11 +344,16 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm, | |||
| 332 | if (ret) { | 344 | if (ret) { |
| 333 | struct iwl_trans *trans = mvm->trans; | 345 | struct iwl_trans *trans = mvm->trans; |
| 334 | 346 | ||
| 347 | if (ret == -ETIMEDOUT) | ||
| 348 | iwl_fw_dbg_error_collect(&mvm->fwrt, | ||
| 349 | FW_DBG_TRIGGER_ALIVE_TIMEOUT); | ||
| 350 | |||
| 335 | if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22000) | 351 | if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22000) |
| 336 | IWL_ERR(mvm, | 352 | IWL_ERR(mvm, |
| 337 | "SecBoot CPU1 Status: 0x%x, CPU2 Status: 0x%x\n", | 353 | "SecBoot CPU1 Status: 0x%x, CPU2 Status: 0x%x\n", |
| 338 | iwl_read_prph(trans, UMAG_SB_CPU_1_STATUS), | 354 | iwl_read_umac_prph(trans, UMAG_SB_CPU_1_STATUS), |
| 339 | iwl_read_prph(trans, UMAG_SB_CPU_2_STATUS)); | 355 | iwl_read_umac_prph(trans, |
| 356 | UMAG_SB_CPU_2_STATUS)); | ||
| 340 | else if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_8000) | 357 | else if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_8000) |
| 341 | IWL_ERR(mvm, | 358 | IWL_ERR(mvm, |
| 342 | "SecBoot CPU1 Status: 0x%x, CPU2 Status: 0x%x\n", | 359 | "SecBoot CPU1 Status: 0x%x, CPU2 Status: 0x%x\n", |
| @@ -377,7 +394,6 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm, | |||
| 377 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 394 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
| 378 | iwl_fw_set_dbg_rec_on(&mvm->fwrt); | 395 | iwl_fw_set_dbg_rec_on(&mvm->fwrt); |
| 379 | #endif | 396 | #endif |
| 380 | clear_bit(IWL_FWRT_STATUS_WAIT_ALIVE, &mvm->fwrt.status); | ||
| 381 | 397 | ||
| 382 | return 0; | 398 | return 0; |
| 383 | } | 399 | } |
| @@ -403,13 +419,15 @@ static int iwl_run_unified_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) | |||
| 403 | iwl_wait_init_complete, | 419 | iwl_wait_init_complete, |
| 404 | NULL); | 420 | NULL); |
| 405 | 421 | ||
| 422 | iwl_fw_dbg_apply_point(&mvm->fwrt, IWL_FW_INI_APPLY_EARLY); | ||
| 423 | |||
| 406 | /* Will also start the device */ | 424 | /* Will also start the device */ |
| 407 | ret = iwl_mvm_load_ucode_wait_alive(mvm, IWL_UCODE_REGULAR); | 425 | ret = iwl_mvm_load_ucode_wait_alive(mvm, IWL_UCODE_REGULAR); |
| 408 | if (ret) { | 426 | if (ret) { |
| 409 | IWL_ERR(mvm, "Failed to start RT ucode: %d\n", ret); | 427 | IWL_ERR(mvm, "Failed to start RT ucode: %d\n", ret); |
| 410 | iwl_fw_assert_error_dump(&mvm->fwrt); | ||
| 411 | goto error; | 428 | goto error; |
| 412 | } | 429 | } |
| 430 | iwl_fw_dbg_apply_point(&mvm->fwrt, IWL_FW_INI_APPLY_AFTER_ALIVE); | ||
| 413 | 431 | ||
| 414 | /* Send init config command to mark that we are sending NVM access | 432 | /* Send init config command to mark that we are sending NVM access |
| 415 | * commands | 433 | * commands |
| @@ -628,10 +646,10 @@ static int iwl_mvm_config_ltr(struct iwl_mvm *mvm) | |||
| 628 | } | 646 | } |
| 629 | 647 | ||
| 630 | #ifdef CONFIG_ACPI | 648 | #ifdef CONFIG_ACPI |
| 631 | static int iwl_mvm_sar_set_profile(struct iwl_mvm *mvm, | 649 | static inline int iwl_mvm_sar_set_profile(struct iwl_mvm *mvm, |
| 632 | union acpi_object *table, | 650 | union acpi_object *table, |
| 633 | struct iwl_mvm_sar_profile *profile, | 651 | struct iwl_mvm_sar_profile *profile, |
| 634 | bool enabled) | 652 | bool enabled) |
| 635 | { | 653 | { |
| 636 | int i; | 654 | int i; |
| 637 | 655 | ||
| @@ -962,6 +980,57 @@ int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm) | |||
| 962 | } | 980 | } |
| 963 | #endif /* CONFIG_ACPI */ | 981 | #endif /* CONFIG_ACPI */ |
| 964 | 982 | ||
| 983 | void iwl_mvm_send_recovery_cmd(struct iwl_mvm *mvm, u32 flags) | ||
| 984 | { | ||
| 985 | u32 error_log_size = mvm->fw->ucode_capa.error_log_size; | ||
| 986 | int ret; | ||
| 987 | u32 resp; | ||
| 988 | |||
| 989 | struct iwl_fw_error_recovery_cmd recovery_cmd = { | ||
| 990 | .flags = cpu_to_le32(flags), | ||
| 991 | .buf_size = 0, | ||
| 992 | }; | ||
| 993 | struct iwl_host_cmd host_cmd = { | ||
| 994 | .id = WIDE_ID(SYSTEM_GROUP, FW_ERROR_RECOVERY_CMD), | ||
| 995 | .flags = CMD_WANT_SKB, | ||
| 996 | .data = {&recovery_cmd, }, | ||
| 997 | .len = {sizeof(recovery_cmd), }, | ||
| 998 | }; | ||
| 999 | |||
| 1000 | /* no error log was defined in TLV */ | ||
| 1001 | if (!error_log_size) | ||
| 1002 | return; | ||
| 1003 | |||
| 1004 | if (flags & ERROR_RECOVERY_UPDATE_DB) { | ||
| 1005 | /* no buf was allocated while HW reset */ | ||
| 1006 | if (!mvm->error_recovery_buf) | ||
| 1007 | return; | ||
| 1008 | |||
| 1009 | host_cmd.data[1] = mvm->error_recovery_buf; | ||
| 1010 | host_cmd.len[1] = error_log_size; | ||
| 1011 | host_cmd.dataflags[1] = IWL_HCMD_DFL_NOCOPY; | ||
| 1012 | recovery_cmd.buf_size = cpu_to_le32(error_log_size); | ||
| 1013 | } | ||
| 1014 | |||
| 1015 | ret = iwl_mvm_send_cmd(mvm, &host_cmd); | ||
| 1016 | kfree(mvm->error_recovery_buf); | ||
| 1017 | mvm->error_recovery_buf = NULL; | ||
| 1018 | |||
| 1019 | if (ret) { | ||
| 1020 | IWL_ERR(mvm, "Failed to send recovery cmd %d\n", ret); | ||
| 1021 | return; | ||
| 1022 | } | ||
| 1023 | |||
| 1024 | /* skb respond is only relevant in ERROR_RECOVERY_UPDATE_DB */ | ||
| 1025 | if (flags & ERROR_RECOVERY_UPDATE_DB) { | ||
| 1026 | resp = le32_to_cpu(*(__le32 *)host_cmd.resp_pkt->data); | ||
| 1027 | if (resp) | ||
| 1028 | IWL_ERR(mvm, | ||
| 1029 | "Failed to send recovery cmd blob was invalid %d\n", | ||
| 1030 | resp); | ||
| 1031 | } | ||
| 1032 | } | ||
| 1033 | |||
| 965 | static int iwl_mvm_sar_init(struct iwl_mvm *mvm) | 1034 | static int iwl_mvm_sar_init(struct iwl_mvm *mvm) |
| 966 | { | 1035 | { |
| 967 | int ret; | 1036 | int ret; |
| @@ -1052,7 +1121,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm) | |||
| 1052 | ret = iwl_mvm_load_rt_fw(mvm); | 1121 | ret = iwl_mvm_load_rt_fw(mvm); |
| 1053 | if (ret) { | 1122 | if (ret) { |
| 1054 | IWL_ERR(mvm, "Failed to start RT ucode: %d\n", ret); | 1123 | IWL_ERR(mvm, "Failed to start RT ucode: %d\n", ret); |
| 1055 | iwl_fw_assert_error_dump(&mvm->fwrt); | 1124 | iwl_fw_dbg_error_collect(&mvm->fwrt, FW_DBG_TRIGGER_DRIVER); |
| 1056 | goto error; | 1125 | goto error; |
| 1057 | } | 1126 | } |
| 1058 | 1127 | ||
| @@ -1198,6 +1267,12 @@ int iwl_mvm_up(struct iwl_mvm *mvm) | |||
| 1198 | if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) | 1267 | if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) |
| 1199 | iwl_mvm_unref(mvm, IWL_MVM_REF_UCODE_DOWN); | 1268 | iwl_mvm_unref(mvm, IWL_MVM_REF_UCODE_DOWN); |
| 1200 | 1269 | ||
| 1270 | if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) | ||
| 1271 | iwl_mvm_send_recovery_cmd(mvm, ERROR_RECOVERY_UPDATE_DB); | ||
| 1272 | |||
| 1273 | if (iwl_acpi_get_eckv(mvm->dev, &mvm->ext_clock_valid)) | ||
| 1274 | IWL_DEBUG_INFO(mvm, "ECKV table doesn't exist in BIOS\n"); | ||
| 1275 | |||
| 1201 | ret = iwl_mvm_sar_init(mvm); | 1276 | ret = iwl_mvm_sar_init(mvm); |
| 1202 | if (ret == 0) { | 1277 | if (ret == 0) { |
| 1203 | ret = iwl_mvm_sar_geo_init(mvm); | 1278 | ret = iwl_mvm_sar_geo_init(mvm); |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/led.c b/drivers/net/wireless/intel/iwlwifi/mvm/led.c index 9bb1de1cad64..4348bb00e761 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/led.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/led.c | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 9 | * Copyright(c) 2017 Intel Deutschland GmbH | 9 | * Copyright(c) 2017 Intel Deutschland GmbH |
| 10 | * Copyright(c) 2018 Intel Corporation | ||
| 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 |
| @@ -28,6 +29,7 @@ | |||
| 28 | * | 29 | * |
| 29 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. | 30 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 30 | * Copyright(c) 2017 Intel Deutschland GmbH | 31 | * Copyright(c) 2017 Intel Deutschland GmbH |
| 32 | * Copyright(c) 2018 Intel Corporation | ||
| 31 | * All rights reserved. | 33 | * All rights reserved. |
| 32 | * | 34 | * |
| 33 | * Redistribution and use in source and binary forms, with or without | 35 | * Redistribution and use in source and binary forms, with or without |
| @@ -113,6 +115,7 @@ int iwl_mvm_leds_init(struct iwl_mvm *mvm) | |||
| 113 | switch (mode) { | 115 | switch (mode) { |
| 114 | case IWL_LED_BLINK: | 116 | case IWL_LED_BLINK: |
| 115 | IWL_ERR(mvm, "Blink led mode not supported, used default\n"); | 117 | IWL_ERR(mvm, "Blink led mode not supported, used default\n"); |
| 118 | /* fall through */ | ||
| 116 | case IWL_LED_DEFAULT: | 119 | case IWL_LED_DEFAULT: |
| 117 | case IWL_LED_RF_STATE: | 120 | case IWL_LED_RF_STATE: |
| 118 | mode = IWL_LED_RF_STATE; | 121 | mode = IWL_LED_RF_STATE; |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c index 7cfdd07d8736..6a70dece447d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c | |||
| @@ -706,8 +706,7 @@ static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm, | |||
| 706 | if (vif->probe_req_reg && vif->bss_conf.assoc && vif->p2p) | 706 | if (vif->probe_req_reg && vif->bss_conf.assoc && vif->p2p) |
| 707 | cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST); | 707 | cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST); |
| 708 | 708 | ||
| 709 | if (vif->bss_conf.assoc && vif->bss_conf.he_support && | 709 | if (vif->bss_conf.he_support && !iwlwifi_mod_params.disable_11ax) { |
| 710 | !iwlwifi_mod_params.disable_11ax) { | ||
| 711 | cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_11AX); | 710 | cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_11AX); |
| 712 | if (vif->bss_conf.twt_requester) | 711 | if (vif->bss_conf.twt_requester) |
| 713 | ctxt_sta->data_policy |= cpu_to_le32(TWT_SUPPORTED); | 712 | ctxt_sta->data_policy |= cpu_to_le32(TWT_SUPPORTED); |
| @@ -812,9 +811,9 @@ static int iwl_mvm_mac_ctxt_cmd_p2p_device(struct iwl_mvm *mvm, | |||
| 812 | return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd); | 811 | return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd); |
| 813 | } | 812 | } |
| 814 | 813 | ||
| 815 | static void iwl_mvm_mac_ctxt_set_tim(struct iwl_mvm *mvm, | 814 | void iwl_mvm_mac_ctxt_set_tim(struct iwl_mvm *mvm, |
| 816 | __le32 *tim_index, __le32 *tim_size, | 815 | __le32 *tim_index, __le32 *tim_size, |
| 817 | u8 *beacon, u32 frame_size) | 816 | u8 *beacon, u32 frame_size) |
| 818 | { | 817 | { |
| 819 | u32 tim_idx; | 818 | u32 tim_idx; |
| 820 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)beacon; | 819 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)beacon; |
| @@ -854,8 +853,8 @@ static u32 iwl_mvm_find_ie_offset(u8 *beacon, u8 eid, u32 frame_size) | |||
| 854 | return ie - beacon; | 853 | return ie - beacon; |
| 855 | } | 854 | } |
| 856 | 855 | ||
| 857 | static u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct ieee80211_tx_info *info, | 856 | u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct ieee80211_tx_info *info, |
| 858 | struct ieee80211_vif *vif) | 857 | struct ieee80211_vif *vif) |
| 859 | { | 858 | { |
| 860 | u8 rate; | 859 | u8 rate; |
| 861 | 860 | ||
| @@ -905,9 +904,9 @@ static void iwl_mvm_mac_ctxt_set_tx(struct iwl_mvm *mvm, | |||
| 905 | 904 | ||
| 906 | } | 905 | } |
| 907 | 906 | ||
| 908 | static int iwl_mvm_mac_ctxt_send_beacon_cmd(struct iwl_mvm *mvm, | 907 | int iwl_mvm_mac_ctxt_send_beacon_cmd(struct iwl_mvm *mvm, |
| 909 | struct sk_buff *beacon, | 908 | struct sk_buff *beacon, |
| 910 | void *data, int len) | 909 | void *data, int len) |
| 911 | { | 910 | { |
| 912 | struct iwl_host_cmd cmd = { | 911 | struct iwl_host_cmd cmd = { |
| 913 | .id = BEACON_TEMPLATE_CMD, | 912 | .id = BEACON_TEMPLATE_CMD, |
| @@ -1010,13 +1009,16 @@ static int iwl_mvm_mac_ctxt_send_beacon_v9(struct iwl_mvm *mvm, | |||
| 1010 | sizeof(beacon_cmd)); | 1009 | sizeof(beacon_cmd)); |
| 1011 | } | 1010 | } |
| 1012 | 1011 | ||
| 1013 | static int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm, | 1012 | int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm, |
| 1014 | struct ieee80211_vif *vif, | 1013 | struct ieee80211_vif *vif, |
| 1015 | struct sk_buff *beacon) | 1014 | struct sk_buff *beacon) |
| 1016 | { | 1015 | { |
| 1017 | if (WARN_ON(!beacon)) | 1016 | if (WARN_ON(!beacon)) |
| 1018 | return -EINVAL; | 1017 | return -EINVAL; |
| 1019 | 1018 | ||
| 1019 | if (IWL_MVM_NON_TRANSMITTING_AP) | ||
| 1020 | return 0; | ||
| 1021 | |||
| 1020 | if (!fw_has_capa(&mvm->fw->ucode_capa, | 1022 | if (!fw_has_capa(&mvm->fw->ucode_capa, |
| 1021 | IWL_UCODE_TLV_CAPA_CSA_AND_TBTT_OFFLOAD)) | 1023 | IWL_UCODE_TLV_CAPA_CSA_AND_TBTT_OFFLOAD)) |
| 1022 | return iwl_mvm_mac_ctxt_send_beacon_v6(mvm, vif, beacon); | 1024 | return iwl_mvm_mac_ctxt_send_beacon_v6(mvm, vif, beacon); |
| @@ -1042,6 +1044,11 @@ int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm, | |||
| 1042 | if (!beacon) | 1044 | if (!beacon) |
| 1043 | return -ENOMEM; | 1045 | return -ENOMEM; |
| 1044 | 1046 | ||
| 1047 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
| 1048 | if (mvm->beacon_inject_active) | ||
| 1049 | return -EBUSY; | ||
| 1050 | #endif | ||
| 1051 | |||
| 1045 | ret = iwl_mvm_mac_ctxt_send_beacon(mvm, vif, beacon); | 1052 | ret = iwl_mvm_mac_ctxt_send_beacon(mvm, vif, beacon); |
| 1046 | dev_kfree_skb(beacon); | 1053 | dev_kfree_skb(beacon); |
| 1047 | return ret; | 1054 | return ret; |
| @@ -1330,7 +1337,7 @@ void iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm, | |||
| 1330 | { | 1337 | { |
| 1331 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 1338 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
| 1332 | struct iwl_extended_beacon_notif *beacon = (void *)pkt->data; | 1339 | struct iwl_extended_beacon_notif *beacon = (void *)pkt->data; |
| 1333 | struct iwl_mvm_tx_resp *beacon_notify_hdr; | 1340 | struct iwl_extended_beacon_notif_v5 *beacon_v5 = (void *)pkt->data; |
| 1334 | struct ieee80211_vif *csa_vif; | 1341 | struct ieee80211_vif *csa_vif; |
| 1335 | struct ieee80211_vif *tx_blocked_vif; | 1342 | struct ieee80211_vif *tx_blocked_vif; |
| 1336 | struct agg_tx_status *agg_status; | 1343 | struct agg_tx_status *agg_status; |
| @@ -1338,18 +1345,29 @@ void iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm, | |||
| 1338 | 1345 | ||
| 1339 | lockdep_assert_held(&mvm->mutex); | 1346 | lockdep_assert_held(&mvm->mutex); |
| 1340 | 1347 | ||
| 1341 | beacon_notify_hdr = &beacon->beacon_notify_hdr; | ||
| 1342 | mvm->ap_last_beacon_gp2 = le32_to_cpu(beacon->gp2); | 1348 | mvm->ap_last_beacon_gp2 = le32_to_cpu(beacon->gp2); |
| 1343 | mvm->ibss_manager = beacon->ibss_mgr_status != 0; | ||
| 1344 | 1349 | ||
| 1345 | agg_status = iwl_mvm_get_agg_status(mvm, beacon_notify_hdr); | 1350 | if (!iwl_mvm_is_short_beacon_notif_supported(mvm)) { |
| 1346 | status = le16_to_cpu(agg_status->status) & TX_STATUS_MSK; | 1351 | struct iwl_mvm_tx_resp *beacon_notify_hdr = |
| 1347 | IWL_DEBUG_RX(mvm, | 1352 | &beacon_v5->beacon_notify_hdr; |
| 1348 | "beacon status %#x retries:%d tsf:0x%016llX gp2:0x%X rate:%d\n", | 1353 | |
| 1349 | status, beacon_notify_hdr->failure_frame, | 1354 | mvm->ibss_manager = beacon_v5->ibss_mgr_status != 0; |
| 1350 | le64_to_cpu(beacon->tsf), | 1355 | agg_status = iwl_mvm_get_agg_status(mvm, beacon_notify_hdr); |
| 1351 | mvm->ap_last_beacon_gp2, | 1356 | status = le16_to_cpu(agg_status->status) & TX_STATUS_MSK; |
| 1352 | le32_to_cpu(beacon_notify_hdr->initial_rate)); | 1357 | IWL_DEBUG_RX(mvm, |
| 1358 | "beacon status %#x retries:%d tsf:0x%016llX gp2:0x%X rate:%d\n", | ||
| 1359 | status, beacon_notify_hdr->failure_frame, | ||
| 1360 | le64_to_cpu(beacon->tsf), | ||
| 1361 | mvm->ap_last_beacon_gp2, | ||
| 1362 | le32_to_cpu(beacon_notify_hdr->initial_rate)); | ||
| 1363 | } else { | ||
| 1364 | mvm->ibss_manager = beacon->ibss_mgr_status != 0; | ||
| 1365 | status = le32_to_cpu(beacon->status) & TX_STATUS_MSK; | ||
| 1366 | IWL_DEBUG_RX(mvm, | ||
| 1367 | "beacon status %#x tsf:0x%016llX gp2:0x%X\n", | ||
| 1368 | status, le64_to_cpu(beacon->tsf), | ||
| 1369 | mvm->ap_last_beacon_gp2); | ||
| 1370 | } | ||
| 1353 | 1371 | ||
| 1354 | csa_vif = rcu_dereference_protected(mvm->csa_vif, | 1372 | csa_vif = rcu_dereference_protected(mvm->csa_vif, |
| 1355 | lockdep_is_held(&mvm->mutex)); | 1373 | lockdep_is_held(&mvm->mutex)); |
| @@ -1539,42 +1557,58 @@ void iwl_mvm_channel_switch_noa_notif(struct iwl_mvm *mvm, | |||
| 1539 | { | 1557 | { |
| 1540 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 1558 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
| 1541 | struct iwl_channel_switch_noa_notif *notif = (void *)pkt->data; | 1559 | struct iwl_channel_switch_noa_notif *notif = (void *)pkt->data; |
| 1542 | struct ieee80211_vif *csa_vif; | 1560 | struct ieee80211_vif *csa_vif, *vif; |
| 1543 | struct iwl_mvm_vif *mvmvif; | 1561 | struct iwl_mvm_vif *mvmvif; |
| 1544 | int len = iwl_rx_packet_payload_len(pkt); | 1562 | int len = iwl_rx_packet_payload_len(pkt); |
| 1545 | u32 id_n_color; | 1563 | u32 id_n_color, csa_id, mac_id; |
| 1546 | 1564 | ||
| 1547 | if (WARN_ON_ONCE(len < sizeof(*notif))) | 1565 | if (WARN_ON_ONCE(len < sizeof(*notif))) |
| 1548 | return; | 1566 | return; |
| 1549 | 1567 | ||
| 1550 | rcu_read_lock(); | ||
| 1551 | |||
| 1552 | csa_vif = rcu_dereference(mvm->csa_vif); | ||
| 1553 | if (WARN_ON(!csa_vif || !csa_vif->csa_active)) | ||
| 1554 | goto out_unlock; | ||
| 1555 | |||
| 1556 | id_n_color = le32_to_cpu(notif->id_and_color); | 1568 | id_n_color = le32_to_cpu(notif->id_and_color); |
| 1569 | mac_id = id_n_color & FW_CTXT_ID_MSK; | ||
| 1557 | 1570 | ||
| 1558 | mvmvif = iwl_mvm_vif_from_mac80211(csa_vif); | 1571 | if (WARN_ON_ONCE(mac_id >= NUM_MAC_INDEX_DRIVER)) |
| 1559 | if (WARN(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color) != id_n_color, | 1572 | return; |
| 1560 | "channel switch noa notification on unexpected vif (csa_vif=%d, notif=%d)", | ||
| 1561 | FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color), id_n_color)) | ||
| 1562 | goto out_unlock; | ||
| 1563 | 1573 | ||
| 1564 | IWL_DEBUG_INFO(mvm, "Channel Switch Started Notification\n"); | 1574 | rcu_read_lock(); |
| 1575 | vif = rcu_dereference(mvm->vif_id_to_mac[mac_id]); | ||
| 1565 | 1576 | ||
| 1566 | schedule_delayed_work(&mvm->cs_tx_unblock_dwork, | 1577 | switch (vif->type) { |
| 1567 | msecs_to_jiffies(IWL_MVM_CS_UNBLOCK_TX_TIMEOUT * | 1578 | case NL80211_IFTYPE_AP: |
| 1568 | csa_vif->bss_conf.beacon_int)); | 1579 | csa_vif = rcu_dereference(mvm->csa_vif); |
| 1580 | if (WARN_ON(!csa_vif || !csa_vif->csa_active || | ||
| 1581 | csa_vif != vif)) | ||
| 1582 | goto out_unlock; | ||
| 1569 | 1583 | ||
| 1570 | ieee80211_csa_finish(csa_vif); | 1584 | mvmvif = iwl_mvm_vif_from_mac80211(csa_vif); |
| 1585 | csa_id = FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color); | ||
| 1586 | if (WARN(csa_id != id_n_color, | ||
| 1587 | "channel switch noa notification on unexpected vif (csa_vif=%d, notif=%d)", | ||
| 1588 | csa_id, id_n_color)) | ||
| 1589 | goto out_unlock; | ||
| 1571 | 1590 | ||
| 1572 | rcu_read_unlock(); | 1591 | IWL_DEBUG_INFO(mvm, "Channel Switch Started Notification\n"); |
| 1573 | 1592 | ||
| 1574 | RCU_INIT_POINTER(mvm->csa_vif, NULL); | 1593 | schedule_delayed_work(&mvm->cs_tx_unblock_dwork, |
| 1594 | msecs_to_jiffies(IWL_MVM_CS_UNBLOCK_TX_TIMEOUT * | ||
| 1595 | csa_vif->bss_conf.beacon_int)); | ||
| 1575 | 1596 | ||
| 1576 | return; | 1597 | ieee80211_csa_finish(csa_vif); |
| 1577 | 1598 | ||
| 1599 | rcu_read_unlock(); | ||
| 1600 | |||
| 1601 | RCU_INIT_POINTER(mvm->csa_vif, NULL); | ||
| 1602 | return; | ||
| 1603 | case NL80211_IFTYPE_STATION: | ||
| 1604 | iwl_mvm_csa_client_absent(mvm, vif); | ||
| 1605 | ieee80211_chswitch_done(vif, true); | ||
| 1606 | break; | ||
| 1607 | default: | ||
| 1608 | /* should never happen */ | ||
| 1609 | WARN_ON_ONCE(1); | ||
| 1610 | break; | ||
| 1611 | } | ||
| 1578 | out_unlock: | 1612 | out_unlock: |
| 1579 | rcu_read_unlock(); | 1613 | rcu_read_unlock(); |
| 1580 | } | 1614 | } |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index e098884dd915..3a92c09d4692 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | |||
| @@ -184,6 +184,29 @@ static const struct iwl_fw_bcast_filter iwl_mvm_default_bcast_filters[] = { | |||
| 184 | }; | 184 | }; |
| 185 | #endif | 185 | #endif |
| 186 | 186 | ||
| 187 | static const struct cfg80211_pmsr_capabilities iwl_mvm_pmsr_capa = { | ||
| 188 | .max_peers = IWL_MVM_TOF_MAX_APS, | ||
| 189 | .report_ap_tsf = 1, | ||
| 190 | .randomize_mac_addr = 1, | ||
| 191 | |||
| 192 | .ftm = { | ||
| 193 | .supported = 1, | ||
| 194 | .asap = 1, | ||
| 195 | .non_asap = 1, | ||
| 196 | .request_lci = 1, | ||
| 197 | .request_civicloc = 1, | ||
| 198 | .max_bursts_exponent = -1, /* all supported */ | ||
| 199 | .max_ftms_per_burst = 0, /* no limits */ | ||
| 200 | .bandwidths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | | ||
| 201 | BIT(NL80211_CHAN_WIDTH_20) | | ||
| 202 | BIT(NL80211_CHAN_WIDTH_40) | | ||
| 203 | BIT(NL80211_CHAN_WIDTH_80), | ||
| 204 | .preambles = BIT(NL80211_PREAMBLE_LEGACY) | | ||
| 205 | BIT(NL80211_PREAMBLE_HT) | | ||
| 206 | BIT(NL80211_PREAMBLE_VHT), | ||
| 207 | }, | ||
| 208 | }; | ||
| 209 | |||
| 187 | void iwl_mvm_ref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type) | 210 | void iwl_mvm_ref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type) |
| 188 | { | 211 | { |
| 189 | if (!iwl_mvm_is_d0i3_supported(mvm)) | 212 | if (!iwl_mvm_is_d0i3_supported(mvm)) |
| @@ -420,6 +443,10 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
| 420 | WLAN_CIPHER_SUITE_TKIP, | 443 | WLAN_CIPHER_SUITE_TKIP, |
| 421 | WLAN_CIPHER_SUITE_CCMP, | 444 | WLAN_CIPHER_SUITE_CCMP, |
| 422 | }; | 445 | }; |
| 446 | #ifdef CONFIG_PM_SLEEP | ||
| 447 | bool unified = fw_has_capa(&mvm->fw->ucode_capa, | ||
| 448 | IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG); | ||
| 449 | #endif | ||
| 423 | 450 | ||
| 424 | /* Tell mac80211 our characteristics */ | 451 | /* Tell mac80211 our characteristics */ |
| 425 | ieee80211_hw_set(hw, SIGNAL_DBM); | 452 | ieee80211_hw_set(hw, SIGNAL_DBM); |
| @@ -544,6 +571,13 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
| 544 | hw->wiphy->n_cipher_suites++; | 571 | hw->wiphy->n_cipher_suites++; |
| 545 | } | 572 | } |
| 546 | 573 | ||
| 574 | if (fw_has_capa(&mvm->fw->ucode_capa, | ||
| 575 | IWL_UCODE_TLV_CAPA_FTM_CALIBRATED)) { | ||
| 576 | wiphy_ext_feature_set(hw->wiphy, | ||
| 577 | NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER); | ||
| 578 | hw->wiphy->pmsr_capa = &iwl_mvm_pmsr_capa; | ||
| 579 | } | ||
| 580 | |||
| 547 | ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS); | 581 | ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS); |
| 548 | hw->wiphy->features |= | 582 | hw->wiphy->features |= |
| 549 | NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR | | 583 | NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR | |
| @@ -709,7 +743,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
| 709 | hw->wiphy->wowlan = &mvm->wowlan; | 743 | hw->wiphy->wowlan = &mvm->wowlan; |
| 710 | } | 744 | } |
| 711 | 745 | ||
| 712 | if (mvm->fw->img[IWL_UCODE_WOWLAN].num_sec && | 746 | if ((unified || mvm->fw->img[IWL_UCODE_WOWLAN].num_sec) && |
| 713 | mvm->trans->ops->d3_suspend && | 747 | mvm->trans->ops->d3_suspend && |
| 714 | mvm->trans->ops->d3_resume && | 748 | mvm->trans->ops->d3_resume && |
| 715 | device_can_wakeup(mvm->trans->dev)) { | 749 | device_can_wakeup(mvm->trans->dev)) { |
| @@ -762,15 +796,15 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
| 762 | hw->netdev_features |= IWL_TX_CSUM_NETIF_FLAGS; | 796 | hw->netdev_features |= IWL_TX_CSUM_NETIF_FLAGS; |
| 763 | } | 797 | } |
| 764 | 798 | ||
| 765 | ret = ieee80211_register_hw(mvm->hw); | ||
| 766 | if (ret) | ||
| 767 | iwl_mvm_leds_exit(mvm); | ||
| 768 | mvm->init_status |= IWL_MVM_INIT_STATUS_REG_HW_INIT_COMPLETE; | ||
| 769 | |||
| 770 | if (mvm->cfg->vht_mu_mimo_supported) | 799 | if (mvm->cfg->vht_mu_mimo_supported) |
| 771 | wiphy_ext_feature_set(hw->wiphy, | 800 | wiphy_ext_feature_set(hw->wiphy, |
| 772 | NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER); | 801 | NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER); |
| 773 | 802 | ||
| 803 | ret = ieee80211_register_hw(mvm->hw); | ||
| 804 | if (ret) { | ||
| 805 | iwl_mvm_leds_exit(mvm); | ||
| 806 | } | ||
| 807 | |||
| 774 | return ret; | 808 | return ret; |
| 775 | } | 809 | } |
| 776 | 810 | ||
| @@ -907,8 +941,14 @@ void iwl_mvm_mac_itxq_xmit(struct ieee80211_hw *hw, struct ieee80211_txq *txq) | |||
| 907 | IWL_PLAT_PM_MODE_DISABLED))) { | 941 | IWL_PLAT_PM_MODE_DISABLED))) { |
| 908 | skb = ieee80211_tx_dequeue(hw, txq); | 942 | skb = ieee80211_tx_dequeue(hw, txq); |
| 909 | 943 | ||
| 910 | if (!skb) | 944 | if (!skb) { |
| 945 | if (txq->sta) | ||
| 946 | IWL_DEBUG_TX(mvm, | ||
| 947 | "TXQ of sta %pM tid %d is now empty\n", | ||
| 948 | txq->sta->addr, | ||
| 949 | txq->tid); | ||
| 911 | break; | 950 | break; |
| 951 | } | ||
| 912 | 952 | ||
| 913 | if (!txq->sta) | 953 | if (!txq->sta) |
| 914 | iwl_mvm_tx_skb_non_sta(mvm, skb); | 954 | iwl_mvm_tx_skb_non_sta(mvm, skb); |
| @@ -1177,6 +1217,8 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm) | |||
| 1177 | iwl_mvm_cleanup_roc_te(mvm); | 1217 | iwl_mvm_cleanup_roc_te(mvm); |
| 1178 | ieee80211_remain_on_channel_expired(mvm->hw); | 1218 | ieee80211_remain_on_channel_expired(mvm->hw); |
| 1179 | 1219 | ||
| 1220 | iwl_mvm_ftm_restart(mvm); | ||
| 1221 | |||
| 1180 | /* | 1222 | /* |
| 1181 | * cleanup all interfaces, even inactive ones, as some might have | 1223 | * cleanup all interfaces, even inactive ones, as some might have |
| 1182 | * gone down during the HW restart | 1224 | * gone down during the HW restart |
| @@ -1290,6 +1332,8 @@ static void iwl_mvm_restart_complete(struct iwl_mvm *mvm) | |||
| 1290 | /* allow transport/FW low power modes */ | 1332 | /* allow transport/FW low power modes */ |
| 1291 | iwl_mvm_unref(mvm, IWL_MVM_REF_UCODE_DOWN); | 1333 | iwl_mvm_unref(mvm, IWL_MVM_REF_UCODE_DOWN); |
| 1292 | 1334 | ||
| 1335 | iwl_mvm_send_recovery_cmd(mvm, ERROR_RECOVERY_END_OF_RECOVERY); | ||
| 1336 | |||
| 1293 | /* | 1337 | /* |
| 1294 | * If we have TDLS peers, remove them. We don't know the last seqno/PN | 1338 | * If we have TDLS peers, remove them. We don't know the last seqno/PN |
| 1295 | * of packets the FW sent out, so we must reconnect. | 1339 | * of packets the FW sent out, so we must reconnect. |
| @@ -1653,6 +1697,9 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw, | |||
| 1653 | IEEE80211_VIF_SUPPORTS_CQM_RSSI); | 1697 | IEEE80211_VIF_SUPPORTS_CQM_RSSI); |
| 1654 | } | 1698 | } |
| 1655 | 1699 | ||
| 1700 | if (vif->bss_conf.ftm_responder) | ||
| 1701 | memset(&mvm->ftm_resp_stats, 0, sizeof(mvm->ftm_resp_stats)); | ||
| 1702 | |||
| 1656 | iwl_mvm_vif_dbgfs_clean(mvm, vif); | 1703 | iwl_mvm_vif_dbgfs_clean(mvm, vif); |
| 1657 | 1704 | ||
| 1658 | /* | 1705 | /* |
| @@ -2363,7 +2410,10 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, | |||
| 2363 | * If update fails - SF might be running in associated | 2410 | * If update fails - SF might be running in associated |
| 2364 | * mode while disassociated - which is forbidden. | 2411 | * mode while disassociated - which is forbidden. |
| 2365 | */ | 2412 | */ |
| 2366 | WARN_ONCE(iwl_mvm_sf_update(mvm, vif, false), | 2413 | ret = iwl_mvm_sf_update(mvm, vif, false); |
| 2414 | WARN_ONCE(ret && | ||
| 2415 | !test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, | ||
| 2416 | &mvm->status), | ||
| 2367 | "Failed to update SF upon disassociation\n"); | 2417 | "Failed to update SF upon disassociation\n"); |
| 2368 | 2418 | ||
| 2369 | /* | 2419 | /* |
| @@ -2584,6 +2634,8 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw, | |||
| 2584 | if (iwl_mvm_phy_ctx_count(mvm) > 1) | 2634 | if (iwl_mvm_phy_ctx_count(mvm) > 1) |
| 2585 | iwl_mvm_teardown_tdls_peers(mvm); | 2635 | iwl_mvm_teardown_tdls_peers(mvm); |
| 2586 | 2636 | ||
| 2637 | iwl_mvm_ftm_restart_responder(mvm, vif); | ||
| 2638 | |||
| 2587 | goto out_unlock; | 2639 | goto out_unlock; |
| 2588 | 2640 | ||
| 2589 | out_quota_failed: | 2641 | out_quota_failed: |
| @@ -2695,6 +2747,15 @@ iwl_mvm_bss_info_changed_ap_ibss(struct iwl_mvm *mvm, | |||
| 2695 | bss_conf->txpower); | 2747 | bss_conf->txpower); |
| 2696 | iwl_mvm_set_tx_power(mvm, vif, bss_conf->txpower); | 2748 | iwl_mvm_set_tx_power(mvm, vif, bss_conf->txpower); |
| 2697 | } | 2749 | } |
| 2750 | |||
| 2751 | if (changes & BSS_CHANGED_FTM_RESPONDER) { | ||
| 2752 | int ret = iwl_mvm_ftm_start_responder(mvm, vif); | ||
| 2753 | |||
| 2754 | if (ret) | ||
| 2755 | IWL_WARN(mvm, "Failed to enable FTM responder (%d)\n", | ||
| 2756 | ret); | ||
| 2757 | } | ||
| 2758 | |||
| 2698 | } | 2759 | } |
| 2699 | 2760 | ||
| 2700 | static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw, | 2761 | static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw, |
| @@ -3106,11 +3167,15 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, | |||
| 3106 | } else if (old_state == IEEE80211_STA_AUTH && | 3167 | } else if (old_state == IEEE80211_STA_AUTH && |
| 3107 | new_state == IEEE80211_STA_ASSOC) { | 3168 | new_state == IEEE80211_STA_ASSOC) { |
| 3108 | if (vif->type == NL80211_IFTYPE_AP) { | 3169 | if (vif->type == NL80211_IFTYPE_AP) { |
| 3170 | vif->bss_conf.he_support = sta->he_cap.has_he; | ||
| 3109 | mvmvif->ap_assoc_sta_count++; | 3171 | mvmvif->ap_assoc_sta_count++; |
| 3110 | iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL); | 3172 | iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL); |
| 3111 | if (vif->bss_conf.he_support && | 3173 | if (vif->bss_conf.he_support && |
| 3112 | !iwlwifi_mod_params.disable_11ax) | 3174 | !iwlwifi_mod_params.disable_11ax) |
| 3113 | iwl_mvm_cfg_he_sta(mvm, vif, mvm_sta->sta_id); | 3175 | iwl_mvm_cfg_he_sta(mvm, vif, mvm_sta->sta_id); |
| 3176 | } else if (vif->type == NL80211_IFTYPE_STATION) { | ||
| 3177 | vif->bss_conf.he_support = sta->he_cap.has_he; | ||
| 3178 | iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL); | ||
| 3114 | } | 3179 | } |
| 3115 | 3180 | ||
| 3116 | iwl_mvm_rs_rate_init(mvm, sta, mvmvif->phy_ctxt->channel->band, | 3181 | iwl_mvm_rs_rate_init(mvm, sta, mvmvif->phy_ctxt->channel->band, |
| @@ -3118,6 +3183,24 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, | |||
| 3118 | ret = iwl_mvm_update_sta(mvm, vif, sta); | 3183 | ret = iwl_mvm_update_sta(mvm, vif, sta); |
| 3119 | } else if (old_state == IEEE80211_STA_ASSOC && | 3184 | } else if (old_state == IEEE80211_STA_ASSOC && |
| 3120 | new_state == IEEE80211_STA_AUTHORIZED) { | 3185 | new_state == IEEE80211_STA_AUTHORIZED) { |
| 3186 | /* if wep is used, need to set the key for the station now */ | ||
| 3187 | if (vif->type == NL80211_IFTYPE_AP && mvmvif->ap_wep_key) { | ||
| 3188 | mvm_sta->wep_key = | ||
| 3189 | kmemdup(mvmvif->ap_wep_key, | ||
| 3190 | sizeof(*mvmvif->ap_wep_key) + | ||
| 3191 | mvmvif->ap_wep_key->keylen, | ||
| 3192 | GFP_KERNEL); | ||
| 3193 | if (!mvm_sta->wep_key) { | ||
| 3194 | ret = -ENOMEM; | ||
| 3195 | goto out_unlock; | ||
| 3196 | } | ||
| 3197 | |||
| 3198 | ret = iwl_mvm_set_sta_key(mvm, vif, sta, | ||
| 3199 | mvm_sta->wep_key, | ||
| 3200 | STA_KEY_IDX_INVALID); | ||
| 3201 | } else { | ||
| 3202 | ret = 0; | ||
| 3203 | } | ||
| 3121 | 3204 | ||
| 3122 | /* we don't support TDLS during DCM */ | 3205 | /* we don't support TDLS during DCM */ |
| 3123 | if (iwl_mvm_phy_ctx_count(mvm) > 1) | 3206 | if (iwl_mvm_phy_ctx_count(mvm) > 1) |
| @@ -3132,18 +3215,13 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, | |||
| 3132 | 3215 | ||
| 3133 | iwl_mvm_rs_rate_init(mvm, sta, mvmvif->phy_ctxt->channel->band, | 3216 | iwl_mvm_rs_rate_init(mvm, sta, mvmvif->phy_ctxt->channel->band, |
| 3134 | true); | 3217 | true); |
| 3135 | |||
| 3136 | /* if wep is used, need to set the key for the station now */ | ||
| 3137 | if (vif->type == NL80211_IFTYPE_AP && mvmvif->ap_wep_key) | ||
| 3138 | ret = iwl_mvm_set_sta_key(mvm, vif, sta, | ||
| 3139 | mvmvif->ap_wep_key, | ||
| 3140 | STA_KEY_IDX_INVALID); | ||
| 3141 | else | ||
| 3142 | ret = 0; | ||
| 3143 | } else if (old_state == IEEE80211_STA_AUTHORIZED && | 3218 | } else if (old_state == IEEE80211_STA_AUTHORIZED && |
| 3144 | new_state == IEEE80211_STA_ASSOC) { | 3219 | new_state == IEEE80211_STA_ASSOC) { |
| 3145 | /* disable beacon filtering */ | 3220 | /* disable beacon filtering */ |
| 3146 | WARN_ON(iwl_mvm_disable_beacon_filter(mvm, vif, 0)); | 3221 | ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0); |
| 3222 | WARN_ON(ret && | ||
| 3223 | !test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, | ||
| 3224 | &mvm->status)); | ||
| 3147 | ret = 0; | 3225 | ret = 0; |
| 3148 | } else if (old_state == IEEE80211_STA_ASSOC && | 3226 | } else if (old_state == IEEE80211_STA_ASSOC && |
| 3149 | new_state == IEEE80211_STA_AUTH) { | 3227 | new_state == IEEE80211_STA_AUTH) { |
| @@ -3167,12 +3245,18 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, | |||
| 3167 | /* Remove STA key if this is an AP using WEP */ | 3245 | /* Remove STA key if this is an AP using WEP */ |
| 3168 | if (vif->type == NL80211_IFTYPE_AP && mvmvif->ap_wep_key) { | 3246 | if (vif->type == NL80211_IFTYPE_AP && mvmvif->ap_wep_key) { |
| 3169 | int rm_ret = iwl_mvm_remove_sta_key(mvm, vif, sta, | 3247 | int rm_ret = iwl_mvm_remove_sta_key(mvm, vif, sta, |
| 3170 | mvmvif->ap_wep_key); | 3248 | mvm_sta->wep_key); |
| 3171 | 3249 | ||
| 3172 | if (!ret) | 3250 | if (!ret) |
| 3173 | ret = rm_ret; | 3251 | ret = rm_ret; |
| 3252 | kfree(mvm_sta->wep_key); | ||
| 3253 | mvm_sta->wep_key = NULL; | ||
| 3174 | } | 3254 | } |
| 3175 | 3255 | ||
| 3256 | if (unlikely(ret && | ||
| 3257 | test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, | ||
| 3258 | &mvm->status))) | ||
| 3259 | ret = 0; | ||
| 3176 | } else { | 3260 | } else { |
| 3177 | ret = -EIO; | 3261 | ret = -EIO; |
| 3178 | } | 3262 | } |
| @@ -3816,11 +3900,43 @@ static int iwl_mvm_cancel_roc(struct ieee80211_hw *hw) | |||
| 3816 | return 0; | 3900 | return 0; |
| 3817 | } | 3901 | } |
| 3818 | 3902 | ||
| 3903 | struct iwl_mvm_ftm_responder_iter_data { | ||
| 3904 | bool responder; | ||
| 3905 | struct ieee80211_chanctx_conf *ctx; | ||
| 3906 | }; | ||
| 3907 | |||
| 3908 | static void iwl_mvm_ftm_responder_chanctx_iter(void *_data, u8 *mac, | ||
| 3909 | struct ieee80211_vif *vif) | ||
| 3910 | { | ||
| 3911 | struct iwl_mvm_ftm_responder_iter_data *data = _data; | ||
| 3912 | |||
| 3913 | if (rcu_access_pointer(vif->chanctx_conf) == data->ctx && | ||
| 3914 | vif->type == NL80211_IFTYPE_AP && vif->bss_conf.ftmr_params) | ||
| 3915 | data->responder = true; | ||
| 3916 | } | ||
| 3917 | |||
| 3918 | static bool iwl_mvm_is_ftm_responder_chanctx(struct iwl_mvm *mvm, | ||
| 3919 | struct ieee80211_chanctx_conf *ctx) | ||
| 3920 | { | ||
| 3921 | struct iwl_mvm_ftm_responder_iter_data data = { | ||
| 3922 | .responder = false, | ||
| 3923 | .ctx = ctx, | ||
| 3924 | }; | ||
| 3925 | |||
| 3926 | ieee80211_iterate_active_interfaces_atomic(mvm->hw, | ||
| 3927 | IEEE80211_IFACE_ITER_NORMAL, | ||
| 3928 | iwl_mvm_ftm_responder_chanctx_iter, | ||
| 3929 | &data); | ||
| 3930 | return data.responder; | ||
| 3931 | } | ||
| 3932 | |||
| 3819 | static int __iwl_mvm_add_chanctx(struct iwl_mvm *mvm, | 3933 | static int __iwl_mvm_add_chanctx(struct iwl_mvm *mvm, |
| 3820 | struct ieee80211_chanctx_conf *ctx) | 3934 | struct ieee80211_chanctx_conf *ctx) |
| 3821 | { | 3935 | { |
| 3822 | u16 *phy_ctxt_id = (u16 *)ctx->drv_priv; | 3936 | u16 *phy_ctxt_id = (u16 *)ctx->drv_priv; |
| 3823 | struct iwl_mvm_phy_ctxt *phy_ctxt; | 3937 | struct iwl_mvm_phy_ctxt *phy_ctxt; |
| 3938 | bool responder = iwl_mvm_is_ftm_responder_chanctx(mvm, ctx); | ||
| 3939 | struct cfg80211_chan_def *def = responder ? &ctx->def : &ctx->min_def; | ||
| 3824 | int ret; | 3940 | int ret; |
| 3825 | 3941 | ||
| 3826 | lockdep_assert_held(&mvm->mutex); | 3942 | lockdep_assert_held(&mvm->mutex); |
| @@ -3833,7 +3949,7 @@ static int __iwl_mvm_add_chanctx(struct iwl_mvm *mvm, | |||
| 3833 | goto out; | 3949 | goto out; |
| 3834 | } | 3950 | } |
| 3835 | 3951 | ||
| 3836 | ret = iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &ctx->min_def, | 3952 | ret = iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, def, |
| 3837 | ctx->rx_chains_static, | 3953 | ctx->rx_chains_static, |
| 3838 | ctx->rx_chains_dynamic); | 3954 | ctx->rx_chains_dynamic); |
| 3839 | if (ret) { | 3955 | if (ret) { |
| @@ -3888,6 +4004,8 @@ static void iwl_mvm_change_chanctx(struct ieee80211_hw *hw, | |||
| 3888 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | 4004 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); |
| 3889 | u16 *phy_ctxt_id = (u16 *)ctx->drv_priv; | 4005 | u16 *phy_ctxt_id = (u16 *)ctx->drv_priv; |
| 3890 | struct iwl_mvm_phy_ctxt *phy_ctxt = &mvm->phy_ctxts[*phy_ctxt_id]; | 4006 | struct iwl_mvm_phy_ctxt *phy_ctxt = &mvm->phy_ctxts[*phy_ctxt_id]; |
| 4007 | bool responder = iwl_mvm_is_ftm_responder_chanctx(mvm, ctx); | ||
| 4008 | struct cfg80211_chan_def *def = responder ? &ctx->def : &ctx->min_def; | ||
| 3891 | 4009 | ||
| 3892 | if (WARN_ONCE((phy_ctxt->ref > 1) && | 4010 | if (WARN_ONCE((phy_ctxt->ref > 1) && |
| 3893 | (changed & ~(IEEE80211_CHANCTX_CHANGE_WIDTH | | 4011 | (changed & ~(IEEE80211_CHANCTX_CHANGE_WIDTH | |
| @@ -3902,17 +4020,17 @@ static void iwl_mvm_change_chanctx(struct ieee80211_hw *hw, | |||
| 3902 | 4020 | ||
| 3903 | /* we are only changing the min_width, may be a noop */ | 4021 | /* we are only changing the min_width, may be a noop */ |
| 3904 | if (changed == IEEE80211_CHANCTX_CHANGE_MIN_WIDTH) { | 4022 | if (changed == IEEE80211_CHANCTX_CHANGE_MIN_WIDTH) { |
| 3905 | if (phy_ctxt->width == ctx->min_def.width) | 4023 | if (phy_ctxt->width == def->width) |
| 3906 | goto out_unlock; | 4024 | goto out_unlock; |
| 3907 | 4025 | ||
| 3908 | /* we are just toggling between 20_NOHT and 20 */ | 4026 | /* we are just toggling between 20_NOHT and 20 */ |
| 3909 | if (phy_ctxt->width <= NL80211_CHAN_WIDTH_20 && | 4027 | if (phy_ctxt->width <= NL80211_CHAN_WIDTH_20 && |
| 3910 | ctx->min_def.width <= NL80211_CHAN_WIDTH_20) | 4028 | def->width <= NL80211_CHAN_WIDTH_20) |
| 3911 | goto out_unlock; | 4029 | goto out_unlock; |
| 3912 | } | 4030 | } |
| 3913 | 4031 | ||
| 3914 | iwl_mvm_bt_coex_vif_change(mvm); | 4032 | iwl_mvm_bt_coex_vif_change(mvm); |
| 3915 | iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &ctx->min_def, | 4033 | iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, def, |
| 3916 | ctx->rx_chains_static, | 4034 | ctx->rx_chains_static, |
| 3917 | ctx->rx_chains_dynamic); | 4035 | ctx->rx_chains_dynamic); |
| 3918 | 4036 | ||
| @@ -3941,6 +4059,7 @@ static int __iwl_mvm_assign_vif_chanctx(struct iwl_mvm *mvm, | |||
| 3941 | mvmvif->ap_ibss_active = true; | 4059 | mvmvif->ap_ibss_active = true; |
| 3942 | break; | 4060 | break; |
| 3943 | } | 4061 | } |
| 4062 | /* fall through */ | ||
| 3944 | case NL80211_IFTYPE_ADHOC: | 4063 | case NL80211_IFTYPE_ADHOC: |
| 3945 | /* | 4064 | /* |
| 3946 | * The AP binding flow is handled as part of the start_ap flow | 4065 | * The AP binding flow is handled as part of the start_ap flow |
| @@ -3993,25 +4112,30 @@ static int __iwl_mvm_assign_vif_chanctx(struct iwl_mvm *mvm, | |||
| 3993 | } | 4112 | } |
| 3994 | 4113 | ||
| 3995 | if (switching_chanctx && vif->type == NL80211_IFTYPE_STATION) { | 4114 | if (switching_chanctx && vif->type == NL80211_IFTYPE_STATION) { |
| 3996 | u32 duration = 3 * vif->bss_conf.beacon_int; | 4115 | mvmvif->csa_bcn_pending = true; |
| 3997 | 4116 | ||
| 3998 | /* iwl_mvm_protect_session() reads directly from the | 4117 | if (!fw_has_capa(&mvm->fw->ucode_capa, |
| 3999 | * device (the system time), so make sure it is | 4118 | IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD)) { |
| 4000 | * available. | 4119 | u32 duration = 3 * vif->bss_conf.beacon_int; |
| 4001 | */ | ||
| 4002 | ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PROTECT_CSA); | ||
| 4003 | if (ret) | ||
| 4004 | goto out_remove_binding; | ||
| 4005 | 4120 | ||
| 4006 | /* Protect the session to make sure we hear the first | ||
| 4007 | * beacon on the new channel. | ||
| 4008 | */ | ||
| 4009 | mvmvif->csa_bcn_pending = true; | ||
| 4010 | iwl_mvm_protect_session(mvm, vif, duration, duration, | ||
| 4011 | vif->bss_conf.beacon_int / 2, | ||
| 4012 | true); | ||
| 4013 | 4121 | ||
| 4014 | iwl_mvm_unref(mvm, IWL_MVM_REF_PROTECT_CSA); | 4122 | /* iwl_mvm_protect_session() reads directly from the |
| 4123 | * device (the system time), so make sure it is | ||
| 4124 | * available. | ||
| 4125 | */ | ||
| 4126 | ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PROTECT_CSA); | ||
| 4127 | if (ret) | ||
| 4128 | goto out_remove_binding; | ||
| 4129 | |||
| 4130 | /* Protect the session to make sure we hear the first | ||
| 4131 | * beacon on the new channel. | ||
| 4132 | */ | ||
| 4133 | iwl_mvm_protect_session(mvm, vif, duration, duration, | ||
| 4134 | vif->bss_conf.beacon_int / 2, | ||
| 4135 | true); | ||
| 4136 | |||
| 4137 | iwl_mvm_unref(mvm, IWL_MVM_REF_PROTECT_CSA); | ||
| 4138 | } | ||
| 4015 | 4139 | ||
| 4016 | iwl_mvm_update_quotas(mvm, false, NULL); | 4140 | iwl_mvm_update_quotas(mvm, false, NULL); |
| 4017 | } | 4141 | } |
| @@ -4081,7 +4205,9 @@ static void __iwl_mvm_unassign_vif_chanctx(struct iwl_mvm *mvm, | |||
| 4081 | 4205 | ||
| 4082 | disabled_vif = vif; | 4206 | disabled_vif = vif; |
| 4083 | 4207 | ||
| 4084 | iwl_mvm_mac_ctxt_changed(mvm, vif, true, NULL); | 4208 | if (!fw_has_capa(&mvm->fw->ucode_capa, |
| 4209 | IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD)) | ||
| 4210 | iwl_mvm_mac_ctxt_changed(mvm, vif, true, NULL); | ||
| 4085 | break; | 4211 | break; |
| 4086 | default: | 4212 | default: |
| 4087 | break; | 4213 | break; |
| @@ -4332,6 +4458,27 @@ static void iwl_mvm_channel_switch(struct ieee80211_hw *hw, | |||
| 4332 | "dummy channel switch op\n"); | 4458 | "dummy channel switch op\n"); |
| 4333 | } | 4459 | } |
| 4334 | 4460 | ||
| 4461 | static int iwl_mvm_schedule_client_csa(struct iwl_mvm *mvm, | ||
| 4462 | struct ieee80211_vif *vif, | ||
| 4463 | struct ieee80211_channel_switch *chsw) | ||
| 4464 | { | ||
| 4465 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
| 4466 | struct iwl_chan_switch_te_cmd cmd = { | ||
| 4467 | .mac_id = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, | ||
| 4468 | mvmvif->color)), | ||
| 4469 | .action = cpu_to_le32(FW_CTXT_ACTION_ADD), | ||
| 4470 | .tsf = cpu_to_le32(chsw->timestamp), | ||
| 4471 | .cs_count = chsw->count, | ||
| 4472 | }; | ||
| 4473 | |||
| 4474 | lockdep_assert_held(&mvm->mutex); | ||
| 4475 | |||
| 4476 | return iwl_mvm_send_cmd_pdu(mvm, | ||
| 4477 | WIDE_ID(MAC_CONF_GROUP, | ||
| 4478 | CHANNEL_SWITCH_TIME_EVENT_CMD), | ||
| 4479 | 0, sizeof(cmd), &cmd); | ||
| 4480 | } | ||
| 4481 | |||
| 4335 | static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw, | 4482 | static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw, |
| 4336 | struct ieee80211_vif *vif, | 4483 | struct ieee80211_vif *vif, |
| 4337 | struct ieee80211_channel_switch *chsw) | 4484 | struct ieee80211_channel_switch *chsw) |
| @@ -4399,14 +4546,19 @@ static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw, | |||
| 4399 | if (chsw->block_tx) | 4546 | if (chsw->block_tx) |
| 4400 | iwl_mvm_csa_client_absent(mvm, vif); | 4547 | iwl_mvm_csa_client_absent(mvm, vif); |
| 4401 | 4548 | ||
| 4402 | iwl_mvm_schedule_csa_period(mvm, vif, vif->bss_conf.beacon_int, | ||
| 4403 | apply_time); | ||
| 4404 | if (mvmvif->bf_data.bf_enabled) { | 4549 | if (mvmvif->bf_data.bf_enabled) { |
| 4405 | ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0); | 4550 | ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0); |
| 4406 | if (ret) | 4551 | if (ret) |
| 4407 | goto out_unlock; | 4552 | goto out_unlock; |
| 4408 | } | 4553 | } |
| 4409 | 4554 | ||
| 4555 | if (fw_has_capa(&mvm->fw->ucode_capa, | ||
| 4556 | IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD)) | ||
| 4557 | iwl_mvm_schedule_client_csa(mvm, vif, chsw); | ||
| 4558 | else | ||
| 4559 | iwl_mvm_schedule_csa_period(mvm, vif, | ||
| 4560 | vif->bss_conf.beacon_int, | ||
| 4561 | apply_time); | ||
| 4410 | break; | 4562 | break; |
| 4411 | default: | 4563 | default: |
| 4412 | break; | 4564 | break; |
| @@ -4799,6 +4951,60 @@ static void iwl_mvm_sync_rx_queues(struct ieee80211_hw *hw) | |||
| 4799 | mutex_unlock(&mvm->mutex); | 4951 | mutex_unlock(&mvm->mutex); |
| 4800 | } | 4952 | } |
| 4801 | 4953 | ||
| 4954 | static int | ||
| 4955 | iwl_mvm_mac_get_ftm_responder_stats(struct ieee80211_hw *hw, | ||
| 4956 | struct ieee80211_vif *vif, | ||
| 4957 | struct cfg80211_ftm_responder_stats *stats) | ||
| 4958 | { | ||
| 4959 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | ||
| 4960 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
| 4961 | |||
| 4962 | if (vif->p2p || vif->type != NL80211_IFTYPE_AP || | ||
| 4963 | !mvmvif->ap_ibss_active || !vif->bss_conf.ftm_responder) | ||
| 4964 | return -EINVAL; | ||
| 4965 | |||
| 4966 | mutex_lock(&mvm->mutex); | ||
| 4967 | *stats = mvm->ftm_resp_stats; | ||
| 4968 | mutex_unlock(&mvm->mutex); | ||
| 4969 | |||
| 4970 | stats->filled = BIT(NL80211_FTM_STATS_SUCCESS_NUM) | | ||
| 4971 | BIT(NL80211_FTM_STATS_PARTIAL_NUM) | | ||
| 4972 | BIT(NL80211_FTM_STATS_FAILED_NUM) | | ||
| 4973 | BIT(NL80211_FTM_STATS_ASAP_NUM) | | ||
| 4974 | BIT(NL80211_FTM_STATS_NON_ASAP_NUM) | | ||
| 4975 | BIT(NL80211_FTM_STATS_TOTAL_DURATION_MSEC) | | ||
| 4976 | BIT(NL80211_FTM_STATS_UNKNOWN_TRIGGERS_NUM) | | ||
| 4977 | BIT(NL80211_FTM_STATS_RESCHEDULE_REQUESTS_NUM) | | ||
| 4978 | BIT(NL80211_FTM_STATS_OUT_OF_WINDOW_TRIGGERS_NUM); | ||
| 4979 | |||
| 4980 | return 0; | ||
| 4981 | } | ||
| 4982 | |||
| 4983 | static int iwl_mvm_start_pmsr(struct ieee80211_hw *hw, | ||
| 4984 | struct ieee80211_vif *vif, | ||
| 4985 | struct cfg80211_pmsr_request *request) | ||
| 4986 | { | ||
| 4987 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | ||
| 4988 | int ret; | ||
| 4989 | |||
| 4990 | mutex_lock(&mvm->mutex); | ||
| 4991 | ret = iwl_mvm_ftm_start(mvm, vif, request); | ||
| 4992 | mutex_unlock(&mvm->mutex); | ||
| 4993 | |||
| 4994 | return ret; | ||
| 4995 | } | ||
| 4996 | |||
| 4997 | static void iwl_mvm_abort_pmsr(struct ieee80211_hw *hw, | ||
| 4998 | struct ieee80211_vif *vif, | ||
| 4999 | struct cfg80211_pmsr_request *request) | ||
| 5000 | { | ||
| 5001 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | ||
| 5002 | |||
| 5003 | mutex_lock(&mvm->mutex); | ||
| 5004 | iwl_mvm_ftm_abort(mvm, request); | ||
| 5005 | mutex_unlock(&mvm->mutex); | ||
| 5006 | } | ||
| 5007 | |||
| 4802 | static bool iwl_mvm_can_hw_csum(struct sk_buff *skb) | 5008 | static bool iwl_mvm_can_hw_csum(struct sk_buff *skb) |
| 4803 | { | 5009 | { |
| 4804 | u8 protocol = ip_hdr(skb)->protocol; | 5010 | u8 protocol = ip_hdr(skb)->protocol; |
| @@ -4901,6 +5107,10 @@ const struct ieee80211_ops iwl_mvm_hw_ops = { | |||
| 4901 | #endif | 5107 | #endif |
| 4902 | .get_survey = iwl_mvm_mac_get_survey, | 5108 | .get_survey = iwl_mvm_mac_get_survey, |
| 4903 | .sta_statistics = iwl_mvm_mac_sta_statistics, | 5109 | .sta_statistics = iwl_mvm_mac_sta_statistics, |
| 5110 | .get_ftm_responder_stats = iwl_mvm_mac_get_ftm_responder_stats, | ||
| 5111 | .start_pmsr = iwl_mvm_start_pmsr, | ||
| 5112 | .abort_pmsr = iwl_mvm_abort_pmsr, | ||
| 5113 | |||
| 4904 | .can_aggregate_in_amsdu = iwl_mvm_mac_can_aggregate, | 5114 | .can_aggregate_in_amsdu = iwl_mvm_mac_can_aggregate, |
| 4905 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 5115 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
| 4906 | .sta_add_debugfs = iwl_mvm_sta_add_debugfs, | 5116 | .sta_add_debugfs = iwl_mvm_sta_add_debugfs, |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 12e9ecc3ee27..bca6f6b536d9 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | |||
| @@ -879,9 +879,6 @@ struct iwl_mvm { | |||
| 879 | 879 | ||
| 880 | bool hw_registered; | 880 | bool hw_registered; |
| 881 | bool calibrating; | 881 | bool calibrating; |
| 882 | u32 error_event_table[2]; | ||
| 883 | u32 log_event_table; | ||
| 884 | u32 umac_error_event_table; | ||
| 885 | bool support_umac_log; | 882 | bool support_umac_log; |
| 886 | 883 | ||
| 887 | u32 ampdu_ref; | 884 | u32 ampdu_ref; |
| @@ -981,6 +978,7 @@ struct iwl_mvm { | |||
| 981 | u32 dbgfs_prph_reg_addr; | 978 | u32 dbgfs_prph_reg_addr; |
| 982 | bool disable_power_off; | 979 | bool disable_power_off; |
| 983 | bool disable_power_off_d3; | 980 | bool disable_power_off_d3; |
| 981 | bool beacon_inject_active; | ||
| 984 | 982 | ||
| 985 | bool scan_iter_notif_enabled; | 983 | bool scan_iter_notif_enabled; |
| 986 | 984 | ||
| @@ -1017,6 +1015,7 @@ struct iwl_mvm { | |||
| 1017 | 1015 | ||
| 1018 | /* -1 for always, 0 for never, >0 for that many times */ | 1016 | /* -1 for always, 0 for never, >0 for that many times */ |
| 1019 | s8 fw_restart; | 1017 | s8 fw_restart; |
| 1018 | u8 *error_recovery_buf; | ||
| 1020 | 1019 | ||
| 1021 | #ifdef CONFIG_IWLWIFI_LEDS | 1020 | #ifdef CONFIG_IWLWIFI_LEDS |
| 1022 | struct led_classdev led; | 1021 | struct led_classdev led; |
| @@ -1106,6 +1105,8 @@ struct iwl_mvm { | |||
| 1106 | 1105 | ||
| 1107 | /* Indicate if device power save is allowed */ | 1106 | /* Indicate if device power save is allowed */ |
| 1108 | u8 ps_disabled; /* u8 instead of bool to ease debugfs_create_* usage */ | 1107 | u8 ps_disabled; /* u8 instead of bool to ease debugfs_create_* usage */ |
| 1108 | /* Indicate if 32Khz external clock is valid */ | ||
| 1109 | u32 ext_clock_valid; | ||
| 1109 | unsigned int max_amsdu_len; /* used for debugfs only */ | 1110 | unsigned int max_amsdu_len; /* used for debugfs only */ |
| 1110 | 1111 | ||
| 1111 | struct ieee80211_vif __rcu *csa_vif; | 1112 | struct ieee80211_vif __rcu *csa_vif; |
| @@ -1150,6 +1151,14 @@ struct iwl_mvm { | |||
| 1150 | u32 ciphers[IWL_MVM_NUM_CIPHERS]; | 1151 | u32 ciphers[IWL_MVM_NUM_CIPHERS]; |
| 1151 | struct ieee80211_cipher_scheme cs[IWL_UCODE_MAX_CS]; | 1152 | struct ieee80211_cipher_scheme cs[IWL_UCODE_MAX_CS]; |
| 1152 | 1153 | ||
| 1154 | struct cfg80211_ftm_responder_stats ftm_resp_stats; | ||
| 1155 | struct { | ||
| 1156 | struct cfg80211_pmsr_request *req; | ||
| 1157 | struct wireless_dev *req_wdev; | ||
| 1158 | struct list_head loc_list; | ||
| 1159 | int responses[IWL_MVM_TOF_MAX_APS]; | ||
| 1160 | } ftm_initiator; | ||
| 1161 | |||
| 1153 | struct ieee80211_vif *nan_vif; | 1162 | struct ieee80211_vif *nan_vif; |
| 1154 | #define IWL_MAX_BAID 32 | 1163 | #define IWL_MAX_BAID 32 |
| 1155 | struct iwl_mvm_baid_data __rcu *baid_map[IWL_MAX_BAID]; | 1164 | struct iwl_mvm_baid_data __rcu *baid_map[IWL_MAX_BAID]; |
| @@ -1167,6 +1176,7 @@ struct iwl_mvm { | |||
| 1167 | 1176 | ||
| 1168 | /* sniffer data to include in radiotap */ | 1177 | /* sniffer data to include in radiotap */ |
| 1169 | __le16 cur_aid; | 1178 | __le16 cur_aid; |
| 1179 | u8 cur_bssid[ETH_ALEN]; | ||
| 1170 | 1180 | ||
| 1171 | #ifdef CONFIG_ACPI | 1181 | #ifdef CONFIG_ACPI |
| 1172 | struct iwl_mvm_sar_profile sar_profiles[ACPI_SAR_PROFILE_NUM]; | 1182 | struct iwl_mvm_sar_profile sar_profiles[ACPI_SAR_PROFILE_NUM]; |
| @@ -1211,7 +1221,6 @@ enum iwl_mvm_status { | |||
| 1211 | enum iwl_mvm_init_status { | 1221 | enum iwl_mvm_init_status { |
| 1212 | IWL_MVM_INIT_STATUS_THERMAL_INIT_COMPLETE = BIT(0), | 1222 | IWL_MVM_INIT_STATUS_THERMAL_INIT_COMPLETE = BIT(0), |
| 1213 | IWL_MVM_INIT_STATUS_LEDS_INIT_COMPLETE = BIT(1), | 1223 | IWL_MVM_INIT_STATUS_LEDS_INIT_COMPLETE = BIT(1), |
| 1214 | IWL_MVM_INIT_STATUS_REG_HW_INIT_COMPLETE = BIT(2), | ||
| 1215 | }; | 1224 | }; |
| 1216 | 1225 | ||
| 1217 | static inline bool iwl_mvm_is_radio_killed(struct iwl_mvm *mvm) | 1226 | static inline bool iwl_mvm_is_radio_killed(struct iwl_mvm *mvm) |
| @@ -1311,6 +1320,12 @@ static inline bool iwl_mvm_is_frag_ebs_supported(struct iwl_mvm *mvm) | |||
| 1311 | return fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_FRAG_EBS); | 1320 | return fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_FRAG_EBS); |
| 1312 | } | 1321 | } |
| 1313 | 1322 | ||
| 1323 | static inline bool iwl_mvm_is_short_beacon_notif_supported(struct iwl_mvm *mvm) | ||
| 1324 | { | ||
| 1325 | return fw_has_api(&mvm->fw->ucode_capa, | ||
| 1326 | IWL_UCODE_TLV_API_SHORT_BEACON_NOTIF); | ||
| 1327 | } | ||
| 1328 | |||
| 1314 | static inline bool iwl_mvm_enter_d0i3_on_suspend(struct iwl_mvm *mvm) | 1329 | static inline bool iwl_mvm_enter_d0i3_on_suspend(struct iwl_mvm *mvm) |
| 1315 | { | 1330 | { |
| 1316 | /* For now we only use this mode to differentiate between | 1331 | /* For now we only use this mode to differentiate between |
| @@ -1646,6 +1661,7 @@ void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, | |||
| 1646 | void iwl_mvm_rx_tx_cmd(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb); | 1661 | void iwl_mvm_rx_tx_cmd(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb); |
| 1647 | void iwl_mvm_mfu_assert_dump_notif(struct iwl_mvm *mvm, | 1662 | void iwl_mvm_mfu_assert_dump_notif(struct iwl_mvm *mvm, |
| 1648 | struct iwl_rx_cmd_buffer *rxb); | 1663 | struct iwl_rx_cmd_buffer *rxb); |
| 1664 | void iwl_mvm_send_recovery_cmd(struct iwl_mvm *mvm, u32 flags); | ||
| 1649 | void iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb); | 1665 | void iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb); |
| 1650 | void iwl_mvm_rx_ant_coupling_notif(struct iwl_mvm *mvm, | 1666 | void iwl_mvm_rx_ant_coupling_notif(struct iwl_mvm *mvm, |
| 1651 | struct iwl_rx_cmd_buffer *rxb); | 1667 | struct iwl_rx_cmd_buffer *rxb); |
| @@ -1680,6 +1696,17 @@ int iwl_mvm_mac_ctxt_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
| 1680 | int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif); | 1696 | int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif); |
| 1681 | int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm, | 1697 | int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm, |
| 1682 | struct ieee80211_vif *vif); | 1698 | struct ieee80211_vif *vif); |
| 1699 | int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm, | ||
| 1700 | struct ieee80211_vif *vif, | ||
| 1701 | struct sk_buff *beacon); | ||
| 1702 | int iwl_mvm_mac_ctxt_send_beacon_cmd(struct iwl_mvm *mvm, | ||
| 1703 | struct sk_buff *beacon, | ||
| 1704 | void *data, int len); | ||
| 1705 | u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct ieee80211_tx_info *info, | ||
| 1706 | struct ieee80211_vif *vif); | ||
| 1707 | void iwl_mvm_mac_ctxt_set_tim(struct iwl_mvm *mvm, | ||
| 1708 | __le32 *tim_index, __le32 *tim_size, | ||
| 1709 | u8 *beacon, u32 frame_size); | ||
| 1683 | void iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm, | 1710 | void iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm, |
| 1684 | struct iwl_rx_cmd_buffer *rxb); | 1711 | struct iwl_rx_cmd_buffer *rxb); |
| 1685 | void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm, | 1712 | void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm, |
| @@ -2007,15 +2034,12 @@ static inline void iwl_mvm_stop_device(struct iwl_mvm *mvm) | |||
| 2007 | &mvm->status)) | 2034 | &mvm->status)) |
| 2008 | iwl_fw_dbg_collect_desc(&mvm->fwrt, &iwl_dump_desc_assert, | 2035 | iwl_fw_dbg_collect_desc(&mvm->fwrt, &iwl_dump_desc_assert, |
| 2009 | false, 0); | 2036 | false, 0); |
| 2010 | /* calling this function without using dump_start/end since at this | 2037 | |
| 2011 | * point we already hold the op mode mutex | ||
| 2012 | */ | ||
| 2013 | iwl_fw_dbg_collect_sync(&mvm->fwrt); | ||
| 2014 | iwl_fw_cancel_timestamp(&mvm->fwrt); | 2038 | iwl_fw_cancel_timestamp(&mvm->fwrt); |
| 2015 | iwl_free_fw_paging(&mvm->fwrt); | ||
| 2016 | clear_bit(IWL_MVM_STATUS_FIRMWARE_RUNNING, &mvm->status); | 2039 | clear_bit(IWL_MVM_STATUS_FIRMWARE_RUNNING, &mvm->status); |
| 2040 | iwl_fwrt_stop_device(&mvm->fwrt); | ||
| 2041 | iwl_free_fw_paging(&mvm->fwrt); | ||
| 2017 | iwl_fw_dump_conf_clear(&mvm->fwrt); | 2042 | iwl_fw_dump_conf_clear(&mvm->fwrt); |
| 2018 | iwl_trans_stop_device(mvm->trans); | ||
| 2019 | } | 2043 | } |
| 2020 | 2044 | ||
| 2021 | /* Re-configure the SCD for a queue that has already been configured */ | 2045 | /* Re-configure the SCD for a queue that has already been configured */ |
| @@ -2057,6 +2081,23 @@ void iwl_mvm_update_changed_regdom(struct iwl_mvm *mvm); | |||
| 2057 | int iwl_mvm_sf_update(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | 2081 | int iwl_mvm_sf_update(struct iwl_mvm *mvm, struct ieee80211_vif *vif, |
| 2058 | bool added_vif); | 2082 | bool added_vif); |
| 2059 | 2083 | ||
| 2084 | /* FTM responder */ | ||
| 2085 | int iwl_mvm_ftm_start_responder(struct iwl_mvm *mvm, struct ieee80211_vif *vif); | ||
| 2086 | void iwl_mvm_ftm_restart_responder(struct iwl_mvm *mvm, | ||
| 2087 | struct ieee80211_vif *vif); | ||
| 2088 | void iwl_mvm_ftm_responder_stats(struct iwl_mvm *mvm, | ||
| 2089 | struct iwl_rx_cmd_buffer *rxb); | ||
| 2090 | |||
| 2091 | /* FTM initiator */ | ||
| 2092 | void iwl_mvm_ftm_restart(struct iwl_mvm *mvm); | ||
| 2093 | void iwl_mvm_ftm_range_resp(struct iwl_mvm *mvm, | ||
| 2094 | struct iwl_rx_cmd_buffer *rxb); | ||
| 2095 | void iwl_mvm_ftm_lc_notif(struct iwl_mvm *mvm, | ||
| 2096 | struct iwl_rx_cmd_buffer *rxb); | ||
| 2097 | int iwl_mvm_ftm_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | ||
| 2098 | struct cfg80211_pmsr_request *request); | ||
| 2099 | void iwl_mvm_ftm_abort(struct iwl_mvm *mvm, struct cfg80211_pmsr_request *req); | ||
| 2100 | |||
| 2060 | /* TDLS */ | 2101 | /* TDLS */ |
| 2061 | 2102 | ||
| 2062 | /* | 2103 | /* |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index 5e4f8b767d10..ba27dce4c2bb 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c | |||
| @@ -82,7 +82,6 @@ | |||
| 82 | #include "fw/api/scan.h" | 82 | #include "fw/api/scan.h" |
| 83 | #include "time-event.h" | 83 | #include "time-event.h" |
| 84 | #include "fw-api.h" | 84 | #include "fw-api.h" |
| 85 | #include "fw/api/scan.h" | ||
| 86 | #include "fw/acpi.h" | 85 | #include "fw/acpi.h" |
| 87 | 86 | ||
| 88 | #define DRV_DESCRIPTION "The new Intel(R) wireless AGN driver for Linux" | 87 | #define DRV_DESCRIPTION "The new Intel(R) wireless AGN driver for Linux" |
| @@ -301,6 +300,14 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = { | |||
| 301 | RX_HANDLER_ASYNC_LOCKED), | 300 | RX_HANDLER_ASYNC_LOCKED), |
| 302 | RX_HANDLER(MFUART_LOAD_NOTIFICATION, iwl_mvm_rx_mfuart_notif, | 301 | RX_HANDLER(MFUART_LOAD_NOTIFICATION, iwl_mvm_rx_mfuart_notif, |
| 303 | RX_HANDLER_SYNC), | 302 | RX_HANDLER_SYNC), |
| 303 | RX_HANDLER_GRP(LOCATION_GROUP, TOF_RESPONDER_STATS, | ||
| 304 | iwl_mvm_ftm_responder_stats, RX_HANDLER_ASYNC_LOCKED), | ||
| 305 | |||
| 306 | RX_HANDLER_GRP(LOCATION_GROUP, TOF_RANGE_RESPONSE_NOTIF, | ||
| 307 | iwl_mvm_ftm_range_resp, RX_HANDLER_ASYNC_LOCKED), | ||
| 308 | RX_HANDLER_GRP(LOCATION_GROUP, TOF_LC_NOTIF, | ||
| 309 | iwl_mvm_ftm_lc_notif, RX_HANDLER_ASYNC_LOCKED), | ||
| 310 | |||
| 304 | RX_HANDLER_GRP(DEBUG_GROUP, MFU_ASSERT_DUMP_NTF, | 311 | RX_HANDLER_GRP(DEBUG_GROUP, MFU_ASSERT_DUMP_NTF, |
| 305 | iwl_mvm_mfu_assert_dump_notif, RX_HANDLER_SYNC), | 312 | iwl_mvm_mfu_assert_dump_notif, RX_HANDLER_SYNC), |
| 306 | RX_HANDLER_GRP(PROT_OFFLOAD_GROUP, STORED_BEACON_NTF, | 313 | RX_HANDLER_GRP(PROT_OFFLOAD_GROUP, STORED_BEACON_NTF, |
| @@ -415,12 +422,14 @@ static const struct iwl_hcmd_names iwl_mvm_legacy_names[] = { | |||
| 415 | static const struct iwl_hcmd_names iwl_mvm_system_names[] = { | 422 | static const struct iwl_hcmd_names iwl_mvm_system_names[] = { |
| 416 | HCMD_NAME(SHARED_MEM_CFG_CMD), | 423 | HCMD_NAME(SHARED_MEM_CFG_CMD), |
| 417 | HCMD_NAME(INIT_EXTENDED_CFG_CMD), | 424 | HCMD_NAME(INIT_EXTENDED_CFG_CMD), |
| 425 | HCMD_NAME(FW_ERROR_RECOVERY_CMD), | ||
| 418 | }; | 426 | }; |
| 419 | 427 | ||
| 420 | /* Please keep this array *SORTED* by hex value. | 428 | /* Please keep this array *SORTED* by hex value. |
| 421 | * Access is done through binary search | 429 | * Access is done through binary search |
| 422 | */ | 430 | */ |
| 423 | static const struct iwl_hcmd_names iwl_mvm_mac_conf_names[] = { | 431 | static const struct iwl_hcmd_names iwl_mvm_mac_conf_names[] = { |
| 432 | HCMD_NAME(CHANNEL_SWITCH_TIME_EVENT_CMD), | ||
| 424 | HCMD_NAME(CHANNEL_SWITCH_NOA_NOTIF), | 433 | HCMD_NAME(CHANNEL_SWITCH_NOA_NOTIF), |
| 425 | }; | 434 | }; |
| 426 | 435 | ||
| @@ -445,6 +454,7 @@ static const struct iwl_hcmd_names iwl_mvm_data_path_names[] = { | |||
| 445 | HCMD_NAME(TRIGGER_RX_QUEUES_NOTIF_CMD), | 454 | HCMD_NAME(TRIGGER_RX_QUEUES_NOTIF_CMD), |
| 446 | HCMD_NAME(STA_HE_CTXT_CMD), | 455 | HCMD_NAME(STA_HE_CTXT_CMD), |
| 447 | HCMD_NAME(RFH_QUEUE_CONFIG_CMD), | 456 | HCMD_NAME(RFH_QUEUE_CONFIG_CMD), |
| 457 | HCMD_NAME(TLC_MNG_CONFIG_CMD), | ||
| 448 | HCMD_NAME(CHEST_COLLECTOR_FILTER_CONFIG_CMD), | 458 | HCMD_NAME(CHEST_COLLECTOR_FILTER_CONFIG_CMD), |
| 449 | HCMD_NAME(STA_PM_NOTIF), | 459 | HCMD_NAME(STA_PM_NOTIF), |
| 450 | HCMD_NAME(MU_GROUP_MGMT_NOTIF), | 460 | HCMD_NAME(MU_GROUP_MGMT_NOTIF), |
| @@ -591,11 +601,17 @@ static int iwl_mvm_fwrt_send_hcmd(void *ctx, struct iwl_host_cmd *host_cmd) | |||
| 591 | return ret; | 601 | return ret; |
| 592 | } | 602 | } |
| 593 | 603 | ||
| 604 | static bool iwl_mvm_d3_debug_enable(void *ctx) | ||
| 605 | { | ||
| 606 | return IWL_MVM_D3_DEBUG; | ||
| 607 | } | ||
| 608 | |||
| 594 | static const struct iwl_fw_runtime_ops iwl_mvm_fwrt_ops = { | 609 | static const struct iwl_fw_runtime_ops iwl_mvm_fwrt_ops = { |
| 595 | .dump_start = iwl_mvm_fwrt_dump_start, | 610 | .dump_start = iwl_mvm_fwrt_dump_start, |
| 596 | .dump_end = iwl_mvm_fwrt_dump_end, | 611 | .dump_end = iwl_mvm_fwrt_dump_end, |
| 597 | .fw_running = iwl_mvm_fwrt_fw_running, | 612 | .fw_running = iwl_mvm_fwrt_fw_running, |
| 598 | .send_hcmd = iwl_mvm_fwrt_send_hcmd, | 613 | .send_hcmd = iwl_mvm_fwrt_send_hcmd, |
| 614 | .d3_debug_enable = iwl_mvm_d3_debug_enable, | ||
| 599 | }; | 615 | }; |
| 600 | 616 | ||
| 601 | static struct iwl_op_mode * | 617 | static struct iwl_op_mode * |
| @@ -690,6 +706,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
| 690 | INIT_LIST_HEAD(&mvm->aux_roc_te_list); | 706 | INIT_LIST_HEAD(&mvm->aux_roc_te_list); |
| 691 | INIT_LIST_HEAD(&mvm->async_handlers_list); | 707 | INIT_LIST_HEAD(&mvm->async_handlers_list); |
| 692 | spin_lock_init(&mvm->time_event_lock); | 708 | spin_lock_init(&mvm->time_event_lock); |
| 709 | INIT_LIST_HEAD(&mvm->ftm_initiator.loc_list); | ||
| 693 | 710 | ||
| 694 | INIT_WORK(&mvm->async_handlers_wk, iwl_mvm_async_handlers_wk); | 711 | INIT_WORK(&mvm->async_handlers_wk, iwl_mvm_async_handlers_wk); |
| 695 | INIT_WORK(&mvm->roc_done_wk, iwl_mvm_roc_done_wk); | 712 | INIT_WORK(&mvm->roc_done_wk, iwl_mvm_roc_done_wk); |
| @@ -817,8 +834,8 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
| 817 | mutex_lock(&mvm->mutex); | 834 | mutex_lock(&mvm->mutex); |
| 818 | iwl_mvm_ref(mvm, IWL_MVM_REF_INIT_UCODE); | 835 | iwl_mvm_ref(mvm, IWL_MVM_REF_INIT_UCODE); |
| 819 | err = iwl_run_init_mvm_ucode(mvm, true); | 836 | err = iwl_run_init_mvm_ucode(mvm, true); |
| 820 | if (test_bit(IWL_FWRT_STATUS_WAIT_ALIVE, &mvm->fwrt.status)) | 837 | if (err) |
| 821 | iwl_fw_alive_error_dump(&mvm->fwrt); | 838 | iwl_fw_dbg_error_collect(&mvm->fwrt, FW_DBG_TRIGGER_DRIVER); |
| 822 | if (!iwlmvm_mod_params.init_dbg || !err) | 839 | if (!iwlmvm_mod_params.init_dbg || !err) |
| 823 | iwl_mvm_stop_device(mvm); | 840 | iwl_mvm_stop_device(mvm); |
| 824 | iwl_mvm_unref(mvm, IWL_MVM_REF_INIT_UCODE); | 841 | iwl_mvm_unref(mvm, IWL_MVM_REF_INIT_UCODE); |
| @@ -902,15 +919,15 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode) | |||
| 902 | 919 | ||
| 903 | iwl_mvm_thermal_exit(mvm); | 920 | iwl_mvm_thermal_exit(mvm); |
| 904 | 921 | ||
| 905 | if (mvm->init_status & IWL_MVM_INIT_STATUS_REG_HW_INIT_COMPLETE) { | 922 | ieee80211_unregister_hw(mvm->hw); |
| 906 | ieee80211_unregister_hw(mvm->hw); | ||
| 907 | mvm->init_status &= ~IWL_MVM_INIT_STATUS_REG_HW_INIT_COMPLETE; | ||
| 908 | } | ||
| 909 | 923 | ||
| 910 | kfree(mvm->scan_cmd); | 924 | kfree(mvm->scan_cmd); |
| 911 | kfree(mvm->mcast_filter_cmd); | 925 | kfree(mvm->mcast_filter_cmd); |
| 912 | mvm->mcast_filter_cmd = NULL; | 926 | mvm->mcast_filter_cmd = NULL; |
| 913 | 927 | ||
| 928 | kfree(mvm->error_recovery_buf); | ||
| 929 | mvm->error_recovery_buf = NULL; | ||
| 930 | |||
| 914 | #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_IWLWIFI_DEBUGFS) | 931 | #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_IWLWIFI_DEBUGFS) |
| 915 | kfree(mvm->d3_resume_sram); | 932 | kfree(mvm->d3_resume_sram); |
| 916 | #endif | 933 | #endif |
| @@ -1105,6 +1122,12 @@ static void iwl_mvm_async_cb(struct iwl_op_mode *op_mode, | |||
| 1105 | iwl_trans_block_txq_ptrs(mvm->trans, false); | 1122 | iwl_trans_block_txq_ptrs(mvm->trans, false); |
| 1106 | } | 1123 | } |
| 1107 | 1124 | ||
| 1125 | static int iwl_mvm_is_static_queue(struct iwl_mvm *mvm, int queue) | ||
| 1126 | { | ||
| 1127 | return queue == mvm->aux_queue || queue == mvm->probe_queue || | ||
| 1128 | queue == mvm->p2p_dev_queue || queue == mvm->snif_queue; | ||
| 1129 | } | ||
| 1130 | |||
| 1108 | static void iwl_mvm_queue_state_change(struct iwl_op_mode *op_mode, | 1131 | static void iwl_mvm_queue_state_change(struct iwl_op_mode *op_mode, |
| 1109 | int hw_queue, bool start) | 1132 | int hw_queue, bool start) |
| 1110 | { | 1133 | { |
| @@ -1131,6 +1154,15 @@ static void iwl_mvm_queue_state_change(struct iwl_op_mode *op_mode, | |||
| 1131 | goto out; | 1154 | goto out; |
| 1132 | mvmsta = iwl_mvm_sta_from_mac80211(sta); | 1155 | mvmsta = iwl_mvm_sta_from_mac80211(sta); |
| 1133 | 1156 | ||
| 1157 | if (iwl_mvm_is_static_queue(mvm, hw_queue)) { | ||
| 1158 | if (!start) | ||
| 1159 | ieee80211_stop_queues(mvm->hw); | ||
| 1160 | else if (mvmsta->sta_state != IEEE80211_STA_NOTEXIST) | ||
| 1161 | ieee80211_wake_queues(mvm->hw); | ||
| 1162 | |||
| 1163 | goto out; | ||
| 1164 | } | ||
| 1165 | |||
| 1134 | if (iwl_mvm_has_new_tx_api(mvm)) { | 1166 | if (iwl_mvm_has_new_tx_api(mvm)) { |
| 1135 | int tid = mvm->tvqm_info[hw_queue].txq_tid; | 1167 | int tid = mvm->tvqm_info[hw_queue].txq_tid; |
| 1136 | 1168 | ||
| @@ -1285,12 +1317,29 @@ void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error) | |||
| 1285 | reprobe->dev = mvm->trans->dev; | 1317 | reprobe->dev = mvm->trans->dev; |
| 1286 | INIT_WORK(&reprobe->work, iwl_mvm_reprobe_wk); | 1318 | INIT_WORK(&reprobe->work, iwl_mvm_reprobe_wk); |
| 1287 | schedule_work(&reprobe->work); | 1319 | schedule_work(&reprobe->work); |
| 1320 | } else if (test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, | ||
| 1321 | &mvm->status)) { | ||
| 1322 | IWL_ERR(mvm, "HW restart already requested, but not started\n"); | ||
| 1288 | } else if (mvm->fwrt.cur_fw_img == IWL_UCODE_REGULAR && | 1323 | } else if (mvm->fwrt.cur_fw_img == IWL_UCODE_REGULAR && |
| 1289 | mvm->hw_registered && | 1324 | mvm->hw_registered && |
| 1290 | !test_bit(STATUS_TRANS_DEAD, &mvm->trans->status)) { | 1325 | !test_bit(STATUS_TRANS_DEAD, &mvm->trans->status)) { |
| 1291 | /* don't let the transport/FW power down */ | 1326 | /* don't let the transport/FW power down */ |
| 1292 | iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN); | 1327 | iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN); |
| 1293 | 1328 | ||
| 1329 | if (mvm->fw->ucode_capa.error_log_size) { | ||
| 1330 | u32 src_size = mvm->fw->ucode_capa.error_log_size; | ||
| 1331 | u32 src_addr = mvm->fw->ucode_capa.error_log_addr; | ||
| 1332 | u8 *recover_buf = kzalloc(src_size, GFP_ATOMIC); | ||
| 1333 | |||
| 1334 | if (recover_buf) { | ||
| 1335 | mvm->error_recovery_buf = recover_buf; | ||
| 1336 | iwl_trans_read_mem_bytes(mvm->trans, | ||
| 1337 | src_addr, | ||
| 1338 | recover_buf, | ||
| 1339 | src_size); | ||
| 1340 | } | ||
| 1341 | } | ||
| 1342 | |||
| 1294 | if (fw_error && mvm->fw_restart > 0) | 1343 | if (fw_error && mvm->fw_restart > 0) |
| 1295 | mvm->fw_restart--; | 1344 | mvm->fw_restart--; |
| 1296 | set_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status); | 1345 | set_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status); |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c index f369173db11c..86e40bae57e3 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c | |||
| @@ -109,6 +109,7 @@ u8 iwl_mvm_get_ctrl_pos(struct cfg80211_chan_def *chandef) | |||
| 109 | return PHY_VHT_CTRL_POS_4_ABOVE; | 109 | return PHY_VHT_CTRL_POS_4_ABOVE; |
| 110 | default: | 110 | default: |
| 111 | WARN(1, "Invalid channel definition"); | 111 | WARN(1, "Invalid channel definition"); |
| 112 | /* fall through */ | ||
| 112 | case 0: | 113 | case 0: |
| 113 | /* | 114 | /* |
| 114 | * The FW is expected to check the control channel position only | 115 | * The FW is expected to check the control channel position only |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/power.c b/drivers/net/wireless/intel/iwlwifi/mvm/power.c index 5a0a28fd762d..36f5fa1ee793 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/power.c | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 9 | * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH | 9 | * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH |
| 10 | * Copyright(c) 2015 - 2017 Intel Deutschland GmbH | 10 | * Copyright(c) 2015 - 2017 Intel Deutschland GmbH |
| 11 | * Copyright (C) 2018 - 2019 Intel Corporation | ||
| 11 | * | 12 | * |
| 12 | * This program is free software; you can redistribute it and/or modify | 13 | * This program is free software; you can redistribute it and/or modify |
| 13 | * it under the terms of version 2 of the GNU General Public License as | 14 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -30,6 +31,7 @@ | |||
| 30 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. | 31 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 31 | * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH | 32 | * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH |
| 32 | * Copyright(c) 2015 - 2017 Intel Deutschland GmbH | 33 | * Copyright(c) 2015 - 2017 Intel Deutschland GmbH |
| 34 | * Copyright (C) 2018 - 2019 Intel Corporation | ||
| 33 | * All rights reserved. | 35 | * All rights reserved. |
| 34 | * | 36 | * |
| 35 | * Redistribution and use in source and binary forms, with or without | 37 | * Redistribution and use in source and binary forms, with or without |
| @@ -79,6 +81,8 @@ int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm, | |||
| 79 | struct iwl_beacon_filter_cmd *cmd, | 81 | struct iwl_beacon_filter_cmd *cmd, |
| 80 | u32 flags) | 82 | u32 flags) |
| 81 | { | 83 | { |
| 84 | u16 len; | ||
| 85 | |||
| 82 | IWL_DEBUG_POWER(mvm, "ba_enable_beacon_abort is: %d\n", | 86 | IWL_DEBUG_POWER(mvm, "ba_enable_beacon_abort is: %d\n", |
| 83 | le32_to_cpu(cmd->ba_enable_beacon_abort)); | 87 | le32_to_cpu(cmd->ba_enable_beacon_abort)); |
| 84 | IWL_DEBUG_POWER(mvm, "ba_escape_timer is: %d\n", | 88 | IWL_DEBUG_POWER(mvm, "ba_escape_timer is: %d\n", |
| @@ -101,9 +105,23 @@ int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm, | |||
| 101 | le32_to_cpu(cmd->bf_temp_fast_filter)); | 105 | le32_to_cpu(cmd->bf_temp_fast_filter)); |
| 102 | IWL_DEBUG_POWER(mvm, "bf_temp_slow_filter is: %d\n", | 106 | IWL_DEBUG_POWER(mvm, "bf_temp_slow_filter is: %d\n", |
| 103 | le32_to_cpu(cmd->bf_temp_slow_filter)); | 107 | le32_to_cpu(cmd->bf_temp_slow_filter)); |
| 108 | IWL_DEBUG_POWER(mvm, "bf_threshold_absolute_low is: %d, %d\n", | ||
| 109 | le32_to_cpu(cmd->bf_threshold_absolute_low[0]), | ||
| 110 | le32_to_cpu(cmd->bf_threshold_absolute_low[1])); | ||
| 111 | |||
| 112 | IWL_DEBUG_POWER(mvm, "bf_threshold_absolute_high is: %d, %d\n", | ||
| 113 | le32_to_cpu(cmd->bf_threshold_absolute_high[0]), | ||
| 114 | le32_to_cpu(cmd->bf_threshold_absolute_high[1])); | ||
| 115 | |||
| 116 | if (fw_has_api(&mvm->fw->ucode_capa, | ||
| 117 | IWL_UCODE_TLV_API_BEACON_FILTER_V4)) | ||
| 118 | len = sizeof(struct iwl_beacon_filter_cmd); | ||
| 119 | else | ||
| 120 | len = offsetof(struct iwl_beacon_filter_cmd, | ||
| 121 | bf_threshold_absolute_low); | ||
| 104 | 122 | ||
| 105 | return iwl_mvm_send_cmd_pdu(mvm, REPLY_BEACON_FILTERING_CMD, flags, | 123 | return iwl_mvm_send_cmd_pdu(mvm, REPLY_BEACON_FILTERING_CMD, flags, |
| 106 | sizeof(struct iwl_beacon_filter_cmd), cmd); | 124 | len, cmd); |
| 107 | } | 125 | } |
| 108 | 126 | ||
| 109 | static | 127 | static |
| @@ -526,6 +544,9 @@ int iwl_mvm_power_update_device(struct iwl_mvm *mvm) | |||
| 526 | cmd.flags &= | 544 | cmd.flags &= |
| 527 | cpu_to_le16(~DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK); | 545 | cpu_to_le16(~DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK); |
| 528 | #endif | 546 | #endif |
| 547 | if (mvm->ext_clock_valid) | ||
| 548 | cmd.flags |= cpu_to_le16(DEVICE_POWER_FLAGS_32K_CLK_VALID_MSK); | ||
| 549 | |||
| 529 | IWL_DEBUG_POWER(mvm, | 550 | IWL_DEBUG_POWER(mvm, |
| 530 | "Sending device power command with flags = 0x%X\n", | 551 | "Sending device power command with flags = 0x%X\n", |
| 531 | cmd.flags); | 552 | cmd.flags); |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c index 09866f50857a..e231a44d2423 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c | |||
| @@ -3,7 +3,7 @@ | |||
| 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 - 2017 Intel Deutschland GmbH | 5 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH |
| 6 | * Copyright(c) 2018 Intel Corporation | 6 | * Copyright(c) 2018 - 2019 Intel Corporation |
| 7 | * | 7 | * |
| 8 | * This program is free software; you can redistribute it and/or modify it | 8 | * This program is free software; you can redistribute it and/or modify it |
| 9 | * under the terms of version 2 of the GNU General Public License as | 9 | * under the terms of version 2 of the GNU General Public License as |
| @@ -1643,8 +1643,26 @@ static s32 rs_get_best_rate(struct iwl_mvm *mvm, | |||
| 1643 | 1643 | ||
| 1644 | static u32 rs_bw_from_sta_bw(struct ieee80211_sta *sta) | 1644 | static u32 rs_bw_from_sta_bw(struct ieee80211_sta *sta) |
| 1645 | { | 1645 | { |
| 1646 | struct ieee80211_sta_vht_cap *sta_vht_cap = &sta->vht_cap; | ||
| 1647 | struct ieee80211_vht_cap vht_cap = { | ||
| 1648 | .vht_cap_info = cpu_to_le32(sta_vht_cap->cap), | ||
| 1649 | .supp_mcs = sta_vht_cap->vht_mcs, | ||
| 1650 | }; | ||
| 1651 | |||
| 1646 | switch (sta->bandwidth) { | 1652 | switch (sta->bandwidth) { |
| 1647 | case IEEE80211_STA_RX_BW_160: | 1653 | case IEEE80211_STA_RX_BW_160: |
| 1654 | /* | ||
| 1655 | * Don't use 160 MHz if VHT extended NSS support | ||
| 1656 | * says we cannot use 2 streams, we don't want to | ||
| 1657 | * deal with this. | ||
| 1658 | * We only check MCS 0 - they will support that if | ||
| 1659 | * we got here at all and we don't care which MCS, | ||
| 1660 | * we want to determine a more global state. | ||
| 1661 | */ | ||
| 1662 | if (ieee80211_get_vht_max_nss(&vht_cap, | ||
| 1663 | IEEE80211_VHT_CHANWIDTH_160MHZ, | ||
| 1664 | 0, true) < sta->rx_nss) | ||
| 1665 | return RATE_MCS_CHAN_WIDTH_80; | ||
| 1648 | return RATE_MCS_CHAN_WIDTH_160; | 1666 | return RATE_MCS_CHAN_WIDTH_160; |
| 1649 | case IEEE80211_STA_RX_BW_80: | 1667 | case IEEE80211_STA_RX_BW_80: |
| 1650 | return RATE_MCS_CHAN_WIDTH_80; | 1668 | return RATE_MCS_CHAN_WIDTH_80; |
| @@ -1757,7 +1775,12 @@ static void rs_set_amsdu_len(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
| 1757 | else | 1775 | else |
| 1758 | mvmsta->amsdu_enabled = 0xFFFF; | 1776 | mvmsta->amsdu_enabled = 0xFFFF; |
| 1759 | 1777 | ||
| 1760 | mvmsta->max_amsdu_len = sta->max_amsdu_len; | 1778 | if (mvmsta->vif->bss_conf.he_support && |
| 1779 | !iwlwifi_mod_params.disable_11ax) | ||
| 1780 | mvmsta->max_amsdu_len = sta->max_amsdu_len; | ||
| 1781 | else | ||
| 1782 | mvmsta->max_amsdu_len = min_t(int, sta->max_amsdu_len, 8500); | ||
| 1783 | |||
| 1761 | sta->max_rc_amsdu_len = mvmsta->max_amsdu_len; | 1784 | sta->max_rc_amsdu_len = mvmsta->max_amsdu_len; |
| 1762 | 1785 | ||
| 1763 | for (i = 0; i < IWL_MAX_TID_COUNT; i++) { | 1786 | for (i = 0; i < IWL_MAX_TID_COUNT; i++) { |
| @@ -1791,7 +1814,7 @@ static bool rs_tweak_rate_tbl(struct iwl_mvm *mvm, | |||
| 1791 | struct iwl_scale_tbl_info *tbl, | 1814 | struct iwl_scale_tbl_info *tbl, |
| 1792 | enum rs_action scale_action) | 1815 | enum rs_action scale_action) |
| 1793 | { | 1816 | { |
| 1794 | if (sta->bandwidth != IEEE80211_STA_RX_BW_80) | 1817 | if (rs_bw_from_sta_bw(sta) != RATE_MCS_CHAN_WIDTH_80) |
| 1795 | return false; | 1818 | return false; |
| 1796 | 1819 | ||
| 1797 | if (!is_vht_siso(&tbl->rate)) | 1820 | if (!is_vht_siso(&tbl->rate)) |
| @@ -4122,6 +4145,7 @@ static const struct rate_control_ops rs_mvm_ops_drv = { | |||
| 4122 | .add_sta_debugfs = rs_drv_add_sta_debugfs, | 4145 | .add_sta_debugfs = rs_drv_add_sta_debugfs, |
| 4123 | .remove_sta_debugfs = rs_remove_sta_debugfs, | 4146 | .remove_sta_debugfs = rs_remove_sta_debugfs, |
| 4124 | #endif | 4147 | #endif |
| 4148 | .capa = RATE_CTRL_CAPA_VHT_EXT_NSS_BW, | ||
| 4125 | }; | 4149 | }; |
| 4126 | 4150 | ||
| 4127 | void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | 4151 | void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c index 235ab26ca429..fbd3014e8b82 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c | |||
| @@ -222,7 +222,7 @@ static u32 iwl_mvm_set_mac80211_rx_flag(struct iwl_mvm *mvm, | |||
| 222 | !(rx_pkt_status & RX_MPDU_RES_STATUS_TTAK_OK)) | 222 | !(rx_pkt_status & RX_MPDU_RES_STATUS_TTAK_OK)) |
| 223 | return 0; | 223 | return 0; |
| 224 | *crypt_len = IEEE80211_TKIP_IV_LEN; | 224 | *crypt_len = IEEE80211_TKIP_IV_LEN; |
| 225 | /* fall through if TTAK OK */ | 225 | /* fall through */ |
| 226 | 226 | ||
| 227 | case RX_MPDU_RES_STATUS_SEC_WEP_ENC: | 227 | case RX_MPDU_RES_STATUS_SEC_WEP_ENC: |
| 228 | if (!(rx_pkt_status & RX_MPDU_RES_STATUS_ICV_OK)) | 228 | if (!(rx_pkt_status & RX_MPDU_RES_STATUS_ICV_OK)) |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c index 2c56f73d688e..1e03acf30762 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | |||
| @@ -66,11 +66,37 @@ | |||
| 66 | #include "mvm.h" | 66 | #include "mvm.h" |
| 67 | #include "fw-api.h" | 67 | #include "fw-api.h" |
| 68 | 68 | ||
| 69 | static void *iwl_mvm_skb_get_hdr(struct sk_buff *skb) | ||
| 70 | { | ||
| 71 | struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb); | ||
| 72 | u8 *data = skb->data; | ||
| 73 | |||
| 74 | /* Alignment concerns */ | ||
| 75 | BUILD_BUG_ON(sizeof(struct ieee80211_radiotap_he) % 4); | ||
| 76 | BUILD_BUG_ON(sizeof(struct ieee80211_radiotap_he_mu) % 4); | ||
| 77 | BUILD_BUG_ON(sizeof(struct ieee80211_radiotap_lsig) % 4); | ||
| 78 | BUILD_BUG_ON(sizeof(struct ieee80211_vendor_radiotap) % 4); | ||
| 79 | |||
| 80 | if (rx_status->flag & RX_FLAG_RADIOTAP_HE) | ||
| 81 | data += sizeof(struct ieee80211_radiotap_he); | ||
| 82 | if (rx_status->flag & RX_FLAG_RADIOTAP_HE_MU) | ||
| 83 | data += sizeof(struct ieee80211_radiotap_he_mu); | ||
| 84 | if (rx_status->flag & RX_FLAG_RADIOTAP_LSIG) | ||
| 85 | data += sizeof(struct ieee80211_radiotap_lsig); | ||
| 86 | if (rx_status->flag & RX_FLAG_RADIOTAP_VENDOR_DATA) { | ||
| 87 | struct ieee80211_vendor_radiotap *radiotap = (void *)data; | ||
| 88 | |||
| 89 | data += sizeof(*radiotap) + radiotap->len + radiotap->pad; | ||
| 90 | } | ||
| 91 | |||
| 92 | return data; | ||
| 93 | } | ||
| 94 | |||
| 69 | static inline int iwl_mvm_check_pn(struct iwl_mvm *mvm, struct sk_buff *skb, | 95 | static inline int iwl_mvm_check_pn(struct iwl_mvm *mvm, struct sk_buff *skb, |
| 70 | int queue, struct ieee80211_sta *sta) | 96 | int queue, struct ieee80211_sta *sta) |
| 71 | { | 97 | { |
| 72 | struct iwl_mvm_sta *mvmsta; | 98 | struct iwl_mvm_sta *mvmsta; |
| 73 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 99 | struct ieee80211_hdr *hdr = iwl_mvm_skb_get_hdr(skb); |
| 74 | struct ieee80211_rx_status *stats = IEEE80211_SKB_RXCB(skb); | 100 | struct ieee80211_rx_status *stats = IEEE80211_SKB_RXCB(skb); |
| 75 | struct iwl_mvm_key_pn *ptk_pn; | 101 | struct iwl_mvm_key_pn *ptk_pn; |
| 76 | int res; | 102 | int res; |
| @@ -197,12 +223,15 @@ static void iwl_mvm_add_rtap_sniffer_config(struct iwl_mvm *mvm, | |||
| 197 | { | 223 | { |
| 198 | struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb); | 224 | struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb); |
| 199 | struct ieee80211_vendor_radiotap *radiotap; | 225 | struct ieee80211_vendor_radiotap *radiotap; |
| 200 | int size = sizeof(*radiotap) + sizeof(__le16); | 226 | const int size = sizeof(*radiotap) + sizeof(__le16); |
| 201 | 227 | ||
| 202 | if (!mvm->cur_aid) | 228 | if (!mvm->cur_aid) |
| 203 | return; | 229 | return; |
| 204 | 230 | ||
| 205 | radiotap = skb_put(skb, size); | 231 | /* ensure alignment */ |
| 232 | BUILD_BUG_ON((size + 2) % 4); | ||
| 233 | |||
| 234 | radiotap = skb_put(skb, size + 2); | ||
| 206 | radiotap->align = 1; | 235 | radiotap->align = 1; |
| 207 | /* Intel OUI */ | 236 | /* Intel OUI */ |
| 208 | radiotap->oui[0] = 0xf6; | 237 | radiotap->oui[0] = 0xf6; |
| @@ -212,10 +241,12 @@ static void iwl_mvm_add_rtap_sniffer_config(struct iwl_mvm *mvm, | |||
| 212 | radiotap->subns = 1; | 241 | radiotap->subns = 1; |
| 213 | radiotap->present = 0x1; | 242 | radiotap->present = 0x1; |
| 214 | radiotap->len = size - sizeof(*radiotap); | 243 | radiotap->len = size - sizeof(*radiotap); |
| 215 | radiotap->pad = 0; | 244 | radiotap->pad = 2; |
| 216 | 245 | ||
| 217 | /* fill the data now */ | 246 | /* fill the data now */ |
| 218 | memcpy(radiotap->data, &mvm->cur_aid, sizeof(mvm->cur_aid)); | 247 | memcpy(radiotap->data, &mvm->cur_aid, sizeof(mvm->cur_aid)); |
| 248 | /* and clear the padding */ | ||
| 249 | memset(radiotap->data + sizeof(__le16), 0, radiotap->pad); | ||
| 219 | 250 | ||
| 220 | rx_status->flag |= RX_FLAG_RADIOTAP_VENDOR_DATA; | 251 | rx_status->flag |= RX_FLAG_RADIOTAP_VENDOR_DATA; |
| 221 | } | 252 | } |
| @@ -227,10 +258,7 @@ static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm, | |||
| 227 | struct ieee80211_sta *sta, | 258 | struct ieee80211_sta *sta, |
| 228 | bool csi) | 259 | bool csi) |
| 229 | { | 260 | { |
| 230 | struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb); | 261 | if (iwl_mvm_check_pn(mvm, skb, queue, sta)) |
| 231 | |||
| 232 | if (!(rx_status->flag & RX_FLAG_NO_PSDU) && | ||
| 233 | iwl_mvm_check_pn(mvm, skb, queue, sta)) | ||
| 234 | kfree_skb(skb); | 262 | kfree_skb(skb); |
| 235 | else | 263 | else |
| 236 | ieee80211_rx_napi(mvm->hw, sta, skb, napi); | 264 | ieee80211_rx_napi(mvm->hw, sta, skb, napi); |
| @@ -310,7 +338,7 @@ static int iwl_mvm_rx_crypto(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr, | |||
| 310 | stats->flag |= RX_FLAG_MMIC_ERROR; | 338 | stats->flag |= RX_FLAG_MMIC_ERROR; |
| 311 | 339 | ||
| 312 | *crypt_len = IEEE80211_TKIP_IV_LEN; | 340 | *crypt_len = IEEE80211_TKIP_IV_LEN; |
| 313 | /* fall through if TTAK OK */ | 341 | /* fall through */ |
| 314 | case IWL_RX_MPDU_STATUS_SEC_WEP: | 342 | case IWL_RX_MPDU_STATUS_SEC_WEP: |
| 315 | if (!(status & IWL_RX_MPDU_STATUS_ICV_OK)) | 343 | if (!(status & IWL_RX_MPDU_STATUS_ICV_OK)) |
| 316 | return -1; | 344 | return -1; |
| @@ -663,7 +691,7 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm, | |||
| 663 | struct sk_buff *skb, | 691 | struct sk_buff *skb, |
| 664 | struct iwl_rx_mpdu_desc *desc) | 692 | struct iwl_rx_mpdu_desc *desc) |
| 665 | { | 693 | { |
| 666 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 694 | struct ieee80211_hdr *hdr = iwl_mvm_skb_get_hdr(skb); |
| 667 | struct iwl_mvm_sta *mvm_sta; | 695 | struct iwl_mvm_sta *mvm_sta; |
| 668 | struct iwl_mvm_baid_data *baid_data; | 696 | struct iwl_mvm_baid_data *baid_data; |
| 669 | struct iwl_mvm_reorder_buffer *buffer; | 697 | struct iwl_mvm_reorder_buffer *buffer; |
| @@ -960,6 +988,7 @@ iwl_mvm_decode_he_phy_ru_alloc(struct iwl_mvm_rx_phy_data *phy_data, | |||
| 960 | * the TSF/timers are not be transmitted in HE-MU. | 988 | * the TSF/timers are not be transmitted in HE-MU. |
| 961 | */ | 989 | */ |
| 962 | u8 ru = le32_get_bits(phy_data->d1, IWL_RX_PHY_DATA1_HE_RU_ALLOC_MASK); | 990 | u8 ru = le32_get_bits(phy_data->d1, IWL_RX_PHY_DATA1_HE_RU_ALLOC_MASK); |
| 991 | u32 he_type = rate_n_flags & RATE_MCS_HE_TYPE_MSK; | ||
| 963 | u8 offs = 0; | 992 | u8 offs = 0; |
| 964 | 993 | ||
| 965 | rx_status->bw = RATE_INFO_BW_HE_RU; | 994 | rx_status->bw = RATE_INFO_BW_HE_RU; |
| @@ -1002,19 +1031,27 @@ iwl_mvm_decode_he_phy_ru_alloc(struct iwl_mvm_rx_phy_data *phy_data, | |||
| 1002 | he->data2 |= | 1031 | he->data2 |= |
| 1003 | cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_SEC); | 1032 | cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_SEC); |
| 1004 | 1033 | ||
| 1005 | if (he_mu) { | ||
| 1006 | #define CHECK_BW(bw) \ | 1034 | #define CHECK_BW(bw) \ |
| 1007 | BUILD_BUG_ON(IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_ ## bw ## MHZ != \ | 1035 | BUILD_BUG_ON(IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_ ## bw ## MHZ != \ |
| 1036 | RATE_MCS_CHAN_WIDTH_##bw >> RATE_MCS_CHAN_WIDTH_POS); \ | ||
| 1037 | BUILD_BUG_ON(IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW_ ## bw ## MHZ != \ | ||
| 1008 | RATE_MCS_CHAN_WIDTH_##bw >> RATE_MCS_CHAN_WIDTH_POS) | 1038 | RATE_MCS_CHAN_WIDTH_##bw >> RATE_MCS_CHAN_WIDTH_POS) |
| 1009 | CHECK_BW(20); | 1039 | CHECK_BW(20); |
| 1010 | CHECK_BW(40); | 1040 | CHECK_BW(40); |
| 1011 | CHECK_BW(80); | 1041 | CHECK_BW(80); |
| 1012 | CHECK_BW(160); | 1042 | CHECK_BW(160); |
| 1043 | |||
| 1044 | if (he_mu) | ||
| 1013 | he_mu->flags2 |= | 1045 | he_mu->flags2 |= |
| 1014 | le16_encode_bits(FIELD_GET(RATE_MCS_CHAN_WIDTH_MSK, | 1046 | le16_encode_bits(FIELD_GET(RATE_MCS_CHAN_WIDTH_MSK, |
| 1015 | rate_n_flags), | 1047 | rate_n_flags), |
| 1016 | IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW); | 1048 | IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW); |
| 1017 | } | 1049 | else if (he_type == RATE_MCS_HE_TYPE_TRIG) |
| 1050 | he->data6 |= | ||
| 1051 | cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW_KNOWN) | | ||
| 1052 | le16_encode_bits(FIELD_GET(RATE_MCS_CHAN_WIDTH_MSK, | ||
| 1053 | rate_n_flags), | ||
| 1054 | IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW); | ||
| 1018 | } | 1055 | } |
| 1019 | 1056 | ||
| 1020 | static void iwl_mvm_decode_he_phy_data(struct iwl_mvm *mvm, | 1057 | static void iwl_mvm_decode_he_phy_data(struct iwl_mvm *mvm, |
| @@ -1037,16 +1074,16 @@ static void iwl_mvm_decode_he_phy_data(struct iwl_mvm *mvm, | |||
| 1037 | IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE2_KNOWN | | 1074 | IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE2_KNOWN | |
| 1038 | IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE3_KNOWN | | 1075 | IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE3_KNOWN | |
| 1039 | IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE4_KNOWN); | 1076 | IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE4_KNOWN); |
| 1040 | he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d0, | 1077 | he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d2, |
| 1041 | IWL_RX_PHY_DATA2_HE_TB_EXT_SPTL_REUSE1), | 1078 | IWL_RX_PHY_DATA2_HE_TB_EXT_SPTL_REUSE1), |
| 1042 | IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE1); | 1079 | IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE1); |
| 1043 | he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d0, | 1080 | he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d2, |
| 1044 | IWL_RX_PHY_DATA2_HE_TB_EXT_SPTL_REUSE2), | 1081 | IWL_RX_PHY_DATA2_HE_TB_EXT_SPTL_REUSE2), |
| 1045 | IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE2); | 1082 | IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE2); |
| 1046 | he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d0, | 1083 | he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d2, |
| 1047 | IWL_RX_PHY_DATA2_HE_TB_EXT_SPTL_REUSE3), | 1084 | IWL_RX_PHY_DATA2_HE_TB_EXT_SPTL_REUSE3), |
| 1048 | IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE3); | 1085 | IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE3); |
| 1049 | he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d0, | 1086 | he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d2, |
| 1050 | IWL_RX_PHY_DATA2_HE_TB_EXT_SPTL_REUSE4), | 1087 | IWL_RX_PHY_DATA2_HE_TB_EXT_SPTL_REUSE4), |
| 1051 | IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE4); | 1088 | IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE4); |
| 1052 | /* fall through */ | 1089 | /* fall through */ |
| @@ -1056,7 +1093,6 @@ static void iwl_mvm_decode_he_phy_data(struct iwl_mvm *mvm, | |||
| 1056 | case IWL_RX_PHY_INFO_TYPE_HE_TB: | 1093 | case IWL_RX_PHY_INFO_TYPE_HE_TB: |
| 1057 | /* HE common */ | 1094 | /* HE common */ |
| 1058 | he->data1 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_LDPC_XSYMSEG_KNOWN | | 1095 | he->data1 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_LDPC_XSYMSEG_KNOWN | |
| 1059 | IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE_KNOWN | | ||
| 1060 | IEEE80211_RADIOTAP_HE_DATA1_DOPPLER_KNOWN | | 1096 | IEEE80211_RADIOTAP_HE_DATA1_DOPPLER_KNOWN | |
| 1061 | IEEE80211_RADIOTAP_HE_DATA1_BSS_COLOR_KNOWN); | 1097 | IEEE80211_RADIOTAP_HE_DATA1_BSS_COLOR_KNOWN); |
| 1062 | he->data2 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_PRE_FEC_PAD_KNOWN | | 1098 | he->data2 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_PRE_FEC_PAD_KNOWN | |
| @@ -1076,9 +1112,6 @@ static void iwl_mvm_decode_he_phy_data(struct iwl_mvm *mvm, | |||
| 1076 | he->data3 |= le16_encode_bits(le32_get_bits(phy_data->d0, | 1112 | he->data3 |= le16_encode_bits(le32_get_bits(phy_data->d0, |
| 1077 | IWL_RX_PHY_DATA0_HE_LDPC_EXT_SYM), | 1113 | IWL_RX_PHY_DATA0_HE_LDPC_EXT_SYM), |
| 1078 | IEEE80211_RADIOTAP_HE_DATA3_LDPC_XSYMSEG); | 1114 | IEEE80211_RADIOTAP_HE_DATA3_LDPC_XSYMSEG); |
| 1079 | he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d0, | ||
| 1080 | IWL_RX_PHY_DATA0_HE_SPATIAL_REUSE_MASK), | ||
| 1081 | IEEE80211_RADIOTAP_HE_DATA4_SU_MU_SPTL_REUSE); | ||
| 1082 | he->data5 |= le16_encode_bits(le32_get_bits(phy_data->d0, | 1115 | he->data5 |= le16_encode_bits(le32_get_bits(phy_data->d0, |
| 1083 | IWL_RX_PHY_DATA0_HE_PRE_FEC_PAD_MASK), | 1116 | IWL_RX_PHY_DATA0_HE_PRE_FEC_PAD_MASK), |
| 1084 | IEEE80211_RADIOTAP_HE_DATA5_PRE_FEC_PAD); | 1117 | IEEE80211_RADIOTAP_HE_DATA5_PRE_FEC_PAD); |
| @@ -1099,6 +1132,20 @@ static void iwl_mvm_decode_he_phy_data(struct iwl_mvm *mvm, | |||
| 1099 | 1132 | ||
| 1100 | switch (phy_data->info_type) { | 1133 | switch (phy_data->info_type) { |
| 1101 | case IWL_RX_PHY_INFO_TYPE_HE_MU_EXT: | 1134 | case IWL_RX_PHY_INFO_TYPE_HE_MU_EXT: |
| 1135 | case IWL_RX_PHY_INFO_TYPE_HE_MU: | ||
| 1136 | case IWL_RX_PHY_INFO_TYPE_HE_SU: | ||
| 1137 | he->data1 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE_KNOWN); | ||
| 1138 | he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d0, | ||
| 1139 | IWL_RX_PHY_DATA0_HE_SPATIAL_REUSE_MASK), | ||
| 1140 | IEEE80211_RADIOTAP_HE_DATA4_SU_MU_SPTL_REUSE); | ||
| 1141 | break; | ||
| 1142 | default: | ||
| 1143 | /* nothing here */ | ||
| 1144 | break; | ||
| 1145 | } | ||
| 1146 | |||
| 1147 | switch (phy_data->info_type) { | ||
| 1148 | case IWL_RX_PHY_INFO_TYPE_HE_MU_EXT: | ||
| 1102 | he_mu->flags1 |= | 1149 | he_mu->flags1 |= |
| 1103 | le16_encode_bits(le16_get_bits(phy_data->d4, | 1150 | le16_encode_bits(le16_get_bits(phy_data->d4, |
| 1104 | IWL_RX_PHY_DATA4_HE_MU_EXT_SIGB_DCM), | 1151 | IWL_RX_PHY_DATA4_HE_MU_EXT_SIGB_DCM), |
| @@ -1165,22 +1212,16 @@ static void iwl_mvm_rx_he(struct iwl_mvm *mvm, struct sk_buff *skb, | |||
| 1165 | .flags2 = cpu_to_le16(IEEE80211_RADIOTAP_HE_MU_FLAGS2_PUNC_FROM_SIG_A_BW_KNOWN | | 1212 | .flags2 = cpu_to_le16(IEEE80211_RADIOTAP_HE_MU_FLAGS2_PUNC_FROM_SIG_A_BW_KNOWN | |
| 1166 | IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN), | 1213 | IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN), |
| 1167 | }; | 1214 | }; |
| 1168 | unsigned int radiotap_len = 0; | ||
| 1169 | 1215 | ||
| 1170 | he = skb_put_data(skb, &known, sizeof(known)); | 1216 | he = skb_put_data(skb, &known, sizeof(known)); |
| 1171 | radiotap_len += sizeof(known); | ||
| 1172 | rx_status->flag |= RX_FLAG_RADIOTAP_HE; | 1217 | rx_status->flag |= RX_FLAG_RADIOTAP_HE; |
| 1173 | 1218 | ||
| 1174 | if (phy_data->info_type == IWL_RX_PHY_INFO_TYPE_HE_MU || | 1219 | if (phy_data->info_type == IWL_RX_PHY_INFO_TYPE_HE_MU || |
| 1175 | phy_data->info_type == IWL_RX_PHY_INFO_TYPE_HE_MU_EXT) { | 1220 | phy_data->info_type == IWL_RX_PHY_INFO_TYPE_HE_MU_EXT) { |
| 1176 | he_mu = skb_put_data(skb, &mu_known, sizeof(mu_known)); | 1221 | he_mu = skb_put_data(skb, &mu_known, sizeof(mu_known)); |
| 1177 | radiotap_len += sizeof(mu_known); | ||
| 1178 | rx_status->flag |= RX_FLAG_RADIOTAP_HE_MU; | 1222 | rx_status->flag |= RX_FLAG_RADIOTAP_HE_MU; |
| 1179 | } | 1223 | } |
| 1180 | 1224 | ||
| 1181 | /* temporarily hide the radiotap data */ | ||
| 1182 | __skb_pull(skb, radiotap_len); | ||
| 1183 | |||
| 1184 | /* report the AMPDU-EOF bit on single frames */ | 1225 | /* report the AMPDU-EOF bit on single frames */ |
| 1185 | if (!queue && !(phy_info & IWL_RX_MPDU_PHY_AMPDU)) { | 1226 | if (!queue && !(phy_info & IWL_RX_MPDU_PHY_AMPDU)) { |
| 1186 | rx_status->flag |= RX_FLAG_AMPDU_DETAILS; | 1227 | rx_status->flag |= RX_FLAG_AMPDU_DETAILS; |
| @@ -1766,7 +1807,7 @@ void iwl_mvm_rx_monitor_ndp(struct iwl_mvm *mvm, struct napi_struct *napi, | |||
| 1766 | rx_status->rate_idx = rate; | 1807 | rx_status->rate_idx = rate; |
| 1767 | } | 1808 | } |
| 1768 | 1809 | ||
| 1769 | iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb, queue, sta, false); | 1810 | ieee80211_rx_napi(mvm->hw, sta, skb, napi); |
| 1770 | out: | 1811 | out: |
| 1771 | rcu_read_unlock(); | 1812 | rcu_read_unlock(); |
| 1772 | } | 1813 | } |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c index 86d598d5b68f..78694bc38e76 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
| 10 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH | 10 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH |
| 11 | * Copyright(c) 2018 Intel Corporation | 11 | * Copyright(c) 2018 - 2019 Intel Corporation |
| 12 | * | 12 | * |
| 13 | * This program is free software; you can redistribute it and/or modify | 13 | * This program is free software; you can redistribute it and/or modify |
| 14 | * it under the terms of version 2 of the GNU General Public License as | 14 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -31,7 +31,7 @@ | |||
| 31 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. | 31 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 32 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 32 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
| 33 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH | 33 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH |
| 34 | * Copyright(c) 2018 Intel Corporation | 34 | * Copyright(c) 2018 - 2019 Intel Corporation |
| 35 | * All rights reserved. | 35 | * All rights reserved. |
| 36 | * | 36 | * |
| 37 | * Redistribution and use in source and binary forms, with or without | 37 | * Redistribution and use in source and binary forms, with or without |
| @@ -1580,6 +1580,11 @@ static int iwl_mvm_check_running_scans(struct iwl_mvm *mvm, int type) | |||
| 1580 | * scheduled scan before starting a normal scan. | 1580 | * scheduled scan before starting a normal scan. |
| 1581 | */ | 1581 | */ |
| 1582 | 1582 | ||
| 1583 | /* FW supports only a single periodic scan */ | ||
| 1584 | if ((type == IWL_MVM_SCAN_SCHED || type == IWL_MVM_SCAN_NETDETECT) && | ||
| 1585 | mvm->scan_status & (IWL_MVM_SCAN_SCHED | IWL_MVM_SCAN_NETDETECT)) | ||
| 1586 | return -EBUSY; | ||
| 1587 | |||
| 1583 | if (iwl_mvm_num_scans(mvm) < mvm->max_scans) | 1588 | if (iwl_mvm_num_scans(mvm) < mvm->max_scans) |
| 1584 | return 0; | 1589 | return 0; |
| 1585 | 1590 | ||
| @@ -1616,10 +1621,10 @@ static int iwl_mvm_check_running_scans(struct iwl_mvm *mvm, int type) | |||
| 1616 | if (mvm->scan_status & IWL_MVM_SCAN_SCHED_MASK) | 1621 | if (mvm->scan_status & IWL_MVM_SCAN_SCHED_MASK) |
| 1617 | return iwl_mvm_scan_stop(mvm, IWL_MVM_SCAN_SCHED, | 1622 | return iwl_mvm_scan_stop(mvm, IWL_MVM_SCAN_SCHED, |
| 1618 | true); | 1623 | true); |
| 1619 | 1624 | /* Something is wrong if no scan was running but we | |
| 1620 | /* fall through, something is wrong if no scan was | 1625 | * ran out of scans. |
| 1621 | * running but we ran out of scans. | ||
| 1622 | */ | 1626 | */ |
| 1627 | /* fall through */ | ||
| 1623 | default: | 1628 | default: |
| 1624 | WARN_ON(1); | 1629 | WARN_ON(1); |
| 1625 | break; | 1630 | break; |
| @@ -1976,9 +1981,8 @@ static int iwl_mvm_scan_stop_wait(struct iwl_mvm *mvm, int type) | |||
| 1976 | return ret; | 1981 | return ret; |
| 1977 | } | 1982 | } |
| 1978 | 1983 | ||
| 1979 | ret = iwl_wait_notification(&mvm->notif_wait, &wait_scan_done, 1 * HZ); | 1984 | return iwl_wait_notification(&mvm->notif_wait, &wait_scan_done, |
| 1980 | 1985 | 1 * HZ); | |
| 1981 | return ret; | ||
| 1982 | } | 1986 | } |
| 1983 | 1987 | ||
| 1984 | int iwl_mvm_scan_size(struct iwl_mvm *mvm) | 1988 | int iwl_mvm_scan_size(struct iwl_mvm *mvm) |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index c5a01470a3bc..498c315291cf 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c | |||
| @@ -314,7 +314,6 @@ static int iwl_mvm_invalidate_sta_queue(struct iwl_mvm *mvm, int queue, | |||
| 314 | struct iwl_mvm_sta *mvmsta; | 314 | struct iwl_mvm_sta *mvmsta; |
| 315 | u32 status; | 315 | u32 status; |
| 316 | u8 sta_id; | 316 | u8 sta_id; |
| 317 | int ret; | ||
| 318 | 317 | ||
| 319 | if (WARN_ON(iwl_mvm_has_new_tx_api(mvm))) | 318 | if (WARN_ON(iwl_mvm_has_new_tx_api(mvm))) |
| 320 | return -EINVAL; | 319 | return -EINVAL; |
| @@ -349,11 +348,9 @@ static int iwl_mvm_invalidate_sta_queue(struct iwl_mvm *mvm, int queue, | |||
| 349 | 348 | ||
| 350 | /* Notify FW of queue removal from the STA queues */ | 349 | /* Notify FW of queue removal from the STA queues */ |
| 351 | status = ADD_STA_SUCCESS; | 350 | status = ADD_STA_SUCCESS; |
| 352 | ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, | 351 | return iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, |
| 353 | iwl_mvm_add_sta_cmd_size(mvm), | 352 | iwl_mvm_add_sta_cmd_size(mvm), |
| 354 | &cmd, &status); | 353 | &cmd, &status); |
| 355 | |||
| 356 | return ret; | ||
| 357 | } | 354 | } |
| 358 | 355 | ||
| 359 | static int iwl_mvm_disable_txq(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | 356 | static int iwl_mvm_disable_txq(struct iwl_mvm *mvm, struct ieee80211_sta *sta, |
| @@ -753,7 +750,8 @@ static int iwl_mvm_tvqm_enable_txq(struct iwl_mvm *mvm, | |||
| 753 | 750 | ||
| 754 | if (tid == IWL_MAX_TID_COUNT) { | 751 | if (tid == IWL_MAX_TID_COUNT) { |
| 755 | tid = IWL_MGMT_TID; | 752 | tid = IWL_MGMT_TID; |
| 756 | size = IWL_MGMT_QUEUE_SIZE; | 753 | size = max_t(u32, IWL_MGMT_QUEUE_SIZE, |
| 754 | mvm->trans->cfg->min_txq_size); | ||
| 757 | } | 755 | } |
| 758 | queue = iwl_trans_txq_alloc(mvm->trans, | 756 | queue = iwl_trans_txq_alloc(mvm->trans, |
| 759 | cpu_to_le16(TX_QUEUE_CFG_ENABLE_QUEUE), | 757 | cpu_to_le16(TX_QUEUE_CFG_ENABLE_QUEUE), |
| @@ -794,11 +792,9 @@ static int iwl_mvm_sta_alloc_queue_tvqm(struct iwl_mvm *mvm, | |||
| 794 | if (queue < 0) | 792 | if (queue < 0) |
| 795 | return queue; | 793 | return queue; |
| 796 | 794 | ||
| 797 | if (sta) { | 795 | mvmtxq->txq_id = queue; |
| 798 | mvmtxq->txq_id = queue; | 796 | mvm->tvqm_info[queue].txq_tid = tid; |
| 799 | mvm->tvqm_info[queue].txq_tid = tid; | 797 | mvm->tvqm_info[queue].sta_id = mvmsta->sta_id; |
| 800 | mvm->tvqm_info[queue].sta_id = mvmsta->sta_id; | ||
| 801 | } | ||
| 802 | 798 | ||
| 803 | IWL_DEBUG_TX_QUEUES(mvm, "Allocated queue is %d\n", queue); | 799 | IWL_DEBUG_TX_QUEUES(mvm, "Allocated queue is %d\n", queue); |
| 804 | 800 | ||
| @@ -2340,11 +2336,13 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
| 2340 | if (mvmvif->ap_wep_key) { | 2336 | if (mvmvif->ap_wep_key) { |
| 2341 | u8 key_offset = iwl_mvm_set_fw_key_idx(mvm); | 2337 | u8 key_offset = iwl_mvm_set_fw_key_idx(mvm); |
| 2342 | 2338 | ||
| 2339 | __set_bit(key_offset, mvm->fw_key_table); | ||
| 2340 | |||
| 2343 | if (key_offset == STA_KEY_IDX_INVALID) | 2341 | if (key_offset == STA_KEY_IDX_INVALID) |
| 2344 | return -ENOSPC; | 2342 | return -ENOSPC; |
| 2345 | 2343 | ||
| 2346 | ret = iwl_mvm_send_sta_key(mvm, mvmvif->mcast_sta.sta_id, | 2344 | ret = iwl_mvm_send_sta_key(mvm, mvmvif->mcast_sta.sta_id, |
| 2347 | mvmvif->ap_wep_key, 1, 0, NULL, 0, | 2345 | mvmvif->ap_wep_key, true, 0, NULL, 0, |
| 2348 | key_offset, 0); | 2346 | key_offset, 0); |
| 2349 | if (ret) | 2347 | if (ret) |
| 2350 | return ret; | 2348 | return ret; |
| @@ -2353,6 +2351,59 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
| 2353 | return 0; | 2351 | return 0; |
| 2354 | } | 2352 | } |
| 2355 | 2353 | ||
| 2354 | static int __iwl_mvm_remove_sta_key(struct iwl_mvm *mvm, u8 sta_id, | ||
| 2355 | struct ieee80211_key_conf *keyconf, | ||
| 2356 | bool mcast) | ||
| 2357 | { | ||
| 2358 | union { | ||
| 2359 | struct iwl_mvm_add_sta_key_cmd_v1 cmd_v1; | ||
| 2360 | struct iwl_mvm_add_sta_key_cmd cmd; | ||
| 2361 | } u = {}; | ||
| 2362 | bool new_api = fw_has_api(&mvm->fw->ucode_capa, | ||
| 2363 | IWL_UCODE_TLV_API_TKIP_MIC_KEYS); | ||
| 2364 | __le16 key_flags; | ||
| 2365 | int ret, size; | ||
| 2366 | u32 status; | ||
| 2367 | |||
| 2368 | /* This is a valid situation for GTK removal */ | ||
| 2369 | if (sta_id == IWL_MVM_INVALID_STA) | ||
| 2370 | return 0; | ||
| 2371 | |||
| 2372 | key_flags = cpu_to_le16((keyconf->keyidx << STA_KEY_FLG_KEYID_POS) & | ||
| 2373 | STA_KEY_FLG_KEYID_MSK); | ||
| 2374 | key_flags |= cpu_to_le16(STA_KEY_FLG_NO_ENC | STA_KEY_FLG_WEP_KEY_MAP); | ||
| 2375 | key_flags |= cpu_to_le16(STA_KEY_NOT_VALID); | ||
| 2376 | |||
| 2377 | if (mcast) | ||
| 2378 | key_flags |= cpu_to_le16(STA_KEY_MULTICAST); | ||
| 2379 | |||
| 2380 | /* | ||
| 2381 | * The fields assigned here are in the same location at the start | ||
| 2382 | * of the command, so we can do this union trick. | ||
| 2383 | */ | ||
| 2384 | u.cmd.common.key_flags = key_flags; | ||
| 2385 | u.cmd.common.key_offset = keyconf->hw_key_idx; | ||
| 2386 | u.cmd.common.sta_id = sta_id; | ||
| 2387 | |||
| 2388 | size = new_api ? sizeof(u.cmd) : sizeof(u.cmd_v1); | ||
| 2389 | |||
| 2390 | status = ADD_STA_SUCCESS; | ||
| 2391 | ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA_KEY, size, &u.cmd, | ||
| 2392 | &status); | ||
| 2393 | |||
| 2394 | switch (status) { | ||
| 2395 | case ADD_STA_SUCCESS: | ||
| 2396 | IWL_DEBUG_WEP(mvm, "MODIFY_STA: remove sta key passed\n"); | ||
| 2397 | break; | ||
| 2398 | default: | ||
| 2399 | ret = -EIO; | ||
| 2400 | IWL_ERR(mvm, "MODIFY_STA: remove sta key failed\n"); | ||
| 2401 | break; | ||
| 2402 | } | ||
| 2403 | |||
| 2404 | return ret; | ||
| 2405 | } | ||
| 2406 | |||
| 2356 | /* | 2407 | /* |
| 2357 | * Send the FW a request to remove the station from it's internal data | 2408 | * Send the FW a request to remove the station from it's internal data |
| 2358 | * structures, and in addition remove it from the local data structure. | 2409 | * structures, and in addition remove it from the local data structure. |
| @@ -2368,6 +2419,28 @@ int iwl_mvm_rm_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
| 2368 | 2419 | ||
| 2369 | iwl_mvm_disable_txq(mvm, NULL, mvmvif->cab_queue, 0, 0); | 2420 | iwl_mvm_disable_txq(mvm, NULL, mvmvif->cab_queue, 0, 0); |
| 2370 | 2421 | ||
| 2422 | if (mvmvif->ap_wep_key) { | ||
| 2423 | int i; | ||
| 2424 | |||
| 2425 | if (!__test_and_clear_bit(mvmvif->ap_wep_key->hw_key_idx, | ||
| 2426 | mvm->fw_key_table)) { | ||
| 2427 | IWL_ERR(mvm, "offset %d not used in fw key table.\n", | ||
| 2428 | mvmvif->ap_wep_key->hw_key_idx); | ||
| 2429 | return -ENOENT; | ||
| 2430 | } | ||
| 2431 | |||
| 2432 | /* track which key was deleted last */ | ||
| 2433 | for (i = 0; i < STA_KEY_MAX_NUM; i++) { | ||
| 2434 | if (mvm->fw_key_deleted[i] < U8_MAX) | ||
| 2435 | mvm->fw_key_deleted[i]++; | ||
| 2436 | } | ||
| 2437 | mvm->fw_key_deleted[mvmvif->ap_wep_key->hw_key_idx] = 0; | ||
| 2438 | ret = __iwl_mvm_remove_sta_key(mvm, mvmvif->mcast_sta.sta_id, | ||
| 2439 | mvmvif->ap_wep_key, true); | ||
| 2440 | if (ret) | ||
| 2441 | return ret; | ||
| 2442 | } | ||
| 2443 | |||
| 2371 | ret = iwl_mvm_rm_sta_common(mvm, mvmvif->mcast_sta.sta_id); | 2444 | ret = iwl_mvm_rm_sta_common(mvm, mvmvif->mcast_sta.sta_id); |
| 2372 | if (ret) | 2445 | if (ret) |
| 2373 | IWL_WARN(mvm, "Failed sending remove station\n"); | 2446 | IWL_WARN(mvm, "Failed sending remove station\n"); |
| @@ -3399,59 +3472,6 @@ static int __iwl_mvm_set_sta_key(struct iwl_mvm *mvm, | |||
| 3399 | return ret; | 3472 | return ret; |
| 3400 | } | 3473 | } |
| 3401 | 3474 | ||
| 3402 | static int __iwl_mvm_remove_sta_key(struct iwl_mvm *mvm, u8 sta_id, | ||
| 3403 | struct ieee80211_key_conf *keyconf, | ||
| 3404 | bool mcast) | ||
| 3405 | { | ||
| 3406 | union { | ||
| 3407 | struct iwl_mvm_add_sta_key_cmd_v1 cmd_v1; | ||
| 3408 | struct iwl_mvm_add_sta_key_cmd cmd; | ||
| 3409 | } u = {}; | ||
| 3410 | bool new_api = fw_has_api(&mvm->fw->ucode_capa, | ||
| 3411 | IWL_UCODE_TLV_API_TKIP_MIC_KEYS); | ||
| 3412 | __le16 key_flags; | ||
| 3413 | int ret, size; | ||
| 3414 | u32 status; | ||
| 3415 | |||
| 3416 | /* This is a valid situation for GTK removal */ | ||
| 3417 | if (sta_id == IWL_MVM_INVALID_STA) | ||
| 3418 | return 0; | ||
| 3419 | |||
| 3420 | key_flags = cpu_to_le16((keyconf->keyidx << STA_KEY_FLG_KEYID_POS) & | ||
| 3421 | STA_KEY_FLG_KEYID_MSK); | ||
| 3422 | key_flags |= cpu_to_le16(STA_KEY_FLG_NO_ENC | STA_KEY_FLG_WEP_KEY_MAP); | ||
| 3423 | key_flags |= cpu_to_le16(STA_KEY_NOT_VALID); | ||
| 3424 | |||
| 3425 | if (mcast) | ||
| 3426 | key_flags |= cpu_to_le16(STA_KEY_MULTICAST); | ||
| 3427 | |||
| 3428 | /* | ||
| 3429 | * The fields assigned here are in the same location at the start | ||
| 3430 | * of the command, so we can do this union trick. | ||
| 3431 | */ | ||
| 3432 | u.cmd.common.key_flags = key_flags; | ||
| 3433 | u.cmd.common.key_offset = keyconf->hw_key_idx; | ||
| 3434 | u.cmd.common.sta_id = sta_id; | ||
| 3435 | |||
| 3436 | size = new_api ? sizeof(u.cmd) : sizeof(u.cmd_v1); | ||
| 3437 | |||
| 3438 | status = ADD_STA_SUCCESS; | ||
| 3439 | ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA_KEY, size, &u.cmd, | ||
| 3440 | &status); | ||
| 3441 | |||
| 3442 | switch (status) { | ||
| 3443 | case ADD_STA_SUCCESS: | ||
| 3444 | IWL_DEBUG_WEP(mvm, "MODIFY_STA: remove sta key passed\n"); | ||
| 3445 | break; | ||
| 3446 | default: | ||
| 3447 | ret = -EIO; | ||
| 3448 | IWL_ERR(mvm, "MODIFY_STA: remove sta key failed\n"); | ||
| 3449 | break; | ||
| 3450 | } | ||
| 3451 | |||
| 3452 | return ret; | ||
| 3453 | } | ||
| 3454 | |||
| 3455 | int iwl_mvm_set_sta_key(struct iwl_mvm *mvm, | 3475 | int iwl_mvm_set_sta_key(struct iwl_mvm *mvm, |
| 3456 | struct ieee80211_vif *vif, | 3476 | struct ieee80211_vif *vif, |
| 3457 | struct ieee80211_sta *sta, | 3477 | struct ieee80211_sta *sta, |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h index 0614296244b3..79700c7310a1 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h | |||
| @@ -394,6 +394,7 @@ struct iwl_mvm_rxq_dup_data { | |||
| 394 | * the BA window. To be used for UAPSD only. | 394 | * the BA window. To be used for UAPSD only. |
| 395 | * @ptk_pn: per-queue PTK PN data structures | 395 | * @ptk_pn: per-queue PTK PN data structures |
| 396 | * @dup_data: per queue duplicate packet detection data | 396 | * @dup_data: per queue duplicate packet detection data |
| 397 | * @wep_key: used in AP mode. Is a duplicate of the WEP key. | ||
| 397 | * @deferred_traffic_tid_map: indication bitmap of deferred traffic per-TID | 398 | * @deferred_traffic_tid_map: indication bitmap of deferred traffic per-TID |
| 398 | * @tx_ant: the index of the antenna to use for data tx to this station. Only | 399 | * @tx_ant: the index of the antenna to use for data tx to this station. Only |
| 399 | * used during connection establishment (e.g. for the 4 way handshake | 400 | * used during connection establishment (e.g. for the 4 way handshake |
| @@ -425,6 +426,8 @@ struct iwl_mvm_sta { | |||
| 425 | struct iwl_mvm_key_pn __rcu *ptk_pn[4]; | 426 | struct iwl_mvm_key_pn __rcu *ptk_pn[4]; |
| 426 | struct iwl_mvm_rxq_dup_data *dup_data; | 427 | struct iwl_mvm_rxq_dup_data *dup_data; |
| 427 | 428 | ||
| 429 | struct ieee80211_key_conf *wep_key; | ||
| 430 | |||
| 428 | u8 reserved_queue; | 431 | u8 reserved_queue; |
| 429 | 432 | ||
| 430 | /* Temporary, until the new TLC will control the Tx protection */ | 433 | /* Temporary, until the new TLC will control the Tx protection */ |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c index 5b34100e9099..9693fa4cdc39 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c | |||
| @@ -85,7 +85,7 @@ void iwl_mvm_te_clear_data(struct iwl_mvm *mvm, | |||
| 85 | { | 85 | { |
| 86 | lockdep_assert_held(&mvm->time_event_lock); | 86 | lockdep_assert_held(&mvm->time_event_lock); |
| 87 | 87 | ||
| 88 | if (!te_data->vif) | 88 | if (!te_data || !te_data->vif) |
| 89 | return; | 89 | return; |
| 90 | 90 | ||
| 91 | list_del(&te_data->list); | 91 | list_del(&te_data->list); |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c index ac62eb8c4b36..0c2aabc842f9 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
| 10 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH | 10 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH |
| 11 | * Copyright(c) 2018 Intel Corporation | 11 | * Copyright(c) 2018 - 2019 Intel Corporation |
| 12 | * | 12 | * |
| 13 | * This program is free software; you can redistribute it and/or modify | 13 | * This program is free software; you can redistribute it and/or modify |
| 14 | * it under the terms of version 2 of the GNU General Public License as | 14 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -31,7 +31,7 @@ | |||
| 31 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. | 31 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 32 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 32 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
| 33 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH | 33 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH |
| 34 | * Copyright(c) 2018 Intel Corporation | 34 | * Copyright(c) 2018 - 2019 Intel Corporation |
| 35 | * All rights reserved. | 35 | * All rights reserved. |
| 36 | * | 36 | * |
| 37 | * Redistribution and use in source and binary forms, with or without | 37 | * Redistribution and use in source and binary forms, with or without |
| @@ -209,7 +209,9 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb, | |||
| 209 | u16 offload_assist = 0; | 209 | u16 offload_assist = 0; |
| 210 | u8 ac; | 210 | u8 ac; |
| 211 | 211 | ||
| 212 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) | 212 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) || |
| 213 | (ieee80211_is_probe_resp(fc) && | ||
| 214 | !is_multicast_ether_addr(hdr->addr1))) | ||
| 213 | tx_flags |= TX_CMD_FLG_ACK; | 215 | tx_flags |= TX_CMD_FLG_ACK; |
| 214 | else | 216 | else |
| 215 | tx_flags &= ~TX_CMD_FLG_ACK; | 217 | tx_flags &= ~TX_CMD_FLG_ACK; |
| @@ -278,7 +280,7 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb, | |||
| 278 | } | 280 | } |
| 279 | 281 | ||
| 280 | if (ieee80211_is_data(fc) && len > mvm->rts_threshold && | 282 | if (ieee80211_is_data(fc) && len > mvm->rts_threshold && |
| 281 | !is_multicast_ether_addr(ieee80211_get_DA(hdr))) | 283 | !is_multicast_ether_addr(hdr->addr1)) |
| 282 | tx_flags |= TX_CMD_FLG_PROT_REQUIRE; | 284 | tx_flags |= TX_CMD_FLG_PROT_REQUIRE; |
| 283 | 285 | ||
| 284 | if (fw_has_capa(&mvm->fw->ucode_capa, | 286 | if (fw_has_capa(&mvm->fw->ucode_capa, |
| @@ -719,6 +721,9 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb) | |||
| 719 | IEEE80211_TX_CTL_TX_OFFCHAN; | 721 | IEEE80211_TX_CTL_TX_OFFCHAN; |
| 720 | int queue = -1; | 722 | int queue = -1; |
| 721 | 723 | ||
| 724 | if (IWL_MVM_NON_TRANSMITTING_AP && ieee80211_is_probe_resp(fc)) | ||
| 725 | return -1; | ||
| 726 | |||
| 722 | memcpy(&info, skb->cb, sizeof(info)); | 727 | memcpy(&info, skb->cb, sizeof(info)); |
| 723 | 728 | ||
| 724 | if (WARN_ON_ONCE(info.flags & IEEE80211_TX_CTL_AMPDU)) | 729 | if (WARN_ON_ONCE(info.flags & IEEE80211_TX_CTL_AMPDU)) |
| @@ -1078,6 +1083,9 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb, | |||
| 1078 | fc = hdr->frame_control; | 1083 | fc = hdr->frame_control; |
| 1079 | hdrlen = ieee80211_hdrlen(fc); | 1084 | hdrlen = ieee80211_hdrlen(fc); |
| 1080 | 1085 | ||
| 1086 | if (IWL_MVM_NON_TRANSMITTING_AP && ieee80211_is_probe_resp(fc)) | ||
| 1087 | return -1; | ||
| 1088 | |||
| 1081 | if (WARN_ON_ONCE(!mvmsta)) | 1089 | if (WARN_ON_ONCE(!mvmsta)) |
| 1082 | return -1; | 1090 | return -1; |
| 1083 | 1091 | ||
| @@ -1107,12 +1115,14 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb, | |||
| 1107 | */ | 1115 | */ |
| 1108 | if (ieee80211_is_data_qos(fc) && !ieee80211_is_qos_nullfunc(fc)) { | 1116 | if (ieee80211_is_data_qos(fc) && !ieee80211_is_qos_nullfunc(fc)) { |
| 1109 | tid = ieee80211_get_tid(hdr); | 1117 | tid = ieee80211_get_tid(hdr); |
| 1110 | if (WARN_ON_ONCE(tid >= IWL_MAX_TID_COUNT)) | 1118 | if (WARN_ONCE(tid >= IWL_MAX_TID_COUNT, "Invalid TID %d", tid)) |
| 1111 | goto drop_unlock_sta; | 1119 | goto drop_unlock_sta; |
| 1112 | 1120 | ||
| 1113 | is_ampdu = info->flags & IEEE80211_TX_CTL_AMPDU; | 1121 | is_ampdu = info->flags & IEEE80211_TX_CTL_AMPDU; |
| 1114 | if (WARN_ON_ONCE(is_ampdu && | 1122 | if (WARN_ONCE(is_ampdu && |
| 1115 | mvmsta->tid_data[tid].state != IWL_AGG_ON)) | 1123 | mvmsta->tid_data[tid].state != IWL_AGG_ON, |
| 1124 | "Invalid internal agg state %d for TID %d", | ||
| 1125 | mvmsta->tid_data[tid].state, tid)) | ||
| 1116 | goto drop_unlock_sta; | 1126 | goto drop_unlock_sta; |
| 1117 | 1127 | ||
| 1118 | seq_number = mvmsta->tid_data[tid].seq_number; | 1128 | seq_number = mvmsta->tid_data[tid].seq_number; |
| @@ -1134,7 +1144,7 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb, | |||
| 1134 | 1144 | ||
| 1135 | WARN_ON_ONCE(info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM); | 1145 | WARN_ON_ONCE(info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM); |
| 1136 | 1146 | ||
| 1137 | if (WARN_ON_ONCE(txq_id == IWL_MVM_INVALID_QUEUE)) { | 1147 | if (WARN_ONCE(txq_id == IWL_MVM_INVALID_QUEUE, "Invalid TXQ id")) { |
| 1138 | iwl_trans_free_tx_cmd(mvm->trans, dev_cmd); | 1148 | iwl_trans_free_tx_cmd(mvm->trans, dev_cmd); |
| 1139 | spin_unlock(&mvmsta->lock); | 1149 | spin_unlock(&mvmsta->lock); |
| 1140 | return 0; | 1150 | return 0; |
| @@ -1184,6 +1194,7 @@ drop_unlock_sta: | |||
| 1184 | iwl_trans_free_tx_cmd(mvm->trans, dev_cmd); | 1194 | iwl_trans_free_tx_cmd(mvm->trans, dev_cmd); |
| 1185 | spin_unlock(&mvmsta->lock); | 1195 | spin_unlock(&mvmsta->lock); |
| 1186 | drop: | 1196 | drop: |
| 1197 | IWL_DEBUG_TX(mvm, "TX to [%d|%d] dropped\n", mvmsta->sta_id, tid); | ||
| 1187 | return -1; | 1198 | return -1; |
| 1188 | } | 1199 | } |
| 1189 | 1200 | ||
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c index 211c4638d690..4649327abb45 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c | |||
| @@ -294,6 +294,7 @@ static const struct { | |||
| 294 | { "SYSASSERT", 0x35 }, | 294 | { "SYSASSERT", 0x35 }, |
| 295 | { "UCODE_VERSION_MISMATCH", 0x37 }, | 295 | { "UCODE_VERSION_MISMATCH", 0x37 }, |
| 296 | { "BAD_COMMAND", 0x38 }, | 296 | { "BAD_COMMAND", 0x38 }, |
| 297 | { "BAD_COMMAND", 0x39 }, | ||
| 297 | { "NMI_INTERRUPT_DATA_ACTION_PT", 0x3C }, | 298 | { "NMI_INTERRUPT_DATA_ACTION_PT", 0x3C }, |
| 298 | { "FATAL_ERROR", 0x3D }, | 299 | { "FATAL_ERROR", 0x3D }, |
| 299 | { "NMI_TRM_HW_ERR", 0x46 }, | 300 | { "NMI_TRM_HW_ERR", 0x46 }, |
| @@ -456,12 +457,14 @@ static void iwl_mvm_dump_umac_error_log(struct iwl_mvm *mvm) | |||
| 456 | { | 457 | { |
| 457 | struct iwl_trans *trans = mvm->trans; | 458 | struct iwl_trans *trans = mvm->trans; |
| 458 | struct iwl_umac_error_event_table table; | 459 | struct iwl_umac_error_event_table table; |
| 460 | u32 base = mvm->trans->umac_error_event_table; | ||
| 459 | 461 | ||
| 460 | if (!mvm->support_umac_log) | 462 | if (!mvm->support_umac_log && |
| 463 | !(mvm->trans->error_event_table_tlv_status & | ||
| 464 | IWL_ERROR_EVENT_TABLE_UMAC)) | ||
| 461 | return; | 465 | return; |
| 462 | 466 | ||
| 463 | iwl_trans_read_mem_bytes(trans, mvm->umac_error_event_table, &table, | 467 | iwl_trans_read_mem_bytes(trans, base, &table, sizeof(table)); |
| 464 | sizeof(table)); | ||
| 465 | 468 | ||
| 466 | if (table.valid) | 469 | if (table.valid) |
| 467 | mvm->fwrt.dump.umac_err_id = table.error_id; | 470 | mvm->fwrt.dump.umac_err_id = table.error_id; |
| @@ -493,7 +496,7 @@ static void iwl_mvm_dump_lmac_error_log(struct iwl_mvm *mvm, u8 lmac_num) | |||
| 493 | { | 496 | { |
| 494 | struct iwl_trans *trans = mvm->trans; | 497 | struct iwl_trans *trans = mvm->trans; |
| 495 | struct iwl_error_event_table table; | 498 | struct iwl_error_event_table table; |
| 496 | u32 val, base = mvm->error_event_table[lmac_num]; | 499 | u32 val, base = mvm->trans->lmac_error_event_table[lmac_num]; |
| 497 | 500 | ||
| 498 | if (mvm->fwrt.cur_fw_img == IWL_UCODE_INIT) { | 501 | if (mvm->fwrt.cur_fw_img == IWL_UCODE_INIT) { |
| 499 | if (!base) | 502 | if (!base) |
| @@ -522,23 +525,9 @@ static void iwl_mvm_dump_lmac_error_log(struct iwl_mvm *mvm, u8 lmac_num) | |||
| 522 | /* reset the device */ | 525 | /* reset the device */ |
| 523 | iwl_trans_sw_reset(trans); | 526 | iwl_trans_sw_reset(trans); |
| 524 | 527 | ||
| 525 | /* set INIT_DONE flag */ | 528 | err = iwl_finish_nic_init(trans); |
| 526 | iwl_set_bit(trans, CSR_GP_CNTRL, | 529 | if (err) |
| 527 | BIT(trans->cfg->csr->flag_init_done)); | ||
| 528 | |||
| 529 | /* and wait for clock stabilization */ | ||
| 530 | if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) | ||
| 531 | udelay(2); | ||
| 532 | |||
| 533 | err = iwl_poll_bit(trans, CSR_GP_CNTRL, | ||
| 534 | BIT(trans->cfg->csr->flag_mac_clock_ready), | ||
| 535 | BIT(trans->cfg->csr->flag_mac_clock_ready), | ||
| 536 | 25000); | ||
| 537 | if (err < 0) { | ||
| 538 | IWL_DEBUG_INFO(trans, | ||
| 539 | "Failed to reset the card for the dump\n"); | ||
| 540 | return; | 530 | return; |
| 541 | } | ||
| 542 | } | 531 | } |
| 543 | 532 | ||
| 544 | iwl_trans_read_mem_bytes(trans, base, &table, sizeof(table)); | 533 | iwl_trans_read_mem_bytes(trans, base, &table, sizeof(table)); |
| @@ -603,7 +592,7 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm) | |||
| 603 | 592 | ||
| 604 | iwl_mvm_dump_lmac_error_log(mvm, 0); | 593 | iwl_mvm_dump_lmac_error_log(mvm, 0); |
| 605 | 594 | ||
| 606 | if (mvm->error_event_table[1]) | 595 | if (mvm->trans->lmac_error_event_table[1]) |
| 607 | iwl_mvm_dump_lmac_error_log(mvm, 1); | 596 | iwl_mvm_dump_lmac_error_log(mvm, 1); |
| 608 | 597 | ||
| 609 | iwl_mvm_dump_umac_error_log(mvm); | 598 | iwl_mvm_dump_umac_error_log(mvm); |
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c index ceb3aa03d561..1e36459948db 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2018 Intel Corporation | 8 | * Copyright(c) 2018 - 2019 Intel Corporation |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -18,7 +18,7 @@ | |||
| 18 | * | 18 | * |
| 19 | * BSD LICENSE | 19 | * BSD LICENSE |
| 20 | * | 20 | * |
| 21 | * Copyright(c) 2018 Intel Corporation | 21 | * Copyright(c) 2018 - 2019 Intel Corporation |
| 22 | * All rights reserved. | 22 | * All rights reserved. |
| 23 | * | 23 | * |
| 24 | * Redistribution and use in source and binary forms, with or without | 24 | * Redistribution and use in source and binary forms, with or without |
| @@ -66,6 +66,7 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans, | |||
| 66 | void *iml_img; | 66 | void *iml_img; |
| 67 | u32 control_flags = 0; | 67 | u32 control_flags = 0; |
| 68 | int ret; | 68 | int ret; |
| 69 | int cmdq_size = max_t(u32, TFD_CMD_SLOTS, trans->cfg->min_txq_size); | ||
| 69 | 70 | ||
| 70 | /* Allocate prph scratch */ | 71 | /* Allocate prph scratch */ |
| 71 | prph_scratch = dma_alloc_coherent(trans->dev, sizeof(*prph_scratch), | 72 | prph_scratch = dma_alloc_coherent(trans->dev, sizeof(*prph_scratch), |
| @@ -151,7 +152,7 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans, | |||
| 151 | ctxt_info_gen3->mcr_base_addr = | 152 | ctxt_info_gen3->mcr_base_addr = |
| 152 | cpu_to_le64(trans_pcie->rxq->used_bd_dma); | 153 | cpu_to_le64(trans_pcie->rxq->used_bd_dma); |
| 153 | ctxt_info_gen3->mtr_size = | 154 | ctxt_info_gen3->mtr_size = |
| 154 | cpu_to_le16(TFD_QUEUE_CB_SIZE(TFD_CMD_SLOTS)); | 155 | cpu_to_le16(TFD_QUEUE_CB_SIZE(cmdq_size)); |
| 155 | ctxt_info_gen3->mcr_size = | 156 | ctxt_info_gen3->mcr_size = |
| 156 | cpu_to_le16(RX_QUEUE_CB_SIZE(MQ_RX_TABLE_SIZE)); | 157 | cpu_to_le16(RX_QUEUE_CB_SIZE(MQ_RX_TABLE_SIZE)); |
| 157 | 158 | ||
| @@ -175,8 +176,13 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans, | |||
| 175 | iwl_write64(trans, CSR_IML_DATA_ADDR, | 176 | iwl_write64(trans, CSR_IML_DATA_ADDR, |
| 176 | trans_pcie->iml_dma_addr); | 177 | trans_pcie->iml_dma_addr); |
| 177 | iwl_write32(trans, CSR_IML_SIZE_ADDR, trans->iml_len); | 178 | iwl_write32(trans, CSR_IML_SIZE_ADDR, trans->iml_len); |
| 178 | iwl_set_bit(trans, CSR_CTXT_INFO_BOOT_CTRL, CSR_AUTO_FUNC_BOOT_ENA); | 179 | |
| 179 | iwl_set_bit(trans, CSR_GP_CNTRL, CSR_AUTO_FUNC_INIT); | 180 | iwl_set_bit(trans, CSR_CTXT_INFO_BOOT_CTRL, |
| 181 | CSR_AUTO_FUNC_BOOT_ENA); | ||
| 182 | if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_AX210) | ||
| 183 | iwl_write_umac_prph(trans, UREG_CPU_INIT_RUN, 1); | ||
| 184 | else | ||
| 185 | iwl_set_bit(trans, CSR_GP_CNTRL, CSR_AUTO_FUNC_INIT); | ||
| 180 | 186 | ||
| 181 | return 0; | 187 | return 0; |
| 182 | } | 188 | } |
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c index 7f4aaa810ea1..9274e317cc77 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c | |||
| @@ -59,8 +59,7 @@ | |||
| 59 | 59 | ||
| 60 | void iwl_pcie_ctxt_info_free_paging(struct iwl_trans *trans) | 60 | void iwl_pcie_ctxt_info_free_paging(struct iwl_trans *trans) |
| 61 | { | 61 | { |
| 62 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 62 | struct iwl_self_init_dram *dram = &trans->init_dram; |
| 63 | struct iwl_self_init_dram *dram = &trans_pcie->init_dram; | ||
| 64 | int i; | 63 | int i; |
| 65 | 64 | ||
| 66 | if (!dram->paging) { | 65 | if (!dram->paging) { |
| @@ -83,8 +82,7 @@ int iwl_pcie_init_fw_sec(struct iwl_trans *trans, | |||
| 83 | const struct fw_img *fw, | 82 | const struct fw_img *fw, |
| 84 | struct iwl_context_info_dram *ctxt_dram) | 83 | struct iwl_context_info_dram *ctxt_dram) |
| 85 | { | 84 | { |
| 86 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 85 | struct iwl_self_init_dram *dram = &trans->init_dram; |
| 87 | struct iwl_self_init_dram *dram = &trans_pcie->init_dram; | ||
| 88 | int i, ret, lmac_cnt, umac_cnt, paging_cnt; | 86 | int i, ret, lmac_cnt, umac_cnt, paging_cnt; |
| 89 | 87 | ||
| 90 | if (WARN(dram->paging, | 88 | if (WARN(dram->paging, |
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index a22e47639a4e..2b94e4cef56c 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. |
| 9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
| 10 | * Copyright(c) 2016-2017 Intel Deutschland GmbH | 10 | * Copyright(c) 2016-2017 Intel Deutschland GmbH |
| 11 | * Copyright(c) 2018 Intel Corporation | 11 | * Copyright(c) 2018 - 2019 Intel Corporation |
| 12 | * | 12 | * |
| 13 | * This program is free software; you can redistribute it and/or modify | 13 | * This program is free software; you can redistribute it and/or modify |
| 14 | * it under the terms of version 2 of the GNU General Public License as | 14 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -32,7 +32,7 @@ | |||
| 32 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 32 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
| 33 | * All rights reserved. | 33 | * All rights reserved. |
| 34 | * Copyright(c) 2017 Intel Deutschland GmbH | 34 | * Copyright(c) 2017 Intel Deutschland GmbH |
| 35 | * Copyright(c) 2018 Intel Corporation | 35 | * Copyright(c) 2018 - 2019 Intel Corporation |
| 36 | * | 36 | * |
| 37 | * Redistribution and use in source and binary forms, with or without | 37 | * Redistribution and use in source and binary forms, with or without |
| 38 | * modification, are permitted provided that the following conditions | 38 | * modification, are permitted provided that the following conditions |
| @@ -517,6 +517,8 @@ static const struct pci_device_id iwl_hw_card_ids[] = { | |||
| 517 | {IWL_PCI_DEVICE(0x02F0, 0x0034, iwl9560_2ac_cfg_soc)}, | 517 | {IWL_PCI_DEVICE(0x02F0, 0x0034, iwl9560_2ac_cfg_soc)}, |
| 518 | {IWL_PCI_DEVICE(0x02F0, 0x0038, iwl9560_2ac_160_cfg_soc)}, | 518 | {IWL_PCI_DEVICE(0x02F0, 0x0038, iwl9560_2ac_160_cfg_soc)}, |
| 519 | {IWL_PCI_DEVICE(0x02F0, 0x003C, iwl9560_2ac_160_cfg_soc)}, | 519 | {IWL_PCI_DEVICE(0x02F0, 0x003C, iwl9560_2ac_160_cfg_soc)}, |
| 520 | {IWL_PCI_DEVICE(0x02F0, 0x0040, iwl_ax101_cfg_qu_hr)}, | ||
| 521 | {IWL_PCI_DEVICE(0x02F0, 0x0044, iwl_ax101_cfg_qu_hr)}, | ||
| 520 | {IWL_PCI_DEVICE(0x02F0, 0x0060, iwl9461_2ac_cfg_soc)}, | 522 | {IWL_PCI_DEVICE(0x02F0, 0x0060, iwl9461_2ac_cfg_soc)}, |
| 521 | {IWL_PCI_DEVICE(0x02F0, 0x0064, iwl9461_2ac_cfg_soc)}, | 523 | {IWL_PCI_DEVICE(0x02F0, 0x0064, iwl9461_2ac_cfg_soc)}, |
| 522 | {IWL_PCI_DEVICE(0x02F0, 0x00A0, iwl9462_2ac_cfg_soc)}, | 524 | {IWL_PCI_DEVICE(0x02F0, 0x00A0, iwl9462_2ac_cfg_soc)}, |
| @@ -525,6 +527,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = { | |||
| 525 | {IWL_PCI_DEVICE(0x02F0, 0x0234, iwl9560_2ac_cfg_soc)}, | 527 | {IWL_PCI_DEVICE(0x02F0, 0x0234, iwl9560_2ac_cfg_soc)}, |
| 526 | {IWL_PCI_DEVICE(0x02F0, 0x0238, iwl9560_2ac_cfg_soc)}, | 528 | {IWL_PCI_DEVICE(0x02F0, 0x0238, iwl9560_2ac_cfg_soc)}, |
| 527 | {IWL_PCI_DEVICE(0x02F0, 0x023C, iwl9560_2ac_cfg_soc)}, | 529 | {IWL_PCI_DEVICE(0x02F0, 0x023C, iwl9560_2ac_cfg_soc)}, |
| 530 | {IWL_PCI_DEVICE(0x02F0, 0x0244, iwl_ax101_cfg_qu_hr)}, | ||
| 528 | {IWL_PCI_DEVICE(0x02F0, 0x0260, iwl9461_2ac_cfg_soc)}, | 531 | {IWL_PCI_DEVICE(0x02F0, 0x0260, iwl9461_2ac_cfg_soc)}, |
| 529 | {IWL_PCI_DEVICE(0x02F0, 0x0264, iwl9461_2ac_cfg_soc)}, | 532 | {IWL_PCI_DEVICE(0x02F0, 0x0264, iwl9461_2ac_cfg_soc)}, |
| 530 | {IWL_PCI_DEVICE(0x02F0, 0x02A0, iwl9462_2ac_cfg_soc)}, | 533 | {IWL_PCI_DEVICE(0x02F0, 0x02A0, iwl9462_2ac_cfg_soc)}, |
| @@ -542,6 +545,8 @@ static const struct pci_device_id iwl_hw_card_ids[] = { | |||
| 542 | {IWL_PCI_DEVICE(0x06F0, 0x0034, iwl9560_2ac_cfg_soc)}, | 545 | {IWL_PCI_DEVICE(0x06F0, 0x0034, iwl9560_2ac_cfg_soc)}, |
| 543 | {IWL_PCI_DEVICE(0x06F0, 0x0038, iwl9560_2ac_160_cfg_soc)}, | 546 | {IWL_PCI_DEVICE(0x06F0, 0x0038, iwl9560_2ac_160_cfg_soc)}, |
| 544 | {IWL_PCI_DEVICE(0x06F0, 0x003C, iwl9560_2ac_160_cfg_soc)}, | 547 | {IWL_PCI_DEVICE(0x06F0, 0x003C, iwl9560_2ac_160_cfg_soc)}, |
| 548 | {IWL_PCI_DEVICE(0x06F0, 0x0040, iwl_ax101_cfg_qu_hr)}, | ||
| 549 | {IWL_PCI_DEVICE(0x06F0, 0x0044, iwl_ax101_cfg_qu_hr)}, | ||
| 545 | {IWL_PCI_DEVICE(0x06F0, 0x0060, iwl9461_2ac_cfg_soc)}, | 550 | {IWL_PCI_DEVICE(0x06F0, 0x0060, iwl9461_2ac_cfg_soc)}, |
| 546 | {IWL_PCI_DEVICE(0x06F0, 0x0064, iwl9461_2ac_cfg_soc)}, | 551 | {IWL_PCI_DEVICE(0x06F0, 0x0064, iwl9461_2ac_cfg_soc)}, |
| 547 | {IWL_PCI_DEVICE(0x06F0, 0x00A0, iwl9462_2ac_cfg_soc)}, | 552 | {IWL_PCI_DEVICE(0x06F0, 0x00A0, iwl9462_2ac_cfg_soc)}, |
| @@ -550,6 +555,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = { | |||
| 550 | {IWL_PCI_DEVICE(0x06F0, 0x0234, iwl9560_2ac_cfg_soc)}, | 555 | {IWL_PCI_DEVICE(0x06F0, 0x0234, iwl9560_2ac_cfg_soc)}, |
| 551 | {IWL_PCI_DEVICE(0x06F0, 0x0238, iwl9560_2ac_cfg_soc)}, | 556 | {IWL_PCI_DEVICE(0x06F0, 0x0238, iwl9560_2ac_cfg_soc)}, |
| 552 | {IWL_PCI_DEVICE(0x06F0, 0x023C, iwl9560_2ac_cfg_soc)}, | 557 | {IWL_PCI_DEVICE(0x06F0, 0x023C, iwl9560_2ac_cfg_soc)}, |
| 558 | {IWL_PCI_DEVICE(0x06F0, 0x0244, iwl_ax101_cfg_qu_hr)}, | ||
| 553 | {IWL_PCI_DEVICE(0x06F0, 0x0260, iwl9461_2ac_cfg_soc)}, | 559 | {IWL_PCI_DEVICE(0x06F0, 0x0260, iwl9461_2ac_cfg_soc)}, |
| 554 | {IWL_PCI_DEVICE(0x06F0, 0x0264, iwl9461_2ac_cfg_soc)}, | 560 | {IWL_PCI_DEVICE(0x06F0, 0x0264, iwl9461_2ac_cfg_soc)}, |
| 555 | {IWL_PCI_DEVICE(0x06F0, 0x02A0, iwl9462_2ac_cfg_soc)}, | 561 | {IWL_PCI_DEVICE(0x06F0, 0x02A0, iwl9462_2ac_cfg_soc)}, |
| @@ -597,6 +603,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = { | |||
| 597 | {IWL_PCI_DEVICE(0x2526, 0x2030, iwl9560_2ac_160_cfg_soc)}, | 603 | {IWL_PCI_DEVICE(0x2526, 0x2030, iwl9560_2ac_160_cfg_soc)}, |
| 598 | {IWL_PCI_DEVICE(0x2526, 0x2034, iwl9560_2ac_160_cfg_soc)}, | 604 | {IWL_PCI_DEVICE(0x2526, 0x2034, iwl9560_2ac_160_cfg_soc)}, |
| 599 | {IWL_PCI_DEVICE(0x2526, 0x4010, iwl9260_2ac_160_cfg)}, | 605 | {IWL_PCI_DEVICE(0x2526, 0x4010, iwl9260_2ac_160_cfg)}, |
| 606 | {IWL_PCI_DEVICE(0x2526, 0x4018, iwl9260_2ac_160_cfg)}, | ||
| 600 | {IWL_PCI_DEVICE(0x2526, 0x401C, iwl9260_2ac_160_cfg)}, | 607 | {IWL_PCI_DEVICE(0x2526, 0x401C, iwl9260_2ac_160_cfg)}, |
| 601 | {IWL_PCI_DEVICE(0x2526, 0x4030, iwl9560_2ac_160_cfg)}, | 608 | {IWL_PCI_DEVICE(0x2526, 0x4030, iwl9560_2ac_160_cfg)}, |
| 602 | {IWL_PCI_DEVICE(0x2526, 0x4034, iwl9560_2ac_160_cfg_soc)}, | 609 | {IWL_PCI_DEVICE(0x2526, 0x4034, iwl9560_2ac_160_cfg_soc)}, |
| @@ -614,6 +621,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = { | |||
| 614 | {IWL_PCI_DEVICE(0x2720, 0x0034, iwl9560_2ac_160_cfg)}, | 621 | {IWL_PCI_DEVICE(0x2720, 0x0034, iwl9560_2ac_160_cfg)}, |
| 615 | {IWL_PCI_DEVICE(0x2720, 0x0038, iwl9560_2ac_160_cfg)}, | 622 | {IWL_PCI_DEVICE(0x2720, 0x0038, iwl9560_2ac_160_cfg)}, |
| 616 | {IWL_PCI_DEVICE(0x2720, 0x003C, iwl9560_2ac_160_cfg)}, | 623 | {IWL_PCI_DEVICE(0x2720, 0x003C, iwl9560_2ac_160_cfg)}, |
| 624 | {IWL_PCI_DEVICE(0x2720, 0x0044, iwl_ax101_cfg_qu_hr)}, | ||
| 617 | {IWL_PCI_DEVICE(0x2720, 0x0060, iwl9461_2ac_cfg_soc)}, | 625 | {IWL_PCI_DEVICE(0x2720, 0x0060, iwl9461_2ac_cfg_soc)}, |
| 618 | {IWL_PCI_DEVICE(0x2720, 0x0064, iwl9461_2ac_cfg_soc)}, | 626 | {IWL_PCI_DEVICE(0x2720, 0x0064, iwl9461_2ac_cfg_soc)}, |
| 619 | {IWL_PCI_DEVICE(0x2720, 0x00A0, iwl9462_2ac_cfg_soc)}, | 627 | {IWL_PCI_DEVICE(0x2720, 0x00A0, iwl9462_2ac_cfg_soc)}, |
| @@ -622,6 +630,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = { | |||
| 622 | {IWL_PCI_DEVICE(0x2720, 0x0234, iwl9560_2ac_cfg)}, | 630 | {IWL_PCI_DEVICE(0x2720, 0x0234, iwl9560_2ac_cfg)}, |
| 623 | {IWL_PCI_DEVICE(0x2720, 0x0238, iwl9560_2ac_cfg)}, | 631 | {IWL_PCI_DEVICE(0x2720, 0x0238, iwl9560_2ac_cfg)}, |
| 624 | {IWL_PCI_DEVICE(0x2720, 0x023C, iwl9560_2ac_cfg)}, | 632 | {IWL_PCI_DEVICE(0x2720, 0x023C, iwl9560_2ac_cfg)}, |
| 633 | {IWL_PCI_DEVICE(0x2720, 0x0244, iwl_ax101_cfg_qu_hr)}, | ||
| 625 | {IWL_PCI_DEVICE(0x2720, 0x0260, iwl9461_2ac_cfg_soc)}, | 634 | {IWL_PCI_DEVICE(0x2720, 0x0260, iwl9461_2ac_cfg_soc)}, |
| 626 | {IWL_PCI_DEVICE(0x2720, 0x0264, iwl9461_2ac_cfg_soc)}, | 635 | {IWL_PCI_DEVICE(0x2720, 0x0264, iwl9461_2ac_cfg_soc)}, |
| 627 | {IWL_PCI_DEVICE(0x2720, 0x02A0, iwl9462_2ac_cfg_soc)}, | 636 | {IWL_PCI_DEVICE(0x2720, 0x02A0, iwl9462_2ac_cfg_soc)}, |
| @@ -699,6 +708,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = { | |||
| 699 | {IWL_PCI_DEVICE(0x34F0, 0x0034, iwl9560_2ac_cfg_qu_b0_jf_b0)}, | 708 | {IWL_PCI_DEVICE(0x34F0, 0x0034, iwl9560_2ac_cfg_qu_b0_jf_b0)}, |
| 700 | {IWL_PCI_DEVICE(0x34F0, 0x0038, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, | 709 | {IWL_PCI_DEVICE(0x34F0, 0x0038, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, |
| 701 | {IWL_PCI_DEVICE(0x34F0, 0x003C, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, | 710 | {IWL_PCI_DEVICE(0x34F0, 0x003C, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, |
| 711 | {IWL_PCI_DEVICE(0x34F0, 0x0044, iwl_ax101_cfg_qu_hr)}, | ||
| 702 | {IWL_PCI_DEVICE(0x34F0, 0x0060, iwl9461_2ac_cfg_qu_b0_jf_b0)}, | 712 | {IWL_PCI_DEVICE(0x34F0, 0x0060, iwl9461_2ac_cfg_qu_b0_jf_b0)}, |
| 703 | {IWL_PCI_DEVICE(0x34F0, 0x0064, iwl9461_2ac_cfg_qu_b0_jf_b0)}, | 713 | {IWL_PCI_DEVICE(0x34F0, 0x0064, iwl9461_2ac_cfg_qu_b0_jf_b0)}, |
| 704 | {IWL_PCI_DEVICE(0x34F0, 0x00A0, iwl9462_2ac_cfg_qu_b0_jf_b0)}, | 714 | {IWL_PCI_DEVICE(0x34F0, 0x00A0, iwl9462_2ac_cfg_qu_b0_jf_b0)}, |
| @@ -707,6 +717,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = { | |||
| 707 | {IWL_PCI_DEVICE(0x34F0, 0x0234, iwl9560_2ac_cfg_qu_b0_jf_b0)}, | 717 | {IWL_PCI_DEVICE(0x34F0, 0x0234, iwl9560_2ac_cfg_qu_b0_jf_b0)}, |
| 708 | {IWL_PCI_DEVICE(0x34F0, 0x0238, iwl9560_2ac_cfg_qu_b0_jf_b0)}, | 718 | {IWL_PCI_DEVICE(0x34F0, 0x0238, iwl9560_2ac_cfg_qu_b0_jf_b0)}, |
| 709 | {IWL_PCI_DEVICE(0x34F0, 0x023C, iwl9560_2ac_cfg_qu_b0_jf_b0)}, | 719 | {IWL_PCI_DEVICE(0x34F0, 0x023C, iwl9560_2ac_cfg_qu_b0_jf_b0)}, |
| 720 | {IWL_PCI_DEVICE(0x34F0, 0x0244, iwl_ax101_cfg_qu_hr)}, | ||
| 710 | {IWL_PCI_DEVICE(0x34F0, 0x0260, iwl9461_2ac_cfg_qu_b0_jf_b0)}, | 721 | {IWL_PCI_DEVICE(0x34F0, 0x0260, iwl9461_2ac_cfg_qu_b0_jf_b0)}, |
| 711 | {IWL_PCI_DEVICE(0x34F0, 0x0264, iwl9461_2ac_cfg_qu_b0_jf_b0)}, | 722 | {IWL_PCI_DEVICE(0x34F0, 0x0264, iwl9461_2ac_cfg_qu_b0_jf_b0)}, |
| 712 | {IWL_PCI_DEVICE(0x34F0, 0x02A0, iwl9462_2ac_cfg_qu_b0_jf_b0)}, | 723 | {IWL_PCI_DEVICE(0x34F0, 0x02A0, iwl9462_2ac_cfg_qu_b0_jf_b0)}, |
| @@ -753,6 +764,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = { | |||
| 753 | {IWL_PCI_DEVICE(0x43F0, 0x0034, iwl9560_2ac_cfg_soc)}, | 764 | {IWL_PCI_DEVICE(0x43F0, 0x0034, iwl9560_2ac_cfg_soc)}, |
| 754 | {IWL_PCI_DEVICE(0x43F0, 0x0038, iwl9560_2ac_160_cfg_soc)}, | 765 | {IWL_PCI_DEVICE(0x43F0, 0x0038, iwl9560_2ac_160_cfg_soc)}, |
| 755 | {IWL_PCI_DEVICE(0x43F0, 0x003C, iwl9560_2ac_160_cfg_soc)}, | 766 | {IWL_PCI_DEVICE(0x43F0, 0x003C, iwl9560_2ac_160_cfg_soc)}, |
| 767 | {IWL_PCI_DEVICE(0x43F0, 0x0044, iwl_ax101_cfg_qu_hr)}, | ||
| 756 | {IWL_PCI_DEVICE(0x43F0, 0x0060, iwl9461_2ac_cfg_soc)}, | 768 | {IWL_PCI_DEVICE(0x43F0, 0x0060, iwl9461_2ac_cfg_soc)}, |
| 757 | {IWL_PCI_DEVICE(0x43F0, 0x0064, iwl9461_2ac_cfg_soc)}, | 769 | {IWL_PCI_DEVICE(0x43F0, 0x0064, iwl9461_2ac_cfg_soc)}, |
| 758 | {IWL_PCI_DEVICE(0x43F0, 0x00A0, iwl9462_2ac_cfg_soc)}, | 770 | {IWL_PCI_DEVICE(0x43F0, 0x00A0, iwl9462_2ac_cfg_soc)}, |
| @@ -761,6 +773,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = { | |||
| 761 | {IWL_PCI_DEVICE(0x43F0, 0x0234, iwl9560_2ac_cfg_soc)}, | 773 | {IWL_PCI_DEVICE(0x43F0, 0x0234, iwl9560_2ac_cfg_soc)}, |
| 762 | {IWL_PCI_DEVICE(0x43F0, 0x0238, iwl9560_2ac_cfg_soc)}, | 774 | {IWL_PCI_DEVICE(0x43F0, 0x0238, iwl9560_2ac_cfg_soc)}, |
| 763 | {IWL_PCI_DEVICE(0x43F0, 0x023C, iwl9560_2ac_cfg_soc)}, | 775 | {IWL_PCI_DEVICE(0x43F0, 0x023C, iwl9560_2ac_cfg_soc)}, |
| 776 | {IWL_PCI_DEVICE(0x43F0, 0x0244, iwl_ax101_cfg_qu_hr)}, | ||
| 764 | {IWL_PCI_DEVICE(0x43F0, 0x0260, iwl9461_2ac_cfg_soc)}, | 777 | {IWL_PCI_DEVICE(0x43F0, 0x0260, iwl9461_2ac_cfg_soc)}, |
| 765 | {IWL_PCI_DEVICE(0x43F0, 0x0264, iwl9461_2ac_cfg_soc)}, | 778 | {IWL_PCI_DEVICE(0x43F0, 0x0264, iwl9461_2ac_cfg_soc)}, |
| 766 | {IWL_PCI_DEVICE(0x43F0, 0x02A0, iwl9462_2ac_cfg_soc)}, | 779 | {IWL_PCI_DEVICE(0x43F0, 0x02A0, iwl9462_2ac_cfg_soc)}, |
| @@ -820,6 +833,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = { | |||
| 820 | {IWL_PCI_DEVICE(0xA0F0, 0x0034, iwl9560_2ac_cfg_soc)}, | 833 | {IWL_PCI_DEVICE(0xA0F0, 0x0034, iwl9560_2ac_cfg_soc)}, |
| 821 | {IWL_PCI_DEVICE(0xA0F0, 0x0038, iwl9560_2ac_160_cfg_soc)}, | 834 | {IWL_PCI_DEVICE(0xA0F0, 0x0038, iwl9560_2ac_160_cfg_soc)}, |
| 822 | {IWL_PCI_DEVICE(0xA0F0, 0x003C, iwl9560_2ac_160_cfg_soc)}, | 835 | {IWL_PCI_DEVICE(0xA0F0, 0x003C, iwl9560_2ac_160_cfg_soc)}, |
| 836 | {IWL_PCI_DEVICE(0xA0F0, 0x0044, iwl_ax101_cfg_qu_hr)}, | ||
| 823 | {IWL_PCI_DEVICE(0xA0F0, 0x0060, iwl9461_2ac_cfg_soc)}, | 837 | {IWL_PCI_DEVICE(0xA0F0, 0x0060, iwl9461_2ac_cfg_soc)}, |
| 824 | {IWL_PCI_DEVICE(0xA0F0, 0x0064, iwl9461_2ac_cfg_soc)}, | 838 | {IWL_PCI_DEVICE(0xA0F0, 0x0064, iwl9461_2ac_cfg_soc)}, |
| 825 | {IWL_PCI_DEVICE(0xA0F0, 0x00A0, iwl9462_2ac_cfg_soc)}, | 839 | {IWL_PCI_DEVICE(0xA0F0, 0x00A0, iwl9462_2ac_cfg_soc)}, |
| @@ -828,6 +842,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = { | |||
| 828 | {IWL_PCI_DEVICE(0xA0F0, 0x0234, iwl9560_2ac_cfg_soc)}, | 842 | {IWL_PCI_DEVICE(0xA0F0, 0x0234, iwl9560_2ac_cfg_soc)}, |
| 829 | {IWL_PCI_DEVICE(0xA0F0, 0x0238, iwl9560_2ac_cfg_soc)}, | 843 | {IWL_PCI_DEVICE(0xA0F0, 0x0238, iwl9560_2ac_cfg_soc)}, |
| 830 | {IWL_PCI_DEVICE(0xA0F0, 0x023C, iwl9560_2ac_cfg_soc)}, | 844 | {IWL_PCI_DEVICE(0xA0F0, 0x023C, iwl9560_2ac_cfg_soc)}, |
| 845 | {IWL_PCI_DEVICE(0xA0F0, 0x0244, iwl_ax101_cfg_qu_hr)}, | ||
| 831 | {IWL_PCI_DEVICE(0xA0F0, 0x0260, iwl9461_2ac_cfg_soc)}, | 846 | {IWL_PCI_DEVICE(0xA0F0, 0x0260, iwl9461_2ac_cfg_soc)}, |
| 832 | {IWL_PCI_DEVICE(0xA0F0, 0x0264, iwl9461_2ac_cfg_soc)}, | 847 | {IWL_PCI_DEVICE(0xA0F0, 0x0264, iwl9461_2ac_cfg_soc)}, |
| 833 | {IWL_PCI_DEVICE(0xA0F0, 0x02A0, iwl9462_2ac_cfg_soc)}, | 848 | {IWL_PCI_DEVICE(0xA0F0, 0x02A0, iwl9462_2ac_cfg_soc)}, |
| @@ -872,82 +887,92 @@ static const struct pci_device_id iwl_hw_card_ids[] = { | |||
| 872 | {IWL_PCI_DEVICE(0xA370, 0x40A4, iwl9462_2ac_cfg_soc)}, | 887 | {IWL_PCI_DEVICE(0xA370, 0x40A4, iwl9462_2ac_cfg_soc)}, |
| 873 | {IWL_PCI_DEVICE(0xA370, 0x4234, iwl9560_2ac_cfg_soc)}, | 888 | {IWL_PCI_DEVICE(0xA370, 0x4234, iwl9560_2ac_cfg_soc)}, |
| 874 | {IWL_PCI_DEVICE(0xA370, 0x42A4, iwl9462_2ac_cfg_soc)}, | 889 | {IWL_PCI_DEVICE(0xA370, 0x42A4, iwl9462_2ac_cfg_soc)}, |
| 890 | {IWL_PCI_DEVICE(0x2720, 0x0030, iwl9560_2ac_cfg_qnj_jf_b0)}, | ||
| 875 | 891 | ||
| 876 | /* 22000 Series */ | 892 | /* 22000 Series */ |
| 877 | {IWL_PCI_DEVICE(0x02F0, 0x0070, iwl22560_2ax_cfg_hr)}, | 893 | {IWL_PCI_DEVICE(0x02F0, 0x0070, iwl_ax101_cfg_qu_hr)}, |
| 878 | {IWL_PCI_DEVICE(0x02F0, 0x0074, iwl22560_2ax_cfg_hr)}, | 894 | {IWL_PCI_DEVICE(0x02F0, 0x0074, iwl_ax101_cfg_qu_hr)}, |
| 879 | {IWL_PCI_DEVICE(0x02F0, 0x0078, iwl22560_2ax_cfg_hr)}, | 895 | {IWL_PCI_DEVICE(0x02F0, 0x0078, iwl_ax101_cfg_qu_hr)}, |
| 880 | {IWL_PCI_DEVICE(0x02F0, 0x007C, iwl22560_2ax_cfg_hr)}, | 896 | {IWL_PCI_DEVICE(0x02F0, 0x007C, iwl_ax101_cfg_qu_hr)}, |
| 881 | {IWL_PCI_DEVICE(0x02F0, 0x0310, iwl22560_2ax_cfg_hr)}, | 897 | {IWL_PCI_DEVICE(0x02F0, 0x0310, iwl_ax101_cfg_qu_hr)}, |
| 882 | {IWL_PCI_DEVICE(0x02F0, 0x1651, killer1650s_2ax_cfg_qu_b0_hr_b0)}, | 898 | {IWL_PCI_DEVICE(0x02F0, 0x1651, killer1650s_2ax_cfg_qu_b0_hr_b0)}, |
| 883 | {IWL_PCI_DEVICE(0x02F0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0)}, | 899 | {IWL_PCI_DEVICE(0x02F0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0)}, |
| 884 | {IWL_PCI_DEVICE(0x02F0, 0x4070, iwl22560_2ax_cfg_hr)}, | 900 | {IWL_PCI_DEVICE(0x02F0, 0x4070, iwl_ax101_cfg_qu_hr)}, |
| 885 | {IWL_PCI_DEVICE(0x06F0, 0x0070, iwl22560_2ax_cfg_hr)}, | 901 | {IWL_PCI_DEVICE(0x06F0, 0x0070, iwl_ax101_cfg_qu_hr)}, |
| 886 | {IWL_PCI_DEVICE(0x06F0, 0x0074, iwl22560_2ax_cfg_hr)}, | 902 | {IWL_PCI_DEVICE(0x06F0, 0x0074, iwl_ax101_cfg_qu_hr)}, |
| 887 | {IWL_PCI_DEVICE(0x06F0, 0x0078, iwl22560_2ax_cfg_hr)}, | 903 | {IWL_PCI_DEVICE(0x06F0, 0x0078, iwl_ax101_cfg_qu_hr)}, |
| 888 | {IWL_PCI_DEVICE(0x06F0, 0x007C, iwl22560_2ax_cfg_hr)}, | 904 | {IWL_PCI_DEVICE(0x06F0, 0x007C, iwl_ax101_cfg_qu_hr)}, |
| 889 | {IWL_PCI_DEVICE(0x06F0, 0x0310, iwl22560_2ax_cfg_hr)}, | 905 | {IWL_PCI_DEVICE(0x06F0, 0x0310, iwl_ax101_cfg_qu_hr)}, |
| 890 | {IWL_PCI_DEVICE(0x06F0, 0x1651, killer1650s_2ax_cfg_qu_b0_hr_b0)}, | 906 | {IWL_PCI_DEVICE(0x06F0, 0x1651, killer1650s_2ax_cfg_qu_b0_hr_b0)}, |
| 891 | {IWL_PCI_DEVICE(0x06F0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0)}, | 907 | {IWL_PCI_DEVICE(0x06F0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0)}, |
| 892 | {IWL_PCI_DEVICE(0x06F0, 0x4070, iwl22560_2ax_cfg_hr)}, | 908 | {IWL_PCI_DEVICE(0x06F0, 0x4070, iwl_ax101_cfg_qu_hr)}, |
| 893 | {IWL_PCI_DEVICE(0x2720, 0x0000, iwl22560_2ax_cfg_hr)}, | 909 | {IWL_PCI_DEVICE(0x2720, 0x0000, iwl_ax101_cfg_qu_hr)}, |
| 894 | {IWL_PCI_DEVICE(0x2720, 0x0030, iwl9560_2ac_160_cfg_soc)}, | 910 | {IWL_PCI_DEVICE(0x2720, 0x0040, iwl_ax101_cfg_qu_hr)}, |
| 895 | {IWL_PCI_DEVICE(0x2720, 0x0040, iwl22560_2ax_cfg_hr)}, | ||
| 896 | {IWL_PCI_DEVICE(0x2720, 0x0070, iwl22000_2ac_cfg_hr_cdb)}, | 911 | {IWL_PCI_DEVICE(0x2720, 0x0070, iwl22000_2ac_cfg_hr_cdb)}, |
| 897 | {IWL_PCI_DEVICE(0x2720, 0x0074, iwl22560_2ax_cfg_hr)}, | 912 | {IWL_PCI_DEVICE(0x2720, 0x0074, iwl_ax101_cfg_qu_hr)}, |
| 898 | {IWL_PCI_DEVICE(0x2720, 0x0078, iwl22560_2ax_cfg_hr)}, | 913 | {IWL_PCI_DEVICE(0x2720, 0x0078, iwl_ax101_cfg_qu_hr)}, |
| 899 | {IWL_PCI_DEVICE(0x2720, 0x007C, iwl22560_2ax_cfg_hr)}, | 914 | {IWL_PCI_DEVICE(0x2720, 0x007C, iwl_ax101_cfg_qu_hr)}, |
| 900 | {IWL_PCI_DEVICE(0x2720, 0x0090, iwl22000_2ac_cfg_hr_cdb)}, | 915 | {IWL_PCI_DEVICE(0x2720, 0x0090, iwl22000_2ac_cfg_hr_cdb)}, |
| 901 | {IWL_PCI_DEVICE(0x2720, 0x0310, iwl22000_2ac_cfg_hr_cdb)}, | 916 | {IWL_PCI_DEVICE(0x2720, 0x0310, iwl22000_2ac_cfg_hr_cdb)}, |
| 902 | {IWL_PCI_DEVICE(0x2720, 0x0A10, iwl22000_2ac_cfg_hr_cdb)}, | 917 | {IWL_PCI_DEVICE(0x2720, 0x0A10, iwl22000_2ac_cfg_hr_cdb)}, |
| 903 | {IWL_PCI_DEVICE(0x2720, 0x1080, iwl22560_2ax_cfg_hr)}, | 918 | {IWL_PCI_DEVICE(0x2720, 0x1080, iwl_ax101_cfg_qu_hr)}, |
| 904 | {IWL_PCI_DEVICE(0x2720, 0x1651, killer1650s_2ax_cfg_qu_b0_hr_b0)}, | 919 | {IWL_PCI_DEVICE(0x2720, 0x1651, killer1650s_2ax_cfg_qu_b0_hr_b0)}, |
| 905 | {IWL_PCI_DEVICE(0x2720, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0)}, | 920 | {IWL_PCI_DEVICE(0x2720, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0)}, |
| 906 | {IWL_PCI_DEVICE(0x2720, 0x4070, iwl22560_2ax_cfg_hr)}, | 921 | {IWL_PCI_DEVICE(0x2720, 0x4070, iwl_ax101_cfg_qu_hr)}, |
| 907 | {IWL_PCI_DEVICE(0x34F0, 0x0040, iwl22560_2ax_cfg_hr)}, | 922 | {IWL_PCI_DEVICE(0x34F0, 0x0040, iwl_ax101_cfg_qu_hr)}, |
| 908 | {IWL_PCI_DEVICE(0x34F0, 0x0070, iwl22560_2ax_cfg_hr)}, | 923 | {IWL_PCI_DEVICE(0x34F0, 0x0070, iwl_ax101_cfg_qu_hr)}, |
| 909 | {IWL_PCI_DEVICE(0x34F0, 0x0074, iwl22560_2ax_cfg_hr)}, | 924 | {IWL_PCI_DEVICE(0x34F0, 0x0074, iwl_ax101_cfg_qu_hr)}, |
| 910 | {IWL_PCI_DEVICE(0x34F0, 0x0078, iwl22560_2ax_cfg_hr)}, | 925 | {IWL_PCI_DEVICE(0x34F0, 0x0078, iwl_ax101_cfg_qu_hr)}, |
| 911 | {IWL_PCI_DEVICE(0x34F0, 0x007C, iwl22560_2ax_cfg_hr)}, | 926 | {IWL_PCI_DEVICE(0x34F0, 0x007C, iwl_ax101_cfg_qu_hr)}, |
| 912 | {IWL_PCI_DEVICE(0x34F0, 0x0310, iwl22560_2ax_cfg_hr)}, | 927 | {IWL_PCI_DEVICE(0x34F0, 0x0310, iwl_ax101_cfg_qu_hr)}, |
| 913 | {IWL_PCI_DEVICE(0x34F0, 0x1651, killer1650s_2ax_cfg_qu_b0_hr_b0)}, | 928 | {IWL_PCI_DEVICE(0x34F0, 0x1651, killer1650s_2ax_cfg_qu_b0_hr_b0)}, |
| 914 | {IWL_PCI_DEVICE(0x34F0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0)}, | 929 | {IWL_PCI_DEVICE(0x34F0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0)}, |
| 915 | {IWL_PCI_DEVICE(0x34F0, 0x4070, iwl22560_2ax_cfg_hr)}, | 930 | {IWL_PCI_DEVICE(0x34F0, 0x4070, iwl_ax101_cfg_qu_hr)}, |
| 916 | {IWL_PCI_DEVICE(0x40C0, 0x0000, iwl22560_2ax_cfg_su_cdb)}, | 931 | {IWL_PCI_DEVICE(0x40C0, 0x0000, iwl22560_2ax_cfg_su_cdb)}, |
| 917 | {IWL_PCI_DEVICE(0x40C0, 0x0010, iwl22560_2ax_cfg_su_cdb)}, | 932 | {IWL_PCI_DEVICE(0x40C0, 0x0010, iwl22560_2ax_cfg_su_cdb)}, |
| 918 | {IWL_PCI_DEVICE(0x40c0, 0x0090, iwl22560_2ax_cfg_su_cdb)}, | 933 | {IWL_PCI_DEVICE(0x40c0, 0x0090, iwl22560_2ax_cfg_su_cdb)}, |
| 919 | {IWL_PCI_DEVICE(0x40C0, 0x0310, iwl22560_2ax_cfg_su_cdb)}, | 934 | {IWL_PCI_DEVICE(0x40C0, 0x0310, iwl22560_2ax_cfg_su_cdb)}, |
| 920 | {IWL_PCI_DEVICE(0x40C0, 0x0A10, iwl22560_2ax_cfg_su_cdb)}, | 935 | {IWL_PCI_DEVICE(0x40C0, 0x0A10, iwl22560_2ax_cfg_su_cdb)}, |
| 921 | {IWL_PCI_DEVICE(0x43F0, 0x0040, iwl22560_2ax_cfg_hr)}, | 936 | {IWL_PCI_DEVICE(0x43F0, 0x0040, iwl_ax101_cfg_qu_hr)}, |
| 922 | {IWL_PCI_DEVICE(0x43F0, 0x0070, iwl22560_2ax_cfg_hr)}, | 937 | {IWL_PCI_DEVICE(0x43F0, 0x0070, iwl_ax101_cfg_qu_hr)}, |
| 923 | {IWL_PCI_DEVICE(0x43F0, 0x0074, iwl22560_2ax_cfg_hr)}, | 938 | {IWL_PCI_DEVICE(0x43F0, 0x0074, iwl_ax101_cfg_qu_hr)}, |
| 924 | {IWL_PCI_DEVICE(0x43F0, 0x0078, iwl22560_2ax_cfg_hr)}, | 939 | {IWL_PCI_DEVICE(0x43F0, 0x0078, iwl_ax101_cfg_qu_hr)}, |
| 925 | {IWL_PCI_DEVICE(0x43F0, 0x007C, iwl22560_2ax_cfg_hr)}, | 940 | {IWL_PCI_DEVICE(0x43F0, 0x007C, iwl_ax101_cfg_qu_hr)}, |
| 926 | {IWL_PCI_DEVICE(0x43F0, 0x1651, killer1650s_2ax_cfg_qu_b0_hr_b0)}, | 941 | {IWL_PCI_DEVICE(0x43F0, 0x1651, killer1650s_2ax_cfg_qu_b0_hr_b0)}, |
| 927 | {IWL_PCI_DEVICE(0x43F0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0)}, | 942 | {IWL_PCI_DEVICE(0x43F0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0)}, |
| 928 | {IWL_PCI_DEVICE(0x43F0, 0x4070, iwl22560_2ax_cfg_hr)}, | 943 | {IWL_PCI_DEVICE(0x43F0, 0x4070, iwl_ax101_cfg_qu_hr)}, |
| 929 | {IWL_PCI_DEVICE(0xA0F0, 0x0000, iwl22560_2ax_cfg_hr)}, | 944 | {IWL_PCI_DEVICE(0xA0F0, 0x0000, iwl_ax101_cfg_qu_hr)}, |
| 930 | {IWL_PCI_DEVICE(0xA0F0, 0x0040, iwl22560_2ax_cfg_hr)}, | 945 | {IWL_PCI_DEVICE(0xA0F0, 0x0040, iwl_ax101_cfg_qu_hr)}, |
| 931 | {IWL_PCI_DEVICE(0xA0F0, 0x0070, iwl22560_2ax_cfg_hr)}, | 946 | {IWL_PCI_DEVICE(0xA0F0, 0x0070, iwl_ax101_cfg_qu_hr)}, |
| 932 | {IWL_PCI_DEVICE(0xA0F0, 0x0074, iwl22560_2ax_cfg_hr)}, | 947 | {IWL_PCI_DEVICE(0xA0F0, 0x0074, iwl_ax101_cfg_qu_hr)}, |
| 933 | {IWL_PCI_DEVICE(0xA0F0, 0x0078, iwl22560_2ax_cfg_hr)}, | 948 | {IWL_PCI_DEVICE(0xA0F0, 0x0078, iwl_ax101_cfg_qu_hr)}, |
| 934 | {IWL_PCI_DEVICE(0xA0F0, 0x007C, iwl22560_2ax_cfg_hr)}, | 949 | {IWL_PCI_DEVICE(0xA0F0, 0x007C, iwl_ax101_cfg_qu_hr)}, |
| 935 | {IWL_PCI_DEVICE(0xA0F0, 0x00B0, iwl22560_2ax_cfg_hr)}, | 950 | {IWL_PCI_DEVICE(0xA0F0, 0x00B0, iwl_ax101_cfg_qu_hr)}, |
| 936 | {IWL_PCI_DEVICE(0xA0F0, 0x0A10, iwl22560_2ax_cfg_hr)}, | 951 | {IWL_PCI_DEVICE(0xA0F0, 0x0A10, iwl_ax101_cfg_qu_hr)}, |
| 937 | {IWL_PCI_DEVICE(0xA0F0, 0x1651, killer1650s_2ax_cfg_qu_b0_hr_b0)}, | 952 | {IWL_PCI_DEVICE(0xA0F0, 0x1651, killer1650s_2ax_cfg_qu_b0_hr_b0)}, |
| 938 | {IWL_PCI_DEVICE(0xA0F0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0)}, | 953 | {IWL_PCI_DEVICE(0xA0F0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0)}, |
| 939 | {IWL_PCI_DEVICE(0xA0F0, 0x4070, iwl22560_2ax_cfg_hr)}, | 954 | {IWL_PCI_DEVICE(0xA0F0, 0x4070, iwl_ax101_cfg_qu_hr)}, |
| 940 | 955 | ||
| 941 | {IWL_PCI_DEVICE(0x2723, 0x0080, iwl22260_2ax_cfg)}, | 956 | {IWL_PCI_DEVICE(0x2723, 0x0080, iwl22260_2ax_cfg)}, |
| 942 | {IWL_PCI_DEVICE(0x2723, 0x0084, iwl22260_2ax_cfg)}, | 957 | {IWL_PCI_DEVICE(0x2723, 0x0084, iwl22260_2ax_cfg)}, |
| 943 | {IWL_PCI_DEVICE(0x2723, 0x0088, iwl22260_2ax_cfg)}, | 958 | {IWL_PCI_DEVICE(0x2723, 0x0088, iwl22260_2ax_cfg)}, |
| 944 | {IWL_PCI_DEVICE(0x2723, 0x008C, iwl22260_2ax_cfg)}, | 959 | {IWL_PCI_DEVICE(0x2723, 0x008C, iwl22260_2ax_cfg)}, |
| 960 | {IWL_PCI_DEVICE(0x2723, 0x1653, killer1650w_2ax_cfg)}, | ||
| 961 | {IWL_PCI_DEVICE(0x2723, 0x1654, killer1650x_2ax_cfg)}, | ||
| 945 | {IWL_PCI_DEVICE(0x2723, 0x4080, iwl22260_2ax_cfg)}, | 962 | {IWL_PCI_DEVICE(0x2723, 0x4080, iwl22260_2ax_cfg)}, |
| 946 | {IWL_PCI_DEVICE(0x2723, 0x4088, iwl22260_2ax_cfg)}, | 963 | {IWL_PCI_DEVICE(0x2723, 0x4088, iwl22260_2ax_cfg)}, |
| 947 | 964 | ||
| 948 | {IWL_PCI_DEVICE(0x1a56, 0x1653, killer1650w_2ax_cfg)}, | 965 | {IWL_PCI_DEVICE(0x1a56, 0x1653, killer1650w_2ax_cfg)}, |
| 949 | {IWL_PCI_DEVICE(0x1a56, 0x1654, killer1650x_2ax_cfg)}, | 966 | {IWL_PCI_DEVICE(0x1a56, 0x1654, killer1650x_2ax_cfg)}, |
| 950 | 967 | ||
| 968 | {IWL_PCI_DEVICE(0x2725, 0x0090, iwlax210_2ax_cfg_so_hr_a0)}, | ||
| 969 | {IWL_PCI_DEVICE(0x7A70, 0x0090, iwlax210_2ax_cfg_so_hr_a0)}, | ||
| 970 | {IWL_PCI_DEVICE(0x7A70, 0x0310, iwlax210_2ax_cfg_so_hr_a0)}, | ||
| 971 | {IWL_PCI_DEVICE(0x2725, 0x0020, iwlax210_2ax_cfg_so_hr_a0)}, | ||
| 972 | {IWL_PCI_DEVICE(0x2725, 0x0310, iwlax210_2ax_cfg_so_hr_a0)}, | ||
| 973 | {IWL_PCI_DEVICE(0x2725, 0x0A10, iwlax210_2ax_cfg_so_hr_a0)}, | ||
| 974 | {IWL_PCI_DEVICE(0x2725, 0x00B0, iwlax210_2ax_cfg_so_hr_a0)}, | ||
| 975 | |||
| 951 | #endif /* CONFIG_IWLMVM */ | 976 | #endif /* CONFIG_IWLMVM */ |
| 952 | 977 | ||
| 953 | {0} | 978 | {0} |
| @@ -999,7 +1024,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 999 | 1024 | ||
| 1000 | if (rf_id_chp == jf_chp_id) { | 1025 | if (rf_id_chp == jf_chp_id) { |
| 1001 | if (iwl_trans->hw_rev == CSR_HW_REV_TYPE_QNJ) | 1026 | if (iwl_trans->hw_rev == CSR_HW_REV_TYPE_QNJ) |
| 1002 | cfg = &iwl22000_2ax_cfg_qnj_jf_b0; | 1027 | cfg = &iwl9560_2ac_cfg_qnj_jf_b0; |
| 1003 | else | 1028 | else |
| 1004 | cfg = &iwl22000_2ac_cfg_jf; | 1029 | cfg = &iwl22000_2ac_cfg_jf; |
| 1005 | } else if (rf_id_chp == hr_chp_id) { | 1030 | } else if (rf_id_chp == hr_chp_id) { |
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h index 0d16bcc3141f..bf8b61a476c5 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | * Copyright(c) 2003 - 2015 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2003 - 2015 Intel Corporation. All rights reserved. |
| 9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
| 10 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH | 10 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH |
| 11 | * Copyright(c) 2018 Intel Corporation | 11 | * Copyright(c) 2018 - 2019 Intel Corporation |
| 12 | * | 12 | * |
| 13 | * This program is free software; you can redistribute it and/or modify it | 13 | * This program is free software; you can redistribute it and/or modify it |
| 14 | * under the terms of version 2 of the GNU General Public License as | 14 | * under the terms of version 2 of the GNU General Public License as |
| @@ -31,7 +31,7 @@ | |||
| 31 | * Copyright(c) 2003 - 2015 Intel Corporation. All rights reserved. | 31 | * Copyright(c) 2003 - 2015 Intel Corporation. All rights reserved. |
| 32 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 32 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
| 33 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH | 33 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH |
| 34 | * Copyright(c) 2018 Intel Corporation | 34 | * Copyright(c) 2018 - 2019 Intel Corporation |
| 35 | * All rights reserved. | 35 | * All rights reserved. |
| 36 | * | 36 | * |
| 37 | * Redistribution and use in source and binary forms, with or without | 37 | * Redistribution and use in source and binary forms, with or without |
| @@ -400,6 +400,8 @@ struct iwl_txq { | |||
| 400 | u32 id; | 400 | u32 id; |
| 401 | int low_mark; | 401 | int low_mark; |
| 402 | int high_mark; | 402 | int high_mark; |
| 403 | |||
| 404 | bool overflow_tx; | ||
| 403 | }; | 405 | }; |
| 404 | 406 | ||
| 405 | static inline dma_addr_t | 407 | static inline dma_addr_t |
| @@ -454,20 +456,6 @@ enum iwl_image_response_code { | |||
| 454 | }; | 456 | }; |
| 455 | 457 | ||
| 456 | /** | 458 | /** |
| 457 | * struct iwl_self_init_dram - dram data used by self init process | ||
| 458 | * @fw: lmac and umac dram data | ||
| 459 | * @fw_cnt: total number of items in array | ||
| 460 | * @paging: paging dram data | ||
| 461 | * @paging_cnt: total number of items in array | ||
| 462 | */ | ||
| 463 | struct iwl_self_init_dram { | ||
| 464 | struct iwl_dram_data *fw; | ||
| 465 | int fw_cnt; | ||
| 466 | struct iwl_dram_data *paging; | ||
| 467 | int paging_cnt; | ||
| 468 | }; | ||
| 469 | |||
| 470 | /** | ||
| 471 | * struct cont_rec: continuous recording data structure | 459 | * struct cont_rec: continuous recording data structure |
| 472 | * @prev_wr_ptr: the last address that was read in monitor_data | 460 | * @prev_wr_ptr: the last address that was read in monitor_data |
| 473 | * debugfs file | 461 | * debugfs file |
| @@ -538,6 +526,8 @@ struct cont_rec { | |||
| 538 | * @fh_mask: current unmasked fh causes | 526 | * @fh_mask: current unmasked fh causes |
| 539 | * @hw_mask: current unmasked hw causes | 527 | * @hw_mask: current unmasked hw causes |
| 540 | * @in_rescan: true if we have triggered a device rescan | 528 | * @in_rescan: true if we have triggered a device rescan |
| 529 | * @base_rb_stts: base virtual address of receive buffer status for all queues | ||
| 530 | * @base_rb_stts_dma: base physical address of receive buffer status | ||
| 541 | */ | 531 | */ |
| 542 | struct iwl_trans_pcie { | 532 | struct iwl_trans_pcie { |
| 543 | struct iwl_rxq *rxq; | 533 | struct iwl_rxq *rxq; |
| @@ -554,7 +544,6 @@ struct iwl_trans_pcie { | |||
| 554 | dma_addr_t prph_info_dma_addr; | 544 | dma_addr_t prph_info_dma_addr; |
| 555 | dma_addr_t prph_scratch_dma_addr; | 545 | dma_addr_t prph_scratch_dma_addr; |
| 556 | dma_addr_t iml_dma_addr; | 546 | dma_addr_t iml_dma_addr; |
| 557 | struct iwl_self_init_dram init_dram; | ||
| 558 | struct iwl_trans *trans; | 547 | struct iwl_trans *trans; |
| 559 | 548 | ||
| 560 | struct net_device napi_dev; | 549 | struct net_device napi_dev; |
| @@ -630,6 +619,9 @@ struct iwl_trans_pcie { | |||
| 630 | cpumask_t affinity_mask[IWL_MAX_RX_HW_QUEUES]; | 619 | cpumask_t affinity_mask[IWL_MAX_RX_HW_QUEUES]; |
| 631 | u16 tx_cmd_queue_size; | 620 | u16 tx_cmd_queue_size; |
| 632 | bool in_rescan; | 621 | bool in_rescan; |
| 622 | |||
| 623 | void *base_rb_stts; | ||
| 624 | dma_addr_t base_rb_stts_dma; | ||
| 633 | }; | 625 | }; |
| 634 | 626 | ||
| 635 | static inline struct iwl_trans_pcie * | 627 | static inline struct iwl_trans_pcie * |
| @@ -813,8 +805,7 @@ static inline int iwl_pcie_ctxt_info_alloc_dma(struct iwl_trans *trans, | |||
| 813 | 805 | ||
| 814 | static inline void iwl_pcie_ctxt_info_free_fw_img(struct iwl_trans *trans) | 806 | static inline void iwl_pcie_ctxt_info_free_fw_img(struct iwl_trans *trans) |
| 815 | { | 807 | { |
| 816 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 808 | struct iwl_self_init_dram *dram = &trans->init_dram; |
| 817 | struct iwl_self_init_dram *dram = &trans_pcie->init_dram; | ||
| 818 | int i; | 809 | int i; |
| 819 | 810 | ||
| 820 | if (!dram->fw) { | 811 | if (!dram->fw) { |
| @@ -1052,6 +1043,7 @@ static inline bool iwl_pcie_dbg_on(struct iwl_trans *trans) | |||
| 1052 | 1043 | ||
| 1053 | void iwl_trans_pcie_rf_kill(struct iwl_trans *trans, bool state); | 1044 | void iwl_trans_pcie_rf_kill(struct iwl_trans *trans, bool state); |
| 1054 | void iwl_trans_pcie_dump_regs(struct iwl_trans *trans); | 1045 | void iwl_trans_pcie_dump_regs(struct iwl_trans *trans); |
| 1046 | void iwl_trans_sync_nmi(struct iwl_trans *trans); | ||
| 1055 | 1047 | ||
| 1056 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 1048 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
| 1057 | int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans); | 1049 | int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans); |
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c index c260d1251b5f..8d4f0628622b 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. |
| 9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
| 10 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH | 10 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH |
| 11 | * Copyright(c) 2018 Intel Corporation | 11 | * Copyright(c) 2018 - 2019 Intel Corporation |
| 12 | * | 12 | * |
| 13 | * This program is free software; you can redistribute it and/or modify it | 13 | * This program is free software; you can redistribute it and/or modify it |
| 14 | * under the terms of version 2 of the GNU General Public License as | 14 | * under the terms of version 2 of the GNU General Public License as |
| @@ -31,7 +31,7 @@ | |||
| 31 | * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. | 31 | * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. |
| 32 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 32 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
| 33 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH | 33 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH |
| 34 | * Copyright(c) 2018 Intel Corporation | 34 | * Copyright(c) 2018 - 2019 Intel Corporation |
| 35 | * All rights reserved. | 35 | * All rights reserved. |
| 36 | * | 36 | * |
| 37 | * Redistribution and use in source and binary forms, with or without | 37 | * Redistribution and use in source and binary forms, with or without |
| @@ -202,9 +202,9 @@ int iwl_pcie_rx_stop(struct iwl_trans *trans) | |||
| 202 | { | 202 | { |
| 203 | if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) { | 203 | if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) { |
| 204 | /* TODO: remove this for 22560 once fw does it */ | 204 | /* TODO: remove this for 22560 once fw does it */ |
| 205 | iwl_write_prph(trans, RFH_RXF_DMA_CFG_GEN3, 0); | 205 | iwl_write_umac_prph(trans, RFH_RXF_DMA_CFG_GEN3, 0); |
| 206 | return iwl_poll_prph_bit(trans, RFH_GEN_STATUS_GEN3, | 206 | return iwl_poll_umac_prph_bit(trans, RFH_GEN_STATUS_GEN3, |
| 207 | RXF_DMA_IDLE, RXF_DMA_IDLE, 1000); | 207 | RXF_DMA_IDLE, RXF_DMA_IDLE, 1000); |
| 208 | } else if (trans->cfg->mq_rx_supported) { | 208 | } else if (trans->cfg->mq_rx_supported) { |
| 209 | iwl_write_prph(trans, RFH_RXF_DMA_CFG, 0); | 209 | iwl_write_prph(trans, RFH_RXF_DMA_CFG, 0); |
| 210 | return iwl_poll_prph_bit(trans, RFH_GEN_STATUS, | 210 | return iwl_poll_prph_bit(trans, RFH_GEN_STATUS, |
| @@ -247,7 +247,7 @@ static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans, | |||
| 247 | } | 247 | } |
| 248 | 248 | ||
| 249 | rxq->write_actual = round_down(rxq->write, 8); | 249 | rxq->write_actual = round_down(rxq->write, 8); |
| 250 | if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) | 250 | if (trans->cfg->device_family == IWL_DEVICE_FAMILY_22560) |
| 251 | iwl_write32(trans, HBUS_TARG_WRPTR, | 251 | iwl_write32(trans, HBUS_TARG_WRPTR, |
| 252 | (rxq->write_actual | | 252 | (rxq->write_actual | |
| 253 | ((FIRST_RX_QUEUE + rxq->id) << 16))); | 253 | ((FIRST_RX_QUEUE + rxq->id) << 16))); |
| @@ -538,9 +538,9 @@ static void iwl_pcie_rx_allocator(struct iwl_trans *trans) | |||
| 538 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 538 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
| 539 | struct iwl_rb_allocator *rba = &trans_pcie->rba; | 539 | struct iwl_rb_allocator *rba = &trans_pcie->rba; |
| 540 | struct list_head local_empty; | 540 | struct list_head local_empty; |
| 541 | int pending = atomic_xchg(&rba->req_pending, 0); | 541 | int pending = atomic_read(&rba->req_pending); |
| 542 | 542 | ||
| 543 | IWL_DEBUG_RX(trans, "Pending allocation requests = %d\n", pending); | 543 | IWL_DEBUG_TPT(trans, "Pending allocation requests = %d\n", pending); |
| 544 | 544 | ||
| 545 | /* If we were scheduled - there is at least one request */ | 545 | /* If we were scheduled - there is at least one request */ |
| 546 | spin_lock(&rba->lock); | 546 | spin_lock(&rba->lock); |
| @@ -593,12 +593,15 @@ static void iwl_pcie_rx_allocator(struct iwl_trans *trans) | |||
| 593 | i++; | 593 | i++; |
| 594 | } | 594 | } |
| 595 | 595 | ||
| 596 | atomic_dec(&rba->req_pending); | ||
| 596 | pending--; | 597 | pending--; |
| 598 | |||
| 597 | if (!pending) { | 599 | if (!pending) { |
| 598 | pending = atomic_xchg(&rba->req_pending, 0); | 600 | pending = atomic_read(&rba->req_pending); |
| 599 | IWL_DEBUG_RX(trans, | 601 | if (pending) |
| 600 | "Pending allocation requests = %d\n", | 602 | IWL_DEBUG_TPT(trans, |
| 601 | pending); | 603 | "Got more pending allocation requests = %d\n", |
| 604 | pending); | ||
| 602 | } | 605 | } |
| 603 | 606 | ||
| 604 | spin_lock(&rba->lock); | 607 | spin_lock(&rba->lock); |
| @@ -609,12 +612,15 @@ static void iwl_pcie_rx_allocator(struct iwl_trans *trans) | |||
| 609 | spin_unlock(&rba->lock); | 612 | spin_unlock(&rba->lock); |
| 610 | 613 | ||
| 611 | atomic_inc(&rba->req_ready); | 614 | atomic_inc(&rba->req_ready); |
| 615 | |||
| 612 | } | 616 | } |
| 613 | 617 | ||
| 614 | spin_lock(&rba->lock); | 618 | spin_lock(&rba->lock); |
| 615 | /* return unused rbds to the allocator empty list */ | 619 | /* return unused rbds to the allocator empty list */ |
| 616 | list_splice_tail(&local_empty, &rba->rbd_empty); | 620 | list_splice_tail(&local_empty, &rba->rbd_empty); |
| 617 | spin_unlock(&rba->lock); | 621 | spin_unlock(&rba->lock); |
| 622 | |||
| 623 | IWL_DEBUG_TPT(trans, "%s, exit.\n", __func__); | ||
| 618 | } | 624 | } |
| 619 | 625 | ||
| 620 | /* | 626 | /* |
| @@ -696,11 +702,6 @@ static void iwl_pcie_free_rxq_dma(struct iwl_trans *trans, | |||
| 696 | rxq->bd_dma = 0; | 702 | rxq->bd_dma = 0; |
| 697 | rxq->bd = NULL; | 703 | rxq->bd = NULL; |
| 698 | 704 | ||
| 699 | if (rxq->rb_stts) | ||
| 700 | dma_free_coherent(trans->dev, | ||
| 701 | use_rx_td ? sizeof(__le16) : | ||
| 702 | sizeof(struct iwl_rb_status), | ||
| 703 | rxq->rb_stts, rxq->rb_stts_dma); | ||
| 704 | rxq->rb_stts_dma = 0; | 705 | rxq->rb_stts_dma = 0; |
| 705 | rxq->rb_stts = NULL; | 706 | rxq->rb_stts = NULL; |
| 706 | 707 | ||
| @@ -737,6 +738,8 @@ static int iwl_pcie_alloc_rxq_dma(struct iwl_trans *trans, | |||
| 737 | int free_size; | 738 | int free_size; |
| 738 | bool use_rx_td = (trans->cfg->device_family >= | 739 | bool use_rx_td = (trans->cfg->device_family >= |
| 739 | IWL_DEVICE_FAMILY_22560); | 740 | IWL_DEVICE_FAMILY_22560); |
| 741 | size_t rb_stts_size = use_rx_td ? sizeof(__le16) : | ||
| 742 | sizeof(struct iwl_rb_status); | ||
| 740 | 743 | ||
| 741 | spin_lock_init(&rxq->lock); | 744 | spin_lock_init(&rxq->lock); |
| 742 | if (trans->cfg->mq_rx_supported) | 745 | if (trans->cfg->mq_rx_supported) |
| @@ -764,12 +767,9 @@ static int iwl_pcie_alloc_rxq_dma(struct iwl_trans *trans, | |||
| 764 | goto err; | 767 | goto err; |
| 765 | } | 768 | } |
| 766 | 769 | ||
| 767 | /* Allocate the driver's pointer to receive buffer status */ | 770 | rxq->rb_stts = trans_pcie->base_rb_stts + rxq->id * rb_stts_size; |
| 768 | rxq->rb_stts = dma_alloc_coherent(dev, | 771 | rxq->rb_stts_dma = |
| 769 | use_rx_td ? sizeof(__le16) : sizeof(struct iwl_rb_status), | 772 | trans_pcie->base_rb_stts_dma + rxq->id * rb_stts_size; |
| 770 | &rxq->rb_stts_dma, GFP_KERNEL); | ||
| 771 | if (!rxq->rb_stts) | ||
| 772 | goto err; | ||
| 773 | 773 | ||
| 774 | if (!use_rx_td) | 774 | if (!use_rx_td) |
| 775 | return 0; | 775 | return 0; |
| @@ -799,7 +799,6 @@ err: | |||
| 799 | 799 | ||
| 800 | iwl_pcie_free_rxq_dma(trans, rxq); | 800 | iwl_pcie_free_rxq_dma(trans, rxq); |
| 801 | } | 801 | } |
| 802 | kfree(trans_pcie->rxq); | ||
| 803 | 802 | ||
| 804 | return -ENOMEM; | 803 | return -ENOMEM; |
| 805 | } | 804 | } |
| @@ -809,6 +808,9 @@ int iwl_pcie_rx_alloc(struct iwl_trans *trans) | |||
| 809 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 808 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
| 810 | struct iwl_rb_allocator *rba = &trans_pcie->rba; | 809 | struct iwl_rb_allocator *rba = &trans_pcie->rba; |
| 811 | int i, ret; | 810 | int i, ret; |
| 811 | size_t rb_stts_size = trans->cfg->device_family >= | ||
| 812 | IWL_DEVICE_FAMILY_22560 ? | ||
| 813 | sizeof(__le16) : sizeof(struct iwl_rb_status); | ||
| 812 | 814 | ||
| 813 | if (WARN_ON(trans_pcie->rxq)) | 815 | if (WARN_ON(trans_pcie->rxq)) |
| 814 | return -EINVAL; | 816 | return -EINVAL; |
| @@ -816,18 +818,46 @@ int iwl_pcie_rx_alloc(struct iwl_trans *trans) | |||
| 816 | trans_pcie->rxq = kcalloc(trans->num_rx_queues, sizeof(struct iwl_rxq), | 818 | trans_pcie->rxq = kcalloc(trans->num_rx_queues, sizeof(struct iwl_rxq), |
| 817 | GFP_KERNEL); | 819 | GFP_KERNEL); |
| 818 | if (!trans_pcie->rxq) | 820 | if (!trans_pcie->rxq) |
| 819 | return -EINVAL; | 821 | return -ENOMEM; |
| 820 | 822 | ||
| 821 | spin_lock_init(&rba->lock); | 823 | spin_lock_init(&rba->lock); |
| 822 | 824 | ||
| 825 | /* | ||
| 826 | * Allocate the driver's pointer to receive buffer status. | ||
| 827 | * Allocate for all queues continuously (HW requirement). | ||
| 828 | */ | ||
| 829 | trans_pcie->base_rb_stts = | ||
| 830 | dma_alloc_coherent(trans->dev, | ||
| 831 | rb_stts_size * trans->num_rx_queues, | ||
| 832 | &trans_pcie->base_rb_stts_dma, | ||
| 833 | GFP_KERNEL); | ||
| 834 | if (!trans_pcie->base_rb_stts) { | ||
| 835 | ret = -ENOMEM; | ||
| 836 | goto err; | ||
| 837 | } | ||
| 838 | |||
| 823 | for (i = 0; i < trans->num_rx_queues; i++) { | 839 | for (i = 0; i < trans->num_rx_queues; i++) { |
| 824 | struct iwl_rxq *rxq = &trans_pcie->rxq[i]; | 840 | struct iwl_rxq *rxq = &trans_pcie->rxq[i]; |
| 825 | 841 | ||
| 842 | rxq->id = i; | ||
| 826 | ret = iwl_pcie_alloc_rxq_dma(trans, rxq); | 843 | ret = iwl_pcie_alloc_rxq_dma(trans, rxq); |
| 827 | if (ret) | 844 | if (ret) |
| 828 | return ret; | 845 | goto err; |
| 829 | } | 846 | } |
| 830 | return 0; | 847 | return 0; |
| 848 | |||
| 849 | err: | ||
| 850 | if (trans_pcie->base_rb_stts) { | ||
| 851 | dma_free_coherent(trans->dev, | ||
| 852 | rb_stts_size * trans->num_rx_queues, | ||
| 853 | trans_pcie->base_rb_stts, | ||
| 854 | trans_pcie->base_rb_stts_dma); | ||
| 855 | trans_pcie->base_rb_stts = NULL; | ||
| 856 | trans_pcie->base_rb_stts_dma = 0; | ||
| 857 | } | ||
| 858 | kfree(trans_pcie->rxq); | ||
| 859 | |||
| 860 | return ret; | ||
| 831 | } | 861 | } |
| 832 | 862 | ||
| 833 | static void iwl_pcie_rx_hw_init(struct iwl_trans *trans, struct iwl_rxq *rxq) | 863 | static void iwl_pcie_rx_hw_init(struct iwl_trans *trans, struct iwl_rxq *rxq) |
| @@ -1036,8 +1066,6 @@ int _iwl_pcie_rx_init(struct iwl_trans *trans) | |||
| 1036 | for (i = 0; i < trans->num_rx_queues; i++) { | 1066 | for (i = 0; i < trans->num_rx_queues; i++) { |
| 1037 | struct iwl_rxq *rxq = &trans_pcie->rxq[i]; | 1067 | struct iwl_rxq *rxq = &trans_pcie->rxq[i]; |
| 1038 | 1068 | ||
| 1039 | rxq->id = i; | ||
| 1040 | |||
| 1041 | spin_lock(&rxq->lock); | 1069 | spin_lock(&rxq->lock); |
| 1042 | /* | 1070 | /* |
| 1043 | * Set read write pointer to reflect that we have processed | 1071 | * Set read write pointer to reflect that we have processed |
| @@ -1124,6 +1152,9 @@ void iwl_pcie_rx_free(struct iwl_trans *trans) | |||
| 1124 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 1152 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
| 1125 | struct iwl_rb_allocator *rba = &trans_pcie->rba; | 1153 | struct iwl_rb_allocator *rba = &trans_pcie->rba; |
| 1126 | int i; | 1154 | int i; |
| 1155 | size_t rb_stts_size = trans->cfg->device_family >= | ||
| 1156 | IWL_DEVICE_FAMILY_22560 ? | ||
| 1157 | sizeof(__le16) : sizeof(struct iwl_rb_status); | ||
| 1127 | 1158 | ||
| 1128 | /* | 1159 | /* |
| 1129 | * if rxq is NULL, it means that nothing has been allocated, | 1160 | * if rxq is NULL, it means that nothing has been allocated, |
| @@ -1138,6 +1169,15 @@ void iwl_pcie_rx_free(struct iwl_trans *trans) | |||
| 1138 | 1169 | ||
| 1139 | iwl_pcie_free_rbs_pool(trans); | 1170 | iwl_pcie_free_rbs_pool(trans); |
| 1140 | 1171 | ||
| 1172 | if (trans_pcie->base_rb_stts) { | ||
| 1173 | dma_free_coherent(trans->dev, | ||
| 1174 | rb_stts_size * trans->num_rx_queues, | ||
| 1175 | trans_pcie->base_rb_stts, | ||
| 1176 | trans_pcie->base_rb_stts_dma); | ||
| 1177 | trans_pcie->base_rb_stts = NULL; | ||
| 1178 | trans_pcie->base_rb_stts_dma = 0; | ||
| 1179 | } | ||
| 1180 | |||
| 1141 | for (i = 0; i < trans->num_rx_queues; i++) { | 1181 | for (i = 0; i < trans->num_rx_queues; i++) { |
| 1142 | struct iwl_rxq *rxq = &trans_pcie->rxq[i]; | 1182 | struct iwl_rxq *rxq = &trans_pcie->rxq[i]; |
| 1143 | 1183 | ||
| @@ -1424,6 +1464,9 @@ restart: | |||
| 1424 | !emergency)) { | 1464 | !emergency)) { |
| 1425 | iwl_pcie_rx_move_to_allocator(rxq, rba); | 1465 | iwl_pcie_rx_move_to_allocator(rxq, rba); |
| 1426 | emergency = true; | 1466 | emergency = true; |
| 1467 | IWL_DEBUG_TPT(trans, | ||
| 1468 | "RX path is in emergency. Pending allocations %d\n", | ||
| 1469 | rb_pending_alloc); | ||
| 1427 | } | 1470 | } |
| 1428 | 1471 | ||
| 1429 | IWL_DEBUG_RX(trans, "Q %d: HW = %d, SW = %d\n", rxq->id, r, i); | 1472 | IWL_DEBUG_RX(trans, "Q %d: HW = %d, SW = %d\n", rxq->id, r, i); |
| @@ -1453,8 +1496,12 @@ restart: | |||
| 1453 | count++; | 1496 | count++; |
| 1454 | if (count == 8) { | 1497 | if (count == 8) { |
| 1455 | count = 0; | 1498 | count = 0; |
| 1456 | if (rb_pending_alloc < rxq->queue_size / 3) | 1499 | if (rb_pending_alloc < rxq->queue_size / 3) { |
| 1500 | IWL_DEBUG_TPT(trans, | ||
| 1501 | "RX path exited emergency. Pending allocations %d\n", | ||
| 1502 | rb_pending_alloc); | ||
| 1457 | emergency = false; | 1503 | emergency = false; |
| 1504 | } | ||
| 1458 | 1505 | ||
| 1459 | rxq->read = i; | 1506 | rxq->read = i; |
| 1460 | spin_unlock(&rxq->lock); | 1507 | spin_unlock(&rxq->lock); |
| @@ -2120,7 +2167,7 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id) | |||
| 2120 | } | 2167 | } |
| 2121 | } | 2168 | } |
| 2122 | 2169 | ||
| 2123 | if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560 && | 2170 | if (trans->cfg->device_family == IWL_DEVICE_FAMILY_22560 && |
| 2124 | inta_hw & MSIX_HW_INT_CAUSES_REG_IPC) { | 2171 | inta_hw & MSIX_HW_INT_CAUSES_REG_IPC) { |
| 2125 | /* Reflect IML transfer status */ | 2172 | /* Reflect IML transfer status */ |
| 2126 | int res = iwl_read32(trans, CSR_IML_RESP_ADDR); | 2173 | int res = iwl_read32(trans, CSR_IML_RESP_ADDR); |
| @@ -2139,6 +2186,17 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id) | |||
| 2139 | isr_stats->wakeup++; | 2186 | isr_stats->wakeup++; |
| 2140 | } | 2187 | } |
| 2141 | 2188 | ||
| 2189 | if (inta_hw & MSIX_HW_INT_CAUSES_REG_IML) { | ||
| 2190 | /* Reflect IML transfer status */ | ||
| 2191 | int res = iwl_read32(trans, CSR_IML_RESP_ADDR); | ||
| 2192 | |||
| 2193 | IWL_DEBUG_ISR(trans, "IML transfer status: %d\n", res); | ||
| 2194 | if (res == IWL_IMAGE_RESP_FAIL) { | ||
| 2195 | isr_stats->sw++; | ||
| 2196 | iwl_pcie_irq_handle_error(trans); | ||
| 2197 | } | ||
| 2198 | } | ||
| 2199 | |||
| 2142 | /* Chip got too hot and stopped itself */ | 2200 | /* Chip got too hot and stopped itself */ |
| 2143 | if (inta_hw & MSIX_HW_INT_CAUSES_REG_CT_KILL) { | 2201 | if (inta_hw & MSIX_HW_INT_CAUSES_REG_CT_KILL) { |
| 2144 | IWL_ERR(trans, "Microcode CT kill error detected.\n"); | 2202 | IWL_ERR(trans, "Microcode CT kill error detected.\n"); |
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c index 77f3610e5ca9..9c203ca75de9 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c | |||
| @@ -92,26 +92,9 @@ int iwl_pcie_gen2_apm_init(struct iwl_trans *trans) | |||
| 92 | 92 | ||
| 93 | iwl_pcie_apm_config(trans); | 93 | iwl_pcie_apm_config(trans); |
| 94 | 94 | ||
| 95 | /* | 95 | ret = iwl_finish_nic_init(trans); |
| 96 | * Set "initialization complete" bit to move adapter from | 96 | if (ret) |
| 97 | * D0U* --> D0A* (powered-up active) state. | ||
| 98 | */ | ||
| 99 | iwl_set_bit(trans, CSR_GP_CNTRL, | ||
| 100 | BIT(trans->cfg->csr->flag_init_done)); | ||
| 101 | |||
| 102 | /* | ||
| 103 | * Wait for clock stabilization; once stabilized, access to | ||
| 104 | * device-internal resources is supported, e.g. iwl_write_prph() | ||
| 105 | * and accesses to uCode SRAM. | ||
| 106 | */ | ||
| 107 | ret = iwl_poll_bit(trans, CSR_GP_CNTRL, | ||
| 108 | BIT(trans->cfg->csr->flag_mac_clock_ready), | ||
| 109 | BIT(trans->cfg->csr->flag_mac_clock_ready), | ||
| 110 | 25000); | ||
| 111 | if (ret < 0) { | ||
| 112 | IWL_DEBUG_INFO(trans, "Failed to init the card\n"); | ||
| 113 | return ret; | 97 | return ret; |
| 114 | } | ||
| 115 | 98 | ||
| 116 | set_bit(STATUS_DEVICE_ENABLED, &trans->status); | 99 | set_bit(STATUS_DEVICE_ENABLED, &trans->status); |
| 117 | 100 | ||
| @@ -188,7 +171,7 @@ void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans, bool low_power) | |||
| 188 | } | 171 | } |
| 189 | 172 | ||
| 190 | iwl_pcie_ctxt_info_free_paging(trans); | 173 | iwl_pcie_ctxt_info_free_paging(trans); |
| 191 | if (trans->cfg->device_family == IWL_DEVICE_FAMILY_22560) | 174 | if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) |
| 192 | iwl_pcie_ctxt_info_gen3_free(trans); | 175 | iwl_pcie_ctxt_info_gen3_free(trans); |
| 193 | else | 176 | else |
| 194 | iwl_pcie_ctxt_info_free(trans); | 177 | iwl_pcie_ctxt_info_free(trans); |
| @@ -251,6 +234,7 @@ void iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans, bool low_power) | |||
| 251 | static int iwl_pcie_gen2_nic_init(struct iwl_trans *trans) | 234 | static int iwl_pcie_gen2_nic_init(struct iwl_trans *trans) |
| 252 | { | 235 | { |
| 253 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 236 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
| 237 | int queue_size = max_t(u32, TFD_CMD_SLOTS, trans->cfg->min_txq_size); | ||
| 254 | 238 | ||
| 255 | /* TODO: most of the logic can be removed in A0 - but not in Z0 */ | 239 | /* TODO: most of the logic can be removed in A0 - but not in Z0 */ |
| 256 | spin_lock(&trans_pcie->irq_lock); | 240 | spin_lock(&trans_pcie->irq_lock); |
| @@ -264,7 +248,7 @@ static int iwl_pcie_gen2_nic_init(struct iwl_trans *trans) | |||
| 264 | return -ENOMEM; | 248 | return -ENOMEM; |
| 265 | 249 | ||
| 266 | /* Allocate or reset and init all Tx and Command queues */ | 250 | /* Allocate or reset and init all Tx and Command queues */ |
| 267 | if (iwl_pcie_gen2_tx_init(trans, trans_pcie->cmd_queue, TFD_CMD_SLOTS)) | 251 | if (iwl_pcie_gen2_tx_init(trans, trans_pcie->cmd_queue, queue_size)) |
| 268 | return -ENOMEM; | 252 | return -ENOMEM; |
| 269 | 253 | ||
| 270 | /* enable shadow regs in HW */ | 254 | /* enable shadow regs in HW */ |
| @@ -349,7 +333,7 @@ int iwl_trans_pcie_gen2_start_fw(struct iwl_trans *trans, | |||
| 349 | goto out; | 333 | goto out; |
| 350 | } | 334 | } |
| 351 | 335 | ||
| 352 | if (trans->cfg->device_family == IWL_DEVICE_FAMILY_22560) | 336 | if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) |
| 353 | ret = iwl_pcie_ctxt_info_gen3_init(trans, fw); | 337 | ret = iwl_pcie_ctxt_info_gen3_init(trans, fw); |
| 354 | else | 338 | else |
| 355 | ret = iwl_pcie_ctxt_info_init(trans, fw); | 339 | ret = iwl_pcie_ctxt_info_init(trans, fw); |
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index f74281508197..fe8269d023de 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | * Copyright(c) 2007 - 2015 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2007 - 2015 Intel Corporation. All rights reserved. |
| 9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
| 10 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH | 10 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH |
| 11 | * Copyright(c) 2018 Intel Corporation | 11 | * Copyright(c) 2018 - 2019 Intel Corporation |
| 12 | * | 12 | * |
| 13 | * This program is free software; you can redistribute it and/or modify | 13 | * This program is free software; you can redistribute it and/or modify |
| 14 | * it under the terms of version 2 of the GNU General Public License as | 14 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -31,7 +31,7 @@ | |||
| 31 | * Copyright(c) 2005 - 2015 Intel Corporation. All rights reserved. | 31 | * Copyright(c) 2005 - 2015 Intel Corporation. All rights reserved. |
| 32 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 32 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
| 33 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH | 33 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH |
| 34 | * Copyright(c) 2018 Intel Corporation | 34 | * Copyright(c) 2018 - 2019 Intel Corporation |
| 35 | * All rights reserved. | 35 | * All rights reserved. |
| 36 | * | 36 | * |
| 37 | * Redistribution and use in source and binary forms, with or without | 37 | * Redistribution and use in source and binary forms, with or without |
| @@ -364,26 +364,9 @@ static int iwl_pcie_apm_init(struct iwl_trans *trans) | |||
| 364 | if (trans->cfg->base_params->pll_cfg) | 364 | if (trans->cfg->base_params->pll_cfg) |
| 365 | iwl_set_bit(trans, CSR_ANA_PLL_CFG, CSR50_ANA_PLL_CFG_VAL); | 365 | iwl_set_bit(trans, CSR_ANA_PLL_CFG, CSR50_ANA_PLL_CFG_VAL); |
| 366 | 366 | ||
| 367 | /* | 367 | ret = iwl_finish_nic_init(trans); |
| 368 | * Set "initialization complete" bit to move adapter from | 368 | if (ret) |
| 369 | * D0U* --> D0A* (powered-up active) state. | ||
| 370 | */ | ||
| 371 | iwl_set_bit(trans, CSR_GP_CNTRL, | ||
| 372 | BIT(trans->cfg->csr->flag_init_done)); | ||
| 373 | |||
| 374 | /* | ||
| 375 | * Wait for clock stabilization; once stabilized, access to | ||
| 376 | * device-internal resources is supported, e.g. iwl_write_prph() | ||
| 377 | * and accesses to uCode SRAM. | ||
| 378 | */ | ||
| 379 | ret = iwl_poll_bit(trans, CSR_GP_CNTRL, | ||
| 380 | BIT(trans->cfg->csr->flag_mac_clock_ready), | ||
| 381 | BIT(trans->cfg->csr->flag_mac_clock_ready), | ||
| 382 | 25000); | ||
| 383 | if (ret < 0) { | ||
| 384 | IWL_ERR(trans, "Failed to init the card\n"); | ||
| 385 | return ret; | 369 | return ret; |
| 386 | } | ||
| 387 | 370 | ||
| 388 | if (trans->cfg->host_interrupt_operation_mode) { | 371 | if (trans->cfg->host_interrupt_operation_mode) { |
| 389 | /* | 372 | /* |
| @@ -453,23 +436,8 @@ static void iwl_pcie_apm_lp_xtal_enable(struct iwl_trans *trans) | |||
| 453 | 436 | ||
| 454 | iwl_trans_pcie_sw_reset(trans); | 437 | iwl_trans_pcie_sw_reset(trans); |
| 455 | 438 | ||
| 456 | /* | 439 | ret = iwl_finish_nic_init(trans); |
| 457 | * Set "initialization complete" bit to move adapter from | 440 | if (WARN_ON(ret)) { |
| 458 | * D0U* --> D0A* (powered-up active) state. | ||
| 459 | */ | ||
| 460 | iwl_set_bit(trans, CSR_GP_CNTRL, | ||
| 461 | BIT(trans->cfg->csr->flag_init_done)); | ||
| 462 | |||
| 463 | /* | ||
| 464 | * Wait for clock stabilization; once stabilized, access to | ||
| 465 | * device-internal resources is possible. | ||
| 466 | */ | ||
| 467 | ret = iwl_poll_bit(trans, CSR_GP_CNTRL, | ||
| 468 | BIT(trans->cfg->csr->flag_mac_clock_ready), | ||
| 469 | BIT(trans->cfg->csr->flag_mac_clock_ready), | ||
| 470 | 25000); | ||
| 471 | if (WARN_ON(ret < 0)) { | ||
| 472 | IWL_ERR(trans, "Access time out - failed to enable LP XTAL\n"); | ||
| 473 | /* Release XTAL ON request */ | 441 | /* Release XTAL ON request */ |
| 474 | __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL, | 442 | __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL, |
| 475 | CSR_GP_CNTRL_REG_FLAG_XTAL_ON); | 443 | CSR_GP_CNTRL_REG_FLAG_XTAL_ON); |
| @@ -928,13 +896,13 @@ void iwl_pcie_apply_destination(struct iwl_trans *trans) | |||
| 928 | if (!trans->num_blocks) | 896 | if (!trans->num_blocks) |
| 929 | return; | 897 | return; |
| 930 | 898 | ||
| 931 | iwl_write_prph(trans, MON_BUFF_BASE_ADDR_VER2, | 899 | iwl_write_umac_prph(trans, MON_BUFF_BASE_ADDR_VER2, |
| 932 | trans->fw_mon[0].physical >> | 900 | trans->fw_mon[0].physical >> |
| 933 | MON_BUFF_SHIFT_VER2); | 901 | MON_BUFF_SHIFT_VER2); |
| 934 | iwl_write_prph(trans, MON_BUFF_END_ADDR_VER2, | 902 | iwl_write_umac_prph(trans, MON_BUFF_END_ADDR_VER2, |
| 935 | (trans->fw_mon[0].physical + | 903 | (trans->fw_mon[0].physical + |
| 936 | trans->fw_mon[0].size - 256) >> | 904 | trans->fw_mon[0].size - 256) >> |
| 937 | MON_BUFF_SHIFT_VER2); | 905 | MON_BUFF_SHIFT_VER2); |
| 938 | return; | 906 | return; |
| 939 | } | 907 | } |
| 940 | 908 | ||
| @@ -1126,6 +1094,7 @@ static struct iwl_causes_list causes_list[] = { | |||
| 1126 | {MSIX_FH_INT_CAUSES_FH_ERR, CSR_MSIX_FH_INT_MASK_AD, 0x5}, | 1094 | {MSIX_FH_INT_CAUSES_FH_ERR, CSR_MSIX_FH_INT_MASK_AD, 0x5}, |
| 1127 | {MSIX_HW_INT_CAUSES_REG_ALIVE, CSR_MSIX_HW_INT_MASK_AD, 0x10}, | 1095 | {MSIX_HW_INT_CAUSES_REG_ALIVE, CSR_MSIX_HW_INT_MASK_AD, 0x10}, |
| 1128 | {MSIX_HW_INT_CAUSES_REG_WAKEUP, CSR_MSIX_HW_INT_MASK_AD, 0x11}, | 1096 | {MSIX_HW_INT_CAUSES_REG_WAKEUP, CSR_MSIX_HW_INT_MASK_AD, 0x11}, |
| 1097 | {MSIX_HW_INT_CAUSES_REG_IML, CSR_MSIX_HW_INT_MASK_AD, 0x12}, | ||
| 1129 | {MSIX_HW_INT_CAUSES_REG_CT_KILL, CSR_MSIX_HW_INT_MASK_AD, 0x16}, | 1098 | {MSIX_HW_INT_CAUSES_REG_CT_KILL, CSR_MSIX_HW_INT_MASK_AD, 0x16}, |
| 1130 | {MSIX_HW_INT_CAUSES_REG_RF_KILL, CSR_MSIX_HW_INT_MASK_AD, 0x17}, | 1099 | {MSIX_HW_INT_CAUSES_REG_RF_KILL, CSR_MSIX_HW_INT_MASK_AD, 0x17}, |
| 1131 | {MSIX_HW_INT_CAUSES_REG_PERIODIC, CSR_MSIX_HW_INT_MASK_AD, 0x18}, | 1100 | {MSIX_HW_INT_CAUSES_REG_PERIODIC, CSR_MSIX_HW_INT_MASK_AD, 0x18}, |
| @@ -1158,7 +1127,7 @@ static void iwl_pcie_map_non_rx_causes(struct iwl_trans *trans) | |||
| 1158 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 1127 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
| 1159 | int val = trans_pcie->def_irq | MSIX_NON_AUTO_CLEAR_CAUSE; | 1128 | int val = trans_pcie->def_irq | MSIX_NON_AUTO_CLEAR_CAUSE; |
| 1160 | int i, arr_size = | 1129 | int i, arr_size = |
| 1161 | (trans->cfg->device_family < IWL_DEVICE_FAMILY_22560) ? | 1130 | (trans->cfg->device_family != IWL_DEVICE_FAMILY_22560) ? |
| 1162 | ARRAY_SIZE(causes_list) : ARRAY_SIZE(causes_list_v2); | 1131 | ARRAY_SIZE(causes_list) : ARRAY_SIZE(causes_list_v2); |
| 1163 | 1132 | ||
| 1164 | /* | 1133 | /* |
| @@ -1168,7 +1137,7 @@ static void iwl_pcie_map_non_rx_causes(struct iwl_trans *trans) | |||
| 1168 | */ | 1137 | */ |
| 1169 | for (i = 0; i < arr_size; i++) { | 1138 | for (i = 0; i < arr_size; i++) { |
| 1170 | struct iwl_causes_list *causes = | 1139 | struct iwl_causes_list *causes = |
| 1171 | (trans->cfg->device_family < IWL_DEVICE_FAMILY_22560) ? | 1140 | (trans->cfg->device_family != IWL_DEVICE_FAMILY_22560) ? |
| 1172 | causes_list : causes_list_v2; | 1141 | causes_list : causes_list_v2; |
| 1173 | 1142 | ||
| 1174 | iwl_write8(trans, CSR_MSIX_IVAR(causes[i].addr), val); | 1143 | iwl_write8(trans, CSR_MSIX_IVAR(causes[i].addr), val); |
| @@ -1214,8 +1183,8 @@ void iwl_pcie_conf_msix_hw(struct iwl_trans_pcie *trans_pcie) | |||
| 1214 | if (!trans_pcie->msix_enabled) { | 1183 | if (!trans_pcie->msix_enabled) { |
| 1215 | if (trans->cfg->mq_rx_supported && | 1184 | if (trans->cfg->mq_rx_supported && |
| 1216 | test_bit(STATUS_DEVICE_ENABLED, &trans->status)) | 1185 | test_bit(STATUS_DEVICE_ENABLED, &trans->status)) |
| 1217 | iwl_write_prph(trans, UREG_CHICK, | 1186 | iwl_write_umac_prph(trans, UREG_CHICK, |
| 1218 | UREG_CHICK_MSI_ENABLE); | 1187 | UREG_CHICK_MSI_ENABLE); |
| 1219 | return; | 1188 | return; |
| 1220 | } | 1189 | } |
| 1221 | /* | 1190 | /* |
| @@ -1224,7 +1193,7 @@ void iwl_pcie_conf_msix_hw(struct iwl_trans_pcie *trans_pcie) | |||
| 1224 | * prph. | 1193 | * prph. |
| 1225 | */ | 1194 | */ |
| 1226 | if (test_bit(STATUS_DEVICE_ENABLED, &trans->status)) | 1195 | if (test_bit(STATUS_DEVICE_ENABLED, &trans->status)) |
| 1227 | iwl_write_prph(trans, UREG_CHICK, UREG_CHICK_MSIX_ENABLE); | 1196 | iwl_write_umac_prph(trans, UREG_CHICK, UREG_CHICK_MSIX_ENABLE); |
| 1228 | 1197 | ||
| 1229 | /* | 1198 | /* |
| 1230 | * Each cause from the causes list above and the RX causes is | 1199 | * Each cause from the causes list above and the RX causes is |
| @@ -1558,20 +1527,10 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans, | |||
| 1558 | 1527 | ||
| 1559 | iwl_set_bit(trans, CSR_GP_CNTRL, | 1528 | iwl_set_bit(trans, CSR_GP_CNTRL, |
| 1560 | BIT(trans->cfg->csr->flag_mac_access_req)); | 1529 | BIT(trans->cfg->csr->flag_mac_access_req)); |
| 1561 | iwl_set_bit(trans, CSR_GP_CNTRL, | ||
| 1562 | BIT(trans->cfg->csr->flag_init_done)); | ||
| 1563 | |||
| 1564 | if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_8000) | ||
| 1565 | udelay(2); | ||
| 1566 | 1530 | ||
| 1567 | ret = iwl_poll_bit(trans, CSR_GP_CNTRL, | 1531 | ret = iwl_finish_nic_init(trans); |
| 1568 | BIT(trans->cfg->csr->flag_mac_clock_ready), | 1532 | if (ret) |
| 1569 | BIT(trans->cfg->csr->flag_mac_clock_ready), | ||
| 1570 | 25000); | ||
| 1571 | if (ret < 0) { | ||
| 1572 | IWL_ERR(trans, "Failed to resume the device (mac ready)\n"); | ||
| 1573 | return ret; | 1533 | return ret; |
| 1574 | } | ||
| 1575 | 1534 | ||
| 1576 | /* | 1535 | /* |
| 1577 | * Reconfigure IVAR table in case of MSIX or reset ict table in | 1536 | * Reconfigure IVAR table in case of MSIX or reset ict table in |
| @@ -1602,7 +1561,7 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans, | |||
| 1602 | } | 1561 | } |
| 1603 | 1562 | ||
| 1604 | IWL_DEBUG_POWER(trans, "WFPM value upon resume = 0x%08X\n", | 1563 | IWL_DEBUG_POWER(trans, "WFPM value upon resume = 0x%08X\n", |
| 1605 | iwl_read_prph(trans, WFPM_GP2)); | 1564 | iwl_read_umac_prph(trans, WFPM_GP2)); |
| 1606 | 1565 | ||
| 1607 | val = iwl_read32(trans, CSR_RESET); | 1566 | val = iwl_read32(trans, CSR_RESET); |
| 1608 | if (val & CSR_RESET_REG_FLAG_NEVO_RESET) | 1567 | if (val & CSR_RESET_REG_FLAG_NEVO_RESET) |
| @@ -1751,15 +1710,18 @@ static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans, bool low_power) | |||
| 1751 | return err; | 1710 | return err; |
| 1752 | } | 1711 | } |
| 1753 | 1712 | ||
| 1754 | hpm = iwl_trans_read_prph(trans, HPM_DEBUG); | 1713 | hpm = iwl_read_umac_prph_no_grab(trans, HPM_DEBUG); |
| 1755 | if (hpm != 0xa5a5a5a0 && (hpm & PERSISTENCE_BIT)) { | 1714 | if (hpm != 0xa5a5a5a0 && (hpm & PERSISTENCE_BIT)) { |
| 1756 | if (iwl_trans_read_prph(trans, PREG_PRPH_WPROT_0) & | 1715 | int wfpm_val = iwl_read_umac_prph_no_grab(trans, |
| 1757 | PREG_WFPM_ACCESS) { | 1716 | PREG_PRPH_WPROT_0); |
| 1717 | |||
| 1718 | if (wfpm_val & PREG_WFPM_ACCESS) { | ||
| 1758 | IWL_ERR(trans, | 1719 | IWL_ERR(trans, |
| 1759 | "Error, can not clear persistence bit\n"); | 1720 | "Error, can not clear persistence bit\n"); |
| 1760 | return -EPERM; | 1721 | return -EPERM; |
| 1761 | } | 1722 | } |
| 1762 | iwl_trans_write_prph(trans, HPM_DEBUG, hpm & ~PERSISTENCE_BIT); | 1723 | iwl_write_umac_prph_no_grab(trans, HPM_DEBUG, |
| 1724 | hpm & ~PERSISTENCE_BIT); | ||
| 1763 | } | 1725 | } |
| 1764 | 1726 | ||
| 1765 | iwl_trans_pcie_sw_reset(trans); | 1727 | iwl_trans_pcie_sw_reset(trans); |
| @@ -2281,6 +2243,7 @@ static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans, int txq_idx) | |||
| 2281 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 2243 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
| 2282 | struct iwl_txq *txq; | 2244 | struct iwl_txq *txq; |
| 2283 | unsigned long now = jiffies; | 2245 | unsigned long now = jiffies; |
| 2246 | bool overflow_tx; | ||
| 2284 | u8 wr_ptr; | 2247 | u8 wr_ptr; |
| 2285 | 2248 | ||
| 2286 | /* Make sure the NIC is still alive in the bus */ | 2249 | /* Make sure the NIC is still alive in the bus */ |
| @@ -2292,18 +2255,37 @@ static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans, int txq_idx) | |||
| 2292 | 2255 | ||
| 2293 | IWL_DEBUG_TX_QUEUES(trans, "Emptying queue %d...\n", txq_idx); | 2256 | IWL_DEBUG_TX_QUEUES(trans, "Emptying queue %d...\n", txq_idx); |
| 2294 | txq = trans_pcie->txq[txq_idx]; | 2257 | txq = trans_pcie->txq[txq_idx]; |
| 2258 | |||
| 2259 | spin_lock_bh(&txq->lock); | ||
| 2260 | overflow_tx = txq->overflow_tx || | ||
| 2261 | !skb_queue_empty(&txq->overflow_q); | ||
| 2262 | spin_unlock_bh(&txq->lock); | ||
| 2263 | |||
| 2295 | wr_ptr = READ_ONCE(txq->write_ptr); | 2264 | wr_ptr = READ_ONCE(txq->write_ptr); |
| 2296 | 2265 | ||
| 2297 | while (txq->read_ptr != READ_ONCE(txq->write_ptr) && | 2266 | while ((txq->read_ptr != READ_ONCE(txq->write_ptr) || |
| 2267 | overflow_tx) && | ||
| 2298 | !time_after(jiffies, | 2268 | !time_after(jiffies, |
| 2299 | now + msecs_to_jiffies(IWL_FLUSH_WAIT_MS))) { | 2269 | now + msecs_to_jiffies(IWL_FLUSH_WAIT_MS))) { |
| 2300 | u8 write_ptr = READ_ONCE(txq->write_ptr); | 2270 | u8 write_ptr = READ_ONCE(txq->write_ptr); |
| 2301 | 2271 | ||
| 2302 | if (WARN_ONCE(wr_ptr != write_ptr, | 2272 | /* |
| 2273 | * If write pointer moved during the wait, warn only | ||
| 2274 | * if the TX came from op mode. In case TX came from | ||
| 2275 | * trans layer (overflow TX) don't warn. | ||
| 2276 | */ | ||
| 2277 | if (WARN_ONCE(wr_ptr != write_ptr && !overflow_tx, | ||
| 2303 | "WR pointer moved while flushing %d -> %d\n", | 2278 | "WR pointer moved while flushing %d -> %d\n", |
| 2304 | wr_ptr, write_ptr)) | 2279 | wr_ptr, write_ptr)) |
| 2305 | return -ETIMEDOUT; | 2280 | return -ETIMEDOUT; |
| 2281 | wr_ptr = write_ptr; | ||
| 2282 | |||
| 2306 | usleep_range(1000, 2000); | 2283 | usleep_range(1000, 2000); |
| 2284 | |||
| 2285 | spin_lock_bh(&txq->lock); | ||
| 2286 | overflow_tx = txq->overflow_tx || | ||
| 2287 | !skb_queue_empty(&txq->overflow_q); | ||
| 2288 | spin_unlock_bh(&txq->lock); | ||
| 2307 | } | 2289 | } |
| 2308 | 2290 | ||
| 2309 | if (txq->read_ptr != txq->write_ptr) { | 2291 | if (txq->read_ptr != txq->write_ptr) { |
| @@ -2989,7 +2971,8 @@ static u32 iwl_trans_pcie_fh_regs_dump(struct iwl_trans *trans, | |||
| 2989 | i += sizeof(u32)) | 2971 | i += sizeof(u32)) |
| 2990 | *val++ = cpu_to_le32(iwl_trans_pcie_read32(trans, i)); | 2972 | *val++ = cpu_to_le32(iwl_trans_pcie_read32(trans, i)); |
| 2991 | else | 2973 | else |
| 2992 | for (i = FH_MEM_LOWER_BOUND_GEN2; i < FH_MEM_UPPER_BOUND_GEN2; | 2974 | for (i = iwl_umac_prph(trans, FH_MEM_LOWER_BOUND_GEN2); |
| 2975 | i < iwl_umac_prph(trans, FH_MEM_UPPER_BOUND_GEN2); | ||
| 2993 | i += sizeof(u32)) | 2976 | i += sizeof(u32)) |
| 2994 | *val++ = cpu_to_le32(iwl_trans_pcie_read_prph(trans, | 2977 | *val++ = cpu_to_le32(iwl_trans_pcie_read_prph(trans, |
| 2995 | i)); | 2978 | i)); |
| @@ -3014,11 +2997,11 @@ iwl_trans_pci_dump_marbh_monitor(struct iwl_trans *trans, | |||
| 3014 | if (!iwl_trans_grab_nic_access(trans, &flags)) | 2997 | if (!iwl_trans_grab_nic_access(trans, &flags)) |
| 3015 | return 0; | 2998 | return 0; |
| 3016 | 2999 | ||
| 3017 | iwl_write_prph_no_grab(trans, MON_DMARB_RD_CTL_ADDR, 0x1); | 3000 | iwl_write_umac_prph_no_grab(trans, MON_DMARB_RD_CTL_ADDR, 0x1); |
| 3018 | for (i = 0; i < buf_size_in_dwords; i++) | 3001 | for (i = 0; i < buf_size_in_dwords; i++) |
| 3019 | buffer[i] = iwl_read_prph_no_grab(trans, | 3002 | buffer[i] = iwl_read_umac_prph_no_grab(trans, |
| 3020 | MON_DMARB_RD_DATA_ADDR); | 3003 | MON_DMARB_RD_DATA_ADDR); |
| 3021 | iwl_write_prph_no_grab(trans, MON_DMARB_RD_CTL_ADDR, 0x0); | 3004 | iwl_write_umac_prph_no_grab(trans, MON_DMARB_RD_CTL_ADDR, 0x0); |
| 3022 | 3005 | ||
| 3023 | iwl_trans_release_nic_access(trans, &flags); | 3006 | iwl_trans_release_nic_access(trans, &flags); |
| 3024 | 3007 | ||
| @@ -3033,9 +3016,9 @@ iwl_trans_pcie_dump_pointers(struct iwl_trans *trans, | |||
| 3033 | 3016 | ||
| 3034 | /* If there was a dest TLV - use the values from there */ | 3017 | /* If there was a dest TLV - use the values from there */ |
| 3035 | if (trans->ini_valid) { | 3018 | if (trans->ini_valid) { |
| 3036 | base = MON_BUFF_BASE_ADDR_VER2; | 3019 | base = iwl_umac_prph(trans, MON_BUFF_BASE_ADDR_VER2); |
| 3037 | write_ptr = MON_BUFF_WRPTR_VER2; | 3020 | write_ptr = iwl_umac_prph(trans, MON_BUFF_WRPTR_VER2); |
| 3038 | wrap_cnt = MON_BUFF_CYCLE_CNT_VER2; | 3021 | wrap_cnt = iwl_umac_prph(trans, MON_BUFF_CYCLE_CNT_VER2); |
| 3039 | } else if (trans->dbg_dest_tlv) { | 3022 | } else if (trans->dbg_dest_tlv) { |
| 3040 | write_ptr = le32_to_cpu(trans->dbg_dest_tlv->write_ptr_reg); | 3023 | write_ptr = le32_to_cpu(trans->dbg_dest_tlv->write_ptr_reg); |
| 3041 | wrap_cnt = le32_to_cpu(trans->dbg_dest_tlv->wrap_count); | 3024 | wrap_cnt = le32_to_cpu(trans->dbg_dest_tlv->wrap_count); |
| @@ -3197,8 +3180,8 @@ static struct iwl_trans_dump_data | |||
| 3197 | if (dump_mask & BIT(IWL_FW_ERROR_DUMP_FH_REGS)) { | 3180 | if (dump_mask & BIT(IWL_FW_ERROR_DUMP_FH_REGS)) { |
| 3198 | if (trans->cfg->gen2) | 3181 | if (trans->cfg->gen2) |
| 3199 | len += sizeof(*data) + | 3182 | len += sizeof(*data) + |
| 3200 | (FH_MEM_UPPER_BOUND_GEN2 - | 3183 | (iwl_umac_prph(trans, FH_MEM_UPPER_BOUND_GEN2) - |
| 3201 | FH_MEM_LOWER_BOUND_GEN2); | 3184 | iwl_umac_prph(trans, FH_MEM_LOWER_BOUND_GEN2)); |
| 3202 | else | 3185 | else |
| 3203 | len += sizeof(*data) + | 3186 | len += sizeof(*data) + |
| 3204 | (FH_MEM_UPPER_BOUND - | 3187 | (FH_MEM_UPPER_BOUND - |
| @@ -3220,10 +3203,10 @@ static struct iwl_trans_dump_data | |||
| 3220 | 3203 | ||
| 3221 | /* Paged memory for gen2 HW */ | 3204 | /* Paged memory for gen2 HW */ |
| 3222 | if (trans->cfg->gen2 && dump_mask & BIT(IWL_FW_ERROR_DUMP_PAGING)) | 3205 | if (trans->cfg->gen2 && dump_mask & BIT(IWL_FW_ERROR_DUMP_PAGING)) |
| 3223 | for (i = 0; i < trans_pcie->init_dram.paging_cnt; i++) | 3206 | for (i = 0; i < trans->init_dram.paging_cnt; i++) |
| 3224 | len += sizeof(*data) + | 3207 | len += sizeof(*data) + |
| 3225 | sizeof(struct iwl_fw_error_dump_paging) + | 3208 | sizeof(struct iwl_fw_error_dump_paging) + |
| 3226 | trans_pcie->init_dram.paging[i].size; | 3209 | trans->init_dram.paging[i].size; |
| 3227 | 3210 | ||
| 3228 | dump_data = vzalloc(len); | 3211 | dump_data = vzalloc(len); |
| 3229 | if (!dump_data) | 3212 | if (!dump_data) |
| @@ -3275,20 +3258,16 @@ static struct iwl_trans_dump_data | |||
| 3275 | 3258 | ||
| 3276 | /* Paged memory for gen2 HW */ | 3259 | /* Paged memory for gen2 HW */ |
| 3277 | if (trans->cfg->gen2 && dump_mask & BIT(IWL_FW_ERROR_DUMP_PAGING)) { | 3260 | if (trans->cfg->gen2 && dump_mask & BIT(IWL_FW_ERROR_DUMP_PAGING)) { |
| 3278 | for (i = 0; i < trans_pcie->init_dram.paging_cnt; i++) { | 3261 | for (i = 0; i < trans->init_dram.paging_cnt; i++) { |
| 3279 | struct iwl_fw_error_dump_paging *paging; | 3262 | struct iwl_fw_error_dump_paging *paging; |
| 3280 | dma_addr_t addr = | 3263 | u32 page_len = trans->init_dram.paging[i].size; |
| 3281 | trans_pcie->init_dram.paging[i].physical; | ||
| 3282 | u32 page_len = trans_pcie->init_dram.paging[i].size; | ||
| 3283 | 3264 | ||
| 3284 | data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PAGING); | 3265 | data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PAGING); |
| 3285 | data->len = cpu_to_le32(sizeof(*paging) + page_len); | 3266 | data->len = cpu_to_le32(sizeof(*paging) + page_len); |
| 3286 | paging = (void *)data->data; | 3267 | paging = (void *)data->data; |
| 3287 | paging->index = cpu_to_le32(i); | 3268 | paging->index = cpu_to_le32(i); |
| 3288 | dma_sync_single_for_cpu(trans->dev, addr, page_len, | ||
| 3289 | DMA_BIDIRECTIONAL); | ||
| 3290 | memcpy(paging->data, | 3269 | memcpy(paging->data, |
| 3291 | trans_pcie->init_dram.paging[i].block, page_len); | 3270 | trans->init_dram.paging[i].block, page_len); |
| 3292 | data = iwl_fw_error_next_data(data); | 3271 | data = iwl_fw_error_next_data(data); |
| 3293 | 3272 | ||
| 3294 | len += sizeof(*data) + sizeof(*paging) + page_len; | 3273 | len += sizeof(*data) + sizeof(*paging) + page_len; |
| @@ -3525,25 +3504,18 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, | |||
| 3525 | * in-order to recognize C step driver should read chip version | 3504 | * in-order to recognize C step driver should read chip version |
| 3526 | * id located at the AUX bus MISC address space. | 3505 | * id located at the AUX bus MISC address space. |
| 3527 | */ | 3506 | */ |
| 3528 | iwl_set_bit(trans, CSR_GP_CNTRL, | 3507 | ret = iwl_finish_nic_init(trans); |
| 3529 | BIT(trans->cfg->csr->flag_init_done)); | 3508 | if (ret) |
| 3530 | udelay(2); | ||
| 3531 | |||
| 3532 | ret = iwl_poll_bit(trans, CSR_GP_CNTRL, | ||
| 3533 | BIT(trans->cfg->csr->flag_mac_clock_ready), | ||
| 3534 | BIT(trans->cfg->csr->flag_mac_clock_ready), | ||
| 3535 | 25000); | ||
| 3536 | if (ret < 0) { | ||
| 3537 | IWL_DEBUG_INFO(trans, "Failed to wake up the nic\n"); | ||
| 3538 | goto out_no_pci; | 3509 | goto out_no_pci; |
| 3539 | } | ||
| 3540 | 3510 | ||
| 3541 | if (iwl_trans_grab_nic_access(trans, &flags)) { | 3511 | if (iwl_trans_grab_nic_access(trans, &flags)) { |
| 3542 | u32 hw_step; | 3512 | u32 hw_step; |
| 3543 | 3513 | ||
| 3544 | hw_step = iwl_read_prph_no_grab(trans, WFPM_CTRL_REG); | 3514 | hw_step = iwl_read_umac_prph_no_grab(trans, |
| 3515 | WFPM_CTRL_REG); | ||
| 3545 | hw_step |= ENABLE_WFPM; | 3516 | hw_step |= ENABLE_WFPM; |
| 3546 | iwl_write_prph_no_grab(trans, WFPM_CTRL_REG, hw_step); | 3517 | iwl_write_umac_prph_no_grab(trans, WFPM_CTRL_REG, |
| 3518 | hw_step); | ||
| 3547 | hw_step = iwl_read_prph_no_grab(trans, AUX_MISC_REG); | 3519 | hw_step = iwl_read_prph_no_grab(trans, AUX_MISC_REG); |
| 3548 | hw_step = (hw_step >> HW_STEP_LOCATION_BITS) & 0xF; | 3520 | hw_step = (hw_step >> HW_STEP_LOCATION_BITS) & 0xF; |
| 3549 | if (hw_step == 0x3) | 3521 | if (hw_step == 0x3) |
| @@ -3558,10 +3530,20 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, | |||
| 3558 | #if IS_ENABLED(CONFIG_IWLMVM) | 3530 | #if IS_ENABLED(CONFIG_IWLMVM) |
| 3559 | trans->hw_rf_id = iwl_read32(trans, CSR_HW_RF_ID); | 3531 | trans->hw_rf_id = iwl_read32(trans, CSR_HW_RF_ID); |
| 3560 | 3532 | ||
| 3561 | if (cfg == &iwl22560_2ax_cfg_hr) { | 3533 | if (cfg == &iwlax210_2ax_cfg_so_hr_a0) { |
| 3534 | if (trans->hw_rev == CSR_HW_REV_TYPE_TY) { | ||
| 3535 | trans->cfg = &iwlax210_2ax_cfg_ty_gf_a0; | ||
| 3536 | } else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) == | ||
| 3537 | CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_JF)) { | ||
| 3538 | trans->cfg = &iwlax210_2ax_cfg_so_jf_a0; | ||
| 3539 | } else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) == | ||
| 3540 | CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_GF)) { | ||
| 3541 | trans->cfg = &iwlax210_2ax_cfg_so_gf_a0; | ||
| 3542 | } | ||
| 3543 | } else if (cfg == &iwl_ax101_cfg_qu_hr) { | ||
| 3562 | if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) == | 3544 | if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) == |
| 3563 | CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR)) { | 3545 | CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR)) { |
| 3564 | trans->cfg = &iwl22560_2ax_cfg_hr; | 3546 | trans->cfg = &iwl_ax101_cfg_qu_hr; |
| 3565 | } else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) == | 3547 | } else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) == |
| 3566 | CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_JF)) { | 3548 | CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_JF)) { |
| 3567 | trans->cfg = &iwl22000_2ax_cfg_jf; | 3549 | trans->cfg = &iwl22000_2ax_cfg_jf; |
| @@ -3654,3 +3636,28 @@ out_no_pci: | |||
| 3654 | iwl_trans_free(trans); | 3636 | iwl_trans_free(trans); |
| 3655 | return ERR_PTR(ret); | 3637 | return ERR_PTR(ret); |
| 3656 | } | 3638 | } |
| 3639 | |||
| 3640 | void iwl_trans_sync_nmi(struct iwl_trans *trans) | ||
| 3641 | { | ||
| 3642 | unsigned long timeout = jiffies + IWL_TRANS_NMI_TIMEOUT; | ||
| 3643 | |||
| 3644 | iwl_disable_interrupts(trans); | ||
| 3645 | iwl_force_nmi(trans); | ||
| 3646 | while (time_after(timeout, jiffies)) { | ||
| 3647 | u32 inta_hw = iwl_read32(trans, | ||
| 3648 | CSR_MSIX_HW_INT_CAUSES_AD); | ||
| 3649 | |||
| 3650 | /* Error detected by uCode */ | ||
| 3651 | if (inta_hw & MSIX_HW_INT_CAUSES_REG_SW_ERR) { | ||
| 3652 | /* Clear causes register */ | ||
| 3653 | iwl_write32(trans, CSR_MSIX_HW_INT_CAUSES_AD, | ||
| 3654 | inta_hw & | ||
| 3655 | MSIX_HW_INT_CAUSES_REG_SW_ERR); | ||
| 3656 | break; | ||
| 3657 | } | ||
| 3658 | |||
| 3659 | mdelay(1); | ||
| 3660 | } | ||
| 3661 | iwl_enable_interrupts(trans); | ||
| 3662 | iwl_trans_fw_error(trans); | ||
| 3663 | } | ||
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c index f3d2e8fe920b..88530d9f4a54 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2017 Intel Deutschland GmbH | 8 | * Copyright(c) 2017 Intel Deutschland GmbH |
| 9 | * Copyright(c) 2018 Intel Corporation | 9 | * Copyright(c) 2018 - 2019 Intel Corporation |
| 10 | * | 10 | * |
| 11 | * This program is free software; you can redistribute it and/or modify | 11 | * 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 | 12 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -20,7 +20,7 @@ | |||
| 20 | * BSD LICENSE | 20 | * BSD LICENSE |
| 21 | * | 21 | * |
| 22 | * Copyright(c) 2017 Intel Deutschland GmbH | 22 | * Copyright(c) 2017 Intel Deutschland GmbH |
| 23 | * Copyright(c) 2018 Intel Corporation | 23 | * Copyright(c) 2018 - 2019 Intel Corporation |
| 24 | * All rights reserved. | 24 | * All rights reserved. |
| 25 | * | 25 | * |
| 26 | * Redistribution and use in source and binary forms, with or without | 26 | * Redistribution and use in source and binary forms, with or without |
| @@ -965,9 +965,7 @@ static int iwl_pcie_gen2_send_hcmd_sync(struct iwl_trans *trans, | |||
| 965 | cmd_str); | 965 | cmd_str); |
| 966 | ret = -ETIMEDOUT; | 966 | ret = -ETIMEDOUT; |
| 967 | 967 | ||
| 968 | iwl_force_nmi(trans); | 968 | iwl_trans_sync_nmi(trans); |
| 969 | iwl_trans_fw_error(trans); | ||
| 970 | |||
| 971 | goto cancel; | 969 | goto cancel; |
| 972 | } | 970 | } |
| 973 | 971 | ||
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c index 07395502f419..9fbd37d23e85 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. |
| 9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
| 10 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH | 10 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH |
| 11 | * Copyright(c) 2018 Intel Corporation | 11 | * Copyright(c) 2018 - 2019 Intel Corporation |
| 12 | * | 12 | * |
| 13 | * This program is free software; you can redistribute it and/or modify it | 13 | * This program is free software; you can redistribute it and/or modify it |
| 14 | * under the terms of version 2 of the GNU General Public License as | 14 | * under the terms of version 2 of the GNU General Public License as |
| @@ -31,7 +31,7 @@ | |||
| 31 | * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. | 31 | * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. |
| 32 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 32 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
| 33 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH | 33 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH |
| 34 | * Copyright(c) 2018 Intel Corporation | 34 | * Copyright(c) 2018 - 2019 Intel Corporation |
| 35 | * All rights reserved. | 35 | * All rights reserved. |
| 36 | * | 36 | * |
| 37 | * Redistribution and use in source and binary forms, with or without | 37 | * Redistribution and use in source and binary forms, with or without |
| @@ -995,7 +995,11 @@ static int iwl_pcie_tx_alloc(struct iwl_trans *trans) | |||
| 995 | txq_id++) { | 995 | txq_id++) { |
| 996 | bool cmd_queue = (txq_id == trans_pcie->cmd_queue); | 996 | bool cmd_queue = (txq_id == trans_pcie->cmd_queue); |
| 997 | 997 | ||
| 998 | slots_num = cmd_queue ? TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; | 998 | if (cmd_queue) |
| 999 | slots_num = max_t(u32, TFD_CMD_SLOTS, | ||
| 1000 | trans->cfg->min_txq_size); | ||
| 1001 | else | ||
| 1002 | slots_num = TFD_TX_CMD_SLOTS; | ||
| 999 | trans_pcie->txq[txq_id] = &trans_pcie->txq_memory[txq_id]; | 1003 | trans_pcie->txq[txq_id] = &trans_pcie->txq_memory[txq_id]; |
| 1000 | ret = iwl_pcie_txq_alloc(trans, trans_pcie->txq[txq_id], | 1004 | ret = iwl_pcie_txq_alloc(trans, trans_pcie->txq[txq_id], |
| 1001 | slots_num, cmd_queue); | 1005 | slots_num, cmd_queue); |
| @@ -1044,7 +1048,11 @@ int iwl_pcie_tx_init(struct iwl_trans *trans) | |||
| 1044 | txq_id++) { | 1048 | txq_id++) { |
| 1045 | bool cmd_queue = (txq_id == trans_pcie->cmd_queue); | 1049 | bool cmd_queue = (txq_id == trans_pcie->cmd_queue); |
| 1046 | 1050 | ||
| 1047 | slots_num = cmd_queue ? TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; | 1051 | if (cmd_queue) |
| 1052 | slots_num = max_t(u32, TFD_CMD_SLOTS, | ||
| 1053 | trans->cfg->min_txq_size); | ||
| 1054 | else | ||
| 1055 | slots_num = TFD_TX_CMD_SLOTS; | ||
| 1048 | ret = iwl_pcie_txq_init(trans, trans_pcie->txq[txq_id], | 1056 | ret = iwl_pcie_txq_init(trans, trans_pcie->txq[txq_id], |
| 1049 | slots_num, cmd_queue); | 1057 | slots_num, cmd_queue); |
| 1050 | if (ret) { | 1058 | if (ret) { |
| @@ -1174,6 +1182,15 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn, | |||
| 1174 | skb_queue_splice_init(&txq->overflow_q, &overflow_skbs); | 1182 | skb_queue_splice_init(&txq->overflow_q, &overflow_skbs); |
| 1175 | 1183 | ||
| 1176 | /* | 1184 | /* |
| 1185 | * We are going to transmit from the overflow queue. | ||
| 1186 | * Remember this state so that wait_for_txq_empty will know we | ||
| 1187 | * are adding more packets to the TFD queue. It cannot rely on | ||
| 1188 | * the state of &txq->overflow_q, as we just emptied it, but | ||
| 1189 | * haven't TXed the content yet. | ||
| 1190 | */ | ||
| 1191 | txq->overflow_tx = true; | ||
| 1192 | |||
| 1193 | /* | ||
| 1177 | * This is tricky: we are in reclaim path which is non | 1194 | * This is tricky: we are in reclaim path which is non |
| 1178 | * re-entrant, so noone will try to take the access the | 1195 | * re-entrant, so noone will try to take the access the |
| 1179 | * txq data from that path. We stopped tx, so we can't | 1196 | * txq data from that path. We stopped tx, so we can't |
| @@ -1201,6 +1218,7 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn, | |||
| 1201 | iwl_wake_queue(trans, txq); | 1218 | iwl_wake_queue(trans, txq); |
| 1202 | 1219 | ||
| 1203 | spin_lock_bh(&txq->lock); | 1220 | spin_lock_bh(&txq->lock); |
| 1221 | txq->overflow_tx = false; | ||
| 1204 | } | 1222 | } |
| 1205 | 1223 | ||
| 1206 | if (txq->read_ptr == txq->write_ptr) { | 1224 | if (txq->read_ptr == txq->write_ptr) { |
| @@ -1942,9 +1960,7 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans, | |||
| 1942 | iwl_get_cmd_string(trans, cmd->id)); | 1960 | iwl_get_cmd_string(trans, cmd->id)); |
| 1943 | ret = -ETIMEDOUT; | 1961 | ret = -ETIMEDOUT; |
| 1944 | 1962 | ||
| 1945 | iwl_force_nmi(trans); | 1963 | iwl_trans_sync_nmi(trans); |
| 1946 | iwl_trans_fw_error(trans); | ||
| 1947 | |||
| 1948 | goto cancel; | 1964 | goto cancel; |
| 1949 | } | 1965 | } |
| 1950 | 1966 | ||
