summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKalle Valo <kvalo@codeaurora.org>2019-12-19 18:27:36 +0200
committerKalle Valo <kvalo@codeaurora.org>2019-12-19 18:27:36 +0200
commitae0a723c4cfd89dad31ce238f47ccfbe81b35b84 (patch)
tree5d485700086b25cd6a5bc230c604d3115598ae06
parentc705f9fc6a1736dcf6ec01f8206707c108dca824 (diff)
parentca0e477931c5a725bb887c764a49eb5d69ab7a67 (diff)
Merge ath-next from git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
ath.git patches for v5.6. Major changes: wil6210 * support set_multicast_to_unicast cfg80211 operation * support set_cqm_rssi_config cfg80211 operation wcn36xx * disable HW_CONNECTION_MONITOR as firmware is buggy
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.c2
-rw-r--r--drivers/net/wireless/ath/ath10k/testmode.c4
-rw-r--r--drivers/net/wireless/ath/ath11k/ce.c23
-rw-r--r--drivers/net/wireless/ath/ath11k/core.c4
-rw-r--r--drivers/net/wireless/ath/ath11k/core.h2
-rw-r--r--drivers/net/wireless/ath/ath11k/debug.c6
-rw-r--r--drivers/net/wireless/ath/ath11k/debug_htt_stats.c3
-rw-r--r--drivers/net/wireless/ath/ath11k/debugfs_sta.c63
-rw-r--r--drivers/net/wireless/ath/ath11k/dp.c16
-rw-r--r--drivers/net/wireless/ath/ath11k/dp.h11
-rw-r--r--drivers/net/wireless/ath/ath11k/dp_rx.c4
-rw-r--r--drivers/net/wireless/ath/ath11k/dp_tx.c88
-rw-r--r--drivers/net/wireless/ath/ath11k/hal_tx.c74
-rw-r--r--drivers/net/wireless/ath/ath11k/hal_tx.h13
-rw-r--r--drivers/net/wireless/ath/ath11k/htc.c2
-rw-r--r--drivers/net/wireless/ath/ath11k/mac.c104
-rw-r--r--drivers/net/wireless/ath/ath11k/testmode.c2
-rw-r--r--drivers/net/wireless/ath/ath11k/wmi.c184
-rw-r--r--drivers/net/wireless/ath/ath11k/wmi.h32
-rw-r--r--drivers/net/wireless/ath/ath9k/hif_usb.c2
-rw-r--r--drivers/net/wireless/ath/wcn36xx/main.c1
-rw-r--r--drivers/net/wireless/ath/wil6210/cfg80211.c34
-rw-r--r--drivers/net/wireless/ath/wil6210/main.c10
-rw-r--r--drivers/net/wireless/ath/wil6210/txrx.c32
-rw-r--r--drivers/net/wireless/ath/wil6210/txrx_edma.c10
-rw-r--r--drivers/net/wireless/ath/wil6210/txrx_edma.h8
-rw-r--r--drivers/net/wireless/ath/wil6210/wil6210.h6
-rw-r--r--drivers/net/wireless/ath/wil6210/wil_crash_dump.c17
-rw-r--r--drivers/net/wireless/ath/wil6210/wmi.c80
-rw-r--r--drivers/net/wireless/ath/wil6210/wmi.h33
30 files changed, 568 insertions, 302 deletions
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 767c7bf16975..0969e9bf5d5e 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -1098,7 +1098,7 @@ static int ath10k_monitor_vdev_stop(struct ath10k *ar)
ret = ath10k_wmi_vdev_stop(ar, ar->monitor_vdev_id);
if (ret)
- ath10k_warn(ar, "failed to to request monitor vdev %i stop: %d\n",
+ ath10k_warn(ar, "failed to request monitor vdev %i stop: %d\n",
ar->monitor_vdev_id, ret);
ret = ath10k_vdev_setup_sync(ar);
diff --git a/drivers/net/wireless/ath/ath10k/testmode.c b/drivers/net/wireless/ath/ath10k/testmode.c
index 1bffe3fbea3f..7a9b9bbcdbfc 100644
--- a/drivers/net/wireless/ath/ath10k/testmode.c
+++ b/drivers/net/wireless/ath/ath10k/testmode.c
@@ -65,7 +65,7 @@ bool ath10k_tm_event_wmi(struct ath10k *ar, u32 cmd_id, struct sk_buff *skb)
ret = nla_put_u32(nl_skb, ATH10K_TM_ATTR_CMD, ATH10K_TM_CMD_WMI);
if (ret) {
ath10k_warn(ar,
- "failed to to put testmode wmi event cmd attribute: %d\n",
+ "failed to put testmode wmi event cmd attribute: %d\n",
ret);
kfree_skb(nl_skb);
goto out;
@@ -74,7 +74,7 @@ bool ath10k_tm_event_wmi(struct ath10k *ar, u32 cmd_id, struct sk_buff *skb)
ret = nla_put_u32(nl_skb, ATH10K_TM_ATTR_WMI_CMDID, cmd_id);
if (ret) {
ath10k_warn(ar,
- "failed to to put testmode wmi even cmd_id: %d\n",
+ "failed to put testmode wmi event cmd_id: %d\n",
ret);
kfree_skb(nl_skb);
goto out;
diff --git a/drivers/net/wireless/ath/ath11k/ce.c b/drivers/net/wireless/ath/ath11k/ce.c
index a6572b414303..cdd40c8fc867 100644
--- a/drivers/net/wireless/ath/ath11k/ce.c
+++ b/drivers/net/wireless/ath/ath11k/ce.c
@@ -441,6 +441,7 @@ static int ath11k_ce_alloc_pipe(struct ath11k_base *ab, int ce_id)
{
struct ath11k_ce_pipe *pipe = &ab->ce.ce_pipe[ce_id];
const struct ce_attr *attr = &host_ce_config_wlan[ce_id];
+ struct ath11k_ce_ring *ring;
int nentries;
int desc_sz;
@@ -450,24 +451,26 @@ static int ath11k_ce_alloc_pipe(struct ath11k_base *ab, int ce_id)
pipe->send_cb = ath11k_ce_send_done_cb;
nentries = roundup_pow_of_two(attr->src_nentries);
desc_sz = ath11k_hal_ce_get_desc_size(HAL_CE_DESC_SRC);
- pipe->src_ring = ath11k_ce_alloc_ring(ab, nentries, desc_sz);
- if (!pipe->src_ring)
- return -ENOMEM;
+ ring = ath11k_ce_alloc_ring(ab, nentries, desc_sz);
+ if (IS_ERR(ring))
+ return PTR_ERR(ring);
+ pipe->src_ring = ring;
}
if (attr->dest_nentries) {
pipe->recv_cb = attr->recv_cb;
nentries = roundup_pow_of_two(attr->dest_nentries);
desc_sz = ath11k_hal_ce_get_desc_size(HAL_CE_DESC_DST);
- pipe->dest_ring = ath11k_ce_alloc_ring(ab, nentries, desc_sz);
-
- if (!pipe->dest_ring)
- return -ENOMEM;
+ ring = ath11k_ce_alloc_ring(ab, nentries, desc_sz);
+ if (IS_ERR(ring))
+ return PTR_ERR(ring);
+ pipe->dest_ring = ring;
desc_sz = ath11k_hal_ce_get_desc_size(HAL_CE_DESC_DST_STATUS);
- pipe->status_ring = ath11k_ce_alloc_ring(ab, nentries, desc_sz);
- if (!pipe->status_ring)
- return -ENOMEM;
+ ring = ath11k_ce_alloc_ring(ab, nentries, desc_sz);
+ if (IS_ERR(ring))
+ return PTR_ERR(ring);
+ pipe->status_ring = ring;
}
return 0;
diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c
index 5cdc9b2aee51..9e823056e673 100644
--- a/drivers/net/wireless/ath/ath11k/core.c
+++ b/drivers/net/wireless/ath/ath11k/core.c
@@ -651,7 +651,7 @@ static void ath11k_core_restart(struct work_struct *work)
idr_destroy(&ar->txmgmt_idr);
}
- wake_up(&ab->wmi_sc.tx_credits_wq);
+ wake_up(&ab->wmi_ab.tx_credits_wq);
wake_up(&ab->peer_mapping_wq);
ret = ath11k_core_reconfigure_on_crash(ab);
@@ -761,7 +761,7 @@ struct ath11k_base *ath11k_core_alloc(struct device *dev)
INIT_LIST_HEAD(&ab->peers);
init_waitqueue_head(&ab->peer_mapping_wq);
- init_waitqueue_head(&ab->wmi_sc.tx_credits_wq);
+ init_waitqueue_head(&ab->wmi_ab.tx_credits_wq);
INIT_WORK(&ab->restart_work, ath11k_core_restart);
timer_setup(&ab->rx_replenish_retry, ath11k_ce_rx_replenish_retry, 0);
ab->dev = dev;
diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h
index 06482a5c102d..25cdcf71d0c4 100644
--- a/drivers/net/wireless/ath/ath11k/core.h
+++ b/drivers/net/wireless/ath/ath11k/core.h
@@ -578,7 +578,7 @@ struct ath11k_base {
struct platform_device *pdev;
struct device *dev;
struct ath11k_qmi qmi;
- struct ath11k_wmi_base wmi_sc;
+ struct ath11k_wmi_base wmi_ab;
struct completion fw_ready;
struct rproc *tgt_rproc;
int num_radios;
diff --git a/drivers/net/wireless/ath/ath11k/debug.c b/drivers/net/wireless/ath/ath11k/debug.c
index c27fffd13a5d..f48daf17f2d2 100644
--- a/drivers/net/wireless/ath/ath11k/debug.c
+++ b/drivers/net/wireless/ath/ath11k/debug.c
@@ -541,7 +541,7 @@ static ssize_t ath11k_write_simulate_fw_crash(struct file *file,
struct ath11k *ar = ab->pdevs[0].ar;
char buf[32] = {0};
ssize_t rc;
- int i, ret, radioup;
+ int i, ret, radioup = 0;
for (i = 0; i < ab->num_radios; i++) {
pdev = &ab->pdevs[i];
@@ -704,7 +704,7 @@ static ssize_t ath11k_write_extd_rx_stats(struct file *file,
DP_RX_BUFFER_SIZE, &tlv_filter);
if (ret) {
- ath11k_warn(ar->ab, "failed to set rx filter for moniter status ring\n");
+ ath11k_warn(ar->ab, "failed to set rx filter for monitor status ring\n");
goto exit;
}
@@ -948,7 +948,7 @@ static ssize_t ath11k_write_pktlog_filter(struct file *file,
HAL_RXDMA_MONITOR_STATUS,
DP_RX_BUFFER_SIZE, &tlv_filter);
if (ret) {
- ath11k_warn(ar->ab, "failed to set rx filter for moniter status ring\n");
+ ath11k_warn(ar->ab, "failed to set rx filter for monitor status ring\n");
goto out;
}
diff --git a/drivers/net/wireless/ath/ath11k/debug_htt_stats.c b/drivers/net/wireless/ath/ath11k/debug_htt_stats.c
index 27b301bc1a1b..090fffa5e53c 100644
--- a/drivers/net/wireless/ath/ath11k/debug_htt_stats.c
+++ b/drivers/net/wireless/ath/ath11k/debug_htt_stats.c
@@ -3512,7 +3512,7 @@ htt_print_rx_pdev_fw_stats_phy_err_tlv(const void *tag_buf,
len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_RX_PDEV_FW_STATS_PHY_ERR_TLV:");
len += HTT_DBG_OUT(buf + len, buf_len - len, "mac_id__word = %u",
htt_stats_buf->mac_id__word);
- len += HTT_DBG_OUT(buf + len, buf_len - len, "tota_phy_err_nct = %u",
+ len += HTT_DBG_OUT(buf + len, buf_len - len, "total_phy_err_nct = %u",
htt_stats_buf->total_phy_err_cnt);
ARRAY_TO_STRING(phy_errs,
@@ -4287,7 +4287,6 @@ int ath11k_dbg_htt_stats_req(struct ath11k *ar)
ret = ath11k_dp_tx_htt_h2t_ext_stats_req(ar, type, &cfg_params, cookie);
if (ret) {
ath11k_warn(ar->ab, "failed to send htt stats request: %d\n", ret);
- mutex_unlock(&ar->conf_mutex);
return ret;
}
diff --git a/drivers/net/wireless/ath/ath11k/debugfs_sta.c b/drivers/net/wireless/ath/ath11k/debugfs_sta.c
index 3c5f931e22a9..743760c9bcae 100644
--- a/drivers/net/wireless/ath/ath11k/debugfs_sta.c
+++ b/drivers/net/wireless/ath/ath11k/debugfs_sta.c
@@ -129,12 +129,16 @@ void ath11k_update_per_peer_stats_from_txcompl(struct ath11k *ar,
{
struct ath11k_base *ab = ar->ab;
struct ath11k_per_peer_tx_stats *peer_stats = &ar->cached_stats;
+ enum hal_tx_rate_stats_pkt_type pkt_type;
+ enum hal_tx_rate_stats_sgi sgi;
+ enum hal_tx_rate_stats_bw bw;
struct ath11k_peer *peer;
struct ath11k_sta *arsta;
struct ieee80211_sta *sta;
u16 rate;
u8 rate_idx;
int ret;
+ u8 mcs;
rcu_read_lock();
spin_lock_bh(&ab->base_lock);
@@ -150,51 +154,52 @@ void ath11k_update_per_peer_stats_from_txcompl(struct ath11k *ar,
arsta = (struct ath11k_sta *)sta->drv_priv;
memset(&arsta->txrate, 0, sizeof(arsta->txrate));
-
- if (ts->pkt_type == HAL_TX_RATE_STATS_PKT_TYPE_11A ||
- ts->pkt_type == HAL_TX_RATE_STATS_PKT_TYPE_11B) {
- ret = ath11k_mac_hw_ratecode_to_legacy_rate(ts->mcs,
- ts->pkt_type,
+ pkt_type = FIELD_GET(HAL_TX_RATE_STATS_INFO0_PKT_TYPE,
+ ts->rate_stats);
+ mcs = FIELD_GET(HAL_TX_RATE_STATS_INFO0_MCS,
+ ts->rate_stats);
+ sgi = FIELD_GET(HAL_TX_RATE_STATS_INFO0_SGI,
+ ts->rate_stats);
+ bw = FIELD_GET(HAL_TX_RATE_STATS_INFO0_BW, ts->rate_stats);
+
+ if (pkt_type == HAL_TX_RATE_STATS_PKT_TYPE_11A ||
+ pkt_type == HAL_TX_RATE_STATS_PKT_TYPE_11B) {
+ ret = ath11k_mac_hw_ratecode_to_legacy_rate(mcs,
+ pkt_type,
&rate_idx,
&rate);
- if (ret < 0) {
- spin_unlock_bh(&ab->base_lock);
- rcu_read_unlock();
- return;
- }
+ if (ret < 0)
+ goto err_out;
arsta->txrate.legacy = rate;
- } else if (ts->pkt_type == HAL_TX_RATE_STATS_PKT_TYPE_11N) {
- if (ts->mcs > 7) {
- ath11k_warn(ab, "Invalid HT mcs index %d\n", ts->mcs);
- spin_unlock_bh(&ab->base_lock);
- rcu_read_unlock();
- return;
+ } else if (pkt_type == HAL_TX_RATE_STATS_PKT_TYPE_11N) {
+ if (mcs > 7) {
+ ath11k_warn(ab, "Invalid HT mcs index %d\n", mcs);
+ goto err_out;
}
- arsta->txrate.mcs = ts->mcs + 8 * (arsta->last_txrate.nss - 1);
+ arsta->txrate.mcs = mcs + 8 * (arsta->last_txrate.nss - 1);
arsta->txrate.flags = RATE_INFO_FLAGS_MCS;
- if (ts->sgi)
+ if (sgi)
arsta->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
- } else if (ts->pkt_type == HAL_TX_RATE_STATS_PKT_TYPE_11AC) {
- if (ts->mcs > 9) {
- ath11k_warn(ab, "Invalid VHT mcs index %d\n", ts->mcs);
- spin_unlock_bh(&ab->base_lock);
- rcu_read_unlock();
- return;
+ } else if (pkt_type == HAL_TX_RATE_STATS_PKT_TYPE_11AC) {
+ if (mcs > 9) {
+ ath11k_warn(ab, "Invalid VHT mcs index %d\n", mcs);
+ goto err_out;
}
- arsta->txrate.mcs = ts->mcs;
+ arsta->txrate.mcs = mcs;
arsta->txrate.flags = RATE_INFO_FLAGS_VHT_MCS;
- if (ts->sgi)
+ if (sgi)
arsta->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
- } else {
- /*TODO: update HE rates */
+ } else if (pkt_type == HAL_TX_RATE_STATS_PKT_TYPE_11AX) {
+ /* TODO */
}
arsta->txrate.nss = arsta->last_txrate.nss;
- arsta->txrate.bw = ath11k_mac_bw_to_mac80211_bw(ts->bw);
+ arsta->txrate.bw = ath11k_mac_bw_to_mac80211_bw(bw);
ath11k_accumulate_per_peer_tx_stats(arsta, peer_stats, rate_idx);
+err_out:
spin_unlock_bh(&ab->base_lock);
rcu_read_unlock();
}
diff --git a/drivers/net/wireless/ath/ath11k/dp.c b/drivers/net/wireless/ath/ath11k/dp.c
index b966a16a930f..b112825a52ed 100644
--- a/drivers/net/wireless/ath/ath11k/dp.c
+++ b/drivers/net/wireless/ath/ath11k/dp.c
@@ -3,7 +3,6 @@
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
*/
-#include <linux/kfifo.h>
#include "core.h"
#include "dp_tx.h"
#include "hal_tx.h"
@@ -828,10 +827,7 @@ void ath11k_dp_free(struct ath11k_base *ab)
ath11k_dp_tx_pending_cleanup, ab);
idr_destroy(&dp->tx_ring[i].txbuf_idr);
spin_unlock_bh(&dp->tx_ring[i].tx_idr_lock);
-
- spin_lock_bh(&dp->tx_ring[i].tx_status_lock);
- kfifo_free(&dp->tx_ring[i].tx_status_fifo);
- spin_unlock_bh(&dp->tx_ring[i].tx_status_lock);
+ kfree(dp->tx_ring[i].tx_status);
}
/* Deinit any SOC level resource */
@@ -871,17 +867,17 @@ int ath11k_dp_alloc(struct ath11k_base *ab)
if (ret)
goto fail_link_desc_cleanup;
- size = roundup_pow_of_two(DP_TX_COMP_RING_SIZE);
+ size = sizeof(struct hal_wbm_release_ring) * DP_TX_COMP_RING_SIZE;
for (i = 0; i < DP_TCL_NUM_RING_MAX; i++) {
idr_init(&dp->tx_ring[i].txbuf_idr);
spin_lock_init(&dp->tx_ring[i].tx_idr_lock);
dp->tx_ring[i].tcl_data_ring_id = i;
- spin_lock_init(&dp->tx_ring[i].tx_status_lock);
- ret = kfifo_alloc(&dp->tx_ring[i].tx_status_fifo, size,
- GFP_KERNEL);
- if (ret)
+ dp->tx_ring[i].tx_status_head = 0;
+ dp->tx_ring[i].tx_status_tail = DP_TX_COMP_RING_SIZE - 1;
+ dp->tx_ring[i].tx_status = kmalloc(size, GFP_KERNEL);
+ if (!dp->tx_ring[i].tx_status)
goto fail_cmn_srng_cleanup;
}
diff --git a/drivers/net/wireless/ath/ath11k/dp.h b/drivers/net/wireless/ath/ath11k/dp.h
index f7e53509ae07..2f0980f2c762 100644
--- a/drivers/net/wireless/ath/ath11k/dp.h
+++ b/drivers/net/wireless/ath/ath11k/dp.h
@@ -6,7 +6,6 @@
#ifndef ATH11K_DP_H
#define ATH11K_DP_H
-#include <linux/kfifo.h>
#include "hal_rx.h"
struct ath11k_base;
@@ -58,6 +57,8 @@ struct dp_rxdma_ring {
int bufs_max;
};
+#define ATH11K_TX_COMPL_NEXT(x) (((x) + 1) % DP_TX_COMP_RING_SIZE)
+
struct dp_tx_ring {
u8 tcl_data_ring_id;
struct dp_srng tcl_data_ring;
@@ -65,11 +66,9 @@ struct dp_tx_ring {
struct idr txbuf_idr;
/* Protects txbuf_idr and num_pending */
spinlock_t tx_idr_lock;
- DECLARE_KFIFO_PTR(tx_status_fifo, struct hal_wbm_release_ring);
- /* lock to protect tx_status_fifo because tx_status_fifo can be
- * accessed concurrently.
- */
- spinlock_t tx_status_lock;
+ struct hal_wbm_release_ring *tx_status;
+ int tx_status_head;
+ int tx_status_tail;
};
struct ath11k_pdev_mon_stats {
diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c
index 1b3b65c0038c..3a3dc7680622 100644
--- a/drivers/net/wireless/ath/ath11k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
@@ -1225,12 +1225,12 @@ static
struct htt_ppdu_stats_info *ath11k_dp_htt_get_ppdu_desc(struct ath11k *ar,
u32 ppdu_id)
{
- struct htt_ppdu_stats_info *ppdu_info = NULL;
+ struct htt_ppdu_stats_info *ppdu_info;
spin_lock_bh(&ar->data_lock);
if (!list_empty(&ar->ppdu_stats_info)) {
list_for_each_entry(ppdu_info, &ar->ppdu_stats_info, list) {
- if (ppdu_info && ppdu_info->ppdu_id == ppdu_id) {
+ if (ppdu_info->ppdu_id == ppdu_id) {
spin_unlock_bh(&ar->data_lock);
return ppdu_info;
}
diff --git a/drivers/net/wireless/ath/ath11k/dp_tx.c b/drivers/net/wireless/ath/ath11k/dp_tx.c
index a8b9557c2346..918305dda106 100644
--- a/drivers/net/wireless/ath/ath11k/dp_tx.c
+++ b/drivers/net/wireless/ath/ath11k/dp_tx.c
@@ -79,7 +79,6 @@ int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif,
struct hal_srng *tcl_ring;
struct ieee80211_hdr *hdr = (void *)skb->data;
struct dp_tx_ring *tx_ring;
- u8 cached_desc[HAL_TCL_DESC_LEN];
void *hal_tcl_desc;
u8 pool_id;
u8 hal_ring_id;
@@ -167,10 +166,6 @@ int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif,
skb_cb->vif = arvif->vif;
skb_cb->ar = ar;
- memset(cached_desc, 0, HAL_TCL_DESC_LEN);
-
- ath11k_hal_tx_cmd_desc_setup(ab, cached_desc, &ti);
-
hal_ring_id = tx_ring->tcl_data_ring.ring_id;
tcl_ring = &ab->hal.srng_list[hal_ring_id];
@@ -190,7 +185,8 @@ int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif,
goto fail_unmap_dma;
}
- ath11k_hal_tx_desc_sync(cached_desc, hal_tcl_desc);
+ ath11k_hal_tx_cmd_desc_setup(ab, hal_tcl_desc +
+ sizeof(struct hal_tlv_hdr), &ti);
ath11k_hal_srng_access_end(ab, tcl_ring);
@@ -427,6 +423,37 @@ exit:
rcu_read_unlock();
}
+static inline void ath11k_dp_tx_status_parse(struct ath11k_base *ab,
+ struct hal_wbm_release_ring *desc,
+ struct hal_tx_status *ts)
+{
+ ts->buf_rel_source =
+ FIELD_GET(HAL_WBM_RELEASE_INFO0_REL_SRC_MODULE, desc->info0);
+ if (ts->buf_rel_source != HAL_WBM_REL_SRC_MODULE_FW &&
+ ts->buf_rel_source != HAL_WBM_REL_SRC_MODULE_TQM)
+ return;
+
+ if (ts->buf_rel_source == HAL_WBM_REL_SRC_MODULE_FW)
+ return;
+
+ ts->status = FIELD_GET(HAL_WBM_RELEASE_INFO0_TQM_RELEASE_REASON,
+ desc->info0);
+ ts->ppdu_id = FIELD_GET(HAL_WBM_RELEASE_INFO1_TQM_STATUS_NUMBER,
+ desc->info1);
+ ts->try_cnt = FIELD_GET(HAL_WBM_RELEASE_INFO1_TRANSMIT_COUNT,
+ desc->info1);
+ ts->ack_rssi = FIELD_GET(HAL_WBM_RELEASE_INFO2_ACK_FRAME_RSSI,
+ desc->info2);
+ if (desc->info2 & HAL_WBM_RELEASE_INFO2_FIRST_MSDU)
+ ts->flags |= HAL_TX_STATUS_FLAGS_FIRST_MSDU;
+ ts->peer_id = FIELD_GET(HAL_WBM_RELEASE_INFO3_PEER_ID, desc->info3);
+ ts->tid = FIELD_GET(HAL_WBM_RELEASE_INFO3_TID, desc->info3);
+ if (desc->rate_stats.info0 & HAL_TX_RATE_STATS_INFO0_VALID)
+ ts->rate_stats = desc->rate_stats.info0;
+ else
+ ts->rate_stats = 0;
+}
+
void ath11k_dp_tx_completion_handler(struct ath11k_base *ab, int ring_id)
{
struct ath11k *ar;
@@ -434,47 +461,48 @@ void ath11k_dp_tx_completion_handler(struct ath11k_base *ab, int ring_id)
int hal_ring_id = dp->tx_ring[ring_id].tcl_comp_ring.ring_id;
struct hal_srng *status_ring = &ab->hal.srng_list[hal_ring_id];
struct sk_buff *msdu;
- struct hal_wbm_release_ring tx_status;
struct hal_tx_status ts;
struct dp_tx_ring *tx_ring = &dp->tx_ring[ring_id];
u32 *desc;
u32 msdu_id;
u8 mac_id;
- spin_lock_bh(&status_ring->lock);
-
ath11k_hal_srng_access_begin(ab, status_ring);
- spin_lock_bh(&tx_ring->tx_status_lock);
- while (!kfifo_is_full(&tx_ring->tx_status_fifo) &&
+ while ((ATH11K_TX_COMPL_NEXT(tx_ring->tx_status_head) !=
+ tx_ring->tx_status_tail) &&
(desc = ath11k_hal_srng_dst_get_next_entry(ab, status_ring))) {
- ath11k_hal_tx_status_desc_sync((void *)desc,
- (void *)&tx_status);
- kfifo_put(&tx_ring->tx_status_fifo, tx_status);
+ memcpy(&tx_ring->tx_status[tx_ring->tx_status_head],
+ desc, sizeof(struct hal_wbm_release_ring));
+ tx_ring->tx_status_head =
+ ATH11K_TX_COMPL_NEXT(tx_ring->tx_status_head);
}
if ((ath11k_hal_srng_dst_peek(ab, status_ring) != NULL) &&
- kfifo_is_full(&tx_ring->tx_status_fifo)) {
+ (ATH11K_TX_COMPL_NEXT(tx_ring->tx_status_head) == tx_ring->tx_status_tail)) {
/* TODO: Process pending tx_status messages when kfifo_is_full() */
ath11k_warn(ab, "Unable to process some of the tx_status ring desc because status_fifo is full\n");
}
- spin_unlock_bh(&tx_ring->tx_status_lock);
-
ath11k_hal_srng_access_end(ab, status_ring);
- spin_unlock_bh(&status_ring->lock);
- spin_lock_bh(&tx_ring->tx_status_lock);
- while (kfifo_get(&tx_ring->tx_status_fifo, &tx_status)) {
- memset(&ts, 0, sizeof(ts));
- ath11k_hal_tx_status_parse(ab, &tx_status, &ts);
+ while (ATH11K_TX_COMPL_NEXT(tx_ring->tx_status_tail) != tx_ring->tx_status_head) {
+ struct hal_wbm_release_ring *tx_status;
+ u32 desc_id;
+
+ tx_ring->tx_status_tail =
+ ATH11K_TX_COMPL_NEXT(tx_ring->tx_status_tail);
+ tx_status = &tx_ring->tx_status[tx_ring->tx_status_tail];
+ ath11k_dp_tx_status_parse(ab, tx_status, &ts);
- mac_id = FIELD_GET(DP_TX_DESC_ID_MAC_ID, ts.desc_id);
- msdu_id = FIELD_GET(DP_TX_DESC_ID_MSDU_ID, ts.desc_id);
+ desc_id = FIELD_GET(BUFFER_ADDR_INFO1_SW_COOKIE,
+ tx_status->buf_addr_info.info1);
+ mac_id = FIELD_GET(DP_TX_DESC_ID_MAC_ID, desc_id);
+ msdu_id = FIELD_GET(DP_TX_DESC_ID_MSDU_ID, desc_id);
if (ts.buf_rel_source == HAL_WBM_REL_SRC_MODULE_FW) {
ath11k_dp_tx_process_htt_tx_complete(ab,
- (void *)&tx_status,
+ (void *)tx_status,
mac_id, msdu_id,
tx_ring);
continue;
@@ -496,12 +524,8 @@ void ath11k_dp_tx_completion_handler(struct ath11k_base *ab, int ring_id)
if (atomic_dec_and_test(&ar->dp.num_tx_pending))
wake_up(&ar->dp.tx_empty_waitq);
- /* TODO: Locking optimization so that tx_completion for an msdu
- * is not called with tx_status_lock acquired
- */
ath11k_dp_tx_complete_msdu(ar, msdu, &ts);
}
- spin_unlock_bh(&tx_ring->tx_status_lock);
}
int ath11k_dp_tx_send_reo_cmd(struct ath11k_base *ab, struct dp_rx_tid *rx_tid,
@@ -645,8 +669,10 @@ int ath11k_dp_tx_htt_srng_setup(struct ath11k_base *ab, u32 ring_id,
HAL_ADDR_MSB_REG_SHIFT;
ret = ath11k_hal_srng_get_entrysize(ring_type);
- if (ret < 0)
- return -EINVAL;
+ if (ret < 0) {
+ ret = -EINVAL;
+ goto err_free;
+ }
ring_entry_sz = ret;
diff --git a/drivers/net/wireless/ath/ath11k/hal_tx.c b/drivers/net/wireless/ath/ath11k/hal_tx.c
index cbe549798762..e4aa7e8a1284 100644
--- a/drivers/net/wireless/ath/ath11k/hal_tx.c
+++ b/drivers/net/wireless/ath/ath11k/hal_tx.c
@@ -71,79 +71,7 @@ void ath11k_hal_tx_cmd_desc_setup(struct ath11k_base *ab, void *cmd,
ti->dscp_tid_tbl_idx) |
FIELD_PREP(HAL_TCL_DATA_CMD_INFO3_SEARCH_INDEX,
ti->bss_ast_hash);
-}
-
-/* Commit the descriptor to hardware */
-void ath11k_hal_tx_desc_sync(void *tx_desc_cached, void *hw_desc)
-{
- memcpy(hw_desc + sizeof(struct hal_tlv_hdr), tx_desc_cached,
- sizeof(struct hal_tcl_data_cmd));
-}
-
-/* Get the descriptor status from hardware */
-void ath11k_hal_tx_status_desc_sync(void *hw_desc, void *local_desc)
-{
- memcpy(local_desc, hw_desc, HAL_TX_STATUS_DESC_LEN);
-}
-
-void ath11k_hal_tx_status_parse(struct ath11k_base *ab,
- struct hal_wbm_release_ring *desc,
- struct hal_tx_status *ts)
-{
- ts->buf_rel_source =
- FIELD_GET(HAL_WBM_RELEASE_INFO0_REL_SRC_MODULE, desc->info0);
- if (ts->buf_rel_source != HAL_WBM_REL_SRC_MODULE_FW &&
- ts->buf_rel_source != HAL_WBM_REL_SRC_MODULE_TQM)
- return;
-
- ts->desc_id = FIELD_GET(BUFFER_ADDR_INFO1_SW_COOKIE,
- desc->buf_addr_info.info1);
-
- if (ts->buf_rel_source == HAL_WBM_REL_SRC_MODULE_FW)
- return;
-
- ts->status = FIELD_GET(HAL_WBM_RELEASE_INFO0_TQM_RELEASE_REASON,
- desc->info0);
- ts->ppdu_id = FIELD_GET(HAL_WBM_RELEASE_INFO1_TQM_STATUS_NUMBER,
- desc->info1);
- ts->try_cnt = FIELD_GET(HAL_WBM_RELEASE_INFO1_TRANSMIT_COUNT,
- desc->info1);
-
- ts->ack_rssi = FIELD_GET(HAL_WBM_RELEASE_INFO2_ACK_FRAME_RSSI,
- desc->info2);
- if (desc->info2 & HAL_WBM_RELEASE_INFO2_FIRST_MSDU)
- ts->flags |= HAL_TX_STATUS_FLAGS_FIRST_MSDU;
-
- if (desc->info2 & HAL_WBM_RELEASE_INFO2_LAST_MSDU)
- ts->flags |= HAL_TX_STATUS_FLAGS_LAST_MSDU;
-
- if (desc->info2 & HAL_WBM_RELEASE_INFO2_MSDU_IN_AMSDU)
- ts->flags |= HAL_TX_STATUS_FLAGS_MSDU_IN_AMSDU;
-
- ts->peer_id = FIELD_GET(HAL_WBM_RELEASE_INFO3_PEER_ID, desc->info3);
- ts->tid = FIELD_GET(HAL_WBM_RELEASE_INFO3_TID, desc->info3);
-
- if (!(desc->rate_stats.info0 & HAL_TX_RATE_STATS_INFO0_VALID))
- return;
-
- ts->flags |= HAL_TX_STATUS_FLAGS_RATE_STATS_VALID;
- ts->tsf = desc->rate_stats.tsf;
- ts->bw = FIELD_GET(HAL_TX_RATE_STATS_INFO0_BW, desc->rate_stats.info0);
- ts->pkt_type = FIELD_GET(HAL_TX_RATE_STATS_INFO0_PKT_TYPE,
- desc->rate_stats.info0);
- if (desc->rate_stats.info0 & HAL_TX_RATE_STATS_INFO0_STBC)
- ts->flags |= HAL_TX_STATUS_FLAGS_RATE_STBC;
- if (desc->rate_stats.info0 & HAL_TX_RATE_STATS_INFO0_LDPC)
- ts->flags |= HAL_TX_STATUS_FLAGS_RATE_LDPC;
- if (desc->rate_stats.info0 & HAL_TX_RATE_STATS_INFO0_OFDMA_TX)
- ts->flags |= HAL_TX_STATUS_FLAGS_OFDMA;
-
- ts->sgi = FIELD_GET(HAL_TX_RATE_STATS_INFO0_SGI,
- desc->rate_stats.info0);
- ts->mcs = FIELD_GET(HAL_TX_RATE_STATS_INFO0_MCS,
- desc->rate_stats.info0);
- ts->num_tones_in_ru = FIELD_GET(HAL_TX_RATE_STATS_INFO0_TONES_IN_RU,
- desc->rate_stats.info0);
+ tcl_cmd->info4 = 0;
}
void ath11k_hal_tx_set_dscp_tid_map(struct ath11k_base *ab, int id)
diff --git a/drivers/net/wireless/ath/ath11k/hal_tx.h b/drivers/net/wireless/ath/ath11k/hal_tx.h
index 5217eaf9da50..ce48a61bfb66 100644
--- a/drivers/net/wireless/ath/ath11k/hal_tx.h
+++ b/drivers/net/wireless/ath/ath11k/hal_tx.h
@@ -48,29 +48,18 @@ struct hal_tx_info {
/* Tx status parsed from srng desc */
struct hal_tx_status {
enum hal_wbm_rel_src_module buf_rel_source;
- u32 desc_id;
enum hal_wbm_tqm_rel_reason status;
u8 ack_rssi;
- enum hal_tx_rate_stats_bw bw;
- enum hal_tx_rate_stats_pkt_type pkt_type;
- enum hal_tx_rate_stats_sgi sgi;
- u8 mcs;
- u16 num_tones_in_ru;
u32 flags; /* %HAL_TX_STATUS_FLAGS_ */
- u32 tsf;
u32 ppdu_id;
u8 try_cnt;
u8 tid;
u16 peer_id;
+ u32 rate_stats;
};
void ath11k_hal_tx_cmd_desc_setup(struct ath11k_base *ab, void *cmd,
struct hal_tx_info *ti);
-void ath11k_hal_tx_desc_sync(void *tx_desc_cached, void *hw_desc);
-void ath11k_hal_tx_status_parse(struct ath11k_base *ab,
- struct hal_wbm_release_ring *desc,
- struct hal_tx_status *ts);
-void ath11k_hal_tx_status_desc_sync(void *hw_desc, void *local_desc);
void ath11k_hal_tx_set_dscp_tid_map(struct ath11k_base *ab, int id);
int ath11k_hal_reo_cmd_send(struct ath11k_base *ab, struct hal_srng *srng,
enum hal_reo_cmd_type type,
diff --git a/drivers/net/wireless/ath/ath11k/htc.c b/drivers/net/wireless/ath/ath11k/htc.c
index 9d4115f25ceb..8f54f58b83e6 100644
--- a/drivers/net/wireless/ath/ath11k/htc.c
+++ b/drivers/net/wireless/ath/ath11k/htc.c
@@ -736,7 +736,7 @@ int ath11k_htc_init(struct ath11k_base *ab)
htc->ab = ab;
- switch (ab->wmi_sc.preferred_hw_mode) {
+ switch (ab->wmi_ab.preferred_hw_mode) {
case WMI_HOST_HW_MODE_SINGLE:
htc->wmi_ep_count = 1;
break;
diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index 978d8768d68a..556eef9881a7 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -1758,6 +1758,20 @@ static void ath11k_mac_op_bss_info_changed(struct ieee80211_hw *hw,
if (ret)
ath11k_warn(ar->ab, "failed to update bcn template: %d\n",
ret);
+
+ if (vif->bss_conf.he_support) {
+ ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
+ WMI_VDEV_PARAM_BA_MODE,
+ WMI_BA_MODE_BUFFER_SIZE_256);
+ if (ret)
+ ath11k_warn(ar->ab,
+ "failed to set BA BUFFER SIZE 256 for vdev: %d\n",
+ arvif->vdev_id);
+ else
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
+ "Set BA BUFFER SIZE 256 for VDEV: %d\n",
+ arvif->vdev_id);
+ }
}
if (changed & (BSS_CHANGED_BEACON_INFO | BSS_CHANGED_BEACON)) {
@@ -1917,9 +1931,9 @@ static void ath11k_mac_op_bss_info_changed(struct ieee80211_hw *hw,
if (changed & BSS_CHANGED_TWT) {
if (info->twt_requester || info->twt_responder)
- ath11k_wmi_send_twt_enable_cmd(ar, ar->pdev_idx);
+ ath11k_wmi_send_twt_enable_cmd(ar, ar->pdev->pdev_id);
else
- ath11k_wmi_send_twt_disable_cmd(ar, ar->pdev_idx);
+ ath11k_wmi_send_twt_disable_cmd(ar, ar->pdev->pdev_id);
}
if (changed & BSS_CHANGED_HE_OBSS_PD)
@@ -3346,6 +3360,77 @@ static void ath11k_gen_ppe_thresh(struct ath11k_ppe_threshold *fw_ppet,
}
}
+static void
+ath11k_mac_filter_he_cap_mesh(struct ieee80211_he_cap_elem *he_cap_elem)
+{
+ u8 m;
+
+ m = IEEE80211_HE_MAC_CAP0_TWT_RES |
+ IEEE80211_HE_MAC_CAP0_TWT_REQ;
+ he_cap_elem->mac_cap_info[0] &= ~m;
+
+ m = IEEE80211_HE_MAC_CAP2_TRS |
+ IEEE80211_HE_MAC_CAP2_BCAST_TWT |
+ IEEE80211_HE_MAC_CAP2_MU_CASCADING;
+ he_cap_elem->mac_cap_info[2] &= ~m;
+
+ m = IEEE80211_HE_MAC_CAP3_FLEX_TWT_SCHED |
+ IEEE80211_HE_MAC_CAP2_BCAST_TWT |
+ IEEE80211_HE_MAC_CAP2_MU_CASCADING;
+ he_cap_elem->mac_cap_info[3] &= ~m;
+
+ m = IEEE80211_HE_MAC_CAP4_BSRP_BQRP_A_MPDU_AGG |
+ IEEE80211_HE_MAC_CAP4_BQR;
+ he_cap_elem->mac_cap_info[4] &= ~m;
+
+ m = IEEE80211_HE_MAC_CAP5_SUBCHAN_SELECVITE_TRANSMISSION |
+ IEEE80211_HE_MAC_CAP5_UL_2x996_TONE_RU |
+ IEEE80211_HE_MAC_CAP5_PUNCTURED_SOUNDING |
+ IEEE80211_HE_MAC_CAP5_HT_VHT_TRIG_FRAME_RX;
+ he_cap_elem->mac_cap_info[5] &= ~m;
+
+ m = IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO |
+ IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO;
+ he_cap_elem->phy_cap_info[2] &= ~m;
+
+ m = IEEE80211_HE_PHY_CAP3_RX_HE_MU_PPDU_FROM_NON_AP_STA |
+ IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_MASK |
+ IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_MASK;
+ he_cap_elem->phy_cap_info[3] &= ~m;
+
+ m = IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER;
+ he_cap_elem->phy_cap_info[4] &= ~m;
+
+ m = IEEE80211_HE_PHY_CAP5_NG16_MU_FEEDBACK;
+ he_cap_elem->phy_cap_info[5] &= ~m;
+
+ m = IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU |
+ IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMER_FB |
+ IEEE80211_HE_PHY_CAP6_TRIG_CQI_FB |
+ IEEE80211_HE_PHY_CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO;
+ he_cap_elem->phy_cap_info[6] &= ~m;
+
+ m = IEEE80211_HE_PHY_CAP7_SRP_BASED_SR |
+ IEEE80211_HE_PHY_CAP7_POWER_BOOST_FACTOR_AR |
+ IEEE80211_HE_PHY_CAP7_STBC_TX_ABOVE_80MHZ |
+ IEEE80211_HE_PHY_CAP7_STBC_RX_ABOVE_80MHZ;
+ he_cap_elem->phy_cap_info[7] &= ~m;
+
+ m = IEEE80211_HE_PHY_CAP8_HE_ER_SU_PPDU_4XLTF_AND_08_US_GI |
+ IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G |
+ IEEE80211_HE_PHY_CAP8_20MHZ_IN_160MHZ_HE_PPDU |
+ IEEE80211_HE_PHY_CAP8_80MHZ_IN_160MHZ_HE_PPDU;
+ he_cap_elem->phy_cap_info[8] &= ~m;
+
+ m = IEEE80211_HE_PHY_CAP9_LONGER_THAN_16_SIGB_OFDM_SYM |
+ IEEE80211_HE_PHY_CAP9_NON_TRIGGERED_CQI_FEEDBACK |
+ IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU |
+ IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU |
+ IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB |
+ IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB;
+ he_cap_elem->phy_cap_info[9] &= ~m;
+}
+
static int ath11k_mac_copy_he_cap(struct ath11k *ar,
struct ath11k_pdev_cap *cap,
struct ieee80211_sband_iftype_data *data,
@@ -3362,6 +3447,7 @@ static int ath11k_mac_copy_he_cap(struct ath11k *ar,
switch (i) {
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_AP:
+ case NL80211_IFTYPE_MESH_POINT:
break;
default:
@@ -3402,6 +3488,9 @@ static int ath11k_mac_copy_he_cap(struct ath11k *ar,
he_cap_elem->phy_cap_info[9] |=
IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU;
break;
+ case NL80211_IFTYPE_MESH_POINT:
+ ath11k_mac_filter_he_cap_mesh(he_cap_elem);
+ break;
}
he_cap->he_mcs_nss_supp.rx_mcs_80 =
@@ -4097,6 +4186,13 @@ static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw,
arvif->vdev_id, ret);
goto err_peer_del;
}
+
+ ret = ath11k_wmi_pdev_set_ps_mode(ar, arvif->vdev_id, false);
+ if (ret) {
+ ath11k_warn(ar->ab, "failed to disable vdev %d ps mode: %d\n",
+ arvif->vdev_id, ret);
+ goto err_peer_del;
+ }
break;
default:
break;
@@ -5238,7 +5334,7 @@ ath11k_mac_update_bss_chan_survey(struct ath11k *ar,
lockdep_assert_held(&ar->conf_mutex);
- if (!test_bit(WMI_TLV_SERVICE_BSS_CHANNEL_INFO_64, ar->ab->wmi_sc.svc_map) ||
+ if (!test_bit(WMI_TLV_SERVICE_BSS_CHANNEL_INFO_64, ar->ab->wmi_ab.svc_map) ||
ar->rx_channel != channel)
return;
@@ -5756,7 +5852,7 @@ int ath11k_mac_allocate(struct ath11k_base *ab)
ar->pdev_idx = i;
ar->lmac_id = ath11k_core_get_hw_mac_id(ab, i);
- ar->wmi = &ab->wmi_sc.wmi[i];
+ ar->wmi = &ab->wmi_ab.wmi[i];
/* FIXME wmi[0] is already initialized during attach,
* Should we do this again?
*/
diff --git a/drivers/net/wireless/ath/ath11k/testmode.c b/drivers/net/wireless/ath/ath11k/testmode.c
index 932bee6d1740..d2dc9db01491 100644
--- a/drivers/net/wireless/ath/ath11k/testmode.c
+++ b/drivers/net/wireless/ath/ath11k/testmode.c
@@ -150,7 +150,7 @@ static int ath11k_tm_cmd_wmi(struct ath11k *ar, struct nlattr *tb[])
ath11k_dbg_dump(ar->ab, ATH11K_DBG_TESTMODE, NULL, "", buf, buf_len);
- skb = ath11k_wmi_alloc_skb(wmi->wmi_sc, buf_len);
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, buf_len);
if (!skb) {
ret = -ENOMEM;
goto out;
diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c
index b05642617b78..a9b301ceb24b 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.c
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
@@ -205,7 +205,7 @@ static int ath11k_wmi_cmd_send_nowait(struct ath11k_pdev_wmi *wmi, struct sk_buf
u32 cmd_id)
{
struct ath11k_skb_cb *skb_cb = ATH11K_SKB_CB(skb);
- struct ath11k_base *ab = wmi->wmi_sc->ab;
+ struct ath11k_base *ab = wmi->wmi_ab->ab;
struct wmi_cmd_hdr *cmd_hdr;
int ret;
u32 cmd = 0;
@@ -234,7 +234,7 @@ err_pull:
int ath11k_wmi_cmd_send(struct ath11k_pdev_wmi *wmi, struct sk_buff *skb,
u32 cmd_id)
{
- struct ath11k_wmi_base *wmi_sc = wmi->wmi_sc;
+ struct ath11k_wmi_base *wmi_sc = wmi->wmi_ab;
int ret = -EOPNOTSUPP;
might_sleep();
@@ -448,7 +448,7 @@ static void ath11k_wmi_service_bitmap_copy(struct ath11k_pdev_wmi *wmi,
for (i = 0, j = 0; i < WMI_SERVICE_BM_SIZE && j < WMI_MAX_SERVICE; i++) {
do {
if (wmi_svc_bm[i] & BIT(j % WMI_SERVICE_BITS_IN_SIZE32))
- set_bit(j, wmi->wmi_sc->svc_map);
+ set_bit(j, wmi->wmi_ab->svc_map);
} while (++j % WMI_SERVICE_BITS_IN_SIZE32);
}
}
@@ -457,7 +457,7 @@ static int ath11k_wmi_tlv_svc_rdy_parse(struct ath11k_base *ab, u16 tag, u16 len
const void *ptr, void *data)
{
struct wmi_tlv_svc_ready_parse *svc_ready = data;
- struct ath11k_pdev_wmi *wmi_handle = &ab->wmi_sc.wmi[0];
+ struct ath11k_pdev_wmi *wmi_handle = &ab->wmi_ab.wmi[0];
u16 expect_len;
switch (tag) {
@@ -538,7 +538,7 @@ int ath11k_wmi_mgmt_send(struct ath11k *ar, u32 vdev_id, u32 buf_id,
len = sizeof(*cmd) + sizeof(*frame_tlv) + roundup(buf_len, 4);
- skb = ath11k_wmi_alloc_skb(wmi->wmi_sc, len);
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len);
if (!skb)
return -ENOMEM;
@@ -590,7 +590,7 @@ int ath11k_wmi_vdev_create(struct ath11k *ar, u8 *macaddr,
len = sizeof(*cmd) + TLV_HDR_SIZE +
(WMI_NUM_SUPPORTED_BAND_MAX * sizeof(*txrx_streams));
- skb = ath11k_wmi_alloc_skb(wmi->wmi_sc, len);
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len);
if (!skb)
return -ENOMEM;
@@ -656,7 +656,7 @@ int ath11k_wmi_vdev_delete(struct ath11k *ar, u8 vdev_id)
struct sk_buff *skb;
int ret;
- skb = ath11k_wmi_alloc_skb(wmi->wmi_sc, sizeof(*cmd));
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));
if (!skb)
return -ENOMEM;
@@ -683,7 +683,7 @@ int ath11k_wmi_vdev_stop(struct ath11k *ar, u8 vdev_id)
struct sk_buff *skb;
int ret;
- skb = ath11k_wmi_alloc_skb(wmi->wmi_sc, sizeof(*cmd));
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));
if (!skb)
return -ENOMEM;
@@ -711,7 +711,7 @@ int ath11k_wmi_vdev_down(struct ath11k *ar, u8 vdev_id)
struct sk_buff *skb;
int ret;
- skb = ath11k_wmi_alloc_skb(wmi->wmi_sc, sizeof(*cmd));
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));
if (!skb)
return -ENOMEM;
@@ -789,7 +789,7 @@ int ath11k_wmi_vdev_start(struct ath11k *ar, struct wmi_vdev_start_req_arg *arg,
len = sizeof(*cmd) + sizeof(*chan) + TLV_HDR_SIZE;
- skb = ath11k_wmi_alloc_skb(wmi->wmi_sc, len);
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len);
if (!skb)
return -ENOMEM;
@@ -867,7 +867,7 @@ int ath11k_wmi_vdev_up(struct ath11k *ar, u32 vdev_id, u32 aid, const u8 *bssid)
struct sk_buff *skb;
int ret;
- skb = ath11k_wmi_alloc_skb(wmi->wmi_sc, sizeof(*cmd));
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));
if (!skb)
return -ENOMEM;
@@ -901,7 +901,7 @@ int ath11k_wmi_send_peer_create_cmd(struct ath11k *ar,
struct sk_buff *skb;
int ret;
- skb = ath11k_wmi_alloc_skb(wmi->wmi_sc, sizeof(*cmd));
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));
if (!skb)
return -ENOMEM;
@@ -934,7 +934,7 @@ int ath11k_wmi_send_peer_delete_cmd(struct ath11k *ar,
struct sk_buff *skb;
int ret;
- skb = ath11k_wmi_alloc_skb(wmi->wmi_sc, sizeof(*cmd));
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));
if (!skb)
return -ENOMEM;
@@ -966,7 +966,7 @@ int ath11k_wmi_send_pdev_set_regdomain(struct ath11k *ar,
struct sk_buff *skb;
int ret;
- skb = ath11k_wmi_alloc_skb(wmi->wmi_sc, sizeof(*cmd));
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));
if (!skb)
return -ENOMEM;
@@ -1006,7 +1006,7 @@ int ath11k_wmi_set_peer_param(struct ath11k *ar, const u8 *peer_addr,
struct sk_buff *skb;
int ret;
- skb = ath11k_wmi_alloc_skb(wmi->wmi_sc, sizeof(*cmd));
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));
if (!skb)
return -ENOMEM;
@@ -1040,7 +1040,7 @@ int ath11k_wmi_send_peer_flush_tids_cmd(struct ath11k *ar,
struct sk_buff *skb;
int ret;
- skb = ath11k_wmi_alloc_skb(wmi->wmi_sc, sizeof(*cmd));
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));
if (!skb)
return -ENOMEM;
@@ -1076,7 +1076,7 @@ int ath11k_wmi_peer_rx_reorder_queue_setup(struct ath11k *ar,
struct sk_buff *skb;
int ret;
- skb = ath11k_wmi_alloc_skb(ar->wmi->wmi_sc, sizeof(*cmd));
+ skb = ath11k_wmi_alloc_skb(ar->wmi->wmi_ab, sizeof(*cmd));
if (!skb)
return -ENOMEM;
@@ -1118,7 +1118,7 @@ ath11k_wmi_rx_reord_queue_remove(struct ath11k *ar,
struct sk_buff *skb;
int ret;
- skb = ath11k_wmi_alloc_skb(wmi->wmi_sc, sizeof(*cmd));
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));
if (!skb)
return -ENOMEM;
@@ -1154,7 +1154,7 @@ int ath11k_wmi_pdev_set_param(struct ath11k *ar, u32 param_id,
struct sk_buff *skb;
int ret;
- skb = ath11k_wmi_alloc_skb(wmi->wmi_sc, sizeof(*cmd));
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));
if (!skb)
return -ENOMEM;
@@ -1178,6 +1178,36 @@ int ath11k_wmi_pdev_set_param(struct ath11k *ar, u32 param_id,
return ret;
}
+int ath11k_wmi_pdev_set_ps_mode(struct ath11k *ar, int vdev_id, u32 enable)
+{
+ struct ath11k_pdev_wmi *wmi = ar->wmi;
+ struct wmi_pdev_set_ps_mode_cmd *cmd;
+ struct sk_buff *skb;
+ int ret;
+
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));
+ if (!skb)
+ return -ENOMEM;
+
+ cmd = (struct wmi_pdev_set_ps_mode_cmd *)skb->data;
+ cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_STA_POWERSAVE_MODE_CMD) |
+ FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE);
+ cmd->vdev_id = vdev_id;
+ cmd->sta_ps_mode = enable;
+
+ ret = ath11k_wmi_cmd_send(wmi, skb, WMI_STA_POWERSAVE_MODE_CMDID);
+ if (ret) {
+ ath11k_warn(ar->ab, "failed to send WMI_PDEV_SET_PARAM cmd\n");
+ dev_kfree_skb(skb);
+ }
+
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "WMI vdev set psmode %d vdev id %d\n",
+ enable, vdev_id);
+
+ return ret;
+}
+
int ath11k_wmi_pdev_suspend(struct ath11k *ar, u32 suspend_opt,
u32 pdev_id)
{
@@ -1186,7 +1216,7 @@ int ath11k_wmi_pdev_suspend(struct ath11k *ar, u32 suspend_opt,
struct sk_buff *skb;
int ret;
- skb = ath11k_wmi_alloc_skb(wmi->wmi_sc, sizeof(*cmd));
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));
if (!skb)
return -ENOMEM;
@@ -1217,7 +1247,7 @@ int ath11k_wmi_pdev_resume(struct ath11k *ar, u32 pdev_id)
struct sk_buff *skb;
int ret;
- skb = ath11k_wmi_alloc_skb(wmi->wmi_sc, sizeof(*cmd));
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));
if (!skb)
return -ENOMEM;
@@ -1251,7 +1281,7 @@ int ath11k_wmi_pdev_bss_chan_info_request(struct ath11k *ar,
struct sk_buff *skb;
int ret;
- skb = ath11k_wmi_alloc_skb(wmi->wmi_sc, sizeof(*cmd));
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));
if (!skb)
return -ENOMEM;
@@ -1284,7 +1314,7 @@ int ath11k_wmi_send_set_ap_ps_param_cmd(struct ath11k *ar, u8 *peer_addr,
struct sk_buff *skb;
int ret;
- skb = ath11k_wmi_alloc_skb(wmi->wmi_sc, sizeof(*cmd));
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));
if (!skb)
return -ENOMEM;
@@ -1319,7 +1349,7 @@ int ath11k_wmi_set_sta_ps_param(struct ath11k *ar, u32 vdev_id,
struct sk_buff *skb;
int ret;
- skb = ath11k_wmi_alloc_skb(wmi->wmi_sc, sizeof(*cmd));
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));
if (!skb)
return -ENOMEM;
@@ -1354,7 +1384,7 @@ int ath11k_wmi_force_fw_hang_cmd(struct ath11k *ar, u32 type, u32 delay_time_ms)
len = sizeof(*cmd);
- skb = ath11k_wmi_alloc_skb(wmi->wmi_sc, len);
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len);
if (!skb)
return -ENOMEM;
@@ -1382,7 +1412,7 @@ int ath11k_wmi_vdev_set_param_cmd(struct ath11k *ar, u32 vdev_id,
struct sk_buff *skb;
int ret;
- skb = ath11k_wmi_alloc_skb(wmi->wmi_sc, sizeof(*cmd));
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));
if (!skb)
return -ENOMEM;
@@ -1416,7 +1446,7 @@ int ath11k_wmi_send_stats_request_cmd(struct ath11k *ar,
struct sk_buff *skb;
int ret;
- skb = ath11k_wmi_alloc_skb(wmi->wmi_sc, sizeof(*cmd));
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));
if (!skb)
return -ENOMEM;
@@ -1449,7 +1479,7 @@ int ath11k_wmi_send_bcn_offload_control_cmd(struct ath11k *ar,
struct sk_buff *skb;
int ret;
- skb = ath11k_wmi_alloc_skb(wmi->wmi_sc, sizeof(*cmd));
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));
if (!skb)
return -ENOMEM;
@@ -1490,7 +1520,7 @@ int ath11k_wmi_bcn_tmpl(struct ath11k *ar, u32 vdev_id,
len = sizeof(*cmd) + sizeof(*bcn_prb_info) + TLV_HDR_SIZE + aligned_len;
- skb = ath11k_wmi_alloc_skb(wmi->wmi_sc, len);
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len);
if (!skb)
return -ENOMEM;
@@ -1541,7 +1571,7 @@ int ath11k_wmi_vdev_install_key(struct ath11k *ar,
len = sizeof(*cmd) + TLV_HDR_SIZE + key_len_aligned;
- skb = ath11k_wmi_alloc_skb(wmi->wmi_sc, len);
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len);
if (!skb)
return -ENOMEM;
@@ -1687,7 +1717,7 @@ int ath11k_wmi_send_peer_assoc_cmd(struct ath11k *ar,
sizeof(*mcs) + TLV_HDR_SIZE +
(sizeof(*he_mcs) * param->peer_he_mcs_count);
- skb = ath11k_wmi_alloc_skb(wmi->wmi_sc, len);
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len);
if (!skb)
return -ENOMEM;
@@ -1953,7 +1983,7 @@ int ath11k_wmi_send_scan_start_cmd(struct ath11k *ar,
roundup(params->extraie.len, sizeof(u32));
len += extraie_len_with_pad;
- skb = ath11k_wmi_alloc_skb(wmi->wmi_sc, len);
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len);
if (!skb)
return -ENOMEM;
@@ -2069,7 +2099,7 @@ int ath11k_wmi_send_scan_stop_cmd(struct ath11k *ar,
struct sk_buff *skb;
int ret;
- skb = ath11k_wmi_alloc_skb(wmi->wmi_sc, sizeof(*cmd));
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));
if (!skb)
return -ENOMEM;
@@ -2125,7 +2155,7 @@ int ath11k_wmi_send_scan_chan_list_cmd(struct ath11k *ar,
len = sizeof(*cmd) + TLV_HDR_SIZE +
sizeof(*chan_info) * chan_list->nallchans;
- skb = ath11k_wmi_alloc_skb(wmi->wmi_sc, len);
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len);
if (!skb)
return -ENOMEM;
@@ -2217,7 +2247,7 @@ int ath11k_wmi_send_wmm_update_cmd_tlv(struct ath11k *ar, u32 vdev_id,
struct sk_buff *skb;
int ret, ac;
- skb = ath11k_wmi_alloc_skb(wmi->wmi_sc, sizeof(*cmd));
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));
if (!skb)
return -ENOMEM;
@@ -2284,7 +2314,7 @@ int ath11k_wmi_send_dfs_phyerr_offload_enable_cmd(struct ath11k *ar,
struct sk_buff *skb;
int ret;
- skb = ath11k_wmi_alloc_skb(wmi->wmi_sc, sizeof(*cmd));
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));
if (!skb)
return -ENOMEM;
@@ -2321,7 +2351,7 @@ int ath11k_wmi_pdev_peer_pktlog_filter(struct ath11k *ar, u8 *addr, u8 enable)
int ret, len;
len = sizeof(*cmd) + sizeof(*info) + TLV_HDR_SIZE;
- skb = ath11k_wmi_alloc_skb(wmi->wmi_sc, len);
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len);
if (!skb)
return -ENOMEM;
@@ -2367,7 +2397,7 @@ ath11k_wmi_send_init_country_cmd(struct ath11k *ar,
struct sk_buff *skb;
int ret;
- skb = ath11k_wmi_alloc_skb(wmi->wmi_sc, sizeof(*cmd));
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));
if (!skb)
return -ENOMEM;
@@ -2419,7 +2449,7 @@ int ath11k_wmi_pdev_pktlog_enable(struct ath11k *ar, u32 pktlog_filter)
struct sk_buff *skb;
int ret;
- skb = ath11k_wmi_alloc_skb(wmi->wmi_sc, sizeof(*cmd));
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));
if (!skb)
return -ENOMEM;
@@ -2449,7 +2479,7 @@ int ath11k_wmi_pdev_pktlog_disable(struct ath11k *ar)
struct sk_buff *skb;
int ret;
- skb = ath11k_wmi_alloc_skb(wmi->wmi_sc, sizeof(*cmd));
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));
if (!skb)
return -ENOMEM;
@@ -2474,18 +2504,18 @@ int
ath11k_wmi_send_twt_enable_cmd(struct ath11k *ar, u32 pdev_id)
{
struct ath11k_pdev_wmi *wmi = ar->wmi;
- struct ath11k_base *ab = wmi->wmi_sc->ab;
+ struct ath11k_base *ab = wmi->wmi_ab->ab;
struct wmi_twt_enable_params_cmd *cmd;
struct sk_buff *skb;
int ret, len;
len = sizeof(*cmd);
- skb = ath11k_wmi_alloc_skb(wmi->wmi_sc, len);
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len);
if (!skb)
return -ENOMEM;
- cmd = (void *)skb->data;
+ cmd = (struct wmi_twt_enable_params_cmd *)skb->data;
cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_TWT_ENABLE_CMD) |
FIELD_PREP(WMI_TLV_LEN, len - TLV_HDR_SIZE);
cmd->pdev_id = pdev_id;
@@ -2525,18 +2555,18 @@ int
ath11k_wmi_send_twt_disable_cmd(struct ath11k *ar, u32 pdev_id)
{
struct ath11k_pdev_wmi *wmi = ar->wmi;
- struct ath11k_base *ab = wmi->wmi_sc->ab;
+ struct ath11k_base *ab = wmi->wmi_ab->ab;
struct wmi_twt_disable_params_cmd *cmd;
struct sk_buff *skb;
int ret, len;
len = sizeof(*cmd);
- skb = ath11k_wmi_alloc_skb(wmi->wmi_sc, len);
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len);
if (!skb)
return -ENOMEM;
- cmd = (void *)skb->data;
+ cmd = (struct wmi_twt_disable_params_cmd *)skb->data;
cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_TWT_DISABLE_CMD) |
FIELD_PREP(WMI_TLV_LEN, len - TLV_HDR_SIZE);
cmd->pdev_id = pdev_id;
@@ -2544,7 +2574,7 @@ ath11k_wmi_send_twt_disable_cmd(struct ath11k *ar, u32 pdev_id)
ret = ath11k_wmi_cmd_send(wmi, skb,
WMI_TWT_DISABLE_CMDID);
if (ret) {
- ath11k_warn(ab, "Failed to send WMI_TWT_DIeABLE_CMDID");
+ ath11k_warn(ab, "Failed to send WMI_TWT_DISABLE_CMDID");
dev_kfree_skb(skb);
}
return ret;
@@ -2555,18 +2585,18 @@ ath11k_wmi_send_obss_spr_cmd(struct ath11k *ar, u32 vdev_id,
struct ieee80211_he_obss_pd *he_obss_pd)
{
struct ath11k_pdev_wmi *wmi = ar->wmi;
- struct ath11k_base *ab = wmi->wmi_sc->ab;
+ struct ath11k_base *ab = wmi->wmi_ab->ab;
struct wmi_obss_spatial_reuse_params_cmd *cmd;
struct sk_buff *skb;
int ret, len;
len = sizeof(*cmd);
- skb = ath11k_wmi_alloc_skb(wmi->wmi_sc, len);
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len);
if (!skb)
return -ENOMEM;
- cmd = (void *)skb->data;
+ cmd = (struct wmi_obss_spatial_reuse_params_cmd *)skb->data;
cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG,
WMI_TAG_OBSS_SPATIAL_REUSE_SET_CMD) |
FIELD_PREP(WMI_TLV_LEN, len - TLV_HDR_SIZE);
@@ -2684,7 +2714,7 @@ ath11k_wmi_copy_resource_config(struct wmi_resource_config *wmi_cfg,
static int ath11k_init_cmd_send(struct ath11k_pdev_wmi *wmi,
struct wmi_init_cmd_param *param)
{
- struct ath11k_base *ab = wmi->wmi_sc->ab;
+ struct ath11k_base *ab = wmi->wmi_ab->ab;
struct sk_buff *skb;
struct wmi_init_cmd *cmd;
struct wmi_resource_config *cfg;
@@ -2704,7 +2734,7 @@ static int ath11k_init_cmd_send(struct ath11k_pdev_wmi *wmi,
len = sizeof(*cmd) + TLV_HDR_SIZE + sizeof(*cfg) + hw_mode_len +
(sizeof(*host_mem_chunks) * WMI_MAX_MEM_REQS);
- skb = ath11k_wmi_alloc_skb(wmi->wmi_sc, len);
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len);
if (!skb)
return -ENOMEM;
@@ -2799,7 +2829,7 @@ int ath11k_wmi_wait_for_service_ready(struct ath11k_base *ab)
{
unsigned long time_left;
- time_left = wait_for_completion_timeout(&ab->wmi_sc.service_ready,
+ time_left = wait_for_completion_timeout(&ab->wmi_ab.service_ready,
WMI_SERVICE_READY_TIMEOUT_HZ);
if (!time_left)
return -ETIMEDOUT;
@@ -2811,7 +2841,7 @@ int ath11k_wmi_wait_for_unified_ready(struct ath11k_base *ab)
{
unsigned long time_left;
- time_left = wait_for_completion_timeout(&ab->wmi_sc.unified_ready,
+ time_left = wait_for_completion_timeout(&ab->wmi_ab.unified_ready,
WMI_SERVICE_READY_TIMEOUT_HZ);
if (!time_left)
return -ETIMEDOUT;
@@ -2821,7 +2851,7 @@ int ath11k_wmi_wait_for_unified_ready(struct ath11k_base *ab)
int ath11k_wmi_cmd_init(struct ath11k_base *ab)
{
- struct ath11k_wmi_base *wmi_sc = &ab->wmi_sc;
+ struct ath11k_wmi_base *wmi_sc = &ab->wmi_ab;
struct wmi_init_cmd_param init_param;
struct target_resource_config config;
@@ -2941,16 +2971,16 @@ static int ath11k_wmi_tlv_hw_mode_caps(struct ath11k_base *soc,
while (i < svc_rdy_ext->n_hw_mode_caps) {
hw_mode_caps = &svc_rdy_ext->hw_mode_caps[i];
mode = hw_mode_caps->hw_mode_id;
- pref = soc->wmi_sc.preferred_hw_mode;
+ pref = soc->wmi_ab.preferred_hw_mode;
if (ath11k_hw_mode_pri_map[mode] < ath11k_hw_mode_pri_map[pref]) {
svc_rdy_ext->pref_hw_mode_caps = *hw_mode_caps;
- soc->wmi_sc.preferred_hw_mode = mode;
+ soc->wmi_ab.preferred_hw_mode = mode;
}
i++;
}
- if (soc->wmi_sc.preferred_hw_mode == WMI_HOST_HW_MODE_MAX)
+ if (soc->wmi_ab.preferred_hw_mode == WMI_HOST_HW_MODE_MAX)
return -EINVAL;
return 0;
@@ -3000,7 +3030,7 @@ static int ath11k_wmi_tlv_ext_hal_reg_caps_parse(struct ath11k_base *soc,
static int ath11k_wmi_tlv_ext_hal_reg_caps(struct ath11k_base *soc,
u16 len, const void *ptr, void *data)
{
- struct ath11k_pdev_wmi *wmi_handle = &soc->wmi_sc.wmi[0];
+ struct ath11k_pdev_wmi *wmi_handle = &soc->wmi_ab.wmi[0];
struct wmi_tlv_svc_rdy_ext_parse *svc_rdy_ext = data;
struct ath11k_hal_reg_capabilities_ext reg_cap;
int ret;
@@ -3036,7 +3066,7 @@ static int ath11k_wmi_tlv_ext_soc_hal_reg_caps_parse(struct ath11k_base *soc,
u16 len, const void *ptr,
void *data)
{
- struct ath11k_pdev_wmi *wmi_handle = &soc->wmi_sc.wmi[0];
+ struct ath11k_pdev_wmi *wmi_handle = &soc->wmi_ab.wmi[0];
struct wmi_tlv_svc_rdy_ext_parse *svc_rdy_ext = data;
u8 hw_mode_id = svc_rdy_ext->pref_hw_mode_caps.hw_mode_id;
u32 phy_id_map;
@@ -3074,7 +3104,7 @@ static int ath11k_wmi_tlv_svc_rdy_ext_parse(struct ath11k_base *ab,
u16 tag, u16 len,
const void *ptr, void *data)
{
- struct ath11k_pdev_wmi *wmi_handle = &ab->wmi_sc.wmi[0];
+ struct ath11k_pdev_wmi *wmi_handle = &ab->wmi_ab.wmi[0];
struct wmi_tlv_svc_rdy_ext_parse *svc_rdy_ext = data;
int ret;
@@ -3126,7 +3156,7 @@ static int ath11k_wmi_tlv_svc_rdy_ext_parse(struct ath11k_base *ab,
return ret;
svc_rdy_ext->ext_hal_reg_done = true;
- complete(&ab->wmi_sc.service_ready);
+ complete(&ab->wmi_ab.service_ready);
}
break;
@@ -4468,7 +4498,7 @@ unlock:
static void ath11k_wmi_op_ep_tx_credits(struct ath11k_base *ab)
{
/* try to send pending beacons first. they take priority */
- wake_up(&ab->wmi_sc.tx_credits_wq);
+ wake_up(&ab->wmi_ab.tx_credits_wq);
}
static void ath11k_wmi_htc_tx_complete(struct ath11k_base *ab,
@@ -4522,7 +4552,7 @@ static int ath11k_reg_chan_list_event(struct ath11k_base *ab, struct sk_buff *sk
if (ab->default_regd[pdev_idx] && !ab->new_regd[pdev_idx] &&
!memcmp((char *)ab->default_regd[pdev_idx]->alpha2,
(char *)reg_info->alpha2, 2))
- return 0;
+ goto mem_free;
/* Intersect new rules with default regd if a new country setting was
* requested, i.e a default regd was already set during initialization
@@ -4638,7 +4668,7 @@ static int ath11k_ready_event(struct ath11k_base *ab, struct sk_buff *skb)
return ret;
}
- complete(&ab->wmi_sc.unified_ready);
+ complete(&ab->wmi_ab.unified_ready);
return 0;
}
@@ -5289,7 +5319,7 @@ static void ath11k_service_available_event(struct ath11k_base *ab, struct sk_buf
do {
if (ev->wmi_service_segment_bitmap[i] &
BIT(j % WMI_AVAIL_SERVICE_BITS_IN_SIZE32))
- set_bit(j, ab->wmi_sc.svc_map);
+ set_bit(j, ab->wmi_ab.svc_map);
} while (++j % WMI_AVAIL_SERVICE_BITS_IN_SIZE32);
}
@@ -5609,9 +5639,9 @@ static int ath11k_connect_pdev_htc_service(struct ath11k_base *ab,
return status;
}
- ab->wmi_sc.wmi_endpoint_id[pdev_idx] = conn_resp.eid;
- ab->wmi_sc.wmi[pdev_idx].eid = conn_resp.eid;
- ab->wmi_sc.max_msg_len[pdev_idx] = conn_resp.max_msg_len;
+ ab->wmi_ab.wmi_endpoint_id[pdev_idx] = conn_resp.eid;
+ ab->wmi_ab.wmi[pdev_idx].eid = conn_resp.eid;
+ ab->wmi_ab.max_msg_len[pdev_idx] = conn_resp.max_msg_len;
return 0;
}
@@ -5634,7 +5664,7 @@ ath11k_wmi_send_unit_test_cmd(struct ath11k *ar,
arg_len = sizeof(u32) * ut_cmd.num_args;
buf_len = sizeof(ut_cmd) + arg_len + TLV_HDR_SIZE;
- skb = ath11k_wmi_alloc_skb(wmi->wmi_sc, buf_len);
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, buf_len);
if (!skb)
return -ENOMEM;
@@ -5741,11 +5771,11 @@ int ath11k_wmi_pdev_attach(struct ath11k_base *ab,
if (pdev_id >= MAX_RADIOS)
return -EINVAL;
- wmi_handle = &ab->wmi_sc.wmi[pdev_id];
+ wmi_handle = &ab->wmi_ab.wmi[pdev_id];
- wmi_handle->wmi_sc = &ab->wmi_sc;
+ wmi_handle->wmi_ab = &ab->wmi_ab;
- ab->wmi_sc.ab = ab;
+ ab->wmi_ab.ab = ab;
/* TODO: Init remaining resource specific to pdev */
return 0;
@@ -5759,12 +5789,12 @@ int ath11k_wmi_attach(struct ath11k_base *ab)
if (ret)
return ret;
- ab->wmi_sc.ab = ab;
- ab->wmi_sc.preferred_hw_mode = WMI_HOST_HW_MODE_MAX;
+ ab->wmi_ab.ab = ab;
+ ab->wmi_ab.preferred_hw_mode = WMI_HOST_HW_MODE_MAX;
/* TODO: Init remaining wmi soc resources required */
- init_completion(&ab->wmi_sc.service_ready);
- init_completion(&ab->wmi_sc.unified_ready);
+ init_completion(&ab->wmi_ab.service_ready);
+ init_completion(&ab->wmi_ab.unified_ready);
return 0;
}
diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h
index 4a518d406bc5..1fde15c762ad 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.h
+++ b/drivers/net/wireless/ath/ath11k/wmi.h
@@ -44,7 +44,7 @@ struct wmi_tlv {
#define WMI_TLV_LEN GENMASK(15, 0)
#define WMI_TLV_TAG GENMASK(31, 16)
-#define TLV_HDR_SIZE FIELD_SIZEOF(struct wmi_tlv, header)
+#define TLV_HDR_SIZE sizeof_field(struct wmi_tlv, header)
#define WMI_CMD_HDR_CMD_ID GENMASK(23, 0)
#define WMI_MAX_MEM_REQS 32
@@ -54,6 +54,7 @@ struct wmi_tlv {
#define WLAN_SCAN_PARAMS_MAX_BSSID 4
#define WLAN_SCAN_PARAMS_MAX_IE_LEN 256
+#define WMI_BA_MODE_BUFFER_SIZE_256 3
/*
* HW mode config type replicated from FW header
* @WMI_HOST_HW_MODE_SINGLE: Only one PHY is active.
@@ -1003,6 +1004,7 @@ enum wmi_tlv_vdev_param {
WMI_VDEV_PARAM_HE_RANGE_EXT,
WMI_VDEV_PARAM_ENABLE_BCAST_PROBE_RESPONSE,
WMI_VDEV_PARAM_FILS_MAX_CHANNEL_GUARD_TIME,
+ WMI_VDEV_PARAM_BA_MODE = 0x7e,
WMI_VDEV_PARAM_SET_HE_SOUNDING_MODE = 0x87,
WMI_VDEV_PARAM_PROTOTYPE = 0x8000,
WMI_VDEV_PARAM_BSS_COLOR,
@@ -2354,7 +2356,7 @@ struct wmi_service_available_event {
} __packed;
struct ath11k_pdev_wmi {
- struct ath11k_wmi_base *wmi_sc;
+ struct ath11k_wmi_base *wmi_ab;
enum ath11k_htc_ep_id eid;
const struct wmi_peer_flags_map *peer_flags;
u32 rx_decap_mode;
@@ -2567,7 +2569,7 @@ static inline const char *ath11k_wmi_phymode_str(enum wmi_phy_mode mode)
/* no default handler to allow compiler to check that the
* enum is fully handled
*/
- };
+ }
return "<unknown>";
}
@@ -2827,6 +2829,12 @@ struct wmi_pdev_set_param_cmd {
u32 param_value;
} __packed;
+struct wmi_pdev_set_ps_mode_cmd {
+ u32 tlv_header;
+ u32 vdev_id;
+ u32 sta_ps_mode;
+} __packed;
+
struct wmi_pdev_suspend_cmd {
u32 tlv_header;
u32 pdev_id;
@@ -2896,15 +2904,6 @@ struct wmi_bcn_offload_ctrl_cmd {
u32 bcn_ctrl_op;
} __packed;
-enum scan_priority {
- SCAN_PRIORITY_VERY_LOW,
- SCAN_PRIORITY_LOW,
- SCAN_PRIORITY_MEDIUM,
- SCAN_PRIORITY_HIGH,
- SCAN_PRIORITY_VERY_HIGH,
- SCAN_PRIORITY_COUNT,
-};
-
enum scan_dwelltime_adaptive_mode {
SCAN_DWELL_MODE_DEFAULT = 0,
SCAN_DWELL_MODE_CONSERVATIVE = 1,
@@ -3056,7 +3055,7 @@ struct scan_req_params {
u32 scan_req_id;
u32 vdev_id;
u32 pdev_id;
- enum scan_priority scan_priority;
+ enum wmi_scan_priority scan_priority;
union {
struct {
u32 scan_ev_started:1,
@@ -4556,12 +4555,12 @@ struct wmi_twt_enable_params_cmd {
u32 mode_check_interval;
u32 add_sta_slot_interval;
u32 remove_sta_slot_interval;
-};
+} __packed;
struct wmi_twt_disable_params_cmd {
u32 tlv_header;
u32 pdev_id;
-};
+} __packed;
struct wmi_obss_spatial_reuse_params_cmd {
u32 tlv_header;
@@ -4570,7 +4569,7 @@ struct wmi_obss_spatial_reuse_params_cmd {
s32 obss_min;
s32 obss_max;
u32 vdev_id;
-};
+} __packed;
struct target_resource_config {
u32 num_vdevs;
@@ -4682,6 +4681,7 @@ int ath11k_wmi_set_peer_param(struct ath11k *ar, const u8 *peer_addr,
u32 vdev_id, u32 param_id, u32 param_val);
int ath11k_wmi_pdev_set_param(struct ath11k *ar, u32 param_id,
u32 param_value, u8 pdev_id);
+int ath11k_wmi_pdev_set_ps_mode(struct ath11k *ar, int vdev_id, u32 enable);
int ath11k_wmi_wait_for_unified_ready(struct ath11k_base *ab);
int ath11k_wmi_cmd_init(struct ath11k_base *ab);
int ath11k_wmi_wait_for_service_ready(struct ath11k_base *ab);
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
index fb649d85b8fc..dd0c32379375 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -1216,7 +1216,7 @@ err_fw:
static int send_eject_command(struct usb_interface *interface)
{
struct usb_device *udev = interface_to_usbdev(interface);
- struct usb_host_interface *iface_desc = &interface->altsetting[0];
+ struct usb_host_interface *iface_desc = interface->cur_altsetting;
struct usb_endpoint_descriptor *endpoint;
unsigned char *cmd;
u8 bulk_out_ep;
diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c
index c30fdd0cbf1e..e49c306e0eef 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -1169,7 +1169,6 @@ static int wcn36xx_init_ieee80211(struct wcn36xx *wcn)
ieee80211_hw_set(wcn->hw, TIMING_BEACON_ONLY);
ieee80211_hw_set(wcn->hw, AMPDU_AGGREGATION);
- ieee80211_hw_set(wcn->hw, CONNECTION_MONITOR);
ieee80211_hw_set(wcn->hw, SUPPORTS_PS);
ieee80211_hw_set(wcn->hw, SIGNAL_DBM);
ieee80211_hw_set(wcn->hw, HAS_RATE_CONTROL);
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c
index 7d6f14420855..0851d2bede89 100644
--- a/drivers/net/wireless/ath/wil6210/cfg80211.c
+++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
@@ -2579,6 +2579,38 @@ wil_cfg80211_update_ft_ies(struct wiphy *wiphy, struct net_device *dev,
return rc;
}
+static int wil_cfg80211_set_multicast_to_unicast(struct wiphy *wiphy,
+ struct net_device *dev,
+ const bool enabled)
+{
+ struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+
+ if (wil->multicast_to_unicast == enabled)
+ return 0;
+
+ wil_info(wil, "set multicast to unicast, enabled=%d\n", enabled);
+ wil->multicast_to_unicast = enabled;
+
+ return 0;
+}
+
+static int wil_cfg80211_set_cqm_rssi_config(struct wiphy *wiphy,
+ struct net_device *dev,
+ s32 rssi_thold, u32 rssi_hyst)
+{
+ struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+ int rc;
+
+ wil->cqm_rssi_thold = rssi_thold;
+
+ rc = wmi_set_cqm_rssi_config(wil, rssi_thold, rssi_hyst);
+ if (rc)
+ /* reset stored value upon failure */
+ wil->cqm_rssi_thold = 0;
+
+ return rc;
+}
+
static const struct cfg80211_ops wil_cfg80211_ops = {
.add_virtual_intf = wil_cfg80211_add_iface,
.del_virtual_intf = wil_cfg80211_del_iface,
@@ -2610,11 +2642,13 @@ static const struct cfg80211_ops wil_cfg80211_ops = {
.start_p2p_device = wil_cfg80211_start_p2p_device,
.stop_p2p_device = wil_cfg80211_stop_p2p_device,
.set_power_mgmt = wil_cfg80211_set_power_mgmt,
+ .set_cqm_rssi_config = wil_cfg80211_set_cqm_rssi_config,
.suspend = wil_cfg80211_suspend,
.resume = wil_cfg80211_resume,
.sched_scan_start = wil_cfg80211_sched_scan_start,
.sched_scan_stop = wil_cfg80211_sched_scan_stop,
.update_ft_ies = wil_cfg80211_update_ft_ies,
+ .set_multicast_to_unicast = wil_cfg80211_set_multicast_to_unicast,
};
static void wil_wiphy_init(struct wiphy *wiphy)
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c
index 06091d8a9e23..6d39547e20fd 100644
--- a/drivers/net/wireless/ath/wil6210/main.c
+++ b/drivers/net/wireless/ath/wil6210/main.c
@@ -1654,6 +1654,8 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
/* Disable device led before reset*/
wmi_led_cfg(wil, false);
+ down_write(&wil->mem_lock);
+
/* prevent NAPI from being scheduled and prevent wmi commands */
mutex_lock(&wil->wmi_mutex);
if (test_bit(wil_status_suspending, wil->status))
@@ -1702,6 +1704,7 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
if (wil->secured_boot) {
wil_err(wil, "secured boot is not supported\n");
+ up_write(&wil->mem_lock);
return -ENOTSUPP;
}
@@ -1737,6 +1740,8 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
clear_bit(wil_status_resetting, wil->status);
+ up_write(&wil->mem_lock);
+
if (load_fw) {
wil_unmask_irq(wil);
@@ -1786,6 +1791,7 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
return rc;
out:
+ up_write(&wil->mem_lock);
clear_bit(wil_status_resetting, wil->status);
return rc;
}
@@ -1811,9 +1817,7 @@ int __wil_up(struct wil6210_priv *wil)
WARN_ON(!mutex_is_locked(&wil->mutex));
- down_write(&wil->mem_lock);
rc = wil_reset(wil, true);
- up_write(&wil->mem_lock);
if (rc)
return rc;
@@ -1905,9 +1909,7 @@ int __wil_down(struct wil6210_priv *wil)
wil_abort_scan_all_vifs(wil, false);
mutex_unlock(&wil->vif_mutex);
- down_write(&wil->mem_lock);
rc = wil_reset(wil, false);
- up_write(&wil->mem_lock);
return rc;
}
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c
index 8ebc6d59aa74..17118d643d7e 100644
--- a/drivers/net/wireless/ath/wil6210/txrx.c
+++ b/drivers/net/wireless/ath/wil6210/txrx.c
@@ -10,6 +10,7 @@
#include <linux/moduleparam.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
+#include <linux/if_vlan.h>
#include <net/ipv6.h>
#include <linux/prefetch.h>
@@ -1529,6 +1530,35 @@ static struct wil_ring *wil_find_tx_bcast_1(struct wil6210_priv *wil,
return v;
}
+/* apply multicast to unicast only for ARP and IP packets
+ * (see NL80211_CMD_SET_MULTICAST_TO_UNICAST for more info)
+ */
+static bool wil_check_multicast_to_unicast(struct wil6210_priv *wil,
+ struct sk_buff *skb)
+{
+ const struct ethhdr *eth = (void *)skb->data;
+ const struct vlan_ethhdr *ethvlan = (void *)skb->data;
+ __be16 ethertype;
+
+ if (!wil->multicast_to_unicast)
+ return false;
+
+ /* multicast to unicast conversion only for some payload */
+ ethertype = eth->h_proto;
+ if (ethertype == htons(ETH_P_8021Q) && skb->len >= VLAN_ETH_HLEN)
+ ethertype = ethvlan->h_vlan_encapsulated_proto;
+ switch (ethertype) {
+ case htons(ETH_P_ARP):
+ case htons(ETH_P_IP):
+ case htons(ETH_P_IPV6):
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+}
+
static void wil_set_da_for_vring(struct wil6210_priv *wil,
struct sk_buff *skb, int vring_index)
{
@@ -2336,7 +2366,7 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev)
/* in STA mode (ESS), all to same VRING (to AP) */
ring = wil_find_tx_ring_sta(wil, vif, skb);
} else if (bcast) {
- if (vif->pbss)
+ if (vif->pbss || wil_check_multicast_to_unicast(wil, skb))
/* in pbss, no bcast VRING - duplicate skb in
* all stations VRINGs
*/
diff --git a/drivers/net/wireless/ath/wil6210/txrx_edma.c b/drivers/net/wireless/ath/wil6210/txrx_edma.c
index 02548d40253c..7bfe867c7509 100644
--- a/drivers/net/wireless/ath/wil6210/txrx_edma.c
+++ b/drivers/net/wireless/ath/wil6210/txrx_edma.c
@@ -903,6 +903,11 @@ again:
if (unlikely(!wil_val_in_range(buff_id, 1, wil->rx_buff_mgmt.size))) {
wil_err(wil, "Corrupt buff_id=%d, sring->swhead=%d\n",
buff_id, sring->swhead);
+ print_hex_dump(KERN_ERR, "RxS ", DUMP_PREFIX_OFFSET, 16, 1,
+ msg, wil->use_compressed_rx_status ?
+ sizeof(struct wil_rx_status_compressed) :
+ sizeof(struct wil_rx_status_extended), false);
+
wil_rx_status_reset_buff_id(sring);
wil_sring_advance_swhead(sring);
sring->invalid_buff_id_cnt++;
@@ -963,6 +968,11 @@ again:
if (unlikely(dmalen > sz)) {
wil_err(wil, "Rx size too large: %d bytes!\n", dmalen);
+ print_hex_dump(KERN_ERR, "RxS ", DUMP_PREFIX_OFFSET, 16, 1,
+ msg, wil->use_compressed_rx_status ?
+ sizeof(struct wil_rx_status_compressed) :
+ sizeof(struct wil_rx_status_extended), false);
+
stats->rx_large_frame++;
rxdata->skipping = true;
}
diff --git a/drivers/net/wireless/ath/wil6210/txrx_edma.h b/drivers/net/wireless/ath/wil6210/txrx_edma.h
index c744c65225da..c736f7413a35 100644
--- a/drivers/net/wireless/ath/wil6210/txrx_edma.h
+++ b/drivers/net/wireless/ath/wil6210/txrx_edma.h
@@ -46,7 +46,7 @@
#define WIL_RX_EDMA_DLPF_LU_MISS_TID_POS 5
-#define WIL_RX_EDMA_MID_VALID_BIT BIT(22)
+#define WIL_RX_EDMA_MID_VALID_BIT BIT(20)
#define WIL_EDMA_DESC_TX_MAC_CFG_0_QID_POS 16
#define WIL_EDMA_DESC_TX_MAC_CFG_0_QID_LEN 6
@@ -244,8 +244,8 @@ struct wil_ring_tx_status {
* calculated, Bit1- L4Err - TCP/UDP Checksum Error
* bit 7 : Reserved:1
* bit 8..19 : Flow ID:12 - MSDU flow ID
- * bit 20..21 : MID:2 - The MAC ID
- * bit 22 : MID_V:1 - The MAC ID field is valid
+ * bit 20 : MID_V:1 - The MAC ID field is valid
+ * bit 21..22 : MID:2 - The MAC ID
* bit 23 : L3T:1 - IP types: 0-IPv6, 1-IPv4
* bit 24 : L4T:1 - Layer 4 Type: 0-UDP, 1-TCP
* bit 25 : BC:1 - The received MPDU is broadcast
@@ -479,7 +479,7 @@ static inline int wil_rx_status_get_mid(void *msg)
return 0; /* use the default MID */
return WIL_GET_BITS(((struct wil_rx_status_compressed *)msg)->d0,
- 20, 21);
+ 21, 22);
}
static inline int wil_rx_status_get_error(void *msg)
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h
index 97626bfd4dac..5dc881d3c057 100644
--- a/drivers/net/wireless/ath/wil6210/wil6210.h
+++ b/drivers/net/wireless/ath/wil6210/wil6210.h
@@ -1059,6 +1059,8 @@ struct wil6210_priv {
u32 max_agg_wsize;
u32 max_ampdu_size;
+ u8 multicast_to_unicast;
+ s32 cqm_rssi_thold;
};
#define wil_to_wiphy(i) (i->wiphy)
@@ -1148,7 +1150,7 @@ static inline void wil_c(struct wil6210_priv *wil, u32 reg, u32 val)
*/
static inline bool wil_cid_valid(struct wil6210_priv *wil, int cid)
{
- return (cid >= 0 && cid < wil->max_assoc_sta);
+ return (cid >= 0 && cid < wil->max_assoc_sta && cid < WIL6210_MAX_CID);
}
void wil_get_board_file(struct wil6210_priv *wil, char *buf, size_t len);
@@ -1440,4 +1442,6 @@ int wmi_addba_rx_resp_edma(struct wil6210_priv *wil, u8 mid, u8 cid,
void update_supported_bands(struct wil6210_priv *wil);
void wil_clear_fw_log_addr(struct wil6210_priv *wil);
+int wmi_set_cqm_rssi_config(struct wil6210_priv *wil,
+ s32 rssi_thold, u32 rssi_hyst);
#endif /* __WIL6210_H__ */
diff --git a/drivers/net/wireless/ath/wil6210/wil_crash_dump.c b/drivers/net/wireless/ath/wil6210/wil_crash_dump.c
index 1332eb8c831f..89c12cb2aaab 100644
--- a/drivers/net/wireless/ath/wil6210/wil_crash_dump.c
+++ b/drivers/net/wireless/ath/wil6210/wil_crash_dump.c
@@ -46,7 +46,7 @@ static int wil_fw_get_crash_dump_bounds(struct wil6210_priv *wil,
int wil_fw_copy_crash_dump(struct wil6210_priv *wil, void *dest, u32 size)
{
- int i, rc;
+ int i;
const struct fw_map *map;
void *data;
u32 host_min, dump_size, offset, len;
@@ -62,9 +62,15 @@ int wil_fw_copy_crash_dump(struct wil6210_priv *wil, void *dest, u32 size)
return -EINVAL;
}
- rc = wil_mem_access_lock(wil);
- if (rc)
- return rc;
+ down_write(&wil->mem_lock);
+
+ if (test_bit(wil_status_suspending, wil->status) ||
+ test_bit(wil_status_suspended, wil->status)) {
+ wil_err(wil,
+ "suspend/resume in progress. cannot copy crash dump\n");
+ up_write(&wil->mem_lock);
+ return -EBUSY;
+ }
/* copy to crash dump area */
for (i = 0; i < ARRAY_SIZE(fw_mapping); i++) {
@@ -84,7 +90,8 @@ int wil_fw_copy_crash_dump(struct wil6210_priv *wil, void *dest, u32 size)
wil_memcpy_fromio_32((void * __force)(dest + offset),
(const void __iomem * __force)data, len);
}
- wil_mem_access_unlock(wil);
+
+ up_write(&wil->mem_lock);
return 0;
}
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c
index 7a0d934eb271..dcba0a4c47b4 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.c
+++ b/drivers/net/wireless/ath/wil6210/wmi.c
@@ -196,8 +196,8 @@ const struct fw_map talyn_mb_fw_mapping[] = {
{0x8c0000, 0x8c0210, 0x8c0000, "dum_user_rgf", true, true},
/* DMA OFU 296b */
{0x8c2000, 0x8c2128, 0x8c2000, "dma_ofu", true, true},
- /* ucode debug 4k */
- {0x8c3000, 0x8c4000, 0x8c3000, "ucode_debug", true, true},
+ /* ucode debug 256b */
+ {0x8c3000, 0x8c3100, 0x8c3000, "ucode_debug", true, true},
/* upper area 1536k */
{0x900000, 0xa80000, 0x900000, "upper", true, true},
/* UCODE areas - accessible by debugfs blobs but not by
@@ -476,6 +476,8 @@ static const char *cmdid2name(u16 cmdid)
return "WMI_RBUFCAP_CFG_CMD";
case WMI_TEMP_SENSE_ALL_CMDID:
return "WMI_TEMP_SENSE_ALL_CMDID";
+ case WMI_SET_LINK_MONITOR_CMDID:
+ return "WMI_SET_LINK_MONITOR_CMD";
default:
return "Untracked CMD";
}
@@ -624,6 +626,10 @@ static const char *eventid2name(u16 eventid)
return "WMI_RBUFCAP_CFG_EVENT";
case WMI_TEMP_SENSE_ALL_DONE_EVENTID:
return "WMI_TEMP_SENSE_ALL_DONE_EVENTID";
+ case WMI_SET_LINK_MONITOR_EVENTID:
+ return "WMI_SET_LINK_MONITOR_EVENT";
+ case WMI_LINK_MONITOR_EVENTID:
+ return "WMI_LINK_MONITOR_EVENT";
default:
return "Untracked EVENT";
}
@@ -1836,6 +1842,32 @@ fail:
wil6210_disconnect(vif, NULL, WLAN_REASON_PREV_AUTH_NOT_VALID);
}
+static void
+wmi_evt_link_monitor(struct wil6210_vif *vif, int id, void *d, int len)
+{
+ struct wil6210_priv *wil = vif_to_wil(vif);
+ struct net_device *ndev = vif_to_ndev(vif);
+ struct wmi_link_monitor_event *evt = d;
+ enum nl80211_cqm_rssi_threshold_event event_type;
+
+ if (len < sizeof(*evt)) {
+ wil_err(wil, "link monitor event too short %d\n", len);
+ return;
+ }
+
+ wil_dbg_wmi(wil, "link monitor event, type %d rssi %d (stored %d)\n",
+ evt->type, evt->rssi_level, wil->cqm_rssi_thold);
+
+ if (evt->type != WMI_LINK_MONITOR_NOTIF_RSSI_THRESHOLD_EVT)
+ /* ignore */
+ return;
+
+ event_type = (evt->rssi_level > wil->cqm_rssi_thold ?
+ NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH :
+ NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW);
+ cfg80211_cqm_rssi_notify(ndev, event_type, evt->rssi_level, GFP_KERNEL);
+}
+
/**
* Some events are ignored for purpose; and need not be interpreted as
* "unhandled events"
@@ -1869,6 +1901,7 @@ static const struct {
{WMI_LINK_STATS_EVENTID, wmi_evt_link_stats},
{WMI_FT_AUTH_STATUS_EVENTID, wmi_evt_auth_status},
{WMI_FT_REASSOC_STATUS_EVENTID, wmi_evt_reassoc_status},
+ {WMI_LINK_MONITOR_EVENTID, wmi_evt_link_monitor},
};
/*
@@ -3981,3 +4014,46 @@ int wmi_link_stats_cfg(struct wil6210_vif *vif, u32 type, u8 cid, u32 interval)
return 0;
}
+
+int wmi_set_cqm_rssi_config(struct wil6210_priv *wil,
+ s32 rssi_thold, u32 rssi_hyst)
+{
+ struct net_device *ndev = wil->main_ndev;
+ struct wil6210_vif *vif = ndev_to_vif(ndev);
+ int rc;
+ struct {
+ struct wmi_set_link_monitor_cmd cmd;
+ s8 rssi_thold;
+ } __packed cmd = {
+ .cmd = {
+ .rssi_hyst = rssi_hyst,
+ .rssi_thresholds_list_size = 1,
+ },
+ .rssi_thold = rssi_thold,
+ };
+ struct {
+ struct wmi_cmd_hdr hdr;
+ struct wmi_set_link_monitor_event evt;
+ } __packed reply = {
+ .evt = {.status = WMI_FW_STATUS_FAILURE},
+ };
+
+ if (rssi_thold > S8_MAX || rssi_thold < S8_MIN || rssi_hyst > U8_MAX)
+ return -EINVAL;
+
+ rc = wmi_call(wil, WMI_SET_LINK_MONITOR_CMDID, vif->mid, &cmd,
+ sizeof(cmd), WMI_SET_LINK_MONITOR_EVENTID,
+ &reply, sizeof(reply), WIL_WMI_CALL_GENERAL_TO_MS);
+ if (rc) {
+ wil_err(wil, "WMI_SET_LINK_MONITOR_CMDID failed, rc %d\n", rc);
+ return rc;
+ }
+
+ if (reply.evt.status != WMI_FW_STATUS_SUCCESS) {
+ wil_err(wil, "WMI_SET_LINK_MONITOR_CMDID failed, status %d\n",
+ reply.evt.status);
+ return -EINVAL;
+ }
+
+ return 0;
+}
diff --git a/drivers/net/wireless/ath/wil6210/wmi.h b/drivers/net/wireless/ath/wil6210/wmi.h
index 6bd4ccee28ab..e3558136e0c4 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.h
+++ b/drivers/net/wireless/ath/wil6210/wmi.h
@@ -192,6 +192,7 @@ enum wmi_command_id {
WMI_RCP_ADDBA_RESP_EDMA_CMDID = 0x83B,
WMI_LINK_MAINTAIN_CFG_WRITE_CMDID = 0x842,
WMI_LINK_MAINTAIN_CFG_READ_CMDID = 0x843,
+ WMI_SET_LINK_MONITOR_CMDID = 0x845,
WMI_SET_SECTORS_CMDID = 0x849,
WMI_MAINTAIN_PAUSE_CMDID = 0x850,
WMI_MAINTAIN_RESUME_CMDID = 0x851,
@@ -1973,6 +1974,7 @@ enum wmi_event_id {
WMI_REPORT_STATISTICS_EVENTID = 0x100B,
WMI_FT_AUTH_STATUS_EVENTID = 0x100C,
WMI_FT_REASSOC_STATUS_EVENTID = 0x100D,
+ WMI_LINK_MONITOR_EVENTID = 0x100E,
WMI_RADAR_GENERAL_CONFIG_EVENTID = 0x1100,
WMI_RADAR_CONFIG_SELECT_EVENTID = 0x1101,
WMI_RADAR_PARAMS_CONFIG_EVENTID = 0x1102,
@@ -2024,6 +2026,7 @@ enum wmi_event_id {
WMI_TX_MGMT_PACKET_EVENTID = 0x1841,
WMI_LINK_MAINTAIN_CFG_WRITE_DONE_EVENTID = 0x1842,
WMI_LINK_MAINTAIN_CFG_READ_DONE_EVENTID = 0x1843,
+ WMI_SET_LINK_MONITOR_EVENTID = 0x1845,
WMI_RF_XPM_READ_RESULT_EVENTID = 0x1856,
WMI_RF_XPM_WRITE_RESULT_EVENTID = 0x1857,
WMI_LED_CFG_DONE_EVENTID = 0x1858,
@@ -3312,6 +3315,36 @@ struct wmi_link_maintain_cfg_read_cmd {
__le32 cid;
} __packed;
+/* WMI_SET_LINK_MONITOR_CMDID */
+struct wmi_set_link_monitor_cmd {
+ u8 rssi_hyst;
+ u8 reserved[12];
+ u8 rssi_thresholds_list_size;
+ s8 rssi_thresholds_list[0];
+} __packed;
+
+/* wmi_link_monitor_event_type */
+enum wmi_link_monitor_event_type {
+ WMI_LINK_MONITOR_NOTIF_RSSI_THRESHOLD_EVT = 0x00,
+ WMI_LINK_MONITOR_NOTIF_TX_ERR_EVT = 0x01,
+ WMI_LINK_MONITOR_NOTIF_THERMAL_EVT = 0x02,
+};
+
+/* WMI_SET_LINK_MONITOR_EVENTID */
+struct wmi_set_link_monitor_event {
+ /* wmi_fw_status */
+ u8 status;
+ u8 reserved[3];
+} __packed;
+
+/* WMI_LINK_MONITOR_EVENTID */
+struct wmi_link_monitor_event {
+ /* link_monitor_event_type */
+ u8 type;
+ s8 rssi_level;
+ u8 reserved[2];
+} __packed;
+
/* WMI_LINK_MAINTAIN_CFG_WRITE_DONE_EVENTID */
struct wmi_link_maintain_cfg_write_done_event {
/* requested connection ID */