ile (!error && !wakeup
&& suspend_ops->suspend_again && suspend_ops->suspend_again());
这里是一个死循环。只有wakeup 为1 的时候,我们才会调出这个循环。
我们设备的suspend的时候有很多的操作,每一个操作都放在不同的链表里面,然后我们根据不同suspend的类型,进行不同的操作。
举例如下:
error = dpm_suspend_start(PMSG_SUSPEND);
error = dpm_prepare(state); 会调用到to_device(dpm_list.next); 这个链表 ,这个链表是我们在创建device 的时候,我们所有创建设备的power 控制的结点。遍历过dpm_list 的链表后,我们将设备放到dpm_prepared_list 链表里面,再进行dpm_prepared_list 这个链表的操作。下面的几种状态也是同样的效果,只是不同的操作罢了。
2、设备的注册
我们在注册一个设备的时候,通常会调用device_register 进行设备的注册。下面设备的流程,我们只care power management 部分,别的细节暂时不care 。
整个设备注册的流程:
return device_add(dev); ----》
device_pm_add(dev);-------》
void device_pm_add(struct device *dev)
{
pr_debug(PM: Adding info for %s:%s
,
dev->bus dev->bus->name : No Bus, dev_name(dev));
mutex_lock(&dpm_list_mtx);
if (dev->parent && dev->parent->power.is_prepared)
dev_warn(dev, parent %s should not be sleeping
,
dev_name(dev->parent));
list_add_tail(&dev->power.entry, &dpm_list);
dev_pm_qos_constraints_init(dev);
mutex_unlock(&dpm_list_mtx);
}
上面的注册会将设备添加到dpm_list里面。 list_add_tail(&dev->power.entry, &dpm_list);
3、suspend_ops 的操作
在整个power management 里面经常会调用到suspend_ops 这个操作集合里面提供的interface 进行
suspend_ops 是存放在kerel/kernel/suspend.c 里面的全部变量。 suspend_set_ops 这个函数会为suspend_set_ops 这个变量进行赋值。
void suspend_set_ops(const struct platform_suspend_ops *ops)
{
lock_system_sleep();
suspend_ops = ops;
unlock_system_sleep();
}
suspend_set_ops 是在/kernel/arch/arm/mach-msm/pm-8x60.c 里面。
static int __init msm_pm_init(void)
{
enum msm_pm_time_stats_id enable_stats[] = {
MSM_PM_STAT_IDLE_WFI,
MSM_PM_STAT_RETENTION,
MSM_PM_STAT_IDLE_STANDALONE_POWER_COLLAPSE,
MSM_PM_STAT_IDLE_POWER_COLLAPSE,
MSM_PM_STAT_SUSPEND,
};
msm_pm_mode_sysfs_add();
msm_pm_add_stats(enable_stats, ARRAY_SIZE(enable_stats));
suspend_set_ops(&msm_pm_ops);
msm_pm_ops 的实现如下:
static const struct platform_suspend_ops msm_pm_ops = {
.enter = msm_pm_enter,
.valid = suspend_valid_only_mem,
.prepare_late = msm_suspend_prepare,
.wake = msm_suspend_wake,
};
看到没有,这个里面实现ops 里面的enter、valid 、prepare_late 、wake 函数。
这些函数在suspend 的时候都会调用到,如:
static int suspend_prepare(void)
{
int error;
if (!suspend_ops || !suspend_ops->enter)
return -EPERM;
这里就在调用enter 函数。
4.设备resume 的流程
当我们按下power key 之后,我们的设备会进入suspend ,整个流程如上面讲解suspend 的流程一样。
source code :
do {
error = suspend_enter(state, &wakeup);
} while (!error && !wakeup
&& suspend_ops->suspend_again && suspend_ops->suspend_again());
suspend_enter 函数的实现:
static int suspend_enter(suspend_state_t state, bool *wakeup)
{
int error;
if (suspend_ops->prepare) {
error = suspend_ops->prepare();
if (error)
goto Platform_finish;
}
error = dpm_suspend_end(PMSG_SUSPEND);
if (error) {
printk(KERN_ERR PM: Some devices failed to power down
);
goto Platform_finish;
}
if (suspend_ops->prepare_late) {
error = suspend_ops->prepare_late();
if (error)
goto Platform_wake;
}
if (suspend_test(TEST_PLATFORM))
goto Platform_wake;
error = disable_nonboot_cpus();
if (error || suspend_test(TEST_CPUS))
goto Enable_cpus;
arch_suspend_disable_irqs();
BUG_ON(!irqs_disabled());
error = syscore_suspend();
if (!error) {
*wakeup = pm_wakeup_pending();
if (!(suspend_test(TEST_CORE) || *wakeup)) {
er