[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <Pine.LNX.4.44L0.0710161107510.4418-100000@iolanthe.rowland.org>
Date: Tue, 16 Oct 2007 11:23:58 -0400 (EDT)
From: Alan Stern <stern@...land.harvard.edu>
To: David Miller <davem@...emloft.net>
cc: david-b@...bell.net, <linux-usb-users@...ts.sourceforge.net>,
<linux-kernel@...r.kernel.org>, <greg@...ah.com>
Subject: Re: [Linux-usb-users] OHCI root_port_reset() deadly loop...
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;
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists