Re: MSI broken in libata?

From: Tejun Heo
Date: Sun Jan 10 2010 - 20:14:16 EST


On 01/10/2010 01:33 PM, Torsten Kaiser wrote:
> I did try the patch from Robert Hancock in
> http://lkml.org/lkml/2010/1/6/417 ,but without success.
>
> if you need any more information, or have something for me to try,
> please just ask. I did look at the code and the documentation about
> enabling MSI, but did not see anything (obvious) wrong, so I don't
> know what to try next.

Can you please try the attached patch?

Thanks.

--
tejun
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);