lede/package/qca/nss/qca-nss-dp/patches/0015-edma_v1-convert-rx-tx_store-to-idr-implementation.patch
2022-09-12 14:06:04 +08:00

240 lines
7.6 KiB
Diff

From e80ad87476fe55f602c4e76f6b1068036b34b7a0 Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Fri, 24 Jun 2022 15:04:44 +0200
Subject: [PATCH 1/3] edma_v1: convert rx/tx_store to idr implementation
Convert rx/tx store to idr implementation to correctly scale in
preparation for support of multiqueue implementation.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
hal/dp_ops/edma_dp/edma_v1/edma_cfg.c | 32 +++++++++----
hal/dp_ops/edma_dp/edma_v1/edma_data_plane.h | 8 +++-
hal/dp_ops/edma_dp/edma_v1/edma_tx_rx.c | 49 ++++++++++++++------
3 files changed, 63 insertions(+), 26 deletions(-)
diff --git a/hal/dp_ops/edma_dp/edma_v1/edma_cfg.c b/hal/dp_ops/edma_dp/edma_v1/edma_cfg.c
index fbd315a..2e98aaf 100644
--- a/hal/dp_ops/edma_dp/edma_v1/edma_cfg.c
+++ b/hal/dp_ops/edma_dp/edma_v1/edma_cfg.c
@@ -72,8 +72,12 @@ static void edma_cleanup_rxfill_ring_res(struct edma_hw *ehw,
* Get sk_buff and free it
*/
store_idx = rxph->opaque;
- skb = ehw->rx_skb_store[store_idx];
- ehw->rx_skb_store[store_idx] = NULL;
+
+ spin_lock_bh(&ehw->rx_skb_idr_lock);
+ skb = idr_find(&ehw->rx_skb_idr, store_idx);
+ idr_remove(&ehw->rx_skb_idr, store_idx);
+ spin_unlock_bh(&ehw->rx_skb_idr_lock);
+
dev_kfree_skb_any(skb);
cons_idx++;
if (cons_idx == rxfill_ring->count)
@@ -173,8 +177,12 @@ static void edma_cleanup_rxdesc_ring_res(struct edma_hw *ehw,
dma_unmap_single(&pdev->dev, rxdesc_desc->buffer_addr,
ehw->rx_alloc_size, DMA_FROM_DEVICE);
store_idx = rxph->opaque;
- skb = ehw->rx_skb_store[store_idx];
- ehw->rx_skb_store[store_idx] = NULL;
+
+ spin_lock_bh(&ehw->rx_skb_idr_lock);
+ skb = idr_find(&ehw->rx_skb_idr, store_idx);
+ idr_remove(&ehw->rx_skb_idr, store_idx);
+ spin_unlock_bh(&ehw->rx_skb_idr_lock);
+
dev_kfree_skb_any(skb);
/*
@@ -270,8 +278,11 @@ static void edma_cleanup_txdesc_ring_res(struct edma_hw *ehw,
while (cons_idx != prod_idx) {
txdesc = EDMA_TXDESC_DESC(txdesc_ring, cons_idx);
store_idx = txdesc->buffer_addr;
- skb = ehw->tx_skb_store[store_idx];
- ehw->tx_skb_store[store_idx] = NULL;
+
+ spin_lock_bh(&ehw->tx_skb_idr_lock);
+ skb = idr_find(&ehw->tx_skb_idr, store_idx);
+ idr_remove(&ehw->tx_skb_idr, store_idx);
+ spin_unlock_bh(&ehw->tx_skb_idr_lock);
buf_len = (txdesc->word1 & EDMA_TXDESC_DATA_LENGTH_MASK) >>
EDMA_TXDESC_DATA_LENGTH_SHIFT;
@@ -675,10 +686,11 @@ static void edma_configure_rings(struct edma_hw *ehw)
/*
* Initialize the store
*/
- for (i = 0; i < EDMA_RING_SIZE; i++) {
- ehw->tx_skb_store[i] = NULL;
- ehw->rx_skb_store[i] = NULL;
- }
+ idr_init(&ehw->rx_skb_idr);
+ spin_lock_init(&ehw->rx_skb_idr_lock);
+
+ idr_init(&ehw->tx_skb_idr);
+ spin_lock_init(&ehw->tx_skb_idr_lock);
/*
* Configure TXDESC ring
diff --git a/hal/dp_ops/edma_dp/edma_v1/edma_data_plane.h b/hal/dp_ops/edma_dp/edma_v1/edma_data_plane.h
index 0b28fe8..2bbe478 100644
--- a/hal/dp_ops/edma_dp/edma_v1/edma_data_plane.h
+++ b/hal/dp_ops/edma_dp/edma_v1/edma_data_plane.h
@@ -44,6 +44,8 @@
#define EDMA_RXPH_SRC_INFO_TYPE_GET(rxph) (((rxph)->src_info >> 8) & 0xf0)
#define EDMA_RXPH_SERVICE_CODE_GET(rxph) (((rxph)->rx_pre4) & 0xff)
+#define EDMA_TX_IDR_MAX EDMA_RING_SIZE * EDMA_MAX_TXDESC_RINGS
+#define EDMA_RX_IDR_MAX EDMA_RING_SIZE * EDMA_MAX_RXDESC_RINGS
/*
* Tx descriptor
*/
@@ -202,8 +204,10 @@ struct edma_hw {
/*
* Store for tx and rx skbs
*/
- struct sk_buff *rx_skb_store[EDMA_RING_SIZE];
- struct sk_buff *tx_skb_store[EDMA_RING_SIZE];
+ struct idr rx_skb_idr;
+ spinlock_t rx_skb_idr_lock;
+ struct idr tx_skb_idr;
+ spinlock_t tx_skb_idr_lock;
struct edma_rxfill_ring *rxfill_ring;
/* Rx Fill Ring, SW is producer */
diff --git a/hal/dp_ops/edma_dp/edma_v1/edma_tx_rx.c b/hal/dp_ops/edma_dp/edma_v1/edma_tx_rx.c
index 5780a30..8cded66 100644
--- a/hal/dp_ops/edma_dp/edma_v1/edma_tx_rx.c
+++ b/hal/dp_ops/edma_dp/edma_v1/edma_tx_rx.c
@@ -37,9 +37,9 @@ int edma_alloc_rx_buffer(struct edma_hw *ehw,
uint16_t cons, next, counter;
struct edma_rxfill_desc *rxfill_desc;
uint32_t reg_data = 0;
- uint32_t store_index = 0;
uint32_t alloc_size = ehw->rx_alloc_size;
struct edma_rx_preheader *rxph = NULL;
+ int store_index;
/*
* Read RXFILL ring producer index
@@ -82,12 +82,16 @@ int edma_alloc_rx_buffer(struct edma_hw *ehw,
/*
* Store the skb in the rx store
*/
- store_index = next;
- if (ehw->rx_skb_store[store_index] != NULL) {
+ spin_lock_bh(&ehw->rx_skb_idr_lock);
+ store_index = idr_alloc(&ehw->rx_skb_idr,
+ skb, 0, EDMA_RX_IDR_MAX, GFP_ATOMIC);
+ spin_unlock_bh(&ehw->rx_skb_idr_lock);
+
+ if (store_index < 0) {
dev_kfree_skb_any(skb);
break;
}
- ehw->rx_skb_store[store_index] = skb;
+
memcpy((uint8_t *)&rxph->opaque, (uint8_t *)&store_index, 4);
/*
* Save buffer size in RXFILL descriptor
@@ -106,7 +110,9 @@ int edma_alloc_rx_buffer(struct edma_hw *ehw,
if (!rxfill_desc->buffer_addr) {
dev_kfree_skb_any(skb);
- ehw->rx_skb_store[store_index] = NULL;
+ spin_lock_bh(&ehw->rx_skb_idr_lock);
+ idr_remove(&ehw->rx_skb_idr, store_index);
+ spin_unlock_bh(&ehw->rx_skb_idr_lock);
break;
}
@@ -173,15 +179,19 @@ uint32_t edma_clean_tx(struct edma_hw *ehw,
* buffer address (opaque) of txcmpl
*/
store_index = txcmpl->buffer_addr;
- skb = ehw->tx_skb_store[store_index];
- ehw->tx_skb_store[store_index] = NULL;
+ spin_lock_bh(&ehw->tx_skb_idr_lock);
+ skb = idr_find(&ehw->tx_skb_idr, store_index);
if (unlikely(!skb)) {
pr_warn("Invalid skb: cons_idx:%u prod_idx:%u status %x\n",
cons_idx, prod_idx, txcmpl->status);
+ spin_unlock_bh(&ehw->tx_skb_idr_lock);
goto next_txcmpl_desc;
}
+ idr_remove(&ehw->tx_skb_idr, store_index);
+ spin_unlock_bh(&ehw->tx_skb_idr_lock);
+
len = skb_headlen(skb);
daddr = (dma_addr_t)virt_to_phys(skb->data);
@@ -322,14 +332,19 @@ static uint32_t edma_clean_rx(struct edma_hw *ehw,
DMA_FROM_DEVICE);
store_index = rxph->opaque;
- skb = ehw->rx_skb_store[store_index];
- ehw->rx_skb_store[store_index] = NULL;
+ spin_lock_bh(&ehw->rx_skb_idr_lock);
+ skb = idr_find(&ehw->rx_skb_idr, store_index);
+
if (unlikely(!skb)) {
+ spin_unlock_bh(&ehw->rx_skb_idr_lock);
pr_warn("WARN: empty skb reference in rx_store:%d\n",
cons_idx);
goto next_rx_desc;
}
+ idr_remove(&ehw->rx_skb_idr, store_index);
+ spin_unlock_bh(&ehw->rx_skb_idr_lock);
+
/*
* Check src_info from Rx preheader
*/
@@ -539,7 +554,7 @@ enum edma_tx edma_ring_xmit(struct edma_hw *ehw,
uint16_t buf_len;
uint16_t hw_next_to_use, hw_next_to_clean, chk_idx;
uint32_t data;
- uint32_t store_index = 0;
+ int store_index = 0;
struct edma_tx_preheader *txph = NULL;
/*
@@ -616,13 +631,16 @@ enum edma_tx edma_ring_xmit(struct edma_hw *ehw,
/*
* Store the skb in tx_store
*/
- store_index = hw_next_to_use & (txdesc_ring->count - 1);
- if (unlikely(ehw->tx_skb_store[store_index] != NULL)) {
+ spin_lock_bh(&ehw->tx_skb_idr_lock);
+ store_index = idr_alloc(&ehw->tx_skb_idr,
+ skb, 0, EDMA_RX_IDR_MAX, GFP_ATOMIC);
+ spin_unlock_bh(&ehw->tx_skb_idr_lock);
+
+ if (unlikely(store_index < 0)) {
spin_unlock_bh(&txdesc_ring->tx_lock);
return EDMA_TX_DESC;
}
- ehw->tx_skb_store[store_index] = skb;
memcpy(skb->data, &store_index, 4);
/*
@@ -645,7 +663,10 @@ enum edma_tx edma_ring_xmit(struct edma_hw *ehw,
*/
dev_kfree_skb_any(skb);
- ehw->tx_skb_store[store_index] = NULL;
+ spin_lock_bh(&ehw->tx_skb_idr_lock);
+ idr_remove(&ehw->tx_skb_idr, store_index);
+ spin_unlock_bh(&ehw->tx_skb_idr_lock);
+
spin_unlock_bh(&txdesc_ring->tx_lock);
return EDMA_TX_OK;
}
--
2.36.1