--- a/sys/dev/raid/amr/amr_pci.c +++ b/sys/dev/raid/amr/amr_pci.c @@ -253,15 +253,6 @@ - /* - * Allocate and connect our interrupt. - */ - rid = 0; - sc->amr_irq = bus_alloc_resource_any(sc->amr_dev, SYS_RES_IRQ, &rid, - RF_SHAREABLE | RF_ACTIVE); - if (sc->amr_irq == NULL) { - device_printf(sc->amr_dev, "can't allocate interrupt\n"); - goto out; - } - if (bus_setup_intr(sc->amr_dev, sc->amr_irq, - INTR_MPSAFE, amr_pci_intr, - sc, &sc->amr_intr, NULL)) { - device_printf(sc->amr_dev, "can't set up interrupt\n"); - goto out; - } - - debug(2, "interrupt attached"); - /* assume failure is 'out of memory' */ error = ENOMEM; @@ -343,8 +334,25 @@ /* * Do bus-independant initialisation, bring controller online. */ error = amr_attach(sc); + if (error != 0) + goto out; + + /* + * Connect our interrupt only once the handler's state exists + * (amr_get_work dispatch, locks, mailbox DMA all initialised by + * amr_attach); a shared-line IRQ before that point would call + * amr_done() -> sc->amr_get_work() while still NULL. + */ + rid = 0; + sc->amr_irq = bus_alloc_resource_any(sc->amr_dev, SYS_RES_IRQ, &rid, + RF_SHAREABLE | RF_ACTIVE); + if (sc->amr_irq == NULL) { + device_printf(sc->amr_dev, "can't allocate interrupt\n"); + error = ENXIO; + goto out; + } + if (bus_setup_intr(sc->amr_dev, sc->amr_irq, + INTR_MPSAFE, amr_pci_intr, + sc, &sc->amr_intr, NULL)) { + device_printf(sc->amr_dev, "can't set up interrupt\n"); + error = ENXIO; + goto out; + } + debug(2, "interrupt attached"); out: if (error) --- a/sys/dev/raid/amr/amr_pci.c +++ b/sys/dev/raid/amr/amr_pci.c @@ -461,6 +461,9 @@ amr_pci_intr(void *arg) debug_called(3); + if ((sc->amr_state & AMR_STATE_INTEN) == 0) + return; /* not our interrupt / not initialised */ + /* collect finished commands, queue anything waiting */ amr_done(sc); }