From nobody Sun Aug 16 10:13:03 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 4hNBcN58ysz6nqpv for ; Sun, 16 Aug 2026 10:13:08 +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 4hNBcN4cGgz3XS3 for ; Sun, 16 Aug 2026 10:13:08 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1786875188; 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=FKdoiM0wGY3DFAfLgnsbpUHyeO4NEzawll46p0152QI=; b=gu/75xn0DaKe1OPUVpM5xEuuixG9OGzyzaDs7IXH8pu2oCjgLwHJcEfRtJ3yFxhlQL3nqo Je5uleygEpbHd104GzoVGBAtoCfDUfw3kij5BM4H14ECsCGLpE4h8Bz7WmntP3b4oFhRsR fmEfUggKRKPMGBMjcqGzwnZzp8SuijnXkHc6xMVnib60N9ph5ZQNImkfScQ1/yaKoiEplf 3dG4qTz4AD0MUaIpOBNf62qsB3cI7FNGrbsHM2zzOjUlsAcMOjg1FnkNrvFYzzWXljeAHP Nr7BHm2ZOZR/m9UbpDc7UuCfuRDtqZ7isLBSPl2LJ6j8n+tMmsfb4U27INLEBg== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1786875188; a=rsa-sha256; cv=none; b=DTWIEaCjYY/ozx5aaV8OOgihpcaisZ7ePPOvyS6X4X1GWDEjRcPcL/IzH0y4OLYLeTfSw+ sCq1Cg67aHVnJ1PNjwezQiFQ7mQMpILPvPoYO5jSD3iAw7LLWuNvvxJXtgisMoovsXecXP X3LXUmS37sWkLA3Rd1njCAKJPvZO6baUpWQxSJAj1MC4g/e8JKtEBokkHTGqSY/zbknJrA hK9Zpv7K1DTD06H1gDXuU4IiR3XgZhykls20MlLXu+8AQpklu66wN3WFHN759d3jsNYKIM AZXw93QQrLfdVXw2r7J5E/BZHPhBKvOywo/TPcyTqR6zACuUQ6zOHtngOZ97Dw== 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=1786875188; 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=FKdoiM0wGY3DFAfLgnsbpUHyeO4NEzawll46p0152QI=; b=yQjv0mwoUEA0FtrUK3INMk071sI/t2oRPw9Xjf/TGGN3XZzcsmbsWdIwG9+LhrSynNS7vg Zn8jEaj94eNpBJhIRVrBpCn7b+5M3pGYZGoSK1KjRWZ7J/QPqrHAMfhI2uIfFQ0EaDqkHN 5Gnl4rVjzKOMKKVyYFF3/l0z+udgxVDpdus2WQVO0+4tRY+tVeLVYNeD6/cMs722aZ+2b9 G9v5FtPPO9gt0BbIkc9pvTR25sGoY6eMu99KT7bAbu2MRDIIhmGd9J+u0a36IfcfYTQ2qh I/LzBERYf0iKcZ/S357YPYT+gZEpa3hw+bJ9JR/3pXZaZE184/prSrCFlycpog== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4hNBcN3W84z7gL for ; Sun, 16 Aug 2026 10:13:08 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 25916 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Sun, 16 Aug 2026 10:13:03 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Kevin Bowling Subject: git: 24917c22a330 - main - e1000: Recover from 82575 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: 24917c22a330e8da350e8ef1a251a70abf0baf83 Auto-Submitted: auto-generated Date: Sun, 16 Aug 2026 10:13:03 +0000 Message-Id: <6a818d2f.25916.1a0f73d7@gitrepo.freebsd.org> The branch main has been updated by kbowling: URL: https://cgit.FreeBSD.org/src/commit/?id=24917c22a330e8da350e8ef1a251a70abf0baf83 commit 24917c22a330e8da350e8ef1a251a70abf0baf83 Author: Kevin Bowling AuthorDate: 2026-08-16 05:39:31 +0000 Commit: Kevin Bowling CommitDate: 2026-08-16 10:11:43 +0000 e1000: Recover from 82575 memory errors 82575 protects its packet buffer and receive and transmit descriptor handlers with ECC. Correctable errors are repaired in hardware. Packet data errors are contained to the affected packet, while the native RX_PBUR, TX_PBUR, RX_DHER, and TX_DHER interrupt causes report unrecoverable packet buffer or descriptor handler state. The affected traffic direction remains stopped until software resets the port. Enable the three ECC blocks and hardware memory error reaction after queue and filter initialization. Capture the clear-on-read status registers in the interrupt filter and keep all four native causes masked while the iflib admin task owns the event. Request port reinitialization for every native PBUR or DHER cause. Packet data errors that do not raise a native cause remain count-only and do not disrupt the port. The captured status registers provide diagnostics and accounting but do not independently initiate recovery. Hardware validation used an 82575EB revision 2 and the documented PBEEI, RDHEEI, and TDHEEI injectors. Correctable TX/RX packet data and descriptor fetch/writeback errors preserved traffic. Uncorrectable TX/RX packet buffer header and descriptor fetch/writeback errors each requested one reset, restored traffic, and rearmed every ECC control. Repeated recovery produced no watchdogs. MFC after: 2 weeks Sponsored by: BBOX.io --- sys/dev/e1000/e1000_defines.h | 15 +++++++ sys/dev/e1000/e1000_regs.h | 3 ++ sys/dev/e1000/if_em.c | 97 +++++++++++++++++++++++++++++++++++-------- 3 files changed, 97 insertions(+), 18 deletions(-) diff --git a/sys/dev/e1000/e1000_defines.h b/sys/dev/e1000/e1000_defines.h index ab53546d5597..033eab0ae370 100644 --- a/sys/dev/e1000/e1000_defines.h +++ b/sys/dev/e1000/e1000_defines.h @@ -93,6 +93,7 @@ #define E1000_CTRL_EXT_IRCA 0x00000001 #define E1000_CTRL_EXT_DRV_LOAD 0x10000000 /* Drv loaded bit for FW */ #define E1000_CTRL_EXT_IAME 0x08000000 /* Int ACK Auto-mask */ +#define E1000_CTRL_EXT_MEHE 0x40000000 /* Memory error handling */ #define E1000_CTRL_EXT_PBA_CLR 0x80000000 /* PBA Clear */ #define E1000_CTRL_EXT_LSECCK 0x00001000 #define E1000_CTRL_EXT_PHYPDEN 0x00100000 @@ -528,6 +529,12 @@ #define E1000_PBECCSTS_UNCORR_ERR_CNT_SHIFT 8 #define E1000_PBECCSTS_ECC_ENABLE 0x00010000 +/* 82575 packet-buffer and descriptor-handler ECC status. */ +#define E1000_ECC_82575_CORR_CNT_MASK 0x000000FF +#define E1000_ECC_82575_UNCORR_CNT_MASK 0x0000FF00 +#define E1000_ECC_82575_UNCORR_CNT_SHIFT 8 +#define E1000_ECC_82575_ENABLE 0x00010000 + /* I350 and I210/I211 memory error status bits. */ #define E1000_PEIND_LANPORT_PARITY_FATAL 0x00000001 #define E1000_PEIND_MNG_PARITY_FATAL 0x00000002 @@ -603,6 +610,13 @@ #define E1000_ICR_GPI_EN3 0x00004000 /* GP Int 3 */ #define E1000_ICR_TXD_LOW 0x00008000 #define E1000_ICR_MNG 0x00040000 /* Manageability event */ +#define E1000_ICR_82575_RX_PBUR 0x00400000 /* Rx packet buffer error */ +#define E1000_ICR_82575_TX_PBUR 0x00800000 /* Tx packet buffer error */ +#define E1000_ICR_82575_RX_DHER 0x01000000 /* Rx descriptor error */ +#define E1000_ICR_82575_TX_DHER 0x02000000 /* Tx descriptor error */ +#define E1000_ICR_82575_MEMORY_ERROR_MASK \ + (E1000_ICR_82575_RX_PBUR | E1000_ICR_82575_TX_PBUR | \ + E1000_ICR_82575_RX_DHER | E1000_ICR_82575_TX_DHER) #define E1000_ICR_ECCER 0x00400000 /* Uncorrectable ECC Error */ #define E1000_ICR_NFER 0x00800000 /* Non-Fatal Error (82576) */ #define E1000_ICR_TS 0x00080000 /* Time Sync Interrupt */ @@ -672,6 +686,7 @@ #define E1000_IMS_RXO E1000_ICR_RXO /* Rx overrun */ #define E1000_IMS_RXT0 E1000_ICR_RXT0 /* Rx timer intr */ #define E1000_IMS_TXD_LOW E1000_ICR_TXD_LOW +#define E1000_IMS_82575_MEMORY_ERROR_MASK E1000_ICR_82575_MEMORY_ERROR_MASK #define E1000_IMS_ECCER E1000_ICR_ECCER /* Uncorrectable ECC Error */ #define E1000_IMS_NFER E1000_ICR_NFER /* Non-Fatal Error (82576) */ #define E1000_IMS_TS E1000_ICR_TS /* Time Sync Interrupt */ diff --git a/sys/dev/e1000/e1000_regs.h b/sys/dev/e1000/e1000_regs.h index 2141118c1246..3cfa1a05f297 100644 --- a/sys/dev/e1000/e1000_regs.h +++ b/sys/dev/e1000/e1000_regs.h @@ -117,6 +117,9 @@ #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_PBECCSTS_82575 0x0245C /* 82575 Packet Buffer ECC Status */ +#define E1000_RDHESTS_82575 0x02468 /* 82575 Rx Descriptor ECC Status */ +#define E1000_TDHESTS_82575 0x0246C /* 82575 Tx Descriptor ECC Status */ #define E1000_SWPBECCSTS_82576 0x0305C /* Switch Packet Buffer ECC Status */ #define E1000_IPPBECCSTS_82576 0x0B470 /* IPsec Packet Buffer ECC Status */ #define E1000_RDHESTS_82576 0x025C0 /* Rx Descriptor Handler ECC Status */ diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c index 8f2502ea2015..91c8eede1de1 100644 --- a/sys/dev/e1000/if_em.c +++ b/sys/dev/e1000/if_em.c @@ -460,6 +460,7 @@ 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_configure_82575_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); @@ -1989,6 +1990,7 @@ em_if_init(if_ctx_t ctx) e1000_set_eee_i350(&sc->hw, true, true); } em_configure_peind_memory_errors(sc); + em_configure_82575_memory_errors(sc); if (sc->vf_ifp) sc->vf_reset_pending = false; } @@ -2180,6 +2182,40 @@ em_has_pch_ecc(const struct e1000_hw *hw) hw->mac.type < e1000_82575); } +static bool +em_has_82575_memory_errors(const struct e1000_hw *hw) +{ + + return (hw->mac.type == e1000_82575); +} + +static void +em_configure_82575_memory_errors(struct e1000_softc *sc) +{ + struct e1000_hw *hw; + u32 ctrl_ext; + + hw = &sc->hw; + if (!em_has_82575_memory_errors(hw)) + return; + + /* Discard pre-driver status before enabling the hardware reaction. */ + (void)E1000_READ_REG(hw, E1000_PBECCSTS_82575); + (void)E1000_READ_REG(hw, E1000_RDHESTS_82575); + (void)E1000_READ_REG(hw, E1000_TDHESTS_82575); + E1000_WRITE_REG(hw, E1000_PBECCSTS_82575, + E1000_ECC_82575_ENABLE); + E1000_WRITE_REG(hw, E1000_RDHESTS_82575, + E1000_ECC_82575_ENABLE); + E1000_WRITE_REG(hw, E1000_TDHESTS_82575, + E1000_ECC_82575_ENABLE); + + ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); + E1000_WRITE_REG(hw, E1000_CTRL_EXT, + ctrl_ext | E1000_CTRL_EXT_MEHE); + E1000_WRITE_FLUSH(hw); +} + static bool em_has_82576_memory_errors(const struct e1000_hw *hw) { @@ -2273,22 +2309,34 @@ em_pcie_fatal_error_mask(const struct e1000_hw *hw) } static u32 -em_fatal_error_intr_mask(struct e1000_softc *sc) +em_memory_error_intr_mask(const struct e1000_hw *hw) { - u32 mask; - if (!em_has_pch_ecc(&sc->hw) && - !em_has_82576_memory_errors(&sc->hw) && - !em_has_i210_i350_memory_errors(&sc->hw)) + if (em_has_82575_memory_errors(hw)) + return (E1000_IMS_82575_MEMORY_ERROR_MASK); + if (em_has_82576_memory_errors(hw)) + return (E1000_IMS_FER | E1000_IMS_NFER); + if (em_has_pch_ecc(hw) || em_has_i210_i350_memory_errors(hw)) + return (E1000_IMS_FER); + return (0); +} + +static bool +em_has_memory_errors(const struct e1000_hw *hw) +{ + + return (em_memory_error_intr_mask(hw) != 0); +} + +static u32 +em_fatal_error_intr_mask(struct e1000_softc *sc) +{ + if (!em_has_memory_errors(&sc->hw)) return (0); if (atomic_load_acq_32(&sc->fatal_error_state) != EM_FATAL_ERROR_NONE) return (0); - - mask = E1000_IMS_FER; - if (em_has_82576_memory_errors(&sc->hw)) - mask |= E1000_IMS_NFER; - return (mask); + return (em_memory_error_intr_mask(&sc->hw)); } static void @@ -2438,7 +2486,7 @@ em_update_i350_ecc_stats(struct e1000_softc *sc) /* * Internal-memory error causes are read-clear. Capture them before handing - * fatal recovery or 82576 non-fatal acknowledgement to the iflib admin task. + * fatal recovery or non-fatal acknowledgement to the iflib admin task. */ static void em_handle_fatal_error_intr(struct e1000_softc *sc, u32 icr) @@ -2446,12 +2494,8 @@ em_handle_fatal_error_intr(struct e1000_softc *sc, u32 icr) struct e1000_hw *hw; u32 dma_rx, dma_tx, error_mask, lanerr, pcieerr, peind; - error_mask = E1000_ICR_FER; - if (em_has_82576_memory_errors(&sc->hw)) - error_mask |= E1000_ICR_NFER; - if ((!em_has_pch_ecc(&sc->hw) && - !em_has_82576_memory_errors(&sc->hw) && - !em_has_i210_i350_memory_errors(&sc->hw)) || + error_mask = em_memory_error_intr_mask(&sc->hw); + if (!em_has_memory_errors(&sc->hw) || (icr & error_mask) == 0) return; @@ -2465,6 +2509,13 @@ em_handle_fatal_error_intr(struct e1000_softc *sc, u32 icr) if (em_has_pch_ecc(hw)) { sc->fatal_error_pbeccsts = E1000_READ_REG(hw, E1000_PBECCSTS); + } else if (em_has_82575_memory_errors(hw)) { + sc->fatal_error_pbeccsts = + E1000_READ_REG(hw, E1000_PBECCSTS_82575); + sc->fatal_error_dma_rx = + E1000_READ_REG(hw, E1000_RDHESTS_82575); + sc->fatal_error_dma_tx = + E1000_READ_REG(hw, E1000_TDHESTS_82575); } else if (em_has_82576_memory_errors(hw)) { sc->fatal_error_peind = E1000_READ_REG(hw, E1000_PEIND); } else { @@ -2519,6 +2570,13 @@ em_handle_fatal_error_admin(struct e1000_softc *sc) "uncorrectable packet-buffer ECC error: " "PBECCSTS %#x; requesting reset\n", sc->fatal_error_pbeccsts); + } else if (em_has_82575_memory_errors(&sc->hw)) { + device_printf(sc->dev, + "unrecoverable internal memory ECC error: ICR %#x, " + "PBECCSTS %#x, RDHESTS %#x, TDHESTS %#x; " + "requesting reset\n", sc->fatal_error_icr, + sc->fatal_error_pbeccsts, sc->fatal_error_dma_rx, + sc->fatal_error_dma_tx); } else if (em_has_82576_memory_errors(&sc->hw)) { peind = sc->fatal_error_peind; em_update_82576_ecc_stats(sc); @@ -2672,7 +2730,10 @@ em_finish_fatal_error_reset(struct e1000_softc *sc) return; hw = &sc->hw; - if (em_has_82576_memory_errors(hw)) { + if (em_has_82575_memory_errors(hw)) { + sc->fatal_error_dma_tx = 0; + sc->fatal_error_dma_rx = 0; + } else if (em_has_82576_memory_errors(hw)) { /* Drain any indication relatched while the port was resetting. */ (void)E1000_READ_REG(hw, E1000_PEIND); sc->fatal_error_peind = 0;