From nobody Sun Aug 16 09:18:10 2026 X-Original-To: dev-commits-src-all@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 4hN9P41gdLz6nmCc for ; Sun, 16 Aug 2026 09:18:16 +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 4hN9P41NbJz3Ncp for ; Sun, 16 Aug 2026 09:18:16 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1786871896; 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=k8qn6ysef3KfQ9TIDC98q04TdBzmOaBhhv1a2ie26htM64pDmxOoybWAmkQqtozC7VyRuD GdXdjgs8Q632GP/HJ4iVmdJnEtbLfowrEWXVcKOMeVYWP8Ls6BGCMvCCmhcd2d0V7URMRq 5eURmNPDCkBuJw1vRP6i/8fTwkszkRMJiH9GmtY1NI7IHGa22p8/tulbL/PGNgSstTP9TZ q5ruuyhpPvLigu+PN9ELDYZUDRya2HuKHvBho865cRVHY8t4FKX2a68tF+pb6fuOGsytod K73iMmAnAiKFKBPR9ShxeCnJV+Z0worbF+CwnRTsyoTndr3/CyHC/Lkygxsm7w== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1786871896; a=rsa-sha256; cv=none; b=qTJjAZ6xVEhHMySu5Ql7yi+7LQ8ezWXYjBnTytuBMM8mf7mU4Ai0diZFIKj2VeW/2h49X5 742astC9ap8rKecIY3vIu/xI1ZK6xLIT/vFl440ejSmiHFOSpr29lRadLiJN7EOsxCPjM9 dQIdhtNJJcOAZk1XKLYaO8wPtwRx9MaMraaGHrS+hV9wZl4Jc3Q89DNgaQ4JXzOUQ1TnWq PYEJjDB7V5O8I+aM6gz8FVXu/xR3t7suJTt+RUNBs1mDUe33cF41HVwsi4WIlew5QASrjX uK2jOZaIdYUp2YNDx4m8MV6xga7410fG3ubuVvgUIGqjYZSTMeKfXDvLs6cKfw== 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=1786871896; 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=kxo2ZfiyvtpdZKhV8QkWKnbB/v1k7bNZiGv+nR92Htft4twiYv+OR5Yo3abt/ACtYSJOSU a3KpZdvs2MLC1Y/0UmLgad5DnqWOiis8pU0hcjVD1V/pofZ+uNAfkPblra+9amVfOIdhu+ 989vv1rs8J+IXCM8AvVW4Kg9BS9JPpuQxqMEoBQdy9opKr1WDc+HSMysERI3djxoiW3yP2 mr6dxbrnPRnCj2uflvCPGKV0bGVWOY5tZOtYFXRH+6wRO1MyfWt3rNDCDtHOZDcZsmfafI ij++puKoJSOX5UHwcJjUopdP1HkMJi/WBIhPwVkuPVPHy67WBZbA+bXGjxIRtQ== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4hN9P40R1dz4nv for ; Sun, 16 Aug 2026 09:18:16 +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 all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@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;