summary refs log tree commit diff
path: root/drivers/ata/libahci.c
diff options
context:
space:
mode:
authorSuman Tripathi <stripathi@apm.com>2015-05-06 00:51:11 +0530
committerTejun Heo <tj@kernel.org>2015-05-10 11:52:44 -0400
commit5903b1643f41ccc0cb3a0cde1d12b1c942914317 (patch)
tree73de1cbc4f0a63194f8b9ab6d23a327c3c93cc8e /drivers/ata/libahci.c
parenta129db89d865b1b91995989bcdee783358d774a5 (diff)
downloadlinux-5903b1643f41ccc0cb3a0cde1d12b1c942914317.tar.gz
libahci: Add support to handle HOST_IRQ_STAT as edge trigger latch.
This patch adds the support to handle HOST_IRQ_STAT as edge trigger
latch.

Signed-off-by: Suman Tripathi <stripathi@apm.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'drivers/ata/libahci.c')
-rw-r--r--drivers/ata/libahci.c40
1 files changed, 40 insertions, 0 deletions
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index aa89c8eecd76..1add5baec584 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -1853,6 +1853,43 @@ static u32 ahci_handle_port_intr(struct ata_host *host, u32 irq_masked)
 	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;
@@ -2495,6 +2532,9 @@ int ahci_host_activate(struct ata_host *host, int irq,
 
 	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);