Commit 58989d7c authored by David S. Miller's avatar David S. Miller

Merge branch 'net-phy-add-device-managed-devm_mdiobus_register'

Heiner Kallweit says:

====================
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.

First user of the new functionality is r8169 driver.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 4406d36d 0785dad4
...@@ -5185,20 +5185,18 @@ static int r8169_mdio_register(struct rtl8169_private *tp) ...@@ -5185,20 +5185,18 @@ static int r8169_mdio_register(struct rtl8169_private *tp)
new_bus->read = r8169_mdio_read_reg; new_bus->read = r8169_mdio_read_reg;
new_bus->write = r8169_mdio_write_reg; new_bus->write = r8169_mdio_write_reg;
ret = mdiobus_register(new_bus); ret = devm_mdiobus_register(new_bus);
if (ret) if (ret)
return ret; return ret;
tp->phydev = mdiobus_get_phy(new_bus, 0); tp->phydev = mdiobus_get_phy(new_bus, 0);
if (!tp->phydev) { if (!tp->phydev) {
mdiobus_unregister(new_bus);
return -ENODEV; return -ENODEV;
} else if (!tp->phydev->drv) { } else if (!tp->phydev->drv) {
/* Most chip versions fail with the genphy driver. /* Most chip versions fail with the genphy driver.
* Therefore ensure that the dedicated PHY driver is loaded. * 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"); dev_err(&pdev->dev, "realtek.ko not loaded, maybe it needs to be added to initramfs?\n");
mdiobus_unregister(new_bus);
return -EUNATCH; return -EUNATCH;
} }
...@@ -5523,7 +5521,7 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -5523,7 +5521,7 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
rc = register_netdev(dev); rc = register_netdev(dev);
if (rc) if (rc)
goto err_mdio_unregister; return rc;
netif_info(tp, probe, dev, "%s, %pM, XID %03x, IRQ %d\n", netif_info(tp, probe, dev, "%s, %pM, XID %03x, IRQ %d\n",
rtl_chip_infos[chipset].name, dev->dev_addr, xid, 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) ...@@ -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); pm_runtime_put_sync(&pdev->dev);
return 0; return 0;
err_mdio_unregister:
mdiobus_unregister(tp->phydev->mdio.bus);
return rc;
} }
static struct pci_driver rtl8169_pci_driver = { static struct pci_driver rtl8169_pci_driver = {
......
...@@ -170,7 +170,12 @@ EXPORT_SYMBOL(mdiobus_alloc_size); ...@@ -170,7 +170,12 @@ EXPORT_SYMBOL(mdiobus_alloc_size);
static void _devm_mdiobus_free(struct device *dev, void *res) 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) 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) ...@@ -210,6 +215,7 @@ struct mii_bus *devm_mdiobus_alloc_size(struct device *dev, int sizeof_priv)
if (bus) { if (bus) {
*ptr = bus; *ptr = bus;
devres_add(dev, ptr); devres_add(dev, ptr);
bus->is_managed = 1;
} else { } else {
devres_free(ptr); devres_free(ptr);
} }
......
...@@ -241,6 +241,9 @@ struct mii_bus { ...@@ -241,6 +241,9 @@ struct mii_bus {
int (*reset)(struct mii_bus *bus); int (*reset)(struct mii_bus *bus);
struct mdio_bus_stats stats[PHY_MAX_ADDR]; 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 * A lock to ensure that only one thing can read/write
* the MDIO bus at a time * the MDIO bus at a time
...@@ -286,6 +289,20 @@ static inline struct mii_bus *mdiobus_alloc(void) ...@@ -286,6 +289,20 @@ static inline struct mii_bus *mdiobus_alloc(void)
int __mdiobus_register(struct mii_bus *bus, struct module *owner); int __mdiobus_register(struct mii_bus *bus, struct module *owner);
#define mdiobus_register(bus) __mdiobus_register(bus, THIS_MODULE) #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_unregister(struct mii_bus *bus);
void mdiobus_free(struct mii_bus *bus); void mdiobus_free(struct mii_bus *bus);
struct mii_bus *devm_mdiobus_alloc_size(struct device *dev, int sizeof_priv); struct mii_bus *devm_mdiobus_alloc_size(struct device *dev, int sizeof_priv);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment