Skip to content

Commit 10377ba

Browse files
kiki gooddavem330
authored andcommitted
net: systemport: Support 64bit statistics
When using Broadcom Systemport device in 32bit Platform, ifconfig can only report up to 4G tx,rx status, which will be wrapped to 0 when the number of incoming or outgoing packets exceeds 4G, only taking around 2 hours in busy network environment (such as streaming). Therefore, it makes hard for network diagnostic tool to get reliable statistical result, so the patch is used to add 64bit support for Broadcom Systemport device in 32bit Platform. This patch provides 64bit statistics capability on both ethtool and ifconfig. Signed-off-by: Jianming.qiao <kiki-good@hotmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 2470f3a commit 10377ba

File tree

2 files changed

+82
-17
lines changed

2 files changed

+82
-17
lines changed

drivers/net/ethernet/broadcom/bcmsysport.c

Lines changed: 61 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -201,10 +201,10 @@ static int bcm_sysport_set_features(struct net_device *dev,
201201
*/
202202
static const struct bcm_sysport_stats bcm_sysport_gstrings_stats[] = {
203203
/* general stats */
204-
STAT_NETDEV(rx_packets),
205-
STAT_NETDEV(tx_packets),
206-
STAT_NETDEV(rx_bytes),
207-
STAT_NETDEV(tx_bytes),
204+
STAT_NETDEV64(rx_packets),
205+
STAT_NETDEV64(tx_packets),
206+
STAT_NETDEV64(rx_bytes),
207+
STAT_NETDEV64(tx_bytes),
208208
STAT_NETDEV(rx_errors),
209209
STAT_NETDEV(tx_errors),
210210
STAT_NETDEV(rx_dropped),
@@ -316,6 +316,7 @@ static inline bool bcm_sysport_lite_stat_valid(enum bcm_sysport_stat_type type)
316316
{
317317
switch (type) {
318318
case BCM_SYSPORT_STAT_NETDEV:
319+
case BCM_SYSPORT_STAT_NETDEV64:
319320
case BCM_SYSPORT_STAT_RXCHK:
320321
case BCM_SYSPORT_STAT_RBUF:
321322
case BCM_SYSPORT_STAT_SOFT:
@@ -398,6 +399,7 @@ static void bcm_sysport_update_mib_counters(struct bcm_sysport_priv *priv)
398399
s = &bcm_sysport_gstrings_stats[i];
399400
switch (s->type) {
400401
case BCM_SYSPORT_STAT_NETDEV:
402+
case BCM_SYSPORT_STAT_NETDEV64:
401403
case BCM_SYSPORT_STAT_SOFT:
402404
continue;
403405
case BCM_SYSPORT_STAT_MIB_RX:
@@ -434,7 +436,10 @@ static void bcm_sysport_get_stats(struct net_device *dev,
434436
struct ethtool_stats *stats, u64 *data)
435437
{
436438
struct bcm_sysport_priv *priv = netdev_priv(dev);
439+
struct bcm_sysport_stats64 *stats64 = &priv->stats64;
440+
struct u64_stats_sync *syncp = &priv->syncp;
437441
struct bcm_sysport_tx_ring *ring;
442+
unsigned int start;
438443
int i, j;
439444

440445
if (netif_running(dev))
@@ -447,10 +452,20 @@ static void bcm_sysport_get_stats(struct net_device *dev,
447452
s = &bcm_sysport_gstrings_stats[i];
448453
if (s->type == BCM_SYSPORT_STAT_NETDEV)
449454
p = (char *)&dev->stats;
455+
else if (s->type == BCM_SYSPORT_STAT_NETDEV64)
456+
p = (char *)stats64;
450457
else
451458
p = (char *)priv;
459+
452460
p += s->stat_offset;
453-
data[j] = *(unsigned long *)p;
461+
462+
if (s->stat_sizeof == sizeof(u64))
463+
do {
464+
start = u64_stats_fetch_begin_irq(syncp);
465+
data[i] = *(u64 *)p;
466+
} while (u64_stats_fetch_retry_irq(syncp, start));
467+
else
468+
data[i] = *(u32 *)p;
454469
j++;
455470
}
456471

@@ -662,6 +677,7 @@ static int bcm_sysport_alloc_rx_bufs(struct bcm_sysport_priv *priv)
662677
static unsigned int bcm_sysport_desc_rx(struct bcm_sysport_priv *priv,
663678
unsigned int budget)
664679
{
680+
struct bcm_sysport_stats64 *stats64 = &priv->stats64;
665681
struct net_device *ndev = priv->netdev;
666682
unsigned int processed = 0, to_process;
667683
struct bcm_sysport_cb *cb;
@@ -765,6 +781,10 @@ static unsigned int bcm_sysport_desc_rx(struct bcm_sysport_priv *priv,
765781
skb->protocol = eth_type_trans(skb, ndev);
766782
ndev->stats.rx_packets++;
767783
ndev->stats.rx_bytes += len;
784+
u64_stats_update_begin(&priv->syncp);
785+
stats64->rx_packets++;
786+
stats64->rx_bytes += len;
787+
u64_stats_update_end(&priv->syncp);
768788

769789
napi_gro_receive(&priv->napi, skb);
770790
next:
@@ -787,17 +807,15 @@ static void bcm_sysport_tx_reclaim_one(struct bcm_sysport_tx_ring *ring,
787807
struct device *kdev = &priv->pdev->dev;
788808

789809
if (cb->skb) {
790-
ring->bytes += cb->skb->len;
791810
*bytes_compl += cb->skb->len;
792811
dma_unmap_single(kdev, dma_unmap_addr(cb, dma_addr),
793812
dma_unmap_len(cb, dma_len),
794813
DMA_TO_DEVICE);
795-
ring->packets++;
796814
(*pkts_compl)++;
797815
bcm_sysport_free_cb(cb);
798816
/* SKB fragment */
799817
} else if (dma_unmap_addr(cb, dma_addr)) {
800-
ring->bytes += dma_unmap_len(cb, dma_len);
818+
*bytes_compl += dma_unmap_len(cb, dma_len);
801819
dma_unmap_page(kdev, dma_unmap_addr(cb, dma_addr),
802820
dma_unmap_len(cb, dma_len), DMA_TO_DEVICE);
803821
dma_unmap_addr_set(cb, dma_addr, 0);
@@ -808,9 +826,9 @@ static void bcm_sysport_tx_reclaim_one(struct bcm_sysport_tx_ring *ring,
808826
static unsigned int __bcm_sysport_tx_reclaim(struct bcm_sysport_priv *priv,
809827
struct bcm_sysport_tx_ring *ring)
810828
{
811-
struct net_device *ndev = priv->netdev;
812829
unsigned int c_index, last_c_index, last_tx_cn, num_tx_cbs;
813830
unsigned int pkts_compl = 0, bytes_compl = 0;
831+
struct net_device *ndev = priv->netdev;
814832
struct bcm_sysport_cb *cb;
815833
u32 hw_ind;
816834

@@ -849,6 +867,11 @@ static unsigned int __bcm_sysport_tx_reclaim(struct bcm_sysport_priv *priv,
849867
last_c_index &= (num_tx_cbs - 1);
850868
}
851869

870+
u64_stats_update_begin(&priv->syncp);
871+
ring->packets += pkts_compl;
872+
ring->bytes += bytes_compl;
873+
u64_stats_update_end(&priv->syncp);
874+
852875
ring->c_index = c_index;
853876

854877
netif_dbg(priv, tx_done, ndev,
@@ -1671,22 +1694,41 @@ static int bcm_sysport_change_mac(struct net_device *dev, void *p)
16711694
return 0;
16721695
}
16731696

1674-
static struct net_device_stats *bcm_sysport_get_nstats(struct net_device *dev)
1697+
static void bcm_sysport_get_stats64(struct net_device *dev,
1698+
struct rtnl_link_stats64 *stats)
16751699
{
16761700
struct bcm_sysport_priv *priv = netdev_priv(dev);
1677-
unsigned long tx_bytes = 0, tx_packets = 0;
1701+
struct bcm_sysport_stats64 *stats64 = &priv->stats64;
16781702
struct bcm_sysport_tx_ring *ring;
1703+
u64 tx_packets = 0, tx_bytes = 0;
1704+
unsigned int start;
16791705
unsigned int q;
16801706

1707+
netdev_stats_to_stats64(stats, &dev->stats);
1708+
16811709
for (q = 0; q < dev->num_tx_queues; q++) {
16821710
ring = &priv->tx_rings[q];
1683-
tx_bytes += ring->bytes;
1684-
tx_packets += ring->packets;
1711+
do {
1712+
start = u64_stats_fetch_begin_irq(&priv->syncp);
1713+
tx_bytes = ring->bytes;
1714+
tx_packets = ring->packets;
1715+
} while (u64_stats_fetch_retry_irq(&priv->syncp, start));
1716+
1717+
stats->tx_bytes += tx_bytes;
1718+
stats->tx_packets += tx_packets;
16851719
}
16861720

1687-
dev->stats.tx_bytes = tx_bytes;
1688-
dev->stats.tx_packets = tx_packets;
1689-
return &dev->stats;
1721+
/* lockless update tx_bytes and tx_packets */
1722+
u64_stats_update_begin(&priv->syncp);
1723+
stats64->tx_bytes = stats->tx_bytes;
1724+
stats64->tx_packets = stats->tx_packets;
1725+
u64_stats_update_end(&priv->syncp);
1726+
1727+
do {
1728+
start = u64_stats_fetch_begin_irq(&priv->syncp);
1729+
stats->rx_packets = stats64->rx_packets;
1730+
stats->rx_bytes = stats64->rx_bytes;
1731+
} while (u64_stats_fetch_retry_irq(&priv->syncp, start));
16901732
}
16911733

16921734
static void bcm_sysport_netif_start(struct net_device *dev)
@@ -1950,7 +1992,7 @@ static const struct net_device_ops bcm_sysport_netdev_ops = {
19501992
#ifdef CONFIG_NET_POLL_CONTROLLER
19511993
.ndo_poll_controller = bcm_sysport_poll_controller,
19521994
#endif
1953-
.ndo_get_stats = bcm_sysport_get_nstats,
1995+
.ndo_get_stats64 = bcm_sysport_get_stats64,
19541996
};
19551997

19561998
#define REV_FMT "v%2x.%02x"
@@ -2098,6 +2140,8 @@ static int bcm_sysport_probe(struct platform_device *pdev)
20982140
/* libphy will adjust the link state accordingly */
20992141
netif_carrier_off(dev);
21002142

2143+
u64_stats_init(&priv->syncp);
2144+
21012145
ret = register_netdev(dev);
21022146
if (ret) {
21032147
dev_err(&pdev->dev, "failed to register net_device\n");

drivers/net/ethernet/broadcom/bcmsysport.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,7 @@ struct bcm_sysport_mib {
603603
/* HW maintains a large list of counters */
604604
enum bcm_sysport_stat_type {
605605
BCM_SYSPORT_STAT_NETDEV = -1,
606+
BCM_SYSPORT_STAT_NETDEV64,
606607
BCM_SYSPORT_STAT_MIB_RX,
607608
BCM_SYSPORT_STAT_MIB_TX,
608609
BCM_SYSPORT_STAT_RUNT,
@@ -619,6 +620,13 @@ enum bcm_sysport_stat_type {
619620
.type = BCM_SYSPORT_STAT_NETDEV, \
620621
}
621622

623+
#define STAT_NETDEV64(m) { \
624+
.stat_string = __stringify(m), \
625+
.stat_sizeof = sizeof(((struct bcm_sysport_stats64 *)0)->m), \
626+
.stat_offset = offsetof(struct bcm_sysport_stats64, m), \
627+
.type = BCM_SYSPORT_STAT_NETDEV64, \
628+
}
629+
622630
#define STAT_MIB(str, m, _type) { \
623631
.stat_string = str, \
624632
.stat_sizeof = sizeof(((struct bcm_sysport_priv *)0)->m), \
@@ -659,6 +667,14 @@ struct bcm_sysport_stats {
659667
u16 reg_offset;
660668
};
661669

670+
struct bcm_sysport_stats64 {
671+
/* 64bit stats on 32bit/64bit Machine */
672+
u64 rx_packets;
673+
u64 rx_bytes;
674+
u64 tx_packets;
675+
u64 tx_bytes;
676+
};
677+
662678
/* Software house keeping helper structure */
663679
struct bcm_sysport_cb {
664680
struct sk_buff *skb; /* SKB for RX packets */
@@ -743,5 +759,10 @@ struct bcm_sysport_priv {
743759

744760
/* Ethtool */
745761
u32 msg_enable;
762+
763+
struct bcm_sysport_stats64 stats64;
764+
765+
/* For atomic update generic 64bit value on 32bit Machine */
766+
struct u64_stats_sync syncp;
746767
};
747768
#endif /* __BCM_SYSPORT_H */

0 commit comments

Comments
 (0)