]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/net/igb/igb_ethtool.c
include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[mv-sheeva.git] / drivers / net / igb / igb_ethtool.c
index f771a6c08777c8438db7f25e37e388089464ccae..d313fae992da8d87c205641067a209de24ec6678 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/if_ether.h>
 #include <linux/ethtool.h>
 #include <linux/sched.h>
+#include <linux/slab.h>
 
 #include "igb.h"
 
@@ -234,6 +235,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)
 {
@@ -296,7 +315,7 @@ static int igb_set_pauseparam(struct net_device *netdev,
 static u32 igb_get_rx_csum(struct net_device *netdev)
 {
        struct igb_adapter *adapter = netdev_priv(netdev);
-       return !!(adapter->rx_ring[0].flags & IGB_RING_FLAG_RX_CSUM);
+       return !!(adapter->rx_ring[0]->flags & IGB_RING_FLAG_RX_CSUM);
 }
 
 static int igb_set_rx_csum(struct net_device *netdev, u32 data)
@@ -306,9 +325,9 @@ static int igb_set_rx_csum(struct net_device *netdev, u32 data)
 
        for (i = 0; i < adapter->num_rx_queues; i++) {
                if (data)
-                       adapter->rx_ring[i].flags |= IGB_RING_FLAG_RX_CSUM;
+                       adapter->rx_ring[i]->flags |= IGB_RING_FLAG_RX_CSUM;
                else
-                       adapter->rx_ring[i].flags &= ~IGB_RING_FLAG_RX_CSUM;
+                       adapter->rx_ring[i]->flags &= ~IGB_RING_FLAG_RX_CSUM;
        }
 
        return 0;
@@ -771,9 +790,9 @@ static int igb_set_ringparam(struct net_device *netdev,
 
        if (!netif_running(adapter->netdev)) {
                for (i = 0; i < adapter->num_tx_queues; i++)
-                       adapter->tx_ring[i].count = new_tx_count;
+                       adapter->tx_ring[i]->count = new_tx_count;
                for (i = 0; i < adapter->num_rx_queues; i++)
-                       adapter->rx_ring[i].count = new_rx_count;
+                       adapter->rx_ring[i]->count = new_rx_count;
                adapter->tx_ring_count = new_tx_count;
                adapter->rx_ring_count = new_rx_count;
                goto clear_reset;
@@ -797,10 +816,10 @@ static int igb_set_ringparam(struct net_device *netdev,
         * to the tx and rx ring structs.
         */
        if (new_tx_count != adapter->tx_ring_count) {
-               memcpy(temp_ring, adapter->tx_ring,
-                      adapter->num_tx_queues * sizeof(struct igb_ring));
-
                for (i = 0; i < adapter->num_tx_queues; i++) {
+                       memcpy(&temp_ring[i], adapter->tx_ring[i],
+                              sizeof(struct igb_ring));
+
                        temp_ring[i].count = new_tx_count;
                        err = igb_setup_tx_resources(&temp_ring[i]);
                        if (err) {
@@ -812,20 +831,21 @@ static int igb_set_ringparam(struct net_device *netdev,
                        }
                }
 
-               for (i = 0; i < adapter->num_tx_queues; i++)
-                       igb_free_tx_resources(&adapter->tx_ring[i]);
+               for (i = 0; i < adapter->num_tx_queues; i++) {
+                       igb_free_tx_resources(adapter->tx_ring[i]);
 
-               memcpy(adapter->tx_ring, temp_ring,
-                      adapter->num_tx_queues * sizeof(struct igb_ring));
+                       memcpy(adapter->tx_ring[i], &temp_ring[i],
+                              sizeof(struct igb_ring));
+               }
 
                adapter->tx_ring_count = new_tx_count;
        }
 
-       if (new_rx_count != adapter->rx_ring->count) {
-               memcpy(temp_ring, adapter->rx_ring,
-                      adapter->num_rx_queues * sizeof(struct igb_ring));
-
+       if (new_rx_count != adapter->rx_ring_count) {
                for (i = 0; i < adapter->num_rx_queues; i++) {
+                       memcpy(&temp_ring[i], adapter->rx_ring[i],
+                              sizeof(struct igb_ring));
+
                        temp_ring[i].count = new_rx_count;
                        err = igb_setup_rx_resources(&temp_ring[i]);
                        if (err) {
@@ -838,11 +858,12 @@ static int igb_set_ringparam(struct net_device *netdev,
 
                }
 
-               for (i = 0; i < adapter->num_rx_queues; i++)
-                       igb_free_rx_resources(&adapter->rx_ring[i]);
+               for (i = 0; i < adapter->num_rx_queues; i++) {
+                       igb_free_rx_resources(adapter->rx_ring[i]);
 
-               memcpy(adapter->rx_ring, temp_ring,
-                      adapter->num_rx_queues * sizeof(struct igb_ring));
+                       memcpy(adapter->rx_ring[i], &temp_ring[i],
+                              sizeof(struct igb_ring));
+               }
 
                adapter->rx_ring_count = new_rx_count;
        }
@@ -1704,6 +1725,9 @@ static void igb_diag_test(struct net_device *netdev,
 
                dev_info(&adapter->pdev->dev, "offline testing starting\n");
 
+               /* power up link for link test */
+               igb_power_up_link(adapter);
+
                /* Link test performed before hardware reset so autoneg doesn't
                 * interfere with test result */
                if (igb_link_test(adapter, &data[4]))
@@ -1727,6 +1751,8 @@ static void igb_diag_test(struct net_device *netdev,
                        eth_test->flags |= ETH_TEST_FL_FAILED;
 
                igb_reset(adapter);
+               /* power up link for loopback test */
+               igb_power_up_link(adapter);
                if (igb_loopback_test(adapter, &data[3]))
                        eth_test->flags |= ETH_TEST_FL_FAILED;
 
@@ -1745,9 +1771,14 @@ static void igb_diag_test(struct net_device *netdev,
                        dev_open(netdev);
        } else {
                dev_info(&adapter->pdev->dev, "online testing starting\n");
-               /* Online tests */
-               if (igb_link_test(adapter, &data[4]))
-                       eth_test->flags |= ETH_TEST_FL_FAILED;
+
+               /* PHY is powered down when interface is down */
+               if (!netif_carrier_ok(netdev)) {
+                       data[4] = 0;
+               } else {
+                       if (igb_link_test(adapter, &data[4]))
+                               eth_test->flags |= ETH_TEST_FL_FAILED;
+               }
 
                /* Online tests aren't run; pass by default */
                data[0] = 0;
@@ -1812,7 +1843,8 @@ static void igb_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
        struct igb_adapter *adapter = netdev_priv(netdev);
 
        wol->supported = WAKE_UCAST | WAKE_MCAST |
-                        WAKE_BCAST | WAKE_MAGIC;
+                        WAKE_BCAST | WAKE_MAGIC |
+                        WAKE_PHY;
        wol->wolopts = 0;
 
        /* this function will set ->supported = 0 and return 1 if wol is not
@@ -1835,15 +1867,15 @@ static void igb_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
                wol->wolopts |= WAKE_BCAST;
        if (adapter->wol & E1000_WUFC_MAG)
                wol->wolopts |= WAKE_MAGIC;
-
-       return;
+       if (adapter->wol & E1000_WUFC_LNKC)
+               wol->wolopts |= WAKE_PHY;
 }
 
 static int igb_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
 {
        struct igb_adapter *adapter = netdev_priv(netdev);
 
-       if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE))
+       if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE))
                return -EOPNOTSUPP;
 
        if (igb_wol_exclusion(adapter, wol) ||
@@ -1861,6 +1893,8 @@ static int igb_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
                adapter->wol |= E1000_WUFC_BC;
        if (wol->wolopts & WAKE_MAGIC)
                adapter->wol |= E1000_WUFC_MAG;
+       if (wol->wolopts & WAKE_PHY)
+               adapter->wol |= E1000_WUFC_LNKC;
        device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
 
        return 0;
@@ -2005,12 +2039,12 @@ static void igb_get_ethtool_stats(struct net_device *netdev,
                        sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
        }
        for (j = 0; j < adapter->num_tx_queues; j++) {
-               queue_stat = (u64 *)&adapter->tx_ring[j].tx_stats;
+               queue_stat = (u64 *)&adapter->tx_ring[j]->tx_stats;
                for (k = 0; k < IGB_TX_QUEUE_STATS_LEN; k++, i++)
                        data[i] = queue_stat[k];
        }
        for (j = 0; j < adapter->num_rx_queues; j++) {
-               queue_stat = (u64 *)&adapter->rx_ring[j].rx_stats;
+               queue_stat = (u64 *)&adapter->rx_ring[j]->rx_stats;
                for (k = 0; k < IGB_RX_QUEUE_STATS_LEN; k++, i++)
                        data[i] = queue_stat[k];
        }
@@ -2074,7 +2108,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,