mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-30 10:49:28 +00:00
Fourth batch of iwlwifi patches intended for v5.1
* Work on the new debugging infrastructure continues; * FTM (Fine Timing Measurement) initiator and responder implementation; * Support for a new device family started; * Bump supported FW API to 46; * General bugfixes; * Other cleanups; -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEF3LNfgb2BPWm68smoUecoho8xfoFAlxlNmgACgkQoUecoho8 xfolGg//Z0843gfkrCMCrix+qgrV1NzBSnPKndlrcNKdmzzpdVuLiNDyY+Ij2FyK d/DuqmSsU0yhCJruHu1PN8cJ8uA9UJV8SMo7HvT/1RFV0d1MqYIKGMKn3BUm8KjR jxm7/RSnXf0DrVaHwyo3+mQT9b0RwfT9mHzo+ARxQLYqX+HwWVlYYM+905YKU4jK GOogrK5i3iIjtImLYibSd4DlsS1ws5oD3nQEn/IxTZVk0aqv49qQkM6+OHVp/6hi oA0ZQe+R19SfXBB2ushblapRGlmPiwZ3hhpHyJcxIhqX+UpYRFYgASqSygG6XhjJ wB8G6KegNSq1Rg6Sw2HZn28XGhsm1Kh67PZkIMp6k4OAttk+fw5NylRi+YwCAMZP axVjtjikUt/Td97TZtjOTjI58+ZN1kQo/3Th3gB9Pg9x7yjcJknAltFXr+kc8Cd9 gq4vPkojP9P+itHI3CcCrHRWnhA3H5ynmLkEmDSCIGJlCxecTKmwg99KRjDzhlOr AZd5rs0+C7u3FlrL0jagrpuy1nF038e56drmuAbHecK561IEx2UY8XofYxvapb0Y /0q8NPdX0Hhe229T0vtTDJnTGYjnV0pSqOhAouPyZz3V9zUiPVWbJ3tqaxH11vDI KjJiOkxPcWpRfAWtovAfY/0l/q2ungpGxqq3lthg3kQa3wUwwtM= =B8hU -----END PGP SIGNATURE----- Merge tag 'iwlwifi-next-for-kalle-2019-02-14' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next Fourth batch of iwlwifi patches intended for v5.1 * Work on the new debugging infrastructure continues; * FTM (Fine Timing Measurement) initiator and responder implementation; * Support for a new device family started; * Bump supported FW API to 46; * General bugfixes; * Other cleanups;
This commit is contained in:
commit
f77ecde5f2
51 changed files with 2352 additions and 302 deletions
|
@ -6,7 +6,7 @@
|
||||||
* GPL LICENSE SUMMARY
|
* GPL LICENSE SUMMARY
|
||||||
*
|
*
|
||||||
* Copyright(c) 2015-2017 Intel Deutschland GmbH
|
* Copyright(c) 2015-2017 Intel Deutschland GmbH
|
||||||
* Copyright (C) 2018 Intel Corporation
|
* Copyright (C) 2018-2019 Intel Corporation
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of version 2 of the GNU General Public License as
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
|
@ -20,7 +20,7 @@
|
||||||
* BSD LICENSE
|
* BSD LICENSE
|
||||||
*
|
*
|
||||||
* Copyright(c) 2015-2017 Intel Deutschland GmbH
|
* Copyright(c) 2015-2017 Intel Deutschland GmbH
|
||||||
* Copyright (C) 2018 Intel Corporation
|
* Copyright (C) 2018-2019 Intel Corporation
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -56,7 +56,7 @@
|
||||||
#include "iwl-config.h"
|
#include "iwl-config.h"
|
||||||
|
|
||||||
/* Highest firmware API version supported */
|
/* Highest firmware API version supported */
|
||||||
#define IWL_22000_UCODE_API_MAX 44
|
#define IWL_22000_UCODE_API_MAX 46
|
||||||
|
|
||||||
/* Lowest firmware API version supported */
|
/* Lowest firmware API version supported */
|
||||||
#define IWL_22000_UCODE_API_MIN 39
|
#define IWL_22000_UCODE_API_MIN 39
|
||||||
|
@ -79,11 +79,15 @@
|
||||||
#define IWL_22000_HR_B_F0_FW_PRE "iwlwifi-Qu-b0-hr-b0-"
|
#define IWL_22000_HR_B_F0_FW_PRE "iwlwifi-Qu-b0-hr-b0-"
|
||||||
#define IWL_22000_QU_B_HR_B_FW_PRE "iwlwifi-Qu-b0-hr-b0-"
|
#define IWL_22000_QU_B_HR_B_FW_PRE "iwlwifi-Qu-b0-hr-b0-"
|
||||||
#define IWL_22000_HR_B_FW_PRE "iwlwifi-QuQnj-b0-hr-b0-"
|
#define IWL_22000_HR_B_FW_PRE "iwlwifi-QuQnj-b0-hr-b0-"
|
||||||
#define IWL_22000_JF_B0_FW_PRE "iwlwifi-QuQnj-a0-jf-b0-"
|
|
||||||
#define IWL_22000_HR_A0_FW_PRE "iwlwifi-QuQnj-a0-hr-a0-"
|
#define IWL_22000_HR_A0_FW_PRE "iwlwifi-QuQnj-a0-hr-a0-"
|
||||||
#define IWL_22000_SU_Z0_FW_PRE "iwlwifi-su-z0-"
|
#define IWL_22000_SU_Z0_FW_PRE "iwlwifi-su-z0-"
|
||||||
#define IWL_QU_B_JF_B_FW_PRE "iwlwifi-Qu-b0-jf-b0-"
|
#define IWL_QU_B_JF_B_FW_PRE "iwlwifi-Qu-b0-jf-b0-"
|
||||||
|
#define IWL_QNJ_B_JF_B_FW_PRE "iwlwifi-QuQnj-b0-jf-b0-"
|
||||||
#define IWL_CC_A_FW_PRE "iwlwifi-cc-a0-"
|
#define IWL_CC_A_FW_PRE "iwlwifi-cc-a0-"
|
||||||
|
#define IWL_22000_SO_A_JF_B_FW_PRE "iwlwifi-so-a0-jf-b0-"
|
||||||
|
#define IWL_22000_SO_A_HR_B_FW_PRE "iwlwifi-so-a0-hr-b0-"
|
||||||
|
#define IWL_22000_SO_A_GF_A_FW_PRE "iwlwifi-so-a0-gf-a0-"
|
||||||
|
#define IWL_22000_TY_A_GF_A_FW_PRE "iwlwifi-ty-a0-gf-a0-"
|
||||||
|
|
||||||
#define IWL_22000_HR_MODULE_FIRMWARE(api) \
|
#define IWL_22000_HR_MODULE_FIRMWARE(api) \
|
||||||
IWL_22000_HR_FW_PRE __stringify(api) ".ucode"
|
IWL_22000_HR_FW_PRE __stringify(api) ".ucode"
|
||||||
|
@ -97,16 +101,26 @@
|
||||||
IWL_22000_QU_B_HR_B_FW_PRE __stringify(api) ".ucode"
|
IWL_22000_QU_B_HR_B_FW_PRE __stringify(api) ".ucode"
|
||||||
#define IWL_22000_HR_B_QNJ_MODULE_FIRMWARE(api) \
|
#define IWL_22000_HR_B_QNJ_MODULE_FIRMWARE(api) \
|
||||||
IWL_22000_HR_B_FW_PRE __stringify(api) ".ucode"
|
IWL_22000_HR_B_FW_PRE __stringify(api) ".ucode"
|
||||||
#define IWL_22000_JF_B0_QNJ_MODULE_FIRMWARE(api) \
|
|
||||||
IWL_22000_JF_B0_FW_PRE __stringify(api) ".ucode"
|
|
||||||
#define IWL_22000_HR_A0_QNJ_MODULE_FIRMWARE(api) \
|
#define IWL_22000_HR_A0_QNJ_MODULE_FIRMWARE(api) \
|
||||||
IWL_22000_HR_A0_FW_PRE __stringify(api) ".ucode"
|
IWL_22000_HR_A0_FW_PRE __stringify(api) ".ucode"
|
||||||
#define IWL_22000_SU_Z0_MODULE_FIRMWARE(api) \
|
#define IWL_22000_SU_Z0_MODULE_FIRMWARE(api) \
|
||||||
IWL_22000_SU_Z0_FW_PRE __stringify(api) ".ucode"
|
IWL_22000_SU_Z0_FW_PRE __stringify(api) ".ucode"
|
||||||
#define IWL_QU_B_JF_B_MODULE_FIRMWARE(api) \
|
#define IWL_QU_B_JF_B_MODULE_FIRMWARE(api) \
|
||||||
IWL_QU_B_JF_B_FW_PRE __stringify(api) ".ucode"
|
IWL_QU_B_JF_B_FW_PRE __stringify(api) ".ucode"
|
||||||
#define IWL_CC_A_MODULE_FIRMWARE(api) \
|
#define IWL_QU_B_JF_B_MODULE_FIRMWARE(api) \
|
||||||
|
IWL_QU_B_JF_B_FW_PRE __stringify(api) ".ucode"
|
||||||
|
#define IWL_QNJ_B_JF_B_MODULE_FIRMWARE(api) \
|
||||||
|
IWL_QNJ_B_JF_B_FW_PRE __stringify(api) ".ucode"
|
||||||
|
#define IWL_CC_A_MODULE_FIRMWARE(api) \
|
||||||
IWL_CC_A_FW_PRE __stringify(api) ".ucode"
|
IWL_CC_A_FW_PRE __stringify(api) ".ucode"
|
||||||
|
#define IWL_22000_SO_A_JF_B_MODULE_FIRMWARE(api) \
|
||||||
|
IWL_22000_SO_A_JF_B_FW_PRE __stringify(api) ".ucode"
|
||||||
|
#define IWL_22000_SO_A_HR_B_MODULE_FIRMWARE(api) \
|
||||||
|
IWL_22000_SO_A_HR_B_FW_PRE __stringify(api) ".ucode"
|
||||||
|
#define IWL_22000_SO_A_GF_A_MODULE_FIRMWARE(api) \
|
||||||
|
IWL_22000_SO_A_GF_A_FW_PRE __stringify(api) ".ucode"
|
||||||
|
#define IWL_22000_TY_A_GF_A_MODULE_FIRMWARE(api) \
|
||||||
|
IWL_22000_TY_A_GF_A_FW_PRE __stringify(api) ".ucode"
|
||||||
|
|
||||||
static const struct iwl_base_params iwl_22000_base_params = {
|
static const struct iwl_base_params iwl_22000_base_params = {
|
||||||
.eeprom_size = OTP_LOW_IMAGE_SIZE_32K,
|
.eeprom_size = OTP_LOW_IMAGE_SIZE_32K,
|
||||||
|
@ -167,6 +181,10 @@ static const struct iwl_ht_params iwl_22000_ht_params = {
|
||||||
.d3_debug_data_base_addr = 0x401000, \
|
.d3_debug_data_base_addr = 0x401000, \
|
||||||
.d3_debug_data_length = 60 * 1024
|
.d3_debug_data_length = 60 * 1024
|
||||||
|
|
||||||
|
#define IWL_DEVICE_AX200_COMMON \
|
||||||
|
IWL_DEVICE_22000_COMMON, \
|
||||||
|
.umac_prph_offset = 0x300000
|
||||||
|
|
||||||
#define IWL_DEVICE_22500 \
|
#define IWL_DEVICE_22500 \
|
||||||
IWL_DEVICE_22000_COMMON, \
|
IWL_DEVICE_22000_COMMON, \
|
||||||
.device_family = IWL_DEVICE_FAMILY_22000, \
|
.device_family = IWL_DEVICE_FAMILY_22000, \
|
||||||
|
@ -179,6 +197,13 @@ static const struct iwl_ht_params iwl_22000_ht_params = {
|
||||||
.base_params = &iwl_22560_base_params, \
|
.base_params = &iwl_22560_base_params, \
|
||||||
.csr = &iwl_csr_v2
|
.csr = &iwl_csr_v2
|
||||||
|
|
||||||
|
#define IWL_DEVICE_AX210 \
|
||||||
|
IWL_DEVICE_AX200_COMMON, \
|
||||||
|
.device_family = IWL_DEVICE_FAMILY_AX210, \
|
||||||
|
.base_params = &iwl_22000_base_params, \
|
||||||
|
.csr = &iwl_csr_v1, \
|
||||||
|
.min_txq_size = 128
|
||||||
|
|
||||||
const struct iwl_cfg iwl22000_2ac_cfg_hr = {
|
const struct iwl_cfg iwl22000_2ac_cfg_hr = {
|
||||||
.name = "Intel(R) Dual Band Wireless AC 22000",
|
.name = "Intel(R) Dual Band Wireless AC 22000",
|
||||||
.fw_name_pre = IWL_22000_HR_FW_PRE,
|
.fw_name_pre = IWL_22000_HR_FW_PRE,
|
||||||
|
@ -278,6 +303,18 @@ const struct iwl_cfg iwl9560_2ac_160_cfg_qu_b0_jf_b0 = {
|
||||||
IWL_DEVICE_22500,
|
IWL_DEVICE_22500,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const struct iwl_cfg iwl9560_2ac_cfg_qnj_jf_b0 = {
|
||||||
|
.name = "Intel(R) Wireless-AC 9560 160MHz",
|
||||||
|
.fw_name_pre = IWL_QNJ_B_JF_B_FW_PRE,
|
||||||
|
IWL_DEVICE_22500,
|
||||||
|
/*
|
||||||
|
* This device doesn't support receiving BlockAck with a large bitmap
|
||||||
|
* so we need to restrict the size of transmitted aggregation to the
|
||||||
|
* HT size; mac80211 would otherwise pick the HE max (256) by default.
|
||||||
|
*/
|
||||||
|
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
|
||||||
|
};
|
||||||
|
|
||||||
const struct iwl_cfg killer1550i_2ac_cfg_qu_b0_jf_b0 = {
|
const struct iwl_cfg killer1550i_2ac_cfg_qu_b0_jf_b0 = {
|
||||||
.name = "Killer (R) Wireless-AC 1550i Wireless Network Adapter (9560NGW)",
|
.name = "Killer (R) Wireless-AC 1550i Wireless Network Adapter (9560NGW)",
|
||||||
.fw_name_pre = IWL_QU_B_JF_B_FW_PRE,
|
.fw_name_pre = IWL_QU_B_JF_B_FW_PRE,
|
||||||
|
@ -350,18 +387,6 @@ const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_b0 = {
|
||||||
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
|
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
|
||||||
};
|
};
|
||||||
|
|
||||||
const struct iwl_cfg iwl22000_2ax_cfg_qnj_jf_b0 = {
|
|
||||||
.name = "Intel(R) Dual Band Wireless AX 22000",
|
|
||||||
.fw_name_pre = IWL_22000_JF_B0_FW_PRE,
|
|
||||||
IWL_DEVICE_22500,
|
|
||||||
/*
|
|
||||||
* This device doesn't support receiving BlockAck with a large bitmap
|
|
||||||
* so we need to restrict the size of transmitted aggregation to the
|
|
||||||
* HT size; mac80211 would otherwise pick the HE max (256) by default.
|
|
||||||
*/
|
|
||||||
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
|
|
||||||
};
|
|
||||||
|
|
||||||
const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_a0 = {
|
const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_a0 = {
|
||||||
.name = "Intel(R) Dual Band Wireless AX 22000",
|
.name = "Intel(R) Dual Band Wireless AX 22000",
|
||||||
.fw_name_pre = IWL_22000_HR_A0_FW_PRE,
|
.fw_name_pre = IWL_22000_HR_A0_FW_PRE,
|
||||||
|
@ -387,13 +412,41 @@ const struct iwl_cfg iwl22560_2ax_cfg_su_cdb = {
|
||||||
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
|
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const struct iwl_cfg iwlax210_2ax_cfg_so_jf_a0 = {
|
||||||
|
.name = "Intel(R) Wireless-AC 9560 160MHz",
|
||||||
|
.fw_name_pre = IWL_22000_SO_A_JF_B_FW_PRE,
|
||||||
|
IWL_DEVICE_AX210,
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct iwl_cfg iwlax210_2ax_cfg_so_hr_a0 = {
|
||||||
|
.name = "Intel(R) Wi-Fi 6 AX201 160MHz",
|
||||||
|
.fw_name_pre = IWL_22000_SO_A_HR_B_FW_PRE,
|
||||||
|
IWL_DEVICE_AX210,
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct iwl_cfg iwlax210_2ax_cfg_so_gf_a0 = {
|
||||||
|
.name = "Intel(R) Wi-Fi 7 AX211 160MHz",
|
||||||
|
.fw_name_pre = IWL_22000_SO_A_GF_A_FW_PRE,
|
||||||
|
IWL_DEVICE_AX210,
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct iwl_cfg iwlax210_2ax_cfg_ty_gf_a0 = {
|
||||||
|
.name = "Intel(R) Wi-Fi 7 AX210 160MHz",
|
||||||
|
.fw_name_pre = IWL_22000_TY_A_GF_A_FW_PRE,
|
||||||
|
IWL_DEVICE_AX210,
|
||||||
|
};
|
||||||
|
|
||||||
MODULE_FIRMWARE(IWL_22000_HR_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
MODULE_FIRMWARE(IWL_22000_HR_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||||
MODULE_FIRMWARE(IWL_22000_JF_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
MODULE_FIRMWARE(IWL_22000_JF_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||||
MODULE_FIRMWARE(IWL_22000_HR_A_F0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
MODULE_FIRMWARE(IWL_22000_HR_A_F0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||||
MODULE_FIRMWARE(IWL_22000_HR_B_F0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
MODULE_FIRMWARE(IWL_22000_HR_B_F0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||||
MODULE_FIRMWARE(IWL_22000_HR_B_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
MODULE_FIRMWARE(IWL_22000_HR_B_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||||
MODULE_FIRMWARE(IWL_22000_JF_B0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
|
||||||
MODULE_FIRMWARE(IWL_22000_HR_A0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
MODULE_FIRMWARE(IWL_22000_HR_A0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||||
MODULE_FIRMWARE(IWL_22000_SU_Z0_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
MODULE_FIRMWARE(IWL_22000_SU_Z0_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||||
MODULE_FIRMWARE(IWL_QU_B_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
MODULE_FIRMWARE(IWL_QU_B_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||||
|
MODULE_FIRMWARE(IWL_QNJ_B_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||||
MODULE_FIRMWARE(IWL_CC_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
MODULE_FIRMWARE(IWL_CC_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||||
|
MODULE_FIRMWARE(IWL_22000_SO_A_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||||
|
MODULE_FIRMWARE(IWL_22000_SO_A_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||||
|
MODULE_FIRMWARE(IWL_22000_SO_A_GF_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||||
|
MODULE_FIRMWARE(IWL_22000_TY_A_GF_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||||
|
|
|
@ -57,7 +57,7 @@
|
||||||
#include "fw/file.h"
|
#include "fw/file.h"
|
||||||
|
|
||||||
/* Highest firmware API version supported */
|
/* Highest firmware API version supported */
|
||||||
#define IWL9000_UCODE_API_MAX 44
|
#define IWL9000_UCODE_API_MAX 46
|
||||||
|
|
||||||
/* Lowest firmware API version supported */
|
/* Lowest firmware API version supported */
|
||||||
#define IWL9000_UCODE_API_MIN 30
|
#define IWL9000_UCODE_API_MIN 30
|
||||||
|
|
|
@ -1881,7 +1881,7 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(iwl_have_debug_level(IWL_DL_FW_ERRORS)) && !full_log)
|
if (!(iwl_have_debug_level(IWL_DL_FW)) && !full_log)
|
||||||
size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES)
|
size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES)
|
||||||
? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size;
|
? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size;
|
||||||
IWL_ERR(priv, "Start IWL Event Log Dump: display last %u entries\n",
|
IWL_ERR(priv, "Start IWL Event Log Dump: display last %u entries\n",
|
||||||
|
@ -1897,7 +1897,7 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
|
||||||
if (!*buf)
|
if (!*buf)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
if (iwl_have_debug_level(IWL_DL_FW_ERRORS) || full_log) {
|
if (iwl_have_debug_level(IWL_DL_FW) || full_log) {
|
||||||
/*
|
/*
|
||||||
* if uCode has wrapped back to top of log,
|
* if uCode has wrapped back to top of log,
|
||||||
* start at the oldest entry,
|
* start at the oldest entry,
|
||||||
|
@ -1927,7 +1927,7 @@ static void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
|
||||||
unsigned int reload_msec;
|
unsigned int reload_msec;
|
||||||
unsigned long reload_jiffies;
|
unsigned long reload_jiffies;
|
||||||
|
|
||||||
if (iwl_have_debug_level(IWL_DL_FW_ERRORS))
|
if (iwl_have_debug_level(IWL_DL_FW))
|
||||||
iwl_print_rx_config_cmd(priv, IWL_RXON_CTX_BSS);
|
iwl_print_rx_config_cmd(priv, IWL_RXON_CTX_BSS);
|
||||||
|
|
||||||
/* uCode is no longer loaded. */
|
/* uCode is no longer loaded. */
|
||||||
|
@ -1965,12 +1965,12 @@ static void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
|
||||||
|
|
||||||
if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) {
|
if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) {
|
||||||
if (iwlwifi_mod_params.fw_restart) {
|
if (iwlwifi_mod_params.fw_restart) {
|
||||||
IWL_DEBUG_FW_ERRORS(priv,
|
IWL_DEBUG_FW(priv,
|
||||||
"Restarting adapter due to uCode error.\n");
|
"Restarting adapter due to uCode error.\n");
|
||||||
queue_work(priv->workqueue, &priv->restart);
|
queue_work(priv->workqueue, &priv->restart);
|
||||||
} else
|
} else
|
||||||
IWL_DEBUG_FW_ERRORS(priv,
|
IWL_DEBUG_FW(priv,
|
||||||
"Detected FW error, but not restarting\n");
|
"Detected FW error, but not restarting\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
* GPL LICENSE SUMMARY
|
* GPL LICENSE SUMMARY
|
||||||
*
|
*
|
||||||
* Copyright(c) 2017 Intel Deutschland GmbH
|
* Copyright(c) 2017 Intel Deutschland GmbH
|
||||||
|
* Copyright (C) 2019 Intel Corporation
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of version 2 of the GNU General Public License as
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
|
@ -26,6 +27,7 @@
|
||||||
* BSD LICENSE
|
* BSD LICENSE
|
||||||
*
|
*
|
||||||
* Copyright(c) 2017 Intel Deutschland GmbH
|
* Copyright(c) 2017 Intel Deutschland GmbH
|
||||||
|
* Copyright (C) 2019 Intel Corporation
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -205,3 +207,33 @@ out:
|
||||||
return dflt_pwr_limit;
|
return dflt_pwr_limit;
|
||||||
}
|
}
|
||||||
IWL_EXPORT_SYMBOL(iwl_acpi_get_pwr_limit);
|
IWL_EXPORT_SYMBOL(iwl_acpi_get_pwr_limit);
|
||||||
|
|
||||||
|
int iwl_acpi_get_eckv(struct device *dev, u32 *extl_clk)
|
||||||
|
{
|
||||||
|
union acpi_object *wifi_pkg, *data;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
data = iwl_acpi_get_object(dev, ACPI_ECKV_METHOD);
|
||||||
|
if (IS_ERR(data))
|
||||||
|
return PTR_ERR(data);
|
||||||
|
|
||||||
|
wifi_pkg = iwl_acpi_get_wifi_pkg(dev, data, ACPI_ECKV_WIFI_DATA_SIZE);
|
||||||
|
if (IS_ERR(wifi_pkg)) {
|
||||||
|
ret = PTR_ERR(wifi_pkg);
|
||||||
|
goto out_free;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto out_free;
|
||||||
|
}
|
||||||
|
|
||||||
|
*extl_clk = wifi_pkg->package.elements[1].integer.value;
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
out_free:
|
||||||
|
kfree(data);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
IWL_EXPORT_SYMBOL(iwl_acpi_get_eckv);
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
* GPL LICENSE SUMMARY
|
* GPL LICENSE SUMMARY
|
||||||
*
|
*
|
||||||
* Copyright(c) 2017 Intel Deutschland GmbH
|
* Copyright(c) 2017 Intel Deutschland GmbH
|
||||||
* Copyright(c) 2018 Intel Corporation
|
* Copyright(c) 2018 - 2019 Intel Corporation
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of version 2 of the GNU General Public License as
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
|
@ -27,7 +27,7 @@
|
||||||
* BSD LICENSE
|
* BSD LICENSE
|
||||||
*
|
*
|
||||||
* Copyright(c) 2017 Intel Deutschland GmbH
|
* Copyright(c) 2017 Intel Deutschland GmbH
|
||||||
* Copyright(c) 2018 Intel Corporation
|
* Copyright(c) 2018 - 2019 Intel Corporation
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -67,6 +67,7 @@
|
||||||
#define ACPI_WGDS_METHOD "WGDS"
|
#define ACPI_WGDS_METHOD "WGDS"
|
||||||
#define ACPI_WRDD_METHOD "WRDD"
|
#define ACPI_WRDD_METHOD "WRDD"
|
||||||
#define ACPI_SPLC_METHOD "SPLC"
|
#define ACPI_SPLC_METHOD "SPLC"
|
||||||
|
#define ACPI_ECKV_METHOD "ECKV"
|
||||||
|
|
||||||
#define ACPI_WIFI_DOMAIN (0x07)
|
#define ACPI_WIFI_DOMAIN (0x07)
|
||||||
|
|
||||||
|
@ -86,6 +87,7 @@
|
||||||
#define ACPI_WGDS_WIFI_DATA_SIZE 19
|
#define ACPI_WGDS_WIFI_DATA_SIZE 19
|
||||||
#define ACPI_WRDD_WIFI_DATA_SIZE 2
|
#define ACPI_WRDD_WIFI_DATA_SIZE 2
|
||||||
#define ACPI_SPLC_WIFI_DATA_SIZE 2
|
#define ACPI_SPLC_WIFI_DATA_SIZE 2
|
||||||
|
#define ACPI_ECKV_WIFI_DATA_SIZE 2
|
||||||
|
|
||||||
#define ACPI_WGDS_NUM_BANDS 2
|
#define ACPI_WGDS_NUM_BANDS 2
|
||||||
#define ACPI_WGDS_TABLE_SIZE 3
|
#define ACPI_WGDS_TABLE_SIZE 3
|
||||||
|
@ -109,6 +111,17 @@ int iwl_acpi_get_mcc(struct device *dev, char *mcc);
|
||||||
|
|
||||||
u64 iwl_acpi_get_pwr_limit(struct device *dev);
|
u64 iwl_acpi_get_pwr_limit(struct device *dev);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* iwl_acpi_get_eckv - read external clock validation from ACPI, if available
|
||||||
|
*
|
||||||
|
* @dev: the struct device
|
||||||
|
* @extl_clk: output var (2 bytes) that will get the clk indication.
|
||||||
|
*
|
||||||
|
* This function tries to read the external clock indication
|
||||||
|
* from ACPI if available.
|
||||||
|
*/
|
||||||
|
int iwl_acpi_get_eckv(struct device *dev, u32 *extl_clk);
|
||||||
|
|
||||||
#else /* CONFIG_ACPI */
|
#else /* CONFIG_ACPI */
|
||||||
|
|
||||||
static inline void *iwl_acpi_get_object(struct device *dev, acpi_string method)
|
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)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int iwl_acpi_get_eckv(struct device *dev, u32 *extl_clk)
|
||||||
|
{
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_ACPI */
|
#endif /* CONFIG_ACPI */
|
||||||
#endif /* __iwl_fw_acpi__ */
|
#endif /* __iwl_fw_acpi__ */
|
||||||
|
|
|
@ -96,14 +96,7 @@ enum {
|
||||||
|
|
||||||
#define IWL_ALIVE_FLG_RFKILL BIT(0)
|
#define IWL_ALIVE_FLG_RFKILL BIT(0)
|
||||||
|
|
||||||
struct iwl_lmac_alive {
|
struct iwl_lmac_debug_addrs {
|
||||||
__le32 ucode_major;
|
|
||||||
__le32 ucode_minor;
|
|
||||||
u8 ver_subtype;
|
|
||||||
u8 ver_type;
|
|
||||||
u8 mac;
|
|
||||||
u8 opt;
|
|
||||||
__le32 timestamp;
|
|
||||||
__le32 error_event_table_ptr; /* SRAM address for error log */
|
__le32 error_event_table_ptr; /* SRAM address for error log */
|
||||||
__le32 log_event_table_ptr; /* SRAM address for LMAC event log */
|
__le32 log_event_table_ptr; /* SRAM address for LMAC event log */
|
||||||
__le32 cpu_register_ptr;
|
__le32 cpu_register_ptr;
|
||||||
|
@ -112,13 +105,28 @@ struct iwl_lmac_alive {
|
||||||
__le32 scd_base_ptr; /* SRAM address for SCD */
|
__le32 scd_base_ptr; /* SRAM address for SCD */
|
||||||
__le32 st_fwrd_addr; /* pointer to Store and forward */
|
__le32 st_fwrd_addr; /* pointer to Store and forward */
|
||||||
__le32 st_fwrd_size;
|
__le32 st_fwrd_size;
|
||||||
|
} __packed; /* UCODE_DEBUG_ADDRS_API_S_VER_2 */
|
||||||
|
|
||||||
|
struct iwl_lmac_alive {
|
||||||
|
__le32 ucode_major;
|
||||||
|
__le32 ucode_minor;
|
||||||
|
u8 ver_subtype;
|
||||||
|
u8 ver_type;
|
||||||
|
u8 mac;
|
||||||
|
u8 opt;
|
||||||
|
__le32 timestamp;
|
||||||
|
struct iwl_lmac_debug_addrs dbg_ptrs;
|
||||||
} __packed; /* UCODE_ALIVE_NTFY_API_S_VER_3 */
|
} __packed; /* UCODE_ALIVE_NTFY_API_S_VER_3 */
|
||||||
|
|
||||||
|
struct iwl_umac_debug_addrs {
|
||||||
|
__le32 error_info_addr; /* SRAM address for UMAC error log */
|
||||||
|
__le32 dbg_print_buff_addr;
|
||||||
|
} __packed; /* UMAC_DEBUG_ADDRS_API_S_VER_1 */
|
||||||
|
|
||||||
struct iwl_umac_alive {
|
struct iwl_umac_alive {
|
||||||
__le32 umac_major; /* UMAC version: major */
|
__le32 umac_major; /* UMAC version: major */
|
||||||
__le32 umac_minor; /* UMAC version: minor */
|
__le32 umac_minor; /* UMAC version: minor */
|
||||||
__le32 error_info_addr; /* SRAM address for UMAC error log */
|
struct iwl_umac_debug_addrs dbg_ptrs;
|
||||||
__le32 dbg_print_buff_addr;
|
|
||||||
} __packed; /* UMAC_ALIVE_DATA_API_S_VER_2 */
|
} __packed; /* UMAC_ALIVE_DATA_API_S_VER_2 */
|
||||||
|
|
||||||
struct mvm_alive_resp_v3 {
|
struct mvm_alive_resp_v3 {
|
||||||
|
@ -189,4 +197,24 @@ struct iwl_card_state_notif {
|
||||||
__le32 flags;
|
__le32 flags;
|
||||||
} __packed; /* CARD_STATE_NTFY_API_S_VER_1 */
|
} __packed; /* CARD_STATE_NTFY_API_S_VER_1 */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum iwl_error_recovery_flags - flags for error recovery cmd
|
||||||
|
* @ERROR_RECOVERY_UPDATE_DB: update db from blob sent
|
||||||
|
* @ERROR_RECOVERY_END_OF_RECOVERY: end of recovery
|
||||||
|
*/
|
||||||
|
enum iwl_error_recovery_flags {
|
||||||
|
ERROR_RECOVERY_UPDATE_DB = BIT(0),
|
||||||
|
ERROR_RECOVERY_END_OF_RECOVERY = BIT(1),
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct iwl_fw_error_recovery_cmd - recovery cmd sent upon assert
|
||||||
|
* @flags: &enum iwl_error_recovery_flags
|
||||||
|
* @buf_size: db buffer size in bytes
|
||||||
|
*/
|
||||||
|
struct iwl_fw_error_recovery_cmd {
|
||||||
|
__le32 flags;
|
||||||
|
__le32 buf_size;
|
||||||
|
} __packed; /* ERROR_RECOVERY_CMD_HDR_API_S_VER_1 */
|
||||||
|
|
||||||
#endif /* __iwl_fw_api_alive_h__ */
|
#endif /* __iwl_fw_api_alive_h__ */
|
||||||
|
|
|
@ -643,6 +643,11 @@ enum iwl_system_subcmd_ids {
|
||||||
* @INIT_EXTENDED_CFG_CMD: &struct iwl_init_extended_cfg_cmd
|
* @INIT_EXTENDED_CFG_CMD: &struct iwl_init_extended_cfg_cmd
|
||||||
*/
|
*/
|
||||||
INIT_EXTENDED_CFG_CMD = 0x03,
|
INIT_EXTENDED_CFG_CMD = 0x03,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @FW_ERROR_RECOVERY_CMD: &struct iwl_fw_error_recovery_cmd
|
||||||
|
*/
|
||||||
|
FW_ERROR_RECOVERY_CMD = 0x7,
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* __iwl_fw_api_commands_h__ */
|
#endif /* __iwl_fw_api_commands_h__ */
|
||||||
|
|
|
@ -204,8 +204,13 @@ struct iwl_fw_ini_region_tlv {
|
||||||
* struct iwl_fw_ini_trigger - (IWL_FW_INI_TLV_TYPE_DUMP_CFG)
|
* struct iwl_fw_ini_trigger - (IWL_FW_INI_TLV_TYPE_DUMP_CFG)
|
||||||
* Region sections define IDs and triggers that use those IDs TLV
|
* Region sections define IDs and triggers that use those IDs TLV
|
||||||
*
|
*
|
||||||
* @trigger_id: enum &iwl_fw_ini_trigger_id
|
* @trigger_id: enum &iwl_fw_ini_tigger_id
|
||||||
* @ignore_default: override FW TLV with binary TLV
|
* @override_trig: determines how apply trigger in case a trigger with the
|
||||||
|
* same id is already in use. Using the first 2 bytes:
|
||||||
|
* Byte 0: if 0, override trigger configuration, otherwise use the
|
||||||
|
* existing configuration.
|
||||||
|
* Byte 1: if 0, override trigger regions, otherwise append regions to
|
||||||
|
* existing trigger.
|
||||||
* @dump_delay: delay from trigger fire to dump, in usec
|
* @dump_delay: delay from trigger fire to dump, in usec
|
||||||
* @occurrences: max amount of times to be fired
|
* @occurrences: max amount of times to be fired
|
||||||
* @ignore_consec: ignore consecutive triggers, in usec
|
* @ignore_consec: ignore consecutive triggers, in usec
|
||||||
|
@ -217,7 +222,7 @@ struct iwl_fw_ini_region_tlv {
|
||||||
*/
|
*/
|
||||||
struct iwl_fw_ini_trigger {
|
struct iwl_fw_ini_trigger {
|
||||||
__le32 trigger_id;
|
__le32 trigger_id;
|
||||||
__le32 ignore_default;
|
__le32 override_trig;
|
||||||
__le32 dump_delay;
|
__le32 dump_delay;
|
||||||
__le32 occurrences;
|
__le32 occurrences;
|
||||||
__le32 ignore_consec;
|
__le32 ignore_consec;
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
*
|
*
|
||||||
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
|
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
|
||||||
* Copyright (C) 2018 Intel Corporation
|
* Copyright (C) 2018 Intel Corporation
|
||||||
|
* Copyright (C) 2019 Intel Corporation
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of version 2 of the GNU General Public License as
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
|
@ -28,6 +29,7 @@
|
||||||
*
|
*
|
||||||
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
|
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
|
||||||
* Copyright (C) 2018 Intel Corporation
|
* Copyright (C) 2018 Intel Corporation
|
||||||
|
* Copyright (C) 2019 Intel Corporation
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -322,7 +324,7 @@ enum iwl_tof_location_query {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct iwl_tof_range_req_ap_entry - AP configuration parameters
|
* struct iwl_tof_range_req_ap_entry_v2 - AP configuration parameters
|
||||||
* @channel_num: Current AP Channel
|
* @channel_num: Current AP Channel
|
||||||
* @bandwidth: Current AP Bandwidth. One of iwl_tof_bandwidth.
|
* @bandwidth: Current AP Bandwidth. One of iwl_tof_bandwidth.
|
||||||
* @tsf_delta_direction: TSF relatively to the subject AP
|
* @tsf_delta_direction: TSF relatively to the subject AP
|
||||||
|
@ -355,7 +357,7 @@ enum iwl_tof_location_query {
|
||||||
* @notify_mcsi: &enum iwl_tof_mcsi_ntfy.
|
* @notify_mcsi: &enum iwl_tof_mcsi_ntfy.
|
||||||
* @reserved: For alignment and future use
|
* @reserved: For alignment and future use
|
||||||
*/
|
*/
|
||||||
struct iwl_tof_range_req_ap_entry {
|
struct iwl_tof_range_req_ap_entry_v2 {
|
||||||
u8 channel_num;
|
u8 channel_num;
|
||||||
u8 bandwidth;
|
u8 bandwidth;
|
||||||
u8 tsf_delta_direction;
|
u8 tsf_delta_direction;
|
||||||
|
@ -374,6 +376,62 @@ struct iwl_tof_range_req_ap_entry {
|
||||||
u8 algo_type;
|
u8 algo_type;
|
||||||
u8 notify_mcsi;
|
u8 notify_mcsi;
|
||||||
__le16 reserved;
|
__le16 reserved;
|
||||||
|
} __packed; /* LOCATION_RANGE_REQ_AP_ENTRY_CMD_API_S_VER_2 */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum iwl_initiator_ap_flags - per responder FTM configuration flags
|
||||||
|
* @IWL_INITIATOR_AP_FLAGS_ASAP: Request for ASAP measurement.
|
||||||
|
* @IWL_INITIATOR_AP_FLAGS_LCI_REQUEST: Request for LCI information
|
||||||
|
* @IWL_INITIATOR_AP_FLAGS_CIVIC_REQUEST: Request for CIVIC information
|
||||||
|
* @IWL_INITIATOR_AP_FLAGS_DYN_ACK: Send HT/VHT ack for FTM frames. If not set,
|
||||||
|
* 20Mhz dup acks will be sent.
|
||||||
|
* @IWL_INITIATOR_AP_FLAGS_ALGO_LR: Use LR algo type for rtt calculation.
|
||||||
|
* Default algo type is ML.
|
||||||
|
* @IWL_INITIATOR_AP_FLAGS_ALGO_FFT: Use FFT algo type for rtt calculation.
|
||||||
|
* Default algo type is ML.
|
||||||
|
* @IWL_INITIATOR_AP_FLAGS_MCSI_REPORT: Send the MCSI for each FTM frame to the
|
||||||
|
* driver.
|
||||||
|
*/
|
||||||
|
enum iwl_initiator_ap_flags {
|
||||||
|
IWL_INITIATOR_AP_FLAGS_ASAP = BIT(1),
|
||||||
|
IWL_INITIATOR_AP_FLAGS_LCI_REQUEST = BIT(2),
|
||||||
|
IWL_INITIATOR_AP_FLAGS_CIVIC_REQUEST = BIT(3),
|
||||||
|
IWL_INITIATOR_AP_FLAGS_DYN_ACK = BIT(4),
|
||||||
|
IWL_INITIATOR_AP_FLAGS_ALGO_LR = BIT(5),
|
||||||
|
IWL_INITIATOR_AP_FLAGS_ALGO_FFT = BIT(6),
|
||||||
|
IWL_INITIATOR_AP_FLAGS_MCSI_REPORT = BIT(8),
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct iwl_tof_range_req_ap_entry - AP configuration parameters
|
||||||
|
* @initiator_ap_flags: see &enum iwl_initiator_ap_flags.
|
||||||
|
* @channel_num: AP Channel number
|
||||||
|
* @bandwidth: AP bandwidth. One of iwl_tof_bandwidth.
|
||||||
|
* @ctrl_ch_position: Coding of the control channel position relative to the
|
||||||
|
* center frequency, see iwl_mvm_get_ctrl_pos().
|
||||||
|
* @ftmr_max_retries: Max number of retries to send the FTMR in case of no
|
||||||
|
* reply from the AP.
|
||||||
|
* @bssid: AP's BSSID
|
||||||
|
* @burst_period: Recommended value to be sent to the AP. Measurement
|
||||||
|
* periodicity In units of 100ms. ignored if num_of_bursts_exp = 0
|
||||||
|
* @samples_per_burst: the number of FTMs pairs in single Burst (1-31);
|
||||||
|
* @num_of_bursts: Recommended value to be sent to the AP. 2s Exponent of
|
||||||
|
* the number of measurement iterations (min 2^0 = 1, max 2^14)
|
||||||
|
* @reserved: For alignment and future use
|
||||||
|
* @tsf_delta: not in use
|
||||||
|
*/
|
||||||
|
struct iwl_tof_range_req_ap_entry {
|
||||||
|
__le32 initiator_ap_flags;
|
||||||
|
u8 channel_num;
|
||||||
|
u8 bandwidth;
|
||||||
|
u8 ctrl_ch_position;
|
||||||
|
u8 ftmr_max_retries;
|
||||||
|
u8 bssid[ETH_ALEN];
|
||||||
|
__le16 burst_period;
|
||||||
|
u8 samples_per_burst;
|
||||||
|
u8 num_of_bursts;
|
||||||
|
__le16 reserved;
|
||||||
|
__le32 tsf_delta;
|
||||||
} __packed; /* LOCATION_RANGE_REQ_AP_ENTRY_CMD_API_S_VER_3 */
|
} __packed; /* LOCATION_RANGE_REQ_AP_ENTRY_CMD_API_S_VER_3 */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -403,7 +461,12 @@ enum iwl_tof_response_mode {
|
||||||
* @IWL_TOF_INITIATOR_FLAGS_TX_CHAIN_SEL_A: use antenna A fo TX ACKs during FTM
|
* @IWL_TOF_INITIATOR_FLAGS_TX_CHAIN_SEL_A: use antenna A fo TX ACKs during FTM
|
||||||
* @IWL_TOF_INITIATOR_FLAGS_TX_CHAIN_SEL_B: use antenna B fo TX ACKs during FTM
|
* @IWL_TOF_INITIATOR_FLAGS_TX_CHAIN_SEL_B: use antenna B fo TX ACKs during FTM
|
||||||
* @IWL_TOF_INITIATOR_FLAGS_TX_CHAIN_SEL_C: use antenna C fo TX ACKs during FTM
|
* @IWL_TOF_INITIATOR_FLAGS_TX_CHAIN_SEL_C: use antenna C fo TX ACKs during FTM
|
||||||
* @IWL_TOF_INITIATOR_FLAGS_MINDELTA_NO_PREF: no preference for minDeltaFTM
|
* @IWL_TOF_INITIATOR_FLAGS_MACADDR_RANDOM: use random mac address for FTM
|
||||||
|
* @IWL_TOF_INITIATOR_FLAGS_SPECIFIC_CALIB: use the specific calib value from
|
||||||
|
* the range request command
|
||||||
|
* @IWL_TOF_INITIATOR_FLAGS_COMMON_CALIB: use the common calib value from the
|
||||||
|
* ragne request command
|
||||||
|
* @IWL_TOF_INITIATOR_FLAGS_NON_ASAP_SUPPORT: support non-asap measurements
|
||||||
*/
|
*/
|
||||||
enum iwl_tof_initiator_flags {
|
enum iwl_tof_initiator_flags {
|
||||||
IWL_TOF_INITIATOR_FLAGS_FAST_ALGO_DISABLED = BIT(0),
|
IWL_TOF_INITIATOR_FLAGS_FAST_ALGO_DISABLED = BIT(0),
|
||||||
|
@ -413,14 +476,17 @@ enum iwl_tof_initiator_flags {
|
||||||
IWL_TOF_INITIATOR_FLAGS_TX_CHAIN_SEL_A = BIT(4),
|
IWL_TOF_INITIATOR_FLAGS_TX_CHAIN_SEL_A = BIT(4),
|
||||||
IWL_TOF_INITIATOR_FLAGS_TX_CHAIN_SEL_B = BIT(5),
|
IWL_TOF_INITIATOR_FLAGS_TX_CHAIN_SEL_B = BIT(5),
|
||||||
IWL_TOF_INITIATOR_FLAGS_TX_CHAIN_SEL_C = BIT(6),
|
IWL_TOF_INITIATOR_FLAGS_TX_CHAIN_SEL_C = BIT(6),
|
||||||
IWL_TOF_INITIATOR_FLAGS_MINDELTA_NO_PREF = BIT(7),
|
IWL_TOF_INITIATOR_FLAGS_MACADDR_RANDOM = BIT(7),
|
||||||
|
IWL_TOF_INITIATOR_FLAGS_SPECIFIC_CALIB = BIT(15),
|
||||||
|
IWL_TOF_INITIATOR_FLAGS_COMMON_CALIB = BIT(16),
|
||||||
|
IWL_TOF_INITIATOR_FLAGS_NON_ASAP_SUPPORT = BIT(20),
|
||||||
}; /* LOCATION_RANGE_REQ_CMD_API_S_VER_5 */
|
}; /* LOCATION_RANGE_REQ_CMD_API_S_VER_5 */
|
||||||
|
|
||||||
#define IWL_MVM_TOF_MAX_APS 5
|
#define IWL_MVM_TOF_MAX_APS 5
|
||||||
#define IWL_MVM_TOF_MAX_TWO_SIDED_APS 5
|
#define IWL_MVM_TOF_MAX_TWO_SIDED_APS 5
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct iwl_tof_range_req_cmd - start measurement cmd
|
* struct iwl_tof_range_req_cmd_v5 - start measurement cmd
|
||||||
* @initiator_flags: see flags @ iwl_tof_initiator_flags
|
* @initiator_flags: see flags @ iwl_tof_initiator_flags
|
||||||
* @request_id: A Token incremented per request. The same Token will be
|
* @request_id: A Token incremented per request. The same Token will be
|
||||||
* sent back in the range response
|
* sent back in the range response
|
||||||
|
@ -448,7 +514,7 @@ enum iwl_tof_initiator_flags {
|
||||||
* @specific_calib: The specific calib value to inject to this measurement calc
|
* @specific_calib: The specific calib value to inject to this measurement calc
|
||||||
* @ap: per-AP request data
|
* @ap: per-AP request data
|
||||||
*/
|
*/
|
||||||
struct iwl_tof_range_req_cmd {
|
struct iwl_tof_range_req_cmd_v5 {
|
||||||
__le32 initiator_flags;
|
__le32 initiator_flags;
|
||||||
u8 request_id;
|
u8 request_id;
|
||||||
u8 initiator;
|
u8 initiator;
|
||||||
|
@ -465,10 +531,42 @@ struct iwl_tof_range_req_cmd {
|
||||||
u8 ftm_tx_chains;
|
u8 ftm_tx_chains;
|
||||||
__le16 common_calib;
|
__le16 common_calib;
|
||||||
__le16 specific_calib;
|
__le16 specific_calib;
|
||||||
struct iwl_tof_range_req_ap_entry ap[IWL_MVM_TOF_MAX_APS];
|
struct iwl_tof_range_req_ap_entry_v2 ap[IWL_MVM_TOF_MAX_APS];
|
||||||
} __packed;
|
} __packed;
|
||||||
/* LOCATION_RANGE_REQ_CMD_API_S_VER_5 */
|
/* LOCATION_RANGE_REQ_CMD_API_S_VER_5 */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct iwl_tof_range_req_cmd - start measurement cmd
|
||||||
|
* @initiator_flags: see flags @ iwl_tof_initiator_flags
|
||||||
|
* @request_id: A Token incremented per request. The same Token will be
|
||||||
|
* sent back in the range response
|
||||||
|
* @num_of_ap: Number of APs to measure (error if > IWL_MVM_TOF_MAX_APS)
|
||||||
|
* @range_req_bssid: ranging request BSSID
|
||||||
|
* @macaddr_mask: Bits set to 0 shall be copied from the MAC address template.
|
||||||
|
* Bits set to 1 shall be randomized by the UMAC
|
||||||
|
* @macaddr_template: MAC address template to use for non-randomized bits
|
||||||
|
* @req_timeout_ms: Requested timeout of the response in units of milliseconds.
|
||||||
|
* This is the session time for completing the measurement.
|
||||||
|
* @tsf_mac_id: report the measurement start time for each ap in terms of the
|
||||||
|
* TSF of this mac id. 0xff to disable TSF reporting.
|
||||||
|
* @common_calib: The common calib value to inject to this measurement calc
|
||||||
|
* @specific_calib: The specific calib value to inject to this measurement calc
|
||||||
|
* @ap: per-AP request data, see &struct iwl_tof_range_req_ap_entry_v2.
|
||||||
|
*/
|
||||||
|
struct iwl_tof_range_req_cmd {
|
||||||
|
__le32 initiator_flags;
|
||||||
|
u8 request_id;
|
||||||
|
u8 num_of_ap;
|
||||||
|
u8 range_req_bssid[ETH_ALEN];
|
||||||
|
u8 macaddr_mask[ETH_ALEN];
|
||||||
|
u8 macaddr_template[ETH_ALEN];
|
||||||
|
__le32 req_timeout_ms;
|
||||||
|
__le32 tsf_mac_id;
|
||||||
|
__le16 common_calib;
|
||||||
|
__le16 specific_calib;
|
||||||
|
struct iwl_tof_range_req_ap_entry ap[IWL_MVM_TOF_MAX_APS];
|
||||||
|
} __packed; /* LOCATION_RANGE_REQ_CMD_API_S_VER_7 */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* enum iwl_tof_range_request_status - status of the sent request
|
* enum iwl_tof_range_request_status - status of the sent request
|
||||||
* @IWL_TOF_RANGE_REQUEST_STATUS_SUCCESSFUL - FW successfully received the
|
* @IWL_TOF_RANGE_REQUEST_STATUS_SUCCESSFUL - FW successfully received the
|
||||||
|
@ -528,7 +626,7 @@ enum iwl_tof_entry_status {
|
||||||
}; /* LOCATION_RANGE_RSP_AP_ENTRY_NTFY_API_S_VER_2 */
|
}; /* LOCATION_RANGE_RSP_AP_ENTRY_NTFY_API_S_VER_2 */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct iwl_tof_range_rsp_ap_entry_ntfy - AP parameters (response)
|
* struct iwl_tof_range_rsp_ap_entry_ntfy_v3 - AP parameters (response)
|
||||||
* @bssid: BSSID of the AP
|
* @bssid: BSSID of the AP
|
||||||
* @measure_status: current APs measurement status, one of
|
* @measure_status: current APs measurement status, one of
|
||||||
* &enum iwl_tof_entry_status.
|
* &enum iwl_tof_entry_status.
|
||||||
|
@ -555,7 +653,7 @@ enum iwl_tof_entry_status {
|
||||||
* @papd_calib_output: The result of the tof papd calibration that was injected
|
* @papd_calib_output: The result of the tof papd calibration that was injected
|
||||||
* into the algorithm.
|
* into the algorithm.
|
||||||
*/
|
*/
|
||||||
struct iwl_tof_range_rsp_ap_entry_ntfy {
|
struct iwl_tof_range_rsp_ap_entry_ntfy_v3 {
|
||||||
u8 bssid[ETH_ALEN];
|
u8 bssid[ETH_ALEN];
|
||||||
u8 measure_status;
|
u8 measure_status;
|
||||||
u8 measure_bw;
|
u8 measure_bw;
|
||||||
|
@ -576,6 +674,59 @@ struct iwl_tof_range_rsp_ap_entry_ntfy {
|
||||||
__le32 papd_calib_output;
|
__le32 papd_calib_output;
|
||||||
} __packed; /* LOCATION_RANGE_RSP_AP_ETRY_NTFY_API_S_VER_3 */
|
} __packed; /* LOCATION_RANGE_RSP_AP_ETRY_NTFY_API_S_VER_3 */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct iwl_tof_range_rsp_ap_entry_ntfy - AP parameters (response)
|
||||||
|
* @bssid: BSSID of the AP
|
||||||
|
* @measure_status: current APs measurement status, one of
|
||||||
|
* &enum iwl_tof_entry_status.
|
||||||
|
* @measure_bw: Current AP Bandwidth: 0 20MHz, 1 40MHz, 2 80MHz
|
||||||
|
* @rtt: The Round Trip Time that took for the last measurement for
|
||||||
|
* current AP [pSec]
|
||||||
|
* @rtt_variance: The Variance of the RTT values measured for current AP
|
||||||
|
* @rtt_spread: The Difference between the maximum and the minimum RTT
|
||||||
|
* values measured for current AP in the current session [pSec]
|
||||||
|
* @rssi: RSSI as uploaded in the Channel Estimation notification
|
||||||
|
* @rssi_spread: The Difference between the maximum and the minimum RSSI values
|
||||||
|
* measured for current AP in the current session
|
||||||
|
* @last_burst: 1 if no more FTM sessions are scheduled for this responder
|
||||||
|
* @refusal_period: refusal period in case of
|
||||||
|
* @IWL_TOF_ENTRY_RESPONDER_CANNOT_COLABORATE [sec]
|
||||||
|
* @timestamp: The GP2 Clock [usec] where Channel Estimation notification was
|
||||||
|
* uploaded by the LMAC
|
||||||
|
* @start_tsf: measurement start time in TSF of the mac specified in the range
|
||||||
|
* request
|
||||||
|
* @rx_rate_n_flags: rate and flags of the last FTM frame received from this
|
||||||
|
* responder
|
||||||
|
* @tx_rate_n_flags: rate and flags of the last ack sent to this responder
|
||||||
|
* @t2t3_initiator: as calculated from the algo in the initiator
|
||||||
|
* @t1t4_responder: as calculated from the algo in the responder
|
||||||
|
* @common_calib: Calib val that was used in for this AP measurement
|
||||||
|
* @specific_calib: val that was used in for this AP measurement
|
||||||
|
* @papd_calib_output: The result of the tof papd calibration that was injected
|
||||||
|
* into the algorithm.
|
||||||
|
*/
|
||||||
|
struct iwl_tof_range_rsp_ap_entry_ntfy {
|
||||||
|
u8 bssid[ETH_ALEN];
|
||||||
|
u8 measure_status;
|
||||||
|
u8 measure_bw;
|
||||||
|
__le32 rtt;
|
||||||
|
__le32 rtt_variance;
|
||||||
|
__le32 rtt_spread;
|
||||||
|
s8 rssi;
|
||||||
|
u8 rssi_spread;
|
||||||
|
u8 last_burst;
|
||||||
|
u8 refusal_period;
|
||||||
|
__le32 timestamp;
|
||||||
|
__le32 start_tsf;
|
||||||
|
__le32 rx_rate_n_flags;
|
||||||
|
__le32 tx_rate_n_flags;
|
||||||
|
__le32 t2t3_initiator;
|
||||||
|
__le32 t1t4_responder;
|
||||||
|
__le16 common_calib;
|
||||||
|
__le16 specific_calib;
|
||||||
|
__le32 papd_calib_output;
|
||||||
|
} __packed; /* LOCATION_RANGE_RSP_AP_ETRY_NTFY_API_S_VER_4 */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* enum iwl_tof_response_status - tof response status
|
* enum iwl_tof_response_status - tof response status
|
||||||
*
|
*
|
||||||
|
@ -593,7 +744,7 @@ enum iwl_tof_response_status {
|
||||||
}; /* LOCATION_RNG_RSP_STATUS */
|
}; /* LOCATION_RNG_RSP_STATUS */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct iwl_tof_range_rsp_ntfy - ranging response notification
|
* struct iwl_tof_range_rsp_ntfy_v5 - ranging response notification
|
||||||
* @request_id: A Token ID of the corresponding Range request
|
* @request_id: A Token ID of the corresponding Range request
|
||||||
* @request_status: status of current measurement session, one of
|
* @request_status: status of current measurement session, one of
|
||||||
* &enum iwl_tof_response_status.
|
* &enum iwl_tof_response_status.
|
||||||
|
@ -601,13 +752,29 @@ enum iwl_tof_response_status {
|
||||||
* @num_of_aps: Number of APs to measure (error if > IWL_MVM_TOF_MAX_APS)
|
* @num_of_aps: Number of APs to measure (error if > IWL_MVM_TOF_MAX_APS)
|
||||||
* @ap: per-AP data
|
* @ap: per-AP data
|
||||||
*/
|
*/
|
||||||
struct iwl_tof_range_rsp_ntfy {
|
struct iwl_tof_range_rsp_ntfy_v5 {
|
||||||
u8 request_id;
|
u8 request_id;
|
||||||
u8 request_status;
|
u8 request_status;
|
||||||
u8 last_in_batch;
|
u8 last_in_batch;
|
||||||
u8 num_of_aps;
|
u8 num_of_aps;
|
||||||
|
struct iwl_tof_range_rsp_ap_entry_ntfy_v3 ap[IWL_MVM_TOF_MAX_APS];
|
||||||
|
} __packed; /* LOCATION_RANGE_RSP_NTFY_API_S_VER_5 */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct iwl_tof_range_rsp_ntfy - ranging response notification
|
||||||
|
* @request_id: A Token ID of the corresponding Range request
|
||||||
|
* @num_of_aps: Number of APs results
|
||||||
|
* @last_report: 1 if no more FTM sessions are scheduled, 0 otherwise.
|
||||||
|
* @reserved: reserved
|
||||||
|
* @ap: per-AP data
|
||||||
|
*/
|
||||||
|
struct iwl_tof_range_rsp_ntfy {
|
||||||
|
u8 request_id;
|
||||||
|
u8 num_of_aps;
|
||||||
|
u8 last_report;
|
||||||
|
u8 reserved;
|
||||||
struct iwl_tof_range_rsp_ap_entry_ntfy ap[IWL_MVM_TOF_MAX_APS];
|
struct iwl_tof_range_rsp_ap_entry_ntfy ap[IWL_MVM_TOF_MAX_APS];
|
||||||
} __packed;
|
} __packed; /* LOCATION_RANGE_RSP_NTFY_API_S_VER_6 */
|
||||||
|
|
||||||
#define IWL_MVM_TOF_MCSI_BUF_SIZE (245)
|
#define IWL_MVM_TOF_MCSI_BUF_SIZE (245)
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||||
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
|
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
|
||||||
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
|
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
|
||||||
* Copyright (C) 2018 Intel Corporation
|
* Copyright (C) 2018 - 2019 Intel Corporation
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of version 2 of the GNU General Public License as
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
|
@ -31,7 +31,7 @@
|
||||||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||||
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
|
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
|
||||||
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
|
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
|
||||||
* Copyright (C) 2018 Intel Corporation
|
* Copyright (C) 2018 - 2019 Intel Corporation
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -200,9 +200,16 @@ struct iwl_powertable_cmd {
|
||||||
* @DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK:
|
* @DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK:
|
||||||
* '1' Allow to save power by turning off
|
* '1' Allow to save power by turning off
|
||||||
* receiver and transmitter. '0' - does not allow.
|
* receiver and transmitter. '0' - does not allow.
|
||||||
|
* @DEVICE_POWER_FLAGS_ALLOW_MEM_RETENTION_MSK:
|
||||||
|
* Device Retention indication, '1' indicate retention is enabled.
|
||||||
|
* @DEVICE_POWER_FLAGS_32K_CLK_VALID_MSK:
|
||||||
|
* 32Khz external slow clock valid indication, '1' indicate cloack is
|
||||||
|
* valid.
|
||||||
*/
|
*/
|
||||||
enum iwl_device_power_flags {
|
enum iwl_device_power_flags {
|
||||||
DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK = BIT(0),
|
DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK = BIT(0),
|
||||||
|
DEVICE_POWER_FLAGS_ALLOW_MEM_RETENTION_MSK = BIT(1),
|
||||||
|
DEVICE_POWER_FLAGS_32K_CLK_VALID_MSK = BIT(12),
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||||
* Copyright(c) 2018 Intel Corporation
|
* Copyright(c) 2018 - 2019 Intel Corporation
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of version 2 of the GNU General Public License as
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
|
@ -31,7 +31,7 @@
|
||||||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||||
* Copyright(c) 2018 Intel Corporation
|
* Copyright(c) 2018 - 2019 Intel Corporation
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -434,7 +434,7 @@ struct iwl_periodic_scan_complete {
|
||||||
/* The maximum of either of these cannot exceed 8, because we use an
|
/* The maximum of either of these cannot exceed 8, because we use an
|
||||||
* 8-bit mask (see IWL_MVM_SCAN_MASK in mvm.h).
|
* 8-bit mask (see IWL_MVM_SCAN_MASK in mvm.h).
|
||||||
*/
|
*/
|
||||||
#define IWL_MVM_MAX_UMAC_SCANS 8
|
#define IWL_MVM_MAX_UMAC_SCANS 4
|
||||||
#define IWL_MVM_MAX_LMAC_SCANS 1
|
#define IWL_MVM_MAX_LMAC_SCANS 1
|
||||||
|
|
||||||
enum scan_config_flags {
|
enum scan_config_flags {
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
|
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
|
||||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||||
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
|
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
|
||||||
* Copyright(c) 2018 Intel Corporation
|
* Copyright(c) 2018 - 2019 Intel Corporation
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of version 2 of the GNU General Public License as
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
|
@ -31,7 +31,7 @@
|
||||||
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
|
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
|
||||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||||
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
|
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
|
||||||
* Copyright(c) 2018 Intel Corporation
|
* Copyright(c) 2018 - 2019 Intel Corporation
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* 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,
|
||||||
cfg->lmac[0].rxfifo1_size, 0, 0);
|
cfg->lmac[0].rxfifo1_size, 0, 0);
|
||||||
/* Pull RXF2 */
|
/* Pull RXF2 */
|
||||||
iwl_fwrt_dump_rxf(fwrt, dump_data, cfg->rxfifo2_size,
|
iwl_fwrt_dump_rxf(fwrt, dump_data, cfg->rxfifo2_size,
|
||||||
RXF_DIFF_FROM_PREV, 1);
|
RXF_DIFF_FROM_PREV +
|
||||||
|
fwrt->trans->cfg->umac_prph_offset, 1);
|
||||||
/* Pull LMAC2 RXF1 */
|
/* Pull LMAC2 RXF1 */
|
||||||
if (fwrt->smem_cfg.num_lmacs > 1)
|
if (fwrt->smem_cfg.num_lmacs > 1)
|
||||||
iwl_fwrt_dump_rxf(fwrt, dump_data,
|
iwl_fwrt_dump_rxf(fwrt, dump_data,
|
||||||
|
@ -673,7 +674,9 @@ static void iwl_fw_prph_handler(struct iwl_fw_runtime *fwrt, void *ptr,
|
||||||
{
|
{
|
||||||
u32 range_len;
|
u32 range_len;
|
||||||
|
|
||||||
if (fwrt->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22000) {
|
if (fwrt->trans->cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
|
||||||
|
/* TODO */
|
||||||
|
} else if (fwrt->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22000) {
|
||||||
range_len = ARRAY_SIZE(iwl_prph_dump_addr_22000);
|
range_len = ARRAY_SIZE(iwl_prph_dump_addr_22000);
|
||||||
handler(fwrt, iwl_prph_dump_addr_22000, range_len, ptr);
|
handler(fwrt, iwl_prph_dump_addr_22000, range_len, ptr);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1132,6 +1135,27 @@ static int iwl_dump_ini_paging_iter(struct iwl_fw_runtime *fwrt,
|
||||||
return le32_to_cpu(range->range_data_size);
|
return le32_to_cpu(range->range_data_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
iwl_dump_ini_mon_dram_iter(struct iwl_fw_runtime *fwrt,
|
||||||
|
struct iwl_fw_ini_error_dump_range *range,
|
||||||
|
struct iwl_fw_ini_region_cfg *reg,
|
||||||
|
int idx)
|
||||||
|
{
|
||||||
|
u32 start_addr = iwl_read_umac_prph(fwrt->trans,
|
||||||
|
MON_BUFF_BASE_ADDR_VER2);
|
||||||
|
|
||||||
|
if (start_addr == 0x5a5a5a5a)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
range->start_addr = cpu_to_le32(start_addr);
|
||||||
|
range->range_data_size = cpu_to_le32(fwrt->trans->fw_mon[idx].size);
|
||||||
|
|
||||||
|
memcpy(range->data, fwrt->trans->fw_mon[idx].block,
|
||||||
|
fwrt->trans->fw_mon[idx].size);
|
||||||
|
|
||||||
|
return le32_to_cpu(range->range_data_size);
|
||||||
|
}
|
||||||
|
|
||||||
static struct iwl_fw_ini_error_dump_range
|
static struct iwl_fw_ini_error_dump_range
|
||||||
*iwl_dump_ini_mem_fill_header(struct iwl_fw_runtime *fwrt, void *data)
|
*iwl_dump_ini_mem_fill_header(struct iwl_fw_runtime *fwrt, void *data)
|
||||||
{
|
{
|
||||||
|
@ -1140,6 +1164,29 @@ static struct iwl_fw_ini_error_dump_range
|
||||||
return dump->ranges;
|
return dump->ranges;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct iwl_fw_ini_error_dump_range
|
||||||
|
*iwl_dump_ini_mon_dram_fill_header(struct iwl_fw_runtime *fwrt, void *data)
|
||||||
|
{
|
||||||
|
struct iwl_fw_ini_monitor_dram_dump *mon_dump = (void *)data;
|
||||||
|
u32 write_ptr, cycle_cnt;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
if (!iwl_trans_grab_nic_access(fwrt->trans, &flags)) {
|
||||||
|
IWL_ERR(fwrt, "Failed to get DRAM monitor header\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
write_ptr = iwl_read_umac_prph_no_grab(fwrt->trans,
|
||||||
|
MON_BUFF_WRPTR_VER2);
|
||||||
|
cycle_cnt = iwl_read_umac_prph_no_grab(fwrt->trans,
|
||||||
|
MON_BUFF_CYCLE_CNT_VER2);
|
||||||
|
iwl_trans_release_nic_access(fwrt->trans, &flags);
|
||||||
|
|
||||||
|
mon_dump->write_ptr = cpu_to_le32(write_ptr);
|
||||||
|
mon_dump->cycle_cnt = cpu_to_le32(cycle_cnt);
|
||||||
|
|
||||||
|
return mon_dump->ranges;
|
||||||
|
}
|
||||||
|
|
||||||
static u32 iwl_dump_ini_mem_get_size(struct iwl_fw_runtime *fwrt,
|
static u32 iwl_dump_ini_mem_get_size(struct iwl_fw_runtime *fwrt,
|
||||||
struct iwl_fw_ini_region_cfg *reg)
|
struct iwl_fw_ini_region_cfg *reg)
|
||||||
{
|
{
|
||||||
|
@ -1169,6 +1216,12 @@ static u32 iwl_dump_ini_paging_get_size(struct iwl_fw_runtime *fwrt,
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static u32 iwl_dump_ini_mon_dram_get_size(struct iwl_fw_runtime *fwrt,
|
||||||
|
struct iwl_fw_ini_region_cfg *reg)
|
||||||
|
{
|
||||||
|
return fwrt->trans->num_blocks ? fwrt->trans->fw_mon[0].size : 0;
|
||||||
|
}
|
||||||
|
|
||||||
static u32 iwl_dump_ini_mem_ranges(struct iwl_fw_runtime *fwrt,
|
static u32 iwl_dump_ini_mem_ranges(struct iwl_fw_runtime *fwrt,
|
||||||
struct iwl_fw_ini_region_cfg *reg)
|
struct iwl_fw_ini_region_cfg *reg)
|
||||||
{
|
{
|
||||||
|
@ -1187,6 +1240,12 @@ static u32 iwl_dump_ini_paging_ranges(struct iwl_fw_runtime *fwrt,
|
||||||
return fwrt->num_of_paging_blk;
|
return fwrt->num_of_paging_blk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static u32 iwl_dump_ini_mon_dram_ranges(struct iwl_fw_runtime *fwrt,
|
||||||
|
struct iwl_fw_ini_region_cfg *reg)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct iwl_dump_ini_mem_ops - ini memory dump operations
|
* struct iwl_dump_ini_mem_ops - ini memory dump operations
|
||||||
* @get_num_of_ranges: returns the number of memory ranges in the region.
|
* @get_num_of_ranges: returns the number of memory ranges in the region.
|
||||||
|
@ -1284,6 +1343,7 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt,
|
||||||
case IWL_FW_INI_REGION_PERIPHERY_MAC:
|
case IWL_FW_INI_REGION_PERIPHERY_MAC:
|
||||||
case IWL_FW_INI_REGION_PERIPHERY_PHY:
|
case IWL_FW_INI_REGION_PERIPHERY_PHY:
|
||||||
case IWL_FW_INI_REGION_PERIPHERY_AUX:
|
case IWL_FW_INI_REGION_PERIPHERY_AUX:
|
||||||
|
case IWL_FW_INI_REGION_INTERNAL_BUFFER:
|
||||||
case IWL_FW_INI_REGION_CSR:
|
case IWL_FW_INI_REGION_CSR:
|
||||||
size += hdr_len + dump_header_len + range_header_len *
|
size += hdr_len + dump_header_len + range_header_len *
|
||||||
iwl_dump_ini_mem_ranges(fwrt, reg) +
|
iwl_dump_ini_mem_ranges(fwrt, reg) +
|
||||||
|
@ -1311,8 +1371,13 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case IWL_FW_INI_REGION_DRAM_BUFFER:
|
case IWL_FW_INI_REGION_DRAM_BUFFER:
|
||||||
/* Transport takes care of DRAM dumping */
|
if (!fwrt->trans->num_blocks)
|
||||||
case IWL_FW_INI_REGION_INTERNAL_BUFFER:
|
break;
|
||||||
|
size += hdr_len +
|
||||||
|
sizeof(struct iwl_fw_ini_monitor_dram_dump) *
|
||||||
|
iwl_dump_ini_mon_dram_ranges(fwrt, reg) +
|
||||||
|
iwl_dump_ini_mon_dram_get_size(fwrt, reg);
|
||||||
|
break;
|
||||||
case IWL_FW_INI_REGION_DRAM_IMR:
|
case IWL_FW_INI_REGION_DRAM_IMR:
|
||||||
/* Undefined yet */
|
/* Undefined yet */
|
||||||
default:
|
default:
|
||||||
|
@ -1324,8 +1389,7 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt,
|
||||||
|
|
||||||
static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt,
|
static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt,
|
||||||
struct iwl_fw_ini_trigger *trigger,
|
struct iwl_fw_ini_trigger *trigger,
|
||||||
struct iwl_fw_error_dump_data **data,
|
struct iwl_fw_error_dump_data **data)
|
||||||
u32 *dump_mask)
|
|
||||||
{
|
{
|
||||||
int i, num = le32_to_cpu(trigger->num_regions);
|
int i, num = le32_to_cpu(trigger->num_regions);
|
||||||
|
|
||||||
|
@ -1346,6 +1410,7 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt,
|
||||||
type = le32_to_cpu(reg->region_type);
|
type = le32_to_cpu(reg->region_type);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case IWL_FW_INI_REGION_DEVICE_MEMORY:
|
case IWL_FW_INI_REGION_DEVICE_MEMORY:
|
||||||
|
case IWL_FW_INI_REGION_INTERNAL_BUFFER:
|
||||||
ops.get_num_of_ranges = iwl_dump_ini_mem_ranges;
|
ops.get_num_of_ranges = iwl_dump_ini_mem_ranges;
|
||||||
ops.get_size = iwl_dump_ini_mem_get_size;
|
ops.get_size = iwl_dump_ini_mem_get_size;
|
||||||
ops.fill_mem_hdr = iwl_dump_ini_mem_fill_header;
|
ops.fill_mem_hdr = iwl_dump_ini_mem_fill_header;
|
||||||
|
@ -1362,7 +1427,11 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt,
|
||||||
iwl_dump_ini_mem(fwrt, type, data, reg, &ops);
|
iwl_dump_ini_mem(fwrt, type, data, reg, &ops);
|
||||||
break;
|
break;
|
||||||
case IWL_FW_INI_REGION_DRAM_BUFFER:
|
case IWL_FW_INI_REGION_DRAM_BUFFER:
|
||||||
*dump_mask |= BIT(IWL_FW_ERROR_DUMP_FW_MONITOR);
|
ops.get_num_of_ranges = iwl_dump_ini_mon_dram_ranges;
|
||||||
|
ops.get_size = iwl_dump_ini_mon_dram_get_size;
|
||||||
|
ops.fill_mem_hdr = iwl_dump_ini_mon_dram_fill_header;
|
||||||
|
ops.fill_range = iwl_dump_ini_mon_dram_iter;
|
||||||
|
iwl_dump_ini_mem(fwrt, type, data, reg, &ops);
|
||||||
break;
|
break;
|
||||||
case IWL_FW_INI_REGION_PAGING: {
|
case IWL_FW_INI_REGION_PAGING: {
|
||||||
ops.fill_mem_hdr = iwl_dump_ini_mem_fill_header;
|
ops.fill_mem_hdr = iwl_dump_ini_mem_fill_header;
|
||||||
|
@ -1396,7 +1465,6 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt,
|
||||||
iwl_dump_ini_mem(fwrt, type, data, reg, &ops);
|
iwl_dump_ini_mem(fwrt, type, data, reg, &ops);
|
||||||
break;
|
break;
|
||||||
case IWL_FW_INI_REGION_DRAM_IMR:
|
case IWL_FW_INI_REGION_DRAM_IMR:
|
||||||
case IWL_FW_INI_REGION_INTERNAL_BUFFER:
|
|
||||||
/* This is undefined yet */
|
/* This is undefined yet */
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -1406,26 +1474,23 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt,
|
||||||
|
|
||||||
static struct iwl_fw_error_dump_file *
|
static struct iwl_fw_error_dump_file *
|
||||||
_iwl_fw_error_ini_dump(struct iwl_fw_runtime *fwrt,
|
_iwl_fw_error_ini_dump(struct iwl_fw_runtime *fwrt,
|
||||||
struct iwl_fw_dump_ptrs *fw_error_dump,
|
struct iwl_fw_dump_ptrs *fw_error_dump)
|
||||||
u32 *dump_mask)
|
|
||||||
{
|
{
|
||||||
int size, id = le32_to_cpu(fwrt->dump.desc->trig_desc.type);
|
int size, id = le32_to_cpu(fwrt->dump.desc->trig_desc.type);
|
||||||
struct iwl_fw_error_dump_data *dump_data;
|
struct iwl_fw_error_dump_data *dump_data;
|
||||||
struct iwl_fw_error_dump_file *dump_file;
|
struct iwl_fw_error_dump_file *dump_file;
|
||||||
struct iwl_fw_ini_trigger *trigger, *ext;
|
struct iwl_fw_ini_trigger *trigger;
|
||||||
|
|
||||||
if (id == FW_DBG_TRIGGER_FW_ASSERT)
|
if (id == FW_DBG_TRIGGER_FW_ASSERT)
|
||||||
id = IWL_FW_TRIGGER_ID_FW_ASSERT;
|
id = IWL_FW_TRIGGER_ID_FW_ASSERT;
|
||||||
|
|
||||||
if (WARN_ON(id >= ARRAY_SIZE(fwrt->dump.active_trigs)))
|
if (!iwl_fw_ini_trigger_on(fwrt, id))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
trigger = fwrt->dump.active_trigs[id].conf;
|
trigger = fwrt->dump.active_trigs[id].trig;
|
||||||
ext = fwrt->dump.active_trigs[id].conf_ext;
|
|
||||||
|
|
||||||
size = sizeof(*dump_file);
|
size = sizeof(*dump_file);
|
||||||
size += iwl_fw_ini_get_trigger_len(fwrt, trigger);
|
size += iwl_fw_ini_get_trigger_len(fwrt, trigger);
|
||||||
size += iwl_fw_ini_get_trigger_len(fwrt, ext);
|
|
||||||
|
|
||||||
if (!size)
|
if (!size)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1440,11 +1505,7 @@ _iwl_fw_error_ini_dump(struct iwl_fw_runtime *fwrt,
|
||||||
dump_data = (void *)dump_file->data;
|
dump_data = (void *)dump_file->data;
|
||||||
dump_file->file_len = cpu_to_le32(size);
|
dump_file->file_len = cpu_to_le32(size);
|
||||||
|
|
||||||
*dump_mask = 0;
|
iwl_fw_ini_dump_trigger(fwrt, trigger, &dump_data);
|
||||||
if (trigger)
|
|
||||||
iwl_fw_ini_dump_trigger(fwrt, trigger, &dump_data, dump_mask);
|
|
||||||
if (ext)
|
|
||||||
iwl_fw_ini_dump_trigger(fwrt, ext, &dump_data, dump_mask);
|
|
||||||
|
|
||||||
return dump_file;
|
return dump_file;
|
||||||
}
|
}
|
||||||
|
@ -1470,8 +1531,7 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (fwrt->trans->ini_valid)
|
if (fwrt->trans->ini_valid)
|
||||||
dump_file = _iwl_fw_error_ini_dump(fwrt, fw_error_dump,
|
dump_file = _iwl_fw_error_ini_dump(fwrt, fw_error_dump);
|
||||||
&dump_mask);
|
|
||||||
else
|
else
|
||||||
dump_file = _iwl_fw_error_dump(fwrt, fw_error_dump);
|
dump_file = _iwl_fw_error_dump(fwrt, fw_error_dump);
|
||||||
|
|
||||||
|
@ -1483,7 +1543,10 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
|
||||||
if (!fwrt->trans->ini_valid && fwrt->dump.monitor_only)
|
if (!fwrt->trans->ini_valid && fwrt->dump.monitor_only)
|
||||||
dump_mask &= IWL_FW_ERROR_DUMP_FW_MONITOR;
|
dump_mask &= IWL_FW_ERROR_DUMP_FW_MONITOR;
|
||||||
|
|
||||||
fw_error_dump->trans_ptr = iwl_trans_dump_data(fwrt->trans, dump_mask);
|
if (!fwrt->trans->ini_valid)
|
||||||
|
fw_error_dump->trans_ptr =
|
||||||
|
iwl_trans_dump_data(fwrt->trans, dump_mask);
|
||||||
|
|
||||||
file_len = le32_to_cpu(dump_file->file_len);
|
file_len = le32_to_cpu(dump_file->file_len);
|
||||||
fw_error_dump->fwrt_len = file_len;
|
fw_error_dump->fwrt_len = file_len;
|
||||||
if (fw_error_dump->trans_ptr) {
|
if (fw_error_dump->trans_ptr) {
|
||||||
|
@ -1557,7 +1620,7 @@ int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt,
|
||||||
fwrt->dump.desc = desc;
|
fwrt->dump.desc = desc;
|
||||||
fwrt->dump.monitor_only = monitor_only;
|
fwrt->dump.monitor_only = monitor_only;
|
||||||
|
|
||||||
schedule_delayed_work(&fwrt->dump.wk, delay);
|
schedule_delayed_work(&fwrt->dump.wk, usecs_to_jiffies(delay));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1613,8 +1676,10 @@ int _iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt,
|
||||||
}
|
}
|
||||||
|
|
||||||
trigger->occurrences = cpu_to_le16(occurrences);
|
trigger->occurrences = cpu_to_le16(occurrences);
|
||||||
delay = le16_to_cpu(trigger->trig_dis_ms);
|
|
||||||
monitor_only = trigger->mode & IWL_FW_DBG_TRIGGER_MONITOR_ONLY;
|
monitor_only = trigger->mode & IWL_FW_DBG_TRIGGER_MONITOR_ONLY;
|
||||||
|
|
||||||
|
/* convert msec to usec */
|
||||||
|
delay = le32_to_cpu(trigger->stop_delay) * USEC_PER_MSEC;
|
||||||
}
|
}
|
||||||
|
|
||||||
desc = kzalloc(sizeof(*desc) + len, GFP_ATOMIC);
|
desc = kzalloc(sizeof(*desc) + len, GFP_ATOMIC);
|
||||||
|
@ -1634,6 +1699,7 @@ int iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt,
|
||||||
u32 id, const char *str, size_t len)
|
u32 id, const char *str, size_t len)
|
||||||
{
|
{
|
||||||
struct iwl_fw_dump_desc *desc;
|
struct iwl_fw_dump_desc *desc;
|
||||||
|
struct iwl_fw_ini_active_triggers *active;
|
||||||
u32 occur, delay;
|
u32 occur, delay;
|
||||||
|
|
||||||
if (!fwrt->trans->ini_valid)
|
if (!fwrt->trans->ini_valid)
|
||||||
|
@ -1642,15 +1708,17 @@ int iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt,
|
||||||
if (id == FW_DBG_TRIGGER_USER)
|
if (id == FW_DBG_TRIGGER_USER)
|
||||||
id = IWL_FW_TRIGGER_ID_USER_TRIGGER;
|
id = IWL_FW_TRIGGER_ID_USER_TRIGGER;
|
||||||
|
|
||||||
if (WARN_ON(!fwrt->dump.active_trigs[id].active))
|
active = &fwrt->dump.active_trigs[id];
|
||||||
|
|
||||||
|
if (WARN_ON(!active->active))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
delay = le32_to_cpu(fwrt->dump.active_trigs[id].conf->dump_delay);
|
delay = le32_to_cpu(active->trig->dump_delay);
|
||||||
occur = le32_to_cpu(fwrt->dump.active_trigs[id].conf->occurrences);
|
occur = le32_to_cpu(active->trig->occurrences);
|
||||||
if (!occur)
|
if (!occur)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (le32_to_cpu(fwrt->dump.active_trigs[id].conf->force_restart)) {
|
if (le32_to_cpu(active->trig->force_restart)) {
|
||||||
IWL_WARN(fwrt, "Force restart: trigger %d fired.\n", id);
|
IWL_WARN(fwrt, "Force restart: trigger %d fired.\n", id);
|
||||||
iwl_force_nmi(fwrt->trans);
|
iwl_force_nmi(fwrt->trans);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1660,8 +1728,7 @@ int iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt,
|
||||||
if (!desc)
|
if (!desc)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
occur--;
|
active->trig->occurrences = cpu_to_le32(--occur);
|
||||||
fwrt->dump.active_trigs[id].conf->occurrences = cpu_to_le32(occur);
|
|
||||||
|
|
||||||
desc->len = len;
|
desc->len = len;
|
||||||
desc->trig_desc.type = cpu_to_le32(id);
|
desc->trig_desc.type = cpu_to_le32(id);
|
||||||
|
@ -1853,7 +1920,8 @@ iwl_fw_dbg_buffer_allocation(struct iwl_fw_runtime *fwrt, u32 size)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void iwl_fw_dbg_buffer_apply(struct iwl_fw_runtime *fwrt,
|
static void iwl_fw_dbg_buffer_apply(struct iwl_fw_runtime *fwrt,
|
||||||
struct iwl_fw_ini_allocation_data *alloc)
|
struct iwl_fw_ini_allocation_data *alloc,
|
||||||
|
enum iwl_fw_ini_apply_point pnt)
|
||||||
{
|
{
|
||||||
struct iwl_trans *trans = fwrt->trans;
|
struct iwl_trans *trans = fwrt->trans;
|
||||||
struct iwl_ldbg_config_cmd ldbg_cmd = {
|
struct iwl_ldbg_config_cmd ldbg_cmd = {
|
||||||
|
@ -1867,9 +1935,19 @@ static void iwl_fw_dbg_buffer_apply(struct iwl_fw_runtime *fwrt,
|
||||||
.len[0] = sizeof(ldbg_cmd),
|
.len[0] = sizeof(ldbg_cmd),
|
||||||
};
|
};
|
||||||
int block_idx = trans->num_blocks;
|
int block_idx = trans->num_blocks;
|
||||||
|
u32 buf_location = le32_to_cpu(alloc->tlv.buffer_location);
|
||||||
|
|
||||||
if (le32_to_cpu(alloc->tlv.buffer_location) !=
|
if (buf_location == IWL_FW_INI_LOCATION_SRAM_PATH) {
|
||||||
IWL_FW_INI_LOCATION_DRAM_PATH)
|
if (!WARN(pnt != IWL_FW_INI_APPLY_EARLY,
|
||||||
|
"Invalid apply point %d for SMEM buffer allocation",
|
||||||
|
pnt))
|
||||||
|
/* set sram monitor by enabling bit 7 */
|
||||||
|
iwl_set_bit(fwrt->trans, CSR_HW_IF_CONFIG_REG,
|
||||||
|
CSR_HW_IF_CONFIG_REG_BIT_MONITOR_SRAM);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buf_location != IWL_FW_INI_LOCATION_DRAM_PATH)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!alloc->is_alloc) {
|
if (!alloc->is_alloc) {
|
||||||
|
@ -1949,6 +2027,26 @@ static void iwl_fw_dbg_update_regions(struct iwl_fw_runtime *fwrt,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int iwl_fw_dbg_trig_realloc(struct iwl_fw_runtime *fwrt,
|
||||||
|
struct iwl_fw_ini_active_triggers *active,
|
||||||
|
u32 id, int size)
|
||||||
|
{
|
||||||
|
void *ptr;
|
||||||
|
|
||||||
|
if (size <= active->size)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ptr = krealloc(active->trig, size, GFP_KERNEL);
|
||||||
|
if (!ptr) {
|
||||||
|
IWL_ERR(fwrt, "Failed to allocate memory for trigger %d\n", id);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
active->trig = ptr;
|
||||||
|
active->size = size;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void iwl_fw_dbg_update_triggers(struct iwl_fw_runtime *fwrt,
|
static void iwl_fw_dbg_update_triggers(struct iwl_fw_runtime *fwrt,
|
||||||
struct iwl_fw_ini_trigger_tlv *tlv,
|
struct iwl_fw_ini_trigger_tlv *tlv,
|
||||||
bool ext,
|
bool ext,
|
||||||
|
@ -1961,43 +2059,63 @@ static void iwl_fw_dbg_update_triggers(struct iwl_fw_runtime *fwrt,
|
||||||
struct iwl_fw_ini_trigger *trig = iter;
|
struct iwl_fw_ini_trigger *trig = iter;
|
||||||
struct iwl_fw_ini_active_triggers *active;
|
struct iwl_fw_ini_active_triggers *active;
|
||||||
int id = le32_to_cpu(trig->trigger_id);
|
int id = le32_to_cpu(trig->trigger_id);
|
||||||
u32 num;
|
u32 trig_regs_size = le32_to_cpu(trig->num_regions) *
|
||||||
|
sizeof(__le32);
|
||||||
|
|
||||||
if (WARN_ON(id >= ARRAY_SIZE(fwrt->dump.active_trigs)))
|
if (WARN_ON(id >= ARRAY_SIZE(fwrt->dump.active_trigs)))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
active = &fwrt->dump.active_trigs[id];
|
active = &fwrt->dump.active_trigs[id];
|
||||||
|
|
||||||
if (active->apply_point != apply_point) {
|
if (!active->active) {
|
||||||
active->conf = NULL;
|
size_t trig_size = sizeof(*trig) + trig_regs_size;
|
||||||
active->conf_ext = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
num = le32_to_cpu(trig->num_regions);
|
if (iwl_fw_dbg_trig_realloc(fwrt, active, id,
|
||||||
|
trig_size))
|
||||||
|
goto next;
|
||||||
|
|
||||||
|
memcpy(active->trig, trig, trig_size);
|
||||||
|
|
||||||
if (ext && active->apply_point == apply_point) {
|
|
||||||
num += le32_to_cpu(active->conf->num_regions);
|
|
||||||
if (trig->ignore_default) {
|
|
||||||
active->conf_ext = active->conf;
|
|
||||||
active->conf = trig;
|
|
||||||
} else {
|
|
||||||
active->conf_ext = trig;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
active->conf = trig;
|
u32 conf_override =
|
||||||
|
!(le32_to_cpu(trig->override_trig) & 0xff);
|
||||||
|
u32 region_override =
|
||||||
|
!(le32_to_cpu(trig->override_trig) & 0xff00);
|
||||||
|
u32 offset = 0;
|
||||||
|
u32 active_regs =
|
||||||
|
le32_to_cpu(active->trig->num_regions);
|
||||||
|
u32 new_regs = le32_to_cpu(trig->num_regions);
|
||||||
|
int mem_to_add = trig_regs_size;
|
||||||
|
|
||||||
|
if (region_override) {
|
||||||
|
mem_to_add -= active_regs * sizeof(__le32);
|
||||||
|
} else {
|
||||||
|
offset += active_regs;
|
||||||
|
new_regs += active_regs;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iwl_fw_dbg_trig_realloc(fwrt, active, id,
|
||||||
|
active->size + mem_to_add))
|
||||||
|
goto next;
|
||||||
|
|
||||||
|
if (conf_override)
|
||||||
|
memcpy(active->trig, trig, sizeof(*trig));
|
||||||
|
|
||||||
|
memcpy(active->trig->data + offset, trig->data,
|
||||||
|
trig_regs_size);
|
||||||
|
active->trig->num_regions = cpu_to_le32(new_regs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Since zero means infinity - just set to -1 */
|
/* Since zero means infinity - just set to -1 */
|
||||||
if (!le32_to_cpu(trig->occurrences))
|
if (!le32_to_cpu(active->trig->occurrences))
|
||||||
trig->occurrences = cpu_to_le32(-1);
|
active->trig->occurrences = cpu_to_le32(-1);
|
||||||
if (!le32_to_cpu(trig->ignore_consec))
|
if (!le32_to_cpu(active->trig->ignore_consec))
|
||||||
trig->ignore_consec = cpu_to_le32(-1);
|
active->trig->ignore_consec = cpu_to_le32(-1);
|
||||||
|
|
||||||
iter += sizeof(*trig) +
|
active->active = true;
|
||||||
le32_to_cpu(trig->num_regions) * sizeof(__le32);
|
next:
|
||||||
|
iter += sizeof(*trig) + trig_regs_size;
|
||||||
|
|
||||||
active->active = num;
|
|
||||||
active->apply_point = apply_point;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2017,7 +2135,7 @@ static void _iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt,
|
||||||
case IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION: {
|
case IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION: {
|
||||||
struct iwl_fw_ini_allocation_data *buf_alloc = ini_tlv;
|
struct iwl_fw_ini_allocation_data *buf_alloc = ini_tlv;
|
||||||
|
|
||||||
iwl_fw_dbg_buffer_apply(fwrt, ini_tlv);
|
iwl_fw_dbg_buffer_apply(fwrt, ini_tlv, pnt);
|
||||||
iter += sizeof(buf_alloc->is_alloc);
|
iter += sizeof(buf_alloc->is_alloc);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2056,6 +2174,10 @@ void iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt,
|
||||||
if (apply_point == IWL_FW_INI_APPLY_EARLY) {
|
if (apply_point == IWL_FW_INI_APPLY_EARLY) {
|
||||||
for (i = 0; i < IWL_FW_INI_MAX_REGION_ID; i++)
|
for (i = 0; i < IWL_FW_INI_MAX_REGION_ID; i++)
|
||||||
fwrt->dump.active_regs[i] = NULL;
|
fwrt->dump.active_regs[i] = NULL;
|
||||||
|
|
||||||
|
/* disable the triggers, used in recovery flow */
|
||||||
|
for (i = 0; i < IWL_FW_TRIGGER_ID_NUM; i++)
|
||||||
|
fwrt->dump.active_trigs[i].active = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_iwl_fw_dbg_apply_point(fwrt, data, apply_point, false);
|
_iwl_fw_dbg_apply_point(fwrt, data, apply_point, false);
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
|
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
|
||||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||||
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
|
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
|
||||||
* Copyright(c) 2018 Intel Corporation
|
* Copyright(c) 2018 - 2019 Intel Corporation
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of version 2 of the GNU General Public License as
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
|
@ -31,7 +31,7 @@
|
||||||
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
|
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
|
||||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||||
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
|
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
|
||||||
* Copyright(c) 2018 Intel Corporation
|
* Copyright(c) 2018 - 2019 Intel Corporation
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -162,9 +162,9 @@ iwl_fw_dbg_trigger_stop_conf_match(struct iwl_fw_runtime *fwrt,
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
iwl_fw_dbg_no_trig_window(struct iwl_fw_runtime *fwrt, u32 id, u32 dis_ms)
|
iwl_fw_dbg_no_trig_window(struct iwl_fw_runtime *fwrt, u32 id, u32 dis_usec)
|
||||||
{
|
{
|
||||||
unsigned long wind_jiff = msecs_to_jiffies(dis_ms);
|
unsigned long wind_jiff = usecs_to_jiffies(dis_usec);
|
||||||
|
|
||||||
/* If this is the first event checked, jump to update start ts */
|
/* If this is the first event checked, jump to update start ts */
|
||||||
if (fwrt->dump.non_collect_ts_start[id] &&
|
if (fwrt->dump.non_collect_ts_start[id] &&
|
||||||
|
@ -181,11 +181,12 @@ iwl_fw_dbg_trigger_check_stop(struct iwl_fw_runtime *fwrt,
|
||||||
struct wireless_dev *wdev,
|
struct wireless_dev *wdev,
|
||||||
struct iwl_fw_dbg_trigger_tlv *trig)
|
struct iwl_fw_dbg_trigger_tlv *trig)
|
||||||
{
|
{
|
||||||
|
u32 usec = le16_to_cpu(trig->trig_dis_ms) * USEC_PER_MSEC;
|
||||||
|
|
||||||
if (wdev && !iwl_fw_dbg_trigger_vif_match(trig, wdev))
|
if (wdev && !iwl_fw_dbg_trigger_vif_match(trig, wdev))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (iwl_fw_dbg_no_trig_window(fwrt, le32_to_cpu(trig->id),
|
if (iwl_fw_dbg_no_trig_window(fwrt, le32_to_cpu(trig->id), usec)) {
|
||||||
le16_to_cpu(trig->trig_dis_ms))) {
|
|
||||||
IWL_WARN(fwrt, "Trigger %d occurred while no-collect window.\n",
|
IWL_WARN(fwrt, "Trigger %d occurred while no-collect window.\n",
|
||||||
trig->id);
|
trig->id);
|
||||||
return false;
|
return false;
|
||||||
|
@ -222,23 +223,22 @@ _iwl_fw_dbg_trigger_on(struct iwl_fw_runtime *fwrt,
|
||||||
})
|
})
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
_iwl_fw_ini_trigger_on(struct iwl_fw_runtime *fwrt,
|
iwl_fw_ini_trigger_on(struct iwl_fw_runtime *fwrt,
|
||||||
const enum iwl_fw_dbg_trigger id)
|
enum iwl_fw_ini_trigger_id id)
|
||||||
{
|
{
|
||||||
struct iwl_fw_ini_active_triggers *trig = &fwrt->dump.active_trigs[id];
|
struct iwl_fw_ini_trigger *trig;
|
||||||
u32 ms;
|
u32 usec;
|
||||||
|
|
||||||
if (!fwrt->trans->ini_valid)
|
|
||||||
|
|
||||||
|
if (!fwrt->trans->ini_valid || id >= IWL_FW_TRIGGER_ID_NUM ||
|
||||||
|
!fwrt->dump.active_trigs[id].active)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!trig || !trig->active)
|
trig = fwrt->dump.active_trigs[id].trig;
|
||||||
return false;
|
usec = le32_to_cpu(trig->ignore_consec);
|
||||||
|
|
||||||
ms = le32_to_cpu(trig->conf->ignore_consec);
|
if (iwl_fw_dbg_no_trig_window(fwrt, id, usec)) {
|
||||||
if (ms)
|
|
||||||
ms /= USEC_PER_MSEC;
|
|
||||||
|
|
||||||
if (iwl_fw_dbg_no_trig_window(fwrt, id, ms)) {
|
|
||||||
IWL_WARN(fwrt, "Trigger %d fired in no-collect window\n", id);
|
IWL_WARN(fwrt, "Trigger %d fired in no-collect window\n", id);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -246,12 +246,6 @@ _iwl_fw_ini_trigger_on(struct iwl_fw_runtime *fwrt,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define iwl_fw_ini_trigger_on(fwrt, wdev, id) ({ \
|
|
||||||
BUILD_BUG_ON(!__builtin_constant_p(id)); \
|
|
||||||
BUILD_BUG_ON((id) >= IWL_FW_TRIGGER_ID_NUM); \
|
|
||||||
_iwl_fw_ini_trigger_on((fwrt), (wdev), (id)); \
|
|
||||||
})
|
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
_iwl_fw_dbg_trigger_simple_stop(struct iwl_fw_runtime *fwrt,
|
_iwl_fw_dbg_trigger_simple_stop(struct iwl_fw_runtime *fwrt,
|
||||||
struct wireless_dev *wdev,
|
struct wireless_dev *wdev,
|
||||||
|
@ -298,13 +292,13 @@ _iwl_fw_dbg_stop_recording(struct iwl_trans *trans,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params) {
|
if (params) {
|
||||||
params->in_sample = iwl_read_prph(trans, DBGC_IN_SAMPLE);
|
params->in_sample = iwl_read_umac_prph(trans, DBGC_IN_SAMPLE);
|
||||||
params->out_ctrl = iwl_read_prph(trans, DBGC_OUT_CTRL);
|
params->out_ctrl = iwl_read_umac_prph(trans, DBGC_OUT_CTRL);
|
||||||
}
|
}
|
||||||
|
|
||||||
iwl_write_prph(trans, DBGC_IN_SAMPLE, 0);
|
iwl_write_umac_prph(trans, DBGC_IN_SAMPLE, 0);
|
||||||
udelay(100);
|
udelay(100);
|
||||||
iwl_write_prph(trans, DBGC_OUT_CTRL, 0);
|
iwl_write_umac_prph(trans, DBGC_OUT_CTRL, 0);
|
||||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||||
trans->dbg_rec_on = false;
|
trans->dbg_rec_on = false;
|
||||||
#endif
|
#endif
|
||||||
|
@ -332,9 +326,9 @@ _iwl_fw_dbg_restart_recording(struct iwl_trans *trans,
|
||||||
iwl_clear_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x1);
|
iwl_clear_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x1);
|
||||||
iwl_set_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x1);
|
iwl_set_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x1);
|
||||||
} else {
|
} else {
|
||||||
iwl_write_prph(trans, DBGC_IN_SAMPLE, params->in_sample);
|
iwl_write_umac_prph(trans, DBGC_IN_SAMPLE, params->in_sample);
|
||||||
udelay(100);
|
udelay(100);
|
||||||
iwl_write_prph(trans, DBGC_OUT_CTRL, params->out_ctrl);
|
iwl_write_umac_prph(trans, DBGC_OUT_CTRL, params->out_ctrl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -375,7 +369,9 @@ static inline bool iwl_fw_dbg_is_d3_debug_enabled(struct iwl_fw_runtime *fwrt)
|
||||||
{
|
{
|
||||||
return fw_has_capa(&fwrt->fw->ucode_capa,
|
return fw_has_capa(&fwrt->fw->ucode_capa,
|
||||||
IWL_UCODE_TLV_CAPA_D3_DEBUG) &&
|
IWL_UCODE_TLV_CAPA_D3_DEBUG) &&
|
||||||
fwrt->trans->cfg->d3_debug_data_length &&
|
fwrt->trans->cfg->d3_debug_data_length && fwrt->ops &&
|
||||||
|
fwrt->ops->d3_debug_enable &&
|
||||||
|
fwrt->ops->d3_debug_enable(fwrt->ops_ctx) &&
|
||||||
iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_D3_DEBUG_DATA);
|
iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_D3_DEBUG_DATA);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -442,6 +438,26 @@ void iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt,
|
||||||
|
|
||||||
void iwl_fwrt_stop_device(struct iwl_fw_runtime *fwrt);
|
void iwl_fwrt_stop_device(struct iwl_fw_runtime *fwrt);
|
||||||
|
|
||||||
|
static inline void iwl_fw_lmac1_set_alive_err_table(struct iwl_trans *trans,
|
||||||
|
u32 lmac_error_event_table)
|
||||||
|
{
|
||||||
|
if (!(trans->error_event_table_tlv_status &
|
||||||
|
IWL_ERROR_EVENT_TABLE_LMAC1) ||
|
||||||
|
WARN_ON(trans->lmac_error_event_table[0] !=
|
||||||
|
lmac_error_event_table))
|
||||||
|
trans->lmac_error_event_table[0] = lmac_error_event_table;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void iwl_fw_umac_set_alive_err_table(struct iwl_trans *trans,
|
||||||
|
u32 umac_error_event_table)
|
||||||
|
{
|
||||||
|
if (!(trans->error_event_table_tlv_status &
|
||||||
|
IWL_ERROR_EVENT_TABLE_UMAC) ||
|
||||||
|
WARN_ON(trans->umac_error_event_table !=
|
||||||
|
umac_error_event_table))
|
||||||
|
trans->umac_error_event_table = umac_error_event_table;
|
||||||
|
}
|
||||||
|
|
||||||
/* This bit is used to differentiate the legacy dump from the ini dump */
|
/* This bit is used to differentiate the legacy dump from the ini dump */
|
||||||
#define INI_DUMP_BIT BIT(31)
|
#define INI_DUMP_BIT BIT(31)
|
||||||
|
|
||||||
|
|
|
@ -301,7 +301,7 @@ struct iwl_fw_ini_error_dump_header {
|
||||||
/**
|
/**
|
||||||
* struct iwl_fw_ini_error_dump - ini region dump
|
* struct iwl_fw_ini_error_dump - ini region dump
|
||||||
* @header: the header of this region
|
* @header: the header of this region
|
||||||
* @ranges: the memory ranges of this this region
|
* @ranges: the memory ranges of this region
|
||||||
*/
|
*/
|
||||||
struct iwl_fw_ini_error_dump {
|
struct iwl_fw_ini_error_dump {
|
||||||
struct iwl_fw_ini_error_dump_header header;
|
struct iwl_fw_ini_error_dump_header header;
|
||||||
|
@ -322,6 +322,20 @@ struct iwl_fw_error_dump_rb {
|
||||||
u8 data[];
|
u8 data[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct iwl_fw_ini_monitor_dram_dump - ini dram monitor dump
|
||||||
|
* @header - header of the region
|
||||||
|
* @write_ptr - write pointer position in the dram
|
||||||
|
* @cycle_cnt - cycles count
|
||||||
|
* @ranges - the memory ranges of this this region
|
||||||
|
*/
|
||||||
|
struct iwl_fw_ini_monitor_dram_dump {
|
||||||
|
struct iwl_fw_ini_error_dump_header header;
|
||||||
|
__le32 write_ptr;
|
||||||
|
__le32 cycle_cnt;
|
||||||
|
struct iwl_fw_ini_error_dump_range ranges[];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct iwl_fw_error_dump_paging - content of the UMAC's image page
|
* struct iwl_fw_error_dump_paging - content of the UMAC's image page
|
||||||
* block on DRAM
|
* block on DRAM
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||||
* Copyright(c) 2018 Intel Corporation
|
* Copyright(c) 2018 Intel Corporation
|
||||||
|
* Copyright(c) 2019 Intel Corporation
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of version 2 of the GNU General Public License as
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
|
@ -32,6 +33,7 @@
|
||||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||||
* Copyright(c) 2018 Intel Corporation
|
* Copyright(c) 2018 Intel Corporation
|
||||||
|
* Copyright(c) 2019 Intel Corporation
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -143,6 +145,9 @@ enum iwl_ucode_tlv_type {
|
||||||
IWL_UCODE_TLV_FW_GSCAN_CAPA = 50,
|
IWL_UCODE_TLV_FW_GSCAN_CAPA = 50,
|
||||||
IWL_UCODE_TLV_FW_MEM_SEG = 51,
|
IWL_UCODE_TLV_FW_MEM_SEG = 51,
|
||||||
IWL_UCODE_TLV_IML = 52,
|
IWL_UCODE_TLV_IML = 52,
|
||||||
|
IWL_UCODE_TLV_UMAC_DEBUG_ADDRS = 54,
|
||||||
|
IWL_UCODE_TLV_LMAC_DEBUG_ADDRS = 55,
|
||||||
|
IWL_UCODE_TLV_FW_RECOVERY_INFO = 57,
|
||||||
IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION = IWL_UCODE_INI_TLV_GROUP | 0x1,
|
IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION = IWL_UCODE_INI_TLV_GROUP | 0x1,
|
||||||
IWL_UCODE_TLV_TYPE_HCMD = IWL_UCODE_INI_TLV_GROUP | 0x2,
|
IWL_UCODE_TLV_TYPE_HCMD = IWL_UCODE_INI_TLV_GROUP | 0x2,
|
||||||
IWL_UCODE_TLV_TYPE_REGIONS = IWL_UCODE_INI_TLV_GROUP | 0x3,
|
IWL_UCODE_TLV_TYPE_REGIONS = IWL_UCODE_INI_TLV_GROUP | 0x3,
|
||||||
|
@ -267,6 +272,8 @@ typedef unsigned int __bitwise iwl_ucode_tlv_api_t;
|
||||||
* version of the beacon notification.
|
* version of the beacon notification.
|
||||||
* @IWL_UCODE_TLV_API_BEACON_FILTER_V4: This ucode supports v4 of
|
* @IWL_UCODE_TLV_API_BEACON_FILTER_V4: This ucode supports v4 of
|
||||||
* BEACON_FILTER_CONFIG_API_S_VER_4.
|
* BEACON_FILTER_CONFIG_API_S_VER_4.
|
||||||
|
* @IWL_UCODE_TLV_API_FTM_NEW_RANGE_REQ: This ucode supports v7 of
|
||||||
|
* LOCATION_RANGE_REQ_CMD_API_S and v6 of LOCATION_RANGE_RESP_NTFY_API_S.
|
||||||
*
|
*
|
||||||
* @NUM_IWL_UCODE_TLV_API: number of bits used
|
* @NUM_IWL_UCODE_TLV_API: number of bits used
|
||||||
*/
|
*/
|
||||||
|
@ -293,6 +300,7 @@ enum iwl_ucode_tlv_api {
|
||||||
IWL_UCODE_TLV_API_REDUCE_TX_POWER = (__force iwl_ucode_tlv_api_t)45,
|
IWL_UCODE_TLV_API_REDUCE_TX_POWER = (__force iwl_ucode_tlv_api_t)45,
|
||||||
IWL_UCODE_TLV_API_SHORT_BEACON_NOTIF = (__force iwl_ucode_tlv_api_t)46,
|
IWL_UCODE_TLV_API_SHORT_BEACON_NOTIF = (__force iwl_ucode_tlv_api_t)46,
|
||||||
IWL_UCODE_TLV_API_BEACON_FILTER_V4 = (__force iwl_ucode_tlv_api_t)47,
|
IWL_UCODE_TLV_API_BEACON_FILTER_V4 = (__force iwl_ucode_tlv_api_t)47,
|
||||||
|
IWL_UCODE_TLV_API_FTM_NEW_RANGE_REQ = (__force iwl_ucode_tlv_api_t)49,
|
||||||
|
|
||||||
NUM_IWL_UCODE_TLV_API
|
NUM_IWL_UCODE_TLV_API
|
||||||
#ifdef __CHECKER__
|
#ifdef __CHECKER__
|
||||||
|
@ -370,12 +378,15 @@ typedef unsigned int __bitwise iwl_ucode_tlv_capa_t;
|
||||||
* capability.
|
* capability.
|
||||||
* @IWL_UCODE_TLV_CAPA_CSI_REPORTING: firmware is capable of being configured
|
* @IWL_UCODE_TLV_CAPA_CSI_REPORTING: firmware is capable of being configured
|
||||||
* to report the CSI information with (certain) RX frames
|
* to report the CSI information with (certain) RX frames
|
||||||
|
* @IWL_UCODE_TLV_CAPA_FTM_CALIBRATED: has FTM calibrated and thus supports both
|
||||||
|
* initiator and responder
|
||||||
*
|
*
|
||||||
* @IWL_UCODE_TLV_CAPA_MLME_OFFLOAD: supports MLME offload
|
* @IWL_UCODE_TLV_CAPA_MLME_OFFLOAD: supports MLME offload
|
||||||
*
|
*
|
||||||
* @NUM_IWL_UCODE_TLV_CAPA: number of bits used
|
* @NUM_IWL_UCODE_TLV_CAPA: number of bits used
|
||||||
*/
|
*/
|
||||||
enum iwl_ucode_tlv_capa {
|
enum iwl_ucode_tlv_capa {
|
||||||
|
/* set 0 */
|
||||||
IWL_UCODE_TLV_CAPA_D0I3_SUPPORT = (__force iwl_ucode_tlv_capa_t)0,
|
IWL_UCODE_TLV_CAPA_D0I3_SUPPORT = (__force iwl_ucode_tlv_capa_t)0,
|
||||||
IWL_UCODE_TLV_CAPA_LAR_SUPPORT = (__force iwl_ucode_tlv_capa_t)1,
|
IWL_UCODE_TLV_CAPA_LAR_SUPPORT = (__force iwl_ucode_tlv_capa_t)1,
|
||||||
IWL_UCODE_TLV_CAPA_UMAC_SCAN = (__force iwl_ucode_tlv_capa_t)2,
|
IWL_UCODE_TLV_CAPA_UMAC_SCAN = (__force iwl_ucode_tlv_capa_t)2,
|
||||||
|
@ -397,6 +408,8 @@ enum iwl_ucode_tlv_capa {
|
||||||
IWL_UCODE_TLV_CAPA_LAR_MULTI_MCC = (__force iwl_ucode_tlv_capa_t)29,
|
IWL_UCODE_TLV_CAPA_LAR_MULTI_MCC = (__force iwl_ucode_tlv_capa_t)29,
|
||||||
IWL_UCODE_TLV_CAPA_BT_COEX_RRC = (__force iwl_ucode_tlv_capa_t)30,
|
IWL_UCODE_TLV_CAPA_BT_COEX_RRC = (__force iwl_ucode_tlv_capa_t)30,
|
||||||
IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT = (__force iwl_ucode_tlv_capa_t)31,
|
IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT = (__force iwl_ucode_tlv_capa_t)31,
|
||||||
|
|
||||||
|
/* set 1 */
|
||||||
IWL_UCODE_TLV_CAPA_STA_PM_NOTIF = (__force iwl_ucode_tlv_capa_t)38,
|
IWL_UCODE_TLV_CAPA_STA_PM_NOTIF = (__force iwl_ucode_tlv_capa_t)38,
|
||||||
IWL_UCODE_TLV_CAPA_BINDING_CDB_SUPPORT = (__force iwl_ucode_tlv_capa_t)39,
|
IWL_UCODE_TLV_CAPA_BINDING_CDB_SUPPORT = (__force iwl_ucode_tlv_capa_t)39,
|
||||||
IWL_UCODE_TLV_CAPA_CDB_SUPPORT = (__force iwl_ucode_tlv_capa_t)40,
|
IWL_UCODE_TLV_CAPA_CDB_SUPPORT = (__force iwl_ucode_tlv_capa_t)40,
|
||||||
|
@ -406,6 +419,9 @@ enum iwl_ucode_tlv_capa {
|
||||||
IWL_UCODE_TLV_CAPA_COEX_SCHEMA_2 = (__force iwl_ucode_tlv_capa_t)45,
|
IWL_UCODE_TLV_CAPA_COEX_SCHEMA_2 = (__force iwl_ucode_tlv_capa_t)45,
|
||||||
IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD = (__force iwl_ucode_tlv_capa_t)46,
|
IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD = (__force iwl_ucode_tlv_capa_t)46,
|
||||||
IWL_UCODE_TLV_CAPA_ULTRA_HB_CHANNELS = (__force iwl_ucode_tlv_capa_t)48,
|
IWL_UCODE_TLV_CAPA_ULTRA_HB_CHANNELS = (__force iwl_ucode_tlv_capa_t)48,
|
||||||
|
IWL_UCODE_TLV_CAPA_FTM_CALIBRATED = (__force iwl_ucode_tlv_capa_t)47,
|
||||||
|
|
||||||
|
/* set 2 */
|
||||||
IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE = (__force iwl_ucode_tlv_capa_t)64,
|
IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE = (__force iwl_ucode_tlv_capa_t)64,
|
||||||
IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS = (__force iwl_ucode_tlv_capa_t)65,
|
IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS = (__force iwl_ucode_tlv_capa_t)65,
|
||||||
IWL_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT = (__force iwl_ucode_tlv_capa_t)67,
|
IWL_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT = (__force iwl_ucode_tlv_capa_t)67,
|
||||||
|
@ -426,6 +442,7 @@ enum iwl_ucode_tlv_capa {
|
||||||
IWL_UCODE_TLV_CAPA_MCC_UPDATE_11AX_SUPPORT = (__force iwl_ucode_tlv_capa_t)89,
|
IWL_UCODE_TLV_CAPA_MCC_UPDATE_11AX_SUPPORT = (__force iwl_ucode_tlv_capa_t)89,
|
||||||
IWL_UCODE_TLV_CAPA_CSI_REPORTING = (__force iwl_ucode_tlv_capa_t)90,
|
IWL_UCODE_TLV_CAPA_CSI_REPORTING = (__force iwl_ucode_tlv_capa_t)90,
|
||||||
|
|
||||||
|
/* set 3 */
|
||||||
IWL_UCODE_TLV_CAPA_MLME_OFFLOAD = (__force iwl_ucode_tlv_capa_t)96,
|
IWL_UCODE_TLV_CAPA_MLME_OFFLOAD = (__force iwl_ucode_tlv_capa_t)96,
|
||||||
|
|
||||||
NUM_IWL_UCODE_TLV_CAPA
|
NUM_IWL_UCODE_TLV_CAPA
|
||||||
|
|
|
@ -105,6 +105,8 @@ struct iwl_ucode_capabilities {
|
||||||
u32 n_scan_channels;
|
u32 n_scan_channels;
|
||||||
u32 standard_phy_calibration_size;
|
u32 standard_phy_calibration_size;
|
||||||
u32 flags;
|
u32 flags;
|
||||||
|
u32 error_log_addr;
|
||||||
|
u32 error_log_size;
|
||||||
unsigned long _api[BITS_TO_LONGS(NUM_IWL_UCODE_TLV_API)];
|
unsigned long _api[BITS_TO_LONGS(NUM_IWL_UCODE_TLV_API)];
|
||||||
unsigned long _capa[BITS_TO_LONGS(NUM_IWL_UCODE_TLV_CAPA)];
|
unsigned long _capa[BITS_TO_LONGS(NUM_IWL_UCODE_TLV_CAPA)];
|
||||||
};
|
};
|
||||||
|
@ -234,15 +236,13 @@ struct iwl_fw_ini_allocation_data {
|
||||||
/**
|
/**
|
||||||
* struct iwl_fw_ini_active_triggers
|
* struct iwl_fw_ini_active_triggers
|
||||||
* @active: is this trigger active
|
* @active: is this trigger active
|
||||||
* @apply_point: last apply point that updated this trigger
|
* @size: allocated memory size of the trigger
|
||||||
* @conf: active trigger
|
* @trig: trigger
|
||||||
* @conf_ext: second trigger, contains extra regions to dump
|
|
||||||
*/
|
*/
|
||||||
struct iwl_fw_ini_active_triggers {
|
struct iwl_fw_ini_active_triggers {
|
||||||
bool active;
|
bool active;
|
||||||
enum iwl_fw_ini_apply_point apply_point;
|
size_t size;
|
||||||
struct iwl_fw_ini_trigger *conf;
|
struct iwl_fw_ini_trigger *trig;
|
||||||
struct iwl_fw_ini_trigger *conf_ext;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
* GPL LICENSE SUMMARY
|
* GPL LICENSE SUMMARY
|
||||||
*
|
*
|
||||||
* Copyright(c) 2017 Intel Deutschland GmbH
|
* Copyright(c) 2017 Intel Deutschland GmbH
|
||||||
* Copyright(c) 2018 Intel Corporation
|
* Copyright (C) 2018-2019 Intel Corporation
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of version 2 of the GNU General Public License as
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
|
@ -27,7 +27,7 @@
|
||||||
* BSD LICENSE
|
* BSD LICENSE
|
||||||
*
|
*
|
||||||
* Copyright(c) 2017 Intel Deutschland GmbH
|
* Copyright(c) 2017 Intel Deutschland GmbH
|
||||||
* Copyright(c) 2018 Intel Corporation
|
* Copyright (C) 2018-2019 Intel Corporation
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -73,6 +73,7 @@ struct iwl_fw_runtime_ops {
|
||||||
void (*dump_end)(void *ctx);
|
void (*dump_end)(void *ctx);
|
||||||
bool (*fw_running)(void *ctx);
|
bool (*fw_running)(void *ctx);
|
||||||
int (*send_hcmd)(void *ctx, struct iwl_host_cmd *host_cmd);
|
int (*send_hcmd)(void *ctx, struct iwl_host_cmd *host_cmd);
|
||||||
|
bool (*d3_debug_enable)(void *ctx);
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MAX_NUM_LMAC 2
|
#define MAX_NUM_LMAC 2
|
||||||
|
@ -137,7 +138,7 @@ struct iwl_fw_runtime {
|
||||||
u8 conf;
|
u8 conf;
|
||||||
|
|
||||||
/* ts of the beginning of a non-collect fw dbg data period */
|
/* ts of the beginning of a non-collect fw dbg data period */
|
||||||
unsigned long non_collect_ts_start[IWL_FW_TRIGGER_ID_NUM - 1];
|
unsigned long non_collect_ts_start[IWL_FW_TRIGGER_ID_NUM];
|
||||||
u32 *d3_debug_data;
|
u32 *d3_debug_data;
|
||||||
struct iwl_fw_ini_region_cfg *active_regs[IWL_FW_INI_MAX_REGION_ID];
|
struct iwl_fw_ini_region_cfg *active_regs[IWL_FW_INI_MAX_REGION_ID];
|
||||||
struct iwl_fw_ini_active_triggers active_trigs[IWL_FW_TRIGGER_ID_NUM];
|
struct iwl_fw_ini_active_triggers active_trigs[IWL_FW_TRIGGER_ID_NUM];
|
||||||
|
@ -160,8 +161,20 @@ void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans,
|
||||||
|
|
||||||
static inline void iwl_fw_runtime_free(struct iwl_fw_runtime *fwrt)
|
static inline void iwl_fw_runtime_free(struct iwl_fw_runtime *fwrt)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
kfree(fwrt->dump.d3_debug_data);
|
kfree(fwrt->dump.d3_debug_data);
|
||||||
fwrt->dump.d3_debug_data = NULL;
|
fwrt->dump.d3_debug_data = NULL;
|
||||||
|
|
||||||
|
for (i = 0; i < IWL_FW_TRIGGER_ID_NUM; i++) {
|
||||||
|
struct iwl_fw_ini_active_triggers *active =
|
||||||
|
&fwrt->dump.active_trigs[i];
|
||||||
|
|
||||||
|
active->active = false;
|
||||||
|
active->size = 0;
|
||||||
|
kfree(active->trig);
|
||||||
|
active->trig = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void iwl_fw_runtime_suspend(struct iwl_fw_runtime *fwrt);
|
void iwl_fw_runtime_suspend(struct iwl_fw_runtime *fwrt);
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
*
|
*
|
||||||
* Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
|
* Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
|
||||||
* Copyright (C) 2016 - 2017 Intel Deutschland GmbH
|
* Copyright (C) 2016 - 2017 Intel Deutschland GmbH
|
||||||
* Copyright(c) 2018 Intel Corporation
|
* Copyright(c) 2018 - 2019 Intel Corporation
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of version 2 of the GNU General Public License as
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
|
@ -29,7 +29,7 @@
|
||||||
*
|
*
|
||||||
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
|
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
|
||||||
* Copyright (C) 2016 - 2017 Intel Deutschland GmbH
|
* Copyright (C) 2016 - 2017 Intel Deutschland GmbH
|
||||||
* Copyright(c) 2018 Intel Corporation
|
* Copyright(c) 2018 - 2019 Intel Corporation
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -89,6 +89,7 @@ enum iwl_device_family {
|
||||||
IWL_DEVICE_FAMILY_9000,
|
IWL_DEVICE_FAMILY_9000,
|
||||||
IWL_DEVICE_FAMILY_22000,
|
IWL_DEVICE_FAMILY_22000,
|
||||||
IWL_DEVICE_FAMILY_22560,
|
IWL_DEVICE_FAMILY_22560,
|
||||||
|
IWL_DEVICE_FAMILY_AX210,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -380,6 +381,8 @@ struct iwl_csr_params {
|
||||||
* @d3_debug_data_base_addr: base address where D3 debug data is stored
|
* @d3_debug_data_base_addr: base address where D3 debug data is stored
|
||||||
* @d3_debug_data_length: length of the D3 debug data
|
* @d3_debug_data_length: length of the D3 debug data
|
||||||
* @bisr_workaround: BISR hardware workaround (for 22260 series devices)
|
* @bisr_workaround: BISR hardware workaround (for 22260 series devices)
|
||||||
|
* @min_txq_size: minimum number of slots required in a TX queue
|
||||||
|
* @umac_prph_offset: offset to add to UMAC periphery address
|
||||||
*
|
*
|
||||||
* We enable the driver to be backward compatible wrt. hardware features.
|
* We enable the driver to be backward compatible wrt. hardware features.
|
||||||
* API differences in uCode shouldn't be handled here but through TLVs
|
* API differences in uCode shouldn't be handled here but through TLVs
|
||||||
|
@ -445,6 +448,8 @@ struct iwl_cfg {
|
||||||
u32 extra_phy_cfg_flags;
|
u32 extra_phy_cfg_flags;
|
||||||
u32 d3_debug_data_base_addr;
|
u32 d3_debug_data_base_addr;
|
||||||
u32 d3_debug_data_length;
|
u32 d3_debug_data_length;
|
||||||
|
u32 min_txq_size;
|
||||||
|
u32 umac_prph_offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const struct iwl_csr_params iwl_csr_v1;
|
extern const struct iwl_csr_params iwl_csr_v1;
|
||||||
|
@ -560,9 +565,13 @@ extern const struct iwl_cfg iwl22000_2ax_cfg_jf;
|
||||||
extern const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_a0_f0;
|
extern const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_a0_f0;
|
||||||
extern const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_b0_f0;
|
extern const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_b0_f0;
|
||||||
extern const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_b0;
|
extern const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_b0;
|
||||||
extern const struct iwl_cfg iwl22000_2ax_cfg_qnj_jf_b0;
|
extern const struct iwl_cfg iwl9560_2ac_cfg_qnj_jf_b0;
|
||||||
extern const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_a0;
|
extern const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_a0;
|
||||||
extern const struct iwl_cfg iwl22560_2ax_cfg_su_cdb;
|
extern const struct iwl_cfg iwl22560_2ax_cfg_su_cdb;
|
||||||
|
extern const struct iwl_cfg iwlax210_2ax_cfg_so_jf_a0;
|
||||||
|
extern const struct iwl_cfg iwlax210_2ax_cfg_so_hr_a0;
|
||||||
|
extern const struct iwl_cfg iwlax210_2ax_cfg_so_gf_a0;
|
||||||
|
extern const struct iwl_cfg iwlax210_2ax_cfg_ty_gf_a0;
|
||||||
#endif /* CPTCFG_IWLMVM || CPTCFG_IWLFMAC */
|
#endif /* CPTCFG_IWLMVM || CPTCFG_IWLFMAC */
|
||||||
|
|
||||||
#endif /* __IWL_CONFIG_H__ */
|
#endif /* __IWL_CONFIG_H__ */
|
||||||
|
|
|
@ -180,6 +180,7 @@
|
||||||
/* Bits for CSR_HW_IF_CONFIG_REG */
|
/* Bits for CSR_HW_IF_CONFIG_REG */
|
||||||
#define CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH (0x00000003)
|
#define CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH (0x00000003)
|
||||||
#define CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP (0x0000000C)
|
#define CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP (0x0000000C)
|
||||||
|
#define CSR_HW_IF_CONFIG_REG_BIT_MONITOR_SRAM (0x00000080)
|
||||||
#define CSR_HW_IF_CONFIG_REG_MSK_BOARD_VER (0x000000C0)
|
#define CSR_HW_IF_CONFIG_REG_MSK_BOARD_VER (0x000000C0)
|
||||||
#define CSR_HW_IF_CONFIG_REG_BIT_MAC_SI (0x00000100)
|
#define CSR_HW_IF_CONFIG_REG_BIT_MAC_SI (0x00000100)
|
||||||
#define CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI (0x00000200)
|
#define CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI (0x00000200)
|
||||||
|
@ -327,11 +328,14 @@ enum {
|
||||||
#define CSR_HW_REV_TYPE_QNJ (0x0000360)
|
#define CSR_HW_REV_TYPE_QNJ (0x0000360)
|
||||||
#define CSR_HW_REV_TYPE_QNJ_B0 (0x0000364)
|
#define CSR_HW_REV_TYPE_QNJ_B0 (0x0000364)
|
||||||
#define CSR_HW_REV_TYPE_HR_CDB (0x0000340)
|
#define CSR_HW_REV_TYPE_HR_CDB (0x0000340)
|
||||||
|
#define CSR_HW_REV_TYPE_SO (0x0000370)
|
||||||
|
#define CSR_HW_REV_TYPE_TY (0x0000420)
|
||||||
|
|
||||||
/* RF_ID value */
|
/* RF_ID value */
|
||||||
#define CSR_HW_RF_ID_TYPE_JF (0x00105100)
|
#define CSR_HW_RF_ID_TYPE_JF (0x00105100)
|
||||||
#define CSR_HW_RF_ID_TYPE_HR (0x0010A000)
|
#define CSR_HW_RF_ID_TYPE_HR (0x0010A000)
|
||||||
#define CSR_HW_RF_ID_TYPE_HRCDB (0x00109F00)
|
#define CSR_HW_RF_ID_TYPE_HRCDB (0x00109F00)
|
||||||
|
#define CSR_HW_RF_ID_TYPE_GF (0x0010D000)
|
||||||
|
|
||||||
/* HW_RF CHIP ID */
|
/* HW_RF CHIP ID */
|
||||||
#define CSR_HW_RF_ID_TYPE_CHIP_ID(_val) (((_val) >> 12) & 0xFFF)
|
#define CSR_HW_RF_ID_TYPE_CHIP_ID(_val) (((_val) >> 12) & 0xFFF)
|
||||||
|
@ -593,6 +597,7 @@ enum msix_hw_int_causes {
|
||||||
MSIX_HW_INT_CAUSES_REG_ALIVE = BIT(0),
|
MSIX_HW_INT_CAUSES_REG_ALIVE = BIT(0),
|
||||||
MSIX_HW_INT_CAUSES_REG_WAKEUP = BIT(1),
|
MSIX_HW_INT_CAUSES_REG_WAKEUP = BIT(1),
|
||||||
MSIX_HW_INT_CAUSES_REG_IPC = BIT(1),
|
MSIX_HW_INT_CAUSES_REG_IPC = BIT(1),
|
||||||
|
MSIX_HW_INT_CAUSES_REG_IML = BIT(2),
|
||||||
MSIX_HW_INT_CAUSES_REG_SW_ERR_V2 = BIT(5),
|
MSIX_HW_INT_CAUSES_REG_SW_ERR_V2 = BIT(5),
|
||||||
MSIX_HW_INT_CAUSES_REG_CT_KILL = BIT(6),
|
MSIX_HW_INT_CAUSES_REG_CT_KILL = BIT(6),
|
||||||
MSIX_HW_INT_CAUSES_REG_RF_KILL = BIT(7),
|
MSIX_HW_INT_CAUSES_REG_RF_KILL = BIT(7),
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
*
|
*
|
||||||
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
|
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
|
||||||
|
* Copyright (C) 2018 Intel Corporation
|
||||||
*
|
*
|
||||||
* Portions of this file are derived from the ipw3945 project.
|
* Portions of this file are derived from the ipw3945 project.
|
||||||
*
|
*
|
||||||
|
@ -159,7 +160,7 @@ do { \
|
||||||
/* 0x000F0000 - 0x00010000 */
|
/* 0x000F0000 - 0x00010000 */
|
||||||
#define IWL_DL_FW 0x00010000
|
#define IWL_DL_FW 0x00010000
|
||||||
#define IWL_DL_RF_KILL 0x00020000
|
#define IWL_DL_RF_KILL 0x00020000
|
||||||
#define IWL_DL_FW_ERRORS 0x00040000
|
#define IWL_DL_TPT 0x00040000
|
||||||
/* 0x00F00000 - 0x00100000 */
|
/* 0x00F00000 - 0x00100000 */
|
||||||
#define IWL_DL_RATE 0x00100000
|
#define IWL_DL_RATE 0x00100000
|
||||||
#define IWL_DL_CALIB 0x00200000
|
#define IWL_DL_CALIB 0x00200000
|
||||||
|
@ -193,7 +194,6 @@ do { \
|
||||||
#define IWL_DEBUG_CALIB(p, f, a...) IWL_DEBUG(p, IWL_DL_CALIB, f, ## a)
|
#define IWL_DEBUG_CALIB(p, f, a...) IWL_DEBUG(p, IWL_DL_CALIB, f, ## a)
|
||||||
#define IWL_DEBUG_FW(p, f, a...) IWL_DEBUG(p, IWL_DL_FW, f, ## a)
|
#define IWL_DEBUG_FW(p, f, a...) IWL_DEBUG(p, IWL_DL_FW, f, ## a)
|
||||||
#define IWL_DEBUG_RF_KILL(p, f, a...) IWL_DEBUG(p, IWL_DL_RF_KILL, f, ## a)
|
#define IWL_DEBUG_RF_KILL(p, f, a...) IWL_DEBUG(p, IWL_DL_RF_KILL, f, ## a)
|
||||||
#define IWL_DEBUG_FW_ERRORS(p, f, a...) IWL_DEBUG(p, IWL_DL_FW_ERRORS, f, ## a)
|
|
||||||
#define IWL_DEBUG_DROP(p, f, a...) IWL_DEBUG(p, IWL_DL_DROP, f, ## a)
|
#define IWL_DEBUG_DROP(p, f, a...) IWL_DEBUG(p, IWL_DL_DROP, f, ## a)
|
||||||
#define IWL_DEBUG_DROP_LIMIT(p, f, a...) \
|
#define IWL_DEBUG_DROP_LIMIT(p, f, a...) \
|
||||||
IWL_DEBUG_LIMIT(p, IWL_DL_DROP, f, ## a)
|
IWL_DEBUG_LIMIT(p, IWL_DL_DROP, f, ## a)
|
||||||
|
@ -215,6 +215,7 @@ do { \
|
||||||
#define IWL_DEBUG_DEV_RADIO(p, f, a...) IWL_DEBUG_DEV(p, IWL_DL_RADIO, f, ## a)
|
#define IWL_DEBUG_DEV_RADIO(p, f, a...) IWL_DEBUG_DEV(p, IWL_DL_RADIO, f, ## a)
|
||||||
#define IWL_DEBUG_POWER(p, f, a...) IWL_DEBUG(p, IWL_DL_POWER, f, ## a)
|
#define IWL_DEBUG_POWER(p, f, a...) IWL_DEBUG(p, IWL_DL_POWER, f, ## a)
|
||||||
#define IWL_DEBUG_11H(p, f, a...) IWL_DEBUG(p, IWL_DL_11H, f, ## a)
|
#define IWL_DEBUG_11H(p, f, a...) IWL_DEBUG(p, IWL_DL_11H, f, ## a)
|
||||||
|
#define IWL_DEBUG_TPT(p, f, a...) IWL_DEBUG(p, IWL_DL_TPT, f, ## a)
|
||||||
#define IWL_DEBUG_RPM(p, f, a...) IWL_DEBUG(p, IWL_DL_RPM, f, ## a)
|
#define IWL_DEBUG_RPM(p, f, a...) IWL_DEBUG(p, IWL_DL_RPM, f, ## a)
|
||||||
#define IWL_DEBUG_LAR(p, f, a...) IWL_DEBUG(p, IWL_DL_LAR, f, ## a)
|
#define IWL_DEBUG_LAR(p, f, a...) IWL_DEBUG(p, IWL_DL_LAR, f, ## a)
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
* Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
|
* Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
|
||||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||||
|
* Copyright(c) 2018 - 2019 Intel Corporation
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of version 2 of the GNU General Public License as
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
|
@ -30,6 +31,7 @@
|
||||||
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
|
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
|
||||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||||
|
* Copyright(c) 2018 - 2019 Intel Corporation
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -75,6 +77,7 @@
|
||||||
#include "iwl-dbg-tlv.h"
|
#include "iwl-dbg-tlv.h"
|
||||||
#include "iwl-config.h"
|
#include "iwl-config.h"
|
||||||
#include "iwl-modparams.h"
|
#include "iwl-modparams.h"
|
||||||
|
#include "fw/api/alive.h"
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
*
|
*
|
||||||
|
@ -588,6 +591,8 @@ static int iwl_parse_v1_v2_firmware(struct iwl_drv *drv,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define FW_ADDR_CACHE_CONTROL 0xC0000000
|
||||||
|
|
||||||
static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
|
static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
|
||||||
const struct firmware *ucode_raw,
|
const struct firmware *ucode_raw,
|
||||||
struct iwl_firmware_pieces *pieces,
|
struct iwl_firmware_pieces *pieces,
|
||||||
|
@ -1085,6 +1090,52 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case IWL_UCODE_TLV_FW_RECOVERY_INFO: {
|
||||||
|
struct {
|
||||||
|
__le32 buf_addr;
|
||||||
|
__le32 buf_size;
|
||||||
|
} *recov_info = (void *)tlv_data;
|
||||||
|
|
||||||
|
if (tlv_len != sizeof(*recov_info))
|
||||||
|
goto invalid_tlv_len;
|
||||||
|
capa->error_log_addr =
|
||||||
|
le32_to_cpu(recov_info->buf_addr);
|
||||||
|
capa->error_log_size =
|
||||||
|
le32_to_cpu(recov_info->buf_size);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case IWL_UCODE_TLV_UMAC_DEBUG_ADDRS: {
|
||||||
|
struct iwl_umac_debug_addrs *dbg_ptrs =
|
||||||
|
(void *)tlv_data;
|
||||||
|
|
||||||
|
if (tlv_len != sizeof(*dbg_ptrs))
|
||||||
|
goto invalid_tlv_len;
|
||||||
|
if (drv->trans->cfg->device_family <
|
||||||
|
IWL_DEVICE_FAMILY_22000)
|
||||||
|
break;
|
||||||
|
drv->trans->umac_error_event_table =
|
||||||
|
le32_to_cpu(dbg_ptrs->error_info_addr) &
|
||||||
|
~FW_ADDR_CACHE_CONTROL;
|
||||||
|
drv->trans->error_event_table_tlv_status |=
|
||||||
|
IWL_ERROR_EVENT_TABLE_UMAC;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case IWL_UCODE_TLV_LMAC_DEBUG_ADDRS: {
|
||||||
|
struct iwl_lmac_debug_addrs *dbg_ptrs =
|
||||||
|
(void *)tlv_data;
|
||||||
|
|
||||||
|
if (tlv_len != sizeof(*dbg_ptrs))
|
||||||
|
goto invalid_tlv_len;
|
||||||
|
if (drv->trans->cfg->device_family <
|
||||||
|
IWL_DEVICE_FAMILY_22000)
|
||||||
|
break;
|
||||||
|
drv->trans->lmac_error_event_table[0] =
|
||||||
|
le32_to_cpu(dbg_ptrs->error_event_table_ptr) &
|
||||||
|
~FW_ADDR_CACHE_CONTROL;
|
||||||
|
drv->trans->error_event_table_tlv_status |=
|
||||||
|
IWL_ERROR_EVENT_TABLE_LMAC1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION:
|
case IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION:
|
||||||
case IWL_UCODE_TLV_TYPE_HCMD:
|
case IWL_UCODE_TLV_TYPE_HCMD:
|
||||||
case IWL_UCODE_TLV_TYPE_REGIONS:
|
case IWL_UCODE_TLV_TYPE_REGIONS:
|
||||||
|
@ -1262,8 +1313,8 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
|
||||||
fw->ucode_capa.standard_phy_calibration_size =
|
fw->ucode_capa.standard_phy_calibration_size =
|
||||||
IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE;
|
IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE;
|
||||||
fw->ucode_capa.n_scan_channels = IWL_DEFAULT_SCAN_CHANNELS;
|
fw->ucode_capa.n_scan_channels = IWL_DEFAULT_SCAN_CHANNELS;
|
||||||
/* dump all fw memory areas by default except d3 debug data */
|
/* dump all fw memory areas by default */
|
||||||
fw->dbg.dump_mask = 0xfffdffff;
|
fw->dbg.dump_mask = 0xffffffff;
|
||||||
|
|
||||||
pieces = kzalloc(sizeof(*pieces), GFP_KERNEL);
|
pieces = kzalloc(sizeof(*pieces), GFP_KERNEL);
|
||||||
if (!pieces)
|
if (!pieces)
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
*
|
*
|
||||||
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
|
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
|
||||||
* Copyright(c) 2015 - 2016 Intel Deutschland GmbH
|
* Copyright(c) 2015 - 2016 Intel Deutschland GmbH
|
||||||
* Copyright (C) 2018 Intel Corporation
|
* Copyright(C) 2018 - 2019 Intel Corporation
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms of version 2 of the GNU General Public License as
|
* under the terms of version 2 of the GNU General Public License as
|
||||||
|
@ -29,7 +29,7 @@
|
||||||
*
|
*
|
||||||
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
|
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
|
||||||
* Copyright(c) 2015 - 2016 Intel Deutschland GmbH
|
* Copyright(c) 2015 - 2016 Intel Deutschland GmbH
|
||||||
* Copyright (C) 2018 Intel Corporation
|
* Copyright (C) 2018 - 2019 Intel Corporation
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -307,9 +307,12 @@ void iwl_force_nmi(struct iwl_trans *trans)
|
||||||
if (trans->cfg->device_family < IWL_DEVICE_FAMILY_9000)
|
if (trans->cfg->device_family < IWL_DEVICE_FAMILY_9000)
|
||||||
iwl_write_prph(trans, DEVICE_SET_NMI_REG,
|
iwl_write_prph(trans, DEVICE_SET_NMI_REG,
|
||||||
DEVICE_SET_NMI_VAL_DRV);
|
DEVICE_SET_NMI_VAL_DRV);
|
||||||
|
else if (trans->cfg->device_family < IWL_DEVICE_FAMILY_AX210)
|
||||||
|
iwl_write_umac_prph(trans, UREG_NIC_SET_NMI_DRIVER,
|
||||||
|
UREG_NIC_SET_NMI_DRIVER_NMI_FROM_DRIVER_MSK);
|
||||||
else
|
else
|
||||||
iwl_write_prph(trans, UREG_NIC_SET_NMI_DRIVER,
|
iwl_write_umac_prph(trans, UREG_DOORBELL_TO_ISR6,
|
||||||
UREG_NIC_SET_NMI_DRIVER_NMI_FROM_DRIVER_MSK);
|
UREG_DOORBELL_TO_ISR6_NMI_BIT);
|
||||||
}
|
}
|
||||||
IWL_EXPORT_SYMBOL(iwl_force_nmi);
|
IWL_EXPORT_SYMBOL(iwl_force_nmi);
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
*
|
*
|
||||||
* GPL LICENSE SUMMARY
|
* GPL LICENSE SUMMARY
|
||||||
*
|
*
|
||||||
* Copyright (C) 2018 Intel Corporation
|
* Copyright (C) 2018 - 2019 Intel Corporation
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms of version 2 of the GNU General Public License as
|
* under the terms of version 2 of the GNU General Public License as
|
||||||
|
@ -25,7 +25,7 @@
|
||||||
*
|
*
|
||||||
* BSD LICENSE
|
* BSD LICENSE
|
||||||
*
|
*
|
||||||
* Copyright (C) 2018 Intel Corporation
|
* Copyright (C) 2018 - 2019 Intel Corporation
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -104,4 +104,43 @@ int iwl_finish_nic_init(struct iwl_trans *trans);
|
||||||
/* Error handling */
|
/* Error handling */
|
||||||
int iwl_dump_fh(struct iwl_trans *trans, char **buf);
|
int iwl_dump_fh(struct iwl_trans *trans, char **buf);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* UMAC periphery address space changed from 0xA00000 to 0xD00000 starting from
|
||||||
|
* device family AX200. So peripheries used in families above and below AX200
|
||||||
|
* should go through iwl_..._umac_..._prph.
|
||||||
|
*/
|
||||||
|
static inline u32 iwl_umac_prph(struct iwl_trans *trans, u32 ofs)
|
||||||
|
{
|
||||||
|
return ofs + trans->cfg->umac_prph_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 iwl_read_umac_prph_no_grab(struct iwl_trans *trans, u32 ofs)
|
||||||
|
{
|
||||||
|
return iwl_read_prph_no_grab(trans, ofs + trans->cfg->umac_prph_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 iwl_read_umac_prph(struct iwl_trans *trans, u32 ofs)
|
||||||
|
{
|
||||||
|
return iwl_read_prph(trans, ofs + trans->cfg->umac_prph_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void iwl_write_umac_prph_no_grab(struct iwl_trans *trans, u32 ofs,
|
||||||
|
u32 val)
|
||||||
|
{
|
||||||
|
iwl_write_prph_no_grab(trans, ofs + trans->cfg->umac_prph_offset, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void iwl_write_umac_prph(struct iwl_trans *trans, u32 ofs,
|
||||||
|
u32 val)
|
||||||
|
{
|
||||||
|
iwl_write_prph(trans, ofs + trans->cfg->umac_prph_offset, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int iwl_poll_umac_prph_bit(struct iwl_trans *trans, u32 addr,
|
||||||
|
u32 bits, u32 mask, int timeout)
|
||||||
|
{
|
||||||
|
return iwl_poll_prph_bit(trans, addr + trans->cfg->umac_prph_offset,
|
||||||
|
bits, mask, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1102,12 +1102,12 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
|
||||||
int max_num_ch = cfg->nvm_type == IWL_NVM_EXT ?
|
int max_num_ch = cfg->nvm_type == IWL_NVM_EXT ?
|
||||||
IWL_NVM_NUM_CHANNELS_EXT : IWL_NVM_NUM_CHANNELS;
|
IWL_NVM_NUM_CHANNELS_EXT : IWL_NVM_NUM_CHANNELS;
|
||||||
|
|
||||||
if (WARN_ON_ONCE(num_of_ch > NL80211_MAX_SUPP_REG_RULES))
|
|
||||||
return ERR_PTR(-EINVAL);
|
|
||||||
|
|
||||||
if (WARN_ON(num_of_ch > max_num_ch))
|
if (WARN_ON(num_of_ch > max_num_ch))
|
||||||
num_of_ch = max_num_ch;
|
num_of_ch = max_num_ch;
|
||||||
|
|
||||||
|
if (WARN_ON_ONCE(num_of_ch > NL80211_MAX_SUPP_REG_RULES))
|
||||||
|
return ERR_PTR(-EINVAL);
|
||||||
|
|
||||||
IWL_DEBUG_DEV(dev, IWL_DL_LAR, "building regdom for %d channels\n",
|
IWL_DEBUG_DEV(dev, IWL_DL_LAR, "building regdom for %d channels\n",
|
||||||
num_of_ch);
|
num_of_ch);
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
|
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
|
||||||
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
|
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
|
||||||
* Copyright(c) 2016 Intel Deutschland GmbH
|
* Copyright(c) 2016 Intel Deutschland GmbH
|
||||||
* Copyright (C) 2018 Intel Corporation
|
* Copyright (C) 2018 - 2019 Intel Corporation
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of version 2 of the GNU General Public License as
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
|
@ -31,7 +31,7 @@
|
||||||
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
|
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
|
||||||
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
|
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
|
||||||
* Copyright(c) 2016 Intel Deutschland GmbH
|
* Copyright(c) 2016 Intel Deutschland GmbH
|
||||||
* Copyright (C) 2018 Intel Corporation
|
* Copyright (C) 2018 - 2019 Intel Corporation
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -433,4 +433,7 @@ enum {
|
||||||
#define HPM_DEBUG 0xA03440
|
#define HPM_DEBUG 0xA03440
|
||||||
#define PERSISTENCE_BIT BIT(12)
|
#define PERSISTENCE_BIT BIT(12)
|
||||||
#define PREG_WFPM_ACCESS BIT(12)
|
#define PREG_WFPM_ACCESS BIT(12)
|
||||||
|
|
||||||
|
#define UREG_DOORBELL_TO_ISR6 0xA05C04
|
||||||
|
#define UREG_DOORBELL_TO_ISR6_NMI_BIT BIT(0)
|
||||||
#endif /* __iwl_prph_h__ */
|
#endif /* __iwl_prph_h__ */
|
||||||
|
|
|
@ -232,6 +232,12 @@ enum iwl_hcmd_dataflag {
|
||||||
IWL_HCMD_DFL_DUP = BIT(1),
|
IWL_HCMD_DFL_DUP = BIT(1),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum iwl_error_event_table_status {
|
||||||
|
IWL_ERROR_EVENT_TABLE_LMAC1 = BIT(0),
|
||||||
|
IWL_ERROR_EVENT_TABLE_LMAC2 = BIT(1),
|
||||||
|
IWL_ERROR_EVENT_TABLE_UMAC = BIT(2),
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct iwl_host_cmd - Host command to the uCode
|
* struct iwl_host_cmd - Host command to the uCode
|
||||||
*
|
*
|
||||||
|
@ -759,6 +765,10 @@ struct iwl_self_init_dram {
|
||||||
* mode is set during the initialization phase and is not
|
* mode is set during the initialization phase and is not
|
||||||
* supposed to change during runtime.
|
* supposed to change during runtime.
|
||||||
* @dbg_rec_on: true iff there is a fw debug recording currently active
|
* @dbg_rec_on: true iff there is a fw debug recording currently active
|
||||||
|
* @lmac_error_event_table: addrs of lmacs error tables
|
||||||
|
* @umac_error_event_table: addr of umac error table
|
||||||
|
* @error_event_table_tlv_status: bitmap that indicates what error table
|
||||||
|
* pointers was recevied via TLV. use enum &iwl_error_event_table_status
|
||||||
*/
|
*/
|
||||||
struct iwl_trans {
|
struct iwl_trans {
|
||||||
const struct iwl_trans_ops *ops;
|
const struct iwl_trans_ops *ops;
|
||||||
|
|
|
@ -5,6 +5,7 @@ iwlmvm-y += utils.o rx.o rxmq.o tx.o binding.o quota.o sta.o sf.o
|
||||||
iwlmvm-y += scan.o time-event.o rs.o rs-fw.o
|
iwlmvm-y += scan.o time-event.o rs.o rs-fw.o
|
||||||
iwlmvm-y += power.o coex.o
|
iwlmvm-y += power.o coex.o
|
||||||
iwlmvm-y += tt.o offloading.o tdls.o
|
iwlmvm-y += tt.o offloading.o tdls.o
|
||||||
|
iwlmvm-y += ftm-responder.o ftm-initiator.o
|
||||||
iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o debugfs-vif.o
|
iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o debugfs-vif.o
|
||||||
iwlmvm-$(CONFIG_IWLWIFI_LEDS) += led.o
|
iwlmvm-$(CONFIG_IWLWIFI_LEDS) += led.o
|
||||||
iwlmvm-$(CONFIG_PM) += d3.o
|
iwlmvm-$(CONFIG_PM) += d3.o
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
* Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
|
* Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
|
||||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||||
* Copyright(c) 2015 Intel Deutschland GmbH
|
* Copyright(c) 2015 Intel Deutschland GmbH
|
||||||
|
* Copyright(c) 2018 - 2019 Intel Corporation
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of version 2 of the GNU General Public License as
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
|
@ -30,6 +31,7 @@
|
||||||
* Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
|
* Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
|
||||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||||
* Copyright(c) 2015 Intel Deutschland GmbH
|
* Copyright(c) 2015 Intel Deutschland GmbH
|
||||||
|
* Copyright(c) 2018 - 2019 Intel Corporation
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -63,6 +65,7 @@
|
||||||
#define __MVM_CONSTANTS_H
|
#define __MVM_CONSTANTS_H
|
||||||
|
|
||||||
#include <linux/ieee80211.h>
|
#include <linux/ieee80211.h>
|
||||||
|
#include "fw-api.h"
|
||||||
|
|
||||||
#define IWL_MVM_UAPSD_NOAGG_BSSIDS_NUM 20
|
#define IWL_MVM_UAPSD_NOAGG_BSSIDS_NUM 20
|
||||||
|
|
||||||
|
@ -145,5 +148,8 @@
|
||||||
#define IWL_MVM_RS_TPC_SR_NO_INCREASE 85 /* percent */
|
#define IWL_MVM_RS_TPC_SR_NO_INCREASE 85 /* percent */
|
||||||
#define IWL_MVM_RS_TPC_TX_POWER_STEP 3
|
#define IWL_MVM_RS_TPC_TX_POWER_STEP 3
|
||||||
#define IWL_MVM_ENABLE_EBS 1
|
#define IWL_MVM_ENABLE_EBS 1
|
||||||
|
#define IWL_MVM_FTM_INITIATOR_ALGO IWL_TOF_ALGO_TYPE_MAX_LIKE
|
||||||
|
#define IWL_MVM_FTM_INITIATOR_DYNACK true
|
||||||
|
#define IWL_MVM_D3_DEBUG false
|
||||||
|
|
||||||
#endif /* __MVM_CONSTANTS_H */
|
#endif /* __MVM_CONSTANTS_H */
|
||||||
|
|
|
@ -1899,7 +1899,7 @@ static void iwl_mvm_d3_disconnect_iter(void *data, u8 *mac,
|
||||||
static int iwl_mvm_check_rt_status(struct iwl_mvm *mvm,
|
static int iwl_mvm_check_rt_status(struct iwl_mvm *mvm,
|
||||||
struct ieee80211_vif *vif)
|
struct ieee80211_vif *vif)
|
||||||
{
|
{
|
||||||
u32 base = mvm->error_event_table[0];
|
u32 base = mvm->trans->lmac_error_event_table[0];
|
||||||
struct error_table_start {
|
struct error_table_start {
|
||||||
/* cf. struct iwl_error_event_table */
|
/* cf. struct iwl_error_event_table */
|
||||||
u32 valid;
|
u32 valid;
|
||||||
|
|
|
@ -1188,6 +1188,108 @@ out:
|
||||||
return ret ?: count;
|
return ret ?: count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int _iwl_dbgfs_inject_beacon_ie(struct iwl_mvm *mvm, char *bin, int len)
|
||||||
|
{
|
||||||
|
struct ieee80211_vif *vif;
|
||||||
|
struct iwl_mvm_vif *mvmvif;
|
||||||
|
struct sk_buff *beacon;
|
||||||
|
struct ieee80211_tx_info *info;
|
||||||
|
struct iwl_mac_beacon_cmd beacon_cmd = {};
|
||||||
|
u8 rate;
|
||||||
|
u16 flags;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
len /= 2;
|
||||||
|
|
||||||
|
/* Element len should be represented by u8 */
|
||||||
|
if (len >= U8_MAX)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (!iwl_mvm_firmware_running(mvm))
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
|
if (!iwl_mvm_has_new_tx_api(mvm) &&
|
||||||
|
!fw_has_api(&mvm->fw->ucode_capa,
|
||||||
|
IWL_UCODE_TLV_API_NEW_BEACON_TEMPLATE))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
rcu_read_lock();
|
||||||
|
|
||||||
|
for (i = 0; i < NUM_MAC_INDEX_DRIVER; i++) {
|
||||||
|
vif = iwl_mvm_rcu_dereference_vif_id(mvm, i, true);
|
||||||
|
if (!vif)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (vif->type == NL80211_IFTYPE_AP)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == NUM_MAC_INDEX_DRIVER || !vif)
|
||||||
|
goto out_err;
|
||||||
|
|
||||||
|
mvm->hw->extra_beacon_tailroom = len;
|
||||||
|
|
||||||
|
beacon = ieee80211_beacon_get_template(mvm->hw, vif, NULL);
|
||||||
|
if (!beacon)
|
||||||
|
goto out_err;
|
||||||
|
|
||||||
|
if (len && hex2bin(skb_put_zero(beacon, len), bin, len)) {
|
||||||
|
dev_kfree_skb(beacon);
|
||||||
|
goto out_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||||
|
info = IEEE80211_SKB_CB(beacon);
|
||||||
|
rate = iwl_mvm_mac_ctxt_get_lowest_rate(info, vif);
|
||||||
|
flags = iwl_mvm_mac80211_idx_to_hwrate(rate);
|
||||||
|
|
||||||
|
if (rate == IWL_FIRST_CCK_RATE)
|
||||||
|
flags |= IWL_MAC_BEACON_CCK;
|
||||||
|
|
||||||
|
beacon_cmd.flags = cpu_to_le16(flags);
|
||||||
|
beacon_cmd.byte_cnt = cpu_to_le16((u16)beacon->len);
|
||||||
|
beacon_cmd.template_id = cpu_to_le32((u32)mvmvif->id);
|
||||||
|
|
||||||
|
iwl_mvm_mac_ctxt_set_tim(mvm, &beacon_cmd.tim_idx,
|
||||||
|
&beacon_cmd.tim_size,
|
||||||
|
beacon->data, beacon->len);
|
||||||
|
|
||||||
|
mutex_lock(&mvm->mutex);
|
||||||
|
iwl_mvm_mac_ctxt_send_beacon_cmd(mvm, beacon, &beacon_cmd,
|
||||||
|
sizeof(beacon_cmd));
|
||||||
|
mutex_unlock(&mvm->mutex);
|
||||||
|
|
||||||
|
dev_kfree_skb(beacon);
|
||||||
|
|
||||||
|
rcu_read_unlock();
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
out_err:
|
||||||
|
rcu_read_unlock();
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t iwl_dbgfs_inject_beacon_ie_write(struct iwl_mvm *mvm,
|
||||||
|
char *buf, size_t count,
|
||||||
|
loff_t *ppos)
|
||||||
|
{
|
||||||
|
int ret = _iwl_dbgfs_inject_beacon_ie(mvm, buf, count);
|
||||||
|
|
||||||
|
mvm->hw->extra_beacon_tailroom = 0;
|
||||||
|
return ret ?: count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t iwl_dbgfs_inject_beacon_ie_restore_write(struct iwl_mvm *mvm,
|
||||||
|
char *buf,
|
||||||
|
size_t count,
|
||||||
|
loff_t *ppos)
|
||||||
|
{
|
||||||
|
int ret = _iwl_dbgfs_inject_beacon_ie(mvm, NULL, 0);
|
||||||
|
|
||||||
|
mvm->hw->extra_beacon_tailroom = 0;
|
||||||
|
return ret ?: count;
|
||||||
|
}
|
||||||
|
|
||||||
static ssize_t iwl_dbgfs_fw_dbg_conf_read(struct file *file,
|
static ssize_t iwl_dbgfs_fw_dbg_conf_read(struct file *file,
|
||||||
char __user *user_buf,
|
char __user *user_buf,
|
||||||
size_t count, loff_t *ppos)
|
size_t count, loff_t *ppos)
|
||||||
|
@ -1806,6 +1908,8 @@ MVM_DEBUGFS_WRITE_FILE_OPS(max_amsdu_len, 8);
|
||||||
MVM_DEBUGFS_WRITE_FILE_OPS(indirection_tbl,
|
MVM_DEBUGFS_WRITE_FILE_OPS(indirection_tbl,
|
||||||
(IWL_RSS_INDIRECTION_TABLE_SIZE * 2));
|
(IWL_RSS_INDIRECTION_TABLE_SIZE * 2));
|
||||||
MVM_DEBUGFS_WRITE_FILE_OPS(inject_packet, 512);
|
MVM_DEBUGFS_WRITE_FILE_OPS(inject_packet, 512);
|
||||||
|
MVM_DEBUGFS_WRITE_FILE_OPS(inject_beacon_ie, 512);
|
||||||
|
MVM_DEBUGFS_WRITE_FILE_OPS(inject_beacon_ie_restore, 512);
|
||||||
|
|
||||||
MVM_DEBUGFS_READ_FILE_OPS(uapsd_noagg_bssids);
|
MVM_DEBUGFS_READ_FILE_OPS(uapsd_noagg_bssids);
|
||||||
|
|
||||||
|
@ -2007,6 +2111,8 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
|
||||||
MVM_DEBUGFS_ADD_FILE(send_echo_cmd, mvm->debugfs_dir, 0200);
|
MVM_DEBUGFS_ADD_FILE(send_echo_cmd, mvm->debugfs_dir, 0200);
|
||||||
MVM_DEBUGFS_ADD_FILE(indirection_tbl, mvm->debugfs_dir, 0200);
|
MVM_DEBUGFS_ADD_FILE(indirection_tbl, mvm->debugfs_dir, 0200);
|
||||||
MVM_DEBUGFS_ADD_FILE(inject_packet, mvm->debugfs_dir, 0200);
|
MVM_DEBUGFS_ADD_FILE(inject_packet, mvm->debugfs_dir, 0200);
|
||||||
|
MVM_DEBUGFS_ADD_FILE(inject_beacon_ie, mvm->debugfs_dir, 0200);
|
||||||
|
MVM_DEBUGFS_ADD_FILE(inject_beacon_ie_restore, mvm->debugfs_dir, 0200);
|
||||||
#ifdef CONFIG_ACPI
|
#ifdef CONFIG_ACPI
|
||||||
MVM_DEBUGFS_ADD_FILE(sar_geo_profile, dbgfs_dir, 0400);
|
MVM_DEBUGFS_ADD_FILE(sar_geo_profile, dbgfs_dir, 0400);
|
||||||
#endif
|
#endif
|
||||||
|
|
654
drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
Normal file
654
drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
Normal file
|
@ -0,0 +1,654 @@
|
||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||||
|
* redistributing this file, you may do so under either license.
|
||||||
|
*
|
||||||
|
* GPL LICENSE SUMMARY
|
||||||
|
*
|
||||||
|
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
|
||||||
|
* Copyright (C) 2018 Intel Corporation
|
||||||
|
* Copyright (C) 2019 Intel Corporation
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* The full GNU General Public License is included in this distribution
|
||||||
|
* in the file called COPYING.
|
||||||
|
*
|
||||||
|
* Contact Information:
|
||||||
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
|
*
|
||||||
|
* BSD LICENSE
|
||||||
|
*
|
||||||
|
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
|
||||||
|
* Copyright (C) 2018 Intel Corporation
|
||||||
|
* Copyright (C) 2019 Intel Corporation
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
* * Neither the name Intel Corporation nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
#include <linux/etherdevice.h>
|
||||||
|
#include <linux/math64.h>
|
||||||
|
#include <net/cfg80211.h>
|
||||||
|
#include "mvm.h"
|
||||||
|
#include "iwl-io.h"
|
||||||
|
#include "iwl-prph.h"
|
||||||
|
#include "constants.h"
|
||||||
|
|
||||||
|
struct iwl_mvm_loc_entry {
|
||||||
|
struct list_head list;
|
||||||
|
u8 addr[ETH_ALEN];
|
||||||
|
u8 lci_len, civic_len;
|
||||||
|
u8 buf[];
|
||||||
|
};
|
||||||
|
|
||||||
|
static void iwl_mvm_ftm_reset(struct iwl_mvm *mvm)
|
||||||
|
{
|
||||||
|
struct iwl_mvm_loc_entry *e, *t;
|
||||||
|
|
||||||
|
mvm->ftm_initiator.req = NULL;
|
||||||
|
mvm->ftm_initiator.req_wdev = NULL;
|
||||||
|
memset(mvm->ftm_initiator.responses, 0,
|
||||||
|
sizeof(mvm->ftm_initiator.responses));
|
||||||
|
list_for_each_entry_safe(e, t, &mvm->ftm_initiator.loc_list, list) {
|
||||||
|
list_del(&e->list);
|
||||||
|
kfree(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void iwl_mvm_ftm_restart(struct iwl_mvm *mvm)
|
||||||
|
{
|
||||||
|
struct cfg80211_pmsr_result result = {
|
||||||
|
.status = NL80211_PMSR_STATUS_FAILURE,
|
||||||
|
.final = 1,
|
||||||
|
.host_time = ktime_get_boot_ns(),
|
||||||
|
.type = NL80211_PMSR_TYPE_FTM,
|
||||||
|
};
|
||||||
|
int i;
|
||||||
|
|
||||||
|
lockdep_assert_held(&mvm->mutex);
|
||||||
|
|
||||||
|
if (!mvm->ftm_initiator.req)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (i = 0; i < mvm->ftm_initiator.req->n_peers; i++) {
|
||||||
|
memcpy(result.addr, mvm->ftm_initiator.req->peers[i].addr,
|
||||||
|
ETH_ALEN);
|
||||||
|
result.ftm.burst_index = mvm->ftm_initiator.responses[i];
|
||||||
|
|
||||||
|
cfg80211_pmsr_report(mvm->ftm_initiator.req_wdev,
|
||||||
|
mvm->ftm_initiator.req,
|
||||||
|
&result, GFP_KERNEL);
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg80211_pmsr_complete(mvm->ftm_initiator.req_wdev,
|
||||||
|
mvm->ftm_initiator.req, GFP_KERNEL);
|
||||||
|
iwl_mvm_ftm_reset(mvm);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
iwl_ftm_range_request_status_to_err(enum iwl_tof_range_request_status s)
|
||||||
|
{
|
||||||
|
switch (s) {
|
||||||
|
case IWL_TOF_RANGE_REQUEST_STATUS_SUCCESS:
|
||||||
|
return 0;
|
||||||
|
case IWL_TOF_RANGE_REQUEST_STATUS_BUSY:
|
||||||
|
return -EBUSY;
|
||||||
|
default:
|
||||||
|
WARN_ON_ONCE(1);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void iwl_mvm_ftm_cmd_v5(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||||
|
struct iwl_tof_range_req_cmd_v5 *cmd,
|
||||||
|
struct cfg80211_pmsr_request *req)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
cmd->request_id = req->cookie;
|
||||||
|
cmd->num_of_ap = req->n_peers;
|
||||||
|
|
||||||
|
/* use maximum for "no timeout" or bigger than what we can do */
|
||||||
|
if (!req->timeout || req->timeout > 255 * 100)
|
||||||
|
cmd->req_timeout = 255;
|
||||||
|
else
|
||||||
|
cmd->req_timeout = DIV_ROUND_UP(req->timeout, 100);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We treat it always as random, since if not we'll
|
||||||
|
* have filled our local address there instead.
|
||||||
|
*/
|
||||||
|
cmd->macaddr_random = 1;
|
||||||
|
memcpy(cmd->macaddr_template, req->mac_addr, ETH_ALEN);
|
||||||
|
for (i = 0; i < ETH_ALEN; i++)
|
||||||
|
cmd->macaddr_mask[i] = ~req->mac_addr_mask[i];
|
||||||
|
|
||||||
|
if (vif->bss_conf.assoc)
|
||||||
|
memcpy(cmd->range_req_bssid, vif->bss_conf.bssid, ETH_ALEN);
|
||||||
|
else
|
||||||
|
eth_broadcast_addr(cmd->range_req_bssid);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void iwl_mvm_ftm_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||||
|
struct iwl_tof_range_req_cmd *cmd,
|
||||||
|
struct cfg80211_pmsr_request *req)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
cmd->initiator_flags =
|
||||||
|
cpu_to_le32(IWL_TOF_INITIATOR_FLAGS_MACADDR_RANDOM |
|
||||||
|
IWL_TOF_INITIATOR_FLAGS_NON_ASAP_SUPPORT);
|
||||||
|
cmd->request_id = req->cookie;
|
||||||
|
cmd->num_of_ap = req->n_peers;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Use a large value for "no timeout". Don't use the maximum value
|
||||||
|
* because of fw limitations.
|
||||||
|
*/
|
||||||
|
if (req->timeout)
|
||||||
|
cmd->req_timeout_ms = cpu_to_le32(req->timeout);
|
||||||
|
else
|
||||||
|
cmd->req_timeout_ms = cpu_to_le32(0xfffff);
|
||||||
|
|
||||||
|
memcpy(cmd->macaddr_template, req->mac_addr, ETH_ALEN);
|
||||||
|
for (i = 0; i < ETH_ALEN; i++)
|
||||||
|
cmd->macaddr_mask[i] = ~req->mac_addr_mask[i];
|
||||||
|
|
||||||
|
if (vif->bss_conf.assoc)
|
||||||
|
memcpy(cmd->range_req_bssid, vif->bss_conf.bssid, ETH_ALEN);
|
||||||
|
else
|
||||||
|
eth_broadcast_addr(cmd->range_req_bssid);
|
||||||
|
|
||||||
|
/* TODO: fill in tsf_mac_id if needed */
|
||||||
|
cmd->tsf_mac_id = cpu_to_le32(0xff);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int iwl_mvm_ftm_target_chandef(struct iwl_mvm *mvm,
|
||||||
|
struct cfg80211_pmsr_request_peer *peer,
|
||||||
|
u8 *channel, u8 *bandwidth,
|
||||||
|
u8 *ctrl_ch_position)
|
||||||
|
{
|
||||||
|
u32 freq = peer->chandef.chan->center_freq;
|
||||||
|
|
||||||
|
*channel = ieee80211_frequency_to_channel(freq);
|
||||||
|
|
||||||
|
switch (peer->chandef.width) {
|
||||||
|
case NL80211_CHAN_WIDTH_20_NOHT:
|
||||||
|
*bandwidth = IWL_TOF_BW_20_LEGACY;
|
||||||
|
break;
|
||||||
|
case NL80211_CHAN_WIDTH_20:
|
||||||
|
*bandwidth = IWL_TOF_BW_20_HT;
|
||||||
|
break;
|
||||||
|
case NL80211_CHAN_WIDTH_40:
|
||||||
|
*bandwidth = IWL_TOF_BW_40;
|
||||||
|
break;
|
||||||
|
case NL80211_CHAN_WIDTH_80:
|
||||||
|
*bandwidth = IWL_TOF_BW_80;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
IWL_ERR(mvm, "Unsupported BW in FTM request (%d)\n",
|
||||||
|
peer->chandef.width);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
*ctrl_ch_position = (peer->chandef.width > NL80211_CHAN_WIDTH_20) ?
|
||||||
|
iwl_mvm_get_ctrl_pos(&peer->chandef) : 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
iwl_mvm_ftm_put_target_v2(struct iwl_mvm *mvm,
|
||||||
|
struct cfg80211_pmsr_request_peer *peer,
|
||||||
|
struct iwl_tof_range_req_ap_entry_v2 *target)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = iwl_mvm_ftm_target_chandef(mvm, peer, &target->channel_num,
|
||||||
|
&target->bandwidth,
|
||||||
|
&target->ctrl_ch_position);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
memcpy(target->bssid, peer->addr, ETH_ALEN);
|
||||||
|
target->burst_period =
|
||||||
|
cpu_to_le16(peer->ftm.burst_period);
|
||||||
|
target->samples_per_burst = peer->ftm.ftms_per_burst;
|
||||||
|
target->num_of_bursts = peer->ftm.num_bursts_exp;
|
||||||
|
target->measure_type = 0; /* regular two-sided FTM */
|
||||||
|
target->retries_per_sample = peer->ftm.ftmr_retries;
|
||||||
|
target->asap_mode = peer->ftm.asap;
|
||||||
|
target->enable_dyn_ack = IWL_MVM_FTM_INITIATOR_DYNACK;
|
||||||
|
|
||||||
|
if (peer->ftm.request_lci)
|
||||||
|
target->location_req |= IWL_TOF_LOC_LCI;
|
||||||
|
if (peer->ftm.request_civicloc)
|
||||||
|
target->location_req |= IWL_TOF_LOC_CIVIC;
|
||||||
|
|
||||||
|
target->algo_type = IWL_MVM_FTM_INITIATOR_ALGO;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FTM_PUT_FLAG(flag) (target->initiator_ap_flags |= \
|
||||||
|
cpu_to_le32(IWL_INITIATOR_AP_FLAGS_##flag))
|
||||||
|
|
||||||
|
static int iwl_mvm_ftm_put_target(struct iwl_mvm *mvm,
|
||||||
|
struct cfg80211_pmsr_request_peer *peer,
|
||||||
|
struct iwl_tof_range_req_ap_entry *target)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = iwl_mvm_ftm_target_chandef(mvm, peer, &target->channel_num,
|
||||||
|
&target->bandwidth,
|
||||||
|
&target->ctrl_ch_position);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
memcpy(target->bssid, peer->addr, ETH_ALEN);
|
||||||
|
target->burst_period =
|
||||||
|
cpu_to_le16(peer->ftm.burst_period);
|
||||||
|
target->samples_per_burst = peer->ftm.ftms_per_burst;
|
||||||
|
target->num_of_bursts = peer->ftm.num_bursts_exp;
|
||||||
|
target->ftmr_max_retries = peer->ftm.ftmr_retries;
|
||||||
|
target->initiator_ap_flags = cpu_to_le32(0);
|
||||||
|
|
||||||
|
if (peer->ftm.asap)
|
||||||
|
FTM_PUT_FLAG(ASAP);
|
||||||
|
|
||||||
|
if (peer->ftm.request_lci)
|
||||||
|
FTM_PUT_FLAG(LCI_REQUEST);
|
||||||
|
|
||||||
|
if (peer->ftm.request_civicloc)
|
||||||
|
FTM_PUT_FLAG(CIVIC_REQUEST);
|
||||||
|
|
||||||
|
if (IWL_MVM_FTM_INITIATOR_DYNACK)
|
||||||
|
FTM_PUT_FLAG(DYN_ACK);
|
||||||
|
|
||||||
|
if (IWL_MVM_FTM_INITIATOR_ALGO == IWL_TOF_ALGO_TYPE_LINEAR_REG)
|
||||||
|
FTM_PUT_FLAG(ALGO_LR);
|
||||||
|
else if (IWL_MVM_FTM_INITIATOR_ALGO == IWL_TOF_ALGO_TYPE_FFT)
|
||||||
|
FTM_PUT_FLAG(ALGO_FFT);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int iwl_mvm_ftm_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||||
|
struct cfg80211_pmsr_request *req)
|
||||||
|
{
|
||||||
|
struct iwl_tof_range_req_cmd_v5 cmd_v5;
|
||||||
|
struct iwl_tof_range_req_cmd cmd;
|
||||||
|
bool new_api = fw_has_api(&mvm->fw->ucode_capa,
|
||||||
|
IWL_UCODE_TLV_API_FTM_NEW_RANGE_REQ);
|
||||||
|
u8 num_of_ap;
|
||||||
|
struct iwl_host_cmd hcmd = {
|
||||||
|
.id = iwl_cmd_id(TOF_RANGE_REQ_CMD, LOCATION_GROUP, 0),
|
||||||
|
.dataflags[0] = IWL_HCMD_DFL_DUP,
|
||||||
|
};
|
||||||
|
u32 status = 0;
|
||||||
|
int err, i;
|
||||||
|
|
||||||
|
lockdep_assert_held(&mvm->mutex);
|
||||||
|
|
||||||
|
if (mvm->ftm_initiator.req)
|
||||||
|
return -EBUSY;
|
||||||
|
|
||||||
|
if (new_api) {
|
||||||
|
iwl_mvm_ftm_cmd(mvm, vif, &cmd, req);
|
||||||
|
hcmd.data[0] = &cmd;
|
||||||
|
hcmd.len[0] = sizeof(cmd);
|
||||||
|
num_of_ap = cmd.num_of_ap;
|
||||||
|
} else {
|
||||||
|
iwl_mvm_ftm_cmd_v5(mvm, vif, &cmd_v5, req);
|
||||||
|
hcmd.data[0] = &cmd_v5;
|
||||||
|
hcmd.len[0] = sizeof(cmd_v5);
|
||||||
|
num_of_ap = cmd_v5.num_of_ap;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < num_of_ap; i++) {
|
||||||
|
struct cfg80211_pmsr_request_peer *peer = &req->peers[i];
|
||||||
|
|
||||||
|
if (new_api)
|
||||||
|
err = iwl_mvm_ftm_put_target(mvm, peer, &cmd.ap[i]);
|
||||||
|
else
|
||||||
|
err = iwl_mvm_ftm_put_target_v2(mvm, peer,
|
||||||
|
&cmd_v5.ap[i]);
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = iwl_mvm_send_cmd_status(mvm, &hcmd, &status);
|
||||||
|
if (!err && status) {
|
||||||
|
IWL_ERR(mvm, "FTM range request command failure, status: %u\n",
|
||||||
|
status);
|
||||||
|
err = iwl_ftm_range_request_status_to_err(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!err) {
|
||||||
|
mvm->ftm_initiator.req = req;
|
||||||
|
mvm->ftm_initiator.req_wdev = ieee80211_vif_to_wdev(vif);
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
void iwl_mvm_ftm_abort(struct iwl_mvm *mvm, struct cfg80211_pmsr_request *req)
|
||||||
|
{
|
||||||
|
struct iwl_tof_range_abort_cmd cmd = {
|
||||||
|
.request_id = req->cookie,
|
||||||
|
};
|
||||||
|
|
||||||
|
lockdep_assert_held(&mvm->mutex);
|
||||||
|
|
||||||
|
if (req != mvm->ftm_initiator.req)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(TOF_RANGE_ABORT_CMD,
|
||||||
|
LOCATION_GROUP, 0),
|
||||||
|
0, sizeof(cmd), &cmd))
|
||||||
|
IWL_ERR(mvm, "failed to abort FTM process\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int iwl_mvm_ftm_find_peer(struct cfg80211_pmsr_request *req,
|
||||||
|
const u8 *addr)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < req->n_peers; i++) {
|
||||||
|
struct cfg80211_pmsr_request_peer *peer = &req->peers[i];
|
||||||
|
|
||||||
|
if (ether_addr_equal_unaligned(peer->addr, addr))
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u64 iwl_mvm_ftm_get_host_time(struct iwl_mvm *mvm, __le32 fw_gp2_ts)
|
||||||
|
{
|
||||||
|
u32 gp2_ts = le32_to_cpu(fw_gp2_ts);
|
||||||
|
u32 curr_gp2, diff;
|
||||||
|
u64 now_from_boot_ns;
|
||||||
|
|
||||||
|
iwl_mvm_get_sync_time(mvm, &curr_gp2, &now_from_boot_ns);
|
||||||
|
|
||||||
|
if (curr_gp2 >= gp2_ts)
|
||||||
|
diff = curr_gp2 - gp2_ts;
|
||||||
|
else
|
||||||
|
diff = curr_gp2 + (U32_MAX - gp2_ts + 1);
|
||||||
|
|
||||||
|
return now_from_boot_ns - (u64)diff * 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void iwl_mvm_ftm_get_lci_civic(struct iwl_mvm *mvm,
|
||||||
|
struct cfg80211_pmsr_result *res)
|
||||||
|
{
|
||||||
|
struct iwl_mvm_loc_entry *entry;
|
||||||
|
|
||||||
|
list_for_each_entry(entry, &mvm->ftm_initiator.loc_list, list) {
|
||||||
|
if (!ether_addr_equal_unaligned(res->addr, entry->addr))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (entry->lci_len) {
|
||||||
|
res->ftm.lci_len = entry->lci_len;
|
||||||
|
res->ftm.lci = entry->buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry->civic_len) {
|
||||||
|
res->ftm.civicloc_len = entry->civic_len;
|
||||||
|
res->ftm.civicloc = entry->buf + entry->lci_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we found the entry we needed */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int iwl_mvm_ftm_range_resp_valid(struct iwl_mvm *mvm, u8 request_id,
|
||||||
|
u8 num_of_aps)
|
||||||
|
{
|
||||||
|
lockdep_assert_held(&mvm->mutex);
|
||||||
|
|
||||||
|
if (request_id != (u8)mvm->ftm_initiator.req->cookie) {
|
||||||
|
IWL_ERR(mvm, "Request ID mismatch, got %u, active %u\n",
|
||||||
|
request_id, (u8)mvm->ftm_initiator.req->cookie);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num_of_aps > mvm->ftm_initiator.req->n_peers) {
|
||||||
|
IWL_ERR(mvm, "FTM range response invalid\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void iwl_mvm_debug_range_resp(struct iwl_mvm *mvm, u8 index,
|
||||||
|
struct cfg80211_pmsr_result *res)
|
||||||
|
{
|
||||||
|
s64 rtt_avg = res->ftm.rtt_avg * 100;
|
||||||
|
|
||||||
|
do_div(rtt_avg, 6666);
|
||||||
|
|
||||||
|
IWL_DEBUG_INFO(mvm, "entry %d\n", index);
|
||||||
|
IWL_DEBUG_INFO(mvm, "\tstatus: %d\n", res->status);
|
||||||
|
IWL_DEBUG_INFO(mvm, "\tBSSID: %pM\n", res->addr);
|
||||||
|
IWL_DEBUG_INFO(mvm, "\thost time: %llu\n", res->host_time);
|
||||||
|
IWL_DEBUG_INFO(mvm, "\tburst index: %hhu\n", res->ftm.burst_index);
|
||||||
|
IWL_DEBUG_INFO(mvm, "\tsuccess num: %u\n", res->ftm.num_ftmr_successes);
|
||||||
|
IWL_DEBUG_INFO(mvm, "\trssi: %d\n", res->ftm.rssi_avg);
|
||||||
|
IWL_DEBUG_INFO(mvm, "\trssi spread: %hhu\n", res->ftm.rssi_spread);
|
||||||
|
IWL_DEBUG_INFO(mvm, "\trtt: %lld\n", res->ftm.rtt_avg);
|
||||||
|
IWL_DEBUG_INFO(mvm, "\trtt var: %llu\n", res->ftm.rtt_variance);
|
||||||
|
IWL_DEBUG_INFO(mvm, "\trtt spread: %llu\n", res->ftm.rtt_spread);
|
||||||
|
IWL_DEBUG_INFO(mvm, "\tdistance: %lld\n", rtt_avg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void iwl_mvm_ftm_range_resp(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb)
|
||||||
|
{
|
||||||
|
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||||
|
struct iwl_tof_range_rsp_ntfy_v5 *fw_resp_v5 = (void *)pkt->data;
|
||||||
|
struct iwl_tof_range_rsp_ntfy *fw_resp = (void *)pkt->data;
|
||||||
|
int i;
|
||||||
|
bool new_api = fw_has_api(&mvm->fw->ucode_capa,
|
||||||
|
IWL_UCODE_TLV_API_FTM_NEW_RANGE_REQ);
|
||||||
|
u8 num_of_aps, last_in_batch;
|
||||||
|
|
||||||
|
lockdep_assert_held(&mvm->mutex);
|
||||||
|
|
||||||
|
if (!mvm->ftm_initiator.req) {
|
||||||
|
IWL_ERR(mvm, "Got FTM response but have no request?\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new_api) {
|
||||||
|
if (iwl_mvm_ftm_range_resp_valid(mvm, fw_resp->request_id,
|
||||||
|
fw_resp->num_of_aps))
|
||||||
|
return;
|
||||||
|
|
||||||
|
num_of_aps = fw_resp->num_of_aps;
|
||||||
|
last_in_batch = fw_resp->last_report;
|
||||||
|
} else {
|
||||||
|
if (iwl_mvm_ftm_range_resp_valid(mvm, fw_resp_v5->request_id,
|
||||||
|
fw_resp_v5->num_of_aps))
|
||||||
|
return;
|
||||||
|
|
||||||
|
num_of_aps = fw_resp_v5->num_of_aps;
|
||||||
|
last_in_batch = fw_resp_v5->last_in_batch;
|
||||||
|
}
|
||||||
|
|
||||||
|
IWL_DEBUG_INFO(mvm, "Range response received\n");
|
||||||
|
IWL_DEBUG_INFO(mvm, "request id: %lld, num of entries: %hhu\n",
|
||||||
|
mvm->ftm_initiator.req->cookie, num_of_aps);
|
||||||
|
|
||||||
|
for (i = 0; i < num_of_aps && i < IWL_MVM_TOF_MAX_APS; i++) {
|
||||||
|
struct cfg80211_pmsr_result result = {};
|
||||||
|
struct iwl_tof_range_rsp_ap_entry_ntfy *fw_ap;
|
||||||
|
int peer_idx;
|
||||||
|
|
||||||
|
if (new_api) {
|
||||||
|
fw_ap = &fw_resp->ap[i];
|
||||||
|
result.final = fw_resp->ap[i].last_burst;
|
||||||
|
} else {
|
||||||
|
/* the first part is the same for old and new APIs */
|
||||||
|
fw_ap = (void *)&fw_resp_v5->ap[i];
|
||||||
|
/*
|
||||||
|
* FIXME: the firmware needs to report this, we don't
|
||||||
|
* even know the number of bursts the responder picked
|
||||||
|
* (if we asked it to)
|
||||||
|
*/
|
||||||
|
result.final = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
peer_idx = iwl_mvm_ftm_find_peer(mvm->ftm_initiator.req,
|
||||||
|
fw_ap->bssid);
|
||||||
|
if (peer_idx < 0) {
|
||||||
|
IWL_WARN(mvm,
|
||||||
|
"Unknown address (%pM, target #%d) in FTM response\n",
|
||||||
|
fw_ap->bssid, i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (fw_ap->measure_status) {
|
||||||
|
case IWL_TOF_ENTRY_SUCCESS:
|
||||||
|
result.status = NL80211_PMSR_STATUS_SUCCESS;
|
||||||
|
break;
|
||||||
|
case IWL_TOF_ENTRY_TIMING_MEASURE_TIMEOUT:
|
||||||
|
result.status = NL80211_PMSR_STATUS_TIMEOUT;
|
||||||
|
break;
|
||||||
|
case IWL_TOF_ENTRY_NO_RESPONSE:
|
||||||
|
result.status = NL80211_PMSR_STATUS_FAILURE;
|
||||||
|
result.ftm.failure_reason =
|
||||||
|
NL80211_PMSR_FTM_FAILURE_NO_RESPONSE;
|
||||||
|
break;
|
||||||
|
case IWL_TOF_ENTRY_REQUEST_REJECTED:
|
||||||
|
result.status = NL80211_PMSR_STATUS_FAILURE;
|
||||||
|
result.ftm.failure_reason =
|
||||||
|
NL80211_PMSR_FTM_FAILURE_PEER_BUSY;
|
||||||
|
result.ftm.busy_retry_time = fw_ap->refusal_period;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
result.status = NL80211_PMSR_STATUS_FAILURE;
|
||||||
|
result.ftm.failure_reason =
|
||||||
|
NL80211_PMSR_FTM_FAILURE_UNSPECIFIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
memcpy(result.addr, fw_ap->bssid, ETH_ALEN);
|
||||||
|
result.host_time = iwl_mvm_ftm_get_host_time(mvm,
|
||||||
|
fw_ap->timestamp);
|
||||||
|
result.type = NL80211_PMSR_TYPE_FTM;
|
||||||
|
result.ftm.burst_index = mvm->ftm_initiator.responses[peer_idx];
|
||||||
|
mvm->ftm_initiator.responses[peer_idx]++;
|
||||||
|
result.ftm.rssi_avg = fw_ap->rssi;
|
||||||
|
result.ftm.rssi_avg_valid = 1;
|
||||||
|
result.ftm.rssi_spread = fw_ap->rssi_spread;
|
||||||
|
result.ftm.rssi_spread_valid = 1;
|
||||||
|
result.ftm.rtt_avg = (s32)le32_to_cpu(fw_ap->rtt);
|
||||||
|
result.ftm.rtt_avg_valid = 1;
|
||||||
|
result.ftm.rtt_variance = le32_to_cpu(fw_ap->rtt_variance);
|
||||||
|
result.ftm.rtt_variance_valid = 1;
|
||||||
|
result.ftm.rtt_spread = le32_to_cpu(fw_ap->rtt_spread);
|
||||||
|
result.ftm.rtt_spread_valid = 1;
|
||||||
|
|
||||||
|
iwl_mvm_ftm_get_lci_civic(mvm, &result);
|
||||||
|
|
||||||
|
cfg80211_pmsr_report(mvm->ftm_initiator.req_wdev,
|
||||||
|
mvm->ftm_initiator.req,
|
||||||
|
&result, GFP_KERNEL);
|
||||||
|
|
||||||
|
iwl_mvm_debug_range_resp(mvm, i, &result);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (last_in_batch) {
|
||||||
|
cfg80211_pmsr_complete(mvm->ftm_initiator.req_wdev,
|
||||||
|
mvm->ftm_initiator.req,
|
||||||
|
GFP_KERNEL);
|
||||||
|
iwl_mvm_ftm_reset(mvm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void iwl_mvm_ftm_lc_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb)
|
||||||
|
{
|
||||||
|
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||||
|
const struct ieee80211_mgmt *mgmt = (void *)pkt->data;
|
||||||
|
size_t len = iwl_rx_packet_payload_len(pkt);
|
||||||
|
struct iwl_mvm_loc_entry *entry;
|
||||||
|
const u8 *ies, *lci, *civic, *msr_ie;
|
||||||
|
size_t ies_len, lci_len = 0, civic_len = 0;
|
||||||
|
size_t baselen = IEEE80211_MIN_ACTION_SIZE +
|
||||||
|
sizeof(mgmt->u.action.u.ftm);
|
||||||
|
static const u8 rprt_type_lci = IEEE80211_SPCT_MSR_RPRT_TYPE_LCI;
|
||||||
|
static const u8 rprt_type_civic = IEEE80211_SPCT_MSR_RPRT_TYPE_CIVIC;
|
||||||
|
|
||||||
|
if (len <= baselen)
|
||||||
|
return;
|
||||||
|
|
||||||
|
lockdep_assert_held(&mvm->mutex);
|
||||||
|
|
||||||
|
ies = mgmt->u.action.u.ftm.variable;
|
||||||
|
ies_len = len - baselen;
|
||||||
|
|
||||||
|
msr_ie = cfg80211_find_ie_match(WLAN_EID_MEASURE_REPORT, ies, ies_len,
|
||||||
|
&rprt_type_lci, 1, 4);
|
||||||
|
if (msr_ie) {
|
||||||
|
lci = msr_ie + 2;
|
||||||
|
lci_len = msr_ie[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
msr_ie = cfg80211_find_ie_match(WLAN_EID_MEASURE_REPORT, ies, ies_len,
|
||||||
|
&rprt_type_civic, 1, 4);
|
||||||
|
if (msr_ie) {
|
||||||
|
civic = msr_ie + 2;
|
||||||
|
civic_len = msr_ie[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
entry = kmalloc(sizeof(*entry) + lci_len + civic_len, GFP_KERNEL);
|
||||||
|
if (!entry)
|
||||||
|
return;
|
||||||
|
|
||||||
|
memcpy(entry->addr, mgmt->bssid, ETH_ALEN);
|
||||||
|
|
||||||
|
entry->lci_len = lci_len;
|
||||||
|
if (lci_len)
|
||||||
|
memcpy(entry->buf, lci, lci_len);
|
||||||
|
|
||||||
|
entry->civic_len = civic_len;
|
||||||
|
if (civic_len)
|
||||||
|
memcpy(entry->buf + lci_len, civic, civic_len);
|
||||||
|
|
||||||
|
list_add_tail(&entry->list, &mvm->ftm_initiator.loc_list);
|
||||||
|
}
|
244
drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c
Normal file
244
drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c
Normal file
|
@ -0,0 +1,244 @@
|
||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||||
|
* redistributing this file, you may do so under either license.
|
||||||
|
*
|
||||||
|
* GPL LICENSE SUMMARY
|
||||||
|
*
|
||||||
|
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
|
||||||
|
* Copyright (C) 2018 Intel Corporation
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* The full GNU General Public License is included in this distribution
|
||||||
|
* in the file called COPYING.
|
||||||
|
*
|
||||||
|
* Contact Information:
|
||||||
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
|
*
|
||||||
|
* BSD LICENSE
|
||||||
|
*
|
||||||
|
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
|
||||||
|
* Copyright (C) 2018 Intel Corporation
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
* * Neither the name Intel Corporation nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
#include <net/cfg80211.h>
|
||||||
|
#include <linux/etherdevice.h>
|
||||||
|
#include "mvm.h"
|
||||||
|
#include "constants.h"
|
||||||
|
|
||||||
|
static int
|
||||||
|
iwl_mvm_ftm_responder_cmd(struct iwl_mvm *mvm,
|
||||||
|
struct ieee80211_vif *vif,
|
||||||
|
struct cfg80211_chan_def *chandef)
|
||||||
|
{
|
||||||
|
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||||
|
struct iwl_tof_responder_config_cmd cmd = {
|
||||||
|
.channel_num = chandef->chan->hw_value,
|
||||||
|
.cmd_valid_fields =
|
||||||
|
cpu_to_le32(IWL_TOF_RESPONDER_CMD_VALID_CHAN_INFO |
|
||||||
|
IWL_TOF_RESPONDER_CMD_VALID_BSSID |
|
||||||
|
IWL_TOF_RESPONDER_CMD_VALID_STA_ID),
|
||||||
|
.sta_id = mvmvif->bcast_sta.sta_id,
|
||||||
|
};
|
||||||
|
|
||||||
|
lockdep_assert_held(&mvm->mutex);
|
||||||
|
|
||||||
|
switch (chandef->width) {
|
||||||
|
case NL80211_CHAN_WIDTH_20_NOHT:
|
||||||
|
cmd.bandwidth = IWL_TOF_BW_20_LEGACY;
|
||||||
|
break;
|
||||||
|
case NL80211_CHAN_WIDTH_20:
|
||||||
|
cmd.bandwidth = IWL_TOF_BW_20_HT;
|
||||||
|
break;
|
||||||
|
case NL80211_CHAN_WIDTH_40:
|
||||||
|
cmd.bandwidth = IWL_TOF_BW_40;
|
||||||
|
cmd.ctrl_ch_position = iwl_mvm_get_ctrl_pos(chandef);
|
||||||
|
break;
|
||||||
|
case NL80211_CHAN_WIDTH_80:
|
||||||
|
cmd.bandwidth = IWL_TOF_BW_80;
|
||||||
|
cmd.ctrl_ch_position = iwl_mvm_get_ctrl_pos(chandef);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
WARN_ON(1);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(cmd.bssid, vif->addr, ETH_ALEN);
|
||||||
|
|
||||||
|
return iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(TOF_RESPONDER_CONFIG_CMD,
|
||||||
|
LOCATION_GROUP, 0),
|
||||||
|
0, sizeof(cmd), &cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
iwl_mvm_ftm_responder_dyn_cfg_cmd(struct iwl_mvm *mvm,
|
||||||
|
struct ieee80211_vif *vif,
|
||||||
|
struct ieee80211_ftm_responder_params *params)
|
||||||
|
{
|
||||||
|
struct iwl_tof_responder_dyn_config_cmd cmd = {
|
||||||
|
.lci_len = cpu_to_le32(params->lci_len + 2),
|
||||||
|
.civic_len = cpu_to_le32(params->civicloc_len + 2),
|
||||||
|
};
|
||||||
|
u8 data[IWL_LCI_CIVIC_IE_MAX_SIZE] = {0};
|
||||||
|
struct iwl_host_cmd hcmd = {
|
||||||
|
.id = iwl_cmd_id(TOF_RESPONDER_DYN_CONFIG_CMD,
|
||||||
|
LOCATION_GROUP, 0),
|
||||||
|
.data[0] = &cmd,
|
||||||
|
.len[0] = sizeof(cmd),
|
||||||
|
.data[1] = &data,
|
||||||
|
/* .len[1] set later */
|
||||||
|
/* may not be able to DMA from stack */
|
||||||
|
.dataflags[1] = IWL_HCMD_DFL_DUP,
|
||||||
|
};
|
||||||
|
u32 aligned_lci_len = ALIGN(params->lci_len + 2, 4);
|
||||||
|
u32 aligned_civicloc_len = ALIGN(params->civicloc_len + 2, 4);
|
||||||
|
u8 *pos = data;
|
||||||
|
|
||||||
|
lockdep_assert_held(&mvm->mutex);
|
||||||
|
|
||||||
|
if (aligned_lci_len + aligned_civicloc_len > sizeof(data)) {
|
||||||
|
IWL_ERR(mvm, "LCI/civicloc data too big (%zd + %zd)\n",
|
||||||
|
params->lci_len, params->civicloc_len);
|
||||||
|
return -ENOBUFS;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos[0] = WLAN_EID_MEASURE_REPORT;
|
||||||
|
pos[1] = params->lci_len;
|
||||||
|
memcpy(pos + 2, params->lci, params->lci_len);
|
||||||
|
|
||||||
|
pos += aligned_lci_len;
|
||||||
|
pos[0] = WLAN_EID_MEASURE_REPORT;
|
||||||
|
pos[1] = params->civicloc_len;
|
||||||
|
memcpy(pos + 2, params->civicloc, params->civicloc_len);
|
||||||
|
|
||||||
|
hcmd.len[1] = aligned_lci_len + aligned_civicloc_len;
|
||||||
|
|
||||||
|
return iwl_mvm_send_cmd(mvm, &hcmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
int iwl_mvm_ftm_start_responder(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||||
|
{
|
||||||
|
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||||
|
struct ieee80211_ftm_responder_params *params;
|
||||||
|
struct ieee80211_chanctx_conf ctx, *pctx;
|
||||||
|
u16 *phy_ctxt_id;
|
||||||
|
struct iwl_mvm_phy_ctxt *phy_ctxt;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
params = vif->bss_conf.ftmr_params;
|
||||||
|
|
||||||
|
lockdep_assert_held(&mvm->mutex);
|
||||||
|
|
||||||
|
if (WARN_ON_ONCE(!vif->bss_conf.ftm_responder))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (vif->p2p || vif->type != NL80211_IFTYPE_AP ||
|
||||||
|
!mvmvif->ap_ibss_active) {
|
||||||
|
IWL_ERR(mvm, "Cannot start responder, not in AP mode\n");
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
rcu_read_lock();
|
||||||
|
pctx = rcu_dereference(vif->chanctx_conf);
|
||||||
|
/* Copy the ctx to unlock the rcu and send the phy ctxt. We don't care
|
||||||
|
* about changes in the ctx after releasing the lock because the driver
|
||||||
|
* is still protected by the mutex. */
|
||||||
|
ctx = *pctx;
|
||||||
|
phy_ctxt_id = (u16 *)pctx->drv_priv;
|
||||||
|
rcu_read_unlock();
|
||||||
|
|
||||||
|
phy_ctxt = &mvm->phy_ctxts[*phy_ctxt_id];
|
||||||
|
ret = iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &ctx.def,
|
||||||
|
ctx.rx_chains_static,
|
||||||
|
ctx.rx_chains_dynamic);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = iwl_mvm_ftm_responder_cmd(mvm, vif, &ctx.def);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (params)
|
||||||
|
ret = iwl_mvm_ftm_responder_dyn_cfg_cmd(mvm, vif, params);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void iwl_mvm_ftm_restart_responder(struct iwl_mvm *mvm,
|
||||||
|
struct ieee80211_vif *vif)
|
||||||
|
{
|
||||||
|
if (!vif->bss_conf.ftm_responder)
|
||||||
|
return;
|
||||||
|
|
||||||
|
iwl_mvm_ftm_start_responder(mvm, vif);
|
||||||
|
}
|
||||||
|
|
||||||
|
void iwl_mvm_ftm_responder_stats(struct iwl_mvm *mvm,
|
||||||
|
struct iwl_rx_cmd_buffer *rxb)
|
||||||
|
{
|
||||||
|
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||||
|
struct iwl_ftm_responder_stats *resp = (void *)pkt->data;
|
||||||
|
struct cfg80211_ftm_responder_stats *stats = &mvm->ftm_resp_stats;
|
||||||
|
u32 flags = le32_to_cpu(resp->flags);
|
||||||
|
|
||||||
|
if (resp->success_ftm == resp->ftm_per_burst)
|
||||||
|
stats->success_num++;
|
||||||
|
else if (resp->success_ftm >= 2)
|
||||||
|
stats->partial_num++;
|
||||||
|
else
|
||||||
|
stats->failed_num++;
|
||||||
|
|
||||||
|
if ((flags & FTM_RESP_STAT_ASAP_REQ) &&
|
||||||
|
(flags & FTM_RESP_STAT_ASAP_RESP))
|
||||||
|
stats->asap_num++;
|
||||||
|
|
||||||
|
if (flags & FTM_RESP_STAT_NON_ASAP_RESP)
|
||||||
|
stats->non_asap_num++;
|
||||||
|
|
||||||
|
stats->total_duration_ms += le32_to_cpu(resp->duration) / USEC_PER_MSEC;
|
||||||
|
|
||||||
|
if (flags & FTM_RESP_STAT_TRIGGER_UNKNOWN)
|
||||||
|
stats->unknown_triggers_num++;
|
||||||
|
|
||||||
|
if (flags & FTM_RESP_STAT_DUP)
|
||||||
|
stats->reschedule_requests_num++;
|
||||||
|
|
||||||
|
if (flags & FTM_RESP_STAT_NON_ASAP_OUT_WIN)
|
||||||
|
stats->out_of_window_triggers_num++;
|
||||||
|
}
|
|
@ -8,7 +8,7 @@
|
||||||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||||
* Copyright(c) 2018 Intel Corporation
|
* Copyright(c) 2018 - 2019 Intel Corporation
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of version 2 of the GNU General Public License as
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
|
@ -31,7 +31,7 @@
|
||||||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||||
* Copyright(c) 2018 Intel Corporation
|
* Copyright(c) 2018 - 2019 Intel Corporation
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -218,7 +218,7 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
|
||||||
struct iwl_lmac_alive *lmac1;
|
struct iwl_lmac_alive *lmac1;
|
||||||
struct iwl_lmac_alive *lmac2 = NULL;
|
struct iwl_lmac_alive *lmac2 = NULL;
|
||||||
u16 status;
|
u16 status;
|
||||||
u32 umac_error_event_table;
|
u32 lmac_error_event_table, umac_error_event_table;
|
||||||
|
|
||||||
if (iwl_rx_packet_payload_len(pkt) == sizeof(*palive)) {
|
if (iwl_rx_packet_payload_len(pkt) == sizeof(*palive)) {
|
||||||
palive = (void *)pkt->data;
|
palive = (void *)pkt->data;
|
||||||
|
@ -233,30 +233,35 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
|
||||||
status = le16_to_cpu(palive3->status);
|
status = le16_to_cpu(palive3->status);
|
||||||
}
|
}
|
||||||
|
|
||||||
mvm->error_event_table[0] = le32_to_cpu(lmac1->error_event_table_ptr);
|
lmac_error_event_table =
|
||||||
if (lmac2)
|
le32_to_cpu(lmac1->dbg_ptrs.error_event_table_ptr);
|
||||||
mvm->error_event_table[1] =
|
iwl_fw_lmac1_set_alive_err_table(mvm->trans, lmac_error_event_table);
|
||||||
le32_to_cpu(lmac2->error_event_table_ptr);
|
|
||||||
mvm->log_event_table = le32_to_cpu(lmac1->log_event_table_ptr);
|
|
||||||
|
|
||||||
umac_error_event_table = le32_to_cpu(umac->error_info_addr);
|
if (lmac2)
|
||||||
|
mvm->trans->lmac_error_event_table[1] =
|
||||||
|
le32_to_cpu(lmac2->dbg_ptrs.error_event_table_ptr);
|
||||||
|
|
||||||
|
umac_error_event_table = le32_to_cpu(umac->dbg_ptrs.error_info_addr);
|
||||||
|
|
||||||
if (!umac_error_event_table) {
|
if (!umac_error_event_table) {
|
||||||
mvm->support_umac_log = false;
|
mvm->support_umac_log = false;
|
||||||
} else if (umac_error_event_table >=
|
} else if (umac_error_event_table >=
|
||||||
mvm->trans->cfg->min_umac_error_event_table) {
|
mvm->trans->cfg->min_umac_error_event_table) {
|
||||||
mvm->support_umac_log = true;
|
mvm->support_umac_log = true;
|
||||||
mvm->umac_error_event_table = umac_error_event_table;
|
|
||||||
} else {
|
} else {
|
||||||
IWL_ERR(mvm,
|
IWL_ERR(mvm,
|
||||||
"Not valid error log pointer 0x%08X for %s uCode\n",
|
"Not valid error log pointer 0x%08X for %s uCode\n",
|
||||||
mvm->umac_error_event_table,
|
umac_error_event_table,
|
||||||
(mvm->fwrt.cur_fw_img == IWL_UCODE_INIT) ?
|
(mvm->fwrt.cur_fw_img == IWL_UCODE_INIT) ?
|
||||||
"Init" : "RT");
|
"Init" : "RT");
|
||||||
mvm->support_umac_log = false;
|
mvm->support_umac_log = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
alive_data->scd_base_addr = le32_to_cpu(lmac1->scd_base_ptr);
|
if (mvm->support_umac_log)
|
||||||
|
iwl_fw_umac_set_alive_err_table(mvm->trans,
|
||||||
|
umac_error_event_table);
|
||||||
|
|
||||||
|
alive_data->scd_base_addr = le32_to_cpu(lmac1->dbg_ptrs.scd_base_ptr);
|
||||||
alive_data->valid = status == IWL_ALIVE_STATUS_OK;
|
alive_data->valid = status == IWL_ALIVE_STATUS_OK;
|
||||||
|
|
||||||
IWL_DEBUG_FW(mvm,
|
IWL_DEBUG_FW(mvm,
|
||||||
|
@ -346,8 +351,9 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
|
||||||
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22000)
|
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22000)
|
||||||
IWL_ERR(mvm,
|
IWL_ERR(mvm,
|
||||||
"SecBoot CPU1 Status: 0x%x, CPU2 Status: 0x%x\n",
|
"SecBoot CPU1 Status: 0x%x, CPU2 Status: 0x%x\n",
|
||||||
iwl_read_prph(trans, UMAG_SB_CPU_1_STATUS),
|
iwl_read_umac_prph(trans, UMAG_SB_CPU_1_STATUS),
|
||||||
iwl_read_prph(trans, UMAG_SB_CPU_2_STATUS));
|
iwl_read_umac_prph(trans,
|
||||||
|
UMAG_SB_CPU_2_STATUS));
|
||||||
else if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_8000)
|
else if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_8000)
|
||||||
IWL_ERR(mvm,
|
IWL_ERR(mvm,
|
||||||
"SecBoot CPU1 Status: 0x%x, CPU2 Status: 0x%x\n",
|
"SecBoot CPU1 Status: 0x%x, CPU2 Status: 0x%x\n",
|
||||||
|
@ -413,12 +419,15 @@ static int iwl_run_unified_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
|
||||||
iwl_wait_init_complete,
|
iwl_wait_init_complete,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
|
iwl_fw_dbg_apply_point(&mvm->fwrt, IWL_FW_INI_APPLY_EARLY);
|
||||||
|
|
||||||
/* Will also start the device */
|
/* Will also start the device */
|
||||||
ret = iwl_mvm_load_ucode_wait_alive(mvm, IWL_UCODE_REGULAR);
|
ret = iwl_mvm_load_ucode_wait_alive(mvm, IWL_UCODE_REGULAR);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
IWL_ERR(mvm, "Failed to start RT ucode: %d\n", ret);
|
IWL_ERR(mvm, "Failed to start RT ucode: %d\n", ret);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
iwl_fw_dbg_apply_point(&mvm->fwrt, IWL_FW_INI_APPLY_AFTER_ALIVE);
|
||||||
|
|
||||||
/* Send init config command to mark that we are sending NVM access
|
/* Send init config command to mark that we are sending NVM access
|
||||||
* commands
|
* commands
|
||||||
|
@ -971,6 +980,57 @@ int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm)
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_ACPI */
|
#endif /* CONFIG_ACPI */
|
||||||
|
|
||||||
|
void iwl_mvm_send_recovery_cmd(struct iwl_mvm *mvm, u32 flags)
|
||||||
|
{
|
||||||
|
u32 error_log_size = mvm->fw->ucode_capa.error_log_size;
|
||||||
|
int ret;
|
||||||
|
u32 resp;
|
||||||
|
|
||||||
|
struct iwl_fw_error_recovery_cmd recovery_cmd = {
|
||||||
|
.flags = cpu_to_le32(flags),
|
||||||
|
.buf_size = 0,
|
||||||
|
};
|
||||||
|
struct iwl_host_cmd host_cmd = {
|
||||||
|
.id = WIDE_ID(SYSTEM_GROUP, FW_ERROR_RECOVERY_CMD),
|
||||||
|
.flags = CMD_WANT_SKB,
|
||||||
|
.data = {&recovery_cmd, },
|
||||||
|
.len = {sizeof(recovery_cmd), },
|
||||||
|
};
|
||||||
|
|
||||||
|
/* no error log was defined in TLV */
|
||||||
|
if (!error_log_size)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (flags & ERROR_RECOVERY_UPDATE_DB) {
|
||||||
|
/* no buf was allocated while HW reset */
|
||||||
|
if (!mvm->error_recovery_buf)
|
||||||
|
return;
|
||||||
|
|
||||||
|
host_cmd.data[1] = mvm->error_recovery_buf;
|
||||||
|
host_cmd.len[1] = error_log_size;
|
||||||
|
host_cmd.dataflags[1] = IWL_HCMD_DFL_NOCOPY;
|
||||||
|
recovery_cmd.buf_size = cpu_to_le32(error_log_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = iwl_mvm_send_cmd(mvm, &host_cmd);
|
||||||
|
kfree(mvm->error_recovery_buf);
|
||||||
|
mvm->error_recovery_buf = NULL;
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
IWL_ERR(mvm, "Failed to send recovery cmd %d\n", ret);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* skb respond is only relevant in ERROR_RECOVERY_UPDATE_DB */
|
||||||
|
if (flags & ERROR_RECOVERY_UPDATE_DB) {
|
||||||
|
resp = le32_to_cpu(*(__le32 *)host_cmd.resp_pkt->data);
|
||||||
|
if (resp)
|
||||||
|
IWL_ERR(mvm,
|
||||||
|
"Failed to send recovery cmd blob was invalid %d\n",
|
||||||
|
resp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int iwl_mvm_sar_init(struct iwl_mvm *mvm)
|
static int iwl_mvm_sar_init(struct iwl_mvm *mvm)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -1207,6 +1267,12 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
|
||||||
if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
|
if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
|
||||||
iwl_mvm_unref(mvm, IWL_MVM_REF_UCODE_DOWN);
|
iwl_mvm_unref(mvm, IWL_MVM_REF_UCODE_DOWN);
|
||||||
|
|
||||||
|
if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
|
||||||
|
iwl_mvm_send_recovery_cmd(mvm, ERROR_RECOVERY_UPDATE_DB);
|
||||||
|
|
||||||
|
if (iwl_acpi_get_eckv(mvm->dev, &mvm->ext_clock_valid))
|
||||||
|
IWL_DEBUG_INFO(mvm, "ECKV table doesn't exist in BIOS\n");
|
||||||
|
|
||||||
ret = iwl_mvm_sar_init(mvm);
|
ret = iwl_mvm_sar_init(mvm);
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
ret = iwl_mvm_sar_geo_init(mvm);
|
ret = iwl_mvm_sar_geo_init(mvm);
|
||||||
|
|
|
@ -811,9 +811,9 @@ static int iwl_mvm_mac_ctxt_cmd_p2p_device(struct iwl_mvm *mvm,
|
||||||
return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
|
return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void iwl_mvm_mac_ctxt_set_tim(struct iwl_mvm *mvm,
|
void iwl_mvm_mac_ctxt_set_tim(struct iwl_mvm *mvm,
|
||||||
__le32 *tim_index, __le32 *tim_size,
|
__le32 *tim_index, __le32 *tim_size,
|
||||||
u8 *beacon, u32 frame_size)
|
u8 *beacon, u32 frame_size)
|
||||||
{
|
{
|
||||||
u32 tim_idx;
|
u32 tim_idx;
|
||||||
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)beacon;
|
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)beacon;
|
||||||
|
@ -853,8 +853,8 @@ static u32 iwl_mvm_find_ie_offset(u8 *beacon, u8 eid, u32 frame_size)
|
||||||
return ie - beacon;
|
return ie - beacon;
|
||||||
}
|
}
|
||||||
|
|
||||||
static u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct ieee80211_tx_info *info,
|
u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct ieee80211_tx_info *info,
|
||||||
struct ieee80211_vif *vif)
|
struct ieee80211_vif *vif)
|
||||||
{
|
{
|
||||||
u8 rate;
|
u8 rate;
|
||||||
|
|
||||||
|
@ -904,9 +904,9 @@ static void iwl_mvm_mac_ctxt_set_tx(struct iwl_mvm *mvm,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int iwl_mvm_mac_ctxt_send_beacon_cmd(struct iwl_mvm *mvm,
|
int iwl_mvm_mac_ctxt_send_beacon_cmd(struct iwl_mvm *mvm,
|
||||||
struct sk_buff *beacon,
|
struct sk_buff *beacon,
|
||||||
void *data, int len)
|
void *data, int len)
|
||||||
{
|
{
|
||||||
struct iwl_host_cmd cmd = {
|
struct iwl_host_cmd cmd = {
|
||||||
.id = BEACON_TEMPLATE_CMD,
|
.id = BEACON_TEMPLATE_CMD,
|
||||||
|
@ -1009,9 +1009,9 @@ static int iwl_mvm_mac_ctxt_send_beacon_v9(struct iwl_mvm *mvm,
|
||||||
sizeof(beacon_cmd));
|
sizeof(beacon_cmd));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm,
|
int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm,
|
||||||
struct ieee80211_vif *vif,
|
struct ieee80211_vif *vif,
|
||||||
struct sk_buff *beacon)
|
struct sk_buff *beacon)
|
||||||
{
|
{
|
||||||
if (WARN_ON(!beacon))
|
if (WARN_ON(!beacon))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
|
@ -184,6 +184,29 @@ static const struct iwl_fw_bcast_filter iwl_mvm_default_bcast_filters[] = {
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static const struct cfg80211_pmsr_capabilities iwl_mvm_pmsr_capa = {
|
||||||
|
.max_peers = IWL_MVM_TOF_MAX_APS,
|
||||||
|
.report_ap_tsf = 1,
|
||||||
|
.randomize_mac_addr = 1,
|
||||||
|
|
||||||
|
.ftm = {
|
||||||
|
.supported = 1,
|
||||||
|
.asap = 1,
|
||||||
|
.non_asap = 1,
|
||||||
|
.request_lci = 1,
|
||||||
|
.request_civicloc = 1,
|
||||||
|
.max_bursts_exponent = -1, /* all supported */
|
||||||
|
.max_ftms_per_burst = 0, /* no limits */
|
||||||
|
.bandwidths = BIT(NL80211_CHAN_WIDTH_20_NOHT) |
|
||||||
|
BIT(NL80211_CHAN_WIDTH_20) |
|
||||||
|
BIT(NL80211_CHAN_WIDTH_40) |
|
||||||
|
BIT(NL80211_CHAN_WIDTH_80),
|
||||||
|
.preambles = BIT(NL80211_PREAMBLE_LEGACY) |
|
||||||
|
BIT(NL80211_PREAMBLE_HT) |
|
||||||
|
BIT(NL80211_PREAMBLE_VHT),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
void iwl_mvm_ref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type)
|
void iwl_mvm_ref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type)
|
||||||
{
|
{
|
||||||
if (!iwl_mvm_is_d0i3_supported(mvm))
|
if (!iwl_mvm_is_d0i3_supported(mvm))
|
||||||
|
@ -420,6 +443,10 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
|
||||||
WLAN_CIPHER_SUITE_TKIP,
|
WLAN_CIPHER_SUITE_TKIP,
|
||||||
WLAN_CIPHER_SUITE_CCMP,
|
WLAN_CIPHER_SUITE_CCMP,
|
||||||
};
|
};
|
||||||
|
#ifdef CONFIG_PM_SLEEP
|
||||||
|
bool unified = fw_has_capa(&mvm->fw->ucode_capa,
|
||||||
|
IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Tell mac80211 our characteristics */
|
/* Tell mac80211 our characteristics */
|
||||||
ieee80211_hw_set(hw, SIGNAL_DBM);
|
ieee80211_hw_set(hw, SIGNAL_DBM);
|
||||||
|
@ -544,6 +571,13 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
|
||||||
hw->wiphy->n_cipher_suites++;
|
hw->wiphy->n_cipher_suites++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fw_has_capa(&mvm->fw->ucode_capa,
|
||||||
|
IWL_UCODE_TLV_CAPA_FTM_CALIBRATED)) {
|
||||||
|
wiphy_ext_feature_set(hw->wiphy,
|
||||||
|
NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER);
|
||||||
|
hw->wiphy->pmsr_capa = &iwl_mvm_pmsr_capa;
|
||||||
|
}
|
||||||
|
|
||||||
ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS);
|
ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS);
|
||||||
hw->wiphy->features |=
|
hw->wiphy->features |=
|
||||||
NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR |
|
NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR |
|
||||||
|
@ -709,7 +743,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
|
||||||
hw->wiphy->wowlan = &mvm->wowlan;
|
hw->wiphy->wowlan = &mvm->wowlan;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mvm->fw->img[IWL_UCODE_WOWLAN].num_sec &&
|
if ((unified || mvm->fw->img[IWL_UCODE_WOWLAN].num_sec) &&
|
||||||
mvm->trans->ops->d3_suspend &&
|
mvm->trans->ops->d3_suspend &&
|
||||||
mvm->trans->ops->d3_resume &&
|
mvm->trans->ops->d3_resume &&
|
||||||
device_can_wakeup(mvm->trans->dev)) {
|
device_can_wakeup(mvm->trans->dev)) {
|
||||||
|
@ -1177,6 +1211,8 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
|
||||||
iwl_mvm_cleanup_roc_te(mvm);
|
iwl_mvm_cleanup_roc_te(mvm);
|
||||||
ieee80211_remain_on_channel_expired(mvm->hw);
|
ieee80211_remain_on_channel_expired(mvm->hw);
|
||||||
|
|
||||||
|
iwl_mvm_ftm_restart(mvm);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* cleanup all interfaces, even inactive ones, as some might have
|
* cleanup all interfaces, even inactive ones, as some might have
|
||||||
* gone down during the HW restart
|
* gone down during the HW restart
|
||||||
|
@ -1290,6 +1326,8 @@ static void iwl_mvm_restart_complete(struct iwl_mvm *mvm)
|
||||||
/* allow transport/FW low power modes */
|
/* allow transport/FW low power modes */
|
||||||
iwl_mvm_unref(mvm, IWL_MVM_REF_UCODE_DOWN);
|
iwl_mvm_unref(mvm, IWL_MVM_REF_UCODE_DOWN);
|
||||||
|
|
||||||
|
iwl_mvm_send_recovery_cmd(mvm, ERROR_RECOVERY_END_OF_RECOVERY);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we have TDLS peers, remove them. We don't know the last seqno/PN
|
* If we have TDLS peers, remove them. We don't know the last seqno/PN
|
||||||
* of packets the FW sent out, so we must reconnect.
|
* of packets the FW sent out, so we must reconnect.
|
||||||
|
@ -1653,6 +1691,9 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,
|
||||||
IEEE80211_VIF_SUPPORTS_CQM_RSSI);
|
IEEE80211_VIF_SUPPORTS_CQM_RSSI);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (vif->bss_conf.ftm_responder)
|
||||||
|
memset(&mvm->ftm_resp_stats, 0, sizeof(mvm->ftm_resp_stats));
|
||||||
|
|
||||||
iwl_mvm_vif_dbgfs_clean(mvm, vif);
|
iwl_mvm_vif_dbgfs_clean(mvm, vif);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2323,7 +2364,10 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
|
||||||
* If update fails - SF might be running in associated
|
* If update fails - SF might be running in associated
|
||||||
* mode while disassociated - which is forbidden.
|
* mode while disassociated - which is forbidden.
|
||||||
*/
|
*/
|
||||||
WARN_ONCE(iwl_mvm_sf_update(mvm, vif, false),
|
ret = iwl_mvm_sf_update(mvm, vif, false);
|
||||||
|
WARN_ONCE(ret &&
|
||||||
|
!test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED,
|
||||||
|
&mvm->status),
|
||||||
"Failed to update SF upon disassociation\n");
|
"Failed to update SF upon disassociation\n");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2544,6 +2588,8 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
|
||||||
if (iwl_mvm_phy_ctx_count(mvm) > 1)
|
if (iwl_mvm_phy_ctx_count(mvm) > 1)
|
||||||
iwl_mvm_teardown_tdls_peers(mvm);
|
iwl_mvm_teardown_tdls_peers(mvm);
|
||||||
|
|
||||||
|
iwl_mvm_ftm_restart_responder(mvm, vif);
|
||||||
|
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
|
||||||
out_quota_failed:
|
out_quota_failed:
|
||||||
|
@ -2655,6 +2701,15 @@ iwl_mvm_bss_info_changed_ap_ibss(struct iwl_mvm *mvm,
|
||||||
bss_conf->txpower);
|
bss_conf->txpower);
|
||||||
iwl_mvm_set_tx_power(mvm, vif, bss_conf->txpower);
|
iwl_mvm_set_tx_power(mvm, vif, bss_conf->txpower);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (changes & BSS_CHANGED_FTM_RESPONDER) {
|
||||||
|
int ret = iwl_mvm_ftm_start_responder(mvm, vif);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
IWL_WARN(mvm, "Failed to enable FTM responder (%d)\n",
|
||||||
|
ret);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw,
|
static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw,
|
||||||
|
@ -3117,7 +3172,10 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
|
||||||
} else if (old_state == IEEE80211_STA_AUTHORIZED &&
|
} else if (old_state == IEEE80211_STA_AUTHORIZED &&
|
||||||
new_state == IEEE80211_STA_ASSOC) {
|
new_state == IEEE80211_STA_ASSOC) {
|
||||||
/* disable beacon filtering */
|
/* disable beacon filtering */
|
||||||
WARN_ON(iwl_mvm_disable_beacon_filter(mvm, vif, 0));
|
ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0);
|
||||||
|
WARN_ON(ret &&
|
||||||
|
!test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED,
|
||||||
|
&mvm->status));
|
||||||
ret = 0;
|
ret = 0;
|
||||||
} else if (old_state == IEEE80211_STA_ASSOC &&
|
} else if (old_state == IEEE80211_STA_ASSOC &&
|
||||||
new_state == IEEE80211_STA_AUTH) {
|
new_state == IEEE80211_STA_AUTH) {
|
||||||
|
@ -3149,6 +3207,10 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
|
||||||
mvm_sta->wep_key = NULL;
|
mvm_sta->wep_key = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (unlikely(ret &&
|
||||||
|
test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED,
|
||||||
|
&mvm->status)))
|
||||||
|
ret = 0;
|
||||||
} else {
|
} else {
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
}
|
}
|
||||||
|
@ -3792,11 +3854,43 @@ static int iwl_mvm_cancel_roc(struct ieee80211_hw *hw)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct iwl_mvm_ftm_responder_iter_data {
|
||||||
|
bool responder;
|
||||||
|
struct ieee80211_chanctx_conf *ctx;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void iwl_mvm_ftm_responder_chanctx_iter(void *_data, u8 *mac,
|
||||||
|
struct ieee80211_vif *vif)
|
||||||
|
{
|
||||||
|
struct iwl_mvm_ftm_responder_iter_data *data = _data;
|
||||||
|
|
||||||
|
if (rcu_access_pointer(vif->chanctx_conf) == data->ctx &&
|
||||||
|
vif->type == NL80211_IFTYPE_AP && vif->bss_conf.ftmr_params)
|
||||||
|
data->responder = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool iwl_mvm_is_ftm_responder_chanctx(struct iwl_mvm *mvm,
|
||||||
|
struct ieee80211_chanctx_conf *ctx)
|
||||||
|
{
|
||||||
|
struct iwl_mvm_ftm_responder_iter_data data = {
|
||||||
|
.responder = false,
|
||||||
|
.ctx = ctx,
|
||||||
|
};
|
||||||
|
|
||||||
|
ieee80211_iterate_active_interfaces_atomic(mvm->hw,
|
||||||
|
IEEE80211_IFACE_ITER_NORMAL,
|
||||||
|
iwl_mvm_ftm_responder_chanctx_iter,
|
||||||
|
&data);
|
||||||
|
return data.responder;
|
||||||
|
}
|
||||||
|
|
||||||
static int __iwl_mvm_add_chanctx(struct iwl_mvm *mvm,
|
static int __iwl_mvm_add_chanctx(struct iwl_mvm *mvm,
|
||||||
struct ieee80211_chanctx_conf *ctx)
|
struct ieee80211_chanctx_conf *ctx)
|
||||||
{
|
{
|
||||||
u16 *phy_ctxt_id = (u16 *)ctx->drv_priv;
|
u16 *phy_ctxt_id = (u16 *)ctx->drv_priv;
|
||||||
struct iwl_mvm_phy_ctxt *phy_ctxt;
|
struct iwl_mvm_phy_ctxt *phy_ctxt;
|
||||||
|
bool responder = iwl_mvm_is_ftm_responder_chanctx(mvm, ctx);
|
||||||
|
struct cfg80211_chan_def *def = responder ? &ctx->def : &ctx->min_def;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
lockdep_assert_held(&mvm->mutex);
|
lockdep_assert_held(&mvm->mutex);
|
||||||
|
@ -3809,7 +3903,7 @@ static int __iwl_mvm_add_chanctx(struct iwl_mvm *mvm,
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &ctx->min_def,
|
ret = iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, def,
|
||||||
ctx->rx_chains_static,
|
ctx->rx_chains_static,
|
||||||
ctx->rx_chains_dynamic);
|
ctx->rx_chains_dynamic);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
@ -3864,6 +3958,8 @@ static void iwl_mvm_change_chanctx(struct ieee80211_hw *hw,
|
||||||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||||
u16 *phy_ctxt_id = (u16 *)ctx->drv_priv;
|
u16 *phy_ctxt_id = (u16 *)ctx->drv_priv;
|
||||||
struct iwl_mvm_phy_ctxt *phy_ctxt = &mvm->phy_ctxts[*phy_ctxt_id];
|
struct iwl_mvm_phy_ctxt *phy_ctxt = &mvm->phy_ctxts[*phy_ctxt_id];
|
||||||
|
bool responder = iwl_mvm_is_ftm_responder_chanctx(mvm, ctx);
|
||||||
|
struct cfg80211_chan_def *def = responder ? &ctx->def : &ctx->min_def;
|
||||||
|
|
||||||
if (WARN_ONCE((phy_ctxt->ref > 1) &&
|
if (WARN_ONCE((phy_ctxt->ref > 1) &&
|
||||||
(changed & ~(IEEE80211_CHANCTX_CHANGE_WIDTH |
|
(changed & ~(IEEE80211_CHANCTX_CHANGE_WIDTH |
|
||||||
|
@ -3878,17 +3974,17 @@ static void iwl_mvm_change_chanctx(struct ieee80211_hw *hw,
|
||||||
|
|
||||||
/* we are only changing the min_width, may be a noop */
|
/* we are only changing the min_width, may be a noop */
|
||||||
if (changed == IEEE80211_CHANCTX_CHANGE_MIN_WIDTH) {
|
if (changed == IEEE80211_CHANCTX_CHANGE_MIN_WIDTH) {
|
||||||
if (phy_ctxt->width == ctx->min_def.width)
|
if (phy_ctxt->width == def->width)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
|
||||||
/* we are just toggling between 20_NOHT and 20 */
|
/* we are just toggling between 20_NOHT and 20 */
|
||||||
if (phy_ctxt->width <= NL80211_CHAN_WIDTH_20 &&
|
if (phy_ctxt->width <= NL80211_CHAN_WIDTH_20 &&
|
||||||
ctx->min_def.width <= NL80211_CHAN_WIDTH_20)
|
def->width <= NL80211_CHAN_WIDTH_20)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
iwl_mvm_bt_coex_vif_change(mvm);
|
iwl_mvm_bt_coex_vif_change(mvm);
|
||||||
iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &ctx->min_def,
|
iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, def,
|
||||||
ctx->rx_chains_static,
|
ctx->rx_chains_static,
|
||||||
ctx->rx_chains_dynamic);
|
ctx->rx_chains_dynamic);
|
||||||
|
|
||||||
|
@ -4809,6 +4905,60 @@ static void iwl_mvm_sync_rx_queues(struct ieee80211_hw *hw)
|
||||||
mutex_unlock(&mvm->mutex);
|
mutex_unlock(&mvm->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
iwl_mvm_mac_get_ftm_responder_stats(struct ieee80211_hw *hw,
|
||||||
|
struct ieee80211_vif *vif,
|
||||||
|
struct cfg80211_ftm_responder_stats *stats)
|
||||||
|
{
|
||||||
|
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||||
|
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||||
|
|
||||||
|
if (vif->p2p || vif->type != NL80211_IFTYPE_AP ||
|
||||||
|
!mvmvif->ap_ibss_active || !vif->bss_conf.ftm_responder)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
mutex_lock(&mvm->mutex);
|
||||||
|
*stats = mvm->ftm_resp_stats;
|
||||||
|
mutex_unlock(&mvm->mutex);
|
||||||
|
|
||||||
|
stats->filled = BIT(NL80211_FTM_STATS_SUCCESS_NUM) |
|
||||||
|
BIT(NL80211_FTM_STATS_PARTIAL_NUM) |
|
||||||
|
BIT(NL80211_FTM_STATS_FAILED_NUM) |
|
||||||
|
BIT(NL80211_FTM_STATS_ASAP_NUM) |
|
||||||
|
BIT(NL80211_FTM_STATS_NON_ASAP_NUM) |
|
||||||
|
BIT(NL80211_FTM_STATS_TOTAL_DURATION_MSEC) |
|
||||||
|
BIT(NL80211_FTM_STATS_UNKNOWN_TRIGGERS_NUM) |
|
||||||
|
BIT(NL80211_FTM_STATS_RESCHEDULE_REQUESTS_NUM) |
|
||||||
|
BIT(NL80211_FTM_STATS_OUT_OF_WINDOW_TRIGGERS_NUM);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int iwl_mvm_start_pmsr(struct ieee80211_hw *hw,
|
||||||
|
struct ieee80211_vif *vif,
|
||||||
|
struct cfg80211_pmsr_request *request)
|
||||||
|
{
|
||||||
|
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
mutex_lock(&mvm->mutex);
|
||||||
|
ret = iwl_mvm_ftm_start(mvm, vif, request);
|
||||||
|
mutex_unlock(&mvm->mutex);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void iwl_mvm_abort_pmsr(struct ieee80211_hw *hw,
|
||||||
|
struct ieee80211_vif *vif,
|
||||||
|
struct cfg80211_pmsr_request *request)
|
||||||
|
{
|
||||||
|
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||||
|
|
||||||
|
mutex_lock(&mvm->mutex);
|
||||||
|
iwl_mvm_ftm_abort(mvm, request);
|
||||||
|
mutex_unlock(&mvm->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
static bool iwl_mvm_can_hw_csum(struct sk_buff *skb)
|
static bool iwl_mvm_can_hw_csum(struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
u8 protocol = ip_hdr(skb)->protocol;
|
u8 protocol = ip_hdr(skb)->protocol;
|
||||||
|
@ -4911,6 +5061,10 @@ const struct ieee80211_ops iwl_mvm_hw_ops = {
|
||||||
#endif
|
#endif
|
||||||
.get_survey = iwl_mvm_mac_get_survey,
|
.get_survey = iwl_mvm_mac_get_survey,
|
||||||
.sta_statistics = iwl_mvm_mac_sta_statistics,
|
.sta_statistics = iwl_mvm_mac_sta_statistics,
|
||||||
|
.get_ftm_responder_stats = iwl_mvm_mac_get_ftm_responder_stats,
|
||||||
|
.start_pmsr = iwl_mvm_start_pmsr,
|
||||||
|
.abort_pmsr = iwl_mvm_abort_pmsr,
|
||||||
|
|
||||||
.can_aggregate_in_amsdu = iwl_mvm_mac_can_aggregate,
|
.can_aggregate_in_amsdu = iwl_mvm_mac_can_aggregate,
|
||||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||||
.sta_add_debugfs = iwl_mvm_sta_add_debugfs,
|
.sta_add_debugfs = iwl_mvm_sta_add_debugfs,
|
||||||
|
|
|
@ -879,9 +879,6 @@ struct iwl_mvm {
|
||||||
|
|
||||||
bool hw_registered;
|
bool hw_registered;
|
||||||
bool calibrating;
|
bool calibrating;
|
||||||
u32 error_event_table[2];
|
|
||||||
u32 log_event_table;
|
|
||||||
u32 umac_error_event_table;
|
|
||||||
bool support_umac_log;
|
bool support_umac_log;
|
||||||
|
|
||||||
u32 ampdu_ref;
|
u32 ampdu_ref;
|
||||||
|
@ -1017,6 +1014,7 @@ struct iwl_mvm {
|
||||||
|
|
||||||
/* -1 for always, 0 for never, >0 for that many times */
|
/* -1 for always, 0 for never, >0 for that many times */
|
||||||
s8 fw_restart;
|
s8 fw_restart;
|
||||||
|
u8 *error_recovery_buf;
|
||||||
|
|
||||||
#ifdef CONFIG_IWLWIFI_LEDS
|
#ifdef CONFIG_IWLWIFI_LEDS
|
||||||
struct led_classdev led;
|
struct led_classdev led;
|
||||||
|
@ -1106,6 +1104,8 @@ struct iwl_mvm {
|
||||||
|
|
||||||
/* Indicate if device power save is allowed */
|
/* Indicate if device power save is allowed */
|
||||||
u8 ps_disabled; /* u8 instead of bool to ease debugfs_create_* usage */
|
u8 ps_disabled; /* u8 instead of bool to ease debugfs_create_* usage */
|
||||||
|
/* Indicate if 32Khz external clock is valid */
|
||||||
|
u32 ext_clock_valid;
|
||||||
unsigned int max_amsdu_len; /* used for debugfs only */
|
unsigned int max_amsdu_len; /* used for debugfs only */
|
||||||
|
|
||||||
struct ieee80211_vif __rcu *csa_vif;
|
struct ieee80211_vif __rcu *csa_vif;
|
||||||
|
@ -1150,6 +1150,14 @@ struct iwl_mvm {
|
||||||
u32 ciphers[IWL_MVM_NUM_CIPHERS];
|
u32 ciphers[IWL_MVM_NUM_CIPHERS];
|
||||||
struct ieee80211_cipher_scheme cs[IWL_UCODE_MAX_CS];
|
struct ieee80211_cipher_scheme cs[IWL_UCODE_MAX_CS];
|
||||||
|
|
||||||
|
struct cfg80211_ftm_responder_stats ftm_resp_stats;
|
||||||
|
struct {
|
||||||
|
struct cfg80211_pmsr_request *req;
|
||||||
|
struct wireless_dev *req_wdev;
|
||||||
|
struct list_head loc_list;
|
||||||
|
int responses[IWL_MVM_TOF_MAX_APS];
|
||||||
|
} ftm_initiator;
|
||||||
|
|
||||||
struct ieee80211_vif *nan_vif;
|
struct ieee80211_vif *nan_vif;
|
||||||
#define IWL_MAX_BAID 32
|
#define IWL_MAX_BAID 32
|
||||||
struct iwl_mvm_baid_data __rcu *baid_map[IWL_MAX_BAID];
|
struct iwl_mvm_baid_data __rcu *baid_map[IWL_MAX_BAID];
|
||||||
|
@ -1652,6 +1660,7 @@ void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
|
||||||
void iwl_mvm_rx_tx_cmd(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb);
|
void iwl_mvm_rx_tx_cmd(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb);
|
||||||
void iwl_mvm_mfu_assert_dump_notif(struct iwl_mvm *mvm,
|
void iwl_mvm_mfu_assert_dump_notif(struct iwl_mvm *mvm,
|
||||||
struct iwl_rx_cmd_buffer *rxb);
|
struct iwl_rx_cmd_buffer *rxb);
|
||||||
|
void iwl_mvm_send_recovery_cmd(struct iwl_mvm *mvm, u32 flags);
|
||||||
void iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb);
|
void iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb);
|
||||||
void iwl_mvm_rx_ant_coupling_notif(struct iwl_mvm *mvm,
|
void iwl_mvm_rx_ant_coupling_notif(struct iwl_mvm *mvm,
|
||||||
struct iwl_rx_cmd_buffer *rxb);
|
struct iwl_rx_cmd_buffer *rxb);
|
||||||
|
@ -1686,6 +1695,17 @@ int iwl_mvm_mac_ctxt_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||||
int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
||||||
int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm,
|
int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm,
|
||||||
struct ieee80211_vif *vif);
|
struct ieee80211_vif *vif);
|
||||||
|
int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm,
|
||||||
|
struct ieee80211_vif *vif,
|
||||||
|
struct sk_buff *beacon);
|
||||||
|
int iwl_mvm_mac_ctxt_send_beacon_cmd(struct iwl_mvm *mvm,
|
||||||
|
struct sk_buff *beacon,
|
||||||
|
void *data, int len);
|
||||||
|
u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct ieee80211_tx_info *info,
|
||||||
|
struct ieee80211_vif *vif);
|
||||||
|
void iwl_mvm_mac_ctxt_set_tim(struct iwl_mvm *mvm,
|
||||||
|
__le32 *tim_index, __le32 *tim_size,
|
||||||
|
u8 *beacon, u32 frame_size);
|
||||||
void iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm,
|
void iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm,
|
||||||
struct iwl_rx_cmd_buffer *rxb);
|
struct iwl_rx_cmd_buffer *rxb);
|
||||||
void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm,
|
void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm,
|
||||||
|
@ -2060,6 +2080,23 @@ void iwl_mvm_update_changed_regdom(struct iwl_mvm *mvm);
|
||||||
int iwl_mvm_sf_update(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
int iwl_mvm_sf_update(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||||
bool added_vif);
|
bool added_vif);
|
||||||
|
|
||||||
|
/* FTM responder */
|
||||||
|
int iwl_mvm_ftm_start_responder(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
||||||
|
void iwl_mvm_ftm_restart_responder(struct iwl_mvm *mvm,
|
||||||
|
struct ieee80211_vif *vif);
|
||||||
|
void iwl_mvm_ftm_responder_stats(struct iwl_mvm *mvm,
|
||||||
|
struct iwl_rx_cmd_buffer *rxb);
|
||||||
|
|
||||||
|
/* FTM initiator */
|
||||||
|
void iwl_mvm_ftm_restart(struct iwl_mvm *mvm);
|
||||||
|
void iwl_mvm_ftm_range_resp(struct iwl_mvm *mvm,
|
||||||
|
struct iwl_rx_cmd_buffer *rxb);
|
||||||
|
void iwl_mvm_ftm_lc_notif(struct iwl_mvm *mvm,
|
||||||
|
struct iwl_rx_cmd_buffer *rxb);
|
||||||
|
int iwl_mvm_ftm_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||||
|
struct cfg80211_pmsr_request *request);
|
||||||
|
void iwl_mvm_ftm_abort(struct iwl_mvm *mvm, struct cfg80211_pmsr_request *req);
|
||||||
|
|
||||||
/* TDLS */
|
/* TDLS */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -300,6 +300,14 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
|
||||||
RX_HANDLER_ASYNC_LOCKED),
|
RX_HANDLER_ASYNC_LOCKED),
|
||||||
RX_HANDLER(MFUART_LOAD_NOTIFICATION, iwl_mvm_rx_mfuart_notif,
|
RX_HANDLER(MFUART_LOAD_NOTIFICATION, iwl_mvm_rx_mfuart_notif,
|
||||||
RX_HANDLER_SYNC),
|
RX_HANDLER_SYNC),
|
||||||
|
RX_HANDLER_GRP(LOCATION_GROUP, TOF_RESPONDER_STATS,
|
||||||
|
iwl_mvm_ftm_responder_stats, RX_HANDLER_ASYNC_LOCKED),
|
||||||
|
|
||||||
|
RX_HANDLER_GRP(LOCATION_GROUP, TOF_RANGE_RESPONSE_NOTIF,
|
||||||
|
iwl_mvm_ftm_range_resp, RX_HANDLER_ASYNC_LOCKED),
|
||||||
|
RX_HANDLER_GRP(LOCATION_GROUP, TOF_LC_NOTIF,
|
||||||
|
iwl_mvm_ftm_lc_notif, RX_HANDLER_ASYNC_LOCKED),
|
||||||
|
|
||||||
RX_HANDLER_GRP(DEBUG_GROUP, MFU_ASSERT_DUMP_NTF,
|
RX_HANDLER_GRP(DEBUG_GROUP, MFU_ASSERT_DUMP_NTF,
|
||||||
iwl_mvm_mfu_assert_dump_notif, RX_HANDLER_SYNC),
|
iwl_mvm_mfu_assert_dump_notif, RX_HANDLER_SYNC),
|
||||||
RX_HANDLER_GRP(PROT_OFFLOAD_GROUP, STORED_BEACON_NTF,
|
RX_HANDLER_GRP(PROT_OFFLOAD_GROUP, STORED_BEACON_NTF,
|
||||||
|
@ -414,6 +422,7 @@ static const struct iwl_hcmd_names iwl_mvm_legacy_names[] = {
|
||||||
static const struct iwl_hcmd_names iwl_mvm_system_names[] = {
|
static const struct iwl_hcmd_names iwl_mvm_system_names[] = {
|
||||||
HCMD_NAME(SHARED_MEM_CFG_CMD),
|
HCMD_NAME(SHARED_MEM_CFG_CMD),
|
||||||
HCMD_NAME(INIT_EXTENDED_CFG_CMD),
|
HCMD_NAME(INIT_EXTENDED_CFG_CMD),
|
||||||
|
HCMD_NAME(FW_ERROR_RECOVERY_CMD),
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Please keep this array *SORTED* by hex value.
|
/* Please keep this array *SORTED* by hex value.
|
||||||
|
@ -592,11 +601,17 @@ static int iwl_mvm_fwrt_send_hcmd(void *ctx, struct iwl_host_cmd *host_cmd)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool iwl_mvm_d3_debug_enable(void *ctx)
|
||||||
|
{
|
||||||
|
return IWL_MVM_D3_DEBUG;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct iwl_fw_runtime_ops iwl_mvm_fwrt_ops = {
|
static const struct iwl_fw_runtime_ops iwl_mvm_fwrt_ops = {
|
||||||
.dump_start = iwl_mvm_fwrt_dump_start,
|
.dump_start = iwl_mvm_fwrt_dump_start,
|
||||||
.dump_end = iwl_mvm_fwrt_dump_end,
|
.dump_end = iwl_mvm_fwrt_dump_end,
|
||||||
.fw_running = iwl_mvm_fwrt_fw_running,
|
.fw_running = iwl_mvm_fwrt_fw_running,
|
||||||
.send_hcmd = iwl_mvm_fwrt_send_hcmd,
|
.send_hcmd = iwl_mvm_fwrt_send_hcmd,
|
||||||
|
.d3_debug_enable = iwl_mvm_d3_debug_enable,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct iwl_op_mode *
|
static struct iwl_op_mode *
|
||||||
|
@ -691,6 +706,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
||||||
INIT_LIST_HEAD(&mvm->aux_roc_te_list);
|
INIT_LIST_HEAD(&mvm->aux_roc_te_list);
|
||||||
INIT_LIST_HEAD(&mvm->async_handlers_list);
|
INIT_LIST_HEAD(&mvm->async_handlers_list);
|
||||||
spin_lock_init(&mvm->time_event_lock);
|
spin_lock_init(&mvm->time_event_lock);
|
||||||
|
INIT_LIST_HEAD(&mvm->ftm_initiator.loc_list);
|
||||||
|
|
||||||
INIT_WORK(&mvm->async_handlers_wk, iwl_mvm_async_handlers_wk);
|
INIT_WORK(&mvm->async_handlers_wk, iwl_mvm_async_handlers_wk);
|
||||||
INIT_WORK(&mvm->roc_done_wk, iwl_mvm_roc_done_wk);
|
INIT_WORK(&mvm->roc_done_wk, iwl_mvm_roc_done_wk);
|
||||||
|
@ -912,6 +928,9 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode)
|
||||||
kfree(mvm->mcast_filter_cmd);
|
kfree(mvm->mcast_filter_cmd);
|
||||||
mvm->mcast_filter_cmd = NULL;
|
mvm->mcast_filter_cmd = NULL;
|
||||||
|
|
||||||
|
kfree(mvm->error_recovery_buf);
|
||||||
|
mvm->error_recovery_buf = NULL;
|
||||||
|
|
||||||
#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_IWLWIFI_DEBUGFS)
|
#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_IWLWIFI_DEBUGFS)
|
||||||
kfree(mvm->d3_resume_sram);
|
kfree(mvm->d3_resume_sram);
|
||||||
#endif
|
#endif
|
||||||
|
@ -1106,6 +1125,12 @@ static void iwl_mvm_async_cb(struct iwl_op_mode *op_mode,
|
||||||
iwl_trans_block_txq_ptrs(mvm->trans, false);
|
iwl_trans_block_txq_ptrs(mvm->trans, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int iwl_mvm_is_static_queue(struct iwl_mvm *mvm, int queue)
|
||||||
|
{
|
||||||
|
return queue == mvm->aux_queue || queue == mvm->probe_queue ||
|
||||||
|
queue == mvm->p2p_dev_queue || queue == mvm->snif_queue;
|
||||||
|
}
|
||||||
|
|
||||||
static void iwl_mvm_queue_state_change(struct iwl_op_mode *op_mode,
|
static void iwl_mvm_queue_state_change(struct iwl_op_mode *op_mode,
|
||||||
int hw_queue, bool start)
|
int hw_queue, bool start)
|
||||||
{
|
{
|
||||||
|
@ -1132,6 +1157,15 @@ static void iwl_mvm_queue_state_change(struct iwl_op_mode *op_mode,
|
||||||
goto out;
|
goto out;
|
||||||
mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||||
|
|
||||||
|
if (iwl_mvm_is_static_queue(mvm, hw_queue)) {
|
||||||
|
if (!start)
|
||||||
|
ieee80211_stop_queues(mvm->hw);
|
||||||
|
else if (mvmsta->sta_state != IEEE80211_STA_NOTEXIST)
|
||||||
|
ieee80211_wake_queues(mvm->hw);
|
||||||
|
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
if (iwl_mvm_has_new_tx_api(mvm)) {
|
if (iwl_mvm_has_new_tx_api(mvm)) {
|
||||||
int tid = mvm->tvqm_info[hw_queue].txq_tid;
|
int tid = mvm->tvqm_info[hw_queue].txq_tid;
|
||||||
|
|
||||||
|
@ -1292,6 +1326,20 @@ void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error)
|
||||||
/* don't let the transport/FW power down */
|
/* don't let the transport/FW power down */
|
||||||
iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN);
|
iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN);
|
||||||
|
|
||||||
|
if (mvm->fw->ucode_capa.error_log_size) {
|
||||||
|
u32 src_size = mvm->fw->ucode_capa.error_log_size;
|
||||||
|
u32 src_addr = mvm->fw->ucode_capa.error_log_addr;
|
||||||
|
u8 *recover_buf = kzalloc(src_size, GFP_ATOMIC);
|
||||||
|
|
||||||
|
if (recover_buf) {
|
||||||
|
mvm->error_recovery_buf = recover_buf;
|
||||||
|
iwl_trans_read_mem_bytes(mvm->trans,
|
||||||
|
src_addr,
|
||||||
|
recover_buf,
|
||||||
|
src_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (fw_error && mvm->fw_restart > 0)
|
if (fw_error && mvm->fw_restart > 0)
|
||||||
mvm->fw_restart--;
|
mvm->fw_restart--;
|
||||||
set_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status);
|
set_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status);
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||||
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
|
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
|
||||||
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
|
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
|
||||||
* Copyright (C) 2018 Intel Corporation
|
* Copyright (C) 2018 - 2019 Intel Corporation
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of version 2 of the GNU General Public License as
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
|
@ -31,7 +31,7 @@
|
||||||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||||
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
|
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
|
||||||
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
|
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
|
||||||
* Copyright (C) 2018 Intel Corporation
|
* Copyright (C) 2018 - 2019 Intel Corporation
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -544,6 +544,9 @@ int iwl_mvm_power_update_device(struct iwl_mvm *mvm)
|
||||||
cmd.flags &=
|
cmd.flags &=
|
||||||
cpu_to_le16(~DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK);
|
cpu_to_le16(~DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK);
|
||||||
#endif
|
#endif
|
||||||
|
if (mvm->ext_clock_valid)
|
||||||
|
cmd.flags |= cpu_to_le16(DEVICE_POWER_FLAGS_32K_CLK_VALID_MSK);
|
||||||
|
|
||||||
IWL_DEBUG_POWER(mvm,
|
IWL_DEBUG_POWER(mvm,
|
||||||
"Sending device power command with flags = 0x%X\n",
|
"Sending device power command with flags = 0x%X\n",
|
||||||
cmd.flags);
|
cmd.flags);
|
||||||
|
|
|
@ -258,10 +258,7 @@ static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm,
|
||||||
struct ieee80211_sta *sta,
|
struct ieee80211_sta *sta,
|
||||||
bool csi)
|
bool csi)
|
||||||
{
|
{
|
||||||
struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
|
if (iwl_mvm_check_pn(mvm, skb, queue, sta))
|
||||||
|
|
||||||
if (!(rx_status->flag & RX_FLAG_NO_PSDU) &&
|
|
||||||
iwl_mvm_check_pn(mvm, skb, queue, sta))
|
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
else
|
else
|
||||||
ieee80211_rx_napi(mvm->hw, sta, skb, napi);
|
ieee80211_rx_napi(mvm->hw, sta, skb, napi);
|
||||||
|
@ -1077,16 +1074,16 @@ static void iwl_mvm_decode_he_phy_data(struct iwl_mvm *mvm,
|
||||||
IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE2_KNOWN |
|
IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE2_KNOWN |
|
||||||
IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE3_KNOWN |
|
IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE3_KNOWN |
|
||||||
IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE4_KNOWN);
|
IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE4_KNOWN);
|
||||||
he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d0,
|
he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d2,
|
||||||
IWL_RX_PHY_DATA2_HE_TB_EXT_SPTL_REUSE1),
|
IWL_RX_PHY_DATA2_HE_TB_EXT_SPTL_REUSE1),
|
||||||
IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE1);
|
IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE1);
|
||||||
he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d0,
|
he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d2,
|
||||||
IWL_RX_PHY_DATA2_HE_TB_EXT_SPTL_REUSE2),
|
IWL_RX_PHY_DATA2_HE_TB_EXT_SPTL_REUSE2),
|
||||||
IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE2);
|
IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE2);
|
||||||
he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d0,
|
he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d2,
|
||||||
IWL_RX_PHY_DATA2_HE_TB_EXT_SPTL_REUSE3),
|
IWL_RX_PHY_DATA2_HE_TB_EXT_SPTL_REUSE3),
|
||||||
IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE3);
|
IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE3);
|
||||||
he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d0,
|
he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d2,
|
||||||
IWL_RX_PHY_DATA2_HE_TB_EXT_SPTL_REUSE4),
|
IWL_RX_PHY_DATA2_HE_TB_EXT_SPTL_REUSE4),
|
||||||
IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE4);
|
IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE4);
|
||||||
/* fall through */
|
/* fall through */
|
||||||
|
@ -1096,7 +1093,6 @@ static void iwl_mvm_decode_he_phy_data(struct iwl_mvm *mvm,
|
||||||
case IWL_RX_PHY_INFO_TYPE_HE_TB:
|
case IWL_RX_PHY_INFO_TYPE_HE_TB:
|
||||||
/* HE common */
|
/* HE common */
|
||||||
he->data1 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_LDPC_XSYMSEG_KNOWN |
|
he->data1 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_LDPC_XSYMSEG_KNOWN |
|
||||||
IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE_KNOWN |
|
|
||||||
IEEE80211_RADIOTAP_HE_DATA1_DOPPLER_KNOWN |
|
IEEE80211_RADIOTAP_HE_DATA1_DOPPLER_KNOWN |
|
||||||
IEEE80211_RADIOTAP_HE_DATA1_BSS_COLOR_KNOWN);
|
IEEE80211_RADIOTAP_HE_DATA1_BSS_COLOR_KNOWN);
|
||||||
he->data2 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_PRE_FEC_PAD_KNOWN |
|
he->data2 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_PRE_FEC_PAD_KNOWN |
|
||||||
|
@ -1116,9 +1112,6 @@ static void iwl_mvm_decode_he_phy_data(struct iwl_mvm *mvm,
|
||||||
he->data3 |= le16_encode_bits(le32_get_bits(phy_data->d0,
|
he->data3 |= le16_encode_bits(le32_get_bits(phy_data->d0,
|
||||||
IWL_RX_PHY_DATA0_HE_LDPC_EXT_SYM),
|
IWL_RX_PHY_DATA0_HE_LDPC_EXT_SYM),
|
||||||
IEEE80211_RADIOTAP_HE_DATA3_LDPC_XSYMSEG);
|
IEEE80211_RADIOTAP_HE_DATA3_LDPC_XSYMSEG);
|
||||||
he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d0,
|
|
||||||
IWL_RX_PHY_DATA0_HE_SPATIAL_REUSE_MASK),
|
|
||||||
IEEE80211_RADIOTAP_HE_DATA4_SU_MU_SPTL_REUSE);
|
|
||||||
he->data5 |= le16_encode_bits(le32_get_bits(phy_data->d0,
|
he->data5 |= le16_encode_bits(le32_get_bits(phy_data->d0,
|
||||||
IWL_RX_PHY_DATA0_HE_PRE_FEC_PAD_MASK),
|
IWL_RX_PHY_DATA0_HE_PRE_FEC_PAD_MASK),
|
||||||
IEEE80211_RADIOTAP_HE_DATA5_PRE_FEC_PAD);
|
IEEE80211_RADIOTAP_HE_DATA5_PRE_FEC_PAD);
|
||||||
|
@ -1137,6 +1130,20 @@ static void iwl_mvm_decode_he_phy_data(struct iwl_mvm *mvm,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (phy_data->info_type) {
|
||||||
|
case IWL_RX_PHY_INFO_TYPE_HE_MU_EXT:
|
||||||
|
case IWL_RX_PHY_INFO_TYPE_HE_MU:
|
||||||
|
case IWL_RX_PHY_INFO_TYPE_HE_SU:
|
||||||
|
he->data1 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE_KNOWN);
|
||||||
|
he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d0,
|
||||||
|
IWL_RX_PHY_DATA0_HE_SPATIAL_REUSE_MASK),
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA4_SU_MU_SPTL_REUSE);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* nothing here */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
switch (phy_data->info_type) {
|
switch (phy_data->info_type) {
|
||||||
case IWL_RX_PHY_INFO_TYPE_HE_MU_EXT:
|
case IWL_RX_PHY_INFO_TYPE_HE_MU_EXT:
|
||||||
he_mu->flags1 |=
|
he_mu->flags1 |=
|
||||||
|
@ -1800,7 +1807,7 @@ void iwl_mvm_rx_monitor_ndp(struct iwl_mvm *mvm, struct napi_struct *napi,
|
||||||
rx_status->rate_idx = rate;
|
rx_status->rate_idx = rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb, queue, sta, false);
|
ieee80211_rx_napi(mvm->hw, sta, skb, napi);
|
||||||
out:
|
out:
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||||
* Copyright(c) 2018 Intel Corporation
|
* Copyright(c) 2018 - 2019 Intel Corporation
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of version 2 of the GNU General Public License as
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
|
@ -31,7 +31,7 @@
|
||||||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||||
* Copyright(c) 2018 Intel Corporation
|
* Copyright(c) 2018 - 2019 Intel Corporation
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* 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)
|
||||||
* scheduled scan before starting a normal scan.
|
* scheduled scan before starting a normal scan.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* FW supports only a single periodic scan */
|
||||||
|
if ((type == IWL_MVM_SCAN_SCHED || type == IWL_MVM_SCAN_NETDETECT) &&
|
||||||
|
mvm->scan_status & (IWL_MVM_SCAN_SCHED | IWL_MVM_SCAN_NETDETECT))
|
||||||
|
return -EBUSY;
|
||||||
|
|
||||||
if (iwl_mvm_num_scans(mvm) < mvm->max_scans)
|
if (iwl_mvm_num_scans(mvm) < mvm->max_scans)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
|
@ -750,7 +750,8 @@ static int iwl_mvm_tvqm_enable_txq(struct iwl_mvm *mvm,
|
||||||
|
|
||||||
if (tid == IWL_MAX_TID_COUNT) {
|
if (tid == IWL_MAX_TID_COUNT) {
|
||||||
tid = IWL_MGMT_TID;
|
tid = IWL_MGMT_TID;
|
||||||
size = IWL_MGMT_QUEUE_SIZE;
|
size = max_t(u32, IWL_MGMT_QUEUE_SIZE,
|
||||||
|
mvm->trans->cfg->min_txq_size);
|
||||||
}
|
}
|
||||||
queue = iwl_trans_txq_alloc(mvm->trans,
|
queue = iwl_trans_txq_alloc(mvm->trans,
|
||||||
cpu_to_le16(TX_QUEUE_CFG_ENABLE_QUEUE),
|
cpu_to_le16(TX_QUEUE_CFG_ENABLE_QUEUE),
|
||||||
|
|
|
@ -85,7 +85,7 @@ void iwl_mvm_te_clear_data(struct iwl_mvm *mvm,
|
||||||
{
|
{
|
||||||
lockdep_assert_held(&mvm->time_event_lock);
|
lockdep_assert_held(&mvm->time_event_lock);
|
||||||
|
|
||||||
if (!te_data->vif)
|
if (!te_data || !te_data->vif)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
list_del(&te_data->list);
|
list_del(&te_data->list);
|
||||||
|
|
|
@ -457,12 +457,14 @@ static void iwl_mvm_dump_umac_error_log(struct iwl_mvm *mvm)
|
||||||
{
|
{
|
||||||
struct iwl_trans *trans = mvm->trans;
|
struct iwl_trans *trans = mvm->trans;
|
||||||
struct iwl_umac_error_event_table table;
|
struct iwl_umac_error_event_table table;
|
||||||
|
u32 base = mvm->trans->umac_error_event_table;
|
||||||
|
|
||||||
if (!mvm->support_umac_log)
|
if (!mvm->support_umac_log &&
|
||||||
|
!(mvm->trans->error_event_table_tlv_status &
|
||||||
|
IWL_ERROR_EVENT_TABLE_UMAC))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
iwl_trans_read_mem_bytes(trans, mvm->umac_error_event_table, &table,
|
iwl_trans_read_mem_bytes(trans, base, &table, sizeof(table));
|
||||||
sizeof(table));
|
|
||||||
|
|
||||||
if (table.valid)
|
if (table.valid)
|
||||||
mvm->fwrt.dump.umac_err_id = table.error_id;
|
mvm->fwrt.dump.umac_err_id = table.error_id;
|
||||||
|
@ -494,7 +496,7 @@ static void iwl_mvm_dump_lmac_error_log(struct iwl_mvm *mvm, u8 lmac_num)
|
||||||
{
|
{
|
||||||
struct iwl_trans *trans = mvm->trans;
|
struct iwl_trans *trans = mvm->trans;
|
||||||
struct iwl_error_event_table table;
|
struct iwl_error_event_table table;
|
||||||
u32 val, base = mvm->error_event_table[lmac_num];
|
u32 val, base = mvm->trans->lmac_error_event_table[lmac_num];
|
||||||
|
|
||||||
if (mvm->fwrt.cur_fw_img == IWL_UCODE_INIT) {
|
if (mvm->fwrt.cur_fw_img == IWL_UCODE_INIT) {
|
||||||
if (!base)
|
if (!base)
|
||||||
|
@ -590,7 +592,7 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm)
|
||||||
|
|
||||||
iwl_mvm_dump_lmac_error_log(mvm, 0);
|
iwl_mvm_dump_lmac_error_log(mvm, 0);
|
||||||
|
|
||||||
if (mvm->error_event_table[1])
|
if (mvm->trans->lmac_error_event_table[1])
|
||||||
iwl_mvm_dump_lmac_error_log(mvm, 1);
|
iwl_mvm_dump_lmac_error_log(mvm, 1);
|
||||||
|
|
||||||
iwl_mvm_dump_umac_error_log(mvm);
|
iwl_mvm_dump_umac_error_log(mvm);
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
*
|
*
|
||||||
* GPL LICENSE SUMMARY
|
* GPL LICENSE SUMMARY
|
||||||
*
|
*
|
||||||
* Copyright(c) 2018 Intel Corporation
|
* Copyright(c) 2018 - 2019 Intel Corporation
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of version 2 of the GNU General Public License as
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
|
@ -18,7 +18,7 @@
|
||||||
*
|
*
|
||||||
* BSD LICENSE
|
* BSD LICENSE
|
||||||
*
|
*
|
||||||
* Copyright(c) 2018 Intel Corporation
|
* Copyright(c) 2018 - 2019 Intel Corporation
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* 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,
|
||||||
void *iml_img;
|
void *iml_img;
|
||||||
u32 control_flags = 0;
|
u32 control_flags = 0;
|
||||||
int ret;
|
int ret;
|
||||||
|
int cmdq_size = max_t(u32, TFD_CMD_SLOTS, trans->cfg->min_txq_size);
|
||||||
|
|
||||||
/* Allocate prph scratch */
|
/* Allocate prph scratch */
|
||||||
prph_scratch = dma_alloc_coherent(trans->dev, sizeof(*prph_scratch),
|
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,
|
||||||
ctxt_info_gen3->mcr_base_addr =
|
ctxt_info_gen3->mcr_base_addr =
|
||||||
cpu_to_le64(trans_pcie->rxq->used_bd_dma);
|
cpu_to_le64(trans_pcie->rxq->used_bd_dma);
|
||||||
ctxt_info_gen3->mtr_size =
|
ctxt_info_gen3->mtr_size =
|
||||||
cpu_to_le16(TFD_QUEUE_CB_SIZE(TFD_CMD_SLOTS));
|
cpu_to_le16(TFD_QUEUE_CB_SIZE(cmdq_size));
|
||||||
ctxt_info_gen3->mcr_size =
|
ctxt_info_gen3->mcr_size =
|
||||||
cpu_to_le16(RX_QUEUE_CB_SIZE(MQ_RX_TABLE_SIZE));
|
cpu_to_le16(RX_QUEUE_CB_SIZE(MQ_RX_TABLE_SIZE));
|
||||||
|
|
||||||
|
@ -175,8 +176,13 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans,
|
||||||
iwl_write64(trans, CSR_IML_DATA_ADDR,
|
iwl_write64(trans, CSR_IML_DATA_ADDR,
|
||||||
trans_pcie->iml_dma_addr);
|
trans_pcie->iml_dma_addr);
|
||||||
iwl_write32(trans, CSR_IML_SIZE_ADDR, trans->iml_len);
|
iwl_write32(trans, CSR_IML_SIZE_ADDR, trans->iml_len);
|
||||||
iwl_set_bit(trans, CSR_CTXT_INFO_BOOT_CTRL, CSR_AUTO_FUNC_BOOT_ENA);
|
|
||||||
iwl_set_bit(trans, CSR_GP_CNTRL, CSR_AUTO_FUNC_INIT);
|
iwl_set_bit(trans, CSR_CTXT_INFO_BOOT_CTRL,
|
||||||
|
CSR_AUTO_FUNC_BOOT_ENA);
|
||||||
|
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
|
||||||
|
iwl_write_umac_prph(trans, UREG_CPU_INIT_RUN, 1);
|
||||||
|
else
|
||||||
|
iwl_set_bit(trans, CSR_GP_CNTRL, CSR_AUTO_FUNC_INIT);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
* Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
|
* Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
|
||||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||||
* Copyright(c) 2016-2017 Intel Deutschland GmbH
|
* Copyright(c) 2016-2017 Intel Deutschland GmbH
|
||||||
* Copyright(c) 2018 Intel Corporation
|
* Copyright(c) 2018 - 2019 Intel Corporation
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of version 2 of the GNU General Public License as
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
|
@ -32,7 +32,7 @@
|
||||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
* Copyright(c) 2017 Intel Deutschland GmbH
|
* Copyright(c) 2017 Intel Deutschland GmbH
|
||||||
* Copyright(c) 2018 Intel Corporation
|
* Copyright(c) 2018 - 2019 Intel Corporation
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
|
@ -872,6 +872,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
|
||||||
{IWL_PCI_DEVICE(0xA370, 0x40A4, iwl9462_2ac_cfg_soc)},
|
{IWL_PCI_DEVICE(0xA370, 0x40A4, iwl9462_2ac_cfg_soc)},
|
||||||
{IWL_PCI_DEVICE(0xA370, 0x4234, iwl9560_2ac_cfg_soc)},
|
{IWL_PCI_DEVICE(0xA370, 0x4234, iwl9560_2ac_cfg_soc)},
|
||||||
{IWL_PCI_DEVICE(0xA370, 0x42A4, iwl9462_2ac_cfg_soc)},
|
{IWL_PCI_DEVICE(0xA370, 0x42A4, iwl9462_2ac_cfg_soc)},
|
||||||
|
{IWL_PCI_DEVICE(0x2720, 0x0030, iwl9560_2ac_cfg_qnj_jf_b0)},
|
||||||
|
|
||||||
/* 22000 Series */
|
/* 22000 Series */
|
||||||
{IWL_PCI_DEVICE(0x02F0, 0x0070, iwl22560_2ax_cfg_hr)},
|
{IWL_PCI_DEVICE(0x02F0, 0x0070, iwl22560_2ax_cfg_hr)},
|
||||||
|
@ -891,7 +892,6 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
|
||||||
{IWL_PCI_DEVICE(0x06F0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0)},
|
{IWL_PCI_DEVICE(0x06F0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0)},
|
||||||
{IWL_PCI_DEVICE(0x06F0, 0x4070, iwl22560_2ax_cfg_hr)},
|
{IWL_PCI_DEVICE(0x06F0, 0x4070, iwl22560_2ax_cfg_hr)},
|
||||||
{IWL_PCI_DEVICE(0x2720, 0x0000, iwl22560_2ax_cfg_hr)},
|
{IWL_PCI_DEVICE(0x2720, 0x0000, iwl22560_2ax_cfg_hr)},
|
||||||
{IWL_PCI_DEVICE(0x2720, 0x0030, iwl9560_2ac_160_cfg_soc)},
|
|
||||||
{IWL_PCI_DEVICE(0x2720, 0x0040, iwl22560_2ax_cfg_hr)},
|
{IWL_PCI_DEVICE(0x2720, 0x0040, iwl22560_2ax_cfg_hr)},
|
||||||
{IWL_PCI_DEVICE(0x2720, 0x0070, iwl22000_2ac_cfg_hr_cdb)},
|
{IWL_PCI_DEVICE(0x2720, 0x0070, iwl22000_2ac_cfg_hr_cdb)},
|
||||||
{IWL_PCI_DEVICE(0x2720, 0x0074, iwl22560_2ax_cfg_hr)},
|
{IWL_PCI_DEVICE(0x2720, 0x0074, iwl22560_2ax_cfg_hr)},
|
||||||
|
@ -948,6 +948,14 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
|
||||||
{IWL_PCI_DEVICE(0x1a56, 0x1653, killer1650w_2ax_cfg)},
|
{IWL_PCI_DEVICE(0x1a56, 0x1653, killer1650w_2ax_cfg)},
|
||||||
{IWL_PCI_DEVICE(0x1a56, 0x1654, killer1650x_2ax_cfg)},
|
{IWL_PCI_DEVICE(0x1a56, 0x1654, killer1650x_2ax_cfg)},
|
||||||
|
|
||||||
|
{IWL_PCI_DEVICE(0x2725, 0x0090, iwlax210_2ax_cfg_so_hr_a0)},
|
||||||
|
{IWL_PCI_DEVICE(0x7A70, 0x0090, iwlax210_2ax_cfg_so_hr_a0)},
|
||||||
|
{IWL_PCI_DEVICE(0x7A70, 0x0310, iwlax210_2ax_cfg_so_hr_a0)},
|
||||||
|
{IWL_PCI_DEVICE(0x2725, 0x0020, iwlax210_2ax_cfg_so_hr_a0)},
|
||||||
|
{IWL_PCI_DEVICE(0x2725, 0x0310, iwlax210_2ax_cfg_so_hr_a0)},
|
||||||
|
{IWL_PCI_DEVICE(0x2725, 0x0A10, iwlax210_2ax_cfg_so_hr_a0)},
|
||||||
|
{IWL_PCI_DEVICE(0x2725, 0x00B0, iwlax210_2ax_cfg_so_hr_a0)},
|
||||||
|
|
||||||
#endif /* CONFIG_IWLMVM */
|
#endif /* CONFIG_IWLMVM */
|
||||||
|
|
||||||
{0}
|
{0}
|
||||||
|
@ -999,7 +1007,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||||
|
|
||||||
if (rf_id_chp == jf_chp_id) {
|
if (rf_id_chp == jf_chp_id) {
|
||||||
if (iwl_trans->hw_rev == CSR_HW_REV_TYPE_QNJ)
|
if (iwl_trans->hw_rev == CSR_HW_REV_TYPE_QNJ)
|
||||||
cfg = &iwl22000_2ax_cfg_qnj_jf_b0;
|
cfg = &iwl9560_2ac_cfg_qnj_jf_b0;
|
||||||
else
|
else
|
||||||
cfg = &iwl22000_2ac_cfg_jf;
|
cfg = &iwl22000_2ac_cfg_jf;
|
||||||
} else if (rf_id_chp == hr_chp_id) {
|
} else if (rf_id_chp == hr_chp_id) {
|
||||||
|
|
|
@ -400,6 +400,8 @@ struct iwl_txq {
|
||||||
u32 id;
|
u32 id;
|
||||||
int low_mark;
|
int low_mark;
|
||||||
int high_mark;
|
int high_mark;
|
||||||
|
|
||||||
|
bool overflow_tx;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline dma_addr_t
|
static inline dma_addr_t
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
|
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
|
||||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||||
* Copyright(c) 2018 Intel Corporation
|
* Copyright(c) 2018 - 2019 Intel Corporation
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms of version 2 of the GNU General Public License as
|
* under the terms of version 2 of the GNU General Public License as
|
||||||
|
@ -31,7 +31,7 @@
|
||||||
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
|
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
|
||||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||||
* Copyright(c) 2018 Intel Corporation
|
* Copyright(c) 2018 - 2019 Intel Corporation
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -202,9 +202,9 @@ int iwl_pcie_rx_stop(struct iwl_trans *trans)
|
||||||
{
|
{
|
||||||
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) {
|
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) {
|
||||||
/* TODO: remove this for 22560 once fw does it */
|
/* TODO: remove this for 22560 once fw does it */
|
||||||
iwl_write_prph(trans, RFH_RXF_DMA_CFG_GEN3, 0);
|
iwl_write_umac_prph(trans, RFH_RXF_DMA_CFG_GEN3, 0);
|
||||||
return iwl_poll_prph_bit(trans, RFH_GEN_STATUS_GEN3,
|
return iwl_poll_umac_prph_bit(trans, RFH_GEN_STATUS_GEN3,
|
||||||
RXF_DMA_IDLE, RXF_DMA_IDLE, 1000);
|
RXF_DMA_IDLE, RXF_DMA_IDLE, 1000);
|
||||||
} else if (trans->cfg->mq_rx_supported) {
|
} else if (trans->cfg->mq_rx_supported) {
|
||||||
iwl_write_prph(trans, RFH_RXF_DMA_CFG, 0);
|
iwl_write_prph(trans, RFH_RXF_DMA_CFG, 0);
|
||||||
return iwl_poll_prph_bit(trans, RFH_GEN_STATUS,
|
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,
|
||||||
}
|
}
|
||||||
|
|
||||||
rxq->write_actual = round_down(rxq->write, 8);
|
rxq->write_actual = round_down(rxq->write, 8);
|
||||||
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560)
|
if (trans->cfg->device_family == IWL_DEVICE_FAMILY_22560)
|
||||||
iwl_write32(trans, HBUS_TARG_WRPTR,
|
iwl_write32(trans, HBUS_TARG_WRPTR,
|
||||||
(rxq->write_actual |
|
(rxq->write_actual |
|
||||||
((FIRST_RX_QUEUE + rxq->id) << 16)));
|
((FIRST_RX_QUEUE + rxq->id) << 16)));
|
||||||
|
@ -538,9 +538,9 @@ static void iwl_pcie_rx_allocator(struct iwl_trans *trans)
|
||||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||||
struct iwl_rb_allocator *rba = &trans_pcie->rba;
|
struct iwl_rb_allocator *rba = &trans_pcie->rba;
|
||||||
struct list_head local_empty;
|
struct list_head local_empty;
|
||||||
int pending = atomic_xchg(&rba->req_pending, 0);
|
int pending = atomic_read(&rba->req_pending);
|
||||||
|
|
||||||
IWL_DEBUG_RX(trans, "Pending allocation requests = %d\n", pending);
|
IWL_DEBUG_TPT(trans, "Pending allocation requests = %d\n", pending);
|
||||||
|
|
||||||
/* If we were scheduled - there is at least one request */
|
/* If we were scheduled - there is at least one request */
|
||||||
spin_lock(&rba->lock);
|
spin_lock(&rba->lock);
|
||||||
|
@ -593,12 +593,15 @@ static void iwl_pcie_rx_allocator(struct iwl_trans *trans)
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
atomic_dec(&rba->req_pending);
|
||||||
pending--;
|
pending--;
|
||||||
|
|
||||||
if (!pending) {
|
if (!pending) {
|
||||||
pending = atomic_xchg(&rba->req_pending, 0);
|
pending = atomic_read(&rba->req_pending);
|
||||||
IWL_DEBUG_RX(trans,
|
if (pending)
|
||||||
"Pending allocation requests = %d\n",
|
IWL_DEBUG_TPT(trans,
|
||||||
pending);
|
"Got more pending allocation requests = %d\n",
|
||||||
|
pending);
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock(&rba->lock);
|
spin_lock(&rba->lock);
|
||||||
|
@ -609,12 +612,15 @@ static void iwl_pcie_rx_allocator(struct iwl_trans *trans)
|
||||||
spin_unlock(&rba->lock);
|
spin_unlock(&rba->lock);
|
||||||
|
|
||||||
atomic_inc(&rba->req_ready);
|
atomic_inc(&rba->req_ready);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock(&rba->lock);
|
spin_lock(&rba->lock);
|
||||||
/* return unused rbds to the allocator empty list */
|
/* return unused rbds to the allocator empty list */
|
||||||
list_splice_tail(&local_empty, &rba->rbd_empty);
|
list_splice_tail(&local_empty, &rba->rbd_empty);
|
||||||
spin_unlock(&rba->lock);
|
spin_unlock(&rba->lock);
|
||||||
|
|
||||||
|
IWL_DEBUG_TPT(trans, "%s, exit.\n", __func__);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1424,6 +1430,9 @@ restart:
|
||||||
!emergency)) {
|
!emergency)) {
|
||||||
iwl_pcie_rx_move_to_allocator(rxq, rba);
|
iwl_pcie_rx_move_to_allocator(rxq, rba);
|
||||||
emergency = true;
|
emergency = true;
|
||||||
|
IWL_DEBUG_TPT(trans,
|
||||||
|
"RX path is in emergency. Pending allocations %d\n",
|
||||||
|
rb_pending_alloc);
|
||||||
}
|
}
|
||||||
|
|
||||||
IWL_DEBUG_RX(trans, "Q %d: HW = %d, SW = %d\n", rxq->id, r, i);
|
IWL_DEBUG_RX(trans, "Q %d: HW = %d, SW = %d\n", rxq->id, r, i);
|
||||||
|
@ -1453,8 +1462,12 @@ restart:
|
||||||
count++;
|
count++;
|
||||||
if (count == 8) {
|
if (count == 8) {
|
||||||
count = 0;
|
count = 0;
|
||||||
if (rb_pending_alloc < rxq->queue_size / 3)
|
if (rb_pending_alloc < rxq->queue_size / 3) {
|
||||||
|
IWL_DEBUG_TPT(trans,
|
||||||
|
"RX path exited emergency. Pending allocations %d\n",
|
||||||
|
rb_pending_alloc);
|
||||||
emergency = false;
|
emergency = false;
|
||||||
|
}
|
||||||
|
|
||||||
rxq->read = i;
|
rxq->read = i;
|
||||||
spin_unlock(&rxq->lock);
|
spin_unlock(&rxq->lock);
|
||||||
|
@ -2120,7 +2133,7 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560 &&
|
if (trans->cfg->device_family == IWL_DEVICE_FAMILY_22560 &&
|
||||||
inta_hw & MSIX_HW_INT_CAUSES_REG_IPC) {
|
inta_hw & MSIX_HW_INT_CAUSES_REG_IPC) {
|
||||||
/* Reflect IML transfer status */
|
/* Reflect IML transfer status */
|
||||||
int res = iwl_read32(trans, CSR_IML_RESP_ADDR);
|
int res = iwl_read32(trans, CSR_IML_RESP_ADDR);
|
||||||
|
@ -2139,6 +2152,17 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id)
|
||||||
isr_stats->wakeup++;
|
isr_stats->wakeup++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (inta_hw & MSIX_HW_INT_CAUSES_REG_IML) {
|
||||||
|
/* Reflect IML transfer status */
|
||||||
|
int res = iwl_read32(trans, CSR_IML_RESP_ADDR);
|
||||||
|
|
||||||
|
IWL_DEBUG_ISR(trans, "IML transfer status: %d\n", res);
|
||||||
|
if (res == IWL_IMAGE_RESP_FAIL) {
|
||||||
|
isr_stats->sw++;
|
||||||
|
iwl_pcie_irq_handle_error(trans);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Chip got too hot and stopped itself */
|
/* Chip got too hot and stopped itself */
|
||||||
if (inta_hw & MSIX_HW_INT_CAUSES_REG_CT_KILL) {
|
if (inta_hw & MSIX_HW_INT_CAUSES_REG_CT_KILL) {
|
||||||
IWL_ERR(trans, "Microcode CT kill error detected.\n");
|
IWL_ERR(trans, "Microcode CT kill error detected.\n");
|
||||||
|
|
|
@ -171,7 +171,7 @@ void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans, bool low_power)
|
||||||
}
|
}
|
||||||
|
|
||||||
iwl_pcie_ctxt_info_free_paging(trans);
|
iwl_pcie_ctxt_info_free_paging(trans);
|
||||||
if (trans->cfg->device_family == IWL_DEVICE_FAMILY_22560)
|
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560)
|
||||||
iwl_pcie_ctxt_info_gen3_free(trans);
|
iwl_pcie_ctxt_info_gen3_free(trans);
|
||||||
else
|
else
|
||||||
iwl_pcie_ctxt_info_free(trans);
|
iwl_pcie_ctxt_info_free(trans);
|
||||||
|
@ -234,6 +234,7 @@ void iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans, bool low_power)
|
||||||
static int iwl_pcie_gen2_nic_init(struct iwl_trans *trans)
|
static int iwl_pcie_gen2_nic_init(struct iwl_trans *trans)
|
||||||
{
|
{
|
||||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||||
|
int queue_size = max_t(u32, TFD_CMD_SLOTS, trans->cfg->min_txq_size);
|
||||||
|
|
||||||
/* TODO: most of the logic can be removed in A0 - but not in Z0 */
|
/* TODO: most of the logic can be removed in A0 - but not in Z0 */
|
||||||
spin_lock(&trans_pcie->irq_lock);
|
spin_lock(&trans_pcie->irq_lock);
|
||||||
|
@ -247,7 +248,7 @@ static int iwl_pcie_gen2_nic_init(struct iwl_trans *trans)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
/* Allocate or reset and init all Tx and Command queues */
|
/* Allocate or reset and init all Tx and Command queues */
|
||||||
if (iwl_pcie_gen2_tx_init(trans, trans_pcie->cmd_queue, TFD_CMD_SLOTS))
|
if (iwl_pcie_gen2_tx_init(trans, trans_pcie->cmd_queue, queue_size))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
/* enable shadow regs in HW */
|
/* enable shadow regs in HW */
|
||||||
|
@ -332,7 +333,7 @@ int iwl_trans_pcie_gen2_start_fw(struct iwl_trans *trans,
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (trans->cfg->device_family == IWL_DEVICE_FAMILY_22560)
|
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560)
|
||||||
ret = iwl_pcie_ctxt_info_gen3_init(trans, fw);
|
ret = iwl_pcie_ctxt_info_gen3_init(trans, fw);
|
||||||
else
|
else
|
||||||
ret = iwl_pcie_ctxt_info_init(trans, fw);
|
ret = iwl_pcie_ctxt_info_init(trans, fw);
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
* Copyright(c) 2007 - 2015 Intel Corporation. All rights reserved.
|
* Copyright(c) 2007 - 2015 Intel Corporation. All rights reserved.
|
||||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||||
* Copyright(c) 2018 Intel Corporation
|
* Copyright(c) 2018 - 2019 Intel Corporation
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of version 2 of the GNU General Public License as
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
|
@ -31,7 +31,7 @@
|
||||||
* Copyright(c) 2005 - 2015 Intel Corporation. All rights reserved.
|
* Copyright(c) 2005 - 2015 Intel Corporation. All rights reserved.
|
||||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||||
* Copyright(c) 2018 Intel Corporation
|
* Copyright(c) 2018 - 2019 Intel Corporation
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -896,13 +896,13 @@ void iwl_pcie_apply_destination(struct iwl_trans *trans)
|
||||||
if (!trans->num_blocks)
|
if (!trans->num_blocks)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
iwl_write_prph(trans, MON_BUFF_BASE_ADDR_VER2,
|
iwl_write_umac_prph(trans, MON_BUFF_BASE_ADDR_VER2,
|
||||||
trans->fw_mon[0].physical >>
|
trans->fw_mon[0].physical >>
|
||||||
MON_BUFF_SHIFT_VER2);
|
MON_BUFF_SHIFT_VER2);
|
||||||
iwl_write_prph(trans, MON_BUFF_END_ADDR_VER2,
|
iwl_write_umac_prph(trans, MON_BUFF_END_ADDR_VER2,
|
||||||
(trans->fw_mon[0].physical +
|
(trans->fw_mon[0].physical +
|
||||||
trans->fw_mon[0].size - 256) >>
|
trans->fw_mon[0].size - 256) >>
|
||||||
MON_BUFF_SHIFT_VER2);
|
MON_BUFF_SHIFT_VER2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1094,6 +1094,7 @@ static struct iwl_causes_list causes_list[] = {
|
||||||
{MSIX_FH_INT_CAUSES_FH_ERR, CSR_MSIX_FH_INT_MASK_AD, 0x5},
|
{MSIX_FH_INT_CAUSES_FH_ERR, CSR_MSIX_FH_INT_MASK_AD, 0x5},
|
||||||
{MSIX_HW_INT_CAUSES_REG_ALIVE, CSR_MSIX_HW_INT_MASK_AD, 0x10},
|
{MSIX_HW_INT_CAUSES_REG_ALIVE, CSR_MSIX_HW_INT_MASK_AD, 0x10},
|
||||||
{MSIX_HW_INT_CAUSES_REG_WAKEUP, CSR_MSIX_HW_INT_MASK_AD, 0x11},
|
{MSIX_HW_INT_CAUSES_REG_WAKEUP, CSR_MSIX_HW_INT_MASK_AD, 0x11},
|
||||||
|
{MSIX_HW_INT_CAUSES_REG_IML, CSR_MSIX_HW_INT_MASK_AD, 0x12},
|
||||||
{MSIX_HW_INT_CAUSES_REG_CT_KILL, CSR_MSIX_HW_INT_MASK_AD, 0x16},
|
{MSIX_HW_INT_CAUSES_REG_CT_KILL, CSR_MSIX_HW_INT_MASK_AD, 0x16},
|
||||||
{MSIX_HW_INT_CAUSES_REG_RF_KILL, CSR_MSIX_HW_INT_MASK_AD, 0x17},
|
{MSIX_HW_INT_CAUSES_REG_RF_KILL, CSR_MSIX_HW_INT_MASK_AD, 0x17},
|
||||||
{MSIX_HW_INT_CAUSES_REG_PERIODIC, CSR_MSIX_HW_INT_MASK_AD, 0x18},
|
{MSIX_HW_INT_CAUSES_REG_PERIODIC, CSR_MSIX_HW_INT_MASK_AD, 0x18},
|
||||||
|
@ -1126,7 +1127,7 @@ static void iwl_pcie_map_non_rx_causes(struct iwl_trans *trans)
|
||||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||||
int val = trans_pcie->def_irq | MSIX_NON_AUTO_CLEAR_CAUSE;
|
int val = trans_pcie->def_irq | MSIX_NON_AUTO_CLEAR_CAUSE;
|
||||||
int i, arr_size =
|
int i, arr_size =
|
||||||
(trans->cfg->device_family < IWL_DEVICE_FAMILY_22560) ?
|
(trans->cfg->device_family != IWL_DEVICE_FAMILY_22560) ?
|
||||||
ARRAY_SIZE(causes_list) : ARRAY_SIZE(causes_list_v2);
|
ARRAY_SIZE(causes_list) : ARRAY_SIZE(causes_list_v2);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1136,7 +1137,7 @@ static void iwl_pcie_map_non_rx_causes(struct iwl_trans *trans)
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < arr_size; i++) {
|
for (i = 0; i < arr_size; i++) {
|
||||||
struct iwl_causes_list *causes =
|
struct iwl_causes_list *causes =
|
||||||
(trans->cfg->device_family < IWL_DEVICE_FAMILY_22560) ?
|
(trans->cfg->device_family != IWL_DEVICE_FAMILY_22560) ?
|
||||||
causes_list : causes_list_v2;
|
causes_list : causes_list_v2;
|
||||||
|
|
||||||
iwl_write8(trans, CSR_MSIX_IVAR(causes[i].addr), val);
|
iwl_write8(trans, CSR_MSIX_IVAR(causes[i].addr), val);
|
||||||
|
@ -1182,8 +1183,8 @@ void iwl_pcie_conf_msix_hw(struct iwl_trans_pcie *trans_pcie)
|
||||||
if (!trans_pcie->msix_enabled) {
|
if (!trans_pcie->msix_enabled) {
|
||||||
if (trans->cfg->mq_rx_supported &&
|
if (trans->cfg->mq_rx_supported &&
|
||||||
test_bit(STATUS_DEVICE_ENABLED, &trans->status))
|
test_bit(STATUS_DEVICE_ENABLED, &trans->status))
|
||||||
iwl_write_prph(trans, UREG_CHICK,
|
iwl_write_umac_prph(trans, UREG_CHICK,
|
||||||
UREG_CHICK_MSI_ENABLE);
|
UREG_CHICK_MSI_ENABLE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
@ -1192,7 +1193,7 @@ void iwl_pcie_conf_msix_hw(struct iwl_trans_pcie *trans_pcie)
|
||||||
* prph.
|
* prph.
|
||||||
*/
|
*/
|
||||||
if (test_bit(STATUS_DEVICE_ENABLED, &trans->status))
|
if (test_bit(STATUS_DEVICE_ENABLED, &trans->status))
|
||||||
iwl_write_prph(trans, UREG_CHICK, UREG_CHICK_MSIX_ENABLE);
|
iwl_write_umac_prph(trans, UREG_CHICK, UREG_CHICK_MSIX_ENABLE);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Each cause from the causes list above and the RX causes is
|
* Each cause from the causes list above and the RX causes is
|
||||||
|
@ -1560,7 +1561,7 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans,
|
||||||
}
|
}
|
||||||
|
|
||||||
IWL_DEBUG_POWER(trans, "WFPM value upon resume = 0x%08X\n",
|
IWL_DEBUG_POWER(trans, "WFPM value upon resume = 0x%08X\n",
|
||||||
iwl_read_prph(trans, WFPM_GP2));
|
iwl_read_umac_prph(trans, WFPM_GP2));
|
||||||
|
|
||||||
val = iwl_read32(trans, CSR_RESET);
|
val = iwl_read32(trans, CSR_RESET);
|
||||||
if (val & CSR_RESET_REG_FLAG_NEVO_RESET)
|
if (val & CSR_RESET_REG_FLAG_NEVO_RESET)
|
||||||
|
@ -1709,15 +1710,18 @@ static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans, bool low_power)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
hpm = iwl_trans_read_prph(trans, HPM_DEBUG);
|
hpm = iwl_read_umac_prph_no_grab(trans, HPM_DEBUG);
|
||||||
if (hpm != 0xa5a5a5a0 && (hpm & PERSISTENCE_BIT)) {
|
if (hpm != 0xa5a5a5a0 && (hpm & PERSISTENCE_BIT)) {
|
||||||
if (iwl_trans_read_prph(trans, PREG_PRPH_WPROT_0) &
|
int wfpm_val = iwl_read_umac_prph_no_grab(trans,
|
||||||
PREG_WFPM_ACCESS) {
|
PREG_PRPH_WPROT_0);
|
||||||
|
|
||||||
|
if (wfpm_val & PREG_WFPM_ACCESS) {
|
||||||
IWL_ERR(trans,
|
IWL_ERR(trans,
|
||||||
"Error, can not clear persistence bit\n");
|
"Error, can not clear persistence bit\n");
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
}
|
}
|
||||||
iwl_trans_write_prph(trans, HPM_DEBUG, hpm & ~PERSISTENCE_BIT);
|
iwl_write_umac_prph_no_grab(trans, HPM_DEBUG,
|
||||||
|
hpm & ~PERSISTENCE_BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
iwl_trans_pcie_sw_reset(trans);
|
iwl_trans_pcie_sw_reset(trans);
|
||||||
|
@ -2239,6 +2243,7 @@ static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans, int txq_idx)
|
||||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||||
struct iwl_txq *txq;
|
struct iwl_txq *txq;
|
||||||
unsigned long now = jiffies;
|
unsigned long now = jiffies;
|
||||||
|
bool overflow_tx;
|
||||||
u8 wr_ptr;
|
u8 wr_ptr;
|
||||||
|
|
||||||
/* Make sure the NIC is still alive in the bus */
|
/* Make sure the NIC is still alive in the bus */
|
||||||
|
@ -2250,18 +2255,37 @@ static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans, int txq_idx)
|
||||||
|
|
||||||
IWL_DEBUG_TX_QUEUES(trans, "Emptying queue %d...\n", txq_idx);
|
IWL_DEBUG_TX_QUEUES(trans, "Emptying queue %d...\n", txq_idx);
|
||||||
txq = trans_pcie->txq[txq_idx];
|
txq = trans_pcie->txq[txq_idx];
|
||||||
|
|
||||||
|
spin_lock_bh(&txq->lock);
|
||||||
|
overflow_tx = txq->overflow_tx ||
|
||||||
|
!skb_queue_empty(&txq->overflow_q);
|
||||||
|
spin_unlock_bh(&txq->lock);
|
||||||
|
|
||||||
wr_ptr = READ_ONCE(txq->write_ptr);
|
wr_ptr = READ_ONCE(txq->write_ptr);
|
||||||
|
|
||||||
while (txq->read_ptr != READ_ONCE(txq->write_ptr) &&
|
while ((txq->read_ptr != READ_ONCE(txq->write_ptr) ||
|
||||||
|
overflow_tx) &&
|
||||||
!time_after(jiffies,
|
!time_after(jiffies,
|
||||||
now + msecs_to_jiffies(IWL_FLUSH_WAIT_MS))) {
|
now + msecs_to_jiffies(IWL_FLUSH_WAIT_MS))) {
|
||||||
u8 write_ptr = READ_ONCE(txq->write_ptr);
|
u8 write_ptr = READ_ONCE(txq->write_ptr);
|
||||||
|
|
||||||
if (WARN_ONCE(wr_ptr != write_ptr,
|
/*
|
||||||
|
* If write pointer moved during the wait, warn only
|
||||||
|
* if the TX came from op mode. In case TX came from
|
||||||
|
* trans layer (overflow TX) don't warn.
|
||||||
|
*/
|
||||||
|
if (WARN_ONCE(wr_ptr != write_ptr && !overflow_tx,
|
||||||
"WR pointer moved while flushing %d -> %d\n",
|
"WR pointer moved while flushing %d -> %d\n",
|
||||||
wr_ptr, write_ptr))
|
wr_ptr, write_ptr))
|
||||||
return -ETIMEDOUT;
|
return -ETIMEDOUT;
|
||||||
|
wr_ptr = write_ptr;
|
||||||
|
|
||||||
usleep_range(1000, 2000);
|
usleep_range(1000, 2000);
|
||||||
|
|
||||||
|
spin_lock_bh(&txq->lock);
|
||||||
|
overflow_tx = txq->overflow_tx ||
|
||||||
|
!skb_queue_empty(&txq->overflow_q);
|
||||||
|
spin_unlock_bh(&txq->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (txq->read_ptr != txq->write_ptr) {
|
if (txq->read_ptr != txq->write_ptr) {
|
||||||
|
@ -2947,7 +2971,8 @@ static u32 iwl_trans_pcie_fh_regs_dump(struct iwl_trans *trans,
|
||||||
i += sizeof(u32))
|
i += sizeof(u32))
|
||||||
*val++ = cpu_to_le32(iwl_trans_pcie_read32(trans, i));
|
*val++ = cpu_to_le32(iwl_trans_pcie_read32(trans, i));
|
||||||
else
|
else
|
||||||
for (i = FH_MEM_LOWER_BOUND_GEN2; i < FH_MEM_UPPER_BOUND_GEN2;
|
for (i = iwl_umac_prph(trans, FH_MEM_LOWER_BOUND_GEN2);
|
||||||
|
i < iwl_umac_prph(trans, FH_MEM_UPPER_BOUND_GEN2);
|
||||||
i += sizeof(u32))
|
i += sizeof(u32))
|
||||||
*val++ = cpu_to_le32(iwl_trans_pcie_read_prph(trans,
|
*val++ = cpu_to_le32(iwl_trans_pcie_read_prph(trans,
|
||||||
i));
|
i));
|
||||||
|
@ -2972,11 +2997,11 @@ iwl_trans_pci_dump_marbh_monitor(struct iwl_trans *trans,
|
||||||
if (!iwl_trans_grab_nic_access(trans, &flags))
|
if (!iwl_trans_grab_nic_access(trans, &flags))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
iwl_write_prph_no_grab(trans, MON_DMARB_RD_CTL_ADDR, 0x1);
|
iwl_write_umac_prph_no_grab(trans, MON_DMARB_RD_CTL_ADDR, 0x1);
|
||||||
for (i = 0; i < buf_size_in_dwords; i++)
|
for (i = 0; i < buf_size_in_dwords; i++)
|
||||||
buffer[i] = iwl_read_prph_no_grab(trans,
|
buffer[i] = iwl_read_umac_prph_no_grab(trans,
|
||||||
MON_DMARB_RD_DATA_ADDR);
|
MON_DMARB_RD_DATA_ADDR);
|
||||||
iwl_write_prph_no_grab(trans, MON_DMARB_RD_CTL_ADDR, 0x0);
|
iwl_write_umac_prph_no_grab(trans, MON_DMARB_RD_CTL_ADDR, 0x0);
|
||||||
|
|
||||||
iwl_trans_release_nic_access(trans, &flags);
|
iwl_trans_release_nic_access(trans, &flags);
|
||||||
|
|
||||||
|
@ -2991,9 +3016,9 @@ iwl_trans_pcie_dump_pointers(struct iwl_trans *trans,
|
||||||
|
|
||||||
/* If there was a dest TLV - use the values from there */
|
/* If there was a dest TLV - use the values from there */
|
||||||
if (trans->ini_valid) {
|
if (trans->ini_valid) {
|
||||||
base = MON_BUFF_BASE_ADDR_VER2;
|
base = iwl_umac_prph(trans, MON_BUFF_BASE_ADDR_VER2);
|
||||||
write_ptr = MON_BUFF_WRPTR_VER2;
|
write_ptr = iwl_umac_prph(trans, MON_BUFF_WRPTR_VER2);
|
||||||
wrap_cnt = MON_BUFF_CYCLE_CNT_VER2;
|
wrap_cnt = iwl_umac_prph(trans, MON_BUFF_CYCLE_CNT_VER2);
|
||||||
} else if (trans->dbg_dest_tlv) {
|
} else if (trans->dbg_dest_tlv) {
|
||||||
write_ptr = le32_to_cpu(trans->dbg_dest_tlv->write_ptr_reg);
|
write_ptr = le32_to_cpu(trans->dbg_dest_tlv->write_ptr_reg);
|
||||||
wrap_cnt = le32_to_cpu(trans->dbg_dest_tlv->wrap_count);
|
wrap_cnt = le32_to_cpu(trans->dbg_dest_tlv->wrap_count);
|
||||||
|
@ -3155,8 +3180,8 @@ static struct iwl_trans_dump_data
|
||||||
if (dump_mask & BIT(IWL_FW_ERROR_DUMP_FH_REGS)) {
|
if (dump_mask & BIT(IWL_FW_ERROR_DUMP_FH_REGS)) {
|
||||||
if (trans->cfg->gen2)
|
if (trans->cfg->gen2)
|
||||||
len += sizeof(*data) +
|
len += sizeof(*data) +
|
||||||
(FH_MEM_UPPER_BOUND_GEN2 -
|
(iwl_umac_prph(trans, FH_MEM_UPPER_BOUND_GEN2) -
|
||||||
FH_MEM_LOWER_BOUND_GEN2);
|
iwl_umac_prph(trans, FH_MEM_LOWER_BOUND_GEN2));
|
||||||
else
|
else
|
||||||
len += sizeof(*data) +
|
len += sizeof(*data) +
|
||||||
(FH_MEM_UPPER_BOUND -
|
(FH_MEM_UPPER_BOUND -
|
||||||
|
@ -3486,9 +3511,11 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
|
||||||
if (iwl_trans_grab_nic_access(trans, &flags)) {
|
if (iwl_trans_grab_nic_access(trans, &flags)) {
|
||||||
u32 hw_step;
|
u32 hw_step;
|
||||||
|
|
||||||
hw_step = iwl_read_prph_no_grab(trans, WFPM_CTRL_REG);
|
hw_step = iwl_read_umac_prph_no_grab(trans,
|
||||||
|
WFPM_CTRL_REG);
|
||||||
hw_step |= ENABLE_WFPM;
|
hw_step |= ENABLE_WFPM;
|
||||||
iwl_write_prph_no_grab(trans, WFPM_CTRL_REG, hw_step);
|
iwl_write_umac_prph_no_grab(trans, WFPM_CTRL_REG,
|
||||||
|
hw_step);
|
||||||
hw_step = iwl_read_prph_no_grab(trans, AUX_MISC_REG);
|
hw_step = iwl_read_prph_no_grab(trans, AUX_MISC_REG);
|
||||||
hw_step = (hw_step >> HW_STEP_LOCATION_BITS) & 0xF;
|
hw_step = (hw_step >> HW_STEP_LOCATION_BITS) & 0xF;
|
||||||
if (hw_step == 0x3)
|
if (hw_step == 0x3)
|
||||||
|
@ -3503,7 +3530,17 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
|
||||||
#if IS_ENABLED(CONFIG_IWLMVM)
|
#if IS_ENABLED(CONFIG_IWLMVM)
|
||||||
trans->hw_rf_id = iwl_read32(trans, CSR_HW_RF_ID);
|
trans->hw_rf_id = iwl_read32(trans, CSR_HW_RF_ID);
|
||||||
|
|
||||||
if (cfg == &iwl22560_2ax_cfg_hr) {
|
if (cfg == &iwlax210_2ax_cfg_so_hr_a0) {
|
||||||
|
if (trans->hw_rev == CSR_HW_REV_TYPE_TY) {
|
||||||
|
trans->cfg = &iwlax210_2ax_cfg_ty_gf_a0;
|
||||||
|
} else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) ==
|
||||||
|
CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_JF)) {
|
||||||
|
trans->cfg = &iwlax210_2ax_cfg_so_jf_a0;
|
||||||
|
} else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) ==
|
||||||
|
CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_GF)) {
|
||||||
|
trans->cfg = &iwlax210_2ax_cfg_so_gf_a0;
|
||||||
|
}
|
||||||
|
} else if (cfg == &iwl22560_2ax_cfg_hr) {
|
||||||
if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) ==
|
if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) ==
|
||||||
CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR)) {
|
CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR)) {
|
||||||
trans->cfg = &iwl22560_2ax_cfg_hr;
|
trans->cfg = &iwl22560_2ax_cfg_hr;
|
||||||
|
|
|
@ -995,7 +995,11 @@ static int iwl_pcie_tx_alloc(struct iwl_trans *trans)
|
||||||
txq_id++) {
|
txq_id++) {
|
||||||
bool cmd_queue = (txq_id == trans_pcie->cmd_queue);
|
bool cmd_queue = (txq_id == trans_pcie->cmd_queue);
|
||||||
|
|
||||||
slots_num = cmd_queue ? TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
|
if (cmd_queue)
|
||||||
|
slots_num = max_t(u32, TFD_CMD_SLOTS,
|
||||||
|
trans->cfg->min_txq_size);
|
||||||
|
else
|
||||||
|
slots_num = TFD_TX_CMD_SLOTS;
|
||||||
trans_pcie->txq[txq_id] = &trans_pcie->txq_memory[txq_id];
|
trans_pcie->txq[txq_id] = &trans_pcie->txq_memory[txq_id];
|
||||||
ret = iwl_pcie_txq_alloc(trans, trans_pcie->txq[txq_id],
|
ret = iwl_pcie_txq_alloc(trans, trans_pcie->txq[txq_id],
|
||||||
slots_num, cmd_queue);
|
slots_num, cmd_queue);
|
||||||
|
@ -1044,7 +1048,11 @@ int iwl_pcie_tx_init(struct iwl_trans *trans)
|
||||||
txq_id++) {
|
txq_id++) {
|
||||||
bool cmd_queue = (txq_id == trans_pcie->cmd_queue);
|
bool cmd_queue = (txq_id == trans_pcie->cmd_queue);
|
||||||
|
|
||||||
slots_num = cmd_queue ? TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
|
if (cmd_queue)
|
||||||
|
slots_num = max_t(u32, TFD_CMD_SLOTS,
|
||||||
|
trans->cfg->min_txq_size);
|
||||||
|
else
|
||||||
|
slots_num = TFD_TX_CMD_SLOTS;
|
||||||
ret = iwl_pcie_txq_init(trans, trans_pcie->txq[txq_id],
|
ret = iwl_pcie_txq_init(trans, trans_pcie->txq[txq_id],
|
||||||
slots_num, cmd_queue);
|
slots_num, cmd_queue);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
@ -1173,6 +1181,15 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
|
||||||
__skb_queue_head_init(&overflow_skbs);
|
__skb_queue_head_init(&overflow_skbs);
|
||||||
skb_queue_splice_init(&txq->overflow_q, &overflow_skbs);
|
skb_queue_splice_init(&txq->overflow_q, &overflow_skbs);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We are going to transmit from the overflow queue.
|
||||||
|
* Remember this state so that wait_for_txq_empty will know we
|
||||||
|
* are adding more packets to the TFD queue. It cannot rely on
|
||||||
|
* the state of &txq->overflow_q, as we just emptied it, but
|
||||||
|
* haven't TXed the content yet.
|
||||||
|
*/
|
||||||
|
txq->overflow_tx = true;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is tricky: we are in reclaim path which is non
|
* This is tricky: we are in reclaim path which is non
|
||||||
* re-entrant, so noone will try to take the access the
|
* re-entrant, so noone will try to take the access the
|
||||||
|
@ -1201,6 +1218,7 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
|
||||||
iwl_wake_queue(trans, txq);
|
iwl_wake_queue(trans, txq);
|
||||||
|
|
||||||
spin_lock_bh(&txq->lock);
|
spin_lock_bh(&txq->lock);
|
||||||
|
txq->overflow_tx = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (txq->read_ptr == txq->write_ptr) {
|
if (txq->read_ptr == txq->write_ptr) {
|
||||||
|
|
|
@ -2118,6 +2118,8 @@ ieee80211_he_oper_size(const u8 *he_oper_ie)
|
||||||
#define IEEE80211_SPCT_MSR_RPRT_TYPE_BASIC 0
|
#define IEEE80211_SPCT_MSR_RPRT_TYPE_BASIC 0
|
||||||
#define IEEE80211_SPCT_MSR_RPRT_TYPE_CCA 1
|
#define IEEE80211_SPCT_MSR_RPRT_TYPE_CCA 1
|
||||||
#define IEEE80211_SPCT_MSR_RPRT_TYPE_RPI 2
|
#define IEEE80211_SPCT_MSR_RPRT_TYPE_RPI 2
|
||||||
|
#define IEEE80211_SPCT_MSR_RPRT_TYPE_LCI 8
|
||||||
|
#define IEEE80211_SPCT_MSR_RPRT_TYPE_CIVIC 11
|
||||||
|
|
||||||
/* 802.11g ERP information element */
|
/* 802.11g ERP information element */
|
||||||
#define WLAN_ERP_NON_ERP_PRESENT (1<<0)
|
#define WLAN_ERP_NON_ERP_PRESENT (1<<0)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue