summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Lord <liml@rtr.ca>2006-05-19 22:33:03 +0200
committerJeff Garzik <jeff@garzik.org>2006-05-20 06:31:45 +0200
commite857f141945f29c16f72ffcfdbce097f8be6c4e9 (patch)
treecd6bcdeaed84701fddc693eedfddae0fcba68e27
parent[PATCH] sata_mv: chip initialization fixes (diff)
downloadlinux-e857f141945f29c16f72ffcfdbce097f8be6c4e9.tar.xz
linux-e857f141945f29c16f72ffcfdbce097f8be6c4e9.zip
[PATCH] sata_mv: spurious interrupt workaround
The 60xx chips, and possibly others, incorrectly assert DEV_IRQ interrupts on a regular basis. The cause of this is under investigation (by me and in theory by Marvell also), but regardless we do need to deal with these events. This patch tidies up some interrupt handler code, and ensures that we ignore DEV_IRQ interrupts when the drive still has ATA_BUSY asserted. Signed-off-by: Mark Lord <liml@rtr.ca> Signed-off-by: Jeff Garzik <jeff@garzik.org>
-rw-r--r--drivers/scsi/sata_mv.c11
1 files changed, 8 insertions, 3 deletions
diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c
index bb2409e761d0..65dc65304f51 100644
--- a/drivers/scsi/sata_mv.c
+++ b/drivers/scsi/sata_mv.c
@@ -1380,12 +1380,12 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant,
struct ata_port *ap = host_set->ports[port];
struct mv_port_priv *pp = ap->private_data;
- hard_port = port & MV_PORT_MASK; /* range 0-3 */
+ hard_port = mv_hardport_from_port(port); /* range 0..3 */
handled = 0; /* ensure ata_status is set if handled++ */
/* Note that DEV_IRQ might happen spuriously during EDMA,
- * and should be ignored in such cases. We could mask it,
- * but it's pretty rare and may not be worth the overhead.
+ * and should be ignored in such cases.
+ * The cause of this is still under investigation.
*/
if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
/* EDMA: check for response queue interrupt */
@@ -1399,6 +1399,11 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant,
ata_status = readb((void __iomem *)
ap->ioaddr.status_addr);
handled = 1;
+ /* ignore spurious intr if drive still BUSY */
+ if (ata_status & ATA_BUSY) {
+ ata_status = 0;
+ handled = 0;
+ }
}
}