net/sfc/base: import loopback control
EFSYS_OPT_LOOPBACK 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:
parent
5935cd8c47
commit
9ee64bd404
@ -259,6 +259,16 @@ extern void
|
||||
ef10_mac_filter_default_rxq_clear(
|
||||
__in efx_nic_t *enp);
|
||||
|
||||
#if EFSYS_OPT_LOOPBACK
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
ef10_mac_loopback_set(
|
||||
__in efx_nic_t *enp,
|
||||
__in efx_link_mode_t link_mode,
|
||||
__in efx_loopback_type_t loopback_type);
|
||||
|
||||
#endif /* EFSYS_OPT_LOOPBACK */
|
||||
|
||||
#if EFSYS_OPT_MAC_STATS
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
@ -337,6 +347,9 @@ typedef struct ef10_link_state_s {
|
||||
uint32_t els_lp_cap_mask;
|
||||
unsigned int els_fcntl;
|
||||
efx_link_mode_t els_link_mode;
|
||||
#if EFSYS_OPT_LOOPBACK
|
||||
efx_loopback_type_t els_loopback;
|
||||
#endif
|
||||
boolean_t els_mac_up;
|
||||
} ef10_link_state_t;
|
||||
|
||||
|
@ -443,6 +443,42 @@ ef10_mac_filter_default_rxq_clear(
|
||||
}
|
||||
|
||||
|
||||
#if EFSYS_OPT_LOOPBACK
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
ef10_mac_loopback_set(
|
||||
__in efx_nic_t *enp,
|
||||
__in efx_link_mode_t link_mode,
|
||||
__in efx_loopback_type_t loopback_type)
|
||||
{
|
||||
efx_port_t *epp = &(enp->en_port);
|
||||
const efx_phy_ops_t *epop = epp->ep_epop;
|
||||
efx_loopback_type_t old_loopback_type;
|
||||
efx_link_mode_t old_loopback_link_mode;
|
||||
efx_rc_t rc;
|
||||
|
||||
/* The PHY object handles this on EF10 */
|
||||
old_loopback_type = epp->ep_loopback_type;
|
||||
old_loopback_link_mode = epp->ep_loopback_link_mode;
|
||||
epp->ep_loopback_type = loopback_type;
|
||||
epp->ep_loopback_link_mode = link_mode;
|
||||
|
||||
if ((rc = epop->epo_reconfigure(enp)) != 0)
|
||||
goto fail1;
|
||||
|
||||
return (0);
|
||||
|
||||
fail1:
|
||||
EFSYS_PROBE1(fail1, efx_rc_t, rc);
|
||||
|
||||
epp->ep_loopback_type = old_loopback_type;
|
||||
epp->ep_loopback_link_mode = old_loopback_link_mode;
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
#endif /* EFSYS_OPT_LOOPBACK */
|
||||
|
||||
#if EFSYS_OPT_MAC_STATS
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
|
@ -1377,10 +1377,19 @@ ef10_nic_probe(
|
||||
goto fail5;
|
||||
#endif
|
||||
|
||||
#if EFSYS_OPT_LOOPBACK
|
||||
if ((rc = efx_mcdi_get_loopback_modes(enp)) != 0)
|
||||
goto fail6;
|
||||
#endif
|
||||
|
||||
encp->enc_features = enp->en_features;
|
||||
|
||||
return (0);
|
||||
|
||||
#if EFSYS_OPT_LOOPBACK
|
||||
fail6:
|
||||
EFSYS_PROBE(fail6);
|
||||
#endif
|
||||
#if EFSYS_OPT_MAC_STATS
|
||||
fail5:
|
||||
EFSYS_PROBE(fail5);
|
||||
|
@ -235,6 +235,30 @@ ef10_phy_get_link(
|
||||
MCDI_OUT_DWORD(req, GET_LINK_OUT_FCNTL),
|
||||
&elsp->els_link_mode, &elsp->els_fcntl);
|
||||
|
||||
#if EFSYS_OPT_LOOPBACK
|
||||
/* Assert the MC_CMD_LOOPBACK and EFX_LOOPBACK namespace agree */
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_NONE == EFX_LOOPBACK_OFF);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_DATA == EFX_LOOPBACK_DATA);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GMAC == EFX_LOOPBACK_GMAC);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XGMII == EFX_LOOPBACK_XGMII);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XGXS == EFX_LOOPBACK_XGXS);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XAUI == EFX_LOOPBACK_XAUI);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GMII == EFX_LOOPBACK_GMII);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SGMII == EFX_LOOPBACK_SGMII);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XGBR == EFX_LOOPBACK_XGBR);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XFI == EFX_LOOPBACK_XFI);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XAUI_FAR == EFX_LOOPBACK_XAUI_FAR);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GMII_FAR == EFX_LOOPBACK_GMII_FAR);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SGMII_FAR == EFX_LOOPBACK_SGMII_FAR);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XFI_FAR == EFX_LOOPBACK_XFI_FAR);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GPHY == EFX_LOOPBACK_GPHY);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PHYXS == EFX_LOOPBACK_PHY_XS);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PCS == EFX_LOOPBACK_PCS);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PMAPMD == EFX_LOOPBACK_PMA_PMD);
|
||||
|
||||
elsp->els_loopback = MCDI_OUT_DWORD(req, GET_LINK_OUT_LOOPBACK_MODE);
|
||||
#endif /* EFSYS_OPT_LOOPBACK */
|
||||
|
||||
elsp->els_mac_up = MCDI_OUT_DWORD(req, GET_LINK_OUT_MAC_FAULT) == 0;
|
||||
|
||||
return (0);
|
||||
@ -289,8 +313,29 @@ ef10_phy_reconfigure(
|
||||
MCDI_IN_SET_DWORD_FIELD(req, SET_LINK_IN_CAP,
|
||||
PHY_CAP_40000FDX, (cap_mask >> EFX_PHY_CAP_40000FDX) & 0x1);
|
||||
|
||||
#if EFSYS_OPT_LOOPBACK
|
||||
MCDI_IN_SET_DWORD(req, SET_LINK_IN_LOOPBACK_MODE,
|
||||
epp->ep_loopback_type);
|
||||
switch (epp->ep_loopback_link_mode) {
|
||||
case EFX_LINK_100FDX:
|
||||
speed = 100;
|
||||
break;
|
||||
case EFX_LINK_1000FDX:
|
||||
speed = 1000;
|
||||
break;
|
||||
case EFX_LINK_10000FDX:
|
||||
speed = 10000;
|
||||
break;
|
||||
case EFX_LINK_40000FDX:
|
||||
speed = 40000;
|
||||
break;
|
||||
default:
|
||||
speed = 0;
|
||||
}
|
||||
#else
|
||||
MCDI_IN_SET_DWORD(req, SET_LINK_IN_LOOPBACK_MODE, MC_CMD_LOOPBACK_NONE);
|
||||
speed = 0;
|
||||
#endif /* EFSYS_OPT_LOOPBACK */
|
||||
MCDI_IN_SET_DWORD(req, SET_LINK_IN_LOOPBACK_SPEED, speed);
|
||||
|
||||
#if EFSYS_OPT_PHY_FLAGS
|
||||
|
@ -646,6 +646,77 @@ extern __checkReturn efx_rc_t
|
||||
efx_port_init(
|
||||
__in efx_nic_t *enp);
|
||||
|
||||
#if EFSYS_OPT_LOOPBACK
|
||||
|
||||
typedef enum efx_loopback_type_e {
|
||||
EFX_LOOPBACK_OFF = 0,
|
||||
EFX_LOOPBACK_DATA = 1,
|
||||
EFX_LOOPBACK_GMAC = 2,
|
||||
EFX_LOOPBACK_XGMII = 3,
|
||||
EFX_LOOPBACK_XGXS = 4,
|
||||
EFX_LOOPBACK_XAUI = 5,
|
||||
EFX_LOOPBACK_GMII = 6,
|
||||
EFX_LOOPBACK_SGMII = 7,
|
||||
EFX_LOOPBACK_XGBR = 8,
|
||||
EFX_LOOPBACK_XFI = 9,
|
||||
EFX_LOOPBACK_XAUI_FAR = 10,
|
||||
EFX_LOOPBACK_GMII_FAR = 11,
|
||||
EFX_LOOPBACK_SGMII_FAR = 12,
|
||||
EFX_LOOPBACK_XFI_FAR = 13,
|
||||
EFX_LOOPBACK_GPHY = 14,
|
||||
EFX_LOOPBACK_PHY_XS = 15,
|
||||
EFX_LOOPBACK_PCS = 16,
|
||||
EFX_LOOPBACK_PMA_PMD = 17,
|
||||
EFX_LOOPBACK_XPORT = 18,
|
||||
EFX_LOOPBACK_XGMII_WS = 19,
|
||||
EFX_LOOPBACK_XAUI_WS = 20,
|
||||
EFX_LOOPBACK_XAUI_WS_FAR = 21,
|
||||
EFX_LOOPBACK_XAUI_WS_NEAR = 22,
|
||||
EFX_LOOPBACK_GMII_WS = 23,
|
||||
EFX_LOOPBACK_XFI_WS = 24,
|
||||
EFX_LOOPBACK_XFI_WS_FAR = 25,
|
||||
EFX_LOOPBACK_PHYXS_WS = 26,
|
||||
EFX_LOOPBACK_PMA_INT = 27,
|
||||
EFX_LOOPBACK_SD_NEAR = 28,
|
||||
EFX_LOOPBACK_SD_FAR = 29,
|
||||
EFX_LOOPBACK_PMA_INT_WS = 30,
|
||||
EFX_LOOPBACK_SD_FEP2_WS = 31,
|
||||
EFX_LOOPBACK_SD_FEP1_5_WS = 32,
|
||||
EFX_LOOPBACK_SD_FEP_WS = 33,
|
||||
EFX_LOOPBACK_SD_FES_WS = 34,
|
||||
EFX_LOOPBACK_NTYPES
|
||||
} efx_loopback_type_t;
|
||||
|
||||
typedef enum efx_loopback_kind_e {
|
||||
EFX_LOOPBACK_KIND_OFF = 0,
|
||||
EFX_LOOPBACK_KIND_ALL,
|
||||
EFX_LOOPBACK_KIND_MAC,
|
||||
EFX_LOOPBACK_KIND_PHY,
|
||||
EFX_LOOPBACK_NKINDS
|
||||
} efx_loopback_kind_t;
|
||||
|
||||
extern void
|
||||
efx_loopback_mask(
|
||||
__in efx_loopback_kind_t loopback_kind,
|
||||
__out efx_qword_t *maskp);
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
efx_port_loopback_set(
|
||||
__in efx_nic_t *enp,
|
||||
__in efx_link_mode_t link_mode,
|
||||
__in efx_loopback_type_t type);
|
||||
|
||||
#if EFSYS_OPT_NAMES
|
||||
|
||||
extern __checkReturn const char *
|
||||
efx_loopback_type_name(
|
||||
__in efx_nic_t *enp,
|
||||
__in efx_loopback_type_t type);
|
||||
|
||||
#endif /* EFSYS_OPT_NAMES */
|
||||
|
||||
#endif /* EFSYS_OPT_LOOPBACK */
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
efx_port_poll(
|
||||
__in efx_nic_t *enp,
|
||||
@ -921,6 +992,9 @@ typedef struct efx_nic_cfg_s {
|
||||
uint32_t enc_rx_prefix_size;
|
||||
uint32_t enc_rx_buf_align_start;
|
||||
uint32_t enc_rx_buf_align_end;
|
||||
#if EFSYS_OPT_LOOPBACK
|
||||
efx_qword_t enc_loopback_types[EFX_LINK_NMODES];
|
||||
#endif /* EFSYS_OPT_LOOPBACK */
|
||||
#if EFSYS_OPT_PHY_FLAGS
|
||||
uint32_t enc_phy_flags_mask;
|
||||
#endif /* EFSYS_OPT_PHY_FLAGS */
|
||||
|
@ -90,6 +90,13 @@
|
||||
# endif
|
||||
#endif /* EFSYS_OPT_HUNTINGTON */
|
||||
|
||||
#if EFSYS_OPT_LOOPBACK
|
||||
/* Support hardware loopback modes */
|
||||
# if !(EFSYS_OPT_SIENA || EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD)
|
||||
# error "LOOPBACK requires SIENA or HUNTINGTON or MEDFORD"
|
||||
# endif
|
||||
#endif /* EFSYS_OPT_LOOPBACK */
|
||||
|
||||
#ifdef EFSYS_OPT_MAC_FALCON_GMAC
|
||||
# error "MAC_FALCON_GMAC is obsolete and is not supported."
|
||||
#endif
|
||||
|
@ -186,6 +186,10 @@ typedef struct efx_mac_ops_s {
|
||||
efx_rc_t (*emo_filter_default_rxq_set)(efx_nic_t *,
|
||||
efx_rxq_t *, boolean_t);
|
||||
void (*emo_filter_default_rxq_clear)(efx_nic_t *);
|
||||
#if EFSYS_OPT_LOOPBACK
|
||||
efx_rc_t (*emo_loopback_set)(efx_nic_t *, efx_link_mode_t,
|
||||
efx_loopback_type_t);
|
||||
#endif /* EFSYS_OPT_LOOPBACK */
|
||||
#if EFSYS_OPT_MAC_STATS
|
||||
efx_rc_t (*emo_stats_get_mask)(efx_nic_t *, uint32_t *, size_t);
|
||||
efx_rc_t (*emo_stats_upload)(efx_nic_t *, efsys_mem_t *);
|
||||
@ -261,6 +265,10 @@ typedef struct efx_port_s {
|
||||
uint8_t ep_mulcst_addr_list[EFX_MAC_ADDR_LEN *
|
||||
EFX_MAC_MULTICAST_LIST_MAX];
|
||||
uint32_t ep_mulcst_addr_count;
|
||||
#if EFSYS_OPT_LOOPBACK
|
||||
efx_loopback_type_t ep_loopback_type;
|
||||
efx_link_mode_t ep_loopback_link_mode;
|
||||
#endif /* EFSYS_OPT_LOOPBACK */
|
||||
#if EFSYS_OPT_PHY_FLAGS
|
||||
uint32_t ep_phy_flags;
|
||||
#endif /* EFSYS_OPT_PHY_FLAGS */
|
||||
|
@ -50,6 +50,9 @@ static const efx_mac_ops_t __efx_siena_mac_ops = {
|
||||
siena_mac_multicast_list_set, /* emo_multicast_list_set */
|
||||
NULL, /* emo_filter_set_default_rxq */
|
||||
NULL, /* emo_filter_default_rxq_clear */
|
||||
#if EFSYS_OPT_LOOPBACK
|
||||
siena_mac_loopback_set, /* emo_loopback_set */
|
||||
#endif /* EFSYS_OPT_LOOPBACK */
|
||||
#if EFSYS_OPT_MAC_STATS
|
||||
siena_mac_stats_get_mask, /* emo_stats_get_mask */
|
||||
efx_mcdi_mac_stats_upload, /* emo_stats_upload */
|
||||
@ -71,6 +74,9 @@ static const efx_mac_ops_t __efx_ef10_mac_ops = {
|
||||
ef10_mac_filter_default_rxq_set, /* emo_filter_default_rxq_set */
|
||||
ef10_mac_filter_default_rxq_clear,
|
||||
/* emo_filter_default_rxq_clear */
|
||||
#if EFSYS_OPT_LOOPBACK
|
||||
ef10_mac_loopback_set, /* emo_loopback_set */
|
||||
#endif /* EFSYS_OPT_LOOPBACK */
|
||||
#if EFSYS_OPT_MAC_STATS
|
||||
ef10_mac_stats_get_mask, /* emo_stats_get_mask */
|
||||
efx_mcdi_mac_stats_upload, /* emo_stats_upload */
|
||||
|
@ -220,6 +220,12 @@ efx_mcdi_mac_stats_periodic(
|
||||
__in boolean_t events);
|
||||
|
||||
|
||||
#if EFSYS_OPT_LOOPBACK
|
||||
extern __checkReturn efx_rc_t
|
||||
efx_mcdi_get_loopback_modes(
|
||||
__in efx_nic_t *enp);
|
||||
#endif /* EFSYS_OPT_LOOPBACK */
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
efx_mcdi_phy_module_get_info(
|
||||
__in efx_nic_t *enp,
|
||||
|
@ -775,6 +775,194 @@ fail1:
|
||||
|
||||
#endif /* EFSYS_OPT_DIAG */
|
||||
|
||||
#if EFSYS_OPT_LOOPBACK
|
||||
|
||||
extern void
|
||||
efx_loopback_mask(
|
||||
__in efx_loopback_kind_t loopback_kind,
|
||||
__out efx_qword_t *maskp)
|
||||
{
|
||||
efx_qword_t mask;
|
||||
|
||||
EFSYS_ASSERT3U(loopback_kind, <, EFX_LOOPBACK_NKINDS);
|
||||
EFSYS_ASSERT(maskp != NULL);
|
||||
|
||||
/* Assert the MC_CMD_LOOPBACK and EFX_LOOPBACK namespace agree */
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_NONE == EFX_LOOPBACK_OFF);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_DATA == EFX_LOOPBACK_DATA);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GMAC == EFX_LOOPBACK_GMAC);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XGMII == EFX_LOOPBACK_XGMII);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XGXS == EFX_LOOPBACK_XGXS);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XAUI == EFX_LOOPBACK_XAUI);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GMII == EFX_LOOPBACK_GMII);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SGMII == EFX_LOOPBACK_SGMII);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XGBR == EFX_LOOPBACK_XGBR);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XFI == EFX_LOOPBACK_XFI);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XAUI_FAR == EFX_LOOPBACK_XAUI_FAR);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GMII_FAR == EFX_LOOPBACK_GMII_FAR);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SGMII_FAR == EFX_LOOPBACK_SGMII_FAR);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XFI_FAR == EFX_LOOPBACK_XFI_FAR);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GPHY == EFX_LOOPBACK_GPHY);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PHYXS == EFX_LOOPBACK_PHY_XS);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PCS == EFX_LOOPBACK_PCS);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PMAPMD == EFX_LOOPBACK_PMA_PMD);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XPORT == EFX_LOOPBACK_XPORT);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XGMII_WS == EFX_LOOPBACK_XGMII_WS);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XAUI_WS == EFX_LOOPBACK_XAUI_WS);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XAUI_WS_FAR ==
|
||||
EFX_LOOPBACK_XAUI_WS_FAR);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XAUI_WS_NEAR ==
|
||||
EFX_LOOPBACK_XAUI_WS_NEAR);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GMII_WS == EFX_LOOPBACK_GMII_WS);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XFI_WS == EFX_LOOPBACK_XFI_WS);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XFI_WS_FAR ==
|
||||
EFX_LOOPBACK_XFI_WS_FAR);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PHYXS_WS == EFX_LOOPBACK_PHYXS_WS);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PMA_INT == EFX_LOOPBACK_PMA_INT);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SD_NEAR == EFX_LOOPBACK_SD_NEAR);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SD_FAR == EFX_LOOPBACK_SD_FAR);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PMA_INT_WS ==
|
||||
EFX_LOOPBACK_PMA_INT_WS);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SD_FEP2_WS ==
|
||||
EFX_LOOPBACK_SD_FEP2_WS);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SD_FEP1_5_WS ==
|
||||
EFX_LOOPBACK_SD_FEP1_5_WS);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SD_FEP_WS == EFX_LOOPBACK_SD_FEP_WS);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SD_FES_WS == EFX_LOOPBACK_SD_FES_WS);
|
||||
|
||||
/* Build bitmask of possible loopback types */
|
||||
EFX_ZERO_QWORD(mask);
|
||||
|
||||
if ((loopback_kind == EFX_LOOPBACK_KIND_OFF) ||
|
||||
(loopback_kind == EFX_LOOPBACK_KIND_ALL)) {
|
||||
EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_OFF);
|
||||
}
|
||||
|
||||
if ((loopback_kind == EFX_LOOPBACK_KIND_MAC) ||
|
||||
(loopback_kind == EFX_LOOPBACK_KIND_ALL)) {
|
||||
/*
|
||||
* The "MAC" grouping has historically been used by drivers to
|
||||
* mean loopbacks supported by on-chip hardware. Keep that
|
||||
* meaning here, and include on-chip PHY layer loopbacks.
|
||||
*/
|
||||
EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_DATA);
|
||||
EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_GMAC);
|
||||
EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XGMII);
|
||||
EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XGXS);
|
||||
EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XAUI);
|
||||
EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_GMII);
|
||||
EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_SGMII);
|
||||
EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XGBR);
|
||||
EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XFI);
|
||||
EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XAUI_FAR);
|
||||
EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_GMII_FAR);
|
||||
EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_SGMII_FAR);
|
||||
EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XFI_FAR);
|
||||
EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_PMA_INT);
|
||||
EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_SD_NEAR);
|
||||
EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_SD_FAR);
|
||||
}
|
||||
|
||||
if ((loopback_kind == EFX_LOOPBACK_KIND_PHY) ||
|
||||
(loopback_kind == EFX_LOOPBACK_KIND_ALL)) {
|
||||
/*
|
||||
* The "PHY" grouping has historically been used by drivers to
|
||||
* mean loopbacks supported by off-chip hardware. Keep that
|
||||
* meaning here.
|
||||
*/
|
||||
EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_GPHY);
|
||||
EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_PHY_XS);
|
||||
EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_PCS);
|
||||
EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_PMA_PMD);
|
||||
}
|
||||
|
||||
*maskp = mask;
|
||||
}
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
efx_mcdi_get_loopback_modes(
|
||||
__in efx_nic_t *enp)
|
||||
{
|
||||
efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
|
||||
efx_mcdi_req_t req;
|
||||
uint8_t payload[MAX(MC_CMD_GET_LOOPBACK_MODES_IN_LEN,
|
||||
MC_CMD_GET_LOOPBACK_MODES_OUT_LEN)];
|
||||
efx_qword_t mask;
|
||||
efx_qword_t modes;
|
||||
efx_rc_t rc;
|
||||
|
||||
(void) memset(payload, 0, sizeof (payload));
|
||||
req.emr_cmd = MC_CMD_GET_LOOPBACK_MODES;
|
||||
req.emr_in_buf = payload;
|
||||
req.emr_in_length = MC_CMD_GET_LOOPBACK_MODES_IN_LEN;
|
||||
req.emr_out_buf = payload;
|
||||
req.emr_out_length = MC_CMD_GET_LOOPBACK_MODES_OUT_LEN;
|
||||
|
||||
efx_mcdi_execute(enp, &req);
|
||||
|
||||
if (req.emr_rc != 0) {
|
||||
rc = req.emr_rc;
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
if (req.emr_out_length_used <
|
||||
MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_OFST +
|
||||
MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_LEN) {
|
||||
rc = EMSGSIZE;
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
/*
|
||||
* We assert the MC_CMD_LOOPBACK and EFX_LOOPBACK namespaces agree
|
||||
* in efx_loopback_mask() and in siena_phy.c:siena_phy_get_link().
|
||||
*/
|
||||
efx_loopback_mask(EFX_LOOPBACK_KIND_ALL, &mask);
|
||||
|
||||
EFX_AND_QWORD(mask,
|
||||
*MCDI_OUT2(req, efx_qword_t, GET_LOOPBACK_MODES_OUT_SUGGESTED));
|
||||
|
||||
modes = *MCDI_OUT2(req, efx_qword_t, GET_LOOPBACK_MODES_OUT_100M);
|
||||
EFX_AND_QWORD(modes, mask);
|
||||
encp->enc_loopback_types[EFX_LINK_100FDX] = modes;
|
||||
|
||||
modes = *MCDI_OUT2(req, efx_qword_t, GET_LOOPBACK_MODES_OUT_1G);
|
||||
EFX_AND_QWORD(modes, mask);
|
||||
encp->enc_loopback_types[EFX_LINK_1000FDX] = modes;
|
||||
|
||||
modes = *MCDI_OUT2(req, efx_qword_t, GET_LOOPBACK_MODES_OUT_10G);
|
||||
EFX_AND_QWORD(modes, mask);
|
||||
encp->enc_loopback_types[EFX_LINK_10000FDX] = modes;
|
||||
|
||||
if (req.emr_out_length_used >=
|
||||
MC_CMD_GET_LOOPBACK_MODES_OUT_40G_OFST +
|
||||
MC_CMD_GET_LOOPBACK_MODES_OUT_40G_LEN) {
|
||||
/* Response includes 40G loopback modes */
|
||||
modes =
|
||||
*MCDI_OUT2(req, efx_qword_t, GET_LOOPBACK_MODES_OUT_40G);
|
||||
EFX_AND_QWORD(modes, mask);
|
||||
encp->enc_loopback_types[EFX_LINK_40000FDX] = modes;
|
||||
}
|
||||
|
||||
EFX_ZERO_QWORD(modes);
|
||||
EFX_SET_QWORD_BIT(modes, EFX_LOOPBACK_OFF);
|
||||
EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_100FDX]);
|
||||
EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_1000FDX]);
|
||||
EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_10000FDX]);
|
||||
EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_40000FDX]);
|
||||
encp->enc_loopback_types[EFX_LINK_UNKNOWN] = modes;
|
||||
|
||||
return (0);
|
||||
|
||||
fail2:
|
||||
EFSYS_PROBE(fail2);
|
||||
fail1:
|
||||
EFSYS_PROBE1(fail1, efx_rc_t, rc);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
#endif /* EFSYS_OPT_LOOPBACK */
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
efx_nic_calculate_pcie_link_bandwidth(
|
||||
__in uint32_t pcie_link_width,
|
||||
|
@ -125,6 +125,107 @@ fail1:
|
||||
return (rc);
|
||||
}
|
||||
|
||||
#if EFSYS_OPT_LOOPBACK
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
efx_port_loopback_set(
|
||||
__in efx_nic_t *enp,
|
||||
__in efx_link_mode_t link_mode,
|
||||
__in efx_loopback_type_t loopback_type)
|
||||
{
|
||||
efx_port_t *epp = &(enp->en_port);
|
||||
efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
|
||||
const efx_mac_ops_t *emop = epp->ep_emop;
|
||||
efx_rc_t rc;
|
||||
|
||||
EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
|
||||
EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
|
||||
EFSYS_ASSERT(emop != NULL);
|
||||
|
||||
EFSYS_ASSERT(link_mode < EFX_LINK_NMODES);
|
||||
|
||||
if (EFX_TEST_QWORD_BIT(encp->enc_loopback_types[link_mode],
|
||||
loopback_type) == 0) {
|
||||
rc = ENOTSUP;
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
if (epp->ep_loopback_type == loopback_type &&
|
||||
epp->ep_loopback_link_mode == link_mode)
|
||||
return (0);
|
||||
|
||||
if ((rc = emop->emo_loopback_set(enp, link_mode, loopback_type)) != 0)
|
||||
goto fail2;
|
||||
|
||||
return (0);
|
||||
|
||||
fail2:
|
||||
EFSYS_PROBE(fail2);
|
||||
fail1:
|
||||
EFSYS_PROBE1(fail1, efx_rc_t, rc);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
#if EFSYS_OPT_NAMES
|
||||
|
||||
static const char * const __efx_loopback_type_name[] = {
|
||||
"OFF",
|
||||
"DATA",
|
||||
"GMAC",
|
||||
"XGMII",
|
||||
"XGXS",
|
||||
"XAUI",
|
||||
"GMII",
|
||||
"SGMII",
|
||||
"XGBR",
|
||||
"XFI",
|
||||
"XAUI_FAR",
|
||||
"GMII_FAR",
|
||||
"SGMII_FAR",
|
||||
"XFI_FAR",
|
||||
"GPHY",
|
||||
"PHY_XS",
|
||||
"PCS",
|
||||
"PMA_PMD",
|
||||
"XPORT",
|
||||
"XGMII_WS",
|
||||
"XAUI_WS",
|
||||
"XAUI_WS_FAR",
|
||||
"XAUI_WS_NEAR",
|
||||
"GMII_WS",
|
||||
"XFI_WS",
|
||||
"XFI_WS_FAR",
|
||||
"PHYXS_WS",
|
||||
"PMA_INT",
|
||||
"SD_NEAR",
|
||||
"SD_FAR",
|
||||
"PMA_INT_WS",
|
||||
"SD_FEP2_WS",
|
||||
"SD_FEP1_5_WS",
|
||||
"SD_FEP_WS",
|
||||
"SD_FES_WS",
|
||||
};
|
||||
|
||||
__checkReturn const char *
|
||||
efx_loopback_type_name(
|
||||
__in efx_nic_t *enp,
|
||||
__in efx_loopback_type_t type)
|
||||
{
|
||||
EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__efx_loopback_type_name) ==
|
||||
EFX_LOOPBACK_NTYPES);
|
||||
|
||||
_NOTE(ARGUNUSED(enp))
|
||||
EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
|
||||
EFSYS_ASSERT3U(type, <, EFX_LOOPBACK_NTYPES);
|
||||
|
||||
return (__efx_loopback_type_name[type]);
|
||||
}
|
||||
|
||||
#endif /* EFSYS_OPT_NAMES */
|
||||
|
||||
#endif /* EFSYS_OPT_LOOPBACK */
|
||||
|
||||
void
|
||||
efx_port_fini(
|
||||
__in efx_nic_t *enp)
|
||||
|
@ -138,6 +138,9 @@ typedef struct siena_link_state_s {
|
||||
uint32_t sls_lp_cap_mask;
|
||||
unsigned int sls_fcntl;
|
||||
efx_link_mode_t sls_link_mode;
|
||||
#if EFSYS_OPT_LOOPBACK
|
||||
efx_loopback_type_t sls_loopback;
|
||||
#endif
|
||||
boolean_t sls_mac_up;
|
||||
} siena_link_state_t;
|
||||
|
||||
@ -232,6 +235,16 @@ siena_mac_pdu_get(
|
||||
__in efx_nic_t *enp,
|
||||
__out size_t *pdu);
|
||||
|
||||
#if EFSYS_OPT_LOOPBACK
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
siena_mac_loopback_set(
|
||||
__in efx_nic_t *enp,
|
||||
__in efx_link_mode_t link_mode,
|
||||
__in efx_loopback_type_t loopback_type);
|
||||
|
||||
#endif /* EFSYS_OPT_LOOPBACK */
|
||||
|
||||
#if EFSYS_OPT_MAC_STATS
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
|
@ -194,6 +194,42 @@ fail1:
|
||||
return (rc);
|
||||
}
|
||||
|
||||
#if EFSYS_OPT_LOOPBACK
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
siena_mac_loopback_set(
|
||||
__in efx_nic_t *enp,
|
||||
__in efx_link_mode_t link_mode,
|
||||
__in efx_loopback_type_t loopback_type)
|
||||
{
|
||||
efx_port_t *epp = &(enp->en_port);
|
||||
const efx_phy_ops_t *epop = epp->ep_epop;
|
||||
efx_loopback_type_t old_loopback_type;
|
||||
efx_link_mode_t old_loopback_link_mode;
|
||||
efx_rc_t rc;
|
||||
|
||||
/* The PHY object handles this on Siena */
|
||||
old_loopback_type = epp->ep_loopback_type;
|
||||
old_loopback_link_mode = epp->ep_loopback_link_mode;
|
||||
epp->ep_loopback_type = loopback_type;
|
||||
epp->ep_loopback_link_mode = link_mode;
|
||||
|
||||
if ((rc = epop->epo_reconfigure(enp)) != 0)
|
||||
goto fail1;
|
||||
|
||||
return (0);
|
||||
|
||||
fail1:
|
||||
EFSYS_PROBE1(fail1, efx_rc_t, rc);
|
||||
|
||||
epp->ep_loopback_type = old_loopback_type;
|
||||
epp->ep_loopback_link_mode = old_loopback_link_mode;
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
#endif /* EFSYS_OPT_LOOPBACK */
|
||||
|
||||
#if EFSYS_OPT_MAC_STATS
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
|
@ -216,10 +216,19 @@ siena_nic_probe(
|
||||
goto fail10;
|
||||
#endif
|
||||
|
||||
#if EFSYS_OPT_LOOPBACK
|
||||
if ((rc = efx_mcdi_get_loopback_modes(enp)) != 0)
|
||||
goto fail11;
|
||||
#endif
|
||||
|
||||
encp->enc_features = enp->en_features;
|
||||
|
||||
return (0);
|
||||
|
||||
#if EFSYS_OPT_LOOPBACK
|
||||
fail11:
|
||||
EFSYS_PROBE(fail11);
|
||||
#endif
|
||||
#if EFSYS_OPT_MAC_STATS
|
||||
fail10:
|
||||
EFSYS_PROBE(fail10);
|
||||
|
@ -226,6 +226,30 @@ siena_phy_get_link(
|
||||
MCDI_OUT_DWORD(req, GET_LINK_OUT_FCNTL),
|
||||
&slsp->sls_link_mode, &slsp->sls_fcntl);
|
||||
|
||||
#if EFSYS_OPT_LOOPBACK
|
||||
/* Assert the MC_CMD_LOOPBACK and EFX_LOOPBACK namespace agree */
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_NONE == EFX_LOOPBACK_OFF);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_DATA == EFX_LOOPBACK_DATA);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GMAC == EFX_LOOPBACK_GMAC);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XGMII == EFX_LOOPBACK_XGMII);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XGXS == EFX_LOOPBACK_XGXS);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XAUI == EFX_LOOPBACK_XAUI);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GMII == EFX_LOOPBACK_GMII);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SGMII == EFX_LOOPBACK_SGMII);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XGBR == EFX_LOOPBACK_XGBR);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XFI == EFX_LOOPBACK_XFI);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XAUI_FAR == EFX_LOOPBACK_XAUI_FAR);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GMII_FAR == EFX_LOOPBACK_GMII_FAR);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SGMII_FAR == EFX_LOOPBACK_SGMII_FAR);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XFI_FAR == EFX_LOOPBACK_XFI_FAR);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GPHY == EFX_LOOPBACK_GPHY);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PHYXS == EFX_LOOPBACK_PHY_XS);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PCS == EFX_LOOPBACK_PCS);
|
||||
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PMAPMD == EFX_LOOPBACK_PMA_PMD);
|
||||
|
||||
slsp->sls_loopback = MCDI_OUT_DWORD(req, GET_LINK_OUT_LOOPBACK_MODE);
|
||||
#endif /* EFSYS_OPT_LOOPBACK */
|
||||
|
||||
slsp->sls_mac_up = MCDI_OUT_DWORD(req, GET_LINK_OUT_MAC_FAULT) == 0;
|
||||
|
||||
return (0);
|
||||
@ -273,8 +297,26 @@ siena_phy_reconfigure(
|
||||
PHY_CAP_ASYM, (cap_mask >> EFX_PHY_CAP_ASYM) & 0x1,
|
||||
PHY_CAP_AN, (cap_mask >> EFX_PHY_CAP_AN) & 0x1);
|
||||
|
||||
#if EFSYS_OPT_LOOPBACK
|
||||
MCDI_IN_SET_DWORD(req, SET_LINK_IN_LOOPBACK_MODE,
|
||||
epp->ep_loopback_type);
|
||||
switch (epp->ep_loopback_link_mode) {
|
||||
case EFX_LINK_100FDX:
|
||||
speed = 100;
|
||||
break;
|
||||
case EFX_LINK_1000FDX:
|
||||
speed = 1000;
|
||||
break;
|
||||
case EFX_LINK_10000FDX:
|
||||
speed = 10000;
|
||||
break;
|
||||
default:
|
||||
speed = 0;
|
||||
}
|
||||
#else
|
||||
MCDI_IN_SET_DWORD(req, SET_LINK_IN_LOOPBACK_MODE, MC_CMD_LOOPBACK_NONE);
|
||||
speed = 0;
|
||||
#endif /* EFSYS_OPT_LOOPBACK */
|
||||
MCDI_IN_SET_DWORD(req, SET_LINK_IN_LOOPBACK_SPEED, speed);
|
||||
|
||||
#if EFSYS_OPT_PHY_FLAGS
|
||||
|
Loading…
x
Reference in New Issue
Block a user