Ubuntu – Ubuntu 16.10 Intel e1000e driver cannot be compiled. Error: ‘struct net_device’ has no member named ‘trans_start’

compilingdriversgcckernel

The built-in e1000e driver for an Intel Gigabit Ethernet controller does not work in Ubuntu, this is a known issue, with a known solution: download the driver from the Intel website, compile it, and install the kernel module as per usual kernel module installation instructions.

I downloaded the Intel e1000e-3.3.4 driver from https://downloadcenter.intel.com/download/15817/Intel-Network-Adapter-Driver-for-PCI-E-Gigabit-Network-Connections-under-Linux-?product=70831


After untarring, I get this error when I run make:

cc1: error: code model kernel does not support PIC mode /bin/sh: 1: [:
-ge: unexpected operator
Makefile:181: *** *** Aborting the build. *** This driver is not supported on kernel versions older than 2.4.0.  Stop.

According to someone on sourceforge, I should remove gcc from Ubuntu's repository (sudo apt remove gcc), and reinstall it from it's source. That, of course, can't be done, because that would also uninstall bbswitch-dkms build-essential dkms g++ gcc libcuda1-367 nvidia-367 nvidia-opencl-icd-367 nvidia-prime.

I found a link to this page about PIE, but it does not contain simple copy&paste instructions to enable or disable PIE, or whatever the hell needs to be done to get this network driver module compiled.

On Unix Stack Exchange I found a question that may or may not be related, and it also doesn't contain clear instructions to patch whatever needs to be patched: https://unix.stackexchange.com/questions/320470/apply-kernel-patch-to-support-pic-mode

My uname -a:

Linux kerbol 4.8.0-27-generic #29-Ubuntu SMP Thu Oct 20 21:03:13 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux

UPDATE 2016-12-02

I was advised to install gcc-4.8, rm gcc from /usr/bin and make a new symlink. Stubborn as I am, I did this instead (which I believe is the recommended "Ubuntu Way" of doing things):

sudo apt install gcc-4.8
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 50
sudo update-alternatives --config gcc

When I ran make again, I got another error. Progress!

make -C /lib/modules/4.8.0-27-generic/build SUBDIRS=/home/amedee/e1000e-3.3.4/src modules
make[1]: Entering directory '/usr/src/linux-headers-4.8.0-27-generic'
  CC [M]  /home/amedee/e1000e-3.3.4/src/netdev.o
gcc: error: unrecognized command line option ‘-fstack-protector-strong’
scripts/Makefile.build:289: recipe for target '/home/amedee/e1000e-3.3.4/src/netdev.o' failed
make[2]: *** [/home/amedee/e1000e-3.3.4/src/netdev.o] Error 1
Makefile:1489: recipe for target '_module_/home/amedee/e1000e-3.3.4/src' failed
make[1]: *** [_module_/home/amedee/e1000e-3.3.4/src] Error 2
make[1]: Leaving directory '/usr/src/linux-headers-4.8.0-27-generic'
Makefile:247: recipe for target 'default' failed
make: *** [default] Error 2

If you Google for "gcc: error: unrecognized command line option ‘-fstack-protector-strong’", then you will find that you don't need gcc-4.8 but gcc-4.9. So I did:

sudo apt install gcc-4.9
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.9 50
sudo update-alternatives --config gcc

When I ran make again, I got yet another error:

make -C /lib/modules/4.8.0-27-generic/build SUBDIRS=/home/amedee/e1000e-3.3.4/src modules
make[1]: Entering directory '/usr/src/linux-headers-4.8.0-27-generic'
  CC [M]  /home/amedee/e1000e-3.3.4/src/netdev.o
In file included from ./include/linux/kernel.h:13:0,
                 from ./include/linux/list.h:8,
                 from ./include/linux/module.h:9,
                 from /home/amedee/e1000e-3.3.4/src/netdev.c:24:
/home/amedee/e1000e-3.3.4/src/netdev.c: In function ‘e1000e_dump’:
/home/amedee/e1000e-3.3.4/src/netdev.c:250:25: error: ‘struct net_device’ has no member named ‘trans_start’
    netdev->state, netdev->trans_start, netdev->last_rx);
                         ^
./include/linux/printk.h:283:34: note: in definition of macro ‘pr_info’
  printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)
                                  ^
/home/amedee/e1000e-3.3.4/src/netdev.c: In function ‘e1000_xmit_frame’:
/home/amedee/e1000e-3.3.4/src/netdev.c:6545:8: error: ‘struct net_device’ has no member named ‘trans_start’
  netdev->trans_start = jiffies;
        ^
scripts/Makefile.build:289: recipe for target '/home/amedee/e1000e-3.3.4/src/netdev.o' failed
make[2]: *** [/home/amedee/e1000e-3.3.4/src/netdev.o] Error 1
Makefile:1489: recipe for target '_module_/home/amedee/e1000e-3.3.4/src' failed
make[1]: *** [_module_/home/amedee/e1000e-3.3.4/src] Error 2
make[1]: Leaving directory '/usr/src/linux-headers-4.8.0-27-generic'
Makefile:247: recipe for target 'default' failed
make: *** [default] Error 2

Now it's becoming interesting because I think I found something that changed starting with 4.7 kernels.
Googling for error: ‘struct net_device’ has no member named ‘trans_start’ told me that I had to change line 6545:

-netdev->trans_start = jiffies;
+netif_trans_update(netdev);

Indeed, this removed the error at line 6545. This still leaves me with an error at line 249-250. This is the current code:

pr_info("%-15s %016lX %016lX %016lX\n", netdev->name,
  netdev->state, netdev->trans_start, netdev->last_rx);

I know I need to replace netdev->trans_start with something else, but I don't know what. Using netif_trans_update(netdev) as the 4th parameter of pr_info won't work because that gives me

/home/amedee/e1000e-3.3.4/src/netdev.c: In function ‘e1000e_dump’:
/home/amedee/e1000e-3.3.4/src/netdev.c:249:3: error: invalid use of void expression
   pr_info("%-15s %016lX %016lX %016lX\n", netdev->name,
   ^

So what do I need to put there instead?

Apparently pr_info is used for logging purposes, so I thought, what if I put lines 249-250 in comments? The result was that the driver finally builds (yay!) but it feels wrong to comment out code if you don't know what it's function is. Especially kernel driver code.

And even with a driver that compiles, I still don't have network after I do

sudo rmmod e1000e
sudo modprobe e1000e

UPDATE: The solution for a dual boot system is to boot into Windows, go to the driver settings of the network card, and disable everything related to power management. Then boot into Linux, reboot into Linux (yes, twice!) and use the default driver provided by the kernel.

Best Answer

Googling netif_trans_update gives the following code:

/* legacy drivers only, netdev_start_xmit() sets txq->trans_start */
 static inline void netif_trans_update(struct net_device *dev)
 {
         struct netdev_queue *txq = netdev_get_tx_queue(dev, 0);

        if (txq->trans_start != jiffies)
                 txq->trans_start = jiffies;
 }

which suggests that a good way to get the trans_start back in pr_info would be to replace

netdev->trans_start

with

netdev_get_tx_queue(netdev,0)->trans_start.

but you're right, this is a log function, fixing it probably won't fix your driver.

Related Question