Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: mscc: ocelot: report ndo_get_stats64 from the wraparound-resistant ocelot->stats

Rather than reading the stats64 counters directly from the 32-bit
hardware, it's better to rely on the output produced by the periodic
ocelot_port_update_stats().

It would be even better to call ocelot_port_update_stats() right from
ocelot_get_stats64() to make sure we report the current values rather
than the ones from 2 seconds ago. But we need to export
ocelot_port_update_stats() from the switch lib towards the switchdev
driver for that, and future work will largely undo that.

There are more ocelot-based drivers waiting to be introduced, an example
of which is the SPI-controlled VSC7512. In that driver's case, it will
be impossible to call ocelot_port_update_stats() from ndo_get_stats64
context, since the latter is atomic, and reading the stats over SPI is
sleepable. So the compromise taken here, which will also hold going
forward, is to report 64-bit counters to stats64, which are not 100% up
to date.

Fixes: a556c76adc05 ("net: mscc: Add initial Ocelot switch support")
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Vladimir Oltean and committed by
Jakub Kicinski
e780e319 d4c36765

+26 -27
+26 -27
drivers/net/ethernet/mscc/ocelot_net.c
··· 725 725 struct ocelot_port_private *priv = netdev_priv(dev); 726 726 struct ocelot *ocelot = priv->port.ocelot; 727 727 int port = priv->port.index; 728 + u64 *s; 728 729 729 730 spin_lock(&ocelot->stats_lock); 730 731 731 - /* Configure the port to read the stats from */ 732 - ocelot_write(ocelot, SYS_STAT_CFG_STAT_VIEW(port), 733 - SYS_STAT_CFG); 732 + s = &ocelot->stats[port * OCELOT_NUM_STATS]; 734 733 735 734 /* Get Rx stats */ 736 - stats->rx_bytes = ocelot_read(ocelot, SYS_COUNT_RX_OCTETS); 737 - stats->rx_packets = ocelot_read(ocelot, SYS_COUNT_RX_SHORTS) + 738 - ocelot_read(ocelot, SYS_COUNT_RX_FRAGMENTS) + 739 - ocelot_read(ocelot, SYS_COUNT_RX_JABBERS) + 740 - ocelot_read(ocelot, SYS_COUNT_RX_LONGS) + 741 - ocelot_read(ocelot, SYS_COUNT_RX_64) + 742 - ocelot_read(ocelot, SYS_COUNT_RX_65_127) + 743 - ocelot_read(ocelot, SYS_COUNT_RX_128_255) + 744 - ocelot_read(ocelot, SYS_COUNT_RX_256_511) + 745 - ocelot_read(ocelot, SYS_COUNT_RX_512_1023) + 746 - ocelot_read(ocelot, SYS_COUNT_RX_1024_1526) + 747 - ocelot_read(ocelot, SYS_COUNT_RX_1527_MAX); 748 - stats->multicast = ocelot_read(ocelot, SYS_COUNT_RX_MULTICAST); 735 + stats->rx_bytes = s[OCELOT_STAT_RX_OCTETS]; 736 + stats->rx_packets = s[OCELOT_STAT_RX_SHORTS] + 737 + s[OCELOT_STAT_RX_FRAGMENTS] + 738 + s[OCELOT_STAT_RX_JABBERS] + 739 + s[OCELOT_STAT_RX_LONGS] + 740 + s[OCELOT_STAT_RX_64] + 741 + s[OCELOT_STAT_RX_65_127] + 742 + s[OCELOT_STAT_RX_128_255] + 743 + s[OCELOT_STAT_RX_256_511] + 744 + s[OCELOT_STAT_RX_512_1023] + 745 + s[OCELOT_STAT_RX_1024_1526] + 746 + s[OCELOT_STAT_RX_1527_MAX]; 747 + stats->multicast = s[OCELOT_STAT_RX_MULTICAST]; 749 748 stats->rx_dropped = dev->stats.rx_dropped; 750 749 751 750 /* Get Tx stats */ 752 - stats->tx_bytes = ocelot_read(ocelot, SYS_COUNT_TX_OCTETS); 753 - stats->tx_packets = ocelot_read(ocelot, SYS_COUNT_TX_64) + 754 - ocelot_read(ocelot, SYS_COUNT_TX_65_127) + 755 - ocelot_read(ocelot, SYS_COUNT_TX_128_255) + 756 - ocelot_read(ocelot, SYS_COUNT_TX_256_511) + 757 - ocelot_read(ocelot, SYS_COUNT_TX_512_1023) + 758 - ocelot_read(ocelot, SYS_COUNT_TX_1024_1526) + 759 - ocelot_read(ocelot, SYS_COUNT_TX_1527_MAX); 760 - stats->tx_dropped = ocelot_read(ocelot, SYS_COUNT_TX_DROPS) + 761 - ocelot_read(ocelot, SYS_COUNT_TX_AGING); 762 - stats->collisions = ocelot_read(ocelot, SYS_COUNT_TX_COLLISION); 751 + stats->tx_bytes = s[OCELOT_STAT_TX_OCTETS]; 752 + stats->tx_packets = s[OCELOT_STAT_TX_64] + 753 + s[OCELOT_STAT_TX_65_127] + 754 + s[OCELOT_STAT_TX_128_255] + 755 + s[OCELOT_STAT_TX_256_511] + 756 + s[OCELOT_STAT_TX_512_1023] + 757 + s[OCELOT_STAT_TX_1024_1526] + 758 + s[OCELOT_STAT_TX_1527_MAX]; 759 + stats->tx_dropped = s[OCELOT_STAT_TX_DROPS] + 760 + s[OCELOT_STAT_TX_AGED]; 761 + stats->collisions = s[OCELOT_STAT_TX_COLLISION]; 763 762 764 763 spin_unlock(&ocelot->stats_lock); 765 764 }