git: 2f3a1ebba812 - main - if_bnxt: add CAGR interrupt coalescing tick-resolution support

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

URL: https://cgit.FreeBSD.org/src/commit/?id=2f3a1ebba81266b5f21640f88d73e03415cf13be

commit 2f3a1ebba81266b5f21640f88d73e03415cf13be
Author:     Sumit Saxena <sumit.saxena@broadcom.com>
AuthorDate: 2026-07-29 08:36:18 +0000
Commit:     Sumit Saxena <ssaxena@FreeBSD.org>
CommitDate: 2026-10-09 08:24:42 +0000

    if_bnxt: add CAGR interrupt coalescing tick-resolution support
    
    Add the P7 CAGR (Completion AGgregation Ring) NQ-aggregation timer
    tick-resolution knob, programmed via a direct GRC-window register
    write, with a new dev.bnxt.<unit>.cagr_tick_res read-only tunable.
    This is independent of the existing per-ring AGGINT_PARAMS coalescing.
    
    Reviewed by:    gallatin
    MFC after:      2 weeks
    Sponsored by:   Broadcom Inc.
    Differential Revision:  https://reviews.freebsd.org/D58598
---
 sys/dev/bnxt/bnxt_en/bnxt.h        |  8 ++++++++
 sys/dev/bnxt/bnxt_en/bnxt_sysctl.c | 27 +++++++++++++++++++++++++++
 sys/dev/bnxt/bnxt_en/if_bnxt.c     | 32 ++++++++++++++++++++++++++++++++
 3 files changed, 67 insertions(+)

diff --git a/sys/dev/bnxt/bnxt_en/bnxt.h b/sys/dev/bnxt/bnxt_en/bnxt.h
index 98f8c1d3f5fa..35f1b9e97a00 100644
--- a/sys/dev/bnxt/bnxt_en/bnxt.h
+++ b/sys/dev/bnxt/bnxt_en/bnxt.h
@@ -1423,6 +1423,14 @@ struct bnxt_softc {
 
 	struct bnxt_ptp_cfg	*ptp_cfg;
 	bool			rx_ts_enabled;
+
+#define BNXT_CAGR_CQCOAL_OFFSET			0xc00
+#define BNXT_CAGR_NQAGG_MAXTIMER		0x5930000
+#define BNXT_CAGR_TICK_RES_DEFAULT		0x2
+#define BNXT_CAGR_TICK_RES_MIN			0x0
+#define BNXT_CAGR_TICK_RES_MAX			0x4
+#define BNXT_CAGR_TICK_RES_OFFSET		16
+	uint32_t		cagr_tick_res;
 };
 
 struct bnxt_filter_info {
diff --git a/sys/dev/bnxt/bnxt_en/bnxt_sysctl.c b/sys/dev/bnxt/bnxt_en/bnxt_sysctl.c
index 88afc83edd9d..c8a0f1962a13 100644
--- a/sys/dev/bnxt/bnxt_en/bnxt_sysctl.c
+++ b/sys/dev/bnxt/bnxt_en/bnxt_sysctl.c
@@ -1556,6 +1556,30 @@ bnxt_set_coal_tx_frames_irq(SYSCTL_HANDLER_ARGS) {
 	return rc;
 }
 
+static int
+bnxt_set_cagr_tick_res(SYSCTL_HANDLER_ARGS) {
+	struct bnxt_softc *softc = arg1;
+	int rc;
+	int val;
+
+	if (softc == NULL)
+		return EBUSY;
+
+	val = softc->cagr_tick_res;
+
+	rc = sysctl_handle_int(oidp, &val, 0, req);
+	if (rc || !req->newptr)
+		return rc;
+
+	if (val < BNXT_CAGR_TICK_RES_MIN ||
+	    val > BNXT_CAGR_TICK_RES_MAX)
+		return EINVAL;
+
+	softc->cagr_tick_res = val;
+
+	return rc;
+}
+
 static
 void simulate_reset(struct bnxt_softc *bp, char *fwcli_string)
 {
@@ -1648,6 +1672,9 @@ bnxt_create_config_sysctls_pre(struct bnxt_softc *softc)
 	    CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, softc, 0,
 	    bnxt_set_coal_tx_frames_irq, "I",
 	    "interrupt coalescing Tx Frames IRQ");
+	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "cagr_tick_res",
+	    CTLTYPE_INT | CTLFLAG_RDTUN | CTLFLAG_MPSAFE, softc, 0,
+	    bnxt_set_cagr_tick_res, "I", "CAGR tick resolution");
 	SYSCTL_ADD_U32(ctx, children, OID_AUTO, "flags", CTLFLAG_RD,
 		&softc->flags, 0, "flags");
 	SYSCTL_ADD_U64(ctx, children, OID_AUTO, "fw_cap", CTLFLAG_RD,
diff --git a/sys/dev/bnxt/bnxt_en/if_bnxt.c b/sys/dev/bnxt/bnxt_en/if_bnxt.c
index 044ab619c399..188311b2d7d4 100644
--- a/sys/dev/bnxt/bnxt_en/if_bnxt.c
+++ b/sys/dev/bnxt/bnxt_en/if_bnxt.c
@@ -2065,6 +2065,26 @@ static inline void __bnxt_map_fw_health_reg(struct bnxt_softc *bp, u32 reg)
 	    BNXT_HWRM_BAR_IDX, reg & BNXT_GRC_BASE_MASK);
 }
 
+static void
+bnxt_set_cqcoal_tick_res(struct bnxt_softc *bp)
+{
+	u32 val = 0;
+	u32 cagr_addr = BNXT_GRCPF_REG_WINDOW_BASE_OUT + BNXT_CAGR_CQCOAL_OFFSET;
+
+	if (!BNXT_CHIP_P7(bp))
+		return;
+
+	writel_fbsd(bp, BNXT_GRCPF_REG_WINDOW_BASE_OUT, BNXT_HWRM_BAR_IDX,
+	    BNXT_CAGR_NQAGG_MAXTIMER);
+	val = readl_fbsd(bp, cagr_addr, BNXT_HWRM_BAR_IDX);
+
+	/* Clear out CAGR tick resolution bits(16-19), before writing new value */
+	val &= ~(0xf << BNXT_CAGR_TICK_RES_OFFSET);
+
+	writel_fbsd(bp, cagr_addr, BNXT_HWRM_BAR_IDX,
+	    (val | bp->cagr_tick_res << BNXT_CAGR_TICK_RES_OFFSET));
+}
+
 static int bnxt_map_fw_health_regs(struct bnxt_softc *bp)
 {
 	struct bnxt_fw_health *fw_health = bp->fw_health;
@@ -2203,6 +2223,12 @@ static bool bnxt_fw_reset_timeout(struct bnxt_softc *bp)
 static int bnxt_open(struct bnxt_softc *bp)
 {
 	int rc = 0;
+
+	/* A function/chip reset drops the CAGR tick-resolution register
+	 * programmed in bnxt_attach_pre(); restore it before we start
+	 * relying on interrupt coalescing again. */
+	bnxt_set_cqcoal_tick_res(bp);
+
 	if (BNXT_PF(bp))
 		rc = bnxt_hwrm_nvm_get_dev_info(bp, &bp->nvm_info->mfg_id,
 			&bp->nvm_info->device_id, &bp->nvm_info->sector_size,
@@ -2886,6 +2912,10 @@ bnxt_attach_pre(if_ctx_t ctx)
 	    HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_IPV6 |
 	    HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_TCP_IPV6 |
 	    HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_UDP_IPV6;
+
+	if (BNXT_CHIP_P7(softc))
+		softc->cagr_tick_res = BNXT_CAGR_TICK_RES_DEFAULT;
+
 	rc = bnxt_create_config_sysctls_pre(softc);
 	if (rc)
 		goto failed;
@@ -2930,6 +2960,8 @@ bnxt_attach_pre(if_ctx_t ctx)
 			snprintf(softc->board_partno, sizeof(softc->board_partno), "%s", part_num);
 	}
 
+	bnxt_set_cqcoal_tick_res(softc);
+
 	return (rc);