Subject: Re: kern/32011 usb HC detach race condition
To: None <kern-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: Matthew Orgass <darkstar@city-net.com>
List: netbsd-bugs
Date: 11/21/2006 18:40:02
The following reply was made to PR kern/32011; it has been noted by GNATS.

From: Matthew Orgass <darkstar@city-net.com>
To: gnats-bugs@netbsd.org
Cc: 
Subject: Re: kern/32011 usb HC detach race condition
Date: Tue, 21 Nov 2006 10:59:42 -0500 (EST)

   An alternate patch that also add sc_dying setting to uhci, moves it in
 ehci and ohci, removes it from usb_detach (where it is unnecessary),
 and includes the patch above.
 
 Index: sys/dev/usb/uhci.c
 ===================================================================
 RCS file: /cvsroot/src/sys/dev/usb/uhci.c,v
 retrieving revision 1.204
 diff -u -p -r1.204 uhci.c
 --- sys/dev/usb/uhci.c	31 Oct 2006 20:43:31 -0000	1.204
 +++ sys/dev/usb/uhci.c	21 Nov 2006 16:34:54 -0000
 @@ -573,6 +573,7 @@ uhci_activate(device_ptr_t self, enum de
  		return (EOPNOTSUPP);
 
  	case DVACT_DEACTIVATE:
 +		sc->sc_dying = 1;
  		if (sc->sc_child != NULL)
  			rv = config_deactivate(sc->sc_child);
  		break;
 Index: sys/dev/usb/ehci.c
 ===================================================================
 RCS file: /cvsroot/src/sys/dev/usb/ehci.c,v
 retrieving revision 1.114
 diff -u -p -r1.114 ehci.c
 --- sys/dev/usb/ehci.c	31 Oct 2006 20:43:31 -0000	1.114
 +++ sys/dev/usb/ehci.c	21 Nov 2006 16:34:59 -0000
 @@ -983,9 +983,9 @@ ehci_activate(device_ptr_t self, enum de
  		return (EOPNOTSUPP);
 
  	case DVACT_DEACTIVATE:
 +		sc->sc_dying = 1;
  		if (sc->sc_child != NULL)
  			rv = config_deactivate(sc->sc_child);
 -		sc->sc_dying = 1;
  		break;
  	}
  	return (rv);
 Index: sys/dev/usb/ohci.c
 ===================================================================
 RCS file: /cvsroot/src/sys/dev/usb/ohci.c,v
 retrieving revision 1.178
 diff -u -p -r1.178 ohci.c
 --- sys/dev/usb/ohci.c	31 Oct 2006 20:43:31 -0000	1.178
 +++ sys/dev/usb/ohci.c	21 Nov 2006 16:35:04 -0000
 @@ -374,9 +374,9 @@ ohci_activate(device_ptr_t self, enum de
  		return (EOPNOTSUPP);
 
  	case DVACT_DEACTIVATE:
 +		sc->sc_dying = 1;
  		if (sc->sc_child != NULL)
  			rv = config_deactivate(sc->sc_child);
 -		sc->sc_dying = 1;
  		break;
  	}
  	return (rv);
 Index: sys/dev/usb/usb.c
 ===================================================================
 RCS file: /cvsroot/src/sys/dev/usb/usb.c,v
 retrieving revision 1.90
 diff -u -p -r1.90 usb.c
 --- sys/dev/usb/usb.c	31 Oct 2006 20:43:31 -0000	1.90
 +++ sys/dev/usb/usb.c	21 Nov 2006 16:35:06 -0000
 @@ -848,21 +848,17 @@ usb_detach(device_ptr_t self, int flags
 
  	DPRINTF(("usb_detach: start\n"));
 
 -	sc->sc_dying = 1;
 +	/* Kill off event thread. */
 +	while (sc->sc_event_thread != NULL) {
 +		wakeup(&sc->sc_bus->needs_explore);
 +		tsleep(sc, PWAIT, "usbdet", hz * 60);
 +	}
 +	DPRINTF(("usb_detach: event thread dead\n"));
 
  	/* Make all devices disconnect. */
  	if (sc->sc_port.device != NULL)
  		usb_disconnect_port(&sc->sc_port, self);
 
 -	/* Kill off event thread. */
 -	if (sc->sc_event_thread != NULL) {
 -		wakeup(&sc->sc_bus->needs_explore);
 -		if (tsleep(sc, PWAIT, "usbdet", hz * 60))
 -			printf("%s: event thread didn't die\n",
 -			       USBDEVNAME(sc->sc_dev));
 -		DPRINTF(("usb_detach: event thread dead\n"));
 -	}
 -
  	usbd_finish();
 
  #ifdef USB_USE_SOFTINTR