Commit b8875ca3 authored by Michael Chan's avatar Michael Chan Committed by David S. Miller
Browse files

bnxt_en: Save ring statistics before reset.



With the current driver, the statistics reported by .ndo_get_stats64()
are reset when the device goes down.  Store a snapshot of the
rtnl_link_stats64 before shutdown.  This snapshot is added to the
current counters in .ndo_get_stats64() so that the counters will not
get reset when the device is down.

Signed-off-by: default avatarMichael Chan <michael.chan@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7c675421
Loading
Loading
Loading
Loading
+43 −14
Original line number Diff line number Diff line
@@ -8333,6 +8333,9 @@ static bool bnxt_drv_busy(struct bnxt *bp)
		test_bit(BNXT_STATE_READ_STATS, &bp->state));
}

static void bnxt_get_ring_stats(struct bnxt *bp,
				struct rtnl_link_stats64 *stats);

static void __bnxt_close_nic(struct bnxt *bp, bool irq_re_init,
			     bool link_re_init)
{
@@ -8358,6 +8361,9 @@ static void __bnxt_close_nic(struct bnxt *bp, bool irq_re_init,
	del_timer_sync(&bp->timer);
	bnxt_free_skbs(bp);

	/* Save ring stats before shutdown */
	if (bp->bnapi)
		bnxt_get_ring_stats(bp, &bp->net_stats_prev);
	if (irq_re_init) {
		bnxt_free_irq(bp);
		bnxt_del_napi(bp);
@@ -8419,23 +8425,12 @@ static int bnxt_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
	return -EOPNOTSUPP;
}

static void
bnxt_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
static void bnxt_get_ring_stats(struct bnxt *bp,
				struct rtnl_link_stats64 *stats)
{
	u32 i;
	struct bnxt *bp = netdev_priv(dev);
	int i;

	set_bit(BNXT_STATE_READ_STATS, &bp->state);
	/* Make sure bnxt_close_nic() sees that we are reading stats before
	 * we check the BNXT_STATE_OPEN flag.
	 */
	smp_mb__after_atomic();
	if (!test_bit(BNXT_STATE_OPEN, &bp->state)) {
		clear_bit(BNXT_STATE_READ_STATS, &bp->state);
		return;
	}

	/* TODO check if we need to synchronize with bnxt_close path */
	for (i = 0; i < bp->cp_nr_rings; i++) {
		struct bnxt_napi *bnapi = bp->bnapi[i];
		struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring;
@@ -8464,6 +8459,40 @@ bnxt_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)

		stats->tx_dropped += le64_to_cpu(hw_stats->tx_drop_pkts);
	}
}

static void bnxt_add_prev_stats(struct bnxt *bp,
				struct rtnl_link_stats64 *stats)
{
	struct rtnl_link_stats64 *prev_stats = &bp->net_stats_prev;

	stats->rx_packets += prev_stats->rx_packets;
	stats->tx_packets += prev_stats->tx_packets;
	stats->rx_bytes += prev_stats->rx_bytes;
	stats->tx_bytes += prev_stats->tx_bytes;
	stats->rx_missed_errors += prev_stats->rx_missed_errors;
	stats->multicast += prev_stats->multicast;
	stats->tx_dropped += prev_stats->tx_dropped;
}

static void
bnxt_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
{
	struct bnxt *bp = netdev_priv(dev);

	set_bit(BNXT_STATE_READ_STATS, &bp->state);
	/* Make sure bnxt_close_nic() sees that we are reading stats before
	 * we check the BNXT_STATE_OPEN flag.
	 */
	smp_mb__after_atomic();
	if (!test_bit(BNXT_STATE_OPEN, &bp->state)) {
		clear_bit(BNXT_STATE_READ_STATS, &bp->state);
		*stats = bp->net_stats_prev;
		return;
	}

	bnxt_get_ring_stats(bp, stats);
	bnxt_add_prev_stats(bp, stats);

	if (bp->flags & BNXT_FLAG_PORT_STATS) {
		struct rx_port_stats *rx = bp->hw_rx_port_stats;
+1 −0
Original line number Diff line number Diff line
@@ -1472,6 +1472,7 @@ struct bnxt {
	void			*hwrm_cmd_resp_addr;
	dma_addr_t		hwrm_cmd_resp_dma_addr;

	struct rtnl_link_stats64	net_stats_prev;
	struct rx_port_stats	*hw_rx_port_stats;
	struct tx_port_stats	*hw_tx_port_stats;
	struct rx_port_stats_ext	*hw_rx_port_stats_ext;