aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Bowling <kbowling@FreeBSD.org>2026-07-25 10:43:28 +0000
committerKevin Bowling <kbowling@FreeBSD.org>2026-07-31 00:50:43 +0000
commita1edeb474b1e67e2bd31d7dc11f488888a28e5c8 (patch)
treea03c901d4eb21e45e2b8d5d9b7cbb2b33aa7ec40
parent89a88e4f2ddc34221105a2d82407ce4337322808 (diff)
e1000: fix 82574 MSI-X interrupt throttling
em_newitr() and the per-queue interrupt_rate sysctl both tested que->msix to decide whether an 82574 is running in MSI-X mode. 0 is a valid MSI-X vector so queue 0 was misclassified as legacy/MSI. Test sc->intr_type == IFLIB_INTR_MSIX instead. While here, index the tx EITR read by tque->msix rather than tque->me so it matches the register em_newitr() actually writes; the two differ once tx_num_queues exceeds rx_num_queues. Also seed que->itr_setting in em_initialize_receive_unit() with the rate the hardware was just programmed with. Otherwise an itr_setting left over from AIM across an interface re-init makes the change detection in em_newitr() suppress the write that would restore it, leaving the hardware at the default rate while software believes otherwise. Fixes: 3e501ef89667 ("e1000: Re-add AIM") (cherry picked from commit 941113a0097ea047bd493f7f78b384718249779d)
-rw-r--r--sys/dev/e1000/if_em.c24
1 files changed, 20 insertions, 4 deletions
diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c
index 248d14f5974c..0253ff95a46a 100644
--- a/sys/dev/e1000/if_em.c
+++ b/sys/dev/e1000/if_em.c
@@ -1781,7 +1781,8 @@ em_set_next_itr:
if (newitr != que->itr_setting) {
que->itr_setting = newitr;
- if (hw->mac.type == e1000_82574 && que->msix) {
+ if (hw->mac.type == e1000_82574 &&
+ sc->intr_type == IFLIB_INTR_MSIX) {
E1000_WRITE_REG(hw,
E1000_EITR_82574(que->msix),
que->itr_setting);
@@ -3802,6 +3803,19 @@ em_initialize_receive_unit(if_ctx_t ctx)
/* Set the default interrupt throttling rate */
E1000_WRITE_REG(hw, E1000_ITR,
EM_INTS_TO_ITR(em_max_interrupt_rate));
+
+ /*
+ * The 82574 MSI-X EITR registers are programmed
+ * with the same value further below. Either way
+ * the hardware now holds the default rate, so seed
+ * the software copy to match; otherwise a stale
+ * itr_setting left over from AIM makes em_newitr()
+ * skip the write that would restore it.
+ */
+ for (i = 0, que = sc->rx_queues; i < sc->rx_num_queues;
+ i++, que++)
+ que->itr_setting =
+ EM_INTS_TO_ITR(em_max_interrupt_rate);
}
/* XXX TEMPORARY WORKAROUND: on some systems with 82573
@@ -4857,8 +4871,9 @@ em_sysctl_interrupt_rate_handler(SYSCTL_HANDLER_ARGS)
hw = &tque->sc->hw;
if (hw->mac.type >= igb_mac_min)
reg = E1000_READ_REG(hw, E1000_EITR(tque->me));
- else if (hw->mac.type == e1000_82574 && tque->msix)
- reg = E1000_READ_REG(hw, E1000_EITR_82574(tque->me));
+ else if (hw->mac.type == e1000_82574 &&
+ tque->sc->intr_type == IFLIB_INTR_MSIX)
+ reg = E1000_READ_REG(hw, E1000_EITR_82574(tque->msix));
else
reg = E1000_READ_REG(hw, E1000_ITR);
} else {
@@ -4866,7 +4881,8 @@ em_sysctl_interrupt_rate_handler(SYSCTL_HANDLER_ARGS)
hw = &rque->sc->hw;
if (hw->mac.type >= igb_mac_min)
reg = E1000_READ_REG(hw, E1000_EITR(rque->msix));
- else if (hw->mac.type == e1000_82574 && rque->msix)
+ else if (hw->mac.type == e1000_82574 &&
+ rque->sc->intr_type == IFLIB_INTR_MSIX)
reg = E1000_READ_REG(hw,
E1000_EITR_82574(rque->msix));
else