Commit c8b5d129 authored by Greg Ungerer's avatar Greg Ungerer Committed by David S. Miller

net: usbnet: support 64bit stats

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: default avatarGreg Ungerer <gerg@linux-m68k.org>
Acked-by: default avatarBjørn Mork <bjorn@mork.no>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 822f9bb1
...@@ -206,6 +206,7 @@ static const struct net_device_ops ax88172_netdev_ops = { ...@@ -206,6 +206,7 @@ static const struct net_device_ops ax88172_netdev_ops = {
.ndo_start_xmit = usbnet_start_xmit, .ndo_start_xmit = usbnet_start_xmit,
.ndo_tx_timeout = usbnet_tx_timeout, .ndo_tx_timeout = usbnet_tx_timeout,
.ndo_change_mtu = usbnet_change_mtu, .ndo_change_mtu = usbnet_change_mtu,
.ndo_get_stats64 = usbnet_get_stats64,
.ndo_set_mac_address = eth_mac_addr, .ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr, .ndo_validate_addr = eth_validate_addr,
.ndo_do_ioctl = asix_ioctl, .ndo_do_ioctl = asix_ioctl,
...@@ -591,6 +592,7 @@ static const struct net_device_ops ax88772_netdev_ops = { ...@@ -591,6 +592,7 @@ static const struct net_device_ops ax88772_netdev_ops = {
.ndo_start_xmit = usbnet_start_xmit, .ndo_start_xmit = usbnet_start_xmit,
.ndo_tx_timeout = usbnet_tx_timeout, .ndo_tx_timeout = usbnet_tx_timeout,
.ndo_change_mtu = usbnet_change_mtu, .ndo_change_mtu = usbnet_change_mtu,
.ndo_get_stats64 = usbnet_get_stats64,
.ndo_set_mac_address = asix_set_mac_address, .ndo_set_mac_address = asix_set_mac_address,
.ndo_validate_addr = eth_validate_addr, .ndo_validate_addr = eth_validate_addr,
.ndo_do_ioctl = asix_ioctl, .ndo_do_ioctl = asix_ioctl,
...@@ -1044,6 +1046,7 @@ static const struct net_device_ops ax88178_netdev_ops = { ...@@ -1044,6 +1046,7 @@ static const struct net_device_ops ax88178_netdev_ops = {
.ndo_stop = usbnet_stop, .ndo_stop = usbnet_stop,
.ndo_start_xmit = usbnet_start_xmit, .ndo_start_xmit = usbnet_start_xmit,
.ndo_tx_timeout = usbnet_tx_timeout, .ndo_tx_timeout = usbnet_tx_timeout,
.ndo_get_stats64 = usbnet_get_stats64,
.ndo_set_mac_address = asix_set_mac_address, .ndo_set_mac_address = asix_set_mac_address,
.ndo_validate_addr = eth_validate_addr, .ndo_validate_addr = eth_validate_addr,
.ndo_set_rx_mode = asix_set_multicast, .ndo_set_rx_mode = asix_set_multicast,
......
...@@ -143,6 +143,7 @@ static const struct net_device_ops ax88172a_netdev_ops = { ...@@ -143,6 +143,7 @@ static const struct net_device_ops ax88172a_netdev_ops = {
.ndo_start_xmit = usbnet_start_xmit, .ndo_start_xmit = usbnet_start_xmit,
.ndo_tx_timeout = usbnet_tx_timeout, .ndo_tx_timeout = usbnet_tx_timeout,
.ndo_change_mtu = usbnet_change_mtu, .ndo_change_mtu = usbnet_change_mtu,
.ndo_get_stats64 = usbnet_get_stats64,
.ndo_set_mac_address = asix_set_mac_address, .ndo_set_mac_address = asix_set_mac_address,
.ndo_validate_addr = eth_validate_addr, .ndo_validate_addr = eth_validate_addr,
.ndo_do_ioctl = ax88172a_ioctl, .ndo_do_ioctl = ax88172a_ioctl,
......
...@@ -959,6 +959,7 @@ static const struct net_device_ops ax88179_netdev_ops = { ...@@ -959,6 +959,7 @@ static const struct net_device_ops ax88179_netdev_ops = {
.ndo_stop = usbnet_stop, .ndo_stop = usbnet_stop,
.ndo_start_xmit = usbnet_start_xmit, .ndo_start_xmit = usbnet_start_xmit,
.ndo_tx_timeout = usbnet_tx_timeout, .ndo_tx_timeout = usbnet_tx_timeout,
.ndo_get_stats64 = usbnet_get_stats64,
.ndo_change_mtu = ax88179_change_mtu, .ndo_change_mtu = ax88179_change_mtu,
.ndo_set_mac_address = ax88179_set_mac_addr, .ndo_set_mac_address = ax88179_set_mac_addr,
.ndo_validate_addr = eth_validate_addr, .ndo_validate_addr = eth_validate_addr,
......
...@@ -100,6 +100,7 @@ static const struct net_device_ops cdc_mbim_netdev_ops = { ...@@ -100,6 +100,7 @@ static const struct net_device_ops cdc_mbim_netdev_ops = {
.ndo_stop = usbnet_stop, .ndo_stop = usbnet_stop,
.ndo_start_xmit = usbnet_start_xmit, .ndo_start_xmit = usbnet_start_xmit,
.ndo_tx_timeout = usbnet_tx_timeout, .ndo_tx_timeout = usbnet_tx_timeout,
.ndo_get_stats64 = usbnet_get_stats64,
.ndo_change_mtu = cdc_ncm_change_mtu, .ndo_change_mtu = cdc_ncm_change_mtu,
.ndo_set_mac_address = eth_mac_addr, .ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr, .ndo_validate_addr = eth_validate_addr,
......
...@@ -753,6 +753,7 @@ static const struct net_device_ops cdc_ncm_netdev_ops = { ...@@ -753,6 +753,7 @@ static const struct net_device_ops cdc_ncm_netdev_ops = {
.ndo_stop = usbnet_stop, .ndo_stop = usbnet_stop,
.ndo_start_xmit = usbnet_start_xmit, .ndo_start_xmit = usbnet_start_xmit,
.ndo_tx_timeout = usbnet_tx_timeout, .ndo_tx_timeout = usbnet_tx_timeout,
.ndo_get_stats64 = usbnet_get_stats64,
.ndo_change_mtu = cdc_ncm_change_mtu, .ndo_change_mtu = cdc_ncm_change_mtu,
.ndo_set_mac_address = eth_mac_addr, .ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr, .ndo_validate_addr = eth_validate_addr,
......
...@@ -343,6 +343,7 @@ static const struct net_device_ops dm9601_netdev_ops = { ...@@ -343,6 +343,7 @@ static const struct net_device_ops dm9601_netdev_ops = {
.ndo_start_xmit = usbnet_start_xmit, .ndo_start_xmit = usbnet_start_xmit,
.ndo_tx_timeout = usbnet_tx_timeout, .ndo_tx_timeout = usbnet_tx_timeout,
.ndo_change_mtu = usbnet_change_mtu, .ndo_change_mtu = usbnet_change_mtu,
.ndo_get_stats64 = usbnet_get_stats64,
.ndo_validate_addr = eth_validate_addr, .ndo_validate_addr = eth_validate_addr,
.ndo_do_ioctl = dm9601_ioctl, .ndo_do_ioctl = dm9601_ioctl,
.ndo_set_rx_mode = dm9601_set_multicast, .ndo_set_rx_mode = dm9601_set_multicast,
......
...@@ -144,6 +144,7 @@ static const struct net_device_ops int51x1_netdev_ops = { ...@@ -144,6 +144,7 @@ static const struct net_device_ops int51x1_netdev_ops = {
.ndo_start_xmit = usbnet_start_xmit, .ndo_start_xmit = usbnet_start_xmit,
.ndo_tx_timeout = usbnet_tx_timeout, .ndo_tx_timeout = usbnet_tx_timeout,
.ndo_change_mtu = usbnet_change_mtu, .ndo_change_mtu = usbnet_change_mtu,
.ndo_get_stats64 = usbnet_get_stats64,
.ndo_set_mac_address = eth_mac_addr, .ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr, .ndo_validate_addr = eth_validate_addr,
.ndo_set_rx_mode = int51x1_set_multicast, .ndo_set_rx_mode = int51x1_set_multicast,
......
...@@ -475,6 +475,7 @@ static const struct net_device_ops mcs7830_netdev_ops = { ...@@ -475,6 +475,7 @@ static const struct net_device_ops mcs7830_netdev_ops = {
.ndo_start_xmit = usbnet_start_xmit, .ndo_start_xmit = usbnet_start_xmit,
.ndo_tx_timeout = usbnet_tx_timeout, .ndo_tx_timeout = usbnet_tx_timeout,
.ndo_change_mtu = usbnet_change_mtu, .ndo_change_mtu = usbnet_change_mtu,
.ndo_get_stats64 = usbnet_get_stats64,
.ndo_validate_addr = eth_validate_addr, .ndo_validate_addr = eth_validate_addr,
.ndo_do_ioctl = mcs7830_ioctl, .ndo_do_ioctl = mcs7830_ioctl,
.ndo_set_rx_mode = mcs7830_set_multicast, .ndo_set_rx_mode = mcs7830_set_multicast,
......
...@@ -542,6 +542,7 @@ static const struct net_device_ops qmi_wwan_netdev_ops = { ...@@ -542,6 +542,7 @@ static const struct net_device_ops qmi_wwan_netdev_ops = {
.ndo_start_xmit = usbnet_start_xmit, .ndo_start_xmit = usbnet_start_xmit,
.ndo_tx_timeout = usbnet_tx_timeout, .ndo_tx_timeout = usbnet_tx_timeout,
.ndo_change_mtu = usbnet_change_mtu, .ndo_change_mtu = usbnet_change_mtu,
.ndo_get_stats64 = usbnet_get_stats64,
.ndo_set_mac_address = qmi_wwan_mac_addr, .ndo_set_mac_address = qmi_wwan_mac_addr,
.ndo_validate_addr = eth_validate_addr, .ndo_validate_addr = eth_validate_addr,
}; };
......
...@@ -291,6 +291,7 @@ static const struct net_device_ops rndis_netdev_ops = { ...@@ -291,6 +291,7 @@ static const struct net_device_ops rndis_netdev_ops = {
.ndo_stop = usbnet_stop, .ndo_stop = usbnet_stop,
.ndo_start_xmit = usbnet_start_xmit, .ndo_start_xmit = usbnet_start_xmit,
.ndo_tx_timeout = usbnet_tx_timeout, .ndo_tx_timeout = usbnet_tx_timeout,
.ndo_get_stats64 = usbnet_get_stats64,
.ndo_set_mac_address = eth_mac_addr, .ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr, .ndo_validate_addr = eth_validate_addr,
}; };
......
...@@ -199,6 +199,7 @@ static const struct net_device_ops sierra_net_device_ops = { ...@@ -199,6 +199,7 @@ static const struct net_device_ops sierra_net_device_ops = {
.ndo_start_xmit = usbnet_start_xmit, .ndo_start_xmit = usbnet_start_xmit,
.ndo_tx_timeout = usbnet_tx_timeout, .ndo_tx_timeout = usbnet_tx_timeout,
.ndo_change_mtu = usbnet_change_mtu, .ndo_change_mtu = usbnet_change_mtu,
.ndo_get_stats64 = usbnet_get_stats64,
.ndo_set_mac_address = eth_mac_addr, .ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr, .ndo_validate_addr = eth_validate_addr,
}; };
......
...@@ -1381,6 +1381,7 @@ static const struct net_device_ops smsc75xx_netdev_ops = { ...@@ -1381,6 +1381,7 @@ static const struct net_device_ops smsc75xx_netdev_ops = {
.ndo_stop = usbnet_stop, .ndo_stop = usbnet_stop,
.ndo_start_xmit = usbnet_start_xmit, .ndo_start_xmit = usbnet_start_xmit,
.ndo_tx_timeout = usbnet_tx_timeout, .ndo_tx_timeout = usbnet_tx_timeout,
.ndo_get_stats64 = usbnet_get_stats64,
.ndo_change_mtu = smsc75xx_change_mtu, .ndo_change_mtu = smsc75xx_change_mtu,
.ndo_set_mac_address = eth_mac_addr, .ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr, .ndo_validate_addr = eth_validate_addr,
......
...@@ -1248,6 +1248,7 @@ static const struct net_device_ops smsc95xx_netdev_ops = { ...@@ -1248,6 +1248,7 @@ static const struct net_device_ops smsc95xx_netdev_ops = {
.ndo_start_xmit = usbnet_start_xmit, .ndo_start_xmit = usbnet_start_xmit,
.ndo_tx_timeout = usbnet_tx_timeout, .ndo_tx_timeout = usbnet_tx_timeout,
.ndo_change_mtu = usbnet_change_mtu, .ndo_change_mtu = usbnet_change_mtu,
.ndo_get_stats64 = usbnet_get_stats64,
.ndo_set_mac_address = eth_mac_addr, .ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr, .ndo_validate_addr = eth_validate_addr,
.ndo_do_ioctl = smsc95xx_ioctl, .ndo_do_ioctl = smsc95xx_ioctl,
......
...@@ -308,6 +308,7 @@ static const struct net_device_ops sr9700_netdev_ops = { ...@@ -308,6 +308,7 @@ static const struct net_device_ops sr9700_netdev_ops = {
.ndo_start_xmit = usbnet_start_xmit, .ndo_start_xmit = usbnet_start_xmit,
.ndo_tx_timeout = usbnet_tx_timeout, .ndo_tx_timeout = usbnet_tx_timeout,
.ndo_change_mtu = usbnet_change_mtu, .ndo_change_mtu = usbnet_change_mtu,
.ndo_get_stats64 = usbnet_get_stats64,
.ndo_validate_addr = eth_validate_addr, .ndo_validate_addr = eth_validate_addr,
.ndo_do_ioctl = sr9700_ioctl, .ndo_do_ioctl = sr9700_ioctl,
.ndo_set_rx_mode = sr9700_set_multicast, .ndo_set_rx_mode = sr9700_set_multicast,
......
...@@ -679,6 +679,7 @@ static const struct net_device_ops sr9800_netdev_ops = { ...@@ -679,6 +679,7 @@ static const struct net_device_ops sr9800_netdev_ops = {
.ndo_start_xmit = usbnet_start_xmit, .ndo_start_xmit = usbnet_start_xmit,
.ndo_tx_timeout = usbnet_tx_timeout, .ndo_tx_timeout = usbnet_tx_timeout,
.ndo_change_mtu = usbnet_change_mtu, .ndo_change_mtu = usbnet_change_mtu,
.ndo_get_stats64 = usbnet_get_stats64,
.ndo_set_mac_address = sr_set_mac_address, .ndo_set_mac_address = sr_set_mac_address,
.ndo_validate_addr = eth_validate_addr, .ndo_validate_addr = eth_validate_addr,
.ndo_do_ioctl = sr_ioctl, .ndo_do_ioctl = sr_ioctl,
......
...@@ -316,6 +316,7 @@ static void __usbnet_status_stop_force(struct usbnet *dev) ...@@ -316,6 +316,7 @@ static void __usbnet_status_stop_force(struct usbnet *dev)
*/ */
void usbnet_skb_return (struct usbnet *dev, struct sk_buff *skb) void usbnet_skb_return (struct usbnet *dev, struct sk_buff *skb)
{ {
struct pcpu_sw_netstats *stats64 = this_cpu_ptr(dev->stats64);
int status; int status;
if (test_bit(EVENT_RX_PAUSED, &dev->flags)) { if (test_bit(EVENT_RX_PAUSED, &dev->flags)) {
...@@ -327,8 +328,10 @@ void usbnet_skb_return (struct usbnet *dev, struct sk_buff *skb) ...@@ -327,8 +328,10 @@ void usbnet_skb_return (struct usbnet *dev, struct sk_buff *skb)
if (skb->protocol == 0) if (skb->protocol == 0)
skb->protocol = eth_type_trans (skb, dev->net); skb->protocol = eth_type_trans (skb, dev->net);
dev->net->stats.rx_packets++; u64_stats_update_begin(&stats64->syncp);
dev->net->stats.rx_bytes += skb->len; 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", netif_dbg(dev, rx_status, dev->net, "< rx, len %zu, type 0x%x\n",
skb->len + sizeof (struct ethhdr), skb->protocol); skb->len + sizeof (struct ethhdr), skb->protocol);
...@@ -981,6 +984,37 @@ int usbnet_set_link_ksettings(struct net_device *net, ...@@ -981,6 +984,37 @@ int usbnet_set_link_ksettings(struct net_device *net,
} }
EXPORT_SYMBOL_GPL(usbnet_set_link_ksettings); 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) u32 usbnet_get_link (struct net_device *net)
{ {
struct usbnet *dev = netdev_priv(net); struct usbnet *dev = netdev_priv(net);
...@@ -1212,8 +1246,12 @@ static void tx_complete (struct urb *urb) ...@@ -1212,8 +1246,12 @@ static void tx_complete (struct urb *urb)
struct usbnet *dev = entry->dev; struct usbnet *dev = entry->dev;
if (urb->status == 0) { if (urb->status == 0) {
dev->net->stats.tx_packets += entry->packets; struct pcpu_sw_netstats *stats64 = this_cpu_ptr(dev->stats64);
dev->net->stats.tx_bytes += entry->length;
u64_stats_update_begin(&stats64->syncp);
stats64->tx_packets += entry->packets;
stats64->tx_bytes += entry->length;
u64_stats_update_end(&stats64->syncp);
} else { } else {
dev->net->stats.tx_errors++; dev->net->stats.tx_errors++;
...@@ -1570,6 +1608,7 @@ void usbnet_disconnect (struct usb_interface *intf) ...@@ -1570,6 +1608,7 @@ void usbnet_disconnect (struct usb_interface *intf)
usb_free_urb(dev->interrupt); usb_free_urb(dev->interrupt);
kfree(dev->padding_pkt); kfree(dev->padding_pkt);
free_percpu(dev->stats64);
free_netdev(net); free_netdev(net);
} }
EXPORT_SYMBOL_GPL(usbnet_disconnect); EXPORT_SYMBOL_GPL(usbnet_disconnect);
...@@ -1581,6 +1620,7 @@ static const struct net_device_ops usbnet_netdev_ops = { ...@@ -1581,6 +1620,7 @@ static const struct net_device_ops usbnet_netdev_ops = {
.ndo_tx_timeout = usbnet_tx_timeout, .ndo_tx_timeout = usbnet_tx_timeout,
.ndo_set_rx_mode = usbnet_set_rx_mode, .ndo_set_rx_mode = usbnet_set_rx_mode,
.ndo_change_mtu = usbnet_change_mtu, .ndo_change_mtu = usbnet_change_mtu,
.ndo_get_stats64 = usbnet_get_stats64,
.ndo_set_mac_address = eth_mac_addr, .ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr, .ndo_validate_addr = eth_validate_addr,
}; };
...@@ -1642,6 +1682,11 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) ...@@ -1642,6 +1682,11 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
dev->intf = udev; dev->intf = udev;
dev->driver_info = info; dev->driver_info = info;
dev->driver_name = name; 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 dev->msg_enable = netif_msg_init (msg_level, NETIF_MSG_DRV
| NETIF_MSG_PROBE | NETIF_MSG_LINK); | NETIF_MSG_PROBE | NETIF_MSG_LINK);
init_waitqueue_head(&dev->wait); init_waitqueue_head(&dev->wait);
...@@ -1781,6 +1826,8 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) ...@@ -1781,6 +1826,8 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
*/ */
cancel_work_sync(&dev->kevent); cancel_work_sync(&dev->kevent);
del_timer_sync(&dev->delay); del_timer_sync(&dev->delay);
free_percpu(dev->stats64);
out0:
free_netdev(net); free_netdev(net);
out: out:
return status; return status;
......
...@@ -3392,6 +3392,7 @@ static const struct net_device_ops rndis_wlan_netdev_ops = { ...@@ -3392,6 +3392,7 @@ static const struct net_device_ops rndis_wlan_netdev_ops = {
.ndo_stop = usbnet_stop, .ndo_stop = usbnet_stop,
.ndo_start_xmit = usbnet_start_xmit, .ndo_start_xmit = usbnet_start_xmit,
.ndo_tx_timeout = usbnet_tx_timeout, .ndo_tx_timeout = usbnet_tx_timeout,
.ndo_get_stats64 = usbnet_get_stats64,
.ndo_set_mac_address = eth_mac_addr, .ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr, .ndo_validate_addr = eth_validate_addr,
.ndo_set_rx_mode = rndis_wlan_set_multicast_list, .ndo_set_rx_mode = rndis_wlan_set_multicast_list,
......
...@@ -64,6 +64,8 @@ struct usbnet { ...@@ -64,6 +64,8 @@ struct usbnet {
struct usb_anchor deferred; struct usb_anchor deferred;
struct tasklet_struct bh; struct tasklet_struct bh;
struct pcpu_sw_netstats __percpu *stats64;
struct work_struct kevent; struct work_struct kevent;
unsigned long flags; unsigned long flags;
# define EVENT_TX_HALT 0 # define EVENT_TX_HALT 0
...@@ -278,5 +280,7 @@ extern int usbnet_status_start(struct usbnet *dev, gfp_t mem_flags); ...@@ -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_status_stop(struct usbnet *dev);
extern void usbnet_update_max_qlen(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 */ #endif /* __LINUX_USB_USBNET_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment