forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 431
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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]>
- Loading branch information
Showing
5 changed files
with
82 additions
and
87 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,25 +1,96 @@ | ||
// SPDX-License-Identifier: GPL-2.0-or-later | ||
|
||
#include <linux/device.h> | ||
#include <linux/phy.h> | ||
#include <linux/stddef.h> | ||
|
||
struct mdiobus_devres { | ||
struct mii_bus *mii; | ||
}; | ||
|
||
static void devm_mdiobus_free(struct device *dev, void *this) | ||
{ | ||
struct mdiobus_devres *dr = this; | ||
|
||
mdiobus_free(dr->mii); | ||
} | ||
|
||
/** | ||
* 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. | ||
* | ||
* RETURNS: | ||
* Pointer to allocated mii_bus on success, NULL on out-of-memory error. | ||
*/ | ||
struct mii_bus *devm_mdiobus_alloc_size(struct device *dev, int sizeof_priv) | ||
{ | ||
struct mdiobus_devres *dr; | ||
|
||
dr = devres_alloc(devm_mdiobus_free, sizeof(*dr), GFP_KERNEL); | ||
if (!dr) | ||
return NULL; | ||
|
||
dr->mii = mdiobus_alloc_size(sizeof_priv); | ||
if (!dr->mii) { | ||
devres_free(dr); | ||
return NULL; | ||
} | ||
|
||
devres_add(dev, dr); | ||
return dr->mii; | ||
} | ||
EXPORT_SYMBOL(devm_mdiobus_alloc_size); | ||
|
||
static void devm_mdiobus_unregister(struct device *dev, void *this) | ||
{ | ||
struct mdiobus_devres *dr = this; | ||
|
||
mdiobus_unregister(dr->mii); | ||
} | ||
|
||
static int mdiobus_devres_match(struct device *dev, | ||
void *this, void *match_data) | ||
{ | ||
struct mdiobus_devres *res = this; | ||
struct mii_bus *mii = match_data; | ||
|
||
return mii == res->mii; | ||
} | ||
|
||
/** | ||
* __devm_mdiobus_register - Resource-managed variant of mdiobus_register() | ||
* @dev: Device to register mii_bus for | ||
* @bus: MII bus structure to register | ||
* @owner: Owning module | ||
* | ||
* Returns 0 on success, negative error number on failure. | ||
*/ | ||
int __devm_mdiobus_register(struct mii_bus *bus, struct module *owner) | ||
int __devm_mdiobus_register(struct device *dev, struct mii_bus *bus, | ||
struct module *owner) | ||
{ | ||
struct mdiobus_devres *dr; | ||
int ret; | ||
|
||
if (!bus->is_managed) | ||
return -EPERM; | ||
if (WARN_ON(!devres_find(dev, devm_mdiobus_free, | ||
mdiobus_devres_match, bus))) | ||
return -EINVAL; | ||
|
||
dr = devres_alloc(devm_mdiobus_unregister, sizeof(*dr), GFP_KERNEL); | ||
if (!dr) | ||
return -ENOMEM; | ||
|
||
ret = __mdiobus_register(bus, owner); | ||
if (!ret) | ||
bus->is_managed_registered = 1; | ||
if (ret) { | ||
devres_free(dr); | ||
return ret; | ||
} | ||
|
||
return ret; | ||
dr->mii = bus; | ||
devres_add(dev, dr); | ||
return 0; | ||
} | ||
EXPORT_SYMBOL(__devm_mdiobus_register); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters