summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarkus Stockhausen2025-06-03 18:21:48 +0000
committerRobert Marko2025-06-11 20:27:22 +0000
commitec310a0993e74d64ebf9bd2b649a3ac321e3bf82 (patch)
tree55eeeb6681844e604221a628be7123c64541a088
parent30fae30e038ba6a5fe8184fa339355cfcfd15c43 (diff)
downloadopenwrt-ec310a0993e74d64ebf9bd2b649a3ac321e3bf82.tar.gz
realtek: 6.12: allow fiber media status to be read without lock
rtl8214fc_media_is_fibre() will need to be run when bus lock is held. Split the function into two versions. Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de> Link: https://github.com/openwrt/openwrt/pull/18935 Signed-off-by: Robert Marko <robimarko@gmail.com>
-rw-r--r--target/linux/realtek/files-6.12/drivers/net/phy/rtl83xx-phy.c39
1 files changed, 29 insertions, 10 deletions
diff --git a/target/linux/realtek/files-6.12/drivers/net/phy/rtl83xx-phy.c b/target/linux/realtek/files-6.12/drivers/net/phy/rtl83xx-phy.c
index ab8126f82a..8d30348082 100644
--- a/target/linux/realtek/files-6.12/drivers/net/phy/rtl83xx-phy.c
+++ b/target/linux/realtek/files-6.12/drivers/net/phy/rtl83xx-phy.c
@@ -981,21 +981,40 @@ static int rtl8380_configure_ext_rtl8218b(struct phy_device *phydev)
return 0;
}
-static bool rtl8214fc_media_is_fibre(struct phy_device *phydev)
+static bool __rtl8214fc_media_is_fibre(struct phy_device *phydev)
{
- int mac = phydev->mdio.addr;
+ struct mii_bus *bus = phydev->mdio.bus;
+ static int regs[] = {16, 19, 20, 21};
+ int addr = phydev->mdio.addr & ~3;
+ int reg = regs[phydev->mdio.addr & 3];
+ int oldpage, val;
- static int reg[] = {16, 19, 20, 21};
- u32 val;
+ /*
+ * The fiber status cannot be read directly from the phy. It is a package "global"
+ * attribute and therefore located in the first phy. To avoid state handling assume
+ * an aligment to addresses divisible by 4.
+ */
- phy_package_write_paged(phydev, RTL838X_PAGE_RAW, RTL821XINT_MEDIA_PAGE_SELECT, RTL821X_MEDIA_PAGE_INTERNAL);
- val = phy_package_read_paged(phydev, RTL821X_PAGE_PORT, reg[mac % 4]);
- phy_package_write_paged(phydev, RTL838X_PAGE_RAW, RTL821XINT_MEDIA_PAGE_SELECT, RTL821X_MEDIA_PAGE_AUTO);
+ oldpage = __mdiobus_read(bus, addr, RTL8XXX_PAGE_SELECT);
+ __mdiobus_write(bus, addr, RTL821XINT_MEDIA_PAGE_SELECT, RTL821X_MEDIA_PAGE_INTERNAL);
+ __mdiobus_write(bus, addr, RTL8XXX_PAGE_SELECT, RTL821X_PAGE_PORT);
+ val = __mdiobus_read(bus, addr, reg);
+ __mdiobus_write(bus, addr, RTL821XINT_MEDIA_PAGE_SELECT, RTL821X_MEDIA_PAGE_AUTO);
+ __mdiobus_write(bus, addr, RTL8XXX_PAGE_SELECT, oldpage);
- if (val & BMCR_PDOWN)
- return false;
+ return !(val & BMCR_PDOWN);
+}
+
+static bool rtl8214fc_media_is_fibre(struct phy_device *phydev)
+{
+ struct mii_bus *bus = phydev->mdio.bus;
+ int ret;
- return true;
+ mutex_lock(&bus->mdio_lock);
+ ret = __rtl8214fc_media_is_fibre(phydev);
+ mutex_unlock(&bus->mdio_lock);
+
+ return ret;
}
static void rtl8214fc_power_set(struct phy_device *phydev, int port, bool on)