From nobody Sun Aug 30 01:37:48 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 4hXZWK2q9xz6ptGr for ; Sun, 30 Aug 2026 01:37:49 +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 4hXZWK01v1z3sSw for ; Sun, 30 Aug 2026 01:37:49 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1788053869; 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=bkfKOH0R+5Pr+r8KnAuChhKoxMhc4Hbz0NmVeJq+ERw=; b=U123rgRboqTfyjitle8b9FEiqIKwbFb5bMmyZ8Ld1aBf34dl+jvQCLfTgEus8W63R+oxUa a9bfeL//AmhZaCL2aa5VuALxsIOlScqs4jbGOIe4UJCxvCF6gpLSjd8WUAIfh4uRwBRgBq 2pPsyaZ7pQ/hjENsJjxrATR4/1T4ctZAoeHepxexzLAE0fi85uIF2oNCqUGSD+qmjXqbA4 vxM0nQlogzacMRpHWrXTVdxPUktHCdvqz0sHBhP5Eb5GK1/ljHHMnRb/8cKUFfa/NeU5Kk BTV7XOQ/xoFQeSSiXUj0yPQ/Fxg2me+4pZv1Wg2sf9/uQO+iGSMXxX0jnNUSEw== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1788053869; a=rsa-sha256; cv=none; b=kN94yNNqOBs8RKTirpH2BEcHcdB9mgXU7gvGTEKB5etF4y0Z5YgNTbXj64QVw2V+KRFMID EVezq0ErJwbit5CT+APe8kzlT5WTYVg6pxyKmsgCRoVe0kfEQacrjMLmi1h/QvDnsvQuH7 WvKWCegJLJFlGZNViAYA5oka/YVHGy/clQgt+DG1oHP0Y/MYzChbN1UTm43KMisQblMc8R 5AbSnQE+fKpvF9IT/D61euEJ4s+sakhZnesfBDd1uxvWDBdjteLJkfWXbaSiXksJBlFz+E hMo1Y3pmjxB65v/5t5kUfJZ/xVF5ZnO6RnsrptTGWDtLWbWHTywFOA8jLblS9g== 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=1788053869; 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=bkfKOH0R+5Pr+r8KnAuChhKoxMhc4Hbz0NmVeJq+ERw=; b=AYMDYAIqT4W8tuukhM6UbxqaPfTrpWG/irxU2nzURAX6QTRyasbbGPBKClLGeRA6Y/nS9V iNQ1WyCU5qyAq+dQCcGrWpBkketpd11uCcz+J+W3QrhWdeSk661GsihFJaAE8YZLR7fJfq Gy3rP2OIC+PbWr6mS0LtC1Whn43A6FBXfDWtY9NqWZ2aUugJxWFUSTYJK5efDhf0dWKCje PakHzmh+Ju72lwhQTo7uI/2ebrYM0L4GgoqN8ZGbndCoiANUByRd4LQCSbdfZREdIN/70+ qveGl21tlXUMz2HhMyNCx9CjqUcShf2OTQC0nG8eOnVfr5z0soeBZb2gYCKhFA== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4hXZWJ5rrpz13fD for ; Sun, 30 Aug 2026 01:37:48 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 3eebc by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Sun, 30 Aug 2026 01:37:48 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Kevin Bowling Subject: git: 35e9e0d246a0 - stable/15 - e1000: Recover from 82576 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/stable/15 X-Git-Reftype: branch X-Git-Commit: 35e9e0d246a0164e6d548ea44d0200b59d0753c9 Auto-Submitted: auto-generated Date: Sun, 30 Aug 2026 01:37:48 +0000 Message-Id: <6a93896c.3eebc.2223a9ac@gitrepo.freebsd.org> The branch stable/15 has been updated by kbowling: URL: https://cgit.FreeBSD.org/src/commit/?id=35e9e0d246a0164e6d548ea44d0200b59d0753c9 commit 35e9e0d246a0164e6d548ea44d0200b59d0753c9 Author: Kevin Bowling AuthorDate: 2026-08-13 23:10:47 +0000 Commit: Kevin Bowling CommitDate: 2026-08-30 01:24:07 +0000 e1000: Recover from 82576 memory errors 82576 reports fatal and non-fatal internal memory errors through ICR.FER and ICR.NFER and identifies the affected memory in its native PEIND layout. Fatal errors can stop transmit, receive, or both until software resets and reinitializes the port. Enable the controller-wide parity detector and implemented PEINDM reaction bits after hardware initialization, while preserving unrelated register state and omitting the absent IPsec memories on 82576NS. Enable both interrupt causes and capture the read-clear PEIND register in the interrupt filter. Keep the causes masked while the iflib admin task owns the event. Acknowledge non-fatal packet data errors without disrupting the port. Request normal port reinitialization for FER, a fatal PEIND source, or the memory hang indication. Do not apply the later I210/I350 register layout or their special PCIe parity reset order. Hardware validation used a dual-port 82576EB revision 1. Firmware left PEINDM at its 0x80000000 default; initialization explicitly programmed the parity-enable bit and produced 0xffffff07 on both ports. An NFER during two-stream TCP sustained line rate without a reset, watchdog, or carrier event. FER on the linked and disconnected ports each requested exactly one reset. The linked port resumed the existing TCP sessions after autonegotiation. PEINDM and both interrupt causes were restored after every reset. The injections set the ICR causes without corrupting SRAM, so their empty PEIND values deliberately exercised the unknown source path. Sponsored by: BBOX.io (cherry picked from commit 4c2dda4c70e210be4efb4527fc32fbb79f23d452) --- sys/dev/e1000/e1000_defines.h | 10 ++++ sys/dev/e1000/if_em.c | 113 +++++++++++++++++++++++++++++++++++++----- sys/dev/e1000/if_em.h | 1 + 3 files changed, 112 insertions(+), 12 deletions(-) diff --git a/sys/dev/e1000/e1000_defines.h b/sys/dev/e1000/e1000_defines.h index 761ce02d06af..cf23bbde846e 100644 --- a/sys/dev/e1000/e1000_defines.h +++ b/sys/dev/e1000/e1000_defines.h @@ -535,6 +535,14 @@ #define E1000_PEIND_DMA_PARITY_FATAL 0x00000008 #define E1000_PEIND_FATAL_MASK 0x0000000F +/* 82576 uses PEIND directly rather than the later four-region layout. */ +#define E1000_PEIND_82576_NONFATAL_MASK 0x00000007 +#define E1000_PEIND_82576_FATAL_MASK 0x7FFFFF00 +#define E1000_PEIND_82576_MEMORY_HANG 0x80000000 +#define E1000_PEINDM_82576_PARITY_ENABLE 0x80000000 +/* 82576NS omits the IPsec key, FIFO, and packet-buffer memories. */ +#define E1000_PEIND_82576_IPSEC_MASK 0x40700600 + #define E1000_PBECCSTS_I210_ECC_ENABLE 0x00000001 #define E1000_PBECCSTS_I210_CORR_ERR 0x00000004 @@ -591,6 +599,7 @@ #define E1000_ICR_TXD_LOW 0x00008000 #define E1000_ICR_MNG 0x00040000 /* Manageability event */ #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 */ #define E1000_ICR_DRSTA 0x40000000 /* Device Reset Asserted */ /* If this bit asserted, the driver should claim the interrupt */ @@ -659,6 +668,7 @@ #define E1000_IMS_RXT0 E1000_ICR_RXT0 /* Rx timer intr */ #define E1000_IMS_TXD_LOW E1000_ICR_TXD_LOW #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 */ #define E1000_IMS_DRSTA E1000_ICR_DRSTA /* Device Reset Asserted */ #define E1000_IMS_DOUTSYNC E1000_ICR_DOUTSYNC /* NIC DMA out of sync */ diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c index db58194d94bf..5c5bc8253465 100644 --- a/sys/dev/e1000/if_em.c +++ b/sys/dev/e1000/if_em.c @@ -1876,6 +1876,44 @@ em_has_pch_ecc(const struct e1000_hw *hw) hw->mac.type < e1000_82575); } +static bool +em_has_82576_memory_errors(const struct e1000_hw *hw) +{ + + return (hw->mac.type == e1000_82576); +} + +static bool +em_82576_has_ipsec(const struct e1000_hw *hw) +{ + + return (hw->device_id != E1000_DEV_ID_82576_NS && + hw->device_id != E1000_DEV_ID_82576_NS_SERDES); +} + +static void +em_configure_82576_memory_errors(struct e1000_softc *sc) +{ + struct e1000_hw *hw; + u32 peindm, reactions; + + hw = &sc->hw; + if (!em_has_82576_memory_errors(hw)) + return; + + reactions = E1000_PEIND_82576_NONFATAL_MASK | + E1000_PEIND_82576_FATAL_MASK | + E1000_PEINDM_82576_PARITY_ENABLE; + if (!em_82576_has_ipsec(hw)) + reactions &= ~E1000_PEIND_82576_IPSEC_MASK; + + /* Discard indications left by firmware before enabling reactions. */ + (void)E1000_READ_REG(hw, E1000_PEIND); + peindm = E1000_READ_REG(hw, E1000_PEINDM); + E1000_WRITE_REG(hw, E1000_PEINDM, peindm | reactions); + E1000_WRITE_FLUSH(hw); +} + static bool em_has_i210_memory_errors(const struct e1000_hw *hw) { @@ -1933,13 +1971,20 @@ em_pcie_fatal_error_mask(const struct e1000_hw *hw) static u32 em_fatal_error_intr_mask(struct e1000_softc *sc) { + u32 mask; - if ((em_has_pch_ecc(&sc->hw) || - em_has_i210_i350_memory_errors(&sc->hw)) && - atomic_load_acq_32(&sc->fatal_error_state) == + if (!em_has_pch_ecc(&sc->hw) && + !em_has_82576_memory_errors(&sc->hw) && + !em_has_i210_i350_memory_errors(&sc->hw)) + return (0); + if (atomic_load_acq_32(&sc->fatal_error_state) != EM_FATAL_ERROR_NONE) - return (E1000_IMS_FER); - return (0); + return (0); + + mask = E1000_IMS_FER; + if (em_has_82576_memory_errors(&sc->hw)) + mask |= E1000_IMS_NFER; + return (mask); } static void @@ -2036,29 +2081,36 @@ em_update_i350_ecc_stats(struct e1000_softc *sc) } /* - * Fatal internal-memory errors stop part or all of the MAC. Capture the - * read-clear indication before handing recovery to the iflib admin task. + * Internal-memory error causes are read-clear. Capture them before handing + * fatal recovery or 82576 non-fatal acknowledgement to the iflib admin task. */ static void em_handle_fatal_error_intr(struct e1000_softc *sc, u32 icr) { struct e1000_hw *hw; - u32 dma_rx, dma_tx, lanerr, pcieerr, peind; + 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)) || - (icr & E1000_ICR_FER) == 0) + (icr & error_mask) == 0) return; hw = &sc->hw; - E1000_WRITE_REG(hw, E1000_IMC, E1000_IMS_FER); + E1000_WRITE_REG(hw, E1000_IMC, error_mask); if (!atomic_cmpset_32(&sc->fatal_error_state, EM_FATAL_ERROR_NONE, EM_FATAL_ERROR_CAPTURING)) return; + sc->fatal_error_icr = icr & error_mask; if (em_has_pch_ecc(hw)) { sc->fatal_error_pbeccsts = E1000_READ_REG(hw, E1000_PBECCSTS); + } else if (em_has_82576_memory_errors(hw)) { + sc->fatal_error_peind = E1000_READ_REG(hw, E1000_PEIND); } else { peind = E1000_READ_REG(hw, E1000_PEIND) & E1000_PEIND_FATAL_MASK; @@ -2097,7 +2149,7 @@ em_handle_fatal_error_intr(struct e1000_softc *sc, u32 icr) static bool em_handle_fatal_error_admin(struct e1000_softc *sc) { - u32 peind; + u32 error_mask, peind; bool reset_required; if (!atomic_cmpset_acq_32(&sc->fatal_error_state, @@ -2111,6 +2163,31 @@ 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_82576_memory_errors(&sc->hw)) { + peind = sc->fatal_error_peind; + reset_required = + (sc->fatal_error_icr & E1000_ICR_FER) != 0 || + (peind & (E1000_PEIND_82576_FATAL_MASK | + E1000_PEIND_82576_MEMORY_HANG)) != 0; + if (!reset_required) { + device_printf(sc->dev, + "non-fatal internal memory error: PEIND %#x\n", + peind); + sc->fatal_error_icr = 0; + sc->fatal_error_peind = 0; + atomic_store_rel_32(&sc->fatal_error_state, + EM_FATAL_ERROR_NONE); + error_mask = E1000_IMS_FER | E1000_IMS_NFER; + E1000_WRITE_REG(&sc->hw, E1000_IMS, error_mask); + E1000_WRITE_FLUSH(&sc->hw); + return (true); + } + if ((peind & (E1000_PEIND_82576_FATAL_MASK | + E1000_PEIND_82576_MEMORY_HANG)) == 0) + sc->fatal_error_unknown_count++; + device_printf(sc->dev, + "fatal internal memory error: PEIND %#x; " + "requesting reset\n", peind); } else { peind = sc->fatal_error_peind; if (peind & E1000_PEIND_LANPORT_PARITY_FATAL) @@ -2238,7 +2315,11 @@ em_finish_fatal_error_reset(struct e1000_softc *sc) return; hw = &sc->hw; - if (em_has_i210_i350_memory_errors(hw)) { + 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; + } else if (em_has_i210_i350_memory_errors(hw)) { pcieerr = sc->fatal_error_pcie | (E1000_READ_REG(hw, E1000_PCIEERRSTS) & em_pcie_fatal_error_mask(hw)); @@ -2277,6 +2358,7 @@ em_finish_fatal_error_reset(struct e1000_softc *sc) sc->fatal_error_dma_tx = 0; sc->fatal_error_dma_rx = 0; } + sc->fatal_error_icr = 0; sc->fatal_error_pbeccsts = 0; atomic_store_rel_32(&sc->fatal_error_state, EM_FATAL_ERROR_NONE); } @@ -3794,6 +3876,7 @@ em_reset(if_ctx_t ctx) device_printf(dev, "Hardware Initialization Failed\n"); return; } + em_configure_82576_memory_errors(sc); em_finish_fatal_error_reset(sc); if (hw->mac.type >= igb_mac_min) igb_init_dmac(sc, pba); @@ -5844,6 +5927,7 @@ em_add_hw_stats(struct e1000_softc *sc) CTLFLAG_RD, &stats->rlpic, "RX LPI event count"); } if (em_has_pch_ecc(&sc->hw) || + em_has_82576_memory_errors(&sc->hw) || em_has_i210_i350_memory_errors(&sc->hw)) { struct sysctl_oid *memerr_node; struct sysctl_oid_list *memerr_list; @@ -5865,6 +5949,11 @@ em_add_hw_stats(struct e1000_softc *sc) "uncorrected_packet_buffer", CTLFLAG_RD, &sc->uncorrected_error_packet_buffer_count, "Uncorrected packet-buffer ECC errors"); + } else if (em_has_82576_memory_errors(&sc->hw)) { + SYSCTL_ADD_UQUAD(ctx, memerr_list, OID_AUTO, + "fatal_unknown", CTLFLAG_RD, + &sc->fatal_error_unknown_count, + "Fatal memory errors without a reported source"); } else { SYSCTL_ADD_UQUAD(ctx, memerr_list, OID_AUTO, "fatal_lan", CTLFLAG_RD, diff --git a/sys/dev/e1000/if_em.h b/sys/dev/e1000/if_em.h index 2ae2c3a8c92d..219ebe7e7414 100644 --- a/sys/dev/e1000/if_em.h +++ b/sys/dev/e1000/if_em.h @@ -619,6 +619,7 @@ struct e1000_softc { int link_mask; int tso_automasked; u32 fatal_error_state; + u32 fatal_error_icr; u32 fatal_error_pbeccsts; u32 fatal_error_peind; u32 fatal_error_pcie;