From nobody Sun Aug 16 09:18:10 2026 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4hN9Nz0rGJz6nlcR for ; Sun, 16 Aug 2026 09:18:11 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "YR2" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4hN9Nz0VfVz3NfY for ; Sun, 16 Aug 2026 09:18:11 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1786871891; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=MH/See9e0MmTIDV4PiSlr/w102SwIKeoXv2Jex1VWrA=; b=cRL/JTHxsgQccflWGdpKlxj/rFQkFuJ32E9OATkSHU9yd/tpOtUZFtXs5LdCpvbd3onFRe +bdzmow9kD9p925bjlHaR1Ujm2iLO5amMzb/1AOw9YyVWMm6L8eC7AXrjiPftRiX3cf4PG UwWcFB8uI8PL/wwV6sO/BjZ2KtQtcgJnlRkwVHVY/L8jvSVtGPfBWD2yTBrPwrk9SJu83q aUP47Rd9XjrIzja4/8CEH0RE8LFt56nCwa8tCVdsGeNS++CQdATv4wSrV6EwegZlWMJCtT NFXzY7hKp/ulj7G7aPFlZRLxnLwzPPmZvyd/OHzjZ5lLqM+rHcHAaLXLpDDbWw== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1786871891; a=rsa-sha256; cv=none; b=adw4Nk+dghhymtontenDHgj+m4tK7H7g/GENahTG9lIBjORbYDCwWKgz1aGpJOafOVQGBU cnffb8BqY8TTcb+S+VUV3SN/5DzvCIh9G3b8RW5XoRqQSnf6Hfp2lCRD4PcUD/pHjgqkV8 JXai5lNoZ89u1ZlRyPmfALzyOU06QV2bH/N/SIWmbkysdfGJHqjWMktWoyfJtMOgVSz0VF zoxhDCmFzdyifmyI2WMh0nmxaY3oa/cxxaD9aFd1KCu9PP9JIW+Qaw2IPafvRLZNSuMGSL 5oruTR42MOme4VnoOAtW3KGpMAJH1yyLhmyHZeRB6JnamX4FidVf3umZsGNiBA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1786871891; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=MH/See9e0MmTIDV4PiSlr/w102SwIKeoXv2Jex1VWrA=; b=vP291jlu0PGQhq85tW4WF7JlHK9OlcThZd2fRs+xpD8OWCVJWo6Zjfwjihf5AZGBvTu8yC p4wn/ntkwpLZEJgeJ/lk3P7ht1Fx6JRJLrfPHp0V/2OqlwPy0TTh05TOzcdqss23t3H5aX ZGnAWlUxBjxY8GM09GmBi+1LheAPEheyBYo1u19xR8flaZSsTsmomnLbHCgJQI2wZY2joi N89ptdzNZhPeCtk1NQwAgg8nYmpgylhcYMFx3wh4XjaxO1X8EdLtBHE53IWIeneyPUat3y m5JQbfzdjpmlFyJA+cCY9UjTaTtd8nVgPT2vxvgvD0hthwlYHBec9mPNLGpIsQ== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4hN9Ny5x84z5TR for ; Sun, 16 Aug 2026 09:18:10 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 1dfee by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Sun, 16 Aug 2026 09:18:10 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Kevin Bowling Subject: git: 8d2d6284bb8c - main - e1000: Recover from I210 and I211 memory errors List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: kbowling X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 8d2d6284bb8ca168f6173c8836a40711b5f34e13 Auto-Submitted: auto-generated Date: Sun, 16 Aug 2026 09:18:10 +0000 Message-Id: <6a818052.1dfee.5f2c6e40@gitrepo.freebsd.org> The branch main has been updated by kbowling: URL: https://cgit.FreeBSD.org/src/commit/?id=8d2d6284bb8ca168f6173c8836a40711b5f34e13 commit 8d2d6284bb8ca168f6173c8836a40711b5f34e13 Author: Kevin Bowling AuthorDate: 2026-08-12 18:33:39 +0000 Commit: Kevin Bowling CommitDate: 2026-08-16 09:15:28 +0000 e1000: Recover from I210 and I211 memory errors I210 and I211 report uncorrectable internal memory errors through ICR.FER and identify the affected region in PEIND. Depending on the region, hardware stops transmit or all PCIe and DMA traffic until the port is reset and reinitialized. Enable FER and all regional indication masks. Discard indication state left by firmware before enabling reactions, capture the read-clear status in the interrupt filter, and keep the cause masked while recovery is pending. Report the affected regions and expose per-region indication counters. Management-only errors remain under firmware control. PCIe region parity errors require a different recovery order from the normal reset path. Assert the port-local CTRL.RST bit, wait at least 3 ms, verify reset completion, disable master requests, clear PCIEERRSTS, and then enter normal port reinitialization. Do not use the device-wide CTRL.DEV_RST sequence used by I225 and I226. Hardware validation used an I210 revision 3 and the self-clearing LANPERRINJ retransmit-buffer bit 9. It injected a real parity error without synthesizing interrupt or status state. Three injections in one boot produced the following result each time: Observed hardware status Result PEIND 0x1, LANPERRSTS 0x200 Reset and recovered fatal_lan advanced exactly once per injection. All tests completed without a panic or watchdog, and FER and the LAN parity masks remained enabled after every recovery. MFC after: 2 weeks Sponsored by: BBOX.io --- sys/dev/e1000/e1000_defines.h | 20 ++++ sys/dev/e1000/e1000_regs.h | 9 +- sys/dev/e1000/if_em.c | 244 +++++++++++++++++++++++++++++++++++++----- sys/dev/e1000/if_em.h | 8 ++ 4 files changed, 254 insertions(+), 27 deletions(-) diff --git a/sys/dev/e1000/e1000_defines.h b/sys/dev/e1000/e1000_defines.h index afa8bb4cce0d..fb2332462206 100644 --- a/sys/dev/e1000/e1000_defines.h +++ b/sys/dev/e1000/e1000_defines.h @@ -334,6 +334,7 @@ #define E1000_STATUS_LAN_INIT_DONE 0x00000200 /* Lan Init Compltn by NVM */ #define E1000_STATUS_PHYRA 0x00000400 /* PHY Reset Asserted */ #define E1000_STATUS_GIO_MASTER_ENABLE 0x00080000 /* Master request status */ +#define E1000_STATUS_RST_DONE 0x00200000 /* Device reset complete */ #define E1000_STATUS_PCI66 0x00000800 /* In 66Mhz slot */ #define E1000_STATUS_BUS64 0x00001000 /* In 64 bit slot */ #define E1000_STATUS_2P5_SKU 0x00001000 /* Val of 2.5GBE SKU strap */ @@ -527,6 +528,25 @@ #define E1000_PBECCSTS_UNCORR_ERR_CNT_SHIFT 8 #define E1000_PBECCSTS_ECC_ENABLE 0x00010000 +/* I210/I211 memory error status bits. */ +#define E1000_PEIND_LANPORT_PARITY_FATAL 0x00000001 +#define E1000_PEIND_MNG_PARITY_FATAL 0x00000002 +#define E1000_PEIND_PCIE_PARITY_FATAL 0x00000004 +#define E1000_PEIND_DMA_PARITY_FATAL 0x00000008 +#define E1000_PEIND_FATAL_MASK 0x0000000F +#define E1000_PEIND_HOST_FATAL_MASK (E1000_PEIND_LANPORT_PARITY_FATAL | \ + E1000_PEIND_PCIE_PARITY_FATAL | E1000_PEIND_DMA_PARITY_FATAL) + +#define E1000_PBECCSTS_I210_ECC_ENABLE 0x00000001 +#define E1000_PBECCSTS_I210_CORR_ERR 0x00000004 + +#define E1000_PCIEERRSTS_FATAL_MASK 0x00000078 +#define E1000_PCIEECCSTS_TX_WR_DATA 0x00000010 +#define E1000_PCIEECCSTS_RETRY_BUF 0x00000020 +#define E1000_PCIEECCSTS_CORR_MASK 0x00000030 + +#define E1000_LANPERRSTS_RETX_BUF 0x00000200 + #define IFS_MAX 80 #define IFS_MIN 40 #define IFS_RATIO 4 diff --git a/sys/dev/e1000/e1000_regs.h b/sys/dev/e1000/e1000_regs.h index 138155cfc5bc..fe7b62a9a493 100644 --- a/sys/dev/e1000/e1000_regs.h +++ b/sys/dev/e1000/e1000_regs.h @@ -114,6 +114,9 @@ #define E1000_PBA 0x01000 /* Packet Buffer Allocation - RW */ #define E1000_PBS 0x01008 /* Packet Buffer Size */ #define E1000_PBECCSTS 0x0100C /* Packet Buffer ECC Status - RW */ +#define E1000_PEIND 0x01084 /* Parity and ECC Indication - RC */ +#define E1000_PEINDM 0x01088 /* Parity and ECC Indication Mask - RW */ +#define E1000_PBECCSTS_I210 0x0245C /* I210 Packet Buffer ECC Status */ #define E1000_IOSFPC 0x00F28 /* TX corrupted data */ #define E1000_EEMNGCTL 0x01010 /* MNG EEprom Control */ #define E1000_EEMNGCTL_I210 0x01010 /* i210 MNG EEprom Mode Control */ @@ -691,8 +694,10 @@ #define E1000_FCRTC 0x02170 /* Flow Control Rx high watermark */ #define E1000_PCIEMISC 0x05BB8 /* PCIE misc config register */ -/* PCIe Parity Status Register */ -#define E1000_PCIEERRSTS 0x05BA8 +/* Memory error status registers */ +#define E1000_PCIEERRSTS 0x05BA8 /* PCIe Parity Status - RW1C */ +#define E1000_PCIEECCSTS 0x05BAC /* PCIe ECC Status - RW1C */ +#define E1000_LANPERRSTS 0x05F58 /* LAN Port Parity Status - RW1C */ #define E1000_PROXYS 0x5F64 /* Proxying Status */ #define E1000_PROXYFC 0x5F60 /* Proxying Filter Control */ diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c index eb4c17f78769..4cc5dbd7b7ee 100644 --- a/sys/dev/e1000/if_em.c +++ b/sys/dev/e1000/if_em.c @@ -457,7 +457,9 @@ static int igb_if_rx_queue_intr_enable(if_ctx_t, uint16_t); static int igb_if_tx_queue_intr_enable(if_ctx_t, uint16_t); static void em_handle_fatal_error_intr(struct e1000_softc *, u32); static bool em_handle_fatal_error_admin(struct e1000_softc *); +static void em_prepare_fatal_error_reset(struct e1000_softc *); static void em_finish_fatal_error_reset(struct e1000_softc *); +static void em_configure_peind_memory_errors(struct e1000_softc *); static void em_if_multi_set(if_ctx_t); static void em_if_update_admin_status(if_ctx_t); static void em_if_debug(if_ctx_t); @@ -507,6 +509,7 @@ enum em_fatal_error_state { EM_FATAL_ERROR_CAPTURING, EM_FATAL_ERROR_DETECTED, EM_FATAL_ERROR_RESET_REQUESTED, + EM_FATAL_ERROR_RESET_PREPARED, }; /* MSI-X handlers */ @@ -1985,6 +1988,7 @@ em_if_init(if_ctx_t ctx) else e1000_set_eee_i350(&sc->hw, true, true); } + em_configure_peind_memory_errors(sc); if (sc->vf_ifp) sc->vf_reset_pending = false; } @@ -2176,14 +2180,41 @@ em_has_pch_ecc(const struct e1000_hw *hw) hw->mac.type < e1000_82575); } +static bool +em_has_i210_memory_errors(const struct e1000_hw *hw) +{ + + return (hw->mac.type == e1000_i210 || + hw->mac.type == e1000_i211); +} +static void +em_configure_peind_memory_errors(struct e1000_softc *sc) +{ + struct e1000_hw *hw; + u32 peindm; + + hw = &sc->hw; + if (!em_has_i210_memory_errors(hw)) + return; + + /* Discard indications left by firmware before enabling reactions. */ + (void)E1000_READ_REG(hw, E1000_PEIND); + /* Do not depend on firmware preserving the datasheet defaults. */ + peindm = E1000_READ_REG(hw, E1000_PEINDM); + E1000_WRITE_REG(hw, E1000_PEINDM, + peindm | E1000_PEIND_FATAL_MASK); + E1000_WRITE_FLUSH(hw); +} + static u32 em_fatal_error_intr_mask(struct e1000_softc *sc) { - if (em_has_pch_ecc(&sc->hw) && + if ((em_has_pch_ecc(&sc->hw) || + em_has_i210_memory_errors(&sc->hw)) && atomic_load_acq_32(&sc->fatal_error_state) == EM_FATAL_ERROR_NONE) - return (E1000_IMS_ECCER); + return (E1000_IMS_FER); return (0); } @@ -2199,24 +2230,44 @@ em_update_pch_ecc_stats(struct e1000_softc *sc, u32 pbeccsts) } /* - * Descriptor-memory ECC errors stop the PCH MAC. Capture the read-clear - * status before handing recovery to the iflib admin task. + * Fatal internal-memory errors stop part or all of the MAC. Capture the + * read-clear indication before handing recovery to the iflib admin task. */ static void em_handle_fatal_error_intr(struct e1000_softc *sc, u32 icr) { struct e1000_hw *hw; + u32 lanerr, pcieerr, peind; - if (!em_has_pch_ecc(&sc->hw) || (icr & E1000_ICR_ECCER) == 0) + if ((!em_has_pch_ecc(&sc->hw) && + !em_has_i210_memory_errors(&sc->hw)) || + (icr & E1000_ICR_FER) == 0) return; hw = &sc->hw; - E1000_WRITE_REG(hw, E1000_IMC, E1000_IMS_ECCER); + E1000_WRITE_REG(hw, E1000_IMC, E1000_IMS_FER); if (!atomic_cmpset_32(&sc->fatal_error_state, EM_FATAL_ERROR_NONE, EM_FATAL_ERROR_CAPTURING)) return; - sc->fatal_error_pbeccsts = E1000_READ_REG(hw, E1000_PBECCSTS); + if (em_has_pch_ecc(hw)) { + sc->fatal_error_pbeccsts = + E1000_READ_REG(hw, E1000_PBECCSTS); + } else { + peind = E1000_READ_REG(hw, E1000_PEIND) & + E1000_PEIND_FATAL_MASK; + pcieerr = E1000_READ_REG(hw, E1000_PCIEERRSTS) & + E1000_PCIEERRSTS_FATAL_MASK; + lanerr = E1000_READ_REG(hw, E1000_LANPERRSTS) & + E1000_LANPERRSTS_RETX_BUF; + if (pcieerr != 0) + peind |= E1000_PEIND_PCIE_PARITY_FATAL; + if (lanerr != 0) + peind |= E1000_PEIND_LANPORT_PARITY_FATAL; + sc->fatal_error_peind = peind; + sc->fatal_error_pcie = pcieerr; + sc->fatal_error_lan = lanerr; + } atomic_store_rel_32(&sc->fatal_error_state, EM_FATAL_ERROR_DETECTED); iflib_admin_intr_deferred(sc->ctx); @@ -2225,16 +2276,51 @@ em_handle_fatal_error_intr(struct e1000_softc *sc, u32 icr) static bool em_handle_fatal_error_admin(struct e1000_softc *sc) { + u32 peind; if (!atomic_cmpset_acq_32(&sc->fatal_error_state, EM_FATAL_ERROR_DETECTED, EM_FATAL_ERROR_RESET_REQUESTED)) 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); + if (em_has_pch_ecc(&sc->hw)) { + 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); + } else { + peind = sc->fatal_error_peind; + if (peind & E1000_PEIND_LANPORT_PARITY_FATAL) + sc->fatal_error_lan_count++; + if (peind & E1000_PEIND_MNG_PARITY_FATAL) + sc->fatal_error_mng_count++; + if (peind & E1000_PEIND_PCIE_PARITY_FATAL) + sc->fatal_error_pcie_count++; + if (peind & E1000_PEIND_DMA_PARITY_FATAL) + sc->fatal_error_dma_count++; + if (peind == 0) + sc->fatal_error_unknown_count++; + device_printf(sc->dev, + "fatal internal memory error: PEIND %#x, " + "PCIEERRSTS %#x, LANPERRSTS %#x\n", peind, + sc->fatal_error_pcie, sc->fatal_error_lan); + /* Management-memory recovery belongs to management firmware. */ + if (peind != 0 && + (peind & E1000_PEIND_HOST_FATAL_MASK) == 0) { + sc->fatal_error_peind = 0; + sc->fatal_error_pcie = 0; + sc->fatal_error_lan = 0; + atomic_store_rel_32(&sc->fatal_error_state, + EM_FATAL_ERROR_NONE); + E1000_WRITE_REG(&sc->hw, E1000_IMS, + E1000_IMS_FER); + E1000_WRITE_FLUSH(&sc->hw); + return (true); + } + device_printf(sc->dev, + "requesting reset after memory error\n"); + } sc->fatal_error_reset_count++; iflib_request_reset(sc->ctx); /* Re-enter the admin task so it observes the reset request. */ @@ -2242,14 +2328,94 @@ em_handle_fatal_error_admin(struct e1000_softc *sc) return (true); } +/* + * A PCIe-region parity failure stops PCIe and DMA traffic. I210 and I211 + * require a port reset before master disable in this case, unlike the normal + * reset path, which disables the bus master first. + */ +static void +em_prepare_fatal_error_reset(struct e1000_softc *sc) +{ + struct e1000_hw *hw; + s32 error; + u32 ctrl, pcieerr; + int i; + + if (!em_has_i210_memory_errors(&sc->hw) || + atomic_load_acq_32(&sc->fatal_error_state) != + EM_FATAL_ERROR_RESET_REQUESTED) + return; + + pcieerr = sc->fatal_error_pcie | + (E1000_READ_REG(&sc->hw, E1000_PCIEERRSTS) & + E1000_PCIEERRSTS_FATAL_MASK); + if ((sc->fatal_error_peind & E1000_PEIND_PCIE_PARITY_FATAL) == 0 && + pcieerr == 0) + return; + + hw = &sc->hw; + ctrl = E1000_READ_REG(hw, E1000_CTRL); + E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST); + /* Do not access device registers for at least 3 ms after RST. */ + msec_delay(3); + for (i = 0; i < AUTO_READ_DONE_TIMEOUT; i++) { + if ((E1000_READ_REG(hw, E1000_EECD) & + E1000_EECD_AUTO_RD) != 0 && + (E1000_READ_REG(hw, E1000_STATUS) & + E1000_STATUS_RST_DONE) != 0) + break; + msec_delay(1); + } + if (i == AUTO_READ_DONE_TIMEOUT) + device_printf(sc->dev, + "port reset did not complete during parity recovery\n"); + error = e1000_disable_pcie_master_generic(hw); + if (error != E1000_SUCCESS) + device_printf(sc->dev, + "PCIe master disable failed during parity recovery: %d\n", + error); + pcieerr |= E1000_READ_REG(hw, E1000_PCIEERRSTS) & + E1000_PCIEERRSTS_FATAL_MASK; + if (pcieerr != 0) + E1000_WRITE_REG(hw, E1000_PCIEERRSTS, pcieerr); + atomic_store_rel_32(&sc->fatal_error_state, + EM_FATAL_ERROR_RESET_PREPARED); +} + static void em_finish_fatal_error_reset(struct e1000_softc *sc) { + struct e1000_hw *hw; + u32 lanerr, pcieerr; + u32 state; - if (atomic_load_acq_32(&sc->fatal_error_state) == - EM_FATAL_ERROR_NONE) + state = atomic_load_acq_32(&sc->fatal_error_state); + if (state != EM_FATAL_ERROR_RESET_REQUESTED && + state != EM_FATAL_ERROR_RESET_PREPARED) return; + hw = &sc->hw; + if (em_has_i210_memory_errors(hw)) { + pcieerr = sc->fatal_error_pcie | + (E1000_READ_REG(hw, E1000_PCIEERRSTS) & + E1000_PCIEERRSTS_FATAL_MASK); + if (pcieerr != 0) + E1000_WRITE_REG(hw, E1000_PCIEERRSTS, pcieerr); + lanerr = sc->fatal_error_lan | + (E1000_READ_REG(hw, E1000_LANPERRSTS) & + E1000_LANPERRSTS_RETX_BUF); + if (lanerr != 0) + E1000_WRITE_REG(hw, E1000_LANPERRSTS, lanerr); + /* + * RST can relatch PEIND from a subordinate status register + * before that register is cleared. Drain the recovered + * indication before unmasking FER. + */ + (void)E1000_READ_REG(hw, E1000_PEIND); + sc->fatal_error_peind = 0; + sc->fatal_error_pcie = 0; + sc->fatal_error_lan = 0; + } sc->fatal_error_pbeccsts = 0; atomic_store_rel_32(&sc->fatal_error_state, EM_FATAL_ERROR_NONE); } @@ -2930,8 +3096,10 @@ em_if_stop(if_ctx_t ctx) igb_iov_reset_prepare(sc); if (!sc->vf_ifp || (atomic_load_acq_32(&sc->vf_mbx_ready) != 0 && - (if_getflags(iflib_get_ifp(ctx)) & IFF_UP) == 0)) + (if_getflags(iflib_get_ifp(ctx)) & IFF_UP) == 0)) { + em_prepare_fatal_error_reset(sc); e1000_reset_hw(&sc->hw); + } if (sc->vf_ifp) atomic_store_rel_32(&sc->vf_mbx_ready, 0); if (sc->hw.mac.type >= e1000_82544 && !sc->vf_ifp) @@ -3914,6 +4082,7 @@ em_reset(if_ctx_t ctx) em_flush_desc_rings(sc); /* Issue a global reset */ + em_prepare_fatal_error_reset(sc); e1000_reset_hw(hw); if (hw->mac.type >= igb_mac_min) { E1000_WRITE_REG(hw, E1000_WUC, 0); @@ -6200,7 +6369,8 @@ 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)) { + if (em_has_pch_ecc(&sc->hw) || + em_has_i210_memory_errors(&sc->hw)) { struct sysctl_oid *memerr_node; struct sysctl_oid_list *memerr_list; @@ -6208,17 +6378,41 @@ 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 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"); + "fatal_resets", CTLFLAG_RD, + &sc->fatal_error_reset_count, + "Resets requested for fatal internal memory errors"); + 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, + "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"); + } else { + SYSCTL_ADD_UQUAD(ctx, memerr_list, OID_AUTO, + "fatal_lan", CTLFLAG_RD, + &sc->fatal_error_lan_count, + "Fatal LAN-port memory error indications"); + SYSCTL_ADD_UQUAD(ctx, memerr_list, OID_AUTO, + "fatal_management", CTLFLAG_RD, + &sc->fatal_error_mng_count, + "Fatal management-memory error indications"); + SYSCTL_ADD_UQUAD(ctx, memerr_list, OID_AUTO, + "fatal_pcie", CTLFLAG_RD, + &sc->fatal_error_pcie_count, + "Fatal PCIe memory error indications"); + SYSCTL_ADD_UQUAD(ctx, memerr_list, OID_AUTO, + "fatal_dma", CTLFLAG_RD, + &sc->fatal_error_dma_count, + "Fatal DMA memory error indications"); + SYSCTL_ADD_UQUAD(ctx, memerr_list, OID_AUTO, + "fatal_unknown", CTLFLAG_RD, + &sc->fatal_error_unknown_count, + "Fatal memory errors without a reported region"); + } } SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "excess_coll", diff --git a/sys/dev/e1000/if_em.h b/sys/dev/e1000/if_em.h index b88cb8abefb5..1d1587331555 100644 --- a/sys/dev/e1000/if_em.h +++ b/sys/dev/e1000/if_em.h @@ -626,7 +626,15 @@ struct e1000_softc { u32 stats_pending; u32 fatal_error_state; u32 fatal_error_pbeccsts; + u32 fatal_error_peind; + u32 fatal_error_pcie; + u32 fatal_error_lan; u64 fatal_error_reset_count; + u64 fatal_error_lan_count; + u64 fatal_error_mng_count; + u64 fatal_error_pcie_count; + u64 fatal_error_dma_count; + u64 fatal_error_unknown_count; u64 corrected_error_packet_buffer_count; u64 uncorrected_error_packet_buffer_count;