Board logo

标题: 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