diff options
Diffstat (limited to 'drivers/ata/libata-sff.c')
-rw-r--r-- | drivers/ata/libata-sff.c | 50 |
1 files changed, 39 insertions, 11 deletions
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 730ef3c384ca..02441fd57e9e 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c | |||
@@ -1763,24 +1763,50 @@ 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 */ |
1770 | spin_lock_irqsave(&host->lock, flags); | 1770 | spin_lock_irqsave(&host->lock, flags); |
1771 | 1771 | ||
1772 | for (i = 0; i < host->n_ports; i++) { | 1772 | for (i = 0; i < host->n_ports; i++) { |
1773 | struct ata_port *ap; | 1773 | struct ata_port *ap = host->ports[i]; |
1774 | struct ata_queued_cmd *qc; | ||
1774 | 1775 | ||
1775 | ap = host->ports[i]; | 1776 | if (unlikely(ap->flags & ATA_FLAG_DISABLED)) |
1776 | if (ap && | 1777 | continue; |
1777 | !(ap->flags & ATA_FLAG_DISABLED)) { | ||
1778 | struct ata_queued_cmd *qc; | ||
1779 | 1778 | ||
1780 | qc = ata_qc_from_tag(ap, ap->link.active_tag); | 1779 | qc = ata_qc_from_tag(ap, ap->link.active_tag); |
1781 | if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)) && | 1780 | if (qc) { |
1782 | (qc->flags & ATA_QCFLAG_ACTIVE)) | 1781 | if (!(qc->tf.flags & ATA_TFLAG_POLLING)) |
1783 | handled |= ata_sff_host_intr(ap, qc); | 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); | ||
1784 | } | 1810 | } |
1785 | } | 1811 | } |
1786 | 1812 | ||
@@ -3011,6 +3037,7 @@ EXPORT_SYMBOL_GPL(ata_pci_sff_activate_host); | |||
3011 | * @ppi: array of port_info, must be enough for two ports | 3037 | * @ppi: array of port_info, must be enough for two ports |
3012 | * @sht: scsi_host_template to use when registering the host | 3038 | * @sht: scsi_host_template to use when registering the host |
3013 | * @host_priv: host private_data | 3039 | * @host_priv: host private_data |
3040 | * @hflag: host flags | ||
3014 | * | 3041 | * |
3015 | * This is a helper function which can be called from a driver's | 3042 | * This is a helper function which can be called from a driver's |
3016 | * xxx_init_one() probe function if the hardware uses traditional | 3043 | * xxx_init_one() probe function if the hardware uses traditional |
@@ -3031,8 +3058,8 @@ EXPORT_SYMBOL_GPL(ata_pci_sff_activate_host); | |||
3031 | * Zero on success, negative on errno-based value on error. | 3058 | * Zero on success, negative on errno-based value on error. |
3032 | */ | 3059 | */ |
3033 | int ata_pci_sff_init_one(struct pci_dev *pdev, | 3060 | int ata_pci_sff_init_one(struct pci_dev *pdev, |
3034 | const struct ata_port_info * const *ppi, | 3061 | const struct ata_port_info * const *ppi, |
3035 | struct scsi_host_template *sht, void *host_priv) | 3062 | struct scsi_host_template *sht, void *host_priv, int hflag) |
3036 | { | 3063 | { |
3037 | struct device *dev = &pdev->dev; | 3064 | struct device *dev = &pdev->dev; |
3038 | const struct ata_port_info *pi = NULL; | 3065 | const struct ata_port_info *pi = NULL; |
@@ -3067,6 +3094,7 @@ int ata_pci_sff_init_one(struct pci_dev *pdev, | |||
3067 | if (rc) | 3094 | if (rc) |
3068 | goto out; | 3095 | goto out; |
3069 | host->private_data = host_priv; | 3096 | host->private_data = host_priv; |
3097 | host->flags |= hflag; | ||
3070 | 3098 | ||
3071 | pci_set_master(pdev); | 3099 | pci_set_master(pdev); |
3072 | rc = ata_pci_sff_activate_host(host, ata_sff_interrupt, sht); | 3100 | rc = ata_pci_sff_activate_host(host, ata_sff_interrupt, sht); |