git: 640916dc50a6 - stable/15 - igc: Propagate hardware initialization failures
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sun, 30 Aug 2026 01:37:55 UTC
The branch stable/15 has been updated by kbowling:
URL: https://cgit.FreeBSD.org/src/commit/?id=640916dc50a6fd88eddad312f9e0e21404211f52
commit 640916dc50a6fd88eddad312f9e0e21404211f52
Author: Kevin Bowling <kbowling@FreeBSD.org>
AuthorDate: 2026-08-16 07:56:03 +0000
Commit: Kevin Bowling <kbowling@FreeBSD.org>
CommitDate: 2026-08-30 01:32:08 +0000
igc: Propagate hardware initialization failures
The reset helper discards igc_reset_hw and igc_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. A
later successful initialization completes pending fatal error cleanup
and re-arms FER.
Cache a requested MAC address before reset, but let init_hw program RAR0
after reset succeeds. Let iflib perform its normal attach-post failure
cleanup instead of releasing the same driver resources from both layers,
and make queue cleanup idempotent.
Sponsored by: BBOX.io
(cherry picked from commit c82a015ede8d49aabc8bb253b7597b8db0f42524)
---
sys/dev/igc/if_igc.c | 62 ++++++++++++++++++++++++++++++++--------------------
1 file changed, 38 insertions(+), 24 deletions(-)
diff --git a/sys/dev/igc/if_igc.c b/sys/dev/igc/if_igc.c
index eae83a673786..3ea000509c6e 100644
--- a/sys/dev/igc/if_igc.c
+++ b/sys/dev/igc/if_igc.c
@@ -118,7 +118,7 @@ static void igc_identify_hardware(if_ctx_t);
static int igc_allocate_pci_resources(if_ctx_t);
static void igc_free_pci_resources(if_ctx_t);
static void igc_disable_broken_l1_2(if_ctx_t);
-static void igc_reset(if_ctx_t);
+static int igc_reset(if_ctx_t);
static int igc_setup_interface(if_ctx_t);
static int igc_setup_msix(if_ctx_t);
@@ -678,7 +678,12 @@ igc_if_attach_pre(if_ctx_t ctx)
** important in reading the nvm and
** mac from that.
*/
- igc_reset_hw(hw);
+ error = igc_reset_hw(hw);
+ if (error != IGC_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 (igc_validate_nvm_checksum(hw) < 0) {
@@ -746,11 +751,11 @@ igc_if_attach_post(if_ctx_t ctx)
/* Setup OS specific network interface */
error = igc_setup_interface(ctx);
- if (error != 0) {
- goto err_late;
- }
+ if (error != 0)
+ return (error);
- igc_reset(ctx);
+ if (igc_reset(ctx) != IGC_SUCCESS)
+ return (EIO);
/* Initialize statistics */
igc_update_stats_counters(sc);
@@ -763,14 +768,6 @@ igc_if_attach_post(if_ctx_t ctx)
INIT_DEBUGOUT("igc_if_attach_post: end");
- return (error);
-
-err_late:
- igc_release_hw_control(sc);
- igc_free_pci_resources(ctx);
- igc_if_queues_free(ctx);
- free(sc->mta, M_DEVBUF);
-
return (error);
}
@@ -880,11 +877,11 @@ igc_if_init(if_ctx_t ctx)
bcopy(if_getlladdr(ifp), sc->hw.mac.addr,
ETHER_ADDR_LEN);
- /* Put the address into the Receive Address Array */
- igc_rar_set(&sc->hw, sc->hw.mac.addr, 0);
-
/* Initialize the hardware */
- igc_reset(ctx);
+ if (igc_reset(ctx) != IGC_SUCCESS) {
+ iflib_init_failed(ctx);
+ return;
+ }
igc_if_update_admin_status(ctx);
for (i = 0, tx_que = sc->tx_queues; i < sc->tx_num_queues;
@@ -1621,12 +1618,18 @@ static void
igc_if_stop(if_ctx_t ctx)
{
struct igc_softc *sc = iflib_get_softc(ctx);
+ s32 error;
INIT_DEBUGOUT("igc_if_stop: begin");
igc_led_restore(sc);
igc_prepare_fatal_error_reset(sc);
- igc_reset_hw(&sc->hw);
+ error = igc_reset_hw(&sc->hw);
+ if (error != IGC_SUCCESS) {
+ device_printf(sc->dev, "Hardware reset failed while stopping: "
+ "%d\n", error);
+ return;
+ }
igc_finish_fatal_error_reset(sc);
IGC_WRITE_REG(&sc->hw, IGC_WUC, 0);
}
@@ -2130,7 +2133,7 @@ igc_init_dmac(struct igc_softc *sc, u32 pba)
* softc structure.
*
**********************************************************************/
-static void
+static int
igc_reset(if_ctx_t ctx)
{
device_t dev = iflib_get_dev(ctx);
@@ -2138,6 +2141,7 @@ igc_reset(if_ctx_t ctx)
struct igc_hw *hw = &sc->hw;
u32 rx_buffer_size;
u32 pba;
+ s32 error;
INIT_DEBUGOUT("igc_reset: begin");
igc_led_restore(sc);
@@ -2184,14 +2188,21 @@ igc_reset(if_ctx_t ctx)
hw->fc.send_xon = true;
/* Issue a global reset */
- igc_reset_hw(hw);
+ error = igc_reset_hw(hw);
+ if (error != IGC_SUCCESS) {
+ device_printf(dev, "Hardware reset failed: %d\n", error);
+ return (error);
+ }
IGC_WRITE_REG(hw, IGC_WUC, 0);
/* and a re-init */
- if (igc_init_hw(hw) < 0) {
- device_printf(dev, "Hardware Initialization Failed\n");
- return;
+ error = igc_init_hw(hw);
+ if (error != IGC_SUCCESS) {
+ device_printf(dev, "Hardware initialization failed: %d\n",
+ error);
+ return (error);
}
+ igc_finish_fatal_error_reset(sc);
/* Setup DMA Coalescing */
igc_init_dmac(sc, pba);
@@ -2202,6 +2213,8 @@ igc_reset(if_ctx_t ctx)
IGC_WRITE_REG(hw, IGC_VET, ETHERTYPE_VLAN);
igc_get_phy_info(hw);
igc_check_for_link(hw);
+
+ return (IGC_SUCCESS);
}
/*
@@ -2468,6 +2481,7 @@ igc_if_queues_free(if_ctx_t ctx)
if (sc->mta != NULL) {
free(sc->mta, M_DEVBUF);
+ sc->mta = NULL;
}
}