diff -purN --exclude=tags linux-2.6.20orig/drivers/usb/host/ehci.h linux-2.6.20new/drivers/usb/host/ehci.h
--- linux-2.6.20orig/drivers/usb/host/ehci.h	2007-02-04 12:44:54.000000000 -0600
+++ linux-2.6.20new/drivers/usb/host/ehci.h	2007-02-20 11:24:31.000000000 -0600
@@ -55,6 +55,11 @@ struct ehci_hcd {			/* one per controlle
 	__u32			hcs_params;	/* cached register copy */
 	spinlock_t		lock;
 
+#ifdef CONFIG_CPU_FREQ
+	struct notifier_block	cpufreq_transition;
+	int			cpufreq_changing;
+#endif
+
 	/* async schedule support */
 	struct ehci_qh		*async;
 	struct ehci_qh		*reclaim;
diff -purN --exclude=tags linux-2.6.20orig/drivers/usb/host/ehci-hcd.c linux-2.6.20new/drivers/usb/host/ehci-hcd.c
--- linux-2.6.20orig/drivers/usb/host/ehci-hcd.c	2007-02-04 12:44:54.000000000 -0600
+++ linux-2.6.20new/drivers/usb/host/ehci-hcd.c	2007-02-20 11:24:31.000000000 -0600
@@ -268,6 +268,62 @@ static void ehci_work(struct ehci_hcd *e
 
 /*-------------------------------------------------------------------------*/
 
+#ifdef CONFIG_CPU_FREQ
+
+#include <linux/cpufreq.h>
+
+static void ehci_cpufreq_pause (struct ehci_hcd *ehci)
+{
+	unsigned long	flags;
+
+	spin_lock_irqsave(&ehci->lock, flags);
+	if (!ehci->cpufreq_changing++ &&
+	    (ehci->periodic_sched) &&
+	    (ehci_to_hcd(ehci)->state == HC_STATE_RUNNING)) {
+		int status;
+		disable_periodic(ehci);
+		/* make sure it's off before proceeding with freq change */
+		status = handshake (&ehci->regs->status, STS_PSS, 0, 9 * 125);
+	}
+	spin_unlock_irqrestore(&ehci->lock, flags);
+}
+
+static void ehci_cpufreq_unpause (struct ehci_hcd *ehci)
+{
+	unsigned long	flags;
+
+	spin_lock_irqsave(&ehci->lock, flags);
+	if (!--ehci->cpufreq_changing &&
+	    (ehci->periodic_sched) &&
+	    (ehci_to_hcd(ehci)->state == HC_STATE_RUNNING)) {
+		enable_periodic(ehci);
+	}
+	spin_unlock_irqrestore(&ehci->lock, flags);
+}
+
+#define __type_entry(ptr,type,member) ((type *)((char *)(ptr)-offsetof(type,member)))
+
+static int ehci_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
+				 void *data)
+{
+	struct ehci_hcd *ehci = __type_entry(nb, struct ehci_hcd, 
+					     cpufreq_transition);
+
+	switch (val) {
+	case CPUFREQ_PRECHANGE:
+		ehci_cpufreq_pause(ehci);
+		break;
+	case CPUFREQ_POSTCHANGE:
+		ehci_cpufreq_unpause(ehci);
+		break;
+	}
+	return 0;
+}
+
+#endif
+
+/*-------------------------------------------------------------------------*/
+
 static void ehci_watchdog (unsigned long param)
 {
 	struct ehci_hcd		*ehci = (struct ehci_hcd *) param;
@@ -307,7 +363,10 @@ ehci_shutdown (struct usb_hcd *hcd)
 
 	ehci = hcd_to_ehci (hcd);
 	(void) ehci_halt (ehci);
-
+#ifdef CONFIG_CPU_FREQ
+	cpufreq_unregister_notifier(&ehci->cpufreq_transition,
+				    CPUFREQ_TRANSITION_NOTIFIER);
+#endif
 	/* make BIOS/etc use companion controller during reboot */
 	writel (0, &ehci->regs->configured_flag);
 }
@@ -485,6 +544,12 @@ static int ehci_init(struct usb_hcd *hcd
 	}
 	ehci->command = temp;
 
+#ifdef CONFIG_CPU_FREQ
+	ehci->cpufreq_transition.notifier_call = ehci_cpufreq_notifier;
+	cpufreq_register_notifier(&ehci->cpufreq_transition,
+				  CPUFREQ_TRANSITION_NOTIFIER);
+#endif
+
 	return 0;
 }
 
diff -purN --exclude=tags linux-2.6.20orig/drivers/usb/host/ehci-sched.c linux-2.6.20new/drivers/usb/host/ehci-sched.c
--- linux-2.6.20orig/drivers/usb/host/ehci-sched.c	2007-02-04 12:44:54.000000000 -0600
+++ linux-2.6.20new/drivers/usb/host/ehci-sched.c	2007-02-20 11:24:31.000000000 -0600
@@ -430,6 +430,15 @@ static int enable_periodic (struct ehci_
 	u32	cmd;
 	int	status;
 
+#ifdef CONFIG_CPU_FREQ
+	/* Only enable if CPUs aren't changing frequency, else
+	 * split transactions may generate QTD_STS_MMF because
+	 * of cache snoop delays when EHCI controller reads mem!
+	 */
+	if (ehci->cpufreq_changing)
+		return 0;
+#endif
+
 	/* did clearing PSE did take effect yet?
 	 * takes effect only at frame boundaries...
 	 */
@@ -455,6 +464,13 @@ static int disable_periodic (struct ehci
 	u32	cmd;
 	int	status;
 
+	/* don't disable if it already is--both CPU freq change and
+	 * an empty periodic schedule can turn it off
+	 */
+	cmd = readl (&ehci->regs->command);
+	if (!(cmd & CMD_PSE))
+		return 0;
+
 	/* did setting PSE not take effect yet?
 	 * takes effect only at frame boundaries...
 	 */
