Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 65e665e6 authored by Igor Russkikh's avatar Igor Russkikh Committed by David S. Miller
Browse files

net: aquantia: Reset nic statistics on interface up/down



Internal statistics system on chip never gets reset until hardware
reboot. This is quite inconvenient in terms of ethtool statistics usage.

This patch implements incremental statistics update inside of
service callback.

Upon nic initialization, first request is done to fetch
initial stat data, current collected stat data gets cleared.
Internal statistics mailbox readout is improved to save space and
increase readability

Signed-off-by: default avatarPavel Belous <pavel.belous@aquantia.com>
Signed-off-by: default avatarIgor Russkikh <igor.russkikh@aquantia.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 197df02c
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -163,6 +163,8 @@ struct aq_hw_ops {
	int (*hw_get_regs)(struct aq_hw_s *self,
			   struct aq_hw_caps_s *aq_hw_caps, u32 *regs_buff);

	int (*hw_update_stats)(struct aq_hw_s *self);

	int (*hw_get_hw_stats)(struct aq_hw_s *self, u64 *data,
			       unsigned int *p_count);

+3 −0
Original line number Diff line number Diff line
@@ -167,6 +167,9 @@ static void aq_nic_service_timer_cb(unsigned long param)
	self->aq_hw_ops.hw_interrupt_moderation_set(self->aq_hw,
		    self->aq_nic_cfg.is_interrupt_moderation);

	if (self->aq_hw_ops.hw_update_stats)
		self->aq_hw_ops.hw_update_stats(self->aq_hw);

	memset(&stats_rx, 0U, sizeof(struct aq_ring_stats_rx_s));
	memset(&stats_tx, 0U, sizeof(struct aq_ring_stats_tx_s));
	for (i = AQ_DIMOF(self->aq_vec); i--;) {
+1 −0
Original line number Diff line number Diff line
@@ -885,6 +885,7 @@ static struct aq_hw_ops hw_atl_ops_ = {
	.hw_rss_set                  = hw_atl_a0_hw_rss_set,
	.hw_rss_hash_set             = hw_atl_a0_hw_rss_hash_set,
	.hw_get_regs                 = hw_atl_utils_hw_get_regs,
	.hw_update_stats             = hw_atl_utils_update_stats,
	.hw_get_hw_stats             = hw_atl_utils_get_hw_stats,
	.hw_get_fw_version           = hw_atl_utils_get_fw_version,
};
+1 −0
Original line number Diff line number Diff line
@@ -939,6 +939,7 @@ static struct aq_hw_ops hw_atl_ops_ = {
	.hw_rss_set                  = hw_atl_b0_hw_rss_set,
	.hw_rss_hash_set             = hw_atl_b0_hw_rss_hash_set,
	.hw_get_regs                 = hw_atl_utils_hw_get_regs,
	.hw_update_stats             = hw_atl_utils_update_stats,
	.hw_get_hw_stats             = hw_atl_utils_get_hw_stats,
	.hw_get_fw_version           = hw_atl_utils_get_fw_version,
};
+55 −14
Original line number Diff line number Diff line
@@ -255,6 +255,15 @@ static int hw_atl_utils_mpi_create(struct aq_hw_s *self,
	return err;
}

int hw_atl_utils_mpi_read_mbox(struct aq_hw_s *self,
			       struct hw_aq_atl_utils_mbox_header *pmbox)
{
	return hw_atl_utils_fw_downld_dwords(self,
				      PHAL_ATLANTIC->mbox_addr,
				      (u32 *)(void *)pmbox,
				      sizeof(*pmbox) / sizeof(u32));
}

void hw_atl_utils_mpi_read_stats(struct aq_hw_s *self,
				 struct hw_aq_atl_utils_mbox *pmbox)
{
@@ -267,9 +276,6 @@ void hw_atl_utils_mpi_read_stats(struct aq_hw_s *self,
	if (err < 0)
		goto err_exit;

	if (pmbox != &PHAL_ATLANTIC->mbox)
		memcpy(pmbox, &PHAL_ATLANTIC->mbox, sizeof(*pmbox));

	if (IS_CHIP_FEATURE(REVISION_A0)) {
		unsigned int mtu = self->aq_nic_cfg ?
					self->aq_nic_cfg->mtu : 1514U;
@@ -299,16 +305,16 @@ void hw_atl_utils_mpi_set(struct aq_hw_s *self,
{
	int err = 0;
	u32 transaction_id = 0;
	struct hw_aq_atl_utils_mbox_header mbox;

	if (state == MPI_RESET) {
		hw_atl_utils_mpi_read_stats(self, &PHAL_ATLANTIC->mbox);
		hw_atl_utils_mpi_read_mbox(self, &mbox);

		transaction_id = PHAL_ATLANTIC->mbox.transaction_id;
		transaction_id = mbox.transaction_id;

		AQ_HW_WAIT_FOR(transaction_id !=
				(hw_atl_utils_mpi_read_stats
					(self, &PHAL_ATLANTIC->mbox),
					PHAL_ATLANTIC->mbox.transaction_id),
				(hw_atl_utils_mpi_read_mbox(self, &mbox),
				 mbox.transaction_id),
			       1000U, 100U);
		if (err < 0)
			goto err_exit;
@@ -492,16 +498,51 @@ int hw_atl_utils_hw_set_power(struct aq_hw_s *self,
	return 0;
}

int hw_atl_utils_update_stats(struct aq_hw_s *self)
{
	struct hw_atl_s *hw_self = PHAL_ATLANTIC;
	struct hw_aq_atl_utils_mbox mbox;

	if (!self->aq_link_status.mbps)
		return 0;

	hw_atl_utils_mpi_read_stats(self, &mbox);

#define AQ_SDELTA(_N_) (hw_self->curr_stats._N_ += \
			mbox.stats._N_ - hw_self->last_stats._N_)

	AQ_SDELTA(uprc);
	AQ_SDELTA(mprc);
	AQ_SDELTA(bprc);
	AQ_SDELTA(erpt);

	AQ_SDELTA(uptc);
	AQ_SDELTA(mptc);
	AQ_SDELTA(bptc);
	AQ_SDELTA(erpr);

	AQ_SDELTA(ubrc);
	AQ_SDELTA(ubtc);
	AQ_SDELTA(mbrc);
	AQ_SDELTA(mbtc);
	AQ_SDELTA(bbrc);
	AQ_SDELTA(bbtc);
	AQ_SDELTA(dpc);

#undef AQ_SDELTA

	memcpy(&hw_self->last_stats, &mbox.stats, sizeof(mbox.stats));

	return 0;
}

int hw_atl_utils_get_hw_stats(struct aq_hw_s *self,
			      u64 *data, unsigned int *p_count)
{
	struct hw_atl_stats_s *stats = NULL;
	struct hw_atl_s *hw_self = PHAL_ATLANTIC;
	struct hw_atl_stats_s *stats = &hw_self->curr_stats;
	int i = 0;

	hw_atl_utils_mpi_read_stats(self, &PHAL_ATLANTIC->mbox);

	stats = &PHAL_ATLANTIC->mbox.stats;

	data[i] = stats->uprc + stats->mprc + stats->bprc;
	data[++i] = stats->uprc;
	data[++i] = stats->mprc;
Loading