diff options
| author | Justin Hibbits <jhibbits@FreeBSD.org> | 2026-01-21 04:19:28 +0000 |
|---|---|---|
| committer | Justin Hibbits <jhibbits@FreeBSD.org> | 2026-01-21 04:28:41 +0000 |
| commit | 21a7a9ef8b49ce21b87c8526b526f97cc91fdd43 (patch) | |
| tree | ba784d7afe3ce464211dcfca5478556c0a91fdb5 | |
| parent | 24d048be7aae10e101596bd0d0f09a901a6f97f0 (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.c | 19 |
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); } |
