git: e35533457530 - main - igc: synchronize interrupt moderation state
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sun, 26 Jul 2026 01:01:16 UTC
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