>From afebdb6e4b52101e863aa36a2fedb5828d93ed4c Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Mon, 1 Apr 2024 18:25:51 +0300 Subject: [PATCH 3/3] net: dsa: move call to driver port_setup after creation of netdev The driver-facing method port_setup() is a good place to add the LEDs of a port to the netdev representing the port. However, when port_setup() is called in dsa_port_devlink_setup(), the netdev does not exist yet. That only happens in dsa_user_create(), which is later in dsa_port_setup(). Move the call to port_setup() out of dsa_port_devlink_setup() and to the end of dsa_port_setup() where the netdev will exist. For the other port types, the call to port_setup() and port_teardown() remains where it was before (functionally speaking), but now it needs to be open-coded in their respective setup/teardown logic. Signed-off-by: Andrew Lunn Signed-off-by: Vladimir Oltean --- net/dsa/devlink.c | 17 +------------- net/dsa/dsa.c | 59 +++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 58 insertions(+), 18 deletions(-) diff --git a/net/dsa/devlink.c b/net/dsa/devlink.c index 431bf52290a1..9c3dc6319269 100644 --- a/net/dsa/devlink.c +++ b/net/dsa/devlink.c @@ -294,20 +294,12 @@ int dsa_port_devlink_setup(struct dsa_port *dp) struct dsa_switch_tree *dst = dp->ds->dst; struct devlink_port_attrs attrs = {}; struct devlink *dl = dp->ds->devlink; - struct dsa_switch *ds = dp->ds; const unsigned char *id; unsigned char len; - int err; memset(dlp, 0, sizeof(*dlp)); devlink_port_init(dl, dlp); - if (ds->ops->port_setup) { - err = ds->ops->port_setup(ds, dp->index); - if (err) - return err; - } - id = (const unsigned char *)&dst->index; len = sizeof(dst->index); @@ -331,14 +323,7 @@ int dsa_port_devlink_setup(struct dsa_port *dp) } devlink_port_attrs_set(dlp, &attrs); - err = devlink_port_register(dl, dlp, dp->index); - if (err) { - if (ds->ops->port_teardown) - ds->ops->port_teardown(ds, dp->index); - return err; - } - - return 0; + return devlink_port_register(dl, dlp, dp->index); } void dsa_port_devlink_teardown(struct dsa_port *dp) diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c index 5d65da9a1971..d8aa869e17ba 100644 --- a/net/dsa/dsa.c +++ b/net/dsa/dsa.c @@ -462,6 +462,15 @@ static void dsa_tree_teardown_cpu_ports(struct dsa_switch_tree *dst) static int dsa_unused_port_setup(struct dsa_port *dp) { + struct dsa_switch *ds = dp->ds; + int err; + + if (ds->ops->port_setup) { + err = ds->ops->port_setup(ds, dp->index); + if (err) + return err; + } + dsa_port_disable(dp); return 0; @@ -469,6 +478,10 @@ static int dsa_unused_port_setup(struct dsa_port *dp) static void dsa_unused_port_teardown(struct dsa_port *dp) { + struct dsa_switch *ds = dp->ds; + + if (ds->ops->port_teardown) + ds->ops->port_teardown(ds, dp->index); } static int dsa_shared_port_setup(struct dsa_port *dp) @@ -490,8 +503,23 @@ static int dsa_shared_port_setup(struct dsa_port *dp) dp->index); } + if (ds->ops->port_setup) { + err = ds->ops->port_setup(ds, dp->index); + if (err) + goto unregister_link; + } + err = dsa_port_enable(dp, NULL); - if (err && link_registered) + if (err) + goto port_teardown; + + return 0; + +port_teardown: + if (ds->ops->port_teardown) + ds->ops->port_teardown(ds, dp->index); +unregister_link: + if (link_registered) dsa_shared_port_link_unregister_of(dp); return err; @@ -499,23 +527,50 @@ static int dsa_shared_port_setup(struct dsa_port *dp) static void dsa_shared_port_teardown(struct dsa_port *dp) { + struct dsa_switch *ds = dp->ds; + dsa_port_disable(dp); + if (ds->ops->port_teardown) + ds->ops->port_teardown(ds, dp->index); if (dp->dn) dsa_shared_port_link_unregister_of(dp); } static int dsa_user_port_setup(struct dsa_port *dp) { + struct dsa_switch *ds = dp->ds; + int err; + of_get_mac_address(dp->dn, dp->mac); - return dsa_user_create(dp); + err = dsa_user_create(dp); + if (err) + return err; + + if (ds->ops->port_setup) { + err = ds->ops->port_setup(ds, dp->index); + if (err) + goto user_destroy; + } + + return 0; + +user_destroy: + dsa_user_destroy(dp->user); + dp->user = NULL; + return err; } static void dsa_user_port_teardown(struct dsa_port *dp) { + struct dsa_switch *ds = dp->ds; + if (!dp->user) return; + if (ds->ops->port_teardown) + ds->ops->port_teardown(ds, dp->index); + dsa_user_destroy(dp->user); dp->user = NULL; } -- 2.34.1