Professional Documents
Culture Documents
Android PM Guide10
Android PM Guide10
chunghan.yi@gmail.com, slowboot
0.91
3. Wakelocks
application wakelock, driver wakelock
References
System running
suspend
resume
wakeup
struct platform_suspend_ops
) struct platform_suspend_ops msm_pm_ops = { .enter = msm_pm_enter, .valid = suspend_valid_only_mem,
};
arch/arm/mach-xxx/pm.c
struct platform_suspend_ops { int (*valid)(suspend_state_t state); int (*begin)(suspend_state_t state); int (*prepare)(void); int (*prepare_late)(void); int (*enter)(suspend_state_t state); void (*wake)(void); void (*finish)(void); void (*end)(void); void (*recover)(void); }; struct platform_driver { int (*probe)(struct platform_device *); int (*remove)(struct platform_device *); int (*shutdown)(struct platform_device *); int (*suspend)(struct platform_device *, ); int (*suspend_late)(struct platform_device *, ); int (*resume_early)(struct platform_device *); int (*resume)(struct platform_device *); };
platform_driver or device_driver
2) standby(Standby) power saving (standby) ON , 1-2 3) mem(Suspend-to-RAM) power saving (Suspend-to-RAM) ON , 3-5 4) disk(Suspend-to-Disk) power saving (Suspend-to-Disk) ON , 30
Power State # cat /sys/power/state Power State # echo mem > /sys/power/state # echo standby > /sys/power/state
Resume : *) interrupt (: power key , ). wakeup . 1) System (/sys/devices/system) , 2) IRQ , CPU 3) (resume callback ), freezing task .
Suspend Sequence
Resume Sequence
(*) Android 1) PowerManager 2) PowerManagerService 3) JNI 4) HAL(power.c) 5) Kernel - Early suspend/late resume - wakelock
System Running
Late Resume: Early Suspend , google linux kernel . Linux resume , early suspend resume .
early_suspend
late_resume
suspend
resume
wakeup
queue_work
early_suspend
queue_work
suspend
(4) check
wake locks
(5)
(B)
wake_lock or wake_unlock
. mem /sys/power/state . (3) early_suspend work(early_suspend_work) <suspend> work queue . <work queue > early_suspend( ) early_suspend callback . main_wake_lock .
(4) wake lock ( ), suspend work(suspend_work) <suspend> work queue .
(5) suspend .
wake lock timer , wake_lock()/wake_unlock() . Wakelock , suspend work <suspend> work queue ^^. Wake lock application linux device driver . , suspend/resume main_wake_lock .
(6)
(4)
InputManager
(7)
Userspace
kernel
Kernel wakeup
Touch
2. Android Power Management Late Resume/2 <Resume & Late Resume Step>
(1) power key .
^^
(3) Power key input driver , android framework . (4) Android framework power key (system_server )EventHub -> Input Manager -> Window Manager . (5) Window Manager power key , PowerManager -> PowerManagerService .
Power key .
(6) PowerManagerService early suspend kernel late resume . (7) on /sys/power/state . (8) late_resume main_wake_lock enable.
early_suspend_work
wakelock
<suspend thread>
suspend_work
func
late_resume_work
(*) , early_suspend late_resume <suspend> work queue ^^ (*) , early_suspend , suspend work queue . (*) Android patch kernel suspend . a) timer , wake_lock b) wake_lock(), wake_unlock() , wake_lock (*) kernel/power/earlysuspend.c, wakelock.c !!!
EarlySuspend State
drivers
No wakelocks
(A)
if wakelocks exist
Suspend Callbacks
(A) : earlysuspend drivers active wakelock , suspend . (B) : suspend , suspend callback , resume .
NG
(B)
Resume Callbacks
OK
Suspend State
=============<callback >===============
void __suspend_report_result(const char *function, void *fn, int ret) { if (ret) printk(KERN_ERR, %s(): %pF returns %d\n, function, fn, ret); }
. [base/power/main.c]
====================================>===============
Execute late and noirq device suspend callbacks - dpm_suspend_late( ) - device_suspend_late( ) - Execute a late suspend callback - callback = pm_late_early_op( ) - dpm_run_callback(callback, ) (C) callback !!!
- suspend_ops->prepare_late(); - disable_nonboot_cpus(); - arch_suspend_disable_irqs(); - syscore_suspend(); .......................................................................................................... [drivers/base/ syscore.c] Execute all the registered system core suspend callbacks.
- ret = ops->suspend( ) (E) callback !!!
3. Wakelocks
(suspend_blocker)
3. Wakelock(1)
goToSleep
acquire wakelock
early_suspend
Unlock main wakelock check Ignored. No
suspend
Yes
check
B
wake_lock
(*) android appl linux device driver wakelock . (*) PowerManager suspend wakelock , wakelock , system suspend ^^.
PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE); PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, My Tag); wl.acquire(); /* screeen will stay on during this section */ wl.release();
(application code )
CPU , screen on . Screen on , keyboard backlight
wake_lock_init()
wake_unlock()
wake_lock_destroy()
[] wake_lock_destroy (&mywakelock);
[] long has_wake_lock(int type); wake lock non-zero return .
Go to suspend
timer
wake_lock() wake_unlock()
main_wake _lock
Go to suspend
wakelock
appl appl appl driver struct wake_lock { struct list_head link; int flags; const char *name; unsigned long expires; };
suspended state
1) main_wake_lock, unknown_wakeup wakelock 2) platform_device(power_device), platform_driver(power_driver) struct platform_driver power_driver = { .driver.name = power, .driver.pm = &power_driver_pm_ops, }; struct platform_device power_device = { .name = power, }; 3) suspend_sys_sync suspend work queue sys_sync early_suspend/suspend/late_resume work queue sys_sync process freeze , check 4) suspend_sys_sync_comp completion kernel/power/process.c freeze_processes( ) suspend_sys_sync_wait( ) , wait_for_completion , suspend_sys_sync_timer handler complete . 5) /proc/wakelocks
(*) : Suspend(Sleep) , ?
0) , .
suspend
1) active wakelocks , 2) early suspend callback suspend callback (?) , 3) runtime pm (?) , suspend .
1) /proc/wakelocks active_since 0 .
(USB )USB PowerManagerService wakelock active_since 0 , . (USB ) active_since 0 , , ram console . active_since , sleep mode , suspend callback , runtime pm , runtime suspend callback .
, 1), 2), 3) kernel log , system (power off , reboot ) , (cat /proc/last_kmsg) .
Page
Page
Page
4. Linux Runtime PM -
System sleep is not enough to decrease runtime energy consumption System sleep . Devices may depend on another device Device . Be helpful to figure out 'idle' condition Idle . Not doable to do I/O runtime PM in CPUIdle CPU PM I/O device PM . - devices may be idle but cpu is not idle - task schedule may be caused during device suspend - some devices' suspend is moved from cpuidle platform driver to runtime PM (such as, uart suspend on omap3/4) - long latency is involved when returning from cpuidle
(*) runtime PM system suspend( ) , System suspend device suspend , system suspend .
Active
resuming
suspending
Suspended
1) Bus port halting 2) clock, regulator disable 3) GPIO pin high impedance
(*) I/O , run-time low-power state , wakeup run-time power management . (*) PM core callback () . (*) include/linux/pm.h
struct dev_pm_ops { int (*runtime_suspend)(struct device *dev); int (*runtime_resume)(struct device *dev); int (*runtime_idle)(struct device *dev); };
5) Device
3) Suspend pm_runtime_suspend()
a)
pm_runtime_get(), _sync(), _noresume() Increment use count, pm_runtime_resume() device resume . b) pm_runtime_put(), _sync, _noidle() Decrement use count, pm_runtime_idle() device idle .
5.1 CPUFreq
5.2 CPUIdle
<linux kernel battery driver> (*) drivers/power/power_supply*.c power supply class (*) drivers/power/ds2784_battery.c battery driver . power supply code
UEventObserver
To BatteryService
Device
ueventd
netlink socket
Userspace kernel
kobject_uevent(struct kobject *kobj, enum kobject_action action); action event socket buffer(sk_buffer)
Start charging
Trickle charging
work
veoc_begin_work
done
16 , __pm8058_start_charging()
App Processor
PMIC chip
interrupt
irq hdler
uevent
pm8058 charger
irq hdler
msm-charger
irq hdler
teoc_work teoc( )
queue_work( )
queue_work process_events( )
msm_charger_notify_event( ) in pm8058_pmic_charger.c
msm_charger_eventd thread
msm_charger
Fuel gauge
Appendix
Ram Console(1)
<Ram Console >
This allows saving the kernel printk messages to a buffer in RAM, so that after a kernel panic they can be viewed in the next kernel invocation, by accessing /proc/last_kmsg. kernel printk message RAM buffer , kernel panic , ( booting ) /proc/last_kmsg !!!
Ram Console(2)
virtual address
printk
Kernel messages through ram console
tty
virtual memory
start = 0x78e00000
size = 256K
/proc/last_kmsg
Ram Console(3)
/proc/last_kmsg
old new
References
1) Android-Power Management.pdf [Renaldo Noma 2010] 2) Suspend-to-RAM in Linux . [Proceedings of the Linux Symposium July 23 rd-26th, 2008] 3) Power Management & Battery Life [The 7th Korea Android Conference, Kwangwoo LEE, kwangwoo.lee@gmail.com] 4) Power Saving in Linux devices [Chris Simmonds, 2net Limited] 5) Linux clock management framework [Siarhei Yermalayeu ] 6) Runtime Power Management [Kevin Hilman] 7) Runtime PM(upstream I/O Device Power Management) [Magnus Damm] 8) Runtime Power Management Framework for I/O Devices in the Linux Kernel [Rafael J. Wysocki] 9) Linux Power Management Architecture(An updated review on Linux PM frameworks [Patrick Bellasi] 10) Power Consumption(kernel level) [Jan Slupski ] 11) Power management [Michael Opdenacker] 12) A Dynamic Voltage and Current Regulator Control Interface for the Linux Kernel [Liam Girdwood] 13) Powerdebugging inside Linaro [Amit Kucheria] 14) Some Internet Articles
SlowBoot