Commit eeda8585 authored by Kevin Groeneveld's avatar Kevin Groeneveld Committed by David S. Miller

b44: add 64 bit stats

Add support for 64 bit stats to Broadcom b44 ethernet driver.
Signed-off-by: default avatarKevin Groeneveld <kgroeneveld@gmail.com>
Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 2e177a5c
...@@ -483,9 +483,11 @@ static int b44_setup_phy(struct b44 *bp) ...@@ -483,9 +483,11 @@ static int b44_setup_phy(struct b44 *bp)
static void b44_stats_update(struct b44 *bp) static void b44_stats_update(struct b44 *bp)
{ {
unsigned long reg; unsigned long reg;
u32 *val; u64 *val;
val = &bp->hw_stats.tx_good_octets; val = &bp->hw_stats.tx_good_octets;
u64_stats_update_begin(&bp->hw_stats.syncp);
for (reg = B44_TX_GOOD_O; reg <= B44_TX_PAUSE; reg += 4UL) { for (reg = B44_TX_GOOD_O; reg <= B44_TX_PAUSE; reg += 4UL) {
*val++ += br32(bp, reg); *val++ += br32(bp, reg);
} }
...@@ -496,6 +498,8 @@ static void b44_stats_update(struct b44 *bp) ...@@ -496,6 +498,8 @@ static void b44_stats_update(struct b44 *bp)
for (reg = B44_RX_GOOD_O; reg <= B44_RX_NPAUSE; reg += 4UL) { for (reg = B44_RX_GOOD_O; reg <= B44_RX_NPAUSE; reg += 4UL) {
*val++ += br32(bp, reg); *val++ += br32(bp, reg);
} }
u64_stats_update_end(&bp->hw_stats.syncp);
} }
static void b44_link_report(struct b44 *bp) static void b44_link_report(struct b44 *bp)
...@@ -1635,13 +1639,17 @@ static int b44_close(struct net_device *dev) ...@@ -1635,13 +1639,17 @@ static int b44_close(struct net_device *dev)
return 0; return 0;
} }
static struct net_device_stats *b44_get_stats(struct net_device *dev) static struct rtnl_link_stats64 *b44_get_stats64(struct net_device *dev,
struct rtnl_link_stats64 *nstat)
{ {
struct b44 *bp = netdev_priv(dev); struct b44 *bp = netdev_priv(dev);
struct net_device_stats *nstat = &dev->stats;
struct b44_hw_stats *hwstat = &bp->hw_stats; struct b44_hw_stats *hwstat = &bp->hw_stats;
unsigned int start;
/* Convert HW stats into netdevice stats. */ do {
start = u64_stats_fetch_begin_bh(&hwstat->syncp);
/* Convert HW stats into rtnl_link_stats64 stats. */
nstat->rx_packets = hwstat->rx_pkts; nstat->rx_packets = hwstat->rx_pkts;
nstat->tx_packets = hwstat->tx_pkts; nstat->tx_packets = hwstat->tx_pkts;
nstat->rx_bytes = hwstat->rx_octets; nstat->rx_bytes = hwstat->rx_octets;
...@@ -1673,6 +1681,7 @@ static struct net_device_stats *b44_get_stats(struct net_device *dev) ...@@ -1673,6 +1681,7 @@ static struct net_device_stats *b44_get_stats(struct net_device *dev)
/* Carrier lost counter seems to be broken for some devices */ /* Carrier lost counter seems to be broken for some devices */
nstat->tx_carrier_errors = hwstat->tx_carrier_lost; nstat->tx_carrier_errors = hwstat->tx_carrier_lost;
#endif #endif
} while (u64_stats_fetch_retry_bh(&hwstat->syncp, start));
return nstat; return nstat;
} }
...@@ -1993,17 +2002,24 @@ static void b44_get_ethtool_stats(struct net_device *dev, ...@@ -1993,17 +2002,24 @@ static void b44_get_ethtool_stats(struct net_device *dev,
struct ethtool_stats *stats, u64 *data) struct ethtool_stats *stats, u64 *data)
{ {
struct b44 *bp = netdev_priv(dev); struct b44 *bp = netdev_priv(dev);
u32 *val = &bp->hw_stats.tx_good_octets; struct b44_hw_stats *hwstat = &bp->hw_stats;
u64 *data_src, *data_dst;
unsigned int start;
u32 i; u32 i;
spin_lock_irq(&bp->lock); spin_lock_irq(&bp->lock);
b44_stats_update(bp); b44_stats_update(bp);
spin_unlock_irq(&bp->lock);
do {
data_src = &hwstat->tx_good_octets;
data_dst = data;
start = u64_stats_fetch_begin_bh(&hwstat->syncp);
for (i = 0; i < ARRAY_SIZE(b44_gstrings); i++) for (i = 0; i < ARRAY_SIZE(b44_gstrings); i++)
*data++ = *val++; *data_dst++ = *data_src++;
spin_unlock_irq(&bp->lock); } while (u64_stats_fetch_retry_bh(&hwstat->syncp, start));
} }
static void b44_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) static void b44_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
...@@ -2113,7 +2129,7 @@ static const struct net_device_ops b44_netdev_ops = { ...@@ -2113,7 +2129,7 @@ static const struct net_device_ops b44_netdev_ops = {
.ndo_open = b44_open, .ndo_open = b44_open,
.ndo_stop = b44_close, .ndo_stop = b44_close,
.ndo_start_xmit = b44_start_xmit, .ndo_start_xmit = b44_start_xmit,
.ndo_get_stats = b44_get_stats, .ndo_get_stats64 = b44_get_stats64,
.ndo_set_rx_mode = b44_set_rx_mode, .ndo_set_rx_mode = b44_set_rx_mode,
.ndo_set_mac_address = b44_set_mac_addr, .ndo_set_mac_address = b44_set_mac_addr,
.ndo_validate_addr = eth_validate_addr, .ndo_validate_addr = eth_validate_addr,
......
...@@ -338,9 +338,10 @@ struct ring_info { ...@@ -338,9 +338,10 @@ struct ring_info {
* the layout * the layout
*/ */
struct b44_hw_stats { struct b44_hw_stats {
#define _B44(x) u32 x; #define _B44(x) u64 x;
B44_STAT_REG_DECLARE B44_STAT_REG_DECLARE
#undef _B44 #undef _B44
struct u64_stats_sync syncp;
}; };
struct ssb_device; struct ssb_device;
......
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