2012年11月15日 星期四

Linux runtime PM and system suspend resume

在 Linux kernel 3.1 比原本的 device driver suspend/resume 多了另一組 runtime PM,隸屬於 struct device 的新屬性
include/linux/device.h 中定義的 struct device 可以看到:

struct device {
...
    struct device_driver *driver;
    struct dev_pm_info power;

Documentation/power/devices.txt
runtime PM 分成:prepare, suspend, suspend_noirq 三個階段

1. prepare 鎖定 parent, child 關係,申請需要的記憶體空間
2. suspend 停止 I/O 讓 device 進 low power mode 或斷電,可能有 wake up event
3. 關閉 irq 後進入 suspend_noirq 顧名思義是不會再收到 irq request 備份所有必要的暫存器,讓 device 進 low power mode 或斷電

相對應的是 resume_noirq, resume, complete
原本的 device driver suspend/resume

struct device_driver {
...
int (*suspend) (struct device *dev, pm_message_t state);
int (*resume) (struct device *dev);

Android 的 early_suspend, late_resume 是最外層,但是 runtime PM 跟 device driver suspend/resume 的順序關係為何?文件中叫我們自己 trace code...

Documentation/power/runtime_pm.txt

直接看 runtime PM 的資料是開機 default suspend 不管硬體狀態,在 system running 可依定義的 runtime PM 群組 suspend/resume suspend 是由 child -> parent,由下而上的順序相依關係,因此要使用 runtime PM 的 device 還需要使用的 device class 或subsystem, bus type 也使用 runtime PM 才行

/sys/devices/.../power/control 寫入 "on" 可以呼叫

pm_runtime_forbid() 保持在 active mode 禁止 runtime PM 動作
等確定可用後再寫入 "auto"

如果 runtime PM 在 running 沒執行過會由 kernel/power/suspend.c 進行 suspend,resume 最好先全部 active 再說?

PM core 會在呼叫 suspend/resume 時個別設定 counter 加一或減一
drivers/usb/gadget/omap_udc.c

會用到 udc->driver->suspend()

drivers/usb/core/driver.c

會用到 udriver->suspend()

所以還是要確定 device driver suspend 順序跟 runtime PM 的順序關係為何?