From c4933fa88a68c69205753601044949d516c4db10 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Fri, 26 May 2023 11:14:24 +0100 Subject: net: mdio: add mdio_device_get() and mdio_device_put() Add two new operations for a mdio device to manage the refcount on the underlying struct device. This will be used by mdio PCS drivers to simplify the creation and destruction handling, making it easier for users to get it correct. Signed-off-by: Russell King (Oracle) Reviewed-by: Andrew Lunn Signed-off-by: Jakub Kicinski --- include/linux/mdio.h | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'include/linux') diff --git a/include/linux/mdio.h b/include/linux/mdio.h index 0670cc6e067c..c1b7008826e5 100644 --- a/include/linux/mdio.h +++ b/include/linux/mdio.h @@ -106,6 +106,16 @@ int mdio_driver_register(struct mdio_driver *drv); void mdio_driver_unregister(struct mdio_driver *drv); int mdio_device_bus_match(struct device *dev, struct device_driver *drv); +static inline void mdio_device_get(struct mdio_device *mdiodev) +{ + get_device(&mdiodev->dev); +} + +static inline void mdio_device_put(struct mdio_device *mdiodev) +{ + mdio_device_free(mdiodev); +} + static inline bool mdio_phy_id_is_c45(int phy_id) { return (phy_id & MDIO_PHY_ID_C45) && !(phy_id & ~MDIO_PHY_ID_C45_MASK); -- cgit v1.2.3 From 9a5d500cffdb3652215172b7c5829ca7b41e9efe Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Fri, 26 May 2023 11:14:29 +0100 Subject: 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) Reviewed-by: Andrew Lunn Signed-off-by: Jakub Kicinski --- drivers/net/pcs/pcs-xpcs.c | 28 ++++++++++++++++++++++++++++ include/linux/pcs/pcs-xpcs.h | 2 ++ 2 files changed, 30 insertions(+) (limited to 'include/linux') diff --git a/drivers/net/pcs/pcs-xpcs.c b/drivers/net/pcs/pcs-xpcs.c index 736776e40c25..1ba214429e01 100644 --- a/drivers/net/pcs/pcs-xpcs.c +++ b/drivers/net/pcs/pcs-xpcs.c @@ -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"); diff --git a/include/linux/pcs/pcs-xpcs.h b/include/linux/pcs/pcs-xpcs.h index d2da1e0b4a92..a99972a6d046 100644 --- a/include/linux/pcs/pcs-xpcs.h +++ b/include/linux/pcs/pcs-xpcs.h @@ -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 */ -- cgit v1.2.3 From 86b5f2d8cd7828c881036d30ce3a4e711a071726 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Fri, 26 May 2023 11:14:39 +0100 Subject: net: pcs: lynx: add lynx_pcs_create_mdiodev() Add lynx_pcs_create_mdiodev() to simplify the creation of the mdio device associated with lynx PCS. In order to allow lynx_pcs_destroy() to clean this up, we need to arrange for lynx_pcs_create() to take a refcount on the mdiodev, and lynx_pcs_destroy() to put it. Adding the refcounting to lynx_pcs_create()..lynx_pcs_destroy() will be transparent to existing users of these interfaces. Signed-off-by: Russell King (Oracle) Reviewed-by: Andrew Lunn Reviewed-by: Ioana Ciornei Tested-by: Ioana Ciornei Signed-off-by: Jakub Kicinski --- drivers/net/pcs/pcs-lynx.c | 31 +++++++++++++++++++++++++++++++ include/linux/pcs-lynx.h | 1 + 2 files changed, 32 insertions(+) (limited to 'include/linux') diff --git a/drivers/net/pcs/pcs-lynx.c b/drivers/net/pcs/pcs-lynx.c index 622c3de3f3a8..f04dc580ffb8 100644 --- a/drivers/net/pcs/pcs-lynx.c +++ b/drivers/net/pcs/pcs-lynx.c @@ -323,6 +323,7 @@ struct phylink_pcs *lynx_pcs_create(struct mdio_device *mdio) if (!lynx) return NULL; + mdio_device_get(mdio); lynx->mdio = mdio; lynx->pcs.ops = &lynx_pcs_phylink_ops; lynx->pcs.poll = true; @@ -331,10 +332,40 @@ struct phylink_pcs *lynx_pcs_create(struct mdio_device *mdio) } EXPORT_SYMBOL(lynx_pcs_create); +struct phylink_pcs *lynx_pcs_create_mdiodev(struct mii_bus *bus, int addr) +{ + struct mdio_device *mdio; + struct phylink_pcs *pcs; + + mdio = mdio_device_create(bus, addr); + if (IS_ERR(mdio)) + return ERR_CAST(mdio); + + pcs = lynx_pcs_create(mdio); + + /* Convert failure to create the PCS to an error pointer, so this + * function has a consistent return value strategy. + */ + if (!pcs) + pcs = ERR_PTR(-ENOMEM); + + /* lynx_create() has taken a refcount on the mdiodev if it was + * successful. If lynx_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 + * lynx_destroy() to automatically free the mdio device. + */ + mdio_device_put(mdio); + + return pcs; +} +EXPORT_SYMBOL(lynx_pcs_create_mdiodev); + void lynx_pcs_destroy(struct phylink_pcs *pcs) { struct lynx_pcs *lynx = phylink_pcs_to_lynx(pcs); + mdio_device_put(lynx->mdio); kfree(lynx); } EXPORT_SYMBOL(lynx_pcs_destroy); diff --git a/include/linux/pcs-lynx.h b/include/linux/pcs-lynx.h index 5712cc2ce775..885b59d10581 100644 --- a/include/linux/pcs-lynx.h +++ b/include/linux/pcs-lynx.h @@ -12,6 +12,7 @@ struct mdio_device *lynx_get_mdio_device(struct phylink_pcs *pcs); struct phylink_pcs *lynx_pcs_create(struct mdio_device *mdio); +struct phylink_pcs *lynx_pcs_create_mdiodev(struct mii_bus *bus, int addr); void lynx_pcs_destroy(struct phylink_pcs *pcs); -- cgit v1.2.3