]> err.no Git - linux-2.6/blobdiff - drivers/net/igb/igb_ethtool.c
igb: fixes 82576 serdes init to correctly support manual flow control changes
[linux-2.6] / drivers / net / igb / igb_ethtool.c
index e27d5a533b4f591d914e8867428e5452cf62dc09..11aee13099513bea5dddd87cb4ff17fa4c135f7b 100644 (file)
@@ -93,6 +93,11 @@ static const struct igb_stats igb_gstrings_stats[] = {
        { "tx_smbus", IGB_STAT(stats.mgptc) },
        { "rx_smbus", IGB_STAT(stats.mgprc) },
        { "dropped_smbus", IGB_STAT(stats.mgpdc) },
+#ifdef CONFIG_IGB_LRO
+       { "lro_aggregated", IGB_STAT(lro_aggregated) },
+       { "lro_flushed", IGB_STAT(lro_flushed) },
+       { "lro_no_desc", IGB_STAT(lro_no_desc) },
+#endif
 };
 
 #define IGB_QUEUE_STATS_LEN \
@@ -1097,7 +1102,7 @@ static int igb_intr_test(struct igb_adapter *adapter, u64 *data)
        if (adapter->msix_entries) {
                /* NOTE: we don't test MSI-X interrupts here, yet */
                return 0;
-       } else if (adapter->msi_enabled) {
+       } else if (adapter->flags & IGB_FLAG_HAS_MSI) {
                shared_int = false;
                if (request_irq(irq, &igb_test_intr, 0, netdev->name, netdev)) {
                        *data = 1;
@@ -1727,7 +1732,6 @@ static int igb_wol_exclusion(struct igb_adapter *adapter,
 
        switch (hw->device_id) {
        case E1000_DEV_ID_82575GB_QUAD_COPPER:
-       case E1000_DEV_ID_82576_QUAD_COPPER:
                /* WoL not supported */
                wol->supported = 0;
                break;
@@ -1742,6 +1746,15 @@ static int igb_wol_exclusion(struct igb_adapter *adapter,
                /* return success for non excluded adapter ports */
                retval = 0;
                break;
+       case E1000_DEV_ID_82576_QUAD_COPPER:
+               /* quad port adapters only support WoL on port A */
+               if (!(adapter->flags & IGB_FLAG_QUAD_PORT_A)) {
+                       wol->supported = 0;
+                       break;
+               }
+               /* return success for non excluded adapter ports */
+               retval = 0;
+               break;
        default:
                /* dual port cards only support WoL on port A from now on
                 * unless it was enabled in the eeprom for port B
@@ -1848,6 +1861,8 @@ static int igb_set_coalesce(struct net_device *netdev,
                            struct ethtool_coalesce *ec)
 {
        struct igb_adapter *adapter = netdev_priv(netdev);
+       struct e1000_hw *hw = &adapter->hw;
+       int i;
 
        if ((ec->rx_coalesce_usecs > IGB_MAX_ITR_USECS) ||
            ((ec->rx_coalesce_usecs > 3) &&
@@ -1856,13 +1871,16 @@ static int igb_set_coalesce(struct net_device *netdev,
                return -EINVAL;
 
        /* convert to rate of irq's per second */
-       if (ec->rx_coalesce_usecs <= 3)
+       if (ec->rx_coalesce_usecs && ec->rx_coalesce_usecs <= 3) {
                adapter->itr_setting = ec->rx_coalesce_usecs;
-       else
-               adapter->itr_setting = (1000000 / ec->rx_coalesce_usecs);
+               adapter->itr = IGB_START_ITR;
+       } else {
+               adapter->itr_setting = ec->rx_coalesce_usecs << 2;
+               adapter->itr = adapter->itr_setting;
+       }
 
-       if (netif_running(netdev))
-               igb_reinit_locked(adapter);
+       for (i = 0; i < adapter->num_rx_queues; i++)
+               wr32(adapter->rx_ring[i].itr_register, adapter->itr);
 
        return 0;
 }
@@ -1875,7 +1893,7 @@ static int igb_get_coalesce(struct net_device *netdev,
        if (adapter->itr_setting <= 3)
                ec->rx_coalesce_usecs = adapter->itr_setting;
        else
-               ec->rx_coalesce_usecs = 1000000 / adapter->itr_setting;
+               ec->rx_coalesce_usecs = adapter->itr_setting >> 2;
 
        return 0;
 }
@@ -1909,6 +1927,18 @@ static void igb_get_ethtool_stats(struct net_device *netdev,
        int stat_count = sizeof(struct igb_queue_stats) / sizeof(u64);
        int j;
        int i;
+#ifdef CONFIG_IGB_LRO
+       int aggregated = 0, flushed = 0, no_desc = 0;
+
+       for (i = 0; i < adapter->num_rx_queues; i++) {
+               aggregated += adapter->rx_ring[i].lro_mgr.stats.aggregated;
+               flushed += adapter->rx_ring[i].lro_mgr.stats.flushed;
+               no_desc += adapter->rx_ring[i].lro_mgr.stats.no_desc;
+       }
+       adapter->lro_aggregated = aggregated;
+       adapter->lro_flushed = flushed;
+       adapter->lro_no_desc = no_desc;
+#endif
 
        igb_update_stats(adapter);
        for (i = 0; i < IGB_GLOBAL_STATS_LEN; i++) {