bitmap_zero(linkset, __ETHTOOL_LINK_MODE_MASK_NBITS); switch (media) { case MC_CMD_MEDIA_KX4:
SET_BIT(Backplane); if (cap & (1 << MC_CMD_PHY_CAP_1000FDX_LBN))
SET_BIT(1000baseKX_Full); if (cap & (1 << MC_CMD_PHY_CAP_10000FDX_LBN))
SET_BIT(10000baseKX4_Full); if (cap & (1 << MC_CMD_PHY_CAP_40000FDX_LBN))
SET_BIT(40000baseKR4_Full); break;
case MC_CMD_MEDIA_XFP: case MC_CMD_MEDIA_SFP_PLUS: case MC_CMD_MEDIA_QSFP_PLUS:
SET_BIT(FIBRE); if (cap & (1 << MC_CMD_PHY_CAP_1000FDX_LBN)) {
SET_BIT(1000baseT_Full);
SET_BIT(1000baseX_Full);
} if (cap & (1 << MC_CMD_PHY_CAP_10000FDX_LBN)) {
SET_BIT(10000baseCR_Full);
SET_BIT(10000baseLR_Full);
SET_BIT(10000baseSR_Full);
} if (cap & (1 << MC_CMD_PHY_CAP_40000FDX_LBN)) {
SET_BIT(40000baseCR4_Full);
SET_BIT(40000baseSR4_Full);
} if (cap & (1 << MC_CMD_PHY_CAP_100000FDX_LBN)) {
SET_BIT(100000baseCR4_Full);
SET_BIT(100000baseSR4_Full);
} if (cap & (1 << MC_CMD_PHY_CAP_25000FDX_LBN)) {
SET_BIT(25000baseCR_Full);
SET_BIT(25000baseSR_Full);
} if (cap & (1 << MC_CMD_PHY_CAP_50000FDX_LBN))
SET_BIT(50000baseCR2_Full); break;
case MC_CMD_MEDIA_BASE_T:
SET_BIT(TP); if (cap & (1 << MC_CMD_PHY_CAP_10HDX_LBN))
SET_BIT(10baseT_Half); if (cap & (1 << MC_CMD_PHY_CAP_10FDX_LBN))
SET_BIT(10baseT_Full); if (cap & (1 << MC_CMD_PHY_CAP_100HDX_LBN))
SET_BIT(100baseT_Half); if (cap & (1 << MC_CMD_PHY_CAP_100FDX_LBN))
SET_BIT(100baseT_Full); if (cap & (1 << MC_CMD_PHY_CAP_1000HDX_LBN))
SET_BIT(1000baseT_Half); if (cap & (1 << MC_CMD_PHY_CAP_1000FDX_LBN))
SET_BIT(1000baseT_Full); if (cap & (1 << MC_CMD_PHY_CAP_10000FDX_LBN))
SET_BIT(10000baseT_Full); break;
}
if (cap & (1 << MC_CMD_PHY_CAP_PAUSE_LBN))
SET_BIT(Pause); if (cap & (1 << MC_CMD_PHY_CAP_ASYM_LBN))
SET_BIT(Asym_Pause); if (cap & (1 << MC_CMD_PHY_CAP_AN_LBN))
SET_BIT(Autoneg);
#undef SET_BIT
}
u32 ethtool_linkset_to_mcdi_cap(constunsignedlong *linkset)
{
u32 result = 0;
#define TEST_BIT(name) test_bit(ETHTOOL_LINK_MODE_ ## name ## _BIT, \
linkset)
if (TEST_BIT(10baseT_Half))
result |= (1 << MC_CMD_PHY_CAP_10HDX_LBN); if (TEST_BIT(10baseT_Full))
result |= (1 << MC_CMD_PHY_CAP_10FDX_LBN); if (TEST_BIT(100baseT_Half))
result |= (1 << MC_CMD_PHY_CAP_100HDX_LBN); if (TEST_BIT(100baseT_Full))
result |= (1 << MC_CMD_PHY_CAP_100FDX_LBN); if (TEST_BIT(1000baseT_Half))
result |= (1 << MC_CMD_PHY_CAP_1000HDX_LBN); if (TEST_BIT(1000baseT_Full) || TEST_BIT(1000baseKX_Full) ||
TEST_BIT(1000baseX_Full))
result |= (1 << MC_CMD_PHY_CAP_1000FDX_LBN); if (TEST_BIT(10000baseT_Full) || TEST_BIT(10000baseKX4_Full) ||
TEST_BIT(10000baseCR_Full) || TEST_BIT(10000baseLR_Full) ||
TEST_BIT(10000baseSR_Full))
result |= (1 << MC_CMD_PHY_CAP_10000FDX_LBN); if (TEST_BIT(40000baseCR4_Full) || TEST_BIT(40000baseKR4_Full) ||
TEST_BIT(40000baseSR4_Full))
result |= (1 << MC_CMD_PHY_CAP_40000FDX_LBN); if (TEST_BIT(100000baseCR4_Full) || TEST_BIT(100000baseSR4_Full))
result |= (1 << MC_CMD_PHY_CAP_100000FDX_LBN); if (TEST_BIT(25000baseCR_Full) || TEST_BIT(25000baseSR_Full))
result |= (1 << MC_CMD_PHY_CAP_25000FDX_LBN); if (TEST_BIT(50000baseCR2_Full))
result |= (1 << MC_CMD_PHY_CAP_50000FDX_LBN); if (TEST_BIT(Pause))
result |= (1 << MC_CMD_PHY_CAP_PAUSE_LBN); if (TEST_BIT(Asym_Pause))
result |= (1 << MC_CMD_PHY_CAP_ASYM_LBN); if (TEST_BIT(Autoneg))
result |= (1 << MC_CMD_PHY_CAP_AN_LBN);
/* Verify that the forced flow control settings (!EFX_FC_AUTO) are *supportedbythelinkpartner.Warntheuserifthisisn'tthecase
*/ void efx_mcdi_phy_check_fcntl(struct efx_nic *efx, u32 lpa)
{ struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
u32 rmtadv;
/* The link partner capabilities are only relevant if the *linksupportsflowcontrolautonegotiation
*/ if (~phy_cfg->supported_cap & (1 << MC_CMD_PHY_CAP_AN_LBN)) return;
/* If flow control autoneg is supported and enabled, then fine */ if (efx->wanted_fc & EFX_FC_AUTO) return;
rc = efx_mcdi_loopback_modes(efx, &efx->loopback_modes); if (rc != 0) goto fail; /* The MC indicates that LOOPBACK_NONE is a valid loopback mode, *butbyconventionwedon't
*/
efx->loopback_modes &= ~(1 << LOOPBACK_NONE);
/* Set the initial link mode */
efx_mcdi_phy_decode_link(efx, &efx->link_state,
MCDI_DWORD(outbuf, GET_LINK_OUT_LINK_SPEED),
MCDI_DWORD(outbuf, GET_LINK_OUT_FLAGS),
MCDI_DWORD(outbuf, GET_LINK_OUT_FCNTL));
/* Default to Autonegotiated flow control if the PHY supports it */
efx->wanted_fc = EFX_FC_RX | EFX_FC_TX; if (phy_data->supported_cap & (1 << MC_CMD_PHY_CAP_AN_LBN))
efx->wanted_fc |= EFX_FC_AUTO;
efx_link_set_wanted_fc(efx, efx->wanted_fc);
/* behaviour for 25G/50G links depends on 25G BASER bit */
speed = MCDI_DWORD(outbuf, GET_LINK_OUT_V2_LINK_SPEED);
is_25g = speed == 25000 || speed == 50000;
caps = MCDI_DWORD(outbuf, GET_LINK_OUT_V2_CAP);
fec->fec = mcdi_fec_caps_to_ethtool(caps, is_25g); /* BASER is never supported on 100G */ if (speed == 100000)
fec->fec &= ~ETHTOOL_FEC_BASER;
active = MCDI_DWORD(outbuf, GET_LINK_OUT_V2_FEC_TYPE); switch (active) { case MC_CMD_FEC_NONE:
fec->active_fec = ETHTOOL_FEC_OFF; break; case MC_CMD_FEC_BASER:
fec->active_fec = ETHTOOL_FEC_BASER; break; case MC_CMD_FEC_RS:
fec->active_fec = ETHTOOL_FEC_RS; break; default:
netif_warn(efx, hw, efx->net_dev, "Firmware reports unrecognised FEC_TYPE %u\n",
active); /* We don't know what firmware has picked. AUTO is as good a *"can'thappen"valueasanyother.
*/
fec->active_fec = ETHTOOL_FEC_AUTO; break;
}
return0;
}
/* Basic validation to ensure that the caps we are going to attempt to set are *infactsupportedbytheadapter.Notethat'noFEC'isalwayssupported.
*/ staticint ethtool_fec_supported(u32 supported_cap, u32 ethtool_cap)
{ if (ethtool_cap & ETHTOOL_FEC_OFF) return0;
if (ethtool_cap &&
!ethtool_fec_caps_to_mcdi(supported_cap, ethtool_cap)) return -EINVAL; return0;
}
int efx_mcdi_phy_set_fecparam(struct efx_nic *efx, conststruct ethtool_fecparam *fec)
{ struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
u32 caps; int rc;
rc = ethtool_fec_supported(phy_cfg->supported_cap, fec->fec); if (rc) return rc;
/* Work out what efx_mcdi_phy_set_link_ksettings() would produce from *savedadvertisingbits
*/ if (test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, efx->link_advertising))
caps = (ethtool_linkset_to_mcdi_cap(efx->link_advertising) | 1 << MC_CMD_PHY_CAP_AN_LBN); else
caps = phy_cfg->forced_cap;
/* SFT9001 specific cable diagnostics output */ if (efx->phy_type == PHY_TYPE_SFT9001B &&
(bist_mode == MC_CMD_PHY_BIST_CABLE_SHORT ||
bist_mode == MC_CMD_PHY_BIST_CABLE_LONG)) {
ptr = MCDI_PTR(outbuf, POLL_BIST_OUT_SFT9001_CABLE_LENGTH_A); if (status == MC_CMD_POLL_BIST_PASSED &&
outlen >= MC_CMD_POLL_BIST_OUT_SFT9001_LEN) { for (i = 0; i < 8; i++) {
results[count + i] =
EFX_DWORD_FIELD(((efx_dword_t *)ptr)[i],
EFX_DWORD_0);
}
}
count += 8;
}
rc = count;
out: return rc;
}
int efx_mcdi_phy_run_tests(struct efx_nic *efx, int *results, unsignedint flags)
{ struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
u32 mode; int rc;
if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_OUT_BIST_LBN)) {
rc = efx_mcdi_bist(efx, MC_CMD_PHY_BIST, results); if (rc < 0) return rc;
results += rc;
}
/* If we support both LONG and SHORT, then run each in response to *breakornot.Otherwise,runtheonewesupport
*/
mode = 0; if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_SHORT_LBN)) { if ((flags & ETH_TEST_FL_OFFLINE) &&
(phy_cfg->flags &
(1 << MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_LONG_LBN)))
mode = MC_CMD_PHY_BIST_CABLE_LONG; else
mode = MC_CMD_PHY_BIST_CABLE_SHORT;
} elseif (phy_cfg->flags &
(1 << MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_LONG_LBN))
mode = MC_CMD_PHY_BIST_CABLE_LONG;
if (mode != 0) {
rc = efx_mcdi_bist(efx, mode, results); if (rc < 0) return rc;
results += rc;
}
staticint efx_mcdi_phy_diag_type(struct efx_nic *efx)
{ /* Page zero of the EEPROM includes the diagnostic type at byte 92. */ return efx_mcdi_phy_get_module_eeprom_byte(efx, 0,
SFF_DIAG_TYPE_OFFSET);
}
staticint efx_mcdi_phy_sff_8472_level(struct efx_nic *efx)
{ /* Page zero of the EEPROM includes the DMT level at byte 94. */ return efx_mcdi_phy_get_module_eeprom_byte(efx, 0,
SFF_DMT_LEVEL_OFFSET);
}
/* Get physical port number (EF10 only; on Siena it is same as PF number) */ int efx_mcdi_port_get_number(struct efx_nic *efx)
{
MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_PORT_ASSIGNMENT_OUT_LEN); int rc;
/* efx->link_state is only modified by efx_mcdi_phy_get_link(), *whichisonlyrunafterflushingtheeventqueues.Therefore,it *issafetomodifythelinkstateoutsideofthemac_lockhere.
*/
efx_mcdi_phy_decode_link(efx, &efx->link_state, speed, flags, fcntl);
efx_mcdi_phy_check_fcntl(efx, lpa);
efx_link_status_changed(efx);
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.18 Sekunden
(vorverarbeitet am 2026-09-29)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.