How to Compile Just One Kernel Module
I received two C.H.I.P computers in 2016. They come with Linux kernel 4.4.13, but the kernel had limited features. When I needed to use the fuse kernel module, I had to re-compile the entire kernel, which took a whole day. Two years later, I upgraded to a newer 4.4.138 kernel, built by community member kaplan2539. The kernel comes with more modules including fuse, which is a better situation than the original kernel.
Recently I acquired a cheap USB Ethernet adapter. When I plugged it in, the kernel recognizes a USB device:
chip@chip-b:~$ lsusb | grep Ethernet Bus 002 Device 002: ID 0fe6:9700 Kontron (Industrial Computer Source / ICS Advent) DM9601 Fast Ethernet Adapter
But there's no new NIC showing up in
ip link command.
A quick Google search of the USB ID
0fe6:9700 indicates that I need the dm9601 kernel module.
chip@chip-b:~$ sudo modprobe dm9601 modprobe: FATAL: Module dm9601 not found.
Do I have to spend a whole day re-compiling the kernel? It turns out that, I can build a single kernel module individually. After some trial and error, I figured out the exact procedure of doing so.
Obtain the kernel headers and the compiler, and download the kernel sources:
sudo apt install build-essential libncurses-dev linux-headers-4.4.138-chip curl -L https://github.com/kaplan2539/ntc-linux/archive/ntc-stable-mlc-4.4.138.tar.gz | tar xz
It's important that the header package and kernel sources both match the running kernel, which can be seen with
Copy the kernel "config" file into the kernel source directory. This file records how the kernel was configured when it was originally built, which serves as a starting point of the new compilation process.
cd ntc-linux-ntc-stable-mlc-4.4.138 cp /boot/config-4.4.138-chip ./.config
Copy the kernel "symbol" file into the kernel source directory as well. This file records what function names exist in the running kernel, so that our new module can link to them.
cp /usr/src/linux-headers-4.4.138-chip/Module.symvers ./
Load the original config file, and modify it.
make oldconfig make menuconfig
make menuconfigcommand brings up an interactive dialog, allowing me to select what kernel features I want. I followed the dialogs into "Device Drivers" - "Network device support" - "USB Network Adapters" menu, and changed "Davicom DM96xx based USB 10/100 ethernet devices" to "M", indicating this feature would be built as a module.
Since the running kernel version is
4.4.138-chip, I need to modify
EXTRAVERSION = -chip. After that,
make kernelversionshould say
4.4.138-chip, exactly matching the output of
Build the module.
make scripts prepare modules_prepare make -C . M=drivers/net/usb
In this command,
drivers/net/usbis the directory containing the dm9601 kernel module source code. This command would build all enabled kernel modules in that directory, not just dm9601.
Install the module.
sudo cp drivers/net/usb/dm9601.ko /lib/modules/4.4.138-chip/kernel/drivers/net/usb/ sudo depmod
At this point, I'm ready to load the module with
In fact, the module would be loaded automatically when I plug in the USB Ethernet adapter.
chip@chip-b:~$ dmesg | grep -i dm9601 [270352.048643] dm9601 2-1:1.0 eth0: register 'dm9601' at usb-1c14400.usb-1, Davicom DM96xx USB 10/100 Ethernet, 00:e0:4c:53:44:58 [270352.070843] usbcore: registered new interface driver dm9601 [270352.923157] dm9601 2-1:1.0 eth0: link up, 100Mbps, full-duplex, lpa 0xFFFF
The whole process took less than an hour, which is a lot less than re-compiling the entire kernel.