diff options
-rw-r--r-- | Documentation/usb/power-management.txt | 217 | ||||
-rw-r--r-- | drivers/usb/core/Kconfig | 4 | ||||
-rw-r--r-- | drivers/usb/core/driver.c | 845 | ||||
-rw-r--r-- | drivers/usb/core/hcd.c | 13 | ||||
-rw-r--r-- | drivers/usb/core/hcd.h | 10 | ||||
-rw-r--r-- | drivers/usb/core/hub.c | 65 | ||||
-rw-r--r-- | drivers/usb/core/message.c | 1 | ||||
-rw-r--r-- | drivers/usb/core/usb.c | 35 | ||||
-rw-r--r-- | drivers/usb/core/usb.h | 49 | ||||
-rw-r--r-- | drivers/usb/misc/usbtest.c | 4 | ||||
-rw-r--r-- | include/linux/usb.h | 31 |
11 files changed, 490 insertions, 784 deletions
diff --git a/Documentation/usb/power-management.txt b/Documentation/usb/power-management.txt index e3fa189c257..2790ad48cfc 100644 --- a/Documentation/usb/power-management.txt +++ b/Documentation/usb/power-management.txt @@ -2,7 +2,7 @@ Alan Stern <stern@rowland.harvard.edu> - November 10, 2009 + December 11, 2009 @@ -29,9 +29,9 @@ covered to some extent (see Documentation/power/*.txt for more information about system PM). Note: Dynamic PM support for USB is present only if the kernel was -built with CONFIG_USB_SUSPEND enabled. System PM support is present -only if the kernel was built with CONFIG_SUSPEND or CONFIG_HIBERNATION -enabled. +built with CONFIG_USB_SUSPEND enabled (which depends on +CONFIG_PM_RUNTIME). System PM support is present only if the kernel +was built with CONFIG_SUSPEND or CONFIG_HIBERNATION enabled. What is Remote Wakeup? @@ -326,64 +326,63 @@ driver does so by calling these six functions: void usb_autopm_get_interface_no_resume(struct usb_interface *intf); void usb_autopm_put_interface_no_suspend(struct usb_interface *intf); -The functions work by maintaining a counter in the usb_interface -structure. When intf->pm_usage_count is > 0 then the interface is -deemed to be busy, and the kernel will not autosuspend the interface's -device. When intf->pm_usage_count is <= 0 then the interface is -considered to be idle, and the kernel may autosuspend the device. +The functions work by maintaining a usage counter in the +usb_interface's embedded device structure. When the counter is > 0 +then the interface is deemed to be busy, and the kernel will not +autosuspend the interface's device. When the usage counter is = 0 +then the interface is considered to be idle, and the kernel may +autosuspend the device. -(There is a similar pm_usage_count field in struct usb_device, +(There is a similar usage counter field in struct usb_device, associated with the device itself rather than any of its interfaces. -This field is used only by the USB core.) - -Drivers must not modify intf->pm_usage_count directly; its value -should be changed only be using the functions listed above. Drivers -are responsible for insuring that the overall change to pm_usage_count -during their lifetime balances out to 0 (it may be necessary for the -disconnect method to call usb_autopm_put_interface() one or more times -to fulfill this requirement). The first two routines use the PM mutex -in struct usb_device for mutual exclusion; drivers using the async -routines are responsible for their own synchronization and mutual -exclusion. - - usb_autopm_get_interface() increments pm_usage_count and - attempts an autoresume if the new value is > 0 and the - device is suspended. - - usb_autopm_put_interface() decrements pm_usage_count and - attempts an autosuspend if the new value is <= 0 and the - device isn't suspended. +This counter is used only by the USB core.) + +Drivers need not be concerned about balancing changes to the usage +counter; the USB core will undo any remaining "get"s when a driver +is unbound from its interface. As a corollary, drivers must not call +any of the usb_autopm_* functions after their diconnect() routine has +returned. + +Drivers using the async routines are responsible for their own +synchronization and mutual exclusion. + + usb_autopm_get_interface() increments the usage counter and + does an autoresume if the device is suspended. If the + autoresume fails, the counter is decremented back. + + usb_autopm_put_interface() decrements the usage counter and + attempts an autosuspend if the new value is = 0. usb_autopm_get_interface_async() and usb_autopm_put_interface_async() do almost the same things as - their non-async counterparts. The differences are: they do - not acquire the PM mutex, and they use a workqueue to do their + their non-async counterparts. The big difference is that they + use a workqueue to do the resume or suspend part of their jobs. As a result they can be called in an atomic context, such as an URB's completion handler, but when they return the - device will not generally not yet be in the desired state. + device will generally not yet be in the desired state. usb_autopm_get_interface_no_resume() and usb_autopm_put_interface_no_suspend() merely increment or - decrement the pm_usage_count value; they do not attempt to - carry out an autoresume or an autosuspend. Hence they can be - called in an atomic context. + decrement the usage counter; they do not attempt to carry out + an autoresume or an autosuspend. Hence they can be called in + an atomic context. -The conventional usage pattern is that a driver calls +The simplest usage pattern is that a driver calls usb_autopm_get_interface() in its open routine and -usb_autopm_put_interface() in its close or release routine. But -other patterns are possible. +usb_autopm_put_interface() in its close or release routine. But other +patterns are possible. The autosuspend attempts mentioned above will often fail for one reason or another. For example, the power/level attribute might be set to "on", or another interface in the same device might not be idle. This is perfectly normal. If the reason for failure was that -the device hasn't been idle for long enough, a delayed workqueue -routine is automatically set up to carry out the operation when the -autosuspend idle-delay has expired. +the device hasn't been idle for long enough, a timer is scheduled to +carry out the operation automatically when the autosuspend idle-delay +has expired. Autoresume attempts also can fail, although failure would mean that the device is no longer present or operating properly. Unlike -autosuspend, there's no delay for an autoresume. +autosuspend, there's no idle-delay for an autoresume. Other parts of the driver interface @@ -413,26 +412,27 @@ though, setting this flag won't cause the kernel to autoresume it. Normally a driver would set this flag in its probe method, at which time the device is guaranteed not to be autosuspended.) -The synchronous usb_autopm_* routines have to run in a sleepable -process context; they must not be called from an interrupt handler or -while holding a spinlock. In fact, the entire autosuspend mechanism -is not well geared toward interrupt-driven operation. However there -is one thing a driver can do in an interrupt handler: +If a driver does its I/O asynchronously in interrupt context, it +should call usb_autopm_get_interface_async() before starting output and +usb_autopm_put_interface_async() when the output queue drains. When +it receives an input event, it should call usb_mark_last_busy(struct usb_device *udev); -This sets udev->last_busy to the current time. udev->last_busy is the -field used for idle-delay calculations; updating it will cause any -pending autosuspend to be moved back. The usb_autopm_* routines will -also set the last_busy field to the current time. - -Calling urb_mark_last_busy() from within an URB completion handler is -subject to races: The kernel may have just finished deciding the -device has been idle for long enough but not yet gotten around to -calling the driver's suspend method. The driver would have to be -responsible for synchronizing its suspend method with its URB -completion handler and causing the autosuspend to fail with -EBUSY if -an URB had completed too recently. +in the event handler. This sets udev->last_busy to the current time. +udev->last_busy is the field used for idle-delay calculations; +updating it will cause any pending autosuspend to be moved back. Most +of the usb_autopm_* routines will also set the last_busy field to the +current time. + +Asynchronous operation is always subject to races. For example, a +driver may call one of the usb_autopm_*_interface_async() routines at +a time when the core has just finished deciding the device has been +idle for long enough but not yet gotten around to calling the driver's +suspend method. The suspend method must be responsible for +synchronizing with the output request routine and the URB completion +handler; it should cause autosuspends to fail with -EBUSY if the +driver needs to use the device. External suspend calls should never be allowed to fail in this way, only autosuspend calls. The driver can tell them apart by checking @@ -440,75 +440,23 @@ the PM_EVENT_AUTO bit in the message.event argument to the suspend method; this bit will be set for internal PM events (autosuspend) and clear for external PM events. -Many of the ingredients in the autosuspend framework are oriented -towards interfaces: The usb_interface structure contains the -pm_usage_cnt field, and the usb_autopm_* routines take an interface -pointer as their argument. But somewhat confusingly, a few of the -pieces (i.e., usb_mark_last_busy()) use the usb_device structure -instead. Drivers need to keep this straight; they can call -interface_to_usbdev() to find the device structure for a given -interface. + Mutual exclusion + ---------------- - Locking requirements - -------------------- - -All three suspend/resume methods are always called while holding the -usb_device's PM mutex. For external events -- but not necessarily for -autosuspend or autoresume -- the device semaphore (udev->dev.sem) will -also be held. This implies that external suspend/resume events are -mutually exclusive with calls to probe, disconnect, pre_reset, and -post_reset; the USB core guarantees that this is true of internal -suspend/resume events as well. +For external events -- but not necessarily for autosuspend or +autoresume -- the device semaphore (udev->dev.sem) will be held when a +suspend or resume method is called. This implies that external +suspend/resume events are mutually exclusive with calls to probe, +disconnect, pre_reset, and post_reset; the USB core guarantees that +this is true of autosuspend/autoresume events as well. If a driver wants to block all suspend/resume calls during some -critical section, it can simply acquire udev->pm_mutex. Note that -calls to resume may be triggered indirectly. Block IO due to memory -allocations can make the vm subsystem resume a device. Thus while -holding this lock you must not allocate memory with GFP_KERNEL or -GFP_NOFS. - -Alternatively, if the critical section might call some of the -usb_autopm_* routines, the driver can avoid deadlock by doing: - - down(&udev->dev.sem); - rc = usb_autopm_get_interface(intf); - -and at the end of the critical section: - - if (!rc) - usb_autopm_put_interface(intf); - up(&udev->dev.sem); - -Holding the device semaphore will block all external PM calls, and the -usb_autopm_get_interface() will prevent any internal PM calls, even if -it fails. (Exercise: Why?) - -The rules for locking order are: - - Never acquire any device semaphore while holding any PM mutex. - - Never acquire udev->pm_mutex while holding the PM mutex for - a device that isn't a descendant of udev. - -In other words, PM mutexes should only be acquired going up the device -tree, and they should be acquired only after locking all the device -semaphores you need to hold. These rules don't matter to drivers very -much; they usually affect just the USB core. - -Still, drivers do need to be careful. For example, many drivers use a -private mutex to synchronize their normal I/O activities with their -disconnect method. Now if the driver supports autosuspend then it -must call usb_autopm_put_interface() from somewhere -- maybe from its -close method. It should make the call while holding the private mutex, -since a driver shouldn't call any of the usb_autopm_* functions for an -interface from which it has been unbound. - -But the usb_autpm_* routines always acquire the device's PM mutex, and -consequently the locking order has to be: private mutex first, PM -mutex second. Since the suspend method is always called with the PM -mutex held, it mustn't try to acquire the private mutex. It has to -synchronize with the driver's I/O activities in some other way. +critical section, the best way is to lock the device and call +usb_autopm_get_interface() (and do the reverse at the end of the +critical section). Holding the device semaphore will block all +external PM calls, and the usb_autopm_get_interface() will prevent any +internal PM calls, even if it fails. (Exercise: Why?) Interaction between dynamic PM and system PM @@ -517,22 +465,11 @@ synchronize with the driver's I/O activities in some other way. Dynamic power management and system power management can interact in a couple of ways. -Firstly, a device may already be manually suspended or autosuspended -when a system suspend occurs. Since system suspends are supposed to -be as transparent as possible, the device should remain suspended -following the system resume. The 2.6.23 kernel obeys this principle -for manually suspended devices but not for autosuspended devices; they -do get resumed when the system wakes up. (Presumably they will be -autosuspended again after their idle-delay time expires.) In later -kernels this behavior will be fixed. - -(There is an exception. If a device would undergo a reset-resume -instead of a normal resume, and the device is enabled for remote -wakeup, then the reset-resume takes place even if the device was -already suspended when the system suspend began. The justification is -that a reset-resume is a kind of remote-wakeup event. Or to put it -another way, a device which needs a reset won't be able to generate -normal remote-wakeup signals, so it ought to be resumed immediately.) +Firstly, a device may already be autosuspended when a system suspend +occurs. Since system suspends are supposed to be as transparent as +possible, the device should remain suspended following the system +resume. But this theory may not work out well in practice; over time +the kernel's behavior in this regard has changed. Secondly, a dynamic power-management event may occur as a system suspend is underway. The window for this is short, since system diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig index ad925946f86..97a819c23ef 100644 --- a/drivers/usb/core/Kconfig +++ b/drivers/usb/core/Kconfig @@ -91,8 +91,8 @@ config USB_DYNAMIC_MINORS If you are unsure about this, say N here. config USB_SUSPEND - bool "USB selective suspend/resume and wakeup" - depends on USB && PM + bool "USB runtime power management (suspend/resume and wakeup)" + depends on USB && PM_RUNTIME help If you say Y here, you can use driver calls or the sysfs "power/level" file to suspend or resume individual USB diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 638d54693a1..6850ec6576f 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -25,7 +25,7 @@ #include <linux/device.h> #include <linux/usb.h> #include <linux/usb/quirks.h> -#include <linux/workqueue.h> +#include <linux/pm_runtime.h> #include "hcd.h" #include "usb.h" @@ -221,7 +221,7 @@ static int usb_probe_device(struct device *dev) { struct usb_device_driver *udriver = to_usb_device_driver(dev->driver); struct usb_device *udev = to_usb_device(dev); - int error = -ENODEV; + int error = 0; dev_dbg(dev, "%s\n", __func__); @@ -230,18 +230,23 @@ static int usb_probe_device(struct device *dev) /* The device should always appear to be in use * unless the driver suports autosuspend. */ - udev->pm_usage_cnt = !(udriver->supports_autosuspend); + if (!udriver->supports_autosuspend) + error = usb_autoresume_device(udev); - error = udriver->probe(udev); + if (!error) + error = udriver->probe(udev); return error; } /* called from driver core with dev locked */ static int usb_unbind_device(struct device *dev) { + struct usb_device *udev = to_usb_device(dev); struct usb_device_driver *udriver = to_usb_device_driver(dev->driver); - udriver->disconnect(to_usb_device(dev)); + udriver->disconnect(udev); + if (!udriver->supports_autosuspend) + usb_autosuspend_device(udev); return 0; } @@ -293,17 +298,16 @@ static int usb_probe_interface(struct device *dev) if (error) return error; - /* Interface "power state" doesn't correspond to any hardware - * state whatsoever. We use it to record when it's bound to - * a driver that may start I/0: it's not frozen/quiesced. - */ - mark_active(intf); intf->condition = USB_INTERFACE_BINDING; - /* The interface should always appear to be in use - * unless the driver suports autosuspend. + /* Bound interfaces are initially active. They are + * runtime-PM-enabled only if the driver has autosuspend support. + * They are sensitive to their children's power states. */ - atomic_set(&intf->pm_usage_cnt, !driver->supports_autosuspend); + pm_runtime_set_active(dev); + pm_suspend_ignore_children(dev, false); + if (driver->supports_autosuspend) + pm_runtime_enable(dev); /* Carry out a deferred switch to altsetting 0 */ if (intf->needs_altsetting0) { @@ -323,10 +327,14 @@ static int usb_probe_interface(struct device *dev) return error; err: - mark_quiesced(intf); intf->needs_remote_wakeup = 0; intf->condition = USB_INTERFACE_UNBOUND; usb_cancel_queued_reset(intf); + + /* Unbound interfaces are always runtime-PM-disabled and -suspended */ + pm_runtime_disable(dev); + pm_runtime_set_suspended(dev); + usb_autosuspend_device(udev); return error; } @@ -376,9 +384,17 @@ static int usb_unbind_interface(struct device *dev) usb_set_intfdata(intf, NULL); intf->condition = USB_INTERFACE_UNBOUND; - mark_quiesced(intf); intf->needs_remote_wakeup = 0; + /* Unbound interfaces are always runtime-PM-disabled and -suspended */ + pm_runtime_disable(dev); + pm_runtime_set_suspended(dev); + + /* Undo any residual pm_autopm_get_interface_* calls */ + for (r = atomic_read(&intf->pm_usage_cnt); r > 0; --r) + usb_autopm_put_interface_no_suspend(intf); + atomic_set(&intf->pm_usage_cnt, 0); + if (!error) usb_autosuspend_device(udev); @@ -409,7 +425,6 @@ int usb_driver_claim_interface(struct usb_driver *driver, struct usb_interface *iface, void *priv) { struct device *dev = &iface->dev; - struct usb_device *udev = interface_to_usbdev(iface); int retval = 0; if (dev->driver) @@ -419,11 +434,16 @@ int usb_driver_claim_interface(struct usb_driver *driver, usb_set_intfdata(iface, priv); iface->needs_binding = 0; - usb_pm_lock(udev); iface->condition = USB_INTERFACE_BOUND; - mark_active(iface); - atomic_set(&iface->pm_usage_cnt, !driver->supports_autosuspend); - usb_pm_unlock(udev); + + /* Bound interfaces are initially active. They are + * runtime-PM-enabled only if the driver has autosuspend support. + * They are sensitive to their children's power states. + */ + pm_runtime_set_active(dev); + pm_suspend_ignore_children(dev, false); + if (driver->supports_autosuspend) + pm_runtime_enable(dev); /* if interface was already added, bind now; else let * the future device_add() bind it, bypassing probe() @@ -982,7 +1002,6 @@ static void do_unbind_rebind(struct usb_device *udev, int action) } } -/* Caller has locked udev's pm_mutex */ static int usb_suspend_device(struct usb_device *udev, pm_message_t msg) { struct usb_device_driver *udriver; @@ -1006,7 +1025,6 @@ static int usb_suspend_device(struct usb_device *udev, pm_message_t msg) return status; } -/* Caller has locked udev's pm_mutex */ static int usb_resume_device(struct usb_device *udev, pm_message_t msg) { struct usb_device_driver *udriver; @@ -1040,27 +1058,20 @@ static int usb_resume_device(struct usb_device *udev, pm_message_t msg) return status; } -/* Caller has locked intf's usb_device's pm mutex */ static int usb_suspend_interface(struct usb_device *udev, struct usb_interface *intf, pm_message_t msg) { struct usb_driver *driver; int status = 0; - /* with no hardware, USB interfaces only use FREEZE and ON states */ - if (udev->state == USB_STATE_NOTATTACHED || !is_active(intf)) - goto done; - - /* This can happen; see usb_driver_release_interface() */ - if (intf->condition == USB_INTERFACE_UNBOUND) + if (udev->state == USB_STATE_NOTATTACHED || + intf->condition == USB_INTERFACE_UNBOUND) goto done; driver = to_usb_driver(intf->dev.driver); if (driver->suspend) { status = driver->suspend(intf, msg); - if (status == 0) - mark_quiesced(intf); - else if (!(msg.event & PM_EVENT_AUTO)) + if (status && !(msg.event & PM_EVENT_AUTO)) dev_err(&intf->dev, "%s error %d\n", "suspend", status); } else { @@ -1068,7 +1079,6 @@ static int usb_suspend_interface(struct usb_device *udev, intf->needs_binding = 1; dev_warn(&intf->dev, "no %s for driver %s?\n", "suspend", driver->name); - mark_quiesced(intf); } done: @@ -1076,14 +1086,13 @@ static int usb_suspend_interface(struct usb_device *udev, return status; } -/* Caller has locked intf's usb_device's pm_mutex */ static int usb_resume_interface(struct usb_device *udev, struct usb_interface *intf, pm_message_t msg, int reset_resume) { struct usb_driver *driver; int status = 0; - if (udev->state == USB_STATE_NOTATTACHED || is_active(intf)) + if (udev->state == USB_STATE_NOTATTACHED) goto done; /* Don't let autoresume interfere with unbinding */ @@ -1134,90 +1143,11 @@ static int usb_resume_interface(struct usb_device *udev, done: dev_vdbg(&intf->dev, "%s: status %d\n", __func__, status); - if (status == 0 && intf->condition == USB_INTERFACE_BOUND) - mark_active(intf); /* Later we will unbind the driver and/or reprobe, if necessary */ return status; } -#ifdef CONFIG_USB_SUSPEND - -/* Internal routine to check whether we may autosuspend a device. */ -static int autosuspend_check(struct usb_device *udev, int reschedule) -{ - int i; - struct usb_interface *intf; - unsigned long suspend_time, j; - - /* For autosuspend, fail fast if anything is in use or autosuspend - * is disabled. Also fail if any interfaces require remote wakeup - * but it isn't available. - */ - if (udev->pm_usage_cnt > 0) - return -EBUSY; - if (udev->autosuspend_delay < 0 || udev->autosuspend_disabled) - return -EPERM; - - suspend_time = udev->last_busy + udev->autosuspend_delay; - if (udev->actconfig) { - for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { - intf = udev->actconfig->interface[i]; - if (!is_active(intf)) - continue; - if (atomic_read(&intf->pm_usage_cnt) > 0) - return -EBUSY; - if (intf->needs_remote_wakeup && - !udev->do_remote_wakeup) { - dev_dbg(&udev->dev, "remote wakeup needed " - "for autosuspend\n"); - return -EOPNOTSUPP; - } - - /* Don't allow autosuspend if the device will need - * a reset-resume and any of its interface drivers - * doesn't include support. - */ - if (udev->quirks & USB_QUIRK_RESET_RESUME) { - struct usb_driver *driver; - - driver = to_usb_driver(intf->dev.driver); - if (!driver->reset_resume || - intf->needs_remote_wakeup) - return -EOPNOTSUPP; - } - } - } - - /* If everything is okay but the device hasn't been idle for long - * enough, queue a delayed autosuspend request. If the device - * _has_ been idle for long enough and the reschedule flag is set, - * likewise queue a delayed (1 second) autosuspend request. - */ - j = jiffies; - if (time_before(j, suspend_time)) - reschedule = 1; - else - suspend_time = j + HZ; - if (reschedule) { - if (!timer_pending(&udev->autosuspend.timer)) { - queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend, - round_jiffies_up_relative(suspend_time - j)); - } - return -EAGAIN; - } - return 0; -} - -#else - -static inline int autosuspend_check(struct usb_device *udev, int reschedule) -{ - return 0; -} - -#endif /* CONFIG_USB_SUSPEND */ - /** * usb_suspend_both - suspend a USB device and its interfaces * @udev: the usb_device to suspend @@ -1229,27 +1159,12 @@ static inline int autosuspend_check(struct usb_device *udev, int reschedule) * all the interfaces which were suspended are resumed so that they remain * in the same state as the device. * - * If an autosuspend is in progress the routine checks first to make sure - * that neither the device itself or any of its active interfaces is in use - * (pm_usage_cnt is greater than 0). If they are, the autosuspend fails. - * - * If the suspend succeeds, the routine recursively queues an autosuspend - * request for @udev's parent device, thereby propagating the change up - * the device tree. If all of the parent's children are now suspended, - * the parent will autosuspend in turn. - * - * The suspend method calls are subject to mutual exclusion under control - * of @udev's pm_mutex. Many of these calls are also under the protection - * of @udev's device lock (including all requests originating outside the - * USB subsystem), but autosuspend requests generated by a child device or - * interface driver may not be. Usbcore will insure that the method calls - * do not arrive during bind, unbind, or reset operations. However, drivers - * must be prepared to handle suspend calls arriving at unpredictable times. - * The only way to block such calls is to do an autoresume (preventing - * autosuspends) while holding @udev's device lock (preventing outside - * suspends). - * - * The caller must hold @udev->pm_mutex. + * Autosuspend requests originating from a child device or an interface + * driver may be made without the protection of @udev's device lock, but + * all other suspend calls will hold the lock. Usbcore will insure that + * method calls do not arrive during bind, unbind, or reset operations. + * However drivers must be prepared to handle suspend calls arriving at + * unpredictable times. * * This routine can run only in process context. */ @@ -1258,20 +1173,11 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg) int status = 0; int i = 0; struct usb_interface *intf; - struct usb_device *parent = udev->parent; if (udev->state == USB_STATE_NOTATTACHED || udev->state == USB_STATE_SUSPENDED) goto done; - udev->do_remote_wakeup = device_may_wakeup(&udev->dev); - - if (msg.event & PM_EVENT_AUTO) { - status = autosuspend_check(udev, 0); - if (status < 0) - goto done; - } - /* Suspend all the interfaces and then udev itself */ if (udev->actconfig) { for (; i < udev->actconfig->desc.bNumInterfaces; i++) { @@ -1286,35 +1192,21 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg) /* If the suspend failed, resume interfaces that did get suspended */ if (status != 0) { - pm_message_t msg2; - - msg2.event = msg.event ^ (PM_EVENT_SUSPEND | PM_EVENT_RESUME); + msg.event ^= (PM_EVENT_SUSPEND | PM_EVENT_RESUME); while (--i >= 0) { intf = udev->actconfig->interface[i]; - usb_resume_interface(udev, intf, msg2, 0); + usb_resume_interface(udev, intf, msg, 0); } - /* Try another autosuspend when the interfaces aren't busy */ - if (msg.event & PM_EVENT_AUTO) - autosuspend_check(udev, status == -EBUSY); - - /* If the suspend succeeded then prevent any more URB submissions, - * flush any outstanding URBs, and propagate the suspend up the tree. + /* If the suspend succeeded then prevent any more URB submissions + * and flush any outstanding URBs. */ } else { - cancel_delayed_work(&udev->autosuspend); udev->can_submit = 0; for (i = 0; i < 16; ++i) { usb_hcd_flush_endpoint(udev, udev->ep_out[i]); usb_hcd_flush_endpoint(udev, udev->ep_in[i]); } - - /* If this is just a FREEZE or a PRETHAW, udev might - * not really be suspended. Only true suspends get - * propagated up the device tree. - */ - if (parent && udev->state == USB_STATE_SUSPENDED) - usb_autosuspend_device(parent); } done: @@ -1331,23 +1223,12 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg) * the resume method for @udev and then calls the resume methods for all * the interface drivers in @udev. * - * Before starting the resume, the routine calls itself recursively for - * the parent device of @udev, thereby propagating the change up the device - * tree and assuring that @udev will be able to resume. If the parent is - * unable to resume successfully, the routine fails. - * - * The resume method calls are subject to mutual exclusion under control - * of @udev's pm_mutex. Many of these calls are also under the protection - * of @udev's device lock (including all requests originating outside the - * USB subsystem), but autoresume requests generated by a child device or - * interface driver may not be. Usbcore will insure that the method calls - * do not arrive during bind, unbind, or reset operations. However, drivers - * must be prepared to handle resume calls arriving at unpredictable times. - * The only way to block such calls is to do an autoresume (preventing - * other autoresumes) while holding @udev's device lock (preventing outside - * resumes). - * - * The caller must hold @udev->pm_mutex. + * Autoresume requests originating from a child device or an interface + * driver may be made without the protection of @udev's device lock, but + * all other resume calls will hold the lock. Usbcore will insure that + * method calls do not arrive during bind, unbind, or reset operations. + * However drivers must be prepared to handle resume calls arriving at + * unpredictable times. * * This routine can run only in process context. */ @@ -1356,48 +1237,18 @@ static int usb_resume_both(struct usb_device *udev, pm_message_t msg) int status = 0; int i; struct usb_interface *intf; - struct usb_device *parent = udev->parent; - cancel_delayed_work(&udev->autosuspend); if (udev->state == USB_STATE_NOTATTACHED) { status = -ENODEV; goto done; } udev->can_submit = 1; - /* Propagate the resume up the tree, if necessary */ - if (udev->state == USB_STATE_SUSPENDED) { - if (parent) { - status = usb_autoresume_device(parent); - if (status == 0) { - status = usb_resume_device(udev, msg); - if (status || udev->state == - USB_STATE_NOTATTACHED) { - usb_autosuspend_device(parent); - - /* It's possible usb_resume_device() - * failed after the port was - * unsuspended, causing udev to be - * logically disconnected. We don't - * want usb_disconnect() to autosuspend - * the parent again, so tell it that - * udev disconnected while still - * suspended. */ - if (udev->state == - USB_STATE_NOTATTACHED) - udev->discon_suspended = 1; - } - } - } else { - - /* We can't progagate beyond the USB subsystem, - * so if a root hub's controller is suspended - * then we're stuck. */ - status = usb_resume_device(udev, msg); - } - } else if (udev->reset_resume) + /* Resume the device */ + if (udev->state == USB_STATE_SUSPENDED || udev->reset_resume) status = usb_resume_device(udev, msg); + /* Resume the interfaces */ if (status == 0 && udev->actconfig) { for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { intf = udev->actconfig->interface[i]; @@ -1413,104 +1264,46 @@ static int usb_resume_both(struct usb_device *udev, pm_message_t msg) return status; } -/** - * usb_external_suspend_device - external suspend of a USB device and its interfaces - * @udev: the usb_device to suspend - * @msg: Power Management message describing this state transition - * - * This routine handles external suspend requests: ones not generated - * internally by a USB driver (autosuspend) but rather coming from the user - * (via sysfs) or the PM core (system sleep). The suspend will be carried - * out regardless of @udev's usage counter or those of its interfaces, - * and regardless of whether or not remote wakeup is enabled. Of course, - * interface drivers still have the option of failing the suspend (if - * there are unsuspended children, for example). - * - * The caller must hold @udev's device lock. - */ -int usb_external_suspend_device(struct usb_device *udev, pm_message_t msg) -{ - int status; - - do_unbind_rebind(udev, DO_UNBIND); - usb_pm_lock(udev); - status = usb_suspend_both(udev, msg); - usb_pm_unlock(udev); - return status; -} - -/** - * usb_external_resume_device - external resume of a USB device and its interfaces - * @udev: the usb_device to resume - * @msg: Power Management message describing this state transition - * - * This routine handles external resume requests: ones not generated - * internally by a USB driver (autoresume) but rather coming from the user - * (via sysfs), the PM core (system resume), or the device itself (remote - * wakeup). @udev's usage counter is unaffected. - * - * The caller must hold @udev's device lock. - */ -int usb_external_resume_device(struct usb_device *udev, pm_message_t msg) -{ - int status; - - usb_pm_lock(udev); - status = usb_resume_both(udev, msg); - udev->last_busy = jiffies; - usb_pm_unlock(udev); - if (status == 0) - do_unbind_rebind(udev, DO_REBIND); - - /* Now that the device is awake, we can start trying to autosuspend - * it again. */ - if (status == 0) - usb_try_autosuspend_device(udev); - return status; -} - +/* The device lock is held by the PM core */ int usb_suspend(struct device *dev, pm_message_t msg) { - struct usb_device *udev; - - udev = to_usb_device(dev); + struct usb_device *udev = to_usb_device(dev); - /* If udev is already suspended, we can skip this suspend and - * we should also skip the upcoming system resume. High-speed - * root hubs are an exception; they need to resume whenever the - * system wakes up in order for USB-PERSIST port handover to work - * properly. - */ - if (udev->state == USB_STATE_SUSPENDED) { - if (udev->parent || udev->speed != USB_SPEED_HIGH) - udev->skip_sys_resume = 1; - return 0; - } - - udev->skip_sys_resume = 0; - return usb_external_suspend_device(udev, msg); + do_unbind_rebind(udev, DO_UNBIND); + udev->do_remote_wakeup = device_may_wakeup(&udev->dev); + return usb_suspend_both(udev, msg); } +/* The device lock is held by the PM core */ int usb_resume(struct device *dev, pm_message_t msg) { - struct usb_device *udev; + struct usb_device *udev = to_usb_device(dev); int status; - udev = to_usb_device(dev); + /* For PM complete calls, all we do is rebind interfaces */ + if (msg.event == PM_EVENT_ON) { + if (udev->state != USB_STATE_NOTATTACHED) + do_unbind_rebind(udev, DO_REBIND); + status = 0; - /* If udev->skip_sys_resume is set then udev was already suspended - * when the system sleep started, so we don't want to resume it - * during this system wakeup. + /* For all other calls, take the device back to full power and + * tell the PM core in case it was autosuspended previously. */ - if (udev->skip_sys_resume) - return 0; - status = usb_external_resume_device(udev, msg); + } else { + sta |