aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2012-08-22 17:23:43 -0400
committerDavid S. Miller <davem@davemloft.net>2012-08-22 17:23:43 -0400
commitbba6ec7e4963e30366359686f34e5bdb00b1a066 (patch)
tree05c44b6b99e46d876b144065537dd8673d07b162
parent1304a7343b30fc4f16045412efdbb4179a3d9255 (diff)
parent8376dad0c877bc691b2feadd3390a162aa3c3bd9 (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.c39
-rw-r--r--drivers/net/ethernet/intel/e1000/e1000_main.c4
-rw-r--r--drivers/net/ethernet/intel/e1000e/ethtool.c41
-rw-r--r--drivers/net/ethernet/intel/e1000e/phy.c31
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_phy.c29
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_phy.h5
-rw-r--r--drivers/net/ethernet/intel/igb/igb_ethtool.c42
-rw-r--r--drivers/net/ethernet/intel/igb/igb_main.c4
-rw-r--r--include/linux/ethtool.h17
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
4944err_inval: 4948err_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
246err_inval: 255err_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
468out: 494out:
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
6680err_inval: 6684err_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)