DF-4725 / fix.diff
--- a/sys/dev/sound/pci/aureal.c +++ b/sys/dev/sound/pci/aureal.c @@ -596,7 +596,7 @@ au_pci_attach(device_t dev) #endif if (reg[j]) { au->st[i] = rman_get_bustag(reg[j]); au->sh[i] = rman_get_bushandle(reg[j]); mapped++; } @@ -604,7 +604,7 @@ au_pci_attach(device_t dev) #endif - if (mapped) j++; + if (reg[j]) j++; /* only count mapped BARs so bad: never + sees a NULL reg[i] (DF-4725) */ if (j == 10) { /* XXX */ device_printf(dev, "too many resources"); goto bad; } @@ -655,14 +655,19 @@ au_pci_attach(device_t dev) return 0; bad: - if (au) free(au, M_DEVBUF); + /* + * Unwind in dependency order (DF-4725): the IRQ handler still + * references `au`, so it must be torn down BEFORE au is freed; + * skip reg[] slots that never mapped; free au LAST. + */ + if (ih) bus_teardown_intr(dev, irq, ih); + if (irq) bus_release_resource(dev, SYS_RES_IRQ, irqid, irq); for (i = 0; i < j; i++) - bus_release_resource(dev, type[i], regid[i], reg[i]); - if (ih) bus_teardown_intr(dev, irq, ih); - if (irq) bus_release_resource(dev, SYS_RES_IRQ, irqid, irq); + if (reg[i] != NULL) + bus_release_resource(dev, type[i], regid[i], reg[i]); + if (au) free(au, M_DEVBUF); return ENXIO; } |