Contents

Introduction

An "initcall" is the initialization function for a module which is statically
linked into the Linux kernel. Running of initcalls can consume a large amount of
time during bootup. However, some modules do not need to be initialized so early,
in order for the embedded device to become usable for its primary purpose. These
initcalls can be run later, after first boot (and possibly first use) has completed.

For example, many digital cameras have USB buses, which need to be initialized
in order for the camera to be used as a mass storage device (to download pictures
to a desktop computer). However, the USB buses do not need to be initialized
for the primary use of the camera, which is to take pictures. In order to be able
to take a picture as soon as possible after booting, initialization of the USB
system in the kernel can be deferred until after the primary boot sequence for the
camera.

Description

Using a short patch (available for kernel version 2.6.27) it is possible to avoid
running certain initcalls at bootup time. The way this patch works is that
the developer selects some initcalls that they want to defer and modifies
the declaration of those initcalls.

When the system is booted, those initcalls are not called in their normal sequence.
When the system is done with primary boot, an application from user space
triggers the calling of the deferred initcalls, using a flag in the /proc filesystem.

When the flag is set, the deferred initcalls are run, and the kernel memory
for the "init" segment is finally freed.

How to use

To use deferred initcalls, first you need to identify the modules
that are not required for the primary functionality of the product,
and which are taking too long to initialize. (See Initcall Debug for this.)

Using the example above of the digital camera and USB, you could identify
uhci_hcd_usb and ehci_hcd_init as two initcalls that could be deferred.

Change the module init routine declaration for the initcalls you wish to defer.
This is done in the Linux kernel source code. For example, change:

module_init(foo_init)

deferred_module_init(foo_init)

Modules marked like this are not initialized during kernel boot

After main init, do:

cat /proc/deferred_initcalls

This will cause the kernel to run all deferred initcalls.
Also the .init section memory is freed by kernel.
The contents of /proc/deferred_initcalls will return 0 if deferred initcalls were not yet run, and 1 otherwise on subsequent reads.

deferred USB initcall example

As a test, on an X86 desktop system, I deferred the initialization
of the USB subsystem on a 2.6.27 kernel, by using deferred_module_init
on the functions: ehci_hcd_init and uhci_hcd_init

This resulted in a total times savings of 530 milliseconds, during
the kernel boot phase. (Of course, this time was used subsequently
when the deferred initcalls were triggered later on.)