]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
net: pse-pd: Introduce attached_phydev to pse control
authorKory Maincent (Dent Project) <kory.maincent@bootlin.com>
Tue, 17 Jun 2025 12:12:00 +0000 (14:12 +0200)
committerJakub Kicinski <kuba@kernel.org>
Thu, 19 Jun 2025 02:00:15 +0000 (19:00 -0700)
In preparation for reporting PSE events via ethtool notifications,
introduce an attached_phydev field in the pse_control structure.
This field stores the phy_device associated with the PSE PI,
ensuring that notifications are sent to the correct network
interface.

The attached_phydev pointer is directly tied to the PHY lifecycle. It
is set when the PHY is registered and cleared when the PHY is removed.
There is no need to use a refcount, as doing so could interfere with
the PHY removal process.

Signed-off-by: Kory Maincent (Dent Project) <kory.maincent@bootlin.com>
Reviewed-by: Oleksij Rempel <o.rempel@pengutronix.de>
Link: https://patch.msgid.link/20250617-feature_poe_port_prio-v14-1-78a1a645e2ee@bootlin.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/mdio/fwnode_mdio.c
drivers/net/pse-pd/pse_core.c
include/linux/pse-pd/pse.h

index aea0f03575689a57670605383544cf8ee8a25653..9b41d4697a4052cfdc253758395a82f650e6a8a9 100644 (file)
@@ -18,7 +18,8 @@ MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("FWNODE MDIO bus (Ethernet PHY) accessors");
 
 static struct pse_control *
-fwnode_find_pse_control(struct fwnode_handle *fwnode)
+fwnode_find_pse_control(struct fwnode_handle *fwnode,
+                       struct phy_device *phydev)
 {
        struct pse_control *psec;
        struct device_node *np;
@@ -30,7 +31,7 @@ fwnode_find_pse_control(struct fwnode_handle *fwnode)
        if (!np)
                return NULL;
 
-       psec = of_pse_control_get(np);
+       psec = of_pse_control_get(np, phydev);
        if (PTR_ERR(psec) == -ENOENT)
                return NULL;
 
@@ -128,15 +129,9 @@ int fwnode_mdiobus_register_phy(struct mii_bus *bus,
        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)) {
-               rc = PTR_ERR(mii_ts);
-               goto clean_pse;
-       }
+       if (IS_ERR(mii_ts))
+               return PTR_ERR(mii_ts);
 
        is_c45 = fwnode_device_is_compatible(child, "ethernet-phy-ieee802.3-c45");
        if (is_c45 || fwnode_get_phy_id(child, &phy_id))
@@ -169,6 +164,12 @@ int fwnode_mdiobus_register_phy(struct mii_bus *bus,
                        goto clean_phy;
        }
 
+       psec = fwnode_find_pse_control(child, phy);
+       if (IS_ERR(psec)) {
+               rc = PTR_ERR(psec);
+               goto unregister_phy;
+       }
+
        phy->psec = psec;
 
        /* phy->mii_ts may already be defined by the PHY driver. A
@@ -180,12 +181,13 @@ int fwnode_mdiobus_register_phy(struct mii_bus *bus,
 
        return 0;
 
+unregister_phy:
+       if (is_acpi_node(child) || is_of_node(child))
+               phy_device_remove(phy);
 clean_phy:
        phy_device_free(phy);
 clean_mii_ts:
        unregister_mii_timestamper(mii_ts);
-clean_pse:
-       pse_control_put(psec);
 
        return rc;
 }
index 4602e26eb8c8612d430aaa1ef0ccb608287cf53c..4610c1f0ddd6d3da6f2f087e8d94742032d9396d 100644 (file)
@@ -23,6 +23,7 @@ static LIST_HEAD(pse_controller_list);
  * @list: list entry for the pcdev's PSE controller list
  * @id: ID of the PSE line in the PSE controller device
  * @refcnt: Number of gets of this pse_control
+ * @attached_phydev: PHY device pointer attached by the PSE control
  */
 struct pse_control {
        struct pse_controller_dev *pcdev;
@@ -30,6 +31,7 @@ struct pse_control {
        struct list_head list;
        unsigned int id;
        struct kref refcnt;
+       struct phy_device *attached_phydev;
 };
 
 static int of_load_single_pse_pi_pairset(struct device_node *node,
@@ -599,7 +601,8 @@ void pse_control_put(struct pse_control *psec)
 EXPORT_SYMBOL_GPL(pse_control_put);
 
 static struct pse_control *
-pse_control_get_internal(struct pse_controller_dev *pcdev, unsigned int index)
+pse_control_get_internal(struct pse_controller_dev *pcdev, unsigned int index,
+                        struct phy_device *phydev)
 {
        struct pse_control *psec;
        int ret;
@@ -638,6 +641,7 @@ pse_control_get_internal(struct pse_controller_dev *pcdev, unsigned int index)
        psec->pcdev = pcdev;
        list_add(&psec->list, &pcdev->pse_control_head);
        psec->id = index;
+       psec->attached_phydev = phydev;
        kref_init(&psec->refcnt);
 
        return psec;
@@ -693,7 +697,8 @@ static int psec_id_xlate(struct pse_controller_dev *pcdev,
        return pse_spec->args[0];
 }
 
-struct pse_control *of_pse_control_get(struct device_node *node)
+struct pse_control *of_pse_control_get(struct device_node *node,
+                                      struct phy_device *phydev)
 {
        struct pse_controller_dev *r, *pcdev;
        struct of_phandle_args args;
@@ -743,7 +748,7 @@ struct pse_control *of_pse_control_get(struct device_node *node)
        }
 
        /* pse_list_mutex also protects the pcdev's pse_control list */
-       psec = pse_control_get_internal(pcdev, psec_id);
+       psec = pse_control_get_internal(pcdev, psec_id, phydev);
 
 out:
        mutex_unlock(&pse_list_mutex);
index c773eeb92d041a1882209f52d3f471887ae8db20..8b0866fad2ad383945df321680ef5644a9fdd85c 100644 (file)
@@ -250,7 +250,8 @@ struct device;
 int devm_pse_controller_register(struct device *dev,
                                 struct pse_controller_dev *pcdev);
 
-struct pse_control *of_pse_control_get(struct device_node *node);
+struct pse_control *of_pse_control_get(struct device_node *node,
+                                      struct phy_device *phydev);
 void pse_control_put(struct pse_control *psec);
 
 int pse_ethtool_get_status(struct pse_control *psec,
@@ -268,7 +269,8 @@ bool pse_has_c33(struct pse_control *psec);
 
 #else
 
-static inline struct pse_control *of_pse_control_get(struct device_node *node)
+static inline struct pse_control *of_pse_control_get(struct device_node *node,
+                                                    struct phy_device *phydev)
 {
        return ERR_PTR(-ENOENT);
 }