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: 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>
This commit is contained in:
committed by
Jakub Kicinski
parent
a5b4e4f4d8
commit
fa2f045417
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user