Commit 1d5846b9216665d0ae743bf351d0b8fa90c40523
Committed by
David S. Miller
1 parent
f523d2114e
Exists in
master
and in
39 other branches
e1000e: rework disable K1 at 1000Mbps for 82577/82578
This patch reworks a previous workaround (commit 7d3cabbcc) 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. The original version of this workaround was found to be incomplete. 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>
Showing 5 changed files with 190 additions and 28 deletions Side-by-side Diff
drivers/net/e1000e/defines.h
... | ... | @@ -76,6 +76,7 @@ |
76 | 76 | /* Extended Device Control */ |
77 | 77 | #define E1000_CTRL_EXT_SDP7_DATA 0x00000080 /* Value of SW Definable Pin 7 */ |
78 | 78 | #define E1000_CTRL_EXT_EE_RST 0x00002000 /* Reinitialize from EEPROM */ |
79 | +#define E1000_CTRL_EXT_SPD_BYPS 0x00008000 /* Speed Select Bypass */ | |
79 | 80 | #define E1000_CTRL_EXT_RO_DIS 0x00020000 /* Relaxed Ordering disable */ |
80 | 81 | #define E1000_CTRL_EXT_DMA_DYN_CLK_EN 0x00080000 /* DMA Dynamic Clock Gating */ |
81 | 82 | #define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000 |
drivers/net/e1000e/e1000.h
... | ... | @@ -141,6 +141,20 @@ |
141 | 141 | #define HV_TNCRS_UPPER PHY_REG(778, 29) /* Transmit with no CRS */ |
142 | 142 | #define HV_TNCRS_LOWER PHY_REG(778, 30) |
143 | 143 | |
144 | +/* BM PHY Copper Specific Status */ | |
145 | +#define BM_CS_STATUS 17 | |
146 | +#define BM_CS_STATUS_LINK_UP 0x0400 | |
147 | +#define BM_CS_STATUS_RESOLVED 0x0800 | |
148 | +#define BM_CS_STATUS_SPEED_MASK 0xC000 | |
149 | +#define BM_CS_STATUS_SPEED_1000 0x8000 | |
150 | + | |
151 | +/* 82577 Mobile Phy Status Register */ | |
152 | +#define HV_M_STATUS 26 | |
153 | +#define HV_M_STATUS_AUTONEG_COMPLETE 0x1000 | |
154 | +#define HV_M_STATUS_SPEED_MASK 0x0300 | |
155 | +#define HV_M_STATUS_SPEED_1000 0x0200 | |
156 | +#define HV_M_STATUS_LINK_UP 0x0040 | |
157 | + | |
144 | 158 | enum e1000_boards { |
145 | 159 | board_82571, |
146 | 160 | board_82572, |
drivers/net/e1000e/hw.h
drivers/net/e1000e/ich8lan.c
... | ... | @@ -140,6 +140,9 @@ |
140 | 140 | #define HV_OEM_BITS_GBE_DIS 0x0040 /* Gigabit Disable */ |
141 | 141 | #define HV_OEM_BITS_RESTART_AN 0x0400 /* Restart Auto-negotiation */ |
142 | 142 | |
143 | +#define E1000_NVM_K1_CONFIG 0x1B /* NVM K1 Config Word */ | |
144 | +#define E1000_NVM_K1_ENABLE 0x1 /* NVM Enable K1 bit */ | |
145 | + | |
143 | 146 | /* ICH GbE Flash Hardware Sequencing Flash Status Register bit breakdown */ |
144 | 147 | /* Offset 04h HSFSTS */ |
145 | 148 | union ich8_hws_flash_status { |
... | ... | @@ -220,6 +223,8 @@ |
220 | 223 | static s32 e1000_led_off_pchlan(struct e1000_hw *hw); |
221 | 224 | static s32 e1000_set_lplu_state_pchlan(struct e1000_hw *hw, bool active); |
222 | 225 | static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw); |
226 | +static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link); | |
227 | +static s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable); | |
223 | 228 | |
224 | 229 | static inline u16 __er16flash(struct e1000_hw *hw, unsigned long reg) |
225 | 230 | { |
... | ... | @@ -495,14 +500,6 @@ |
495 | 500 | goto out; |
496 | 501 | } |
497 | 502 | |
498 | - if (hw->mac.type == e1000_pchlan) { | |
499 | - ret_val = e1000e_write_kmrn_reg(hw, | |
500 | - E1000_KMRNCTRLSTA_K1_CONFIG, | |
501 | - E1000_KMRNCTRLSTA_K1_ENABLE); | |
502 | - if (ret_val) | |
503 | - goto out; | |
504 | - } | |
505 | - | |
506 | 503 | /* |
507 | 504 | * First we want to see if the MII Status Register reports |
508 | 505 | * link. If so, then we want to get the current speed/duplex |
... | ... | @@ -512,6 +509,12 @@ |
512 | 509 | if (ret_val) |
513 | 510 | goto out; |
514 | 511 | |
512 | + if (hw->mac.type == e1000_pchlan) { | |
513 | + ret_val = e1000_k1_gig_workaround_hv(hw, link); | |
514 | + if (ret_val) | |
515 | + goto out; | |
516 | + } | |
517 | + | |
515 | 518 | if (!link) |
516 | 519 | goto out; /* No link detected */ |
517 | 520 | |
... | ... | @@ -929,6 +932,141 @@ |
929 | 932 | } |
930 | 933 | |
931 | 934 | /** |
935 | + * e1000_k1_gig_workaround_hv - K1 Si workaround | |
936 | + * @hw: pointer to the HW structure | |
937 | + * @link: link up bool flag | |
938 | + * | |
939 | + * If K1 is enabled for 1Gbps, the MAC might stall when transitioning | |
940 | + * from a lower speed. This workaround disables K1 whenever link is at 1Gig | |
941 | + * If link is down, the function will restore the default K1 setting located | |
942 | + * in the NVM. | |
943 | + **/ | |
944 | +static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link) | |
945 | +{ | |
946 | + s32 ret_val = 0; | |
947 | + u16 status_reg = 0; | |
948 | + bool k1_enable = hw->dev_spec.ich8lan.nvm_k1_enabled; | |
949 | + | |
950 | + if (hw->mac.type != e1000_pchlan) | |
951 | + goto out; | |
952 | + | |
953 | + /* Wrap the whole flow with the sw flag */ | |
954 | + ret_val = hw->phy.ops.acquire_phy(hw); | |
955 | + if (ret_val) | |
956 | + goto out; | |
957 | + | |
958 | + /* Disable K1 when link is 1Gbps, otherwise use the NVM setting */ | |
959 | + if (link) { | |
960 | + if (hw->phy.type == e1000_phy_82578) { | |
961 | + ret_val = hw->phy.ops.read_phy_reg_locked(hw, | |
962 | + BM_CS_STATUS, | |
963 | + &status_reg); | |
964 | + if (ret_val) | |
965 | + goto release; | |
966 | + | |
967 | + status_reg &= BM_CS_STATUS_LINK_UP | | |
968 | + BM_CS_STATUS_RESOLVED | | |
969 | + BM_CS_STATUS_SPEED_MASK; | |
970 | + | |
971 | + if (status_reg == (BM_CS_STATUS_LINK_UP | | |
972 | + BM_CS_STATUS_RESOLVED | | |
973 | + BM_CS_STATUS_SPEED_1000)) | |
974 | + k1_enable = false; | |
975 | + } | |
976 | + | |
977 | + if (hw->phy.type == e1000_phy_82577) { | |
978 | + ret_val = hw->phy.ops.read_phy_reg_locked(hw, | |
979 | + HV_M_STATUS, | |
980 | + &status_reg); | |
981 | + if (ret_val) | |
982 | + goto release; | |
983 | + | |
984 | + status_reg &= HV_M_STATUS_LINK_UP | | |
985 | + HV_M_STATUS_AUTONEG_COMPLETE | | |
986 | + HV_M_STATUS_SPEED_MASK; | |
987 | + | |
988 | + if (status_reg == (HV_M_STATUS_LINK_UP | | |
989 | + HV_M_STATUS_AUTONEG_COMPLETE | | |
990 | + HV_M_STATUS_SPEED_1000)) | |
991 | + k1_enable = false; | |
992 | + } | |
993 | + | |
994 | + /* Link stall fix for link up */ | |
995 | + ret_val = hw->phy.ops.write_phy_reg_locked(hw, PHY_REG(770, 19), | |
996 | + 0x0100); | |
997 | + if (ret_val) | |
998 | + goto release; | |
999 | + | |
1000 | + } else { | |
1001 | + /* Link stall fix for link down */ | |
1002 | + ret_val = hw->phy.ops.write_phy_reg_locked(hw, PHY_REG(770, 19), | |
1003 | + 0x4100); | |
1004 | + if (ret_val) | |
1005 | + goto release; | |
1006 | + } | |
1007 | + | |
1008 | + ret_val = e1000_configure_k1_ich8lan(hw, k1_enable); | |
1009 | + | |
1010 | +release: | |
1011 | + hw->phy.ops.release_phy(hw); | |
1012 | +out: | |
1013 | + return ret_val; | |
1014 | +} | |
1015 | + | |
1016 | +/** | |
1017 | + * e1000_configure_k1_ich8lan - Configure K1 power state | |
1018 | + * @hw: pointer to the HW structure | |
1019 | + * @enable: K1 state to configure | |
1020 | + * | |
1021 | + * Configure the K1 power state based on the provided parameter. | |
1022 | + * Assumes semaphore already acquired. | |
1023 | + * | |
1024 | + * Success returns 0, Failure returns -E1000_ERR_PHY (-2) | |
1025 | + **/ | |
1026 | +static s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable) | |
1027 | +{ | |
1028 | + s32 ret_val = 0; | |
1029 | + u32 ctrl_reg = 0; | |
1030 | + u32 ctrl_ext = 0; | |
1031 | + u32 reg = 0; | |
1032 | + u16 kmrn_reg = 0; | |
1033 | + | |
1034 | + ret_val = e1000e_read_kmrn_reg_locked(hw, | |
1035 | + E1000_KMRNCTRLSTA_K1_CONFIG, | |
1036 | + &kmrn_reg); | |
1037 | + if (ret_val) | |
1038 | + goto out; | |
1039 | + | |
1040 | + if (k1_enable) | |
1041 | + kmrn_reg |= E1000_KMRNCTRLSTA_K1_ENABLE; | |
1042 | + else | |
1043 | + kmrn_reg &= ~E1000_KMRNCTRLSTA_K1_ENABLE; | |
1044 | + | |
1045 | + ret_val = e1000e_write_kmrn_reg_locked(hw, | |
1046 | + E1000_KMRNCTRLSTA_K1_CONFIG, | |
1047 | + kmrn_reg); | |
1048 | + if (ret_val) | |
1049 | + goto out; | |
1050 | + | |
1051 | + udelay(20); | |
1052 | + ctrl_ext = er32(CTRL_EXT); | |
1053 | + ctrl_reg = er32(CTRL); | |
1054 | + | |
1055 | + reg = ctrl_reg & ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100); | |
1056 | + reg |= E1000_CTRL_FRCSPD; | |
1057 | + ew32(CTRL, reg); | |
1058 | + | |
1059 | + ew32(CTRL_EXT, ctrl_ext | E1000_CTRL_EXT_SPD_BYPS); | |
1060 | + udelay(20); | |
1061 | + ew32(CTRL, ctrl_reg); | |
1062 | + ew32(CTRL_EXT, ctrl_ext); | |
1063 | + udelay(20); | |
1064 | + | |
1065 | +out: | |
1066 | + return ret_val; | |
1067 | +} | |
1068 | + | |
1069 | +/** | |
932 | 1070 | * e1000_oem_bits_config_ich8lan - SW-based LCD Configuration |
933 | 1071 | * @hw: pointer to the HW structure |
934 | 1072 | * @d0_state: boolean if entering d0 or d3 device state |
935 | 1073 | |
936 | 1074 | |
... | ... | @@ -1030,10 +1168,20 @@ |
1030 | 1168 | ret_val = hw->phy.ops.acquire_phy(hw); |
1031 | 1169 | if (ret_val) |
1032 | 1170 | return ret_val; |
1171 | + | |
1033 | 1172 | hw->phy.addr = 1; |
1034 | - e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, 0); | |
1173 | + ret_val = e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, 0); | |
1174 | + if (ret_val) | |
1175 | + goto out; | |
1035 | 1176 | hw->phy.ops.release_phy(hw); |
1036 | 1177 | |
1178 | + /* | |
1179 | + * Configure the K1 Si workaround during phy reset assuming there is | |
1180 | + * link so that it disables K1 if link is in 1Gbps. | |
1181 | + */ | |
1182 | + ret_val = e1000_k1_gig_workaround_hv(hw, true); | |
1183 | + | |
1184 | +out: | |
1037 | 1185 | return ret_val; |
1038 | 1186 | } |
1039 | 1187 | |
... | ... | @@ -2435,6 +2583,7 @@ |
2435 | 2583 | **/ |
2436 | 2584 | static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) |
2437 | 2585 | { |
2586 | + struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; | |
2438 | 2587 | u16 reg; |
2439 | 2588 | u32 ctrl, icr, kab; |
2440 | 2589 | s32 ret_val; |
... | ... | @@ -2470,6 +2619,18 @@ |
2470 | 2619 | ew32(PBS, E1000_PBS_16K); |
2471 | 2620 | } |
2472 | 2621 | |
2622 | + if (hw->mac.type == e1000_pchlan) { | |
2623 | + /* Save the NVM K1 bit setting*/ | |
2624 | + ret_val = e1000_read_nvm(hw, E1000_NVM_K1_CONFIG, 1, ®); | |
2625 | + if (ret_val) | |
2626 | + return ret_val; | |
2627 | + | |
2628 | + if (reg & E1000_NVM_K1_ENABLE) | |
2629 | + dev_spec->nvm_k1_enabled = true; | |
2630 | + else | |
2631 | + dev_spec->nvm_k1_enabled = false; | |
2632 | + } | |
2633 | + | |
2473 | 2634 | ctrl = er32(CTRL); |
2474 | 2635 | |
2475 | 2636 | if (!e1000_check_reset_block(hw)) { |
... | ... | @@ -2846,14 +3007,6 @@ |
2846 | 3007 | ret_val = e1000e_get_speed_and_duplex_copper(hw, speed, duplex); |
2847 | 3008 | if (ret_val) |
2848 | 3009 | return ret_val; |
2849 | - | |
2850 | - if ((hw->mac.type == e1000_pchlan) && (*speed == SPEED_1000)) { | |
2851 | - ret_val = e1000e_write_kmrn_reg(hw, | |
2852 | - E1000_KMRNCTRLSTA_K1_CONFIG, | |
2853 | - E1000_KMRNCTRLSTA_K1_DISABLE); | |
2854 | - if (ret_val) | |
2855 | - return ret_val; | |
2856 | - } | |
2857 | 3010 | |
2858 | 3011 | if ((hw->mac.type == e1000_ich8lan) && |
2859 | 3012 | (hw->phy.type == e1000_phy_igp_3) && |
drivers/net/e1000e/phy.c
... | ... | @@ -95,13 +95,6 @@ |
95 | 95 | /* BM PHY Copper Specific Control 1 */ |
96 | 96 | #define BM_CS_CTRL1 16 |
97 | 97 | |
98 | -/* BM PHY Copper Specific Status */ | |
99 | -#define BM_CS_STATUS 17 | |
100 | -#define BM_CS_STATUS_LINK_UP 0x0400 | |
101 | -#define BM_CS_STATUS_RESOLVED 0x0800 | |
102 | -#define BM_CS_STATUS_SPEED_MASK 0xC000 | |
103 | -#define BM_CS_STATUS_SPEED_1000 0x8000 | |
104 | - | |
105 | 98 | #define HV_MUX_DATA_CTRL PHY_REG(776, 16) |
106 | 99 | #define HV_MUX_DATA_CTRL_GEN_TO_MAC 0x0400 |
107 | 100 | #define HV_MUX_DATA_CTRL_FORCE_SPEED 0x0004 |
... | ... | @@ -563,7 +556,7 @@ |
563 | 556 | } |
564 | 557 | |
565 | 558 | /** |
566 | - * e1000_read_kmrn_reg_locked - Read kumeran register | |
559 | + * e1000e_read_kmrn_reg_locked - Read kumeran register | |
567 | 560 | * @hw: pointer to the HW structure |
568 | 561 | * @offset: register offset to be read |
569 | 562 | * @data: pointer to the read data |
... | ... | @@ -572,7 +565,7 @@ |
572 | 565 | * information retrieved is stored in data. |
573 | 566 | * Assumes semaphore already acquired. |
574 | 567 | **/ |
575 | -s32 e1000_read_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 *data) | |
568 | +s32 e1000e_read_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 *data) | |
576 | 569 | { |
577 | 570 | return __e1000_read_kmrn_reg(hw, offset, data, true); |
578 | 571 | } |
... | ... | @@ -631,7 +624,7 @@ |
631 | 624 | } |
632 | 625 | |
633 | 626 | /** |
634 | - * e1000_write_kmrn_reg_locked - Write kumeran register | |
627 | + * e1000e_write_kmrn_reg_locked - Write kumeran register | |
635 | 628 | * @hw: pointer to the HW structure |
636 | 629 | * @offset: register offset to write to |
637 | 630 | * @data: data to write at register offset |
... | ... | @@ -639,7 +632,7 @@ |
639 | 632 | * Write the data to PHY register at the offset using the kumeran interface. |
640 | 633 | * Assumes semaphore already acquired. |
641 | 634 | **/ |
642 | -s32 e1000_write_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 data) | |
635 | +s32 e1000e_write_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 data) | |
643 | 636 | { |
644 | 637 | return __e1000_write_kmrn_reg(hw, offset, data, true); |
645 | 638 | } |