diff --git a/sys/amd64/conf/GENERIC b/sys/amd64/conf/GENERIC --- a/sys/amd64/conf/GENERIC +++ b/sys/amd64/conf/GENERIC @@ -223,6 +223,9 @@ device puc # Multi I/O cards and multi-channel UARTs +# MDIO bus for Ethernet NICs that directly expose the MDIO bus +device mdio + # PCI/PCI-X/PCIe Ethernet NICs that use iflib infrastructure device iflib device em # Intel PRO/1000 Gigabit Ethernet Family diff --git a/sys/conf/NOTES b/sys/conf/NOTES --- a/sys/conf/NOTES +++ b/sys/conf/NOTES @@ -1993,6 +1993,9 @@ device vte # DM&P Vortex86 RDC R6040 Fast Ethernet device xl # 3Com 3c90x (``Boomerang'', ``Cyclone'') +# MDIO bus for Ethernet NICs that directly expose the MDIO bus +device mdio + # PCI/PCI-X/PCIe Ethernet NICs that use iflib infrastructure device iflib device em # Intel Pro/1000 Gigabit Ethernet diff --git a/sys/conf/files b/sys/conf/files --- a/sys/conf/files +++ b/sys/conf/files @@ -2256,6 +2256,8 @@ compile-with "${NORMAL_C} -I$S/dev/ixgbe -DSMP" dev/ixgbe/if_ixv.c optional ixv inet \ compile-with "${NORMAL_C} -I$S/dev/ixgbe -DSMP" +dev/ixgbe/if_ix_mdio.c optional ix inet mdio \ + compile-with "${NORMAL_C} -I$S/dev/ixgbe" dev/ixgbe/if_bypass.c optional ix inet \ compile-with "${NORMAL_C} -I$S/dev/ixgbe" dev/ixgbe/if_fdir.c optional ix inet | ixv inet \ @@ -2290,6 +2292,8 @@ compile-with "${NORMAL_C} -I$S/dev/ixgbe" dev/ixgbe/ixgbe_dcb_82599.c optional ix inet | ixv inet \ compile-with "${NORMAL_C} -I$S/dev/ixgbe" +dev/ixgbe/ixgbe_mdio.c optional ix inet | ixv inet \ + compile-with "${NORMAL_C} -I$S/dev/ixgbe" dev/jedec_dimm/jedec_dimm.c optional jedec_dimm smbus dev/jme/if_jme.c optional jme pci dev/kbd/kbd.c optional atkbd | pckbd | sc | ukbd | vt | hkbd diff --git a/sys/dev/ixgbe/if_ix.c b/sys/dev/ixgbe/if_ix.c --- a/sys/dev/ixgbe/if_ix.c +++ b/sys/dev/ixgbe/if_ix.c @@ -36,10 +36,14 @@ #include "opt_rss.h" #include "ixgbe.h" +#include "mdio_if.h" #include "ixgbe_sriov.h" #include "ifdi_if.h" +#include "ixgbe_mdio.h" +#include "if_ix_mdio.h" #include +#include #include /************************************************************************ @@ -271,6 +275,13 @@ DEVMETHOD(pci_iov_uninit, iflib_device_iov_uninit), DEVMETHOD(pci_iov_add_vf, iflib_device_iov_add_vf), #endif /* PCI_IOV */ + +#if 1 + DEVMETHOD(bus_add_child, device_add_child_ordered), + DEVMETHOD(mdio_readreg, ixgbe_mdio_readreg), + DEVMETHOD(mdio_writereg, ixgbe_mdio_writereg), +#endif + DEVMETHOD_END }; @@ -278,11 +289,13 @@ "ix", ix_methods, sizeof(struct ixgbe_softc), }; -DRIVER_MODULE(ix, pci, ix_driver, 0, 0); +DRIVER_MODULE(mdio, ix, mdio_driver, 0, 0); /* needs to happen before ix */ +DRIVER_MODULE_ORDERED(ix, pci, ix_driver, NULL, NULL, SI_ORDER_ANY); /* needs to be last */ IFLIB_PNP_INFO(pci, ix_driver, ixgbe_vendor_info_array); MODULE_DEPEND(ix, pci, 1, 1, 1); MODULE_DEPEND(ix, ether, 1, 1, 1); MODULE_DEPEND(ix, iflib, 1, 1, 1); +MODULE_DEPEND(ix, mdio, 1, 1, 1); static device_method_t ixgbe_if_methods[] = { DEVMETHOD(ifdi_attach_pre, ixgbe_if_attach_pre), @@ -1198,6 +1211,9 @@ /* Add sysctls */ ixgbe_add_device_sysctls(ctx); + /* Add MDIO bus if required / supported */ + ixgbe_mdio_attach(sc); + /* Init recovery mode timer and state variable */ if (sc->feat_en & IXGBE_FEATURE_RECOVERY_MODE) { sc->recovery_mode = 0; diff --git a/sys/dev/ixgbe/if_ix_mdio.h b/sys/dev/ixgbe/if_ix_mdio.h new file mode 100644 --- /dev/null +++ b/sys/dev/ixgbe/if_ix_mdio.h @@ -0,0 +1,34 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025 Adrian Chadd + * + * 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. + */ + +#ifndef _IF_IX_MDIO_H_ +#define _IF_IX_MDIO_H_ + +int ixgbe_mdio_readreg(device_t, int, int); +int ixgbe_mdio_writereg(device_t, int, int, int); +void ixgbe_mdio_attach(struct ixgbe_softc *); + +#endif /* _IF_IX_MDIO_H */ diff --git a/sys/dev/ixgbe/if_ix_mdio.c b/sys/dev/ixgbe/if_ix_mdio.c new file mode 100644 --- /dev/null +++ b/sys/dev/ixgbe/if_ix_mdio.c @@ -0,0 +1,89 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025 Adrian Chadd + * + * 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 "ixgbe_mdio.h" +#include "if_ix_mdio.h" + +#include + +int +ixgbe_mdio_readreg(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; + + 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); +} + +int +ixgbe_mdio_writereg(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; + + 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); +} + +void +ixgbe_mdio_attach(struct ixgbe_softc *sc) +{ + + device_add_child(sc->dev, "mdio", DEVICE_UNIT_ANY); + bus_attach_children(sc->dev); +} diff --git a/sys/dev/ixgbe/ixgbe_mdio.h b/sys/dev/ixgbe/ixgbe_mdio.h new file mode 100644 --- /dev/null +++ b/sys/dev/ixgbe/ixgbe_mdio.h @@ -0,0 +1,40 @@ +/****************************************************************************** + SPDX-License-Identifier: BSD-3-Clause + + Copyright (c) 2025, Adrian Chadd + + 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. + + 3. Neither the name of the Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + 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. + +******************************************************************************/ + +#ifndef _IXGBE_MDIO_H_ +#define _IXGBE_MDIO_H_ + +s32 ixgbe_read_mdio_c22(struct ixgbe_hw *hw, u16 phy, u16 reg, u16 *phy_data); +s32 ixgbe_write_mdio_c22(struct ixgbe_hw *hw, u16 phy, u16 reg, u16 data); + +#endif /* _IXGBE_MDIO_H_ */ diff --git a/sys/dev/ixgbe/ixgbe_mdio.c b/sys/dev/ixgbe/ixgbe_mdio.c new file mode 100644 --- /dev/null +++ b/sys/dev/ixgbe/ixgbe_mdio.c @@ -0,0 +1,180 @@ +/****************************************************************************** + SPDX-License-Identifier: BSD-3-Clause + + Copyright (c) 2001-2020, Intel Corporation + Copyright (c) 2025, Adrian Chadd + 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. + + 3. Neither the name of the Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + 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. + +******************************************************************************/ + +#include "ixgbe_api.h" +#include "ixgbe_common.h" +#include "ixgbe_phy.h" +#include "ixgbe_mdio.h" + +/* + * These routines are separate from the rest of ixgbe for now to make merging + * easier. + */ + +static s32 +ixgbe_read_mdio_unlocked_c22(struct ixgbe_hw *hw, u16 phy, u16 reg, u16 *phy_data) +{ + u32 i, data, command; + + /* Setup and write the read command */ + command = (reg << IXGBE_MSCA_DEV_TYPE_SHIFT) | + (phy << IXGBE_MSCA_PHY_ADDR_SHIFT) | + IXGBE_MSCA_OLD_PROTOCOL | IXGBE_MSCA_READ_AUTOINC | + IXGBE_MSCA_MDI_COMMAND; + + IXGBE_WRITE_REG(hw, IXGBE_MSCA, command); + + /* Check every 10 usec to see if the access completed. + * The MDI Command bit will clear when the operation is + * complete + */ + for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) { + usec_delay(10); + + command = IXGBE_READ_REG(hw, IXGBE_MSCA); + if (!(command & IXGBE_MSCA_MDI_COMMAND)) + break; + } + + if (command & IXGBE_MSCA_MDI_COMMAND) + return IXGBE_ERR_PHY; + + /* Read operation is complete. Get the data from MSRWD */ + data = IXGBE_READ_REG(hw, IXGBE_MSRWD); + data >>= IXGBE_MSRWD_READ_DATA_SHIFT; + *phy_data = (u16)data; + + return IXGBE_SUCCESS; +} + +static s32 +ixgbe_write_mdio_unlocked_c22(struct ixgbe_hw *hw, u16 phy, u16 reg, u16 phy_data) +{ + u32 i, command; + + /* Put the data in the MDI single read and write data register*/ + IXGBE_WRITE_REG(hw, IXGBE_MSRWD, (u32)phy_data); + + /* Setup and write the write command */ + command = (reg << IXGBE_MSCA_DEV_TYPE_SHIFT) | + (phy << IXGBE_MSCA_PHY_ADDR_SHIFT) | + IXGBE_MSCA_OLD_PROTOCOL | IXGBE_MSCA_WRITE | + IXGBE_MSCA_MDI_COMMAND; + + IXGBE_WRITE_REG(hw, IXGBE_MSCA, command); + + /* Check every 10 usec to see if the access completed. + * The MDI Command bit will clear when the operation is + * complete + */ + for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) { + usec_delay(10); + + command = IXGBE_READ_REG(hw, IXGBE_MSCA); + if (!(command & IXGBE_MSCA_MDI_COMMAND)) + break; + } + + if (command & IXGBE_MSCA_MDI_COMMAND) + return IXGBE_ERR_PHY; + + return IXGBE_SUCCESS; +} + +/* + * Return true if the MAC is an X55x backplane. + * + * These have a single MDIO PHY semaphore (PHY0) and also require the + * token semaphore. + */ +static bool +ixgbe_check_mdio_is_x550em(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; + default: + return false; + } +} + +s32 +ixgbe_read_mdio_c22(struct ixgbe_hw *hw, u16 phy, u16 reg, u16 *phy_data) +{ + u32 gssr = hw->phy.phy_semaphore_mask; + s32 ret; + + if (ixgbe_check_mdio_is_x550em(hw)) + gssr |= IXGBE_GSSR_PHY0_SM | IXGBE_GSSR_TOKEN_SM; + + if (hw->mac.ops.acquire_swfw_sync(hw, gssr)) { + *phy_data = -1; + return IXGBE_ERR_TIMEOUT; + } + + ret = ixgbe_read_mdio_unlocked_c22(hw, phy, reg, phy_data); + if (ret != IXGBE_SUCCESS) + *phy_data = -1; + + hw->mac.ops.release_swfw_sync(hw, gssr); + return ret; +} + +s32 +ixgbe_write_mdio_c22(struct ixgbe_hw *hw, u16 phy, u16 reg, u16 data) +{ + u32 gssr = hw->phy.phy_semaphore_mask; + s32 ret; + + if (ixgbe_check_mdio_is_x550em(hw)) + gssr |= IXGBE_GSSR_PHY0_SM | IXGBE_GSSR_TOKEN_SM; + + if (hw->mac.ops.acquire_swfw_sync(hw, gssr)) + return IXGBE_ERR_TIMEOUT; + + ret = ixgbe_write_mdio_unlocked_c22(hw, phy, reg, data); + + hw->mac.ops.release_swfw_sync(hw, gssr); + return ret; +} diff --git a/sys/modules/ix/Makefile b/sys/modules/ix/Makefile --- a/sys/modules/ix/Makefile +++ b/sys/modules/ix/Makefile @@ -1,13 +1,15 @@ .PATH: ${SRCTOP}/sys/dev/ixgbe KMOD = if_ix -SRCS = device_if.h bus_if.h pci_if.h pci_iov_if.h ifdi_if.h +SRCS = device_if.h bus_if.h pci_if.h pci_iov_if.h ifdi_if.h mdio_if.h SRCS += opt_inet.h opt_inet6.h opt_rss.h SRCS += if_ix.c if_bypass.c if_fdir.c if_sriov.c ix_txrx.c ixgbe_osdep.c +SRCS += if_ix_mdio.c # Shared source SRCS += ixgbe_common.c ixgbe_api.c ixgbe_phy.c ixgbe_mbx.c ixgbe_vf.c SRCS += ixgbe_dcb.c ixgbe_dcb_82598.c ixgbe_dcb_82599.c SRCS += ixgbe_82598.c ixgbe_82599.c ixgbe_x540.c ixgbe_x550.c +SRCS += ixgbe_mdio.c CFLAGS+= -I${SRCTOP}/sys/dev/ixgbe .include