From nobody Sun Aug 30 01:37:51 2026 X-Original-To: dev-commits-src-branches@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 4hXZWM4FVpz6pt7r for ; Sun, 30 Aug 2026 01:37:51 +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 4hXZWM1SGwz3sPL for ; Sun, 30 Aug 2026 01:37:51 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1788053871; 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=id5j/ggo/NfCQ9enP6gxchQmJY9+WHAj6O0DlFXs8po=; b=WeXbI/3F/xE31J2qiDMIur19dqHVdLw2hVMfi5Ut+bqHKtjYRvN7vNbpZ5FB2lX9NafKEp kOj86xn1pM0+WaD7+egJoQYaypFSbDdF16TBrD65jm/w/+wBXCRy3U4UXo5ZPPLPa2+rV5 rrl+M3U4Ecd9y/D2izLVPxrbkJBbKe+BJzyr0fp401dcd4EVDoX/7pWGwSGFgXQ0XcFluu wqe8e+EAJ2z8atoH1GYJHSlkbDqIhE4UZI2U6+kaSNIq3dGzx4XuK5U4OOQwdixKsGs0mI lO7dzcWFfFTj6RIpquDjKk9O8MIxXdLXPtY5/vS/7sA//lZOaVyZPmBMj+qeqQ== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1788053871; a=rsa-sha256; cv=none; b=nwpNVln0gmg27hYRSAECOBXFaPPEqxJnmtsaXDks9S4VNyYv75/Upv/ojUdKpQ8K1X8TEr wU7JbFtVgsFUhVoG4wpe5Pjj0Nzro+FHYkvgcDcFPKhKKGz/Mp5kd+5Egfq3b2U1yRFSrs /ImjYsaKS6h+BMYQr8sUmqh/P9J5X0wxTnb2lSuquogX/7L4Trx39yKK2XOLqQD3weZxQT H2VA0ZzENBUongnZGFCisJLDlLrTOwsWoqsZcI4umQ0rnKlPPCtWoNYF+/nFRf3DSkYETD bFfx8EsSYhmRQ44Lu81+FkOV4vEJ/tjGriRXS4EW/mtociZMjknqfcB27MuyTw== 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=1788053871; 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=id5j/ggo/NfCQ9enP6gxchQmJY9+WHAj6O0DlFXs8po=; b=sECd6raNQsuW4TqbHgpzHyoCmG6oObr6A15rPp01crex4O0vGb4QpS+g0w4g/NgOPIxMyQ bVF7VJu0EAU0diyj/gVUn5i4Lm+8eB+OhdCW3uqCyePfS+Pr5sO+/G1m+igMHu9ZuZzTc1 Ek01IllmXW4rENAINncQTk/ocAVSjH1VsTk36PpGhTeeOGqUGcYGwAwaelUMaDlLxkEFpW LqQ7hXl9EBss0t0MECI5jEzdiWvIx/B90W7Ku4LZPqEF3Kx6XNsse1TkzZs+4bjB1EvjRT y43NzLMG+m+2iDnwQ0QM2f6h+35pMLBI+2EAb82kkJMCxvFU6FPx7gkzO5WTtQ== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4hXZWM0Spzz149m for ; Sun, 30 Aug 2026 01:37:51 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 3e2f2 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Sun, 30 Aug 2026 01:37:51 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Kevin Bowling Subject: git: 06730a067360 - stable/15 - e1000: Recover from 82575 memory errors List-Id: Commits to the stable branches of the FreeBSD src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-branches List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-branches@freebsd.org Sender: owner-dev-commits-src-branches@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/stable/15 X-Git-Reftype: branch X-Git-Commit: 06730a0673601f6828242f45261df6e383d406fa Auto-Submitted: auto-generated Date: Sun, 30 Aug 2026 01:37:51 +0000 Message-Id: <6a93896f.3e2f2.27a956d7@gitrepo.freebsd.org> The branch stable/15 has been updated by kbowling: URL: https://cgit.FreeBSD.org/src/commit/?id=06730a0673601f6828242f45261df6e383d406fa commit 06730a0673601f6828242f45261df6e383d406fa Author: Kevin Bowling AuthorDate: 2026-08-16 05:39:31 +0000 Commit: Kevin Bowling CommitDate: 2026-08-30 01:27:59 +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. Sponsored by: BBOX.io (cherry picked from commit 24917c22a330e8da350e8ef1a251a70abf0baf83) --- 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 af5373c19aac..f45d99e10e0d 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 b158540071fd..c4c036ff17f7 100644 --- a/sys/dev/e1000/if_em.c +++ b/sys/dev/e1000/if_em.c @@ -447,6 +447,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); @@ -1688,6 +1689,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); } /* @@ -1876,6 +1878,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) { @@ -1969,22 +2005,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 @@ -2134,7 +2182,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) @@ -2142,12 +2190,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; @@ -2161,6 +2205,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 { @@ -2215,6 +2266,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); @@ -2368,7 +2426,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;