Third batch of updates for v4.16

* Small cleanups in the new rate-scaling code;
 * Some improvements in debugging;
 * New FW API changes;
 * Fix a bug where we got a false-positive warning;
 * Fix forced quota debugfs functionality;
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEF3LNfgb2BPWm68smoUecoho8xfoFAlo6j9kACgkQoUecoho8
 xfrjDxAAm4JLAERLr8ntPzNRh3PdOf53aXUttm5X02jArbKLzz+Na+bnSrWGyIeP
 4LrkJKVoE8/k9ku/mQoDIlD3RPXIrVj8skWGGvg0u7azJLT9icW0F6IWHeAXS251
 lW6bBqNJ0uShRQ7VKRETvZaAs+kcEkdUiqLvtQ27PGSUxoKgjUepV0bMAdYO5kX/
 XCkoszpVXbXsjfcPdhcuW1dLi+sRk11a73up0Gk0a+idP8NzUBx7QtTo77OH8+w6
 BGdFuYOlB8MdpoACUmRh5XmRSv5NqX4/jGbWNjcXya6MoB8bLLGfYZAKGwNpfWcA
 k160Z9ah9ZYEgS5OQ3RSItJZo215dFiKY+Gvkv3NMjSBcpfSV3EX4GC5zaWsW782
 L2Hgs9ylSyMLDAjRKfd8rJER+rfCaj+4YvL/QPLL+DfJtLRQiQNGZSJWuQTi9IQf
 yCtpg4n2XMGiQZzUEHsA3LOhBS6k35y80CQt9djpWFqb4SeKub0y0616Vk+f9+4p
 TEvOYEYeyvd32o5Z+CfiJHzma1btWgD2XD1KzcSbMzEffFACH3NXcuYTtE9mNz8A
 datricRtqmESe2Rm0MgxjOY0PZB+HdfyD0pa3OrToRfQvJQSw7/JVHKBJUNTmbeV
 /K1HBXntlzIwEUxkZL8YZ4bt9mdu2E6oOJx2SWXc0TWNkXBYyNE=
 =gWyv
 -----END PGP SIGNATURE-----

Merge tag 'iwlwifi-next-for-kalle-2017-12-20' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next

Third batch of updates for v4.16

* Small cleanups in the new rate-scaling code;
* Some improvements in debugging;
* New FW API changes;
* Fix a bug where we got a false-positive warning;
* Fix forced quota debugfs functionality;
This commit is contained in:
Kalle Valo 2018-01-11 18:29:54 +02:00
commit a08e61d274
27 changed files with 583 additions and 105 deletions

View File

@ -15,6 +15,7 @@ iwlwifi-objs += fw/notif-wait.o
iwlwifi-$(CONFIG_IWLMVM) += fw/paging.o fw/smem.o fw/init.o fw/dbg.o iwlwifi-$(CONFIG_IWLMVM) += fw/paging.o fw/smem.o fw/init.o fw/dbg.o
iwlwifi-$(CONFIG_IWLMVM) += fw/common_rx.o fw/nvm.o iwlwifi-$(CONFIG_IWLMVM) += fw/common_rx.o fw/nvm.o
iwlwifi-$(CONFIG_ACPI) += fw/acpi.o iwlwifi-$(CONFIG_ACPI) += fw/acpi.o
iwlwifi-$(CONFIG_IWLWIFI_DEBUGFS) += fw/debugfs.o
iwlwifi-objs += $(iwlwifi-m) iwlwifi-objs += $(iwlwifi-m)

View File

@ -250,10 +250,12 @@ struct iwl_mfu_assert_dump_notif {
* The ids for different type of markers to insert into the usniffer logs * The ids for different type of markers to insert into the usniffer logs
* *
* @MARKER_ID_TX_FRAME_LATENCY: TX latency marker * @MARKER_ID_TX_FRAME_LATENCY: TX latency marker
* @MARKER_ID_SYNC_CLOCK: sync FW time and systime
*/ */
enum iwl_mvm_marker_id { enum iwl_mvm_marker_id {
MARKER_ID_TX_FRAME_LATENCY = 1, MARKER_ID_TX_FRAME_LATENCY = 1,
}; /* MARKER_ID_API_E_VER_1 */ MARKER_ID_SYNC_CLOCK = 2,
}; /* MARKER_ID_API_E_VER_2 */
/** /**
* struct iwl_mvm_marker - mark info into the usniffer logs * struct iwl_mvm_marker - mark info into the usniffer logs

View File

@ -67,6 +67,10 @@
* enum iwl_mac_conf_subcmd_ids - mac configuration command IDs * enum iwl_mac_conf_subcmd_ids - mac configuration command IDs
*/ */
enum iwl_mac_conf_subcmd_ids { enum iwl_mac_conf_subcmd_ids {
/**
* @LOW_LATENCY_CMD: &struct iwl_mac_low_latency_cmd
*/
LOW_LATENCY_CMD = 0x3,
/** /**
* @CHANNEL_SWITCH_NOA_NOTIF: &struct iwl_channel_switch_noa_notif * @CHANNEL_SWITCH_NOA_NOTIF: &struct iwl_channel_switch_noa_notif
*/ */
@ -82,4 +86,19 @@ struct iwl_channel_switch_noa_notif {
__le32 id_and_color; __le32 id_and_color;
} __packed; /* CHANNEL_SWITCH_START_NTFY_API_S_VER_1 */ } __packed; /* CHANNEL_SWITCH_START_NTFY_API_S_VER_1 */
/**
* struct iwl_mac_low_latency_cmd - set/clear mac to 'low-latency mode'
*
* @mac_id: MAC ID to whom to apply the low-latency configurations
* @low_latency_rx: 1/0 to set/clear Rx low latency direction
* @low_latency_tx: 1/0 to set/clear Tx low latency direction
* @reserved: reserved for alignment purposes
*/
struct iwl_mac_low_latency_cmd {
__le32 mac_id;
u8 low_latency_rx;
u8 low_latency_tx;
__le16 reserved;
} __packed; /* MAC_LOW_LATENCY_API_S_VER_1 */
#endif /* __iwl_fw_api_mac_cfg_h__ */ #endif /* __iwl_fw_api_mac_cfg_h__ */

View File

@ -71,7 +71,7 @@
* @IWL_TLC_MNG_CFG_FLAGS_BF_MSK: enable BFER * @IWL_TLC_MNG_CFG_FLAGS_BF_MSK: enable BFER
* @IWL_TLC_MNG_CFG_FLAGS_DCM_MSK: enable DCM * @IWL_TLC_MNG_CFG_FLAGS_DCM_MSK: enable DCM
*/ */
enum iwl_tlc_mng_cfg_flags_enum { enum iwl_tlc_mng_cfg_flags {
IWL_TLC_MNG_CFG_FLAGS_CCK_MSK = BIT(0), IWL_TLC_MNG_CFG_FLAGS_CCK_MSK = BIT(0),
IWL_TLC_MNG_CFG_FLAGS_DD_MSK = BIT(1), IWL_TLC_MNG_CFG_FLAGS_DD_MSK = BIT(1),
IWL_TLC_MNG_CFG_FLAGS_STBC_MSK = BIT(2), IWL_TLC_MNG_CFG_FLAGS_STBC_MSK = BIT(2),
@ -81,14 +81,14 @@ enum iwl_tlc_mng_cfg_flags_enum {
}; };
/** /**
* enum iwl_tlc_mng_cfg_cw_enum - channel width options * enum iwl_tlc_mng_cfg_cw - channel width options
* @IWL_TLC_MNG_MAX_CH_WIDTH_20MHZ: 20MHZ channel * @IWL_TLC_MNG_MAX_CH_WIDTH_20MHZ: 20MHZ channel
* @IWL_TLC_MNG_MAX_CH_WIDTH_40MHZ: 40MHZ channel * @IWL_TLC_MNG_MAX_CH_WIDTH_40MHZ: 40MHZ channel
* @IWL_TLC_MNG_MAX_CH_WIDTH_80MHZ: 80MHZ channel * @IWL_TLC_MNG_MAX_CH_WIDTH_80MHZ: 80MHZ channel
* @IWL_TLC_MNG_MAX_CH_WIDTH_160MHZ: 160MHZ channel * @IWL_TLC_MNG_MAX_CH_WIDTH_160MHZ: 160MHZ channel
* @IWL_TLC_MNG_MAX_CH_WIDTH_LAST: maximum value * @IWL_TLC_MNG_MAX_CH_WIDTH_LAST: maximum value
*/ */
enum iwl_tlc_mng_cfg_cw_enum { enum iwl_tlc_mng_cfg_cw {
IWL_TLC_MNG_MAX_CH_WIDTH_20MHZ, IWL_TLC_MNG_MAX_CH_WIDTH_20MHZ,
IWL_TLC_MNG_MAX_CH_WIDTH_40MHZ, IWL_TLC_MNG_MAX_CH_WIDTH_40MHZ,
IWL_TLC_MNG_MAX_CH_WIDTH_80MHZ, IWL_TLC_MNG_MAX_CH_WIDTH_80MHZ,
@ -97,25 +97,25 @@ enum iwl_tlc_mng_cfg_cw_enum {
}; };
/** /**
* enum iwl_tlc_mng_cfg_chains_enum - possible chains * enum iwl_tlc_mng_cfg_chains - possible chains
* @IWL_TLC_MNG_CHAIN_A_MSK: chain A * @IWL_TLC_MNG_CHAIN_A_MSK: chain A
* @IWL_TLC_MNG_CHAIN_B_MSK: chain B * @IWL_TLC_MNG_CHAIN_B_MSK: chain B
* @IWL_TLC_MNG_CHAIN_C_MSK: chain C * @IWL_TLC_MNG_CHAIN_C_MSK: chain C
*/ */
enum iwl_tlc_mng_cfg_chains_enum { enum iwl_tlc_mng_cfg_chains {
IWL_TLC_MNG_CHAIN_A_MSK = BIT(0), IWL_TLC_MNG_CHAIN_A_MSK = BIT(0),
IWL_TLC_MNG_CHAIN_B_MSK = BIT(1), IWL_TLC_MNG_CHAIN_B_MSK = BIT(1),
IWL_TLC_MNG_CHAIN_C_MSK = BIT(2), IWL_TLC_MNG_CHAIN_C_MSK = BIT(2),
}; };
/** /**
* enum iwl_tlc_mng_cfg_gi_enum - guard interval options * enum iwl_tlc_mng_cfg_gi - guard interval options
* @IWL_TLC_MNG_SGI_20MHZ_MSK: enable short GI for 20MHZ * @IWL_TLC_MNG_SGI_20MHZ_MSK: enable short GI for 20MHZ
* @IWL_TLC_MNG_SGI_40MHZ_MSK: enable short GI for 40MHZ * @IWL_TLC_MNG_SGI_40MHZ_MSK: enable short GI for 40MHZ
* @IWL_TLC_MNG_SGI_80MHZ_MSK: enable short GI for 80MHZ * @IWL_TLC_MNG_SGI_80MHZ_MSK: enable short GI for 80MHZ
* @IWL_TLC_MNG_SGI_160MHZ_MSK: enable short GI for 160MHZ * @IWL_TLC_MNG_SGI_160MHZ_MSK: enable short GI for 160MHZ
*/ */
enum iwl_tlc_mng_cfg_gi_enum { enum iwl_tlc_mng_cfg_gi {
IWL_TLC_MNG_SGI_20MHZ_MSK = BIT(0), IWL_TLC_MNG_SGI_20MHZ_MSK = BIT(0),
IWL_TLC_MNG_SGI_40MHZ_MSK = BIT(1), IWL_TLC_MNG_SGI_40MHZ_MSK = BIT(1),
IWL_TLC_MNG_SGI_80MHZ_MSK = BIT(2), IWL_TLC_MNG_SGI_80MHZ_MSK = BIT(2),
@ -123,7 +123,7 @@ enum iwl_tlc_mng_cfg_gi_enum {
}; };
/** /**
* enum iwl_tlc_mng_cfg_mode_enum - supported modes * enum iwl_tlc_mng_cfg_mode - supported modes
* @IWL_TLC_MNG_MODE_CCK: enable CCK * @IWL_TLC_MNG_MODE_CCK: enable CCK
* @IWL_TLC_MNG_MODE_OFDM_NON_HT: enable OFDM (non HT) * @IWL_TLC_MNG_MODE_OFDM_NON_HT: enable OFDM (non HT)
* @IWL_TLC_MNG_MODE_NON_HT: enable non HT * @IWL_TLC_MNG_MODE_NON_HT: enable non HT
@ -133,7 +133,7 @@ enum iwl_tlc_mng_cfg_gi_enum {
* @IWL_TLC_MNG_MODE_INVALID: invalid value * @IWL_TLC_MNG_MODE_INVALID: invalid value
* @IWL_TLC_MNG_MODE_NUM: a count of possible modes * @IWL_TLC_MNG_MODE_NUM: a count of possible modes
*/ */
enum iwl_tlc_mng_cfg_mode_enum { enum iwl_tlc_mng_cfg_mode {
IWL_TLC_MNG_MODE_CCK = 0, IWL_TLC_MNG_MODE_CCK = 0,
IWL_TLC_MNG_MODE_OFDM_NON_HT = IWL_TLC_MNG_MODE_CCK, IWL_TLC_MNG_MODE_OFDM_NON_HT = IWL_TLC_MNG_MODE_CCK,
IWL_TLC_MNG_MODE_NON_HT = IWL_TLC_MNG_MODE_CCK, IWL_TLC_MNG_MODE_NON_HT = IWL_TLC_MNG_MODE_CCK,
@ -145,14 +145,14 @@ enum iwl_tlc_mng_cfg_mode_enum {
}; };
/** /**
* enum iwl_tlc_mng_vht_he_types_enum - VHT HE types * enum iwl_tlc_mng_vht_he_types - VHT HE types
* @IWL_TLC_MNG_VALID_VHT_HE_TYPES_SU: VHT HT single user * @IWL_TLC_MNG_VALID_VHT_HE_TYPES_SU: VHT HT single user
* @IWL_TLC_MNG_VALID_VHT_HE_TYPES_SU_EXT: VHT HT single user extended * @IWL_TLC_MNG_VALID_VHT_HE_TYPES_SU_EXT: VHT HT single user extended
* @IWL_TLC_MNG_VALID_VHT_HE_TYPES_MU: VHT HT multiple users * @IWL_TLC_MNG_VALID_VHT_HE_TYPES_MU: VHT HT multiple users
* @IWL_TLC_MNG_VALID_VHT_HE_TYPES_TRIG_BASED: trigger based * @IWL_TLC_MNG_VALID_VHT_HE_TYPES_TRIG_BASED: trigger based
* @IWL_TLC_MNG_VALID_VHT_HE_TYPES_NUM: a count of possible types * @IWL_TLC_MNG_VALID_VHT_HE_TYPES_NUM: a count of possible types
*/ */
enum iwl_tlc_mng_vht_he_types_enum { enum iwl_tlc_mng_vht_he_types {
IWL_TLC_MNG_VALID_VHT_HE_TYPES_SU = 0, IWL_TLC_MNG_VALID_VHT_HE_TYPES_SU = 0,
IWL_TLC_MNG_VALID_VHT_HE_TYPES_SU_EXT, IWL_TLC_MNG_VALID_VHT_HE_TYPES_SU_EXT,
IWL_TLC_MNG_VALID_VHT_HE_TYPES_MU, IWL_TLC_MNG_VALID_VHT_HE_TYPES_MU,
@ -163,7 +163,7 @@ enum iwl_tlc_mng_vht_he_types_enum {
}; };
/** /**
* enum iwl_tlc_mng_ht_rates_enum - HT/VHT rates * enum iwl_tlc_mng_ht_rates - HT/VHT rates
* @IWL_TLC_MNG_HT_RATE_MCS0: index of MCS0 * @IWL_TLC_MNG_HT_RATE_MCS0: index of MCS0
* @IWL_TLC_MNG_HT_RATE_MCS1: index of MCS1 * @IWL_TLC_MNG_HT_RATE_MCS1: index of MCS1
* @IWL_TLC_MNG_HT_RATE_MCS2: index of MCS2 * @IWL_TLC_MNG_HT_RATE_MCS2: index of MCS2
@ -176,7 +176,7 @@ enum iwl_tlc_mng_vht_he_types_enum {
* @IWL_TLC_MNG_HT_RATE_MCS9: index of MCS9 * @IWL_TLC_MNG_HT_RATE_MCS9: index of MCS9
* @IWL_TLC_MNG_HT_RATE_MAX: maximal rate for HT/VHT * @IWL_TLC_MNG_HT_RATE_MAX: maximal rate for HT/VHT
*/ */
enum iwl_tlc_mng_ht_rates_enum { enum iwl_tlc_mng_ht_rates {
IWL_TLC_MNG_HT_RATE_MCS0 = 0, IWL_TLC_MNG_HT_RATE_MCS0 = 0,
IWL_TLC_MNG_HT_RATE_MCS1, IWL_TLC_MNG_HT_RATE_MCS1,
IWL_TLC_MNG_HT_RATE_MCS2, IWL_TLC_MNG_HT_RATE_MCS2,
@ -198,13 +198,13 @@ enum iwl_tlc_mng_ht_rates_enum {
* @sta_id: station id * @sta_id: station id
* @reserved1: reserved * @reserved1: reserved
* @max_supp_ch_width: channel width * @max_supp_ch_width: channel width
* @flags: bitmask of %IWL_TLC_MNG_CONFIG_FLAGS_ENABLE_\* * @flags: bitmask of &enum iwl_tlc_mng_cfg_flags
* @chains: bitmask of %IWL_TLC_MNG_CHAIN_\* * @chains: bitmask of &enum iwl_tlc_mng_cfg_chains
* @max_supp_ss: valid values are 0-3, 0 - spatial streams are not supported * @max_supp_ss: valid values are 0-3, 0 - spatial streams are not supported
* @valid_vht_he_types: bitmap of %IWL_TLC_MNG_VALID_VHT_HE_TYPES_\* * @valid_vht_he_types: bitmap of &enum iwl_tlc_mng_vht_he_types
* @non_ht_supp_rates: bitmap of supported legacy rates * @non_ht_supp_rates: bitmap of supported legacy rates
* @ht_supp_rates: bitmap of supported HT/VHT rates, valid bits are 0-9 * @ht_supp_rates: bitmap of supported HT/VHT rates, valid bits are 0-9
* @mode: modulation type %IWL_TLC_MNG_MODE_\* * @mode: &enum iwl_tlc_mng_cfg_mode
* @reserved2: reserved * @reserved2: reserved
* @he_supp_rates: bitmap of supported HE rates * @he_supp_rates: bitmap of supported HE rates
* @sgi_ch_width_supp: bitmap of SGI support per channel width * @sgi_ch_width_supp: bitmap of SGI support per channel width

View File

@ -0,0 +1,195 @@
/******************************************************************************
*
* 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) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 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) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 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 "api/commands.h"
#include "debugfs.h"
#define FWRT_DEBUGFS_READ_FILE_OPS(name) \
static ssize_t iwl_dbgfs_##name##_read(struct iwl_fw_runtime *fwrt, \
char *buf, size_t count, \
loff_t *ppos); \
static const struct file_operations iwl_dbgfs_##name##_ops = { \
.read = iwl_dbgfs_##name##_read, \
.open = simple_open, \
.llseek = generic_file_llseek, \
}
#define FWRT_DEBUGFS_WRITE_WRAPPER(name, buflen) \
static ssize_t iwl_dbgfs_##name##_write(struct iwl_fw_runtime *fwrt, \
char *buf, size_t count, \
loff_t *ppos); \
static ssize_t _iwl_dbgfs_##name##_write(struct file *file, \
const char __user *user_buf, \
size_t count, loff_t *ppos) \
{ \
struct iwl_fw_runtime *fwrt = file->private_data; \
char buf[buflen] = {}; \
size_t buf_size = min(count, sizeof(buf) - 1); \
\
if (copy_from_user(buf, user_buf, buf_size)) \
return -EFAULT; \
\
return iwl_dbgfs_##name##_write(fwrt, buf, buf_size, ppos); \
}
#define FWRT_DEBUGFS_READ_WRITE_FILE_OPS(name, buflen) \
FWRT_DEBUGFS_WRITE_WRAPPER(name, buflen) \
static const struct file_operations iwl_dbgfs_##name##_ops = { \
.write = _iwl_dbgfs_##name##_write, \
.read = iwl_dbgfs_##name##_read, \
.open = simple_open, \
.llseek = generic_file_llseek, \
}
#define FWRT_DEBUGFS_WRITE_FILE_OPS(name, buflen) \
FWRT_DEBUGFS_WRITE_WRAPPER(name, buflen) \
static const struct file_operations iwl_dbgfs_##name##_ops = { \
.write = _iwl_dbgfs_##name##_write, \
.open = simple_open, \
.llseek = generic_file_llseek, \
}
#define FWRT_DEBUGFS_ADD_FILE_ALIAS(alias, name, parent, mode) do { \
if (!debugfs_create_file(alias, mode, parent, fwrt, \
&iwl_dbgfs_##name##_ops)) \
goto err; \
} while (0)
#define FWRT_DEBUGFS_ADD_FILE(name, parent, mode) \
FWRT_DEBUGFS_ADD_FILE_ALIAS(#name, name, parent, mode)
static int iwl_fw_send_timestamp_marker_cmd(struct iwl_fw_runtime *fwrt)
{
struct iwl_mvm_marker marker = {
.dw_len = sizeof(struct iwl_mvm_marker) / 4,
.marker_id = MARKER_ID_SYNC_CLOCK,
/* the real timestamp is taken from the ftrace clock
* this is for finding the match between fw and kernel logs
*/
.timestamp = cpu_to_le64(fwrt->timestamp.seq++),
};
struct iwl_host_cmd hcmd = {
.id = MARKER_CMD,
.flags = CMD_ASYNC,
.data[0] = &marker,
.len[0] = sizeof(marker),
};
return iwl_trans_send_cmd(fwrt->trans, &hcmd);
}
static void iwl_fw_timestamp_marker_wk(struct work_struct *work)
{
int ret;
struct iwl_fw_runtime *fwrt =
container_of(work, struct iwl_fw_runtime, timestamp.wk.work);
unsigned long delay = fwrt->timestamp.delay;
ret = iwl_fw_send_timestamp_marker_cmd(fwrt);
if (!ret && delay)
schedule_delayed_work(&fwrt->timestamp.wk,
round_jiffies_relative(delay));
else
IWL_INFO(fwrt,
"stopping timestamp_marker, ret: %d, delay: %u\n",
ret, jiffies_to_msecs(delay) / 1000);
}
static ssize_t iwl_dbgfs_timestamp_marker_write(struct iwl_fw_runtime *fwrt,
char *buf, size_t count,
loff_t *ppos)
{
int ret;
u32 delay;
ret = kstrtou32(buf, 10, &delay);
if (ret < 0)
return ret;
IWL_INFO(fwrt,
"starting timestamp_marker trigger with delay: %us\n",
delay);
iwl_fw_cancel_timestamp(fwrt);
fwrt->timestamp.delay = msecs_to_jiffies(delay * 1000);
schedule_delayed_work(&fwrt->timestamp.wk,
round_jiffies_relative(fwrt->timestamp.delay));
return count;
}
FWRT_DEBUGFS_WRITE_FILE_OPS(timestamp_marker, 10);
int iwl_fwrt_dbgfs_register(struct iwl_fw_runtime *fwrt,
struct dentry *dbgfs_dir)
{
INIT_DELAYED_WORK(&fwrt->timestamp.wk, iwl_fw_timestamp_marker_wk);
FWRT_DEBUGFS_ADD_FILE(timestamp_marker, dbgfs_dir, S_IWUSR);
return 0;
err:
IWL_ERR(fwrt, "Can't create the fwrt debugfs directory\n");
return -ENOMEM;
}

View File

@ -0,0 +1,87 @@
/******************************************************************************
*
* 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) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 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) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 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 "runtime.h"
#ifdef CONFIG_IWLWIFI_DEBUGFS
int iwl_fwrt_dbgfs_register(struct iwl_fw_runtime *fwrt,
struct dentry *dbgfs_dir);
static inline void iwl_fw_cancel_timestamp(struct iwl_fw_runtime *fwrt)
{
fwrt->timestamp.delay = 0;
cancel_delayed_work_sync(&fwrt->timestamp.wk);
}
#else
static inline int iwl_fwrt_dbgfs_register(struct iwl_fw_runtime *fwrt,
struct dentry *dbgfs_dir)
{
return 0;
}
static inline void iwl_fw_cancel_timestamp(struct iwl_fw_runtime *fwrt) {}
#endif /* CONFIG_IWLWIFI_DEBUGFS */

View File

@ -7,7 +7,7 @@
* *
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 Intel Deutschland GmbH * Copyright(c) 2016 - 2017 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
@ -34,7 +34,7 @@
* *
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 Intel Deutschland GmbH * Copyright(c) 2016 - 2017 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
@ -248,6 +248,8 @@ typedef unsigned int __bitwise iwl_ucode_tlv_api_t;
* @IWL_UCODE_TLV_API_NEW_RX_STATS: should new RX STATISTICS API be used * @IWL_UCODE_TLV_API_NEW_RX_STATS: should new RX STATISTICS API be used
* @IWL_UCODE_TLV_API_QUOTA_LOW_LATENCY: Quota command includes a field * @IWL_UCODE_TLV_API_QUOTA_LOW_LATENCY: Quota command includes a field
* indicating low latency direction. * indicating low latency direction.
* @IWL_UCODE_TLV_API_DEPRECATE_TTAK: RX status flag TTAK ok (bit 7) is
* deprecated.
* *
* @NUM_IWL_UCODE_TLV_API: number of bits used * @NUM_IWL_UCODE_TLV_API: number of bits used
*/ */
@ -266,6 +268,7 @@ enum iwl_ucode_tlv_api {
IWL_UCODE_TLV_API_NEW_BEACON_TEMPLATE = (__force iwl_ucode_tlv_api_t)34, IWL_UCODE_TLV_API_NEW_BEACON_TEMPLATE = (__force iwl_ucode_tlv_api_t)34,
IWL_UCODE_TLV_API_NEW_RX_STATS = (__force iwl_ucode_tlv_api_t)35, IWL_UCODE_TLV_API_NEW_RX_STATS = (__force iwl_ucode_tlv_api_t)35,
IWL_UCODE_TLV_API_QUOTA_LOW_LATENCY = (__force iwl_ucode_tlv_api_t)38, IWL_UCODE_TLV_API_QUOTA_LOW_LATENCY = (__force iwl_ucode_tlv_api_t)38,
IWL_UCODE_TLV_API_DEPRECATE_TTAK = (__force iwl_ucode_tlv_api_t)41,
NUM_IWL_UCODE_TLV_API NUM_IWL_UCODE_TLV_API
#ifdef __CHECKER__ #ifdef __CHECKER__
@ -311,6 +314,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_STA_PM_NOTIF: firmware will send STA PM notification * @IWL_UCODE_TLV_CAPA_STA_PM_NOTIF: firmware will send STA PM notification
* @IWL_UCODE_TLV_CAPA_TLC_OFFLOAD: firmware implements rate scaling algorithm * @IWL_UCODE_TLV_CAPA_TLC_OFFLOAD: firmware implements rate scaling algorithm
* @IWL_UCODE_TLV_CAPA_DYNAMIC_QUOTA: firmware implements quota related
* @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 * @IWL_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT: supports bt-coex Multi-priority LUT
@ -366,6 +370,7 @@ enum iwl_ucode_tlv_capa {
IWL_UCODE_TLV_CAPA_CDB_SUPPORT = (__force iwl_ucode_tlv_capa_t)40, IWL_UCODE_TLV_CAPA_CDB_SUPPORT = (__force iwl_ucode_tlv_capa_t)40,
IWL_UCODE_TLV_CAPA_D0I3_END_FIRST = (__force iwl_ucode_tlv_capa_t)41, IWL_UCODE_TLV_CAPA_D0I3_END_FIRST = (__force iwl_ucode_tlv_capa_t)41,
IWL_UCODE_TLV_CAPA_TLC_OFFLOAD = (__force iwl_ucode_tlv_capa_t)43, IWL_UCODE_TLV_CAPA_TLC_OFFLOAD = (__force iwl_ucode_tlv_capa_t)43,
IWL_UCODE_TLV_CAPA_DYNAMIC_QUOTA = (__force iwl_ucode_tlv_capa_t)44,
IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE = (__force iwl_ucode_tlv_capa_t)64, IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE = (__force iwl_ucode_tlv_capa_t)64,
IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS = (__force iwl_ucode_tlv_capa_t)65, IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS = (__force iwl_ucode_tlv_capa_t)65,
IWL_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT = (__force iwl_ucode_tlv_capa_t)67, IWL_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT = (__force iwl_ucode_tlv_capa_t)67,
@ -540,7 +545,7 @@ struct iwl_fw_dbg_mem_seg_tlv {
} __packed; } __packed;
/** /**
* struct iwl_fw_dbg_dest_tlv - configures the destination of the debug data * struct iwl_fw_dbg_dest_tlv_v1 - configures the destination of the debug data
* *
* @version: version of the TLV - currently 0 * @version: version of the TLV - currently 0
* @monitor_mode: &enum iwl_fw_dbg_monitor_mode * @monitor_mode: &enum iwl_fw_dbg_monitor_mode
@ -555,7 +560,7 @@ struct iwl_fw_dbg_mem_seg_tlv {
* *
* This parses IWL_UCODE_TLV_FW_DBG_DEST * This parses IWL_UCODE_TLV_FW_DBG_DEST
*/ */
struct iwl_fw_dbg_dest_tlv { struct iwl_fw_dbg_dest_tlv_v1 {
u8 version; u8 version;
u8 monitor_mode; u8 monitor_mode;
u8 size_power; u8 size_power;
@ -569,6 +574,26 @@ struct iwl_fw_dbg_dest_tlv {
struct iwl_fw_dbg_reg_op reg_ops[0]; struct iwl_fw_dbg_reg_op reg_ops[0];
} __packed; } __packed;
/* Mask of the register for defining the LDBG MAC2SMEM buffer SMEM size */
#define IWL_LDBG_M2S_BUF_SIZE_MSK 0x0fff0000
/* Mask of the register for defining the LDBG MAC2SMEM SMEM base address */
#define IWL_LDBG_M2S_BUF_BA_MSK 0x00000fff
/* The smem buffer chunks are in units of 256 bits */
#define IWL_M2S_UNIT_SIZE 0x100
struct iwl_fw_dbg_dest_tlv {
u8 version;
u8 monitor_mode;
u8 size_power;
u8 reserved;
__le32 cfg_reg;
__le32 write_ptr_reg;
__le32 wrap_count;
u8 base_shift;
u8 size_shift;
struct iwl_fw_dbg_reg_op reg_ops[0];
} __packed;
struct iwl_fw_dbg_conf_hcmd { struct iwl_fw_dbg_conf_hcmd {
u8 id; u8 id;
u8 reserved; u8 reserved;

View File

@ -284,7 +284,7 @@ struct iwl_fw {
struct iwl_fw_cipher_scheme cs[IWL_UCODE_MAX_CS]; struct iwl_fw_cipher_scheme cs[IWL_UCODE_MAX_CS];
u8 human_readable[FW_VER_HUMAN_READABLE_SZ]; u8 human_readable[FW_VER_HUMAN_READABLE_SZ];
struct iwl_fw_dbg_dest_tlv *dbg_dest_tlv; struct iwl_fw_dbg_dest_tlv_v1 *dbg_dest_tlv;
struct iwl_fw_dbg_conf_tlv *dbg_conf_tlv[FW_DBG_CONF_MAX]; struct iwl_fw_dbg_conf_tlv *dbg_conf_tlv[FW_DBG_CONF_MAX];
size_t dbg_conf_tlv_len[FW_DBG_CONF_MAX]; size_t dbg_conf_tlv_len[FW_DBG_CONF_MAX];
struct iwl_fw_dbg_trigger_tlv *dbg_trigger_tlv[FW_DBG_TRIGGER_MAX]; struct iwl_fw_dbg_trigger_tlv *dbg_trigger_tlv[FW_DBG_TRIGGER_MAX];

View File

@ -58,10 +58,12 @@
#include "iwl-drv.h" #include "iwl-drv.h"
#include "runtime.h" #include "runtime.h"
#include "dbg.h" #include "dbg.h"
#include "debugfs.h"
void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans, void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans,
const struct iwl_fw *fw, const struct iwl_fw *fw,
const struct iwl_fw_runtime_ops *ops, void *ops_ctx) const struct iwl_fw_runtime_ops *ops, void *ops_ctx,
struct dentry *dbgfs_dir)
{ {
memset(fwrt, 0, sizeof(*fwrt)); memset(fwrt, 0, sizeof(*fwrt));
fwrt->trans = trans; fwrt->trans = trans;
@ -71,5 +73,12 @@ void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans,
fwrt->ops = ops; fwrt->ops = ops;
fwrt->ops_ctx = ops_ctx; fwrt->ops_ctx = ops_ctx;
INIT_DELAYED_WORK(&fwrt->dump.wk, iwl_fw_error_dump_wk); INIT_DELAYED_WORK(&fwrt->dump.wk, iwl_fw_error_dump_wk);
iwl_fwrt_dbgfs_register(fwrt, dbgfs_dir);
} }
IWL_EXPORT_SYMBOL(iwl_fw_runtime_init); IWL_EXPORT_SYMBOL(iwl_fw_runtime_init);
void iwl_fw_runtime_exit(struct iwl_fw_runtime *fwrt)
{
iwl_fw_cancel_timestamp(fwrt);
}
IWL_EXPORT_SYMBOL(iwl_fw_runtime_exit);

View File

@ -134,11 +134,21 @@ struct iwl_fw_runtime {
/* ts of the beginning of a non-collect fw dbg data period */ /* ts of the beginning of a non-collect fw dbg data period */
unsigned long non_collect_ts_start[FW_DBG_TRIGGER_MAX - 1]; unsigned long non_collect_ts_start[FW_DBG_TRIGGER_MAX - 1];
} dump; } dump;
#ifdef CONFIG_IWLWIFI_DEBUGFS
struct {
struct delayed_work wk;
u32 delay;
u64 seq;
} timestamp;
#endif /* CONFIG_IWLWIFI_DEBUGFS */
}; };
void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans, void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans,
const struct iwl_fw *fw, const struct iwl_fw *fw,
const struct iwl_fw_runtime_ops *ops, void *ops_ctx); const struct iwl_fw_runtime_ops *ops, void *ops_ctx,
struct dentry *dbgfs_dir);
void iwl_fw_runtime_exit(struct iwl_fw_runtime *fwrt);
static inline void iwl_fw_set_current_image(struct iwl_fw_runtime *fwrt, static inline void iwl_fw_set_current_image(struct iwl_fw_runtime *fwrt,
enum iwl_ucode_type cur_fw_img) enum iwl_ucode_type cur_fw_img)

View File

@ -95,7 +95,7 @@ TRACE_EVENT(iwlwifi_dev_tx,
TP_ARGS(dev, skb, tfd, tfdlen, buf0, buf0_len, hdr_len), TP_ARGS(dev, skb, tfd, tfdlen, buf0, buf0_len, hdr_len),
TP_STRUCT__entry( TP_STRUCT__entry(
DEV_ENTRY DEV_ENTRY
__field(void *, skbaddr)
__field(size_t, framelen) __field(size_t, framelen)
__dynamic_array(u8, tfd, tfdlen) __dynamic_array(u8, tfd, tfdlen)
@ -110,6 +110,7 @@ TRACE_EVENT(iwlwifi_dev_tx,
), ),
TP_fast_assign( TP_fast_assign(
DEV_ASSIGN; DEV_ASSIGN;
__entry->skbaddr = skb;
__entry->framelen = buf0_len; __entry->framelen = buf0_len;
if (hdr_len > 0) if (hdr_len > 0)
__entry->framelen += skb->len - hdr_len; __entry->framelen += skb->len - hdr_len;
@ -120,9 +121,9 @@ TRACE_EVENT(iwlwifi_dev_tx,
__get_dynamic_array(buf1), __get_dynamic_array(buf1),
skb->len - hdr_len); skb->len - hdr_len);
), ),
TP_printk("[%s] TX %.2x (%zu bytes)", TP_printk("[%s] TX %.2x (%zu bytes) skbaddr=%p",
__get_str(dev), ((u8 *)__get_dynamic_array(buf0))[0], __get_str(dev), ((u8 *)__get_dynamic_array(buf0))[0],
__entry->framelen) __entry->framelen, __entry->skbaddr)
); );
TRACE_EVENT(iwlwifi_dev_ucode_error, TRACE_EVENT(iwlwifi_dev_ucode_error,

View File

@ -296,7 +296,12 @@ struct iwl_firmware_pieces {
u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr; u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr;
/* FW debug data parsed for driver usage */ /* FW debug data parsed for driver usage */
struct iwl_fw_dbg_dest_tlv *dbg_dest_tlv; bool dbg_dest_tlv_init;
u8 *dbg_dest_ver;
union {
struct iwl_fw_dbg_dest_tlv *dbg_dest_tlv;
struct iwl_fw_dbg_dest_tlv_v1 *dbg_dest_tlv_v1;
};
struct iwl_fw_dbg_conf_tlv *dbg_conf_tlv[FW_DBG_CONF_MAX]; struct iwl_fw_dbg_conf_tlv *dbg_conf_tlv[FW_DBG_CONF_MAX];
size_t dbg_conf_tlv_len[FW_DBG_CONF_MAX]; size_t dbg_conf_tlv_len[FW_DBG_CONF_MAX];
struct iwl_fw_dbg_trigger_tlv *dbg_trigger_tlv[FW_DBG_TRIGGER_MAX]; struct iwl_fw_dbg_trigger_tlv *dbg_trigger_tlv[FW_DBG_TRIGGER_MAX];
@ -930,21 +935,49 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
break; break;
} }
case IWL_UCODE_TLV_FW_DBG_DEST: { case IWL_UCODE_TLV_FW_DBG_DEST: {
struct iwl_fw_dbg_dest_tlv *dest = (void *)tlv_data; struct iwl_fw_dbg_dest_tlv *dest = NULL;
struct iwl_fw_dbg_dest_tlv_v1 *dest_v1 = NULL;
u8 mon_mode;
if (pieces->dbg_dest_tlv) { pieces->dbg_dest_ver = (u8 *)tlv_data;
if (*pieces->dbg_dest_ver == 1) {
dest = (void *)tlv_data;
} else if (*pieces->dbg_dest_ver == 0) {
dest_v1 = (void *)tlv_data;
} else {
IWL_ERR(drv,
"The version is %d, and it is invalid\n",
*pieces->dbg_dest_ver);
break;
}
if (pieces->dbg_dest_tlv_init) {
IWL_ERR(drv, IWL_ERR(drv,
"dbg destination ignored, already exists\n"); "dbg destination ignored, already exists\n");
break; break;
} }
pieces->dbg_dest_tlv = dest; pieces->dbg_dest_tlv_init = true;
IWL_INFO(drv, "Found debug destination: %s\n",
get_fw_dbg_mode_string(dest->monitor_mode)); if (dest_v1) {
pieces->dbg_dest_tlv_v1 = dest_v1;
mon_mode = dest_v1->monitor_mode;
} else {
pieces->dbg_dest_tlv = dest;
mon_mode = dest->monitor_mode;
}
IWL_INFO(drv, "Found debug destination: %s\n",
get_fw_dbg_mode_string(mon_mode));
drv->fw.dbg_dest_reg_num = (dest_v1) ?
tlv_len -
offsetof(struct iwl_fw_dbg_dest_tlv_v1,
reg_ops) :
tlv_len -
offsetof(struct iwl_fw_dbg_dest_tlv,
reg_ops);
drv->fw.dbg_dest_reg_num =
tlv_len - offsetof(struct iwl_fw_dbg_dest_tlv,
reg_ops);
drv->fw.dbg_dest_reg_num /= drv->fw.dbg_dest_reg_num /=
sizeof(drv->fw.dbg_dest_tlv->reg_ops[0]); sizeof(drv->fw.dbg_dest_tlv->reg_ops[0]);
@ -953,7 +986,7 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
case IWL_UCODE_TLV_FW_DBG_CONF: { case IWL_UCODE_TLV_FW_DBG_CONF: {
struct iwl_fw_dbg_conf_tlv *conf = (void *)tlv_data; struct iwl_fw_dbg_conf_tlv *conf = (void *)tlv_data;
if (!pieces->dbg_dest_tlv) { if (!pieces->dbg_dest_tlv_init) {
IWL_ERR(drv, IWL_ERR(drv,
"Ignore dbg config %d - no destination configured\n", "Ignore dbg config %d - no destination configured\n",
conf->id); conf->id);
@ -1340,15 +1373,51 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
if (iwl_alloc_ucode(drv, pieces, i)) if (iwl_alloc_ucode(drv, pieces, i))
goto out_free_fw; goto out_free_fw;
if (pieces->dbg_dest_tlv) { if (pieces->dbg_dest_tlv_init) {
drv->fw.dbg_dest_tlv = size_t dbg_dest_size = sizeof(*drv->fw.dbg_dest_tlv) +
kmemdup(pieces->dbg_dest_tlv, sizeof(drv->fw.dbg_dest_tlv->reg_ops[0]) *
sizeof(*pieces->dbg_dest_tlv) + drv->fw.dbg_dest_reg_num;
sizeof(pieces->dbg_dest_tlv->reg_ops[0]) *
drv->fw.dbg_dest_reg_num, GFP_KERNEL); drv->fw.dbg_dest_tlv = kmalloc(dbg_dest_size, GFP_KERNEL);
if (!drv->fw.dbg_dest_tlv) if (!drv->fw.dbg_dest_tlv)
goto out_free_fw; goto out_free_fw;
if (*pieces->dbg_dest_ver == 0) {
memcpy(drv->fw.dbg_dest_tlv, pieces->dbg_dest_tlv_v1,
dbg_dest_size);
} else {
struct iwl_fw_dbg_dest_tlv_v1 *dest_tlv =
drv->fw.dbg_dest_tlv;
dest_tlv->version = pieces->dbg_dest_tlv->version;
dest_tlv->monitor_mode =
pieces->dbg_dest_tlv->monitor_mode;
dest_tlv->size_power =
pieces->dbg_dest_tlv->size_power;
dest_tlv->wrap_count =
pieces->dbg_dest_tlv->wrap_count;
dest_tlv->write_ptr_reg =
pieces->dbg_dest_tlv->write_ptr_reg;
dest_tlv->base_shift =
pieces->dbg_dest_tlv->base_shift;
memcpy(dest_tlv->reg_ops,
pieces->dbg_dest_tlv->reg_ops,
sizeof(drv->fw.dbg_dest_tlv->reg_ops[0]) *
drv->fw.dbg_dest_reg_num);
/* In version 1 of the destination tlv, which is
* relevant for internal buffer exclusively,
* the base address is part of given with the length
* of the buffer, and the size shift is give instead of
* end shift. We now store these values in base_reg,
* and end shift, and when dumping the data we'll
* manipulate it for extracting both the length and
* base address */
dest_tlv->base_reg = pieces->dbg_dest_tlv->cfg_reg;
dest_tlv->end_shift =
pieces->dbg_dest_tlv->size_shift;
}
} }
for (i = 0; i < ARRAY_SIZE(drv->fw.dbg_conf_tlv); i++) { for (i = 0; i < ARRAY_SIZE(drv->fw.dbg_conf_tlv); i++) {

View File

@ -579,6 +579,7 @@ struct iwl_trans_ops {
void (*configure)(struct iwl_trans *trans, void (*configure)(struct iwl_trans *trans,
const struct iwl_trans_config *trans_cfg); const struct iwl_trans_config *trans_cfg);
void (*set_pmi)(struct iwl_trans *trans, bool state); void (*set_pmi)(struct iwl_trans *trans, bool state);
void (*sw_reset)(struct iwl_trans *trans);
bool (*grab_nic_access)(struct iwl_trans *trans, unsigned long *flags); bool (*grab_nic_access)(struct iwl_trans *trans, unsigned long *flags);
void (*release_nic_access)(struct iwl_trans *trans, void (*release_nic_access)(struct iwl_trans *trans,
unsigned long *flags); unsigned long *flags);
@ -744,7 +745,7 @@ struct iwl_trans {
struct lockdep_map sync_cmd_lockdep_map; struct lockdep_map sync_cmd_lockdep_map;
#endif #endif
const struct iwl_fw_dbg_dest_tlv *dbg_dest_tlv; const struct iwl_fw_dbg_dest_tlv_v1 *dbg_dest_tlv;
const struct iwl_fw_dbg_conf_tlv *dbg_conf_tlv[FW_DBG_CONF_MAX]; const struct iwl_fw_dbg_conf_tlv *dbg_conf_tlv[FW_DBG_CONF_MAX];
struct iwl_fw_dbg_trigger_tlv * const *dbg_trigger_tlv; struct iwl_fw_dbg_trigger_tlv * const *dbg_trigger_tlv;
u8 dbg_dest_reg_num; u8 dbg_dest_reg_num;
@ -1124,6 +1125,12 @@ static inline void iwl_trans_set_pmi(struct iwl_trans *trans, bool state)
trans->ops->set_pmi(trans, state); trans->ops->set_pmi(trans, state);
} }
static inline void iwl_trans_sw_reset(struct iwl_trans *trans)
{
if (trans->ops->sw_reset)
trans->ops->sw_reset(trans);
}
static inline void static inline void
iwl_trans_set_bits_mask(struct iwl_trans *trans, u32 reg, u32 mask, u32 value) iwl_trans_set_bits_mask(struct iwl_trans *trans, u32 reg, u32 mask, u32 value)
{ {

View File

@ -1221,7 +1221,7 @@ static ssize_t iwl_dbgfs_cont_recording_write(struct iwl_mvm *mvm,
loff_t *ppos) loff_t *ppos)
{ {
struct iwl_trans *trans = mvm->trans; struct iwl_trans *trans = mvm->trans;
const struct iwl_fw_dbg_dest_tlv *dest = trans->dbg_dest_tlv; const struct iwl_fw_dbg_dest_tlv_v1 *dest = trans->dbg_dest_tlv;
struct iwl_continuous_record_cmd cont_rec = {}; struct iwl_continuous_record_cmd cont_rec = {};
int ret, rec_mode; int ret, rec_mode;
@ -1914,7 +1914,7 @@ void iwl_mvm_sta_add_debugfs(struct ieee80211_hw *hw,
{ {
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_TLC_OFFLOAD)) if (iwl_mvm_has_tlc_offload(mvm))
MVM_DEBUGFS_ADD_STA_FILE(rs_data, dir, S_IRUSR); MVM_DEBUGFS_ADD_STA_FILE(rs_data, dir, S_IRUSR);
return; return;

View File

@ -421,7 +421,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
ieee80211_hw_set(hw, SUPPORTS_AMSDU_IN_AMPDU); ieee80211_hw_set(hw, SUPPORTS_AMSDU_IN_AMPDU);
ieee80211_hw_set(hw, NEEDS_UNIQUE_STA_ADDR); ieee80211_hw_set(hw, NEEDS_UNIQUE_STA_ADDR);
if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_TLC_OFFLOAD)) { if (iwl_mvm_has_tlc_offload(mvm)) {
ieee80211_hw_set(hw, TX_AMPDU_SETUP_IN_HW); ieee80211_hw_set(hw, TX_AMPDU_SETUP_IN_HW);
ieee80211_hw_set(hw, HAS_RATE_CONTROL); ieee80211_hw_set(hw, HAS_RATE_CONTROL);
} }
@ -460,7 +460,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
/* this is the case for CCK frames, it's better (only 8) for OFDM */ /* this is the case for CCK frames, it's better (only 8) for OFDM */
hw->radiotap_timestamp.accuracy = 22; hw->radiotap_timestamp.accuracy = 22;
if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_TLC_OFFLOAD)) if (!iwl_mvm_has_tlc_offload(mvm))
hw->rate_control_algorithm = RS_NAME; hw->rate_control_algorithm = RS_NAME;
hw->uapsd_queues = IWL_MVM_UAPSD_QUEUES; hw->uapsd_queues = IWL_MVM_UAPSD_QUEUES;
@ -3801,7 +3801,7 @@ static int __iwl_mvm_mac_testmode_cmd(struct iwl_mvm *mvm,
mvm->noa_duration = noa_duration; mvm->noa_duration = noa_duration;
mvm->noa_vif = vif; mvm->noa_vif = vif;
return iwl_mvm_update_quotas(mvm, false, NULL); return iwl_mvm_update_quotas(mvm, true, NULL);
case IWL_MVM_TM_CMD_SET_BEACON_FILTER: case IWL_MVM_TM_CMD_SET_BEACON_FILTER:
/* must be associated client vif - ignore authorized */ /* must be associated client vif - ignore authorized */
if (!vif || vif->type != NL80211_IFTYPE_STATION || if (!vif || vif->type != NL80211_IFTYPE_STATION ||

View File

@ -1278,6 +1278,12 @@ static inline bool iwl_mvm_has_quota_low_latency(struct iwl_mvm *mvm)
IWL_UCODE_TLV_API_QUOTA_LOW_LATENCY); IWL_UCODE_TLV_API_QUOTA_LOW_LATENCY);
} }
static inline bool iwl_mvm_has_tlc_offload(const struct iwl_mvm *mvm)
{
return fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_TLC_OFFLOAD);
}
static inline struct agg_tx_status * static inline struct agg_tx_status *
iwl_mvm_get_agg_status(struct iwl_mvm *mvm, void *tx_resp) iwl_mvm_get_agg_status(struct iwl_mvm *mvm, void *tx_resp)
{ {

View File

@ -602,7 +602,8 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
mvm->fw = fw; mvm->fw = fw;
mvm->hw = hw; mvm->hw = hw;
iwl_fw_runtime_init(&mvm->fwrt, trans, fw, &iwl_mvm_fwrt_ops, mvm); iwl_fw_runtime_init(&mvm->fwrt, trans, fw, &iwl_mvm_fwrt_ops, mvm,
dbgfs_dir);
mvm->init_status = 0; mvm->init_status = 0;
@ -801,6 +802,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
iwl_mvm_leds_exit(mvm); iwl_mvm_leds_exit(mvm);
iwl_mvm_thermal_exit(mvm); iwl_mvm_thermal_exit(mvm);
out_free: out_free:
iwl_fw_runtime_exit(&mvm->fwrt);
iwl_fw_flush_dump(&mvm->fwrt); iwl_fw_flush_dump(&mvm->fwrt);
if (iwlmvm_mod_params.init_dbg) if (iwlmvm_mod_params.init_dbg)
@ -841,7 +843,7 @@ 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);
#endif #endif
iwl_fw_runtime_exit(&mvm->fwrt);
iwl_trans_op_mode_leave(mvm->trans); iwl_trans_op_mode_leave(mvm->trans);
iwl_phy_db_free(mvm->phy_db); iwl_phy_db_free(mvm->phy_db);

View File

@ -202,6 +202,10 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm,
lockdep_assert_held(&mvm->mutex); lockdep_assert_held(&mvm->mutex);
if (fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_DYNAMIC_QUOTA))
return 0;
/* update all upon completion */ /* update all upon completion */
if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
return 0; return 0;

View File

@ -4052,7 +4052,7 @@ static const struct rate_control_ops rs_mvm_ops_drv = {
void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
enum nl80211_band band, bool init) enum nl80211_band band, bool init)
{ {
if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_TLC_OFFLOAD)) if (iwl_mvm_has_tlc_offload(mvm))
rs_fw_rate_init(mvm, sta, band); rs_fw_rate_init(mvm, sta, band);
else else
rs_drv_rate_init(mvm, sta, band, init); rs_drv_rate_init(mvm, sta, band, init);
@ -4096,7 +4096,7 @@ static int rs_drv_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
int iwl_mvm_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta, int iwl_mvm_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
bool enable) bool enable)
{ {
if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_TLC_OFFLOAD)) if (iwl_mvm_has_tlc_offload(mvm))
return rs_fw_tx_protection(mvm, mvmsta, enable); return rs_fw_tx_protection(mvm, mvmsta, enable);
else else
return rs_drv_tx_protection(mvm, mvmsta, enable); return rs_drv_tx_protection(mvm, mvmsta, enable);

View File

@ -222,7 +222,9 @@ static u32 iwl_mvm_set_mac80211_rx_flag(struct iwl_mvm *mvm,
case RX_MPDU_RES_STATUS_SEC_TKIP_ENC: case RX_MPDU_RES_STATUS_SEC_TKIP_ENC:
/* Don't drop the frame and decrypt it in SW */ /* Don't drop the frame and decrypt it in SW */
if (!(rx_pkt_status & RX_MPDU_RES_STATUS_TTAK_OK)) if (!fw_has_api(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_API_DEPRECATE_TTAK) &&
!(rx_pkt_status & RX_MPDU_RES_STATUS_TTAK_OK))
return 0; return 0;
*crypt_len = IEEE80211_TKIP_IV_LEN; *crypt_len = IEEE80211_TKIP_IV_LEN;
/* fall through if TTAK OK */ /* fall through if TTAK OK */

View File

@ -261,7 +261,9 @@ static int iwl_mvm_rx_crypto(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr,
return 0; return 0;
case IWL_RX_MPDU_STATUS_SEC_TKIP: case IWL_RX_MPDU_STATUS_SEC_TKIP:
/* Don't drop the frame and decrypt it in SW */ /* Don't drop the frame and decrypt it in SW */
if (!(status & IWL_RX_MPDU_RES_STATUS_TTAK_OK)) if (!fw_has_api(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_API_DEPRECATE_TTAK) &&
!(status & IWL_RX_MPDU_RES_STATUS_TTAK_OK))
return 0; return 0;
*crypt_len = IEEE80211_TKIP_IV_LEN; *crypt_len = IEEE80211_TKIP_IV_LEN;

View File

@ -1443,7 +1443,7 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm,
* if rs is registered with mac80211, then "add station" will be handled * if rs is registered with mac80211, then "add station" will be handled
* via the corresponding ops, otherwise need to notify rate scaling here * via the corresponding ops, otherwise need to notify rate scaling here
*/ */
if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_TLC_OFFLOAD)) if (iwl_mvm_has_tlc_offload(mvm))
iwl_mvm_rs_add_sta(mvm, mvm_sta); iwl_mvm_rs_add_sta(mvm, mvm_sta);
update_fw: update_fw:
@ -2586,8 +2586,7 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
* When FW supports TLC_OFFLOAD, it also implements Tx aggregation * When FW supports TLC_OFFLOAD, it also implements Tx aggregation
* manager, so this function should never be called in this case. * manager, so this function should never be called in this case.
*/ */
if (WARN_ON_ONCE(fw_has_capa(&mvm->fw->ucode_capa, if (WARN_ON_ONCE(iwl_mvm_has_tlc_offload(mvm)))
IWL_UCODE_TLV_CAPA_TLC_OFFLOAD)))
return -EINVAL; return -EINVAL;
BUILD_BUG_ON((sizeof(mvmsta->agg_tids) * BITS_PER_BYTE) BUILD_BUG_ON((sizeof(mvmsta->agg_tids) * BITS_PER_BYTE)

View File

@ -888,10 +888,9 @@ static void iwl_mvm_tx_add_stream(struct iwl_mvm *mvm,
/* /*
* The first deferred frame should've stopped the MAC queues, so we * The first deferred frame should've stopped the MAC queues, so we
* should never get a second deferred frame for the RA/TID. * should never get a second deferred frame for the RA/TID.
* In case of GSO the first packet may have been split, so don't warn.
*/ */
if (!WARN(skb_queue_len(deferred_tx_frames) != 1, if (skb_queue_len(deferred_tx_frames) == 1) {
"RATID %d/%d has %d deferred frames\n", mvm_sta->sta_id, tid,
skb_queue_len(deferred_tx_frames))) {
iwl_mvm_stop_mac_queues(mvm, BIT(mac_queue)); iwl_mvm_stop_mac_queues(mvm, BIT(mac_queue));
schedule_work(&mvm->add_stream_wk); schedule_work(&mvm->add_stream_wk);
} }
@ -1719,8 +1718,7 @@ static void iwl_mvm_tx_reclaim(struct iwl_mvm *mvm, int sta_id, int tid,
ba_info->band = chanctx_conf->def.chan->band; ba_info->band = chanctx_conf->def.chan->band;
iwl_mvm_hwrate_to_tx_status(rate, ba_info); iwl_mvm_hwrate_to_tx_status(rate, ba_info);
if (!fw_has_capa(&mvm->fw->ucode_capa, if (!iwl_mvm_has_tlc_offload(mvm)) {
IWL_UCODE_TLV_CAPA_TLC_OFFLOAD)) {
IWL_DEBUG_TX_REPLY(mvm, IWL_DEBUG_TX_REPLY(mvm,
"No reclaim. Update rs directly\n"); "No reclaim. Update rs directly\n");
iwl_mvm_rs_tx_status(mvm, sta, tid, ba_info, false); iwl_mvm_rs_tx_status(mvm, sta, tid, ba_info, false);

View File

@ -516,8 +516,7 @@ static void iwl_mvm_dump_lmac_error_log(struct iwl_mvm *mvm, u32 base)
IWL_ERR(trans, "HW error, resetting before reading\n"); IWL_ERR(trans, "HW error, resetting before reading\n");
/* reset the device */ /* reset the device */
iwl_set_bit(trans, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); iwl_trans_sw_reset(trans);
usleep_range(5000, 6000);
/* set INIT_DONE flag */ /* set INIT_DONE flag */
iwl_set_bit(trans, CSR_GP_CNTRL, iwl_set_bit(trans, CSR_GP_CNTRL,
@ -913,8 +912,7 @@ int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq, bool init)
}; };
if (WARN_ON(lq->sta_id == IWL_MVM_INVALID_STA || if (WARN_ON(lq->sta_id == IWL_MVM_INVALID_STA ||
fw_has_capa(&mvm->fw->ucode_capa, iwl_mvm_has_tlc_offload(mvm)))
IWL_UCODE_TLV_CAPA_TLC_OFFLOAD)))
return -EINVAL; return -EINVAL;
return iwl_mvm_send_cmd(mvm, &cmd); return iwl_mvm_send_cmd(mvm, &cmd);
@ -1033,12 +1031,34 @@ int iwl_mvm_update_low_latency(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
{ {
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
int res; int res;
bool low_latency;
lockdep_assert_held(&mvm->mutex); lockdep_assert_held(&mvm->mutex);
if (iwl_mvm_vif_low_latency(mvmvif) == prev) low_latency = iwl_mvm_vif_low_latency(mvmvif);
if (low_latency == prev)
return 0; return 0;
if (fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_DYNAMIC_QUOTA)) {
struct iwl_mac_low_latency_cmd cmd = {
.mac_id = cpu_to_le32(mvmvif->id)
};
if (low_latency) {
/* currently we don't care about the direction */
cmd.low_latency_rx = 1;
cmd.low_latency_tx = 1;
}
res = iwl_mvm_send_cmd_pdu(mvm,
iwl_cmd_id(LOW_LATENCY_CMD,
MAC_CONF_GROUP, 0),
0, sizeof(cmd), &cmd);
if (res)
IWL_ERR(mvm, "Failed to send low latency command\n");
}
res = iwl_mvm_update_quotas(mvm, false, NULL); res = iwl_mvm_update_quotas(mvm, false, NULL);
if (res) if (res)
return res; return res;

View File

@ -658,13 +658,6 @@ static inline void iwl_enable_fw_load_int(struct iwl_trans *trans)
} }
} }
static inline void iwl_pcie_sw_reset(struct iwl_trans *trans)
{
/* Reset entire device - do controller reset (results in SHRD_HW_RST) */
iwl_set_bit(trans, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
usleep_range(5000, 6000);
}
static inline u8 iwl_pcie_get_cmd_index(struct iwl_txq *q, u32 index) static inline u8 iwl_pcie_get_cmd_index(struct iwl_txq *q, u32 index)
{ {
return index & (q->n_window - 1); return index & (q->n_window - 1);

View File

@ -137,7 +137,7 @@ static void iwl_pcie_gen2_apm_stop(struct iwl_trans *trans, bool op_mode_leave)
/* Stop device's DMA activity */ /* Stop device's DMA activity */
iwl_pcie_apm_stop_master(trans); iwl_pcie_apm_stop_master(trans);
iwl_pcie_sw_reset(trans); iwl_trans_sw_reset(trans);
/* /*
* Clear "initialization complete" bit to move adapter from * Clear "initialization complete" bit to move adapter from
@ -192,7 +192,7 @@ void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans, bool low_power)
/* Stop the device, and put it in low power state */ /* Stop the device, and put it in low power state */
iwl_pcie_gen2_apm_stop(trans, false); iwl_pcie_gen2_apm_stop(trans, false);
iwl_pcie_sw_reset(trans); iwl_trans_sw_reset(trans);
/* /*
* Upon stop, the IVAR table gets erased, so msi-x won't * Upon stop, the IVAR table gets erased, so msi-x won't

View File

@ -176,6 +176,13 @@ out:
kfree(buf); kfree(buf);
} }
static void iwl_trans_pcie_sw_reset(struct iwl_trans *trans)
{
/* Reset entire device - do controller reset (results in SHRD_HW_RST) */
iwl_set_bit(trans, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
usleep_range(5000, 6000);
}
static void iwl_pcie_free_fw_monitor(struct iwl_trans *trans) static void iwl_pcie_free_fw_monitor(struct iwl_trans *trans)
{ {
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
@ -446,7 +453,7 @@ static void iwl_pcie_apm_lp_xtal_enable(struct iwl_trans *trans)
__iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL, __iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_XTAL_ON); CSR_GP_CNTRL_REG_FLAG_XTAL_ON);
iwl_pcie_sw_reset(trans); iwl_trans_pcie_sw_reset(trans);
/* /*
* Set "initialization complete" bit to move adapter from * Set "initialization complete" bit to move adapter from
@ -487,7 +494,7 @@ static void iwl_pcie_apm_lp_xtal_enable(struct iwl_trans *trans)
apmg_xtal_cfg_reg | apmg_xtal_cfg_reg |
SHR_APMG_XTAL_CFG_XTAL_ON_REQ); SHR_APMG_XTAL_CFG_XTAL_ON_REQ);
iwl_pcie_sw_reset(trans); iwl_trans_pcie_sw_reset(trans);
/* Enable LP XTAL by indirect access through CSR */ /* Enable LP XTAL by indirect access through CSR */
apmg_gp1_reg = iwl_trans_pcie_read_shr(trans, SHR_APMG_GP1_REG); apmg_gp1_reg = iwl_trans_pcie_read_shr(trans, SHR_APMG_GP1_REG);
@ -580,7 +587,7 @@ static void iwl_pcie_apm_stop(struct iwl_trans *trans, bool op_mode_leave)
return; return;
} }
iwl_pcie_sw_reset(trans); iwl_trans_pcie_sw_reset(trans);
/* /*
* Clear "initialization complete" bit to move adapter from * Clear "initialization complete" bit to move adapter from
@ -915,14 +922,9 @@ static int iwl_pcie_load_cpu_sections(struct iwl_trans *trans,
void iwl_pcie_apply_destination(struct iwl_trans *trans) void iwl_pcie_apply_destination(struct iwl_trans *trans)
{ {
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
const struct iwl_fw_dbg_dest_tlv *dest = trans->dbg_dest_tlv; const struct iwl_fw_dbg_dest_tlv_v1 *dest = trans->dbg_dest_tlv;
int i; int i;
if (dest->version)
IWL_ERR(trans,
"DBG DEST version is %d - expect issues\n",
dest->version);
IWL_INFO(trans, "Applying debug destination %s\n", IWL_INFO(trans, "Applying debug destination %s\n",
get_fw_dbg_mode_string(dest->monitor_mode)); get_fw_dbg_mode_string(dest->monitor_mode));
@ -1270,7 +1272,7 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power)
/* Stop the device, and put it in low power state */ /* Stop the device, and put it in low power state */
iwl_pcie_apm_stop(trans, false); iwl_pcie_apm_stop(trans, false);
iwl_pcie_sw_reset(trans); iwl_trans_pcie_sw_reset(trans);
/* /*
* Upon stop, the IVAR table gets erased, so msi-x won't * Upon stop, the IVAR table gets erased, so msi-x won't
@ -1744,7 +1746,7 @@ static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans, bool low_power)
return err; return err;
} }
iwl_pcie_sw_reset(trans); iwl_trans_pcie_sw_reset(trans);
err = iwl_pcie_apm_init(trans); err = iwl_pcie_apm_init(trans);
if (err) if (err)
@ -2816,8 +2818,17 @@ iwl_trans_pcie_dump_monitor(struct iwl_trans *trans,
* Update pointers to reflect actual values after * Update pointers to reflect actual values after
* shifting * shifting
*/ */
base = iwl_read_prph(trans, base) << if (trans->dbg_dest_tlv->version) {
trans->dbg_dest_tlv->base_shift; base = (iwl_read_prph(trans, base) &
IWL_LDBG_M2S_BUF_BA_MSK) <<
trans->dbg_dest_tlv->base_shift;
base *= IWL_M2S_UNIT_SIZE;
base += trans->cfg->smem_offset;
} else {
base = iwl_read_prph(trans, base) <<
trans->dbg_dest_tlv->base_shift;
}
iwl_trans_read_mem(trans, base, fw_mon_data->data, iwl_trans_read_mem(trans, base, fw_mon_data->data,
monitor_len / sizeof(u32)); monitor_len / sizeof(u32));
} else if (trans->dbg_dest_tlv->monitor_mode == MARBH_MODE) { } else if (trans->dbg_dest_tlv->monitor_mode == MARBH_MODE) {
@ -2865,21 +2876,36 @@ static struct iwl_trans_dump_data
trans_pcie->fw_mon_size; trans_pcie->fw_mon_size;
monitor_len = trans_pcie->fw_mon_size; monitor_len = trans_pcie->fw_mon_size;
} else if (trans->dbg_dest_tlv) { } else if (trans->dbg_dest_tlv) {
u32 base, end; u32 base, end, cfg_reg;
base = le32_to_cpu(trans->dbg_dest_tlv->base_reg); if (trans->dbg_dest_tlv->version == 1) {
end = le32_to_cpu(trans->dbg_dest_tlv->end_reg); cfg_reg = le32_to_cpu(trans->dbg_dest_tlv->base_reg);
cfg_reg = iwl_read_prph(trans, cfg_reg);
base = (cfg_reg & IWL_LDBG_M2S_BUF_BA_MSK) <<
trans->dbg_dest_tlv->base_shift;
base *= IWL_M2S_UNIT_SIZE;
base += trans->cfg->smem_offset;
base = iwl_read_prph(trans, base) << monitor_len =
trans->dbg_dest_tlv->base_shift; (cfg_reg & IWL_LDBG_M2S_BUF_SIZE_MSK) >>
end = iwl_read_prph(trans, end) << trans->dbg_dest_tlv->end_shift;
trans->dbg_dest_tlv->end_shift; monitor_len *= IWL_M2S_UNIT_SIZE;
} else {
base = le32_to_cpu(trans->dbg_dest_tlv->base_reg);
end = le32_to_cpu(trans->dbg_dest_tlv->end_reg);
/* Make "end" point to the actual end */ base = iwl_read_prph(trans, base) <<
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_8000 || trans->dbg_dest_tlv->base_shift;
trans->dbg_dest_tlv->monitor_mode == MARBH_MODE) end = iwl_read_prph(trans, end) <<
end += (1 << trans->dbg_dest_tlv->end_shift); trans->dbg_dest_tlv->end_shift;
monitor_len = end - base;
/* Make "end" point to the actual end */
if (trans->cfg->device_family >=
IWL_DEVICE_FAMILY_8000 ||
trans->dbg_dest_tlv->monitor_mode == MARBH_MODE)
end += (1 << trans->dbg_dest_tlv->end_shift);
monitor_len = end - base;
}
len += sizeof(*data) + sizeof(struct iwl_fw_error_dump_fw_mon) + len += sizeof(*data) + sizeof(struct iwl_fw_error_dump_fw_mon) +
monitor_len; monitor_len;
} else { } else {
@ -3025,6 +3051,7 @@ static void iwl_trans_pcie_resume(struct iwl_trans *trans)
.write_mem = iwl_trans_pcie_write_mem, \ .write_mem = iwl_trans_pcie_write_mem, \
.configure = iwl_trans_pcie_configure, \ .configure = iwl_trans_pcie_configure, \
.set_pmi = iwl_trans_pcie_set_pmi, \ .set_pmi = iwl_trans_pcie_set_pmi, \
.sw_reset = iwl_trans_pcie_sw_reset, \
.grab_nic_access = iwl_trans_pcie_grab_nic_access, \ .grab_nic_access = iwl_trans_pcie_grab_nic_access, \
.release_nic_access = iwl_trans_pcie_release_nic_access, \ .release_nic_access = iwl_trans_pcie_release_nic_access, \
.set_bits_mask = iwl_trans_pcie_set_bits_mask, \ .set_bits_mask = iwl_trans_pcie_set_bits_mask, \