Skip to content

Commit

Permalink
drivers: net: xgene: fix statistics counters race condition
Browse files Browse the repository at this point in the history
This patch fixes the race condition on updating the statistics
counters by moving the counters to the ring structure.

Signed-off-by: Iyappan Subramanian <isubramanian@apm.com>
Tested-by: Toan Le <toanle@apm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Iyappan Subramanian authored and David S. Miller committed May 14, 2016
1 parent 1b090a4 commit 3bb502f
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 19 deletions.
19 changes: 11 additions & 8 deletions drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
Original file line number Diff line number Diff line change
Expand Up @@ -219,27 +219,30 @@ void xgene_enet_parse_error(struct xgene_enet_desc_ring *ring,
struct xgene_enet_pdata *pdata,
enum xgene_enet_err_code status)
{
struct rtnl_link_stats64 *stats = &pdata->stats;

switch (status) {
case INGRESS_CRC:
stats->rx_crc_errors++;
ring->rx_crc_errors++;
ring->rx_dropped++;
break;
case INGRESS_CHECKSUM:
case INGRESS_CHECKSUM_COMPUTE:
stats->rx_errors++;
ring->rx_errors++;
ring->rx_dropped++;
break;
case INGRESS_TRUNC_FRAME:
stats->rx_frame_errors++;
ring->rx_frame_errors++;
ring->rx_dropped++;
break;
case INGRESS_PKT_LEN:
stats->rx_length_errors++;
ring->rx_length_errors++;
ring->rx_dropped++;
break;
case INGRESS_PKT_UNDER:
stats->rx_frame_errors++;
ring->rx_frame_errors++;
ring->rx_dropped++;
break;
case INGRESS_FIFO_OVERRUN:
stats->rx_fifo_errors++;
ring->rx_fifo_errors++;
break;
default:
break;
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,8 @@ enum xgene_enet_rm {
#define USERINFO_LEN 32
#define FPQNUM_POS 32
#define FPQNUM_LEN 12
#define ELERR_POS 46
#define ELERR_LEN 2
#define NV_POS 50
#define NV_LEN 1
#define LL_POS 51
Expand Down
41 changes: 30 additions & 11 deletions drivers/net/ethernet/apm/xgene/xgene_enet_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -443,8 +443,8 @@ static netdev_tx_t xgene_enet_start_xmit(struct sk_buff *skb,

skb_tx_timestamp(skb);

pdata->stats.tx_packets++;
pdata->stats.tx_bytes += skb->len;
tx_ring->tx_packets++;
tx_ring->tx_bytes += skb->len;

pdata->ring_ops->wr_cmd(tx_ring, count);
return NETDEV_TX_OK;
Expand Down Expand Up @@ -483,12 +483,12 @@ static int xgene_enet_rx_frame(struct xgene_enet_desc_ring *rx_ring,
skb = buf_pool->rx_skb[skb_index];

/* 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)) {
dev_kfree_skb_any(skb);
xgene_enet_parse_error(rx_ring, netdev_priv(rx_ring->ndev),
status);
pdata->stats.rx_dropped++;
ret = -EIO;
goto out;
}
Expand All @@ -506,8 +506,8 @@ static int xgene_enet_rx_frame(struct xgene_enet_desc_ring *rx_ring,
xgene_enet_skip_csum(skb);
}

pdata->stats.rx_packets++;
pdata->stats.rx_bytes += datalen;
rx_ring->rx_packets++;
rx_ring->rx_bytes += datalen;
napi_gro_receive(&rx_ring->napi, skb);
out:
if (--rx_ring->nbufpool == 0) {
Expand Down Expand Up @@ -1114,12 +1114,31 @@ static struct rtnl_link_stats64 *xgene_enet_get_stats64(
{
struct xgene_enet_pdata *pdata = netdev_priv(ndev);
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 +
stats->rx_crc_errors +
stats->rx_frame_errors +
stats->rx_fifo_errors;
memcpy(storage, &pdata->stats, sizeof(struct rtnl_link_stats64));
for (i = 0; i < pdata->rxq_cnt; i++) {
ring = pdata->rx_ring[i];
if (ring) {
stats->rx_packets += ring->rx_packets;
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;
}
Expand Down
10 changes: 10 additions & 0 deletions drivers/net/ethernet/apm/xgene/xgene_enet_main.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,16 @@ struct xgene_enet_desc_ring {
struct xgene_enet_raw_desc16 *raw_desc16;
};
__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 {
Expand Down

0 comments on commit 3bb502f

Please sign in to comment.