From: David Miller <davem@davemloft.net>
To: david-b@pacbell.net
Cc: linux-usb-users@lists.sourceforge.net,
linux-kernel@vger.kernel.org, greg@kroah.com
Subject: Re: OHCI root_port_reset() deadly loop...
Date: Mon, 08 Oct 2007 21:44:08 -0700 (PDT) [thread overview]
Message-ID: <20071008.214408.98397070.davem@davemloft.net> (raw)
In-Reply-To: <20071009043643.773CC23715F@adsl-69-226-248-13.dsl.pltn13.pacbell.net>
From: David Brownell <david-b@pacbell.net>
Date: Mon, 08 Oct 2007 21:36:43 -0700
> Don't need this "limit_1" timeout; "reset_done" handles all
> the timeout needed there. The regs->fmnumber is essentially
> a millisecond counter.
If the hardware hangs and the register stops incrementing,
the entire kernel will hang. That is unacceptable.
We do need it.
>
> > + int limit_2;
> > +
> > /* spin until any current reset finishes */
> > - for (;;) {
> > + limit_2 = PORT_RESET_MSEC * 2;
>
> This is the loop that didn't terminate for you, right?
> PORT_RESET_HW_MSEC is the ceiling you should use here,
> not PORT_RESET_MSEC.
Ok, fixed.
> What values do you see for "portstat"?
0x111
> I suspect there will be some flag set which would allow a more
> immediate exit from that loop. RH_PS_CCS might clear, for example.
Absolutely nothing clears in the register from it's initial value.
Here is the patch with the limit_2 initial value fixed.
I kept loop_1 in there, it is necessary. No kernel code should
hang in an endless loop because of malfunctioning hardware.
Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index bb9cc59..9149593 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -563,14 +563,19 @@ static inline int root_port_reset (struct ohci_hcd *ohci, unsigned port)
u32 temp;
u16 now = ohci_readl(ohci, &ohci->regs->fmnumber);
u16 reset_done = now + PORT_RESET_MSEC;
+ int limit_1;
/* build a "continuous enough" reset signal, with up to
* 3msec gap between pulses. scheduler HZ==100 must work;
* this might need to be deadline-scheduled.
*/
- do {
+ limit_1 = 100;
+ while (--limit_1 >= 0) {
+ int limit_2;
+
/* spin until any current reset finishes */
- for (;;) {
+ limit_2 = PORT_RESET_HW_MSEC * 2;
+ while (--limit_2 >= 0) {
temp = ohci_readl (ohci, portstat);
/* handle e.g. CardBus eject */
if (temp == ~(u32)0)
@@ -579,6 +584,10 @@ static inline int root_port_reset (struct ohci_hcd *ohci, unsigned port)
break;
udelay (500);
}
+ if (limit_2 < 0) {
+ ohci_warn(ohci, "Root port inner-loop reset timeout, "
+ "portstat[%08x]\n", temp);
+ }
if (!(temp & RH_PS_CCS))
break;
@@ -589,7 +598,14 @@ static inline int root_port_reset (struct ohci_hcd *ohci, unsigned port)
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));
+ if (!tick_before(now, reset_done))
+ break;
+ }
+ if (limit_1 < 0) {
+ ohci_warn(ohci, "Root port outer-loop reset timeout, "
+ "now[%04x] reset_done[%04x]\n",
+ now, reset_done);
+ }
/* caller synchronizes using PRSC */
return 0;
next prev parent reply other threads:[~2007-10-09 4:44 UTC|newest]
Thread overview: 49+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-10-07 6:53 OHCI root_port_reset() deadly loop David Miller
2007-10-07 7:31 ` David Brownell
2007-10-07 7:51 ` David Miller
2007-10-08 23:54 ` David Miller
2007-10-09 3:10 ` Greg KH
2007-10-09 3:16 ` David Miller
2007-10-09 3:34 ` David Brownell
2007-10-09 3:42 ` David Miller
2007-10-09 4:39 ` Greg KH
2007-10-09 4:47 ` David Miller
2007-10-09 5:11 ` Benjamin Herrenschmidt
2007-10-09 6:06 ` Greg KH
2007-10-09 19:22 ` [linux-usb-devel] " David Brownell
2007-10-10 15:32 ` Alan Stern
2007-10-09 5:00 ` David Brownell
2007-10-09 5:23 ` David Miller
2007-10-09 6:43 ` Benjamin Herrenschmidt
2007-10-09 18:48 ` David Brownell
2007-10-09 16:01 ` [Linux-usb-users] " Alan Stern
2007-10-09 17:39 ` Greg KH
2007-10-09 18:42 ` Alan Stern
2007-10-09 18:59 ` David Brownell
2007-10-09 21:27 ` David Miller
2007-10-09 21:43 ` David Brownell
2007-10-09 22:00 ` David Miller
2007-10-10 4:35 ` David Miller
2007-10-15 22:01 ` David Miller
2007-10-15 23:39 ` David Brownell
2007-10-15 23:58 ` David Miller
2007-10-16 15:23 ` Alan Stern
2007-10-16 22:06 ` David Miller
2007-10-16 22:20 ` Greg KH
2007-10-17 15:56 ` Alan Stern
2007-10-16 22:08 ` David Miller
2007-10-17 15:51 ` Alan Stern
2007-10-17 23:03 ` David Miller
2007-10-18 14:28 ` Alan Stern
2007-10-16 18:26 ` David Brownell
2007-10-09 4:09 ` David Brownell
2007-10-09 5:13 ` Benjamin Herrenschmidt
2007-10-09 5:26 ` David Miller
2007-10-09 6:37 ` Benjamin Herrenschmidt
2007-10-09 4:36 ` David Brownell
2007-10-09 4:44 ` David Miller [this message]
2007-10-09 16:38 ` David Brownell
2007-10-09 20:41 ` David Miller
2007-10-09 20:46 ` Greg KH
2007-10-09 21:05 ` David Brownell
2007-10-09 21:09 ` David Brownell
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20071008.214408.98397070.davem@davemloft.net \
--to=davem@davemloft.net \
--cc=david-b@pacbell.net \
--cc=greg@kroah.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-usb-users@lists.sourceforge.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox