kernel syscore

syscore作为低功耗流程的一部分,其涉及的文件主要有syscore_ops.h和syscore.c,这一级别的回调函数是在完全屏蔽中断的场景下进行的。

1、主要结构体struct syscore_ops,该结构体是syscore操作的对象类型。


   
   
  1. struct syscore_ops {
  2. struct list_head node; //用于链表控制,注册和删除syscore对象时操作此链表完成
  3. int (*suspend)( void); //睡眠流程时回调函数
  4. void (*resume)( void); //唤醒流程时回调函数
  5. void (*shutdown)( void); //这一级别的回调函数主要用于系统级的重启、停止或者掉电时才会使用
  6. };

2、主要接口:


   
   
  1. extern void register_syscore_ops(struct syscore_ops *ops); //注册syscore回调函数
  2. extern void unregister_syscore_ops(struct syscore_ops *ops); //取消注册的回调函数
  3. #ifdef CONFIG_PM_SLEEP
  4. extern int syscore_suspend(void); //回调注册的syscore对象的suspend回调函数
  5. extern void syscore_resume(void); //回调注册的syscore对象的resume回调函数
  6. #endif
  7. extern void syscore_shutdown(void); //回调注册的syscore对象的shutdown回调函数

3、具体实现,syscore.c

1)全局变量


   
   
  1. static LIST_HEAD(syscore_ops_list); //初始化控制链表头结点,统一管理注册的syscore对象
  2. static DEFINE_MUTEX(syscore_ops_lock); //访问上述链表时,通过此互斥信号量来互斥访问

2)register_syscore_ops:其他组件主要通过此接口来注册回调函数,我们可以看到,把注册的对象存放在了syscore_ops_list链表中。


   
   
  1. /**
  2. * register_syscore_ops - Register a set of system core operations.
  3. * @ops: System core operations to register.
  4. */
  5. void register_syscore_ops(struct syscore_ops *ops)
  6. {
  7. mutex_lock(&syscore_ops_lock);
  8. list_add_tail(&ops->node, &syscore_ops_list);
  9. mutex_unlock(&syscore_ops_lock);
  10. }

3)unregister_syscore_ops:与register_syscore_ops功能相反,取消注册,从控制链表中删除。


   
   
  1. /**
  2. * unregister_syscore_ops - Unregister a set of system core operations.
  3. * @ops: System core operations to unregister.
  4. */
  5. void unregister_syscore_ops(struct syscore_ops *ops)
  6. {
  7. mutex_lock(&syscore_ops_lock);
  8. list_del(&ops->node);
  9. mutex_unlock(&syscore_ops_lock);
  10. }

4)syscore_suspend:该接口回调所有注册对象的suspend接口,该接口在suspend.c的suspend_enter函数中被调用,执行cpu掉电前的最后阶段操作。


   
   
  1. /**
  2. * syscore_suspend - Execute all the registered system core suspend callbacks.
  3. *
  4. * This function is executed with one CPU on-line and disabled interrupts.
  5. */
  6. int syscore_suspend(void)
  7. {
  8. struct syscore_ops *ops;
  9. int ret = 0;
  10. pr_debug( "Checking wakeup interrupts\n");
  11. /* Return error code if there are any wakeup interrupts pending. */
  12. ret = check_wakeup_irqs();
  13. if (ret)
  14. return ret;
  15. WARN_ONCE(! irqs_disabled(),
  16. "Interrupts enabled before system core suspend.\n"); //我们可以看到,如果此时中断没有屏蔽掉,会有警告产生
  17. list_for_each_entry_reverse(ops, &syscore_ops_list, node) //按照链表逆序执行各个注册对象的suspend回调函数
  18. if (ops->suspend) {
  19. if (initcall_debug)
  20. pr_info( "PM: Calling %pF\n", ops->suspend);
  21. ret = ops-> suspend();
  22. if (ret)
  23. goto err_out;
  24. WARN_ONCE(! irqs_disabled(),
  25. "Interrupts enabled after %pF\n", ops->suspend);
  26. }
  27. return 0;
  28. err_out:
  29. pr_err( "PM: System core suspend callback %pF failed.\n", ops->suspend);
  30. list_for_each_entry_continue(ops, &syscore_ops_list, node) //如果有失败的,则执行已经执行过suspend回调的对象的resume回调
  31. if (ops->resume)
  32. ops-> resume();
  33. return ret;
  34. }
  35. EXPORT_SYMBOL_GPL(syscore_suspend);

5)syscore_resume:执行注册对象的resume回调,在suspend.c的唤醒流程中被调用


   
   
  1. /**
  2. * syscore_resume - Execute all the registered system core resume callbacks.
  3. *
  4. * This function is executed with one CPU on-line and disabled interrupts.
  5. */
  6. void syscore_resume(void)
  7. {
  8. struct syscore_ops *ops;
  9. WARN_ONCE(! irqs_disabled(),
  10. "Interrupts enabled before system core resume.\n");
  11. list_for_each_entry(ops, &syscore_ops_list, node)
  12. if (ops->resume) {
  13. if (initcall_debug)
  14. pr_info( "PM: Calling %pF\n", ops->resume);
  15. ops-> resume();
  16. WARN_ONCE(! irqs_disabled(),
  17. "Interrupts enabled after %pF\n", ops->resume);
  18. }
  19. }


6)syscore_shutdown:该接口正常睡眠流程中不涉及调用,主要在sys.c中调用,涉及系统重启、halt等流程。


   
   
  1. /**
  2. * syscore_shutdown - Execute all the registered system core shutdown callbacks.
  3. */
  4. void syscore_shutdown(void)
  5. {
  6. struct syscore_ops *ops;
  7. mutex_lock(&syscore_ops_lock);
  8. list_for_each_entry_reverse(ops, &syscore_ops_list, node)
  9. if (ops->shutdown) {
  10. if (initcall_debug)
  11. pr_info( "PM: Calling %pF\n", ops->shutdown);
  12. ops-> shutdown();
  13. }
  14. mutex_unlock(&syscore_ops_lock);
  15. }








 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值