mirror of https://gitee.com/openkylin/linux.git
* BT coex improvements (Avri, Moshe)
* D3 operation bugfixes (Luca, Eliad) * Rate control improvements (Eyal) * Firmware debugging infra improvements (Golan) * Ground work for multi Rx (Johannes) * Various security fixes (Johannes) -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJWXfLYAAoJEC0Llv5uNjIBhTMP/R9/xbj7geqGHnyxP1XvONXT 3/TdrLmDTzEtxoE1GvyMsXnCEbaMi4ki7vrKPFgJ37kzaKfOeJLJytl9MimyGXgn g3iXu2wB3Cm3vC5CTY7VfG1GqrJurMb2iNDwLVgmcyUjCHjCzOL2TEAD70SeAlNx ruQtM0c/Yoi0fWGj2C6gGgdK4Zv1/V2VGwzYL9g+/ZZLE23R04zpHnsa5IFzt3aP FL5QQG2yO5pX8RUrLMzo3J3PNvllqMWNzYwwuwwK1d4ZgQ4nfv7wWetEuOkSHhYX 3X5KgBuizJkc5yL+G+mMIRvrFQaY0Qc0yStj+O2bEWIGu3hQHtqROzsPjaU1er3z npOo6JQfF42gJaM75eVAHDSmr9wm6wGBsAgu5pgU2s02PXuaSwWjiwx6m970Fv0C sveJqz1Z4azsyrHdGt1N/+sMFg2r4NbkWpAe7jHaAVApLaum7UDVpLjKVNMlgmtA wb0SG57r+lTwanKWdn1PcE70AIQYtoTubsx45XCkFTSHi5/SYwnJE6zECXfDeeby bVVDzy31pDphQ/B/jnzleRPGGj6oWHW33It/lmKNXume3L981wyGN0EMeAE8OgNr VcKJlL4UbuCKGKd381RBz1U0QT1Z/CO07PSoLpbBkF7C1TisfnGBTjU7AMgkk/r8 vAgbKwuoyx1LLxxSnFBz =GDfS -----END PGP SIGNATURE----- Merge tag 'iwlwifi-next-for-kalle-2015-12-01' of https://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next * BT coex improvements (Avri, Moshe) * D3 operation bugfixes (Luca, Eliad) * Rate control improvements (Eyal) * Firmware debugging infra improvements (Golan) * Ground work for multi Rx (Johannes) * Various security fixes (Johannes)
This commit is contained in:
commit
2abcd3d40d
|
@ -53,7 +53,7 @@ config IWLWIFI_LEDS
|
||||||
|
|
||||||
config IWLDVM
|
config IWLDVM
|
||||||
tristate "Intel Wireless WiFi DVM Firmware support"
|
tristate "Intel Wireless WiFi DVM Firmware support"
|
||||||
default IWLWIFI
|
depends on m
|
||||||
help
|
help
|
||||||
This is the driver that supports the DVM firmware. The list
|
This is the driver that supports the DVM firmware. The list
|
||||||
of the devices that use this firmware is available here:
|
of the devices that use this firmware is available here:
|
||||||
|
|
|
@ -8,7 +8,7 @@ iwlwifi-objs += iwl-eeprom-read.o iwl-eeprom-parse.o
|
||||||
iwlwifi-objs += iwl-phy-db.o iwl-nvm-parse.o
|
iwlwifi-objs += iwl-phy-db.o iwl-nvm-parse.o
|
||||||
iwlwifi-objs += pcie/drv.o pcie/rx.o pcie/tx.o pcie/trans.o
|
iwlwifi-objs += pcie/drv.o pcie/rx.o pcie/tx.o pcie/trans.o
|
||||||
iwlwifi-$(CONFIG_IWLDVM) += iwl-1000.o iwl-2000.o iwl-5000.o iwl-6000.o
|
iwlwifi-$(CONFIG_IWLDVM) += iwl-1000.o iwl-2000.o iwl-5000.o iwl-6000.o
|
||||||
iwlwifi-$(CONFIG_IWLMVM) += iwl-7000.o iwl-8000.o
|
iwlwifi-$(CONFIG_IWLMVM) += iwl-7000.o iwl-8000.o iwl-9000.o
|
||||||
iwlwifi-objs += iwl-trans.o
|
iwlwifi-objs += iwl-trans.o
|
||||||
|
|
||||||
iwlwifi-objs += $(iwlwifi-m)
|
iwlwifi-objs += $(iwlwifi-m)
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
* in the file called COPYING.
|
* in the file called COPYING.
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
*
|
*
|
||||||
* BSD LICENSE
|
* BSD LICENSE
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
* in the file called COPYING.
|
* in the file called COPYING.
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
*
|
*
|
||||||
* BSD LICENSE
|
* BSD LICENSE
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
* in the file called COPYING.
|
* in the file called COPYING.
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
*
|
*
|
||||||
* BSD LICENSE
|
* BSD LICENSE
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
* file called LICENSE.
|
* file called LICENSE.
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
*
|
*
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
* file called LICENSE.
|
* file called LICENSE.
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
*
|
*
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
@ -134,8 +134,6 @@ static int iwl_led_cmd(struct iwl_priv *priv,
|
||||||
on = IWL_LED_SOLID;
|
on = IWL_LED_SOLID;
|
||||||
}
|
}
|
||||||
|
|
||||||
IWL_DEBUG_LED(priv, "Led blink time compensation=%u\n",
|
|
||||||
priv->cfg->base_params->led_compensation);
|
|
||||||
led_cmd.on = iwl_blink_compensation(priv, on,
|
led_cmd.on = iwl_blink_compensation(priv, on,
|
||||||
priv->cfg->base_params->led_compensation);
|
priv->cfg->base_params->led_compensation);
|
||||||
led_cmd.off = iwl_blink_compensation(priv, off,
|
led_cmd.off = iwl_blink_compensation(priv, off,
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
* in the file called COPYING.
|
* in the file called COPYING.
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
*
|
*
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
|
@ -1411,13 +1411,7 @@ static void iwlagn_mac_remove_interface(struct ieee80211_hw *hw,
|
||||||
|
|
||||||
mutex_lock(&priv->mutex);
|
mutex_lock(&priv->mutex);
|
||||||
|
|
||||||
if (WARN_ON(ctx->vif != vif)) {
|
WARN_ON(ctx->vif != vif);
|
||||||
struct iwl_rxon_context *tmp;
|
|
||||||
IWL_ERR(priv, "ctx->vif = %p, vif = %p\n", ctx->vif, vif);
|
|
||||||
for_each_context(priv, tmp)
|
|
||||||
IWL_ERR(priv, "\tID = %d:\tctx = %p\tctx->vif = %p\n",
|
|
||||||
tmp->ctxid, tmp, tmp->vif);
|
|
||||||
}
|
|
||||||
ctx->vif = NULL;
|
ctx->vif = NULL;
|
||||||
|
|
||||||
iwl_teardown_interface(priv, vif, false);
|
iwl_teardown_interface(priv, vif, false);
|
||||||
|
|
|
@ -1227,7 +1227,21 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
|
||||||
trans_cfg.op_mode = op_mode;
|
trans_cfg.op_mode = op_mode;
|
||||||
trans_cfg.no_reclaim_cmds = no_reclaim_cmds;
|
trans_cfg.no_reclaim_cmds = no_reclaim_cmds;
|
||||||
trans_cfg.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds);
|
trans_cfg.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds);
|
||||||
trans_cfg.rx_buf_size_8k = iwlwifi_mod_params.amsdu_size_8K;
|
|
||||||
|
switch (iwlwifi_mod_params.amsdu_size) {
|
||||||
|
case IWL_AMSDU_4K:
|
||||||
|
trans_cfg.rx_buf_size = IWL_AMSDU_4K;
|
||||||
|
break;
|
||||||
|
case IWL_AMSDU_8K:
|
||||||
|
trans_cfg.rx_buf_size = IWL_AMSDU_8K;
|
||||||
|
break;
|
||||||
|
case IWL_AMSDU_12K:
|
||||||
|
default:
|
||||||
|
trans_cfg.rx_buf_size = IWL_AMSDU_4K;
|
||||||
|
pr_err("Unsupported amsdu_size: %d\n",
|
||||||
|
iwlwifi_mod_params.amsdu_size);
|
||||||
|
}
|
||||||
|
|
||||||
trans_cfg.cmd_q_wdg_timeout = IWL_WATCHDOG_DISABLED;
|
trans_cfg.cmd_q_wdg_timeout = IWL_WATCHDOG_DISABLED;
|
||||||
|
|
||||||
trans_cfg.command_names = iwl_dvm_cmd_strings;
|
trans_cfg.command_names = iwl_dvm_cmd_strings;
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
* file called LICENSE.
|
* file called LICENSE.
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
* file called LICENSE.
|
* file called LICENSE.
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
#ifndef __iwl_power_setting_h__
|
#ifndef __iwl_power_setting_h__
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
* in the file called COPYING.
|
* in the file called COPYING.
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
*
|
*
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
* file called LICENSE.
|
* file called LICENSE.
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
*
|
*
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
* file called LICENSE.
|
* file called LICENSE.
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
*
|
*
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
* file called LICENSE.
|
* file called LICENSE.
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
*
|
*
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
* file called LICENSE.
|
* file called LICENSE.
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
*
|
*
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
|
@ -7,6 +7,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 Intel Deutschland GmbH
|
||||||
*
|
*
|
||||||
* 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
|
||||||
|
@ -33,6 +34,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 Intel Deutschland GmbH
|
||||||
* 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
|
||||||
|
@ -69,7 +71,7 @@
|
||||||
#include "iwl-agn-hw.h"
|
#include "iwl-agn-hw.h"
|
||||||
|
|
||||||
/* Highest firmware API version supported */
|
/* Highest firmware API version supported */
|
||||||
#define IWL7260_UCODE_API_MAX 17
|
#define IWL7260_UCODE_API_MAX 19
|
||||||
|
|
||||||
/* Oldest version we won't warn about */
|
/* Oldest version we won't warn about */
|
||||||
#define IWL7260_UCODE_API_OK 13
|
#define IWL7260_UCODE_API_OK 13
|
||||||
|
@ -274,6 +276,17 @@ const struct iwl_cfg iwl3165_2ac_cfg = {
|
||||||
.dccm_len = IWL7265_DCCM_LEN,
|
.dccm_len = IWL7265_DCCM_LEN,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const struct iwl_cfg iwl3168_2ac_cfg = {
|
||||||
|
.name = "Intel(R) Dual Band Wireless AC 3168",
|
||||||
|
.fw_name_pre = IWL7265D_FW_PRE,
|
||||||
|
IWL_DEVICE_7000,
|
||||||
|
.ht_params = &iwl7000_ht_params,
|
||||||
|
.nvm_ver = IWL3165_NVM_VERSION,
|
||||||
|
.nvm_calib_ver = IWL3165_TX_POWER_VERSION,
|
||||||
|
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
|
||||||
|
.dccm_len = IWL7265_DCCM_LEN,
|
||||||
|
};
|
||||||
|
|
||||||
const struct iwl_cfg iwl7265_2ac_cfg = {
|
const struct iwl_cfg iwl7265_2ac_cfg = {
|
||||||
.name = "Intel(R) Dual Band Wireless AC 7265",
|
.name = "Intel(R) Dual Band Wireless AC 7265",
|
||||||
.fw_name_pre = IWL7265_FW_PRE,
|
.fw_name_pre = IWL7265_FW_PRE,
|
||||||
|
|
|
@ -69,7 +69,7 @@
|
||||||
#include "iwl-agn-hw.h"
|
#include "iwl-agn-hw.h"
|
||||||
|
|
||||||
/* Highest firmware API version supported */
|
/* Highest firmware API version supported */
|
||||||
#define IWL8000_UCODE_API_MAX 17
|
#define IWL8000_UCODE_API_MAX 19
|
||||||
|
|
||||||
/* Oldest version we won't warn about */
|
/* Oldest version we won't warn about */
|
||||||
#define IWL8000_UCODE_API_OK 13
|
#define IWL8000_UCODE_API_OK 13
|
||||||
|
@ -154,7 +154,6 @@ static const struct iwl_tt_params iwl8000_tt_params = {
|
||||||
.base_params = &iwl8000_base_params, \
|
.base_params = &iwl8000_base_params, \
|
||||||
.led_mode = IWL_LED_RF_STATE, \
|
.led_mode = IWL_LED_RF_STATE, \
|
||||||
.nvm_hw_section_num = NVM_HW_SECTION_NUM_FAMILY_8000, \
|
.nvm_hw_section_num = NVM_HW_SECTION_NUM_FAMILY_8000, \
|
||||||
.d0i3 = true, \
|
|
||||||
.features = NETIF_F_RXCSUM, \
|
.features = NETIF_F_RXCSUM, \
|
||||||
.non_shared_ant = ANT_A, \
|
.non_shared_ant = ANT_A, \
|
||||||
.dccm_offset = IWL8260_DCCM_OFFSET, \
|
.dccm_offset = IWL8260_DCCM_OFFSET, \
|
||||||
|
@ -187,6 +186,16 @@ const struct iwl_cfg iwl8260_2ac_cfg = {
|
||||||
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K,
|
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const struct iwl_cfg iwl8265_2ac_cfg = {
|
||||||
|
.name = "Intel(R) Dual Band Wireless AC 8265",
|
||||||
|
.fw_name_pre = IWL8000_FW_PRE,
|
||||||
|
IWL_DEVICE_8000,
|
||||||
|
.ht_params = &iwl8000_ht_params,
|
||||||
|
.nvm_ver = IWL8000_NVM_VERSION,
|
||||||
|
.nvm_calib_ver = IWL8000_TX_POWER_VERSION,
|
||||||
|
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K,
|
||||||
|
};
|
||||||
|
|
||||||
const struct iwl_cfg iwl4165_2ac_cfg = {
|
const struct iwl_cfg iwl4165_2ac_cfg = {
|
||||||
.name = "Intel(R) Dual Band Wireless AC 4165",
|
.name = "Intel(R) Dual Band Wireless AC 4165",
|
||||||
.fw_name_pre = IWL8000_FW_PRE,
|
.fw_name_pre = IWL8000_FW_PRE,
|
||||||
|
|
|
@ -0,0 +1,163 @@
|
||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* 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 Intel Deutschland GmbH
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* BSD LICENSE
|
||||||
|
*
|
||||||
|
* Copyright(c) 2015 Intel Deutschland GmbH
|
||||||
|
* 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/module.h>
|
||||||
|
#include <linux/stringify.h>
|
||||||
|
#include "iwl-config.h"
|
||||||
|
#include "iwl-agn-hw.h"
|
||||||
|
|
||||||
|
/* Highest firmware API version supported */
|
||||||
|
#define IWL9000_UCODE_API_MAX 16
|
||||||
|
|
||||||
|
/* Oldest version we won't warn about */
|
||||||
|
#define IWL9000_UCODE_API_OK 13
|
||||||
|
|
||||||
|
/* Lowest firmware API version supported */
|
||||||
|
#define IWL9000_UCODE_API_MIN 13
|
||||||
|
|
||||||
|
/* NVM versions */
|
||||||
|
#define IWL9000_NVM_VERSION 0x0a1d
|
||||||
|
#define IWL9000_TX_POWER_VERSION 0xffff /* meaningless */
|
||||||
|
|
||||||
|
/* Memory offsets and lengths */
|
||||||
|
#define IWL9000_DCCM_OFFSET 0x800000
|
||||||
|
#define IWL9000_DCCM_LEN 0x18000
|
||||||
|
#define IWL9000_DCCM2_OFFSET 0x880000
|
||||||
|
#define IWL9000_DCCM2_LEN 0x8000
|
||||||
|
#define IWL9000_SMEM_OFFSET 0x400000
|
||||||
|
#define IWL9000_SMEM_LEN 0x68000
|
||||||
|
|
||||||
|
#define IWL9000_FW_PRE "iwlwifi-9000-"
|
||||||
|
#define IWL9000_MODULE_FIRMWARE(api) \
|
||||||
|
IWL9000_FW_PRE "-" __stringify(api) ".ucode"
|
||||||
|
|
||||||
|
#define NVM_HW_SECTION_NUM_FAMILY_9000 10
|
||||||
|
|
||||||
|
static const struct iwl_base_params iwl9000_base_params = {
|
||||||
|
.eeprom_size = OTP_LOW_IMAGE_SIZE_FAMILY_9000,
|
||||||
|
.num_of_queues = IWLAGN_NUM_QUEUES,
|
||||||
|
.pll_cfg_val = 0,
|
||||||
|
.shadow_ram_support = true,
|
||||||
|
.led_compensation = 57,
|
||||||
|
.wd_timeout = IWL_LONG_WD_TIMEOUT,
|
||||||
|
.max_event_log_size = 512,
|
||||||
|
.shadow_reg_enable = true,
|
||||||
|
.pcie_l1_allowed = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct iwl_ht_params iwl9000_ht_params = {
|
||||||
|
.stbc = true,
|
||||||
|
.ldpc = true,
|
||||||
|
.ht40_bands = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ),
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct iwl_tt_params iwl9000_tt_params = {
|
||||||
|
.ct_kill_entry = 115,
|
||||||
|
.ct_kill_exit = 93,
|
||||||
|
.ct_kill_duration = 5,
|
||||||
|
.dynamic_smps_entry = 111,
|
||||||
|
.dynamic_smps_exit = 107,
|
||||||
|
.tx_protection_entry = 112,
|
||||||
|
.tx_protection_exit = 105,
|
||||||
|
.tx_backoff = {
|
||||||
|
{.temperature = 110, .backoff = 200},
|
||||||
|
{.temperature = 111, .backoff = 600},
|
||||||
|
{.temperature = 112, .backoff = 1200},
|
||||||
|
{.temperature = 113, .backoff = 2000},
|
||||||
|
{.temperature = 114, .backoff = 4000},
|
||||||
|
},
|
||||||
|
.support_ct_kill = true,
|
||||||
|
.support_dynamic_smps = true,
|
||||||
|
.support_tx_protection = true,
|
||||||
|
.support_tx_backoff = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define IWL_DEVICE_9000 \
|
||||||
|
.ucode_api_max = IWL9000_UCODE_API_MAX, \
|
||||||
|
.ucode_api_ok = IWL9000_UCODE_API_OK, \
|
||||||
|
.ucode_api_min = IWL9000_UCODE_API_MIN, \
|
||||||
|
.device_family = IWL_DEVICE_FAMILY_8000, \
|
||||||
|
.max_inst_size = IWL60_RTC_INST_SIZE, \
|
||||||
|
.max_data_size = IWL60_RTC_DATA_SIZE, \
|
||||||
|
.base_params = &iwl9000_base_params, \
|
||||||
|
.led_mode = IWL_LED_RF_STATE, \
|
||||||
|
.nvm_hw_section_num = NVM_HW_SECTION_NUM_FAMILY_9000, \
|
||||||
|
.non_shared_ant = ANT_A, \
|
||||||
|
.dccm_offset = IWL9000_DCCM_OFFSET, \
|
||||||
|
.dccm_len = IWL9000_DCCM_LEN, \
|
||||||
|
.dccm2_offset = IWL9000_DCCM2_OFFSET, \
|
||||||
|
.dccm2_len = IWL9000_DCCM2_LEN, \
|
||||||
|
.smem_offset = IWL9000_SMEM_OFFSET, \
|
||||||
|
.smem_len = IWL9000_SMEM_LEN, \
|
||||||
|
.thermal_params = &iwl9000_tt_params, \
|
||||||
|
.apmg_not_supported = true
|
||||||
|
|
||||||
|
const struct iwl_cfg iwl9260_2ac_cfg = {
|
||||||
|
.name = "Intel(R) Dual Band Wireless AC 9260",
|
||||||
|
.fw_name_pre = IWL9000_FW_PRE,
|
||||||
|
IWL_DEVICE_9000,
|
||||||
|
.ht_params = &iwl9000_ht_params,
|
||||||
|
.nvm_ver = IWL9000_NVM_VERSION,
|
||||||
|
.nvm_calib_ver = IWL9000_TX_POWER_VERSION,
|
||||||
|
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K,
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct iwl_cfg iwl5165_2ac_cfg = {
|
||||||
|
.name = "Intel(R) Dual Band Wireless AC 5165",
|
||||||
|
.fw_name_pre = IWL9000_FW_PRE,
|
||||||
|
IWL_DEVICE_9000,
|
||||||
|
.ht_params = &iwl9000_ht_params,
|
||||||
|
.nvm_ver = IWL9000_NVM_VERSION,
|
||||||
|
.nvm_calib_ver = IWL9000_TX_POWER_VERSION,
|
||||||
|
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K,
|
||||||
|
};
|
||||||
|
|
||||||
|
MODULE_FIRMWARE(IWL9000_MODULE_FIRMWARE(IWL9000_UCODE_API_OK));
|
|
@ -25,7 +25,7 @@
|
||||||
* in the file called COPYING.
|
* in the file called COPYING.
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
*
|
*
|
||||||
* BSD LICENSE
|
* BSD LICENSE
|
||||||
|
|
|
@ -254,6 +254,7 @@ struct iwl_tt_params {
|
||||||
#define OTP_LOW_IMAGE_SIZE (2 * 512 * sizeof(u16)) /* 2 KB */
|
#define OTP_LOW_IMAGE_SIZE (2 * 512 * sizeof(u16)) /* 2 KB */
|
||||||
#define OTP_LOW_IMAGE_SIZE_FAMILY_7000 (16 * 512 * sizeof(u16)) /* 16 KB */
|
#define OTP_LOW_IMAGE_SIZE_FAMILY_7000 (16 * 512 * sizeof(u16)) /* 16 KB */
|
||||||
#define OTP_LOW_IMAGE_SIZE_FAMILY_8000 (32 * 512 * sizeof(u16)) /* 32 KB */
|
#define OTP_LOW_IMAGE_SIZE_FAMILY_8000 (32 * 512 * sizeof(u16)) /* 32 KB */
|
||||||
|
#define OTP_LOW_IMAGE_SIZE_FAMILY_9000 OTP_LOW_IMAGE_SIZE_FAMILY_8000
|
||||||
|
|
||||||
struct iwl_eeprom_params {
|
struct iwl_eeprom_params {
|
||||||
const u8 regulatory_bands[7];
|
const u8 regulatory_bands[7];
|
||||||
|
@ -295,7 +296,6 @@ struct iwl_pwr_tx_backoff {
|
||||||
* @high_temp: Is this NIC is designated to be in high temperature.
|
* @high_temp: Is this NIC is designated to be in high temperature.
|
||||||
* @host_interrupt_operation_mode: device needs host interrupt operation
|
* @host_interrupt_operation_mode: device needs host interrupt operation
|
||||||
* mode set
|
* mode set
|
||||||
* @d0i3: device uses d0i3 instead of d3
|
|
||||||
* @nvm_hw_section_num: the ID of the HW NVM section
|
* @nvm_hw_section_num: the ID of the HW NVM section
|
||||||
* @features: hw features, any combination of feature_whitelist
|
* @features: hw features, any combination of feature_whitelist
|
||||||
* @pwr_tx_backoffs: translation table between power limits and backoffs
|
* @pwr_tx_backoffs: translation table between power limits and backoffs
|
||||||
|
@ -342,7 +342,6 @@ struct iwl_cfg {
|
||||||
const bool internal_wimax_coex;
|
const bool internal_wimax_coex;
|
||||||
const bool host_interrupt_operation_mode;
|
const bool host_interrupt_operation_mode;
|
||||||
bool high_temp;
|
bool high_temp;
|
||||||
bool d0i3;
|
|
||||||
u8 nvm_hw_section_num;
|
u8 nvm_hw_section_num;
|
||||||
bool lp_xtal_workaround;
|
bool lp_xtal_workaround;
|
||||||
const struct iwl_pwr_tx_backoff *pwr_tx_backoffs;
|
const struct iwl_pwr_tx_backoff *pwr_tx_backoffs;
|
||||||
|
@ -421,6 +420,7 @@ extern const struct iwl_cfg iwl3160_2ac_cfg;
|
||||||
extern const struct iwl_cfg iwl3160_2n_cfg;
|
extern const struct iwl_cfg iwl3160_2n_cfg;
|
||||||
extern const struct iwl_cfg iwl3160_n_cfg;
|
extern const struct iwl_cfg iwl3160_n_cfg;
|
||||||
extern const struct iwl_cfg iwl3165_2ac_cfg;
|
extern const struct iwl_cfg iwl3165_2ac_cfg;
|
||||||
|
extern const struct iwl_cfg iwl3168_2ac_cfg;
|
||||||
extern const struct iwl_cfg iwl7265_2ac_cfg;
|
extern const struct iwl_cfg iwl7265_2ac_cfg;
|
||||||
extern const struct iwl_cfg iwl7265_2n_cfg;
|
extern const struct iwl_cfg iwl7265_2n_cfg;
|
||||||
extern const struct iwl_cfg iwl7265_n_cfg;
|
extern const struct iwl_cfg iwl7265_n_cfg;
|
||||||
|
@ -429,9 +429,12 @@ extern const struct iwl_cfg iwl7265d_2n_cfg;
|
||||||
extern const struct iwl_cfg iwl7265d_n_cfg;
|
extern const struct iwl_cfg iwl7265d_n_cfg;
|
||||||
extern const struct iwl_cfg iwl8260_2n_cfg;
|
extern const struct iwl_cfg iwl8260_2n_cfg;
|
||||||
extern const struct iwl_cfg iwl8260_2ac_cfg;
|
extern const struct iwl_cfg iwl8260_2ac_cfg;
|
||||||
|
extern const struct iwl_cfg iwl8265_2ac_cfg;
|
||||||
extern const struct iwl_cfg iwl4165_2ac_cfg;
|
extern const struct iwl_cfg iwl4165_2ac_cfg;
|
||||||
extern const struct iwl_cfg iwl8260_2ac_sdio_cfg;
|
extern const struct iwl_cfg iwl8260_2ac_sdio_cfg;
|
||||||
extern const struct iwl_cfg iwl4165_2ac_sdio_cfg;
|
extern const struct iwl_cfg iwl4165_2ac_sdio_cfg;
|
||||||
|
extern const struct iwl_cfg iwl9260_2ac_cfg;
|
||||||
|
extern const struct iwl_cfg iwl5165_2ac_cfg;
|
||||||
#endif /* CONFIG_IWLMVM */
|
#endif /* CONFIG_IWLMVM */
|
||||||
|
|
||||||
#endif /* __IWL_CONFIG_H__ */
|
#endif /* __IWL_CONFIG_H__ */
|
||||||
|
|
|
@ -163,7 +163,6 @@ do { \
|
||||||
#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_FW_ERRORS 0x00040000
|
||||||
#define IWL_DL_LED 0x00080000
|
|
||||||
/* 0x00F00000 - 0x00100000 */
|
/* 0x00F00000 - 0x00100000 */
|
||||||
#define IWL_DL_RATE 0x00100000
|
#define IWL_DL_RATE 0x00100000
|
||||||
#define IWL_DL_CALIB 0x00200000
|
#define IWL_DL_CALIB 0x00200000
|
||||||
|
@ -189,7 +188,6 @@ do { \
|
||||||
#define IWL_DEBUG_RX(p, f, a...) IWL_DEBUG(p, IWL_DL_RX, f, ## a)
|
#define IWL_DEBUG_RX(p, f, a...) IWL_DEBUG(p, IWL_DL_RX, f, ## a)
|
||||||
#define IWL_DEBUG_TX(p, f, a...) IWL_DEBUG(p, IWL_DL_TX, f, ## a)
|
#define IWL_DEBUG_TX(p, f, a...) IWL_DEBUG(p, IWL_DL_TX, f, ## a)
|
||||||
#define IWL_DEBUG_ISR(p, f, a...) IWL_DEBUG(p, IWL_DL_ISR, f, ## a)
|
#define IWL_DEBUG_ISR(p, f, a...) IWL_DEBUG(p, IWL_DL_ISR, f, ## a)
|
||||||
#define IWL_DEBUG_LED(p, f, a...) IWL_DEBUG(p, IWL_DL_LED, f, ## a)
|
|
||||||
#define IWL_DEBUG_WEP(p, f, a...) IWL_DEBUG(p, IWL_DL_WEP, f, ## a)
|
#define IWL_DEBUG_WEP(p, f, a...) IWL_DEBUG(p, IWL_DL_WEP, f, ## a)
|
||||||
#define IWL_DEBUG_HC(p, f, a...) IWL_DEBUG(p, IWL_DL_HCMD, f, ## a)
|
#define IWL_DEBUG_HC(p, f, a...) IWL_DEBUG(p, IWL_DL_HCMD, f, ## a)
|
||||||
#define IWL_DEBUG_QUOTA(p, f, a...) IWL_DEBUG(p, IWL_DL_QUOTA, f, ## a)
|
#define IWL_DEBUG_QUOTA(p, f, a...) IWL_DEBUG(p, IWL_DL_QUOTA, f, ## a)
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
* file called LICENSE.
|
* file called LICENSE.
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
*
|
*
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
* file called LICENSE.
|
* file called LICENSE.
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
*
|
*
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
* file called LICENSE.
|
* file called LICENSE.
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
*
|
*
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
* file called LICENSE.
|
* file called LICENSE.
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
*
|
*
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
|
@ -451,7 +451,9 @@ static int iwl_set_ucode_api_flags(struct iwl_drv *drv, const u8 *data,
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (api_index >= DIV_ROUND_UP(NUM_IWL_UCODE_TLV_API, 32)) {
|
if (api_index >= DIV_ROUND_UP(NUM_IWL_UCODE_TLV_API, 32)) {
|
||||||
IWL_ERR(drv, "api_index larger than supported by driver\n");
|
IWL_ERR(drv,
|
||||||
|
"api flags index %d larger than supported by driver\n",
|
||||||
|
api_index);
|
||||||
/* don't return an error so we can load FW that has more bits */
|
/* don't return an error so we can load FW that has more bits */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -473,7 +475,9 @@ static int iwl_set_ucode_capabilities(struct iwl_drv *drv, const u8 *data,
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (api_index >= DIV_ROUND_UP(NUM_IWL_UCODE_TLV_CAPA, 32)) {
|
if (api_index >= DIV_ROUND_UP(NUM_IWL_UCODE_TLV_CAPA, 32)) {
|
||||||
IWL_ERR(drv, "api_index larger than supported by driver\n");
|
IWL_ERR(drv,
|
||||||
|
"capa flags index %d larger than supported by driver\n",
|
||||||
|
api_index);
|
||||||
/* don't return an error so we can load FW that has more bits */
|
/* don't return an error so we can load FW that has more bits */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1323,6 +1327,8 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
|
||||||
sizeof(struct iwl_fw_dbg_trigger_time_event);
|
sizeof(struct iwl_fw_dbg_trigger_time_event);
|
||||||
trigger_tlv_sz[FW_DBG_TRIGGER_BA] =
|
trigger_tlv_sz[FW_DBG_TRIGGER_BA] =
|
||||||
sizeof(struct iwl_fw_dbg_trigger_ba);
|
sizeof(struct iwl_fw_dbg_trigger_ba);
|
||||||
|
trigger_tlv_sz[FW_DBG_TRIGGER_TDLS] =
|
||||||
|
sizeof(struct iwl_fw_dbg_trigger_tdls);
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(drv->fw.dbg_trigger_tlv); i++) {
|
for (i = 0; i < ARRAY_SIZE(drv->fw.dbg_trigger_tlv); i++) {
|
||||||
if (pieces->dbg_trigger_tlv[i]) {
|
if (pieces->dbg_trigger_tlv[i]) {
|
||||||
|
@ -1539,6 +1545,7 @@ struct iwl_mod_params iwlwifi_mod_params = {
|
||||||
.bt_coex_active = true,
|
.bt_coex_active = true,
|
||||||
.power_level = IWL_POWER_INDEX_1,
|
.power_level = IWL_POWER_INDEX_1,
|
||||||
.d0i3_disable = true,
|
.d0i3_disable = true,
|
||||||
|
.d0i3_entry_delay = 1000,
|
||||||
#ifndef CONFIG_IWLWIFI_UAPSD
|
#ifndef CONFIG_IWLWIFI_UAPSD
|
||||||
.uapsd_disable = true,
|
.uapsd_disable = true,
|
||||||
#endif /* CONFIG_IWLWIFI_UAPSD */
|
#endif /* CONFIG_IWLWIFI_UAPSD */
|
||||||
|
@ -1637,9 +1644,9 @@ MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])");
|
||||||
module_param_named(11n_disable, iwlwifi_mod_params.disable_11n, uint, S_IRUGO);
|
module_param_named(11n_disable, iwlwifi_mod_params.disable_11n, uint, S_IRUGO);
|
||||||
MODULE_PARM_DESC(11n_disable,
|
MODULE_PARM_DESC(11n_disable,
|
||||||
"disable 11n functionality, bitmap: 1: full, 2: disable agg TX, 4: disable agg RX, 8 enable agg TX");
|
"disable 11n functionality, bitmap: 1: full, 2: disable agg TX, 4: disable agg RX, 8 enable agg TX");
|
||||||
module_param_named(amsdu_size_8K, iwlwifi_mod_params.amsdu_size_8K,
|
module_param_named(amsdu_size, iwlwifi_mod_params.amsdu_size,
|
||||||
int, S_IRUGO);
|
int, S_IRUGO);
|
||||||
MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size (default 0)");
|
MODULE_PARM_DESC(amsdu_size, "amsdu size 0:4K 1:8K 2:12K (default 0)");
|
||||||
module_param_named(fw_restart, iwlwifi_mod_params.restart_fw, bool, S_IRUGO);
|
module_param_named(fw_restart, iwlwifi_mod_params.restart_fw, bool, S_IRUGO);
|
||||||
MODULE_PARM_DESC(fw_restart, "restart firmware in case of error (default true)");
|
MODULE_PARM_DESC(fw_restart, "restart firmware in case of error (default true)");
|
||||||
|
|
||||||
|
@ -1704,3 +1711,7 @@ MODULE_PARM_DESC(power_level,
|
||||||
module_param_named(fw_monitor, iwlwifi_mod_params.fw_monitor, bool, S_IRUGO);
|
module_param_named(fw_monitor, iwlwifi_mod_params.fw_monitor, bool, S_IRUGO);
|
||||||
MODULE_PARM_DESC(fw_monitor,
|
MODULE_PARM_DESC(fw_monitor,
|
||||||
"firmware monitor - to debug FW (default: false - needs lots of memory)");
|
"firmware monitor - to debug FW (default: false - needs lots of memory)");
|
||||||
|
|
||||||
|
module_param_named(d0i3_timeout, iwlwifi_mod_params.d0i3_entry_delay,
|
||||||
|
uint, S_IRUGO);
|
||||||
|
MODULE_PARM_DESC(d0i3_timeout, "Timeout to D0i3 entry when idle (ms)");
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
* in the file called COPYING.
|
* in the file called COPYING.
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
*
|
*
|
||||||
* BSD LICENSE
|
* BSD LICENSE
|
||||||
|
@ -766,7 +766,7 @@ void iwl_init_ht_hw_capab(const struct iwl_cfg *cfg,
|
||||||
if (cfg->ht_params->ldpc)
|
if (cfg->ht_params->ldpc)
|
||||||
ht_info->cap |= IEEE80211_HT_CAP_LDPC_CODING;
|
ht_info->cap |= IEEE80211_HT_CAP_LDPC_CODING;
|
||||||
|
|
||||||
if (iwlwifi_mod_params.amsdu_size_8K)
|
if (iwlwifi_mod_params.amsdu_size >= IWL_AMSDU_8K)
|
||||||
ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU;
|
ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU;
|
||||||
|
|
||||||
ht_info->ampdu_factor = cfg->max_ht_ampdu_exponent;
|
ht_info->ampdu_factor = cfg->max_ht_ampdu_exponent;
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
* in the file called COPYING.
|
* in the file called COPYING.
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
*
|
*
|
||||||
* BSD LICENSE
|
* BSD LICENSE
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
* in the file called COPYING.
|
* in the file called COPYING.
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
*
|
*
|
||||||
* BSD LICENSE
|
* BSD LICENSE
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
* in the file called COPYING.
|
* in the file called COPYING.
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
*
|
*
|
||||||
* BSD LICENSE
|
* BSD LICENSE
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
* in the file called COPYING.
|
* in the file called COPYING.
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
*
|
*
|
||||||
* BSD LICENSE
|
* BSD LICENSE
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
* in the file called COPYING.
|
* in the file called COPYING.
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
*
|
*
|
||||||
* BSD LICENSE
|
* BSD LICENSE
|
||||||
|
@ -288,6 +288,9 @@ iwl_fw_error_next_data(struct iwl_fw_error_dump_data *data)
|
||||||
* @FW_DBG_TRIGGER_TIME_EVENT: trigger log collection upon time events related
|
* @FW_DBG_TRIGGER_TIME_EVENT: trigger log collection upon time events related
|
||||||
* events.
|
* events.
|
||||||
* @FW_DBG_TRIGGER_BA: trigger log collection upon BlockAck related events.
|
* @FW_DBG_TRIGGER_BA: trigger log collection upon BlockAck related events.
|
||||||
|
* @FW_DBG_TX_LATENCY: trigger log collection when the tx latency goes above a
|
||||||
|
* threshold.
|
||||||
|
* @FW_DBG_TDLS: trigger log collection upon TDLS related events.
|
||||||
*/
|
*/
|
||||||
enum iwl_fw_dbg_trigger {
|
enum iwl_fw_dbg_trigger {
|
||||||
FW_DBG_TRIGGER_INVALID = 0,
|
FW_DBG_TRIGGER_INVALID = 0,
|
||||||
|
@ -302,6 +305,8 @@ enum iwl_fw_dbg_trigger {
|
||||||
FW_DBG_TRIGGER_TXQ_TIMERS,
|
FW_DBG_TRIGGER_TXQ_TIMERS,
|
||||||
FW_DBG_TRIGGER_TIME_EVENT,
|
FW_DBG_TRIGGER_TIME_EVENT,
|
||||||
FW_DBG_TRIGGER_BA,
|
FW_DBG_TRIGGER_BA,
|
||||||
|
FW_DBG_TRIGGER_TX_LATENCY,
|
||||||
|
FW_DBG_TRIGGER_TDLS,
|
||||||
|
|
||||||
/* must be last */
|
/* must be last */
|
||||||
FW_DBG_TRIGGER_MAX,
|
FW_DBG_TRIGGER_MAX,
|
||||||
|
|
|
@ -308,6 +308,7 @@ typedef unsigned int __bitwise__ iwl_ucode_tlv_capa_t;
|
||||||
* @IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT: supports gscan
|
* @IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT: supports gscan
|
||||||
* @IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE: extended DTS measurement
|
* @IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE: extended DTS measurement
|
||||||
* @IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS: supports short PM timeouts
|
* @IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS: supports short PM timeouts
|
||||||
|
* @IWL_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT: supports bt-coex Multi-priority LUT
|
||||||
*
|
*
|
||||||
* @NUM_IWL_UCODE_TLV_CAPA: number of bits used
|
* @NUM_IWL_UCODE_TLV_CAPA: number of bits used
|
||||||
*/
|
*/
|
||||||
|
@ -334,6 +335,7 @@ enum iwl_ucode_tlv_capa {
|
||||||
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,
|
||||||
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,
|
||||||
|
|
||||||
NUM_IWL_UCODE_TLV_CAPA
|
NUM_IWL_UCODE_TLV_CAPA
|
||||||
#ifdef __CHECKER__
|
#ifdef __CHECKER__
|
||||||
|
@ -722,6 +724,19 @@ struct iwl_fw_dbg_trigger_ba {
|
||||||
__le16 frame_timeout;
|
__le16 frame_timeout;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct iwl_fw_dbg_trigger_tdls - configures trigger for TDLS events.
|
||||||
|
* @action_bitmap: the TDLS action to trigger the collection upon
|
||||||
|
* @peer_mode: trigger on specific peer or all
|
||||||
|
* @peer: the TDLS peer to trigger the collection on
|
||||||
|
*/
|
||||||
|
struct iwl_fw_dbg_trigger_tdls {
|
||||||
|
u8 action_bitmap;
|
||||||
|
u8 peer_mode;
|
||||||
|
u8 peer[ETH_ALEN];
|
||||||
|
u8 reserved[4];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct iwl_fw_dbg_conf_tlv - a TLV that describes a debug configuration.
|
* struct iwl_fw_dbg_conf_tlv - a TLV that describes a debug configuration.
|
||||||
* @id: conf id
|
* @id: conf id
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
* in the file called COPYING.
|
* in the file called COPYING.
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
*
|
*
|
||||||
* BSD LICENSE
|
* BSD LICENSE
|
||||||
|
@ -305,18 +305,4 @@ iwl_fw_dbg_conf_usniffer(const struct iwl_fw *fw, u8 id)
|
||||||
return conf_tlv->usniffer;
|
return conf_tlv->usniffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define iwl_fw_dbg_trigger_enabled(fw, id) ({ \
|
|
||||||
void *__dbg_trigger = (fw)->dbg_trigger_tlv[(id)]; \
|
|
||||||
unlikely(__dbg_trigger); \
|
|
||||||
})
|
|
||||||
|
|
||||||
static inline struct iwl_fw_dbg_trigger_tlv*
|
|
||||||
iwl_fw_dbg_get_trigger(const struct iwl_fw *fw, u8 id)
|
|
||||||
{
|
|
||||||
if (WARN_ON(id >= ARRAY_SIZE(fw->dbg_trigger_tlv)))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return fw->dbg_trigger_tlv[id];
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* __iwl_fw_h__ */
|
#endif /* __iwl_fw_h__ */
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
*
|
*
|
||||||
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
|
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
|
||||||
|
* Copyright(c) 2015 Intel Deutschland GmbH
|
||||||
*
|
*
|
||||||
* Portions of this file are derived from the ipw3945 project.
|
* Portions of this file are derived from the ipw3945 project.
|
||||||
*
|
*
|
||||||
|
@ -117,18 +118,20 @@ int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask,
|
||||||
}
|
}
|
||||||
IWL_EXPORT_SYMBOL(iwl_poll_direct_bit);
|
IWL_EXPORT_SYMBOL(iwl_poll_direct_bit);
|
||||||
|
|
||||||
u32 __iwl_read_prph(struct iwl_trans *trans, u32 ofs)
|
u32 iwl_read_prph_no_grab(struct iwl_trans *trans, u32 ofs)
|
||||||
{
|
{
|
||||||
u32 val = iwl_trans_read_prph(trans, ofs);
|
u32 val = iwl_trans_read_prph(trans, ofs);
|
||||||
trace_iwlwifi_dev_ioread_prph32(trans->dev, ofs, val);
|
trace_iwlwifi_dev_ioread_prph32(trans->dev, ofs, val);
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
IWL_EXPORT_SYMBOL(iwl_read_prph_no_grab);
|
||||||
|
|
||||||
void __iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val)
|
void iwl_write_prph_no_grab(struct iwl_trans *trans, u32 ofs, u32 val)
|
||||||
{
|
{
|
||||||
trace_iwlwifi_dev_iowrite_prph32(trans->dev, ofs, val);
|
trace_iwlwifi_dev_iowrite_prph32(trans->dev, ofs, val);
|
||||||
iwl_trans_write_prph(trans, ofs, val);
|
iwl_trans_write_prph(trans, ofs, val);
|
||||||
}
|
}
|
||||||
|
IWL_EXPORT_SYMBOL(iwl_write_prph_no_grab);
|
||||||
|
|
||||||
u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs)
|
u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs)
|
||||||
{
|
{
|
||||||
|
@ -136,7 +139,7 @@ u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs)
|
||||||
u32 val = 0x5a5a5a5a;
|
u32 val = 0x5a5a5a5a;
|
||||||
|
|
||||||
if (iwl_trans_grab_nic_access(trans, false, &flags)) {
|
if (iwl_trans_grab_nic_access(trans, false, &flags)) {
|
||||||
val = __iwl_read_prph(trans, ofs);
|
val = iwl_read_prph_no_grab(trans, ofs);
|
||||||
iwl_trans_release_nic_access(trans, &flags);
|
iwl_trans_release_nic_access(trans, &flags);
|
||||||
}
|
}
|
||||||
return val;
|
return val;
|
||||||
|
@ -148,7 +151,7 @@ void iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val)
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
if (iwl_trans_grab_nic_access(trans, false, &flags)) {
|
if (iwl_trans_grab_nic_access(trans, false, &flags)) {
|
||||||
__iwl_write_prph(trans, ofs, val);
|
iwl_write_prph_no_grab(trans, ofs, val);
|
||||||
iwl_trans_release_nic_access(trans, &flags);
|
iwl_trans_release_nic_access(trans, &flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -174,8 +177,9 @@ void iwl_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask)
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
if (iwl_trans_grab_nic_access(trans, false, &flags)) {
|
if (iwl_trans_grab_nic_access(trans, false, &flags)) {
|
||||||
__iwl_write_prph(trans, ofs,
|
iwl_write_prph_no_grab(trans, ofs,
|
||||||
__iwl_read_prph(trans, ofs) | mask);
|
iwl_read_prph_no_grab(trans, ofs) |
|
||||||
|
mask);
|
||||||
iwl_trans_release_nic_access(trans, &flags);
|
iwl_trans_release_nic_access(trans, &flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -187,8 +191,9 @@ void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs,
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
if (iwl_trans_grab_nic_access(trans, false, &flags)) {
|
if (iwl_trans_grab_nic_access(trans, false, &flags)) {
|
||||||
__iwl_write_prph(trans, ofs,
|
iwl_write_prph_no_grab(trans, ofs,
|
||||||
(__iwl_read_prph(trans, ofs) & mask) | bits);
|
(iwl_read_prph_no_grab(trans, ofs) &
|
||||||
|
mask) | bits);
|
||||||
iwl_trans_release_nic_access(trans, &flags);
|
iwl_trans_release_nic_access(trans, &flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -200,8 +205,8 @@ void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask)
|
||||||
u32 val;
|
u32 val;
|
||||||
|
|
||||||
if (iwl_trans_grab_nic_access(trans, false, &flags)) {
|
if (iwl_trans_grab_nic_access(trans, false, &flags)) {
|
||||||
val = __iwl_read_prph(trans, ofs);
|
val = iwl_read_prph_no_grab(trans, ofs);
|
||||||
__iwl_write_prph(trans, ofs, (val & ~mask));
|
iwl_write_prph_no_grab(trans, ofs, (val & ~mask));
|
||||||
iwl_trans_release_nic_access(trans, &flags);
|
iwl_trans_release_nic_access(trans, &flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
* file called LICENSE.
|
* file called LICENSE.
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
*
|
*
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
@ -55,9 +55,9 @@ u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg);
|
||||||
void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value);
|
void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value);
|
||||||
|
|
||||||
|
|
||||||
u32 __iwl_read_prph(struct iwl_trans *trans, u32 ofs);
|
u32 iwl_read_prph_no_grab(struct iwl_trans *trans, u32 ofs);
|
||||||
u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs);
|
u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs);
|
||||||
void __iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val);
|
void iwl_write_prph_no_grab(struct iwl_trans *trans, u32 ofs, u32 val);
|
||||||
void iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val);
|
void iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val);
|
||||||
int iwl_poll_prph_bit(struct iwl_trans *trans, u32 addr,
|
int iwl_poll_prph_bit(struct iwl_trans *trans, u32 addr,
|
||||||
u32 bits, u32 mask, int timeout);
|
u32 bits, u32 mask, int timeout);
|
||||||
|
|
|
@ -86,6 +86,12 @@ enum iwl_disable_11n {
|
||||||
IWL_ENABLE_HT_TXAGG = BIT(3),
|
IWL_ENABLE_HT_TXAGG = BIT(3),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum iwl_amsdu_size {
|
||||||
|
IWL_AMSDU_4K = 0,
|
||||||
|
IWL_AMSDU_8K = 1,
|
||||||
|
IWL_AMSDU_12K = 2,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct iwl_mod_params
|
* struct iwl_mod_params
|
||||||
*
|
*
|
||||||
|
@ -94,7 +100,7 @@ enum iwl_disable_11n {
|
||||||
* @sw_crypto: using hardware encryption, default = 0
|
* @sw_crypto: using hardware encryption, default = 0
|
||||||
* @disable_11n: disable 11n capabilities, default = 0,
|
* @disable_11n: disable 11n capabilities, default = 0,
|
||||||
* use IWL_[DIS,EN]ABLE_HT_* constants
|
* use IWL_[DIS,EN]ABLE_HT_* constants
|
||||||
* @amsdu_size_8K: enable 8K amsdu size, default = 0
|
* @amsdu_size: enable 8K amsdu size, default = 4K. enum iwl_amsdu_size.
|
||||||
* @restart_fw: restart firmware, default = 1
|
* @restart_fw: restart firmware, default = 1
|
||||||
* @bt_coex_active: enable bt coex, default = true
|
* @bt_coex_active: enable bt coex, default = true
|
||||||
* @led_mode: system default, default = 0
|
* @led_mode: system default, default = 0
|
||||||
|
@ -103,13 +109,15 @@ enum iwl_disable_11n {
|
||||||
* @debug_level: levels are IWL_DL_*
|
* @debug_level: levels are IWL_DL_*
|
||||||
* @ant_coupling: antenna coupling in dB, default = 0
|
* @ant_coupling: antenna coupling in dB, default = 0
|
||||||
* @d0i3_disable: disable d0i3, default = 1,
|
* @d0i3_disable: disable d0i3, default = 1,
|
||||||
|
* @d0i3_entry_delay: time to wait after no refs are taken before
|
||||||
|
* entering D0i3 (in msecs)
|
||||||
* @lar_disable: disable LAR (regulatory), default = 0
|
* @lar_disable: disable LAR (regulatory), default = 0
|
||||||
* @fw_monitor: allow to use firmware monitor
|
* @fw_monitor: allow to use firmware monitor
|
||||||
*/
|
*/
|
||||||
struct iwl_mod_params {
|
struct iwl_mod_params {
|
||||||
int sw_crypto;
|
int sw_crypto;
|
||||||
unsigned int disable_11n;
|
unsigned int disable_11n;
|
||||||
int amsdu_size_8K;
|
int amsdu_size;
|
||||||
bool restart_fw;
|
bool restart_fw;
|
||||||
bool bt_coex_active;
|
bool bt_coex_active;
|
||||||
int led_mode;
|
int led_mode;
|
||||||
|
@ -122,6 +130,7 @@ struct iwl_mod_params {
|
||||||
char *nvm_file;
|
char *nvm_file;
|
||||||
bool uapsd_disable;
|
bool uapsd_disable;
|
||||||
bool d0i3_disable;
|
bool d0i3_disable;
|
||||||
|
unsigned int d0i3_entry_delay;
|
||||||
bool lar_disable;
|
bool lar_disable;
|
||||||
bool fw_monitor;
|
bool fw_monitor;
|
||||||
};
|
};
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
* in the file called COPYING.
|
* in the file called COPYING.
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
*
|
*
|
||||||
* BSD LICENSE
|
* BSD LICENSE
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
* in the file called COPYING.
|
* in the file called COPYING.
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
*
|
*
|
||||||
* BSD LICENSE
|
* BSD LICENSE
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
* in the file called COPYING.
|
* in the file called COPYING.
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
*
|
*
|
||||||
* BSD LICENSE
|
* BSD LICENSE
|
||||||
|
@ -379,8 +379,19 @@ static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg,
|
||||||
else
|
else
|
||||||
vht_cap->cap |= IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN;
|
vht_cap->cap |= IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN;
|
||||||
|
|
||||||
if (iwlwifi_mod_params.amsdu_size_8K)
|
switch (iwlwifi_mod_params.amsdu_size) {
|
||||||
|
case IWL_AMSDU_4K:
|
||||||
|
vht_cap->cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895;
|
||||||
|
break;
|
||||||
|
case IWL_AMSDU_8K:
|
||||||
vht_cap->cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991;
|
vht_cap->cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991;
|
||||||
|
break;
|
||||||
|
case IWL_AMSDU_12K:
|
||||||
|
vht_cap->cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
vht_cap->vht_mcs.rx_mcs_map =
|
vht_cap->vht_mcs.rx_mcs_map =
|
||||||
cpu_to_le16(IEEE80211_VHT_MCS_SUPPORT_0_9 << 0 |
|
cpu_to_le16(IEEE80211_VHT_MCS_SUPPORT_0_9 << 0 |
|
||||||
|
@ -580,15 +591,13 @@ static void iwl_set_hw_address_family_8000(struct device *dev,
|
||||||
IWL_ERR_DEV(dev, "mac address is not found\n");
|
IWL_ERR_DEV(dev, "mac address is not found\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
#define IWL_4165_DEVICE_ID 0x5501
|
|
||||||
|
|
||||||
struct iwl_nvm_data *
|
struct iwl_nvm_data *
|
||||||
iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
|
iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
|
||||||
const __le16 *nvm_hw, const __le16 *nvm_sw,
|
const __le16 *nvm_hw, const __le16 *nvm_sw,
|
||||||
const __le16 *nvm_calib, const __le16 *regulatory,
|
const __le16 *nvm_calib, const __le16 *regulatory,
|
||||||
const __le16 *mac_override, const __le16 *phy_sku,
|
const __le16 *mac_override, const __le16 *phy_sku,
|
||||||
u8 tx_chains, u8 rx_chains, bool lar_fw_supported,
|
u8 tx_chains, u8 rx_chains, bool lar_fw_supported,
|
||||||
u32 mac_addr0, u32 mac_addr1, u32 hw_id)
|
u32 mac_addr0, u32 mac_addr1)
|
||||||
{
|
{
|
||||||
struct iwl_nvm_data *data;
|
struct iwl_nvm_data *data;
|
||||||
u32 sku;
|
u32 sku;
|
||||||
|
@ -627,17 +636,6 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
|
||||||
(sku & NVM_SKU_CAP_11AC_ENABLE);
|
(sku & NVM_SKU_CAP_11AC_ENABLE);
|
||||||
data->sku_cap_mimo_disabled = sku & NVM_SKU_CAP_MIMO_DISABLE;
|
data->sku_cap_mimo_disabled = sku & NVM_SKU_CAP_MIMO_DISABLE;
|
||||||
|
|
||||||
/*
|
|
||||||
* OTP 0x52 bug work around
|
|
||||||
* define antenna 1x1 according to MIMO disabled
|
|
||||||
*/
|
|
||||||
if (hw_id == IWL_4165_DEVICE_ID && data->sku_cap_mimo_disabled) {
|
|
||||||
data->valid_tx_ant = ANT_B;
|
|
||||||
data->valid_rx_ant = ANT_B;
|
|
||||||
tx_chains = ANT_B;
|
|
||||||
rx_chains = ANT_B;
|
|
||||||
}
|
|
||||||
|
|
||||||
data->n_hw_addrs = iwl_get_n_hw_addrs(cfg, nvm_sw);
|
data->n_hw_addrs = iwl_get_n_hw_addrs(cfg, nvm_sw);
|
||||||
|
|
||||||
if (cfg->device_family != IWL_DEVICE_FAMILY_8000) {
|
if (cfg->device_family != IWL_DEVICE_FAMILY_8000) {
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
* in the file called COPYING.
|
* in the file called COPYING.
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
*
|
*
|
||||||
* BSD LICENSE
|
* BSD LICENSE
|
||||||
|
@ -79,7 +79,7 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
|
||||||
const __le16 *nvm_calib, const __le16 *regulatory,
|
const __le16 *nvm_calib, const __le16 *regulatory,
|
||||||
const __le16 *mac_override, const __le16 *phy_sku,
|
const __le16 *mac_override, const __le16 *phy_sku,
|
||||||
u8 tx_chains, u8 rx_chains, bool lar_fw_supported,
|
u8 tx_chains, u8 rx_chains, bool lar_fw_supported,
|
||||||
u32 mac_addr0, u32 mac_addr1, u32 hw_id);
|
u32 mac_addr0, u32 mac_addr1);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* iwl_parse_mcc_info - parse MCC (mobile country code) info coming from FW
|
* iwl_parse_mcc_info - parse MCC (mobile country code) info coming from FW
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
* in the file called COPYING.
|
* in the file called COPYING.
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
*
|
*
|
||||||
* BSD LICENSE
|
* BSD LICENSE
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
* in the file called COPYING.
|
* in the file called COPYING.
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
*
|
*
|
||||||
* BSD LICENSE
|
* BSD LICENSE
|
||||||
|
|
|
@ -423,6 +423,22 @@ enum iwl_trans_status {
|
||||||
STATUS_TRANS_DEAD,
|
STATUS_TRANS_DEAD,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
iwl_trans_get_rb_size_order(enum iwl_amsdu_size rb_size)
|
||||||
|
{
|
||||||
|
switch (rb_size) {
|
||||||
|
case IWL_AMSDU_4K:
|
||||||
|
return get_order(4 * 1024);
|
||||||
|
case IWL_AMSDU_8K:
|
||||||
|
return get_order(8 * 1024);
|
||||||
|
case IWL_AMSDU_12K:
|
||||||
|
return get_order(12 * 1024);
|
||||||
|
default:
|
||||||
|
WARN_ON(1);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct iwl_trans_config - transport configuration
|
* struct iwl_trans_config - transport configuration
|
||||||
*
|
*
|
||||||
|
@ -436,7 +452,7 @@ enum iwl_trans_status {
|
||||||
* list of such notifications to filter. Max length is
|
* list of such notifications to filter. Max length is
|
||||||
* %MAX_NO_RECLAIM_CMDS.
|
* %MAX_NO_RECLAIM_CMDS.
|
||||||
* @n_no_reclaim_cmds: # of commands in list
|
* @n_no_reclaim_cmds: # of commands in list
|
||||||
* @rx_buf_size_8k: 8 kB RX buffer size needed for A-MSDUs,
|
* @rx_buf_size: RX buffer size needed for A-MSDUs
|
||||||
* if unset 4k will be the RX buffer size
|
* if unset 4k will be the RX buffer size
|
||||||
* @bc_table_dword: set to true if the BC table expects the byte count to be
|
* @bc_table_dword: set to true if the BC table expects the byte count to be
|
||||||
* in DWORD (as opposed to bytes)
|
* in DWORD (as opposed to bytes)
|
||||||
|
@ -456,7 +472,7 @@ struct iwl_trans_config {
|
||||||
const u8 *no_reclaim_cmds;
|
const u8 *no_reclaim_cmds;
|
||||||
unsigned int n_no_reclaim_cmds;
|
unsigned int n_no_reclaim_cmds;
|
||||||
|
|
||||||
bool rx_buf_size_8k;
|
enum iwl_amsdu_size rx_buf_size;
|
||||||
bool bc_table_dword;
|
bool bc_table_dword;
|
||||||
bool scd_set_active;
|
bool scd_set_active;
|
||||||
bool wide_cmd_header;
|
bool wide_cmd_header;
|
||||||
|
@ -526,8 +542,6 @@ struct iwl_trans_txq_scd_cfg {
|
||||||
* @wait_tx_queue_empty: wait until tx queues are empty. May sleep.
|
* @wait_tx_queue_empty: wait until tx queues are empty. May sleep.
|
||||||
* @freeze_txq_timer: prevents the timer of the queue from firing until the
|
* @freeze_txq_timer: prevents the timer of the queue from firing until the
|
||||||
* queue is set to awake. Must be atomic.
|
* queue is set to awake. Must be atomic.
|
||||||
* @dbgfs_register: add the dbgfs files under this directory. Files will be
|
|
||||||
* automatically deleted.
|
|
||||||
* @write8: write a u8 to a register at offset ofs from the BAR
|
* @write8: write a u8 to a register at offset ofs from the BAR
|
||||||
* @write32: write a u32 to a register at offset ofs from the BAR
|
* @write32: write a u32 to a register at offset ofs from the BAR
|
||||||
* @read32: read a u32 register at offset ofs from the BAR
|
* @read32: read a u32 register at offset ofs from the BAR
|
||||||
|
@ -583,7 +597,6 @@ struct iwl_trans_ops {
|
||||||
void (*txq_disable)(struct iwl_trans *trans, int queue,
|
void (*txq_disable)(struct iwl_trans *trans, int queue,
|
||||||
bool configure_scd);
|
bool configure_scd);
|
||||||
|
|
||||||
int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir);
|
|
||||||
int (*wait_tx_queue_empty)(struct iwl_trans *trans, u32 txq_bm);
|
int (*wait_tx_queue_empty)(struct iwl_trans *trans, u32 txq_bm);
|
||||||
void (*freeze_txq_timer)(struct iwl_trans *trans, unsigned long txqs,
|
void (*freeze_txq_timer)(struct iwl_trans *trans, unsigned long txqs,
|
||||||
bool freeze);
|
bool freeze);
|
||||||
|
@ -1006,12 +1019,6 @@ static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans,
|
||||||
return trans->ops->wait_tx_queue_empty(trans, txqs);
|
return trans->ops->wait_tx_queue_empty(trans, txqs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int iwl_trans_dbgfs_register(struct iwl_trans *trans,
|
|
||||||
struct dentry *dir)
|
|
||||||
{
|
|
||||||
return trans->ops->dbgfs_register(trans, dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void iwl_trans_write8(struct iwl_trans *trans, u32 ofs, u8 val)
|
static inline void iwl_trans_write8(struct iwl_trans *trans, u32 ofs, u8 val)
|
||||||
{
|
{
|
||||||
trans->ops->write8(trans, ofs, val);
|
trans->ops->write8(trans, ofs, val);
|
||||||
|
|
|
@ -6,7 +6,7 @@ iwlmvm-y += power.o coex.o coex_legacy.o
|
||||||
iwlmvm-y += tt.o offloading.o tdls.o
|
iwlmvm-y += tt.o offloading.o tdls.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-y += tof.o
|
iwlmvm-y += tof.o fw-dbg.o
|
||||||
iwlmvm-$(CONFIG_PM_SLEEP) += d3.o
|
iwlmvm-$(CONFIG_PM_SLEEP) += d3.o
|
||||||
|
|
||||||
ccflags-y += -D__CHECK_ENDIAN__ -I$(src)/../
|
ccflags-y += -D__CHECK_ENDIAN__ -I$(src)/../
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
* in the file called COPYING.
|
* in the file called COPYING.
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
*
|
*
|
||||||
* BSD LICENSE
|
* BSD LICENSE
|
||||||
|
|
|
@ -443,11 +443,8 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
|
||||||
if (iwl_mvm_bt_is_plcr_supported(mvm))
|
if (iwl_mvm_bt_is_plcr_supported(mvm))
|
||||||
bt_cmd.enabled_modules |= cpu_to_le32(BT_COEX_CORUN_ENABLED);
|
bt_cmd.enabled_modules |= cpu_to_le32(BT_COEX_CORUN_ENABLED);
|
||||||
|
|
||||||
if (IWL_MVM_BT_COEX_MPLUT) {
|
if (iwl_mvm_is_mplut_supported(mvm))
|
||||||
bt_cmd.enabled_modules |= cpu_to_le32(BT_COEX_MPLUT_ENABLED);
|
bt_cmd.enabled_modules |= cpu_to_le32(BT_COEX_MPLUT_ENABLED);
|
||||||
bt_cmd.enabled_modules |=
|
|
||||||
cpu_to_le32(BT_COEX_MPLUT_BOOST_ENABLED);
|
|
||||||
}
|
|
||||||
|
|
||||||
bt_cmd.enabled_modules |= cpu_to_le32(BT_COEX_HIGH_BAND_RET);
|
bt_cmd.enabled_modules |= cpu_to_le32(BT_COEX_HIGH_BAND_RET);
|
||||||
|
|
||||||
|
@ -904,6 +901,7 @@ u8 iwl_mvm_bt_coex_tx_prio(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr,
|
||||||
struct ieee80211_tx_info *info, u8 ac)
|
struct ieee80211_tx_info *info, u8 ac)
|
||||||
{
|
{
|
||||||
__le16 fc = hdr->frame_control;
|
__le16 fc = hdr->frame_control;
|
||||||
|
bool mplut_enabled = iwl_mvm_is_mplut_supported(mvm);
|
||||||
|
|
||||||
if (info->band != IEEE80211_BAND_2GHZ)
|
if (info->band != IEEE80211_BAND_2GHZ)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -911,22 +909,27 @@ u8 iwl_mvm_bt_coex_tx_prio(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr,
|
||||||
if (unlikely(mvm->bt_tx_prio))
|
if (unlikely(mvm->bt_tx_prio))
|
||||||
return mvm->bt_tx_prio - 1;
|
return mvm->bt_tx_prio - 1;
|
||||||
|
|
||||||
/* High prio packet (wrt. BT coex) if it is EAPOL, MCAST or MGMT */
|
if (likely(ieee80211_is_data(fc))) {
|
||||||
if (info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO ||
|
if (likely(ieee80211_is_data_qos(fc))) {
|
||||||
is_multicast_ether_addr(hdr->addr1) ||
|
switch (ac) {
|
||||||
ieee80211_is_ctl(fc) || ieee80211_is_mgmt(fc) ||
|
case IEEE80211_AC_BE:
|
||||||
ieee80211_is_nullfunc(fc) || ieee80211_is_qos_nullfunc(fc))
|
return mplut_enabled ? 1 : 0;
|
||||||
|
case IEEE80211_AC_VI:
|
||||||
|
return mplut_enabled ? 2 : 3;
|
||||||
|
case IEEE80211_AC_VO:
|
||||||
|
return 3;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else if (is_multicast_ether_addr(hdr->addr1)) {
|
||||||
|
return 3;
|
||||||
|
} else
|
||||||
|
return 0;
|
||||||
|
} else if (ieee80211_is_mgmt(fc)) {
|
||||||
|
return ieee80211_is_disassoc(fc) ? 0 : 3;
|
||||||
|
} else if (ieee80211_is_ctl(fc)) {
|
||||||
|
/* ignore cfend and cfendack frames as we never send those */
|
||||||
return 3;
|
return 3;
|
||||||
|
|
||||||
switch (ac) {
|
|
||||||
case IEEE80211_AC_BE:
|
|
||||||
return 1;
|
|
||||||
case IEEE80211_AC_VO:
|
|
||||||
return 3;
|
|
||||||
case IEEE80211_AC_VI:
|
|
||||||
return 2;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -136,7 +136,7 @@ static void iwl_mvm_convert_p1k(u16 *p1k, __le16 *out)
|
||||||
struct wowlan_key_data {
|
struct wowlan_key_data {
|
||||||
struct iwl_wowlan_rsc_tsc_params_cmd *rsc_tsc;
|
struct iwl_wowlan_rsc_tsc_params_cmd *rsc_tsc;
|
||||||
struct iwl_wowlan_tkip_params_cmd *tkip;
|
struct iwl_wowlan_tkip_params_cmd *tkip;
|
||||||
bool error, use_rsc_tsc, use_tkip;
|
bool error, use_rsc_tsc, use_tkip, configure_keys;
|
||||||
int wep_key_idx;
|
int wep_key_idx;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -158,8 +158,6 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw,
|
||||||
u16 p1k[IWL_P1K_SIZE];
|
u16 p1k[IWL_P1K_SIZE];
|
||||||
int ret, i;
|
int ret, i;
|
||||||
|
|
||||||
mutex_lock(&mvm->mutex);
|
|
||||||
|
|
||||||
switch (key->cipher) {
|
switch (key->cipher) {
|
||||||
case WLAN_CIPHER_SUITE_WEP40:
|
case WLAN_CIPHER_SUITE_WEP40:
|
||||||
case WLAN_CIPHER_SUITE_WEP104: { /* hack it for now */
|
case WLAN_CIPHER_SUITE_WEP104: { /* hack it for now */
|
||||||
|
@ -195,20 +193,25 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw,
|
||||||
wkc.wep_key.key_offset = data->wep_key_idx;
|
wkc.wep_key.key_offset = data->wep_key_idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = iwl_mvm_send_cmd_pdu(mvm, WEP_KEY, 0, sizeof(wkc), &wkc);
|
if (data->configure_keys) {
|
||||||
data->error = ret != 0;
|
mutex_lock(&mvm->mutex);
|
||||||
|
ret = iwl_mvm_send_cmd_pdu(mvm, WEP_KEY, 0,
|
||||||
|
sizeof(wkc), &wkc);
|
||||||
|
data->error = ret != 0;
|
||||||
|
|
||||||
mvm->ptk_ivlen = key->iv_len;
|
mvm->ptk_ivlen = key->iv_len;
|
||||||
mvm->ptk_icvlen = key->icv_len;
|
mvm->ptk_icvlen = key->icv_len;
|
||||||
mvm->gtk_ivlen = key->iv_len;
|
mvm->gtk_ivlen = key->iv_len;
|
||||||
mvm->gtk_icvlen = key->icv_len;
|
mvm->gtk_icvlen = key->icv_len;
|
||||||
|
mutex_unlock(&mvm->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
/* don't upload key again */
|
/* don't upload key again */
|
||||||
goto out_unlock;
|
return;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
data->error = true;
|
data->error = true;
|
||||||
goto out_unlock;
|
return;
|
||||||
case WLAN_CIPHER_SUITE_AES_CMAC:
|
case WLAN_CIPHER_SUITE_AES_CMAC:
|
||||||
/*
|
/*
|
||||||
* Ignore CMAC keys -- the WoWLAN firmware doesn't support them
|
* Ignore CMAC keys -- the WoWLAN firmware doesn't support them
|
||||||
|
@ -217,7 +220,7 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw,
|
||||||
* IGTK for anything. This means we could spuriously wake up or
|
* IGTK for anything. This means we could spuriously wake up or
|
||||||
* be deauthenticated, but that was considered acceptable.
|
* be deauthenticated, but that was considered acceptable.
|
||||||
*/
|
*/
|
||||||
goto out_unlock;
|
return;
|
||||||
case WLAN_CIPHER_SUITE_TKIP:
|
case WLAN_CIPHER_SUITE_TKIP:
|
||||||
if (sta) {
|
if (sta) {
|
||||||
tkip_sc = data->rsc_tsc->all_tsc_rsc.tkip.unicast_rsc;
|
tkip_sc = data->rsc_tsc->all_tsc_rsc.tkip.unicast_rsc;
|
||||||
|
@ -304,30 +307,30 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
if (data->configure_keys) {
|
||||||
* The D3 firmware hardcodes the key offset 0 as the key it uses
|
mutex_lock(&mvm->mutex);
|
||||||
* to transmit packets to the AP, i.e. the PTK.
|
|
||||||
*/
|
|
||||||
if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) {
|
|
||||||
key->hw_key_idx = 0;
|
|
||||||
mvm->ptk_ivlen = key->iv_len;
|
|
||||||
mvm->ptk_icvlen = key->icv_len;
|
|
||||||
} else {
|
|
||||||
/*
|
/*
|
||||||
* firmware only supports TSC/RSC for a single key,
|
* The D3 firmware hardcodes the key offset 0 as the key it
|
||||||
* so if there are multiple keep overwriting them
|
* uses to transmit packets to the AP, i.e. the PTK.
|
||||||
* with new ones -- this relies on mac80211 doing
|
|
||||||
* list_add_tail().
|
|
||||||
*/
|
*/
|
||||||
key->hw_key_idx = 1;
|
if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) {
|
||||||
mvm->gtk_ivlen = key->iv_len;
|
mvm->ptk_ivlen = key->iv_len;
|
||||||
mvm->gtk_icvlen = key->icv_len;
|
mvm->ptk_icvlen = key->icv_len;
|
||||||
|
ret = iwl_mvm_set_sta_key(mvm, vif, sta, key, 0);
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* firmware only supports TSC/RSC for a single key,
|
||||||
|
* so if there are multiple keep overwriting them
|
||||||
|
* with new ones -- this relies on mac80211 doing
|
||||||
|
* list_add_tail().
|
||||||
|
*/
|
||||||
|
mvm->gtk_ivlen = key->iv_len;
|
||||||
|
mvm->gtk_icvlen = key->icv_len;
|
||||||
|
ret = iwl_mvm_set_sta_key(mvm, vif, sta, key, 1);
|
||||||
|
}
|
||||||
|
mutex_unlock(&mvm->mutex);
|
||||||
|
data->error = ret != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = iwl_mvm_set_sta_key(mvm, vif, sta, key, true);
|
|
||||||
data->error = ret != 0;
|
|
||||||
out_unlock:
|
|
||||||
mutex_unlock(&mvm->mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int iwl_mvm_send_patterns(struct iwl_mvm *mvm,
|
static int iwl_mvm_send_patterns(struct iwl_mvm *mvm,
|
||||||
|
@ -772,9 +775,6 @@ static int iwl_mvm_switch_to_d3(struct iwl_mvm *mvm)
|
||||||
*/
|
*/
|
||||||
set_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status);
|
set_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status);
|
||||||
|
|
||||||
/* We reprogram keys and shouldn't allocate new key indices */
|
|
||||||
memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table));
|
|
||||||
|
|
||||||
mvm->ptk_ivlen = 0;
|
mvm->ptk_ivlen = 0;
|
||||||
mvm->ptk_icvlen = 0;
|
mvm->ptk_icvlen = 0;
|
||||||
mvm->ptk_ivlen = 0;
|
mvm->ptk_ivlen = 0;
|
||||||
|
@ -846,6 +846,82 @@ iwl_mvm_get_wowlan_config(struct iwl_mvm *mvm,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int iwl_mvm_wowlan_config_key_params(struct iwl_mvm *mvm,
|
||||||
|
struct ieee80211_vif *vif,
|
||||||
|
bool configure_keys,
|
||||||
|
u32 cmd_flags)
|
||||||
|
{
|
||||||
|
struct iwl_wowlan_kek_kck_material_cmd kek_kck_cmd = {};
|
||||||
|
struct iwl_wowlan_tkip_params_cmd tkip_cmd = {};
|
||||||
|
struct wowlan_key_data key_data = {
|
||||||
|
.configure_keys = configure_keys,
|
||||||
|
.use_rsc_tsc = false,
|
||||||
|
.tkip = &tkip_cmd,
|
||||||
|
.use_tkip = false,
|
||||||
|
};
|
||||||
|
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
key_data.rsc_tsc = kzalloc(sizeof(*key_data.rsc_tsc), GFP_KERNEL);
|
||||||
|
if (!key_data.rsc_tsc)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note that currently we don't propagate cmd_flags
|
||||||
|
* to the iterator. In case of key_data.configure_keys,
|
||||||
|
* all the configured commands are SYNC, and
|
||||||
|
* iwl_mvm_wowlan_program_keys() will take care of
|
||||||
|
* locking/unlocking mvm->mutex.
|
||||||
|
*/
|
||||||
|
ieee80211_iter_keys(mvm->hw, vif,
|
||||||
|
iwl_mvm_wowlan_program_keys,
|
||||||
|
&key_data);
|
||||||
|
|
||||||
|
if (key_data.error) {
|
||||||
|
ret = -EIO;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key_data.use_rsc_tsc) {
|
||||||
|
ret = iwl_mvm_send_cmd_pdu(mvm,
|
||||||
|
WOWLAN_TSC_RSC_PARAM, cmd_flags,
|
||||||
|
sizeof(*key_data.rsc_tsc),
|
||||||
|
key_data.rsc_tsc);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key_data.use_tkip) {
|
||||||
|
ret = iwl_mvm_send_cmd_pdu(mvm,
|
||||||
|
WOWLAN_TKIP_PARAM,
|
||||||
|
cmd_flags, sizeof(tkip_cmd),
|
||||||
|
&tkip_cmd);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mvmvif->rekey_data.valid) {
|
||||||
|
memset(&kek_kck_cmd, 0, sizeof(kek_kck_cmd));
|
||||||
|
memcpy(kek_kck_cmd.kck, mvmvif->rekey_data.kck,
|
||||||
|
NL80211_KCK_LEN);
|
||||||
|
kek_kck_cmd.kck_len = cpu_to_le16(NL80211_KCK_LEN);
|
||||||
|
memcpy(kek_kck_cmd.kek, mvmvif->rekey_data.kek,
|
||||||
|
NL80211_KEK_LEN);
|
||||||
|
kek_kck_cmd.kek_len = cpu_to_le16(NL80211_KEK_LEN);
|
||||||
|
kek_kck_cmd.replay_ctr = mvmvif->rekey_data.replay_ctr;
|
||||||
|
|
||||||
|
ret = iwl_mvm_send_cmd_pdu(mvm,
|
||||||
|
WOWLAN_KEK_KCK_MATERIAL, cmd_flags,
|
||||||
|
sizeof(kek_kck_cmd),
|
||||||
|
&kek_kck_cmd);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
kfree(key_data.rsc_tsc);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
iwl_mvm_wowlan_config(struct iwl_mvm *mvm,
|
iwl_mvm_wowlan_config(struct iwl_mvm *mvm,
|
||||||
struct cfg80211_wowlan *wowlan,
|
struct cfg80211_wowlan *wowlan,
|
||||||
|
@ -853,13 +929,6 @@ iwl_mvm_wowlan_config(struct iwl_mvm *mvm,
|
||||||
struct ieee80211_vif *vif, struct iwl_mvm_vif *mvmvif,
|
struct ieee80211_vif *vif, struct iwl_mvm_vif *mvmvif,
|
||||||
struct ieee80211_sta *ap_sta)
|
struct ieee80211_sta *ap_sta)
|
||||||
{
|
{
|
||||||
struct iwl_wowlan_kek_kck_material_cmd kek_kck_cmd = {};
|
|
||||||
struct iwl_wowlan_tkip_params_cmd tkip_cmd = {};
|
|
||||||
struct wowlan_key_data key_data = {
|
|
||||||
.use_rsc_tsc = false,
|
|
||||||
.tkip = &tkip_cmd,
|
|
||||||
.use_tkip = false,
|
|
||||||
};
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = iwl_mvm_switch_to_d3(mvm);
|
ret = iwl_mvm_switch_to_d3(mvm);
|
||||||
|
@ -870,10 +939,6 @@ iwl_mvm_wowlan_config(struct iwl_mvm *mvm,
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
key_data.rsc_tsc = kzalloc(sizeof(*key_data.rsc_tsc), GFP_KERNEL);
|
|
||||||
if (!key_data.rsc_tsc)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
if (!iwlwifi_mod_params.sw_crypto) {
|
if (!iwlwifi_mod_params.sw_crypto) {
|
||||||
/*
|
/*
|
||||||
* This needs to be unlocked due to lock ordering
|
* This needs to be unlocked due to lock ordering
|
||||||
|
@ -881,74 +946,25 @@ iwl_mvm_wowlan_config(struct iwl_mvm *mvm,
|
||||||
* that isn't really a problem though.
|
* that isn't really a problem though.
|
||||||
*/
|
*/
|
||||||
mutex_unlock(&mvm->mutex);
|
mutex_unlock(&mvm->mutex);
|
||||||
ieee80211_iter_keys(mvm->hw, vif,
|
iwl_mvm_wowlan_config_key_params(mvm, vif, true, CMD_ASYNC);
|
||||||
iwl_mvm_wowlan_program_keys,
|
|
||||||
&key_data);
|
|
||||||
mutex_lock(&mvm->mutex);
|
mutex_lock(&mvm->mutex);
|
||||||
if (key_data.error) {
|
|
||||||
ret = -EIO;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key_data.use_rsc_tsc) {
|
|
||||||
struct iwl_host_cmd rsc_tsc_cmd = {
|
|
||||||
.id = WOWLAN_TSC_RSC_PARAM,
|
|
||||||
.data[0] = key_data.rsc_tsc,
|
|
||||||
.dataflags[0] = IWL_HCMD_DFL_NOCOPY,
|
|
||||||
.len[0] = sizeof(*key_data.rsc_tsc),
|
|
||||||
};
|
|
||||||
|
|
||||||
ret = iwl_mvm_send_cmd(mvm, &rsc_tsc_cmd);
|
|
||||||
if (ret)
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key_data.use_tkip) {
|
|
||||||
ret = iwl_mvm_send_cmd_pdu(mvm,
|
|
||||||
WOWLAN_TKIP_PARAM,
|
|
||||||
0, sizeof(tkip_cmd),
|
|
||||||
&tkip_cmd);
|
|
||||||
if (ret)
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mvmvif->rekey_data.valid) {
|
|
||||||
memset(&kek_kck_cmd, 0, sizeof(kek_kck_cmd));
|
|
||||||
memcpy(kek_kck_cmd.kck, mvmvif->rekey_data.kck,
|
|
||||||
NL80211_KCK_LEN);
|
|
||||||
kek_kck_cmd.kck_len = cpu_to_le16(NL80211_KCK_LEN);
|
|
||||||
memcpy(kek_kck_cmd.kek, mvmvif->rekey_data.kek,
|
|
||||||
NL80211_KEK_LEN);
|
|
||||||
kek_kck_cmd.kek_len = cpu_to_le16(NL80211_KEK_LEN);
|
|
||||||
kek_kck_cmd.replay_ctr = mvmvif->rekey_data.replay_ctr;
|
|
||||||
|
|
||||||
ret = iwl_mvm_send_cmd_pdu(mvm,
|
|
||||||
WOWLAN_KEK_KCK_MATERIAL, 0,
|
|
||||||
sizeof(kek_kck_cmd),
|
|
||||||
&kek_kck_cmd);
|
|
||||||
if (ret)
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_CONFIGURATION, 0,
|
ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_CONFIGURATION, 0,
|
||||||
sizeof(*wowlan_config_cmd),
|
sizeof(*wowlan_config_cmd),
|
||||||
wowlan_config_cmd);
|
wowlan_config_cmd);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
return ret;
|
||||||
|
|
||||||
ret = iwl_mvm_send_patterns(mvm, wowlan);
|
ret = iwl_mvm_send_patterns(mvm, wowlan);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
return ret;
|
||||||
|
|
||||||
ret = iwl_mvm_send_proto_offload(mvm, vif, false, 0);
|
ret = iwl_mvm_send_proto_offload(mvm, vif, false, 0);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
return ret;
|
||||||
|
|
||||||
ret = iwl_mvm_send_remote_wake_cfg(mvm, vif, wowlan->tcp);
|
ret = iwl_mvm_send_remote_wake_cfg(mvm, vif, wowlan->tcp);
|
||||||
|
|
||||||
out:
|
|
||||||
kfree(key_data.rsc_tsc);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1061,13 +1077,13 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
|
||||||
|
|
||||||
if (mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT) {
|
if (mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT) {
|
||||||
/* if we're not associated, this must be netdetect */
|
/* if we're not associated, this must be netdetect */
|
||||||
if (!wowlan->nd_config && !mvm->nd_config) {
|
if (!wowlan->nd_config) {
|
||||||
ret = 1;
|
ret = 1;
|
||||||
goto out_noreset;
|
goto out_noreset;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = iwl_mvm_netdetect_config(
|
ret = iwl_mvm_netdetect_config(
|
||||||
mvm, wowlan, wowlan->nd_config ?: mvm->nd_config, vif);
|
mvm, wowlan, wowlan->nd_config, vif);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
@ -1220,6 +1236,8 @@ static void iwl_mvm_report_wakeup_reasons(struct iwl_mvm *mvm,
|
||||||
goto report;
|
goto report;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pm_wakeup_event(mvm->dev, 0);
|
||||||
|
|
||||||
if (reasons & IWL_WOWLAN_WAKEUP_BY_MAGIC_PACKET)
|
if (reasons & IWL_WOWLAN_WAKEUP_BY_MAGIC_PACKET)
|
||||||
wakeup.magic_pkt = true;
|
wakeup.magic_pkt = true;
|
||||||
|
|
||||||
|
@ -1410,7 +1428,7 @@ struct iwl_mvm_d3_gtk_iter_data {
|
||||||
int num_keys;
|
int num_keys;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void iwl_mvm_d3_update_gtks(struct ieee80211_hw *hw,
|
static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw,
|
||||||
struct ieee80211_vif *vif,
|
struct ieee80211_vif *vif,
|
||||||
struct ieee80211_sta *sta,
|
struct ieee80211_sta *sta,
|
||||||
struct ieee80211_key_conf *key,
|
struct ieee80211_key_conf *key,
|
||||||
|
@ -1498,7 +1516,7 @@ static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,
|
||||||
/* find last GTK that we used initially, if any */
|
/* find last GTK that we used initially, if any */
|
||||||
gtkdata.find_phase = true;
|
gtkdata.find_phase = true;
|
||||||
ieee80211_iter_keys(mvm->hw, vif,
|
ieee80211_iter_keys(mvm->hw, vif,
|
||||||
iwl_mvm_d3_update_gtks, >kdata);
|
iwl_mvm_d3_update_keys, >kdata);
|
||||||
/* not trying to keep connections with MFP/unhandled ciphers */
|
/* not trying to keep connections with MFP/unhandled ciphers */
|
||||||
if (gtkdata.unhandled_cipher)
|
if (gtkdata.unhandled_cipher)
|
||||||
return false;
|
return false;
|
||||||
|
@ -1513,7 +1531,7 @@ static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,
|
||||||
*/
|
*/
|
||||||
gtkdata.find_phase = false;
|
gtkdata.find_phase = false;
|
||||||
ieee80211_iter_keys(mvm->hw, vif,
|
ieee80211_iter_keys(mvm->hw, vif,
|
||||||
iwl_mvm_d3_update_gtks, >kdata);
|
iwl_mvm_d3_update_keys, >kdata);
|
||||||
|
|
||||||
if (status->num_of_gtk_rekeys) {
|
if (status->num_of_gtk_rekeys) {
|
||||||
struct ieee80211_key_conf *key;
|
struct ieee80211_key_conf *key;
|
||||||
|
|
|
@ -65,6 +65,7 @@
|
||||||
#include <linux/vmalloc.h>
|
#include <linux/vmalloc.h>
|
||||||
|
|
||||||
#include "mvm.h"
|
#include "mvm.h"
|
||||||
|
#include "fw-dbg.h"
|
||||||
#include "sta.h"
|
#include "sta.h"
|
||||||
#include "iwl-io.h"
|
#include "iwl-io.h"
|
||||||
#include "debugfs.h"
|
#include "debugfs.h"
|
||||||
|
@ -512,6 +513,10 @@ static ssize_t iwl_dbgfs_bt_notif_read(struct file *file, char __user *user_buf,
|
||||||
pos += scnprintf(buf+pos, bufsz-pos,
|
pos += scnprintf(buf+pos, bufsz-pos,
|
||||||
"antenna isolation = %d CORUN LUT index = %d\n",
|
"antenna isolation = %d CORUN LUT index = %d\n",
|
||||||
mvm->last_ant_isol, mvm->last_corun_lut);
|
mvm->last_ant_isol, mvm->last_corun_lut);
|
||||||
|
pos += scnprintf(buf + pos, bufsz - pos, "bt_rrc = %d\n",
|
||||||
|
notif->rrc_enabled);
|
||||||
|
pos += scnprintf(buf + pos, bufsz - pos, "bt_ttc = %d\n",
|
||||||
|
notif->ttc_enabled);
|
||||||
} else {
|
} else {
|
||||||
struct iwl_bt_coex_profile_notif *notif =
|
struct iwl_bt_coex_profile_notif *notif =
|
||||||
&mvm->last_bt_notif;
|
&mvm->last_bt_notif;
|
||||||
|
@ -530,8 +535,19 @@ static ssize_t iwl_dbgfs_bt_notif_read(struct file *file, char __user *user_buf,
|
||||||
pos += scnprintf(buf+pos, bufsz-pos,
|
pos += scnprintf(buf+pos, bufsz-pos,
|
||||||
"antenna isolation = %d CORUN LUT index = %d\n",
|
"antenna isolation = %d CORUN LUT index = %d\n",
|
||||||
mvm->last_ant_isol, mvm->last_corun_lut);
|
mvm->last_ant_isol, mvm->last_corun_lut);
|
||||||
|
pos += scnprintf(buf + pos, bufsz - pos, "bt_rrc = %d\n",
|
||||||
|
(notif->ttc_rrc_status >> 4) & 0xF);
|
||||||
|
pos += scnprintf(buf + pos, bufsz - pos, "bt_ttc = %d\n",
|
||||||
|
notif->ttc_rrc_status & 0xF);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pos += scnprintf(buf + pos, bufsz - pos, "sync_sco = %d\n",
|
||||||
|
IWL_MVM_BT_COEX_SYNC2SCO);
|
||||||
|
pos += scnprintf(buf + pos, bufsz - pos, "mplut = %d\n",
|
||||||
|
IWL_MVM_BT_COEX_MPLUT);
|
||||||
|
pos += scnprintf(buf + pos, bufsz - pos, "corunning = %d\n",
|
||||||
|
IWL_MVM_BT_COEX_CORUNNING);
|
||||||
|
|
||||||
mutex_unlock(&mvm->mutex);
|
mutex_unlock(&mvm->mutex);
|
||||||
|
|
||||||
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||||
|
@ -945,6 +961,44 @@ static ssize_t iwl_dbgfs_fw_dbg_conf_read(struct file *file,
|
||||||
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enable / Disable continuous recording.
|
||||||
|
* Cause the FW to start continuous recording, by sending the relevant hcmd.
|
||||||
|
* Enable: input of every integer larger than 0, ENABLE_CONT_RECORDING.
|
||||||
|
* Disable: for 0 as input, DISABLE_CONT_RECORDING.
|
||||||
|
*/
|
||||||
|
static ssize_t iwl_dbgfs_cont_recording_write(struct iwl_mvm *mvm,
|
||||||
|
char *buf, size_t count,
|
||||||
|
loff_t *ppos)
|
||||||
|
{
|
||||||
|
struct iwl_trans *trans = mvm->trans;
|
||||||
|
const struct iwl_fw_dbg_dest_tlv *dest = trans->dbg_dest_tlv;
|
||||||
|
struct iwl_continuous_record_cmd cont_rec = {};
|
||||||
|
int ret, rec_mode;
|
||||||
|
|
||||||
|
if (!dest)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
if (dest->monitor_mode != SMEM_MODE ||
|
||||||
|
trans->cfg->device_family != IWL_DEVICE_FAMILY_8000)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
ret = kstrtouint(buf, 0, &rec_mode);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
cont_rec.record_mode.enable_recording = rec_mode ?
|
||||||
|
cpu_to_le16(ENABLE_CONT_RECORDING) :
|
||||||
|
cpu_to_le16(DISABLE_CONT_RECORDING);
|
||||||
|
|
||||||
|
mutex_lock(&mvm->mutex);
|
||||||
|
ret = iwl_mvm_send_cmd_pdu(mvm, LDBG_CONFIG_CMD, 0,
|
||||||
|
sizeof(cont_rec), &cont_rec);
|
||||||
|
mutex_unlock(&mvm->mutex);
|
||||||
|
|
||||||
|
return ret ?: count;
|
||||||
|
}
|
||||||
|
|
||||||
static ssize_t iwl_dbgfs_fw_dbg_conf_write(struct iwl_mvm *mvm,
|
static ssize_t iwl_dbgfs_fw_dbg_conf_write(struct iwl_mvm *mvm,
|
||||||
char *buf, size_t count,
|
char *buf, size_t count,
|
||||||
loff_t *ppos)
|
loff_t *ppos)
|
||||||
|
@ -1397,6 +1451,7 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8);
|
||||||
MVM_DEBUGFS_READ_WRITE_FILE_OPS(d0i3_refs, 8);
|
MVM_DEBUGFS_READ_WRITE_FILE_OPS(d0i3_refs, 8);
|
||||||
MVM_DEBUGFS_READ_WRITE_FILE_OPS(fw_dbg_conf, 8);
|
MVM_DEBUGFS_READ_WRITE_FILE_OPS(fw_dbg_conf, 8);
|
||||||
MVM_DEBUGFS_WRITE_FILE_OPS(fw_dbg_collect, 8);
|
MVM_DEBUGFS_WRITE_FILE_OPS(fw_dbg_collect, 8);
|
||||||
|
MVM_DEBUGFS_WRITE_FILE_OPS(cont_recording, 8);
|
||||||
|
|
||||||
#ifdef CONFIG_IWLWIFI_BCAST_FILTERING
|
#ifdef CONFIG_IWLWIFI_BCAST_FILTERING
|
||||||
MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters, 256);
|
MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters, 256);
|
||||||
|
@ -1440,6 +1495,7 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
|
||||||
MVM_DEBUGFS_ADD_FILE(fw_dbg_conf, mvm->debugfs_dir, S_IRUSR | S_IWUSR);
|
MVM_DEBUGFS_ADD_FILE(fw_dbg_conf, mvm->debugfs_dir, S_IRUSR | S_IWUSR);
|
||||||
MVM_DEBUGFS_ADD_FILE(fw_dbg_collect, mvm->debugfs_dir, S_IWUSR);
|
MVM_DEBUGFS_ADD_FILE(fw_dbg_collect, mvm->debugfs_dir, S_IWUSR);
|
||||||
MVM_DEBUGFS_ADD_FILE(send_echo_cmd, mvm->debugfs_dir, S_IWUSR);
|
MVM_DEBUGFS_ADD_FILE(send_echo_cmd, mvm->debugfs_dir, S_IWUSR);
|
||||||
|
MVM_DEBUGFS_ADD_FILE(cont_recording, mvm->debugfs_dir, S_IWUSR);
|
||||||
if (!debugfs_create_bool("enable_scan_iteration_notif",
|
if (!debugfs_create_bool("enable_scan_iteration_notif",
|
||||||
S_IRUSR | S_IWUSR,
|
S_IRUSR | S_IWUSR,
|
||||||
mvm->debugfs_dir,
|
mvm->debugfs_dir,
|
||||||
|
@ -1476,10 +1532,6 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
|
||||||
goto err;
|
goto err;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!debugfs_create_u8("low_latency_agg_frame_limit", S_IRUSR | S_IWUSR,
|
|
||||||
mvm->debugfs_dir,
|
|
||||||
&mvm->low_latency_agg_frame_limit))
|
|
||||||
goto err;
|
|
||||||
if (!debugfs_create_u8("ps_disabled", S_IRUSR,
|
if (!debugfs_create_u8("ps_disabled", S_IRUSR,
|
||||||
mvm->debugfs_dir, &mvm->ps_disabled))
|
mvm->debugfs_dir, &mvm->ps_disabled))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
* in the file called COPYING.
|
* in the file called COPYING.
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
*
|
*
|
||||||
* BSD LICENSE
|
* BSD LICENSE
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
* in the file called COPYING.
|
* in the file called COPYING.
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
*
|
*
|
||||||
* BSD LICENSE
|
* BSD LICENSE
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
* in the file called COPYING.
|
* in the file called COPYING.
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
*
|
*
|
||||||
* BSD LICENSE
|
* BSD LICENSE
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
* in the file called COPYING.
|
* in the file called COPYING.
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
*
|
*
|
||||||
* BSD LICENSE
|
* BSD LICENSE
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
* in the file called COPYING.
|
* in the file called COPYING.
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
*
|
*
|
||||||
* BSD LICENSE
|
* BSD LICENSE
|
||||||
|
|
|
@ -68,6 +68,8 @@
|
||||||
#ifndef __fw_api_rx_h__
|
#ifndef __fw_api_rx_h__
|
||||||
#define __fw_api_rx_h__
|
#define __fw_api_rx_h__
|
||||||
|
|
||||||
|
/* API for pre-9000 hardware */
|
||||||
|
|
||||||
#define IWL_RX_INFO_PHY_CNT 8
|
#define IWL_RX_INFO_PHY_CNT 8
|
||||||
#define IWL_RX_INFO_ENERGY_ANT_ABC_IDX 1
|
#define IWL_RX_INFO_ENERGY_ANT_ABC_IDX 1
|
||||||
#define IWL_RX_INFO_ENERGY_ANT_A_MSK 0x000000ff
|
#define IWL_RX_INFO_ENERGY_ANT_A_MSK 0x000000ff
|
||||||
|
@ -229,10 +231,122 @@ enum iwl_mvm_rx_status {
|
||||||
RX_MPDU_RES_STATUS_CSUM_DONE = BIT(16),
|
RX_MPDU_RES_STATUS_CSUM_DONE = BIT(16),
|
||||||
RX_MPDU_RES_STATUS_CSUM_OK = BIT(17),
|
RX_MPDU_RES_STATUS_CSUM_OK = BIT(17),
|
||||||
RX_MPDU_RES_STATUS_HASH_INDEX_MSK = (0x3F0000),
|
RX_MPDU_RES_STATUS_HASH_INDEX_MSK = (0x3F0000),
|
||||||
RX_MPDU_RES_STATUS_STA_ID_MSK = (0x1f000000),
|
RX_MDPU_RES_STATUS_STA_ID_SHIFT = 24,
|
||||||
|
RX_MPDU_RES_STATUS_STA_ID_MSK = 0x1f << RX_MDPU_RES_STATUS_STA_ID_SHIFT,
|
||||||
RX_MPDU_RES_STATUS_RRF_KILL = BIT(29),
|
RX_MPDU_RES_STATUS_RRF_KILL = BIT(29),
|
||||||
RX_MPDU_RES_STATUS_FILTERING_MSK = (0xc00000),
|
RX_MPDU_RES_STATUS_FILTERING_MSK = (0xc00000),
|
||||||
RX_MPDU_RES_STATUS2_FILTERING_MSK = (0xc0000000),
|
RX_MPDU_RES_STATUS2_FILTERING_MSK = (0xc0000000),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* 9000 series API */
|
||||||
|
enum iwl_rx_mpdu_mac_flags1 {
|
||||||
|
IWL_RX_MDPU_MFLG1_ADDRTYPE_MASK = 0x03,
|
||||||
|
IWL_RX_MPDU_MFLG1_MIC_CRC_LEN_MASK = 0xf0,
|
||||||
|
/* shift should be 4, but the length is measured in 2-byte
|
||||||
|
* words, so shifting only by 3 gives a byte result
|
||||||
|
*/
|
||||||
|
IWL_RX_MPDU_MFLG1_MIC_CRC_LEN_SHIFT = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum iwl_rx_mpdu_mac_flags2 {
|
||||||
|
/* in 2-byte words */
|
||||||
|
IWL_RX_MPDU_MFLG2_HDR_LEN_MASK = 0x1f,
|
||||||
|
IWL_RX_MPDU_MFLG2_PAD = 0x20,
|
||||||
|
IWL_RX_MPDU_MFLG2_AMSDU = 0x40,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum iwl_rx_mpdu_amsdu_info {
|
||||||
|
IWL_RX_MPDU_AMSDU_SUBFRAME_IDX_MASK = 0x3f,
|
||||||
|
IWL_RX_MPDU_AMSDU_LAST_SUBFRAME = 0x40,
|
||||||
|
/* 0x80 bit reserved for now */
|
||||||
|
};
|
||||||
|
|
||||||
|
enum iwl_rx_l3l4_flags {
|
||||||
|
IWL_RX_L3L4_IP_HDR_CSUM_OK = BIT(0),
|
||||||
|
IWL_RX_L3L4_TCP_UDP_CSUM_OK = BIT(1),
|
||||||
|
IWL_RX_L3L4_TCP_FIN_SYN_RST_PSH = BIT(2),
|
||||||
|
IWL_RX_L3L4_TCP_ACK = BIT(3),
|
||||||
|
IWL_RX_L3L4_L3_PROTO_MASK = 0xf << 4,
|
||||||
|
IWL_RX_L3L4_L4_PROTO_MASK = 0xf << 8,
|
||||||
|
IWL_RX_L3L4_RSS_HASH_MASK = 0xf << 12,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum iwl_rx_mpdu_status {
|
||||||
|
IWL_RX_MPDU_STATUS_CRC_OK = BIT(0),
|
||||||
|
IWL_RX_MPDU_STATUS_OVERRUN_OK = BIT(1),
|
||||||
|
IWL_RX_MPDU_STATUS_SRC_STA_FOUND = BIT(2),
|
||||||
|
IWL_RX_MPDU_STATUS_KEY_VALID = BIT(3),
|
||||||
|
IWL_RX_MPDU_STATUS_KEY_ERROR = BIT(4),
|
||||||
|
IWL_RX_MPDU_STATUS_ICV_OK = BIT(5),
|
||||||
|
IWL_RX_MPDU_STATUS_MIC_OK = BIT(6),
|
||||||
|
IWL_RX_MPDU_STATUS_SEC_MASK = 0x7 << 8,
|
||||||
|
IWL_RX_MPDU_STATUS_SEC_NONE = 0x0 << 8,
|
||||||
|
IWL_RX_MPDU_STATUS_SEC_WEP = 0x1 << 8,
|
||||||
|
IWL_RX_MPDU_STATUS_SEC_CCM = 0x2 << 8,
|
||||||
|
IWL_RX_MPDU_STATUS_SEC_TKIP = 0x3 << 8,
|
||||||
|
IWL_RX_MPDU_STATUS_DECRYPTED = BIT(11),
|
||||||
|
IWL_RX_MPDU_STATUS_WEP_MATCH = BIT(12),
|
||||||
|
IWL_RX_MPDU_STATUS_EXT_IV_MATCH = BIT(13),
|
||||||
|
IWL_RX_MPDU_STATUS_KEY_ID_MATCH = BIT(14),
|
||||||
|
IWL_RX_MPDU_STATUS_KEY_COLOR = BIT(15),
|
||||||
|
};
|
||||||
|
|
||||||
|
enum iwl_rx_mpdu_hash_filter {
|
||||||
|
IWL_RX_MPDU_HF_A1_HASH_MASK = 0x3f,
|
||||||
|
IWL_RX_MPDU_HF_FILTER_STATUS_MASK = 0xc0,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum iwl_rx_mpdu_sta_id_flags {
|
||||||
|
IWL_RX_MPDU_SIF_STA_ID_MASK = 0x1f,
|
||||||
|
IWL_RX_MPDU_SIF_RRF_ABORT = 0x20,
|
||||||
|
IWL_RX_MPDU_SIF_FILTER_STATUS_MASK = 0xc0,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum iwl_rx_mpdu_reorder_data {
|
||||||
|
IWL_RX_MPDU_REORDER_NSSN_MASK = 0x00000fff,
|
||||||
|
IWL_RX_MPDU_REORDER_SN_MASK = 0x00fff000,
|
||||||
|
IWL_RX_MPDU_REORDER_SN_SHIFT = 12,
|
||||||
|
IWL_RX_MPDU_REORDER_BAID_MASK = 0x7f000000,
|
||||||
|
IWL_RX_MPDU_REORDER_BAID_SHIFT = 24,
|
||||||
|
IWL_RX_MPDU_REORDER_BA_OLD_SN = 0x80000000,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct iwl_rx_mpdu_desc {
|
||||||
|
/* DW2 */
|
||||||
|
__le16 mpdu_len;
|
||||||
|
u8 mac_flags1;
|
||||||
|
u8 mac_flags2;
|
||||||
|
/* DW3 */
|
||||||
|
u8 amsdu_info;
|
||||||
|
__le16 reserved_for_software;
|
||||||
|
u8 mac_phy_idx;
|
||||||
|
/* DW4 */
|
||||||
|
__le16 raw_csum; /* alledgedly unreliable */
|
||||||
|
__le16 l3l4_flags;
|
||||||
|
/* DW5 */
|
||||||
|
__le16 status;
|
||||||
|
u8 hash_filter;
|
||||||
|
u8 sta_id_flags;
|
||||||
|
/* DW6 */
|
||||||
|
__le32 reorder_data;
|
||||||
|
/* DW7 */
|
||||||
|
__le32 rss_hash;
|
||||||
|
/* DW8 */
|
||||||
|
__le32 filter_match;
|
||||||
|
/* DW9 */
|
||||||
|
__le32 gp2_on_air_rise;
|
||||||
|
/* DW10 */
|
||||||
|
__le32 rate_n_flags;
|
||||||
|
/* DW11 */
|
||||||
|
u8 energy_a, energy_b, energy_c, channel;
|
||||||
|
/* DW12 & DW13 */
|
||||||
|
__le64 tsf_on_air_rise;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
struct iwl_frame_release {
|
||||||
|
u8 baid;
|
||||||
|
u8 reserved;
|
||||||
|
__le16 nssn;
|
||||||
|
};
|
||||||
|
|
||||||
#endif /* __fw_api_rx_h__ */
|
#endif /* __fw_api_rx_h__ */
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
* in the file called COPYING.
|
* in the file called COPYING.
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
*
|
*
|
||||||
* BSD LICENSE
|
* BSD LICENSE
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
* in the file called COPYING.
|
* in the file called COPYING.
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
*
|
*
|
||||||
* BSD LICENSE
|
* BSD LICENSE
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
* in the file called COPYING.
|
* in the file called COPYING.
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
*
|
*
|
||||||
* BSD LICENSE
|
* BSD LICENSE
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
* in the file called COPYING.
|
* in the file called COPYING.
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
*
|
*
|
||||||
* BSD LICENSE
|
* BSD LICENSE
|
||||||
|
|
|
@ -213,6 +213,7 @@ enum {
|
||||||
|
|
||||||
REPLY_RX_PHY_CMD = 0xc0,
|
REPLY_RX_PHY_CMD = 0xc0,
|
||||||
REPLY_RX_MPDU_CMD = 0xc1,
|
REPLY_RX_MPDU_CMD = 0xc1,
|
||||||
|
FRAME_RELEASE = 0xc3,
|
||||||
BA_NOTIF = 0xc5,
|
BA_NOTIF = 0xc5,
|
||||||
|
|
||||||
/* Location Aware Regulatory */
|
/* Location Aware Regulatory */
|
||||||
|
@ -239,6 +240,7 @@ enum {
|
||||||
DTS_MEASUREMENT_NOTIFICATION = 0xdd,
|
DTS_MEASUREMENT_NOTIFICATION = 0xdd,
|
||||||
|
|
||||||
REPLY_DEBUG_CMD = 0xf0,
|
REPLY_DEBUG_CMD = 0xf0,
|
||||||
|
LDBG_CONFIG_CMD = 0xf6,
|
||||||
DEBUG_LOG_MSG = 0xf7,
|
DEBUG_LOG_MSG = 0xf7,
|
||||||
|
|
||||||
BCAST_FILTER_CMD = 0xcf,
|
BCAST_FILTER_CMD = 0xcf,
|
||||||
|
@ -426,6 +428,26 @@ struct iwl_fw_get_item_cmd {
|
||||||
__le32 item_id;
|
__le32 item_id;
|
||||||
} __packed; /* FW_GET_ITEM_CMD_API_S_VER_1 */
|
} __packed; /* FW_GET_ITEM_CMD_API_S_VER_1 */
|
||||||
|
|
||||||
|
#define CONT_REC_COMMAND_SIZE 80
|
||||||
|
#define ENABLE_CONT_RECORDING 0x15
|
||||||
|
#define DISABLE_CONT_RECORDING 0x16
|
||||||
|
|
||||||
|
/*
|
||||||
|
* struct iwl_continuous_record_mode - recording mode
|
||||||
|
*/
|
||||||
|
struct iwl_continuous_record_mode {
|
||||||
|
__le16 enable_recording;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* struct iwl_continuous_record_cmd - enable/disable continuous recording
|
||||||
|
*/
|
||||||
|
struct iwl_continuous_record_cmd {
|
||||||
|
struct iwl_continuous_record_mode record_mode;
|
||||||
|
u8 pad[CONT_REC_COMMAND_SIZE -
|
||||||
|
sizeof(struct iwl_continuous_record_mode)];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
struct iwl_fw_get_item_resp {
|
struct iwl_fw_get_item_resp {
|
||||||
__le32 item_id;
|
__le32 item_id;
|
||||||
__le32 item_byte_cnt;
|
__le32 item_byte_cnt;
|
||||||
|
|
|
@ -0,0 +1,780 @@
|
||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* 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) 2008 - 2014 Intel Corporation. All rights reserved.
|
||||||
|
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||||
|
* Copyright(c) 2015 Intel Deutschland GmbH
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program;
|
||||||
|
*
|
||||||
|
* 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) 2005 - 2014 Intel Corporation. All rights reserved.
|
||||||
|
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||||
|
* Copyright(c) 2015 Intel Deutschland GmbH
|
||||||
|
* 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/devcoredump.h>
|
||||||
|
|
||||||
|
#include "fw-dbg.h"
|
||||||
|
#include "iwl-io.h"
|
||||||
|
#include "mvm.h"
|
||||||
|
#include "iwl-prph.h"
|
||||||
|
#include "iwl-csr.h"
|
||||||
|
|
||||||
|
static ssize_t iwl_mvm_read_coredump(char *buffer, loff_t offset, size_t count,
|
||||||
|
const void *data, size_t datalen)
|
||||||
|
{
|
||||||
|
const struct iwl_mvm_dump_ptrs *dump_ptrs = data;
|
||||||
|
ssize_t bytes_read;
|
||||||
|
ssize_t bytes_read_trans;
|
||||||
|
|
||||||
|
if (offset < dump_ptrs->op_mode_len) {
|
||||||
|
bytes_read = min_t(ssize_t, count,
|
||||||
|
dump_ptrs->op_mode_len - offset);
|
||||||
|
memcpy(buffer, (u8 *)dump_ptrs->op_mode_ptr + offset,
|
||||||
|
bytes_read);
|
||||||
|
offset += bytes_read;
|
||||||
|
count -= bytes_read;
|
||||||
|
|
||||||
|
if (count == 0)
|
||||||
|
return bytes_read;
|
||||||
|
} else {
|
||||||
|
bytes_read = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dump_ptrs->trans_ptr)
|
||||||
|
return bytes_read;
|
||||||
|
|
||||||
|
offset -= dump_ptrs->op_mode_len;
|
||||||
|
bytes_read_trans = min_t(ssize_t, count,
|
||||||
|
dump_ptrs->trans_ptr->len - offset);
|
||||||
|
memcpy(buffer + bytes_read,
|
||||||
|
(u8 *)dump_ptrs->trans_ptr->data + offset,
|
||||||
|
bytes_read_trans);
|
||||||
|
|
||||||
|
return bytes_read + bytes_read_trans;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void iwl_mvm_free_coredump(const void *data)
|
||||||
|
{
|
||||||
|
const struct iwl_mvm_dump_ptrs *fw_error_dump = data;
|
||||||
|
|
||||||
|
vfree(fw_error_dump->op_mode_ptr);
|
||||||
|
vfree(fw_error_dump->trans_ptr);
|
||||||
|
kfree(fw_error_dump);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void iwl_mvm_dump_fifos(struct iwl_mvm *mvm,
|
||||||
|
struct iwl_fw_error_dump_data **dump_data)
|
||||||
|
{
|
||||||
|
struct iwl_fw_error_dump_fifo *fifo_hdr;
|
||||||
|
u32 *fifo_data;
|
||||||
|
u32 fifo_len;
|
||||||
|
unsigned long flags;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
if (!iwl_trans_grab_nic_access(mvm->trans, false, &flags))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Pull RXF data from all RXFs */
|
||||||
|
for (i = 0; i < ARRAY_SIZE(mvm->shared_mem_cfg.rxfifo_size); i++) {
|
||||||
|
/*
|
||||||
|
* Keep aside the additional offset that might be needed for
|
||||||
|
* next RXF
|
||||||
|
*/
|
||||||
|
u32 offset_diff = RXF_DIFF_FROM_PREV * i;
|
||||||
|
|
||||||
|
fifo_hdr = (void *)(*dump_data)->data;
|
||||||
|
fifo_data = (void *)fifo_hdr->data;
|
||||||
|
fifo_len = mvm->shared_mem_cfg.rxfifo_size[i];
|
||||||
|
|
||||||
|
/* No need to try to read the data if the length is 0 */
|
||||||
|
if (fifo_len == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Add a TLV for the RXF */
|
||||||
|
(*dump_data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_RXF);
|
||||||
|
(*dump_data)->len = cpu_to_le32(fifo_len + sizeof(*fifo_hdr));
|
||||||
|
|
||||||
|
fifo_hdr->fifo_num = cpu_to_le32(i);
|
||||||
|
fifo_hdr->available_bytes =
|
||||||
|
cpu_to_le32(iwl_trans_read_prph(mvm->trans,
|
||||||
|
RXF_RD_D_SPACE +
|
||||||
|
offset_diff));
|
||||||
|
fifo_hdr->wr_ptr =
|
||||||
|
cpu_to_le32(iwl_trans_read_prph(mvm->trans,
|
||||||
|
RXF_RD_WR_PTR +
|
||||||
|
offset_diff));
|
||||||
|
fifo_hdr->rd_ptr =
|
||||||
|
cpu_to_le32(iwl_trans_read_prph(mvm->trans,
|
||||||
|
RXF_RD_RD_PTR +
|
||||||
|
offset_diff));
|
||||||
|
fifo_hdr->fence_ptr =
|
||||||
|
cpu_to_le32(iwl_trans_read_prph(mvm->trans,
|
||||||
|
RXF_RD_FENCE_PTR +
|
||||||
|
offset_diff));
|
||||||
|
fifo_hdr->fence_mode =
|
||||||
|
cpu_to_le32(iwl_trans_read_prph(mvm->trans,
|
||||||
|
RXF_SET_FENCE_MODE +
|
||||||
|
offset_diff));
|
||||||
|
|
||||||
|
/* Lock fence */
|
||||||
|
iwl_trans_write_prph(mvm->trans,
|
||||||
|
RXF_SET_FENCE_MODE + offset_diff, 0x1);
|
||||||
|
/* Set fence pointer to the same place like WR pointer */
|
||||||
|
iwl_trans_write_prph(mvm->trans,
|
||||||
|
RXF_LD_WR2FENCE + offset_diff, 0x1);
|
||||||
|
/* Set fence offset */
|
||||||
|
iwl_trans_write_prph(mvm->trans,
|
||||||
|
RXF_LD_FENCE_OFFSET_ADDR + offset_diff,
|
||||||
|
0x0);
|
||||||
|
|
||||||
|
/* Read FIFO */
|
||||||
|
fifo_len /= sizeof(u32); /* Size in DWORDS */
|
||||||
|
for (j = 0; j < fifo_len; j++)
|
||||||
|
fifo_data[j] = iwl_trans_read_prph(mvm->trans,
|
||||||
|
RXF_FIFO_RD_FENCE_INC +
|
||||||
|
offset_diff);
|
||||||
|
*dump_data = iwl_fw_error_next_data(*dump_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pull TXF data from all TXFs */
|
||||||
|
for (i = 0; i < ARRAY_SIZE(mvm->shared_mem_cfg.txfifo_size); i++) {
|
||||||
|
/* Mark the number of TXF we're pulling now */
|
||||||
|
iwl_trans_write_prph(mvm->trans, TXF_LARC_NUM, i);
|
||||||
|
|
||||||
|
fifo_hdr = (void *)(*dump_data)->data;
|
||||||
|
fifo_data = (void *)fifo_hdr->data;
|
||||||
|
fifo_len = mvm->shared_mem_cfg.txfifo_size[i];
|
||||||
|
|
||||||
|
/* No need to try to read the data if the length is 0 */
|
||||||
|
if (fifo_len == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Add a TLV for the FIFO */
|
||||||
|
(*dump_data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_TXF);
|
||||||
|
(*dump_data)->len = cpu_to_le32(fifo_len + sizeof(*fifo_hdr));
|
||||||
|
|
||||||
|
fifo_hdr->fifo_num = cpu_to_le32(i);
|
||||||
|
fifo_hdr->available_bytes =
|
||||||
|
cpu_to_le32(iwl_trans_read_prph(mvm->trans,
|
||||||
|
TXF_FIFO_ITEM_CNT));
|
||||||
|
fifo_hdr->wr_ptr =
|
||||||
|
cpu_to_le32(iwl_trans_read_prph(mvm->trans,
|
||||||
|
TXF_WR_PTR));
|
||||||
|
fifo_hdr->rd_ptr =
|
||||||
|
cpu_to_le32(iwl_trans_read_prph(mvm->trans,
|
||||||
|
TXF_RD_PTR));
|
||||||
|
fifo_hdr->fence_ptr =
|
||||||
|
cpu_to_le32(iwl_trans_read_prph(mvm->trans,
|
||||||
|
TXF_FENCE_PTR));
|
||||||
|
fifo_hdr->fence_mode =
|
||||||
|
cpu_to_le32(iwl_trans_read_prph(mvm->trans,
|
||||||
|
TXF_LOCK_FENCE));
|
||||||
|
|
||||||
|
/* Set the TXF_READ_MODIFY_ADDR to TXF_WR_PTR */
|
||||||
|
iwl_trans_write_prph(mvm->trans, TXF_READ_MODIFY_ADDR,
|
||||||
|
TXF_WR_PTR);
|
||||||
|
|
||||||
|
/* Dummy-read to advance the read pointer to the head */
|
||||||
|
iwl_trans_read_prph(mvm->trans, TXF_READ_MODIFY_DATA);
|
||||||
|
|
||||||
|
/* Read FIFO */
|
||||||
|
fifo_len /= sizeof(u32); /* Size in DWORDS */
|
||||||
|
for (j = 0; j < fifo_len; j++)
|
||||||
|
fifo_data[j] = iwl_trans_read_prph(mvm->trans,
|
||||||
|
TXF_READ_MODIFY_DATA);
|
||||||
|
*dump_data = iwl_fw_error_next_data(*dump_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
iwl_trans_release_nic_access(mvm->trans, &flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
void iwl_mvm_free_fw_dump_desc(struct iwl_mvm *mvm)
|
||||||
|
{
|
||||||
|
if (mvm->fw_dump_desc == &iwl_mvm_dump_desc_assert ||
|
||||||
|
!mvm->fw_dump_desc)
|
||||||
|
return;
|
||||||
|
|
||||||
|
kfree(mvm->fw_dump_desc);
|
||||||
|
mvm->fw_dump_desc = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define IWL8260_ICCM_OFFSET 0x44000 /* Only for B-step */
|
||||||
|
#define IWL8260_ICCM_LEN 0xC000 /* Only for B-step */
|
||||||
|
|
||||||
|
static const struct {
|
||||||
|
u32 start, end;
|
||||||
|
} iwl_prph_dump_addr[] = {
|
||||||
|
{ .start = 0x00a00000, .end = 0x00a00000 },
|
||||||
|
{ .start = 0x00a0000c, .end = 0x00a00024 },
|
||||||
|
{ .start = 0x00a0002c, .end = 0x00a0003c },
|
||||||
|
{ .start = 0x00a00410, .end = 0x00a00418 },
|
||||||
|
{ .start = 0x00a00420, .end = 0x00a00420 },
|
||||||
|
{ .start = 0x00a00428, .end = 0x00a00428 },
|
||||||
|
{ .start = 0x00a00430, .end = 0x00a0043c },
|
||||||
|
{ .start = 0x00a00444, .end = 0x00a00444 },
|
||||||
|
{ .start = 0x00a004c0, .end = 0x00a004cc },
|
||||||
|
{ .start = 0x00a004d8, .end = 0x00a004d8 },
|
||||||
|
{ .start = 0x00a004e0, .end = 0x00a004f0 },
|
||||||
|
{ .start = 0x00a00840, .end = 0x00a00840 },
|
||||||
|
{ .start = 0x00a00850, .end = 0x00a00858 },
|
||||||
|
{ .start = 0x00a01004, .end = 0x00a01008 },
|
||||||
|
{ .start = 0x00a01010, .end = 0x00a01010 },
|
||||||
|
{ .start = 0x00a01018, .end = 0x00a01018 },
|
||||||
|
{ .start = 0x00a01024, .end = 0x00a01024 },
|
||||||
|
{ .start = 0x00a0102c, .end = 0x00a01034 },
|
||||||
|
{ .start = 0x00a0103c, .end = 0x00a01040 },
|
||||||
|
{ .start = 0x00a01048, .end = 0x00a01094 },
|
||||||
|
{ .start = 0x00a01c00, .end = 0x00a01c20 },
|
||||||
|
{ .start = 0x00a01c58, .end = 0x00a01c58 },
|
||||||
|
{ .start = 0x00a01c7c, .end = 0x00a01c7c },
|
||||||
|
{ .start = 0x00a01c28, .end = 0x00a01c54 },
|
||||||
|
{ .start = 0x00a01c5c, .end = 0x00a01c5c },
|
||||||
|
{ .start = 0x00a01c60, .end = 0x00a01cdc },
|
||||||
|
{ .start = 0x00a01ce0, .end = 0x00a01d0c },
|
||||||
|
{ .start = 0x00a01d18, .end = 0x00a01d20 },
|
||||||
|
{ .start = 0x00a01d2c, .end = 0x00a01d30 },
|
||||||
|
{ .start = 0x00a01d40, .end = 0x00a01d5c },
|
||||||
|
{ .start = 0x00a01d80, .end = 0x00a01d80 },
|
||||||
|
{ .start = 0x00a01d98, .end = 0x00a01d9c },
|
||||||
|
{ .start = 0x00a01da8, .end = 0x00a01da8 },
|
||||||
|
{ .start = 0x00a01db8, .end = 0x00a01df4 },
|
||||||
|
{ .start = 0x00a01dc0, .end = 0x00a01dfc },
|
||||||
|
{ .start = 0x00a01e00, .end = 0x00a01e2c },
|
||||||
|
{ .start = 0x00a01e40, .end = 0x00a01e60 },
|
||||||
|
{ .start = 0x00a01e68, .end = 0x00a01e6c },
|
||||||
|
{ .start = 0x00a01e74, .end = 0x00a01e74 },
|
||||||
|
{ .start = 0x00a01e84, .end = 0x00a01e90 },
|
||||||
|
{ .start = 0x00a01e9c, .end = 0x00a01ec4 },
|
||||||
|
{ .start = 0x00a01ed0, .end = 0x00a01ee0 },
|
||||||
|
{ .start = 0x00a01f00, .end = 0x00a01f1c },
|
||||||
|
{ .start = 0x00a01f44, .end = 0x00a01ffc },
|
||||||
|
{ .start = 0x00a02000, .end = 0x00a02048 },
|
||||||
|
{ .start = 0x00a02068, .end = 0x00a020f0 },
|
||||||
|
{ .start = 0x00a02100, .end = 0x00a02118 },
|
||||||
|
{ .start = 0x00a02140, .end = 0x00a0214c },
|
||||||
|
{ .start = 0x00a02168, .end = 0x00a0218c },
|
||||||
|
{ .start = 0x00a021c0, .end = 0x00a021c0 },
|
||||||
|
{ .start = 0x00a02400, .end = 0x00a02410 },
|
||||||
|
{ .start = 0x00a02418, .end = 0x00a02420 },
|
||||||
|
{ .start = 0x00a02428, .end = 0x00a0242c },
|
||||||
|
{ .start = 0x00a02434, .end = 0x00a02434 },
|
||||||
|
{ .start = 0x00a02440, .end = 0x00a02460 },
|
||||||
|
{ .start = 0x00a02468, .end = 0x00a024b0 },
|
||||||
|
{ .start = 0x00a024c8, .end = 0x00a024cc },
|
||||||
|
{ .start = 0x00a02500, .end = 0x00a02504 },
|
||||||
|
{ .start = 0x00a0250c, .end = 0x00a02510 },
|
||||||
|
{ .start = 0x00a02540, .end = 0x00a02554 },
|
||||||
|
{ .start = 0x00a02580, .end = 0x00a025f4 },
|
||||||
|
{ .start = 0x00a02600, .end = 0x00a0260c },
|
||||||
|
{ .start = 0x00a02648, .end = 0x00a02650 },
|
||||||
|
{ .start = 0x00a02680, .end = 0x00a02680 },
|
||||||
|
{ .start = 0x00a026c0, .end = 0x00a026d0 },
|
||||||
|
{ .start = 0x00a02700, .end = 0x00a0270c },
|
||||||
|
{ .start = 0x00a02804, .end = 0x00a02804 },
|
||||||
|
{ .start = 0x00a02818, .end = 0x00a0281c },
|
||||||
|
{ .start = 0x00a02c00, .end = 0x00a02db4 },
|
||||||
|
{ .start = 0x00a02df4, .end = 0x00a02fb0 },
|
||||||
|
{ .start = 0x00a03000, .end = 0x00a03014 },
|
||||||
|
{ .start = 0x00a0301c, .end = 0x00a0302c },
|
||||||
|
{ .start = 0x00a03034, .end = 0x00a03038 },
|
||||||
|
{ .start = 0x00a03040, .end = 0x00a03048 },
|
||||||
|
{ .start = 0x00a03060, .end = 0x00a03068 },
|
||||||
|
{ .start = 0x00a03070, .end = 0x00a03074 },
|
||||||
|
{ .start = 0x00a0307c, .end = 0x00a0307c },
|
||||||
|
{ .start = 0x00a03080, .end = 0x00a03084 },
|
||||||
|
{ .start = 0x00a0308c, .end = 0x00a03090 },
|
||||||
|
{ .start = 0x00a03098, .end = 0x00a03098 },
|
||||||
|
{ .start = 0x00a030a0, .end = 0x00a030a0 },
|
||||||
|
{ .start = 0x00a030a8, .end = 0x00a030b4 },
|
||||||
|
{ .start = 0x00a030bc, .end = 0x00a030bc },
|
||||||
|
{ .start = 0x00a030c0, .end = 0x00a0312c },
|
||||||
|
{ .start = 0x00a03c00, .end = 0x00a03c5c },
|
||||||
|
{ .start = 0x00a04400, .end = 0x00a04454 },
|
||||||
|
{ .start = 0x00a04460, .end = 0x00a04474 },
|
||||||
|
{ .start = 0x00a044c0, .end = 0x00a044ec },
|
||||||
|
{ .start = 0x00a04500, .end = 0x00a04504 },
|
||||||
|
{ .start = 0x00a04510, .end = 0x00a04538 },
|
||||||
|
{ .start = 0x00a04540, .end = 0x00a04548 },
|
||||||
|
{ .start = 0x00a04560, .end = 0x00a0457c },
|
||||||
|
{ .start = 0x00a04590, .end = 0x00a04598 },
|
||||||
|
{ .start = 0x00a045c0, .end = 0x00a045f4 },
|
||||||
|
};
|
||||||
|
|
||||||
|
static u32 iwl_dump_prph(struct iwl_trans *trans,
|
||||||
|
struct iwl_fw_error_dump_data **data)
|
||||||
|
{
|
||||||
|
struct iwl_fw_error_dump_prph *prph;
|
||||||
|
unsigned long flags;
|
||||||
|
u32 prph_len = 0, i;
|
||||||
|
|
||||||
|
if (!iwl_trans_grab_nic_access(trans, false, &flags))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(iwl_prph_dump_addr); i++) {
|
||||||
|
/* The range includes both boundaries */
|
||||||
|
int num_bytes_in_chunk = iwl_prph_dump_addr[i].end -
|
||||||
|
iwl_prph_dump_addr[i].start + 4;
|
||||||
|
int reg;
|
||||||
|
__le32 *val;
|
||||||
|
|
||||||
|
prph_len += sizeof(**data) + sizeof(*prph) + num_bytes_in_chunk;
|
||||||
|
|
||||||
|
(*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PRPH);
|
||||||
|
(*data)->len = cpu_to_le32(sizeof(*prph) +
|
||||||
|
num_bytes_in_chunk);
|
||||||
|
prph = (void *)(*data)->data;
|
||||||
|
prph->prph_start = cpu_to_le32(iwl_prph_dump_addr[i].start);
|
||||||
|
val = (void *)prph->data;
|
||||||
|
|
||||||
|
for (reg = iwl_prph_dump_addr[i].start;
|
||||||
|
reg <= iwl_prph_dump_addr[i].end;
|
||||||
|
reg += 4)
|
||||||
|
*val++ = cpu_to_le32(iwl_read_prph_no_grab(trans,
|
||||||
|
reg));
|
||||||
|
|
||||||
|
*data = iwl_fw_error_next_data(*data);
|
||||||
|
}
|
||||||
|
|
||||||
|
iwl_trans_release_nic_access(trans, &flags);
|
||||||
|
|
||||||
|
return prph_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
|
||||||
|
{
|
||||||
|
struct iwl_fw_error_dump_file *dump_file;
|
||||||
|
struct iwl_fw_error_dump_data *dump_data;
|
||||||
|
struct iwl_fw_error_dump_info *dump_info;
|
||||||
|
struct iwl_fw_error_dump_mem *dump_mem;
|
||||||
|
struct iwl_fw_error_dump_trigger_desc *dump_trig;
|
||||||
|
struct iwl_mvm_dump_ptrs *fw_error_dump;
|
||||||
|
u32 sram_len, sram_ofs;
|
||||||
|
u32 file_len, fifo_data_len = 0;
|
||||||
|
u32 smem_len = mvm->cfg->smem_len;
|
||||||
|
u32 sram2_len = mvm->cfg->dccm2_len;
|
||||||
|
bool monitor_dump_only = false;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
lockdep_assert_held(&mvm->mutex);
|
||||||
|
|
||||||
|
/* there's no point in fw dump if the bus is dead */
|
||||||
|
if (test_bit(STATUS_TRANS_DEAD, &mvm->trans->status)) {
|
||||||
|
IWL_ERR(mvm, "Skip fw error dump since bus is dead\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mvm->fw_dump_trig &&
|
||||||
|
mvm->fw_dump_trig->mode & IWL_FW_DBG_TRIGGER_MONITOR_ONLY)
|
||||||
|
monitor_dump_only = true;
|
||||||
|
|
||||||
|
fw_error_dump = kzalloc(sizeof(*fw_error_dump), GFP_KERNEL);
|
||||||
|
if (!fw_error_dump)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* SRAM - include stack CCM if driver knows the values for it */
|
||||||
|
if (!mvm->cfg->dccm_offset || !mvm->cfg->dccm_len) {
|
||||||
|
const struct fw_img *img;
|
||||||
|
|
||||||
|
img = &mvm->fw->img[mvm->cur_ucode];
|
||||||
|
sram_ofs = img->sec[IWL_UCODE_SECTION_DATA].offset;
|
||||||
|
sram_len = img->sec[IWL_UCODE_SECTION_DATA].len;
|
||||||
|
} else {
|
||||||
|
sram_ofs = mvm->cfg->dccm_offset;
|
||||||
|
sram_len = mvm->cfg->dccm_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* reading RXF/TXF sizes */
|
||||||
|
if (test_bit(STATUS_FW_ERROR, &mvm->trans->status)) {
|
||||||
|
struct iwl_mvm_shared_mem_cfg *mem_cfg = &mvm->shared_mem_cfg;
|
||||||
|
|
||||||
|
fifo_data_len = 0;
|
||||||
|
|
||||||
|
/* Count RXF size */
|
||||||
|
for (i = 0; i < ARRAY_SIZE(mem_cfg->rxfifo_size); i++) {
|
||||||
|
if (!mem_cfg->rxfifo_size[i])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Add header info */
|
||||||
|
fifo_data_len += mem_cfg->rxfifo_size[i] +
|
||||||
|
sizeof(*dump_data) +
|
||||||
|
sizeof(struct iwl_fw_error_dump_fifo);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(mem_cfg->txfifo_size); i++) {
|
||||||
|
if (!mem_cfg->txfifo_size[i])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Add header info */
|
||||||
|
fifo_data_len += mem_cfg->txfifo_size[i] +
|
||||||
|
sizeof(*dump_data) +
|
||||||
|
sizeof(struct iwl_fw_error_dump_fifo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
file_len = sizeof(*dump_file) +
|
||||||
|
sizeof(*dump_data) * 2 +
|
||||||
|
sram_len + sizeof(*dump_mem) +
|
||||||
|
fifo_data_len +
|
||||||
|
sizeof(*dump_info);
|
||||||
|
|
||||||
|
/* Make room for the SMEM, if it exists */
|
||||||
|
if (smem_len)
|
||||||
|
file_len += sizeof(*dump_data) + sizeof(*dump_mem) + smem_len;
|
||||||
|
|
||||||
|
/* Make room for the secondary SRAM, if it exists */
|
||||||
|
if (sram2_len)
|
||||||
|
file_len += sizeof(*dump_data) + sizeof(*dump_mem) + sram2_len;
|
||||||
|
|
||||||
|
/* Make room for fw's virtual image pages, if it exists */
|
||||||
|
if (mvm->fw->img[mvm->cur_ucode].paging_mem_size)
|
||||||
|
file_len += mvm->num_of_paging_blk *
|
||||||
|
(sizeof(*dump_data) +
|
||||||
|
sizeof(struct iwl_fw_error_dump_paging) +
|
||||||
|
PAGING_BLOCK_SIZE);
|
||||||
|
|
||||||
|
/* If we only want a monitor dump, reset the file length */
|
||||||
|
if (monitor_dump_only) {
|
||||||
|
file_len = sizeof(*dump_file) + sizeof(*dump_data) +
|
||||||
|
sizeof(*dump_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make room for PRPH registers */
|
||||||
|
for (i = 0; i < ARRAY_SIZE(iwl_prph_dump_addr); i++) {
|
||||||
|
/* The range includes both boundaries */
|
||||||
|
int num_bytes_in_chunk = iwl_prph_dump_addr[i].end -
|
||||||
|
iwl_prph_dump_addr[i].start + 4;
|
||||||
|
|
||||||
|
file_len += sizeof(*dump_data) +
|
||||||
|
sizeof(struct iwl_fw_error_dump_prph) +
|
||||||
|
num_bytes_in_chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In 8000 HW family B-step include the ICCM (which resides separately)
|
||||||
|
*/
|
||||||
|
if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_8000 &&
|
||||||
|
CSR_HW_REV_STEP(mvm->trans->hw_rev) == SILICON_B_STEP)
|
||||||
|
file_len += sizeof(*dump_data) + sizeof(*dump_mem) +
|
||||||
|
IWL8260_ICCM_LEN;
|
||||||
|
|
||||||
|
if (mvm->fw_dump_desc)
|
||||||
|
file_len += sizeof(*dump_data) + sizeof(*dump_trig) +
|
||||||
|
mvm->fw_dump_desc->len;
|
||||||
|
|
||||||
|
dump_file = vzalloc(file_len);
|
||||||
|
if (!dump_file) {
|
||||||
|
kfree(fw_error_dump);
|
||||||
|
iwl_mvm_free_fw_dump_desc(mvm);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fw_error_dump->op_mode_ptr = dump_file;
|
||||||
|
|
||||||
|
dump_file->barker = cpu_to_le32(IWL_FW_ERROR_DUMP_BARKER);
|
||||||
|
dump_data = (void *)dump_file->data;
|
||||||
|
|
||||||
|
dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_DEV_FW_INFO);
|
||||||
|
dump_data->len = cpu_to_le32(sizeof(*dump_info));
|
||||||
|
dump_info = (void *)dump_data->data;
|
||||||
|
dump_info->device_family =
|
||||||
|
mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000 ?
|
||||||
|
cpu_to_le32(IWL_FW_ERROR_DUMP_FAMILY_7) :
|
||||||
|
cpu_to_le32(IWL_FW_ERROR_DUMP_FAMILY_8);
|
||||||
|
dump_info->hw_step = cpu_to_le32(CSR_HW_REV_STEP(mvm->trans->hw_rev));
|
||||||
|
memcpy(dump_info->fw_human_readable, mvm->fw->human_readable,
|
||||||
|
sizeof(dump_info->fw_human_readable));
|
||||||
|
strncpy(dump_info->dev_human_readable, mvm->cfg->name,
|
||||||
|
sizeof(dump_info->dev_human_readable));
|
||||||
|
strncpy(dump_info->bus_human_readable, mvm->dev->bus->name,
|
||||||
|
sizeof(dump_info->bus_human_readable));
|
||||||
|
|
||||||
|
dump_data = iwl_fw_error_next_data(dump_data);
|
||||||
|
/* We only dump the FIFOs if the FW is in error state */
|
||||||
|
if (test_bit(STATUS_FW_ERROR, &mvm->trans->status))
|
||||||
|
iwl_mvm_dump_fifos(mvm, &dump_data);
|
||||||
|
|
||||||
|
if (mvm->fw_dump_desc) {
|
||||||
|
dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_ERROR_INFO);
|
||||||
|
dump_data->len = cpu_to_le32(sizeof(*dump_trig) +
|
||||||
|
mvm->fw_dump_desc->len);
|
||||||
|
dump_trig = (void *)dump_data->data;
|
||||||
|
memcpy(dump_trig, &mvm->fw_dump_desc->trig_desc,
|
||||||
|
sizeof(*dump_trig) + mvm->fw_dump_desc->len);
|
||||||
|
|
||||||
|
/* now we can free this copy */
|
||||||
|
iwl_mvm_free_fw_dump_desc(mvm);
|
||||||
|
dump_data = iwl_fw_error_next_data(dump_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* In case we only want monitor dump, skip to dump trasport data */
|
||||||
|
if (monitor_dump_only)
|
||||||
|
goto dump_trans_data;
|
||||||
|
|
||||||
|
dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM);
|
||||||
|
dump_data->len = cpu_to_le32(sram_len + sizeof(*dump_mem));
|
||||||
|
dump_mem = (void *)dump_data->data;
|
||||||
|
dump_mem->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM_SRAM);
|
||||||
|
dump_mem->offset = cpu_to_le32(sram_ofs);
|
||||||
|
iwl_trans_read_mem_bytes(mvm->trans, sram_ofs, dump_mem->data,
|
||||||
|
sram_len);
|
||||||
|
|
||||||
|
if (smem_len) {
|
||||||
|
dump_data = iwl_fw_error_next_data(dump_data);
|
||||||
|
dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM);
|
||||||
|
dump_data->len = cpu_to_le32(smem_len + sizeof(*dump_mem));
|
||||||
|
dump_mem = (void *)dump_data->data;
|
||||||
|
dump_mem->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM_SMEM);
|
||||||
|
dump_mem->offset = cpu_to_le32(mvm->cfg->smem_offset);
|
||||||
|
iwl_trans_read_mem_bytes(mvm->trans, mvm->cfg->smem_offset,
|
||||||
|
dump_mem->data, smem_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sram2_len) {
|
||||||
|
dump_data = iwl_fw_error_next_data(dump_data);
|
||||||
|
dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM);
|
||||||
|
dump_data->len = cpu_to_le32(sram2_len + sizeof(*dump_mem));
|
||||||
|
dump_mem = (void *)dump_data->data;
|
||||||
|
dump_mem->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM_SRAM);
|
||||||
|
dump_mem->offset = cpu_to_le32(mvm->cfg->dccm2_offset);
|
||||||
|
iwl_trans_read_mem_bytes(mvm->trans, mvm->cfg->dccm2_offset,
|
||||||
|
dump_mem->data, sram2_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_8000 &&
|
||||||
|
CSR_HW_REV_STEP(mvm->trans->hw_rev) == SILICON_B_STEP) {
|
||||||
|
dump_data = iwl_fw_error_next_data(dump_data);
|
||||||
|
dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM);
|
||||||
|
dump_data->len = cpu_to_le32(IWL8260_ICCM_LEN +
|
||||||
|
sizeof(*dump_mem));
|
||||||
|
dump_mem = (void *)dump_data->data;
|
||||||
|
dump_mem->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM_SRAM);
|
||||||
|
dump_mem->offset = cpu_to_le32(IWL8260_ICCM_OFFSET);
|
||||||
|
iwl_trans_read_mem_bytes(mvm->trans, IWL8260_ICCM_OFFSET,
|
||||||
|
dump_mem->data, IWL8260_ICCM_LEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dump fw's virtual image */
|
||||||
|
if (mvm->fw->img[mvm->cur_ucode].paging_mem_size) {
|
||||||
|
u32 i;
|
||||||
|
|
||||||
|
for (i = 1; i < mvm->num_of_paging_blk + 1; i++) {
|
||||||
|
struct iwl_fw_error_dump_paging *paging;
|
||||||
|
struct page *pages =
|
||||||
|
mvm->fw_paging_db[i].fw_paging_block;
|
||||||
|
|
||||||
|
dump_data = iwl_fw_error_next_data(dump_data);
|
||||||
|
dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PAGING);
|
||||||
|
dump_data->len = cpu_to_le32(sizeof(*paging) +
|
||||||
|
PAGING_BLOCK_SIZE);
|
||||||
|
paging = (void *)dump_data->data;
|
||||||
|
paging->index = cpu_to_le32(i);
|
||||||
|
memcpy(paging->data, page_address(pages),
|
||||||
|
PAGING_BLOCK_SIZE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dump_data = iwl_fw_error_next_data(dump_data);
|
||||||
|
iwl_dump_prph(mvm->trans, &dump_data);
|
||||||
|
|
||||||
|
dump_trans_data:
|
||||||
|
fw_error_dump->trans_ptr = iwl_trans_dump_data(mvm->trans,
|
||||||
|
mvm->fw_dump_trig);
|
||||||
|
fw_error_dump->op_mode_len = file_len;
|
||||||
|
if (fw_error_dump->trans_ptr)
|
||||||
|
file_len += fw_error_dump->trans_ptr->len;
|
||||||
|
dump_file->file_len = cpu_to_le32(file_len);
|
||||||
|
|
||||||
|
dev_coredumpm(mvm->trans->dev, THIS_MODULE, fw_error_dump, 0,
|
||||||
|
GFP_KERNEL, iwl_mvm_read_coredump, iwl_mvm_free_coredump);
|
||||||
|
|
||||||
|
mvm->fw_dump_trig = NULL;
|
||||||
|
clear_bit(IWL_MVM_STATUS_DUMPING_FW_LOG, &mvm->status);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct iwl_mvm_dump_desc iwl_mvm_dump_desc_assert = {
|
||||||
|
.trig_desc = {
|
||||||
|
.type = cpu_to_le32(FW_DBG_TRIGGER_FW_ASSERT),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
int iwl_mvm_fw_dbg_collect_desc(struct iwl_mvm *mvm,
|
||||||
|
struct iwl_mvm_dump_desc *desc,
|
||||||
|
struct iwl_fw_dbg_trigger_tlv *trigger)
|
||||||
|
{
|
||||||
|
unsigned int delay = 0;
|
||||||
|
|
||||||
|
if (trigger)
|
||||||
|
delay = msecs_to_jiffies(le32_to_cpu(trigger->stop_delay));
|
||||||
|
|
||||||
|
if (test_and_set_bit(IWL_MVM_STATUS_DUMPING_FW_LOG, &mvm->status))
|
||||||
|
return -EBUSY;
|
||||||
|
|
||||||
|
if (WARN_ON(mvm->fw_dump_desc))
|
||||||
|
iwl_mvm_free_fw_dump_desc(mvm);
|
||||||
|
|
||||||
|
IWL_WARN(mvm, "Collecting data: trigger %d fired.\n",
|
||||||
|
le32_to_cpu(desc->trig_desc.type));
|
||||||
|
|
||||||
|
mvm->fw_dump_desc = desc;
|
||||||
|
mvm->fw_dump_trig = trigger;
|
||||||
|
|
||||||
|
queue_delayed_work(system_wq, &mvm->fw_dump_wk, delay);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int iwl_mvm_fw_dbg_collect(struct iwl_mvm *mvm, enum iwl_fw_dbg_trigger trig,
|
||||||
|
const char *str, size_t len,
|
||||||
|
struct iwl_fw_dbg_trigger_tlv *trigger)
|
||||||
|
{
|
||||||
|
struct iwl_mvm_dump_desc *desc;
|
||||||
|
|
||||||
|
desc = kzalloc(sizeof(*desc) + len, GFP_ATOMIC);
|
||||||
|
if (!desc)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
desc->len = len;
|
||||||
|
desc->trig_desc.type = cpu_to_le32(trig);
|
||||||
|
memcpy(desc->trig_desc.data, str, len);
|
||||||
|
|
||||||
|
return iwl_mvm_fw_dbg_collect_desc(mvm, desc, trigger);
|
||||||
|
}
|
||||||
|
|
||||||
|
int iwl_mvm_fw_dbg_collect_trig(struct iwl_mvm *mvm,
|
||||||
|
struct iwl_fw_dbg_trigger_tlv *trigger,
|
||||||
|
const char *fmt, ...)
|
||||||
|
{
|
||||||
|
u16 occurrences = le16_to_cpu(trigger->occurrences);
|
||||||
|
int ret, len = 0;
|
||||||
|
char buf[64];
|
||||||
|
|
||||||
|
if (!occurrences)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (fmt) {
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
buf[sizeof(buf) - 1] = '\0';
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
/* check for truncation */
|
||||||
|
if (WARN_ON_ONCE(buf[sizeof(buf) - 1]))
|
||||||
|
buf[sizeof(buf) - 1] = '\0';
|
||||||
|
|
||||||
|
len = strlen(buf) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = iwl_mvm_fw_dbg_collect(mvm, le32_to_cpu(trigger->id), buf, len,
|
||||||
|
trigger);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
trigger->occurrences = cpu_to_le16(occurrences - 1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void iwl_mvm_restart_early_start(struct iwl_mvm *mvm)
|
||||||
|
{
|
||||||
|
if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000)
|
||||||
|
iwl_clear_bits_prph(mvm->trans, MON_BUFF_SAMPLE_CTL, 0x100);
|
||||||
|
else
|
||||||
|
iwl_write_prph(mvm->trans, DBGC_IN_SAMPLE, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int iwl_mvm_start_fw_dbg_conf(struct iwl_mvm *mvm, u8 conf_id)
|
||||||
|
{
|
||||||
|
u8 *ptr;
|
||||||
|
int ret;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (WARN_ONCE(conf_id >= ARRAY_SIZE(mvm->fw->dbg_conf_tlv),
|
||||||
|
"Invalid configuration %d\n", conf_id))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* EARLY START - firmware's configuration is hard coded */
|
||||||
|
if ((!mvm->fw->dbg_conf_tlv[conf_id] ||
|
||||||
|
!mvm->fw->dbg_conf_tlv[conf_id]->num_of_hcmds) &&
|
||||||
|
conf_id == FW_DBG_START_FROM_ALIVE) {
|
||||||
|
iwl_mvm_restart_early_start(mvm);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mvm->fw->dbg_conf_tlv[conf_id])
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (mvm->fw_dbg_conf != FW_DBG_INVALID)
|
||||||
|
IWL_WARN(mvm, "FW already configured (%d) - re-configuring\n",
|
||||||
|
mvm->fw_dbg_conf);
|
||||||
|
|
||||||
|
/* Send all HCMDs for configuring the FW debug */
|
||||||
|
ptr = (void *)&mvm->fw->dbg_conf_tlv[conf_id]->hcmd;
|
||||||
|
for (i = 0; i < mvm->fw->dbg_conf_tlv[conf_id]->num_of_hcmds; i++) {
|
||||||
|
struct iwl_fw_dbg_conf_hcmd *cmd = (void *)ptr;
|
||||||
|
|
||||||
|
ret = iwl_mvm_send_cmd_pdu(mvm, cmd->id, 0,
|
||||||
|
le16_to_cpu(cmd->len), cmd->data);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ptr += sizeof(*cmd);
|
||||||
|
ptr += le16_to_cpu(cmd->len);
|
||||||
|
}
|
||||||
|
|
||||||
|
mvm->fw_dbg_conf = conf_id;
|
||||||
|
return ret;
|
||||||
|
}
|
|
@ -0,0 +1,150 @@
|
||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* 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) 2008 - 2014 Intel Corporation. All rights reserved.
|
||||||
|
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||||
|
* Copyright(c) 2015 Intel Deutschland GmbH
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program;
|
||||||
|
*
|
||||||
|
* 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) 2005 - 2014 Intel Corporation. All rights reserved.
|
||||||
|
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||||
|
* Copyright(c) 2015 Intel Deutschland GmbH
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef __mvm_fw_dbg_h__
|
||||||
|
#define __mvm_fw_dbg_h__
|
||||||
|
#include "iwl-fw-file.h"
|
||||||
|
#include "iwl-fw-error-dump.h"
|
||||||
|
#include "mvm.h"
|
||||||
|
|
||||||
|
void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm);
|
||||||
|
void iwl_mvm_free_fw_dump_desc(struct iwl_mvm *mvm);
|
||||||
|
int iwl_mvm_fw_dbg_collect_desc(struct iwl_mvm *mvm,
|
||||||
|
struct iwl_mvm_dump_desc *desc,
|
||||||
|
struct iwl_fw_dbg_trigger_tlv *trigger);
|
||||||
|
int iwl_mvm_fw_dbg_collect(struct iwl_mvm *mvm, enum iwl_fw_dbg_trigger trig,
|
||||||
|
const char *str, size_t len,
|
||||||
|
struct iwl_fw_dbg_trigger_tlv *trigger);
|
||||||
|
int iwl_mvm_fw_dbg_collect_trig(struct iwl_mvm *mvm,
|
||||||
|
struct iwl_fw_dbg_trigger_tlv *trigger,
|
||||||
|
const char *fmt, ...) __printf(3, 4);
|
||||||
|
int iwl_mvm_start_fw_dbg_conf(struct iwl_mvm *mvm, u8 id);
|
||||||
|
|
||||||
|
#define iwl_fw_dbg_trigger_enabled(fw, id) ({ \
|
||||||
|
void *__dbg_trigger = (fw)->dbg_trigger_tlv[(id)]; \
|
||||||
|
unlikely(__dbg_trigger); \
|
||||||
|
})
|
||||||
|
|
||||||
|
static inline struct iwl_fw_dbg_trigger_tlv*
|
||||||
|
_iwl_fw_dbg_get_trigger(const struct iwl_fw *fw, enum iwl_fw_dbg_trigger id)
|
||||||
|
{
|
||||||
|
return fw->dbg_trigger_tlv[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
#define iwl_fw_dbg_get_trigger(fw, id) ({ \
|
||||||
|
BUILD_BUG_ON(!__builtin_constant_p(id)); \
|
||||||
|
BUILD_BUG_ON((id) >= FW_DBG_TRIGGER_MAX); \
|
||||||
|
_iwl_fw_dbg_get_trigger((fw), (id)); \
|
||||||
|
})
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
iwl_fw_dbg_trigger_vif_match(struct iwl_fw_dbg_trigger_tlv *trig,
|
||||||
|
struct ieee80211_vif *vif)
|
||||||
|
{
|
||||||
|
u32 trig_vif = le32_to_cpu(trig->vif_type);
|
||||||
|
|
||||||
|
return trig_vif == IWL_FW_DBG_CONF_VIF_ANY || vif->type == trig_vif;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
iwl_fw_dbg_trigger_stop_conf_match(struct iwl_mvm *mvm,
|
||||||
|
struct iwl_fw_dbg_trigger_tlv *trig)
|
||||||
|
{
|
||||||
|
return ((trig->mode & IWL_FW_DBG_TRIGGER_STOP) &&
|
||||||
|
(mvm->fw_dbg_conf == FW_DBG_INVALID ||
|
||||||
|
(BIT(mvm->fw_dbg_conf) & le32_to_cpu(trig->stop_conf_ids))));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
iwl_fw_dbg_trigger_check_stop(struct iwl_mvm *mvm,
|
||||||
|
struct ieee80211_vif *vif,
|
||||||
|
struct iwl_fw_dbg_trigger_tlv *trig)
|
||||||
|
{
|
||||||
|
if (vif && !iwl_fw_dbg_trigger_vif_match(trig, vif))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return iwl_fw_dbg_trigger_stop_conf_match(mvm, trig);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
_iwl_fw_dbg_trigger_simple_stop(struct iwl_mvm *mvm,
|
||||||
|
struct ieee80211_vif *vif,
|
||||||
|
struct iwl_fw_dbg_trigger_tlv *trigger)
|
||||||
|
{
|
||||||
|
if (!trigger)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!iwl_fw_dbg_trigger_check_stop(mvm, vif, trigger))
|
||||||
|
return;
|
||||||
|
|
||||||
|
iwl_mvm_fw_dbg_collect_trig(mvm, trigger, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define iwl_fw_dbg_trigger_simple_stop(mvm, vif, trig) \
|
||||||
|
_iwl_fw_dbg_trigger_simple_stop((mvm), (vif), \
|
||||||
|
iwl_fw_dbg_get_trigger((mvm)->fw,\
|
||||||
|
(trig)))
|
||||||
|
|
||||||
|
#endif /* __mvm_fw_dbg_h__ */
|
|
@ -74,6 +74,7 @@
|
||||||
#include "iwl-eeprom-parse.h"
|
#include "iwl-eeprom-parse.h"
|
||||||
|
|
||||||
#include "mvm.h"
|
#include "mvm.h"
|
||||||
|
#include "fw-dbg.h"
|
||||||
#include "iwl-phy-db.h"
|
#include "iwl-phy-db.h"
|
||||||
|
|
||||||
#define MVM_UCODE_ALIVE_TIMEOUT HZ
|
#define MVM_UCODE_ALIVE_TIMEOUT HZ
|
||||||
|
@ -805,137 +806,6 @@ static void iwl_mvm_get_shared_mem_conf(struct iwl_mvm *mvm)
|
||||||
iwl_free_resp(&cmd);
|
iwl_free_resp(&cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
int iwl_mvm_fw_dbg_collect_desc(struct iwl_mvm *mvm,
|
|
||||||
struct iwl_mvm_dump_desc *desc,
|
|
||||||
struct iwl_fw_dbg_trigger_tlv *trigger)
|
|
||||||
{
|
|
||||||
unsigned int delay = 0;
|
|
||||||
|
|
||||||
if (trigger)
|
|
||||||
delay = msecs_to_jiffies(le32_to_cpu(trigger->stop_delay));
|
|
||||||
|
|
||||||
if (test_and_set_bit(IWL_MVM_STATUS_DUMPING_FW_LOG, &mvm->status))
|
|
||||||
return -EBUSY;
|
|
||||||
|
|
||||||
if (WARN_ON(mvm->fw_dump_desc))
|
|
||||||
iwl_mvm_free_fw_dump_desc(mvm);
|
|
||||||
|
|
||||||
IWL_WARN(mvm, "Collecting data: trigger %d fired.\n",
|
|
||||||
le32_to_cpu(desc->trig_desc.type));
|
|
||||||
|
|
||||||
mvm->fw_dump_desc = desc;
|
|
||||||
mvm->fw_dump_trig = trigger;
|
|
||||||
|
|
||||||
queue_delayed_work(system_wq, &mvm->fw_dump_wk, delay);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int iwl_mvm_fw_dbg_collect(struct iwl_mvm *mvm, enum iwl_fw_dbg_trigger trig,
|
|
||||||
const char *str, size_t len,
|
|
||||||
struct iwl_fw_dbg_trigger_tlv *trigger)
|
|
||||||
{
|
|
||||||
struct iwl_mvm_dump_desc *desc;
|
|
||||||
|
|
||||||
desc = kzalloc(sizeof(*desc) + len, GFP_ATOMIC);
|
|
||||||
if (!desc)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
desc->len = len;
|
|
||||||
desc->trig_desc.type = cpu_to_le32(trig);
|
|
||||||
memcpy(desc->trig_desc.data, str, len);
|
|
||||||
|
|
||||||
return iwl_mvm_fw_dbg_collect_desc(mvm, desc, trigger);
|
|
||||||
}
|
|
||||||
|
|
||||||
int iwl_mvm_fw_dbg_collect_trig(struct iwl_mvm *mvm,
|
|
||||||
struct iwl_fw_dbg_trigger_tlv *trigger,
|
|
||||||
const char *fmt, ...)
|
|
||||||
{
|
|
||||||
u16 occurrences = le16_to_cpu(trigger->occurrences);
|
|
||||||
int ret, len = 0;
|
|
||||||
char buf[64];
|
|
||||||
|
|
||||||
if (!occurrences)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (fmt) {
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
buf[sizeof(buf) - 1] = '\0';
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
vsnprintf(buf, sizeof(buf), fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
/* check for truncation */
|
|
||||||
if (WARN_ON_ONCE(buf[sizeof(buf) - 1]))
|
|
||||||
buf[sizeof(buf) - 1] = '\0';
|
|
||||||
|
|
||||||
len = strlen(buf) + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = iwl_mvm_fw_dbg_collect(mvm, le32_to_cpu(trigger->id), buf, len,
|
|
||||||
trigger);
|
|
||||||
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
trigger->occurrences = cpu_to_le16(occurrences - 1);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void iwl_mvm_restart_early_start(struct iwl_mvm *mvm)
|
|
||||||
{
|
|
||||||
if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000)
|
|
||||||
iwl_clear_bits_prph(mvm->trans, MON_BUFF_SAMPLE_CTL, 0x100);
|
|
||||||
else
|
|
||||||
iwl_write_prph(mvm->trans, DBGC_IN_SAMPLE, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int iwl_mvm_start_fw_dbg_conf(struct iwl_mvm *mvm, u8 conf_id)
|
|
||||||
{
|
|
||||||
u8 *ptr;
|
|
||||||
int ret;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (WARN_ONCE(conf_id >= ARRAY_SIZE(mvm->fw->dbg_conf_tlv),
|
|
||||||
"Invalid configuration %d\n", conf_id))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
/* EARLY START - firmware's configuration is hard coded */
|
|
||||||
if ((!mvm->fw->dbg_conf_tlv[conf_id] ||
|
|
||||||
!mvm->fw->dbg_conf_tlv[conf_id]->num_of_hcmds) &&
|
|
||||||
conf_id == FW_DBG_START_FROM_ALIVE) {
|
|
||||||
iwl_mvm_restart_early_start(mvm);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!mvm->fw->dbg_conf_tlv[conf_id])
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
if (mvm->fw_dbg_conf != FW_DBG_INVALID)
|
|
||||||
IWL_WARN(mvm, "FW already configured (%d) - re-configuring\n",
|
|
||||||
mvm->fw_dbg_conf);
|
|
||||||
|
|
||||||
/* Send all HCMDs for configuring the FW debug */
|
|
||||||
ptr = (void *)&mvm->fw->dbg_conf_tlv[conf_id]->hcmd;
|
|
||||||
for (i = 0; i < mvm->fw->dbg_conf_tlv[conf_id]->num_of_hcmds; i++) {
|
|
||||||
struct iwl_fw_dbg_conf_hcmd *cmd = (void *)ptr;
|
|
||||||
|
|
||||||
ret = iwl_mvm_send_cmd_pdu(mvm, cmd->id, 0,
|
|
||||||
le16_to_cpu(cmd->len), cmd->data);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
ptr += sizeof(*cmd);
|
|
||||||
ptr += le16_to_cpu(cmd->len);
|
|
||||||
}
|
|
||||||
|
|
||||||
mvm->fw_dbg_conf = conf_id;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int iwl_mvm_config_ltr(struct iwl_mvm *mvm)
|
static int iwl_mvm_config_ltr(struct iwl_mvm *mvm)
|
||||||
{
|
{
|
||||||
struct iwl_ltr_config_cmd cmd = {
|
struct iwl_ltr_config_cmd cmd = {
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
* in the file called COPYING.
|
* in the file called COPYING.
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
*
|
*
|
||||||
* BSD LICENSE
|
* BSD LICENSE
|
||||||
|
|
|
@ -72,6 +72,7 @@
|
||||||
#include "fw-api.h"
|
#include "fw-api.h"
|
||||||
#include "mvm.h"
|
#include "mvm.h"
|
||||||
#include "time-event.h"
|
#include "time-event.h"
|
||||||
|
#include "fw-dbg.h"
|
||||||
|
|
||||||
const u8 iwl_mvm_ac_to_tx_fifo[] = {
|
const u8 iwl_mvm_ac_to_tx_fifo[] = {
|
||||||
IWL_MVM_TX_FIFO_VO,
|
IWL_MVM_TX_FIFO_VO,
|
||||||
|
|
|
@ -70,6 +70,7 @@
|
||||||
#include <linux/ip.h>
|
#include <linux/ip.h>
|
||||||
#include <linux/if_arp.h>
|
#include <linux/if_arp.h>
|
||||||
#include <linux/devcoredump.h>
|
#include <linux/devcoredump.h>
|
||||||
|
#include <linux/time.h>
|
||||||
#include <net/mac80211.h>
|
#include <net/mac80211.h>
|
||||||
#include <net/ieee80211_radiotap.h>
|
#include <net/ieee80211_radiotap.h>
|
||||||
#include <net/tcp.h>
|
#include <net/tcp.h>
|
||||||
|
@ -86,6 +87,7 @@
|
||||||
#include "iwl-prph.h"
|
#include "iwl-prph.h"
|
||||||
#include "iwl-csr.h"
|
#include "iwl-csr.h"
|
||||||
#include "iwl-nvm-parse.h"
|
#include "iwl-nvm-parse.h"
|
||||||
|
#include "fw-dbg.h"
|
||||||
|
|
||||||
static const struct ieee80211_iface_limit iwl_mvm_limits[] = {
|
static const struct ieee80211_iface_limit iwl_mvm_limits[] = {
|
||||||
{
|
{
|
||||||
|
@ -939,431 +941,6 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac,
|
||||||
memset(&mvmvif->bf_data, 0, sizeof(mvmvif->bf_data));
|
memset(&mvmvif->bf_data, 0, sizeof(mvmvif->bf_data));
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t iwl_mvm_read_coredump(char *buffer, loff_t offset, size_t count,
|
|
||||||
const void *data, size_t datalen)
|
|
||||||
{
|
|
||||||
const struct iwl_mvm_dump_ptrs *dump_ptrs = data;
|
|
||||||
ssize_t bytes_read;
|
|
||||||
ssize_t bytes_read_trans;
|
|
||||||
|
|
||||||
if (offset < dump_ptrs->op_mode_len) {
|
|
||||||
bytes_read = min_t(ssize_t, count,
|
|
||||||
dump_ptrs->op_mode_len - offset);
|
|
||||||
memcpy(buffer, (u8 *)dump_ptrs->op_mode_ptr + offset,
|
|
||||||
bytes_read);
|
|
||||||
offset += bytes_read;
|
|
||||||
count -= bytes_read;
|
|
||||||
|
|
||||||
if (count == 0)
|
|
||||||
return bytes_read;
|
|
||||||
} else {
|
|
||||||
bytes_read = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!dump_ptrs->trans_ptr)
|
|
||||||
return bytes_read;
|
|
||||||
|
|
||||||
offset -= dump_ptrs->op_mode_len;
|
|
||||||
bytes_read_trans = min_t(ssize_t, count,
|
|
||||||
dump_ptrs->trans_ptr->len - offset);
|
|
||||||
memcpy(buffer + bytes_read,
|
|
||||||
(u8 *)dump_ptrs->trans_ptr->data + offset,
|
|
||||||
bytes_read_trans);
|
|
||||||
|
|
||||||
return bytes_read + bytes_read_trans;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void iwl_mvm_free_coredump(const void *data)
|
|
||||||
{
|
|
||||||
const struct iwl_mvm_dump_ptrs *fw_error_dump = data;
|
|
||||||
|
|
||||||
vfree(fw_error_dump->op_mode_ptr);
|
|
||||||
vfree(fw_error_dump->trans_ptr);
|
|
||||||
kfree(fw_error_dump);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void iwl_mvm_dump_fifos(struct iwl_mvm *mvm,
|
|
||||||
struct iwl_fw_error_dump_data **dump_data)
|
|
||||||
{
|
|
||||||
struct iwl_fw_error_dump_fifo *fifo_hdr;
|
|
||||||
u32 *fifo_data;
|
|
||||||
u32 fifo_len;
|
|
||||||
unsigned long flags;
|
|
||||||
int i, j;
|
|
||||||
|
|
||||||
if (!iwl_trans_grab_nic_access(mvm->trans, false, &flags))
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* Pull RXF data from all RXFs */
|
|
||||||
for (i = 0; i < ARRAY_SIZE(mvm->shared_mem_cfg.rxfifo_size); i++) {
|
|
||||||
/*
|
|
||||||
* Keep aside the additional offset that might be needed for
|
|
||||||
* next RXF
|
|
||||||
*/
|
|
||||||
u32 offset_diff = RXF_DIFF_FROM_PREV * i;
|
|
||||||
|
|
||||||
fifo_hdr = (void *)(*dump_data)->data;
|
|
||||||
fifo_data = (void *)fifo_hdr->data;
|
|
||||||
fifo_len = mvm->shared_mem_cfg.rxfifo_size[i];
|
|
||||||
|
|
||||||
/* No need to try to read the data if the length is 0 */
|
|
||||||
if (fifo_len == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* Add a TLV for the RXF */
|
|
||||||
(*dump_data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_RXF);
|
|
||||||
(*dump_data)->len = cpu_to_le32(fifo_len + sizeof(*fifo_hdr));
|
|
||||||
|
|
||||||
fifo_hdr->fifo_num = cpu_to_le32(i);
|
|
||||||
fifo_hdr->available_bytes =
|
|
||||||
cpu_to_le32(iwl_trans_read_prph(mvm->trans,
|
|
||||||
RXF_RD_D_SPACE +
|
|
||||||
offset_diff));
|
|
||||||
fifo_hdr->wr_ptr =
|
|
||||||
cpu_to_le32(iwl_trans_read_prph(mvm->trans,
|
|
||||||
RXF_RD_WR_PTR +
|
|
||||||
offset_diff));
|
|
||||||
fifo_hdr->rd_ptr =
|
|
||||||
cpu_to_le32(iwl_trans_read_prph(mvm->trans,
|
|
||||||
RXF_RD_RD_PTR +
|
|
||||||
offset_diff));
|
|
||||||
fifo_hdr->fence_ptr =
|
|
||||||
cpu_to_le32(iwl_trans_read_prph(mvm->trans,
|
|
||||||
RXF_RD_FENCE_PTR +
|
|
||||||
offset_diff));
|
|
||||||
fifo_hdr->fence_mode =
|
|
||||||
cpu_to_le32(iwl_trans_read_prph(mvm->trans,
|
|
||||||
RXF_SET_FENCE_MODE +
|
|
||||||
offset_diff));
|
|
||||||
|
|
||||||
/* Lock fence */
|
|
||||||
iwl_trans_write_prph(mvm->trans,
|
|
||||||
RXF_SET_FENCE_MODE + offset_diff, 0x1);
|
|
||||||
/* Set fence pointer to the same place like WR pointer */
|
|
||||||
iwl_trans_write_prph(mvm->trans,
|
|
||||||
RXF_LD_WR2FENCE + offset_diff, 0x1);
|
|
||||||
/* Set fence offset */
|
|
||||||
iwl_trans_write_prph(mvm->trans,
|
|
||||||
RXF_LD_FENCE_OFFSET_ADDR + offset_diff,
|
|
||||||
0x0);
|
|
||||||
|
|
||||||
/* Read FIFO */
|
|
||||||
fifo_len /= sizeof(u32); /* Size in DWORDS */
|
|
||||||
for (j = 0; j < fifo_len; j++)
|
|
||||||
fifo_data[j] = iwl_trans_read_prph(mvm->trans,
|
|
||||||
RXF_FIFO_RD_FENCE_INC +
|
|
||||||
offset_diff);
|
|
||||||
*dump_data = iwl_fw_error_next_data(*dump_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Pull TXF data from all TXFs */
|
|
||||||
for (i = 0; i < ARRAY_SIZE(mvm->shared_mem_cfg.txfifo_size); i++) {
|
|
||||||
/* Mark the number of TXF we're pulling now */
|
|
||||||
iwl_trans_write_prph(mvm->trans, TXF_LARC_NUM, i);
|
|
||||||
|
|
||||||
fifo_hdr = (void *)(*dump_data)->data;
|
|
||||||
fifo_data = (void *)fifo_hdr->data;
|
|
||||||
fifo_len = mvm->shared_mem_cfg.txfifo_size[i];
|
|
||||||
|
|
||||||
/* No need to try to read the data if the length is 0 */
|
|
||||||
if (fifo_len == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* Add a TLV for the FIFO */
|
|
||||||
(*dump_data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_TXF);
|
|
||||||
(*dump_data)->len = cpu_to_le32(fifo_len + sizeof(*fifo_hdr));
|
|
||||||
|
|
||||||
fifo_hdr->fifo_num = cpu_to_le32(i);
|
|
||||||
fifo_hdr->available_bytes =
|
|
||||||
cpu_to_le32(iwl_trans_read_prph(mvm->trans,
|
|
||||||
TXF_FIFO_ITEM_CNT));
|
|
||||||
fifo_hdr->wr_ptr =
|
|
||||||
cpu_to_le32(iwl_trans_read_prph(mvm->trans,
|
|
||||||
TXF_WR_PTR));
|
|
||||||
fifo_hdr->rd_ptr =
|
|
||||||
cpu_to_le32(iwl_trans_read_prph(mvm->trans,
|
|
||||||
TXF_RD_PTR));
|
|
||||||
fifo_hdr->fence_ptr =
|
|
||||||
cpu_to_le32(iwl_trans_read_prph(mvm->trans,
|
|
||||||
TXF_FENCE_PTR));
|
|
||||||
fifo_hdr->fence_mode =
|
|
||||||
cpu_to_le32(iwl_trans_read_prph(mvm->trans,
|
|
||||||
TXF_LOCK_FENCE));
|
|
||||||
|
|
||||||
/* Set the TXF_READ_MODIFY_ADDR to TXF_WR_PTR */
|
|
||||||
iwl_trans_write_prph(mvm->trans, TXF_READ_MODIFY_ADDR,
|
|
||||||
TXF_WR_PTR);
|
|
||||||
|
|
||||||
/* Dummy-read to advance the read pointer to the head */
|
|
||||||
iwl_trans_read_prph(mvm->trans, TXF_READ_MODIFY_DATA);
|
|
||||||
|
|
||||||
/* Read FIFO */
|
|
||||||
fifo_len /= sizeof(u32); /* Size in DWORDS */
|
|
||||||
for (j = 0; j < fifo_len; j++)
|
|
||||||
fifo_data[j] = iwl_trans_read_prph(mvm->trans,
|
|
||||||
TXF_READ_MODIFY_DATA);
|
|
||||||
*dump_data = iwl_fw_error_next_data(*dump_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
iwl_trans_release_nic_access(mvm->trans, &flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
void iwl_mvm_free_fw_dump_desc(struct iwl_mvm *mvm)
|
|
||||||
{
|
|
||||||
if (mvm->fw_dump_desc == &iwl_mvm_dump_desc_assert ||
|
|
||||||
!mvm->fw_dump_desc)
|
|
||||||
return;
|
|
||||||
|
|
||||||
kfree(mvm->fw_dump_desc);
|
|
||||||
mvm->fw_dump_desc = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define IWL8260_ICCM_OFFSET 0x44000 /* Only for B-step */
|
|
||||||
#define IWL8260_ICCM_LEN 0xC000 /* Only for B-step */
|
|
||||||
|
|
||||||
void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
|
|
||||||
{
|
|
||||||
struct iwl_fw_error_dump_file *dump_file;
|
|
||||||
struct iwl_fw_error_dump_data *dump_data;
|
|
||||||
struct iwl_fw_error_dump_info *dump_info;
|
|
||||||
struct iwl_fw_error_dump_mem *dump_mem;
|
|
||||||
struct iwl_fw_error_dump_trigger_desc *dump_trig;
|
|
||||||
struct iwl_mvm_dump_ptrs *fw_error_dump;
|
|
||||||
u32 sram_len, sram_ofs;
|
|
||||||
u32 file_len, fifo_data_len = 0;
|
|
||||||
u32 smem_len = mvm->cfg->smem_len;
|
|
||||||
u32 sram2_len = mvm->cfg->dccm2_len;
|
|
||||||
bool monitor_dump_only = false;
|
|
||||||
|
|
||||||
lockdep_assert_held(&mvm->mutex);
|
|
||||||
|
|
||||||
/* there's no point in fw dump if the bus is dead */
|
|
||||||
if (test_bit(STATUS_TRANS_DEAD, &mvm->trans->status)) {
|
|
||||||
IWL_ERR(mvm, "Skip fw error dump since bus is dead\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mvm->fw_dump_trig &&
|
|
||||||
mvm->fw_dump_trig->mode & IWL_FW_DBG_TRIGGER_MONITOR_ONLY)
|
|
||||||
monitor_dump_only = true;
|
|
||||||
|
|
||||||
fw_error_dump = kzalloc(sizeof(*fw_error_dump), GFP_KERNEL);
|
|
||||||
if (!fw_error_dump)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* SRAM - include stack CCM if driver knows the values for it */
|
|
||||||
if (!mvm->cfg->dccm_offset || !mvm->cfg->dccm_len) {
|
|
||||||
const struct fw_img *img;
|
|
||||||
|
|
||||||
img = &mvm->fw->img[mvm->cur_ucode];
|
|
||||||
sram_ofs = img->sec[IWL_UCODE_SECTION_DATA].offset;
|
|
||||||
sram_len = img->sec[IWL_UCODE_SECTION_DATA].len;
|
|
||||||
} else {
|
|
||||||
sram_ofs = mvm->cfg->dccm_offset;
|
|
||||||
sram_len = mvm->cfg->dccm_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* reading RXF/TXF sizes */
|
|
||||||
if (test_bit(STATUS_FW_ERROR, &mvm->trans->status)) {
|
|
||||||
struct iwl_mvm_shared_mem_cfg *mem_cfg = &mvm->shared_mem_cfg;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
fifo_data_len = 0;
|
|
||||||
|
|
||||||
/* Count RXF size */
|
|
||||||
for (i = 0; i < ARRAY_SIZE(mem_cfg->rxfifo_size); i++) {
|
|
||||||
if (!mem_cfg->rxfifo_size[i])
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* Add header info */
|
|
||||||
fifo_data_len += mem_cfg->rxfifo_size[i] +
|
|
||||||
sizeof(*dump_data) +
|
|
||||||
sizeof(struct iwl_fw_error_dump_fifo);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(mem_cfg->txfifo_size); i++) {
|
|
||||||
if (!mem_cfg->txfifo_size[i])
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* Add header info */
|
|
||||||
fifo_data_len += mem_cfg->txfifo_size[i] +
|
|
||||||
sizeof(*dump_data) +
|
|
||||||
sizeof(struct iwl_fw_error_dump_fifo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
file_len = sizeof(*dump_file) +
|
|
||||||
sizeof(*dump_data) * 2 +
|
|
||||||
sram_len + sizeof(*dump_mem) +
|
|
||||||
fifo_data_len +
|
|
||||||
sizeof(*dump_info);
|
|
||||||
|
|
||||||
/* Make room for the SMEM, if it exists */
|
|
||||||
if (smem_len)
|
|
||||||
file_len += sizeof(*dump_data) + sizeof(*dump_mem) + smem_len;
|
|
||||||
|
|
||||||
/* Make room for the secondary SRAM, if it exists */
|
|
||||||
if (sram2_len)
|
|
||||||
file_len += sizeof(*dump_data) + sizeof(*dump_mem) + sram2_len;
|
|
||||||
|
|
||||||
/* Make room for fw's virtual image pages, if it exists */
|
|
||||||
if (mvm->fw->img[mvm->cur_ucode].paging_mem_size)
|
|
||||||
file_len += mvm->num_of_paging_blk *
|
|
||||||
(sizeof(*dump_data) +
|
|
||||||
sizeof(struct iwl_fw_error_dump_paging) +
|
|
||||||
PAGING_BLOCK_SIZE);
|
|
||||||
|
|
||||||
/* If we only want a monitor dump, reset the file length */
|
|
||||||
if (monitor_dump_only) {
|
|
||||||
file_len = sizeof(*dump_file) + sizeof(*dump_data) +
|
|
||||||
sizeof(*dump_info);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* In 8000 HW family B-step include the ICCM (which resides separately)
|
|
||||||
*/
|
|
||||||
if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_8000 &&
|
|
||||||
CSR_HW_REV_STEP(mvm->trans->hw_rev) == SILICON_B_STEP)
|
|
||||||
file_len += sizeof(*dump_data) + sizeof(*dump_mem) +
|
|
||||||
IWL8260_ICCM_LEN;
|
|
||||||
|
|
||||||
if (mvm->fw_dump_desc)
|
|
||||||
file_len += sizeof(*dump_data) + sizeof(*dump_trig) +
|
|
||||||
mvm->fw_dump_desc->len;
|
|
||||||
|
|
||||||
dump_file = vzalloc(file_len);
|
|
||||||
if (!dump_file) {
|
|
||||||
kfree(fw_error_dump);
|
|
||||||
iwl_mvm_free_fw_dump_desc(mvm);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fw_error_dump->op_mode_ptr = dump_file;
|
|
||||||
|
|
||||||
dump_file->barker = cpu_to_le32(IWL_FW_ERROR_DUMP_BARKER);
|
|
||||||
dump_data = (void *)dump_file->data;
|
|
||||||
|
|
||||||
dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_DEV_FW_INFO);
|
|
||||||
dump_data->len = cpu_to_le32(sizeof(*dump_info));
|
|
||||||
dump_info = (void *) dump_data->data;
|
|
||||||
dump_info->device_family =
|
|
||||||
mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000 ?
|
|
||||||
cpu_to_le32(IWL_FW_ERROR_DUMP_FAMILY_7) :
|
|
||||||
cpu_to_le32(IWL_FW_ERROR_DUMP_FAMILY_8);
|
|
||||||
dump_info->hw_step = cpu_to_le32(CSR_HW_REV_STEP(mvm->trans->hw_rev));
|
|
||||||
memcpy(dump_info->fw_human_readable, mvm->fw->human_readable,
|
|
||||||
sizeof(dump_info->fw_human_readable));
|
|
||||||
strncpy(dump_info->dev_human_readable, mvm->cfg->name,
|
|
||||||
sizeof(dump_info->dev_human_readable));
|
|
||||||
strncpy(dump_info->bus_human_readable, mvm->dev->bus->name,
|
|
||||||
sizeof(dump_info->bus_human_readable));
|
|
||||||
|
|
||||||
dump_data = iwl_fw_error_next_data(dump_data);
|
|
||||||
/* We only dump the FIFOs if the FW is in error state */
|
|
||||||
if (test_bit(STATUS_FW_ERROR, &mvm->trans->status))
|
|
||||||
iwl_mvm_dump_fifos(mvm, &dump_data);
|
|
||||||
|
|
||||||
if (mvm->fw_dump_desc) {
|
|
||||||
dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_ERROR_INFO);
|
|
||||||
dump_data->len = cpu_to_le32(sizeof(*dump_trig) +
|
|
||||||
mvm->fw_dump_desc->len);
|
|
||||||
dump_trig = (void *)dump_data->data;
|
|
||||||
memcpy(dump_trig, &mvm->fw_dump_desc->trig_desc,
|
|
||||||
sizeof(*dump_trig) + mvm->fw_dump_desc->len);
|
|
||||||
|
|
||||||
/* now we can free this copy */
|
|
||||||
iwl_mvm_free_fw_dump_desc(mvm);
|
|
||||||
dump_data = iwl_fw_error_next_data(dump_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* In case we only want monitor dump, skip to dump trasport data */
|
|
||||||
if (monitor_dump_only)
|
|
||||||
goto dump_trans_data;
|
|
||||||
|
|
||||||
dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM);
|
|
||||||
dump_data->len = cpu_to_le32(sram_len + sizeof(*dump_mem));
|
|
||||||
dump_mem = (void *)dump_data->data;
|
|
||||||
dump_mem->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM_SRAM);
|
|
||||||
dump_mem->offset = cpu_to_le32(sram_ofs);
|
|
||||||
iwl_trans_read_mem_bytes(mvm->trans, sram_ofs, dump_mem->data,
|
|
||||||
sram_len);
|
|
||||||
|
|
||||||
if (smem_len) {
|
|
||||||
dump_data = iwl_fw_error_next_data(dump_data);
|
|
||||||
dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM);
|
|
||||||
dump_data->len = cpu_to_le32(smem_len + sizeof(*dump_mem));
|
|
||||||
dump_mem = (void *)dump_data->data;
|
|
||||||
dump_mem->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM_SMEM);
|
|
||||||
dump_mem->offset = cpu_to_le32(mvm->cfg->smem_offset);
|
|
||||||
iwl_trans_read_mem_bytes(mvm->trans, mvm->cfg->smem_offset,
|
|
||||||
dump_mem->data, smem_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sram2_len) {
|
|
||||||
dump_data = iwl_fw_error_next_data(dump_data);
|
|
||||||
dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM);
|
|
||||||
dump_data->len = cpu_to_le32(sram2_len + sizeof(*dump_mem));
|
|
||||||
dump_mem = (void *)dump_data->data;
|
|
||||||
dump_mem->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM_SRAM);
|
|
||||||
dump_mem->offset = cpu_to_le32(mvm->cfg->dccm2_offset);
|
|
||||||
iwl_trans_read_mem_bytes(mvm->trans, mvm->cfg->dccm2_offset,
|
|
||||||
dump_mem->data, sram2_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_8000 &&
|
|
||||||
CSR_HW_REV_STEP(mvm->trans->hw_rev) == SILICON_B_STEP) {
|
|
||||||
dump_data = iwl_fw_error_next_data(dump_data);
|
|
||||||
dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM);
|
|
||||||
dump_data->len = cpu_to_le32(IWL8260_ICCM_LEN +
|
|
||||||
sizeof(*dump_mem));
|
|
||||||
dump_mem = (void *)dump_data->data;
|
|
||||||
dump_mem->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM_SRAM);
|
|
||||||
dump_mem->offset = cpu_to_le32(IWL8260_ICCM_OFFSET);
|
|
||||||
iwl_trans_read_mem_bytes(mvm->trans, IWL8260_ICCM_OFFSET,
|
|
||||||
dump_mem->data, IWL8260_ICCM_LEN);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Dump fw's virtual image */
|
|
||||||
if (mvm->fw->img[mvm->cur_ucode].paging_mem_size) {
|
|
||||||
u32 i;
|
|
||||||
|
|
||||||
for (i = 1; i < mvm->num_of_paging_blk + 1; i++) {
|
|
||||||
struct iwl_fw_error_dump_paging *paging;
|
|
||||||
struct page *pages =
|
|
||||||
mvm->fw_paging_db[i].fw_paging_block;
|
|
||||||
|
|
||||||
dump_data = iwl_fw_error_next_data(dump_data);
|
|
||||||
dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PAGING);
|
|
||||||
dump_data->len = cpu_to_le32(sizeof(*paging) +
|
|
||||||
PAGING_BLOCK_SIZE);
|
|
||||||
paging = (void *)dump_data->data;
|
|
||||||
paging->index = cpu_to_le32(i);
|
|
||||||
memcpy(paging->data, page_address(pages),
|
|
||||||
PAGING_BLOCK_SIZE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dump_trans_data:
|
|
||||||
fw_error_dump->trans_ptr = iwl_trans_dump_data(mvm->trans,
|
|
||||||
mvm->fw_dump_trig);
|
|
||||||
fw_error_dump->op_mode_len = file_len;
|
|
||||||
if (fw_error_dump->trans_ptr)
|
|
||||||
file_len += fw_error_dump->trans_ptr->len;
|
|
||||||
dump_file->file_len = cpu_to_le32(file_len);
|
|
||||||
|
|
||||||
dev_coredumpm(mvm->trans->dev, THIS_MODULE, fw_error_dump, 0,
|
|
||||||
GFP_KERNEL, iwl_mvm_read_coredump, iwl_mvm_free_coredump);
|
|
||||||
|
|
||||||
mvm->fw_dump_trig = NULL;
|
|
||||||
clear_bit(IWL_MVM_STATUS_DUMPING_FW_LOG, &mvm->status);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct iwl_mvm_dump_desc iwl_mvm_dump_desc_assert = {
|
|
||||||
.trig_desc = {
|
|
||||||
.type = cpu_to_le32(FW_DBG_TRIGGER_FW_ASSERT),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
|
static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
|
||||||
{
|
{
|
||||||
/* clear the D3 reconfig, we only need it to avoid dumping a
|
/* clear the D3 reconfig, we only need it to avoid dumping a
|
||||||
|
@ -2699,6 +2276,34 @@ static void iwl_mvm_check_uapsd(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||||
vif->driver_flags |= IEEE80211_VIF_SUPPORTS_UAPSD;
|
vif->driver_flags |= IEEE80211_VIF_SUPPORTS_UAPSD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
iwl_mvm_tdls_check_trigger(struct iwl_mvm *mvm,
|
||||||
|
struct ieee80211_vif *vif, u8 *peer_addr,
|
||||||
|
enum nl80211_tdls_operation action)
|
||||||
|
{
|
||||||
|
struct iwl_fw_dbg_trigger_tlv *trig;
|
||||||
|
struct iwl_fw_dbg_trigger_tdls *tdls_trig;
|
||||||
|
|
||||||
|
if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_TDLS))
|
||||||
|
return;
|
||||||
|
|
||||||
|
trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_TDLS);
|
||||||
|
tdls_trig = (void *)trig->data;
|
||||||
|
if (!iwl_fw_dbg_trigger_check_stop(mvm, vif, trig))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!(tdls_trig->action_bitmap & BIT(action)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (tdls_trig->peer_mode &&
|
||||||
|
memcmp(tdls_trig->peer, peer_addr, ETH_ALEN) != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
iwl_mvm_fw_dbg_collect_trig(mvm, trig,
|
||||||
|
"TDLS event occurred, peer %pM, action %d",
|
||||||
|
peer_addr, action);
|
||||||
|
}
|
||||||
|
|
||||||
static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
|
static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
|
||||||
struct ieee80211_vif *vif,
|
struct ieee80211_vif *vif,
|
||||||
struct ieee80211_sta *sta,
|
struct ieee80211_sta *sta,
|
||||||
|
@ -2749,8 +2354,11 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = iwl_mvm_add_sta(mvm, vif, sta);
|
ret = iwl_mvm_add_sta(mvm, vif, sta);
|
||||||
if (sta->tdls && ret == 0)
|
if (sta->tdls && ret == 0) {
|
||||||
iwl_mvm_recalc_tdls_state(mvm, vif, true);
|
iwl_mvm_recalc_tdls_state(mvm, vif, true);
|
||||||
|
iwl_mvm_tdls_check_trigger(mvm, vif, sta->addr,
|
||||||
|
NL80211_TDLS_SETUP);
|
||||||
|
}
|
||||||
} else if (old_state == IEEE80211_STA_NONE &&
|
} else if (old_state == IEEE80211_STA_NONE &&
|
||||||
new_state == IEEE80211_STA_AUTH) {
|
new_state == IEEE80211_STA_AUTH) {
|
||||||
/*
|
/*
|
||||||
|
@ -2774,6 +2382,10 @@ static int iwl_mvm_mac_sta_state(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);
|
||||||
|
|
||||||
|
if (sta->tdls)
|
||||||
|
iwl_mvm_tdls_check_trigger(mvm, vif, sta->addr,
|
||||||
|
NL80211_TDLS_ENABLE_LINK);
|
||||||
|
|
||||||
/* enable beacon filtering */
|
/* enable beacon filtering */
|
||||||
WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0));
|
WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0));
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
@ -2791,8 +2403,11 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
|
||||||
} else if (old_state == IEEE80211_STA_NONE &&
|
} else if (old_state == IEEE80211_STA_NONE &&
|
||||||
new_state == IEEE80211_STA_NOTEXIST) {
|
new_state == IEEE80211_STA_NOTEXIST) {
|
||||||
ret = iwl_mvm_rm_sta(mvm, vif, sta);
|
ret = iwl_mvm_rm_sta(mvm, vif, sta);
|
||||||
if (sta->tdls)
|
if (sta->tdls) {
|
||||||
iwl_mvm_recalc_tdls_state(mvm, vif, false);
|
iwl_mvm_recalc_tdls_state(mvm, vif, false);
|
||||||
|
iwl_mvm_tdls_check_trigger(mvm, vif, sta->addr,
|
||||||
|
NL80211_TDLS_DISABLE_LINK);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
}
|
}
|
||||||
|
@ -2941,6 +2556,7 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
|
||||||
{
|
{
|
||||||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||||
int ret;
|
int ret;
|
||||||
|
u8 key_offset;
|
||||||
|
|
||||||
if (iwlwifi_mod_params.sw_crypto) {
|
if (iwlwifi_mod_params.sw_crypto) {
|
||||||
IWL_DEBUG_MAC80211(mvm, "leave - hwcrypto disabled\n");
|
IWL_DEBUG_MAC80211(mvm, "leave - hwcrypto disabled\n");
|
||||||
|
@ -3006,10 +2622,14 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* in HW restart reuse the index, otherwise request a new one */
|
||||||
|
if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
|
||||||
|
key_offset = key->hw_key_idx;
|
||||||
|
else
|
||||||
|
key_offset = STA_KEY_IDX_INVALID;
|
||||||
|
|
||||||
IWL_DEBUG_MAC80211(mvm, "set hwcrypto key\n");
|
IWL_DEBUG_MAC80211(mvm, "set hwcrypto key\n");
|
||||||
ret = iwl_mvm_set_sta_key(mvm, vif, sta, key,
|
ret = iwl_mvm_set_sta_key(mvm, vif, sta, key, key_offset);
|
||||||
test_bit(IWL_MVM_STATUS_IN_HW_RESTART,
|
|
||||||
&mvm->status));
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
IWL_WARN(mvm, "set key failed\n");
|
IWL_WARN(mvm, "set key failed\n");
|
||||||
/*
|
/*
|
||||||
|
@ -3087,7 +2707,11 @@ static bool iwl_mvm_rx_aux_roc(struct iwl_notif_wait_data *notif_wait,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define AUX_ROC_MAX_DELAY_ON_CHANNEL 200
|
#define AUX_ROC_MIN_DURATION MSEC_TO_TU(100)
|
||||||
|
#define AUX_ROC_MIN_DELAY MSEC_TO_TU(200)
|
||||||
|
#define AUX_ROC_MAX_DELAY MSEC_TO_TU(600)
|
||||||
|
#define AUX_ROC_SAFETY_BUFFER MSEC_TO_TU(20)
|
||||||
|
#define AUX_ROC_MIN_SAFETY_BUFFER MSEC_TO_TU(10)
|
||||||
static int iwl_mvm_send_aux_roc_cmd(struct iwl_mvm *mvm,
|
static int iwl_mvm_send_aux_roc_cmd(struct iwl_mvm *mvm,
|
||||||
struct ieee80211_channel *channel,
|
struct ieee80211_channel *channel,
|
||||||
struct ieee80211_vif *vif,
|
struct ieee80211_vif *vif,
|
||||||
|
@ -3098,6 +2722,9 @@ static int iwl_mvm_send_aux_roc_cmd(struct iwl_mvm *mvm,
|
||||||
struct iwl_mvm_time_event_data *te_data = &mvmvif->hs_time_event_data;
|
struct iwl_mvm_time_event_data *te_data = &mvmvif->hs_time_event_data;
|
||||||
static const u16 time_event_response[] = { HOT_SPOT_CMD };
|
static const u16 time_event_response[] = { HOT_SPOT_CMD };
|
||||||
struct iwl_notification_wait wait_time_event;
|
struct iwl_notification_wait wait_time_event;
|
||||||
|
u32 dtim_interval = vif->bss_conf.dtim_period *
|
||||||
|
vif->bss_conf.beacon_int;
|
||||||
|
u32 req_dur, delay;
|
||||||
struct iwl_hs20_roc_req aux_roc_req = {
|
struct iwl_hs20_roc_req aux_roc_req = {
|
||||||
.action = cpu_to_le32(FW_CTXT_ACTION_ADD),
|
.action = cpu_to_le32(FW_CTXT_ACTION_ADD),
|
||||||
.id_and_color =
|
.id_and_color =
|
||||||
|
@ -3110,11 +2737,38 @@ static int iwl_mvm_send_aux_roc_cmd(struct iwl_mvm *mvm,
|
||||||
.channel_info.width = PHY_VHT_CHANNEL_MODE20,
|
.channel_info.width = PHY_VHT_CHANNEL_MODE20,
|
||||||
/* Set the time and duration */
|
/* Set the time and duration */
|
||||||
.apply_time = cpu_to_le32(iwl_read_prph(mvm->trans, time_reg)),
|
.apply_time = cpu_to_le32(iwl_read_prph(mvm->trans, time_reg)),
|
||||||
.apply_time_max_delay =
|
|
||||||
cpu_to_le32(MSEC_TO_TU(AUX_ROC_MAX_DELAY_ON_CHANNEL)),
|
|
||||||
.duration = cpu_to_le32(MSEC_TO_TU(duration)),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
delay = AUX_ROC_MIN_DELAY;
|
||||||
|
req_dur = MSEC_TO_TU(duration);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we are associated we want the delay time to be at least one
|
||||||
|
* dtim interval so that the FW can wait until after the DTIM and
|
||||||
|
* then start the time event, this will potentially allow us to
|
||||||
|
* remain off-channel for the max duration.
|
||||||
|
* Since we want to use almost a whole dtim interval we would also
|
||||||
|
* like the delay to be for 2-3 dtim intervals, in case there are
|
||||||
|
* other time events with higher priority.
|
||||||
|
*/
|
||||||
|
if (vif->bss_conf.assoc) {
|
||||||
|
delay = min_t(u32, dtim_interval * 3, AUX_ROC_MAX_DELAY);
|
||||||
|
/* We cannot remain off-channel longer than the DTIM interval */
|
||||||
|
if (dtim_interval <= req_dur) {
|
||||||
|
req_dur = dtim_interval - AUX_ROC_SAFETY_BUFFER;
|
||||||
|
if (req_dur <= AUX_ROC_MIN_DURATION)
|
||||||
|
req_dur = dtim_interval -
|
||||||
|
AUX_ROC_MIN_SAFETY_BUFFER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
aux_roc_req.duration = cpu_to_le32(req_dur);
|
||||||
|
aux_roc_req.apply_time_max_delay = cpu_to_le32(delay);
|
||||||
|
|
||||||
|
IWL_DEBUG_TE(mvm,
|
||||||
|
"ROC: Requesting to remain on channel %u for %ums (requested = %ums, max_delay = %ums, dtim_interval = %ums)\n",
|
||||||
|
channel->hw_value, req_dur, duration, delay,
|
||||||
|
dtim_interval);
|
||||||
/* Set the node address */
|
/* Set the node address */
|
||||||
memcpy(aux_roc_req.node_addr, vif->addr, ETH_ALEN);
|
memcpy(aux_roc_req.node_addr, vif->addr, ETH_ALEN);
|
||||||
|
|
||||||
|
|
|
@ -643,6 +643,7 @@ struct iwl_mvm {
|
||||||
unsigned int scan_status;
|
unsigned int scan_status;
|
||||||
void *scan_cmd;
|
void *scan_cmd;
|
||||||
struct iwl_mcast_filter_cmd *mcast_filter_cmd;
|
struct iwl_mcast_filter_cmd *mcast_filter_cmd;
|
||||||
|
bool scan_fragmented;
|
||||||
|
|
||||||
/* max number of simultaneous scans the FW supports */
|
/* max number of simultaneous scans the FW supports */
|
||||||
unsigned int max_scans;
|
unsigned int max_scans;
|
||||||
|
@ -731,7 +732,6 @@ struct iwl_mvm {
|
||||||
int gtk_ivlen, gtk_icvlen, ptk_ivlen, ptk_icvlen;
|
int gtk_ivlen, gtk_icvlen, ptk_ivlen, ptk_icvlen;
|
||||||
|
|
||||||
/* sched scan settings for net detect */
|
/* sched scan settings for net detect */
|
||||||
struct cfg80211_sched_scan_request *nd_config;
|
|
||||||
struct ieee80211_scan_ies nd_ies;
|
struct ieee80211_scan_ies nd_ies;
|
||||||
struct cfg80211_match_set *nd_match_sets;
|
struct cfg80211_match_set *nd_match_sets;
|
||||||
int n_nd_match_sets;
|
int n_nd_match_sets;
|
||||||
|
@ -813,8 +813,6 @@ struct iwl_mvm {
|
||||||
bool lar_regdom_set;
|
bool lar_regdom_set;
|
||||||
enum iwl_mcc_source mcc_src;
|
enum iwl_mcc_source mcc_src;
|
||||||
|
|
||||||
u8 low_latency_agg_frame_limit;
|
|
||||||
|
|
||||||
/* TDLS channel switch data */
|
/* TDLS channel switch data */
|
||||||
struct {
|
struct {
|
||||||
struct delayed_work dwork;
|
struct delayed_work dwork;
|
||||||
|
@ -915,11 +913,9 @@ iwl_mvm_sta_from_staid_protected(struct iwl_mvm *mvm, u8 sta_id)
|
||||||
|
|
||||||
static inline bool iwl_mvm_is_d0i3_supported(struct iwl_mvm *mvm)
|
static inline bool iwl_mvm_is_d0i3_supported(struct iwl_mvm *mvm)
|
||||||
{
|
{
|
||||||
return mvm->trans->cfg->d0i3 &&
|
return !iwlwifi_mod_params.d0i3_disable &&
|
||||||
mvm->trans->d0i3_mode != IWL_D0I3_MODE_OFF &&
|
fw_has_capa(&mvm->fw->ucode_capa,
|
||||||
!iwlwifi_mod_params.d0i3_disable &&
|
IWL_UCODE_TLV_CAPA_D0I3_SUPPORT);
|
||||||
fw_has_capa(&mvm->fw->ucode_capa,
|
|
||||||
IWL_UCODE_TLV_CAPA_D0I3_SUPPORT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool iwl_mvm_is_dqa_supported(struct iwl_mvm *mvm)
|
static inline bool iwl_mvm_is_dqa_supported(struct iwl_mvm *mvm)
|
||||||
|
@ -975,6 +971,13 @@ static inline bool iwl_mvm_is_csum_supported(struct iwl_mvm *mvm)
|
||||||
IWL_UCODE_TLV_CAPA_CSUM_SUPPORT);
|
IWL_UCODE_TLV_CAPA_CSUM_SUPPORT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool iwl_mvm_is_mplut_supported(struct iwl_mvm *mvm)
|
||||||
|
{
|
||||||
|
return fw_has_capa(&mvm->fw->ucode_capa,
|
||||||
|
IWL_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT) &&
|
||||||
|
IWL_MVM_BT_COEX_MPLUT;
|
||||||
|
}
|
||||||
|
|
||||||
static inline bool iwl_mvm_has_new_rx_api(struct iwl_mvm *mvm)
|
static inline bool iwl_mvm_has_new_rx_api(struct iwl_mvm *mvm)
|
||||||
{
|
{
|
||||||
/* firmware flag isn't defined yet */
|
/* firmware flag isn't defined yet */
|
||||||
|
@ -1246,6 +1249,10 @@ static inline void iwl_mvm_leds_exit(struct iwl_mvm *mvm)
|
||||||
/* D3 (WoWLAN, NetDetect) */
|
/* D3 (WoWLAN, NetDetect) */
|
||||||
int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan);
|
int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan);
|
||||||
int iwl_mvm_resume(struct ieee80211_hw *hw);
|
int iwl_mvm_resume(struct ieee80211_hw *hw);
|
||||||
|
int iwl_mvm_wowlan_config_key_params(struct iwl_mvm *mvm,
|
||||||
|
struct ieee80211_vif *vif,
|
||||||
|
bool configure_keys,
|
||||||
|
u32 cmd_flags);
|
||||||
void iwl_mvm_set_wakeup(struct ieee80211_hw *hw, bool enabled);
|
void iwl_mvm_set_wakeup(struct ieee80211_hw *hw, bool enabled);
|
||||||
void iwl_mvm_set_rekey_data(struct ieee80211_hw *hw,
|
void iwl_mvm_set_rekey_data(struct ieee80211_hw *hw,
|
||||||
struct ieee80211_vif *vif,
|
struct ieee80211_vif *vif,
|
||||||
|
@ -1376,6 +1383,15 @@ void iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue,
|
||||||
u8 tid, u8 flags);
|
u8 tid, u8 flags);
|
||||||
int iwl_mvm_find_free_queue(struct iwl_mvm *mvm, u8 minq, u8 maxq);
|
int iwl_mvm_find_free_queue(struct iwl_mvm *mvm, u8 minq, u8 maxq);
|
||||||
|
|
||||||
|
/* Return a bitmask with all the hw supported queues, except for the
|
||||||
|
* command queue, which can't be flushed.
|
||||||
|
*/
|
||||||
|
static inline u32 iwl_mvm_flushable_queues(struct iwl_mvm *mvm)
|
||||||
|
{
|
||||||
|
return ((BIT(mvm->cfg->base_params->num_of_queues) - 1) &
|
||||||
|
~BIT(IWL_MVM_CMD_QUEUE));
|
||||||
|
}
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
void iwl_mvm_enable_ac_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue,
|
void iwl_mvm_enable_ac_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue,
|
||||||
u8 fifo, u16 ssn, unsigned int wdg_timeout)
|
u8 fifo, u16 ssn, unsigned int wdg_timeout)
|
||||||
|
@ -1468,68 +1484,10 @@ void iwl_mvm_tdls_ch_switch_work(struct work_struct *work);
|
||||||
struct ieee80211_vif *iwl_mvm_get_bss_vif(struct iwl_mvm *mvm);
|
struct ieee80211_vif *iwl_mvm_get_bss_vif(struct iwl_mvm *mvm);
|
||||||
|
|
||||||
void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error);
|
void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error);
|
||||||
void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm);
|
|
||||||
|
|
||||||
int iwl_mvm_start_fw_dbg_conf(struct iwl_mvm *mvm, u8 id);
|
|
||||||
int iwl_mvm_fw_dbg_collect(struct iwl_mvm *mvm, enum iwl_fw_dbg_trigger trig,
|
|
||||||
const char *str, size_t len,
|
|
||||||
struct iwl_fw_dbg_trigger_tlv *trigger);
|
|
||||||
int iwl_mvm_fw_dbg_collect_desc(struct iwl_mvm *mvm,
|
|
||||||
struct iwl_mvm_dump_desc *desc,
|
|
||||||
struct iwl_fw_dbg_trigger_tlv *trigger);
|
|
||||||
void iwl_mvm_free_fw_dump_desc(struct iwl_mvm *mvm);
|
|
||||||
int iwl_mvm_fw_dbg_collect_trig(struct iwl_mvm *mvm,
|
|
||||||
struct iwl_fw_dbg_trigger_tlv *trigger,
|
|
||||||
const char *fmt, ...) __printf(3, 4);
|
|
||||||
unsigned int iwl_mvm_get_wd_timeout(struct iwl_mvm *mvm,
|
unsigned int iwl_mvm_get_wd_timeout(struct iwl_mvm *mvm,
|
||||||
struct ieee80211_vif *vif,
|
struct ieee80211_vif *vif,
|
||||||
bool tdls, bool cmd_q);
|
bool tdls, bool cmd_q);
|
||||||
void iwl_mvm_connection_loss(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
void iwl_mvm_connection_loss(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||||
const char *errmsg);
|
const char *errmsg);
|
||||||
static inline bool
|
|
||||||
iwl_fw_dbg_trigger_vif_match(struct iwl_fw_dbg_trigger_tlv *trig,
|
|
||||||
struct ieee80211_vif *vif)
|
|
||||||
{
|
|
||||||
u32 trig_vif = le32_to_cpu(trig->vif_type);
|
|
||||||
|
|
||||||
return trig_vif == IWL_FW_DBG_CONF_VIF_ANY || vif->type == trig_vif;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool
|
|
||||||
iwl_fw_dbg_trigger_stop_conf_match(struct iwl_mvm *mvm,
|
|
||||||
struct iwl_fw_dbg_trigger_tlv *trig)
|
|
||||||
{
|
|
||||||
return ((trig->mode & IWL_FW_DBG_TRIGGER_STOP) &&
|
|
||||||
(mvm->fw_dbg_conf == FW_DBG_INVALID ||
|
|
||||||
(BIT(mvm->fw_dbg_conf) & le32_to_cpu(trig->stop_conf_ids))));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool
|
|
||||||
iwl_fw_dbg_trigger_check_stop(struct iwl_mvm *mvm,
|
|
||||||
struct ieee80211_vif *vif,
|
|
||||||
struct iwl_fw_dbg_trigger_tlv *trig)
|
|
||||||
{
|
|
||||||
if (vif && !iwl_fw_dbg_trigger_vif_match(trig, vif))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return iwl_fw_dbg_trigger_stop_conf_match(mvm, trig);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
iwl_fw_dbg_trigger_simple_stop(struct iwl_mvm *mvm,
|
|
||||||
struct ieee80211_vif *vif,
|
|
||||||
enum iwl_fw_dbg_trigger trig)
|
|
||||||
{
|
|
||||||
struct iwl_fw_dbg_trigger_tlv *trigger;
|
|
||||||
|
|
||||||
if (!iwl_fw_dbg_trigger_enabled(mvm->fw, trig))
|
|
||||||
return;
|
|
||||||
|
|
||||||
trigger = iwl_fw_dbg_get_trigger(mvm->fw, trig);
|
|
||||||
if (!iwl_fw_dbg_trigger_check_stop(mvm, vif, trigger))
|
|
||||||
return;
|
|
||||||
|
|
||||||
iwl_mvm_fw_dbg_collect_trig(mvm, trigger, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* __IWL_MVM_H__ */
|
#endif /* __IWL_MVM_H__ */
|
||||||
|
|
|
@ -104,13 +104,35 @@ static int iwl_nvm_write_chunk(struct iwl_mvm *mvm, u16 section,
|
||||||
struct iwl_host_cmd cmd = {
|
struct iwl_host_cmd cmd = {
|
||||||
.id = NVM_ACCESS_CMD,
|
.id = NVM_ACCESS_CMD,
|
||||||
.len = { sizeof(struct iwl_nvm_access_cmd), length },
|
.len = { sizeof(struct iwl_nvm_access_cmd), length },
|
||||||
.flags = CMD_SEND_IN_RFKILL,
|
.flags = CMD_WANT_SKB | CMD_SEND_IN_RFKILL,
|
||||||
.data = { &nvm_access_cmd, data },
|
.data = { &nvm_access_cmd, data },
|
||||||
/* data may come from vmalloc, so use _DUP */
|
/* data may come from vmalloc, so use _DUP */
|
||||||
.dataflags = { 0, IWL_HCMD_DFL_DUP },
|
.dataflags = { 0, IWL_HCMD_DFL_DUP },
|
||||||
};
|
};
|
||||||
|
struct iwl_rx_packet *pkt;
|
||||||
|
struct iwl_nvm_access_resp *nvm_resp;
|
||||||
|
int ret;
|
||||||
|
|
||||||
return iwl_mvm_send_cmd(mvm, &cmd);
|
ret = iwl_mvm_send_cmd(mvm, &cmd);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
pkt = cmd.resp_pkt;
|
||||||
|
if (!pkt) {
|
||||||
|
IWL_ERR(mvm, "Error in NVM_ACCESS response\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
/* Extract & check NVM write response */
|
||||||
|
nvm_resp = (void *)pkt->data;
|
||||||
|
if (le16_to_cpu(nvm_resp->status) != READ_NVM_CHUNK_SUCCEED) {
|
||||||
|
IWL_ERR(mvm,
|
||||||
|
"NVM access write command failed for section %u (status = 0x%x)\n",
|
||||||
|
section, le16_to_cpu(nvm_resp->status));
|
||||||
|
ret = -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
iwl_free_resp(&cmd);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section,
|
static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section,
|
||||||
|
@ -210,6 +232,19 @@ static int iwl_nvm_write_section(struct iwl_mvm *mvm, u16 section,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void iwl_mvm_nvm_fixups(struct iwl_mvm *mvm, unsigned int section,
|
||||||
|
u8 *data, unsigned int len)
|
||||||
|
{
|
||||||
|
#define IWL_4165_DEVICE_ID 0x5501
|
||||||
|
#define NVM_SKU_CAP_MIMO_DISABLE BIT(5)
|
||||||
|
|
||||||
|
if (section == NVM_SECTION_TYPE_PHY_SKU &&
|
||||||
|
mvm->trans->hw_id == IWL_4165_DEVICE_ID && data && len >= 5 &&
|
||||||
|
(data[4] & NVM_SKU_CAP_MIMO_DISABLE))
|
||||||
|
/* OTP 0x52 bug work around: it's a 1x1 device */
|
||||||
|
data[3] = ANT_B | (ANT_B << 4);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reads an NVM section completely.
|
* Reads an NVM section completely.
|
||||||
* NICs prior to 7000 family doesn't have a real NVM, but just read
|
* NICs prior to 7000 family doesn't have a real NVM, but just read
|
||||||
|
@ -250,6 +285,8 @@ static int iwl_nvm_read_section(struct iwl_mvm *mvm, u16 section,
|
||||||
offset += ret;
|
offset += ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iwl_mvm_nvm_fixups(mvm, section, data, offset);
|
||||||
|
|
||||||
IWL_DEBUG_EEPROM(mvm->trans->dev,
|
IWL_DEBUG_EEPROM(mvm->trans->dev,
|
||||||
"NVM section %d read completed\n", section);
|
"NVM section %d read completed\n", section);
|
||||||
return offset;
|
return offset;
|
||||||
|
@ -316,8 +353,7 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm)
|
||||||
return iwl_parse_nvm_data(mvm->trans->dev, mvm->cfg, hw, sw, calib,
|
return iwl_parse_nvm_data(mvm->trans->dev, mvm->cfg, hw, sw, calib,
|
||||||
regulatory, mac_override, phy_sku,
|
regulatory, mac_override, phy_sku,
|
||||||
mvm->fw->valid_tx_ant, mvm->fw->valid_rx_ant,
|
mvm->fw->valid_tx_ant, mvm->fw->valid_rx_ant,
|
||||||
lar_enabled, mac_addr0, mac_addr1,
|
lar_enabled, mac_addr0, mac_addr1);
|
||||||
mvm->trans->hw_id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MAX_NVM_FILE_LEN 16384
|
#define MAX_NVM_FILE_LEN 16384
|
||||||
|
@ -353,7 +389,8 @@ static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm)
|
||||||
__le16 word2;
|
__le16 word2;
|
||||||
u8 data[];
|
u8 data[];
|
||||||
} *file_sec;
|
} *file_sec;
|
||||||
const u8 *eof, *temp;
|
const u8 *eof;
|
||||||
|
u8 *temp;
|
||||||
int max_section_size;
|
int max_section_size;
|
||||||
const __le32 *dword_buff;
|
const __le32 *dword_buff;
|
||||||
|
|
||||||
|
@ -483,6 +520,9 @@ static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm)
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iwl_mvm_nvm_fixups(mvm, section_id, temp, section_size);
|
||||||
|
|
||||||
kfree(mvm->nvm_sections[section_id].data);
|
kfree(mvm->nvm_sections[section_id].data);
|
||||||
mvm->nvm_sections[section_id].data = temp;
|
mvm->nvm_sections[section_id].data = temp;
|
||||||
mvm->nvm_sections[section_id].length = section_size;
|
mvm->nvm_sections[section_id].length = section_size;
|
||||||
|
@ -548,6 +588,9 @@ int iwl_nvm_init(struct iwl_mvm *mvm, bool read_nvm_from_nic)
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iwl_mvm_nvm_fixups(mvm, section, temp, ret);
|
||||||
|
|
||||||
mvm->nvm_sections[section].data = temp;
|
mvm->nvm_sections[section].data = temp;
|
||||||
mvm->nvm_sections[section].length = ret;
|
mvm->nvm_sections[section].length = ret;
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
* in the file called COPYING.
|
* in the file called COPYING.
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
*
|
*
|
||||||
* BSD LICENSE
|
* BSD LICENSE
|
||||||
|
|
|
@ -82,6 +82,7 @@
|
||||||
#include "rs.h"
|
#include "rs.h"
|
||||||
#include "fw-api-scan.h"
|
#include "fw-api-scan.h"
|
||||||
#include "time-event.h"
|
#include "time-event.h"
|
||||||
|
#include "fw-dbg.h"
|
||||||
|
|
||||||
#define DRV_DESCRIPTION "The new Intel(R) wireless AGN driver for Linux"
|
#define DRV_DESCRIPTION "The new Intel(R) wireless AGN driver for Linux"
|
||||||
MODULE_DESCRIPTION(DRV_DESCRIPTION);
|
MODULE_DESCRIPTION(DRV_DESCRIPTION);
|
||||||
|
@ -309,6 +310,7 @@ static const char *const iwl_mvm_cmd_strings[REPLY_MAX + 1] = {
|
||||||
CMD(WEP_KEY),
|
CMD(WEP_KEY),
|
||||||
CMD(REPLY_RX_PHY_CMD),
|
CMD(REPLY_RX_PHY_CMD),
|
||||||
CMD(REPLY_RX_MPDU_CMD),
|
CMD(REPLY_RX_MPDU_CMD),
|
||||||
|
CMD(FRAME_RELEASE),
|
||||||
CMD(BEACON_NOTIFICATION),
|
CMD(BEACON_NOTIFICATION),
|
||||||
CMD(BEACON_TEMPLATE_CMD),
|
CMD(BEACON_TEMPLATE_CMD),
|
||||||
CMD(STATISTICS_CMD),
|
CMD(STATISTICS_CMD),
|
||||||
|
@ -362,6 +364,7 @@ static const char *const iwl_mvm_cmd_strings[REPLY_MAX + 1] = {
|
||||||
CMD(TDLS_CONFIG_CMD),
|
CMD(TDLS_CONFIG_CMD),
|
||||||
CMD(MCC_UPDATE_CMD),
|
CMD(MCC_UPDATE_CMD),
|
||||||
CMD(SCAN_ITERATION_COMPLETE_UMAC),
|
CMD(SCAN_ITERATION_COMPLETE_UMAC),
|
||||||
|
CMD(LDBG_CONFIG_CMD),
|
||||||
};
|
};
|
||||||
#undef CMD
|
#undef CMD
|
||||||
|
|
||||||
|
@ -452,7 +455,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
||||||
mvm->first_agg_queue = 12;
|
mvm->first_agg_queue = 12;
|
||||||
}
|
}
|
||||||
mvm->sf_state = SF_UNINIT;
|
mvm->sf_state = SF_UNINIT;
|
||||||
mvm->low_latency_agg_frame_limit = 6;
|
|
||||||
mvm->cur_ucode = IWL_UCODE_INIT;
|
mvm->cur_ucode = IWL_UCODE_INIT;
|
||||||
|
|
||||||
mutex_init(&mvm->mutex);
|
mutex_init(&mvm->mutex);
|
||||||
|
@ -485,7 +487,21 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
||||||
trans_cfg.op_mode = op_mode;
|
trans_cfg.op_mode = op_mode;
|
||||||
trans_cfg.no_reclaim_cmds = no_reclaim_cmds;
|
trans_cfg.no_reclaim_cmds = no_reclaim_cmds;
|
||||||
trans_cfg.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds);
|
trans_cfg.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds);
|
||||||
trans_cfg.rx_buf_size_8k = iwlwifi_mod_params.amsdu_size_8K;
|
switch (iwlwifi_mod_params.amsdu_size) {
|
||||||
|
case IWL_AMSDU_4K:
|
||||||
|
trans_cfg.rx_buf_size = IWL_AMSDU_4K;
|
||||||
|
break;
|
||||||
|
case IWL_AMSDU_8K:
|
||||||
|
trans_cfg.rx_buf_size = IWL_AMSDU_8K;
|
||||||
|
break;
|
||||||
|
case IWL_AMSDU_12K:
|
||||||
|
trans_cfg.rx_buf_size = IWL_AMSDU_12K;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
pr_err("%s: Unsupported amsdu_size: %d\n", KBUILD_MODNAME,
|
||||||
|
iwlwifi_mod_params.amsdu_size);
|
||||||
|
trans_cfg.rx_buf_size = IWL_AMSDU_4K;
|
||||||
|
}
|
||||||
trans_cfg.wide_cmd_header = fw_has_api(&mvm->fw->ucode_capa,
|
trans_cfg.wide_cmd_header = fw_has_api(&mvm->fw->ucode_capa,
|
||||||
IWL_UCODE_TLV_API_WIDE_CMD_HDR);
|
IWL_UCODE_TLV_API_WIDE_CMD_HDR);
|
||||||
|
|
||||||
|
@ -628,12 +644,6 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode)
|
||||||
|
|
||||||
#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);
|
||||||
if (mvm->nd_config) {
|
|
||||||
kfree(mvm->nd_config->match_sets);
|
|
||||||
kfree(mvm->nd_config->scan_plans);
|
|
||||||
kfree(mvm->nd_config);
|
|
||||||
mvm->nd_config = NULL;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
iwl_trans_op_mode_leave(mvm->trans);
|
iwl_trans_op_mode_leave(mvm->trans);
|
||||||
|
@ -1196,6 +1206,11 @@ int iwl_mvm_enter_d0i3(struct iwl_op_mode *op_mode)
|
||||||
/* make sure we have no running tx while configuring the seqno */
|
/* make sure we have no running tx while configuring the seqno */
|
||||||
synchronize_net();
|
synchronize_net();
|
||||||
|
|
||||||
|
/* Flush the hw queues, in case something got queued during entry */
|
||||||
|
ret = iwl_mvm_flush_tx_path(mvm, iwl_mvm_flushable_queues(mvm), flags);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
/* configure wowlan configuration only if needed */
|
/* configure wowlan configuration only if needed */
|
||||||
if (mvm->d0i3_ap_sta_id != IWL_MVM_STATION_COUNT) {
|
if (mvm->d0i3_ap_sta_id != IWL_MVM_STATION_COUNT) {
|
||||||
iwl_mvm_set_wowlan_data(mvm, &wowlan_config_cmd,
|
iwl_mvm_set_wowlan_data(mvm, &wowlan_config_cmd,
|
||||||
|
|
|
@ -1827,7 +1827,7 @@ static int rs_switch_to_column(struct iwl_mvm *mvm,
|
||||||
rate->type = lq_sta->is_vht ? LQ_VHT_MIMO2 : LQ_HT_MIMO2;
|
rate->type = lq_sta->is_vht ? LQ_VHT_MIMO2 : LQ_HT_MIMO2;
|
||||||
rate_mask = lq_sta->active_mimo2_rate;
|
rate_mask = lq_sta->active_mimo2_rate;
|
||||||
} else {
|
} else {
|
||||||
WARN_ON_ONCE("Bad column mode");
|
WARN_ONCE(1, "Bad column mode");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (column->mode != RS_LEGACY) {
|
if (column->mode != RS_LEGACY) {
|
||||||
|
@ -3454,15 +3454,9 @@ static void rs_fill_lq_cmd(struct iwl_mvm *mvm,
|
||||||
* Tx Fifo so that it can start a transaction in the same TxOP. This
|
* Tx Fifo so that it can start a transaction in the same TxOP. This
|
||||||
* basically allows the firmware to send bursts.
|
* basically allows the firmware to send bursts.
|
||||||
*/
|
*/
|
||||||
if (iwl_mvm_vif_low_latency(mvmvif)) {
|
if (iwl_mvm_vif_low_latency(mvmvif))
|
||||||
lq_cmd->agg_frame_cnt_limit--;
|
lq_cmd->agg_frame_cnt_limit--;
|
||||||
|
|
||||||
if (mvm->low_latency_agg_frame_limit)
|
|
||||||
lq_cmd->agg_frame_cnt_limit =
|
|
||||||
min(lq_cmd->agg_frame_cnt_limit,
|
|
||||||
mvm->low_latency_agg_frame_limit);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mvmsta->vif->p2p)
|
if (mvmsta->vif->p2p)
|
||||||
lq_cmd->flags |= LQ_FLAG_USE_RTS_MSK;
|
lq_cmd->flags |= LQ_FLAG_USE_RTS_MSK;
|
||||||
|
|
||||||
|
|
|
@ -61,10 +61,12 @@
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
#include <linux/etherdevice.h>
|
||||||
#include <linux/skbuff.h>
|
#include <linux/skbuff.h>
|
||||||
#include "iwl-trans.h"
|
#include "iwl-trans.h"
|
||||||
#include "mvm.h"
|
#include "mvm.h"
|
||||||
#include "fw-api.h"
|
#include "fw-api.h"
|
||||||
|
#include "fw-dbg.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* iwl_mvm_rx_rx_phy_cmd - REPLY_RX_PHY_CMD handler
|
* iwl_mvm_rx_rx_phy_cmd - REPLY_RX_PHY_CMD handler
|
||||||
|
@ -261,7 +263,7 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi,
|
||||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||||
struct iwl_rx_phy_info *phy_info;
|
struct iwl_rx_phy_info *phy_info;
|
||||||
struct iwl_rx_mpdu_res_start *rx_res;
|
struct iwl_rx_mpdu_res_start *rx_res;
|
||||||
struct ieee80211_sta *sta;
|
struct ieee80211_sta *sta = NULL;
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
u32 len;
|
u32 len;
|
||||||
u32 ampdu_status;
|
u32 ampdu_status;
|
||||||
|
@ -332,22 +334,33 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi,
|
||||||
(unsigned long long)rx_status->mactime);
|
(unsigned long long)rx_status->mactime);
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
/*
|
if (rx_pkt_status & RX_MPDU_RES_STATUS_SRC_STA_FOUND) {
|
||||||
* We have tx blocked stations (with CS bit). If we heard frames from
|
u32 id = rx_pkt_status & RX_MPDU_RES_STATUS_STA_ID_MSK;
|
||||||
* a blocked station on a new channel we can TX to it again.
|
|
||||||
*/
|
id >>= RX_MDPU_RES_STATUS_STA_ID_SHIFT;
|
||||||
if (unlikely(mvm->csa_tx_block_bcn_timeout)) {
|
|
||||||
sta = ieee80211_find_sta(
|
if (!WARN_ON_ONCE(id >= IWL_MVM_STATION_COUNT)) {
|
||||||
rcu_dereference(mvm->csa_tx_blocked_vif), hdr->addr2);
|
sta = rcu_dereference(mvm->fw_id_to_mac_id[id]);
|
||||||
if (sta)
|
if (IS_ERR(sta))
|
||||||
iwl_mvm_sta_modify_disable_tx_ap(mvm, sta, false);
|
sta = NULL;
|
||||||
|
}
|
||||||
|
} else if (!is_multicast_ether_addr(hdr->addr2)) {
|
||||||
|
/* This is fine since we prevent two stations with the same
|
||||||
|
* address from being added.
|
||||||
|
*/
|
||||||
|
sta = ieee80211_find_sta_by_ifaddr(mvm->hw, hdr->addr2, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is fine since we don't support multiple AP interfaces */
|
|
||||||
sta = ieee80211_find_sta_by_ifaddr(mvm->hw, hdr->addr2, NULL);
|
|
||||||
if (sta) {
|
if (sta) {
|
||||||
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||||
|
|
||||||
|
/* We have tx blocked stations (with CS bit). If we heard
|
||||||
|
* frames from a blocked station on a new channel we can
|
||||||
|
* TX to it again.
|
||||||
|
*/
|
||||||
|
if (unlikely(mvm->csa_tx_block_bcn_timeout))
|
||||||
|
iwl_mvm_sta_modify_disable_tx_ap(mvm, sta, false);
|
||||||
|
|
||||||
rs_update_last_rssi(mvm, &mvmsta->lq_sta, rx_status);
|
rs_update_last_rssi(mvm, &mvmsta->lq_sta, rx_status);
|
||||||
|
|
||||||
if (iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_RSSI) &&
|
if (iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_RSSI) &&
|
||||||
|
@ -368,11 +381,10 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi,
|
||||||
if (trig_check && rx_status->signal < rssi)
|
if (trig_check && rx_status->signal < rssi)
|
||||||
iwl_mvm_fw_dbg_collect_trig(mvm, trig, NULL);
|
iwl_mvm_fw_dbg_collect_trig(mvm, trig, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ieee80211_is_data(hdr->frame_control))
|
||||||
|
iwl_mvm_rx_csum(sta, skb, rx_pkt_status);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sta && ieee80211_is_data(hdr->frame_control))
|
|
||||||
iwl_mvm_rx_csum(sta, skb, rx_pkt_status);
|
|
||||||
|
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
|
||||||
/* set the preamble flag if appropriate */
|
/* set the preamble flag if appropriate */
|
||||||
|
|
|
@ -333,6 +333,13 @@ void iwl_mvm_rx_lmac_scan_complete_notif(struct iwl_mvm *mvm,
|
||||||
struct iwl_periodic_scan_complete *scan_notif = (void *)pkt->data;
|
struct iwl_periodic_scan_complete *scan_notif = (void *)pkt->data;
|
||||||
bool aborted = (scan_notif->status == IWL_SCAN_OFFLOAD_ABORTED);
|
bool aborted = (scan_notif->status == IWL_SCAN_OFFLOAD_ABORTED);
|
||||||
|
|
||||||
|
/* If this happens, the firmware has mistakenly sent an LMAC
|
||||||
|
* notification during UMAC scans -- warn and ignore it.
|
||||||
|
*/
|
||||||
|
if (WARN_ON_ONCE(fw_has_capa(&mvm->fw->ucode_capa,
|
||||||
|
IWL_UCODE_TLV_CAPA_UMAC_SCAN)))
|
||||||
|
return;
|
||||||
|
|
||||||
/* scan status must be locked for proper checking */
|
/* scan status must be locked for proper checking */
|
||||||
lockdep_assert_held(&mvm->mutex);
|
lockdep_assert_held(&mvm->mutex);
|
||||||
|
|
||||||
|
@ -920,6 +927,8 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm)
|
||||||
if (!scan_config)
|
if (!scan_config)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
mvm->scan_fragmented = iwl_mvm_low_latency(mvm);
|
||||||
|
|
||||||
scan_config->flags = cpu_to_le32(SCAN_CONFIG_FLAG_ACTIVATE |
|
scan_config->flags = cpu_to_le32(SCAN_CONFIG_FLAG_ACTIVATE |
|
||||||
SCAN_CONFIG_FLAG_ALLOW_CHUB_REQS |
|
SCAN_CONFIG_FLAG_ALLOW_CHUB_REQS |
|
||||||
SCAN_CONFIG_FLAG_SET_TX_CHAINS |
|
SCAN_CONFIG_FLAG_SET_TX_CHAINS |
|
||||||
|
@ -928,7 +937,10 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm)
|
||||||
SCAN_CONFIG_FLAG_SET_LEGACY_RATES |
|
SCAN_CONFIG_FLAG_SET_LEGACY_RATES |
|
||||||
SCAN_CONFIG_FLAG_SET_MAC_ADDR |
|
SCAN_CONFIG_FLAG_SET_MAC_ADDR |
|
||||||
SCAN_CONFIG_FLAG_SET_CHANNEL_FLAGS|
|
SCAN_CONFIG_FLAG_SET_CHANNEL_FLAGS|
|
||||||
SCAN_CONFIG_N_CHANNELS(num_channels));
|
SCAN_CONFIG_N_CHANNELS(num_channels) |
|
||||||
|
(mvm->scan_fragmented ?
|
||||||
|
SCAN_CONFIG_FLAG_SET_FRAGMENTED :
|
||||||
|
SCAN_CONFIG_FLAG_CLEAR_FRAGMENTED));
|
||||||
scan_config->tx_chains = cpu_to_le32(iwl_mvm_get_valid_tx_ant(mvm));
|
scan_config->tx_chains = cpu_to_le32(iwl_mvm_get_valid_tx_ant(mvm));
|
||||||
scan_config->rx_chains = cpu_to_le32(iwl_mvm_scan_rx_ant(mvm));
|
scan_config->rx_chains = cpu_to_le32(iwl_mvm_scan_rx_ant(mvm));
|
||||||
scan_config->legacy_rates = iwl_mvm_scan_config_rates(mvm);
|
scan_config->legacy_rates = iwl_mvm_scan_config_rates(mvm);
|
||||||
|
@ -1150,7 +1162,7 @@ static int iwl_mvm_check_running_scans(struct iwl_mvm *mvm, int type)
|
||||||
case IWL_MVM_SCAN_SCHED:
|
case IWL_MVM_SCAN_SCHED:
|
||||||
if (mvm->scan_status & IWL_MVM_SCAN_SCHED_MASK)
|
if (mvm->scan_status & IWL_MVM_SCAN_SCHED_MASK)
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
iwl_mvm_scan_stop(mvm, IWL_MVM_SCAN_REGULAR, true);
|
return iwl_mvm_scan_stop(mvm, IWL_MVM_SCAN_REGULAR, true);
|
||||||
case IWL_MVM_SCAN_NETDETECT:
|
case IWL_MVM_SCAN_NETDETECT:
|
||||||
/* No need to stop anything for net-detect since the
|
/* No need to stop anything for net-detect since the
|
||||||
* firmware is restarted anyway. This way, any sched
|
* firmware is restarted anyway. This way, any sched
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
* in the file called COPYING.
|
* in the file called COPYING.
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
*
|
*
|
||||||
* BSD LICENSE
|
* BSD LICENSE
|
||||||
|
|
|
@ -1201,7 +1201,8 @@ static int iwl_mvm_set_fw_key_idx(struct iwl_mvm *mvm)
|
||||||
return max_offs;
|
return max_offs;
|
||||||
}
|
}
|
||||||
|
|
||||||
static u8 iwl_mvm_get_key_sta_id(struct ieee80211_vif *vif,
|
static u8 iwl_mvm_get_key_sta_id(struct iwl_mvm *mvm,
|
||||||
|
struct ieee80211_vif *vif,
|
||||||
struct ieee80211_sta *sta)
|
struct ieee80211_sta *sta)
|
||||||
{
|
{
|
||||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||||
|
@ -1218,8 +1219,21 @@ static u8 iwl_mvm_get_key_sta_id(struct ieee80211_vif *vif,
|
||||||
* station ID, then use AP's station ID.
|
* station ID, then use AP's station ID.
|
||||||
*/
|
*/
|
||||||
if (vif->type == NL80211_IFTYPE_STATION &&
|
if (vif->type == NL80211_IFTYPE_STATION &&
|
||||||
mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT)
|
mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT) {
|
||||||
return mvmvif->ap_sta_id;
|
u8 sta_id = mvmvif->ap_sta_id;
|
||||||
|
|
||||||
|
sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id],
|
||||||
|
lockdep_is_held(&mvm->mutex));
|
||||||
|
/*
|
||||||
|
* It is possible that the 'sta' parameter is NULL,
|
||||||
|
* for example when a GTK is removed - the sta_id will then
|
||||||
|
* be the AP ID, and no station was passed by mac80211.
|
||||||
|
*/
|
||||||
|
if (IS_ERR_OR_NULL(sta))
|
||||||
|
return IWL_MVM_STATION_COUNT;
|
||||||
|
|
||||||
|
return sta_id;
|
||||||
|
}
|
||||||
|
|
||||||
return IWL_MVM_STATION_COUNT;
|
return IWL_MVM_STATION_COUNT;
|
||||||
}
|
}
|
||||||
|
@ -1227,7 +1241,8 @@ static u8 iwl_mvm_get_key_sta_id(struct ieee80211_vif *vif,
|
||||||
static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm,
|
static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm,
|
||||||
struct iwl_mvm_sta *mvm_sta,
|
struct iwl_mvm_sta *mvm_sta,
|
||||||
struct ieee80211_key_conf *keyconf, bool mcast,
|
struct ieee80211_key_conf *keyconf, bool mcast,
|
||||||
u32 tkip_iv32, u16 *tkip_p1k, u32 cmd_flags)
|
u32 tkip_iv32, u16 *tkip_p1k, u32 cmd_flags,
|
||||||
|
u8 key_offset)
|
||||||
{
|
{
|
||||||
struct iwl_mvm_add_sta_key_cmd cmd = {};
|
struct iwl_mvm_add_sta_key_cmd cmd = {};
|
||||||
__le16 key_flags;
|
__le16 key_flags;
|
||||||
|
@ -1269,7 +1284,7 @@ static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm,
|
||||||
if (mcast)
|
if (mcast)
|
||||||
key_flags |= cpu_to_le16(STA_KEY_MULTICAST);
|
key_flags |= cpu_to_le16(STA_KEY_MULTICAST);
|
||||||
|
|
||||||
cmd.key_offset = keyconf->hw_key_idx;
|
cmd.key_offset = key_offset;
|
||||||
cmd.key_flags = key_flags;
|
cmd.key_flags = key_flags;
|
||||||
cmd.sta_id = sta_id;
|
cmd.sta_id = sta_id;
|
||||||
|
|
||||||
|
@ -1360,6 +1375,7 @@ static int __iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
|
||||||
struct ieee80211_vif *vif,
|
struct ieee80211_vif *vif,
|
||||||
struct ieee80211_sta *sta,
|
struct ieee80211_sta *sta,
|
||||||
struct ieee80211_key_conf *keyconf,
|
struct ieee80211_key_conf *keyconf,
|
||||||
|
u8 key_offset,
|
||||||
bool mcast)
|
bool mcast)
|
||||||
{
|
{
|
||||||
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
|
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
|
||||||
|
@ -1375,17 +1391,17 @@ static int __iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
|
||||||
ieee80211_get_key_rx_seq(keyconf, 0, &seq);
|
ieee80211_get_key_rx_seq(keyconf, 0, &seq);
|
||||||
ieee80211_get_tkip_rx_p1k(keyconf, addr, seq.tkip.iv32, p1k);
|
ieee80211_get_tkip_rx_p1k(keyconf, addr, seq.tkip.iv32, p1k);
|
||||||
ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, mcast,
|
ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, mcast,
|
||||||
seq.tkip.iv32, p1k, 0);
|
seq.tkip.iv32, p1k, 0, key_offset);
|
||||||
break;
|
break;
|
||||||
case WLAN_CIPHER_SUITE_CCMP:
|
case WLAN_CIPHER_SUITE_CCMP:
|
||||||
case WLAN_CIPHER_SUITE_WEP40:
|
case WLAN_CIPHER_SUITE_WEP40:
|
||||||
case WLAN_CIPHER_SUITE_WEP104:
|
case WLAN_CIPHER_SUITE_WEP104:
|
||||||
ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, mcast,
|
ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, mcast,
|
||||||
0, NULL, 0);
|
0, NULL, 0, key_offset);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, mcast,
|
ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, mcast,
|
||||||
0, NULL, 0);
|
0, NULL, 0, key_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -1433,7 +1449,7 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
|
||||||
struct ieee80211_vif *vif,
|
struct ieee80211_vif *vif,
|
||||||
struct ieee80211_sta *sta,
|
struct ieee80211_sta *sta,
|
||||||
struct ieee80211_key_conf *keyconf,
|
struct ieee80211_key_conf *keyconf,
|
||||||
bool have_key_offset)
|
u8 key_offset)
|
||||||
{
|
{
|
||||||
bool mcast = !(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE);
|
bool mcast = !(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE);
|
||||||
u8 sta_id;
|
u8 sta_id;
|
||||||
|
@ -1443,7 +1459,7 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
|
||||||
lockdep_assert_held(&mvm->mutex);
|
lockdep_assert_held(&mvm->mutex);
|
||||||
|
|
||||||
/* Get the station id from the mvm local station table */
|
/* Get the station id from the mvm local station table */
|
||||||
sta_id = iwl_mvm_get_key_sta_id(vif, sta);
|
sta_id = iwl_mvm_get_key_sta_id(mvm, vif, sta);
|
||||||
if (sta_id == IWL_MVM_STATION_COUNT) {
|
if (sta_id == IWL_MVM_STATION_COUNT) {
|
||||||
IWL_ERR(mvm, "Failed to find station id\n");
|
IWL_ERR(mvm, "Failed to find station id\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -1470,18 +1486,25 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
|
||||||
if (WARN_ON_ONCE(iwl_mvm_sta_from_mac80211(sta)->vif != vif))
|
if (WARN_ON_ONCE(iwl_mvm_sta_from_mac80211(sta)->vif != vif))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (!have_key_offset) {
|
/* If the key_offset is not pre-assigned, we need to find a
|
||||||
/*
|
* new offset to use. In normal cases, the offset is not
|
||||||
* The D3 firmware hardcodes the PTK offset to 0, so we have to
|
* pre-assigned, but during HW_RESTART we want to reuse the
|
||||||
* configure it there. As a result, this workaround exists to
|
* same indices, so we pass them when this function is called.
|
||||||
* let the caller set the key offset (hw_key_idx), see d3.c.
|
*
|
||||||
*/
|
* In D3 entry, we need to hardcoded the indices (because the
|
||||||
keyconf->hw_key_idx = iwl_mvm_set_fw_key_idx(mvm);
|
* firmware hardcodes the PTK offset to 0). In this case, we
|
||||||
if (keyconf->hw_key_idx == STA_KEY_IDX_INVALID)
|
* need to make sure we don't overwrite the hw_key_idx in the
|
||||||
|
* keyconf structure, because otherwise we cannot configure
|
||||||
|
* the original ones back when resuming.
|
||||||
|
*/
|
||||||
|
if (key_offset == STA_KEY_IDX_INVALID) {
|
||||||
|
key_offset = iwl_mvm_set_fw_key_idx(mvm);
|
||||||
|
if (key_offset == STA_KEY_IDX_INVALID)
|
||||||
return -ENOSPC;
|
return -ENOSPC;
|
||||||
|
keyconf->hw_key_idx = key_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = __iwl_mvm_set_sta_key(mvm, vif, sta, keyconf, mcast);
|
ret = __iwl_mvm_set_sta_key(mvm, vif, sta, keyconf, key_offset, mcast);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
__clear_bit(keyconf->hw_key_idx, mvm->fw_key_table);
|
__clear_bit(keyconf->hw_key_idx, mvm->fw_key_table);
|
||||||
goto end;
|
goto end;
|
||||||
|
@ -1495,7 +1518,8 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
|
||||||
*/
|
*/
|
||||||
if (keyconf->cipher == WLAN_CIPHER_SUITE_WEP40 ||
|
if (keyconf->cipher == WLAN_CIPHER_SUITE_WEP40 ||
|
||||||
keyconf->cipher == WLAN_CIPHER_SUITE_WEP104) {
|
keyconf->cipher == WLAN_CIPHER_SUITE_WEP104) {
|
||||||
ret = __iwl_mvm_set_sta_key(mvm, vif, sta, keyconf, !mcast);
|
ret = __iwl_mvm_set_sta_key(mvm, vif, sta, keyconf,
|
||||||
|
key_offset, !mcast);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
__clear_bit(keyconf->hw_key_idx, mvm->fw_key_table);
|
__clear_bit(keyconf->hw_key_idx, mvm->fw_key_table);
|
||||||
__iwl_mvm_remove_sta_key(mvm, sta_id, keyconf, mcast);
|
__iwl_mvm_remove_sta_key(mvm, sta_id, keyconf, mcast);
|
||||||
|
@ -1521,7 +1545,7 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm,
|
||||||
lockdep_assert_held(&mvm->mutex);
|
lockdep_assert_held(&mvm->mutex);
|
||||||
|
|
||||||
/* Get the station id from the mvm local station table */
|
/* Get the station id from the mvm local station table */
|
||||||
sta_id = iwl_mvm_get_key_sta_id(vif, sta);
|
sta_id = iwl_mvm_get_key_sta_id(mvm, vif, sta);
|
||||||
|
|
||||||
IWL_DEBUG_WEP(mvm, "mvm remove dynamic key: idx=%d sta=%d\n",
|
IWL_DEBUG_WEP(mvm, "mvm remove dynamic key: idx=%d sta=%d\n",
|
||||||
keyconf->keyidx, sta_id);
|
keyconf->keyidx, sta_id);
|
||||||
|
@ -1547,24 +1571,6 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* It is possible that the 'sta' parameter is NULL, and thus
|
|
||||||
* there is a need to retrieve the sta from the local station table,
|
|
||||||
* for example when a GTK is removed (where the sta_id will then be
|
|
||||||
* the AP ID, and no station was passed by mac80211.)
|
|
||||||
*/
|
|
||||||
if (!sta) {
|
|
||||||
sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id],
|
|
||||||
lockdep_is_held(&mvm->mutex));
|
|
||||||
if (!sta) {
|
|
||||||
IWL_ERR(mvm, "Invalid station id\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (WARN_ON_ONCE(iwl_mvm_sta_from_mac80211(sta)->vif != vif))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
ret = __iwl_mvm_remove_sta_key(mvm, sta_id, keyconf, mcast);
|
ret = __iwl_mvm_remove_sta_key(mvm, sta_id, keyconf, mcast);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -1584,7 +1590,7 @@ void iwl_mvm_update_tkip_key(struct iwl_mvm *mvm,
|
||||||
u16 *phase1key)
|
u16 *phase1key)
|
||||||
{
|
{
|
||||||
struct iwl_mvm_sta *mvm_sta;
|
struct iwl_mvm_sta *mvm_sta;
|
||||||
u8 sta_id = iwl_mvm_get_key_sta_id(vif, sta);
|
u8 sta_id = iwl_mvm_get_key_sta_id(mvm, vif, sta);
|
||||||
bool mcast = !(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE);
|
bool mcast = !(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE);
|
||||||
|
|
||||||
if (WARN_ON_ONCE(sta_id == IWL_MVM_STATION_COUNT))
|
if (WARN_ON_ONCE(sta_id == IWL_MVM_STATION_COUNT))
|
||||||
|
@ -1602,7 +1608,7 @@ void iwl_mvm_update_tkip_key(struct iwl_mvm *mvm,
|
||||||
|
|
||||||
mvm_sta = iwl_mvm_sta_from_mac80211(sta);
|
mvm_sta = iwl_mvm_sta_from_mac80211(sta);
|
||||||
iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, mcast,
|
iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, mcast,
|
||||||
iv32, phase1key, CMD_ASYNC);
|
iv32, phase1key, CMD_ASYNC, keyconf->hw_key_idx);
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -365,8 +365,8 @@ int iwl_mvm_rm_sta_id(struct iwl_mvm *mvm,
|
||||||
int iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
|
int iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
|
||||||
struct ieee80211_vif *vif,
|
struct ieee80211_vif *vif,
|
||||||
struct ieee80211_sta *sta,
|
struct ieee80211_sta *sta,
|
||||||
struct ieee80211_key_conf *key,
|
struct ieee80211_key_conf *keyconf,
|
||||||
bool have_key_offset);
|
u8 key_offset);
|
||||||
int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm,
|
int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm,
|
||||||
struct ieee80211_vif *vif,
|
struct ieee80211_vif *vif,
|
||||||
struct ieee80211_sta *sta,
|
struct ieee80211_sta *sta,
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
* in the file called COPYING.
|
* in the file called COPYING.
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
*
|
*
|
||||||
* BSD LICENSE
|
* BSD LICENSE
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
* in the file called COPYING.
|
* in the file called COPYING.
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
*
|
*
|
||||||
* BSD LICENSE
|
* BSD LICENSE
|
||||||
|
@ -73,6 +73,7 @@
|
||||||
#include "mvm.h"
|
#include "mvm.h"
|
||||||
#include "iwl-io.h"
|
#include "iwl-io.h"
|
||||||
#include "iwl-prph.h"
|
#include "iwl-prph.h"
|
||||||
|
#include "fw-dbg.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For the high priority TE use a time event type that has similar priority to
|
* For the high priority TE use a time event type that has similar priority to
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
* in the file called COPYING.
|
* in the file called COPYING.
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
*
|
*
|
||||||
* BSD LICENSE
|
* BSD LICENSE
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
* in the file called COPYING.
|
* in the file called COPYING.
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
*
|
*
|
||||||
* BSD LICENSE
|
* BSD LICENSE
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
#include "iwl-eeprom-parse.h"
|
#include "iwl-eeprom-parse.h"
|
||||||
#include "mvm.h"
|
#include "mvm.h"
|
||||||
#include "sta.h"
|
#include "sta.h"
|
||||||
|
#include "fw-dbg.h"
|
||||||
|
|
||||||
static void
|
static void
|
||||||
iwl_mvm_bar_check_trigger(struct iwl_mvm *mvm, const u8 *addr,
|
iwl_mvm_bar_check_trigger(struct iwl_mvm *mvm, const u8 *addr,
|
||||||
|
|
|
@ -68,7 +68,7 @@
|
||||||
#include "iwl-debug.h"
|
#include "iwl-debug.h"
|
||||||
#include "iwl-io.h"
|
#include "iwl-io.h"
|
||||||
#include "iwl-prph.h"
|
#include "iwl-prph.h"
|
||||||
|
#include "fw-dbg.h"
|
||||||
#include "mvm.h"
|
#include "mvm.h"
|
||||||
#include "fw-api-rs.h"
|
#include "fw-api-rs.h"
|
||||||
|
|
||||||
|
|
|
@ -377,6 +377,10 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
|
||||||
{IWL_PCI_DEVICE(0x3165, 0x8010, iwl3165_2ac_cfg)},
|
{IWL_PCI_DEVICE(0x3165, 0x8010, iwl3165_2ac_cfg)},
|
||||||
{IWL_PCI_DEVICE(0x3165, 0x8110, iwl3165_2ac_cfg)},
|
{IWL_PCI_DEVICE(0x3165, 0x8110, iwl3165_2ac_cfg)},
|
||||||
|
|
||||||
|
/* 3168 Series */
|
||||||
|
{IWL_PCI_DEVICE(0x24FB, 0x2110, iwl3168_2ac_cfg)},
|
||||||
|
{IWL_PCI_DEVICE(0x24FB, 0x0000, iwl3168_2ac_cfg)},
|
||||||
|
|
||||||
/* 7265 Series */
|
/* 7265 Series */
|
||||||
{IWL_PCI_DEVICE(0x095A, 0x5010, iwl7265_2ac_cfg)},
|
{IWL_PCI_DEVICE(0x095A, 0x5010, iwl7265_2ac_cfg)},
|
||||||
{IWL_PCI_DEVICE(0x095A, 0x5110, iwl7265_2ac_cfg)},
|
{IWL_PCI_DEVICE(0x095A, 0x5110, iwl7265_2ac_cfg)},
|
||||||
|
@ -423,14 +427,21 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
|
||||||
/* 8000 Series */
|
/* 8000 Series */
|
||||||
{IWL_PCI_DEVICE(0x24F3, 0x0010, iwl8260_2ac_cfg)},
|
{IWL_PCI_DEVICE(0x24F3, 0x0010, iwl8260_2ac_cfg)},
|
||||||
{IWL_PCI_DEVICE(0x24F3, 0x1010, iwl8260_2ac_cfg)},
|
{IWL_PCI_DEVICE(0x24F3, 0x1010, iwl8260_2ac_cfg)},
|
||||||
|
{IWL_PCI_DEVICE(0x24F3, 0x0130, iwl8260_2ac_cfg)},
|
||||||
|
{IWL_PCI_DEVICE(0x24F3, 0x1130, iwl8260_2ac_cfg)},
|
||||||
|
{IWL_PCI_DEVICE(0x24F3, 0x0132, iwl8260_2ac_cfg)},
|
||||||
|
{IWL_PCI_DEVICE(0x24F3, 0x1132, iwl8260_2ac_cfg)},
|
||||||
{IWL_PCI_DEVICE(0x24F3, 0x0110, iwl8260_2ac_cfg)},
|
{IWL_PCI_DEVICE(0x24F3, 0x0110, iwl8260_2ac_cfg)},
|
||||||
|
{IWL_PCI_DEVICE(0x24F3, 0x01F0, iwl8260_2ac_cfg)},
|
||||||
|
{IWL_PCI_DEVICE(0x24F3, 0x0012, iwl8260_2ac_cfg)},
|
||||||
|
{IWL_PCI_DEVICE(0x24F3, 0x1012, iwl8260_2ac_cfg)},
|
||||||
{IWL_PCI_DEVICE(0x24F3, 0x1110, iwl8260_2ac_cfg)},
|
{IWL_PCI_DEVICE(0x24F3, 0x1110, iwl8260_2ac_cfg)},
|
||||||
{IWL_PCI_DEVICE(0x24F3, 0x0050, iwl8260_2ac_cfg)},
|
{IWL_PCI_DEVICE(0x24F3, 0x0050, iwl8260_2ac_cfg)},
|
||||||
{IWL_PCI_DEVICE(0x24F3, 0x0250, iwl8260_2ac_cfg)},
|
{IWL_PCI_DEVICE(0x24F3, 0x0250, iwl8260_2ac_cfg)},
|
||||||
{IWL_PCI_DEVICE(0x24F3, 0x1050, iwl8260_2ac_cfg)},
|
{IWL_PCI_DEVICE(0x24F3, 0x1050, iwl8260_2ac_cfg)},
|
||||||
{IWL_PCI_DEVICE(0x24F3, 0x0150, iwl8260_2ac_cfg)},
|
{IWL_PCI_DEVICE(0x24F3, 0x0150, iwl8260_2ac_cfg)},
|
||||||
|
{IWL_PCI_DEVICE(0x24F3, 0x1150, iwl8260_2ac_cfg)},
|
||||||
{IWL_PCI_DEVICE(0x24F4, 0x0030, iwl8260_2ac_cfg)},
|
{IWL_PCI_DEVICE(0x24F4, 0x0030, iwl8260_2ac_cfg)},
|
||||||
{IWL_PCI_DEVICE(0x24F4, 0x1130, iwl8260_2ac_cfg)},
|
|
||||||
{IWL_PCI_DEVICE(0x24F4, 0x1030, iwl8260_2ac_cfg)},
|
{IWL_PCI_DEVICE(0x24F4, 0x1030, iwl8260_2ac_cfg)},
|
||||||
{IWL_PCI_DEVICE(0x24F3, 0xC010, iwl8260_2ac_cfg)},
|
{IWL_PCI_DEVICE(0x24F3, 0xC010, iwl8260_2ac_cfg)},
|
||||||
{IWL_PCI_DEVICE(0x24F3, 0xC110, iwl8260_2ac_cfg)},
|
{IWL_PCI_DEVICE(0x24F3, 0xC110, iwl8260_2ac_cfg)},
|
||||||
|
@ -438,18 +449,43 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
|
||||||
{IWL_PCI_DEVICE(0x24F3, 0xC050, iwl8260_2ac_cfg)},
|
{IWL_PCI_DEVICE(0x24F3, 0xC050, iwl8260_2ac_cfg)},
|
||||||
{IWL_PCI_DEVICE(0x24F3, 0xD050, iwl8260_2ac_cfg)},
|
{IWL_PCI_DEVICE(0x24F3, 0xD050, iwl8260_2ac_cfg)},
|
||||||
{IWL_PCI_DEVICE(0x24F3, 0x8010, iwl8260_2ac_cfg)},
|
{IWL_PCI_DEVICE(0x24F3, 0x8010, iwl8260_2ac_cfg)},
|
||||||
|
{IWL_PCI_DEVICE(0x24F3, 0x8110, iwl8260_2ac_cfg)},
|
||||||
{IWL_PCI_DEVICE(0x24F3, 0x9010, iwl8260_2ac_cfg)},
|
{IWL_PCI_DEVICE(0x24F3, 0x9010, iwl8260_2ac_cfg)},
|
||||||
|
{IWL_PCI_DEVICE(0x24F3, 0x9110, iwl8260_2ac_cfg)},
|
||||||
{IWL_PCI_DEVICE(0x24F4, 0x8030, iwl8260_2ac_cfg)},
|
{IWL_PCI_DEVICE(0x24F4, 0x8030, iwl8260_2ac_cfg)},
|
||||||
{IWL_PCI_DEVICE(0x24F4, 0x9030, iwl8260_2ac_cfg)},
|
{IWL_PCI_DEVICE(0x24F4, 0x9030, iwl8260_2ac_cfg)},
|
||||||
|
{IWL_PCI_DEVICE(0x24F3, 0x8130, iwl8260_2ac_cfg)},
|
||||||
|
{IWL_PCI_DEVICE(0x24F3, 0x9130, iwl8260_2ac_cfg)},
|
||||||
|
{IWL_PCI_DEVICE(0x24F3, 0x8132, iwl8260_2ac_cfg)},
|
||||||
|
{IWL_PCI_DEVICE(0x24F3, 0x9132, iwl8260_2ac_cfg)},
|
||||||
{IWL_PCI_DEVICE(0x24F3, 0x8050, iwl8260_2ac_cfg)},
|
{IWL_PCI_DEVICE(0x24F3, 0x8050, iwl8260_2ac_cfg)},
|
||||||
|
{IWL_PCI_DEVICE(0x24F3, 0x8150, iwl8260_2ac_cfg)},
|
||||||
{IWL_PCI_DEVICE(0x24F3, 0x9050, iwl8260_2ac_cfg)},
|
{IWL_PCI_DEVICE(0x24F3, 0x9050, iwl8260_2ac_cfg)},
|
||||||
|
{IWL_PCI_DEVICE(0x24F3, 0x9150, iwl8260_2ac_cfg)},
|
||||||
{IWL_PCI_DEVICE(0x24F3, 0x0004, iwl8260_2n_cfg)},
|
{IWL_PCI_DEVICE(0x24F3, 0x0004, iwl8260_2n_cfg)},
|
||||||
|
{IWL_PCI_DEVICE(0x24F3, 0x0044, iwl8260_2n_cfg)},
|
||||||
{IWL_PCI_DEVICE(0x24F5, 0x0010, iwl4165_2ac_cfg)},
|
{IWL_PCI_DEVICE(0x24F5, 0x0010, iwl4165_2ac_cfg)},
|
||||||
{IWL_PCI_DEVICE(0x24F6, 0x0030, iwl4165_2ac_cfg)},
|
{IWL_PCI_DEVICE(0x24F6, 0x0030, iwl4165_2ac_cfg)},
|
||||||
{IWL_PCI_DEVICE(0x24F3, 0x0810, iwl8260_2ac_cfg)},
|
{IWL_PCI_DEVICE(0x24F3, 0x0810, iwl8260_2ac_cfg)},
|
||||||
{IWL_PCI_DEVICE(0x24F3, 0x0910, iwl8260_2ac_cfg)},
|
{IWL_PCI_DEVICE(0x24F3, 0x0910, iwl8260_2ac_cfg)},
|
||||||
{IWL_PCI_DEVICE(0x24F3, 0x0850, iwl8260_2ac_cfg)},
|
{IWL_PCI_DEVICE(0x24F3, 0x0850, iwl8260_2ac_cfg)},
|
||||||
{IWL_PCI_DEVICE(0x24F3, 0x0950, iwl8260_2ac_cfg)},
|
{IWL_PCI_DEVICE(0x24F3, 0x0950, iwl8260_2ac_cfg)},
|
||||||
|
{IWL_PCI_DEVICE(0x24F3, 0x0930, iwl8260_2ac_cfg)},
|
||||||
|
{IWL_PCI_DEVICE(0x24FD, 0x0000, iwl8265_2ac_cfg)},
|
||||||
|
{IWL_PCI_DEVICE(0x24FD, 0x0010, iwl8265_2ac_cfg)},
|
||||||
|
|
||||||
|
/* 9000 Series */
|
||||||
|
{IWL_PCI_DEVICE(0x9DF0, 0x2A10, iwl5165_2ac_cfg)},
|
||||||
|
{IWL_PCI_DEVICE(0x9DF0, 0x2010, iwl5165_2ac_cfg)},
|
||||||
|
{IWL_PCI_DEVICE(0x9DF0, 0x0A10, iwl9260_2ac_cfg)},
|
||||||
|
{IWL_PCI_DEVICE(0x9DF0, 0x0010, iwl9260_2ac_cfg)},
|
||||||
|
{IWL_PCI_DEVICE(0x9DF0, 0x0000, iwl9260_2ac_cfg)},
|
||||||
|
{IWL_PCI_DEVICE(0x9DF0, 0x0310, iwl5165_2ac_cfg)},
|
||||||
|
{IWL_PCI_DEVICE(0x9DF0, 0x0510, iwl9260_2ac_cfg)},
|
||||||
|
{IWL_PCI_DEVICE(0x9DF0, 0x0710, iwl9260_2ac_cfg)},
|
||||||
|
{IWL_PCI_DEVICE(0x9DF0, 0x0210, iwl5165_2ac_cfg)},
|
||||||
|
{IWL_PCI_DEVICE(0x9DF0, 0x0410, iwl9260_2ac_cfg)},
|
||||||
|
{IWL_PCI_DEVICE(0x9DF0, 0x0610, iwl9260_2ac_cfg)},
|
||||||
#endif /* CONFIG_IWLMVM */
|
#endif /* CONFIG_IWLMVM */
|
||||||
|
|
||||||
{0}
|
{0}
|
||||||
|
@ -581,7 +617,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||||
set_dflt_pwr_limit(iwl_trans, pdev);
|
set_dflt_pwr_limit(iwl_trans, pdev);
|
||||||
|
|
||||||
/* register transport layer debugfs here */
|
/* register transport layer debugfs here */
|
||||||
ret = iwl_trans_dbgfs_register(iwl_trans, iwl_trans->dbgfs_dir);
|
ret = iwl_trans_pcie_dbgfs_register(iwl_trans);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out_free_drv;
|
goto out_free_drv;
|
||||||
|
|
||||||
|
|
|
@ -302,7 +302,7 @@ iwl_pcie_get_scratchbuf_dma(struct iwl_txq *txq, int idx)
|
||||||
* @ucode_write_complete: indicates that the ucode has been copied.
|
* @ucode_write_complete: indicates that the ucode has been copied.
|
||||||
* @ucode_write_waitq: wait queue for uCode load
|
* @ucode_write_waitq: wait queue for uCode load
|
||||||
* @cmd_queue - command queue number
|
* @cmd_queue - command queue number
|
||||||
* @rx_buf_size_8k: 8 kB RX buffer size
|
* @rx_buf_size: Rx buffer size
|
||||||
* @bc_table_dword: true if the BC table expects DWORD (as opposed to bytes)
|
* @bc_table_dword: true if the BC table expects DWORD (as opposed to bytes)
|
||||||
* @scd_set_active: should the transport configure the SCD for HCMD queue
|
* @scd_set_active: should the transport configure the SCD for HCMD queue
|
||||||
* @wide_cmd_header: true when ucode supports wide command header format
|
* @wide_cmd_header: true when ucode supports wide command header format
|
||||||
|
@ -356,7 +356,7 @@ struct iwl_trans_pcie {
|
||||||
u8 n_no_reclaim_cmds;
|
u8 n_no_reclaim_cmds;
|
||||||
u8 no_reclaim_cmds[MAX_NO_RECLAIM_CMDS];
|
u8 no_reclaim_cmds[MAX_NO_RECLAIM_CMDS];
|
||||||
|
|
||||||
bool rx_buf_size_8k;
|
enum iwl_amsdu_size rx_buf_size;
|
||||||
bool bc_table_dword;
|
bool bc_table_dword;
|
||||||
bool scd_set_active;
|
bool scd_set_active;
|
||||||
bool wide_cmd_header;
|
bool wide_cmd_header;
|
||||||
|
@ -378,8 +378,11 @@ struct iwl_trans_pcie {
|
||||||
u32 fw_mon_size;
|
u32 fw_mon_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \
|
static inline struct iwl_trans_pcie *
|
||||||
((struct iwl_trans_pcie *) ((_iwl_trans)->trans_specific))
|
IWL_TRANS_GET_PCIE_TRANS(struct iwl_trans *trans)
|
||||||
|
{
|
||||||
|
return (void *)trans->trans_specific;
|
||||||
|
}
|
||||||
|
|
||||||
static inline struct iwl_trans *
|
static inline struct iwl_trans *
|
||||||
iwl_trans_pcie_get_trans(struct iwl_trans_pcie *trans_pcie)
|
iwl_trans_pcie_get_trans(struct iwl_trans_pcie *trans_pcie)
|
||||||
|
@ -566,4 +569,13 @@ static inline void __iwl_trans_pcie_set_bit(struct iwl_trans *trans,
|
||||||
|
|
||||||
void iwl_trans_pcie_rf_kill(struct iwl_trans *trans, bool state);
|
void iwl_trans_pcie_rf_kill(struct iwl_trans *trans, bool state);
|
||||||
|
|
||||||
|
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||||
|
int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans);
|
||||||
|
#else
|
||||||
|
static inline int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* __iwl_trans_int_pcie_h__ */
|
#endif /* __iwl_trans_int_pcie_h__ */
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
* file called LICENSE.
|
* file called LICENSE.
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
*
|
*
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
@ -602,10 +602,20 @@ static void iwl_pcie_rx_hw_init(struct iwl_trans *trans, struct iwl_rxq *rxq)
|
||||||
u32 rb_size;
|
u32 rb_size;
|
||||||
const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */
|
const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */
|
||||||
|
|
||||||
if (trans_pcie->rx_buf_size_8k)
|
switch (trans_pcie->rx_buf_size) {
|
||||||
rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K;
|
case IWL_AMSDU_4K:
|
||||||
else
|
|
||||||
rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K;
|
rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K;
|
||||||
|
break;
|
||||||
|
case IWL_AMSDU_8K:
|
||||||
|
rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K;
|
||||||
|
break;
|
||||||
|
case IWL_AMSDU_12K:
|
||||||
|
rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_12K;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
WARN_ON(1);
|
||||||
|
rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K;
|
||||||
|
}
|
||||||
|
|
||||||
/* Stop Rx DMA */
|
/* Stop Rx DMA */
|
||||||
iwl_write_direct32(trans, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
|
iwl_write_direct32(trans, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
|
||||||
|
@ -629,7 +639,7 @@ static void iwl_pcie_rx_hw_init(struct iwl_trans *trans, struct iwl_rxq *rxq)
|
||||||
* FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY is set because of HW bug in
|
* FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY is set because of HW bug in
|
||||||
* the credit mechanism in 5000 HW RX FIFO
|
* the credit mechanism in 5000 HW RX FIFO
|
||||||
* Direct rx interrupts to hosts
|
* Direct rx interrupts to hosts
|
||||||
* Rx buffer size 4 or 8k
|
* Rx buffer size 4 or 8k or 12k
|
||||||
* RB timeout 0x10
|
* RB timeout 0x10
|
||||||
* 256 RBDs
|
* 256 RBDs
|
||||||
*/
|
*/
|
||||||
|
@ -986,8 +996,7 @@ static void iwl_pcie_rx_handle(struct iwl_trans *trans)
|
||||||
rxb = rxq->queue[i];
|
rxb = rxq->queue[i];
|
||||||
rxq->queue[i] = NULL;
|
rxq->queue[i] = NULL;
|
||||||
|
|
||||||
IWL_DEBUG_RX(trans, "rxbuf: HW = %d, SW = %d (%p)\n",
|
IWL_DEBUG_RX(trans, "rxbuf: HW = %d, SW = %d\n", r, i);
|
||||||
r, i, rxb);
|
|
||||||
iwl_pcie_rx_handle_rb(trans, rxb, emergency);
|
iwl_pcie_rx_handle_rb(trans, rxb, emergency);
|
||||||
|
|
||||||
i = (i + 1) & RX_QUEUE_MASK;
|
i = (i + 1) & RX_QUEUE_MASK;
|
||||||
|
@ -1481,10 +1490,6 @@ int iwl_pcie_alloc_ict(struct iwl_trans *trans)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
IWL_DEBUG_ISR(trans, "ict dma addr %Lx ict vir addr %p\n",
|
|
||||||
(unsigned long long)trans_pcie->ict_tbl_dma,
|
|
||||||
trans_pcie->ict_tbl);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1435,11 +1435,9 @@ static void iwl_trans_pcie_configure(struct iwl_trans *trans,
|
||||||
memcpy(trans_pcie->no_reclaim_cmds, trans_cfg->no_reclaim_cmds,
|
memcpy(trans_pcie->no_reclaim_cmds, trans_cfg->no_reclaim_cmds,
|
||||||
trans_pcie->n_no_reclaim_cmds * sizeof(u8));
|
trans_pcie->n_no_reclaim_cmds * sizeof(u8));
|
||||||
|
|
||||||
trans_pcie->rx_buf_size_8k = trans_cfg->rx_buf_size_8k;
|
trans_pcie->rx_buf_size = trans_cfg->rx_buf_size;
|
||||||
if (trans_pcie->rx_buf_size_8k)
|
trans_pcie->rx_page_order =
|
||||||
trans_pcie->rx_page_order = get_order(8 * 1024);
|
iwl_trans_get_rb_size_order(trans_pcie->rx_buf_size);
|
||||||
else
|
|
||||||
trans_pcie->rx_page_order = get_order(4 * 1024);
|
|
||||||
|
|
||||||
trans_pcie->wide_cmd_header = trans_cfg->wide_cmd_header;
|
trans_pcie->wide_cmd_header = trans_cfg->wide_cmd_header;
|
||||||
trans_pcie->command_names = trans_cfg->command_names;
|
trans_pcie->command_names = trans_cfg->command_names;
|
||||||
|
@ -2109,13 +2107,11 @@ DEBUGFS_READ_FILE_OPS(rx_queue);
|
||||||
DEBUGFS_READ_FILE_OPS(tx_queue);
|
DEBUGFS_READ_FILE_OPS(tx_queue);
|
||||||
DEBUGFS_WRITE_FILE_OPS(csr);
|
DEBUGFS_WRITE_FILE_OPS(csr);
|
||||||
|
|
||||||
/*
|
/* Create the debugfs files and directories */
|
||||||
* Create the debugfs files and directories
|
int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans)
|
||||||
*
|
|
||||||
*/
|
|
||||||
static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans,
|
|
||||||
struct dentry *dir)
|
|
||||||
{
|
{
|
||||||
|
struct dentry *dir = trans->dbgfs_dir;
|
||||||
|
|
||||||
DEBUGFS_ADD_FILE(rx_queue, dir, S_IRUSR);
|
DEBUGFS_ADD_FILE(rx_queue, dir, S_IRUSR);
|
||||||
DEBUGFS_ADD_FILE(tx_queue, dir, S_IRUSR);
|
DEBUGFS_ADD_FILE(tx_queue, dir, S_IRUSR);
|
||||||
DEBUGFS_ADD_FILE(interrupt, dir, S_IWUSR | S_IRUSR);
|
DEBUGFS_ADD_FILE(interrupt, dir, S_IWUSR | S_IRUSR);
|
||||||
|
@ -2127,12 +2123,6 @@ static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans,
|
||||||
IWL_ERR(trans, "failed to create the trans debugfs entry\n");
|
IWL_ERR(trans, "failed to create the trans debugfs entry\n");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans,
|
|
||||||
struct dentry *dir)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif /*CONFIG_IWLWIFI_DEBUGFS */
|
#endif /*CONFIG_IWLWIFI_DEBUGFS */
|
||||||
|
|
||||||
static u32 iwl_trans_pcie_get_cmdlen(struct iwl_tfd *tfd)
|
static u32 iwl_trans_pcie_get_cmdlen(struct iwl_tfd *tfd)
|
||||||
|
@ -2146,144 +2136,6 @@ static u32 iwl_trans_pcie_get_cmdlen(struct iwl_tfd *tfd)
|
||||||
return cmdlen;
|
return cmdlen;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct {
|
|
||||||
u32 start, end;
|
|
||||||
} iwl_prph_dump_addr[] = {
|
|
||||||
{ .start = 0x00a00000, .end = 0x00a00000 },
|
|
||||||
{ .start = 0x00a0000c, .end = 0x00a00024 },
|
|
||||||
{ .start = 0x00a0002c, .end = 0x00a0003c },
|
|
||||||
{ .start = 0x00a00410, .end = 0x00a00418 },
|
|
||||||
{ .start = 0x00a00420, .end = 0x00a00420 },
|
|
||||||
{ .start = 0x00a00428, .end = 0x00a00428 },
|
|
||||||
{ .start = 0x00a00430, .end = 0x00a0043c },
|
|
||||||
{ .start = 0x00a00444, .end = 0x00a00444 },
|
|
||||||
{ .start = 0x00a004c0, .end = 0x00a004cc },
|
|
||||||
{ .start = 0x00a004d8, .end = 0x00a004d8 },
|
|
||||||
{ .start = 0x00a004e0, .end = 0x00a004f0 },
|
|
||||||
{ .start = 0x00a00840, .end = 0x00a00840 },
|
|
||||||
{ .start = 0x00a00850, .end = 0x00a00858 },
|
|
||||||
{ .start = 0x00a01004, .end = 0x00a01008 },
|
|
||||||
{ .start = 0x00a01010, .end = 0x00a01010 },
|
|
||||||
{ .start = 0x00a01018, .end = 0x00a01018 },
|
|
||||||
{ .start = 0x00a01024, .end = 0x00a01024 },
|
|
||||||
{ .start = 0x00a0102c, .end = 0x00a01034 },
|
|
||||||
{ .start = 0x00a0103c, .end = 0x00a01040 },
|
|
||||||
{ .start = 0x00a01048, .end = 0x00a01094 },
|
|
||||||
{ .start = 0x00a01c00, .end = 0x00a01c20 },
|
|
||||||
{ .start = 0x00a01c58, .end = 0x00a01c58 },
|
|
||||||
{ .start = 0x00a01c7c, .end = 0x00a01c7c },
|
|
||||||
{ .start = 0x00a01c28, .end = 0x00a01c54 },
|
|
||||||
{ .start = 0x00a01c5c, .end = 0x00a01c5c },
|
|
||||||
{ .start = 0x00a01c60, .end = 0x00a01cdc },
|
|
||||||
{ .start = 0x00a01ce0, .end = 0x00a01d0c },
|
|
||||||
{ .start = 0x00a01d18, .end = 0x00a01d20 },
|
|
||||||
{ .start = 0x00a01d2c, .end = 0x00a01d30 },
|
|
||||||
{ .start = 0x00a01d40, .end = 0x00a01d5c },
|
|
||||||
{ .start = 0x00a01d80, .end = 0x00a01d80 },
|
|
||||||
{ .start = 0x00a01d98, .end = 0x00a01d9c },
|
|
||||||
{ .start = 0x00a01da8, .end = 0x00a01da8 },
|
|
||||||
{ .start = 0x00a01db8, .end = 0x00a01df4 },
|
|
||||||
{ .start = 0x00a01dc0, .end = 0x00a01dfc },
|
|
||||||
{ .start = 0x00a01e00, .end = 0x00a01e2c },
|
|
||||||
{ .start = 0x00a01e40, .end = 0x00a01e60 },
|
|
||||||
{ .start = 0x00a01e68, .end = 0x00a01e6c },
|
|
||||||
{ .start = 0x00a01e74, .end = 0x00a01e74 },
|
|
||||||
{ .start = 0x00a01e84, .end = 0x00a01e90 },
|
|
||||||
{ .start = 0x00a01e9c, .end = 0x00a01ec4 },
|
|
||||||
{ .start = 0x00a01ed0, .end = 0x00a01ee0 },
|
|
||||||
{ .start = 0x00a01f00, .end = 0x00a01f1c },
|
|
||||||
{ .start = 0x00a01f44, .end = 0x00a01ffc },
|
|
||||||
{ .start = 0x00a02000, .end = 0x00a02048 },
|
|
||||||
{ .start = 0x00a02068, .end = 0x00a020f0 },
|
|
||||||
{ .start = 0x00a02100, .end = 0x00a02118 },
|
|
||||||
{ .start = 0x00a02140, .end = 0x00a0214c },
|
|
||||||
{ .start = 0x00a02168, .end = 0x00a0218c },
|
|
||||||
{ .start = 0x00a021c0, .end = 0x00a021c0 },
|
|
||||||
{ .start = 0x00a02400, .end = 0x00a02410 },
|
|
||||||
{ .start = 0x00a02418, .end = 0x00a02420 },
|
|
||||||
{ .start = 0x00a02428, .end = 0x00a0242c },
|
|
||||||
{ .start = 0x00a02434, .end = 0x00a02434 },
|
|
||||||
{ .start = 0x00a02440, .end = 0x00a02460 },
|
|
||||||
{ .start = 0x00a02468, .end = 0x00a024b0 },
|
|
||||||
{ .start = 0x00a024c8, .end = 0x00a024cc },
|
|
||||||
{ .start = 0x00a02500, .end = 0x00a02504 },
|
|
||||||
{ .start = 0x00a0250c, .end = 0x00a02510 },
|
|
||||||
{ .start = 0x00a02540, .end = 0x00a02554 },
|
|
||||||
{ .start = 0x00a02580, .end = 0x00a025f4 },
|
|
||||||
{ .start = 0x00a02600, .end = 0x00a0260c },
|
|
||||||
{ .start = 0x00a02648, .end = 0x00a02650 },
|
|
||||||
{ .start = 0x00a02680, .end = 0x00a02680 },
|
|
||||||
{ .start = 0x00a026c0, .end = 0x00a026d0 },
|
|
||||||
{ .start = 0x00a02700, .end = 0x00a0270c },
|
|
||||||
{ .start = 0x00a02804, .end = 0x00a02804 },
|
|
||||||
{ .start = 0x00a02818, .end = 0x00a0281c },
|
|
||||||
{ .start = 0x00a02c00, .end = 0x00a02db4 },
|
|
||||||
{ .start = 0x00a02df4, .end = 0x00a02fb0 },
|
|
||||||
{ .start = 0x00a03000, .end = 0x00a03014 },
|
|
||||||
{ .start = 0x00a0301c, .end = 0x00a0302c },
|
|
||||||
{ .start = 0x00a03034, .end = 0x00a03038 },
|
|
||||||
{ .start = 0x00a03040, .end = 0x00a03048 },
|
|
||||||
{ .start = 0x00a03060, .end = 0x00a03068 },
|
|
||||||
{ .start = 0x00a03070, .end = 0x00a03074 },
|
|
||||||
{ .start = 0x00a0307c, .end = 0x00a0307c },
|
|
||||||
{ .start = 0x00a03080, .end = 0x00a03084 },
|
|
||||||
{ .start = 0x00a0308c, .end = 0x00a03090 },
|
|
||||||
{ .start = 0x00a03098, .end = 0x00a03098 },
|
|
||||||
{ .start = 0x00a030a0, .end = 0x00a030a0 },
|
|
||||||
{ .start = 0x00a030a8, .end = 0x00a030b4 },
|
|
||||||
{ .start = 0x00a030bc, .end = 0x00a030bc },
|
|
||||||
{ .start = 0x00a030c0, .end = 0x00a0312c },
|
|
||||||
{ .start = 0x00a03c00, .end = 0x00a03c5c },
|
|
||||||
{ .start = 0x00a04400, .end = 0x00a04454 },
|
|
||||||
{ .start = 0x00a04460, .end = 0x00a04474 },
|
|
||||||
{ .start = 0x00a044c0, .end = 0x00a044ec },
|
|
||||||
{ .start = 0x00a04500, .end = 0x00a04504 },
|
|
||||||
{ .start = 0x00a04510, .end = 0x00a04538 },
|
|
||||||
{ .start = 0x00a04540, .end = 0x00a04548 },
|
|
||||||
{ .start = 0x00a04560, .end = 0x00a0457c },
|
|
||||||
{ .start = 0x00a04590, .end = 0x00a04598 },
|
|
||||||
{ .start = 0x00a045c0, .end = 0x00a045f4 },
|
|
||||||
};
|
|
||||||
|
|
||||||
static u32 iwl_trans_pcie_dump_prph(struct iwl_trans *trans,
|
|
||||||
struct iwl_fw_error_dump_data **data)
|
|
||||||
{
|
|
||||||
struct iwl_fw_error_dump_prph *prph;
|
|
||||||
unsigned long flags;
|
|
||||||
u32 prph_len = 0, i;
|
|
||||||
|
|
||||||
if (!iwl_trans_grab_nic_access(trans, false, &flags))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(iwl_prph_dump_addr); i++) {
|
|
||||||
/* The range includes both boundaries */
|
|
||||||
int num_bytes_in_chunk = iwl_prph_dump_addr[i].end -
|
|
||||||
iwl_prph_dump_addr[i].start + 4;
|
|
||||||
int reg;
|
|
||||||
__le32 *val;
|
|
||||||
|
|
||||||
prph_len += sizeof(**data) + sizeof(*prph) + num_bytes_in_chunk;
|
|
||||||
|
|
||||||
(*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PRPH);
|
|
||||||
(*data)->len = cpu_to_le32(sizeof(*prph) +
|
|
||||||
num_bytes_in_chunk);
|
|
||||||
prph = (void *)(*data)->data;
|
|
||||||
prph->prph_start = cpu_to_le32(iwl_prph_dump_addr[i].start);
|
|
||||||
val = (void *)prph->data;
|
|
||||||
|
|
||||||
for (reg = iwl_prph_dump_addr[i].start;
|
|
||||||
reg <= iwl_prph_dump_addr[i].end;
|
|
||||||
reg += 4)
|
|
||||||
*val++ = cpu_to_le32(iwl_trans_pcie_read_prph(trans,
|
|
||||||
reg));
|
|
||||||
*data = iwl_fw_error_next_data(*data);
|
|
||||||
}
|
|
||||||
|
|
||||||
iwl_trans_release_nic_access(trans, &flags);
|
|
||||||
|
|
||||||
return prph_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
static u32 iwl_trans_pcie_dump_rbs(struct iwl_trans *trans,
|
static u32 iwl_trans_pcie_dump_rbs(struct iwl_trans *trans,
|
||||||
struct iwl_fw_error_dump_data **data,
|
struct iwl_fw_error_dump_data **data,
|
||||||
int allocated_rb_nums)
|
int allocated_rb_nums)
|
||||||
|
@ -2384,10 +2236,11 @@ iwl_trans_pci_dump_marbh_monitor(struct iwl_trans *trans,
|
||||||
if (!iwl_trans_grab_nic_access(trans, false, &flags))
|
if (!iwl_trans_grab_nic_access(trans, false, &flags))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
__iwl_write_prph(trans, MON_DMARB_RD_CTL_ADDR, 0x1);
|
iwl_write_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(trans, MON_DMARB_RD_DATA_ADDR);
|
buffer[i] = iwl_read_prph_no_grab(trans,
|
||||||
__iwl_write_prph(trans, MON_DMARB_RD_CTL_ADDR, 0x0);
|
MON_DMARB_RD_DATA_ADDR);
|
||||||
|
iwl_write_prph_no_grab(trans, MON_DMARB_RD_CTL_ADDR, 0x0);
|
||||||
|
|
||||||
iwl_trans_release_nic_access(trans, &flags);
|
iwl_trans_release_nic_access(trans, &flags);
|
||||||
|
|
||||||
|
@ -2535,16 +2388,6 @@ static struct iwl_trans_dump_data
|
||||||
/* CSR registers */
|
/* CSR registers */
|
||||||
len += sizeof(*data) + IWL_CSR_TO_DUMP;
|
len += sizeof(*data) + IWL_CSR_TO_DUMP;
|
||||||
|
|
||||||
/* PRPH registers */
|
|
||||||
for (i = 0; i < ARRAY_SIZE(iwl_prph_dump_addr); i++) {
|
|
||||||
/* The range includes both boundaries */
|
|
||||||
int num_bytes_in_chunk = iwl_prph_dump_addr[i].end -
|
|
||||||
iwl_prph_dump_addr[i].start + 4;
|
|
||||||
|
|
||||||
len += sizeof(*data) + sizeof(struct iwl_fw_error_dump_prph) +
|
|
||||||
num_bytes_in_chunk;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FH registers */
|
/* FH registers */
|
||||||
len += sizeof(*data) + (FH_MEM_UPPER_BOUND - FH_MEM_LOWER_BOUND);
|
len += sizeof(*data) + (FH_MEM_UPPER_BOUND - FH_MEM_LOWER_BOUND);
|
||||||
|
|
||||||
|
@ -2592,7 +2435,6 @@ static struct iwl_trans_dump_data
|
||||||
len += sizeof(*data);
|
len += sizeof(*data);
|
||||||
data = iwl_fw_error_next_data(data);
|
data = iwl_fw_error_next_data(data);
|
||||||
|
|
||||||
len += iwl_trans_pcie_dump_prph(trans, &data);
|
|
||||||
len += iwl_trans_pcie_dump_csr(trans, &data);
|
len += iwl_trans_pcie_dump_csr(trans, &data);
|
||||||
len += iwl_trans_pcie_fh_regs_dump(trans, &data);
|
len += iwl_trans_pcie_fh_regs_dump(trans, &data);
|
||||||
if (dump_rbs)
|
if (dump_rbs)
|
||||||
|
@ -2623,8 +2465,6 @@ static const struct iwl_trans_ops trans_ops_pcie = {
|
||||||
.txq_disable = iwl_trans_pcie_txq_disable,
|
.txq_disable = iwl_trans_pcie_txq_disable,
|
||||||
.txq_enable = iwl_trans_pcie_txq_enable,
|
.txq_enable = iwl_trans_pcie_txq_enable,
|
||||||
|
|
||||||
.dbgfs_register = iwl_trans_pcie_dbgfs_register,
|
|
||||||
|
|
||||||
.wait_tx_queue_empty = iwl_trans_pcie_wait_txq_empty,
|
.wait_tx_queue_empty = iwl_trans_pcie_wait_txq_empty,
|
||||||
.freeze_txq_timer = iwl_trans_pcie_freeze_txq_timer,
|
.freeze_txq_timer = iwl_trans_pcie_freeze_txq_timer,
|
||||||
|
|
||||||
|
@ -2775,10 +2615,10 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
|
||||||
if (iwl_trans_grab_nic_access(trans, false, &flags)) {
|
if (iwl_trans_grab_nic_access(trans, false, &flags)) {
|
||||||
u32 hw_step;
|
u32 hw_step;
|
||||||
|
|
||||||
hw_step = __iwl_read_prph(trans, WFPM_CTRL_REG);
|
hw_step = iwl_read_prph_no_grab(trans, WFPM_CTRL_REG);
|
||||||
hw_step |= ENABLE_WFPM;
|
hw_step |= ENABLE_WFPM;
|
||||||
__iwl_write_prph(trans, WFPM_CTRL_REG, hw_step);
|
iwl_write_prph_no_grab(trans, WFPM_CTRL_REG, hw_step);
|
||||||
hw_step = __iwl_read_prph(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)
|
||||||
trans->hw_rev = (trans->hw_rev & 0xFFFFFFF3) |
|
trans->hw_rev = (trans->hw_rev & 0xFFFFFFF3) |
|
||||||
|
|
Loading…
Reference in New Issue