Search code examples
linux-kerneldriversarm

Change the order that built in kernel drivers get initialized?


I'm targeting an embedded Linux 2.6.35.3 for a Freescale iMX53 Arm CPU board.

I need to change when all the various CAN bus related drivers (FlexCAN) get initialized and ready for use during the kernel boot process. I need the CAN bus to be initialized much sooner then it currently is so that I can send out some specific CAN raw messages a lot sooner before the user-space is ready for scripts to do the job.

How does one control WHEN the compiled (built-in) kernel modules/drivers get probed internally by the kernel during its boot up and init sequence.

I'm not talking about file system level .ko files that can be mod-probed in scripts.. this is way before that.

Sorry for my poorly formatted linux question.. i don't work in kernel space very often.. trying hack my way through this as fast as possible.


Solution

  • initcall ordering is defined here:

    http://lxr.free-electrons.com/source/include/linux/init.h#L194

    which is, for reference:

    /*
     * A "pure" initcall has no dependencies on anything else, and purely
     * initializes variables that couldn't be statically initialized.
     *
     * This only exists for built-in code, not for modules.
     * Keep main.c:initcall_level_names[] in sync.
     */
    #define pure_initcall(fn)               __define_initcall(fn, 0)
    
    #define core_initcall(fn)               __define_initcall(fn, 1)
    #define core_initcall_sync(fn)          __define_initcall(fn, 1s)
    #define postcore_initcall(fn)           __define_initcall(fn, 2)
    #define postcore_initcall_sync(fn)      __define_initcall(fn, 2s)
    #define arch_initcall(fn)               __define_initcall(fn, 3)
    #define arch_initcall_sync(fn)          __define_initcall(fn, 3s)
    #define subsys_initcall(fn)             __define_initcall(fn, 4)
    #define subsys_initcall_sync(fn)        __define_initcall(fn, 4s)
    #define fs_initcall(fn)                 __define_initcall(fn, 5)
    #define fs_initcall_sync(fn)            __define_initcall(fn, 5s)
    #define rootfs_initcall(fn)             __define_initcall(fn, rootfs)
    #define device_initcall(fn)             __define_initcall(fn, 6)
    #define device_initcall_sync(fn)        __define_initcall(fn, 6s)
    #define late_initcall(fn)               __define_initcall(fn, 7)
    #define late_initcall_sync(fn)          __define_initcall(fn, 7s)
    

    As module_init is #defined to be device_initcall, a general module with nothing dependent on it gets initialized towards the end of the sequence. To load your module early, you simply change its module_init call to something else that occurs earlier (like subsys_initcall, for example)

    Note: just switching the order on things can break other dependencies, and you can get in a catch-22 dependency loop from hell.