Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 22 Apr 2009 17:07:56 +0000 (UTC)
From:      Andrew Thompson <thompsa@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r191396 - head/sys/dev/usb
Message-ID:  <200904221707.n3MH7urT062602@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: thompsa
Date: Wed Apr 22 17:07:56 2009
New Revision: 191396
URL: http://svn.freebsd.org/changeset/base/191396

Log:
  MFp4 //depot/projects/usb@160485
  
  Fix a bug in the USB power daemon code where connection of multiple HUBs in
  series would result in incorrect device suspend.
  
  Reported by:	Nicolas xxx@wanadoo.fr
  Submitted by:	Hans Petter Selasky

Modified:
  head/sys/dev/usb/usb_hub.c

Modified: head/sys/dev/usb/usb_hub.c
==============================================================================
--- head/sys/dev/usb/usb_hub.c	Wed Apr 22 17:07:53 2009	(r191395)
+++ head/sys/dev/usb/usb_hub.c	Wed Apr 22 17:07:56 2009	(r191396)
@@ -1786,12 +1786,10 @@ usb2_dev_resume_peer(struct usb2_device 
 static void
 usb2_dev_suspend_peer(struct usb2_device *udev)
 {
-	struct usb2_device *hub;
 	struct usb2_device *child;
 	int err;
 	uint8_t x;
 	uint8_t nports;
-	uint8_t suspend_parent;
 
 repeat:
 	/* be NULL safe */
@@ -1808,16 +1806,15 @@ repeat:
 
 	DPRINTF("udev=%p\n", udev);
 
-	/* check if all devices on the parent hub are suspended */
-	hub = udev->parent_hub;
-	if (hub != NULL) {
-		nports = hub->hub->nports;
-		suspend_parent = 1;
+	/* check if the current device is a HUB */
+	if (udev->hub != NULL) {
+		nports = udev->hub->nports;
 
+		/* check if all devices on the HUB are suspended */
 		for (x = 0; x != nports; x++) {
 
-			child = usb2_bus_port_get_device(hub->bus,
-			    hub->hub->ports + x);
+			child = usb2_bus_port_get_device(udev->bus,
+			    udev->hub->ports + x);
 
 			if (child == NULL)
 				continue;
@@ -1825,16 +1822,9 @@ repeat:
 			if (child->pwr_save.suspended)
 				continue;
 
-			if (child == udev)
-				continue;
-
-			/* another device on the HUB is not suspended */
-			suspend_parent = 0;
-
-			break;
+			DPRINTFN(1, "Port %u is busy on the HUB!\n", x + 1);
+			return;
 		}
-	} else {
-		suspend_parent = 0;
 	}
 
 	sx_xlock(udev->default_sx + 1);
@@ -1877,11 +1867,9 @@ repeat:
 		DPRINTFN(0, "Suspending port failed\n");
 		return;
 	}
-	if (suspend_parent) {
-		udev = udev->parent_hub;
-		goto repeat;
-	}
-	return;
+
+	udev = udev->parent_hub;
+	goto repeat;
 }
 
 /*------------------------------------------------------------------------*



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200904221707.n3MH7urT062602>