這里沒有大堆的文字說明,只是羅列了一下睡眠和喚醒的主要流程,具體細節還需要自己去分析。
關鍵的一點:
Android上層和底層間“通信”是通過它的虛擬文件系統中的屬性,上層對該屬性執行寫操作,底層對應的調用該屬性的store方法。
一、上層的一些流程
updatePowerStateLocked(); updateSuspendBlockerLocked(); setHalAutoSuspendModeLocked(); nativeSetAutoSuspend(); autosuspend_enable(); autosuspend_init(); autosuspend_ops->enable(); autosuspend_earlysuspend_enable(); #define EARLYSUSPEND_SYS_POWER_STATE "/sys/power/state" static const char *pwr_state_mem = "mem"; sPowerStatefd = open(EARLYSUSPEND_SYS_POWER_STATE, O_RDWR); write(sPowerStatefd, pwr_state_mem, strlen(pwr_state_mem));
二、底層函數執行流程
power_attr(state); // /kernel/power/main.c #ifdef CONFIG_MTK_LDVT //在現有的代碼中,走的是下面的函數 state_store();{ decode_state(); //根據寫入的字符串,轉換得到狀態 pm_suspend(state);{ enter_state(state);{ suspend_prepare(state);{ //這個不是我想要的重點,忽略它 } suspend_devices_and_enter(state);{ suspend_console(); //掛起終端,非重點 dpm_suspend_start(PMSG_SUSPEND);{ dpm_prepare(state);{ while (!list_empty(&dpm_list)){ //如果 dpm_list 鏈表不為空 struct device *dev = to_device(dpm_list.next); //根據鏈表節點獲取對應的設備 device_prepare(dev, state); //執行電源管理操作函數集中的prepare函數,具體執行的順序見下面列表。 list_move_tail(&dev->power.entry, &dpm_prepared_list); //把dev元素,移到dpm_prepared_list鏈表后面 } } dpm_suspend(state); { while (!list_empty(&dpm_prepared_list)) { //遍歷dpm_prepared_list鏈表 struct device *dev = to_device(dpm_prepared_list.prev); device_suspend(dev);{ //分為同步和異步執行,此處分析同步執行 __device_suspend(dev, pm_transition, false); //執行電源管理操作函數集中的suspend函數,具體執行的順序見下面列表。 } list_move(&dev->power.entry, &dpm_suspended_list); } } } suspend_enter(state, &wakeup);{ suspend_ops->prepare(); dpm_suspend_end(PMSG_SUSPEND);{ dpm_suspend_late(state);{ while (!list_empty(&dpm_suspended_list)){ //遍歷鏈表dpm_suspended_list struct device *dev = to_device(dpm_suspended_list.prev); device_suspend_late(dev, state); //執行電源管理操作函數集中的suspend_late函數,具體執行順序見下面說明。 list_move(&dev->power.entry, &dpm_late_early_list); } } dpm_suspend_noirq(state);{ cpuidle_pause(); suspend_device_irqs(); while (!list_empty(&dpm_late_early_list)){ struct device *dev = to_device(dpm_late_early_list.prev); device_suspend_noirq(dev, state); //執行電源管理操作函數集中的suspend_noirq函數,具體執行順序見下面說明。 list_move(&dev->power.entry, &dpm_noirq_list); } } } suspend_ops->prepare_late(); disable_nonboot_cpus(); arch_suspend_disable_irqs(); syscore_suspend();{ list_for_each_entry_reverse(ops, &syscore_ops_list, node){ ops->suspend(); } } pm_wakeup_pending(); suspend_ops->enter(state); //后續環節即為喚醒流程 syscore_resume(); arch_suspend_enable_irqs(); enable_nonboot_cpus(); suspend_ops->wake(); dpm_resume_start(PMSG_RESUME); suspend_ops->finish(); } //睡眠被打斷之后繼續執行其后的喚醒流程 dpm_resume_end(PMSG_RESUME); dpm_resume(state); while (!list_empty(&dpm_suspended_list)) //遍歷鏈表dpm_suspended_list device_resume(dev, state, false); pm_op(dev->driver->pm, state); //可能有多種情形,視具體情況而定 ops->resume; dpm_complete(state); while (!list_empty(&dpm_prepared_list)) device_complete(dev, state); dev->driver->pm->complete; //可能有多種情形,視具體情況而定 resume_console(); } } } } #else state_store();{ #ifdef CONFIG_EARLYSUSPEND //現有的代碼中,有該定義,所以沒有使用enter_state函數 request_suspend_state(new_state);{ //Earlysuspend.c (kernel-3.10\kernel\power) if (new_state != PM_SUSPEND_ON){ //該狀態分支執行掛起操作,即suspend queue_work(sys_sync_work_queue, &early_sys_sync_work);{ //掛起操作之前,先執行同步操作。 static DECLARE_WORK(early_sys_sync_work, early_sys_sync); early_sys_sync(struct work_struct *work){ sys_sync(); } } queue_work(suspend_work_queue, &early_suspend_work);{ static DECLARE_WORK(early_suspend_work, early_suspend); early_suspend(struct work_struct *work){ list_for_each_entry(pos, &early_suspend_handlers, link){ pos->suspend(pos); } } } }else if(new_state == PM_SUSPEND_ON){ //該狀態分支執行恢復操作,即resume queue_work(suspend_work_queue, &late_resume_work);{ static DECLARE_WORK(late_resume_work, late_resume); late_resume(struct work_struct *work){ list_for_each_entry_reverse(pos, &early_suspend_handlers, link){ pos->resume(pos); } } } } } #else enter_state(state); #endif } #endif
三、涉及到的幾個鏈表結構中成員的轉移關系
從左到右為suspend過程,從右到左為resume過程
dpm_list dpm_prepared_list dpm_suspended_list dpm_late_early_list dpm_noirq_list
四、dpm_list的成員添加流程:
device_create(); device_create_vargs(); device_register(struct device *dev); device_add(dev); device_pm_add(dev); //kernel-3.10\drivers\base\Core.c list_add_tail(&dev->power.entry, &dpm_list); //kernel-3.10\drivers\base\power\Main.c
只要調用其中的函數就可以了,沒有必要說是必須調用那個函數;
只是列出了它的可能調用流程,明白那些操作可以添加dpm_list的成員。
五、suspend過程函數執行流程
prepare執行的先后順序 if (dev->power.syscore) return 0; callback = dev->pm_domain->ops.prepare; callback = dev->type->pm->prepare; callback = dev->class->pm->prepare; callback = dev->bus->pm->prepare; callback = dev->driver->pm->prepare; error = callback(dev); suspend的執行順序 if (dev->power.syscore) goto Complete; callback = pm_op(&dev->pm_domain->ops, state); callback = pm_op(dev->type->pm, state); callback = pm_op(dev->class->pm, state); dev->class->suspend; callback = pm_op(dev->bus->pm, state); dev->bus->suspend; callback = pm_op(dev->driver->pm, state); suspend_late的執行順序 if (dev->power.syscore) return 0; callback = pm_late_early_op(&dev->pm_domain->ops, state); callback = pm_late_early_op(dev->type->pm, state); callback = pm_late_early_op(dev->class->pm, state); callback = pm_late_early_op(dev->bus->pm, state); callback = pm_late_early_op(dev->driver->pm, state); suspend_noirq的執行順序 if (dev->power.syscore) return 0; callback = pm_noirq_op(&dev->pm_domain->ops, state); callback = pm_noirq_op(dev->type->pm, state); callback = pm_noirq_op(dev->class->pm, state); callback = pm_noirq_op(dev->bus->pm, state); callback = pm_noirq_op(dev->driver->pm, state);
六、resume過程函數執行流程
暫時未分析,后續補齊
七、部分結構對應的操作方法集
dev->pm_domain->ops 函數操作集合 dev->type->pm 函數操作集合 dev->class->pm 函數操作集合 dev->bus->pm 函數操作集合 dev->driver->pm 函數操作集合 struct dev_pm_ops { int (*prepare)(struct device *dev); void (*complete)(struct device *dev); int (*suspend)(struct device *dev); int (*resume)(struct device *dev); int (*freeze)(struct device *dev); int (*thaw)(struct device *dev); int (*poweroff)(struct device *dev); int (*restore)(struct device *dev); int (*suspend_late)(struct device *dev); int (*resume_early)(struct device *dev); int (*freeze_late)(struct device *dev); int (*thaw_early)(struct device *dev); int (*poweroff_late)(struct device *dev); int (*restore_early)(struct device *dev); int (*suspend_noirq)(struct device *dev); int (*resume_noirq)(struct device *dev); int (*freeze_noirq)(struct device *dev); int (*thaw_noirq)(struct device *dev); int (*poweroff_noirq)(struct device *dev); int (*restore_noirq)(struct device *dev); int (*runtime_suspend)(struct device *dev); int (*runtime_resume)(struct device *dev); int (*runtime_idle)(struct device *dev); }; dev->pm_domain 函數操作集合 無 dev->type 函數操作集合 int (*uevent)(struct device *dev, struct kobj_uevent_env *env); char *(*devnode)(struct device *dev, umode_t *mode, kuid_t *uid, kgid_t *gid); void (*release)(struct device *dev); dev->class 函數操作集合 int (*dev_uevent)(struct device *dev, struct kobj_uevent_env *env); char *(*devnode)(struct device *dev, umode_t *mode); void (*class_release)(struct class *class); void (*dev_release)(struct device *dev); int (*suspend)(struct device *dev, pm_message_t state); int (*resume)(struct device *dev); const void *(*namespace)(struct device *dev); dev->bus 函數操作集合 int (*match)(struct device *dev, struct device_driver *drv); int (*uevent)(struct device *dev, struct kobj_uevent_env *env); int (*probe)(struct device *dev); int (*remove)(struct device *dev); void (*shutdown)(struct device *dev); int (*suspend)(struct device *dev, pm_message_t state); int (*resume)(struct device *dev); dev->driver 函數操作集合 int (*probe) (struct device *dev); int (*remove) (struct device *dev); void (*shutdown) (struct device *dev); int (*suspend) (struct device *dev, pm_message_t state); int (*resume) (struct device *dev);
八、MTK平台的register_early_suspend函數分析
struct early_suspend { #ifdef CONFIG_HAS_EARLYSUSPEND struct list_head link; int level; void (*suspend) (struct early_suspend *h); void (*resume) (struct early_suspend *h); #endif }; register_early_suspend(struct early_suspend *handler) //Earlysuspend.c (kernel-3.10\kernel\power) list_for_each(pos, &early_suspend_handlers){ //根據handler->level的等級,在鏈表early_suspend_handlers中選擇合適的插入位置。 } list_add_tail(&handler->link, pos); early_suspend_count++; register_early_suspend函數的主要任務是把early_suspend結構體添加到early_suspend_handlers鏈表中。 現在存在的一個疑問是在什么時候調用鏈表中的相關函數。 static DECLARE_WORK(early_suspend_work, early_suspend); static DECLARE_WORK(late_resume_work, late_resume); static void early_suspend(struct work_struct *work){ list_for_each_entry(pos, &early_suspend_handlers, link){ pos->suspend(pos); } } static void late_resume(struct work_struct *work){ list_for_each_entry_reverse(pos, &early_suspend_handlers, link){ pos->resume(pos); } }