Linux Driver Loading, Binding and Registration

Linux Driver Loading, Binding and Registration

In Linux we have two different types of how drivers find their way into the system. The first is builtin drivers, those drivers are compiled into the kernel image – they are always there and you cannot get rid of them easily (well, you can blacklist them). The other way is the way modules go. Modules are dynamically loaded extensions for the kernel, you can load and unload them as you wish.

In the following I will focus mainly on the latter and the HID subsystem.

How is a driver module loaded?

The kernel is sending out a so called uevent when a hotplug-capable device is plugged in (or removed). Udev (udevd) is listening to those events (via a Netlink-Socket) and is responsible to load the necessary driver modules. You can monitor the communication between the kernel an udev by running the following command

udevadmn monitor

How does udev load the modules?

Udev does itself invoke another programm called kmod (which is roughly the same as modprobe, modinfo, …), this is done by the following simple udev-rule located in /usr/lib/udev/rules.d/80-drivers.rules

DRIVER!="?*", ENV{MODALIAS}=="?*", RUN{builtin}="kmod load $env{MODALIAS}"

kmod is a builtin systemd tool (which you cannot simply call from userspace), as an argument it gets the so called modalias.

The modalias is nothing more but another name for the module to be loaded, but the „other name“ is not arbitrary, it is an unique hardware identifier.

Okay, but how does kmod know which modules to load?

Every driver (e.g. a HID driver) includes a list of fitting devices, the so called MODULE_DEVICE_TABLE, it looks something like the following

static const struct hid_device_id xpadneo_devices[] = {
	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, 0x02FD) },
	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, 0x02E0) },
	/* SENTINEL VALUE, indicates the end*/
	{ }
};

Out of this array of structs (and those of all other drivers) a list called modules.alias is generated (amongst others), its content looks like this:

alias hid:b0005g*v0000045Ep000002E0 hid_xpadneo
alias hid:b0005g*v0000045Ep000002FD hid_xpadneo

As you can see, the module hid_xpadneo has more than just one alias. When kmod gets passed any of those aliases (which simply represent hardware types) it loads the module hid_xpadneo.

Kmod equals modprobe in userspace. According to the explained aliases the following commands are therefore equal

modprobe hid:b0005g0001v0000045Ep000002E0
modprobe hid_xpadneo

The former one does in fact load all modules for which hid:b0005g0001v0000045Ep000002E0 is an alias for, hence if there are more than just one fitting modules all of them are loaded!

Registration

Whenever a new driver is loaded by udev it has to register itself at the bus master. How exactly is this registering done?

Each newly loaded driver does call a function called driver_register() which is another name for e.g. __hid_driver_register() (if it is a HID driver). Now here a function called bus_add_driver() is called.

The bus master does hold a list of drivers to which the new driver is now simply appended.

What does that mean for the priority?

The driver which is registered first at the bus is the one which is served when a fitting device is plugged in. Therefore bultin drivers (drivers which aren’t loadable modules but built into the kernel-image itself) are always served first, just because they are already registered at boot time. If there is more than one builtin driver for a specific device, the one which is linked first (according to the Makefile) is preferred. Read more about this binding below.

Binding

So now the driver is loaded into the system and it is registered at the bus master. But how is a device bound to the driver?

I will start at device_attach() which is called if a new device is recognized.

 * device_attach - try to attach device to a driver.
 * @dev: device.
 *
 * Walk the list of drivers that the bus has and call
 * driver_probe_device() for each pair. If a compatible
 * pair is found, break out and return.
 *
 * Returns 1 if the device was bound to a driver;
 * 0 if no matching driver was found;
 * -ENODEV if the device is not registered.

device_attach() calls the internal function __device_attach() which does check if the device already has a driver information (dev->driver) or is already bound to a driver. If the device is not already bound it calls device_bind_driver() for the given driver, or – if there is not yet any driver information, it calls __device_attach_driver() for each driver of the bus master.

Unglücklicherweise ist dieser Eintrag noch nicht ganz fertig, bitte habt ein wenig Geduld.

Unfortunately this entry is not yet finished – stay tuned.

  1. (device_bind_driver()) actually binds the device to the driver by calling driver_sysfs_add() here, then it calls driver_bound() (here) where finally the ‚bind‘ uevent is generated (here) which you can see via udevadm monitor.
  2. bus_for_each_drv(dev->bus, NULL, &data, __device_attach_driver) (defined here) does nothing else but calling __device_attach_driver() (here) for each driver until the first one is found that returns ‚1‘. In __device_attach_driver() then driver_match_device(drv, dev) and, if they match, driver_probe_device(drv, dev) is called. driver_probe_device() attempts to bind the device & driver together – to do that it calls really_probe() (defined here. really_probe() does a lot of things to bind device & driver together, it does e.g. call the drivers and busses probe() functions. When everything went fine and both do fit eachother, then dev->driver is set to the fitting driver which was registered at the bus, then the device is bound to the driver by calling driver_sysfs_add() and driver_bound()` is called as above.