diff options
Diffstat (limited to 'drivers/net/e1000/e1000_ethtool.c')
-rw-r--r-- | drivers/net/e1000/e1000_ethtool.c | 40 |
1 files changed, 30 insertions, 10 deletions
diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index 88a82ba88f57..2baccf864328 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c @@ -183,6 +183,9 @@ e1000_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) return -EINVAL; } + while (test_and_set_bit(__E1000_RESETTING, &adapter->flags)) + msleep(1); + if (ecmd->autoneg == AUTONEG_ENABLE) { hw->autoneg = 1; if (hw->media_type == e1000_media_type_fiber) @@ -199,16 +202,20 @@ e1000_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) ADVERTISED_TP; ecmd->advertising = hw->autoneg_advertised; } else - if (e1000_set_spd_dplx(adapter, ecmd->speed + ecmd->duplex)) + if (e1000_set_spd_dplx(adapter, ecmd->speed + ecmd->duplex)) { + clear_bit(__E1000_RESETTING, &adapter->flags); return -EINVAL; + } /* reset the link */ - if (netif_running(adapter->netdev)) - e1000_reinit_locked(adapter); - else + if (netif_running(adapter->netdev)) { + e1000_down(adapter); + e1000_up(adapter); + } else e1000_reset(adapter); + clear_bit(__E1000_RESETTING, &adapter->flags); return 0; } @@ -238,9 +245,13 @@ e1000_set_pauseparam(struct net_device *netdev, { struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; + int retval = 0; adapter->fc_autoneg = pause->autoneg; + while (test_and_set_bit(__E1000_RESETTING, &adapter->flags)) + msleep(1); + if (pause->rx_pause && pause->tx_pause) hw->fc = e1000_fc_full; else if (pause->rx_pause && !pause->tx_pause) @@ -253,15 +264,17 @@ e1000_set_pauseparam(struct net_device *netdev, hw->original_fc = hw->fc; if (adapter->fc_autoneg == AUTONEG_ENABLE) { - if (netif_running(adapter->netdev)) - e1000_reinit_locked(adapter); - else + if (netif_running(adapter->netdev)) { + e1000_down(adapter); + e1000_up(adapter); + } else e1000_reset(adapter); } else - return ((hw->media_type == e1000_media_type_fiber) ? - e1000_setup_link(hw) : e1000_force_mac_fc(hw)); + retval = ((hw->media_type == e1000_media_type_fiber) ? + e1000_setup_link(hw) : e1000_force_mac_fc(hw)); - return 0; + clear_bit(__E1000_RESETTING, &adapter->flags); + return retval; } static uint32_t @@ -1590,6 +1603,8 @@ e1000_diag_test_count(struct net_device *netdev) return E1000_TEST_LEN; } +extern void e1000_power_up_phy(struct e1000_adapter *); + static void e1000_diag_test(struct net_device *netdev, struct ethtool_test *eth_test, uint64_t *data) @@ -1606,6 +1621,8 @@ e1000_diag_test(struct net_device *netdev, uint8_t forced_speed_duplex = adapter->hw.forced_speed_duplex; uint8_t autoneg = adapter->hw.autoneg; + DPRINTK(HW, INFO, "offline testing starting\n"); + /* Link test performed before hardware reset so autoneg doesn't * interfere with test result */ if (e1000_link_test(adapter, &data[4])) @@ -1629,6 +1646,8 @@ e1000_diag_test(struct net_device *netdev, eth_test->flags |= ETH_TEST_FL_FAILED; e1000_reset(adapter); + /* make sure the phy is powered up */ + e1000_power_up_phy(adapter); if (e1000_loopback_test(adapter, &data[3])) eth_test->flags |= ETH_TEST_FL_FAILED; @@ -1642,6 +1661,7 @@ e1000_diag_test(struct net_device *netdev, if (if_running) dev_open(netdev); } else { + DPRINTK(HW, INFO, "online testing starting\n"); /* Online tests */ if (e1000_link_test(adapter, &data[4])) eth_test->flags |= ETH_TEST_FL_FAILED; |