diff options
| author | Adrian Chadd <adrian@FreeBSD.org> | 2026-04-17 10:11:42 -0700 |
|---|---|---|
| committer | Adrian Chadd <adrian@FreeBSD.org> | 2026-04-17 10:11:42 -0700 |
| commit | cfec995c87f39e59c80554b85625b4aaa8ddf8db (patch) | |
| tree | 7e2e211a81a88b174ffe851097d6edc6a1f4561b /sys/dev | |
| parent | eb0279550d52962241b4178101cd7f7d732eb682 (diff) | |
ixgbe: add MDIO bus support
This works enough to let me see the marvell switch on the MDIO bus.
It uses clause 22, which ixgbe's existing MDIO code doesn't currently
support, so it's implemented in a new source file.
Since mdio(4) is now required, add it where appropriate to GENERIC kernels.
Reviewed by: kbowling
Differential Revision: https://reviews.freebsd.org/D50128
Diffstat (limited to 'sys/dev')
| -rw-r--r-- | sys/dev/ixgbe/if_ix.c | 15 | ||||
| -rw-r--r-- | sys/dev/ixgbe/if_ix_mdio.c | 158 | ||||
| -rw-r--r-- | sys/dev/ixgbe/if_ix_mdio.h | 34 | ||||
| -rw-r--r-- | sys/dev/ixgbe/if_ix_mdio_hw.c | 181 | ||||
| -rw-r--r-- | sys/dev/ixgbe/if_ix_mdio_hw.h | 33 |
5 files changed, 420 insertions, 1 deletions
diff --git a/sys/dev/ixgbe/if_ix.c b/sys/dev/ixgbe/if_ix.c index 829fbba48a72..b9d88fcab523 100644 --- 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 "if_ix_mdio_hw.h" +#include "if_ix_mdio.h" #include <net/netmap.h> +#include <dev/mdio/mdio.h> #include <dev/netmap/netmap_kern.h> /************************************************************************ @@ -298,6 +302,10 @@ static device_method_t ix_methods[] = { DEVMETHOD(pci_iov_uninit, iflib_device_iov_uninit), DEVMETHOD(pci_iov_add_vf, iflib_device_iov_add_vf), #endif /* PCI_IOV */ + DEVMETHOD(bus_add_child, device_add_child_ordered), + DEVMETHOD(mdio_readreg, ixgbe_mdio_readreg_c22), + DEVMETHOD(mdio_writereg, ixgbe_mdio_writereg_c22), + DEVMETHOD_END }; @@ -305,11 +313,13 @@ static driver_t ix_driver = { "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), @@ -1274,6 +1284,9 @@ ixgbe_if_attach_post(if_ctx_t ctx) /* 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.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); +} diff --git a/sys/dev/ixgbe/if_ix_mdio.h b/sys/dev/ixgbe/if_ix_mdio.h new file mode 100644 index 000000000000..f9fe99275b2b --- /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 <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. + */ + +#ifndef _IF_IX_MDIO_H_ +#define _IF_IX_MDIO_H_ + +int ixgbe_mdio_readreg_c22(device_t, int, int); +int ixgbe_mdio_writereg_c22(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_hw.c b/sys/dev/ixgbe/if_ix_mdio_hw.c new file mode 100644 index 000000000000..581ed09f27e3 --- /dev/null +++ b/sys/dev/ixgbe/if_ix_mdio_hw.c @@ -0,0 +1,181 @@ +/****************************************************************************** + SPDX-License-Identifier: BSD-3-Clause + + Copyright (c) 2001-2024, Intel Corporation + All rights reserved. + Copyright (c) 2026 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. + + 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 "if_ix_mdio_hw.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/dev/ixgbe/if_ix_mdio_hw.h b/sys/dev/ixgbe/if_ix_mdio_hw.h new file mode 100644 index 000000000000..b2db5d431819 --- /dev/null +++ b/sys/dev/ixgbe/if_ix_mdio_hw.h @@ -0,0 +1,33 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2026 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. + */ + +#ifndef _IF_IX_MDIO_HW_H_ +#define _IF_IX_MDIO_HW_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 /* _IF_IX_MDIO_HW_H_ */ |
