Developing on NVIDIA® Jetson™ for AI on the Edge

Build Modules and Drivers for NVIDIA Jetson TK1 – L4T 21.1

The release of Linux for Tegra (L4T) 21.1 for the NVIDIA Jetson TK1 brought with it the use of UBoot as the new kernel boot loader. UBoot makes it easier to load modules and drivers dynamically. I thought it would be nice to build a driver for an Intel 7260 PCIe wireless card, and show that as an example.

Note 7-16-15: This article was originally written to address a bug in the software at the time the article was written. The issue has since been resolved (tested under Linux L4T 21.4). The bug exhibited itself as not showing the wireless access points in the connection menu after loading the 7260 firmware. Since the bug has been squashed, to enable wireless for the 7260 all that is needed is to execute in a Terminal:

$ sudo apt-get install linux-firmware

and then reboot the machine. The access points will then show up in the connection menu. However, the information in the article shows how to build a kernel module, which is a useful knowledge in and of itself.

As a preface, I’ll note that I hate upgrades. I’m convinced that the reason that we have software professionals is so they can scurry about and try to deal with everybody “upgrading” everything all the time. In a typical upgrade, bits and pieces are changed which bring about what I am told are good things, but from my perspective it just tends to break all of my stuff that I rely on for day to day stuff. For example, upgrade to 21.1, break the wireless. It’s simple I’m told, just recompile the kernel and drivers.

For some reason, I don’t get real excited about that.

Anyway, I wanted my wireless to work so off to build land. “How hard could it be?” I thought. This changed quickly to “How could that be?”. Cutting to the chase, here’s the video of how to build the modules and drivers. Looky here:

Here’s the Github Repository buildJetsonModules with the scripts. The file gives a pretty good description of how to do the actual building and install.

Here’s the story of some of the trials and tribulations of building the wireless driver. I thought it would be easy and straightforward, which it is up until the part where you fall over the cliff. In my naiveté, I downloaded the Kernel Sources and decompressed the files from the Linux for Tegra R21 page onto my Jetson into /usr/src.

So far so good. I was happy to see that the kernel had the source for the Intel 7260 driver. There are three parts to this. First, there is the wireless Module that loads the driver and does the protocol-ing stuff. There are a couple of these needed, cfg80211 and mac80211. These are built and available on the Jetson in stock configuration, as is a wireless driver for Realtek products called rtlwifi.

The second part is a Driver for the Intel 7260. This is called iwlwifi and consists of Jetson side code which talks to the card. The third part is the Firmware, which is loaded onto the card itself. This is available to the Jetson through a repository:

$ sudo apt-get install linux-firmware

This installs a bunch of firmware for different sets of hardware, but I wasn’t really concerned. This is installed in /lib/firmware.

Eventually I figured out that I needed configure the kernel:

$ make menuconfig

and was promptly transported back to a 1985 era DOS looking tool. I’m old enough to remember “the good old days”, I’ll just say that these types of interfaces make me regret not taking drugs back then. After a whole bunch of fiddling to actually figure out how to build the driver for iwlwifi, I saved the configuration .config file.

Let me just add, the Terminal program on Ubuntu needs to be taken out back and shot. The great thing about menuconfig is that it expands to the size of the Terminal window. And as you know, the Terminal type is only 80 characters so there’s not much of a need to ever expand the width of the Terminal window. However, menuconfig spills over the 80 character limit (like in the name for the iwlwifi driver). It didn’t really occur to me that I could make the Terminal window wider than 80 characters and see any change. Until I accidentally resized the window, then I was really pissed off.

The interface for menuconfig is just like an adventure game of the 1980s too, “a twisty passage of halls, all alike”, everything randomly scattered about. Seriously, someone needs to modernize that stuff.

The first build was uneventful once I figured out where everything should go. I just built the iwlwifi driver:

make prepare
make modules_prepare
make modules SUBDIRS=drivers/net/wireless

and copied the resultant iwlwifi folder to the correct spot into the intuitively named /lib/modules/3.10.40-g8c4516e/kernel/drivers/net/wireless folder, and rebooted. Nothing showed up in the network menu, which was disappointing but not surprising. Looking through the dmesg log, I saw that the version of the driver didn’t match the version of the kernel, so the driver wasn’t loaded. To be clear, the driver version was 3.10.40, and the kernel version is: 3.10.40-g8c4516e. Seriously?

Back to menuconfig land, and try to figure out how to set the postfix to match. Ok, fix that (eventually) reload and reboot. Still no joy. It turns out that it tried to load the driver, but there was a missing symbol in mac80211. This confused me a little, as I thought that the source that was provided was the same as what was running. How could a symbol be missing?

Once I got over that, build mac80211 too:

make prepare
make modules_prepare
make modules SUBDIRS=net/mac80211
make modules SUBDIRS=drivers/net/wireless

Install the mac80211 module into /lib/modules/3.10.40-g8c4516e/kernel/net/mac80211. Tell the Jetson to rebuild the Module symbol table:

depmod -a

Reboot …

OK. Dmesg says that cfg80211 rolled over and died. Here’s the thing, there’s no map somewhere that says cfg80211 is the “wireless” directory. So it’s like a hunt just to figure out where it is in menuconfig and where it should go after building:

make prepare
make modules_prepare
make modules SUBDIRS=net/wireless
make modules SUBDIRS=net/mac80211
make modules SUBDIRS=drivers/net/wireless

Of course, it goes in /lib/modules/3.10.40-g8c4516e/kernel/net/wireless. Rebuild module symbol table. Reboot.

Now we’re getting somewhere. Rfkill has killed it, and turned off iwlwifi. This is good, because I remember what the answer is to that issue. It turns out that the Jetson needs to turn on General Purpose Input Output (GPIO) 191 to be able to talk to the mini-PCIe card. That’s no problem, the solution is to add:

echo 191 > /sys/class/gpio/export;
echo out > /sys/class/gpio/gpio191/direction;
echo 1 > /sys/class/gpio/gpio191/value;
# Reload the wifi driver for the Intel mini PCIe card
modprobe -r iwlwifi;
modprobe iwlwifi;

to the file /etc/rc.local

Reboot, and Voila! Wireless Access! All is swell again. Until the next upgrade …


You’ll see error messages when you’re building the Modules and Drivers. These take the form “Could not find Module.symvers”. There are several reasons for this, but as far as I can figure Module.symvers is generated when the kernel itself is compiled and ought to be provided to the user as part of the kernel build environment package. I couldn’t find it (which doesn’t mean that it’s not available, just that I lost patience hunting for it). So what do you give up by not having it? Basically you give up versioning of the module, but that wasn’t something I really care about right now.

To me, the point of modules is that you should only have to build the module to add it to a system. If you have to compile the entire kernel, all the modules and drivers in order to get them to work, ain’t much point in modules is there?


9 Responses

  1. Well done, enjoy the sense of humor. Maybe not the most important ingredient, but definately a dependency. Takes me back to the days of hacking the ACSI interface so I could sink about $300, and untold hours connecting a 20 Meg hard drive to my Atari ST. Trust me, drugs wouldn’t have helped. So my delema is do I spend the hours hammering out a driver for my Broadcom BCM4352, or just drop $20 on one that already works, and live without 802.11AC, which probably wouldn’t work anyway. That is, until the next upgrade.

    1. The drugs would have helped me forget. The Intel 7260 has 802.11ac, and has built in support in the L4T 21.x releases. The new releases just require you to download the 7260 firmware:

      $ sudo apt-get install linux-firmware

      and after that it is up and running. I’ve had issues with not being able to see access points through the pull down, but if the SSID is known you can just type it in. If you recompile the module, then everything works as normal. I haven’t tested L4T 21.3 yet to see if they have fixed that particular bug.

      I think you’ve run into the dilemma that all dev kits have, or maybe Linux in general. How much time do you spend on stuff that ultimately is a $20 problem, and doesn’t really effect your project or enjoyment? Personally, I had been away from Linux long enough to need to relearn the module building skills, so I bit the bullet and learned how to do it. The unfortunate part is it’s one of those things where you need to ‘know’ so many parts of the architecture to jam it in there that you get overwhelmed by the nomenclature. For the Intel wireless, there was Module, Driver, and Firmware you needed to know, but no easily accessible map telling you which each one of those were named or their function (or even that you needed all three). One can make educated guesses, but things like ‘iwlwifi’ don’t mean a whole bunch to the NooB.

      With the above guide, it shouldn’t take too long to get the BCM4352 up and running, but certainly if you don’t enjoy that type of thing (or value your time at all), it’s probably easier and cheaper to get another wireless card.

      1. Completely agree. There is no overall map. My entire life with Lynux has been “do the next step, fix the error, rinse and repeat”. And this is not only my own development projects, but the FDA regulated servers I work on for my day job as well. Just about every time, even though it eats up a rediculous amount of time, I’m amazed at how much I learn.

        Your guide is tempting me back in. It’s just that when I start, I can’t seem to quit until it works. The older I get, the less I believe that sleep is overrated.

        Oh, and as bad as the terminal program is, I absolutely refuse to ever touch vi again. Lucky for me there are many alternatives. If I’m given the choice of begging in the street to feed my kid or use vi, I’m getting the organ grinder and tin cup out.

        I may have forgotten to say it, but thanks for taking the time to post this. Very well done, and helpful.

  2. I meet a problem about the 3g mobile broadband . I used to use R19.3 and it works well both when I put the card to mini pci-e slot or put the card to usb through a usb adapter.
    Now I use 21.3.4 and now the mobile broadband card now just works with the adapter through usb but not work when I put the card into mini pci-e slot.I don’t know why.Who can tell me ?

    My card is Huawei 909s-821.

    1. Hi,
      Unfortunately I do not have any experience with the Huawei, or what the issue in your particular case is. In general, to get these devices to work you will need the Linux device driver for the device (this article calls that a module), and the actual firmware for the device, which you can most likely get with the command:
      $ sudo apt-get install linux-firmware
      Sorry I can’t be of more help.

Leave a Reply

Your email address will not be published. Required fields are marked *


Some links here are affiliate links. If you purchase through these links I will receive a small commission at no additional cost to you. As an Amazon Associate, I earn from qualifying purchases.

Books, Ideas & Other Curiosities