git: 6ef368a29b11 - main - e1000: synchronize interrupt moderation state
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sun, 26 Jul 2026 01:01:09 UTC
The branch main has been updated by kbowling:
URL: https://cgit.FreeBSD.org/src/commit/?id=6ef368a29b11ebc769e7929566809b75ae2c1e90
commit 6ef368a29b11ebc769e7929566809b75ae2c1e90
Author: Kevin Bowling <kbowling@FreeBSD.org>
AuthorDate: 2026-07-25 23:49:03 +0000
Commit: Kevin Bowling <kbowling@FreeBSD.org>
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