diff options
Diffstat (limited to 'drivers/net/sfc/base/ef10_mac.c')
-rw-r--r-- | drivers/net/sfc/base/ef10_mac.c | 193 |
1 files changed, 184 insertions, 9 deletions
diff --git a/drivers/net/sfc/base/ef10_mac.c b/drivers/net/sfc/base/ef10_mac.c index db7692ee..1031e836 100644 --- a/drivers/net/sfc/base/ef10_mac.c +++ b/drivers/net/sfc/base/ef10_mac.c @@ -8,7 +8,7 @@ #include "efx_impl.h" -#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD +#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 __checkReturn efx_rc_t ef10_mac_poll( @@ -356,7 +356,8 @@ ef10_mac_multicast_list_set( efx_rc_t rc; EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || - enp->en_family == EFX_FAMILY_MEDFORD); + enp->en_family == EFX_FAMILY_MEDFORD || + enp->en_family == EFX_FAMILY_MEDFORD2); if ((rc = emop->emo_reconfigure(enp)) != 0) goto fail1; @@ -522,8 +523,44 @@ ef10_mac_stats_get_mask( goto fail6; } + if (encp->enc_fec_counters) { + const struct efx_mac_stats_range ef10_fec[] = { + { EFX_MAC_FEC_UNCORRECTED_ERRORS, + EFX_MAC_FEC_CORRECTED_SYMBOLS_LANE3 }, + }; + if ((rc = efx_mac_stats_mask_add_ranges(maskp, mask_size, + ef10_fec, EFX_ARRAY_SIZE(ef10_fec))) != 0) + goto fail7; + } + + if (encp->enc_mac_stats_nstats >= MC_CMD_MAC_NSTATS_V4) { + const struct efx_mac_stats_range ef10_rxdp_sdt[] = { + { EFX_MAC_RXDP_SCATTER_DISABLED_TRUNC, + EFX_MAC_RXDP_SCATTER_DISABLED_TRUNC }, + }; + + if ((rc = efx_mac_stats_mask_add_ranges(maskp, mask_size, + ef10_rxdp_sdt, EFX_ARRAY_SIZE(ef10_rxdp_sdt))) != 0) + goto fail8; + } + + if (encp->enc_hlb_counters) { + const struct efx_mac_stats_range ef10_hlb[] = { + { EFX_MAC_RXDP_HLB_IDLE, EFX_MAC_RXDP_HLB_TIMEOUT }, + }; + if ((rc = efx_mac_stats_mask_add_ranges(maskp, mask_size, + ef10_hlb, EFX_ARRAY_SIZE(ef10_hlb))) != 0) + goto fail9; + } + return (0); +fail9: + EFSYS_PROBE(fail9); +fail8: + EFSYS_PROBE(fail8); +fail7: + EFSYS_PROBE(fail7); fail6: EFSYS_PROBE(fail6); fail5: @@ -551,16 +588,45 @@ ef10_mac_stats_update( __inout_ecount(EFX_MAC_NSTATS) efsys_stat_t *stat, __inout_opt uint32_t *generationp) { - efx_qword_t value; + const efx_nic_cfg_t *encp = &enp->en_nic_cfg; efx_qword_t generation_start; efx_qword_t generation_end; + efx_qword_t value; + efx_rc_t rc; - _NOTE(ARGUNUSED(enp)) + /* + * The MAC_STATS contain start and end generation counters used to + * detect when the DMA buffer has been updated during stats decode. + * All stats counters are 64bit unsigned values. + * + * Siena-compatible MAC stats contain MC_CMD_MAC_NSTATS 64bit counters. + * The generation end counter is at index MC_CMD_MAC_GENERATION_END + * (same as MC_CMD_MAC_NSTATS-1). + * + * Medford2 and later use a larger DMA buffer: MAC_STATS_NUM_STATS from + * MC_CMD_GET_CAPABILITIES_V4_OUT reports the number of 64bit counters. + * + * Firmware writes the generation end counter as the last counter in the + * DMA buffer. Do not use MC_CMD_MAC_GENERATION_END, as that is only + * correct for legacy Siena-compatible MAC stats. + */ + + if (encp->enc_mac_stats_nstats < MC_CMD_MAC_NSTATS) { + /* MAC stats count too small for legacy MAC stats */ + rc = ENOSPC; + goto fail1; + } + if (EFSYS_MEM_SIZE(esmp) < + (encp->enc_mac_stats_nstats * sizeof (efx_qword_t))) { + /* DMA buffer too small */ + rc = ENOSPC; + goto fail2; + } /* Read END first so we don't race with the MC */ - EFSYS_DMA_SYNC_FOR_KERNEL(esmp, 0, EFX_MAC_STATS_SIZE); - EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_GENERATION_END, - &generation_end); + EFSYS_DMA_SYNC_FOR_KERNEL(esmp, 0, EFSYS_MEM_SIZE(esmp)); + EF10_MAC_STAT_READ(esmp, (encp->enc_mac_stats_nstats - 1), + &generation_end); EFSYS_MEM_READ_BARRIER(); /* TX */ @@ -851,7 +917,109 @@ ef10_mac_stats_update( EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_VADAPTER_TX_OVERFLOW]), &value); - EFSYS_DMA_SYNC_FOR_KERNEL(esmp, 0, EFX_MAC_STATS_SIZE); + if (encp->enc_mac_stats_nstats < MC_CMD_MAC_NSTATS_V2) + goto done; + + /* FEC */ + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_FEC_UNCORRECTED_ERRORS, &value); + EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_FEC_UNCORRECTED_ERRORS]), &value); + + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_FEC_CORRECTED_ERRORS, &value); + EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_FEC_CORRECTED_ERRORS]), &value); + + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_FEC_CORRECTED_SYMBOLS_LANE0, + &value); + EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_FEC_CORRECTED_SYMBOLS_LANE0]), + &value); + + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_FEC_CORRECTED_SYMBOLS_LANE1, + &value); + EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_FEC_CORRECTED_SYMBOLS_LANE1]), + &value); + + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_FEC_CORRECTED_SYMBOLS_LANE2, + &value); + EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_FEC_CORRECTED_SYMBOLS_LANE2]), + &value); + + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_FEC_CORRECTED_SYMBOLS_LANE3, + &value); + EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_FEC_CORRECTED_SYMBOLS_LANE3]), + &value); + + if (encp->enc_mac_stats_nstats < MC_CMD_MAC_NSTATS_V3) + goto done; + + /* CTPIO exceptions */ + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_CTPIO_VI_BUSY_FALLBACK, &value); + EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_CTPIO_VI_BUSY_FALLBACK]), &value); + + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_CTPIO_LONG_WRITE_SUCCESS, &value); + EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_CTPIO_LONG_WRITE_SUCCESS]), &value); + + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_CTPIO_MISSING_DBELL_FAIL, &value); + EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_CTPIO_MISSING_DBELL_FAIL]), &value); + + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_CTPIO_OVERFLOW_FAIL, &value); + EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_CTPIO_OVERFLOW_FAIL]), &value); + + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_CTPIO_UNDERFLOW_FAIL, &value); + EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_CTPIO_UNDERFLOW_FAIL]), &value); + + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_CTPIO_TIMEOUT_FAIL, &value); + EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_CTPIO_TIMEOUT_FAIL]), &value); + + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_CTPIO_NONCONTIG_WR_FAIL, &value); + EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_CTPIO_NONCONTIG_WR_FAIL]), &value); + + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_CTPIO_FRM_CLOBBER_FAIL, &value); + EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_CTPIO_FRM_CLOBBER_FAIL]), &value); + + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_CTPIO_INVALID_WR_FAIL, &value); + EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_CTPIO_INVALID_WR_FAIL]), &value); + + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_CTPIO_VI_CLOBBER_FALLBACK, &value); + EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_CTPIO_VI_CLOBBER_FALLBACK]), + &value); + + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_CTPIO_UNQUALIFIED_FALLBACK, &value); + EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_CTPIO_UNQUALIFIED_FALLBACK]), + &value); + + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_CTPIO_RUNT_FALLBACK, &value); + EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_CTPIO_RUNT_FALLBACK]), &value); + + /* CTPIO per-port stats */ + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_CTPIO_SUCCESS, &value); + EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_CTPIO_SUCCESS]), &value); + + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_CTPIO_FALLBACK, &value); + EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_CTPIO_FALLBACK]), &value); + + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_CTPIO_POISON, &value); + EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_CTPIO_POISON]), &value); + + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_CTPIO_ERASE, &value); + EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_CTPIO_ERASE]), &value); + + if (encp->enc_mac_stats_nstats < MC_CMD_MAC_NSTATS_V4) + goto done; + + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RXDP_SCATTER_DISABLED_TRUNC, + &value); + EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RXDP_SCATTER_DISABLED_TRUNC]), + &value); + + /* Head-of-line blocking */ + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RXDP_HLB_IDLE, &value); + EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RXDP_HLB_IDLE]), &value); + + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RXDP_HLB_TIMEOUT, &value); + EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RXDP_HLB_TIMEOUT]), &value); + +done: + /* Read START generation counter */ + EFSYS_DMA_SYNC_FOR_KERNEL(esmp, 0, EFSYS_MEM_SIZE(esmp)); EFSYS_MEM_READ_BARRIER(); EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_GENERATION_START, &generation_start); @@ -866,8 +1034,15 @@ ef10_mac_stats_update( *generationp = EFX_QWORD_FIELD(generation_start, EFX_DWORD_0); return (0); + +fail2: + EFSYS_PROBE(fail2); +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + + return (rc); } #endif /* EFSYS_OPT_MAC_STATS */ -#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */ +#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */ |