aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/core/usb.c
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2006-08-30 15:47:02 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2006-09-27 14:58:57 -0400
commit645daaab0b6adc35c1838df2a82f9d729fdb1767 (patch)
tree908d58f6c0ad01e9c1622a4c12c9c8080c629baa /drivers/usb/core/usb.c
parentb6956ffa595db97656d5901ca8fec77ef272d41a (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.c23
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 */
186static 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