usb 休眠唤醒包括两种:
1. system suspend/resume 系统休眠唤醒
如果不支持usb remote wakeup, 则usb控制器, phy都可以进入休眠状态。 关闭相关clock时钟, 甚至断电。
如果需要支持usb remote wakeup, 则不能完全断电, 需要留下部分底电流, 当usb外设发出request wakeup请求后, 能通过
usbphy->usb controller->cpu 将整体系统唤醒。 (常见如个人电脑产品, 基本都支持usb鼠标键盘唤醒)
2. dynamic suspend/resume 动态休眠唤醒, 也叫runtime suspend/resume 或者 selective suspend/resume
即运行时休眠唤醒和选择性休眠唤醒。
此种休眠唤醒和系统其它IP, cpu 核心就没有关系了。
仅和usb 控制器 、phy 及外接设备有关
相关文档可以参考Documents/driver-api/usb/power-management.rst
3. runtime suspend/resume 系统文件
sysfs文件系统中有关于runtime suspend/resume 控制的一些文件, 位置如下:
/sys/bus/usb/devices/.../power/'' 其中, ...为设备id
文件:
- power/wakeup -- enable/disabled, 代表是否支持remote wakeup功能, 即系统唤醒功能。常见如鼠标, 键盘等HID设备都是支持的。
- power/control -- on/auto, on代表auto suspend/resume是不允许的, 即一直是active状态; auto代表该设备支持auto suspend/resume。 常见如hub, 鼠标, 键盘等都支持auto suspend/resume, 而我手头的U盘等设备并支持。
- power/autosuspend_delay_ms -- 默认值是2000, 代表设备在idle状态(总线无数据读写)下2000毫秒后即进入auto suspend状态。0代表 auto suspend as soon as the device becomes idle. 即尽快进入休眠状态。
* echo -1 > power/auto_suspend_delay_ms和 echo "on" > power/control 是同样的作用, 即防止设备进入auto suspend状态。
4. usb控制器中关于休眠唤醒的寄存器
查看intel xhci-1.2协议文档。
主要是0x420和0x430寄存器, PORTSC (Port Status and Control Register)
bit[5:8], 读取的值 0 - U0, 1 - U1, 2 - U2, 3 - U3, 4 - Disabled, 5 - RxDetect, 6 - Inactive, - Polling, 8 - Recovery, 9 - Hot Reset,
10 - Compliance Mode, 11 - Test Mode, 12 - 14 Reserved, 15 - Resume State
5. 如何修改idle_delay 默认值, 即总线空闲多久进入suspend的默认时间
usbcore内核模块参数可以控制。
modprobe usbcore autosuspend=5
这样总线需要空闲5秒后才进入auto suspend状态
等价的, 也可以在/etc/modprobe.d中添加
options usbcore autosuspend=5 添加内核参数
如果是buildin的usbcore模块, 则添加
usbcore.autosuspend=5
最后, 也可以开机后直接操作sysfs文件系统,
echo 5 > /sys/module/usbcore/parameters/autosuspend 即可
6. Warnings
根据USB协议, 所有的USB设备需要支持电源管理, 但是悲伤的事实是, 很多usb设备对于电源管理的支持都不怎么好...
比如很多设备休眠后就无法唤醒, 或需要重新初始化等。
所以Linux内核代码对所有usb设备, 默认都将power/control属性初始化为"On"。 其中除了usb hub设备。
至少hub设备看起来都能比较好的支持auto suspend/resume。
所以对于非hub的usb设备, 需要手动echo auto > power/control后, 才能支持auto suspend/resume
试验了下 手头的惠普鼠标修改power/control后, 可以顺利进入auto susepnd状态。
但金士顿, 联想, 兰科芯U盘都不行... (主控有慧荣SMI3267AE, 群联PS2251-09等) 其中金士顿DataTraverler 主控未知, ChipGenius_v4_19_0319版本无法识别...
另外Orico的usb hub 也无法进入suspend状态。
以上行为都是开发板中的行为 (USB控制器synopsys dwc3)
后续对比PC产品以判断是开发板问题还是usb外设问题。
7. 编程相关
:c:type:usb_driver 结构体, 三个方法, 其中reset_resume可选。
.suspend -- to warn the driver that the device is going to be suspended. 通常返回成功0, 需要取消所有的outstanding URBs
(:c:func: usb_kill_urb), 并且不提交其他任何usb请求块。
.resume -- to tell the driver that the device has been resumed and the driver can return to normal operation.
.reset_resume -- 可选, to tell the driver that the device ahs been resumed and it also has been reset. 需要重新初始化。
If the device is disconnected or power down while it is suspended, the 'disconnect' method will be called instead of the 'resume' or 'reset_resume' method.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
除了以上suspend/resume等接口, :c:type:usb_driver结构体中还有个.supports_autosuspend标志。
以及以下6个接口:
› 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);
内部有个usage_counter, >0 说明总线busy, =0说明总线idle。具体使用中再熟悉吧...
其他函数:
usb_enable_autosuspend
usb_disable_autosuspend
usb_mark_last_busy
等等, 其实就是操作sysfs的一些文件节点的实际函数动作。
8. 动态电源管理和系统电源管理之间的联系 (Interaction between dynamic PM and system PM)
1). 当系统休眠时, 可能设备早就auto suspend了... 所以对于该外设就继续保持休眠就可以了, 但唤醒的动作需要定义, 是否要去唤醒该auto suspend设备?? 2.6.37内核定义的策略是在系统唤醒时, 唤醒所有休眠 的设备。 让设备自己去触发auto suspend。
2). 在系统休眠的过程中, 外设的auto suspend也发生了... 这也是有可能发生的, 因为系统休眠通常需要几秒钟的时间, 在该段时间内总线进idle, 发生了auto suspend当然是合理的...
同样, 一个remote wakeup事件也可能发生在系统休眠过程中... it can happen...
不管怎样, 系统休眠和动态休眠都是独立发生的, 可能会互相影响, 具体问题具体分析...
9. xHCI hardware link PM
hardware link power management.
L1 - usb2.0 devices
U1/U2 usb3.0 devices
关于Link, 即链接, LPM即链接电管管理, (链路层电源管理)
可参考
https://docs.microsoft.com/zh-cn/windows-hardware/drivers/usbcon/link-power-management-in-usb-3-0-hardware
https://docs.microsoft.com/zh-cn/windows-hardware/drivers/usbcon/usb-3-0-lpm-mechanism-
https://docs.microsoft.com/zh-tw/windows-hardware/drivers/usbcon/usb-3-0-lpm-mechanism-
What is a link
A USB connection exists between two USB ports:
The downstream port (DS port) of a host or a hub.
The upstream port (US port) of an attached device or hub.
A link is a pair of DS and US ports; the ports are known as link partners. Each port has two layers. The physical layer transmits or receives sequences of bytes or other control signals. The logical layer manages the physical layer and ensures smooth flow of information between the link partners. The logical layer is also responsible for any buffering that might be required for the information flow.
大体就是usb phy选择性控制连接的外设进行电源管理。
xhci 协议中PortSC 寄存器的bit[5:8] 即为Port Link State
或者dwc3 datasheet中的DSTS寄存器中的Link Status位,
enum dwc3_link_state {
› /* In SuperSpeed */
› DWC3_LINK_STATE_U0› › = 0x00, /* in HS, means ON */
› DWC3_LINK_STATE_U1› › = 0x01,
› DWC3_LINK_STATE_U2› › = 0x02, /* in HS, means SLEEP */
› DWC3_LINK_STATE_U3› › = 0x03, /* in HS, means SUSPEND */
› DWC3_LINK_STATE_SS_DIS› › = 0x04,
› DWC3_LINK_STATE_RX_DET› › = 0x05, /* in HS, means Early Suspend */
› DWC3_LINK_STATE_SS_INACT› = 0x06,
› DWC3_LINK_STATE_POLL› › = 0x07,
› DWC3_LINK_STATE_RECOV› › = 0x08,
› DWC3_LINK_STATE_HRESET› › = 0x09,
› DWC3_LINK_STATE_CMPLY› › = 0x0a,
› DWC3_LINK_STATE_LPBK› › = 0x0b,
› DWC3_LINK_STATE_RESET› › = 0x0e,
› DWC3_LINK_STATE_RESUME› › = 0x0f,
› DWC3_LINK_STATE_MASK› › = 0x0f,
};
对于usb3.0来说, 有u0, u1, u2, u3等link state状态, 分别对应休眠的等级, 相当于 u0 - 没睡, u1 - 浅睡, u2 - 中睡, u3 - 深睡
对于usb2.0来说, 状态就少点了, 根据上面描述, 也就u0 - 激活, u2 - sleep, u3 - suspend
对比前面描述的休眠唤醒, LPM相当于多了些休眠等级。功能之间有些细微的差别。
且LPM基本不需要软件进行参与, 配置好功能后, usb phy会根据设备状态让其进入相应的Link State。
系统文件目录(/sys/bus/usb/devices/.../power/)中有些控制节点, 比如
power/usb2_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.
当接入的设备支持usb2.0 LPM且测试通过, 该文件就是显示。 用户可以控制该文件来enable/disable USB2 hardware LPM功能。
power/usb3_hardware_lpm_u1
power/usb3_hardware_lpm_u2
› ``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.
字面意思, 当支持usb3.0 LPM的设备插入后, 会检查U1, U2的exit latencies, 是否被设置在BOS描述信息中。
如果检查通过, 且xhci控制器支持USB3 LPM功能, 则usb3 lpm功能则会被使能, 且这些文件会被创建。
用户可以通过写入字符串enable/disable 去控制usb3 hardare lpm功能的开启和关闭。
10. USB Port Power Control (usb端口电源管理相关)
主机供电, 显然该功能是控制对应端口的供电, 以控制usb外设供电。
相关函数:
Set/ClearPortFeature(PORT_POWER) >>>> 发送该请求给hub (单独hub或控制器root hub)
如此, root hub 或者 platform-internal hub (内部集成hub) 会进行对应端口电源管理控制。
比如xhci控制器的PortSC寄存器的Port Power(PP)位, 就可以控制端口的供电。
ClearPortFeature(PORT_POWER) 请求一个usb端口逻辑关闭。则可能会触发实际的VBUS断电。
vbus也有可能继续维持, 这个看具体集线器的设计和行为。参看文档描述:
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
不管怎样, logic off肯定导致连接是断开的。
11. User Interface for Port Power Control
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.
12. 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 ``/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.
端口电源管理部分还不够完善, 具体遇到再理解添加。
以上所以基本参考内核文档:
Documents/driver-api/usb/power-management.rst
总结下, 相关知识点:
1. 系统休眠唤醒
2. 动态/运行时/可选择休眠唤醒
3. LPM (U0, U1, U2, U3) 链路层电源管理
4. PPM (Port Power Management) 端口电源管理
5. Remote Wakeup, 设备/硬件唤醒 系统