Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[safe/jmp/linux-2.6] / drivers / net / ixgbe / ixgbe_ethtool.c
index 53b0a66..1525c86 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2009 Intel Corporation.
+  Copyright(c) 1999 - 2010 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
 
 #define IXGBE_ALL_RAR_ENTRIES 16
 
+enum {NETDEV_STATS, IXGBE_STATS};
+
 struct ixgbe_stats {
        char stat_string[ETH_GSTRING_LEN];
+       int type;
        int sizeof_stat;
        int stat_offset;
 };
 
-#define IXGBE_STAT(m) sizeof(((struct ixgbe_adapter *)0)->m), \
-                             offsetof(struct ixgbe_adapter, m)
+#define IXGBE_STAT(m)          IXGBE_STATS, \
+                               sizeof(((struct ixgbe_adapter *)0)->m), \
+                               offsetof(struct ixgbe_adapter, m)
+#define IXGBE_NETDEV_STAT(m)   NETDEV_STATS, \
+                               sizeof(((struct net_device *)0)->m), \
+                               offsetof(struct net_device, m)
+
 static struct ixgbe_stats ixgbe_gstrings_stats[] = {
-       {"rx_packets", IXGBE_STAT(net_stats.rx_packets)},
-       {"tx_packets", IXGBE_STAT(net_stats.tx_packets)},
-       {"rx_bytes", IXGBE_STAT(net_stats.rx_bytes)},
-       {"tx_bytes", IXGBE_STAT(net_stats.tx_bytes)},
+       {"rx_packets", IXGBE_NETDEV_STAT(stats.rx_packets)},
+       {"tx_packets", IXGBE_NETDEV_STAT(stats.tx_packets)},
+       {"rx_bytes", IXGBE_NETDEV_STAT(stats.rx_bytes)},
+       {"tx_bytes", IXGBE_NETDEV_STAT(stats.tx_bytes)},
+       {"rx_pkts_nic", IXGBE_STAT(stats.gprc)},
+       {"tx_pkts_nic", IXGBE_STAT(stats.gptc)},
+       {"rx_bytes_nic", IXGBE_STAT(stats.gorc)},
+       {"tx_bytes_nic", IXGBE_STAT(stats.gotc)},
        {"lsc_int", IXGBE_STAT(lsc_int)},
        {"tx_busy", IXGBE_STAT(tx_busy)},
        {"non_eop_descs", IXGBE_STAT(non_eop_descs)},
-       {"rx_errors", IXGBE_STAT(net_stats.rx_errors)},
-       {"tx_errors", IXGBE_STAT(net_stats.tx_errors)},
-       {"rx_dropped", IXGBE_STAT(net_stats.rx_dropped)},
-       {"tx_dropped", IXGBE_STAT(net_stats.tx_dropped)},
-       {"multicast", IXGBE_STAT(net_stats.multicast)},
+       {"rx_errors", IXGBE_NETDEV_STAT(stats.rx_errors)},
+       {"tx_errors", IXGBE_NETDEV_STAT(stats.tx_errors)},
+       {"rx_dropped", IXGBE_NETDEV_STAT(stats.rx_dropped)},
+       {"tx_dropped", IXGBE_NETDEV_STAT(stats.tx_dropped)},
+       {"multicast", IXGBE_NETDEV_STAT(stats.multicast)},
        {"broadcast", IXGBE_STAT(stats.bprc)},
        {"rx_no_buffer_count", IXGBE_STAT(stats.rnbc[0]) },
-       {"collisions", IXGBE_STAT(net_stats.collisions)},
-       {"rx_over_errors", IXGBE_STAT(net_stats.rx_over_errors)},
-       {"rx_crc_errors", IXGBE_STAT(net_stats.rx_crc_errors)},
-       {"rx_frame_errors", IXGBE_STAT(net_stats.rx_frame_errors)},
-       {"hw_rsc_count", IXGBE_STAT(rsc_count)},
+       {"collisions", IXGBE_NETDEV_STAT(stats.collisions)},
+       {"rx_over_errors", IXGBE_NETDEV_STAT(stats.rx_over_errors)},
+       {"rx_crc_errors", IXGBE_NETDEV_STAT(stats.rx_crc_errors)},
+       {"rx_frame_errors", IXGBE_NETDEV_STAT(stats.rx_frame_errors)},
+       {"hw_rsc_aggregated", IXGBE_STAT(rsc_total_count)},
+       {"hw_rsc_flushed", IXGBE_STAT(rsc_total_flush)},
        {"fdir_match", IXGBE_STAT(stats.fdirmatch)},
        {"fdir_miss", IXGBE_STAT(stats.fdirmiss)},
-       {"rx_fifo_errors", IXGBE_STAT(net_stats.rx_fifo_errors)},
-       {"rx_missed_errors", IXGBE_STAT(net_stats.rx_missed_errors)},
-       {"tx_aborted_errors", IXGBE_STAT(net_stats.tx_aborted_errors)},
-       {"tx_carrier_errors", IXGBE_STAT(net_stats.tx_carrier_errors)},
-       {"tx_fifo_errors", IXGBE_STAT(net_stats.tx_fifo_errors)},
-       {"tx_heartbeat_errors", IXGBE_STAT(net_stats.tx_heartbeat_errors)},
+       {"rx_fifo_errors", IXGBE_NETDEV_STAT(stats.rx_fifo_errors)},
+       {"rx_missed_errors", IXGBE_NETDEV_STAT(stats.rx_missed_errors)},
+       {"tx_aborted_errors", IXGBE_NETDEV_STAT(stats.tx_aborted_errors)},
+       {"tx_carrier_errors", IXGBE_NETDEV_STAT(stats.tx_carrier_errors)},
+       {"tx_fifo_errors", IXGBE_NETDEV_STAT(stats.tx_fifo_errors)},
+       {"tx_heartbeat_errors", IXGBE_NETDEV_STAT(stats.tx_heartbeat_errors)},
        {"tx_timeout_count", IXGBE_STAT(tx_timeout_count)},
        {"tx_restart_queue", IXGBE_STAT(restart_queue)},
        {"rx_long_length_errors", IXGBE_STAT(stats.roc)},
        {"rx_short_length_errors", IXGBE_STAT(stats.ruc)},
-       {"tx_tcp4_seg_ctxt", IXGBE_STAT(hw_tso_ctxt)},
-       {"tx_tcp6_seg_ctxt", IXGBE_STAT(hw_tso6_ctxt)},
        {"tx_flow_control_xon", IXGBE_STAT(stats.lxontxc)},
        {"rx_flow_control_xon", IXGBE_STAT(stats.lxonrxc)},
        {"tx_flow_control_xoff", IXGBE_STAT(stats.lxofftxc)},
        {"rx_flow_control_xoff", IXGBE_STAT(stats.lxoffrxc)},
-       {"rx_csum_offload_good", IXGBE_STAT(hw_csum_rx_good)},
        {"rx_csum_offload_errors", IXGBE_STAT(hw_csum_rx_error)},
-       {"tx_csum_offload_ctxt", IXGBE_STAT(hw_csum_tx_good)},
-       {"rx_header_split", IXGBE_STAT(rx_hdr_split)},
        {"alloc_rx_page_failed", IXGBE_STAT(alloc_rx_page_failed)},
        {"alloc_rx_buff_failed", IXGBE_STAT(alloc_rx_buff_failed)},
        {"rx_no_dma_resources", IXGBE_STAT(hw_rx_no_dma_resources)},
@@ -192,6 +200,56 @@ static int ixgbe_get_settings(struct net_device *netdev,
                ecmd->autoneg = AUTONEG_DISABLE;
        }
 
+       /* Get PHY type */
+       switch (adapter->hw.phy.type) {
+       case ixgbe_phy_tn:
+       case ixgbe_phy_cu_unknown:
+               /* Copper 10G-BASET */
+               ecmd->port = PORT_TP;
+               break;
+       case ixgbe_phy_qt:
+               ecmd->port = PORT_FIBRE;
+               break;
+       case ixgbe_phy_nl:
+       case ixgbe_phy_tw_tyco:
+       case ixgbe_phy_tw_unknown:
+       case ixgbe_phy_sfp_ftl:
+       case ixgbe_phy_sfp_avago:
+       case ixgbe_phy_sfp_intel:
+       case ixgbe_phy_sfp_unknown:
+               switch (adapter->hw.phy.sfp_type) {
+               /* SFP+ devices, further checking needed */
+               case ixgbe_sfp_type_da_cu:
+               case ixgbe_sfp_type_da_cu_core0:
+               case ixgbe_sfp_type_da_cu_core1:
+                       ecmd->port = PORT_DA;
+                       break;
+               case ixgbe_sfp_type_sr:
+               case ixgbe_sfp_type_lr:
+               case ixgbe_sfp_type_srlr_core0:
+               case ixgbe_sfp_type_srlr_core1:
+                       ecmd->port = PORT_FIBRE;
+                       break;
+               case ixgbe_sfp_type_not_present:
+                       ecmd->port = PORT_NONE;
+                       break;
+               case ixgbe_sfp_type_unknown:
+               default:
+                       ecmd->port = PORT_OTHER;
+                       break;
+               }
+               break;
+       case ixgbe_phy_xaui:
+               ecmd->port = PORT_NONE;
+               break;
+       case ixgbe_phy_unknown:
+       case ixgbe_phy_generic:
+       case ixgbe_phy_sfp_unsupported:
+       default:
+               ecmd->port = PORT_OTHER;
+               break;
+       }
+
        hw->mac.ops.check_link(hw, &link_speed, &link_up, false);
        if (link_up) {
                ecmd->speed = (link_speed == IXGBE_LINK_SPEED_10GB_FULL) ?
@@ -794,7 +852,7 @@ static int ixgbe_set_ringparam(struct net_device *netdev,
 {
        struct ixgbe_adapter *adapter = netdev_priv(netdev);
        struct ixgbe_ring *temp_tx_ring, *temp_rx_ring;
-       int i, err;
+       int i, err = 0;
        u32 new_rx_count, new_tx_count;
        bool need_update = false;
 
@@ -818,6 +876,16 @@ static int ixgbe_set_ringparam(struct net_device *netdev,
        while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state))
                msleep(1);
 
+       if (!netif_running(adapter->netdev)) {
+               for (i = 0; i < adapter->num_tx_queues; i++)
+                       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->tx_ring_count = new_tx_count;
+               adapter->rx_ring_count = new_rx_count;
+               goto err_setup;
+       }
+
        temp_tx_ring = kcalloc(adapter->num_tx_queues,
                               sizeof(struct ixgbe_ring), GFP_KERNEL);
        if (!temp_tx_ring) {
@@ -875,8 +943,7 @@ static int ixgbe_set_ringparam(struct net_device *netdev,
 
        /* if rings need to be updated, here's the place to do it in one shot */
        if (need_update) {
-               if (netif_running(netdev))
-                       ixgbe_down(adapter);
+               ixgbe_down(adapter);
 
                /* tx */
                if (new_tx_count != adapter->tx_ring_count) {
@@ -893,13 +960,8 @@ static int ixgbe_set_ringparam(struct net_device *netdev,
                        temp_rx_ring = NULL;
                        adapter->rx_ring_count = new_rx_count;
                }
-       }
-
-       /* success! */
-       err = 0;
-       if (netif_running(netdev))
                ixgbe_up(adapter);
-
+       }
 err_setup:
        clear_bit(__IXGBE_RESETTING, &adapter->state);
        return err;
@@ -925,10 +987,22 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev,
        int stat_count = sizeof(struct ixgbe_queue_stats) / sizeof(u64);
        int j, k;
        int i;
+       char *p = NULL;
 
        ixgbe_update_stats(adapter);
+       dev_get_stats(netdev);
        for (i = 0; i < IXGBE_GLOBAL_STATS_LEN; i++) {
-               char *p = (char *)adapter + ixgbe_gstrings_stats[i].stat_offset;
+               switch (ixgbe_gstrings_stats[i].type) {
+               case NETDEV_STATS:
+                       p = (char *) netdev +
+                                       ixgbe_gstrings_stats[i].stat_offset;
+                       break;
+               case IXGBE_STATS:
+                       p = (char *) adapter +
+                                       ixgbe_gstrings_stats[i].stat_offset;
+                       break;
+               }
+
                data[i] = (ixgbe_gstrings_stats[i].sizeof_stat ==
                           sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
        }
@@ -1247,15 +1321,15 @@ static int ixgbe_intr_test(struct ixgbe_adapter *adapter, u64 *data)
                return 0;
        } else if (adapter->flags & IXGBE_FLAG_MSI_ENABLED) {
                shared_int = false;
-               if (request_irq(irq, &ixgbe_test_intr, 0, netdev->name,
+               if (request_irq(irq, ixgbe_test_intr, 0, netdev->name,
                                netdev)) {
                        *data = 1;
                        return -1;
                }
-       } else if (!request_irq(irq, &ixgbe_test_intr, IRQF_PROBE_SHARED,
+       } else if (!request_irq(irq, ixgbe_test_intr, IRQF_PROBE_SHARED,
                                netdev->name, netdev)) {
                shared_int = false;
-       } else if (request_irq(irq, &ixgbe_test_intr, IRQF_SHARED,
+       } else if (request_irq(irq, ixgbe_test_intr, IRQF_SHARED,
                               netdev->name, netdev)) {
                *data = 1;
                return -1;
@@ -1793,11 +1867,22 @@ static void ixgbe_diag_test(struct net_device *netdev,
                if (ixgbe_intr_test(adapter, &data[2]))
                        eth_test->flags |= ETH_TEST_FL_FAILED;
 
+               /* If SRIOV or VMDq is enabled then skip MAC
+                * loopback diagnostic. */
+               if (adapter->flags & (IXGBE_FLAG_SRIOV_ENABLED |
+                                     IXGBE_FLAG_VMDQ_ENABLED)) {
+                       DPRINTK(HW, INFO, "Skip MAC loopback diagnostic in VT "
+                               "mode\n");
+                       data[3] = 0;
+                       goto skip_loopback;
+               }
+
                ixgbe_reset(adapter);
                DPRINTK(HW, INFO, "loopback testing starting\n");
                if (ixgbe_loopback_test(adapter, &data[3]))
                        eth_test->flags |= ETH_TEST_FL_FAILED;
 
+skip_loopback:
                ixgbe_reset(adapter);
 
                clear_bit(__IXGBE_TESTING, &adapter->state);
@@ -1944,6 +2029,10 @@ static int ixgbe_get_coalesce(struct net_device *netdev,
                break;
        }
 
+       /* if in mixed tx/rx queues per vector mode, report only rx settings */
+       if (adapter->q_vector[0]->txr_count && adapter->q_vector[0]->rxr_count)
+               return 0;
+
        /* only valid if in constant ITR mode */
        switch (adapter->tx_itr_setting) {
        case 0:
@@ -1969,12 +2058,9 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
        struct ixgbe_q_vector *q_vector;
        int i;
 
-       /*
-        * don't accept tx specific changes if we've got mixed RxTx vectors
-        * test and jump out here if needed before changing the rx numbers
-        */
-       if ((1000000/ec->tx_coalesce_usecs) != adapter->tx_eitr_param &&
-           adapter->q_vector[0]->txr_count && adapter->q_vector[0]->rxr_count)
+       /* don't accept tx specific changes if we've got mixed RxTx vectors */
+       if (adapter->q_vector[0]->txr_count && adapter->q_vector[0]->rxr_count
+          && ec->tx_coalesce_usecs)
                return -EINVAL;
 
        if (ec->tx_max_coalesced_frames_irq)