diff options
-rw-r--r-- | arch/s390/appldata/appldata_net_sum.c | 3 | ||||
-rw-r--r-- | drivers/net/bonding/bond_main.c | 64 | ||||
-rw-r--r-- | drivers/net/ixgbe/ixgbe_ethtool.c | 8 | ||||
-rw-r--r-- | drivers/net/loopback.c | 4 | ||||
-rw-r--r-- | drivers/net/macvlan.c | 6 | ||||
-rw-r--r-- | drivers/net/sfc/efx.c | 3 | ||||
-rw-r--r-- | drivers/net/sfc/ethtool.c | 3 | ||||
-rw-r--r-- | drivers/parisc/led.c | 3 | ||||
-rw-r--r-- | drivers/scsi/fcoe/fcoe.c | 3 | ||||
-rw-r--r-- | drivers/staging/batman-adv/hard-interface.c | 3 | ||||
-rw-r--r-- | drivers/usb/gadget/rndis.c | 3 | ||||
-rw-r--r-- | include/linux/netdevice.h | 12 | ||||
-rw-r--r-- | net/8021q/vlan_dev.c | 6 | ||||
-rw-r--r-- | net/8021q/vlanproc.c | 3 | ||||
-rw-r--r-- | net/bridge/br_device.c | 4 | ||||
-rw-r--r-- | net/core/dev.c | 25 | ||||
-rw-r--r-- | net/core/net-sysfs.c | 4 | ||||
-rw-r--r-- | net/core/rtnetlink.c | 3 |
18 files changed, 89 insertions, 71 deletions
diff --git a/arch/s390/appldata/appldata_net_sum.c b/arch/s390/appldata/appldata_net_sum.c index 9a9586f4103f..f02e89ce4df1 100644 --- a/arch/s390/appldata/appldata_net_sum.c +++ b/arch/s390/appldata/appldata_net_sum.c | |||
@@ -85,7 +85,8 @@ static void appldata_get_net_sum_data(void *data) | |||
85 | 85 | ||
86 | rcu_read_lock(); | 86 | rcu_read_lock(); |
87 | for_each_netdev_rcu(&init_net, dev) { | 87 | for_each_netdev_rcu(&init_net, dev) { |
88 | const struct net_device_stats *stats = dev_get_stats(dev); | 88 | struct rtnl_link_stats64 temp; |
89 | const struct net_device_stats *stats = dev_get_stats(dev, &temp); | ||
89 | 90 | ||
90 | rx_packets += stats->rx_packets; | 91 | rx_packets += stats->rx_packets; |
91 | tx_packets += stats->tx_packets; | 92 | tx_packets += stats->tx_packets; |
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index a95a41b74b4e..9bb9bfa225b6 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c | |||
@@ -3804,51 +3804,49 @@ static int bond_close(struct net_device *bond_dev) | |||
3804 | return 0; | 3804 | return 0; |
3805 | } | 3805 | } |
3806 | 3806 | ||
3807 | static struct rtnl_link_stats64 *bond_get_stats(struct net_device *bond_dev) | 3807 | static struct rtnl_link_stats64 *bond_get_stats(struct net_device *bond_dev, |
3808 | struct rtnl_link_stats64 *stats) | ||
3808 | { | 3809 | { |
3809 | struct bonding *bond = netdev_priv(bond_dev); | 3810 | struct bonding *bond = netdev_priv(bond_dev); |
3810 | struct rtnl_link_stats64 *stats = &bond_dev->stats64; | 3811 | struct rtnl_link_stats64 temp; |
3811 | struct rtnl_link_stats64 local_stats; | ||
3812 | struct slave *slave; | 3812 | struct slave *slave; |
3813 | int i; | 3813 | int i; |
3814 | 3814 | ||
3815 | memset(&local_stats, 0, sizeof(local_stats)); | 3815 | memset(stats, 0, sizeof(*stats)); |
3816 | 3816 | ||
3817 | read_lock_bh(&bond->lock); | 3817 | read_lock_bh(&bond->lock); |
3818 | 3818 | ||
3819 | bond_for_each_slave(bond, slave, i) { | 3819 | bond_for_each_slave(bond, slave, i) { |
3820 | const struct rtnl_link_stats64 *sstats = | 3820 | const struct rtnl_link_stats64 *sstats = |
3821 | dev_get_stats(slave->dev); | 3821 | dev_get_stats(slave->dev, &temp); |
3822 | 3822 | ||
3823 | local_stats.rx_packets += sstats->rx_packets; | 3823 | stats->rx_packets += sstats->rx_packets; |
3824 | local_stats.rx_bytes += sstats->rx_bytes; | 3824 | stats->rx_bytes += sstats->rx_bytes; |
3825 | local_stats.rx_errors += sstats->rx_errors; | 3825 | stats->rx_errors += sstats->rx_errors; |
3826 | local_stats.rx_dropped += sstats->rx_dropped; | 3826 | stats->rx_dropped += sstats->rx_dropped; |
3827 | 3827 | ||
3828 | local_stats.tx_packets += sstats->tx_packets; | 3828 | stats->tx_packets += sstats->tx_packets; |
3829 | local_stats.tx_bytes += sstats->tx_bytes; | 3829 | stats->tx_bytes += sstats->tx_bytes; |
3830 | local_stats.tx_errors += sstats->tx_errors; | 3830 | stats->tx_errors += sstats->tx_errors; |
3831 | local_stats.tx_dropped += sstats->tx_dropped; | 3831 | stats->tx_dropped += sstats->tx_dropped; |
3832 | 3832 | ||
3833 | local_stats.multicast += sstats->multicast; | 3833 | stats->multicast += sstats->multicast; |
3834 | local_stats.collisions += sstats->collisions; | 3834 | stats->collisions += sstats->collisions; |
3835 | 3835 | ||
3836 | local_stats.rx_length_errors += sstats->rx_length_errors; | 3836 | stats->rx_length_errors += sstats->rx_length_errors; |
3837 | local_stats.rx_over_errors += sstats->rx_over_errors; | 3837 | stats->rx_over_errors += sstats->rx_over_errors; |
3838 | local_stats.rx_crc_errors += sstats->rx_crc_errors; | 3838 | stats->rx_crc_errors += sstats->rx_crc_errors; |
3839 | local_stats.rx_frame_errors += sstats->rx_frame_errors; | 3839 | stats->rx_frame_errors += sstats->rx_frame_errors; |
3840 | local_stats.rx_fifo_errors += sstats->rx_fifo_errors; | 3840 | stats->rx_fifo_errors += sstats->rx_fifo_errors; |
3841 | local_stats.rx_missed_errors += sstats->rx_missed_errors; | 3841 | stats->rx_missed_errors += sstats->rx_missed_errors; |
3842 | 3842 | ||
3843 | local_stats.tx_aborted_errors += sstats->tx_aborted_errors; | 3843 | stats->tx_aborted_errors += sstats->tx_aborted_errors; |
3844 | local_stats.tx_carrier_errors += sstats->tx_carrier_errors; | 3844 | stats->tx_carrier_errors += sstats->tx_carrier_errors; |
3845 | local_stats.tx_fifo_errors += sstats->tx_fifo_errors; | 3845 | stats->tx_fifo_errors += sstats->tx_fifo_errors; |
3846 | local_stats.tx_heartbeat_errors += sstats->tx_heartbeat_errors; | 3846 | stats->tx_heartbeat_errors += sstats->tx_heartbeat_errors; |
3847 | local_stats.tx_window_errors += sstats->tx_window_errors; | 3847 | stats->tx_window_errors += sstats->tx_window_errors; |
3848 | } | 3848 | } |
3849 | 3849 | ||
3850 | memcpy(stats, &local_stats, sizeof(struct net_device_stats)); | ||
3851 | |||
3852 | read_unlock_bh(&bond->lock); | 3850 | read_unlock_bh(&bond->lock); |
3853 | 3851 | ||
3854 | return stats; | 3852 | return stats; |
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index b35ef36741ef..da54b38bb480 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c | |||
@@ -55,7 +55,7 @@ struct ixgbe_stats { | |||
55 | offsetof(struct ixgbe_adapter, m) | 55 | offsetof(struct ixgbe_adapter, m) |
56 | #define IXGBE_NETDEV_STAT(m) NETDEV_STATS, \ | 56 | #define IXGBE_NETDEV_STAT(m) NETDEV_STATS, \ |
57 | sizeof(((struct net_device *)0)->m), \ | 57 | sizeof(((struct net_device *)0)->m), \ |
58 | offsetof(struct net_device, m) | 58 | offsetof(struct net_device, m) - offsetof(struct net_device, stats) |
59 | 59 | ||
60 | static struct ixgbe_stats ixgbe_gstrings_stats[] = { | 60 | static struct ixgbe_stats ixgbe_gstrings_stats[] = { |
61 | {"rx_packets", IXGBE_NETDEV_STAT(stats.rx_packets)}, | 61 | {"rx_packets", IXGBE_NETDEV_STAT(stats.rx_packets)}, |
@@ -998,16 +998,18 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev, | |||
998 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | 998 | struct ixgbe_adapter *adapter = netdev_priv(netdev); |
999 | u64 *queue_stat; | 999 | u64 *queue_stat; |
1000 | int stat_count = sizeof(struct ixgbe_queue_stats) / sizeof(u64); | 1000 | int stat_count = sizeof(struct ixgbe_queue_stats) / sizeof(u64); |
1001 | struct rtnl_link_stats64 temp; | ||
1002 | const struct rtnl_link_stats64 *net_stats; | ||
1001 | int j, k; | 1003 | int j, k; |
1002 | int i; | 1004 | int i; |
1003 | char *p = NULL; | 1005 | char *p = NULL; |
1004 | 1006 | ||
1005 | ixgbe_update_stats(adapter); | 1007 | ixgbe_update_stats(adapter); |
1006 | dev_get_stats(netdev); | 1008 | net_stats = dev_get_stats(netdev, &temp); |
1007 | for (i = 0; i < IXGBE_GLOBAL_STATS_LEN; i++) { | 1009 | for (i = 0; i < IXGBE_GLOBAL_STATS_LEN; i++) { |
1008 | switch (ixgbe_gstrings_stats[i].type) { | 1010 | switch (ixgbe_gstrings_stats[i].type) { |
1009 | case NETDEV_STATS: | 1011 | case NETDEV_STATS: |
1010 | p = (char *) netdev + | 1012 | p = (char *) net_stats + |
1011 | ixgbe_gstrings_stats[i].stat_offset; | 1013 | ixgbe_gstrings_stats[i].stat_offset; |
1012 | break; | 1014 | break; |
1013 | case IXGBE_STATS: | 1015 | case IXGBE_STATS: |
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index 4dd0510d7a99..9a0996795321 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c | |||
@@ -98,10 +98,10 @@ static netdev_tx_t loopback_xmit(struct sk_buff *skb, | |||
98 | return NETDEV_TX_OK; | 98 | return NETDEV_TX_OK; |
99 | } | 99 | } |
100 | 100 | ||
101 | static struct rtnl_link_stats64 *loopback_get_stats64(struct net_device *dev) | 101 | static struct rtnl_link_stats64 *loopback_get_stats64(struct net_device *dev, |
102 | struct rtnl_link_stats64 *stats) | ||
102 | { | 103 | { |
103 | const struct pcpu_lstats __percpu *pcpu_lstats; | 104 | const struct pcpu_lstats __percpu *pcpu_lstats; |
104 | struct rtnl_link_stats64 *stats = &dev->stats64; | ||
105 | u64 bytes = 0; | 105 | u64 bytes = 0; |
106 | u64 packets = 0; | 106 | u64 packets = 0; |
107 | u64 drops = 0; | 107 | u64 drops = 0; |
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index e6d626e78515..6112f1498940 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c | |||
@@ -431,12 +431,12 @@ static void macvlan_uninit(struct net_device *dev) | |||
431 | free_percpu(vlan->rx_stats); | 431 | free_percpu(vlan->rx_stats); |
432 | } | 432 | } |
433 | 433 | ||
434 | static struct rtnl_link_stats64 *macvlan_dev_get_stats64(struct net_device *dev) | 434 | static struct rtnl_link_stats64 *macvlan_dev_get_stats64(struct net_device *dev, |
435 | struct rtnl_link_stats64 *stats) | ||
435 | { | 436 | { |
436 | struct rtnl_link_stats64 *stats = &dev->stats64; | ||
437 | struct macvlan_dev *vlan = netdev_priv(dev); | 437 | struct macvlan_dev *vlan = netdev_priv(dev); |
438 | 438 | ||
439 | dev_txq_stats_fold(dev, &dev->stats); | 439 | dev_txq_stats_fold(dev, (struct net_device_stats *)stats); |
440 | 440 | ||
441 | if (vlan->rx_stats) { | 441 | if (vlan->rx_stats) { |
442 | struct macvlan_rx_stats *p, accum = {0}; | 442 | struct macvlan_rx_stats *p, accum = {0}; |
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index 35b3f2922e5c..ba674c5ca29e 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c | |||
@@ -1533,11 +1533,10 @@ static int efx_net_stop(struct net_device *net_dev) | |||
1533 | } | 1533 | } |
1534 | 1534 | ||
1535 | /* Context: process, dev_base_lock or RTNL held, non-blocking. */ | 1535 | /* Context: process, dev_base_lock or RTNL held, non-blocking. */ |
1536 | static struct rtnl_link_stats64 *efx_net_stats(struct net_device *net_dev) | 1536 | static struct rtnl_link_stats64 *efx_net_stats(struct net_device *net_dev, struct rtnl_link_stats64 *stats) |
1537 | { | 1537 | { |
1538 | struct efx_nic *efx = netdev_priv(net_dev); | 1538 | struct efx_nic *efx = netdev_priv(net_dev); |
1539 | struct efx_mac_stats *mac_stats = &efx->mac_stats; | 1539 | struct efx_mac_stats *mac_stats = &efx->mac_stats; |
1540 | struct rtnl_link_stats64 *stats = &net_dev->stats64; | ||
1541 | 1540 | ||
1542 | spin_lock_bh(&efx->stats_lock); | 1541 | spin_lock_bh(&efx->stats_lock); |
1543 | efx->type->update_stats(efx); | 1542 | efx->type->update_stats(efx); |
diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c index 3b8b0a062749..fd19d6ab97a2 100644 --- a/drivers/net/sfc/ethtool.c +++ b/drivers/net/sfc/ethtool.c | |||
@@ -469,12 +469,13 @@ static void efx_ethtool_get_stats(struct net_device *net_dev, | |||
469 | struct efx_mac_stats *mac_stats = &efx->mac_stats; | 469 | struct efx_mac_stats *mac_stats = &efx->mac_stats; |
470 | struct efx_ethtool_stat *stat; | 470 | struct efx_ethtool_stat *stat; |
471 | struct efx_channel *channel; | 471 | struct efx_channel *channel; |
472 | struct rtnl_link_stats64 temp; | ||
472 | int i; | 473 | int i; |
473 | 474 | ||
474 | EFX_BUG_ON_PARANOID(stats->n_stats != EFX_ETHTOOL_NUM_STATS); | 475 | EFX_BUG_ON_PARANOID(stats->n_stats != EFX_ETHTOOL_NUM_STATS); |
475 | 476 | ||
476 | /* Update MAC and NIC statistics */ | 477 | /* Update MAC and NIC statistics */ |
477 | dev_get_stats(net_dev); | 478 | dev_get_stats(net_dev, &temp); |
478 | 479 | ||
479 | /* Fill detailed statistics buffer */ | 480 | /* Fill detailed statistics buffer */ |
480 | for (i = 0; i < EFX_ETHTOOL_NUM_STATS; i++) { | 481 | for (i = 0; i < EFX_ETHTOOL_NUM_STATS; i++) { |
diff --git a/drivers/parisc/led.c b/drivers/parisc/led.c index 188bc8496a26..18dff43b8bd2 100644 --- a/drivers/parisc/led.c +++ b/drivers/parisc/led.c | |||
@@ -355,12 +355,13 @@ static __inline__ int led_get_net_activity(void) | |||
355 | rcu_read_lock(); | 355 | rcu_read_lock(); |
356 | for_each_netdev_rcu(&init_net, dev) { | 356 | for_each_netdev_rcu(&init_net, dev) { |
357 | const struct net_device_stats *stats; | 357 | const struct net_device_stats *stats; |
358 | struct rtnl_link_stats64 temp; | ||
358 | struct in_device *in_dev = __in_dev_get_rcu(dev); | 359 | struct in_device *in_dev = __in_dev_get_rcu(dev); |
359 | if (!in_dev || !in_dev->ifa_list) | 360 | if (!in_dev || !in_dev->ifa_list) |
360 | continue; | 361 | continue; |
361 | if (ipv4_is_loopback(in_dev->ifa_list->ifa_local)) | 362 | if (ipv4_is_loopback(in_dev->ifa_list->ifa_local)) |
362 | continue; | 363 | continue; |
363 | stats = dev_get_stats(dev); | 364 | stats = dev_get_stats(dev, &temp); |
364 | rx_total += stats->rx_packets; | 365 | rx_total += stats->rx_packets; |
365 | tx_total += stats->tx_packets; | 366 | tx_total += stats->tx_packets; |
366 | } | 367 | } |
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 44a07593de56..1a429ed6da9d 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c | |||
@@ -2653,6 +2653,7 @@ static void fcoe_get_lesb(struct fc_lport *lport, | |||
2653 | u32 lfc, vlfc, mdac; | 2653 | u32 lfc, vlfc, mdac; |
2654 | struct fcoe_dev_stats *devst; | 2654 | struct fcoe_dev_stats *devst; |
2655 | struct fcoe_fc_els_lesb *lesb; | 2655 | struct fcoe_fc_els_lesb *lesb; |
2656 | struct rtnl_link_stats64 temp; | ||
2656 | struct net_device *netdev = fcoe_netdev(lport); | 2657 | struct net_device *netdev = fcoe_netdev(lport); |
2657 | 2658 | ||
2658 | lfc = 0; | 2659 | lfc = 0; |
@@ -2669,7 +2670,7 @@ static void fcoe_get_lesb(struct fc_lport *lport, | |||
2669 | lesb->lesb_link_fail = htonl(lfc); | 2670 | lesb->lesb_link_fail = htonl(lfc); |
2670 | lesb->lesb_vlink_fail = htonl(vlfc); | 2671 | lesb->lesb_vlink_fail = htonl(vlfc); |
2671 | lesb->lesb_miss_fka = htonl(mdac); | 2672 | lesb->lesb_miss_fka = htonl(mdac); |
2672 | lesb->lesb_fcs_error = htonl(dev_get_stats(netdev)->rx_crc_errors); | 2673 | lesb->lesb_fcs_error = htonl(dev_get_stats(netdev, &temp)->rx_crc_errors); |
2673 | } | 2674 | } |
2674 | 2675 | ||
2675 | /** | 2676 | /** |
diff --git a/drivers/staging/batman-adv/hard-interface.c b/drivers/staging/batman-adv/hard-interface.c index 5ede9c255094..96c86c873011 100644 --- a/drivers/staging/batman-adv/hard-interface.c +++ b/drivers/staging/batman-adv/hard-interface.c | |||
@@ -440,6 +440,7 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, | |||
440 | struct batman_packet *batman_packet; | 440 | struct batman_packet *batman_packet; |
441 | struct batman_if *batman_if; | 441 | struct batman_if *batman_if; |
442 | struct net_device_stats *stats; | 442 | struct net_device_stats *stats; |
443 | struct rtnl_link_stats64 temp; | ||
443 | int ret; | 444 | int ret; |
444 | 445 | ||
445 | skb = skb_share_check(skb, GFP_ATOMIC); | 446 | skb = skb_share_check(skb, GFP_ATOMIC); |
@@ -468,7 +469,7 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, | |||
468 | if (batman_if->if_status != IF_ACTIVE) | 469 | if (batman_if->if_status != IF_ACTIVE) |
469 | goto err_free; | 470 | goto err_free; |
470 | 471 | ||
471 | stats = (struct net_device_stats *)dev_get_stats(skb->dev); | 472 | stats = (struct net_device_stats *)dev_get_stats(skb->dev, &temp); |
472 | if (stats) { | 473 | if (stats) { |
473 | stats->rx_packets++; | 474 | stats->rx_packets++; |
474 | stats->rx_bytes += skb->len; | 475 | stats->rx_bytes += skb->len; |
diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c index fb69b01c8f3a..020fa5a25fda 100644 --- a/drivers/usb/gadget/rndis.c +++ b/drivers/usb/gadget/rndis.c | |||
@@ -171,6 +171,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
171 | int i, count; | 171 | int i, count; |
172 | rndis_query_cmplt_type *resp; | 172 | rndis_query_cmplt_type *resp; |
173 | struct net_device *net; | 173 | struct net_device *net; |
174 | struct rtnl_link_stats64 temp; | ||
174 | const struct rtnl_link_stats64 *stats; | 175 | const struct rtnl_link_stats64 *stats; |
175 | 176 | ||
176 | if (!r) return -ENOMEM; | 177 | if (!r) return -ENOMEM; |
@@ -194,7 +195,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
194 | resp->InformationBufferOffset = cpu_to_le32 (16); | 195 | resp->InformationBufferOffset = cpu_to_le32 (16); |
195 | 196 | ||
196 | net = rndis_per_dev_params[configNr].dev; | 197 | net = rndis_per_dev_params[configNr].dev; |
197 | stats = dev_get_stats(net); | 198 | stats = dev_get_stats(net, &temp); |
198 | 199 | ||
199 | switch (OID) { | 200 | switch (OID) { |
200 | 201 | ||
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 4d27368674db..60de65316fdb 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
@@ -666,7 +666,8 @@ struct netdev_rx_queue { | |||
666 | * Callback uses when the transmitter has not made any progress | 666 | * Callback uses when the transmitter has not made any progress |
667 | * for dev->watchdog ticks. | 667 | * for dev->watchdog ticks. |
668 | * | 668 | * |
669 | * struct rtnl_link_stats64* (*ndo_get_stats64)(struct net_device *dev); | 669 | * struct rtnl_link_stats64* (*ndo_get_stats64)(struct net_device *dev |
670 | * struct rtnl_link_stats64 *storage); | ||
670 | * struct net_device_stats* (*ndo_get_stats)(struct net_device *dev); | 671 | * struct net_device_stats* (*ndo_get_stats)(struct net_device *dev); |
671 | * Called when a user wants to get the network device usage | 672 | * Called when a user wants to get the network device usage |
672 | * statistics. Drivers must do one of the following: | 673 | * statistics. Drivers must do one of the following: |
@@ -733,7 +734,8 @@ struct net_device_ops { | |||
733 | struct neigh_parms *); | 734 | struct neigh_parms *); |
734 | void (*ndo_tx_timeout) (struct net_device *dev); | 735 | void (*ndo_tx_timeout) (struct net_device *dev); |
735 | 736 | ||
736 | struct rtnl_link_stats64* (*ndo_get_stats64)(struct net_device *dev); | 737 | struct rtnl_link_stats64* (*ndo_get_stats64)(struct net_device *dev, |
738 | struct rtnl_link_stats64 *storage); | ||
737 | struct net_device_stats* (*ndo_get_stats)(struct net_device *dev); | 739 | struct net_device_stats* (*ndo_get_stats)(struct net_device *dev); |
738 | 740 | ||
739 | void (*ndo_vlan_rx_register)(struct net_device *dev, | 741 | void (*ndo_vlan_rx_register)(struct net_device *dev, |
@@ -2139,8 +2141,10 @@ extern void netdev_features_change(struct net_device *dev); | |||
2139 | /* Load a device via the kmod */ | 2141 | /* Load a device via the kmod */ |
2140 | extern void dev_load(struct net *net, const char *name); | 2142 | extern void dev_load(struct net *net, const char *name); |
2141 | extern void dev_mcast_init(void); | 2143 | extern void dev_mcast_init(void); |
2142 | extern const struct rtnl_link_stats64 *dev_get_stats(struct net_device *dev); | 2144 | extern const struct rtnl_link_stats64 *dev_get_stats(struct net_device *dev, |
2143 | extern void dev_txq_stats_fold(const struct net_device *dev, struct net_device_stats *stats); | 2145 | struct rtnl_link_stats64 *storage); |
2146 | extern void dev_txq_stats_fold(const struct net_device *dev, | ||
2147 | struct net_device_stats *stats); | ||
2144 | 2148 | ||
2145 | extern int netdev_max_backlog; | 2149 | extern int netdev_max_backlog; |
2146 | extern int netdev_tstamp_prequeue; | 2150 | extern int netdev_tstamp_prequeue; |
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index c6456cb842fa..7865a4ce5250 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c | |||
@@ -803,11 +803,9 @@ static u32 vlan_ethtool_get_flags(struct net_device *dev) | |||
803 | return dev_ethtool_get_flags(vlan->real_dev); | 803 | return dev_ethtool_get_flags(vlan->real_dev); |
804 | } | 804 | } |
805 | 805 | ||
806 | static struct rtnl_link_stats64 *vlan_dev_get_stats64(struct net_device *dev) | 806 | static struct rtnl_link_stats64 *vlan_dev_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) |
807 | { | 807 | { |
808 | struct rtnl_link_stats64 *stats = &dev->stats64; | 808 | dev_txq_stats_fold(dev, (struct net_device_stats *)stats); |
809 | |||
810 | dev_txq_stats_fold(dev, &dev->stats); | ||
811 | 809 | ||
812 | if (vlan_dev_info(dev)->vlan_rx_stats) { | 810 | if (vlan_dev_info(dev)->vlan_rx_stats) { |
813 | struct vlan_rx_stats *p, accum = {0}; | 811 | struct vlan_rx_stats *p, accum = {0}; |
diff --git a/net/8021q/vlanproc.c b/net/8021q/vlanproc.c index df56f5ce887c..80e280f56686 100644 --- a/net/8021q/vlanproc.c +++ b/net/8021q/vlanproc.c | |||
@@ -278,6 +278,7 @@ static int vlandev_seq_show(struct seq_file *seq, void *offset) | |||
278 | { | 278 | { |
279 | struct net_device *vlandev = (struct net_device *) seq->private; | 279 | struct net_device *vlandev = (struct net_device *) seq->private; |
280 | const struct vlan_dev_info *dev_info = vlan_dev_info(vlandev); | 280 | const struct vlan_dev_info *dev_info = vlan_dev_info(vlandev); |
281 | struct rtnl_link_stats64 temp; | ||
281 | const struct rtnl_link_stats64 *stats; | 282 | const struct rtnl_link_stats64 *stats; |
282 | static const char fmt[] = "%30s %12lu\n"; | 283 | static const char fmt[] = "%30s %12lu\n"; |
283 | static const char fmt64[] = "%30s %12llu\n"; | 284 | static const char fmt64[] = "%30s %12llu\n"; |
@@ -286,7 +287,7 @@ static int vlandev_seq_show(struct seq_file *seq, void *offset) | |||
286 | if (!is_vlan_dev(vlandev)) | 287 | if (!is_vlan_dev(vlandev)) |
287 | return 0; | 288 | return 0; |
288 | 289 | ||
289 | stats = dev_get_stats(vlandev); | 290 | stats = dev_get_stats(vlandev, &temp); |
290 | seq_printf(seq, | 291 | seq_printf(seq, |
291 | "%s VID: %d REORDER_HDR: %i dev->priv_flags: %hx\n", | 292 | "%s VID: %d REORDER_HDR: %i dev->priv_flags: %hx\n", |
292 | vlandev->name, dev_info->vlan_id, | 293 | vlandev->name, dev_info->vlan_id, |
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index edf639e96281..075c435ad22d 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c | |||
@@ -98,10 +98,10 @@ static int br_dev_stop(struct net_device *dev) | |||
98 | return 0; | 98 | return 0; |
99 | } | 99 | } |
100 | 100 | ||
101 | static struct rtnl_link_stats64 *br_get_stats64(struct net_device *dev) | 101 | static struct rtnl_link_stats64 *br_get_stats64(struct net_device *dev, |
102 | struct rtnl_link_stats64 *stats) | ||
102 | { | 103 | { |
103 | struct net_bridge *br = netdev_priv(dev); | 104 | struct net_bridge *br = netdev_priv(dev); |
104 | struct rtnl_link_stats64 *stats = &dev->stats64; | ||
105 | struct br_cpu_netstats tmp, sum = { 0 }; | 105 | struct br_cpu_netstats tmp, sum = { 0 }; |
106 | unsigned int cpu; | 106 | unsigned int cpu; |
107 | 107 | ||
diff --git a/net/core/dev.c b/net/core/dev.c index 93b8929fa21d..92482d7a87a9 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -3703,7 +3703,8 @@ void dev_seq_stop(struct seq_file *seq, void *v) | |||
3703 | 3703 | ||
3704 | static void dev_seq_printf_stats(struct seq_file *seq, struct net_device *dev) | 3704 | static void dev_seq_printf_stats(struct seq_file *seq, struct net_device *dev) |
3705 | { | 3705 | { |
3706 | const struct rtnl_link_stats64 *stats = dev_get_stats(dev); | 3706 | struct rtnl_link_stats64 temp; |
3707 | const struct rtnl_link_stats64 *stats = dev_get_stats(dev, &temp); | ||
3707 | 3708 | ||
3708 | seq_printf(seq, "%6s: %7llu %7llu %4llu %4llu %4llu %5llu %10llu %9llu " | 3709 | seq_printf(seq, "%6s: %7llu %7llu %4llu %4llu %4llu %5llu %10llu %9llu " |
3709 | "%8llu %7llu %4llu %4llu %4llu %5llu %7llu %10llu\n", | 3710 | "%8llu %7llu %4llu %4llu %4llu %5llu %7llu %10llu\n", |
@@ -5281,23 +5282,29 @@ EXPORT_SYMBOL(dev_txq_stats_fold); | |||
5281 | /** | 5282 | /** |
5282 | * dev_get_stats - get network device statistics | 5283 | * dev_get_stats - get network device statistics |
5283 | * @dev: device to get statistics from | 5284 | * @dev: device to get statistics from |
5285 | * @storage: place to store stats | ||
5284 | * | 5286 | * |
5285 | * Get network statistics from device. The device driver may provide | 5287 | * Get network statistics from device. The device driver may provide |
5286 | * its own method by setting dev->netdev_ops->get_stats64 or | 5288 | * its own method by setting dev->netdev_ops->get_stats64 or |
5287 | * dev->netdev_ops->get_stats; otherwise the internal statistics | 5289 | * dev->netdev_ops->get_stats; otherwise the internal statistics |
5288 | * structure is used. | 5290 | * structure is used. |
5289 | */ | 5291 | */ |
5290 | const struct rtnl_link_stats64 *dev_get_stats(struct net_device *dev) | 5292 | const struct rtnl_link_stats64 *dev_get_stats(struct net_device *dev, |
5293 | struct rtnl_link_stats64 *storage) | ||
5291 | { | 5294 | { |
5292 | const struct net_device_ops *ops = dev->netdev_ops; | 5295 | const struct net_device_ops *ops = dev->netdev_ops; |
5293 | 5296 | ||
5294 | if (ops->ndo_get_stats64) | 5297 | if (ops->ndo_get_stats64) { |
5295 | return ops->ndo_get_stats64(dev); | 5298 | memset(storage, 0, sizeof(*storage)); |
5296 | if (ops->ndo_get_stats) | 5299 | return ops->ndo_get_stats64(dev, storage); |
5297 | return (struct rtnl_link_stats64 *)ops->ndo_get_stats(dev); | 5300 | } |
5298 | 5301 | if (ops->ndo_get_stats) { | |
5299 | dev_txq_stats_fold(dev, &dev->stats); | 5302 | memcpy(storage, ops->ndo_get_stats(dev), sizeof(*storage)); |
5300 | return &dev->stats64; | 5303 | return storage; |
5304 | } | ||
5305 | memcpy(storage, &dev->stats, sizeof(*storage)); | ||
5306 | dev_txq_stats_fold(dev, (struct net_device_stats *)storage); | ||
5307 | return storage; | ||
5301 | } | 5308 | } |
5302 | EXPORT_SYMBOL(dev_get_stats); | 5309 | EXPORT_SYMBOL(dev_get_stats); |
5303 | 5310 | ||
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index ea3bb4c3b87d..914f42b0f039 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c | |||
@@ -330,7 +330,9 @@ static ssize_t netstat_show(const struct device *d, | |||
330 | 330 | ||
331 | read_lock(&dev_base_lock); | 331 | read_lock(&dev_base_lock); |
332 | if (dev_isalive(dev)) { | 332 | if (dev_isalive(dev)) { |
333 | const struct rtnl_link_stats64 *stats = dev_get_stats(dev); | 333 | struct rtnl_link_stats64 temp; |
334 | const struct rtnl_link_stats64 *stats = dev_get_stats(dev, &temp); | ||
335 | |||
334 | ret = sprintf(buf, fmt_u64, *(u64 *)(((u8 *) stats) + offset)); | 336 | ret = sprintf(buf, fmt_u64, *(u64 *)(((u8 *) stats) + offset)); |
335 | } | 337 | } |
336 | read_unlock(&dev_base_lock); | 338 | read_unlock(&dev_base_lock); |
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index e645778e9b7e..5e773ea2201d 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -791,6 +791,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, | |||
791 | { | 791 | { |
792 | struct ifinfomsg *ifm; | 792 | struct ifinfomsg *ifm; |
793 | struct nlmsghdr *nlh; | 793 | struct nlmsghdr *nlh; |
794 | struct rtnl_link_stats64 temp; | ||
794 | const struct rtnl_link_stats64 *stats; | 795 | const struct rtnl_link_stats64 *stats; |
795 | struct nlattr *attr; | 796 | struct nlattr *attr; |
796 | 797 | ||
@@ -847,7 +848,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, | |||
847 | if (attr == NULL) | 848 | if (attr == NULL) |
848 | goto nla_put_failure; | 849 | goto nla_put_failure; |
849 | 850 | ||
850 | stats = dev_get_stats(dev); | 851 | stats = dev_get_stats(dev, &temp); |
851 | copy_rtnl_link_stats(nla_data(attr), stats); | 852 | copy_rtnl_link_stats(nla_data(attr), stats); |
852 | 853 | ||
853 | attr = nla_reserve(skb, IFLA_STATS64, | 854 | attr = nla_reserve(skb, IFLA_STATS64, |