diff options
Diffstat (limited to 'drivers/ata/pata_scc.c')
-rw-r--r-- | drivers/ata/pata_scc.c | 54 |
1 files changed, 35 insertions, 19 deletions
diff --git a/drivers/ata/pata_scc.c b/drivers/ata/pata_scc.c index 61502bc7bf1d..c55667e0eb65 100644 --- a/drivers/ata/pata_scc.c +++ b/drivers/ata/pata_scc.c | |||
@@ -238,6 +238,12 @@ static void scc_set_dmamode (struct ata_port *ap, struct ata_device *adev) | |||
238 | else | 238 | else |
239 | offset = 0; /* 100MHz */ | 239 | offset = 0; /* 100MHz */ |
240 | 240 | ||
241 | /* errata A308 workaround: limit ATAPI UDMA mode to UDMA4 */ | ||
242 | if (adev->class == ATA_DEV_ATAPI && speed > XFER_UDMA_4) { | ||
243 | printk(KERN_INFO "%s: limit ATAPI UDMA to UDMA4\n", DRV_NAME); | ||
244 | speed = XFER_UDMA_4; | ||
245 | } | ||
246 | |||
241 | if (speed >= XFER_UDMA_0) | 247 | if (speed >= XFER_UDMA_0) |
242 | idx = speed - XFER_UDMA_0; | 248 | idx = speed - XFER_UDMA_0; |
243 | else | 249 | else |
@@ -724,22 +730,36 @@ static void scc_bmdma_stop (struct ata_queued_cmd *qc) | |||
724 | 730 | ||
725 | static u8 scc_bmdma_status (struct ata_port *ap) | 731 | static u8 scc_bmdma_status (struct ata_port *ap) |
726 | { | 732 | { |
727 | u8 host_stat; | ||
728 | void __iomem *mmio = ap->ioaddr.bmdma_addr; | 733 | void __iomem *mmio = ap->ioaddr.bmdma_addr; |
729 | 734 | u8 host_stat = in_be32(mmio + SCC_DMA_STATUS); | |
730 | host_stat = in_be32(mmio + SCC_DMA_STATUS); | 735 | u32 int_status = in_be32(mmio + SCC_DMA_INTST); |
731 | 736 | struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag); | |
732 | /* Workaround for PTERADD: emulate DMA_INTR when | 737 | static int retry = 0; |
733 | * - IDE_STATUS[ERR] = 1 | 738 | |
734 | * - INT_STATUS[INTRQ] = 1 | 739 | /* return if IOS_SS is cleared */ |
735 | * - DMA_STATUS[IORACTA] = 1 | 740 | if (!(in_be32(mmio + SCC_DMA_CMD) & ATA_DMA_START)) |
736 | */ | 741 | return host_stat; |
737 | if (!(host_stat & ATA_DMA_INTR)) { | 742 | |
738 | u32 int_status = in_be32(mmio + SCC_DMA_INTST); | 743 | /* errata A252,A308 workaround: Step4 */ |
739 | if (ata_altstatus(ap) & ATA_ERR && | 744 | if (ata_altstatus(ap) & ATA_ERR && int_status & INTSTS_INTRQ) |
740 | int_status & INTSTS_INTRQ && | 745 | return (host_stat | ATA_DMA_INTR); |
741 | host_stat & ATA_DMA_ACTIVE) | 746 | |
742 | host_stat |= ATA_DMA_INTR; | 747 | /* errata A308 workaround Step5 */ |
748 | if (int_status & INTSTS_IOIRQS) { | ||
749 | host_stat |= ATA_DMA_INTR; | ||
750 | |||
751 | /* We don't check ATAPI DMA because it is limited to UDMA4 */ | ||
752 | if ((qc->tf.protocol == ATA_PROT_DMA && | ||
753 | qc->dev->xfer_mode > XFER_UDMA_4)) { | ||
754 | if (!(int_status & INTSTS_ACTEINT)) { | ||
755 | printk(KERN_WARNING "ata%u: data lost occurred. (ACTEINT==0, retry:%d)\n", | ||
756 | ap->print_id, retry); | ||
757 | host_stat |= ATA_DMA_ERR; | ||
758 | if (retry++) | ||
759 | ap->udma_mask >>= 1; | ||
760 | } else | ||
761 | retry = 0; | ||
762 | } | ||
743 | } | 763 | } |
744 | 764 | ||
745 | return host_stat; | 765 | return host_stat; |
@@ -892,10 +912,6 @@ static void scc_std_postreset (struct ata_port *ap, unsigned int *classes) | |||
892 | { | 912 | { |
893 | DPRINTK("ENTER\n"); | 913 | DPRINTK("ENTER\n"); |
894 | 914 | ||
895 | /* re-enable interrupts */ | ||
896 | if (!ap->ops->error_handler) | ||
897 | ap->ops->irq_on(ap); | ||
898 | |||
899 | /* is double-select really necessary? */ | 915 | /* is double-select really necessary? */ |
900 | if (classes[0] != ATA_DEV_NONE) | 916 | if (classes[0] != ATA_DEV_NONE) |
901 | ap->ops->dev_select(ap, 1); | 917 | ap->ops->dev_select(ap, 1); |