diff --git a/qca/qca-nss-dp/patches/0015-edma_v1-convert-rx-tx_store-to-idr-implementation.patch b/qca/qca-nss-dp/patches/0015-edma_v1-convert-rx-tx_store-to-idr-implementation.patch new file mode 100644 index 0000000..21e3c68 --- /dev/null +++ b/qca/qca-nss-dp/patches/0015-edma_v1-convert-rx-tx_store-to-idr-implementation.patch @@ -0,0 +1,239 @@ +From e80ad87476fe55f602c4e76f6b1068036b34b7a0 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +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 +--- + 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 +