diff options
Diffstat (limited to 'drivers/usb/core/hub.c')
| -rw-r--r-- | drivers/usb/core/hub.c | 16 | 
1 files changed, 11 insertions, 5 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 90ae1753dda..a428aa080a3 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1634,6 +1634,7 @@ void usb_disconnect(struct usb_device **pdev)  {  	struct usb_device	*udev = *pdev;  	int			i; +	struct usb_hcd		*hcd = bus_to_hcd(udev->bus);  	if (!udev) {  		pr_debug ("%s nodev\n", __func__); @@ -1661,7 +1662,9 @@ void usb_disconnect(struct usb_device **pdev)  	 * so that the hardware is now fully quiesced.  	 */  	dev_dbg (&udev->dev, "unregistering device\n"); +	mutex_lock(hcd->bandwidth_mutex);  	usb_disable_device(udev, 0); +	mutex_unlock(hcd->bandwidth_mutex);  	usb_hcd_synchronize_unlinks(udev);  	usb_remove_ep_devs(&udev->ep0); @@ -2362,6 +2365,10 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)  				USB_DEVICE_REMOTE_WAKEUP, 0,  				NULL, 0,  				USB_CTRL_SET_TIMEOUT); + +		/* System sleep transitions should never fail */ +		if (!(msg.event & PM_EVENT_AUTO)) +			status = 0;  	} else {  		/* device has up to 10 msec to fully suspend */  		dev_dbg(&udev->dev, "usb %ssuspend\n", @@ -2611,16 +2618,15 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)  	struct usb_device	*hdev = hub->hdev;  	unsigned		port1; -	/* fail if children aren't already suspended */ +	/* Warn if children aren't already suspended */  	for (port1 = 1; port1 <= hdev->maxchild; port1++) {  		struct usb_device	*udev;  		udev = hdev->children [port1-1];  		if (udev && udev->can_submit) { -			if (!(msg.event & PM_EVENT_AUTO)) -				dev_dbg(&intf->dev, "port %d nyet suspended\n", -						port1); -			return -EBUSY; +			dev_warn(&intf->dev, "port %d nyet suspended\n", port1); +			if (msg.event & PM_EVENT_AUTO) +				return -EBUSY;  		}  	}  |