.set_pauseparam    = mlx5e_uplink_rep_set_pauseparam,
 };
 
-static void mlx5e_rep_get_port_parent_id(struct net_device *dev,
-                                        struct netdev_phys_item_id *ppid)
-{
-       struct mlx5e_priv *priv;
-       u64 parent_id;
-
-       priv = netdev_priv(dev);
-
-       parent_id = mlx5_query_nic_system_image_guid(priv->mdev);
-       ppid->id_len = sizeof(parent_id);
-       memcpy(ppid->id, &parent_id, sizeof(parent_id));
-}
-
 static void mlx5e_sqs2vport_stop(struct mlx5_eswitch *esw,
                                 struct mlx5_eswitch_rep *rep)
 {
        return 0;
 }
 
-static struct devlink_port *mlx5e_rep_get_devlink_port(struct net_device *dev)
+static struct devlink_port *mlx5e_rep_get_devlink_port(struct net_device *netdev)
 {
-       struct mlx5e_priv *priv = netdev_priv(dev);
+       struct mlx5e_priv *priv = netdev_priv(netdev);
        struct mlx5e_rep_priv *rpriv = priv->ppriv;
+       struct mlx5_core_dev *dev = priv->mdev;
 
-       return &rpriv->dl_port;
+       return mlx5_esw_offloads_devlink_port(dev->priv.eswitch, rpriv->rep->vport);
 }
 
 static int mlx5e_rep_change_carrier(struct net_device *dev, bool new_carrier)
        .stats_grps_num         = mlx5e_ul_rep_stats_grps_num,
 };
 
-static bool
-is_devlink_port_supported(const struct mlx5_core_dev *dev,
-                         const struct mlx5e_rep_priv *rpriv)
-{
-       return rpriv->rep->vport == MLX5_VPORT_UPLINK ||
-              rpriv->rep->vport == MLX5_VPORT_PF ||
-              mlx5_eswitch_is_vf_vport(dev->priv.eswitch, rpriv->rep->vport);
-}
-
-static int register_devlink_port(struct mlx5_core_dev *dev,
-                                struct mlx5e_rep_priv *rpriv)
-{
-       struct mlx5_esw_offload *offloads = &dev->priv.eswitch->offloads;
-       struct devlink *devlink = priv_to_devlink(dev);
-       struct mlx5_eswitch_rep *rep = rpriv->rep;
-       struct devlink_port_attrs attrs = {};
-       struct netdev_phys_item_id ppid = {};
-       unsigned int dl_port_index = 0;
-       u32 controller_num = 0;
-       bool external;
-       u16 pfnum;
-
-       if (!is_devlink_port_supported(dev, rpriv))
-               return 0;
-
-       external = mlx5_core_is_ecpf_esw_manager(dev);
-       if (external)
-               controller_num = offloads->host_number + 1;
-       mlx5e_rep_get_port_parent_id(rpriv->netdev, &ppid);
-       dl_port_index = mlx5_esw_vport_to_devlink_port_index(dev, rep->vport);
-       pfnum = PCI_FUNC(dev->pdev->devfn);
-       if (rep->vport == MLX5_VPORT_UPLINK) {
-               attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
-               attrs.phys.port_number = pfnum;
-               memcpy(attrs.switch_id.id, &ppid.id[0], ppid.id_len);
-               attrs.switch_id.id_len = ppid.id_len;
-               devlink_port_attrs_set(&rpriv->dl_port, &attrs);
-       } else if (rep->vport == MLX5_VPORT_PF) {
-               memcpy(rpriv->dl_port.attrs.switch_id.id, &ppid.id[0], ppid.id_len);
-               rpriv->dl_port.attrs.switch_id.id_len = ppid.id_len;
-               devlink_port_attrs_pci_pf_set(&rpriv->dl_port, controller_num,
-                                             pfnum, external);
-       } else if (mlx5_eswitch_is_vf_vport(dev->priv.eswitch, rpriv->rep->vport)) {
-               memcpy(rpriv->dl_port.attrs.switch_id.id, &ppid.id[0], ppid.id_len);
-               rpriv->dl_port.attrs.switch_id.id_len = ppid.id_len;
-               devlink_port_attrs_pci_vf_set(&rpriv->dl_port, controller_num,
-                                             pfnum, rep->vport - 1, external);
-       }
-       return devlink_port_register(devlink, &rpriv->dl_port, dl_port_index);
-}
-
-static void unregister_devlink_port(struct mlx5_core_dev *dev,
-                                   struct mlx5e_rep_priv *rpriv)
-{
-       if (is_devlink_port_supported(dev, rpriv))
-               devlink_port_unregister(&rpriv->dl_port);
-}
-
 /* e-Switch vport representors */
 static int
 mlx5e_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
 {
        const struct mlx5e_profile *profile;
        struct mlx5e_rep_priv *rpriv;
+       struct devlink_port *dl_port;
        struct net_device *netdev;
        int nch, err;
 
                goto err_detach_netdev;
        }
 
-       err = register_devlink_port(dev, rpriv);
-       if (err) {
-               netdev_warn(netdev, "Failed to register devlink port %d\n",
-                           rep->vport);
-               goto err_neigh_cleanup;
-       }
-
        err = register_netdev(netdev);
        if (err) {
                netdev_warn(netdev,
                            "Failed to register representor netdev for vport %d\n",
                            rep->vport);
-               goto err_devlink_cleanup;
+               goto err_neigh_cleanup;
        }
 
-       if (is_devlink_port_supported(dev, rpriv))
-               devlink_port_type_eth_set(&rpriv->dl_port, netdev);
+       dl_port = mlx5_esw_offloads_devlink_port(dev->priv.eswitch, rpriv->rep->vport);
+       if (dl_port)
+               devlink_port_type_eth_set(dl_port, netdev);
        return 0;
 
-err_devlink_cleanup:
-       unregister_devlink_port(dev, rpriv);
-
 err_neigh_cleanup:
        mlx5e_rep_neigh_cleanup(rpriv);
 
        struct net_device *netdev = rpriv->netdev;
        struct mlx5e_priv *priv = netdev_priv(netdev);
        struct mlx5_core_dev *dev = priv->mdev;
+       struct devlink_port *dl_port;
        void *ppriv = priv->ppriv;
 
-       if (is_devlink_port_supported(dev, rpriv))
-               devlink_port_type_clear(&rpriv->dl_port);
+       dl_port = mlx5_esw_offloads_devlink_port(dev->priv.eswitch, rpriv->rep->vport);
+       if (dl_port)
+               devlink_port_type_clear(dl_port);
        unregister_netdev(netdev);
-       unregister_devlink_port(dev, rpriv);
        mlx5e_rep_neigh_cleanup(rpriv);
        mlx5e_detach_netdev(priv);
        if (rep->vport == MLX5_VPORT_UPLINK)
 
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
+/* Copyright (c) 2020 Mellanox Technologies Ltd. */
+
+#include <linux/mlx5/driver.h>
+#include "eswitch.h"
+
+static void
+mlx5_esw_get_port_parent_id(struct mlx5_core_dev *dev, struct netdev_phys_item_id *ppid)
+{
+       u64 parent_id;
+
+       parent_id = mlx5_query_nic_system_image_guid(dev);
+       ppid->id_len = sizeof(parent_id);
+       memcpy(ppid->id, &parent_id, sizeof(parent_id));
+}
+
+static bool
+mlx5_esw_devlink_port_supported(const struct mlx5_eswitch *esw, u16 vport_num)
+{
+       return vport_num == MLX5_VPORT_UPLINK ||
+              (mlx5_core_is_ecpf(esw->dev) && vport_num == MLX5_VPORT_PF) ||
+              mlx5_eswitch_is_vf_vport(esw, vport_num);
+}
+
+static struct devlink_port *mlx5_esw_dl_port_alloc(struct mlx5_eswitch *esw, u16 vport_num)
+{
+       struct mlx5_core_dev *dev = esw->dev;
+       struct devlink_port_attrs attrs = {};
+       struct netdev_phys_item_id ppid = {};
+       struct devlink_port *dl_port;
+       u32 controller_num = 0;
+       bool external;
+       u16 pfnum;
+
+       dl_port = kzalloc(sizeof(*dl_port), GFP_KERNEL);
+       if (!dl_port)
+               return NULL;
+
+       mlx5_esw_get_port_parent_id(dev, &ppid);
+       pfnum = PCI_FUNC(dev->pdev->devfn);
+       external = mlx5_core_is_ecpf_esw_manager(dev);
+       if (external)
+               controller_num = dev->priv.eswitch->offloads.host_number + 1;
+
+       if (vport_num == MLX5_VPORT_UPLINK) {
+               attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
+               attrs.phys.port_number = pfnum;
+               memcpy(attrs.switch_id.id, ppid.id, ppid.id_len);
+               attrs.switch_id.id_len = ppid.id_len;
+               devlink_port_attrs_set(dl_port, &attrs);
+       } else if (vport_num == MLX5_VPORT_PF) {
+               memcpy(dl_port->attrs.switch_id.id, ppid.id, ppid.id_len);
+               dl_port->attrs.switch_id.id_len = ppid.id_len;
+               devlink_port_attrs_pci_pf_set(dl_port, controller_num, pfnum, external);
+       } else if (mlx5_eswitch_is_vf_vport(esw, vport_num)) {
+               memcpy(dl_port->attrs.switch_id.id, ppid.id, ppid.id_len);
+               dl_port->attrs.switch_id.id_len = ppid.id_len;
+               devlink_port_attrs_pci_vf_set(dl_port, controller_num, pfnum,
+                                             vport_num - 1, external);
+       }
+       return dl_port;
+}
+
+static void mlx5_esw_dl_port_free(struct devlink_port *dl_port)
+{
+       kfree(dl_port);
+}
+
+int mlx5_esw_offloads_devlink_port_register(struct mlx5_eswitch *esw, u16 vport_num)
+{
+       struct mlx5_core_dev *dev = esw->dev;
+       struct devlink_port *dl_port;
+       unsigned int dl_port_index;
+       struct mlx5_vport *vport;
+       struct devlink *devlink;
+       int err;
+
+       if (!mlx5_esw_devlink_port_supported(esw, vport_num))
+               return 0;
+
+       vport = mlx5_eswitch_get_vport(esw, vport_num);
+       if (IS_ERR(vport))
+               return PTR_ERR(vport);
+
+       dl_port = mlx5_esw_dl_port_alloc(esw, vport_num);
+       if (!dl_port)
+               return -ENOMEM;
+
+       devlink = priv_to_devlink(dev);
+       dl_port_index = mlx5_esw_vport_to_devlink_port_index(dev, vport_num);
+       err = devlink_port_register(devlink, dl_port, dl_port_index);
+       if (err)
+               goto reg_err;
+
+       vport->dl_port = dl_port;
+       return 0;
+
+reg_err:
+       mlx5_esw_dl_port_free(dl_port);
+       return err;
+}
+
+void mlx5_esw_offloads_devlink_port_unregister(struct mlx5_eswitch *esw, u16 vport_num)
+{
+       struct mlx5_vport *vport;
+
+       if (!mlx5_esw_devlink_port_supported(esw, vport_num))
+               return;
+
+       vport = mlx5_eswitch_get_vport(esw, vport_num);
+       if (IS_ERR(vport))
+               return;
+       devlink_port_unregister(vport->dl_port);
+       mlx5_esw_dl_port_free(vport->dl_port);
+       vport->dl_port = NULL;
+}
+
+struct devlink_port *mlx5_esw_offloads_devlink_port(struct mlx5_eswitch *esw, u16 vport_num)
+{
+       struct mlx5_vport *vport;
+
+       vport = mlx5_eswitch_get_vport(esw, vport_num);
+       return vport->dl_port;
+}