Skip to content

Commit

Permalink
e1000: configure and read MDI settings
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Jesse Brandeburg authored and Jeff Kirsher committed Aug 21, 2012
1 parent 1b55678 commit c819bbd
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 0 deletions.
39 changes: 39 additions & 0 deletions drivers/net/ethernet/intel/e1000/e1000_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand All @@ -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);

Expand All @@ -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)) {
Expand Down
4 changes: 4 additions & 0 deletions drivers/net/ethernet/intel/e1000/e1000_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down

0 comments on commit c819bbd

Please sign in to comment.