AHCI_HFLAG_MULTI_MSI = (1 << 16), /* multiple PCI MSIs */
AHCI_HFLAG_NO_DEVSLP = (1 << 17), /* no device sleep */
AHCI_HFLAG_NO_FBS = (1 << 18), /* no FBS */
+ AHCI_HFLAG_EDGE_IRQ = (1 << 19), /* HOST_IRQ_STAT behaves as
+ Edge Triggered */
/* ap->flags bits */
return handled;
}
+static irqreturn_t ahci_single_edge_irq_intr(int irq, void *dev_instance)
+{
+ struct ata_host *host = dev_instance;
+ struct ahci_host_priv *hpriv;
+ unsigned int rc = 0;
+ void __iomem *mmio;
+ u32 irq_stat, irq_masked;
+
+ VPRINTK("ENTER\n");
+
+ hpriv = host->private_data;
+ mmio = hpriv->mmio;
+
+ /* sigh. 0xffffffff is a valid return from h/w */
+ irq_stat = readl(mmio + HOST_IRQ_STAT);
+ if (!irq_stat)
+ return IRQ_NONE;
+
+ irq_masked = irq_stat & hpriv->port_map;
+
+ spin_lock(&host->lock);
+
+ /*
+ * HOST_IRQ_STAT behaves as edge triggered latch meaning that
+ * it should be cleared before all the port events are cleared.
+ */
+ writel(irq_stat, mmio + HOST_IRQ_STAT);
+
+ rc = ahci_handle_port_intr(host, irq_masked);
+
+ spin_unlock(&host->lock);
+
+ VPRINTK("EXIT\n");
+
+ return IRQ_RETVAL(rc);
+}
+
static irqreturn_t ahci_single_level_irq_intr(int irq, void *dev_instance)
{
struct ata_host *host = dev_instance;
if (hpriv->flags & AHCI_HFLAG_MULTI_MSI)
rc = ahci_host_activate_multi_irqs(host, irq, sht);
+ else if (hpriv->flags & AHCI_HFLAG_EDGE_IRQ)
+ rc = ata_host_activate(host, irq, ahci_single_edge_irq_intr,
+ IRQF_SHARED, sht);
else
rc = ata_host_activate(host, irq, ahci_single_level_irq_intr,
IRQF_SHARED, sht);