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); }
时间: 2024-10-10 07:13:01