net/sfc/base: import PHY statistics
authorAndrew Rybchenko <arybchenko@solarflare.com>
Tue, 29 Nov 2016 16:18:48 +0000 (16:18 +0000)
committerFerruh Yigit <ferruh.yigit@intel.com>
Tue, 17 Jan 2017 18:39:26 +0000 (19:39 +0100)
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>
drivers/net/sfc/base/ef10_impl.h
drivers/net/sfc/base/ef10_phy.c
drivers/net/sfc/base/efx.h
drivers/net/sfc/base/efx_check.h
drivers/net/sfc/base/efx_impl.h
drivers/net/sfc/base/efx_mcdi.c
drivers/net/sfc/base/efx_phy.c
drivers/net/sfc/base/siena_impl.h
drivers/net/sfc/base/siena_nic.c
drivers/net/sfc/base/siena_phy.c

index 3af5b0a..3efba1f 100644 (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
index c7e584b..b15b693 100644 (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
index 54d39c2..d2fe43e 100644 (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;
index 68c01f3..adda531 100644 (file)
 # 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
index 489fcbc..2b81768 100644 (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);
index 85c1ac1..c5422da 100644 (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,
index f07f127..20debd3 100644 (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 @@ fail1:
        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
 
index bdaa4a3..fc01205 100644 (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
index 2d079c2..135f705 100644 (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:
index 6451298..73690f1 100644 (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