aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/libata-sff.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ata/libata-sff.c')
-rw-r--r--drivers/ata/libata-sff.c35
1 files changed, 32 insertions, 3 deletions
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index c62ed13b0596..c2661ea70330 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -1763,7 +1763,7 @@ irqreturn_t ata_sff_interrupt(int irq, void *dev_instance)
1763{ 1763{
1764 struct ata_host *host = dev_instance; 1764 struct ata_host *host = dev_instance;
1765 unsigned int i; 1765 unsigned int i;
1766 unsigned int handled = 0; 1766 unsigned int handled = 0, polling = 0;
1767 unsigned long flags; 1767 unsigned long flags;
1768 1768
1769 /* TODO: make _irqsave conditional on x86 PCI IDE legacy mode */ 1769 /* TODO: make _irqsave conditional on x86 PCI IDE legacy mode */
@@ -1777,8 +1777,37 @@ irqreturn_t ata_sff_interrupt(int irq, void *dev_instance)
1777 continue; 1777 continue;
1778 1778
1779 qc = ata_qc_from_tag(ap, ap->link.active_tag); 1779 qc = ata_qc_from_tag(ap, ap->link.active_tag);
1780 if (qc && !(qc->tf.flags & ATA_TFLAG_POLLING)) 1780 if (qc) {
1781 handled |= ata_sff_host_intr(ap, qc); 1781 if (!(qc->tf.flags & ATA_TFLAG_POLLING))
1782 handled |= ata_sff_host_intr(ap, qc);
1783 else
1784 polling |= 1 << i;
1785 }
1786 }
1787
1788 /*
1789 * If no port was expecting IRQ but the controller is actually
1790 * asserting IRQ line, nobody cared will ensue. Check IRQ
1791 * pending status if available and clear spurious IRQ.
1792 */
1793 if (!handled) {
1794 for (i = 0; i < host->n_ports; i++) {
1795 struct ata_port *ap = host->ports[i];
1796
1797 if (polling & (1 << i))
1798 continue;
1799
1800 if (!ap->ops->sff_irq_check ||
1801 !ap->ops->sff_irq_check(ap))
1802 continue;
1803
1804 if (printk_ratelimit())
1805 ata_port_printk(ap, KERN_INFO,
1806 "clearing spurious IRQ\n");
1807
1808 ap->ops->sff_check_status(ap);
1809 ap->ops->sff_irq_clear(ap);
1810 }
1782 } 1811 }
1783 1812
1784 spin_unlock_irqrestore(&host->lock, flags); 1813 spin_unlock_irqrestore(&host->lock, flags);