Dear, All. I have found a problem where the root_port_reset() goes into an infinite loop and stall the kernel.
This happens when an 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 machine fails before root_port_reset(), root_port_reset() will loop infinitely because ohci_readl() will always return "-1". The probability of this problem is low, but it will increase if PnP processing becomes frequent. The attached patch can solve this problem and I believe that it is better to fix this problem. [in the case of the USB device connection] hub_events() | hub_port_connect_change() | <omission> | usb_submit_urb() | hcd_submit_urb() <---- If the H/W machine trouble has already occured, | hcd_submit_urb() returns error code(ESHUTDOWN). | And the functions after this are not called. <omission> | | <------- If the H/W machine trouble occurs between hcd_submit_urb() | and root_port_reset(),root_port_reset() will go into | endless loop because ohci_readl() will always return "-1". | root_port_reset() The patch that fixed this problem is as follows. Signed-off-by:Takamasa Ohtake <[EMAIL PROTECTED]> Index: linux-2.6.15.4/drivers/usb/host/ohci-hub.c =================================================================== --- linux-2.6.15.4/drivers/usb/host/ohci-hub.c.orig 2006-02-28 14:05:22.716664344 +0900 +++ linux-2.6.15.4/drivers/usb/host/ohci-hub.c 2006-02-28 14:05:22.699666928 +0900 @@ -475,7 +475,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; @@ -490,6 +490,8 @@ static inline void root_port_reset (stru /* spin until any current reset finishes */ for (;;) { temp = ohci_readl (ohci, portstat); + if (temp == ~(u32)0) + return -ESHUTDOWN; if (!(temp & RH_PS_PRS)) break; udelay (500); @@ -506,6 +508,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 ( @@ -625,7 +629,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; ^--- -------------------------------------------------- Takamasa Ohtake | Servers Software Division | NEC System Technologies, Ltd. | [EMAIL PROTECTED] -------------------------------------------------- ------------------------------------------------------- This SF.Net email is sponsored by xPML, a groundbreaking scripting language that extends applications into web and mobile media. Attend the live webcast and join the prime developer group breaking into this new coding territory! http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642 _______________________________________________ linux-usb-devel@lists.sourceforge.net To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel