Skip to content

Commit

Permalink
mdio_bus: implement devm_mdiobus_alloc/devm_mdiobus_free
Browse files Browse the repository at this point in the history
Add a resource managed devm_mdiobus_alloc[_size]()/devm_mdiobus_free()
to automatically clean up MDIO bus alocations made by MDIO drivers,
thus leading to simplified MDIO drivers code.

Cc: Florian Fainelli <f.fainelli@gmail.com>
Cc: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
Acked-and-tested-by: Lad, Prabhakar <prabhakar.csengg@gmail.com>
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Grygorii Strashko authored and David S. Miller committed May 2, 2014
1 parent ca8b6e0 commit 6d48f44
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 0 deletions.
5 changes: 5 additions & 0 deletions Documentation/driver-model/devres.txt
Original file line number Diff line number Diff line change
Expand Up @@ -308,3 +308,8 @@ SLAVE DMA ENGINE

SPI
devm_spi_register_master()

MDIO
devm_mdiobus_alloc()
devm_mdiobus_alloc_size()
devm_mdiobus_free()
67 changes: 67 additions & 0 deletions drivers/net/phy/mdio_bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,73 @@ struct mii_bus *mdiobus_alloc_size(size_t size)
}
EXPORT_SYMBOL(mdiobus_alloc_size);

static void _devm_mdiobus_free(struct device *dev, void *res)
{
mdiobus_free(*(struct mii_bus **)res);
}

static int devm_mdiobus_match(struct device *dev, void *res, void *data)
{
struct mii_bus **r = res;

if (WARN_ON(!r || !*r))
return 0;

return *r == data;
}

/**
* devm_mdiobus_alloc_size - Resource-managed mdiobus_alloc_size()
* @dev: Device to allocate mii_bus for
* @sizeof_priv: Space to allocate for private structure.
*
* Managed mdiobus_alloc_size. mii_bus allocated with this function is
* automatically freed on driver detach.
*
* If an mii_bus allocated with this function needs to be freed separately,
* devm_mdiobus_free() must be used.
*
* RETURNS:
* Pointer to allocated mii_bus on success, NULL on failure.
*/
struct mii_bus *devm_mdiobus_alloc_size(struct device *dev, int sizeof_priv)
{
struct mii_bus **ptr, *bus;

ptr = devres_alloc(_devm_mdiobus_free, sizeof(*ptr), GFP_KERNEL);
if (!ptr)
return NULL;

/* use raw alloc_dr for kmalloc caller tracing */
bus = mdiobus_alloc_size(sizeof_priv);
if (bus) {
*ptr = bus;
devres_add(dev, ptr);
} else {
devres_free(ptr);
}

return bus;
}
EXPORT_SYMBOL_GPL(devm_mdiobus_alloc);

/**
* devm_mdiobus_free - Resource-managed mdiobus_free()
* @dev: Device this mii_bus belongs to
* @bus: the mii_bus associated with the device
*
* Free mii_bus allocated with devm_mdiobus_alloc_size().
*/
void devm_mdiobus_free(struct device *dev, struct mii_bus *bus)
{
int rc;

rc = devres_release(dev, _devm_mdiobus_free,
devm_mdiobus_match, bus);
WARN_ON(rc);
}
EXPORT_SYMBOL_GPL(devm_mdiobus_free);

/**
* mdiobus_release - mii_bus device release callback
* @d: the target struct device that contains the mii_bus
Expand Down
7 changes: 7 additions & 0 deletions include/linux/phy.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,13 @@ static inline struct mii_bus *mdiobus_alloc(void)
int mdiobus_register(struct mii_bus *bus);
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);
static inline struct mii_bus *devm_mdiobus_alloc(struct device *dev)
{
return devm_mdiobus_alloc_size(dev, 0);
}

void devm_mdiobus_free(struct device *dev, struct mii_bus *bus);
struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr);
int mdiobus_read(struct mii_bus *bus, int addr, u32 regnum);
int mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val);
Expand Down

0 comments on commit 6d48f44

Please sign in to comment.