X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fsfc%2Fbase%2Fefx_nic.c;h=35e84e33161bbd9c8495fa284120320bb9844033;hb=096cd34217f50416d5144474cfa619114984cebb;hp=76caa744c66ea899c249772eb34ebc4fce72ac64;hpb=ba6afee9a81e3d8f210d831f2a958b9cf70a6b2c;p=dpdk.git diff --git a/drivers/net/sfc/base/efx_nic.c b/drivers/net/sfc/base/efx_nic.c index 76caa744c6..35e84e3316 100644 --- a/drivers/net/sfc/base/efx_nic.c +++ b/drivers/net/sfc/base/efx_nic.c @@ -1,41 +1,19 @@ -/* - * Copyright (c) 2007-2016 Solarflare Communications Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. +/* SPDX-License-Identifier: BSD-3-Clause * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are - * those of the authors and should not be interpreted as representing official - * policies, either expressed or implied, of the FreeBSD Project. + * Copyright (c) 2007-2018 Solarflare Communications Inc. + * All rights reserved. */ #include "efx.h" #include "efx_impl.h" + __checkReturn efx_rc_t efx_family( __in uint16_t venid, __in uint16_t devid, - __out efx_family_t *efp) + __out efx_family_t *efp, + __out unsigned int *membarp) { if (venid == EFX_PCI_VENID_SFC) { switch (devid) { @@ -45,12 +23,10 @@ efx_family( * Hardware default for PF0 of uninitialised Siena. * manftest must be able to cope with this device id. */ - *efp = EFX_FAMILY_SIENA; - return (0); - case EFX_PCI_DEVID_BETHPAGE: case EFX_PCI_DEVID_SIENA: *efp = EFX_FAMILY_SIENA; + *membarp = EFX_MEM_BAR_SIENA; return (0); #endif /* EFSYS_OPT_SIENA */ @@ -60,17 +36,16 @@ efx_family( * Hardware default for PF0 of uninitialised Huntington. * manftest must be able to cope with this device id. */ - *efp = EFX_FAMILY_HUNTINGTON; - return (0); - case EFX_PCI_DEVID_FARMINGDALE: case EFX_PCI_DEVID_GREENPORT: *efp = EFX_FAMILY_HUNTINGTON; + *membarp = EFX_MEM_BAR_HUNTINGTON_PF; return (0); case EFX_PCI_DEVID_FARMINGDALE_VF: case EFX_PCI_DEVID_GREENPORT_VF: *efp = EFX_FAMILY_HUNTINGTON; + *membarp = EFX_MEM_BAR_HUNTINGTON_VF; return (0); #endif /* EFSYS_OPT_HUNTINGTON */ @@ -80,18 +55,30 @@ efx_family( * Hardware default for PF0 of uninitialised Medford. * manftest must be able to cope with this device id. */ - *efp = EFX_FAMILY_MEDFORD; - return (0); - case EFX_PCI_DEVID_MEDFORD: *efp = EFX_FAMILY_MEDFORD; + *membarp = EFX_MEM_BAR_MEDFORD_PF; return (0); case EFX_PCI_DEVID_MEDFORD_VF: *efp = EFX_FAMILY_MEDFORD; + *membarp = EFX_MEM_BAR_MEDFORD_VF; return (0); #endif /* EFSYS_OPT_MEDFORD */ +#if EFSYS_OPT_MEDFORD2 + case EFX_PCI_DEVID_MEDFORD2_PF_UNINIT: + /* + * Hardware default for PF0 of uninitialised Medford2. + * manftest must be able to cope with this device id. + */ + case EFX_PCI_DEVID_MEDFORD2: + case EFX_PCI_DEVID_MEDFORD2_VF: + *efp = EFX_FAMILY_MEDFORD2; + *membarp = EFX_MEM_BAR_MEDFORD2; + return (0); +#endif /* EFSYS_OPT_MEDFORD2 */ + case EFX_PCI_DEVID_FALCON: /* Obsolete, not supported */ default: break; @@ -103,77 +90,6 @@ efx_family( } -#define EFX_BIU_MAGIC0 0x01234567 -#define EFX_BIU_MAGIC1 0xfedcba98 - - __checkReturn efx_rc_t -efx_nic_biu_test( - __in efx_nic_t *enp) -{ - efx_oword_t oword; - efx_rc_t rc; - - /* - * Write magic values to scratch registers 0 and 1, then - * verify that the values were written correctly. Interleave - * the accesses to ensure that the BIU is not just reading - * back the cached value that was last written. - */ - EFX_POPULATE_OWORD_1(oword, FRF_AZ_DRIVER_DW0, EFX_BIU_MAGIC0); - EFX_BAR_TBL_WRITEO(enp, FR_AZ_DRIVER_REG, 0, &oword, B_TRUE); - - EFX_POPULATE_OWORD_1(oword, FRF_AZ_DRIVER_DW0, EFX_BIU_MAGIC1); - EFX_BAR_TBL_WRITEO(enp, FR_AZ_DRIVER_REG, 1, &oword, B_TRUE); - - EFX_BAR_TBL_READO(enp, FR_AZ_DRIVER_REG, 0, &oword, B_TRUE); - if (EFX_OWORD_FIELD(oword, FRF_AZ_DRIVER_DW0) != EFX_BIU_MAGIC0) { - rc = EIO; - goto fail1; - } - - EFX_BAR_TBL_READO(enp, FR_AZ_DRIVER_REG, 1, &oword, B_TRUE); - if (EFX_OWORD_FIELD(oword, FRF_AZ_DRIVER_DW0) != EFX_BIU_MAGIC1) { - rc = EIO; - goto fail2; - } - - /* - * Perform the same test, with the values swapped. This - * ensures that subsequent tests don't start with the correct - * values already written into the scratch registers. - */ - EFX_POPULATE_OWORD_1(oword, FRF_AZ_DRIVER_DW0, EFX_BIU_MAGIC1); - EFX_BAR_TBL_WRITEO(enp, FR_AZ_DRIVER_REG, 0, &oword, B_TRUE); - - EFX_POPULATE_OWORD_1(oword, FRF_AZ_DRIVER_DW0, EFX_BIU_MAGIC0); - EFX_BAR_TBL_WRITEO(enp, FR_AZ_DRIVER_REG, 1, &oword, B_TRUE); - - EFX_BAR_TBL_READO(enp, FR_AZ_DRIVER_REG, 0, &oword, B_TRUE); - if (EFX_OWORD_FIELD(oword, FRF_AZ_DRIVER_DW0) != EFX_BIU_MAGIC1) { - rc = EIO; - goto fail3; - } - - EFX_BAR_TBL_READO(enp, FR_AZ_DRIVER_REG, 1, &oword, B_TRUE); - if (EFX_OWORD_FIELD(oword, FRF_AZ_DRIVER_DW0) != EFX_BIU_MAGIC0) { - rc = EIO; - goto fail4; - } - - return (0); - -fail4: - EFSYS_PROBE(fail4); -fail3: - EFSYS_PROBE(fail3); -fail2: - EFSYS_PROBE(fail2); -fail1: - EFSYS_PROBE1(fail1, efx_rc_t, rc); - - return (rc); -} - #if EFSYS_OPT_SIENA static const efx_nic_ops_t __efx_nic_siena_ops = { @@ -231,6 +147,25 @@ static const efx_nic_ops_t __efx_nic_medford_ops = { #endif /* EFSYS_OPT_MEDFORD */ +#if EFSYS_OPT_MEDFORD2 + +static const efx_nic_ops_t __efx_nic_medford2_ops = { + ef10_nic_probe, /* eno_probe */ + medford2_board_cfg, /* eno_board_cfg */ + ef10_nic_set_drv_limits, /* eno_set_drv_limits */ + ef10_nic_reset, /* eno_reset */ + ef10_nic_init, /* eno_init */ + ef10_nic_get_vi_pool, /* eno_get_vi_pool */ + ef10_nic_get_bar_region, /* eno_get_bar_region */ +#if EFSYS_OPT_DIAG + ef10_nic_register_test, /* eno_register_test */ +#endif /* EFSYS_OPT_DIAG */ + ef10_nic_fini, /* eno_fini */ + ef10_nic_unprobe, /* eno_unprobe */ +}; + +#endif /* EFSYS_OPT_MEDFORD2 */ + __checkReturn efx_rc_t efx_nic_create( @@ -309,6 +244,22 @@ efx_nic_create( break; #endif /* EFSYS_OPT_MEDFORD */ +#if EFSYS_OPT_MEDFORD2 + case EFX_FAMILY_MEDFORD2: + enp->en_enop = &__efx_nic_medford2_ops; + enp->en_features = + EFX_FEATURE_IPV6 | + EFX_FEATURE_LINK_EVENTS | + EFX_FEATURE_PERIODIC_MAC_STATS | + EFX_FEATURE_MCDI | + EFX_FEATURE_MAC_HEADER_FILTERS | + EFX_FEATURE_MCDI_DMA | + EFX_FEATURE_PIO_BUFFERS | + EFX_FEATURE_FW_ASSISTED_TSO_V2 | + EFX_FEATURE_PACKED_STREAM; + break; +#endif /* EFSYS_OPT_MEDFORD2 */ + default: rc = ENOTSUP; goto fail2; @@ -637,9 +588,9 @@ efx_nic_get_fw_version( goto fail2; rc = efx_mcdi_get_capabilities(enp, NULL, - &enfip->enfi_rx_dpcpu_fw_id, - &enfip->enfi_tx_dpcpu_fw_id, - NULL, NULL); + &enfip->enfi_rx_dpcpu_fw_id, + &enfip->enfi_tx_dpcpu_fw_id, + NULL, NULL); if (rc == 0) { enfip->enfi_dpcpu_fw_ids_valid = B_TRUE; } else if (rc == ENOTSUP) { @@ -650,7 +601,8 @@ efx_nic_get_fw_version( goto fail3; } - memcpy(enfip->enfi_mc_fw_version, mc_fw_version, sizeof(mc_fw_version)); + memcpy(enfip->enfi_mc_fw_version, mc_fw_version, + sizeof (mc_fw_version)); return (0); @@ -682,139 +634,6 @@ efx_nic_register_test( return (0); -fail1: - EFSYS_PROBE1(fail1, efx_rc_t, rc); - - return (rc); -} - - __checkReturn efx_rc_t -efx_nic_test_registers( - __in efx_nic_t *enp, - __in efx_register_set_t *rsp, - __in size_t count) -{ - unsigned int bit; - efx_oword_t original; - efx_oword_t reg; - efx_oword_t buf; - efx_rc_t rc; - - while (count > 0) { - /* This function is only suitable for registers */ - EFSYS_ASSERT(rsp->rows == 1); - - /* bit sweep on and off */ - EFSYS_BAR_READO(enp->en_esbp, rsp->address, &original, - B_TRUE); - for (bit = 0; bit < 128; bit++) { - /* Is this bit in the mask? */ - if (~(rsp->mask.eo_u32[bit >> 5]) & (1 << bit)) - continue; - - /* Test this bit can be set in isolation */ - reg = original; - EFX_AND_OWORD(reg, rsp->mask); - EFX_SET_OWORD_BIT(reg, bit); - - EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, ®, - B_TRUE); - EFSYS_BAR_READO(enp->en_esbp, rsp->address, &buf, - B_TRUE); - - EFX_AND_OWORD(buf, rsp->mask); - if (memcmp(®, &buf, sizeof (reg))) { - rc = EIO; - goto fail1; - } - - /* Test this bit can be cleared in isolation */ - EFX_OR_OWORD(reg, rsp->mask); - EFX_CLEAR_OWORD_BIT(reg, bit); - - EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, ®, - B_TRUE); - EFSYS_BAR_READO(enp->en_esbp, rsp->address, &buf, - B_TRUE); - - EFX_AND_OWORD(buf, rsp->mask); - if (memcmp(®, &buf, sizeof (reg))) { - rc = EIO; - goto fail2; - } - } - - /* Restore the old value */ - EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, &original, - B_TRUE); - - --count; - ++rsp; - } - - return (0); - -fail2: - EFSYS_PROBE(fail2); -fail1: - EFSYS_PROBE1(fail1, efx_rc_t, rc); - - /* Restore the old value */ - EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, &original, B_TRUE); - - return (rc); -} - - __checkReturn efx_rc_t -efx_nic_test_tables( - __in efx_nic_t *enp, - __in efx_register_set_t *rsp, - __in efx_pattern_type_t pattern, - __in size_t count) -{ - efx_sram_pattern_fn_t func; - unsigned int index; - unsigned int address; - efx_oword_t reg; - efx_oword_t buf; - efx_rc_t rc; - - EFSYS_ASSERT(pattern < EFX_PATTERN_NTYPES); - func = __efx_sram_pattern_fns[pattern]; - - while (count > 0) { - /* Write */ - address = rsp->address; - for (index = 0; index < rsp->rows; ++index) { - func(2 * index + 0, B_FALSE, ®.eo_qword[0]); - func(2 * index + 1, B_FALSE, ®.eo_qword[1]); - EFX_AND_OWORD(reg, rsp->mask); - EFSYS_BAR_WRITEO(enp->en_esbp, address, ®, B_TRUE); - - address += rsp->step; - } - - /* Read */ - address = rsp->address; - for (index = 0; index < rsp->rows; ++index) { - func(2 * index + 0, B_FALSE, ®.eo_qword[0]); - func(2 * index + 1, B_FALSE, ®.eo_qword[1]); - EFX_AND_OWORD(reg, rsp->mask); - EFSYS_BAR_READO(enp->en_esbp, address, &buf, B_TRUE); - if (memcmp(®, &buf, sizeof (reg))) { - rc = EIO; - goto fail1; - } - - address += rsp->step; - } - - ++rsp; - --count; - } - - return (0); - fail1: EFSYS_PROBE1(fail1, efx_rc_t, rc); @@ -835,48 +654,49 @@ efx_loopback_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); + /* Assert the MC_CMD_LOOPBACK and EFX_LOOPBACK namespaces agree */ +#define LOOPBACK_CHECK(_mcdi, _efx) \ + EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_##_mcdi == EFX_LOOPBACK_##_efx) + + LOOPBACK_CHECK(NONE, OFF); + LOOPBACK_CHECK(DATA, DATA); + LOOPBACK_CHECK(GMAC, GMAC); + LOOPBACK_CHECK(XGMII, XGMII); + LOOPBACK_CHECK(XGXS, XGXS); + LOOPBACK_CHECK(XAUI, XAUI); + LOOPBACK_CHECK(GMII, GMII); + LOOPBACK_CHECK(SGMII, SGMII); + LOOPBACK_CHECK(XGBR, XGBR); + LOOPBACK_CHECK(XFI, XFI); + LOOPBACK_CHECK(XAUI_FAR, XAUI_FAR); + LOOPBACK_CHECK(GMII_FAR, GMII_FAR); + LOOPBACK_CHECK(SGMII_FAR, SGMII_FAR); + LOOPBACK_CHECK(XFI_FAR, XFI_FAR); + LOOPBACK_CHECK(GPHY, GPHY); + LOOPBACK_CHECK(PHYXS, PHY_XS); + LOOPBACK_CHECK(PCS, PCS); + LOOPBACK_CHECK(PMAPMD, PMA_PMD); + LOOPBACK_CHECK(XPORT, XPORT); + LOOPBACK_CHECK(XGMII_WS, XGMII_WS); + LOOPBACK_CHECK(XAUI_WS, XAUI_WS); + LOOPBACK_CHECK(XAUI_WS_FAR, XAUI_WS_FAR); + LOOPBACK_CHECK(XAUI_WS_NEAR, XAUI_WS_NEAR); + LOOPBACK_CHECK(GMII_WS, GMII_WS); + LOOPBACK_CHECK(XFI_WS, XFI_WS); + LOOPBACK_CHECK(XFI_WS_FAR, XFI_WS_FAR); + LOOPBACK_CHECK(PHYXS_WS, PHYXS_WS); + LOOPBACK_CHECK(PMA_INT, PMA_INT); + LOOPBACK_CHECK(SD_NEAR, SD_NEAR); + LOOPBACK_CHECK(SD_FAR, SD_FAR); + LOOPBACK_CHECK(PMA_INT_WS, PMA_INT_WS); + LOOPBACK_CHECK(SD_FEP2_WS, SD_FEP2_WS); + LOOPBACK_CHECK(SD_FEP1_5_WS, SD_FEP1_5_WS); + LOOPBACK_CHECK(SD_FEP_WS, SD_FEP_WS); + LOOPBACK_CHECK(SD_FES_WS, SD_FES_WS); + LOOPBACK_CHECK(AOE_INT_NEAR, AOE_INT_NEAR); + LOOPBACK_CHECK(DATA_WS, DATA_WS); + LOOPBACK_CHECK(FORCE_EXT_LINK, FORCE_EXT_LINK); +#undef LOOPBACK_CHECK /* Build bitmask of possible loopback types */ EFX_ZERO_QWORD(mask); @@ -934,7 +754,7 @@ efx_mcdi_get_loopback_modes( 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)]; + MC_CMD_GET_LOOPBACK_MODES_OUT_V2_LEN)]; efx_qword_t mask; efx_qword_t modes; efx_rc_t rc; @@ -944,7 +764,7 @@ efx_mcdi_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; + req.emr_out_length = MC_CMD_GET_LOOPBACK_MODES_OUT_V2_LEN; efx_mcdi_execute(enp, &req); @@ -985,18 +805,51 @@ efx_mcdi_get_loopback_modes( 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); + 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; } + if (req.emr_out_length_used >= + MC_CMD_GET_LOOPBACK_MODES_OUT_V2_25G_OFST + + MC_CMD_GET_LOOPBACK_MODES_OUT_V2_25G_LEN) { + /* Response includes 25G loopback modes */ + modes = *MCDI_OUT2(req, efx_qword_t, + GET_LOOPBACK_MODES_OUT_V2_25G); + EFX_AND_QWORD(modes, mask); + encp->enc_loopback_types[EFX_LINK_25000FDX] = modes; + } + + if (req.emr_out_length_used >= + MC_CMD_GET_LOOPBACK_MODES_OUT_V2_50G_OFST + + MC_CMD_GET_LOOPBACK_MODES_OUT_V2_50G_LEN) { + /* Response includes 50G loopback modes */ + modes = *MCDI_OUT2(req, efx_qword_t, + GET_LOOPBACK_MODES_OUT_V2_50G); + EFX_AND_QWORD(modes, mask); + encp->enc_loopback_types[EFX_LINK_50000FDX] = modes; + } + + if (req.emr_out_length_used >= + MC_CMD_GET_LOOPBACK_MODES_OUT_V2_100G_OFST + + MC_CMD_GET_LOOPBACK_MODES_OUT_V2_100G_LEN) { + /* Response includes 100G loopback modes */ + modes = *MCDI_OUT2(req, efx_qword_t, + GET_LOOPBACK_MODES_OUT_V2_100G); + EFX_AND_QWORD(modes, mask); + encp->enc_loopback_types[EFX_LINK_100000FDX] = 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]); + EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_25000FDX]); + EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_50000FDX]); + EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_100000FDX]); encp->enc_loopback_types[EFX_LINK_UNKNOWN] = modes; return (0);