summaryrefslogtreecommitdiff
path: root/drivers/usb/core/driver.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/core/driver.c')
-rw-r--r--drivers/usb/core/driver.c43
1 files changed, 15 insertions, 28 deletions
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 2f3dc4cdf79b..207146743ea7 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -26,8 +26,9 @@
#include <linux/slab.h>
#include <linux/usb.h>
#include <linux/usb/quirks.h>
+#include <linux/usb/hcd.h>
#include <linux/pm_runtime.h>
-#include "hcd.h"
+
#include "usb.h"
@@ -1355,13 +1356,9 @@ int usb_resume(struct device *dev, pm_message_t msg)
*
* The caller must hold @udev's device lock.
*/
-int usb_enable_autosuspend(struct usb_device *udev)
+void usb_enable_autosuspend(struct usb_device *udev)
{
- if (udev->autosuspend_disabled) {
- udev->autosuspend_disabled = 0;
- usb_autosuspend_device(udev);
- }
- return 0;
+ pm_runtime_allow(&udev->dev);
}
EXPORT_SYMBOL_GPL(usb_enable_autosuspend);
@@ -1374,16 +1371,9 @@ EXPORT_SYMBOL_GPL(usb_enable_autosuspend);
*
* The caller must hold @udev's device lock.
*/
-int usb_disable_autosuspend(struct usb_device *udev)
+void usb_disable_autosuspend(struct usb_device *udev)
{
- int rc = 0;
-
- if (!udev->autosuspend_disabled) {
- rc = usb_autoresume_device(udev);
- if (rc == 0)
- udev->autosuspend_disabled = 1;
- }
- return rc;
+ pm_runtime_forbid(&udev->dev);
}
EXPORT_SYMBOL_GPL(usb_disable_autosuspend);
@@ -1485,9 +1475,6 @@ int usb_autoresume_device(struct usb_device *udev)
* 0, a delayed autosuspend request for @intf's device is attempted. The
* attempt may fail (see autosuspend_check()).
*
- * If the driver has set @intf->needs_remote_wakeup then autosuspend will
- * take place only if the device's remote-wakeup facility is enabled.
- *
* This routine can run only in process context.
*/
void usb_autopm_put_interface(struct usb_interface *intf)
@@ -1530,7 +1517,7 @@ void usb_autopm_put_interface_async(struct usb_interface *intf)
atomic_dec(&intf->pm_usage_cnt);
pm_runtime_put_noidle(&intf->dev);
- if (!udev->autosuspend_disabled) {
+ if (udev->dev.power.runtime_auto) {
/* Optimization: Don't schedule a delayed autosuspend if
* the timer is already running and the expiration time
* wouldn't change.
@@ -1672,14 +1659,14 @@ EXPORT_SYMBOL_GPL(usb_autopm_get_interface_no_resume);
/* Internal routine to check whether we may autosuspend a device. */
static int autosuspend_check(struct usb_device *udev)
{
- int i;
+ int w, i;
struct usb_interface *intf;
unsigned long suspend_time, j;
/* Fail if autosuspend is disabled, or any interfaces are in use, or
* any interface drivers require remote wakeup but it isn't available.
*/
- udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
+ w = 0;
if (udev->actconfig) {
for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
intf = udev->actconfig->interface[i];
@@ -1693,12 +1680,7 @@ static int autosuspend_check(struct usb_device *udev)
continue;
if (atomic_read(&intf->dev.power.usage_count) > 0)
return -EBUSY;
- if (intf->needs_remote_wakeup &&
- !udev->do_remote_wakeup) {
- dev_dbg(&udev->dev, "remote wakeup needed "
- "for autosuspend\n");
- return -EOPNOTSUPP;
- }
+ w |= intf->needs_remote_wakeup;
/* Don't allow autosuspend if the device will need
* a reset-resume and any of its interface drivers
@@ -1714,6 +1696,11 @@ static int autosuspend_check(struct usb_device *udev)
}
}
}
+ if (w && !device_can_wakeup(&udev->dev)) {
+ dev_dbg(&udev->dev, "remote wakeup needed for autosuspend\n");
+ return -EOPNOTSUPP;
+ }
+ udev->do_remote_wakeup = w;
/* If everything is okay but the device hasn't been idle for long
* enough, queue a delayed autosuspend request.