Skip to content

Commit ac3a68d

Browse files
brgldavem330
authored andcommitted
net: phy: don't abuse devres in devm_mdiobus_register()
We currently have two managed helpers for mdiobus - devm_mdiobus_alloc() and devm_mdiobus_register(). The idea behind devres is that the release callback releases whatever resource the devm function allocates. In the mdiobus case however there's no devres associated with the device by devm_mdiobus_register(). Instead the release callback for devm_mdiobus_alloc(): _devm_mdiobus_free() unregisters the device if it is marked as managed. This all seems wrong. The managed structure shouldn't need to know or care about whether it's managed or not - and this is the case now for struct mii_bus. The devres wrapper should be opaque to the managed resource. This changeset makes devm_mdiobus_alloc() and devm_mdiobus_register() conform to common devres standards: devm_mdiobus_alloc() allocates a devres structure and registers a callback that will call mdiobus_free(). __devm_mdiobus_register() allocated another devres and registers a callback that will unregister the bus. Signed-off-by: Bartosz Golaszewski <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 6a9a572 commit ac3a68d

File tree

5 files changed

+82
-87
lines changed

5 files changed

+82
-87
lines changed

Documentation/driver-api/driver-model/devres.rst

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,6 @@ LED
342342
MDIO
343343
devm_mdiobus_alloc()
344344
devm_mdiobus_alloc_size()
345-
devm_mdiobus_free()
346345
devm_mdiobus_register()
347346

348347
MEM

drivers/net/ethernet/realtek/r8169_main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5012,7 +5012,7 @@ static int r8169_mdio_register(struct rtl8169_private *tp)
50125012
new_bus->read = r8169_mdio_read_reg;
50135013
new_bus->write = r8169_mdio_write_reg;
50145014

5015-
ret = devm_mdiobus_register(new_bus);
5015+
ret = devm_mdiobus_register(&pdev->dev, new_bus);
50165016
if (ret)
50175017
return ret;
50185018

drivers/net/phy/mdio_bus.c

Lines changed: 0 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -165,79 +165,6 @@ struct mii_bus *mdiobus_alloc_size(size_t size)
165165
}
166166
EXPORT_SYMBOL(mdiobus_alloc_size);
167167

168-
static void _devm_mdiobus_free(struct device *dev, void *res)
169-
{
170-
struct mii_bus *bus = *(struct mii_bus **)res;
171-
172-
if (bus->is_managed_registered && bus->state == MDIOBUS_REGISTERED)
173-
mdiobus_unregister(bus);
174-
175-
mdiobus_free(bus);
176-
}
177-
178-
static int devm_mdiobus_match(struct device *dev, void *res, void *data)
179-
{
180-
struct mii_bus **r = res;
181-
182-
if (WARN_ON(!r || !*r))
183-
return 0;
184-
185-
return *r == data;
186-
}
187-
188-
/**
189-
* devm_mdiobus_alloc_size - Resource-managed mdiobus_alloc_size()
190-
* @dev: Device to allocate mii_bus for
191-
* @sizeof_priv: Space to allocate for private structure.
192-
*
193-
* Managed mdiobus_alloc_size. mii_bus allocated with this function is
194-
* automatically freed on driver detach.
195-
*
196-
* If an mii_bus allocated with this function needs to be freed separately,
197-
* devm_mdiobus_free() must be used.
198-
*
199-
* RETURNS:
200-
* Pointer to allocated mii_bus on success, NULL on failure.
201-
*/
202-
struct mii_bus *devm_mdiobus_alloc_size(struct device *dev, int sizeof_priv)
203-
{
204-
struct mii_bus **ptr, *bus;
205-
206-
ptr = devres_alloc(_devm_mdiobus_free, sizeof(*ptr), GFP_KERNEL);
207-
if (!ptr)
208-
return NULL;
209-
210-
/* use raw alloc_dr for kmalloc caller tracing */
211-
bus = mdiobus_alloc_size(sizeof_priv);
212-
if (bus) {
213-
*ptr = bus;
214-
devres_add(dev, ptr);
215-
bus->is_managed = 1;
216-
} else {
217-
devres_free(ptr);
218-
}
219-
220-
return bus;
221-
}
222-
EXPORT_SYMBOL_GPL(devm_mdiobus_alloc_size);
223-
224-
/**
225-
* devm_mdiobus_free - Resource-managed mdiobus_free()
226-
* @dev: Device this mii_bus belongs to
227-
* @bus: the mii_bus associated with the device
228-
*
229-
* Free mii_bus allocated with devm_mdiobus_alloc_size().
230-
*/
231-
void devm_mdiobus_free(struct device *dev, struct mii_bus *bus)
232-
{
233-
int rc;
234-
235-
rc = devres_release(dev, _devm_mdiobus_free,
236-
devm_mdiobus_match, bus);
237-
WARN_ON(rc);
238-
}
239-
EXPORT_SYMBOL_GPL(devm_mdiobus_free);
240-
241168
/**
242169
* mdiobus_release - mii_bus device release callback
243170
* @d: the target struct device that contains the mii_bus

drivers/net/phy/mdio_devres.c

Lines changed: 77 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,96 @@
11
// SPDX-License-Identifier: GPL-2.0-or-later
22

3+
#include <linux/device.h>
34
#include <linux/phy.h>
5+
#include <linux/stddef.h>
6+
7+
struct mdiobus_devres {
8+
struct mii_bus *mii;
9+
};
10+
11+
static void devm_mdiobus_free(struct device *dev, void *this)
12+
{
13+
struct mdiobus_devres *dr = this;
14+
15+
mdiobus_free(dr->mii);
16+
}
17+
18+
/**
19+
* devm_mdiobus_alloc_size - Resource-managed mdiobus_alloc_size()
20+
* @dev: Device to allocate mii_bus for
21+
* @sizeof_priv: Space to allocate for private structure
22+
*
23+
* Managed mdiobus_alloc_size. mii_bus allocated with this function is
24+
* automatically freed on driver detach.
25+
*
26+
* RETURNS:
27+
* Pointer to allocated mii_bus on success, NULL on out-of-memory error.
28+
*/
29+
struct mii_bus *devm_mdiobus_alloc_size(struct device *dev, int sizeof_priv)
30+
{
31+
struct mdiobus_devres *dr;
32+
33+
dr = devres_alloc(devm_mdiobus_free, sizeof(*dr), GFP_KERNEL);
34+
if (!dr)
35+
return NULL;
36+
37+
dr->mii = mdiobus_alloc_size(sizeof_priv);
38+
if (!dr->mii) {
39+
devres_free(dr);
40+
return NULL;
41+
}
42+
43+
devres_add(dev, dr);
44+
return dr->mii;
45+
}
46+
EXPORT_SYMBOL(devm_mdiobus_alloc_size);
47+
48+
static void devm_mdiobus_unregister(struct device *dev, void *this)
49+
{
50+
struct mdiobus_devres *dr = this;
51+
52+
mdiobus_unregister(dr->mii);
53+
}
54+
55+
static int mdiobus_devres_match(struct device *dev,
56+
void *this, void *match_data)
57+
{
58+
struct mdiobus_devres *res = this;
59+
struct mii_bus *mii = match_data;
60+
61+
return mii == res->mii;
62+
}
463

564
/**
665
* __devm_mdiobus_register - Resource-managed variant of mdiobus_register()
66+
* @dev: Device to register mii_bus for
767
* @bus: MII bus structure to register
868
* @owner: Owning module
969
*
1070
* Returns 0 on success, negative error number on failure.
1171
*/
12-
int __devm_mdiobus_register(struct mii_bus *bus, struct module *owner)
72+
int __devm_mdiobus_register(struct device *dev, struct mii_bus *bus,
73+
struct module *owner)
1374
{
75+
struct mdiobus_devres *dr;
1476
int ret;
1577

16-
if (!bus->is_managed)
17-
return -EPERM;
78+
if (WARN_ON(!devres_find(dev, devm_mdiobus_free,
79+
mdiobus_devres_match, bus)))
80+
return -EINVAL;
81+
82+
dr = devres_alloc(devm_mdiobus_unregister, sizeof(*dr), GFP_KERNEL);
83+
if (!dr)
84+
return -ENOMEM;
1885

1986
ret = __mdiobus_register(bus, owner);
20-
if (!ret)
21-
bus->is_managed_registered = 1;
87+
if (ret) {
88+
devres_free(dr);
89+
return ret;
90+
}
2291

23-
return ret;
92+
dr->mii = bus;
93+
devres_add(dev, dr);
94+
return 0;
2495
}
2596
EXPORT_SYMBOL(__devm_mdiobus_register);

include/linux/phy.h

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -261,9 +261,6 @@ struct mii_bus {
261261
int (*reset)(struct mii_bus *bus);
262262
struct mdio_bus_stats stats[PHY_MAX_ADDR];
263263

264-
unsigned int is_managed:1; /* is device-managed */
265-
unsigned int is_managed_registered:1;
266-
267264
/*
268265
* A lock to ensure that only one thing can read/write
269266
* the MDIO bus at a time
@@ -322,9 +319,11 @@ static inline struct mii_bus *mdiobus_alloc(void)
322319
}
323320

324321
int __mdiobus_register(struct mii_bus *bus, struct module *owner);
325-
int __devm_mdiobus_register(struct mii_bus *bus, struct module *owner);
322+
int __devm_mdiobus_register(struct device *dev, struct mii_bus *bus,
323+
struct module *owner);
326324
#define mdiobus_register(bus) __mdiobus_register(bus, THIS_MODULE)
327-
#define devm_mdiobus_register(bus) __devm_mdiobus_register(bus, THIS_MODULE)
325+
#define devm_mdiobus_register(dev, bus) \
326+
__devm_mdiobus_register(dev, bus, THIS_MODULE)
328327

329328
void mdiobus_unregister(struct mii_bus *bus);
330329
void mdiobus_free(struct mii_bus *bus);
@@ -335,7 +334,6 @@ static inline struct mii_bus *devm_mdiobus_alloc(struct device *dev)
335334
}
336335

337336
struct mii_bus *mdio_find_bus(const char *mdio_name);
338-
void devm_mdiobus_free(struct device *dev, struct mii_bus *bus);
339337
struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr);
340338

341339
#define PHY_INTERRUPT_DISABLED false

0 commit comments

Comments
 (0)