Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5903b164 authored by Suman Tripathi's avatar Suman Tripathi Committed by Tejun Heo
Browse files

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: default avatarSuman Tripathi <stripathi@apm.com>
Signed-off-by: default avatarTejun Heo <tj@kernel.org>
parent a129db89
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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_IRQ		= (1 << 19), /* HOST_IRQ_STAT behaves as
							Edge Triggered */

	/* ap->flags bits */

+40 −0
Original line number Diff line number Diff line
@@ -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);