git: 644880d7b9b8 - main - if_bnxt: support more Tx rings than Rx rings on P5+

From: Sumit Saxena <ssaxena_at_FreeBSD.org>
Date: Fri, 09 Oct 2026 10:12:54 UTC
The branch main has been updated by ssaxena:

URL: https://cgit.FreeBSD.org/src/commit/?id=644880d7b9b86fa16797fa45e7a876ac503227f9

commit 644880d7b9b86fa16797fa45e7a876ac503227f9
Author:     Sumit Saxena <sumit.saxena@broadcom.com>
AuthorDate: 2026-08-01 08:52:51 +0000
Commit:     Sumit Saxena <ssaxena@FreeBSD.org>
CommitDate: 2026-10-09 08:24:45 +0000

    if_bnxt: support more Tx rings than Rx rings on P5+
    
    Add an unsupported-config guard rejecting nrxqsets > ntxqsets, and
    teach the P5+ NQ datapath to handle the opposite asymmetric case:
    extra Tx rings beyond the Rx ring count. softc->nq_rings[i].type now
    tags each NQ as SHARED_NQ (paired with an Rx CQ) or BNXT_TX_ONLY_NQ
    (dedicated to an extra Tx CQ with no backing Rx ring); bnxt_init()
    and bnxt_hwrm_resource_free() gate all Rx ring group/ring/stat-ctx
    alloc and free on IS_SHARED_NQ() so the extra Tx-only NQs don't touch
    nonexistent Rx ring state. Gate the new type-tagging and IS_SHARED_NQ
    checks on BNXT_CHIP_P5_PLUS(), since non-P5+ chips never allocate
    softc->nq_rings and would otherwise access a nonexistent array.
    
    BNXT_TX_ONLY_NQ is a distinct value from the existing MPC-private
    TX_CP_NQ; the two are unrelated and kept apart to avoid confusion.
    
    Suggested by:   gallatin
    Reviewed by:    gallatin
    MFC after:      2 weeks
    Sponsored by:   Broadcom Inc.
    Differential Revision:  https://reviews.freebsd.org/D58618
---
 sys/dev/bnxt/bnxt_en/bnxt.h    |  11 +++
 sys/dev/bnxt/bnxt_en/if_bnxt.c | 187 ++++++++++++++++++++++++-----------------
 2 files changed, 121 insertions(+), 77 deletions(-)

diff --git a/sys/dev/bnxt/bnxt_en/bnxt.h b/sys/dev/bnxt/bnxt_en/bnxt.h
index 37914dae9a1d..14f17b6d288a 100644
--- a/sys/dev/bnxt/bnxt_en/bnxt.h
+++ b/sys/dev/bnxt/bnxt_en/bnxt.h
@@ -712,11 +712,22 @@ struct bnxt_cp_ring {
 #define Q_TYPE_TX		1
 #define Q_TYPE_RX		2
 #define TX_CP_NQ		3	/* MPC-private NQ ring (bnxt_mpc.c) */
+/* BNXT_TX_ONLY_NQ is kept distinct from the MPC-private TX_CP_NQ above -
+ * same field, unrelated arrays. */
+#define SHARED_NQ		4
+#define BNXT_TX_ONLY_NQ		5
+#define RX_CP_NQ		6
 	int			msix_vec;	/* MPC-private ring: bus_setup_intr vector */
 	struct resource		*irq_res;	/* MPC-private ring: bus_setup_intr resource */
 	void			*irq_cookie;	/* MPC-private ring: bus_setup_intr cookie */
 };
 
+#define MAX_RXQ_INDEX(softc) ((softc)->nrxqsets - 1)
+#define IS_SHARED_NQ(softc, i) \
+	(BNXT_CHIP_P5_PLUS(softc) && (softc)->nq_rings[i].type == SHARED_NQ)
+#define IS_TX_NQ(softc, i) ((softc)->nq_rings[i].type == BNXT_TX_ONLY_NQ)
+#define IS_RX_NQ(softc, i) ((softc)->nq_rings[i].type == RX_CP_NQ)
+
 struct bnxt_full_tpa_start {
 	struct rx_tpa_start_cmpl low;
 	struct rx_tpa_start_cmpl_hi high;
diff --git a/sys/dev/bnxt/bnxt_en/if_bnxt.c b/sys/dev/bnxt/bnxt_en/if_bnxt.c
index b7dd72ffb177..2129c0ff51b0 100644
--- a/sys/dev/bnxt/bnxt_en/if_bnxt.c
+++ b/sys/dev/bnxt/bnxt_en/if_bnxt.c
@@ -3000,6 +3000,19 @@ bnxt_attach_pre(if_ctx_t ctx)
 		device_printf(softc->dev,
 		    "WARNING: ntxd0 (%d) should be at least 2 * ntxd1 (%d).  Driver may be unstable\n",
 		    scctx->isc_ntxd[0], scctx->isc_ntxd[1]);
+
+	/*
+	 * Unsupported configuration: number of Rx rings
+	 * exceeding number of Tx rings
+	 */
+	if (scctx->isc_nrxqsets > scctx->isc_ntxqsets) {
+		device_printf(softc->dev, "Unsupported config: number of"
+		    " Rx rings(%u) exceeds number of Tx rings(%u)\n",
+		    scctx->isc_nrxqsets, scctx->isc_ntxqsets);
+		rc = EOPNOTSUPP;
+		goto failed;
+	}
+
 	scctx->isc_txqsizes[0] = sizeof(struct cmpl_base) * scctx->isc_ntxd[0];
 	scctx->isc_txqsizes[1] = sizeof(struct tx_bd_short) *
 	    scctx->isc_ntxd[1];
@@ -3436,31 +3449,33 @@ bnxt_hwrm_resource_free(struct bnxt_softc *softc)
 	if (rc)
 		goto fail;
 
-	for (i = 0; i < softc->nrxqsets; i++) {
-		rc = bnxt_hwrm_ring_grp_free(softc, &softc->grp_info[i]);
-		if (rc)
-			goto fail;
+	for (i = 0; i < softc->ntxqsets; i++) {
+		if (IS_SHARED_NQ(softc, i) || !BNXT_CHIP_P5_PLUS(softc)) {
+			rc = bnxt_hwrm_ring_grp_free(softc, &softc->grp_info[i]);
+			if (rc)
+				goto fail;
 
-		rc = bnxt_hwrm_ring_free(softc,
-				HWRM_RING_ALLOC_INPUT_RING_TYPE_RX_AGG,
-				&softc->ag_rings[i],
-				(uint16_t)HWRM_NA_SIGNATURE);
-		if (rc)
-			goto fail;
+			rc = bnxt_hwrm_ring_free(softc,
+					HWRM_RING_ALLOC_INPUT_RING_TYPE_RX_AGG,
+					&softc->ag_rings[i],
+					(uint16_t)HWRM_NA_SIGNATURE);
+			if (rc)
+				goto fail;
 
-		rc = bnxt_hwrm_ring_free(softc,
-				HWRM_RING_ALLOC_INPUT_RING_TYPE_RX,
-				&softc->rx_rings[i],
-				softc->rx_cp_rings[i].ring.phys_id);
-		if (rc)
-			goto fail;
+			rc = bnxt_hwrm_ring_free(softc,
+					HWRM_RING_ALLOC_INPUT_RING_TYPE_RX,
+					&softc->rx_rings[i],
+					softc->rx_cp_rings[i].ring.phys_id);
+			if (rc)
+				goto fail;
 
-		rc = bnxt_hwrm_ring_free(softc,
-				HWRM_RING_ALLOC_INPUT_RING_TYPE_L2_CMPL,
-				&softc->rx_cp_rings[i].ring,
-				(uint16_t)HWRM_NA_SIGNATURE);
-		if (rc)
-			goto fail;
+			rc = bnxt_hwrm_ring_free(softc,
+					HWRM_RING_ALLOC_INPUT_RING_TYPE_L2_CMPL,
+					&softc->rx_cp_rings[i].ring,
+					(uint16_t)HWRM_NA_SIGNATURE);
+			if (rc)
+				goto fail;
+		}
 
 		if (BNXT_CHIP_P5_PLUS(softc)) {
 			rc = bnxt_hwrm_ring_free(softc,
@@ -3471,9 +3486,11 @@ bnxt_hwrm_resource_free(struct bnxt_softc *softc)
 				goto fail;
 		}
 
-		rc = bnxt_hwrm_stat_ctx_free(softc, &softc->rx_cp_rings[i]);
-		if (rc)
-			goto fail;
+		if (IS_SHARED_NQ(softc, i) || !BNXT_CHIP_P5_PLUS(softc)) {
+			rc = bnxt_hwrm_stat_ctx_free(softc, &softc->rx_cp_rings[i]);
+			if (rc)
+				goto fail;
+		}
 	}
 
 fail:
@@ -3662,12 +3679,23 @@ skip_def_cp_ring:
 		}
 	}
 
-	for (i = 0; i < softc->nrxqsets; i++) {
-		/* Allocate the statistics context */
-		rc = bnxt_hwrm_stat_ctx_alloc(softc, &softc->rx_cp_rings[i],
-		    softc->rx_stats[i].idi_paddr);
-		if (rc)
-			goto fail;
+	for (i = 0; i < softc->ntxqsets; i++) {
+		/* Extra Tx rings over Rx: NQs up to MAX_RXQ_INDEX are shared
+		 * Tx/Rx; NQs beyond that are Tx-only. */
+		if (BNXT_CHIP_P5_PLUS(softc)) {
+			if (i <= MAX_RXQ_INDEX(softc))
+				softc->nq_rings[i].type = SHARED_NQ;
+			else
+				softc->nq_rings[i].type = BNXT_TX_ONLY_NQ;
+		}
+
+		if (IS_SHARED_NQ(softc, i) || !BNXT_CHIP_P5_PLUS(softc)) {
+			/* Allocate the statistics context */
+			rc = bnxt_hwrm_stat_ctx_alloc(softc, &softc->rx_cp_rings[i],
+			    softc->rx_stats[i].idi_paddr);
+			if (rc)
+				goto fail;
+		}
 
 		if (BNXT_CHIP_P5_PLUS(softc)) {
 			/* Allocate the NQ */
@@ -3686,53 +3714,56 @@ skip_def_cp_ring:
 
 			softc->db_ops.bnxt_db_nq(&softc->nq_rings[i], 1);
 		}
-		/* Allocate the completion ring */
-		softc->rx_cp_rings[i].cons = UINT32_MAX;
-		softc->rx_cp_rings[i].raw_cons = UINT32_MAX;
-		softc->rx_cp_rings[i].v_bit = 1;
-		softc->rx_cp_rings[i].last_idx = UINT32_MAX;
-		softc->rx_cp_rings[i].toggle = 0;
-		bnxt_mark_cpr_invalid(&softc->rx_cp_rings[i]);
-		rc = bnxt_hwrm_ring_alloc(softc,
-				HWRM_RING_ALLOC_INPUT_RING_TYPE_L2_CMPL,
-				&softc->rx_cp_rings[i].ring);
-		bnxt_set_db_mask(softc, &softc->rx_cp_rings[i].ring,
-				HWRM_RING_ALLOC_INPUT_RING_TYPE_L2_CMPL);
-		if (rc)
-			goto fail;
 
-		if (BNXT_CHIP_P5_PLUS(softc))
-			softc->db_ops.bnxt_db_rx_cq(&softc->rx_cp_rings[i], 1);
+		if (IS_SHARED_NQ(softc, i) || !BNXT_CHIP_P5_PLUS(softc)) {
+			/* Allocate the completion ring */
+			softc->rx_cp_rings[i].cons = UINT32_MAX;
+			softc->rx_cp_rings[i].raw_cons = UINT32_MAX;
+			softc->rx_cp_rings[i].v_bit = 1;
+			softc->rx_cp_rings[i].last_idx = UINT32_MAX;
+			softc->rx_cp_rings[i].toggle = 0;
+			bnxt_mark_cpr_invalid(&softc->rx_cp_rings[i]);
+			rc = bnxt_hwrm_ring_alloc(softc,
+					HWRM_RING_ALLOC_INPUT_RING_TYPE_L2_CMPL,
+					&softc->rx_cp_rings[i].ring);
+			bnxt_set_db_mask(softc, &softc->rx_cp_rings[i].ring,
+					HWRM_RING_ALLOC_INPUT_RING_TYPE_L2_CMPL);
+			if (rc)
+				goto fail;
 
-		/* Allocate the RX ring */
-		rc = bnxt_hwrm_ring_alloc(softc,
-		    HWRM_RING_ALLOC_INPUT_RING_TYPE_RX, &softc->rx_rings[i]);
-		bnxt_set_db_mask(softc, &softc->rx_rings[i],
-				HWRM_RING_ALLOC_INPUT_RING_TYPE_RX);
-		if (rc)
-			goto fail;
-		softc->db_ops.bnxt_db_rx(&softc->rx_rings[i], 0);
+			if (BNXT_CHIP_P5_PLUS(softc))
+				softc->db_ops.bnxt_db_rx_cq(&softc->rx_cp_rings[i], 1);
 
-		/* Allocate the AG ring */
-		rc = bnxt_hwrm_ring_alloc(softc,
-				HWRM_RING_ALLOC_INPUT_RING_TYPE_RX_AGG,
-				&softc->ag_rings[i]);
-		bnxt_set_db_mask(softc, &softc->ag_rings[i],
-				HWRM_RING_ALLOC_INPUT_RING_TYPE_RX_AGG);
-		if (rc)
-			goto fail;
-		softc->db_ops.bnxt_db_rx(&softc->ag_rings[i], 0);
+			/* Allocate the RX ring */
+			rc = bnxt_hwrm_ring_alloc(softc,
+			    HWRM_RING_ALLOC_INPUT_RING_TYPE_RX, &softc->rx_rings[i]);
+			bnxt_set_db_mask(softc, &softc->rx_rings[i],
+					HWRM_RING_ALLOC_INPUT_RING_TYPE_RX);
+			if (rc)
+				goto fail;
+			softc->db_ops.bnxt_db_rx(&softc->rx_rings[i], 0);
 
-		/* Allocate the ring group */
-		softc->grp_info[i].stats_ctx =
-		    softc->rx_cp_rings[i].stats_ctx_id;
-		softc->grp_info[i].rx_ring_id = softc->rx_rings[i].phys_id;
-		softc->grp_info[i].ag_ring_id = softc->ag_rings[i].phys_id;
-		softc->grp_info[i].cp_ring_id =
-		    softc->rx_cp_rings[i].ring.phys_id;
-		rc = bnxt_hwrm_ring_grp_alloc(softc, &softc->grp_info[i]);
-		if (rc)
-			goto fail;
+			/* Allocate the AG ring */
+			rc = bnxt_hwrm_ring_alloc(softc,
+					HWRM_RING_ALLOC_INPUT_RING_TYPE_RX_AGG,
+					&softc->ag_rings[i]);
+			bnxt_set_db_mask(softc, &softc->ag_rings[i],
+					HWRM_RING_ALLOC_INPUT_RING_TYPE_RX_AGG);
+			if (rc)
+				goto fail;
+			softc->db_ops.bnxt_db_rx(&softc->ag_rings[i], 0);
+
+			/* Allocate the ring group */
+			softc->grp_info[i].stats_ctx =
+			    softc->rx_cp_rings[i].stats_ctx_id;
+			softc->grp_info[i].rx_ring_id = softc->rx_rings[i].phys_id;
+			softc->grp_info[i].ag_ring_id = softc->ag_rings[i].phys_id;
+			softc->grp_info[i].cp_ring_id =
+			    softc->rx_cp_rings[i].ring.phys_id;
+			rc = bnxt_hwrm_ring_grp_alloc(softc, &softc->grp_info[i]);
+			if (rc)
+				goto fail;
+		}
 	}
 
 	/* Inform PF to approve MAC as default VF MAC. */
@@ -4387,10 +4418,12 @@ bnxt_tx_queue_intr_enable(if_ctx_t ctx, uint16_t qid)
 {
 	struct bnxt_softc *softc = iflib_get_softc(ctx);
 
-	if (BNXT_CHIP_P5_PLUS(softc))
-		softc->db_ops.bnxt_db_nq(&softc->nq_rings[qid], 1);
-	else
+	if (BNXT_CHIP_P5_PLUS(softc)) {
+		if (!IS_SHARED_NQ(softc, qid))
+			softc->db_ops.bnxt_db_nq(&softc->nq_rings[qid], 1);
+	} else {
 		softc->db_ops.bnxt_db_rx_cq(&softc->tx_cp_rings[qid], 1);
+	}
 
 	return 0;
 }