linux-ide.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] amd74xx: don't configure udma mode higher than BIOS did
@ 2007-02-05  7:58 Tejun Heo
  2007-02-05 11:24 ` Alan
  0 siblings, 1 reply; 22+ messages in thread
From: Tejun Heo @ 2007-02-05  7:58 UTC (permalink / raw)
  To: bzolnier, Alan Cox, linux-ide

On many nvidia boards, BIOSen often set CABLE bit in EIDE Controller
Configuration Register even when 40c cable is attached but configures
transfer mode correctly (<= udma33).  As amd74xx depends on the CABLE
bit to determine the cable type and thus the highest allowed udma
mode, this often results in incorrectly configured device resulting in
CRC errors and DMA disabling.

This patch makes amd74xx not configure udma mode higher than BIOS did.
If BIOS configured the device <= udma44, udma33 is the maximum speed.
Otherwise, the mode BIOs configured is the highest.  udma44
discrepancy is due to limitation in ide_find_best_mode() interface.
This shouldn't make much difference.

Signed-off-by: Tejun Heo <htejun@gmail.com>
---
Without this change, amd74xx can't figure out the right udma mode.
I've verified with 40c and 80c cables and a few new and old disks and
ODDs.  Works pretty good.

 drivers/ide/pci/amd74xx.c |   43 ++++++++++++++++++++++++++++++++++++-------
 1 file changed, 36 insertions(+), 7 deletions(-)

Index: work/drivers/ide/pci/amd74xx.c
===================================================================
--- work.orig/drivers/ide/pci/amd74xx.c
+++ work/drivers/ide/pci/amd74xx.c
@@ -84,6 +84,7 @@ static struct amd_ide_chip *amd_config;
 static ide_pci_device_t *amd_chipset;
 static unsigned int amd_80w;
 static unsigned int amd_clock;
+static u32 amd_udma_timing;
 
 static char *amd_dma[] = { "MWDMA16", "UDMA33", "UDMA66", "UDMA100", "UDMA133" };
 static unsigned char amd_cyc2udma[] = { 6, 6, 5, 4, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 7 };
@@ -292,14 +293,37 @@ static void amd74xx_tune_drive(ide_drive
 
 static int amd74xx_ide_dma_check(ide_drive_t *drive)
 {
-	int w80 = HWIF(drive)->udma_four;
+	/* UDMA timing to limit map, we don't limit below udma33 */
+	static const int udma_limit_map[] =
+		{ AMD_UDMA_33, AMD_UDMA_33, AMD_UDMA_33, AMD_UDMA_33,
+		  AMD_UDMA_33, AMD_UDMA_66, AMD_UDMA_100, AMD_UDMA_133 };
+	int w80, map;
+	u8 speed;
+
+	w80 = HWIF(drive)->udma_four && eighty_ninty_three(drive);
+	map = XFER_PIO | XFER_EPIO | XFER_MWDMA | XFER_UDMA |
+		((amd_config->flags & AMD_BAD_SWDMA) ? 0 : XFER_SWDMA);
+
+	if (w80) {
+		int udma_mode = amd_config->flags & AMD_UDMA;
+		u32 udma_timing = amd_udma_timing;
+
+		/* don't go over BIOS configured speed */
+		udma_timing >>= 8 * (3 - drive->dn);
+
+		if ((udma_timing & 0xc0) == 0xc0)
+			udma_mode = min(udma_mode,
+					udma_limit_map[udma_timing & 0x07]);
+
+		if (udma_mode >= AMD_UDMA_66)
+			map |= XFER_UDMA_66;
+		if (udma_mode >= AMD_UDMA_100)
+			map |= XFER_UDMA_100;
+		if (udma_mode >= AMD_UDMA_133)
+			map |= XFER_UDMA_133;
+	}
 
-	u8 speed = ide_find_best_mode(drive,
-		XFER_PIO | XFER_EPIO | XFER_MWDMA | XFER_UDMA |
-		((amd_config->flags & AMD_BAD_SWDMA) ? 0 : XFER_SWDMA) |
-		(w80 && (amd_config->flags & AMD_UDMA) >= AMD_UDMA_66 ? XFER_UDMA_66 : 0) |
-		(w80 && (amd_config->flags & AMD_UDMA) >= AMD_UDMA_100 ? XFER_UDMA_100 : 0) |
-		(w80 && (amd_config->flags & AMD_UDMA) >= AMD_UDMA_133 ? XFER_UDMA_133 : 0));
+	speed = ide_find_best_mode(drive, map);
 
 	amd_set_drive(drive, speed);
 
@@ -355,6 +379,11 @@ static unsigned int __devinit init_chips
 	}
 
 /*
+ * Cache UDMA timing BIOS configured.
+ */
+	pci_read_config_dword(dev, AMD_UDMA_TIMING, &amd_udma_timing);
+
+/*
  * Take care of prefetch & postwrite.
  */
 

^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2007-02-05 22:00 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-02-05  7:58 [PATCH] amd74xx: don't configure udma mode higher than BIOS did Tejun Heo
2007-02-05 11:24 ` Alan
2007-02-05 12:16   ` Tejun Heo
2007-02-05 12:33     ` Tejun Heo
2007-02-05 13:24       ` Alan
2007-02-05 14:17         ` Tejun Heo
2007-02-05 13:22     ` Alan
2007-02-05 14:07       ` Tejun Heo
2007-02-05 14:34         ` Nvidia cable detection problems (was [PATCH] amd74xx: don't configure udma mode higher than BIOS did) Alan
2007-02-05 14:50           ` Tejun Heo
2007-02-05 15:49             ` Alan
     [not found]             ` <58cb370e0702050709w1b7682dr5dff9e7ce69465a@mail.gmail.com>
2007-02-05 17:08               ` Allen Martin
2007-02-05 18:12                 ` Alan
2007-02-05 18:36                   ` Tejun Heo
2007-02-05 18:55                     ` Bartlomiej Zolnierkiewicz
2007-02-05 19:15                       ` Tejun Heo
2007-02-05 21:27                       ` Bartlomiej Zolnierkiewicz
2007-02-05 22:02                         ` Alan
2007-02-05 22:00                           ` Bartlomiej Zolnierkiewicz
2007-02-05 19:13                     ` Alan
2007-02-05 21:43                       ` Jeff Garzik
2007-02-05 15:32         ` [PATCH] amd74xx: don't configure udma mode higher than BIOS did Sergei Shtylyov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).