Skip to content

Commit 915c628

Browse files
committed
igb: Report 82580 memory ECC errors
82580 exposes clear-on-read, saturating corrected error counters for the receive and transmit packet buffers. Its two PCIe command memories expose RW1C indications for uncorrectable ECC errors. Sample the packet buffer counters and PCIe indications from the regular hardware statistics update. Fatal recovery samples the PCIe indications from the serialized admin path rather than the interrupt filter. Thus, either the regular statistics pass or recovery reads and clears each indication, but they cannot both account it. Also preserve indications observed while initialization is completing. Expose the exact packet buffer error total and observed PCIe command memory indications under the memory_errors sysctl node. Multiple PCIe errors between samples can collapse into one indication per memory. Validated on an Intel I340-T2 (82580, revision 1). A clean boot and three down/up cycles left the packet-buffer, PCIe, and region-specific counters at zero. Synthetic ICS.FER events advanced fatal_unknown and fatal_resets exactly once on the targeted function without changing the sibling or ECC counters. The 82580 datasheet exposes no ECC or parity error injection register, so corrected packet buffer and PCIe ECC accounting could not be forced independently. MFC after: 2 weeks Sponsored by: BBOX.io
1 parent 5e56a1f commit 915c628

3 files changed

Lines changed: 58 additions & 12 deletions

File tree

sys/dev/e1000/e1000_defines.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,7 @@
553553
#define E1000_PCIEECCSTS_82580_ERROR_MASK 0x00000003
554554
#define E1000_LANPERRSTS_82580_ERROR_MASK 0x00007FFF
555555
#define E1000_PBECCSTS_82580_ECC_ENABLE 0x00010000
556+
#define E1000_PBECCSTS_82580_CORR_CNT_MASK 0x000000FF
556557

557558
/* 82576 uses PEIND directly rather than the later four-region layout. */
558559
#define E1000_PEIND_82576_NONFATAL_MASK 0x00000007

sys/dev/e1000/if_em.c

Lines changed: 56 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,8 @@ static void em_finish_fatal_error_reset(struct e1000_softc *);
462462
static void em_configure_peind_memory_errors(struct e1000_softc *);
463463
static void em_configure_82575_memory_errors(struct e1000_softc *);
464464
static void em_configure_82580_memory_errors(struct e1000_softc *);
465+
static void em_update_82580_ecc_stats(struct e1000_softc *, u32, u32,
466+
u32);
465467
static void em_if_multi_set(if_ctx_t);
466468
static void em_if_update_admin_status(if_ctx_t);
467469
static void em_if_debug(if_ctx_t);
@@ -2303,10 +2305,11 @@ em_configure_82580_memory_errors(struct e1000_softc *sc)
23032305
em_clear_82580_memory_error_status(hw, E1000_DRPARS_82580);
23042306
em_clear_82580_memory_error_status(hw, E1000_DDPARS_82580);
23052307
em_clear_82580_memory_error_status(hw, E1000_PCIEERRSTS);
2306-
em_clear_82580_memory_error_status(hw, E1000_PCIEECCSTS);
23072308
(void)E1000_READ_REG(hw, E1000_LANPERRSTS);
2308-
(void)E1000_READ_REG(hw, E1000_RPBECCSTS);
2309-
(void)E1000_READ_REG(hw, E1000_TPBECCSTS);
2309+
em_update_82580_ecc_stats(sc,
2310+
E1000_READ_REG(hw, E1000_RPBECCSTS),
2311+
E1000_READ_REG(hw, E1000_TPBECCSTS),
2312+
E1000_READ_REG(hw, E1000_PCIEECCSTS));
23102313
E1000_WRITE_REG(hw, E1000_RPBECCSTS,
23112314
E1000_PBECCSTS_82580_ECC_ENABLE);
23122315
E1000_WRITE_REG(hw, E1000_TPBECCSTS,
@@ -2434,6 +2437,21 @@ em_fatal_error_intr_mask(struct e1000_softc *sc)
24342437
return (em_memory_error_intr_mask(&sc->hw));
24352438
}
24362439

2440+
static void
2441+
em_update_82580_ecc_stats(struct e1000_softc *sc, u32 rpbeccsts,
2442+
u32 tpbeccsts, u32 pcieeccsts)
2443+
{
2444+
u32 status;
2445+
2446+
sc->corrected_error_packet_buffer_count +=
2447+
(rpbeccsts & E1000_PBECCSTS_82580_CORR_CNT_MASK) +
2448+
(tpbeccsts & E1000_PBECCSTS_82580_CORR_CNT_MASK);
2449+
status = pcieeccsts & E1000_PCIEECCSTS_82580_ERROR_MASK;
2450+
sc->uncorrected_error_pcie_count += bitcount32(status);
2451+
if (status != 0)
2452+
E1000_WRITE_REG(&sc->hw, E1000_PCIEECCSTS, status);
2453+
}
2454+
24372455
static void
24382456
em_update_82575_ecc_stats(struct e1000_softc *sc, u32 pbeccsts,
24392457
u32 rdhests, u32 tdhests)
@@ -2625,8 +2643,7 @@ static void
26252643
em_handle_fatal_error_intr(struct e1000_softc *sc, u32 icr)
26262644
{
26272645
struct e1000_hw *hw;
2628-
u32 dma_host, dma_rx, dma_tx, error_mask, lanerr, pcieecc;
2629-
u32 pcieerr, peind;
2646+
u32 dma_host, dma_rx, dma_tx, error_mask, lanerr, pcieerr, peind;
26302647

26312648
error_mask = em_memory_error_intr_mask(&sc->hw);
26322649
if (!em_has_memory_errors(&sc->hw) ||
@@ -2657,7 +2674,6 @@ em_handle_fatal_error_intr(struct e1000_softc *sc, u32 icr)
26572674
E1000_PEIND_FATAL_MASK;
26582675
pcieerr = E1000_READ_REG(hw, E1000_PCIEERRSTS) &
26592676
em_pcie_fatal_error_mask(hw);
2660-
pcieecc = 0;
26612677
dma_host = 0;
26622678
if (em_has_82580_memory_errors(hw)) {
26632679
/*
@@ -2667,8 +2683,6 @@ em_handle_fatal_error_intr(struct e1000_softc *sc, u32 icr)
26672683
* status registers.
26682684
*/
26692685
peind &= E1000_PEIND_MNG_PARITY_FATAL;
2670-
pcieecc = E1000_READ_REG(hw, E1000_PCIEECCSTS) &
2671-
E1000_PCIEECCSTS_82580_ERROR_MASK;
26722686
dma_tx = E1000_READ_REG(hw, E1000_DTPARS_82580);
26732687
dma_rx = E1000_READ_REG(hw, E1000_DRPARS_82580);
26742688
dma_host = E1000_READ_REG(hw,
@@ -2688,15 +2702,14 @@ em_handle_fatal_error_intr(struct e1000_softc *sc, u32 icr)
26882702
lanerr = E1000_READ_REG(hw, E1000_LANPERRSTS) &
26892703
E1000_LANPERRSTS_RETX_BUF;
26902704
}
2691-
if (pcieerr != 0 || pcieecc != 0)
2705+
if (pcieerr != 0)
26922706
peind |= E1000_PEIND_PCIE_PARITY_FATAL;
26932707
if (lanerr != 0)
26942708
peind |= E1000_PEIND_LANPORT_PARITY_FATAL;
26952709
if (dma_tx != 0 || dma_rx != 0 || dma_host != 0)
26962710
peind |= E1000_PEIND_DMA_PARITY_FATAL;
26972711
sc->fatal_error_peind = peind;
26982712
sc->fatal_error_pcie = pcieerr;
2699-
sc->fatal_error_pcie_ecc = pcieecc;
27002713
sc->fatal_error_lan = lanerr;
27012714
sc->fatal_error_dma_tx = dma_tx;
27022715
sc->fatal_error_dma_rx = dma_rx;
@@ -2710,7 +2723,7 @@ em_handle_fatal_error_intr(struct e1000_softc *sc, u32 icr)
27102723
static bool
27112724
em_handle_fatal_error_admin(struct e1000_softc *sc)
27122725
{
2713-
u32 error_mask, peind;
2726+
u32 error_mask, pcieecc, peind;
27142727
bool reset_required;
27152728

27162729
if (!atomic_cmpset_acq_32(&sc->fatal_error_state,
@@ -2761,6 +2774,20 @@ em_handle_fatal_error_admin(struct e1000_softc *sc)
27612774
"requesting reset\n", peind);
27622775
} else {
27632776
peind = sc->fatal_error_peind;
2777+
if (em_has_82580_memory_errors(&sc->hw)) {
2778+
pcieecc = E1000_READ_REG(&sc->hw,
2779+
E1000_PCIEECCSTS) &
2780+
E1000_PCIEECCSTS_82580_ERROR_MASK;
2781+
sc->fatal_error_pcie_ecc |= pcieecc;
2782+
if (pcieecc != 0) {
2783+
peind |= E1000_PEIND_PCIE_PARITY_FATAL;
2784+
sc->fatal_error_peind = peind;
2785+
}
2786+
em_update_82580_ecc_stats(sc,
2787+
E1000_READ_REG(&sc->hw, E1000_RPBECCSTS),
2788+
E1000_READ_REG(&sc->hw, E1000_TPBECCSTS),
2789+
pcieecc);
2790+
}
27642791
if (peind & E1000_PEIND_LANPORT_PARITY_FATAL)
27652792
sc->fatal_error_lan_count++;
27662793
if (peind & E1000_PEIND_MNG_PARITY_FATAL)
@@ -2843,6 +2870,9 @@ em_handle_fatal_error_admin(struct e1000_softc *sc)
28432870
* PCIe traffic for a fatal error in any host-owned region, so use the same
28442871
* order for every 82580 recovery. This differs from the normal reset path,
28452872
* which disables the bus master first.
2873+
*
2874+
* Indications that relatch after admin accounting are discarded during
2875+
* reset; sticky bits cannot distinguish them from the saved event.
28462876
*/
28472877
static void
28482878
em_prepare_fatal_error_reset(struct e1000_softc *sc)
@@ -6587,6 +6617,11 @@ em_update_stats_counters(struct e1000_softc *sc)
65876617
E1000_READ_REG(&sc->hw, E1000_TDHESTS_82575));
65886618
else if (em_has_82576_memory_errors(&sc->hw))
65896619
em_update_82576_ecc_stats(sc);
6620+
else if (em_has_82580_memory_errors(&sc->hw))
6621+
em_update_82580_ecc_stats(sc,
6622+
E1000_READ_REG(&sc->hw, E1000_RPBECCSTS),
6623+
E1000_READ_REG(&sc->hw, E1000_TPBECCSTS),
6624+
E1000_READ_REG(&sc->hw, E1000_PCIEECCSTS));
65906625
else if (em_has_i350_memory_errors(&sc->hw))
65916626
em_update_i350_ecc_stats(sc);
65926627
else if (em_has_i210_memory_errors(&sc->hw))
@@ -7101,7 +7136,16 @@ em_add_hw_stats(struct e1000_softc *sc)
71017136
"fatal_unknown", CTLFLAG_RD,
71027137
&sc->fatal_error_unknown_count,
71037138
"Fatal memory errors without a reported region");
7104-
if (em_has_i210_memory_errors(&sc->hw)) {
7139+
if (em_has_82580_memory_errors(&sc->hw)) {
7140+
SYSCTL_ADD_UQUAD(ctx, memerr_list, OID_AUTO,
7141+
"corrected_packet_buffer", CTLFLAG_RD,
7142+
&sc->corrected_error_packet_buffer_count,
7143+
"Corrected packet-buffer ECC errors");
7144+
SYSCTL_ADD_UQUAD(ctx, memerr_list, OID_AUTO,
7145+
"uncorrected_pcie", CTLFLAG_RD,
7146+
&sc->uncorrected_error_pcie_count,
7147+
"Uncorrected PCIe command-memory ECC indications");
7148+
} else if (em_has_i210_memory_errors(&sc->hw)) {
71057149
SYSCTL_ADD_UQUAD(ctx, memerr_list, OID_AUTO,
71067150
"corrected_dma", CTLFLAG_RD,
71077151
&sc->corrected_error_dma_count,

sys/dev/e1000/if_em.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,7 @@ struct e1000_softc {
648648
u64 corrected_error_packet_buffer_count;
649649
u64 uncorrected_error_packet_buffer_count;
650650
u64 uncorrected_error_dma_count;
651+
u64 uncorrected_error_pcie_count;
651652

652653
#ifdef PCI_IOV
653654
struct igb_vf *vfs;

0 commit comments

Comments
 (0)