[patch 2.6.23-rc3 2/4] EHCI issues with cpufreq on VIA
David Brownell <[email protected]>
| Newsgroups | gmane.linux.usb.devel |
|---|---|
| Message-ID | <[email protected]> |
From: Stuart Hayes <[email protected]> This patch fixes lockups caused by the cpu frequency change notifier interacting with silicon bugs in VIA EHCI controllers. VIA EHCI does not correctly implement the "inactivate" bit used by the cpu frequency change handler. Old EHCI 0.95 versions ignore this bit completely. At least VT6212 (discrete) and VT8237 (southbridge) EHCI 1.00 versions 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 adds a parameter to allow it to be disabled manually in case other problems are found. Signed-off-by: Stuart Hayes <[email protected]> Signed-off-by: David Brownell <[email protected]> --- This patch resolves a regression, and should merge for 2.6.23-final. drivers/usb/host/ehci-hcd.c | 22 +++++++++++++++++----- drivers/usb/host/ehci-pci.c | 15 ++++++++++++++- drivers/usb/host/ehci.h | 5 +++-- 3 files changed, 34 insertions(+), 8 deletions(-) --- g26.orig/drivers/usb/host/ehci.h 2007-07-12 17:50:02.000000000 -0700 +++ g26/drivers/usb/host/ehci.h 2007-08-17 22:45:12.000000000 -0700 @@ -75,13 +75,14 @@ struct ehci_hcd { /* one per controlle struct notifier_block cpufreq_transition; int cpufreq_changing; struct list_head split_intr_qhs; + unsigned cpufreq_handler_disable:1; #endif /* async schedule support */ - struct ehci_qh *async; - struct ehci_qh *reclaim; unsigned reclaim_ready : 1; unsigned scanning : 1; + struct ehci_qh *async; + struct ehci_qh *reclaim; /* periodic schedule support */ #define DEFAULT_I_TDPS 1024 /* some HCs can do less */ --- g26.orig/drivers/usb/host/ehci-hcd.c 2007-07-12 17:50:02.000000000 -0700 +++ g26/drivers/usb/host/ehci-hcd.c 2007-08-17 22:45:28.000000000 -0700 @@ -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; +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; } --- g26.orig/drivers/usb/host/ehci-pci.c 2007-08-17 22:29:47.000000000 -0700 +++ g26/drivers/usb/host/ehci-pci.c 2007-08-17 22:39:27.000000000 -0700 @@ -112,6 +112,19 @@ 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, "VIA bugs; ignoring cpufreq transitions\n"); +#endif } /* cache this readonly data; minimize chip reads */ @@ -390,5 +403,5 @@ static struct pci_driver ehci_pci_driver .suspend = usb_hcd_pci_suspend, .resume = usb_hcd_pci_resume, #endif - .shutdown = usb_hcd_pci_shutdown, + .shutdown = usb_hcd_pci_shutdown, }; ------------------------------------------------------------------------- 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