diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2006-08-30 15:47:02 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-09-27 14:58:57 -0400 |
commit | 645daaab0b6adc35c1838df2a82f9d729fdb1767 (patch) | |
tree | 908d58f6c0ad01e9c1622a4c12c9c8080c629baa /drivers/usb/core/usb.c | |
parent | b6956ffa595db97656d5901ca8fec77ef272d41a (diff) |
usbcore: add autosuspend/autoresume infrastructure
This patch (as739) adds the basic infrastructure for USB autosuspend
and autoresume. The main features are:
PM usage counters added to struct usb_device and struct
usb_interface, indicating whether it's okay to autosuspend
them or they are currently in use.
Flag added to usb_device indicating whether the current
suspend/resume operation originated from outside or as an
autosuspend/autoresume.
Flag added to usb_driver indicating whether the driver
supports autosuspend. If not, no device bound to the driver
will be autosuspended.
Mutex added to usb_device for protecting PM operations.
Unlike the device semaphore, the locking rule for the pm_mutex
is that you must acquire the locks going _up_ the device tree.
New routines handling autosuspend/autoresume requests for
interfaces and devices.
Suspend and resume requests are propagated up the device tree
(but not outside the USB subsystem).
work_struct added to usb_device, for carrying out delayed
autosuspend requests.
Autoresume added (and autosuspend prevented) during probe and
disconnect.
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/core/usb.c')
-rw-r--r-- | drivers/usb/core/usb.c | 23 |
1 files changed, 23 insertions, 0 deletions
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index b0c0a993338f..6b029cdb8671 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c | |||
@@ -168,6 +168,10 @@ static void usb_release_dev(struct device *dev) | |||
168 | 168 | ||
169 | udev = to_usb_device(dev); | 169 | udev = to_usb_device(dev); |
170 | 170 | ||
171 | #ifdef CONFIG_PM | ||
172 | cancel_delayed_work(&udev->autosuspend); | ||
173 | flush_scheduled_work(); | ||
174 | #endif | ||
171 | usb_destroy_configuration(udev); | 175 | usb_destroy_configuration(udev); |
172 | usb_put_hcd(bus_to_hcd(udev->bus)); | 176 | usb_put_hcd(bus_to_hcd(udev->bus)); |
173 | kfree(udev->product); | 177 | kfree(udev->product); |
@@ -176,6 +180,21 @@ static void usb_release_dev(struct device *dev) | |||
176 | kfree(udev); | 180 | kfree(udev); |
177 | } | 181 | } |
178 | 182 | ||
183 | #ifdef CONFIG_PM | ||
184 | |||
185 | /* usb_autosuspend_work - callback routine to autosuspend a USB device */ | ||
186 | static void usb_autosuspend_work(void *_udev) | ||
187 | { | ||
188 | struct usb_device *udev = _udev; | ||
189 | |||
190 | mutex_lock_nested(&udev->pm_mutex, udev->level); | ||
191 | udev->auto_pm = 1; | ||
192 | usb_suspend_both(udev, PMSG_SUSPEND); | ||
193 | mutex_unlock(&udev->pm_mutex); | ||
194 | } | ||
195 | |||
196 | #endif | ||
197 | |||
179 | /** | 198 | /** |
180 | * usb_alloc_dev - usb device constructor (usbcore-internal) | 199 | * usb_alloc_dev - usb device constructor (usbcore-internal) |
181 | * @parent: hub to which device is connected; null to allocate a root hub | 200 | * @parent: hub to which device is connected; null to allocate a root hub |
@@ -251,6 +270,10 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1) | |||
251 | dev->parent = parent; | 270 | dev->parent = parent; |
252 | INIT_LIST_HEAD(&dev->filelist); | 271 | INIT_LIST_HEAD(&dev->filelist); |
253 | 272 | ||
273 | #ifdef CONFIG_PM | ||
274 | mutex_init(&dev->pm_mutex); | ||
275 | INIT_WORK(&dev->autosuspend, usb_autosuspend_work, dev); | ||
276 | #endif | ||
254 | return dev; | 277 | return dev; |
255 | } | 278 | } |
256 | 279 | ||