git: aec0f1b85b54 - main - e1000: Report 82571 packet buffer ECC errors
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 20 Aug 2026 05:35:28 UTC
The branch main has been updated by kbowling:
URL: https://cgit.FreeBSD.org/src/commit/?id=aec0f1b85b54d14819747ed3364f366d21e76d88
commit aec0f1b85b54d14819747ed3364f366d21e76d88
Author: Kevin Bowling <kbowling@FreeBSD.org>
AuthorDate: 2026-08-16 07:11:57 +0000
Commit: Kevin Bowling <kbowling@FreeBSD.org>
CommitDate: 2026-08-20 05:33:54 +0000
e1000: Report 82571 packet buffer ECC errors
The 82571 PBA_ECC register contains a 12-bit count of packet buffer ECC
detections. The shared code enables single-bit correction, but neither
FreeBSD nor the DPDK base driver consumes the counter.
Sample it with the ordinary statistics timer, accumulate the value under
dev.em.N.memory_errors.detected_packet_buffer, and clear the hardware
counter while preserving correction and reserved register state. Do not
enable its shared interrupt: the register does not distinguish corrected
from uncorrectable events and does not provide a safe fatal recovery
policy.
Validated on a dual port 82571EB. Both functions reported zero after a
clean boot, and a controlled link down/up cycle left the counter at zero
while the management link recovered at 1 Gb/s without issue.
MFC after: 2 weeks
Sponsored by: BBOX.io
---
sys/dev/e1000/if_em.c | 54 ++++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 47 insertions(+), 7 deletions(-)
diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c
index f07f75100650..7e312399b132 100644
--- a/sys/dev/e1000/if_em.c
+++ b/sys/dev/e1000/if_em.c
@@ -2189,6 +2189,13 @@ em_has_pch_ecc(const struct e1000_hw *hw)
hw->mac.type < e1000_82575);
}
+static bool
+em_has_82571_ecc_stats(const struct e1000_hw *hw)
+{
+
+ return (hw->mac.type == e1000_82571);
+}
+
static bool
em_has_82575_memory_errors(const struct e1000_hw *hw)
{
@@ -2335,6 +2342,13 @@ em_has_memory_errors(const struct e1000_hw *hw)
return (em_memory_error_intr_mask(hw) != 0);
}
+static bool
+em_has_memory_error_stats(const struct e1000_hw *hw)
+{
+
+ return (em_has_82571_ecc_stats(hw) || em_has_memory_errors(hw));
+}
+
static u32
em_fatal_error_intr_mask(struct e1000_softc *sc)
{
@@ -2429,6 +2443,24 @@ em_update_pch_ecc_stats(struct e1000_softc *sc, u32 pbeccsts)
E1000_PBECCSTS_UNCORR_ERR_CNT_SHIFT;
}
+static void
+em_update_82571_ecc_stats(struct e1000_softc *sc)
+{
+ struct e1000_hw *hw;
+ u32 count, pba_ecc;
+
+ hw = &sc->hw;
+ pba_ecc = E1000_READ_REG(hw, E1000_PBA_ECC);
+ count = (pba_ecc & E1000_PBA_ECC_COUNTER_MASK) >>
+ E1000_PBA_ECC_COUNTER_SHIFT;
+ if (count == 0)
+ return;
+ sc->corrected_error_packet_buffer_count += count;
+ /* Preserve correction and reserved state while clearing statistics. */
+ E1000_WRITE_REG(hw, E1000_PBA_ECC,
+ pba_ecc | E1000_PBA_ECC_STAT_CLR);
+}
+
static void
em_update_i210_ecc_stats(struct e1000_softc *sc)
{
@@ -6380,7 +6412,9 @@ em_update_stats_counters(struct e1000_softc *sc)
E1000_READ_REG(&sc->hw, E1000_TSCTFC);
}
- if (em_has_pch_ecc(&sc->hw))
+ if (em_has_82571_ecc_stats(&sc->hw))
+ em_update_82571_ecc_stats(sc);
+ else if (em_has_pch_ecc(&sc->hw))
em_update_pch_ecc_stats(sc,
E1000_READ_REG(&sc->hw, E1000_PBECCSTS));
else if (em_has_82575_memory_errors(&sc->hw))
@@ -6806,7 +6840,7 @@ em_add_hw_stats(struct e1000_softc *sc)
SYSCTL_ADD_UQUAD(ctx, eee_list, OID_AUTO, "rx_lpi_count",
CTLFLAG_RD, &stats->rlpic, "RX LPI event count");
}
- if (em_has_memory_errors(&sc->hw)) {
+ if (em_has_memory_error_stats(&sc->hw)) {
struct sysctl_oid *memerr_node;
struct sysctl_oid_list *memerr_list;
@@ -6814,11 +6848,17 @@ em_add_hw_stats(struct e1000_softc *sc)
"memory_errors", CTLFLAG_RD | CTLFLAG_MPSAFE, NULL,
"Internal memory error indications");
memerr_list = SYSCTL_CHILDREN(memerr_node);
- SYSCTL_ADD_UQUAD(ctx, memerr_list, OID_AUTO,
- "fatal_resets", CTLFLAG_RD,
- &sc->fatal_error_reset_count,
- "Resets requested for fatal internal memory errors");
- if (em_has_pch_ecc(&sc->hw)) {
+ if (em_has_memory_errors(&sc->hw))
+ SYSCTL_ADD_UQUAD(ctx, memerr_list, OID_AUTO,
+ "fatal_resets", CTLFLAG_RD,
+ &sc->fatal_error_reset_count,
+ "Resets requested for fatal internal memory errors");
+ if (em_has_82571_ecc_stats(&sc->hw)) {
+ SYSCTL_ADD_UQUAD(ctx, memerr_list, OID_AUTO,
+ "detected_packet_buffer", CTLFLAG_RD,
+ &sc->corrected_error_packet_buffer_count,
+ "Detected packet-buffer ECC errors");
+ } else if (em_has_pch_ecc(&sc->hw)) {
SYSCTL_ADD_UQUAD(ctx, memerr_list, OID_AUTO,
"corrected_packet_buffer", CTLFLAG_RD,
&sc->corrected_error_packet_buffer_count,