mirror of
https://github.com/coolsnowwolf/lede.git
synced 2025-04-16 14:23:38 +00:00
240 lines
7.6 KiB
Diff
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
|
|
|