From 38b375d9610e2467cb793a84d17c6f65e44cdb39 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 21 Jul 2008 09:56:26 -0400 Subject: USB: OHCI: fix system hang caused by earlier patch This patch (as1114) fixes a problem that was revealed by an earlier patch (as1069b). Some broken controllers seem never to turn off their RHCS interrupt status bit, even when told to do so. As a result they generate an interrupt storm and hang the system. The patch avoids enabling RHSC interrupt requests when the RHCS status bit is already set. This should have no adverse affects on normal controllers, since they won't set the status bit until a root-hub status change actually occurs, in which case we wouldn't enable RHSC interrupt requests anyway -- we would wait until the status change had been processed and cleared. Signed-off-by: Alan Stern Tested by: Andrey Borzenkov Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-hub.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/usb/host/ohci-hub.c') diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index b56739221d1..d54183f1d70 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c @@ -483,6 +483,13 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf) length++; } + /* Some broken controllers never turn off RHCS in the interrupt + * status register. For their sake we won't re-enable RHSC + * interrupts if the flag is already set. + */ + if (ohci_readl(ohci, &ohci->regs->intrstatus) & OHCI_INTR_RHSC) + changed = 1; + /* look at each port */ for (i = 0; i < ohci->num_ports; i++) { u32 status = roothub_portstatus (ohci, i); -- cgit v1.2.3 From e8b24450a635bbbd3a2b4c2649eef060c742ebc0 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sun, 6 Jul 2008 14:26:30 +0400 Subject: USB: Hook start_hnp into ohci struct Signed-off-by: Dmitry Baryshkov Acked-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-hub.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/usb/host/ohci-hub.c') diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index d54183f1d70..439beb784f3 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c @@ -579,8 +579,6 @@ static int ohci_start_port_reset (struct usb_hcd *hcd, unsigned port) return 0; } -static void start_hnp(struct ohci_hcd *ohci); - #else #define ohci_start_port_reset NULL @@ -767,7 +765,7 @@ static int ohci_hub_control ( #ifdef CONFIG_USB_OTG if (hcd->self.otg_port == (wIndex + 1) && hcd->self.b_hnp_enable) - start_hnp(ohci); + ohci->start_hnp(ohci); else #endif ohci_writel (ohci, RH_PS_PSS, -- cgit v1.2.3