On Mon, 15 Oct 2007, David Miller wrote:

> I want to help with this, but if I even breath on the kernel the bug
> goes away.  The race just gets harder to trigger, and if we just keep
> adding things it'll make the problem go away but for the absolutely
> wrong reasons.
> 
> The only way we will provably fix this is to make sure EHCI initialize
> fully, first, regardless of kernel config or what userland does.

Unfortunately that simply isn't possible.  No matter what you do, the 
user can always unload ehci-hcd and then load it back in again.

Do you have any idea _where_ in ohci_hub_control the hang still occurs?  
Is it the same unbounded reset loop?

Does the patch below satisfy both Davids?

Alan Stern



Index: usb-2.6/drivers/usb/host/ohci-hub.c
===================================================================
--- usb-2.6.orig/drivers/usb/host/ohci-hub.c
+++ usb-2.6/drivers/usb/host/ohci-hub.c
@@ -560,10 +560,10 @@ static void start_hnp(struct ohci_hcd *o
 /* called from some task, normally khubd */
 static inline int root_port_reset (struct ohci_hcd *ohci, unsigned port)
 {
-       __hc32 __iomem *portstat = &ohci->regs->roothub.portstatus [port];
-       u32     temp;
-       u16     now = ohci_readl(ohci, &ohci->regs->fmnumber);
-       u16     reset_done = now + PORT_RESET_MSEC;
+       __hc32 __iomem  *portstat = &ohci->regs->roothub.portstatus[port];
+       u32             temp;
+       unsigned long   reset_done = jiffies +
+                               msecs_to_jiffies(PORT_RESET_MSEC);
 
        /* build a "continuous enough" reset signal, with up to
         * 3msec gap between pulses.  scheduler HZ==100 must work;
@@ -578,6 +578,8 @@ static inline int root_port_reset (struc
                                return -ESHUTDOWN;
                        if (!(temp & RH_PS_PRS))
                                break;
+                       if (time_after(jiffies, reset_done))
+                               break;
                        udelay (500);
                }
 
@@ -589,8 +591,7 @@ static inline int root_port_reset (struc
                /* start the next reset, sleep till it's probably done */
                ohci_writel (ohci, RH_PS_PRS, portstat);
                msleep(PORT_RESET_HW_MSEC);
-               now = ohci_readl(ohci, &ohci->regs->fmnumber);
-       } while (tick_before(now, reset_done));
+       } while (time_before_eq(jiffies, reset_done));
        /* caller synchronizes using PRSC */
 
        return 0;


-------------------------------------------------------------------------
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/
_______________________________________________
Linux-usb-users@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-users

Reply via email to