diff options
author | Mark Lord <mlord@pobox.com> | 2009-02-25 15:15:39 -0500 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2009-03-24 22:02:40 -0400 |
commit | 42ed893d8011264f9945c2f54055b47c298ac53e (patch) | |
tree | 1923c308e4b103960b9fefb24c51e50a91739a4e /drivers/ata | |
parent | c01e8a23128c746f23088db836bd4c820f3eb0b4 (diff) |
[libata] sata_mv: Tighten up interrupt masking in mv_qc_issue()
so that it doesn't miss any protocols. Handle future cases where a
qc is specially marked for polled issue or where a particular chip
version prefers interrupts over polling for PIO.
This mimics the polling decision logic from ata_sff_qc_issue().
Signed-off-by: Mark Lord <mlord@pobox.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/ata')
-rw-r--r-- | drivers/ata/sata_mv.c | 34 |
1 files changed, 21 insertions, 13 deletions
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 3bfe721ba766..b74af945a2fe 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c | |||
@@ -1809,7 +1809,7 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc) | |||
1809 | void __iomem *port_mmio = mv_ap_base(ap); | 1809 | void __iomem *port_mmio = mv_ap_base(ap); |
1810 | struct mv_port_priv *pp = ap->private_data; | 1810 | struct mv_port_priv *pp = ap->private_data; |
1811 | u32 in_index; | 1811 | u32 in_index; |
1812 | unsigned int port_irqs = DONE_IRQ | ERR_IRQ; | 1812 | unsigned int port_irqs; |
1813 | 1813 | ||
1814 | switch (qc->tf.protocol) { | 1814 | switch (qc->tf.protocol) { |
1815 | case ATA_PROT_DMA: | 1815 | case ATA_PROT_DMA: |
@@ -1842,20 +1842,28 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc) | |||
1842 | "this may fail due to h/w errata\n"); | 1842 | "this may fail due to h/w errata\n"); |
1843 | } | 1843 | } |
1844 | /* drop through */ | 1844 | /* drop through */ |
1845 | case ATA_PROT_NODATA: | ||
1845 | case ATAPI_PROT_PIO: | 1846 | case ATAPI_PROT_PIO: |
1846 | port_irqs = ERR_IRQ; /* leave DONE_IRQ masked for PIO */ | 1847 | case ATAPI_PROT_NODATA: |
1847 | /* drop through */ | 1848 | if (ap->flags & ATA_FLAG_PIO_POLLING) |
1848 | default: | 1849 | qc->tf.flags |= ATA_TFLAG_POLLING; |
1849 | /* | 1850 | break; |
1850 | * We're about to send a non-EDMA capable command to the | ||
1851 | * port. Turn off EDMA so there won't be problems accessing | ||
1852 | * shadow block, etc registers. | ||
1853 | */ | ||
1854 | mv_stop_edma(ap); | ||
1855 | mv_clear_and_enable_port_irqs(ap, mv_ap_base(ap), port_irqs); | ||
1856 | mv_pmp_select(ap, qc->dev->link->pmp); | ||
1857 | return ata_sff_qc_issue(qc); | ||
1858 | } | 1851 | } |
1852 | |||
1853 | if (qc->tf.flags & ATA_TFLAG_POLLING) | ||
1854 | port_irqs = ERR_IRQ; /* mask device interrupt when polling */ | ||
1855 | else | ||
1856 | port_irqs = ERR_IRQ | DONE_IRQ; /* unmask all interrupts */ | ||
1857 | |||
1858 | /* | ||
1859 | * We're about to send a non-EDMA capable command to the | ||
1860 | * port. Turn off EDMA so there won't be problems accessing | ||
1861 | * shadow block, etc registers. | ||
1862 | */ | ||
1863 | mv_stop_edma(ap); | ||
1864 | mv_clear_and_enable_port_irqs(ap, mv_ap_base(ap), port_irqs); | ||
1865 | mv_pmp_select(ap, qc->dev->link->pmp); | ||
1866 | return ata_sff_qc_issue(qc); | ||
1859 | } | 1867 | } |
1860 | 1868 | ||
1861 | static struct ata_queued_cmd *mv_get_active_qc(struct ata_port *ap) | 1869 | static struct ata_queued_cmd *mv_get_active_qc(struct ata_port *ap) |