igb: Implement reading of reg RQDPC (Receive Queue Drop Packet Count)
authorJesper Dangaard Brouer <hawk@comx.dk>
Tue, 26 May 2009 13:50:31 +0000 (13:50 +0000)
committerDavid S. Miller <davem@davemloft.net>
Wed, 27 May 2009 03:35:05 +0000 (20:35 -0700)
Based on the previous patches from Jesper Dangaard Brouer <hawk@comx.dk>

Implement reading the per queue drop stats register
RQDPC (Receive Queue Drop Packet Count).  It counts the number of
packets dropped by a queue due to lack of descriptors available.

Notice RQDPC (Receive Queue Drop Packet Count) stats only gets
incremented, if the DROP_EN bit it set (in the SRRCTL register
for that queue).  If DROP_EN bit is NOT set, then the some what
equivalent count is stored in RNBC (not per queue basis).

The RQDPC register is only 12 bit, thus the precision might
suffer due to overrun in-netween the watchdog polling interval.

Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
CC: Jesper Dangaard Brouer <hawk@comx.dk>
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 154c5acc6fce641eadf1d86405a1a5f240b8af8b..b2c98dea9eed4c01bd0bbfbdf750d1231b53c66e 100644 (file)
@@ -137,11 +137,17 @@ struct igb_buffer {
        };
 };
 
-struct igb_queue_stats {
+struct igb_tx_queue_stats {
        u64 packets;
        u64 bytes;
 };
 
+struct igb_rx_queue_stats {
+       u64 packets;
+       u64 bytes;
+       u64 drops;
+};
+
 struct igb_ring {
        struct igb_adapter *adapter; /* backlink */
        void *desc;                  /* descriptor ring memory */
@@ -167,12 +173,13 @@ struct igb_ring {
        union {
                /* TX */
                struct {
-                       struct igb_queue_stats tx_stats;
+                       struct igb_tx_queue_stats tx_stats;
                        bool detect_tx_hung;
                };
                /* RX */
                struct {
-                       struct igb_queue_stats rx_stats;
+                       struct igb_rx_queue_stats rx_stats;
+                       u64 rx_queue_drops;
                        struct napi_struct napi;
                        int set_itr;
                        struct igb_ring *buddy;
index b8551a57dd3f8d2b5b66a50e145fe56211b380f7..2ae98f91372e8c3d46d8ef5dfe76aeca0f018047 100644 (file)
@@ -96,9 +96,10 @@ static const struct igb_stats igb_gstrings_stats[] = {
 };
 
 #define IGB_QUEUE_STATS_LEN \
-       ((((struct igb_adapter *)netdev_priv(netdev))->num_rx_queues + \
-        ((struct igb_adapter *)netdev_priv(netdev))->num_tx_queues) * \
-       (sizeof(struct igb_queue_stats) / sizeof(u64)))
+       (((((struct igb_adapter *)netdev_priv(netdev))->num_rx_queues)* \
+         (sizeof(struct igb_rx_queue_stats) / sizeof(u64))) + \
+        ((((struct igb_adapter *)netdev_priv(netdev))->num_tx_queues) * \
+         (sizeof(struct igb_tx_queue_stats) / sizeof(u64))))
 #define IGB_GLOBAL_STATS_LEN   \
        sizeof(igb_gstrings_stats) / sizeof(struct igb_stats)
 #define IGB_STATS_LEN (IGB_GLOBAL_STATS_LEN + IGB_QUEUE_STATS_LEN)
@@ -1960,7 +1961,8 @@ static void igb_get_ethtool_stats(struct net_device *netdev,
 {
        struct igb_adapter *adapter = netdev_priv(netdev);
        u64 *queue_stat;
-       int stat_count = sizeof(struct igb_queue_stats) / sizeof(u64);
+       int stat_count_tx = sizeof(struct igb_tx_queue_stats) / sizeof(u64);
+       int stat_count_rx = sizeof(struct igb_rx_queue_stats) / sizeof(u64);
        int j;
        int i;
 
@@ -1973,14 +1975,14 @@ static void igb_get_ethtool_stats(struct net_device *netdev,
        for (j = 0; j < adapter->num_tx_queues; j++) {
                int k;
                queue_stat = (u64 *)&adapter->tx_ring[j].tx_stats;
-               for (k = 0; k < stat_count; k++)
+               for (k = 0; k < stat_count_tx; k++)
                        data[i + k] = queue_stat[k];
                i += k;
        }
        for (j = 0; j < adapter->num_rx_queues; j++) {
                int k;
                queue_stat = (u64 *)&adapter->rx_ring[j].rx_stats;
-               for (k = 0; k < stat_count; k++)
+               for (k = 0; k < stat_count_rx; k++)
                        data[i + k] = queue_stat[k];
                i += k;
        }
@@ -2014,6 +2016,8 @@ static void igb_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
                        p += ETH_GSTRING_LEN;
                        sprintf(p, "rx_queue_%u_bytes", i);
                        p += ETH_GSTRING_LEN;
+                       sprintf(p, "rx_queue_%u_drops", i);
+                       p += ETH_GSTRING_LEN;
                }
 /*             BUG_ON(p - data != IGB_STATS_LEN * ETH_GSTRING_LEN); */
                break;
index 2ec98091948b9955967e09334e08cb49842444e7..4ae81331dca5db7a11046a9c990b6109ee115874 100644 (file)
@@ -3588,8 +3588,25 @@ void igb_update_stats(struct igb_adapter *adapter)
 
        /* Rx Errors */
 
+       if (hw->mac.type != e1000_82575) {
+               u32 rqdpc_tmp;
+               int i;
+               /* Read out drops stats per RX queue.  Notice RQDPC (Receive
+                * Queue Drop Packet Count) stats only gets incremented, if
+                * the DROP_EN but it set (in the SRRCTL register for that
+                * queue).  If DROP_EN bit is NOT set, then the some what
+                * equivalent count is stored in RNBC (not per queue basis).
+                * Also note the drop count is due to lack of available
+                * descriptors.
+                */
+               for (i = 0; i < adapter->num_rx_queues; i++) {
+                       rqdpc_tmp = rd32(E1000_RQDPC(i)) & 0xFFF;
+                       adapter->rx_ring[i].rx_stats.drops += rqdpc_tmp;
+               }
+       }
+
        /* RLEC on some newer hardware can be incorrect so build
-       * our own version based on RUC and ROC */
+        * our own version based on RUC and ROC */
        adapter->net_stats.rx_errors = adapter->stats.rxerrc +
                adapter->stats.crcerrs + adapter->stats.algnerrc +
                adapter->stats.ruc + adapter->stats.roc +