Commit 8bc513b9 authored by Kalle Valo's avatar Kalle Valo

Merge ath-next from git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git

ath.git patches for v5.7. Major changes:

ath11k

* handle RX fragments

* enable PN offload

* add support for HE BSS color
parents 7f1d4230 95a568c4
......@@ -119,6 +119,7 @@ struct ath10k_skb_cb {
u16 airtime_est;
struct ieee80211_vif *vif;
struct ieee80211_txq *txq;
u32 ucast_cipher;
} __packed;
struct ath10k_skb_rxcb {
......@@ -504,6 +505,7 @@ struct ath10k_sta {
struct work_struct update_wk;
u64 rx_duration;
struct ath10k_htt_tx_stats *tx_stats;
u32 ucast_cipher;
#ifdef CONFIG_MAC80211_DEBUGFS
/* protected by conf_mutex */
......
......@@ -1163,6 +1163,7 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
int len = 0;
int msdu_id = -1;
int res;
const u8 *peer_addr;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data;
len += sizeof(cmd->hdr);
......@@ -1178,7 +1179,16 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
ieee80211_is_deauth(hdr->frame_control) ||
ieee80211_is_disassoc(hdr->frame_control)) &&
ieee80211_has_protected(hdr->frame_control)) {
skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
peer_addr = hdr->addr1;
if (is_multicast_ether_addr(peer_addr)) {
skb_put(msdu, sizeof(struct ieee80211_mmie_16));
} else {
if (skb_cb->ucast_cipher == WLAN_CIPHER_SUITE_GCMP ||
skb_cb->ucast_cipher == WLAN_CIPHER_SUITE_GCMP_256)
skb_put(msdu, IEEE80211_GCMP_MIC_LEN);
else
skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
}
}
txdesc = ath10k_htc_alloc_skb(ar, len);
......
......@@ -258,6 +258,7 @@ static int ath10k_send_key(struct ath10k_vif *arvif,
case WLAN_CIPHER_SUITE_GCMP:
case WLAN_CIPHER_SUITE_GCMP_256:
arg.key_cipher = ar->wmi_key_cipher[WMI_CIPHER_AES_GCM];
key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV_MGMT;
break;
case WLAN_CIPHER_SUITE_BIP_GMAC_128:
case WLAN_CIPHER_SUITE_BIP_GMAC_256:
......@@ -3576,6 +3577,7 @@ static void ath10k_tx_h_add_p2p_noa_ie(struct ath10k *ar,
static void ath10k_mac_tx_h_fill_cb(struct ath10k *ar,
struct ieee80211_vif *vif,
struct ieee80211_txq *txq,
struct ieee80211_sta *sta,
struct sk_buff *skb, u16 airtime)
{
struct ieee80211_hdr *hdr = (void *)skb->data;
......@@ -3583,6 +3585,7 @@ static void ath10k_mac_tx_h_fill_cb(struct ath10k *ar,
const struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
bool is_data = ieee80211_is_data(hdr->frame_control) ||
ieee80211_is_data_qos(hdr->frame_control);
struct ath10k_sta *arsta;
cb->flags = 0;
if (!ath10k_tx_h_use_hwcrypto(vif, skb))
......@@ -3607,6 +3610,12 @@ static void ath10k_mac_tx_h_fill_cb(struct ath10k *ar,
cb->vif = vif;
cb->txq = txq;
cb->airtime_est = airtime;
if (sta) {
arsta = (struct ath10k_sta *)sta->drv_priv;
spin_lock_bh(&ar->data_lock);
cb->ucast_cipher = arsta->ucast_cipher;
spin_unlock_bh(&ar->data_lock);
}
}
bool ath10k_mac_tx_frm_has_freq(struct ath10k *ar)
......@@ -4078,7 +4087,7 @@ int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw,
}
airtime = ath10k_mac_update_airtime(ar, txq, skb);
ath10k_mac_tx_h_fill_cb(ar, vif, txq, skb, airtime);
ath10k_mac_tx_h_fill_cb(ar, vif, txq, sta, skb, airtime);
skb_len = skb->len;
txmode = ath10k_mac_tx_h_get_txmode(ar, vif, sta, skb);
......@@ -4348,7 +4357,7 @@ static void ath10k_mac_op_tx(struct ieee80211_hw *hw,
u16 airtime;
airtime = ath10k_mac_update_airtime(ar, txq, skb);
ath10k_mac_tx_h_fill_cb(ar, vif, txq, skb, airtime);
ath10k_mac_tx_h_fill_cb(ar, vif, txq, sta, skb, airtime);
txmode = ath10k_mac_tx_h_get_txmode(ar, vif, sta, skb);
txpath = ath10k_mac_tx_h_get_txpath(ar, skb, txmode);
......@@ -6197,6 +6206,7 @@ static int ath10k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
{
struct ath10k *ar = hw->priv;
struct ath10k_vif *arvif = (void *)vif->drv_priv;
struct ath10k_sta *arsta;
struct ath10k_peer *peer;
const u8 *peer_addr;
bool is_wep = key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
......@@ -6221,12 +6231,17 @@ static int ath10k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
mutex_lock(&ar->conf_mutex);
if (sta)
if (sta) {
arsta = (struct ath10k_sta *)sta->drv_priv;
peer_addr = sta->addr;
else if (arvif->vdev_type == WMI_VDEV_TYPE_STA)
spin_lock_bh(&ar->data_lock);
arsta->ucast_cipher = key->cipher;
spin_unlock_bh(&ar->data_lock);
} else if (arvif->vdev_type == WMI_VDEV_TYPE_STA) {
peer_addr = vif->bss_conf.bssid;
else
} else {
peer_addr = vif->addr;
}
key->hw_key_idx = key->keyidx;
......
......@@ -1926,6 +1926,7 @@ ath10k_wmi_op_gen_mgmt_tx(struct ath10k *ar, struct sk_buff *msdu)
u32 vdev_id;
u32 buf_len = msdu->len;
u16 fc;
const u8 *peer_addr;
hdr = (struct ieee80211_hdr *)msdu->data;
fc = le16_to_cpu(hdr->frame_control);
......@@ -1946,8 +1947,20 @@ ath10k_wmi_op_gen_mgmt_tx(struct ath10k *ar, struct sk_buff *msdu)
ieee80211_is_deauth(hdr->frame_control) ||
ieee80211_is_disassoc(hdr->frame_control)) &&
ieee80211_has_protected(hdr->frame_control)) {
len += IEEE80211_CCMP_MIC_LEN;
buf_len += IEEE80211_CCMP_MIC_LEN;
peer_addr = hdr->addr1;
if (is_multicast_ether_addr(peer_addr)) {
len += sizeof(struct ieee80211_mmie_16);
buf_len += sizeof(struct ieee80211_mmie_16);
} else {
if (cb->ucast_cipher == WLAN_CIPHER_SUITE_GCMP ||
cb->ucast_cipher == WLAN_CIPHER_SUITE_GCMP_256) {
len += IEEE80211_GCMP_MIC_LEN;
buf_len += IEEE80211_GCMP_MIC_LEN;
} else {
len += IEEE80211_CCMP_MIC_LEN;
buf_len += IEEE80211_CCMP_MIC_LEN;
}
}
}
len = round_up(len, 4);
......
......@@ -3,6 +3,7 @@ config ATH11K
tristate "Qualcomm Technologies 802.11ax chipset support"
depends on MAC80211 && HAS_DMA
depends on REMOTEPROC
depends on CRYPTO_MICHAEL_MIC
depends on ARCH_QCOM || COMPILE_TEST
select ATH_COMMON
select QCOM_QMI_HELPERS
......
......@@ -458,7 +458,6 @@ static void ath11k_ahb_ext_grp_disable(struct ath11k_ext_irq_grp *irq_grp)
static void __ath11k_ahb_ext_irq_disable(struct ath11k_base *ab)
{
struct sk_buff *skb;
int i;
for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
......@@ -468,9 +467,6 @@ static void __ath11k_ahb_ext_irq_disable(struct ath11k_base *ab)
napi_synchronize(&irq_grp->napi);
napi_disable(&irq_grp->napi);
while ((skb = __skb_dequeue(&irq_grp->pending_q)))
dev_kfree_skb_any(skb);
}
}
......@@ -681,6 +677,9 @@ static irqreturn_t ath11k_ahb_ce_interrupt_handler(int irq, void *arg)
{
struct ath11k_ce_pipe *ce_pipe = arg;
/* last interrupt received for this CE */
ce_pipe->timestamp = jiffies;
ath11k_ahb_ce_irq_disable(ce_pipe->ab, ce_pipe->pipe_num);
tasklet_schedule(&ce_pipe->intr_tq);
......@@ -712,6 +711,9 @@ static irqreturn_t ath11k_ahb_ext_interrupt_handler(int irq, void *arg)
{
struct ath11k_ext_irq_grp *irq_grp = arg;
/* last interrupt received for this group */
irq_grp->timestamp = jiffies;
ath11k_ahb_ext_grp_disable(irq_grp);
napi_schedule(&irq_grp->napi);
......@@ -734,7 +736,6 @@ static int ath11k_ahb_ext_irq_config(struct ath11k_base *ab)
init_dummy_netdev(&irq_grp->napi_ndev);
netif_napi_add(&irq_grp->napi_ndev, &irq_grp->napi,
ath11k_ahb_ext_grp_napi_poll, NAPI_POLL_WEIGHT);
__skb_queue_head_init(&irq_grp->pending_q);
for (j = 0; j < ATH11K_EXT_IRQ_NUM_MAX; j++) {
if (ath11k_tx_ring_mask[i] & BIT(j)) {
......
......@@ -161,6 +161,7 @@ struct ath11k_ce_pipe {
struct ath11k_ce_ring *src_ring;
struct ath11k_ce_ring *dest_ring;
struct ath11k_ce_ring *status_ring;
u64 timestamp;
};
struct ath11k_ce {
......
......@@ -77,6 +77,8 @@ struct ath11k_skb_rxcb {
u8 err_code;
u8 mac_id;
u8 unmapped;
u8 is_frag;
u8 tid;
};
enum ath11k_hw_rev {
......@@ -109,12 +111,9 @@ struct ath11k_ext_irq_grp {
u32 irqs[ATH11K_EXT_IRQ_NUM_MAX];
u32 num_irq;
u32 grp_id;
u64 timestamp;
struct napi_struct napi;
struct net_device napi_ndev;
/* Queue of pending packets, not expected to be accessed concurrently
* to avoid locking overhead.
*/
struct sk_buff_head pending_q;
};
#define HEHANDLE_CAP_PHYINFO_SIZE 3
......@@ -332,6 +331,7 @@ struct ath11k_sta {
u32 bw;
u32 nss;
u32 smps;
enum hal_pn_type pn_type;
struct work_struct update_wk;
struct rate_info txrate;
......
......@@ -53,6 +53,8 @@ enum ath11k_dbg_htt_ext_stats_type {
ATH11K_DBG_HTT_EXT_STATS_TWT_SESSIONS = 20,
ATH11K_DBG_HTT_EXT_STATS_REO_RESOURCE_STATS = 21,
ATH11K_DBG_HTT_EXT_STATS_TX_SOUNDING_INFO = 22,
ATH11K_DBG_HTT_EXT_STATS_PDEV_OBSS_PD_STATS = 23,
ATH11K_DBG_HTT_EXT_STATS_RING_BACKPRESSURE_STATS = 24,
/* keep this last */
ATH11K_DBG_HTT_NUM_EXT_STATS,
......
......@@ -3854,6 +3854,47 @@ htt_print_pdev_obss_pd_stats_tlv_v(const void *tag_buf,
stats_req->buf_len = len;
}
static inline void htt_print_backpressure_stats_tlv_v(const u32 *tag_buf,
u8 *data)
{
struct debug_htt_stats_req *stats_req =
(struct debug_htt_stats_req *)data;
struct htt_ring_backpressure_stats_tlv *htt_stats_buf =
(struct htt_ring_backpressure_stats_tlv *)tag_buf;
int i;
u8 *buf = stats_req->buf;
u32 len = stats_req->buf_len;
u32 buf_len = ATH11K_HTT_STATS_BUF_SIZE;
len += HTT_DBG_OUT(buf + len, buf_len - len, "pdev_id = %u",
htt_stats_buf->pdev_id);
len += HTT_DBG_OUT(buf + len, buf_len - len, "current_head_idx = %u",
htt_stats_buf->current_head_idx);
len += HTT_DBG_OUT(buf + len, buf_len - len, "current_tail_idx = %u",
htt_stats_buf->current_tail_idx);
len += HTT_DBG_OUT(buf + len, buf_len - len, "num_htt_msgs_sent = %u",
htt_stats_buf->num_htt_msgs_sent);
len += HTT_DBG_OUT(buf + len, buf_len - len,
"backpressure_time_ms = %u",
htt_stats_buf->backpressure_time_ms);
for (i = 0; i < 5; i++)
len += HTT_DBG_OUT(buf + len, buf_len - len,
"backpressure_hist_%u = %u",
i + 1, htt_stats_buf->backpressure_hist[i]);
len += HTT_DBG_OUT(buf + len, buf_len - len,
"============================");
if (len >= buf_len) {
buf[buf_len - 1] = 0;
stats_req->buf_len = buf_len - 1;
} else {
buf[len] = 0;
stats_req->buf_len = len;
}
}
static inline void htt_htt_stats_debug_dump(const u32 *tag_buf,
struct debug_htt_stats_req *stats_req)
{
......@@ -4246,6 +4287,9 @@ static int ath11k_dbg_htt_ext_stats_parse(struct ath11k_base *ab,
case HTT_STATS_PDEV_OBSS_PD_TAG:
htt_print_pdev_obss_pd_stats_tlv_v(tag_buf, stats_req);
break;
case HTT_STATS_RING_BACKPRESSURE_STATS_TAG:
htt_print_backpressure_stats_tlv_v(tag_buf, user_data);
break;
default:
break;
}
......
......@@ -100,6 +100,8 @@ enum htt_tlv_tag_t {
HTT_STATS_SCHED_TXQ_SCHED_ORDER_SU_TAG = 86,
HTT_STATS_SCHED_TXQ_SCHED_INELIGIBILITY_TAG = 87,
HTT_STATS_PDEV_OBSS_PD_TAG = 88,
HTT_STATS_HW_WAR_TAG = 89,
HTT_STATS_RING_BACKPRESSURE_STATS_TAG = 90,
HTT_STATS_MAX_TAG,
};
......@@ -1659,4 +1661,30 @@ struct htt_pdev_obss_pd_stats_tlv {
};
void ath11k_debug_htt_stats_init(struct ath11k *ar);
struct htt_ring_backpressure_stats_tlv {
u32 pdev_id;
u32 current_head_idx;
u32 current_tail_idx;
u32 num_htt_msgs_sent;
/* Time in milliseconds for which the ring has been in
* its current backpressure condition
*/
u32 backpressure_time_ms;
/* backpressure_hist - histogram showing how many times
* different degrees of backpressure duration occurred:
* Index 0 indicates the number of times ring was
* continuously in backpressure state for 100 - 200ms.
* Index 1 indicates the number of times ring was
* continuously in backpressure state for 200 - 300ms.
* Index 2 indicates the number of times ring was
* continuously in backpressure state for 300 - 400ms.
* Index 3 indicates the number of times ring was
* continuously in backpressure state for 400 - 500ms.
* Index 4 indicates the number of times ring was
* continuously in backpressure state beyond 500ms.
*/
u32 backpressure_hist[5];
};
#endif
......@@ -219,6 +219,9 @@ static ssize_t ath11k_dbg_sta_dump_tx_stats(struct file *file,
const int size = 2 * 4096;
char *buf;
if (!arsta->tx_stats)
return -ENOENT;
buf = kzalloc(size, GFP_KERNEL);
if (!buf)
return -ENOMEM;
......
......@@ -3,6 +3,7 @@
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
*/
#include <crypto/hash.h>
#include "core.h"
#include "dp_tx.h"
#include "hal_tx.h"
......@@ -33,6 +34,7 @@ void ath11k_dp_peer_cleanup(struct ath11k *ar, int vdev_id, const u8 *addr)
}
ath11k_peer_rx_tid_cleanup(ar, peer);
crypto_free_shash(peer->tfm_mmic);
spin_unlock_bh(&ab->base_lock);
}
......@@ -56,8 +58,8 @@ int ath11k_dp_peer_setup(struct ath11k *ar, int vdev_id, const u8 *addr)
}
for (tid = 0; tid <= IEEE80211_NUM_TIDS; tid++) {
ret = ath11k_peer_rx_tid_setup(ar, addr, vdev_id,
tid, 1, 0);
ret = ath11k_peer_rx_tid_setup(ar, addr, vdev_id, tid, 1, 0,
HAL_PN_TYPE_NONE);
if (ret) {
ath11k_warn(ab, "failed to setup rxd tid queue for tid %d: %d\n",
tid, ret);
......@@ -65,6 +67,12 @@ int ath11k_dp_peer_setup(struct ath11k *ar, int vdev_id, const u8 *addr)
}
}
ret = ath11k_peer_rx_frag_setup(ar, addr, vdev_id);
if (ret) {
ath11k_warn(ab, "failed to setup rx defrag context\n");
return ret;
}
/* TODO: Setup other peer specific resource used in data path */
return 0;
......@@ -210,6 +218,7 @@ static int ath11k_dp_srng_common_setup(struct ath11k_base *ab)
struct ath11k_dp *dp = &ab->dp;
struct hal_srng *srng;
int i, ret;
u32 ring_hash_map;
ret = ath11k_dp_srng_setup(ab, &dp->wbm_desc_rel_ring,
HAL_SW2WBM_RELEASE, 0, 0,
......@@ -297,7 +306,21 @@ static int ath11k_dp_srng_common_setup(struct ath11k_base *ab)
goto err;
}
ath11k_hal_reo_hw_setup(ab);
/* When hash based routing of rx packet is enabled, 32 entries to map
* the hash values to the ring will be configured. Each hash entry uses
* three bits to map to a particular ring. The ring mapping will be
* 0:TCL, 1:SW1, 2:SW2, 3:SW3, 4:SW4, 5:Release, 6:FW and 7:Not used.
*/
ring_hash_map = HAL_HASH_ROUTING_RING_SW1 << 0 |
HAL_HASH_ROUTING_RING_SW2 << 3 |
HAL_HASH_ROUTING_RING_SW3 << 6 |
HAL_HASH_ROUTING_RING_SW4 << 9 |
HAL_HASH_ROUTING_RING_SW1 << 12 |
HAL_HASH_ROUTING_RING_SW2 << 15 |
HAL_HASH_ROUTING_RING_SW3 << 18 |
HAL_HASH_ROUTING_RING_SW4 << 21;
ath11k_hal_reo_hw_setup(ab, ring_hash_map);
return 0;
......@@ -627,17 +650,13 @@ int ath11k_dp_service_srng(struct ath11k_base *ab,
}
if (ath11k_rx_ring_mask[grp_id]) {
for (i = 0; i < ab->num_radios; i++) {
if (ath11k_rx_ring_mask[grp_id] & BIT(i)) {
work_done = ath11k_dp_process_rx(ab, i, napi,
&irq_grp->pending_q,
budget);
budget -= work_done;
tot_work_done += work_done;
}
if (budget <= 0)
goto done;
}
i = fls(ath11k_rx_ring_mask[grp_id]) - 1;
work_done = ath11k_dp_process_rx(ab, i, napi,
budget);
budget -= work_done;
tot_work_done += work_done;
if (budget <= 0)
goto done;
}
if (rx_mon_status_ring_mask[grp_id]) {
......
......@@ -22,6 +22,18 @@ struct dp_rx_tid {
u32 size;
u32 ba_win_sz;
bool active;
/* Info related to rx fragments */
u32 cur_sn;
u16 last_frag_no;
u16 rx_frag_bitmap;
struct sk_buff_head rx_frags;
struct hal_reo_dest_ring *dst_ring_desc;
/* Timer info related to fragments */
struct timer_list frag_timer;
struct ath11k_base *ab;
};
#define DP_REO_DESC_FREE_TIMEOUT_MS 1000
......@@ -128,7 +140,6 @@ struct ath11k_pdev_dp {
u32 mac_id;
atomic_t num_tx_pending;
wait_queue_head_t tx_empty_waitq;
struct dp_srng reo_dst_ring;
struct dp_rxdma_ring rx_refill_buf_ring;
struct dp_srng rxdma_err_dst_ring;
struct dp_srng rxdma_mon_dst_ring;
......@@ -148,7 +159,7 @@ struct ath11k_pdev_dp {
#define DP_AVG_MPDUS_PER_TID_MAX 128
#define DP_AVG_MSDUS_PER_MPDU 4
#define DP_RX_HASH_ENABLE 0 /* Disable hash based Rx steering */
#define DP_RX_HASH_ENABLE 1 /* Enable hash based Rx steering */
#define DP_BA_WIN_SZ_MAX 256
......@@ -206,6 +217,7 @@ struct ath11k_dp {
struct dp_srng reo_except_ring;
struct dp_srng reo_cmd_ring;
struct dp_srng reo_status_ring;
struct dp_srng reo_dst_ring[DP_REO_DST_RING_MAX];
struct dp_tx_ring tx_ring[DP_TCL_NUM_RING_MAX];
struct hal_wbm_idle_scatter_list scatter_list[DP_IDLE_SCATTER_BUFS_MAX];
struct list_head reo_cmd_list;
......@@ -924,6 +936,7 @@ enum htt_t2h_msg_type {
HTT_T2H_MSG_TYPE_PEER_UNMAP = 0x1f,
HTT_T2H_MSG_TYPE_PPDU_STATS_IND = 0x1d,
HTT_T2H_MSG_TYPE_EXT_STATS_CONF = 0x1c,
HTT_T2H_MSG_TYPE_BKPRESSURE_EVENT_IND = 0x24,
};
#define HTT_TARGET_VERSION_MAJOR 3
......@@ -972,6 +985,13 @@ struct htt_resp_msg {
};
} __packed;
#define HTT_BACKPRESSURE_EVENT_PDEV_ID_M GENMASK(15, 8)
#define HTT_BACKPRESSURE_EVENT_RING_TYPE_M GENMASK(23, 16)
#define HTT_BACKPRESSURE_EVENT_RING_ID_M GENMASK(31, 24)
#define HTT_BACKPRESSURE_EVENT_HP_M GENMASK(15, 0)
#define HTT_BACKPRESSURE_EVENT_TP_M GENMASK(31, 16)
/* ppdu stats
*
* @details
......
This diff is collapsed.
......@@ -9,6 +9,8 @@
#include "rx_desc.h"
#include "debug.h"
#define DP_MAX_NWIFI_HDR_LEN 30
#define DP_RX_MPDU_ERR_FCS BIT(0)
#define DP_RX_MPDU_ERR_DECRYPT BIT(1)
#define DP_RX_MPDU_ERR_TKIP_MIC BIT(2)
......@@ -43,11 +45,16 @@ int ath11k_dp_rx_ampdu_start(struct ath11k *ar,
struct ieee80211_ampdu_params *params);
int ath11k_dp_rx_ampdu_stop(struct ath11k *ar,
struct ieee80211_ampdu_params *params);
int ath11k_dp_peer_rx_pn_replay_config(struct ath11k_vif *arvif,
const u8 *peer_addr,
enum set_key_cmd key_cmd,
struct ieee80211_key_conf *key);
void ath11k_peer_rx_tid_cleanup(struct ath11k *ar, struct ath11k_peer *peer);
void ath11k_peer_rx_tid_delete(struct ath11k *ar,
struct ath11k_peer *peer, u8 tid);
int ath11k_peer_rx_tid_setup(struct ath11k *ar, const u8 *peer_mac, int vdev_id,
u8 tid, u32 ba_win_sz, u16 ssn);
u8 tid, u32 ba_win_sz, u16 ssn,
enum hal_pn_type pn_type);
void ath11k_dp_htt_htc_t2h_msg_handler(struct ath11k_base *ab,
struct sk_buff *skb);
int ath11k_dp_pdev_reo_setup(struct ath11k_base *ab);
......@@ -62,7 +69,7 @@ int ath11k_dp_rx_process_wbm_err(struct ath11k_base *ab,
int ath11k_dp_process_rx_err(struct ath11k_base *ab, struct napi_struct *napi,
int budget);
int ath11k_dp_process_rx(struct ath11k_base *ab, int mac_id,
struct napi_struct *napi, struct sk_buff_head *pending_q,
struct napi_struct *napi,
int budget);
int ath11k_dp_rxbufs_replenish(struct ath11k_base *ab, int mac_id,
struct dp_rxdma_ring *rx_ring,
......@@ -84,5 +91,6 @@ int ath11k_dp_rx_mon_status_bufs_replenish(struct ath11k_base *ab, int mac_id,
gfp_t gfp);
int ath11k_dp_rx_pdev_mon_detach(struct ath11k *ar);
int ath11k_dp_rx_pdev_mon_attach(struct ath11k *ar);
int ath11k_peer_rx_frag_setup(struct ath11k *ar, const u8 *peer_mac, int vdev_id);
#endif /* ATH11K_DP_RX_H */
......@@ -47,7 +47,7 @@ static u8 ath11k_dp_tx_get_tid(struct sk_buff *skb)
return skb->priority & IEEE80211_QOS_CTL_TID_MASK;
}
static enum hal_encrypt_type ath11k_dp_tx_get_encrypt_type(u32 cipher)
enum hal_encrypt_type ath11k_dp_tx_get_encrypt_type(u32 cipher)
{
switch (cipher) {
case WLAN_CIPHER_SUITE_WEP40:
......
......@@ -877,23 +877,32 @@ void ath11k_hal_srng_access_end(struct ath11k_base *ab, struct hal_srng *srng)
/* For LMAC rings, ring pointer updates are done through FW and
* hence written to a shared memory location that is read by FW
*/
if (srng->ring_dir == HAL_SRNG_DIR_SRC)
if (srng->ring_dir == HAL_SRNG_DIR_SRC) {
srng->u.src_ring.last_tp =
*(volatile u32 *)srng->u.src_ring.tp_addr;
*srng->u.src_ring.hp_addr = srng->u.src_ring.hp;
else
} else {
srng->u.dst_ring.last_hp = *srng->u.dst_ring.hp_addr;
*srng->u.dst_ring.tp_addr = srng->u.dst_ring.tp;
}
} else {
if (srng->ring_dir == HAL_SRNG_DIR_SRC) {
srng->u.src_ring.last_tp =
*(volatile u32 *)srng->u.src_ring.tp_addr;
ath11k_ahb_write32(ab,
(unsigned long)srng->u.src_ring.hp_addr -
(unsigned long)ab->mem,
srng->u.src_ring.hp);
} else {
srng->u.dst_ring.last_hp = *srng->u.dst_ring.hp_addr;
ath11k_ahb_write32(ab,
(unsigned long)srng->u.dst_ring.tp_addr -
(unsigned long)ab->mem,
srng->u.dst_ring.tp);
}
}
srng->timestamp = jiffies;
}
void ath11k_hal_setup_link_idle_list(struct ath11k_base *ab,
......@@ -1017,6 +1026,7 @@ int ath11k_hal_srng_setup(struct ath11k_base *ab, enum hal_ring_type type,
params->intr_batch_cntr_thres_entries;
srng->intr_timer_thres_us = params->intr_timer_thres_us;
srng->flags = params->flags;
srng->initialized = 1;
spin_lock_init(&srng->lock);
for (i = 0; i < HAL_SRNG_NUM_REG_GRP; i++) {
......@@ -1122,3 +1132,55 @@ void ath11k_hal_srng_deinit(struct ath11k_base *ab)
ath11k_hal_free_cont_rdp(ab);
ath11k_hal_free_cont_wrp(ab);
}
void ath11k_hal_dump_srng_stats(struct ath11k_base *ab)
{
struct hal_srng *srng;
struct ath11k_ext_irq_grp *irq_grp;
struct ath11k_ce_pipe *ce_pipe;
int i;
ath11k_err(ab, "Last interrupt received for each CE:\n");
for (i = 0; i < CE_COUNT; i++) {
ce_pipe = &ab->ce.ce_pipe[i];
if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR)
continue;
ath11k_err(ab, "CE_id %d pipe_num %d %ums before\n",
i, ce_pipe->pipe_num,
jiffies_to_msecs(jiffies - ce_pipe->timestamp));
}
ath11k_err(ab, "\nLast interrupt received for each group:\n");
for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
irq_grp = &ab->ext_irq_grp[i];
ath11k_err(ab, "group_id %d %ums before\n",
irq_grp->grp_id,
jiffies_to_msecs(jiffies - irq_grp->timestamp));
}
for (i = 0; i < HAL_SRNG_RING_ID_MAX; i++) {
srng = &ab->hal.srng_list[i];
if (!srng->initialized)
continue;
if (srng->ring_dir == HAL_SRNG_DIR_SRC)
ath11k_err(ab,
"src srng id %u hp %u, reap_hp %u, cur tp %u, cached tp %u last tp %u napi processed before %ums\n",
srng->ring_id, srng->u.src_ring.hp,
srng->u.src_ring.reap_hp,
*srng->u.src_ring.tp_addr, srng->u.src_ring.cached_tp,
srng->u.src_ring.last_tp,
jiffies_to_msecs(jiffies - srng->timestamp));
else if (srng->ring_dir == HAL_SRNG_DIR_DST)
ath11k_err(ab,
"dst srng id %u tp %u, cur hp %u, cached hp %u last hp %u napi processed before %ums\n",
srng->ring_id, srng->u.dst_ring.tp,
*srng->u.dst_ring.hp_addr,
srng->u.dst_ring.cached_hp,
srng->u.dst_ring.last_hp,
jiffies_to_msecs(jiffies - srng->timestamp));
}
}
......@@ -96,6 +96,8 @@ struct ath11k_base;
/* REO2SW(x) R0 ring configuration address */
#define HAL_REO1_GEN_ENABLE 0x00000000
#define HAL_REO1_DEST_RING_CTRL_IX_0 0x00000004
#define HAL_REO1_DEST_RING_CTRL_IX_1 0x00000008
#define HAL_REO1_DEST_RING_CTRL_IX_2 0x0000000c
#define HAL_REO1_DEST_RING_CTRL_IX_3 0x00000010
#define HAL_REO1_RING_BASE_LSB 0x0000029c
......@@ -529,6 +531,8 @@ struct hal_srng {
*/
u32 hwreg_base[HAL_SRNG_NUM_REG_GRP];
u64 timestamp;
/* Source or Destination ring */
enum hal_srng_dir ring_dir;
......@@ -554,6 +558,9 @@ struct hal_srng {
/* max transfer size */
u16 max_buffer_length;
/* head pointer at access end */
u32 last_hp;
} dst_ring;
struct {
......@@ -577,6 +584,9 @@ struct hal_srng {
/* Low threshold - in number of ring entries */
u32 low_threshold;
/* tail pointer at access end */
u32 last_tp;
} src_ring;
} u;
};
......@@ -717,6 +727,14 @@ enum hal_ce_desc {
HAL_CE_DESC_DST_STATUS,
};
#define HAL_HASH_ROUTING_RING_TCL 0
#define HAL_HASH_ROUTING_RING_SW1 1
#define HAL_HASH_ROUTING_RING_SW2 2
#define HAL_HASH_ROUTING_RING_SW3 3
#define HAL_HASH_ROUTING_RING_SW4 4
#define HAL_HASH_ROUTING_RING_REL 5
#define HAL_HASH_ROUTING_RING_FW 6
struct hal_reo_status_header {
u16 cmd_num;
enum hal_reo_cmd_status cmd_status;
......@@ -847,10 +865,10 @@ struct ath11k_hal {
u32 ath11k_hal_reo_qdesc_size(u32 ba_window_size, u8 tid);
void ath11k_hal_reo_qdesc_setup(void *vaddr, int tid, u32 ba_window_size,
u32 start_seqtype);
u32 start_seq, enum hal_pn_type type);
void ath11k_hal_reo_init_cmd_ring(struct ath11k_base *ab,
struct hal_srng *srng);
void ath11k_hal_reo_hw_setup(struct ath11k_base *ab);
void ath11k_hal_reo_hw_setup(struct ath11k_base *ab, u32 ring_hash_map);
void ath11k_hal_setup_link_idle_list(struct ath11k_base *ab,
struct hal_wbm_idle_scatter_list *sbuf,
u32 nsbufs, u32 tot_link_desc,
......@@ -893,5 +911,6 @@ int ath11k_hal_srng_setup(struct ath11k_base *ab, enum hal_ring_type type,
struct hal_srng_params *params);
int ath11k_hal_srng_init(struct ath11k_base *ath11k);
void ath11k_hal_srng_deinit(struct ath11k_base *ath11k);
void ath11k_hal_dump_srng_stats(struct ath11k_base *ab);
#endif
......@@ -694,7 +694,7 @@ u32 ath11k_hal_reo_qdesc_size(u32 ba_window_size, u8 tid)
}
void ath11k_hal_reo_qdesc_setup(void *vaddr, int tid, u32 ba_window_size,
u32 start_seq)
u32 start_seq, enum hal_pn_type type)
{
struct hal_rx_reo_queue *qdesc = (struct hal_rx_reo_queue *)vaddr;
struct hal_rx_reo_queue_ext *ext_desc;
......@@ -723,6 +723,18 @@ void ath11k_hal_reo_qdesc_setup(void *vaddr, int tid, u32 ba_window_size,
qdesc->info0 |= FIELD_PREP(HAL_RX_REO_QUEUE_INFO0_BA_WINDOW_SIZE,
ba_window_size - 1);
switch (type) {
case HAL_PN_TYPE_NONE:
case HAL_PN_TYPE_WAPI_EVEN:
case HAL_PN_TYPE_WAPI_UNEVEN:
break;
case HAL_PN_TYPE_WPA:
qdesc->info0 |=
FIELD_PREP(HAL_RX_REO_QUEUE_INFO0_PN_CHECK, 1) |
FIELD_PREP(HAL_RX_REO_QUEUE_INFO0_PN_SIZE,
HAL_RX_REO_QUEUE_PN_SIZE_48);
break;
}
/* TODO: Set Ignore ampdu flags based on BA window size and/or
* AMPDU capabilities
......@@ -787,7 +799,7 @@ void ath11k_hal_reo_init_cmd_ring(struct ath11k_base *ab,
}
}
void ath11k_hal_reo_hw_setup(struct ath11k_base *ab)
void ath11k_hal_reo_hw_setup(struct ath11k_base *ab, u32 ring_hash_map)
{
u32 reo_base = HAL_SEQ_WCSS_UMAC_REO_REG;
u32 val;
......@@ -809,6 +821,19 @@ void ath11k_hal_reo_hw_setup(struct ath11k_base *ab)
HAL_DEFAULT_REO_TIMEOUT_USEC);
ath11k_ahb_write32(ab, reo_base + HAL_REO1_AGING_THRESH_IX_3,
HAL_DEFAULT_REO_TIMEOUT_USEC);
ath11k_ahb_write32(ab, reo_base + HAL_REO1_DEST_RING_CTRL_IX_0,
FIELD_PREP(HAL_REO_DEST_RING_CTRL_HASH_RING_MAP,
ring_hash_map));
ath11k_ahb_write32(ab, reo_base + HAL_REO1_DEST_RING_CTRL_IX_1,
FIELD_PREP(HAL_REO_DEST_RING_CTRL_HASH_RING_MAP,
ring_hash_map));
ath11k_ahb_write32(ab, reo_base + HAL_REO1_DEST_RING_CTRL_IX_2,
FIELD_PREP(HAL_REO_DEST_RING_CTRL_HASH_RING_MAP,
ring_hash_map));
ath11k_ahb_write32(ab, reo_base + HAL_REO1_DEST_RING_CTRL_IX_3,
FIELD_PREP(HAL_REO_DEST_RING_CTRL_HASH_RING_MAP,
ring_hash_map));
}
static enum hal_rx_mon_status
......
......@@ -62,6 +62,7 @@
#define TARGET_RX_BATCHMODE 1
#define ATH11K_HW_MAX_QUEUES 4
#define ATH11K_QUEUE_LEN 4096
#define ATH11k_HW_RATECODE_CCK_SHORT_PREAM_MASK 0x4
......
......@@ -1956,6 +1956,31 @@ static void ath11k_mac_op_bss_info_changed(struct ieee80211_hw *hw,
ath11k_wmi_send_obss_spr_cmd(ar, arvif->vdev_id,
&info->he_obss_pd);
if (changed & BSS_CHANGED_HE_BSS_COLOR) {
if (vif->type == NL80211_IFTYPE_AP) {
ret = ath11k_wmi_send_obss_color_collision_cfg_cmd(
ar, arvif->vdev_id, info->he_bss_color.color,
ATH11K_BSS_COLOR_COLLISION_DETECTION_AP_PERIOD_MS,
!info->he_bss_color.disabled);
if (ret)
ath11k_warn(ar->ab, "failed to set bss color collision on vdev %i: %d\n",
arvif->vdev_id, ret);
} else if (vif->type == NL80211_IFTYPE_STATION) {
ret = ath11k_wmi_send_bss_color_change_enable_cmd(ar,
arvif->vdev_id,
1);
if (ret)
ath11k_warn(ar->ab, "failed to enable bss color change on vdev %i: %d\n",
arvif->vdev_id, ret);
ret = ath11k_wmi_send_obss_color_collision_cfg_cmd(
ar, arvif->vdev_id, 0,
ATH11K_BSS_COLOR_COLLISION_DETECTION_STA_PERIOD_MS, 1);
if (ret)
ath11k_warn(ar->ab, "failed to set bss color collision on vdev %i: %d\n",
arvif->vdev_id, ret);
}
}
mutex_unlock(&ar->conf_mutex);
}
......@@ -2325,6 +2350,7 @@ static int ath11k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
struct ath11k_base *ab = ar->ab;
struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
struct ath11k_peer *peer;
struct ath11k_sta *arsta;
const u8 *peer_addr;
int ret = 0;
u32 flags = 0;
......@@ -2382,15 +2408,53 @@ static int ath11k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
goto exit;
}
ret = ath11k_dp_peer_rx_pn_replay_config(arvif, peer_addr, cmd, key);
if (ret) {
ath11k_warn(ab, "failed to offload PN replay detection %d\n", ret);
goto exit;
}
spin_lock_bh(&ab->base_lock);
peer = ath11k_peer_find(ab, arvif->vdev_id, peer_addr);
if (peer && cmd == SET_KEY)
if (peer && cmd == SET_KEY) {
peer->keys[key->keyidx] = key;
else if (peer && cmd == DISABLE_KEY)
if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) {
peer->ucast_keyidx = key->keyidx;
peer->sec_type = ath11k_dp_tx_get_encrypt_type(key->cipher);
} else {
peer->mcast_keyidx = key->keyidx;
peer->sec_type_grp = ath11k_dp_tx_get_encrypt_type(key->cipher);
}
} else if (peer && cmd == DISABLE_KEY) {
peer->keys[key->keyidx] = NULL;
else if (!peer)
if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
peer->ucast_keyidx = 0;
else
peer->mcast_keyidx = 0;
} else if (!peer)
/* impossible unless FW goes crazy */
ath11k_warn(ab, "peer %pM disappeared!\n", peer_addr);
if (sta) {
arsta = (struct ath11k_sta *)sta->drv_priv;
switch (key->cipher) {
case WLAN_CIPHER_SUITE_TKIP:
case WLAN_CIPHER_SUITE_CCMP:
case WLAN_CIPHER_SUITE_CCMP_256:
case WLAN_CIPHER_SUITE_GCMP:
case WLAN_CIPHER_SUITE_GCMP_256:
if (cmd == SET_KEY)
arsta->pn_type = HAL_PN_TYPE_WPA;
else
arsta->pn_type = HAL_PN_TYPE_NONE;
break;
default:
arsta->pn_type = HAL_PN_TYPE_NONE;
break;
}
}
spin_unlock_bh(&ab->base_lock);
exit:
......@@ -3914,6 +3978,9 @@ static int ath11k_mac_op_start(struct ieee80211_hw *hw)
goto err;
}
/* Configure the hash seed for hash based reo dest ring selection */
ath11k_wmi_pdev_lro_cfg(ar, ar->pdev->pdev_id);
mutex_unlock(&ar->conf_mutex);
rcu_assign_pointer(ab->pdevs_active[ar->pdev_idx],
......@@ -5731,6 +5798,7 @@ static int __ath11k_mac_register(struct ath11k *ar)
ieee80211_hw_set(ar->hw, TX_AMPDU_SETUP_IN_HW);
ieee80211_hw_set(ar->hw, SUPPORTS_REORDERING_BUFFER);
ieee80211_hw_set(ar->hw, SUPPORTS_AMSDU_IN_AMPDU);
ieee80211_hw_set(ar->hw, USES_RSS);
}
ar->hw->wiphy->features |= NL80211_FEATURE_STATIC_SMPS;
......@@ -5762,6 +5830,7 @@ static int __ath11k_mac_register(struct ath11k *ar)
ar->hw->wiphy->max_ap_assoc_sta = ar->max_num_stations;
ar->hw->queues = ATH11K_HW_MAX_QUEUES;
ar->hw->wiphy->tx_queue_len = ATH11K_QUEUE_LEN;
ar->hw->offchannel_tx_hw_queue = ATH11K_HW_MAX_QUEUES - 1;
ar->hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF;
......
......@@ -145,4 +145,5 @@ void ath11k_mac_peer_cleanup_all(struct ath11k *ar);
int ath11k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx);
u8 ath11k_mac_bw_to_mac80211_bw(u8 bw);
enum ath11k_supported_bw ath11k_mac_mac80211_bw_to_ath11k_bw(enum rate_info_bw bw);
enum hal_encrypt_type ath11k_dp_tx_get_encrypt_type(u32 cipher);
#endif
......@@ -228,6 +228,9 @@ int ath11k_peer_create(struct ath11k *ar, struct ath11k_vif *arvif,
peer->sta = sta;
arvif->ast_hash = peer->ast_hash;
peer->sec_type = HAL_ENCRYPT_TYPE_OPEN;
peer->sec_type_grp = HAL_ENCRYPT_TYPE_OPEN;
ar->num_peers++;
spin_unlock_bh(&ar->ab->base_lock);
......
......@@ -17,6 +17,15 @@ struct ath11k_peer {
/* protected by ab->data_lock */
struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1];
struct dp_rx_tid rx_tid[IEEE80211_NUM_TIDS + 1];
/* Info used in MMIC verification of
* RX fragments
*/
struct crypto_shash *tfm_mmic;
u8 mcast_keyidx;
u8 ucast_keyidx;
u16 sec_type;
u16 sec_type_grp;
};
void ath11k_peer_unmap_event(struct ath11k_base *ab, u16 peer_id);
......
......@@ -2365,6 +2365,7 @@ static void ath11k_qmi_driver_event_work(struct work_struct *work)
break;
case ATH11K_QMI_EVENT_FW_READY:
if (test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags)) {
ath11k_hal_dump_srng_stats(ab);
queue_work(ab->workqueue, &ab->restart_work);
break;
}
......
......@@ -342,7 +342,7 @@ struct rx_attention {
#define RX_MPDU_START_INFO0_PROTO_VER_ERR BIT(12)
#define RX_MPDU_START_INFO0_AST_LOOKUP_VALID BIT(13)
#define RX_MPDU_START_INFO1_MPDU_CTRL_VALID BIT(0)
#define RX_MPDU_START_INFO1_MPDU_FCTRL_VALID BIT(0)
#define RX_MPDU_START_INFO1_MPDU_DUR_VALID BIT(1)
#define RX_MPDU_START_INFO1_MAC_ADDR1_VALID BIT(2)
#define RX_MPDU_START_INFO1_MAC_ADDR2_VALID BIT(3)
......
......@@ -2707,6 +2707,84 @@ ath11k_wmi_send_obss_spr_cmd(struct ath11k *ar, u32 vdev_id,
return ret;
}
int
ath11k_wmi_send_obss_color_collision_cfg_cmd(struct ath11k *ar, u32 vdev_id,
u8 bss_color, u32 period,
bool enable)
{
struct ath11k_pdev_wmi *wmi = ar->wmi;
struct ath11k_base *ab = wmi->wmi_ab->ab;
struct wmi_obss_color_collision_cfg_params_cmd *cmd;
struct sk_buff *skb;
int ret, len;
len = sizeof(*cmd);
skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len);
if (!skb)
return -ENOMEM;
cmd = (struct wmi_obss_color_collision_cfg_params_cmd *)skb->data;
cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG,
WMI_TAG_OBSS_COLOR_COLLISION_DET_CONFIG) |
FIELD_PREP(WMI_TLV_LEN, len - TLV_HDR_SIZE);
cmd->vdev_id = vdev_id;
cmd->evt_type = enable ? ATH11K_OBSS_COLOR_COLLISION_DETECTION :
ATH11K_OBSS_COLOR_COLLISION_DETECTION_DISABLE;
cmd->current_bss_color = bss_color;
cmd->detection_period_ms = period;
cmd->scan_period_ms = ATH11K_BSS_COLOR_COLLISION_SCAN_PERIOD_MS;
cmd->free_slot_expiry_time_ms = 0;
cmd->flags = 0;
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
"wmi_send_obss_color_collision_cfg id %d type %d bss_color %d detect_period %d scan_period %d\n",
cmd->vdev_id, cmd->evt_type, cmd->current_bss_color,
cmd->detection_period_ms, cmd->scan_period_ms);
ret = ath11k_wmi_cmd_send(wmi, skb,
WMI_OBSS_COLOR_COLLISION_DET_CONFIG_CMDID);
if (ret) {
ath11k_warn(ab, "Failed to send WMI_OBSS_COLOR_COLLISION_DET_CONFIG_CMDID");
dev_kfree_skb(skb);
}
return ret;
}
int ath11k_wmi_send_bss_color_change_enable_cmd(struct ath11k *ar, u32 vdev_id,
bool enable)
{
struct ath11k_pdev_wmi *wmi = ar->wmi;
struct ath11k_base *ab = wmi->wmi_ab->ab;
struct wmi_bss_color_change_enable_params_cmd *cmd;
struct sk_buff *skb;
int ret, len;
len = sizeof(*cmd);
skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len);
if (!skb)
return -ENOMEM;
cmd = (struct wmi_bss_color_change_enable_params_cmd *)skb->data;
cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_BSS_COLOR_CHANGE_ENABLE) |
FIELD_PREP(WMI_TLV_LEN, len - TLV_HDR_SIZE);
cmd->vdev_id = vdev_id;
cmd->enable = enable ? 1 : 0;
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
"wmi_send_bss_color_change_enable id %d enable %d\n",
cmd->vdev_id, cmd->enable);
ret = ath11k_wmi_cmd_send(wmi, skb,
WMI_BSS_COLOR_CHANGE_ENABLE_CMDID);
if (ret) {
ath11k_warn(ab, "Failed to send WMI_TWT_DIeABLE_CMDID");
dev_kfree_skb(skb);
}
return ret;
}
static void
ath11k_fill_band_to_mac_param(struct ath11k_base *soc,
struct wmi_host_pdev_band_to_mac *band_to_mac)
......@@ -2917,6 +2995,41 @@ static int ath11k_init_cmd_send(struct ath11k_pdev_wmi *wmi,
return ret;
}
int ath11k_wmi_pdev_lro_cfg(struct ath11k *ar,
int pdev_id)
{
struct ath11k_wmi_pdev_lro_config_cmd *cmd;
struct sk_buff *skb;
int ret;
skb = ath11k_wmi_alloc_skb(ar->wmi->wmi_ab, sizeof(*cmd));
if (!skb)
return -ENOMEM;
cmd = (struct ath11k_wmi_pdev_lro_config_cmd *)skb->data;
cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_LRO_INFO_CMD) |
FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE);
get_random_bytes(cmd->th_4, sizeof(uint32_t) * ATH11K_IPV4_TH_SEED_SIZE);
get_random_bytes(cmd->th_6, sizeof(uint32_t) * ATH11K_IPV6_TH_SEED_SIZE);
cmd->pdev_id = pdev_id;
ret = ath11k_wmi_cmd_send(ar->wmi, skb, WMI_LRO_CONFIG_CMDID);
if (ret) {
ath11k_warn(ar->ab,
"failed to send lro cfg req wmi cmd\n");
goto err;
}
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
"WMI lro cfg cmd pdev_id 0x%x\n", pdev_id);
return 0;
err:
dev_kfree_skb(skb);
return ret;
}
int ath11k_wmi_wait_for_service_ready(struct ath11k_base *ab)
{
unsigned long time_left;
......
......@@ -488,6 +488,7 @@ enum wmi_tlv_cmd_id {
WMI_SAR_LIMITS_CMDID,
WMI_OBSS_SCAN_ENABLE_CMDID = WMI_TLV_CMD(WMI_GRP_OBSS_OFL),
WMI_OBSS_SCAN_DISABLE_CMDID,
WMI_OBSS_COLOR_COLLISION_DET_CONFIG_CMDID,
WMI_LPI_MGMT_SNOOPING_CONFIG_CMDID = WMI_TLV_CMD(WMI_GRP_LPI),
WMI_LPI_START_SCAN_CMDID,
WMI_LPI_STOP_SCAN_CMDID,
......@@ -4620,6 +4621,42 @@ struct wmi_obss_spatial_reuse_params_cmd {
u32 vdev_id;
} __packed;
#define ATH11K_BSS_COLOR_COLLISION_SCAN_PERIOD_MS 200
#define ATH11K_OBSS_COLOR_COLLISION_DETECTION_DISABLE 0
#define ATH11K_OBSS_COLOR_COLLISION_DETECTION 1
#define ATH11K_BSS_COLOR_COLLISION_DETECTION_STA_PERIOD_MS 10000
#define ATH11K_BSS_COLOR_COLLISION_DETECTION_AP_PERIOD_MS 5000
struct wmi_obss_color_collision_cfg_params_cmd {
u32 tlv_header;
u32 vdev_id;
u32 flags;
u32 evt_type;
u32 current_bss_color;
u32 detection_period_ms;
u32 scan_period_ms;
u32 free_slot_expiry_time_ms;
} __packed;
struct wmi_bss_color_change_enable_params_cmd {
u32 tlv_header;
u32 vdev_id;
u32 enable;
} __packed;
#define ATH11K_IPV4_TH_SEED_SIZE 5
#define ATH11K_IPV6_TH_SEED_SIZE 11
struct ath11k_wmi_pdev_lro_config_cmd {
u32 tlv_header;
u32 lro_enable;
u32 res;
u32 th_4[ATH11K_IPV4_TH_SEED_SIZE];
u32 th_6[ATH11K_IPV6_TH_SEED_SIZE];
u32 pdev_id;
} __packed;
struct target_resource_config {
u32 num_vdevs;
u32 num_peers;
......@@ -4814,4 +4851,10 @@ int ath11k_wmi_send_twt_enable_cmd(struct ath11k *ar, u32 pdev_id);
int ath11k_wmi_send_twt_disable_cmd(struct ath11k *ar, u32 pdev_id);
int ath11k_wmi_send_obss_spr_cmd(struct ath11k *ar, u32 vdev_id,
struct ieee80211_he_obss_pd *he_obss_pd);
int ath11k_wmi_send_obss_color_collision_cfg_cmd(struct ath11k *ar, u32 vdev_id,
u8 bss_color, u32 period,
bool enable);
int ath11k_wmi_send_bss_color_change_enable_cmd(struct ath11k *ar, u32 vdev_id,
bool enable);
int ath11k_wmi_pdev_lro_cfg(struct ath11k *ar, int pdev_id);
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment