标签:
syscore作为低功耗流程的一部分,其涉及的文件主要有syscore_ops.h和syscore.c,这一级别的回调函数是在完全屏蔽中断的场景下进行的。
1、主要结构体struct syscore_ops,该结构体是syscore操作的对象类型。
struct syscore_ops {
struct list_head node;//用于链表控制,注册和删除syscore对象时操作此链表完成
int (*suspend)(void);//睡眠流程时回调函数
void (*resume)(void);//唤醒流程时回调函数
void (*shutdown)(void);//这一级别的回调函数主要用于系统级的重启、停止或者掉电时才会使用
};
2、主要接口:
extern void register_syscore_ops(struct syscore_ops *ops);//注册syscore回调函数 extern void unregister_syscore_ops(struct syscore_ops *ops);//取消注册的回调函数 #ifdef CONFIG_PM_SLEEP extern int syscore_suspend(void);//回调注册的syscore对象的suspend回调函数 extern void syscore_resume(void);//回调注册的syscore对象的resume回调函数 #endif extern void syscore_shutdown(void);//回调注册的syscore对象的shutdown回调函数
3、具体实现,syscore.c
1)全局变量
static LIST_HEAD(syscore_ops_list);//初始化控制链表头结点,统一管理注册的syscore对象 static DEFINE_MUTEX(syscore_ops_lock);//访问上述链表时,通过此互斥信号量来互斥访问
2)register_syscore_ops:其他组件主要通过此接口来注册回调函数,我们可以看到,把注册的对象存放在了syscore_ops_list链表中。
/**
* register_syscore_ops - Register a set of system core operations.
* @ops: System core operations to register.
*/
void register_syscore_ops(struct syscore_ops *ops)
{
mutex_lock(&syscore_ops_lock);
list_add_tail(&ops->node, &syscore_ops_list);
mutex_unlock(&syscore_ops_lock);
}
3)unregister_syscore_ops:与register_syscore_ops功能相反,取消注册,从控制链表中删除。
/**
* unregister_syscore_ops - Unregister a set of system core operations.
* @ops: System core operations to unregister.
*/
void unregister_syscore_ops(struct syscore_ops *ops)
{
mutex_lock(&syscore_ops_lock);
list_del(&ops->node);
mutex_unlock(&syscore_ops_lock);
}
4)syscore_suspend:该接口回调所有注册对象的suspend接口,该接口在suspend.c的suspend_enter函数中被调用,执行cpu掉电前的最后阶段操作。
/**
* syscore_suspend - Execute all the registered system core suspend callbacks.
*
* This function is executed with one CPU on-line and disabled interrupts.
*/
int syscore_suspend(void)
{
struct syscore_ops *ops;
int ret = 0;
pr_debug("Checking wakeup interrupts\n");
/* Return error code if there are any wakeup interrupts pending. */
ret = check_wakeup_irqs();
if (ret)
return ret;
WARN_ONCE(!irqs_disabled(),
"Interrupts enabled before system core suspend.\n");//我们可以看到,如果此时中断没有屏蔽掉,会有警告产生
list_for_each_entry_reverse(ops, &syscore_ops_list, node)//按照链表逆序执行各个注册对象的suspend回调函数
if (ops->suspend) {
if (initcall_debug)
pr_info("PM: Calling %pF\n", ops->suspend);
ret = ops->suspend();
if (ret)
goto err_out;
WARN_ONCE(!irqs_disabled(),
"Interrupts enabled after %pF\n", ops->suspend);
}
return 0;
err_out:
pr_err("PM: System core suspend callback %pF failed.\n", ops->suspend);
list_for_each_entry_continue(ops, &syscore_ops_list, node)//如果有失败的,则执行已经执行过suspend回调的对象的resume回调
if (ops->resume)
ops->resume();
return ret;
}
EXPORT_SYMBOL_GPL(syscore_suspend);
5)syscore_resume:执行注册对象的resume回调,在suspend.c的唤醒流程中被调用
/**
* syscore_resume - Execute all the registered system core resume callbacks.
*
* This function is executed with one CPU on-line and disabled interrupts.
*/
void syscore_resume(void)
{
struct syscore_ops *ops;
WARN_ONCE(!irqs_disabled(),
"Interrupts enabled before system core resume.\n");
list_for_each_entry(ops, &syscore_ops_list, node)
if (ops->resume) {
if (initcall_debug)
pr_info("PM: Calling %pF\n", ops->resume);
ops->resume();
WARN_ONCE(!irqs_disabled(),
"Interrupts enabled after %pF\n", ops->resume);
}
}
6)syscore_shutdown:该接口正常睡眠流程中不涉及调用,主要在sys.c中调用,涉及系统重启、halt等流程。
/**
* syscore_shutdown - Execute all the registered system core shutdown callbacks.
*/
void syscore_shutdown(void)
{
struct syscore_ops *ops;
mutex_lock(&syscore_ops_lock);
list_for_each_entry_reverse(ops, &syscore_ops_list, node)
if (ops->shutdown) {
if (initcall_debug)
pr_info("PM: Calling %pF\n", ops->shutdown);
ops->shutdown();
}
mutex_unlock(&syscore_ops_lock);
}
标签:
原文地址:http://blog.csdn.net/lixiaojie1012/article/details/45625699