From: Takamasa Ohtake <[EMAIL PROTECTED]>
I have found a problem where the root_port_reset() goes into an infinite
loop and stalls the kernel.
This happens when a hardware fault inside the machine occurs during a small
timing window. In case of USB device connection, if a USB device responds to
hcd_submit_urb(), and later the controller fails before root_port_reset(),
root_port_reset() will loop infinitely because ohci_readl() will always
return "-1". Such a failure can include ejecting a CardBus OHCI controller.
The probability of this problem is low, but it will increase if PnP type
usage is frequent. The attached patch can solve this problem and I believe
that it is better to fix this problem.
Signed-off-by: Takamasa Ohtake <[EMAIL PROTECTED]>
Signed-off-by: David Brownell <[EMAIL PROTECTED]>
Index: g26/drivers/usb/host/ohci-hub.c
===================================================================
--- g26.orig/drivers/usb/host/ohci-hub.c 2006-12-04 15:01:33.000000000
-0800
+++ g26/drivers/usb/host/ohci-hub.c 2006-12-06 16:57:12.000000000 -0800
@@ -547,7 +547,7 @@ static void start_hnp(struct ohci_hcd *o
#define tick_before(t1,t2) ((s16)(((s16)(t1))-((s16)(t2))) < 0)
/* called from some task, normally khubd */
-static inline void root_port_reset (struct ohci_hcd *ohci, unsigned port)
+static inline int root_port_reset (struct ohci_hcd *ohci, unsigned port)
{
__hc32 __iomem *portstat = &ohci->regs->roothub.portstatus [port];
u32 temp;
@@ -562,6 +562,9 @@ static inline void root_port_reset (stru
/* spin until any current reset finishes */
for (;;) {
temp = ohci_readl (ohci, portstat);
+ /* handle e.g. CardBus eject */
+ if (temp == ~(u32)0)
+ return -ESHUTDOWN;
if (!(temp & RH_PS_PRS))
break;
udelay (500);
@@ -578,6 +581,8 @@ static inline void root_port_reset (stru
now = ohci_readl(ohci, &ohci->regs->fmnumber);
} while (tick_before(now, reset_done));
/* caller synchronizes using PRSC */
+
+ return 0;
}
static int ohci_hub_control (
@@ -694,7 +699,7 @@ static int ohci_hub_control (
&ohci->regs->roothub.portstatus [wIndex]);
break;
case USB_PORT_FEAT_RESET:
- root_port_reset (ohci, wIndex);
+ retval = root_port_reset (ohci, wIndex);
break;
default:
goto error;
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel