
2013年1月14日
※要点区:
※设计思想:
※数据结构关系图:
表示用来描述request 的work ,work 将被放置在workqueue 中 pm_message_t power_state unsigned int can_wakeup 表示设备物理上是否支持唤醒事件 unsigned int
should_wakeup 表示设备是否启用它的唤醒机制 unsigned
async_suspend
表示suspend 操作的同步信号
enum dpm_state status DPM_INVALID DPM_ON
DPM_PREPARING DPM_RESUMING DPM_SUSPENDING DPM_OFF DPM_OFF_IRQ
dev_pm_info
dpm_state
struct list_head entry
struct completion completion struct timer_list suspend_timer unsigned long timer_expires; struct work_struct work enum rpm_request request atomic_t
usage_count 设置定时器的定时时间
表示设备使用计数器
atomic_t child_count 表示处于“active ”状态的子设备的个数 unsigned int
disable_depth unsigned int
ignore_children unsigned int
idle_notification 若被置位,runtime_idle()将被执行 unsigned int
request_pending 若存在未处理的请求,标志位将置1
unsigned int deferred_resume 若被置位,设备在执行完suspend 操作后立即执行resume unsigned int runtime_auto 若被置位,设备属于runtime 电源管理模式 spin_lock_t
lock
enum rpm_status runtime_status int
runtime_error
若回调函数执行失败,标志位将置1
表示设备的run-time PM 状态,但不能反映真实的电源状态 RPM_REQ_NONE = 0
RPM_REQ_IDLE
RPM_REQ_SUSPEND
RPM_REQ_RESUME
rpm_request
RPM_ACTIVE = 0 RPM_RESUMING RPM_SUSPENDED RPM_SUSPENDING
rpm_status
若被置位,忽略处于“active ”状态的子设备的个数若被设置为非0,关闭runtime PM 功能
表示用于对suspend 请求进行调度的timer 表示与PM 核操作相关的设备当前状态
struct dev_pm_info power device
... ...
表示未处理请求的类型表示同步锁
※电源管理代码流程分析:
步骤一:初始化
device_register()→device_initialize()→device_pm_init(dev)→pm_runtime_init ()
device_register()
device_initialize()
device_pm_init()
pm_runtime_init()
INIT_WORK(&dev->power.work,pm_runtime_work)
setup_timer(&dev->power.suspend_timer,pm_suspend_timer_fn,…)
init_waitqueue_head(&dev->power.wait_queue)
__pm_runtime_idle()
dev->power.request = RPM_REQ_IDLE?
Y
__pm_runtime_suspend()
dev->power.request = RPM_REQ_SUSPEND?
Y
__pm_runtime_resume()
dev->power.request = RPM_REQ_RESUME?
Y
expires > 0 &&
!time_after(expires,jiffies)?
Y
__pm_request_suspend()
dev->power.request = RPM_REQ_SUSPEND queue_work(pm_wq,&dev->power.work)
core_initcall(pm_init)
pm_init()
pm_wq = create_freezeable_workqueue(“pm ”)
void pm_runtime_init (struct device *dev) { ... ... ;
//确定工作任务对应的处理函数 INIT_WORK(&dev->power.work, pm_runtime_work );
//设置用于安排挂起请求的定时器,定时器时间到将执行pm_suspend_timer_fn 函数
setup_timer(&dev->power.suspend_timer, pm_suspend_timer_fn ,(unsigned long)dev); init_waitqueue_head(&dev->power.wait_queue);
}
{
struct device *dev = container_of(work, struct device, power.work);
enum rpm_request req;
... ... ;
req = dev->power.request;
//设置未处理请求的类型为RPM_REQ_NONE
dev->power.request = RPM_REQ_NONE;
//设置不存在未处理的请求
dev->power.request_pending = false;
//根据未处理请求的类型执行相应操作
switch (req) {
case RPM_REQ_NONE:
break;
case RPM_REQ_IDLE:
__pm_runtime_idle(dev);
break;
case RPM_REQ_SUSPEND:
__pm_runtime_suspend(dev, true);
break;
case RPM_REQ_RESUME:
__pm_runtime_resume(dev, true);
break;
}
}
static int __pm_runtime_idle(struct device *dev)
{
dev->power.idle_notification = true;
if (dev->bus->pm->runtime_idle)
dev->bus->pm->runtime_idle(dev);
else if (dev->type->pm->runtime_idle)
dev->type->pm->runtime_idle(dev);
if ( dev->class->pm->runtime_idle)
dev->class->pm->runtime_idle(dev);
dev->power.idle_notification = false;
//唤醒等待队列
wake_up_all(&dev->power.wait_queue);}
int __pm_runtime_suspend(struct device *dev, bool from_wq)
{
//取消还未处理的suspend请求
pm_runtime_cancel_pending(dev);
//判定设备是否正处于suspend操作
if (dev->power.runtime_status == RPM_SUSPENDING) {
DEFINE_WAIT(wait);
//等待已经进入处理状态的suspend请求处理完毕
for (;;) {
prepare_to_wait(&dev->power.wait_queue, &wait,TASK_UNINTERRUPTIBLE);
schedule();
... ... ;
}
finish_wait(&dev->power.wait_queue, &wait);
}
//设置设备电源管理的操作状态为RPM_SUSPENDING,即正处于挂起中
dev->power.runtime_status = RPM_SUSPENDING;
//设置在执行完suspend操作后不会立即执行resume
dev->power.deferred_resume = false;
if (dev->bus->pm->runtime_suspend)
dev->bus->pm->runtime_suspend(dev);
else if (dev->type->pm->runtime_suspend)
dev->type->pm->runtime_suspend(dev);
else if ( dev->class->pm->runtime_suspend)
dev->class->pm->runtime_suspend(dev);
//设置设备电源管理的操作状态为RPM_SUSPENDED,即已完成挂起操作
dev->power.runtime_status = RPM_SUSPENDED;
//使suspend 定时器无效
pm_runtime_deactivate_timer(dev);
//唤醒等待队列
wake_up_all(&dev->power.wait_queue);
//确定是否应该执行resume
if (dev->power.deferred_resume)__pm_runtime_resume(dev, false);
}
int __pm_runtime_resume(struct device *dev, bool from_wq)
{
//取消还未处理的suspend请求
pm_runtime_cancel_pending(dev);
//判定是否存在设备正处于suspend操作或resume操作
if (dev->power.runtime_status == RPM_RESUMING ||
dev->power.runtime_status == RPM_SUSPENDING) {
DEFINE_WAIT(wait);
for (;;) {
prepare_to_wait(&dev->power.wait_queue, &wait,TASK_UNINTERRUPTIBLE);
schedule();
finish_wait(&dev->power.wait_queue, &wait);
}
}
//设置设备电源管理的操作状态为RPM_RESUMING,即正处于恢复过程中
dev->power.runtime_status = RPM_RESUMING;
if (dev->bus->pm->runtime_resume)
dev->bus->pm->runtime_resume(dev);
else if (dev->type->pm->runtime_resume)
dev->type->pm->runtime_resume(dev);
else if (dev->class->pm->runtime_resume)
dev->class->pm->runtime_resume(dev);
//设置设备电源管理的操作状态为RPM_ACTIVE,即设备已激活
dev->power.runtime_status = RPM_ACTIVE;
wake_up_all(&dev->power.wait_queue);
}
static void pm_suspend_timer_fn(unsigned long data)
{
if (expires > 0 && !time_after(expires, jiffies))
__pm_request_suspend(dev);
... ... ;
}
static int __pm_request_suspend(struct device *dev)
{//设置电源管理请求类型为suspend
dev->power.request = RPM_REQ_SUSPEND;
//添加工作到pm_wq工作队列
queue_work(pm_wq, &dev->power.work);
... ... ;
}
static int __init pm_init(void)←core_initcall(pm_init)
{
pm_wq = create_freezeable_workqueue("pm");
//在/sys/目录下创建名为power的目录
power_kobj = kobject_create_and_add("power
//在/sys/power/目录下创建
sysfs_create_group(power_kobj, &attr_group);
}
static struct attribute_group attr_group = {
.attrs = g,
};
static struct attribute * g[] = {
&state_attr.attr,
&pm_async_attr.attr,
&wake_lock_attr.attr,
&wake_unlock_attr.attr,
};
步骤二:
? ? ?
↓
dpm_suspend_start() dpm_suspend_end()
↓
dpm_prepare() dpm_suspend() dpm_resume() dpm_complete() dpm_suspend_noirq() dpm_resume_noirq()
