git: df5bdb59bc89 - stable/15 - e1000: Propagate hardware initialization failures

From: Kevin Bowling <kbowling_at_FreeBSD.org>
Date: Sun, 30 Aug 2026 01:37:54 UTC
The branch stable/15 has been updated by kbowling:

URL: https://cgit.FreeBSD.org/src/commit/?id=df5bdb59bc89365d06296cab813cad33807e94e1

commit df5bdb59bc89365d06296cab813cad33807e94e1
Author:     Kevin Bowling <kbowling@FreeBSD.org>
AuthorDate: 2026-08-16 07:55:37 +0000
Commit:     Kevin Bowling <kbowling@FreeBSD.org>
CommitDate: 2026-08-30 01:31:48 +0000

    e1000: Propagate hardware initialization failures
    
    The reset helper discards reset_hw and init_hw errors.  Runtime
    initialization then continues programming rings and filters, and iflib
    publishes the interface as running even though the controller did not
    reach a usable state.  Initial attach similarly continues into NVM and
    MAC setup after a failed reset.
    
    Return errors from the reset helper.  Fail attach when the controller
    cannot be reset or initialized, and report runtime failures through
    iflib_init_failed() so iflib leaves the interface stopped.  Also stop
    register accesses and report the error when a stop-path reset fails.
    
    Sponsored by:   BBOX.io
    
    (cherry picked from commit 41a0f7a0a447ef2092faadb35f6d4c3f80c088bf)
---
 sys/dev/e1000/if_em.c | 51 +++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 41 insertions(+), 10 deletions(-)

diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c
index b1b4fb6f6b1a..7f1da9fb7d3f 100644
--- a/sys/dev/e1000/if_em.c
+++ b/sys/dev/e1000/if_em.c
@@ -427,7 +427,7 @@ static bool	em_if_needs_restart(if_ctx_t, enum iflib_restart_event);
 static void	em_identify_hardware(if_ctx_t);
 static int	em_allocate_pci_resources(if_ctx_t);
 static void	em_free_pci_resources(if_ctx_t);
-static void	em_reset(if_ctx_t);
+static int	em_reset(if_ctx_t);
 static int	em_setup_interface(if_ctx_t);
 static int	em_setup_msix(if_ctx_t);
 
@@ -1346,7 +1346,12 @@ em_if_attach_pre(if_ctx_t ctx)
 	** important in reading the nvm and
 	** mac from that.
 	*/
-	e1000_reset_hw(hw);
+	error = e1000_reset_hw(hw);
+	if (!sc->vf_ifp && error != E1000_SUCCESS) {
+		device_printf(dev, "Hardware reset failed: %d\n", error);
+		error = EIO;
+		goto err_late;
+	}
 
 	/* Make sure we have a good EEPROM before we read from it */
 	if (e1000_validate_nvm_checksum(hw) < 0) {
@@ -1424,7 +1429,12 @@ em_if_attach_post(if_ctx_t ctx)
 		goto err_late;
 	}
 
-	em_reset(ctx);
+	if (sc->vf_ifp) {
+		(void)em_reset(ctx);
+	} else if (em_reset(ctx) != E1000_SUCCESS) {
+		error = EIO;
+		goto err_late;
+	}
 
 	/* Initialize statistics */
 	if (sc->vf_ifp)
@@ -1608,7 +1618,12 @@ em_if_init(if_ctx_t ctx)
 	}
 
 	/* Initialize the hardware */
-	em_reset(ctx);
+	if (sc->vf_ifp) {
+		(void)em_reset(ctx);
+	} else if (em_reset(ctx) != E1000_SUCCESS) {
+		iflib_init_failed(ctx);
+		return;
+	}
 	/* Re-arm a link-up transition deferred for this reset. */
 	if (sc->link_state == EM_LINK_STATE_DOWN_RESET_PENDING ||
 	    sc->link_state == EM_LINK_STATE_UP_RESET_PENDING)
@@ -3058,6 +3073,7 @@ static void
 em_if_stop(if_ctx_t ctx)
 {
 	struct e1000_softc *sc = iflib_get_softc(ctx);
+	s32 error;
 
 	INIT_DEBUGOUT("em_if_stop: begin");
 
@@ -3066,7 +3082,12 @@ em_if_stop(if_ctx_t ctx)
 		em_flush_desc_rings(sc);
 
 	em_prepare_fatal_error_reset(sc);
-	e1000_reset_hw(&sc->hw);
+	error = e1000_reset_hw(&sc->hw);
+	if (!sc->vf_ifp && error != E1000_SUCCESS) {
+		device_printf(sc->dev, "Hardware reset failed while "
+		    "stopping: %d\n", error);
+		return;
+	}
 	if (sc->hw.mac.type >= e1000_82544 && !sc->vf_ifp)
 		E1000_WRITE_REG(&sc->hw, E1000_WUFC, 0);
 
@@ -3755,7 +3776,7 @@ em_flush_desc_rings(struct e1000_softc *sc)
  *  sc structure.
  *
  **********************************************************************/
-static void
+static int
 em_reset(if_ctx_t ctx)
 {
 	device_t dev = iflib_get_dev(ctx);
@@ -3764,6 +3785,7 @@ em_reset(if_ctx_t ctx)
 	struct e1000_hw *hw = &sc->hw;
 	u32 rx_buffer_size;
 	u32 pba;
+	s32 error;
 
 	INIT_DEBUGOUT("em_reset: begin");
 	/* Let the firmware know the OS is in control */
@@ -3995,7 +4017,12 @@ em_reset(if_ctx_t ctx)
 
 	/* Issue a global reset */
 	em_prepare_fatal_error_reset(sc);
-	e1000_reset_hw(hw);
+	error = e1000_reset_hw(hw);
+	if (error != E1000_SUCCESS) {
+		if (!sc->vf_ifp)
+			device_printf(dev, "Hardware reset failed: %d\n", error);
+		return (error);
+	}
 	if (!sc->vf_ifp) {
 		if (hw->mac.type >= igb_mac_min) {
 			E1000_WRITE_REG(hw, E1000_WUC, 0);
@@ -4010,9 +4037,11 @@ em_reset(if_ctx_t ctx)
 		sc->flags &= ~IGB_MEDIA_RESET;
 	}
 	/* and a re-init */
-	if (e1000_init_hw(hw) < 0) {
-		device_printf(dev, "Hardware Initialization Failed\n");
-		return;
+	error = e1000_init_hw(hw);
+	if (error != E1000_SUCCESS) {
+		device_printf(dev, "Hardware initialization failed: %d\n",
+		    error);
+		return (error);
 	}
 	em_configure_82576_memory_errors(sc);
 	em_finish_fatal_error_reset(sc);
@@ -4025,6 +4054,8 @@ em_reset(if_ctx_t ctx)
 	E1000_WRITE_REG(hw, E1000_VET, ETHERTYPE_VLAN);
 	e1000_get_phy_info(hw);
 	e1000_check_for_link(hw);
+
+	return (E1000_SUCCESS);
 }
 
 /*