aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-09-26 11:57:27 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-09-26 11:57:27 -0400
commit4d3fac08718b49fc256bdb447a479d089ca97b78 (patch)
tree01bb670864df83f891c2b2a8eb576ad5c4b0bbe4
parent1f23f4209f2b99fdddf09821eead6364a6dd9654 (diff)
parentedeb614c1c8388b354d93ff7790317cc5d6a38ec (diff)
Merge branch 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev
* 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev: pata_sis: add missing UDMA5 timing value in sis_66_set_dmamode() sata_sil24: fix IRQ clearing race when PCIX_IRQ_WOC is used
-rw-r--r--drivers/ata/pata_sis.c3
-rw-r--r--drivers/ata/sata_sil24.c16
2 files changed, 14 insertions, 5 deletions
diff --git a/drivers/ata/pata_sis.c b/drivers/ata/pata_sis.c
index 2bd7645f1a88..cce2834b2b60 100644
--- a/drivers/ata/pata_sis.c
+++ b/drivers/ata/pata_sis.c
@@ -375,8 +375,9 @@ static void sis_66_set_dmamode (struct ata_port *ap, struct ata_device *adev)
375 int drive_pci = sis_old_port_base(adev); 375 int drive_pci = sis_old_port_base(adev);
376 u16 timing; 376 u16 timing;
377 377
378 /* MWDMA 0-2 and UDMA 0-5 */
378 const u16 mwdma_bits[] = { 0x008, 0x302, 0x301 }; 379 const u16 mwdma_bits[] = { 0x008, 0x302, 0x301 };
379 const u16 udma_bits[] = { 0xF000, 0xD000, 0xB000, 0xA000, 0x9000}; 380 const u16 udma_bits[] = { 0xF000, 0xD000, 0xB000, 0xA000, 0x9000, 0x8000 };
380 381
381 pci_read_config_word(pdev, drive_pci, &timing); 382 pci_read_config_word(pdev, drive_pci, &timing);
382 383
diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c
index ef83e6b1e314..233e88693395 100644
--- a/drivers/ata/sata_sil24.c
+++ b/drivers/ata/sata_sil24.c
@@ -888,6 +888,16 @@ static inline void sil24_host_intr(struct ata_port *ap)
888 u32 slot_stat, qc_active; 888 u32 slot_stat, qc_active;
889 int rc; 889 int rc;
890 890
891 /* If PCIX_IRQ_WOC, there's an inherent race window between
892 * clearing IRQ pending status and reading PORT_SLOT_STAT
893 * which may cause spurious interrupts afterwards. This is
894 * unavoidable and much better than losing interrupts which
895 * happens if IRQ pending is cleared after reading
896 * PORT_SLOT_STAT.
897 */
898 if (ap->flags & SIL24_FLAG_PCIX_IRQ_WOC)
899 writel(PORT_IRQ_COMPLETE, port + PORT_IRQ_STAT);
900
891 slot_stat = readl(port + PORT_SLOT_STAT); 901 slot_stat = readl(port + PORT_SLOT_STAT);
892 902
893 if (unlikely(slot_stat & HOST_SSTAT_ATTN)) { 903 if (unlikely(slot_stat & HOST_SSTAT_ATTN)) {
@@ -895,9 +905,6 @@ static inline void sil24_host_intr(struct ata_port *ap)
895 return; 905 return;
896 } 906 }
897 907
898 if (ap->flags & SIL24_FLAG_PCIX_IRQ_WOC)
899 writel(PORT_IRQ_COMPLETE, port + PORT_IRQ_STAT);
900
901 qc_active = slot_stat & ~HOST_SSTAT_ATTN; 908 qc_active = slot_stat & ~HOST_SSTAT_ATTN;
902 rc = ata_qc_complete_multiple(ap, qc_active, sil24_finish_qc); 909 rc = ata_qc_complete_multiple(ap, qc_active, sil24_finish_qc);
903 if (rc > 0) 910 if (rc > 0)
@@ -910,7 +917,8 @@ static inline void sil24_host_intr(struct ata_port *ap)
910 return; 917 return;
911 } 918 }
912 919
913 if (ata_ratelimit()) 920 /* spurious interrupts are expected if PCIX_IRQ_WOC */
921 if (!(ap->flags & SIL24_FLAG_PCIX_IRQ_WOC) && ata_ratelimit())
914 ata_port_printk(ap, KERN_INFO, "spurious interrupt " 922 ata_port_printk(ap, KERN_INFO, "spurious interrupt "
915 "(slot_stat 0x%x active_tag %d sactive 0x%x)\n", 923 "(slot_stat 0x%x active_tag %d sactive 0x%x)\n",
916 slot_stat, ap->active_tag, ap->sactive); 924 slot_stat, ap->active_tag, ap->sactive);