summaryrefslogtreecommitdiffstats
path: root/Documentation/usb/power-management.txt
diff options
context:
space:
mode:
Diffstat (limited to 'Documentation/usb/power-management.txt')
-rw-r--r--Documentation/usb/power-management.txt217
1 files changed, 77 insertions, 140 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