aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin Hibbits <jhibbits@FreeBSD.org>2026-01-21 04:19:28 +0000
committerJustin Hibbits <jhibbits@FreeBSD.org>2026-01-21 04:28:41 +0000
commit21a7a9ef8b49ce21b87c8526b526f97cc91fdd43 (patch)
treeba784d7afe3ce464211dcfca5478556c0a91fdb5
parent24d048be7aae10e101596bd0d0f09a901a6f97f0 (diff)
powerpc/mpc85xx: Fix PCI attach error cleanup
If an error occurs during attach after ofw_pcib_init() runs, the device is torn down, leaving the rmans embedded in the softc attached to the rman list, thus corrupting the rman list. Fix this by undoing everything that was done by this point. MFC after: 1 week
-rw-r--r--sys/powerpc/mpc85xx/pci_mpc85xx.c19
1 files changed, 17 insertions, 2 deletions
diff --git a/sys/powerpc/mpc85xx/pci_mpc85xx.c b/sys/powerpc/mpc85xx/pci_mpc85xx.c
index 8e349df03a51..33dca7ab6c50 100644
--- a/sys/powerpc/mpc85xx/pci_mpc85xx.c
+++ b/sys/powerpc/mpc85xx/pci_mpc85xx.c
@@ -360,13 +360,13 @@ fsl_pcib_attach(device_t dev)
error = ofw_pcib_init(dev);
if (error)
- return (error);
+ goto err;
/*
* Configure decode windows for PCI(E) access.
*/
if (fsl_pcib_decode_win(node, sc) != 0)
- goto err;
+ goto err1;
cfgreg = fsl_pcib_cfgread(sc, 0, 0, 0, PCIR_COMMAND, 2);
cfgreg |= PCIM_CMD_SERRESPEN | PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN |
@@ -392,6 +392,7 @@ fsl_pcib_attach(device_t dev)
if (sc->sc_pcie) {
ltssm = fsl_pcib_cfgread(sc, 0, 0, 0, PCIR_LTSSM, 1);
if (ltssm < LTSSM_STAT_L0) {
+ /* Stay attached, it may change later. */
if (bootverbose)
printf("PCI %d: no PCIE link, skipping\n",
device_get_unit(dev));
@@ -432,7 +433,15 @@ fsl_pcib_attach(device_t dev)
return (ofw_pcib_attach(dev));
+err1:
+ ofw_pcib_fini(dev);
err:
+ if (sc->sc_irq_res != NULL)
+ bus_release_resource(dev, sc->sc_irq_res);
+ if (sc->sc_res != NULL)
+ bus_release_resource(dev, sc->sc_res);
+ mtx_destroy(&sc->sc_cfg_mtx);
+
return (ENXIO);
}
@@ -680,9 +689,15 @@ fsl_pcib_detach(device_t dev)
return (error);
sc = device_get_softc(dev);
+ ofw_pcib_fini(dev);
mtx_destroy(&sc->sc_cfg_mtx);
+ if (sc->sc_irq_res != NULL)
+ bus_release_resource(dev, sc->sc_irq_res);
+ if (sc->sc_res != NULL)
+ bus_release_resource(dev, sc->sc_res);
+
return (0);
}