From 8482b9983bb4cb17d0f7c405b907b5f98ab20aec Mon Sep 17 00:00:00 2001 From: Markus Stockhausen Date: Wed, 6 May 2026 22:19:41 +0200 Subject: [PATCH] realtek: mdio: add reverse lookup bus/phy to port Until now there is a O(n) loop that looks up a port for a given bus/phy combination. This is slow for high port count devices (RTL839x and RTL931x). Implement a efficient reverse lookup table for that. While we are here adapt tiny bits of the documentation to better reflect the driver logic after the recent refactoring. Signed-off-by: Markus Stockhausen Link: https://github.com/openwrt/openwrt/pull/23230 Signed-off-by: Robert Marko --- .../drivers/net/mdio/mdio-realtek-otto.c | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/target/linux/realtek/files-6.18/drivers/net/mdio/mdio-realtek-otto.c b/target/linux/realtek/files-6.18/drivers/net/mdio/mdio-realtek-otto.c index da476ade578..a3a0b08c9d0 100644 --- a/target/linux/realtek/files-6.18/drivers/net/mdio/mdio-realtek-otto.c +++ b/target/linux/realtek/files-6.18/drivers/net/mdio/mdio-realtek-otto.c @@ -180,8 +180,8 @@ * all 8 ports of the PHY individually. * * While the C45 clause stuff is pretty standard the legacy functions basically track - * the accesses and the state of the bus with the attributes page[], raw[] and portaddr - * of the bus_priv structure. The page selection works as follows: + * the accesses and the state of the bus with the rtmd_port attributes of the control + * structure. The page selection works as follows: * * phy_write(phydev, RTMD_PAGE_SELECT, 12) : store internal page 12 in driver * phy_write(phydev, 7, 33) : write page=12, reg=7, val=33 @@ -233,6 +233,7 @@ struct rtmd_ctrl { struct rtmd_chan { struct rtmd_ctrl *ctrl; u8 smi_bus; + s8 port[PHY_MAX_ADDR]; }; struct rtmd_command_data { @@ -281,14 +282,8 @@ static inline struct rtmd_ctrl *rtmd_ctrl_from_bus(struct mii_bus *bus) static int rtmd_phy_to_port(struct mii_bus *bus, int phy) { struct rtmd_chan *chan = bus->priv; - struct rtmd_ctrl *ctrl = chan->ctrl; - int pn; - for_each_port(ctrl, pn) - if (ctrl->port[pn].smi_bus == chan->smi_bus && ctrl->port[pn].smi_addr == phy) - return pn; - - return -ENOENT; + return chan->port[phy]; } static int rtmd_run_cmd(struct mii_bus *bus, u32 cmd, @@ -537,7 +532,7 @@ static int rtmd_read_c45(struct mii_bus *bus, int phy, int devnum, int regnum) pn = rtmd_phy_to_port(bus, phy); if (pn < 0) - return pn; + return -ENOENT; guard(mutex)(&ctrl->lock); ret = (*ctrl->cfg->read_c45)(bus, pn, devnum, regnum, &val); @@ -554,7 +549,7 @@ static int rtmd_read_c22(struct mii_bus *bus, int phy, int regnum) pn = rtmd_phy_to_port(bus, phy); if (pn < 0) - return pn; + return -ENOENT; guard(mutex)(&ctrl->lock); if (regnum == RTMD_PAGE_SELECT && @@ -577,7 +572,7 @@ static int rtmd_write_c45(struct mii_bus *bus, int phy, int devnum, int regnum, pn = rtmd_phy_to_port(bus, phy); if (pn < 0) - return pn; + return -ENOENT; guard(mutex)(&ctrl->lock); ret = (*ctrl->cfg->write_c45)(bus, pn, devnum, regnum, val); @@ -594,7 +589,7 @@ static int rtmd_write_c22(struct mii_bus *bus, int phy, int regnum, u16 val) pn = rtmd_phy_to_port(bus, phy); if (pn < 0) - return pn; + return -ENOENT; guard(mutex)(&ctrl->lock); page = ctrl->port[pn].page; @@ -1008,6 +1003,7 @@ static int rtmd_probe_one(struct device *dev, struct rtmd_ctrl *ctrl, struct rtmd_chan *chan; struct mii_bus *bus; int smi_bus, ret; + u32 pn; ret = fwnode_property_read_u32(fw_bus, "reg", &smi_bus); if (ret) @@ -1025,6 +1021,13 @@ static int rtmd_probe_one(struct device *dev, struct rtmd_ctrl *ctrl, chan->ctrl = ctrl; chan->smi_bus = smi_bus; + /* setup reverse lookup bus/phy -> port */ + for (int smi_addr = 0; smi_addr < ARRAY_SIZE(chan->port); smi_addr++) + chan->port[smi_addr] = -1; + for_each_port(ctrl, pn) + if (ctrl->port[pn].smi_bus == smi_bus) + chan->port[ctrl->port[pn].smi_addr] = pn; + bus->name = "Realtek MDIO bus"; bus->read = rtmd_read_c22; bus->write = rtmd_write_c22;