mirror of
https://github.com/torvalds/linux.git
synced 2024-12-22 02:52:56 +00:00
Merge ath-next from git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
ath.git patches for 5.3. Major changes: ath10k * fixes for SDIO support * add support for firmware logging via WMI
This commit is contained in:
commit
5adcdab6ae
@ -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__ */
|
||||
|
Loading…
Reference in New Issue
Block a user