diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c index 1370df6..b03bc5b 100644 --- a/drivers/ata/sata_sil24.c +++ b/drivers/ata/sata_sil24.c @@ -102,6 +102,7 @@ enum { HOST_CTRL_STOP = (1 << 18), /* latched PCI STOP */ HOST_CTRL_DEVSEL = (1 << 19), /* latched PCI DEVSEL */ HOST_CTRL_REQ64 = (1 << 20), /* latched PCI REQ64 */ + HOST_CTRL_MSIACK = (1 << 30), /* MSI acknowledge */ HOST_CTRL_GLOBAL_RST = (1 << 31), /* global reset */ /* @@ -248,6 +249,7 @@ enum { ATA_FLAG_NCQ | ATA_FLAG_ACPI_SATA | ATA_FLAG_AN | ATA_FLAG_PMP, SIL24_FLAG_PCIX_IRQ_WOC = (1 << 24), /* IRQ loss errata on PCI-X */ + SIL24_FLAG_MSI = (1 << 25), /* MSI enabled */ IRQ_STAT_4PORTS = 0xf, }; @@ -1144,18 +1146,22 @@ static irqreturn_t sil24_interrupt(int irq, void *dev_instance) u32 status; int i; + spin_lock(&host->lock); + + if (host->ports[0]->flags & SIL24_FLAG_MSI) + writel(IRQ_STAT_4PORTS | HOST_CTRL_MSIACK, + host_base + HOST_CTRL); + status = readl(host_base + HOST_IRQ_STAT); if (status == 0xffffffff) { printk(KERN_ERR DRV_NAME ": IRQ status == 0xffffffff, " "PCI fault or device removal?\n"); - goto out; + goto out_unlock; } if (!(status & IRQ_STAT_4PORTS)) - goto out; - - spin_lock(&host->lock); + goto out_unlock; for (i = 0; i < host->n_ports; i++) if (status & (1 << i)) { @@ -1168,8 +1174,8 @@ static irqreturn_t sil24_interrupt(int irq, void *dev_instance) ": interrupt from disabled port %d\n", i); } + out_unlock: spin_unlock(&host->lock); - out: return IRQ_RETVAL(handled); } @@ -1347,6 +1353,7 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (sata_sil24_msi && !pci_enable_msi(pdev)) { dev_printk(KERN_INFO, &pdev->dev, "Using MSI\n"); pci_intx(pdev, 0); + host->ports[0]->flags |= SIL24_FLAG_MSI; } pci_set_master(pdev);