usb休眠喚醒相關

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 ``<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.

 

端口電源管理部分還不夠完善, 具體遇到再理解添加。

以上所以基本參考內核文檔:

Documents/driver-api/usb/power-management.rst

 

總結下, 相關知識點:

1. 系統休眠喚醒

2. 動態/運行時/可選擇休眠喚醒

3. LPM (U0, U1, U2, U3) 鏈路層電源管理

4. PPM (Port Power Management) 端口電源管理

5. Remote Wakeup, 設備/硬件喚醒 系統

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章