diff options
author | David S. Miller <davem@davemloft.net> | 2012-08-22 17:23:43 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-08-22 17:23:43 -0400 |
commit | bba6ec7e4963e30366359686f34e5bdb00b1a066 (patch) | |
tree | 05c44b6b99e46d876b144065537dd8673d07b162 | |
parent | 1304a7343b30fc4f16045412efdbb4179a3d9255 (diff) | |
parent | 8376dad0c877bc691b2feadd3390a162aa3c3bd9 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net-next
Jeff Kirsher says:
====================
This series contains updates to ethtool.h, e1000, e1000e, and igb to
implement MDI/MDIx control.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/intel/e1000/e1000_ethtool.c | 39 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/e1000/e1000_main.c | 4 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/e1000e/ethtool.c | 41 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/e1000e/phy.c | 31 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/igb/e1000_phy.c | 29 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/igb/e1000_phy.h | 5 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/igb/igb_ethtool.c | 42 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/igb/igb_main.c | 4 | ||||
-rw-r--r-- | include/linux/ethtool.h | 17 |
9 files changed, 198 insertions, 14 deletions
diff --git a/drivers/net/ethernet/intel/e1000/e1000_ethtool.c b/drivers/net/ethernet/intel/e1000/e1000_ethtool.c index 736a7d987db5..9089d00f1421 100644 --- a/drivers/net/ethernet/intel/e1000/e1000_ethtool.c +++ b/drivers/net/ethernet/intel/e1000/e1000_ethtool.c | |||
@@ -174,6 +174,20 @@ static int e1000_get_settings(struct net_device *netdev, | |||
174 | 174 | ||
175 | ecmd->autoneg = ((hw->media_type == e1000_media_type_fiber) || | 175 | ecmd->autoneg = ((hw->media_type == e1000_media_type_fiber) || |
176 | hw->autoneg) ? AUTONEG_ENABLE : AUTONEG_DISABLE; | 176 | hw->autoneg) ? AUTONEG_ENABLE : AUTONEG_DISABLE; |
177 | |||
178 | /* MDI-X => 1; MDI => 0 */ | ||
179 | if ((hw->media_type == e1000_media_type_copper) && | ||
180 | netif_carrier_ok(netdev)) | ||
181 | ecmd->eth_tp_mdix = (!!adapter->phy_info.mdix_mode ? | ||
182 | ETH_TP_MDI_X : | ||
183 | ETH_TP_MDI); | ||
184 | else | ||
185 | ecmd->eth_tp_mdix = ETH_TP_MDI_INVALID; | ||
186 | |||
187 | if (hw->mdix == AUTO_ALL_MODES) | ||
188 | ecmd->eth_tp_mdix_ctrl = ETH_TP_MDI_AUTO; | ||
189 | else | ||
190 | ecmd->eth_tp_mdix_ctrl = hw->mdix; | ||
177 | return 0; | 191 | return 0; |
178 | } | 192 | } |
179 | 193 | ||
@@ -183,6 +197,22 @@ static int e1000_set_settings(struct net_device *netdev, | |||
183 | struct e1000_adapter *adapter = netdev_priv(netdev); | 197 | struct e1000_adapter *adapter = netdev_priv(netdev); |
184 | struct e1000_hw *hw = &adapter->hw; | 198 | struct e1000_hw *hw = &adapter->hw; |
185 | 199 | ||
200 | /* | ||
201 | * MDI setting is only allowed when autoneg enabled because | ||
202 | * some hardware doesn't allow MDI setting when speed or | ||
203 | * duplex is forced. | ||
204 | */ | ||
205 | if (ecmd->eth_tp_mdix_ctrl) { | ||
206 | if (hw->media_type != e1000_media_type_copper) | ||
207 | return -EOPNOTSUPP; | ||
208 | |||
209 | if ((ecmd->eth_tp_mdix_ctrl != ETH_TP_MDI_AUTO) && | ||
210 | (ecmd->autoneg != AUTONEG_ENABLE)) { | ||
211 | e_err(drv, "forcing MDI/MDI-X state is not supported when link speed and/or duplex are forced\n"); | ||
212 | return -EINVAL; | ||
213 | } | ||
214 | } | ||
215 | |||
186 | while (test_and_set_bit(__E1000_RESETTING, &adapter->flags)) | 216 | while (test_and_set_bit(__E1000_RESETTING, &adapter->flags)) |
187 | msleep(1); | 217 | msleep(1); |
188 | 218 | ||
@@ -199,12 +229,21 @@ static int e1000_set_settings(struct net_device *netdev, | |||
199 | ecmd->advertising = hw->autoneg_advertised; | 229 | ecmd->advertising = hw->autoneg_advertised; |
200 | } else { | 230 | } else { |
201 | u32 speed = ethtool_cmd_speed(ecmd); | 231 | u32 speed = ethtool_cmd_speed(ecmd); |
232 | /* calling this overrides forced MDI setting */ | ||
202 | if (e1000_set_spd_dplx(adapter, speed, ecmd->duplex)) { | 233 | if (e1000_set_spd_dplx(adapter, speed, ecmd->duplex)) { |
203 | clear_bit(__E1000_RESETTING, &adapter->flags); | 234 | clear_bit(__E1000_RESETTING, &adapter->flags); |
204 | return -EINVAL; | 235 | return -EINVAL; |
205 | } | 236 | } |
206 | } | 237 | } |
207 | 238 | ||
239 | /* MDI-X => 2; MDI => 1; Auto => 3 */ | ||
240 | if (ecmd->eth_tp_mdix_ctrl) { | ||
241 | if (ecmd->eth_tp_mdix_ctrl == ETH_TP_MDI_AUTO) | ||
242 | hw->mdix = AUTO_ALL_MODES; | ||
243 | else | ||
244 | hw->mdix = ecmd->eth_tp_mdix_ctrl; | ||
245 | } | ||
246 | |||
208 | /* reset the link */ | 247 | /* reset the link */ |
209 | 248 | ||
210 | if (netif_running(adapter->netdev)) { | 249 | if (netif_running(adapter->netdev)) { |
diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c index 3bfbb8df8989..0ae2fcfa5124 100644 --- a/drivers/net/ethernet/intel/e1000/e1000_main.c +++ b/drivers/net/ethernet/intel/e1000/e1000_main.c | |||
@@ -4939,6 +4939,10 @@ int e1000_set_spd_dplx(struct e1000_adapter *adapter, u32 spd, u8 dplx) | |||
4939 | default: | 4939 | default: |
4940 | goto err_inval; | 4940 | goto err_inval; |
4941 | } | 4941 | } |
4942 | |||
4943 | /* clear MDI, MDI(-X) override is only allowed when autoneg enabled */ | ||
4944 | hw->mdix = AUTO_ALL_MODES; | ||
4945 | |||
4942 | return 0; | 4946 | return 0; |
4943 | 4947 | ||
4944 | err_inval: | 4948 | err_inval: |
diff --git a/drivers/net/ethernet/intel/e1000e/ethtool.c b/drivers/net/ethernet/intel/e1000e/ethtool.c index 0349e2478df8..2e76f06720fd 100644 --- a/drivers/net/ethernet/intel/e1000e/ethtool.c +++ b/drivers/net/ethernet/intel/e1000e/ethtool.c | |||
@@ -199,6 +199,11 @@ static int e1000_get_settings(struct net_device *netdev, | |||
199 | else | 199 | else |
200 | ecmd->eth_tp_mdix = ETH_TP_MDI_INVALID; | 200 | ecmd->eth_tp_mdix = ETH_TP_MDI_INVALID; |
201 | 201 | ||
202 | if (hw->phy.mdix == AUTO_ALL_MODES) | ||
203 | ecmd->eth_tp_mdix_ctrl = ETH_TP_MDI_AUTO; | ||
204 | else | ||
205 | ecmd->eth_tp_mdix_ctrl = hw->phy.mdix; | ||
206 | |||
202 | return 0; | 207 | return 0; |
203 | } | 208 | } |
204 | 209 | ||
@@ -241,6 +246,10 @@ static int e1000_set_spd_dplx(struct e1000_adapter *adapter, u32 spd, u8 dplx) | |||
241 | default: | 246 | default: |
242 | goto err_inval; | 247 | goto err_inval; |
243 | } | 248 | } |
249 | |||
250 | /* clear MDI, MDI(-X) override is only allowed when autoneg enabled */ | ||
251 | adapter->hw.phy.mdix = AUTO_ALL_MODES; | ||
252 | |||
244 | return 0; | 253 | return 0; |
245 | 254 | ||
246 | err_inval: | 255 | err_inval: |
@@ -264,6 +273,22 @@ static int e1000_set_settings(struct net_device *netdev, | |||
264 | return -EINVAL; | 273 | return -EINVAL; |
265 | } | 274 | } |
266 | 275 | ||
276 | /* | ||
277 | * MDI setting is only allowed when autoneg enabled because | ||
278 | * some hardware doesn't allow MDI setting when speed or | ||
279 | * duplex is forced. | ||
280 | */ | ||
281 | if (ecmd->eth_tp_mdix_ctrl) { | ||
282 | if (hw->phy.media_type != e1000_media_type_copper) | ||
283 | return -EOPNOTSUPP; | ||
284 | |||
285 | if ((ecmd->eth_tp_mdix_ctrl != ETH_TP_MDI_AUTO) && | ||
286 | (ecmd->autoneg != AUTONEG_ENABLE)) { | ||
287 | e_err("forcing MDI/MDI-X state is not supported when link speed and/or duplex are forced\n"); | ||
288 | return -EINVAL; | ||
289 | } | ||
290 | } | ||
291 | |||
267 | while (test_and_set_bit(__E1000_RESETTING, &adapter->state)) | 292 | while (test_and_set_bit(__E1000_RESETTING, &adapter->state)) |
268 | usleep_range(1000, 2000); | 293 | usleep_range(1000, 2000); |
269 | 294 | ||
@@ -282,20 +307,32 @@ static int e1000_set_settings(struct net_device *netdev, | |||
282 | hw->fc.requested_mode = e1000_fc_default; | 307 | hw->fc.requested_mode = e1000_fc_default; |
283 | } else { | 308 | } else { |
284 | u32 speed = ethtool_cmd_speed(ecmd); | 309 | u32 speed = ethtool_cmd_speed(ecmd); |
310 | /* calling this overrides forced MDI setting */ | ||
285 | if (e1000_set_spd_dplx(adapter, speed, ecmd->duplex)) { | 311 | if (e1000_set_spd_dplx(adapter, speed, ecmd->duplex)) { |
286 | clear_bit(__E1000_RESETTING, &adapter->state); | 312 | clear_bit(__E1000_RESETTING, &adapter->state); |
287 | return -EINVAL; | 313 | return -EINVAL; |
288 | } | 314 | } |
289 | } | 315 | } |
290 | 316 | ||
317 | /* MDI-X => 2; MDI => 1; Auto => 3 */ | ||
318 | if (ecmd->eth_tp_mdix_ctrl) { | ||
319 | /* | ||
320 | * fix up the value for auto (3 => 0) as zero is mapped | ||
321 | * internally to auto | ||
322 | */ | ||
323 | if (ecmd->eth_tp_mdix_ctrl == ETH_TP_MDI_AUTO) | ||
324 | hw->phy.mdix = AUTO_ALL_MODES; | ||
325 | else | ||
326 | hw->phy.mdix = ecmd->eth_tp_mdix_ctrl; | ||
327 | } | ||
328 | |||
291 | /* reset the link */ | 329 | /* reset the link */ |
292 | 330 | ||
293 | if (netif_running(adapter->netdev)) { | 331 | if (netif_running(adapter->netdev)) { |
294 | e1000e_down(adapter); | 332 | e1000e_down(adapter); |
295 | e1000e_up(adapter); | 333 | e1000e_up(adapter); |
296 | } else { | 334 | } else |
297 | e1000e_reset(adapter); | 335 | e1000e_reset(adapter); |
298 | } | ||
299 | 336 | ||
300 | clear_bit(__E1000_RESETTING, &adapter->state); | 337 | clear_bit(__E1000_RESETTING, &adapter->state); |
301 | return 0; | 338 | return 0; |
diff --git a/drivers/net/ethernet/intel/e1000e/phy.c b/drivers/net/ethernet/intel/e1000e/phy.c index b860d4f7ea2a..fc62a3f3a5be 100644 --- a/drivers/net/ethernet/intel/e1000e/phy.c +++ b/drivers/net/ethernet/intel/e1000e/phy.c | |||
@@ -84,8 +84,9 @@ static const u16 e1000_igp_2_cable_length_table[] = { | |||
84 | #define I82577_PHY_STATUS2_SPEED_1000MBPS 0x0200 | 84 | #define I82577_PHY_STATUS2_SPEED_1000MBPS 0x0200 |
85 | 85 | ||
86 | /* I82577 PHY Control 2 */ | 86 | /* I82577 PHY Control 2 */ |
87 | #define I82577_PHY_CTRL2_AUTO_MDIX 0x0400 | 87 | #define I82577_PHY_CTRL2_MANUAL_MDIX 0x0200 |
88 | #define I82577_PHY_CTRL2_FORCE_MDI_MDIX 0x0200 | 88 | #define I82577_PHY_CTRL2_AUTO_MDI_MDIX 0x0400 |
89 | #define I82577_PHY_CTRL2_MDIX_CFG_MASK 0x0600 | ||
89 | 90 | ||
90 | /* I82577 PHY Diagnostics Status */ | 91 | /* I82577 PHY Diagnostics Status */ |
91 | #define I82577_DSTATUS_CABLE_LENGTH 0x03FC | 92 | #define I82577_DSTATUS_CABLE_LENGTH 0x03FC |
@@ -702,6 +703,32 @@ s32 e1000_copper_link_setup_82577(struct e1000_hw *hw) | |||
702 | if (ret_val) | 703 | if (ret_val) |
703 | return ret_val; | 704 | return ret_val; |
704 | 705 | ||
706 | /* Set MDI/MDIX mode */ | ||
707 | ret_val = e1e_rphy(hw, I82577_PHY_CTRL_2, &phy_data); | ||
708 | if (ret_val) | ||
709 | return ret_val; | ||
710 | phy_data &= ~I82577_PHY_CTRL2_MDIX_CFG_MASK; | ||
711 | /* | ||
712 | * Options: | ||
713 | * 0 - Auto (default) | ||
714 | * 1 - MDI mode | ||
715 | * 2 - MDI-X mode | ||
716 | */ | ||
717 | switch (hw->phy.mdix) { | ||
718 | case 1: | ||
719 | break; | ||
720 | case 2: | ||
721 | phy_data |= I82577_PHY_CTRL2_MANUAL_MDIX; | ||
722 | break; | ||
723 | case 0: | ||
724 | default: | ||
725 | phy_data |= I82577_PHY_CTRL2_AUTO_MDI_MDIX; | ||
726 | break; | ||
727 | } | ||
728 | ret_val = e1e_wphy(hw, I82577_PHY_CTRL_2, phy_data); | ||
729 | if (ret_val) | ||
730 | return ret_val; | ||
731 | |||
705 | return e1000_set_master_slave_mode(hw); | 732 | return e1000_set_master_slave_mode(hw); |
706 | } | 733 | } |
707 | 734 | ||
diff --git a/drivers/net/ethernet/intel/igb/e1000_phy.c b/drivers/net/ethernet/intel/igb/e1000_phy.c index 7be98b6f1052..3404bc79f4ca 100644 --- a/drivers/net/ethernet/intel/igb/e1000_phy.c +++ b/drivers/net/ethernet/intel/igb/e1000_phy.c | |||
@@ -464,6 +464,32 @@ s32 igb_copper_link_setup_82580(struct e1000_hw *hw) | |||
464 | phy_data |= I82580_CFG_ENABLE_DOWNSHIFT; | 464 | phy_data |= I82580_CFG_ENABLE_DOWNSHIFT; |
465 | 465 | ||
466 | ret_val = phy->ops.write_reg(hw, I82580_CFG_REG, phy_data); | 466 | ret_val = phy->ops.write_reg(hw, I82580_CFG_REG, phy_data); |
467 | if (ret_val) | ||
468 | goto out; | ||
469 | |||
470 | /* Set MDI/MDIX mode */ | ||
471 | ret_val = phy->ops.read_reg(hw, I82580_PHY_CTRL_2, &phy_data); | ||
472 | if (ret_val) | ||
473 | goto out; | ||
474 | phy_data &= ~I82580_PHY_CTRL2_MDIX_CFG_MASK; | ||
475 | /* | ||
476 | * Options: | ||
477 | * 0 - Auto (default) | ||
478 | * 1 - MDI mode | ||
479 | * 2 - MDI-X mode | ||
480 | */ | ||
481 | switch (hw->phy.mdix) { | ||
482 | case 1: | ||
483 | break; | ||
484 | case 2: | ||
485 | phy_data |= I82580_PHY_CTRL2_MANUAL_MDIX; | ||
486 | break; | ||
487 | case 0: | ||
488 | default: | ||
489 | phy_data |= I82580_PHY_CTRL2_AUTO_MDI_MDIX; | ||
490 | break; | ||
491 | } | ||
492 | ret_val = hw->phy.ops.write_reg(hw, I82580_PHY_CTRL_2, phy_data); | ||
467 | 493 | ||
468 | out: | 494 | out: |
469 | return ret_val; | 495 | return ret_val; |
@@ -2246,8 +2272,7 @@ s32 igb_phy_force_speed_duplex_82580(struct e1000_hw *hw) | |||
2246 | if (ret_val) | 2272 | if (ret_val) |
2247 | goto out; | 2273 | goto out; |
2248 | 2274 | ||
2249 | phy_data &= ~I82580_PHY_CTRL2_AUTO_MDIX; | 2275 | phy_data &= ~I82580_PHY_CTRL2_MDIX_CFG_MASK; |
2250 | phy_data &= ~I82580_PHY_CTRL2_FORCE_MDI_MDIX; | ||
2251 | 2276 | ||
2252 | ret_val = phy->ops.write_reg(hw, I82580_PHY_CTRL_2, phy_data); | 2277 | ret_val = phy->ops.write_reg(hw, I82580_PHY_CTRL_2, phy_data); |
2253 | if (ret_val) | 2278 | if (ret_val) |
diff --git a/drivers/net/ethernet/intel/igb/e1000_phy.h b/drivers/net/ethernet/intel/igb/e1000_phy.h index 34e40619f16b..6ac3299bfcb9 100644 --- a/drivers/net/ethernet/intel/igb/e1000_phy.h +++ b/drivers/net/ethernet/intel/igb/e1000_phy.h | |||
@@ -111,8 +111,9 @@ s32 igb_check_polarity_m88(struct e1000_hw *hw); | |||
111 | #define I82580_PHY_STATUS2_SPEED_100MBPS 0x0100 | 111 | #define I82580_PHY_STATUS2_SPEED_100MBPS 0x0100 |
112 | 112 | ||
113 | /* I82580 PHY Control 2 */ | 113 | /* I82580 PHY Control 2 */ |
114 | #define I82580_PHY_CTRL2_AUTO_MDIX 0x0400 | 114 | #define I82580_PHY_CTRL2_MANUAL_MDIX 0x0200 |
115 | #define I82580_PHY_CTRL2_FORCE_MDI_MDIX 0x0200 | 115 | #define I82580_PHY_CTRL2_AUTO_MDI_MDIX 0x0400 |
116 | #define I82580_PHY_CTRL2_MDIX_CFG_MASK 0x0600 | ||
116 | 117 | ||
117 | /* I82580 PHY Diagnostics Status */ | 118 | /* I82580 PHY Diagnostics Status */ |
118 | #define I82580_DSTATUS_CABLE_LENGTH 0x03FC | 119 | #define I82580_DSTATUS_CABLE_LENGTH 0x03FC |
diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c index 70591117051b..be02168f1308 100644 --- a/drivers/net/ethernet/intel/igb/igb_ethtool.c +++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c | |||
@@ -198,6 +198,19 @@ static int igb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) | |||
198 | } | 198 | } |
199 | 199 | ||
200 | ecmd->autoneg = hw->mac.autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE; | 200 | ecmd->autoneg = hw->mac.autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE; |
201 | |||
202 | /* MDI-X => 2; MDI =>1; Invalid =>0 */ | ||
203 | if (hw->phy.media_type == e1000_media_type_copper) | ||
204 | ecmd->eth_tp_mdix = hw->phy.is_mdix ? ETH_TP_MDI_X : | ||
205 | ETH_TP_MDI; | ||
206 | else | ||
207 | ecmd->eth_tp_mdix = ETH_TP_MDI_INVALID; | ||
208 | |||
209 | if (hw->phy.mdix == AUTO_ALL_MODES) | ||
210 | ecmd->eth_tp_mdix_ctrl = ETH_TP_MDI_AUTO; | ||
211 | else | ||
212 | ecmd->eth_tp_mdix_ctrl = hw->phy.mdix; | ||
213 | |||
201 | return 0; | 214 | return 0; |
202 | } | 215 | } |
203 | 216 | ||
@@ -214,6 +227,22 @@ static int igb_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) | |||
214 | return -EINVAL; | 227 | return -EINVAL; |
215 | } | 228 | } |
216 | 229 | ||
230 | /* | ||
231 | * MDI setting is only allowed when autoneg enabled because | ||
232 | * some hardware doesn't allow MDI setting when speed or | ||
233 | * duplex is forced. | ||
234 | */ | ||
235 | if (ecmd->eth_tp_mdix_ctrl) { | ||
236 | if (hw->phy.media_type != e1000_media_type_copper) | ||
237 | return -EOPNOTSUPP; | ||
238 | |||
239 | if ((ecmd->eth_tp_mdix_ctrl != ETH_TP_MDI_AUTO) && | ||
240 | (ecmd->autoneg != AUTONEG_ENABLE)) { | ||
241 | dev_err(&adapter->pdev->dev, "forcing MDI/MDI-X state is not supported when link speed and/or duplex are forced\n"); | ||
242 | return -EINVAL; | ||
243 | } | ||
244 | } | ||
245 | |||
217 | while (test_and_set_bit(__IGB_RESETTING, &adapter->state)) | 246 | while (test_and_set_bit(__IGB_RESETTING, &adapter->state)) |
218 | msleep(1); | 247 | msleep(1); |
219 | 248 | ||
@@ -227,12 +256,25 @@ static int igb_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) | |||
227 | hw->fc.requested_mode = e1000_fc_default; | 256 | hw->fc.requested_mode = e1000_fc_default; |
228 | } else { | 257 | } else { |
229 | u32 speed = ethtool_cmd_speed(ecmd); | 258 | u32 speed = ethtool_cmd_speed(ecmd); |
259 | /* calling this overrides forced MDI setting */ | ||
230 | if (igb_set_spd_dplx(adapter, speed, ecmd->duplex)) { | 260 | if (igb_set_spd_dplx(adapter, speed, ecmd->duplex)) { |
231 | clear_bit(__IGB_RESETTING, &adapter->state); | 261 | clear_bit(__IGB_RESETTING, &adapter->state); |
232 | return -EINVAL; | 262 | return -EINVAL; |
233 | } | 263 | } |
234 | } | 264 | } |
235 | 265 | ||
266 | /* MDI-X => 2; MDI => 1; Auto => 3 */ | ||
267 | if (ecmd->eth_tp_mdix_ctrl) { | ||
268 | /* | ||
269 | * fix up the value for auto (3 => 0) as zero is mapped | ||
270 | * internally to auto | ||
271 | */ | ||
272 | if (ecmd->eth_tp_mdix_ctrl == ETH_TP_MDI_AUTO) | ||
273 | hw->phy.mdix = AUTO_ALL_MODES; | ||
274 | else | ||
275 | hw->phy.mdix = ecmd->eth_tp_mdix_ctrl; | ||
276 | } | ||
277 | |||
236 | /* reset the link */ | 278 | /* reset the link */ |
237 | if (netif_running(adapter->netdev)) { | 279 | if (netif_running(adapter->netdev)) { |
238 | igb_down(adapter); | 280 | igb_down(adapter); |
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 48cc4fb1a307..73cc273ef98b 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c | |||
@@ -6675,6 +6675,10 @@ int igb_set_spd_dplx(struct igb_adapter *adapter, u32 spd, u8 dplx) | |||
6675 | default: | 6675 | default: |
6676 | goto err_inval; | 6676 | goto err_inval; |
6677 | } | 6677 | } |
6678 | |||
6679 | /* clear MDI, MDI(-X) override is only allowed when autoneg enabled */ | ||
6680 | adapter->hw.phy.mdix = AUTO_ALL_MODES; | ||
6681 | |||
6678 | return 0; | 6682 | return 0; |
6679 | 6683 | ||
6680 | err_inval: | 6684 | err_inval: |
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index 21eff418091b..fcb4f8e60c1c 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h | |||
@@ -45,8 +45,10 @@ struct ethtool_cmd { | |||
45 | * bits) in Mbps. Please use | 45 | * bits) in Mbps. Please use |
46 | * ethtool_cmd_speed()/_set() to | 46 | * ethtool_cmd_speed()/_set() to |
47 | * access it */ | 47 | * access it */ |
48 | __u8 eth_tp_mdix; | 48 | __u8 eth_tp_mdix; /* twisted pair MDI-X status */ |
49 | __u8 reserved2; | 49 | __u8 eth_tp_mdix_ctrl; /* twisted pair MDI-X control, when set, |
50 | * link should be renegotiated if necessary | ||
51 | */ | ||
50 | __u32 lp_advertising; /* Features the link partner advertises */ | 52 | __u32 lp_advertising; /* Features the link partner advertises */ |
51 | __u32 reserved[2]; | 53 | __u32 reserved[2]; |
52 | }; | 54 | }; |
@@ -1229,10 +1231,13 @@ struct ethtool_ops { | |||
1229 | #define AUTONEG_DISABLE 0x00 | 1231 | #define AUTONEG_DISABLE 0x00 |
1230 | #define AUTONEG_ENABLE 0x01 | 1232 | #define AUTONEG_ENABLE 0x01 |
1231 | 1233 | ||
1232 | /* Mode MDI or MDI-X */ | 1234 | /* MDI or MDI-X status/control - if MDI/MDI_X/AUTO is set then |
1233 | #define ETH_TP_MDI_INVALID 0x00 | 1235 | * the driver is required to renegotiate link |
1234 | #define ETH_TP_MDI 0x01 | 1236 | */ |
1235 | #define ETH_TP_MDI_X 0x02 | 1237 | #define ETH_TP_MDI_INVALID 0x00 /* status: unknown; control: unsupported */ |
1238 | #define ETH_TP_MDI 0x01 /* status: MDI; control: force MDI */ | ||
1239 | #define ETH_TP_MDI_X 0x02 /* status: MDI-X; control: force MDI-X */ | ||
1240 | #define ETH_TP_MDI_AUTO 0x03 /* control: auto-select */ | ||
1236 | 1241 | ||
1237 | /* Wake-On-Lan options. */ | 1242 | /* Wake-On-Lan options. */ |
1238 | #define WAKE_PHY (1 << 0) | 1243 | #define WAKE_PHY (1 << 0) |