aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/loopback.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/loopback.c')
-rw-r--r--drivers/net/loopback.c33
1 files changed, 22 insertions, 11 deletions
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index 72b7949c91b1..9a0996795321 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -58,11 +58,13 @@
58#include <linux/tcp.h> 58#include <linux/tcp.h>
59#include <linux/percpu.h> 59#include <linux/percpu.h>
60#include <net/net_namespace.h> 60#include <net/net_namespace.h>
61#include <linux/u64_stats_sync.h>
61 62
62struct pcpu_lstats { 63struct pcpu_lstats {
63 unsigned long packets; 64 u64 packets;
64 unsigned long bytes; 65 u64 bytes;
65 unsigned long drops; 66 struct u64_stats_sync syncp;
67 unsigned long drops;
66}; 68};
67 69
68/* 70/*
@@ -86,31 +88,40 @@ static netdev_tx_t loopback_xmit(struct sk_buff *skb,
86 88
87 len = skb->len; 89 len = skb->len;
88 if (likely(netif_rx(skb) == NET_RX_SUCCESS)) { 90 if (likely(netif_rx(skb) == NET_RX_SUCCESS)) {
91 u64_stats_update_begin(&lb_stats->syncp);
89 lb_stats->bytes += len; 92 lb_stats->bytes += len;
90 lb_stats->packets++; 93 lb_stats->packets++;
94 u64_stats_update_end(&lb_stats->syncp);
91 } else 95 } else
92 lb_stats->drops++; 96 lb_stats->drops++;
93 97
94 return NETDEV_TX_OK; 98 return NETDEV_TX_OK;
95} 99}
96 100
97static struct net_device_stats *loopback_get_stats(struct net_device *dev) 101static struct rtnl_link_stats64 *loopback_get_stats64(struct net_device *dev,
102 struct rtnl_link_stats64 *stats)
98{ 103{
99 const struct pcpu_lstats __percpu *pcpu_lstats; 104 const struct pcpu_lstats __percpu *pcpu_lstats;
100 struct net_device_stats *stats = &dev->stats; 105 u64 bytes = 0;
101 unsigned long bytes = 0; 106 u64 packets = 0;
102 unsigned long packets = 0; 107 u64 drops = 0;
103 unsigned long drops = 0;
104 int i; 108 int i;
105 109
106 pcpu_lstats = (void __percpu __force *)dev->ml_priv; 110 pcpu_lstats = (void __percpu __force *)dev->ml_priv;
107 for_each_possible_cpu(i) { 111 for_each_possible_cpu(i) {
108 const struct pcpu_lstats *lb_stats; 112 const struct pcpu_lstats *lb_stats;
113 u64 tbytes, tpackets;
114 unsigned int start;
109 115
110 lb_stats = per_cpu_ptr(pcpu_lstats, i); 116 lb_stats = per_cpu_ptr(pcpu_lstats, i);
111 bytes += lb_stats->bytes; 117 do {
112 packets += lb_stats->packets; 118 start = u64_stats_fetch_begin(&lb_stats->syncp);
119 tbytes = lb_stats->bytes;
120 tpackets = lb_stats->packets;
121 } while (u64_stats_fetch_retry(&lb_stats->syncp, start));
113 drops += lb_stats->drops; 122 drops += lb_stats->drops;
123 bytes += tbytes;
124 packets += tpackets;
114 } 125 }
115 stats->rx_packets = packets; 126 stats->rx_packets = packets;
116 stats->tx_packets = packets; 127 stats->tx_packets = packets;
@@ -158,7 +169,7 @@ static void loopback_dev_free(struct net_device *dev)
158static const struct net_device_ops loopback_ops = { 169static const struct net_device_ops loopback_ops = {
159 .ndo_init = loopback_dev_init, 170 .ndo_init = loopback_dev_init,
160 .ndo_start_xmit= loopback_xmit, 171 .ndo_start_xmit= loopback_xmit,
161 .ndo_get_stats = loopback_get_stats, 172 .ndo_get_stats64 = loopback_get_stats64,
162}; 173};
163 174
164/* 175/*