diff options
author | Grygorii Strashko <grygorii.strashko@ti.com> | 2014-04-30 08:23:33 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-05-02 16:16:26 -0400 |
commit | 6d48f44b7b2af67b33c1ae5994b8f642685c8bc8 (patch) | |
tree | 3c39a984abea3ca8016660b111783874d982f5b4 | |
parent | ca8b6e04bc38891cbc0f2c7855bc7d0498dfff9b (diff) |
mdio_bus: implement devm_mdiobus_alloc/devm_mdiobus_free
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>
-rw-r--r-- | Documentation/driver-model/devres.txt | 5 | ||||
-rw-r--r-- | drivers/net/phy/mdio_bus.c | 67 | ||||
-rw-r--r-- | include/linux/phy.h | 7 |
3 files changed, 79 insertions, 0 deletions
diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt index 4f7897e99cba..c74e04494ade 100644 --- a/Documentation/driver-model/devres.txt +++ b/Documentation/driver-model/devres.txt | |||
@@ -308,3 +308,8 @@ SLAVE DMA ENGINE | |||
308 | 308 | ||
309 | SPI | 309 | SPI |
310 | devm_spi_register_master() | 310 | devm_spi_register_master() |
311 | |||
312 | MDIO | ||
313 | devm_mdiobus_alloc() | ||
314 | devm_mdiobus_alloc_size() | ||
315 | devm_mdiobus_free() | ||
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 76f54b32a120..68a9a3867c0f 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c | |||
@@ -69,6 +69,73 @@ struct mii_bus *mdiobus_alloc_size(size_t size) | |||
69 | } | 69 | } |
70 | EXPORT_SYMBOL(mdiobus_alloc_size); | 70 | EXPORT_SYMBOL(mdiobus_alloc_size); |
71 | 71 | ||
72 | static void _devm_mdiobus_free(struct device *dev, void *res) | ||
73 | { | ||
74 | mdiobus_free(*(struct mii_bus **)res); | ||
75 | } | ||
76 | |||
77 | static int devm_mdiobus_match(struct device *dev, void *res, void *data) | ||
78 | { | ||
79 | struct mii_bus **r = res; | ||
80 | |||
81 | if (WARN_ON(!r || !*r)) | ||
82 | return 0; | ||
83 | |||
84 | return *r == data; | ||
85 | } | ||
86 | |||
87 | /** | ||
88 | * devm_mdiobus_alloc_size - Resource-managed mdiobus_alloc_size() | ||
89 | * @dev: Device to allocate mii_bus for | ||
90 | * @sizeof_priv: Space to allocate for private structure. | ||
91 | * | ||
92 | * Managed mdiobus_alloc_size. mii_bus allocated with this function is | ||
93 | * automatically freed on driver detach. | ||
94 | * | ||
95 | * If an mii_bus allocated with this function needs to be freed separately, | ||
96 | * devm_mdiobus_free() must be used. | ||
97 | * | ||
98 | * RETURNS: | ||
99 | * Pointer to allocated mii_bus on success, NULL on failure. | ||
100 | */ | ||
101 | struct mii_bus *devm_mdiobus_alloc_size(struct device *dev, int sizeof_priv) | ||
102 | { | ||
103 | struct mii_bus **ptr, *bus; | ||
104 | |||
105 | ptr = devres_alloc(_devm_mdiobus_free, sizeof(*ptr), GFP_KERNEL); | ||
106 | if (!ptr) | ||
107 | return NULL; | ||
108 | |||
109 | /* use raw alloc_dr for kmalloc caller tracing */ | ||
110 | bus = mdiobus_alloc_size(sizeof_priv); | ||
111 | if (bus) { | ||
112 | *ptr = bus; | ||
113 | devres_add(dev, ptr); | ||
114 | } else { | ||
115 | devres_free(ptr); | ||
116 | } | ||
117 | |||
118 | return bus; | ||
119 | } | ||
120 | EXPORT_SYMBOL_GPL(devm_mdiobus_alloc); | ||
121 | |||
122 | /** | ||
123 | * devm_mdiobus_free - Resource-managed mdiobus_free() | ||
124 | * @dev: Device this mii_bus belongs to | ||
125 | * @bus: the mii_bus associated with the device | ||
126 | * | ||
127 | * Free mii_bus allocated with devm_mdiobus_alloc_size(). | ||
128 | */ | ||
129 | void devm_mdiobus_free(struct device *dev, struct mii_bus *bus) | ||
130 | { | ||
131 | int rc; | ||
132 | |||
133 | rc = devres_release(dev, _devm_mdiobus_free, | ||
134 | devm_mdiobus_match, bus); | ||
135 | WARN_ON(rc); | ||
136 | } | ||
137 | EXPORT_SYMBOL_GPL(devm_mdiobus_free); | ||
138 | |||
72 | /** | 139 | /** |
73 | * mdiobus_release - mii_bus device release callback | 140 | * mdiobus_release - mii_bus device release callback |
74 | * @d: the target struct device that contains the mii_bus | 141 | * @d: the target struct device that contains the mii_bus |
diff --git a/include/linux/phy.h b/include/linux/phy.h index 51d15f684e7e..864ddafad8cc 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h | |||
@@ -198,6 +198,13 @@ static inline struct mii_bus *mdiobus_alloc(void) | |||
198 | int mdiobus_register(struct mii_bus *bus); | 198 | int mdiobus_register(struct mii_bus *bus); |
199 | void mdiobus_unregister(struct mii_bus *bus); | 199 | void mdiobus_unregister(struct mii_bus *bus); |
200 | void mdiobus_free(struct mii_bus *bus); | 200 | void mdiobus_free(struct mii_bus *bus); |
201 | struct mii_bus *devm_mdiobus_alloc_size(struct device *dev, int sizeof_priv); | ||
202 | static inline struct mii_bus *devm_mdiobus_alloc(struct device *dev) | ||
203 | { | ||
204 | return devm_mdiobus_alloc_size(dev, 0); | ||
205 | } | ||
206 | |||
207 | void devm_mdiobus_free(struct device *dev, struct mii_bus *bus); | ||
201 | struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr); | 208 | struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr); |
202 | int mdiobus_read(struct mii_bus *bus, int addr, u32 regnum); | 209 | int mdiobus_read(struct mii_bus *bus, int addr, u32 regnum); |
203 | int mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val); | 210 | int mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val); |