mirror of
https://github.com/torvalds/linux.git
synced 2026-05-31 18:43:33 +02:00
Merge ath-next from git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
ath.git patches for 4.19. Major changes: ath10k * add debugfs file warm_hw_reset wil6210 * add debugfs files tx_latency, link_stats and link_stats_global * add 3-MSI support * allow scan on AP interface * support max aggregation window size 64
This commit is contained in:
commit
33c740411a
|
|
@ -133,11 +133,8 @@ static void ath10k_ahb_clock_deinit(struct ath10k *ar)
|
|||
static int ath10k_ahb_clock_enable(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);
|
||||
struct device *dev;
|
||||
int ret;
|
||||
|
||||
dev = &ar_ahb->pdev->dev;
|
||||
|
||||
if (IS_ERR_OR_NULL(ar_ahb->cmd_clk) ||
|
||||
IS_ERR_OR_NULL(ar_ahb->ref_clk) ||
|
||||
IS_ERR_OR_NULL(ar_ahb->rtc_clk)) {
|
||||
|
|
@ -451,12 +448,10 @@ static int ath10k_ahb_resource_init(struct ath10k *ar)
|
|||
{
|
||||
struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);
|
||||
struct platform_device *pdev;
|
||||
struct device *dev;
|
||||
struct resource *res;
|
||||
int ret;
|
||||
|
||||
pdev = ar_ahb->pdev;
|
||||
dev = &pdev->dev;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
|
|
|
|||
|
|
@ -2095,6 +2095,7 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
|
|||
ar->fw_stats_req_mask = WMI_STAT_PDEV | WMI_STAT_VDEV |
|
||||
WMI_STAT_PEER;
|
||||
ar->max_spatial_stream = WMI_MAX_SPATIAL_STREAM;
|
||||
ar->wmi.mgmt_max_num_pending_tx = TARGET_TLV_MGMT_NUM_MSDU_DESC;
|
||||
break;
|
||||
case ATH10K_FW_WMI_OP_VERSION_10_4:
|
||||
ar->max_num_peers = TARGET_10_4_NUM_PEERS;
|
||||
|
|
|
|||
|
|
@ -186,6 +186,11 @@ struct ath10k_wmi {
|
|||
const struct wmi_ops *ops;
|
||||
const struct wmi_peer_flags_map *peer_flags;
|
||||
|
||||
u32 mgmt_max_num_pending_tx;
|
||||
|
||||
/* Protected by data_lock */
|
||||
struct idr mgmt_pending_tx;
|
||||
|
||||
u32 num_mem_chunks;
|
||||
u32 rx_decap_mode;
|
||||
struct ath10k_mem_chunk mem_chunks[WMI_MAX_MEM_REQS];
|
||||
|
|
|
|||
|
|
@ -2297,6 +2297,52 @@ static const struct file_operations fops_tpc_stats_final = {
|
|||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static ssize_t ath10k_write_warm_hw_reset(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath10k *ar = file->private_data;
|
||||
int ret;
|
||||
bool val;
|
||||
|
||||
if (kstrtobool_from_user(user_buf, count, &val))
|
||||
return -EFAULT;
|
||||
|
||||
if (!val)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
if (ar->state != ATH10K_STATE_ON) {
|
||||
ret = -ENETDOWN;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (!(test_bit(WMI_SERVICE_RESET_CHIP, ar->wmi.svc_map)))
|
||||
ath10k_warn(ar, "wmi service for reset chip is not available\n");
|
||||
|
||||
ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->pdev_reset,
|
||||
WMI_RST_MODE_WARM_RESET);
|
||||
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to enable warm hw reset: %d\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = count;
|
||||
|
||||
exit:
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct file_operations fops_warm_hw_reset = {
|
||||
.write = ath10k_write_warm_hw_reset,
|
||||
.open = simple_open,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
int ath10k_debug_create(struct ath10k *ar)
|
||||
{
|
||||
ar->debug.cal_data = vzalloc(ATH10K_DEBUG_CAL_DATA_LEN);
|
||||
|
|
@ -2425,6 +2471,9 @@ int ath10k_debug_register(struct ath10k *ar)
|
|||
ar->debug.debugfs_phy, ar,
|
||||
&fops_tpc_stats_final);
|
||||
|
||||
debugfs_create_file("warm_hw_reset", 0600, ar->debug.debugfs_phy, ar,
|
||||
&fops_warm_hw_reset);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -208,10 +208,10 @@ int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt, struct sk_buff *skb)
|
|||
struct ath10k *ar = htt->ar;
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&htt->tx_lock);
|
||||
|
||||
spin_lock_bh(&htt->tx_lock);
|
||||
ret = idr_alloc(&htt->pending_tx, skb, 0,
|
||||
htt->max_num_pending_tx, GFP_ATOMIC);
|
||||
spin_unlock_bh(&htt->tx_lock);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_HTT, "htt tx alloc msdu_id %d\n", ret);
|
||||
|
||||
|
|
@ -1077,9 +1077,7 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
|
|||
len += sizeof(cmd->hdr);
|
||||
len += sizeof(cmd->mgmt_tx);
|
||||
|
||||
spin_lock_bh(&htt->tx_lock);
|
||||
res = ath10k_htt_tx_alloc_msdu_id(htt, msdu);
|
||||
spin_unlock_bh(&htt->tx_lock);
|
||||
if (res < 0)
|
||||
goto err;
|
||||
|
||||
|
|
@ -1161,9 +1159,7 @@ static int ath10k_htt_tx_32(struct ath10k_htt *htt,
|
|||
struct htt_msdu_ext_desc *ext_desc = NULL;
|
||||
struct htt_msdu_ext_desc *ext_desc_t = NULL;
|
||||
|
||||
spin_lock_bh(&htt->tx_lock);
|
||||
res = ath10k_htt_tx_alloc_msdu_id(htt, msdu);
|
||||
spin_unlock_bh(&htt->tx_lock);
|
||||
if (res < 0)
|
||||
goto err;
|
||||
|
||||
|
|
@ -1363,9 +1359,7 @@ static int ath10k_htt_tx_64(struct ath10k_htt *htt,
|
|||
struct htt_msdu_ext_desc_64 *ext_desc = NULL;
|
||||
struct htt_msdu_ext_desc_64 *ext_desc_t = NULL;
|
||||
|
||||
spin_lock_bh(&htt->tx_lock);
|
||||
res = ath10k_htt_tx_alloc_msdu_id(htt, msdu);
|
||||
spin_unlock_bh(&htt->tx_lock);
|
||||
if (res < 0)
|
||||
goto err;
|
||||
|
||||
|
|
|
|||
|
|
@ -699,6 +699,7 @@ ath10k_rx_desc_get_l3_pad_bytes(struct ath10k_hw_params *hw,
|
|||
#define TARGET_TLV_NUM_TIDS ((TARGET_TLV_NUM_PEERS) * 2)
|
||||
#define TARGET_TLV_NUM_MSDU_DESC (1024 + 32)
|
||||
#define TARGET_TLV_NUM_WOW_PATTERNS 22
|
||||
#define TARGET_TLV_MGMT_NUM_MSDU_DESC (50)
|
||||
|
||||
/* Target specific defines for WMI-HL-1.0 firmware */
|
||||
#define TARGET_HL_10_TLV_NUM_PEERS 14
|
||||
|
|
|
|||
|
|
@ -101,6 +101,8 @@ static struct ieee80211_rate ath10k_rates_rev2[] = {
|
|||
#define ath10k_g_rates_rev2 (ath10k_rates_rev2 + 0)
|
||||
#define ath10k_g_rates_rev2_size (ARRAY_SIZE(ath10k_rates_rev2))
|
||||
|
||||
#define ath10k_wmi_legacy_rates ath10k_rates
|
||||
|
||||
static bool ath10k_mac_bitrate_is_cck(int bitrate)
|
||||
{
|
||||
switch (bitrate) {
|
||||
|
|
@ -3085,6 +3087,13 @@ static int ath10k_update_channel_list(struct ath10k *ar)
|
|||
passive = channel->flags & IEEE80211_CHAN_NO_IR;
|
||||
ch->passive = passive;
|
||||
|
||||
/* the firmware is ignoring the "radar" flag of the
|
||||
* channel and is scanning actively using Probe Requests
|
||||
* on "Radar detection"/DFS channels which are not
|
||||
* marked as "available"
|
||||
*/
|
||||
ch->passive |= ch->chan_radar;
|
||||
|
||||
ch->freq = channel->center_freq;
|
||||
ch->band_center_freq1 = channel->center_freq;
|
||||
ch->min_power = 0;
|
||||
|
|
@ -5439,8 +5448,12 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
|
|||
{
|
||||
struct ath10k *ar = hw->priv;
|
||||
struct ath10k_vif *arvif = (void *)vif->drv_priv;
|
||||
int ret = 0;
|
||||
struct cfg80211_chan_def def;
|
||||
u32 vdev_param, pdev_param, slottime, preamble;
|
||||
u16 bitrate, hw_value;
|
||||
u8 rate;
|
||||
int rateidx, ret = 0;
|
||||
enum nl80211_band band;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
|
|
@ -5608,6 +5621,44 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
|
|||
arvif->vdev_id, ret);
|
||||
}
|
||||
|
||||
if (changed & BSS_CHANGED_MCAST_RATE &&
|
||||
!WARN_ON(ath10k_mac_vif_chan(arvif->vif, &def))) {
|
||||
band = def.chan->band;
|
||||
rateidx = vif->bss_conf.mcast_rate[band] - 1;
|
||||
|
||||
if (ar->phy_capability & WHAL_WLAN_11A_CAPABILITY)
|
||||
rateidx += ATH10K_MAC_FIRST_OFDM_RATE_IDX;
|
||||
|
||||
bitrate = ath10k_wmi_legacy_rates[rateidx].bitrate;
|
||||
hw_value = ath10k_wmi_legacy_rates[rateidx].hw_value;
|
||||
if (ath10k_mac_bitrate_is_cck(bitrate))
|
||||
preamble = WMI_RATE_PREAMBLE_CCK;
|
||||
else
|
||||
preamble = WMI_RATE_PREAMBLE_OFDM;
|
||||
|
||||
rate = ATH10K_HW_RATECODE(hw_value, 0, preamble);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC,
|
||||
"mac vdev %d mcast_rate %x\n",
|
||||
arvif->vdev_id, rate);
|
||||
|
||||
vdev_param = ar->wmi.vdev_param->mcast_data_rate;
|
||||
ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id,
|
||||
vdev_param, rate);
|
||||
if (ret)
|
||||
ath10k_warn(ar,
|
||||
"failed to set mcast rate on vdev %i: %d\n",
|
||||
arvif->vdev_id, ret);
|
||||
|
||||
vdev_param = ar->wmi.vdev_param->bcast_data_rate;
|
||||
ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id,
|
||||
vdev_param, rate);
|
||||
if (ret)
|
||||
ath10k_warn(ar,
|
||||
"failed to set bcast rate on vdev %i: %d\n",
|
||||
arvif->vdev_id, ret);
|
||||
}
|
||||
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
}
|
||||
|
||||
|
|
@ -6063,13 +6114,13 @@ static void ath10k_sta_rc_update_wk(struct work_struct *wk)
|
|||
|
||||
mode = chan_to_phymode(&def);
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac update sta %pM peer bw %d phymode %d\n",
|
||||
sta->addr, bw, mode);
|
||||
sta->addr, bw, mode);
|
||||
|
||||
err = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr,
|
||||
WMI_PEER_PHYMODE, mode);
|
||||
WMI_PEER_PHYMODE, mode);
|
||||
if (err) {
|
||||
ath10k_warn(ar, "failed to update STA %pM peer phymode %d: %d\n",
|
||||
sta->addr, mode, err);
|
||||
sta->addr, mode, err);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
|
@ -6935,7 +6986,6 @@ ath10k_mac_bitrate_mask_get_single_rate(struct ath10k *ar,
|
|||
const struct cfg80211_bitrate_mask *mask,
|
||||
u8 *rate, u8 *nss)
|
||||
{
|
||||
struct ieee80211_supported_band *sband = &ar->mac.sbands[band];
|
||||
int rate_idx;
|
||||
int i;
|
||||
u16 bitrate;
|
||||
|
|
@ -6945,8 +6995,11 @@ ath10k_mac_bitrate_mask_get_single_rate(struct ath10k *ar,
|
|||
if (hweight32(mask->control[band].legacy) == 1) {
|
||||
rate_idx = ffs(mask->control[band].legacy) - 1;
|
||||
|
||||
hw_rate = sband->bitrates[rate_idx].hw_value;
|
||||
bitrate = sband->bitrates[rate_idx].bitrate;
|
||||
if (ar->phy_capability & WHAL_WLAN_11A_CAPABILITY)
|
||||
rate_idx += ATH10K_MAC_FIRST_OFDM_RATE_IDX;
|
||||
|
||||
hw_rate = ath10k_wmi_legacy_rates[rate_idx].hw_value;
|
||||
bitrate = ath10k_wmi_legacy_rates[rate_idx].bitrate;
|
||||
|
||||
if (ath10k_mac_bitrate_is_cck(bitrate))
|
||||
preamble = WMI_RATE_PREAMBLE_CCK;
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@ struct wmi_ops {
|
|||
struct wmi_scan_ev_arg *arg);
|
||||
int (*pull_mgmt_rx)(struct ath10k *ar, struct sk_buff *skb,
|
||||
struct wmi_mgmt_rx_ev_arg *arg);
|
||||
int (*pull_mgmt_tx_compl)(struct ath10k *ar, struct sk_buff *skb,
|
||||
struct wmi_tlv_mgmt_tx_compl_ev_arg *arg);
|
||||
int (*pull_ch_info)(struct ath10k *ar, struct sk_buff *skb,
|
||||
struct wmi_ch_info_ev_arg *arg);
|
||||
int (*pull_vdev_start)(struct ath10k *ar, struct sk_buff *skb,
|
||||
|
|
@ -261,6 +263,16 @@ ath10k_wmi_pull_scan(struct ath10k *ar, struct sk_buff *skb,
|
|||
return ar->wmi.ops->pull_scan(ar, skb, arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
ath10k_wmi_pull_mgmt_tx_compl(struct ath10k *ar, struct sk_buff *skb,
|
||||
struct wmi_tlv_mgmt_tx_compl_ev_arg *arg)
|
||||
{
|
||||
if (!ar->wmi.ops->pull_mgmt_tx_compl)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return ar->wmi.ops->pull_mgmt_tx_compl(ar, skb, arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
ath10k_wmi_pull_mgmt_rx(struct ath10k *ar, struct sk_buff *skb,
|
||||
struct wmi_mgmt_rx_ev_arg *arg)
|
||||
|
|
|
|||
|
|
@ -618,6 +618,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_MGMT_TX_COMPLETION_EVENTID:
|
||||
ath10k_wmi_event_mgmt_tx_compl(ar, skb);
|
||||
break;
|
||||
default:
|
||||
ath10k_warn(ar, "Unknown eventid: %d\n", id);
|
||||
break;
|
||||
|
|
@ -659,6 +662,31 @@ static int ath10k_wmi_tlv_op_pull_scan_ev(struct ath10k *ar,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ath10k_wmi_tlv_op_pull_mgmt_tx_compl_ev(struct ath10k *ar, struct sk_buff *skb,
|
||||
struct wmi_tlv_mgmt_tx_compl_ev_arg *arg)
|
||||
{
|
||||
const void **tb;
|
||||
const struct wmi_tlv_mgmt_tx_compl_ev *ev;
|
||||
int ret;
|
||||
|
||||
tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ev = tb[WMI_TLV_TAG_STRUCT_MGMT_TX_COMPL_EVENT];
|
||||
|
||||
arg->desc_id = ev->desc_id;
|
||||
arg->status = ev->status;
|
||||
arg->pdev_id = ev->pdev_id;
|
||||
|
||||
kfree(tb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath10k_wmi_tlv_op_pull_mgmt_rx_ev(struct ath10k *ar,
|
||||
struct sk_buff *skb,
|
||||
struct wmi_mgmt_rx_ev_arg *arg)
|
||||
|
|
@ -1586,6 +1614,11 @@ static struct sk_buff *ath10k_wmi_tlv_op_gen_init(struct ath10k *ar)
|
|||
cfg->keep_alive_pattern_size = __cpu_to_le32(0);
|
||||
cfg->max_tdls_concurrent_sleep_sta = __cpu_to_le32(1);
|
||||
cfg->max_tdls_concurrent_buffer_sta = __cpu_to_le32(1);
|
||||
cfg->wmi_send_separate = __cpu_to_le32(0);
|
||||
cfg->num_ocb_vdevs = __cpu_to_le32(0);
|
||||
cfg->num_ocb_channels = __cpu_to_le32(0);
|
||||
cfg->num_ocb_schedules = __cpu_to_le32(0);
|
||||
cfg->host_capab = __cpu_to_le32(0);
|
||||
|
||||
ath10k_wmi_put_host_mem_chunks(ar, chunks);
|
||||
|
||||
|
|
@ -1787,7 +1820,6 @@ ath10k_wmi_tlv_op_gen_vdev_start(struct ath10k *ar,
|
|||
{
|
||||
struct wmi_tlv_vdev_start_cmd *cmd;
|
||||
struct wmi_channel *ch;
|
||||
struct wmi_p2p_noa_descriptor *noa;
|
||||
struct wmi_tlv *tlv;
|
||||
struct sk_buff *skb;
|
||||
size_t len;
|
||||
|
|
@ -1845,7 +1877,6 @@ ath10k_wmi_tlv_op_gen_vdev_start(struct ath10k *ar,
|
|||
tlv = ptr;
|
||||
tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
|
||||
tlv->len = 0;
|
||||
noa = (void *)tlv->value;
|
||||
|
||||
/* Note: This is a nested TLV containing:
|
||||
* [wmi_tlv][wmi_p2p_noa_descriptor][wmi_tlv]..
|
||||
|
|
@ -2607,6 +2638,30 @@ ath10k_wmi_tlv_op_gen_request_stats(struct ath10k *ar, u32 stats_mask)
|
|||
return skb;
|
||||
}
|
||||
|
||||
static int
|
||||
ath10k_wmi_mgmt_tx_alloc_msdu_id(struct ath10k *ar, struct sk_buff *skb,
|
||||
dma_addr_t paddr)
|
||||
{
|
||||
struct ath10k_wmi *wmi = &ar->wmi;
|
||||
struct ath10k_mgmt_tx_pkt_addr *pkt_addr;
|
||||
int ret;
|
||||
|
||||
pkt_addr = kmalloc(sizeof(*pkt_addr), GFP_ATOMIC);
|
||||
if (!pkt_addr)
|
||||
return -ENOMEM;
|
||||
|
||||
pkt_addr->vaddr = skb;
|
||||
pkt_addr->paddr = paddr;
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
ret = idr_alloc(&wmi->mgmt_pending_tx, pkt_addr, 0,
|
||||
wmi->mgmt_max_num_pending_tx, GFP_ATOMIC);
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi mgmt tx alloc msdu_id ret %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct sk_buff *
|
||||
ath10k_wmi_tlv_op_gen_mgmt_tx_send(struct ath10k *ar, struct sk_buff *msdu,
|
||||
dma_addr_t paddr)
|
||||
|
|
@ -2618,9 +2673,9 @@ ath10k_wmi_tlv_op_gen_mgmt_tx_send(struct ath10k *ar, struct sk_buff *msdu,
|
|||
u32 buf_len = msdu->len;
|
||||
struct wmi_tlv *tlv;
|
||||
struct sk_buff *skb;
|
||||
int len, desc_id;
|
||||
u32 vdev_id;
|
||||
void *ptr;
|
||||
int len;
|
||||
|
||||
if (!cb->vif)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
|
@ -2651,13 +2706,17 @@ ath10k_wmi_tlv_op_gen_mgmt_tx_send(struct ath10k *ar, struct sk_buff *msdu,
|
|||
if (!skb)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
desc_id = ath10k_wmi_mgmt_tx_alloc_msdu_id(ar, msdu, paddr);
|
||||
if (desc_id < 0)
|
||||
goto err_free_skb;
|
||||
|
||||
ptr = (void *)skb->data;
|
||||
tlv = ptr;
|
||||
tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_MGMT_TX_CMD);
|
||||
tlv->len = __cpu_to_le16(sizeof(*cmd));
|
||||
cmd = (void *)tlv->value;
|
||||
cmd->vdev_id = __cpu_to_le32(vdev_id);
|
||||
cmd->desc_id = 0;
|
||||
cmd->desc_id = __cpu_to_le32(desc_id);
|
||||
cmd->chanfreq = 0;
|
||||
cmd->buf_len = __cpu_to_le32(buf_len);
|
||||
cmd->frame_len = __cpu_to_le32(msdu->len);
|
||||
|
|
@ -2674,6 +2733,10 @@ ath10k_wmi_tlv_op_gen_mgmt_tx_send(struct ath10k *ar, struct sk_buff *msdu,
|
|||
memcpy(ptr, msdu->data, buf_len);
|
||||
|
||||
return skb;
|
||||
|
||||
err_free_skb:
|
||||
dev_kfree_skb(skb);
|
||||
return ERR_PTR(desc_id);
|
||||
}
|
||||
|
||||
static struct sk_buff *
|
||||
|
|
@ -2702,7 +2765,8 @@ ath10k_wmi_tlv_op_gen_force_fw_hang(struct ath10k *ar,
|
|||
|
||||
static struct sk_buff *
|
||||
ath10k_wmi_tlv_op_gen_dbglog_cfg(struct ath10k *ar, u64 module_enable,
|
||||
u32 log_level) {
|
||||
u32 log_level)
|
||||
{
|
||||
struct wmi_tlv_dbglog_cmd *cmd;
|
||||
struct wmi_tlv *tlv;
|
||||
struct sk_buff *skb;
|
||||
|
|
@ -3837,6 +3901,7 @@ static const struct wmi_ops wmi_tlv_ops = {
|
|||
|
||||
.pull_scan = ath10k_wmi_tlv_op_pull_scan_ev,
|
||||
.pull_mgmt_rx = ath10k_wmi_tlv_op_pull_mgmt_rx_ev,
|
||||
.pull_mgmt_tx_compl = ath10k_wmi_tlv_op_pull_mgmt_tx_compl_ev,
|
||||
.pull_ch_info = ath10k_wmi_tlv_op_pull_ch_info_ev,
|
||||
.pull_vdev_start = ath10k_wmi_tlv_op_pull_vdev_start_ev,
|
||||
.pull_peer_kick = ath10k_wmi_tlv_op_pull_peer_kick_ev,
|
||||
|
|
|
|||
|
|
@ -320,6 +320,7 @@ enum wmi_tlv_event_id {
|
|||
WMI_TLV_TBTTOFFSET_UPDATE_EVENTID,
|
||||
WMI_TLV_OFFLOAD_BCN_TX_STATUS_EVENTID,
|
||||
WMI_TLV_OFFLOAD_PROB_RESP_TX_STATUS_EVENTID,
|
||||
WMI_TLV_MGMT_TX_COMPLETION_EVENTID,
|
||||
WMI_TLV_TX_DELBA_COMPLETE_EVENTID = WMI_TLV_EV(WMI_TLV_GRP_BA_NEG),
|
||||
WMI_TLV_TX_ADDBA_COMPLETE_EVENTID,
|
||||
WMI_TLV_BA_RSP_SSN_EVENTID,
|
||||
|
|
@ -1573,6 +1574,17 @@ struct wmi_tlv {
|
|||
u8 value[0];
|
||||
} __packed;
|
||||
|
||||
struct ath10k_mgmt_tx_pkt_addr {
|
||||
void *vaddr;
|
||||
dma_addr_t paddr;
|
||||
};
|
||||
|
||||
struct wmi_tlv_mgmt_tx_compl_ev {
|
||||
__le32 desc_id;
|
||||
__le32 status;
|
||||
__le32 pdev_id;
|
||||
};
|
||||
|
||||
#define WMI_TLV_MGMT_RX_NUM_RSSI 4
|
||||
|
||||
struct wmi_tlv_mgmt_rx_ev {
|
||||
|
|
@ -1670,6 +1682,11 @@ struct wmi_tlv_resource_config {
|
|||
__le32 keep_alive_pattern_size;
|
||||
__le32 max_tdls_concurrent_sleep_sta;
|
||||
__le32 max_tdls_concurrent_buffer_sta;
|
||||
__le32 wmi_send_separate;
|
||||
__le32 num_ocb_vdevs;
|
||||
__le32 num_ocb_channels;
|
||||
__le32 num_ocb_schedules;
|
||||
__le32 host_capab;
|
||||
} __packed;
|
||||
|
||||
struct wmi_tlv_init_cmd {
|
||||
|
|
|
|||
|
|
@ -1333,7 +1333,7 @@ static struct wmi_pdev_param_map wmi_10_2_4_pdev_param_map = {
|
|||
.enable_per_tid_ampdu = WMI_PDEV_PARAM_UNSUPPORTED,
|
||||
.cca_threshold = WMI_PDEV_PARAM_UNSUPPORTED,
|
||||
.rts_fixed_rate = WMI_PDEV_PARAM_UNSUPPORTED,
|
||||
.pdev_reset = WMI_PDEV_PARAM_UNSUPPORTED,
|
||||
.pdev_reset = WMI_10X_PDEV_PARAM_PDEV_RESET,
|
||||
.wapi_mbssid_offset = WMI_PDEV_PARAM_UNSUPPORTED,
|
||||
.arp_srcaddr = WMI_PDEV_PARAM_UNSUPPORTED,
|
||||
.arp_dstaddr = WMI_PDEV_PARAM_UNSUPPORTED,
|
||||
|
|
@ -2313,6 +2313,59 @@ static bool ath10k_wmi_rx_is_decrypted(struct ath10k *ar,
|
|||
return true;
|
||||
}
|
||||
|
||||
static int wmi_process_mgmt_tx_comp(struct ath10k *ar, u32 desc_id,
|
||||
u32 status)
|
||||
{
|
||||
struct ath10k_mgmt_tx_pkt_addr *pkt_addr;
|
||||
struct ath10k_wmi *wmi = &ar->wmi;
|
||||
struct ieee80211_tx_info *info;
|
||||
struct sk_buff *msdu;
|
||||
int ret;
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
|
||||
pkt_addr = idr_find(&wmi->mgmt_pending_tx, desc_id);
|
||||
if (!pkt_addr) {
|
||||
ath10k_warn(ar, "received mgmt tx completion for invalid msdu_id: %d\n",
|
||||
desc_id);
|
||||
ret = -ENOENT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
msdu = pkt_addr->vaddr;
|
||||
dma_unmap_single(ar->dev, pkt_addr->paddr,
|
||||
msdu->len, DMA_FROM_DEVICE);
|
||||
info = IEEE80211_SKB_CB(msdu);
|
||||
info->flags |= status;
|
||||
ieee80211_tx_status_irqsafe(ar->hw, msdu);
|
||||
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
idr_remove(&wmi->mgmt_pending_tx, desc_id);
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath10k_wmi_event_mgmt_tx_compl(struct ath10k *ar, struct sk_buff *skb)
|
||||
{
|
||||
struct wmi_tlv_mgmt_tx_compl_ev_arg arg;
|
||||
int ret;
|
||||
|
||||
ret = ath10k_wmi_pull_mgmt_tx_compl(ar, skb, &arg);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to parse mgmt comp event: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
wmi_process_mgmt_tx_comp(ar, __le32_to_cpu(arg.desc_id),
|
||||
__le32_to_cpu(arg.status));
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv evnt mgmt tx completion\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
|
||||
{
|
||||
struct wmi_mgmt_rx_ev_arg arg = {};
|
||||
|
|
@ -9073,6 +9126,11 @@ int ath10k_wmi_attach(struct ath10k *ar)
|
|||
INIT_WORK(&ar->radar_confirmation_work,
|
||||
ath10k_radar_confirmation_work);
|
||||
|
||||
if (test_bit(ATH10K_FW_FEATURE_MGMT_TX_BY_REF,
|
||||
ar->running_fw->fw_file.fw_features)) {
|
||||
idr_init(&ar->wmi.mgmt_pending_tx);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -9091,8 +9149,35 @@ void ath10k_wmi_free_host_mem(struct ath10k *ar)
|
|||
ar->wmi.num_mem_chunks = 0;
|
||||
}
|
||||
|
||||
static int ath10k_wmi_mgmt_tx_clean_up_pending(int msdu_id, void *ptr,
|
||||
void *ctx)
|
||||
{
|
||||
struct ath10k_mgmt_tx_pkt_addr *pkt_addr = ptr;
|
||||
struct ath10k *ar = ctx;
|
||||
struct sk_buff *msdu;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_WMI,
|
||||
"force cleanup mgmt msdu_id %hu\n", msdu_id);
|
||||
|
||||
msdu = pkt_addr->vaddr;
|
||||
dma_unmap_single(ar->dev, pkt_addr->paddr,
|
||||
msdu->len, DMA_FROM_DEVICE);
|
||||
ieee80211_free_txskb(ar->hw, msdu);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ath10k_wmi_detach(struct ath10k *ar)
|
||||
{
|
||||
if (test_bit(ATH10K_FW_FEATURE_MGMT_TX_BY_REF,
|
||||
ar->running_fw->fw_file.fw_features)) {
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
idr_for_each(&ar->wmi.mgmt_pending_tx,
|
||||
ath10k_wmi_mgmt_tx_clean_up_pending, ar);
|
||||
idr_destroy(&ar->wmi.mgmt_pending_tx);
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
}
|
||||
|
||||
cancel_work_sync(&ar->svc_rdy_work);
|
||||
|
||||
if (ar->svc_rdy_skb)
|
||||
|
|
|
|||
|
|
@ -462,6 +462,7 @@ static inline char *wmi_service_name(int service_id)
|
|||
SVCSTR(WMI_SERVICE_HTT_MGMT_TX_COMP_VALID_FLAGS);
|
||||
SVCSTR(WMI_SERVICE_HOST_DFS_CHECK_SUPPORT);
|
||||
SVCSTR(WMI_SERVICE_TPC_STATS_FINAL);
|
||||
SVCSTR(WMI_SERVICE_RESET_CHIP);
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -3934,7 +3935,11 @@ enum wmi_10x_pdev_param {
|
|||
WMI_10X_PDEV_PARAM_REMOVE_MCAST2UCAST_BUFFER,
|
||||
WMI_10X_PDEV_PARAM_PEER_STA_PS_STATECHG_ENABLE,
|
||||
WMI_10X_PDEV_PARAM_RTS_FIXED_RATE,
|
||||
WMI_10X_PDEV_PARAM_CAL_PERIOD
|
||||
WMI_10X_PDEV_PARAM_CAL_PERIOD,
|
||||
WMI_10X_PDEV_PARAM_ATF_STRICT_SCH,
|
||||
WMI_10X_PDEV_PARAM_ATF_SCHED_DURATION,
|
||||
WMI_10X_PDEV_PARAM_SET_PROMISC_MODE_CMDID,
|
||||
WMI_10X_PDEV_PARAM_PDEV_RESET
|
||||
};
|
||||
|
||||
enum wmi_10_4_pdev_param {
|
||||
|
|
@ -6501,6 +6506,15 @@ struct wmi_force_fw_hang_cmd {
|
|||
__le32 delay_ms;
|
||||
} __packed;
|
||||
|
||||
enum wmi_pdev_reset_mode_type {
|
||||
WMI_RST_MODE_TX_FLUSH = 1,
|
||||
WMI_RST_MODE_WARM_RESET,
|
||||
WMI_RST_MODE_COLD_RESET,
|
||||
WMI_RST_MODE_WARM_RESET_RESTORE_CAL,
|
||||
WMI_RST_MODE_COLD_RESET_RESTORE_CAL,
|
||||
WMI_RST_MODE_MAX,
|
||||
};
|
||||
|
||||
enum ath10k_dbglog_level {
|
||||
ATH10K_DBGLOG_LEVEL_VERBOSE = 0,
|
||||
ATH10K_DBGLOG_LEVEL_INFO = 1,
|
||||
|
|
@ -6600,6 +6614,12 @@ struct wmi_scan_ev_arg {
|
|||
__le32 vdev_id;
|
||||
};
|
||||
|
||||
struct wmi_tlv_mgmt_tx_compl_ev_arg {
|
||||
__le32 desc_id;
|
||||
__le32 status;
|
||||
__le32 pdev_id;
|
||||
};
|
||||
|
||||
struct wmi_mgmt_rx_ev_arg {
|
||||
__le32 channel;
|
||||
__le32 snr;
|
||||
|
|
@ -7071,6 +7091,7 @@ int ath10k_wmi_start_scan_verify(const struct wmi_start_scan_arg *arg);
|
|||
|
||||
int ath10k_wmi_event_scan(struct ath10k *ar, struct sk_buff *skb);
|
||||
int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb);
|
||||
int ath10k_wmi_event_mgmt_tx_compl(struct ath10k *ar, struct sk_buff *skb);
|
||||
void ath10k_wmi_event_chan_info(struct ath10k *ar, struct sk_buff *skb);
|
||||
void ath10k_wmi_event_echo(struct ath10k *ar, struct sk_buff *skb);
|
||||
int ath10k_wmi_event_debug_mesg(struct ath10k *ar, struct sk_buff *skb);
|
||||
|
|
|
|||
|
|
@ -483,7 +483,6 @@ static u32
|
|||
ath5k_hw_rf_gainf_corr(struct ath5k_hw *ah)
|
||||
{
|
||||
u32 mix, step;
|
||||
u32 *rf;
|
||||
const struct ath5k_gain_opt *go;
|
||||
const struct ath5k_gain_opt_step *g_step;
|
||||
const struct ath5k_rf_reg *rf_regs;
|
||||
|
|
@ -502,7 +501,6 @@ ath5k_hw_rf_gainf_corr(struct ath5k_hw *ah)
|
|||
if (ah->ah_rf_banks == NULL)
|
||||
return 0;
|
||||
|
||||
rf = ah->ah_rf_banks;
|
||||
ah->ah_gain.g_f_corr = 0;
|
||||
|
||||
/* No VGA (Variable Gain Amplifier) override, skip */
|
||||
|
|
@ -549,13 +547,10 @@ ath5k_hw_rf_check_gainf_readback(struct ath5k_hw *ah)
|
|||
{
|
||||
const struct ath5k_rf_reg *rf_regs;
|
||||
u32 step, mix_ovr, level[4];
|
||||
u32 *rf;
|
||||
|
||||
if (ah->ah_rf_banks == NULL)
|
||||
return false;
|
||||
|
||||
rf = ah->ah_rf_banks;
|
||||
|
||||
if (ah->ah_radio == AR5K_RF5111) {
|
||||
|
||||
rf_regs = rf_regs_5111;
|
||||
|
|
|
|||
|
|
@ -534,7 +534,7 @@ int ath6kl_bmi_init(struct ath6kl *ar)
|
|||
/* cmd + addr + len + data_size */
|
||||
ar->bmi.max_cmd_size = ar->bmi.max_data_size + (sizeof(u32) * 3);
|
||||
|
||||
ar->bmi.cmd_buf = kzalloc(ar->bmi.max_cmd_size, GFP_ATOMIC);
|
||||
ar->bmi.cmd_buf = kzalloc(ar->bmi.max_cmd_size, GFP_KERNEL);
|
||||
if (!ar->bmi.cmd_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
|
|||
|
|
@ -746,10 +746,8 @@ static int ath6kl_htc_pipe_tx_complete(struct ath6kl *ar, struct sk_buff *skb)
|
|||
struct htc_endpoint *ep;
|
||||
struct htc_packet *packet;
|
||||
u8 ep_id, *netdata;
|
||||
u32 netlen;
|
||||
|
||||
netdata = skb->data;
|
||||
netlen = skb->len;
|
||||
|
||||
htc_hdr = (struct htc_frame_hdr *) netdata;
|
||||
|
||||
|
|
@ -855,12 +853,8 @@ static int htc_process_trailer(struct htc_target *target, u8 *buffer,
|
|||
{
|
||||
struct htc_credit_report *report;
|
||||
struct htc_record_hdr *record;
|
||||
u8 *record_buf, *orig_buf;
|
||||
int orig_len, status;
|
||||
|
||||
orig_buf = buffer;
|
||||
orig_len = len;
|
||||
status = 0;
|
||||
u8 *record_buf;
|
||||
int status = 0;
|
||||
|
||||
while (len > 0) {
|
||||
if (len < sizeof(struct htc_record_hdr)) {
|
||||
|
|
|
|||
|
|
@ -272,7 +272,7 @@ int ath6kl_read_fwlogs(struct ath6kl *ar)
|
|||
{
|
||||
struct ath6kl_dbglog_hdr debug_hdr;
|
||||
struct ath6kl_dbglog_buf debug_buf;
|
||||
u32 address, length, dropped, firstbuf, debug_hdr_addr;
|
||||
u32 address, length, firstbuf, debug_hdr_addr;
|
||||
int ret, loop;
|
||||
u8 *buf;
|
||||
|
||||
|
|
@ -303,7 +303,6 @@ int ath6kl_read_fwlogs(struct ath6kl *ar)
|
|||
address = TARG_VTOP(ar->target_type,
|
||||
le32_to_cpu(debug_hdr.dbuf_addr));
|
||||
firstbuf = address;
|
||||
dropped = le32_to_cpu(debug_hdr.dropped);
|
||||
ret = ath6kl_diag_read(ar, address, &debug_buf, sizeof(debug_buf));
|
||||
if (ret)
|
||||
goto out;
|
||||
|
|
|
|||
|
|
@ -1701,7 +1701,6 @@ void aggr_recv_addba_req_evt(struct ath6kl_vif *vif, u8 tid_mux, u16 seq_no,
|
|||
struct ath6kl_sta *sta;
|
||||
struct aggr_info_conn *aggr_conn = NULL;
|
||||
struct rxtid *rxtid;
|
||||
struct rxtid_stats *stats;
|
||||
u16 hold_q_size;
|
||||
u8 tid, aid;
|
||||
|
||||
|
|
@ -1722,7 +1721,6 @@ void aggr_recv_addba_req_evt(struct ath6kl_vif *vif, u8 tid_mux, u16 seq_no,
|
|||
return;
|
||||
|
||||
rxtid = &aggr_conn->rx_tid[tid];
|
||||
stats = &aggr_conn->stat[tid];
|
||||
|
||||
if (win_sz < AGGR_WIN_SZ_MIN || win_sz > AGGR_WIN_SZ_MAX)
|
||||
ath6kl_dbg(ATH6KL_DBG_WLAN_RX, "%s: win_sz %d, tid %d\n",
|
||||
|
|
|
|||
|
|
@ -676,10 +676,10 @@ static int ar9002_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
|
|||
return 0;
|
||||
|
||||
ah->cal_list_curr = currCal = currCal->calNext;
|
||||
if (currCal->calState == CAL_WAITING) {
|
||||
if (currCal->calState == CAL_WAITING)
|
||||
ath9k_hw_reset_calibration(ah, currCal);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Do NF cal only at longer intervals */
|
||||
|
|
|
|||
|
|
@ -1800,6 +1800,8 @@ static void ar9003_hw_spectral_scan_config(struct ath_hw *ah,
|
|||
|
||||
static void ar9003_hw_spectral_scan_trigger(struct ath_hw *ah)
|
||||
{
|
||||
REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN,
|
||||
AR_PHY_SPECTRAL_SCAN_ENABLE);
|
||||
/* Activate spectral scan */
|
||||
REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN,
|
||||
AR_PHY_SPECTRAL_SCAN_ACTIVE);
|
||||
|
|
|
|||
|
|
@ -2942,16 +2942,19 @@ void ath9k_hw_apply_txpower(struct ath_hw *ah, struct ath9k_channel *chan,
|
|||
struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
|
||||
struct ieee80211_channel *channel;
|
||||
int chan_pwr, new_pwr;
|
||||
u16 ctl = NO_CTL;
|
||||
|
||||
if (!chan)
|
||||
return;
|
||||
|
||||
if (!test)
|
||||
ctl = ath9k_regd_get_ctl(reg, chan);
|
||||
|
||||
channel = chan->chan;
|
||||
chan_pwr = min_t(int, channel->max_power * 2, MAX_RATE_POWER);
|
||||
new_pwr = min_t(int, chan_pwr, reg->power_limit);
|
||||
|
||||
ah->eep_ops->set_txpower(ah, chan,
|
||||
ath9k_regd_get_ctl(reg, chan),
|
||||
ah->eep_ops->set_txpower(ah, chan, ctl,
|
||||
get_antenna_gain(ah, chan), new_pwr, test);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
|
|||
struct ath_tx_status *ts, int nframes, int nbad,
|
||||
int txok);
|
||||
static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
|
||||
int seqno);
|
||||
struct ath_buf *bf);
|
||||
static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
|
||||
struct ath_txq *txq,
|
||||
struct ath_atx_tid *tid,
|
||||
|
|
@ -86,7 +86,8 @@ static void ath_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
|
|||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_sta *sta = info->status.status_driver_data[0];
|
||||
|
||||
if (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) {
|
||||
if (info->flags & (IEEE80211_TX_CTL_REQ_TX_STATUS |
|
||||
IEEE80211_TX_STATUS_EOSP)) {
|
||||
ieee80211_tx_status(hw, skb);
|
||||
return;
|
||||
}
|
||||
|
|
@ -295,7 +296,7 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
|
|||
}
|
||||
|
||||
if (fi->baw_tracked) {
|
||||
ath_tx_update_baw(sc, tid, bf->bf_state.seqno);
|
||||
ath_tx_update_baw(sc, tid, bf);
|
||||
sendbar = true;
|
||||
}
|
||||
|
||||
|
|
@ -311,10 +312,15 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
|
|||
}
|
||||
|
||||
static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
|
||||
int seqno)
|
||||
struct ath_buf *bf)
|
||||
{
|
||||
struct ath_frame_info *fi = get_frame_info(bf->bf_mpdu);
|
||||
u16 seqno = bf->bf_state.seqno;
|
||||
int index, cindex;
|
||||
|
||||
if (!fi->baw_tracked)
|
||||
return;
|
||||
|
||||
index = ATH_BA_INDEX(tid->seq_start, seqno);
|
||||
cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1);
|
||||
|
||||
|
|
@ -335,6 +341,9 @@ static void ath_tx_addto_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
|
|||
u16 seqno = bf->bf_state.seqno;
|
||||
int index, cindex;
|
||||
|
||||
if (fi->baw_tracked)
|
||||
return;
|
||||
|
||||
index = ATH_BA_INDEX(tid->seq_start, seqno);
|
||||
cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1);
|
||||
__set_bit(cindex, tid->tx_buf);
|
||||
|
|
@ -611,7 +620,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
|
|||
* complete the acked-ones/xretried ones; update
|
||||
* block-ack window
|
||||
*/
|
||||
ath_tx_update_baw(sc, tid, seqno);
|
||||
ath_tx_update_baw(sc, tid, bf);
|
||||
|
||||
if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) {
|
||||
memcpy(tx_info->control.rates, rates, sizeof(rates));
|
||||
|
|
@ -641,7 +650,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
|
|||
* run out of tx buf.
|
||||
*/
|
||||
if (!tbf) {
|
||||
ath_tx_update_baw(sc, tid, seqno);
|
||||
ath_tx_update_baw(sc, tid, bf);
|
||||
|
||||
ath_tx_complete_buf(sc, bf, txq,
|
||||
&bf_head, NULL, ts,
|
||||
|
|
@ -969,7 +978,8 @@ ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq,
|
|||
bf->bf_lastbf = bf;
|
||||
|
||||
tx_info = IEEE80211_SKB_CB(skb);
|
||||
tx_info->flags &= ~IEEE80211_TX_CTL_CLEAR_PS_FILT;
|
||||
tx_info->flags &= ~(IEEE80211_TX_CTL_CLEAR_PS_FILT |
|
||||
IEEE80211_TX_STATUS_EOSP);
|
||||
|
||||
/*
|
||||
* No aggregation session is running, but there may be frames
|
||||
|
|
@ -1009,11 +1019,14 @@ ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq,
|
|||
|
||||
INIT_LIST_HEAD(&bf_head);
|
||||
list_add(&bf->list, &bf_head);
|
||||
ath_tx_update_baw(sc, tid, seqno);
|
||||
ath_tx_update_baw(sc, tid, bf);
|
||||
ath_tx_complete_buf(sc, bf, txq, &bf_head, NULL, &ts, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bf_isampdu(bf))
|
||||
ath_tx_addto_baw(sc, tid, bf);
|
||||
|
||||
return bf;
|
||||
}
|
||||
|
||||
|
|
@ -1071,8 +1084,6 @@ ath_tx_form_aggr(struct ath_softc *sc, struct ath_txq *txq,
|
|||
bf->bf_next = NULL;
|
||||
|
||||
/* link buffers of this frame to the aggregate */
|
||||
if (!fi->baw_tracked)
|
||||
ath_tx_addto_baw(sc, tid, bf);
|
||||
bf->bf_state.ndelim = ndelim;
|
||||
|
||||
list_add_tail(&bf->list, bf_q);
|
||||
|
|
@ -1659,6 +1670,22 @@ void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ath9k_set_moredata(struct ath_softc *sc, struct ath_buf *bf, bool val)
|
||||
{
|
||||
struct ieee80211_hdr *hdr;
|
||||
u16 mask = cpu_to_le16(IEEE80211_FCTL_MOREDATA);
|
||||
u16 mask_val = mask * val;
|
||||
|
||||
hdr = (struct ieee80211_hdr *) bf->bf_mpdu->data;
|
||||
if ((hdr->frame_control & mask) != mask_val) {
|
||||
hdr->frame_control = (hdr->frame_control & ~mask) | mask_val;
|
||||
dma_sync_single_for_device(sc->dev, bf->bf_buf_addr,
|
||||
sizeof(*hdr), DMA_TO_DEVICE);
|
||||
}
|
||||
}
|
||||
|
||||
void ath9k_release_buffered_frames(struct ieee80211_hw *hw,
|
||||
struct ieee80211_sta *sta,
|
||||
u16 tids, int nframes,
|
||||
|
|
@ -1689,12 +1716,11 @@ void ath9k_release_buffered_frames(struct ieee80211_hw *hw,
|
|||
if (!bf)
|
||||
break;
|
||||
|
||||
ath9k_set_moredata(sc, bf, true);
|
||||
list_add_tail(&bf->list, &bf_q);
|
||||
ath_set_rates(tid->an->vif, tid->an->sta, bf);
|
||||
if (bf_isampdu(bf)) {
|
||||
ath_tx_addto_baw(sc, tid, bf);
|
||||
if (bf_isampdu(bf))
|
||||
bf->bf_state.bf_type &= ~BUF_AGGR;
|
||||
}
|
||||
if (bf_tail)
|
||||
bf_tail->bf_next = bf;
|
||||
|
||||
|
|
@ -1712,6 +1738,9 @@ void ath9k_release_buffered_frames(struct ieee80211_hw *hw,
|
|||
if (list_empty(&bf_q))
|
||||
return;
|
||||
|
||||
if (!more_data)
|
||||
ath9k_set_moredata(sc, bf_tail, false);
|
||||
|
||||
info = IEEE80211_SKB_CB(bf_tail->bf_mpdu);
|
||||
info->flags |= IEEE80211_TX_STATUS_EOSP;
|
||||
|
||||
|
|
@ -2407,7 +2436,6 @@ void ath_tx_cabq(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|||
.txq = sc->beacon.cabq
|
||||
};
|
||||
struct ath_tx_info info = {};
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct ath_buf *bf_tail = NULL;
|
||||
struct ath_buf *bf;
|
||||
LIST_HEAD(bf_q);
|
||||
|
|
@ -2451,15 +2479,10 @@ void ath_tx_cabq(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|||
if (list_empty(&bf_q))
|
||||
return;
|
||||
|
||||
bf = list_last_entry(&bf_q, struct ath_buf, list);
|
||||
ath9k_set_moredata(sc, bf, false);
|
||||
|
||||
bf = list_first_entry(&bf_q, struct ath_buf, list);
|
||||
hdr = (struct ieee80211_hdr *) bf->bf_mpdu->data;
|
||||
|
||||
if (hdr->frame_control & cpu_to_le16(IEEE80211_FCTL_MOREDATA)) {
|
||||
hdr->frame_control &= ~cpu_to_le16(IEEE80211_FCTL_MOREDATA);
|
||||
dma_sync_single_for_device(sc->dev, bf->bf_buf_addr,
|
||||
sizeof(*hdr), DMA_TO_DEVICE);
|
||||
}
|
||||
|
||||
ath_txq_lock(sc, txctl.txq);
|
||||
ath_tx_fill_desc(sc, bf, txctl.txq, 0);
|
||||
ath_tx_txqaddbuf(sc, txctl.txq, &bf_q, false);
|
||||
|
|
|
|||
|
|
@ -689,11 +689,12 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
|
|||
|
||||
wil_dbg_misc(wil, "scan: wdev=0x%p iftype=%d\n", wdev, wdev->iftype);
|
||||
|
||||
/* check we are client side */
|
||||
/* scan is supported on client interfaces and on AP interface */
|
||||
switch (wdev->iftype) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
case NL80211_IFTYPE_P2P_CLIENT:
|
||||
case NL80211_IFTYPE_P2P_DEVICE:
|
||||
case NL80211_IFTYPE_AP:
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
|
|
@ -1089,18 +1090,51 @@ int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
|
|||
int rc;
|
||||
bool tx_status;
|
||||
|
||||
/* Note, currently we do not support the "wait" parameter, user-space
|
||||
* must call remain_on_channel before mgmt_tx or listen on a channel
|
||||
* another way (AP/PCP or connected station)
|
||||
* in addition we need to check if specified "chan" argument is
|
||||
* different from currently "listened" channel and fail if it is.
|
||||
wil_dbg_misc(wil, "mgmt_tx: channel %d offchan %d, wait %d\n",
|
||||
params->chan ? params->chan->hw_value : -1,
|
||||
params->offchan,
|
||||
params->wait);
|
||||
|
||||
/* Note, currently we support the "wait" parameter only on AP mode.
|
||||
* In other modes, user-space must call remain_on_channel before
|
||||
* mgmt_tx or listen on a channel other than active one.
|
||||
*/
|
||||
|
||||
rc = wmi_mgmt_tx(vif, buf, len);
|
||||
tx_status = (rc == 0);
|
||||
if (params->chan && params->chan->hw_value == 0) {
|
||||
wil_err(wil, "invalid channel\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (wdev->iftype != NL80211_IFTYPE_AP) {
|
||||
wil_dbg_misc(wil,
|
||||
"send WMI_SW_TX_REQ_CMDID on non-AP interfaces\n");
|
||||
rc = wmi_mgmt_tx(vif, buf, len);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!params->chan || params->chan->hw_value == vif->channel) {
|
||||
wil_dbg_misc(wil,
|
||||
"send WMI_SW_TX_REQ_CMDID for on-channel\n");
|
||||
rc = wmi_mgmt_tx(vif, buf, len);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (params->offchan == 0) {
|
||||
wil_err(wil,
|
||||
"invalid channel params: current %d requested %d, off-channel not allowed\n",
|
||||
vif->channel, params->chan->hw_value);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* use the wmi_mgmt_tx_ext only on AP mode and off-channel */
|
||||
rc = wmi_mgmt_tx_ext(vif, buf, len, params->chan->hw_value,
|
||||
params->wait);
|
||||
|
||||
out:
|
||||
tx_status = (rc == 0);
|
||||
cfg80211_mgmt_tx_status(wdev, cookie ? *cookie : 0, buf, len,
|
||||
tx_status, GFP_KERNEL);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1388,7 +1388,7 @@ static const struct file_operations fops_bf = {
|
|||
};
|
||||
|
||||
/*---------temp------------*/
|
||||
static void print_temp(struct seq_file *s, const char *prefix, u32 t)
|
||||
static void print_temp(struct seq_file *s, const char *prefix, s32 t)
|
||||
{
|
||||
switch (t) {
|
||||
case 0:
|
||||
|
|
@ -1396,7 +1396,8 @@ static void print_temp(struct seq_file *s, const char *prefix, u32 t)
|
|||
seq_printf(s, "%s N/A\n", prefix);
|
||||
break;
|
||||
default:
|
||||
seq_printf(s, "%s %d.%03d\n", prefix, t / 1000, t % 1000);
|
||||
seq_printf(s, "%s %s%d.%03d\n", prefix, (t < 0 ? "-" : ""),
|
||||
abs(t / 1000), abs(t % 1000));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -1404,7 +1405,7 @@ static void print_temp(struct seq_file *s, const char *prefix, u32 t)
|
|||
static int wil_temp_debugfs_show(struct seq_file *s, void *data)
|
||||
{
|
||||
struct wil6210_priv *wil = s->private;
|
||||
u32 t_m, t_r;
|
||||
s32 t_m, t_r;
|
||||
int rc = wmi_get_temperature(wil, &t_m, &t_r);
|
||||
|
||||
if (rc) {
|
||||
|
|
@ -1640,6 +1641,7 @@ static void wil_print_rxtid(struct seq_file *s, struct wil_tid_ampdu_rx *r)
|
|||
int i;
|
||||
u16 index = ((r->head_seq_num - r->ssn) & 0xfff) % r->buf_size;
|
||||
unsigned long long drop_dup = r->drop_dup, drop_old = r->drop_old;
|
||||
unsigned long long drop_dup_mcast = r->drop_dup_mcast;
|
||||
|
||||
seq_printf(s, "([%2d]) 0x%03x [", r->buf_size, r->head_seq_num);
|
||||
for (i = 0; i < r->buf_size; i++) {
|
||||
|
|
@ -1649,9 +1651,9 @@ static void wil_print_rxtid(struct seq_file *s, struct wil_tid_ampdu_rx *r)
|
|||
seq_printf(s, "%c", r->reorder_buf[i] ? '*' : '_');
|
||||
}
|
||||
seq_printf(s,
|
||||
"] total %llu drop %llu (dup %llu + old %llu) last 0x%03x\n",
|
||||
r->total, drop_dup + drop_old, drop_dup, drop_old,
|
||||
r->ssn_last_drop);
|
||||
"] total %llu drop %llu (dup %llu + old %llu + dup mcast %llu) last 0x%03x\n",
|
||||
r->total, drop_dup + drop_old + drop_dup_mcast, drop_dup,
|
||||
drop_old, drop_dup_mcast, r->ssn_last_drop);
|
||||
}
|
||||
|
||||
static void wil_print_rxtid_crypto(struct seq_file *s, int tid,
|
||||
|
|
@ -1733,13 +1735,12 @@ __acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock)
|
|||
p->stats.rx_short_frame,
|
||||
p->stats.rx_large_frame,
|
||||
p->stats.rx_replay);
|
||||
|
||||
if (wil->use_enhanced_dma_hw)
|
||||
seq_printf(s,
|
||||
"mic error %lu, key error %lu, amsdu error %lu\n",
|
||||
p->stats.rx_mic_error,
|
||||
p->stats.rx_key_error,
|
||||
p->stats.rx_amsdu_error);
|
||||
seq_printf(s,
|
||||
"mic error %lu, key error %lu, amsdu error %lu, csum error %lu\n",
|
||||
p->stats.rx_mic_error,
|
||||
p->stats.rx_key_error,
|
||||
p->stats.rx_amsdu_error,
|
||||
p->stats.rx_csum_err);
|
||||
|
||||
seq_puts(s, "Rx/MCS:");
|
||||
for (mcs = 0; mcs < ARRAY_SIZE(p->stats.rx_per_mcs);
|
||||
|
|
@ -1801,6 +1802,343 @@ static const struct file_operations fops_mids = {
|
|||
.llseek = seq_lseek,
|
||||
};
|
||||
|
||||
static int wil_tx_latency_debugfs_show(struct seq_file *s, void *data)
|
||||
__acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock)
|
||||
{
|
||||
struct wil6210_priv *wil = s->private;
|
||||
int i, bin;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(wil->sta); i++) {
|
||||
struct wil_sta_info *p = &wil->sta[i];
|
||||
char *status = "unknown";
|
||||
u8 aid = 0;
|
||||
u8 mid;
|
||||
|
||||
if (!p->tx_latency_bins)
|
||||
continue;
|
||||
|
||||
switch (p->status) {
|
||||
case wil_sta_unused:
|
||||
status = "unused ";
|
||||
break;
|
||||
case wil_sta_conn_pending:
|
||||
status = "pending ";
|
||||
break;
|
||||
case wil_sta_connected:
|
||||
status = "connected";
|
||||
aid = p->aid;
|
||||
break;
|
||||
}
|
||||
mid = (p->status != wil_sta_unused) ? p->mid : U8_MAX;
|
||||
seq_printf(s, "[%d] %pM %s MID %d AID %d\n", i, p->addr, status,
|
||||
mid, aid);
|
||||
|
||||
if (p->status == wil_sta_connected) {
|
||||
u64 num_packets = 0;
|
||||
u64 tx_latency_avg = p->stats.tx_latency_total_us;
|
||||
|
||||
seq_puts(s, "Tx/Latency bin:");
|
||||
for (bin = 0; bin < WIL_NUM_LATENCY_BINS; bin++) {
|
||||
seq_printf(s, " %lld",
|
||||
p->tx_latency_bins[bin]);
|
||||
num_packets += p->tx_latency_bins[bin];
|
||||
}
|
||||
seq_puts(s, "\n");
|
||||
if (!num_packets)
|
||||
continue;
|
||||
do_div(tx_latency_avg, num_packets);
|
||||
seq_printf(s, "Tx/Latency min/avg/max (us): %d/%lld/%d",
|
||||
p->stats.tx_latency_min_us,
|
||||
tx_latency_avg,
|
||||
p->stats.tx_latency_max_us);
|
||||
|
||||
seq_puts(s, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wil_tx_latency_seq_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, wil_tx_latency_debugfs_show,
|
||||
inode->i_private);
|
||||
}
|
||||
|
||||
static ssize_t wil_tx_latency_write(struct file *file, const char __user *buf,
|
||||
size_t len, loff_t *ppos)
|
||||
{
|
||||
struct seq_file *s = file->private_data;
|
||||
struct wil6210_priv *wil = s->private;
|
||||
int val, rc, i;
|
||||
bool enable;
|
||||
|
||||
rc = kstrtoint_from_user(buf, len, 0, &val);
|
||||
if (rc) {
|
||||
wil_err(wil, "Invalid argument\n");
|
||||
return rc;
|
||||
}
|
||||
if (val == 1)
|
||||
/* default resolution */
|
||||
val = 500;
|
||||
if (val && (val < 50 || val > 1000)) {
|
||||
wil_err(wil, "Invalid resolution %d\n", val);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
enable = !!val;
|
||||
if (wil->tx_latency == enable)
|
||||
return len;
|
||||
|
||||
wil_info(wil, "%s TX latency measurements (resolution %dusec)\n",
|
||||
enable ? "Enabling" : "Disabling", val);
|
||||
|
||||
if (enable) {
|
||||
size_t sz = sizeof(u64) * WIL_NUM_LATENCY_BINS;
|
||||
|
||||
wil->tx_latency_res = val;
|
||||
for (i = 0; i < ARRAY_SIZE(wil->sta); i++) {
|
||||
struct wil_sta_info *sta = &wil->sta[i];
|
||||
|
||||
kfree(sta->tx_latency_bins);
|
||||
sta->tx_latency_bins = kzalloc(sz, GFP_KERNEL);
|
||||
if (!sta->tx_latency_bins)
|
||||
return -ENOMEM;
|
||||
sta->stats.tx_latency_min_us = U32_MAX;
|
||||
sta->stats.tx_latency_max_us = 0;
|
||||
sta->stats.tx_latency_total_us = 0;
|
||||
}
|
||||
}
|
||||
wil->tx_latency = enable;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static const struct file_operations fops_tx_latency = {
|
||||
.open = wil_tx_latency_seq_open,
|
||||
.release = single_release,
|
||||
.read = seq_read,
|
||||
.write = wil_tx_latency_write,
|
||||
.llseek = seq_lseek,
|
||||
};
|
||||
|
||||
static void wil_link_stats_print_basic(struct wil6210_vif *vif,
|
||||
struct seq_file *s,
|
||||
struct wmi_link_stats_basic *basic)
|
||||
{
|
||||
char per[5] = "?";
|
||||
|
||||
if (basic->per_average != 0xff)
|
||||
snprintf(per, sizeof(per), "%d%%", basic->per_average);
|
||||
|
||||
seq_printf(s, "CID %d {\n"
|
||||
"\tTxMCS %d TxTpt %d\n"
|
||||
"\tGoodput(rx:tx) %d:%d\n"
|
||||
"\tRxBcastFrames %d\n"
|
||||
"\tRSSI %d SQI %d SNR %d PER %s\n"
|
||||
"\tRx RFC %d Ant num %d\n"
|
||||
"\tSectors(rx:tx) my %d:%d peer %d:%d\n"
|
||||
"}\n",
|
||||
basic->cid,
|
||||
basic->bf_mcs, le32_to_cpu(basic->tx_tpt),
|
||||
le32_to_cpu(basic->rx_goodput),
|
||||
le32_to_cpu(basic->tx_goodput),
|
||||
le32_to_cpu(basic->rx_bcast_frames),
|
||||
basic->rssi, basic->sqi, basic->snr, per,
|
||||
basic->selected_rfc, basic->rx_effective_ant_num,
|
||||
basic->my_rx_sector, basic->my_tx_sector,
|
||||
basic->other_rx_sector, basic->other_tx_sector);
|
||||
}
|
||||
|
||||
static void wil_link_stats_print_global(struct wil6210_priv *wil,
|
||||
struct seq_file *s,
|
||||
struct wmi_link_stats_global *global)
|
||||
{
|
||||
seq_printf(s, "Frames(rx:tx) %d:%d\n"
|
||||
"BA Frames(rx:tx) %d:%d\n"
|
||||
"Beacons %d\n"
|
||||
"Rx Errors (MIC:CRC) %d:%d\n"
|
||||
"Tx Errors (no ack) %d\n",
|
||||
le32_to_cpu(global->rx_frames),
|
||||
le32_to_cpu(global->tx_frames),
|
||||
le32_to_cpu(global->rx_ba_frames),
|
||||
le32_to_cpu(global->tx_ba_frames),
|
||||
le32_to_cpu(global->tx_beacons),
|
||||
le32_to_cpu(global->rx_mic_errors),
|
||||
le32_to_cpu(global->rx_crc_errors),
|
||||
le32_to_cpu(global->tx_fail_no_ack));
|
||||
}
|
||||
|
||||
static void wil_link_stats_debugfs_show_vif(struct wil6210_vif *vif,
|
||||
struct seq_file *s)
|
||||
{
|
||||
struct wil6210_priv *wil = vif_to_wil(vif);
|
||||
struct wmi_link_stats_basic *stats;
|
||||
int i;
|
||||
|
||||
if (!vif->fw_stats_ready) {
|
||||
seq_puts(s, "no statistics\n");
|
||||
return;
|
||||
}
|
||||
|
||||
seq_printf(s, "TSF %lld\n", vif->fw_stats_tsf);
|
||||
for (i = 0; i < ARRAY_SIZE(wil->sta); i++) {
|
||||
if (wil->sta[i].status == wil_sta_unused)
|
||||
continue;
|
||||
if (wil->sta[i].mid != vif->mid)
|
||||
continue;
|
||||
|
||||
stats = &wil->sta[i].fw_stats_basic;
|
||||
wil_link_stats_print_basic(vif, s, stats);
|
||||
}
|
||||
}
|
||||
|
||||
static int wil_link_stats_debugfs_show(struct seq_file *s, void *data)
|
||||
{
|
||||
struct wil6210_priv *wil = s->private;
|
||||
struct wil6210_vif *vif;
|
||||
int i, rc;
|
||||
|
||||
rc = mutex_lock_interruptible(&wil->vif_mutex);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/* iterate over all MIDs and show per-cid statistics. Then show the
|
||||
* global statistics
|
||||
*/
|
||||
for (i = 0; i < wil->max_vifs; i++) {
|
||||
vif = wil->vifs[i];
|
||||
|
||||
seq_printf(s, "MID %d ", i);
|
||||
if (!vif) {
|
||||
seq_puts(s, "unused\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
wil_link_stats_debugfs_show_vif(vif, s);
|
||||
}
|
||||
|
||||
mutex_unlock(&wil->vif_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wil_link_stats_seq_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, wil_link_stats_debugfs_show, inode->i_private);
|
||||
}
|
||||
|
||||
static ssize_t wil_link_stats_write(struct file *file, const char __user *buf,
|
||||
size_t len, loff_t *ppos)
|
||||
{
|
||||
struct seq_file *s = file->private_data;
|
||||
struct wil6210_priv *wil = s->private;
|
||||
int cid, interval, rc, i;
|
||||
struct wil6210_vif *vif;
|
||||
char *kbuf = kmalloc(len + 1, GFP_KERNEL);
|
||||
|
||||
if (!kbuf)
|
||||
return -ENOMEM;
|
||||
|
||||
rc = simple_write_to_buffer(kbuf, len, ppos, buf, len);
|
||||
if (rc != len) {
|
||||
kfree(kbuf);
|
||||
return rc >= 0 ? -EIO : rc;
|
||||
}
|
||||
|
||||
kbuf[len] = '\0';
|
||||
/* specify cid (use -1 for all cids) and snapshot interval in ms */
|
||||
rc = sscanf(kbuf, "%d %d", &cid, &interval);
|
||||
kfree(kbuf);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
if (rc < 2 || interval < 0)
|
||||
return -EINVAL;
|
||||
|
||||
wil_info(wil, "request link statistics, cid %d interval %d\n",
|
||||
cid, interval);
|
||||
|
||||
rc = mutex_lock_interruptible(&wil->vif_mutex);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
for (i = 0; i < wil->max_vifs; i++) {
|
||||
vif = wil->vifs[i];
|
||||
if (!vif)
|
||||
continue;
|
||||
|
||||
rc = wmi_link_stats_cfg(vif, WMI_LINK_STATS_TYPE_BASIC,
|
||||
(cid == -1 ? 0xff : cid), interval);
|
||||
if (rc)
|
||||
wil_err(wil, "link statistics failed for mid %d\n", i);
|
||||
}
|
||||
mutex_unlock(&wil->vif_mutex);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static const struct file_operations fops_link_stats = {
|
||||
.open = wil_link_stats_seq_open,
|
||||
.release = single_release,
|
||||
.read = seq_read,
|
||||
.write = wil_link_stats_write,
|
||||
.llseek = seq_lseek,
|
||||
};
|
||||
|
||||
static int
|
||||
wil_link_stats_global_debugfs_show(struct seq_file *s, void *data)
|
||||
{
|
||||
struct wil6210_priv *wil = s->private;
|
||||
|
||||
if (!wil->fw_stats_global.ready)
|
||||
return 0;
|
||||
|
||||
seq_printf(s, "TSF %lld\n", wil->fw_stats_global.tsf);
|
||||
wil_link_stats_print_global(wil, s, &wil->fw_stats_global.stats);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
wil_link_stats_global_seq_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, wil_link_stats_global_debugfs_show,
|
||||
inode->i_private);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
wil_link_stats_global_write(struct file *file, const char __user *buf,
|
||||
size_t len, loff_t *ppos)
|
||||
{
|
||||
struct seq_file *s = file->private_data;
|
||||
struct wil6210_priv *wil = s->private;
|
||||
int interval, rc;
|
||||
struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
|
||||
|
||||
/* specify snapshot interval in ms */
|
||||
rc = kstrtoint_from_user(buf, len, 0, &interval);
|
||||
if (rc || interval < 0) {
|
||||
wil_err(wil, "Invalid argument\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
wil_info(wil, "request global link stats, interval %d\n", interval);
|
||||
|
||||
rc = wmi_link_stats_cfg(vif, WMI_LINK_STATS_TYPE_GLOBAL, 0, interval);
|
||||
if (rc)
|
||||
wil_err(wil, "global link stats failed %d\n", rc);
|
||||
|
||||
return rc ? rc : len;
|
||||
}
|
||||
|
||||
static const struct file_operations fops_link_stats_global = {
|
||||
.open = wil_link_stats_global_seq_open,
|
||||
.release = single_release,
|
||||
.read = seq_read,
|
||||
.write = wil_link_stats_global_write,
|
||||
.llseek = seq_lseek,
|
||||
};
|
||||
|
||||
static ssize_t wil_read_file_led_cfg(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
|
|
@ -2134,6 +2472,9 @@ static const struct {
|
|||
{"srings", 0444, &fops_srings},
|
||||
{"status_msg", 0444, &fops_status_msg},
|
||||
{"rx_buff_mgmt", 0444, &fops_rx_buff_mgmt},
|
||||
{"tx_latency", 0644, &fops_tx_latency},
|
||||
{"link_stats", 0644, &fops_link_stats},
|
||||
{"link_stats_global", 0644, &fops_link_stats_global},
|
||||
};
|
||||
|
||||
static void wil6210_debugfs_init_files(struct wil6210_priv *wil,
|
||||
|
|
@ -2250,10 +2591,14 @@ int wil6210_debugfs_init(struct wil6210_priv *wil)
|
|||
|
||||
void wil6210_debugfs_remove(struct wil6210_priv *wil)
|
||||
{
|
||||
int i;
|
||||
|
||||
debugfs_remove_recursive(wil->debug);
|
||||
wil->debug = NULL;
|
||||
|
||||
kfree(wil->dbg_data.data_arr);
|
||||
for (i = 0; i < ARRAY_SIZE(wil->sta); i++)
|
||||
kfree(wil->sta[i].tx_latency_bins);
|
||||
|
||||
/* free pmc memory without sending command to fw, as it will
|
||||
* be reset on the way down anyway
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2014-2015,2017 Qualcomm Atheros, Inc.
|
||||
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
|
@ -22,6 +23,8 @@
|
|||
MODULE_FIRMWARE(WIL_FW_NAME_DEFAULT);
|
||||
MODULE_FIRMWARE(WIL_FW_NAME_SPARROW_PLUS);
|
||||
MODULE_FIRMWARE(WIL_BOARD_FILE_NAME);
|
||||
MODULE_FIRMWARE(WIL_FW_NAME_TALYN);
|
||||
MODULE_FIRMWARE(WIL_BRD_NAME_TALYN);
|
||||
|
||||
static
|
||||
void wil_memset_toio_32(volatile void __iomem *dst, u32 val,
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ fw_handle_capabilities(struct wil6210_priv *wil, const void *data,
|
|||
capabilities);
|
||||
bitmap_zero(wil->fw_capabilities, WMI_FW_CAPABILITY_MAX);
|
||||
memcpy(wil->fw_capabilities, rec->capabilities,
|
||||
min(sizeof(wil->fw_capabilities), capa_size));
|
||||
min_t(size_t, sizeof(wil->fw_capabilities), capa_size));
|
||||
wil_hex_dump_fw("CAPA", DUMP_PREFIX_OFFSET, 16, 1,
|
||||
rec->capabilities, capa_size, false);
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -625,6 +625,15 @@ static irqreturn_t wil6210_irq_misc_thread(int irq, void *cookie)
|
|||
|
||||
wil6210_unmask_irq_misc(wil, false);
|
||||
|
||||
/* in non-triple MSI case, this is done inside wil6210_thread_irq
|
||||
* because it has to be done after unmasking the pseudo.
|
||||
*/
|
||||
if (wil->n_msi == 3 && wil->suspend_resp_rcvd) {
|
||||
wil_dbg_irq(wil, "set suspend_resp_comp to true\n");
|
||||
wil->suspend_resp_comp = true;
|
||||
wake_up_interruptible(&wil->wq);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
|
@ -782,6 +791,40 @@ static irqreturn_t wil6210_hardirq(int irq, void *cookie)
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int wil6210_request_3msi(struct wil6210_priv *wil, int irq)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* IRQ's are in the following order:
|
||||
* - Tx
|
||||
* - Rx
|
||||
* - Misc
|
||||
*/
|
||||
rc = request_irq(irq, wil->txrx_ops.irq_tx, IRQF_SHARED,
|
||||
WIL_NAME "_tx", wil);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = request_irq(irq + 1, wil->txrx_ops.irq_rx, IRQF_SHARED,
|
||||
WIL_NAME "_rx", wil);
|
||||
if (rc)
|
||||
goto free0;
|
||||
|
||||
rc = request_threaded_irq(irq + 2, wil6210_irq_misc,
|
||||
wil6210_irq_misc_thread,
|
||||
IRQF_SHARED, WIL_NAME "_misc", wil);
|
||||
if (rc)
|
||||
goto free1;
|
||||
|
||||
return 0;
|
||||
free1:
|
||||
free_irq(irq + 1, wil);
|
||||
free0:
|
||||
free_irq(irq, wil);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* can't use wil_ioread32_and_clear because ICC value is not set yet */
|
||||
static inline void wil_clear32(void __iomem *addr)
|
||||
{
|
||||
|
|
@ -822,11 +865,12 @@ void wil6210_clear_halp(struct wil6210_priv *wil)
|
|||
wil6210_unmask_halp(wil);
|
||||
}
|
||||
|
||||
int wil6210_init_irq(struct wil6210_priv *wil, int irq, bool use_msi)
|
||||
int wil6210_init_irq(struct wil6210_priv *wil, int irq)
|
||||
{
|
||||
int rc;
|
||||
|
||||
wil_dbg_misc(wil, "init_irq: %s\n", use_msi ? "MSI" : "INTx");
|
||||
wil_dbg_misc(wil, "init_irq: %s, n_msi=%d\n",
|
||||
wil->n_msi ? "MSI" : "INTx", wil->n_msi);
|
||||
|
||||
if (wil->use_enhanced_dma_hw) {
|
||||
wil->txrx_ops.irq_tx = wil6210_irq_tx_edma;
|
||||
|
|
@ -835,10 +879,14 @@ int wil6210_init_irq(struct wil6210_priv *wil, int irq, bool use_msi)
|
|||
wil->txrx_ops.irq_tx = wil6210_irq_tx;
|
||||
wil->txrx_ops.irq_rx = wil6210_irq_rx;
|
||||
}
|
||||
rc = request_threaded_irq(irq, wil6210_hardirq,
|
||||
wil6210_thread_irq,
|
||||
use_msi ? 0 : IRQF_SHARED,
|
||||
WIL_NAME, wil);
|
||||
|
||||
if (wil->n_msi == 3)
|
||||
rc = wil6210_request_3msi(wil, irq);
|
||||
else
|
||||
rc = request_threaded_irq(irq, wil6210_hardirq,
|
||||
wil6210_thread_irq,
|
||||
wil->n_msi ? 0 : IRQF_SHARED,
|
||||
WIL_NAME, wil);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
@ -848,4 +896,8 @@ void wil6210_fini_irq(struct wil6210_priv *wil, int irq)
|
|||
|
||||
wil_mask_irq(wil);
|
||||
free_irq(irq, wil);
|
||||
if (wil->n_msi == 3) {
|
||||
free_irq(irq + 1, wil);
|
||||
free_irq(irq + 2, wil);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#define WAIT_FOR_HALP_VOTE_MS 100
|
||||
#define WAIT_FOR_SCAN_ABORT_MS 1000
|
||||
#define WIL_DEFAULT_NUM_RX_STATUS_RINGS 1
|
||||
#define WIL_BOARD_FILE_MAX_NAMELEN 128
|
||||
|
||||
bool debug_fw; /* = false; */
|
||||
module_param(debug_fw, bool, 0444);
|
||||
|
|
@ -278,6 +279,7 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
|
|||
}
|
||||
/* statistics */
|
||||
memset(&sta->stats, 0, sizeof(sta->stats));
|
||||
sta->stats.tx_latency_min_us = U32_MAX;
|
||||
}
|
||||
|
||||
static bool wil_vif_is_connected(struct wil6210_priv *wil, u8 mid)
|
||||
|
|
@ -1128,6 +1130,9 @@ void wil_refresh_fw_capabilities(struct wil6210_priv *wil)
|
|||
wiphy->max_sched_scan_plans = WMI_MAX_PLANS_NUM;
|
||||
}
|
||||
|
||||
if (test_bit(WMI_FW_CAPABILITY_TX_REQ_EXT, wil->fw_capabilities))
|
||||
wiphy->flags |= WIPHY_FLAG_OFFCHAN_TX;
|
||||
|
||||
if (wil->platform_ops.set_features) {
|
||||
features = (test_bit(WMI_FW_CAPABILITY_REF_CLOCK_CONTROL,
|
||||
wil->fw_capabilities) &&
|
||||
|
|
@ -1135,8 +1140,20 @@ void wil_refresh_fw_capabilities(struct wil6210_priv *wil)
|
|||
wil->platform_capa)) ?
|
||||
BIT(WIL_PLATFORM_FEATURE_FW_EXT_CLK_CONTROL) : 0;
|
||||
|
||||
if (wil->n_msi == 3)
|
||||
features |= BIT(WIL_PLATFORM_FEATURE_TRIPLE_MSI);
|
||||
|
||||
wil->platform_ops.set_features(wil->platform_handle, features);
|
||||
}
|
||||
|
||||
if (test_bit(WMI_FW_CAPABILITY_BACK_WIN_SIZE_64,
|
||||
wil->fw_capabilities)) {
|
||||
wil->max_agg_wsize = WIL_MAX_AGG_WSIZE_64;
|
||||
wil->max_ampdu_size = WIL_MAX_AMPDU_SIZE_128;
|
||||
} else {
|
||||
wil->max_agg_wsize = WIL_MAX_AGG_WSIZE;
|
||||
wil->max_ampdu_size = WIL_MAX_AMPDU_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r)
|
||||
|
|
@ -1148,6 +1165,28 @@ void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r)
|
|||
le32_to_cpus(&r->head);
|
||||
}
|
||||
|
||||
/* construct actual board file name to use */
|
||||
void wil_get_board_file(struct wil6210_priv *wil, char *buf, size_t len)
|
||||
{
|
||||
const char *board_file;
|
||||
const char *wil_talyn_fw_name = ftm_mode ? WIL_FW_NAME_FTM_TALYN :
|
||||
WIL_FW_NAME_TALYN;
|
||||
|
||||
if (wil->board_file) {
|
||||
board_file = wil->board_file;
|
||||
} else {
|
||||
/* If specific FW file is used for Talyn,
|
||||
* use specific board file
|
||||
*/
|
||||
if (strcmp(wil->wil_fw_name, wil_talyn_fw_name) == 0)
|
||||
board_file = WIL_BRD_NAME_TALYN;
|
||||
else
|
||||
board_file = WIL_BOARD_FILE_NAME;
|
||||
}
|
||||
|
||||
strlcpy(buf, board_file, len);
|
||||
}
|
||||
|
||||
static int wil_get_bl_info(struct wil6210_priv *wil)
|
||||
{
|
||||
struct net_device *ndev = wil->main_ndev;
|
||||
|
|
@ -1269,7 +1308,7 @@ static int wil_get_otp_info(struct wil6210_priv *wil)
|
|||
|
||||
static int wil_wait_for_fw_ready(struct wil6210_priv *wil)
|
||||
{
|
||||
ulong to = msecs_to_jiffies(1000);
|
||||
ulong to = msecs_to_jiffies(2000);
|
||||
ulong left = wait_for_completion_timeout(&wil->wmi_ready, to);
|
||||
|
||||
if (0 == left) {
|
||||
|
|
@ -1519,8 +1558,17 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
|
|||
|
||||
wil_set_oob_mode(wil, oob_mode);
|
||||
if (load_fw) {
|
||||
char board_file[WIL_BOARD_FILE_MAX_NAMELEN];
|
||||
|
||||
if (wil->secured_boot) {
|
||||
wil_err(wil, "secured boot is not supported\n");
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
board_file[0] = '\0';
|
||||
wil_get_board_file(wil, board_file, sizeof(board_file));
|
||||
wil_info(wil, "Use firmware <%s> + board <%s>\n",
|
||||
wil->wil_fw_name, WIL_BOARD_FILE_NAME);
|
||||
wil->wil_fw_name, board_file);
|
||||
|
||||
if (!no_flash)
|
||||
wil_bl_prepare_halt(wil);
|
||||
|
|
@ -1532,11 +1580,9 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
|
|||
if (rc)
|
||||
goto out;
|
||||
if (wil->brd_file_addr)
|
||||
rc = wil_request_board(wil, WIL_BOARD_FILE_NAME);
|
||||
rc = wil_request_board(wil, board_file);
|
||||
else
|
||||
rc = wil_request_firmware(wil,
|
||||
WIL_BOARD_FILE_NAME,
|
||||
true);
|
||||
rc = wil_request_firmware(wil, board_file, true);
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
|
|
@ -1568,6 +1614,13 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
|
|||
|
||||
wil->txrx_ops.configure_interrupt_moderation(wil);
|
||||
|
||||
/* Enable OFU rdy valid bug fix, to prevent hang in oful34_rx
|
||||
* while there is back-pressure from Host during RX
|
||||
*/
|
||||
if (wil->hw_version >= HW_VER_TALYN_MB)
|
||||
wil_s(wil, RGF_DMA_MISC_CTL,
|
||||
BIT_OFUL34_RDY_VALID_BUG_FIX_EN);
|
||||
|
||||
rc = wil_restore_vifs(wil);
|
||||
if (rc) {
|
||||
wil_err(wil, "failed to restore vifs, rc %d\n", rc);
|
||||
|
|
|
|||
|
|
@ -24,11 +24,11 @@
|
|||
#include <linux/rtnetlink.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
static bool use_msi = true;
|
||||
module_param(use_msi, bool, 0444);
|
||||
MODULE_PARM_DESC(use_msi, " Use MSI interrupt, default - true");
|
||||
static int n_msi = 3;
|
||||
module_param(n_msi, int, 0444);
|
||||
MODULE_PARM_DESC(n_msi, " Use MSI interrupt: 0 - use INTx, 1 - single, or 3 - (default) ");
|
||||
|
||||
static bool ftm_mode;
|
||||
bool ftm_mode;
|
||||
module_param(ftm_mode, bool, 0444);
|
||||
MODULE_PARM_DESC(ftm_mode, " Set factory test mode, default - false");
|
||||
|
||||
|
|
@ -93,6 +93,10 @@ int wil_set_capabilities(struct wil6210_priv *wil)
|
|||
if (wil_r(wil, RGF_USER_OTP_HW_RD_MACHINE_1) &
|
||||
BIT_NO_FLASH_INDICATION)
|
||||
set_bit(hw_capa_no_flash, wil->hw_capa);
|
||||
wil_fw_name = ftm_mode ? WIL_FW_NAME_FTM_TALYN :
|
||||
WIL_FW_NAME_TALYN;
|
||||
if (wil_fw_verify_file_exists(wil, wil_fw_name))
|
||||
wil->wil_fw_name = wil_fw_name;
|
||||
break;
|
||||
case JTAG_DEV_ID_TALYN_MB:
|
||||
wil->hw_name = "Talyn-MB";
|
||||
|
|
@ -104,6 +108,10 @@ int wil_set_capabilities(struct wil6210_priv *wil)
|
|||
set_bit(hw_capa_no_flash, wil->hw_capa);
|
||||
wil->use_enhanced_dma_hw = true;
|
||||
wil->use_rx_hw_reordering = true;
|
||||
wil_fw_name = ftm_mode ? WIL_FW_NAME_FTM_TALYN :
|
||||
WIL_FW_NAME_TALYN;
|
||||
if (wil_fw_verify_file_exists(wil, wil_fw_name))
|
||||
wil->wil_fw_name = wil_fw_name;
|
||||
break;
|
||||
default:
|
||||
wil_err(wil, "Unknown board hardware, chip_id 0x%08x, chip_revision 0x%08x\n",
|
||||
|
|
@ -142,12 +150,24 @@ int wil_set_capabilities(struct wil6210_priv *wil)
|
|||
|
||||
void wil_disable_irq(struct wil6210_priv *wil)
|
||||
{
|
||||
disable_irq(wil->pdev->irq);
|
||||
int irq = wil->pdev->irq;
|
||||
|
||||
disable_irq(irq);
|
||||
if (wil->n_msi == 3) {
|
||||
disable_irq(irq + 1);
|
||||
disable_irq(irq + 2);
|
||||
}
|
||||
}
|
||||
|
||||
void wil_enable_irq(struct wil6210_priv *wil)
|
||||
{
|
||||
enable_irq(wil->pdev->irq);
|
||||
int irq = wil->pdev->irq;
|
||||
|
||||
enable_irq(irq);
|
||||
if (wil->n_msi == 3) {
|
||||
enable_irq(irq + 1);
|
||||
enable_irq(irq + 2);
|
||||
}
|
||||
}
|
||||
|
||||
static void wil_remove_all_additional_vifs(struct wil6210_priv *wil)
|
||||
|
|
@ -174,28 +194,47 @@ static int wil_if_pcie_enable(struct wil6210_priv *wil)
|
|||
* and only MSI should be used
|
||||
*/
|
||||
int msi_only = pdev->msi_enabled;
|
||||
bool _use_msi = use_msi;
|
||||
|
||||
wil_dbg_misc(wil, "if_pcie_enable\n");
|
||||
|
||||
pci_set_master(pdev);
|
||||
|
||||
wil_dbg_misc(wil, "Setup %s interrupt\n", use_msi ? "MSI" : "INTx");
|
||||
|
||||
if (use_msi && pci_enable_msi(pdev)) {
|
||||
wil_err(wil, "pci_enable_msi failed, use INTx\n");
|
||||
_use_msi = false;
|
||||
/* how many MSI interrupts to request? */
|
||||
switch (n_msi) {
|
||||
case 3:
|
||||
case 1:
|
||||
wil_dbg_misc(wil, "Setup %d MSI interrupts\n", n_msi);
|
||||
break;
|
||||
case 0:
|
||||
wil_dbg_misc(wil, "MSI interrupts disabled, use INTx\n");
|
||||
break;
|
||||
default:
|
||||
wil_err(wil, "Invalid n_msi=%d, default to 1\n", n_msi);
|
||||
n_msi = 1;
|
||||
}
|
||||
|
||||
if (!_use_msi && msi_only) {
|
||||
if (n_msi == 3 &&
|
||||
pci_alloc_irq_vectors(pdev, n_msi, n_msi, PCI_IRQ_MSI) < n_msi) {
|
||||
wil_err(wil, "3 MSI mode failed, try 1 MSI\n");
|
||||
n_msi = 1;
|
||||
}
|
||||
|
||||
if (n_msi == 1 && pci_enable_msi(pdev)) {
|
||||
wil_err(wil, "pci_enable_msi failed, use INTx\n");
|
||||
n_msi = 0;
|
||||
}
|
||||
|
||||
wil->n_msi = n_msi;
|
||||
|
||||
if (wil->n_msi == 0 && msi_only) {
|
||||
wil_err(wil, "Interrupt pin not routed, unable to use INTx\n");
|
||||
rc = -ENODEV;
|
||||
goto stop_master;
|
||||
}
|
||||
|
||||
rc = wil6210_init_irq(wil, pdev->irq, _use_msi);
|
||||
rc = wil6210_init_irq(wil, pdev->irq);
|
||||
if (rc)
|
||||
goto stop_master;
|
||||
goto release_vectors;
|
||||
|
||||
/* need reset here to obtain MAC */
|
||||
mutex_lock(&wil->mutex);
|
||||
|
|
@ -208,8 +247,9 @@ static int wil_if_pcie_enable(struct wil6210_priv *wil)
|
|||
|
||||
release_irq:
|
||||
wil6210_fini_irq(wil, pdev->irq);
|
||||
/* safe to call if no MSI */
|
||||
pci_disable_msi(pdev);
|
||||
release_vectors:
|
||||
/* safe to call if no allocation */
|
||||
pci_free_irq_vectors(pdev);
|
||||
stop_master:
|
||||
pci_clear_master(pdev);
|
||||
return rc;
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
|
|||
{
|
||||
struct wil6210_vif *vif;
|
||||
struct net_device *ndev;
|
||||
int tid, cid, mid, mcast;
|
||||
int tid, cid, mid, mcast, retry;
|
||||
u16 seq;
|
||||
struct wil_sta_info *sta;
|
||||
struct wil_tid_ampdu_rx *r;
|
||||
|
|
@ -103,7 +103,7 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
|
|||
int index;
|
||||
|
||||
wil->txrx_ops.get_reorder_params(wil, skb, &tid, &cid, &mid, &seq,
|
||||
&mcast);
|
||||
&mcast, &retry);
|
||||
sta = &wil->sta[cid];
|
||||
|
||||
wil_dbg_txrx(wil, "MID %d CID %d TID %d Seq 0x%03x mcast %01x\n",
|
||||
|
|
@ -117,11 +117,6 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
|
|||
}
|
||||
ndev = vif_to_ndev(vif);
|
||||
|
||||
if (unlikely(mcast)) {
|
||||
wil_netif_rx_any(skb, ndev);
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock(&sta->tid_rx_lock);
|
||||
|
||||
r = sta->tid_rx[tid];
|
||||
|
|
@ -130,6 +125,19 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (unlikely(mcast)) {
|
||||
if (retry && seq == r->mcast_last_seq) {
|
||||
r->drop_dup_mcast++;
|
||||
wil_dbg_txrx(wil, "Rx drop: dup mcast seq 0x%03x\n",
|
||||
seq);
|
||||
dev_kfree_skb(skb);
|
||||
goto out;
|
||||
}
|
||||
r->mcast_last_seq = seq;
|
||||
wil_netif_rx_any(skb, ndev);
|
||||
goto out;
|
||||
}
|
||||
|
||||
r->total++;
|
||||
hseq = r->head_seq_num;
|
||||
|
||||
|
|
@ -262,6 +270,7 @@ struct wil_tid_ampdu_rx *wil_tid_ampdu_rx_alloc(struct wil6210_priv *wil,
|
|||
r->buf_size = size;
|
||||
r->stored_mpdu_num = 0;
|
||||
r->first_time = true;
|
||||
r->mcast_last_seq = U16_MAX;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
@ -288,7 +297,7 @@ void wil_tid_ampdu_rx_free(struct wil6210_priv *wil,
|
|||
/* ADDBA processing */
|
||||
static u16 wil_agg_size(struct wil6210_priv *wil, u16 req_agg_wsize)
|
||||
{
|
||||
u16 max_agg_size = min_t(u16, WIL_MAX_AGG_WSIZE, WIL_MAX_AMPDU_SIZE /
|
||||
u16 max_agg_size = min_t(u16, wil->max_agg_wsize, wil->max_ampdu_size /
|
||||
(mtu_max + WIL_MAX_MPDU_OVERHEAD));
|
||||
|
||||
if (!req_agg_wsize)
|
||||
|
|
@ -355,11 +364,11 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
|
|||
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;
|
||||
wil->max_agg_wsize);
|
||||
agg_wsize = wil->max_agg_wsize;
|
||||
} else {
|
||||
agg_wsize = min_t(u16,
|
||||
WIL_MAX_AGG_WSIZE, req_agg_wsize);
|
||||
wil->max_agg_wsize, req_agg_wsize);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -281,6 +281,12 @@ static int wil_vring_alloc_skb(struct wil6210_priv *wil, struct wil_ring *vring,
|
|||
skb_reserve(skb, headroom);
|
||||
skb_put(skb, sz);
|
||||
|
||||
/**
|
||||
* Make sure that the network stack calculates checksum for packets
|
||||
* which failed the HW checksum calculation
|
||||
*/
|
||||
skb->ip_summed = CHECKSUM_NONE;
|
||||
|
||||
pa = dma_map_single(dev, skb->data, skb->len, DMA_FROM_DEVICE);
|
||||
if (unlikely(dma_mapping_error(dev, pa))) {
|
||||
kfree_skb(skb);
|
||||
|
|
@ -569,6 +575,8 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
|
|||
* mis-calculates TCP checksum - if it should be 0x0,
|
||||
* it writes 0xffff in violation of RFC 1624
|
||||
*/
|
||||
else
|
||||
stats->rx_csum_err++;
|
||||
}
|
||||
|
||||
if (snaplen) {
|
||||
|
|
@ -678,6 +686,21 @@ static int wil_rx_crypto_check(struct wil6210_priv *wil, struct sk_buff *skb)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int wil_rx_error_check(struct wil6210_priv *wil, struct sk_buff *skb,
|
||||
struct wil_net_stats *stats)
|
||||
{
|
||||
struct vring_rx_desc *d = wil_skb_rxdesc(skb);
|
||||
|
||||
if ((d->dma.status & RX_DMA_STATUS_ERROR) &&
|
||||
(d->dma.error & RX_DMA_ERROR_MIC)) {
|
||||
stats->rx_mic_error++;
|
||||
wil_dbg_txrx(wil, "MIC error, dropping packet\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void wil_get_netif_rx_params(struct sk_buff *skb, int *cid,
|
||||
int *security)
|
||||
{
|
||||
|
|
@ -736,6 +759,12 @@ void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev)
|
|||
goto stats;
|
||||
}
|
||||
|
||||
/* check errors reported by HW and update statistics */
|
||||
if (unlikely(wil->txrx_ops.rx_error_check(wil, skb, stats))) {
|
||||
dev_kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
|
||||
if (wdev->iftype == NL80211_IFTYPE_AP && !vif->ap_isolate) {
|
||||
if (mcast) {
|
||||
/* send multicast frames both to higher layers in
|
||||
|
|
@ -1672,6 +1701,11 @@ static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct wil6210_vif *vif,
|
|||
*/
|
||||
wmb();
|
||||
|
||||
if (wil->tx_latency)
|
||||
*(ktime_t *)&skb->cb = ktime_get();
|
||||
else
|
||||
memset(skb->cb, 0, sizeof(ktime_t));
|
||||
|
||||
wil_w(wil, vring->hwtail, vring->swhead);
|
||||
return 0;
|
||||
|
||||
|
|
@ -1823,6 +1857,11 @@ static int __wil_tx_ring(struct wil6210_priv *wil, struct wil6210_vif *vif,
|
|||
*/
|
||||
wmb();
|
||||
|
||||
if (wil->tx_latency)
|
||||
*(ktime_t *)&skb->cb = ktime_get();
|
||||
else
|
||||
memset(skb->cb, 0, sizeof(ktime_t));
|
||||
|
||||
wil_w(wil, ring->hwtail, ring->swhead);
|
||||
|
||||
return 0;
|
||||
|
|
@ -2044,6 +2083,31 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev)
|
|||
return NET_XMIT_DROP;
|
||||
}
|
||||
|
||||
void wil_tx_latency_calc(struct wil6210_priv *wil, struct sk_buff *skb,
|
||||
struct wil_sta_info *sta)
|
||||
{
|
||||
int skb_time_us;
|
||||
int bin;
|
||||
|
||||
if (!wil->tx_latency)
|
||||
return;
|
||||
|
||||
if (ktime_to_ms(*(ktime_t *)&skb->cb) == 0)
|
||||
return;
|
||||
|
||||
skb_time_us = ktime_us_delta(ktime_get(), *(ktime_t *)&skb->cb);
|
||||
bin = skb_time_us / wil->tx_latency_res;
|
||||
bin = min_t(int, bin, WIL_NUM_LATENCY_BINS - 1);
|
||||
|
||||
wil_dbg_txrx(wil, "skb time %dus => bin %d\n", skb_time_us, bin);
|
||||
sta->tx_latency_bins[bin]++;
|
||||
sta->stats.tx_latency_total_us += skb_time_us;
|
||||
if (skb_time_us < sta->stats.tx_latency_min_us)
|
||||
sta->stats.tx_latency_min_us = skb_time_us;
|
||||
if (skb_time_us > sta->stats.tx_latency_max_us)
|
||||
sta->stats.tx_latency_max_us = skb_time_us;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up transmitted skb's from the Tx VRING
|
||||
*
|
||||
|
|
@ -2130,6 +2194,9 @@ int wil_tx_complete(struct wil6210_vif *vif, int ringid)
|
|||
if (stats) {
|
||||
stats->tx_packets++;
|
||||
stats->tx_bytes += skb->len;
|
||||
|
||||
wil_tx_latency_calc(wil, skb,
|
||||
&wil->sta[cid]);
|
||||
}
|
||||
} else {
|
||||
ndev->stats.tx_errors++;
|
||||
|
|
@ -2180,7 +2247,7 @@ static inline void wil_tx_fini(struct wil6210_priv *wil) {}
|
|||
|
||||
static void wil_get_reorder_params(struct wil6210_priv *wil,
|
||||
struct sk_buff *skb, int *tid, int *cid,
|
||||
int *mid, u16 *seq, int *mcast)
|
||||
int *mid, u16 *seq, int *mcast, int *retry)
|
||||
{
|
||||
struct vring_rx_desc *d = wil_skb_rxdesc(skb);
|
||||
|
||||
|
|
@ -2189,6 +2256,7 @@ static void wil_get_reorder_params(struct wil6210_priv *wil,
|
|||
*mid = wil_rxdesc_mid(d);
|
||||
*seq = wil_rxdesc_seq(d);
|
||||
*mcast = wil_rxdesc_mcast(d);
|
||||
*retry = wil_rxdesc_retry(d);
|
||||
}
|
||||
|
||||
void wil_init_txrx_ops_legacy_dma(struct wil6210_priv *wil)
|
||||
|
|
@ -2211,6 +2279,7 @@ void wil_init_txrx_ops_legacy_dma(struct wil6210_priv *wil)
|
|||
wil->txrx_ops.get_netif_rx_params =
|
||||
wil_get_netif_rx_params;
|
||||
wil->txrx_ops.rx_crypto_check = wil_rx_crypto_check;
|
||||
wil->txrx_ops.rx_error_check = wil_rx_error_check;
|
||||
wil->txrx_ops.is_rx_idle = wil_is_rx_idle;
|
||||
wil->txrx_ops.rx_fini = wil_rx_fini;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -500,6 +500,11 @@ static inline int wil_rxdesc_ext_subtype(struct vring_rx_desc *d)
|
|||
return WIL_GET_BITS(d->mac.d0, 28, 31);
|
||||
}
|
||||
|
||||
static inline int wil_rxdesc_retry(struct vring_rx_desc *d)
|
||||
{
|
||||
return WIL_GET_BITS(d->mac.d0, 31, 31);
|
||||
}
|
||||
|
||||
static inline int wil_rxdesc_key_id(struct vring_rx_desc *d)
|
||||
{
|
||||
return WIL_GET_BITS(d->mac.d1, 4, 5);
|
||||
|
|
@ -615,5 +620,7 @@ void wil_tid_ampdu_rx_free(struct wil6210_priv *wil,
|
|||
struct wil_tid_ampdu_rx *r);
|
||||
void wil_tx_data_init(struct wil_ring_tx_data *txdata);
|
||||
void wil_init_txrx_ops_legacy_dma(struct wil6210_priv *wil);
|
||||
void wil_tx_latency_calc(struct wil6210_priv *wil, struct sk_buff *skb,
|
||||
struct wil_sta_info *sta);
|
||||
|
||||
#endif /* WIL6210_TXRX_H */
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@
|
|||
#include "trace.h"
|
||||
|
||||
#define WIL_EDMA_MAX_DATA_OFFSET (2)
|
||||
/* RX buffer size must be aligned to 4 bytes */
|
||||
#define WIL_EDMA_RX_BUF_LEN_DEFAULT (2048)
|
||||
|
||||
static void wil_tx_desc_unmap_edma(struct device *dev,
|
||||
union wil_tx_desc *desc,
|
||||
|
|
@ -158,8 +160,7 @@ static int wil_ring_alloc_skb_edma(struct wil6210_priv *wil,
|
|||
struct wil_ring *ring, u32 i)
|
||||
{
|
||||
struct device *dev = wil_to_dev(wil);
|
||||
unsigned int sz = wil->rx_buf_len + ETH_HLEN +
|
||||
WIL_EDMA_MAX_DATA_OFFSET;
|
||||
unsigned int sz = ALIGN(wil->rx_buf_len, 4);
|
||||
dma_addr_t pa;
|
||||
u16 buff_id;
|
||||
struct list_head *active = &wil->rx_buff_mgmt.active;
|
||||
|
|
@ -182,6 +183,12 @@ static int wil_ring_alloc_skb_edma(struct wil6210_priv *wil,
|
|||
|
||||
skb_put(skb, sz);
|
||||
|
||||
/**
|
||||
* Make sure that the network stack calculates checksum for packets
|
||||
* which failed the HW checksum calculation
|
||||
*/
|
||||
skb->ip_summed = CHECKSUM_NONE;
|
||||
|
||||
pa = dma_map_single(dev, skb->data, skb->len, DMA_FROM_DEVICE);
|
||||
if (unlikely(dma_mapping_error(dev, pa))) {
|
||||
kfree_skb(skb);
|
||||
|
|
@ -503,7 +510,7 @@ static int wil_init_rx_desc_ring(struct wil6210_priv *wil, u16 desc_ring_size,
|
|||
static void wil_get_reorder_params_edma(struct wil6210_priv *wil,
|
||||
struct sk_buff *skb, int *tid,
|
||||
int *cid, int *mid, u16 *seq,
|
||||
int *mcast)
|
||||
int *mcast, int *retry)
|
||||
{
|
||||
struct wil_rx_status_extended *s = wil_skb_rxstatus(skb);
|
||||
|
||||
|
|
@ -512,6 +519,7 @@ static void wil_get_reorder_params_edma(struct wil6210_priv *wil,
|
|||
*mid = wil_rx_status_get_mid(s);
|
||||
*seq = le16_to_cpu(wil_rx_status_get_seq(wil, s));
|
||||
*mcast = wil_rx_status_get_mcast(s);
|
||||
*retry = wil_rx_status_get_retry(s);
|
||||
}
|
||||
|
||||
static void wil_get_netif_rx_params_edma(struct sk_buff *skb, int *cid,
|
||||
|
|
@ -593,7 +601,7 @@ static bool wil_is_rx_idle_edma(struct wil6210_priv *wil)
|
|||
static void wil_rx_buf_len_init_edma(struct wil6210_priv *wil)
|
||||
{
|
||||
wil->rx_buf_len = rx_large_buf ?
|
||||
WIL_MAX_ETH_MTU : TXRX_BUF_LEN_DEFAULT - WIL_MAX_MPDU_OVERHEAD;
|
||||
WIL_MAX_ETH_MTU : WIL_EDMA_RX_BUF_LEN_DEFAULT;
|
||||
}
|
||||
|
||||
static int wil_rx_init_edma(struct wil6210_priv *wil, u16 desc_ring_size)
|
||||
|
|
@ -626,8 +634,7 @@ static int wil_rx_init_edma(struct wil6210_priv *wil, u16 desc_ring_size)
|
|||
|
||||
wil_rx_buf_len_init_edma(wil);
|
||||
|
||||
max_rx_pl_per_desc = wil->rx_buf_len + ETH_HLEN +
|
||||
WIL_EDMA_MAX_DATA_OFFSET;
|
||||
max_rx_pl_per_desc = ALIGN(wil->rx_buf_len, 4);
|
||||
|
||||
/* Use debugfs dbg_num_rx_srings if set, reserve one sring for TX */
|
||||
if (wil->num_rx_status_rings > WIL6210_MAX_STATUS_RINGS - 1)
|
||||
|
|
@ -794,14 +801,15 @@ static int wil_check_bar(struct wil6210_priv *wil, void *msg, int cid,
|
|||
return -EAGAIN;
|
||||
}
|
||||
|
||||
static int wil_rx_edma_check_errors(struct wil6210_priv *wil, void *msg,
|
||||
struct wil_net_stats *stats,
|
||||
struct sk_buff *skb)
|
||||
static int wil_rx_error_check_edma(struct wil6210_priv *wil,
|
||||
struct sk_buff *skb,
|
||||
struct wil_net_stats *stats)
|
||||
{
|
||||
int error;
|
||||
int l2_rx_status;
|
||||
int l3_rx_status;
|
||||
int l4_rx_status;
|
||||
void *msg = wil_skb_rxstatus(skb);
|
||||
|
||||
error = wil_rx_status_get_error(msg);
|
||||
if (!error) {
|
||||
|
|
@ -845,6 +853,8 @@ static int wil_rx_edma_check_errors(struct wil6210_priv *wil, void *msg,
|
|||
* mis-calculates TCP checksum - if it should be 0x0,
|
||||
* it writes 0xffff in violation of RFC 1624
|
||||
*/
|
||||
else
|
||||
stats->rx_csum_err++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -859,12 +869,10 @@ static struct sk_buff *wil_sring_reap_rx_edma(struct wil6210_priv *wil,
|
|||
struct sk_buff *skb;
|
||||
dma_addr_t pa;
|
||||
struct wil_ring_rx_data *rxdata = &sring->rx_data;
|
||||
unsigned int sz = wil->rx_buf_len + ETH_HLEN +
|
||||
WIL_EDMA_MAX_DATA_OFFSET;
|
||||
unsigned int sz = ALIGN(wil->rx_buf_len, 4);
|
||||
struct wil_net_stats *stats = NULL;
|
||||
u16 dmalen;
|
||||
int cid;
|
||||
int rc;
|
||||
bool eop, headstolen;
|
||||
int delta;
|
||||
u8 dr_bit;
|
||||
|
|
@ -936,13 +944,6 @@ static struct sk_buff *wil_sring_reap_rx_edma(struct wil6210_priv *wil,
|
|||
goto skipping;
|
||||
}
|
||||
|
||||
/* Check and treat errors reported by HW */
|
||||
rc = wil_rx_edma_check_errors(wil, msg, stats, skb);
|
||||
if (rc) {
|
||||
rxdata->skipping = true;
|
||||
goto skipping;
|
||||
}
|
||||
|
||||
if (unlikely(dmalen > sz)) {
|
||||
wil_err(wil, "Rx size too large: %d bytes!\n", dmalen);
|
||||
stats->rx_large_frame++;
|
||||
|
|
@ -1223,6 +1224,9 @@ int wil_tx_sring_handler(struct wil6210_priv *wil,
|
|||
if (stats) {
|
||||
stats->tx_packets++;
|
||||
stats->tx_bytes += skb->len;
|
||||
|
||||
wil_tx_latency_calc(wil, skb,
|
||||
&wil->sta[cid]);
|
||||
}
|
||||
} else {
|
||||
ndev->stats.tx_errors++;
|
||||
|
|
@ -1473,6 +1477,11 @@ static int __wil_tx_ring_tso_edma(struct wil6210_priv *wil,
|
|||
*/
|
||||
wmb();
|
||||
|
||||
if (wil->tx_latency)
|
||||
*(ktime_t *)&skb->cb = ktime_get();
|
||||
else
|
||||
memset(skb->cb, 0, sizeof(ktime_t));
|
||||
|
||||
wil_w(wil, ring->hwtail, ring->swhead);
|
||||
|
||||
return 0;
|
||||
|
|
@ -1592,6 +1601,7 @@ void wil_init_txrx_ops_edma(struct wil6210_priv *wil)
|
|||
wil->txrx_ops.get_reorder_params = wil_get_reorder_params_edma;
|
||||
wil->txrx_ops.get_netif_rx_params = wil_get_netif_rx_params_edma;
|
||||
wil->txrx_ops.rx_crypto_check = wil_rx_crypto_check_edma;
|
||||
wil->txrx_ops.rx_error_check = wil_rx_error_check_edma;
|
||||
wil->txrx_ops.is_rx_idle = wil_is_rx_idle_edma;
|
||||
wil->txrx_ops.rx_fini = wil_rx_fini_edma;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -471,6 +471,12 @@ static inline __le16 wil_rx_status_get_seq(struct wil6210_priv *wil, void *msg)
|
|||
return ((struct wil_rx_status_extended *)msg)->ext.seq_num;
|
||||
}
|
||||
|
||||
static inline u8 wil_rx_status_get_retry(void *msg)
|
||||
{
|
||||
/* retry bit is missing in EDMA HW. return 1 to be on the safe side */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int wil_rx_status_get_mid(void *msg)
|
||||
{
|
||||
if (!(((struct wil_rx_status_compressed *)msg)->d0 &
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ extern bool rx_align_2;
|
|||
extern bool rx_large_buf;
|
||||
extern bool debug_fw;
|
||||
extern bool disable_ap_sme;
|
||||
extern bool ftm_mode;
|
||||
|
||||
struct wil6210_priv;
|
||||
struct wil6210_vif;
|
||||
|
|
@ -50,11 +51,17 @@ union wil_tx_desc;
|
|||
#define WIL_FW_NAME_SPARROW_PLUS "wil6210_sparrow_plus.fw"
|
||||
#define WIL_FW_NAME_FTM_SPARROW_PLUS "wil6210_sparrow_plus_ftm.fw"
|
||||
|
||||
#define WIL_FW_NAME_TALYN "wil6436.fw"
|
||||
#define WIL_FW_NAME_FTM_TALYN "wil6436_ftm.fw"
|
||||
#define WIL_BRD_NAME_TALYN "wil6436.brd"
|
||||
|
||||
#define WIL_BOARD_FILE_NAME "wil6210.brd" /* board & radio parameters */
|
||||
|
||||
#define WIL_DEFAULT_BUS_REQUEST_KBPS 128000 /* ~1Gbps */
|
||||
#define WIL_MAX_BUS_REQUEST_KBPS 800000 /* ~6.1Gbps */
|
||||
|
||||
#define WIL_NUM_LATENCY_BINS 200
|
||||
|
||||
/* maximum number of virtual interfaces the driver supports
|
||||
* (including the main interface)
|
||||
*/
|
||||
|
|
@ -85,6 +92,8 @@ static inline u32 WIL_GET_BITS(u32 x, int b0, int b1)
|
|||
#define WIL6210_NAPI_BUDGET (16) /* arbitrary */
|
||||
#define WIL_MAX_AMPDU_SIZE (64 * 1024) /* FW/HW limit */
|
||||
#define WIL_MAX_AGG_WSIZE (32) /* FW/HW limit */
|
||||
#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)
|
||||
|
||||
/* Hardware offload block adds the following:
|
||||
|
|
@ -293,6 +302,8 @@ struct RGF_ICR {
|
|||
#define BIT_DMA_ITR_RX_IDL_CNT_CTL_FOREVER BIT(2)
|
||||
#define BIT_DMA_ITR_RX_IDL_CNT_CTL_CLR BIT(3)
|
||||
#define BIT_DMA_ITR_RX_IDL_CNT_CTL_REACHED_TRESH BIT(4)
|
||||
#define RGF_DMA_MISC_CTL (0x881d6c)
|
||||
#define BIT_OFUL34_RDY_VALID_BUG_FIX_EN BIT(7)
|
||||
|
||||
#define RGF_DMA_PSEUDO_CAUSE (0x881c68)
|
||||
#define RGF_DMA_PSEUDO_CAUSE_MASK_SW (0x881c6c)
|
||||
|
|
@ -543,6 +554,31 @@ struct wil_status_ring {
|
|||
struct wil_ring_rx_data rx_data;
|
||||
};
|
||||
|
||||
#define WIL_STA_TID_NUM (16)
|
||||
#define WIL_MCS_MAX (12) /* Maximum MCS supported */
|
||||
|
||||
struct wil_net_stats {
|
||||
unsigned long rx_packets;
|
||||
unsigned long tx_packets;
|
||||
unsigned long rx_bytes;
|
||||
unsigned long tx_bytes;
|
||||
unsigned long tx_errors;
|
||||
u32 tx_latency_min_us;
|
||||
u32 tx_latency_max_us;
|
||||
u64 tx_latency_total_us;
|
||||
unsigned long rx_dropped;
|
||||
unsigned long rx_non_data_frame;
|
||||
unsigned long rx_short_frame;
|
||||
unsigned long rx_large_frame;
|
||||
unsigned long rx_replay;
|
||||
unsigned long rx_mic_error;
|
||||
unsigned long rx_key_error; /* eDMA specific */
|
||||
unsigned long rx_amsdu_error; /* eDMA specific */
|
||||
unsigned long rx_csum_err;
|
||||
u16 last_mcs_rx;
|
||||
u64 rx_per_mcs[WIL_MCS_MAX + 1];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct tx_rx_ops - different TX/RX ops for legacy and enhanced
|
||||
* DMA flow
|
||||
|
|
@ -572,10 +608,12 @@ struct wil_txrx_ops {
|
|||
u16 agg_wsize, u16 timeout);
|
||||
void (*get_reorder_params)(struct wil6210_priv *wil,
|
||||
struct sk_buff *skb, int *tid, int *cid,
|
||||
int *mid, u16 *seq, int *mcast);
|
||||
int *mid, u16 *seq, int *mcast, int *retry);
|
||||
void (*get_netif_rx_params)(struct sk_buff *skb,
|
||||
int *cid, int *security);
|
||||
int (*rx_crypto_check)(struct wil6210_priv *wil, struct sk_buff *skb);
|
||||
int (*rx_error_check)(struct wil6210_priv *wil, struct sk_buff *skb,
|
||||
struct wil_net_stats *stats);
|
||||
bool (*is_rx_idle)(struct wil6210_priv *wil);
|
||||
irqreturn_t (*irq_rx)(int irq, void *cookie);
|
||||
};
|
||||
|
|
@ -625,6 +663,8 @@ struct pci_dev;
|
|||
* @drop_dup: duplicate frames dropped for this reorder buffer
|
||||
* @drop_old: old frames dropped for this reorder buffer
|
||||
* @first_time: true when this buffer used 1-st time
|
||||
* @mcast_last_seq: sequence number (SN) of last received multicast packet
|
||||
* @drop_dup_mcast: duplicate multicast frames dropped for this reorder buffer
|
||||
*/
|
||||
struct wil_tid_ampdu_rx {
|
||||
struct sk_buff **reorder_buf;
|
||||
|
|
@ -638,6 +678,8 @@ struct wil_tid_ampdu_rx {
|
|||
unsigned long long drop_dup;
|
||||
unsigned long long drop_old;
|
||||
bool first_time; /* is it 1-st time this buffer used? */
|
||||
u16 mcast_last_seq; /* multicast dup detection */
|
||||
unsigned long long drop_dup_mcast;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -672,27 +714,6 @@ enum wil_sta_status {
|
|||
wil_sta_connected = 2,
|
||||
};
|
||||
|
||||
#define WIL_STA_TID_NUM (16)
|
||||
#define WIL_MCS_MAX (12) /* Maximum MCS supported */
|
||||
|
||||
struct wil_net_stats {
|
||||
unsigned long rx_packets;
|
||||
unsigned long tx_packets;
|
||||
unsigned long rx_bytes;
|
||||
unsigned long tx_bytes;
|
||||
unsigned long tx_errors;
|
||||
unsigned long rx_dropped;
|
||||
unsigned long rx_non_data_frame;
|
||||
unsigned long rx_short_frame;
|
||||
unsigned long rx_large_frame;
|
||||
unsigned long rx_replay;
|
||||
unsigned long rx_mic_error; /* eDMA specific */
|
||||
unsigned long rx_key_error; /* eDMA specific */
|
||||
unsigned long rx_amsdu_error; /* eDMA specific */
|
||||
u16 last_mcs_rx;
|
||||
u64 rx_per_mcs[WIL_MCS_MAX + 1];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct wil_sta_info - data for peer
|
||||
*
|
||||
|
|
@ -706,6 +727,14 @@ struct wil_sta_info {
|
|||
u8 mid;
|
||||
enum wil_sta_status status;
|
||||
struct wil_net_stats stats;
|
||||
/**
|
||||
* 20 latency bins. 1st bin counts packets with latency
|
||||
* of 0..tx_latency_res, last bin counts packets with latency
|
||||
* of 19*tx_latency_res and above.
|
||||
* tx_latency_res is configured from "tx_latency" debug-fs.
|
||||
*/
|
||||
u64 *tx_latency_bins;
|
||||
struct wmi_link_stats_basic fw_stats_basic;
|
||||
/* Rx BACK */
|
||||
struct wil_tid_ampdu_rx *tid_rx[WIL_STA_TID_NUM];
|
||||
spinlock_t tid_rx_lock; /* guarding tid_rx array */
|
||||
|
|
@ -820,6 +849,8 @@ struct wil6210_vif {
|
|||
struct mutex probe_client_mutex; /* protect @probe_client_pending */
|
||||
struct work_struct probe_client_worker;
|
||||
int net_queue_stopped; /* netif_tx_stop_all_queues invoked */
|
||||
bool fw_stats_ready; /* per-cid statistics are ready inside sta_info */
|
||||
u64 fw_stats_tsf; /* measurement timestamp */
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -847,11 +878,18 @@ struct wil_rx_buff_mgmt {
|
|||
unsigned long free_list_empty_cnt; /* statistics */
|
||||
};
|
||||
|
||||
struct wil_fw_stats_global {
|
||||
bool ready;
|
||||
u64 tsf; /* measurement timestamp */
|
||||
struct wmi_link_stats_global stats;
|
||||
};
|
||||
|
||||
struct wil6210_priv {
|
||||
struct pci_dev *pdev;
|
||||
u32 bar_size;
|
||||
struct wiphy *wiphy;
|
||||
struct net_device *main_ndev;
|
||||
int n_msi;
|
||||
void __iomem *csr;
|
||||
DECLARE_BITMAP(status, wil_status_last);
|
||||
u8 fw_version[ETHTOOL_FWVERS_LEN];
|
||||
|
|
@ -937,6 +975,8 @@ struct wil6210_priv {
|
|||
u8 wakeup_trigger;
|
||||
struct wil_suspend_stats suspend_stats;
|
||||
struct wil_debugfs_data dbg_data;
|
||||
bool tx_latency; /* collect TX latency measurements */
|
||||
size_t tx_latency_res; /* bin resolution in usec */
|
||||
|
||||
void *platform_handle;
|
||||
struct wil_platform_ops platform_ops;
|
||||
|
|
@ -977,6 +1017,11 @@ struct wil6210_priv {
|
|||
bool use_rx_hw_reordering;
|
||||
bool secured_boot;
|
||||
u8 boot_config;
|
||||
|
||||
struct wil_fw_stats_global fw_stats_global;
|
||||
|
||||
u32 max_agg_wsize;
|
||||
u32 max_ampdu_size;
|
||||
};
|
||||
|
||||
#define wil_to_wiphy(i) (i->wiphy)
|
||||
|
|
@ -1060,6 +1105,8 @@ static inline void wil_c(struct wil6210_priv *wil, u32 reg, u32 val)
|
|||
wil_w(wil, reg, wil_r(wil, reg) & ~val);
|
||||
}
|
||||
|
||||
void wil_get_board_file(struct wil6210_priv *wil, char *buf, size_t len);
|
||||
|
||||
#if defined(CONFIG_DYNAMIC_DEBUG)
|
||||
#define wil_hex_dump_txrx(prefix_str, prefix_type, rowsize, \
|
||||
groupsize, buf, len, ascii) \
|
||||
|
|
@ -1176,13 +1223,14 @@ int wmi_new_sta(struct wil6210_vif *vif, const u8 *mac, u8 aid);
|
|||
int wmi_port_allocate(struct wil6210_priv *wil, u8 mid,
|
||||
const u8 *mac, enum nl80211_iftype iftype);
|
||||
int wmi_port_delete(struct wil6210_priv *wil, u8 mid);
|
||||
int wmi_link_stats_cfg(struct wil6210_vif *vif, u32 type, u8 cid, u32 interval);
|
||||
int wil_addba_rx_request(struct wil6210_priv *wil, u8 mid,
|
||||
u8 cidxtid, u8 dialog_token, __le16 ba_param_set,
|
||||
__le16 ba_timeout, __le16 ba_seq_ctrl);
|
||||
int wil_addba_tx_request(struct wil6210_priv *wil, u8 ringid, u16 wsize);
|
||||
|
||||
void wil6210_clear_irq(struct wil6210_priv *wil);
|
||||
int wil6210_init_irq(struct wil6210_priv *wil, int irq, bool use_msi);
|
||||
int wil6210_init_irq(struct wil6210_priv *wil, int irq);
|
||||
void wil6210_fini_irq(struct wil6210_priv *wil, int irq);
|
||||
void wil_mask_irq(struct wil6210_priv *wil);
|
||||
void wil_unmask_irq(struct wil6210_priv *wil);
|
||||
|
|
@ -1304,6 +1352,8 @@ int wmi_start_sched_scan(struct wil6210_priv *wil,
|
|||
struct cfg80211_sched_scan_request *request);
|
||||
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 reverse_memcmp(const void *cs, const void *ct, size_t count);
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ enum wil_platform_event {
|
|||
|
||||
enum wil_platform_features {
|
||||
WIL_PLATFORM_FEATURE_FW_EXT_CLK_CONTROL = 0,
|
||||
WIL_PLATFORM_FEATURE_TRIPLE_MSI = 1,
|
||||
WIL_PLATFORM_FEATURE_MAX,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -464,6 +464,10 @@ static const char *cmdid2name(u16 cmdid)
|
|||
return "WMI_BCAST_DESC_RING_ADD_CMD";
|
||||
case WMI_CFG_DEF_RX_OFFLOAD_CMDID:
|
||||
return "WMI_CFG_DEF_RX_OFFLOAD_CMD";
|
||||
case WMI_LINK_STATS_CMDID:
|
||||
return "WMI_LINK_STATS_CMD";
|
||||
case WMI_SW_TX_REQ_EXT_CMDID:
|
||||
return "WMI_SW_TX_REQ_EXT_CMDID";
|
||||
default:
|
||||
return "Untracked CMD";
|
||||
}
|
||||
|
|
@ -598,6 +602,10 @@ static const char *eventid2name(u16 eventid)
|
|||
return "WMI_RX_DESC_RING_CFG_DONE_EVENT";
|
||||
case WMI_CFG_DEF_RX_OFFLOAD_DONE_EVENTID:
|
||||
return "WMI_CFG_DEF_RX_OFFLOAD_DONE_EVENT";
|
||||
case WMI_LINK_STATS_CONFIG_DONE_EVENTID:
|
||||
return "WMI_LINK_STATS_CONFIG_DONE_EVENT";
|
||||
case WMI_LINK_STATS_EVENTID:
|
||||
return "WMI_LINK_STATS_EVENT";
|
||||
default:
|
||||
return "Untracked EVENT";
|
||||
}
|
||||
|
|
@ -1329,6 +1337,130 @@ wmi_evt_sched_scan_result(struct wil6210_vif *vif, int id, void *d, int len)
|
|||
cfg80211_sched_scan_results(wiphy, 0);
|
||||
}
|
||||
|
||||
static void wil_link_stats_store_basic(struct wil6210_vif *vif,
|
||||
struct wmi_link_stats_basic *basic)
|
||||
{
|
||||
struct wil6210_priv *wil = vif_to_wil(vif);
|
||||
u8 cid = basic->cid;
|
||||
struct wil_sta_info *sta;
|
||||
|
||||
if (cid < 0 || cid >= WIL6210_MAX_CID) {
|
||||
wil_err(wil, "invalid cid %d\n", cid);
|
||||
return;
|
||||
}
|
||||
|
||||
sta = &wil->sta[cid];
|
||||
sta->fw_stats_basic = *basic;
|
||||
}
|
||||
|
||||
static void wil_link_stats_store_global(struct wil6210_vif *vif,
|
||||
struct wmi_link_stats_global *global)
|
||||
{
|
||||
struct wil6210_priv *wil = vif_to_wil(vif);
|
||||
|
||||
wil->fw_stats_global.stats = *global;
|
||||
}
|
||||
|
||||
static void wmi_link_stats_parse(struct wil6210_vif *vif, u64 tsf,
|
||||
bool has_next, void *payload,
|
||||
size_t payload_size)
|
||||
{
|
||||
struct wil6210_priv *wil = vif_to_wil(vif);
|
||||
size_t hdr_size = sizeof(struct wmi_link_stats_record);
|
||||
size_t stats_size, record_size, expected_size;
|
||||
struct wmi_link_stats_record *hdr;
|
||||
|
||||
if (payload_size < hdr_size) {
|
||||
wil_err(wil, "link stats wrong event size %zu\n", payload_size);
|
||||
return;
|
||||
}
|
||||
|
||||
while (payload_size >= hdr_size) {
|
||||
hdr = payload;
|
||||
stats_size = le16_to_cpu(hdr->record_size);
|
||||
record_size = hdr_size + stats_size;
|
||||
|
||||
if (payload_size < record_size) {
|
||||
wil_err(wil, "link stats payload ended unexpectedly, size %zu < %zu\n",
|
||||
payload_size, record_size);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (hdr->record_type_id) {
|
||||
case WMI_LINK_STATS_TYPE_BASIC:
|
||||
expected_size = sizeof(struct wmi_link_stats_basic);
|
||||
if (stats_size < expected_size) {
|
||||
wil_err(wil, "link stats invalid basic record size %zu < %zu\n",
|
||||
stats_size, expected_size);
|
||||
return;
|
||||
}
|
||||
if (vif->fw_stats_ready) {
|
||||
/* clean old statistics */
|
||||
vif->fw_stats_tsf = 0;
|
||||
vif->fw_stats_ready = 0;
|
||||
}
|
||||
|
||||
wil_link_stats_store_basic(vif, payload + hdr_size);
|
||||
|
||||
if (!has_next) {
|
||||
vif->fw_stats_tsf = tsf;
|
||||
vif->fw_stats_ready = 1;
|
||||
}
|
||||
|
||||
break;
|
||||
case WMI_LINK_STATS_TYPE_GLOBAL:
|
||||
expected_size = sizeof(struct wmi_link_stats_global);
|
||||
if (stats_size < sizeof(struct wmi_link_stats_global)) {
|
||||
wil_err(wil, "link stats invalid global record size %zu < %zu\n",
|
||||
stats_size, expected_size);
|
||||
return;
|
||||
}
|
||||
|
||||
if (wil->fw_stats_global.ready) {
|
||||
/* clean old statistics */
|
||||
wil->fw_stats_global.tsf = 0;
|
||||
wil->fw_stats_global.ready = 0;
|
||||
}
|
||||
|
||||
wil_link_stats_store_global(vif, payload + hdr_size);
|
||||
|
||||
if (!has_next) {
|
||||
wil->fw_stats_global.tsf = tsf;
|
||||
wil->fw_stats_global.ready = 1;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* skip to next record */
|
||||
payload += record_size;
|
||||
payload_size -= record_size;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
wmi_evt_link_stats(struct wil6210_vif *vif, int id, void *d, int len)
|
||||
{
|
||||
struct wil6210_priv *wil = vif_to_wil(vif);
|
||||
struct wmi_link_stats_event *evt = d;
|
||||
size_t payload_size;
|
||||
|
||||
if (len < offsetof(struct wmi_link_stats_event, payload)) {
|
||||
wil_err(wil, "stats event way too short %d\n", len);
|
||||
return;
|
||||
}
|
||||
payload_size = le16_to_cpu(evt->payload_size);
|
||||
if (len < sizeof(struct wmi_link_stats_event) + payload_size) {
|
||||
wil_err(wil, "stats event too short %d\n", len);
|
||||
return;
|
||||
}
|
||||
|
||||
wmi_link_stats_parse(vif, le64_to_cpu(evt->tsf), evt->has_next,
|
||||
evt->payload, payload_size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Some events are ignored for purpose; and need not be interpreted as
|
||||
* "unhandled events"
|
||||
|
|
@ -1359,6 +1491,7 @@ static const struct {
|
|||
{WMI_RING_EN_EVENTID, wmi_evt_ring_en},
|
||||
{WMI_DATA_PORT_OPEN_EVENTID, wmi_evt_ignore},
|
||||
{WMI_SCHED_SCAN_RESULT_EVENTID, wmi_evt_sched_scan_result},
|
||||
{WMI_LINK_STATS_EVENTID, wmi_evt_link_stats},
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -2983,6 +3116,60 @@ int wmi_mgmt_tx(struct wil6210_vif *vif, const u8 *buf, size_t len)
|
|||
return rc;
|
||||
}
|
||||
|
||||
int wmi_mgmt_tx_ext(struct wil6210_vif *vif, const u8 *buf, size_t len,
|
||||
u8 channel, u16 duration_ms)
|
||||
{
|
||||
size_t total;
|
||||
struct wil6210_priv *wil = vif_to_wil(vif);
|
||||
struct ieee80211_mgmt *mgmt_frame = (void *)buf;
|
||||
struct wmi_sw_tx_req_ext_cmd *cmd;
|
||||
struct {
|
||||
struct wmi_cmd_hdr wmi;
|
||||
struct wmi_sw_tx_complete_event evt;
|
||||
} __packed evt = {
|
||||
.evt = {.status = WMI_FW_STATUS_FAILURE},
|
||||
};
|
||||
int rc;
|
||||
|
||||
wil_dbg_wmi(wil, "mgmt_tx_ext mid %d channel %d duration %d\n",
|
||||
vif->mid, channel, duration_ms);
|
||||
wil_hex_dump_wmi("mgmt_tx_ext frame ", DUMP_PREFIX_OFFSET, 16, 1, buf,
|
||||
len, true);
|
||||
|
||||
if (len < sizeof(struct ieee80211_hdr_3addr)) {
|
||||
wil_err(wil, "short frame. len %zu\n", len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
total = sizeof(*cmd) + len;
|
||||
if (total < len) {
|
||||
wil_err(wil, "mgmt_tx_ext invalid len %zu\n", len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cmd = kzalloc(total, GFP_KERNEL);
|
||||
if (!cmd)
|
||||
return -ENOMEM;
|
||||
|
||||
memcpy(cmd->dst_mac, mgmt_frame->da, WMI_MAC_LEN);
|
||||
cmd->len = cpu_to_le16(len);
|
||||
memcpy(cmd->payload, buf, len);
|
||||
cmd->channel = channel - 1;
|
||||
cmd->duration_ms = cpu_to_le16(duration_ms);
|
||||
|
||||
rc = wmi_call(wil, WMI_SW_TX_REQ_EXT_CMDID, vif->mid, cmd, total,
|
||||
WMI_SW_TX_COMPLETE_EVENTID, &evt, sizeof(evt), 2000);
|
||||
if (!rc && evt.evt.status != WMI_FW_STATUS_SUCCESS) {
|
||||
wil_err(wil, "mgmt_tx_ext failed with status %d\n",
|
||||
evt.evt.status);
|
||||
rc = -EINVAL;
|
||||
}
|
||||
|
||||
kfree(cmd);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int wil_wmi_tx_sring_cfg(struct wil6210_priv *wil, int ring_id)
|
||||
{
|
||||
int rc;
|
||||
|
|
@ -3242,3 +3429,37 @@ int wil_wmi_bcast_desc_ring_add(struct wil6210_vif *vif, int ring_id)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wmi_link_stats_cfg(struct wil6210_vif *vif, u32 type, u8 cid, u32 interval)
|
||||
{
|
||||
struct wil6210_priv *wil = vif_to_wil(vif);
|
||||
struct wmi_link_stats_cmd cmd = {
|
||||
.record_type_mask = cpu_to_le32(type),
|
||||
.cid = cid,
|
||||
.action = WMI_LINK_STATS_SNAPSHOT,
|
||||
.interval_msec = cpu_to_le32(interval),
|
||||
};
|
||||
struct {
|
||||
struct wmi_cmd_hdr wmi;
|
||||
struct wmi_link_stats_config_done_event evt;
|
||||
} __packed reply = {
|
||||
.evt = {.status = WMI_FW_STATUS_FAILURE},
|
||||
};
|
||||
int rc;
|
||||
|
||||
rc = wmi_call(wil, WMI_LINK_STATS_CMDID, vif->mid, &cmd, sizeof(cmd),
|
||||
WMI_LINK_STATS_CONFIG_DONE_EVENTID, &reply,
|
||||
sizeof(reply), WIL_WMI_CALL_GENERAL_TO_MS);
|
||||
if (rc) {
|
||||
wil_err(wil, "WMI_LINK_STATS_CMDID failed, rc %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (reply.evt.status != WMI_FW_STATUS_SUCCESS) {
|
||||
wil_err(wil, "Link statistics config failed, status %d\n",
|
||||
reply.evt.status);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,6 +53,17 @@
|
|||
* must always be kept equal to (WMI_RF_RX2TX_LENGTH+1)
|
||||
*/
|
||||
#define WMI_RF_RX2TX_CONF_LENGTH (4)
|
||||
/* Qos configuration */
|
||||
#define WMI_QOS_NUM_OF_PRIORITY (4)
|
||||
#define WMI_QOS_MIN_DEFAULT_WEIGHT (10)
|
||||
#define WMI_QOS_VRING_SLOT_MIN_MS (2)
|
||||
#define WMI_QOS_VRING_SLOT_MAX_MS (10)
|
||||
/* (WMI_QOS_MIN_DEFAULT_WEIGHT * WMI_QOS_VRING_SLOT_MAX_MS /
|
||||
* WMI_QOS_VRING_SLOT_MIN_MS)
|
||||
*/
|
||||
#define WMI_QOS_MAX_WEIGHT 50
|
||||
#define WMI_QOS_SET_VIF_PRIORITY (0xFF)
|
||||
#define WMI_QOS_DEFAULT_PRIORITY (WMI_QOS_NUM_OF_PRIORITY)
|
||||
|
||||
/* Mailbox interface
|
||||
* used for commands and events
|
||||
|
|
@ -86,7 +97,12 @@ enum wmi_fw_capability {
|
|||
WMI_FW_CAPABILITY_PNO = 15,
|
||||
WMI_FW_CAPABILITY_REF_CLOCK_CONTROL = 18,
|
||||
WMI_FW_CAPABILITY_AP_SME_OFFLOAD_NONE = 19,
|
||||
WMI_FW_CAPABILITY_MULTI_VIFS = 20,
|
||||
WMI_FW_CAPABILITY_FT_ROAMING = 21,
|
||||
WMI_FW_CAPABILITY_BACK_WIN_SIZE_64 = 22,
|
||||
WMI_FW_CAPABILITY_AMSDU = 23,
|
||||
WMI_FW_CAPABILITY_RAW_MODE = 24,
|
||||
WMI_FW_CAPABILITY_TX_REQ_EXT = 25,
|
||||
WMI_FW_CAPABILITY_MAX,
|
||||
};
|
||||
|
||||
|
|
@ -110,6 +126,9 @@ enum wmi_command_id {
|
|||
WMI_SET_PROBED_SSID_CMDID = 0x0A,
|
||||
/* deprecated */
|
||||
WMI_SET_LISTEN_INT_CMDID = 0x0B,
|
||||
WMI_FT_AUTH_CMDID = 0x0C,
|
||||
WMI_FT_REASSOC_CMDID = 0x0D,
|
||||
WMI_UPDATE_FT_IES_CMDID = 0x0E,
|
||||
WMI_BCON_CTRL_CMDID = 0x0F,
|
||||
WMI_ADD_CIPHER_KEY_CMDID = 0x16,
|
||||
WMI_DELETE_CIPHER_KEY_CMDID = 0x17,
|
||||
|
|
@ -118,6 +137,12 @@ enum wmi_command_id {
|
|||
WMI_SET_WSC_STATUS_CMDID = 0x41,
|
||||
WMI_PXMT_RANGE_CFG_CMDID = 0x42,
|
||||
WMI_PXMT_SNR2_RANGE_CFG_CMDID = 0x43,
|
||||
WMI_RADAR_GENERAL_CONFIG_CMDID = 0x100,
|
||||
WMI_RADAR_CONFIG_SELECT_CMDID = 0x101,
|
||||
WMI_RADAR_PARAMS_CONFIG_CMDID = 0x102,
|
||||
WMI_RADAR_SET_MODE_CMDID = 0x103,
|
||||
WMI_RADAR_CONTROL_CMDID = 0x104,
|
||||
WMI_RADAR_PCI_CONTROL_CMDID = 0x105,
|
||||
WMI_MEM_READ_CMDID = 0x800,
|
||||
WMI_MEM_WR_CMDID = 0x801,
|
||||
WMI_ECHO_CMDID = 0x803,
|
||||
|
|
@ -158,6 +183,10 @@ enum wmi_command_id {
|
|||
WMI_SET_PCP_CHANNEL_CMDID = 0x829,
|
||||
WMI_GET_PCP_CHANNEL_CMDID = 0x82A,
|
||||
WMI_SW_TX_REQ_CMDID = 0x82B,
|
||||
/* Event is shared between WMI_SW_TX_REQ_CMDID and
|
||||
* WMI_SW_TX_REQ_EXT_CMDID
|
||||
*/
|
||||
WMI_SW_TX_REQ_EXT_CMDID = 0x82C,
|
||||
WMI_MLME_PUSH_CMDID = 0x835,
|
||||
WMI_BEAMFORMING_MGMT_CMDID = 0x836,
|
||||
WMI_BF_TXSS_MGMT_CMDID = 0x837,
|
||||
|
|
@ -207,7 +236,12 @@ enum wmi_command_id {
|
|||
WMI_GET_PCP_FACTOR_CMDID = 0x91B,
|
||||
/* Power Save Configuration Commands */
|
||||
WMI_PS_DEV_PROFILE_CFG_CMDID = 0x91C,
|
||||
WMI_RS_ENABLE_CMDID = 0x91E,
|
||||
WMI_RS_CFG_EX_CMDID = 0x91F,
|
||||
WMI_GET_DETAILED_RS_RES_EX_CMDID = 0x920,
|
||||
/* deprecated */
|
||||
WMI_RS_CFG_CMDID = 0x921,
|
||||
/* deprecated */
|
||||
WMI_GET_DETAILED_RS_RES_CMDID = 0x922,
|
||||
WMI_AOA_MEAS_CMDID = 0x923,
|
||||
WMI_BRP_SET_ANT_LIMIT_CMDID = 0x924,
|
||||
|
|
@ -236,7 +270,9 @@ enum wmi_command_id {
|
|||
WMI_PRIO_TX_SECTORS_ORDER_CMDID = 0x9A5,
|
||||
WMI_PRIO_TX_SECTORS_NUMBER_CMDID = 0x9A6,
|
||||
WMI_PRIO_TX_SECTORS_SET_DEFAULT_CFG_CMDID = 0x9A7,
|
||||
/* deprecated */
|
||||
WMI_BF_CONTROL_CMDID = 0x9AA,
|
||||
WMI_BF_CONTROL_EX_CMDID = 0x9AB,
|
||||
WMI_TX_STATUS_RING_ADD_CMDID = 0x9C0,
|
||||
WMI_RX_STATUS_RING_ADD_CMDID = 0x9C1,
|
||||
WMI_TX_DESC_RING_ADD_CMDID = 0x9C2,
|
||||
|
|
@ -252,6 +288,11 @@ enum wmi_command_id {
|
|||
WMI_GET_CCA_INDICATIONS_CMDID = 0xA07,
|
||||
WMI_SET_CCA_INDICATIONS_BI_AVG_NUM_CMDID = 0xA08,
|
||||
WMI_INTERNAL_FW_IOCTL_CMDID = 0xA0B,
|
||||
WMI_LINK_STATS_CMDID = 0xA0C,
|
||||
WMI_SET_GRANT_MCS_CMDID = 0xA0E,
|
||||
WMI_SET_AP_SLOT_SIZE_CMDID = 0xA0F,
|
||||
WMI_SET_VRING_PRIORITY_WEIGHT_CMDID = 0xA10,
|
||||
WMI_SET_VRING_PRIORITY_CMDID = 0xA11,
|
||||
WMI_SET_MAC_ADDRESS_CMDID = 0xF003,
|
||||
WMI_ABORT_SCAN_CMDID = 0xF007,
|
||||
WMI_SET_PROMISCUOUS_MODE_CMDID = 0xF041,
|
||||
|
|
@ -450,6 +491,30 @@ struct wmi_start_sched_scan_cmd {
|
|||
struct wmi_sched_scan_plan scan_plans[WMI_MAX_PLANS_NUM];
|
||||
} __packed;
|
||||
|
||||
/* WMI_FT_AUTH_CMDID */
|
||||
struct wmi_ft_auth_cmd {
|
||||
u8 bssid[WMI_MAC_LEN];
|
||||
/* enum wmi_channel */
|
||||
u8 channel;
|
||||
/* enum wmi_channel */
|
||||
u8 edmg_channel;
|
||||
u8 reserved[4];
|
||||
} __packed;
|
||||
|
||||
/* WMI_FT_REASSOC_CMDID */
|
||||
struct wmi_ft_reassoc_cmd {
|
||||
u8 bssid[WMI_MAC_LEN];
|
||||
u8 reserved[2];
|
||||
} __packed;
|
||||
|
||||
/* WMI_UPDATE_FT_IES_CMDID */
|
||||
struct wmi_update_ft_ies_cmd {
|
||||
/* Length of the FT IEs */
|
||||
__le16 ie_len;
|
||||
u8 reserved[2];
|
||||
u8 ie_info[0];
|
||||
} __packed;
|
||||
|
||||
/* WMI_SET_PROBED_SSID_CMDID */
|
||||
#define MAX_PROBED_SSID_INDEX (3)
|
||||
|
||||
|
|
@ -506,6 +571,109 @@ struct wmi_pxmt_snr2_range_cfg_cmd {
|
|||
s8 snr2range_arr[2];
|
||||
} __packed;
|
||||
|
||||
/* WMI_RADAR_GENERAL_CONFIG_CMDID */
|
||||
struct wmi_radar_general_config_cmd {
|
||||
/* Number of pulses (CIRs) in FW FIFO to initiate pulses transfer
|
||||
* from FW to Host
|
||||
*/
|
||||
__le32 fifo_watermark;
|
||||
/* In unit of us, in the range [100, 1000000] */
|
||||
__le32 t_burst;
|
||||
/* Valid in the range [1, 32768], 0xFFFF means infinite */
|
||||
__le32 n_bursts;
|
||||
/* In unit of 330Mhz clk, in the range [4, 2000]*330 */
|
||||
__le32 t_pulse;
|
||||
/* In the range of [1,4096] */
|
||||
__le16 n_pulses;
|
||||
/* Number of taps after cTap per CIR */
|
||||
__le16 n_samples;
|
||||
/* Offset from the main tap (0 = zero-distance). In the range of [0,
|
||||
* 255]
|
||||
*/
|
||||
u8 first_sample_offset;
|
||||
/* Number of Pulses to average, 1, 2, 4, 8 */
|
||||
u8 pulses_to_avg;
|
||||
/* Number of adjacent taps to average, 1, 2, 4, 8 */
|
||||
u8 samples_to_avg;
|
||||
/* The index to config general params */
|
||||
u8 general_index;
|
||||
u8 reserved[4];
|
||||
} __packed;
|
||||
|
||||
/* WMI_RADAR_CONFIG_SELECT_CMDID */
|
||||
struct wmi_radar_config_select_cmd {
|
||||
/* Select the general params index to use */
|
||||
u8 general_index;
|
||||
u8 reserved[3];
|
||||
/* 0 means don't update burst_active_vector */
|
||||
__le32 burst_active_vector;
|
||||
/* 0 means don't update pulse_active_vector */
|
||||
__le32 pulse_active_vector;
|
||||
} __packed;
|
||||
|
||||
/* WMI_RADAR_PARAMS_CONFIG_CMDID */
|
||||
struct wmi_radar_params_config_cmd {
|
||||
/* The burst index selected to config */
|
||||
u8 burst_index;
|
||||
/* 0-not active, 1-active */
|
||||
u8 burst_en;
|
||||
/* The pulse index selected to config */
|
||||
u8 pulse_index;
|
||||
/* 0-not active, 1-active */
|
||||
u8 pulse_en;
|
||||
/* TX RF to use on current pulse */
|
||||
u8 tx_rfc_idx;
|
||||
u8 tx_sector;
|
||||
/* Offset from calibrated value.(expected to be 0)(value is row in
|
||||
* Gain-LUT, not dB)
|
||||
*/
|
||||
s8 tx_rf_gain_comp;
|
||||
/* expected to be 0 */
|
||||
s8 tx_bb_gain_comp;
|
||||
/* RX RF to use on current pulse */
|
||||
u8 rx_rfc_idx;
|
||||
u8 rx_sector;
|
||||
/* Offset from calibrated value.(expected to be 0)(value is row in
|
||||
* Gain-LUT, not dB)
|
||||
*/
|
||||
s8 rx_rf_gain_comp;
|
||||
/* Value in dB.(expected to be 0) */
|
||||
s8 rx_bb_gain_comp;
|
||||
/* Offset from calibrated value.(expected to be 0) */
|
||||
s8 rx_timing_offset;
|
||||
u8 reserved[3];
|
||||
} __packed;
|
||||
|
||||
/* WMI_RADAR_SET_MODE_CMDID */
|
||||
struct wmi_radar_set_mode_cmd {
|
||||
/* 0-disable/1-enable */
|
||||
u8 enable;
|
||||
/* enum wmi_channel */
|
||||
u8 channel;
|
||||
/* In the range of [0,7], 0xff means use default */
|
||||
u8 tx_rfc_idx;
|
||||
/* In the range of [0,7], 0xff means use default */
|
||||
u8 rx_rfc_idx;
|
||||
} __packed;
|
||||
|
||||
/* WMI_RADAR_CONTROL_CMDID */
|
||||
struct wmi_radar_control_cmd {
|
||||
/* 0-stop/1-start */
|
||||
u8 start;
|
||||
u8 reserved[3];
|
||||
} __packed;
|
||||
|
||||
/* WMI_RADAR_PCI_CONTROL_CMDID */
|
||||
struct wmi_radar_pci_control_cmd {
|
||||
/* pcie host buffer start address */
|
||||
__le64 base_addr;
|
||||
/* pcie host control block address */
|
||||
__le64 control_block_addr;
|
||||
/* pcie host buffer size */
|
||||
__le32 buffer_size;
|
||||
__le32 reserved;
|
||||
} __packed;
|
||||
|
||||
/* WMI_RF_MGMT_CMDID */
|
||||
enum wmi_rf_mgmt_type {
|
||||
WMI_RF_MGMT_W_DISABLE = 0x00,
|
||||
|
|
@ -643,12 +811,18 @@ struct wmi_pcp_start_cmd {
|
|||
u8 pcp_max_assoc_sta;
|
||||
u8 hidden_ssid;
|
||||
u8 is_go;
|
||||
u8 reserved0[5];
|
||||
/* enum wmi_channel WMI_CHANNEL_9..WMI_CHANNEL_12 */
|
||||
u8 edmg_channel;
|
||||
u8 raw_mode;
|
||||
u8 reserved[3];
|
||||
/* A-BFT length override if non-0 */
|
||||
u8 abft_len;
|
||||
/* enum wmi_ap_sme_offload_mode_e */
|
||||
u8 ap_sme_offload_mode;
|
||||
u8 network_type;
|
||||
/* enum wmi_channel WMI_CHANNEL_1..WMI_CHANNEL_6; for EDMG this is
|
||||
* the primary channel number
|
||||
*/
|
||||
u8 channel;
|
||||
u8 disable_sec_offload;
|
||||
u8 disable_sec;
|
||||
|
|
@ -661,6 +835,17 @@ struct wmi_sw_tx_req_cmd {
|
|||
u8 payload[0];
|
||||
} __packed;
|
||||
|
||||
/* WMI_SW_TX_REQ_EXT_CMDID */
|
||||
struct wmi_sw_tx_req_ext_cmd {
|
||||
u8 dst_mac[WMI_MAC_LEN];
|
||||
__le16 len;
|
||||
__le16 duration_ms;
|
||||
/* Channel to use, 0xFF for currently active channel */
|
||||
u8 channel;
|
||||
u8 reserved[5];
|
||||
u8 payload[0];
|
||||
} __packed;
|
||||
|
||||
/* WMI_VRING_SWITCH_TIMING_CONFIG_CMDID */
|
||||
struct wmi_vring_switch_timing_config_cmd {
|
||||
/* Set vring timing configuration:
|
||||
|
|
@ -687,6 +872,7 @@ struct wmi_vring_cfg_schd {
|
|||
enum wmi_vring_cfg_encap_trans_type {
|
||||
WMI_VRING_ENC_TYPE_802_3 = 0x00,
|
||||
WMI_VRING_ENC_TYPE_NATIVE_WIFI = 0x01,
|
||||
WMI_VRING_ENC_TYPE_NONE = 0x02,
|
||||
};
|
||||
|
||||
enum wmi_vring_cfg_ds_cfg {
|
||||
|
|
@ -744,7 +930,11 @@ struct wmi_vring_cfg {
|
|||
u8 cid;
|
||||
/* Used when cidxtid = CIDXTID_EXTENDED_CID_TID */
|
||||
u8 tid;
|
||||
u8 reserved[2];
|
||||
/* Update the vring's priority for Qos purpose. Set to
|
||||
* WMI_QOS_DEFAULT_PRIORITY to use MID's QoS priority
|
||||
*/
|
||||
u8 qos_priority;
|
||||
u8 reserved;
|
||||
} __packed;
|
||||
|
||||
enum wmi_vring_cfg_cmd_action {
|
||||
|
|
@ -775,20 +965,6 @@ struct wmi_bcast_vring_cfg_cmd {
|
|||
struct wmi_bcast_vring_cfg vring_cfg;
|
||||
} __packed;
|
||||
|
||||
/* WMI_LO_POWER_CALIB_FROM_OTP_CMDID */
|
||||
struct wmi_lo_power_calib_from_otp_cmd {
|
||||
/* index to read from OTP. zero based */
|
||||
u8 index;
|
||||
u8 reserved[3];
|
||||
} __packed;
|
||||
|
||||
/* WMI_LO_POWER_CALIB_FROM_OTP_EVENTID */
|
||||
struct wmi_lo_power_calib_from_otp_event {
|
||||
/* wmi_fw_status */
|
||||
u8 status;
|
||||
u8 reserved[3];
|
||||
} __packed;
|
||||
|
||||
struct wmi_edma_ring_cfg {
|
||||
__le64 ring_mem_base;
|
||||
/* size in number of items */
|
||||
|
|
@ -861,6 +1037,20 @@ struct wmi_bcast_desc_ring_add_cmd {
|
|||
u8 reserved[4];
|
||||
} __packed;
|
||||
|
||||
/* WMI_LO_POWER_CALIB_FROM_OTP_CMDID */
|
||||
struct wmi_lo_power_calib_from_otp_cmd {
|
||||
/* index to read from OTP. zero based */
|
||||
u8 index;
|
||||
u8 reserved[3];
|
||||
} __packed;
|
||||
|
||||
/* WMI_LO_POWER_CALIB_FROM_OTP_EVENTID */
|
||||
struct wmi_lo_power_calib_from_otp_event {
|
||||
/* wmi_fw_status */
|
||||
u8 status;
|
||||
u8 reserved[3];
|
||||
} __packed;
|
||||
|
||||
/* WMI_RING_BA_EN_CMDID */
|
||||
struct wmi_ring_ba_en_cmd {
|
||||
u8 ring_id;
|
||||
|
|
@ -1094,8 +1284,8 @@ struct wmi_echo_cmd {
|
|||
} __packed;
|
||||
|
||||
/* WMI_DEEP_ECHO_CMDID
|
||||
* Check FW and ucode are alive
|
||||
* Returned event: WMI_ECHO_RSP_EVENTID
|
||||
* Check FW and uCode is alive
|
||||
* Returned event: WMI_DEEP_ECHO_RSP_EVENTID
|
||||
*/
|
||||
struct wmi_deep_echo_cmd {
|
||||
__le32 value;
|
||||
|
|
@ -1419,6 +1609,10 @@ struct wmi_fixed_scheduling_config_complete_event {
|
|||
u8 reserved[3];
|
||||
} __packed;
|
||||
|
||||
/* This value exists for backwards compatibility only.
|
||||
* Do not use it in new commands.
|
||||
* Use dynamic arrays where possible.
|
||||
*/
|
||||
#define WMI_NUM_MCS (13)
|
||||
|
||||
/* WMI_FIXED_SCHEDULING_CONFIG_CMDID */
|
||||
|
|
@ -1466,6 +1660,52 @@ struct wmi_set_multi_directed_omnis_config_event {
|
|||
u8 reserved[3];
|
||||
} __packed;
|
||||
|
||||
/* WMI_RADAR_GENERAL_CONFIG_EVENTID */
|
||||
struct wmi_radar_general_config_event {
|
||||
/* wmi_fw_status */
|
||||
u8 status;
|
||||
u8 reserved[3];
|
||||
} __packed;
|
||||
|
||||
/* WMI_RADAR_CONFIG_SELECT_EVENTID */
|
||||
struct wmi_radar_config_select_event {
|
||||
/* wmi_fw_status */
|
||||
u8 status;
|
||||
u8 reserved[3];
|
||||
/* In unit of bytes */
|
||||
__le32 fifo_size;
|
||||
/* In unit of bytes */
|
||||
__le32 pulse_size;
|
||||
} __packed;
|
||||
|
||||
/* WMI_RADAR_PARAMS_CONFIG_EVENTID */
|
||||
struct wmi_radar_params_config_event {
|
||||
/* wmi_fw_status */
|
||||
u8 status;
|
||||
u8 reserved[3];
|
||||
} __packed;
|
||||
|
||||
/* WMI_RADAR_SET_MODE_EVENTID */
|
||||
struct wmi_radar_set_mode_event {
|
||||
/* wmi_fw_status */
|
||||
u8 status;
|
||||
u8 reserved[3];
|
||||
} __packed;
|
||||
|
||||
/* WMI_RADAR_CONTROL_EVENTID */
|
||||
struct wmi_radar_control_event {
|
||||
/* wmi_fw_status */
|
||||
u8 status;
|
||||
u8 reserved[3];
|
||||
} __packed;
|
||||
|
||||
/* WMI_RADAR_PCI_CONTROL_EVENTID */
|
||||
struct wmi_radar_pci_control_event {
|
||||
/* wmi_fw_status */
|
||||
u8 status;
|
||||
u8 reserved[3];
|
||||
} __packed;
|
||||
|
||||
/* WMI_SET_LONG_RANGE_CONFIG_CMDID */
|
||||
struct wmi_set_long_range_config_cmd {
|
||||
__le32 reserved;
|
||||
|
|
@ -1478,12 +1718,12 @@ struct wmi_set_long_range_config_complete_event {
|
|||
u8 reserved[3];
|
||||
} __packed;
|
||||
|
||||
/* payload max size is 236 bytes: max event buffer size (256) - WMI headers
|
||||
/* payload max size is 1024 bytes: max event buffer size (1044) - WMI headers
|
||||
* (16) - prev struct field size (4)
|
||||
*/
|
||||
#define WMI_MAX_IOCTL_PAYLOAD_SIZE (236)
|
||||
#define WMI_MAX_IOCTL_REPLY_PAYLOAD_SIZE (236)
|
||||
#define WMI_MAX_INTERNAL_EVENT_PAYLOAD_SIZE (236)
|
||||
#define WMI_MAX_IOCTL_PAYLOAD_SIZE (1024)
|
||||
#define WMI_MAX_IOCTL_REPLY_PAYLOAD_SIZE (1024)
|
||||
#define WMI_MAX_INTERNAL_EVENT_PAYLOAD_SIZE (1024)
|
||||
|
||||
enum wmi_internal_fw_ioctl_code {
|
||||
WMI_INTERNAL_FW_CODE_NONE = 0x0,
|
||||
|
|
@ -1523,7 +1763,37 @@ struct wmi_internal_fw_event_event {
|
|||
__le32 payload[0];
|
||||
} __packed;
|
||||
|
||||
/* WMI_BF_CONTROL_CMDID */
|
||||
/* WMI_SET_VRING_PRIORITY_WEIGHT_CMDID */
|
||||
struct wmi_set_vring_priority_weight_cmd {
|
||||
/* Array of weights. Valid values are
|
||||
* WMI_QOS_MIN_DEFAULT_WEIGHT...WMI_QOS_MAX_WEIGHT. Weight #0 is
|
||||
* hard-coded WMI_QOS_MIN_WEIGHT. This array provide the weights
|
||||
* #1..#3
|
||||
*/
|
||||
u8 weight[3];
|
||||
u8 reserved;
|
||||
} __packed;
|
||||
|
||||
/* WMI_SET_VRING_PRIORITY_CMDID */
|
||||
struct wmi_vring_priority {
|
||||
u8 vring_idx;
|
||||
/* Weight index. Valid value is 0-3 */
|
||||
u8 priority;
|
||||
u8 reserved[2];
|
||||
} __packed;
|
||||
|
||||
/* WMI_SET_VRING_PRIORITY_CMDID */
|
||||
struct wmi_set_vring_priority_cmd {
|
||||
/* number of entries in vring_priority. Set to
|
||||
* WMI_QOS_SET_VIF_PRIORITY to update the VIF's priority, and there
|
||||
* will be only one entry in vring_priority
|
||||
*/
|
||||
u8 num_of_vrings;
|
||||
u8 reserved[3];
|
||||
struct wmi_vring_priority vring_priority[0];
|
||||
} __packed;
|
||||
|
||||
/* WMI_BF_CONTROL_CMDID - deprecated */
|
||||
struct wmi_bf_control_cmd {
|
||||
/* wmi_bf_triggers */
|
||||
__le32 triggers;
|
||||
|
|
@ -1565,6 +1835,95 @@ struct wmi_bf_control_cmd {
|
|||
u8 reserved2[2];
|
||||
} __packed;
|
||||
|
||||
/* BF configuration for each MCS */
|
||||
struct wmi_bf_control_ex_mcs {
|
||||
/* Long term throughput threshold [Mbps] */
|
||||
u8 long_term_mbps_th_tbl;
|
||||
u8 reserved;
|
||||
/* Long term timeout threshold table [msec] */
|
||||
__le16 long_term_trig_timeout_per_mcs;
|
||||
} __packed;
|
||||
|
||||
/* WMI_BF_CONTROL_EX_CMDID */
|
||||
struct wmi_bf_control_ex_cmd {
|
||||
/* wmi_bf_triggers */
|
||||
__le32 triggers;
|
||||
/* enum wmi_edmg_tx_mode */
|
||||
u8 tx_mode;
|
||||
/* DISABLED = 0, ENABLED = 1 , DRY_RUN = 2 */
|
||||
u8 txss_mode;
|
||||
/* DISABLED = 0, ENABLED = 1, DRY_RUN = 2 */
|
||||
u8 brp_mode;
|
||||
/* Max cts threshold (correspond to
|
||||
* WMI_BF_TRIGGER_MAX_CTS_FAILURE_IN_TXOP)
|
||||
*/
|
||||
u8 bf_trigger_max_cts_failure_thr;
|
||||
/* Max cts threshold in dense (correspond to
|
||||
* WMI_BF_TRIGGER_MAX_CTS_FAILURE_IN_TXOP)
|
||||
*/
|
||||
u8 bf_trigger_max_cts_failure_dense_thr;
|
||||
/* Max b-ack threshold (correspond to
|
||||
* WMI_BF_TRIGGER_MAX_BACK_FAILURE)
|
||||
*/
|
||||
u8 bf_trigger_max_back_failure_thr;
|
||||
/* Max b-ack threshold in dense (correspond to
|
||||
* WMI_BF_TRIGGER_MAX_BACK_FAILURE)
|
||||
*/
|
||||
u8 bf_trigger_max_back_failure_dense_thr;
|
||||
u8 reserved0;
|
||||
/* Wrong sectors threshold */
|
||||
__le32 wrong_sector_bis_thr;
|
||||
/* BOOL to enable/disable long term trigger */
|
||||
u8 long_term_enable;
|
||||
/* 1 = Update long term thresholds from the long_term_mbps_th_tbl and
|
||||
* long_term_trig_timeout_per_mcs arrays, 0 = Ignore
|
||||
*/
|
||||
u8 long_term_update_thr;
|
||||
u8 each_mcs_cfg_size;
|
||||
u8 reserved1;
|
||||
/* Configuration for each MCS */
|
||||
struct wmi_bf_control_ex_mcs each_mcs_cfg[0];
|
||||
} __packed;
|
||||
|
||||
/* WMI_LINK_STATS_CMD */
|
||||
enum wmi_link_stats_action {
|
||||
WMI_LINK_STATS_SNAPSHOT = 0x00,
|
||||
WMI_LINK_STATS_PERIODIC = 0x01,
|
||||
WMI_LINK_STATS_STOP_PERIODIC = 0x02,
|
||||
};
|
||||
|
||||
/* WMI_LINK_STATS_EVENT record identifiers */
|
||||
enum wmi_link_stats_record_type {
|
||||
WMI_LINK_STATS_TYPE_BASIC = 0x01,
|
||||
WMI_LINK_STATS_TYPE_GLOBAL = 0x02,
|
||||
};
|
||||
|
||||
/* WMI_LINK_STATS_CMDID */
|
||||
struct wmi_link_stats_cmd {
|
||||
/* bitmask of required record types
|
||||
* (wmi_link_stats_record_type_e)
|
||||
*/
|
||||
__le32 record_type_mask;
|
||||
/* 0xff for all cids */
|
||||
u8 cid;
|
||||
/* wmi_link_stats_action_e */
|
||||
u8 action;
|
||||
u8 reserved[6];
|
||||
/* range = 100 - 10000 */
|
||||
__le32 interval_msec;
|
||||
} __packed;
|
||||
|
||||
/* WMI_SET_GRANT_MCS_CMDID */
|
||||
struct wmi_set_grant_mcs_cmd {
|
||||
u8 mcs;
|
||||
u8 reserved[3];
|
||||
} __packed;
|
||||
|
||||
/* WMI_SET_AP_SLOT_SIZE_CMDID */
|
||||
struct wmi_set_ap_slot_size_cmd {
|
||||
__le32 slot_size;
|
||||
} __packed;
|
||||
|
||||
/* WMI Events
|
||||
* List of Events (target to host)
|
||||
*/
|
||||
|
|
@ -1577,10 +1936,19 @@ enum wmi_event_id {
|
|||
WMI_SCHED_SCAN_RESULT_EVENTID = 0x1007,
|
||||
WMI_SCAN_COMPLETE_EVENTID = 0x100A,
|
||||
WMI_REPORT_STATISTICS_EVENTID = 0x100B,
|
||||
WMI_FT_AUTH_STATUS_EVENTID = 0x100C,
|
||||
WMI_FT_REASSOC_STATUS_EVENTID = 0x100D,
|
||||
WMI_RADAR_GENERAL_CONFIG_EVENTID = 0x1100,
|
||||
WMI_RADAR_CONFIG_SELECT_EVENTID = 0x1101,
|
||||
WMI_RADAR_PARAMS_CONFIG_EVENTID = 0x1102,
|
||||
WMI_RADAR_SET_MODE_EVENTID = 0x1103,
|
||||
WMI_RADAR_CONTROL_EVENTID = 0x1104,
|
||||
WMI_RADAR_PCI_CONTROL_EVENTID = 0x1105,
|
||||
WMI_RD_MEM_RSP_EVENTID = 0x1800,
|
||||
WMI_FW_READY_EVENTID = 0x1801,
|
||||
WMI_EXIT_FAST_MEM_ACC_MODE_EVENTID = 0x200,
|
||||
WMI_ECHO_RSP_EVENTID = 0x1803,
|
||||
WMI_DEEP_ECHO_RSP_EVENTID = 0x1804,
|
||||
/* deprecated */
|
||||
WMI_FS_TUNE_DONE_EVENTID = 0x180A,
|
||||
/* deprecated */
|
||||
|
|
@ -1606,6 +1974,9 @@ enum wmi_event_id {
|
|||
WMI_DELBA_EVENTID = 0x1826,
|
||||
WMI_GET_SSID_EVENTID = 0x1828,
|
||||
WMI_GET_PCP_CHANNEL_EVENTID = 0x182A,
|
||||
/* Event is shared between WMI_SW_TX_REQ_CMDID and
|
||||
* WMI_SW_TX_REQ_EXT_CMDID
|
||||
*/
|
||||
WMI_SW_TX_COMPLETE_EVENTID = 0x182B,
|
||||
WMI_BEAMFORMING_MGMT_DONE_EVENTID = 0x1836,
|
||||
WMI_BF_TXSS_MGMT_DONE_EVENTID = 0x1837,
|
||||
|
|
@ -1653,7 +2024,12 @@ enum wmi_event_id {
|
|||
WMI_PCP_FACTOR_EVENTID = 0x191A,
|
||||
/* Power Save Configuration Events */
|
||||
WMI_PS_DEV_PROFILE_CFG_EVENTID = 0x191C,
|
||||
WMI_RS_ENABLE_EVENTID = 0x191E,
|
||||
WMI_RS_CFG_EX_EVENTID = 0x191F,
|
||||
WMI_GET_DETAILED_RS_RES_EX_EVENTID = 0x1920,
|
||||
/* deprecated */
|
||||
WMI_RS_CFG_DONE_EVENTID = 0x1921,
|
||||
/* deprecated */
|
||||
WMI_GET_DETAILED_RS_RES_EVENTID = 0x1922,
|
||||
WMI_AOA_MEAS_EVENTID = 0x1923,
|
||||
WMI_BRP_SET_ANT_LIMIT_EVENTID = 0x1924,
|
||||
|
|
@ -1681,7 +2057,9 @@ enum wmi_event_id {
|
|||
WMI_PRIO_TX_SECTORS_ORDER_EVENTID = 0x19A5,
|
||||
WMI_PRIO_TX_SECTORS_NUMBER_EVENTID = 0x19A6,
|
||||
WMI_PRIO_TX_SECTORS_SET_DEFAULT_CFG_EVENTID = 0x19A7,
|
||||
/* deprecated */
|
||||
WMI_BF_CONTROL_EVENTID = 0x19AA,
|
||||
WMI_BF_CONTROL_EX_EVENTID = 0x19AB,
|
||||
WMI_TX_STATUS_RING_CFG_DONE_EVENTID = 0x19C0,
|
||||
WMI_RX_STATUS_RING_CFG_DONE_EVENTID = 0x19C1,
|
||||
WMI_TX_DESC_RING_CFG_DONE_EVENTID = 0x19C2,
|
||||
|
|
@ -1697,6 +2075,12 @@ enum wmi_event_id {
|
|||
WMI_SET_CCA_INDICATIONS_BI_AVG_NUM_EVENTID = 0x1A08,
|
||||
WMI_INTERNAL_FW_EVENT_EVENTID = 0x1A0A,
|
||||
WMI_INTERNAL_FW_IOCTL_EVENTID = 0x1A0B,
|
||||
WMI_LINK_STATS_CONFIG_DONE_EVENTID = 0x1A0C,
|
||||
WMI_LINK_STATS_EVENTID = 0x1A0D,
|
||||
WMI_SET_GRANT_MCS_EVENTID = 0x1A0E,
|
||||
WMI_SET_AP_SLOT_SIZE_EVENTID = 0x1A0F,
|
||||
WMI_SET_VRING_PRIORITY_WEIGHT_EVENTID = 0x1A10,
|
||||
WMI_SET_VRING_PRIORITY_EVENTID = 0x1A11,
|
||||
WMI_SET_CHANNEL_EVENTID = 0x9000,
|
||||
WMI_ASSOC_REQ_EVENTID = 0x9001,
|
||||
WMI_EAPOL_RX_EVENTID = 0x9002,
|
||||
|
|
@ -1961,6 +2345,33 @@ struct wmi_scan_complete_event {
|
|||
__le32 status;
|
||||
} __packed;
|
||||
|
||||
/* WMI_FT_AUTH_STATUS_EVENTID */
|
||||
struct wmi_ft_auth_status_event {
|
||||
/* enum wmi_fw_status */
|
||||
u8 status;
|
||||
u8 reserved[3];
|
||||
u8 mac_addr[WMI_MAC_LEN];
|
||||
__le16 ie_len;
|
||||
u8 ie_info[0];
|
||||
} __packed;
|
||||
|
||||
/* WMI_FT_REASSOC_STATUS_EVENTID */
|
||||
struct wmi_ft_reassoc_status_event {
|
||||
/* enum wmi_fw_status */
|
||||
u8 status;
|
||||
/* association id received from new AP */
|
||||
u8 aid;
|
||||
/* enum wmi_channel */
|
||||
u8 channel;
|
||||
/* enum wmi_channel */
|
||||
u8 edmg_channel;
|
||||
u8 mac_addr[WMI_MAC_LEN];
|
||||
__le16 beacon_ie_len;
|
||||
__le16 reassoc_req_ie_len;
|
||||
__le16 reassoc_resp_ie_len;
|
||||
u8 ie_info[0];
|
||||
} __packed;
|
||||
|
||||
/* wmi_rx_mgmt_info */
|
||||
struct wmi_rx_mgmt_info {
|
||||
u8 mcs;
|
||||
|
|
@ -2317,6 +2728,11 @@ struct wmi_echo_rsp_event {
|
|||
__le32 echoed_value;
|
||||
} __packed;
|
||||
|
||||
/* WMI_DEEP_ECHO_RSP_EVENTID */
|
||||
struct wmi_deep_echo_rsp_event {
|
||||
__le32 echoed_value;
|
||||
} __packed;
|
||||
|
||||
/* WMI_RF_PWR_ON_DELAY_RSP_EVENTID */
|
||||
struct wmi_rf_pwr_on_delay_rsp_event {
|
||||
/* wmi_fw_status */
|
||||
|
|
@ -2455,6 +2871,81 @@ struct wmi_rs_cfg {
|
|||
__le32 mcs_en_vec;
|
||||
} __packed;
|
||||
|
||||
enum wmi_edmg_tx_mode {
|
||||
WMI_TX_MODE_DMG = 0x0,
|
||||
WMI_TX_MODE_EDMG_CB1 = 0x1,
|
||||
WMI_TX_MODE_EDMG_CB2 = 0x2,
|
||||
WMI_TX_MODE_EDMG_CB1_LONG_LDPC = 0x3,
|
||||
WMI_TX_MODE_EDMG_CB2_LONG_LDPC = 0x4,
|
||||
WMI_TX_MODE_MAX,
|
||||
};
|
||||
|
||||
/* Rate search parameters common configuration */
|
||||
struct wmi_rs_cfg_ex_common {
|
||||
/* enum wmi_edmg_tx_mode */
|
||||
u8 mode;
|
||||
/* stop threshold [0-100] */
|
||||
u8 stop_th;
|
||||
/* MCS1 stop threshold [0-100] */
|
||||
u8 mcs1_fail_th;
|
||||
u8 max_back_failure_th;
|
||||
/* Debug feature for disabling internal RS trigger (which is
|
||||
* currently triggered by BF Done)
|
||||
*/
|
||||
u8 dbg_disable_internal_trigger;
|
||||
u8 reserved[3];
|
||||
__le32 back_failure_mask;
|
||||
} __packed;
|
||||
|
||||
/* Rate search parameters configuration per MCS */
|
||||
struct wmi_rs_cfg_ex_mcs {
|
||||
/* The maximal allowed PER for each MCS
|
||||
* MCS will be considered as failed if PER during RS is higher
|
||||
*/
|
||||
u8 per_threshold;
|
||||
/* Number of MPDUs for each MCS
|
||||
* this is the minimal statistic required to make an educated
|
||||
* decision
|
||||
*/
|
||||
u8 min_frame_cnt;
|
||||
u8 reserved[2];
|
||||
} __packed;
|
||||
|
||||
/* WMI_RS_CFG_EX_CMDID */
|
||||
struct wmi_rs_cfg_ex_cmd {
|
||||
/* Configuration for all MCSs */
|
||||
struct wmi_rs_cfg_ex_common common_cfg;
|
||||
u8 each_mcs_cfg_size;
|
||||
u8 reserved[3];
|
||||
/* Configuration for each MCS */
|
||||
struct wmi_rs_cfg_ex_mcs each_mcs_cfg[0];
|
||||
} __packed;
|
||||
|
||||
/* WMI_RS_CFG_EX_EVENTID */
|
||||
struct wmi_rs_cfg_ex_event {
|
||||
/* enum wmi_edmg_tx_mode */
|
||||
u8 mode;
|
||||
/* enum wmi_fw_status */
|
||||
u8 status;
|
||||
u8 reserved[2];
|
||||
} __packed;
|
||||
|
||||
/* WMI_RS_ENABLE_CMDID */
|
||||
struct wmi_rs_enable_cmd {
|
||||
u8 cid;
|
||||
/* enable or disable rate search */
|
||||
u8 rs_enable;
|
||||
u8 reserved[2];
|
||||
__le32 mcs_en_vec;
|
||||
} __packed;
|
||||
|
||||
/* WMI_RS_ENABLE_EVENTID */
|
||||
struct wmi_rs_enable_event {
|
||||
/* enum wmi_fw_status */
|
||||
u8 status;
|
||||
u8 reserved[3];
|
||||
} __packed;
|
||||
|
||||
/* Slot types */
|
||||
enum wmi_sched_scheme_slot_type {
|
||||
WMI_SCHED_SLOT_SP = 0x0,
|
||||
|
|
@ -2547,7 +3038,7 @@ struct wmi_scheduling_scheme_event {
|
|||
u8 reserved[1];
|
||||
} __packed;
|
||||
|
||||
/* WMI_RS_CFG_CMDID */
|
||||
/* WMI_RS_CFG_CMDID - deprecated */
|
||||
struct wmi_rs_cfg_cmd {
|
||||
/* connection id */
|
||||
u8 cid;
|
||||
|
|
@ -2557,7 +3048,7 @@ struct wmi_rs_cfg_cmd {
|
|||
struct wmi_rs_cfg rs_cfg;
|
||||
} __packed;
|
||||
|
||||
/* WMI_RS_CFG_DONE_EVENTID */
|
||||
/* WMI_RS_CFG_DONE_EVENTID - deprecated */
|
||||
struct wmi_rs_cfg_done_event {
|
||||
u8 cid;
|
||||
/* enum wmi_fw_status */
|
||||
|
|
@ -2565,7 +3056,7 @@ struct wmi_rs_cfg_done_event {
|
|||
u8 reserved[2];
|
||||
} __packed;
|
||||
|
||||
/* WMI_GET_DETAILED_RS_RES_CMDID */
|
||||
/* WMI_GET_DETAILED_RS_RES_CMDID - deprecated */
|
||||
struct wmi_get_detailed_rs_res_cmd {
|
||||
/* connection id */
|
||||
u8 cid;
|
||||
|
|
@ -2590,7 +3081,7 @@ struct wmi_rs_results {
|
|||
u8 mcs;
|
||||
} __packed;
|
||||
|
||||
/* WMI_GET_DETAILED_RS_RES_EVENTID */
|
||||
/* WMI_GET_DETAILED_RS_RES_EVENTID - deprecated */
|
||||
struct wmi_get_detailed_rs_res_event {
|
||||
u8 cid;
|
||||
/* enum wmi_rs_results_status */
|
||||
|
|
@ -2600,6 +3091,45 @@ struct wmi_get_detailed_rs_res_event {
|
|||
u8 reserved[3];
|
||||
} __packed;
|
||||
|
||||
/* WMI_GET_DETAILED_RS_RES_EX_CMDID */
|
||||
struct wmi_get_detailed_rs_res_ex_cmd {
|
||||
u8 cid;
|
||||
u8 reserved[3];
|
||||
} __packed;
|
||||
|
||||
/* Rate search results */
|
||||
struct wmi_rs_results_ex_common {
|
||||
/* RS timestamp */
|
||||
__le32 tsf;
|
||||
/* RS selected MCS */
|
||||
u8 mcs;
|
||||
/* enum wmi_edmg_tx_mode */
|
||||
u8 mode;
|
||||
u8 reserved[2];
|
||||
} __packed;
|
||||
|
||||
/* Rate search results */
|
||||
struct wmi_rs_results_ex_mcs {
|
||||
/* number of sent MPDUs */
|
||||
u8 num_of_tx_pkt;
|
||||
/* number of non-acked MPDUs */
|
||||
u8 num_of_non_acked_pkt;
|
||||
u8 reserved[2];
|
||||
} __packed;
|
||||
|
||||
/* WMI_GET_DETAILED_RS_RES_EX_EVENTID */
|
||||
struct wmi_get_detailed_rs_res_ex_event {
|
||||
u8 cid;
|
||||
/* enum wmi_rs_results_status */
|
||||
u8 status;
|
||||
u8 reserved0[2];
|
||||
struct wmi_rs_results_ex_common common_rs_results;
|
||||
u8 each_mcs_results_size;
|
||||
u8 reserved1[3];
|
||||
/* Results for each MCS */
|
||||
struct wmi_rs_results_ex_mcs each_mcs_results[0];
|
||||
} __packed;
|
||||
|
||||
/* BRP antenna limit mode */
|
||||
enum wmi_brp_ant_limit_mode {
|
||||
/* Disable BRP force antenna limit */
|
||||
|
|
@ -3350,13 +3880,20 @@ struct wmi_get_assoc_list_res_event {
|
|||
u8 reserved[3];
|
||||
} __packed;
|
||||
|
||||
/* WMI_BF_CONTROL_EVENTID */
|
||||
/* WMI_BF_CONTROL_EVENTID - deprecated */
|
||||
struct wmi_bf_control_event {
|
||||
/* wmi_fw_status */
|
||||
u8 status;
|
||||
u8 reserved[3];
|
||||
} __packed;
|
||||
|
||||
/* WMI_BF_CONTROL_EX_EVENTID */
|
||||
struct wmi_bf_control_ex_event {
|
||||
/* wmi_fw_status */
|
||||
u8 status;
|
||||
u8 reserved[3];
|
||||
} __packed;
|
||||
|
||||
/* WMI_COMMAND_NOT_SUPPORTED_EVENTID */
|
||||
struct wmi_command_not_supported_event {
|
||||
/* device id */
|
||||
|
|
@ -3426,4 +3963,96 @@ struct wmi_internal_fw_set_channel_event {
|
|||
u8 reserved[3];
|
||||
} __packed;
|
||||
|
||||
/* WMI_LINK_STATS_CONFIG_DONE_EVENTID */
|
||||
struct wmi_link_stats_config_done_event {
|
||||
/* wmi_fw_status_e */
|
||||
u8 status;
|
||||
u8 reserved[3];
|
||||
} __packed;
|
||||
|
||||
/* WMI_LINK_STATS_EVENTID */
|
||||
struct wmi_link_stats_event {
|
||||
__le64 tsf;
|
||||
__le16 payload_size;
|
||||
u8 has_next;
|
||||
u8 reserved[5];
|
||||
/* a stream of wmi_link_stats_record_s */
|
||||
u8 payload[0];
|
||||
} __packed;
|
||||
|
||||
/* WMI_LINK_STATS_EVENT */
|
||||
struct wmi_link_stats_record {
|
||||
/* wmi_link_stats_record_type_e */
|
||||
u8 record_type_id;
|
||||
u8 reserved;
|
||||
__le16 record_size;
|
||||
u8 record[0];
|
||||
} __packed;
|
||||
|
||||
/* WMI_LINK_STATS_TYPE_BASIC */
|
||||
struct wmi_link_stats_basic {
|
||||
u8 cid;
|
||||
s8 rssi;
|
||||
u8 sqi;
|
||||
u8 bf_mcs;
|
||||
u8 per_average;
|
||||
u8 selected_rfc;
|
||||
u8 rx_effective_ant_num;
|
||||
u8 my_rx_sector;
|
||||
u8 my_tx_sector;
|
||||
u8 other_rx_sector;
|
||||
u8 other_tx_sector;
|
||||
u8 reserved[7];
|
||||
/* 1/4 Db units */
|
||||
__le16 snr;
|
||||
__le32 tx_tpt;
|
||||
__le32 tx_goodput;
|
||||
__le32 rx_goodput;
|
||||
__le32 bf_count;
|
||||
__le32 rx_bcast_frames;
|
||||
} __packed;
|
||||
|
||||
/* WMI_LINK_STATS_TYPE_GLOBAL */
|
||||
struct wmi_link_stats_global {
|
||||
/* all ack-able frames */
|
||||
__le32 rx_frames;
|
||||
/* all ack-able frames */
|
||||
__le32 tx_frames;
|
||||
__le32 rx_ba_frames;
|
||||
__le32 tx_ba_frames;
|
||||
__le32 tx_beacons;
|
||||
__le32 rx_mic_errors;
|
||||
__le32 rx_crc_errors;
|
||||
__le32 tx_fail_no_ack;
|
||||
u8 reserved[8];
|
||||
} __packed;
|
||||
|
||||
/* WMI_SET_GRANT_MCS_EVENTID */
|
||||
struct wmi_set_grant_mcs_event {
|
||||
/* wmi_fw_status */
|
||||
u8 status;
|
||||
u8 reserved[3];
|
||||
} __packed;
|
||||
|
||||
/* WMI_SET_AP_SLOT_SIZE_EVENTID */
|
||||
struct wmi_set_ap_slot_size_event {
|
||||
/* wmi_fw_status */
|
||||
u8 status;
|
||||
u8 reserved[3];
|
||||
} __packed;
|
||||
|
||||
/* WMI_SET_VRING_PRIORITY_WEIGHT_EVENTID */
|
||||
struct wmi_set_vring_priority_weight_event {
|
||||
/* wmi_fw_status */
|
||||
u8 status;
|
||||
u8 reserved[3];
|
||||
} __packed;
|
||||
|
||||
/* WMI_SET_VRING_PRIORITY_EVENTID */
|
||||
struct wmi_set_vring_priority_event {
|
||||
/* wmi_fw_status */
|
||||
u8 status;
|
||||
u8 reserved[3];
|
||||
} __packed;
|
||||
|
||||
#endif /* __WILOCITY_WMI_H__ */
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user