aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2006-06-26 08:23:52 -0400
committerJeff Garzik <jeff@garzik.org>2006-06-26 21:02:36 -0400
commit201ce85946504ea0e6bd9a365de26684b437121e (patch)
treeae3eb625c5327f0c34c94fcb0bf9d0230670eb44
parent88574551b46ba69b0f145d2775006f2e7dfebc84 (diff)
[PATCH] sata_sil: disable hotplug interrupts on two ATI IXPs
Some SATA controllers embedded in ATI IXPs seem to have broken SATA_IRQ bit in their bmdma2 registers which is always stuck at 1. This makes the driver believe that there has been a hotplug event and freeze the port whenever there's an interrupt thus failing all commands. This patch disables SATA_IRQ for those controllers. Signed-off-by: Tejun Heo <htejun@gmail.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
-rw-r--r--drivers/scsi/sata_sil.c29
1 files changed, 23 insertions, 6 deletions
diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
index 662ad10de288..51d86d750e84 100644
--- a/drivers/scsi/sata_sil.c
+++ b/drivers/scsi/sata_sil.c
@@ -52,6 +52,7 @@ enum {
52 /* 52 /*
53 * host flags 53 * host flags
54 */ 54 */
55 SIL_FLAG_NO_SATA_IRQ = (1 << 28),
55 SIL_FLAG_RERR_ON_DMA_ACT = (1 << 29), 56 SIL_FLAG_RERR_ON_DMA_ACT = (1 << 29),
56 SIL_FLAG_MOD15WRITE = (1 << 30), 57 SIL_FLAG_MOD15WRITE = (1 << 30),
57 58
@@ -62,8 +63,9 @@ enum {
62 * Controller IDs 63 * Controller IDs
63 */ 64 */
64 sil_3112 = 0, 65 sil_3112 = 0,
65 sil_3512 = 1, 66 sil_3112_no_sata_irq = 1,
66 sil_3114 = 2, 67 sil_3512 = 2,
68 sil_3114 = 3,
67 69
68 /* 70 /*
69 * Register offsets 71 * Register offsets
@@ -123,8 +125,8 @@ static const struct pci_device_id sil_pci_tbl[] = {
123 { 0x1095, 0x3512, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3512 }, 125 { 0x1095, 0x3512, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3512 },
124 { 0x1095, 0x3114, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3114 }, 126 { 0x1095, 0x3114, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3114 },
125 { 0x1002, 0x436e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 }, 127 { 0x1002, 0x436e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
126 { 0x1002, 0x4379, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 }, 128 { 0x1002, 0x4379, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_no_sata_irq },
127 { 0x1002, 0x437a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 }, 129 { 0x1002, 0x437a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_no_sata_irq },
128 { } /* terminate list */ 130 { } /* terminate list */
129}; 131};
130 132
@@ -217,6 +219,16 @@ static const struct ata_port_info sil_port_info[] = {
217 .udma_mask = 0x3f, /* udma0-5 */ 219 .udma_mask = 0x3f, /* udma0-5 */
218 .port_ops = &sil_ops, 220 .port_ops = &sil_ops,
219 }, 221 },
222 /* sil_3112_no_sata_irq */
223 {
224 .sht = &sil_sht,
225 .host_flags = SIL_DFL_HOST_FLAGS | SIL_FLAG_MOD15WRITE |
226 SIL_FLAG_NO_SATA_IRQ,
227 .pio_mask = 0x1f, /* pio0-4 */
228 .mwdma_mask = 0x07, /* mwdma0-2 */
229 .udma_mask = 0x3f, /* udma0-5 */
230 .port_ops = &sil_ops,
231 },
220 /* sil_3512 */ 232 /* sil_3512 */
221 { 233 {
222 .sht = &sil_sht, 234 .sht = &sil_sht,
@@ -437,6 +449,10 @@ static irqreturn_t sil_interrupt(int irq, void *dev_instance,
437 if (unlikely(!ap || ap->flags & ATA_FLAG_DISABLED)) 449 if (unlikely(!ap || ap->flags & ATA_FLAG_DISABLED))
438 continue; 450 continue;
439 451
452 /* turn off SATA_IRQ if not supported */
453 if (ap->flags & SIL_FLAG_NO_SATA_IRQ)
454 bmdma2 &= ~SIL_DMA_SATA_IRQ;
455
440 if (bmdma2 == 0xffffffff || 456 if (bmdma2 == 0xffffffff ||
441 !(bmdma2 & (SIL_DMA_COMPLETE | SIL_DMA_SATA_IRQ))) 457 !(bmdma2 & (SIL_DMA_COMPLETE | SIL_DMA_SATA_IRQ)))
442 continue; 458 continue;
@@ -474,8 +490,9 @@ static void sil_thaw(struct ata_port *ap)
474 ata_chk_status(ap); 490 ata_chk_status(ap);
475 ata_bmdma_irq_clear(ap); 491 ata_bmdma_irq_clear(ap);
476 492
477 /* turn on SATA IRQ */ 493 /* turn on SATA IRQ if supported */
478 writel(SIL_SIEN_N, mmio_base + sil_port[ap->port_no].sien); 494 if (!(ap->flags & SIL_FLAG_NO_SATA_IRQ))
495 writel(SIL_SIEN_N, mmio_base + sil_port[ap->port_no].sien);
479 496
480 /* turn on IRQ */ 497 /* turn on IRQ */
481 tmp = readl(mmio_base + SIL_SYSCFG); 498 tmp = readl(mmio_base + SIL_SYSCFG);