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:
Kalle Valo 2019-02-18 20:10:46 +02:00
commit f77ecde5f2
51 changed files with 2352 additions and 302 deletions

View file

@ -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));

View file

@ -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

View file

@ -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");
} }
} }

View file

@ -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);

View file

@ -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__ */

View file

@ -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__ */

View file

@ -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__ */

View file

@ -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;

View file

@ -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)
/** /**

View file

@ -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),
}; };
/** /**

View file

@ -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 {

View file

@ -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);

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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;
}; };
/** /**

View file

@ -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);

View file

@ -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__ */

View file

@ -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),

View file

@ -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)

View file

@ -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)

View file

@ -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);

View file

@ -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

View file

@ -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);

View file

@ -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__ */

View file

@ -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;

View file

@ -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

View file

@ -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 */

View file

@ -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;

View file

@ -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

View 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);
}

View 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++;
}

View file

@ -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);

View file

@ -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;

View file

@ -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,

View file

@ -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 */
/* /*

View file

@ -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);

View file

@ -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);

View file

@ -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();
} }

View file

@ -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;

View file

@ -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),

View file

@ -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);

View file

@ -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);

View file

@ -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;
} }

View file

@ -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) {

View file

@ -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

View file

@ -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");

View file

@ -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);

View file

@ -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;

View file

@ -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) {

View file

@ -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)