现在的位置: 首页 > 综合 > 正文

Run-time PM 详解

2013年05月01日 ⁄ 综合 ⁄ 共 3504字 ⁄ 字号 评论关闭

Run-time PM. 
每个device或者bus都会向run-time PM core注册3个callback
struct dev_pm_ops {
...
int (*runtime_suspend)(struct device *dev);
int (*runtime_resume)(struct device *dev);
int (*runtime_idle)(struct device *dev);
...
};

每个device或者bus都会有2个计数器,一个是device的usage counter,一个是device的active状态的children个数。
当这个device的两个counter都减少为0的时候。
run-time PM core就会去调用runtime_idle函数,但是这里的idle函数可不是当前device的idle函数。
代码如下:
if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_idle) {
spin_unlock_irq(&dev->power.lock);
dev->bus->pm->runtime_idle(dev);
spin_lock_irq(&dev->power.lock);
} else if (dev->type && dev->type->pm && dev->type->pm->runtime_idle) {
spin_unlock_irq(&dev->power.lock);
dev->type->pm->runtime_idle(dev);
spin_lock_irq(&dev->power.lock);
} else if (dev->class && dev->class->pm
   && dev->class->pm->runtime_idle) {
spin_unlock_irq(&dev->power.lock);
dev->class->pm->runtime_idle(dev);
spin_lock_irq(&dev->power.lock);
}
按照dev->bus, dev->type, dev->class的顺序去调用。
大家会问了,那runtime_suspend函数什么时候调用?
runtime_suspend函数不会被RPM core主动去调用,一般情况下是在bus,或者class的idle函数里去调用。
例如:
static int xxx_runtime_idle(struct device *dev)
{
return pm_schedule_suspend(dev, 50);
}
pm_schedule_suspend函数会去调用device里的suspend函数,调用顺序代码如下:
if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_suspend) {
spin_unlock_irq(&dev->power.lock);
retval = dev->bus->pm->runtime_suspend(dev);
spin_lock_irq(&dev->power.lock);
dev->power.runtime_error = retval;
} else if (dev->type && dev->type->pm
   && dev->type->pm->runtime_suspend) {
spin_unlock_irq(&dev->power.lock);
retval = dev->type->pm->runtime_suspend(dev);
spin_lock_irq(&dev->power.lock);
dev->power.runtime_error = retval;
} else if (dev->class && dev->class->pm
   && dev->class->pm->runtime_suspend) {
spin_unlock_irq(&dev->power.lock);
retval = dev->class->pm->runtime_suspend(dev);
spin_lock_irq(&dev->power.lock);
dev->power.runtime_error = retval;
} else {
retval = -ENOSYS;
每个device或者bus都会向run-time PM core注册3个callback
struct dev_pm_ops {
...
int (*runtime_suspend)(struct device *dev);
int (*runtime_resume)(struct device *dev);
int (*runtime_idle)(struct device *dev);
...
};

每个device或者bus都会有2个计数器,一个是device的usage counter,一个是device的active状态的children个数。
当这个device的两个counter都减少为0的时候。
run-time PM core就会去调用runtime_idle函数,但是这里的idle函数可不是当前device的idle函数。
代码如下:
if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_idle) {
spin_unlock_irq(&dev->power.lock);
dev->bus->pm->runtime_idle(dev);
spin_lock_irq(&dev->power.lock);
} else if (dev->type && dev->type->pm && dev->type->pm->runtime_idle) {
spin_unlock_irq(&dev->power.lock);
dev->type->pm->runtime_idle(dev);
spin_lock_irq(&dev->power.lock);
} else if (dev->class && dev->class->pm
   && dev->class->pm->runtime_idle) {
spin_unlock_irq(&dev->power.lock);
dev->class->pm->runtime_idle(dev);
spin_lock_irq(&dev->power.lock);
}
按照dev->bus, dev->type, dev->class的顺序去调用。
大家会问了,那runtime_suspend函数什么时候调用?
runtime_suspend函数不会被RPM core主动去调用,一般情况下是在bus,或者class的idle函数里去调用。
例如:
static int xxx_runtime_idle(struct device *dev)
{
return pm_schedule_suspend(dev, 50);
}
pm_schedule_suspend函数会去调用device里的suspend函数,调用顺序代码如下:
if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_suspend) {
spin_unlock_irq(&dev->power.lock);
retval = dev->bus->pm->runtime_suspend(dev);
spin_lock_irq(&dev->power.lock);
dev->power.runtime_error = retval;
} else if (dev->type && dev->type->pm
   && dev->type->pm->runtime_suspend) {
spin_unlock_irq(&dev->power.lock);
retval = dev->type->pm->runtime_suspend(dev);
spin_lock_irq(&dev->power.lock);
dev->power.runtime_error = retval;
} else if (dev->class && dev->class->pm
   && dev->class->pm->runtime_suspend) {
spin_unlock_irq(&dev->power.lock);
retval = dev->class->pm->runtime_suspend(dev);
spin_lock_irq(&dev->power.lock);
dev->power.runtime_error = retval;
} else {
retval = -ENOSYS;

抱歉!评论已关闭.