Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 26 Jul 2026 01:01:16 +0000
From:      Kevin Bowling <kbowling@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: e35533457530 - main - igc: synchronize interrupt moderation state
Message-ID:  <6a655c5c.328a2.39d16193@gitrepo.freebsd.org>

index | next in thread | raw e-mail

The branch main has been updated by kbowling:

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

commit e35533457530bb9db655e6137c2eea790e18b97b
Author:     Kevin Bowling <kbowling@FreeBSD.org>
AuthorDate: 2026-07-25 23:58:58 +0000
Commit:     Kevin Bowling <kbowling@FreeBSD.org>
CommitDate: 2026-07-26 01:00:02 +0000

    igc: synchronize interrupt moderation state
    
    Keep the saved EITR value synchronized with hardware across
    reinitialization.  Correct EITR encoding, decoding, and MSI-X register
    selection, and reject nonpositive fallback rates.
    
    Apply the packet-buffer fallback without permanently disabling AIM.
    
    MFC after:      1 week
---
 sys/dev/igc/if_igc.c | 35 +++++++++++++++++++++++++----------
 sys/dev/igc/if_igc.h |  6 ++++--
 2 files changed, 29 insertions(+), 12 deletions(-)

diff --git a/sys/dev/igc/if_igc.c b/sys/dev/igc/if_igc.c
index d0e9ad3b7a8d..3e4c0228619a 100644
--- a/sys/dev/igc/if_igc.c
+++ b/sys/dev/igc/if_igc.c
@@ -165,6 +165,7 @@ static int	igc_sysctl_eee(SYSCTL_HANDLER_ARGS);
 static int	igc_get_regs(SYSCTL_HANDLER_ARGS);
 
 static void	igc_configure_queues(struct igc_softc *);
+static void	igc_initialize_interrupt_rate(struct igc_softc *);
 
 
 /*********************************************************************
@@ -469,6 +470,13 @@ igc_if_attach_pre(if_ctx_t ctx)
 	dev = iflib_get_dev(ctx);
 	sc = iflib_get_softc(ctx);
 
+	if (igc_max_interrupt_rate <= 0) {
+		device_printf(dev,
+		    "Invalid max_interrupt_rate %d; using default %d\n",
+		    igc_max_interrupt_rate, IGC_INTS_DEFAULT);
+		igc_max_interrupt_rate = IGC_INTS_DEFAULT;
+	}
+
 	sc->ctx = sc->osdep.ctx = ctx;
 	sc->dev = sc->osdep.dev = dev;
 	scctx = sc->shared = iflib_get_softc_ctx(ctx);
@@ -880,6 +888,7 @@ igc_if_init(if_ctx_t ctx)
 
 	if (sc->intr_type == IFLIB_INTR_MSIX) /* Set up queue routing */
 		igc_configure_queues(sc);
+	igc_initialize_interrupt_rate(sc);
 
 	/* this clears any pending interrupts */
 	IGC_READ_REG(&sc->hw, IGC_ICR);
@@ -990,7 +999,6 @@ igc_neweitr(struct igc_softc *sc, struct igc_rx_queue *que,
 		/* Want at least enough packet buffer for two frames to AIM */
 		if (sc->shared->isc_max_frame_size * 2 > (sc->pba << 10)) {
 			neweitr = igc_max_interrupt_rate;
-			sc->enable_aim = 0;
 			goto igc_set_next_eitr;
 		}
 
@@ -1640,7 +1648,7 @@ igc_configure_queues(struct igc_softc *sc)
 	struct igc_hw *hw = &sc->hw;
 	struct igc_rx_queue *rx_que;
 	struct igc_tx_queue *tx_que;
-	u32 ivar = 0, newitr = 0;
+	u32 ivar = 0;
 
 	/* First turn on RSS capability */
 	IGC_WRITE_REG(hw, IGC_GPIE,
@@ -1683,18 +1691,25 @@ igc_configure_queues(struct igc_softc *sc)
 	sc->link_mask = 1 << sc->linkvec;
 	IGC_WRITE_REG(hw, IGC_IVAR_MISC, ivar);
 
-	/* Set the starting interrupt rate */
-	if (igc_max_interrupt_rate > 0)
-		newitr = IGC_INTS_TO_EITR(igc_max_interrupt_rate);
+	return;
+}
+
+static void
+igc_initialize_interrupt_rate(struct igc_softc *sc)
+{
+	struct igc_hw *hw = &sc->hw;
+	struct igc_rx_queue *rx_que;
+	u32 newitr;
 
+	newitr = IGC_INTS_TO_EITR(igc_max_interrupt_rate);
 	newitr |= IGC_EITR_CNT_IGNR;
 
 	for (int i = 0; i < sc->rx_num_queues; i++) {
 		rx_que = &sc->rx_queues[i];
-		IGC_WRITE_REG(hw, IGC_EITR(rx_que->msix), newitr);
+		rx_que->eitr_setting = newitr;
+		IGC_WRITE_REG(hw, IGC_EITR(rx_que->msix),
+		    rx_que->eitr_setting);
 	}
-
-	return;
 }
 
 static void
@@ -2693,7 +2708,7 @@ igc_sysctl_interrupt_rate_handler(SYSCTL_HANDLER_ARGS)
 	if (tx) {
 		tque = oidp->oid_arg1;
 		hw = &tque->sc->hw;
-		reg = IGC_READ_REG(hw, IGC_EITR(tque->me));
+		reg = IGC_READ_REG(hw, IGC_EITR(tque->msix));
 	} else {
 		rque = oidp->oid_arg1;
 		hw = &rque->sc->hw;
@@ -2702,7 +2717,7 @@ igc_sysctl_interrupt_rate_handler(SYSCTL_HANDLER_ARGS)
 
 	usec = (reg & IGC_QVECTOR_MASK);
 	if (usec > 0)
-		rate = IGC_INTS_TO_EITR(usec);
+		rate = IGC_EITR_TO_INTS(usec);
 	else
 		rate = 0;
 
diff --git a/sys/dev/igc/if_igc.h b/sys/dev/igc/if_igc.h
index d8d5d5b251fa..4af08e03fedb 100644
--- a/sys/dev/igc/if_igc.h
+++ b/sys/dev/igc/if_igc.h
@@ -171,8 +171,10 @@
 #define IGC_EITR_DIVIDEND	1000000
 #define IGC_EITR_SHIFT		2
 #define IGC_QVECTOR_MASK	0x7FFC
-#define IGC_INTS_TO_EITR(i)	(((IGC_EITR_DIVIDEND/i) & IGC_QVECTOR_MASK) << \
-				    IGC_EITR_SHIFT)
+#define IGC_INTS_TO_EITR(i)	\
+	(((IGC_EITR_DIVIDEND / (i)) << IGC_EITR_SHIFT) & IGC_QVECTOR_MASK)
+#define IGC_EITR_TO_INTS(i)	((IGC_EITR_DIVIDEND << IGC_EITR_SHIFT) / \
+					    ((i) & IGC_QVECTOR_MASK))
 
 /*
  * TDBA/RDBA should be aligned on 16 byte boundary. But TDLEN/RDLEN should be


home | help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6a655c5c.328a2.39d16193>