diff mbox series

[RFC,net-next,v2,9/9] bnxt: swap rx ring mem during queue_stop()

Message ID 20240502045410.3524155-10-dw@davidwei.uk (mailing list archive)
State RFC
Delegated to: Netdev Maintainers
Headers show
Series bnxt: implement queue api | expand

Checks

Context Check Description
netdev/series_format success Posting correctly formatted
netdev/tree_selection success Clearly marked for net-next, async
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 926 this patch: 926
netdev/build_tools success No tools touched, skip
netdev/cc_maintainers success CCed 5 of 5 maintainers
netdev/build_clang success Errors and warnings before: 937 this patch: 937
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 939 this patch: 939
netdev/checkpatch warning WARNING: line length of 81 exceeds 80 columns
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 2 this patch: 2
netdev/source_inline success Was 0 now: 0

Commit Message

David Wei May 2, 2024, 4:54 a.m. UTC
After stopping an rx ring in bnxt_queue_stop(), swap the preallocated
ring memory into the existing rx ring that the hardware is aware of. As
discussed in the last patch, the hardware ring is associated with the
address of static arrays in struct bnxt_rx_ring_info. For example:

struct bnxt_rx_ring_info              struct bnxt_ring_mem_info

struct rx_bd *rx_desc_ring[MAX]   <-> void **pg_arr
struct bnxt_sw_rx_bd *rx_buf_ring <-> void **vmem

The pg_tbl that is registered w/ the hardware via HWRM contains an array
of dma mappings to the pg_arr above. We can't touch this association
during reset, so can't simply swap the ring and its clone directly.

Instead, swap the ring memory only then update the pg_tbl. Functionally
it should be the same as the existing bnxt_rx_ring_reset(), except the
allocations happen before resetting the ring using a clone struct
bnxt_rx_ring_info.

Signed-off-by: David Wei <dw@davidwei.uk>
---
 drivers/net/ethernet/broadcom/bnxt/bnxt.c | 54 +++++++++++++++++------
 1 file changed, 41 insertions(+), 13 deletions(-)
diff mbox series

Patch

diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index d848b9ceabf0..4dd4aa0911b1 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -15024,8 +15024,6 @@  static int bnxt_queue_start(struct net_device *dev, int idx, void *qmem)
 	struct bnxt_rx_ring_info *rxr = qmem;
 	struct bnxt *bp = netdev_priv(dev);
 
-	bnxt_alloc_one_rx_ring(bp, rxr);
-
 	if (bp->flags & BNXT_FLAG_AGG_RINGS)
 		bnxt_db_write(bp, &rxr->rx_agg_db, rxr->rx_agg_prod);
 	bnxt_db_write(bp, &rxr->rx_db, rxr->rx_prod);
@@ -15038,26 +15036,56 @@  static int bnxt_queue_start(struct net_device *dev, int idx, void *qmem)
 
 static int bnxt_queue_stop(struct net_device *dev, int idx, void **out_qmem)
 {
+	struct bnxt_rx_ring_info *orig, *rplc;
 	struct bnxt *bp = netdev_priv(dev);
-	struct bnxt_rx_ring_info *rxr;
+	struct bnxt_ring_mem_info *rmem;
 	struct bnxt_cp_ring_info *cpr;
-	int rc;
+	int i, rc;
 
 	rc = bnxt_hwrm_rx_ring_reset(bp, idx);
 	if (rc)
 		return rc;
 
-	rxr = &bp->rx_ring[idx];
-	bnxt_free_one_rx_ring_skbs(bp, rxr);
-	rxr->rx_prod = 0;
-	rxr->rx_agg_prod = 0;
-	rxr->rx_sw_agg_prod = 0;
-	rxr->rx_next_cons = 0;
-
-	cpr = &rxr->bnapi->cp_ring;
+	/* HW ring is registered w/ the original bnxt_rx_ring_info so we cannot
+	 * do a direct swap between orig and rplc. Instead, swap the
+	 * dynamically allocated queue memory and then update pg_tbl.
+	 */
+	orig = &bp->rx_ring[idx];
+	rplc = orig->rplc;
+
+	swap(orig->rx_prod, rplc->rx_prod);
+	swap(orig->rx_agg_prod, rplc->rx_agg_prod);
+	swap(orig->rx_sw_agg_prod, rplc->rx_sw_agg_prod);
+	swap(orig->rx_next_cons, rplc->rx_next_cons);
+
+	for (i = 0; i < MAX_RX_PAGES; i++) {
+		swap(orig->rx_desc_ring[i], rplc->rx_desc_ring[i]);
+		swap(orig->rx_desc_mapping[i], rplc->rx_desc_mapping[i]);
+
+		swap(orig->rx_agg_desc_ring[i], rplc->rx_agg_desc_ring[i]);
+		swap(orig->rx_agg_desc_mapping[i], rplc->rx_agg_desc_mapping[i]);
+	}
+	swap(orig->rx_buf_ring, rplc->rx_buf_ring);
+	swap(orig->rx_agg_ring, rplc->rx_agg_ring);
+	swap(orig->rx_agg_bmap, rplc->rx_agg_bmap);
+	swap(orig->rx_agg_bmap_size, rplc->rx_agg_bmap_size);
+	swap(orig->rx_tpa, rplc->rx_tpa);
+	swap(orig->rx_tpa_idx_map, rplc->rx_tpa_idx_map);
+	swap(orig->page_pool, rplc->page_pool);
+
+	rmem = &orig->rx_ring_struct.ring_mem;
+	for (i = 0; i < rmem->nr_pages; i++)
+		rmem->pg_tbl[i] = cpu_to_le64(rmem->dma_arr[i]);
+
+	rmem = &rplc->rx_ring_struct.ring_mem;
+	for (i = 0; i < rmem->nr_pages; i++)
+		rmem->pg_tbl[i] = cpu_to_le64(rmem->dma_arr[i]);
+
+	cpr = &orig->bnapi->cp_ring;
 	cpr->sw_stats.rx.rx_resets++;
 
-	*out_qmem = rxr;
+	*out_qmem = rplc;
+	orig->rplc = NULL;
 
 	return 0;
 }