dp->cpu_dp = NULL;
 }
 
+static int dsa_port_devlink_setup(struct dsa_port *dp)
+{
+       struct devlink_port *dlp = &dp->devlink_port;
+       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);
+
+       attrs.phys.port_number = dp->index;
+       memcpy(attrs.switch_id.id, id, len);
+       attrs.switch_id.id_len = len;
+
+       switch (dp->type) {
+       case DSA_PORT_TYPE_UNUSED:
+               attrs.flavour = DEVLINK_PORT_FLAVOUR_UNUSED;
+               break;
+       case DSA_PORT_TYPE_CPU:
+               attrs.flavour = DEVLINK_PORT_FLAVOUR_CPU;
+               break;
+       case DSA_PORT_TYPE_DSA:
+               attrs.flavour = DEVLINK_PORT_FLAVOUR_DSA;
+               break;
+       case DSA_PORT_TYPE_USER:
+               attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
+               break;
+       }
+
+       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;
+       }
+       dp->devlink_port_setup = true;
+
+       return 0;
+}
+
+static void dsa_port_devlink_teardown(struct dsa_port *dp)
+{
+       struct devlink_port *dlp = &dp->devlink_port;
+       struct dsa_switch *ds = dp->ds;
+
+       if (dp->devlink_port_setup) {
+               devlink_port_unregister(dlp);
+               if (ds->ops->port_teardown)
+                       ds->ops->port_teardown(ds, dp->index);
+               devlink_port_fini(dlp);
+       }
+       dp->devlink_port_setup = false;
+}
+
 static int dsa_port_setup(struct dsa_port *dp)
 {
        struct devlink_port *dlp = &dp->devlink_port;
        if (dp->setup)
                return 0;
 
+       err = dsa_port_devlink_setup(dp);
+       if (err)
+               return err;
+
        switch (dp->type) {
        case DSA_PORT_TYPE_UNUSED:
                dsa_port_disable(dp);
                dsa_port_disable(dp);
        if (err && dsa_port_link_registered)
                dsa_shared_port_link_unregister_of(dp);
-       if (err)
-               return err;
-
-       dp->setup = true;
-
-       return 0;
-}
-
-static int dsa_port_devlink_setup(struct dsa_port *dp)
-{
-       struct devlink_port *dlp = &dp->devlink_port;
-       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);
-
-       attrs.phys.port_number = dp->index;
-       memcpy(attrs.switch_id.id, id, len);
-       attrs.switch_id.id_len = len;
-
-       switch (dp->type) {
-       case DSA_PORT_TYPE_UNUSED:
-               attrs.flavour = DEVLINK_PORT_FLAVOUR_UNUSED;
-               break;
-       case DSA_PORT_TYPE_CPU:
-               attrs.flavour = DEVLINK_PORT_FLAVOUR_CPU;
-               break;
-       case DSA_PORT_TYPE_DSA:
-               attrs.flavour = DEVLINK_PORT_FLAVOUR_DSA;
-               break;
-       case DSA_PORT_TYPE_USER:
-               attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
-               break;
-       }
-
-       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);
+               dsa_port_devlink_teardown(dp);
                return err;
        }
-       dp->devlink_port_setup = true;
+
+       dp->setup = true;
 
        return 0;
 }
                break;
        }
 
-       dp->setup = false;
-}
-
-static void dsa_port_devlink_teardown(struct dsa_port *dp)
-{
-       struct devlink_port *dlp = &dp->devlink_port;
-       struct dsa_switch *ds = dp->ds;
+       dsa_port_devlink_teardown(dp);
 
-       if (dp->devlink_port_setup) {
-               devlink_port_unregister(dlp);
-               if (ds->ops->port_teardown)
-                       ds->ops->port_teardown(ds, dp->index);
-               devlink_port_fini(dlp);
-       }
-       dp->devlink_port_setup = false;
+       dp->setup = false;
 }
 
-/* Destroy the current devlink port, and create a new one which has the UNUSED
- * flavour.
- */
-static int dsa_port_reinit_as_unused(struct dsa_port *dp)
+static int dsa_port_setup_as_unused(struct dsa_port *dp)
 {
-       dsa_port_devlink_teardown(dp);
        dp->type = DSA_PORT_TYPE_UNUSED;
-       return dsa_port_devlink_setup(dp);
+       return dsa_port_setup(dp);
 }
 
 static int dsa_devlink_info_get(struct devlink *dl,
 {
        struct dsa_devlink_priv *dl_priv;
        struct device_node *dn;
-       struct dsa_port *dp;
        int err;
 
        if (ds->setup)
        dl_priv = devlink_priv(ds->devlink);
        dl_priv->ds = ds;
 
-       /* Setup devlink port instances now, so that the switch
-        * setup() can register regions etc, against the ports
-        */
-       dsa_switch_for_each_port(dp, ds) {
-               err = dsa_port_devlink_setup(dp);
-               if (err)
-                       goto unregister_devlink_ports;
-       }
-
        err = dsa_switch_register_notifier(ds);
        if (err)
-               goto unregister_devlink_ports;
+               goto devlink_free;
 
        ds->configure_vlan_while_not_filtering = true;
 
                ds->ops->teardown(ds);
 unregister_notifier:
        dsa_switch_unregister_notifier(ds);
-unregister_devlink_ports:
-       dsa_switch_for_each_port(dp, ds)
-               dsa_port_devlink_teardown(dp);
+devlink_free:
        devlink_free(ds->devlink);
        ds->devlink = NULL;
        return err;
 
 static void dsa_switch_teardown(struct dsa_switch *ds)
 {
-       struct dsa_port *dp;
-
        if (!ds->setup)
                return;
 
        dsa_switch_unregister_notifier(ds);
 
        if (ds->devlink) {
-               dsa_switch_for_each_port(dp, ds)
-                       dsa_port_devlink_teardown(dp);
                devlink_free(ds->devlink);
                ds->devlink = NULL;
        }
                if (dsa_port_is_user(dp) || dsa_port_is_unused(dp)) {
                        err = dsa_port_setup(dp);
                        if (err) {
-                               err = dsa_port_reinit_as_unused(dp);
+                               err = dsa_port_setup_as_unused(dp);
                                if (err)
                                        goto teardown;
                        }