net/sfc/base: import PHY statistics

EFSYS_OPT_PHY_STATS should be enabled to use it.

From Solarflare Communications Inc.

Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
This commit is contained in:
Andrew Rybchenko 2016-11-29 16:18:48 +00:00 committed by Ferruh Yigit
parent 8bc0b2bd78
commit 0a78643491
10 changed files with 392 additions and 0 deletions

View File

@ -352,6 +352,16 @@ ef10_phy_oui_get(
__in efx_nic_t *enp,
__out uint32_t *ouip);
#if EFSYS_OPT_PHY_STATS
extern __checkReturn efx_rc_t
ef10_phy_stats_update(
__in efx_nic_t *enp,
__in efsys_mem_t *esmp,
__inout_ecount(EFX_PHY_NSTATS) uint32_t *stat);
#endif /* EFSYS_OPT_PHY_STATS */
#if EFSYS_OPT_BIST
extern __checkReturn efx_rc_t

View File

@ -394,6 +394,23 @@ ef10_phy_oui_get(
return (ENOTSUP);
}
#if EFSYS_OPT_PHY_STATS
__checkReturn efx_rc_t
ef10_phy_stats_update(
__in efx_nic_t *enp,
__in efsys_mem_t *esmp,
__inout_ecount(EFX_PHY_NSTATS) uint32_t *stat)
{
/* TBD: no stats support in firmware yet */
_NOTE(ARGUNUSED(enp, esmp))
memset(stat, 0, EFX_PHY_NSTATS * sizeof (*stat));
return (0);
}
#endif /* EFSYS_OPT_PHY_STATS */
#if EFSYS_OPT_BIST
__checkReturn efx_rc_t

View File

@ -548,6 +548,80 @@ efx_phy_module_get_info(
__in uint8_t len,
__out_bcount(len) uint8_t *data);
#if EFSYS_OPT_PHY_STATS
/* START MKCONFIG GENERATED PhyHeaderStatsBlock 30ed56ad501f8e36 */
typedef enum efx_phy_stat_e {
EFX_PHY_STAT_OUI,
EFX_PHY_STAT_PMA_PMD_LINK_UP,
EFX_PHY_STAT_PMA_PMD_RX_FAULT,
EFX_PHY_STAT_PMA_PMD_TX_FAULT,
EFX_PHY_STAT_PMA_PMD_REV_A,
EFX_PHY_STAT_PMA_PMD_REV_B,
EFX_PHY_STAT_PMA_PMD_REV_C,
EFX_PHY_STAT_PMA_PMD_REV_D,
EFX_PHY_STAT_PCS_LINK_UP,
EFX_PHY_STAT_PCS_RX_FAULT,
EFX_PHY_STAT_PCS_TX_FAULT,
EFX_PHY_STAT_PCS_BER,
EFX_PHY_STAT_PCS_BLOCK_ERRORS,
EFX_PHY_STAT_PHY_XS_LINK_UP,
EFX_PHY_STAT_PHY_XS_RX_FAULT,
EFX_PHY_STAT_PHY_XS_TX_FAULT,
EFX_PHY_STAT_PHY_XS_ALIGN,
EFX_PHY_STAT_PHY_XS_SYNC_A,
EFX_PHY_STAT_PHY_XS_SYNC_B,
EFX_PHY_STAT_PHY_XS_SYNC_C,
EFX_PHY_STAT_PHY_XS_SYNC_D,
EFX_PHY_STAT_AN_LINK_UP,
EFX_PHY_STAT_AN_MASTER,
EFX_PHY_STAT_AN_LOCAL_RX_OK,
EFX_PHY_STAT_AN_REMOTE_RX_OK,
EFX_PHY_STAT_CL22EXT_LINK_UP,
EFX_PHY_STAT_SNR_A,
EFX_PHY_STAT_SNR_B,
EFX_PHY_STAT_SNR_C,
EFX_PHY_STAT_SNR_D,
EFX_PHY_STAT_PMA_PMD_SIGNAL_A,
EFX_PHY_STAT_PMA_PMD_SIGNAL_B,
EFX_PHY_STAT_PMA_PMD_SIGNAL_C,
EFX_PHY_STAT_PMA_PMD_SIGNAL_D,
EFX_PHY_STAT_AN_COMPLETE,
EFX_PHY_STAT_PMA_PMD_REV_MAJOR,
EFX_PHY_STAT_PMA_PMD_REV_MINOR,
EFX_PHY_STAT_PMA_PMD_REV_MICRO,
EFX_PHY_STAT_PCS_FW_VERSION_0,
EFX_PHY_STAT_PCS_FW_VERSION_1,
EFX_PHY_STAT_PCS_FW_VERSION_2,
EFX_PHY_STAT_PCS_FW_VERSION_3,
EFX_PHY_STAT_PCS_FW_BUILD_YY,
EFX_PHY_STAT_PCS_FW_BUILD_MM,
EFX_PHY_STAT_PCS_FW_BUILD_DD,
EFX_PHY_STAT_PCS_OP_MODE,
EFX_PHY_NSTATS
} efx_phy_stat_t;
/* END MKCONFIG GENERATED PhyHeaderStatsBlock */
#if EFSYS_OPT_NAMES
extern const char *
efx_phy_stat_name(
__in efx_nic_t *enp,
__in efx_phy_stat_t stat);
#endif /* EFSYS_OPT_NAMES */
#define EFX_PHY_STATS_SIZE 0x100
extern __checkReturn efx_rc_t
efx_phy_stats_update(
__in efx_nic_t *enp,
__in efsys_mem_t *esmp,
__inout_ecount(EFX_PHY_NSTATS) uint32_t *stat);
#endif /* EFSYS_OPT_PHY_STATS */
#if EFSYS_OPT_BIST
@ -671,8 +745,14 @@ typedef struct efx_nic_cfg_s {
#if EFSYS_OPT_PHY_FLAGS
uint32_t enc_phy_flags_mask;
#endif /* EFSYS_OPT_PHY_FLAGS */
#if EFSYS_OPT_PHY_STATS
uint64_t enc_phy_stat_mask;
#endif /* EFSYS_OPT_PHY_STATS */
#if EFSYS_OPT_MCDI
uint8_t enc_mcdi_mdio_channel;
#if EFSYS_OPT_PHY_STATS
uint32_t enc_mcdi_phy_stat_mask;
#endif /* EFSYS_OPT_PHY_STATS */
#endif /* EFSYS_OPT_MCDI */
#if EFSYS_OPT_BIST
uint32_t enc_bist_mask;

View File

@ -201,6 +201,13 @@
# error "PHY_SFX7101 is obsolete and is not supported."
#endif
#if EFSYS_OPT_PHY_STATS
/* Support PHY statistics */
# if !EFSYS_OPT_SIENA
# error "PHY_STATS requires SIENA"
# endif
#endif /* EFSYS_OPT_PHY_STATS */
#ifdef EFSYS_OPT_PHY_TXC43128
# error "PHY_TXC43128 is obsolete and is not supported."
#endif

View File

@ -182,6 +182,10 @@ typedef struct efx_phy_ops_s {
efx_rc_t (*epo_reconfigure)(efx_nic_t *);
efx_rc_t (*epo_verify)(efx_nic_t *);
efx_rc_t (*epo_oui_get)(efx_nic_t *, uint32_t *);
#if EFSYS_OPT_PHY_STATS
efx_rc_t (*epo_stats_update)(efx_nic_t *, efsys_mem_t *,
uint32_t *);
#endif /* EFSYS_OPT_PHY_STATS */
#if EFSYS_OPT_BIST
efx_rc_t (*epo_bist_enable_offline)(efx_nic_t *);
efx_rc_t (*epo_bist_start)(efx_nic_t *, efx_bist_type_t);

View File

@ -1435,6 +1435,11 @@ efx_mcdi_get_phy_cfg(
encp->enc_mcdi_mdio_channel =
(uint8_t)MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_CHANNEL);
#if EFSYS_OPT_PHY_STATS
encp->enc_mcdi_phy_stat_mask =
MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_STATS_MASK);
#endif /* EFSYS_OPT_PHY_STATS */
#if EFSYS_OPT_BIST
encp->enc_bist_mask = 0;
if (MCDI_OUT_DWORD_FIELD(req, GET_PHY_CFG_OUT_FLAGS,

View File

@ -39,6 +39,9 @@ static const efx_phy_ops_t __efx_phy_siena_ops = {
siena_phy_reconfigure, /* epo_reconfigure */
siena_phy_verify, /* epo_verify */
siena_phy_oui_get, /* epo_oui_get */
#if EFSYS_OPT_PHY_STATS
siena_phy_stats_update, /* epo_stats_update */
#endif /* EFSYS_OPT_PHY_STATS */
#if EFSYS_OPT_BIST
NULL, /* epo_bist_enable_offline */
siena_phy_bist_start, /* epo_bist_start */
@ -55,6 +58,9 @@ static const efx_phy_ops_t __efx_phy_ef10_ops = {
ef10_phy_reconfigure, /* epo_reconfigure */
ef10_phy_verify, /* epo_verify */
ef10_phy_oui_get, /* epo_oui_get */
#if EFSYS_OPT_PHY_STATS
ef10_phy_stats_update, /* epo_stats_update */
#endif /* EFSYS_OPT_PHY_STATS */
#if EFSYS_OPT_BIST
ef10_bist_enable_offline, /* epo_bist_enable_offline */
ef10_bist_start, /* epo_bist_start */
@ -277,6 +283,93 @@ efx_phy_module_get_info(
return (rc);
}
#if EFSYS_OPT_PHY_STATS
#if EFSYS_OPT_NAMES
/* START MKCONFIG GENERATED PhyStatNamesBlock af9ffa24da3bc100 */
static const char * const __efx_phy_stat_name[] = {
"oui",
"pma_pmd_link_up",
"pma_pmd_rx_fault",
"pma_pmd_tx_fault",
"pma_pmd_rev_a",
"pma_pmd_rev_b",
"pma_pmd_rev_c",
"pma_pmd_rev_d",
"pcs_link_up",
"pcs_rx_fault",
"pcs_tx_fault",
"pcs_ber",
"pcs_block_errors",
"phy_xs_link_up",
"phy_xs_rx_fault",
"phy_xs_tx_fault",
"phy_xs_align",
"phy_xs_sync_a",
"phy_xs_sync_b",
"phy_xs_sync_c",
"phy_xs_sync_d",
"an_link_up",
"an_master",
"an_local_rx_ok",
"an_remote_rx_ok",
"cl22ext_link_up",
"snr_a",
"snr_b",
"snr_c",
"snr_d",
"pma_pmd_signal_a",
"pma_pmd_signal_b",
"pma_pmd_signal_c",
"pma_pmd_signal_d",
"an_complete",
"pma_pmd_rev_major",
"pma_pmd_rev_minor",
"pma_pmd_rev_micro",
"pcs_fw_version_0",
"pcs_fw_version_1",
"pcs_fw_version_2",
"pcs_fw_version_3",
"pcs_fw_build_yy",
"pcs_fw_build_mm",
"pcs_fw_build_dd",
"pcs_op_mode",
};
/* END MKCONFIG GENERATED PhyStatNamesBlock */
const char *
efx_phy_stat_name(
__in efx_nic_t *enp,
__in efx_phy_stat_t type)
{
_NOTE(ARGUNUSED(enp))
EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
EFSYS_ASSERT3U(type, <, EFX_PHY_NSTATS);
return (__efx_phy_stat_name[type]);
}
#endif /* EFSYS_OPT_NAMES */
__checkReturn efx_rc_t
efx_phy_stats_update(
__in efx_nic_t *enp,
__in efsys_mem_t *esmp,
__inout_ecount(EFX_PHY_NSTATS) uint32_t *stat)
{
efx_port_t *epp = &(enp->en_port);
const efx_phy_ops_t *epop = epp->ep_epop;
EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
return (epop->epo_stats_update(enp, esmp, stat));
}
#endif /* EFSYS_OPT_PHY_STATS */
#if EFSYS_OPT_BIST

View File

@ -170,6 +170,24 @@ siena_phy_oui_get(
__in efx_nic_t *enp,
__out uint32_t *ouip);
#if EFSYS_OPT_PHY_STATS
extern void
siena_phy_decode_stats(
__in efx_nic_t *enp,
__in uint32_t vmask,
__in_opt efsys_mem_t *esmp,
__out_opt uint64_t *smaskp,
__inout_ecount_opt(EFX_PHY_NSTATS) uint32_t *stat);
extern __checkReturn efx_rc_t
siena_phy_stats_update(
__in efx_nic_t *enp,
__in efsys_mem_t *esmp,
__inout_ecount(EFX_PHY_NSTATS) uint32_t *stat);
#endif /* EFSYS_OPT_PHY_STATS */
#if EFSYS_OPT_BIST
extern __checkReturn efx_rc_t

View File

@ -145,6 +145,12 @@ siena_phy_cfg(
if ((rc = efx_mcdi_get_phy_cfg(enp)) != 0)
goto fail1;
#if EFSYS_OPT_PHY_STATS
/* Convert the MCDI statistic mask into the EFX_PHY_STAT mask */
siena_phy_decode_stats(enp, encp->enc_mcdi_phy_stat_mask,
NULL, &encp->enc_phy_stat_mask, NULL);
#endif /* EFSYS_OPT_PHY_STATS */
return (0);
fail1:

View File

@ -376,6 +376,158 @@ siena_phy_oui_get(
return (ENOTSUP);
}
#if EFSYS_OPT_PHY_STATS
#define SIENA_SIMPLE_STAT_SET(_vmask, _esmp, _smask, _stat, \
_mc_record, _efx_record) \
if ((_vmask) & (1ULL << (_mc_record))) { \
(_smask) |= (1ULL << (_efx_record)); \
if ((_stat) != NULL && !EFSYS_MEM_IS_NULL(_esmp)) { \
efx_dword_t dword; \
EFSYS_MEM_READD(_esmp, (_mc_record) * 4, &dword);\
(_stat)[_efx_record] = \
EFX_DWORD_FIELD(dword, EFX_DWORD_0); \
} \
}
#define SIENA_SIMPLE_STAT_SET2(_vmask, _esmp, _smask, _stat, _record) \
SIENA_SIMPLE_STAT_SET(_vmask, _esmp, _smask, _stat, \
MC_CMD_ ## _record, \
EFX_PHY_STAT_ ## _record)
void
siena_phy_decode_stats(
__in efx_nic_t *enp,
__in uint32_t vmask,
__in_opt efsys_mem_t *esmp,
__out_opt uint64_t *smaskp,
__inout_ecount_opt(EFX_PHY_NSTATS) uint32_t *stat)
{
uint64_t smask = 0;
_NOTE(ARGUNUSED(enp))
SIENA_SIMPLE_STAT_SET2(vmask, esmp, smask, stat, OUI);
SIENA_SIMPLE_STAT_SET2(vmask, esmp, smask, stat, PMA_PMD_LINK_UP);
SIENA_SIMPLE_STAT_SET2(vmask, esmp, smask, stat, PMA_PMD_RX_FAULT);
SIENA_SIMPLE_STAT_SET2(vmask, esmp, smask, stat, PMA_PMD_TX_FAULT);
if (vmask & (1 << MC_CMD_PMA_PMD_SIGNAL)) {
smask |= ((1ULL << EFX_PHY_STAT_PMA_PMD_SIGNAL_A) |
(1ULL << EFX_PHY_STAT_PMA_PMD_SIGNAL_B) |
(1ULL << EFX_PHY_STAT_PMA_PMD_SIGNAL_C) |
(1ULL << EFX_PHY_STAT_PMA_PMD_SIGNAL_D));
if (stat != NULL && esmp != NULL && !EFSYS_MEM_IS_NULL(esmp)) {
efx_dword_t dword;
uint32_t sig;
EFSYS_MEM_READD(esmp, 4 * MC_CMD_PMA_PMD_SIGNAL,
&dword);
sig = EFX_DWORD_FIELD(dword, EFX_DWORD_0);
stat[EFX_PHY_STAT_PMA_PMD_SIGNAL_A] = (sig >> 1) & 1;
stat[EFX_PHY_STAT_PMA_PMD_SIGNAL_B] = (sig >> 2) & 1;
stat[EFX_PHY_STAT_PMA_PMD_SIGNAL_C] = (sig >> 3) & 1;
stat[EFX_PHY_STAT_PMA_PMD_SIGNAL_D] = (sig >> 4) & 1;
}
}
SIENA_SIMPLE_STAT_SET(vmask, esmp, smask, stat, MC_CMD_PMA_PMD_SNR_A,
EFX_PHY_STAT_SNR_A);
SIENA_SIMPLE_STAT_SET(vmask, esmp, smask, stat, MC_CMD_PMA_PMD_SNR_B,
EFX_PHY_STAT_SNR_B);
SIENA_SIMPLE_STAT_SET(vmask, esmp, smask, stat, MC_CMD_PMA_PMD_SNR_C,
EFX_PHY_STAT_SNR_C);
SIENA_SIMPLE_STAT_SET(vmask, esmp, smask, stat, MC_CMD_PMA_PMD_SNR_D,
EFX_PHY_STAT_SNR_D);
SIENA_SIMPLE_STAT_SET2(vmask, esmp, smask, stat, PCS_LINK_UP);
SIENA_SIMPLE_STAT_SET2(vmask, esmp, smask, stat, PCS_RX_FAULT);
SIENA_SIMPLE_STAT_SET2(vmask, esmp, smask, stat, PCS_TX_FAULT);
SIENA_SIMPLE_STAT_SET2(vmask, esmp, smask, stat, PCS_BER);
SIENA_SIMPLE_STAT_SET2(vmask, esmp, smask, stat, PCS_BLOCK_ERRORS);
SIENA_SIMPLE_STAT_SET(vmask, esmp, smask, stat, MC_CMD_PHYXS_LINK_UP,
EFX_PHY_STAT_PHY_XS_LINK_UP);
SIENA_SIMPLE_STAT_SET(vmask, esmp, smask, stat, MC_CMD_PHYXS_RX_FAULT,
EFX_PHY_STAT_PHY_XS_RX_FAULT);
SIENA_SIMPLE_STAT_SET(vmask, esmp, smask, stat, MC_CMD_PHYXS_TX_FAULT,
EFX_PHY_STAT_PHY_XS_TX_FAULT);
SIENA_SIMPLE_STAT_SET(vmask, esmp, smask, stat, MC_CMD_PHYXS_ALIGN,
EFX_PHY_STAT_PHY_XS_ALIGN);
if (vmask & (1 << MC_CMD_PHYXS_SYNC)) {
smask |= ((1 << EFX_PHY_STAT_PHY_XS_SYNC_A) |
(1 << EFX_PHY_STAT_PHY_XS_SYNC_B) |
(1 << EFX_PHY_STAT_PHY_XS_SYNC_C) |
(1 << EFX_PHY_STAT_PHY_XS_SYNC_D));
if (stat != NULL && !EFSYS_MEM_IS_NULL(esmp)) {
efx_dword_t dword;
uint32_t sync;
EFSYS_MEM_READD(esmp, 4 * MC_CMD_PHYXS_SYNC, &dword);
sync = EFX_DWORD_FIELD(dword, EFX_DWORD_0);
stat[EFX_PHY_STAT_PHY_XS_SYNC_A] = (sync >> 0) & 1;
stat[EFX_PHY_STAT_PHY_XS_SYNC_B] = (sync >> 1) & 1;
stat[EFX_PHY_STAT_PHY_XS_SYNC_C] = (sync >> 2) & 1;
stat[EFX_PHY_STAT_PHY_XS_SYNC_D] = (sync >> 3) & 1;
}
}
SIENA_SIMPLE_STAT_SET2(vmask, esmp, smask, stat, AN_LINK_UP);
SIENA_SIMPLE_STAT_SET2(vmask, esmp, smask, stat, AN_COMPLETE);
SIENA_SIMPLE_STAT_SET(vmask, esmp, smask, stat, MC_CMD_CL22_LINK_UP,
EFX_PHY_STAT_CL22EXT_LINK_UP);
if (smaskp != NULL)
*smaskp = smask;
}
__checkReturn efx_rc_t
siena_phy_stats_update(
__in efx_nic_t *enp,
__in efsys_mem_t *esmp,
__inout_ecount(EFX_PHY_NSTATS) uint32_t *stat)
{
efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
uint32_t vmask = encp->enc_mcdi_phy_stat_mask;
uint64_t smask;
efx_mcdi_req_t req;
uint8_t payload[MAX(MC_CMD_PHY_STATS_IN_LEN,
MC_CMD_PHY_STATS_OUT_DMA_LEN)];
efx_rc_t rc;
(void) memset(payload, 0, sizeof (payload));
req.emr_cmd = MC_CMD_PHY_STATS;
req.emr_in_buf = payload;
req.emr_in_length = MC_CMD_PHY_STATS_IN_LEN;
req.emr_out_buf = payload;
req.emr_out_length = MC_CMD_PHY_STATS_OUT_DMA_LEN;
MCDI_IN_SET_DWORD(req, PHY_STATS_IN_DMA_ADDR_LO,
EFSYS_MEM_ADDR(esmp) & 0xffffffff);
MCDI_IN_SET_DWORD(req, PHY_STATS_IN_DMA_ADDR_HI,
EFSYS_MEM_ADDR(esmp) >> 32);
efx_mcdi_execute(enp, &req);
if (req.emr_rc != 0) {
rc = req.emr_rc;
goto fail1;
}
EFSYS_ASSERT3U(req.emr_out_length, ==, MC_CMD_PHY_STATS_OUT_DMA_LEN);
siena_phy_decode_stats(enp, vmask, esmp, &smask, stat);
EFSYS_ASSERT(smask == encp->enc_phy_stat_mask);
return (0);
fail1:
EFSYS_PROBE1(fail1, efx_rc_t, rc);
return (0);
}
#endif /* EFSYS_OPT_PHY_STATS */
#if EFSYS_OPT_BIST
__checkReturn efx_rc_t