|
@@ -888,6 +888,16 @@ static inline void sil24_host_intr(struct ata_port *ap)
|
|
|
u32 slot_stat, qc_active;
|
|
|
int rc;
|
|
|
|
|
|
+ /* If PCIX_IRQ_WOC, there's an inherent race window between
|
|
|
+ * clearing IRQ pending status and reading PORT_SLOT_STAT
|
|
|
+ * which may cause spurious interrupts afterwards. This is
|
|
|
+ * unavoidable and much better than losing interrupts which
|
|
|
+ * happens if IRQ pending is cleared after reading
|
|
|
+ * PORT_SLOT_STAT.
|
|
|
+ */
|
|
|
+ if (ap->flags & SIL24_FLAG_PCIX_IRQ_WOC)
|
|
|
+ writel(PORT_IRQ_COMPLETE, port + PORT_IRQ_STAT);
|
|
|
+
|
|
|
slot_stat = readl(port + PORT_SLOT_STAT);
|
|
|
|
|
|
if (unlikely(slot_stat & HOST_SSTAT_ATTN)) {
|
|
@@ -895,9 +905,6 @@ static inline void sil24_host_intr(struct ata_port *ap)
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- if (ap->flags & SIL24_FLAG_PCIX_IRQ_WOC)
|
|
|
- writel(PORT_IRQ_COMPLETE, port + PORT_IRQ_STAT);
|
|
|
-
|
|
|
qc_active = slot_stat & ~HOST_SSTAT_ATTN;
|
|
|
rc = ata_qc_complete_multiple(ap, qc_active, sil24_finish_qc);
|
|
|
if (rc > 0)
|
|
@@ -910,7 +917,8 @@ static inline void sil24_host_intr(struct ata_port *ap)
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- if (ata_ratelimit())
|
|
|
+ /* spurious interrupts are expected if PCIX_IRQ_WOC */
|
|
|
+ if (!(ap->flags & SIL24_FLAG_PCIX_IRQ_WOC) && ata_ratelimit())
|
|
|
ata_port_printk(ap, KERN_INFO, "spurious interrupt "
|
|
|
"(slot_stat 0x%x active_tag %d sactive 0x%x)\n",
|
|
|
slot_stat, ap->active_tag, ap->sactive);
|