Calling the kernel driver initialization function

On Linux, if device drivers are built as loadable kernel modules, then after inserting the device driver kernel module, the kernel calls the device driver init function, as indicated by the module_init() macro.

How does this work for device drivers that are statically compiled into the kernel? What is the name of the init function?

+4
source share
2 answers

The initial driver initialization procedure can still use the module_init() macro to declare this entry point. Or the driver may use device_initcall() when the driver will never be compiled as a loadable module. Or, to move its initialization very early in the boot sequence, the driver could use subsys_initcall() .

In include/linux/init.h sequence for invoking these initialization procedures is described as:

 /* initcalls are now grouped by functionality into separate * subsections. Ordering inside the subsections is determined * by link order. * For backwards compatibility, initcall() puts the call in * the device init subsection. * * The `id' arg to __define_initcall() is needed so that multiple initcalls * can point at the same handler without causing duplicate-symbol build errors. */ 

I assume that these subsections for device drivers correspond to subdirectories in the drivers directory of the source tree of the Linux kernel and that the order of the links is written in the embedded file of each subdirectory in drivers . Therefore, during kernel loading, the initialization procedure for each built-in driver is ultimately done by do_initcalls() in init/main.c .

The device driver initialization procedure is responsible for checking the system to ensure that the HW device really exists. The driver should not allocate any resources or register any devices when the probe fails.

UPDATE :
Passing the initcall_debug option on the kernel command line will cause temporary information to be printed on the console for each initcall. initcalls are used to initialize statically linked kernel drivers and subsystems and contribute a significant amount of time to the Linux boot process. The result looks like this:

 calling tty_class_init+0x0/0x44 @ 1 initcall tty_class_init+0x0/0x44 returned 0 after 9765 usecs calling spi_init+0x0/0x90 @ 1 initcall spi_init+0x0/0x90 returned 0 after 9765 usecs 

Link: http://elinux.org/Initcall_Debug

+5
source

As pointed out by comments in the init.h kernel

"module_init () will either be called during do_initcalls () (if built-in), or in the module insert time (if module).

If you look in init.h, you will see

define module_init (x) __initcall (x);

And if you watch carefully, then

define __initcall (fn) device_initcall (fn)

and

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

Thus, basically initializing the module leads to initcall ( NOTE: only for statically compiled modules ) only at boot time.

+2
source

Source: https://habr.com/ru/post/1439455/


All Articles