Skip to content

Commit 6a8162e

Browse files
Michael Scherbandavem330
authored andcommitted
net: netcp: store network statistics in 64 bits
Previously the network statistics were stored in 32 bit variable which can cause some stats to roll over after several minutes of high traffic. This implements 64 bit storage so larger numbers can be stored. Signed-off-by: Michael Scherban <[email protected]> Signed-off-by: Murali Karicheri <[email protected]> Signed-off-by: Sekhar Nori <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent aa25510 commit 6a8162e

File tree

2 files changed

+74
-12
lines changed

2 files changed

+74
-12
lines changed

drivers/net/ethernet/ti/netcp.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
#include <linux/netdevice.h>
2525
#include <linux/soc/ti/knav_dma.h>
26+
#include <linux/u64_stats_sync.h>
2627

2728
/* Maximum Ethernet frame size supported by Keystone switch */
2829
#define NETCP_MAX_FRAME_SIZE 9504
@@ -68,6 +69,20 @@ struct netcp_addr {
6869
struct list_head node;
6970
};
7071

72+
struct netcp_stats {
73+
struct u64_stats_sync syncp_rx ____cacheline_aligned_in_smp;
74+
u64 rx_packets;
75+
u64 rx_bytes;
76+
u32 rx_errors;
77+
u32 rx_dropped;
78+
79+
struct u64_stats_sync syncp_tx ____cacheline_aligned_in_smp;
80+
u64 tx_packets;
81+
u64 tx_bytes;
82+
u32 tx_errors;
83+
u32 tx_dropped;
84+
};
85+
7186
struct netcp_intf {
7287
struct device *dev;
7388
struct device *ndev_dev;
@@ -88,6 +103,9 @@ struct netcp_intf {
88103
struct napi_struct rx_napi;
89104
struct napi_struct tx_napi;
90105

106+
/* 64-bit netcp stats */
107+
struct netcp_stats stats;
108+
91109
void *rx_channel;
92110
const char *dma_chan_name;
93111
u32 rx_pool_size;

drivers/net/ethernet/ti/netcp_core.c

Lines changed: 56 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -629,6 +629,7 @@ static void netcp_free_rx_desc_chain(struct netcp_intf *netcp,
629629

630630
static void netcp_empty_rx_queue(struct netcp_intf *netcp)
631631
{
632+
struct netcp_stats *rx_stats = &netcp->stats;
632633
struct knav_dma_desc *desc;
633634
unsigned int dma_sz;
634635
dma_addr_t dma;
@@ -642,16 +643,17 @@ static void netcp_empty_rx_queue(struct netcp_intf *netcp)
642643
if (unlikely(!desc)) {
643644
dev_err(netcp->ndev_dev, "%s: failed to unmap Rx desc\n",
644645
__func__);
645-
netcp->ndev->stats.rx_errors++;
646+
rx_stats->rx_errors++;
646647
continue;
647648
}
648649
netcp_free_rx_desc_chain(netcp, desc);
649-
netcp->ndev->stats.rx_dropped++;
650+
rx_stats->rx_dropped++;
650651
}
651652
}
652653

653654
static int netcp_process_one_rx_packet(struct netcp_intf *netcp)
654655
{
656+
struct netcp_stats *rx_stats = &netcp->stats;
655657
unsigned int dma_sz, buf_len, org_buf_len;
656658
struct knav_dma_desc *desc, *ndesc;
657659
unsigned int pkt_sz = 0, accum_sz;
@@ -757,8 +759,8 @@ static int netcp_process_one_rx_packet(struct netcp_intf *netcp)
757759
if (unlikely(ret)) {
758760
dev_err(netcp->ndev_dev, "RX hook %d failed: %d\n",
759761
rx_hook->order, ret);
760-
netcp->ndev->stats.rx_errors++;
761762
/* Free the primary descriptor */
763+
rx_stats->rx_dropped++;
762764
knav_pool_desc_put(netcp->rx_pool, desc);
763765
dev_kfree_skb(skb);
764766
return 0;
@@ -767,8 +769,10 @@ static int netcp_process_one_rx_packet(struct netcp_intf *netcp)
767769
/* Free the primary descriptor */
768770
knav_pool_desc_put(netcp->rx_pool, desc);
769771

770-
netcp->ndev->stats.rx_packets++;
771-
netcp->ndev->stats.rx_bytes += skb->len;
772+
u64_stats_update_begin(&rx_stats->syncp_rx);
773+
rx_stats->rx_packets++;
774+
rx_stats->rx_bytes += skb->len;
775+
u64_stats_update_end(&rx_stats->syncp_rx);
772776

773777
/* push skb up the stack */
774778
skb->protocol = eth_type_trans(skb, netcp->ndev);
@@ -777,7 +781,7 @@ static int netcp_process_one_rx_packet(struct netcp_intf *netcp)
777781

778782
free_desc:
779783
netcp_free_rx_desc_chain(netcp, desc);
780-
netcp->ndev->stats.rx_errors++;
784+
rx_stats->rx_errors++;
781785
return 0;
782786
}
783787

@@ -1008,6 +1012,7 @@ static void netcp_free_tx_desc_chain(struct netcp_intf *netcp,
10081012
static int netcp_process_tx_compl_packets(struct netcp_intf *netcp,
10091013
unsigned int budget)
10101014
{
1015+
struct netcp_stats *tx_stats = &netcp->stats;
10111016
struct knav_dma_desc *desc;
10121017
struct netcp_tx_cb *tx_cb;
10131018
struct sk_buff *skb;
@@ -1022,7 +1027,7 @@ static int netcp_process_tx_compl_packets(struct netcp_intf *netcp,
10221027
desc = knav_pool_desc_unmap(netcp->tx_pool, dma, dma_sz);
10231028
if (unlikely(!desc)) {
10241029
dev_err(netcp->ndev_dev, "failed to unmap Tx desc\n");
1025-
netcp->ndev->stats.tx_errors++;
1030+
tx_stats->tx_errors++;
10261031
continue;
10271032
}
10281033

@@ -1033,7 +1038,7 @@ static int netcp_process_tx_compl_packets(struct netcp_intf *netcp,
10331038
netcp_free_tx_desc_chain(netcp, desc, dma_sz);
10341039
if (!skb) {
10351040
dev_err(netcp->ndev_dev, "No skb in Tx desc\n");
1036-
netcp->ndev->stats.tx_errors++;
1041+
tx_stats->tx_errors++;
10371042
continue;
10381043
}
10391044

@@ -1050,8 +1055,10 @@ static int netcp_process_tx_compl_packets(struct netcp_intf *netcp,
10501055
netif_wake_subqueue(netcp->ndev, subqueue);
10511056
}
10521057

1053-
netcp->ndev->stats.tx_packets++;
1054-
netcp->ndev->stats.tx_bytes += skb->len;
1058+
u64_stats_update_begin(&tx_stats->syncp_tx);
1059+
tx_stats->tx_packets++;
1060+
tx_stats->tx_bytes += skb->len;
1061+
u64_stats_update_end(&tx_stats->syncp_tx);
10551062
dev_kfree_skb(skb);
10561063
pkts++;
10571064
}
@@ -1272,6 +1279,7 @@ static int netcp_tx_submit_skb(struct netcp_intf *netcp,
12721279
static int netcp_ndo_start_xmit(struct sk_buff *skb, struct net_device *ndev)
12731280
{
12741281
struct netcp_intf *netcp = netdev_priv(ndev);
1282+
struct netcp_stats *tx_stats = &netcp->stats;
12751283
int subqueue = skb_get_queue_mapping(skb);
12761284
struct knav_dma_desc *desc;
12771285
int desc_count, ret = 0;
@@ -1287,7 +1295,7 @@ static int netcp_ndo_start_xmit(struct sk_buff *skb, struct net_device *ndev)
12871295
/* If we get here, the skb has already been dropped */
12881296
dev_warn(netcp->ndev_dev, "padding failed (%d), packet dropped\n",
12891297
ret);
1290-
ndev->stats.tx_dropped++;
1298+
tx_stats->tx_dropped++;
12911299
return ret;
12921300
}
12931301
skb->len = NETCP_MIN_PACKET_SIZE;
@@ -1315,7 +1323,7 @@ static int netcp_ndo_start_xmit(struct sk_buff *skb, struct net_device *ndev)
13151323
return NETDEV_TX_OK;
13161324

13171325
drop:
1318-
ndev->stats.tx_dropped++;
1326+
tx_stats->tx_dropped++;
13191327
if (desc)
13201328
netcp_free_tx_desc_chain(netcp, desc, sizeof(*desc));
13211329
dev_kfree_skb(skb);
@@ -1897,12 +1905,46 @@ static int netcp_setup_tc(struct net_device *dev, u32 handle, __be16 proto,
18971905
return 0;
18981906
}
18991907

1908+
static struct rtnl_link_stats64 *
1909+
netcp_get_stats(struct net_device *ndev, struct rtnl_link_stats64 *stats)
1910+
{
1911+
struct netcp_intf *netcp = netdev_priv(ndev);
1912+
struct netcp_stats *p = &netcp->stats;
1913+
u64 rxpackets, rxbytes, txpackets, txbytes;
1914+
unsigned int start;
1915+
1916+
do {
1917+
start = u64_stats_fetch_begin_irq(&p->syncp_rx);
1918+
rxpackets = p->rx_packets;
1919+
rxbytes = p->rx_bytes;
1920+
} while (u64_stats_fetch_retry_irq(&p->syncp_rx, start));
1921+
1922+
do {
1923+
start = u64_stats_fetch_begin_irq(&p->syncp_tx);
1924+
txpackets = p->tx_packets;
1925+
txbytes = p->tx_bytes;
1926+
} while (u64_stats_fetch_retry_irq(&p->syncp_tx, start));
1927+
1928+
stats->rx_packets = rxpackets;
1929+
stats->rx_bytes = rxbytes;
1930+
stats->tx_packets = txpackets;
1931+
stats->tx_bytes = txbytes;
1932+
1933+
/* The following are stored as 32 bit */
1934+
stats->rx_errors = p->rx_errors;
1935+
stats->rx_dropped = p->rx_dropped;
1936+
stats->tx_dropped = p->tx_dropped;
1937+
1938+
return stats;
1939+
}
1940+
19001941
static const struct net_device_ops netcp_netdev_ops = {
19011942
.ndo_open = netcp_ndo_open,
19021943
.ndo_stop = netcp_ndo_stop,
19031944
.ndo_start_xmit = netcp_ndo_start_xmit,
19041945
.ndo_set_rx_mode = netcp_set_rx_mode,
19051946
.ndo_do_ioctl = netcp_ndo_ioctl,
1947+
.ndo_get_stats64 = netcp_get_stats,
19061948
.ndo_set_mac_address = eth_mac_addr,
19071949
.ndo_validate_addr = eth_validate_addr,
19081950
.ndo_vlan_rx_add_vid = netcp_rx_add_vid,
@@ -1949,6 +1991,8 @@ static int netcp_create_interface(struct netcp_device *netcp_device,
19491991
INIT_LIST_HEAD(&netcp->txhook_list_head);
19501992
INIT_LIST_HEAD(&netcp->rxhook_list_head);
19511993
INIT_LIST_HEAD(&netcp->addr_list);
1994+
u64_stats_init(&netcp->stats.syncp_rx);
1995+
u64_stats_init(&netcp->stats.syncp_tx);
19521996
netcp->netcp_device = netcp_device;
19531997
netcp->dev = netcp_device->device;
19541998
netcp->ndev = ndev;

0 commit comments

Comments
 (0)