Medford2 NICs support more than MC_CMD_MAC_NSTATS stats, and report the new count in a field of MC_CMD_GET_CAPABILITIES_V4. This also means that the end generation count moves (it is, as before, the last 64 bits of the DMA buffer, but that is no longer MC_CMD_MAC_GENERATION_END). So read num_mac_stats from the GET_CAPABILITIES response, if present; otherwise assume MC_CMD_MAC_NSTATS; and always use num_mac_stats - 1 rather than MC_CMD_MAC_GENERATION_END.
Signed-off-by: Edward Cree <ec...@solarflare.com> --- drivers/net/ethernet/sfc/ef10.c | 23 ++++++++++++++++++----- drivers/net/ethernet/sfc/efx.c | 2 ++ drivers/net/ethernet/sfc/mcdi_port.c | 10 +++++----- drivers/net/ethernet/sfc/net_driver.h | 3 +++ drivers/net/ethernet/sfc/siena.c | 2 +- 5 files changed, 29 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index 1f64c7f60943..27b981e7e786 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -233,7 +233,7 @@ static int efx_ef10_get_vf_index(struct efx_nic *efx) static int efx_ef10_init_datapath_caps(struct efx_nic *efx) { - MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_CAPABILITIES_V3_OUT_LEN); + MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_CAPABILITIES_V4_OUT_LEN); struct efx_ef10_nic_data *nic_data = efx->nic_data; size_t outlen; int rc; @@ -306,6 +306,19 @@ static int efx_ef10_init_datapath_caps(struct efx_nic *efx) efx->vi_stride); } + if (outlen >= MC_CMD_GET_CAPABILITIES_V4_OUT_LEN) { + efx->num_mac_stats = MCDI_WORD(outbuf, + GET_CAPABILITIES_V4_OUT_MAC_STATS_NUM_STATS); + netif_dbg(efx, probe, efx->net_dev, + "firmware reports num_mac_stats = %u\n", + efx->num_mac_stats); + } else { + /* leave num_mac_stats as the default value, MC_CMD_MAC_NSTATS */ + netif_dbg(efx, probe, efx->net_dev, + "firmware did not report num_mac_stats, assuming %u\n", + efx->num_mac_stats); + } + return 0; } @@ -1850,7 +1863,7 @@ static int efx_ef10_try_update_nic_stats_pf(struct efx_nic *efx) dma_stats = efx->stats_buffer.addr; - generation_end = dma_stats[MC_CMD_MAC_GENERATION_END]; + generation_end = dma_stats[efx->num_mac_stats - 1]; if (generation_end == EFX_MC_STATS_GENERATION_INVALID) return 0; rmb(); @@ -1898,7 +1911,7 @@ static int efx_ef10_try_update_nic_stats_vf(struct efx_nic *efx) DECLARE_BITMAP(mask, EF10_STAT_COUNT); __le64 generation_start, generation_end; u64 *stats = nic_data->stats; - u32 dma_len = MC_CMD_MAC_NSTATS * sizeof(u64); + u32 dma_len = efx->num_mac_stats * sizeof(u64); struct efx_buffer stats_buf; __le64 *dma_stats; int rc; @@ -1923,7 +1936,7 @@ static int efx_ef10_try_update_nic_stats_vf(struct efx_nic *efx) } dma_stats = stats_buf.addr; - dma_stats[MC_CMD_MAC_GENERATION_END] = EFX_MC_STATS_GENERATION_INVALID; + dma_stats[efx->num_mac_stats - 1] = EFX_MC_STATS_GENERATION_INVALID; MCDI_SET_QWORD(inbuf, MAC_STATS_IN_DMA_ADDR, stats_buf.dma_addr); MCDI_POPULATE_DWORD_1(inbuf, MAC_STATS_IN_CMD, @@ -1942,7 +1955,7 @@ static int efx_ef10_try_update_nic_stats_vf(struct efx_nic *efx) goto out; } - generation_end = dma_stats[MC_CMD_MAC_GENERATION_END]; + generation_end = dma_stats[efx->num_mac_stats - 1]; if (generation_end == EFX_MC_STATS_GENERATION_INVALID) { WARN_ON_ONCE(1); goto out; diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 7bcbedce07a5..3780161de5a1 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -2983,6 +2983,8 @@ static int efx_init_struct(struct efx_nic *efx, efx->type->rx_ts_offset - efx->type->rx_prefix_size; spin_lock_init(&efx->stats_lock); efx->vi_stride = EFX_DEFAULT_VI_STRIDE; + efx->num_mac_stats = MC_CMD_MAC_NSTATS; + BUILD_BUG_ON(MC_CMD_MAC_NSTATS - 1 != MC_CMD_MAC_GENERATION_END); mutex_init(&efx->mac_lock); efx->phy_op = &efx_dummy_phy_operations; efx->mdio.dev = net_dev; diff --git a/drivers/net/ethernet/sfc/mcdi_port.c b/drivers/net/ethernet/sfc/mcdi_port.c index 6e1f282b2976..65ee1a468170 100644 --- a/drivers/net/ethernet/sfc/mcdi_port.c +++ b/drivers/net/ethernet/sfc/mcdi_port.c @@ -1087,7 +1087,7 @@ static int efx_mcdi_mac_stats(struct efx_nic *efx, 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; + efx->num_mac_stats * sizeof(u64) : 0; BUILD_BUG_ON(MC_CMD_MAC_STATS_OUT_DMA_LEN != 0); @@ -1121,7 +1121,7 @@ void efx_mcdi_mac_start_stats(struct efx_nic *efx) { __le64 *dma_stats = efx->stats_buffer.addr; - dma_stats[MC_CMD_MAC_GENERATION_END] = EFX_MC_STATS_GENERATION_INVALID; + dma_stats[efx->num_mac_stats - 1] = EFX_MC_STATS_GENERATION_INVALID; efx_mcdi_mac_stats(efx, EFX_STATS_ENABLE, 0); } @@ -1139,10 +1139,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; + dma_stats[efx->num_mac_stats - 1] = EFX_MC_STATS_GENERATION_INVALID; efx_mcdi_mac_stats(efx, EFX_STATS_PULL, 0); - while (dma_stats[MC_CMD_MAC_GENERATION_END] == + while (dma_stats[efx->num_mac_stats - 1] == EFX_MC_STATS_GENERATION_INVALID && attempts-- != 0) udelay(EFX_MAC_STATS_WAIT_US); @@ -1167,7 +1167,7 @@ int efx_mcdi_port_probe(struct efx_nic *efx) /* Allocate buffer for stats */ rc = efx_nic_alloc_buffer(efx, &efx->stats_buffer, - MC_CMD_MAC_NSTATS * sizeof(u64), GFP_KERNEL); + efx->num_mac_stats * sizeof(u64), GFP_KERNEL); if (rc) return rc; netif_dbg(efx, probe, efx->net_dev, diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index 6b8730a24513..4cedc5c4c6d9 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -774,6 +774,8 @@ struct vfdi_status; * @port_initialized: Port initialized? * @net_dev: Operating system network device. Consider holding the rtnl lock * @fixed_features: Features which cannot be turned off + * @num_mac_stats: Number of MAC stats reported by firmware (MAC_STATS_NUM_STATS + * field of %MC_CMD_GET_CAPABILITIES_V4 response, or %MC_CMD_MAC_NSTATS) * @stats_buffer: DMA buffer for statistics * @phy_type: PHY type * @phy_op: PHY interface @@ -922,6 +924,7 @@ struct efx_nic { netdev_features_t fixed_features; + u16 num_mac_stats; struct efx_buffer stats_buffer; u64 rx_nodesc_drops_total; u64 rx_nodesc_drops_while_down; diff --git a/drivers/net/ethernet/sfc/siena.c b/drivers/net/ethernet/sfc/siena.c index 22d49ebb347c..ae8645ae4492 100644 --- a/drivers/net/ethernet/sfc/siena.c +++ b/drivers/net/ethernet/sfc/siena.c @@ -555,7 +555,7 @@ static int siena_try_update_nic_stats(struct efx_nic *efx) dma_stats = efx->stats_buffer.addr; - generation_end = dma_stats[MC_CMD_MAC_GENERATION_END]; + generation_end = dma_stats[efx->num_mac_stats - 1]; if (generation_end == EFX_MC_STATS_GENERATION_INVALID) return 0; rmb();