From 38f961e744840db9044af68f4773ae5feae60a89 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Mon, 20 Apr 2020 23:29:05 +0200 Subject: [PATCH 1/2] net: phy: add device-managed devm_mdiobus_register If there's no special ordering requirement for mdiobus_unregister(), then driver code can be simplified by using a device-managed version of mdiobus_register(). Prerequisite is that bus allocation has been done device-managed too. Else mdiobus_free() may be called whilst bus is still registered, resulting in a BUG_ON(). Therefore let devm_mdiobus_register() return -EPERM if bus was allocated non-managed. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/phy/mdio_bus.c | 8 +++++++- include/linux/phy.h | 17 +++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 346e88435d29..26b00af94573 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -170,7 +170,12 @@ EXPORT_SYMBOL(mdiobus_alloc_size); static void _devm_mdiobus_free(struct device *dev, void *res) { - mdiobus_free(*(struct mii_bus **)res); + struct mii_bus *bus = *(struct mii_bus **)res; + + if (bus->is_managed_registered && bus->state == MDIOBUS_REGISTERED) + mdiobus_unregister(bus); + + mdiobus_free(bus); } static int devm_mdiobus_match(struct device *dev, void *res, void *data) @@ -210,6 +215,7 @@ struct mii_bus *devm_mdiobus_alloc_size(struct device *dev, int sizeof_priv) if (bus) { *ptr = bus; devres_add(dev, ptr); + bus->is_managed = 1; } else { devres_free(ptr); } diff --git a/include/linux/phy.h b/include/linux/phy.h index 2432ca463ddc..3941a6bcba10 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -241,6 +241,9 @@ struct mii_bus { int (*reset)(struct mii_bus *bus); struct mdio_bus_stats stats[PHY_MAX_ADDR]; + unsigned int is_managed:1; /* is device-managed */ + unsigned int is_managed_registered:1; + /* * A lock to ensure that only one thing can read/write * the MDIO bus at a time @@ -286,6 +289,20 @@ static inline struct mii_bus *mdiobus_alloc(void) int __mdiobus_register(struct mii_bus *bus, struct module *owner); #define mdiobus_register(bus) __mdiobus_register(bus, THIS_MODULE) +static inline int devm_mdiobus_register(struct mii_bus *bus) +{ + int ret; + + if (!bus->is_managed) + return -EPERM; + + ret = mdiobus_register(bus); + if (!ret) + bus->is_managed_registered = 1; + + return ret; +} + void mdiobus_unregister(struct mii_bus *bus); void mdiobus_free(struct mii_bus *bus); struct mii_bus *devm_mdiobus_alloc_size(struct device *dev, int sizeof_priv); From 0785dad48003408da27579845db2f83c024636df Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Mon, 20 Apr 2020 23:29:55 +0200 Subject: [PATCH 2/2] r8169: use devm_mdiobus_register Use new function devm_mdiobus_register() to simplify the driver. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169_main.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c index b7a2853e7396..4c616701856a 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -5185,20 +5185,18 @@ static int r8169_mdio_register(struct rtl8169_private *tp) new_bus->read = r8169_mdio_read_reg; new_bus->write = r8169_mdio_write_reg; - ret = mdiobus_register(new_bus); + ret = devm_mdiobus_register(new_bus); if (ret) return ret; tp->phydev = mdiobus_get_phy(new_bus, 0); if (!tp->phydev) { - mdiobus_unregister(new_bus); return -ENODEV; } else if (!tp->phydev->drv) { /* Most chip versions fail with the genphy driver. * Therefore ensure that the dedicated PHY driver is loaded. */ dev_err(&pdev->dev, "realtek.ko not loaded, maybe it needs to be added to initramfs?\n"); - mdiobus_unregister(new_bus); return -EUNATCH; } @@ -5523,7 +5521,7 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) rc = register_netdev(dev); if (rc) - goto err_mdio_unregister; + return rc; netif_info(tp, probe, dev, "%s, %pM, XID %03x, IRQ %d\n", rtl_chip_infos[chipset].name, dev->dev_addr, xid, @@ -5542,10 +5540,6 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) pm_runtime_put_sync(&pdev->dev); return 0; - -err_mdio_unregister: - mdiobus_unregister(tp->phydev->mdio.bus); - return rc; } static struct pci_driver rtl8169_pci_driver = {