diff options
Diffstat (limited to 'drivers/net/igb/e1000_phy.c')
-rw-r--r-- | drivers/net/igb/e1000_phy.c | 39 |
1 files changed, 25 insertions, 14 deletions
diff --git a/drivers/net/igb/e1000_phy.c b/drivers/net/igb/e1000_phy.c index 5fe03e114b83..83b706c460b3 100644 --- a/drivers/net/igb/e1000_phy.c +++ b/drivers/net/igb/e1000_phy.c | |||
@@ -39,6 +39,9 @@ static s32 igb_wait_autoneg(struct e1000_hw *hw); | |||
39 | /* Cable length tables */ | 39 | /* Cable length tables */ |
40 | static const u16 e1000_m88_cable_length_table[] = | 40 | static const u16 e1000_m88_cable_length_table[] = |
41 | { 0, 50, 80, 110, 140, 140, E1000_CABLE_LENGTH_UNDEFINED }; | 41 | { 0, 50, 80, 110, 140, 140, E1000_CABLE_LENGTH_UNDEFINED }; |
42 | #define M88E1000_CABLE_LENGTH_TABLE_SIZE \ | ||
43 | (sizeof(e1000_m88_cable_length_table) / \ | ||
44 | sizeof(e1000_m88_cable_length_table[0])) | ||
42 | 45 | ||
43 | static const u16 e1000_igp_2_cable_length_table[] = | 46 | static const u16 e1000_igp_2_cable_length_table[] = |
44 | { 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11, 13, 16, 18, 21, | 47 | { 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11, 13, 16, 18, 21, |
@@ -109,7 +112,10 @@ out: | |||
109 | **/ | 112 | **/ |
110 | static s32 igb_phy_reset_dsp(struct e1000_hw *hw) | 113 | static s32 igb_phy_reset_dsp(struct e1000_hw *hw) |
111 | { | 114 | { |
112 | s32 ret_val; | 115 | s32 ret_val = 0; |
116 | |||
117 | if (!(hw->phy.ops.write_reg)) | ||
118 | goto out; | ||
113 | 119 | ||
114 | ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xC1); | 120 | ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xC1); |
115 | if (ret_val) | 121 | if (ret_val) |
@@ -1059,22 +1065,19 @@ s32 igb_phy_force_speed_duplex_m88(struct e1000_hw *hw) | |||
1059 | 1065 | ||
1060 | igb_phy_force_speed_duplex_setup(hw, &phy_data); | 1066 | igb_phy_force_speed_duplex_setup(hw, &phy_data); |
1061 | 1067 | ||
1062 | /* Reset the phy to commit changes. */ | ||
1063 | phy_data |= MII_CR_RESET; | ||
1064 | |||
1065 | ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data); | 1068 | ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data); |
1066 | if (ret_val) | 1069 | if (ret_val) |
1067 | goto out; | 1070 | goto out; |
1068 | 1071 | ||
1069 | udelay(1); | 1072 | /* Reset the phy to commit changes. */ |
1073 | ret_val = igb_phy_sw_reset(hw); | ||
1074 | if (ret_val) | ||
1075 | goto out; | ||
1070 | 1076 | ||
1071 | if (phy->autoneg_wait_to_complete) { | 1077 | if (phy->autoneg_wait_to_complete) { |
1072 | hw_dbg("Waiting for forced speed/duplex link on M88 phy.\n"); | 1078 | hw_dbg("Waiting for forced speed/duplex link on M88 phy.\n"); |
1073 | 1079 | ||
1074 | ret_val = igb_phy_has_link(hw, | 1080 | ret_val = igb_phy_has_link(hw, PHY_FORCE_LIMIT, 100000, &link); |
1075 | PHY_FORCE_LIMIT, | ||
1076 | 100000, | ||
1077 | &link); | ||
1078 | if (ret_val) | 1081 | if (ret_val) |
1079 | goto out; | 1082 | goto out; |
1080 | 1083 | ||
@@ -1084,8 +1087,8 @@ s32 igb_phy_force_speed_duplex_m88(struct e1000_hw *hw) | |||
1084 | * Reset the DSP and cross our fingers. | 1087 | * Reset the DSP and cross our fingers. |
1085 | */ | 1088 | */ |
1086 | ret_val = phy->ops.write_reg(hw, | 1089 | ret_val = phy->ops.write_reg(hw, |
1087 | M88E1000_PHY_PAGE_SELECT, | 1090 | M88E1000_PHY_PAGE_SELECT, |
1088 | 0x001d); | 1091 | 0x001d); |
1089 | if (ret_val) | 1092 | if (ret_val) |
1090 | goto out; | 1093 | goto out; |
1091 | ret_val = igb_phy_reset_dsp(hw); | 1094 | ret_val = igb_phy_reset_dsp(hw); |
@@ -1095,7 +1098,7 @@ s32 igb_phy_force_speed_duplex_m88(struct e1000_hw *hw) | |||
1095 | 1098 | ||
1096 | /* Try once more */ | 1099 | /* Try once more */ |
1097 | ret_val = igb_phy_has_link(hw, PHY_FORCE_LIMIT, | 1100 | ret_val = igb_phy_has_link(hw, PHY_FORCE_LIMIT, |
1098 | 100000, &link); | 1101 | 100000, &link); |
1099 | if (ret_val) | 1102 | if (ret_val) |
1100 | goto out; | 1103 | goto out; |
1101 | } | 1104 | } |
@@ -1207,9 +1210,12 @@ static void igb_phy_force_speed_duplex_setup(struct e1000_hw *hw, | |||
1207 | s32 igb_set_d3_lplu_state(struct e1000_hw *hw, bool active) | 1210 | s32 igb_set_d3_lplu_state(struct e1000_hw *hw, bool active) |
1208 | { | 1211 | { |
1209 | struct e1000_phy_info *phy = &hw->phy; | 1212 | struct e1000_phy_info *phy = &hw->phy; |
1210 | s32 ret_val; | 1213 | s32 ret_val = 0; |
1211 | u16 data; | 1214 | u16 data; |
1212 | 1215 | ||
1216 | if (!(hw->phy.ops.read_reg)) | ||
1217 | goto out; | ||
1218 | |||
1213 | ret_val = phy->ops.read_reg(hw, IGP02E1000_PHY_POWER_MGMT, &data); | 1219 | ret_val = phy->ops.read_reg(hw, IGP02E1000_PHY_POWER_MGMT, &data); |
1214 | if (ret_val) | 1220 | if (ret_val) |
1215 | goto out; | 1221 | goto out; |
@@ -1495,8 +1501,13 @@ s32 igb_get_cable_length_m88(struct e1000_hw *hw) | |||
1495 | 1501 | ||
1496 | index = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >> | 1502 | index = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >> |
1497 | M88E1000_PSSR_CABLE_LENGTH_SHIFT; | 1503 | M88E1000_PSSR_CABLE_LENGTH_SHIFT; |
1504 | if (index >= M88E1000_CABLE_LENGTH_TABLE_SIZE - 1) { | ||
1505 | ret_val = -E1000_ERR_PHY; | ||
1506 | goto out; | ||
1507 | } | ||
1508 | |||
1498 | phy->min_cable_length = e1000_m88_cable_length_table[index]; | 1509 | phy->min_cable_length = e1000_m88_cable_length_table[index]; |
1499 | phy->max_cable_length = e1000_m88_cable_length_table[index+1]; | 1510 | phy->max_cable_length = e1000_m88_cable_length_table[index + 1]; |
1500 | 1511 | ||
1501 | phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2; | 1512 | phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2; |
1502 | 1513 | ||