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® Ethernet, visit
http://communities.intel.com/community/wired