요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
.. _usb-power-management:
Power Management for USB
~~~~~~~~~~~~~~~~~~~~~~~~
:Author: Alan Stern <[email protected]>
:Date: Last-updated: February 2014
..
Contents:
---------
* What is Power Management?
* What is Remote Wakeup?
* When is a USB device idle?
* Forms of dynamic PM
* The user interface for dynamic PM
* Changing the default idle-delay time
* Warnings
* The driver interface for Power Management
* The driver interface for autosuspend and autoresume
* Other parts of the driver interface
* Mutual exclusion
* Interaction between dynamic PM and system PM
* xHCI hardware link PM
* USB Port Power Control
* User Interface for Port Power Control
* Suggested Userspace Port Power Policy
What is Power Management?
-------------------------
Power Management (PM) is the practice of saving energy by suspending
parts of a computer system when they aren't being used. While a
component is ``suspended`` it is in a nonfunctional low-power state; it
might even be turned off completely. A suspended component can be
``resumed`` (returned to a functional full-power state) when the kernel
needs to use it. (There also are forms of PM in which components are
placed in a less functional but still usable state instead of being
suspended; an example would be reducing the CPU's clock rate. This
document will not discuss those other forms.)
When the parts being suspended include the CPU and most of the rest of
the system, we speak of it as a "system suspend". When a particular
device is turned off while the system as a whole remains running, we
call it a "dynamic suspend" (also known as a "runtime suspend" or
"selective suspend"). This document concentrates mostly on how
dynamic PM is implemented in the USB subsystem, although system PM is
covered to some extent (see ``Documentation/power/*.rst`` for more
information about system PM).
System PM support is present only if the kernel was built with
``CONFIG_SUSPEND`` or ``CONFIG_HIBERNATION`` enabled. Dynamic PM support
for USB is present whenever
the kernel was built with ``CONFIG_PM`` enabled.
[Historically, dynamic PM support for USB was present only if the
kernel had been built with ``CONFIG_USB_SUSPEND`` enabled (which depended on
``CONFIG_PM_RUNTIME``). Starting with the 3.10 kernel release, dynamic PM
support for USB was present whenever the kernel was built with
``CONFIG_PM_RUNTIME`` enabled. The ``CONFIG_USB_SUSPEND`` option had been
eliminated.]
What is Remote Wakeup?
----------------------
When a device has been suspended, it generally doesn't resume until
the computer tells it to. Likewise, if the entire computer has been
suspended, it generally doesn't resume until the user tells it to, say
by pressing a power button or opening the cover.
However some devices have the capability of resuming by themselves, or
asking the kernel to resume them, or even telling the entire computer
to resume. This capability goes by several names such as "Wake On
LAN"; we will refer to it generically as "remote wakeup". When a
device is enabled for remote wakeup and it is suspended, it may resume
itself (or send a request to be resumed) in response to some external
event. Examples include a suspended keyboard resuming when a key is
pressed, or a suspended USB hub resuming when a device is plugged in.
When is a USB device idle?
--------------------------
A device is idle whenever the kernel thinks it's not busy doing
anything important and thus is a candidate for being suspended. The
exact definition depends on the device's driver; drivers are allowed
to declare that a device isn't idle even when there's no actual
communication taking place. (For example, a hub isn't considered idle
unless all the devices plugged into that hub are already suspended.)
In addition, a device isn't considered idle so long as a program keeps
its usbfs file open, whether or not any I/O is going on.
If a USB device has no driver, its usbfs file isn't open, and it isn't
being accessed through sysfs, then it definitely is idle.
Forms of dynamic PM
-------------------
Dynamic suspends occur when the kernel decides to suspend an idle
device. This is called ``autosuspend`` for short. In general, a device
won't be autosuspended unless it has been idle for some minimum period
of time, the so-called idle-delay time.
Of course, nothing the kernel does on its own initiative should
prevent the computer or its devices from working properly. If a
device has been autosuspended and a program tries to use it, the
kernel will automatically resume the device (autoresume). For the
same reason, an autosuspended device will usually have remote wakeup
enabled, if the device supports remote wakeup.
It is worth mentioning that many USB drivers don't support
autosuspend. In fact, at the time of this writing (Linux 2.6.23) the
only drivers which do support it are the hub driver, kaweth, asix,
usblp, usblcd, and usb-skeleton (which doesn't count). If a
non-supporting driver is bound to a device, the device won't be
autosuspended. In effect, the kernel pretends the device is never
idle.
We can categorize power management events in two broad classes:
external and internal. External events are those triggered by some
agent outside the USB stack: system suspend/resume (triggered by
userspace), manual dynamic resume (also triggered by userspace), and
remote wakeup (triggered by the device). Internal events are those
triggered within the USB stack: autosuspend and autoresume. Note that
all dynamic suspend events are internal; external agents are not
allowed to issue dynamic suspends.
The user interface for dynamic PM
---------------------------------
The user interface for controlling dynamic PM is located in the ``power/``
subdirectory of each USB device's sysfs directory, that is, in
``/sys/bus/usb/devices/.../power/`` where "..." is the device's ID. The
relevant attribute files are: wakeup, control, and
``autosuspend_delay_ms``. (There may also be a file named ``level``; this
file was deprecated as of the 2.6.35 kernel and replaced by the
``control`` file. In 2.6.38 the ``autosuspend`` file will be deprecated
and replaced by the ``autosuspend_delay_ms`` file. The only difference
is that the newer file expresses the delay in milliseconds whereas the
older file uses seconds. Confusingly, both files are present in 2.6.37
but only ``autosuspend`` works.)
``power/wakeup``
This file is empty if the device does not support
remote wakeup. Otherwise the file contains either the
word ``enabled`` or the word ``disabled``, and you can
write those words to the file. The setting determines
whether or not remote wakeup will be enabled when the
device is next suspended. (If the setting is changed
while the device is suspended, the change won't take
effect until the following suspend.)
``power/control``
This file contains one of two words: ``on`` or ``auto``.
You can write those words to the file to change the
device's setting.
- ``on`` means that the device should be resumed and
autosuspend is not allowed. (Of course, system
suspends are still allowed.)
- ``auto`` is the normal state in which the kernel is
allowed to autosuspend and autoresume the device.
(In kernels up to 2.6.32, you could also specify
``suspend``, meaning that the device should remain
suspended and autoresume was not allowed. This
setting is no longer supported.)
``power/autosuspend_delay_ms``
This file contains an integer value, which is the
number of milliseconds the device should remain idle
before the kernel will autosuspend it (the idle-delay
time). The default is 2000. 0 means to autosuspend
as soon as the device becomes idle, and negative
values mean never to autosuspend. You can write a
number to the file to change the autosuspend
idle-delay time.
Writing ``-1`` to ``power/autosuspend_delay_ms`` and writing ``on`` to
``power/control`` do essentially the same thing -- they both prevent the
device from being autosuspended. Yes, this is a redundancy in the
API.
(In 2.6.21 writing ``0`` to ``power/autosuspend`` would prevent the device
from being autosuspended; the behavior was changed in 2.6.22. The
``power/autosuspend`` attribute did not exist prior to 2.6.21, and the
``power/level`` attribute did not exist prior to 2.6.22. ``power/control``
was added in 2.6.34, and ``power/autosuspend_delay_ms`` was added in
2.6.37 but did not become functional until 2.6.38.)
Changing the default idle-delay time
------------------------------------
The default autosuspend idle-delay time (in seconds) is controlled by
a module parameter in usbcore. You can specify the value when usbcore
is loaded. For example, to set it to 5 seconds instead of 2 you would
do::
modprobe usbcore autosuspend=5
Equivalently, you could add to a configuration file in /etc/modprobe.d
a line saying::
options usbcore autosuspend=5
Some distributions load the usbcore module very early during the boot
process, by means of a program or script running from an initramfs
image. To alter the parameter value you would have to rebuild that
image.
If usbcore is compiled into the kernel rather than built as a loadable
module, you can add::
usbcore.autosuspend=5
to the kernel's boot command line.
Finally, the parameter value can be changed while the system is
running. If you do::
echo 5 >/sys/module/usbcore/parameters/autosuspend
then each new USB device will have its autosuspend idle-delay
initialized to 5. (The idle-delay values for already existing devices
will not be affected.)
Setting the initial default idle-delay to -1 will prevent any
autosuspend of any USB device. This has the benefit of allowing you
then to enable autosuspend for selected devices.
Warnings
--------
The USB specification states that all USB devices must support power
management. Nevertheless, the sad fact is that many devices do not
support it very well. You can suspend them all right, but when you
try to resume them they disconnect themselves from the USB bus or
they stop working entirely. This seems to be especially prevalent
among printers and scanners, but plenty of other types of device have
the same deficiency.
For this reason, by default the kernel disables autosuspend (the
``power/control`` attribute is initialized to ``on``) for all devices other
than hubs. Hubs, at least, appear to be reasonably well-behaved in
this regard.
(In 2.6.21 and 2.6.22 this wasn't the case. Autosuspend was enabled
by default for almost all USB devices. A number of people experienced
problems as a result.)
This means that non-hub devices won't be autosuspended unless the user
or a program explicitly enables it. As of this writing there aren't
any widespread programs which will do this; we hope that in the near
future device managers such as HAL will take on this added
responsibility. In the meantime you can always carry out the
necessary operations by hand or add them to a udev script. You can
also change the idle-delay time; 2 seconds is not the best choice for
every device.
If a driver knows that its device has proper suspend/resume support,
it can enable autosuspend all by itself. For example, the video
driver for a laptop's webcam might do this (in recent kernels they
do), since these devices are rarely used and so should normally be
autosuspended.
Sometimes it turns out that even when a device does work okay with
autosuspend there are still problems. For example, the usbhid driver,
which manages keyboards and mice, has autosuspend support. Tests with
a number of keyboards show that typing on a suspended keyboard, while
causing the keyboard to do a remote wakeup all right, will nonetheless
frequently result in lost keystrokes. Tests with mice show that some
of them will issue a remote-wakeup request in response to button
presses but not to motion, and some in response to neither.
The kernel will not prevent you from enabling autosuspend on devices
that can't handle it. It is even possible in theory to damage a
device by suspending it at the wrong time. (Highly unlikely, but
possible.) Take care.
The driver interface for Power Management
-----------------------------------------
The requirements for a USB driver to support external power management
are pretty modest; the driver need only define::
.suspend
.resume
.reset_resume
methods in its :c:type:`usb_driver` structure, and the ``reset_resume`` method
is optional. The methods' jobs are quite simple:
- The ``suspend`` method is called to warn the driver that the
device is going to be suspended. If the driver returns a
negative error code, the suspend will be aborted. Normally
the driver will return 0, in which case it must cancel all
outstanding URBs (:c:func:`usb_kill_urb`) and not submit any more.
- The ``resume`` method is called to tell the driver that the
device has been resumed and the driver can return to normal
operation. URBs may once more be submitted.
- The ``reset_resume`` method is called to tell the driver that
the device has been resumed and it also has been reset.
The driver should redo any necessary device initialization,
since the device has probably lost most or all of its state
(although the interfaces will be in the same altsettings as
before the suspend).
If the device is disconnected or powered down while it is suspended,
the ``disconnect`` method will be called instead of the ``resume`` or
``reset_resume`` method. This is also quite likely to happen when
waking up from hibernation, as many systems do not maintain suspend
current to the USB host controllers during hibernation. (It's
possible to work around the hibernation-forces-disconnect problem by
using the USB Persist facility.)
The ``reset_resume`` method is used by the USB Persist facility (see
:ref:`usb-persist`) and it can also be used under certain
circumstances when ``CONFIG_USB_PERSIST`` is not enabled. Currently, if a
device is reset during a resume and the driver does not have a
``reset_resume`` method, the driver won't receive any notification about
the resume. Later kernels will call the driver's ``disconnect`` method;
2.6.23 doesn't do this.
USB drivers are bound to interfaces, so their ``suspend`` and ``resume``
methods get called when the interfaces are suspended or resumed. In
principle one might want to suspend some interfaces on a device (i.e.,
force the drivers for those interface to stop all activity) without
suspending the other interfaces. The USB core doesn't allow this; all
interfaces are suspended when the device itself is suspended and all
interfaces are resumed when the device is resumed. It isn't possible
to suspend or resume some but not all of a device's interfaces. The
closest you can come is to unbind the interfaces' drivers.
The driver interface for autosuspend and autoresume
---------------------------------------------------
To support autosuspend and autoresume, a driver should implement all
three of the methods listed above. In addition, a driver indicates
that it supports autosuspend by setting the ``.supports_autosuspend`` flag
in its usb_driver structure. It is then responsible for informing the
USB core whenever one of its interfaces becomes busy or idle. The
driver does so by calling these six functions::
int usb_autopm_get_interface(struct usb_interface *intf);
void usb_autopm_put_interface(struct usb_interface *intf);
int usb_autopm_get_interface_async(struct usb_interface *intf);
void usb_autopm_put_interface_async(struct usb_interface *intf);
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 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.
Drivers must be careful to balance their overall changes to the usage
counter. Unbalanced "get"s will remain in effect when a driver is
unbound from its interface, preventing the device from going into
runtime suspend should the interface be bound to a driver again. On
the other hand, drivers are allowed to achieve this balance by calling
the ``usb_autopm_*`` functions even after their ``disconnect`` routine
has returned -- say from within a work-queue routine -- provided they
retain an active reference to the interface (via ``usb_get_intf`` and
``usb_put_intf``).
Drivers using the async routines are responsible for their own
synchronization and mutual exclusion.
:c:func:`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.
:c:func:`usb_autopm_put_interface` decrements the usage counter and
attempts an autosuspend if the new value is = 0.
:c:func:`usb_autopm_get_interface_async` and
:c:func:`usb_autopm_put_interface_async` do almost the same things as
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 generally not yet be in the desired state.
:c:func:`usb_autopm_get_interface_no_resume` and
:c:func:`usb_autopm_put_interface_no_suspend` merely increment or
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 simplest usage pattern is that a driver calls
:c:func:`usb_autopm_get_interface` in its open routine and
:c:func:`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/control`` 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 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 idle-delay for an autoresume.
Other parts of the driver interface
-----------------------------------
Drivers can enable autosuspend for their devices by calling::
usb_enable_autosuspend(struct usb_device *udev);
in their :c:func:`probe` routine, if they know that the device is capable of
suspending and resuming correctly. This is exactly equivalent to
writing ``auto`` to the device's ``power/control`` attribute. Likewise,
drivers can disable autosuspend by calling::
usb_disable_autosuspend(struct usb_device *udev);
This is exactly the same as writing ``on`` to the ``power/control`` attribute.
Sometimes a driver needs to make sure that remote wakeup is enabled
during autosuspend. For example, there's not much point
autosuspending a keyboard if the user can't cause the keyboard to do a
remote wakeup by typing on it. If the driver sets
``intf->needs_remote_wakeup`` to 1, the kernel won't autosuspend the
device if remote wakeup isn't available. (If the device is already
autosuspended, 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.)
If a driver does its I/O asynchronously in interrupt context, it
should call :c:func:`usb_autopm_get_interface_async` before starting output and
:c:func:`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);
in the event handler. This tells the PM core that the device was just
busy and therefore the next autosuspend idle-delay expiration should
be pushed back. Many of the usb_autopm_* routines also make this call,
so drivers need to worry only when interrupt-driven input arrives.
Asynchronous operation is always subject to races. For example, a
driver may call the :c:func:`usb_autopm_get_interface_async` routine 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 I/O 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 applying
the :c:func:`PMSG_IS_AUTO` macro to the message argument to the ``suspend``
method; it will return True for internal PM events (autosuspend) and
False for external PM events.
Mutual exclusion
----------------
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, the best way is to lock the device and call
:c:func:`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 :c:func:`usb_autopm_get_interface` will prevent any
internal PM calls, even if it fails. (Exercise: Why?)
Interaction between dynamic PM and system PM
--------------------------------------------
Dynamic power management and system power management can interact in
a couple of ways.
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. As of 2.6.37 the
policy is to resume all devices during a system resume and let them
handle their own runtime suspends afterward.
Secondly, a dynamic power-management event may occur as a system
suspend is underway. The window for this is short, since system
suspends don't take long (a few seconds usually), but it can happen.
For example, a suspended device may send a remote-wakeup signal while
the system is suspending. The remote wakeup may succeed, which would
cause the system suspend to abort. If the remote wakeup doesn't
succeed, it may still remain active and thus cause the system to
resume as soon as the system suspend is complete. Or the remote
wakeup may fail and get lost. Which outcome occurs depends on timing
and on the hardware and firmware design.
xHCI hardware link PM
---------------------
xHCI host controller provides hardware link power management to usb2.0
(xHCI 1.0 feature) and usb3.0 devices which support link PM. By
enabling hardware LPM, the host can automatically put the device into
lower power state(L1 for usb2.0 devices, or U1/U2 for usb3.0 devices),
which state device can enter and resume very quickly.
The user interface for controlling hardware LPM is located in the
``power/`` subdirectory of each USB device's sysfs directory, that is, in
``/sys/bus/usb/devices/.../power/`` where "..." is the device's ID. The
relevant attribute files are ``usb2_hardware_lpm`` and ``usb3_hardware_lpm``.
``power/usb2_hardware_lpm``
When a USB2 device which support LPM is plugged to a
xHCI host root hub which support software LPM, the
host will run a software LPM test for it; if the device
enters L1 state and resume successfully and the host
supports USB2 hardware LPM, this file will show up and
driver will enable hardware LPM for the device. You
can write y/Y/1 or n/N/0 to the file to enable/disable
USB2 hardware LPM manually. This is for test purpose mainly.
``power/usb3_hardware_lpm_u1``
``power/usb3_hardware_lpm_u2``
When a USB 3.0 lpm-capable device is plugged in to a
xHCI host which supports link PM, it will check if U1
and U2 exit latencies have been set in the BOS
descriptor; if the check is passed and the host
supports USB3 hardware LPM, USB3 hardware LPM will be
enabled for the device and these files will be created.
The files hold a string value (enable or disable)
indicating whether or not USB3 hardware LPM U1 or U2
is enabled for the device.
USB Port Power Control
----------------------
In addition to suspending endpoint devices and enabling hardware
controlled link power management, the USB subsystem also has the
capability to disable power to ports under some conditions. Power is
controlled through ``Set/ClearPortFeature(PORT_POWER)`` requests to a hub.
In the case of a root or platform-internal hub the host controller
driver translates ``PORT_POWER`` requests into platform firmware (ACPI)
method calls to set the port power state. For more background see the
Linux Plumbers Conference 2012 slides [#f1]_ and video [#f2]_:
Upon receiving a ``ClearPortFeature(PORT_POWER)`` request a USB port is
logically off, and may trigger the actual loss of VBUS to the port [#f3]_.
VBUS may be maintained in the case where a hub gangs multiple ports into
a shared power well causing power to remain until all ports in the gang
are turned off. VBUS may also be maintained by hub ports configured for
a charging application. In any event a logically off port will lose
connection with its device, not respond to hotplug events, and not
respond to remote wakeup events.
.. warning::
turning off a port may result in the inability to hot add a device.
Please see "User Interface for Port Power Control" for details.
As far as the effect on the device itself it is similar to what a device
goes through during system suspend, i.e. the power session is lost. Any
USB device or driver that misbehaves with system suspend will be
similarly affected by a port power cycle event. For this reason the
implementation shares the same device recovery path (and honors the same
quirks) as the system resume path for the hub.
.. [#f1]
http://dl.dropbox.com/u/96820575/sarah-sharp-lpt-port-power-off2-mini.pdf
.. [#f2]
http://linuxplumbers.ubicast.tv/videos/usb-port-power-off-kerneluserspace-api/
.. [#f3]
USB 3.1 Section 10.12
wakeup note: if a device is configured to send wakeup events the port
power control implementation will block poweroff attempts on that
port.
User Interface for Port Power Control
-------------------------------------
The port power control mechanism uses the PM runtime system. Poweroff is
requested by clearing the ``power/pm_qos_no_power_off`` flag of the port device
(defaults to 1). If the port is disconnected it will immediately receive a
``ClearPortFeature(PORT_POWER)`` request. Otherwise, it will honor the pm
runtime rules and require the attached child device and all descendants to be
suspended. This mechanism is dependent on the hub advertising port power
switching in its hub descriptor (wHubCharacteristics logical power switching
mode field).
Note, some interface devices/drivers do not support autosuspend. Userspace may
need to unbind the interface drivers before the :c:type:`usb_device` will
suspend. An unbound interface device is suspended by default. When unbinding,
be careful to unbind interface drivers, not the driver of the parent usb
device. Also, leave hub interface drivers bound. If the driver for the usb
device (not interface) is unbound the kernel is no longer able to resume the
device. If a hub interface driver is unbound, control of its child ports is
lost and all attached child-devices will disconnect. A good rule of thumb is
that if the 'driver/module' link for a device points to
``/sys/module/usbcore`` then unbinding it will interfere with port power
control.
Example of the relevant files for port power control. Note, in this example
these files are relative to a usb hub device (prefix)::
prefix=/sys/devices/pci0000:00/0000:00:14.0/usb3/3-1
attached child device +
hub port device + |
hub interface device + | |
v v v
$prefix/3-1:1.0/3-1-port1/device
$prefix/3-1:1.0/3-1-port1/power/pm_qos_no_power_off
$prefix/3-1:1.0/3-1-port1/device/power/control
$prefix/3-1:1.0/3-1-port1/device/3-1.1:<intf0>/driver/unbind
$prefix/3-1:1.0/3-1-port1/device/3-1.1:<intf1>/driver/unbind
...
$prefix/3-1:1.0/3-1-port1/device/3-1.1:<intfN>/driver/unbind
In addition to these files some ports may have a 'peer' link to a port on
another hub. The expectation is that all superspeed ports have a
hi-speed peer::
$prefix/3-1:1.0/3-1-port1/peer -> ../../../../usb2/2-1/2-1:1.0/2-1-port1
../../../../usb2/2-1/2-1:1.0/2-1-port1/peer -> ../../../../usb3/3-1/3-1:1.0/3-1-port1
Distinct from 'companion ports', or 'ehci/xhci shared switchover ports'
peer ports are simply the hi-speed and superspeed interface pins that
are combined into a single usb3 connector. Peer ports share the same
ancestor XHCI device.
While a superspeed port is powered off a device may downgrade its
connection and attempt to connect to the hi-speed pins. The
implementation takes steps to prevent this:
1. Port suspend is sequenced to guarantee that hi-speed ports are powered-off
before their superspeed peer is permitted to power-off. The implication is
that the setting ``pm_qos_no_power_off`` to zero on a superspeed port may
not cause the port to power-off until its highspeed peer has gone to its
runtime suspend state. Userspace must take care to order the suspensions
if it wants to guarantee that a superspeed port will power-off.
2. Port resume is sequenced to force a superspeed port to power-on prior to its
highspeed peer.
3. Port resume always triggers an attached child device to resume. After a
power session is lost the device may have been removed, or need reset.
Resuming the child device when the parent port regains power resolves those
states and clamps the maximum port power cycle frequency at the rate the
child device can suspend (autosuspend-delay) and resume (reset-resume
latency).
Sysfs files relevant for port power control:
``<hubdev-portX>/power/pm_qos_no_power_off``:
This writable flag controls the state of an idle port.
Once all children and descendants have suspended the
port may suspend/poweroff provided that
pm_qos_no_power_off is '0'. If pm_qos_no_power_off is
'1' the port will remain active/powered regardless of
the stats of descendants. Defaults to 1.
``<hubdev-portX>/power/runtime_status``:
This file reflects whether the port is 'active' (power is on)
or 'suspended' (logically off). There is no indication to
userspace whether VBUS is still supplied.
``<hubdev-portX>/connect_type``:
An advisory read-only flag to userspace indicating the
location and connection type of the port. It returns
one of four values 'hotplug', 'hardwired', 'not used',
and 'unknown'. All values, besides unknown, are set by
platform firmware.
``hotplug`` indicates an externally connectable/visible
port on the platform. Typically userspace would choose
to keep such a port powered to handle new device
connection events.
``hardwired`` refers to a port that is not visible but
connectable. Examples are internal ports for USB
bluetooth that can be disconnected via an external
switch or a port with a hardwired USB camera. It is
expected to be safe to allow these ports to suspend
provided pm_qos_no_power_off is coordinated with any
switch that gates connections. Userspace must arrange
for the device to be connected prior to the port
powering off, or to activate the port prior to enabling
connection via a switch.
``not used`` refers to an internal port that is expected
to never have a device connected to it. These may be
empty internal ports, or ports that are not physically
exposed on a platform. Considered safe to be
powered-off at all times.
``unknown`` means platform firmware does not provide
information for this port. Most commonly refers to
external hub ports which should be considered 'hotplug'
for policy decisions.
.. note::
- since we are relying on the BIOS to get this ACPI
information correct, the USB port descriptions may
be missing or wrong.
- Take care in clearing ``pm_qos_no_power_off``. Once
power is off this port will
not respond to new connect events.
Once a child device is attached additional constraints are
applied before the port is allowed to poweroff.
``<child>/power/control``:
Must be ``auto``, and the port will not
power down until ``<child>/power/runtime_status``
reflects the 'suspended' state. Default
value is controlled by child device driver.
``<child>/power/persist``:
This defaults to ``1`` for most devices and indicates if
kernel can persist the device's configuration across a
power session loss (suspend / port-power event). When
this value is ``0`` (quirky devices), port poweroff is
disabled.
``<child>/driver/unbind``:
Wakeup capable devices will block port poweroff. At
this time the only mechanism to clear the usb-internal
wakeup-capability for an interface device is to unbind
its driver.
Summary of poweroff pre-requisite settings relative to a port device::
echo 0 > power/pm_qos_no_power_off
echo 0 > peer/power/pm_qos_no_power_off # if it exists
echo auto > power/control # this is the default value
echo auto > <child>/power/control
echo 1 > <child>/power/persist # this is the default value
Suggested Userspace Port Power Policy
-------------------------------------
As noted above userspace needs to be careful and deliberate about what
ports are enabled for poweroff.
The default configuration is that all ports start with
``power/pm_qos_no_power_off`` set to ``1`` causing ports to always remain
active.
Given confidence in the platform firmware's description of the ports
(ACPI _PLD record for a port populates 'connect_type') userspace can
clear pm_qos_no_power_off for all 'not used' ports. The same can be
done for 'hardwired' ports provided poweroff is coordinated with any
connection switch for the port.
A more aggressive userspace policy is to enable USB port power off for
all ports (set ``<hubdev-portX>/power/pm_qos_no_power_off`` to ``0``) when
some external factor indicates the user has stopped interacting with the
system. For example, a distro may want to enable power off all USB
ports when the screen blanks, and re-power them when the screen becomes
active. Smart phones and tablets may want to power off USB ports when
the user pushes the power button.
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
USB Power Management 기본 개념
1-65Power Management(PM)는 사용하지 않는 computer component를 suspend해 energy를 절약하는 방식입니다. `suspended` component는 기능하지 않는 low-power state이며 완전히 꺼질 수도 있고, kernel이 필요할 때 `resumed`되어 full-power functional state로 돌아옵니다.
CPU clock을 낮추는 것처럼 기능을 줄이되 계속 사용할 수 있는 PM도 있지만 이 문서는 그런 방식은 다루지 않습니다.
CPU와 system 대부분을 suspend하면 `system suspend`, system은 계속 실행하면서 특정 device만 끄면 `dynamic suspend`, `runtime suspend`, `selective suspend`라고 합니다. 이 문서는 USB dynamic PM을 중심으로 설명하며 system PM의 자세한 내용은 `Documentation/power/*.rst`를 참고합니다.
System PM은 `CONFIG_SUSPEND` 또는 `CONFIG_HIBERNATION`이 enable된 kernel에서 지원됩니다. USB dynamic PM은 `CONFIG_PM`이 enable되면 제공됩니다.
역사적으로 USB dynamic PM은 `CONFIG_PM_RUNTIME`에 의존하는 `CONFIG_USB_SUSPEND`가 있어야 했습니다. Linux 3.10부터는 `CONFIG_PM_RUNTIME`만으로 제공됐고 `CONFIG_USB_SUSPEND` option은 제거되었습니다.
.. _usb-power-management:
Power Management for USB
~~~~~~~~~~~~~~~~~~~~~~~~
:Author: Alan Stern <[email protected]>
:Date: Last-updated: February 2014
..
Contents:
---------
* What is Power Management?
* What is Remote Wakeup?
* When is a USB device idle?
* Forms of dynamic PM
* The user interface for dynamic PM
* Changing the default idle-delay time
* Warnings
* The driver interface for Power Management
* The driver interface for autosuspend and autoresume
* Other parts of the driver interface
* Mutual exclusion
* Interaction between dynamic PM and system PM
* xHCI hardware link PM
* USB Port Power Control
* User Interface for Port Power Control
* Suggested Userspace Port Power Policy
What is Power Management?
-------------------------
Power Management (PM) is the practice of saving energy by suspending
parts of a computer system when they aren't being used. While a
component is ``suspended`` it is in a nonfunctional low-power state; it
might even be turned off completely. A suspended component can be
``resumed`` (returned to a functional full-power state) when the kernel
needs to use it. (There also are forms of PM in which components are
placed in a less functional but still usable state instead of being
suspended; an example would be reducing the CPU's clock rate. This
document will not discuss those other forms.)
When the parts being suspended include the CPU and most of the rest of
the system, we speak of it as a "system suspend". When a particular
device is turned off while the system as a whole remains running, we
call it a "dynamic suspend" (also known as a "runtime suspend" or
"selective suspend"). This document concentrates mostly on how
dynamic PM is implemented in the USB subsystem, although system PM is
covered to some extent (see ``Documentation/power/*.rst`` for more
information about system PM).
System PM support is present only if the kernel was built with
``CONFIG_SUSPEND`` or ``CONFIG_HIBERNATION`` enabled. Dynamic PM support
for USB is present whenever
the kernel was built with ``CONFIG_PM`` enabled.
[Historically, dynamic PM support for USB was present only if the
kernel had been built with ``CONFIG_USB_SUSPEND`` enabled (which depended on
``CONFIG_PM_RUNTIME``). Starting with the 3.10 kernel release, dynamic PM
support for USB was present whenever the kernel was built with
``CONFIG_PM_RUNTIME`` enabled. The ``CONFIG_USB_SUSPEND`` option had been
eliminated.]
Remote wakeup과 idle 판정
66-99Suspend된 device와 computer는 보통 computer 또는 사용자가 resume을 지시할 때까지 깨어나지 않습니다.
일부 device는 외부 event에 반응해 스스로 resume하거나 kernel 또는 전체 computer에 resume을 요청할 수 있습니다. Wake On LAN 등 여러 이름이 있지만 여기서는 일반적으로 `remote wakeup`이라고 부릅니다.
Remote wakeup이 enable된 suspend device는 keyboard key press나 USB hub의 device plug 같은 event에 반응해 resume할 수 있습니다.
Kernel이 중요한 일을 하지 않는다고 판단해 suspend 후보로 삼을 때 device는 idle입니다. 정확한 정의는 driver에 달려 있어 실제 communication이 없어도 busy로 선언할 수 있습니다. 예를 들어 hub는 모든 child device가 이미 suspend되어야 idle입니다.
Program이 usbfs file을 open한 동안은 I/O 여부와 관계없이 idle로 보지 않습니다. Driver가 없고 usbfs file이 열리지 않았으며 sysfs access도 없는 USB device는 확실히 idle입니다.
Device가 suspend 후보가 되고 외부 event로 복귀하는 흐름입니다.
What is Remote Wakeup?
----------------------
When a device has been suspended, it generally doesn't resume until
the computer tells it to. Likewise, if the entire computer has been
suspended, it generally doesn't resume until the user tells it to, say
by pressing a power button or opening the cover.
However some devices have the capability of resuming by themselves, or
asking the kernel to resume them, or even telling the entire computer
to resume. This capability goes by several names such as "Wake On
LAN"; we will refer to it generically as "remote wakeup". When a
device is enabled for remote wakeup and it is suspended, it may resume
itself (or send a request to be resumed) in response to some external
event. Examples include a suspended keyboard resuming when a key is
pressed, or a suspended USB hub resuming when a device is plugged in.
When is a USB device idle?
--------------------------
A device is idle whenever the kernel thinks it's not busy doing
anything important and thus is a candidate for being suspended. The
exact definition depends on the device's driver; drivers are allowed
to declare that a device isn't idle even when there's no actual
communication taking place. (For example, a hub isn't considered idle
unless all the devices plugged into that hub are already suspended.)
In addition, a device isn't considered idle so long as a program keeps
its usbfs file open, whether or not any I/O is going on.
If a USB device has no driver, its usbfs file isn't open, and it isn't
being accessed through sysfs, then it definitely is idle.
Autosuspend와 autoresume event 분류
100-132Kernel이 idle device를 suspend하는 dynamic suspend를 `autosuspend`라고 합니다. 보통 device는 최소 idle-delay time 동안 idle이어야 autosuspend됩니다.
Autosuspend된 device를 program이 사용하려 하면 kernel은 자동으로 device를 resume하는 `autoresume`을 수행합니다. Device가 remote wakeup을 지원하면 autosuspend 중 보통 이를 enable합니다.
많은 USB driver는 autosuspend를 지원하지 않습니다. 지원하지 않는 driver가 bind되면 kernel은 device가 절대 idle이 아닌 것처럼 취급해 autosuspend하지 않습니다.
PM event는 external과 internal로 나뉩니다. External event에는 userspace가 trigger하는 system suspend·resume과 manual dynamic resume, device가 trigger하는 remote wakeup이 있습니다.
Internal event는 USB stack 안에서 trigger되는 autosuspend와 autoresume입니다. 모든 dynamic suspend는 internal이며 external agent가 dynamic suspend를 직접 명령할 수는 없습니다.
Forms of dynamic PM
-------------------
Dynamic suspends occur when the kernel decides to suspend an idle
device. This is called ``autosuspend`` for short. In general, a device
won't be autosuspended unless it has been idle for some minimum period
of time, the so-called idle-delay time.
Of course, nothing the kernel does on its own initiative should
prevent the computer or its devices from working properly. If a
device has been autosuspended and a program tries to use it, the
kernel will automatically resume the device (autoresume). For the
same reason, an autosuspended device will usually have remote wakeup
enabled, if the device supports remote wakeup.
It is worth mentioning that many USB drivers don't support
autosuspend. In fact, at the time of this writing (Linux 2.6.23) the
only drivers which do support it are the hub driver, kaweth, asix,
usblp, usblcd, and usb-skeleton (which doesn't count). If a
non-supporting driver is bound to a device, the device won't be
autosuspended. In effect, the kernel pretends the device is never
idle.
We can categorize power management events in two broad classes:
external and internal. External events are those triggered by some
agent outside the USB stack: system suspend/resume (triggered by
userspace), manual dynamic resume (also triggered by userspace), and
remote wakeup (triggered by the device). Internal events are those
triggered within the USB stack: autosuspend and autoresume. Note that
all dynamic suspend events are internal; external agents are not
allowed to issue dynamic suspends.
Dynamic PM sysfs 사용자 인터페이스
133-200Dynamic PM 제어 file은 각 USB device sysfs directory의 `power/`, 즉 `/sys/bus/usb/devices/.../power/`에 있습니다. 핵심 attribute는 `wakeup`, `control`, `autosuspend_delay_ms`입니다.
`level`은 Linux 2.6.35부터 deprecated되어 `control`로 대체됐습니다. 초 단위 `autosuspend`는 millisecond 단위 `autosuspend_delay_ms`로 대체됐으며 2.6.37에는 둘 다 있었지만 old file만 동작했고 새 file은 2.6.38부터 동작했습니다.
`power/wakeup`은 remote wakeup 미지원 device에서는 비어 있습니다. 지원 device에서는 `enabled` 또는 `disabled`를 읽고 쓸 수 있으며 다음 suspend에서 remote wakeup을 enable할지 결정합니다. Suspend 중 변경하면 그 다음 suspend부터 적용됩니다.
`power/control`의 `on`은 device를 resume 상태로 유지하고 autosuspend를 금지하지만 system suspend는 허용합니다. `auto`는 kernel이 autosuspend·autoresume할 수 있는 정상 상태입니다. 과거의 `suspend` 값은 더 이상 지원되지 않습니다.
`power/autosuspend_delay_ms`는 idle 후 autosuspend까지 기다릴 millisecond 정수입니다. 기본값은 2000, `0`은 idle 즉시 suspend, 음수는 autosuspend 금지입니다.
`autosuspend_delay_ms`에 `-1`을 쓰는 것과 `control`에 `on`을 쓰는 것은 모두 autosuspend를 막으므로 API에 중복이 있습니다. 여러 historical kernel version에서 attribute 존재 여부와 `0` 의미가 달랐습니다.
The user interface for dynamic PM
---------------------------------
The user interface for controlling dynamic PM is located in the ``power/``
subdirectory of each USB device's sysfs directory, that is, in
``/sys/bus/usb/devices/.../power/`` where "..." is the device's ID. The
relevant attribute files are: wakeup, control, and
``autosuspend_delay_ms``. (There may also be a file named ``level``; this
file was deprecated as of the 2.6.35 kernel and replaced by the
``control`` file. In 2.6.38 the ``autosuspend`` file will be deprecated
and replaced by the ``autosuspend_delay_ms`` file. The only difference
is that the newer file expresses the delay in milliseconds whereas the
older file uses seconds. Confusingly, both files are present in 2.6.37
but only ``autosuspend`` works.)
``power/wakeup``
This file is empty if the device does not support
remote wakeup. Otherwise the file contains either the
word ``enabled`` or the word ``disabled``, and you can
write those words to the file. The setting determines
whether or not remote wakeup will be enabled when the
device is next suspended. (If the setting is changed
while the device is suspended, the change won't take
effect until the following suspend.)
``power/control``
This file contains one of two words: ``on`` or ``auto``.
You can write those words to the file to change the
device's setting.
- ``on`` means that the device should be resumed and
autosuspend is not allowed. (Of course, system
suspends are still allowed.)
- ``auto`` is the normal state in which the kernel is
allowed to autosuspend and autoresume the device.
(In kernels up to 2.6.32, you could also specify
``suspend``, meaning that the device should remain
suspended and autoresume was not allowed. This
setting is no longer supported.)
``power/autosuspend_delay_ms``
This file contains an integer value, which is the
number of milliseconds the device should remain idle
before the kernel will autosuspend it (the idle-delay
time). The default is 2000. 0 means to autosuspend
as soon as the device becomes idle, and negative
values mean never to autosuspend. You can write a
number to the file to change the autosuspend
idle-delay time.
Writing ``-1`` to ``power/autosuspend_delay_ms`` and writing ``on`` to
``power/control`` do essentially the same thing -- they both prevent the
device from being autosuspended. Yes, this is a redundancy in the
API.
(In 2.6.21 writing ``0`` to ``power/autosuspend`` would prevent the device
from being autosuspended; the behavior was changed in 2.6.22. The
``power/autosuspend`` attribute did not exist prior to 2.6.21, and the
``power/level`` attribute did not exist prior to 2.6.22. ``power/control``
was added in 2.6.34, and ``power/autosuspend_delay_ms`` was added in
2.6.37 but did not become functional until 2.6.38.)
기본 autosuspend idle-delay 변경
201-241기본 autosuspend idle-delay의 초 단위 값은 usbcore module parameter로 제어합니다. Usbcore load 시 5초로 지정하려면 `modprobe usbcore autosuspend=5`를 사용합니다.
같은 설정을 `/etc/modprobe.d`의 configuration file에 `options usbcore autosuspend=5`로 넣을 수 있습니다. Distribution이 initramfs의 program·script로 usbcore를 매우 일찍 load한다면 parameter 변경 후 image를 rebuild해야 합니다.
Usbcore가 loadable module이 아니라 kernel에 built-in이면 boot command line에 `usbcore.autosuspend=5`를 추가합니다.
실행 중에는 `echo 5 >/sys/module/usbcore/parameters/autosuspend`로 값을 바꿀 수 있습니다. 이후 새 USB device의 idle-delay가 5초로 초기화되지만 기존 device 값은 바뀌지 않습니다.
초기 기본 idle-delay를 `-1`로 두면 모든 USB device의 autosuspend를 막고 필요한 device만 선택적으로 enable할 수 있습니다.
Changing the default idle-delay time
------------------------------------
The default autosuspend idle-delay time (in seconds) is controlled by
a module parameter in usbcore. You can specify the value when usbcore
is loaded. For example, to set it to 5 seconds instead of 2 you would
do::
modprobe usbcore autosuspend=5
Equivalently, you could add to a configuration file in /etc/modprobe.d
a line saying::
options usbcore autosuspend=5
Some distributions load the usbcore module very early during the boot
process, by means of a program or script running from an initramfs
image. To alter the parameter value you would have to rebuild that
image.
If usbcore is compiled into the kernel rather than built as a loadable
module, you can add::
usbcore.autosuspend=5
to the kernel's boot command line.
Finally, the parameter value can be changed while the system is
running. If you do::
echo 5 >/sys/module/usbcore/parameters/autosuspend
then each new USB device will have its autosuspend idle-delay
initialized to 5. (The idle-delay values for already existing devices
will not be affected.)
Setting the initial default idle-delay to -1 will prevent any
autosuspend of any USB device. This has the benefit of allowing you
then to enable autosuspend for selected devices.
Autosuspend 호환성 경고
242-291USB specification은 모든 device가 PM을 지원하도록 요구하지만 실제로는 suspend 뒤 bus에서 스스로 disconnect하거나 완전히 멈추는 device가 많습니다. Printer와 scanner에서 특히 흔하지만 다른 종류도 영향을 받습니다.
이 때문에 kernel은 hub를 제외한 모든 device에서 기본적으로 autosuspend를 disable하며 `power/control`을 `on`으로 초기화합니다. Hub는 비교적 안정적으로 동작합니다.
따라서 non-hub device는 user 또는 program이 명시적으로 enable해야 autosuspend됩니다. Device manager, 수동 sysfs 작업 또는 udev script가 이를 수행할 수 있고 2초 idle-delay가 모든 device에 최적은 아니므로 조정할 수 있습니다.
Driver가 device의 suspend·resume 지원을 확신하면 스스로 autosuspend를 enable할 수 있습니다. 자주 사용하지 않는 laptop webcam이 대표 사례입니다.
기능상 autosuspend가 동작해도 문제는 남을 수 있습니다. `usbhid` keyboard는 remote wakeup 뒤 key가 유실될 수 있고 일부 mouse는 button에는 wakeup하지만 motion에는 반응하지 않거나 둘 다 지원하지 않습니다.
Kernel은 호환되지 않는 device에서 autosuspend를 enable하는 것을 막지 않습니다. 이론적으로 잘못된 시점의 suspend가 device를 손상시킬 수도 있으므로 주의해야 합니다.
Warnings
--------
The USB specification states that all USB devices must support power
management. Nevertheless, the sad fact is that many devices do not
support it very well. You can suspend them all right, but when you
try to resume them they disconnect themselves from the USB bus or
they stop working entirely. This seems to be especially prevalent
among printers and scanners, but plenty of other types of device have
the same deficiency.
For this reason, by default the kernel disables autosuspend (the
``power/control`` attribute is initialized to ``on``) for all devices other
than hubs. Hubs, at least, appear to be reasonably well-behaved in
this regard.
(In 2.6.21 and 2.6.22 this wasn't the case. Autosuspend was enabled
by default for almost all USB devices. A number of people experienced
problems as a result.)
This means that non-hub devices won't be autosuspended unless the user
or a program explicitly enables it. As of this writing there aren't
any widespread programs which will do this; we hope that in the near
future device managers such as HAL will take on this added
responsibility. In the meantime you can always carry out the
necessary operations by hand or add them to a udev script. You can
also change the idle-delay time; 2 seconds is not the best choice for
every device.
If a driver knows that its device has proper suspend/resume support,
it can enable autosuspend all by itself. For example, the video
driver for a laptop's webcam might do this (in recent kernels they
do), since these devices are rarely used and so should normally be
autosuspended.
Sometimes it turns out that even when a device does work okay with
autosuspend there are still problems. For example, the usbhid driver,
which manages keyboards and mice, has autosuspend support. Tests with
a number of keyboards show that typing on a suspended keyboard, while
causing the keyboard to do a remote wakeup all right, will nonetheless
frequently result in lost keystrokes. Tests with mice show that some
of them will issue a remote-wakeup request in response to button
presses but not to motion, and some in response to neither.
The kernel will not prevent you from enabling autosuspend on devices
that can't handle it. It is even possible in theory to damage a
device by suspending it at the wrong time. (Highly unlikely, but
possible.) Take care.
External PM driver callback
292-348USB driver가 external PM을 지원하려면 `usb_driver`에 `.suspend`, `.resume`, 선택적인 `.reset_resume` method를 정의하면 됩니다.
`suspend`는 device가 suspend될 예정임을 알립니다. Negative error를 반환하면 suspend가 중단됩니다. `0`을 반환하면 driver는 `usb_kill_urb()`로 모든 outstanding URB를 cancel하고 새 URB를 submit하지 않아야 합니다.
`resume`은 device가 resume되어 정상 operation과 URB submit을 다시 시작할 수 있음을 알립니다.
`reset_resume`은 resume과 함께 device reset도 일어났음을 알립니다. Interface altsetting은 suspend 전과 같지만 device state 대부분을 잃었을 수 있으므로 필요한 initialization을 다시 해야 합니다.
Suspend 중 device가 disconnect되거나 power down되면 `resume`·`reset_resume` 대신 `disconnect`가 호출됩니다. Hibernation 중 host controller에 suspend current가 유지되지 않는 system에서 흔하며 USB Persist로 우회할 수 있습니다.
`reset_resume`은 USB Persist와 일부 non-`CONFIG_USB_PERSIST` 상황에서 사용됩니다. Resume 중 reset됐는데 method가 없으면 과거 kernel에서는 notification을 받지 못했고 이후 kernel은 `disconnect`를 호출하는 방향으로 바뀌었습니다.
USB driver는 interface에 bind되므로 callback도 interface suspend·resume 때 호출됩니다. USB core는 device의 일부 interface만 suspend하거나 resume하는 것을 허용하지 않으며 전체 interface를 함께 전환합니다. 가장 가까운 대안은 해당 interface driver를 unbind하는 것입니다.
External suspend 요청부터 정상 복귀 또는 disconnect까지의 계약입니다.
The driver interface for Power Management
-----------------------------------------
The requirements for a USB driver to support external power management
are pretty modest; the driver need only define::
.suspend
.resume
.reset_resume
methods in its :c:type:`usb_driver` structure, and the ``reset_resume`` method
is optional. The methods' jobs are quite simple:
- The ``suspend`` method is called to warn the driver that the
device is going to be suspended. If the driver returns a
negative error code, the suspend will be aborted. Normally
the driver will return 0, in which case it must cancel all
outstanding URBs (:c:func:`usb_kill_urb`) and not submit any more.
- The ``resume`` method is called to tell the driver that the
device has been resumed and the driver can return to normal
operation. URBs may once more be submitted.
- The ``reset_resume`` method is called to tell the driver that
the device has been resumed and it also has been reset.
The driver should redo any necessary device initialization,
since the device has probably lost most or all of its state
(although the interfaces will be in the same altsettings as
before the suspend).
If the device is disconnected or powered down while it is suspended,
the ``disconnect`` method will be called instead of the ``resume`` or
``reset_resume`` method. This is also quite likely to happen when
waking up from hibernation, as many systems do not maintain suspend
current to the USB host controllers during hibernation. (It's
possible to work around the hibernation-forces-disconnect problem by
using the USB Persist facility.)
The ``reset_resume`` method is used by the USB Persist facility (see
:ref:`usb-persist`) and it can also be used under certain
circumstances when ``CONFIG_USB_PERSIST`` is not enabled. Currently, if a
device is reset during a resume and the driver does not have a
``reset_resume`` method, the driver won't receive any notification about
the resume. Later kernels will call the driver's ``disconnect`` method;
2.6.23 doesn't do this.
USB drivers are bound to interfaces, so their ``suspend`` and ``resume``
methods get called when the interfaces are suspended or resumed. In
principle one might want to suspend some interfaces on a device (i.e.,
force the drivers for those interface to stop all activity) without
suspending the other interfaces. The USB core doesn't allow this; all
interfaces are suspended when the device itself is suspended and all
interfaces are resumed when the device is resumed. It isn't possible
to suspend or resume some but not all of a device's interfaces. The
closest you can come is to unbind the interfaces' drivers.
Autosuspend·autoresume driver interface
349-424Autosuspend와 autoresume을 지원하려면 앞의 세 callback을 모두 구현하고 `usb_driver`의 `.supports_autosuspend` flag를 설정해야 합니다. Driver는 interface가 busy 또는 idle이 될 때 USB core에 알려야 합니다.
이를 위해 `usb_autopm_get_interface()`, `usb_autopm_put_interface()`, async variant 두 개, `usb_autopm_get_interface_no_resume()`, `usb_autopm_put_interface_no_suspend()`의 여섯 함수를 사용합니다.
함수들은 `usb_interface`에 내장된 device structure의 usage counter를 관리합니다. Counter가 0보다 크면 busy여서 device를 autosuspend하지 않고, 0이면 idle이라 autosuspend할 수 있습니다.
Driver는 usage counter의 전체 증감을 반드시 맞춰야 합니다. Unbalanced get은 unbind 뒤에도 남아 다시 bind될 때 runtime suspend를 막습니다. `usb_get_intf()`·`usb_put_intf()`로 active reference를 유지하면 `disconnect` 반환 뒤 workqueue에서도 balance를 맞출 수 있습니다.
Async routine을 쓰는 driver는 synchronization과 mutual exclusion을 직접 책임집니다.
`usb_autopm_get_interface()`는 counter를 늘리고 suspend 상태면 autoresume하며 실패 시 counter를 되돌립니다. `usb_autopm_put_interface()`는 counter를 줄이고 새 값이 0이면 autosuspend를 시도합니다.
Async variant는 workqueue에서 resume·suspend를 수행하므로 URB completion handler 같은 atomic context에서 호출할 수 있지만 반환 시 device가 아직 원하는 state가 아닐 수 있습니다. No-resume·no-suspend variant는 counter만 변경해 atomic context에서 사용할 수 있습니다.
가장 단순한 pattern은 open에서 get, close·release에서 put을 호출하는 것입니다. Autosuspend 실패는 `power/control=on`, 다른 interface busy, idle-delay 미만 등 정상적인 이유로 흔히 발생하며 idle-delay 때문이면 timer가 만료 시 다시 수행합니다. Autoresume 실패는 device 부재나 고장을 뜻하며 delay가 없습니다.
The driver interface for autosuspend and autoresume
---------------------------------------------------
To support autosuspend and autoresume, a driver should implement all
three of the methods listed above. In addition, a driver indicates
that it supports autosuspend by setting the ``.supports_autosuspend`` flag
in its usb_driver structure. It is then responsible for informing the
USB core whenever one of its interfaces becomes busy or idle. The
driver does so by calling these six functions::
int usb_autopm_get_interface(struct usb_interface *intf);
void usb_autopm_put_interface(struct usb_interface *intf);
int usb_autopm_get_interface_async(struct usb_interface *intf);
void usb_autopm_put_interface_async(struct usb_interface *intf);
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 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.
Drivers must be careful to balance their overall changes to the usage
counter. Unbalanced "get"s will remain in effect when a driver is
unbound from its interface, preventing the device from going into
runtime suspend should the interface be bound to a driver again. On
the other hand, drivers are allowed to achieve this balance by calling
the ``usb_autopm_*`` functions even after their ``disconnect`` routine
has returned -- say from within a work-queue routine -- provided they
retain an active reference to the interface (via ``usb_get_intf`` and
``usb_put_intf``).
Drivers using the async routines are responsible for their own
synchronization and mutual exclusion.
:c:func:`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.
:c:func:`usb_autopm_put_interface` decrements the usage counter and
attempts an autosuspend if the new value is = 0.
:c:func:`usb_autopm_get_interface_async` and
:c:func:`usb_autopm_put_interface_async` do almost the same things as
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 generally not yet be in the desired state.
:c:func:`usb_autopm_get_interface_no_resume` and
:c:func:`usb_autopm_put_interface_no_suspend` merely increment or
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 simplest usage pattern is that a driver calls
:c:func:`usb_autopm_get_interface` in its open routine and
:c:func:`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/control`` 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 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 idle-delay for an autoresume.
Driver autosuspend 도구와 race 처리
425-479Driver가 device의 suspend·resume을 신뢰하면 `probe()`에서 `usb_enable_autosuspend(struct usb_device *udev)`를 호출할 수 있으며 `power/control`에 `auto`를 쓰는 것과 같습니다. `usb_disable_autosuspend()`는 `on`을 쓰는 것과 같습니다.
Autosuspend 중 remote wakeup이 반드시 필요하면 `intf->needs_remote_wakeup=1`을 설정합니다. Remote wakeup을 사용할 수 없으면 kernel은 device를 autosuspend하지 않습니다. 이미 suspend된 뒤 flag를 설정해도 autoresume은 일어나지 않으므로 보통 `probe`에서 설정합니다.
Interrupt context에서 비동기 I/O를 수행하는 driver는 output 시작 전 `usb_autopm_get_interface_async()`, queue가 비면 `usb_autopm_put_interface_async()`를 호출합니다. Input event handler는 `usb_mark_last_busy()`로 최근 busy 시간을 갱신해 다음 idle-delay 만료를 뒤로 미룹니다.
Async operation에는 race가 있습니다. Core가 idle-delay 충족을 결정했지만 아직 `suspend` callback을 부르기 전 driver가 async get을 요청할 수 있습니다. `suspend`는 I/O request routine과 URB completion handler를 synchronize하고 device 사용이 필요하면 autosuspend에 `-EBUSY`를 반환해야 합니다.
External suspend는 이런 이유로 실패하면 안 되고 autosuspend만 `-EBUSY`를 허용합니다. `suspend` message에 `PMSG_IS_AUTO`를 적용하면 internal autosuspend는 True, external PM event는 False입니다.
Driver가 busy 상태를 알리고 suspend callback이 race를 정리하는 흐름입니다.
Other parts of the driver interface
-----------------------------------
Drivers can enable autosuspend for their devices by calling::
usb_enable_autosuspend(struct usb_device *udev);
in their :c:func:`probe` routine, if they know that the device is capable of
suspending and resuming correctly. This is exactly equivalent to
writing ``auto`` to the device's ``power/control`` attribute. Likewise,
drivers can disable autosuspend by calling::
usb_disable_autosuspend(struct usb_device *udev);
This is exactly the same as writing ``on`` to the ``power/control`` attribute.
Sometimes a driver needs to make sure that remote wakeup is enabled
during autosuspend. For example, there's not much point
autosuspending a keyboard if the user can't cause the keyboard to do a
remote wakeup by typing on it. If the driver sets
``intf->needs_remote_wakeup`` to 1, the kernel won't autosuspend the
device if remote wakeup isn't available. (If the device is already
autosuspended, 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.)
If a driver does its I/O asynchronously in interrupt context, it
should call :c:func:`usb_autopm_get_interface_async` before starting output and
:c:func:`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);
in the event handler. This tells the PM core that the device was just
busy and therefore the next autosuspend idle-delay expiration should
be pushed back. Many of the usb_autopm_* routines also make this call,
so drivers need to worry only when interrupt-driven input arrives.
Asynchronous operation is always subject to races. For example, a
driver may call the :c:func:`usb_autopm_get_interface_async` routine 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 I/O 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 applying
the :c:func:`PMSG_IS_AUTO` macro to the message argument to the ``suspend``
method; it will return True for internal PM events (autosuspend) and
False for external PM events.
Mutual exclusion과 system PM 상호작용
480-523External event에서 `suspend`·`resume` method를 호출할 때 device semaphore `udev->dev.sem`을 보유하지만 autosuspend·autoresume에서는 반드시 그렇지는 않습니다. External PM은 `probe`, `disconnect`, `pre_reset`, `post_reset`과 상호 배제되며 USB core는 internal PM에도 같은 보장을 제공합니다.
Critical section 동안 모든 suspend·resume을 막으려면 device를 lock하고 `usb_autopm_get_interface()`를 호출한 뒤 종료 시 역순으로 해제합니다. Device semaphore가 external PM을 막고 get이 실패하더라도 internal PM을 막습니다.
System suspend 시 device가 이미 autosuspend됐을 수 있습니다. 투명성을 위해 system resume 뒤에도 suspend 상태를 유지하는 것이 이상적이지만 kernel policy는 바뀌어 왔고 Linux 2.6.37부터는 system resume 때 모든 device를 resume한 뒤 각자 runtime suspend를 다시 처리하게 합니다.
System suspend 진행 중에도 dynamic PM event가 생길 수 있습니다. Suspend device의 remote-wakeup signal이 성공하면 system suspend가 abort되고, 완전히 성공하지 않아도 signal이 남아 suspend 직후 resume할 수 있으며, 실패해 유실될 수도 있습니다. 결과는 timing과 hardware·firmware design에 달렸습니다.
Mutual exclusion
----------------
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, the best way is to lock the device and call
:c:func:`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 :c:func:`usb_autopm_get_interface` will prevent any
internal PM calls, even if it fails. (Exercise: Why?)
Interaction between dynamic PM and system PM
--------------------------------------------
Dynamic power management and system power management can interact in
a couple of ways.
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. As of 2.6.37 the
policy is to resume all devices during a system resume and let them
handle their own runtime suspends afterward.
Secondly, a dynamic power-management event may occur as a system
suspend is underway. The window for this is short, since system
suspends don't take long (a few seconds usually), but it can happen.
For example, a suspended device may send a remote-wakeup signal while
the system is suspending. The remote wakeup may succeed, which would
cause the system suspend to abort. If the remote wakeup doesn't
succeed, it may still remain active and thus cause the system to
resume as soon as the system suspend is complete. Or the remote
wakeup may fail and get lost. Which outcome occurs depends on timing
and on the hardware and firmware design.
xHCI hardware LPM과 USB port power
524-611xHCI host controller는 link PM을 지원하는 USB 2.0과 USB 3.0 device에 hardware link power management를 제공합니다. Host는 device를 USB 2.0의 L1 또는 USB 3.0의 U1·U2로 자동 전환하며 빠르게 진입·resume할 수 있습니다.
Sysfs의 `power/usb2_hardware_lpm`은 USB 2.0 LPM-capable device가 software LPM test에서 L1 진입·resume에 성공하고 host가 hardware LPM을 지원할 때 나타납니다. `y/Y/1` 또는 `n/N/0`으로 수동 enable·disable하며 주로 test용입니다.
USB 3.0의 `power/usb3_hardware_lpm_u1`과 `power/usb3_hardware_lpm_u2`는 BOS descriptor에 U1·U2 exit latency가 설정되고 host가 link PM을 지원할 때 생성됩니다. 값 `enable`·`disable`이 각 state 사용 여부를 나타냅니다.
USB subsystem은 endpoint suspend와 link PM 외에도 일부 조건에서 port power를 끌 수 있습니다. Hub에 `Set/ClearPortFeature(PORT_POWER)` request를 보내며 root·platform-internal hub에서는 HCD가 이를 ACPI method call로 변환합니다.
`ClearPortFeature(PORT_POWER)`를 받으면 port는 논리적으로 off되고 VBUS가 실제로 사라질 수 있습니다. Shared power well이나 charging port에서는 VBUS가 남을 수 있지만 논리적으로 off된 port는 device connection, hotplug, remote wakeup event에 응답하지 않습니다.
Port poweroff는 hot-add 불능을 초래할 수 있습니다. Device 관점에서는 system suspend처럼 power session을 잃으며, hub system-resume과 같은 recovery path와 quirk를 사용합니다.
배경 자료는 Linux Plumbers Conference 2012 slide `http://dl.dropbox.com/u/96820575/sarah-sharp-lpt-port-power-off2-mini.pdf`, video `http://linuxplumbers.ubicast.tv/videos/usb-port-power-off-kerneluserspace-api/`, USB 3.1 section 10.12입니다. Wakeup event가 설정된 device가 있으면 port poweroff를 차단합니다.
xHCI hardware link PM
---------------------
xHCI host controller provides hardware link power management to usb2.0
(xHCI 1.0 feature) and usb3.0 devices which support link PM. By
enabling hardware LPM, the host can automatically put the device into
lower power state(L1 for usb2.0 devices, or U1/U2 for usb3.0 devices),
which state device can enter and resume very quickly.
The user interface for controlling hardware LPM is located in the
``power/`` subdirectory of each USB device's sysfs directory, that is, in
``/sys/bus/usb/devices/.../power/`` where "..." is the device's ID. The
relevant attribute files are ``usb2_hardware_lpm`` and ``usb3_hardware_lpm``.
``power/usb2_hardware_lpm``
When a USB2 device which support LPM is plugged to a
xHCI host root hub which support software LPM, the
host will run a software LPM test for it; if the device
enters L1 state and resume successfully and the host
supports USB2 hardware LPM, this file will show up and
driver will enable hardware LPM for the device. You
can write y/Y/1 or n/N/0 to the file to enable/disable
USB2 hardware LPM manually. This is for test purpose mainly.
``power/usb3_hardware_lpm_u1``
``power/usb3_hardware_lpm_u2``
When a USB 3.0 lpm-capable device is plugged in to a
xHCI host which supports link PM, it will check if U1
and U2 exit latencies have been set in the BOS
descriptor; if the check is passed and the host
supports USB3 hardware LPM, USB3 hardware LPM will be
enabled for the device and these files will be created.
The files hold a string value (enable or disable)
indicating whether or not USB3 hardware LPM U1 or U2
is enabled for the device.
USB Port Power Control
----------------------
In addition to suspending endpoint devices and enabling hardware
controlled link power management, the USB subsystem also has the
capability to disable power to ports under some conditions. Power is
controlled through ``Set/ClearPortFeature(PORT_POWER)`` requests to a hub.
In the case of a root or platform-internal hub the host controller
driver translates ``PORT_POWER`` requests into platform firmware (ACPI)
method calls to set the port power state. For more background see the
Linux Plumbers Conference 2012 slides [#f1]_ and video [#f2]_:
Upon receiving a ``ClearPortFeature(PORT_POWER)`` request a USB port is
logically off, and may trigger the actual loss of VBUS to the port [#f3]_.
VBUS may be maintained in the case where a hub gangs multiple ports into
a shared power well causing power to remain until all ports in the gang
are turned off. VBUS may also be maintained by hub ports configured for
a charging application. In any event a logically off port will lose
connection with its device, not respond to hotplug events, and not
respond to remote wakeup events.
.. warning::
turning off a port may result in the inability to hot add a device.
Please see "User Interface for Port Power Control" for details.
As far as the effect on the device itself it is similar to what a device
goes through during system suspend, i.e. the power session is lost. Any
USB device or driver that misbehaves with system suspend will be
similarly affected by a port power cycle event. For this reason the
implementation shares the same device recovery path (and honors the same
quirks) as the system resume path for the hub.
.. [#f1]
http://dl.dropbox.com/u/96820575/sarah-sharp-lpt-port-power-off2-mini.pdf
.. [#f2]
http://linuxplumbers.ubicast.tv/videos/usb-port-power-off-kerneluserspace-api/
.. [#f3]
USB 3.1 Section 10.12
wakeup note: if a device is configured to send wakeup events the port
power control implementation will block poweroff attempts on that
port.
Port power control 사용자 인터페이스와 순서
612-686Port power control은 PM runtime system을 사용합니다. Port device의 `power/pm_qos_no_power_off`를 기본값 `1`에서 clear해 poweroff를 요청합니다. Port가 disconnected면 즉시 `ClearPortFeature(PORT_POWER)`를 받고, 연결됐으면 child와 모든 descendant가 suspend되어야 한다는 runtime PM 규칙을 따릅니다. Hub descriptor의 `wHubCharacteristics`가 port power switching을 광고해야 합니다.
Autosuspend 미지원 interface driver는 `usb_device` suspend 전에 userspace가 unbind해야 할 수 있습니다. Unbound interface는 기본 suspend 상태입니다.
Parent USB device driver를 unbind하면 kernel이 device를 resume할 수 없고, hub interface driver를 unbind하면 child port control이 사라져 모든 child device가 disconnect됩니다. `driver/module` link가 `/sys/module/usbcore`를 가리키는 device는 unbind 시 port power control을 방해한다고 보는 것이 좋습니다.
예시 경로는 hub interface device, hub port device, attached child device의 계층과 `pm_qos_no_power_off`, child `power/control`, 각 interface `driver/unbind` file을 보여 줍니다.
일부 SuperSpeed port에는 다른 hub의 high-speed port를 가리키는 `peer` link가 있습니다. Peer port는 companion·shared switchover port와 달리 하나의 USB3 connector에 결합된 high-speed·SuperSpeed pin이며 같은 xHCI ancestor를 공유합니다.
SuperSpeed port가 off일 때 device가 high-speed pin으로 downgrade 연결하는 것을 막기 위해 suspend는 high-speed peer를 먼저 poweroff하고 그 뒤 SuperSpeed를 끕니다. Resume은 SuperSpeed를 먼저 켜고 high-speed peer를 나중에 켭니다.
Port resume은 attached child도 항상 resume합니다. Power session 손실 뒤 device 제거·reset 필요 상태를 해결하고 power-cycle frequency를 child의 autosuspend delay와 reset-resume latency 이하로 제한합니다.
한 connector의 high-speed·SuperSpeed peer를 안전하게 전환하는 순서입니다.
User Interface for Port Power Control
-------------------------------------
The port power control mechanism uses the PM runtime system. Poweroff is
requested by clearing the ``power/pm_qos_no_power_off`` flag of the port device
(defaults to 1). If the port is disconnected it will immediately receive a
``ClearPortFeature(PORT_POWER)`` request. Otherwise, it will honor the pm
runtime rules and require the attached child device and all descendants to be
suspended. This mechanism is dependent on the hub advertising port power
switching in its hub descriptor (wHubCharacteristics logical power switching
mode field).
Note, some interface devices/drivers do not support autosuspend. Userspace may
need to unbind the interface drivers before the :c:type:`usb_device` will
suspend. An unbound interface device is suspended by default. When unbinding,
be careful to unbind interface drivers, not the driver of the parent usb
device. Also, leave hub interface drivers bound. If the driver for the usb
device (not interface) is unbound the kernel is no longer able to resume the
device. If a hub interface driver is unbound, control of its child ports is
lost and all attached child-devices will disconnect. A good rule of thumb is
that if the 'driver/module' link for a device points to
``/sys/module/usbcore`` then unbinding it will interfere with port power
control.
Example of the relevant files for port power control. Note, in this example
these files are relative to a usb hub device (prefix)::
prefix=/sys/devices/pci0000:00/0000:00:14.0/usb3/3-1
attached child device +
hub port device + |
hub interface device + | |
v v v
$prefix/3-1:1.0/3-1-port1/device
$prefix/3-1:1.0/3-1-port1/power/pm_qos_no_power_off
$prefix/3-1:1.0/3-1-port1/device/power/control
$prefix/3-1:1.0/3-1-port1/device/3-1.1:<intf0>/driver/unbind
$prefix/3-1:1.0/3-1-port1/device/3-1.1:<intf1>/driver/unbind
...
$prefix/3-1:1.0/3-1-port1/device/3-1.1:<intfN>/driver/unbind
In addition to these files some ports may have a 'peer' link to a port on
another hub. The expectation is that all superspeed ports have a
hi-speed peer::
$prefix/3-1:1.0/3-1-port1/peer -> ../../../../usb2/2-1/2-1:1.0/2-1-port1
../../../../usb2/2-1/2-1:1.0/2-1-port1/peer -> ../../../../usb3/3-1/3-1:1.0/3-1-port1
Distinct from 'companion ports', or 'ehci/xhci shared switchover ports'
peer ports are simply the hi-speed and superspeed interface pins that
are combined into a single usb3 connector. Peer ports share the same
ancestor XHCI device.
While a superspeed port is powered off a device may downgrade its
connection and attempt to connect to the hi-speed pins. The
implementation takes steps to prevent this:
1. Port suspend is sequenced to guarantee that hi-speed ports are powered-off
before their superspeed peer is permitted to power-off. The implication is
that the setting ``pm_qos_no_power_off`` to zero on a superspeed port may
not cause the port to power-off until its highspeed peer has gone to its
runtime suspend state. Userspace must take care to order the suspensions
if it wants to guarantee that a superspeed port will power-off.
2. Port resume is sequenced to force a superspeed port to power-on prior to its
highspeed peer.
3. Port resume always triggers an attached child device to resume. After a
power session is lost the device may have been removed, or need reset.
Resuming the child device when the parent port regains power resolves those
states and clamps the maximum port power cycle frequency at the rate the
child device can suspend (autosuspend-delay) and resume (reset-resume
latency).
Port power sysfs와 poweroff 선행 조건
687-775`<hubdev-portX>/power/pm_qos_no_power_off`는 idle port 상태를 제어합니다. 모든 child와 descendant가 suspend된 뒤 값이 `0`이면 port가 suspend·poweroff될 수 있고 `1`이면 descendant 상태와 무관하게 active·powered를 유지합니다. 기본값은 `1`입니다.
`<hubdev-portX>/power/runtime_status`는 port가 power-on인 `active`인지 논리적으로 off인 `suspended`인지 보여 주지만 VBUS가 실제로 공급되는지는 알려 주지 않습니다.
Read-only `connect_type`은 `hotplug`, `hardwired`, `not used`, `unknown` 중 하나를 반환합니다. `hotplug`는 외부 연결 port라 보통 power 유지가 적절합니다. `hardwired`는 내부 Bluetooth·camera 등 보이지 않지만 연결 가능한 port라 switch와 조정하면 suspend할 수 있습니다.
`not used`는 device가 연결되지 않을 내부·비노출 port라 항상 poweroff해도 안전합니다. `unknown`은 firmware 정보가 없음을 뜻하며 external hub port가 흔하므로 policy에서는 `hotplug`로 취급해야 합니다. BIOS ACPI 설명이 누락되거나 잘못될 수 있고 poweroff 뒤 새 connect event에 응답하지 않는 점을 주의해야 합니다.
Child가 연결되면 `<child>/power/control`이 `auto`여야 하고 child `runtime_status`가 `suspended`가 될 때까지 port는 꺼지지 않습니다.
`<child>/power/persist`는 대부분 기본 `1`이며 power-session loss를 지나 configuration을 유지할 수 있음을 뜻합니다. Quirky device에서 `0`이면 port poweroff를 disable합니다.
Wakeup-capable device도 port poweroff를 막습니다. 현재 interface의 USB-internal wakeup capability를 clear하는 방법은 driver unbind뿐입니다.
Poweroff 선행 설정은 port와 peer의 `pm_qos_no_power_off=0`, port·child `power/control=auto`, child `power/persist=1`입니다.
Sysfs files relevant for port power control:
``<hubdev-portX>/power/pm_qos_no_power_off``:
This writable flag controls the state of an idle port.
Once all children and descendants have suspended the
port may suspend/poweroff provided that
pm_qos_no_power_off is '0'. If pm_qos_no_power_off is
'1' the port will remain active/powered regardless of
the stats of descendants. Defaults to 1.
``<hubdev-portX>/power/runtime_status``:
This file reflects whether the port is 'active' (power is on)
or 'suspended' (logically off). There is no indication to
userspace whether VBUS is still supplied.
``<hubdev-portX>/connect_type``:
An advisory read-only flag to userspace indicating the
location and connection type of the port. It returns
one of four values 'hotplug', 'hardwired', 'not used',
and 'unknown'. All values, besides unknown, are set by
platform firmware.
``hotplug`` indicates an externally connectable/visible
port on the platform. Typically userspace would choose
to keep such a port powered to handle new device
connection events.
``hardwired`` refers to a port that is not visible but
connectable. Examples are internal ports for USB
bluetooth that can be disconnected via an external
switch or a port with a hardwired USB camera. It is
expected to be safe to allow these ports to suspend
provided pm_qos_no_power_off is coordinated with any
switch that gates connections. Userspace must arrange
for the device to be connected prior to the port
powering off, or to activate the port prior to enabling
connection via a switch.
``not used`` refers to an internal port that is expected
to never have a device connected to it. These may be
empty internal ports, or ports that are not physically
exposed on a platform. Considered safe to be
powered-off at all times.
``unknown`` means platform firmware does not provide
information for this port. Most commonly refers to
external hub ports which should be considered 'hotplug'
for policy decisions.
.. note::
- since we are relying on the BIOS to get this ACPI
information correct, the USB port descriptions may
be missing or wrong.
- Take care in clearing ``pm_qos_no_power_off``. Once
power is off this port will
not respond to new connect events.
Once a child device is attached additional constraints are
applied before the port is allowed to poweroff.
``<child>/power/control``:
Must be ``auto``, and the port will not
power down until ``<child>/power/runtime_status``
reflects the 'suspended' state. Default
value is controlled by child device driver.
``<child>/power/persist``:
This defaults to ``1`` for most devices and indicates if
kernel can persist the device's configuration across a
power session loss (suspend / port-power event). When
this value is ``0`` (quirky devices), port poweroff is
disabled.
``<child>/driver/unbind``:
Wakeup capable devices will block port poweroff. At
this time the only mechanism to clear the usb-internal
wakeup-capability for an interface device is to unbind
its driver.
Summary of poweroff pre-requisite settings relative to a port device::
echo 0 > power/pm_qos_no_power_off
echo 0 > peer/power/pm_qos_no_power_off # if it exists
echo auto > power/control # this is the default value
echo auto > <child>/power/control
echo 1 > <child>/power/persist # this is the default value
권장 userspace port power 정책
776-798Userspace는 어떤 port에 poweroff를 enable할지 신중하고 명시적으로 결정해야 합니다.
기본 configuration에서는 모든 port의 `power/pm_qos_no_power_off`가 `1`이어서 항상 active 상태를 유지합니다.
Platform firmware의 ACPI `_PLD` port 설명과 `connect_type`을 신뢰할 수 있다면 userspace는 모든 `not used` port에서 flag를 clear할 수 있습니다. `hardwired` port도 connection switch와 poweroff를 조정할 수 있으면 같은 정책을 적용할 수 있습니다.
더 공격적인 policy는 user가 system과 상호작용하지 않는다는 외부 신호가 있을 때 모든 port의 `<hubdev-portX>/power/pm_qos_no_power_off`를 `0`으로 설정하는 것입니다.
Distribution은 screen blank 때 모든 USB port를 끄고 screen이 active가 되면 다시 켤 수 있습니다. Smartphone과 tablet은 power button을 누를 때 USB port를 끌 수 있습니다.
Suggested Userspace Port Power Policy
-------------------------------------
As noted above userspace needs to be careful and deliberate about what
ports are enabled for poweroff.
The default configuration is that all ports start with
``power/pm_qos_no_power_off`` set to ``1`` causing ports to always remain
active.
Given confidence in the platform firmware's description of the ports
(ACPI _PLD record for a port populates 'connect_type') userspace can
clear pm_qos_no_power_off for all 'not used' ports. The same can be
done for 'hardwired' ports provided poweroff is coordinated with any
connection switch for the port.
A more aggressive userspace policy is to enable USB port power off for
all ports (set ``<hubdev-portX>/power/pm_qos_no_power_off`` to ``0``) when
some external factor indicates the user has stopped interacting with the
system. For example, a distro may want to enable power off all USB
ports when the screen blanks, and re-power them when the screen becomes
active. Smart phones and tablets may want to power off USB ports when
the user pushes the power button.
요약·해설
power-management.rst:1-798USB PM은 device usage counter와 idle-delay로 runtime suspend를 결정하고 callback·remote wakeup으로 복귀를 조정합니다. xHCI link state와 hub port power는 별도 sysfs policy와 peer sequencing, child persistence 조건을 함께 만족해야 합니다.