Skip to content

Commit 8ecb1a2

Browse files
ffainellidavem330
authored andcommitted
net: systemport: Fix 64-bit statistics dependency
There are several problems with commit 10377ba ("net: systemport: Support 64bit statistics", first one got fixed in 7095c97 ("net: systemport: Fix 64-bit stats deadlock"). The second problem is that this specific code updates the stats64.tx_{packets,bytes} from ndo_get_stats64() and that is what we are returning to ethtool -S. If we are not running a tool that involves calling ndo_get_stats64(), then we won't get updated ethtool stats. The solution to this is to update the stats from both call sites, factoring that into a specific function, While at it, don't just check the sizeof() but also the type of the statistics in order to use the 64-bit stats seqlock. Fixes: 10377ba ("net: systemport: Support 64bit statistics") Signed-off-by: Florian Fainelli <f.fainelli@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 129c6cd commit 8ecb1a2

File tree

1 file changed

+32
-20
lines changed

1 file changed

+32
-20
lines changed

drivers/net/ethernet/broadcom/bcmsysport.c

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -432,18 +432,44 @@ static void bcm_sysport_update_mib_counters(struct bcm_sysport_priv *priv)
432432
netif_dbg(priv, hw, priv->netdev, "updated MIB counters\n");
433433
}
434434

435+
static void bcm_sysport_update_tx_stats(struct bcm_sysport_priv *priv,
436+
u64 *tx_bytes, u64 *tx_packets)
437+
{
438+
struct bcm_sysport_tx_ring *ring;
439+
u64 bytes = 0, packets = 0;
440+
unsigned int start;
441+
unsigned int q;
442+
443+
for (q = 0; q < priv->netdev->num_tx_queues; q++) {
444+
ring = &priv->tx_rings[q];
445+
do {
446+
start = u64_stats_fetch_begin_irq(&priv->syncp);
447+
bytes = ring->bytes;
448+
packets = ring->packets;
449+
} while (u64_stats_fetch_retry_irq(&priv->syncp, start));
450+
451+
*tx_bytes += bytes;
452+
*tx_packets += packets;
453+
}
454+
}
455+
435456
static void bcm_sysport_get_stats(struct net_device *dev,
436457
struct ethtool_stats *stats, u64 *data)
437458
{
438459
struct bcm_sysport_priv *priv = netdev_priv(dev);
439460
struct bcm_sysport_stats64 *stats64 = &priv->stats64;
440461
struct u64_stats_sync *syncp = &priv->syncp;
441462
struct bcm_sysport_tx_ring *ring;
463+
u64 tx_bytes = 0, tx_packets = 0;
442464
unsigned int start;
443465
int i, j;
444466

445-
if (netif_running(dev))
467+
if (netif_running(dev)) {
446468
bcm_sysport_update_mib_counters(priv);
469+
bcm_sysport_update_tx_stats(priv, &tx_bytes, &tx_packets);
470+
stats64->tx_bytes = tx_bytes;
471+
stats64->tx_packets = tx_packets;
472+
}
447473

448474
for (i = 0, j = 0; i < BCM_SYSPORT_STATS_LEN; i++) {
449475
const struct bcm_sysport_stats *s;
@@ -461,12 +487,13 @@ static void bcm_sysport_get_stats(struct net_device *dev,
461487
continue;
462488
p += s->stat_offset;
463489

464-
if (s->stat_sizeof == sizeof(u64))
490+
if (s->stat_sizeof == sizeof(u64) &&
491+
s->type == BCM_SYSPORT_STAT_NETDEV64) {
465492
do {
466493
start = u64_stats_fetch_begin_irq(syncp);
467494
data[i] = *(u64 *)p;
468495
} while (u64_stats_fetch_retry_irq(syncp, start));
469-
else
496+
} else
470497
data[i] = *(u32 *)p;
471498
j++;
472499
}
@@ -1716,27 +1743,12 @@ static void bcm_sysport_get_stats64(struct net_device *dev,
17161743
{
17171744
struct bcm_sysport_priv *priv = netdev_priv(dev);
17181745
struct bcm_sysport_stats64 *stats64 = &priv->stats64;
1719-
struct bcm_sysport_tx_ring *ring;
1720-
u64 tx_packets = 0, tx_bytes = 0;
17211746
unsigned int start;
1722-
unsigned int q;
17231747

17241748
netdev_stats_to_stats64(stats, &dev->stats);
17251749

1726-
for (q = 0; q < dev->num_tx_queues; q++) {
1727-
ring = &priv->tx_rings[q];
1728-
do {
1729-
start = u64_stats_fetch_begin_irq(&priv->syncp);
1730-
tx_bytes = ring->bytes;
1731-
tx_packets = ring->packets;
1732-
} while (u64_stats_fetch_retry_irq(&priv->syncp, start));
1733-
1734-
stats->tx_bytes += tx_bytes;
1735-
stats->tx_packets += tx_packets;
1736-
}
1737-
1738-
stats64->tx_bytes = stats->tx_bytes;
1739-
stats64->tx_packets = stats->tx_packets;
1750+
bcm_sysport_update_tx_stats(priv, &stats->tx_bytes,
1751+
&stats->tx_packets);
17401752

17411753
do {
17421754
start = u64_stats_fetch_begin_irq(&priv->syncp);

0 commit comments

Comments
 (0)