diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-09-26 11:57:27 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-09-26 11:57:27 -0400 |
commit | 4d3fac08718b49fc256bdb447a479d089ca97b78 (patch) | |
tree | 01bb670864df83f891c2b2a8eb576ad5c4b0bbe4 | |
parent | 1f23f4209f2b99fdddf09821eead6364a6dd9654 (diff) | |
parent | edeb614c1c8388b354d93ff7790317cc5d6a38ec (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.c | 3 | ||||
-rw-r--r-- | drivers/ata/sata_sil24.c | 16 |
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); |