net: pcs: lynx: add lynx_pcs_create_mdiodev()
authorRussell King (Oracle) <rmk+kernel@armlinux.org.uk>
Fri, 26 May 2023 10:14:39 +0000 (11:14 +0100)
committerJakub Kicinski <kuba@kernel.org>
Tue, 30 May 2023 04:46:53 +0000 (21:46 -0700)
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) <rmk+kernel@armlinux.org.uk>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Ioana Ciornei <ioana.ciornei@nxp.com>
Tested-by: Ioana Ciornei <ioana.ciornei@nxp.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/pcs/pcs-lynx.c
include/linux/pcs-lynx.h

index 622c3de3f3a8b4b252d8a76d79362509e14f2c3f..f04dc580ffb83df77ad006dcdd85e7dd73310eb1 100644 (file)
@@ -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);
index 5712cc2ce775516a6a1afa2f433ab5abdbc70818..885b59d1058132b2b3a684677fb96334df3595cc 100644 (file)
@@ -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);