aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/sfc/ef10.c
diff options
context:
space:
mode:
authorEdward Cree <ecree@solarflare.com>2020-06-29 14:34:20 +0100
committerDavid S. Miller <davem@davemloft.net>2020-06-29 17:37:48 -0700
commitd3142c193dca9a2f6878f4128ce1aaf221bb3f99 (patch)
tree8722218c1475c4f51a49cebd78e68bc703d2863d /drivers/net/ethernet/sfc/ef10.c
parentsfc: don't try to create more channels than we can have VIs (diff)
downloadlinux-dev-d3142c193dca9a2f6878f4128ce1aaf221bb3f99.tar.xz
linux-dev-d3142c193dca9a2f6878f4128ce1aaf221bb3f99.zip
sfc: refactor EF10 stats handling
Separate the generation-count handling from the format conversion, to make it easier to re-use both for EF100. Signed-off-by: Edward Cree <ecree@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/sfc/ef10.c')
-rw-r--r--drivers/net/ethernet/sfc/ef10.c68
1 files changed, 34 insertions, 34 deletions
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c
index c99fedb315fe..49af06ba7a8e 100644
--- a/drivers/net/ethernet/sfc/ef10.c
+++ b/drivers/net/ethernet/sfc/ef10.c
@@ -1279,6 +1279,14 @@ static int efx_ef10_dimension_resources(struct efx_nic *efx)
return 0;
}
+static void efx_ef10_fini_nic(struct efx_nic *efx)
+{
+ struct efx_ef10_nic_data *nic_data = efx->nic_data;
+
+ kfree(nic_data->mc_stats);
+ nic_data->mc_stats = NULL;
+}
+
static int efx_ef10_init_nic(struct efx_nic *efx)
{
struct efx_ef10_nic_data *nic_data = efx->nic_data;
@@ -1300,6 +1308,11 @@ static int efx_ef10_init_nic(struct efx_nic *efx)
efx->must_realloc_vis = false;
}
+ nic_data->mc_stats = kmalloc(efx->num_mac_stats * sizeof(__le64),
+ GFP_KERNEL);
+ if (!nic_data->mc_stats)
+ return -ENOMEM;
+
if (nic_data->must_restore_piobufs && nic_data->n_piobufs) {
rc = efx_ef10_alloc_piobufs(efx, nic_data->n_piobufs);
if (rc == 0) {
@@ -1775,55 +1788,42 @@ static size_t efx_ef10_update_stats_common(struct efx_nic *efx, u64 *full_stats,
return stats_count;
}
-static int efx_ef10_try_update_nic_stats_pf(struct efx_nic *efx)
+static size_t efx_ef10_update_stats_pf(struct efx_nic *efx, u64 *full_stats,
+ struct rtnl_link_stats64 *core_stats)
{
struct efx_ef10_nic_data *nic_data = efx->nic_data;
DECLARE_BITMAP(mask, EF10_STAT_COUNT);
- __le64 generation_start, generation_end;
u64 *stats = nic_data->stats;
- __le64 *dma_stats;
efx_ef10_get_stat_mask(efx, mask);
- dma_stats = efx->stats_buffer.addr;
-
- generation_end = dma_stats[efx->num_mac_stats - 1];
- if (generation_end == EFX_MC_STATS_GENERATION_INVALID)
- return 0;
- rmb();
- efx_nic_update_stats(efx_ef10_stat_desc, EF10_STAT_COUNT, mask,
- stats, efx->stats_buffer.addr, false);
- rmb();
- generation_start = dma_stats[MC_CMD_MAC_GENERATION_START];
- if (generation_end != generation_start)
- return -EAGAIN;
+ efx_nic_copy_stats(efx, nic_data->mc_stats);
+ efx_nic_update_stats(efx_ef10_stat_desc, EF10_STAT_COUNT,
+ mask, stats, nic_data->mc_stats, false);
/* Update derived statistics */
efx_nic_fix_nodesc_drop_stat(efx,
&stats[EF10_STAT_port_rx_nodesc_drops]);
+ /* MC Firmware reads RX_BYTES and RX_GOOD_BYTES from the MAC.
+ * It then calculates RX_BAD_BYTES and DMAs it to us with RX_BYTES.
+ * We report these as port_rx_ stats. We are not given RX_GOOD_BYTES.
+ * Here we calculate port_rx_good_bytes.
+ */
stats[EF10_STAT_port_rx_good_bytes] =
stats[EF10_STAT_port_rx_bytes] -
stats[EF10_STAT_port_rx_bytes_minus_good_bytes];
+
+ /* The asynchronous reads used to calculate RX_BAD_BYTES in
+ * MC Firmware are done such that we should not see an increase in
+ * RX_BAD_BYTES when a good packet has arrived. Unfortunately this
+ * does mean that the stat can decrease at times. Here we do not
+ * update the stat unless it has increased or has gone to zero
+ * (In the case of the NIC rebooting).
+ * Please see Bug 33781 for a discussion of why things work this way.
+ */
efx_update_diff_stat(&stats[EF10_STAT_port_rx_bad_bytes],
stats[EF10_STAT_port_rx_bytes_minus_good_bytes]);
efx_update_sw_stats(efx, stats);
- return 0;
-}
-
-
-static size_t efx_ef10_update_stats_pf(struct efx_nic *efx, u64 *full_stats,
- struct rtnl_link_stats64 *core_stats)
-{
- int retry;
-
- /* If we're unlucky enough to read statistics during the DMA, wait
- * up to 10ms for it to finish (typically takes <500us)
- */
- for (retry = 0; retry < 100; ++retry) {
- if (efx_ef10_try_update_nic_stats_pf(efx) == 0)
- break;
- udelay(100);
- }
return efx_ef10_update_stats_common(efx, full_stats, core_stats);
}
@@ -4033,7 +4033,7 @@ const struct efx_nic_type efx_hunt_a0_vf_nic_type = {
.remove = efx_ef10_remove,
.dimension_resources = efx_ef10_dimension_resources,
.init = efx_ef10_init_nic,
- .fini = efx_port_dummy_op_void,
+ .fini = efx_ef10_fini_nic,
.map_reset_reason = efx_ef10_map_reset_reason,
.map_reset_flags = efx_ef10_map_reset_flags,
.reset = efx_ef10_reset,
@@ -4142,7 +4142,7 @@ const struct efx_nic_type efx_hunt_a0_nic_type = {
.remove = efx_ef10_remove,
.dimension_resources = efx_ef10_dimension_resources,
.init = efx_ef10_init_nic,
- .fini = efx_port_dummy_op_void,
+ .fini = efx_ef10_fini_nic,
.map_reset_reason = efx_ef10_map_reset_reason,
.map_reset_flags = efx_ef10_map_reset_flags,
.reset = efx_ef10_reset,