diff --git a/sys/dev/ata/ata-pci.c b/sys/dev/ata/ata-pci.c index 303a05fd9e94..62d41d0f29e4 100644 --- a/sys/dev/ata/ata-pci.c +++ b/sys/dev/ata/ata-pci.c @@ -150,7 +150,9 @@ ata_pci_detach(device_t dev) if (ctlr->r_irq) { bus_teardown_intr(dev, ctlr->r_irq, ctlr->handle); - bus_release_resource(dev, SYS_RES_IRQ, ATA_IRQ_RID, ctlr->r_irq); + bus_release_resource(dev, SYS_RES_IRQ, ctlr->r_irq_rid, ctlr->r_irq); + if (ctlr->r_irq_rid != ATA_IRQ_RID) + pci_release_msi(dev); } if (ctlr->r_res2) bus_release_resource(dev, ctlr->r_type2, ctlr->r_rid2, ctlr->r_res2); @@ -653,11 +655,19 @@ int ata_setup_interrupt(device_t dev, void *intr_func) { struct ata_pci_controller *ctlr = device_get_softc(dev); - int rid = ATA_IRQ_RID; + int i, msi = 0; if (!ctlr->legacy) { - if (!(ctlr->r_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, - RF_SHAREABLE | RF_ACTIVE))) { + if (resource_int_value(device_get_name(dev), + device_get_unit(dev), "msi", &i) == 0 && i != 0) + msi = 1; + if (msi && pci_msi_count(dev) > 0 && pci_alloc_msi(dev, &msi) == 0) { + ctlr->r_irq_rid = 0x1; + } else { + ctlr->r_irq_rid = ATA_IRQ_RID; + } + if (!(ctlr->r_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, + &ctlr->r_irq_rid, RF_SHAREABLE | RF_ACTIVE))) { device_printf(dev, "unable to map interrupt\n"); return ENXIO; } diff --git a/sys/dev/ata/ata-pci.h b/sys/dev/ata/ata-pci.h index e5edd8760784..a31f30eed51e 100644 --- a/sys/dev/ata/ata-pci.h +++ b/sys/dev/ata/ata-pci.h @@ -45,6 +45,7 @@ struct ata_pci_controller { int r_type2; int r_rid2; struct resource *r_res2; + int r_irq_rid; struct resource *r_irq; void *handle; struct ata_chip_id *chip;