Hello,

I currently ran into this problem and had a fix for it. It will be great if 
someone take a look at it and let me know if there is anything wrong with the 
solution?

Environment
==========
Kernel Version:            2.6.32
Driver Version:             Intel(R) PRO/1000 Network Driver - 1.2.20-k2
Pci hardware info:      05:00.0 Ethernet controller: Intel Corporation 82574L 
Gigabit Network Connection


Problem
=======
In the normal case, both the interfaces are up on the local machine and switch. 
Ethool returns Link detected yes, speed and duplex.
Settings for lan2_0:
        Supported ports: [ FIBRE ]
        Supported link modes:   1000baseT/Full 
        Supports auto-negotiation: Yes
        Advertised link modes:  1000baseT/Full 
        Advertised pause frame use: No
        Advertised auto-negotiation: Yes
        Speed: 1000Mb/s
        Duplex: Full
        Port: FIBRE
        PHYAD: 0
        Transceiver: external
        Auto-negotiation: on
        Supports Wake-on: d
        Wake-on: d
        Current message level: 0x00000001 (1)
        Link detected: yes

Problem occurred when shutting down the interface on the switch. Ethool returns 
Link detected no and mistakenly print out speed and duplex.
Settings for lan2_0:
    Supported ports: [ FIBRE ]
    Supported link modes:   1000baseT/Full 
    Supports auto-negotiation: Yes
    Advertised link modes:  1000baseT/Full 
    Advertised pause frame use: No
    Advertised auto-negotiation: Yes
    Speed: 1000Mb/s           <---------- should be Unknown!
    Duplex: Full                       <---------- should be Unknown!
    Port: FIBRE
    PHYAD: 0
    Transceiver: external
    Auto-negotiation: on
    Supports Wake-on: d
    Wake-on: d
    Current message level: 0x00000001 (1)
    Link detected: no         <--------- Link is down

Added some printk statements and I have tracked it down to the following code 
e1000_get_settings()

        if (netif_running(netdev)) {
                if (netif_carrier_ok(netdev)) {
                        ecmd->speed = adapter->link_speed;
                        ecmd->duplex = adapter->link_duplex - 1;
                }
        } else {
                u32 status = er32(STATUS);
                if (status & E1000_STATUS_LU) {                     <---------- 
The code checks bit-2 of STATUS register to determine if there the link is up 
or not.
                        if (status & E1000_STATUS_SPEED_1000)
                                ecmd->speed = 1000;
                        else if (status & E1000_STATUS_SPEED_100)
                                ecmd->speed = 100;
                        else
                                ecmd->speed = 10;

                        if (status & E1000_STATUS_FD)
                                ecmd->duplex = DUPLEX_FULL;
                        else
                                ecmd->duplex = DUPLEX_HALF;
                }
        }

Investigation and Solution
====================
I have checked the Intel 82574 Gbe Controller Family datasheet, section 
10.2.2.2 has the following information about this bit.

"Link Up
0b = No link establish
1b = Link establish. For this to be valid, the Set Link Up bit of the Device 
Control (CTRL.SU) register must be set."

So, it looks like just checking this bit may not be a reliable way to determine 
if link is up and that's why this problem don't show up on some other machines.

Next, I changed the code to call netif_carrier_ok() (the way ethtool detects 
link up/down). The speed and duplex printed as "Unknown!" which is the expected 
result.

       if (netif_running(netdev)) {
                if (netif_carrier_ok(netdev)) {
                        ecmd->speed = adapter->link_speed;
                        ecmd->duplex = adapter->link_duplex - 1;
                }
        } else {
                if (netif_carrier_ok(netdev)) {                        
<--------- Change is made here.
                        u32 status = er32(STATUS);

                        if (status & E1000_STATUS_SPEED_1000)
                                ecmd->speed = 1000;
                        else if (status & E1000_STATUS_SPEED_100)
                                ecmd->speed = 100;
                        else
                                ecmd->speed = 10;

                        if (status & E1000_STATUS_FD)
                                ecmd->duplex = DUPLEX_FULL;
                        else
                                ecmd->duplex = DUPLEX_HALF;
                }
        }

Your comments to the fix will be greatly appreciated.

Thanks and regards,
--Steven


------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
E1000-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/e1000-devel
To learn more about Intel&#174; Ethernet, visit 
http://communities.intel.com/community/wired

Reply via email to