USB 3.0 in Linux kernel

I’ve got this one from Sarah’s blog, take a look at her blog she has a lot of cool articles:

Installing a custom kernel with USB 3.0 support

This documents my personal flow for downloading and installing a Linux kernel with my xHCI and USB 3.0 code. Until the code is in the upstream kernel and shipping in Linux distributions, you’ll have to follow these directions to get Linux USB 3.0 support.


This tutorial is mostly for vendors who want to test their USB 3.0 devices or xHCI host controller prototypes. This assumes you already have a standard Debian or Ubuntu installation. There are many helpful guides for installing Ubuntu or Debian, so I won’t go into detail on that here.

There are also other guides for creating a custom kernel, but most walk you through creating a .deb package. Going through the extra steps of creating the package adds too much time if you’re updating your kernel a lot in order to track an upstream git tree.


First, you need to install some extra software that may not come with a standard Ubuntu or Debian install. You can install software by using a gui installer (like synaptic). You can also open a terminal (found under the Applications menu in Gnome and under the System menu in KDE) and install software using the command line. I’ll assume you’re using the command line in this tutorial.

First install the packages necessary to compile the Linux kernel. If you’re on Debian, type the following:

sudo aptitude install wget make git-core libncurses5-dev

If you’re on Ubuntu, use this command instead:

sudo aptitude install wget make git-core lib32ncurses5-dev

Next, you’ll need to add a script to install the Linux kernel.

mkdir ~/bin/ cd ~/bin/ wget sudo chmod a+x installkernel

A standard Debian or Ubuntu install should add the bin directory in your homedir to your path automatically whenever you start a new terminal shell. To make sure you can run that script, close your current terminal, restart a new terminal, and type

echo $PATH

You should see /home/username/bin in the output (replace username with whatever username you picked). You can also make sure the script is in your path by typing “installker” and hitting tab. If the command expands to “installkernel”, then your path is set correctly and the script permissions are right. If not, follow the next instructions.

Using the installkernel script

Now add that script to your PATH in your rc file for your terminal shell of choice. Bash is the default option, so edit (or create) the .bashrc file in your home directory. You can use vim, emacs, or even OpenOffice Writer to edit this file. If you must use OpenOffice Writer, make sure you save the file with the name “.bashrc” with a Text encoded (txt) file type, and uncheck the “Automatic file name extension” box.

Add this line to your .bashrc:


If you already have a line that starts with PATH, simply add the ~/bin: after the first double quote.

Download a custom kernel

Most custom kernels are hosted on They are kept under revision control using the VCS called “git”. This means the kernels are updated often, and you may need to use git to update to the latest version. That’s explained later.

In this tutorial, I’ll assume you want to download my custom kernel to test USB 3.0 host controllers and devices.

First, move to your homedirectory and “clone” the git repository so you have a local copy checked out:

cd git clone git://

Downloading the kernel may take a while. If you’re behind a firewall, you may need to set the $http_proxy environment variable (by adding a “http_proxy=url” line to your .bashrc) and use http to clone the repository. In this case, replace the last command with

git clone

You should see output like “Initialized empty Git repository in /home/username/xhci/.git/”. If nothing else happens for a couple minutes after that output, then you probably have firewall problems.

Choosing your kernel configuration

First, change directories into the newly created repository clone:

cd xhci/

Now we need to choose the configuration options for the new kernel, and compile it. A configuration file describes your system configuration, and whether you want drivers compiled into the kernel or if you want the drivers to be dynamically loadable as a module.

You can use the configuration file that the default distribution install created by typing:

cp /boot/config-uname -r .config

Now we need to change or add new configuration options:

make menuconfig

This will present a text-based GUI of all the configuration options for the Linux kernel. This is everything from what file systems to support (like FAT or EXT3) to what drivers to load (like SCSI, USB, or networking cards). A driver is built into the kernel if it has a star “*” by it. The driver is a dynamically loadable module if it has an “M” by it. If the option has nothing in the brackets, it won’t be compiled. If you want a driver to be a module, just hit the “m” key. If you don’t want a driver, hit “n”; if you want to compile a module into the kernel or say yes to a configuration option, hit “y”.

To be able to use my USB 3.0 code, navigate to Device Drivers and onto the USB support menu. Make sure “Support for Host-side USB” is a dynamically loadable module by moving the cursor to that item and hitting the ‘m’ key. You may get a message that other drivers depend on host-side USB being built into the kernel. If so, you need to make sure all the drivers under this menu with a star by them (“*”) are changed to be modules (with an “M”) by them.

You need to change a few more things in this menu. Choose to compile the xHCI (USB 3.0) host controller driver as a module by hitting “m”. Turn off (hit “n”) on the “USB selective suspend/resume and wakeup” option, since that isn’t supported by the driver yet. Turn on debugging for the USB subsystem by hitting “y” on “USB verbose debug messages” and “USB announce new devices”. Also turn on the “Debugging for the xHCI host controller” option.

Compiling and installing your kernel

Now that you have your kernel configured, compile your kernel by typing

make -j4

This make take a while. Go get a cup of tea or wander off for lunch. Once that compile finishes, you’re ready to install your kernel by typing

sudo make modules_install install

That will take a bit, but not as long as the compile. Near the end, you will see a line similar to

update-initramfs: Generating /boot/initrd.img-2.6.30-rc3

Remember the number after “initrd.img-” for the next step.

Controlling when the xHCI driver is loaded

This next step is optional. If you follow the above steps exactly, the xHCI driver will be loaded automatically when you boot the new kernel. It’s much easier for me to look at debug output from the driver if it’s not interspersed with boot code. To do that, you should dynamically load the driver after the machine finishes booting.

First, we have to prevent the driver from being loaded automatically at boot time by “hiding” it from the module loader. You’ll need to know the version of the kernel, which was mentioned in the last step.

sudo mv /lib/modules/2.6.30-rc3/kernel/drivers/usb/host/xhci.ko /lib/modules/2.6.30-rc3/kernel/drivers/usb/host/.xhci.ko

Now whenever you want to load the xHCI driver, type the following (after you’ve rebooted into the new kernel):

sudo insmod /lib/modules/2.6.30-rc3/kernel/drivers/usb/host/.xhci.ko

When you want to unload the module, type this:

sudo rmmod xhci

This is equivalent to enabling and then disabling the driver in the Windows system manager.

Updating your Kernel

If the tree gets patches added to it, or it’s updated to a newer kernel, you’ll need to update your local checkout. There are a couple ways to this, depending on if you have local changes to the files. If you haven’t modified any files, it’s safe to type these two commands from within your xhci directory:

git fetch git reset –hard origin/master

This resets the local checkout to exactly what’s in the remote repository. If you have local changes, you’ll need to do something more complicated in order to merge in or rebase against the remote repository changes.

You’ll need to repeat the compiling, installing, and moving the xHCI driver steps after you update your checkout of the code.


I suggest that when you run the xHCI driver, you have three tabs in your terminal window open. In one tab, redirect the kernel debugging messages to a file:

tail -f /var/log/kern.log > ~/xhci-log.txt

In the second tab, start a similar command that will output the debugging messages to that terminal window:

tail -f /var/log/kern.log

In the third tab, start the xHCI driver after 5 seconds. The slight delay allows you time to switch back to the second tab to watch the driver debug messages. If you haven’t moved the xHCI driver from its default location, type

sleep 5 && sudo modprobe xhci

If you have moved the driver so it isn’t loaded at boot, type

sleep 5 && sudo insmod /lib/modules/2.6.30-rc3/kernel/drivers/usb/host/.xhci.ko

Send the logfile to me if you have issues. You may need to use netconsole to capture the kernel debug messages if your system is hanging because of a driver bug.


Hamilton Vera

  1. EeePC vx6: Windows 7 yes, Linux no
  2. USB 3.0 on kernel >3.4

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: