summaryrefslogtreecommitdiff
path: root/drivers/usb/core/driver.c
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2010-01-08 20:56:54 +0300
committerGreg Kroah-Hartman <gregkh@suse.de>2010-03-03 01:54:10 +0300
commit088f7fec8a0e683db72fd8826c5d3ab914e197b1 (patch)
tree971ef100d0db9727e4403865b67c72de62e8247a /drivers/usb/core/driver.c
parent0c4db6df915bc470f0cd32fe48287fa6eb6adfb4 (diff)
downloadlinux-088f7fec8a0e683db72fd8826c5d3ab914e197b1.tar.xz
USB: implement usb_enable_autosuspend
This patch (as1326) adds usb_enable_autosuspend() and usb_disable_autosuspend() routines for use by drivers. If a driver knows that its device can handle suspends and resumes correctly, it can enable autosuspend all by itself. This is equivalent to the user writing "auto" to the device's power/level attribute. The implementation differs slightly from what it used to be. Now autosuspend is disabled simply by doing usb_autoresume_device() (to increment the usage counter) and enabled by doing usb_autosuspend_device() (to decrement the usage counter). The set_level() attribute method is updated to use the new routines, and the USB Power-Management documentation is updated. The patch adds a usb_enable_autosuspend() call to the hub driver's probe routine, allowing the special-case code for hubs in quirks.c to be removed. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/core/driver.c')
-rw-r--r--drivers/usb/core/driver.c42
1 files changed, 42 insertions, 0 deletions
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 2b39583040d0..057eeab06004 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -1415,6 +1415,48 @@ static int usb_resume_both(struct usb_device *udev, pm_message_t msg)
#ifdef CONFIG_USB_SUSPEND
+/**
+ * usb_enable_autosuspend - allow a USB device to be autosuspended
+ * @udev: the USB device which may be autosuspended
+ *
+ * This routine allows @udev to be autosuspended. An autosuspend won't
+ * take place until the autosuspend_delay has elapsed and all the other
+ * necessary conditions are satisfied.
+ *
+ * The caller must hold @udev's device lock.
+ */
+int usb_enable_autosuspend(struct usb_device *udev)
+{
+ if (udev->autosuspend_disabled) {
+ udev->autosuspend_disabled = 0;
+ usb_autosuspend_device(udev);
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(usb_enable_autosuspend);
+
+/**
+ * usb_disable_autosuspend - prevent a USB device from being autosuspended
+ * @udev: the USB device which may not be autosuspended
+ *
+ * This routine prevents @udev from being autosuspended and wakes it up
+ * if it is already autosuspended.
+ *
+ * The caller must hold @udev's device lock.
+ */
+int 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;
+}
+EXPORT_SYMBOL_GPL(usb_disable_autosuspend);
+
/* Internal routine to adjust a device's usage counter and change
* its autosuspend state.
*/