From baf0edceb8e257cb20a996a931e0426f715e54e0 Mon Sep 17 00:00:00 2001 From: Akira Iguchi Date: Tue, 10 Jul 2007 18:29:34 +0900 Subject: [PATCH] --- yaml --- r: 59077 b: refs/heads/master c: fae57d348379861f115fe1e586a1e0902b71ae9e h: refs/heads/master i: 59075: 2183dd50e27df88aef124422ed27ebc84849b393 v: v3 --- [refs] | 2 +- trunk/drivers/ata/pata_scc.c | 50 +++++++++++++++++++++++++----------- 2 files changed, 36 insertions(+), 16 deletions(-) diff --git a/[refs] b/[refs] index 0745e8c06d3e..d095867dbbe2 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: a520f2614690b8d3a7b431a1d8a40ea6a04d4827 +refs/heads/master: fae57d348379861f115fe1e586a1e0902b71ae9e diff --git a/trunk/drivers/ata/pata_scc.c b/trunk/drivers/ata/pata_scc.c index 61502bc7bf1d..274fabfc90e1 100644 --- a/trunk/drivers/ata/pata_scc.c +++ b/trunk/drivers/ata/pata_scc.c @@ -238,6 +238,12 @@ static void scc_set_dmamode (struct ata_port *ap, struct ata_device *adev) else offset = 0; /* 100MHz */ + /* errata A308 workaround: limit ATAPI UDMA mode to UDMA4 */ + if (adev->class == ATA_DEV_ATAPI && speed > XFER_UDMA_4) { + printk(KERN_INFO "%s: limit ATAPI UDMA to UDMA4\n", DRV_NAME); + speed = XFER_UDMA_4; + } + if (speed >= XFER_UDMA_0) idx = speed - XFER_UDMA_0; else @@ -724,22 +730,36 @@ static void scc_bmdma_stop (struct ata_queued_cmd *qc) static u8 scc_bmdma_status (struct ata_port *ap) { - u8 host_stat; void __iomem *mmio = ap->ioaddr.bmdma_addr; - - host_stat = in_be32(mmio + SCC_DMA_STATUS); - - /* Workaround for PTERADD: emulate DMA_INTR when - * - IDE_STATUS[ERR] = 1 - * - INT_STATUS[INTRQ] = 1 - * - DMA_STATUS[IORACTA] = 1 - */ - if (!(host_stat & ATA_DMA_INTR)) { - u32 int_status = in_be32(mmio + SCC_DMA_INTST); - if (ata_altstatus(ap) & ATA_ERR && - int_status & INTSTS_INTRQ && - host_stat & ATA_DMA_ACTIVE) - host_stat |= ATA_DMA_INTR; + u8 host_stat = in_be32(mmio + SCC_DMA_STATUS); + u32 int_status = in_be32(mmio + SCC_DMA_INTST); + struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag); + static int retry = 0; + + /* return if IOS_SS is cleared */ + if (!(in_be32(mmio + SCC_DMA_CMD) & ATA_DMA_START)) + return host_stat; + + /* errata A252,A308 workaround: Step4 */ + if (ata_altstatus(ap) & ATA_ERR && int_status & INTSTS_INTRQ) + return (host_stat | ATA_DMA_INTR); + + /* errata A308 workaround Step5 */ + if (int_status & INTSTS_IOIRQS) { + host_stat |= ATA_DMA_INTR; + + /* We don't check ATAPI DMA because it is limited to UDMA4 */ + if ((qc->tf.protocol == ATA_PROT_DMA && + qc->dev->xfer_mode > XFER_UDMA_4)) { + if (!(int_status & INTSTS_ACTEINT)) { + printk(KERN_WARNING "ata%u: data lost occurred. (ACTEINT==0, retry:%d)\n", + ap->print_id, retry); + host_stat |= ATA_DMA_ERR; + if (retry++) + ap->udma_mask >>= 1; + } else + retry = 0; + } } return host_stat;