ifb: convert to 64 bit stats
authorstephen hemminger <shemminger@vyatta.com>
Mon, 20 Jun 2011 11:42:30 +0000 (11:42 +0000)
committerDavid S. Miller <davem@davemloft.net>
Tue, 21 Jun 2011 22:55:09 +0000 (15:55 -0700)
Convert input functional block device to use 64 bit stats.

Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Acked-by: Jamal Hadi Salim <hadi@cyberus.ca>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ifb.c

index ce53f4a23b199f2fceaa0b938a6f70fbce3aac04..6e82dd32e8063b019dcba2918c8fb108d6ab7eb5 100644 (file)
 struct ifb_private {
        struct tasklet_struct   ifb_tasklet;
        int     tasklet_pending;
+
+       struct u64_stats_sync   rsync;
        struct sk_buff_head     rq;
+       u64 rx_packets;
+       u64 rx_bytes;
+
+       struct u64_stats_sync   tsync;
        struct sk_buff_head     tq;
+       u64 tx_packets;
+       u64 tx_bytes;
 };
 
 static int numifbs = 2;
@@ -54,10 +62,8 @@ static int ifb_close(struct net_device *dev);
 
 static void ri_tasklet(unsigned long dev)
 {
-
        struct net_device *_dev = (struct net_device *)dev;
        struct ifb_private *dp = netdev_priv(_dev);
-       struct net_device_stats *stats = &_dev->stats;
        struct netdev_queue *txq;
        struct sk_buff *skb;
 
@@ -77,15 +83,18 @@ static void ri_tasklet(unsigned long dev)
 
                skb->tc_verd = 0;
                skb->tc_verd = SET_TC_NCLS(skb->tc_verd);
-               stats->tx_packets++;
-               stats->tx_bytes +=skb->len;
+
+               u64_stats_update_begin(&dp->tsync);
+               dp->tx_packets++;
+               dp->tx_bytes += skb->len;
+               u64_stats_update_end(&dp->tsync);
 
                rcu_read_lock();
                skb->dev = dev_get_by_index_rcu(&init_net, skb->skb_iif);
                if (!skb->dev) {
                        rcu_read_unlock();
                        dev_kfree_skb(skb);
-                       stats->tx_dropped++;
+                       _dev->stats.tx_dropped++;
                        if (skb_queue_len(&dp->tq) != 0)
                                goto resched;
                        break;
@@ -120,9 +129,37 @@ resched:
 
 }
 
+static struct rtnl_link_stats64 *ifb_stats64(struct net_device *dev,
+                                            struct rtnl_link_stats64 *stats)
+{
+       struct ifb_private *dp = netdev_priv(dev);
+       unsigned int start;
+
+       do {
+               start = u64_stats_fetch_begin_bh(&dp->rsync);
+               stats->rx_packets = dp->rx_packets;
+               stats->rx_bytes = dp->rx_bytes;
+       } while (u64_stats_fetch_retry_bh(&dp->rsync, start));
+
+       do {
+               start = u64_stats_fetch_begin_bh(&dp->tsync);
+
+               stats->tx_packets = dp->tx_packets;
+               stats->tx_bytes = dp->tx_bytes;
+
+       } while (u64_stats_fetch_retry_bh(&dp->tsync, start));
+
+       stats->rx_dropped = dev->stats.rx_dropped;
+       stats->tx_dropped = dev->stats.tx_dropped;
+
+       return stats;
+}
+
+
 static const struct net_device_ops ifb_netdev_ops = {
        .ndo_open       = ifb_open,
        .ndo_stop       = ifb_close,
+       .ndo_get_stats64 = ifb_stats64,
        .ndo_start_xmit = ifb_xmit,
        .ndo_validate_addr = eth_validate_addr,
 };
@@ -153,15 +190,16 @@ static void ifb_setup(struct net_device *dev)
 static netdev_tx_t ifb_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct ifb_private *dp = netdev_priv(dev);
-       struct net_device_stats *stats = &dev->stats;
        u32 from = G_TC_FROM(skb->tc_verd);
 
-       stats->rx_packets++;
-       stats->rx_bytes+=skb->len;
+       u64_stats_update_begin(&dp->rsync);
+       dp->rx_packets++;
+       dp->rx_bytes += skb->len;
+       u64_stats_update_end(&dp->rsync);
 
        if (!(from & (AT_INGRESS|AT_EGRESS)) || !skb->skb_iif) {
                dev_kfree_skb(skb);
-               stats->rx_dropped++;
+               dev->stats.rx_dropped++;
                return NETDEV_TX_OK;
        }