]> git.ipfire.org Git - thirdparty/openwrt.git/commitdiff
realtek: mdio: add reverse lookup bus/phy to port 23230/head
authorMarkus Stockhausen <markus.stockhausen@gmx.de>
Wed, 6 May 2026 20:19:41 +0000 (22:19 +0200)
committerRobert Marko <robimarko@gmail.com>
Mon, 11 May 2026 08:32:30 +0000 (10:32 +0200)
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 <markus.stockhausen@gmx.de>
Link: https://github.com/openwrt/openwrt/pull/23230
Signed-off-by: Robert Marko <robimarko@gmail.com>
target/linux/realtek/files-6.18/drivers/net/mdio/mdio-realtek-otto.c

index da476ade57803fa7d5e71ec355f3a6a7c9d13edc..a3a0b08c9d04348ba1f5d94380583ed48c7847ee 100644 (file)
  * 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;