loadable kernel module (LKM) for multiple devices - linux

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.

Related

How to configure for building a kernel module same as loaded one

I'm trying to modify one of the Linux kernel drivers.
But when I tried to insmod, the kernel keeps making "unknown symbol" error message.
I think I configured something different from the original for build. :(
So here is my question.
How can I configure the exact the same config as the original module?
Is there any way to configure easily for a certain kernel image?
There are two possibilities for this error:
Unknown symbols suggests that you are using any symbol which can be FUNCTION or Variable in your Driver program that Kernel is not able to find while loading your module. when you do insmod of your driver, do dmesg and see what all Symbols, Kernel is not able to find.
It could be possible that in your modification of the driver, you by mistake have used some variable or function which are not defined anywhere. Look for any 'extern variables' or any spelling mistakes in your modified code ;).
Your Driver is dependent on some other module. Here, dependent meaning, there are few functions or variable which your driver is using which are loaded to Kernel by some other module. In that case, you have to load that module first and then your module.
Unknown symbols is not a config issue. Config issue would have given other error.
If you need more help on it, please paste the dmesg output here..
Regards.

Linux kernel module, concept of configuration and persistent state

I work on Linux kernel loadable module and I look for proper way to configure it and way to load/store binary data when module is loaded/unloaded. The module needs to read configuration data in time of loading, but it may change data and save them in run-time. I read on many places that reading/writing to file is not recommended and I also read that sysfs can be used for such purpose. Can be binary configuration data stored in sysfs ? Or exist more suitable solution ? Can you provide link to some example or doc where I can found some details about how to load/save persistent configuration by module ?
Peter
Maybe you can use the firmware interface in the module.
It should be able to load a binary file which include your settings with request_firmware(..)
I think it isn't required to write this binary file to the hardware...?
There are probably a lot of ways to do this. The way that leaps to my mind is with a character device and a script running in userspace. You could arrange that the script loads your module and then writes the binary data to the character device file created by the module. The script could proceed to loop on a read of the device file. When the module wants to export new state, it unblocks the read. The script then copies out the data, and repeats.

Hard time in understanding MODULE_DEVICE_TABLE(usb, id_table) usage

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.

What is the Linux built-in driver load order?

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

How can I get edge events via GPIO on Linux without a busy-loop?

I'm working an a system with embedded Linux (Kernel 2.6.31).
It is a AT91SAM9G20 chip inside, and some of the Pins are forwarded to the outside.
Now I want to use them as GPIO Inputs.
I read the gpio.txt documentation about using the GPIOs via filesystem, and that works very well 'til here. I connected some switches to the gpio-pins and I can see the result in /sys/class/gpio/gpioX/value. But now I'd like to react on a change without busy-waiting in a loop. (i.e echo "Switch1 was pressed").
I guess I need interrupts here, but I couldn't find out how to use them without writing my own kernel driver. I'm relatively new to Linux and C (I normally program in Java), so I'd like to handle the Interrupts via sysfs too. But my problem is, that there is no "edge"-file in my GPIO directory (I guess because this is only since Kernel version 2.6.33+). Is that right? Instead of "edge" I've got a uevent file in there, which is not described in gpio.txt.
In the gpio.txt documentation there was a Standard Kernel Driver mentioned: "gpio_keys". Is it possible to use this for my problem?
I guess it would be better to work with this driver than allowing a userspace program to manipulate kernel tasks.
I found a lot of codesnippets for writing my own driver, but I wasn't even able to find out which of the 600 gpio.h files to include, and how to refer to the library (cross compiler couldn't find the gpio.h file).
Sorry for newbie questions, I hope you could give me some advices.
Thanks in advance
See this for an example on how to do that. Basically, the thing you're missing is the usage of the select or poll system calls.

Resources