aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/e1000/e1000_main.c
diff options
context:
space:
mode:
authorJesse Brandeburg <jesse.brandeburg@intel.com>2009-09-25 08:17:44 -0400
committerDavid S. Miller <davem@davemloft.net>2009-09-26 23:15:36 -0400
commitbe0f071956e2142e2e88e9d6d5655ba1c75d07c8 (patch)
treee0b1be3f259841aaabcfbb02c4495dd2580d0130 /drivers/net/e1000/e1000_main.c
parentbaa34745fe6263c733f43feddb0b8100d6538f37 (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.c49
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
2254static 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
2370link_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;