Subject: [CPUFREQ] longhaul - avoid ide timeouts when bus mastering is off.

I really don't like this. Really.
Unfortunatly its necessary, otherwise after the transition, we live
for just a few minutes, and then just lockup.  In an ideal world,
the pm layer would allow some means of walking the device tree
quiescing DMA. Sadly, we don't live in an ideal world.

I'm open to suggestions on better ways to do this, as I'd rather
not push this to Linus' tree.

From patch by: Ken Staton <ken_staton@agilent.com>
Signed-off-by: Dave Jones <davej@redhat.com>

--- linux-2.6.11/arch/i386/kernel/cpu/cpufreq/longhaul.c~	2005-05-24 01:51:51.000000000 -0400
+++ linux-2.6.11/arch/i386/kernel/cpu/cpufreq/longhaul.c	2005-05-24 01:52:07.000000000 -0400
@@ -30,6 +30,8 @@
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/pci.h>
+#include <linux/ide.h>
+#include <linux/delay.h>
 
 #include <asm/msr.h>
 #include <asm/timex.h>
@@ -91,6 +91,25 @@ static char *print_speed(int speed)
 }
 #endif
 
+static void ide_idle(void)
+ {
+	int i;
+	ide_hwif_t *hwif = ide_hwifs;
+	ide_drive_t *drive;
+
+	i = 0;
+	do {
+		drive = &hwif->drives[i];
+		i++;
+		if (strncmp(drive->name,"hd",2) == 0) {
+			while (drive->waiting_for_dma)
+			udelay(10);
+		} else {
+			i = 0;
+		}
+	} while (i != 0);
+}	
+
 
 static unsigned int calc_speed(int mult)
 {
@@ -146,6 +165,7 @@ static void do_powersaver(union msr_long
 	longhaul->bits.RevisionKey = 0;
 
 	preempt_disable();
+	ide_idle();	/* avoid ide timeouts when bus master off */
 	local_irq_save(flags);
 
 	/*

