net: mvneta: move rx_dropped and rx_errors in per-cpu stats
authorLorenzo Bianconi <lorenzo@kernel.org>
Thu, 6 Feb 2020 09:14:39 +0000 (10:14 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 11 Feb 2020 12:35:49 +0000 (04:35 -0800)
[ Upstream commit c35947b8ff8acca33134ee39c31708233765c31a ]

Move rx_dropped and rx_errors counters in mvneta_pcpu_stats in order to
avoid possible races updating statistics

Fixes: 562e2f467e71 ("net: mvneta: Improve the buffer allocation method for SWBM")
Fixes: dc35a10f68d3 ("net: mvneta: bm: add support for hardware buffer management")
Fixes: c5aff18204da ("net: mvneta: driver for Marvell Armada 370/XP network unit")
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/net/ethernet/marvell/mvneta.c

index e498206..6b1a81d 100644 (file)
@@ -388,6 +388,8 @@ struct mvneta_pcpu_stats {
        struct  u64_stats_sync syncp;
        u64     rx_packets;
        u64     rx_bytes;
+       u64     rx_dropped;
+       u64     rx_errors;
        u64     tx_packets;
        u64     tx_bytes;
 };
@@ -706,6 +708,8 @@ mvneta_get_stats64(struct net_device *dev,
                struct mvneta_pcpu_stats *cpu_stats;
                u64 rx_packets;
                u64 rx_bytes;
+               u64 rx_dropped;
+               u64 rx_errors;
                u64 tx_packets;
                u64 tx_bytes;
 
@@ -714,19 +718,20 @@ mvneta_get_stats64(struct net_device *dev,
                        start = u64_stats_fetch_begin_irq(&cpu_stats->syncp);
                        rx_packets = cpu_stats->rx_packets;
                        rx_bytes   = cpu_stats->rx_bytes;
+                       rx_dropped = cpu_stats->rx_dropped;
+                       rx_errors  = cpu_stats->rx_errors;
                        tx_packets = cpu_stats->tx_packets;
                        tx_bytes   = cpu_stats->tx_bytes;
                } while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, start));
 
                stats->rx_packets += rx_packets;
                stats->rx_bytes   += rx_bytes;
+               stats->rx_dropped += rx_dropped;
+               stats->rx_errors  += rx_errors;
                stats->tx_packets += tx_packets;
                stats->tx_bytes   += tx_bytes;
        }
 
-       stats->rx_errors        = dev->stats.rx_errors;
-       stats->rx_dropped       = dev->stats.rx_dropped;
-
        stats->tx_dropped       = dev->stats.tx_dropped;
 }
 
@@ -1703,8 +1708,14 @@ static u32 mvneta_txq_desc_csum(int l3_offs, int l3_proto,
 static void mvneta_rx_error(struct mvneta_port *pp,
                            struct mvneta_rx_desc *rx_desc)
 {
+       struct mvneta_pcpu_stats *stats = this_cpu_ptr(pp->stats);
        u32 status = rx_desc->status;
 
+       /* update per-cpu counter */
+       u64_stats_update_begin(&stats->syncp);
+       stats->rx_errors++;
+       u64_stats_update_end(&stats->syncp);
+
        switch (status & MVNETA_RXD_ERR_CODE_MASK) {
        case MVNETA_RXD_ERR_CRC:
                netdev_err(pp->dev, "bad rx status %08x (crc error), size=%d\n",
@@ -1965,7 +1976,6 @@ static int mvneta_rx_swbm(struct napi_struct *napi,
                        /* Check errors only for FIRST descriptor */
                        if (rx_status & MVNETA_RXD_ERR_SUMMARY) {
                                mvneta_rx_error(pp, rx_desc);
-                               dev->stats.rx_errors++;
                                /* leave the descriptor untouched */
                                continue;
                        }
@@ -1976,11 +1986,17 @@ static int mvneta_rx_swbm(struct napi_struct *napi,
                        skb_size = max(rx_copybreak, rx_header_size);
                        rxq->skb = netdev_alloc_skb_ip_align(dev, skb_size);
                        if (unlikely(!rxq->skb)) {
+                               struct mvneta_pcpu_stats *stats = this_cpu_ptr(pp->stats);
+
                                netdev_err(dev,
                                           "Can't allocate skb on queue %d\n",
                                           rxq->id);
-                               dev->stats.rx_dropped++;
+
                                rxq->skb_alloc_err++;
+
+                               u64_stats_update_begin(&stats->syncp);
+                               stats->rx_dropped++;
+                               u64_stats_update_end(&stats->syncp);
                                continue;
                        }
                        copy_size = min(skb_size, rx_bytes);
@@ -2137,7 +2153,6 @@ err_drop_frame_ret_pool:
                        mvneta_bm_pool_put_bp(pp->bm_priv, bm_pool,
                                              rx_desc->buf_phys_addr);
 err_drop_frame:
-                       dev->stats.rx_errors++;
                        mvneta_rx_error(pp, rx_desc);
                        /* leave the descriptor untouched */
                        continue;