git: 6ef368a29b11 - main - e1000: synchronize interrupt moderation state

Kevin Bowling <[email protected]>
Newsgroups gmane.os.freebsd.devel.cvs.src,gmane.os.freebsd.current.scm
Message-ID <[email protected]>
The branch main has been updated by kbowling:

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

commit 6ef368a29b11ebc769e7929566809b75ae2c1e90
Author:     Kevin Bowling <[email protected]>
AuthorDate: 2026-07-25 23:49:03 +0000
Commit:     Kevin Bowling <[email protected]>
CommitDate: 2026-07-26 01:00:02 +0000

    e1000: synchronize interrupt moderation state
    
    Keep the saved EITR and PBA values synchronized with hardware across
    reinitialization.  Correct EITR encoding, decoding, and MSI-X register
    selection, and reject nonpositive fallback rates.
    
    Treat only sub-gigabit links as sub-gigabit and apply the packet-buffer
    fallback without permanently disabling AIM.
    
    MFC after:      1 week
---
 sys/dev/e1000/if_em.c | 56 +++++++++++++++++++++++++++++++++------------------
 sys/dev/e1000/if_em.h |  6 ++++--
 2 files changed, 40 insertions(+), 22 deletions(-)

diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c
index 3fa5a7ed9a5b..40a5e9f75de9 100644
--- a/sys/dev/e1000/if_em.c
+++ b/sys/dev/e1000/if_em.c
@@ -496,6 +496,7 @@ static int	em_get_regs(SYSCTL_HANDLER_ARGS);
 
 static void	lem_smartspeed(struct e1000_softc *);
 static void	igb_configure_queues(struct e1000_softc *);
+static void	igb_initialize_interrupt_rate(struct e1000_softc *);
 static void	em_flush_desc_rings(struct e1000_softc *);
 
 
@@ -968,6 +969,13 @@ em_if_attach_pre(if_ctx_t ctx)
 	dev = iflib_get_dev(ctx);
 	sc = iflib_get_softc(ctx);
 
+	if (em_max_interrupt_rate <= 0) {
+		device_printf(dev,
+		    "Invalid max_interrupt_rate %d; using default %d\n",
+		    em_max_interrupt_rate, EM_INTS_DEFAULT);
+		em_max_interrupt_rate = EM_INTS_DEFAULT;
+	}
+
 	sc->ctx = sc->osdep.ctx = ctx;
 	sc->dev = sc->osdep.dev = dev;
 	scctx = sc->shared = iflib_get_softc_ctx(ctx);
@@ -1622,6 +1630,8 @@ em_if_init(if_ctx_t ctx)
 		/* Set up queue routing */
 		igb_configure_queues(sc);
 	}
+	if (sc->hw.mac.type >= igb_mac_min)
+		igb_initialize_interrupt_rate(sc);
 
 	/* this clears any pending interrupts */
 	E1000_READ_REG(&sc->hw, E1000_ICR);
@@ -1732,14 +1742,13 @@ em_newitr(struct e1000_softc *sc, struct em_rx_queue *que,
 		nextlatency = rxr->rx_nextlatency;
 
 		/* Use half default (4K) ITR if sub-gig */
-		if (sc->link_speed != 1000) {
+		if (sc->link_speed < SPEED_1000) {
 			newitr = EM_INTS_4K;
 			goto em_set_next_itr;
 		}
 		/* Want at least enough packet buffer for two frames to AIM */
 		if (sc->shared->isc_max_frame_size * 2 > (sc->pba << 10)) {
 			newitr = em_max_interrupt_rate;
-			sc->enable_aim = 0;
 			goto em_set_next_itr;
 		}
 
@@ -2627,7 +2636,7 @@ igb_configure_queues(struct e1000_softc *sc)
 	struct e1000_hw *hw = &sc->hw;
 	struct em_rx_queue *rx_que;
 	struct em_tx_queue *tx_que;
-	u32 tmp, ivar = 0, newitr = 0;
+	u32 tmp, ivar = 0;
 
 	/* First turn on RSS capability */
 	if (hw->mac.type != e1000_82575)
@@ -2751,22 +2760,28 @@ igb_configure_queues(struct e1000_softc *sc)
 		break;
 	}
 
-	/* Set the igb starting interrupt rate */
-	if (em_max_interrupt_rate > 0) {
-		newitr = IGB_INTS_TO_EITR(em_max_interrupt_rate);
+	return;
+}
 
-		if (hw->mac.type == e1000_82575)
-			newitr |= newitr << 16;
-		else
-			newitr |= E1000_EITR_CNT_IGNR;
+static void
+igb_initialize_interrupt_rate(struct e1000_softc *sc)
+{
+	struct e1000_hw *hw = &sc->hw;
+	struct em_rx_queue *rx_que;
+	u32 newitr;
 
-		for (int i = 0; i < sc->rx_num_queues; i++) {
-			rx_que = &sc->rx_queues[i];
-			E1000_WRITE_REG(hw, E1000_EITR(rx_que->msix), newitr);
-		}
-	}
+	newitr = IGB_INTS_TO_EITR(em_max_interrupt_rate);
+	if (hw->mac.type == e1000_82575)
+		newitr |= newitr << 16;
+	else
+		newitr |= E1000_EITR_CNT_IGNR;
 
-	return;
+	for (int i = 0; i < sc->rx_num_queues; i++) {
+		rx_que = &sc->rx_queues[i];
+		rx_que->itr_setting = newitr;
+		E1000_WRITE_REG(hw, E1000_EITR(rx_que->msix),
+		    rx_que->itr_setting);
+	}
 }
 
 static void
@@ -3300,9 +3315,10 @@ em_reset(if_ctx_t ctx)
 		hw->fc.refresh_time = 0xFFFF;
 		/* Jumbos need adjusted PBA */
 		if (if_getmtu(ifp) > ETHERMTU)
-			E1000_WRITE_REG(hw, E1000_PBA, 12);
+			pba = E1000_PBA_12K;
 		else
-			E1000_WRITE_REG(hw, E1000_PBA, 26);
+			pba = E1000_PBA_26K;
+		E1000_WRITE_REG(hw, E1000_PBA, pba);
 		break;
 	case e1000_82575:
 	case e1000_82576:
@@ -5017,7 +5033,7 @@ em_sysctl_interrupt_rate_handler(SYSCTL_HANDLER_ARGS)
 		tque = oidp->oid_arg1;
 		hw = &tque->sc->hw;
 		if (hw->mac.type >= igb_mac_min)
-			reg = E1000_READ_REG(hw, E1000_EITR(tque->me));
+			reg = E1000_READ_REG(hw, E1000_EITR(tque->msix));
 		else if (hw->mac.type == e1000_82574 &&
 		    tque->sc->intr_type == IFLIB_INTR_MSIX)
 			reg = E1000_READ_REG(hw, E1000_EITR_82574(tque->msix));
@@ -5044,7 +5060,7 @@ em_sysctl_interrupt_rate_handler(SYSCTL_HANDLER_ARGS)
 	} else {
 		usec = (reg & IGB_QVECTOR_MASK);
 		if (usec > 0)
-			rate = IGB_INTS_TO_EITR(usec);
+			rate = IGB_EITR_TO_INTS(usec);
 		else
 			rate = 0;
 	}
diff --git a/sys/dev/e1000/if_em.h b/sys/dev/e1000/if_em.h
index 007f5f42d5a7..594399498db3 100644
--- a/sys/dev/e1000/if_em.h
+++ b/sys/dev/e1000/if_em.h
@@ -253,8 +253,10 @@
 #define IGB_EITR_DIVIDEND	1000000
 #define IGB_EITR_SHIFT		2
 #define IGB_QVECTOR_MASK	0x7FFC
-#define IGB_INTS_TO_EITR(i)	(((IGB_EITR_DIVIDEND/i) & IGB_QVECTOR_MASK) << \
-				    IGB_EITR_SHIFT)
+#define IGB_INTS_TO_EITR(i)	\
+	(((IGB_EITR_DIVIDEND / (i)) << IGB_EITR_SHIFT) & IGB_QVECTOR_MASK)
+#define IGB_EITR_TO_INTS(i)	((IGB_EITR_DIVIDEND << IGB_EITR_SHIFT) / \
+					    ((i) & IGB_QVECTOR_MASK))
 
 #define IGB_LINK_ITR		2000
 #define I210_LINK_DELAY		1000
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.