net: mdiobus: search for PSE nodes by parsing PHY nodes.
authorOleksij Rempel <o.rempel@pengutronix.de>
Mon, 3 Oct 2022 06:51:59 +0000 (08:51 +0200)
committerJakub Kicinski <kuba@kernel.org>
Tue, 4 Oct 2022 00:33:57 +0000 (17:33 -0700)
Some PHYs can be linked with PSE (Power Sourcing Equipment), so search
for related nodes and attach it to the phydev.

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/mdio/fwnode_mdio.c
drivers/net/phy/phy_device.c
include/linux/phy.h

index 7ff7349a27a2fa17af3149edecf333069dc1284d..689e728345ce38b317d2071afcc003c041c5a098 100644 (file)
 #include <linux/fwnode_mdio.h>
 #include <linux/of.h>
 #include <linux/phy.h>
+#include <linux/pse-pd/pse.h>
 
 MODULE_AUTHOR("Calvin Johnson <calvin.johnson@oss.nxp.com>");
 MODULE_LICENSE("GPL");
 
+static struct pse_control *
+fwnode_find_pse_control(struct fwnode_handle *fwnode)
+{
+       struct pse_control *psec;
+       struct device_node *np;
+
+       if (!IS_ENABLED(CONFIG_PSE_CONTROLLER))
+               return NULL;
+
+       np = to_of_node(fwnode);
+       if (!np)
+               return NULL;
+
+       psec = of_pse_control_get(np);
+       if (PTR_ERR(psec) == -ENOENT)
+               return NULL;
+
+       return psec;
+}
+
 static struct mii_timestamper *
 fwnode_find_mii_timestamper(struct fwnode_handle *fwnode)
 {
@@ -91,14 +112,21 @@ int fwnode_mdiobus_register_phy(struct mii_bus *bus,
                                struct fwnode_handle *child, u32 addr)
 {
        struct mii_timestamper *mii_ts = NULL;
+       struct pse_control *psec = NULL;
        struct phy_device *phy;
        bool is_c45 = false;
        u32 phy_id;
        int rc;
 
+       psec = fwnode_find_pse_control(child);
+       if (IS_ERR(psec))
+               return PTR_ERR(psec);
+
        mii_ts = fwnode_find_mii_timestamper(child);
-       if (IS_ERR(mii_ts))
-               return PTR_ERR(mii_ts);
+       if (IS_ERR(mii_ts)) {
+               rc = PTR_ERR(mii_ts);
+               goto clean_pse;
+       }
 
        rc = fwnode_property_match_string(child, "compatible",
                                          "ethernet-phy-ieee802.3-c45");
@@ -134,18 +162,23 @@ int fwnode_mdiobus_register_phy(struct mii_bus *bus,
                        goto clean_phy;
        }
 
+       phy->psec = psec;
+
        /* phy->mii_ts may already be defined by the PHY driver. A
         * mii_timestamper probed via the device tree will still have
         * precedence.
         */
        if (mii_ts)
                phy->mii_ts = mii_ts;
+
        return 0;
 
 clean_phy:
        phy_device_free(phy);
 clean_mii_ts:
        unregister_mii_timestamper(mii_ts);
+clean_pse:
+       pse_control_put(psec);
 
        return rc;
 }
index a4f5f151014aeaf1a96eb428fad8c948e8414d0a..57849ac0384eff810c034855f1dbba5c0554a88e 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/netdevice.h>
 #include <linux/phy.h>
 #include <linux/phy_led_triggers.h>
+#include <linux/pse-pd/pse.h>
 #include <linux/property.h>
 #include <linux/sfp.h>
 #include <linux/skbuff.h>
@@ -991,6 +992,7 @@ EXPORT_SYMBOL(phy_device_register);
 void phy_device_remove(struct phy_device *phydev)
 {
        unregister_mii_timestamper(phydev->mii_ts);
+       pse_control_put(phydev->psec);
 
        device_del(&phydev->mdio.dev);
 
index d65fc76fe0aeeb497b50de64e3719f0f32b05f72..ddf66198f75110ed8420c9f9ad21527842d29aaf 100644 (file)
@@ -597,6 +597,7 @@ struct macsec_ops;
  * @master_slave_get: Current master/slave advertisement
  * @master_slave_state: Current master/slave configuration
  * @mii_ts: Pointer to time stamper callbacks
+ * @psec: Pointer to Power Sourcing Equipment control struct
  * @lock:  Mutex for serialization access to PHY
  * @state_queue: Work queue for state machine
  * @shared: Pointer to private data shared by phys in one package
@@ -715,6 +716,7 @@ struct phy_device {
        struct phylink *phylink;
        struct net_device *attached_dev;
        struct mii_timestamper *mii_ts;
+       struct pse_control *psec;
 
        u8 mdix;
        u8 mdix_ctrl;