Skip to main content

r8169 module with DKMS in Ubuntu 12.04 LTS

When testing network issues with different cards it is a good idea to make sure they actually have different chipsets.

Update: I found no difference between the NIC operating with built-in r8169 module and the version that is available on the RealTek’s web site. You will want to use the vendor-provided module only if your card is not supported by the driver shipped with the linux kernel.

Update: I packaged the source-only dkms – r8169-6.017.00-source-only.dkms.tar.gz, which can be installed with:

sudo dkms ldtarball r8169-6.017.00-source-only.dkms.tar.gz
sudo dkms build r8169/6.017.00
sudo dkms install r8169/6.017.00

Update: See the end of the post, patch is required for DGE-528T to be picked by this module.

I had a complex VM network setup with separate vlan on the router for virtual machines and second network card in the server to prevent connection hanging when network topology was changing on the VM startup. Then I decided to simplify the network and use one NIC only, in my case that would be DLink DGE-528T.

This card is driven by realtek 8169 chip and for some reason these like to drop network connection. I’ve found quite a few topics on poor performance of 8169 with in-kernel driver, but the built-in r8168 chip running under r8169 driver included in the kernel performs way worse than r8169.

There is a driver update on the Realtek web site so I decided to give it a try.

I started with dkms.conf from Fixing RTL8111/8168B kernel module on Debian/Ubuntu post by Randy, but for some reason r8169 module kept overwriting the system wide one. It turns out that Makefile installs module automatically when called with no specific target.

So here’s how I made it work:

  1. Download the tarball from Realtek web site.

  2. Unpack the resulting r8169-6.017.00.tar.bz2 to /usr/src.

  3. Add the dkms.conf file to /usr/src/r8169-6.017.00/:

    PACKAGE_NAME="r8169"
    PACKAGE_VERSION="6.017.00"
    CLEAN="make clean"
    BUILT_MODULE_NAME[0]="r8169"
    BUILT_MODULE_LOCATION[0]="src"
    DEST_MODULE_LOCATION[0]="/updates"
    MAKE[0]="'make' 'modules'"
    AUTOINSTALL="YES"
    
  4. Build and install the module:

    $ sudo dkms install r8169/6.017.00
    ...
     - Installation
       - Installing to /lib/modules/3.2.0-35-generic/updates/dkms/
    ...
    

At the moment due to the bug in dkms script it is not possible to create the dkms tarball directly from realtek sources but you can create one after you perform the steps above.

$ sudo dkms mktarball r8169/6.017.00
Marking modules for 3.2.0-35-generic (x86_64) for archiving...

Marking /var/lib/dkms/r8169/6.017.00/source for archiving...

Tarball location: /var/lib/dkms/r8169/6.017.00/tarball//r8169-6.017.00-kernel3.2.0-35-generic-x86_64.dkms.tar.gz

Afterwards you can load this tarbal on a different machine:

$ sudo dkms ldtarball r8169-6.017.00-kernel3.2.0-35-generic-x86_64.dkms.tar.gz

Loading tarball for r8169-6.017.00
Loading /var/lib/dkms/r8169/6.017.00/3.2.0-35-generic/x86_64...

DKMS: ldtarball completed.

Creating symlink /var/lib/dkms/r8169/6.017.00/source ->
                /usr/src/r8169-6.017.00

DKMS: add completed.

$ sudo dkms install r8169/6.017.00

Creating symlink /var/lib/dkms/r8169/6.017.00/source ->
                /usr/src/r8169-6.017.00

DKMS: add completed.

Kernel preparation unnecessary for this kernel.  Skipping...

Building module:
cleaning build area....
'make' 'modules'....
cleaning build area....

DKMS: build completed.

r8169.ko:
Running module version sanity check.
- Original module
- Installation
- Installing to /lib/modules/3.2.0-35-generic/updates/dkms/

depmod....

DKMS: install completed.

DGE-528T

So I left this module running for about a week and yesterday I could not make the card work after a reboot. It turns out that while the updated r8169 module is installed, it is not being used for D-Link DGE-528T card.

r8169_n.c contains the following:

static struct pci_device_id rtl8169_pci_tbl[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_REALTEK,     0x8167), 0, 0, RTL_CFG_0 },
        { PCI_DEVICE(PCI_VENDOR_ID_REALTEK,     0x8169), 0, 0, RTL_CFG_0 },
        { PCI_VENDOR_ID_DLINK, 0x4300, PCI_VENDOR_ID_DLINK, 0x4c00, 0, 0, RTL_CFG_0 },
        {0,},
};

So the module does not match PCI_VENDOR_ID_DLINK:0x4c00 subsystem (lspci -vnn):

02:06.0 Ethernet controller [0200]: D-Link System Inc DGE-528T Gigabit Ethernet Adapter [1186:4300] (rev 10)
    Subsystem: D-Link System Inc DGE-528T Gigabit Ethernet Adapter [1186:4300]
    Flags: bus master, 66MHz, medium devsel, latency 64, IRQ 21
    I/O ports at e800 [size=256]
    Memory at febffc00 (32-bit, non-prefetchable) [size=256]
    Expansion ROM at febc0000 [disabled] [size=128K]
    Capabilities: [dc] Power Management version 2
    Kernel driver in use: r8169
    Kernel modules: r8169

1186:4c00 is actually a DGE-T530 card, but it looks like there are some DGE-T528 cards with 1186:4300 subsystem and some have 1186:4c00 one. The original driver from D-Link has PCI_ANY_ID for subsystem fields so it looks like these are compatible.

I was so sure the updated module would fix the issues I was having with the network card that it actually stopped misbehaving.

However, I decided to patch the module to make it work with my card too:

--- r8169_n.c.ori   2012-05-03 15:23:12.000000000 +0300
+++ r8169_n.c   2012-12-30 19:42:14.818322918 +0200
@@ -115,7 +115,8 @@
static struct pci_device_id rtl8169_pci_tbl[] = {
    { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), 0, 0, RTL_CFG_0 },
    { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 },
-   { PCI_VENDOR_ID_DLINK, 0x4300, PCI_VENDOR_ID_DLINK, 0x4c00, 0, 0, RTL_CFG_0 },
+   { PCI_DEVICE(PCI_VENDOR_ID_DLINK,       0x4300), 0, 0, RTL_CFG_0 },
+   //{ PCI_VENDOR_ID_DLINK, 0x4300, PCI_VENDOR_ID_DLINK, 0x4c00, 0, 0, RTL_CFG_0 },
    {0,},
};

And now the module prints the following when loaded:

[18014.031288] r8169 Gigabit Ethernet driver 6.017.00-NAPI loaded
[18014.031344] r8169 0000:02:06.0: PCI INT A -> GSI 21 (level, low) -> IRQ 21
[18014.033537] r8169: This product is covered by one or more of the following patents: US5,307,459, US5,434,872, US5,732,094, US6,570,884, US6,115,776, and US6,327,625.

So now I am really testing the module provided by Realtek.