diff options
| author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2012-01-08 23:38:23 -0800 | 
|---|---|---|
| committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2012-01-08 23:38:23 -0800 | 
| commit | da733563be5a9da26fe81d9f007262d00b846e22 (patch) | |
| tree | db28291df94a2043af2123911984c5c173da4e6f /drivers/usb/core/driver.c | |
| parent | 6ccbcf2cb41131f8d56ef0723bf3f7c1f8486076 (diff) | |
| parent | dab78d7924598ea4031663dd10db814e2e324928 (diff) | |
Merge branch 'next' into for-linus
Diffstat (limited to 'drivers/usb/core/driver.c')
| -rw-r--r-- | drivers/usb/core/driver.c | 31 | 
1 files changed, 25 insertions, 6 deletions
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 34e3da5aa72..45887a0ff87 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -24,6 +24,7 @@  #include <linux/device.h>  #include <linux/slab.h> +#include <linux/export.h>  #include <linux/usb.h>  #include <linux/usb/quirks.h>  #include <linux/usb/hcd.h> @@ -1046,8 +1047,7 @@ static int usb_resume_device(struct usb_device *udev, pm_message_t msg)  	/* Non-root devices on a full/low-speed bus must wait for their  	 * companion high-speed root hub, in case a handoff is needed.  	 */ -	if (!(msg.event & PM_EVENT_AUTO) && udev->parent && -			udev->bus->hs_companion) +	if (!PMSG_IS_AUTO(msg) && udev->parent && udev->bus->hs_companion)  		device_pm_wait_for_dev(&udev->dev,  				&udev->bus->hs_companion->root_hub->dev); @@ -1075,7 +1075,7 @@ static int usb_suspend_interface(struct usb_device *udev,  	if (driver->suspend) {  		status = driver->suspend(intf, msg); -		if (status && !(msg.event & PM_EVENT_AUTO)) +		if (status && !PMSG_IS_AUTO(msg))  			dev_err(&intf->dev, "%s error %d\n",  					"suspend", status);  	} else { @@ -1189,7 +1189,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)  			status = usb_suspend_interface(udev, intf, msg);  			/* Ignore errors during system sleep transitions */ -			if (!(msg.event & PM_EVENT_AUTO)) +			if (!PMSG_IS_AUTO(msg))  				status = 0;  			if (status != 0)  				break; @@ -1199,7 +1199,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)  		status = usb_suspend_device(udev, msg);  		/* Again, ignore errors during system sleep transitions */ -		if (!(msg.event & PM_EVENT_AUTO)) +		if (!PMSG_IS_AUTO(msg))  			status = 0;  	} @@ -1583,7 +1583,7 @@ int usb_autopm_get_interface_async(struct usb_interface *intf)  	dev_vdbg(&intf->dev, "%s: cnt %d -> %d\n",  			__func__, atomic_read(&intf->dev.power.usage_count),  			status); -	if (status > 0) +	if (status > 0 || status == -EINPROGRESS)  		status = 0;  	return status;  } @@ -1668,6 +1668,11 @@ int usb_runtime_suspend(struct device *dev)  		return -EAGAIN;  	status = usb_suspend_both(udev, PMSG_AUTO_SUSPEND); + +	/* Allow a retry if autosuspend failed temporarily */ +	if (status == -EAGAIN || status == -EBUSY) +		usb_mark_last_busy(udev); +  	/* The PM core reacts badly unless the return code is 0,  	 * -EAGAIN, or -EBUSY, so always return -EBUSY on an error.  	 */ @@ -1700,6 +1705,20 @@ int usb_runtime_idle(struct device *dev)  	return 0;  } +int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable) +{ +	struct usb_hcd *hcd = bus_to_hcd(udev->bus); +	int ret = -EPERM; + +	if (hcd->driver->set_usb2_hw_lpm) { +		ret = hcd->driver->set_usb2_hw_lpm(hcd, udev, enable); +		if (!ret) +			udev->usb2_hw_lpm_enabled = enable; +	} + +	return ret; +} +  #endif /* CONFIG_USB_SUSPEND */  struct bus_type usb_bus_type = {  | 
