@@ -201,10 +201,10 @@ static int bcm_sysport_set_features(struct net_device *dev,
201
201
*/
202
202
static const struct bcm_sysport_stats bcm_sysport_gstrings_stats [] = {
203
203
/* 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 ),
208
208
STAT_NETDEV (rx_errors ),
209
209
STAT_NETDEV (tx_errors ),
210
210
STAT_NETDEV (rx_dropped ),
@@ -316,6 +316,7 @@ static inline bool bcm_sysport_lite_stat_valid(enum bcm_sysport_stat_type type)
316
316
{
317
317
switch (type ) {
318
318
case BCM_SYSPORT_STAT_NETDEV :
319
+ case BCM_SYSPORT_STAT_NETDEV64 :
319
320
case BCM_SYSPORT_STAT_RXCHK :
320
321
case BCM_SYSPORT_STAT_RBUF :
321
322
case BCM_SYSPORT_STAT_SOFT :
@@ -398,6 +399,7 @@ static void bcm_sysport_update_mib_counters(struct bcm_sysport_priv *priv)
398
399
s = & bcm_sysport_gstrings_stats [i ];
399
400
switch (s -> type ) {
400
401
case BCM_SYSPORT_STAT_NETDEV :
402
+ case BCM_SYSPORT_STAT_NETDEV64 :
401
403
case BCM_SYSPORT_STAT_SOFT :
402
404
continue ;
403
405
case BCM_SYSPORT_STAT_MIB_RX :
@@ -434,7 +436,10 @@ static void bcm_sysport_get_stats(struct net_device *dev,
434
436
struct ethtool_stats * stats , u64 * data )
435
437
{
436
438
struct bcm_sysport_priv * priv = netdev_priv (dev );
439
+ struct bcm_sysport_stats64 * stats64 = & priv -> stats64 ;
440
+ struct u64_stats_sync * syncp = & priv -> syncp ;
437
441
struct bcm_sysport_tx_ring * ring ;
442
+ unsigned int start ;
438
443
int i , j ;
439
444
440
445
if (netif_running (dev ))
@@ -447,10 +452,20 @@ static void bcm_sysport_get_stats(struct net_device *dev,
447
452
s = & bcm_sysport_gstrings_stats [i ];
448
453
if (s -> type == BCM_SYSPORT_STAT_NETDEV )
449
454
p = (char * )& dev -> stats ;
455
+ else if (s -> type == BCM_SYSPORT_STAT_NETDEV64 )
456
+ p = (char * )stats64 ;
450
457
else
451
458
p = (char * )priv ;
459
+
452
460
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 ;
454
469
j ++ ;
455
470
}
456
471
@@ -662,6 +677,7 @@ static int bcm_sysport_alloc_rx_bufs(struct bcm_sysport_priv *priv)
662
677
static unsigned int bcm_sysport_desc_rx (struct bcm_sysport_priv * priv ,
663
678
unsigned int budget )
664
679
{
680
+ struct bcm_sysport_stats64 * stats64 = & priv -> stats64 ;
665
681
struct net_device * ndev = priv -> netdev ;
666
682
unsigned int processed = 0 , to_process ;
667
683
struct bcm_sysport_cb * cb ;
@@ -765,6 +781,10 @@ static unsigned int bcm_sysport_desc_rx(struct bcm_sysport_priv *priv,
765
781
skb -> protocol = eth_type_trans (skb , ndev );
766
782
ndev -> stats .rx_packets ++ ;
767
783
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 );
768
788
769
789
napi_gro_receive (& priv -> napi , skb );
770
790
next :
@@ -787,17 +807,15 @@ static void bcm_sysport_tx_reclaim_one(struct bcm_sysport_tx_ring *ring,
787
807
struct device * kdev = & priv -> pdev -> dev ;
788
808
789
809
if (cb -> skb ) {
790
- ring -> bytes += cb -> skb -> len ;
791
810
* bytes_compl += cb -> skb -> len ;
792
811
dma_unmap_single (kdev , dma_unmap_addr (cb , dma_addr ),
793
812
dma_unmap_len (cb , dma_len ),
794
813
DMA_TO_DEVICE );
795
- ring -> packets ++ ;
796
814
(* pkts_compl )++ ;
797
815
bcm_sysport_free_cb (cb );
798
816
/* SKB fragment */
799
817
} 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 );
801
819
dma_unmap_page (kdev , dma_unmap_addr (cb , dma_addr ),
802
820
dma_unmap_len (cb , dma_len ), DMA_TO_DEVICE );
803
821
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,
808
826
static unsigned int __bcm_sysport_tx_reclaim (struct bcm_sysport_priv * priv ,
809
827
struct bcm_sysport_tx_ring * ring )
810
828
{
811
- struct net_device * ndev = priv -> netdev ;
812
829
unsigned int c_index , last_c_index , last_tx_cn , num_tx_cbs ;
813
830
unsigned int pkts_compl = 0 , bytes_compl = 0 ;
831
+ struct net_device * ndev = priv -> netdev ;
814
832
struct bcm_sysport_cb * cb ;
815
833
u32 hw_ind ;
816
834
@@ -849,6 +867,11 @@ static unsigned int __bcm_sysport_tx_reclaim(struct bcm_sysport_priv *priv,
849
867
last_c_index &= (num_tx_cbs - 1 );
850
868
}
851
869
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
+
852
875
ring -> c_index = c_index ;
853
876
854
877
netif_dbg (priv , tx_done , ndev ,
@@ -1671,22 +1694,41 @@ static int bcm_sysport_change_mac(struct net_device *dev, void *p)
1671
1694
return 0 ;
1672
1695
}
1673
1696
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 )
1675
1699
{
1676
1700
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 ;
1678
1702
struct bcm_sysport_tx_ring * ring ;
1703
+ u64 tx_packets = 0 , tx_bytes = 0 ;
1704
+ unsigned int start ;
1679
1705
unsigned int q ;
1680
1706
1707
+ netdev_stats_to_stats64 (stats , & dev -> stats );
1708
+
1681
1709
for (q = 0 ; q < dev -> num_tx_queues ; q ++ ) {
1682
1710
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 ;
1685
1719
}
1686
1720
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 ));
1690
1732
}
1691
1733
1692
1734
static void bcm_sysport_netif_start (struct net_device * dev )
@@ -1950,7 +1992,7 @@ static const struct net_device_ops bcm_sysport_netdev_ops = {
1950
1992
#ifdef CONFIG_NET_POLL_CONTROLLER
1951
1993
.ndo_poll_controller = bcm_sysport_poll_controller ,
1952
1994
#endif
1953
- .ndo_get_stats = bcm_sysport_get_nstats ,
1995
+ .ndo_get_stats64 = bcm_sysport_get_stats64 ,
1954
1996
};
1955
1997
1956
1998
#define REV_FMT "v%2x.%02x"
@@ -2098,6 +2140,8 @@ static int bcm_sysport_probe(struct platform_device *pdev)
2098
2140
/* libphy will adjust the link state accordingly */
2099
2141
netif_carrier_off (dev );
2100
2142
2143
+ u64_stats_init (& priv -> syncp );
2144
+
2101
2145
ret = register_netdev (dev );
2102
2146
if (ret ) {
2103
2147
dev_err (& pdev -> dev , "failed to register net_device\n" );
0 commit comments