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.
But:
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
uname -r
command.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
The
make menuconfig
command 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 modifyMakefile
and setEXTRAVERSION = -chip
. After that,make kernelversion
should say4.4.138-chip
, exactly matching the output ofuname -r
command.Build the module.
make scripts prepare modules_prepare make -C . M=drivers/net/usb
In this command,
drivers/net/usb
is 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 modprobe
.
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.
Reference: Oleg Kokorin's answer to "How to recompile just a single kernel module?"