Commit 212079df authored by Paul Gortmaker's avatar Paul Gortmaker

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: default avatarEric Dumazet <edumazet@google.com>
Signed-off-by: default avatarPaul Gortmaker <paul.gortmaker@windriver.com>
parent 68719786
...@@ -2648,7 +2648,7 @@ static inline void count_errors(unsigned short status, struct net_device *dev) ...@@ -2648,7 +2648,7 @@ static inline void count_errors(unsigned short status, struct net_device *dev)
if (status & RXBD_TRUNCATED) { if (status & RXBD_TRUNCATED) {
stats->rx_length_errors++; stats->rx_length_errors++;
estats->rx_trunc++; atomic64_inc(&estats->rx_trunc);
return; return;
} }
...@@ -2657,20 +2657,20 @@ static inline void count_errors(unsigned short status, struct net_device *dev) ...@@ -2657,20 +2657,20 @@ static inline void count_errors(unsigned short status, struct net_device *dev)
stats->rx_length_errors++; stats->rx_length_errors++;
if (status & RXBD_LARGE) if (status & RXBD_LARGE)
estats->rx_large++; atomic64_inc(&estats->rx_large);
else else
estats->rx_short++; atomic64_inc(&estats->rx_short);
} }
if (status & RXBD_NONOCTET) { if (status & RXBD_NONOCTET) {
stats->rx_frame_errors++; stats->rx_frame_errors++;
estats->rx_nonoctet++; atomic64_inc(&estats->rx_nonoctet);
} }
if (status & RXBD_CRCERR) { if (status & RXBD_CRCERR) {
estats->rx_crcerr++; atomic64_inc(&estats->rx_crcerr);
stats->rx_crc_errors++; stats->rx_crc_errors++;
} }
if (status & RXBD_OVERRUN) { if (status & RXBD_OVERRUN) {
estats->rx_overrun++; atomic64_inc(&estats->rx_overrun);
stats->rx_crc_errors++; stats->rx_crc_errors++;
} }
} }
...@@ -2744,7 +2744,7 @@ static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, ...@@ -2744,7 +2744,7 @@ static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb,
ret = napi_gro_receive(napi, skb); ret = napi_gro_receive(napi, skb);
if (GRO_DROP == ret) if (GRO_DROP == ret)
priv->extra_stats.kernel_dropped++; atomic64_inc(&priv->extra_stats.kernel_dropped);
return 0; return 0;
} }
...@@ -2812,7 +2812,7 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit) ...@@ -2812,7 +2812,7 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit)
} else { } else {
netif_warn(priv, rx_err, dev, "Missing skb!\n"); netif_warn(priv, rx_err, dev, "Missing skb!\n");
rx_queue->stats.rx_dropped++; rx_queue->stats.rx_dropped++;
priv->extra_stats.rx_skbmissing++; atomic64_inc(&priv->extra_stats.rx_skbmissing);
} }
} }
...@@ -3245,7 +3245,7 @@ static irqreturn_t gfar_error(int irq, void *grp_id) ...@@ -3245,7 +3245,7 @@ static irqreturn_t gfar_error(int irq, void *grp_id)
netif_dbg(priv, tx_err, dev, netif_dbg(priv, tx_err, dev,
"TX FIFO underrun, packet dropped\n"); "TX FIFO underrun, packet dropped\n");
dev->stats.tx_dropped++; dev->stats.tx_dropped++;
priv->extra_stats.tx_underrun++; atomic64_inc(&priv->extra_stats.tx_underrun);
local_irq_save(flags); local_irq_save(flags);
lock_tx_qs(priv); lock_tx_qs(priv);
...@@ -3260,7 +3260,7 @@ static irqreturn_t gfar_error(int irq, void *grp_id) ...@@ -3260,7 +3260,7 @@ static irqreturn_t gfar_error(int irq, void *grp_id)
} }
if (events & IEVENT_BSY) { if (events & IEVENT_BSY) {
dev->stats.rx_errors++; dev->stats.rx_errors++;
priv->extra_stats.rx_bsy++; atomic64_inc(&priv->extra_stats.rx_bsy);
gfar_receive(irq, grp_id); gfar_receive(irq, grp_id);
...@@ -3269,19 +3269,19 @@ static irqreturn_t gfar_error(int irq, void *grp_id) ...@@ -3269,19 +3269,19 @@ static irqreturn_t gfar_error(int irq, void *grp_id)
} }
if (events & IEVENT_BABR) { if (events & IEVENT_BABR) {
dev->stats.rx_errors++; dev->stats.rx_errors++;
priv->extra_stats.rx_babr++; atomic64_inc(&priv->extra_stats.rx_babr);
netif_dbg(priv, rx_err, dev, "babbling RX error\n"); netif_dbg(priv, rx_err, dev, "babbling RX error\n");
} }
if (events & IEVENT_EBERR) { if (events & IEVENT_EBERR) {
priv->extra_stats.eberr++; atomic64_inc(&priv->extra_stats.eberr);
netif_dbg(priv, rx_err, dev, "bus error\n"); netif_dbg(priv, rx_err, dev, "bus error\n");
} }
if (events & IEVENT_RXC) if (events & IEVENT_RXC)
netif_dbg(priv, rx_status, dev, "control frame\n"); netif_dbg(priv, rx_status, dev, "control frame\n");
if (events & IEVENT_BABT) { if (events & IEVENT_BABT) {
priv->extra_stats.tx_babt++; atomic64_inc(&priv->extra_stats.tx_babt);
netif_dbg(priv, tx_err, dev, "babbling TX error\n"); netif_dbg(priv, tx_err, dev, "babbling TX error\n");
} }
return IRQ_HANDLED; return IRQ_HANDLED;
......
...@@ -627,24 +627,25 @@ struct rmon_mib ...@@ -627,24 +627,25 @@ struct rmon_mib
}; };
struct gfar_extra_stats { struct gfar_extra_stats {
u64 kernel_dropped; atomic64_t kernel_dropped;
u64 rx_large; atomic64_t rx_large;
u64 rx_short; atomic64_t rx_short;
u64 rx_nonoctet; atomic64_t rx_nonoctet;
u64 rx_crcerr; atomic64_t rx_crcerr;
u64 rx_overrun; atomic64_t rx_overrun;
u64 rx_bsy; atomic64_t rx_bsy;
u64 rx_babr; atomic64_t rx_babr;
u64 rx_trunc; atomic64_t rx_trunc;
u64 eberr; atomic64_t eberr;
u64 tx_babt; atomic64_t tx_babt;
u64 tx_underrun; atomic64_t tx_underrun;
u64 rx_skbmissing; atomic64_t rx_skbmissing;
u64 tx_timeout; atomic64_t tx_timeout;
}; };
#define GFAR_RMON_LEN ((sizeof(struct rmon_mib) - 16)/sizeof(u32)) #define GFAR_RMON_LEN ((sizeof(struct rmon_mib) - 16)/sizeof(u32))
#define GFAR_EXTRA_STATS_LEN (sizeof(struct gfar_extra_stats)/sizeof(u64)) #define GFAR_EXTRA_STATS_LEN \
(sizeof(struct gfar_extra_stats)/sizeof(atomic64_t))
/* Number of stats exported via ethtool */ /* Number of stats exported via ethtool */
#define GFAR_STATS_LEN (GFAR_RMON_LEN + GFAR_EXTRA_STATS_LEN) #define GFAR_STATS_LEN (GFAR_RMON_LEN + GFAR_EXTRA_STATS_LEN)
......
...@@ -149,10 +149,10 @@ static void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy, ...@@ -149,10 +149,10 @@ static void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy,
int i; int i;
struct gfar_private *priv = netdev_priv(dev); struct gfar_private *priv = netdev_priv(dev);
struct gfar __iomem *regs = priv->gfargrp[0].regs; struct gfar __iomem *regs = priv->gfargrp[0].regs;
u64 *extra = (u64 *) & priv->extra_stats; atomic64_t *extra = (atomic64_t *)&priv->extra_stats;
for (i = 0; i < GFAR_EXTRA_STATS_LEN; i++) for (i = 0; i < GFAR_EXTRA_STATS_LEN; i++)
buf[i] = extra[i]; buf[i] = atomic64_read(&extra[i]);
if (priv->device_flags & FSL_GIANFAR_DEV_HAS_RMON) { if (priv->device_flags & FSL_GIANFAR_DEV_HAS_RMON) {
u32 __iomem *rmon = (u32 __iomem *) &regs->rmon; u32 __iomem *rmon = (u32 __iomem *) &regs->rmon;
......
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