e1000: Report link status in ethtool when interface is down
authorNick Nunley <nicholasx.d.nunley@intel.com>
Wed, 3 Feb 2010 14:49:28 +0000 (14:49 +0000)
committerDavid S. Miller <davem@davemloft.net>
Thu, 4 Feb 2010 03:39:56 +0000 (19:39 -0800)
With this change ethtool will correctly report link status when
the interface is down. Currently ethtool reports the link as not
detected when the interface is down.

Signed-off-by: Nicholas Nunley <nicholasx.d.nunley@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/e1000/e1000.h
drivers/net/e1000/e1000_ethtool.c
drivers/net/e1000/e1000_main.c

index e8932db7ee77ef42aa4c2ed349e641addc7c0ddd..9902b33b716052f7974cad7126b923a3068a27be 100644 (file)
@@ -349,6 +349,7 @@ extern int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
 extern void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
 extern void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
 extern void e1000_update_stats(struct e1000_adapter *adapter);
+extern bool e1000_has_link(struct e1000_adapter *adapter);
 extern void e1000_power_up_phy(struct e1000_adapter *);
 extern void e1000_set_ethtool_ops(struct net_device *netdev);
 extern void e1000_check_options(struct e1000_adapter *adapter);
index 13e9ece168898be9cde1265857f95ee29544b250..c67e93117271bb7478aac4d0c7d82cbbc19e64f6 100644 (file)
@@ -215,6 +215,23 @@ static int e1000_set_settings(struct net_device *netdev,
        return 0;
 }
 
+static u32 e1000_get_link(struct net_device *netdev)
+{
+       struct e1000_adapter *adapter = netdev_priv(netdev);
+
+       /*
+        * If the link is not reported up to netdev, interrupts are disabled,
+        * and so the physical link state may have changed since we last
+        * looked. Set get_link_status to make sure that the true link
+        * state is interrogated, rather than pulling a cached and possibly
+        * stale link state from the driver.
+        */
+       if (!netif_carrier_ok(netdev))
+               adapter->hw.get_link_status = 1;
+
+       return e1000_has_link(adapter);
+}
+
 static void e1000_get_pauseparam(struct net_device *netdev,
                                 struct ethtool_pauseparam *pause)
 {
@@ -1892,7 +1909,7 @@ static const struct ethtool_ops e1000_ethtool_ops = {
        .get_msglevel           = e1000_get_msglevel,
        .set_msglevel           = e1000_set_msglevel,
        .nway_reset             = e1000_nway_reset,
-       .get_link               = ethtool_op_get_link,
+       .get_link               = e1000_get_link,
        .get_eeprom_len         = e1000_get_eeprom_len,
        .get_eeprom             = e1000_get_eeprom,
        .set_eeprom             = e1000_set_eeprom,
index b608528f26fc962527104963ce90ec3799dca14c..4ff50d6fe5e4b2a42d604aba0404366d8c11d97a 100644 (file)
@@ -2246,7 +2246,7 @@ static void e1000_82547_tx_fifo_stall(unsigned long data)
        }
 }
 
-static bool e1000_has_link(struct e1000_adapter *adapter)
+bool e1000_has_link(struct e1000_adapter *adapter)
 {
        struct e1000_hw *hw = &adapter->hw;
        bool link_active = false;