What is the Linux built-in driver load order?
Built-in drivers wont be loaded, hence built-in. Their initialization functions are called and the drivers are activated when kernel sets up itself. These init functions are called in init/main.c::do_initcalls()
. All init calls are classified in levels, which are defined in initcall_levels
and include/linux/init.h
These levels are actuall symbols defined in linker script (arch/*/kernel/vmlinux.lds.*
). At kernel compile time, the linker collects all function marked module_init()
or other *_initcall()
, classify in levels, put all functions in the same level together in the same place, and create like an array of function pointers.
What do_initcall_level() does in the run-time is to call each function pointed by the pointers in the array. There is no calling policy, except levels, in do_initcall_level, but the order in the array is decided in the link time.
So, now you can see that the driver's initiation order is fixed at the link time, but what can you do?
- put your init function in the higher level, or
- put your device driver at the higher position in
Makefile
The first one is clear if you've read the above. ie) use early_initcall() instead if it is appropriate.
The second one needs a bit more explanation. The reason why the order in a Makefile
matter is how the current kernel build system works and how the linkers works. To make a long story short, the build system takes all object files in obj-y
and link them together. It is highly environment dependent but there is high probability that the linker place first object file in the obj-y
in lower address, thus, called earlier.
If you just want your driver to be called earlier than other drivers in the same directory, this is simplest way to do it.
Change the order that built in kernel drivers get initialized?
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.
Changing Linux kernel module boot order
I was able to solve the problem. It turns out that order to make *_initcall()
's work, the module should be statically linked, therefore, I set;
CONFIG_DRM_VC4=y
CONFIG_SND=y
CONFIG_SNC_SOC=y
This loses a couple of milliseconds of boot time, but now /dev/fb0 loads at around ~0.3 seconds, rather than ~9 seconds.
Are builtin driver always prioritized over loadable modules?
I found the answer in the meanwhile and I documented it here:
http://0x0001.de/linux-driver-loading-registration-and-binding
To make a long story short:
Yes, builtin drivers are in general prioritized over loadable drivers.
Just because they are registered first and "first comes first serves" principle while binding.
Driver probe order in Linux Kernel
According to this SO answer, the order in the makefile is the correct approach to this.
See also this other SO answer for a detailed explanation of the mechanisms.
How to change kernel module loading order in yocto
You can also use the KERNEL_MODULE_AUTOLOAD variable. It is working for me.
AddKERNEL_MODULE_AUTOLOAD += "<module-name>"
in your local.conf
Difference between Linux Loadable and built-in modules
Linux kernel supports inserting of modules (aka device drivers) in two ways:
- Built-in kernel modules - When the kernel is booted up, the kernel automatically inserts this driver in to the kernel (it's more like it is already part of the kernel code).
- Loadable kernel module (LKM) - A driver that is not automatically loaded by the kernel, the user can insert this module at run-time by
insmod driver.ko
ormodprobe driver.ko
The advantage the loadable modules have over the built-in modules is that you can load unload them on run-time. This is good if you are working on a module and you need to test it. Every time you test it and you need to make changes to it, you can easily unload it (rmmod driver.ko
or modprobe -r driver.ko
) and then after making changes, you can insert it back. But for the built-in modules if you need to make any changes in the module then you need to compile the whole kernel and then reboot the system with the new image of the kernel.
Configuration:
You can configure a module to be either of the two by editing the .config
file in the root folder of your kernel source:
DRIVER_1=y // y indicate a builtin module
DRIVER_1=m //m inicates a loadable module
Note: lsmod
displays only the dynamically loaded modules
not the built-in
ones.
Read on: http://www.tldp.org/HOWTO/Module-HOWTO/x73.html
Related Topics
How to Store the Output of a Git Command in a Variable
How to Start Redis-Server on a Different Port Than the Default Port 6379 in Ubuntu
Get Rid of "Gcc - /Usr/Bin/Ld: Warning Lib Not Found"
Fallocate() Command Equivalent in Os X
Running Docker on Ubuntu: Mounted Host Volume Is Not Writable from Container
How to Return Spawned Process Exit Code in Expect Script
Gdb Break When Program Opens Specific File
Docker Not Responding to Ctrl+C in Terminal
What Is the Use of File Descriptor 255 in Bash Process
How to Replace to Apostrophe ' Inside a File Using Sed
Dynamic Loading and Weak Symbol Resolution
How to View and Edit the Ephemeral Port Range on Linux
Nginx: [Emerg] Unknown Directive " " in /Etc/Nginx/Sites-Enabled/Example.Com:3
Xampp: Another Web Server Daemon Is Already Running
Ldd Says "Not Found" Even Though Library Is in My Ld_Library_Path