* 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:
Kalle Valo 2015-12-03 17:23:43 +02:00
commit 2abcd3d40d
88 changed files with 1990 additions and 1163 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,7 @@
/****************************************************************************** /******************************************************************************
* *
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 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);
} }
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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, &gtkdata); iwl_mvm_d3_update_keys, &gtkdata);
/* 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, &gtkdata); iwl_mvm_d3_update_keys, &gtkdata);
if (status->num_of_gtk_rekeys) { if (status->num_of_gtk_rekeys) {
struct ieee80211_key_conf *key; struct ieee80211_key_conf *key;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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