标题:
Linux 电源管理在ARM上的实现原理(3)
[打印本页]
作者:
yuyang911220
时间:
2015-6-24 22:02
标题:
Linux 电源管理在ARM上的实现原理(3)
4.2 进入阶段,挂起设备。
int suspend_devices_and_enter(suspend_state_t state)
{
int error;
if (!suspend_ops)
return-ENOSYS;
if (suspend_ops->begin) {
error = suspend_ops->begin(state);
if (error)
goto Close;
}
suspend_console();
suspend_test_start();
//挂起设备
error =dpm_suspend_start(PMSG_SUSPEND);
if (error) {
printk(KERN_ERR "PM: Some devices failed to suspend\n");
goto Recover_platform;
}
suspend_test_finish("suspenddevices");
if(suspend_test(TEST_DEVICES))
goto Recover_platform;
suspend_enter(state);
Resume_devices:
suspend_test_start();
dpm_resume_end(PMSG_RESUME);
suspend_test_finish("resume devices");
resume_console();
Close:
if (suspend_ops->end)
suspend_ops->end();
return error;
Recover_platform:
if (suspend_ops->recover)
suspend_ops->recover();
goto Resume_devices;
}
4.2.1挂起设备
int dpm_suspend_start(pm_message_t state)
{
int error;
might_sleep();
error = dpm_prepare(state);
if (!error)
error = dpm_suspend(state);
return error;
}
函数dpm_suspend_start()最后会调用dpm_suspend函数来挂起每个设备。
static int dpm_suspend(pm_message_t state)
{
struct list_head list;
int error = 0;
INIT_LIST_HEAD(&list);
mutex_lock(&dpm_list_mtx);
//遍历设备链表, 当一个设备被注册进系统时, 它同时会被加入到这个dpm_list队列中
while (!list_empty(&dpm_list)){
structdevice *dev = to_device(dpm_list.prev);
get_device(dev);
mutex_unlock(&dpm_list_mtx);
//挂起这个设备
error =suspend_device(dev, state);
mutex_lock(&dpm_list_mtx);
if (error) {
pm_dev_err(dev, state, "", error);
put_device(dev);
break;
}
dev->power.status = DPM_OFF;
//加入list队列, 用于以后唤醒
if(!list_empty(&dev->power.entry))
list_move(&dev->power.entry,&list);
put_device(dev);
}
list_splice(&list, dpm_list.prev);
mutex_unlock(&dpm_list_mtx);
return error;
}
此函数又会调用 suspend_device()函数挂起相应得设备,这个函数调用相应设备的suspend实现设备挂起. 所以说,系统挂起时, 设备也应该做相应的工作, 由于设备的特殊性, 这些就是留在设备里面来实现了.
static int suspend_device(struct device *dev, pm_message_tstate)
{
int error = 0;
down(&dev->sem);
if (dev->class) {
if(dev->class->pm) {
pm_dev_dbg(dev, state, "class ");
error = pm_op(dev, dev->class->pm,state);
} else if (dev->class->suspend){
pm_dev_dbg(dev, state, "legacy class ");
error = dev->class->suspend(dev,state);
suspend_report_result(dev->class->suspend,error);
}
if (error)
goto End;
}
if (dev->type) {
if (dev->type->pm) {
pm_dev_dbg(dev, state, "type ");
error = pm_op(dev, dev->type->pm,state);
}else if (dev->type->suspend) {
pm_dev_dbg(dev, state, "legacy type ");
error = dev->type->suspend(dev,state);
suspend_report_result(dev->type->suspend,error);
}
if (error)
goto End;
}
欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/)
Powered by Discuz! 7.0.0