Commit 59081825 authored by Brice Goglin's avatar Brice Goglin Committed by David S. Miller

myri10ge: force stats update in ethtool gstats

Force a statistics update when our ethtool gstats routine
is called.  Otherwise, ethtool will continue to read stale
stats until something forces an update by reading /proc/net/dev

This requires putting a lock around the stats update to guard
against 2 threads (one via ethtool, and one via procfs)
updating the stats at once.
Signed-off-by: default avatarBrice Goglin <brice@myri.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a54bfa40
...@@ -361,6 +361,8 @@ static inline void put_be32(__be32 val, __be32 __iomem * p) ...@@ -361,6 +361,8 @@ static inline void put_be32(__be32 val, __be32 __iomem * p)
__raw_writel((__force __u32) val, (__force void __iomem *)p); __raw_writel((__force __u32) val, (__force void __iomem *)p);
} }
static struct net_device_stats *myri10ge_get_stats(struct net_device *dev);
static int static int
myri10ge_send_cmd(struct myri10ge_priv *mgp, u32 cmd, myri10ge_send_cmd(struct myri10ge_priv *mgp, u32 cmd,
struct myri10ge_cmd *data, int atomic) struct myri10ge_cmd *data, int atomic)
...@@ -1803,6 +1805,8 @@ myri10ge_get_ethtool_stats(struct net_device *netdev, ...@@ -1803,6 +1805,8 @@ myri10ge_get_ethtool_stats(struct net_device *netdev,
int slice; int slice;
int i; int i;
/* force stats update */
(void)myri10ge_get_stats(netdev);
for (i = 0; i < MYRI10GE_NET_STATS_LEN; i++) for (i = 0; i < MYRI10GE_NET_STATS_LEN; i++)
data[i] = ((unsigned long *)&mgp->stats)[i]; data[i] = ((unsigned long *)&mgp->stats)[i];
...@@ -2969,6 +2973,7 @@ static struct net_device_stats *myri10ge_get_stats(struct net_device *dev) ...@@ -2969,6 +2973,7 @@ static struct net_device_stats *myri10ge_get_stats(struct net_device *dev)
struct net_device_stats *stats = &mgp->stats; struct net_device_stats *stats = &mgp->stats;
int i; int i;
spin_lock(&mgp->stats_lock);
memset(stats, 0, sizeof(*stats)); memset(stats, 0, sizeof(*stats));
for (i = 0; i < mgp->num_slices; i++) { for (i = 0; i < mgp->num_slices; i++) {
slice_stats = &mgp->ss[i].stats; slice_stats = &mgp->ss[i].stats;
...@@ -2979,6 +2984,7 @@ static struct net_device_stats *myri10ge_get_stats(struct net_device *dev) ...@@ -2979,6 +2984,7 @@ static struct net_device_stats *myri10ge_get_stats(struct net_device *dev)
stats->rx_dropped += slice_stats->rx_dropped; stats->rx_dropped += slice_stats->rx_dropped;
stats->tx_dropped += slice_stats->tx_dropped; stats->tx_dropped += slice_stats->tx_dropped;
} }
spin_unlock(&mgp->stats_lock);
return stats; return stats;
} }
...@@ -3902,6 +3908,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -3902,6 +3908,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
setup_timer(&mgp->watchdog_timer, myri10ge_watchdog_timer, setup_timer(&mgp->watchdog_timer, myri10ge_watchdog_timer,
(unsigned long)mgp); (unsigned long)mgp);
spin_lock_init(&mgp->stats_lock);
SET_ETHTOOL_OPS(netdev, &myri10ge_ethtool_ops); SET_ETHTOOL_OPS(netdev, &myri10ge_ethtool_ops);
INIT_WORK(&mgp->watchdog_work, myri10ge_watchdog); INIT_WORK(&mgp->watchdog_work, myri10ge_watchdog);
status = register_netdev(netdev); status = register_netdev(netdev);
......
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