[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID:
<176133848134.2245037.8819965842869649833.stgit@ahduyck-xeon-server.home.arpa>
Date: Fri, 24 Oct 2025 13:41:21 -0700
From: Alexander Duyck <alexander.duyck@...il.com>
To: netdev@...r.kernel.org
Cc: kuba@...nel.org, kernel-team@...a.com, andrew+netdev@...n.ch,
hkallweit1@...il.com, linux@...linux.org.uk, pabeni@...hat.com,
davem@...emloft.net
Subject: [net-next PATCH 7/8] fbnic: Add SW shim for MII interface to PMA/PMD
From: Alexander Duyck <alexanderduyck@...com>
In order for us to support a phydev device we need to add an MII bus to
allow the phydev driver to have access to the registers for the device.
This change adds such an interface, currently as a read only interface for
a single PHY.
The plan is in the future to extend out this interface adding RSFEC support
to the PMA, and eventually adding PCS register access through a remapping
of our CSRs which will essentialy convert the standard c45 offsets to ones
matching the setup within our device.
Signed-off-by: Alexander Duyck <alexanderduyck@...com>
---
drivers/net/ethernet/meta/fbnic/Makefile | 1
drivers/net/ethernet/meta/fbnic/fbnic.h | 5 +
drivers/net/ethernet/meta/fbnic/fbnic_pci.c | 3 +
drivers/net/ethernet/meta/fbnic/fbnic_swmii.c | 145 +++++++++++++++++++++++++
4 files changed, 154 insertions(+)
create mode 100644 drivers/net/ethernet/meta/fbnic/fbnic_swmii.c
diff --git a/drivers/net/ethernet/meta/fbnic/Makefile b/drivers/net/ethernet/meta/fbnic/Makefile
index 15e8ff649615..b15616c3523c 100644
--- a/drivers/net/ethernet/meta/fbnic/Makefile
+++ b/drivers/net/ethernet/meta/fbnic/Makefile
@@ -21,6 +21,7 @@ fbnic-y := fbnic_csr.o \
fbnic_pci.o \
fbnic_phylink.o \
fbnic_rpc.o \
+ fbnic_swmii.o \
fbnic_time.o \
fbnic_tlv.o \
fbnic_txrx.o \
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic.h b/drivers/net/ethernet/meta/fbnic/fbnic.h
index 783a1a91dd25..4a77ea12ddec 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic.h
+++ b/drivers/net/ethernet/meta/fbnic/fbnic.h
@@ -95,6 +95,9 @@ struct fbnic_dev {
u64 prev_firmware_time;
struct fbnic_fw_log fw_log;
+
+ /* SW MII bus for FW PHY */
+ struct mii_bus *mii_bus;
};
/* Reserve entry 0 in the MSI-X "others" array until we have filled all
@@ -204,6 +207,8 @@ void fbnic_dbg_exit(void);
void fbnic_rpc_reset_valid_entries(struct fbnic_dev *fbd);
+int fbnic_swmii_create(struct fbnic_dev *fbd);
+
void fbnic_csr_get_regs(struct fbnic_dev *fbd, u32 *data, u32 *regs_version);
int fbnic_csr_regs_len(struct fbnic_dev *fbd);
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_pci.c b/drivers/net/ethernet/meta/fbnic/fbnic_pci.c
index 428fc861deff..a5390996393c 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic_pci.c
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_pci.c
@@ -339,6 +339,9 @@ static int fbnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto init_failure_mode;
}
+ if (fbnic_swmii_create(fbd))
+ goto init_failure_mode;
+
netdev = fbnic_netdev_alloc(fbd);
if (!netdev) {
dev_err(&pdev->dev, "Netdev allocation failed\n");
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_swmii.c b/drivers/net/ethernet/meta/fbnic/fbnic_swmii.c
new file mode 100644
index 000000000000..7698fb60f660
--- /dev/null
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_swmii.c
@@ -0,0 +1,145 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) Meta Platforms, Inc. and affiliates. */
+
+#include <linux/mdio.h>
+
+#include "fbnic.h"
+#include "fbnic_netdev.h"
+
+static int
+fbnic_swmii_read_pmapmd(struct fbnic_dev *fbd, int regnum)
+{
+ u16 ctrl1 = 0, ctrl2 = 0;
+ struct fbnic_net *fbn;
+ int ret = 0;
+ u8 aui;
+
+ if (fbd->netdev) {
+ fbn = netdev_priv(fbd->netdev);
+ aui = fbn->aui;
+ }
+
+ switch (aui) {
+ case FBNIC_AUI_25GAUI:
+ ctrl1 = MDIO_CTRL1_SPEED25G;
+ ctrl2 = MDIO_PMA_CTRL2_25GBCR;
+ break;
+ case FBNIC_AUI_LAUI2:
+ ctrl1 = MDIO_CTRL1_SPEED50G;
+ ctrl2 = MDIO_PMA_CTRL2_50GBCR2;
+ break;
+ case FBNIC_AUI_50GAUI1:
+ ctrl1 = MDIO_CTRL1_SPEED50G;
+ ctrl2 = MDIO_PMA_CTRL2_50GBCR;
+ break;
+ case FBNIC_AUI_100GAUI2:
+ ctrl1 = MDIO_CTRL1_SPEED100G;
+ ctrl2 = MDIO_PMA_CTRL2_100GBCR2;
+ break;
+ default:
+ break;
+ }
+
+ switch (regnum) {
+ case MDIO_CTRL1:
+ ret = ctrl1;
+ break;
+ case MDIO_STAT1:
+ ret = fbd->pmd_state == FBNIC_PMD_SEND_DATA ?
+ MDIO_STAT1_LSTATUS : 0;
+ break;
+ case MDIO_DEVS1:
+ ret = MDIO_DEVS_PMAPMD;
+ break;
+ case MDIO_CTRL2:
+ ret = ctrl2;
+ break;
+ case MDIO_STAT2:
+ ret = MDIO_STAT2_DEVPRST_VAL |
+ MDIO_PMA_STAT2_EXTABLE;
+ break;
+ case MDIO_PMA_EXTABLE:
+ ret = MDIO_PMA_EXTABLE_40_100G |
+ MDIO_PMA_EXTABLE_25G;
+ break;
+ case MDIO_PMA_40G_EXTABLE:
+ ret = MDIO_PMA_40G_EXTABLE_50GBCR2;
+ break;
+ case MDIO_PMA_25G_EXTABLE:
+ ret = MDIO_PMA_25G_EXTABLE_25GBCR;
+ break;
+ case MDIO_PMA_50G_EXTABLE:
+ ret = MDIO_PMA_50G_EXTABLE_50GBCR;
+ break;
+ case MDIO_PMA_EXTABLE2:
+ ret = MDIO_PMA_EXTABLE2_50G;
+ break;
+ case MDIO_PMA_100G_EXTABLE:
+ ret = MDIO_PMA_100G_EXTABLE_100GBCR2;
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+static int
+fbnic_swmii_read_c45(struct mii_bus *bus, int addr, int devnum, int regnum)
+{
+ struct fbnic_dev *fbd = bus->priv;
+
+ if (addr != 0)
+ return 0xffff;
+
+ if (devnum == MDIO_MMD_PMAPMD)
+ return fbnic_swmii_read_pmapmd(fbd, regnum);
+
+ return 0xffff;
+}
+
+static int
+fbnic_swmii_write_c45(struct mii_bus *bus, int addr, int devnum,
+ int regnum, u16 val)
+{
+ /* Currently PHY setup is meant to be read-only */
+ return 0;
+}
+
+/**
+ * fbnic_swmii_create - Create a swmii to allow interfacing phydev w/ FW PHY
+ * @fbd: Pointer to FBNIC device structure to populate bus on
+ *
+ * Initialize an MII bus and place a pointer to it on the fbd struct. This bus
+ * will be used to interface with the PMA/PMD for now, and may add support for
+ * the PCS in the future.
+ *
+ * Return: 0 on success, negative on failure
+ **/
+int fbnic_swmii_create(struct fbnic_dev *fbd)
+{
+ struct mii_bus *bus;
+ int err;
+
+ bus = devm_mdiobus_alloc(fbd->dev);
+ if (!bus)
+ return -ENOMEM;
+
+ bus->name = "fbnic_mii_bus";
+ bus->read_c45 = &fbnic_swmii_read_c45;
+ bus->write_c45 = &fbnic_swmii_write_c45;
+ bus->parent = fbd->dev;
+ bus->phy_mask = GENMASK(31, 1);
+ bus->priv = fbd;
+ snprintf(bus->id, MII_BUS_ID_SIZE, "%s-mii", dev_name(fbd->dev));
+
+ err = devm_mdiobus_register(fbd->dev, bus);
+ if (err) {
+ dev_err(fbd->dev, "Failed to create MDIO bus: %d\n", err);
+ return err;
+ }
+
+ fbd->mii_bus = bus;
+
+ return 0;
+}
Powered by blists - more mailing lists