[PATCH] bug with EHCI cpufreq patch on VIA controllers

<[email protected]>
Newsgroups gmane.linux.usb.devel
Message-ID <DFEF91B22ED07447AB6AA4B237F913F9B18ED8@ausx3mpc125.aus.amer.dell.com>
This patch fixes lockups caused by the cpu frequency change notifier and
VIA EHCI controllers.  The VIA controllers do not implement the
"inactivate" bit used by the cpu frequency change handler correctly.
EHCI 0.95 VIA controllers seem to ignore this bit completely, while EHCI
1.00 VIA controllers (the VT6212 and VT8237, at least) seem to respond
to this bit incorrectly by starting a split transaction and then marking
the transaction inactive without finishing it.

This patch will automatically disable the EHCI cpu frequency change
notifier when a VIA controller is detected, and also adds a parameter to
allow it to be disabled manually in case other problems are found.

This patch is against the 2.6.23-rc3 kernel plus the patch submitted and
accepted on 8/1 to fix a bug with nVidia controllers
(http://www.mail-archive.com/[email protected]/msg56
523.html).

Signed-off-by: Stuart Hayes <[email protected]>

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >>  http://get.splunk.com/

_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel
ehci_cpufreq_via.patch (application/octet-stream, 3.5 KB)
diff -purN --exclude=Makefile linux-2.6.23-rc3plus/drivers/usb/host/ehci.h linux-2.6.23-rc3plus_x/drivers/usb/host/ehci.h
--- linux-2.6.23-rc3plus/drivers/usb/host/ehci.h	2007-08-16 14:58:59.000000000 -0500
+++ linux-2.6.23-rc3plus_x/drivers/usb/host/ehci.h	2007-08-16 13:55:21.000000000 -0500
@@ -75,6 +75,7 @@ struct ehci_hcd {			/* one per controlle
 	struct notifier_block	cpufreq_transition;
 	int			cpufreq_changing;
 	struct list_head	split_intr_qhs;
+	int			cpufreq_handler_disable;
 #endif
 
 	/* async schedule support */
diff -purN --exclude=Makefile linux-2.6.23-rc3plus/drivers/usb/host/ehci-hcd.c linux-2.6.23-rc3plus_x/drivers/usb/host/ehci-hcd.c
--- linux-2.6.23-rc3plus/drivers/usb/host/ehci-hcd.c	2007-08-16 14:58:59.000000000 -0500
+++ linux-2.6.23-rc3plus_x/drivers/usb/host/ehci-hcd.c	2007-08-16 15:37:57.000000000 -0500
@@ -129,6 +129,11 @@ static int ignore_oc = 0;
 module_param (ignore_oc, bool, S_IRUGO);
 MODULE_PARM_DESC (ignore_oc, "ignore bogus hardware overcurrent indications");
 
+/* allow user to disable cpufreq notifier--it can break with bad HW */
+static int cpufreq_ignore = 0;
+module_param (cpufreq_ignore, bool, S_IRUGO);
+MODULE_PARM_DESC (cpufreq_ignore, "ignore cpufreq transitions");
+
 #define	INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT)
 
 /*-------------------------------------------------------------------------*/
@@ -461,8 +466,9 @@ static void ehci_stop (struct usb_hcd *h
 	spin_unlock_irq(&ehci->lock);
 
 #ifdef CONFIG_CPU_FREQ
-	cpufreq_unregister_notifier(&ehci->cpufreq_transition,
-				    CPUFREQ_TRANSITION_NOTIFIER);
+	if (!ehci->cpufreq_handler_disable)
+		cpufreq_unregister_notifier(&ehci->cpufreq_transition,
+					    CPUFREQ_TRANSITION_NOTIFIER);
 #endif
 	/* let companion controllers work when we aren't */
 	ehci_writel(ehci, 0, &ehci->regs->configured_flag);
@@ -576,9 +582,15 @@ static int ehci_init(struct usb_hcd *hcd
 	 * isn't needed unless there are so many low/full speed devices
 	 * that the controller's can't cache it all.
 	 */
-	ehci->cpufreq_transition.notifier_call = ehci_cpufreq_notifier;
-	cpufreq_register_notifier(&ehci->cpufreq_transition,
-				  CPUFREQ_TRANSITION_NOTIFIER);
+	if (cpufreq_ignore)
+		ehci->cpufreq_handler_disable = 1;
+
+	if (!ehci->cpufreq_handler_disable) {
+		ehci->cpufreq_transition.notifier_call = ehci_cpufreq_notifier;
+		cpufreq_register_notifier(&ehci->cpufreq_transition,
+					  CPUFREQ_TRANSITION_NOTIFIER);
+	} else
+		ehci_info(ehci, "ignoring cpu frequency transitions\n");
 #endif
 	return 0;
 }
diff -purN --exclude=Makefile linux-2.6.23-rc3plus/drivers/usb/host/ehci-pci.c linux-2.6.23-rc3plus_x/drivers/usb/host/ehci-pci.c
--- linux-2.6.23-rc3plus/drivers/usb/host/ehci-pci.c	2007-08-16 14:58:59.000000000 -0500
+++ linux-2.6.23-rc3plus_x/drivers/usb/host/ehci-pci.c	2007-08-17 14:35:58.000000000 -0500
@@ -114,6 +114,20 @@ static int ehci_pci_setup(struct usb_hcd
 			break;
 		}
 		break;
+#ifdef CONFIG_CPU_FREQ
+	case PCI_VENDOR_ID_VIA:
+		/* VIA controllers do not support the "inactivate" bit
+		 * correctly... their EHCI 0.95 parts ignore it, and their
+		 * EHCI 1.00 parts (at least the VT6212 controller and
+		 * VT8237 bridge) start a split transaction but don't finish
+		 * it when the "inactivate" bit is set. 
+		 * Right now, the cpufreq handler uses this bit, so disable
+		 * this for VIA controllers.
+		 */
+		ehci->cpufreq_handler_disable = 1;
+		ehci_warn(ehci, "ignoring cpu frequency transitions "
+				"because of a bug in VIA controllers.\n");
+#endif
 	}
 
 	/* cache this readonly data; minimize chip reads */
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.