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:
Kalle Valo 2019-07-01 22:23:11 +03:00
commit 5adcdab6ae
39 changed files with 833 additions and 228 deletions

View File

@ -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);

View File

@ -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 *));

View File

@ -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;

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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) {

View File

@ -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,

View File

@ -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

View File

@ -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)

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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 */

View File

@ -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[] = {

View File

@ -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,

View File

@ -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);

View File

@ -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");

View File

@ -7,3 +7,4 @@
#define CREATE_TRACE_POINTS
#include "trace.h"
EXPORT_SYMBOL(__tracepoint_ath10k_log_dbg);

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -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);

View File

@ -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,

View File

@ -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

View File

@ -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);

View File

@ -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;
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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

View File

@ -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__ */

View File

@ -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,
};

View File

@ -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__ */