From b13296c6617f22e8c0174a7af32780617db0e680 Mon Sep 17 00:00:00 2001
From: David Brownell <david-b@pacbell.net>
Date: Tue, 27 Sep 2005 10:38:54 -0700
Subject: [PATCH] [PATCH] updates for "controller suspended" handling

Reject URBs to _all_ devices when their host controllers are suspended;
even root hub registers will be unavailable.  Also, don't reject urbs
to root hubs in other cases; the only upstream link is through that
controller (on PCI or whatever SOC bus is in use).

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

 drivers/usb/core/hcd.c |   28 ++++++++++++----------------
 drivers/usb/core/urb.c |    3 ++-
 2 files changed, 14 insertions(+), 17 deletions(-)
---
 drivers/usb/core/hcd.c | 28 ++++++++++++----------------
 drivers/usb/core/urb.c |  3 ++-
 2 files changed, 14 insertions(+), 17 deletions(-)

diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index de59bb515315d..b7bb8dd1894a4 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -458,22 +458,18 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
 
 	default:
 		/* non-generic request */
-		if (HC_IS_SUSPENDED (hcd->state))
-			status = -EAGAIN;
-		else {
-			switch (typeReq) {
-			case GetHubStatus:
-			case GetPortStatus:
-				len = 4;
-				break;
-			case GetHubDescriptor:
-				len = sizeof (struct usb_hub_descriptor);
-				break;
-			}
-			status = hcd->driver->hub_control (hcd,
-				typeReq, wValue, wIndex,
-				tbuf, wLength);
+		switch (typeReq) {
+		case GetHubStatus:
+		case GetPortStatus:
+			len = 4;
+			break;
+		case GetHubDescriptor:
+			len = sizeof (struct usb_hub_descriptor);
+			break;
 		}
+		status = hcd->driver->hub_control (hcd,
+			typeReq, wValue, wIndex,
+			tbuf, wLength);
 		break;
 error:
 		/* "protocol stall" on error */
@@ -487,7 +483,7 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
 				"CTRL: TypeReq=0x%x val=0x%x "
 				"idx=0x%x len=%d ==> %d\n",
 				typeReq, wValue, wIndex,
-				wLength, urb->status);
+				wLength, status);
 		}
 	}
 	if (len) {
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index b32898e0a27d1..f2a1fed2a8024 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -237,7 +237,8 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
 	    (dev->state < USB_STATE_DEFAULT) ||
 	    (!dev->bus) || (dev->devnum <= 0))
 		return -ENODEV;
-	if (dev->state == USB_STATE_SUSPENDED)
+	if (dev->bus->controller->power.power_state.event != PM_EVENT_ON
+			|| dev->state == USB_STATE_SUSPENDED)
 		return -EHOSTUNREACH;
 	if (!(op = dev->bus->op) || !op->submit_urb)
 		return -ENODEV;
-- 
GitLab