Removing a device driver module that was statically compiled - linux

I compiled the linux kernel with serial device driver statically i.e obj-y.
Now I'm working on a simple serial driver and I want to test it, but since the module is loaded when the kernel boots up, the IO port regions (0x3f8 and onwards) are registered to the serial module. I need to remove(unregister) it so that I can allocate it to my driver.
So, is there any way to remove the statically linked device driver ? or should I recompile the whole kernel :/

You should recompile the whole kernel and make this driver an obj-m.
Once it's loaded (either done automatically by modprobe or manually with insmod), you may remove it (using rmmod), modify the code, compile it again and load it again.
Of course, if there was some critical error that was not handled properly during the driver's operation, the whole kernel will be in an unstable state and you will have to reboot (until you fix what causes this).

Related

Difficulties backporting Linux kernel driver

I'm trying to backport a Linux kernel driver (the PCF85063 RTC, specifically) from the 3.17+ kernel into a 3.14 kernel I'm using, and I'm running into a few issues. I don't have any experience with adding/modifying kernel drivers, so I'm not sure if what I've done so far is correct:
I took the rtc-pcf85063.c file from the newer kernel, and added it to my drivers/rtc/ directory in the kernel source.
I added the following line to drivers/rtc/Makefile:
obj-$(CONFIG_RTC_DRV_PCF85063) += rtc-pcf85063.o
I added this snippet to drivers/rtc/Kconfig
config CONFIG_RTC_DRV_PCF85063
tristate "NXP PCF85063"
help
If you say yes here, you get support for the NXP PCF85063 RTC.
From my understanding, that should be all it takes to add driver support for the new RTC. When I execute make menuconfig, I can see my new RTC entry under Device Drivers > Real Time Clock, labeled as NXP PCF85063 with the correct help information. So it's clear that the third step above was successful.
The problem is, when I include this driver (by selecting it in menuconfig and saving/exiting) in my kernel build, it doesn't actually get built in. If I deploy the kernel and read /lib/modules/3.14.17/modules.builtin, the new driver is nowhere to be found. Also, if I check drivers/rtc/ after building the kernel, there are object files for every RTC driver included through menuconfig except the new one; the kernel isn't even compiling the driver.
I found one interesting thing that might give some hint as to what's going on. When I go to include/config in the linux source after running menuconfig, I have a bunch of directories, some of which correspond to drivers. There's an rtc directory, and when I navigate to include/config/rtc/drv, there's a header file for every RTC driver included in the build except the one I added.
The thing is, the header file corresponding to the new driver is in include/config; it's hidden away in include/config/config/rtc/drv. It looks like menuconfig isn't treating the new driver as a regular RTC driver.
I know this is a pretty specific problem, but I was hoping that someone might notice that I'm missing a step or going about this the wrong way. Thanks.

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.

can not find the driver in /proc/device

I want to compile a device driver in kernel, and I configure it with *, (not in module ). After the compilation, I can't see the device in /proc/device. Also I check the output of make bzImage, the driver has been compiled. Do I need to delete the two lines:
module_init(mydriver_init);
module_exit(mydriver_exit);
There is not enough information to understand your problem. You should show some code.
Anyway, /proc/devices does not show all kernel module. It shows devices, maybe your driver is not registering a device.
You can put some printk() in your code and read it with the command dmesg from your terminal. If your read your print, your module is loaded.
Evan if you do not compile a module as module, but you built it within the kernel, functions
module_init(mydriver_init);
module_exit(mydriver_exit);
must be there. mydriver_init will be executed when the kernel load your driver, module_exit will be executed when the kernel unload your driver.
The /proc/devices file which is read-only doesn't seem to be editable or viewable using editors like VIM. So try 'cat /proc/devices', your device may show up then.

Debugging kernel hang because of IOCTL calls

I am trying to make a kernel module which is working on 2.6.32 kernel to work on 3.6 kernel. We use IOCTL calls to update structures in Linux Kernel Module. These calls are working fine in 2.6.32 kernel.
When I try the same in 3.6 kernel I am facing kernel hang whenever ioctl calls are made from user-space application. Its a socket based interface not a file based interface hence we use the ioctl under struct proto_ops.
How can I debug this scenario as there is no core dump generated. To copy data from userspace I am using copy_from_user command.
Any pointers for debugging this scenario would be very helpful
ioctl() is one of the remaining parts of the kernel which runs under the Big Kernel Lock (BKL). In the past, the usage of the BKL has made it possible for long-running ioctl() methods to create long latencies for unrelated processes.
Follows an explanation of the patch that introduced unlocked_ioctl and compat_ioctl into 2.6.11. The removal of the ioctl field happened a lot later, in 2.6.36.
Explanation: When ioctl was executed, it took the Big Kernel Lock (BKL), so nothing else could execute at the same time. This is very bad on a multiprocessor machine, so there was a big effort to get rid of the BKL. First, unlocked_ioctl was introduced. It lets each driver writer choose what lock to use instead. This can be difficult, so there was a period of transition during which old drivers still worked (using ioctl) but new drivers could use the improved interface (unlocked_ioctl). Eventually all drivers were converted and ioctl could be removed.
compat_ioctl is actually unrelated, even though it was added at the same time. Its purpose is to allow 32-bit userland programs to make ioctl calls on a 64-bit kernel. The meaning of the last argument to ioctl depends on the driver, so there is no way to do a driver-independent conversion.
Reference: The new way of ioctl() by Jonathan Corbet

Upgrade a specific Linux Kernel Subsystem?

Is it possible to upgrade only a specific sub-system, say I2C, of the Linux Kernel.
For example:
Is it possible to include "Support for multiplexed I2C bus topologies (introduced in Kernel 2.6.36)" in the Kernel version 2.6.31.1.
No this is not possible.
A kernel module or 'subsystem' (eg the i2c module) is build for a specific kernel image, you cannot combine different kernel(module) versions.
If you are feeling lucky (depending on your kernel skills), you could:
download the source code of your kernel
Install compiler and friends
add the updated ic2 driver
Try to compile the module for your kernel version
Cross your fingers and load it into your own kernel...\
I do not have any experience with this, so I do not know whether this works or not. Of course, if the ic2 module requires other (updated) modules, you could be ending up with updating (almost) the complete kernel...

Resources