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

Commit f8f3b5ae authored by Jon Cooper's avatar Jon Cooper Committed by Ben Hutchings
Browse files

sfc: Correct RX dropped count for drops while interface is down



We don't directly control RX ingress on Siena or any later
controllers, and so we cannot prevent packets from entering the RX
datapath while the RX queues are not set up.  This results in
the hardware incrementing RX_NODESC_DROP_CNT, but it's not an
error and we should not include it in error stats.

When bringing an interface up or down, pull (or wait for) stats and
count the number of packets that were dropped while the interface was
down.  Subtract this from the reported RX dropped count.

Signed-off-by: default avatarBen Hutchings <bhutchings@solarflare.com>
parent cce28794
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -902,6 +902,7 @@ static int efx_ef10_try_update_nic_stats(struct efx_nic *efx)
		return -EAGAIN;

	/* Update derived statistics */
	efx_nic_fix_nodesc_drop_stat(efx, &stats[EF10_STAT_rx_nodesc_drops]);
	stats[EF10_STAT_rx_good_bytes] =
		stats[EF10_STAT_rx_bytes] -
		stats[EF10_STAT_rx_bytes_minus_good_bytes];
@@ -3423,6 +3424,7 @@ const struct efx_nic_type efx_hunt_a0_nic_type = {
	.describe_stats = efx_ef10_describe_stats,
	.update_stats = efx_ef10_update_stats,
	.start_stats = efx_mcdi_mac_start_stats,
	.pull_stats = efx_mcdi_mac_pull_stats,
	.stop_stats = efx_mcdi_mac_stop_stats,
	.set_id_led = efx_mcdi_set_id_led,
	.push_irq_moderation = efx_ef10_push_irq_moderation,
+11 −0
Original line number Diff line number Diff line
@@ -1684,6 +1684,10 @@ static void efx_start_all(struct efx_nic *efx)
	}

	efx->type->start_stats(efx);
	efx->type->pull_stats(efx);
	spin_lock_bh(&efx->stats_lock);
	efx->type->update_stats(efx, NULL, NULL);
	spin_unlock_bh(&efx->stats_lock);
}

/* Flush all delayed work. Should only be called when no more delayed work
@@ -1711,6 +1715,13 @@ static void efx_stop_all(struct efx_nic *efx)
	if (!efx->port_enabled)
		return;

	/* update stats before we go down so we can accurately count
	 * rx_nodesc_drops
	 */
	efx->type->pull_stats(efx);
	spin_lock_bh(&efx->stats_lock);
	efx->type->update_stats(efx, NULL, NULL);
	spin_unlock_bh(&efx->stats_lock);
	efx->type->stop_stats(efx);
	efx_stop_port(efx);

+10 −0
Original line number Diff line number Diff line
@@ -2593,6 +2593,14 @@ void falcon_start_nic_stats(struct efx_nic *efx)
	spin_unlock_bh(&efx->stats_lock);
}

/* We don't acutally pull stats on falcon. Wait 10ms so that
 * they arrive when we call this just after start_stats
 */
void falcon_pull_nic_stats(struct efx_nic *efx)
{
	msleep(10);
}

void falcon_stop_nic_stats(struct efx_nic *efx)
{
	struct falcon_nic_data *nic_data = efx->nic_data;
@@ -2672,6 +2680,7 @@ const struct efx_nic_type falcon_a1_nic_type = {
	.describe_stats = falcon_describe_nic_stats,
	.update_stats = falcon_update_nic_stats,
	.start_stats = falcon_start_nic_stats,
	.pull_stats = falcon_pull_nic_stats,
	.stop_stats = falcon_stop_nic_stats,
	.set_id_led = falcon_set_id_led,
	.push_irq_moderation = falcon_push_irq_moderation,
@@ -2765,6 +2774,7 @@ const struct efx_nic_type falcon_b0_nic_type = {
	.describe_stats = falcon_describe_nic_stats,
	.update_stats = falcon_update_nic_stats,
	.start_stats = falcon_start_nic_stats,
	.pull_stats = falcon_pull_nic_stats,
	.stop_stats = falcon_stop_nic_stats,
	.set_id_led = falcon_set_id_led,
	.push_irq_moderation = falcon_push_irq_moderation,
+1 −0
Original line number Diff line number Diff line
@@ -301,6 +301,7 @@ int efx_mcdi_set_mac(struct efx_nic *efx);
#define EFX_MC_STATS_GENERATION_INVALID ((__force __le64)(-1))
void efx_mcdi_mac_start_stats(struct efx_nic *efx);
void efx_mcdi_mac_stop_stats(struct efx_nic *efx);
void efx_mcdi_mac_pull_stats(struct efx_nic *efx);
bool efx_mcdi_mac_check_fault(struct efx_nic *efx);
enum reset_type efx_mcdi_map_reset_reason(enum reset_type reason);
int efx_mcdi_reset(struct efx_nic *efx, enum reset_type method);
+38 −11
Original line number Diff line number Diff line
@@ -927,12 +927,23 @@ bool efx_mcdi_mac_check_fault(struct efx_nic *efx)
	return MCDI_DWORD(outbuf, GET_LINK_OUT_MAC_FAULT) != 0;
}

static int efx_mcdi_mac_stats(struct efx_nic *efx, dma_addr_t dma_addr,
			      u32 dma_len, int enable, int clear)
enum efx_stats_action {
	EFX_STATS_ENABLE,
	EFX_STATS_DISABLE,
	EFX_STATS_PULL,
};

static int efx_mcdi_mac_stats(struct efx_nic *efx,
			      enum efx_stats_action action, int clear)
{
	MCDI_DECLARE_BUF(inbuf, MC_CMD_MAC_STATS_IN_LEN);
	int rc;
	int period = enable ? 1000 : 0;
	int change = action == EFX_STATS_PULL ? 0 : 1;
	int enable = action == EFX_STATS_ENABLE ? 1 : 0;
	int period = action == EFX_STATS_ENABLE ? 1000 : 0;
	dma_addr_t dma_addr = efx->stats_buffer.dma_addr;
	u32 dma_len = action != EFX_STATS_DISABLE ?
		MC_CMD_MAC_NSTATS * sizeof(u64) : 0;

	BUILD_BUG_ON(MC_CMD_MAC_STATS_OUT_DMA_LEN != 0);

@@ -940,8 +951,8 @@ static int efx_mcdi_mac_stats(struct efx_nic *efx, dma_addr_t dma_addr,
	MCDI_POPULATE_DWORD_7(inbuf, MAC_STATS_IN_CMD,
			      MAC_STATS_IN_DMA, !!enable,
			      MAC_STATS_IN_CLEAR, clear,
			      MAC_STATS_IN_PERIODIC_CHANGE, 1,
			      MAC_STATS_IN_PERIODIC_ENABLE, !!enable,
			      MAC_STATS_IN_PERIODIC_CHANGE, change,
			      MAC_STATS_IN_PERIODIC_ENABLE, enable,
			      MAC_STATS_IN_PERIODIC_CLEAR, 0,
			      MAC_STATS_IN_PERIODIC_NOEVENT, 1,
			      MAC_STATS_IN_PERIOD_MS, period);
@@ -955,8 +966,8 @@ static int efx_mcdi_mac_stats(struct efx_nic *efx, dma_addr_t dma_addr,
	return 0;

fail:
	netif_err(efx, hw, efx->net_dev, "%s: %s failed rc=%d\n",
		  __func__, enable ? "enable" : "disable", rc);
	netif_err(efx, hw, efx->net_dev, "%s: action %d failed rc=%d\n",
		  __func__, action, rc);
	return rc;
}

@@ -966,13 +977,29 @@ void efx_mcdi_mac_start_stats(struct efx_nic *efx)

	dma_stats[MC_CMD_MAC_GENERATION_END] = EFX_MC_STATS_GENERATION_INVALID;

	efx_mcdi_mac_stats(efx, efx->stats_buffer.dma_addr,
			   MC_CMD_MAC_NSTATS * sizeof(u64), 1, 0);
	efx_mcdi_mac_stats(efx, EFX_STATS_ENABLE, 0);
}

void efx_mcdi_mac_stop_stats(struct efx_nic *efx)
{
	efx_mcdi_mac_stats(efx, efx->stats_buffer.dma_addr, 0, 0, 0);
	efx_mcdi_mac_stats(efx, EFX_STATS_DISABLE, 0);
}

#define EFX_MAC_STATS_WAIT_US 100
#define EFX_MAC_STATS_WAIT_ATTEMPTS 10

void efx_mcdi_mac_pull_stats(struct efx_nic *efx)
{
	__le64 *dma_stats = efx->stats_buffer.addr;
	int attempts = EFX_MAC_STATS_WAIT_ATTEMPTS;

	dma_stats[MC_CMD_MAC_GENERATION_END] = EFX_MC_STATS_GENERATION_INVALID;
	efx_mcdi_mac_stats(efx, EFX_STATS_PULL, 0);

	while (dma_stats[MC_CMD_MAC_GENERATION_END] ==
				EFX_MC_STATS_GENERATION_INVALID &&
			attempts-- != 0)
		udelay(EFX_MAC_STATS_WAIT_US);
}

int efx_mcdi_port_probe(struct efx_nic *efx)
@@ -1003,7 +1030,7 @@ int efx_mcdi_port_probe(struct efx_nic *efx)
		  efx->stats_buffer.addr,
		  (u64)virt_to_phys(efx->stats_buffer.addr));

	efx_mcdi_mac_stats(efx, efx->stats_buffer.dma_addr, 0, 0, 1);
	efx_mcdi_mac_stats(efx, EFX_STATS_DISABLE, 1);

	return 0;
}
Loading