#include <linux/rcupdate.h>
 #include <linux/slab.h>
 #include <asm/byteorder.h>
+#include <net/devlink.h>
 
 #include "core.h"
 #include "item.h"
        const char *device_kind = mlxsw_bus_info->device_kind;
        struct mlxsw_core *mlxsw_core;
        struct mlxsw_driver *mlxsw_driver;
+       struct devlink *devlink;
        size_t alloc_size;
        int err;
 
        if (!mlxsw_driver)
                return -EINVAL;
        alloc_size = sizeof(*mlxsw_core) + mlxsw_driver->priv_size;
-       mlxsw_core = kzalloc(alloc_size, GFP_KERNEL);
-       if (!mlxsw_core) {
+       devlink = devlink_alloc(NULL, alloc_size);
+       if (!devlink) {
                err = -ENOMEM;
-               goto err_core_alloc;
+               goto err_devlink_alloc;
        }
 
+       mlxsw_core = devlink_priv(devlink);
        INIT_LIST_HEAD(&mlxsw_core->rx_listener_list);
        INIT_LIST_HEAD(&mlxsw_core->event_listener_list);
        mlxsw_core->driver = mlxsw_driver;
        if (err)
                goto err_hwmon_init;
 
+       err = devlink_register(devlink, mlxsw_bus_info->dev);
+       if (err)
+               goto err_devlink_register;
+
        err = mlxsw_driver->init(mlxsw_core->driver_priv, mlxsw_core,
                                 mlxsw_bus_info);
        if (err)
 err_debugfs_init:
        mlxsw_core->driver->fini(mlxsw_core->driver_priv);
 err_driver_init:
+       devlink_unregister(devlink);
+err_devlink_register:
 err_hwmon_init:
        mlxsw_emad_fini(mlxsw_core);
 err_emad_init:
 err_alloc_lag_mapping:
        free_percpu(mlxsw_core->pcpu_stats);
 err_alloc_stats:
-       kfree(mlxsw_core);
-err_core_alloc:
+       devlink_free(devlink);
+err_devlink_alloc:
        mlxsw_core_driver_put(device_kind);
        return err;
 }
 void mlxsw_core_bus_device_unregister(struct mlxsw_core *mlxsw_core)
 {
        const char *device_kind = mlxsw_core->bus_info->device_kind;
+       struct devlink *devlink = priv_to_devlink(mlxsw_core);
 
        mlxsw_core_debugfs_fini(mlxsw_core);
        mlxsw_core->driver->fini(mlxsw_core->driver_priv);
+       devlink_unregister(devlink);
        mlxsw_emad_fini(mlxsw_core);
        mlxsw_core->bus->fini(mlxsw_core->bus_priv);
        kfree(mlxsw_core->lag.mapping);
        free_percpu(mlxsw_core->pcpu_stats);
-       kfree(mlxsw_core);
+       devlink_free(devlink);
        mlxsw_core_driver_put(device_kind);
 }
 EXPORT_SYMBOL(mlxsw_core_bus_device_unregister);
 
 #include <linux/jiffies.h>
 #include <linux/bitops.h>
 #include <linux/list.h>
+#include <net/devlink.h>
 #include <net/switchdev.h>
 #include <generated/utsrelease.h>
 
 
 static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port)
 {
+       struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
        struct mlxsw_sp_port *mlxsw_sp_port;
+       struct devlink_port *devlink_port;
        struct net_device *dev;
        bool usable;
        size_t bytes;
                goto port_not_usable;
        }
 
+       devlink_port = &mlxsw_sp_port->devlink_port;
+       err = devlink_port_register(devlink, devlink_port, local_port);
+       if (err) {
+               dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to register devlink port\n",
+                       mlxsw_sp_port->local_port);
+               goto err_devlink_port_register;
+       }
+
        err = mlxsw_sp_port_system_port_mapping_set(mlxsw_sp_port);
        if (err) {
                dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to set system port mapping\n",
                goto err_register_netdev;
        }
 
+       devlink_port_type_eth_set(devlink_port, dev);
+
        err = mlxsw_sp_port_vlan_init(mlxsw_sp_port);
        if (err)
                goto err_port_vlan_init;
 err_port_mtu_set:
 err_port_swid_set:
 err_port_system_port_mapping_set:
+       devlink_port_unregister(&mlxsw_sp_port->devlink_port);
+err_devlink_port_register:
 port_not_usable:
 err_port_module_check:
 err_dev_addr_init:
 static void mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u8 local_port)
 {
        struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp->ports[local_port];
+       struct devlink_port *devlink_port;
 
        if (!mlxsw_sp_port)
                return;
+       devlink_port = &mlxsw_sp_port->devlink_port;
+       devlink_port_type_clear(devlink_port);
        unregister_netdev(mlxsw_sp_port->dev); /* This calls ndo_stop */
+       devlink_port_unregister(devlink_port);
        mlxsw_sp_port_vports_fini(mlxsw_sp_port);
        mlxsw_sp_port_switchdev_fini(mlxsw_sp_port);
        free_percpu(mlxsw_sp_port->pcpu_stats);
 
 #include <linux/if_vlan.h>
 #include <linux/list.h>
 #include <net/switchdev.h>
+#include <net/devlink.h>
 
 #include "port.h"
 #include "core.h"
        unsigned long *untagged_vlans;
        /* VLAN interfaces */
        struct list_head vports_list;
+       struct devlink_port devlink_port;
 };
 
 static inline struct mlxsw_sp_port *
 
 #include <linux/device.h>
 #include <linux/skbuff.h>
 #include <linux/if_vlan.h>
+#include <net/devlink.h>
 #include <net/switchdev.h>
 #include <generated/utsrelease.h>
 
        struct mlxsw_sx_port_pcpu_stats __percpu *pcpu_stats;
        struct mlxsw_sx *mlxsw_sx;
        u8 local_port;
+       struct devlink_port devlink_port;
 };
 
 /* tx_hdr_version
 
 static int mlxsw_sx_port_create(struct mlxsw_sx *mlxsw_sx, u8 local_port)
 {
+       struct devlink *devlink = priv_to_devlink(mlxsw_sx->core);
        struct mlxsw_sx_port *mlxsw_sx_port;
+       struct devlink_port *devlink_port;
        struct net_device *dev;
        bool usable;
        int err;
                goto port_not_usable;
        }
 
+       devlink_port = &mlxsw_sx_port->devlink_port;
+       err = devlink_port_register(devlink, devlink_port, local_port);
+       if (err) {
+               dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to register devlink port\n",
+                       mlxsw_sx_port->local_port);
+               goto err_devlink_port_register;
+       }
+
        err = mlxsw_sx_port_system_port_mapping_set(mlxsw_sx_port);
        if (err) {
                dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to set system port mapping\n",
                goto err_register_netdev;
        }
 
+       devlink_port_type_eth_set(devlink_port, dev);
+
        mlxsw_sx->ports[local_port] = mlxsw_sx_port;
        return 0;
 
 err_port_speed_set:
 err_port_swid_set:
 err_port_system_port_mapping_set:
+       devlink_port_unregister(&mlxsw_sx_port->devlink_port);
+err_devlink_port_register:
 port_not_usable:
 err_port_module_check:
 err_dev_addr_get:
 static void mlxsw_sx_port_remove(struct mlxsw_sx *mlxsw_sx, u8 local_port)
 {
        struct mlxsw_sx_port *mlxsw_sx_port = mlxsw_sx->ports[local_port];
+       struct devlink_port *devlink_port;
 
        if (!mlxsw_sx_port)
                return;
+       devlink_port = &mlxsw_sx_port->devlink_port;
+       devlink_port_type_clear(devlink_port);
        unregister_netdev(mlxsw_sx_port->dev); /* This calls ndo_stop */
        mlxsw_sx_port_swid_set(mlxsw_sx_port, MLXSW_PORT_SWID_DISABLED_PORT);
+       devlink_port_unregister(devlink_port);
        free_percpu(mlxsw_sx_port->pcpu_stats);
        free_netdev(mlxsw_sx_port->dev);
 }