diff options
author | Mark Lord <liml@rtr.ca> | 2008-05-17 13:36:30 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2008-05-19 17:29:51 -0400 |
commit | 88e675e193159b9891c1c576de4348eaf490f5d0 (patch) | |
tree | 6af356c51ed75d862ac7aa731a9aeea49e340eb6 /drivers | |
parent | c4de573b14d78ac83861d81d12977457d1e9cb6d (diff) |
sata_mv: fix pmp drives not found
Part three of simplifying/fixing handling of the main_irq_mask register
to resolve unexpected interrupt issues observed in 2.6.26-rc*.
Partially fix a reported bug whereby we sometimes miss seeing drives on
a port-multiplier, as reported by Gwendal Grignou <gwendal@google.com>.
The problem was that we were receiving unexpected interrupts
during EH from POLLed commands while accessing port-multiplier registers.
These unexpected interrupts can be prevented by masking the DONE_IRQ bit
for the port whenever not operating in EDMA mode.
Also fix port_stop() to mask all port interrupts.
Signed-off-by: Mark Lord <mlord@pobox.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/ata/sata_mv.c | 5 |
1 files changed, 4 insertions, 1 deletions
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index d0fd83635fa4..47dae7a2fbf4 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c | |||
@@ -908,6 +908,7 @@ static void mv_start_dma(struct ata_port *ap, void __iomem *port_mmio, | |||
908 | writelfl(0, port_mmio + SATA_FIS_IRQ_CAUSE_OFS); | 908 | writelfl(0, port_mmio + SATA_FIS_IRQ_CAUSE_OFS); |
909 | 909 | ||
910 | mv_set_edma_ptrs(port_mmio, hpriv, pp); | 910 | mv_set_edma_ptrs(port_mmio, hpriv, pp); |
911 | mv_enable_port_irqs(ap, DONE_IRQ|ERR_IRQ); | ||
911 | 912 | ||
912 | writelfl(EDMA_EN, port_mmio + EDMA_CMD_OFS); | 913 | writelfl(EDMA_EN, port_mmio + EDMA_CMD_OFS); |
913 | pp->pp_flags |= MV_PP_FLAG_EDMA_EN; | 914 | pp->pp_flags |= MV_PP_FLAG_EDMA_EN; |
@@ -1360,6 +1361,7 @@ out_port_free_dma_mem: | |||
1360 | static void mv_port_stop(struct ata_port *ap) | 1361 | static void mv_port_stop(struct ata_port *ap) |
1361 | { | 1362 | { |
1362 | mv_stop_edma(ap); | 1363 | mv_stop_edma(ap); |
1364 | mv_enable_port_irqs(ap, 0); | ||
1363 | mv_port_free_dma_mem(ap); | 1365 | mv_port_free_dma_mem(ap); |
1364 | } | 1366 | } |
1365 | 1367 | ||
@@ -1601,6 +1603,7 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc) | |||
1601 | * shadow block, etc registers. | 1603 | * shadow block, etc registers. |
1602 | */ | 1604 | */ |
1603 | mv_stop_edma(ap); | 1605 | mv_stop_edma(ap); |
1606 | mv_enable_port_irqs(ap, ERR_IRQ); | ||
1604 | mv_pmp_select(ap, qc->dev->link->pmp); | 1607 | mv_pmp_select(ap, qc->dev->link->pmp); |
1605 | return ata_sff_qc_issue(qc); | 1608 | return ata_sff_qc_issue(qc); |
1606 | } | 1609 | } |
@@ -2800,7 +2803,7 @@ static void mv_eh_thaw(struct ata_port *ap) | |||
2800 | hc_irq_cause &= ~((DEV_IRQ | DMA_IRQ) << hardport); | 2803 | hc_irq_cause &= ~((DEV_IRQ | DMA_IRQ) << hardport); |
2801 | writelfl(hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS); | 2804 | writelfl(hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS); |
2802 | 2805 | ||
2803 | mv_enable_port_irqs(ap, DONE_IRQ | ERR_IRQ); | 2806 | mv_enable_port_irqs(ap, ERR_IRQ); |
2804 | } | 2807 | } |
2805 | 2808 | ||
2806 | /** | 2809 | /** |