diff options
author | Eric Dumazet <eric.dumazet@gmail.com> | 2010-07-07 17:58:56 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-07-07 17:58:56 -0400 |
commit | 28172739f0a276eb8d6ca917b3974c2edb036da3 (patch) | |
tree | b1dc00cfa20c209992e247c6f73601f609f9ca3b /drivers/net/ixgbe | |
parent | 217d32dc5f299c483ca0d3c8cc6811c72c0339c4 (diff) |
net: fix 64 bit counters on 32 bit arches
There is a small possibility that a reader gets incorrect values on 32
bit arches. SNMP applications could catch incorrect counters when a
32bit high part is changed by another stats consumer/provider.
One way to solve this is to add a rtnl_link_stats64 param to all
ndo_get_stats64() methods, and also add such a parameter to
dev_get_stats().
Rule is that we are not allowed to use dev->stats64 as a temporary
storage for 64bit stats, but a caller provided area (usually on stack)
Old drivers (only providing get_stats() method) need no changes.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ixgbe')
-rw-r--r-- | drivers/net/ixgbe/ixgbe_ethtool.c | 8 |
1 files changed, 5 insertions, 3 deletions
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: |