diff options
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 7af3255a8e9..11508afdfdb 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; |