Commit fa2f0454 authored by Kory Maincent (Dent Project)'s avatar Kory Maincent (Dent Project) Committed by Jakub Kicinski
Browse files

net: pse-pd: Introduce attached_phydev to pse control



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: default avatarKory Maincent (Dent Project) <kory.maincent@bootlin.com>
Reviewed-by: default avatarOleksij Rempel <o.rempel@pengutronix.de>
Link: https://patch.msgid.link/20250617-feature_poe_port_prio-v14-1-78a1a645e2ee@bootlin.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent a5b4e4f4
Loading
Loading
Loading
Loading
+14 −12
Original line number Diff line number Diff line
@@ -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;
}
+8 −3
Original line number Diff line number Diff line
@@ -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);
+4 −2
Original line number Diff line number Diff line
@@ -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);
}