mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-12-20 19:03:39 +00:00
186 lines
6.2 KiB
Diff
186 lines
6.2 KiB
Diff
From 9600bc899bd28386375f5b5902a33f1984ce9da8 Mon Sep 17 00:00:00 2001
|
|
From: Venkateswara Naralasetty <quic_vnaralas@quicinc.com>
|
|
Date: Thu, 18 Nov 2021 13:11:02 +0530
|
|
Subject: [PATCH] ath11k: add simple tx handler for AP mode
|
|
|
|
Add simple tx handler for AP mode to skip cheks which are not
|
|
applicable for AP mode.
|
|
|
|
Signed-off-by: Venkateswara Naralasetty <quic_vnaralas@quicinc.com>
|
|
---
|
|
drivers/net/wireless/ath/ath11k/dp_tx.c | 123 +++++++++++++++++++++++++++++
|
|
drivers/net/wireless/ath/ath11k/dp_tx.h | 2 +
|
|
drivers/net/wireless/ath/ath11k/hal_desc.h | 6 ++
|
|
drivers/net/wireless/ath/ath11k/mac.c | 3 +
|
|
4 files changed, 134 insertions(+)
|
|
|
|
--- a/drivers/net/wireless/ath/ath11k/dp_tx.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/dp_tx.c
|
|
@@ -92,6 +92,128 @@ static int ath11k_dp_prepare_htt_metadat
|
|
return 0;
|
|
}
|
|
|
|
+int ath11k_dp_tx_simple(struct ath11k *ar, struct ath11k_vif *arvif,
|
|
+ struct sk_buff *skb, struct ath11k_sta *arsta)
|
|
+{
|
|
+ struct ath11k_base *ab = ar->ab;
|
|
+ struct ath11k_dp *dp = &ab->dp;
|
|
+ struct ath11k_skb_cb *skb_cb = ATH11K_SKB_CB(skb);
|
|
+ struct hal_srng *tcl_ring;
|
|
+ struct dp_tx_ring *tx_ring;
|
|
+ struct hal_tcl_data_cmd *tcl_desc;
|
|
+ void *hal_tcl_desc;
|
|
+ dma_addr_t paddr;
|
|
+ u8 pool_id;
|
|
+ u8 hal_ring_id;
|
|
+ int ret;
|
|
+ u32 idr;
|
|
+ u8 tcl_ring_id, ring_id, max_tx_ring;
|
|
+ u8 buf_id;
|
|
+ u32 desc_id;
|
|
+ u8 ring_selector;
|
|
+
|
|
+ max_tx_ring = ab->hw_params.max_tx_ring;
|
|
+
|
|
+ if (unlikely(atomic_read(&ab->num_max_allowed) > DP_TX_COMP_MAX_ALLOWED)) {
|
|
+ atomic_inc(&ab->soc_stats.tx_err.max_fail);
|
|
+ ret = -EINVAL;
|
|
+ }
|
|
+
|
|
+ ring_selector = smp_processor_id();
|
|
+ pool_id = ring_selector;
|
|
+
|
|
+ if (max_tx_ring == 1) {
|
|
+ ring_id = 0;
|
|
+ tcl_ring_id = 0;
|
|
+ } else {
|
|
+ ring_id = ring_selector % max_tx_ring;
|
|
+ tcl_ring_id = (ring_id == DP_TCL_NUM_RING_MAX) ?
|
|
+ DP_TCL_NUM_RING_MAX - 1 : ring_id;
|
|
+ }
|
|
+
|
|
+ buf_id = tcl_ring_id + HAL_RX_BUF_RBM_SW0_BM;
|
|
+ tx_ring = &dp->tx_ring[tcl_ring_id];
|
|
+
|
|
+ spin_lock_bh(&tx_ring->tx_idr_lock);
|
|
+ idr = find_first_zero_bit(tx_ring->idrs, DP_TX_IDR_SIZE);
|
|
+ if (unlikely(idr >= DP_TX_IDR_SIZE)) {
|
|
+ spin_unlock_bh(&tx_ring->tx_idr_lock);
|
|
+ return -ENOSPC;
|
|
+ }
|
|
+
|
|
+ set_bit(idr, tx_ring->idrs);
|
|
+ tx_ring->idr_pool[idr].id = idr;
|
|
+ tx_ring->idr_pool[idr].buf = skb;
|
|
+ spin_unlock_bh(&tx_ring->tx_idr_lock);
|
|
+
|
|
+ desc_id = FIELD_PREP(DP_TX_DESC_ID_MAC_ID, ar->pdev_idx) |
|
|
+ FIELD_PREP(DP_TX_DESC_ID_MSDU_ID, idr) |
|
|
+ FIELD_PREP(DP_TX_DESC_ID_POOL_ID, pool_id);
|
|
+
|
|
+ skb_cb->vif = arvif->vif;
|
|
+ skb_cb->ar = ar;
|
|
+
|
|
+ paddr = dma_map_single(ab->dev, skb->data, skb->len, DMA_TO_DEVICE);
|
|
+ if (unlikely(dma_mapping_error(ab->dev, paddr))) {
|
|
+ atomic_inc(&ab->soc_stats.tx_err.misc_fail);
|
|
+ ath11k_warn(ab, "failed to DMA map data Tx buffer\n");
|
|
+ ret = -ENOMEM;
|
|
+ goto fail_remove_idr;
|
|
+ }
|
|
+
|
|
+ skb_cb->paddr = paddr;
|
|
+
|
|
+ hal_ring_id = tx_ring->tcl_data_ring.ring_id;
|
|
+ tcl_ring = &ab->hal.srng_list[hal_ring_id];
|
|
+
|
|
+ spin_lock_bh(&tcl_ring->lock);
|
|
+ ath11k_hal_srng_access_begin(ab, tcl_ring);
|
|
+
|
|
+ hal_tcl_desc = (void *)ath11k_hal_srng_src_get_next_entry(ab, tcl_ring);
|
|
+ if (unlikely(!hal_tcl_desc)) {
|
|
+ ath11k_hal_srng_access_end(ab, tcl_ring);
|
|
+ spin_unlock_bh(&tcl_ring->lock);
|
|
+ ab->soc_stats.tx_err.desc_na[tcl_ring_id]++;
|
|
+ ret = -ENOMEM;
|
|
+ goto fail_remove_idr;
|
|
+ }
|
|
+
|
|
+ tcl_desc = (struct hal_tcl_data_cmd *)(hal_tcl_desc + sizeof(struct hal_tlv_hdr));
|
|
+ tcl_desc->info3 = 0;
|
|
+ tcl_desc->info4 = 0;
|
|
+
|
|
+ tcl_desc->buf_addr_info.info0 = FIELD_PREP(BUFFER_ADDR_INFO0_ADDR, paddr);
|
|
+ tcl_desc->buf_addr_info.info1 = FIELD_PREP(BUFFER_ADDR_INFO1_ADDR,
|
|
+ ((uint64_t)paddr >> HAL_ADDR_MSB_REG_SHIFT));
|
|
+ tcl_desc->buf_addr_info.info1 |= FIELD_PREP(BUFFER_ADDR_INFO1_RET_BUF_MGR, buf_id) |
|
|
+ FIELD_PREP(BUFFER_ADDR_INFO1_SW_COOKIE, desc_id);
|
|
+ tcl_desc->info0 = FIELD_PREP(HAL_TCL_DATA_CMD_INFO0_SEARCH_TYPE,
|
|
+ arvif->search_type) |
|
|
+ FIELD_PREP(HAL_TCL_DATA_CMD_INFO0_ENCAP_TYPE, HAL_TCL_ENCAP_TYPE_ETHERNET) |
|
|
+ FIELD_PREP(HAL_TCL_DATA_CMD_INFO0_ADDR_EN, arvif->hal_addr_search_flags) |
|
|
+ FIELD_PREP(HAL_TCL_DATA_CMD_INFO0_CMD_NUM, arvif->tcl_metadata);
|
|
+
|
|
+ tcl_desc->info1 = FIELD_PREP(HAL_TCL_DATA_CMD_INFO1_DATA_LEN, skb->len);
|
|
+
|
|
+ if (likely(skb->ip_summed == CHECKSUM_PARTIAL))
|
|
+ tcl_desc->info1 |= TX_IP_CHECKSUM;
|
|
+
|
|
+ tcl_desc->info2 = FIELD_PREP(HAL_TCL_DATA_CMD_INFO2_LMAC_ID, ar->lmac_id);
|
|
+
|
|
+ ath11k_hal_srng_access_end(ab, tcl_ring);
|
|
+ spin_unlock_bh(&tcl_ring->lock);
|
|
+
|
|
+ atomic_inc(&ar->dp.num_tx_pending);
|
|
+ atomic_inc(&ab->num_max_allowed);
|
|
+
|
|
+ return 0;
|
|
+
|
|
+fail_remove_idr:
|
|
+ tx_ring->idr_pool[idr].id = -1;
|
|
+ clear_bit(idr, tx_ring->idrs);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif,
|
|
struct sk_buff *skb, struct ath11k_sta *arsta)
|
|
{
|
|
--- a/drivers/net/wireless/ath/ath11k/dp_tx.h
|
|
+++ b/drivers/net/wireless/ath/ath11k/dp_tx.h
|
|
@@ -220,6 +220,8 @@ struct htt_tx_msdu_desc_ext {
|
|
int ath11k_dp_tx_htt_h2t_ver_req_msg(struct ath11k_base *ab);
|
|
int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif,
|
|
struct ath11k_sta *arsta, struct sk_buff *skb);
|
|
+int ath11k_dp_tx_simple(struct ath11k *ar, struct ath11k_vif *arvif,
|
|
+ struct sk_buff *skb, struct ath11k_sta *arsta);
|
|
void ath11k_dp_tx_completion_handler(struct ath11k_base *ab, int ring_id);
|
|
int ath11k_dp_tx_send_reo_cmd(struct ath11k_base *ab, struct dp_rx_tid *rx_tid,
|
|
enum hal_reo_cmd_type type,
|
|
--- a/drivers/net/wireless/ath/ath11k/hal_desc.h
|
|
+++ b/drivers/net/wireless/ath/ath11k/hal_desc.h
|
|
@@ -952,6 +952,12 @@ struct hal_reo_flush_cache {
|
|
u32 rsvd0[6];
|
|
} __packed;
|
|
|
|
+#define TX_IP_CHECKSUM HAL_TCL_DATA_CMD_INFO1_IP4_CKSUM_EN | \
|
|
+ HAL_TCL_DATA_CMD_INFO1_UDP4_CKSUM_EN | \
|
|
+ HAL_TCL_DATA_CMD_INFO1_UDP6_CKSUM_EN | \
|
|
+ HAL_TCL_DATA_CMD_INFO1_TCP4_CKSUM_EN | \
|
|
+ HAL_TCL_DATA_CMD_INFO1_TCP6_CKSUM_EN
|
|
+
|
|
#define HAL_TCL_DATA_CMD_INFO0_DESC_TYPE BIT(0)
|
|
#define HAL_TCL_DATA_CMD_INFO0_EPD BIT(1)
|
|
#define HAL_TCL_DATA_CMD_INFO0_ENCAP_TYPE GENMASK(3, 2)
|
|
--- a/drivers/net/wireless/ath/ath11k/mac.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/mac.c
|
|
@@ -6784,6 +6784,9 @@ static void ath11k_mac_op_tx(struct ieee
|
|
|
|
if (ar->ab->nss.enabled)
|
|
ret = ath11k_nss_tx(arvif, skb);
|
|
+ else if (info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP)
|
|
+ ret = ath11k_dp_tx_simple(ar, arvif, skb,
|
|
+ (control->sta) ? control->sta->drv_priv : NULL);
|
|
else
|
|
ret = ath11k_dp_tx(ar, arvif, skb,
|
|
(control->sta) ? control->sta->drv_priv : NULL);
|