电源管理休眠流程梳理( 二 )


static int __init pm_init(void){int error = pm_start_workqueue();if (error)return error;hibernate_image_size_init();hibernate_reserved_size_init();power_kobj = kobject_create_and_add("power", NULL);if (!power_kobj)return -ENOMEM;error = sysfs_create_group(power_kobj, &attr_group);if (error)return error;pm_print_times_init();return pm_autosleep_init();}
这里在power目录下创建了一个state文件,对应的读函数是,写函数是,所以echo “mem” > /sys/power/state会触发函数 。
//位于kernel\power\main.cstatic ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,const char *buf, size_t n){suspend_state_t state;int error;error = pm_autosleep_lock();if (error)return error;if (pm_autosleep_state() > PM_SUSPEND_ON) {error = -EBUSY;goto out;}state = decode_state(buf, n);if (state < PM_SUSPEND_MAX)error = pm_suspend(state); 【见下解析】else if (state == PM_SUSPEND_MAX)error = hibernate();elseerror = -EINVAL;out:pm_autosleep_unlock();return error ? error : n;}power_attr(state);
定义了一个名称为state的文件,该文件的store接口为,该接口在lock住功能后,解析用户传入的(、 or mem),转换成state参数 。
state参数的类型为,在\linux\.h中定义,为电源管理状态在内核中的表示 。具体如下:
typedef int __bitwise suspend_state_t;#define PM_SUSPEND_ON((__force suspend_state_t) 0)#define PM_SUSPEND_FREEZE((__force suspend_state_t) 1)#define PM_SUSPEND_STANDBY((__force suspend_state_t) 2)#define PM_SUSPEND_MEM((__force suspend_state_t) 3)#define PM_SUSPEND_MINPM_SUSPEND_FREEZE#define PM_SUSPEND_MAX((__force suspend_state_t) 4)
下面看看函数和
int pm_suspend(suspend_state_t state){int error;if (state <= PM_SUSPEND_ON || state >= PM_SUSPEND_MAX)return -EINVAL;error = enter_state(state);//【见下解析】if (error) {suspend_stats.fail++;dpm_save_failed_errno(error);} else {suspend_stats.success++;}return error;}static int enter_state(suspend_state_t state){int error;if (!valid_state(state))//【见下解析】return -ENODEV;if (!mutex_trylock(&pm_mutex))return -EBUSY;if (state == PM_SUSPEND_FREEZE)freeze_begin();printk(KERN_INFO "PM: Syncing filesystems ... ");sys_sync();printk("done.\n");pr_debug("PM: Preparing system for %s sleep\n", pm_states[state]);error = suspend_prepare(state);//【见下解析】if (error)goto Unlock;if (suspend_test(TEST_FREEZER))goto Finish;pr_debug("PM: Entering %s sleep\n", pm_states[state]);pm_restrict_gfp_mask();//【见下解析】error = suspend_devices_and_enter(state);//让设备进入休眠状态pm_restore_gfp_mask();Finish:pr_debug("PM: Finishing wakeup.\n");suspend_finish();Unlock:mutex_unlock(&pm_mutex);return error;}bool valid_state(suspend_state_t state){if (state == PM_SUSPEND_FREEZE) {return true;}/** PM_SUSPEND_STANDBY and PM_SUSPEND_MEMORY states need lowlevel* support and need to be valid to the lowlevel* implementation, no valid callback implies that none are valid.*/return suspend_ops && suspend_ops->valid && suspend_ops->valid(state);}//调用valid_state,判断该平台是否支持该电源状态 。//如果是freeze,无需平台代码参与即可支持,直接返回true 。对于standby和mem,则需要调用suspend_ops的valid回掉,由底层平台代码判断是否支持 。static int suspend_prepare(suspend_state_t state){int error;if (!sleep_state_supported(state))return -EPERM;pm_prepare_console();error = pm_notifier_call_chain(PM_SUSPEND_PREPARE);//通知所有关心“休眠消息”的驱动程序if (error)goto Finish;trace_suspend_resume(TPS("freeze_processes"), 0, true);error = suspend_freeze_processes();//冻结APP和内核线程trace_suspend_resume(TPS("freeze_processes"), 0, false);if (!error)return 0;suspend_stats.failed_freeze++;dpm_save_failed_step(SUSPEND_FREEZE);Finish:pm_notifier_call_chain(PM_POST_SUSPEND);pm_restore_console();return error;}//让设备进入休眠状态int suspend_devices_and_enter(suspend_state_t state){int error;bool wakeup = false;if (need_suspend_ops(state) && !suspend_ops)return -ENOSYS;trace_machine_suspend(state);//检查平台代码是否需要提供以及是否提供了suspend_ops//调用suspend_ops的begin回调(有的话),通知平台代码,以便让其作相应的处理(需要的话) 。可能失败,需要跳至Close处执行恢复操作(suspend_ops->end) 。if (need_suspend_ops(state) && suspend_ops->begin) {error = suspend_ops->begin(state);if (error)goto Close;}suspend_console();//停止串口ftrace_stop();suspend_test_start();//dpm_suspend_start中会调用dpm_prepare(state)和dpm_suspend(state)两个函数/*1.dpm_prepare(state)中,对于dpm_list链表中的每一个设备都调用device_prepare,即准备阶段即对于每一个涉笔调用它的dev->pm_domain->ops->suspend_noirq或dev->type->pm->suspend_noirq或dev->class->pm->suspend_noirq或dev->bus->pm->suspend_noirq或dev->driver->pm->suspend_noirq *//*2.dpm_suspend(state)中,让各类设备休眠将准备好的设备放入dpm_prepared_list中,对于dpm_prepared_list链表中的每一个设备,都调用device_suspend(dev);__device_suspend(dev, pm_transition, false);对于该设备,调用它的dev->pm_domain->ops->suspend 或dev->type->pm->suspend或dev->class->pm->suspend或dev->bus->pm->suspend或dev->driver->pm->suspend*/error = dpm_suspend_start(PMSG_SUSPEND);if (error) {printk(KERN_ERR "PM: Some devices failed to suspend\n");//注意:调用dpm_suspend_start,调用所有设备的->prepare和->suspend回调函数,suspend需要正常suspend的设备 。suspend device可能失败,需要跳至 Recover_platform,执行recover操作(suspend_ops->recover) 。goto Recover_platform;}suspend_test_finish("suspend devices");if (suspend_test(TEST_DEVICES))goto Recover_platform;do {error = suspend_enter(state, &wakeup);//让CPU进入休眠//suspend_enter返回,如果返回原因不是发生错误,且不是wakeup事件 。则调用suspend_ops的suspend_again回调,检查是否需要再次suspend 。再什么情况下要再次suspend呢?需要看具体的平台了 。} while (!error && !wakeup && need_suspend_ops(state)&& suspend_ops->suspend_again && suspend_ops->suspend_again());//Resume_devices:suspend_test_start();dpm_resume_end(PMSG_RESUME);suspend_test_finish("resume devices");ftrace_start();resume_console();//回复串口Close:if (need_suspend_ops(state) && suspend_ops->end)suspend_ops->end();trace_machine_suspend(PWR_EVENT_EXIT);return error;Recover_platform:if (need_suspend_ops(state) && suspend_ops->recover)suspend_ops->recover();goto Resume_devices;}