Bug 451855 - e1000e driver does not return proper link up status
Summary: e1000e driver does not return proper link up status
Keywords:
Status: CLOSED CURRENTRELEASE
Alias: None
Product: Red Hat Enterprise Linux 5
Classification: Red Hat
Component: kernel
Version: 5.2
Hardware: All
OS: Linux
low
medium
Target Milestone: rc
: ---
Assignee: Andy Gospodarek
QA Contact: Martin Jenner
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2008-06-17 19:42 UTC by John DeFranco
Modified: 2014-06-29 23:00 UTC (History)
7 users (show)

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Clone Of:
Environment:
Last Closed: 2009-01-28 21:34:03 UTC
Target Upstream Version:
Embargoed:


Attachments (Terms of Use)

Description John DeFranco 2008-06-17 19:42:28 UTC
From Bugzilla Helper:
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.12) Gecko/20080203 SUSE/2.0.0.12-0.2 Firefox/2.0.0.12

Description of problem:
I'm seeing what I consider a problem with getting link status via
SIOCETHTOOL and the e1000e driver. According to all the data I have and
based on how the e1000/e100/tg3 and any broadcom driver works if I
issue something like the following:

   edata.cmd = ETHTOOL_GLINK;
   ifr.ifr_data = (caddr_t)&edata;

   if (ioctl(mii_socket, SIOCETHTOOL, &ifr) != 0 ){
       printf("errno: %d, %s\n", errno, strerror(errno));
   }  else  {
      printf("status for %s: 0x%x\n", if_name, edata.data);
   }

I would/should get an edata.data value of 1 for link up and 0 for link
down.  Here is an example on an interface that uses the tg3 driver:

[root@ ~]# ./test eth0
mii_socket: 3
Proper MII ioctl for eth0 is SIOCETHTOOL.
status for eth0: 0x1

The link is up and I get a 1. Same test on a nic with the e1000e driver
shows:

[root@ ~]# ./test eth4
mii_socket: 3
Proper MII ioctl for eth4 is SIOCETHTOOL.
status for eth4: 0x2

The link is definately up and connected but instead of showing a status
of 1 it give me 2. If I unplug the link it does give me a 0 (as
expected).


Information I received when I reported this to the e1000 alias:

Yup, it's known and already fixed in-house.

Essentially, the return from e1000_get_link() should be something like:

        return ((status & E1000_STATUS_LU) ? 1 : 0);

According to other information, this fix will be included in an aug 15 submittal to kernel.org.

This fix needs to be in 5.3 and 5.2 if possible.


Version-Release number of selected component (if applicable):
kernel-2.6.18-92.el5

How reproducible:
Always


Steps to Reproduce:
1. setup an nic that uses the e1000e driver (actually I don't even believe the interface needs to be up, just connected to a network).
2. Run the test program included in the additional information section.
3.

Actual Results:
With a cable connected to the NIC it returns 2. 

Expected Results:
It should return 1.

Additional info:
Sample program to see behavior:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <netdb.h>
#include <sys/uio.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <net/route.h>
#include <net/if_arp.h>
#include <linux/if.h>
#include <linux/if_ether.h>
#include <linux/if_packet.h>
#include <linux/if_bonding.h>
#include <linux/sockios.h>
#include <endian.h>

#ifndef SIOCETHTOOL
#define SIOCETHTOOL (0x8946) 
#endif
#ifndef SIOCGMIIPHY
#define SIOCGMIIPHY (0x8947) 
#endif
#ifndef SIOCGMIIREG
#define SIOCGMIIREG (0x8948) 
#endif
#define ETHTOOL_GSET            0x00000001 /* Get settings. */
#define ETHTOOL_SSET            0x00000002 /* Set settings, privileged. */
#define ETHTOOL_GDRVINFO        0x00000003 /* Get driver info. */
#define ETHTOOL_GREGS           0x00000004 /* Get NIC registers, privileged. */
#define ETHTOOL_GWOL            0x00000005 /* Get wake-on-lan options. */
#define ETHTOOL_SWOL            0x00000006 /* Set wake-on-lan options, priv. */
#define ETHTOOL_GMSGLVL         0x00000007 /* Get driver message level */
#define ETHTOOL_SMSGLVL         0x00000008 /* Set driver msg level, priv. */
#define ETHTOOL_NWAY_RST        0x00000009 /* Restart autonegotiation, priv. */
#define ETHTOOL_GLINK           0x0000000a /* Get link status (ethtool_value) */
#define ETHTOOL_GEEPROM         0x0000000b /* Get EEPROM data */
#define ETHTOOL_SEEPROM         0x0000000c /* Set EEPROM data, priv. */
#define ETHTOOL_GCOALESCE       0x0000000e /* Get coalesce config */
#define ETHTOOL_SCOALESCE       0x0000000f /* Set coalesce config, priv. */
#define ETHTOOL_GRINGPARAM      0x00000010 /* Get ring parameters */
#define ETHTOOL_SRINGPARAM      0x00000011 /* Set ring parameters, priv. */
#define ETHTOOL_GPAUSEPARAM     0x00000012 /* Get pause parameters */
#define ETHTOOL_SPAUSEPARAM     0x00000013 /* Set pause parameters, priv. */
#define ETHTOOL_GRXCSUM         0x00000014 /* Get RX hw csum enable (ethtool_value) */
#define ETHTOOL_SRXCSUM         0x00000015 /* Set RX hw csum enable (ethtool_value) */

/* for passing single values */
struct ethtool_value {
        unsigned int     cmd;
        unsigned int     data;
};

extern int errno;
main(int argc, char ** argv)
{
    int mii_socket;
    int mii_ioctl;
    char if_name[10];
    struct ifreq ifr;
    struct ethtool_value edata;
    unsigned short *data = (unsigned short *) &ifr.ifr_data;

    if (argc == 1) {
        printf("usage: %s <ethX>\n", argv[0]);
        exit(1);
    }

    strcpy(if_name ,argv[1]);
    sprintf(ifr.ifr_name, "%s", if_name);
    edata.cmd = ETHTOOL_GLINK;
    ifr.ifr_data = (caddr_t)&edata;

    mii_socket = socket(AF_INET, SOCK_DGRAM, 0);
    if (mii_socket < 0 ) {
        printf ("MII link status socket open failed: %s\n", 
            strerror(errno));
        exit(1);
    }
   printf("mii_socket: %d\n", mii_socket);
   mii_ioctl = ioctl(mii_socket, SIOCETHTOOL, &ifr);
   if (mii_ioctl == 0 ) {
        printf("Proper MII ioctl for %s is SIOCETHTOOL.\n", if_name);
   } else {
        printf ("error, mii_ioctl: %u\n", mii_ioctl);
        exit (1);
   }

   edata.cmd = ETHTOOL_GLINK;
   ifr.ifr_data = (caddr_t)&edata;

   if (ioctl(mii_socket, SIOCETHTOOL, &ifr) != 0 ){
       printf("errno: %d, %s\n", errno, strerror(errno));
   }  else  {
      printf("status for %s: 0x%x\n", if_name, edata.data);
   }
}

Comment 1 Bill Hayes 2008-08-21 21:23:27 UTC
Andy,

I see that this change was submitted by Intel upstream and Dave Miller has taken it into his tree: http://git.kernel.org/?p=linux/kernel/git/davem/net-next-2.6.git;a=commitdiff;h=56e1f82968af79f70902008098a4687198142ce7.  Are these changes that you have pulled into the 5.3 kernel already?  Can it still make 5.3?

Bill

Comment 2 Andy Gospodarek 2008-08-21 21:28:08 UTC
Bill, that patch will get included.

Comment 3 Bill Hayes 2008-08-21 21:37:32 UTC
Andy, Thanks.  Let us know if you have a test kernel to try.

Comment 4 rick bieber 2008-08-22 15:08:05 UTC
Adding myself to cc list.

Comment 5 Andy Gospodarek 2008-08-26 20:29:45 UTC
My test kernels have been updated to include a patch for this bugzilla.

http://people.redhat.com/agospoda/#rhel5

Please test them and report back your results.

Comment 6 John DeFranco 2008-08-26 20:58:30 UTC
I will download the kernel and give it a try. It may take a day or two to gain access to the system. Will let you know the results.

Comment 7 John DeFranco 2008-09-04 16:55:07 UTC
I have tested with this new kernel. Results are good. The postfix results show:

fixed kernel for e1000e driver
[root@pltest12 ~]# uname -a
Linux pltest12.cup.hp.com 2.6.18-106.el5.gtest.54 #1 SMP Wed Aug 27 17:12:29 EDT
 2008 i686 athlon i386 GNU/Linux

[root@pltest12 ~]# ./test eth0
mii_socket: 3
Proper MII ioctl for eth0 is SIOCETHTOOL.
status for eth0: 0x0

[root@pltest12 ~]# ./test eth1
mii_socket: 3
Proper MII ioctl for eth1 is SIOCETHTOOL.
status for eth1: 0x1

[root@pltest12 ~]# ./test eth2
mii_socket: 3
Proper MII ioctl for eth2 is SIOCETHTOOL.
status for eth2: 0x0

[root@pltest12 ~]# ./test eth3
mii_socket: 3
Proper MII ioctl for eth3 is SIOCETHTOOL.
status for eth3: 0x0

eth0-3: e1000e, eth0,2, 3 are not connected, eth1 is connected.


In the above eth0-3 are all using the e1000e driver. eth1 is the nic that is connected the others are not. Running my test program (included in the original bugzilla submittal) shows that for eth0,2 and 3 the status is 0x0 and for eth1 its 0x1 which is correct. Previous results would show this as 0x2.

Comment 8 Andy Gospodarek 2009-01-28 21:34:03 UTC
This is in 5.3 kernels.  Closing.


Note You need to log in before you can comment on or make changes to this bug.