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
This commit is contained in:
Kalle Valo 2019-12-19 18:27:36 +02:00
commit ae0a723c4c
30 changed files with 567 additions and 301 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 @@ static void ath11k_dp_tx_complete_msdu(struct ath11k *ar,
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;
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);
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);
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;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 @@ static int ath11k_wmi_cmd_send_nowait(struct ath11k_pdev_wmi *wmi, struct sk_buf
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 @@ void ath11k_wmi_fw_stats_fill(struct ath11k *ar,
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;
}

View File

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

View File

@ -1216,7 +1216,7 @@ static void ath9k_hif_usb_firmware_cb(const struct firmware *fw, void *context)
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;

View File

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

View File

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

View File

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

View File

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

View File

@ -903,6 +903,11 @@ static struct sk_buff *wil_sring_reap_rx_edma(struct wil6210_priv *wil,
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 @@ static struct sk_buff *wil_sring_reap_rx_edma(struct wil6210_priv *wil,
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;
}

View File

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

View File

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

View File

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

View File

@ -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 @@ wmi_evt_reassoc_status(struct wil6210_vif *vif, int id, void *d, int len)
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;
}

View File

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