]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
net: usbnet: support 64bit stats
authorGreg Ungerer <gerg@linux-m68k.org>
Mon, 3 Apr 2017 05:50:03 +0000 (15:50 +1000)
committerDavid S. Miller <davem@davemloft.net>
Tue, 4 Apr 2017 02:09:40 +0000 (19:09 -0700)
Add support for the net stats64 counters to the usbnet core. With that
in place put the hooks into every usbnet driver to use it.

This is a strait forward addition of 64bit counters for RX and TX packet
and byte counts. It is done in the same style as for the other net drivers
that support stats64. Note that the other stats fields remain as 32bit
sized values (error counts, etc).

The motivation to add this is that it is not particularly difficult to
get the RX and TX byte counts to wrap on 32bit platforms.

Signed-off-by: Greg Ungerer <gerg@linux-m68k.org>
Acked-by: Bjørn Mork <bjorn@mork.no>
Signed-off-by: David S. Miller <davem@davemloft.net>
18 files changed:
drivers/net/usb/asix_devices.c
drivers/net/usb/ax88172a.c
drivers/net/usb/ax88179_178a.c
drivers/net/usb/cdc_mbim.c
drivers/net/usb/cdc_ncm.c
drivers/net/usb/dm9601.c
drivers/net/usb/int51x1.c
drivers/net/usb/mcs7830.c
drivers/net/usb/qmi_wwan.c
drivers/net/usb/rndis_host.c
drivers/net/usb/sierra_net.c
drivers/net/usb/smsc75xx.c
drivers/net/usb/smsc95xx.c
drivers/net/usb/sr9700.c
drivers/net/usb/sr9800.c
drivers/net/usb/usbnet.c
drivers/net/wireless/rndis_wlan.c
include/linux/usb/usbnet.h

index 38456d0bcfd20dbae6f2d4a42a80a8f4f8ccc0e2..a3aa0a27dfe56b22121a0571cc4eaca1b2bbee03 100644 (file)
@@ -206,6 +206,7 @@ static const struct net_device_ops ax88172_netdev_ops = {
        .ndo_start_xmit         = usbnet_start_xmit,
        .ndo_tx_timeout         = usbnet_tx_timeout,
        .ndo_change_mtu         = usbnet_change_mtu,
+       .ndo_get_stats64        = usbnet_get_stats64,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_do_ioctl           = asix_ioctl,
@@ -591,6 +592,7 @@ static const struct net_device_ops ax88772_netdev_ops = {
        .ndo_start_xmit         = usbnet_start_xmit,
        .ndo_tx_timeout         = usbnet_tx_timeout,
        .ndo_change_mtu         = usbnet_change_mtu,
+       .ndo_get_stats64        = usbnet_get_stats64,
        .ndo_set_mac_address    = asix_set_mac_address,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_do_ioctl           = asix_ioctl,
@@ -1044,6 +1046,7 @@ static const struct net_device_ops ax88178_netdev_ops = {
        .ndo_stop               = usbnet_stop,
        .ndo_start_xmit         = usbnet_start_xmit,
        .ndo_tx_timeout         = usbnet_tx_timeout,
+       .ndo_get_stats64        = usbnet_get_stats64,
        .ndo_set_mac_address    = asix_set_mac_address,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_rx_mode        = asix_set_multicast,
index 6308386b09dfeafcb12c7912b06e8acf6aaff69b..501576f538546392381471da43f0d2897df243bd 100644 (file)
@@ -143,6 +143,7 @@ static const struct net_device_ops ax88172a_netdev_ops = {
        .ndo_start_xmit         = usbnet_start_xmit,
        .ndo_tx_timeout         = usbnet_tx_timeout,
        .ndo_change_mtu         = usbnet_change_mtu,
+       .ndo_get_stats64        = usbnet_get_stats64,
        .ndo_set_mac_address    = asix_set_mac_address,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_do_ioctl           = ax88172a_ioctl,
index 4a0ae7ce83f6b76abab36f08215623eb437dbd97..51cf60092a18e33924f52c568d91a33f30828b21 100644 (file)
@@ -959,6 +959,7 @@ static const struct net_device_ops ax88179_netdev_ops = {
        .ndo_stop               = usbnet_stop,
        .ndo_start_xmit         = usbnet_start_xmit,
        .ndo_tx_timeout         = usbnet_tx_timeout,
+       .ndo_get_stats64        = usbnet_get_stats64,
        .ndo_change_mtu         = ax88179_change_mtu,
        .ndo_set_mac_address    = ax88179_set_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
index 3a98f3762a4c81debc023d04b9c01876c6cbdc5f..a6b997cffd3b6e4c4f039a3d3dee5f386bb17e48 100644 (file)
@@ -100,6 +100,7 @@ static const struct net_device_ops cdc_mbim_netdev_ops = {
        .ndo_stop             = usbnet_stop,
        .ndo_start_xmit       = usbnet_start_xmit,
        .ndo_tx_timeout       = usbnet_tx_timeout,
+       .ndo_get_stats64      = usbnet_get_stats64,
        .ndo_change_mtu       = cdc_ncm_change_mtu,
        .ndo_set_mac_address  = eth_mac_addr,
        .ndo_validate_addr    = eth_validate_addr,
index b6c1d3abad967da3f79c514be1428d3b9d336be3..bb3f71f9fbde06ef1a8d514dbb856c8aa7ff5130 100644 (file)
@@ -753,6 +753,7 @@ static const struct net_device_ops cdc_ncm_netdev_ops = {
        .ndo_stop            = usbnet_stop,
        .ndo_start_xmit      = usbnet_start_xmit,
        .ndo_tx_timeout      = usbnet_tx_timeout,
+       .ndo_get_stats64     = usbnet_get_stats64,
        .ndo_change_mtu      = cdc_ncm_change_mtu,
        .ndo_set_mac_address = eth_mac_addr,
        .ndo_validate_addr   = eth_validate_addr,
index fea1b64ca26a6c284758bf0a827f582ba57def3a..b91f92e4e5f22d659d89c35d8accc6ef03191b74 100644 (file)
@@ -343,6 +343,7 @@ static const struct net_device_ops dm9601_netdev_ops = {
        .ndo_start_xmit         = usbnet_start_xmit,
        .ndo_tx_timeout         = usbnet_tx_timeout,
        .ndo_change_mtu         = usbnet_change_mtu,
+       .ndo_get_stats64        = usbnet_get_stats64,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_do_ioctl           = dm9601_ioctl,
        .ndo_set_rx_mode        = dm9601_set_multicast,
index 4ff70b22c6eec0e0516373b02b66c71fae158028..5a43b77a6b9c60ef4f2b667ae0ffaa86aa65d4bd 100644 (file)
@@ -144,6 +144,7 @@ static const struct net_device_ops int51x1_netdev_ops = {
        .ndo_start_xmit         = usbnet_start_xmit,
        .ndo_tx_timeout         = usbnet_tx_timeout,
        .ndo_change_mtu         = usbnet_change_mtu,
+       .ndo_get_stats64        = usbnet_get_stats64,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_rx_mode        = int51x1_set_multicast,
index 5771ff261fa8d0ff6199d975aaca2131d8bce409..5a47e5510ca8243eed8f12cc86a4ec70ac42658e 100644 (file)
@@ -475,6 +475,7 @@ static const struct net_device_ops mcs7830_netdev_ops = {
        .ndo_start_xmit         = usbnet_start_xmit,
        .ndo_tx_timeout         = usbnet_tx_timeout,
        .ndo_change_mtu         = usbnet_change_mtu,
+       .ndo_get_stats64        = usbnet_get_stats64,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_do_ioctl           = mcs7830_ioctl,
        .ndo_set_rx_mode        = mcs7830_set_multicast,
index 629fe64cd74a58fc299f805e1c7cc35b1053b2e2..adbed261cc8aed15138fb6090258988c6c112a85 100644 (file)
@@ -542,6 +542,7 @@ static const struct net_device_ops qmi_wwan_netdev_ops = {
        .ndo_start_xmit         = usbnet_start_xmit,
        .ndo_tx_timeout         = usbnet_tx_timeout,
        .ndo_change_mtu         = usbnet_change_mtu,
+       .ndo_get_stats64        = usbnet_get_stats64,
        .ndo_set_mac_address    = qmi_wwan_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 };
index c5b21138b7eb1723579528532deb1b7ea9c2aa72..e96e2e5673d724ea5e009b686ca32afaf921190f 100644 (file)
@@ -291,6 +291,7 @@ static const struct net_device_ops rndis_netdev_ops = {
        .ndo_stop               = usbnet_stop,
        .ndo_start_xmit         = usbnet_start_xmit,
        .ndo_tx_timeout         = usbnet_tx_timeout,
+       .ndo_get_stats64        = usbnet_get_stats64,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 };
index c8f60b887c22e2b839a0e9ab5d9fe3a6e5a3595a..2110ab3513f0446a9a090a83de66b0044b0791c9 100644 (file)
@@ -199,6 +199,7 @@ static const struct net_device_ops sierra_net_device_ops = {
        .ndo_start_xmit         = usbnet_start_xmit,
        .ndo_tx_timeout         = usbnet_tx_timeout,
        .ndo_change_mtu         = usbnet_change_mtu,
+       .ndo_get_stats64        = usbnet_get_stats64,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 };
index 1ab0ff43c6a2245c74f677a6aae454e0ef841410..1ce01dbd494f3581236a3afcd71e145a5eb6cb52 100644 (file)
@@ -1381,6 +1381,7 @@ static const struct net_device_ops smsc75xx_netdev_ops = {
        .ndo_stop               = usbnet_stop,
        .ndo_start_xmit         = usbnet_start_xmit,
        .ndo_tx_timeout         = usbnet_tx_timeout,
+       .ndo_get_stats64        = usbnet_get_stats64,
        .ndo_change_mtu         = smsc75xx_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
index 4a8bf960cbb9082c18998c64e328f5ecfb980e9f..c2f67cecdf5bfcd4d7b07566c8aaaf7ec14269e2 100644 (file)
@@ -1248,6 +1248,7 @@ static const struct net_device_ops smsc95xx_netdev_ops = {
        .ndo_start_xmit         = usbnet_start_xmit,
        .ndo_tx_timeout         = usbnet_tx_timeout,
        .ndo_change_mtu         = usbnet_change_mtu,
+       .ndo_get_stats64        = usbnet_get_stats64,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_do_ioctl           = smsc95xx_ioctl,
index 950a3a9466bdaf62931cd2781a598af2cf6ad478..317287f4409c840638f2ef30df36754805fb2410 100644 (file)
@@ -308,6 +308,7 @@ static const struct net_device_ops sr9700_netdev_ops = {
        .ndo_start_xmit         = usbnet_start_xmit,
        .ndo_tx_timeout         = usbnet_tx_timeout,
        .ndo_change_mtu         = usbnet_change_mtu,
+       .ndo_get_stats64        = usbnet_get_stats64,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_do_ioctl           = sr9700_ioctl,
        .ndo_set_rx_mode        = sr9700_set_multicast,
index a696b628782ce00cc664681e76069b28d72d796b..9277a0f228dfa6de355c74d2652edcf2fb1d2f4b 100644 (file)
@@ -679,6 +679,7 @@ static const struct net_device_ops sr9800_netdev_ops = {
        .ndo_start_xmit         = usbnet_start_xmit,
        .ndo_tx_timeout         = usbnet_tx_timeout,
        .ndo_change_mtu         = usbnet_change_mtu,
+       .ndo_get_stats64        = usbnet_get_stats64,
        .ndo_set_mac_address    = sr_set_mac_address,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_do_ioctl           = sr_ioctl,
index 13d4ec5f6f34f6bd16e29576a1e5cb0c1dd3dce9..9890656af7358b6b8c8edb2d208627230cbc63ef 100644 (file)
@@ -316,6 +316,7 @@ static void __usbnet_status_stop_force(struct usbnet *dev)
  */
 void usbnet_skb_return (struct usbnet *dev, struct sk_buff *skb)
 {
+       struct pcpu_sw_netstats *stats64 = this_cpu_ptr(dev->stats64);
        int     status;
 
        if (test_bit(EVENT_RX_PAUSED, &dev->flags)) {
@@ -327,8 +328,10 @@ void usbnet_skb_return (struct usbnet *dev, struct sk_buff *skb)
        if (skb->protocol == 0)
                skb->protocol = eth_type_trans (skb, dev->net);
 
-       dev->net->stats.rx_packets++;
-       dev->net->stats.rx_bytes += skb->len;
+       u64_stats_update_begin(&stats64->syncp);
+       stats64->rx_packets++;
+       stats64->rx_bytes += skb->len;
+       u64_stats_update_end(&stats64->syncp);
 
        netif_dbg(dev, rx_status, dev->net, "< rx, len %zu, type 0x%x\n",
                  skb->len + sizeof (struct ethhdr), skb->protocol);
@@ -981,6 +984,37 @@ int usbnet_set_link_ksettings(struct net_device *net,
 }
 EXPORT_SYMBOL_GPL(usbnet_set_link_ksettings);
 
+void usbnet_get_stats64(struct net_device *net, struct rtnl_link_stats64 *stats)
+{
+       struct usbnet *dev = netdev_priv(net);
+       unsigned int start;
+       int cpu;
+
+       netdev_stats_to_stats64(stats, &net->stats);
+
+       for_each_possible_cpu(cpu) {
+               struct pcpu_sw_netstats *stats64;
+               u64 rx_packets, rx_bytes;
+               u64 tx_packets, tx_bytes;
+
+               stats64 = per_cpu_ptr(dev->stats64, cpu);
+
+               do {
+                       start = u64_stats_fetch_begin_irq(&stats64->syncp);
+                       rx_packets = stats64->rx_packets;
+                       rx_bytes = stats64->rx_bytes;
+                       tx_packets = stats64->tx_packets;
+                       tx_bytes = stats64->tx_bytes;
+               } while (u64_stats_fetch_retry_irq(&stats64->syncp, start));
+
+               stats->rx_packets += rx_packets;
+               stats->rx_bytes += rx_bytes;
+               stats->tx_packets += tx_packets;
+               stats->tx_bytes += tx_bytes;
+       }
+}
+EXPORT_SYMBOL_GPL(usbnet_get_stats64);
+
 u32 usbnet_get_link (struct net_device *net)
 {
        struct usbnet *dev = netdev_priv(net);
@@ -1212,8 +1246,12 @@ static void tx_complete (struct urb *urb)
        struct usbnet           *dev = entry->dev;
 
        if (urb->status == 0) {
-               dev->net->stats.tx_packets += entry->packets;
-               dev->net->stats.tx_bytes += entry->length;
+               struct pcpu_sw_netstats *stats64 = this_cpu_ptr(dev->stats64);
+
+               u64_stats_update_begin(&stats64->syncp);
+               stats64->tx_packets += entry->packets;
+               stats64->tx_bytes += entry->length;
+               u64_stats_update_end(&stats64->syncp);
        } else {
                dev->net->stats.tx_errors++;
 
@@ -1570,6 +1608,7 @@ void usbnet_disconnect (struct usb_interface *intf)
        usb_free_urb(dev->interrupt);
        kfree(dev->padding_pkt);
 
+       free_percpu(dev->stats64);
        free_netdev(net);
 }
 EXPORT_SYMBOL_GPL(usbnet_disconnect);
@@ -1581,6 +1620,7 @@ static const struct net_device_ops usbnet_netdev_ops = {
        .ndo_tx_timeout         = usbnet_tx_timeout,
        .ndo_set_rx_mode        = usbnet_set_rx_mode,
        .ndo_change_mtu         = usbnet_change_mtu,
+       .ndo_get_stats64        = usbnet_get_stats64,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 };
@@ -1642,6 +1682,11 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
        dev->intf = udev;
        dev->driver_info = info;
        dev->driver_name = name;
+
+       dev->stats64 = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
+       if (!dev->stats64)
+               goto out0;
+
        dev->msg_enable = netif_msg_init (msg_level, NETIF_MSG_DRV
                                | NETIF_MSG_PROBE | NETIF_MSG_LINK);
        init_waitqueue_head(&dev->wait);
@@ -1781,6 +1826,8 @@ out1:
         */
        cancel_work_sync(&dev->kevent);
        del_timer_sync(&dev->delay);
+       free_percpu(dev->stats64);
+out0:
        free_netdev(net);
 out:
        return status;
index 785334f7a5386e82c32cd6fe41dee6d36b37b969..3b68eaffb48c32e709be0cdb0f12f539a06dbfc5 100644 (file)
@@ -3392,6 +3392,7 @@ static const struct net_device_ops rndis_wlan_netdev_ops = {
        .ndo_stop               = usbnet_stop,
        .ndo_start_xmit         = usbnet_start_xmit,
        .ndo_tx_timeout         = usbnet_tx_timeout,
+       .ndo_get_stats64        = usbnet_get_stats64,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_rx_mode        = rndis_wlan_set_multicast_list,
index e2b56917450f24e9d4a3926fa8b1796829fcba1a..7dffa5624ea62bee992e547c44ed4a86a577b0a7 100644 (file)
@@ -64,6 +64,8 @@ struct usbnet {
        struct usb_anchor       deferred;
        struct tasklet_struct   bh;
 
+       struct pcpu_sw_netstats __percpu *stats64;
+
        struct work_struct      kevent;
        unsigned long           flags;
 #              define EVENT_TX_HALT    0
@@ -278,5 +280,7 @@ extern int usbnet_status_start(struct usbnet *dev, gfp_t mem_flags);
 extern void usbnet_status_stop(struct usbnet *dev);
 
 extern void usbnet_update_max_qlen(struct usbnet *dev);
+extern void usbnet_get_stats64(struct net_device *dev,
+                              struct rtnl_link_stats64 *stats);
 
 #endif /* __LINUX_USB_USBNET_H */