kernel驱动由于资源的使用,经常遇到某一个driver的初始化依赖另一个driver是否初始化完成。
比如touch依赖i2c。
本篇总结两种解决方案。
方法一,定义不同级别的driver ,使被依赖的driver高优先初始化
内核为满足不同初始化等级,设计了1~7个等级,以及1s~7s个等级。共14个等级。如下图:
常用的module init 宏定义如下:
#define module_init(x)__initcall(x) include/linux/module.h
具体原理参考 here
方法二,利用defer probe机制, 推迟初始化driver
kernel driver初始化过程中,如果遇到依赖的资源没有准备好,返回EPROBE_DEFER ,则1~7等级的driver将会在1s~7s对应等级中再次probe 。
kernel probe过程参考 here
defer probe实现原理如下,
EPROBE_DEFER返回值的module driver 加入到probe_pending_list ,
同一级别driver probe过程中,local_trigger_count与defered_trigger_count相等,不会触发defer probe
注意:
如下图really_probe函数中返回EPROBE_DEFER同时通过devres_release_all释放devm_xxx申请的硬件资源。
sysfs , drvdata 等等也释放。
defer probe是如何再次启动的呢???
如上图,定义1s~7s对应等级defererd probe driver, 及late_initcall driver module:deferred_probe_enable_fn ,
该函数会触发defer probe动作。
如下图,从probe_pending_list取出再probe 。