From 82ac698a63ae11bd8f61ecced94b4d7f4bdcea48 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 5 Jul 2008 13:10:50 +0900 Subject: [PATCH] --- yaml --- r: 98728 b: refs/heads/master c: d28f87aa87ce8b196349d7c306a7e6fe3abd7155 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/drivers/ata/ahci.c | 16 +++++++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/[refs] b/[refs] index 729c5d717603..7ac7a832a3c6 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: d79df630f622806c4d0e116fbaf6ebf6baf53461 +refs/heads/master: d28f87aa87ce8b196349d7c306a7e6fe3abd7155 diff --git a/trunk/drivers/ata/ahci.c b/trunk/drivers/ata/ahci.c index 061817a3a0e5..5e6468a7ca4b 100644 --- a/trunk/drivers/ata/ahci.c +++ b/trunk/drivers/ata/ahci.c @@ -1777,7 +1777,7 @@ static irqreturn_t ahci_interrupt(int irq, void *dev_instance) struct ahci_host_priv *hpriv; unsigned int i, handled = 0; void __iomem *mmio; - u32 irq_stat; + u32 irq_stat, irq_masked; VPRINTK("ENTER\n"); @@ -1786,16 +1786,17 @@ static irqreturn_t ahci_interrupt(int irq, void *dev_instance) /* sigh. 0xffffffff is a valid return from h/w */ irq_stat = readl(mmio + HOST_IRQ_STAT); - irq_stat &= hpriv->port_map; if (!irq_stat) return IRQ_NONE; + irq_masked = irq_stat & hpriv->port_map; + spin_lock(&host->lock); for (i = 0; i < host->n_ports; i++) { struct ata_port *ap; - if (!(irq_stat & (1 << i))) + if (!(irq_masked & (1 << i))) continue; ap = host->ports[i]; @@ -1812,6 +1813,15 @@ static irqreturn_t ahci_interrupt(int irq, void *dev_instance) handled = 1; } + /* HOST_IRQ_STAT behaves as level triggered latch meaning that + * it should be cleared after all the port events are cleared; + * otherwise, it will raise a spurious interrupt after each + * valid one. Please read section 10.6.2 of ahci 1.1 for more + * information. + * + * Also, use the unmasked value to clear interrupt as spurious + * pending event on a dummy port might cause screaming IRQ. + */ writel(irq_stat, mmio + HOST_IRQ_STAT); spin_unlock(&host->lock);