Commit 3bb502f8 authored by Iyappan Subramanian's avatar Iyappan Subramanian Committed by David S. Miller

drivers: net: xgene: fix statistics counters race condition

This patch fixes the race condition on updating the statistics
counters by moving the counters to the ring structure.
Signed-off-by: default avatarIyappan Subramanian <isubramanian@apm.com>
Tested-by: default avatarToan Le <toanle@apm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 1b090a48
...@@ -219,27 +219,30 @@ void xgene_enet_parse_error(struct xgene_enet_desc_ring *ring, ...@@ -219,27 +219,30 @@ void xgene_enet_parse_error(struct xgene_enet_desc_ring *ring,
struct xgene_enet_pdata *pdata, struct xgene_enet_pdata *pdata,
enum xgene_enet_err_code status) enum xgene_enet_err_code status)
{ {
struct rtnl_link_stats64 *stats = &pdata->stats;
switch (status) { switch (status) {
case INGRESS_CRC: case INGRESS_CRC:
stats->rx_crc_errors++; ring->rx_crc_errors++;
ring->rx_dropped++;
break; break;
case INGRESS_CHECKSUM: case INGRESS_CHECKSUM:
case INGRESS_CHECKSUM_COMPUTE: case INGRESS_CHECKSUM_COMPUTE:
stats->rx_errors++; ring->rx_errors++;
ring->rx_dropped++;
break; break;
case INGRESS_TRUNC_FRAME: case INGRESS_TRUNC_FRAME:
stats->rx_frame_errors++; ring->rx_frame_errors++;
ring->rx_dropped++;
break; break;
case INGRESS_PKT_LEN: case INGRESS_PKT_LEN:
stats->rx_length_errors++; ring->rx_length_errors++;
ring->rx_dropped++;
break; break;
case INGRESS_PKT_UNDER: case INGRESS_PKT_UNDER:
stats->rx_frame_errors++; ring->rx_frame_errors++;
ring->rx_dropped++;
break; break;
case INGRESS_FIFO_OVERRUN: case INGRESS_FIFO_OVERRUN:
stats->rx_fifo_errors++; ring->rx_fifo_errors++;
break; break;
default: default:
break; break;
......
...@@ -201,6 +201,8 @@ enum xgene_enet_rm { ...@@ -201,6 +201,8 @@ enum xgene_enet_rm {
#define USERINFO_LEN 32 #define USERINFO_LEN 32
#define FPQNUM_POS 32 #define FPQNUM_POS 32
#define FPQNUM_LEN 12 #define FPQNUM_LEN 12
#define ELERR_POS 46
#define ELERR_LEN 2
#define NV_POS 50 #define NV_POS 50
#define NV_LEN 1 #define NV_LEN 1
#define LL_POS 51 #define LL_POS 51
......
...@@ -443,8 +443,8 @@ static netdev_tx_t xgene_enet_start_xmit(struct sk_buff *skb, ...@@ -443,8 +443,8 @@ static netdev_tx_t xgene_enet_start_xmit(struct sk_buff *skb,
skb_tx_timestamp(skb); skb_tx_timestamp(skb);
pdata->stats.tx_packets++; tx_ring->tx_packets++;
pdata->stats.tx_bytes += skb->len; tx_ring->tx_bytes += skb->len;
pdata->ring_ops->wr_cmd(tx_ring, count); pdata->ring_ops->wr_cmd(tx_ring, count);
return NETDEV_TX_OK; return NETDEV_TX_OK;
...@@ -483,12 +483,12 @@ static int xgene_enet_rx_frame(struct xgene_enet_desc_ring *rx_ring, ...@@ -483,12 +483,12 @@ static int xgene_enet_rx_frame(struct xgene_enet_desc_ring *rx_ring,
skb = buf_pool->rx_skb[skb_index]; skb = buf_pool->rx_skb[skb_index];
/* checking for error */ /* checking for error */
status = GET_VAL(LERR, le64_to_cpu(raw_desc->m0)); status = (GET_VAL(ELERR, le64_to_cpu(raw_desc->m0)) << LERR_LEN) ||
GET_VAL(LERR, le64_to_cpu(raw_desc->m0));
if (unlikely(status > 2)) { if (unlikely(status > 2)) {
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
xgene_enet_parse_error(rx_ring, netdev_priv(rx_ring->ndev), xgene_enet_parse_error(rx_ring, netdev_priv(rx_ring->ndev),
status); status);
pdata->stats.rx_dropped++;
ret = -EIO; ret = -EIO;
goto out; goto out;
} }
...@@ -506,8 +506,8 @@ static int xgene_enet_rx_frame(struct xgene_enet_desc_ring *rx_ring, ...@@ -506,8 +506,8 @@ static int xgene_enet_rx_frame(struct xgene_enet_desc_ring *rx_ring,
xgene_enet_skip_csum(skb); xgene_enet_skip_csum(skb);
} }
pdata->stats.rx_packets++; rx_ring->rx_packets++;
pdata->stats.rx_bytes += datalen; rx_ring->rx_bytes += datalen;
napi_gro_receive(&rx_ring->napi, skb); napi_gro_receive(&rx_ring->napi, skb);
out: out:
if (--rx_ring->nbufpool == 0) { if (--rx_ring->nbufpool == 0) {
...@@ -1114,12 +1114,31 @@ static struct rtnl_link_stats64 *xgene_enet_get_stats64( ...@@ -1114,12 +1114,31 @@ static struct rtnl_link_stats64 *xgene_enet_get_stats64(
{ {
struct xgene_enet_pdata *pdata = netdev_priv(ndev); struct xgene_enet_pdata *pdata = netdev_priv(ndev);
struct rtnl_link_stats64 *stats = &pdata->stats; struct rtnl_link_stats64 *stats = &pdata->stats;
struct xgene_enet_desc_ring *ring;
int i;
memset(stats, 0, sizeof(struct rtnl_link_stats64));
for (i = 0; i < pdata->txq_cnt; i++) {
ring = pdata->tx_ring[i];
if (ring) {
stats->tx_packets += ring->tx_packets;
stats->tx_bytes += ring->tx_bytes;
}
}
stats->rx_errors += stats->rx_length_errors + for (i = 0; i < pdata->rxq_cnt; i++) {
stats->rx_crc_errors + ring = pdata->rx_ring[i];
stats->rx_frame_errors + if (ring) {
stats->rx_fifo_errors; stats->rx_packets += ring->rx_packets;
memcpy(storage, &pdata->stats, sizeof(struct rtnl_link_stats64)); stats->rx_bytes += ring->rx_bytes;
stats->rx_errors += ring->rx_length_errors +
ring->rx_crc_errors +
ring->rx_frame_errors +
ring->rx_fifo_errors;
stats->rx_dropped += ring->rx_dropped;
}
}
memcpy(storage, stats, sizeof(struct rtnl_link_stats64));
return storage; return storage;
} }
......
...@@ -121,6 +121,16 @@ struct xgene_enet_desc_ring { ...@@ -121,6 +121,16 @@ struct xgene_enet_desc_ring {
struct xgene_enet_raw_desc16 *raw_desc16; struct xgene_enet_raw_desc16 *raw_desc16;
}; };
__le64 *exp_bufs; __le64 *exp_bufs;
u64 tx_packets;
u64 tx_bytes;
u64 rx_packets;
u64 rx_bytes;
u64 rx_dropped;
u64 rx_errors;
u64 rx_length_errors;
u64 rx_crc_errors;
u64 rx_frame_errors;
u64 rx_fifo_errors;
}; };
struct xgene_mac_ops { struct xgene_mac_ops {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment