aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/pata_scc.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-12 16:38:50 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-12 16:38:50 -0400
commit57399ec9077a4b962b81037aaa279fab52f5e989 (patch)
tree847dfb9304001ab9ffc5eef5f20ae514cd01bb90 /drivers/ata/pata_scc.c
parente1bd2ac5a6b7a8b625e40c9e9f8b6dea4cf22f85 (diff)
parentc6e54a578133fb353a50fb44d650768b3b9eb18e (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: (21 commits) libata: remove irq_on from ata_bus_reset() and ata_std_postreset() ata_piix: kill incorrect invalid map value warning libata: add another Maxtor drive with broken NCQ to the list [libata] sata_mv: Fix and clean up per-chip-generation tests [libata] sata_mv: Convert to new exception handling (EH) infrastructure [libata] sata_mv: minor bug fixes, enhancements, and cleanups (prep for new EH) [libata] sata_mv: Minor cleanups and renaming, preparing for new EH & NCQ libata-link: add PMP related ATA constants libata-link: separate out ata_eh_handle_dev_fail() pata_hpt3x3: fix DMA Kconfig option to actually have a hope of working Add Hitachi HDS7250SASUN500G 0621KTAWSD to NCQ blacklist pata_scc.c: Workaround for errata A308 libata: add FUJITSU MHV2080BH to NCQ blacklist pata_hpt3x3: major reworking and testing libata: clean up horkage handling libata: quirk IOMEGA ZIP 250 ATAPI FLOPPY libata: simplify PCI legacy SFF host handling pata_mpc52xx: suspend/resume support sata_promise: SATA hotplug support, take 2 pata_sis: FIFO whack ...
Diffstat (limited to 'drivers/ata/pata_scc.c')
-rw-r--r--drivers/ata/pata_scc.c54
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
725static u8 scc_bmdma_status (struct ata_port *ap) 731static 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);