Re: RE: Reboot on "shutdown -r" hangs after final "uptime ..." string

From: Don Lewis <truckman_at_FreeBSD.org>
Date: Fri, 10 Aug 2007 08:05:03 -0700 (PDT)
On 10 Aug, Bruce Cran wrote:
> Thomas Sparrevohn wrote:
>> I have the same problem - just as a test try to load a kernel without
>> any USB drivers at all And shutdown - on my machine it the ACPI part
>> works - however the system hangs during the device Shutdown phase -
>> this machine is a dell as well - would be nice if somebody using
>> other than dell has the problem
>>   
> I'm running 7.0-CURRENT and am seeing the same problem on my Dell 
> Inspiron 1501 amd64 laptop.  This machine has OHCI and EHCI
> controllers; removing the EHCI driver solves the problem and allows
> the computer to reboot properly.  I initially thought it was an ACPI
> problem but now I'm not so sure - is there anything I can do to help
> debug it?  I've added printfs to kern_shutdown.c and as far as I can
> see the last function to be called is shutdown_wait; since that
> doesn't do anything I know more is going on, but I don't know where
> to look.

I'm seeing this problem on an Athlon 64 desktop machine with the NVIDIA
GeForce 7050PV / nForce 630a chipset.  The hang is occuring at this
point in boot() in kern_shutdown.c:

        /* Now that we're going to really halt the system... */
        EVENTHANDLER_INVOKE(shutdown_final, howto);

The culprit is an infinite loop in ehci_pci_givecontroller(), which is
called from ehci_shutdown().  The infinite loop is triggered by reading
the incorrect value from one of the EHCI controller registers because
the register is being read before a reset of the controller has
completed.

Try this patch:

Index: sys/dev/usb/ehci.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/usb/ehci.c,v
retrieving revision 1.55
diff -u -r1.55 ehci.c
--- sys/dev/usb/ehci.c	20 Jun 2007 05:10:52 -0000	1.55
+++ sys/dev/usb/ehci.c	4 Aug 2007 21:05:46 -0000
_at__at_ -311,6 +311,25 _at__at_
 	ehci_device_isoc_done,
 };
 
+static usbd_status
+ehci_hcreset(ehci_softc_t *sc)
+{
+	u_int32_t hcr;
+	u_int i;
+
+	EOWRITE4(sc, EHCI_USBCMD, 0);	/* Halt controller */
+	usb_delay_ms(&sc->sc_bus, 1);
+	EOWRITE4(sc, EHCI_USBCMD, EHCI_CMD_HCRESET);
+	for (i = 0; i < 100; i++) {
+		usb_delay_ms(&sc->sc_bus, 1);
+		hcr = EOREAD4(sc, EHCI_USBCMD) & EHCI_CMD_HCRESET;
+		if (!hcr)
+			return (USBD_NORMAL_COMPLETION);
+	}
+	printf("%s: reset timeout\n", device_get_nameunit(sc->sc_bus.bdev));
+	return (USBD_IOERROR);
+}
+
 usbd_status
 ehci_init(ehci_softc_t *sc)
 {
_at__at_ -365,20 +384,9 _at__at_
 
 	/* Reset the controller */
 	DPRINTF(("%s: resetting\n", device_get_nameunit(sc->sc_bus.bdev)));
-	EOWRITE4(sc, EHCI_USBCMD, 0);	/* Halt controller */
-	usb_delay_ms(&sc->sc_bus, 1);
-	EOWRITE4(sc, EHCI_USBCMD, EHCI_CMD_HCRESET);
-	for (i = 0; i < 100; i++) {
-		usb_delay_ms(&sc->sc_bus, 1);
-		hcr = EOREAD4(sc, EHCI_USBCMD) & EHCI_CMD_HCRESET;
-		if (!hcr)
-			break;
-	}
-	if (hcr) {
-		printf("%s: reset timeout\n",
-		    device_get_nameunit(sc->sc_bus.bdev));
-		return (USBD_IOERROR);
-	}
+	err = ehci_hcreset(sc);
+	if (err != USBD_NORMAL_COMPLETION)
+		return (err);
 
 	/* frame list size at default, read back what we got and use that */
 	switch (EHCI_CMD_FLS(EOREAD4(sc, EHCI_USBCMD))) {
_at__at_ -927,8 +935,7 _at__at_
 	sc->sc_dying = 1;
 
 	EOWRITE4(sc, EHCI_USBINTR, sc->sc_eintrs);
-	EOWRITE4(sc, EHCI_USBCMD, 0);
-	EOWRITE4(sc, EHCI_USBCMD, EHCI_CMD_HCRESET);
+	(void) ehci_hcreset(sc);
 	callout_stop(&sc->sc_tmo_intrlist);
 	callout_stop(&sc->sc_tmo_pcd);
 
_at__at_ -1090,8 +1097,7 _at__at_
 	ehci_softc_t *sc = v;
 
 	DPRINTF(("ehci_shutdown: stopping the HC\n"));
-	EOWRITE4(sc, EHCI_USBCMD, 0);	/* Halt controller */
-	EOWRITE4(sc, EHCI_USBCMD, EHCI_CMD_HCRESET);
+	(void) ehci_hcreset(sc);
 }
 
 usbd_status
Received on Fri Aug 10 2007 - 13:05:23 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:39:16 UTC