e1000: configure and read MDI settings
This is the implementation in e1000 to allow ethtool to force MDI state, allowing users to work around some improperly behaving switches. Forcing in this driver is for now only allowed when auto-neg is enabled. To use must have the matching version of ethtool app that supports this functionality. Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com> CC: Tushar Dave <tushar.n.dave@intel.com> Tested-by: Aaron Brown aaron.f.brown@intel.com Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
This commit is contained in:
parent
1b556783ab
commit
c819bbd5ec
|
@ -174,6 +174,20 @@ static int e1000_get_settings(struct net_device *netdev,
|
|||
|
||||
ecmd->autoneg = ((hw->media_type == e1000_media_type_fiber) ||
|
||||
hw->autoneg) ? AUTONEG_ENABLE : AUTONEG_DISABLE;
|
||||
|
||||
/* MDI-X => 1; MDI => 0 */
|
||||
if ((hw->media_type == e1000_media_type_copper) &&
|
||||
netif_carrier_ok(netdev))
|
||||
ecmd->eth_tp_mdix = (!!adapter->phy_info.mdix_mode ?
|
||||
ETH_TP_MDI_X :
|
||||
ETH_TP_MDI);
|
||||
else
|
||||
ecmd->eth_tp_mdix = ETH_TP_MDI_INVALID;
|
||||
|
||||
if (hw->mdix == AUTO_ALL_MODES)
|
||||
ecmd->eth_tp_mdix_ctrl = ETH_TP_MDI_AUTO;
|
||||
else
|
||||
ecmd->eth_tp_mdix_ctrl = hw->mdix;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -183,6 +197,22 @@ static int e1000_set_settings(struct net_device *netdev,
|
|||
struct e1000_adapter *adapter = netdev_priv(netdev);
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
|
||||
/*
|
||||
* 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->media_type != e1000_media_type_copper)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if ((ecmd->eth_tp_mdix_ctrl != ETH_TP_MDI_AUTO) &&
|
||||
(ecmd->autoneg != AUTONEG_ENABLE)) {
|
||||
e_err(drv, "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->flags))
|
||||
msleep(1);
|
||||
|
||||
|
@ -199,12 +229,21 @@ static int e1000_set_settings(struct net_device *netdev,
|
|||
ecmd->advertising = hw->autoneg_advertised;
|
||||
} else {
|
||||
u32 speed = ethtool_cmd_speed(ecmd);
|
||||
/* calling this overrides forced MDI setting */
|
||||
if (e1000_set_spd_dplx(adapter, speed, ecmd->duplex)) {
|
||||
clear_bit(__E1000_RESETTING, &adapter->flags);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/* MDI-X => 2; MDI => 1; Auto => 3 */
|
||||
if (ecmd->eth_tp_mdix_ctrl) {
|
||||
if (ecmd->eth_tp_mdix_ctrl == ETH_TP_MDI_AUTO)
|
||||
hw->mdix = AUTO_ALL_MODES;
|
||||
else
|
||||
hw->mdix = ecmd->eth_tp_mdix_ctrl;
|
||||
}
|
||||
|
||||
/* reset the link */
|
||||
|
||||
if (netif_running(adapter->netdev)) {
|
||||
|
|
|
@ -4939,6 +4939,10 @@ int e1000_set_spd_dplx(struct e1000_adapter *adapter, u32 spd, u8 dplx)
|
|||
default:
|
||||
goto err_inval;
|
||||
}
|
||||
|
||||
/* clear MDI, MDI(-X) override is only allowed when autoneg enabled */
|
||||
hw->mdix = AUTO_ALL_MODES;
|
||||
|
||||
return 0;
|
||||
|
||||
err_inval:
|
||||
|
|
Loading…
Reference in New Issue