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);
}
}