diff options
Diffstat (limited to 'drivers/ata/libata-sff.c')
-rw-r--r-- | drivers/ata/libata-sff.c | 35 |
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); |