--- a/sys/dev/raid/iir/iir_pci.c +++ b/sys/dev/raid/iir/iir_pci.c @@ -178,7 +178,7 @@ iir_pci_attach(device_t dev) { struct gdt_softc *gdt; struct resource *io = NULL, *irq = NULL; - int retries, rid, error = 0; + int retries, io_rid, rid, error = 0; void *ih; u_int8_t protocol; @@ -190,6 +190,7 @@ iir_pci_attach(device_t dev) error = ENOMEM; goto err; } + io_rid = rid; /* get IRQ */ rid = 0; @@ -336,6 +337,27 @@ iir_pci_attach(device_t dev) error = bus_setup_intr(dev, irq, 0, iir_intr, gdt, &ih, NULL); if (error) { device_printf(dev, "Unable to register interrupt handler\n"); + /* + * Undo everything iir_init()/iir_attach() set up: XPT SIMs, + * the shutdown handler, the control device and all DMA state. + * Buses whose xpt_create_path() failed were already torn down + * inside iir_attach() itself, so only buses with a live path + * are deregistered here. + */ + if (gdt->sc_shutdown_eh != NULL) { + EVENTHANDLER_DEREGISTER(shutdown_post_sync, gdt->sc_shutdown_eh); + gdt->sc_shutdown_eh = NULL; + } + for (rid = 0; rid < GDT_MAXBUS; rid++) { + if (gdt->paths[rid] != NULL) { + xpt_free_path(gdt->paths[rid]); + gdt->paths[rid] = NULL; + xpt_bus_deregister(cam_sim_path(gdt->sims[rid])); + cam_sim_free(gdt->sims[rid]); + gdt->sims[rid] = NULL; + } + } + iir_free(gdt); error = ENXIO; goto err; } @@ -346,10 +368,8 @@ iir_pci_attach(device_t dev) err: if (irq) bus_release_resource( dev, SYS_RES_IRQ, 0, irq ); -/* if (io) - bus_release_resource( dev, SYS_RES_MEMORY, rid, io ); -*/ + bus_release_resource( dev, SYS_RES_MEMORY, io_rid, io ); return (error); } --- a/sys/dev/raid/iir/iir.h +++ b/sys/dev/raid/iir/iir.h @@ -659,6 +659,7 @@ struct gdt_softc { struct cam_sim *sims[GDT_MAXBUS]; struct cam_path *paths[GDT_MAXBUS]; + eventhandler_tag sc_shutdown_eh; void (*sc_copy_cmd)(struct gdt_softc *, struct gdt_ccb *); u_int8_t (*sc_get_status)(struct gdt_softc *); --- a/sys/dev/raid/iir/iir.c +++ b/sys/dev/raid/iir/iir.c @@ -511,8 +511,9 @@ iir_attach(struct gdt_softc *gdt) } cam_simq_release(devq); if (i > 0) - EVENTHANDLER_REGISTER(shutdown_post_sync, iir_shutdown, - gdt, SHUTDOWN_PRI_DRIVER); + gdt->sc_shutdown_eh = EVENTHANDLER_REGISTER(shutdown_post_sync, + iir_shutdown, + gdt, SHUTDOWN_PRI_DRIVER); gdt->sc_state = GDT_NORMAL; }