aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorPaul Gortmaker <paul.gortmaker@windriver.com>2013-02-12 15:38:19 -0500
committerPaul Gortmaker <paul.gortmaker@windriver.com>2013-02-12 19:08:27 -0500
commit212079df6d77c0daada96b1d906f4b7749871411 (patch)
tree2c4f2b31b6bdc2a6ea1a22617fd840c19ff90882 /drivers
parent68719786cba169f93b6cb5a53f5dd6ea1bdbb9f3 (diff)
gianfar: convert u64 status counters to atomic64_t
While looking at some asm dump for an unrelated change, Eric noticed in the following stats count increment code: 50b8: 81 3c 01 f8 lwz r9,504(r28) 50bc: 81 5c 01 fc lwz r10,508(r28) 50c0: 31 4a 00 01 addic r10,r10,1 50c4: 7d 29 01 94 addze r9,r9 50c8: 91 3c 01 f8 stw r9,504(r28) 50cc: 91 5c 01 fc stw r10,508(r28) that a 64 bit counter was used on ppc-32 without sync and hence the "ethtool -S" output was racy. Here we convert all the values to use atomic64_t so that the output will always be consistent. Reported-by: Eric Dumazet <edumazet@google.com> Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/ethernet/freescale/gianfar.c26
-rw-r--r--drivers/net/ethernet/freescale/gianfar.h31
-rw-r--r--drivers/net/ethernet/freescale/gianfar_ethtool.c4
3 files changed, 31 insertions, 30 deletions
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index ab32bd0be8ff..c82f67727f43 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -2648,7 +2648,7 @@ static inline void count_errors(unsigned short status, struct net_device *dev)
2648 if (status & RXBD_TRUNCATED) { 2648 if (status & RXBD_TRUNCATED) {
2649 stats->rx_length_errors++; 2649 stats->rx_length_errors++;
2650 2650
2651 estats->rx_trunc++; 2651 atomic64_inc(&estats->rx_trunc);
2652 2652
2653 return; 2653 return;
2654 } 2654 }
@@ -2657,20 +2657,20 @@ static inline void count_errors(unsigned short status, struct net_device *dev)
2657 stats->rx_length_errors++; 2657 stats->rx_length_errors++;
2658 2658
2659 if (status & RXBD_LARGE) 2659 if (status & RXBD_LARGE)
2660 estats->rx_large++; 2660 atomic64_inc(&estats->rx_large);
2661 else 2661 else
2662 estats->rx_short++; 2662 atomic64_inc(&estats->rx_short);
2663 } 2663 }
2664 if (status & RXBD_NONOCTET) { 2664 if (status & RXBD_NONOCTET) {
2665 stats->rx_frame_errors++; 2665 stats->rx_frame_errors++;
2666 estats->rx_nonoctet++; 2666 atomic64_inc(&estats->rx_nonoctet);
2667 } 2667 }
2668 if (status & RXBD_CRCERR) { 2668 if (status & RXBD_CRCERR) {
2669 estats->rx_crcerr++; 2669 atomic64_inc(&estats->rx_crcerr);
2670 stats->rx_crc_errors++; 2670 stats->rx_crc_errors++;
2671 } 2671 }
2672 if (status & RXBD_OVERRUN) { 2672 if (status & RXBD_OVERRUN) {
2673 estats->rx_overrun++; 2673 atomic64_inc(&estats->rx_overrun);
2674 stats->rx_crc_errors++; 2674 stats->rx_crc_errors++;
2675 } 2675 }
2676} 2676}
@@ -2744,7 +2744,7 @@ static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb,
2744 ret = napi_gro_receive(napi, skb); 2744 ret = napi_gro_receive(napi, skb);
2745 2745
2746 if (GRO_DROP == ret) 2746 if (GRO_DROP == ret)
2747 priv->extra_stats.kernel_dropped++; 2747 atomic64_inc(&priv->extra_stats.kernel_dropped);
2748 2748
2749 return 0; 2749 return 0;
2750} 2750}
@@ -2812,7 +2812,7 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit)
2812 } else { 2812 } else {
2813 netif_warn(priv, rx_err, dev, "Missing skb!\n"); 2813 netif_warn(priv, rx_err, dev, "Missing skb!\n");
2814 rx_queue->stats.rx_dropped++; 2814 rx_queue->stats.rx_dropped++;
2815 priv->extra_stats.rx_skbmissing++; 2815 atomic64_inc(&priv->extra_stats.rx_skbmissing);
2816 } 2816 }
2817 2817
2818 } 2818 }
@@ -3245,7 +3245,7 @@ static irqreturn_t gfar_error(int irq, void *grp_id)
3245 netif_dbg(priv, tx_err, dev, 3245 netif_dbg(priv, tx_err, dev,
3246 "TX FIFO underrun, packet dropped\n"); 3246 "TX FIFO underrun, packet dropped\n");
3247 dev->stats.tx_dropped++; 3247 dev->stats.tx_dropped++;
3248 priv->extra_stats.tx_underrun++; 3248 atomic64_inc(&priv->extra_stats.tx_underrun);
3249 3249
3250 local_irq_save(flags); 3250 local_irq_save(flags);
3251 lock_tx_qs(priv); 3251 lock_tx_qs(priv);
@@ -3260,7 +3260,7 @@ static irqreturn_t gfar_error(int irq, void *grp_id)
3260 } 3260 }
3261 if (events & IEVENT_BSY) { 3261 if (events & IEVENT_BSY) {
3262 dev->stats.rx_errors++; 3262 dev->stats.rx_errors++;
3263 priv->extra_stats.rx_bsy++; 3263 atomic64_inc(&priv->extra_stats.rx_bsy);
3264 3264
3265 gfar_receive(irq, grp_id); 3265 gfar_receive(irq, grp_id);
3266 3266
@@ -3269,19 +3269,19 @@ static irqreturn_t gfar_error(int irq, void *grp_id)
3269 } 3269 }
3270 if (events & IEVENT_BABR) { 3270 if (events & IEVENT_BABR) {
3271 dev->stats.rx_errors++; 3271 dev->stats.rx_errors++;
3272 priv->extra_stats.rx_babr++; 3272 atomic64_inc(&priv->extra_stats.rx_babr);
3273 3273
3274 netif_dbg(priv, rx_err, dev, "babbling RX error\n"); 3274 netif_dbg(priv, rx_err, dev, "babbling RX error\n");
3275 } 3275 }
3276 if (events & IEVENT_EBERR) { 3276 if (events & IEVENT_EBERR) {
3277 priv->extra_stats.eberr++; 3277 atomic64_inc(&priv->extra_stats.eberr);
3278 netif_dbg(priv, rx_err, dev, "bus error\n"); 3278 netif_dbg(priv, rx_err, dev, "bus error\n");
3279 } 3279 }
3280 if (events & IEVENT_RXC) 3280 if (events & IEVENT_RXC)
3281 netif_dbg(priv, rx_status, dev, "control frame\n"); 3281 netif_dbg(priv, rx_status, dev, "control frame\n");
3282 3282
3283 if (events & IEVENT_BABT) { 3283 if (events & IEVENT_BABT) {
3284 priv->extra_stats.tx_babt++; 3284 atomic64_inc(&priv->extra_stats.tx_babt);
3285 netif_dbg(priv, tx_err, dev, "babbling TX error\n"); 3285 netif_dbg(priv, tx_err, dev, "babbling TX error\n");
3286 } 3286 }
3287 return IRQ_HANDLED; 3287 return IRQ_HANDLED;
diff --git a/drivers/net/ethernet/freescale/gianfar.h b/drivers/net/ethernet/freescale/gianfar.h
index 61b1785c9ca7..78125f1f870e 100644
--- a/drivers/net/ethernet/freescale/gianfar.h
+++ b/drivers/net/ethernet/freescale/gianfar.h
@@ -627,24 +627,25 @@ struct rmon_mib
627}; 627};
628 628
629struct gfar_extra_stats { 629struct gfar_extra_stats {
630 u64 kernel_dropped; 630 atomic64_t kernel_dropped;
631 u64 rx_large; 631 atomic64_t rx_large;
632 u64 rx_short; 632 atomic64_t rx_short;
633 u64 rx_nonoctet; 633 atomic64_t rx_nonoctet;
634 u64 rx_crcerr; 634 atomic64_t rx_crcerr;
635 u64 rx_overrun; 635 atomic64_t rx_overrun;
636 u64 rx_bsy; 636 atomic64_t rx_bsy;
637 u64 rx_babr; 637 atomic64_t rx_babr;
638 u64 rx_trunc; 638 atomic64_t rx_trunc;
639 u64 eberr; 639 atomic64_t eberr;
640 u64 tx_babt; 640 atomic64_t tx_babt;
641 u64 tx_underrun; 641 atomic64_t tx_underrun;
642 u64 rx_skbmissing; 642 atomic64_t rx_skbmissing;
643 u64 tx_timeout; 643 atomic64_t tx_timeout;
644}; 644};
645 645
646#define GFAR_RMON_LEN ((sizeof(struct rmon_mib) - 16)/sizeof(u32)) 646#define GFAR_RMON_LEN ((sizeof(struct rmon_mib) - 16)/sizeof(u32))
647#define GFAR_EXTRA_STATS_LEN (sizeof(struct gfar_extra_stats)/sizeof(u64)) 647#define GFAR_EXTRA_STATS_LEN \
648 (sizeof(struct gfar_extra_stats)/sizeof(atomic64_t))
648 649
649/* Number of stats exported via ethtool */ 650/* Number of stats exported via ethtool */
650#define GFAR_STATS_LEN (GFAR_RMON_LEN + GFAR_EXTRA_STATS_LEN) 651#define GFAR_STATS_LEN (GFAR_RMON_LEN + GFAR_EXTRA_STATS_LEN)
diff --git a/drivers/net/ethernet/freescale/gianfar_ethtool.c b/drivers/net/ethernet/freescale/gianfar_ethtool.c
index 172acb923bfb..75e89acf4912 100644
--- a/drivers/net/ethernet/freescale/gianfar_ethtool.c
+++ b/drivers/net/ethernet/freescale/gianfar_ethtool.c
@@ -149,10 +149,10 @@ static void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy,
149 int i; 149 int i;
150 struct gfar_private *priv = netdev_priv(dev); 150 struct gfar_private *priv = netdev_priv(dev);
151 struct gfar __iomem *regs = priv->gfargrp[0].regs; 151 struct gfar __iomem *regs = priv->gfargrp[0].regs;
152 u64 *extra = (u64 *) & priv->extra_stats; 152 atomic64_t *extra = (atomic64_t *)&priv->extra_stats;
153 153
154 for (i = 0; i < GFAR_EXTRA_STATS_LEN; i++) 154 for (i = 0; i < GFAR_EXTRA_STATS_LEN; i++)
155 buf[i] = extra[i]; 155 buf[i] = atomic64_read(&extra[i]);
156 156
157 if (priv->device_flags & FSL_GIANFAR_DEV_HAS_RMON) { 157 if (priv->device_flags & FSL_GIANFAR_DEV_HAS_RMON) {
158 u32 __iomem *rmon = (u32 __iomem *) &regs->rmon; 158 u32 __iomem *rmon = (u32 __iomem *) &regs->rmon;