net: pcs: xpcs: add xpcs_create_mdiodev()

Add xpcs_create_mdiodev() to simplify the creation of the mdio device
associated with the XPCS. In order to allow xpcs_destroy() to clean
this up, we need to arrange for xpcs_create() to take a refcount on
the mdiodev, and xpcs_destroy() to put it.

Adding the refcounting to xpcs_create()..xpcs_destroy() will be
transparent to existing users of these interfaces.

Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Russell King (Oracle) 2023-05-26 11:14:29 +01:00 committed by Jakub Kicinski
parent c4933fa88a
commit 9a5d500cff
2 changed files with 30 additions and 0 deletions

View file

@ -1235,6 +1235,7 @@ struct dw_xpcs *xpcs_create(struct mdio_device *mdiodev,
if (!xpcs)
return ERR_PTR(-ENOMEM);
mdio_device_get(mdiodev);
xpcs->mdiodev = mdiodev;
xpcs_id = xpcs_get_id(xpcs);
@ -1267,6 +1268,7 @@ struct dw_xpcs *xpcs_create(struct mdio_device *mdiodev,
ret = -ENODEV;
out:
mdio_device_put(mdiodev);
kfree(xpcs);
return ERR_PTR(ret);
@ -1275,8 +1277,34 @@ EXPORT_SYMBOL_GPL(xpcs_create);
void xpcs_destroy(struct dw_xpcs *xpcs)
{
if (xpcs)
mdio_device_put(xpcs->mdiodev);
kfree(xpcs);
}
EXPORT_SYMBOL_GPL(xpcs_destroy);
struct dw_xpcs *xpcs_create_mdiodev(struct mii_bus *bus, int addr,
phy_interface_t interface)
{
struct mdio_device *mdiodev;
struct dw_xpcs *xpcs;
mdiodev = mdio_device_create(bus, addr);
if (IS_ERR(mdiodev))
return ERR_CAST(mdiodev);
xpcs = xpcs_create(mdiodev, interface);
/* xpcs_create() has taken a refcount on the mdiodev if it was
* successful. If xpcs_create() fails, this will free the mdio
* device here. In any case, we don't need to hold our reference
* anymore, and putting it here will allow mdio_device_put() in
* xpcs_destroy() to automatically free the mdio device.
*/
mdio_device_put(mdiodev);
return xpcs;
}
EXPORT_SYMBOL_GPL(xpcs_create_mdiodev);
MODULE_LICENSE("GPL v2");

View file

@ -37,6 +37,8 @@ int xpcs_config_eee(struct dw_xpcs *xpcs, int mult_fact_100ns,
int enable);
struct dw_xpcs *xpcs_create(struct mdio_device *mdiodev,
phy_interface_t interface);
struct dw_xpcs *xpcs_create_mdiodev(struct mii_bus *bus, int addr,
phy_interface_t interface);
void xpcs_destroy(struct dw_xpcs *xpcs);
#endif /* __LINUX_PCS_XPCS_H */