Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
fork

Configure Feed

Select the types of activity you want to include in your feed.

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: Iyappan Subramanian <isubramanian@apm.com>
Tested-by: Toan Le <toanle@apm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Iyappan Subramanian and committed by
David S. Miller
3bb502f8 1b090a48

+53 -19
+11 -8
drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
··· 219 219 struct xgene_enet_pdata *pdata, 220 220 enum xgene_enet_err_code status) 221 221 { 222 - struct rtnl_link_stats64 *stats = &pdata->stats; 223 - 224 222 switch (status) { 225 223 case INGRESS_CRC: 226 - stats->rx_crc_errors++; 224 + ring->rx_crc_errors++; 225 + ring->rx_dropped++; 227 226 break; 228 227 case INGRESS_CHECKSUM: 229 228 case INGRESS_CHECKSUM_COMPUTE: 230 - stats->rx_errors++; 229 + ring->rx_errors++; 230 + ring->rx_dropped++; 231 231 break; 232 232 case INGRESS_TRUNC_FRAME: 233 - stats->rx_frame_errors++; 233 + ring->rx_frame_errors++; 234 + ring->rx_dropped++; 234 235 break; 235 236 case INGRESS_PKT_LEN: 236 - stats->rx_length_errors++; 237 + ring->rx_length_errors++; 238 + ring->rx_dropped++; 237 239 break; 238 240 case INGRESS_PKT_UNDER: 239 - stats->rx_frame_errors++; 241 + ring->rx_frame_errors++; 242 + ring->rx_dropped++; 240 243 break; 241 244 case INGRESS_FIFO_OVERRUN: 242 - stats->rx_fifo_errors++; 245 + ring->rx_fifo_errors++; 243 246 break; 244 247 default: 245 248 break;
+2
drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
··· 201 201 #define USERINFO_LEN 32 202 202 #define FPQNUM_POS 32 203 203 #define FPQNUM_LEN 12 204 + #define ELERR_POS 46 205 + #define ELERR_LEN 2 204 206 #define NV_POS 50 205 207 #define NV_LEN 1 206 208 #define LL_POS 51
+30 -11
drivers/net/ethernet/apm/xgene/xgene_enet_main.c
··· 443 443 444 444 skb_tx_timestamp(skb); 445 445 446 - pdata->stats.tx_packets++; 447 - pdata->stats.tx_bytes += skb->len; 446 + tx_ring->tx_packets++; 447 + tx_ring->tx_bytes += skb->len; 448 448 449 449 pdata->ring_ops->wr_cmd(tx_ring, count); 450 450 return NETDEV_TX_OK; ··· 483 483 skb = buf_pool->rx_skb[skb_index]; 484 484 485 485 /* checking for error */ 486 - status = GET_VAL(LERR, le64_to_cpu(raw_desc->m0)); 486 + status = (GET_VAL(ELERR, le64_to_cpu(raw_desc->m0)) << LERR_LEN) || 487 + GET_VAL(LERR, le64_to_cpu(raw_desc->m0)); 487 488 if (unlikely(status > 2)) { 488 489 dev_kfree_skb_any(skb); 489 490 xgene_enet_parse_error(rx_ring, netdev_priv(rx_ring->ndev), 490 491 status); 491 - pdata->stats.rx_dropped++; 492 492 ret = -EIO; 493 493 goto out; 494 494 } ··· 506 506 xgene_enet_skip_csum(skb); 507 507 } 508 508 509 - pdata->stats.rx_packets++; 510 - pdata->stats.rx_bytes += datalen; 509 + rx_ring->rx_packets++; 510 + rx_ring->rx_bytes += datalen; 511 511 napi_gro_receive(&rx_ring->napi, skb); 512 512 out: 513 513 if (--rx_ring->nbufpool == 0) { ··· 1114 1114 { 1115 1115 struct xgene_enet_pdata *pdata = netdev_priv(ndev); 1116 1116 struct rtnl_link_stats64 *stats = &pdata->stats; 1117 + struct xgene_enet_desc_ring *ring; 1118 + int i; 1117 1119 1118 - stats->rx_errors += stats->rx_length_errors + 1119 - stats->rx_crc_errors + 1120 - stats->rx_frame_errors + 1121 - stats->rx_fifo_errors; 1122 - memcpy(storage, &pdata->stats, sizeof(struct rtnl_link_stats64)); 1120 + memset(stats, 0, sizeof(struct rtnl_link_stats64)); 1121 + for (i = 0; i < pdata->txq_cnt; i++) { 1122 + ring = pdata->tx_ring[i]; 1123 + if (ring) { 1124 + stats->tx_packets += ring->tx_packets; 1125 + stats->tx_bytes += ring->tx_bytes; 1126 + } 1127 + } 1128 + 1129 + for (i = 0; i < pdata->rxq_cnt; i++) { 1130 + ring = pdata->rx_ring[i]; 1131 + if (ring) { 1132 + stats->rx_packets += ring->rx_packets; 1133 + stats->rx_bytes += ring->rx_bytes; 1134 + stats->rx_errors += ring->rx_length_errors + 1135 + ring->rx_crc_errors + 1136 + ring->rx_frame_errors + 1137 + ring->rx_fifo_errors; 1138 + stats->rx_dropped += ring->rx_dropped; 1139 + } 1140 + } 1141 + memcpy(storage, stats, sizeof(struct rtnl_link_stats64)); 1123 1142 1124 1143 return storage; 1125 1144 }
+10
drivers/net/ethernet/apm/xgene/xgene_enet_main.h
··· 121 121 struct xgene_enet_raw_desc16 *raw_desc16; 122 122 }; 123 123 __le64 *exp_bufs; 124 + u64 tx_packets; 125 + u64 tx_bytes; 126 + u64 rx_packets; 127 + u64 rx_bytes; 128 + u64 rx_dropped; 129 + u64 rx_errors; 130 + u64 rx_length_errors; 131 + u64 rx_crc_errors; 132 + u64 rx_frame_errors; 133 + u64 rx_fifo_errors; 124 134 }; 125 135 126 136 struct xgene_mac_ops {