git: d7be8a3e2291 - main - e1000: Report PCH packet buffer ECC statistics

From: Kevin Bowling <kbowling_at_FreeBSD.org>
Date: Sun, 16 Aug 2026 09:00:18 UTC
The branch main has been updated by kbowling:

URL: https://cgit.FreeBSD.org/src/commit/?id=d7be8a3e229174bea06228b461da3b1825c6cc54

commit d7be8a3e229174bea06228b461da3b1825c6cc54
Author:     Kevin Bowling <kbowling@FreeBSD.org>
AuthorDate: 2026-08-12 18:30:08 +0000
Commit:     Kevin Bowling <kbowling@FreeBSD.org>
CommitDate: 2026-08-16 09:00:11 +0000

    e1000: Report PCH packet buffer ECC statistics
    
    PCH packet buffer ECC status contains read-clear byte counters for
    corrected and uncorrected errors.  Sample them with the regular
    hardware statistics update and account for the snapshot captured by
    the fatal error interrupt path.
    
    Expose the counters and the number of reset worthy interrupt
    indications under dev.em.N.memory_errors.  Keeping the reset counter
    separate also preserves evidence when another status reader wins the
    read-clear race.
    
    Hardware validation used an I219-LM.  Three documented ICS.ECCER
    injections advanced fatal_resets from zero to three, exactly once per
    reset.  corrected_packet_buffer and uncorrected_packet_buffer remained
    zero, as expected because ICS does not inject a memory error or alter
    PBECCSTS.
    
    MFC after:      2 weeks
    Sponsored by:   BBOX.io
---
 sys/dev/e1000/if_em.c | 36 ++++++++++++++++++++++++++++++++++++
 sys/dev/e1000/if_em.h |  2 ++
 2 files changed, 38 insertions(+)

diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c
index ce59a12df0de..eb4c17f78769 100644
--- a/sys/dev/e1000/if_em.c
+++ b/sys/dev/e1000/if_em.c
@@ -2187,6 +2187,17 @@ em_fatal_error_intr_mask(struct e1000_softc *sc)
 	return (0);
 }
 
+static void
+em_update_pch_ecc_stats(struct e1000_softc *sc, u32 pbeccsts)
+{
+
+	sc->corrected_error_packet_buffer_count +=
+	    pbeccsts & E1000_PBECCSTS_CORR_ERR_CNT_MASK;
+	sc->uncorrected_error_packet_buffer_count +=
+	    (pbeccsts & E1000_PBECCSTS_UNCORR_ERR_CNT_MASK) >>
+	    E1000_PBECCSTS_UNCORR_ERR_CNT_SHIFT;
+}
+
 /*
  * Descriptor-memory ECC errors stop the PCH MAC.  Capture the read-clear
  * status before handing recovery to the iflib admin task.
@@ -2220,6 +2231,7 @@ em_handle_fatal_error_admin(struct e1000_softc *sc)
 		return (atomic_load_acq_32(&sc->fatal_error_state) !=
 		    EM_FATAL_ERROR_NONE);
 
+	em_update_pch_ecc_stats(sc, sc->fatal_error_pbeccsts);
 	device_printf(sc->dev,
 	    "uncorrectable packet-buffer ECC error: PBECCSTS %#x; "
 	    "requesting reset\n", sc->fatal_error_pbeccsts);
@@ -5772,6 +5784,10 @@ em_update_stats_counters(struct e1000_softc *sc)
 		stats->tsctfc +=
 		E1000_READ_REG(&sc->hw, E1000_TSCTFC);
 	}
+
+	if (em_has_pch_ecc(&sc->hw))
+		em_update_pch_ecc_stats(sc,
+		    E1000_READ_REG(&sc->hw, E1000_PBECCSTS));
 }
 
 static bool
@@ -6184,6 +6200,26 @@ 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_pch_ecc(&sc->hw)) {
+		struct sysctl_oid *memerr_node;
+		struct sysctl_oid_list *memerr_list;
+
+		memerr_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO,
+		    "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 packet-buffer ECC errors");
+		SYSCTL_ADD_UQUAD(ctx, memerr_list, OID_AUTO,
+		    "corrected_packet_buffer", CTLFLAG_RD,
+		    &sc->corrected_error_packet_buffer_count,
+		    "Corrected packet-buffer ECC errors");
+		SYSCTL_ADD_UQUAD(ctx, memerr_list, OID_AUTO,
+		    "uncorrected_packet_buffer", CTLFLAG_RD,
+		    &sc->uncorrected_error_packet_buffer_count,
+		    "Uncorrected packet-buffer ECC errors");
+	}
 
 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "excess_coll",
 	    CTLFLAG_RD, &stats->ecol,
diff --git a/sys/dev/e1000/if_em.h b/sys/dev/e1000/if_em.h
index 0c6f59f3f576..b88cb8abefb5 100644
--- a/sys/dev/e1000/if_em.h
+++ b/sys/dev/e1000/if_em.h
@@ -627,6 +627,8 @@ struct e1000_softc {
 	u32			fatal_error_state;
 	u32			fatal_error_pbeccsts;
 	u64			fatal_error_reset_count;
+	u64			corrected_error_packet_buffer_count;
+	u64			uncorrected_error_packet_buffer_count;
 
 #ifdef PCI_IOV
 	struct igb_vf		*vfs;