14 #include <linux/slab.h>
47 outbuf,
sizeof(outbuf), &outlen);
59 MCDI_DWORD(outbuf, GET_PHY_CFG_OUT_SUPPORTED_CAP);
103 static int efx_mcdi_loopback_modes(
struct efx_nic *efx,
u64 *loopback_modes)
110 outbuf,
sizeof(outbuf), &outlen);
119 *loopback_modes =
MCDI_QWORD(outbuf, GET_LOOPBACK_MODES_OUT_SUGGESTED);
129 unsigned int prtad,
unsigned int devad,
u16 addr,
130 u16 *value_out,
u32 *status_out)
143 outbuf,
sizeof(outbuf), &outlen);
148 *status_out =
MCDI_DWORD(outbuf, MDIO_READ_OUT_STATUS);
157 unsigned int prtad,
unsigned int devad,
u16 addr,
172 outbuf,
sizeof(outbuf), &outlen);
176 *status_out =
MCDI_DWORD(outbuf, MDIO_WRITE_OUT_STATUS);
231 static u32 ethtool_to_mcdi_cap(
u32 cap)
259 static u32 efx_get_mcdi_phy_flags(
struct efx_nic *efx)
287 static u32 mcdi_to_ethtool_media(
u32 media)
307 static int efx_mcdi_phy_probe(
struct efx_nic *efx)
315 phy_data = kzalloc(
sizeof(*phy_data),
GFP_KERNEL);
316 if (phy_data ==
NULL)
319 rc = efx_mcdi_get_phy_cfg(efx, phy_data);
326 outbuf,
sizeof(outbuf),
NULL);
337 efx->
mdio.mode_support = 0;
346 mcdi_to_ethtool_cap(phy_data->
media, caps);
413 return efx_mcdi_set_link(efx, caps, efx_get_mcdi_phy_flags(efx),
441 link_state->
speed = speed;
469 "warning: link partner doesn't support pause frames");
472 static bool efx_mcdi_phy_poll(
struct efx_nic *efx)
483 outbuf,
sizeof(outbuf),
NULL);
496 return !efx_link_state_equal(&efx->
link_state, &old_state);
499 static void efx_mcdi_phy_remove(
struct efx_nic *efx)
516 ethtool_cmd_speed_set(ecmd, efx->
link_state.speed);
518 ecmd->
port = mcdi_to_ethtool_media(phy_cfg->
media);
527 outbuf,
sizeof(outbuf),
NULL);
534 mcdi_to_ethtool_cap(phy_cfg->
media,
547 }
else if (ecmd->
duplex) {
548 switch (ethtool_cmd_speed(ecmd)) {
556 switch (ethtool_cmd_speed(ecmd)) {
564 rc = efx_mcdi_set_link(efx, caps, efx_get_mcdi_phy_flags(efx),
580 static int efx_mcdi_phy_test_alive(
struct efx_nic *efx)
589 outbuf,
sizeof(outbuf), &outlen);
601 static const char *
const mcdi_sft9001_cable_diag_names[] = {
602 "cable.pairA.length",
603 "cable.pairB.length",
604 "cable.pairC.length",
605 "cable.pairD.length",
606 "cable.pairA.status",
607 "cable.pairB.status",
608 "cable.pairC.status",
609 "cable.pairD.status",
612 static int efx_mcdi_bist(
struct efx_nic *efx,
unsigned int bist_mode,
633 for (retry = 0; retry < 100; ++
retry) {
636 buf, 0x100, &outlen);
640 status =
MCDI_DWORD(buf, POLL_BIST_OUT_RESULT);
657 ptr =
MCDI_PTR(buf, POLL_BIST_OUT_SFT9001_CABLE_LENGTH_A);
660 for (i = 0; i < 8; i++) {
676 static int efx_mcdi_phy_run_tests(
struct efx_nic *efx,
int *results,
701 }
else if (phy_cfg->
flags &
706 rc = efx_mcdi_bist(efx, mode, results);
715 static const char *efx_mcdi_phy_test_name(
struct efx_nic *efx,
733 if (index <
ARRAY_SIZE(mcdi_sft9001_cable_diag_names))
734 return mcdi_sft9001_cable_diag_names[
index];
735 index -=
ARRAY_SIZE(mcdi_sft9001_cable_diag_names);
742 #define SFP_PAGE_SIZE 128
743 #define SFP_NUM_PAGES 2
744 static int efx_mcdi_phy_get_module_eeprom(
struct efx_nic *efx,
752 unsigned int space_remaining = ee->
len;
754 unsigned int page_off;
755 unsigned int to_copy;
767 inbuf,
sizeof(inbuf),
768 outbuf,
sizeof(outbuf),
778 GET_PHY_MEDIA_INFO_OUT_DATALEN);
783 payload_len -= page_off;
785 space_remaining : payload_len;
792 space_remaining -= to_copy;
793 user_data += to_copy;
801 static int efx_mcdi_phy_get_module_info(
struct efx_nic *efx,
806 switch (phy_cfg->
media) {
817 .probe = efx_mcdi_phy_probe,
820 .poll = efx_mcdi_phy_poll,
822 .remove = efx_mcdi_phy_remove,
823 .get_settings = efx_mcdi_phy_get_settings,
824 .set_settings = efx_mcdi_phy_set_settings,
825 .test_alive = efx_mcdi_phy_test_alive,
826 .run_tests = efx_mcdi_phy_run_tests,
827 .test_name = efx_mcdi_phy_test_name,
828 .get_module_eeprom = efx_mcdi_phy_get_module_eeprom,
829 .get_module_info = efx_mcdi_phy_get_module_info,