diff options
author | Bruce Allan <bruce.w.allan@intel.com> | 2009-07-01 09:29:08 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-07-03 23:09:42 -0400 |
commit | 7d3cabbcc86f7f69c47cb20c23ee84350ae6cfbb (patch) | |
tree | 9fb7d845cbcc5da255dc2cf9dd32a612ff29456b /drivers/net/e1000e | |
parent | 906e8d9792b1c4a8b58c1383f4c00fc4c9936fc3 (diff) |
e1000e: disable K1 at 1000Mbps for 82577/82578
This workaround is required for an issue in hardware where noise on the
interconnect between the MAC and PHY could be generated by a lower power
mode (K1) at 1000Mbps resulting in bad packets. Disable K1 while at 1000
Mbps but keep it enabled for 10/100Mbps and when the cable is disconnected.
Signed-off-by: Bruce Allan <bruce.w.allan@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/e1000e')
-rw-r--r-- | drivers/net/e1000e/hw.h | 4 | ||||
-rw-r--r-- | drivers/net/e1000e/ich8lan.c | 107 | ||||
-rw-r--r-- | drivers/net/e1000e/lib.c | 6 |
3 files changed, 110 insertions, 7 deletions
diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h index 163c1c0cfee7..fd44d9f90769 100644 --- a/drivers/net/e1000e/hw.h +++ b/drivers/net/e1000e/hw.h | |||
@@ -215,6 +215,7 @@ enum e1e_registers { | |||
215 | E1000_SWSM = 0x05B50, /* SW Semaphore */ | 215 | E1000_SWSM = 0x05B50, /* SW Semaphore */ |
216 | E1000_FWSM = 0x05B54, /* FW Semaphore */ | 216 | E1000_FWSM = 0x05B54, /* FW Semaphore */ |
217 | E1000_SWSM2 = 0x05B58, /* Driver-only SW semaphore */ | 217 | E1000_SWSM2 = 0x05B58, /* Driver-only SW semaphore */ |
218 | E1000_CRC_OFFSET = 0x05F50, /* CRC Offset register */ | ||
218 | E1000_HICR = 0x08F00, /* Host Interface Control */ | 219 | E1000_HICR = 0x08F00, /* Host Interface Control */ |
219 | }; | 220 | }; |
220 | 221 | ||
@@ -302,6 +303,9 @@ enum e1e_registers { | |||
302 | #define E1000_KMRNCTRLSTA_REN 0x00200000 | 303 | #define E1000_KMRNCTRLSTA_REN 0x00200000 |
303 | #define E1000_KMRNCTRLSTA_DIAG_OFFSET 0x3 /* Kumeran Diagnostic */ | 304 | #define E1000_KMRNCTRLSTA_DIAG_OFFSET 0x3 /* Kumeran Diagnostic */ |
304 | #define E1000_KMRNCTRLSTA_DIAG_NELPBK 0x1000 /* Nearend Loopback mode */ | 305 | #define E1000_KMRNCTRLSTA_DIAG_NELPBK 0x1000 /* Nearend Loopback mode */ |
306 | #define E1000_KMRNCTRLSTA_K1_CONFIG 0x7 | ||
307 | #define E1000_KMRNCTRLSTA_K1_ENABLE 0x140E | ||
308 | #define E1000_KMRNCTRLSTA_K1_DISABLE 0x1400 | ||
305 | 309 | ||
306 | #define IFE_PHY_EXTENDED_STATUS_CONTROL 0x10 | 310 | #define IFE_PHY_EXTENDED_STATUS_CONTROL 0x10 |
307 | #define IFE_PHY_SPECIAL_CONTROL 0x11 /* 100BaseTx PHY Special Control */ | 311 | #define IFE_PHY_SPECIAL_CONTROL 0x11 /* 100BaseTx PHY Special Control */ |
diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c index 0e0755f0db3f..d56c7473144a 100644 --- a/drivers/net/e1000e/ich8lan.c +++ b/drivers/net/e1000e/ich8lan.c | |||
@@ -461,6 +461,95 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_adapter *adapter) | |||
461 | return 0; | 461 | return 0; |
462 | } | 462 | } |
463 | 463 | ||
464 | /** | ||
465 | * e1000_check_for_copper_link_ich8lan - Check for link (Copper) | ||
466 | * @hw: pointer to the HW structure | ||
467 | * | ||
468 | * Checks to see of the link status of the hardware has changed. If a | ||
469 | * change in link status has been detected, then we read the PHY registers | ||
470 | * to get the current speed/duplex if link exists. | ||
471 | **/ | ||
472 | static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) | ||
473 | { | ||
474 | struct e1000_mac_info *mac = &hw->mac; | ||
475 | s32 ret_val; | ||
476 | bool link; | ||
477 | |||
478 | /* | ||
479 | * We only want to go out to the PHY registers to see if Auto-Neg | ||
480 | * has completed and/or if our link status has changed. The | ||
481 | * get_link_status flag is set upon receiving a Link Status | ||
482 | * Change or Rx Sequence Error interrupt. | ||
483 | */ | ||
484 | if (!mac->get_link_status) { | ||
485 | ret_val = 0; | ||
486 | goto out; | ||
487 | } | ||
488 | |||
489 | if (hw->mac.type == e1000_pchlan) { | ||
490 | ret_val = e1000e_write_kmrn_reg(hw, | ||
491 | E1000_KMRNCTRLSTA_K1_CONFIG, | ||
492 | E1000_KMRNCTRLSTA_K1_ENABLE); | ||
493 | if (ret_val) | ||
494 | goto out; | ||
495 | } | ||
496 | |||
497 | /* | ||
498 | * First we want to see if the MII Status Register reports | ||
499 | * link. If so, then we want to get the current speed/duplex | ||
500 | * of the PHY. | ||
501 | */ | ||
502 | ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link); | ||
503 | if (ret_val) | ||
504 | goto out; | ||
505 | |||
506 | if (!link) | ||
507 | goto out; /* No link detected */ | ||
508 | |||
509 | mac->get_link_status = false; | ||
510 | |||
511 | if (hw->phy.type == e1000_phy_82578) { | ||
512 | ret_val = e1000_link_stall_workaround_hv(hw); | ||
513 | if (ret_val) | ||
514 | goto out; | ||
515 | } | ||
516 | |||
517 | /* | ||
518 | * Check if there was DownShift, must be checked | ||
519 | * immediately after link-up | ||
520 | */ | ||
521 | e1000e_check_downshift(hw); | ||
522 | |||
523 | /* | ||
524 | * If we are forcing speed/duplex, then we simply return since | ||
525 | * we have already determined whether we have link or not. | ||
526 | */ | ||
527 | if (!mac->autoneg) { | ||
528 | ret_val = -E1000_ERR_CONFIG; | ||
529 | goto out; | ||
530 | } | ||
531 | |||
532 | /* | ||
533 | * Auto-Neg is enabled. Auto Speed Detection takes care | ||
534 | * of MAC speed/duplex configuration. So we only need to | ||
535 | * configure Collision Distance in the MAC. | ||
536 | */ | ||
537 | e1000e_config_collision_dist(hw); | ||
538 | |||
539 | /* | ||
540 | * Configure Flow Control now that Auto-Neg has completed. | ||
541 | * First, we need to restore the desired flow control | ||
542 | * settings because we may have had to re-autoneg with a | ||
543 | * different link partner. | ||
544 | */ | ||
545 | ret_val = e1000e_config_fc_after_link_up(hw); | ||
546 | if (ret_val) | ||
547 | hw_dbg(hw, "Error configuring flow control\n"); | ||
548 | |||
549 | out: | ||
550 | return ret_val; | ||
551 | } | ||
552 | |||
464 | static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter) | 553 | static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter) |
465 | { | 554 | { |
466 | struct e1000_hw *hw = &adapter->hw; | 555 | struct e1000_hw *hw = &adapter->hw; |
@@ -2224,6 +2313,14 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) | |||
2224 | } | 2313 | } |
2225 | } | 2314 | } |
2226 | 2315 | ||
2316 | /* | ||
2317 | * For PCH, this write will make sure that any noise | ||
2318 | * will be detected as a CRC error and be dropped rather than show up | ||
2319 | * as a bad packet to the DMA engine. | ||
2320 | */ | ||
2321 | if (hw->mac.type == e1000_pchlan) | ||
2322 | ew32(CRC_OFFSET, 0x65656565); | ||
2323 | |||
2227 | ew32(IMC, 0xffffffff); | 2324 | ew32(IMC, 0xffffffff); |
2228 | icr = er32(ICR); | 2325 | icr = er32(ICR); |
2229 | 2326 | ||
@@ -2538,6 +2635,14 @@ static s32 e1000_get_link_up_info_ich8lan(struct e1000_hw *hw, u16 *speed, | |||
2538 | if (ret_val) | 2635 | if (ret_val) |
2539 | return ret_val; | 2636 | return ret_val; |
2540 | 2637 | ||
2638 | if ((hw->mac.type == e1000_pchlan) && (*speed == SPEED_1000)) { | ||
2639 | ret_val = e1000e_write_kmrn_reg(hw, | ||
2640 | E1000_KMRNCTRLSTA_K1_CONFIG, | ||
2641 | E1000_KMRNCTRLSTA_K1_DISABLE); | ||
2642 | if (ret_val) | ||
2643 | return ret_val; | ||
2644 | } | ||
2645 | |||
2541 | if ((hw->mac.type == e1000_ich8lan) && | 2646 | if ((hw->mac.type == e1000_ich8lan) && |
2542 | (hw->phy.type == e1000_phy_igp_3) && | 2647 | (hw->phy.type == e1000_phy_igp_3) && |
2543 | (*speed == SPEED_1000)) { | 2648 | (*speed == SPEED_1000)) { |
@@ -2984,7 +3089,7 @@ static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw) | |||
2984 | static struct e1000_mac_operations ich8_mac_ops = { | 3089 | static struct e1000_mac_operations ich8_mac_ops = { |
2985 | .id_led_init = e1000e_id_led_init, | 3090 | .id_led_init = e1000e_id_led_init, |
2986 | .check_mng_mode = e1000_check_mng_mode_ich8lan, | 3091 | .check_mng_mode = e1000_check_mng_mode_ich8lan, |
2987 | .check_for_link = e1000e_check_for_copper_link, | 3092 | .check_for_link = e1000_check_for_copper_link_ich8lan, |
2988 | /* cleanup_led dependent on mac type */ | 3093 | /* cleanup_led dependent on mac type */ |
2989 | .clear_hw_cntrs = e1000_clear_hw_cntrs_ich8lan, | 3094 | .clear_hw_cntrs = e1000_clear_hw_cntrs_ich8lan, |
2990 | .get_bus_info = e1000_get_bus_info_ich8lan, | 3095 | .get_bus_info = e1000_get_bus_info_ich8lan, |
diff --git a/drivers/net/e1000e/lib.c b/drivers/net/e1000e/lib.c index be6d9e990374..99ba2b8a2a05 100644 --- a/drivers/net/e1000e/lib.c +++ b/drivers/net/e1000e/lib.c | |||
@@ -378,12 +378,6 @@ s32 e1000e_check_for_copper_link(struct e1000_hw *hw) | |||
378 | 378 | ||
379 | mac->get_link_status = 0; | 379 | mac->get_link_status = 0; |
380 | 380 | ||
381 | if (hw->phy.type == e1000_phy_82578) { | ||
382 | ret_val = e1000_link_stall_workaround_hv(hw); | ||
383 | if (ret_val) | ||
384 | return ret_val; | ||
385 | } | ||
386 | |||
387 | /* | 381 | /* |
388 | * Check if there was DownShift, must be checked | 382 | * Check if there was DownShift, must be checked |
389 | * immediately after link-up | 383 | * immediately after link-up |