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

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
Loading
Loading
Loading
Loading
+2 −8
Original line number Diff line number Diff line
@@ -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 = {
+7 −1
Original line number Diff line number Diff line
@@ -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);
	}
+17 −0
Original line number Diff line number Diff line
@@ -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);