DF-4818 / fix.diff
--- a/sys/dev/disk/nvme/nvme_attach.c +++ b/sys/dev/disk/nvme/nvme_attach.c @@ -101,6 +101,7 @@ int error; int msi_enable; int msix_enable; + int msix_setup_ok; #if 0 if (pci_read_config(dev, PCIR_COMMAND, 2) & 0x0400) { @@ -156,6 +157,7 @@ sc->nirqs = ncpus + 1; error = pci_setup_msix(dev); + msix_setup_ok = (error == 0); cpu = (last_global_cpu + 0) % ncpus; /* GCC warn */ for (i = 0; error == 0 && i < sc->nirqs; ++i) { cpu = (last_global_cpu + i) % ncpus; @@ -166,6 +168,10 @@ sc->irq[i] = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->rid_irq[i], RF_ACTIVE); + if (sc->irq[i] == NULL) { + error = ENODEV; + break; + } /* * We want this to overwrite queue 0's cpu vector * when the cpu's rotate through later on. @@ -197,6 +203,13 @@ pci_release_msix_vector(dev, sc->rid_irq[i]); sc->irq[i] = NULL; } + /* + * Tear the MSI-X setup down so the fallback (and a + * possible later re-attach) does not trip over a + * half-configured MSI-X state. + */ + if (msix_setup_ok) + pci_teardown_msix(dev); /* leave error intact to fall through to normal */ } else { last_global_cpu = (last_global_cpu + sc->nirqs) % ncpus; |