Re: [Linux-usb-users] OHCI root_port_reset() deadly loop...

Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]
From: Alan Stern
Date: Wednesday, October 17, 2007 - 8:51 am

On Tue, 16 Oct 2007, David Miller wrote:


Okay, below is my patch with a warning message.


It isn't just fine.  See below for comments. 


Where did 100 come from?  Why not rely on the reset_done criterion,
which clearly is what you want?  Why have two tests for end-of-loop?


This also is a somewhat arbitrary limit.  There's no obvious reason why
PORT_RESET_HW_MSEC should be both the limit for this loop and the
length of the msleep below.


I realize that you are copying existing code here, but this makes the 
same kind of mistake you are trying to fix.  If a broken controller 
fails to increment its framenumber register, this termination condition 
will never be satisfied.  Better to compare against a jiffies value.


What reason is there for having two warning messages?  One ought to be 
enough.

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,12 @@ static inline int root_port_reset (struc
 				return -ESHUTDOWN;
 			if (!(temp & RH_PS_PRS))
 				break;
+			if (time_after(jiffies, reset_done)) {
+				ohci_warn(ohci, "Port %d reset timeout, "
+						"status %x\n",
+						port + 1, temp);
+				break;
+			}
 			udelay (500);
 		}
 
@@ -589,8 +595,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;

-
Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]

Messages in current thread:
OHCI root_port_reset() deadly loop..., David Miller, (Sat Oct 6, 11:53 pm)
Re: OHCI root_port_reset() deadly loop..., David Brownell, (Sun Oct 7, 12:31 am)
Re: OHCI root_port_reset() deadly loop..., David Miller, (Sun Oct 7, 12:51 am)
Re: OHCI root_port_reset() deadly loop..., David Miller, (Mon Oct 8, 4:54 pm)
Re: OHCI root_port_reset() deadly loop..., Greg KH, (Mon Oct 8, 8:10 pm)
Re: OHCI root_port_reset() deadly loop..., David Miller, (Mon Oct 8, 8:16 pm)
Re: OHCI root_port_reset() deadly loop..., David Brownell, (Mon Oct 8, 8:34 pm)
Re: OHCI root_port_reset() deadly loop..., David Miller, (Mon Oct 8, 8:42 pm)
Re: OHCI root_port_reset() deadly loop..., David Brownell, (Mon Oct 8, 9:09 pm)
Re: OHCI root_port_reset() deadly loop..., David Brownell, (Mon Oct 8, 9:36 pm)
Re: OHCI root_port_reset() deadly loop..., Greg KH, (Mon Oct 8, 9:39 pm)
Re: OHCI root_port_reset() deadly loop..., David Miller, (Mon Oct 8, 9:44 pm)
Re: OHCI root_port_reset() deadly loop..., David Miller, (Mon Oct 8, 9:47 pm)
Re: OHCI root_port_reset() deadly loop..., David Brownell, (Mon Oct 8, 10:00 pm)
Re: OHCI root_port_reset() deadly loop..., Benjamin Herrenschmidt, (Mon Oct 8, 10:11 pm)
Re: OHCI root_port_reset() deadly loop..., Benjamin Herrenschmidt, (Mon Oct 8, 10:13 pm)
Re: OHCI root_port_reset() deadly loop..., David Miller, (Mon Oct 8, 10:23 pm)
Re: OHCI root_port_reset() deadly loop..., David Miller, (Mon Oct 8, 10:26 pm)
Re: OHCI root_port_reset() deadly loop..., Greg KH, (Mon Oct 8, 11:06 pm)
Re: OHCI root_port_reset() deadly loop..., Benjamin Herrenschmidt, (Mon Oct 8, 11:37 pm)
Re: OHCI root_port_reset() deadly loop..., Benjamin Herrenschmidt, (Mon Oct 8, 11:43 pm)
Re: OHCI root_port_reset() deadly loop..., David Brownell, (Tue Oct 9, 9:38 am)
Re: OHCI root_port_reset() deadly loop..., David Brownell, (Tue Oct 9, 11:48 am)
Re: OHCI root_port_reset() deadly loop..., David Miller, (Tue Oct 9, 1:41 pm)
Re: OHCI root_port_reset() deadly loop..., Greg KH, (Tue Oct 9, 1:46 pm)
Re: OHCI root_port_reset() deadly loop..., David Brownell, (Tue Oct 9, 2:05 pm)
Re: OHCI root_port_reset() deadly loop..., David Brownell, (Tue Oct 9, 2:09 pm)
Re: [Linux-usb-users] OHCI root_port_reset() deadly loop..., David Brownell, (Tue Oct 16, 11:26 am)
Re: [Linux-usb-users] OHCI root_port_reset() deadly loop..., Alan Stern, (Wed Oct 17, 8:51 am)