diff options
author | Jesse Brandeburg <jesse.brandeburg@intel.com> | 2009-09-25 08:17:44 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-09-26 23:15:36 -0400 |
commit | be0f071956e2142e2e88e9d6d5655ba1c75d07c8 (patch) | |
tree | e0b1be3f259841aaabcfbb02c4495dd2580d0130 /drivers/net/e1000/e1000_main.c | |
parent | baa34745fe6263c733f43feddb0b8100d6538f37 (diff) |
e1000: test link state conclusively
e1000 was using one particular way to detect link, but with the advent
of some of the newer hardware designs using SERDES connections, tests
for link must completely cover all cases.
Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Signed-off-by: Don Skidmore <donald.c.skidmore@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/e1000/e1000_main.c')
-rw-r--r-- | drivers/net/e1000/e1000_main.c | 49 |
1 files changed, 41 insertions, 8 deletions
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 7af3255a8e9c..11508afdfdb9 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c | |||
@@ -2251,6 +2251,41 @@ static void e1000_82547_tx_fifo_stall(unsigned long data) | |||
2251 | } | 2251 | } |
2252 | } | 2252 | } |
2253 | 2253 | ||
2254 | static bool e1000_has_link(struct e1000_adapter *adapter) | ||
2255 | { | ||
2256 | struct e1000_hw *hw = &adapter->hw; | ||
2257 | bool link_active = false; | ||
2258 | s32 ret_val = 0; | ||
2259 | |||
2260 | /* get_link_status is set on LSC (link status) interrupt or | ||
2261 | * rx sequence error interrupt. get_link_status will stay | ||
2262 | * false until the e1000_check_for_link establishes link | ||
2263 | * for copper adapters ONLY | ||
2264 | */ | ||
2265 | switch (hw->media_type) { | ||
2266 | case e1000_media_type_copper: | ||
2267 | if (hw->get_link_status) { | ||
2268 | ret_val = e1000_check_for_link(hw); | ||
2269 | link_active = !hw->get_link_status; | ||
2270 | } else { | ||
2271 | link_active = true; | ||
2272 | } | ||
2273 | break; | ||
2274 | case e1000_media_type_fiber: | ||
2275 | ret_val = e1000_check_for_link(hw); | ||
2276 | link_active = !!(er32(STATUS) & E1000_STATUS_LU); | ||
2277 | break; | ||
2278 | case e1000_media_type_internal_serdes: | ||
2279 | ret_val = e1000_check_for_link(hw); | ||
2280 | link_active = hw->serdes_has_link; | ||
2281 | break; | ||
2282 | default: | ||
2283 | break; | ||
2284 | } | ||
2285 | |||
2286 | return link_active; | ||
2287 | } | ||
2288 | |||
2254 | /** | 2289 | /** |
2255 | * e1000_watchdog - Timer Call-back | 2290 | * e1000_watchdog - Timer Call-back |
2256 | * @data: pointer to adapter cast into an unsigned long | 2291 | * @data: pointer to adapter cast into an unsigned long |
@@ -2263,18 +2298,15 @@ static void e1000_watchdog(unsigned long data) | |||
2263 | struct e1000_tx_ring *txdr = adapter->tx_ring; | 2298 | struct e1000_tx_ring *txdr = adapter->tx_ring; |
2264 | u32 link, tctl; | 2299 | u32 link, tctl; |
2265 | 2300 | ||
2266 | e1000_check_for_link(hw); | 2301 | link = e1000_has_link(adapter); |
2267 | 2302 | if ((netif_carrier_ok(netdev)) && link) | |
2268 | if ((hw->media_type == e1000_media_type_internal_serdes) && | 2303 | goto link_up; |
2269 | !(er32(TXCW) & E1000_TXCW_ANE)) | ||
2270 | link = !hw->serdes_link_down; | ||
2271 | else | ||
2272 | link = er32(STATUS) & E1000_STATUS_LU; | ||
2273 | 2304 | ||
2274 | if (link) { | 2305 | if (link) { |
2275 | if (!netif_carrier_ok(netdev)) { | 2306 | if (!netif_carrier_ok(netdev)) { |
2276 | u32 ctrl; | 2307 | u32 ctrl; |
2277 | bool txb2b = true; | 2308 | bool txb2b = true; |
2309 | /* update snapshot of PHY registers on LSC */ | ||
2278 | e1000_get_speed_and_duplex(hw, | 2310 | e1000_get_speed_and_duplex(hw, |
2279 | &adapter->link_speed, | 2311 | &adapter->link_speed, |
2280 | &adapter->link_duplex); | 2312 | &adapter->link_duplex); |
@@ -2299,7 +2331,7 @@ static void e1000_watchdog(unsigned long data) | |||
2299 | case SPEED_10: | 2331 | case SPEED_10: |
2300 | txb2b = false; | 2332 | txb2b = false; |
2301 | netdev->tx_queue_len = 10; | 2333 | netdev->tx_queue_len = 10; |
2302 | adapter->tx_timeout_factor = 8; | 2334 | adapter->tx_timeout_factor = 16; |
2303 | break; | 2335 | break; |
2304 | case SPEED_100: | 2336 | case SPEED_100: |
2305 | txb2b = false; | 2337 | txb2b = false; |
@@ -2335,6 +2367,7 @@ static void e1000_watchdog(unsigned long data) | |||
2335 | e1000_smartspeed(adapter); | 2367 | e1000_smartspeed(adapter); |
2336 | } | 2368 | } |
2337 | 2369 | ||
2370 | link_up: | ||
2338 | e1000_update_stats(adapter); | 2371 | e1000_update_stats(adapter); |
2339 | 2372 | ||
2340 | hw->tx_packet_delta = adapter->stats.tpt - adapter->tpt_old; | 2373 | hw->tx_packet_delta = adapter->stats.tpt - adapter->tpt_old; |