module_init模块加载顺序

版权声明:本文为博主原创文章,欢迎转载,转载请注明转载地址 https://blog.csdn.net/u012839187/article/details/84873131

[第二次修改:linux中有各个模块init函数放在init断中。最先init的设备(驱动最先被注册),睡眠唤醒的时候最后被suspend最先被resume。]

需求:dsi这边的驱动需要比我一个挂载在i2c上的设备晚.

也就是说.平台端要先初始化i2c从设备以后,再输出mipi信号.

平台:qcom 8930

 做法

1.修改dsi

--- a/drivers/video/msm/mdss/mdss_dsi.c
+++ b/drivers/video/msm/mdss/mdss_dsi.c
@@ -3180,6 +3180,7 @@ static int mdss_dsi_ctrl_probe(struct platform_device *pdev)
        static int te_irq_registered;
        struct mdss_panel_data *pdata;
+//    msleep(5000);
+//    mdelay(5000);
+    printk("mdss ctrl probe sleep 5s\n");
        if (!pdev || !pdev->dev.of_node) {
                pr_err("%s: pdev not found for DSI controller\n", __func__);
                return -ENODEV;
@@ -4357,6 +4358,7 @@ static int __init mdss_dsi_driver_init(void)
        return ret;
 }
 module_init(mdss_dsi_driver_init);
+//late_initcall(mdss_dsi_driver_init);
 
 
 static int mdss_dsi_ctrl_register_driver(void)
@@ -4377,6 +4379,7 @@ static int __init mdss_dsi_ctrl_driver_init(void)
        return ret;
 }
 module_init(mdss_dsi_ctrl_driver_init);
+//late_initcall(mdss_dsi_ctrl_driver_init);

msleep与mdelay都试过。不行。这个线程delay导致整个probe流程都不行。方法一失败

将module_init的逻辑改为late_initcall 。mdss_dsi这边确实会往后推。但是mdss逻辑probe太多。如果不全部往后推。系统panic挂掉。方法二也失败。

module_init的顺序其实如下

#define module_init(x)     __initcall(x);              //include\linux\init.h

#define __initcall(fn) device_initcall(fn)

#define device_initcall(fn)                 __define_initcall("6",fn,6)

#define __define_initcall(level,fn,id) \

         static initcall_t __initcall_##fn##id __used \

         __attribute__((__section__(".initcall" level ".init"))) = fn

[第一次更新:后来去试了一下,因为我们的从设备仅仅依赖gpio,i2c总线的初始化,其实我们可以使用rootfs_initcall即可将我们的i2c从设备的初始化顺序拉到mdss_dsi之前]

言归正传,INITCALLS在__initcall_start = .与__initcall_end = .之间,
表示INITCALLS宏内涵的相关段代码顺序存放在这里,module_init所代表段的镶嵌其中

#define pure_initcall(fn)          __define_initcall("0",fn,0)
#define core_initcall(fn)          __define_initcall("1",fn,1)
#define core_initcall_sync(fn)        __define_initcall("1s",fn,1s)
#define postcore_initcall(fn)           __define_initcall("2",fn,2)
#define postcore_initcall_sync(fn) __define_initcall("2s",fn,2s)
#define arch_initcall(fn)          __define_initcall("3",fn,3)
#define arch_initcall_sync(fn)        __define_initcall("3s",fn,3s)
#define subsys_initcall(fn)              __define_initcall("4",fn,4)
#define subsys_initcall_sync(fn)    __define_initcall("4s",fn,4s)
#define fs_initcall(fn)                     __define_initcall("5",fn,5)
#define fs_initcall_sync(fn)            __define_initcall("5s",fn,5s)
#define rootfs_initcall(fn)        __define_initcall("rootfs",fn,rootfs)
#define device_initcall(fn)              __define_initcall("6",fn,6)
#define device_initcall_sync(fn)    __define_initcall("6s",fn,6s)
#define late_initcall(fn)           __define_initcall("7",fn,7)
#define late_initcall_sync(fn)         __define_initcall("7s",fn,7s)

MODULE是在kernel 根目录下面的makefile中定义的
KBUILD_AFLAGS_MODULE  := -DMODULE
KBUILD_CFLAGS_MODULE  := -DMODULE

因此如果在build module的时候会定义MODULE。而定了了MODULE的话,则下面的都是同一个优先级
#define early_initcall(fn)        module_init(fn)
#define core_initcall(fn)        module_init(fn)
#define core_initcall_sync(fn)        module_init(fn)
#define postcore_initcall(fn)        module_init(fn)
#define postcore_initcall_sync(fn)    module_init(fn)
#define arch_initcall(fn)        module_init(fn)
#define subsys_initcall(fn)        module_init(fn)
#define subsys_initcall_sync(fn)    module_init(fn)
#define fs_initcall(fn)            module_init(fn)
#define fs_initcall_sync(fn)        module_init(fn)
#define rootfs_initcall(fn)        module_init(fn)
#define device_initcall(fn)        module_init(fn)
#define device_initcall_sync(fn)    module_init(fn)
#define late_initcall(fn)        module_init(fn)
#define late_initcall_sync(fn)        module_init(fn)

#define console_initcall(fn)        module_init(fn)
#define security_initcall(fn)        module_init(fn)
--------------------- 
作者:tiantao2012 
来源:CSDN 
原文:https://blog.csdn.net/tiantao2012/article/details/54311085 
版权声明:本文为博主原创文章,转载请附上博文链接!

遍历相同优先级的initcall时,是按照地址从低到高进行的,因此调用顺序就是编译时连接到initcall section的顺序,通过System.map可以查到顺序,例如:

62054:ffffffc000e61c38 T __initcall_start

62055:ffffffc000e61c38 t __initcall_trace_init_flags_sys_exitearly

62057:ffffffc000e61c40 t __initcall_trace_init_flags_sys_enterearly

62058:ffffffc000e61c48 t __initcall_init_hw_perf_eventsearly

62059:ffffffc000e61c50 t __initcall_cpu_suspend_initearly

链接顺序可以通过调整Makefile中的.o文件的先后进行调整。

最后用的方法是:查看kernel_log 发现在kernel_log之前有一个i2c上的从设备probe成功了。

将我的驱动代码放在这个从设备的代码路径。make bootimage 烧录。解决

翻阅了System.map以后从我看到的情况来说。最早的probe顺序是放在pin脚的probe之后,毕竟这个时候驱动对外部的依赖基本满足.

猜你喜欢

转载自blog.csdn.net/u012839187/article/details/84873131