diff options
Diffstat (limited to 'drivers/net/ethernet/broadcom/b44.c')
| -rw-r--r-- | drivers/net/ethernet/broadcom/b44.c | 90 | 
1 files changed, 53 insertions, 37 deletions
diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c index d09c6b583d1..9786c0e9890 100644 --- a/drivers/net/ethernet/broadcom/b44.c +++ b/drivers/net/ethernet/broadcom/b44.c @@ -483,9 +483,11 @@ out:  static void b44_stats_update(struct b44 *bp)  {  	unsigned long reg; -	u32 *val; +	u64 *val;  	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) {  		*val++ += br32(bp, reg);  	} @@ -496,6 +498,8 @@ static void b44_stats_update(struct b44 *bp)  	for (reg = B44_RX_GOOD_O; reg <= B44_RX_NPAUSE; reg += 4UL) {  		*val++ += br32(bp, reg);  	} + +	u64_stats_update_end(&bp->hw_stats.syncp);  }  static void b44_link_report(struct b44 *bp) @@ -1635,44 +1639,49 @@ static int b44_close(struct net_device *dev)  	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 net_device_stats *nstat = &dev->stats;  	struct b44_hw_stats *hwstat = &bp->hw_stats; +	unsigned int start; -	/* Convert HW stats into netdevice stats. */ -	nstat->rx_packets = hwstat->rx_pkts; -	nstat->tx_packets = hwstat->tx_pkts; -	nstat->rx_bytes   = hwstat->rx_octets; -	nstat->tx_bytes   = hwstat->tx_octets; -	nstat->tx_errors  = (hwstat->tx_jabber_pkts + -			     hwstat->tx_oversize_pkts + -			     hwstat->tx_underruns + -			     hwstat->tx_excessive_cols + -			     hwstat->tx_late_cols); -	nstat->multicast  = hwstat->tx_multicast_pkts; -	nstat->collisions = hwstat->tx_total_cols; +	do { +		start = u64_stats_fetch_begin_bh(&hwstat->syncp); -	nstat->rx_length_errors = (hwstat->rx_oversize_pkts + -				   hwstat->rx_undersize); -	nstat->rx_over_errors   = hwstat->rx_missed_pkts; -	nstat->rx_frame_errors  = hwstat->rx_align_errs; -	nstat->rx_crc_errors    = hwstat->rx_crc_errs; -	nstat->rx_errors        = (hwstat->rx_jabber_pkts + -				   hwstat->rx_oversize_pkts + -				   hwstat->rx_missed_pkts + -				   hwstat->rx_crc_align_errs + -				   hwstat->rx_undersize + -				   hwstat->rx_crc_errs + -				   hwstat->rx_align_errs + -				   hwstat->rx_symbol_errs); +		/* Convert HW stats into rtnl_link_stats64 stats. */ +		nstat->rx_packets = hwstat->rx_pkts; +		nstat->tx_packets = hwstat->tx_pkts; +		nstat->rx_bytes   = hwstat->rx_octets; +		nstat->tx_bytes   = hwstat->tx_octets; +		nstat->tx_errors  = (hwstat->tx_jabber_pkts + +				     hwstat->tx_oversize_pkts + +				     hwstat->tx_underruns + +				     hwstat->tx_excessive_cols + +				     hwstat->tx_late_cols); +		nstat->multicast  = hwstat->tx_multicast_pkts; +		nstat->collisions = hwstat->tx_total_cols; -	nstat->tx_aborted_errors = hwstat->tx_underruns; +		nstat->rx_length_errors = (hwstat->rx_oversize_pkts + +					   hwstat->rx_undersize); +		nstat->rx_over_errors   = hwstat->rx_missed_pkts; +		nstat->rx_frame_errors  = hwstat->rx_align_errs; +		nstat->rx_crc_errors    = hwstat->rx_crc_errs; +		nstat->rx_errors        = (hwstat->rx_jabber_pkts + +					   hwstat->rx_oversize_pkts + +					   hwstat->rx_missed_pkts + +					   hwstat->rx_crc_align_errs + +					   hwstat->rx_undersize + +					   hwstat->rx_crc_errs + +					   hwstat->rx_align_errs + +					   hwstat->rx_symbol_errs); + +		nstat->tx_aborted_errors = hwstat->tx_underruns;  #if 0 -	/* Carrier lost counter seems to be broken for some devices */ -	nstat->tx_carrier_errors = hwstat->tx_carrier_lost; +		/* Carrier lost counter seems to be broken for some devices */ +		nstat->tx_carrier_errors = hwstat->tx_carrier_lost;  #endif +	} while (u64_stats_fetch_retry_bh(&hwstat->syncp, start));  	return nstat;  } @@ -1993,17 +2002,24 @@ static void b44_get_ethtool_stats(struct net_device *dev,  				  struct ethtool_stats *stats, u64 *data)  {  	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;  	spin_lock_irq(&bp->lock); -  	b44_stats_update(bp); +	spin_unlock_irq(&bp->lock); -	for (i = 0; i < ARRAY_SIZE(b44_gstrings); i++) -		*data++ = *val++; +	do { +		data_src = &hwstat->tx_good_octets; +		data_dst = data; +		start = u64_stats_fetch_begin_bh(&hwstat->syncp); -	spin_unlock_irq(&bp->lock); +		for (i = 0; i < ARRAY_SIZE(b44_gstrings); i++) +			*data_dst++ = *data_src++; + +	} while (u64_stats_fetch_retry_bh(&hwstat->syncp, start));  }  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 = {  	.ndo_open		= b44_open,  	.ndo_stop		= b44_close,  	.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_mac_address	= b44_set_mac_addr,  	.ndo_validate_addr	= eth_validate_addr,  |