Kernel cross compile failing

HI,

Just got my Jetson TK1 board and am trying to build a new Kernel for it. Host system is Ubuntu 14.04 on x86 architecture.
I got the latest sources from developer.nvidia.com and unzipped to ~/jetson/kernel
I installed the 2014-05-29 CodeSourcery cross compiler and set up the PATH for it.

I then did.

cd ~/jetson
mkdir kernel-out
cd kernel
export ARCH=arm
export CROSS_COMPILE=arm-none-linux-gnueabi-
export TEGRA_KERNEL_OUT=~/jetson/kernel-out

On the target:

zcat /proc/config.gz > ~/config

Copied this config file to ~/jetson/kernel-out/.config

make O=$TEGRA_KERNEL_OUT menuconfig

Saved it without making changes to test my build process

make O=$TEGRA_KERNEL_OUT zImage

It all fell over here:

CC      drivers/mmc/host/sdhci-pltfm.o
  CC      drivers/mmc/host/sdhci-tegra.o
/home/rico/jetson-build/kernel/drivers/mmc/host/sdhci-tegra.c: In function 'adjust_window_boundaries':
/home/rico/jetson-build/kernel/drivers/mmc/host/sdhci-tegra.c:1890:43: error: 'vmax_tap_hole' may be used uninitialized in this function [-Werror=maybe-uninitialized]
   tap_data->win_start = slide_window_start(sdhci, tuning_data,
                                           ^
/home/rico/jetson-build/kernel/drivers/mmc/host/sdhci-tegra.c:1899:39: error: 'vmin_tap_hole' may be used uninitialized in this function [-Werror=maybe-uninitialized]
   tap_data->win_end = slide_window_end(sdhci, tuning_data,
                                       ^
cc1: all warnings being treated as errors
make[4]: *** [drivers/mmc/host/sdhci-tegra.o] Error 1
make[3]: *** [drivers/mmc/host] Error 2
make[2]: *** [drivers/mmc] Error 2
make[1]: *** [drivers] Error 2
make: *** [sub-make] Error 2

I’m not happy yet with playing around with the kernel sources so I was wondering if:

  • Anyone has seen this before and has a workaround/advice
  • There is a patch that solves this

Many thanks in advance.

I have dealt with this exact error, and I did report it to nVidia’s tegra kernel bug email. Certain blocks of code are never compiled unless the options are configured for this, and so the error may not show up until someone configures a certain way. I added a lot of kernel debugging options which resulted in a failed compile because of these uninitialized variables.

It seems these particular variables are fine when uninitialized…the compiler calls it an error because it checks for all cases, but the logic would never actually use the variables uninitialized. I just set the variables in question to 0 at declaration and the problem was solved. So change sdhci-tegra.c lines 1879 and 1880 to initialize to 0:

int vmin_tap_hole = 0;  // BUG missing init
int vmax_tap_hole = 0;  // BUG missing init

That’s great - thanks.

I then went on to build vmlinux (I need to have the debug symbols for my debugger) but I got a lot of warnings about missing __init sections of the i2c driver(s). Some examples are shown here.

MODPOST vmlinux.o
WARNING: vmlinux.o(.text+0x54a24): Section mismatch in reference from the function ardbeg_i2c_init() to the function .init.text:i2c_register_board_info()
The function ardbeg_i2c_init() references
the function __init i2c_register_board_info().
This is often because ardbeg_i2c_init lacks a __init 
annotation or the annotation of i2c_register_board_info is wrong.

WARNING: vmlinux.o(.text+0x54a68): Section mismatch in reference from the function ardbeg_i2c_init() to the function .init.text:i2c_register_board_info()
The function ardbeg_i2c_init() references
the function __init i2c_register_board_info().
This is often because ardbeg_i2c_init lacks a __init 
annotation or the annotation of i2c_register_board_info is wrong.

WARNING: vmlinux.o(.text+0x54a84): Section mismatch in reference from the function ardbeg_i2c_init() to the function .init.text:i2c_register_board_info()
The function ardbeg_i2c_init() references
the function __init i2c_register_board_info().
This is often because ardbeg_i2c_init lacks a __init 
annotation or the annotation of i2c_register_board_info is wrong.

WARNING: vmlinux.o(.text+0x54aa4): Section mismatch in reference from the function ardbeg_i2c_init() to the function .init.text:i2c_register_board_info()
The function ardbeg_i2c_init() references
the function __init i2c_register_board_info().
This is often because ardbeg_i2c_init lacks a __init 
annotation or the annotation of i2c_register_board_info is wrong.

WARNING: vmlinux.o(.text+0x54ab0): Section mismatch in reference from the function ardbeg_i2c_init() to the (unknown reference) .init.data:(unknown)
The function ardbeg_i2c_init() references
the (unknown reference) __initdata (unknown).
This is often because ardbeg_i2c_init lacks a __initdata 
annotation or the annotation of (unknown) is wrong.

WARNING: vmlinux.o(.text+0x54ae4): Section mismatch in reference from the function laguna_register_max98090() to the function .init.text:i2c_register_board_info()
The function laguna_register_max98090() references
the function __init i2c_register_board_info().
This is often because laguna_register_max98090 lacks a __init 
annotation or the annotation of i2c_register_board_info is wrong.

WARNING: vmlinux.o(.text+0x54af4): Section mismatch in reference from the function laguna_register_max98090() to the function .init.text:i2c_register_board_info()
The function laguna_register_max98090() references
the function __init i2c_register_board_info().
This is often because laguna_register_max98090 lacks a __init 
annotation or the annotation of i2c_register_board_info is wrong.

Can I safely ignore these?
There were no problems building the zImage and that’s what I’ll put on the target.

Thanks again.

I’m getting curious about these as well. At this point I don’t know whether there is any issue, but I can say I’ve been running my kernel with these warnings for a while now and have not had any known issues.

Hi linuxdev,

I’m beginner for Tegra K1 and linux O.S., and I would like to build own kernel and flash it, however I have questions for flash it, could I ask you for help ?
My tegra version is 21.4 release, and host system is Ubuntu 14.04 on x86 architecture.

I list my steps, please help to check, if it wrong please correct me.
After make zImage, the zImage is in <TEGRA_KERNEL_OUT>/arch/arm/boot/ , and I copy it to L4T’s kernel folder.
Then I use “sudo ./flash.sh -K /kernel/zImage jetson-tk1 mmcblk0p1” to flash kernel.
There is no error in flash procedure, however, after finish flashing, I cannot boot-up the tegra successfully, I mean the screen is all dark. could you please give me some advises ?

Thanks
Regards

A very important detail is that originally L4T used fastboot as its boot loader. Fastboot is not nearly as convenient nor as powerful for developers as is u-boot…so initially fastboot was default during flash, but a bit later u-boot became default. No flash is needed for a u-boot kernel update, only file copy and/or boot menu edit (no boot menu edit needed if a new kernel replaces an old…if using multiple entries, such as preserving old entry while creating a new entry, then one would edit the boot menu). Fastboot required flash because of the separate partition for the kernel.

So I would suggest just do a clean flash with R21.4 like this:

sudo flash.sh -S 14580MiB jetson-tk1 mmcblk0p1

Once that is done, should you choose to update a kernel, take a look at “/boot/extlinux/extlinux.conf”. The reference in the default label is to use “/boot/zImage” as the kernel (the LINUX line). Replacing /boot/zImage replaces the kernel via simple file copy. Alternately, the zImage can be renamed (such as zImage-custom1) and the extlinux.conf can be edited to name the new kernel. Multiple labels can also be used (copy and paste plus edit of LABEL and MENU LABEL) naming different kernels in each…then selected at boot time via serial console. I usually advise people to keep the original zImage as is, and put in a new zImage with versioning in its name, e.g., copy the new zImage as zImage-3.10.40 or zImage-3.10.40-gdacac96_1).

Hi linuxdev,

Thanks for your suggestion, but I don’t really understand what you say, please forgive me that I have questions to ask you.
As you say, I just rename my own zImage and copy it to /boot/ , and Replace /boot/zImage with /boot/<own zImage’s name>, then I can boot from my own kernel, right ?
Although I don’t have any idea about LABEL and MENU LABEL and how to select at boot time via serial console, I will survey it by google.

Thanks a lot
Regards

The file /boot/extlinux/extlinux.conf lists the kernel path which u-boot looks for. By default it is /boot/zImage. Replacing zImage with your kernel will then cause that kernel to be used instead. The extlinux.conf file is human-readable…you’ll notice default selection and listing during u-boot stage over serial console is governed by the LABEL and MENU LABEL lines of this file.

It is possible to make a second entry in extlinux.conf and have both kernels available, selected by serial console at the start of boot.

Please note that your kernel version numbering is tied to where the booting kernel looks for modules. The default L4T R21.4 kernel is version 3.10.40, and LOCALVERSION was set to “-gdacac96”. Thus the command “uname -r” reads “3.10.40-gdacac96”, and because of this modules are searched for in “/usr/lib/modules/3.10.40-gdacac96”. If you use the same 3.10.40 kernel source, starting with the original operating configuration, and then change only module configuration, a LOCALVERSION in your new kernel of “-gdacac96” will result in being able to use the same module directory and firmware files. This is ideal if you only wish to add new modules and not change the basic kernel. If you are only adding modules, then you don’t even need to put a new kernel in “/boot”.

Serial console has a very short moment at the start of boot where hitting a key will cause u-boot to pause and wait for options. If you hit a key too soon it allows you to explore the environment, or continue booting via typing “boot” in the serial console. Right after that you can hit a key again, and it will pause and show you kernels it has been set up to offer (selected by a number). I always set this up with the original entry as a rescue entry, and test new kernels with extra entries (versus replacing the original zImage).

Hi linuxdev,

Thank for your response and explanation, I’m more familiar with Linux and Tegra k1.
Yes, I use the same kernel source (download from R21.4 release link) and change few driver codes. Is that why I just use zImage and don’t re-compiler modules and flash it ? It’s able to use original R21.4 modules, right ?

As you mentioned before, if we want to only add modules, we don’t even need to copy a new kernel in “/boot”. Can you please illustrate how to achieve it ?

Meanwhile, I’m going to edit extlinux.conf to add multiple entries, and select them by serial console at boot time.

Thank you.
Regards

If you change only modules you need only make modules and make modules_install (setting LOCALVERSION though or else it will find the wrong module directory). If modules are all that change you don’t even need to make zImage.

If you change the base kernel though you can’t be certain the modules will still load and function correctly, so in that case you should build and install both zImage and modules. The LOCALVERSION should be different, or else it will look for the original module directory (where the modules would now possibly be incompatible).

Modules only:

  1. Set CONFIG_LOCALVERSION to same as previous kernel.
  2. make modules
  3. make modules_install

Base kernel change:

  1. Set different CONFIG_LOCALVERSION.
  2. make zImage
  3. make modules
  4. make modules_install
  5. Copy zImage to /boot (possibly renaming and editing in extlinux.conf)

Sometimes firmware may also need update (mostly not). If you do kernel debugging you may want to also save some of the files not normally saved.

Flash is required only if the boot loader itself is to be updated (this includes all cases of fastboot, but very rarely would you update u-boot for a kernel upgrade…fastboot hard codes many things, u-boot is configurable).

Hi linuxdev,

The methods you provided are on Tegra K1 or host machine ?

Thanks
Regards

CONFIG_LOCALVERSION is inside the .config of the kernel source. I suggest simplifying life by compiling on the Jetson TK1 itself…if cross compiling this would still be in the .config, but on host side. Same with “make zImage” (or just “make” to do this…you don’t really need to name zImage) and “make modules”…wherever the source is.

Note that CONFIG_LOCALVERSION can be changed inside “make menuconfig” if you wish, it is a “General setup —>” item, then second line down. “make menuconfig” may require adding package “libncurses5-dev”. The .config file can be edited directly as well if you choose to do so.

If not cross-compiling, but instead compiling directly on Jetson, then “make modules_install” is also from kernel source with install “just working”. If cross-compiling you’d need to name a module directory and then copy over to Jetson. Regardless of cross-compile or native compile, you’d need to manually copy zImage to /boot.

All /boot/extlinux/extlinux.conf edits are on the Jetson itself.

Hi linuxdev,

I have another question is that I build the new zImage and make modules, make modules_install.
I know I can copy zImage to another tk1 which is the same kernel, but how can I do forward modules and firmware like Grinch, it provided its module and firmware ?
Thanks.

Regards

Modules are searched for in “/lib/modules/${uname -r}/”. The base version of the kernel source is the prefix in “uname -r”, the CONFIG_LOCALVERSION is the suffix. So if you compile modules in the same source tree as your other machine where modules are destined, but fail to match CONFIG_LOCALVERSION, you’ll probably get errors on the other machine as the module load is attempted. The inverse of that situation is that if your build source kernel version is the same and the CONFIG_LOCALVERSION matches, any failure upon load would be based on actual software failures (kernel versioning would not be an issue).

To guarantee that you will get compatibility, both build source and running destination kernels (for copying modules to) should have the same “integrated” features. During configuration (e.g., “make menuconfig”) you can choose “yes” (‘y’, integrated), “no” (‘n’, remove the feature), or “module” (‘m’, runtime loadable feature). Avoid changing integrated features, keep these unchanged between build source and destination source…add or remove runtime loadable features as you please. If integrated features change, modules may still work, but may also fail (it’d be hard to predict reliably).

Firmware files are generally independent of kernel config and in many cases will not care about differing CONFIG_LOCALVERSION. However, the actual content of the firmware files needs to be in whatever format the kernel features expect. Basically that implies if an API is consistent firmware will be valid.

Note that if you want firmware and modules to go to some isolated location (versus actually installing), you can use a command like this (make sure the .config is in the TEGRA_KERNEL_OUT directory):

export TEGRA_KERNEL_OUT="/wherever/you/want/kernel/build/stuff"
export TEGRA_MODULES_OUT="/wherever/you/want/modules/and/firmware"
make O=$TEGRA_KERNEL_OUT modules_install <b>INSTALL_MOD_PATH=$TEGRA_MODULES_OUT</b>

I am new to this board and I want to add usbmon module to the kernel.
I am following the instruction to build 21.5 kernel on my TK1 (not cross compiling).
The build went successfully. I copied the resulting zImage to /boot/ and restart the board.
After this, the TK1 didn’t seem to boot and nothing got displayed on the screen.

Did I miss anything? How do I troubleshoot this?

Do you have a serial console set up? This would tell you a lot (setting is 115200 8N1…you can use CTS/RTS flow control or software flow control). Are you able to ping or access via ssh (it might just be video failure)?

Did you set your CONFIG_LOCALVERSION prior to the kernel build? FYI, if you just needed the module, then no zImage copy would be required (and conversely, adding a zImage for a feature built as a module would not install the feature).

Hi TheGreatSage,
How do you fix warnings about missing __init sections of the i2c driver(s) issue? I have met the samiliar issue as you, hope you could share the resolution,Thanks!

Unless they cause a problem I don’t attempt to fix those. Have you found a problem with a particular driver which fails? The trouble is that it might not matter, but there might be more than one place which needs a change if you change just one.

If you have a specific case you might post the kernel output for the compile which applies to that block of code. You’ll also want to say how any config you have differs from the running system’s “/proc/config.gz” of a default kernel, along with which L4T release you are using (“head -n 1 /etc/nv_tegra_release”). Also mention which gcc version you use since this alters what might be warned against and how the warning might be worded.

Hi Linuxdev,
I havn’t find any issue though there are such warnings, just ignore now,Thanks!