git: e35533457530 - main - igc: synchronize interrupt moderation state

Kevin Bowling <[email protected]>
Newsgroups gmane.os.freebsd.devel.cvs.src
Message-ID <6a655c5c.328a2.39d16193__47914.2149140657$1785027785$gmane$org@gitrepo.freebsd.org>
The branch main has been updated by kbowling:

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

commit e35533457530bb9db655e6137c2eea790e18b97b
Author:     Kevin Bowling <[email protected]>
AuthorDate: 2026-07-25 23:58:58 +0000
Commit:     Kevin Bowling <[email protected]>
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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.