Third batch of iwlwifi patches intended for v5.1
* Work on the new debugging infrastructure continues; * HE radiotap; * Support for new FW version 44; * A couple of new FW API changes; * A bunch of fixes for static analyzer reported issues; * General bugfixes; * Other cleanups and small fixes; -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEF3LNfgb2BPWm68smoUecoho8xfoFAlxYFbcACgkQoUecoho8 xfoFhg//eJLoosJx5BIX7vJ0b4uUJ7gjTj67qMja7RBVUXxMfYcn7Yrztlenm+H7 yIsZe7I0Jap88WH3HKYU/G6ASFiyXZo6TrUt4rzY3Xuy3SIgSG5gmnt4XcQRSSBd mYp+hjmz5PJPx2lzRGccQ167oOQZ/DHLn7JwuuLmgtLfz4RMHpUtitOQf9WGlKx4 nure2JLFZ4yV+lng6XBPma/lelgi9q8L8bu7izOhJkh0saSDlSWQUcn5kWoWG5av syQsrxb3FH6wfZijZXW4USolpThgCcXxTzd0IFPPXIyx/z6PEZK0yBNvGeiiPxm9 bWT1fJGrSea+82qY2vTVE1NLKd46S8jATSxSawqwGFQRv7EeLW1IdDzpFlbqU+Rn 1dUaOHzIUtK6MdCzNco4rcYZlvmFnMlqROQexnCp/sNp1J+eOfL1aqog3wRZc7sN IAtZJbwMcLC1YHunMhFOCs1+imXVrhBBN8tEJGoQHtBvIQpTumX6VFGeGBmXiyVX FLJLF0aeYg970OMcwqNuMzNIcSk13uhw3F/M/jIIN8IyK3L3bX6kiaUevUMgYK3T +3zPj41hJWGFelLa7FNryqt1S4Vbi12EubuK1gv1QcpvXro9OsUEXzeJw7PWEPj0 r3JBiIIkfpFul88F6a3163dNQoo03k4Nd69dNww/RdD7+GGuZWU= =ckmd -----END PGP SIGNATURE----- Merge tag 'iwlwifi-next-for-kalle-2019-02-04' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next Third batch of iwlwifi patches intended for v5.1 * Work on the new debugging infrastructure continues; * HE radiotap; * Support for new FW version 44; * A couple of new FW API changes; * A bunch of fixes for static analyzer reported issues; * General bugfixes; * Other cleanups and small fixes;
This commit is contained in:
commit
3479f74ee4
45 changed files with 1175 additions and 663 deletions
|
@ -56,7 +56,7 @@
|
|||
#include "iwl-config.h"
|
||||
|
||||
/* Highest firmware API version supported */
|
||||
#define IWL_22000_UCODE_API_MAX 43
|
||||
#define IWL_22000_UCODE_API_MAX 44
|
||||
|
||||
/* Lowest firmware API version supported */
|
||||
#define IWL_22000_UCODE_API_MIN 39
|
||||
|
@ -220,6 +220,7 @@ const struct iwl_cfg iwl22260_2ax_cfg = {
|
|||
* HT size; mac80211 would otherwise pick the HE max (256) by default.
|
||||
*/
|
||||
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
|
||||
.bisr_workaround = 1,
|
||||
};
|
||||
|
||||
const struct iwl_cfg killer1650x_2ax_cfg = {
|
||||
|
@ -232,6 +233,7 @@ const struct iwl_cfg killer1650x_2ax_cfg = {
|
|||
* HT size; mac80211 would otherwise pick the HE max (256) by default.
|
||||
*/
|
||||
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
|
||||
.bisr_workaround = 1,
|
||||
};
|
||||
|
||||
const struct iwl_cfg killer1650w_2ax_cfg = {
|
||||
|
@ -244,6 +246,7 @@ const struct iwl_cfg killer1650w_2ax_cfg = {
|
|||
* HT size; mac80211 would otherwise pick the HE max (256) by default.
|
||||
*/
|
||||
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
|
||||
.bisr_workaround = 1,
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -57,7 +57,7 @@
|
|||
#include "fw/file.h"
|
||||
|
||||
/* Highest firmware API version supported */
|
||||
#define IWL9000_UCODE_API_MAX 43
|
||||
#define IWL9000_UCODE_API_MAX 44
|
||||
|
||||
/* Lowest firmware API version supported */
|
||||
#define IWL9000_UCODE_API_MIN 30
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2018 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -2238,7 +2239,7 @@ static ssize_t iwl_dbgfs_log_event_write(struct file *file,
|
|||
buf_size = min(count, sizeof(buf) - 1);
|
||||
if (copy_from_user(buf, user_buf, buf_size))
|
||||
return -EFAULT;
|
||||
if (sscanf(buf, "%d", &event_log_flag) != 1)
|
||||
if (sscanf(buf, "%u", &event_log_flag) != 1)
|
||||
return -EFAULT;
|
||||
if (event_log_flag == 1)
|
||||
iwl_dump_nic_event_log(priv, true, NULL);
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
*
|
||||
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2015 Intel Deutschland GmbH
|
||||
* Copyright(c) 2018 Intel Corporation
|
||||
*
|
||||
* Portions of this file are derived from the ipw3945 project, as well
|
||||
* as portionhelp of the ieee80211 subsystem header files.
|
||||
|
@ -592,7 +593,7 @@ static int iwlagn_set_decrypted_flag(struct iwl_priv *priv,
|
|||
if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) ==
|
||||
RX_RES_STATUS_BAD_KEY_TTAK)
|
||||
break;
|
||||
|
||||
/* fall through */
|
||||
case RX_RES_STATUS_SEC_TYPE_WEP:
|
||||
if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) ==
|
||||
RX_RES_STATUS_BAD_ICV_MIC) {
|
||||
|
@ -601,6 +602,7 @@ static int iwlagn_set_decrypted_flag(struct iwl_priv *priv,
|
|||
IWL_DEBUG_RX(priv, "Packet destroyed\n");
|
||||
return -1;
|
||||
}
|
||||
/* fall through */
|
||||
case RX_RES_STATUS_SEC_TYPE_CCMP:
|
||||
if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) ==
|
||||
RX_RES_STATUS_DECRYPT_OK) {
|
||||
|
@ -729,7 +731,7 @@ static u32 iwlagn_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in)
|
|||
decrypt_out |= RX_RES_STATUS_BAD_KEY_TTAK;
|
||||
break;
|
||||
}
|
||||
/* fall through if TTAK OK */
|
||||
/* fall through */
|
||||
default:
|
||||
if (!(decrypt_in & RX_MPDU_RES_STATUS_ICV_OK))
|
||||
decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC;
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2018 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -418,7 +419,7 @@ static u16 iwl_limit_dwell(struct iwl_priv *priv, u16 dwell_time)
|
|||
limit = (limits[1] * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2;
|
||||
limit /= 2;
|
||||
dwell_time = min(limit, dwell_time);
|
||||
/* fall through to limit further */
|
||||
/* fall through */
|
||||
case 1:
|
||||
limit = (limits[0] * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2;
|
||||
limit /= n_active;
|
||||
|
|
|
@ -70,7 +70,7 @@ struct iwl_fw_ini_header {
|
|||
__le32 tlv_version;
|
||||
__le32 apply_point;
|
||||
u8 data[];
|
||||
} __packed; /* FW_INI_HEADER_TLV_S */
|
||||
} __packed; /* FW_DEBUG_TLV_HEADER_S */
|
||||
|
||||
/**
|
||||
* struct iwl_fw_ini_allocation_tlv - (IWL_FW_INI_TLV_TYPE_BUFFER_ALLOCATION)
|
||||
|
@ -92,7 +92,7 @@ struct iwl_fw_ini_allocation_tlv {
|
|||
__le32 size;
|
||||
__le32 max_fragments;
|
||||
__le32 min_frag_size;
|
||||
} __packed; /* FW_INI_BUFFER_ALLOCATION_TLV_S_VER_1 */
|
||||
} __packed; /* FW_DEBUG_TLV_BUFFER_ALLOCATION_TLV_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_fw_ini_hcmd (IWL_FW_INI_TLV_TYPE_HCMD)
|
||||
|
@ -108,7 +108,7 @@ struct iwl_fw_ini_hcmd {
|
|||
u8 group;
|
||||
__le16 padding;
|
||||
u8 data[0];
|
||||
} __packed; /* FW_INI_HCMD_S */
|
||||
} __packed; /* FW_DEBUG_TLV_HCMD_DATA_S */
|
||||
|
||||
/**
|
||||
* struct iwl_fw_ini_hcmd_tlv
|
||||
|
@ -118,7 +118,7 @@ struct iwl_fw_ini_hcmd {
|
|||
struct iwl_fw_ini_hcmd_tlv {
|
||||
struct iwl_fw_ini_header header;
|
||||
struct iwl_fw_ini_hcmd hcmd;
|
||||
} __packed; /* FW_INI_HCMD_TLV_S_VER_1 */
|
||||
} __packed; /* FW_DEBUG_TLV_HCMD_S_VER_1 */
|
||||
|
||||
/*
|
||||
* struct iwl_fw_ini_debug_flow_tlv (IWL_FW_INI_TLV_TYPE_DEBUG_FLOW)
|
||||
|
@ -129,20 +129,49 @@ struct iwl_fw_ini_hcmd_tlv {
|
|||
struct iwl_fw_ini_debug_flow_tlv {
|
||||
struct iwl_fw_ini_header header;
|
||||
__le32 debug_flow_cfg;
|
||||
} __packed; /* FW_INI_DEBUG_FLOW_TLV_S_VER_1 */
|
||||
} __packed; /* FW_DEBUG_TLV_FLOW_TLV_S_VER_1 */
|
||||
|
||||
#define IWL_FW_INI_MAX_REGION_ID 20
|
||||
#define IWL_FW_INI_MAX_REGION_ID 64
|
||||
#define IWL_FW_INI_MAX_NAME 32
|
||||
|
||||
/**
|
||||
* struct iwl_fw_ini_region_cfg_internal - meta data of internal memory region
|
||||
* @num_of_range: the amount of ranges in the region
|
||||
* @range_data_size: size of the data to read per range, in bytes.
|
||||
*/
|
||||
struct iwl_fw_ini_region_cfg_internal {
|
||||
__le32 num_of_ranges;
|
||||
__le32 range_data_size;
|
||||
} __packed; /* FW_DEBUG_TLV_REGION_NIC_INTERNAL_RANGES_S */
|
||||
|
||||
/**
|
||||
* struct iwl_fw_ini_region_cfg_fifos - meta data of fifos region
|
||||
* @lmac1_id: bit map of lmac1 fifos to include in the region.
|
||||
* @lmac2_id: bit map of lmac2 fifos to include in the region.
|
||||
* @num_of_registers: number of prph registers in the region, each register is
|
||||
* 4 bytes size.
|
||||
* @header_only: none zero value indicates that this region does not include
|
||||
* fifo data and includes only the given registers.
|
||||
*/
|
||||
struct iwl_fw_ini_region_cfg_fifos {
|
||||
__le32 lmac1_id;
|
||||
__le32 lmac2_id;
|
||||
__le32 num_of_registers;
|
||||
__le32 header_only;
|
||||
} __packed; /* FW_DEBUG_TLV_REGION_FIFOS_S */
|
||||
|
||||
/**
|
||||
* struct iwl_fw_ini_region_cfg
|
||||
* @region_id: ID of this dump configuration
|
||||
* @region_type: &enum iwl_fw_ini_region_type
|
||||
* @num_regions: amount of regions in the address array.
|
||||
* @allocation_id: For DRAM type field substitutes for allocation_id.
|
||||
* @name_len: name length
|
||||
* @name: file name to use for this region
|
||||
* @size: size of the data, in bytes.(unused for IWL_FW_INI_REGION_DRAM_BUFFER)
|
||||
* @start_addr: array of addresses. (unused for IWL_FW_INI_REGION_DRAM_BUFFER)
|
||||
* @internal: used in case the region uses internal memory.
|
||||
* @allocation_id: For DRAM type field substitutes for allocation_id
|
||||
* @fifos: used in case of fifos region.
|
||||
* @offset: offset to use for each memory base address
|
||||
* @start_addr: array of addresses.
|
||||
*/
|
||||
struct iwl_fw_ini_region_cfg {
|
||||
__le32 region_id;
|
||||
|
@ -150,31 +179,32 @@ struct iwl_fw_ini_region_cfg {
|
|||
__le32 name_len;
|
||||
u8 name[IWL_FW_INI_MAX_NAME];
|
||||
union {
|
||||
__le32 num_regions;
|
||||
struct iwl_fw_ini_region_cfg_internal internal;
|
||||
__le32 allocation_id;
|
||||
struct iwl_fw_ini_region_cfg_fifos fifos;
|
||||
};
|
||||
__le32 size;
|
||||
__le32 offset;
|
||||
__le32 start_addr[];
|
||||
} __packed; /* FW_INI_REGION_CONFIG_S */
|
||||
} __packed; /* FW_DEBUG_TLV_REGION_CONFIG_S */
|
||||
|
||||
/**
|
||||
* struct iwl_fw_ini_region_tlv - (IWL_FW_INI_TLV_TYPE_REGION_CFG)
|
||||
* DUMP sections define IDs and triggers that use those IDs TLV
|
||||
* @header: header
|
||||
* @num_regions: how many different region section and IDs are coming next
|
||||
* @iwl_fw_ini_dump dump_config: list of dump configurations
|
||||
* @region_config: list of dump configurations
|
||||
*/
|
||||
struct iwl_fw_ini_region_tlv {
|
||||
struct iwl_fw_ini_header header;
|
||||
__le32 num_regions;
|
||||
struct iwl_fw_ini_region_cfg region_config[];
|
||||
} __packed; /* FW_INI_REGION_CFG_S */
|
||||
} __packed; /* FW_DEBUG_TLV_REGIONS_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_fw_ini_trigger - (IWL_FW_INI_TLV_TYPE_DUMP_CFG)
|
||||
* Region sections define IDs and triggers that use those IDs TLV
|
||||
*
|
||||
* @trigger_id: enum &iwl_fw_ini_tigger_id
|
||||
* @trigger_id: enum &iwl_fw_ini_trigger_id
|
||||
* @ignore_default: override FW TLV with binary TLV
|
||||
* @dump_delay: delay from trigger fire to dump, in usec
|
||||
* @occurrences: max amount of times to be fired
|
||||
|
@ -196,7 +226,7 @@ struct iwl_fw_ini_trigger {
|
|||
__le32 trigger_data;
|
||||
__le32 num_regions;
|
||||
__le32 data[];
|
||||
} __packed; /* FW_INI_TRIGGER_CONFIG_S */
|
||||
} __packed; /* FW_TLV_DEBUG_TRIGGER_CONFIG_S */
|
||||
|
||||
/**
|
||||
* struct iwl_fw_ini_trigger_tlv - (IWL_FW_INI_TLV_TYPE_TRIGGERS_CFG)
|
||||
|
@ -210,20 +240,17 @@ struct iwl_fw_ini_trigger_tlv {
|
|||
struct iwl_fw_ini_header header;
|
||||
__le32 num_triggers;
|
||||
struct iwl_fw_ini_trigger trigger_config[];
|
||||
} __packed; /* FW_INI_TRIGGER_CFG_S */
|
||||
} __packed; /* FW_TLV_DEBUG_TRIGGERS_S_VER_1 */
|
||||
|
||||
/**
|
||||
* enum iwl_fw_ini_trigger_id
|
||||
* @IWL_FW_TRIGGER_ID_FW_ASSERT: FW assert
|
||||
* @IWL_FW_TRIGGER_ID_FW_TFD_Q_HANG: TFD queue hang
|
||||
* @IWL_FW_TRIGGER_ID_FW_HW_ERROR: HW assert
|
||||
* @IWL_FW_TRIGGER_ID_FW_TRIGGER_ERROR: FW error notification
|
||||
* @IWL_FW_TRIGGER_ID_FW_TRIGGER_WARNING: FW warning notification
|
||||
* @IWL_FW_TRIGGER_ID_FW_TRIGGER_INFO: FW info notification
|
||||
* @IWL_FW_TRIGGER_ID_FW_TRIGGER_DEBUG: FW debug notification
|
||||
* @IWL_FW_TRIGGER_ID_FW_TFD_Q_HANG: TFD queue hang
|
||||
* @IWL_FW_TRIGGER_ID_FW_DEBUG_HOST_TRIGGER: FW debug notification
|
||||
* @IWL_FW_TRIGGER_ID_FW_GENERIC_NOTIFOCATION: FW generic notification
|
||||
* @IWL_FW_TRIGGER_ID_USER_TRIGGER: User trigger
|
||||
* @IWL_FW_TRIGGER_ID_HOST_PEER_CLIENT_INACTIVITY: peer inactivity
|
||||
* @FW_DEBUG_TLV_TRIGGER_ID_HOST_DID_INITIATED_EVENT: undefined
|
||||
* @IWL_FW_TRIGGER_ID_HOST_TX_LATENCY_THRESHOLD_CROSSED: TX latency
|
||||
* threshold was crossed
|
||||
* @IWL_FW_TRIGGER_ID_HOST_TX_RESPONSE_STATUS_FAILED: TX failed
|
||||
|
@ -257,50 +284,53 @@ struct iwl_fw_ini_trigger_tlv {
|
|||
* @IWL_FW_TRIGGER_ID_NUM: number of trigger IDs
|
||||
*/
|
||||
enum iwl_fw_ini_trigger_id {
|
||||
IWL_FW_TRIGGER_ID_INVALID = 0,
|
||||
|
||||
/* Errors triggers */
|
||||
IWL_FW_TRIGGER_ID_FW_ASSERT = 1,
|
||||
IWL_FW_TRIGGER_ID_FW_TFD_Q_HANG = 2,
|
||||
IWL_FW_TRIGGER_ID_FW_HW_ERROR = 3,
|
||||
/* Generic triggers */
|
||||
IWL_FW_TRIGGER_ID_FW_TRIGGER_ERROR = 4,
|
||||
IWL_FW_TRIGGER_ID_FW_TRIGGER_WARNING = 5,
|
||||
IWL_FW_TRIGGER_ID_FW_TRIGGER_INFO = 6,
|
||||
IWL_FW_TRIGGER_ID_FW_TRIGGER_DEBUG = 7,
|
||||
/* User Trigger */
|
||||
IWL_FW_TRIGGER_ID_USER_TRIGGER = 8,
|
||||
IWL_FW_TRIGGER_ID_FW_HW_ERROR = 2,
|
||||
IWL_FW_TRIGGER_ID_FW_TFD_Q_HANG = 3,
|
||||
|
||||
/* FW triggers */
|
||||
IWL_FW_TRIGGER_ID_FW_DEBUG_HOST_TRIGGER = 4,
|
||||
IWL_FW_TRIGGER_ID_FW_GENERIC_NOTIFOCATION = 5,
|
||||
|
||||
/* User trigger */
|
||||
IWL_FW_TRIGGER_ID_USER_TRIGGER = 6,
|
||||
|
||||
/* Host triggers */
|
||||
IWL_FW_TRIGGER_ID_HOST_PEER_CLIENT_INACTIVITY = 9,
|
||||
IWL_FW_TRIGGER_ID_HOST_DID_INITIATED_EVENT = 10,
|
||||
IWL_FW_TRIGGER_ID_HOST_TX_LATENCY_THRESHOLD_CROSSED = 11,
|
||||
IWL_FW_TRIGGER_ID_HOST_TX_RESPONSE_STATUS_FAILED = 12,
|
||||
IWL_FW_TRIGGER_ID_HOST_OS_REQ_DEAUTH_PEER = 13,
|
||||
IWL_FW_TRIGGER_ID_HOST_STOP_GO_REQUEST = 14,
|
||||
IWL_FW_TRIGGER_ID_HOST_START_GO_REQUEST = 15,
|
||||
IWL_FW_TRIGGER_ID_HOST_JOIN_GROUP_REQUEST = 16,
|
||||
IWL_FW_TRIGGER_ID_HOST_SCAN_START = 17,
|
||||
IWL_FW_TRIGGER_ID_HOST_SCAN_SUBITTED = 18,
|
||||
IWL_FW_TRIGGER_ID_HOST_SCAN_PARAMS = 19,
|
||||
IWL_FW_TRIGGER_ID_HOST_CHECK_FOR_HANG = 20,
|
||||
IWL_FW_TRIGGER_ID_HOST_BAR_RECEIVED = 21,
|
||||
IWL_FW_TRIGGER_ID_HOST_AGG_TX_RESPONSE_STATUS_FAILED = 22,
|
||||
IWL_FW_TRIGGER_ID_HOST_EAPOL_TX_RESPONSE_FAILED = 23,
|
||||
IWL_FW_TRIGGER_ID_HOST_FAKE_TX_RESPONSE_SUSPECTED = 24,
|
||||
IWL_FW_TRIGGER_ID_HOST_AUTH_REQ_FROM_ASSOC_CLIENT = 25,
|
||||
IWL_FW_TRIGGER_ID_HOST_ROAM_COMPLETE = 26,
|
||||
IWL_FW_TRIGGER_ID_HOST_AUTH_ASSOC_FAST_FAILED = 27,
|
||||
IWL_FW_TRIGGER_ID_HOST_D3_START = 28,
|
||||
IWL_FW_TRIGGER_ID_HOST_D3_END = 29,
|
||||
IWL_FW_TRIGGER_ID_HOST_BSS_MISSED_BEACONS = 30,
|
||||
IWL_FW_TRIGGER_ID_HOST_P2P_CLIENT_MISSED_BEACONS = 31,
|
||||
IWL_FW_TRIGGER_ID_HOST_PEER_CLIENT_TX_FAILURES = 32,
|
||||
IWL_FW_TRIGGER_ID_HOST_TX_WFD_ACTION_FRAME_FAILED = 33,
|
||||
IWL_FW_TRIGGER_ID_HOST_AUTH_ASSOC_FAILED = 34,
|
||||
IWL_FW_TRIGGER_ID_HOST_SCAN_COMPLETE = 35,
|
||||
IWL_FW_TRIGGER_ID_HOST_SCAN_ABORT = 36,
|
||||
IWL_FW_TRIGGER_ID_HOST_NIC_ALIVE = 37,
|
||||
IWL_FW_TRIGGER_ID_HOST_CHANNEL_SWITCH_COMPLETE = 38,
|
||||
IWL_FW_TRIGGER_ID_HOST_PEER_CLIENT_INACTIVITY = 7,
|
||||
IWL_FW_TRIGGER_ID_HOST_TX_LATENCY_THRESHOLD_CROSSED = 8,
|
||||
IWL_FW_TRIGGER_ID_HOST_TX_RESPONSE_STATUS_FAILED = 9,
|
||||
IWL_FW_TRIGGER_ID_HOST_OS_REQ_DEAUTH_PEER = 10,
|
||||
IWL_FW_TRIGGER_ID_HOST_STOP_GO_REQUEST = 11,
|
||||
IWL_FW_TRIGGER_ID_HOST_START_GO_REQUEST = 12,
|
||||
IWL_FW_TRIGGER_ID_HOST_JOIN_GROUP_REQUEST = 13,
|
||||
IWL_FW_TRIGGER_ID_HOST_SCAN_START = 14,
|
||||
IWL_FW_TRIGGER_ID_HOST_SCAN_SUBMITTED = 15,
|
||||
IWL_FW_TRIGGER_ID_HOST_SCAN_PARAMS = 16,
|
||||
IWL_FW_TRIGGER_ID_HOST_CHECK_FOR_HANG = 17,
|
||||
IWL_FW_TRIGGER_ID_HOST_BAR_RECEIVED = 18,
|
||||
IWL_FW_TRIGGER_ID_HOST_AGG_TX_RESPONSE_STATUS_FAILED = 19,
|
||||
IWL_FW_TRIGGER_ID_HOST_EAPOL_TX_RESPONSE_FAILED = 20,
|
||||
IWL_FW_TRIGGER_ID_HOST_FAKE_TX_RESPONSE_SUSPECTED = 21,
|
||||
IWL_FW_TRIGGER_ID_HOST_AUTH_REQ_FROM_ASSOC_CLIENT = 22,
|
||||
IWL_FW_TRIGGER_ID_HOST_ROAM_COMPLETE = 23,
|
||||
IWL_FW_TRIGGER_ID_HOST_AUTH_ASSOC_FAST_FAILED = 24,
|
||||
IWL_FW_TRIGGER_ID_HOST_D3_START = 25,
|
||||
IWL_FW_TRIGGER_ID_HOST_D3_END = 26,
|
||||
IWL_FW_TRIGGER_ID_HOST_BSS_MISSED_BEACONS = 27,
|
||||
IWL_FW_TRIGGER_ID_HOST_P2P_CLIENT_MISSED_BEACONS = 28,
|
||||
IWL_FW_TRIGGER_ID_HOST_PEER_CLIENT_TX_FAILURES = 29,
|
||||
IWL_FW_TRIGGER_ID_HOST_TX_WFD_ACTION_FRAME_FAILED = 30,
|
||||
IWL_FW_TRIGGER_ID_HOST_AUTH_ASSOC_FAILED = 31,
|
||||
IWL_FW_TRIGGER_ID_HOST_SCAN_COMPLETE = 32,
|
||||
IWL_FW_TRIGGER_ID_HOST_SCAN_ABORT = 33,
|
||||
IWL_FW_TRIGGER_ID_HOST_NIC_ALIVE = 34,
|
||||
IWL_FW_TRIGGER_ID_HOST_CHANNEL_SWITCH_COMPLETE = 35,
|
||||
|
||||
IWL_FW_TRIGGER_ID_NUM,
|
||||
}; /* FW_INI_TRIGGER_ID_E_VER_1 */
|
||||
}; /* FW_DEBUG_TLV_TRIGGER_ID_E_VER_1 */
|
||||
|
||||
/**
|
||||
* enum iwl_fw_ini_apply_point
|
||||
|
@ -320,7 +350,7 @@ enum iwl_fw_ini_apply_point {
|
|||
IWL_FW_INI_APPLY_MISSED_BEACONS,
|
||||
IWL_FW_INI_APPLY_SCAN_COMPLETE,
|
||||
IWL_FW_INI_APPLY_NUM,
|
||||
}; /* FW_INI_APPLY_POINT_E_VER_1 */
|
||||
}; /* FW_DEBUG_TLV_APPLY_POINT_E_VER_1 */
|
||||
|
||||
/**
|
||||
* enum iwl_fw_ini_allocation_id
|
||||
|
@ -340,7 +370,7 @@ enum iwl_fw_ini_allocation_id {
|
|||
IWL_FW_INI_ALLOCATION_ID_SDFX,
|
||||
IWL_FW_INI_ALLOCATION_ID_FW_DUMP,
|
||||
IWL_FW_INI_ALLOCATION_ID_USER_DEFINED,
|
||||
}; /* FW_INI_ALLOCATION_ID_E_VER_1 */
|
||||
}; /* FW_DEBUG_TLV_ALLOCATION_ID_E_VER_1 */
|
||||
|
||||
/**
|
||||
* enum iwl_fw_ini_buffer_location
|
||||
|
@ -349,10 +379,10 @@ enum iwl_fw_ini_allocation_id {
|
|||
* @IWL_FW_INI_LOCATION_DRAM_PATH: DRAM location
|
||||
*/
|
||||
enum iwl_fw_ini_buffer_location {
|
||||
IWL_FW_INI_LOCATION_SRAM_INVALID,
|
||||
IWL_FW_INI_LOCATION_INVALID,
|
||||
IWL_FW_INI_LOCATION_SRAM_PATH,
|
||||
IWL_FW_INI_LOCATION_DRAM_PATH,
|
||||
}; /* FW_INI_BUFFER_LOCATION_E_VER_1 */
|
||||
}; /* FW_DEBUG_TLV_BUFFER_LOCATION_E_VER_1 */
|
||||
|
||||
/**
|
||||
* enum iwl_fw_ini_debug_flow
|
||||
|
@ -364,7 +394,7 @@ enum iwl_fw_ini_debug_flow {
|
|||
IWL_FW_INI_DEBUG_INVALID,
|
||||
IWL_FW_INI_DEBUG_DBTR_FLOW,
|
||||
IWL_FW_INI_DEBUG_TB2DTF_FLOW,
|
||||
}; /* FW_INI_DEBUG_FLOW_E_VER_1 */
|
||||
}; /* FW_DEBUG_TLV_FLOW_E_VER_1 */
|
||||
|
||||
/**
|
||||
* enum iwl_fw_ini_region_type
|
||||
|
@ -396,6 +426,6 @@ enum iwl_fw_ini_region_type {
|
|||
IWL_FW_INI_REGION_PAGING,
|
||||
IWL_FW_INI_REGION_CSR,
|
||||
IWL_FW_INI_REGION_NUM
|
||||
}; /* FW_INI_REGION_TYPE_E_VER_1*/
|
||||
}; /* FW_DEBUG_TLV_REGION_TYPE_E_VER_1 */
|
||||
|
||||
#endif
|
||||
|
|
|
@ -73,6 +73,10 @@ enum iwl_mac_conf_subcmd_ids {
|
|||
* @LOW_LATENCY_CMD: &struct iwl_mac_low_latency_cmd
|
||||
*/
|
||||
LOW_LATENCY_CMD = 0x3,
|
||||
/**
|
||||
* @CHANNEL_SWITCH_TIME_EVENT_CMD: &struct iwl_chan_switch_te_cmd
|
||||
*/
|
||||
CHANNEL_SWITCH_TIME_EVENT_CMD = 0x4,
|
||||
/**
|
||||
* @PROBE_RESPONSE_DATA_NOTIF: &struct iwl_probe_resp_data_notif
|
||||
*/
|
||||
|
@ -135,6 +139,29 @@ struct iwl_channel_switch_noa_notif {
|
|||
__le32 id_and_color;
|
||||
} __packed; /* CHANNEL_SWITCH_START_NTFY_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_chan_switch_te_cmd - Channel Switch Time Event command
|
||||
*
|
||||
* @mac_id: MAC ID for channel switch
|
||||
* @action: action to perform, one of FW_CTXT_ACTION_*
|
||||
* @tsf: beacon tsf
|
||||
* @cs_count: channel switch count from CSA/eCSA IE
|
||||
* @cs_delayed_bcn_count: if set to N (!= 0) GO/AP can delay N beacon intervals
|
||||
* at the new channel after the channel switch, otherwise (N == 0) expect
|
||||
* beacon right after the channel switch.
|
||||
* @cs_mode: 1 - quiet, 0 - otherwise
|
||||
* @reserved: reserved for alignment purposes
|
||||
*/
|
||||
struct iwl_chan_switch_te_cmd {
|
||||
__le32 mac_id;
|
||||
__le32 action;
|
||||
__le32 tsf;
|
||||
u8 cs_count;
|
||||
u8 cs_delayed_bcn_count;
|
||||
u8 cs_mode;
|
||||
u8 reserved;
|
||||
} __packed; /* MAC_CHANNEL_SWITCH_TIME_EVENT_S_VER_2 */
|
||||
|
||||
/**
|
||||
* struct iwl_mac_low_latency_cmd - set/clear mac to 'low-latency mode'
|
||||
*
|
||||
|
|
|
@ -470,6 +470,13 @@ struct iwl_geo_tx_power_profiles_resp {
|
|||
* @ba_escape_timer: Fully receive and parse beacon if no beacons were passed
|
||||
* for a longer period of time then this escape-timeout. Units: Beacons.
|
||||
* @ba_enable_beacon_abort: 1, beacon abort is enabled; 0, disabled.
|
||||
* @bf_threshold_absolute_low: See below.
|
||||
* @bf_threshold_absolute_high: Send Beacon to driver if Energy value calculated
|
||||
* for this beacon crossed this absolute threshold. For the 'Increase'
|
||||
* direction the bf_energy_absolute_low[i] is used. For the 'Decrease'
|
||||
* direction the bf_energy_absolute_high[i] is used. Zero value means
|
||||
* that this specific threshold is ignored for beacon filtering, and
|
||||
* beacon will not be forced to be sent to driver due to this setting.
|
||||
*/
|
||||
struct iwl_beacon_filter_cmd {
|
||||
__le32 bf_energy_delta;
|
||||
|
@ -483,7 +490,9 @@ struct iwl_beacon_filter_cmd {
|
|||
__le32 bf_escape_timer;
|
||||
__le32 ba_escape_timer;
|
||||
__le32 ba_enable_beacon_abort;
|
||||
} __packed;
|
||||
__le32 bf_threshold_absolute_low[2];
|
||||
__le32 bf_threshold_absolute_high[2];
|
||||
} __packed; /* BEACON_FILTER_CONFIG_API_S_VER_4 */
|
||||
|
||||
/* Beacon filtering and beacon abort */
|
||||
#define IWL_BF_ENERGY_DELTA_DEFAULT 5
|
||||
|
|
|
@ -847,19 +847,33 @@ struct iwl_beacon_notif {
|
|||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_extended_beacon_notif - notifies about beacon transmission
|
||||
* struct iwl_extended_beacon_notif_v5 - notifies about beacon transmission
|
||||
* @beacon_notify_hdr: tx response command associated with the beacon
|
||||
* @tsf: last beacon tsf
|
||||
* @ibss_mgr_status: whether IBSS is manager
|
||||
* @gp2: last beacon time in gp2
|
||||
*/
|
||||
struct iwl_extended_beacon_notif {
|
||||
struct iwl_extended_beacon_notif_v5 {
|
||||
struct iwl_mvm_tx_resp beacon_notify_hdr;
|
||||
__le64 tsf;
|
||||
__le32 ibss_mgr_status;
|
||||
__le32 gp2;
|
||||
} __packed; /* BEACON_NTFY_API_S_VER_5 */
|
||||
|
||||
/**
|
||||
* struct iwl_extended_beacon_notif - notifies about beacon transmission
|
||||
* @status: the status of the Tx response of the beacon
|
||||
* @tsf: last beacon tsf
|
||||
* @ibss_mgr_status: whether IBSS is manager
|
||||
* @gp2: last beacon time in gp2
|
||||
*/
|
||||
struct iwl_extended_beacon_notif {
|
||||
__le32 status;
|
||||
__le64 tsf;
|
||||
__le32 ibss_mgr_status;
|
||||
__le32 gp2;
|
||||
} __packed; /* BEACON_NTFY_API_S_VER_6_ */
|
||||
|
||||
/**
|
||||
* enum iwl_dump_control - dump (flush) control flags
|
||||
* @DUMP_TX_FIFO_FLUSH: Dump MSDUs until the the FIFO is empty
|
||||
|
|
|
@ -707,28 +707,6 @@ static void iwl_fw_dump_mem(struct iwl_fw_runtime *fwrt,
|
|||
IWL_DEBUG_INFO(fwrt, "WRT memory dump. Type=%u\n", dump_mem->type);
|
||||
}
|
||||
|
||||
static void iwl_fw_dump_named_mem(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_fw_error_dump_data **dump_data,
|
||||
u32 len, u32 ofs, u8 *name, u8 name_len)
|
||||
{
|
||||
struct iwl_fw_error_dump_named_mem *dump_mem;
|
||||
|
||||
if (!len)
|
||||
return;
|
||||
|
||||
(*dump_data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM);
|
||||
(*dump_data)->len = cpu_to_le32(len + sizeof(*dump_mem));
|
||||
dump_mem = (void *)(*dump_data)->data;
|
||||
dump_mem->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM_NAMED_MEM);
|
||||
dump_mem->offset = cpu_to_le32(ofs);
|
||||
dump_mem->name_len = name_len;
|
||||
memcpy(dump_mem->name, name, name_len);
|
||||
iwl_trans_read_mem_bytes(fwrt->trans, ofs, dump_mem->data, len);
|
||||
*dump_data = iwl_fw_error_next_data(*dump_data);
|
||||
|
||||
IWL_DEBUG_INFO(fwrt, "WRT memory dump. Type=%u\n", dump_mem->type);
|
||||
}
|
||||
|
||||
#define ADD_LEN(len, item_len, const_len) \
|
||||
do {size_t item = item_len; len += (!!item) * const_len + item; } \
|
||||
while (0)
|
||||
|
@ -815,6 +793,9 @@ static void iwl_dump_paging(struct iwl_fw_runtime *fwrt,
|
|||
DMA_BIDIRECTIONAL);
|
||||
memcpy(paging->data, page_address(pages),
|
||||
PAGING_BLOCK_SIZE);
|
||||
dma_sync_single_for_device(fwrt->trans->dev, addr,
|
||||
PAGING_BLOCK_SIZE,
|
||||
DMA_BIDIRECTIONAL);
|
||||
(*data) = iwl_fw_error_next_data(*data);
|
||||
}
|
||||
}
|
||||
|
@ -1059,95 +1040,254 @@ out:
|
|||
return dump_file;
|
||||
}
|
||||
|
||||
static void iwl_dump_prph_ini(struct iwl_trans *trans,
|
||||
struct iwl_fw_error_dump_data **data,
|
||||
struct iwl_fw_ini_region_cfg *reg)
|
||||
static int iwl_dump_ini_prph_iter(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_fw_ini_error_dump_range *range,
|
||||
struct iwl_fw_ini_region_cfg *reg,
|
||||
int idx)
|
||||
{
|
||||
struct iwl_fw_error_dump_prph *prph;
|
||||
unsigned long flags;
|
||||
u32 i, size = le32_to_cpu(reg->num_regions);
|
||||
__le32 *val = range->data;
|
||||
u32 addr, prph_val, offset = le32_to_cpu(reg->offset);
|
||||
int i;
|
||||
|
||||
IWL_DEBUG_INFO(trans, "WRT PRPH dump\n");
|
||||
|
||||
if (!iwl_trans_grab_nic_access(trans, &flags))
|
||||
return;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
(*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PRPH);
|
||||
(*data)->len = cpu_to_le32(le32_to_cpu(reg->size) +
|
||||
sizeof(*prph));
|
||||
prph = (void *)(*data)->data;
|
||||
prph->prph_start = reg->start_addr[i];
|
||||
prph->data[0] = cpu_to_le32(iwl_read_prph_no_grab(trans,
|
||||
le32_to_cpu(prph->prph_start)));
|
||||
*data = iwl_fw_error_next_data(*data);
|
||||
range->start_addr = reg->start_addr[idx];
|
||||
range->range_data_size = reg->internal.range_data_size;
|
||||
for (i = 0; i < le32_to_cpu(reg->internal.range_data_size); i += 4) {
|
||||
addr = le32_to_cpu(range->start_addr) + i;
|
||||
prph_val = iwl_read_prph(fwrt->trans, addr + offset);
|
||||
if (prph_val == 0x5a5a5a5a)
|
||||
return -1;
|
||||
*val++ = cpu_to_le32(prph_val);
|
||||
}
|
||||
iwl_trans_release_nic_access(trans, &flags);
|
||||
return le32_to_cpu(range->range_data_size);
|
||||
}
|
||||
|
||||
static void iwl_dump_csr_ini(struct iwl_trans *trans,
|
||||
struct iwl_fw_error_dump_data **data,
|
||||
struct iwl_fw_ini_region_cfg *reg)
|
||||
static int iwl_dump_ini_csr_iter(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_fw_ini_error_dump_range *range,
|
||||
struct iwl_fw_ini_region_cfg *reg,
|
||||
int idx)
|
||||
{
|
||||
int i, num = le32_to_cpu(reg->num_regions);
|
||||
u32 size = le32_to_cpu(reg->size);
|
||||
__le32 *val = range->data;
|
||||
u32 addr, offset = le32_to_cpu(reg->offset);
|
||||
int i;
|
||||
|
||||
IWL_DEBUG_INFO(trans, "WRT CSR dump\n");
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
u32 add = le32_to_cpu(reg->start_addr[i]);
|
||||
__le32 *val;
|
||||
int j;
|
||||
|
||||
(*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_CSR);
|
||||
(*data)->len = cpu_to_le32(size);
|
||||
val = (void *)(*data)->data;
|
||||
|
||||
for (j = 0; j < size; j += 4)
|
||||
*val++ = cpu_to_le32(iwl_trans_read32(trans, j + add));
|
||||
|
||||
*data = iwl_fw_error_next_data(*data);
|
||||
range->start_addr = reg->start_addr[idx];
|
||||
range->range_data_size = reg->internal.range_data_size;
|
||||
for (i = 0; i < le32_to_cpu(reg->internal.range_data_size); i += 4) {
|
||||
addr = le32_to_cpu(range->start_addr) + i;
|
||||
*val++ = cpu_to_le32(iwl_trans_read32(fwrt->trans,
|
||||
addr + offset));
|
||||
}
|
||||
return le32_to_cpu(range->range_data_size);
|
||||
}
|
||||
|
||||
static int iwl_dump_ini_dev_mem_iter(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_fw_ini_error_dump_range *range,
|
||||
struct iwl_fw_ini_region_cfg *reg,
|
||||
int idx)
|
||||
{
|
||||
u32 addr = le32_to_cpu(range->start_addr);
|
||||
u32 offset = le32_to_cpu(reg->offset);
|
||||
|
||||
range->start_addr = reg->start_addr[idx];
|
||||
range->range_data_size = reg->internal.range_data_size;
|
||||
iwl_trans_read_mem_bytes(fwrt->trans, addr + offset, range->data,
|
||||
le32_to_cpu(reg->internal.range_data_size));
|
||||
return le32_to_cpu(range->range_data_size);
|
||||
}
|
||||
|
||||
static int
|
||||
iwl_dump_ini_paging_gen2_iter(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_fw_ini_error_dump_range *range,
|
||||
struct iwl_fw_ini_region_cfg *reg,
|
||||
int idx)
|
||||
{
|
||||
u32 page_size = fwrt->trans->init_dram.paging[idx].size;
|
||||
|
||||
range->start_addr = cpu_to_le32(idx);
|
||||
range->range_data_size = cpu_to_le32(page_size);
|
||||
memcpy(range->data, fwrt->trans->init_dram.paging[idx].block,
|
||||
page_size);
|
||||
return le32_to_cpu(range->range_data_size);
|
||||
}
|
||||
|
||||
static int iwl_dump_ini_paging_iter(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_fw_ini_error_dump_range *range,
|
||||
struct iwl_fw_ini_region_cfg *reg,
|
||||
int idx)
|
||||
{
|
||||
/* increase idx by 1 since the pages are from 1 to
|
||||
* fwrt->num_of_paging_blk + 1
|
||||
*/
|
||||
struct page *page = fwrt->fw_paging_db[++idx].fw_paging_block;
|
||||
dma_addr_t addr = fwrt->fw_paging_db[idx].fw_paging_phys;
|
||||
u32 page_size = fwrt->fw_paging_db[idx].fw_paging_size;
|
||||
|
||||
range->start_addr = cpu_to_le32(idx);
|
||||
range->range_data_size = cpu_to_le32(page_size);
|
||||
dma_sync_single_for_cpu(fwrt->trans->dev, addr, page_size,
|
||||
DMA_BIDIRECTIONAL);
|
||||
memcpy(range->data, page_address(page), page_size);
|
||||
dma_sync_single_for_device(fwrt->trans->dev, addr, page_size,
|
||||
DMA_BIDIRECTIONAL);
|
||||
return le32_to_cpu(range->range_data_size);
|
||||
}
|
||||
|
||||
static struct iwl_fw_ini_error_dump_range
|
||||
*iwl_dump_ini_mem_fill_header(struct iwl_fw_runtime *fwrt, void *data)
|
||||
{
|
||||
struct iwl_fw_ini_error_dump *dump = data;
|
||||
|
||||
return dump->ranges;
|
||||
}
|
||||
|
||||
static u32 iwl_dump_ini_mem_get_size(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_fw_ini_region_cfg *reg)
|
||||
{
|
||||
return le32_to_cpu(reg->internal.num_of_ranges) *
|
||||
le32_to_cpu(reg->internal.range_data_size);
|
||||
}
|
||||
|
||||
static u32 iwl_dump_ini_paging_gen2_get_size(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_fw_ini_region_cfg *reg)
|
||||
{
|
||||
int i;
|
||||
u32 size = 0;
|
||||
|
||||
for (i = 0; i < fwrt->trans->init_dram.paging_cnt; i++)
|
||||
size += fwrt->trans->init_dram.paging[i].size;
|
||||
return size;
|
||||
}
|
||||
|
||||
static u32 iwl_dump_ini_paging_get_size(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_fw_ini_region_cfg *reg)
|
||||
{
|
||||
int i;
|
||||
u32 size = 0;
|
||||
|
||||
for (i = 1; i <= fwrt->num_of_paging_blk; i++)
|
||||
size += fwrt->fw_paging_db[i].fw_paging_size;
|
||||
return size;
|
||||
}
|
||||
|
||||
static u32 iwl_dump_ini_mem_ranges(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_fw_ini_region_cfg *reg)
|
||||
{
|
||||
return le32_to_cpu(reg->internal.num_of_ranges);
|
||||
}
|
||||
|
||||
static u32 iwl_dump_ini_paging_gen2_ranges(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_fw_ini_region_cfg *reg)
|
||||
{
|
||||
return fwrt->trans->init_dram.paging_cnt;
|
||||
}
|
||||
|
||||
static u32 iwl_dump_ini_paging_ranges(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_fw_ini_region_cfg *reg)
|
||||
{
|
||||
return fwrt->num_of_paging_blk;
|
||||
}
|
||||
|
||||
/**
|
||||
* struct iwl_dump_ini_mem_ops - ini memory dump operations
|
||||
* @get_num_of_ranges: returns the number of memory ranges in the region.
|
||||
* @get_size: returns the size of the region data without headers.
|
||||
* @fill_mem_hdr: fills region type specific headers and returns the first
|
||||
* range or NULL if failed to fill headers.
|
||||
* @fill_range: copies a given memory range into the dump.
|
||||
* Returns the size of the range or -1 otherwise.
|
||||
*/
|
||||
struct iwl_dump_ini_mem_ops {
|
||||
u32 (*get_num_of_ranges)(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_fw_ini_region_cfg *reg);
|
||||
u32 (*get_size)(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_fw_ini_region_cfg *reg);
|
||||
struct iwl_fw_ini_error_dump_range *
|
||||
(*fill_mem_hdr)(struct iwl_fw_runtime *fwrt, void *data);
|
||||
int (*fill_range)(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_fw_ini_error_dump_range *range,
|
||||
struct iwl_fw_ini_region_cfg *reg, int idx);
|
||||
};
|
||||
|
||||
/**
|
||||
* iwl_dump_ini_mem - copy a memory region into the dump
|
||||
* @fwrt: fw runtime struct.
|
||||
* @data: dump memory data.
|
||||
* @reg: region to copy to the dump.
|
||||
*/
|
||||
static void
|
||||
iwl_dump_ini_mem(struct iwl_fw_runtime *fwrt,
|
||||
enum iwl_fw_ini_region_type type,
|
||||
struct iwl_fw_error_dump_data **data,
|
||||
struct iwl_fw_ini_region_cfg *reg,
|
||||
struct iwl_dump_ini_mem_ops *ops)
|
||||
{
|
||||
struct iwl_fw_ini_error_dump_header *header = (void *)(*data)->data;
|
||||
struct iwl_fw_ini_error_dump_range *range;
|
||||
u32 num_of_ranges, i;
|
||||
|
||||
if (WARN_ON(!ops || !ops->get_num_of_ranges || !ops->get_size ||
|
||||
!ops->fill_mem_hdr || !ops->fill_range))
|
||||
return;
|
||||
|
||||
num_of_ranges = ops->get_num_of_ranges(fwrt, reg);
|
||||
|
||||
(*data)->type = cpu_to_le32(type | INI_DUMP_BIT);
|
||||
(*data)->len = cpu_to_le32(sizeof(*header) + num_of_ranges *
|
||||
sizeof(*range) + ops->get_size(fwrt, reg));
|
||||
|
||||
header->num_of_ranges = cpu_to_le32(num_of_ranges);
|
||||
header->name_len = cpu_to_le32(min_t(int, IWL_FW_INI_MAX_NAME,
|
||||
le32_to_cpu(reg->name_len)));
|
||||
memcpy(header->name, reg->name, le32_to_cpu(header->name_len));
|
||||
|
||||
range = ops->fill_mem_hdr(fwrt, header);
|
||||
if (!range)
|
||||
return;
|
||||
|
||||
for (i = 0; i < num_of_ranges; i++) {
|
||||
int range_data_size = ops->fill_range(fwrt, range, reg, i);
|
||||
|
||||
if (range_data_size < 0) {
|
||||
IWL_ERR(fwrt, "Failed to dump region type %d\n", type);
|
||||
return;
|
||||
}
|
||||
range = ((void *)range) + sizeof(*range) + range_data_size;
|
||||
}
|
||||
*data = iwl_fw_error_next_data(*data);
|
||||
}
|
||||
|
||||
static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_fw_ini_trigger *trigger)
|
||||
{
|
||||
int i, num, size = 0, hdr_len = sizeof(struct iwl_fw_error_dump_data);
|
||||
int i, size = 0, hdr_len = sizeof(struct iwl_fw_error_dump_data);
|
||||
u32 dump_header_len = sizeof(struct iwl_fw_ini_error_dump);
|
||||
u32 range_header_len = sizeof(struct iwl_fw_ini_error_dump_range);
|
||||
|
||||
if (!trigger || !trigger->num_regions)
|
||||
return 0;
|
||||
|
||||
num = le32_to_cpu(trigger->num_regions);
|
||||
for (i = 0; i < num; i++) {
|
||||
for (i = 0; i < le32_to_cpu(trigger->num_regions); i++) {
|
||||
u32 reg_id = le32_to_cpu(trigger->data[i]);
|
||||
struct iwl_fw_ini_region_cfg *reg;
|
||||
enum iwl_fw_ini_region_type type;
|
||||
u32 num_entries;
|
||||
|
||||
if (WARN_ON(reg_id >= ARRAY_SIZE(fwrt->dump.active_regs)))
|
||||
continue;
|
||||
|
||||
reg = fwrt->dump.active_regs[reg_id].reg;
|
||||
reg = fwrt->dump.active_regs[reg_id];
|
||||
if (WARN(!reg, "Unassigned region %d\n", reg_id))
|
||||
continue;
|
||||
|
||||
type = le32_to_cpu(reg->region_type);
|
||||
num_entries = le32_to_cpu(reg->num_regions);
|
||||
|
||||
switch (type) {
|
||||
case IWL_FW_INI_REGION_DEVICE_MEMORY:
|
||||
size += hdr_len +
|
||||
sizeof(struct iwl_fw_error_dump_named_mem) +
|
||||
le32_to_cpu(reg->size);
|
||||
break;
|
||||
case IWL_FW_INI_REGION_PERIPHERY_MAC:
|
||||
case IWL_FW_INI_REGION_PERIPHERY_PHY:
|
||||
case IWL_FW_INI_REGION_PERIPHERY_AUX:
|
||||
size += num_entries *
|
||||
(hdr_len +
|
||||
sizeof(struct iwl_fw_error_dump_prph) +
|
||||
sizeof(u32));
|
||||
case IWL_FW_INI_REGION_CSR:
|
||||
size += hdr_len + dump_header_len + range_header_len *
|
||||
iwl_dump_ini_mem_ranges(fwrt, reg) +
|
||||
iwl_dump_ini_mem_get_size(fwrt, reg);
|
||||
break;
|
||||
case IWL_FW_INI_REGION_TXF:
|
||||
size += iwl_fw_txf_len(fwrt, &fwrt->smem_cfg);
|
||||
|
@ -1155,18 +1295,21 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt,
|
|||
case IWL_FW_INI_REGION_RXF:
|
||||
size += iwl_fw_rxf_len(fwrt, &fwrt->smem_cfg);
|
||||
break;
|
||||
case IWL_FW_INI_REGION_PAGING:
|
||||
if (!iwl_fw_dbg_is_paging_enabled(fwrt))
|
||||
break;
|
||||
size += fwrt->num_of_paging_blk *
|
||||
(hdr_len +
|
||||
sizeof(struct iwl_fw_error_dump_paging) +
|
||||
PAGING_BLOCK_SIZE);
|
||||
break;
|
||||
case IWL_FW_INI_REGION_CSR:
|
||||
size += num_entries *
|
||||
(hdr_len + le32_to_cpu(reg->size));
|
||||
case IWL_FW_INI_REGION_PAGING: {
|
||||
size += hdr_len + dump_header_len;
|
||||
if (iwl_fw_dbg_is_paging_enabled(fwrt)) {
|
||||
size += range_header_len *
|
||||
iwl_dump_ini_paging_ranges(fwrt, reg) +
|
||||
iwl_dump_ini_paging_get_size(fwrt, reg);
|
||||
} else {
|
||||
size += range_header_len *
|
||||
iwl_dump_ini_paging_gen2_ranges(fwrt,
|
||||
reg) +
|
||||
iwl_dump_ini_paging_gen2_get_size(fwrt,
|
||||
reg);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IWL_FW_INI_REGION_DRAM_BUFFER:
|
||||
/* Transport takes care of DRAM dumping */
|
||||
case IWL_FW_INI_REGION_INTERNAL_BUFFER:
|
||||
|
@ -1190,11 +1333,12 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt,
|
|||
u32 reg_id = le32_to_cpu(trigger->data[i]);
|
||||
enum iwl_fw_ini_region_type type;
|
||||
struct iwl_fw_ini_region_cfg *reg;
|
||||
struct iwl_dump_ini_mem_ops ops;
|
||||
|
||||
if (reg_id >= ARRAY_SIZE(fwrt->dump.active_regs))
|
||||
continue;
|
||||
|
||||
reg = fwrt->dump.active_regs[reg_id].reg;
|
||||
reg = fwrt->dump.active_regs[reg_id];
|
||||
/* Don't warn, get_trigger_len already warned */
|
||||
if (!reg)
|
||||
continue;
|
||||
|
@ -1202,28 +1346,42 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt,
|
|||
type = le32_to_cpu(reg->region_type);
|
||||
switch (type) {
|
||||
case IWL_FW_INI_REGION_DEVICE_MEMORY:
|
||||
if (WARN_ON(le32_to_cpu(reg->num_regions) > 1))
|
||||
continue;
|
||||
iwl_fw_dump_named_mem(fwrt, data,
|
||||
le32_to_cpu(reg->size),
|
||||
le32_to_cpu(reg->start_addr[0]),
|
||||
reg->name,
|
||||
le32_to_cpu(reg->name_len));
|
||||
ops.get_num_of_ranges = iwl_dump_ini_mem_ranges;
|
||||
ops.get_size = iwl_dump_ini_mem_get_size;
|
||||
ops.fill_mem_hdr = iwl_dump_ini_mem_fill_header;
|
||||
ops.fill_range = iwl_dump_ini_dev_mem_iter;
|
||||
iwl_dump_ini_mem(fwrt, type, data, reg, &ops);
|
||||
break;
|
||||
case IWL_FW_INI_REGION_PERIPHERY_MAC:
|
||||
case IWL_FW_INI_REGION_PERIPHERY_PHY:
|
||||
case IWL_FW_INI_REGION_PERIPHERY_AUX:
|
||||
iwl_dump_prph_ini(fwrt->trans, data, reg);
|
||||
ops.get_num_of_ranges = iwl_dump_ini_mem_ranges;
|
||||
ops.get_size = iwl_dump_ini_mem_get_size;
|
||||
ops.fill_mem_hdr = iwl_dump_ini_mem_fill_header;
|
||||
ops.fill_range = iwl_dump_ini_prph_iter;
|
||||
iwl_dump_ini_mem(fwrt, type, data, reg, &ops);
|
||||
break;
|
||||
case IWL_FW_INI_REGION_DRAM_BUFFER:
|
||||
*dump_mask |= BIT(IWL_FW_ERROR_DUMP_FW_MONITOR);
|
||||
break;
|
||||
case IWL_FW_INI_REGION_PAGING:
|
||||
if (iwl_fw_dbg_is_paging_enabled(fwrt))
|
||||
iwl_dump_paging(fwrt, data);
|
||||
else
|
||||
*dump_mask |= BIT(IWL_FW_ERROR_DUMP_PAGING);
|
||||
case IWL_FW_INI_REGION_PAGING: {
|
||||
ops.fill_mem_hdr = iwl_dump_ini_mem_fill_header;
|
||||
if (iwl_fw_dbg_is_paging_enabled(fwrt)) {
|
||||
ops.get_num_of_ranges =
|
||||
iwl_dump_ini_paging_ranges;
|
||||
ops.get_size = iwl_dump_ini_paging_get_size;
|
||||
ops.fill_range = iwl_dump_ini_paging_iter;
|
||||
} else {
|
||||
ops.get_num_of_ranges =
|
||||
iwl_dump_ini_paging_gen2_ranges;
|
||||
ops.get_size =
|
||||
iwl_dump_ini_paging_gen2_get_size;
|
||||
ops.fill_range = iwl_dump_ini_paging_gen2_iter;
|
||||
}
|
||||
|
||||
iwl_dump_ini_mem(fwrt, type, data, reg, &ops);
|
||||
break;
|
||||
}
|
||||
case IWL_FW_INI_REGION_TXF:
|
||||
iwl_fw_dump_txf(fwrt, data);
|
||||
break;
|
||||
|
@ -1231,7 +1389,11 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt,
|
|||
iwl_fw_dump_rxf(fwrt, data);
|
||||
break;
|
||||
case IWL_FW_INI_REGION_CSR:
|
||||
iwl_dump_csr_ini(fwrt->trans, data, reg);
|
||||
ops.get_num_of_ranges = iwl_dump_ini_mem_ranges;
|
||||
ops.get_size = iwl_dump_ini_mem_get_size;
|
||||
ops.fill_mem_hdr = iwl_dump_ini_mem_fill_header;
|
||||
ops.fill_range = iwl_dump_ini_csr_iter;
|
||||
iwl_dump_ini_mem(fwrt, type, data, reg, &ops);
|
||||
break;
|
||||
case IWL_FW_INI_REGION_DRAM_IMR:
|
||||
case IWL_FW_INI_REGION_INTERNAL_BUFFER:
|
||||
|
@ -1362,38 +1524,6 @@ const struct iwl_fw_dump_desc iwl_dump_desc_assert = {
|
|||
};
|
||||
IWL_EXPORT_SYMBOL(iwl_dump_desc_assert);
|
||||
|
||||
void iwl_fw_assert_error_dump(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
IWL_INFO(fwrt, "error dump due to fw assert\n");
|
||||
fwrt->dump.desc = &iwl_dump_desc_assert;
|
||||
iwl_fw_error_dump(fwrt);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_fw_assert_error_dump);
|
||||
|
||||
void iwl_fw_alive_error_dump(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
struct iwl_fw_dump_desc *iwl_dump_desc_no_alive =
|
||||
kmalloc(sizeof(*iwl_dump_desc_no_alive), GFP_KERNEL);
|
||||
|
||||
if (!iwl_dump_desc_no_alive)
|
||||
return;
|
||||
|
||||
iwl_dump_desc_no_alive->trig_desc.type =
|
||||
cpu_to_le32(FW_DBG_TRIGGER_NO_ALIVE);
|
||||
iwl_dump_desc_no_alive->len = 0;
|
||||
|
||||
if (WARN_ON(fwrt->dump.desc))
|
||||
iwl_fw_free_dump_desc(fwrt);
|
||||
|
||||
IWL_WARN(fwrt, "Collecting data: trigger %d fired.\n",
|
||||
FW_DBG_TRIGGER_NO_ALIVE);
|
||||
|
||||
fwrt->dump.desc = iwl_dump_desc_no_alive;
|
||||
iwl_fw_error_dump(fwrt);
|
||||
clear_bit(IWL_FWRT_STATUS_WAIT_ALIVE, &fwrt->status);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_fw_alive_error_dump);
|
||||
|
||||
int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt,
|
||||
const struct iwl_fw_dump_desc *desc,
|
||||
bool monitor_only,
|
||||
|
@ -1415,8 +1545,7 @@ int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt,
|
|||
fwrt->smem_cfg.num_lmacs)
|
||||
return -EIO;
|
||||
|
||||
if (test_and_set_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status) ||
|
||||
test_bit(IWL_FWRT_STATUS_WAIT_ALIVE, &fwrt->status))
|
||||
if (test_and_set_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status))
|
||||
return -EBUSY;
|
||||
|
||||
if (WARN_ON(fwrt->dump.desc))
|
||||
|
@ -1434,6 +1563,33 @@ int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt,
|
|||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_fw_dbg_collect_desc);
|
||||
|
||||
int iwl_fw_dbg_error_collect(struct iwl_fw_runtime *fwrt,
|
||||
enum iwl_fw_dbg_trigger trig_type)
|
||||
{
|
||||
int ret;
|
||||
struct iwl_fw_dump_desc *iwl_dump_error_desc =
|
||||
kmalloc(sizeof(*iwl_dump_error_desc), GFP_KERNEL);
|
||||
|
||||
if (!iwl_dump_error_desc)
|
||||
return -ENOMEM;
|
||||
|
||||
iwl_dump_error_desc->trig_desc.type = cpu_to_le32(trig_type);
|
||||
iwl_dump_error_desc->len = 0;
|
||||
|
||||
ret = iwl_fw_dbg_collect_desc(fwrt, iwl_dump_error_desc, false, 0);
|
||||
if (ret) {
|
||||
kfree(iwl_dump_error_desc);
|
||||
} else {
|
||||
set_bit(STATUS_FW_WAIT_DUMP, &fwrt->trans->status);
|
||||
|
||||
/* trigger nmi to halt the fw */
|
||||
iwl_force_nmi(fwrt->trans);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_fw_dbg_error_collect);
|
||||
|
||||
int _iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt,
|
||||
enum iwl_fw_dbg_trigger trig,
|
||||
const char *str, size_t len,
|
||||
|
@ -1670,8 +1826,34 @@ void iwl_fw_dbg_read_d3_debug_data(struct iwl_fw_runtime *fwrt)
|
|||
IWL_EXPORT_SYMBOL(iwl_fw_dbg_read_d3_debug_data);
|
||||
|
||||
static void
|
||||
iwl_fw_dbg_buffer_allocation(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_fw_ini_allocation_tlv *alloc)
|
||||
iwl_fw_dbg_buffer_allocation(struct iwl_fw_runtime *fwrt, u32 size)
|
||||
{
|
||||
struct iwl_trans *trans = fwrt->trans;
|
||||
void *virtual_addr = NULL;
|
||||
dma_addr_t phys_addr;
|
||||
|
||||
if (WARN_ON_ONCE(trans->num_blocks == ARRAY_SIZE(trans->fw_mon)))
|
||||
return;
|
||||
|
||||
virtual_addr =
|
||||
dma_alloc_coherent(fwrt->trans->dev, size, &phys_addr,
|
||||
GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO |
|
||||
__GFP_COMP);
|
||||
|
||||
/* TODO: alloc fragments if needed */
|
||||
if (!virtual_addr)
|
||||
IWL_ERR(fwrt, "Failed to allocate debug memory\n");
|
||||
|
||||
trans->fw_mon[trans->num_blocks].block = virtual_addr;
|
||||
trans->fw_mon[trans->num_blocks].physical = phys_addr;
|
||||
trans->fw_mon[trans->num_blocks].size = size;
|
||||
trans->num_blocks++;
|
||||
|
||||
IWL_DEBUG_FW(trans, "Allocated debug block of size %d\n", size);
|
||||
}
|
||||
|
||||
static void iwl_fw_dbg_buffer_apply(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_fw_ini_allocation_data *alloc)
|
||||
{
|
||||
struct iwl_trans *trans = fwrt->trans;
|
||||
struct iwl_ldbg_config_cmd ldbg_cmd = {
|
||||
|
@ -1684,43 +1866,30 @@ iwl_fw_dbg_buffer_allocation(struct iwl_fw_runtime *fwrt,
|
|||
.data[0] = &ldbg_cmd,
|
||||
.len[0] = sizeof(ldbg_cmd),
|
||||
};
|
||||
void *virtual_addr = NULL;
|
||||
u32 size = le32_to_cpu(alloc->size);
|
||||
dma_addr_t phys_addr;
|
||||
int block_idx = trans->num_blocks;
|
||||
|
||||
if (!trans->num_blocks &&
|
||||
le32_to_cpu(alloc->buffer_location) !=
|
||||
if (le32_to_cpu(alloc->tlv.buffer_location) !=
|
||||
IWL_FW_INI_LOCATION_DRAM_PATH)
|
||||
return;
|
||||
|
||||
virtual_addr =
|
||||
dma_alloc_coherent(fwrt->trans->dev, size, &phys_addr,
|
||||
GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO |
|
||||
__GFP_COMP);
|
||||
|
||||
/* TODO: alloc fragments if needed */
|
||||
if (!virtual_addr)
|
||||
IWL_ERR(fwrt, "Failed to allocate debug memory\n");
|
||||
|
||||
if (WARN_ON_ONCE(trans->num_blocks == ARRAY_SIZE(trans->fw_mon)))
|
||||
return;
|
||||
|
||||
trans->fw_mon[trans->num_blocks].block = virtual_addr;
|
||||
trans->fw_mon[trans->num_blocks].physical = phys_addr;
|
||||
trans->fw_mon[trans->num_blocks].size = size;
|
||||
trans->num_blocks++;
|
||||
|
||||
IWL_DEBUG_FW(trans, "Allocated debug block of size %d\n", size);
|
||||
if (!alloc->is_alloc) {
|
||||
iwl_fw_dbg_buffer_allocation(fwrt,
|
||||
le32_to_cpu(alloc->tlv.size));
|
||||
if (block_idx == trans->num_blocks)
|
||||
return;
|
||||
alloc->is_alloc = 1;
|
||||
}
|
||||
|
||||
/* First block is assigned via registers / context info */
|
||||
if (trans->num_blocks == 1)
|
||||
return;
|
||||
|
||||
cmd->num_frags = cpu_to_le32(1);
|
||||
cmd->fragments[0].address = cpu_to_le64(phys_addr);
|
||||
cmd->fragments[0].size = alloc->size;
|
||||
cmd->allocation_id = alloc->allocation_id;
|
||||
cmd->buffer_location = alloc->buffer_location;
|
||||
cmd->fragments[0].address =
|
||||
cpu_to_le64(trans->fw_mon[block_idx].physical);
|
||||
cmd->fragments[0].size = alloc->tlv.size;
|
||||
cmd->allocation_id = alloc->tlv.allocation_id;
|
||||
cmd->buffer_location = alloc->tlv.buffer_location;
|
||||
|
||||
iwl_trans_send_cmd(trans, &hcmd);
|
||||
}
|
||||
|
@ -1749,9 +1918,9 @@ static void iwl_fw_dbg_update_regions(struct iwl_fw_runtime *fwrt,
|
|||
int i, size = le32_to_cpu(tlv->num_regions);
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
struct iwl_fw_ini_region_cfg *reg = iter;
|
||||
struct iwl_fw_ini_region_cfg *reg = iter, **active;
|
||||
int id = le32_to_cpu(reg->region_id);
|
||||
struct iwl_fw_ini_active_regs *active;
|
||||
u32 type = le32_to_cpu(reg->region_type);
|
||||
|
||||
if (WARN(id >= ARRAY_SIZE(fwrt->dump.active_regs),
|
||||
"Invalid region id %d for apply point %d\n", id, pnt))
|
||||
|
@ -1759,21 +1928,22 @@ static void iwl_fw_dbg_update_regions(struct iwl_fw_runtime *fwrt,
|
|||
|
||||
active = &fwrt->dump.active_regs[id];
|
||||
|
||||
if (ext && active->apply_point == pnt)
|
||||
IWL_WARN(fwrt->trans,
|
||||
"External region TLV overrides FW default %x\n",
|
||||
id);
|
||||
if (*active)
|
||||
IWL_WARN(fwrt->trans, "region TLV %d override\n", id);
|
||||
|
||||
IWL_DEBUG_FW(fwrt,
|
||||
"%s: apply point %d, activating region ID %d\n",
|
||||
__func__, pnt, id);
|
||||
|
||||
active->reg = reg;
|
||||
active->apply_point = pnt;
|
||||
*active = reg;
|
||||
|
||||
if (le32_to_cpu(reg->region_type) !=
|
||||
IWL_FW_INI_REGION_DRAM_BUFFER)
|
||||
iter += le32_to_cpu(reg->num_regions) * sizeof(__le32);
|
||||
if (type == IWL_FW_INI_REGION_TXF ||
|
||||
type == IWL_FW_INI_REGION_RXF)
|
||||
iter += le32_to_cpu(reg->fifos.num_of_registers) *
|
||||
sizeof(__le32);
|
||||
else if (type != IWL_FW_INI_REGION_DRAM_BUFFER)
|
||||
iter += le32_to_cpu(reg->internal.num_of_ranges) *
|
||||
sizeof(__le32);
|
||||
|
||||
iter += sizeof(*reg);
|
||||
}
|
||||
|
@ -1844,9 +2014,13 @@ static void _iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt,
|
|||
u32 type = le32_to_cpu(tlv->type);
|
||||
|
||||
switch (type) {
|
||||
case IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION:
|
||||
iwl_fw_dbg_buffer_allocation(fwrt, ini_tlv);
|
||||
case IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION: {
|
||||
struct iwl_fw_ini_allocation_data *buf_alloc = ini_tlv;
|
||||
|
||||
iwl_fw_dbg_buffer_apply(fwrt, ini_tlv);
|
||||
iter += sizeof(buf_alloc->is_alloc);
|
||||
break;
|
||||
}
|
||||
case IWL_UCODE_TLV_TYPE_HCMD:
|
||||
if (pnt < IWL_FW_INI_APPLY_AFTER_ALIVE) {
|
||||
IWL_ERR(fwrt,
|
||||
|
@ -1877,6 +2051,12 @@ void iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt,
|
|||
enum iwl_fw_ini_apply_point apply_point)
|
||||
{
|
||||
void *data = &fwrt->trans->apply_points[apply_point];
|
||||
int i;
|
||||
|
||||
if (apply_point == IWL_FW_INI_APPLY_EARLY) {
|
||||
for (i = 0; i < IWL_FW_INI_MAX_REGION_ID; i++)
|
||||
fwrt->dump.active_regs[i] = NULL;
|
||||
}
|
||||
|
||||
_iwl_fw_dbg_apply_point(fwrt, data, apply_point, false);
|
||||
|
||||
|
@ -1884,3 +2064,27 @@ void iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt,
|
|||
_iwl_fw_dbg_apply_point(fwrt, data, apply_point, true);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_fw_dbg_apply_point);
|
||||
|
||||
void iwl_fwrt_stop_device(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
/* if the wait event timeout elapses instead of wake up then
|
||||
* the driver did not receive NMI interrupt and can not assume the FW
|
||||
* is halted
|
||||
*/
|
||||
int ret = wait_event_timeout(fwrt->trans->fw_halt_waitq,
|
||||
!test_bit(STATUS_FW_WAIT_DUMP,
|
||||
&fwrt->trans->status),
|
||||
msecs_to_jiffies(2000));
|
||||
if (!ret) {
|
||||
/* failed to receive NMI interrupt, assuming the FW is stuck */
|
||||
set_bit(STATUS_FW_ERROR, &fwrt->trans->status);
|
||||
|
||||
clear_bit(STATUS_FW_WAIT_DUMP, &fwrt->trans->status);
|
||||
}
|
||||
|
||||
/* Assuming the op mode mutex is held at this point */
|
||||
iwl_fw_dbg_collect_sync(fwrt);
|
||||
|
||||
iwl_trans_stop_device(fwrt->trans);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_fwrt_stop_device);
|
||||
|
|
|
@ -112,6 +112,8 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt);
|
|||
int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt,
|
||||
const struct iwl_fw_dump_desc *desc,
|
||||
bool monitor_only, unsigned int delay);
|
||||
int iwl_fw_dbg_error_collect(struct iwl_fw_runtime *fwrt,
|
||||
enum iwl_fw_dbg_trigger trig_type);
|
||||
int _iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt,
|
||||
enum iwl_fw_dbg_trigger trig,
|
||||
const char *str, size_t len,
|
||||
|
@ -434,10 +436,13 @@ static inline void iwl_fw_resume_timestamp(struct iwl_fw_runtime *fwrt) {}
|
|||
|
||||
#endif /* CONFIG_IWLWIFI_DEBUGFS */
|
||||
|
||||
void iwl_fw_assert_error_dump(struct iwl_fw_runtime *fwrt);
|
||||
void iwl_fw_alive_error_dump(struct iwl_fw_runtime *fwrt);
|
||||
void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt);
|
||||
void iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt,
|
||||
enum iwl_fw_ini_apply_point apply_point);
|
||||
|
||||
void iwl_fwrt_stop_device(struct iwl_fw_runtime *fwrt);
|
||||
|
||||
/* This bit is used to differentiate the legacy dump from the ini dump */
|
||||
#define INI_DUMP_BIT BIT(31)
|
||||
|
||||
#endif /* __iwl_fw_dbg_h__ */
|
||||
|
|
|
@ -275,21 +275,39 @@ struct iwl_fw_error_dump_mem {
|
|||
};
|
||||
|
||||
/**
|
||||
* struct iwl_fw_error_dump_named_mem - chunk of memory
|
||||
* @type: &enum iwl_fw_error_dump_mem_type
|
||||
* @offset: the offset from which the memory was read
|
||||
* @name_len: name length
|
||||
* @name: file name
|
||||
* @data: the content of the memory
|
||||
* struct iwl_fw_ini_error_dump_range - range of memory
|
||||
* @start_addr: the start address of this range
|
||||
* @range_data_size: the size of this range, in bytes
|
||||
* @data: the actual memory
|
||||
*/
|
||||
struct iwl_fw_error_dump_named_mem {
|
||||
__le32 type;
|
||||
__le32 offset;
|
||||
u8 name_len;
|
||||
u8 name[32];
|
||||
u8 data[];
|
||||
struct iwl_fw_ini_error_dump_range {
|
||||
__le32 start_addr;
|
||||
__le32 range_data_size;
|
||||
__le32 data[];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_fw_ini_error_dump_header - ini region dump header
|
||||
* @num_of_ranges: number of ranges in this region
|
||||
* @name_len: number of bytes allocated to the name string of this region
|
||||
* @name: name of the region
|
||||
*/
|
||||
struct iwl_fw_ini_error_dump_header {
|
||||
__le32 num_of_ranges;
|
||||
__le32 name_len;
|
||||
u8 name[IWL_FW_INI_MAX_NAME];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_fw_ini_error_dump - ini region dump
|
||||
* @header: the header of this region
|
||||
* @ranges: the memory ranges of this this region
|
||||
*/
|
||||
struct iwl_fw_ini_error_dump {
|
||||
struct iwl_fw_ini_error_dump_header header;
|
||||
struct iwl_fw_ini_error_dump_range ranges[];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_fw_error_dump_rb - content of an Receive Buffer
|
||||
* @index: the index of the Receive Buffer in the Rx queue
|
||||
|
@ -355,7 +373,9 @@ iwl_fw_error_next_data(struct iwl_fw_error_dump_data *data)
|
|||
* @FW_DBG_TDLS: trigger log collection upon TDLS related events.
|
||||
* @FW_DBG_TRIGGER_TX_STATUS: trigger log collection upon tx status when
|
||||
* the firmware sends a tx reply.
|
||||
* @FW_DBG_TRIGGER_NO_ALIVE: trigger log collection if alive flow fails
|
||||
* @FW_DBG_TRIGGER_ALIVE_TIMEOUT: trigger log collection if alive flow timeouts
|
||||
* @FW_DBG_TRIGGER_DRIVER: trigger log collection upon a flow failure
|
||||
* in the driver.
|
||||
*/
|
||||
enum iwl_fw_dbg_trigger {
|
||||
FW_DBG_TRIGGER_INVALID = 0,
|
||||
|
@ -373,7 +393,8 @@ enum iwl_fw_dbg_trigger {
|
|||
FW_DBG_TRIGGER_TX_LATENCY,
|
||||
FW_DBG_TRIGGER_TDLS,
|
||||
FW_DBG_TRIGGER_TX_STATUS,
|
||||
FW_DBG_TRIGGER_NO_ALIVE,
|
||||
FW_DBG_TRIGGER_ALIVE_TIMEOUT,
|
||||
FW_DBG_TRIGGER_DRIVER,
|
||||
|
||||
/* must be last */
|
||||
FW_DBG_TRIGGER_MAX,
|
||||
|
|
|
@ -263,6 +263,10 @@ typedef unsigned int __bitwise iwl_ucode_tlv_api_t;
|
|||
* @IWL_UCODE_TLV_API_FRAG_EBS: This ucode supports fragmented EBS
|
||||
* @IWL_UCODE_TLV_API_REDUCE_TX_POWER: This ucode supports v5 of
|
||||
* the REDUCE_TX_POWER_CMD.
|
||||
* @IWL_UCODE_TLV_API_SHORT_BEACON_NOTIF: This ucode supports the short
|
||||
* version of the beacon notification.
|
||||
* @IWL_UCODE_TLV_API_BEACON_FILTER_V4: This ucode supports v4 of
|
||||
* BEACON_FILTER_CONFIG_API_S_VER_4.
|
||||
*
|
||||
* @NUM_IWL_UCODE_TLV_API: number of bits used
|
||||
*/
|
||||
|
@ -287,6 +291,8 @@ enum iwl_ucode_tlv_api {
|
|||
IWL_UCODE_TLV_API_ADAPTIVE_DWELL_V2 = (__force iwl_ucode_tlv_api_t)42,
|
||||
IWL_UCODE_TLV_API_FRAG_EBS = (__force iwl_ucode_tlv_api_t)44,
|
||||
IWL_UCODE_TLV_API_REDUCE_TX_POWER = (__force iwl_ucode_tlv_api_t)45,
|
||||
IWL_UCODE_TLV_API_SHORT_BEACON_NOTIF = (__force iwl_ucode_tlv_api_t)46,
|
||||
IWL_UCODE_TLV_API_BEACON_FILTER_V4 = (__force iwl_ucode_tlv_api_t)47,
|
||||
|
||||
NUM_IWL_UCODE_TLV_API
|
||||
#ifdef __CHECKER__
|
||||
|
@ -333,6 +339,7 @@ typedef unsigned int __bitwise iwl_ucode_tlv_capa_t;
|
|||
* @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_COEX_SCHEMA_2: firmware implements Coex Schema 2
|
||||
* IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD: firmware supports CSA command
|
||||
* @IWL_UCODE_TLV_CAPA_ULTRA_HB_CHANNELS: firmware supports ultra high band
|
||||
* (6 GHz).
|
||||
* @IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE: extended DTS measurement
|
||||
|
@ -397,6 +404,7 @@ enum iwl_ucode_tlv_capa {
|
|||
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_COEX_SCHEMA_2 = (__force iwl_ucode_tlv_capa_t)45,
|
||||
IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD = (__force iwl_ucode_tlv_capa_t)46,
|
||||
IWL_UCODE_TLV_CAPA_ULTRA_HB_CHANNELS = (__force iwl_ucode_tlv_capa_t)48,
|
||||
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,
|
||||
|
|
|
@ -222,6 +222,15 @@ struct iwl_fw_dbg {
|
|||
u32 dump_mask;
|
||||
};
|
||||
|
||||
/**
|
||||
* @tlv: the buffer allocation tlv
|
||||
* @is_alloc: indicates if the buffer was already allocated
|
||||
*/
|
||||
struct iwl_fw_ini_allocation_data {
|
||||
struct iwl_fw_ini_allocation_tlv tlv;
|
||||
u32 is_alloc;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_fw_ini_active_triggers
|
||||
* @active: is this trigger active
|
||||
|
@ -236,16 +245,6 @@ struct iwl_fw_ini_active_triggers {
|
|||
struct iwl_fw_ini_trigger *conf_ext;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_fw_ini_active_regs
|
||||
* @reg: active region from TLV
|
||||
* @apply_point: apply point where it became active
|
||||
*/
|
||||
struct iwl_fw_ini_active_regs {
|
||||
struct iwl_fw_ini_region_cfg *reg;
|
||||
enum iwl_fw_ini_apply_point apply_point;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_fw - variables associated with the firmware
|
||||
*
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2017 Intel Deutschland GmbH
|
||||
* Copyright(c) 2019 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -26,6 +27,7 @@
|
|||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2017 Intel Deutschland GmbH
|
||||
* Copyright(c) 2019 Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -74,6 +76,7 @@ void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans,
|
|||
fwrt->ops_ctx = ops_ctx;
|
||||
INIT_DELAYED_WORK(&fwrt->dump.wk, iwl_fw_error_dump_wk);
|
||||
iwl_fwrt_dbgfs_register(fwrt, dbgfs_dir);
|
||||
init_waitqueue_head(&fwrt->trans->fw_halt_waitq);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_fw_runtime_init);
|
||||
|
||||
|
|
|
@ -90,7 +90,6 @@ struct iwl_fwrt_shared_mem_cfg {
|
|||
|
||||
enum iwl_fw_runtime_status {
|
||||
IWL_FWRT_STATUS_DUMPING = 0,
|
||||
IWL_FWRT_STATUS_WAIT_ALIVE,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -140,7 +139,7 @@ struct iwl_fw_runtime {
|
|||
/* ts of the beginning of a non-collect fw dbg data period */
|
||||
unsigned long non_collect_ts_start[IWL_FW_TRIGGER_ID_NUM - 1];
|
||||
u32 *d3_debug_data;
|
||||
struct iwl_fw_ini_active_regs active_regs[IWL_FW_INI_MAX_REGION_ID];
|
||||
struct iwl_fw_ini_region_cfg *active_regs[IWL_FW_INI_MAX_REGION_ID];
|
||||
struct iwl_fw_ini_active_triggers active_trigs[IWL_FW_TRIGGER_ID_NUM];
|
||||
u32 lmac_err_id[MAX_NUM_LMAC];
|
||||
u32 umac_err_id;
|
||||
|
|
|
@ -379,6 +379,7 @@ struct iwl_csr_params {
|
|||
* @nvm_type: see &enum iwl_nvm_type
|
||||
* @d3_debug_data_base_addr: base address where D3 debug data is stored
|
||||
* @d3_debug_data_length: length of the D3 debug data
|
||||
* @bisr_workaround: BISR hardware workaround (for 22260 series devices)
|
||||
*
|
||||
* We enable the driver to be backward compatible wrt. hardware features.
|
||||
* API differences in uCode shouldn't be handled here but through TLVs
|
||||
|
@ -428,7 +429,8 @@ struct iwl_cfg {
|
|||
use_tfh:1,
|
||||
gen2:1,
|
||||
cdb:1,
|
||||
dbgc_supported:1;
|
||||
dbgc_supported:1,
|
||||
bisr_workaround:1;
|
||||
u8 valid_tx_ant;
|
||||
u8 valid_rx_ant;
|
||||
u8 non_shared_ant;
|
||||
|
@ -445,35 +447,8 @@ struct iwl_cfg {
|
|||
u32 d3_debug_data_length;
|
||||
};
|
||||
|
||||
static const struct iwl_csr_params iwl_csr_v1 = {
|
||||
.flag_mac_clock_ready = 0,
|
||||
.flag_val_mac_access_en = 0,
|
||||
.flag_init_done = 2,
|
||||
.flag_mac_access_req = 3,
|
||||
.flag_sw_reset = 7,
|
||||
.flag_master_dis = 8,
|
||||
.flag_stop_master = 9,
|
||||
.addr_sw_reset = (CSR_BASE + 0x020),
|
||||
.mac_addr0_otp = 0x380,
|
||||
.mac_addr1_otp = 0x384,
|
||||
.mac_addr0_strap = 0x388,
|
||||
.mac_addr1_strap = 0x38C
|
||||
};
|
||||
|
||||
static const struct iwl_csr_params iwl_csr_v2 = {
|
||||
.flag_init_done = 6,
|
||||
.flag_mac_clock_ready = 20,
|
||||
.flag_val_mac_access_en = 20,
|
||||
.flag_mac_access_req = 21,
|
||||
.flag_master_dis = 28,
|
||||
.flag_stop_master = 29,
|
||||
.flag_sw_reset = 31,
|
||||
.addr_sw_reset = (CSR_BASE + 0x024),
|
||||
.mac_addr0_otp = 0x30,
|
||||
.mac_addr1_otp = 0x34,
|
||||
.mac_addr0_strap = 0x38,
|
||||
.mac_addr1_strap = 0x3C
|
||||
};
|
||||
extern const struct iwl_csr_params iwl_csr_v1;
|
||||
extern const struct iwl_csr_params iwl_csr_v2;
|
||||
|
||||
/*
|
||||
* This list declares the config structures for all devices.
|
||||
|
|
|
@ -71,6 +71,7 @@ void iwl_fw_dbg_copy_tlv(struct iwl_trans *trans, struct iwl_ucode_tlv *tlv,
|
|||
u32 apply_point = le32_to_cpu(header->apply_point);
|
||||
|
||||
int copy_size = le32_to_cpu(tlv->length) + sizeof(*tlv);
|
||||
int offset_size = copy_size;
|
||||
|
||||
if (WARN_ONCE(apply_point >= IWL_FW_INI_APPLY_NUM,
|
||||
"Invalid apply point id %d\n", apply_point))
|
||||
|
@ -81,17 +82,25 @@ void iwl_fw_dbg_copy_tlv(struct iwl_trans *trans, struct iwl_ucode_tlv *tlv,
|
|||
else
|
||||
data = &trans->apply_points[apply_point];
|
||||
|
||||
/* add room for is_alloc field in &iwl_fw_ini_allocation_data struct */
|
||||
if (le32_to_cpu(tlv->type) == IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION) {
|
||||
struct iwl_fw_ini_allocation_data *buf_alloc =
|
||||
(void *)tlv->data;
|
||||
|
||||
offset_size += sizeof(buf_alloc->is_alloc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure we still have room to copy this TLV. Offset points to the
|
||||
* location the last copy ended.
|
||||
*/
|
||||
if (WARN_ONCE(data->offset + copy_size > data->size,
|
||||
if (WARN_ONCE(data->offset + offset_size > data->size,
|
||||
"Not enough memory for apply point %d\n",
|
||||
apply_point))
|
||||
return;
|
||||
|
||||
memcpy(data->data + data->offset, (void *)tlv, copy_size);
|
||||
data->offset += copy_size;
|
||||
data->offset += offset_size;
|
||||
}
|
||||
|
||||
void iwl_alloc_dbg_tlv(struct iwl_trans *trans, size_t len, const u8 *data,
|
||||
|
@ -129,6 +138,16 @@ void iwl_alloc_dbg_tlv(struct iwl_trans *trans, size_t len, const u8 *data,
|
|||
if (WARN_ON(apply >= IWL_FW_INI_APPLY_NUM))
|
||||
continue;
|
||||
|
||||
/* add room for is_alloc field in &iwl_fw_ini_allocation_data
|
||||
* struct
|
||||
*/
|
||||
if (tlv_type == IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION) {
|
||||
struct iwl_fw_ini_allocation_data *buf_alloc =
|
||||
(void *)tlv->data;
|
||||
|
||||
size[apply] += sizeof(buf_alloc->is_alloc);
|
||||
}
|
||||
|
||||
size[apply] += sizeof(*tlv) + tlv_len;
|
||||
}
|
||||
|
||||
|
|
|
@ -193,34 +193,25 @@ static int iwl_init_otp_access(struct iwl_trans *trans)
|
|||
{
|
||||
int ret;
|
||||
|
||||
/* Enable 40MHz radio clock */
|
||||
iwl_write32(trans, CSR_GP_CNTRL,
|
||||
iwl_read32(trans, CSR_GP_CNTRL) |
|
||||
BIT(trans->cfg->csr->flag_init_done));
|
||||
ret = iwl_finish_nic_init(trans);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* wait for clock to be ready */
|
||||
ret = iwl_poll_bit(trans, CSR_GP_CNTRL,
|
||||
BIT(trans->cfg->csr->flag_mac_clock_ready),
|
||||
BIT(trans->cfg->csr->flag_mac_clock_ready),
|
||||
25000);
|
||||
if (ret < 0) {
|
||||
IWL_ERR(trans, "Time out access OTP\n");
|
||||
} else {
|
||||
iwl_set_bits_prph(trans, APMG_PS_CTRL_REG,
|
||||
APMG_PS_CTRL_VAL_RESET_REQ);
|
||||
udelay(5);
|
||||
iwl_clear_bits_prph(trans, APMG_PS_CTRL_REG,
|
||||
APMG_PS_CTRL_VAL_RESET_REQ);
|
||||
iwl_set_bits_prph(trans, APMG_PS_CTRL_REG,
|
||||
APMG_PS_CTRL_VAL_RESET_REQ);
|
||||
udelay(5);
|
||||
iwl_clear_bits_prph(trans, APMG_PS_CTRL_REG,
|
||||
APMG_PS_CTRL_VAL_RESET_REQ);
|
||||
|
||||
/*
|
||||
* CSR auto clock gate disable bit -
|
||||
* this is only applicable for HW with OTP shadow RAM
|
||||
*/
|
||||
if (trans->cfg->base_params->shadow_ram_support)
|
||||
iwl_set_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG,
|
||||
CSR_RESET_LINK_PWR_MGMT_DISABLED);
|
||||
}
|
||||
return ret;
|
||||
/*
|
||||
* CSR auto clock gate disable bit -
|
||||
* this is only applicable for HW with OTP shadow RAM
|
||||
*/
|
||||
if (trans->cfg->base_params->shadow_ram_support)
|
||||
iwl_set_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG,
|
||||
CSR_RESET_LINK_PWR_MGMT_DISABLED);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwl_read_otp_word(struct iwl_trans *trans, u16 addr,
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
*
|
||||
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2015 - 2016 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -28,6 +29,7 @@
|
|||
*
|
||||
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2015 - 2016 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018 Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -68,6 +70,36 @@
|
|||
#include "iwl-prph.h"
|
||||
#include "iwl-fh.h"
|
||||
|
||||
const struct iwl_csr_params iwl_csr_v1 = {
|
||||
.flag_mac_clock_ready = 0,
|
||||
.flag_val_mac_access_en = 0,
|
||||
.flag_init_done = 2,
|
||||
.flag_mac_access_req = 3,
|
||||
.flag_sw_reset = 7,
|
||||
.flag_master_dis = 8,
|
||||
.flag_stop_master = 9,
|
||||
.addr_sw_reset = CSR_BASE + 0x020,
|
||||
.mac_addr0_otp = 0x380,
|
||||
.mac_addr1_otp = 0x384,
|
||||
.mac_addr0_strap = 0x388,
|
||||
.mac_addr1_strap = 0x38C
|
||||
};
|
||||
|
||||
const struct iwl_csr_params iwl_csr_v2 = {
|
||||
.flag_init_done = 6,
|
||||
.flag_mac_clock_ready = 20,
|
||||
.flag_val_mac_access_en = 20,
|
||||
.flag_mac_access_req = 21,
|
||||
.flag_master_dis = 28,
|
||||
.flag_stop_master = 29,
|
||||
.flag_sw_reset = 31,
|
||||
.addr_sw_reset = CSR_BASE + 0x024,
|
||||
.mac_addr0_otp = 0x30,
|
||||
.mac_addr1_otp = 0x34,
|
||||
.mac_addr0_strap = 0x38,
|
||||
.mac_addr1_strap = 0x3C
|
||||
};
|
||||
|
||||
void iwl_write8(struct iwl_trans *trans, u32 ofs, u8 val)
|
||||
{
|
||||
trace_iwlwifi_dev_iowrite8(trans->dev, ofs, val);
|
||||
|
@ -456,3 +488,43 @@ int iwl_dump_fh(struct iwl_trans *trans, char **buf)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iwl_finish_nic_init(struct iwl_trans *trans)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (trans->cfg->bisr_workaround) {
|
||||
/* ensure the TOP FSM isn't still in previous reset */
|
||||
mdelay(2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set "initialization complete" bit to move adapter from
|
||||
* D0U* --> D0A* (powered-up active) state.
|
||||
*/
|
||||
iwl_set_bit(trans, CSR_GP_CNTRL,
|
||||
BIT(trans->cfg->csr->flag_init_done));
|
||||
|
||||
if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
|
||||
udelay(2);
|
||||
|
||||
/*
|
||||
* Wait for clock stabilization; once stabilized, access to
|
||||
* device-internal resources is supported, e.g. iwl_write_prph()
|
||||
* and accesses to uCode SRAM.
|
||||
*/
|
||||
err = iwl_poll_bit(trans, CSR_GP_CNTRL,
|
||||
BIT(trans->cfg->csr->flag_mac_clock_ready),
|
||||
BIT(trans->cfg->csr->flag_mac_clock_ready),
|
||||
25000);
|
||||
if (err < 0)
|
||||
IWL_DEBUG_INFO(trans, "Failed to wake NIC\n");
|
||||
|
||||
if (trans->cfg->bisr_workaround) {
|
||||
/* ensure BISR shift has finished */
|
||||
udelay(200);
|
||||
}
|
||||
|
||||
return err < 0 ? err : 0;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_finish_nic_init);
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright (C) 2018 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
|
@ -23,6 +25,7 @@
|
|||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright (C) 2018 Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -96,6 +99,8 @@ void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs,
|
|||
void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask);
|
||||
void iwl_force_nmi(struct iwl_trans *trans);
|
||||
|
||||
int iwl_finish_nic_init(struct iwl_trans *trans);
|
||||
|
||||
/* Error handling */
|
||||
int iwl_dump_fh(struct iwl_trans *trans, char **buf);
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
* Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||
* Copyright(c) 2018 - 2019 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -30,6 +31,7 @@
|
|||
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||
* Copyright(c) 2018 - 2019 Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -330,6 +332,7 @@ enum iwl_d3_status {
|
|||
* are sent
|
||||
* @STATUS_TRANS_IDLE: the trans is idle - general commands are not to be sent
|
||||
* @STATUS_TRANS_DEAD: trans is dead - avoid any read/write operation
|
||||
* @STATUS_FW_WAIT_DUMP: if set, wait until cleared before collecting dump
|
||||
*/
|
||||
enum iwl_trans_status {
|
||||
STATUS_SYNC_HCMD_ACTIVE,
|
||||
|
@ -342,6 +345,7 @@ enum iwl_trans_status {
|
|||
STATUS_TRANS_GOING_IDLE,
|
||||
STATUS_TRANS_IDLE,
|
||||
STATUS_TRANS_DEAD,
|
||||
STATUS_FW_WAIT_DUMP,
|
||||
};
|
||||
|
||||
static inline int
|
||||
|
@ -684,6 +688,9 @@ enum iwl_plat_pm_mode {
|
|||
*/
|
||||
#define IWL_TRANS_IDLE_TIMEOUT 2000
|
||||
|
||||
/* Max time to wait for nmi interrupt */
|
||||
#define IWL_TRANS_NMI_TIMEOUT (HZ / 4)
|
||||
|
||||
/**
|
||||
* struct iwl_dram_data
|
||||
* @physical: page phy pointer
|
||||
|
@ -696,6 +703,20 @@ struct iwl_dram_data {
|
|||
int size;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_self_init_dram - dram data used by self init process
|
||||
* @fw: lmac and umac dram data
|
||||
* @fw_cnt: total number of items in array
|
||||
* @paging: paging dram data
|
||||
* @paging_cnt: total number of items in array
|
||||
*/
|
||||
struct iwl_self_init_dram {
|
||||
struct iwl_dram_data *fw;
|
||||
int fw_cnt;
|
||||
struct iwl_dram_data *paging;
|
||||
int paging_cnt;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_trans - transport common data
|
||||
*
|
||||
|
@ -790,12 +811,18 @@ struct iwl_trans {
|
|||
u8 dbg_n_dest_reg;
|
||||
int num_blocks;
|
||||
struct iwl_dram_data fw_mon[IWL_FW_INI_APPLY_NUM];
|
||||
struct iwl_self_init_dram init_dram;
|
||||
|
||||
enum iwl_plat_pm_mode system_pm_mode;
|
||||
enum iwl_plat_pm_mode runtime_pm_mode;
|
||||
bool suspending;
|
||||
bool dbg_rec_on;
|
||||
|
||||
u32 lmac_error_event_table[2];
|
||||
u32 umac_error_event_table;
|
||||
unsigned int error_event_table_tlv_status;
|
||||
wait_queue_head_t fw_halt_waitq;
|
||||
|
||||
/* pointer to trans specific struct */
|
||||
/*Ensure that this pointer will always be aligned to sizeof pointer */
|
||||
char trans_specific[0] __aligned(sizeof(void *));
|
||||
|
@ -1202,6 +1229,10 @@ static inline void iwl_trans_fw_error(struct iwl_trans *trans)
|
|||
/* prevent double restarts due to the same erroneous FW */
|
||||
if (!test_and_set_bit(STATUS_FW_ERROR, &trans->status))
|
||||
iwl_op_mode_nic_error(trans->op_mode);
|
||||
|
||||
if (test_and_clear_bit(STATUS_FW_WAIT_DUMP, &trans->status))
|
||||
wake_up(&trans->fw_halt_waitq);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************
|
||||
|
|
|
@ -241,7 +241,6 @@ static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id,
|
|||
struct iwl_bt_coex_reduced_txp_update_cmd cmd = {};
|
||||
struct iwl_mvm_sta *mvmsta;
|
||||
u32 value;
|
||||
int ret;
|
||||
|
||||
mvmsta = iwl_mvm_sta_from_staid_protected(mvm, sta_id);
|
||||
if (!mvmsta)
|
||||
|
@ -262,10 +261,8 @@ static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id,
|
|||
cmd.reduced_txp = cpu_to_le32(value);
|
||||
mvmsta->bt_reduced_txpower = enable;
|
||||
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, BT_COEX_UPDATE_REDUCED_TXP, CMD_ASYNC,
|
||||
sizeof(cmd), &cmd);
|
||||
|
||||
return ret;
|
||||
return iwl_mvm_send_cmd_pdu(mvm, BT_COEX_UPDATE_REDUCED_TXP,
|
||||
CMD_ASYNC, sizeof(cmd), &cmd);
|
||||
}
|
||||
|
||||
struct iwl_bt_iterator_data {
|
||||
|
|
|
@ -105,12 +105,12 @@ static int iwl_send_rss_cfg_cmd(struct iwl_mvm *mvm)
|
|||
int i;
|
||||
struct iwl_rss_config_cmd cmd = {
|
||||
.flags = cpu_to_le32(IWL_RSS_ENABLE),
|
||||
.hash_mask = IWL_RSS_HASH_TYPE_IPV4_TCP |
|
||||
IWL_RSS_HASH_TYPE_IPV4_UDP |
|
||||
IWL_RSS_HASH_TYPE_IPV4_PAYLOAD |
|
||||
IWL_RSS_HASH_TYPE_IPV6_TCP |
|
||||
IWL_RSS_HASH_TYPE_IPV6_UDP |
|
||||
IWL_RSS_HASH_TYPE_IPV6_PAYLOAD,
|
||||
.hash_mask = BIT(IWL_RSS_HASH_TYPE_IPV4_TCP) |
|
||||
BIT(IWL_RSS_HASH_TYPE_IPV4_UDP) |
|
||||
BIT(IWL_RSS_HASH_TYPE_IPV4_PAYLOAD) |
|
||||
BIT(IWL_RSS_HASH_TYPE_IPV6_TCP) |
|
||||
BIT(IWL_RSS_HASH_TYPE_IPV6_UDP) |
|
||||
BIT(IWL_RSS_HASH_TYPE_IPV6_PAYLOAD),
|
||||
};
|
||||
|
||||
if (mvm->trans->num_rx_queues == 1)
|
||||
|
@ -127,13 +127,17 @@ static int iwl_send_rss_cfg_cmd(struct iwl_mvm *mvm)
|
|||
|
||||
static int iwl_configure_rxq(struct iwl_mvm *mvm)
|
||||
{
|
||||
int i, num_queues, size;
|
||||
int i, num_queues, size, ret;
|
||||
struct iwl_rfh_queue_config *cmd;
|
||||
struct iwl_host_cmd hcmd = {
|
||||
.id = WIDE_ID(DATA_PATH_GROUP, RFH_QUEUE_CONFIG_CMD),
|
||||
.dataflags[0] = IWL_HCMD_DFL_NOCOPY,
|
||||
};
|
||||
|
||||
/* Do not configure default queue, it is configured via context info */
|
||||
num_queues = mvm->trans->num_rx_queues - 1;
|
||||
|
||||
size = sizeof(*cmd) + num_queues * sizeof(struct iwl_rfh_queue_data);
|
||||
size = struct_size(cmd, data, num_queues);
|
||||
|
||||
cmd = kzalloc(size, GFP_KERNEL);
|
||||
if (!cmd)
|
||||
|
@ -154,10 +158,14 @@ static int iwl_configure_rxq(struct iwl_mvm *mvm)
|
|||
cmd->data[i].fr_bd_wid = cpu_to_le32(data.fr_bd_wid);
|
||||
}
|
||||
|
||||
return iwl_mvm_send_cmd_pdu(mvm,
|
||||
WIDE_ID(DATA_PATH_GROUP,
|
||||
RFH_QUEUE_CONFIG_CMD),
|
||||
0, size, cmd);
|
||||
hcmd.data[0] = cmd;
|
||||
hcmd.len[0] = size;
|
||||
|
||||
ret = iwl_mvm_send_cmd(mvm, &hcmd);
|
||||
|
||||
kfree(cmd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int iwl_mvm_send_dqa_cmd(struct iwl_mvm *mvm)
|
||||
|
@ -299,7 +307,6 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
|
|||
enum iwl_ucode_type old_type = mvm->fwrt.cur_fw_img;
|
||||
static const u16 alive_cmd[] = { MVM_ALIVE };
|
||||
|
||||
set_bit(IWL_FWRT_STATUS_WAIT_ALIVE, &mvm->fwrt.status);
|
||||
if (ucode_type == IWL_UCODE_REGULAR &&
|
||||
iwl_fw_dbg_conf_usniffer(mvm->fw, FW_DBG_START_FROM_ALIVE) &&
|
||||
!(fw_has_capa(&mvm->fw->ucode_capa,
|
||||
|
@ -332,6 +339,10 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
|
|||
if (ret) {
|
||||
struct iwl_trans *trans = mvm->trans;
|
||||
|
||||
if (ret == -ETIMEDOUT)
|
||||
iwl_fw_dbg_error_collect(&mvm->fwrt,
|
||||
FW_DBG_TRIGGER_ALIVE_TIMEOUT);
|
||||
|
||||
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22000)
|
||||
IWL_ERR(mvm,
|
||||
"SecBoot CPU1 Status: 0x%x, CPU2 Status: 0x%x\n",
|
||||
|
@ -377,7 +388,6 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
|
|||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
iwl_fw_set_dbg_rec_on(&mvm->fwrt);
|
||||
#endif
|
||||
clear_bit(IWL_FWRT_STATUS_WAIT_ALIVE, &mvm->fwrt.status);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -407,7 +417,6 @@ static int iwl_run_unified_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
|
|||
ret = iwl_mvm_load_ucode_wait_alive(mvm, IWL_UCODE_REGULAR);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "Failed to start RT ucode: %d\n", ret);
|
||||
iwl_fw_assert_error_dump(&mvm->fwrt);
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
@ -1052,7 +1061,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
|
|||
ret = iwl_mvm_load_rt_fw(mvm);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "Failed to start RT ucode: %d\n", ret);
|
||||
iwl_fw_assert_error_dump(&mvm->fwrt);
|
||||
iwl_fw_dbg_error_collect(&mvm->fwrt, FW_DBG_TRIGGER_DRIVER);
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
*
|
||||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2017 Intel Deutschland GmbH
|
||||
* Copyright(c) 2018 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -28,6 +29,7 @@
|
|||
*
|
||||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2017 Intel Deutschland GmbH
|
||||
* Copyright(c) 2018 Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -113,6 +115,7 @@ int iwl_mvm_leds_init(struct iwl_mvm *mvm)
|
|||
switch (mode) {
|
||||
case IWL_LED_BLINK:
|
||||
IWL_ERR(mvm, "Blink led mode not supported, used default\n");
|
||||
/* fall through */
|
||||
case IWL_LED_DEFAULT:
|
||||
case IWL_LED_RF_STATE:
|
||||
mode = IWL_LED_RF_STATE;
|
||||
|
|
|
@ -706,8 +706,7 @@ static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,
|
|||
if (vif->probe_req_reg && vif->bss_conf.assoc && vif->p2p)
|
||||
cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST);
|
||||
|
||||
if (vif->bss_conf.assoc && vif->bss_conf.he_support &&
|
||||
!iwlwifi_mod_params.disable_11ax) {
|
||||
if (vif->bss_conf.he_support && !iwlwifi_mod_params.disable_11ax) {
|
||||
cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_11AX);
|
||||
if (vif->bss_conf.twt_requester)
|
||||
ctxt_sta->data_policy |= cpu_to_le32(TWT_SUPPORTED);
|
||||
|
@ -1330,7 +1329,7 @@ void iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm,
|
|||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_extended_beacon_notif *beacon = (void *)pkt->data;
|
||||
struct iwl_mvm_tx_resp *beacon_notify_hdr;
|
||||
struct iwl_extended_beacon_notif_v5 *beacon_v5 = (void *)pkt->data;
|
||||
struct ieee80211_vif *csa_vif;
|
||||
struct ieee80211_vif *tx_blocked_vif;
|
||||
struct agg_tx_status *agg_status;
|
||||
|
@ -1338,18 +1337,29 @@ void iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm,
|
|||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
beacon_notify_hdr = &beacon->beacon_notify_hdr;
|
||||
mvm->ap_last_beacon_gp2 = le32_to_cpu(beacon->gp2);
|
||||
mvm->ibss_manager = beacon->ibss_mgr_status != 0;
|
||||
|
||||
agg_status = iwl_mvm_get_agg_status(mvm, beacon_notify_hdr);
|
||||
status = le16_to_cpu(agg_status->status) & TX_STATUS_MSK;
|
||||
IWL_DEBUG_RX(mvm,
|
||||
"beacon status %#x retries:%d tsf:0x%016llX gp2:0x%X rate:%d\n",
|
||||
status, beacon_notify_hdr->failure_frame,
|
||||
le64_to_cpu(beacon->tsf),
|
||||
mvm->ap_last_beacon_gp2,
|
||||
le32_to_cpu(beacon_notify_hdr->initial_rate));
|
||||
if (!iwl_mvm_is_short_beacon_notif_supported(mvm)) {
|
||||
struct iwl_mvm_tx_resp *beacon_notify_hdr =
|
||||
&beacon_v5->beacon_notify_hdr;
|
||||
|
||||
mvm->ibss_manager = beacon_v5->ibss_mgr_status != 0;
|
||||
agg_status = iwl_mvm_get_agg_status(mvm, beacon_notify_hdr);
|
||||
status = le16_to_cpu(agg_status->status) & TX_STATUS_MSK;
|
||||
IWL_DEBUG_RX(mvm,
|
||||
"beacon status %#x retries:%d tsf:0x%016llX gp2:0x%X rate:%d\n",
|
||||
status, beacon_notify_hdr->failure_frame,
|
||||
le64_to_cpu(beacon->tsf),
|
||||
mvm->ap_last_beacon_gp2,
|
||||
le32_to_cpu(beacon_notify_hdr->initial_rate));
|
||||
} else {
|
||||
mvm->ibss_manager = beacon->ibss_mgr_status != 0;
|
||||
status = le32_to_cpu(beacon->status) & TX_STATUS_MSK;
|
||||
IWL_DEBUG_RX(mvm,
|
||||
"beacon status %#x tsf:0x%016llX gp2:0x%X\n",
|
||||
status, le64_to_cpu(beacon->tsf),
|
||||
mvm->ap_last_beacon_gp2);
|
||||
}
|
||||
|
||||
csa_vif = rcu_dereference_protected(mvm->csa_vif,
|
||||
lockdep_is_held(&mvm->mutex));
|
||||
|
@ -1539,42 +1549,58 @@ void iwl_mvm_channel_switch_noa_notif(struct iwl_mvm *mvm,
|
|||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_channel_switch_noa_notif *notif = (void *)pkt->data;
|
||||
struct ieee80211_vif *csa_vif;
|
||||
struct ieee80211_vif *csa_vif, *vif;
|
||||
struct iwl_mvm_vif *mvmvif;
|
||||
int len = iwl_rx_packet_payload_len(pkt);
|
||||
u32 id_n_color;
|
||||
u32 id_n_color, csa_id, mac_id;
|
||||
|
||||
if (WARN_ON_ONCE(len < sizeof(*notif)))
|
||||
return;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
csa_vif = rcu_dereference(mvm->csa_vif);
|
||||
if (WARN_ON(!csa_vif || !csa_vif->csa_active))
|
||||
goto out_unlock;
|
||||
|
||||
id_n_color = le32_to_cpu(notif->id_and_color);
|
||||
mac_id = id_n_color & FW_CTXT_ID_MSK;
|
||||
|
||||
mvmvif = iwl_mvm_vif_from_mac80211(csa_vif);
|
||||
if (WARN(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color) != id_n_color,
|
||||
"channel switch noa notification on unexpected vif (csa_vif=%d, notif=%d)",
|
||||
FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color), id_n_color))
|
||||
goto out_unlock;
|
||||
if (WARN_ON_ONCE(mac_id >= NUM_MAC_INDEX_DRIVER))
|
||||
return;
|
||||
|
||||
IWL_DEBUG_INFO(mvm, "Channel Switch Started Notification\n");
|
||||
rcu_read_lock();
|
||||
vif = rcu_dereference(mvm->vif_id_to_mac[mac_id]);
|
||||
|
||||
schedule_delayed_work(&mvm->cs_tx_unblock_dwork,
|
||||
msecs_to_jiffies(IWL_MVM_CS_UNBLOCK_TX_TIMEOUT *
|
||||
csa_vif->bss_conf.beacon_int));
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_AP:
|
||||
csa_vif = rcu_dereference(mvm->csa_vif);
|
||||
if (WARN_ON(!csa_vif || !csa_vif->csa_active ||
|
||||
csa_vif != vif))
|
||||
goto out_unlock;
|
||||
|
||||
ieee80211_csa_finish(csa_vif);
|
||||
mvmvif = iwl_mvm_vif_from_mac80211(csa_vif);
|
||||
csa_id = FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color);
|
||||
if (WARN(csa_id != id_n_color,
|
||||
"channel switch noa notification on unexpected vif (csa_vif=%d, notif=%d)",
|
||||
csa_id, id_n_color))
|
||||
goto out_unlock;
|
||||
|
||||
rcu_read_unlock();
|
||||
IWL_DEBUG_INFO(mvm, "Channel Switch Started Notification\n");
|
||||
|
||||
RCU_INIT_POINTER(mvm->csa_vif, NULL);
|
||||
schedule_delayed_work(&mvm->cs_tx_unblock_dwork,
|
||||
msecs_to_jiffies(IWL_MVM_CS_UNBLOCK_TX_TIMEOUT *
|
||||
csa_vif->bss_conf.beacon_int));
|
||||
|
||||
return;
|
||||
ieee80211_csa_finish(csa_vif);
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
RCU_INIT_POINTER(mvm->csa_vif, NULL);
|
||||
return;
|
||||
case NL80211_IFTYPE_STATION:
|
||||
iwl_mvm_csa_client_absent(mvm, vif);
|
||||
ieee80211_chswitch_done(vif, true);
|
||||
break;
|
||||
default:
|
||||
/* should never happen */
|
||||
WARN_ON_ONCE(1);
|
||||
break;
|
||||
}
|
||||
out_unlock:
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
|
|
@ -3066,11 +3066,15 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
|
|||
} else if (old_state == IEEE80211_STA_AUTH &&
|
||||
new_state == IEEE80211_STA_ASSOC) {
|
||||
if (vif->type == NL80211_IFTYPE_AP) {
|
||||
vif->bss_conf.he_support = sta->he_cap.has_he;
|
||||
mvmvif->ap_assoc_sta_count++;
|
||||
iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
|
||||
if (vif->bss_conf.he_support &&
|
||||
!iwlwifi_mod_params.disable_11ax)
|
||||
iwl_mvm_cfg_he_sta(mvm, vif, mvm_sta->sta_id);
|
||||
} else if (vif->type == NL80211_IFTYPE_STATION) {
|
||||
vif->bss_conf.he_support = sta->he_cap.has_he;
|
||||
iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
|
||||
}
|
||||
|
||||
iwl_mvm_rs_rate_init(mvm, sta, mvmvif->phy_ctxt->channel->band,
|
||||
|
@ -3078,6 +3082,24 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
|
|||
ret = iwl_mvm_update_sta(mvm, vif, sta);
|
||||
} else if (old_state == IEEE80211_STA_ASSOC &&
|
||||
new_state == IEEE80211_STA_AUTHORIZED) {
|
||||
/* if wep is used, need to set the key for the station now */
|
||||
if (vif->type == NL80211_IFTYPE_AP && mvmvif->ap_wep_key) {
|
||||
mvm_sta->wep_key =
|
||||
kmemdup(mvmvif->ap_wep_key,
|
||||
sizeof(*mvmvif->ap_wep_key) +
|
||||
mvmvif->ap_wep_key->keylen,
|
||||
GFP_KERNEL);
|
||||
if (!mvm_sta->wep_key) {
|
||||
ret = -ENOMEM;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
ret = iwl_mvm_set_sta_key(mvm, vif, sta,
|
||||
mvm_sta->wep_key,
|
||||
STA_KEY_IDX_INVALID);
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
/* we don't support TDLS during DCM */
|
||||
if (iwl_mvm_phy_ctx_count(mvm) > 1)
|
||||
|
@ -3092,14 +3114,6 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
|
|||
|
||||
iwl_mvm_rs_rate_init(mvm, sta, mvmvif->phy_ctxt->channel->band,
|
||||
true);
|
||||
|
||||
/* if wep is used, need to set the key for the station now */
|
||||
if (vif->type == NL80211_IFTYPE_AP && mvmvif->ap_wep_key)
|
||||
ret = iwl_mvm_set_sta_key(mvm, vif, sta,
|
||||
mvmvif->ap_wep_key,
|
||||
STA_KEY_IDX_INVALID);
|
||||
else
|
||||
ret = 0;
|
||||
} else if (old_state == IEEE80211_STA_AUTHORIZED &&
|
||||
new_state == IEEE80211_STA_ASSOC) {
|
||||
/* disable beacon filtering */
|
||||
|
@ -3127,10 +3141,12 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
|
|||
/* Remove STA key if this is an AP using WEP */
|
||||
if (vif->type == NL80211_IFTYPE_AP && mvmvif->ap_wep_key) {
|
||||
int rm_ret = iwl_mvm_remove_sta_key(mvm, vif, sta,
|
||||
mvmvif->ap_wep_key);
|
||||
mvm_sta->wep_key);
|
||||
|
||||
if (!ret)
|
||||
ret = rm_ret;
|
||||
kfree(mvm_sta->wep_key);
|
||||
mvm_sta->wep_key = NULL;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
@ -3901,6 +3917,7 @@ static int __iwl_mvm_assign_vif_chanctx(struct iwl_mvm *mvm,
|
|||
mvmvif->ap_ibss_active = true;
|
||||
break;
|
||||
}
|
||||
/* fall through */
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
/*
|
||||
* The AP binding flow is handled as part of the start_ap flow
|
||||
|
@ -3953,25 +3970,30 @@ static int __iwl_mvm_assign_vif_chanctx(struct iwl_mvm *mvm,
|
|||
}
|
||||
|
||||
if (switching_chanctx && vif->type == NL80211_IFTYPE_STATION) {
|
||||
u32 duration = 3 * vif->bss_conf.beacon_int;
|
||||
|
||||
/* iwl_mvm_protect_session() reads directly from the
|
||||
* device (the system time), so make sure it is
|
||||
* available.
|
||||
*/
|
||||
ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PROTECT_CSA);
|
||||
if (ret)
|
||||
goto out_remove_binding;
|
||||
|
||||
/* Protect the session to make sure we hear the first
|
||||
* beacon on the new channel.
|
||||
*/
|
||||
mvmvif->csa_bcn_pending = true;
|
||||
iwl_mvm_protect_session(mvm, vif, duration, duration,
|
||||
vif->bss_conf.beacon_int / 2,
|
||||
true);
|
||||
|
||||
iwl_mvm_unref(mvm, IWL_MVM_REF_PROTECT_CSA);
|
||||
if (!fw_has_capa(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD)) {
|
||||
u32 duration = 3 * vif->bss_conf.beacon_int;
|
||||
|
||||
|
||||
/* iwl_mvm_protect_session() reads directly from the
|
||||
* device (the system time), so make sure it is
|
||||
* available.
|
||||
*/
|
||||
ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PROTECT_CSA);
|
||||
if (ret)
|
||||
goto out_remove_binding;
|
||||
|
||||
/* Protect the session to make sure we hear the first
|
||||
* beacon on the new channel.
|
||||
*/
|
||||
iwl_mvm_protect_session(mvm, vif, duration, duration,
|
||||
vif->bss_conf.beacon_int / 2,
|
||||
true);
|
||||
|
||||
iwl_mvm_unref(mvm, IWL_MVM_REF_PROTECT_CSA);
|
||||
}
|
||||
|
||||
iwl_mvm_update_quotas(mvm, false, NULL);
|
||||
}
|
||||
|
@ -4041,7 +4063,9 @@ static void __iwl_mvm_unassign_vif_chanctx(struct iwl_mvm *mvm,
|
|||
|
||||
disabled_vif = vif;
|
||||
|
||||
iwl_mvm_mac_ctxt_changed(mvm, vif, true, NULL);
|
||||
if (!fw_has_capa(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD))
|
||||
iwl_mvm_mac_ctxt_changed(mvm, vif, true, NULL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -4292,6 +4316,27 @@ static void iwl_mvm_channel_switch(struct ieee80211_hw *hw,
|
|||
"dummy channel switch op\n");
|
||||
}
|
||||
|
||||
static int iwl_mvm_schedule_client_csa(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_channel_switch *chsw)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_chan_switch_te_cmd cmd = {
|
||||
.mac_id = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
|
||||
mvmvif->color)),
|
||||
.action = cpu_to_le32(FW_CTXT_ACTION_ADD),
|
||||
.tsf = cpu_to_le32(chsw->timestamp),
|
||||
.cs_count = chsw->count,
|
||||
};
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
return iwl_mvm_send_cmd_pdu(mvm,
|
||||
WIDE_ID(MAC_CONF_GROUP,
|
||||
CHANNEL_SWITCH_TIME_EVENT_CMD),
|
||||
0, sizeof(cmd), &cmd);
|
||||
}
|
||||
|
||||
static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_channel_switch *chsw)
|
||||
|
@ -4359,14 +4404,19 @@ static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw,
|
|||
if (chsw->block_tx)
|
||||
iwl_mvm_csa_client_absent(mvm, vif);
|
||||
|
||||
iwl_mvm_schedule_csa_period(mvm, vif, vif->bss_conf.beacon_int,
|
||||
apply_time);
|
||||
if (mvmvif->bf_data.bf_enabled) {
|
||||
ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0);
|
||||
if (ret)
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
if (fw_has_capa(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD))
|
||||
iwl_mvm_schedule_client_csa(mvm, vif, chsw);
|
||||
else
|
||||
iwl_mvm_schedule_csa_period(mvm, vif,
|
||||
vif->bss_conf.beacon_int,
|
||||
apply_time);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -1311,6 +1311,12 @@ static inline bool iwl_mvm_is_frag_ebs_supported(struct iwl_mvm *mvm)
|
|||
return fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_FRAG_EBS);
|
||||
}
|
||||
|
||||
static inline bool iwl_mvm_is_short_beacon_notif_supported(struct iwl_mvm *mvm)
|
||||
{
|
||||
return fw_has_api(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_API_SHORT_BEACON_NOTIF);
|
||||
}
|
||||
|
||||
static inline bool iwl_mvm_enter_d0i3_on_suspend(struct iwl_mvm *mvm)
|
||||
{
|
||||
/* For now we only use this mode to differentiate between
|
||||
|
@ -2007,15 +2013,12 @@ static inline void iwl_mvm_stop_device(struct iwl_mvm *mvm)
|
|||
&mvm->status))
|
||||
iwl_fw_dbg_collect_desc(&mvm->fwrt, &iwl_dump_desc_assert,
|
||||
false, 0);
|
||||
/* calling this function without using dump_start/end since at this
|
||||
* point we already hold the op mode mutex
|
||||
*/
|
||||
iwl_fw_dbg_collect_sync(&mvm->fwrt);
|
||||
|
||||
iwl_fw_cancel_timestamp(&mvm->fwrt);
|
||||
iwl_free_fw_paging(&mvm->fwrt);
|
||||
clear_bit(IWL_MVM_STATUS_FIRMWARE_RUNNING, &mvm->status);
|
||||
iwl_fwrt_stop_device(&mvm->fwrt);
|
||||
iwl_free_fw_paging(&mvm->fwrt);
|
||||
iwl_fw_dump_conf_clear(&mvm->fwrt);
|
||||
iwl_trans_stop_device(mvm->trans);
|
||||
}
|
||||
|
||||
/* Re-configure the SCD for a queue that has already been configured */
|
||||
|
|
|
@ -82,7 +82,6 @@
|
|||
#include "fw/api/scan.h"
|
||||
#include "time-event.h"
|
||||
#include "fw-api.h"
|
||||
#include "fw/api/scan.h"
|
||||
#include "fw/acpi.h"
|
||||
|
||||
#define DRV_DESCRIPTION "The new Intel(R) wireless AGN driver for Linux"
|
||||
|
@ -421,6 +420,7 @@ static const struct iwl_hcmd_names iwl_mvm_system_names[] = {
|
|||
* Access is done through binary search
|
||||
*/
|
||||
static const struct iwl_hcmd_names iwl_mvm_mac_conf_names[] = {
|
||||
HCMD_NAME(CHANNEL_SWITCH_TIME_EVENT_CMD),
|
||||
HCMD_NAME(CHANNEL_SWITCH_NOA_NOTIF),
|
||||
};
|
||||
|
||||
|
@ -445,6 +445,7 @@ static const struct iwl_hcmd_names iwl_mvm_data_path_names[] = {
|
|||
HCMD_NAME(TRIGGER_RX_QUEUES_NOTIF_CMD),
|
||||
HCMD_NAME(STA_HE_CTXT_CMD),
|
||||
HCMD_NAME(RFH_QUEUE_CONFIG_CMD),
|
||||
HCMD_NAME(TLC_MNG_CONFIG_CMD),
|
||||
HCMD_NAME(CHEST_COLLECTOR_FILTER_CONFIG_CMD),
|
||||
HCMD_NAME(STA_PM_NOTIF),
|
||||
HCMD_NAME(MU_GROUP_MGMT_NOTIF),
|
||||
|
@ -817,8 +818,8 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
|||
mutex_lock(&mvm->mutex);
|
||||
iwl_mvm_ref(mvm, IWL_MVM_REF_INIT_UCODE);
|
||||
err = iwl_run_init_mvm_ucode(mvm, true);
|
||||
if (test_bit(IWL_FWRT_STATUS_WAIT_ALIVE, &mvm->fwrt.status))
|
||||
iwl_fw_alive_error_dump(&mvm->fwrt);
|
||||
if (err)
|
||||
iwl_fw_dbg_error_collect(&mvm->fwrt, FW_DBG_TRIGGER_DRIVER);
|
||||
if (!iwlmvm_mod_params.init_dbg || !err)
|
||||
iwl_mvm_stop_device(mvm);
|
||||
iwl_mvm_unref(mvm, IWL_MVM_REF_INIT_UCODE);
|
||||
|
|
|
@ -109,6 +109,7 @@ u8 iwl_mvm_get_ctrl_pos(struct cfg80211_chan_def *chandef)
|
|||
return PHY_VHT_CTRL_POS_4_ABOVE;
|
||||
default:
|
||||
WARN(1, "Invalid channel definition");
|
||||
/* fall through */
|
||||
case 0:
|
||||
/*
|
||||
* The FW is expected to check the control channel position only
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -30,6 +31,7 @@
|
|||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018 Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -79,6 +81,8 @@ int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm,
|
|||
struct iwl_beacon_filter_cmd *cmd,
|
||||
u32 flags)
|
||||
{
|
||||
u16 len;
|
||||
|
||||
IWL_DEBUG_POWER(mvm, "ba_enable_beacon_abort is: %d\n",
|
||||
le32_to_cpu(cmd->ba_enable_beacon_abort));
|
||||
IWL_DEBUG_POWER(mvm, "ba_escape_timer is: %d\n",
|
||||
|
@ -101,9 +105,23 @@ int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm,
|
|||
le32_to_cpu(cmd->bf_temp_fast_filter));
|
||||
IWL_DEBUG_POWER(mvm, "bf_temp_slow_filter is: %d\n",
|
||||
le32_to_cpu(cmd->bf_temp_slow_filter));
|
||||
IWL_DEBUG_POWER(mvm, "bf_threshold_absolute_low is: %d, %d\n",
|
||||
le32_to_cpu(cmd->bf_threshold_absolute_low[0]),
|
||||
le32_to_cpu(cmd->bf_threshold_absolute_low[1]));
|
||||
|
||||
IWL_DEBUG_POWER(mvm, "bf_threshold_absolute_high is: %d, %d\n",
|
||||
le32_to_cpu(cmd->bf_threshold_absolute_high[0]),
|
||||
le32_to_cpu(cmd->bf_threshold_absolute_high[1]));
|
||||
|
||||
if (fw_has_api(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_API_BEACON_FILTER_V4))
|
||||
len = sizeof(struct iwl_beacon_filter_cmd);
|
||||
else
|
||||
len = offsetof(struct iwl_beacon_filter_cmd,
|
||||
bf_threshold_absolute_low);
|
||||
|
||||
return iwl_mvm_send_cmd_pdu(mvm, REPLY_BEACON_FILTERING_CMD, flags,
|
||||
sizeof(struct iwl_beacon_filter_cmd), cmd);
|
||||
len, cmd);
|
||||
}
|
||||
|
||||
static
|
||||
|
|
|
@ -1757,7 +1757,12 @@ static void rs_set_amsdu_len(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
|||
else
|
||||
mvmsta->amsdu_enabled = 0xFFFF;
|
||||
|
||||
mvmsta->max_amsdu_len = sta->max_amsdu_len;
|
||||
if (mvmsta->vif->bss_conf.he_support &&
|
||||
!iwlwifi_mod_params.disable_11ax)
|
||||
mvmsta->max_amsdu_len = sta->max_amsdu_len;
|
||||
else
|
||||
mvmsta->max_amsdu_len = min_t(int, sta->max_amsdu_len, 8500);
|
||||
|
||||
sta->max_rc_amsdu_len = mvmsta->max_amsdu_len;
|
||||
|
||||
for (i = 0; i < IWL_MAX_TID_COUNT; i++) {
|
||||
|
|
|
@ -222,7 +222,7 @@ static u32 iwl_mvm_set_mac80211_rx_flag(struct iwl_mvm *mvm,
|
|||
!(rx_pkt_status & RX_MPDU_RES_STATUS_TTAK_OK))
|
||||
return 0;
|
||||
*crypt_len = IEEE80211_TKIP_IV_LEN;
|
||||
/* fall through if TTAK OK */
|
||||
/* fall through */
|
||||
|
||||
case RX_MPDU_RES_STATUS_SEC_WEP_ENC:
|
||||
if (!(rx_pkt_status & RX_MPDU_RES_STATUS_ICV_OK))
|
||||
|
|
|
@ -66,11 +66,37 @@
|
|||
#include "mvm.h"
|
||||
#include "fw-api.h"
|
||||
|
||||
static void *iwl_mvm_skb_get_hdr(struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
|
||||
u8 *data = skb->data;
|
||||
|
||||
/* Alignment concerns */
|
||||
BUILD_BUG_ON(sizeof(struct ieee80211_radiotap_he) % 4);
|
||||
BUILD_BUG_ON(sizeof(struct ieee80211_radiotap_he_mu) % 4);
|
||||
BUILD_BUG_ON(sizeof(struct ieee80211_radiotap_lsig) % 4);
|
||||
BUILD_BUG_ON(sizeof(struct ieee80211_vendor_radiotap) % 4);
|
||||
|
||||
if (rx_status->flag & RX_FLAG_RADIOTAP_HE)
|
||||
data += sizeof(struct ieee80211_radiotap_he);
|
||||
if (rx_status->flag & RX_FLAG_RADIOTAP_HE_MU)
|
||||
data += sizeof(struct ieee80211_radiotap_he_mu);
|
||||
if (rx_status->flag & RX_FLAG_RADIOTAP_LSIG)
|
||||
data += sizeof(struct ieee80211_radiotap_lsig);
|
||||
if (rx_status->flag & RX_FLAG_RADIOTAP_VENDOR_DATA) {
|
||||
struct ieee80211_vendor_radiotap *radiotap = (void *)data;
|
||||
|
||||
data += sizeof(*radiotap) + radiotap->len + radiotap->pad;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static inline int iwl_mvm_check_pn(struct iwl_mvm *mvm, struct sk_buff *skb,
|
||||
int queue, struct ieee80211_sta *sta)
|
||||
{
|
||||
struct iwl_mvm_sta *mvmsta;
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
struct ieee80211_hdr *hdr = iwl_mvm_skb_get_hdr(skb);
|
||||
struct ieee80211_rx_status *stats = IEEE80211_SKB_RXCB(skb);
|
||||
struct iwl_mvm_key_pn *ptk_pn;
|
||||
int res;
|
||||
|
@ -197,12 +223,15 @@ static void iwl_mvm_add_rtap_sniffer_config(struct iwl_mvm *mvm,
|
|||
{
|
||||
struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
|
||||
struct ieee80211_vendor_radiotap *radiotap;
|
||||
int size = sizeof(*radiotap) + sizeof(__le16);
|
||||
const int size = sizeof(*radiotap) + sizeof(__le16);
|
||||
|
||||
if (!mvm->cur_aid)
|
||||
return;
|
||||
|
||||
radiotap = skb_put(skb, size);
|
||||
/* ensure alignment */
|
||||
BUILD_BUG_ON((size + 2) % 4);
|
||||
|
||||
radiotap = skb_put(skb, size + 2);
|
||||
radiotap->align = 1;
|
||||
/* Intel OUI */
|
||||
radiotap->oui[0] = 0xf6;
|
||||
|
@ -212,10 +241,12 @@ static void iwl_mvm_add_rtap_sniffer_config(struct iwl_mvm *mvm,
|
|||
radiotap->subns = 1;
|
||||
radiotap->present = 0x1;
|
||||
radiotap->len = size - sizeof(*radiotap);
|
||||
radiotap->pad = 0;
|
||||
radiotap->pad = 2;
|
||||
|
||||
/* fill the data now */
|
||||
memcpy(radiotap->data, &mvm->cur_aid, sizeof(mvm->cur_aid));
|
||||
/* and clear the padding */
|
||||
memset(radiotap->data + sizeof(__le16), 0, radiotap->pad);
|
||||
|
||||
rx_status->flag |= RX_FLAG_RADIOTAP_VENDOR_DATA;
|
||||
}
|
||||
|
@ -310,7 +341,7 @@ static int iwl_mvm_rx_crypto(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr,
|
|||
stats->flag |= RX_FLAG_MMIC_ERROR;
|
||||
|
||||
*crypt_len = IEEE80211_TKIP_IV_LEN;
|
||||
/* fall through if TTAK OK */
|
||||
/* fall through */
|
||||
case IWL_RX_MPDU_STATUS_SEC_WEP:
|
||||
if (!(status & IWL_RX_MPDU_STATUS_ICV_OK))
|
||||
return -1;
|
||||
|
@ -663,7 +694,7 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
|
|||
struct sk_buff *skb,
|
||||
struct iwl_rx_mpdu_desc *desc)
|
||||
{
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
struct ieee80211_hdr *hdr = iwl_mvm_skb_get_hdr(skb);
|
||||
struct iwl_mvm_sta *mvm_sta;
|
||||
struct iwl_mvm_baid_data *baid_data;
|
||||
struct iwl_mvm_reorder_buffer *buffer;
|
||||
|
@ -960,6 +991,7 @@ iwl_mvm_decode_he_phy_ru_alloc(struct iwl_mvm_rx_phy_data *phy_data,
|
|||
* the TSF/timers are not be transmitted in HE-MU.
|
||||
*/
|
||||
u8 ru = le32_get_bits(phy_data->d1, IWL_RX_PHY_DATA1_HE_RU_ALLOC_MASK);
|
||||
u32 he_type = rate_n_flags & RATE_MCS_HE_TYPE_MSK;
|
||||
u8 offs = 0;
|
||||
|
||||
rx_status->bw = RATE_INFO_BW_HE_RU;
|
||||
|
@ -1002,19 +1034,27 @@ iwl_mvm_decode_he_phy_ru_alloc(struct iwl_mvm_rx_phy_data *phy_data,
|
|||
he->data2 |=
|
||||
cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_SEC);
|
||||
|
||||
if (he_mu) {
|
||||
#define CHECK_BW(bw) \
|
||||
BUILD_BUG_ON(IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_ ## bw ## MHZ != \
|
||||
RATE_MCS_CHAN_WIDTH_##bw >> RATE_MCS_CHAN_WIDTH_POS); \
|
||||
BUILD_BUG_ON(IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW_ ## bw ## MHZ != \
|
||||
RATE_MCS_CHAN_WIDTH_##bw >> RATE_MCS_CHAN_WIDTH_POS)
|
||||
CHECK_BW(20);
|
||||
CHECK_BW(40);
|
||||
CHECK_BW(80);
|
||||
CHECK_BW(160);
|
||||
CHECK_BW(20);
|
||||
CHECK_BW(40);
|
||||
CHECK_BW(80);
|
||||
CHECK_BW(160);
|
||||
|
||||
if (he_mu)
|
||||
he_mu->flags2 |=
|
||||
le16_encode_bits(FIELD_GET(RATE_MCS_CHAN_WIDTH_MSK,
|
||||
rate_n_flags),
|
||||
IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW);
|
||||
}
|
||||
else if (he_type == RATE_MCS_HE_TYPE_TRIG)
|
||||
he->data6 |=
|
||||
cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW_KNOWN) |
|
||||
le16_encode_bits(FIELD_GET(RATE_MCS_CHAN_WIDTH_MSK,
|
||||
rate_n_flags),
|
||||
IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW);
|
||||
}
|
||||
|
||||
static void iwl_mvm_decode_he_phy_data(struct iwl_mvm *mvm,
|
||||
|
@ -1165,22 +1205,16 @@ static void iwl_mvm_rx_he(struct iwl_mvm *mvm, struct sk_buff *skb,
|
|||
.flags2 = cpu_to_le16(IEEE80211_RADIOTAP_HE_MU_FLAGS2_PUNC_FROM_SIG_A_BW_KNOWN |
|
||||
IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN),
|
||||
};
|
||||
unsigned int radiotap_len = 0;
|
||||
|
||||
he = skb_put_data(skb, &known, sizeof(known));
|
||||
radiotap_len += sizeof(known);
|
||||
rx_status->flag |= RX_FLAG_RADIOTAP_HE;
|
||||
|
||||
if (phy_data->info_type == IWL_RX_PHY_INFO_TYPE_HE_MU ||
|
||||
phy_data->info_type == IWL_RX_PHY_INFO_TYPE_HE_MU_EXT) {
|
||||
he_mu = skb_put_data(skb, &mu_known, sizeof(mu_known));
|
||||
radiotap_len += sizeof(mu_known);
|
||||
rx_status->flag |= RX_FLAG_RADIOTAP_HE_MU;
|
||||
}
|
||||
|
||||
/* temporarily hide the radiotap data */
|
||||
__skb_pull(skb, radiotap_len);
|
||||
|
||||
/* report the AMPDU-EOF bit on single frames */
|
||||
if (!queue && !(phy_info & IWL_RX_MPDU_PHY_AMPDU)) {
|
||||
rx_status->flag |= RX_FLAG_AMPDU_DETAILS;
|
||||
|
|
|
@ -1616,10 +1616,10 @@ static int iwl_mvm_check_running_scans(struct iwl_mvm *mvm, int type)
|
|||
if (mvm->scan_status & IWL_MVM_SCAN_SCHED_MASK)
|
||||
return iwl_mvm_scan_stop(mvm, IWL_MVM_SCAN_SCHED,
|
||||
true);
|
||||
|
||||
/* fall through, something is wrong if no scan was
|
||||
* running but we ran out of scans.
|
||||
/* Something is wrong if no scan was running but we
|
||||
* ran out of scans.
|
||||
*/
|
||||
/* fall through */
|
||||
default:
|
||||
WARN_ON(1);
|
||||
break;
|
||||
|
@ -1976,9 +1976,8 @@ static int iwl_mvm_scan_stop_wait(struct iwl_mvm *mvm, int type)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = iwl_wait_notification(&mvm->notif_wait, &wait_scan_done, 1 * HZ);
|
||||
|
||||
return ret;
|
||||
return iwl_wait_notification(&mvm->notif_wait, &wait_scan_done,
|
||||
1 * HZ);
|
||||
}
|
||||
|
||||
int iwl_mvm_scan_size(struct iwl_mvm *mvm)
|
||||
|
|
|
@ -314,7 +314,6 @@ static int iwl_mvm_invalidate_sta_queue(struct iwl_mvm *mvm, int queue,
|
|||
struct iwl_mvm_sta *mvmsta;
|
||||
u32 status;
|
||||
u8 sta_id;
|
||||
int ret;
|
||||
|
||||
if (WARN_ON(iwl_mvm_has_new_tx_api(mvm)))
|
||||
return -EINVAL;
|
||||
|
@ -349,11 +348,9 @@ static int iwl_mvm_invalidate_sta_queue(struct iwl_mvm *mvm, int queue,
|
|||
|
||||
/* Notify FW of queue removal from the STA queues */
|
||||
status = ADD_STA_SUCCESS;
|
||||
ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA,
|
||||
iwl_mvm_add_sta_cmd_size(mvm),
|
||||
&cmd, &status);
|
||||
|
||||
return ret;
|
||||
return iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA,
|
||||
iwl_mvm_add_sta_cmd_size(mvm),
|
||||
&cmd, &status);
|
||||
}
|
||||
|
||||
static int iwl_mvm_disable_txq(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
||||
|
@ -794,11 +791,9 @@ static int iwl_mvm_sta_alloc_queue_tvqm(struct iwl_mvm *mvm,
|
|||
if (queue < 0)
|
||||
return queue;
|
||||
|
||||
if (sta) {
|
||||
mvmtxq->txq_id = queue;
|
||||
mvm->tvqm_info[queue].txq_tid = tid;
|
||||
mvm->tvqm_info[queue].sta_id = mvmsta->sta_id;
|
||||
}
|
||||
mvmtxq->txq_id = queue;
|
||||
mvm->tvqm_info[queue].txq_tid = tid;
|
||||
mvm->tvqm_info[queue].sta_id = mvmsta->sta_id;
|
||||
|
||||
IWL_DEBUG_TX_QUEUES(mvm, "Allocated queue is %d\n", queue);
|
||||
|
||||
|
@ -2340,11 +2335,13 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
|||
if (mvmvif->ap_wep_key) {
|
||||
u8 key_offset = iwl_mvm_set_fw_key_idx(mvm);
|
||||
|
||||
__set_bit(key_offset, mvm->fw_key_table);
|
||||
|
||||
if (key_offset == STA_KEY_IDX_INVALID)
|
||||
return -ENOSPC;
|
||||
|
||||
ret = iwl_mvm_send_sta_key(mvm, mvmvif->mcast_sta.sta_id,
|
||||
mvmvif->ap_wep_key, 1, 0, NULL, 0,
|
||||
mvmvif->ap_wep_key, true, 0, NULL, 0,
|
||||
key_offset, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
@ -2353,6 +2350,59 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int __iwl_mvm_remove_sta_key(struct iwl_mvm *mvm, u8 sta_id,
|
||||
struct ieee80211_key_conf *keyconf,
|
||||
bool mcast)
|
||||
{
|
||||
union {
|
||||
struct iwl_mvm_add_sta_key_cmd_v1 cmd_v1;
|
||||
struct iwl_mvm_add_sta_key_cmd cmd;
|
||||
} u = {};
|
||||
bool new_api = fw_has_api(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_API_TKIP_MIC_KEYS);
|
||||
__le16 key_flags;
|
||||
int ret, size;
|
||||
u32 status;
|
||||
|
||||
/* This is a valid situation for GTK removal */
|
||||
if (sta_id == IWL_MVM_INVALID_STA)
|
||||
return 0;
|
||||
|
||||
key_flags = cpu_to_le16((keyconf->keyidx << STA_KEY_FLG_KEYID_POS) &
|
||||
STA_KEY_FLG_KEYID_MSK);
|
||||
key_flags |= cpu_to_le16(STA_KEY_FLG_NO_ENC | STA_KEY_FLG_WEP_KEY_MAP);
|
||||
key_flags |= cpu_to_le16(STA_KEY_NOT_VALID);
|
||||
|
||||
if (mcast)
|
||||
key_flags |= cpu_to_le16(STA_KEY_MULTICAST);
|
||||
|
||||
/*
|
||||
* The fields assigned here are in the same location at the start
|
||||
* of the command, so we can do this union trick.
|
||||
*/
|
||||
u.cmd.common.key_flags = key_flags;
|
||||
u.cmd.common.key_offset = keyconf->hw_key_idx;
|
||||
u.cmd.common.sta_id = sta_id;
|
||||
|
||||
size = new_api ? sizeof(u.cmd) : sizeof(u.cmd_v1);
|
||||
|
||||
status = ADD_STA_SUCCESS;
|
||||
ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA_KEY, size, &u.cmd,
|
||||
&status);
|
||||
|
||||
switch (status) {
|
||||
case ADD_STA_SUCCESS:
|
||||
IWL_DEBUG_WEP(mvm, "MODIFY_STA: remove sta key passed\n");
|
||||
break;
|
||||
default:
|
||||
ret = -EIO;
|
||||
IWL_ERR(mvm, "MODIFY_STA: remove sta key failed\n");
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send the FW a request to remove the station from it's internal data
|
||||
* structures, and in addition remove it from the local data structure.
|
||||
|
@ -2368,6 +2418,28 @@ int iwl_mvm_rm_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
|||
|
||||
iwl_mvm_disable_txq(mvm, NULL, mvmvif->cab_queue, 0, 0);
|
||||
|
||||
if (mvmvif->ap_wep_key) {
|
||||
int i;
|
||||
|
||||
if (!__test_and_clear_bit(mvmvif->ap_wep_key->hw_key_idx,
|
||||
mvm->fw_key_table)) {
|
||||
IWL_ERR(mvm, "offset %d not used in fw key table.\n",
|
||||
mvmvif->ap_wep_key->hw_key_idx);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/* track which key was deleted last */
|
||||
for (i = 0; i < STA_KEY_MAX_NUM; i++) {
|
||||
if (mvm->fw_key_deleted[i] < U8_MAX)
|
||||
mvm->fw_key_deleted[i]++;
|
||||
}
|
||||
mvm->fw_key_deleted[mvmvif->ap_wep_key->hw_key_idx] = 0;
|
||||
ret = __iwl_mvm_remove_sta_key(mvm, mvmvif->mcast_sta.sta_id,
|
||||
mvmvif->ap_wep_key, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = iwl_mvm_rm_sta_common(mvm, mvmvif->mcast_sta.sta_id);
|
||||
if (ret)
|
||||
IWL_WARN(mvm, "Failed sending remove station\n");
|
||||
|
@ -3399,59 +3471,6 @@ static int __iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int __iwl_mvm_remove_sta_key(struct iwl_mvm *mvm, u8 sta_id,
|
||||
struct ieee80211_key_conf *keyconf,
|
||||
bool mcast)
|
||||
{
|
||||
union {
|
||||
struct iwl_mvm_add_sta_key_cmd_v1 cmd_v1;
|
||||
struct iwl_mvm_add_sta_key_cmd cmd;
|
||||
} u = {};
|
||||
bool new_api = fw_has_api(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_API_TKIP_MIC_KEYS);
|
||||
__le16 key_flags;
|
||||
int ret, size;
|
||||
u32 status;
|
||||
|
||||
/* This is a valid situation for GTK removal */
|
||||
if (sta_id == IWL_MVM_INVALID_STA)
|
||||
return 0;
|
||||
|
||||
key_flags = cpu_to_le16((keyconf->keyidx << STA_KEY_FLG_KEYID_POS) &
|
||||
STA_KEY_FLG_KEYID_MSK);
|
||||
key_flags |= cpu_to_le16(STA_KEY_FLG_NO_ENC | STA_KEY_FLG_WEP_KEY_MAP);
|
||||
key_flags |= cpu_to_le16(STA_KEY_NOT_VALID);
|
||||
|
||||
if (mcast)
|
||||
key_flags |= cpu_to_le16(STA_KEY_MULTICAST);
|
||||
|
||||
/*
|
||||
* The fields assigned here are in the same location at the start
|
||||
* of the command, so we can do this union trick.
|
||||
*/
|
||||
u.cmd.common.key_flags = key_flags;
|
||||
u.cmd.common.key_offset = keyconf->hw_key_idx;
|
||||
u.cmd.common.sta_id = sta_id;
|
||||
|
||||
size = new_api ? sizeof(u.cmd) : sizeof(u.cmd_v1);
|
||||
|
||||
status = ADD_STA_SUCCESS;
|
||||
ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA_KEY, size, &u.cmd,
|
||||
&status);
|
||||
|
||||
switch (status) {
|
||||
case ADD_STA_SUCCESS:
|
||||
IWL_DEBUG_WEP(mvm, "MODIFY_STA: remove sta key passed\n");
|
||||
break;
|
||||
default:
|
||||
ret = -EIO;
|
||||
IWL_ERR(mvm, "MODIFY_STA: remove sta key failed\n");
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
|
|
|
@ -394,6 +394,7 @@ struct iwl_mvm_rxq_dup_data {
|
|||
* the BA window. To be used for UAPSD only.
|
||||
* @ptk_pn: per-queue PTK PN data structures
|
||||
* @dup_data: per queue duplicate packet detection data
|
||||
* @wep_key: used in AP mode. Is a duplicate of the WEP key.
|
||||
* @deferred_traffic_tid_map: indication bitmap of deferred traffic per-TID
|
||||
* @tx_ant: the index of the antenna to use for data tx to this station. Only
|
||||
* used during connection establishment (e.g. for the 4 way handshake
|
||||
|
@ -425,6 +426,8 @@ struct iwl_mvm_sta {
|
|||
struct iwl_mvm_key_pn __rcu *ptk_pn[4];
|
||||
struct iwl_mvm_rxq_dup_data *dup_data;
|
||||
|
||||
struct ieee80211_key_conf *wep_key;
|
||||
|
||||
u8 reserved_queue;
|
||||
|
||||
/* Temporary, until the new TLC will control the Tx protection */
|
||||
|
|
|
@ -294,6 +294,7 @@ static const struct {
|
|||
{ "SYSASSERT", 0x35 },
|
||||
{ "UCODE_VERSION_MISMATCH", 0x37 },
|
||||
{ "BAD_COMMAND", 0x38 },
|
||||
{ "BAD_COMMAND", 0x39 },
|
||||
{ "NMI_INTERRUPT_DATA_ACTION_PT", 0x3C },
|
||||
{ "FATAL_ERROR", 0x3D },
|
||||
{ "NMI_TRM_HW_ERR", 0x46 },
|
||||
|
@ -522,23 +523,9 @@ static void iwl_mvm_dump_lmac_error_log(struct iwl_mvm *mvm, u8 lmac_num)
|
|||
/* reset the device */
|
||||
iwl_trans_sw_reset(trans);
|
||||
|
||||
/* set INIT_DONE flag */
|
||||
iwl_set_bit(trans, CSR_GP_CNTRL,
|
||||
BIT(trans->cfg->csr->flag_init_done));
|
||||
|
||||
/* and wait for clock stabilization */
|
||||
if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
|
||||
udelay(2);
|
||||
|
||||
err = iwl_poll_bit(trans, CSR_GP_CNTRL,
|
||||
BIT(trans->cfg->csr->flag_mac_clock_ready),
|
||||
BIT(trans->cfg->csr->flag_mac_clock_ready),
|
||||
25000);
|
||||
if (err < 0) {
|
||||
IWL_DEBUG_INFO(trans,
|
||||
"Failed to reset the card for the dump\n");
|
||||
err = iwl_finish_nic_init(trans);
|
||||
if (err)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
iwl_trans_read_mem_bytes(trans, base, &table, sizeof(table));
|
||||
|
|
|
@ -59,8 +59,7 @@
|
|||
|
||||
void iwl_pcie_ctxt_info_free_paging(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
struct iwl_self_init_dram *dram = &trans_pcie->init_dram;
|
||||
struct iwl_self_init_dram *dram = &trans->init_dram;
|
||||
int i;
|
||||
|
||||
if (!dram->paging) {
|
||||
|
@ -83,8 +82,7 @@ int iwl_pcie_init_fw_sec(struct iwl_trans *trans,
|
|||
const struct fw_img *fw,
|
||||
struct iwl_context_info_dram *ctxt_dram)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
struct iwl_self_init_dram *dram = &trans_pcie->init_dram;
|
||||
struct iwl_self_init_dram *dram = &trans->init_dram;
|
||||
int i, ret, lmac_cnt, umac_cnt, paging_cnt;
|
||||
|
||||
if (WARN(dram->paging,
|
||||
|
|
|
@ -453,20 +453,6 @@ enum iwl_image_response_code {
|
|||
IWL_IMAGE_RESP_FAIL = 2,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_self_init_dram - dram data used by self init process
|
||||
* @fw: lmac and umac dram data
|
||||
* @fw_cnt: total number of items in array
|
||||
* @paging: paging dram data
|
||||
* @paging_cnt: total number of items in array
|
||||
*/
|
||||
struct iwl_self_init_dram {
|
||||
struct iwl_dram_data *fw;
|
||||
int fw_cnt;
|
||||
struct iwl_dram_data *paging;
|
||||
int paging_cnt;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cont_rec: continuous recording data structure
|
||||
* @prev_wr_ptr: the last address that was read in monitor_data
|
||||
|
@ -554,7 +540,6 @@ struct iwl_trans_pcie {
|
|||
dma_addr_t prph_info_dma_addr;
|
||||
dma_addr_t prph_scratch_dma_addr;
|
||||
dma_addr_t iml_dma_addr;
|
||||
struct iwl_self_init_dram init_dram;
|
||||
struct iwl_trans *trans;
|
||||
|
||||
struct net_device napi_dev;
|
||||
|
@ -813,8 +798,7 @@ static inline int iwl_pcie_ctxt_info_alloc_dma(struct iwl_trans *trans,
|
|||
|
||||
static inline void iwl_pcie_ctxt_info_free_fw_img(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
struct iwl_self_init_dram *dram = &trans_pcie->init_dram;
|
||||
struct iwl_self_init_dram *dram = &trans->init_dram;
|
||||
int i;
|
||||
|
||||
if (!dram->fw) {
|
||||
|
@ -1052,6 +1036,7 @@ static inline bool iwl_pcie_dbg_on(struct iwl_trans *trans)
|
|||
|
||||
void iwl_trans_pcie_rf_kill(struct iwl_trans *trans, bool state);
|
||||
void iwl_trans_pcie_dump_regs(struct iwl_trans *trans);
|
||||
void iwl_trans_sync_nmi(struct iwl_trans *trans);
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans);
|
||||
|
|
|
@ -92,26 +92,9 @@ int iwl_pcie_gen2_apm_init(struct iwl_trans *trans)
|
|||
|
||||
iwl_pcie_apm_config(trans);
|
||||
|
||||
/*
|
||||
* Set "initialization complete" bit to move adapter from
|
||||
* D0U* --> D0A* (powered-up active) state.
|
||||
*/
|
||||
iwl_set_bit(trans, CSR_GP_CNTRL,
|
||||
BIT(trans->cfg->csr->flag_init_done));
|
||||
|
||||
/*
|
||||
* Wait for clock stabilization; once stabilized, access to
|
||||
* device-internal resources is supported, e.g. iwl_write_prph()
|
||||
* and accesses to uCode SRAM.
|
||||
*/
|
||||
ret = iwl_poll_bit(trans, CSR_GP_CNTRL,
|
||||
BIT(trans->cfg->csr->flag_mac_clock_ready),
|
||||
BIT(trans->cfg->csr->flag_mac_clock_ready),
|
||||
25000);
|
||||
if (ret < 0) {
|
||||
IWL_DEBUG_INFO(trans, "Failed to init the card\n");
|
||||
ret = iwl_finish_nic_init(trans);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
set_bit(STATUS_DEVICE_ENABLED, &trans->status);
|
||||
|
||||
|
|
|
@ -364,26 +364,9 @@ static int iwl_pcie_apm_init(struct iwl_trans *trans)
|
|||
if (trans->cfg->base_params->pll_cfg)
|
||||
iwl_set_bit(trans, CSR_ANA_PLL_CFG, CSR50_ANA_PLL_CFG_VAL);
|
||||
|
||||
/*
|
||||
* Set "initialization complete" bit to move adapter from
|
||||
* D0U* --> D0A* (powered-up active) state.
|
||||
*/
|
||||
iwl_set_bit(trans, CSR_GP_CNTRL,
|
||||
BIT(trans->cfg->csr->flag_init_done));
|
||||
|
||||
/*
|
||||
* Wait for clock stabilization; once stabilized, access to
|
||||
* device-internal resources is supported, e.g. iwl_write_prph()
|
||||
* and accesses to uCode SRAM.
|
||||
*/
|
||||
ret = iwl_poll_bit(trans, CSR_GP_CNTRL,
|
||||
BIT(trans->cfg->csr->flag_mac_clock_ready),
|
||||
BIT(trans->cfg->csr->flag_mac_clock_ready),
|
||||
25000);
|
||||
if (ret < 0) {
|
||||
IWL_ERR(trans, "Failed to init the card\n");
|
||||
ret = iwl_finish_nic_init(trans);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (trans->cfg->host_interrupt_operation_mode) {
|
||||
/*
|
||||
|
@ -453,23 +436,8 @@ static void iwl_pcie_apm_lp_xtal_enable(struct iwl_trans *trans)
|
|||
|
||||
iwl_trans_pcie_sw_reset(trans);
|
||||
|
||||
/*
|
||||
* Set "initialization complete" bit to move adapter from
|
||||
* D0U* --> D0A* (powered-up active) state.
|
||||
*/
|
||||
iwl_set_bit(trans, CSR_GP_CNTRL,
|
||||
BIT(trans->cfg->csr->flag_init_done));
|
||||
|
||||
/*
|
||||
* Wait for clock stabilization; once stabilized, access to
|
||||
* device-internal resources is possible.
|
||||
*/
|
||||
ret = iwl_poll_bit(trans, CSR_GP_CNTRL,
|
||||
BIT(trans->cfg->csr->flag_mac_clock_ready),
|
||||
BIT(trans->cfg->csr->flag_mac_clock_ready),
|
||||
25000);
|
||||
if (WARN_ON(ret < 0)) {
|
||||
IWL_ERR(trans, "Access time out - failed to enable LP XTAL\n");
|
||||
ret = iwl_finish_nic_init(trans);
|
||||
if (WARN_ON(ret)) {
|
||||
/* Release XTAL ON request */
|
||||
__iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL,
|
||||
CSR_GP_CNTRL_REG_FLAG_XTAL_ON);
|
||||
|
@ -1558,20 +1526,10 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans,
|
|||
|
||||
iwl_set_bit(trans, CSR_GP_CNTRL,
|
||||
BIT(trans->cfg->csr->flag_mac_access_req));
|
||||
iwl_set_bit(trans, CSR_GP_CNTRL,
|
||||
BIT(trans->cfg->csr->flag_init_done));
|
||||
|
||||
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_8000)
|
||||
udelay(2);
|
||||
|
||||
ret = iwl_poll_bit(trans, CSR_GP_CNTRL,
|
||||
BIT(trans->cfg->csr->flag_mac_clock_ready),
|
||||
BIT(trans->cfg->csr->flag_mac_clock_ready),
|
||||
25000);
|
||||
if (ret < 0) {
|
||||
IWL_ERR(trans, "Failed to resume the device (mac ready)\n");
|
||||
ret = iwl_finish_nic_init(trans);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reconfigure IVAR table in case of MSIX or reset ict table in
|
||||
|
@ -3220,10 +3178,10 @@ static struct iwl_trans_dump_data
|
|||
|
||||
/* Paged memory for gen2 HW */
|
||||
if (trans->cfg->gen2 && dump_mask & BIT(IWL_FW_ERROR_DUMP_PAGING))
|
||||
for (i = 0; i < trans_pcie->init_dram.paging_cnt; i++)
|
||||
for (i = 0; i < trans->init_dram.paging_cnt; i++)
|
||||
len += sizeof(*data) +
|
||||
sizeof(struct iwl_fw_error_dump_paging) +
|
||||
trans_pcie->init_dram.paging[i].size;
|
||||
trans->init_dram.paging[i].size;
|
||||
|
||||
dump_data = vzalloc(len);
|
||||
if (!dump_data)
|
||||
|
@ -3275,20 +3233,16 @@ static struct iwl_trans_dump_data
|
|||
|
||||
/* Paged memory for gen2 HW */
|
||||
if (trans->cfg->gen2 && dump_mask & BIT(IWL_FW_ERROR_DUMP_PAGING)) {
|
||||
for (i = 0; i < trans_pcie->init_dram.paging_cnt; i++) {
|
||||
for (i = 0; i < trans->init_dram.paging_cnt; i++) {
|
||||
struct iwl_fw_error_dump_paging *paging;
|
||||
dma_addr_t addr =
|
||||
trans_pcie->init_dram.paging[i].physical;
|
||||
u32 page_len = trans_pcie->init_dram.paging[i].size;
|
||||
u32 page_len = trans->init_dram.paging[i].size;
|
||||
|
||||
data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PAGING);
|
||||
data->len = cpu_to_le32(sizeof(*paging) + page_len);
|
||||
paging = (void *)data->data;
|
||||
paging->index = cpu_to_le32(i);
|
||||
dma_sync_single_for_cpu(trans->dev, addr, page_len,
|
||||
DMA_BIDIRECTIONAL);
|
||||
memcpy(paging->data,
|
||||
trans_pcie->init_dram.paging[i].block, page_len);
|
||||
trans->init_dram.paging[i].block, page_len);
|
||||
data = iwl_fw_error_next_data(data);
|
||||
|
||||
len += sizeof(*data) + sizeof(*paging) + page_len;
|
||||
|
@ -3525,18 +3479,9 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
|
|||
* in-order to recognize C step driver should read chip version
|
||||
* id located at the AUX bus MISC address space.
|
||||
*/
|
||||
iwl_set_bit(trans, CSR_GP_CNTRL,
|
||||
BIT(trans->cfg->csr->flag_init_done));
|
||||
udelay(2);
|
||||
|
||||
ret = iwl_poll_bit(trans, CSR_GP_CNTRL,
|
||||
BIT(trans->cfg->csr->flag_mac_clock_ready),
|
||||
BIT(trans->cfg->csr->flag_mac_clock_ready),
|
||||
25000);
|
||||
if (ret < 0) {
|
||||
IWL_DEBUG_INFO(trans, "Failed to wake up the nic\n");
|
||||
ret = iwl_finish_nic_init(trans);
|
||||
if (ret)
|
||||
goto out_no_pci;
|
||||
}
|
||||
|
||||
if (iwl_trans_grab_nic_access(trans, &flags)) {
|
||||
u32 hw_step;
|
||||
|
@ -3654,3 +3599,28 @@ out_no_pci:
|
|||
iwl_trans_free(trans);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
void iwl_trans_sync_nmi(struct iwl_trans *trans)
|
||||
{
|
||||
unsigned long timeout = jiffies + IWL_TRANS_NMI_TIMEOUT;
|
||||
|
||||
iwl_disable_interrupts(trans);
|
||||
iwl_force_nmi(trans);
|
||||
while (time_after(timeout, jiffies)) {
|
||||
u32 inta_hw = iwl_read32(trans,
|
||||
CSR_MSIX_HW_INT_CAUSES_AD);
|
||||
|
||||
/* Error detected by uCode */
|
||||
if (inta_hw & MSIX_HW_INT_CAUSES_REG_SW_ERR) {
|
||||
/* Clear causes register */
|
||||
iwl_write32(trans, CSR_MSIX_HW_INT_CAUSES_AD,
|
||||
inta_hw &
|
||||
MSIX_HW_INT_CAUSES_REG_SW_ERR);
|
||||
break;
|
||||
}
|
||||
|
||||
mdelay(1);
|
||||
}
|
||||
iwl_enable_interrupts(trans);
|
||||
iwl_trans_fw_error(trans);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2017 Intel Deutschland GmbH
|
||||
* Copyright(c) 2018 Intel Corporation
|
||||
* Copyright(c) 2018 - 2019 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -20,7 +20,7 @@
|
|||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2017 Intel Deutschland GmbH
|
||||
* Copyright(c) 2018 Intel Corporation
|
||||
* Copyright(c) 2018 - 2019 Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -965,9 +965,7 @@ static int iwl_pcie_gen2_send_hcmd_sync(struct iwl_trans *trans,
|
|||
cmd_str);
|
||||
ret = -ETIMEDOUT;
|
||||
|
||||
iwl_force_nmi(trans);
|
||||
iwl_trans_fw_error(trans);
|
||||
|
||||
iwl_trans_sync_nmi(trans);
|
||||
goto cancel;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||
* Copyright(c) 2018 Intel Corporation
|
||||
* Copyright(c) 2018 - 2019 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -31,7 +31,7 @@
|
|||
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||
* Copyright(c) 2018 Intel Corporation
|
||||
* Copyright(c) 2018 - 2019 Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -1942,9 +1942,7 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans,
|
|||
iwl_get_cmd_string(trans, cmd->id));
|
||||
ret = -ETIMEDOUT;
|
||||
|
||||
iwl_force_nmi(trans);
|
||||
iwl_trans_fw_error(trans);
|
||||
|
||||
iwl_trans_sync_nmi(trans);
|
||||
goto cancel;
|
||||
}
|
||||
|
||||
|
|
|
@ -291,6 +291,12 @@ enum ieee80211_radiotap_he_bits {
|
|||
|
||||
IEEE80211_RADIOTAP_HE_DATA6_NSTS = 0x000f,
|
||||
IEEE80211_RADIOTAP_HE_DATA6_DOPPLER = 0x0010,
|
||||
IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW_KNOWN = 0x0020,
|
||||
IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW = 0x00c0,
|
||||
IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW_20MHZ = 0,
|
||||
IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW_40MHZ = 1,
|
||||
IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW_80MHZ = 2,
|
||||
IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW_160MHZ = 3,
|
||||
IEEE80211_RADIOTAP_HE_DATA6_TXOP = 0x7f00,
|
||||
IEEE80211_RADIOTAP_HE_DATA6_MIDAMBLE_PDCTY = 0x8000,
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue