git: 0ea53a7123ff - main - e1000: Report corrected I210 and I211 ECC errors
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sun, 16 Aug 2026 09:19:39 UTC
The branch main has been updated by kbowling:
URL: https://cgit.FreeBSD.org/src/commit/?id=0ea53a7123ffc1ea11daa748e7148ac8413fd2de
commit 0ea53a7123ffc1ea11daa748e7148ac8413fd2de
Author: Kevin Bowling <kbowling@FreeBSD.org>
AuthorDate: 2026-08-12 18:34:15 +0000
Commit: Kevin Bowling <kbowling@FreeBSD.org>
CommitDate: 2026-08-16 09:18:18 +0000
e1000: Report corrected I210 and I211 ECC errors
I210 and I211 do not interrupt for corrected internal ECC errors.
Instead, the DMA packet-buffer and PCIe memories expose sticky status
bits in PBECCSTS and PCIEECCSTS.
Sample these bits with the regular hardware statistics update, preserve
the I210/I211 PBECCSTS enable state while clearing its RW1C indication,
and expose separate counters for the DMA packet buffer, PCIe transmit
data, and PCIe retry buffer.
The counters represent observed indications rather than exact error
counts because multiple corrections between samples collapse into one
sticky status bit.
Hardware validation used an I210 revision 3. Unlike I225 and I226, the
published I210/I211 register definitions do not expose self-clearing
injectors for these corrected ECC memories. The three counter sysctls
were present and remained zero under line-rate traffic and three fatal
LAN parity recoveries. PBECCSTS.ECC_ENABLE remained set after every
reset. Actual corrected-error accounting was therefore not injected.
MFC after: 2 weeks
Sponsored by: BBOX.io
---
sys/dev/e1000/if_em.c | 40 ++++++++++++++++++++++++++++++++++++++++
sys/dev/e1000/if_em.h | 3 +++
2 files changed, 43 insertions(+)
diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c
index 4cc5dbd7b7ee..1d9ac22bb667 100644
--- a/sys/dev/e1000/if_em.c
+++ b/sys/dev/e1000/if_em.c
@@ -2229,6 +2229,32 @@ em_update_pch_ecc_stats(struct e1000_softc *sc, u32 pbeccsts)
E1000_PBECCSTS_UNCORR_ERR_CNT_SHIFT;
}
+static void
+em_update_i210_ecc_stats(struct e1000_softc *sc)
+{
+ struct e1000_hw *hw;
+ u32 pbeccsts, pcieeccsts;
+
+ hw = &sc->hw;
+ pbeccsts = E1000_READ_REG(hw, E1000_PBECCSTS_I210);
+ if (pbeccsts & E1000_PBECCSTS_I210_CORR_ERR) {
+ sc->corrected_error_dma_count++;
+ /* Preserve the enable bit while clearing the RW1C status. */
+ E1000_WRITE_REG(hw, E1000_PBECCSTS_I210,
+ pbeccsts & (E1000_PBECCSTS_I210_ECC_ENABLE |
+ E1000_PBECCSTS_I210_CORR_ERR));
+ }
+
+ pcieeccsts = E1000_READ_REG(hw, E1000_PCIEECCSTS) &
+ E1000_PCIEECCSTS_CORR_MASK;
+ if (pcieeccsts & E1000_PCIEECCSTS_TX_WR_DATA)
+ sc->corrected_error_pcie_tx_data_count++;
+ if (pcieeccsts & E1000_PCIEECCSTS_RETRY_BUF)
+ sc->corrected_error_pcie_retry_count++;
+ if (pcieeccsts != 0)
+ E1000_WRITE_REG(hw, E1000_PCIEECCSTS, pcieeccsts);
+}
+
/*
* Fatal internal-memory errors stop part or all of the MAC. Capture the
* read-clear indication before handing recovery to the iflib admin task.
@@ -5957,6 +5983,8 @@ em_update_stats_counters(struct e1000_softc *sc)
if (em_has_pch_ecc(&sc->hw))
em_update_pch_ecc_stats(sc,
E1000_READ_REG(&sc->hw, E1000_PBECCSTS));
+ else if (em_has_i210_memory_errors(&sc->hw))
+ em_update_i210_ecc_stats(sc);
}
static bool
@@ -6412,6 +6440,18 @@ em_add_hw_stats(struct e1000_softc *sc)
"fatal_unknown", CTLFLAG_RD,
&sc->fatal_error_unknown_count,
"Fatal memory errors without a reported region");
+ SYSCTL_ADD_UQUAD(ctx, memerr_list, OID_AUTO,
+ "corrected_dma", CTLFLAG_RD,
+ &sc->corrected_error_dma_count,
+ "Corrected DMA memory error indications");
+ SYSCTL_ADD_UQUAD(ctx, memerr_list, OID_AUTO,
+ "corrected_pcie_tx_data", CTLFLAG_RD,
+ &sc->corrected_error_pcie_tx_data_count,
+ "Corrected PCIe transmit-data memory indications");
+ SYSCTL_ADD_UQUAD(ctx, memerr_list, OID_AUTO,
+ "corrected_pcie_retry", CTLFLAG_RD,
+ &sc->corrected_error_pcie_retry_count,
+ "Corrected PCIe retry-buffer memory indications");
}
}
diff --git a/sys/dev/e1000/if_em.h b/sys/dev/e1000/if_em.h
index 1d1587331555..0dd413dafcc8 100644
--- a/sys/dev/e1000/if_em.h
+++ b/sys/dev/e1000/if_em.h
@@ -635,6 +635,9 @@ struct e1000_softc {
u64 fatal_error_pcie_count;
u64 fatal_error_dma_count;
u64 fatal_error_unknown_count;
+ u64 corrected_error_dma_count;
+ u64 corrected_error_pcie_tx_data_count;
+ u64 corrected_error_pcie_retry_count;
u64 corrected_error_packet_buffer_count;
u64 uncorrected_error_packet_buffer_count;