+++ /dev/null
-From: Tejun Heo <tj@kernel.org>
-Subject: ata_piix: detect and clear spurious IRQs
-References: bnc#445872
-
-The DMA_IRQ bit in the bmdma status register is always set when IDEIRQ
-is asserted allowing spurious IRQ detection. Detect spurious IRQs and
-clear them. This protects ata_piix against nobody-cared which gets
-reported not so rarely.
-
-Signed-off-by: Tejun Heo <tj@kernel.org>
-Signed-off-by: Tejun Heo <teheo@suse.de>
----
- drivers/ata/ata_piix.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++-
- 1 file changed, 53 insertions(+), 1 deletion(-)
-
---- a/drivers/ata/ata_piix.c
-+++ b/drivers/ata/ata_piix.c
-@@ -923,6 +923,58 @@ static int piix_sidpr_scr_read(struct at
- return 0;
- }
-
-+static irqreturn_t piix_interrupt(int irq, void *dev_instance)
-+{
-+ struct ata_host *host = dev_instance;
-+ unsigned int i;
-+ unsigned int handled = 0;
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&host->lock, flags);
-+
-+ for (i = 0; i < host->n_ports; i++) {
-+ struct ata_port *ap = host->ports[i];
-+ struct ata_queued_cmd *qc;
-+ u8 host_stat;
-+
-+ if (ata_port_is_dummy(ap))
-+ continue;
-+
-+ qc = ata_qc_from_tag(ap, ap->link.active_tag);
-+ if (qc && !(qc->tf.flags & ATA_TFLAG_POLLING)) {
-+ handled |= ata_sff_host_intr(ap, qc);
-+ continue;
-+ }
-+
-+ /*
-+ * Control reaches here if HSM is not expecting IRQ.
-+ * If the controller is actually asserting IRQ line,
-+ * this will lead to nobody cared. Fortuantely,
-+ * DMA_INTR of PIIX is set whenever IDEIRQ is set so
-+ * it can be used to detect spurious IRQs. As the
-+ * driver is not expecting IRQ at all, clearing IRQ
-+ * here won't lead to loss of IRQ event.
-+ */
-+ if (unlikely(!ap->ioaddr.bmdma_addr))
-+ continue;
-+
-+ host_stat = ap->ops->bmdma_status(ap);
-+ if (!(host_stat & ATA_DMA_INTR))
-+ continue;
-+
-+ if (printk_ratelimit())
-+ ata_port_printk(ap, KERN_INFO,
-+ "clearing spurious IRQ\n");
-+ ap->ops->sff_check_status(ap);
-+ ap->ops->sff_irq_clear(ap);
-+ handled |= 1;
-+ }
-+
-+ spin_unlock_irqrestore(&host->lock, flags);
-+
-+ return IRQ_RETVAL(handled);
-+}
-+
- static int piix_sidpr_scr_write(struct ata_link *link,
- unsigned int reg, u32 val)
- {
-@@ -1543,7 +1595,7 @@ static int __devinit piix_init_one(struc
- }
-
- pci_set_master(pdev);
-- return ata_pci_sff_activate_host(host, ata_sff_interrupt, &piix_sht);
-+ return ata_pci_sff_activate_host(host, piix_interrupt, &piix_sht);
- }
-
- static int __init piix_init(void)