您的位置:首页 > 移动开发 > Android开发

Android休眠唤醒驱动流程分析(三)

2013-07-04 14:40 429 查看
接上一节:
 

static int suspend_enter(suspend_state_t state)

{

int error = 0;

 

device_pm_lock();

#ifdef CONFIG_CPU_FREQ

cpufreq_get_cpufreq_name(0);

strcpy(governor_name, cpufreq_governor_name);

if(strnicmp(governor_name, userspace_governor, CPUFREQ_NAME_LEN)) {

cpufreq_set_policy(0, "performance");

}

#endif 

arch_suspend_disable_irqs();

BUG_ON(!irqs_disabled());

 

if ((error = device_power_down(PMSG_SUSPEND))) {

printk(KERN_ERR "PM: Some devices failed to power down\n");

goto Done;

}

 

error = sysdev_suspend(PMSG_SUSPEND);

if (!error) {

if (!suspend_test(TEST_CORE))

error = suspend_ops->enter(state);  //suspend过程完成处

sysdev_resume();

}

 

device_power_up(PMSG_RESUME);

 Done:

arch_suspend_enable_irqs();

#ifdef CONFIG_CPU_FREQ

if(strnicmp(governor_name, userspace_governor, CPUFREQ_NAME_LEN)) {

cpufreq_set_policy(0, governor_name);

}

#endif 

BUG_ON(irqs_disabled());

device_pm_unlock();

return error;

}
 
然后回到suspend_devices_and_enter()函数中,使能休眠时候停止掉的非启动CPU,继续唤醒每个设备,使能终端。

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 = device_suspend(PMSG_SUSPEND);

if (error) {

printk(KERN_ERR "PM: Some devices failed to suspend\n");

goto Recover_platform;

}

suspend_test_finish("suspend devices");

if (suspend_test(TEST_DEVICES))

goto Recover_platform;

 

if (suspend_ops->prepare) {

error = suspend_ops->prepare();

if (error)

goto Resume_devices;

}

 

if (suspend_test(TEST_PLATFORM))

goto Finish;

 

error = disable_nonboot_cpus();

if (!error && !suspend_test(TEST_CPUS))

suspend_enter(state);  //suspend过程完成处

 

enable_nonboot_cpus();

 Finish:

if (suspend_ops->finish)

suspend_ops->finish();

 Resume_devices:

suspend_test_start();

device_resume(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;

}
 
当suspend_devices_and_enter()执行完成后,系统外设已经唤醒,但进程依然是冻结的状态,返回到enter_state函数中,调用suspend_finish()函数。

static int enter_state(suspend_state_t state)

{

int error;

 

if (!valid_state(state))

return -ENODEV;

 

if (!mutex_trylock(&pm_mutex))

return -EBUSY;

 

printk(KERN_INFO "PM: Syncing filesystems ... ");

sys_sync();

printk("done.\n");

 

pr_debug("PM: Preparing system for %s sleep\n", pm_states[state]);

error = suspend_prepare();

if (error)

goto Unlock;

 

if (suspend_test(TEST_FREEZER))

goto Finish;

 

pr_debug("PM: Entering %s sleep\n", pm_states[state]);

error = suspend_devices_and_enter(state);  //suspend过程完成处

 

 Finish:

pr_debug("PM: Finishing wakeup.\n");

suspend_finish();

 Unlock:

mutex_unlock(&pm_mutex);

return error;

}
 
在suspend_finish()函数中,解冻进程和任务,使能用户空间helper进程,广播一个系统从suspend状态退出的notify,唤醒终端。

static void suspend_finish(void)

{

suspend_thaw_processes();

usermodehelper_enable();

pm_notifier_call_chain(PM_POST_SUSPEND);

pm_restore_console();

}
 
当所有的唤醒已经结束以后,用户进程都已经开始运行了,但没点亮屏幕,唤醒通常会是以下的几种原因:
如果是来电,那么Modem会通过发送命令给rild来让rild通知WindowManager有来电响应,这样就会远程调用PowerManagerService来写”on”到 /sys/power/state 来调用late resume(),执行点亮屏幕等操作。
用户按键事件会送到WindowManager中,WindowManager会处理这些按键事件,按键分为几种情况,如果按键不是唤醒键,那么WindowManager会主动放弃wakeLock来使系统进入再次休眠;如果按键是唤醒键,那么WindowManger就会调用PowerManagerService中的接口来执行late Resume。
 
当”on”被写入到/sys/power/state之后,同early_suspend过程,request_suspend_state()被调用,只是执行的工作队列变为late_resume_work。在late_resume函数中,唤醒调用了early_suspend的设备。
static DECLARE_WORK(late_resume_work, late_resume);

static void late_resume(struct work_struct *work)

{

struct early_suspend *pos;

unsigned long irqflags;

int abort = 0;

 

mutex_lock(&early_suspend_lock);

spin_lock_irqsave(&state_lock, irqflags);

if (state == SUSPENDED)

state &= ~SUSPENDED;

else

abort = 1;

spin_unlock_irqrestore(&state_lock, irqflags);

 

if (abort) {

if (debug_mask & DEBUG_SUSPEND)

pr_info("late_resume: abort, state %d\n", state);

goto abort;

}

if (debug_mask & DEBUG_SUSPEND)

pr_info("late_resume: call handlers\n");

list_for_each_entry_reverse(pos, &early_suspend_handlers, link)

if (pos->resume != NULL)

pos->resume(pos);

if (debug_mask & DEBUG_SUSPEND)

pr_info("late_resume: done\n");

abort:

mutex_unlock(&early_suspend_lock);

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: