Commit 8db32fa4 authored by Kalle Valo's avatar Kalle Valo

Merge tag 'iwlwifi-next-for-kalle-2019-03-22' of...

Merge tag 'iwlwifi-next-for-kalle-2019-03-22' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next

First batch of patches intended for v5.2

* Send NO_DATA events so they can be captured in radiotap;
* Some channel-switch changes;
* Support for multiple BSSID;
* Continued work and bugfixes for the new debugging infra;
* Support for some new FW API versions;
* Some work to support new hardware;
* General bugfixes;
* Other cleanups;
parents 35f861e3 fe63f21b
...@@ -88,6 +88,7 @@ ...@@ -88,6 +88,7 @@
#define IWL_22000_SO_A_HR_B_FW_PRE "iwlwifi-so-a0-hr-b0-" #define IWL_22000_SO_A_HR_B_FW_PRE "iwlwifi-so-a0-hr-b0-"
#define IWL_22000_SO_A_GF_A_FW_PRE "iwlwifi-so-a0-gf-a0-" #define IWL_22000_SO_A_GF_A_FW_PRE "iwlwifi-so-a0-gf-a0-"
#define IWL_22000_TY_A_GF_A_FW_PRE "iwlwifi-ty-a0-gf-a0-" #define IWL_22000_TY_A_GF_A_FW_PRE "iwlwifi-ty-a0-gf-a0-"
#define IWL_22000_SO_A_GF4_A_FW_PRE "iwlwifi-so-a0-gf4-a0-"
#define IWL_22000_HR_MODULE_FIRMWARE(api) \ #define IWL_22000_HR_MODULE_FIRMWARE(api) \
IWL_22000_HR_FW_PRE __stringify(api) ".ucode" IWL_22000_HR_FW_PRE __stringify(api) ".ucode"
...@@ -427,12 +428,20 @@ const struct iwl_cfg iwlax210_2ax_cfg_so_hr_a0 = { ...@@ -427,12 +428,20 @@ const struct iwl_cfg iwlax210_2ax_cfg_so_hr_a0 = {
const struct iwl_cfg iwlax210_2ax_cfg_so_gf_a0 = { const struct iwl_cfg iwlax210_2ax_cfg_so_gf_a0 = {
.name = "Intel(R) Wi-Fi 7 AX211 160MHz", .name = "Intel(R) Wi-Fi 7 AX211 160MHz",
.fw_name_pre = IWL_22000_SO_A_GF_A_FW_PRE, .fw_name_pre = IWL_22000_SO_A_GF_A_FW_PRE,
.uhb_supported = true,
IWL_DEVICE_AX210, IWL_DEVICE_AX210,
}; };
const struct iwl_cfg iwlax210_2ax_cfg_ty_gf_a0 = { const struct iwl_cfg iwlax210_2ax_cfg_ty_gf_a0 = {
.name = "Intel(R) Wi-Fi 7 AX210 160MHz", .name = "Intel(R) Wi-Fi 7 AX210 160MHz",
.fw_name_pre = IWL_22000_TY_A_GF_A_FW_PRE, .fw_name_pre = IWL_22000_TY_A_GF_A_FW_PRE,
.uhb_supported = true,
IWL_DEVICE_AX210,
};
const struct iwl_cfg iwlax210_2ax_cfg_so_gf4_a0 = {
.name = "Intel(R) Wi-Fi 7 AX210 160MHz",
.fw_name_pre = IWL_22000_SO_A_GF4_A_FW_PRE,
IWL_DEVICE_AX210, IWL_DEVICE_AX210,
}; };
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* Copyright (C) 2018 Intel Corporation * Copyright(C) 2018 - 2019 Intel Corporation
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* Copyright (C) 2018 Intel Corporation * Copyright(C) 2018 - 2019 Intel Corporation
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
...@@ -233,7 +233,8 @@ struct iwl_nvm_get_info_phy { ...@@ -233,7 +233,8 @@ struct iwl_nvm_get_info_phy {
__le32 rx_chains; __le32 rx_chains;
} __packed; /* REGULATORY_NVM_GET_INFO_PHY_SKU_SECTION_S_VER_1 */ } __packed; /* REGULATORY_NVM_GET_INFO_PHY_SKU_SECTION_S_VER_1 */
#define IWL_NUM_CHANNELS (51) #define IWL_NUM_CHANNELS_V1 51
#define IWL_NUM_CHANNELS 110
/** /**
* struct iwl_nvm_get_info_regulatory - regulatory information * struct iwl_nvm_get_info_regulatory - regulatory information
...@@ -241,12 +242,38 @@ struct iwl_nvm_get_info_phy { ...@@ -241,12 +242,38 @@ struct iwl_nvm_get_info_phy {
* @channel_profile: regulatory data of this channel * @channel_profile: regulatory data of this channel
* @reserved: reserved * @reserved: reserved
*/ */
struct iwl_nvm_get_info_regulatory { struct iwl_nvm_get_info_regulatory_v1 {
__le32 lar_enabled; __le32 lar_enabled;
__le16 channel_profile[IWL_NUM_CHANNELS]; __le16 channel_profile[IWL_NUM_CHANNELS_V1];
__le16 reserved; __le16 reserved;
} __packed; /* REGULATORY_NVM_GET_INFO_REGULATORY_S_VER_1 */ } __packed; /* REGULATORY_NVM_GET_INFO_REGULATORY_S_VER_1 */
/**
* struct iwl_nvm_get_info_regulatory - regulatory information
* @lar_enabled: is LAR enabled
* @n_channels: number of valid channels in the array
* @channel_profile: regulatory data of this channel
*/
struct iwl_nvm_get_info_regulatory {
__le32 lar_enabled;
__le32 n_channels;
__le32 channel_profile[IWL_NUM_CHANNELS];
} __packed; /* REGULATORY_NVM_GET_INFO_REGULATORY_S_VER_2 */
/**
* struct iwl_nvm_get_info_rsp_v3 - response to get NVM data
* @general: general NVM data
* @mac_sku: data relating to MAC sku
* @phy_sku: data relating to PHY sku
* @regulatory: regulatory data
*/
struct iwl_nvm_get_info_rsp_v3 {
struct iwl_nvm_get_info_general general;
struct iwl_nvm_get_info_sku mac_sku;
struct iwl_nvm_get_info_phy phy_sku;
struct iwl_nvm_get_info_regulatory_v1 regulatory;
} __packed; /* REGULATORY_NVM_GET_INFO_RSP_API_S_VER_3 */
/** /**
* struct iwl_nvm_get_info_rsp - response to get NVM data * struct iwl_nvm_get_info_rsp - response to get NVM data
* @general: general NVM data * @general: general NVM data
...@@ -259,7 +286,7 @@ struct iwl_nvm_get_info_rsp { ...@@ -259,7 +286,7 @@ struct iwl_nvm_get_info_rsp {
struct iwl_nvm_get_info_sku mac_sku; struct iwl_nvm_get_info_sku mac_sku;
struct iwl_nvm_get_info_phy phy_sku; struct iwl_nvm_get_info_phy phy_sku;
struct iwl_nvm_get_info_regulatory regulatory; struct iwl_nvm_get_info_regulatory regulatory;
} __packed; /* REGULATORY_NVM_GET_INFO_RSP_API_S_VER_3 */ } __packed; /* REGULATORY_NVM_GET_INFO_RSP_API_S_VER_4 */
/** /**
* struct iwl_nvm_access_complete_cmd - NVM_ACCESS commands are completed * struct iwl_nvm_access_complete_cmd - NVM_ACCESS commands are completed
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation * Copyright(c) 2018 - 2019 Intel Corporation
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
...@@ -688,13 +688,6 @@ struct iwl_rx_mpdu_desc { ...@@ -688,13 +688,6 @@ struct iwl_rx_mpdu_desc {
#define IWL_RX_DESC_SIZE_V1 offsetofend(struct iwl_rx_mpdu_desc, v1) #define IWL_RX_DESC_SIZE_V1 offsetofend(struct iwl_rx_mpdu_desc, v1)
#define IWL_CD_STTS_OPTIMIZED_POS 0
#define IWL_CD_STTS_OPTIMIZED_MSK 0x01
#define IWL_CD_STTS_TRANSFER_STATUS_POS 1
#define IWL_CD_STTS_TRANSFER_STATUS_MSK 0x0E
#define IWL_CD_STTS_WIFI_STATUS_POS 4
#define IWL_CD_STTS_WIFI_STATUS_MSK 0xF0
#define RX_NO_DATA_CHAIN_A_POS 0 #define RX_NO_DATA_CHAIN_A_POS 0
#define RX_NO_DATA_CHAIN_A_MSK (0xff << RX_NO_DATA_CHAIN_A_POS) #define RX_NO_DATA_CHAIN_A_MSK (0xff << RX_NO_DATA_CHAIN_A_POS)
#define RX_NO_DATA_CHAIN_B_POS 8 #define RX_NO_DATA_CHAIN_B_POS 8
...@@ -747,62 +740,6 @@ struct iwl_rx_no_data { ...@@ -747,62 +740,6 @@ struct iwl_rx_no_data {
__le32 rx_vec[2]; __le32 rx_vec[2];
} __packed; /* RX_NO_DATA_NTFY_API_S_VER_1 */ } __packed; /* RX_NO_DATA_NTFY_API_S_VER_1 */
/**
* enum iwl_completion_desc_transfer_status - transfer status (bits 1-3)
* @IWL_CD_STTS_UNUSED: unused
* @IWL_CD_STTS_UNUSED_2: unused
* @IWL_CD_STTS_END_TRANSFER: successful transfer complete.
* In sniffer mode, when split is used, set in last CD completion. (RX)
* @IWL_CD_STTS_OVERFLOW: In sniffer mode, when using split - used for
* all CD completion. (RX)
* @IWL_CD_STTS_ABORTED: CR abort / close flow. (RX)
* @IWL_CD_STTS_ERROR: general error (RX)
*/
enum iwl_completion_desc_transfer_status {
IWL_CD_STTS_UNUSED,
IWL_CD_STTS_UNUSED_2,
IWL_CD_STTS_END_TRANSFER,
IWL_CD_STTS_OVERFLOW,
IWL_CD_STTS_ABORTED,
IWL_CD_STTS_ERROR,
};
/**
* enum iwl_completion_desc_wifi_status - wifi status (bits 4-7)
* @IWL_CD_STTS_VALID: the packet is valid (RX)
* @IWL_CD_STTS_FCS_ERR: frame check sequence error (RX)
* @IWL_CD_STTS_SEC_KEY_ERR: error handling the security key of rx (RX)
* @IWL_CD_STTS_DECRYPTION_ERR: error decrypting the frame (RX)
* @IWL_CD_STTS_DUP: duplicate packet (RX)
* @IWL_CD_STTS_ICV_MIC_ERR: MIC error (RX)
* @IWL_CD_STTS_INTERNAL_SNAP_ERR: problems removing the snap (RX)
* @IWL_CD_STTS_SEC_PORT_FAIL: security port fail (RX)
* @IWL_CD_STTS_BA_OLD_SN: block ack received old SN (RX)
* @IWL_CD_STTS_QOS_NULL: QoS null packet (RX)
* @IWL_CD_STTS_MAC_HDR_ERR: MAC header conversion error (RX)
* @IWL_CD_STTS_MAX_RETRANS: reached max number of retransmissions (TX)
* @IWL_CD_STTS_EX_LIFETIME: exceeded lifetime (TX)
* @IWL_CD_STTS_NOT_USED: completed but not used (RX)
* @IWL_CD_STTS_REPLAY_ERR: pn check failed, replay error (RX)
*/
enum iwl_completion_desc_wifi_status {
IWL_CD_STTS_VALID,
IWL_CD_STTS_FCS_ERR,
IWL_CD_STTS_SEC_KEY_ERR,
IWL_CD_STTS_DECRYPTION_ERR,
IWL_CD_STTS_DUP,
IWL_CD_STTS_ICV_MIC_ERR,
IWL_CD_STTS_INTERNAL_SNAP_ERR,
IWL_CD_STTS_SEC_PORT_FAIL,
IWL_CD_STTS_BA_OLD_SN,
IWL_CD_STTS_QOS_NULL,
IWL_CD_STTS_MAC_HDR_ERR,
IWL_CD_STTS_MAX_RETRANS,
IWL_CD_STTS_EX_LIFETIME,
IWL_CD_STTS_NOT_USED,
IWL_CD_STTS_REPLAY_ERR,
};
struct iwl_frame_release { struct iwl_frame_release {
u8 baid; u8 baid;
u8 reserved; u8 reserved;
......
...@@ -788,7 +788,53 @@ struct iwl_umac_scan_complete { ...@@ -788,7 +788,53 @@ struct iwl_umac_scan_complete {
__le32 reserved; __le32 reserved;
} __packed; /* SCAN_COMPLETE_NTF_UMAC_API_S_VER_1 */ } __packed; /* SCAN_COMPLETE_NTF_UMAC_API_S_VER_1 */
#define SCAN_OFFLOAD_MATCHING_CHANNELS_LEN 5 #define SCAN_OFFLOAD_MATCHING_CHANNELS_LEN_V1 5
#define SCAN_OFFLOAD_MATCHING_CHANNELS_LEN 7
/**
* struct iwl_scan_offload_profile_match_v1 - match information
* @bssid: matched bssid
* @reserved: reserved
* @channel: channel where the match occurred
* @energy: energy
* @matching_feature: feature matches
* @matching_channels: bitmap of channels that matched, referencing
* the channels passed in the scan offload request.
*/
struct iwl_scan_offload_profile_match_v1 {
u8 bssid[ETH_ALEN];
__le16 reserved;
u8 channel;
u8 energy;
u8 matching_feature;
u8 matching_channels[SCAN_OFFLOAD_MATCHING_CHANNELS_LEN_V1];
} __packed; /* SCAN_OFFLOAD_PROFILE_MATCH_RESULTS_S_VER_1 */
/**
* struct iwl_scan_offload_profiles_query_v1 - match results query response
* @matched_profiles: bitmap of matched profiles, referencing the
* matches passed in the scan offload request
* @last_scan_age: age of the last offloaded scan
* @n_scans_done: number of offloaded scans done
* @gp2_d0u: GP2 when D0U occurred
* @gp2_invoked: GP2 when scan offload was invoked
* @resume_while_scanning: not used
* @self_recovery: obsolete
* @reserved: reserved
* @matches: array of match information, one for each match
*/
struct iwl_scan_offload_profiles_query_v1 {
__le32 matched_profiles;
__le32 last_scan_age;
__le32 n_scans_done;
__le32 gp2_d0u;
__le32 gp2_invoked;
u8 resume_while_scanning;
u8 self_recovery;
__le16 reserved;
struct iwl_scan_offload_profile_match_v1 matches[IWL_SCAN_MAX_PROFILES];
} __packed; /* SCAN_OFFLOAD_PROFILES_QUERY_RSP_S_VER_2 */
/** /**
* struct iwl_scan_offload_profile_match - match information * struct iwl_scan_offload_profile_match - match information
* @bssid: matched bssid * @bssid: matched bssid
...@@ -797,7 +843,7 @@ struct iwl_umac_scan_complete { ...@@ -797,7 +843,7 @@ struct iwl_umac_scan_complete {
* @energy: energy * @energy: energy
* @matching_feature: feature matches * @matching_feature: feature matches
* @matching_channels: bitmap of channels that matched, referencing * @matching_channels: bitmap of channels that matched, referencing
* the channels passed in tue scan offload request * the channels passed in the scan offload request.
*/ */
struct iwl_scan_offload_profile_match { struct iwl_scan_offload_profile_match {
u8 bssid[ETH_ALEN]; u8 bssid[ETH_ALEN];
...@@ -806,7 +852,7 @@ struct iwl_scan_offload_profile_match { ...@@ -806,7 +852,7 @@ struct iwl_scan_offload_profile_match {
u8 energy; u8 energy;
u8 matching_feature; u8 matching_feature;
u8 matching_channels[SCAN_OFFLOAD_MATCHING_CHANNELS_LEN]; u8 matching_channels[SCAN_OFFLOAD_MATCHING_CHANNELS_LEN];
} __packed; /* SCAN_OFFLOAD_PROFILE_MATCH_RESULTS_S_VER_1 */ } __packed; /* SCAN_OFFLOAD_PROFILE_MATCH_RESULTS_S_VER_2 */
/** /**
* struct iwl_scan_offload_profiles_query - match results query response * struct iwl_scan_offload_profiles_query - match results query response
...@@ -831,7 +877,7 @@ struct iwl_scan_offload_profiles_query { ...@@ -831,7 +877,7 @@ struct iwl_scan_offload_profiles_query {
u8 self_recovery; u8 self_recovery;
__le16 reserved; __le16 reserved;
struct iwl_scan_offload_profile_match matches[IWL_SCAN_MAX_PROFILES]; struct iwl_scan_offload_profile_match matches[IWL_SCAN_MAX_PROFILES];
} __packed; /* SCAN_OFFLOAD_PROFILES_QUERY_RSP_S_VER_2 */ } __packed; /* SCAN_OFFLOAD_PROFILES_QUERY_RSP_S_VER_3 */
/** /**
* struct iwl_umac_scan_iter_complete_notif - notifies end of scanning iteration * struct iwl_umac_scan_iter_complete_notif - notifies end of scanning iteration
......
...@@ -804,8 +804,8 @@ static void iwl_dump_paging(struct iwl_fw_runtime *fwrt, ...@@ -804,8 +804,8 @@ static void iwl_dump_paging(struct iwl_fw_runtime *fwrt,
} }
static struct iwl_fw_error_dump_file * static struct iwl_fw_error_dump_file *
_iwl_fw_error_dump(struct iwl_fw_runtime *fwrt, iwl_fw_error_dump_file(struct iwl_fw_runtime *fwrt,
struct iwl_fw_dump_ptrs *fw_error_dump) struct iwl_fw_dump_ptrs *fw_error_dump)
{ {
struct iwl_fw_error_dump_file *dump_file; struct iwl_fw_error_dump_file *dump_file;
struct iwl_fw_error_dump_data *dump_data; struct iwl_fw_error_dump_data *dump_data;
...@@ -1791,16 +1791,13 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt, ...@@ -1791,16 +1791,13 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt,
} }
static struct iwl_fw_error_dump_file * static struct iwl_fw_error_dump_file *
_iwl_fw_error_ini_dump(struct iwl_fw_runtime *fwrt, iwl_fw_error_ini_dump_file(struct iwl_fw_runtime *fwrt)
struct iwl_fw_dump_ptrs *fw_error_dump)
{ {
int size, id = le32_to_cpu(fwrt->dump.desc->trig_desc.type); int size;
struct iwl_fw_error_dump_data *dump_data; struct iwl_fw_error_dump_data *dump_data;
struct iwl_fw_error_dump_file *dump_file; struct iwl_fw_error_dump_file *dump_file;
struct iwl_fw_ini_trigger *trigger; struct iwl_fw_ini_trigger *trigger;
enum iwl_fw_ini_trigger_id id = fwrt->dump.ini_trig_id;
if (id == FW_DBG_TRIGGER_FW_ASSERT)
id = IWL_FW_TRIGGER_ID_FW_ASSERT;
if (!iwl_fw_ini_trigger_on(fwrt, id)) if (!iwl_fw_ini_trigger_on(fwrt, id))
return NULL; return NULL;
...@@ -1817,8 +1814,6 @@ _iwl_fw_error_ini_dump(struct iwl_fw_runtime *fwrt, ...@@ -1817,8 +1814,6 @@ _iwl_fw_error_ini_dump(struct iwl_fw_runtime *fwrt,
if (!dump_file) if (!dump_file)
return NULL; return NULL;
fw_error_dump->fwrt_ptr = dump_file;
dump_file->barker = cpu_to_le32(IWL_FW_ERROR_DUMP_BARKER); dump_file->barker = cpu_to_le32(IWL_FW_ERROR_DUMP_BARKER);
dump_data = (void *)dump_file->data; dump_data = (void *)dump_file->data;
dump_file->file_len = cpu_to_le32(size); dump_file->file_len = cpu_to_le32(size);
...@@ -1828,47 +1823,27 @@ _iwl_fw_error_ini_dump(struct iwl_fw_runtime *fwrt, ...@@ -1828,47 +1823,27 @@ _iwl_fw_error_ini_dump(struct iwl_fw_runtime *fwrt,
return dump_file; return dump_file;
} }
void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt) static void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
{ {
struct iwl_fw_dump_ptrs *fw_error_dump; struct iwl_fw_dump_ptrs fw_error_dump = {};
struct iwl_fw_error_dump_file *dump_file; struct iwl_fw_error_dump_file *dump_file;
struct scatterlist *sg_dump_data; struct scatterlist *sg_dump_data;
u32 file_len; u32 file_len;
u32 dump_mask = fwrt->fw->dbg.dump_mask; u32 dump_mask = fwrt->fw->dbg.dump_mask;
IWL_DEBUG_INFO(fwrt, "WRT dump start\n"); dump_file = iwl_fw_error_dump_file(fwrt, &fw_error_dump);
if (!dump_file)
/* there's no point in fw dump if the bus is dead */
if (test_bit(STATUS_TRANS_DEAD, &fwrt->trans->status)) {
IWL_ERR(fwrt, "Skip fw error dump since bus is dead\n");
goto out;
}
fw_error_dump = kzalloc(sizeof(*fw_error_dump), GFP_KERNEL);
if (!fw_error_dump)
goto out;
if (fwrt->trans->ini_valid)
dump_file = _iwl_fw_error_ini_dump(fwrt, fw_error_dump);
else
dump_file = _iwl_fw_error_dump(fwrt, fw_error_dump);
if (!dump_file) {
kfree(fw_error_dump);
goto out; goto out;
}
if (!fwrt->trans->ini_valid && fwrt->dump.monitor_only) if (!fwrt->trans->ini_valid && fwrt->dump.monitor_only)
dump_mask &= IWL_FW_ERROR_DUMP_FW_MONITOR; dump_mask &= IWL_FW_ERROR_DUMP_FW_MONITOR;
if (!fwrt->trans->ini_valid) fw_error_dump.trans_ptr = iwl_trans_dump_data(fwrt->trans, dump_mask);
fw_error_dump->trans_ptr =
iwl_trans_dump_data(fwrt->trans, dump_mask);
file_len = le32_to_cpu(dump_file->file_len); file_len = le32_to_cpu(dump_file->file_len);
fw_error_dump->fwrt_len = file_len; fw_error_dump.fwrt_len = file_len;
if (fw_error_dump->trans_ptr) {
file_len += fw_error_dump->trans_ptr->len; if (fw_error_dump.trans_ptr) {
file_len += fw_error_dump.trans_ptr->len;
dump_file->file_len = cpu_to_le32(file_len); dump_file->file_len = cpu_to_le32(file_len);
} }
...@@ -1876,27 +1851,49 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt) ...@@ -1876,27 +1851,49 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
if (sg_dump_data) { if (sg_dump_data) {
sg_pcopy_from_buffer(sg_dump_data, sg_pcopy_from_buffer(sg_dump_data,
sg_nents(sg_dump_data), sg_nents(sg_dump_data),
fw_error_dump->fwrt_ptr, fw_error_dump.fwrt_ptr,
fw_error_dump->fwrt_len, 0); fw_error_dump.fwrt_len, 0);
if (fw_error_dump->trans_ptr) if (fw_error_dump.trans_ptr)
sg_pcopy_from_buffer(sg_dump_data, sg_pcopy_from_buffer(sg_dump_data,
sg_nents(sg_dump_data), sg_nents(sg_dump_data),
fw_error_dump->trans_ptr->data, fw_error_dump.trans_ptr->data,
fw_error_dump->trans_ptr->len, fw_error_dump.trans_ptr->len,
fw_error_dump->fwrt_len); fw_error_dump.fwrt_len);
dev_coredumpsg(fwrt->trans->dev, sg_dump_data, file_len, dev_coredumpsg(fwrt->trans->dev, sg_dump_data, file_len,
GFP_KERNEL); GFP_KERNEL);
} }
vfree(fw_error_dump->fwrt_ptr); vfree(fw_error_dump.fwrt_ptr);
vfree(fw_error_dump->trans_ptr); vfree(fw_error_dump.trans_ptr);
kfree(fw_error_dump);
out: out:
iwl_fw_free_dump_desc(fwrt); iwl_fw_free_dump_desc(fwrt);
clear_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status); clear_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status);
IWL_DEBUG_INFO(fwrt, "WRT dump done\n");
} }
IWL_EXPORT_SYMBOL(iwl_fw_error_dump);
static void iwl_fw_error_ini_dump(struct iwl_fw_runtime *fwrt)
{
struct iwl_fw_error_dump_file *dump_file;
struct scatterlist *sg_dump_data;
u32 file_len;
dump_file = iwl_fw_error_ini_dump_file(fwrt);
if (!dump_file)
goto out;
file_len = le32_to_cpu(dump_file->file_len);
sg_dump_data = alloc_sgtable(file_len);
if (sg_dump_data) {
sg_pcopy_from_buffer(sg_dump_data, sg_nents(sg_dump_data),
dump_file, file_len, 0);
dev_coredumpsg(fwrt->trans->dev, sg_dump_data, file_len,
GFP_KERNEL);
}
vfree(dump_file);
out:
fwrt->dump.ini_trig_id = IWL_FW_TRIGGER_ID_INVALID;
clear_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status);
}
const struct iwl_fw_dump_desc iwl_dump_desc_assert = { const struct iwl_fw_dump_desc iwl_dump_desc_assert = {
.trig_desc = { .trig_desc = {
...@@ -1910,6 +1907,17 @@ int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt, ...@@ -1910,6 +1907,17 @@ int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt,
bool monitor_only, bool monitor_only,
unsigned int delay) unsigned int delay)
{ {
u32 trig_type = le32_to_cpu(desc->trig_desc.type);
int ret;
if (fwrt->trans->ini_valid) {
ret = iwl_fw_dbg_ini_collect(fwrt, trig_type);
if (!ret)
iwl_fw_free_dump_desc(fwrt);
return ret;
}
if (test_and_set_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status)) if (test_and_set_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status))
return -EBUSY; return -EBUSY;
...@@ -1955,10 +1963,10 @@ int iwl_fw_dbg_error_collect(struct iwl_fw_runtime *fwrt, ...@@ -1955,10 +1963,10 @@ int iwl_fw_dbg_error_collect(struct iwl_fw_runtime *fwrt,
} }
IWL_EXPORT_SYMBOL(iwl_fw_dbg_error_collect); IWL_EXPORT_SYMBOL(iwl_fw_dbg_error_collect);
int _iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt, int iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt,
enum iwl_fw_dbg_trigger trig, enum iwl_fw_dbg_trigger trig,
const char *str, size_t len, const char *str, size_t len,
struct iwl_fw_dbg_trigger_tlv *trigger) struct iwl_fw_dbg_trigger_tlv *trigger)
{ {
struct iwl_fw_dump_desc *desc; struct iwl_fw_dump_desc *desc;
unsigned int delay = 0; unsigned int delay = 0;
...@@ -1995,50 +2003,64 @@ int _iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt, ...@@ -1995,50 +2003,64 @@ int _iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt,
return iwl_fw_dbg_collect_desc(fwrt, desc, monitor_only, delay); return iwl_fw_dbg_collect_desc(fwrt, desc, monitor_only, delay);
} }
IWL_EXPORT_SYMBOL(_iwl_fw_dbg_collect); IWL_EXPORT_SYMBOL(iwl_fw_dbg_collect);
int iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt, int _iwl_fw_dbg_ini_collect(struct iwl_fw_runtime *fwrt,
u32 id, const char *str, size_t len) enum iwl_fw_ini_trigger_id id)
{ {
struct iwl_fw_dump_desc *desc;
struct iwl_fw_ini_active_triggers *active; struct iwl_fw_ini_active_triggers *active;
u32 occur, delay; u32 occur, delay;
if (!fwrt->trans->ini_valid) if (WARN_ON(!iwl_fw_ini_trigger_on(fwrt, id)))
return _iwl_fw_dbg_collect(fwrt, id, str, len, NULL); return -EINVAL;
if (id == FW_DBG_TRIGGER_USER) if (test_and_set_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status))
id = IWL_FW_TRIGGER_ID_USER_TRIGGER; return -EBUSY;
active = &fwrt->dump.active_trigs[id]; active = &fwrt->dump.active_trigs[id];
if (WARN_ON(!active->active))
return -EINVAL;
delay = le32_to_cpu(active->trig->dump_delay); delay = le32_to_cpu(active->trig->dump_delay);
occur = le32_to_cpu(active->trig->occurrences); occur = le32_to_cpu(active->trig->occurrences);
if (!occur) if (!occur)
return 0; return 0;
active->trig->occurrences = cpu_to_le32(--occur);
if (le32_to_cpu(active->trig->force_restart)) { if (le32_to_cpu(active->trig->force_restart)) {
IWL_WARN(fwrt, "Force restart: trigger %d fired.\n", id); IWL_WARN(fwrt, "Force restart: trigger %d fired.\n", id);
iwl_force_nmi(fwrt->trans); iwl_force_nmi(fwrt->trans);
return 0; return 0;
} }
desc = kzalloc(sizeof(*desc) + len, GFP_ATOMIC); fwrt->dump.ini_trig_id = id;
if (!desc)
return -ENOMEM;
active->trig->occurrences = cpu_to_le32(--occur); IWL_WARN(fwrt, "Collecting data: ini trigger %d fired.\n", id);
desc->len = len; schedule_delayed_work(&fwrt->dump.wk, usecs_to_jiffies(delay));
desc->trig_desc.type = cpu_to_le32(id);
memcpy(desc->trig_desc.data, str, len);
return iwl_fw_dbg_collect_desc(fwrt, desc, true, delay); return 0;
} }
IWL_EXPORT_SYMBOL(iwl_fw_dbg_collect); IWL_EXPORT_SYMBOL(_iwl_fw_dbg_ini_collect);
int iwl_fw_dbg_ini_collect(struct iwl_fw_runtime *fwrt, u32 legacy_trigger_id)
{
int id;
switch (legacy_trigger_id) {
case FW_DBG_TRIGGER_FW_ASSERT:
case FW_DBG_TRIGGER_ALIVE_TIMEOUT:
case FW_DBG_TRIGGER_DRIVER:
id = IWL_FW_TRIGGER_ID_FW_ASSERT;
break;
case FW_DBG_TRIGGER_USER:
id = IWL_FW_TRIGGER_ID_USER_TRIGGER;
break;
default:
return -EIO;
}
return _iwl_fw_dbg_ini_collect(fwrt, id);
}
IWL_EXPORT_SYMBOL(iwl_fw_dbg_ini_collect);
int iwl_fw_dbg_collect_trig(struct iwl_fw_runtime *fwrt, int iwl_fw_dbg_collect_trig(struct iwl_fw_runtime *fwrt,
struct iwl_fw_dbg_trigger_tlv *trigger, struct iwl_fw_dbg_trigger_tlv *trigger,
...@@ -2066,8 +2088,8 @@ int iwl_fw_dbg_collect_trig(struct iwl_fw_runtime *fwrt, ...@@ -2066,8 +2088,8 @@ int iwl_fw_dbg_collect_trig(struct iwl_fw_runtime *fwrt,
len = strlen(buf) + 1; len = strlen(buf) + 1;
} }
ret = _iwl_fw_dbg_collect(fwrt, le32_to_cpu(trigger->id), buf, len, ret = iwl_fw_dbg_collect(fwrt, le32_to_cpu(trigger->id), buf, len,
trigger); trigger);
if (ret) if (ret)
return ret; return ret;
...@@ -2141,9 +2163,20 @@ void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt) ...@@ -2141,9 +2163,20 @@ void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt)
return; return;
} }
/* there's no point in fw dump if the bus is dead */
if (test_bit(STATUS_TRANS_DEAD, &fwrt->trans->status)) {
IWL_ERR(fwrt, "Skip fw error dump since bus is dead\n");
return;
}
iwl_fw_dbg_stop_recording(fwrt, &params); iwl_fw_dbg_stop_recording(fwrt, &params);
iwl_fw_error_dump(fwrt); IWL_DEBUG_INFO(fwrt, "WRT dump start\n");
if (fwrt->trans->ini_valid)
iwl_fw_error_ini_dump(fwrt);
else
iwl_fw_error_dump(fwrt);
IWL_DEBUG_INFO(fwrt, "WRT dump done\n");
/* start recording again if the firmware is not crashed */ /* start recording again if the firmware is not crashed */
if (!test_bit(STATUS_FW_ERROR, &fwrt->trans->status) && if (!test_bit(STATUS_FW_ERROR, &fwrt->trans->status) &&
......
...@@ -108,18 +108,17 @@ static inline void iwl_fw_free_dump_desc(struct iwl_fw_runtime *fwrt) ...@@ -108,18 +108,17 @@ static inline void iwl_fw_free_dump_desc(struct iwl_fw_runtime *fwrt)
fwrt->dump.umac_err_id = 0; fwrt->dump.umac_err_id = 0;
} }
void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt);
int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt, int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt,
const struct iwl_fw_dump_desc *desc, const struct iwl_fw_dump_desc *desc,
bool monitor_only, unsigned int delay); bool monitor_only, unsigned int delay);
int iwl_fw_dbg_error_collect(struct iwl_fw_runtime *fwrt, int iwl_fw_dbg_error_collect(struct iwl_fw_runtime *fwrt,
enum iwl_fw_dbg_trigger trig_type); enum iwl_fw_dbg_trigger trig_type);
int _iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt, int _iwl_fw_dbg_ini_collect(struct iwl_fw_runtime *fwrt,
enum iwl_fw_dbg_trigger trig, enum iwl_fw_ini_trigger_id id);
const char *str, size_t len, int iwl_fw_dbg_ini_collect(struct iwl_fw_runtime *fwrt, u32 legacy_trigger_id);
struct iwl_fw_dbg_trigger_tlv *trigger);
int iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt, int iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt,
u32 id, const char *str, size_t len); enum iwl_fw_dbg_trigger trig, const char *str,
size_t len, struct iwl_fw_dbg_trigger_tlv *trigger);
int iwl_fw_dbg_collect_trig(struct iwl_fw_runtime *fwrt, int iwl_fw_dbg_collect_trig(struct iwl_fw_runtime *fwrt,
struct iwl_fw_dbg_trigger_tlv *trigger, struct iwl_fw_dbg_trigger_tlv *trigger,
const char *fmt, ...) __printf(3, 4); const char *fmt, ...) __printf(3, 4);
...@@ -229,10 +228,8 @@ iwl_fw_ini_trigger_on(struct iwl_fw_runtime *fwrt, ...@@ -229,10 +228,8 @@ iwl_fw_ini_trigger_on(struct iwl_fw_runtime *fwrt,
struct iwl_fw_ini_trigger *trig; struct iwl_fw_ini_trigger *trig;
u32 usec; u32 usec;
if (!fwrt->trans->ini_valid || id == IWL_FW_TRIGGER_ID_INVALID ||
id >= IWL_FW_TRIGGER_ID_NUM || !fwrt->dump.active_trigs[id].active)
if (!fwrt->trans->ini_valid || id >= IWL_FW_TRIGGER_ID_NUM ||
!fwrt->dump.active_trigs[id].active)
return false; return false;
trig = fwrt->dump.active_trigs[id].trig; trig = fwrt->dump.active_trigs[id].trig;
......
...@@ -211,6 +211,9 @@ struct iwl_fw_error_dump_info { ...@@ -211,6 +211,9 @@ struct iwl_fw_error_dump_info {
* @fw_mon_wr_ptr: the position of the write pointer in the cyclic buffer * @fw_mon_wr_ptr: the position of the write pointer in the cyclic buffer
* @fw_mon_base_ptr: base pointer of the data * @fw_mon_base_ptr: base pointer of the data
* @fw_mon_cycle_cnt: number of wraparounds * @fw_mon_cycle_cnt: number of wraparounds
* @fw_mon_base_high_ptr: used in AX210 devices, the base adderss is 64 bit
* so fw_mon_base_ptr holds LSB 32 bits and fw_mon_base_high_ptr hold
* MSB 32 bits
* @reserved: for future use * @reserved: for future use
* @data: captured data * @data: captured data
*/ */
...@@ -218,7 +221,8 @@ struct iwl_fw_error_dump_fw_mon { ...@@ -218,7 +221,8 @@ struct iwl_fw_error_dump_fw_mon {
__le32 fw_mon_wr_ptr; __le32 fw_mon_wr_ptr;
__le32 fw_mon_base_ptr; __le32 fw_mon_base_ptr;
__le32 fw_mon_cycle_cnt; __le32 fw_mon_cycle_cnt;
__le32 reserved[3]; __le32 fw_mon_base_high_ptr;
__le32 reserved[2];
u8 data[]; u8 data[];
} __packed; } __packed;
......
...@@ -272,8 +272,13 @@ typedef unsigned int __bitwise iwl_ucode_tlv_api_t; ...@@ -272,8 +272,13 @@ typedef unsigned int __bitwise iwl_ucode_tlv_api_t;
* version of the beacon notification. * version of the beacon notification.
* @IWL_UCODE_TLV_API_BEACON_FILTER_V4: This ucode supports v4 of * @IWL_UCODE_TLV_API_BEACON_FILTER_V4: This ucode supports v4 of
* BEACON_FILTER_CONFIG_API_S_VER_4. * BEACON_FILTER_CONFIG_API_S_VER_4.
* @IWL_UCODE_TLV_API_REGULATORY_NVM_INFO: This ucode supports v4 of
* REGULATORY_NVM_GET_INFO_RSP_API_S.
* @IWL_UCODE_TLV_API_FTM_NEW_RANGE_REQ: This ucode supports v7 of * @IWL_UCODE_TLV_API_FTM_NEW_RANGE_REQ: This ucode supports v7 of
* LOCATION_RANGE_REQ_CMD_API_S and v6 of LOCATION_RANGE_RESP_NTFY_API_S. * LOCATION_RANGE_REQ_CMD_API_S and v6 of LOCATION_RANGE_RESP_NTFY_API_S.
* @IWL_UCODE_TLV_API_SCAN_OFFLOAD_CHANS: This ucode supports v2 of
* SCAN_OFFLOAD_PROFILE_MATCH_RESULTS_S and v3 of
* SCAN_OFFLOAD_PROFILES_QUERY_RSP_S.
* *
* @NUM_IWL_UCODE_TLV_API: number of bits used * @NUM_IWL_UCODE_TLV_API: number of bits used
*/ */
...@@ -300,7 +305,9 @@ enum iwl_ucode_tlv_api { ...@@ -300,7 +305,9 @@ enum iwl_ucode_tlv_api {
IWL_UCODE_TLV_API_REDUCE_TX_POWER = (__force iwl_ucode_tlv_api_t)45, IWL_UCODE_TLV_API_REDUCE_TX_POWER = (__force iwl_ucode_tlv_api_t)45,
IWL_UCODE_TLV_API_SHORT_BEACON_NOTIF = (__force iwl_ucode_tlv_api_t)46, IWL_UCODE_TLV_API_SHORT_BEACON_NOTIF = (__force iwl_ucode_tlv_api_t)46,
IWL_UCODE_TLV_API_BEACON_FILTER_V4 = (__force iwl_ucode_tlv_api_t)47, IWL_UCODE_TLV_API_BEACON_FILTER_V4 = (__force iwl_ucode_tlv_api_t)47,
IWL_UCODE_TLV_API_REGULATORY_NVM_INFO = (__force iwl_ucode_tlv_api_t)48,
IWL_UCODE_TLV_API_FTM_NEW_RANGE_REQ = (__force iwl_ucode_tlv_api_t)49, IWL_UCODE_TLV_API_FTM_NEW_RANGE_REQ = (__force iwl_ucode_tlv_api_t)49,
IWL_UCODE_TLV_API_SCAN_OFFLOAD_CHANS = (__force iwl_ucode_tlv_api_t)50,
NUM_IWL_UCODE_TLV_API NUM_IWL_UCODE_TLV_API
#ifdef __CHECKER__ #ifdef __CHECKER__
...@@ -350,6 +357,7 @@ typedef unsigned int __bitwise iwl_ucode_tlv_capa_t; ...@@ -350,6 +357,7 @@ typedef unsigned int __bitwise iwl_ucode_tlv_capa_t;
* IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD: firmware supports CSA command * IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD: firmware supports CSA command
* @IWL_UCODE_TLV_CAPA_ULTRA_HB_CHANNELS: firmware supports ultra high band * @IWL_UCODE_TLV_CAPA_ULTRA_HB_CHANNELS: firmware supports ultra high band
* (6 GHz). * (6 GHz).
* @IWL_UCODE_TLV_CAPA_CS_MODIFY: firmware supports modify action CSA command
* @IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE: extended DTS measurement * @IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE: extended DTS measurement
* @IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS: supports short PM timeouts * @IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS: supports short PM timeouts
* @IWL_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT: supports bt-coex Multi-priority LUT * @IWL_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT: supports bt-coex Multi-priority LUT
...@@ -420,6 +428,7 @@ enum iwl_ucode_tlv_capa { ...@@ -420,6 +428,7 @@ enum iwl_ucode_tlv_capa {
IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD = (__force iwl_ucode_tlv_capa_t)46, IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD = (__force iwl_ucode_tlv_capa_t)46,
IWL_UCODE_TLV_CAPA_ULTRA_HB_CHANNELS = (__force iwl_ucode_tlv_capa_t)48, IWL_UCODE_TLV_CAPA_ULTRA_HB_CHANNELS = (__force iwl_ucode_tlv_capa_t)48,
IWL_UCODE_TLV_CAPA_FTM_CALIBRATED = (__force iwl_ucode_tlv_capa_t)47, IWL_UCODE_TLV_CAPA_FTM_CALIBRATED = (__force iwl_ucode_tlv_capa_t)47,
IWL_UCODE_TLV_CAPA_CS_MODIFY = (__force iwl_ucode_tlv_capa_t)49,
/* set 2 */ /* set 2 */
IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE = (__force iwl_ucode_tlv_capa_t)64, IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE = (__force iwl_ucode_tlv_capa_t)64,
......
...@@ -145,6 +145,7 @@ struct iwl_fw_runtime { ...@@ -145,6 +145,7 @@ struct iwl_fw_runtime {
u32 lmac_err_id[MAX_NUM_LMAC]; u32 lmac_err_id[MAX_NUM_LMAC];
u32 umac_err_id; u32 umac_err_id;
void *fifo_iter; void *fifo_iter;
enum iwl_fw_ini_trigger_id ini_trig_id;
} dump; } dump;
#ifdef CONFIG_IWLWIFI_DEBUGFS #ifdef CONFIG_IWLWIFI_DEBUGFS
struct { struct {
......
...@@ -383,6 +383,7 @@ struct iwl_csr_params { ...@@ -383,6 +383,7 @@ struct iwl_csr_params {
* @bisr_workaround: BISR hardware workaround (for 22260 series devices) * @bisr_workaround: BISR hardware workaround (for 22260 series devices)
* @min_txq_size: minimum number of slots required in a TX queue * @min_txq_size: minimum number of slots required in a TX queue
* @umac_prph_offset: offset to add to UMAC periphery address * @umac_prph_offset: offset to add to UMAC periphery address
* @uhb_supported: ultra high band channels supported
* *
* We enable the driver to be backward compatible wrt. hardware features. * We enable the driver to be backward compatible wrt. hardware features.
* API differences in uCode shouldn't be handled here but through TLVs * API differences in uCode shouldn't be handled here but through TLVs
...@@ -433,7 +434,8 @@ struct iwl_cfg { ...@@ -433,7 +434,8 @@ struct iwl_cfg {
gen2:1, gen2:1,
cdb:1, cdb:1,
dbgc_supported:1, dbgc_supported:1,
bisr_workaround:1; bisr_workaround:1,
uhb_supported:1;
u8 valid_tx_ant; u8 valid_tx_ant;
u8 valid_rx_ant; u8 valid_rx_ant;
u8 non_shared_ant; u8 non_shared_ant;
...@@ -572,6 +574,7 @@ extern const struct iwl_cfg iwlax210_2ax_cfg_so_jf_a0; ...@@ -572,6 +574,7 @@ extern const struct iwl_cfg iwlax210_2ax_cfg_so_jf_a0;
extern const struct iwl_cfg iwlax210_2ax_cfg_so_hr_a0; extern const struct iwl_cfg iwlax210_2ax_cfg_so_hr_a0;
extern const struct iwl_cfg iwlax210_2ax_cfg_so_gf_a0; extern const struct iwl_cfg iwlax210_2ax_cfg_so_gf_a0;
extern const struct iwl_cfg iwlax210_2ax_cfg_ty_gf_a0; extern const struct iwl_cfg iwlax210_2ax_cfg_ty_gf_a0;
extern const struct iwl_cfg iwlax210_2ax_cfg_so_gf4_a0;
#endif /* CPTCFG_IWLMVM || CPTCFG_IWLFMAC */ #endif /* CPTCFG_IWLMVM || CPTCFG_IWLFMAC */
#endif /* __IWL_CONFIG_H__ */ #endif /* __IWL_CONFIG_H__ */
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2016 Intel Deutschland GmbH * Copyright(c) 2016 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation * Copyright(c) 2018 - 2019 Intel Corporation
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
* *
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2018 Intel Corporation * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
...@@ -336,6 +336,7 @@ enum { ...@@ -336,6 +336,7 @@ enum {
#define CSR_HW_RF_ID_TYPE_HR (0x0010A000) #define CSR_HW_RF_ID_TYPE_HR (0x0010A000)
#define CSR_HW_RF_ID_TYPE_HRCDB (0x00109F00) #define CSR_HW_RF_ID_TYPE_HRCDB (0x00109F00)
#define CSR_HW_RF_ID_TYPE_GF (0x0010D000) #define CSR_HW_RF_ID_TYPE_GF (0x0010D000)
#define CSR_HW_RF_ID_TYPE_GF4 (0x0010E000)
/* HW_RF CHIP ID */ /* HW_RF CHIP ID */
#define CSR_HW_RF_ID_TYPE_CHIP_ID(_val) (((_val) >> 12) & 0xFFF) #define CSR_HW_RF_ID_TYPE_CHIP_ID(_val) (((_val) >> 12) & 0xFFF)
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* *
* GPL LICENSE SUMMARY * GPL LICENSE SUMMARY
* *
* Copyright (C) 2018 Intel Corporation * Copyright (C) 2018 - 2019 Intel Corporation
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
* *
* BSD LICENSE * BSD LICENSE
* *
* Copyright (C) 2018 Intel Corporation * Copyright (C) 2018 - 2019 Intel Corporation
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
...@@ -73,6 +73,9 @@ void iwl_fw_dbg_copy_tlv(struct iwl_trans *trans, struct iwl_ucode_tlv *tlv, ...@@ -73,6 +73,9 @@ void iwl_fw_dbg_copy_tlv(struct iwl_trans *trans, struct iwl_ucode_tlv *tlv,
int copy_size = le32_to_cpu(tlv->length) + sizeof(*tlv); int copy_size = le32_to_cpu(tlv->length) + sizeof(*tlv);
int offset_size = copy_size; int offset_size = copy_size;
if (le32_to_cpu(header->tlv_version) != 1)
return;
if (WARN_ONCE(apply_point >= IWL_FW_INI_APPLY_NUM, if (WARN_ONCE(apply_point >= IWL_FW_INI_APPLY_NUM,
"Invalid apply point id %d\n", apply_point)) "Invalid apply point id %d\n", apply_point))
return; return;
...@@ -132,6 +135,9 @@ void iwl_alloc_dbg_tlv(struct iwl_trans *trans, size_t len, const u8 *data, ...@@ -132,6 +135,9 @@ void iwl_alloc_dbg_tlv(struct iwl_trans *trans, size_t len, const u8 *data,
hdr = (void *)&tlv->data[0]; hdr = (void *)&tlv->data[0];
apply = le32_to_cpu(hdr->apply_point); apply = le32_to_cpu(hdr->apply_point);
if (le32_to_cpu(hdr->tlv_version) != 1)
continue;
IWL_DEBUG_FW(trans, "Read TLV %x, apply point %d\n", IWL_DEBUG_FW(trans, "Read TLV %x, apply point %d\n",
le32_to_cpu(tlv->type), apply); le32_to_cpu(tlv->type), apply);
......
...@@ -130,7 +130,7 @@ enum nvm_sku_bits { ...@@ -130,7 +130,7 @@ enum nvm_sku_bits {
/* /*
* These are the channel numbers in the order that they are stored in the NVM * These are the channel numbers in the order that they are stored in the NVM
*/ */
static const u8 iwl_nvm_channels[] = { static const u16 iwl_nvm_channels[] = {
/* 2.4 GHz */ /* 2.4 GHz */
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
/* 5 GHz */ /* 5 GHz */
...@@ -139,7 +139,7 @@ static const u8 iwl_nvm_channels[] = { ...@@ -139,7 +139,7 @@ static const u8 iwl_nvm_channels[] = {
149, 153, 157, 161, 165 149, 153, 157, 161, 165
}; };
static const u8 iwl_ext_nvm_channels[] = { static const u16 iwl_ext_nvm_channels[] = {
/* 2.4 GHz */ /* 2.4 GHz */
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
/* 5 GHz */ /* 5 GHz */
...@@ -148,14 +148,27 @@ static const u8 iwl_ext_nvm_channels[] = { ...@@ -148,14 +148,27 @@ static const u8 iwl_ext_nvm_channels[] = {
149, 153, 157, 161, 165, 169, 173, 177, 181 149, 153, 157, 161, 165, 169, 173, 177, 181
}; };
static const u16 iwl_uhb_nvm_channels[] = {
/* 2.4 GHz */
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
/* 5 GHz */
36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92,
96, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144,
149, 153, 157, 161, 165, 169, 173, 177, 181,
/* 6-7 GHz */
189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 237, 241,
245, 249, 253, 257, 261, 265, 269, 273, 277, 281, 285, 289, 293, 297,
301, 305, 309, 313, 317, 321, 325, 329, 333, 337, 341, 345, 349, 353,
357, 361, 365, 369, 373, 377, 381, 385, 389, 393, 397, 401, 405, 409,
413, 417, 421
};
#define IWL_NVM_NUM_CHANNELS ARRAY_SIZE(iwl_nvm_channels) #define IWL_NVM_NUM_CHANNELS ARRAY_SIZE(iwl_nvm_channels)
#define IWL_NVM_NUM_CHANNELS_EXT ARRAY_SIZE(iwl_ext_nvm_channels) #define IWL_NVM_NUM_CHANNELS_EXT ARRAY_SIZE(iwl_ext_nvm_channels)
#define IWL_NVM_NUM_CHANNELS_UHB ARRAY_SIZE(iwl_uhb_nvm_channels)
#define NUM_2GHZ_CHANNELS 14 #define NUM_2GHZ_CHANNELS 14
#define NUM_2GHZ_CHANNELS_EXT 14
#define FIRST_2GHZ_HT_MINUS 5 #define FIRST_2GHZ_HT_MINUS 5
#define LAST_2GHZ_HT_PLUS 9 #define LAST_2GHZ_HT_PLUS 9
#define LAST_5GHZ_HT 165
#define LAST_5GHZ_HT_FAMILY_8000 181
#define N_HW_ADDR_MASK 0xF #define N_HW_ADDR_MASK 0xF
/* rate data (static) */ /* rate data (static) */
...@@ -213,7 +226,7 @@ enum iwl_nvm_channel_flags { ...@@ -213,7 +226,7 @@ enum iwl_nvm_channel_flags {
}; };
static inline void iwl_nvm_print_channel_flags(struct device *dev, u32 level, static inline void iwl_nvm_print_channel_flags(struct device *dev, u32 level,
int chan, u16 flags) int chan, u32 flags)
{ {
#define CHECK_AND_PRINT_I(x) \ #define CHECK_AND_PRINT_I(x) \
((flags & NVM_CHANNEL_##x) ? " " #x : "") ((flags & NVM_CHANNEL_##x) ? " " #x : "")
...@@ -244,20 +257,16 @@ static inline void iwl_nvm_print_channel_flags(struct device *dev, u32 level, ...@@ -244,20 +257,16 @@ static inline void iwl_nvm_print_channel_flags(struct device *dev, u32 level,
} }
static u32 iwl_get_channel_flags(u8 ch_num, int ch_idx, bool is_5ghz, static u32 iwl_get_channel_flags(u8 ch_num, int ch_idx, bool is_5ghz,
u16 nvm_flags, const struct iwl_cfg *cfg) u32 nvm_flags, const struct iwl_cfg *cfg)
{ {
u32 flags = IEEE80211_CHAN_NO_HT40; u32 flags = IEEE80211_CHAN_NO_HT40;
u32 last_5ghz_ht = LAST_5GHZ_HT;
if (cfg->nvm_type == IWL_NVM_EXT)
last_5ghz_ht = LAST_5GHZ_HT_FAMILY_8000;
if (!is_5ghz && (nvm_flags & NVM_CHANNEL_40MHZ)) { if (!is_5ghz && (nvm_flags & NVM_CHANNEL_40MHZ)) {
if (ch_num <= LAST_2GHZ_HT_PLUS) if (ch_num <= LAST_2GHZ_HT_PLUS)
flags &= ~IEEE80211_CHAN_NO_HT40PLUS; flags &= ~IEEE80211_CHAN_NO_HT40PLUS;
if (ch_num >= FIRST_2GHZ_HT_MINUS) if (ch_num >= FIRST_2GHZ_HT_MINUS)
flags &= ~IEEE80211_CHAN_NO_HT40MINUS; flags &= ~IEEE80211_CHAN_NO_HT40MINUS;
} else if (ch_num <= last_5ghz_ht && (nvm_flags & NVM_CHANNEL_40MHZ)) { } else if (nvm_flags & NVM_CHANNEL_40MHZ) {
if ((ch_idx - NUM_2GHZ_CHANNELS) % 2 == 0) if ((ch_idx - NUM_2GHZ_CHANNELS) % 2 == 0)
flags &= ~IEEE80211_CHAN_NO_HT40PLUS; flags &= ~IEEE80211_CHAN_NO_HT40PLUS;
else else
...@@ -292,30 +301,36 @@ static u32 iwl_get_channel_flags(u8 ch_num, int ch_idx, bool is_5ghz, ...@@ -292,30 +301,36 @@ static u32 iwl_get_channel_flags(u8 ch_num, int ch_idx, bool is_5ghz,
static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
struct iwl_nvm_data *data, struct iwl_nvm_data *data,
const __le16 * const nvm_ch_flags, const void * const nvm_ch_flags,
u32 sbands_flags) u32 sbands_flags, bool v4)
{ {
int ch_idx; int ch_idx;
int n_channels = 0; int n_channels = 0;
struct ieee80211_channel *channel; struct ieee80211_channel *channel;
u16 ch_flags; u32 ch_flags;
int num_of_ch, num_2ghz_channels; int num_of_ch, num_2ghz_channels = NUM_2GHZ_CHANNELS;
const u8 *nvm_chan; const u16 *nvm_chan;
if (cfg->nvm_type != IWL_NVM_EXT) { if (cfg->uhb_supported) {
num_of_ch = IWL_NVM_NUM_CHANNELS; num_of_ch = IWL_NVM_NUM_CHANNELS_UHB;
nvm_chan = &iwl_nvm_channels[0]; nvm_chan = iwl_uhb_nvm_channels;
num_2ghz_channels = NUM_2GHZ_CHANNELS; } else if (cfg->nvm_type == IWL_NVM_EXT) {
} else {
num_of_ch = IWL_NVM_NUM_CHANNELS_EXT; num_of_ch = IWL_NVM_NUM_CHANNELS_EXT;
nvm_chan = &iwl_ext_nvm_channels[0]; nvm_chan = iwl_ext_nvm_channels;
num_2ghz_channels = NUM_2GHZ_CHANNELS_EXT; } else {
num_of_ch = IWL_NVM_NUM_CHANNELS;
nvm_chan = iwl_nvm_channels;
} }
for (ch_idx = 0; ch_idx < num_of_ch; ch_idx++) { for (ch_idx = 0; ch_idx < num_of_ch; ch_idx++) {
bool is_5ghz = (ch_idx >= num_2ghz_channels); bool is_5ghz = (ch_idx >= num_2ghz_channels);
ch_flags = __le16_to_cpup(nvm_ch_flags + ch_idx); if (v4)
ch_flags =
__le32_to_cpup((__le32 *)nvm_ch_flags + ch_idx);
else
ch_flags =
__le16_to_cpup((__le16 *)nvm_ch_flags + ch_idx);
if (is_5ghz && !data->sku_cap_band_52ghz_enable) if (is_5ghz && !data->sku_cap_band_52ghz_enable)
continue; continue;
...@@ -661,15 +676,15 @@ static void iwl_init_he_hw_capab(struct ieee80211_supported_band *sband, ...@@ -661,15 +676,15 @@ static void iwl_init_he_hw_capab(struct ieee80211_supported_band *sband,
static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg,
struct iwl_nvm_data *data, struct iwl_nvm_data *data,
const __le16 *nvm_ch_flags, u8 tx_chains, const void *nvm_ch_flags, u8 tx_chains,
u8 rx_chains, u32 sbands_flags) u8 rx_chains, u32 sbands_flags, bool v4)
{ {
int n_channels; int n_channels;
int n_used = 0; int n_used = 0;
struct ieee80211_supported_band *sband; struct ieee80211_supported_band *sband;
n_channels = iwl_init_channel_map(dev, cfg, data, nvm_ch_flags, n_channels = iwl_init_channel_map(dev, cfg, data, nvm_ch_flags,
sbands_flags); sbands_flags, v4);
sband = &data->bands[NL80211_BAND_2GHZ]; sband = &data->bands[NL80211_BAND_2GHZ];
sband->band = NL80211_BAND_2GHZ; sband->band = NL80211_BAND_2GHZ;
sband->bitrates = &iwl_cfg80211_rates[RATES_24_OFFS]; sband->bitrates = &iwl_cfg80211_rates[RATES_24_OFFS];
...@@ -1006,22 +1021,18 @@ iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg, ...@@ -1006,22 +1021,18 @@ iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
sbands_flags |= IWL_NVM_SBANDS_FLAGS_NO_WIDE_IN_5GHZ; sbands_flags |= IWL_NVM_SBANDS_FLAGS_NO_WIDE_IN_5GHZ;
iwl_init_sbands(dev, cfg, data, ch_section, tx_chains, rx_chains, iwl_init_sbands(dev, cfg, data, ch_section, tx_chains, rx_chains,
sbands_flags); sbands_flags, false);
data->calib_version = 255; data->calib_version = 255;
return data; return data;
} }
IWL_EXPORT_SYMBOL(iwl_parse_nvm_data); IWL_EXPORT_SYMBOL(iwl_parse_nvm_data);
static u32 iwl_nvm_get_regdom_bw_flags(const u8 *nvm_chan, static u32 iwl_nvm_get_regdom_bw_flags(const u16 *nvm_chan,
int ch_idx, u16 nvm_flags, int ch_idx, u16 nvm_flags,
const struct iwl_cfg *cfg) const struct iwl_cfg *cfg)
{ {
u32 flags = NL80211_RRF_NO_HT40; u32 flags = NL80211_RRF_NO_HT40;
u32 last_5ghz_ht = LAST_5GHZ_HT;
if (cfg->nvm_type == IWL_NVM_EXT)
last_5ghz_ht = LAST_5GHZ_HT_FAMILY_8000;
if (ch_idx < NUM_2GHZ_CHANNELS && if (ch_idx < NUM_2GHZ_CHANNELS &&
(nvm_flags & NVM_CHANNEL_40MHZ)) { (nvm_flags & NVM_CHANNEL_40MHZ)) {
...@@ -1029,8 +1040,7 @@ static u32 iwl_nvm_get_regdom_bw_flags(const u8 *nvm_chan, ...@@ -1029,8 +1040,7 @@ static u32 iwl_nvm_get_regdom_bw_flags(const u8 *nvm_chan,
flags &= ~NL80211_RRF_NO_HT40PLUS; flags &= ~NL80211_RRF_NO_HT40PLUS;
if (nvm_chan[ch_idx] >= FIRST_2GHZ_HT_MINUS) if (nvm_chan[ch_idx] >= FIRST_2GHZ_HT_MINUS)
flags &= ~NL80211_RRF_NO_HT40MINUS; flags &= ~NL80211_RRF_NO_HT40MINUS;
} else if (nvm_chan[ch_idx] <= last_5ghz_ht && } else if (nvm_flags & NVM_CHANNEL_40MHZ) {
(nvm_flags & NVM_CHANNEL_40MHZ)) {
if ((ch_idx - NUM_2GHZ_CHANNELS) % 2 == 0) if ((ch_idx - NUM_2GHZ_CHANNELS) % 2 == 0)
flags &= ~NL80211_RRF_NO_HT40PLUS; flags &= ~NL80211_RRF_NO_HT40PLUS;
else else
...@@ -1074,18 +1084,26 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg, ...@@ -1074,18 +1084,26 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
int ch_idx; int ch_idx;
u16 ch_flags; u16 ch_flags;
u32 reg_rule_flags, prev_reg_rule_flags = 0; u32 reg_rule_flags, prev_reg_rule_flags = 0;
const u8 *nvm_chan = cfg->nvm_type == IWL_NVM_EXT ? const u16 *nvm_chan;
iwl_ext_nvm_channels : iwl_nvm_channels;
struct ieee80211_regdomain *regd, *copy_rd; struct ieee80211_regdomain *regd, *copy_rd;
int size_of_regd, regd_to_copy;
struct ieee80211_reg_rule *rule; struct ieee80211_reg_rule *rule;
struct regdb_ptrs *regdb_ptrs; struct regdb_ptrs *regdb_ptrs;
enum nl80211_band band; enum nl80211_band band;
int center_freq, prev_center_freq = 0; int center_freq, prev_center_freq = 0;
int valid_rules = 0; int valid_rules = 0;
bool new_rule; bool new_rule;
int max_num_ch = cfg->nvm_type == IWL_NVM_EXT ? int max_num_ch;
IWL_NVM_NUM_CHANNELS_EXT : IWL_NVM_NUM_CHANNELS;
if (cfg->uhb_supported) {
max_num_ch = IWL_NVM_NUM_CHANNELS_UHB;
nvm_chan = iwl_uhb_nvm_channels;
} else if (cfg->nvm_type == IWL_NVM_EXT) {
max_num_ch = IWL_NVM_NUM_CHANNELS_EXT;
nvm_chan = iwl_ext_nvm_channels;
} else {
max_num_ch = IWL_NVM_NUM_CHANNELS;
nvm_chan = iwl_nvm_channels;
}
if (WARN_ON(num_of_ch > max_num_ch)) if (WARN_ON(num_of_ch > max_num_ch))
num_of_ch = max_num_ch; num_of_ch = max_num_ch;
...@@ -1097,11 +1115,7 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg, ...@@ -1097,11 +1115,7 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
num_of_ch); num_of_ch);
/* build a regdomain rule for every valid channel */ /* build a regdomain rule for every valid channel */
size_of_regd = regd = kzalloc(struct_size(regd, reg_rules, num_of_ch), GFP_KERNEL);
sizeof(struct ieee80211_regdomain) +
num_of_ch * sizeof(struct ieee80211_reg_rule);
regd = kzalloc(size_of_regd, GFP_KERNEL);
if (!regd) if (!regd)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
...@@ -1177,14 +1191,10 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg, ...@@ -1177,14 +1191,10 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
* Narrow down regdom for unused regulatory rules to prevent hole * Narrow down regdom for unused regulatory rules to prevent hole
* between reg rules to wmm rules. * between reg rules to wmm rules.
*/ */
regd_to_copy = sizeof(struct ieee80211_regdomain) + copy_rd = kmemdup(regd, struct_size(regd, reg_rules, valid_rules),
valid_rules * sizeof(struct ieee80211_reg_rule); GFP_KERNEL);
if (!copy_rd)
copy_rd = kmemdup(regd, regd_to_copy, GFP_KERNEL);
if (!copy_rd) {
copy_rd = ERR_PTR(-ENOMEM); copy_rd = ERR_PTR(-ENOMEM);
goto out;
}
out: out:
kfree(regdb_ptrs); kfree(regdb_ptrs);
...@@ -1393,7 +1403,6 @@ struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans, ...@@ -1393,7 +1403,6 @@ struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans,
const struct iwl_fw *fw) const struct iwl_fw *fw)
{ {
struct iwl_nvm_get_info cmd = {}; struct iwl_nvm_get_info cmd = {};
struct iwl_nvm_get_info_rsp *rsp;
struct iwl_nvm_data *nvm; struct iwl_nvm_data *nvm;
struct iwl_host_cmd hcmd = { struct iwl_host_cmd hcmd = {
.flags = CMD_WANT_SKB | CMD_SEND_IN_RFKILL, .flags = CMD_WANT_SKB | CMD_SEND_IN_RFKILL,
...@@ -1408,12 +1417,24 @@ struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans, ...@@ -1408,12 +1417,24 @@ struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans,
bool empty_otp; bool empty_otp;
u32 mac_flags; u32 mac_flags;
u32 sbands_flags = 0; u32 sbands_flags = 0;
/*
* All the values in iwl_nvm_get_info_rsp v4 are the same as
* in v3, except for the channel profile part of the
* regulatory. So we can just access the new struct, with the
* exception of the latter.
*/
struct iwl_nvm_get_info_rsp *rsp;
struct iwl_nvm_get_info_rsp_v3 *rsp_v3;
bool v4 = fw_has_api(&fw->ucode_capa,
IWL_UCODE_TLV_API_REGULATORY_NVM_INFO);
size_t rsp_size = v4 ? sizeof(*rsp) : sizeof(*rsp_v3);
void *channel_profile;
ret = iwl_trans_send_cmd(trans, &hcmd); ret = iwl_trans_send_cmd(trans, &hcmd);
if (ret) if (ret)
return ERR_PTR(ret); return ERR_PTR(ret);
if (WARN(iwl_rx_packet_payload_len(hcmd.resp_pkt) != sizeof(*rsp), if (WARN(iwl_rx_packet_payload_len(hcmd.resp_pkt) != rsp_size,
"Invalid payload len in NVM response from FW %d", "Invalid payload len in NVM response from FW %d",
iwl_rx_packet_payload_len(hcmd.resp_pkt))) { iwl_rx_packet_payload_len(hcmd.resp_pkt))) {
ret = -EINVAL; ret = -EINVAL;
...@@ -1475,11 +1496,15 @@ struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans, ...@@ -1475,11 +1496,15 @@ struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans,
sbands_flags |= IWL_NVM_SBANDS_FLAGS_LAR; sbands_flags |= IWL_NVM_SBANDS_FLAGS_LAR;
} }
rsp_v3 = (void *)rsp;
channel_profile = v4 ? (void *)rsp->regulatory.channel_profile :
(void *)rsp_v3->regulatory.channel_profile;
iwl_init_sbands(trans->dev, trans->cfg, nvm, iwl_init_sbands(trans->dev, trans->cfg, nvm,
rsp->regulatory.channel_profile, rsp->regulatory.channel_profile,
nvm->valid_tx_ant & fw->valid_tx_ant, nvm->valid_tx_ant & fw->valid_tx_ant,
nvm->valid_rx_ant & fw->valid_rx_ant, nvm->valid_rx_ant & fw->valid_rx_ant,
sbands_flags); sbands_flags, v4);
iwl_free_resp(&hcmd); iwl_free_resp(&hcmd);
return nvm; return nvm;
......
...@@ -368,6 +368,12 @@ ...@@ -368,6 +368,12 @@
#define MON_BUFF_WRPTR_VER2 (0xa03c24) #define MON_BUFF_WRPTR_VER2 (0xa03c24)
#define MON_BUFF_CYCLE_CNT_VER2 (0xa03c28) #define MON_BUFF_CYCLE_CNT_VER2 (0xa03c28)
#define MON_BUFF_SHIFT_VER2 (0x8) #define MON_BUFF_SHIFT_VER2 (0x8)
/* FW monitor familiy AX210 and on */
#define DBGC_CUR_DBGBUF_BASE_ADDR_LSB (0xd03c20)
#define DBGC_CUR_DBGBUF_BASE_ADDR_MSB (0xd03c24)
#define DBGC_CUR_DBGBUF_STATUS (0xd03c1c)
#define DBGC_DBGBUF_WRAP_AROUND (0xd03c2c)
#define DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK (0x00ffffff)
#define MON_DMARB_RD_CTL_ADDR (0xa03c60) #define MON_DMARB_RD_CTL_ADDR (0xa03c60)
#define MON_DMARB_RD_DATA_ADDR (0xa03c5c) #define MON_DMARB_RD_DATA_ADDR (0xa03c5c)
......
...@@ -274,7 +274,6 @@ struct iwl_rx_cmd_buffer { ...@@ -274,7 +274,6 @@ struct iwl_rx_cmd_buffer {
bool _page_stolen; bool _page_stolen;
u32 _rx_page_order; u32 _rx_page_order;
unsigned int truesize; unsigned int truesize;
u8 status;
}; };
static inline void *rxb_addr(struct iwl_rx_cmd_buffer *r) static inline void *rxb_addr(struct iwl_rx_cmd_buffer *r)
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation * Copyright(c) 2018 - 2019 Intel Corporation
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
...@@ -1728,9 +1728,12 @@ void iwl_mvm_d0i3_update_keys(struct iwl_mvm *mvm, ...@@ -1728,9 +1728,12 @@ void iwl_mvm_d0i3_update_keys(struct iwl_mvm *mvm,
iwl_mvm_iter_d0i3_ap_keys(mvm, vif, iwl_mvm_d3_update_keys, &gtkdata); iwl_mvm_iter_d0i3_ap_keys(mvm, vif, iwl_mvm_d3_update_keys, &gtkdata);
} }
#define ND_QUERY_BUF_LEN (sizeof(struct iwl_scan_offload_profile_match) * \
IWL_SCAN_MAX_PROFILES)
struct iwl_mvm_nd_query_results { struct iwl_mvm_nd_query_results {
u32 matched_profiles; u32 matched_profiles;
struct iwl_scan_offload_profile_match matches[IWL_SCAN_MAX_PROFILES]; u8 matches[ND_QUERY_BUF_LEN];
}; };
static int static int
...@@ -1743,6 +1746,7 @@ iwl_mvm_netdetect_query_results(struct iwl_mvm *mvm, ...@@ -1743,6 +1746,7 @@ iwl_mvm_netdetect_query_results(struct iwl_mvm *mvm,
.flags = CMD_WANT_SKB, .flags = CMD_WANT_SKB,
}; };
int ret, len; int ret, len;
size_t query_len, matches_len;
ret = iwl_mvm_send_cmd(mvm, &cmd); ret = iwl_mvm_send_cmd(mvm, &cmd);
if (ret) { if (ret) {
...@@ -1750,8 +1754,19 @@ iwl_mvm_netdetect_query_results(struct iwl_mvm *mvm, ...@@ -1750,8 +1754,19 @@ iwl_mvm_netdetect_query_results(struct iwl_mvm *mvm,
return ret; return ret;
} }
if (fw_has_api(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_API_SCAN_OFFLOAD_CHANS)) {
query_len = sizeof(struct iwl_scan_offload_profiles_query);
matches_len = sizeof(struct iwl_scan_offload_profile_match) *
IWL_SCAN_MAX_PROFILES;
} else {
query_len = sizeof(struct iwl_scan_offload_profiles_query_v1);
matches_len = sizeof(struct iwl_scan_offload_profile_match_v1) *
IWL_SCAN_MAX_PROFILES;
}
len = iwl_rx_packet_payload_len(cmd.resp_pkt); len = iwl_rx_packet_payload_len(cmd.resp_pkt);
if (len < sizeof(*query)) { if (len < query_len) {
IWL_ERR(mvm, "Invalid scan offload profiles query response!\n"); IWL_ERR(mvm, "Invalid scan offload profiles query response!\n");
ret = -EIO; ret = -EIO;
goto out_free_resp; goto out_free_resp;
...@@ -1760,7 +1775,7 @@ iwl_mvm_netdetect_query_results(struct iwl_mvm *mvm, ...@@ -1760,7 +1775,7 @@ iwl_mvm_netdetect_query_results(struct iwl_mvm *mvm,
query = (void *)cmd.resp_pkt->data; query = (void *)cmd.resp_pkt->data;
results->matched_profiles = le32_to_cpu(query->matched_profiles); results->matched_profiles = le32_to_cpu(query->matched_profiles);
memcpy(results->matches, query->matches, sizeof(results->matches)); memcpy(results->matches, query->matches, matches_len);
#ifdef CONFIG_IWLWIFI_DEBUGFS #ifdef CONFIG_IWLWIFI_DEBUGFS
mvm->last_netdetect_scans = le32_to_cpu(query->n_scans_done); mvm->last_netdetect_scans = le32_to_cpu(query->n_scans_done);
...@@ -1771,6 +1786,57 @@ iwl_mvm_netdetect_query_results(struct iwl_mvm *mvm, ...@@ -1771,6 +1786,57 @@ iwl_mvm_netdetect_query_results(struct iwl_mvm *mvm,
return ret; return ret;
} }
static int iwl_mvm_query_num_match_chans(struct iwl_mvm *mvm,
struct iwl_mvm_nd_query_results *query,
int idx)
{
int n_chans = 0, i;
if (fw_has_api(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_API_SCAN_OFFLOAD_CHANS)) {
struct iwl_scan_offload_profile_match *matches =
(struct iwl_scan_offload_profile_match *)query->matches;
for (i = 0; i < SCAN_OFFLOAD_MATCHING_CHANNELS_LEN; i++)
n_chans += hweight8(matches[idx].matching_channels[i]);
} else {
struct iwl_scan_offload_profile_match_v1 *matches =
(struct iwl_scan_offload_profile_match_v1 *)query->matches;
for (i = 0; i < SCAN_OFFLOAD_MATCHING_CHANNELS_LEN_V1; i++)
n_chans += hweight8(matches[idx].matching_channels[i]);
}
return n_chans;
}
static void iwl_mvm_query_set_freqs(struct iwl_mvm *mvm,
struct iwl_mvm_nd_query_results *query,
struct cfg80211_wowlan_nd_match *match,
int idx)
{
int i;
if (fw_has_api(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_API_SCAN_OFFLOAD_CHANS)) {
struct iwl_scan_offload_profile_match *matches =
(struct iwl_scan_offload_profile_match *)query->matches;
for (i = 0; i < SCAN_OFFLOAD_MATCHING_CHANNELS_LEN * 8; i++)
if (matches[idx].matching_channels[i / 8] & (BIT(i % 8)))
match->channels[match->n_channels++] =
mvm->nd_channels[i]->center_freq;
} else {
struct iwl_scan_offload_profile_match_v1 *matches =
(struct iwl_scan_offload_profile_match_v1 *)query->matches;
for (i = 0; i < SCAN_OFFLOAD_MATCHING_CHANNELS_LEN_V1 * 8; i++)
if (matches[idx].matching_channels[i / 8] & (BIT(i % 8)))
match->channels[match->n_channels++] =
mvm->nd_channels[i]->center_freq;
}
}
static void iwl_mvm_query_netdetect_reasons(struct iwl_mvm *mvm, static void iwl_mvm_query_netdetect_reasons(struct iwl_mvm *mvm,
struct ieee80211_vif *vif) struct ieee80211_vif *vif)
{ {
...@@ -1783,7 +1849,7 @@ static void iwl_mvm_query_netdetect_reasons(struct iwl_mvm *mvm, ...@@ -1783,7 +1849,7 @@ static void iwl_mvm_query_netdetect_reasons(struct iwl_mvm *mvm,
struct iwl_wowlan_status *fw_status; struct iwl_wowlan_status *fw_status;
unsigned long matched_profiles; unsigned long matched_profiles;
u32 reasons = 0; u32 reasons = 0;
int i, j, n_matches, ret; int i, n_matches, ret;
fw_status = iwl_mvm_get_wakeup_status(mvm); fw_status = iwl_mvm_get_wakeup_status(mvm);
if (!IS_ERR_OR_NULL(fw_status)) { if (!IS_ERR_OR_NULL(fw_status)) {
...@@ -1817,14 +1883,10 @@ static void iwl_mvm_query_netdetect_reasons(struct iwl_mvm *mvm, ...@@ -1817,14 +1883,10 @@ static void iwl_mvm_query_netdetect_reasons(struct iwl_mvm *mvm,
goto out_report_nd; goto out_report_nd;
for_each_set_bit(i, &matched_profiles, mvm->n_nd_match_sets) { for_each_set_bit(i, &matched_profiles, mvm->n_nd_match_sets) {
struct iwl_scan_offload_profile_match *fw_match;
struct cfg80211_wowlan_nd_match *match; struct cfg80211_wowlan_nd_match *match;
int idx, n_channels = 0; int idx, n_channels = 0;
fw_match = &query.matches[i]; n_channels = iwl_mvm_query_num_match_chans(mvm, &query, i);
for (j = 0; j < SCAN_OFFLOAD_MATCHING_CHANNELS_LEN; j++)
n_channels += hweight8(fw_match->matching_channels[j]);
match = kzalloc(struct_size(match, channels, n_channels), match = kzalloc(struct_size(match, channels, n_channels),
GFP_KERNEL); GFP_KERNEL);
...@@ -1844,10 +1906,7 @@ static void iwl_mvm_query_netdetect_reasons(struct iwl_mvm *mvm, ...@@ -1844,10 +1906,7 @@ static void iwl_mvm_query_netdetect_reasons(struct iwl_mvm *mvm,
if (mvm->n_nd_channels < n_channels) if (mvm->n_nd_channels < n_channels)
continue; continue;
for (j = 0; j < SCAN_OFFLOAD_MATCHING_CHANNELS_LEN * 8; j++) iwl_mvm_query_set_freqs(mvm, &query, match, i);
if (fw_match->matching_channels[j / 8] & (BIT(j % 8)))
match->channels[match->n_channels++] =
mvm->nd_channels[j]->center_freq;
} }
out_report_nd: out_report_nd:
...@@ -2030,7 +2089,6 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test) ...@@ -2030,7 +2089,6 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test)
* 2. We are using a unified image but had an error while exiting D3 * 2. We are using a unified image but had an error while exiting D3
*/ */
set_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status); set_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status);
set_bit(IWL_MVM_STATUS_D3_RECONFIG, &mvm->status);
/* /*
* When switching images we return 1, which causes mac80211 * When switching images we return 1, which causes mac80211
* to do a reconfig with IEEE80211_RECONFIG_TYPE_RESTART. * to do a reconfig with IEEE80211_RECONFIG_TYPE_RESTART.
......
...@@ -1349,7 +1349,7 @@ static ssize_t iwl_dbgfs_fw_dbg_collect_write(struct iwl_mvm *mvm, ...@@ -1349,7 +1349,7 @@ static ssize_t iwl_dbgfs_fw_dbg_collect_write(struct iwl_mvm *mvm,
return 0; return 0;
iwl_fw_dbg_collect(&mvm->fwrt, FW_DBG_TRIGGER_USER, buf, iwl_fw_dbg_collect(&mvm->fwrt, FW_DBG_TRIGGER_USER, buf,
(count - 1)); (count - 1), NULL);
iwl_mvm_unref(mvm, IWL_MVM_REF_PRPH_WRITE); iwl_mvm_unref(mvm, IWL_MVM_REF_PRPH_WRITE);
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation * Copyright(c) 2018 - 2019 Intel Corporation
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
...@@ -1573,6 +1573,7 @@ void iwl_mvm_channel_switch_noa_notif(struct iwl_mvm *mvm, ...@@ -1573,6 +1573,7 @@ void iwl_mvm_channel_switch_noa_notif(struct iwl_mvm *mvm,
rcu_read_lock(); rcu_read_lock();
vif = rcu_dereference(mvm->vif_id_to_mac[mac_id]); vif = rcu_dereference(mvm->vif_id_to_mac[mac_id]);
mvmvif = iwl_mvm_vif_from_mac80211(vif);
switch (vif->type) { switch (vif->type) {
case NL80211_IFTYPE_AP: case NL80211_IFTYPE_AP:
...@@ -1581,7 +1582,6 @@ void iwl_mvm_channel_switch_noa_notif(struct iwl_mvm *mvm, ...@@ -1581,7 +1582,6 @@ void iwl_mvm_channel_switch_noa_notif(struct iwl_mvm *mvm,
csa_vif != vif)) csa_vif != vif))
goto out_unlock; goto out_unlock;
mvmvif = iwl_mvm_vif_from_mac80211(csa_vif);
csa_id = FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color); csa_id = FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color);
if (WARN(csa_id != id_n_color, if (WARN(csa_id != id_n_color,
"channel switch noa notification on unexpected vif (csa_vif=%d, notif=%d)", "channel switch noa notification on unexpected vif (csa_vif=%d, notif=%d)",
...@@ -1602,6 +1602,7 @@ void iwl_mvm_channel_switch_noa_notif(struct iwl_mvm *mvm, ...@@ -1602,6 +1602,7 @@ void iwl_mvm_channel_switch_noa_notif(struct iwl_mvm *mvm,
return; return;
case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_STATION:
iwl_mvm_csa_client_absent(mvm, vif); iwl_mvm_csa_client_absent(mvm, vif);
cancel_delayed_work_sync(&mvmvif->csa_work);
ieee80211_chswitch_done(vif, true); ieee80211_chswitch_done(vif, true);
break; break;
default: default:
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation * Copyright(c) 2018 - 2019 Intel Corporation
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
...@@ -420,6 +420,7 @@ int iwl_mvm_init_fw_regd(struct iwl_mvm *mvm) ...@@ -420,6 +420,7 @@ int iwl_mvm_init_fw_regd(struct iwl_mvm *mvm)
const static u8 he_if_types_ext_capa_sta[] = { const static u8 he_if_types_ext_capa_sta[] = {
[0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING, [0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,
[2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT,
[7] = WLAN_EXT_CAPA8_OPMODE_NOTIF, [7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,
[9] = WLAN_EXT_CAPA10_TWT_REQUESTER_SUPPORT, [9] = WLAN_EXT_CAPA10_TWT_REQUESTER_SUPPORT,
}; };
...@@ -597,6 +598,9 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) ...@@ -597,6 +598,9 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
BIT(NL80211_IFTYPE_ADHOC); BIT(NL80211_IFTYPE_ADHOC);
hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
hw->wiphy->features |= NL80211_FEATURE_HT_IBSS;
hw->wiphy->regulatory_flags |= REGULATORY_ENABLE_RELAX_NO_IR; hw->wiphy->regulatory_flags |= REGULATORY_ENABLE_RELAX_NO_IR;
if (iwl_mvm_is_lar_supported(mvm)) if (iwl_mvm_is_lar_supported(mvm))
hw->wiphy->regulatory_flags |= REGULATORY_WIPHY_SELF_MANAGED; hw->wiphy->regulatory_flags |= REGULATORY_WIPHY_SELF_MANAGED;
...@@ -732,6 +736,9 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) ...@@ -732,6 +736,9 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
hw->wiphy->iftype_ext_capab = he_iftypes_ext_capa; hw->wiphy->iftype_ext_capab = he_iftypes_ext_capa;
hw->wiphy->num_iftype_ext_capab = hw->wiphy->num_iftype_ext_capab =
ARRAY_SIZE(he_iftypes_ext_capa); ARRAY_SIZE(he_iftypes_ext_capa);
ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID);
ieee80211_hw_set(hw, SUPPORTS_ONLY_HE_MULTI_BSSID);
} }
mvm->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; mvm->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
...@@ -1191,15 +1198,6 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac, ...@@ -1191,15 +1198,6 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac,
static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm) static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
{ {
/* clear the D3 reconfig, we only need it to avoid dumping a
* firmware coredump on reconfiguration, we shouldn't do that
* on D3->D0 transition
*/
if (!test_and_clear_bit(IWL_MVM_STATUS_D3_RECONFIG, &mvm->status)) {
mvm->fwrt.dump.desc = &iwl_dump_desc_assert;
iwl_fw_error_dump(&mvm->fwrt);
}
/* cleanup all stale references (scan, roc), but keep the /* cleanup all stale references (scan, roc), but keep the
* ucode_down ref until reconfig is complete * ucode_down ref until reconfig is complete
*/ */
...@@ -1500,6 +1498,91 @@ static int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif, ...@@ -1500,6 +1498,91 @@ static int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
return iwl_mvm_send_cmd_pdu(mvm, REDUCE_TX_POWER_CMD, 0, len, &cmd); return iwl_mvm_send_cmd_pdu(mvm, REDUCE_TX_POWER_CMD, 0, len, &cmd);
} }
static int iwl_mvm_post_channel_switch(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
int ret;
mutex_lock(&mvm->mutex);
if (mvmvif->csa_failed) {
mvmvif->csa_failed = false;
ret = -EIO;
goto out_unlock;
}
if (vif->type == NL80211_IFTYPE_STATION) {
struct iwl_mvm_sta *mvmsta;
mvmvif->csa_bcn_pending = false;
mvmsta = iwl_mvm_sta_from_staid_protected(mvm,
mvmvif->ap_sta_id);
if (WARN_ON(!mvmsta)) {
ret = -EIO;
goto out_unlock;
}
iwl_mvm_sta_modify_disable_tx(mvm, mvmsta, false);
iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
ret = iwl_mvm_enable_beacon_filter(mvm, vif, 0);
if (ret)
goto out_unlock;
iwl_mvm_stop_session_protection(mvm, vif);
}
mvmvif->ps_disabled = false;
ret = iwl_mvm_power_update_ps(mvm);
out_unlock:
mutex_unlock(&mvm->mutex);
return ret;
}
static void iwl_mvm_abort_channel_switch(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
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_REMOVE),
};
IWL_DEBUG_MAC80211(mvm, "Abort CSA on mac %d\n", mvmvif->id);
mutex_lock(&mvm->mutex);
WARN_ON(iwl_mvm_send_cmd_pdu(mvm,
WIDE_ID(MAC_CONF_GROUP,
CHANNEL_SWITCH_TIME_EVENT_CMD),
0, sizeof(cmd), &cmd));
mutex_unlock(&mvm->mutex);
WARN_ON(iwl_mvm_post_channel_switch(hw, vif));
}
static void iwl_mvm_channel_switch_disconnect_wk(struct work_struct *wk)
{
struct iwl_mvm *mvm;
struct iwl_mvm_vif *mvmvif;
struct ieee80211_vif *vif;
mvmvif = container_of(wk, struct iwl_mvm_vif, csa_work.work);
vif = container_of((void *)mvmvif, struct ieee80211_vif, drv_priv);
mvm = mvmvif->mvm;
iwl_mvm_abort_channel_switch(mvm->hw, vif);
ieee80211_chswitch_done(vif, false);
}
static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif) struct ieee80211_vif *vif)
{ {
...@@ -1626,6 +1709,8 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, ...@@ -1626,6 +1709,8 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
} }
iwl_mvm_tcm_add_vif(mvm, vif); iwl_mvm_tcm_add_vif(mvm, vif);
INIT_DELAYED_WORK(&mvmvif->csa_work,
iwl_mvm_channel_switch_disconnect_wk);
if (vif->type == NL80211_IFTYPE_MONITOR) if (vif->type == NL80211_IFTYPE_MONITOR)
mvm->monitor_on = true; mvm->monitor_on = true;
...@@ -2308,7 +2393,11 @@ static void iwl_mvm_cfg_he_sta(struct iwl_mvm *mvm, ...@@ -2308,7 +2393,11 @@ static void iwl_mvm_cfg_he_sta(struct iwl_mvm *mvm,
(vif->bss_conf.uora_ocw_range >> 3) & 0x7; (vif->bss_conf.uora_ocw_range >> 3) & 0x7;
} }
/* TODO: support Multi BSSID IE */ if (vif->bss_conf.nontransmitted) {
flags |= STA_CTXT_HE_REF_BSSID_VALID;
ether_addr_copy(sta_ctxt_cmd.ref_bssid_addr,
vif->bss_conf.transmitter_bssid);
}
sta_ctxt_cmd.flags = cpu_to_le32(flags); sta_ctxt_cmd.flags = cpu_to_le32(flags);
...@@ -4469,16 +4558,22 @@ static int iwl_mvm_schedule_client_csa(struct iwl_mvm *mvm, ...@@ -4469,16 +4558,22 @@ static int iwl_mvm_schedule_client_csa(struct iwl_mvm *mvm,
.action = cpu_to_le32(FW_CTXT_ACTION_ADD), .action = cpu_to_le32(FW_CTXT_ACTION_ADD),
.tsf = cpu_to_le32(chsw->timestamp), .tsf = cpu_to_le32(chsw->timestamp),
.cs_count = chsw->count, .cs_count = chsw->count,
.cs_mode = chsw->block_tx,
}; };
lockdep_assert_held(&mvm->mutex); lockdep_assert_held(&mvm->mutex);
if (chsw->delay)
cmd.cs_delayed_bcn_count =
DIV_ROUND_UP(chsw->delay, vif->bss_conf.beacon_int);
return iwl_mvm_send_cmd_pdu(mvm, return iwl_mvm_send_cmd_pdu(mvm,
WIDE_ID(MAC_CONF_GROUP, WIDE_ID(MAC_CONF_GROUP,
CHANNEL_SWITCH_TIME_EVENT_CMD), CHANNEL_SWITCH_TIME_EVENT_CMD),
0, sizeof(cmd), &cmd); 0, sizeof(cmd), &cmd);
} }
#define IWL_MAX_CSA_BLOCK_TX 1500
static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw, static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, struct ieee80211_vif *vif,
struct ieee80211_channel_switch *chsw) struct ieee80211_channel_switch *chsw)
...@@ -4543,8 +4638,18 @@ static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw, ...@@ -4543,8 +4638,18 @@ static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw,
((vif->bss_conf.beacon_int * (chsw->count - 1) - ((vif->bss_conf.beacon_int * (chsw->count - 1) -
IWL_MVM_CHANNEL_SWITCH_TIME_CLIENT) * 1024); IWL_MVM_CHANNEL_SWITCH_TIME_CLIENT) * 1024);
if (chsw->block_tx) if (chsw->block_tx) {
iwl_mvm_csa_client_absent(mvm, vif); iwl_mvm_csa_client_absent(mvm, vif);
/*
* In case of undetermined / long time with immediate
* quiet monitor status to gracefully disconnect
*/
if (!chsw->count ||
chsw->count * vif->bss_conf.beacon_int >
IWL_MAX_CSA_BLOCK_TX)
schedule_delayed_work(&mvmvif->csa_work,
msecs_to_jiffies(IWL_MAX_CSA_BLOCK_TX));
}
if (mvmvif->bf_data.bf_enabled) { if (mvmvif->bf_data.bf_enabled) {
ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0); ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0);
...@@ -4559,6 +4664,9 @@ static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw, ...@@ -4559,6 +4664,9 @@ static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw,
iwl_mvm_schedule_csa_period(mvm, vif, iwl_mvm_schedule_csa_period(mvm, vif,
vif->bss_conf.beacon_int, vif->bss_conf.beacon_int,
apply_time); apply_time);
mvmvif->csa_count = chsw->count;
mvmvif->csa_misbehave = false;
break; break;
default: default:
break; break;
...@@ -4579,52 +4687,42 @@ static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw, ...@@ -4579,52 +4687,42 @@ static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw,
return ret; return ret;
} }
static int iwl_mvm_post_channel_switch(struct ieee80211_hw *hw, static void iwl_mvm_channel_switch_rx_beacon(struct ieee80211_hw *hw,
struct ieee80211_vif *vif) struct ieee80211_vif *vif,
struct ieee80211_channel_switch *chsw)
{ {
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
int ret; struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_chan_switch_te_cmd cmd = {
mutex_lock(&mvm->mutex); .mac_id = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
mvmvif->color)),
if (mvmvif->csa_failed) { .action = cpu_to_le32(FW_CTXT_ACTION_MODIFY),
mvmvif->csa_failed = false; .tsf = cpu_to_le32(chsw->timestamp),
ret = -EIO; .cs_count = chsw->count,
goto out_unlock; .cs_mode = chsw->block_tx,
} };
if (vif->type == NL80211_IFTYPE_STATION) {
struct iwl_mvm_sta *mvmsta;
mvmvif->csa_bcn_pending = false; if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_CS_MODIFY))
mvmsta = iwl_mvm_sta_from_staid_protected(mvm, return;
mvmvif->ap_sta_id);
if (WARN_ON(!mvmsta)) { if (chsw->count >= mvmvif->csa_count && chsw->block_tx) {
ret = -EIO; if (mvmvif->csa_misbehave) {
goto out_unlock; /* Second time, give up on this AP*/
iwl_mvm_abort_channel_switch(hw, vif);
ieee80211_chswitch_done(vif, false);
mvmvif->csa_misbehave = false;
return;
} }
mvmvif->csa_misbehave = true;
iwl_mvm_sta_modify_disable_tx(mvm, mvmsta, false);
iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
ret = iwl_mvm_enable_beacon_filter(mvm, vif, 0);
if (ret)
goto out_unlock;
iwl_mvm_stop_session_protection(mvm, vif);
} }
mvmvif->csa_count = chsw->count;
mvmvif->ps_disabled = false; IWL_DEBUG_MAC80211(mvm, "Modify CSA on mac %d\n", mvmvif->id);
ret = iwl_mvm_power_update_ps(mvm);
out_unlock:
mutex_unlock(&mvm->mutex);
return ret; WARN_ON(iwl_mvm_send_cmd_pdu(mvm,
WIDE_ID(MAC_CONF_GROUP,
CHANNEL_SWITCH_TIME_EVENT_CMD),
CMD_ASYNC, sizeof(cmd), &cmd));
} }
static void iwl_mvm_flush_no_vif(struct iwl_mvm *mvm, u32 queues, bool drop) static void iwl_mvm_flush_no_vif(struct iwl_mvm *mvm, u32 queues, bool drop)
...@@ -5083,6 +5181,8 @@ const struct ieee80211_ops iwl_mvm_hw_ops = { ...@@ -5083,6 +5181,8 @@ const struct ieee80211_ops iwl_mvm_hw_ops = {
.channel_switch = iwl_mvm_channel_switch, .channel_switch = iwl_mvm_channel_switch,
.pre_channel_switch = iwl_mvm_pre_channel_switch, .pre_channel_switch = iwl_mvm_pre_channel_switch,
.post_channel_switch = iwl_mvm_post_channel_switch, .post_channel_switch = iwl_mvm_post_channel_switch,
.abort_channel_switch = iwl_mvm_abort_channel_switch,
.channel_switch_rx_beacon = iwl_mvm_channel_switch_rx_beacon,
.tdls_channel_switch = iwl_mvm_tdls_channel_switch, .tdls_channel_switch = iwl_mvm_tdls_channel_switch,
.tdls_cancel_channel_switch = iwl_mvm_tdls_cancel_channel_switch, .tdls_cancel_channel_switch = iwl_mvm_tdls_cancel_channel_switch,
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation * Copyright(c) 2018 - 2019 Intel Corporation
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
...@@ -490,6 +490,9 @@ struct iwl_mvm_vif { ...@@ -490,6 +490,9 @@ struct iwl_mvm_vif {
bool csa_countdown; bool csa_countdown;
bool csa_failed; bool csa_failed;
u16 csa_target_freq; u16 csa_target_freq;
u16 csa_count;
u16 csa_misbehave;
struct delayed_work csa_work;
/* Indicates that we are waiting for a beacon on a new channel */ /* Indicates that we are waiting for a beacon on a new channel */
bool csa_bcn_pending; bool csa_bcn_pending;
...@@ -1200,7 +1203,6 @@ struct iwl_mvm { ...@@ -1200,7 +1203,6 @@ struct iwl_mvm {
* @IWL_MVM_STATUS_IN_HW_RESTART: HW restart is active * @IWL_MVM_STATUS_IN_HW_RESTART: HW restart is active
* @IWL_MVM_STATUS_IN_D0I3: NIC is in D0i3 * @IWL_MVM_STATUS_IN_D0I3: NIC is in D0i3
* @IWL_MVM_STATUS_ROC_AUX_RUNNING: AUX remain-on-channel is running * @IWL_MVM_STATUS_ROC_AUX_RUNNING: AUX remain-on-channel is running
* @IWL_MVM_STATUS_D3_RECONFIG: D3 reconfiguration is being done
* @IWL_MVM_STATUS_FIRMWARE_RUNNING: firmware is running * @IWL_MVM_STATUS_FIRMWARE_RUNNING: firmware is running
* @IWL_MVM_STATUS_NEED_FLUSH_P2P: need to flush P2P bcast STA * @IWL_MVM_STATUS_NEED_FLUSH_P2P: need to flush P2P bcast STA
*/ */
...@@ -1212,7 +1214,6 @@ enum iwl_mvm_status { ...@@ -1212,7 +1214,6 @@ enum iwl_mvm_status {
IWL_MVM_STATUS_IN_HW_RESTART, IWL_MVM_STATUS_IN_HW_RESTART,
IWL_MVM_STATUS_IN_D0I3, IWL_MVM_STATUS_IN_D0I3,
IWL_MVM_STATUS_ROC_AUX_RUNNING, IWL_MVM_STATUS_ROC_AUX_RUNNING,
IWL_MVM_STATUS_D3_RECONFIG,
IWL_MVM_STATUS_FIRMWARE_RUNNING, IWL_MVM_STATUS_FIRMWARE_RUNNING,
IWL_MVM_STATUS_NEED_FLUSH_P2P, IWL_MVM_STATUS_NEED_FLUSH_P2P,
}; };
...@@ -1650,8 +1651,8 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi, ...@@ -1650,8 +1651,8 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi,
struct iwl_rx_cmd_buffer *rxb); struct iwl_rx_cmd_buffer *rxb);
void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi, void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
struct iwl_rx_cmd_buffer *rxb, int queue); struct iwl_rx_cmd_buffer *rxb, int queue);
void iwl_mvm_rx_monitor_ndp(struct iwl_mvm *mvm, struct napi_struct *napi, void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi,
struct iwl_rx_cmd_buffer *rxb, int queue); struct iwl_rx_cmd_buffer *rxb, int queue);
void iwl_mvm_rx_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi, void iwl_mvm_rx_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi,
struct iwl_rx_cmd_buffer *rxb, int queue); struct iwl_rx_cmd_buffer *rxb, int queue);
int iwl_mvm_notify_rx_queue(struct iwl_mvm *mvm, u32 rxq_mask, int iwl_mvm_notify_rx_queue(struct iwl_mvm *mvm, u32 rxq_mask,
...@@ -2024,17 +2025,6 @@ static inline u32 iwl_mvm_flushable_queues(struct iwl_mvm *mvm) ...@@ -2024,17 +2025,6 @@ static inline u32 iwl_mvm_flushable_queues(struct iwl_mvm *mvm)
static inline void iwl_mvm_stop_device(struct iwl_mvm *mvm) static inline void iwl_mvm_stop_device(struct iwl_mvm *mvm)
{ {
lockdep_assert_held(&mvm->mutex); lockdep_assert_held(&mvm->mutex);
/* If IWL_MVM_STATUS_HW_RESTART_REQUESTED bit is set then we received
* an assert. Since we failed to bring the interface up, mac80211
* will not attempt to reconfig the device,
* which handles the dump collection in assert flow,
* so trigger dump collection here.
*/
if (test_and_clear_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED,
&mvm->status))
iwl_fw_dbg_collect_desc(&mvm->fwrt, &iwl_dump_desc_assert,
false, 0);
iwl_fw_cancel_timestamp(&mvm->fwrt); iwl_fw_cancel_timestamp(&mvm->fwrt);
clear_bit(IWL_MVM_STATUS_FIRMWARE_RUNNING, &mvm->status); clear_bit(IWL_MVM_STATUS_FIRMWARE_RUNNING, &mvm->status);
iwl_fwrt_stop_device(&mvm->fwrt); iwl_fwrt_stop_device(&mvm->fwrt);
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation * Copyright(c) 2018 - 2019 Intel Corporation
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
...@@ -1105,7 +1105,7 @@ static void iwl_mvm_rx_mq(struct iwl_op_mode *op_mode, ...@@ -1105,7 +1105,7 @@ static void iwl_mvm_rx_mq(struct iwl_op_mode *op_mode,
else if (cmd == WIDE_ID(LEGACY_GROUP, FRAME_RELEASE)) else if (cmd == WIDE_ID(LEGACY_GROUP, FRAME_RELEASE))
iwl_mvm_rx_frame_release(mvm, napi, rxb, 0); iwl_mvm_rx_frame_release(mvm, napi, rxb, 0);
else if (cmd == WIDE_ID(DATA_PATH_GROUP, RX_NO_DATA_NOTIF)) else if (cmd == WIDE_ID(DATA_PATH_GROUP, RX_NO_DATA_NOTIF))
iwl_mvm_rx_monitor_ndp(mvm, napi, rxb, 0); iwl_mvm_rx_monitor_no_data(mvm, napi, rxb, 0);
else else
iwl_mvm_rx_common(mvm, rxb, pkt); iwl_mvm_rx_common(mvm, rxb, pkt);
} }
...@@ -1340,6 +1340,8 @@ void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error) ...@@ -1340,6 +1340,8 @@ void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error)
} }
} }
iwl_fw_dbg_collect_desc(&mvm->fwrt, &iwl_dump_desc_assert,
false, 0);
if (fw_error && mvm->fw_restart > 0) if (fw_error && mvm->fw_restart > 0)
mvm->fw_restart--; mvm->fw_restart--;
set_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status); set_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status);
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* GPL LICENSE SUMMARY * GPL LICENSE SUMMARY
* *
* Copyright(c) 2017 Intel Deutschland GmbH * Copyright(c) 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation * Copyright(c) 2018 - 2019 Intel Corporation
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
* BSD LICENSE * BSD LICENSE
* *
* Copyright(c) 2017 Intel Deutschland GmbH * Copyright(c) 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
...@@ -345,6 +345,37 @@ void iwl_mvm_tlc_update_notif(struct iwl_mvm *mvm, ...@@ -345,6 +345,37 @@ void iwl_mvm_tlc_update_notif(struct iwl_mvm *mvm,
rcu_read_unlock(); rcu_read_unlock();
} }
static u16 rs_fw_get_max_amsdu_len(struct ieee80211_sta *sta)
{
const struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap;
const struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
if (vht_cap && vht_cap->vht_supported) {
switch (vht_cap->cap & IEEE80211_VHT_CAP_MAX_MPDU_MASK) {
case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454:
return IEEE80211_MAX_MPDU_LEN_VHT_11454;
case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991:
return IEEE80211_MAX_MPDU_LEN_VHT_7991;
default:
return IEEE80211_MAX_MPDU_LEN_VHT_3895;
}
} else if (ht_cap && ht_cap->ht_supported) {
if (ht_cap->cap & IEEE80211_HT_CAP_MAX_AMSDU)
/*
* agg is offloaded so we need to assume that agg
* are enabled and max mpdu in ampdu is 4095
* (spec 802.11-2016 9.3.2.1)
*/
return IEEE80211_MAX_MPDU_LEN_HT_BA;
else
return IEEE80211_MAX_MPDU_LEN_HT_3839;
}
/* in legacy mode no amsdu is enabled so return zero */
return 0;
}
void rs_fw_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, void rs_fw_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
enum nl80211_band band, bool update) enum nl80211_band band, bool update)
{ {
...@@ -353,14 +384,15 @@ void rs_fw_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, ...@@ -353,14 +384,15 @@ void rs_fw_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
struct iwl_lq_sta_rs_fw *lq_sta = &mvmsta->lq_sta.rs_fw; struct iwl_lq_sta_rs_fw *lq_sta = &mvmsta->lq_sta.rs_fw;
u32 cmd_id = iwl_cmd_id(TLC_MNG_CONFIG_CMD, DATA_PATH_GROUP, 0); u32 cmd_id = iwl_cmd_id(TLC_MNG_CONFIG_CMD, DATA_PATH_GROUP, 0);
struct ieee80211_supported_band *sband; struct ieee80211_supported_band *sband;
u16 max_amsdu_len = rs_fw_get_max_amsdu_len(sta);
struct iwl_tlc_config_cmd cfg_cmd = { struct iwl_tlc_config_cmd cfg_cmd = {
.sta_id = mvmsta->sta_id, .sta_id = mvmsta->sta_id,
.max_ch_width = update ? .max_ch_width = update ?
rs_fw_bw_from_sta_bw(sta) : RATE_MCS_CHAN_WIDTH_20, rs_fw_bw_from_sta_bw(sta) : RATE_MCS_CHAN_WIDTH_20,
.flags = cpu_to_le16(rs_fw_set_config_flags(mvm, sta)), .flags = cpu_to_le16(rs_fw_set_config_flags(mvm, sta)),
.chains = rs_fw_set_active_chains(iwl_mvm_get_valid_tx_ant(mvm)), .chains = rs_fw_set_active_chains(iwl_mvm_get_valid_tx_ant(mvm)),
.max_mpdu_len = cpu_to_le16(sta->max_amsdu_len),
.sgi_ch_width_supp = rs_fw_sgi_cw_support(sta), .sgi_ch_width_supp = rs_fw_sgi_cw_support(sta),
.max_mpdu_len = cpu_to_le16(max_amsdu_len),
.amsdu = iwl_mvm_is_csum_supported(mvm), .amsdu = iwl_mvm_is_csum_supported(mvm),
}; };
int ret; int ret;
...@@ -373,6 +405,12 @@ void rs_fw_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, ...@@ -373,6 +405,12 @@ void rs_fw_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
sband = hw->wiphy->bands[band]; sband = hw->wiphy->bands[band];
rs_fw_set_supp_rates(sta, sband, &cfg_cmd); rs_fw_set_supp_rates(sta, sband, &cfg_cmd);
/*
* since TLC offload works with one mode we can assume
* that only vht/ht is used and also set it as station max amsdu
*/
sta->max_amsdu_len = max_amsdu_len;
ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, sizeof(cfg_cmd), &cfg_cmd); ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, sizeof(cfg_cmd), &cfg_cmd);
if (ret) if (ret)
IWL_ERR(mvm, "Failed to send rate scale config (%d)\n", ret); IWL_ERR(mvm, "Failed to send rate scale config (%d)\n", ret);
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation * Copyright(c) 2018 - 2019 Intel Corporation
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
...@@ -1679,8 +1679,8 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi, ...@@ -1679,8 +1679,8 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
rcu_read_unlock(); rcu_read_unlock();
} }
void iwl_mvm_rx_monitor_ndp(struct iwl_mvm *mvm, struct napi_struct *napi, void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi,
struct iwl_rx_cmd_buffer *rxb, int queue) struct iwl_rx_cmd_buffer *rxb, int queue)
{ {
struct ieee80211_rx_status *rx_status; struct ieee80211_rx_status *rx_status;
struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_rx_packet *pkt = rxb_addr(rxb);
...@@ -1701,10 +1701,6 @@ void iwl_mvm_rx_monitor_ndp(struct iwl_mvm *mvm, struct napi_struct *napi, ...@@ -1701,10 +1701,6 @@ void iwl_mvm_rx_monitor_ndp(struct iwl_mvm *mvm, struct napi_struct *napi,
if (unlikely(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))) if (unlikely(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)))
return; return;
/* Currently only NDP type is supported */
if (info_type != RX_NO_DATA_INFO_TYPE_NDP)
return;
energy_a = (rssi & RX_NO_DATA_CHAIN_A_MSK) >> RX_NO_DATA_CHAIN_A_POS; energy_a = (rssi & RX_NO_DATA_CHAIN_A_MSK) >> RX_NO_DATA_CHAIN_A_POS;
energy_b = (rssi & RX_NO_DATA_CHAIN_B_MSK) >> RX_NO_DATA_CHAIN_B_POS; energy_b = (rssi & RX_NO_DATA_CHAIN_B_MSK) >> RX_NO_DATA_CHAIN_B_POS;
channel = (rssi & RX_NO_DATA_CHANNEL_MSK) >> RX_NO_DATA_CHANNEL_POS; channel = (rssi & RX_NO_DATA_CHANNEL_MSK) >> RX_NO_DATA_CHANNEL_POS;
...@@ -1726,9 +1722,22 @@ void iwl_mvm_rx_monitor_ndp(struct iwl_mvm *mvm, struct napi_struct *napi, ...@@ -1726,9 +1722,22 @@ void iwl_mvm_rx_monitor_ndp(struct iwl_mvm *mvm, struct napi_struct *napi,
/* 0-length PSDU */ /* 0-length PSDU */
rx_status->flag |= RX_FLAG_NO_PSDU; rx_status->flag |= RX_FLAG_NO_PSDU;
/* currently this is the only type for which we get this notif */
rx_status->zero_length_psdu_type = switch (info_type) {
IEEE80211_RADIOTAP_ZERO_LEN_PSDU_SOUNDING; case RX_NO_DATA_INFO_TYPE_NDP:
rx_status->zero_length_psdu_type =
IEEE80211_RADIOTAP_ZERO_LEN_PSDU_SOUNDING;
break;
case RX_NO_DATA_INFO_TYPE_MU_UNMATCHED:
case RX_NO_DATA_INFO_TYPE_HE_TB_UNMATCHED:
rx_status->zero_length_psdu_type =
IEEE80211_RADIOTAP_ZERO_LEN_PSDU_NOT_CAPTURED;
break;
default:
rx_status->zero_length_psdu_type =
IEEE80211_RADIOTAP_ZERO_LEN_PSDU_VENDOR;
break;
}
/* This may be overridden by iwl_mvm_rx_he() to HE_RU */ /* This may be overridden by iwl_mvm_rx_he() to HE_RU */
switch (rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK) { switch (rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK) {
......
...@@ -1082,21 +1082,23 @@ static void iwl_mvm_fill_scan_dwell(struct iwl_mvm *mvm, ...@@ -1082,21 +1082,23 @@ static void iwl_mvm_fill_scan_dwell(struct iwl_mvm *mvm,
dwell->extended = IWL_SCAN_DWELL_EXTENDED; dwell->extended = IWL_SCAN_DWELL_EXTENDED;
} }
static void iwl_mvm_fill_channels(struct iwl_mvm *mvm, u8 *channels) static void iwl_mvm_fill_channels(struct iwl_mvm *mvm, u8 *channels,
u32 max_channels)
{ {
struct ieee80211_supported_band *band; struct ieee80211_supported_band *band;
int i, j = 0; int i, j = 0;
band = &mvm->nvm_data->bands[NL80211_BAND_2GHZ]; band = &mvm->nvm_data->bands[NL80211_BAND_2GHZ];
for (i = 0; i < band->n_channels; i++, j++) for (i = 0; i < band->n_channels && j < max_channels; i++, j++)
channels[j] = band->channels[i].hw_value; channels[j] = band->channels[i].hw_value;
band = &mvm->nvm_data->bands[NL80211_BAND_5GHZ]; band = &mvm->nvm_data->bands[NL80211_BAND_5GHZ];
for (i = 0; i < band->n_channels; i++, j++) for (i = 0; i < band->n_channels && j < max_channels; i++, j++)
channels[j] = band->channels[i].hw_value; channels[j] = band->channels[i].hw_value;
} }
static void iwl_mvm_fill_scan_config_v1(struct iwl_mvm *mvm, void *config, static void iwl_mvm_fill_scan_config_v1(struct iwl_mvm *mvm, void *config,
u32 flags, u8 channel_flags) u32 flags, u8 channel_flags,
u32 max_channels)
{ {
enum iwl_mvm_scan_type type = iwl_mvm_get_scan_type(mvm, NULL); enum iwl_mvm_scan_type type = iwl_mvm_get_scan_type(mvm, NULL);
struct iwl_scan_config_v1 *cfg = config; struct iwl_scan_config_v1 *cfg = config;
...@@ -1115,11 +1117,12 @@ static void iwl_mvm_fill_scan_config_v1(struct iwl_mvm *mvm, void *config, ...@@ -1115,11 +1117,12 @@ static void iwl_mvm_fill_scan_config_v1(struct iwl_mvm *mvm, void *config,
cfg->bcast_sta_id = mvm->aux_sta.sta_id; cfg->bcast_sta_id = mvm->aux_sta.sta_id;
cfg->channel_flags = channel_flags; cfg->channel_flags = channel_flags;
iwl_mvm_fill_channels(mvm, cfg->channel_array); iwl_mvm_fill_channels(mvm, cfg->channel_array, max_channels);
} }
static void iwl_mvm_fill_scan_config(struct iwl_mvm *mvm, void *config, static void iwl_mvm_fill_scan_config(struct iwl_mvm *mvm, void *config,
u32 flags, u8 channel_flags) u32 flags, u8 channel_flags,
u32 max_channels)
{ {
struct iwl_scan_config *cfg = config; struct iwl_scan_config *cfg = config;
...@@ -1162,7 +1165,7 @@ static void iwl_mvm_fill_scan_config(struct iwl_mvm *mvm, void *config, ...@@ -1162,7 +1165,7 @@ static void iwl_mvm_fill_scan_config(struct iwl_mvm *mvm, void *config,
cfg->bcast_sta_id = mvm->aux_sta.sta_id; cfg->bcast_sta_id = mvm->aux_sta.sta_id;
cfg->channel_flags = channel_flags; cfg->channel_flags = channel_flags;
iwl_mvm_fill_channels(mvm, cfg->channel_array); iwl_mvm_fill_channels(mvm, cfg->channel_array, max_channels);
} }
int iwl_mvm_config_scan(struct iwl_mvm *mvm) int iwl_mvm_config_scan(struct iwl_mvm *mvm)
...@@ -1181,7 +1184,7 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm) ...@@ -1181,7 +1184,7 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm)
u8 channel_flags; u8 channel_flags;
if (WARN_ON(num_channels > mvm->fw->ucode_capa.n_scan_channels)) if (WARN_ON(num_channels > mvm->fw->ucode_capa.n_scan_channels))
return -ENOBUFS; num_channels = mvm->fw->ucode_capa.n_scan_channels;
if (iwl_mvm_is_cdb_supported(mvm)) { if (iwl_mvm_is_cdb_supported(mvm)) {
type = iwl_mvm_get_scan_type_band(mvm, NULL, type = iwl_mvm_get_scan_type_band(mvm, NULL,
...@@ -1234,9 +1237,11 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm) ...@@ -1234,9 +1237,11 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm)
flags |= (iwl_mvm_is_scan_fragmented(hb_type)) ? flags |= (iwl_mvm_is_scan_fragmented(hb_type)) ?
SCAN_CONFIG_FLAG_SET_LMAC2_FRAGMENTED : SCAN_CONFIG_FLAG_SET_LMAC2_FRAGMENTED :
SCAN_CONFIG_FLAG_CLEAR_LMAC2_FRAGMENTED; SCAN_CONFIG_FLAG_CLEAR_LMAC2_FRAGMENTED;
iwl_mvm_fill_scan_config(mvm, cfg, flags, channel_flags); iwl_mvm_fill_scan_config(mvm, cfg, flags, channel_flags,
num_channels);
} else { } else {
iwl_mvm_fill_scan_config_v1(mvm, cfg, flags, channel_flags); iwl_mvm_fill_scan_config_v1(mvm, cfg, flags, channel_flags,
num_channels);
} }
cmd.data[0] = cfg; cmd.data[0] = cfg;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2017 Intel Deutschland GmbH * Copyright(c) 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation * Copyright(c) 2018 - 2019 Intel Corporation
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2017 Intel Deutschland GmbH * Copyright(c) 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
...@@ -234,6 +234,7 @@ iwl_mvm_te_handle_notify_csa(struct iwl_mvm *mvm, ...@@ -234,6 +234,7 @@ iwl_mvm_te_handle_notify_csa(struct iwl_mvm *mvm,
break; break;
} }
iwl_mvm_csa_client_absent(mvm, te_data->vif); iwl_mvm_csa_client_absent(mvm, te_data->vif);
cancel_delayed_work_sync(&mvmvif->csa_work);
ieee80211_chswitch_done(te_data->vif, true); ieee80211_chswitch_done(te_data->vif, true);
break; break;
default: default:
......
...@@ -106,7 +106,6 @@ struct iwl_host_cmd; ...@@ -106,7 +106,6 @@ struct iwl_host_cmd;
* @page: driver's pointer to the rxb page * @page: driver's pointer to the rxb page
* @invalid: rxb is in driver ownership - not owned by HW * @invalid: rxb is in driver ownership - not owned by HW
* @vid: index of this rxb in the global table * @vid: index of this rxb in the global table
* @size: size used from the buffer
*/ */
struct iwl_rx_mem_buffer { struct iwl_rx_mem_buffer {
dma_addr_t page_dma; dma_addr_t page_dma;
...@@ -114,7 +113,6 @@ struct iwl_rx_mem_buffer { ...@@ -114,7 +113,6 @@ struct iwl_rx_mem_buffer {
u16 vid; u16 vid;
bool invalid; bool invalid;
struct list_head list; struct list_head list;
u32 size;
}; };
/** /**
...@@ -135,46 +133,32 @@ struct isr_statistics { ...@@ -135,46 +133,32 @@ struct isr_statistics {
u32 unhandled; u32 unhandled;
}; };
#define IWL_RX_TD_TYPE_MSK 0xff000000
#define IWL_RX_TD_SIZE_MSK 0x00ffffff
#define IWL_RX_TD_SIZE_2K BIT(11)
#define IWL_RX_TD_TYPE 0
/** /**
* struct iwl_rx_transfer_desc - transfer descriptor * struct iwl_rx_transfer_desc - transfer descriptor
* @type_n_size: buffer type (bit 0: external buff valid,
* bit 1: optional footer valid, bit 2-7: reserved)
* and buffer size
* @addr: ptr to free buffer start address * @addr: ptr to free buffer start address
* @rbid: unique tag of the buffer * @rbid: unique tag of the buffer
* @reserved: reserved * @reserved: reserved
*/ */
struct iwl_rx_transfer_desc { struct iwl_rx_transfer_desc {
__le32 type_n_size;
__le64 addr;
__le16 rbid; __le16 rbid;
__le16 reserved; __le16 reserved[3];
__le64 addr;
} __packed; } __packed;
#define IWL_RX_CD_SIZE 0xffffff00 #define IWL_RX_CD_FLAGS_FRAGMENTED BIT(0)
/** /**
* struct iwl_rx_completion_desc - completion descriptor * struct iwl_rx_completion_desc - completion descriptor
* @type: buffer type (bit 0: external buff valid,
* bit 1: optional footer valid, bit 2-7: reserved)
* @status: status of the completion
* @reserved1: reserved * @reserved1: reserved
* @rbid: unique tag of the received buffer * @rbid: unique tag of the received buffer
* @size: buffer size, masked by IWL_RX_CD_SIZE * @flags: flags (0: fragmented, all others: reserved)
* @reserved2: reserved * @reserved2: reserved
*/ */
struct iwl_rx_completion_desc { struct iwl_rx_completion_desc {
u8 type; __le32 reserved1;
u8 status;
__le16 reserved1;
__le16 rbid; __le16 rbid;
__le32 size; u8 flags;
u8 reserved2[22]; u8 reserved2[25];
} __packed; } __packed;
/** /**
......
...@@ -282,9 +282,8 @@ static void iwl_pcie_restock_bd(struct iwl_trans *trans, ...@@ -282,9 +282,8 @@ static void iwl_pcie_restock_bd(struct iwl_trans *trans,
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) { if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) {
struct iwl_rx_transfer_desc *bd = rxq->bd; struct iwl_rx_transfer_desc *bd = rxq->bd;
bd[rxq->write].type_n_size = BUILD_BUG_ON(sizeof(*bd) != 2 * sizeof(u64));
cpu_to_le32((IWL_RX_TD_TYPE & IWL_RX_TD_TYPE_MSK) |
((IWL_RX_TD_SIZE_2K >> 8) & IWL_RX_TD_SIZE_MSK));
bd[rxq->write].addr = cpu_to_le64(rxb->page_dma); bd[rxq->write].addr = cpu_to_le64(rxb->page_dma);
bd[rxq->write].rbid = cpu_to_le16(rxb->vid); bd[rxq->write].rbid = cpu_to_le16(rxb->vid);
} else { } else {
...@@ -1265,9 +1264,6 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans, ...@@ -1265,9 +1264,6 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans,
.truesize = max_len, .truesize = max_len,
}; };
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560)
rxcb.status = rxq->cd[i].status;
pkt = rxb_addr(&rxcb); pkt = rxb_addr(&rxcb);
if (pkt->len_n_flags == cpu_to_le32(FH_RSCSR_FRAME_INVALID)) { if (pkt->len_n_flags == cpu_to_le32(FH_RSCSR_FRAME_INVALID)) {
...@@ -1394,6 +1390,8 @@ static struct iwl_rx_mem_buffer *iwl_pcie_get_rxb(struct iwl_trans *trans, ...@@ -1394,6 +1390,8 @@ static struct iwl_rx_mem_buffer *iwl_pcie_get_rxb(struct iwl_trans *trans,
struct iwl_rx_mem_buffer *rxb; struct iwl_rx_mem_buffer *rxb;
u16 vid; u16 vid;
BUILD_BUG_ON(sizeof(struct iwl_rx_completion_desc) != 32);
if (!trans->cfg->mq_rx_supported) { if (!trans->cfg->mq_rx_supported) {
rxb = rxq->queue[i]; rxb = rxq->queue[i];
rxq->queue[i] = NULL; rxq->queue[i] = NULL;
...@@ -1415,9 +1413,6 @@ static struct iwl_rx_mem_buffer *iwl_pcie_get_rxb(struct iwl_trans *trans, ...@@ -1415,9 +1413,6 @@ static struct iwl_rx_mem_buffer *iwl_pcie_get_rxb(struct iwl_trans *trans,
IWL_DEBUG_RX(trans, "Got virtual RB ID %u\n", (u32)rxb->vid); IWL_DEBUG_RX(trans, "Got virtual RB ID %u\n", (u32)rxb->vid);
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560)
rxb->size = le32_to_cpu(rxq->cd[i].size) & IWL_RX_CD_SIZE;
rxb->invalid = true; rxb->invalid = true;
return rxb; return rxb;
......
...@@ -3012,10 +3012,14 @@ static void ...@@ -3012,10 +3012,14 @@ static void
iwl_trans_pcie_dump_pointers(struct iwl_trans *trans, iwl_trans_pcie_dump_pointers(struct iwl_trans *trans,
struct iwl_fw_error_dump_fw_mon *fw_mon_data) struct iwl_fw_error_dump_fw_mon *fw_mon_data)
{ {
u32 base, write_ptr, wrap_cnt; u32 base, base_high, write_ptr, write_ptr_val, wrap_cnt;
/* If there was a dest TLV - use the values from there */ if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
if (trans->ini_valid) { base = DBGC_CUR_DBGBUF_BASE_ADDR_LSB;
base_high = DBGC_CUR_DBGBUF_BASE_ADDR_MSB;
write_ptr = DBGC_CUR_DBGBUF_STATUS;
wrap_cnt = DBGC_DBGBUF_WRAP_AROUND;
} else if (trans->ini_valid) {
base = iwl_umac_prph(trans, MON_BUFF_BASE_ADDR_VER2); base = iwl_umac_prph(trans, MON_BUFF_BASE_ADDR_VER2);
write_ptr = iwl_umac_prph(trans, MON_BUFF_WRPTR_VER2); write_ptr = iwl_umac_prph(trans, MON_BUFF_WRPTR_VER2);
wrap_cnt = iwl_umac_prph(trans, MON_BUFF_CYCLE_CNT_VER2); wrap_cnt = iwl_umac_prph(trans, MON_BUFF_CYCLE_CNT_VER2);
...@@ -3028,12 +3032,18 @@ iwl_trans_pcie_dump_pointers(struct iwl_trans *trans, ...@@ -3028,12 +3032,18 @@ iwl_trans_pcie_dump_pointers(struct iwl_trans *trans,
write_ptr = MON_BUFF_WRPTR; write_ptr = MON_BUFF_WRPTR;
wrap_cnt = MON_BUFF_CYCLE_CNT; wrap_cnt = MON_BUFF_CYCLE_CNT;
} }
fw_mon_data->fw_mon_wr_ptr =
cpu_to_le32(iwl_read_prph(trans, write_ptr)); write_ptr_val = iwl_read_prph(trans, write_ptr);
fw_mon_data->fw_mon_cycle_cnt = fw_mon_data->fw_mon_cycle_cnt =
cpu_to_le32(iwl_read_prph(trans, wrap_cnt)); cpu_to_le32(iwl_read_prph(trans, wrap_cnt));
fw_mon_data->fw_mon_base_ptr = fw_mon_data->fw_mon_base_ptr =
cpu_to_le32(iwl_read_prph(trans, base)); cpu_to_le32(iwl_read_prph(trans, base));
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
fw_mon_data->fw_mon_base_high_ptr =
cpu_to_le32(iwl_read_prph(trans, base_high));
write_ptr_val &= DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK;
}
fw_mon_data->fw_mon_wr_ptr = cpu_to_le32(write_ptr_val);
} }
static u32 static u32
...@@ -3044,9 +3054,10 @@ iwl_trans_pcie_dump_monitor(struct iwl_trans *trans, ...@@ -3044,9 +3054,10 @@ iwl_trans_pcie_dump_monitor(struct iwl_trans *trans,
u32 len = 0; u32 len = 0;
if ((trans->num_blocks && if ((trans->num_blocks &&
trans->cfg->device_family == IWL_DEVICE_FAMILY_7000) || (trans->cfg->device_family == IWL_DEVICE_FAMILY_7000 ||
(trans->dbg_dest_tlv && !trans->ini_valid) || trans->cfg->device_family >= IWL_DEVICE_FAMILY_AX210 ||
(trans->ini_valid && trans->num_blocks)) { trans->ini_valid)) ||
(trans->dbg_dest_tlv && !trans->ini_valid)) {
struct iwl_fw_error_dump_fw_mon *fw_mon_data; struct iwl_fw_error_dump_fw_mon *fw_mon_data;
(*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_FW_MONITOR); (*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_FW_MONITOR);
...@@ -3165,8 +3176,10 @@ static struct iwl_trans_dump_data ...@@ -3165,8 +3176,10 @@ static struct iwl_trans_dump_data
len = sizeof(*dump_data); len = sizeof(*dump_data);
/* host commands */ /* host commands */
len += sizeof(*data) + if (dump_mask & BIT(IWL_FW_ERROR_DUMP_TXCMD))
cmdq->n_window * (sizeof(*txcmd) + TFD_MAX_PAYLOAD_SIZE); len += sizeof(*data) +
cmdq->n_window * (sizeof(*txcmd) +
TFD_MAX_PAYLOAD_SIZE);
/* FW monitor */ /* FW monitor */
if (dump_mask & BIT(IWL_FW_ERROR_DUMP_FW_MONITOR)) if (dump_mask & BIT(IWL_FW_ERROR_DUMP_FW_MONITOR))
...@@ -3539,6 +3552,9 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, ...@@ -3539,6 +3552,9 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
} else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) == } else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) ==
CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_GF)) { CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_GF)) {
trans->cfg = &iwlax210_2ax_cfg_so_gf_a0; trans->cfg = &iwlax210_2ax_cfg_so_gf_a0;
} else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) ==
CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_GF4)) {
trans->cfg = &iwlax210_2ax_cfg_so_gf4_a0;
} }
} else if (cfg == &iwl_ax101_cfg_qu_hr) { } else if (cfg == &iwl_ax101_cfg_qu_hr) {
if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) == if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) ==
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment