Add a method to dsa_switch_ops to allow a switch driver to override the fwnode used to setup phylink for a port. This will be used for the Marvell 88e6xxx driver to provide its "maximum interface" and "maximum speed" mode to keep compatibility with existing behaviour for CPU and DSA ports via a swnode-backed fwnode. We need to release the swnode after phylink_create() has completed no matter what the outcome was. Signed-off-by: Russell King (Oracle) <rmk+kernel@xxxxxxxxxxxxxxx> --- include/net/dsa.h | 3 +++ net/dsa/port.c | 12 ++++++++++++ 2 files changed, 15 insertions(+) diff --git a/include/net/dsa.h b/include/net/dsa.h index a15f17a38eca..764f3e74448b 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -854,6 +854,9 @@ struct dsa_switch_ops { */ int (*port_setup)(struct dsa_switch *ds, int port); void (*port_teardown)(struct dsa_switch *ds, int port); + struct fwnode_handle *(*port_get_fwnode)(struct dsa_switch *ds, + int port, + struct fwnode_handle *h); u32 (*get_phy_flags)(struct dsa_switch *ds, int port); diff --git a/net/dsa/port.c b/net/dsa/port.c index 07f9cb374a5d..c30e3a7d2145 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c @@ -1693,6 +1693,15 @@ int dsa_port_phylink_create(struct dsa_port *dp) ds->ops->phylink_get_caps(ds, dp->index, &dp->pl_config); fwnode = of_fwnode_handle(dp->dn); + if (ds->ops->port_get_fwnode) { + fwnode = ds->ops->port_get_fwnode(ds, dp->index, fwnode); + if (IS_ERR(fwnode)) { + dev_err(ds->dev, + "Failed to get fwnode for port %d: %pe\n", + dp->index, fwnode); + return PTR_ERR(fwnode); + } + } mode = fwnode_get_phy_mode(fwnode); if (mode < 0) @@ -1700,6 +1709,9 @@ int dsa_port_phylink_create(struct dsa_port *dp) pl = phylink_create(&dp->pl_config, fwnode, mode, &dsa_port_phylink_mac_ops); + + fwnode_remove_software_node(fwnode); + if (IS_ERR(pl)) { pr_err("error creating PHYLINK: %ld\n", PTR_ERR(pl)); return PTR_ERR(pl); -- 2.30.2