|
@@ -199,6 +199,11 @@ static int e1000_get_settings(struct net_device *netdev,
|
|
else
|
|
else
|
|
ecmd->eth_tp_mdix = ETH_TP_MDI_INVALID;
|
|
ecmd->eth_tp_mdix = ETH_TP_MDI_INVALID;
|
|
|
|
|
|
|
|
+ if (hw->phy.mdix == AUTO_ALL_MODES)
|
|
|
|
+ ecmd->eth_tp_mdix_ctrl = ETH_TP_MDI_AUTO;
|
|
|
|
+ else
|
|
|
|
+ ecmd->eth_tp_mdix_ctrl = hw->phy.mdix;
|
|
|
|
+
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -241,6 +246,10 @@ static int e1000_set_spd_dplx(struct e1000_adapter *adapter, u32 spd, u8 dplx)
|
|
default:
|
|
default:
|
|
goto err_inval;
|
|
goto err_inval;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ /* clear MDI, MDI(-X) override is only allowed when autoneg enabled */
|
|
|
|
+ adapter->hw.phy.mdix = AUTO_ALL_MODES;
|
|
|
|
+
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
err_inval:
|
|
err_inval:
|
|
@@ -264,6 +273,22 @@ static int e1000_set_settings(struct net_device *netdev,
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /*
|
|
|
|
+ * MDI setting is only allowed when autoneg enabled because
|
|
|
|
+ * some hardware doesn't allow MDI setting when speed or
|
|
|
|
+ * duplex is forced.
|
|
|
|
+ */
|
|
|
|
+ if (ecmd->eth_tp_mdix_ctrl) {
|
|
|
|
+ if (hw->phy.media_type != e1000_media_type_copper)
|
|
|
|
+ return -EOPNOTSUPP;
|
|
|
|
+
|
|
|
|
+ if ((ecmd->eth_tp_mdix_ctrl != ETH_TP_MDI_AUTO) &&
|
|
|
|
+ (ecmd->autoneg != AUTONEG_ENABLE)) {
|
|
|
|
+ e_err("forcing MDI/MDI-X state is not supported when link speed and/or duplex are forced\n");
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
while (test_and_set_bit(__E1000_RESETTING, &adapter->state))
|
|
while (test_and_set_bit(__E1000_RESETTING, &adapter->state))
|
|
usleep_range(1000, 2000);
|
|
usleep_range(1000, 2000);
|
|
|
|
|
|
@@ -282,20 +307,32 @@ static int e1000_set_settings(struct net_device *netdev,
|
|
hw->fc.requested_mode = e1000_fc_default;
|
|
hw->fc.requested_mode = e1000_fc_default;
|
|
} else {
|
|
} else {
|
|
u32 speed = ethtool_cmd_speed(ecmd);
|
|
u32 speed = ethtool_cmd_speed(ecmd);
|
|
|
|
+ /* calling this overrides forced MDI setting */
|
|
if (e1000_set_spd_dplx(adapter, speed, ecmd->duplex)) {
|
|
if (e1000_set_spd_dplx(adapter, speed, ecmd->duplex)) {
|
|
clear_bit(__E1000_RESETTING, &adapter->state);
|
|
clear_bit(__E1000_RESETTING, &adapter->state);
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /* MDI-X => 2; MDI => 1; Auto => 3 */
|
|
|
|
+ if (ecmd->eth_tp_mdix_ctrl) {
|
|
|
|
+ /*
|
|
|
|
+ * fix up the value for auto (3 => 0) as zero is mapped
|
|
|
|
+ * internally to auto
|
|
|
|
+ */
|
|
|
|
+ if (ecmd->eth_tp_mdix_ctrl == ETH_TP_MDI_AUTO)
|
|
|
|
+ hw->phy.mdix = AUTO_ALL_MODES;
|
|
|
|
+ else
|
|
|
|
+ hw->phy.mdix = ecmd->eth_tp_mdix_ctrl;
|
|
|
|
+ }
|
|
|
|
+
|
|
/* reset the link */
|
|
/* reset the link */
|
|
|
|
|
|
if (netif_running(adapter->netdev)) {
|
|
if (netif_running(adapter->netdev)) {
|
|
e1000e_down(adapter);
|
|
e1000e_down(adapter);
|
|
e1000e_up(adapter);
|
|
e1000e_up(adapter);
|
|
- } else {
|
|
|
|
|
|
+ } else
|
|
e1000e_reset(adapter);
|
|
e1000e_reset(adapter);
|
|
- }
|
|
|
|
|
|
|
|
clear_bit(__E1000_RESETTING, &adapter->state);
|
|
clear_bit(__E1000_RESETTING, &adapter->state);
|
|
return 0;
|
|
return 0;
|