igb: Report link status in ethtool when interface is down
authorNick Nunley <nicholasx.d.nunley@intel.com>
Wed, 17 Feb 2010 01:01:21 +0000 (01:01 +0000)
committerDavid S. Miller <davem@davemloft.net>
Wed, 17 Feb 2010 21:21:32 +0000 (13:21 -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/igb/igb.h
drivers/net/igb/igb_ethtool.c
drivers/net/igb/igb_main.c

index 0efd28515e6ec14e68a63f11216e409784669264..452a4dee87f8d40e0fbb0ce68947d438d1e91418 100644 (file)
@@ -356,6 +356,7 @@ extern void igb_unmap_and_free_tx_resource(struct igb_ring *,
                                           struct igb_buffer *);
 extern void igb_alloc_rx_buffers_adv(struct igb_ring *, int);
 extern void igb_update_stats(struct igb_adapter *);
+extern bool igb_has_link(struct igb_adapter *adapter);
 extern void igb_set_ethtool_ops(struct net_device *);
 
 static inline s32 igb_reset_phy(struct e1000_hw *hw)
index 145a8eb55fab61717afcf3bd8c672eb20ce3a737..4eea03b428c486534415216aab16675e3b2d3a48 100644 (file)
@@ -234,6 +234,24 @@ static int igb_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
        return 0;
 }
 
+static u32 igb_get_link(struct net_device *netdev)
+{
+       struct igb_adapter *adapter = netdev_priv(netdev);
+       struct e1000_mac_info *mac = &adapter->hw.mac;
+
+       /*
+        * 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))
+               mac->get_link_status = 1;
+
+       return igb_has_link(adapter);
+}
+
 static void igb_get_pauseparam(struct net_device *netdev,
                               struct ethtool_pauseparam *pause)
 {
@@ -2077,7 +2095,7 @@ static const struct ethtool_ops igb_ethtool_ops = {
        .get_msglevel           = igb_get_msglevel,
        .set_msglevel           = igb_set_msglevel,
        .nway_reset             = igb_nway_reset,
-       .get_link               = ethtool_op_get_link,
+       .get_link               = igb_get_link,
        .get_eeprom_len         = igb_get_eeprom_len,
        .get_eeprom             = igb_get_eeprom,
        .set_eeprom             = igb_set_eeprom,
index 677b5f5ab49c6e922c90b0ba8bd8347e04b3efc8..e40319e2ec251ed5e494f02e8beac32b6b32bea2 100644 (file)
@@ -3020,7 +3020,7 @@ static void igb_update_phy_info(unsigned long data)
  * igb_has_link - check shared code for link and determine up/down
  * @adapter: pointer to driver private info
  **/
-static bool igb_has_link(struct igb_adapter *adapter)
+bool igb_has_link(struct igb_adapter *adapter)
 {
        struct e1000_hw *hw = &adapter->hw;
        bool link_active = false;