I built a custom kernel on my host Ubuntu on which I enabled some modules. Here is what I did:
make -C kernel/kernel-5.10/ ARCH=arm64 O=$KERNEL_OUT LOCALVERSION=-tegra CROSS_COMPILE=${CROSS_COMPILE} tegra_defconfig
make -C kernel/kernel-5.10/ ARCH=arm64 O=$KERNEL_OUT LOCALVERSION=-tegra CROSS_COMPILE=$CROSS_COMPILE menuconfig
→ I enabled here the modules I wanted
Compiled the kernel :
make -C kernel/kernel-5.10/ ARCH=arm64 O=$KERNEL_OUT LOCALVERSION=-tegra CROSS_COMPILE=${CROSS_COMPILE} -j12 Image
make -C kernel/kernel-5.10/ ARCH=arm64 O=$KERNEL_OUT LOCALVERSION=-tegra CROSS_COMPILE=${CROSS_COMPILE} -j12 dtbs
make -C kernel/kernel-5.10/ ARCH=arm64 O=$KERNEL_OUT LOCALVERSION=-tegra CROSS_COMPILE=${CROSS_COMPILE} -j12 modules
make -C kernel/kernel-5.10/ ARCH=arm64 O=$KERNEL_OUT LOCALVERSION=-tegra INSTALL_MOD_PATH=$KERNEL_MODULES_OUT modules_install
I then copied :
kernel_out/arch/arm64/boot/Image in my Jetson /boot/Image
Copied content of KERNEL_MODULES in Jetson /lib/modules
It did not work. The modules I enabled are still not loaded (and don’t even exist).
When I went deeper, I realized that some of the modules compiled were NOT in the KERNEL_MODULES folder, but inside the kernel one : for instance: ./kernel_out/net/ipv4/ah4.o
Did I do something wrong ? How should I correct it ?
To start with, did you set CONFIG_LOCALVERSION" to “-tegra”? If not, then even if it worked, it would fail to load (when using that module with the original Image). The rest seems ok, except that you shouldn’t have copied the Image file for installing only a module.
Some notes…
Module search location is determined via the output of the command “uname -r”. That output has a prefix equal to the kernel source version, and a suffix equal to the “CONFIG_LOCALVERSION”. So if your original kernel version is 5.10.0 (I don’t know if that is the exact release, adjust if not), and if CONFIG_LOCALVERSION is “-tegra”, then the search location is here: /lib/modules/$(uname -r)/kernel
equivalent for this case: /lib/modules/5.10.0-tegra/kernel
Now if you built that kernel without the “-tegra” suffix (CONFIG_LOCALVERSION), and installed the new modules to the original module directory, then no module would be found. That’s because with that missing “-tegra” suffix, the search location becomes: /lib/modules/5.10.0/kernel
I advise people to always leave the original kernel Image and use it as a backup if they are going to modify the Image itself. However, you started with tegra_defconfig, which means that after adding in CONFIG_LOCALVERSION, it is a match for the original kernel (assuming a default kernel). If, while in menuconfig, you only added features or removed features via the “=m” (as a module) edit, then your original Image should be left alone and only module files should go in place.
Much of the official documentation is designed around installing to the flash content, and then flashing with that new content. If you are just working on the kernel of a working system, and don’t plan to flash it, then typically you will just work with file copies (there are exceptions, especially if security fuses are burned, but SD card models don’t have security fuses to burn).
On the host PC, do you still have the modules_install location? Under that, what subdirectory do you see within its “lib/modules/”? Is it something like 5.10.0?
When you used menuconfig, did you add features via the “m” button on the keyboard (implying in the form of a module)? Or did you use the “y” key to add features (meaning integrated to the Image)?
Not all features can be a module. However, when modifying an existing setup, one should always use a module if possible, unless you have a good reason for it.
Does your Jetson still boot? If so, what is the output of “uname -r”?
Thank you for your answer.
It seems to be working.
I guess this is more a generic linux question, do I need to copy the new kernel sources if I set the module as “built-in” (y) instead of “loadable” (m) ?
The story behind this is that both modules and “integrated” features are part of the kernel. However, a module sort of plugs in to the kernel by a dynamic loading interface, while the other features are always there. Answering with “=m” builds a loadable module, and answering with “=y” puts the feature in the Image file without the ability to unload or load (it is the Image file which is performing the loading of modules).
Modules might depend on features either integrated into the Image, or they might depend on features which other modules provide. If you alter where a dependency is located, then chances are you need to install both the Image and the modules. If you are just adding modules, then even if you add several modules (they might be independent, or they might be parts of a chain of dependencies), it is unlikely you need to change the Image itself. Borrowing from molecular biology, you could say that modules have an ABI which fits like “a lock and key”, with a specific signature or shape, and that if the integrated features of the Image are constant, then that signature will still be compatible. Changing to/from “=y” will likely change the signature and force rebuilding modules.
So any time you can start with the original configuration, and add or change only the modular (“=m”) features, you only need to copy over module files. Changing something with “=y” (integrated) implies you most likely need to reinstall everything.