How can we customize the built-in driver load order (to make some built-in driver module load first, and the dependent module load later)?
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.
depmod examines the symbols exported and required by each module and does a topological sort on them that modprobe can later use to load modules in the proper order. Requiring the symbols from modules you wish to be dependent on is enough for it to do the right thing.
Correct module order and dependencies are handled by modprobe, even within the initrd.
Recently i got this problem my charger driver is having dependency on ADC driver so before loading ADC driver charger driver has loaded and checking for adc phandle which is defined in DTS file and has to intialize by ADC driver. its got resolved by changing the order of the module in drivers/Makefile
Related
I'm using User Mode Linux and I'm redefining some I/O memory related functions. The idea it's that any function that is called from a list of our own kernel modules will be handled differently from the rest of the modules.
Is that possible to know whichy module is calling (kernel module name would be enough) a function like writel?
Libunwind defines a portable and efficient C programming interface (API) to determine the call-chain of a program (http://savannah.nongnu.org/projects/libunwind).
/proc/modules file displays a list of all modules loaded into the kernel along with their sizes and memory offsets.
I have a simple loadable kernel module which controls an LED by providing blinkingPeriod, on/off features etc...
The device is present at /sys/led , and functions fine.
I have provided an input paramater for the command line which takes in which GPIO the LED is connnected to.
Now I want to reuse the same kernel module, for an additional number of LED's, however I cannot load the module with insmod for additional LED's with a different command line parameter, since an error is thrown:
Error: could not insert module - File exists.
I know this is telling me that I cannot load the same module twice, but what is the best approach when trying to provide LKM's for multiple devices ?
The only solution I can think of is to re-write a LKM for each individual LED/device which hardly seems efficient, or pack all of the LED's in one LKM which isn't very scalable/portable.
Does anyone have any comments on the best approach.
Thanks in advance.
What you should do is:
- adding support for multiple LEDs in your module
- stop using the module parameters to configure the GPIO
- implement a sysfs interface to allow instantiating LEDs. I would use something like gpiolib.
An even better solution would be to use device tree if your platform supports it.
However, your driver is probably not needed and you can surely already do want you want with the leds-gpio and leds-pwm drivers.
Can anyone explain me in simple terms the following thing.
How Linux drivers are loaded into kernel space?
Which functions are exported, after drivers being loaded?
How driver functions are called?
Normally you will use insmod or modprobe userspace application to load module (and possibly its dependencies in case of the 2nd one). Both of them do the same under the hood to actually load single module - they read the file into memory and use init_module system call, providing address of memory where this module was loaded. This call tells kernel that module should be loaded.
Now kernel modules are actually ELF files and are not much different from shared libraries used in userspace. The kernel has an equivalent of shared library linker, that will parse those files, get a list of symbols that are provided by it, updating the list of functions known to kernel. It will also check if all the symbols that this module needs are already in the kernel and do proper relocations. One of the last thing that it will do is to call initialization function in the module.
Note that you cannot compile the kernel that will directly call any function that is provided by module. Similarly, you can call any function provided by a module in another module before loading the first one. Kernel will refuse to load any module with symbols that are not known. Most of the modules will, however, register its functions as some kind of callbacks that can be called indirectly.
I have a hard time understanding the exact usage of MODULE_DEVICE_TABLE(usb, id_table)
AFAIK this will generate the map files that will be used later by modprobe whenever a new device is inserted, it will match it against those map files and load the module if it matches.
But my misunderstanding is "isn't the module loaded anyway?"
I mean I already loaded it when I did insmod module-name. or am I missing something?
It is usually used to support hot-plugging, by loading/inserting the driver for a device if not already loaded.
There is a similar question here: Detect the presence of a device when it's hot plugged in Linux
(From my ans)
It works as follows:
Each driver in the code exposes its vendor/device id using:
MODULE_DEVICE_TABLE(of, omap_mcspi_of_match);
At compilation time the build process extracts this infomation from all the drivers and prepares a device table.
When you insert the device, the device table is referred by the kernel and if an entry is found matching the device/vendor id of the added device, then its module is loaded and initialized.
According to Linux Device Drivers:
MODULE_DEVICE_TABLE is used to generate map files by depmod program;
When device is hot-plugged, bus driver generates hotplug event. Kernel calls /sbin/hotplug with appropriate environmental variables set;
Given map files and information from environment, /sbin/hotplug decides which module to load and actually loads it. If the module is already loaded, it's OK.
I should mention again that this mechanism just ensures that needed module is in-place when device is plugged. That doesn't link module with that device or anything else. Just loads module.
To check if driver is OK for specific device, match() function from bus_type is used.
Here is how I understands the things [Xbuntu 14.04 compatible].
Once we wrote a module, we can either load it manually, or automatically.
Manually -> insmod modulename.ko or modprob modulename.ko
Automatically-> There are multiple ways.
copy to /lib/modules/`uname -r`/kernel/modulename.ko and update /etc/modules. System will load the module while booting.
Write a script/command to load the module.ko for an specific harware add/change/remove event in a udev rule /etc/udev/rules.d/10-local.rules. You can do both load/unload using this method.
Code your module with MODULE_DEVICE_TABLE registration. Then load your modulename.ko once and run depmod command [sudo depmod -a] to add the new module to /lib/modules/3.16.0-34-generic/modules.alias /lib/modules/3.16.0-34-generic/modules.dep files. As I know, system will load only if the module is not loaded.
You can monitor module loading/unloading using udev events using :
udevadm monitor
command.
Thanks to every one,
This is the question asked in one of the interview i faced.
I have a Linux device driver which was compiled in Linux kernel version 2.6.I would like to port the same driver in a Linux PC which has kernel 3.X without compiling in new versions.
Is it possible ? If it is possible please let me know how. If it is not possible please let me know why not ?
Thanks & Regards
Siva
No you cannot port module which is compiled for one version to other version.
The reason is as follows
Modules are strongly tied to the data structures and function prototypes defined in a particular kernel version;
the interface seen by a module can change significantly from one kernel version to
the next. This is especially true of development kernels, of course
The kernel does not just assume that a given module has been built against the
proper kernel version. One of the steps in the build process is to link your module
against a file (called vermagic.o) from the current kernel tree; this object contains a
fair amount of information about the kernel the module was built for, including the
target kernel version, compiler version, and the settings of a number of important
configuration variables. When an attempt is made to load a module, this information
can be tested for compatibility with the running kernel. If things don’t match,
the module is not loaded; instead, you see something like:
# insmod hello.ko
Error inserting './hello.ko': -1 Invalid module format
A look in the system log file (/var/log/messages or whatever your system is configured
to use) will reveal the specific problem that caused the module to fail to load.
Kernel interfaces often change between releases. If you are writing a module that is
intended to work with multiple versions of the kernel (especially if it must work
across major releases), you likely have to make use of macros and #ifdef constructs
to make your code build properly.
now it's not possible:
usually, a "driver" is a binary kernel-module
porting will involve code-changes to the kernel module. if you change the code, you need to compile it, in order to get a binary.
since kernel modules run in kernel space, it is crucial that they are robust. since parts of the kernel-API change every now and then, trying to use a module compiled for kernel-X with another kernel-Y, might either not load because of missing symbols (if you are lucky) or lead to a kernel panic because semantics have changed.
btw, all this is not really related to 2.6.x vs 3.y, but holds true for any kernel version
but then: of course in theory it is possible to "write" a kernel-module as binary code in your favourite hex-editor, without resorting to compilers and such. this would allow you to "port" a driver from one kernel to another without recompilation. i guess this is not for humans though...