wireless-drivers-next patches for 5.3
Second, and last, set of patches for 5.3. Major changes: mt76 * use NAPI polling for tx cleanup on mt7603/mt7615 * add support for toggling edcca on mt7603 * fix rate control / tx status reporting issues on mt76x02/mt7603 * add support for eeprom calibration data from mtd on mt7615 * support configuring tx power on mt7615 * per-chain signal reporting on mt7615 iwlwifi * Update the FW API for Channel State Information (CSI) * Special Specific Absorption Rate (SAR) implementation for South Korea ath10k * fixes for SDIO support * add support for firmware logging via WMI -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJdIEMUAAoJEG4XJFUm622bYLsIAI7SOgbSvyuxi/SRk6PXZ5KI WVqoQ0Jzt61C7gr2324lbExbQA4OoHaJfusyzIUwWifP55W83iYGHgLCXUKnBvng /LehHN6satVBC0JMReLmuVE7Ac+4aPdFw9WbS4QneZwLr90CzjXgPebiKchFOI5V 1PwPfN0nG/NKJac2vv6/Y8gERyj5i4ZvYipGMQCiKRHFrb7FRRhxwI3uG1BkeR1r i7QjUiQXG5RmeXd2QWJg/MkwZY5XKNqYxZyXUhBRy8kUH75poAEJ8ll3KIrAvJ87 0r3YnDlhyxseShYDzcKt1bgVcqEkJVGhHPaadq2nkmys5NKoKiuTYD1Jj7089jQ= =OVjU -----END PGP SIGNATURE----- Merge tag 'wireless-drivers-next-for-davem-2019-07-06' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next Kalle Valo says: ==================== wireless-drivers-next patches for 5.3 Second, and last, set of patches for 5.3. Major changes: mt76 * use NAPI polling for tx cleanup on mt7603/mt7615 * add support for toggling edcca on mt7603 * fix rate control / tx status reporting issues on mt76x02/mt7603 * add support for eeprom calibration data from mtd on mt7615 * support configuring tx power on mt7615 * per-chain signal reporting on mt7615 iwlwifi * Update the FW API for Channel State Information (CSI) * Special Specific Absorption Rate (SAR) implementation for South Korea ath10k * fixes for SDIO support * add support for firmware logging via WMI ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
437fde6cda
|
@ -2,7 +2,7 @@
|
|||
/*
|
||||
* Copyright (c) 2005-2011 Atheros Communications Inc.
|
||||
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
|
||||
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
@ -26,10 +26,13 @@
|
|||
#include "coredump.h"
|
||||
|
||||
unsigned int ath10k_debug_mask;
|
||||
EXPORT_SYMBOL(ath10k_debug_mask);
|
||||
|
||||
static unsigned int ath10k_cryptmode_param;
|
||||
static bool uart_print;
|
||||
static bool skip_otp;
|
||||
static bool rawmode;
|
||||
static bool fw_diag_log;
|
||||
|
||||
unsigned long ath10k_coredump_mask = BIT(ATH10K_FW_CRASH_DUMP_REGISTERS) |
|
||||
BIT(ATH10K_FW_CRASH_DUMP_CE_DATA);
|
||||
|
@ -40,6 +43,7 @@ module_param_named(cryptmode, ath10k_cryptmode_param, uint, 0644);
|
|||
module_param(uart_print, bool, 0644);
|
||||
module_param(skip_otp, bool, 0644);
|
||||
module_param(rawmode, bool, 0644);
|
||||
module_param(fw_diag_log, bool, 0644);
|
||||
module_param_named(coredump_mask, ath10k_coredump_mask, ulong, 0444);
|
||||
|
||||
MODULE_PARM_DESC(debug_mask, "Debugging mask");
|
||||
|
@ -48,6 +52,7 @@ MODULE_PARM_DESC(skip_otp, "Skip otp failure for calibration in testmode");
|
|||
MODULE_PARM_DESC(cryptmode, "Crypto mode: 0-hardware, 1-software");
|
||||
MODULE_PARM_DESC(rawmode, "Use raw 802.11 frame datapath");
|
||||
MODULE_PARM_DESC(coredump_mask, "Bitfield of what to include in firmware crash file");
|
||||
MODULE_PARM_DESC(fw_diag_log, "Diag based fw log debugging");
|
||||
|
||||
static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
{
|
||||
|
@ -83,6 +88,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
|||
.rri_on_ddr = false,
|
||||
.hw_filter_reset_required = true,
|
||||
.fw_diag_ce_download = false,
|
||||
.tx_stats_over_pktlog = true,
|
||||
},
|
||||
{
|
||||
.id = QCA988X_HW_2_0_VERSION,
|
||||
|
@ -117,6 +123,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
|||
.rri_on_ddr = false,
|
||||
.hw_filter_reset_required = true,
|
||||
.fw_diag_ce_download = false,
|
||||
.tx_stats_over_pktlog = true,
|
||||
},
|
||||
{
|
||||
.id = QCA9887_HW_1_0_VERSION,
|
||||
|
@ -152,6 +159,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
|||
.rri_on_ddr = false,
|
||||
.hw_filter_reset_required = true,
|
||||
.fw_diag_ce_download = false,
|
||||
.tx_stats_over_pktlog = false,
|
||||
},
|
||||
{
|
||||
.id = QCA6174_HW_3_2_VERSION,
|
||||
|
@ -170,7 +178,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
|||
.board_size = QCA6174_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA6174_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
.hw_ops = &qca6174_ops,
|
||||
.hw_ops = &qca6174_sdio_ops,
|
||||
.hw_clk = qca6174_clk,
|
||||
.target_cpu_freq = 176000000,
|
||||
.decap_align_bytes = 4,
|
||||
|
@ -179,6 +187,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
|||
.ast_skid_limit = 0x10,
|
||||
.num_wds_entries = 0x20,
|
||||
.uart_pin_workaround = true,
|
||||
.tx_stats_over_pktlog = false,
|
||||
},
|
||||
{
|
||||
.id = QCA6174_HW_2_1_VERSION,
|
||||
|
@ -213,6 +222,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
|||
.rri_on_ddr = false,
|
||||
.hw_filter_reset_required = true,
|
||||
.fw_diag_ce_download = false,
|
||||
.tx_stats_over_pktlog = false,
|
||||
},
|
||||
{
|
||||
.id = QCA6174_HW_2_1_VERSION,
|
||||
|
@ -247,6 +257,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
|||
.rri_on_ddr = false,
|
||||
.hw_filter_reset_required = true,
|
||||
.fw_diag_ce_download = false,
|
||||
.tx_stats_over_pktlog = false,
|
||||
},
|
||||
{
|
||||
.id = QCA6174_HW_3_0_VERSION,
|
||||
|
@ -281,6 +292,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
|||
.rri_on_ddr = false,
|
||||
.hw_filter_reset_required = true,
|
||||
.fw_diag_ce_download = false,
|
||||
.tx_stats_over_pktlog = false,
|
||||
},
|
||||
{
|
||||
.id = QCA6174_HW_3_2_VERSION,
|
||||
|
@ -318,6 +330,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
|||
.rri_on_ddr = false,
|
||||
.hw_filter_reset_required = true,
|
||||
.fw_diag_ce_download = true,
|
||||
.tx_stats_over_pktlog = false,
|
||||
},
|
||||
{
|
||||
.id = QCA99X0_HW_2_0_DEV_VERSION,
|
||||
|
@ -358,6 +371,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
|||
.rri_on_ddr = false,
|
||||
.hw_filter_reset_required = true,
|
||||
.fw_diag_ce_download = false,
|
||||
.tx_stats_over_pktlog = false,
|
||||
},
|
||||
{
|
||||
.id = QCA9984_HW_1_0_DEV_VERSION,
|
||||
|
@ -405,6 +419,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
|||
.rri_on_ddr = false,
|
||||
.hw_filter_reset_required = true,
|
||||
.fw_diag_ce_download = false,
|
||||
.tx_stats_over_pktlog = false,
|
||||
},
|
||||
{
|
||||
.id = QCA9888_HW_2_0_DEV_VERSION,
|
||||
|
@ -449,6 +464,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
|||
.rri_on_ddr = false,
|
||||
.hw_filter_reset_required = true,
|
||||
.fw_diag_ce_download = false,
|
||||
.tx_stats_over_pktlog = false,
|
||||
},
|
||||
{
|
||||
.id = QCA9377_HW_1_0_DEV_VERSION,
|
||||
|
@ -483,6 +499,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
|||
.rri_on_ddr = false,
|
||||
.hw_filter_reset_required = true,
|
||||
.fw_diag_ce_download = false,
|
||||
.tx_stats_over_pktlog = false,
|
||||
},
|
||||
{
|
||||
.id = QCA9377_HW_1_1_DEV_VERSION,
|
||||
|
@ -519,6 +536,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
|||
.rri_on_ddr = false,
|
||||
.hw_filter_reset_required = true,
|
||||
.fw_diag_ce_download = true,
|
||||
.tx_stats_over_pktlog = false,
|
||||
},
|
||||
{
|
||||
.id = QCA4019_HW_1_0_DEV_VERSION,
|
||||
|
@ -560,6 +578,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
|||
.rri_on_ddr = false,
|
||||
.hw_filter_reset_required = true,
|
||||
.fw_diag_ce_download = false,
|
||||
.tx_stats_over_pktlog = false,
|
||||
},
|
||||
{
|
||||
.id = WCN3990_HW_1_0_DEV_VERSION,
|
||||
|
@ -587,6 +606,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
|||
.rri_on_ddr = true,
|
||||
.hw_filter_reset_required = false,
|
||||
.fw_diag_ce_download = false,
|
||||
.tx_stats_over_pktlog = false,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -612,6 +632,7 @@ static const char *const ath10k_core_fw_feature_str[] = {
|
|||
[ATH10K_FW_FEATURE_MGMT_TX_BY_REF] = "mgmt-tx-by-reference",
|
||||
[ATH10K_FW_FEATURE_NON_BMI] = "non-bmi",
|
||||
[ATH10K_FW_FEATURE_SINGLE_CHAN_INFO_PER_CHANNEL] = "single-chan-info-per-channel",
|
||||
[ATH10K_FW_FEATURE_PEER_FIXED_RATE] = "peer-fixed-rate",
|
||||
};
|
||||
|
||||
static unsigned int ath10k_core_get_fw_feature_str(char *buf,
|
||||
|
@ -2179,6 +2200,7 @@ static void ath10k_core_restart(struct work_struct *work)
|
|||
complete(&ar->offchan_tx_completed);
|
||||
complete(&ar->install_key_done);
|
||||
complete(&ar->vdev_setup_done);
|
||||
complete(&ar->vdev_delete_done);
|
||||
complete(&ar->thermal.wmi_sync);
|
||||
complete(&ar->bss_survey_done);
|
||||
wake_up(&ar->htt.empty_tx_wq);
|
||||
|
@ -2760,6 +2782,12 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
|
|||
if (status)
|
||||
goto err_hif_stop;
|
||||
|
||||
status = ath10k_hif_set_target_log_mode(ar, fw_diag_log);
|
||||
if (status && status != -EOPNOTSUPP) {
|
||||
ath10k_warn(ar, "set traget log mode faileds: %d\n", status);
|
||||
goto err_hif_stop;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_hif_stop:
|
||||
|
@ -3145,8 +3173,10 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
|
|||
|
||||
init_completion(&ar->install_key_done);
|
||||
init_completion(&ar->vdev_setup_done);
|
||||
init_completion(&ar->vdev_delete_done);
|
||||
init_completion(&ar->thermal.wmi_sync);
|
||||
init_completion(&ar->bss_survey_done);
|
||||
init_completion(&ar->peer_delete_done);
|
||||
|
||||
INIT_DELAYED_WORK(&ar->scan.timeout, ath10k_scan_timeout_work);
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
/*
|
||||
* Copyright (c) 2005-2011 Atheros Communications Inc.
|
||||
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
|
||||
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CORE_H_
|
||||
|
@ -514,7 +514,8 @@ struct ath10k_sta {
|
|||
u32 peer_ps_state;
|
||||
};
|
||||
|
||||
#define ATH10K_VDEV_SETUP_TIMEOUT_HZ (5 * HZ)
|
||||
#define ATH10K_VDEV_SETUP_TIMEOUT_HZ (5 * HZ)
|
||||
#define ATH10K_VDEV_DELETE_TIMEOUT_HZ (5 * HZ)
|
||||
|
||||
enum ath10k_beacon_state {
|
||||
ATH10K_BEACON_SCHEDULED = 0,
|
||||
|
@ -579,6 +580,10 @@ struct ath10k_vif {
|
|||
struct work_struct ap_csa_work;
|
||||
struct delayed_work connection_loss_work;
|
||||
struct cfg80211_bitrate_mask bitrate_mask;
|
||||
|
||||
/* For setting VHT peer fixed rate, protected by conf_mutex */
|
||||
int vht_num_rates;
|
||||
u8 vht_pfr;
|
||||
};
|
||||
|
||||
struct ath10k_vif_iter {
|
||||
|
@ -640,6 +645,7 @@ struct ath10k_debug {
|
|||
u32 nf_cal_period;
|
||||
void *cal_data;
|
||||
u32 enable_extd_tx_stats;
|
||||
u8 fw_dbglog_mode;
|
||||
};
|
||||
|
||||
enum ath10k_state {
|
||||
|
@ -770,6 +776,9 @@ enum ath10k_fw_features {
|
|||
/* Firmware sends only one chan_info event per channel */
|
||||
ATH10K_FW_FEATURE_SINGLE_CHAN_INFO_PER_CHANNEL = 20,
|
||||
|
||||
/* Firmware allows setting peer fixed rate */
|
||||
ATH10K_FW_FEATURE_PEER_FIXED_RATE = 21,
|
||||
|
||||
/* keep last */
|
||||
ATH10K_FW_FEATURE_COUNT,
|
||||
};
|
||||
|
@ -1065,6 +1074,7 @@ struct ath10k {
|
|||
|
||||
int last_wmi_vdev_start_status;
|
||||
struct completion vdev_setup_done;
|
||||
struct completion vdev_delete_done;
|
||||
|
||||
struct workqueue_struct *workqueue;
|
||||
/* Auxiliary workqueue */
|
||||
|
@ -1199,6 +1209,7 @@ struct ath10k {
|
|||
struct ath10k_radar_found_info last_radar_info;
|
||||
struct work_struct radar_confirmation_work;
|
||||
struct ath10k_bus_params bus_param;
|
||||
struct completion peer_delete_done;
|
||||
|
||||
/* must be last */
|
||||
u8 drv_priv[0] __aligned(sizeof(void *));
|
||||
|
|
|
@ -2664,8 +2664,8 @@ void ath10k_debug_unregister(struct ath10k *ar)
|
|||
#endif /* CONFIG_ATH10K_DEBUGFS */
|
||||
|
||||
#ifdef CONFIG_ATH10K_DEBUG
|
||||
void ath10k_dbg(struct ath10k *ar, enum ath10k_debug_mask mask,
|
||||
const char *fmt, ...)
|
||||
void __ath10k_dbg(struct ath10k *ar, enum ath10k_debug_mask mask,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
struct va_format vaf;
|
||||
va_list args;
|
||||
|
@ -2682,7 +2682,7 @@ void ath10k_dbg(struct ath10k *ar, enum ath10k_debug_mask mask,
|
|||
|
||||
va_end(args);
|
||||
}
|
||||
EXPORT_SYMBOL(ath10k_dbg);
|
||||
EXPORT_SYMBOL(__ath10k_dbg);
|
||||
|
||||
void ath10k_dbg_dump(struct ath10k *ar,
|
||||
enum ath10k_debug_mask mask,
|
||||
|
@ -2695,7 +2695,7 @@ void ath10k_dbg_dump(struct ath10k *ar,
|
|||
|
||||
if (ath10k_debug_mask & mask) {
|
||||
if (msg)
|
||||
ath10k_dbg(ar, mask, "%s\n", msg);
|
||||
__ath10k_dbg(ar, mask, "%s\n", msg);
|
||||
|
||||
for (ptr = buf; (ptr - buf) < len; ptr += 16) {
|
||||
linebuflen = 0;
|
||||
|
|
|
@ -71,6 +71,9 @@ struct ath10k_pktlog_hdr {
|
|||
/* FIXME: How to calculate the buffer size sanely? */
|
||||
#define ATH10K_FW_STATS_BUF_SIZE (1024 * 1024)
|
||||
|
||||
#define ATH10K_TX_POWER_MAX_VAL 70
|
||||
#define ATH10K_TX_POWER_MIN_VAL 0
|
||||
|
||||
extern unsigned int ath10k_debug_mask;
|
||||
|
||||
__printf(2, 3) void ath10k_info(struct ath10k *ar, const char *fmt, ...);
|
||||
|
@ -240,18 +243,18 @@ void ath10k_sta_update_rx_tid_stats_ampdu(struct ath10k *ar,
|
|||
#endif /* CONFIG_MAC80211_DEBUGFS */
|
||||
|
||||
#ifdef CONFIG_ATH10K_DEBUG
|
||||
__printf(3, 4) void ath10k_dbg(struct ath10k *ar,
|
||||
enum ath10k_debug_mask mask,
|
||||
const char *fmt, ...);
|
||||
__printf(3, 4) void __ath10k_dbg(struct ath10k *ar,
|
||||
enum ath10k_debug_mask mask,
|
||||
const char *fmt, ...);
|
||||
void ath10k_dbg_dump(struct ath10k *ar,
|
||||
enum ath10k_debug_mask mask,
|
||||
const char *msg, const char *prefix,
|
||||
const void *buf, size_t len);
|
||||
#else /* CONFIG_ATH10K_DEBUG */
|
||||
|
||||
static inline int ath10k_dbg(struct ath10k *ar,
|
||||
enum ath10k_debug_mask dbg_mask,
|
||||
const char *fmt, ...)
|
||||
static inline int __ath10k_dbg(struct ath10k *ar,
|
||||
enum ath10k_debug_mask dbg_mask,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -263,4 +266,14 @@ static inline void ath10k_dbg_dump(struct ath10k *ar,
|
|||
{
|
||||
}
|
||||
#endif /* CONFIG_ATH10K_DEBUG */
|
||||
|
||||
/* Avoid calling __ath10k_dbg() if debug_mask is not set and tracing
|
||||
* disabled.
|
||||
*/
|
||||
#define ath10k_dbg(ar, dbg_mask, fmt, ...) \
|
||||
do { \
|
||||
if ((ath10k_debug_mask & dbg_mask) || \
|
||||
trace_ath10k_log_dbg_enabled()) \
|
||||
__ath10k_dbg(ar, dbg_mask, fmt, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#endif /* _DEBUG_H_ */
|
||||
|
|
|
@ -12,6 +12,12 @@
|
|||
#include "bmi.h"
|
||||
#include "debug.h"
|
||||
|
||||
/* Types of fw logging mode */
|
||||
enum ath_dbg_mode {
|
||||
ATH10K_ENABLE_FW_LOG_DIAG,
|
||||
ATH10K_ENABLE_FW_LOG_CE,
|
||||
};
|
||||
|
||||
struct ath10k_hif_sg_item {
|
||||
u16 transfer_id;
|
||||
void *transfer_context; /* NULL = tx completion callback not called */
|
||||
|
@ -88,6 +94,7 @@ struct ath10k_hif_ops {
|
|||
|
||||
int (*get_target_info)(struct ath10k *ar,
|
||||
struct bmi_target_info *target_info);
|
||||
int (*set_target_log_mode)(struct ath10k *ar, u8 fw_log_mode);
|
||||
};
|
||||
|
||||
static inline int ath10k_hif_tx_sg(struct ath10k *ar, u8 pipe_id,
|
||||
|
@ -230,4 +237,12 @@ static inline int ath10k_hif_get_target_info(struct ath10k *ar,
|
|||
return ar->hif.ops->get_target_info(ar, tgt_info);
|
||||
}
|
||||
|
||||
static inline int ath10k_hif_set_target_log_mode(struct ath10k *ar,
|
||||
u8 fw_log_mode)
|
||||
{
|
||||
if (!ar->hif.ops->set_target_log_mode)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return ar->hif.ops->set_target_log_mode(ar, fw_log_mode);
|
||||
}
|
||||
#endif /* _HIF_H_ */
|
||||
|
|
|
@ -257,7 +257,7 @@ int ath10k_htt_setup(struct ath10k_htt *htt)
|
|||
return status;
|
||||
}
|
||||
|
||||
status = htt->tx_ops->htt_h2t_aggr_cfg_msg(htt,
|
||||
status = ath10k_htt_h2t_aggr_cfg_msg(htt,
|
||||
htt->max_num_ampdu,
|
||||
htt->max_num_amsdu);
|
||||
if (status) {
|
||||
|
|
|
@ -2086,6 +2086,19 @@ static inline void ath10k_htt_free_txbuff(struct ath10k_htt *htt)
|
|||
htt->tx_ops->htt_free_txbuff(htt);
|
||||
}
|
||||
|
||||
static inline int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt,
|
||||
u8 max_subfrms_ampdu,
|
||||
u8 max_subfrms_amsdu)
|
||||
|
||||
{
|
||||
if (!htt->tx_ops->htt_h2t_aggr_cfg_msg)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return htt->tx_ops->htt_h2t_aggr_cfg_msg(htt,
|
||||
max_subfrms_ampdu,
|
||||
max_subfrms_amsdu);
|
||||
}
|
||||
|
||||
struct ath10k_htt_rx_ops {
|
||||
size_t (*htt_get_rx_ring_size)(struct ath10k_htt *htt);
|
||||
void (*htt_config_paddrs_ring)(struct ath10k_htt *htt, void *vaddr);
|
||||
|
@ -2246,9 +2259,6 @@ bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb);
|
|||
int ath10k_htt_h2t_ver_req_msg(struct ath10k_htt *htt);
|
||||
int ath10k_htt_h2t_stats_req(struct ath10k_htt *htt, u32 mask, u32 reset_mask,
|
||||
u64 cookie);
|
||||
int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt,
|
||||
u8 max_subfrms_ampdu,
|
||||
u8 max_subfrms_amsdu);
|
||||
void ath10k_htt_hif_tx_complete(struct ath10k *ar, struct sk_buff *skb);
|
||||
int ath10k_htt_tx_fetch_resp(struct ath10k *ar,
|
||||
__le32 token,
|
||||
|
|
|
@ -2158,13 +2158,14 @@ static bool ath10k_htt_rx_proc_rx_ind_hl(struct ath10k_htt *htt,
|
|||
int num_mpdu_ranges;
|
||||
size_t tot_hdr_len;
|
||||
struct ieee80211_channel *ch;
|
||||
bool pn_invalid;
|
||||
|
||||
peer_id = __le16_to_cpu(rx->hdr.peer_id);
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
peer = ath10k_peer_find_by_id(ar, peer_id);
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
if (!peer)
|
||||
if (!peer && peer_id != HTT_INVALID_PEERID)
|
||||
ath10k_warn(ar, "Got RX ind from invalid peer: %u\n", peer_id);
|
||||
|
||||
num_mpdu_ranges = MS(__le32_to_cpu(rx->hdr.info1),
|
||||
|
@ -2183,15 +2184,21 @@ static bool ath10k_htt_rx_proc_rx_ind_hl(struct ath10k_htt *htt,
|
|||
num_mpdu_ranges);
|
||||
|
||||
if (mpdu_ranges->mpdu_range_status !=
|
||||
HTT_RX_IND_MPDU_STATUS_OK) {
|
||||
HTT_RX_IND_MPDU_STATUS_OK &&
|
||||
mpdu_ranges->mpdu_range_status !=
|
||||
HTT_RX_IND_MPDU_STATUS_TKIP_MIC_ERR) {
|
||||
ath10k_warn(ar, "MPDU range status: %d\n",
|
||||
mpdu_ranges->mpdu_range_status);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (check_pn_type == HTT_RX_PN_CHECK &&
|
||||
ath10k_htt_rx_pn_check_replay_hl(ar, peer, rx))
|
||||
goto err;
|
||||
if (check_pn_type == HTT_RX_PN_CHECK) {
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
pn_invalid = ath10k_htt_rx_pn_check_replay_hl(ar, peer, rx);
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
if (pn_invalid)
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Strip off all headers before the MAC header before delivery to
|
||||
* mac80211
|
||||
|
@ -2253,6 +2260,9 @@ static bool ath10k_htt_rx_proc_rx_ind_hl(struct ath10k_htt *htt,
|
|||
rx_status->flag &= ~RX_FLAG_IV_STRIPPED &
|
||||
~RX_FLAG_MMIC_STRIPPED;
|
||||
|
||||
if (mpdu_ranges->mpdu_range_status == HTT_RX_IND_MPDU_STATUS_TKIP_MIC_ERR)
|
||||
rx_status->flag |= RX_FLAG_MMIC_ERROR;
|
||||
|
||||
ieee80211_rx_ni(ar->hw, skb);
|
||||
|
||||
/* We have delivered the skb to the upper layers (mac80211) so we
|
||||
|
|
|
@ -978,9 +978,9 @@ static int ath10k_htt_send_rx_ring_cfg_hl(struct ath10k_htt *htt)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt,
|
||||
u8 max_subfrms_ampdu,
|
||||
u8 max_subfrms_amsdu)
|
||||
static int ath10k_htt_h2t_aggr_cfg_msg_32(struct ath10k_htt *htt,
|
||||
u8 max_subfrms_ampdu,
|
||||
u8 max_subfrms_amsdu)
|
||||
{
|
||||
struct ath10k *ar = htt->ar;
|
||||
struct htt_aggr_conf *aggr_conf;
|
||||
|
@ -1747,7 +1747,7 @@ static const struct ath10k_htt_tx_ops htt_tx_ops_32 = {
|
|||
.htt_tx = ath10k_htt_tx_32,
|
||||
.htt_alloc_txbuff = ath10k_htt_tx_alloc_cont_txbuf_32,
|
||||
.htt_free_txbuff = ath10k_htt_tx_free_cont_txbuf_32,
|
||||
.htt_h2t_aggr_cfg_msg = ath10k_htt_h2t_aggr_cfg_msg,
|
||||
.htt_h2t_aggr_cfg_msg = ath10k_htt_h2t_aggr_cfg_msg_32,
|
||||
};
|
||||
|
||||
static const struct ath10k_htt_tx_ops htt_tx_ops_64 = {
|
||||
|
@ -1765,6 +1765,7 @@ static const struct ath10k_htt_tx_ops htt_tx_ops_hl = {
|
|||
.htt_send_rx_ring_cfg = ath10k_htt_send_rx_ring_cfg_hl,
|
||||
.htt_send_frag_desc_bank_cfg = ath10k_htt_send_frag_desc_bank_cfg_32,
|
||||
.htt_tx = ath10k_htt_tx_hl,
|
||||
.htt_h2t_aggr_cfg_msg = ath10k_htt_h2t_aggr_cfg_msg_32,
|
||||
};
|
||||
|
||||
void ath10k_htt_set_tx_ops(struct ath10k_htt *htt)
|
||||
|
|
|
@ -158,7 +158,7 @@ const struct ath10k_hw_values qca6174_values = {
|
|||
};
|
||||
|
||||
const struct ath10k_hw_values qca99x0_values = {
|
||||
.rtc_state_val_on = 5,
|
||||
.rtc_state_val_on = 7,
|
||||
.ce_count = 12,
|
||||
.msi_assign_ce_max = 12,
|
||||
.num_target_ce_config_wlan = 10,
|
||||
|
@ -1153,6 +1153,10 @@ const struct ath10k_hw_ops qca6174_ops = {
|
|||
.is_rssi_enable = ath10k_htt_tx_rssi_enable,
|
||||
};
|
||||
|
||||
const struct ath10k_hw_ops qca6174_sdio_ops = {
|
||||
.enable_pll_clk = ath10k_hw_qca6174_enable_pll_clock,
|
||||
};
|
||||
|
||||
const struct ath10k_hw_ops wcn3990_ops = {
|
||||
.tx_data_rssi_pad_bytes = ath10k_get_htt_tx_data_rssi_pad,
|
||||
.is_rssi_enable = ath10k_htt_tx_rssi_enable_wcn3990,
|
||||
|
|
|
@ -152,6 +152,8 @@ enum qca9377_chip_id_rev {
|
|||
#define ATH10K_FW_UTF_FILE "utf.bin"
|
||||
#define ATH10K_FW_UTF_API2_FILE "utf-2.bin"
|
||||
|
||||
#define ATH10K_FW_UTF_FILE_BASE "utf"
|
||||
|
||||
/* includes also the null byte */
|
||||
#define ATH10K_FIRMWARE_MAGIC "QCA-ATH10K"
|
||||
#define ATH10K_BOARD_MAGIC "QCA-ATH10K-BOARD"
|
||||
|
@ -612,6 +614,9 @@ struct ath10k_hw_params {
|
|||
* firmware bug
|
||||
*/
|
||||
bool uart_pin_workaround;
|
||||
|
||||
/* tx stats support over pktlog */
|
||||
bool tx_stats_over_pktlog;
|
||||
};
|
||||
|
||||
struct htt_rx_desc;
|
||||
|
@ -631,6 +636,7 @@ struct ath10k_hw_ops {
|
|||
extern const struct ath10k_hw_ops qca988x_ops;
|
||||
extern const struct ath10k_hw_ops qca99x0_ops;
|
||||
extern const struct ath10k_hw_ops qca6174_ops;
|
||||
extern const struct ath10k_hw_ops qca6174_sdio_ops;
|
||||
extern const struct ath10k_hw_ops wcn3990_ops;
|
||||
|
||||
extern const struct ath10k_hw_clk_params qca6174_clk[];
|
||||
|
@ -1101,6 +1107,7 @@ ath10k_is_rssi_enable(struct ath10k_hw_params *hw,
|
|||
#define MBOX_CPU_INT_STATUS_ENABLE_ADDRESS 0x00000819
|
||||
#define MBOX_CPU_INT_STATUS_ENABLE_BIT_LSB 0
|
||||
#define MBOX_CPU_INT_STATUS_ENABLE_BIT_MASK 0x000000ff
|
||||
#define MBOX_CPU_STATUS_ENABLE_ASSERT_MASK 0x00000001
|
||||
#define MBOX_ERROR_STATUS_ENABLE_ADDRESS 0x0000081a
|
||||
#define MBOX_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB 1
|
||||
#define MBOX_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK 0x00000002
|
||||
|
|
|
@ -693,6 +693,26 @@ ath10k_mac_get_any_chandef_iter(struct ieee80211_hw *hw,
|
|||
*def = &conf->def;
|
||||
}
|
||||
|
||||
static void ath10k_wait_for_peer_delete_done(struct ath10k *ar, u32 vdev_id,
|
||||
const u8 *addr)
|
||||
{
|
||||
unsigned long time_left;
|
||||
int ret;
|
||||
|
||||
if (test_bit(WMI_SERVICE_SYNC_DELETE_CMDS, ar->wmi.svc_map)) {
|
||||
ret = ath10k_wait_for_peer_deleted(ar, vdev_id, addr);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed wait for peer deleted");
|
||||
return;
|
||||
}
|
||||
|
||||
time_left = wait_for_completion_timeout(&ar->peer_delete_done,
|
||||
5 * HZ);
|
||||
if (!time_left)
|
||||
ath10k_warn(ar, "Timeout in receiving peer delete response\n");
|
||||
}
|
||||
}
|
||||
|
||||
static int ath10k_peer_create(struct ath10k *ar,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
|
@ -737,7 +757,7 @@ static int ath10k_peer_create(struct ath10k *ar,
|
|||
spin_unlock_bh(&ar->data_lock);
|
||||
ath10k_warn(ar, "failed to find peer %pM on vdev %i after creation\n",
|
||||
addr, vdev_id);
|
||||
ath10k_wmi_peer_delete(ar, vdev_id, addr);
|
||||
ath10k_wait_for_peer_delete_done(ar, vdev_id, addr);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
|
@ -819,6 +839,18 @@ static int ath10k_peer_delete(struct ath10k *ar, u32 vdev_id, const u8 *addr)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (test_bit(WMI_SERVICE_SYNC_DELETE_CMDS, ar->wmi.svc_map)) {
|
||||
unsigned long time_left;
|
||||
|
||||
time_left = wait_for_completion_timeout
|
||||
(&ar->peer_delete_done, 5 * HZ);
|
||||
|
||||
if (!time_left) {
|
||||
ath10k_warn(ar, "Timeout in receiving peer delete response\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
|
||||
ar->num_peers--;
|
||||
|
||||
return 0;
|
||||
|
@ -1011,6 +1043,7 @@ static int ath10k_monitor_vdev_start(struct ath10k *ar, int vdev_id)
|
|||
arg.channel.max_antenna_gain = channel->max_antenna_gain * 2;
|
||||
|
||||
reinit_completion(&ar->vdev_setup_done);
|
||||
reinit_completion(&ar->vdev_delete_done);
|
||||
|
||||
ret = ath10k_wmi_vdev_start(ar, &arg);
|
||||
if (ret) {
|
||||
|
@ -1060,6 +1093,7 @@ static int ath10k_monitor_vdev_stop(struct ath10k *ar)
|
|||
ar->monitor_vdev_id, ret);
|
||||
|
||||
reinit_completion(&ar->vdev_setup_done);
|
||||
reinit_completion(&ar->vdev_delete_done);
|
||||
|
||||
ret = ath10k_wmi_vdev_stop(ar, ar->monitor_vdev_id);
|
||||
if (ret)
|
||||
|
@ -1401,6 +1435,7 @@ static int ath10k_vdev_stop(struct ath10k_vif *arvif)
|
|||
lockdep_assert_held(&ar->conf_mutex);
|
||||
|
||||
reinit_completion(&ar->vdev_setup_done);
|
||||
reinit_completion(&ar->vdev_delete_done);
|
||||
|
||||
ret = ath10k_wmi_vdev_stop(ar, arvif->vdev_id);
|
||||
if (ret) {
|
||||
|
@ -1437,6 +1472,7 @@ static int ath10k_vdev_start_restart(struct ath10k_vif *arvif,
|
|||
lockdep_assert_held(&ar->conf_mutex);
|
||||
|
||||
reinit_completion(&ar->vdev_setup_done);
|
||||
reinit_completion(&ar->vdev_delete_done);
|
||||
|
||||
arg.vdev_id = arvif->vdev_id;
|
||||
arg.dtim_period = arvif->dtim_period;
|
||||
|
@ -5419,8 +5455,11 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
|
|||
|
||||
err_peer_delete:
|
||||
if (arvif->vdev_type == WMI_VDEV_TYPE_AP ||
|
||||
arvif->vdev_type == WMI_VDEV_TYPE_IBSS)
|
||||
arvif->vdev_type == WMI_VDEV_TYPE_IBSS) {
|
||||
ath10k_wmi_peer_delete(ar, arvif->vdev_id, vif->addr);
|
||||
ath10k_wait_for_peer_delete_done(ar, arvif->vdev_id,
|
||||
vif->addr);
|
||||
}
|
||||
|
||||
err_vdev_delete:
|
||||
ath10k_wmi_vdev_delete(ar, arvif->vdev_id);
|
||||
|
@ -5455,6 +5494,7 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw,
|
|||
struct ath10k *ar = hw->priv;
|
||||
struct ath10k_vif *arvif = (void *)vif->drv_priv;
|
||||
struct ath10k_peer *peer;
|
||||
unsigned long time_left;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
|
@ -5485,6 +5525,8 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw,
|
|||
ath10k_warn(ar, "failed to submit AP/IBSS self-peer removal on vdev %i: %d\n",
|
||||
arvif->vdev_id, ret);
|
||||
|
||||
ath10k_wait_for_peer_delete_done(ar, arvif->vdev_id,
|
||||
vif->addr);
|
||||
kfree(arvif->u.ap.noa_data);
|
||||
}
|
||||
|
||||
|
@ -5496,6 +5538,15 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw,
|
|||
ath10k_warn(ar, "failed to delete WMI vdev %i: %d\n",
|
||||
arvif->vdev_id, ret);
|
||||
|
||||
if (test_bit(WMI_SERVICE_SYNC_DELETE_CMDS, ar->wmi.svc_map)) {
|
||||
time_left = wait_for_completion_timeout(&ar->vdev_delete_done,
|
||||
ATH10K_VDEV_DELETE_TIMEOUT_HZ);
|
||||
if (time_left == 0) {
|
||||
ath10k_warn(ar, "Timeout in receiving vdev delete response\n");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/* Some firmware revisions don't notify host about self-peer removal
|
||||
* until after associated vdev is deleted.
|
||||
*/
|
||||
|
@ -5546,6 +5597,7 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw,
|
|||
|
||||
ath10k_mac_txq_unref(ar, vif->txq);
|
||||
|
||||
out:
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
}
|
||||
|
||||
|
@ -6358,6 +6410,41 @@ static void ath10k_mac_dec_num_stations(struct ath10k_vif *arvif,
|
|||
ar->num_stations--;
|
||||
}
|
||||
|
||||
static int ath10k_sta_set_txpwr(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
struct ath10k *ar = hw->priv;
|
||||
struct ath10k_vif *arvif = (void *)vif->drv_priv;
|
||||
int ret = 0;
|
||||
s16 txpwr;
|
||||
|
||||
if (sta->txpwr.type == NL80211_TX_POWER_AUTOMATIC) {
|
||||
txpwr = 0;
|
||||
} else {
|
||||
txpwr = sta->txpwr.power;
|
||||
if (!txpwr)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (txpwr > ATH10K_TX_POWER_MAX_VAL || txpwr < ATH10K_TX_POWER_MIN_VAL)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
ret = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr,
|
||||
WMI_PEER_USE_FIXED_PWR, txpwr);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to set tx power for station ret: %d\n",
|
||||
ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath10k_sta_state(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
|
@ -7107,18 +7194,23 @@ exit:
|
|||
static bool
|
||||
ath10k_mac_bitrate_mask_has_single_rate(struct ath10k *ar,
|
||||
enum nl80211_band band,
|
||||
const struct cfg80211_bitrate_mask *mask)
|
||||
const struct cfg80211_bitrate_mask *mask,
|
||||
int *vht_num_rates)
|
||||
{
|
||||
int num_rates = 0;
|
||||
int i;
|
||||
int i, tmp;
|
||||
|
||||
num_rates += hweight32(mask->control[band].legacy);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++)
|
||||
num_rates += hweight8(mask->control[band].ht_mcs[i]);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mask->control[band].vht_mcs); i++)
|
||||
num_rates += hweight16(mask->control[band].vht_mcs[i]);
|
||||
*vht_num_rates = 0;
|
||||
for (i = 0; i < ARRAY_SIZE(mask->control[band].vht_mcs); i++) {
|
||||
tmp = hweight16(mask->control[band].vht_mcs[i]);
|
||||
num_rates += tmp;
|
||||
*vht_num_rates += tmp;
|
||||
}
|
||||
|
||||
return num_rates == 1;
|
||||
}
|
||||
|
@ -7176,7 +7268,7 @@ static int
|
|||
ath10k_mac_bitrate_mask_get_single_rate(struct ath10k *ar,
|
||||
enum nl80211_band band,
|
||||
const struct cfg80211_bitrate_mask *mask,
|
||||
u8 *rate, u8 *nss)
|
||||
u8 *rate, u8 *nss, bool vht_only)
|
||||
{
|
||||
int rate_idx;
|
||||
int i;
|
||||
|
@ -7184,6 +7276,9 @@ ath10k_mac_bitrate_mask_get_single_rate(struct ath10k *ar,
|
|||
u8 preamble;
|
||||
u8 hw_rate;
|
||||
|
||||
if (vht_only)
|
||||
goto next;
|
||||
|
||||
if (hweight32(mask->control[band].legacy) == 1) {
|
||||
rate_idx = ffs(mask->control[band].legacy) - 1;
|
||||
|
||||
|
@ -7217,6 +7312,7 @@ ath10k_mac_bitrate_mask_get_single_rate(struct ath10k *ar,
|
|||
}
|
||||
}
|
||||
|
||||
next:
|
||||
for (i = 0; i < ARRAY_SIZE(mask->control[band].vht_mcs); i++) {
|
||||
if (hweight16(mask->control[band].vht_mcs[i]) == 1) {
|
||||
*nss = i + 1;
|
||||
|
@ -7278,7 +7374,8 @@ static int ath10k_mac_set_fixed_rate_params(struct ath10k_vif *arvif,
|
|||
static bool
|
||||
ath10k_mac_can_set_bitrate_mask(struct ath10k *ar,
|
||||
enum nl80211_band band,
|
||||
const struct cfg80211_bitrate_mask *mask)
|
||||
const struct cfg80211_bitrate_mask *mask,
|
||||
bool allow_pfr)
|
||||
{
|
||||
int i;
|
||||
u16 vht_mcs;
|
||||
|
@ -7297,7 +7394,8 @@ ath10k_mac_can_set_bitrate_mask(struct ath10k *ar,
|
|||
case BIT(10) - 1:
|
||||
break;
|
||||
default:
|
||||
ath10k_warn(ar, "refusing bitrate mask with missing 0-7 VHT MCS rates\n");
|
||||
if (!allow_pfr)
|
||||
ath10k_warn(ar, "refusing bitrate mask with missing 0-7 VHT MCS rates\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -7305,6 +7403,26 @@ ath10k_mac_can_set_bitrate_mask(struct ath10k *ar,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool ath10k_mac_set_vht_bitrate_mask_fixup(struct ath10k *ar,
|
||||
struct ath10k_vif *arvif,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
int err;
|
||||
u8 rate = arvif->vht_pfr;
|
||||
|
||||
/* skip non vht and multiple rate peers */
|
||||
if (!sta->vht_cap.vht_supported || arvif->vht_num_rates != 1)
|
||||
return false;
|
||||
|
||||
err = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr,
|
||||
WMI_PEER_PARAM_FIXED_RATE, rate);
|
||||
if (err)
|
||||
ath10k_warn(ar, "failed to eanble STA %pM peer fixed rate: %d\n",
|
||||
sta->addr, err);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void ath10k_mac_set_bitrate_mask_iter(void *data,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
|
@ -7315,6 +7433,9 @@ static void ath10k_mac_set_bitrate_mask_iter(void *data,
|
|||
if (arsta->arvif != arvif)
|
||||
return;
|
||||
|
||||
if (ath10k_mac_set_vht_bitrate_mask_fixup(ar, arvif, sta))
|
||||
return;
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
arsta->changed |= IEEE80211_RC_SUPP_RATES_CHANGED;
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
@ -7322,6 +7443,26 @@ static void ath10k_mac_set_bitrate_mask_iter(void *data,
|
|||
ieee80211_queue_work(ar->hw, &arsta->update_wk);
|
||||
}
|
||||
|
||||
static void ath10k_mac_clr_bitrate_mask_iter(void *data,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
struct ath10k_vif *arvif = data;
|
||||
struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
|
||||
struct ath10k *ar = arvif->ar;
|
||||
int err;
|
||||
|
||||
/* clear vht peers only */
|
||||
if (arsta->arvif != arvif || !sta->vht_cap.vht_supported)
|
||||
return;
|
||||
|
||||
err = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr,
|
||||
WMI_PEER_PARAM_FIXED_RATE,
|
||||
WMI_FIXED_RATE_NONE);
|
||||
if (err)
|
||||
ath10k_warn(ar, "failed to clear STA %pM peer fixed rate: %d\n",
|
||||
sta->addr, err);
|
||||
}
|
||||
|
||||
static int ath10k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
const struct cfg80211_bitrate_mask *mask)
|
||||
|
@ -7338,6 +7479,9 @@ static int ath10k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw,
|
|||
u8 ldpc;
|
||||
int single_nss;
|
||||
int ret;
|
||||
int vht_num_rates, allow_pfr;
|
||||
u8 vht_pfr;
|
||||
bool update_bitrate_mask = true;
|
||||
|
||||
if (ath10k_mac_vif_chan(vif, &def))
|
||||
return -EPERM;
|
||||
|
@ -7351,9 +7495,21 @@ static int ath10k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw,
|
|||
if (sgi == NL80211_TXRATE_FORCE_LGI)
|
||||
return -EINVAL;
|
||||
|
||||
if (ath10k_mac_bitrate_mask_has_single_rate(ar, band, mask)) {
|
||||
allow_pfr = test_bit(ATH10K_FW_FEATURE_PEER_FIXED_RATE,
|
||||
ar->normal_mode_fw.fw_file.fw_features);
|
||||
if (allow_pfr) {
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
ieee80211_iterate_stations_atomic(ar->hw,
|
||||
ath10k_mac_clr_bitrate_mask_iter,
|
||||
arvif);
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
}
|
||||
|
||||
if (ath10k_mac_bitrate_mask_has_single_rate(ar, band, mask,
|
||||
&vht_num_rates)) {
|
||||
ret = ath10k_mac_bitrate_mask_get_single_rate(ar, band, mask,
|
||||
&rate, &nss);
|
||||
&rate, &nss,
|
||||
false);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to get single rate for vdev %i: %d\n",
|
||||
arvif->vdev_id, ret);
|
||||
|
@ -7369,12 +7525,30 @@ static int ath10k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw,
|
|||
max(ath10k_mac_max_ht_nss(ht_mcs_mask),
|
||||
ath10k_mac_max_vht_nss(vht_mcs_mask)));
|
||||
|
||||
if (!ath10k_mac_can_set_bitrate_mask(ar, band, mask))
|
||||
return -EINVAL;
|
||||
if (!ath10k_mac_can_set_bitrate_mask(ar, band, mask,
|
||||
allow_pfr)) {
|
||||
u8 vht_nss;
|
||||
|
||||
if (!allow_pfr || vht_num_rates != 1)
|
||||
return -EINVAL;
|
||||
|
||||
/* Reach here, firmware supports peer fixed rate and has
|
||||
* single vht rate, and don't update vif birate_mask, as
|
||||
* the rate only for specific peer.
|
||||
*/
|
||||
ath10k_mac_bitrate_mask_get_single_rate(ar, band, mask,
|
||||
&vht_pfr,
|
||||
&vht_nss,
|
||||
true);
|
||||
update_bitrate_mask = false;
|
||||
}
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
arvif->bitrate_mask = *mask;
|
||||
if (update_bitrate_mask)
|
||||
arvif->bitrate_mask = *mask;
|
||||
arvif->vht_num_rates = vht_num_rates;
|
||||
arvif->vht_pfr = vht_pfr;
|
||||
ieee80211_iterate_stations_atomic(ar->hw,
|
||||
ath10k_mac_set_bitrate_mask_iter,
|
||||
arvif);
|
||||
|
@ -7877,7 +8051,8 @@ ath10k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
|
|||
arvif->vdev_id, ret);
|
||||
}
|
||||
|
||||
if (ath10k_peer_stats_enabled(ar)) {
|
||||
if (ath10k_peer_stats_enabled(ar) &&
|
||||
ar->hw_params.tx_stats_over_pktlog) {
|
||||
ar->pktlog_filter |= ATH10K_PKTLOG_PEER_STATS;
|
||||
ret = ath10k_wmi_pdev_pktlog_enable(ar,
|
||||
ar->pktlog_filter);
|
||||
|
@ -8015,6 +8190,7 @@ static const struct ieee80211_ops ath10k_ops = {
|
|||
.set_key = ath10k_set_key,
|
||||
.set_default_unicast_key = ath10k_set_default_unicast_key,
|
||||
.sta_state = ath10k_sta_state,
|
||||
.sta_set_txpwr = ath10k_sta_set_txpwr,
|
||||
.conf_tx = ath10k_conf_tx,
|
||||
.remain_on_channel = ath10k_remain_on_channel,
|
||||
.cancel_remain_on_channel = ath10k_cancel_remain_on_channel,
|
||||
|
@ -8703,6 +8879,9 @@ int ath10k_mac_register(struct ath10k *ar)
|
|||
wiphy_ext_feature_set(ar->hw->wiphy,
|
||||
NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER);
|
||||
|
||||
if (test_bit(WMI_SERVICE_TX_PWR_PER_PEER, ar->wmi.svc_map))
|
||||
wiphy_ext_feature_set(ar->hw->wiphy,
|
||||
NL80211_EXT_FEATURE_STA_TX_PWR);
|
||||
/*
|
||||
* on LL hardware queues are managed entirely by the FW
|
||||
* so we only advertise to mac we can do the queues thing
|
||||
|
|
|
@ -909,7 +909,7 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
|
|||
/* Host buffer address in CE space */
|
||||
u32 ce_data;
|
||||
dma_addr_t ce_data_base = 0;
|
||||
void *data_buf = NULL;
|
||||
void *data_buf;
|
||||
int i;
|
||||
|
||||
mutex_lock(&ar_pci->ce_diag_mutex);
|
||||
|
@ -923,10 +923,8 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
|
|||
*/
|
||||
alloc_nbytes = min_t(unsigned int, nbytes, DIAG_TRANSFER_LIMIT);
|
||||
|
||||
data_buf = (unsigned char *)dma_alloc_coherent(ar->dev, alloc_nbytes,
|
||||
&ce_data_base,
|
||||
GFP_ATOMIC);
|
||||
|
||||
data_buf = dma_alloc_coherent(ar->dev, alloc_nbytes, &ce_data_base,
|
||||
GFP_ATOMIC);
|
||||
if (!data_buf) {
|
||||
ret = -ENOMEM;
|
||||
goto done;
|
||||
|
@ -1054,7 +1052,7 @@ int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
|
|||
u32 *buf;
|
||||
unsigned int completed_nbytes, alloc_nbytes, remaining_bytes;
|
||||
struct ath10k_ce_pipe *ce_diag;
|
||||
void *data_buf = NULL;
|
||||
void *data_buf;
|
||||
dma_addr_t ce_data_base = 0;
|
||||
int i;
|
||||
|
||||
|
@ -1069,10 +1067,8 @@ int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
|
|||
*/
|
||||
alloc_nbytes = min_t(unsigned int, nbytes, DIAG_TRANSFER_LIMIT);
|
||||
|
||||
data_buf = (unsigned char *)dma_alloc_coherent(ar->dev,
|
||||
alloc_nbytes,
|
||||
&ce_data_base,
|
||||
GFP_ATOMIC);
|
||||
data_buf = dma_alloc_coherent(ar->dev, alloc_nbytes, &ce_data_base,
|
||||
GFP_ATOMIC);
|
||||
if (!data_buf) {
|
||||
ret = -ENOMEM;
|
||||
goto done;
|
||||
|
@ -2059,6 +2055,11 @@ static void ath10k_pci_hif_stop(struct ath10k *ar)
|
|||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif stop\n");
|
||||
|
||||
ath10k_pci_irq_disable(ar);
|
||||
ath10k_pci_irq_sync(ar);
|
||||
napi_synchronize(&ar->napi);
|
||||
napi_disable(&ar->napi);
|
||||
|
||||
/* Most likely the device has HTT Rx ring configured. The only way to
|
||||
* prevent the device from accessing (and possible corrupting) host
|
||||
* memory is to reset the chip now.
|
||||
|
@ -2072,10 +2073,6 @@ static void ath10k_pci_hif_stop(struct ath10k *ar)
|
|||
*/
|
||||
ath10k_pci_safe_chip_reset(ar);
|
||||
|
||||
ath10k_pci_irq_disable(ar);
|
||||
ath10k_pci_irq_sync(ar);
|
||||
napi_synchronize(&ar->napi);
|
||||
napi_disable(&ar->napi);
|
||||
ath10k_pci_flush(ar);
|
||||
|
||||
spin_lock_irqsave(&ar_pci->ps_lock, flags);
|
||||
|
|
|
@ -620,6 +620,51 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
int ath10k_qmi_set_fw_log_mode(struct ath10k *ar, u8 fw_log_mode)
|
||||
{
|
||||
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
|
||||
struct wlfw_ini_resp_msg_v01 resp = {};
|
||||
struct ath10k_qmi *qmi = ar_snoc->qmi;
|
||||
struct wlfw_ini_req_msg_v01 req = {};
|
||||
struct qmi_txn txn;
|
||||
int ret;
|
||||
|
||||
req.enablefwlog_valid = 1;
|
||||
req.enablefwlog = fw_log_mode;
|
||||
|
||||
ret = qmi_txn_init(&qmi->qmi_hdl, &txn, wlfw_ini_resp_msg_v01_ei,
|
||||
&resp);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = qmi_send_request(&qmi->qmi_hdl, NULL, &txn,
|
||||
QMI_WLFW_INI_REQ_V01,
|
||||
WLFW_INI_REQ_MSG_V01_MAX_MSG_LEN,
|
||||
wlfw_ini_req_msg_v01_ei, &req);
|
||||
if (ret < 0) {
|
||||
qmi_txn_cancel(&txn);
|
||||
ath10k_err(ar, "fail to send fw log reqest: %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = qmi_txn_wait(&txn, ATH10K_QMI_TIMEOUT * HZ);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
|
||||
ath10k_err(ar, "fw log request rejectedr: %d\n",
|
||||
resp.resp.error);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
ath10k_dbg(ar, ATH10K_DBG_QMI, "qmi fw log request completed, mode: %d\n",
|
||||
fw_log_mode);
|
||||
return 0;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
ath10k_qmi_ind_register_send_sync_msg(struct ath10k_qmi *qmi)
|
||||
{
|
||||
|
@ -1003,6 +1048,7 @@ int ath10k_qmi_deinit(struct ath10k *ar)
|
|||
qmi_handle_release(&qmi->qmi_hdl);
|
||||
cancel_work_sync(&qmi->event_work);
|
||||
destroy_workqueue(qmi->event_wq);
|
||||
kfree(qmi);
|
||||
ar_snoc->qmi = NULL;
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -114,5 +114,6 @@ int ath10k_qmi_wlan_disable(struct ath10k *ar);
|
|||
int ath10k_qmi_register_service_notifier(struct notifier_block *nb);
|
||||
int ath10k_qmi_init(struct ath10k *ar, u32 msa_size);
|
||||
int ath10k_qmi_deinit(struct ath10k *ar);
|
||||
int ath10k_qmi_set_fw_log_mode(struct ath10k *ar, u8 fw_log_mode);
|
||||
|
||||
#endif /* ATH10K_QMI_H */
|
||||
|
|
|
@ -607,6 +607,10 @@ static int ath10k_sdio_mbox_rx_alloc(struct ath10k *ar,
|
|||
full_len,
|
||||
last_in_bundle,
|
||||
last_in_bundle);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "alloc_rx_pkt error %d\n", ret);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
ar_sdio->n_rx_pkts = i;
|
||||
|
@ -855,6 +859,10 @@ static int ath10k_sdio_mbox_proc_cpu_intr(struct ath10k *ar)
|
|||
|
||||
out:
|
||||
mutex_unlock(&irq_data->mtx);
|
||||
if (cpu_int_status & MBOX_CPU_STATUS_ENABLE_ASSERT_MASK) {
|
||||
ath10k_err(ar, "firmware crashed!\n");
|
||||
queue_work(ar->workqueue, &ar->restart_work);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1500,8 +1508,10 @@ static int ath10k_sdio_hif_enable_intrs(struct ath10k *ar)
|
|||
regs->int_status_en |=
|
||||
FIELD_PREP(MBOX_INT_STATUS_ENABLE_MBOX_DATA_MASK, 1);
|
||||
|
||||
/* Set up the CPU Interrupt status Register */
|
||||
regs->cpu_int_status_en = 0;
|
||||
/* Set up the CPU Interrupt Status Register, enable CPU sourced interrupt #0
|
||||
* #0 is used for report assertion from target
|
||||
*/
|
||||
regs->cpu_int_status_en = FIELD_PREP(MBOX_CPU_STATUS_ENABLE_ASSERT_MASK, 1);
|
||||
|
||||
/* Set up the Error Interrupt status Register */
|
||||
regs->err_int_status_en =
|
||||
|
@ -2087,6 +2097,9 @@ static void ath10k_sdio_remove(struct sdio_func *func)
|
|||
|
||||
ath10k_core_unregister(ar);
|
||||
ath10k_core_destroy(ar);
|
||||
|
||||
flush_workqueue(ar_sdio->workqueue);
|
||||
destroy_workqueue(ar_sdio->workqueue);
|
||||
}
|
||||
|
||||
static const struct sdio_device_id ath10k_sdio_devices[] = {
|
||||
|
|
|
@ -1050,6 +1050,19 @@ err_wlan_enable:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int ath10k_snoc_hif_set_target_log_mode(struct ath10k *ar,
|
||||
u8 fw_log_mode)
|
||||
{
|
||||
u8 fw_dbg_mode;
|
||||
|
||||
if (fw_log_mode)
|
||||
fw_dbg_mode = ATH10K_ENABLE_FW_LOG_CE;
|
||||
else
|
||||
fw_dbg_mode = ATH10K_ENABLE_FW_LOG_DIAG;
|
||||
|
||||
return ath10k_qmi_set_fw_log_mode(ar, fw_dbg_mode);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int ath10k_snoc_hif_suspend(struct ath10k *ar)
|
||||
{
|
||||
|
@ -1103,6 +1116,8 @@ static const struct ath10k_hif_ops ath10k_snoc_hif_ops = {
|
|||
.send_complete_check = ath10k_snoc_hif_send_complete_check,
|
||||
.get_free_queue_number = ath10k_snoc_hif_get_free_queue_number,
|
||||
.get_target_info = ath10k_snoc_hif_get_target_info,
|
||||
.set_target_log_mode = ath10k_snoc_hif_set_target_log_mode,
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
.suspend = ath10k_snoc_hif_suspend,
|
||||
.resume = ath10k_snoc_hif_resume,
|
||||
|
|
|
@ -106,10 +106,8 @@ ath10k_swap_code_seg_alloc(struct ath10k *ar, size_t swap_bin_len)
|
|||
|
||||
virt_addr = dma_alloc_coherent(ar->dev, swap_bin_len, &paddr,
|
||||
GFP_KERNEL);
|
||||
if (!virt_addr) {
|
||||
ath10k_err(ar, "failed to allocate dma coherent memory\n");
|
||||
if (!virt_addr)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
seg_info->seg_hw_info.bus_addr[0] = __cpu_to_le32(paddr);
|
||||
seg_info->seg_hw_info.size = __cpu_to_le32(swap_bin_len);
|
||||
|
|
|
@ -174,8 +174,23 @@ static int ath10k_tm_fetch_firmware(struct ath10k *ar)
|
|||
{
|
||||
struct ath10k_fw_components *utf_mode_fw;
|
||||
int ret;
|
||||
char fw_name[100];
|
||||
int fw_api2 = 2;
|
||||
|
||||
ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_UTF_API2_FILE,
|
||||
switch (ar->hif.bus) {
|
||||
case ATH10K_BUS_SDIO:
|
||||
case ATH10K_BUS_USB:
|
||||
scnprintf(fw_name, sizeof(fw_name), "%s-%s-%d.bin",
|
||||
ATH10K_FW_UTF_FILE_BASE, ath10k_bus_str(ar->hif.bus),
|
||||
fw_api2);
|
||||
break;
|
||||
default:
|
||||
scnprintf(fw_name, sizeof(fw_name), "%s-%d.bin",
|
||||
ATH10K_FW_UTF_FILE_BASE, fw_api2);
|
||||
break;
|
||||
}
|
||||
|
||||
ret = ath10k_core_fetch_firmware_api_n(ar, fw_name,
|
||||
&ar->testmode.utf_mode_fw.fw_file);
|
||||
if (ret == 0) {
|
||||
ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode using fw utf api 2");
|
||||
|
|
|
@ -7,3 +7,4 @@
|
|||
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include "trace.h"
|
||||
EXPORT_SYMBOL(__tracepoint_ath10k_log_dbg);
|
||||
|
|
|
@ -29,7 +29,11 @@ static inline u32 ath10k_frm_hdr_len(const void *buf, size_t len)
|
|||
#if !defined(CONFIG_ATH10K_TRACING)
|
||||
#undef TRACE_EVENT
|
||||
#define TRACE_EVENT(name, proto, ...) \
|
||||
static inline void trace_ ## name(proto) {}
|
||||
static inline void trace_ ## name(proto) {} \
|
||||
static inline bool trace_##name##_enabled(void) \
|
||||
{ \
|
||||
return false; \
|
||||
}
|
||||
#undef DECLARE_EVENT_CLASS
|
||||
#define DECLARE_EVENT_CLASS(...)
|
||||
#undef DEFINE_EVENT
|
||||
|
|
|
@ -1016,7 +1016,7 @@ static int ath10k_usb_probe(struct usb_interface *interface,
|
|||
}
|
||||
|
||||
/* TODO: remove this once USB support is fully implemented */
|
||||
ath10k_warn(ar, "WARNING: ath10k USB support is incomplete, don't expect anything to work!\n");
|
||||
ath10k_warn(ar, "Warning: ath10k USB support is incomplete, don't expect anything to work!\n");
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
/*
|
||||
* Copyright (c) 2005-2011 Atheros Communications Inc.
|
||||
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
|
||||
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
#include "core.h"
|
||||
#include "debug.h"
|
||||
|
@ -212,6 +212,13 @@ static int ath10k_wmi_tlv_event_bcn_tx_status(struct ath10k *ar,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void ath10k_wmi_tlv_event_vdev_delete_resp(struct ath10k *ar,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_VDEV_DELETE_RESP_EVENTID\n");
|
||||
complete(&ar->vdev_delete_done);
|
||||
}
|
||||
|
||||
static int ath10k_wmi_tlv_event_diag_data(struct ath10k *ar,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
|
@ -458,6 +465,24 @@ static void ath10k_wmi_event_tdls_peer(struct ath10k *ar, struct sk_buff *skb)
|
|||
kfree(tb);
|
||||
}
|
||||
|
||||
static int ath10k_wmi_tlv_event_peer_delete_resp(struct ath10k *ar,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct wmi_peer_delete_resp_ev_arg *arg;
|
||||
struct wmi_tlv *tlv_hdr;
|
||||
|
||||
tlv_hdr = (struct wmi_tlv *)skb->data;
|
||||
arg = (struct wmi_peer_delete_resp_ev_arg *)tlv_hdr->value;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_WMI, "vdev id %d", arg->vdev_id);
|
||||
ath10k_dbg(ar, ATH10K_DBG_WMI, "peer mac addr %pM", &arg->peer_addr);
|
||||
ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv peer delete response\n");
|
||||
|
||||
complete(&ar->peer_delete_done);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***********/
|
||||
/* TLV ops */
|
||||
/***********/
|
||||
|
@ -514,6 +539,9 @@ static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb)
|
|||
case WMI_TLV_VDEV_STOPPED_EVENTID:
|
||||
ath10k_wmi_event_vdev_stopped(ar, skb);
|
||||
break;
|
||||
case WMI_TLV_VDEV_DELETE_RESP_EVENTID:
|
||||
ath10k_wmi_tlv_event_vdev_delete_resp(ar, skb);
|
||||
break;
|
||||
case WMI_TLV_PEER_STA_KICKOUT_EVENTID:
|
||||
ath10k_wmi_event_peer_sta_kickout(ar, skb);
|
||||
break;
|
||||
|
@ -607,6 +635,9 @@ static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb)
|
|||
case WMI_TLV_TDLS_PEER_EVENTID:
|
||||
ath10k_wmi_event_tdls_peer(ar, skb);
|
||||
break;
|
||||
case WMI_TLV_PEER_DELETE_RESP_EVENTID:
|
||||
ath10k_wmi_tlv_event_peer_delete_resp(ar, skb);
|
||||
break;
|
||||
case WMI_TLV_MGMT_TX_COMPLETION_EVENTID:
|
||||
ath10k_wmi_event_mgmt_tx_compl(ar, skb);
|
||||
break;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
/*
|
||||
* Copyright (c) 2005-2011 Atheros Communications Inc.
|
||||
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
|
||||
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
#ifndef _WMI_TLV_H
|
||||
#define _WMI_TLV_H
|
||||
|
@ -301,11 +301,15 @@ enum wmi_tlv_event_id {
|
|||
WMI_TLV_VDEV_STOPPED_EVENTID,
|
||||
WMI_TLV_VDEV_INSTALL_KEY_COMPLETE_EVENTID,
|
||||
WMI_TLV_VDEV_MCC_BCN_INTERVAL_CHANGE_REQ_EVENTID,
|
||||
WMI_TLV_VDEV_TSF_REPORT_EVENTID,
|
||||
WMI_TLV_VDEV_DELETE_RESP_EVENTID,
|
||||
WMI_TLV_PEER_STA_KICKOUT_EVENTID = WMI_TLV_EV(WMI_TLV_GRP_PEER),
|
||||
WMI_TLV_PEER_INFO_EVENTID,
|
||||
WMI_TLV_PEER_TX_FAIL_CNT_THR_EVENTID,
|
||||
WMI_TLV_PEER_ESTIMATED_LINKSPEED_EVENTID,
|
||||
WMI_TLV_PEER_STATE_EVENTID,
|
||||
WMI_TLV_PEER_ASSOC_CONF_EVENTID,
|
||||
WMI_TLV_PEER_DELETE_RESP_EVENTID,
|
||||
WMI_TLV_MGMT_RX_EVENTID = WMI_TLV_EV(WMI_TLV_GRP_MGMT),
|
||||
WMI_TLV_HOST_SWBA_EVENTID,
|
||||
WMI_TLV_TBTTOFFSET_UPDATE_EVENTID,
|
||||
|
@ -1569,6 +1573,8 @@ wmi_tlv_svc_map(const __le32 *in, unsigned long *out, size_t len)
|
|||
WMI_SERVICE_MGMT_TX_WMI, len);
|
||||
SVCMAP(WMI_TLV_SERVICE_MESH_11S,
|
||||
WMI_SERVICE_MESH_11S, len);
|
||||
SVCMAP(WMI_TLV_SERVICE_SYNC_DELETE_CMDS,
|
||||
WMI_SERVICE_SYNC_DELETE_CMDS, len);
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
/*
|
||||
* Copyright (c) 2005-2011 Atheros Communications Inc.
|
||||
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
|
||||
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _WMI_H_
|
||||
|
@ -200,6 +200,8 @@ enum wmi_service {
|
|||
WMI_SERVICE_RTT_RESPONDER_ROLE,
|
||||
WMI_SERVICE_PER_PACKET_SW_ENCRYPT,
|
||||
WMI_SERVICE_REPORT_AIRTIME,
|
||||
WMI_SERVICE_SYNC_DELETE_CMDS,
|
||||
WMI_SERVICE_TX_PWR_PER_PEER,
|
||||
|
||||
/* Remember to add the new value to wmi_service_name()! */
|
||||
|
||||
|
@ -367,6 +369,7 @@ enum wmi_10_4_service {
|
|||
WMI_10_4_SERVICE_RTT_RESPONDER_ROLE,
|
||||
WMI_10_4_SERVICE_EXT_PEER_TID_CONFIGS_SUPPORT,
|
||||
WMI_10_4_SERVICE_REPORT_AIRTIME,
|
||||
WMI_10_4_SERVICE_TX_PWR_PER_PEER,
|
||||
};
|
||||
|
||||
static inline char *wmi_service_name(enum wmi_service service_id)
|
||||
|
@ -491,6 +494,8 @@ static inline char *wmi_service_name(enum wmi_service service_id)
|
|||
SVCSTR(WMI_SERVICE_RTT_RESPONDER_ROLE);
|
||||
SVCSTR(WMI_SERVICE_PER_PACKET_SW_ENCRYPT);
|
||||
SVCSTR(WMI_SERVICE_REPORT_AIRTIME);
|
||||
SVCSTR(WMI_SERVICE_SYNC_DELETE_CMDS);
|
||||
SVCSTR(WMI_SERVICE_TX_PWR_PER_PEER);
|
||||
|
||||
case WMI_SERVICE_MAX:
|
||||
return NULL;
|
||||
|
@ -818,6 +823,8 @@ static inline void wmi_10_4_svc_map(const __le32 *in, unsigned long *out,
|
|||
WMI_SERVICE_PER_PACKET_SW_ENCRYPT, len);
|
||||
SVCMAP(WMI_10_4_SERVICE_REPORT_AIRTIME,
|
||||
WMI_SERVICE_REPORT_AIRTIME, len);
|
||||
SVCMAP(WMI_10_4_SERVICE_TX_PWR_PER_PEER,
|
||||
WMI_SERVICE_TX_PWR_PER_PEER, len);
|
||||
}
|
||||
|
||||
#undef SVCMAP
|
||||
|
@ -6260,6 +6267,8 @@ enum wmi_peer_param {
|
|||
WMI_PEER_CHAN_WIDTH = 0x4,
|
||||
WMI_PEER_NSS = 0x5,
|
||||
WMI_PEER_USE_4ADDR = 0x6,
|
||||
WMI_PEER_USE_FIXED_PWR = 0x8,
|
||||
WMI_PEER_PARAM_FIXED_RATE = 0x9,
|
||||
WMI_PEER_DEBUG = 0xa,
|
||||
WMI_PEER_PHYMODE = 0xd,
|
||||
WMI_PEER_DUMMY_VAR = 0xff, /* dummy parameter for STA PS workaround */
|
||||
|
@ -6757,6 +6766,11 @@ struct wmi_tlv_mgmt_tx_bundle_compl_ev_arg {
|
|||
const __le32 *ack_rssi;
|
||||
};
|
||||
|
||||
struct wmi_peer_delete_resp_ev_arg {
|
||||
__le32 vdev_id;
|
||||
struct wmi_mac_addr peer_addr;
|
||||
};
|
||||
|
||||
struct wmi_mgmt_rx_ev_arg {
|
||||
__le32 channel;
|
||||
__le32 snr;
|
||||
|
|
|
@ -815,6 +815,7 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
|
|||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ieee80211_hdr *hdr;
|
||||
bool discard_current = sc->rx.discard_next;
|
||||
bool is_phyerr;
|
||||
|
||||
/*
|
||||
* Discard corrupt descriptors which are marked in
|
||||
|
@ -827,8 +828,11 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
|
|||
|
||||
/*
|
||||
* Discard zero-length packets and packets smaller than an ACK
|
||||
* which are not PHY_ERROR (short radar pulses have a length of 3)
|
||||
*/
|
||||
if (rx_stats->rs_datalen < 10) {
|
||||
is_phyerr = rx_stats->rs_status & ATH9K_RXERR_PHY;
|
||||
if (!rx_stats->rs_datalen ||
|
||||
(rx_stats->rs_datalen < 10 && !is_phyerr)) {
|
||||
RX_STAT_INC(sc, rx_len_err);
|
||||
goto corrupt;
|
||||
}
|
||||
|
|
|
@ -1387,13 +1387,8 @@ static int carl9170_op_conf_tx(struct ieee80211_hw *hw,
|
|||
int ret;
|
||||
|
||||
mutex_lock(&ar->mutex);
|
||||
if (queue < ar->hw->queues) {
|
||||
memcpy(&ar->edcf[ar9170_qmap[queue]], param, sizeof(*param));
|
||||
ret = carl9170_set_qos(ar);
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
memcpy(&ar->edcf[ar9170_qmap[queue]], param, sizeof(*param));
|
||||
ret = carl9170_set_qos(ar);
|
||||
mutex_unlock(&ar->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -128,6 +128,8 @@ static const struct usb_device_id carl9170_usb_ids[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(usb, carl9170_usb_ids);
|
||||
|
||||
static struct usb_driver carl9170_driver;
|
||||
|
||||
static void carl9170_usb_submit_data_urb(struct ar9170 *ar)
|
||||
{
|
||||
struct urb *urb;
|
||||
|
@ -966,32 +968,28 @@ err_out:
|
|||
|
||||
static void carl9170_usb_firmware_failed(struct ar9170 *ar)
|
||||
{
|
||||
struct device *parent = ar->udev->dev.parent;
|
||||
struct usb_device *udev;
|
||||
|
||||
/*
|
||||
* Store a copy of the usb_device pointer locally.
|
||||
* This is because device_release_driver initiates
|
||||
* carl9170_usb_disconnect, which in turn frees our
|
||||
* driver context (ar).
|
||||
/* Store a copies of the usb_interface and usb_device pointer locally.
|
||||
* This is because release_driver initiates carl9170_usb_disconnect,
|
||||
* which in turn frees our driver context (ar).
|
||||
*/
|
||||
udev = ar->udev;
|
||||
struct usb_interface *intf = ar->intf;
|
||||
struct usb_device *udev = ar->udev;
|
||||
|
||||
complete(&ar->fw_load_wait);
|
||||
/* at this point 'ar' could be already freed. Don't use it anymore */
|
||||
ar = NULL;
|
||||
|
||||
/* unbind anything failed */
|
||||
if (parent)
|
||||
device_lock(parent);
|
||||
usb_lock_device(udev);
|
||||
usb_driver_release_interface(&carl9170_driver, intf);
|
||||
usb_unlock_device(udev);
|
||||
|
||||
device_release_driver(&udev->dev);
|
||||
if (parent)
|
||||
device_unlock(parent);
|
||||
|
||||
usb_put_dev(udev);
|
||||
usb_put_intf(intf);
|
||||
}
|
||||
|
||||
static void carl9170_usb_firmware_finish(struct ar9170 *ar)
|
||||
{
|
||||
struct usb_interface *intf = ar->intf;
|
||||
int err;
|
||||
|
||||
err = carl9170_parse_firmware(ar);
|
||||
|
@ -1009,7 +1007,7 @@ static void carl9170_usb_firmware_finish(struct ar9170 *ar)
|
|||
goto err_unrx;
|
||||
|
||||
complete(&ar->fw_load_wait);
|
||||
usb_put_dev(ar->udev);
|
||||
usb_put_intf(intf);
|
||||
return;
|
||||
|
||||
err_unrx:
|
||||
|
@ -1052,7 +1050,6 @@ static int carl9170_usb_probe(struct usb_interface *intf,
|
|||
return PTR_ERR(ar);
|
||||
|
||||
udev = interface_to_usbdev(intf);
|
||||
usb_get_dev(udev);
|
||||
ar->udev = udev;
|
||||
ar->intf = intf;
|
||||
ar->features = id->driver_info;
|
||||
|
@ -1094,15 +1091,14 @@ static int carl9170_usb_probe(struct usb_interface *intf,
|
|||
atomic_set(&ar->rx_anch_urbs, 0);
|
||||
atomic_set(&ar->rx_pool_urbs, 0);
|
||||
|
||||
usb_get_dev(ar->udev);
|
||||
usb_get_intf(intf);
|
||||
|
||||
carl9170_set_state(ar, CARL9170_STOPPED);
|
||||
|
||||
err = request_firmware_nowait(THIS_MODULE, 1, CARL9170FW_NAME,
|
||||
&ar->udev->dev, GFP_KERNEL, ar, carl9170_usb_firmware_step2);
|
||||
if (err) {
|
||||
usb_put_dev(udev);
|
||||
usb_put_dev(udev);
|
||||
usb_put_intf(intf);
|
||||
carl9170_free(ar);
|
||||
}
|
||||
return err;
|
||||
|
@ -1131,7 +1127,6 @@ static void carl9170_usb_disconnect(struct usb_interface *intf)
|
|||
|
||||
carl9170_release_firmware(ar);
|
||||
carl9170_free(ar);
|
||||
usb_put_dev(udev);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
|
|
@ -314,7 +314,8 @@ int wil_cid_fill_sinfo(struct wil6210_vif *vif, int cid,
|
|||
memset(&reply, 0, sizeof(reply));
|
||||
|
||||
rc = wmi_call(wil, WMI_NOTIFY_REQ_CMDID, vif->mid, &cmd, sizeof(cmd),
|
||||
WMI_NOTIFY_REQ_DONE_EVENTID, &reply, sizeof(reply), 20);
|
||||
WMI_NOTIFY_REQ_DONE_EVENTID, &reply, sizeof(reply),
|
||||
WIL_WMI_CALL_GENERAL_TO_MS);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
|
@ -380,8 +381,8 @@ static int wil_cfg80211_get_station(struct wiphy *wiphy,
|
|||
|
||||
wil_dbg_misc(wil, "get_station: %pM CID %d MID %d\n", mac, cid,
|
||||
vif->mid);
|
||||
if (cid < 0)
|
||||
return cid;
|
||||
if (!wil_cid_valid(wil, cid))
|
||||
return -ENOENT;
|
||||
|
||||
rc = wil_cid_fill_sinfo(vif, cid, sinfo);
|
||||
|
||||
|
@ -417,7 +418,7 @@ static int wil_cfg80211_dump_station(struct wiphy *wiphy,
|
|||
int rc;
|
||||
int cid = wil_find_cid_by_idx(wil, vif->mid, idx);
|
||||
|
||||
if (cid < 0)
|
||||
if (!wil_cid_valid(wil, cid))
|
||||
return -ENOENT;
|
||||
|
||||
ether_addr_copy(mac, wil->sta[cid].addr);
|
||||
|
@ -643,6 +644,16 @@ out:
|
|||
return rc;
|
||||
}
|
||||
|
||||
static bool wil_is_safe_switch(enum nl80211_iftype from,
|
||||
enum nl80211_iftype to)
|
||||
{
|
||||
if (from == NL80211_IFTYPE_STATION &&
|
||||
to == NL80211_IFTYPE_P2P_CLIENT)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int wil_cfg80211_change_iface(struct wiphy *wiphy,
|
||||
struct net_device *ndev,
|
||||
enum nl80211_iftype type,
|
||||
|
@ -668,7 +679,8 @@ static int wil_cfg80211_change_iface(struct wiphy *wiphy,
|
|||
* because it can cause significant disruption
|
||||
*/
|
||||
if (!wil_has_other_active_ifaces(wil, ndev, true, false) &&
|
||||
netif_running(ndev) && !wil_is_recovery_blocked(wil)) {
|
||||
netif_running(ndev) && !wil_is_recovery_blocked(wil) &&
|
||||
!wil_is_safe_switch(wdev->iftype, type)) {
|
||||
wil_dbg_misc(wil, "interface is up. resetting...\n");
|
||||
mutex_lock(&wil->mutex);
|
||||
__wil_down(wil);
|
||||
|
|
|
@ -422,25 +422,18 @@ static int wil_debugfs_iomem_x32_get(void *data, u64 *val)
|
|||
DEFINE_DEBUGFS_ATTRIBUTE(fops_iomem_x32, wil_debugfs_iomem_x32_get,
|
||||
wil_debugfs_iomem_x32_set, "0x%08llx\n");
|
||||
|
||||
static struct dentry *wil_debugfs_create_iomem_x32(const char *name,
|
||||
umode_t mode,
|
||||
struct dentry *parent,
|
||||
void *value,
|
||||
struct wil6210_priv *wil)
|
||||
static void wil_debugfs_create_iomem_x32(const char *name, umode_t mode,
|
||||
struct dentry *parent, void *value,
|
||||
struct wil6210_priv *wil)
|
||||
{
|
||||
struct dentry *file;
|
||||
struct wil_debugfs_iomem_data *data = &wil->dbg_data.data_arr[
|
||||
wil->dbg_data.iomem_data_count];
|
||||
|
||||
data->wil = wil;
|
||||
data->offset = value;
|
||||
|
||||
file = debugfs_create_file_unsafe(name, mode, parent, data,
|
||||
&fops_iomem_x32);
|
||||
if (!IS_ERR_OR_NULL(file))
|
||||
wil->dbg_data.iomem_data_count++;
|
||||
|
||||
return file;
|
||||
debugfs_create_file_unsafe(name, mode, parent, data, &fops_iomem_x32);
|
||||
wil->dbg_data.iomem_data_count++;
|
||||
}
|
||||
|
||||
static int wil_debugfs_ulong_set(void *data, u64 val)
|
||||
|
@ -458,14 +451,6 @@ static int wil_debugfs_ulong_get(void *data, u64 *val)
|
|||
DEFINE_DEBUGFS_ATTRIBUTE(wil_fops_ulong, wil_debugfs_ulong_get,
|
||||
wil_debugfs_ulong_set, "0x%llx\n");
|
||||
|
||||
static struct dentry *wil_debugfs_create_ulong(const char *name, umode_t mode,
|
||||
struct dentry *parent,
|
||||
ulong *value)
|
||||
{
|
||||
return debugfs_create_file_unsafe(name, mode, parent, value,
|
||||
&wil_fops_ulong);
|
||||
}
|
||||
|
||||
/**
|
||||
* wil6210_debugfs_init_offset - create set of debugfs files
|
||||
* @wil - driver's context, used for printing
|
||||
|
@ -482,37 +467,30 @@ static void wil6210_debugfs_init_offset(struct wil6210_priv *wil,
|
|||
int i;
|
||||
|
||||
for (i = 0; tbl[i].name; i++) {
|
||||
struct dentry *f;
|
||||
|
||||
switch (tbl[i].type) {
|
||||
case doff_u32:
|
||||
f = debugfs_create_u32(tbl[i].name, tbl[i].mode, dbg,
|
||||
base + tbl[i].off);
|
||||
debugfs_create_u32(tbl[i].name, tbl[i].mode, dbg,
|
||||
base + tbl[i].off);
|
||||
break;
|
||||
case doff_x32:
|
||||
f = debugfs_create_x32(tbl[i].name, tbl[i].mode, dbg,
|
||||
base + tbl[i].off);
|
||||
debugfs_create_x32(tbl[i].name, tbl[i].mode, dbg,
|
||||
base + tbl[i].off);
|
||||
break;
|
||||
case doff_ulong:
|
||||
f = wil_debugfs_create_ulong(tbl[i].name, tbl[i].mode,
|
||||
dbg, base + tbl[i].off);
|
||||
debugfs_create_file_unsafe(tbl[i].name, tbl[i].mode,
|
||||
dbg, base + tbl[i].off,
|
||||
&wil_fops_ulong);
|
||||
break;
|
||||
case doff_io32:
|
||||
f = wil_debugfs_create_iomem_x32(tbl[i].name,
|
||||
tbl[i].mode, dbg,
|
||||
base + tbl[i].off,
|
||||
wil);
|
||||
wil_debugfs_create_iomem_x32(tbl[i].name, tbl[i].mode,
|
||||
dbg, base + tbl[i].off,
|
||||
wil);
|
||||
break;
|
||||
case doff_u8:
|
||||
f = debugfs_create_u8(tbl[i].name, tbl[i].mode, dbg,
|
||||
base + tbl[i].off);
|
||||
debugfs_create_u8(tbl[i].name, tbl[i].mode, dbg,
|
||||
base + tbl[i].off);
|
||||
break;
|
||||
default:
|
||||
f = ERR_PTR(-EINVAL);
|
||||
}
|
||||
if (IS_ERR_OR_NULL(f))
|
||||
wil_err(wil, "Create file \"%s\": err %ld\n",
|
||||
tbl[i].name, PTR_ERR(f));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -527,19 +505,14 @@ static const struct dbg_off isr_off[] = {
|
|||
{},
|
||||
};
|
||||
|
||||
static int wil6210_debugfs_create_ISR(struct wil6210_priv *wil,
|
||||
const char *name,
|
||||
struct dentry *parent, u32 off)
|
||||
static void wil6210_debugfs_create_ISR(struct wil6210_priv *wil,
|
||||
const char *name, struct dentry *parent,
|
||||
u32 off)
|
||||
{
|
||||
struct dentry *d = debugfs_create_dir(name, parent);
|
||||
|
||||
if (IS_ERR_OR_NULL(d))
|
||||
return -ENODEV;
|
||||
|
||||
wil6210_debugfs_init_offset(wil, d, (void * __force)wil->csr + off,
|
||||
isr_off);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dbg_off pseudo_isr_off[] = {
|
||||
|
@ -549,18 +522,13 @@ static const struct dbg_off pseudo_isr_off[] = {
|
|||
{},
|
||||
};
|
||||
|
||||
static int wil6210_debugfs_create_pseudo_ISR(struct wil6210_priv *wil,
|
||||
struct dentry *parent)
|
||||
static void wil6210_debugfs_create_pseudo_ISR(struct wil6210_priv *wil,
|
||||
struct dentry *parent)
|
||||
{
|
||||
struct dentry *d = debugfs_create_dir("PSEUDO_ISR", parent);
|
||||
|
||||
if (IS_ERR_OR_NULL(d))
|
||||
return -ENODEV;
|
||||
|
||||
wil6210_debugfs_init_offset(wil, d, (void * __force)wil->csr,
|
||||
pseudo_isr_off);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dbg_off lgc_itr_cnt_off[] = {
|
||||
|
@ -608,13 +576,9 @@ static int wil6210_debugfs_create_ITR_CNT(struct wil6210_priv *wil,
|
|||
struct dentry *d, *dtx, *drx;
|
||||
|
||||
d = debugfs_create_dir("ITR_CNT", parent);
|
||||
if (IS_ERR_OR_NULL(d))
|
||||
return -ENODEV;
|
||||
|
||||
dtx = debugfs_create_dir("TX", d);
|
||||
drx = debugfs_create_dir("RX", d);
|
||||
if (IS_ERR_OR_NULL(dtx) || IS_ERR_OR_NULL(drx))
|
||||
return -ENODEV;
|
||||
|
||||
wil6210_debugfs_init_offset(wil, d, (void * __force)wil->csr,
|
||||
lgc_itr_cnt_off);
|
||||
|
@ -777,6 +741,44 @@ static const struct file_operations fops_rxon = {
|
|||
.open = simple_open,
|
||||
};
|
||||
|
||||
static ssize_t wil_write_file_rbufcap(struct file *file,
|
||||
const char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct wil6210_priv *wil = file->private_data;
|
||||
int val;
|
||||
int rc;
|
||||
|
||||
rc = kstrtoint_from_user(buf, count, 0, &val);
|
||||
if (rc) {
|
||||
wil_err(wil, "Invalid argument\n");
|
||||
return rc;
|
||||
}
|
||||
/* input value: negative to disable, 0 to use system default,
|
||||
* 1..ring size to set descriptor threshold
|
||||
*/
|
||||
wil_info(wil, "%s RBUFCAP, descriptors threshold - %d\n",
|
||||
val < 0 ? "Disabling" : "Enabling", val);
|
||||
|
||||
if (!wil->ring_rx.va || val > wil->ring_rx.size) {
|
||||
wil_err(wil, "Invalid descriptors threshold, %d\n", val);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = wmi_rbufcap_cfg(wil, val < 0 ? 0 : 1, val < 0 ? 0 : val);
|
||||
if (rc) {
|
||||
wil_err(wil, "RBUFCAP config failed: %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations fops_rbufcap = {
|
||||
.write = wil_write_file_rbufcap,
|
||||
.open = simple_open,
|
||||
};
|
||||
|
||||
/* block ack control, write:
|
||||
* - "add <ringid> <agg_size> <timeout>" to trigger ADDBA
|
||||
* - "del_tx <ringid> <reason>" to trigger DELBA for Tx side
|
||||
|
@ -938,9 +940,8 @@ static ssize_t wil_read_pmccfg(struct file *file, char __user *user_buf,
|
|||
" - \"alloc <num descriptors> <descriptor_size>\" to allocate pmc\n"
|
||||
" - \"free\" to free memory allocated for pmc\n";
|
||||
|
||||
sprintf(text, "Last command status: %d\n\n%s",
|
||||
wil_pmc_last_cmd_status(wil),
|
||||
help);
|
||||
snprintf(text, sizeof(text), "Last command status: %d\n\n%s",
|
||||
wil_pmc_last_cmd_status(wil), help);
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, text,
|
||||
strlen(text) + 1);
|
||||
|
@ -1297,7 +1298,7 @@ static int bf_show(struct seq_file *s, void *data)
|
|||
rc = wmi_call(wil, WMI_NOTIFY_REQ_CMDID, vif->mid,
|
||||
&cmd, sizeof(cmd),
|
||||
WMI_NOTIFY_REQ_DONE_EVENTID, &reply,
|
||||
sizeof(reply), 20);
|
||||
sizeof(reply), WIL_WMI_CALL_GENERAL_TO_MS);
|
||||
/* if reply is all-0, ignore this CID */
|
||||
if (rc || is_all_zeros(&reply.evt, sizeof(reply.evt)))
|
||||
continue;
|
||||
|
@ -1335,7 +1336,7 @@ static void print_temp(struct seq_file *s, const char *prefix, s32 t)
|
|||
{
|
||||
switch (t) {
|
||||
case 0:
|
||||
case ~(u32)0:
|
||||
case WMI_INVALID_TEMPERATURE:
|
||||
seq_printf(s, "%s N/A\n", prefix);
|
||||
break;
|
||||
default:
|
||||
|
@ -1348,17 +1349,41 @@ static void print_temp(struct seq_file *s, const char *prefix, s32 t)
|
|||
static int temp_show(struct seq_file *s, void *data)
|
||||
{
|
||||
struct wil6210_priv *wil = s->private;
|
||||
s32 t_m, t_r;
|
||||
int rc = wmi_get_temperature(wil, &t_m, &t_r);
|
||||
int rc, i;
|
||||
|
||||
if (rc) {
|
||||
seq_puts(s, "Failed\n");
|
||||
return 0;
|
||||
if (test_bit(WMI_FW_CAPABILITY_TEMPERATURE_ALL_RF,
|
||||
wil->fw_capabilities)) {
|
||||
struct wmi_temp_sense_all_done_event sense_all_evt;
|
||||
|
||||
wil_dbg_misc(wil,
|
||||
"WMI_FW_CAPABILITY_TEMPERATURE_ALL_RF is supported");
|
||||
rc = wmi_get_all_temperatures(wil, &sense_all_evt);
|
||||
if (rc) {
|
||||
seq_puts(s, "Failed\n");
|
||||
return 0;
|
||||
}
|
||||
print_temp(s, "T_mac =",
|
||||
le32_to_cpu(sense_all_evt.baseband_t1000));
|
||||
seq_printf(s, "Connected RFs [0x%08x]\n",
|
||||
sense_all_evt.rf_bitmap);
|
||||
for (i = 0; i < WMI_MAX_XIF_PORTS_NUM; i++) {
|
||||
seq_printf(s, "RF[%d] = ", i);
|
||||
print_temp(s, "",
|
||||
le32_to_cpu(sense_all_evt.rf_t1000[i]));
|
||||
}
|
||||
} else {
|
||||
s32 t_m, t_r;
|
||||
|
||||
wil_dbg_misc(wil,
|
||||
"WMI_FW_CAPABILITY_TEMPERATURE_ALL_RF is not supported");
|
||||
rc = wmi_get_temperature(wil, &t_m, &t_r);
|
||||
if (rc) {
|
||||
seq_puts(s, "Failed\n");
|
||||
return 0;
|
||||
}
|
||||
print_temp(s, "T_mac =", t_m);
|
||||
print_temp(s, "T_radio =", t_r);
|
||||
}
|
||||
|
||||
print_temp(s, "T_mac =", t_m);
|
||||
print_temp(s, "T_radio =", t_r);
|
||||
|
||||
return 0;
|
||||
}
|
||||
DEFINE_SHOW_ATTRIBUTE(temp);
|
||||
|
@ -2364,6 +2389,7 @@ static const struct {
|
|||
{"tx_latency", 0644, &fops_tx_latency},
|
||||
{"link_stats", 0644, &fops_link_stats},
|
||||
{"link_stats_global", 0644, &fops_link_stats_global},
|
||||
{"rbufcap", 0244, &fops_rbufcap},
|
||||
};
|
||||
|
||||
static void wil6210_debugfs_init_files(struct wil6210_priv *wil,
|
||||
|
|
|
@ -340,7 +340,7 @@ static void _wil6210_disconnect_complete(struct wil6210_vif *vif,
|
|||
wil_dbg_misc(wil,
|
||||
"Disconnect complete %pM, CID=%d, reason=%d\n",
|
||||
bssid, cid, reason_code);
|
||||
if (cid >= 0) /* disconnect 1 peer */
|
||||
if (wil_cid_valid(wil, cid)) /* disconnect 1 peer */
|
||||
wil_disconnect_cid_complete(vif, cid, reason_code);
|
||||
} else { /* all */
|
||||
wil_dbg_misc(wil, "Disconnect complete all\n");
|
||||
|
@ -452,7 +452,7 @@ static void _wil6210_disconnect(struct wil6210_vif *vif, const u8 *bssid,
|
|||
cid = wil_find_cid(wil, vif->mid, bssid);
|
||||
wil_dbg_misc(wil, "Disconnect %pM, CID=%d, reason=%d\n",
|
||||
bssid, cid, reason_code);
|
||||
if (cid >= 0) /* disconnect 1 peer */
|
||||
if (wil_cid_valid(wil, cid)) /* disconnect 1 peer */
|
||||
wil_disconnect_cid(vif, cid, reason_code);
|
||||
} else { /* all */
|
||||
wil_dbg_misc(wil, "Disconnect all\n");
|
||||
|
@ -1522,6 +1522,7 @@ int wil_ps_update(struct wil6210_priv *wil, enum wmi_ps_profile_type ps_profile)
|
|||
|
||||
static void wil_pre_fw_config(struct wil6210_priv *wil)
|
||||
{
|
||||
wil_clear_fw_log_addr(wil);
|
||||
/* Mark FW as loaded from host */
|
||||
wil_s(wil, RGF_USER_USAGE_6, 1);
|
||||
|
||||
|
@ -1578,6 +1579,20 @@ static int wil_restore_vifs(struct wil6210_priv *wil)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear FW and ucode log start addr to indicate FW log is not ready. The host
|
||||
* driver clears the addresses before FW starts and FW initializes the address
|
||||
* when it is ready to send logs.
|
||||
*/
|
||||
void wil_clear_fw_log_addr(struct wil6210_priv *wil)
|
||||
{
|
||||
/* FW log addr */
|
||||
wil_w(wil, RGF_USER_USAGE_1, 0);
|
||||
/* ucode log addr */
|
||||
wil_w(wil, RGF_USER_USAGE_2, 0);
|
||||
wil_dbg_misc(wil, "Cleared FW and ucode log address");
|
||||
}
|
||||
|
||||
/*
|
||||
* We reset all the structures, and we reset the UMAC.
|
||||
* After calling this routine, you're expected to reload
|
||||
|
|
|
@ -420,6 +420,7 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
}
|
||||
/* rollback to bus_disable */
|
||||
|
||||
wil_clear_fw_log_addr(wil);
|
||||
rc = wil_if_add(wil);
|
||||
if (rc) {
|
||||
wil_err(wil, "wil_if_add failed: %d\n", rc);
|
||||
|
|
|
@ -316,7 +316,7 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
|
|||
u16 agg_timeout = le16_to_cpu(ba_timeout);
|
||||
u16 seq_ctrl = le16_to_cpu(ba_seq_ctrl);
|
||||
struct wil_sta_info *sta;
|
||||
u16 agg_wsize = 0;
|
||||
u16 agg_wsize;
|
||||
/* bit 0: A-MSDU supported
|
||||
* bit 1: policy (should be 0 for us)
|
||||
* bits 2..5: TID
|
||||
|
@ -328,7 +328,6 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
|
|||
test_bit(WMI_FW_CAPABILITY_AMSDU, wil->fw_capabilities) &&
|
||||
wil->amsdu_en && (param_set & BIT(0));
|
||||
int ba_policy = param_set & BIT(1);
|
||||
u16 status = WLAN_STATUS_SUCCESS;
|
||||
u16 ssn = seq_ctrl >> 4;
|
||||
struct wil_tid_ampdu_rx *r;
|
||||
int rc = 0;
|
||||
|
@ -355,27 +354,19 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
|
|||
agg_amsdu ? "+" : "-", !!ba_policy, dialog_token, ssn);
|
||||
|
||||
/* apply policies */
|
||||
if (ba_policy) {
|
||||
wil_err(wil, "BACK requested unsupported ba_policy == 1\n");
|
||||
status = WLAN_STATUS_INVALID_QOS_PARAM;
|
||||
}
|
||||
if (status == WLAN_STATUS_SUCCESS) {
|
||||
if (req_agg_wsize == 0) {
|
||||
wil_dbg_misc(wil, "Suggest BACK wsize %d\n",
|
||||
wil->max_agg_wsize);
|
||||
agg_wsize = wil->max_agg_wsize;
|
||||
} else {
|
||||
agg_wsize = min_t(u16,
|
||||
wil->max_agg_wsize, req_agg_wsize);
|
||||
}
|
||||
if (req_agg_wsize == 0) {
|
||||
wil_dbg_misc(wil, "Suggest BACK wsize %d\n",
|
||||
wil->max_agg_wsize);
|
||||
agg_wsize = wil->max_agg_wsize;
|
||||
} else {
|
||||
agg_wsize = min_t(u16, wil->max_agg_wsize, req_agg_wsize);
|
||||
}
|
||||
|
||||
rc = wil->txrx_ops.wmi_addba_rx_resp(wil, mid, cid, tid, dialog_token,
|
||||
status, agg_amsdu, agg_wsize,
|
||||
agg_timeout);
|
||||
if (rc || (status != WLAN_STATUS_SUCCESS)) {
|
||||
wil_err(wil, "do not apply ba, rc(%d), status(%d)\n", rc,
|
||||
status);
|
||||
WLAN_STATUS_SUCCESS, agg_amsdu,
|
||||
agg_wsize, agg_timeout);
|
||||
if (rc) {
|
||||
wil_err(wil, "do not apply ba, rc(%d)\n", rc);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
|
|
@ -1037,7 +1037,8 @@ static int wil_vring_init_tx(struct wil6210_vif *vif, int id, int size,
|
|||
if (!vif->privacy)
|
||||
txdata->dot1x_open = true;
|
||||
rc = wmi_call(wil, WMI_VRING_CFG_CMDID, vif->mid, &cmd, sizeof(cmd),
|
||||
WMI_VRING_CFG_DONE_EVENTID, &reply, sizeof(reply), 100);
|
||||
WMI_VRING_CFG_DONE_EVENTID, &reply, sizeof(reply),
|
||||
WIL_WMI_CALL_GENERAL_TO_MS);
|
||||
if (rc)
|
||||
goto out_free;
|
||||
|
||||
|
@ -1125,7 +1126,8 @@ static int wil_tx_vring_modify(struct wil6210_vif *vif, int ring_id, int cid,
|
|||
cmd.vring_cfg.tx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa);
|
||||
|
||||
rc = wmi_call(wil, WMI_VRING_CFG_CMDID, vif->mid, &cmd, sizeof(cmd),
|
||||
WMI_VRING_CFG_DONE_EVENTID, &reply, sizeof(reply), 100);
|
||||
WMI_VRING_CFG_DONE_EVENTID, &reply, sizeof(reply),
|
||||
WIL_WMI_CALL_GENERAL_TO_MS);
|
||||
if (rc)
|
||||
goto fail;
|
||||
|
||||
|
@ -1205,7 +1207,8 @@ int wil_vring_init_bcast(struct wil6210_vif *vif, int id, int size)
|
|||
txdata->dot1x_open = true;
|
||||
rc = wmi_call(wil, WMI_BCAST_VRING_CFG_CMDID, vif->mid,
|
||||
&cmd, sizeof(cmd),
|
||||
WMI_VRING_CFG_DONE_EVENTID, &reply, sizeof(reply), 100);
|
||||
WMI_VRING_CFG_DONE_EVENTID, &reply, sizeof(reply),
|
||||
WIL_WMI_CALL_GENERAL_TO_MS);
|
||||
if (rc)
|
||||
goto out_free;
|
||||
|
||||
|
|
|
@ -26,6 +26,10 @@
|
|||
#include "txrx.h"
|
||||
#include "trace.h"
|
||||
|
||||
/* Max number of entries (packets to complete) to update the hwtail of tx
|
||||
* status ring. Should be power of 2
|
||||
*/
|
||||
#define WIL_EDMA_TX_SRING_UPDATE_HW_TAIL 128
|
||||
#define WIL_EDMA_MAX_DATA_OFFSET (2)
|
||||
/* RX buffer size must be aligned to 4 bytes */
|
||||
#define WIL_EDMA_RX_BUF_LEN_DEFAULT (2048)
|
||||
|
@ -1155,7 +1159,7 @@ int wil_tx_sring_handler(struct wil6210_priv *wil,
|
|||
struct wil_net_stats *stats;
|
||||
struct wil_tx_enhanced_desc *_d;
|
||||
unsigned int ring_id;
|
||||
unsigned int num_descs;
|
||||
unsigned int num_descs, num_statuses = 0;
|
||||
int i;
|
||||
u8 dr_bit; /* Descriptor Ready bit */
|
||||
struct wil_ring_tx_status msg;
|
||||
|
@ -1276,6 +1280,11 @@ int wil_tx_sring_handler(struct wil6210_priv *wil,
|
|||
}
|
||||
|
||||
again:
|
||||
num_statuses++;
|
||||
if (num_statuses % WIL_EDMA_TX_SRING_UPDATE_HW_TAIL == 0)
|
||||
/* update HW tail to allow HW to push new statuses */
|
||||
wil_w(wil, sring->hwtail, sring->swhead);
|
||||
|
||||
wil_sring_advance_swhead(sring);
|
||||
|
||||
wil_get_next_tx_status_msg(sring, &msg);
|
||||
|
@ -1286,8 +1295,9 @@ again:
|
|||
if (desc_cnt)
|
||||
wil_update_net_queues(wil, vif, NULL, false);
|
||||
|
||||
/* Update the HW tail ptr (RD ptr) */
|
||||
wil_w(wil, sring->hwtail, (sring->swhead - 1) % sring->size);
|
||||
if (num_statuses % WIL_EDMA_TX_SRING_UPDATE_HW_TAIL != 0)
|
||||
/* Update the HW tail ptr (RD ptr) */
|
||||
wil_w(wil, sring->hwtail, (sring->swhead - 1) % sring->size);
|
||||
|
||||
return desc_cnt;
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#define WIL_SRING_SIZE_ORDER_MAX (WIL_RING_SIZE_ORDER_MAX)
|
||||
/* RX sring order should be bigger than RX ring order */
|
||||
#define WIL_RX_SRING_SIZE_ORDER_DEFAULT (12)
|
||||
#define WIL_TX_SRING_SIZE_ORDER_DEFAULT (12)
|
||||
#define WIL_TX_SRING_SIZE_ORDER_DEFAULT (14)
|
||||
#define WIL_RX_BUFF_ARR_SIZE_DEFAULT (2600)
|
||||
|
||||
#define WIL_DEFAULT_RX_STATUS_RING_ID 0
|
||||
|
|
|
@ -99,6 +99,7 @@ static inline u32 WIL_GET_BITS(u32 x, int b0, int b1)
|
|||
#define WIL_MAX_AMPDU_SIZE_128 (128 * 1024) /* FW/HW limit */
|
||||
#define WIL_MAX_AGG_WSIZE_64 (64) /* FW/HW limit */
|
||||
#define WIL6210_MAX_STATUS_RINGS (8)
|
||||
#define WIL_WMI_CALL_GENERAL_TO_MS 100
|
||||
|
||||
/* Hardware offload block adds the following:
|
||||
* 26 bytes - 3-address QoS data header
|
||||
|
@ -1252,6 +1253,9 @@ int wmi_rx_chain_add(struct wil6210_priv *wil, struct wil_ring *vring);
|
|||
int wmi_update_ft_ies(struct wil6210_vif *vif, u16 ie_len, const void *ie);
|
||||
int wmi_rxon(struct wil6210_priv *wil, bool on);
|
||||
int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_m, u32 *t_r);
|
||||
int wmi_get_all_temperatures(struct wil6210_priv *wil,
|
||||
struct wmi_temp_sense_all_done_event
|
||||
*sense_all_evt);
|
||||
int wmi_disconnect_sta(struct wil6210_vif *vif, const u8 *mac, u16 reason,
|
||||
bool del_sta);
|
||||
int wmi_addba(struct wil6210_priv *wil, u8 mid,
|
||||
|
@ -1406,6 +1410,7 @@ int wmi_stop_sched_scan(struct wil6210_priv *wil);
|
|||
int wmi_mgmt_tx(struct wil6210_vif *vif, const u8 *buf, size_t len);
|
||||
int wmi_mgmt_tx_ext(struct wil6210_vif *vif, const u8 *buf, size_t len,
|
||||
u8 channel, u16 duration_ms);
|
||||
int wmi_rbufcap_cfg(struct wil6210_priv *wil, bool enable, u16 threshold);
|
||||
|
||||
int reverse_memcmp(const void *cs, const void *ct, size_t count);
|
||||
|
||||
|
@ -1424,4 +1429,5 @@ int wmi_addba_rx_resp_edma(struct wil6210_priv *wil, u8 mid, u8 cid,
|
|||
|
||||
void update_supported_bands(struct wil6210_priv *wil);
|
||||
|
||||
void wil_clear_fw_log_addr(struct wil6210_priv *wil);
|
||||
#endif /* __WIL6210_H__ */
|
||||
|
|
|
@ -40,7 +40,6 @@ MODULE_PARM_DESC(led_id,
|
|||
" 60G device led enablement. Set the led ID (0-2) to enable");
|
||||
|
||||
#define WIL_WAIT_FOR_SUSPEND_RESUME_COMP 200
|
||||
#define WIL_WMI_CALL_GENERAL_TO_MS 100
|
||||
#define WIL_WMI_PCP_STOP_TO_MS 5000
|
||||
|
||||
/**
|
||||
|
@ -484,6 +483,10 @@ static const char *cmdid2name(u16 cmdid)
|
|||
return "WMI_FT_REASSOC_CMD";
|
||||
case WMI_UPDATE_FT_IES_CMDID:
|
||||
return "WMI_UPDATE_FT_IES_CMD";
|
||||
case WMI_RBUFCAP_CFG_CMDID:
|
||||
return "WMI_RBUFCAP_CFG_CMD";
|
||||
case WMI_TEMP_SENSE_ALL_CMDID:
|
||||
return "WMI_TEMP_SENSE_ALL_CMDID";
|
||||
default:
|
||||
return "Untracked CMD";
|
||||
}
|
||||
|
@ -628,6 +631,10 @@ static const char *eventid2name(u16 eventid)
|
|||
return "WMI_FT_AUTH_STATUS_EVENT";
|
||||
case WMI_FT_REASSOC_STATUS_EVENTID:
|
||||
return "WMI_FT_REASSOC_STATUS_EVENT";
|
||||
case WMI_RBUFCAP_CFG_EVENTID:
|
||||
return "WMI_RBUFCAP_CFG_EVENT";
|
||||
case WMI_TEMP_SENSE_ALL_DONE_EVENTID:
|
||||
return "WMI_TEMP_SENSE_ALL_DONE_EVENTID";
|
||||
default:
|
||||
return "Untracked EVENT";
|
||||
}
|
||||
|
@ -2051,7 +2058,8 @@ int wmi_echo(struct wil6210_priv *wil)
|
|||
};
|
||||
|
||||
return wmi_call(wil, WMI_ECHO_CMDID, vif->mid, &cmd, sizeof(cmd),
|
||||
WMI_ECHO_RSP_EVENTID, NULL, 0, 50);
|
||||
WMI_ECHO_RSP_EVENTID, NULL, 0,
|
||||
WIL_WMI_CALL_GENERAL_TO_MS);
|
||||
}
|
||||
|
||||
int wmi_set_mac_address(struct wil6210_priv *wil, void *addr)
|
||||
|
@ -2110,7 +2118,7 @@ int wmi_led_cfg(struct wil6210_priv *wil, bool enable)
|
|||
|
||||
rc = wmi_call(wil, WMI_LED_CFG_CMDID, vif->mid, &cmd, sizeof(cmd),
|
||||
WMI_LED_CFG_DONE_EVENTID, &reply, sizeof(reply),
|
||||
100);
|
||||
WIL_WMI_CALL_GENERAL_TO_MS);
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
|
@ -2124,6 +2132,37 @@ out:
|
|||
return rc;
|
||||
}
|
||||
|
||||
int wmi_rbufcap_cfg(struct wil6210_priv *wil, bool enable, u16 threshold)
|
||||
{
|
||||
struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
|
||||
int rc;
|
||||
|
||||
struct wmi_rbufcap_cfg_cmd cmd = {
|
||||
.enable = enable,
|
||||
.rx_desc_threshold = cpu_to_le16(threshold),
|
||||
};
|
||||
struct {
|
||||
struct wmi_cmd_hdr wmi;
|
||||
struct wmi_rbufcap_cfg_event evt;
|
||||
} __packed reply = {
|
||||
.evt = {.status = WMI_FW_STATUS_FAILURE},
|
||||
};
|
||||
|
||||
rc = wmi_call(wil, WMI_RBUFCAP_CFG_CMDID, vif->mid, &cmd, sizeof(cmd),
|
||||
WMI_RBUFCAP_CFG_EVENTID, &reply, sizeof(reply),
|
||||
WIL_WMI_CALL_GENERAL_TO_MS);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (reply.evt.status != WMI_FW_STATUS_SUCCESS) {
|
||||
wil_err(wil, "RBUFCAP_CFG failed. status %d\n",
|
||||
reply.evt.status);
|
||||
rc = -EINVAL;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int wmi_pcp_start(struct wil6210_vif *vif,
|
||||
int bi, u8 wmi_nettype, u8 chan, u8 hidden_ssid, u8 is_go)
|
||||
{
|
||||
|
@ -2228,7 +2267,8 @@ int wmi_get_ssid(struct wil6210_vif *vif, u8 *ssid_len, void *ssid)
|
|||
memset(&reply, 0, sizeof(reply));
|
||||
|
||||
rc = wmi_call(wil, WMI_GET_SSID_CMDID, vif->mid, NULL, 0,
|
||||
WMI_GET_SSID_EVENTID, &reply, sizeof(reply), 20);
|
||||
WMI_GET_SSID_EVENTID, &reply, sizeof(reply),
|
||||
WIL_WMI_CALL_GENERAL_TO_MS);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
|
@ -2265,7 +2305,8 @@ int wmi_get_channel(struct wil6210_priv *wil, int *channel)
|
|||
memset(&reply, 0, sizeof(reply));
|
||||
|
||||
rc = wmi_call(wil, WMI_GET_PCP_CHANNEL_CMDID, vif->mid, NULL, 0,
|
||||
WMI_GET_PCP_CHANNEL_EVENTID, &reply, sizeof(reply), 20);
|
||||
WMI_GET_PCP_CHANNEL_EVENTID, &reply, sizeof(reply),
|
||||
WIL_WMI_CALL_GENERAL_TO_MS);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
|
@ -2361,7 +2402,8 @@ int wmi_stop_discovery(struct wil6210_vif *vif)
|
|||
wil_dbg_wmi(wil, "sending WMI_DISCOVERY_STOP_CMDID\n");
|
||||
|
||||
rc = wmi_call(wil, WMI_DISCOVERY_STOP_CMDID, vif->mid, NULL, 0,
|
||||
WMI_DISCOVERY_STOPPED_EVENTID, NULL, 0, 100);
|
||||
WMI_DISCOVERY_STOPPED_EVENTID, NULL, 0,
|
||||
WIL_WMI_CALL_GENERAL_TO_MS);
|
||||
|
||||
if (rc)
|
||||
wil_err(wil, "Failed to stop discovery\n");
|
||||
|
@ -2507,12 +2549,14 @@ int wmi_rxon(struct wil6210_priv *wil, bool on)
|
|||
if (on) {
|
||||
rc = wmi_call(wil, WMI_START_LISTEN_CMDID, vif->mid, NULL, 0,
|
||||
WMI_LISTEN_STARTED_EVENTID,
|
||||
&reply, sizeof(reply), 100);
|
||||
&reply, sizeof(reply),
|
||||
WIL_WMI_CALL_GENERAL_TO_MS);
|
||||
if ((rc == 0) && (reply.evt.status != WMI_FW_STATUS_SUCCESS))
|
||||
rc = -EINVAL;
|
||||
} else {
|
||||
rc = wmi_call(wil, WMI_DISCOVERY_STOP_CMDID, vif->mid, NULL, 0,
|
||||
WMI_DISCOVERY_STOPPED_EVENTID, NULL, 0, 20);
|
||||
WMI_DISCOVERY_STOPPED_EVENTID, NULL, 0,
|
||||
WIL_WMI_CALL_GENERAL_TO_MS);
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
@ -2601,7 +2645,8 @@ int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_bb, u32 *t_rf)
|
|||
memset(&reply, 0, sizeof(reply));
|
||||
|
||||
rc = wmi_call(wil, WMI_TEMP_SENSE_CMDID, vif->mid, &cmd, sizeof(cmd),
|
||||
WMI_TEMP_SENSE_DONE_EVENTID, &reply, sizeof(reply), 100);
|
||||
WMI_TEMP_SENSE_DONE_EVENTID, &reply, sizeof(reply),
|
||||
WIL_WMI_CALL_GENERAL_TO_MS);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
|
@ -2613,6 +2658,44 @@ int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_bb, u32 *t_rf)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int wmi_get_all_temperatures(struct wil6210_priv *wil,
|
||||
struct wmi_temp_sense_all_done_event
|
||||
*sense_all_evt)
|
||||
{
|
||||
struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
|
||||
int rc;
|
||||
struct wmi_temp_sense_all_cmd cmd = {
|
||||
.measure_baseband_en = true,
|
||||
.measure_rf_en = true,
|
||||
.measure_mode = TEMPERATURE_MEASURE_NOW,
|
||||
};
|
||||
struct {
|
||||
struct wmi_cmd_hdr wmi;
|
||||
struct wmi_temp_sense_all_done_event evt;
|
||||
} __packed reply;
|
||||
|
||||
if (!sense_all_evt) {
|
||||
wil_err(wil, "Invalid sense_all_evt value\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memset(&reply, 0, sizeof(reply));
|
||||
reply.evt.status = WMI_FW_STATUS_FAILURE;
|
||||
rc = wmi_call(wil, WMI_TEMP_SENSE_ALL_CMDID, vif->mid, &cmd,
|
||||
sizeof(cmd), WMI_TEMP_SENSE_ALL_DONE_EVENTID,
|
||||
&reply, sizeof(reply), WIL_WMI_CALL_GENERAL_TO_MS);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (reply.evt.status == WMI_FW_STATUS_FAILURE) {
|
||||
wil_err(wil, "Failed geting TEMP_SENSE_ALL\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memcpy(sense_all_evt, &reply.evt, sizeof(reply.evt));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wmi_disconnect_sta(struct wil6210_vif *vif, const u8 *mac, u16 reason,
|
||||
bool del_sta)
|
||||
{
|
||||
|
@ -2715,7 +2798,7 @@ int wmi_addba_rx_resp(struct wil6210_priv *wil,
|
|||
.dialog_token = token,
|
||||
.status_code = cpu_to_le16(status),
|
||||
/* bit 0: A-MSDU supported
|
||||
* bit 1: policy (should be 0 for us)
|
||||
* bit 1: policy (controlled by FW)
|
||||
* bits 2..5: TID
|
||||
* bits 6..15: buffer size
|
||||
*/
|
||||
|
@ -2745,7 +2828,7 @@ int wmi_addba_rx_resp(struct wil6210_priv *wil,
|
|||
|
||||
rc = wmi_call(wil, WMI_RCP_ADDBA_RESP_CMDID, mid, &cmd, sizeof(cmd),
|
||||
WMI_RCP_ADDBA_RESP_SENT_EVENTID, &reply, sizeof(reply),
|
||||
100);
|
||||
WIL_WMI_CALL_GENERAL_TO_MS);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
|
@ -2769,7 +2852,7 @@ int wmi_addba_rx_resp_edma(struct wil6210_priv *wil, u8 mid, u8 cid, u8 tid,
|
|||
.dialog_token = token,
|
||||
.status_code = cpu_to_le16(status),
|
||||
/* bit 0: A-MSDU supported
|
||||
* bit 1: policy (should be 0 for us)
|
||||
* bit 1: policy (controlled by FW)
|
||||
* bits 2..5: TID
|
||||
* bits 6..15: buffer size
|
||||
*/
|
||||
|
@ -2827,7 +2910,7 @@ int wmi_ps_dev_profile_cfg(struct wil6210_priv *wil,
|
|||
rc = wmi_call(wil, WMI_PS_DEV_PROFILE_CFG_CMDID, vif->mid,
|
||||
&cmd, sizeof(cmd),
|
||||
WMI_PS_DEV_PROFILE_CFG_EVENTID, &reply, sizeof(reply),
|
||||
100);
|
||||
WIL_WMI_CALL_GENERAL_TO_MS);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
|
@ -2864,7 +2947,7 @@ int wmi_set_mgmt_retry(struct wil6210_priv *wil, u8 retry_short)
|
|||
rc = wmi_call(wil, WMI_SET_MGMT_RETRY_LIMIT_CMDID, vif->mid,
|
||||
&cmd, sizeof(cmd),
|
||||
WMI_SET_MGMT_RETRY_LIMIT_EVENTID, &reply, sizeof(reply),
|
||||
100);
|
||||
WIL_WMI_CALL_GENERAL_TO_MS);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
|
@ -2894,7 +2977,7 @@ int wmi_get_mgmt_retry(struct wil6210_priv *wil, u8 *retry_short)
|
|||
memset(&reply, 0, sizeof(reply));
|
||||
rc = wmi_call(wil, WMI_GET_MGMT_RETRY_LIMIT_CMDID, vif->mid, NULL, 0,
|
||||
WMI_GET_MGMT_RETRY_LIMIT_EVENTID, &reply, sizeof(reply),
|
||||
100);
|
||||
WIL_WMI_CALL_GENERAL_TO_MS);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
|
@ -3220,7 +3303,18 @@ static void wmi_event_handle(struct wil6210_priv *wil,
|
|||
/* check if someone waits for this event */
|
||||
if (wil->reply_id && wil->reply_id == id &&
|
||||
wil->reply_mid == mid) {
|
||||
WARN_ON(wil->reply_buf);
|
||||
if (wil->reply_buf) {
|
||||
/* event received while wmi_call is waiting
|
||||
* with a buffer. Such event should be handled
|
||||
* in wmi_recv_cmd function. Handling the event
|
||||
* here means a previous wmi_call was timeout.
|
||||
* Drop the event and do not handle it.
|
||||
*/
|
||||
wil_err(wil,
|
||||
"Old event (%d, %s) while wmi_call is waiting. Drop it and Continue waiting\n",
|
||||
id, eventid2name(id));
|
||||
return;
|
||||
}
|
||||
|
||||
wmi_evt_call_handler(vif, id, evt_data,
|
||||
len - sizeof(*wmi));
|
||||
|
@ -3800,6 +3894,7 @@ int wil_wmi_bcast_desc_ring_add(struct wil6210_vif *vif, int ring_id)
|
|||
.ring_size = cpu_to_le16(ring->size),
|
||||
.ring_id = ring_id,
|
||||
},
|
||||
.max_msdu_size = cpu_to_le16(wil_mtu2macbuf(mtu_max)),
|
||||
.status_ring_id = wil->tx_sring_idx,
|
||||
.encap_trans_type = WMI_VRING_ENC_TYPE_802_3,
|
||||
};
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#define WMI_PROX_RANGE_NUM (3)
|
||||
#define WMI_MAX_LOSS_DMG_BEACONS (20)
|
||||
#define MAX_NUM_OF_SECTORS (128)
|
||||
#define WMI_INVALID_TEMPERATURE (0xFFFFFFFF)
|
||||
#define WMI_SCHED_MAX_ALLOCS_PER_CMD (4)
|
||||
#define WMI_RF_DTYPE_LENGTH (3)
|
||||
#define WMI_RF_ETYPE_LENGTH (3)
|
||||
|
@ -64,6 +65,7 @@
|
|||
#define WMI_QOS_MAX_WEIGHT 50
|
||||
#define WMI_QOS_SET_VIF_PRIORITY (0xFF)
|
||||
#define WMI_QOS_DEFAULT_PRIORITY (WMI_QOS_NUM_OF_PRIORITY)
|
||||
#define WMI_MAX_XIF_PORTS_NUM (8)
|
||||
|
||||
/* Mailbox interface
|
||||
* used for commands and events
|
||||
|
@ -105,6 +107,7 @@ enum wmi_fw_capability {
|
|||
WMI_FW_CAPABILITY_TX_REQ_EXT = 25,
|
||||
WMI_FW_CAPABILITY_CHANNEL_4 = 26,
|
||||
WMI_FW_CAPABILITY_IPA = 27,
|
||||
WMI_FW_CAPABILITY_TEMPERATURE_ALL_RF = 30,
|
||||
WMI_FW_CAPABILITY_MAX,
|
||||
};
|
||||
|
||||
|
@ -296,6 +299,7 @@ enum wmi_command_id {
|
|||
WMI_SET_VRING_PRIORITY_WEIGHT_CMDID = 0xA10,
|
||||
WMI_SET_VRING_PRIORITY_CMDID = 0xA11,
|
||||
WMI_RBUFCAP_CFG_CMDID = 0xA12,
|
||||
WMI_TEMP_SENSE_ALL_CMDID = 0xA13,
|
||||
WMI_SET_MAC_ADDRESS_CMDID = 0xF003,
|
||||
WMI_ABORT_SCAN_CMDID = 0xF007,
|
||||
WMI_SET_PROMISCUOUS_MODE_CMDID = 0xF041,
|
||||
|
@ -1411,12 +1415,7 @@ struct wmi_rf_xpm_write_cmd {
|
|||
u8 data_bytes[0];
|
||||
} __packed;
|
||||
|
||||
/* WMI_TEMP_SENSE_CMDID
|
||||
*
|
||||
* Measure MAC and radio temperatures
|
||||
*
|
||||
* Possible modes for temperature measurement
|
||||
*/
|
||||
/* Possible modes for temperature measurement */
|
||||
enum wmi_temperature_measure_mode {
|
||||
TEMPERATURE_USE_OLD_VALUE = 0x01,
|
||||
TEMPERATURE_MEASURE_NOW = 0x02,
|
||||
|
@ -1942,6 +1941,14 @@ struct wmi_set_ap_slot_size_cmd {
|
|||
__le32 slot_size;
|
||||
} __packed;
|
||||
|
||||
/* WMI_TEMP_SENSE_ALL_CMDID */
|
||||
struct wmi_temp_sense_all_cmd {
|
||||
u8 measure_baseband_en;
|
||||
u8 measure_rf_en;
|
||||
u8 measure_mode;
|
||||
u8 reserved;
|
||||
} __packed;
|
||||
|
||||
/* WMI Events
|
||||
* List of Events (target to host)
|
||||
*/
|
||||
|
@ -2101,6 +2108,7 @@ enum wmi_event_id {
|
|||
WMI_SET_VRING_PRIORITY_WEIGHT_EVENTID = 0x1A10,
|
||||
WMI_SET_VRING_PRIORITY_EVENTID = 0x1A11,
|
||||
WMI_RBUFCAP_CFG_EVENTID = 0x1A12,
|
||||
WMI_TEMP_SENSE_ALL_DONE_EVENTID = 0x1A13,
|
||||
WMI_SET_CHANNEL_EVENTID = 0x9000,
|
||||
WMI_ASSOC_REQ_EVENTID = 0x9001,
|
||||
WMI_EAPOL_RX_EVENTID = 0x9002,
|
||||
|
@ -2784,11 +2792,13 @@ struct wmi_fixed_scheduling_ul_config_event {
|
|||
*/
|
||||
struct wmi_temp_sense_done_event {
|
||||
/* Temperature times 1000 (actual temperature will be achieved by
|
||||
* dividing the value by 1000)
|
||||
* dividing the value by 1000). When temperature cannot be read from
|
||||
* device return WMI_INVALID_TEMPERATURE
|
||||
*/
|
||||
__le32 baseband_t1000;
|
||||
/* Temperature times 1000 (actual temperature will be achieved by
|
||||
* dividing the value by 1000)
|
||||
* dividing the value by 1000). When temperature cannot be read from
|
||||
* device return WMI_INVALID_TEMPERATURE
|
||||
*/
|
||||
__le32 rf_t1000;
|
||||
} __packed;
|
||||
|
@ -4140,4 +4150,25 @@ struct wmi_rbufcap_cfg_event {
|
|||
u8 reserved[3];
|
||||
} __packed;
|
||||
|
||||
/* WMI_TEMP_SENSE_ALL_DONE_EVENTID
|
||||
* Measure MAC and all radio temperatures
|
||||
*/
|
||||
struct wmi_temp_sense_all_done_event {
|
||||
/* enum wmi_fw_status */
|
||||
u8 status;
|
||||
/* Bitmap of connected RFs */
|
||||
u8 rf_bitmap;
|
||||
u8 reserved[2];
|
||||
/* Temperature times 1000 (actual temperature will be achieved by
|
||||
* dividing the value by 1000). When temperature cannot be read from
|
||||
* device return WMI_INVALID_TEMPERATURE
|
||||
*/
|
||||
__le32 rf_t1000[WMI_MAX_XIF_PORTS_NUM];
|
||||
/* Temperature times 1000 (actual temperature will be achieved by
|
||||
* dividing the value by 1000). When temperature cannot be read from
|
||||
* device return WMI_INVALID_TEMPERATURE
|
||||
*/
|
||||
__le32 baseband_t1000;
|
||||
} __packed;
|
||||
|
||||
#endif /* __WILOCITY_WMI_H__ */
|
||||
|
|
|
@ -797,7 +797,7 @@ static void free_all_descbuffers(struct b43_dmaring *ring)
|
|||
}
|
||||
}
|
||||
|
||||
static u64 supported_dma_mask(struct b43_wldev *dev)
|
||||
static enum b43_dmatype b43_engine_type(struct b43_wldev *dev)
|
||||
{
|
||||
u32 tmp;
|
||||
u16 mmio_base;
|
||||
|
@ -807,14 +807,14 @@ static u64 supported_dma_mask(struct b43_wldev *dev)
|
|||
case B43_BUS_BCMA:
|
||||
tmp = bcma_aread32(dev->dev->bdev, BCMA_IOST);
|
||||
if (tmp & BCMA_IOST_DMA64)
|
||||
return DMA_BIT_MASK(64);
|
||||
return B43_DMA_64BIT;
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_B43_SSB
|
||||
case B43_BUS_SSB:
|
||||
tmp = ssb_read32(dev->dev->sdev, SSB_TMSHIGH);
|
||||
if (tmp & SSB_TMSHIGH_DMA64)
|
||||
return DMA_BIT_MASK(64);
|
||||
return B43_DMA_64BIT;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
@ -823,20 +823,7 @@ static u64 supported_dma_mask(struct b43_wldev *dev)
|
|||
b43_write32(dev, mmio_base + B43_DMA32_TXCTL, B43_DMA32_TXADDREXT_MASK);
|
||||
tmp = b43_read32(dev, mmio_base + B43_DMA32_TXCTL);
|
||||
if (tmp & B43_DMA32_TXADDREXT_MASK)
|
||||
return DMA_BIT_MASK(32);
|
||||
|
||||
return DMA_BIT_MASK(30);
|
||||
}
|
||||
|
||||
static enum b43_dmatype dma_mask_to_engine_type(u64 dmamask)
|
||||
{
|
||||
if (dmamask == DMA_BIT_MASK(30))
|
||||
return B43_DMA_30BIT;
|
||||
if (dmamask == DMA_BIT_MASK(32))
|
||||
return B43_DMA_32BIT;
|
||||
if (dmamask == DMA_BIT_MASK(64))
|
||||
return B43_DMA_64BIT;
|
||||
B43_WARN_ON(1);
|
||||
return B43_DMA_30BIT;
|
||||
}
|
||||
|
||||
|
@ -1043,42 +1030,6 @@ void b43_dma_free(struct b43_wldev *dev)
|
|||
destroy_ring(dma, tx_ring_mcast);
|
||||
}
|
||||
|
||||
static int b43_dma_set_mask(struct b43_wldev *dev, u64 mask)
|
||||
{
|
||||
u64 orig_mask = mask;
|
||||
bool fallback = false;
|
||||
int err;
|
||||
|
||||
/* Try to set the DMA mask. If it fails, try falling back to a
|
||||
* lower mask, as we can always also support a lower one. */
|
||||
while (1) {
|
||||
err = dma_set_mask_and_coherent(dev->dev->dma_dev, mask);
|
||||
if (!err)
|
||||
break;
|
||||
if (mask == DMA_BIT_MASK(64)) {
|
||||
mask = DMA_BIT_MASK(32);
|
||||
fallback = true;
|
||||
continue;
|
||||
}
|
||||
if (mask == DMA_BIT_MASK(32)) {
|
||||
mask = DMA_BIT_MASK(30);
|
||||
fallback = true;
|
||||
continue;
|
||||
}
|
||||
b43err(dev->wl, "The machine/kernel does not support "
|
||||
"the required %u-bit DMA mask\n",
|
||||
(unsigned int)dma_mask_to_engine_type(orig_mask));
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
if (fallback) {
|
||||
b43info(dev->wl, "DMA mask fallback from %u-bit to %u-bit\n",
|
||||
(unsigned int)dma_mask_to_engine_type(orig_mask),
|
||||
(unsigned int)dma_mask_to_engine_type(mask));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Some hardware with 64-bit DMA seems to be bugged and looks for translation
|
||||
* bit in low address word instead of high one.
|
||||
*/
|
||||
|
@ -1101,15 +1052,15 @@ static bool b43_dma_translation_in_low_word(struct b43_wldev *dev,
|
|||
int b43_dma_init(struct b43_wldev *dev)
|
||||
{
|
||||
struct b43_dma *dma = &dev->dma;
|
||||
enum b43_dmatype type = b43_engine_type(dev);
|
||||
int err;
|
||||
u64 dmamask;
|
||||
enum b43_dmatype type;
|
||||
|
||||
dmamask = supported_dma_mask(dev);
|
||||
type = dma_mask_to_engine_type(dmamask);
|
||||
err = b43_dma_set_mask(dev, dmamask);
|
||||
if (err)
|
||||
err = dma_set_mask_and_coherent(dev->dev->dma_dev, DMA_BIT_MASK(type));
|
||||
if (err) {
|
||||
b43err(dev->wl, "The machine/kernel does not support "
|
||||
"the required %u-bit DMA mask\n", type);
|
||||
return err;
|
||||
}
|
||||
|
||||
switch (dev->dev->bus_type) {
|
||||
#ifdef CONFIG_B43_BCMA
|
||||
|
@ -1813,7 +1764,7 @@ void b43_dma_direct_fifo_rx(struct b43_wldev *dev,
|
|||
enum b43_dmatype type;
|
||||
u16 mmio_base;
|
||||
|
||||
type = dma_mask_to_engine_type(supported_dma_mask(dev));
|
||||
type = b43_engine_type(dev);
|
||||
|
||||
mmio_base = b43_dmacontroller_base(type, engine_index);
|
||||
direct_fifo_rx(dev, type, mmio_base, enable);
|
||||
|
|
|
@ -603,7 +603,7 @@ static void free_all_descbuffers(struct b43legacy_dmaring *ring)
|
|||
}
|
||||
}
|
||||
|
||||
static u64 supported_dma_mask(struct b43legacy_wldev *dev)
|
||||
static enum b43legacy_dmatype b43legacy_engine_type(struct b43legacy_wldev *dev)
|
||||
{
|
||||
u32 tmp;
|
||||
u16 mmio_base;
|
||||
|
@ -615,18 +615,7 @@ static u64 supported_dma_mask(struct b43legacy_wldev *dev)
|
|||
tmp = b43legacy_read32(dev, mmio_base +
|
||||
B43legacy_DMA32_TXCTL);
|
||||
if (tmp & B43legacy_DMA32_TXADDREXT_MASK)
|
||||
return DMA_BIT_MASK(32);
|
||||
|
||||
return DMA_BIT_MASK(30);
|
||||
}
|
||||
|
||||
static enum b43legacy_dmatype dma_mask_to_engine_type(u64 dmamask)
|
||||
{
|
||||
if (dmamask == DMA_BIT_MASK(30))
|
||||
return B43legacy_DMA_30BIT;
|
||||
if (dmamask == DMA_BIT_MASK(32))
|
||||
return B43legacy_DMA_32BIT;
|
||||
B43legacy_WARN_ON(1);
|
||||
return B43legacy_DMA_30BIT;
|
||||
}
|
||||
|
||||
|
@ -784,54 +773,14 @@ void b43legacy_dma_free(struct b43legacy_wldev *dev)
|
|||
dma->tx_ring0 = NULL;
|
||||
}
|
||||
|
||||
static int b43legacy_dma_set_mask(struct b43legacy_wldev *dev, u64 mask)
|
||||
{
|
||||
u64 orig_mask = mask;
|
||||
bool fallback = false;
|
||||
int err;
|
||||
|
||||
/* Try to set the DMA mask. If it fails, try falling back to a
|
||||
* lower mask, as we can always also support a lower one. */
|
||||
while (1) {
|
||||
err = dma_set_mask_and_coherent(dev->dev->dma_dev, mask);
|
||||
if (!err)
|
||||
break;
|
||||
if (mask == DMA_BIT_MASK(64)) {
|
||||
mask = DMA_BIT_MASK(32);
|
||||
fallback = true;
|
||||
continue;
|
||||
}
|
||||
if (mask == DMA_BIT_MASK(32)) {
|
||||
mask = DMA_BIT_MASK(30);
|
||||
fallback = true;
|
||||
continue;
|
||||
}
|
||||
b43legacyerr(dev->wl, "The machine/kernel does not support "
|
||||
"the required %u-bit DMA mask\n",
|
||||
(unsigned int)dma_mask_to_engine_type(orig_mask));
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
if (fallback) {
|
||||
b43legacyinfo(dev->wl, "DMA mask fallback from %u-bit to %u-"
|
||||
"bit\n",
|
||||
(unsigned int)dma_mask_to_engine_type(orig_mask),
|
||||
(unsigned int)dma_mask_to_engine_type(mask));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int b43legacy_dma_init(struct b43legacy_wldev *dev)
|
||||
{
|
||||
struct b43legacy_dma *dma = &dev->dma;
|
||||
struct b43legacy_dmaring *ring;
|
||||
enum b43legacy_dmatype type = b43legacy_engine_type(dev);
|
||||
int err;
|
||||
u64 dmamask;
|
||||
enum b43legacy_dmatype type;
|
||||
|
||||
dmamask = supported_dma_mask(dev);
|
||||
type = dma_mask_to_engine_type(dmamask);
|
||||
err = b43legacy_dma_set_mask(dev, dmamask);
|
||||
err = dma_set_mask_and_coherent(dev->dev->dma_dev, DMA_BIT_MASK(type));
|
||||
if (err) {
|
||||
#ifdef CONFIG_B43LEGACY_PIO
|
||||
b43legacywarn(dev->wl, "DMA for this device not supported. "
|
||||
|
|
|
@ -1009,8 +1009,7 @@ int iwlagn_send_patterns(struct iwl_priv *priv,
|
|||
if (!wowlan->n_patterns)
|
||||
return 0;
|
||||
|
||||
cmd.len[0] = sizeof(*pattern_cmd) +
|
||||
wowlan->n_patterns * sizeof(struct iwlagn_wowlan_pattern);
|
||||
cmd.len[0] = struct_size(pattern_cmd, patterns, wowlan->n_patterns);
|
||||
|
||||
pattern_cmd = kmalloc(cmd.len[0], GFP_KERNEL);
|
||||
if (!pattern_cmd)
|
||||
|
|
|
@ -97,7 +97,7 @@ IWL_EXPORT_SYMBOL(iwl_acpi_get_object);
|
|||
|
||||
union acpi_object *iwl_acpi_get_wifi_pkg(struct device *dev,
|
||||
union acpi_object *data,
|
||||
int data_size)
|
||||
int data_size, int *tbl_rev)
|
||||
{
|
||||
int i;
|
||||
union acpi_object *wifi_pkg;
|
||||
|
@ -113,16 +113,19 @@ union acpi_object *iwl_acpi_get_wifi_pkg(struct device *dev,
|
|||
/*
|
||||
* We need at least two packages, one for the revision and one
|
||||
* for the data itself. Also check that the revision is valid
|
||||
* (i.e. it is an integer set to 0).
|
||||
* (i.e. it is an integer smaller than 2, as we currently support only
|
||||
* 2 revisions).
|
||||
*/
|
||||
if (data->type != ACPI_TYPE_PACKAGE ||
|
||||
data->package.count < 2 ||
|
||||
data->package.elements[0].type != ACPI_TYPE_INTEGER ||
|
||||
data->package.elements[0].integer.value != 0) {
|
||||
data->package.elements[0].integer.value > 1) {
|
||||
IWL_DEBUG_DEV_RADIO(dev, "Unsupported packages structure\n");
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
*tbl_rev = data->package.elements[0].integer.value;
|
||||
|
||||
/* loop through all the packages to find the one for WiFi */
|
||||
for (i = 1; i < data->package.count; i++) {
|
||||
union acpi_object *domain;
|
||||
|
@ -151,14 +154,15 @@ int iwl_acpi_get_mcc(struct device *dev, char *mcc)
|
|||
{
|
||||
union acpi_object *wifi_pkg, *data;
|
||||
u32 mcc_val;
|
||||
int ret;
|
||||
int ret, tbl_rev;
|
||||
|
||||
data = iwl_acpi_get_object(dev, ACPI_WRDD_METHOD);
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
|
||||
wifi_pkg = iwl_acpi_get_wifi_pkg(dev, data, ACPI_WRDD_WIFI_DATA_SIZE);
|
||||
if (IS_ERR(wifi_pkg)) {
|
||||
wifi_pkg = iwl_acpi_get_wifi_pkg(dev, data, ACPI_WRDD_WIFI_DATA_SIZE,
|
||||
&tbl_rev);
|
||||
if (IS_ERR(wifi_pkg) || tbl_rev != 0) {
|
||||
ret = PTR_ERR(wifi_pkg);
|
||||
goto out_free;
|
||||
}
|
||||
|
@ -185,6 +189,7 @@ u64 iwl_acpi_get_pwr_limit(struct device *dev)
|
|||
{
|
||||
union acpi_object *data, *wifi_pkg;
|
||||
u64 dflt_pwr_limit;
|
||||
int tbl_rev;
|
||||
|
||||
data = iwl_acpi_get_object(dev, ACPI_SPLC_METHOD);
|
||||
if (IS_ERR(data)) {
|
||||
|
@ -193,8 +198,8 @@ u64 iwl_acpi_get_pwr_limit(struct device *dev)
|
|||
}
|
||||
|
||||
wifi_pkg = iwl_acpi_get_wifi_pkg(dev, data,
|
||||
ACPI_SPLC_WIFI_DATA_SIZE);
|
||||
if (IS_ERR(wifi_pkg) ||
|
||||
ACPI_SPLC_WIFI_DATA_SIZE, &tbl_rev);
|
||||
if (IS_ERR(wifi_pkg) || tbl_rev != 0 ||
|
||||
wifi_pkg->package.elements[1].integer.value != ACPI_TYPE_INTEGER) {
|
||||
dflt_pwr_limit = 0;
|
||||
goto out_free;
|
||||
|
@ -211,14 +216,15 @@ IWL_EXPORT_SYMBOL(iwl_acpi_get_pwr_limit);
|
|||
int iwl_acpi_get_eckv(struct device *dev, u32 *extl_clk)
|
||||
{
|
||||
union acpi_object *wifi_pkg, *data;
|
||||
int ret;
|
||||
int ret, tbl_rev;
|
||||
|
||||
data = iwl_acpi_get_object(dev, ACPI_ECKV_METHOD);
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
|
||||
wifi_pkg = iwl_acpi_get_wifi_pkg(dev, data, ACPI_ECKV_WIFI_DATA_SIZE);
|
||||
if (IS_ERR(wifi_pkg)) {
|
||||
wifi_pkg = iwl_acpi_get_wifi_pkg(dev, data, ACPI_ECKV_WIFI_DATA_SIZE,
|
||||
&tbl_rev);
|
||||
if (IS_ERR(wifi_pkg) || tbl_rev != 0) {
|
||||
ret = PTR_ERR(wifi_pkg);
|
||||
goto out_free;
|
||||
}
|
||||
|
|
|
@ -97,7 +97,7 @@
|
|||
void *iwl_acpi_get_object(struct device *dev, acpi_string method);
|
||||
union acpi_object *iwl_acpi_get_wifi_pkg(struct device *dev,
|
||||
union acpi_object *data,
|
||||
int data_size);
|
||||
int data_size, int *tbl_rev);
|
||||
|
||||
/**
|
||||
* iwl_acpi_get_mcc - read MCC from ACPI, if available
|
||||
|
@ -131,7 +131,8 @@ static inline void *iwl_acpi_get_object(struct device *dev, acpi_string method)
|
|||
|
||||
static inline union acpi_object *iwl_acpi_get_wifi_pkg(struct device *dev,
|
||||
union acpi_object *data,
|
||||
int data_size)
|
||||
int data_size,
|
||||
int *tbl_rev)
|
||||
{
|
||||
return ERR_PTR(-ENOENT);
|
||||
}
|
||||
|
|
|
@ -291,6 +291,28 @@ struct iwl_fw_ini_trigger_tlv {
|
|||
struct iwl_fw_ini_trigger trigger_config[];
|
||||
} __packed; /* FW_TLV_DEBUG_TRIGGERS_API_S_VER_1 */
|
||||
|
||||
#define IWL_FW_INI_MAX_IMG_NAME_LEN 32
|
||||
#define IWL_FW_INI_MAX_DBG_CFG_NAME_LEN 64
|
||||
|
||||
/**
|
||||
* struct iwl_fw_ini_debug_info_tlv - (IWL_UCODE_TLV_TYPE_DEBUG_INFO)
|
||||
*
|
||||
* holds image name and debug configuration name
|
||||
*
|
||||
* @header: header
|
||||
* @img_name_len: length of the image name string
|
||||
* @img_name: image name string
|
||||
* @dbg_cfg_name_len : length of the debug configuration name string
|
||||
* @dbg_cfg_name: debug configuration name string
|
||||
*/
|
||||
struct iwl_fw_ini_debug_info_tlv {
|
||||
struct iwl_fw_ini_header header;
|
||||
__le32 img_name_len;
|
||||
u8 img_name[IWL_FW_INI_MAX_IMG_NAME_LEN];
|
||||
__le32 dbg_cfg_name_len;
|
||||
u8 dbg_cfg_name[IWL_FW_INI_MAX_DBG_CFG_NAME_LEN];
|
||||
} __packed; /* FW_DEBUG_TLV_INFO_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* enum iwl_fw_ini_trigger_id
|
||||
*
|
||||
|
|
|
@ -937,8 +937,13 @@ struct iwl_ftm_responder_stats {
|
|||
__le16 reserved;
|
||||
} __packed; /* TOF_RESPONDER_STATISTICS_NTFY_S_VER_2 */
|
||||
|
||||
#define IWL_CSI_CHUNK_CTL_NUM_MASK 0x3
|
||||
#define IWL_CSI_CHUNK_CTL_IDX_MASK 0xc
|
||||
#define IWL_CSI_MAX_EXPECTED_CHUNKS 16
|
||||
|
||||
#define IWL_CSI_CHUNK_CTL_NUM_MASK_VER_1 0x0003
|
||||
#define IWL_CSI_CHUNK_CTL_IDX_MASK_VER_1 0x000c
|
||||
|
||||
#define IWL_CSI_CHUNK_CTL_NUM_MASK_VER_2 0x00ff
|
||||
#define IWL_CSI_CHUNK_CTL_IDX_MASK_VER_2 0xff00
|
||||
|
||||
struct iwl_csi_chunk_notification {
|
||||
__le32 token;
|
||||
|
@ -946,6 +951,6 @@ struct iwl_csi_chunk_notification {
|
|||
__le16 ctl;
|
||||
__le32 size;
|
||||
u8 data[];
|
||||
} __packed; /* CSI_CHUNKS_HDR_NTFY_API_S_VER_1 */
|
||||
} __packed; /* CSI_CHUNKS_HDR_NTFY_API_S_VER_1/VER_2 */
|
||||
|
||||
#endif /* __iwl_fw_api_location_h__ */
|
||||
|
|
|
@ -419,14 +419,26 @@ struct iwl_per_chain_offset_group {
|
|||
struct iwl_per_chain_offset hb;
|
||||
} __packed; /* PER_CHAIN_LIMIT_OFFSET_GROUP_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_geo_tx_power_profile_cmd_v1 - struct for GEO_TX_POWER_LIMIT cmd.
|
||||
* @ops: operations, value from &enum iwl_geo_per_chain_offset_operation
|
||||
* @table: offset profile per band.
|
||||
*/
|
||||
struct iwl_geo_tx_power_profiles_cmd_v1 {
|
||||
__le32 ops;
|
||||
struct iwl_per_chain_offset_group table[IWL_NUM_GEO_PROFILES];
|
||||
} __packed; /* GEO_TX_POWER_LIMIT_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_geo_tx_power_profile_cmd - struct for GEO_TX_POWER_LIMIT cmd.
|
||||
* @ops: operations, value from &enum iwl_geo_per_chain_offset_operation
|
||||
* @table: offset profile per band.
|
||||
* @table_revision: BIOS table revision.
|
||||
*/
|
||||
struct iwl_geo_tx_power_profiles_cmd {
|
||||
__le32 ops;
|
||||
struct iwl_per_chain_offset_group table[IWL_NUM_GEO_PROFILES];
|
||||
__le32 table_revision;
|
||||
} __packed; /* GEO_TX_POWER_LIMIT */
|
||||
|
||||
/**
|
||||
|
|
|
@ -750,6 +750,21 @@ struct iwl_scan_req_umac {
|
|||
struct iwl_scan_umac_chan_param channel;
|
||||
u8 data[];
|
||||
} v8; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_8 */
|
||||
struct {
|
||||
u8 active_dwell[SCAN_TWO_LMACS];
|
||||
u8 adwell_default_hb_n_aps;
|
||||
u8 adwell_default_lb_n_aps;
|
||||
u8 adwell_default_n_aps_social;
|
||||
u8 general_flags2;
|
||||
__le16 adwell_max_budget;
|
||||
__le32 max_out_time[SCAN_TWO_LMACS];
|
||||
__le32 suspend_time[SCAN_TWO_LMACS];
|
||||
__le32 scan_priority;
|
||||
u8 passive_dwell[SCAN_TWO_LMACS];
|
||||
u8 num_of_fragments[SCAN_TWO_LMACS];
|
||||
struct iwl_scan_umac_chan_param channel;
|
||||
u8 data[];
|
||||
} v9; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_9 */
|
||||
};
|
||||
} __packed;
|
||||
|
||||
|
|
|
@ -1059,7 +1059,7 @@ static int iwl_dump_ini_prph_iter(struct iwl_fw_runtime *fwrt,
|
|||
u32 addr = le32_to_cpu(reg->start_addr[idx]) + le32_to_cpu(reg->offset);
|
||||
int i;
|
||||
|
||||
range->start_addr = cpu_to_le64(addr);
|
||||
range->internal_base_addr = cpu_to_le32(addr);
|
||||
range->range_data_size = reg->internal.range_data_size;
|
||||
for (i = 0; i < le32_to_cpu(reg->internal.range_data_size); i += 4) {
|
||||
prph_val = iwl_read_prph(fwrt->trans, addr + i);
|
||||
|
@ -1080,7 +1080,7 @@ static int iwl_dump_ini_csr_iter(struct iwl_fw_runtime *fwrt,
|
|||
u32 addr = le32_to_cpu(reg->start_addr[idx]) + le32_to_cpu(reg->offset);
|
||||
int i;
|
||||
|
||||
range->start_addr = cpu_to_le64(addr);
|
||||
range->internal_base_addr = cpu_to_le32(addr);
|
||||
range->range_data_size = reg->internal.range_data_size;
|
||||
for (i = 0; i < le32_to_cpu(reg->internal.range_data_size); i += 4)
|
||||
*val++ = cpu_to_le32(iwl_trans_read32(fwrt->trans, addr + i));
|
||||
|
@ -1095,7 +1095,7 @@ static int iwl_dump_ini_dev_mem_iter(struct iwl_fw_runtime *fwrt,
|
|||
struct iwl_fw_ini_error_dump_range *range = range_ptr;
|
||||
u32 addr = le32_to_cpu(reg->start_addr[idx]) + le32_to_cpu(reg->offset);
|
||||
|
||||
range->start_addr = cpu_to_le64(addr);
|
||||
range->internal_base_addr = cpu_to_le32(addr);
|
||||
range->range_data_size = reg->internal.range_data_size;
|
||||
iwl_trans_read_mem_bytes(fwrt->trans, addr, range->data,
|
||||
le32_to_cpu(reg->internal.range_data_size));
|
||||
|
@ -1111,7 +1111,7 @@ iwl_dump_ini_paging_gen2_iter(struct iwl_fw_runtime *fwrt,
|
|||
struct iwl_fw_ini_error_dump_range *range = range_ptr;
|
||||
u32 page_size = fwrt->trans->init_dram.paging[idx].size;
|
||||
|
||||
range->start_addr = cpu_to_le64(idx);
|
||||
range->page_num = cpu_to_le32(idx);
|
||||
range->range_data_size = cpu_to_le32(page_size);
|
||||
memcpy(range->data, fwrt->trans->init_dram.paging[idx].block,
|
||||
page_size);
|
||||
|
@ -1131,7 +1131,7 @@ static int iwl_dump_ini_paging_iter(struct iwl_fw_runtime *fwrt,
|
|||
dma_addr_t addr = fwrt->fw_paging_db[idx].fw_paging_phys;
|
||||
u32 page_size = fwrt->fw_paging_db[idx].fw_paging_size;
|
||||
|
||||
range->start_addr = cpu_to_le64(idx);
|
||||
range->page_num = cpu_to_le32(idx);
|
||||
range->range_data_size = cpu_to_le32(page_size);
|
||||
dma_sync_single_for_cpu(fwrt->trans->dev, addr, page_size,
|
||||
DMA_BIDIRECTIONAL);
|
||||
|
@ -1154,11 +1154,11 @@ iwl_dump_ini_mon_dram_iter(struct iwl_fw_runtime *fwrt,
|
|||
if (start_addr == 0x5a5a5a5a)
|
||||
return -EBUSY;
|
||||
|
||||
range->start_addr = cpu_to_le64(start_addr);
|
||||
range->range_data_size = cpu_to_le32(fwrt->trans->fw_mon[idx].size);
|
||||
range->dram_base_addr = cpu_to_le64(start_addr);
|
||||
range->range_data_size = cpu_to_le32(fwrt->trans->dbg.fw_mon[idx].size);
|
||||
|
||||
memcpy(range->data, fwrt->trans->fw_mon[idx].block,
|
||||
fwrt->trans->fw_mon[idx].size);
|
||||
memcpy(range->data, fwrt->trans->dbg.fw_mon[idx].block,
|
||||
fwrt->trans->dbg.fw_mon[idx].size);
|
||||
|
||||
return sizeof(*range) + le32_to_cpu(range->range_data_size);
|
||||
}
|
||||
|
@ -1228,7 +1228,7 @@ static int iwl_dump_ini_txf_iter(struct iwl_fw_runtime *fwrt,
|
|||
struct iwl_fw_ini_region_cfg *reg,
|
||||
void *range_ptr, int idx)
|
||||
{
|
||||
struct iwl_fw_ini_fifo_error_dump_range *range = range_ptr;
|
||||
struct iwl_fw_ini_error_dump_range *range = range_ptr;
|
||||
struct iwl_ini_txf_iter_data *iter;
|
||||
struct iwl_fw_ini_error_dump_register *reg_dump = (void *)range->data;
|
||||
u32 offs = le32_to_cpu(reg->offset), addr;
|
||||
|
@ -1246,8 +1246,8 @@ static int iwl_dump_ini_txf_iter(struct iwl_fw_runtime *fwrt,
|
|||
|
||||
iter = fwrt->dump.fifo_iter;
|
||||
|
||||
range->fifo_num = cpu_to_le32(iter->fifo);
|
||||
range->num_of_registers = reg->fifos.num_of_registers;
|
||||
range->fifo_hdr.fifo_num = cpu_to_le32(iter->fifo);
|
||||
range->fifo_hdr.num_of_registers = reg->fifos.num_of_registers;
|
||||
range->range_data_size = cpu_to_le32(iter->fifo_size + registers_size);
|
||||
|
||||
iwl_write_prph_no_grab(fwrt->trans, TXF_LARC_NUM + offs, iter->fifo);
|
||||
|
@ -1336,7 +1336,7 @@ static int iwl_dump_ini_rxf_iter(struct iwl_fw_runtime *fwrt,
|
|||
struct iwl_fw_ini_region_cfg *reg,
|
||||
void *range_ptr, int idx)
|
||||
{
|
||||
struct iwl_fw_ini_fifo_error_dump_range *range = range_ptr;
|
||||
struct iwl_fw_ini_error_dump_range *range = range_ptr;
|
||||
struct iwl_ini_rxf_data rxf_data;
|
||||
struct iwl_fw_ini_error_dump_register *reg_dump = (void *)range->data;
|
||||
u32 offs = le32_to_cpu(reg->offset), addr;
|
||||
|
@ -1353,8 +1353,8 @@ static int iwl_dump_ini_rxf_iter(struct iwl_fw_runtime *fwrt,
|
|||
if (!iwl_trans_grab_nic_access(fwrt->trans, &flags))
|
||||
return -EBUSY;
|
||||
|
||||
range->fifo_num = cpu_to_le32(rxf_data.fifo_num);
|
||||
range->num_of_registers = reg->fifos.num_of_registers;
|
||||
range->fifo_hdr.fifo_num = cpu_to_le32(rxf_data.fifo_num);
|
||||
range->fifo_hdr.num_of_registers = reg->fifos.num_of_registers;
|
||||
range->range_data_size = cpu_to_le32(rxf_data.size + registers_size);
|
||||
|
||||
/*
|
||||
|
@ -1408,7 +1408,7 @@ static void *iwl_dump_ini_mem_fill_header(struct iwl_fw_runtime *fwrt,
|
|||
{
|
||||
struct iwl_fw_ini_error_dump *dump = data;
|
||||
|
||||
dump->header.version = cpu_to_le32(IWL_INI_DUMP_MEM_VER);
|
||||
dump->header.version = cpu_to_le32(IWL_INI_DUMP_VER);
|
||||
|
||||
return dump->ranges;
|
||||
}
|
||||
|
@ -1433,7 +1433,7 @@ static void
|
|||
|
||||
iwl_trans_release_nic_access(fwrt->trans, &flags);
|
||||
|
||||
data->header.version = cpu_to_le32(IWL_INI_DUMP_MONITOR_VER);
|
||||
data->header.version = cpu_to_le32(IWL_INI_DUMP_VER);
|
||||
data->write_ptr = cpu_to_le32(write_ptr & write_ptr_msk);
|
||||
data->cycle_cnt = cpu_to_le32(cycle_cnt & cycle_cnt_msk);
|
||||
|
||||
|
@ -1490,17 +1490,6 @@ static void
|
|||
|
||||
}
|
||||
|
||||
static void *iwl_dump_ini_fifo_fill_header(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_fw_ini_region_cfg *reg,
|
||||
void *data)
|
||||
{
|
||||
struct iwl_fw_ini_fifo_error_dump *dump = data;
|
||||
|
||||
dump->header.version = cpu_to_le32(IWL_INI_DUMP_FIFO_VER);
|
||||
|
||||
return dump->ranges;
|
||||
}
|
||||
|
||||
static u32 iwl_dump_ini_mem_ranges(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_fw_ini_region_cfg *reg)
|
||||
{
|
||||
|
@ -1592,8 +1581,8 @@ static u32 iwl_dump_ini_mon_dram_get_size(struct iwl_fw_runtime *fwrt,
|
|||
u32 size = sizeof(struct iwl_fw_ini_monitor_dump) +
|
||||
sizeof(struct iwl_fw_ini_error_dump_range);
|
||||
|
||||
if (fwrt->trans->num_blocks)
|
||||
size += fwrt->trans->fw_mon[0].size;
|
||||
if (fwrt->trans->dbg.num_blocks)
|
||||
size += fwrt->trans->dbg.fw_mon[0].size;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
@ -1613,8 +1602,9 @@ static u32 iwl_dump_ini_txf_get_size(struct iwl_fw_runtime *fwrt,
|
|||
struct iwl_ini_txf_iter_data iter = { .init = true };
|
||||
void *fifo_iter = fwrt->dump.fifo_iter;
|
||||
u32 size = 0;
|
||||
u32 fifo_hdr = sizeof(struct iwl_fw_ini_fifo_error_dump_range) +
|
||||
le32_to_cpu(reg->fifos.num_of_registers) * sizeof(__le32) * 2;
|
||||
u32 fifo_hdr = sizeof(struct iwl_fw_ini_error_dump_range) +
|
||||
le32_to_cpu(reg->fifos.num_of_registers) *
|
||||
sizeof(struct iwl_fw_ini_error_dump_register);
|
||||
|
||||
fwrt->dump.fifo_iter = &iter;
|
||||
while (iwl_ini_txf_iter(fwrt, reg)) {
|
||||
|
@ -1624,7 +1614,7 @@ static u32 iwl_dump_ini_txf_get_size(struct iwl_fw_runtime *fwrt,
|
|||
}
|
||||
|
||||
if (size)
|
||||
size += sizeof(struct iwl_fw_ini_fifo_error_dump);
|
||||
size += sizeof(struct iwl_fw_ini_error_dump);
|
||||
|
||||
fwrt->dump.fifo_iter = fifo_iter;
|
||||
|
||||
|
@ -1635,9 +1625,10 @@ static u32 iwl_dump_ini_rxf_get_size(struct iwl_fw_runtime *fwrt,
|
|||
struct iwl_fw_ini_region_cfg *reg)
|
||||
{
|
||||
struct iwl_ini_rxf_data rx_data;
|
||||
u32 size = sizeof(struct iwl_fw_ini_fifo_error_dump) +
|
||||
sizeof(struct iwl_fw_ini_fifo_error_dump_range) +
|
||||
le32_to_cpu(reg->fifos.num_of_registers) * sizeof(__le32) * 2;
|
||||
u32 size = sizeof(struct iwl_fw_ini_error_dump) +
|
||||
sizeof(struct iwl_fw_ini_error_dump_range) +
|
||||
le32_to_cpu(reg->fifos.num_of_registers) *
|
||||
sizeof(struct iwl_fw_ini_error_dump_register);
|
||||
|
||||
if (reg->fifos.header_only)
|
||||
return size;
|
||||
|
@ -1683,20 +1674,24 @@ iwl_dump_ini_mem(struct iwl_fw_runtime *fwrt,
|
|||
struct iwl_dump_ini_mem_ops *ops)
|
||||
{
|
||||
struct iwl_fw_ini_error_dump_header *header = (void *)(*data)->data;
|
||||
u32 num_of_ranges, i, type = le32_to_cpu(reg->region_type);
|
||||
u32 num_of_ranges, i, type = le32_to_cpu(reg->region_type), size;
|
||||
void *range;
|
||||
|
||||
if (WARN_ON(!ops || !ops->get_num_of_ranges || !ops->get_size ||
|
||||
!ops->fill_mem_hdr || !ops->fill_range))
|
||||
return;
|
||||
|
||||
size = ops->get_size(fwrt, reg);
|
||||
if (!size)
|
||||
return;
|
||||
|
||||
IWL_DEBUG_FW(fwrt, "WRT: collecting region: id=%d, type=%d\n",
|
||||
le32_to_cpu(reg->region_id), type);
|
||||
|
||||
num_of_ranges = ops->get_num_of_ranges(fwrt, reg);
|
||||
|
||||
(*data)->type = cpu_to_le32(type | INI_DUMP_BIT);
|
||||
(*data)->len = cpu_to_le32(ops->get_size(fwrt, reg));
|
||||
(*data)->type = cpu_to_le32(type);
|
||||
(*data)->len = cpu_to_le32(size);
|
||||
|
||||
header->region_id = reg->region_id;
|
||||
header->num_of_ranges = cpu_to_le32(num_of_ranges);
|
||||
|
@ -1709,7 +1704,7 @@ iwl_dump_ini_mem(struct iwl_fw_runtime *fwrt,
|
|||
IWL_ERR(fwrt,
|
||||
"WRT: failed to fill region header: id=%d, type=%d\n",
|
||||
le32_to_cpu(reg->region_id), type);
|
||||
memset(*data, 0, le32_to_cpu((*data)->len));
|
||||
memset(*data, 0, size);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1720,7 +1715,7 @@ iwl_dump_ini_mem(struct iwl_fw_runtime *fwrt,
|
|||
IWL_ERR(fwrt,
|
||||
"WRT: failed to dump region: id=%d, type=%d\n",
|
||||
le32_to_cpu(reg->region_id), type);
|
||||
memset(*data, 0, le32_to_cpu((*data)->len));
|
||||
memset(*data, 0, size);
|
||||
return;
|
||||
}
|
||||
range = range + range_size;
|
||||
|
@ -1728,10 +1723,71 @@ iwl_dump_ini_mem(struct iwl_fw_runtime *fwrt,
|
|||
*data = iwl_fw_error_next_data(*data);
|
||||
}
|
||||
|
||||
static void iwl_dump_ini_info(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_fw_ini_trigger *trigger,
|
||||
struct iwl_fw_error_dump_data **data)
|
||||
{
|
||||
struct iwl_fw_ini_dump_info *dump = (void *)(*data)->data;
|
||||
u32 reg_ids_size = le32_to_cpu(trigger->num_regions) * sizeof(__le32);
|
||||
|
||||
(*data)->type = cpu_to_le32(IWL_INI_DUMP_INFO_TYPE);
|
||||
(*data)->len = cpu_to_le32(sizeof(*dump) + reg_ids_size);
|
||||
|
||||
dump->version = cpu_to_le32(IWL_INI_DUMP_VER);
|
||||
dump->trigger_id = trigger->trigger_id;
|
||||
dump->is_external_cfg =
|
||||
cpu_to_le32(fwrt->trans->dbg.external_ini_loaded);
|
||||
|
||||
dump->ver_type = cpu_to_le32(fwrt->dump.fw_ver.type);
|
||||
dump->ver_subtype = cpu_to_le32(fwrt->dump.fw_ver.subtype);
|
||||
|
||||
dump->hw_step = cpu_to_le32(CSR_HW_REV_STEP(fwrt->trans->hw_rev));
|
||||
dump->hw_type = cpu_to_le32(CSR_HW_REV_TYPE(fwrt->trans->hw_rev));
|
||||
|
||||
dump->rf_id_flavor =
|
||||
cpu_to_le32(CSR_HW_RFID_FLAVOR(fwrt->trans->hw_rf_id));
|
||||
dump->rf_id_dash = cpu_to_le32(CSR_HW_RFID_DASH(fwrt->trans->hw_rf_id));
|
||||
dump->rf_id_step = cpu_to_le32(CSR_HW_RFID_STEP(fwrt->trans->hw_rf_id));
|
||||
dump->rf_id_type = cpu_to_le32(CSR_HW_RFID_TYPE(fwrt->trans->hw_rf_id));
|
||||
|
||||
dump->lmac_major = cpu_to_le32(fwrt->dump.fw_ver.lmac_major);
|
||||
dump->lmac_minor = cpu_to_le32(fwrt->dump.fw_ver.lmac_minor);
|
||||
dump->umac_major = cpu_to_le32(fwrt->dump.fw_ver.umac_major);
|
||||
dump->umac_minor = cpu_to_le32(fwrt->dump.fw_ver.umac_minor);
|
||||
|
||||
dump->build_tag_len = cpu_to_le32(sizeof(dump->build_tag));
|
||||
memcpy(dump->build_tag, fwrt->fw->human_readable,
|
||||
sizeof(dump->build_tag));
|
||||
|
||||
dump->img_name_len = cpu_to_le32(sizeof(dump->img_name));
|
||||
memcpy(dump->img_name, fwrt->dump.img_name, sizeof(dump->img_name));
|
||||
|
||||
dump->internal_dbg_cfg_name_len =
|
||||
cpu_to_le32(sizeof(dump->internal_dbg_cfg_name));
|
||||
memcpy(dump->internal_dbg_cfg_name, fwrt->dump.internal_dbg_cfg_name,
|
||||
sizeof(dump->internal_dbg_cfg_name));
|
||||
|
||||
dump->external_dbg_cfg_name_len =
|
||||
cpu_to_le32(sizeof(dump->external_dbg_cfg_name));
|
||||
|
||||
/* dump info size is allocated in iwl_fw_ini_get_trigger_len.
|
||||
* The driver allocates (sizeof(*dump) + reg_ids_size) so it is safe to
|
||||
* use reg_ids_size
|
||||
*/
|
||||
memcpy(dump->external_dbg_cfg_name, fwrt->dump.external_dbg_cfg_name,
|
||||
sizeof(dump->external_dbg_cfg_name));
|
||||
|
||||
dump->regions_num = trigger->num_regions;
|
||||
memcpy(dump->region_ids, trigger->data, reg_ids_size);
|
||||
|
||||
*data = iwl_fw_error_next_data(*data);
|
||||
}
|
||||
|
||||
static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_fw_ini_trigger *trigger)
|
||||
{
|
||||
int i, size = 0, hdr_len = sizeof(struct iwl_fw_error_dump_data);
|
||||
int i, ret_size = 0, hdr_len = sizeof(struct iwl_fw_error_dump_data);
|
||||
u32 size;
|
||||
|
||||
if (!trigger || !trigger->num_regions)
|
||||
return 0;
|
||||
|
@ -1763,32 +1819,40 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt,
|
|||
case IWL_FW_INI_REGION_CSR:
|
||||
case IWL_FW_INI_REGION_LMAC_ERROR_TABLE:
|
||||
case IWL_FW_INI_REGION_UMAC_ERROR_TABLE:
|
||||
size += hdr_len + iwl_dump_ini_mem_get_size(fwrt, reg);
|
||||
size = iwl_dump_ini_mem_get_size(fwrt, reg);
|
||||
if (size)
|
||||
ret_size += hdr_len + size;
|
||||
break;
|
||||
case IWL_FW_INI_REGION_TXF:
|
||||
size += hdr_len + iwl_dump_ini_txf_get_size(fwrt, reg);
|
||||
size = iwl_dump_ini_txf_get_size(fwrt, reg);
|
||||
if (size)
|
||||
ret_size += hdr_len + size;
|
||||
break;
|
||||
case IWL_FW_INI_REGION_RXF:
|
||||
size += hdr_len + iwl_dump_ini_rxf_get_size(fwrt, reg);
|
||||
size = iwl_dump_ini_rxf_get_size(fwrt, reg);
|
||||
if (size)
|
||||
ret_size += hdr_len + size;
|
||||
break;
|
||||
case IWL_FW_INI_REGION_PAGING:
|
||||
size += hdr_len;
|
||||
if (iwl_fw_dbg_is_paging_enabled(fwrt)) {
|
||||
size += iwl_dump_ini_paging_get_size(fwrt, reg);
|
||||
} else {
|
||||
size += iwl_dump_ini_paging_gen2_get_size(fwrt,
|
||||
reg);
|
||||
}
|
||||
if (iwl_fw_dbg_is_paging_enabled(fwrt))
|
||||
size = iwl_dump_ini_paging_get_size(fwrt, reg);
|
||||
else
|
||||
size = iwl_dump_ini_paging_gen2_get_size(fwrt,
|
||||
reg);
|
||||
if (size)
|
||||
ret_size += hdr_len + size;
|
||||
break;
|
||||
case IWL_FW_INI_REGION_DRAM_BUFFER:
|
||||
if (!fwrt->trans->num_blocks)
|
||||
if (!fwrt->trans->dbg.num_blocks)
|
||||
break;
|
||||
size += hdr_len +
|
||||
iwl_dump_ini_mon_dram_get_size(fwrt, reg);
|
||||
size = iwl_dump_ini_mon_dram_get_size(fwrt, reg);
|
||||
if (size)
|
||||
ret_size += hdr_len + size;
|
||||
break;
|
||||
case IWL_FW_INI_REGION_INTERNAL_BUFFER:
|
||||
size += hdr_len +
|
||||
iwl_dump_ini_mon_smem_get_size(fwrt, reg);
|
||||
size = iwl_dump_ini_mon_smem_get_size(fwrt, reg);
|
||||
if (size)
|
||||
ret_size += hdr_len + size;
|
||||
break;
|
||||
case IWL_FW_INI_REGION_DRAM_IMR:
|
||||
/* Undefined yet */
|
||||
|
@ -1796,7 +1860,13 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt,
|
|||
break;
|
||||
}
|
||||
}
|
||||
return size;
|
||||
|
||||
/* add dump info size */
|
||||
if (ret_size)
|
||||
ret_size += hdr_len + sizeof(struct iwl_fw_ini_dump_info) +
|
||||
(le32_to_cpu(trigger->num_regions) * sizeof(__le32));
|
||||
|
||||
return ret_size;
|
||||
}
|
||||
|
||||
static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt,
|
||||
|
@ -1805,6 +1875,8 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt,
|
|||
{
|
||||
int i, num = le32_to_cpu(trigger->num_regions);
|
||||
|
||||
iwl_dump_ini_info(fwrt, trigger, data);
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
u32 reg_id = le32_to_cpu(trigger->data[i]);
|
||||
struct iwl_fw_ini_region_cfg *reg;
|
||||
|
@ -1879,7 +1951,7 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt,
|
|||
fwrt->dump.fifo_iter = &iter;
|
||||
ops.get_num_of_ranges = iwl_dump_ini_txf_ranges;
|
||||
ops.get_size = iwl_dump_ini_txf_get_size;
|
||||
ops.fill_mem_hdr = iwl_dump_ini_fifo_fill_header;
|
||||
ops.fill_mem_hdr = iwl_dump_ini_mem_fill_header;
|
||||
ops.fill_range = iwl_dump_ini_txf_iter;
|
||||
iwl_dump_ini_mem(fwrt, data, reg, &ops);
|
||||
fwrt->dump.fifo_iter = fifo_iter;
|
||||
|
@ -1888,7 +1960,7 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt,
|
|||
case IWL_FW_INI_REGION_RXF:
|
||||
ops.get_num_of_ranges = iwl_dump_ini_rxf_ranges;
|
||||
ops.get_size = iwl_dump_ini_rxf_get_size;
|
||||
ops.fill_mem_hdr = iwl_dump_ini_fifo_fill_header;
|
||||
ops.fill_mem_hdr = iwl_dump_ini_mem_fill_header;
|
||||
ops.fill_range = iwl_dump_ini_rxf_iter;
|
||||
iwl_dump_ini_mem(fwrt, data, reg, &ops);
|
||||
break;
|
||||
|
@ -1908,18 +1980,18 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt,
|
|||
}
|
||||
|
||||
static struct iwl_fw_error_dump_file *
|
||||
iwl_fw_error_ini_dump_file(struct iwl_fw_runtime *fwrt)
|
||||
iwl_fw_error_ini_dump_file(struct iwl_fw_runtime *fwrt,
|
||||
enum iwl_fw_ini_trigger_id trig_id)
|
||||
{
|
||||
int size;
|
||||
struct iwl_fw_error_dump_data *dump_data;
|
||||
struct iwl_fw_error_dump_file *dump_file;
|
||||
struct iwl_fw_ini_trigger *trigger;
|
||||
enum iwl_fw_ini_trigger_id id = fwrt->dump.ini_trig_id;
|
||||
|
||||
if (!iwl_fw_ini_trigger_on(fwrt, id))
|
||||
if (!iwl_fw_ini_trigger_on(fwrt, trig_id))
|
||||
return NULL;
|
||||
|
||||
trigger = fwrt->dump.active_trigs[id].trig;
|
||||
trigger = fwrt->dump.active_trigs[trig_id].trig;
|
||||
|
||||
size = iwl_fw_ini_get_trigger_len(fwrt, trigger);
|
||||
if (!size)
|
||||
|
@ -1931,7 +2003,7 @@ iwl_fw_error_ini_dump_file(struct iwl_fw_runtime *fwrt)
|
|||
if (!dump_file)
|
||||
return NULL;
|
||||
|
||||
dump_file->barker = cpu_to_le32(IWL_FW_ERROR_DUMP_BARKER);
|
||||
dump_file->barker = cpu_to_le32(IWL_FW_INI_ERROR_DUMP_BARKER);
|
||||
dump_data = (void *)dump_file->data;
|
||||
dump_file->file_len = cpu_to_le32(size);
|
||||
|
||||
|
@ -1952,7 +2024,7 @@ static void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
|
|||
if (!dump_file)
|
||||
goto out;
|
||||
|
||||
if (!fwrt->trans->ini_valid && fwrt->dump.monitor_only)
|
||||
if (fwrt->dump.monitor_only)
|
||||
dump_mask &= IWL_FW_ERROR_DUMP_FW_MONITOR;
|
||||
|
||||
fw_error_dump.trans_ptr = iwl_trans_dump_data(fwrt->trans, dump_mask);
|
||||
|
@ -1984,16 +2056,16 @@ static void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
|
|||
|
||||
out:
|
||||
iwl_fw_free_dump_desc(fwrt);
|
||||
clear_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status);
|
||||
}
|
||||
|
||||
static void iwl_fw_error_ini_dump(struct iwl_fw_runtime *fwrt)
|
||||
static void iwl_fw_error_ini_dump(struct iwl_fw_runtime *fwrt, u8 wk_idx)
|
||||
{
|
||||
enum iwl_fw_ini_trigger_id trig_id = fwrt->dump.wks[wk_idx].ini_trig_id;
|
||||
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);
|
||||
dump_file = iwl_fw_error_ini_dump_file(fwrt, trig_id);
|
||||
if (!dump_file)
|
||||
goto out;
|
||||
|
||||
|
@ -2008,8 +2080,7 @@ static void iwl_fw_error_ini_dump(struct iwl_fw_runtime *fwrt)
|
|||
}
|
||||
vfree(dump_file);
|
||||
out:
|
||||
fwrt->dump.ini_trig_id = IWL_FW_TRIGGER_ID_INVALID;
|
||||
clear_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status);
|
||||
fwrt->dump.wks[wk_idx].ini_trig_id = IWL_FW_TRIGGER_ID_INVALID;
|
||||
}
|
||||
|
||||
const struct iwl_fw_dump_desc iwl_dump_desc_assert = {
|
||||
|
@ -2027,7 +2098,7 @@ int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt,
|
|||
u32 trig_type = le32_to_cpu(desc->trig_desc.type);
|
||||
int ret;
|
||||
|
||||
if (fwrt->trans->ini_valid) {
|
||||
if (fwrt->trans->dbg.ini_valid) {
|
||||
ret = iwl_fw_dbg_ini_collect(fwrt, trig_type);
|
||||
if (!ret)
|
||||
iwl_fw_free_dump_desc(fwrt);
|
||||
|
@ -2035,7 +2106,10 @@ int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt,
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (test_and_set_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status))
|
||||
/* use wks[0] since dump flow prior to ini does not need to support
|
||||
* consecutive triggers collection
|
||||
*/
|
||||
if (test_and_set_bit(fwrt->dump.wks[0].idx, &fwrt->dump.active_wks))
|
||||
return -EBUSY;
|
||||
|
||||
if (WARN_ON(fwrt->dump.desc))
|
||||
|
@ -2047,7 +2121,7 @@ int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt,
|
|||
fwrt->dump.desc = desc;
|
||||
fwrt->dump.monitor_only = monitor_only;
|
||||
|
||||
schedule_delayed_work(&fwrt->dump.wk, usecs_to_jiffies(delay));
|
||||
schedule_delayed_work(&fwrt->dump.wks[0].wk, usecs_to_jiffies(delay));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -2057,9 +2131,12 @@ int iwl_fw_dbg_error_collect(struct iwl_fw_runtime *fwrt,
|
|||
enum iwl_fw_dbg_trigger trig_type)
|
||||
{
|
||||
int ret;
|
||||
struct iwl_fw_dump_desc *iwl_dump_error_desc =
|
||||
kmalloc(sizeof(*iwl_dump_error_desc), GFP_KERNEL);
|
||||
struct iwl_fw_dump_desc *iwl_dump_error_desc;
|
||||
|
||||
if (!test_bit(STATUS_DEVICE_ENABLED, &fwrt->trans->status))
|
||||
return -EIO;
|
||||
|
||||
iwl_dump_error_desc = kmalloc(sizeof(*iwl_dump_error_desc), GFP_KERNEL);
|
||||
if (!iwl_dump_error_desc)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -2123,13 +2200,11 @@ int _iwl_fw_dbg_ini_collect(struct iwl_fw_runtime *fwrt,
|
|||
{
|
||||
struct iwl_fw_ini_active_triggers *active;
|
||||
u32 occur, delay;
|
||||
unsigned long idx;
|
||||
|
||||
if (WARN_ON(!iwl_fw_ini_trigger_on(fwrt, id)))
|
||||
return -EINVAL;
|
||||
|
||||
if (test_and_set_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status))
|
||||
return -EBUSY;
|
||||
|
||||
if (!iwl_fw_ini_trigger_on(fwrt, id)) {
|
||||
IWL_WARN(fwrt, "WRT: Trigger %d is not active, aborting dump\n",
|
||||
id);
|
||||
|
@ -2150,14 +2225,24 @@ int _iwl_fw_dbg_ini_collect(struct iwl_fw_runtime *fwrt,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (test_and_set_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status))
|
||||
/* Check there is an available worker.
|
||||
* ffz return value is undefined if no zero exists,
|
||||
* so check against ~0UL first.
|
||||
*/
|
||||
if (fwrt->dump.active_wks == ~0UL)
|
||||
return -EBUSY;
|
||||
|
||||
fwrt->dump.ini_trig_id = id;
|
||||
idx = ffz(fwrt->dump.active_wks);
|
||||
|
||||
if (idx >= IWL_FW_RUNTIME_DUMP_WK_NUM ||
|
||||
test_and_set_bit(fwrt->dump.wks[idx].idx, &fwrt->dump.active_wks))
|
||||
return -EBUSY;
|
||||
|
||||
fwrt->dump.wks[idx].ini_trig_id = id;
|
||||
|
||||
IWL_WARN(fwrt, "WRT: collecting data: ini trigger %d fired.\n", id);
|
||||
|
||||
schedule_delayed_work(&fwrt->dump.wk, usecs_to_jiffies(delay));
|
||||
schedule_delayed_work(&fwrt->dump.wks[idx].wk, usecs_to_jiffies(delay));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -2191,9 +2276,6 @@ int iwl_fw_dbg_collect_trig(struct iwl_fw_runtime *fwrt,
|
|||
int ret, len = 0;
|
||||
char buf[64];
|
||||
|
||||
if (fwrt->trans->ini_valid)
|
||||
return 0;
|
||||
|
||||
if (fmt) {
|
||||
va_list ap;
|
||||
|
||||
|
@ -2270,56 +2352,57 @@ IWL_EXPORT_SYMBOL(iwl_fw_start_dbg_conf);
|
|||
/* this function assumes dump_start was called beforehand and dump_end will be
|
||||
* called afterwards
|
||||
*/
|
||||
void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt)
|
||||
static void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt, u8 wk_idx)
|
||||
{
|
||||
struct iwl_fw_dbg_params params = {0};
|
||||
|
||||
if (!test_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status))
|
||||
if (!test_bit(wk_idx, &fwrt->dump.active_wks))
|
||||
return;
|
||||
|
||||
if (fwrt->ops && fwrt->ops->fw_running &&
|
||||
!fwrt->ops->fw_running(fwrt->ops_ctx)) {
|
||||
IWL_ERR(fwrt, "Firmware not running - cannot dump error\n");
|
||||
iwl_fw_free_dump_desc(fwrt);
|
||||
clear_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status);
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
goto out;
|
||||
}
|
||||
|
||||
iwl_fw_dbg_stop_recording(fwrt, ¶ms);
|
||||
iwl_fw_dbg_stop_recording(fwrt->trans, ¶ms);
|
||||
|
||||
IWL_DEBUG_FW_INFO(fwrt, "WRT: data collection start\n");
|
||||
if (fwrt->trans->ini_valid)
|
||||
iwl_fw_error_ini_dump(fwrt);
|
||||
if (fwrt->trans->dbg.ini_valid)
|
||||
iwl_fw_error_ini_dump(fwrt, wk_idx);
|
||||
else
|
||||
iwl_fw_error_dump(fwrt);
|
||||
IWL_DEBUG_FW_INFO(fwrt, "WRT: data collection done\n");
|
||||
|
||||
/* start recording again if the firmware is not crashed */
|
||||
if (!test_bit(STATUS_FW_ERROR, &fwrt->trans->status) &&
|
||||
fwrt->fw->dbg.dest_tlv) {
|
||||
/* wait before we collect the data till the DBGC stop */
|
||||
udelay(500);
|
||||
iwl_fw_dbg_restart_recording(fwrt, ¶ms);
|
||||
}
|
||||
iwl_fw_dbg_restart_recording(fwrt, ¶ms);
|
||||
|
||||
out:
|
||||
clear_bit(wk_idx, &fwrt->dump.active_wks);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_fw_dbg_collect_sync);
|
||||
|
||||
void iwl_fw_error_dump_wk(struct work_struct *work)
|
||||
{
|
||||
struct iwl_fw_runtime *fwrt =
|
||||
container_of(work, struct iwl_fw_runtime, dump.wk.work);
|
||||
struct iwl_fw_runtime *fwrt;
|
||||
typeof(fwrt->dump.wks[0]) *wks;
|
||||
|
||||
wks = container_of(work, typeof(fwrt->dump.wks[0]), wk.work);
|
||||
fwrt = container_of(wks, struct iwl_fw_runtime, dump.wks[wks->idx]);
|
||||
|
||||
/* assumes the op mode mutex is locked in dump_start since
|
||||
* iwl_fw_dbg_collect_sync can't run in parallel
|
||||
*/
|
||||
if (fwrt->ops && fwrt->ops->dump_start &&
|
||||
fwrt->ops->dump_start(fwrt->ops_ctx))
|
||||
return;
|
||||
|
||||
iwl_fw_dbg_collect_sync(fwrt);
|
||||
iwl_fw_dbg_collect_sync(fwrt, wks->idx);
|
||||
|
||||
if (fwrt->ops && fwrt->ops->dump_end)
|
||||
fwrt->ops->dump_end(fwrt->ops_ctx);
|
||||
|
@ -2349,6 +2432,38 @@ void iwl_fw_dbg_read_d3_debug_data(struct iwl_fw_runtime *fwrt)
|
|||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_fw_dbg_read_d3_debug_data);
|
||||
|
||||
static void iwl_fw_dbg_info_apply(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_fw_ini_debug_info_tlv *dbg_info,
|
||||
bool ext, enum iwl_fw_ini_apply_point pnt)
|
||||
{
|
||||
u32 img_name_len = le32_to_cpu(dbg_info->img_name_len);
|
||||
u32 dbg_cfg_name_len = le32_to_cpu(dbg_info->dbg_cfg_name_len);
|
||||
const char err_str[] =
|
||||
"WRT: ext=%d. Invalid %s name length %d, expected %d\n";
|
||||
|
||||
if (img_name_len != IWL_FW_INI_MAX_IMG_NAME_LEN) {
|
||||
IWL_WARN(fwrt, err_str, ext, "image", img_name_len,
|
||||
IWL_FW_INI_MAX_IMG_NAME_LEN);
|
||||
return;
|
||||
}
|
||||
|
||||
if (dbg_cfg_name_len != IWL_FW_INI_MAX_DBG_CFG_NAME_LEN) {
|
||||
IWL_WARN(fwrt, err_str, ext, "debug cfg", dbg_cfg_name_len,
|
||||
IWL_FW_INI_MAX_DBG_CFG_NAME_LEN);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ext) {
|
||||
memcpy(fwrt->dump.external_dbg_cfg_name, dbg_info->dbg_cfg_name,
|
||||
sizeof(fwrt->dump.external_dbg_cfg_name));
|
||||
} else {
|
||||
memcpy(fwrt->dump.img_name, dbg_info->img_name,
|
||||
sizeof(fwrt->dump.img_name));
|
||||
memcpy(fwrt->dump.internal_dbg_cfg_name, dbg_info->dbg_cfg_name,
|
||||
sizeof(fwrt->dump.internal_dbg_cfg_name));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
iwl_fw_dbg_buffer_allocation(struct iwl_fw_runtime *fwrt, u32 size)
|
||||
{
|
||||
|
@ -2356,7 +2471,8 @@ iwl_fw_dbg_buffer_allocation(struct iwl_fw_runtime *fwrt, u32 size)
|
|||
void *virtual_addr = NULL;
|
||||
dma_addr_t phys_addr;
|
||||
|
||||
if (WARN_ON_ONCE(trans->num_blocks == ARRAY_SIZE(trans->fw_mon)))
|
||||
if (WARN_ON_ONCE(trans->dbg.num_blocks ==
|
||||
ARRAY_SIZE(trans->dbg.fw_mon)))
|
||||
return;
|
||||
|
||||
virtual_addr =
|
||||
|
@ -2370,12 +2486,12 @@ iwl_fw_dbg_buffer_allocation(struct iwl_fw_runtime *fwrt, u32 size)
|
|||
|
||||
IWL_DEBUG_FW(trans,
|
||||
"Allocated DRAM buffer[%d], size=0x%x\n",
|
||||
trans->num_blocks, size);
|
||||
trans->dbg.num_blocks, size);
|
||||
|
||||
trans->fw_mon[trans->num_blocks].block = virtual_addr;
|
||||
trans->fw_mon[trans->num_blocks].physical = phys_addr;
|
||||
trans->fw_mon[trans->num_blocks].size = size;
|
||||
trans->num_blocks++;
|
||||
trans->dbg.fw_mon[trans->dbg.num_blocks].block = virtual_addr;
|
||||
trans->dbg.fw_mon[trans->dbg.num_blocks].physical = phys_addr;
|
||||
trans->dbg.fw_mon[trans->dbg.num_blocks].size = size;
|
||||
trans->dbg.num_blocks++;
|
||||
}
|
||||
|
||||
static void iwl_fw_dbg_buffer_apply(struct iwl_fw_runtime *fwrt,
|
||||
|
@ -2393,20 +2509,26 @@ static void iwl_fw_dbg_buffer_apply(struct iwl_fw_runtime *fwrt,
|
|||
.data[0] = &ldbg_cmd,
|
||||
.len[0] = sizeof(ldbg_cmd),
|
||||
};
|
||||
int block_idx = trans->num_blocks;
|
||||
int block_idx = trans->dbg.num_blocks;
|
||||
u32 buf_location = le32_to_cpu(alloc->tlv.buffer_location);
|
||||
|
||||
if (buf_location == IWL_FW_INI_LOCATION_SRAM_PATH) {
|
||||
if (!WARN(pnt != IWL_FW_INI_APPLY_EARLY,
|
||||
"WRT: Invalid apply point %d for SMEM buffer allocation, aborting\n",
|
||||
pnt)) {
|
||||
IWL_DEBUG_FW(trans,
|
||||
"WRT: applying SMEM buffer destination\n");
|
||||
if (fwrt->trans->dbg.ini_dest == IWL_FW_INI_LOCATION_INVALID)
|
||||
fwrt->trans->dbg.ini_dest = buf_location;
|
||||
|
||||
if (buf_location != fwrt->trans->dbg.ini_dest) {
|
||||
WARN(fwrt,
|
||||
"WRT: attempt to override buffer location on apply point %d\n",
|
||||
pnt);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (buf_location == IWL_FW_INI_LOCATION_SRAM_PATH) {
|
||||
IWL_DEBUG_FW(trans, "WRT: applying SMEM buffer destination\n");
|
||||
/* set sram monitor by enabling bit 7 */
|
||||
iwl_set_bit(fwrt->trans, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_BIT_MONITOR_SRAM);
|
||||
|
||||
/* set sram monitor by enabling bit 7 */
|
||||
iwl_set_bit(fwrt->trans, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_BIT_MONITOR_SRAM);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2416,13 +2538,13 @@ static void iwl_fw_dbg_buffer_apply(struct iwl_fw_runtime *fwrt,
|
|||
if (!alloc->is_alloc) {
|
||||
iwl_fw_dbg_buffer_allocation(fwrt,
|
||||
le32_to_cpu(alloc->tlv.size));
|
||||
if (block_idx == trans->num_blocks)
|
||||
if (block_idx == trans->dbg.num_blocks)
|
||||
return;
|
||||
alloc->is_alloc = 1;
|
||||
}
|
||||
|
||||
/* First block is assigned via registers / context info */
|
||||
if (trans->num_blocks == 1)
|
||||
if (trans->dbg.num_blocks == 1)
|
||||
return;
|
||||
|
||||
IWL_DEBUG_FW(trans,
|
||||
|
@ -2430,7 +2552,7 @@ static void iwl_fw_dbg_buffer_apply(struct iwl_fw_runtime *fwrt,
|
|||
|
||||
cmd->num_frags = cpu_to_le32(1);
|
||||
cmd->fragments[0].address =
|
||||
cpu_to_le64(trans->fw_mon[block_idx].physical);
|
||||
cpu_to_le64(trans->dbg.fw_mon[block_idx].physical);
|
||||
cmd->fragments[0].size = alloc->tlv.size;
|
||||
cmd->allocation_id = alloc->tlv.allocation_id;
|
||||
cmd->buffer_location = alloc->tlv.buffer_location;
|
||||
|
@ -2653,20 +2775,30 @@ static void _iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt,
|
|||
struct iwl_ucode_tlv *tlv = iter;
|
||||
void *ini_tlv = (void *)tlv->data;
|
||||
u32 type = le32_to_cpu(tlv->type);
|
||||
const char invalid_ap_str[] =
|
||||
"WRT: ext=%d. Invalid apply point %d for %s\n";
|
||||
|
||||
switch (type) {
|
||||
case IWL_UCODE_TLV_TYPE_DEBUG_INFO:
|
||||
iwl_fw_dbg_info_apply(fwrt, ini_tlv, ext, pnt);
|
||||
break;
|
||||
case IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION: {
|
||||
struct iwl_fw_ini_allocation_data *buf_alloc = ini_tlv;
|
||||
|
||||
if (pnt != IWL_FW_INI_APPLY_EARLY) {
|
||||
IWL_ERR(fwrt, invalid_ap_str, ext, pnt,
|
||||
"buffer allocation");
|
||||
goto next;
|
||||
}
|
||||
|
||||
iwl_fw_dbg_buffer_apply(fwrt, ini_tlv, pnt);
|
||||
iter += sizeof(buf_alloc->is_alloc);
|
||||
break;
|
||||
}
|
||||
case IWL_UCODE_TLV_TYPE_HCMD:
|
||||
if (pnt < IWL_FW_INI_APPLY_AFTER_ALIVE) {
|
||||
IWL_ERR(fwrt,
|
||||
"WRT: ext=%d. Invalid apply point %d for host command\n",
|
||||
ext, pnt);
|
||||
IWL_ERR(fwrt, invalid_ap_str, ext, pnt,
|
||||
"host command");
|
||||
goto next;
|
||||
}
|
||||
iwl_fw_dbg_send_hcmd(fwrt, tlv, ext);
|
||||
|
@ -2690,34 +2822,51 @@ next:
|
|||
}
|
||||
}
|
||||
|
||||
static void iwl_fw_dbg_ini_reset_cfg(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < IWL_FW_INI_MAX_REGION_ID; i++)
|
||||
fwrt->dump.active_regs[i] = NULL;
|
||||
|
||||
/* disable the triggers, used in recovery flow */
|
||||
for (i = 0; i < IWL_FW_TRIGGER_ID_NUM; i++)
|
||||
fwrt->dump.active_trigs[i].active = false;
|
||||
|
||||
memset(fwrt->dump.img_name, 0,
|
||||
sizeof(fwrt->dump.img_name));
|
||||
memset(fwrt->dump.internal_dbg_cfg_name, 0,
|
||||
sizeof(fwrt->dump.internal_dbg_cfg_name));
|
||||
memset(fwrt->dump.external_dbg_cfg_name, 0,
|
||||
sizeof(fwrt->dump.external_dbg_cfg_name));
|
||||
|
||||
fwrt->trans->dbg.ini_dest = IWL_FW_INI_LOCATION_INVALID;
|
||||
}
|
||||
|
||||
void iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt,
|
||||
enum iwl_fw_ini_apply_point apply_point)
|
||||
{
|
||||
void *data = &fwrt->trans->apply_points[apply_point];
|
||||
int i;
|
||||
void *data = &fwrt->trans->dbg.apply_points[apply_point];
|
||||
|
||||
IWL_DEBUG_FW(fwrt, "WRT: enabling apply point %d\n", apply_point);
|
||||
|
||||
if (apply_point == IWL_FW_INI_APPLY_EARLY) {
|
||||
for (i = 0; i < IWL_FW_INI_MAX_REGION_ID; i++)
|
||||
fwrt->dump.active_regs[i] = NULL;
|
||||
|
||||
/* disable the triggers, used in recovery flow */
|
||||
for (i = 0; i < IWL_FW_TRIGGER_ID_NUM; i++)
|
||||
fwrt->dump.active_trigs[i].active = false;
|
||||
}
|
||||
if (apply_point == IWL_FW_INI_APPLY_EARLY)
|
||||
iwl_fw_dbg_ini_reset_cfg(fwrt);
|
||||
|
||||
_iwl_fw_dbg_apply_point(fwrt, data, apply_point, false);
|
||||
|
||||
data = &fwrt->trans->apply_points_ext[apply_point];
|
||||
data = &fwrt->trans->dbg.apply_points_ext[apply_point];
|
||||
_iwl_fw_dbg_apply_point(fwrt, data, apply_point, true);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_fw_dbg_apply_point);
|
||||
|
||||
void iwl_fwrt_stop_device(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
int i;
|
||||
|
||||
del_timer(&fwrt->dump.periodic_trig);
|
||||
iwl_fw_dbg_collect_sync(fwrt);
|
||||
for (i = 0; i < IWL_FW_RUNTIME_DUMP_WK_NUM; i++)
|
||||
iwl_fw_dbg_collect_sync(fwrt, i);
|
||||
|
||||
iwl_trans_stop_device(fwrt->trans);
|
||||
}
|
||||
|
|
|
@ -73,6 +73,7 @@
|
|||
#include "error-dump.h"
|
||||
#include "api/commands.h"
|
||||
#include "api/dbg-tlv.h"
|
||||
#include "api/alive.h"
|
||||
|
||||
/**
|
||||
* struct iwl_fw_dump_desc - describes the dump
|
||||
|
@ -201,7 +202,7 @@ _iwl_fw_dbg_trigger_on(struct iwl_fw_runtime *fwrt,
|
|||
{
|
||||
struct iwl_fw_dbg_trigger_tlv *trig;
|
||||
|
||||
if (fwrt->trans->ini_valid)
|
||||
if (fwrt->trans->dbg.ini_valid)
|
||||
return NULL;
|
||||
|
||||
if (!iwl_fw_dbg_trigger_enabled(fwrt->fw, id))
|
||||
|
@ -228,7 +229,7 @@ iwl_fw_ini_trigger_on(struct iwl_fw_runtime *fwrt,
|
|||
struct iwl_fw_ini_trigger *trig;
|
||||
u32 usec;
|
||||
|
||||
if (!fwrt->trans->ini_valid || id == IWL_FW_TRIGGER_ID_INVALID ||
|
||||
if (!fwrt->trans->dbg.ini_valid || id == IWL_FW_TRIGGER_ID_INVALID ||
|
||||
id >= IWL_FW_TRIGGER_ID_NUM || !fwrt->dump.active_trigs[id].active)
|
||||
return false;
|
||||
|
||||
|
@ -262,23 +263,6 @@ _iwl_fw_dbg_trigger_simple_stop(struct iwl_fw_runtime *fwrt,
|
|||
iwl_fw_dbg_get_trigger((fwrt)->fw,\
|
||||
(trig)))
|
||||
|
||||
static inline int
|
||||
iwl_fw_dbg_start_stop_hcmd(struct iwl_fw_runtime *fwrt, bool start)
|
||||
{
|
||||
struct iwl_ldbg_config_cmd cmd = {
|
||||
.type = start ? cpu_to_le32(START_DEBUG_RECORDING) :
|
||||
cpu_to_le32(STOP_DEBUG_RECORDING),
|
||||
};
|
||||
struct iwl_host_cmd hcmd = {
|
||||
.id = LDBG_CONFIG_CMD,
|
||||
.flags = CMD_ASYNC,
|
||||
.data[0] = &cmd,
|
||||
.len[0] = sizeof(cmd),
|
||||
};
|
||||
|
||||
return iwl_trans_send_cmd(fwrt->trans, &hcmd);
|
||||
}
|
||||
|
||||
static inline void
|
||||
_iwl_fw_dbg_stop_recording(struct iwl_trans *trans,
|
||||
struct iwl_fw_dbg_params *params)
|
||||
|
@ -294,21 +278,35 @@ _iwl_fw_dbg_stop_recording(struct iwl_trans *trans,
|
|||
}
|
||||
|
||||
iwl_write_umac_prph(trans, DBGC_IN_SAMPLE, 0);
|
||||
udelay(100);
|
||||
/* wait for the DBGC to finish writing the internal buffer to DRAM to
|
||||
* avoid halting the HW while writing
|
||||
*/
|
||||
usleep_range(700, 1000);
|
||||
iwl_write_umac_prph(trans, DBGC_OUT_CTRL, 0);
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
trans->dbg_rec_on = false;
|
||||
trans->dbg.rec_on = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void
|
||||
iwl_fw_dbg_stop_recording(struct iwl_fw_runtime *fwrt,
|
||||
iwl_fw_dbg_stop_recording(struct iwl_trans *trans,
|
||||
struct iwl_fw_dbg_params *params)
|
||||
{
|
||||
if (fwrt->trans->cfg->device_family < IWL_DEVICE_FAMILY_22560)
|
||||
_iwl_fw_dbg_stop_recording(fwrt->trans, params);
|
||||
else
|
||||
iwl_fw_dbg_start_stop_hcmd(fwrt, false);
|
||||
/* if the FW crashed or not debug monitor cfg was given, there is
|
||||
* no point in stopping
|
||||
*/
|
||||
if (test_bit(STATUS_FW_ERROR, &trans->status) ||
|
||||
(!trans->dbg.dest_tlv &&
|
||||
trans->dbg.ini_dest == IWL_FW_INI_LOCATION_INVALID))
|
||||
return;
|
||||
|
||||
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) {
|
||||
IWL_ERR(trans,
|
||||
"WRT: unsupported device family %d for debug stop recording\n",
|
||||
trans->cfg->device_family);
|
||||
return;
|
||||
}
|
||||
_iwl_fw_dbg_stop_recording(trans, params);
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
@ -324,7 +322,6 @@ _iwl_fw_dbg_restart_recording(struct iwl_trans *trans,
|
|||
iwl_set_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x1);
|
||||
} else {
|
||||
iwl_write_umac_prph(trans, DBGC_IN_SAMPLE, params->in_sample);
|
||||
udelay(100);
|
||||
iwl_write_umac_prph(trans, DBGC_OUT_CTRL, params->out_ctrl);
|
||||
}
|
||||
}
|
||||
|
@ -332,8 +329,10 @@ _iwl_fw_dbg_restart_recording(struct iwl_trans *trans,
|
|||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
static inline void iwl_fw_set_dbg_rec_on(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
if (fwrt->fw->dbg.dest_tlv && fwrt->cur_fw_img == IWL_UCODE_REGULAR)
|
||||
fwrt->trans->dbg_rec_on = true;
|
||||
if (fwrt->cur_fw_img == IWL_UCODE_REGULAR &&
|
||||
(fwrt->fw->dbg.dest_tlv ||
|
||||
fwrt->trans->dbg.ini_dest != IWL_FW_INI_LOCATION_INVALID))
|
||||
fwrt->trans->dbg.rec_on = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -341,10 +340,21 @@ static inline void
|
|||
iwl_fw_dbg_restart_recording(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_fw_dbg_params *params)
|
||||
{
|
||||
if (fwrt->trans->cfg->device_family < IWL_DEVICE_FAMILY_22560)
|
||||
_iwl_fw_dbg_restart_recording(fwrt->trans, params);
|
||||
else
|
||||
iwl_fw_dbg_start_stop_hcmd(fwrt, true);
|
||||
/* if the FW crashed or not debug monitor cfg was given, there is
|
||||
* no point in restarting
|
||||
*/
|
||||
if (test_bit(STATUS_FW_ERROR, &fwrt->trans->status) ||
|
||||
(!fwrt->trans->dbg.dest_tlv &&
|
||||
fwrt->trans->dbg.ini_dest == IWL_FW_INI_LOCATION_INVALID))
|
||||
return;
|
||||
|
||||
if (fwrt->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) {
|
||||
IWL_ERR(fwrt,
|
||||
"WRT: unsupported device family %d for debug restart recording\n",
|
||||
fwrt->trans->cfg->device_family);
|
||||
return;
|
||||
}
|
||||
_iwl_fw_dbg_restart_recording(fwrt->trans, params);
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
iwl_fw_set_dbg_rec_on(fwrt);
|
||||
#endif
|
||||
|
@ -359,7 +369,7 @@ void iwl_fw_error_dump_wk(struct work_struct *work);
|
|||
|
||||
static inline bool iwl_fw_dbg_type_on(struct iwl_fw_runtime *fwrt, u32 type)
|
||||
{
|
||||
return (fwrt->fw->dbg.dump_mask & BIT(type) || fwrt->trans->ini_valid);
|
||||
return (fwrt->fw->dbg.dump_mask & BIT(type));
|
||||
}
|
||||
|
||||
static inline bool iwl_fw_dbg_is_d3_debug_enabled(struct iwl_fw_runtime *fwrt)
|
||||
|
@ -383,16 +393,26 @@ static inline bool iwl_fw_dbg_is_paging_enabled(struct iwl_fw_runtime *fwrt)
|
|||
|
||||
void iwl_fw_dbg_read_d3_debug_data(struct iwl_fw_runtime *fwrt);
|
||||
|
||||
static inline void iwl_fw_flush_dump(struct iwl_fw_runtime *fwrt)
|
||||
static inline void iwl_fw_flush_dumps(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
int i;
|
||||
|
||||
del_timer(&fwrt->dump.periodic_trig);
|
||||
flush_delayed_work(&fwrt->dump.wk);
|
||||
for (i = 0; i < IWL_FW_RUNTIME_DUMP_WK_NUM; i++) {
|
||||
flush_delayed_work(&fwrt->dump.wks[i].wk);
|
||||
fwrt->dump.wks[i].ini_trig_id = IWL_FW_TRIGGER_ID_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void iwl_fw_cancel_dump(struct iwl_fw_runtime *fwrt)
|
||||
static inline void iwl_fw_cancel_dumps(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
int i;
|
||||
|
||||
del_timer(&fwrt->dump.periodic_trig);
|
||||
cancel_delayed_work_sync(&fwrt->dump.wk);
|
||||
for (i = 0; i < IWL_FW_RUNTIME_DUMP_WK_NUM; i++) {
|
||||
cancel_delayed_work_sync(&fwrt->dump.wks[i].wk);
|
||||
fwrt->dump.wks[i].ini_trig_id = IWL_FW_TRIGGER_ID_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
|
@ -431,7 +451,6 @@ static inline void iwl_fw_resume_timestamp(struct iwl_fw_runtime *fwrt) {}
|
|||
|
||||
#endif /* CONFIG_IWLWIFI_DEBUGFS */
|
||||
|
||||
void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt);
|
||||
void iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt,
|
||||
enum iwl_fw_ini_apply_point apply_point);
|
||||
|
||||
|
@ -440,31 +459,28 @@ void iwl_fwrt_stop_device(struct iwl_fw_runtime *fwrt);
|
|||
static inline void iwl_fw_lmac1_set_alive_err_table(struct iwl_trans *trans,
|
||||
u32 lmac_error_event_table)
|
||||
{
|
||||
if (!(trans->error_event_table_tlv_status &
|
||||
if (!(trans->dbg.error_event_table_tlv_status &
|
||||
IWL_ERROR_EVENT_TABLE_LMAC1) ||
|
||||
WARN_ON(trans->lmac_error_event_table[0] !=
|
||||
WARN_ON(trans->dbg.lmac_error_event_table[0] !=
|
||||
lmac_error_event_table))
|
||||
trans->lmac_error_event_table[0] = lmac_error_event_table;
|
||||
trans->dbg.lmac_error_event_table[0] = lmac_error_event_table;
|
||||
}
|
||||
|
||||
static inline void iwl_fw_umac_set_alive_err_table(struct iwl_trans *trans,
|
||||
u32 umac_error_event_table)
|
||||
{
|
||||
if (!(trans->error_event_table_tlv_status &
|
||||
if (!(trans->dbg.error_event_table_tlv_status &
|
||||
IWL_ERROR_EVENT_TABLE_UMAC) ||
|
||||
WARN_ON(trans->umac_error_event_table !=
|
||||
WARN_ON(trans->dbg.umac_error_event_table !=
|
||||
umac_error_event_table))
|
||||
trans->umac_error_event_table = umac_error_event_table;
|
||||
trans->dbg.umac_error_event_table = umac_error_event_table;
|
||||
}
|
||||
|
||||
/* This bit is used to differentiate the legacy dump from the ini dump */
|
||||
#define INI_DUMP_BIT BIT(31)
|
||||
|
||||
static inline void iwl_fw_error_collect(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
if (fwrt->trans->ini_valid && fwrt->trans->hw_error) {
|
||||
if (fwrt->trans->dbg.ini_valid && fwrt->trans->dbg.hw_error) {
|
||||
_iwl_fw_dbg_ini_collect(fwrt, IWL_FW_TRIGGER_ID_FW_HW_ERROR);
|
||||
fwrt->trans->hw_error = false;
|
||||
fwrt->trans->dbg.hw_error = false;
|
||||
} else {
|
||||
iwl_fw_dbg_collect_desc(fwrt, &iwl_dump_desc_assert, false, 0);
|
||||
}
|
||||
|
@ -473,4 +489,21 @@ static inline void iwl_fw_error_collect(struct iwl_fw_runtime *fwrt)
|
|||
void iwl_fw_dbg_periodic_trig_handler(struct timer_list *t);
|
||||
|
||||
void iwl_fw_error_print_fseq_regs(struct iwl_fw_runtime *fwrt);
|
||||
|
||||
static inline void iwl_fwrt_update_fw_versions(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_lmac_alive *lmac,
|
||||
struct iwl_umac_alive *umac)
|
||||
{
|
||||
if (lmac) {
|
||||
fwrt->dump.fw_ver.type = lmac->ver_type;
|
||||
fwrt->dump.fw_ver.subtype = lmac->ver_subtype;
|
||||
fwrt->dump.fw_ver.lmac_major = le32_to_cpu(lmac->ucode_major);
|
||||
fwrt->dump.fw_ver.lmac_minor = le32_to_cpu(lmac->ucode_minor);
|
||||
}
|
||||
|
||||
if (umac) {
|
||||
fwrt->dump.fw_ver.umac_major = le32_to_cpu(umac->umac_major);
|
||||
fwrt->dump.fw_ver.umac_minor = le32_to_cpu(umac->umac_minor);
|
||||
}
|
||||
}
|
||||
#endif /* __iwl_fw_dbg_h__ */
|
||||
|
|
|
@ -67,6 +67,7 @@
|
|||
#include <linux/types.h>
|
||||
|
||||
#define IWL_FW_ERROR_DUMP_BARKER 0x14789632
|
||||
#define IWL_FW_INI_ERROR_DUMP_BARKER 0x14789633
|
||||
|
||||
/**
|
||||
* enum iwl_fw_error_dump_type - types of data in the dump file
|
||||
|
@ -278,19 +279,42 @@ struct iwl_fw_error_dump_mem {
|
|||
u8 data[];
|
||||
};
|
||||
|
||||
#define IWL_INI_DUMP_MEM_VER 1
|
||||
#define IWL_INI_DUMP_MONITOR_VER 1
|
||||
#define IWL_INI_DUMP_FIFO_VER 1
|
||||
/* Dump version, used by the dump parser to differentiate between
|
||||
* different dump formats
|
||||
*/
|
||||
#define IWL_INI_DUMP_VER 1
|
||||
|
||||
/* Use bit 31 as dump info type to avoid colliding with region types */
|
||||
#define IWL_INI_DUMP_INFO_TYPE BIT(31)
|
||||
|
||||
/**
|
||||
* struct iwl_fw_ini_fifo_hdr - fifo range header
|
||||
* @fifo_num: the fifo number. In case of umac rx fifo, set BIT(31) to
|
||||
* distinguish between lmac and umac rx fifos
|
||||
* @num_of_registers: num of registers to dump, dword size each
|
||||
*/
|
||||
struct iwl_fw_ini_fifo_hdr {
|
||||
__le32 fifo_num;
|
||||
__le32 num_of_registers;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_fw_ini_error_dump_range - range of memory
|
||||
* @range_data_size: the size of this range, in bytes
|
||||
* @start_addr: the start address of this range
|
||||
* @internal_base_addr - base address of internal memory range
|
||||
* @dram_base_addr - base address of dram monitor range
|
||||
* @page_num - page number of memory range
|
||||
* @fifo_hdr - fifo header of memory range
|
||||
* @data: the actual memory
|
||||
*/
|
||||
struct iwl_fw_ini_error_dump_range {
|
||||
__le32 range_data_size;
|
||||
__le64 start_addr;
|
||||
union {
|
||||
__le32 internal_base_addr;
|
||||
__le64 dram_base_addr;
|
||||
__le32 page_num;
|
||||
struct iwl_fw_ini_fifo_hdr fifo_hdr;
|
||||
};
|
||||
__le32 data[];
|
||||
} __packed;
|
||||
|
||||
|
@ -333,30 +357,63 @@ struct iwl_fw_ini_error_dump_register {
|
|||
__le32 data;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_fw_ini_fifo_error_dump_range - ini fifo range dump
|
||||
* @fifo_num: the fifo num. In case of rxf and umac rxf, set BIT(31) to
|
||||
* distinguish between lmac and umac
|
||||
* @num_of_registers: num of registers to dump, dword size each
|
||||
* @range_data_size: the size of the data
|
||||
* @data: consist of
|
||||
* num_of_registers * (register address + register value) + fifo data
|
||||
/* struct iwl_fw_ini_dump_info - ini dump information
|
||||
* @version: dump version
|
||||
* @trigger_id: trigger id that caused the dump collection
|
||||
* @trigger_reason: not supported yet
|
||||
* @is_external_cfg: 1 if an external debug configuration was loaded
|
||||
* and 0 otherwise
|
||||
* @ver_type: FW version type
|
||||
* @ver_subtype: FW version subype
|
||||
* @hw_step: HW step
|
||||
* @hw_type: HW type
|
||||
* @rf_id_flavor: HW RF id flavor
|
||||
* @rf_id_dash: HW RF id dash
|
||||
* @rf_id_step: HW RF id step
|
||||
* @rf_id_type: HW RF id type
|
||||
* @lmac_major: lmac major version
|
||||
* @lmac_minor: lmac minor version
|
||||
* @umac_major: umac major version
|
||||
* @umac_minor: umac minor version
|
||||
* @build_tag_len: length of the build tag
|
||||
* @build_tag: build tag string
|
||||
* @img_name_len: length of the FW image name
|
||||
* @img_name: FW image name
|
||||
* @internal_dbg_cfg_name_len: length of the internal debug configuration name
|
||||
* @internal_dbg_cfg_name: internal debug configuration name
|
||||
* @external_dbg_cfg_name_len: length of the external debug configuration name
|
||||
* @external_dbg_cfg_name: external debug configuration name
|
||||
* @regions_num: number of region ids
|
||||
* @region_ids: region ids the trigger configured to collect
|
||||
*/
|
||||
struct iwl_fw_ini_fifo_error_dump_range {
|
||||
__le32 fifo_num;
|
||||
__le32 num_of_registers;
|
||||
__le32 range_data_size;
|
||||
__le32 data[];
|
||||
} __packed;
|
||||
struct iwl_fw_ini_dump_info {
|
||||
__le32 version;
|
||||
__le32 trigger_id;
|
||||
__le32 trigger_reason;
|
||||
__le32 is_external_cfg;
|
||||
__le32 ver_type;
|
||||
__le32 ver_subtype;
|
||||
__le32 hw_step;
|
||||
__le32 hw_type;
|
||||
__le32 rf_id_flavor;
|
||||
__le32 rf_id_dash;
|
||||
__le32 rf_id_step;
|
||||
__le32 rf_id_type;
|
||||
__le32 lmac_major;
|
||||
__le32 lmac_minor;
|
||||
__le32 umac_major;
|
||||
__le32 umac_minor;
|
||||
__le32 build_tag_len;
|
||||
u8 build_tag[FW_VER_HUMAN_READABLE_SZ];
|
||||
__le32 img_name_len;
|
||||
u8 img_name[IWL_FW_INI_MAX_IMG_NAME_LEN];
|
||||
__le32 internal_dbg_cfg_name_len;
|
||||
u8 internal_dbg_cfg_name[IWL_FW_INI_MAX_DBG_CFG_NAME_LEN];
|
||||
__le32 external_dbg_cfg_name_len;
|
||||
u8 external_dbg_cfg_name[IWL_FW_INI_MAX_DBG_CFG_NAME_LEN];
|
||||
__le32 regions_num;
|
||||
__le32 region_ids[];
|
||||
|
||||
/**
|
||||
* struct iwl_fw_ini_fifo_error_dump - ini fifo region dump
|
||||
* @header: the header of this region
|
||||
* @ranges: the memory ranges of this region
|
||||
*/
|
||||
struct iwl_fw_ini_fifo_error_dump {
|
||||
struct iwl_fw_ini_error_dump_header header;
|
||||
struct iwl_fw_ini_fifo_error_dump_range ranges[];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
|
|
|
@ -151,12 +151,13 @@ enum iwl_ucode_tlv_type {
|
|||
IWL_UCODE_TLV_FW_RECOVERY_INFO = 57,
|
||||
IWL_UCODE_TLV_FW_FSEQ_VERSION = 60,
|
||||
|
||||
IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION = IWL_UCODE_INI_TLV_GROUP + 0x1,
|
||||
IWL_UCODE_TLV_DEBUG_BASE = IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION,
|
||||
IWL_UCODE_TLV_TYPE_HCMD = IWL_UCODE_INI_TLV_GROUP + 0x2,
|
||||
IWL_UCODE_TLV_TYPE_REGIONS = IWL_UCODE_INI_TLV_GROUP + 0x3,
|
||||
IWL_UCODE_TLV_TYPE_TRIGGERS = IWL_UCODE_INI_TLV_GROUP + 0x4,
|
||||
IWL_UCODE_TLV_TYPE_DEBUG_FLOW = IWL_UCODE_INI_TLV_GROUP + 0x5,
|
||||
IWL_UCODE_TLV_DEBUG_BASE = IWL_UCODE_INI_TLV_GROUP,
|
||||
IWL_UCODE_TLV_TYPE_DEBUG_INFO = IWL_UCODE_TLV_DEBUG_BASE + 0,
|
||||
IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION = IWL_UCODE_TLV_DEBUG_BASE + 1,
|
||||
IWL_UCODE_TLV_TYPE_HCMD = IWL_UCODE_TLV_DEBUG_BASE + 2,
|
||||
IWL_UCODE_TLV_TYPE_REGIONS = IWL_UCODE_TLV_DEBUG_BASE + 3,
|
||||
IWL_UCODE_TLV_TYPE_TRIGGERS = IWL_UCODE_TLV_DEBUG_BASE + 4,
|
||||
IWL_UCODE_TLV_TYPE_DEBUG_FLOW = IWL_UCODE_TLV_DEBUG_BASE + 5,
|
||||
IWL_UCODE_TLV_DEBUG_MAX = IWL_UCODE_TLV_TYPE_DEBUG_FLOW,
|
||||
|
||||
/* TLVs 0x1000-0x2000 are for internal driver usage */
|
||||
|
@ -286,6 +287,8 @@ typedef unsigned int __bitwise iwl_ucode_tlv_api_t;
|
|||
* SCAN_OFFLOAD_PROFILES_QUERY_RSP_S.
|
||||
* @IWL_UCODE_TLV_API_MBSSID_HE: This ucode supports v2 of
|
||||
* STA_CONTEXT_DOT11AX_API_S
|
||||
* @IWL_UCODE_TLV_CAPA_SAR_TABLE_VER: This ucode supports different sar
|
||||
* version tables.
|
||||
*
|
||||
* @NUM_IWL_UCODE_TLV_API: number of bits used
|
||||
*/
|
||||
|
@ -318,6 +321,8 @@ enum iwl_ucode_tlv_api {
|
|||
IWL_UCODE_TLV_API_MBSSID_HE = (__force iwl_ucode_tlv_api_t)52,
|
||||
IWL_UCODE_TLV_API_WOWLAN_TCP_SYN_WAKE = (__force iwl_ucode_tlv_api_t)53,
|
||||
IWL_UCODE_TLV_API_FTM_RTT_ACCURACY = (__force iwl_ucode_tlv_api_t)54,
|
||||
IWL_UCODE_TLV_API_SAR_TABLE_VER = (__force iwl_ucode_tlv_api_t)55,
|
||||
IWL_UCODE_TLV_API_ADWELL_HB_DEF_N_AP = (__force iwl_ucode_tlv_api_t)57,
|
||||
|
||||
NUM_IWL_UCODE_TLV_API
|
||||
#ifdef __CHECKER__
|
||||
|
|
|
@ -67,6 +67,8 @@ void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans,
|
|||
const struct iwl_fw_runtime_ops *ops, void *ops_ctx,
|
||||
struct dentry *dbgfs_dir)
|
||||
{
|
||||
int i;
|
||||
|
||||
memset(fwrt, 0, sizeof(*fwrt));
|
||||
fwrt->trans = trans;
|
||||
fwrt->fw = fw;
|
||||
|
@ -74,7 +76,10 @@ void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans,
|
|||
fwrt->dump.conf = FW_DBG_INVALID;
|
||||
fwrt->ops = ops;
|
||||
fwrt->ops_ctx = ops_ctx;
|
||||
INIT_DELAYED_WORK(&fwrt->dump.wk, iwl_fw_error_dump_wk);
|
||||
for (i = 0; i < IWL_FW_RUNTIME_DUMP_WK_NUM; i++) {
|
||||
fwrt->dump.wks[i].idx = i;
|
||||
INIT_DELAYED_WORK(&fwrt->dump.wks[i].wk, iwl_fw_error_dump_wk);
|
||||
}
|
||||
iwl_fwrt_dbgfs_register(fwrt, dbgfs_dir);
|
||||
timer_setup(&fwrt->dump.periodic_trig,
|
||||
iwl_fw_dbg_periodic_trig_handler, 0);
|
||||
|
|
|
@ -89,9 +89,7 @@ struct iwl_fwrt_shared_mem_cfg {
|
|||
u32 internal_txfifo_size[TX_FIFO_INTERNAL_MAX_NUM];
|
||||
};
|
||||
|
||||
enum iwl_fw_runtime_status {
|
||||
IWL_FWRT_STATUS_DUMPING = 0,
|
||||
};
|
||||
#define IWL_FW_RUNTIME_DUMP_WK_NUM 5
|
||||
|
||||
/**
|
||||
* struct iwl_fw_runtime - runtime data for firmware
|
||||
|
@ -100,7 +98,6 @@ enum iwl_fw_runtime_status {
|
|||
* @dev: device pointer
|
||||
* @ops: user ops
|
||||
* @ops_ctx: user ops context
|
||||
* @status: status flags
|
||||
* @fw_paging_db: paging database
|
||||
* @num_of_paging_blk: number of paging blocks
|
||||
* @num_of_pages_in_last_blk: number of pages in the last block
|
||||
|
@ -117,8 +114,6 @@ struct iwl_fw_runtime {
|
|||
const struct iwl_fw_runtime_ops *ops;
|
||||
void *ops_ctx;
|
||||
|
||||
unsigned long status;
|
||||
|
||||
/* Paging */
|
||||
struct iwl_fw_paging fw_paging_db[NUM_OF_FW_PAGING_BLOCKS];
|
||||
u16 num_of_paging_blk;
|
||||
|
@ -133,7 +128,12 @@ struct iwl_fw_runtime {
|
|||
struct {
|
||||
const struct iwl_fw_dump_desc *desc;
|
||||
bool monitor_only;
|
||||
struct delayed_work wk;
|
||||
struct {
|
||||
u8 idx;
|
||||
enum iwl_fw_ini_trigger_id ini_trig_id;
|
||||
struct delayed_work wk;
|
||||
} wks[IWL_FW_RUNTIME_DUMP_WK_NUM];
|
||||
unsigned long active_wks;
|
||||
|
||||
u8 conf;
|
||||
|
||||
|
@ -145,8 +145,20 @@ struct iwl_fw_runtime {
|
|||
u32 lmac_err_id[MAX_NUM_LMAC];
|
||||
u32 umac_err_id;
|
||||
void *fifo_iter;
|
||||
enum iwl_fw_ini_trigger_id ini_trig_id;
|
||||
struct timer_list periodic_trig;
|
||||
|
||||
u8 img_name[IWL_FW_INI_MAX_IMG_NAME_LEN];
|
||||
u8 internal_dbg_cfg_name[IWL_FW_INI_MAX_DBG_CFG_NAME_LEN];
|
||||
u8 external_dbg_cfg_name[IWL_FW_INI_MAX_DBG_CFG_NAME_LEN];
|
||||
|
||||
struct {
|
||||
u8 type;
|
||||
u8 subtype;
|
||||
u32 lmac_major;
|
||||
u32 lmac_minor;
|
||||
u32 umac_major;
|
||||
u32 umac_minor;
|
||||
} fw_ver;
|
||||
} dump;
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
struct {
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||
* Copyright(c) 2018 Intel Corporation
|
||||
* Copyright(c) 2018 - 2019 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -31,7 +31,7 @@
|
|||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||
* Copyright(c) 2018 Intel Corporation
|
||||
* Copyright(c) 2018 - 2019 Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -134,6 +134,7 @@ void iwl_get_shared_mem_conf(struct iwl_fw_runtime *fwrt)
|
|||
.len = { 0, },
|
||||
};
|
||||
struct iwl_rx_packet *pkt;
|
||||
int ret;
|
||||
|
||||
if (fw_has_capa(&fwrt->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG))
|
||||
|
@ -141,8 +142,13 @@ void iwl_get_shared_mem_conf(struct iwl_fw_runtime *fwrt)
|
|||
else
|
||||
cmd.id = SHARED_MEM_CFG;
|
||||
|
||||
if (WARN_ON(iwl_trans_send_cmd(fwrt->trans, &cmd)))
|
||||
ret = iwl_trans_send_cmd(fwrt->trans, &cmd);
|
||||
|
||||
if (ret) {
|
||||
WARN(ret != -ERFKILL,
|
||||
"Could not send the SMEM command: %d\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
pkt = cmd.resp_pkt;
|
||||
if (fwrt->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22000)
|
||||
|
|
|
@ -81,9 +81,9 @@ void iwl_fw_dbg_copy_tlv(struct iwl_trans *trans, struct iwl_ucode_tlv *tlv,
|
|||
return;
|
||||
|
||||
if (ext)
|
||||
data = &trans->apply_points_ext[apply_point];
|
||||
data = &trans->dbg.apply_points_ext[apply_point];
|
||||
else
|
||||
data = &trans->apply_points[apply_point];
|
||||
data = &trans->dbg.apply_points[apply_point];
|
||||
|
||||
/* add room for is_alloc field in &iwl_fw_ini_allocation_data struct */
|
||||
if (le32_to_cpu(tlv->type) == IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION) {
|
||||
|
@ -172,14 +172,14 @@ void iwl_alloc_dbg_tlv(struct iwl_trans *trans, size_t len, const u8 *data,
|
|||
}
|
||||
|
||||
if (ext) {
|
||||
trans->apply_points_ext[i].data = mem;
|
||||
trans->apply_points_ext[i].size = size[i];
|
||||
trans->dbg.apply_points_ext[i].data = mem;
|
||||
trans->dbg.apply_points_ext[i].size = size[i];
|
||||
} else {
|
||||
trans->apply_points[i].data = mem;
|
||||
trans->apply_points[i].size = size[i];
|
||||
trans->dbg.apply_points[i].data = mem;
|
||||
trans->dbg.apply_points[i].size = size[i];
|
||||
}
|
||||
|
||||
trans->ini_valid = true;
|
||||
trans->dbg.ini_valid = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -187,14 +187,14 @@ void iwl_fw_dbg_free(struct iwl_trans *trans)
|
|||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(trans->apply_points); i++) {
|
||||
kfree(trans->apply_points[i].data);
|
||||
trans->apply_points[i].size = 0;
|
||||
trans->apply_points[i].offset = 0;
|
||||
for (i = 0; i < ARRAY_SIZE(trans->dbg.apply_points); i++) {
|
||||
kfree(trans->dbg.apply_points[i].data);
|
||||
trans->dbg.apply_points[i].size = 0;
|
||||
trans->dbg.apply_points[i].offset = 0;
|
||||
|
||||
kfree(trans->apply_points_ext[i].data);
|
||||
trans->apply_points_ext[i].size = 0;
|
||||
trans->apply_points_ext[i].offset = 0;
|
||||
kfree(trans->dbg.apply_points_ext[i].data);
|
||||
trans->dbg.apply_points_ext[i].size = 0;
|
||||
trans->dbg.apply_points_ext[i].offset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -221,6 +221,7 @@ static int iwl_parse_fw_dbg_tlv(struct iwl_trans *trans, const u8 *data,
|
|||
data += sizeof(*tlv) + ALIGN(tlv_len, 4);
|
||||
|
||||
switch (tlv_type) {
|
||||
case IWL_UCODE_TLV_TYPE_DEBUG_INFO:
|
||||
case IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION:
|
||||
case IWL_UCODE_TLV_TYPE_HCMD:
|
||||
case IWL_UCODE_TLV_TYPE_REGIONS:
|
||||
|
@ -242,7 +243,7 @@ void iwl_load_fw_dbg_tlv(struct device *dev, struct iwl_trans *trans)
|
|||
const struct firmware *fw;
|
||||
int res;
|
||||
|
||||
if (trans->external_ini_loaded || !iwlwifi_mod_params.enable_ini)
|
||||
if (trans->dbg.external_ini_loaded || !iwlwifi_mod_params.enable_ini)
|
||||
return;
|
||||
|
||||
res = request_firmware(&fw, "iwl-dbg-tlv.ini", dev);
|
||||
|
@ -252,6 +253,6 @@ void iwl_load_fw_dbg_tlv(struct device *dev, struct iwl_trans *trans)
|
|||
iwl_alloc_dbg_tlv(trans, fw->size, fw->data, true);
|
||||
iwl_parse_fw_dbg_tlv(trans, fw->data, fw->size);
|
||||
|
||||
trans->external_ini_loaded = true;
|
||||
trans->dbg.external_ini_loaded = true;
|
||||
release_firmware(fw);
|
||||
}
|
||||
|
|
|
@ -1105,6 +1105,18 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
|
|||
le32_to_cpu(recov_info->buf_size);
|
||||
}
|
||||
break;
|
||||
case IWL_UCODE_TLV_FW_FSEQ_VERSION: {
|
||||
struct {
|
||||
u8 version[32];
|
||||
u8 sha1[20];
|
||||
} *fseq_ver = (void *)tlv_data;
|
||||
|
||||
if (tlv_len != sizeof(*fseq_ver))
|
||||
goto invalid_tlv_len;
|
||||
IWL_INFO(drv, "TLV_FW_FSEQ_VERSION: %s\n",
|
||||
fseq_ver->version);
|
||||
}
|
||||
break;
|
||||
case IWL_UCODE_TLV_UMAC_DEBUG_ADDRS: {
|
||||
struct iwl_umac_debug_addrs *dbg_ptrs =
|
||||
(void *)tlv_data;
|
||||
|
@ -1114,10 +1126,10 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
|
|||
if (drv->trans->cfg->device_family <
|
||||
IWL_DEVICE_FAMILY_22000)
|
||||
break;
|
||||
drv->trans->umac_error_event_table =
|
||||
drv->trans->dbg.umac_error_event_table =
|
||||
le32_to_cpu(dbg_ptrs->error_info_addr) &
|
||||
~FW_ADDR_CACHE_CONTROL;
|
||||
drv->trans->error_event_table_tlv_status |=
|
||||
drv->trans->dbg.error_event_table_tlv_status |=
|
||||
IWL_ERROR_EVENT_TABLE_UMAC;
|
||||
break;
|
||||
}
|
||||
|
@ -1130,13 +1142,14 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
|
|||
if (drv->trans->cfg->device_family <
|
||||
IWL_DEVICE_FAMILY_22000)
|
||||
break;
|
||||
drv->trans->lmac_error_event_table[0] =
|
||||
drv->trans->dbg.lmac_error_event_table[0] =
|
||||
le32_to_cpu(dbg_ptrs->error_event_table_ptr) &
|
||||
~FW_ADDR_CACHE_CONTROL;
|
||||
drv->trans->error_event_table_tlv_status |=
|
||||
drv->trans->dbg.error_event_table_tlv_status |=
|
||||
IWL_ERROR_EVENT_TABLE_LMAC1;
|
||||
break;
|
||||
}
|
||||
case IWL_UCODE_TLV_TYPE_DEBUG_INFO:
|
||||
case IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION:
|
||||
case IWL_UCODE_TLV_TYPE_HCMD:
|
||||
case IWL_UCODE_TLV_TYPE_REGIONS:
|
||||
|
@ -1744,7 +1757,7 @@ IWL_EXPORT_SYMBOL(iwl_opmode_deregister);
|
|||
|
||||
static int __init iwl_drv_init(void)
|
||||
{
|
||||
int i;
|
||||
int i, err;
|
||||
|
||||
mutex_init(&iwlwifi_opmode_table_mtx);
|
||||
|
||||
|
@ -1759,7 +1772,17 @@ static int __init iwl_drv_init(void)
|
|||
iwl_dbgfs_root = debugfs_create_dir(DRV_NAME, NULL);
|
||||
#endif
|
||||
|
||||
return iwl_pci_register_driver();
|
||||
err = iwl_pci_register_driver();
|
||||
if (err)
|
||||
goto cleanup_debugfs;
|
||||
|
||||
return 0;
|
||||
|
||||
cleanup_debugfs:
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
debugfs_remove_recursive(iwl_dbgfs_root);
|
||||
#endif
|
||||
return err;
|
||||
}
|
||||
module_init(iwl_drv_init);
|
||||
|
||||
|
|
|
@ -721,6 +721,50 @@ struct iwl_self_init_dram {
|
|||
int paging_cnt;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_trans_debug - transport debug related data
|
||||
*
|
||||
* @n_dest_reg: num of reg_ops in %dbg_dest_tlv
|
||||
* @rec_on: true iff there is a fw debug recording currently active
|
||||
* @dest_tlv: points to the destination TLV for debug
|
||||
* @conf_tlv: array of pointers to configuration TLVs for debug
|
||||
* @trigger_tlv: array of pointers to triggers TLVs for debug
|
||||
* @lmac_error_event_table: addrs of lmacs error tables
|
||||
* @umac_error_event_table: addr of umac error table
|
||||
* @error_event_table_tlv_status: bitmap that indicates what error table
|
||||
* pointers was recevied via TLV. uses enum &iwl_error_event_table_status
|
||||
* @external_ini_loaded: indicates if an external ini cfg was given
|
||||
* @ini_valid: indicates if debug ini mode is on
|
||||
* @num_blocks: number of blocks in fw_mon
|
||||
* @fw_mon: address of the buffers for firmware monitor
|
||||
* @hw_error: equals true if hw error interrupt was received from the FW
|
||||
* @ini_dest: debug monitor destination uses &enum iwl_fw_ini_buffer_location
|
||||
*/
|
||||
struct iwl_trans_debug {
|
||||
u8 n_dest_reg;
|
||||
bool rec_on;
|
||||
|
||||
const struct iwl_fw_dbg_dest_tlv_v1 *dest_tlv;
|
||||
const struct iwl_fw_dbg_conf_tlv *conf_tlv[FW_DBG_CONF_MAX];
|
||||
struct iwl_fw_dbg_trigger_tlv * const *trigger_tlv;
|
||||
|
||||
u32 lmac_error_event_table[2];
|
||||
u32 umac_error_event_table;
|
||||
unsigned int error_event_table_tlv_status;
|
||||
|
||||
bool external_ini_loaded;
|
||||
bool ini_valid;
|
||||
|
||||
struct iwl_apply_point_data apply_points[IWL_FW_INI_APPLY_NUM];
|
||||
struct iwl_apply_point_data apply_points_ext[IWL_FW_INI_APPLY_NUM];
|
||||
|
||||
int num_blocks;
|
||||
struct iwl_dram_data fw_mon[IWL_FW_INI_APPLY_NUM];
|
||||
|
||||
bool hw_error;
|
||||
enum iwl_fw_ini_buffer_location ini_dest;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_trans - transport common data
|
||||
*
|
||||
|
@ -750,24 +794,12 @@ struct iwl_self_init_dram {
|
|||
* @rx_mpdu_cmd_hdr_size: used for tracing, amount of data before the
|
||||
* start of the 802.11 header in the @rx_mpdu_cmd
|
||||
* @dflt_pwr_limit: default power limit fetched from the platform (ACPI)
|
||||
* @dbg_dest_tlv: points to the destination TLV for debug
|
||||
* @dbg_conf_tlv: array of pointers to configuration TLVs for debug
|
||||
* @dbg_trigger_tlv: array of pointers to triggers TLVs for debug
|
||||
* @dbg_n_dest_reg: num of reg_ops in %dbg_dest_tlv
|
||||
* @num_blocks: number of blocks in fw_mon
|
||||
* @fw_mon: address of the buffers for firmware monitor
|
||||
* @system_pm_mode: the system-wide power management mode in use.
|
||||
* This mode is set dynamically, depending on the WoWLAN values
|
||||
* configured from the userspace at runtime.
|
||||
* @runtime_pm_mode: the runtime power management mode in use. This
|
||||
* mode is set during the initialization phase and is not
|
||||
* supposed to change during runtime.
|
||||
* @dbg_rec_on: true iff there is a fw debug recording currently active
|
||||
* @lmac_error_event_table: addrs of lmacs error tables
|
||||
* @umac_error_event_table: addr of umac error table
|
||||
* @error_event_table_tlv_status: bitmap that indicates what error table
|
||||
* pointers was recevied via TLV. use enum &iwl_error_event_table_status
|
||||
* @hw_error: equals true if hw error interrupt was received from the FW
|
||||
*/
|
||||
struct iwl_trans {
|
||||
const struct iwl_trans_ops *ops;
|
||||
|
@ -808,29 +840,12 @@ struct iwl_trans {
|
|||
struct lockdep_map sync_cmd_lockdep_map;
|
||||
#endif
|
||||
|
||||
struct iwl_apply_point_data apply_points[IWL_FW_INI_APPLY_NUM];
|
||||
struct iwl_apply_point_data apply_points_ext[IWL_FW_INI_APPLY_NUM];
|
||||
|
||||
bool external_ini_loaded;
|
||||
bool ini_valid;
|
||||
|
||||
const struct iwl_fw_dbg_dest_tlv_v1 *dbg_dest_tlv;
|
||||
const struct iwl_fw_dbg_conf_tlv *dbg_conf_tlv[FW_DBG_CONF_MAX];
|
||||
struct iwl_fw_dbg_trigger_tlv * const *dbg_trigger_tlv;
|
||||
u8 dbg_n_dest_reg;
|
||||
int num_blocks;
|
||||
struct iwl_dram_data fw_mon[IWL_FW_INI_APPLY_NUM];
|
||||
struct iwl_trans_debug dbg;
|
||||
struct iwl_self_init_dram init_dram;
|
||||
|
||||
enum iwl_plat_pm_mode system_pm_mode;
|
||||
enum iwl_plat_pm_mode runtime_pm_mode;
|
||||
bool suspending;
|
||||
bool dbg_rec_on;
|
||||
|
||||
u32 lmac_error_event_table[2];
|
||||
u32 umac_error_event_table;
|
||||
unsigned int error_event_table_tlv_status;
|
||||
bool hw_error;
|
||||
|
||||
/* pointer to trans specific struct */
|
||||
/*Ensure that this pointer will always be aligned to sizeof pointer */
|
||||
|
|
|
@ -152,5 +152,6 @@
|
|||
#define IWL_MVM_FTM_INITIATOR_ALGO IWL_TOF_ALGO_TYPE_MAX_LIKE
|
||||
#define IWL_MVM_FTM_INITIATOR_DYNACK true
|
||||
#define IWL_MVM_D3_DEBUG false
|
||||
#define IWL_MVM_USE_TWT false
|
||||
|
||||
#endif /* __MVM_CONSTANTS_H */
|
||||
|
|
|
@ -398,8 +398,7 @@ static int iwl_mvm_send_patterns_v1(struct iwl_mvm *mvm,
|
|||
if (!wowlan->n_patterns)
|
||||
return 0;
|
||||
|
||||
cmd.len[0] = sizeof(*pattern_cmd) +
|
||||
wowlan->n_patterns * sizeof(struct iwl_wowlan_pattern_v1);
|
||||
cmd.len[0] = struct_size(pattern_cmd, patterns, wowlan->n_patterns);
|
||||
|
||||
pattern_cmd = kmalloc(cmd.len[0], GFP_KERNEL);
|
||||
if (!pattern_cmd)
|
||||
|
@ -1079,11 +1078,12 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
|
|||
#endif
|
||||
|
||||
/*
|
||||
* TODO: this is needed because the firmware is not stopping
|
||||
* the recording automatically before entering D3. This can
|
||||
* be removed once the FW starts doing that.
|
||||
* Prior to 9000 device family the driver needs to stop the dbg
|
||||
* recording before entering D3. In later devices the FW stops the
|
||||
* recording automatically.
|
||||
*/
|
||||
_iwl_fw_dbg_stop_recording(mvm->fwrt.trans, NULL);
|
||||
if (mvm->trans->cfg->device_family < IWL_DEVICE_FAMILY_9000)
|
||||
iwl_fw_dbg_stop_recording(mvm->trans, NULL);
|
||||
|
||||
/* must be last -- this switches firmware state */
|
||||
ret = iwl_mvm_send_cmd(mvm, &d3_cfg_cmd);
|
||||
|
@ -1986,7 +1986,7 @@ static void iwl_mvm_d3_disconnect_iter(void *data, u8 *mac,
|
|||
static int iwl_mvm_check_rt_status(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
u32 base = mvm->trans->lmac_error_event_table[0];
|
||||
u32 base = mvm->trans->dbg.lmac_error_event_table[0];
|
||||
struct error_table_start {
|
||||
/* cf. struct iwl_error_event_table */
|
||||
u32 valid;
|
||||
|
|
|
@ -467,6 +467,46 @@ static ssize_t iwl_dbgfs_rs_data_read(struct file *file, char __user *user_buf,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_amsdu_len_write(struct ieee80211_sta *sta,
|
||||
char *buf, size_t count,
|
||||
loff_t *ppos)
|
||||
{
|
||||
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
int i;
|
||||
u16 amsdu_len;
|
||||
|
||||
if (kstrtou16(buf, 0, &amsdu_len))
|
||||
return -EINVAL;
|
||||
|
||||
if (amsdu_len) {
|
||||
mvmsta->orig_amsdu_len = sta->max_amsdu_len;
|
||||
sta->max_amsdu_len = amsdu_len;
|
||||
for (i = 0; i < ARRAY_SIZE(sta->max_tid_amsdu_len); i++)
|
||||
sta->max_tid_amsdu_len[i] = amsdu_len;
|
||||
} else {
|
||||
sta->max_amsdu_len = mvmsta->orig_amsdu_len;
|
||||
mvmsta->orig_amsdu_len = 0;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_amsdu_len_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ieee80211_sta *sta = file->private_data;
|
||||
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
|
||||
char buf[32];
|
||||
int pos;
|
||||
|
||||
pos = scnprintf(buf, sizeof(buf), "current %d ", sta->max_amsdu_len);
|
||||
pos += scnprintf(buf + pos, sizeof(buf) - pos, "stored %d\n",
|
||||
mvmsta->orig_amsdu_len);
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_disable_power_off_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
|
@ -1356,24 +1396,6 @@ static ssize_t iwl_dbgfs_fw_dbg_collect_write(struct iwl_mvm *mvm,
|
|||
return count;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_max_amsdu_len_write(struct iwl_mvm *mvm,
|
||||
char *buf, size_t count,
|
||||
loff_t *ppos)
|
||||
{
|
||||
unsigned int max_amsdu_len;
|
||||
int ret;
|
||||
|
||||
ret = kstrtouint(buf, 0, &max_amsdu_len);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (max_amsdu_len > IEEE80211_MAX_MPDU_LEN_VHT_11454)
|
||||
return -EINVAL;
|
||||
mvm->max_amsdu_len = max_amsdu_len;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
#define ADD_TEXT(...) pos += scnprintf(buf + pos, bufsz - pos, __VA_ARGS__)
|
||||
#ifdef CONFIG_IWLWIFI_BCAST_FILTERING
|
||||
static ssize_t iwl_dbgfs_bcast_filters_read(struct file *file,
|
||||
|
@ -1873,7 +1895,6 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8);
|
|||
MVM_DEBUGFS_READ_WRITE_FILE_OPS(d0i3_refs, 8);
|
||||
MVM_DEBUGFS_READ_WRITE_FILE_OPS(fw_dbg_conf, 8);
|
||||
MVM_DEBUGFS_WRITE_FILE_OPS(fw_dbg_collect, 64);
|
||||
MVM_DEBUGFS_WRITE_FILE_OPS(max_amsdu_len, 8);
|
||||
MVM_DEBUGFS_WRITE_FILE_OPS(indirection_tbl,
|
||||
(IWL_RSS_INDIRECTION_TABLE_SIZE * 2));
|
||||
MVM_DEBUGFS_WRITE_FILE_OPS(inject_packet, 512);
|
||||
|
@ -1891,6 +1912,8 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters_macs, 256);
|
|||
MVM_DEBUGFS_READ_FILE_OPS(sar_geo_profile);
|
||||
#endif
|
||||
|
||||
MVM_DEBUGFS_READ_WRITE_STA_FILE_OPS(amsdu_len, 16);
|
||||
|
||||
MVM_DEBUGFS_READ_WRITE_FILE_OPS(he_sniffer_params, 32);
|
||||
|
||||
static ssize_t iwl_dbgfs_mem_read(struct file *file, char __user *user_buf,
|
||||
|
@ -2032,8 +2055,10 @@ void iwl_mvm_sta_add_debugfs(struct ieee80211_hw *hw,
|
|||
{
|
||||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
|
||||
if (iwl_mvm_has_tlc_offload(mvm))
|
||||
if (iwl_mvm_has_tlc_offload(mvm)) {
|
||||
MVM_DEBUGFS_ADD_STA_FILE(rs_data, dir, 0400);
|
||||
}
|
||||
MVM_DEBUGFS_ADD_STA_FILE(amsdu_len, dir, 0600);
|
||||
}
|
||||
|
||||
void iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
|
||||
|
@ -2069,7 +2094,6 @@ void iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
|
|||
MVM_DEBUGFS_ADD_FILE(d0i3_refs, mvm->debugfs_dir, 0600);
|
||||
MVM_DEBUGFS_ADD_FILE(fw_dbg_conf, mvm->debugfs_dir, 0600);
|
||||
MVM_DEBUGFS_ADD_FILE(fw_dbg_collect, mvm->debugfs_dir, 0200);
|
||||
MVM_DEBUGFS_ADD_FILE(max_amsdu_len, mvm->debugfs_dir, 0200);
|
||||
MVM_DEBUGFS_ADD_FILE(send_echo_cmd, mvm->debugfs_dir, 0200);
|
||||
MVM_DEBUGFS_ADD_FILE(indirection_tbl, mvm->debugfs_dir, 0200);
|
||||
MVM_DEBUGFS_ADD_FILE(inject_packet, mvm->debugfs_dir, 0200);
|
||||
|
|
|
@ -238,7 +238,7 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
|
|||
iwl_fw_lmac1_set_alive_err_table(mvm->trans, lmac_error_event_table);
|
||||
|
||||
if (lmac2)
|
||||
mvm->trans->lmac_error_event_table[1] =
|
||||
mvm->trans->dbg.lmac_error_event_table[1] =
|
||||
le32_to_cpu(lmac2->dbg_ptrs.error_event_table_ptr);
|
||||
|
||||
umac_error_event_table = le32_to_cpu(umac->dbg_ptrs.error_info_addr);
|
||||
|
@ -276,6 +276,8 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
|
|||
le32_to_cpu(umac->umac_major),
|
||||
le32_to_cpu(umac->umac_minor));
|
||||
|
||||
iwl_fwrt_update_fw_versions(&mvm->fwrt, lmac1, umac);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -419,6 +421,8 @@ static int iwl_run_unified_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
|
|||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
mvm->rfkill_safe_init_done = false;
|
||||
|
||||
iwl_init_notification_wait(&mvm->notif_wait,
|
||||
&init_wait,
|
||||
init_complete,
|
||||
|
@ -537,8 +541,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
|
|||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
if (WARN_ON_ONCE(mvm->rfkill_safe_init_done))
|
||||
return 0;
|
||||
mvm->rfkill_safe_init_done = false;
|
||||
|
||||
iwl_init_notification_wait(&mvm->notif_wait,
|
||||
&calib_wait,
|
||||
|
@ -681,15 +684,15 @@ static int iwl_mvm_sar_get_wrds_table(struct iwl_mvm *mvm)
|
|||
{
|
||||
union acpi_object *wifi_pkg, *table, *data;
|
||||
bool enabled;
|
||||
int ret;
|
||||
int ret, tbl_rev;
|
||||
|
||||
data = iwl_acpi_get_object(mvm->dev, ACPI_WRDS_METHOD);
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
|
||||
wifi_pkg = iwl_acpi_get_wifi_pkg(mvm->dev, data,
|
||||
ACPI_WRDS_WIFI_DATA_SIZE);
|
||||
if (IS_ERR(wifi_pkg)) {
|
||||
ACPI_WRDS_WIFI_DATA_SIZE, &tbl_rev);
|
||||
if (IS_ERR(wifi_pkg) || tbl_rev != 0) {
|
||||
ret = PTR_ERR(wifi_pkg);
|
||||
goto out_free;
|
||||
}
|
||||
|
@ -718,15 +721,15 @@ static int iwl_mvm_sar_get_ewrd_table(struct iwl_mvm *mvm)
|
|||
{
|
||||
union acpi_object *wifi_pkg, *data;
|
||||
bool enabled;
|
||||
int i, n_profiles, ret;
|
||||
int i, n_profiles, ret, tbl_rev;
|
||||
|
||||
data = iwl_acpi_get_object(mvm->dev, ACPI_EWRD_METHOD);
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
|
||||
wifi_pkg = iwl_acpi_get_wifi_pkg(mvm->dev, data,
|
||||
ACPI_EWRD_WIFI_DATA_SIZE);
|
||||
if (IS_ERR(wifi_pkg)) {
|
||||
ACPI_EWRD_WIFI_DATA_SIZE, &tbl_rev);
|
||||
if (IS_ERR(wifi_pkg) || tbl_rev != 0) {
|
||||
ret = PTR_ERR(wifi_pkg);
|
||||
goto out_free;
|
||||
}
|
||||
|
@ -777,7 +780,7 @@ out_free:
|
|||
static int iwl_mvm_sar_get_wgds_table(struct iwl_mvm *mvm)
|
||||
{
|
||||
union acpi_object *wifi_pkg, *data;
|
||||
int i, j, ret;
|
||||
int i, j, ret, tbl_rev;
|
||||
int idx = 1;
|
||||
|
||||
data = iwl_acpi_get_object(mvm->dev, ACPI_WGDS_METHOD);
|
||||
|
@ -785,12 +788,13 @@ static int iwl_mvm_sar_get_wgds_table(struct iwl_mvm *mvm)
|
|||
return PTR_ERR(data);
|
||||
|
||||
wifi_pkg = iwl_acpi_get_wifi_pkg(mvm->dev, data,
|
||||
ACPI_WGDS_WIFI_DATA_SIZE);
|
||||
if (IS_ERR(wifi_pkg)) {
|
||||
ACPI_WGDS_WIFI_DATA_SIZE, &tbl_rev);
|
||||
if (IS_ERR(wifi_pkg) || tbl_rev > 1) {
|
||||
ret = PTR_ERR(wifi_pkg);
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
mvm->geo_rev = tbl_rev;
|
||||
for (i = 0; i < ACPI_NUM_GEO_PROFILES; i++) {
|
||||
for (j = 0; j < ACPI_GEO_TABLE_SIZE; j++) {
|
||||
union acpi_object *entry;
|
||||
|
@ -858,6 +862,9 @@ int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b)
|
|||
return -ENOENT;
|
||||
}
|
||||
|
||||
IWL_DEBUG_INFO(mvm,
|
||||
"SAR EWRD: chain %d profile index %d\n",
|
||||
i, profs[i]);
|
||||
IWL_DEBUG_RADIO(mvm, " Chain[%d]:\n", i);
|
||||
for (j = 0; j < ACPI_SAR_NUM_SUB_BANDS; j++) {
|
||||
idx = (i * ACPI_SAR_NUM_SUB_BANDS) + j;
|
||||
|
@ -877,15 +884,29 @@ int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm)
|
|||
{
|
||||
struct iwl_geo_tx_power_profiles_resp *resp;
|
||||
int ret;
|
||||
u16 len;
|
||||
void *data;
|
||||
struct iwl_geo_tx_power_profiles_cmd geo_cmd;
|
||||
struct iwl_geo_tx_power_profiles_cmd_v1 geo_cmd_v1;
|
||||
struct iwl_host_cmd cmd;
|
||||
|
||||
struct iwl_geo_tx_power_profiles_cmd geo_cmd = {
|
||||
.ops = cpu_to_le32(IWL_PER_CHAIN_OFFSET_GET_CURRENT_TABLE),
|
||||
};
|
||||
struct iwl_host_cmd cmd = {
|
||||
if (fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_SAR_TABLE_VER)) {
|
||||
geo_cmd.ops =
|
||||
cpu_to_le32(IWL_PER_CHAIN_OFFSET_GET_CURRENT_TABLE);
|
||||
len = sizeof(geo_cmd);
|
||||
data = &geo_cmd;
|
||||
} else {
|
||||
geo_cmd_v1.ops =
|
||||
cpu_to_le32(IWL_PER_CHAIN_OFFSET_GET_CURRENT_TABLE);
|
||||
len = sizeof(geo_cmd_v1);
|
||||
data = &geo_cmd_v1;
|
||||
}
|
||||
|
||||
cmd = (struct iwl_host_cmd){
|
||||
.id = WIDE_ID(PHY_OPS_GROUP, GEO_TX_POWER_LIMIT),
|
||||
.len = { sizeof(geo_cmd), },
|
||||
.len = { len, },
|
||||
.flags = CMD_WANT_SKB,
|
||||
.data = { &geo_cmd },
|
||||
.data = { data },
|
||||
};
|
||||
|
||||
ret = iwl_mvm_send_cmd(mvm, &cmd);
|
||||
|
@ -955,6 +976,16 @@ static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm)
|
|||
i, j, value[1], value[2], value[0]);
|
||||
}
|
||||
}
|
||||
|
||||
cmd.table_revision = cpu_to_le32(mvm->geo_rev);
|
||||
|
||||
if (!fw_has_api(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_API_SAR_TABLE_VER)) {
|
||||
return iwl_mvm_send_cmd_pdu(mvm, cmd_wide_id, 0,
|
||||
sizeof(struct iwl_geo_tx_power_profiles_cmd_v1),
|
||||
&cmd);
|
||||
}
|
||||
|
||||
return iwl_mvm_send_cmd_pdu(mvm, cmd_wide_id, 0, sizeof(cmd), &cmd);
|
||||
}
|
||||
|
||||
|
@ -1108,10 +1139,13 @@ static int iwl_mvm_load_rt_fw(struct iwl_mvm *mvm)
|
|||
|
||||
iwl_fw_dbg_apply_point(&mvm->fwrt, IWL_FW_INI_APPLY_EARLY);
|
||||
|
||||
mvm->rfkill_safe_init_done = false;
|
||||
ret = iwl_mvm_load_ucode_wait_alive(mvm, IWL_UCODE_REGULAR);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mvm->rfkill_safe_init_done = true;
|
||||
|
||||
iwl_fw_dbg_apply_point(&mvm->fwrt, IWL_FW_INI_APPLY_AFTER_ALIVE);
|
||||
|
||||
return iwl_init_paging(&mvm->fwrt, mvm->fwrt.cur_fw_img);
|
||||
|
@ -1144,7 +1178,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
|
|||
if (ret)
|
||||
IWL_ERR(mvm, "Failed to initialize Smart Fifo\n");
|
||||
|
||||
if (!mvm->trans->ini_valid) {
|
||||
if (!mvm->trans->dbg.ini_valid) {
|
||||
mvm->fwrt.dump.conf = FW_DBG_INVALID;
|
||||
/* if we have a destination, assume EARLY START */
|
||||
if (mvm->fw->dbg.dest_tlv)
|
||||
|
|
|
@ -558,15 +558,16 @@ static void iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
|
|||
|
||||
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
|
||||
u8 txf = iwl_mvm_mac_ac_to_tx_fifo(mvm, i);
|
||||
u8 ucode_ac = iwl_mvm_mac80211_ac_to_ucode_ac(i);
|
||||
|
||||
cmd->ac[txf].cw_min =
|
||||
cmd->ac[ucode_ac].cw_min =
|
||||
cpu_to_le16(mvmvif->queue_params[i].cw_min);
|
||||
cmd->ac[txf].cw_max =
|
||||
cmd->ac[ucode_ac].cw_max =
|
||||
cpu_to_le16(mvmvif->queue_params[i].cw_max);
|
||||
cmd->ac[txf].edca_txop =
|
||||
cmd->ac[ucode_ac].edca_txop =
|
||||
cpu_to_le16(mvmvif->queue_params[i].txop * 32);
|
||||
cmd->ac[txf].aifsn = mvmvif->queue_params[i].aifs;
|
||||
cmd->ac[txf].fifos_mask = BIT(txf);
|
||||
cmd->ac[ucode_ac].aifsn = mvmvif->queue_params[i].aifs;
|
||||
cmd->ac[ucode_ac].fifos_mask = BIT(txf);
|
||||
}
|
||||
|
||||
if (vif->bss_conf.qos)
|
||||
|
@ -678,7 +679,7 @@ static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,
|
|||
|
||||
if (vif->bss_conf.he_support && !iwlwifi_mod_params.disable_11ax) {
|
||||
cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_11AX);
|
||||
if (vif->bss_conf.twt_requester)
|
||||
if (vif->bss_conf.twt_requester && IWL_MVM_USE_TWT)
|
||||
ctxt_sta->data_policy |= cpu_to_le32(TWT_SUPPORTED);
|
||||
}
|
||||
|
||||
|
@ -1081,9 +1082,6 @@ static void iwl_mvm_mac_ctxt_cmd_fill_ap(struct iwl_mvm *mvm,
|
|||
IWL_DEBUG_HC(mvm, "No need to receive beacons\n");
|
||||
}
|
||||
|
||||
if (vif->bss_conf.he_support && !iwlwifi_mod_params.disable_11ax)
|
||||
cmd->filter_flags |= cpu_to_le32(MAC_FILTER_IN_11AX);
|
||||
|
||||
ctxt_ap->bi = cpu_to_le32(vif->bss_conf.beacon_int);
|
||||
ctxt_ap->dtim_interval = cpu_to_le32(vif->bss_conf.beacon_int *
|
||||
vif->bss_conf.dtim_period);
|
||||
|
|
|
@ -207,6 +207,12 @@ static const struct cfg80211_pmsr_capabilities iwl_mvm_pmsr_capa = {
|
|||
},
|
||||
};
|
||||
|
||||
static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
|
||||
enum set_key_cmd cmd,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *key);
|
||||
|
||||
void iwl_mvm_ref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type)
|
||||
{
|
||||
if (!iwl_mvm_is_d0i3_supported(mvm))
|
||||
|
@ -1439,7 +1445,7 @@ static void iwl_mvm_mac_stop(struct ieee80211_hw *hw)
|
|||
*/
|
||||
clear_bit(IWL_MVM_STATUS_FIRMWARE_RUNNING, &mvm->status);
|
||||
|
||||
iwl_fw_cancel_dump(&mvm->fwrt);
|
||||
iwl_fw_cancel_dumps(&mvm->fwrt);
|
||||
cancel_delayed_work_sync(&mvm->cs_tx_unblock_dwork);
|
||||
cancel_delayed_work_sync(&mvm->scan_timeout_dwork);
|
||||
iwl_fw_free_dump_desc(&mvm->fwrt);
|
||||
|
@ -2365,22 +2371,23 @@ static void iwl_mvm_cfg_he_sta(struct iwl_mvm *mvm,
|
|||
|
||||
/* Mark MU EDCA as enabled, unless none detected on some AC */
|
||||
flags |= STA_CTXT_HE_MU_EDCA_CW;
|
||||
for (i = 0; i < AC_NUM; i++) {
|
||||
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
|
||||
struct ieee80211_he_mu_edca_param_ac_rec *mu_edca =
|
||||
&mvmvif->queue_params[i].mu_edca_param_rec;
|
||||
u8 ac = iwl_mvm_mac80211_ac_to_ucode_ac(i);
|
||||
|
||||
if (!mvmvif->queue_params[i].mu_edca) {
|
||||
flags &= ~STA_CTXT_HE_MU_EDCA_CW;
|
||||
break;
|
||||
}
|
||||
|
||||
sta_ctxt_cmd.trig_based_txf[i].cwmin =
|
||||
sta_ctxt_cmd.trig_based_txf[ac].cwmin =
|
||||
cpu_to_le16(mu_edca->ecw_min_max & 0xf);
|
||||
sta_ctxt_cmd.trig_based_txf[i].cwmax =
|
||||
sta_ctxt_cmd.trig_based_txf[ac].cwmax =
|
||||
cpu_to_le16((mu_edca->ecw_min_max & 0xf0) >> 4);
|
||||
sta_ctxt_cmd.trig_based_txf[i].aifsn =
|
||||
sta_ctxt_cmd.trig_based_txf[ac].aifsn =
|
||||
cpu_to_le16(mu_edca->aifsn);
|
||||
sta_ctxt_cmd.trig_based_txf[i].mu_time =
|
||||
sta_ctxt_cmd.trig_based_txf[ac].mu_time =
|
||||
cpu_to_le16(mu_edca->mu_edca_timer);
|
||||
}
|
||||
|
||||
|
@ -2636,7 +2643,7 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
|
|||
{
|
||||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
int ret;
|
||||
int ret, i;
|
||||
|
||||
/*
|
||||
* iwl_mvm_mac_ctxt_add() might read directly from the device
|
||||
|
@ -2710,6 +2717,20 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
|
|||
/* must be set before quota calculations */
|
||||
mvmvif->ap_ibss_active = true;
|
||||
|
||||
/* send all the early keys to the device now */
|
||||
for (i = 0; i < ARRAY_SIZE(mvmvif->ap_early_keys); i++) {
|
||||
struct ieee80211_key_conf *key = mvmvif->ap_early_keys[i];
|
||||
|
||||
if (!key)
|
||||
continue;
|
||||
|
||||
mvmvif->ap_early_keys[i] = NULL;
|
||||
|
||||
ret = iwl_mvm_mac_set_key(hw, SET_KEY, vif, NULL, key);
|
||||
if (ret)
|
||||
goto out_quota_failed;
|
||||
}
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_AP && !vif->p2p) {
|
||||
iwl_mvm_vif_set_low_latency(mvmvif, true,
|
||||
LOW_LATENCY_VIF_TYPE);
|
||||
|
@ -3479,11 +3500,12 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
|
|||
struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *key)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
struct iwl_mvm_sta *mvmsta;
|
||||
struct iwl_mvm_key_pn *ptk_pn;
|
||||
int keyidx = key->keyidx;
|
||||
int ret;
|
||||
int ret, i;
|
||||
u8 key_offset;
|
||||
|
||||
if (iwlwifi_mod_params.swcrypto) {
|
||||
|
@ -3556,6 +3578,22 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
|
|||
key->hw_key_idx = STA_KEY_IDX_INVALID;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!mvmvif->ap_ibss_active) {
|
||||
for (i = 0;
|
||||
i < ARRAY_SIZE(mvmvif->ap_early_keys);
|
||||
i++) {
|
||||
if (!mvmvif->ap_early_keys[i]) {
|
||||
mvmvif->ap_early_keys[i] = key;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i >= ARRAY_SIZE(mvmvif->ap_early_keys))
|
||||
ret = -ENOSPC;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* During FW restart, in order to restore the state as it was,
|
||||
|
@ -3624,6 +3662,18 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
|
|||
|
||||
break;
|
||||
case DISABLE_KEY:
|
||||
ret = -ENOENT;
|
||||
for (i = 0; i < ARRAY_SIZE(mvmvif->ap_early_keys); i++) {
|
||||
if (mvmvif->ap_early_keys[i] == key) {
|
||||
mvmvif->ap_early_keys[i] = NULL;
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* found in pending list - don't do anything else */
|
||||
if (ret == 0)
|
||||
break;
|
||||
|
||||
if (key->hw_key_idx == STA_KEY_IDX_INVALID) {
|
||||
ret = 0;
|
||||
break;
|
||||
|
|
|
@ -501,6 +501,9 @@ struct iwl_mvm_vif {
|
|||
netdev_features_t features;
|
||||
|
||||
struct iwl_probe_resp_data __rcu *probe_resp_data;
|
||||
|
||||
/* we can only have 2 GTK + 2 IGTK active at a time */
|
||||
struct ieee80211_key_conf *ap_early_keys[4];
|
||||
};
|
||||
|
||||
static inline struct iwl_mvm_vif *
|
||||
|
@ -1107,7 +1110,6 @@ struct iwl_mvm {
|
|||
u8 ps_disabled; /* u8 instead of bool to ease debugfs_create_* usage */
|
||||
/* Indicate if 32Khz external clock is valid */
|
||||
u32 ext_clock_valid;
|
||||
unsigned int max_amsdu_len; /* used for debugfs only */
|
||||
|
||||
struct ieee80211_vif __rcu *csa_vif;
|
||||
struct ieee80211_vif __rcu *csa_tx_blocked_vif;
|
||||
|
@ -1181,6 +1183,7 @@ struct iwl_mvm {
|
|||
#ifdef CONFIG_ACPI
|
||||
struct iwl_mvm_sar_profile sar_profiles[ACPI_SAR_PROFILE_NUM];
|
||||
struct iwl_mvm_geo_profile geo_profiles[ACPI_NUM_GEO_PROFILES];
|
||||
u32 geo_rev;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -1307,6 +1310,12 @@ static inline bool iwl_mvm_is_adaptive_dwell_v2_supported(struct iwl_mvm *mvm)
|
|||
IWL_UCODE_TLV_API_ADAPTIVE_DWELL_V2);
|
||||
}
|
||||
|
||||
static inline bool iwl_mvm_is_adwell_hb_ap_num_supported(struct iwl_mvm *mvm)
|
||||
{
|
||||
return fw_has_api(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_API_ADWELL_HB_DEF_N_AP);
|
||||
}
|
||||
|
||||
static inline bool iwl_mvm_is_oce_supported(struct iwl_mvm *mvm)
|
||||
{
|
||||
/* OCE should never be enabled for LMAC scan FWs */
|
||||
|
@ -1532,6 +1541,7 @@ void iwl_mvm_hwrate_to_tx_rate(u32 rate_n_flags,
|
|||
enum nl80211_band band,
|
||||
struct ieee80211_tx_rate *r);
|
||||
u8 iwl_mvm_mac80211_idx_to_hwrate(int rate_idx);
|
||||
u8 iwl_mvm_mac80211_ac_to_ucode_ac(enum ieee80211_ac_numbers ac);
|
||||
void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm);
|
||||
u8 first_antenna(u8 mask);
|
||||
u8 iwl_mvm_next_antenna(struct iwl_mvm *mvm, u8 valid, u8 last_idx);
|
||||
|
|
|
@ -620,6 +620,7 @@ void iwl_mvm_rx_chub_update_mcc(struct iwl_mvm *mvm,
|
|||
enum iwl_mcc_source src;
|
||||
char mcc[3];
|
||||
struct ieee80211_regdomain *regd;
|
||||
u32 wgds_tbl_idx;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
|
@ -643,6 +644,14 @@ void iwl_mvm_rx_chub_update_mcc(struct iwl_mvm *mvm,
|
|||
if (IS_ERR_OR_NULL(regd))
|
||||
return;
|
||||
|
||||
wgds_tbl_idx = iwl_mvm_get_sar_geo_profile(mvm);
|
||||
if (wgds_tbl_idx < 0)
|
||||
IWL_DEBUG_INFO(mvm, "SAR WGDS is disabled (%d)\n",
|
||||
wgds_tbl_idx);
|
||||
else
|
||||
IWL_DEBUG_INFO(mvm, "SAR WGDS: geo profile %d is configured\n",
|
||||
wgds_tbl_idx);
|
||||
|
||||
regulatory_set_wiphy_regd(mvm->hw->wiphy, regd);
|
||||
kfree(regd);
|
||||
}
|
||||
|
|
|
@ -564,24 +564,24 @@ unlock:
|
|||
static int iwl_mvm_fwrt_dump_start(void *ctx)
|
||||
{
|
||||
struct iwl_mvm *mvm = ctx;
|
||||
int ret;
|
||||
|
||||
ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_FW_DBG_COLLECT);
|
||||
if (ret)
|
||||
return ret;
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
|
||||
return 0;
|
||||
ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_FW_DBG_COLLECT);
|
||||
if (ret)
|
||||
mutex_unlock(&mvm->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void iwl_mvm_fwrt_dump_end(void *ctx)
|
||||
{
|
||||
struct iwl_mvm *mvm = ctx;
|
||||
|
||||
mutex_unlock(&mvm->mutex);
|
||||
|
||||
iwl_mvm_unref(mvm, IWL_MVM_REF_FW_DBG_COLLECT);
|
||||
|
||||
mutex_unlock(&mvm->mutex);
|
||||
}
|
||||
|
||||
static bool iwl_mvm_fwrt_fw_running(void *ctx)
|
||||
|
@ -799,11 +799,11 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
|||
iwl_trans_configure(mvm->trans, &trans_cfg);
|
||||
|
||||
trans->rx_mpdu_cmd = REPLY_RX_MPDU_CMD;
|
||||
trans->dbg_dest_tlv = mvm->fw->dbg.dest_tlv;
|
||||
trans->dbg_n_dest_reg = mvm->fw->dbg.n_dest_reg;
|
||||
memcpy(trans->dbg_conf_tlv, mvm->fw->dbg.conf_tlv,
|
||||
sizeof(trans->dbg_conf_tlv));
|
||||
trans->dbg_trigger_tlv = mvm->fw->dbg.trigger_tlv;
|
||||
trans->dbg.dest_tlv = mvm->fw->dbg.dest_tlv;
|
||||
trans->dbg.n_dest_reg = mvm->fw->dbg.n_dest_reg;
|
||||
memcpy(trans->dbg.conf_tlv, mvm->fw->dbg.conf_tlv,
|
||||
sizeof(trans->dbg.conf_tlv));
|
||||
trans->dbg.trigger_tlv = mvm->fw->dbg.trigger_tlv;
|
||||
|
||||
trans->iml = mvm->fw->iml;
|
||||
trans->iml_len = mvm->fw->iml_len;
|
||||
|
@ -880,7 +880,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
|||
return op_mode;
|
||||
|
||||
out_free:
|
||||
iwl_fw_flush_dump(&mvm->fwrt);
|
||||
iwl_fw_flush_dumps(&mvm->fwrt);
|
||||
iwl_fw_runtime_free(&mvm->fwrt);
|
||||
|
||||
if (iwlmvm_mod_params.init_dbg)
|
||||
|
|
|
@ -101,7 +101,7 @@ static u8 rs_fw_sgi_cw_support(struct ieee80211_sta *sta)
|
|||
struct ieee80211_sta_he_cap *he_cap = &sta->he_cap;
|
||||
u8 supp = 0;
|
||||
|
||||
if (he_cap && he_cap->has_he)
|
||||
if (he_cap->has_he)
|
||||
return 0;
|
||||
|
||||
if (ht_cap->cap & IEEE80211_HT_CAP_SGI_20)
|
||||
|
@ -123,12 +123,12 @@ static u16 rs_fw_get_config_flags(struct iwl_mvm *mvm,
|
|||
struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
|
||||
struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap;
|
||||
struct ieee80211_sta_he_cap *he_cap = &sta->he_cap;
|
||||
bool vht_ena = vht_cap && vht_cap->vht_supported;
|
||||
bool vht_ena = vht_cap->vht_supported;
|
||||
u16 flags = 0;
|
||||
|
||||
if (mvm->cfg->ht_params->stbc &&
|
||||
(num_of_ant(iwl_mvm_get_valid_tx_ant(mvm)) > 1)) {
|
||||
if (he_cap && he_cap->has_he) {
|
||||
if (he_cap->has_he) {
|
||||
if (he_cap->he_cap_elem.phy_cap_info[2] &
|
||||
IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ)
|
||||
flags |= IWL_TLC_MNG_CFG_FLAGS_STBC_MSK;
|
||||
|
@ -136,15 +136,14 @@ static u16 rs_fw_get_config_flags(struct iwl_mvm *mvm,
|
|||
if (he_cap->he_cap_elem.phy_cap_info[7] &
|
||||
IEEE80211_HE_PHY_CAP7_STBC_RX_ABOVE_80MHZ)
|
||||
flags |= IWL_TLC_MNG_CFG_FLAGS_HE_STBC_160MHZ_MSK;
|
||||
} else if ((ht_cap &&
|
||||
(ht_cap->cap & IEEE80211_HT_CAP_RX_STBC)) ||
|
||||
} else if ((ht_cap->cap & IEEE80211_HT_CAP_RX_STBC) ||
|
||||
(vht_ena &&
|
||||
(vht_cap->cap & IEEE80211_VHT_CAP_RXSTBC_MASK)))
|
||||
flags |= IWL_TLC_MNG_CFG_FLAGS_STBC_MSK;
|
||||
}
|
||||
|
||||
if (mvm->cfg->ht_params->ldpc &&
|
||||
((ht_cap && (ht_cap->cap & IEEE80211_HT_CAP_LDPC_CODING)) ||
|
||||
((ht_cap->cap & IEEE80211_HT_CAP_LDPC_CODING) ||
|
||||
(vht_ena && (vht_cap->cap & IEEE80211_VHT_CAP_RXLDPC))))
|
||||
flags |= IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK;
|
||||
|
||||
|
@ -154,7 +153,7 @@ static u16 rs_fw_get_config_flags(struct iwl_mvm *mvm,
|
|||
IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD))
|
||||
flags &= ~IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK;
|
||||
|
||||
if (he_cap && he_cap->has_he &&
|
||||
if (he_cap->has_he &&
|
||||
(he_cap->he_cap_elem.phy_cap_info[3] &
|
||||
IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_MASK))
|
||||
flags |= IWL_TLC_MNG_CFG_FLAGS_HE_DCM_NSS_1_MSK;
|
||||
|
@ -293,13 +292,13 @@ static void rs_fw_set_supp_rates(struct ieee80211_sta *sta,
|
|||
cmd->mode = IWL_TLC_MNG_MODE_NON_HT;
|
||||
|
||||
/* HT/VHT rates */
|
||||
if (he_cap && he_cap->has_he) {
|
||||
if (he_cap->has_he) {
|
||||
cmd->mode = IWL_TLC_MNG_MODE_HE;
|
||||
rs_fw_he_set_enabled_rates(sta, sband, cmd);
|
||||
} else if (vht_cap && vht_cap->vht_supported) {
|
||||
} else if (vht_cap->vht_supported) {
|
||||
cmd->mode = IWL_TLC_MNG_MODE_VHT;
|
||||
rs_fw_vht_set_enabled_rates(sta, vht_cap, cmd);
|
||||
} else if (ht_cap && ht_cap->ht_supported) {
|
||||
} else if (ht_cap->ht_supported) {
|
||||
cmd->mode = IWL_TLC_MNG_MODE_HT;
|
||||
cmd->ht_rates[0][0] = cpu_to_le16(ht_cap->mcs.rx_mask[0]);
|
||||
cmd->ht_rates[1][0] = cpu_to_le16(ht_cap->mcs.rx_mask[1]);
|
||||
|
@ -344,7 +343,7 @@ void iwl_mvm_tlc_update_notif(struct iwl_mvm *mvm,
|
|||
lq_sta->last_rate_n_flags);
|
||||
}
|
||||
|
||||
if (flags & IWL_TLC_NOTIF_FLAG_AMSDU) {
|
||||
if (flags & IWL_TLC_NOTIF_FLAG_AMSDU && !mvmsta->orig_amsdu_len) {
|
||||
u16 size = le32_to_cpu(notif->amsdu_size);
|
||||
int i;
|
||||
|
||||
|
@ -381,7 +380,7 @@ 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) {
|
||||
if (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;
|
||||
|
@ -391,7 +390,7 @@ static u16 rs_fw_get_max_amsdu_len(struct ieee80211_sta *sta)
|
|||
return IEEE80211_MAX_MPDU_LEN_VHT_3895;
|
||||
}
|
||||
|
||||
} else if (ht_cap && ht_cap->ht_supported) {
|
||||
} else if (ht_cap->ht_supported) {
|
||||
if (ht_cap->cap & IEEE80211_HT_CAP_MAX_AMSDU)
|
||||
/*
|
||||
* agg is offloaded so we need to assume that agg
|
||||
|
|
|
@ -83,8 +83,10 @@
|
|||
#define IWL_SCAN_ADWELL_MAX_BUDGET_FULL_SCAN 300
|
||||
/* adaptive dwell max budget time [TU] for directed scan */
|
||||
#define IWL_SCAN_ADWELL_MAX_BUDGET_DIRECTED_SCAN 100
|
||||
/* adaptive dwell default APs number */
|
||||
#define IWL_SCAN_ADWELL_DEFAULT_N_APS 2
|
||||
/* adaptive dwell default high band APs number */
|
||||
#define IWL_SCAN_ADWELL_DEFAULT_HB_N_APS 8
|
||||
/* adaptive dwell default low band APs number */
|
||||
#define IWL_SCAN_ADWELL_DEFAULT_LB_N_APS 2
|
||||
/* adaptive dwell default APs number in social channels (1, 6, 11) */
|
||||
#define IWL_SCAN_ADWELL_DEFAULT_N_APS_SOCIAL 10
|
||||
|
||||
|
@ -1288,7 +1290,11 @@ static void iwl_mvm_scan_umac_dwell(struct iwl_mvm *mvm,
|
|||
cmd->v7.adwell_default_n_aps_social =
|
||||
IWL_SCAN_ADWELL_DEFAULT_N_APS_SOCIAL;
|
||||
cmd->v7.adwell_default_n_aps =
|
||||
IWL_SCAN_ADWELL_DEFAULT_N_APS;
|
||||
IWL_SCAN_ADWELL_DEFAULT_LB_N_APS;
|
||||
|
||||
if (iwl_mvm_is_adwell_hb_ap_num_supported(mvm))
|
||||
cmd->v9.adwell_default_hb_n_aps =
|
||||
IWL_SCAN_ADWELL_DEFAULT_HB_N_APS;
|
||||
|
||||
/* if custom max budget was configured with debugfs */
|
||||
if (IWL_MVM_ADWELL_MAX_BUDGET)
|
||||
|
|
|
@ -386,6 +386,9 @@ struct iwl_mvm_rxq_dup_data {
|
|||
* @amsdu_enabled: bitmap of TX AMSDU allowed TIDs.
|
||||
* In case TLC offload is not active it is either 0xFFFF or 0.
|
||||
* @max_amsdu_len: max AMSDU length
|
||||
* @orig_amsdu_len: used to save the original amsdu_len when it is changed via
|
||||
* debugfs. If it's set to 0, it means that it is it's not set via
|
||||
* debugfs.
|
||||
* @agg_tids: bitmap of tids whose status is operational aggregated (IWL_AGG_ON)
|
||||
* @sleep_tx_count: the number of frames that we told the firmware to let out
|
||||
* even when that station is asleep. This is useful in case the queue
|
||||
|
@ -434,6 +437,7 @@ struct iwl_mvm_sta {
|
|||
bool disable_tx;
|
||||
u16 amsdu_enabled;
|
||||
u16 max_amsdu_len;
|
||||
u16 orig_amsdu_len;
|
||||
bool sleeping;
|
||||
u8 agg_tids;
|
||||
u8 sleep_tx_count;
|
||||
|
|
|
@ -726,6 +726,9 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
|
|||
|
||||
memcpy(&info, skb->cb, sizeof(info));
|
||||
|
||||
if (WARN_ON_ONCE(skb->len > IEEE80211_MAX_DATA_LEN + hdrlen))
|
||||
return -1;
|
||||
|
||||
if (WARN_ON_ONCE(info.flags & IEEE80211_TX_CTL_AMPDU))
|
||||
return -1;
|
||||
|
||||
|
@ -893,18 +896,15 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb,
|
|||
unsigned int mss = skb_shinfo(skb)->gso_size;
|
||||
unsigned int num_subframes, tcp_payload_len, subf_len, max_amsdu_len;
|
||||
u16 snap_ip_tcp, pad;
|
||||
unsigned int dbg_max_amsdu_len;
|
||||
netdev_features_t netdev_flags = NETIF_F_CSUM_MASK | NETIF_F_SG;
|
||||
u8 tid;
|
||||
|
||||
snap_ip_tcp = 8 + skb_transport_header(skb) - skb_network_header(skb) +
|
||||
tcp_hdrlen(skb);
|
||||
|
||||
dbg_max_amsdu_len = READ_ONCE(mvm->max_amsdu_len);
|
||||
|
||||
if (!mvmsta->max_amsdu_len ||
|
||||
!ieee80211_is_data_qos(hdr->frame_control) ||
|
||||
(!mvmsta->amsdu_enabled && !dbg_max_amsdu_len))
|
||||
!mvmsta->amsdu_enabled)
|
||||
return iwl_mvm_tx_tso_segment(skb, 1, netdev_flags, mpdus_skb);
|
||||
|
||||
/*
|
||||
|
@ -936,10 +936,6 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb,
|
|||
|
||||
max_amsdu_len = iwl_mvm_max_amsdu_size(mvm, sta, tid);
|
||||
|
||||
if (unlikely(dbg_max_amsdu_len))
|
||||
max_amsdu_len = min_t(unsigned int, max_amsdu_len,
|
||||
dbg_max_amsdu_len);
|
||||
|
||||
/*
|
||||
* Limit A-MSDU in A-MPDU to 4095 bytes when VHT is not
|
||||
* supported. This is a spec requirement (IEEE 802.11-2015
|
||||
|
@ -1063,7 +1059,9 @@ static int iwl_mvm_tx_pkt_queued(struct iwl_mvm *mvm,
|
|||
}
|
||||
|
||||
/*
|
||||
* Sets the fields in the Tx cmd that are crypto related
|
||||
* Sets the fields in the Tx cmd that are crypto related.
|
||||
*
|
||||
* This function must be called with BHs disabled.
|
||||
*/
|
||||
static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb,
|
||||
struct ieee80211_tx_info *info,
|
||||
|
|
|
@ -238,6 +238,18 @@ u8 iwl_mvm_mac80211_idx_to_hwrate(int rate_idx)
|
|||
return fw_rate_idx_to_plcp[rate_idx];
|
||||
}
|
||||
|
||||
u8 iwl_mvm_mac80211_ac_to_ucode_ac(enum ieee80211_ac_numbers ac)
|
||||
{
|
||||
static const u8 mac80211_ac_to_ucode_ac[] = {
|
||||
AC_VO,
|
||||
AC_VI,
|
||||
AC_BE,
|
||||
AC_BK
|
||||
};
|
||||
|
||||
return mac80211_ac_to_ucode_ac[ac];
|
||||
}
|
||||
|
||||
void iwl_mvm_rx_fw_error(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
|
@ -457,10 +469,10 @@ static void iwl_mvm_dump_umac_error_log(struct iwl_mvm *mvm)
|
|||
{
|
||||
struct iwl_trans *trans = mvm->trans;
|
||||
struct iwl_umac_error_event_table table;
|
||||
u32 base = mvm->trans->umac_error_event_table;
|
||||
u32 base = mvm->trans->dbg.umac_error_event_table;
|
||||
|
||||
if (!mvm->support_umac_log &&
|
||||
!(mvm->trans->error_event_table_tlv_status &
|
||||
!(mvm->trans->dbg.error_event_table_tlv_status &
|
||||
IWL_ERROR_EVENT_TABLE_UMAC))
|
||||
return;
|
||||
|
||||
|
@ -496,7 +508,7 @@ static void iwl_mvm_dump_lmac_error_log(struct iwl_mvm *mvm, u8 lmac_num)
|
|||
{
|
||||
struct iwl_trans *trans = mvm->trans;
|
||||
struct iwl_error_event_table table;
|
||||
u32 val, base = mvm->trans->lmac_error_event_table[lmac_num];
|
||||
u32 val, base = mvm->trans->dbg.lmac_error_event_table[lmac_num];
|
||||
|
||||
if (mvm->fwrt.cur_fw_img == IWL_UCODE_INIT) {
|
||||
if (!base)
|
||||
|
@ -592,7 +604,7 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm)
|
|||
|
||||
iwl_mvm_dump_lmac_error_log(mvm, 0);
|
||||
|
||||
if (mvm->trans->lmac_error_event_table[1])
|
||||
if (mvm->trans->dbg.lmac_error_event_table[1])
|
||||
iwl_mvm_dump_lmac_error_log(mvm, 1);
|
||||
|
||||
iwl_mvm_dump_umac_error_log(mvm);
|
||||
|
|
|
@ -96,13 +96,13 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans,
|
|||
cpu_to_le64(trans_pcie->rxq->bd_dma);
|
||||
|
||||
/* Configure debug, for integration */
|
||||
if (!trans->ini_valid)
|
||||
if (!trans->dbg.ini_valid)
|
||||
iwl_pcie_alloc_fw_monitor(trans, 0);
|
||||
if (trans->num_blocks) {
|
||||
if (trans->dbg.num_blocks) {
|
||||
prph_sc_ctrl->hwm_cfg.hwm_base_addr =
|
||||
cpu_to_le64(trans->fw_mon[0].physical);
|
||||
cpu_to_le64(trans->dbg.fw_mon[0].physical);
|
||||
prph_sc_ctrl->hwm_cfg.hwm_size =
|
||||
cpu_to_le32(trans->fw_mon[0].size);
|
||||
cpu_to_le32(trans->dbg.fw_mon[0].size);
|
||||
}
|
||||
|
||||
/* allocate ucode sections in dram and set addresses */
|
||||
|
@ -169,7 +169,7 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans,
|
|||
|
||||
memcpy(iml_img, trans->iml, trans->iml_len);
|
||||
|
||||
iwl_enable_interrupts(trans);
|
||||
iwl_enable_fw_load_int_ctx_info(trans);
|
||||
|
||||
/* kick FW self load */
|
||||
iwl_write64(trans, CSR_CTXT_INFO_ADDR,
|
||||
|
|
|
@ -222,7 +222,7 @@ int iwl_pcie_ctxt_info_init(struct iwl_trans *trans,
|
|||
|
||||
trans_pcie->ctxt_info = ctxt_info;
|
||||
|
||||
iwl_enable_interrupts(trans);
|
||||
iwl_enable_fw_load_int_ctx_info(trans);
|
||||
|
||||
/* Configure debug, if exists */
|
||||
if (iwl_pcie_dbg_on(trans))
|
||||
|
|
|
@ -874,6 +874,33 @@ static inline void iwl_enable_fw_load_int(struct iwl_trans *trans)
|
|||
}
|
||||
}
|
||||
|
||||
static inline void iwl_enable_fw_load_int_ctx_info(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
|
||||
IWL_DEBUG_ISR(trans, "Enabling ALIVE interrupt only\n");
|
||||
|
||||
if (!trans_pcie->msix_enabled) {
|
||||
/*
|
||||
* When we'll receive the ALIVE interrupt, the ISR will call
|
||||
* iwl_enable_fw_load_int_ctx_info again to set the ALIVE
|
||||
* interrupt (which is not really needed anymore) but also the
|
||||
* RX interrupt which will allow us to receive the ALIVE
|
||||
* notification (which is Rx) and continue the flow.
|
||||
*/
|
||||
trans_pcie->inta_mask = CSR_INT_BIT_ALIVE | CSR_INT_BIT_FH_RX;
|
||||
iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask);
|
||||
} else {
|
||||
iwl_enable_hw_int_msk_msix(trans,
|
||||
MSIX_HW_INT_CAUSES_REG_ALIVE);
|
||||
/*
|
||||
* Leave all the FH causes enabled to get the ALIVE
|
||||
* notification.
|
||||
*/
|
||||
iwl_enable_fh_int_msk_msix(trans, trans_pcie->fh_init_mask);
|
||||
}
|
||||
}
|
||||
|
||||
static inline u16 iwl_pcie_get_cmd_index(const struct iwl_txq *q, u32 index)
|
||||
{
|
||||
return index & (q->n_window - 1);
|
||||
|
@ -1018,7 +1045,7 @@ static inline void __iwl_trans_pcie_set_bit(struct iwl_trans *trans,
|
|||
|
||||
static inline bool iwl_pcie_dbg_on(struct iwl_trans *trans)
|
||||
{
|
||||
return (trans->dbg_dest_tlv || trans->ini_valid);
|
||||
return (trans->dbg.dest_tlv || trans->dbg.ini_valid);
|
||||
}
|
||||
|
||||
void iwl_trans_pcie_rf_kill(struct iwl_trans *trans, bool state);
|
||||
|
|
|
@ -1827,26 +1827,26 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (iwl_have_debug_level(IWL_DL_ISR)) {
|
||||
/* NIC fires this, but we don't use it, redundant with WAKEUP */
|
||||
if (inta & CSR_INT_BIT_SCD) {
|
||||
IWL_DEBUG_ISR(trans,
|
||||
"Scheduler finished to transmit the frame/frames.\n");
|
||||
isr_stats->sch++;
|
||||
/* NIC fires this, but we don't use it, redundant with WAKEUP */
|
||||
if (inta & CSR_INT_BIT_SCD) {
|
||||
IWL_DEBUG_ISR(trans,
|
||||
"Scheduler finished to transmit the frame/frames.\n");
|
||||
isr_stats->sch++;
|
||||
}
|
||||
|
||||
/* Alive notification via Rx interrupt will do the real work */
|
||||
if (inta & CSR_INT_BIT_ALIVE) {
|
||||
IWL_DEBUG_ISR(trans, "Alive interrupt\n");
|
||||
isr_stats->alive++;
|
||||
if (trans->cfg->gen2) {
|
||||
/*
|
||||
* We can restock, since firmware configured
|
||||
* the RFH
|
||||
*/
|
||||
iwl_pcie_rxmq_restock(trans, trans_pcie->rxq);
|
||||
}
|
||||
|
||||
/* Alive notification via Rx interrupt will do the real work */
|
||||
if (inta & CSR_INT_BIT_ALIVE) {
|
||||
IWL_DEBUG_ISR(trans, "Alive interrupt\n");
|
||||
isr_stats->alive++;
|
||||
if (trans->cfg->gen2) {
|
||||
/*
|
||||
* We can restock, since firmware configured
|
||||
* the RFH
|
||||
*/
|
||||
iwl_pcie_rxmq_restock(trans, trans_pcie->rxq);
|
||||
}
|
||||
}
|
||||
handled |= CSR_INT_BIT_ALIVE;
|
||||
}
|
||||
|
||||
/* Safely ignore these bits for debug checks below */
|
||||
|
@ -1965,6 +1965,9 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
|
|||
/* Re-enable RF_KILL if it occurred */
|
||||
else if (handled & CSR_INT_BIT_RF_KILL)
|
||||
iwl_enable_rfkill_int(trans);
|
||||
/* Re-enable the ALIVE / Rx interrupt if it occurred */
|
||||
else if (handled & (CSR_INT_BIT_ALIVE | CSR_INT_BIT_FH_RX))
|
||||
iwl_enable_fw_load_int_ctx_info(trans);
|
||||
spin_unlock(&trans_pcie->irq_lock);
|
||||
|
||||
out:
|
||||
|
@ -2108,10 +2111,18 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id)
|
|||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
if (iwl_have_debug_level(IWL_DL_ISR))
|
||||
IWL_DEBUG_ISR(trans, "ISR inta_fh 0x%08x, enabled 0x%08x\n",
|
||||
inta_fh,
|
||||
if (iwl_have_debug_level(IWL_DL_ISR)) {
|
||||
IWL_DEBUG_ISR(trans,
|
||||
"ISR inta_fh 0x%08x, enabled (sw) 0x%08x (hw) 0x%08x\n",
|
||||
inta_fh, trans_pcie->fh_mask,
|
||||
iwl_read32(trans, CSR_MSIX_FH_INT_MASK_AD));
|
||||
if (inta_fh & ~trans_pcie->fh_mask)
|
||||
IWL_DEBUG_ISR(trans,
|
||||
"We got a masked interrupt (0x%08x)\n",
|
||||
inta_fh & ~trans_pcie->fh_mask);
|
||||
}
|
||||
|
||||
inta_fh &= trans_pcie->fh_mask;
|
||||
|
||||
if ((trans_pcie->shared_vec_mask & IWL_SHARED_IRQ_NON_RX) &&
|
||||
inta_fh & MSIX_FH_INT_CAUSES_Q0) {
|
||||
|
@ -2151,11 +2162,18 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id)
|
|||
}
|
||||
|
||||
/* After checking FH register check HW register */
|
||||
if (iwl_have_debug_level(IWL_DL_ISR))
|
||||
if (iwl_have_debug_level(IWL_DL_ISR)) {
|
||||
IWL_DEBUG_ISR(trans,
|
||||
"ISR inta_hw 0x%08x, enabled 0x%08x\n",
|
||||
inta_hw,
|
||||
"ISR inta_hw 0x%08x, enabled (sw) 0x%08x (hw) 0x%08x\n",
|
||||
inta_hw, trans_pcie->hw_mask,
|
||||
iwl_read32(trans, CSR_MSIX_HW_INT_MASK_AD));
|
||||
if (inta_hw & ~trans_pcie->hw_mask)
|
||||
IWL_DEBUG_ISR(trans,
|
||||
"We got a masked interrupt 0x%08x\n",
|
||||
inta_hw & ~trans_pcie->hw_mask);
|
||||
}
|
||||
|
||||
inta_hw &= trans_pcie->hw_mask;
|
||||
|
||||
/* Alive notification via Rx interrupt will do the real work */
|
||||
if (inta_hw & MSIX_HW_INT_CAUSES_REG_ALIVE) {
|
||||
|
@ -2212,7 +2230,7 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id)
|
|||
"Hardware error detected. Restarting.\n");
|
||||
|
||||
isr_stats->hw++;
|
||||
trans->hw_error = true;
|
||||
trans->dbg.hw_error = true;
|
||||
iwl_pcie_irq_handle_error(trans);
|
||||
}
|
||||
|
||||
|
|
|
@ -148,7 +148,7 @@ void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans, bool low_power)
|
|||
trans_pcie->is_down = true;
|
||||
|
||||
/* Stop dbgc before stopping device */
|
||||
_iwl_fw_dbg_stop_recording(trans, NULL);
|
||||
iwl_fw_dbg_stop_recording(trans, NULL);
|
||||
|
||||
/* tell the device to stop sending interrupts */
|
||||
iwl_disable_interrupts(trans);
|
||||
|
@ -273,6 +273,15 @@ void iwl_trans_pcie_gen2_fw_alive(struct iwl_trans *trans, u32 scd_addr)
|
|||
* paging memory cannot be freed included since FW will still use it
|
||||
*/
|
||||
iwl_pcie_ctxt_info_free(trans);
|
||||
|
||||
/*
|
||||
* Re-enable all the interrupts, including the RF-Kill one, now that
|
||||
* the firmware is alive.
|
||||
*/
|
||||
iwl_enable_interrupts(trans);
|
||||
mutex_lock(&trans_pcie->mutex);
|
||||
iwl_pcie_check_hw_rf_kill(trans);
|
||||
mutex_unlock(&trans_pcie->mutex);
|
||||
}
|
||||
|
||||
int iwl_trans_pcie_gen2_start_fw(struct iwl_trans *trans,
|
||||
|
|
|
@ -90,8 +90,10 @@
|
|||
|
||||
void iwl_trans_pcie_dump_regs(struct iwl_trans *trans)
|
||||
{
|
||||
#define PCI_DUMP_SIZE 64
|
||||
#define PREFIX_LEN 32
|
||||
#define PCI_DUMP_SIZE 352
|
||||
#define PCI_MEM_DUMP_SIZE 64
|
||||
#define PCI_PARENT_DUMP_SIZE 524
|
||||
#define PREFIX_LEN 32
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
struct pci_dev *pdev = trans_pcie->pci_dev;
|
||||
u32 i, pos, alloc_size, *ptr, *buf;
|
||||
|
@ -102,11 +104,15 @@ void iwl_trans_pcie_dump_regs(struct iwl_trans *trans)
|
|||
|
||||
/* Should be a multiple of 4 */
|
||||
BUILD_BUG_ON(PCI_DUMP_SIZE > 4096 || PCI_DUMP_SIZE & 0x3);
|
||||
BUILD_BUG_ON(PCI_MEM_DUMP_SIZE > 4096 || PCI_MEM_DUMP_SIZE & 0x3);
|
||||
BUILD_BUG_ON(PCI_PARENT_DUMP_SIZE > 4096 || PCI_PARENT_DUMP_SIZE & 0x3);
|
||||
|
||||
/* Alloc a max size buffer */
|
||||
if (PCI_ERR_ROOT_ERR_SRC + 4 > PCI_DUMP_SIZE)
|
||||
alloc_size = PCI_ERR_ROOT_ERR_SRC + 4 + PREFIX_LEN;
|
||||
else
|
||||
alloc_size = PCI_DUMP_SIZE + PREFIX_LEN;
|
||||
alloc_size = PCI_ERR_ROOT_ERR_SRC + 4 + PREFIX_LEN;
|
||||
alloc_size = max_t(u32, alloc_size, PCI_DUMP_SIZE + PREFIX_LEN);
|
||||
alloc_size = max_t(u32, alloc_size, PCI_MEM_DUMP_SIZE + PREFIX_LEN);
|
||||
alloc_size = max_t(u32, alloc_size, PCI_PARENT_DUMP_SIZE + PREFIX_LEN);
|
||||
|
||||
buf = kmalloc(alloc_size, GFP_ATOMIC);
|
||||
if (!buf)
|
||||
return;
|
||||
|
@ -123,7 +129,7 @@ void iwl_trans_pcie_dump_regs(struct iwl_trans *trans)
|
|||
print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32, 4, buf, i, 0);
|
||||
|
||||
IWL_ERR(trans, "iwlwifi device memory mapped registers:\n");
|
||||
for (i = 0, ptr = buf; i < PCI_DUMP_SIZE; i += 4, ptr++)
|
||||
for (i = 0, ptr = buf; i < PCI_MEM_DUMP_SIZE; i += 4, ptr++)
|
||||
*ptr = iwl_read32(trans, i);
|
||||
print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32, 4, buf, i, 0);
|
||||
|
||||
|
@ -146,7 +152,7 @@ void iwl_trans_pcie_dump_regs(struct iwl_trans *trans)
|
|||
|
||||
IWL_ERR(trans, "iwlwifi parent port (%s) config registers:\n",
|
||||
pci_name(pdev));
|
||||
for (i = 0, ptr = buf; i < PCI_DUMP_SIZE; i += 4, ptr++)
|
||||
for (i = 0, ptr = buf; i < PCI_PARENT_DUMP_SIZE; i += 4, ptr++)
|
||||
if (pci_read_config_dword(pdev, i, ptr))
|
||||
goto err_read;
|
||||
print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32, 4, buf, i, 0);
|
||||
|
@ -188,14 +194,14 @@ static void iwl_pcie_free_fw_monitor(struct iwl_trans *trans)
|
|||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < trans->num_blocks; i++) {
|
||||
dma_free_coherent(trans->dev, trans->fw_mon[i].size,
|
||||
trans->fw_mon[i].block,
|
||||
trans->fw_mon[i].physical);
|
||||
trans->fw_mon[i].block = NULL;
|
||||
trans->fw_mon[i].physical = 0;
|
||||
trans->fw_mon[i].size = 0;
|
||||
trans->num_blocks--;
|
||||
for (i = 0; i < trans->dbg.num_blocks; i++) {
|
||||
dma_free_coherent(trans->dev, trans->dbg.fw_mon[i].size,
|
||||
trans->dbg.fw_mon[i].block,
|
||||
trans->dbg.fw_mon[i].physical);
|
||||
trans->dbg.fw_mon[i].block = NULL;
|
||||
trans->dbg.fw_mon[i].physical = 0;
|
||||
trans->dbg.fw_mon[i].size = 0;
|
||||
trans->dbg.num_blocks--;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -230,10 +236,10 @@ static void iwl_pcie_alloc_fw_monitor_block(struct iwl_trans *trans,
|
|||
(unsigned long)BIT(power - 10),
|
||||
(unsigned long)BIT(max_power - 10));
|
||||
|
||||
trans->fw_mon[trans->num_blocks].block = cpu_addr;
|
||||
trans->fw_mon[trans->num_blocks].physical = phys;
|
||||
trans->fw_mon[trans->num_blocks].size = size;
|
||||
trans->num_blocks++;
|
||||
trans->dbg.fw_mon[trans->dbg.num_blocks].block = cpu_addr;
|
||||
trans->dbg.fw_mon[trans->dbg.num_blocks].physical = phys;
|
||||
trans->dbg.fw_mon[trans->dbg.num_blocks].size = size;
|
||||
trans->dbg.num_blocks++;
|
||||
}
|
||||
|
||||
void iwl_pcie_alloc_fw_monitor(struct iwl_trans *trans, u8 max_power)
|
||||
|
@ -254,7 +260,7 @@ void iwl_pcie_alloc_fw_monitor(struct iwl_trans *trans, u8 max_power)
|
|||
* This function allocats the default fw monitor.
|
||||
* The optional additional ones will be allocated in runtime
|
||||
*/
|
||||
if (trans->num_blocks)
|
||||
if (trans->dbg.num_blocks)
|
||||
return;
|
||||
|
||||
iwl_pcie_alloc_fw_monitor_block(trans, max_power, 11);
|
||||
|
@ -889,21 +895,21 @@ static int iwl_pcie_load_cpu_sections(struct iwl_trans *trans,
|
|||
|
||||
void iwl_pcie_apply_destination(struct iwl_trans *trans)
|
||||
{
|
||||
const struct iwl_fw_dbg_dest_tlv_v1 *dest = trans->dbg_dest_tlv;
|
||||
const struct iwl_fw_dbg_dest_tlv_v1 *dest = trans->dbg.dest_tlv;
|
||||
int i;
|
||||
|
||||
if (trans->ini_valid) {
|
||||
if (!trans->num_blocks)
|
||||
if (trans->dbg.ini_valid) {
|
||||
if (!trans->dbg.num_blocks)
|
||||
return;
|
||||
|
||||
IWL_DEBUG_FW(trans,
|
||||
"WRT: applying DRAM buffer[0] destination\n");
|
||||
iwl_write_umac_prph(trans, MON_BUFF_BASE_ADDR_VER2,
|
||||
trans->fw_mon[0].physical >>
|
||||
trans->dbg.fw_mon[0].physical >>
|
||||
MON_BUFF_SHIFT_VER2);
|
||||
iwl_write_umac_prph(trans, MON_BUFF_END_ADDR_VER2,
|
||||
(trans->fw_mon[0].physical +
|
||||
trans->fw_mon[0].size - 256) >>
|
||||
(trans->dbg.fw_mon[0].physical +
|
||||
trans->dbg.fw_mon[0].size - 256) >>
|
||||
MON_BUFF_SHIFT_VER2);
|
||||
return;
|
||||
}
|
||||
|
@ -916,7 +922,7 @@ void iwl_pcie_apply_destination(struct iwl_trans *trans)
|
|||
else
|
||||
IWL_WARN(trans, "PCI should have external buffer debug\n");
|
||||
|
||||
for (i = 0; i < trans->dbg_n_dest_reg; i++) {
|
||||
for (i = 0; i < trans->dbg.n_dest_reg; i++) {
|
||||
u32 addr = le32_to_cpu(dest->reg_ops[i].addr);
|
||||
u32 val = le32_to_cpu(dest->reg_ops[i].val);
|
||||
|
||||
|
@ -955,18 +961,19 @@ void iwl_pcie_apply_destination(struct iwl_trans *trans)
|
|||
}
|
||||
|
||||
monitor:
|
||||
if (dest->monitor_mode == EXTERNAL_MODE && trans->fw_mon[0].size) {
|
||||
if (dest->monitor_mode == EXTERNAL_MODE && trans->dbg.fw_mon[0].size) {
|
||||
iwl_write_prph(trans, le32_to_cpu(dest->base_reg),
|
||||
trans->fw_mon[0].physical >> dest->base_shift);
|
||||
trans->dbg.fw_mon[0].physical >>
|
||||
dest->base_shift);
|
||||
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_8000)
|
||||
iwl_write_prph(trans, le32_to_cpu(dest->end_reg),
|
||||
(trans->fw_mon[0].physical +
|
||||
trans->fw_mon[0].size - 256) >>
|
||||
(trans->dbg.fw_mon[0].physical +
|
||||
trans->dbg.fw_mon[0].size - 256) >>
|
||||
dest->end_shift);
|
||||
else
|
||||
iwl_write_prph(trans, le32_to_cpu(dest->end_reg),
|
||||
(trans->fw_mon[0].physical +
|
||||
trans->fw_mon[0].size) >>
|
||||
(trans->dbg.fw_mon[0].physical +
|
||||
trans->dbg.fw_mon[0].size) >>
|
||||
dest->end_shift);
|
||||
}
|
||||
}
|
||||
|
@ -1003,12 +1010,12 @@ static int iwl_pcie_load_given_ucode(struct iwl_trans *trans,
|
|||
trans->cfg->device_family == IWL_DEVICE_FAMILY_7000) {
|
||||
iwl_pcie_alloc_fw_monitor(trans, 0);
|
||||
|
||||
if (trans->fw_mon[0].size) {
|
||||
if (trans->dbg.fw_mon[0].size) {
|
||||
iwl_write_prph(trans, MON_BUFF_BASE_ADDR,
|
||||
trans->fw_mon[0].physical >> 4);
|
||||
trans->dbg.fw_mon[0].physical >> 4);
|
||||
iwl_write_prph(trans, MON_BUFF_END_ADDR,
|
||||
(trans->fw_mon[0].physical +
|
||||
trans->fw_mon[0].size) >> 4);
|
||||
(trans->dbg.fw_mon[0].physical +
|
||||
trans->dbg.fw_mon[0].size) >> 4);
|
||||
}
|
||||
} else if (iwl_pcie_dbg_on(trans)) {
|
||||
iwl_pcie_apply_destination(trans);
|
||||
|
@ -1236,7 +1243,7 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power)
|
|||
trans_pcie->is_down = true;
|
||||
|
||||
/* Stop dbgc before stopping device */
|
||||
_iwl_fw_dbg_stop_recording(trans, NULL);
|
||||
iwl_fw_dbg_stop_recording(trans, NULL);
|
||||
|
||||
/* tell the device to stop sending interrupts */
|
||||
iwl_disable_interrupts(trans);
|
||||
|
@ -2729,8 +2736,8 @@ static int iwl_dbgfs_monitor_data_open(struct inode *inode,
|
|||
struct iwl_trans *trans = inode->i_private;
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
|
||||
if (!trans->dbg_dest_tlv ||
|
||||
trans->dbg_dest_tlv->monitor_mode != EXTERNAL_MODE) {
|
||||
if (!trans->dbg.dest_tlv ||
|
||||
trans->dbg.dest_tlv->monitor_mode != EXTERNAL_MODE) {
|
||||
IWL_ERR(trans, "Debug destination is not set to DRAM\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
@ -2777,22 +2784,22 @@ static ssize_t iwl_dbgfs_monitor_data_read(struct file *file,
|
|||
{
|
||||
struct iwl_trans *trans = file->private_data;
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
void *cpu_addr = (void *)trans->fw_mon[0].block, *curr_buf;
|
||||
void *cpu_addr = (void *)trans->dbg.fw_mon[0].block, *curr_buf;
|
||||
struct cont_rec *data = &trans_pcie->fw_mon_data;
|
||||
u32 write_ptr_addr, wrap_cnt_addr, write_ptr, wrap_cnt;
|
||||
ssize_t size, bytes_copied = 0;
|
||||
bool b_full;
|
||||
|
||||
if (trans->dbg_dest_tlv) {
|
||||
if (trans->dbg.dest_tlv) {
|
||||
write_ptr_addr =
|
||||
le32_to_cpu(trans->dbg_dest_tlv->write_ptr_reg);
|
||||
wrap_cnt_addr = le32_to_cpu(trans->dbg_dest_tlv->wrap_count);
|
||||
le32_to_cpu(trans->dbg.dest_tlv->write_ptr_reg);
|
||||
wrap_cnt_addr = le32_to_cpu(trans->dbg.dest_tlv->wrap_count);
|
||||
} else {
|
||||
write_ptr_addr = MON_BUFF_WRPTR;
|
||||
wrap_cnt_addr = MON_BUFF_CYCLE_CNT;
|
||||
}
|
||||
|
||||
if (unlikely(!trans->dbg_rec_on))
|
||||
if (unlikely(!trans->dbg.rec_on))
|
||||
return 0;
|
||||
|
||||
mutex_lock(&data->mutex);
|
||||
|
@ -2816,7 +2823,7 @@ static ssize_t iwl_dbgfs_monitor_data_read(struct file *file,
|
|||
|
||||
} else if (data->prev_wrap_cnt == wrap_cnt - 1 &&
|
||||
write_ptr < data->prev_wr_ptr) {
|
||||
size = trans->fw_mon[0].size - data->prev_wr_ptr;
|
||||
size = trans->dbg.fw_mon[0].size - data->prev_wr_ptr;
|
||||
curr_buf = cpu_addr + data->prev_wr_ptr;
|
||||
b_full = iwl_write_to_user_buf(user_buf, count,
|
||||
curr_buf, &size,
|
||||
|
@ -3035,14 +3042,10 @@ iwl_trans_pcie_dump_pointers(struct iwl_trans *trans,
|
|||
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);
|
||||
write_ptr = iwl_umac_prph(trans, MON_BUFF_WRPTR_VER2);
|
||||
wrap_cnt = iwl_umac_prph(trans, MON_BUFF_CYCLE_CNT_VER2);
|
||||
} else if (trans->dbg_dest_tlv) {
|
||||
write_ptr = le32_to_cpu(trans->dbg_dest_tlv->write_ptr_reg);
|
||||
wrap_cnt = le32_to_cpu(trans->dbg_dest_tlv->wrap_count);
|
||||
base = le32_to_cpu(trans->dbg_dest_tlv->base_reg);
|
||||
} else if (trans->dbg.dest_tlv) {
|
||||
write_ptr = le32_to_cpu(trans->dbg.dest_tlv->write_ptr_reg);
|
||||
wrap_cnt = le32_to_cpu(trans->dbg.dest_tlv->wrap_count);
|
||||
base = le32_to_cpu(trans->dbg.dest_tlv->base_reg);
|
||||
} else {
|
||||
base = MON_BUFF_BASE_ADDR;
|
||||
write_ptr = MON_BUFF_WRPTR;
|
||||
|
@ -3069,11 +3072,10 @@ iwl_trans_pcie_dump_monitor(struct iwl_trans *trans,
|
|||
{
|
||||
u32 len = 0;
|
||||
|
||||
if ((trans->num_blocks &&
|
||||
if (trans->dbg.dest_tlv ||
|
||||
(trans->dbg.num_blocks &&
|
||||
(trans->cfg->device_family == IWL_DEVICE_FAMILY_7000 ||
|
||||
trans->cfg->device_family >= IWL_DEVICE_FAMILY_AX210 ||
|
||||
trans->ini_valid)) ||
|
||||
(trans->dbg_dest_tlv && !trans->ini_valid)) {
|
||||
trans->cfg->device_family >= IWL_DEVICE_FAMILY_AX210))) {
|
||||
struct iwl_fw_error_dump_fw_mon *fw_mon_data;
|
||||
|
||||
(*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_FW_MONITOR);
|
||||
|
@ -3082,32 +3084,32 @@ iwl_trans_pcie_dump_monitor(struct iwl_trans *trans,
|
|||
iwl_trans_pcie_dump_pointers(trans, fw_mon_data);
|
||||
|
||||
len += sizeof(**data) + sizeof(*fw_mon_data);
|
||||
if (trans->num_blocks) {
|
||||
if (trans->dbg.num_blocks) {
|
||||
memcpy(fw_mon_data->data,
|
||||
trans->fw_mon[0].block,
|
||||
trans->fw_mon[0].size);
|
||||
trans->dbg.fw_mon[0].block,
|
||||
trans->dbg.fw_mon[0].size);
|
||||
|
||||
monitor_len = trans->fw_mon[0].size;
|
||||
} else if (trans->dbg_dest_tlv->monitor_mode == SMEM_MODE) {
|
||||
monitor_len = trans->dbg.fw_mon[0].size;
|
||||
} else if (trans->dbg.dest_tlv->monitor_mode == SMEM_MODE) {
|
||||
u32 base = le32_to_cpu(fw_mon_data->fw_mon_base_ptr);
|
||||
/*
|
||||
* Update pointers to reflect actual values after
|
||||
* shifting
|
||||
*/
|
||||
if (trans->dbg_dest_tlv->version) {
|
||||
if (trans->dbg.dest_tlv->version) {
|
||||
base = (iwl_read_prph(trans, base) &
|
||||
IWL_LDBG_M2S_BUF_BA_MSK) <<
|
||||
trans->dbg_dest_tlv->base_shift;
|
||||
trans->dbg.dest_tlv->base_shift;
|
||||
base *= IWL_M2S_UNIT_SIZE;
|
||||
base += trans->cfg->smem_offset;
|
||||
} else {
|
||||
base = iwl_read_prph(trans, base) <<
|
||||
trans->dbg_dest_tlv->base_shift;
|
||||
trans->dbg.dest_tlv->base_shift;
|
||||
}
|
||||
|
||||
iwl_trans_read_mem(trans, base, fw_mon_data->data,
|
||||
monitor_len / sizeof(u32));
|
||||
} else if (trans->dbg_dest_tlv->monitor_mode == MARBH_MODE) {
|
||||
} else if (trans->dbg.dest_tlv->monitor_mode == MARBH_MODE) {
|
||||
monitor_len =
|
||||
iwl_trans_pci_dump_marbh_monitor(trans,
|
||||
fw_mon_data,
|
||||
|
@ -3126,40 +3128,40 @@ iwl_trans_pcie_dump_monitor(struct iwl_trans *trans,
|
|||
|
||||
static int iwl_trans_get_fw_monitor_len(struct iwl_trans *trans, u32 *len)
|
||||
{
|
||||
if (trans->num_blocks) {
|
||||
if (trans->dbg.num_blocks) {
|
||||
*len += sizeof(struct iwl_fw_error_dump_data) +
|
||||
sizeof(struct iwl_fw_error_dump_fw_mon) +
|
||||
trans->fw_mon[0].size;
|
||||
return trans->fw_mon[0].size;
|
||||
} else if (trans->dbg_dest_tlv) {
|
||||
trans->dbg.fw_mon[0].size;
|
||||
return trans->dbg.fw_mon[0].size;
|
||||
} else if (trans->dbg.dest_tlv) {
|
||||
u32 base, end, cfg_reg, monitor_len;
|
||||
|
||||
if (trans->dbg_dest_tlv->version == 1) {
|
||||
cfg_reg = le32_to_cpu(trans->dbg_dest_tlv->base_reg);
|
||||
if (trans->dbg.dest_tlv->version == 1) {
|
||||
cfg_reg = le32_to_cpu(trans->dbg.dest_tlv->base_reg);
|
||||
cfg_reg = iwl_read_prph(trans, cfg_reg);
|
||||
base = (cfg_reg & IWL_LDBG_M2S_BUF_BA_MSK) <<
|
||||
trans->dbg_dest_tlv->base_shift;
|
||||
trans->dbg.dest_tlv->base_shift;
|
||||
base *= IWL_M2S_UNIT_SIZE;
|
||||
base += trans->cfg->smem_offset;
|
||||
|
||||
monitor_len =
|
||||
(cfg_reg & IWL_LDBG_M2S_BUF_SIZE_MSK) >>
|
||||
trans->dbg_dest_tlv->end_shift;
|
||||
trans->dbg.dest_tlv->end_shift;
|
||||
monitor_len *= IWL_M2S_UNIT_SIZE;
|
||||
} else {
|
||||
base = le32_to_cpu(trans->dbg_dest_tlv->base_reg);
|
||||
end = le32_to_cpu(trans->dbg_dest_tlv->end_reg);
|
||||
base = le32_to_cpu(trans->dbg.dest_tlv->base_reg);
|
||||
end = le32_to_cpu(trans->dbg.dest_tlv->end_reg);
|
||||
|
||||
base = iwl_read_prph(trans, base) <<
|
||||
trans->dbg_dest_tlv->base_shift;
|
||||
trans->dbg.dest_tlv->base_shift;
|
||||
end = iwl_read_prph(trans, end) <<
|
||||
trans->dbg_dest_tlv->end_shift;
|
||||
trans->dbg.dest_tlv->end_shift;
|
||||
|
||||
/* Make "end" point to the actual end */
|
||||
if (trans->cfg->device_family >=
|
||||
IWL_DEVICE_FAMILY_8000 ||
|
||||
trans->dbg_dest_tlv->monitor_mode == MARBH_MODE)
|
||||
end += (1 << trans->dbg_dest_tlv->end_shift);
|
||||
trans->dbg.dest_tlv->monitor_mode == MARBH_MODE)
|
||||
end += (1 << trans->dbg.dest_tlv->end_shift);
|
||||
monitor_len = end - base;
|
||||
}
|
||||
*len += sizeof(struct iwl_fw_error_dump_data) +
|
||||
|
@ -3192,7 +3194,7 @@ static struct iwl_trans_dump_data
|
|||
len = sizeof(*dump_data);
|
||||
|
||||
/* host commands */
|
||||
if (dump_mask & BIT(IWL_FW_ERROR_DUMP_TXCMD))
|
||||
if (dump_mask & BIT(IWL_FW_ERROR_DUMP_TXCMD) && cmdq)
|
||||
len += sizeof(*data) +
|
||||
cmdq->n_window * (sizeof(*txcmd) +
|
||||
TFD_MAX_PAYLOAD_SIZE);
|
||||
|
@ -3244,7 +3246,7 @@ static struct iwl_trans_dump_data
|
|||
len = 0;
|
||||
data = (void *)dump_data->data;
|
||||
|
||||
if (dump_mask & BIT(IWL_FW_ERROR_DUMP_TXCMD)) {
|
||||
if (dump_mask & BIT(IWL_FW_ERROR_DUMP_TXCMD) && cmdq) {
|
||||
u16 tfd_size = trans_pcie->tfd_size;
|
||||
|
||||
data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_TXCMD);
|
||||
|
@ -3681,6 +3683,7 @@ void iwl_trans_pcie_sync_nmi(struct iwl_trans *trans)
|
|||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
unsigned long timeout = jiffies + IWL_TRANS_NMI_TIMEOUT;
|
||||
bool interrupts_enabled = test_bit(STATUS_INT_ENABLED, &trans->status);
|
||||
u32 inta_addr, sw_err_bit;
|
||||
|
||||
if (trans_pcie->msix_enabled) {
|
||||
|
@ -3691,7 +3694,12 @@ void iwl_trans_pcie_sync_nmi(struct iwl_trans *trans)
|
|||
sw_err_bit = CSR_INT_BIT_SW_ERR;
|
||||
}
|
||||
|
||||
iwl_disable_interrupts(trans);
|
||||
/* if the interrupts were already disabled, there is no point in
|
||||
* calling iwl_disable_interrupts
|
||||
*/
|
||||
if (interrupts_enabled)
|
||||
iwl_disable_interrupts(trans);
|
||||
|
||||
iwl_force_nmi(trans);
|
||||
while (time_after(timeout, jiffies)) {
|
||||
u32 inta_hw = iwl_read32(trans, inta_addr);
|
||||
|
@ -3705,6 +3713,13 @@ void iwl_trans_pcie_sync_nmi(struct iwl_trans *trans)
|
|||
|
||||
mdelay(1);
|
||||
}
|
||||
iwl_enable_interrupts(trans);
|
||||
|
||||
/* enable interrupts only if there were already enabled before this
|
||||
* function to avoid a case were the driver enable interrupts before
|
||||
* proper configurations were made
|
||||
*/
|
||||
if (interrupts_enabled)
|
||||
iwl_enable_interrupts(trans);
|
||||
|
||||
iwl_trans_fw_error(trans);
|
||||
}
|
||||
|
|
|
@ -84,17 +84,15 @@ mwifiex_get_ba_status(struct mwifiex_private *priv,
|
|||
enum mwifiex_ba_status ba_status)
|
||||
{
|
||||
struct mwifiex_tx_ba_stream_tbl *tx_ba_tsr_tbl;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags);
|
||||
spin_lock_bh(&priv->tx_ba_stream_tbl_lock);
|
||||
list_for_each_entry(tx_ba_tsr_tbl, &priv->tx_ba_stream_tbl_ptr, list) {
|
||||
if (tx_ba_tsr_tbl->ba_status == ba_status) {
|
||||
spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock,
|
||||
flags);
|
||||
spin_unlock_bh(&priv->tx_ba_stream_tbl_lock);
|
||||
return tx_ba_tsr_tbl;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags);
|
||||
spin_unlock_bh(&priv->tx_ba_stream_tbl_lock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -516,13 +514,12 @@ void mwifiex_11n_delete_all_tx_ba_stream_tbl(struct mwifiex_private *priv)
|
|||
{
|
||||
int i;
|
||||
struct mwifiex_tx_ba_stream_tbl *del_tbl_ptr, *tmp_node;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags);
|
||||
spin_lock_bh(&priv->tx_ba_stream_tbl_lock);
|
||||
list_for_each_entry_safe(del_tbl_ptr, tmp_node,
|
||||
&priv->tx_ba_stream_tbl_ptr, list)
|
||||
mwifiex_11n_delete_tx_ba_stream_tbl_entry(priv, del_tbl_ptr);
|
||||
spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags);
|
||||
spin_unlock_bh(&priv->tx_ba_stream_tbl_lock);
|
||||
|
||||
INIT_LIST_HEAD(&priv->tx_ba_stream_tbl_ptr);
|
||||
|
||||
|
@ -539,18 +536,16 @@ struct mwifiex_tx_ba_stream_tbl *
|
|||
mwifiex_get_ba_tbl(struct mwifiex_private *priv, int tid, u8 *ra)
|
||||
{
|
||||
struct mwifiex_tx_ba_stream_tbl *tx_ba_tsr_tbl;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags);
|
||||
spin_lock_bh(&priv->tx_ba_stream_tbl_lock);
|
||||
list_for_each_entry(tx_ba_tsr_tbl, &priv->tx_ba_stream_tbl_ptr, list) {
|
||||
if (ether_addr_equal_unaligned(tx_ba_tsr_tbl->ra, ra) &&
|
||||
tx_ba_tsr_tbl->tid == tid) {
|
||||
spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock,
|
||||
flags);
|
||||
spin_unlock_bh(&priv->tx_ba_stream_tbl_lock);
|
||||
return tx_ba_tsr_tbl;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags);
|
||||
spin_unlock_bh(&priv->tx_ba_stream_tbl_lock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -563,7 +558,6 @@ void mwifiex_create_ba_tbl(struct mwifiex_private *priv, u8 *ra, int tid,
|
|||
{
|
||||
struct mwifiex_tx_ba_stream_tbl *new_node;
|
||||
struct mwifiex_ra_list_tbl *ra_list;
|
||||
unsigned long flags;
|
||||
int tid_down;
|
||||
|
||||
if (!mwifiex_get_ba_tbl(priv, tid, ra)) {
|
||||
|
@ -584,9 +578,9 @@ void mwifiex_create_ba_tbl(struct mwifiex_private *priv, u8 *ra, int tid,
|
|||
new_node->ba_status = ba_status;
|
||||
memcpy(new_node->ra, ra, ETH_ALEN);
|
||||
|
||||
spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags);
|
||||
spin_lock_bh(&priv->tx_ba_stream_tbl_lock);
|
||||
list_add_tail(&new_node->list, &priv->tx_ba_stream_tbl_ptr);
|
||||
spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags);
|
||||
spin_unlock_bh(&priv->tx_ba_stream_tbl_lock);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -599,7 +593,6 @@ int mwifiex_send_addba(struct mwifiex_private *priv, int tid, u8 *peer_mac)
|
|||
u32 tx_win_size = priv->add_ba_param.tx_win_size;
|
||||
static u8 dialog_tok;
|
||||
int ret;
|
||||
unsigned long flags;
|
||||
u16 block_ack_param_set;
|
||||
|
||||
mwifiex_dbg(priv->adapter, CMD, "cmd: %s: tid %d\n", __func__, tid);
|
||||
|
@ -612,10 +605,10 @@ int mwifiex_send_addba(struct mwifiex_private *priv, int tid, u8 *peer_mac)
|
|||
memcmp(priv->cfg_bssid, peer_mac, ETH_ALEN)) {
|
||||
struct mwifiex_sta_node *sta_ptr;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_list_spinlock, flags);
|
||||
spin_lock_bh(&priv->sta_list_spinlock);
|
||||
sta_ptr = mwifiex_get_sta_entry(priv, peer_mac);
|
||||
if (!sta_ptr) {
|
||||
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
|
||||
spin_unlock_bh(&priv->sta_list_spinlock);
|
||||
mwifiex_dbg(priv->adapter, ERROR,
|
||||
"BA setup with unknown TDLS peer %pM!\n",
|
||||
peer_mac);
|
||||
|
@ -623,7 +616,7 @@ int mwifiex_send_addba(struct mwifiex_private *priv, int tid, u8 *peer_mac)
|
|||
}
|
||||
if (sta_ptr->is_11ac_enabled)
|
||||
tx_win_size = MWIFIEX_11AC_STA_AMPDU_DEF_TXWINSIZE;
|
||||
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
|
||||
spin_unlock_bh(&priv->sta_list_spinlock);
|
||||
}
|
||||
|
||||
block_ack_param_set = (u16)((tid << BLOCKACKPARAM_TID_POS) |
|
||||
|
@ -687,9 +680,8 @@ int mwifiex_send_delba(struct mwifiex_private *priv, int tid, u8 *peer_mac,
|
|||
void mwifiex_11n_delba(struct mwifiex_private *priv, int tid)
|
||||
{
|
||||
struct mwifiex_rx_reorder_tbl *rx_reor_tbl_ptr;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
|
||||
spin_lock_bh(&priv->rx_reorder_tbl_lock);
|
||||
list_for_each_entry(rx_reor_tbl_ptr, &priv->rx_reorder_tbl_ptr, list) {
|
||||
if (rx_reor_tbl_ptr->tid == tid) {
|
||||
dev_dbg(priv->adapter->dev,
|
||||
|
@ -700,7 +692,7 @@ void mwifiex_11n_delba(struct mwifiex_private *priv, int tid)
|
|||
}
|
||||
}
|
||||
exit:
|
||||
spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
|
||||
spin_unlock_bh(&priv->rx_reorder_tbl_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -729,9 +721,8 @@ int mwifiex_get_rx_reorder_tbl(struct mwifiex_private *priv,
|
|||
struct mwifiex_ds_rx_reorder_tbl *rx_reo_tbl = buf;
|
||||
struct mwifiex_rx_reorder_tbl *rx_reorder_tbl_ptr;
|
||||
int count = 0;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
|
||||
spin_lock_bh(&priv->rx_reorder_tbl_lock);
|
||||
list_for_each_entry(rx_reorder_tbl_ptr, &priv->rx_reorder_tbl_ptr,
|
||||
list) {
|
||||
rx_reo_tbl->tid = (u16) rx_reorder_tbl_ptr->tid;
|
||||
|
@ -750,7 +741,7 @@ int mwifiex_get_rx_reorder_tbl(struct mwifiex_private *priv,
|
|||
if (count >= MWIFIEX_MAX_RX_BASTREAM_SUPPORTED)
|
||||
break;
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
|
||||
spin_unlock_bh(&priv->rx_reorder_tbl_lock);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
@ -764,9 +755,8 @@ int mwifiex_get_tx_ba_stream_tbl(struct mwifiex_private *priv,
|
|||
struct mwifiex_tx_ba_stream_tbl *tx_ba_tsr_tbl;
|
||||
struct mwifiex_ds_tx_ba_stream_tbl *rx_reo_tbl = buf;
|
||||
int count = 0;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags);
|
||||
spin_lock_bh(&priv->tx_ba_stream_tbl_lock);
|
||||
list_for_each_entry(tx_ba_tsr_tbl, &priv->tx_ba_stream_tbl_ptr, list) {
|
||||
rx_reo_tbl->tid = (u16) tx_ba_tsr_tbl->tid;
|
||||
mwifiex_dbg(priv->adapter, DATA, "data: %s tid=%d\n",
|
||||
|
@ -778,7 +768,7 @@ int mwifiex_get_tx_ba_stream_tbl(struct mwifiex_private *priv,
|
|||
if (count >= MWIFIEX_MAX_TX_BASTREAM_SUPPORTED)
|
||||
break;
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags);
|
||||
spin_unlock_bh(&priv->tx_ba_stream_tbl_lock);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
@ -790,16 +780,15 @@ int mwifiex_get_tx_ba_stream_tbl(struct mwifiex_private *priv,
|
|||
void mwifiex_del_tx_ba_stream_tbl_by_ra(struct mwifiex_private *priv, u8 *ra)
|
||||
{
|
||||
struct mwifiex_tx_ba_stream_tbl *tbl, *tmp;
|
||||
unsigned long flags;
|
||||
|
||||
if (!ra)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags);
|
||||
spin_lock_bh(&priv->tx_ba_stream_tbl_lock);
|
||||
list_for_each_entry_safe(tbl, tmp, &priv->tx_ba_stream_tbl_ptr, list)
|
||||
if (!memcmp(tbl->ra, ra, ETH_ALEN))
|
||||
mwifiex_11n_delete_tx_ba_stream_tbl_entry(priv, tbl);
|
||||
spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags);
|
||||
spin_unlock_bh(&priv->tx_ba_stream_tbl_lock);
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -147,11 +147,10 @@ mwifiex_find_stream_to_delete(struct mwifiex_private *priv, int ptr_tid,
|
|||
int tid;
|
||||
u8 ret = false;
|
||||
struct mwifiex_tx_ba_stream_tbl *tx_tbl;
|
||||
unsigned long flags;
|
||||
|
||||
tid = priv->aggr_prio_tbl[ptr_tid].ampdu_user;
|
||||
|
||||
spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags);
|
||||
spin_lock_bh(&priv->tx_ba_stream_tbl_lock);
|
||||
list_for_each_entry(tx_tbl, &priv->tx_ba_stream_tbl_ptr, list) {
|
||||
if (tid > priv->aggr_prio_tbl[tx_tbl->tid].ampdu_user) {
|
||||
tid = priv->aggr_prio_tbl[tx_tbl->tid].ampdu_user;
|
||||
|
@ -160,7 +159,7 @@ mwifiex_find_stream_to_delete(struct mwifiex_private *priv, int ptr_tid,
|
|||
ret = true;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags);
|
||||
spin_unlock_bh(&priv->tx_ba_stream_tbl_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -155,7 +155,7 @@ mwifiex_11n_form_amsdu_txpd(struct mwifiex_private *priv,
|
|||
int
|
||||
mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
|
||||
struct mwifiex_ra_list_tbl *pra_list,
|
||||
int ptrindex, unsigned long ra_list_flags)
|
||||
int ptrindex)
|
||||
__releases(&priv->wmm.ra_list_spinlock)
|
||||
{
|
||||
struct mwifiex_adapter *adapter = priv->adapter;
|
||||
|
@ -168,8 +168,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
|
|||
|
||||
skb_src = skb_peek(&pra_list->skb_head);
|
||||
if (!skb_src) {
|
||||
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
|
||||
ra_list_flags);
|
||||
spin_unlock_bh(&priv->wmm.ra_list_spinlock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -177,8 +176,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
|
|||
skb_aggr = mwifiex_alloc_dma_align_buf(adapter->tx_buf_size,
|
||||
GFP_ATOMIC);
|
||||
if (!skb_aggr) {
|
||||
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
|
||||
ra_list_flags);
|
||||
spin_unlock_bh(&priv->wmm.ra_list_spinlock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -208,17 +206,15 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
|
|||
pra_list->total_pkt_count--;
|
||||
atomic_dec(&priv->wmm.tx_pkts_queued);
|
||||
aggr_num++;
|
||||
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
|
||||
ra_list_flags);
|
||||
spin_unlock_bh(&priv->wmm.ra_list_spinlock);
|
||||
mwifiex_11n_form_amsdu_pkt(skb_aggr, skb_src, &pad);
|
||||
|
||||
mwifiex_write_data_complete(adapter, skb_src, 0, 0);
|
||||
|
||||
spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags);
|
||||
spin_lock_bh(&priv->wmm.ra_list_spinlock);
|
||||
|
||||
if (!mwifiex_is_ralist_valid(priv, pra_list, ptrindex)) {
|
||||
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
|
||||
ra_list_flags);
|
||||
spin_unlock_bh(&priv->wmm.ra_list_spinlock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -232,7 +228,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
|
|||
|
||||
} while (skb_src);
|
||||
|
||||
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags);
|
||||
spin_unlock_bh(&priv->wmm.ra_list_spinlock);
|
||||
|
||||
/* Last AMSDU packet does not need padding */
|
||||
skb_trim(skb_aggr, skb_aggr->len - pad);
|
||||
|
@ -265,10 +261,9 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
|
|||
}
|
||||
switch (ret) {
|
||||
case -EBUSY:
|
||||
spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags);
|
||||
spin_lock_bh(&priv->wmm.ra_list_spinlock);
|
||||
if (!mwifiex_is_ralist_valid(priv, pra_list, ptrindex)) {
|
||||
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
|
||||
ra_list_flags);
|
||||
spin_unlock_bh(&priv->wmm.ra_list_spinlock);
|
||||
mwifiex_write_data_complete(adapter, skb_aggr, 1, -1);
|
||||
return -1;
|
||||
}
|
||||
|
@ -286,8 +281,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
|
|||
atomic_inc(&priv->wmm.tx_pkts_queued);
|
||||
|
||||
tx_info_aggr->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT;
|
||||
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
|
||||
ra_list_flags);
|
||||
spin_unlock_bh(&priv->wmm.ra_list_spinlock);
|
||||
mwifiex_dbg(adapter, ERROR, "data: -EBUSY is returned\n");
|
||||
break;
|
||||
case -1:
|
||||
|
|
|
@ -27,7 +27,7 @@ int mwifiex_11n_deaggregate_pkt(struct mwifiex_private *priv,
|
|||
struct sk_buff *skb);
|
||||
int mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
|
||||
struct mwifiex_ra_list_tbl *ptr,
|
||||
int ptr_index, unsigned long flags)
|
||||
int ptr_index)
|
||||
__releases(&priv->wmm.ra_list_spinlock);
|
||||
|
||||
#endif /* !_MWIFIEX_11N_AGGR_H_ */
|
||||
|
|
|
@ -76,7 +76,8 @@ static int mwifiex_11n_dispatch_amsdu_pkt(struct mwifiex_private *priv,
|
|||
/* This function will process the rx packet and forward it to kernel/upper
|
||||
* layer.
|
||||
*/
|
||||
static int mwifiex_11n_dispatch_pkt(struct mwifiex_private *priv, void *payload)
|
||||
static int mwifiex_11n_dispatch_pkt(struct mwifiex_private *priv,
|
||||
struct sk_buff *payload)
|
||||
{
|
||||
|
||||
int ret;
|
||||
|
@ -109,27 +110,25 @@ mwifiex_11n_dispatch_pkt_until_start_win(struct mwifiex_private *priv,
|
|||
struct mwifiex_rx_reorder_tbl *tbl,
|
||||
int start_win)
|
||||
{
|
||||
struct sk_buff_head list;
|
||||
struct sk_buff *skb;
|
||||
int pkt_to_send, i;
|
||||
void *rx_tmp_ptr;
|
||||
unsigned long flags;
|
||||
|
||||
__skb_queue_head_init(&list);
|
||||
spin_lock_bh(&priv->rx_reorder_tbl_lock);
|
||||
|
||||
pkt_to_send = (start_win > tbl->start_win) ?
|
||||
min((start_win - tbl->start_win), tbl->win_size) :
|
||||
tbl->win_size;
|
||||
|
||||
for (i = 0; i < pkt_to_send; ++i) {
|
||||
spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
|
||||
rx_tmp_ptr = NULL;
|
||||
if (tbl->rx_reorder_ptr[i]) {
|
||||
rx_tmp_ptr = tbl->rx_reorder_ptr[i];
|
||||
skb = tbl->rx_reorder_ptr[i];
|
||||
__skb_queue_tail(&list, skb);
|
||||
tbl->rx_reorder_ptr[i] = NULL;
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
|
||||
if (rx_tmp_ptr)
|
||||
mwifiex_11n_dispatch_pkt(priv, rx_tmp_ptr);
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
|
||||
/*
|
||||
* We don't have a circular buffer, hence use rotation to simulate
|
||||
* circular buffer
|
||||
|
@ -140,7 +139,10 @@ mwifiex_11n_dispatch_pkt_until_start_win(struct mwifiex_private *priv,
|
|||
}
|
||||
|
||||
tbl->start_win = start_win;
|
||||
spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
|
||||
spin_unlock_bh(&priv->rx_reorder_tbl_lock);
|
||||
|
||||
while ((skb = __skb_dequeue(&list)))
|
||||
mwifiex_11n_dispatch_pkt(priv, skb);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -155,24 +157,21 @@ static void
|
|||
mwifiex_11n_scan_and_dispatch(struct mwifiex_private *priv,
|
||||
struct mwifiex_rx_reorder_tbl *tbl)
|
||||
{
|
||||
struct sk_buff_head list;
|
||||
struct sk_buff *skb;
|
||||
int i, j, xchg;
|
||||
void *rx_tmp_ptr;
|
||||
unsigned long flags;
|
||||
|
||||
__skb_queue_head_init(&list);
|
||||
spin_lock_bh(&priv->rx_reorder_tbl_lock);
|
||||
|
||||
for (i = 0; i < tbl->win_size; ++i) {
|
||||
spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
|
||||
if (!tbl->rx_reorder_ptr[i]) {
|
||||
spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock,
|
||||
flags);
|
||||
if (!tbl->rx_reorder_ptr[i])
|
||||
break;
|
||||
}
|
||||
rx_tmp_ptr = tbl->rx_reorder_ptr[i];
|
||||
skb = tbl->rx_reorder_ptr[i];
|
||||
__skb_queue_tail(&list, skb);
|
||||
tbl->rx_reorder_ptr[i] = NULL;
|
||||
spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
|
||||
mwifiex_11n_dispatch_pkt(priv, rx_tmp_ptr);
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
|
||||
/*
|
||||
* We don't have a circular buffer, hence use rotation to simulate
|
||||
* circular buffer
|
||||
|
@ -185,7 +184,11 @@ mwifiex_11n_scan_and_dispatch(struct mwifiex_private *priv,
|
|||
}
|
||||
}
|
||||
tbl->start_win = (tbl->start_win + i) & (MAX_TID_VALUE - 1);
|
||||
spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
|
||||
|
||||
spin_unlock_bh(&priv->rx_reorder_tbl_lock);
|
||||
|
||||
while ((skb = __skb_dequeue(&list)))
|
||||
mwifiex_11n_dispatch_pkt(priv, skb);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -198,19 +201,18 @@ static void
|
|||
mwifiex_del_rx_reorder_entry(struct mwifiex_private *priv,
|
||||
struct mwifiex_rx_reorder_tbl *tbl)
|
||||
{
|
||||
unsigned long flags;
|
||||
int start_win;
|
||||
|
||||
if (!tbl)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&priv->adapter->rx_proc_lock, flags);
|
||||
spin_lock_bh(&priv->adapter->rx_proc_lock);
|
||||
priv->adapter->rx_locked = true;
|
||||
if (priv->adapter->rx_processing) {
|
||||
spin_unlock_irqrestore(&priv->adapter->rx_proc_lock, flags);
|
||||
spin_unlock_bh(&priv->adapter->rx_proc_lock);
|
||||
flush_workqueue(priv->adapter->rx_workqueue);
|
||||
} else {
|
||||
spin_unlock_irqrestore(&priv->adapter->rx_proc_lock, flags);
|
||||
spin_unlock_bh(&priv->adapter->rx_proc_lock);
|
||||
}
|
||||
|
||||
start_win = (tbl->start_win + tbl->win_size) & (MAX_TID_VALUE - 1);
|
||||
|
@ -219,16 +221,16 @@ mwifiex_del_rx_reorder_entry(struct mwifiex_private *priv,
|
|||
del_timer_sync(&tbl->timer_context.timer);
|
||||
tbl->timer_context.timer_is_set = false;
|
||||
|
||||
spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
|
||||
spin_lock_bh(&priv->rx_reorder_tbl_lock);
|
||||
list_del(&tbl->list);
|
||||
spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
|
||||
spin_unlock_bh(&priv->rx_reorder_tbl_lock);
|
||||
|
||||
kfree(tbl->rx_reorder_ptr);
|
||||
kfree(tbl);
|
||||
|
||||
spin_lock_irqsave(&priv->adapter->rx_proc_lock, flags);
|
||||
spin_lock_bh(&priv->adapter->rx_proc_lock);
|
||||
priv->adapter->rx_locked = false;
|
||||
spin_unlock_irqrestore(&priv->adapter->rx_proc_lock, flags);
|
||||
spin_unlock_bh(&priv->adapter->rx_proc_lock);
|
||||
|
||||
}
|
||||
|
||||
|
@ -240,17 +242,15 @@ struct mwifiex_rx_reorder_tbl *
|
|||
mwifiex_11n_get_rx_reorder_tbl(struct mwifiex_private *priv, int tid, u8 *ta)
|
||||
{
|
||||
struct mwifiex_rx_reorder_tbl *tbl;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
|
||||
spin_lock_bh(&priv->rx_reorder_tbl_lock);
|
||||
list_for_each_entry(tbl, &priv->rx_reorder_tbl_ptr, list) {
|
||||
if (!memcmp(tbl->ta, ta, ETH_ALEN) && tbl->tid == tid) {
|
||||
spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock,
|
||||
flags);
|
||||
spin_unlock_bh(&priv->rx_reorder_tbl_lock);
|
||||
return tbl;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
|
||||
spin_unlock_bh(&priv->rx_reorder_tbl_lock);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -261,21 +261,19 @@ mwifiex_11n_get_rx_reorder_tbl(struct mwifiex_private *priv, int tid, u8 *ta)
|
|||
void mwifiex_11n_del_rx_reorder_tbl_by_ta(struct mwifiex_private *priv, u8 *ta)
|
||||
{
|
||||
struct mwifiex_rx_reorder_tbl *tbl, *tmp;
|
||||
unsigned long flags;
|
||||
|
||||
if (!ta)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
|
||||
spin_lock_bh(&priv->rx_reorder_tbl_lock);
|
||||
list_for_each_entry_safe(tbl, tmp, &priv->rx_reorder_tbl_ptr, list) {
|
||||
if (!memcmp(tbl->ta, ta, ETH_ALEN)) {
|
||||
spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock,
|
||||
flags);
|
||||
spin_unlock_bh(&priv->rx_reorder_tbl_lock);
|
||||
mwifiex_del_rx_reorder_entry(priv, tbl);
|
||||
spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
|
||||
spin_lock_bh(&priv->rx_reorder_tbl_lock);
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
|
||||
spin_unlock_bh(&priv->rx_reorder_tbl_lock);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -289,18 +287,16 @@ mwifiex_11n_find_last_seq_num(struct reorder_tmr_cnxt *ctx)
|
|||
{
|
||||
struct mwifiex_rx_reorder_tbl *rx_reorder_tbl_ptr = ctx->ptr;
|
||||
struct mwifiex_private *priv = ctx->priv;
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
|
||||
spin_lock_bh(&priv->rx_reorder_tbl_lock);
|
||||
for (i = rx_reorder_tbl_ptr->win_size - 1; i >= 0; --i) {
|
||||
if (rx_reorder_tbl_ptr->rx_reorder_ptr[i]) {
|
||||
spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock,
|
||||
flags);
|
||||
spin_unlock_bh(&priv->rx_reorder_tbl_lock);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
|
||||
spin_unlock_bh(&priv->rx_reorder_tbl_lock);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
@ -348,7 +344,6 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta,
|
|||
int i;
|
||||
struct mwifiex_rx_reorder_tbl *tbl, *new_node;
|
||||
u16 last_seq = 0;
|
||||
unsigned long flags;
|
||||
struct mwifiex_sta_node *node;
|
||||
|
||||
/*
|
||||
|
@ -372,7 +367,7 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta,
|
|||
new_node->init_win = seq_num;
|
||||
new_node->flags = 0;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_list_spinlock, flags);
|
||||
spin_lock_bh(&priv->sta_list_spinlock);
|
||||
if (mwifiex_queuing_ra_based(priv)) {
|
||||
if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) {
|
||||
node = mwifiex_get_sta_entry(priv, ta);
|
||||
|
@ -386,7 +381,7 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta,
|
|||
else
|
||||
last_seq = priv->rx_seq[tid];
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
|
||||
spin_unlock_bh(&priv->sta_list_spinlock);
|
||||
|
||||
mwifiex_dbg(priv->adapter, INFO,
|
||||
"info: last_seq=%d start_win=%d\n",
|
||||
|
@ -418,9 +413,9 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta,
|
|||
for (i = 0; i < win_size; ++i)
|
||||
new_node->rx_reorder_ptr[i] = NULL;
|
||||
|
||||
spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
|
||||
spin_lock_bh(&priv->rx_reorder_tbl_lock);
|
||||
list_add_tail(&new_node->list, &priv->rx_reorder_tbl_ptr);
|
||||
spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
|
||||
spin_unlock_bh(&priv->rx_reorder_tbl_lock);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -476,18 +471,17 @@ int mwifiex_cmd_11n_addba_rsp_gen(struct mwifiex_private *priv,
|
|||
u32 rx_win_size = priv->add_ba_param.rx_win_size;
|
||||
u8 tid;
|
||||
int win_size;
|
||||
unsigned long flags;
|
||||
uint16_t block_ack_param_set;
|
||||
|
||||
if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
|
||||
ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
|
||||
priv->adapter->is_hw_11ac_capable &&
|
||||
memcmp(priv->cfg_bssid, cmd_addba_req->peer_mac_addr, ETH_ALEN)) {
|
||||
spin_lock_irqsave(&priv->sta_list_spinlock, flags);
|
||||
spin_lock_bh(&priv->sta_list_spinlock);
|
||||
sta_ptr = mwifiex_get_sta_entry(priv,
|
||||
cmd_addba_req->peer_mac_addr);
|
||||
if (!sta_ptr) {
|
||||
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
|
||||
spin_unlock_bh(&priv->sta_list_spinlock);
|
||||
mwifiex_dbg(priv->adapter, ERROR,
|
||||
"BA setup with unknown TDLS peer %pM!\n",
|
||||
cmd_addba_req->peer_mac_addr);
|
||||
|
@ -495,7 +489,7 @@ int mwifiex_cmd_11n_addba_rsp_gen(struct mwifiex_private *priv,
|
|||
}
|
||||
if (sta_ptr->is_11ac_enabled)
|
||||
rx_win_size = MWIFIEX_11AC_STA_AMPDU_DEF_RXWINSIZE;
|
||||
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
|
||||
spin_unlock_bh(&priv->sta_list_spinlock);
|
||||
}
|
||||
|
||||
cmd->command = cpu_to_le16(HostCmd_CMD_11N_ADDBA_RSP);
|
||||
|
@ -682,7 +676,6 @@ mwifiex_del_ba_tbl(struct mwifiex_private *priv, int tid, u8 *peer_mac,
|
|||
struct mwifiex_tx_ba_stream_tbl *ptx_tbl;
|
||||
struct mwifiex_ra_list_tbl *ra_list;
|
||||
u8 cleanup_rx_reorder_tbl;
|
||||
unsigned long flags;
|
||||
int tid_down;
|
||||
|
||||
if (type == TYPE_DELBA_RECEIVE)
|
||||
|
@ -716,9 +709,9 @@ mwifiex_del_ba_tbl(struct mwifiex_private *priv, int tid, u8 *peer_mac,
|
|||
ra_list->amsdu_in_ampdu = false;
|
||||
ra_list->ba_status = BA_SETUP_NONE;
|
||||
}
|
||||
spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags);
|
||||
spin_lock_bh(&priv->tx_ba_stream_tbl_lock);
|
||||
mwifiex_11n_delete_tx_ba_stream_tbl_entry(priv, ptx_tbl);
|
||||
spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags);
|
||||
spin_unlock_bh(&priv->tx_ba_stream_tbl_lock);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -804,17 +797,16 @@ void mwifiex_11n_ba_stream_timeout(struct mwifiex_private *priv,
|
|||
void mwifiex_11n_cleanup_reorder_tbl(struct mwifiex_private *priv)
|
||||
{
|
||||
struct mwifiex_rx_reorder_tbl *del_tbl_ptr, *tmp_node;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
|
||||
spin_lock_bh(&priv->rx_reorder_tbl_lock);
|
||||
list_for_each_entry_safe(del_tbl_ptr, tmp_node,
|
||||
&priv->rx_reorder_tbl_ptr, list) {
|
||||
spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
|
||||
spin_unlock_bh(&priv->rx_reorder_tbl_lock);
|
||||
mwifiex_del_rx_reorder_entry(priv, del_tbl_ptr);
|
||||
spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
|
||||
spin_lock_bh(&priv->rx_reorder_tbl_lock);
|
||||
}
|
||||
INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr);
|
||||
spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
|
||||
spin_unlock_bh(&priv->rx_reorder_tbl_lock);
|
||||
|
||||
mwifiex_reset_11n_rx_seq_num(priv);
|
||||
}
|
||||
|
@ -826,7 +818,6 @@ void mwifiex_update_rxreor_flags(struct mwifiex_adapter *adapter, u8 flags)
|
|||
{
|
||||
struct mwifiex_private *priv;
|
||||
struct mwifiex_rx_reorder_tbl *tbl;
|
||||
unsigned long lock_flags;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < adapter->priv_num; i++) {
|
||||
|
@ -834,10 +825,10 @@ void mwifiex_update_rxreor_flags(struct mwifiex_adapter *adapter, u8 flags)
|
|||
if (!priv)
|
||||
continue;
|
||||
|
||||
spin_lock_irqsave(&priv->rx_reorder_tbl_lock, lock_flags);
|
||||
spin_lock_bh(&priv->rx_reorder_tbl_lock);
|
||||
list_for_each_entry(tbl, &priv->rx_reorder_tbl_ptr, list)
|
||||
tbl->flags = flags;
|
||||
spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, lock_flags);
|
||||
spin_unlock_bh(&priv->rx_reorder_tbl_lock);
|
||||
}
|
||||
|
||||
return;
|
||||
|
|
|
@ -876,13 +876,13 @@ static int mwifiex_deinit_priv_params(struct mwifiex_private *priv)
|
|||
spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&adapter->rx_proc_lock, flags);
|
||||
spin_lock_bh(&adapter->rx_proc_lock);
|
||||
adapter->rx_locked = true;
|
||||
if (adapter->rx_processing) {
|
||||
spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
|
||||
spin_unlock_bh(&adapter->rx_proc_lock);
|
||||
flush_workqueue(adapter->rx_workqueue);
|
||||
} else {
|
||||
spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
|
||||
spin_unlock_bh(&adapter->rx_proc_lock);
|
||||
}
|
||||
|
||||
mwifiex_free_priv(priv);
|
||||
|
@ -934,9 +934,9 @@ mwifiex_init_new_priv_params(struct mwifiex_private *priv,
|
|||
adapter->main_locked = false;
|
||||
spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
|
||||
|
||||
spin_lock_irqsave(&adapter->rx_proc_lock, flags);
|
||||
spin_lock_bh(&adapter->rx_proc_lock);
|
||||
adapter->rx_locked = false;
|
||||
spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
|
||||
spin_unlock_bh(&adapter->rx_proc_lock);
|
||||
|
||||
mwifiex_set_mac_address(priv, dev, false, NULL);
|
||||
|
||||
|
@ -1827,7 +1827,6 @@ mwifiex_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev,
|
|||
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
|
||||
struct mwifiex_sta_node *sta_node;
|
||||
u8 deauth_mac[ETH_ALEN];
|
||||
unsigned long flags;
|
||||
|
||||
if (!priv->bss_started && priv->wdev.cac_started) {
|
||||
mwifiex_dbg(priv->adapter, INFO, "%s: abort CAC!\n", __func__);
|
||||
|
@ -1845,11 +1844,11 @@ mwifiex_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev,
|
|||
|
||||
eth_zero_addr(deauth_mac);
|
||||
|
||||
spin_lock_irqsave(&priv->sta_list_spinlock, flags);
|
||||
spin_lock_bh(&priv->sta_list_spinlock);
|
||||
sta_node = mwifiex_get_sta_entry(priv, params->mac);
|
||||
if (sta_node)
|
||||
ether_addr_copy(deauth_mac, params->mac);
|
||||
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
|
||||
spin_unlock_bh(&priv->sta_list_spinlock);
|
||||
|
||||
if (is_valid_ether_addr(deauth_mac)) {
|
||||
if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_STA_DEAUTH,
|
||||
|
@ -3852,15 +3851,14 @@ mwifiex_cfg80211_tdls_chan_switch(struct wiphy *wiphy, struct net_device *dev,
|
|||
struct cfg80211_chan_def *chandef)
|
||||
{
|
||||
struct mwifiex_sta_node *sta_ptr;
|
||||
unsigned long flags;
|
||||
u16 chan;
|
||||
u8 second_chan_offset, band;
|
||||
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
|
||||
|
||||
spin_lock_irqsave(&priv->sta_list_spinlock, flags);
|
||||
spin_lock_bh(&priv->sta_list_spinlock);
|
||||
sta_ptr = mwifiex_get_sta_entry(priv, addr);
|
||||
if (!sta_ptr) {
|
||||
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
|
||||
spin_unlock_bh(&priv->sta_list_spinlock);
|
||||
wiphy_err(wiphy, "%s: Invalid TDLS peer %pM\n",
|
||||
__func__, addr);
|
||||
return -ENOENT;
|
||||
|
@ -3868,18 +3866,18 @@ mwifiex_cfg80211_tdls_chan_switch(struct wiphy *wiphy, struct net_device *dev,
|
|||
|
||||
if (!(sta_ptr->tdls_cap.extcap.ext_capab[3] &
|
||||
WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH)) {
|
||||
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
|
||||
spin_unlock_bh(&priv->sta_list_spinlock);
|
||||
wiphy_err(wiphy, "%pM do not support tdls cs\n", addr);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (sta_ptr->tdls_status == TDLS_CHAN_SWITCHING ||
|
||||
sta_ptr->tdls_status == TDLS_IN_OFF_CHAN) {
|
||||
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
|
||||
spin_unlock_bh(&priv->sta_list_spinlock);
|
||||
wiphy_err(wiphy, "channel switch is running, abort request\n");
|
||||
return -EALREADY;
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
|
||||
spin_unlock_bh(&priv->sta_list_spinlock);
|
||||
|
||||
chan = chandef->chan->hw_value;
|
||||
second_chan_offset = mwifiex_get_sec_chan_offset(chan);
|
||||
|
@ -3895,23 +3893,22 @@ mwifiex_cfg80211_tdls_cancel_chan_switch(struct wiphy *wiphy,
|
|||
const u8 *addr)
|
||||
{
|
||||
struct mwifiex_sta_node *sta_ptr;
|
||||
unsigned long flags;
|
||||
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
|
||||
|
||||
spin_lock_irqsave(&priv->sta_list_spinlock, flags);
|
||||
spin_lock_bh(&priv->sta_list_spinlock);
|
||||
sta_ptr = mwifiex_get_sta_entry(priv, addr);
|
||||
if (!sta_ptr) {
|
||||
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
|
||||
spin_unlock_bh(&priv->sta_list_spinlock);
|
||||
wiphy_err(wiphy, "%s: Invalid TDLS peer %pM\n",
|
||||
__func__, addr);
|
||||
} else if (!(sta_ptr->tdls_status == TDLS_CHAN_SWITCHING ||
|
||||
sta_ptr->tdls_status == TDLS_IN_BASE_CHAN ||
|
||||
sta_ptr->tdls_status == TDLS_IN_OFF_CHAN)) {
|
||||
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
|
||||
spin_unlock_bh(&priv->sta_list_spinlock);
|
||||
wiphy_err(wiphy, "tdls chan switch not initialize by %pM\n",
|
||||
addr);
|
||||
} else {
|
||||
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
|
||||
spin_unlock_bh(&priv->sta_list_spinlock);
|
||||
mwifiex_stop_tdls_cs(priv, addr);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,19 +61,18 @@ static struct cmd_ctrl_node *
|
|||
mwifiex_get_cmd_node(struct mwifiex_adapter *adapter)
|
||||
{
|
||||
struct cmd_ctrl_node *cmd_node;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&adapter->cmd_free_q_lock, flags);
|
||||
spin_lock_bh(&adapter->cmd_free_q_lock);
|
||||
if (list_empty(&adapter->cmd_free_q)) {
|
||||
mwifiex_dbg(adapter, ERROR,
|
||||
"GET_CMD_NODE: cmd node not available\n");
|
||||
spin_unlock_irqrestore(&adapter->cmd_free_q_lock, flags);
|
||||
spin_unlock_bh(&adapter->cmd_free_q_lock);
|
||||
return NULL;
|
||||
}
|
||||
cmd_node = list_first_entry(&adapter->cmd_free_q,
|
||||
struct cmd_ctrl_node, list);
|
||||
list_del(&cmd_node->list);
|
||||
spin_unlock_irqrestore(&adapter->cmd_free_q_lock, flags);
|
||||
spin_unlock_bh(&adapter->cmd_free_q_lock);
|
||||
|
||||
return cmd_node;
|
||||
}
|
||||
|
@ -117,8 +116,6 @@ static void
|
|||
mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter,
|
||||
struct cmd_ctrl_node *cmd_node)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (!cmd_node)
|
||||
return;
|
||||
|
||||
|
@ -128,9 +125,9 @@ mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter,
|
|||
mwifiex_clean_cmd_node(adapter, cmd_node);
|
||||
|
||||
/* Insert node into cmd_free_q */
|
||||
spin_lock_irqsave(&adapter->cmd_free_q_lock, flags);
|
||||
spin_lock_bh(&adapter->cmd_free_q_lock);
|
||||
list_add_tail(&cmd_node->list, &adapter->cmd_free_q);
|
||||
spin_unlock_irqrestore(&adapter->cmd_free_q_lock, flags);
|
||||
spin_unlock_bh(&adapter->cmd_free_q_lock);
|
||||
}
|
||||
|
||||
/* This function reuses a command node. */
|
||||
|
@ -183,7 +180,6 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,
|
|||
struct host_cmd_ds_command *host_cmd;
|
||||
uint16_t cmd_code;
|
||||
uint16_t cmd_size;
|
||||
unsigned long flags;
|
||||
|
||||
if (!adapter || !cmd_node)
|
||||
return -1;
|
||||
|
@ -223,9 +219,9 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,
|
|||
cmd_node->priv->bss_num,
|
||||
cmd_node->priv->bss_type));
|
||||
|
||||
spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
|
||||
spin_lock_bh(&adapter->mwifiex_cmd_lock);
|
||||
adapter->curr_cmd = cmd_node;
|
||||
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
|
||||
spin_unlock_bh(&adapter->mwifiex_cmd_lock);
|
||||
|
||||
/* Adjust skb length */
|
||||
if (cmd_node->cmd_skb->len > cmd_size)
|
||||
|
@ -276,9 +272,9 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,
|
|||
adapter->cmd_wait_q.status = -1;
|
||||
mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd);
|
||||
|
||||
spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
|
||||
spin_lock_bh(&adapter->mwifiex_cmd_lock);
|
||||
adapter->curr_cmd = NULL;
|
||||
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
|
||||
spin_unlock_bh(&adapter->mwifiex_cmd_lock);
|
||||
|
||||
adapter->dbg.num_cmd_host_to_card_failure++;
|
||||
return -1;
|
||||
|
@ -697,7 +693,6 @@ mwifiex_insert_cmd_to_pending_q(struct mwifiex_adapter *adapter,
|
|||
{
|
||||
struct host_cmd_ds_command *host_cmd = NULL;
|
||||
u16 command;
|
||||
unsigned long flags;
|
||||
bool add_tail = true;
|
||||
|
||||
host_cmd = (struct host_cmd_ds_command *) (cmd_node->cmd_skb->data);
|
||||
|
@ -719,12 +714,12 @@ mwifiex_insert_cmd_to_pending_q(struct mwifiex_adapter *adapter,
|
|||
}
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags);
|
||||
spin_lock_bh(&adapter->cmd_pending_q_lock);
|
||||
if (add_tail)
|
||||
list_add_tail(&cmd_node->list, &adapter->cmd_pending_q);
|
||||
else
|
||||
list_add(&cmd_node->list, &adapter->cmd_pending_q);
|
||||
spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags);
|
||||
spin_unlock_bh(&adapter->cmd_pending_q_lock);
|
||||
|
||||
atomic_inc(&adapter->cmd_pending);
|
||||
mwifiex_dbg(adapter, CMD,
|
||||
|
@ -749,8 +744,6 @@ int mwifiex_exec_next_cmd(struct mwifiex_adapter *adapter)
|
|||
struct cmd_ctrl_node *cmd_node;
|
||||
int ret = 0;
|
||||
struct host_cmd_ds_command *host_cmd;
|
||||
unsigned long cmd_flags;
|
||||
unsigned long cmd_pending_q_flags;
|
||||
|
||||
/* Check if already in processing */
|
||||
if (adapter->curr_cmd) {
|
||||
|
@ -759,13 +752,12 @@ int mwifiex_exec_next_cmd(struct mwifiex_adapter *adapter)
|
|||
return -1;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags);
|
||||
spin_lock_bh(&adapter->mwifiex_cmd_lock);
|
||||
/* Check if any command is pending */
|
||||
spin_lock_irqsave(&adapter->cmd_pending_q_lock, cmd_pending_q_flags);
|
||||
spin_lock_bh(&adapter->cmd_pending_q_lock);
|
||||
if (list_empty(&adapter->cmd_pending_q)) {
|
||||
spin_unlock_irqrestore(&adapter->cmd_pending_q_lock,
|
||||
cmd_pending_q_flags);
|
||||
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
|
||||
spin_unlock_bh(&adapter->cmd_pending_q_lock);
|
||||
spin_unlock_bh(&adapter->mwifiex_cmd_lock);
|
||||
return 0;
|
||||
}
|
||||
cmd_node = list_first_entry(&adapter->cmd_pending_q,
|
||||
|
@ -778,17 +770,15 @@ int mwifiex_exec_next_cmd(struct mwifiex_adapter *adapter)
|
|||
mwifiex_dbg(adapter, ERROR,
|
||||
"%s: cannot send cmd in sleep state,\t"
|
||||
"this should not happen\n", __func__);
|
||||
spin_unlock_irqrestore(&adapter->cmd_pending_q_lock,
|
||||
cmd_pending_q_flags);
|
||||
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
|
||||
spin_unlock_bh(&adapter->cmd_pending_q_lock);
|
||||
spin_unlock_bh(&adapter->mwifiex_cmd_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
list_del(&cmd_node->list);
|
||||
spin_unlock_irqrestore(&adapter->cmd_pending_q_lock,
|
||||
cmd_pending_q_flags);
|
||||
spin_unlock_bh(&adapter->cmd_pending_q_lock);
|
||||
|
||||
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
|
||||
spin_unlock_bh(&adapter->mwifiex_cmd_lock);
|
||||
ret = mwifiex_dnld_cmd_to_fw(priv, cmd_node);
|
||||
priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
|
||||
/* Any command sent to the firmware when host is in sleep
|
||||
|
@ -822,7 +812,6 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter)
|
|||
uint16_t orig_cmdresp_no;
|
||||
uint16_t cmdresp_no;
|
||||
uint16_t cmdresp_result;
|
||||
unsigned long flags;
|
||||
|
||||
if (!adapter->curr_cmd || !adapter->curr_cmd->resp_skb) {
|
||||
resp = (struct host_cmd_ds_command *) adapter->upld_buf;
|
||||
|
@ -891,9 +880,9 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter)
|
|||
adapter->cmd_wait_q.status = -1;
|
||||
|
||||
mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd);
|
||||
spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
|
||||
spin_lock_bh(&adapter->mwifiex_cmd_lock);
|
||||
adapter->curr_cmd = NULL;
|
||||
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
|
||||
spin_unlock_bh(&adapter->mwifiex_cmd_lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -925,9 +914,9 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter)
|
|||
|
||||
mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd);
|
||||
|
||||
spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
|
||||
spin_lock_bh(&adapter->mwifiex_cmd_lock);
|
||||
adapter->curr_cmd = NULL;
|
||||
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
|
||||
spin_unlock_bh(&adapter->mwifiex_cmd_lock);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -1033,17 +1022,16 @@ void
|
|||
mwifiex_cancel_pending_scan_cmd(struct mwifiex_adapter *adapter)
|
||||
{
|
||||
struct cmd_ctrl_node *cmd_node = NULL, *tmp_node;
|
||||
unsigned long flags;
|
||||
|
||||
/* Cancel all pending scan command */
|
||||
spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
|
||||
spin_lock_bh(&adapter->scan_pending_q_lock);
|
||||
list_for_each_entry_safe(cmd_node, tmp_node,
|
||||
&adapter->scan_pending_q, list) {
|
||||
list_del(&cmd_node->list);
|
||||
cmd_node->wait_q_enabled = false;
|
||||
mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
|
||||
}
|
||||
spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
|
||||
spin_unlock_bh(&adapter->scan_pending_q_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1057,9 +1045,8 @@ void
|
|||
mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter)
|
||||
{
|
||||
struct cmd_ctrl_node *cmd_node = NULL, *tmp_node;
|
||||
unsigned long flags, cmd_flags;
|
||||
|
||||
spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags);
|
||||
spin_lock_bh(&adapter->mwifiex_cmd_lock);
|
||||
/* Cancel current cmd */
|
||||
if ((adapter->curr_cmd) && (adapter->curr_cmd->wait_q_enabled)) {
|
||||
adapter->cmd_wait_q.status = -1;
|
||||
|
@ -1068,7 +1055,7 @@ mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter)
|
|||
/* no recycle probably wait for response */
|
||||
}
|
||||
/* Cancel all pending command */
|
||||
spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags);
|
||||
spin_lock_bh(&adapter->cmd_pending_q_lock);
|
||||
list_for_each_entry_safe(cmd_node, tmp_node,
|
||||
&adapter->cmd_pending_q, list) {
|
||||
list_del(&cmd_node->list);
|
||||
|
@ -1077,8 +1064,8 @@ mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter)
|
|||
adapter->cmd_wait_q.status = -1;
|
||||
mwifiex_recycle_cmd_node(adapter, cmd_node);
|
||||
}
|
||||
spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags);
|
||||
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
|
||||
spin_unlock_bh(&adapter->cmd_pending_q_lock);
|
||||
spin_unlock_bh(&adapter->mwifiex_cmd_lock);
|
||||
|
||||
mwifiex_cancel_scan(adapter);
|
||||
}
|
||||
|
@ -1097,11 +1084,10 @@ static void
|
|||
mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter)
|
||||
{
|
||||
struct cmd_ctrl_node *cmd_node = NULL;
|
||||
unsigned long cmd_flags;
|
||||
|
||||
if ((adapter->curr_cmd) &&
|
||||
(adapter->curr_cmd->wait_q_enabled)) {
|
||||
spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags);
|
||||
spin_lock_bh(&adapter->mwifiex_cmd_lock);
|
||||
cmd_node = adapter->curr_cmd;
|
||||
/* setting curr_cmd to NULL is quite dangerous, because
|
||||
* mwifiex_process_cmdresp checks curr_cmd to be != NULL
|
||||
|
@ -1112,7 +1098,7 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter)
|
|||
* at that point
|
||||
*/
|
||||
adapter->curr_cmd = NULL;
|
||||
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
|
||||
spin_unlock_bh(&adapter->mwifiex_cmd_lock);
|
||||
|
||||
mwifiex_recycle_cmd_node(adapter, cmd_node);
|
||||
}
|
||||
|
|
|
@ -36,7 +36,6 @@ static int mwifiex_add_bss_prio_tbl(struct mwifiex_private *priv)
|
|||
struct mwifiex_adapter *adapter = priv->adapter;
|
||||
struct mwifiex_bss_prio_node *bss_prio;
|
||||
struct mwifiex_bss_prio_tbl *tbl = adapter->bss_prio_tbl;
|
||||
unsigned long flags;
|
||||
|
||||
bss_prio = kzalloc(sizeof(struct mwifiex_bss_prio_node), GFP_KERNEL);
|
||||
if (!bss_prio)
|
||||
|
@ -45,9 +44,9 @@ static int mwifiex_add_bss_prio_tbl(struct mwifiex_private *priv)
|
|||
bss_prio->priv = priv;
|
||||
INIT_LIST_HEAD(&bss_prio->list);
|
||||
|
||||
spin_lock_irqsave(&tbl[priv->bss_priority].bss_prio_lock, flags);
|
||||
spin_lock_bh(&tbl[priv->bss_priority].bss_prio_lock);
|
||||
list_add_tail(&bss_prio->list, &tbl[priv->bss_priority].bss_prio_head);
|
||||
spin_unlock_irqrestore(&tbl[priv->bss_priority].bss_prio_lock, flags);
|
||||
spin_unlock_bh(&tbl[priv->bss_priority].bss_prio_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -344,11 +343,9 @@ void mwifiex_set_trans_start(struct net_device *dev)
|
|||
void mwifiex_wake_up_net_dev_queue(struct net_device *netdev,
|
||||
struct mwifiex_adapter *adapter)
|
||||
{
|
||||
unsigned long dev_queue_flags;
|
||||
|
||||
spin_lock_irqsave(&adapter->queue_lock, dev_queue_flags);
|
||||
spin_lock_bh(&adapter->queue_lock);
|
||||
netif_tx_wake_all_queues(netdev);
|
||||
spin_unlock_irqrestore(&adapter->queue_lock, dev_queue_flags);
|
||||
spin_unlock_bh(&adapter->queue_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -357,11 +354,9 @@ void mwifiex_wake_up_net_dev_queue(struct net_device *netdev,
|
|||
void mwifiex_stop_net_dev_queue(struct net_device *netdev,
|
||||
struct mwifiex_adapter *adapter)
|
||||
{
|
||||
unsigned long dev_queue_flags;
|
||||
|
||||
spin_lock_irqsave(&adapter->queue_lock, dev_queue_flags);
|
||||
spin_lock_bh(&adapter->queue_lock);
|
||||
netif_tx_stop_all_queues(netdev);
|
||||
spin_unlock_irqrestore(&adapter->queue_lock, dev_queue_flags);
|
||||
spin_unlock_bh(&adapter->queue_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -506,7 +501,6 @@ int mwifiex_init_fw(struct mwifiex_adapter *adapter)
|
|||
struct mwifiex_private *priv;
|
||||
u8 i, first_sta = true;
|
||||
int is_cmd_pend_q_empty;
|
||||
unsigned long flags;
|
||||
|
||||
adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING;
|
||||
|
||||
|
@ -547,9 +541,9 @@ int mwifiex_init_fw(struct mwifiex_adapter *adapter)
|
|||
}
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags);
|
||||
spin_lock_bh(&adapter->cmd_pending_q_lock);
|
||||
is_cmd_pend_q_empty = list_empty(&adapter->cmd_pending_q);
|
||||
spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags);
|
||||
spin_unlock_bh(&adapter->cmd_pending_q_lock);
|
||||
if (!is_cmd_pend_q_empty) {
|
||||
/* Send the first command in queue and return */
|
||||
if (mwifiex_main_process(adapter) != -1)
|
||||
|
@ -574,7 +568,6 @@ static void mwifiex_delete_bss_prio_tbl(struct mwifiex_private *priv)
|
|||
struct mwifiex_bss_prio_node *bssprio_node, *tmp_node;
|
||||
struct list_head *head;
|
||||
spinlock_t *lock; /* bss priority lock */
|
||||
unsigned long flags;
|
||||
|
||||
for (i = 0; i < adapter->priv_num; ++i) {
|
||||
head = &adapter->bss_prio_tbl[i].bss_prio_head;
|
||||
|
@ -586,7 +579,7 @@ static void mwifiex_delete_bss_prio_tbl(struct mwifiex_private *priv)
|
|||
priv->bss_type, priv->bss_num, i, head);
|
||||
|
||||
{
|
||||
spin_lock_irqsave(lock, flags);
|
||||
spin_lock_bh(lock);
|
||||
list_for_each_entry_safe(bssprio_node, tmp_node, head,
|
||||
list) {
|
||||
if (bssprio_node->priv == priv) {
|
||||
|
@ -598,7 +591,7 @@ static void mwifiex_delete_bss_prio_tbl(struct mwifiex_private *priv)
|
|||
kfree(bssprio_node);
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(lock, flags);
|
||||
spin_unlock_bh(lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -630,7 +623,6 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter)
|
|||
{
|
||||
struct mwifiex_private *priv;
|
||||
s32 i;
|
||||
unsigned long flags;
|
||||
struct sk_buff *skb;
|
||||
|
||||
/* mwifiex already shutdown */
|
||||
|
@ -665,7 +657,7 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter)
|
|||
while ((skb = skb_dequeue(&adapter->tx_data_q)))
|
||||
mwifiex_write_data_complete(adapter, skb, 0, 0);
|
||||
|
||||
spin_lock_irqsave(&adapter->rx_proc_lock, flags);
|
||||
spin_lock_bh(&adapter->rx_proc_lock);
|
||||
|
||||
while ((skb = skb_dequeue(&adapter->rx_data_q))) {
|
||||
struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb);
|
||||
|
@ -678,7 +670,7 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter)
|
|||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
|
||||
spin_unlock_bh(&adapter->rx_proc_lock);
|
||||
|
||||
mwifiex_adapter_cleanup(adapter);
|
||||
|
||||
|
|
|
@ -173,30 +173,27 @@ EXPORT_SYMBOL_GPL(mwifiex_queue_main_work);
|
|||
|
||||
static void mwifiex_queue_rx_work(struct mwifiex_adapter *adapter)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&adapter->rx_proc_lock, flags);
|
||||
spin_lock_bh(&adapter->rx_proc_lock);
|
||||
if (adapter->rx_processing) {
|
||||
spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
|
||||
spin_unlock_bh(&adapter->rx_proc_lock);
|
||||
} else {
|
||||
spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
|
||||
spin_unlock_bh(&adapter->rx_proc_lock);
|
||||
queue_work(adapter->rx_workqueue, &adapter->rx_work);
|
||||
}
|
||||
}
|
||||
|
||||
static int mwifiex_process_rx(struct mwifiex_adapter *adapter)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct sk_buff *skb;
|
||||
struct mwifiex_rxinfo *rx_info;
|
||||
|
||||
spin_lock_irqsave(&adapter->rx_proc_lock, flags);
|
||||
spin_lock_bh(&adapter->rx_proc_lock);
|
||||
if (adapter->rx_processing || adapter->rx_locked) {
|
||||
spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
|
||||
spin_unlock_bh(&adapter->rx_proc_lock);
|
||||
goto exit_rx_proc;
|
||||
} else {
|
||||
adapter->rx_processing = true;
|
||||
spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
|
||||
spin_unlock_bh(&adapter->rx_proc_lock);
|
||||
}
|
||||
|
||||
/* Check for Rx data */
|
||||
|
@ -219,9 +216,9 @@ static int mwifiex_process_rx(struct mwifiex_adapter *adapter)
|
|||
mwifiex_handle_rx_packet(adapter, skb);
|
||||
}
|
||||
}
|
||||
spin_lock_irqsave(&adapter->rx_proc_lock, flags);
|
||||
spin_lock_bh(&adapter->rx_proc_lock);
|
||||
adapter->rx_processing = false;
|
||||
spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
|
||||
spin_unlock_bh(&adapter->rx_proc_lock);
|
||||
|
||||
exit_rx_proc:
|
||||
return 0;
|
||||
|
@ -825,13 +822,12 @@ mwifiex_clone_skb_for_tx_status(struct mwifiex_private *priv,
|
|||
|
||||
skb = skb_clone(skb, GFP_ATOMIC);
|
||||
if (skb) {
|
||||
unsigned long flags;
|
||||
int id;
|
||||
|
||||
spin_lock_irqsave(&priv->ack_status_lock, flags);
|
||||
spin_lock_bh(&priv->ack_status_lock);
|
||||
id = idr_alloc(&priv->ack_status_frames, orig_skb,
|
||||
1, 0x10, GFP_ATOMIC);
|
||||
spin_unlock_irqrestore(&priv->ack_status_lock, flags);
|
||||
spin_unlock_bh(&priv->ack_status_lock);
|
||||
|
||||
if (id >= 0) {
|
||||
tx_info = MWIFIEX_SKB_TXCB(skb);
|
||||
|
@ -1354,12 +1350,11 @@ void mwifiex_init_priv_params(struct mwifiex_private *priv,
|
|||
*/
|
||||
int is_command_pending(struct mwifiex_adapter *adapter)
|
||||
{
|
||||
unsigned long flags;
|
||||
int is_cmd_pend_q_empty;
|
||||
|
||||
spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags);
|
||||
spin_lock_bh(&adapter->cmd_pending_q_lock);
|
||||
is_cmd_pend_q_empty = list_empty(&adapter->cmd_pending_q);
|
||||
spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags);
|
||||
spin_unlock_bh(&adapter->cmd_pending_q_lock);
|
||||
|
||||
return !is_cmd_pend_q_empty;
|
||||
}
|
||||
|
|
|
@ -1500,7 +1500,6 @@ int mwifiex_scan_networks(struct mwifiex_private *priv,
|
|||
u8 filtered_scan;
|
||||
u8 scan_current_chan_only;
|
||||
u8 max_chan_per_scan;
|
||||
unsigned long flags;
|
||||
|
||||
if (adapter->scan_processing) {
|
||||
mwifiex_dbg(adapter, WARN,
|
||||
|
@ -1521,9 +1520,9 @@ int mwifiex_scan_networks(struct mwifiex_private *priv,
|
|||
return -EFAULT;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
|
||||
spin_lock_bh(&adapter->mwifiex_cmd_lock);
|
||||
adapter->scan_processing = true;
|
||||
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
|
||||
spin_unlock_bh(&adapter->mwifiex_cmd_lock);
|
||||
|
||||
scan_cfg_out = kzalloc(sizeof(union mwifiex_scan_cmd_config_tlv),
|
||||
GFP_KERNEL);
|
||||
|
@ -1551,13 +1550,12 @@ int mwifiex_scan_networks(struct mwifiex_private *priv,
|
|||
|
||||
/* Get scan command from scan_pending_q and put to cmd_pending_q */
|
||||
if (!ret) {
|
||||
spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
|
||||
spin_lock_bh(&adapter->scan_pending_q_lock);
|
||||
if (!list_empty(&adapter->scan_pending_q)) {
|
||||
cmd_node = list_first_entry(&adapter->scan_pending_q,
|
||||
struct cmd_ctrl_node, list);
|
||||
list_del(&cmd_node->list);
|
||||
spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
|
||||
flags);
|
||||
spin_unlock_bh(&adapter->scan_pending_q_lock);
|
||||
mwifiex_insert_cmd_to_pending_q(adapter, cmd_node);
|
||||
queue_work(adapter->workqueue, &adapter->main_work);
|
||||
|
||||
|
@ -1568,8 +1566,7 @@ int mwifiex_scan_networks(struct mwifiex_private *priv,
|
|||
mwifiex_wait_queue_complete(adapter, cmd_node);
|
||||
}
|
||||
} else {
|
||||
spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
|
||||
flags);
|
||||
spin_unlock_bh(&adapter->scan_pending_q_lock);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1577,9 +1574,9 @@ int mwifiex_scan_networks(struct mwifiex_private *priv,
|
|||
kfree(scan_chan_list);
|
||||
done:
|
||||
if (ret) {
|
||||
spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
|
||||
spin_lock_bh(&adapter->mwifiex_cmd_lock);
|
||||
adapter->scan_processing = false;
|
||||
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
|
||||
spin_unlock_bh(&adapter->mwifiex_cmd_lock);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -1715,7 +1712,6 @@ static int mwifiex_update_curr_bss_params(struct mwifiex_private *priv,
|
|||
{
|
||||
struct mwifiex_bssdescriptor *bss_desc;
|
||||
int ret;
|
||||
unsigned long flags;
|
||||
|
||||
/* Allocate and fill new bss descriptor */
|
||||
bss_desc = kzalloc(sizeof(struct mwifiex_bssdescriptor), GFP_KERNEL);
|
||||
|
@ -1730,7 +1726,7 @@ static int mwifiex_update_curr_bss_params(struct mwifiex_private *priv,
|
|||
if (ret)
|
||||
goto done;
|
||||
|
||||
spin_lock_irqsave(&priv->curr_bcn_buf_lock, flags);
|
||||
spin_lock_bh(&priv->curr_bcn_buf_lock);
|
||||
/* Make a copy of current BSSID descriptor */
|
||||
memcpy(&priv->curr_bss_params.bss_descriptor, bss_desc,
|
||||
sizeof(priv->curr_bss_params.bss_descriptor));
|
||||
|
@ -1739,7 +1735,7 @@ static int mwifiex_update_curr_bss_params(struct mwifiex_private *priv,
|
|||
* in mwifiex_save_curr_bcn()
|
||||
*/
|
||||
mwifiex_save_curr_bcn(priv);
|
||||
spin_unlock_irqrestore(&priv->curr_bcn_buf_lock, flags);
|
||||
spin_unlock_bh(&priv->curr_bcn_buf_lock);
|
||||
|
||||
done:
|
||||
/* beacon_ie buffer was allocated in function
|
||||
|
@ -1993,15 +1989,14 @@ static void mwifiex_check_next_scan_command(struct mwifiex_private *priv)
|
|||
{
|
||||
struct mwifiex_adapter *adapter = priv->adapter;
|
||||
struct cmd_ctrl_node *cmd_node;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
|
||||
spin_lock_bh(&adapter->scan_pending_q_lock);
|
||||
if (list_empty(&adapter->scan_pending_q)) {
|
||||
spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
|
||||
spin_unlock_bh(&adapter->scan_pending_q_lock);
|
||||
|
||||
spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
|
||||
spin_lock_bh(&adapter->mwifiex_cmd_lock);
|
||||
adapter->scan_processing = false;
|
||||
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
|
||||
spin_unlock_bh(&adapter->mwifiex_cmd_lock);
|
||||
|
||||
mwifiex_active_scan_req_for_passive_chan(priv);
|
||||
|
||||
|
@ -2025,13 +2020,13 @@ static void mwifiex_check_next_scan_command(struct mwifiex_private *priv)
|
|||
}
|
||||
} else if ((priv->scan_aborting && !priv->scan_request) ||
|
||||
priv->scan_block) {
|
||||
spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
|
||||
spin_unlock_bh(&adapter->scan_pending_q_lock);
|
||||
|
||||
mwifiex_cancel_pending_scan_cmd(adapter);
|
||||
|
||||
spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
|
||||
spin_lock_bh(&adapter->mwifiex_cmd_lock);
|
||||
adapter->scan_processing = false;
|
||||
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
|
||||
spin_unlock_bh(&adapter->mwifiex_cmd_lock);
|
||||
|
||||
if (!adapter->active_scan_triggered) {
|
||||
if (priv->scan_request) {
|
||||
|
@ -2057,7 +2052,7 @@ static void mwifiex_check_next_scan_command(struct mwifiex_private *priv)
|
|||
cmd_node = list_first_entry(&adapter->scan_pending_q,
|
||||
struct cmd_ctrl_node, list);
|
||||
list_del(&cmd_node->list);
|
||||
spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
|
||||
spin_unlock_bh(&adapter->scan_pending_q_lock);
|
||||
mwifiex_insert_cmd_to_pending_q(adapter, cmd_node);
|
||||
}
|
||||
|
||||
|
@ -2067,15 +2062,14 @@ static void mwifiex_check_next_scan_command(struct mwifiex_private *priv)
|
|||
void mwifiex_cancel_scan(struct mwifiex_adapter *adapter)
|
||||
{
|
||||
struct mwifiex_private *priv;
|
||||
unsigned long cmd_flags;
|
||||
int i;
|
||||
|
||||
mwifiex_cancel_pending_scan_cmd(adapter);
|
||||
|
||||
if (adapter->scan_processing) {
|
||||
spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags);
|
||||
spin_lock_bh(&adapter->mwifiex_cmd_lock);
|
||||
adapter->scan_processing = false;
|
||||
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
|
||||
spin_unlock_bh(&adapter->mwifiex_cmd_lock);
|
||||
for (i = 0; i < adapter->priv_num; i++) {
|
||||
priv = adapter->priv[i];
|
||||
if (!priv)
|
||||
|
@ -2557,7 +2551,6 @@ int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv,
|
|||
|
||||
struct host_cmd_ds_command *cmd_ptr;
|
||||
struct cmd_ctrl_node *cmd_node;
|
||||
unsigned long cmd_flags, scan_flags;
|
||||
bool complete_scan = false;
|
||||
|
||||
mwifiex_dbg(adapter, INFO, "info: EXT scan returns successfully\n");
|
||||
|
@ -2592,8 +2585,8 @@ int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv,
|
|||
sizeof(struct mwifiex_ie_types_header));
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&adapter->cmd_pending_q_lock, cmd_flags);
|
||||
spin_lock_irqsave(&adapter->scan_pending_q_lock, scan_flags);
|
||||
spin_lock_bh(&adapter->cmd_pending_q_lock);
|
||||
spin_lock_bh(&adapter->scan_pending_q_lock);
|
||||
if (list_empty(&adapter->scan_pending_q)) {
|
||||
complete_scan = true;
|
||||
list_for_each_entry(cmd_node, &adapter->cmd_pending_q, list) {
|
||||
|
@ -2607,8 +2600,8 @@ int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv,
|
|||
}
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&adapter->scan_pending_q_lock, scan_flags);
|
||||
spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, cmd_flags);
|
||||
spin_unlock_bh(&adapter->scan_pending_q_lock);
|
||||
spin_unlock_bh(&adapter->cmd_pending_q_lock);
|
||||
|
||||
if (complete_scan)
|
||||
mwifiex_complete_scan(priv);
|
||||
|
@ -2780,13 +2773,12 @@ mwifiex_queue_scan_cmd(struct mwifiex_private *priv,
|
|||
struct cmd_ctrl_node *cmd_node)
|
||||
{
|
||||
struct mwifiex_adapter *adapter = priv->adapter;
|
||||
unsigned long flags;
|
||||
|
||||
cmd_node->wait_q_enabled = true;
|
||||
cmd_node->condition = &adapter->scan_wait_q_woken;
|
||||
spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
|
||||
spin_lock_bh(&adapter->scan_pending_q_lock);
|
||||
list_add_tail(&cmd_node->list, &adapter->scan_pending_q);
|
||||
spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
|
||||
spin_unlock_bh(&adapter->scan_pending_q_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -46,7 +46,6 @@ mwifiex_process_cmdresp_error(struct mwifiex_private *priv,
|
|||
{
|
||||
struct mwifiex_adapter *adapter = priv->adapter;
|
||||
struct host_cmd_ds_802_11_ps_mode_enh *pm;
|
||||
unsigned long flags;
|
||||
|
||||
mwifiex_dbg(adapter, ERROR,
|
||||
"CMD_RESP: cmd %#x error, result=%#x\n",
|
||||
|
@ -87,9 +86,9 @@ mwifiex_process_cmdresp_error(struct mwifiex_private *priv,
|
|||
/* Handling errors here */
|
||||
mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd);
|
||||
|
||||
spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
|
||||
spin_lock_bh(&adapter->mwifiex_cmd_lock);
|
||||
adapter->curr_cmd = NULL;
|
||||
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
|
||||
spin_unlock_bh(&adapter->mwifiex_cmd_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -345,7 +345,6 @@ static void mwifiex_process_uap_tx_pause(struct mwifiex_private *priv,
|
|||
{
|
||||
struct mwifiex_tx_pause_tlv *tp;
|
||||
struct mwifiex_sta_node *sta_ptr;
|
||||
unsigned long flags;
|
||||
|
||||
tp = (void *)tlv;
|
||||
mwifiex_dbg(priv->adapter, EVENT,
|
||||
|
@ -361,14 +360,14 @@ static void mwifiex_process_uap_tx_pause(struct mwifiex_private *priv,
|
|||
} else if (is_multicast_ether_addr(tp->peermac)) {
|
||||
mwifiex_update_ralist_tx_pause(priv, tp->peermac, tp->tx_pause);
|
||||
} else {
|
||||
spin_lock_irqsave(&priv->sta_list_spinlock, flags);
|
||||
spin_lock_bh(&priv->sta_list_spinlock);
|
||||
sta_ptr = mwifiex_get_sta_entry(priv, tp->peermac);
|
||||
if (sta_ptr && sta_ptr->tx_pause != tp->tx_pause) {
|
||||
sta_ptr->tx_pause = tp->tx_pause;
|
||||
mwifiex_update_ralist_tx_pause(priv, tp->peermac,
|
||||
tp->tx_pause);
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
|
||||
spin_unlock_bh(&priv->sta_list_spinlock);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -378,7 +377,6 @@ static void mwifiex_process_sta_tx_pause(struct mwifiex_private *priv,
|
|||
struct mwifiex_tx_pause_tlv *tp;
|
||||
struct mwifiex_sta_node *sta_ptr;
|
||||
int status;
|
||||
unsigned long flags;
|
||||
|
||||
tp = (void *)tlv;
|
||||
mwifiex_dbg(priv->adapter, EVENT,
|
||||
|
@ -397,7 +395,7 @@ static void mwifiex_process_sta_tx_pause(struct mwifiex_private *priv,
|
|||
|
||||
status = mwifiex_get_tdls_link_status(priv, tp->peermac);
|
||||
if (mwifiex_is_tdls_link_setup(status)) {
|
||||
spin_lock_irqsave(&priv->sta_list_spinlock, flags);
|
||||
spin_lock_bh(&priv->sta_list_spinlock);
|
||||
sta_ptr = mwifiex_get_sta_entry(priv, tp->peermac);
|
||||
if (sta_ptr && sta_ptr->tx_pause != tp->tx_pause) {
|
||||
sta_ptr->tx_pause = tp->tx_pause;
|
||||
|
@ -405,7 +403,7 @@ static void mwifiex_process_sta_tx_pause(struct mwifiex_private *priv,
|
|||
tp->peermac,
|
||||
tp->tx_pause);
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
|
||||
spin_unlock_bh(&priv->sta_list_spinlock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,12 +33,11 @@ static void mwifiex_restore_tdls_packets(struct mwifiex_private *priv,
|
|||
struct list_head *tid_list;
|
||||
struct sk_buff *skb, *tmp;
|
||||
struct mwifiex_txinfo *tx_info;
|
||||
unsigned long flags;
|
||||
u32 tid;
|
||||
u8 tid_down;
|
||||
|
||||
mwifiex_dbg(priv->adapter, DATA, "%s: %pM\n", __func__, mac);
|
||||
spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
|
||||
spin_lock_bh(&priv->wmm.ra_list_spinlock);
|
||||
|
||||
skb_queue_walk_safe(&priv->tdls_txq, skb, tmp) {
|
||||
if (!ether_addr_equal(mac, skb->data))
|
||||
|
@ -78,7 +77,7 @@ static void mwifiex_restore_tdls_packets(struct mwifiex_private *priv,
|
|||
atomic_inc(&priv->wmm.tx_pkts_queued);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
|
||||
spin_unlock_bh(&priv->wmm.ra_list_spinlock);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -88,11 +87,10 @@ static void mwifiex_hold_tdls_packets(struct mwifiex_private *priv,
|
|||
struct mwifiex_ra_list_tbl *ra_list;
|
||||
struct list_head *ra_list_head;
|
||||
struct sk_buff *skb, *tmp;
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
mwifiex_dbg(priv->adapter, DATA, "%s: %pM\n", __func__, mac);
|
||||
spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
|
||||
spin_lock_bh(&priv->wmm.ra_list_spinlock);
|
||||
|
||||
for (i = 0; i < MAX_NUM_TID; i++) {
|
||||
if (!list_empty(&priv->wmm.tid_tbl_ptr[i].ra_list)) {
|
||||
|
@ -111,7 +109,7 @@ static void mwifiex_hold_tdls_packets(struct mwifiex_private *priv,
|
|||
}
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
|
||||
spin_unlock_bh(&priv->wmm.ra_list_spinlock);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1070,7 +1068,6 @@ mwifiex_tdls_process_disable_link(struct mwifiex_private *priv, const u8 *peer)
|
|||
{
|
||||
struct mwifiex_sta_node *sta_ptr;
|
||||
struct mwifiex_ds_tdls_oper tdls_oper;
|
||||
unsigned long flags;
|
||||
|
||||
memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper));
|
||||
sta_ptr = mwifiex_get_sta_entry(priv, peer);
|
||||
|
@ -1078,11 +1075,9 @@ mwifiex_tdls_process_disable_link(struct mwifiex_private *priv, const u8 *peer)
|
|||
if (sta_ptr) {
|
||||
if (sta_ptr->is_11n_enabled) {
|
||||
mwifiex_11n_cleanup_reorder_tbl(priv);
|
||||
spin_lock_irqsave(&priv->wmm.ra_list_spinlock,
|
||||
flags);
|
||||
spin_lock_bh(&priv->wmm.ra_list_spinlock);
|
||||
mwifiex_11n_delete_all_tx_ba_stream_tbl(priv);
|
||||
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
|
||||
flags);
|
||||
spin_unlock_bh(&priv->wmm.ra_list_spinlock);
|
||||
}
|
||||
mwifiex_del_sta_entry(priv, peer);
|
||||
}
|
||||
|
@ -1100,7 +1095,6 @@ mwifiex_tdls_process_enable_link(struct mwifiex_private *priv, const u8 *peer)
|
|||
{
|
||||
struct mwifiex_sta_node *sta_ptr;
|
||||
struct ieee80211_mcs_info mcs;
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
sta_ptr = mwifiex_get_sta_entry(priv, peer);
|
||||
|
@ -1145,11 +1139,9 @@ mwifiex_tdls_process_enable_link(struct mwifiex_private *priv, const u8 *peer)
|
|||
"tdls: enable link %pM failed\n", peer);
|
||||
if (sta_ptr) {
|
||||
mwifiex_11n_cleanup_reorder_tbl(priv);
|
||||
spin_lock_irqsave(&priv->wmm.ra_list_spinlock,
|
||||
flags);
|
||||
spin_lock_bh(&priv->wmm.ra_list_spinlock);
|
||||
mwifiex_11n_delete_all_tx_ba_stream_tbl(priv);
|
||||
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
|
||||
flags);
|
||||
spin_unlock_bh(&priv->wmm.ra_list_spinlock);
|
||||
mwifiex_del_sta_entry(priv, peer);
|
||||
}
|
||||
mwifiex_restore_tdls_packets(priv, peer, TDLS_LINK_TEARDOWN);
|
||||
|
@ -1194,7 +1186,6 @@ int mwifiex_get_tdls_list(struct mwifiex_private *priv,
|
|||
struct mwifiex_sta_node *sta_ptr;
|
||||
struct tdls_peer_info *peer = buf;
|
||||
int count = 0;
|
||||
unsigned long flags;
|
||||
|
||||
if (!ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info))
|
||||
return 0;
|
||||
|
@ -1203,7 +1194,7 @@ int mwifiex_get_tdls_list(struct mwifiex_private *priv,
|
|||
if (!(priv->bss_type == MWIFIEX_BSS_TYPE_STA && priv->media_connected))
|
||||
return 0;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_list_spinlock, flags);
|
||||
spin_lock_bh(&priv->sta_list_spinlock);
|
||||
list_for_each_entry(sta_ptr, &priv->sta_list, list) {
|
||||
if (mwifiex_is_tdls_link_setup(sta_ptr->tdls_status)) {
|
||||
ether_addr_copy(peer->peer_addr, sta_ptr->mac_addr);
|
||||
|
@ -1213,7 +1204,7 @@ int mwifiex_get_tdls_list(struct mwifiex_private *priv,
|
|||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
|
||||
spin_unlock_bh(&priv->sta_list_spinlock);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
@ -1222,7 +1213,6 @@ void mwifiex_disable_all_tdls_links(struct mwifiex_private *priv)
|
|||
{
|
||||
struct mwifiex_sta_node *sta_ptr;
|
||||
struct mwifiex_ds_tdls_oper tdls_oper;
|
||||
unsigned long flags;
|
||||
|
||||
if (list_empty(&priv->sta_list))
|
||||
return;
|
||||
|
@ -1232,11 +1222,9 @@ void mwifiex_disable_all_tdls_links(struct mwifiex_private *priv)
|
|||
|
||||
if (sta_ptr->is_11n_enabled) {
|
||||
mwifiex_11n_cleanup_reorder_tbl(priv);
|
||||
spin_lock_irqsave(&priv->wmm.ra_list_spinlock,
|
||||
flags);
|
||||
spin_lock_bh(&priv->wmm.ra_list_spinlock);
|
||||
mwifiex_11n_delete_all_tx_ba_stream_tbl(priv);
|
||||
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
|
||||
flags);
|
||||
spin_unlock_bh(&priv->wmm.ra_list_spinlock);
|
||||
}
|
||||
|
||||
mwifiex_restore_tdls_packets(priv, sta_ptr->mac_addr,
|
||||
|
@ -1256,12 +1244,11 @@ void mwifiex_disable_all_tdls_links(struct mwifiex_private *priv)
|
|||
int mwifiex_tdls_check_tx(struct mwifiex_private *priv, struct sk_buff *skb)
|
||||
{
|
||||
struct mwifiex_auto_tdls_peer *peer;
|
||||
unsigned long flags;
|
||||
u8 mac[ETH_ALEN];
|
||||
|
||||
ether_addr_copy(mac, skb->data);
|
||||
|
||||
spin_lock_irqsave(&priv->auto_tdls_lock, flags);
|
||||
spin_lock_bh(&priv->auto_tdls_lock);
|
||||
list_for_each_entry(peer, &priv->auto_tdls_list, list) {
|
||||
if (!memcmp(mac, peer->mac_addr, ETH_ALEN)) {
|
||||
if (peer->rssi <= MWIFIEX_TDLS_RSSI_HIGH &&
|
||||
|
@ -1290,7 +1277,7 @@ int mwifiex_tdls_check_tx(struct mwifiex_private *priv, struct sk_buff *skb)
|
|||
}
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->auto_tdls_lock, flags);
|
||||
spin_unlock_bh(&priv->auto_tdls_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1298,33 +1285,31 @@ int mwifiex_tdls_check_tx(struct mwifiex_private *priv, struct sk_buff *skb)
|
|||
void mwifiex_flush_auto_tdls_list(struct mwifiex_private *priv)
|
||||
{
|
||||
struct mwifiex_auto_tdls_peer *peer, *tmp_node;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&priv->auto_tdls_lock, flags);
|
||||
spin_lock_bh(&priv->auto_tdls_lock);
|
||||
list_for_each_entry_safe(peer, tmp_node, &priv->auto_tdls_list, list) {
|
||||
list_del(&peer->list);
|
||||
kfree(peer);
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&priv->auto_tdls_list);
|
||||
spin_unlock_irqrestore(&priv->auto_tdls_lock, flags);
|
||||
spin_unlock_bh(&priv->auto_tdls_lock);
|
||||
priv->check_tdls_tx = false;
|
||||
}
|
||||
|
||||
void mwifiex_add_auto_tdls_peer(struct mwifiex_private *priv, const u8 *mac)
|
||||
{
|
||||
struct mwifiex_auto_tdls_peer *tdls_peer;
|
||||
unsigned long flags;
|
||||
|
||||
if (!priv->adapter->auto_tdls)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&priv->auto_tdls_lock, flags);
|
||||
spin_lock_bh(&priv->auto_tdls_lock);
|
||||
list_for_each_entry(tdls_peer, &priv->auto_tdls_list, list) {
|
||||
if (!memcmp(tdls_peer->mac_addr, mac, ETH_ALEN)) {
|
||||
tdls_peer->tdls_status = TDLS_SETUP_INPROGRESS;
|
||||
tdls_peer->rssi_jiffies = jiffies;
|
||||
spin_unlock_irqrestore(&priv->auto_tdls_lock, flags);
|
||||
spin_unlock_bh(&priv->auto_tdls_lock);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1341,19 +1326,18 @@ void mwifiex_add_auto_tdls_peer(struct mwifiex_private *priv, const u8 *mac)
|
|||
"Add auto TDLS peer= %pM to list\n", mac);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&priv->auto_tdls_lock, flags);
|
||||
spin_unlock_bh(&priv->auto_tdls_lock);
|
||||
}
|
||||
|
||||
void mwifiex_auto_tdls_update_peer_status(struct mwifiex_private *priv,
|
||||
const u8 *mac, u8 link_status)
|
||||
{
|
||||
struct mwifiex_auto_tdls_peer *peer;
|
||||
unsigned long flags;
|
||||
|
||||
if (!priv->adapter->auto_tdls)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&priv->auto_tdls_lock, flags);
|
||||
spin_lock_bh(&priv->auto_tdls_lock);
|
||||
list_for_each_entry(peer, &priv->auto_tdls_list, list) {
|
||||
if (!memcmp(peer->mac_addr, mac, ETH_ALEN)) {
|
||||
if ((link_status == TDLS_NOT_SETUP) &&
|
||||
|
@ -1366,19 +1350,18 @@ void mwifiex_auto_tdls_update_peer_status(struct mwifiex_private *priv,
|
|||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->auto_tdls_lock, flags);
|
||||
spin_unlock_bh(&priv->auto_tdls_lock);
|
||||
}
|
||||
|
||||
void mwifiex_auto_tdls_update_peer_signal(struct mwifiex_private *priv,
|
||||
u8 *mac, s8 snr, s8 nflr)
|
||||
{
|
||||
struct mwifiex_auto_tdls_peer *peer;
|
||||
unsigned long flags;
|
||||
|
||||
if (!priv->adapter->auto_tdls)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&priv->auto_tdls_lock, flags);
|
||||
spin_lock_bh(&priv->auto_tdls_lock);
|
||||
list_for_each_entry(peer, &priv->auto_tdls_list, list) {
|
||||
if (!memcmp(peer->mac_addr, mac, ETH_ALEN)) {
|
||||
peer->rssi = nflr - snr;
|
||||
|
@ -1386,14 +1369,13 @@ void mwifiex_auto_tdls_update_peer_signal(struct mwifiex_private *priv,
|
|||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->auto_tdls_lock, flags);
|
||||
spin_unlock_bh(&priv->auto_tdls_lock);
|
||||
}
|
||||
|
||||
void mwifiex_check_auto_tdls(struct timer_list *t)
|
||||
{
|
||||
struct mwifiex_private *priv = from_timer(priv, t, auto_tdls_timer);
|
||||
struct mwifiex_auto_tdls_peer *tdls_peer;
|
||||
unsigned long flags;
|
||||
u16 reason = WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED;
|
||||
|
||||
if (WARN_ON_ONCE(!priv || !priv->adapter)) {
|
||||
|
@ -1413,7 +1395,7 @@ void mwifiex_check_auto_tdls(struct timer_list *t)
|
|||
|
||||
priv->check_tdls_tx = false;
|
||||
|
||||
spin_lock_irqsave(&priv->auto_tdls_lock, flags);
|
||||
spin_lock_bh(&priv->auto_tdls_lock);
|
||||
list_for_each_entry(tdls_peer, &priv->auto_tdls_list, list) {
|
||||
if ((jiffies - tdls_peer->rssi_jiffies) >
|
||||
(MWIFIEX_AUTO_TDLS_IDLE_TIME * HZ)) {
|
||||
|
@ -1448,7 +1430,7 @@ void mwifiex_check_auto_tdls(struct timer_list *t)
|
|||
tdls_peer->rssi);
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->auto_tdls_lock, flags);
|
||||
spin_unlock_bh(&priv->auto_tdls_lock);
|
||||
|
||||
mod_timer(&priv->auto_tdls_timer,
|
||||
jiffies + msecs_to_jiffies(MWIFIEX_TIMER_10S));
|
||||
|
|
|
@ -334,15 +334,14 @@ void mwifiex_parse_tx_status_event(struct mwifiex_private *priv,
|
|||
{
|
||||
struct tx_status_event *tx_status = (void *)priv->adapter->event_body;
|
||||
struct sk_buff *ack_skb;
|
||||
unsigned long flags;
|
||||
struct mwifiex_txinfo *tx_info;
|
||||
|
||||
if (!tx_status->tx_token_id)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&priv->ack_status_lock, flags);
|
||||
spin_lock_bh(&priv->ack_status_lock);
|
||||
ack_skb = idr_remove(&priv->ack_status_frames, tx_status->tx_token_id);
|
||||
spin_unlock_irqrestore(&priv->ack_status_lock, flags);
|
||||
spin_unlock_bh(&priv->ack_status_lock);
|
||||
|
||||
if (ack_skb) {
|
||||
tx_info = MWIFIEX_SKB_TXCB(ack_skb);
|
||||
|
|
|
@ -71,11 +71,10 @@ mwifiex_uap_del_tx_pkts_in_ralist(struct mwifiex_private *priv,
|
|||
*/
|
||||
static void mwifiex_uap_cleanup_tx_queues(struct mwifiex_private *priv)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct list_head *ra_list;
|
||||
int i;
|
||||
|
||||
spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
|
||||
spin_lock_bh(&priv->wmm.ra_list_spinlock);
|
||||
|
||||
for (i = 0; i < MAX_NUM_TID; i++, priv->del_list_idx++) {
|
||||
if (priv->del_list_idx == MAX_NUM_TID)
|
||||
|
@ -87,7 +86,7 @@ static void mwifiex_uap_cleanup_tx_queues(struct mwifiex_private *priv)
|
|||
}
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
|
||||
spin_unlock_bh(&priv->wmm.ra_list_spinlock);
|
||||
}
|
||||
|
||||
|
||||
|
@ -378,7 +377,6 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_private *priv,
|
|||
struct rx_packet_hdr *rx_pkt_hdr;
|
||||
u16 rx_pkt_type;
|
||||
u8 ta[ETH_ALEN], pkt_type;
|
||||
unsigned long flags;
|
||||
struct mwifiex_sta_node *node;
|
||||
|
||||
uap_rx_pd = (struct uap_rxpd *)(skb->data);
|
||||
|
@ -413,12 +411,12 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_private *priv,
|
|||
|
||||
|
||||
if (rx_pkt_type != PKT_TYPE_BAR && uap_rx_pd->priority < MAX_NUM_TID) {
|
||||
spin_lock_irqsave(&priv->sta_list_spinlock, flags);
|
||||
spin_lock_bh(&priv->sta_list_spinlock);
|
||||
node = mwifiex_get_sta_entry(priv, ta);
|
||||
if (node)
|
||||
node->rx_seq[uap_rx_pd->priority] =
|
||||
le16_to_cpu(uap_rx_pd->seq_num);
|
||||
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
|
||||
spin_unlock_bh(&priv->sta_list_spinlock);
|
||||
}
|
||||
|
||||
if (!priv->ap_11n_enabled ||
|
||||
|
|
|
@ -1128,10 +1128,9 @@ static void mwifiex_usb_tx_aggr_tmo(struct timer_list *t)
|
|||
from_timer(timer_context, t, hold_timer);
|
||||
struct mwifiex_adapter *adapter = timer_context->adapter;
|
||||
struct usb_tx_data_port *port = timer_context->port;
|
||||
unsigned long flags;
|
||||
int err = 0;
|
||||
|
||||
spin_lock_irqsave(&port->tx_aggr_lock, flags);
|
||||
spin_lock_bh(&port->tx_aggr_lock);
|
||||
err = mwifiex_usb_prepare_tx_aggr_skb(adapter, port, &skb_send);
|
||||
if (err) {
|
||||
mwifiex_dbg(adapter, ERROR,
|
||||
|
@ -1158,7 +1157,7 @@ done:
|
|||
if (err == -1)
|
||||
mwifiex_write_data_complete(adapter, skb_send, 0, -1);
|
||||
unlock:
|
||||
spin_unlock_irqrestore(&port->tx_aggr_lock, flags);
|
||||
spin_unlock_bh(&port->tx_aggr_lock);
|
||||
}
|
||||
|
||||
/* This function write a command/data packet to card. */
|
||||
|
@ -1169,7 +1168,6 @@ static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep,
|
|||
struct usb_card_rec *card = adapter->card;
|
||||
struct urb_context *context = NULL;
|
||||
struct usb_tx_data_port *port = NULL;
|
||||
unsigned long flags;
|
||||
int idx, ret;
|
||||
|
||||
if (test_bit(MWIFIEX_IS_SUSPENDED, &adapter->work_flags)) {
|
||||
|
@ -1211,10 +1209,10 @@ static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep,
|
|||
}
|
||||
|
||||
if (adapter->bus_aggr.enable) {
|
||||
spin_lock_irqsave(&port->tx_aggr_lock, flags);
|
||||
spin_lock_bh(&port->tx_aggr_lock);
|
||||
ret = mwifiex_usb_aggr_tx_data(adapter, ep, skb,
|
||||
tx_param, port);
|
||||
spin_unlock_irqrestore(&port->tx_aggr_lock, flags);
|
||||
spin_unlock_bh(&port->tx_aggr_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -607,12 +607,11 @@ struct mwifiex_sta_node *
|
|||
mwifiex_add_sta_entry(struct mwifiex_private *priv, const u8 *mac)
|
||||
{
|
||||
struct mwifiex_sta_node *node;
|
||||
unsigned long flags;
|
||||
|
||||
if (!mac)
|
||||
return NULL;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_list_spinlock, flags);
|
||||
spin_lock_bh(&priv->sta_list_spinlock);
|
||||
node = mwifiex_get_sta_entry(priv, mac);
|
||||
if (node)
|
||||
goto done;
|
||||
|
@ -625,7 +624,7 @@ mwifiex_add_sta_entry(struct mwifiex_private *priv, const u8 *mac)
|
|||
list_add_tail(&node->list, &priv->sta_list);
|
||||
|
||||
done:
|
||||
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
|
||||
spin_unlock_bh(&priv->sta_list_spinlock);
|
||||
return node;
|
||||
}
|
||||
|
||||
|
@ -662,9 +661,8 @@ mwifiex_set_sta_ht_cap(struct mwifiex_private *priv, const u8 *ies,
|
|||
void mwifiex_del_sta_entry(struct mwifiex_private *priv, const u8 *mac)
|
||||
{
|
||||
struct mwifiex_sta_node *node;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_list_spinlock, flags);
|
||||
spin_lock_bh(&priv->sta_list_spinlock);
|
||||
|
||||
node = mwifiex_get_sta_entry(priv, mac);
|
||||
if (node) {
|
||||
|
@ -672,7 +670,7 @@ void mwifiex_del_sta_entry(struct mwifiex_private *priv, const u8 *mac)
|
|||
kfree(node);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
|
||||
spin_unlock_bh(&priv->sta_list_spinlock);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -680,9 +678,8 @@ void mwifiex_del_sta_entry(struct mwifiex_private *priv, const u8 *mac)
|
|||
void mwifiex_del_all_sta_list(struct mwifiex_private *priv)
|
||||
{
|
||||
struct mwifiex_sta_node *node, *tmp;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_list_spinlock, flags);
|
||||
spin_lock_bh(&priv->sta_list_spinlock);
|
||||
|
||||
list_for_each_entry_safe(node, tmp, &priv->sta_list, list) {
|
||||
list_del(&node->list);
|
||||
|
@ -690,7 +687,7 @@ void mwifiex_del_all_sta_list(struct mwifiex_private *priv)
|
|||
}
|
||||
|
||||
INIT_LIST_HEAD(&priv->sta_list);
|
||||
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
|
||||
spin_unlock_bh(&priv->sta_list_spinlock);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -138,7 +138,6 @@ void mwifiex_ralist_add(struct mwifiex_private *priv, const u8 *ra)
|
|||
struct mwifiex_ra_list_tbl *ra_list;
|
||||
struct mwifiex_adapter *adapter = priv->adapter;
|
||||
struct mwifiex_sta_node *node;
|
||||
unsigned long flags;
|
||||
|
||||
|
||||
for (i = 0; i < MAX_NUM_TID; ++i) {
|
||||
|
@ -163,7 +162,7 @@ void mwifiex_ralist_add(struct mwifiex_private *priv, const u8 *ra)
|
|||
ra_list->is_11n_enabled = IS_11N_ENABLED(priv);
|
||||
}
|
||||
} else {
|
||||
spin_lock_irqsave(&priv->sta_list_spinlock, flags);
|
||||
spin_lock_bh(&priv->sta_list_spinlock);
|
||||
node = mwifiex_get_sta_entry(priv, ra);
|
||||
if (node)
|
||||
ra_list->tx_paused = node->tx_pause;
|
||||
|
@ -171,7 +170,7 @@ void mwifiex_ralist_add(struct mwifiex_private *priv, const u8 *ra)
|
|||
mwifiex_is_sta_11n_enabled(priv, node);
|
||||
if (ra_list->is_11n_enabled)
|
||||
ra_list->max_amsdu = node->max_amsdu;
|
||||
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
|
||||
spin_unlock_bh(&priv->sta_list_spinlock);
|
||||
}
|
||||
|
||||
mwifiex_dbg(adapter, DATA, "data: ralist %p: is_11n_enabled=%d\n",
|
||||
|
@ -583,11 +582,10 @@ static int mwifiex_free_ack_frame(int id, void *p, void *data)
|
|||
void
|
||||
mwifiex_clean_txrx(struct mwifiex_private *priv)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct sk_buff *skb, *tmp;
|
||||
|
||||
mwifiex_11n_cleanup_reorder_tbl(priv);
|
||||
spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
|
||||
spin_lock_bh(&priv->wmm.ra_list_spinlock);
|
||||
|
||||
mwifiex_wmm_cleanup_queues(priv);
|
||||
mwifiex_11n_delete_all_tx_ba_stream_tbl(priv);
|
||||
|
@ -601,7 +599,7 @@ mwifiex_clean_txrx(struct mwifiex_private *priv)
|
|||
if (priv->adapter->if_ops.clean_pcie_ring &&
|
||||
!test_bit(MWIFIEX_SURPRISE_REMOVED, &priv->adapter->work_flags))
|
||||
priv->adapter->if_ops.clean_pcie_ring(priv->adapter);
|
||||
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
|
||||
spin_unlock_bh(&priv->wmm.ra_list_spinlock);
|
||||
|
||||
skb_queue_walk_safe(&priv->tdls_txq, skb, tmp) {
|
||||
skb_unlink(skb, &priv->tdls_txq);
|
||||
|
@ -642,10 +640,9 @@ void mwifiex_update_ralist_tx_pause(struct mwifiex_private *priv, u8 *mac,
|
|||
{
|
||||
struct mwifiex_ra_list_tbl *ra_list;
|
||||
u32 pkt_cnt = 0, tx_pkts_queued;
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
|
||||
spin_lock_bh(&priv->wmm.ra_list_spinlock);
|
||||
|
||||
for (i = 0; i < MAX_NUM_TID; ++i) {
|
||||
ra_list = mwifiex_wmm_get_ralist_node(priv, i, mac);
|
||||
|
@ -671,7 +668,7 @@ void mwifiex_update_ralist_tx_pause(struct mwifiex_private *priv, u8 *mac,
|
|||
atomic_set(&priv->wmm.tx_pkts_queued, tx_pkts_queued);
|
||||
atomic_set(&priv->wmm.highest_queued_prio, HIGH_PRIO_TID);
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
|
||||
spin_unlock_bh(&priv->wmm.ra_list_spinlock);
|
||||
}
|
||||
|
||||
/* This function updates non-tdls peer ralist tx_pause while
|
||||
|
@ -682,10 +679,9 @@ void mwifiex_update_ralist_tx_pause_in_tdls_cs(struct mwifiex_private *priv,
|
|||
{
|
||||
struct mwifiex_ra_list_tbl *ra_list;
|
||||
u32 pkt_cnt = 0, tx_pkts_queued;
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
|
||||
spin_lock_bh(&priv->wmm.ra_list_spinlock);
|
||||
|
||||
for (i = 0; i < MAX_NUM_TID; ++i) {
|
||||
list_for_each_entry(ra_list, &priv->wmm.tid_tbl_ptr[i].ra_list,
|
||||
|
@ -716,7 +712,7 @@ void mwifiex_update_ralist_tx_pause_in_tdls_cs(struct mwifiex_private *priv,
|
|||
atomic_set(&priv->wmm.tx_pkts_queued, tx_pkts_queued);
|
||||
atomic_set(&priv->wmm.highest_queued_prio, HIGH_PRIO_TID);
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
|
||||
spin_unlock_bh(&priv->wmm.ra_list_spinlock);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -748,10 +744,9 @@ void
|
|||
mwifiex_wmm_del_peer_ra_list(struct mwifiex_private *priv, const u8 *ra_addr)
|
||||
{
|
||||
struct mwifiex_ra_list_tbl *ra_list;
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
|
||||
spin_lock_bh(&priv->wmm.ra_list_spinlock);
|
||||
|
||||
for (i = 0; i < MAX_NUM_TID; ++i) {
|
||||
ra_list = mwifiex_wmm_get_ralist_node(priv, i, ra_addr);
|
||||
|
@ -767,7 +762,7 @@ mwifiex_wmm_del_peer_ra_list(struct mwifiex_private *priv, const u8 *ra_addr)
|
|||
list_del(&ra_list->list);
|
||||
kfree(ra_list);
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
|
||||
spin_unlock_bh(&priv->wmm.ra_list_spinlock);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -818,7 +813,6 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv,
|
|||
u32 tid;
|
||||
struct mwifiex_ra_list_tbl *ra_list;
|
||||
u8 ra[ETH_ALEN], tid_down;
|
||||
unsigned long flags;
|
||||
struct list_head list_head;
|
||||
int tdls_status = TDLS_NOT_SETUP;
|
||||
struct ethhdr *eth_hdr = (struct ethhdr *)skb->data;
|
||||
|
@ -844,7 +838,7 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv,
|
|||
|
||||
tid = skb->priority;
|
||||
|
||||
spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
|
||||
spin_lock_bh(&priv->wmm.ra_list_spinlock);
|
||||
|
||||
tid_down = mwifiex_wmm_downgrade_tid(priv, tid);
|
||||
|
||||
|
@ -864,8 +858,7 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv,
|
|||
break;
|
||||
case TDLS_SETUP_INPROGRESS:
|
||||
skb_queue_tail(&priv->tdls_txq, skb);
|
||||
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
|
||||
flags);
|
||||
spin_unlock_bh(&priv->wmm.ra_list_spinlock);
|
||||
return;
|
||||
default:
|
||||
list_head = priv->wmm.tid_tbl_ptr[tid_down].ra_list;
|
||||
|
@ -881,7 +874,7 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv,
|
|||
}
|
||||
|
||||
if (!ra_list) {
|
||||
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
|
||||
spin_unlock_bh(&priv->wmm.ra_list_spinlock);
|
||||
mwifiex_write_data_complete(adapter, skb, 0, -1);
|
||||
return;
|
||||
}
|
||||
|
@ -901,7 +894,7 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv,
|
|||
else
|
||||
atomic_inc(&priv->wmm.tx_pkts_queued);
|
||||
|
||||
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
|
||||
spin_unlock_bh(&priv->wmm.ra_list_spinlock);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1092,7 +1085,6 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter,
|
|||
struct mwifiex_ra_list_tbl *ptr;
|
||||
struct mwifiex_tid_tbl *tid_ptr;
|
||||
atomic_t *hqp;
|
||||
unsigned long flags_ra;
|
||||
int i, j;
|
||||
|
||||
/* check the BSS with highest priority first */
|
||||
|
@ -1118,8 +1110,7 @@ try_again:
|
|||
hqp = &priv_tmp->wmm.highest_queued_prio;
|
||||
for (i = atomic_read(hqp); i >= LOW_PRIO_TID; --i) {
|
||||
|
||||
spin_lock_irqsave(&priv_tmp->wmm.
|
||||
ra_list_spinlock, flags_ra);
|
||||
spin_lock_bh(&priv_tmp->wmm.ra_list_spinlock);
|
||||
|
||||
tid_ptr = &(priv_tmp)->wmm.
|
||||
tid_tbl_ptr[tos_to_tid[i]];
|
||||
|
@ -1134,9 +1125,7 @@ try_again:
|
|||
goto found;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&priv_tmp->wmm.
|
||||
ra_list_spinlock,
|
||||
flags_ra);
|
||||
spin_unlock_bh(&priv_tmp->wmm.ra_list_spinlock);
|
||||
}
|
||||
|
||||
if (atomic_read(&priv_tmp->wmm.tx_pkts_queued) != 0) {
|
||||
|
@ -1158,7 +1147,7 @@ found:
|
|||
/* holds ra_list_spinlock */
|
||||
if (atomic_read(hqp) > i)
|
||||
atomic_set(hqp, i);
|
||||
spin_unlock_irqrestore(&priv_tmp->wmm.ra_list_spinlock, flags_ra);
|
||||
spin_unlock_bh(&priv_tmp->wmm.ra_list_spinlock);
|
||||
|
||||
*priv = priv_tmp;
|
||||
*tid = tos_to_tid[i];
|
||||
|
@ -1182,24 +1171,23 @@ void mwifiex_rotate_priolists(struct mwifiex_private *priv,
|
|||
struct mwifiex_adapter *adapter = priv->adapter;
|
||||
struct mwifiex_bss_prio_tbl *tbl = adapter->bss_prio_tbl;
|
||||
struct mwifiex_tid_tbl *tid_ptr = &priv->wmm.tid_tbl_ptr[tid];
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&tbl[priv->bss_priority].bss_prio_lock, flags);
|
||||
spin_lock_bh(&tbl[priv->bss_priority].bss_prio_lock);
|
||||
/*
|
||||
* dirty trick: we remove 'head' temporarily and reinsert it after
|
||||
* curr bss node. imagine list to stay fixed while head is moved
|
||||
*/
|
||||
list_move(&tbl[priv->bss_priority].bss_prio_head,
|
||||
&tbl[priv->bss_priority].bss_prio_cur->list);
|
||||
spin_unlock_irqrestore(&tbl[priv->bss_priority].bss_prio_lock, flags);
|
||||
spin_unlock_bh(&tbl[priv->bss_priority].bss_prio_lock);
|
||||
|
||||
spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
|
||||
spin_lock_bh(&priv->wmm.ra_list_spinlock);
|
||||
if (mwifiex_is_ralist_valid(priv, ra, tid)) {
|
||||
priv->wmm.packets_out[tid]++;
|
||||
/* same as above */
|
||||
list_move(&tid_ptr->ra_list, &ra->list);
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
|
||||
spin_unlock_bh(&priv->wmm.ra_list_spinlock);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1236,8 +1224,7 @@ mwifiex_is_11n_aggragation_possible(struct mwifiex_private *priv,
|
|||
*/
|
||||
static void
|
||||
mwifiex_send_single_packet(struct mwifiex_private *priv,
|
||||
struct mwifiex_ra_list_tbl *ptr, int ptr_index,
|
||||
unsigned long ra_list_flags)
|
||||
struct mwifiex_ra_list_tbl *ptr, int ptr_index)
|
||||
__releases(&priv->wmm.ra_list_spinlock)
|
||||
{
|
||||
struct sk_buff *skb, *skb_next;
|
||||
|
@ -1246,8 +1233,7 @@ mwifiex_send_single_packet(struct mwifiex_private *priv,
|
|||
struct mwifiex_txinfo *tx_info;
|
||||
|
||||
if (skb_queue_empty(&ptr->skb_head)) {
|
||||
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
|
||||
ra_list_flags);
|
||||
spin_unlock_bh(&priv->wmm.ra_list_spinlock);
|
||||
mwifiex_dbg(adapter, DATA, "data: nothing to send\n");
|
||||
return;
|
||||
}
|
||||
|
@ -1265,18 +1251,17 @@ mwifiex_send_single_packet(struct mwifiex_private *priv,
|
|||
else
|
||||
skb_next = NULL;
|
||||
|
||||
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags);
|
||||
spin_unlock_bh(&priv->wmm.ra_list_spinlock);
|
||||
|
||||
tx_param.next_pkt_len = ((skb_next) ? skb_next->len +
|
||||
sizeof(struct txpd) : 0);
|
||||
|
||||
if (mwifiex_process_tx(priv, skb, &tx_param) == -EBUSY) {
|
||||
/* Queue the packet back at the head */
|
||||
spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags);
|
||||
spin_lock_bh(&priv->wmm.ra_list_spinlock);
|
||||
|
||||
if (!mwifiex_is_ralist_valid(priv, ptr, ptr_index)) {
|
||||
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
|
||||
ra_list_flags);
|
||||
spin_unlock_bh(&priv->wmm.ra_list_spinlock);
|
||||
mwifiex_write_data_complete(adapter, skb, 0, -1);
|
||||
return;
|
||||
}
|
||||
|
@ -1286,8 +1271,7 @@ mwifiex_send_single_packet(struct mwifiex_private *priv,
|
|||
ptr->total_pkt_count++;
|
||||
ptr->ba_pkt_count++;
|
||||
tx_info->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT;
|
||||
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
|
||||
ra_list_flags);
|
||||
spin_unlock_bh(&priv->wmm.ra_list_spinlock);
|
||||
} else {
|
||||
mwifiex_rotate_priolists(priv, ptr, ptr_index);
|
||||
atomic_dec(&priv->wmm.tx_pkts_queued);
|
||||
|
@ -1323,8 +1307,7 @@ mwifiex_is_ptr_processed(struct mwifiex_private *priv,
|
|||
*/
|
||||
static void
|
||||
mwifiex_send_processed_packet(struct mwifiex_private *priv,
|
||||
struct mwifiex_ra_list_tbl *ptr, int ptr_index,
|
||||
unsigned long ra_list_flags)
|
||||
struct mwifiex_ra_list_tbl *ptr, int ptr_index)
|
||||
__releases(&priv->wmm.ra_list_spinlock)
|
||||
{
|
||||
struct mwifiex_tx_param tx_param;
|
||||
|
@ -1334,8 +1317,7 @@ mwifiex_send_processed_packet(struct mwifiex_private *priv,
|
|||
struct mwifiex_txinfo *tx_info;
|
||||
|
||||
if (skb_queue_empty(&ptr->skb_head)) {
|
||||
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
|
||||
ra_list_flags);
|
||||
spin_unlock_bh(&priv->wmm.ra_list_spinlock);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1343,8 +1325,7 @@ mwifiex_send_processed_packet(struct mwifiex_private *priv,
|
|||
|
||||
if (adapter->data_sent || adapter->tx_lock_flag) {
|
||||
ptr->total_pkt_count--;
|
||||
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
|
||||
ra_list_flags);
|
||||
spin_unlock_bh(&priv->wmm.ra_list_spinlock);
|
||||
skb_queue_tail(&adapter->tx_data_q, skb);
|
||||
atomic_dec(&priv->wmm.tx_pkts_queued);
|
||||
atomic_inc(&adapter->tx_queued);
|
||||
|
@ -1358,7 +1339,7 @@ mwifiex_send_processed_packet(struct mwifiex_private *priv,
|
|||
|
||||
tx_info = MWIFIEX_SKB_TXCB(skb);
|
||||
|
||||
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags);
|
||||
spin_unlock_bh(&priv->wmm.ra_list_spinlock);
|
||||
|
||||
tx_param.next_pkt_len =
|
||||
((skb_next) ? skb_next->len +
|
||||
|
@ -1374,11 +1355,10 @@ mwifiex_send_processed_packet(struct mwifiex_private *priv,
|
|||
switch (ret) {
|
||||
case -EBUSY:
|
||||
mwifiex_dbg(adapter, ERROR, "data: -EBUSY is returned\n");
|
||||
spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags);
|
||||
spin_lock_bh(&priv->wmm.ra_list_spinlock);
|
||||
|
||||
if (!mwifiex_is_ralist_valid(priv, ptr, ptr_index)) {
|
||||
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
|
||||
ra_list_flags);
|
||||
spin_unlock_bh(&priv->wmm.ra_list_spinlock);
|
||||
mwifiex_write_data_complete(adapter, skb, 0, -1);
|
||||
return;
|
||||
}
|
||||
|
@ -1386,8 +1366,7 @@ mwifiex_send_processed_packet(struct mwifiex_private *priv,
|
|||
skb_queue_tail(&ptr->skb_head, skb);
|
||||
|
||||
tx_info->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT;
|
||||
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
|
||||
ra_list_flags);
|
||||
spin_unlock_bh(&priv->wmm.ra_list_spinlock);
|
||||
break;
|
||||
case -1:
|
||||
mwifiex_dbg(adapter, ERROR, "host_to_card failed: %#x\n", ret);
|
||||
|
@ -1404,10 +1383,9 @@ mwifiex_send_processed_packet(struct mwifiex_private *priv,
|
|||
if (ret != -EBUSY) {
|
||||
mwifiex_rotate_priolists(priv, ptr, ptr_index);
|
||||
atomic_dec(&priv->wmm.tx_pkts_queued);
|
||||
spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags);
|
||||
spin_lock_bh(&priv->wmm.ra_list_spinlock);
|
||||
ptr->total_pkt_count--;
|
||||
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
|
||||
ra_list_flags);
|
||||
spin_unlock_bh(&priv->wmm.ra_list_spinlock);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1423,7 +1401,6 @@ mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter)
|
|||
int ptr_index = 0;
|
||||
u8 ra[ETH_ALEN];
|
||||
int tid_del = 0, tid = 0;
|
||||
unsigned long flags;
|
||||
|
||||
ptr = mwifiex_wmm_get_highest_priolist_ptr(adapter, &priv, &ptr_index);
|
||||
if (!ptr)
|
||||
|
@ -1433,14 +1410,14 @@ mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter)
|
|||
|
||||
mwifiex_dbg(adapter, DATA, "data: tid=%d\n", tid);
|
||||
|
||||
spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
|
||||
spin_lock_bh(&priv->wmm.ra_list_spinlock);
|
||||
if (!mwifiex_is_ralist_valid(priv, ptr, ptr_index)) {
|
||||
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
|
||||
spin_unlock_bh(&priv->wmm.ra_list_spinlock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mwifiex_is_ptr_processed(priv, ptr)) {
|
||||
mwifiex_send_processed_packet(priv, ptr, ptr_index, flags);
|
||||
mwifiex_send_processed_packet(priv, ptr, ptr_index);
|
||||
/* ra_list_spinlock has been freed in
|
||||
mwifiex_send_processed_packet() */
|
||||
return 0;
|
||||
|
@ -1455,12 +1432,12 @@ mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter)
|
|||
mwifiex_is_amsdu_allowed(priv, tid) &&
|
||||
mwifiex_is_11n_aggragation_possible(priv, ptr,
|
||||
adapter->tx_buf_size))
|
||||
mwifiex_11n_aggregate_pkt(priv, ptr, ptr_index, flags);
|
||||
mwifiex_11n_aggregate_pkt(priv, ptr, ptr_index);
|
||||
/* ra_list_spinlock has been freed in
|
||||
* mwifiex_11n_aggregate_pkt()
|
||||
*/
|
||||
else
|
||||
mwifiex_send_single_packet(priv, ptr, ptr_index, flags);
|
||||
mwifiex_send_single_packet(priv, ptr, ptr_index);
|
||||
/* ra_list_spinlock has been freed in
|
||||
* mwifiex_send_single_packet()
|
||||
*/
|
||||
|
@ -1481,11 +1458,11 @@ mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter)
|
|||
if (mwifiex_is_amsdu_allowed(priv, tid) &&
|
||||
mwifiex_is_11n_aggragation_possible(priv, ptr,
|
||||
adapter->tx_buf_size))
|
||||
mwifiex_11n_aggregate_pkt(priv, ptr, ptr_index, flags);
|
||||
mwifiex_11n_aggregate_pkt(priv, ptr, ptr_index);
|
||||
/* ra_list_spinlock has been freed in
|
||||
mwifiex_11n_aggregate_pkt() */
|
||||
else
|
||||
mwifiex_send_single_packet(priv, ptr, ptr_index, flags);
|
||||
mwifiex_send_single_packet(priv, ptr, ptr_index);
|
||||
/* ra_list_spinlock has been freed in
|
||||
mwifiex_send_single_packet() */
|
||||
}
|
||||
|
|
|
@ -588,6 +588,7 @@ void mt76_dma_cleanup(struct mt76_dev *dev)
|
|||
{
|
||||
int i;
|
||||
|
||||
netif_napi_del(&dev->tx_napi);
|
||||
for (i = 0; i < ARRAY_SIZE(dev->q_tx); i++)
|
||||
mt76_dma_tx_cleanup(dev, i, true);
|
||||
|
||||
|
|
|
@ -766,10 +766,21 @@ int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|||
*dbm = DIV_ROUND_UP(dev->txpower_cur, 2);
|
||||
|
||||
/* convert from per-chain power to combined
|
||||
* output on 2x2 devices
|
||||
* output power
|
||||
*/
|
||||
if (n_chains > 1)
|
||||
switch (n_chains) {
|
||||
case 4:
|
||||
*dbm += 6;
|
||||
break;
|
||||
case 3:
|
||||
*dbm += 4;
|
||||
break;
|
||||
case 2:
|
||||
*dbm += 3;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -820,3 +831,50 @@ mt76_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set)
|
|||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_set_tim);
|
||||
|
||||
void mt76_insert_ccmp_hdr(struct sk_buff *skb, u8 key_id)
|
||||
{
|
||||
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
|
||||
int hdr_len = ieee80211_get_hdrlen_from_skb(skb);
|
||||
u8 *hdr, *pn = status->iv;
|
||||
|
||||
__skb_push(skb, 8);
|
||||
memmove(skb->data, skb->data + 8, hdr_len);
|
||||
hdr = skb->data + hdr_len;
|
||||
|
||||
hdr[0] = pn[5];
|
||||
hdr[1] = pn[4];
|
||||
hdr[2] = 0;
|
||||
hdr[3] = 0x20 | (key_id << 6);
|
||||
hdr[4] = pn[3];
|
||||
hdr[5] = pn[2];
|
||||
hdr[6] = pn[1];
|
||||
hdr[7] = pn[0];
|
||||
|
||||
status->flag &= ~RX_FLAG_IV_STRIPPED;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_insert_ccmp_hdr);
|
||||
|
||||
int mt76_get_rate(struct mt76_dev *dev,
|
||||
struct ieee80211_supported_band *sband,
|
||||
int idx, bool cck)
|
||||
{
|
||||
int i, offset = 0, len = sband->n_bitrates;
|
||||
|
||||
if (cck) {
|
||||
if (sband == &dev->sband_5g.sband)
|
||||
return 0;
|
||||
|
||||
idx &= ~BIT(2); /* short preamble */
|
||||
} else if (sband == &dev->sband_2g.sband) {
|
||||
offset = 4;
|
||||
}
|
||||
|
||||
for (i = offset; i < len; i++) {
|
||||
if ((sband->bitrates[i].hw_value & GENMASK(7, 0)) == idx)
|
||||
return i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_get_rate);
|
||||
|
|
|
@ -258,10 +258,11 @@ struct mt76_rx_tid {
|
|||
#define MT_TX_CB_TXS_DONE BIT(1)
|
||||
#define MT_TX_CB_TXS_FAILED BIT(2)
|
||||
|
||||
#define MT_PACKET_ID_MASK GENMASK(7, 0)
|
||||
#define MT_PACKET_ID_MASK GENMASK(6, 0)
|
||||
#define MT_PACKET_ID_NO_ACK 0
|
||||
#define MT_PACKET_ID_NO_SKB 1
|
||||
#define MT_PACKET_ID_FIRST 2
|
||||
#define MT_PACKET_ID_HAS_RATE BIT(7)
|
||||
|
||||
#define MT_TX_STATUS_SKB_TIMEOUT HZ
|
||||
|
||||
|
@ -381,7 +382,8 @@ enum mt76u_out_ep {
|
|||
__MT_EP_OUT_MAX,
|
||||
};
|
||||
|
||||
#define MT_SG_MAX_SIZE 8
|
||||
#define MT_TX_SG_MAX_SIZE 8
|
||||
#define MT_RX_SG_MAX_SIZE 1
|
||||
#define MT_NUM_TX_ENTRIES 256
|
||||
#define MT_NUM_RX_ENTRIES 128
|
||||
#define MCU_RESP_URB_SIZE 1024
|
||||
|
@ -393,9 +395,7 @@ struct mt76_usb {
|
|||
struct delayed_work stat_work;
|
||||
|
||||
u8 out_ep[__MT_EP_OUT_MAX];
|
||||
u16 out_max_packet;
|
||||
u8 in_ep[__MT_EP_IN_MAX];
|
||||
u16 in_max_packet;
|
||||
bool sg_en;
|
||||
|
||||
struct mt76u_mcu {
|
||||
|
@ -452,6 +452,7 @@ struct mt76_dev {
|
|||
int tx_dma_idx[4];
|
||||
|
||||
struct tasklet_struct tx_tasklet;
|
||||
struct napi_struct tx_napi;
|
||||
struct delayed_work mac_work;
|
||||
|
||||
wait_queue_head_t tx_wait;
|
||||
|
@ -483,6 +484,8 @@ struct mt76_dev {
|
|||
int txpower_conf;
|
||||
int txpower_cur;
|
||||
|
||||
enum nl80211_dfs_regions region;
|
||||
|
||||
u32 debugfs_reg;
|
||||
|
||||
struct led_classdev led_cdev;
|
||||
|
@ -688,6 +691,14 @@ static inline void mt76_insert_hdr_pad(struct sk_buff *skb)
|
|||
skb->data[len + 1] = 0;
|
||||
}
|
||||
|
||||
static inline bool mt76_is_skb_pktid(u8 pktid)
|
||||
{
|
||||
if (pktid & MT_PACKET_ID_HAS_RATE)
|
||||
return false;
|
||||
|
||||
return pktid >= MT_PACKET_ID_FIRST;
|
||||
}
|
||||
|
||||
void mt76_rx(struct mt76_dev *dev, enum mt76_rxq_id q, struct sk_buff *skb);
|
||||
void mt76_tx(struct mt76_dev *dev, struct ieee80211_sta *sta,
|
||||
struct mt76_wcid *wcid, struct sk_buff *skb);
|
||||
|
@ -749,6 +760,10 @@ void mt76_csa_check(struct mt76_dev *dev);
|
|||
void mt76_csa_finish(struct mt76_dev *dev);
|
||||
|
||||
int mt76_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set);
|
||||
void mt76_insert_ccmp_hdr(struct sk_buff *skb, u8 key_id);
|
||||
int mt76_get_rate(struct mt76_dev *dev,
|
||||
struct ieee80211_supported_band *sband,
|
||||
int idx, bool cck);
|
||||
|
||||
/* internal */
|
||||
void mt76_tx_free(struct mt76_dev *dev);
|
||||
|
|
|
@ -35,7 +35,7 @@ irqreturn_t mt7603_irq_handler(int irq, void *dev_instance)
|
|||
|
||||
if (intr & MT_INT_TX_DONE_ALL) {
|
||||
mt7603_irq_disable(dev, MT_INT_TX_DONE_ALL);
|
||||
tasklet_schedule(&dev->mt76.tx_tasklet);
|
||||
napi_schedule(&dev->mt76.tx_napi);
|
||||
}
|
||||
|
||||
if (intr & MT_INT_RX_DONE(0)) {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue