diff options
Diffstat (limited to 'sys/dev/ixgbe/if_ix_mdio.c')
| -rw-r--r-- | sys/dev/ixgbe/if_ix_mdio.c | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/sys/dev/ixgbe/if_ix_mdio.c b/sys/dev/ixgbe/if_ix_mdio.c new file mode 100644 index 000000000000..3aa7ea80c3a7 --- /dev/null +++ b/sys/dev/ixgbe/if_ix_mdio.c @@ -0,0 +1,158 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025 Adrian Chadd <adrian@FreeBSD.org> + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + */ + +#include "opt_inet.h" +#include "opt_inet6.h" +#include "opt_rss.h" + +#include "ixgbe.h" +#include "mdio_if.h" +#include "ixgbe_sriov.h" +#include "ifdi_if.h" +#include "if_ix_mdio_hw.h" +#include "if_ix_mdio.h" + +#include <dev/mdio/mdio.h> + +/** + * @brief Return if the given ixgbe chipset supports clause 22 MDIO bus access. + * + * Although technically all of the ixgbe chipsets support an MDIO + * bus interface, there's a bunch of factors controlling whether + * this should be exposed for external control. + * + * This functionr returns true if it supports an MDIO bus and + * clause 22 transactions. + */ +static bool +ixgbe_has_mdio_bus_clause22(struct ixgbe_hw *hw) +{ + switch (hw->device_id) { + case IXGBE_DEV_ID_X550EM_A_KR: + case IXGBE_DEV_ID_X550EM_A_KR_L: + case IXGBE_DEV_ID_X550EM_A_SFP_N: + case IXGBE_DEV_ID_X550EM_A_SGMII: + case IXGBE_DEV_ID_X550EM_A_SGMII_L: + case IXGBE_DEV_ID_X550EM_A_10G_T: + case IXGBE_DEV_ID_X550EM_A_SFP: + case IXGBE_DEV_ID_X550EM_A_1G_T: + case IXGBE_DEV_ID_X550EM_A_1G_T_L: + return (true); + } + return (false); +} + + + +/** + * @brief Initiate a clause-22 MDIO read transfer. + * + * Note this is only officially supported for a small subset + * of NICs, notably the X552/X553 devices. This must not be + * called for other chipsets. + */ +int +ixgbe_mdio_readreg_c22(device_t dev, int phy, int reg) +{ + if_ctx_t ctx = device_get_softc(dev); + struct sx *iflib_ctx_lock = iflib_ctx_lock_get(ctx); + struct ixgbe_softc *sc = iflib_get_softc(ctx); + struct ixgbe_hw *hw = &sc->hw; + uint16_t val = 0; + int32_t ret = 0; + + if (! ixgbe_has_mdio_bus_clause22(hw)) + return (-1); + + sx_xlock(iflib_ctx_lock); + ret = ixgbe_read_mdio_c22(hw, phy, reg, &val); + if (ret != IXGBE_SUCCESS) { + device_printf(dev, "%s: read_mdi_22 failed (%d)\n", + __func__, ret); + sx_xunlock(iflib_ctx_lock); + return (-1); + } + sx_xunlock(iflib_ctx_lock); + return (val); +} + +/** + * @brief Initiate a clause-22 MDIO write transfer. + * + * Note this is only officially supported for a small subset + * of NICs, notably the X552/X553 devices. This must not be + * called for other chipsets. + */ +int +ixgbe_mdio_writereg_c22(device_t dev, int phy, int reg, int data) +{ + if_ctx_t ctx = device_get_softc(dev); + struct sx *iflib_ctx_lock = iflib_ctx_lock_get(ctx); + struct ixgbe_softc *sc = iflib_get_softc(ctx); + struct ixgbe_hw *hw = &sc->hw; + int32_t ret; + + if (! ixgbe_has_mdio_bus_clause22(hw)) + return (-1); + + sx_xlock(iflib_ctx_lock); + ret = ixgbe_write_mdio_c22(hw, phy, reg, data); + if (ret != IXGBE_SUCCESS) { + device_printf(dev, "%s: write_mdi_22 failed (%d)\n", + __func__, ret); + sx_xunlock(iflib_ctx_lock); + return (-1); + } + sx_xunlock(iflib_ctx_lock); + return (0); +} + +/** + * @brief Attach the MDIO bus if one exists. + */ +void +ixgbe_mdio_attach(struct ixgbe_softc *sc) +{ + struct ixgbe_hw *hw = &sc->hw; + int enable_mdio = 0; + + /* + * This explicitly needs to be enabled regardless of whether + * the device / instance supports an external MDIO bus. + */ + if (resource_int_value(device_get_name(sc->dev), + device_get_unit(sc->dev), "enable_mdio", &enable_mdio) == 0) { + if (enable_mdio == 0) + return; + } else + return; + + if (! ixgbe_has_mdio_bus_clause22(hw)) + return; + + device_add_child(sc->dev, "mdio", DEVICE_UNIT_ANY); + bus_attach_children(sc->dev); +} |
