diff options
Diffstat (limited to 'drivers/net/ethernet/sfc/ef10.c')
-rw-r--r-- | drivers/net/ethernet/sfc/ef10.c | 100 |
1 files changed, 50 insertions, 50 deletions
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index 4b0e3695a71a..efc49869320f 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -601,10 +601,14 @@ static int efx_ef10_probe(struct efx_nic *efx) * However, until we use TX option descriptors we need two TX queues * per channel. */ - efx->max_channels = min_t(unsigned int, - EFX_MAX_CHANNELS, - efx_ef10_mem_map_size(efx) / - (efx->vi_stride * EFX_TXQ_TYPES)); + efx->max_vis = efx_ef10_mem_map_size(efx) / efx->vi_stride; + if (!efx->max_vis) { + netif_err(efx, drv, efx->net_dev, "error determining max VIs\n"); + rc = -EIO; + goto fail5; + } + efx->max_channels = min_t(unsigned int, EFX_MAX_CHANNELS, + efx->max_vis / EFX_TXQ_TYPES); efx->max_tx_channels = efx->max_channels; if (WARN_ON(efx->max_channels == 0)) { rc = -EIO; @@ -1129,6 +1133,12 @@ static int efx_ef10_dimension_resources(struct efx_nic *efx) ((efx->n_tx_channels + efx->n_extra_tx_channels) * EFX_TXQ_TYPES) + efx->n_xdp_channels * efx->xdp_tx_per_channel); + if (efx->max_vis && efx->max_vis < channel_vis) { + netif_dbg(efx, drv, efx->net_dev, + "Reducing channel VIs from %u to %u\n", + channel_vis, efx->max_vis); + channel_vis = efx->max_vis; + } #ifdef EFX_USE_PIO /* Try to allocate PIO buffers if wanted and if the full @@ -1269,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; @@ -1290,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) { @@ -1410,8 +1433,6 @@ static int efx_ef10_reset(struct efx_nic *efx, enum reset_type reset_type) { NULL, 64, 8 * MC_CMD_MAC_ ## mcdi_name } #define EF10_OTHER_STAT(ext_name) \ [EF10_STAT_ ## ext_name] = { #ext_name, 0, 0 } -#define GENERIC_SW_STAT(ext_name) \ - [GENERIC_STAT_ ## ext_name] = { #ext_name, 0, 0 } static const struct efx_hw_stat_desc efx_ef10_stat_desc[EF10_STAT_COUNT] = { EF10_DMA_STAT(port_tx_bytes, TX_BYTES), @@ -1455,8 +1476,8 @@ static const struct efx_hw_stat_desc efx_ef10_stat_desc[EF10_STAT_COUNT] = { EF10_DMA_STAT(port_rx_align_error, RX_ALIGN_ERROR_PKTS), EF10_DMA_STAT(port_rx_length_error, RX_LENGTH_ERROR_PKTS), EF10_DMA_STAT(port_rx_nodesc_drops, RX_NODESC_DROPS), - GENERIC_SW_STAT(rx_nodesc_trunc), - GENERIC_SW_STAT(rx_noskb_drops), + EFX_GENERIC_SW_STAT(rx_nodesc_trunc), + EFX_GENERIC_SW_STAT(rx_noskb_drops), EF10_DMA_STAT(port_rx_pm_trunc_bb_overflow, PM_TRUNC_BB_OVERFLOW), EF10_DMA_STAT(port_rx_pm_discard_bb_overflow, PM_DISCARD_BB_OVERFLOW), EF10_DMA_STAT(port_rx_pm_trunc_vfifo_full, PM_TRUNC_VFIFO_FULL), @@ -1765,55 +1786,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); } @@ -3109,14 +3117,6 @@ fail: netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc); } -void efx_ef10_handle_drain_event(struct efx_nic *efx) -{ - if (atomic_dec_and_test(&efx->active_queues)) - wake_up(&efx->flush_wq); - - WARN_ON(atomic_read(&efx->active_queues) < 0); -} - static int efx_ef10_fini_dmaq(struct efx_nic *efx) { struct efx_tx_queue *tx_queue; @@ -4023,7 +4023,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, @@ -4132,7 +4132,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, |