This patch adds the support to handle HOST_IRQ_STAT as edge trigger latch. Signed-off-by: Suman Tripathi <stripathi@xxxxxxx> --- drivers/ata/ahci.h | 2 ++ drivers/ata/libahci.c | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h index 71262e0..2df2237 100644 --- a/drivers/ata/ahci.h +++ b/drivers/ata/ahci.h @@ -238,6 +238,8 @@ enum { 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_TRIG_IRQ = (1 << 19), /* HOST_IRQ_STAT behaves as + Edge Triggered */ /* ap->flags bits */ diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index 61a9c07..0e7e8b4 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -1879,6 +1879,25 @@ static irqreturn_t ahci_single_irq_intr(int irq, void *dev_instance) */ writel(irq_stat, mmio + HOST_IRQ_STAT); + /* + * HOST_IRQ_STAT behaves as edge trigger latch. When HOST_IRQ_STAT + * detects a egde from PORT_IRQ_STAT, it happens to loose interrupts + * when interrupts are triggered from both ports. So handling of + * the residual interrupt is required. + */ + if (hpriv->flags & AHCI_HFLAG_EDGE_TRIG_IRQ) { + for (i = 0; i < host->n_ports; i++) { + struct ata_port *ap; + + ap = host->ports[i]; + if (ap) { + ahci_port_intr(ap); + VPRINTK("Residual irq from port %u\n", i); + } + handled = 1; + } + } + spin_unlock(&host->lock); VPRINTK("EXIT\n"); -- 1.8.2.1 -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html