Re: Serial ATA (SATA) for Linux status report
From: Jeff Garzik
Date: Wed Jan 14 2004 - 19:46:50 EST
I'm pretty sure the "excessive interrupts" issue was successfully
tracked down by Jon Burgess (thanks!). He found this post describing an
ICH5 hardware issue,
http://www.mail-archive.com/freebsd-stable@xxxxxxxxxxx/msg58421.html
and he also submitted the attached patch.
I've been meaning to rewrite his patch to isolate it more to ata_piix,
but in the meantime maybe folks could test this?
Jeff
--- libata-core.c-orig 2003-12-07 01:54:19.000000000 +0000
+++ libata-core.c 2003-12-07 16:25:11.961806872 +0000
@@ -2386,6 +2386,37 @@
}
/**
+ * ata_chk_spurious_int - Check for spurious interrupts
+ * @ap: port to which command is being issued
+ *
+ * Examines the DMA status registers and clears
+ * unexpected interrupts
+ *
+ * LOCKING:
+ */
+static inline void ata_chk_spurious_int(struct ata_port *ap) {
+ int host_stat;
+
+ if (ap->flags & ATA_FLAG_MMIO) {
+ void *mmio = (void *) ap->ioaddr.bmdma_addr;
+ host_stat = readb(mmio + ATA_DMA_STATUS);
+ } else
+ host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+
+ if ((host_stat & (ATA_DMA_INTR | ATA_DMA_ERR | ATA_DMA_ACTIVE)) == ATA_DMA_INTR) {
+ if (ap->flags & ATA_FLAG_MMIO) {
+ void *mmio = (void *) ap->ioaddr.bmdma_addr;
+ writeb(host_stat & ~ATA_DMA_ERR, mmio + ATA_DMA_STATUS);
+ } else
+ outb(host_stat & ~ATA_DMA_ERR, ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+
+ DPRINTK("ata%u: Caught spurious interrupt, status 0x%X\n", ap->id, host_stat);
+ udelay(1);
+ }
+}
+
+
+/**
* ata_interrupt -
* @irq:
* @dev_instance:
@@ -2417,6 +2448,7 @@
qc = ata_qc_from_tag(ap, ap->active_tag);
if (qc && ((qc->flags & ATA_QCFLAG_POLL) == 0))
handled += ata_host_intr(ap, qc);
+ ata_chk_spurious_int(ap);
}
}