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;
 }
 
        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);
 
                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)) {