},
 };
 
-static u64 mlxsw_sp_resource_kvd_linear_occ_get(struct devlink *devlink)
-{
-       struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
-       struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
-
-       return mlxsw_sp_kvdl_occ_get(mlxsw_sp);
-}
-
-static const struct devlink_resource_ops mlxsw_sp_resource_kvd_linear_ops = {
-       .occ_get = mlxsw_sp_resource_kvd_linear_occ_get,
-};
-
 static void
 mlxsw_sp_resource_size_params_prepare(struct mlxsw_core *mlxsw_core,
                                      struct devlink_resource_size_params *kvd_size_params,
        err = devlink_resource_register(devlink, MLXSW_SP_RESOURCE_NAME_KVD,
                                        kvd_size, MLXSW_SP_RESOURCE_KVD,
                                        DEVLINK_RESOURCE_ID_PARENT_TOP,
-                                       &kvd_size_params,
-                                       NULL);
+                                       &kvd_size_params);
        if (err)
                return err;
 
                                        linear_size,
                                        MLXSW_SP_RESOURCE_KVD_LINEAR,
                                        MLXSW_SP_RESOURCE_KVD,
-                                       &linear_size_params,
-                                       &mlxsw_sp_resource_kvd_linear_ops);
+                                       &linear_size_params);
        if (err)
                return err;
 
                                        double_size,
                                        MLXSW_SP_RESOURCE_KVD_HASH_DOUBLE,
                                        MLXSW_SP_RESOURCE_KVD,
-                                       &hash_double_size_params,
-                                       NULL);
+                                       &hash_double_size_params);
        if (err)
                return err;
 
                                        single_size,
                                        MLXSW_SP_RESOURCE_KVD_HASH_SINGLE,
                                        MLXSW_SP_RESOURCE_KVD,
-                                       &hash_single_size_params,
-                                       NULL);
+                                       &hash_single_size_params);
        if (err)
                return err;
 
 
 int mlxsw_sp_kvdl_alloc_size_query(struct mlxsw_sp *mlxsw_sp,
                                   unsigned int entry_count,
                                   unsigned int *p_alloc_size);
-u64 mlxsw_sp_kvdl_occ_get(const struct mlxsw_sp *mlxsw_sp);
 int mlxsw_sp_kvdl_resources_register(struct mlxsw_core *mlxsw_core);
 
 struct mlxsw_sp_acl_rule_info {
 
        return occ;
 }
 
-u64 mlxsw_sp_kvdl_occ_get(const struct mlxsw_sp *mlxsw_sp)
+static u64 mlxsw_sp_kvdl_occ_get(void *priv)
 {
+       const struct mlxsw_sp *mlxsw_sp = priv;
        u64 occ = 0;
        int i;
 
        return occ;
 }
 
-static u64 mlxsw_sp_kvdl_single_occ_get(struct devlink *devlink)
+static u64 mlxsw_sp_kvdl_single_occ_get(void *priv)
 {
-       struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
-       struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
+       const struct mlxsw_sp *mlxsw_sp = priv;
        struct mlxsw_sp_kvdl_part *part;
 
        part = mlxsw_sp->kvdl->parts[MLXSW_SP_KVDL_PART_ID_SINGLE];
        return mlxsw_sp_kvdl_part_occ(part);
 }
 
-static u64 mlxsw_sp_kvdl_chunks_occ_get(struct devlink *devlink)
+static u64 mlxsw_sp_kvdl_chunks_occ_get(void *priv)
 {
-       struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
-       struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
+       const struct mlxsw_sp *mlxsw_sp = priv;
        struct mlxsw_sp_kvdl_part *part;
 
        part = mlxsw_sp->kvdl->parts[MLXSW_SP_KVDL_PART_ID_CHUNKS];
        return mlxsw_sp_kvdl_part_occ(part);
 }
 
-static u64 mlxsw_sp_kvdl_large_chunks_occ_get(struct devlink *devlink)
+static u64 mlxsw_sp_kvdl_large_chunks_occ_get(void *priv)
 {
-       struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
-       struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
+       const struct mlxsw_sp *mlxsw_sp = priv;
        struct mlxsw_sp_kvdl_part *part;
 
        part = mlxsw_sp->kvdl->parts[MLXSW_SP_KVDL_PART_ID_LARGE_CHUNKS];
        return mlxsw_sp_kvdl_part_occ(part);
 }
 
-static const struct devlink_resource_ops mlxsw_sp_kvdl_single_ops = {
-       .occ_get = mlxsw_sp_kvdl_single_occ_get,
-};
-
-static const struct devlink_resource_ops mlxsw_sp_kvdl_chunks_ops = {
-       .occ_get = mlxsw_sp_kvdl_chunks_occ_get,
-};
-
-static const struct devlink_resource_ops mlxsw_sp_kvdl_chunks_large_ops = {
-       .occ_get = mlxsw_sp_kvdl_large_chunks_occ_get,
-};
-
 int mlxsw_sp_kvdl_resources_register(struct mlxsw_core *mlxsw_core)
 {
        struct devlink *devlink = priv_to_devlink(mlxsw_core);
                                        MLXSW_SP_KVDL_SINGLE_SIZE,
                                        MLXSW_SP_RESOURCE_KVD_LINEAR_SINGLE,
                                        MLXSW_SP_RESOURCE_KVD_LINEAR,
-                                       &size_params,
-                                       &mlxsw_sp_kvdl_single_ops);
+                                       &size_params);
        if (err)
                return err;
 
                                        MLXSW_SP_KVDL_CHUNKS_SIZE,
                                        MLXSW_SP_RESOURCE_KVD_LINEAR_CHUNKS,
                                        MLXSW_SP_RESOURCE_KVD_LINEAR,
-                                       &size_params,
-                                       &mlxsw_sp_kvdl_chunks_ops);
+                                       &size_params);
        if (err)
                return err;
 
                                        MLXSW_SP_KVDL_LARGE_CHUNKS_SIZE,
                                        MLXSW_SP_RESOURCE_KVD_LINEAR_LARGE_CHUNKS,
                                        MLXSW_SP_RESOURCE_KVD_LINEAR,
-                                       &size_params,
-                                       &mlxsw_sp_kvdl_chunks_large_ops);
+                                       &size_params);
        return err;
 }
 
 int mlxsw_sp_kvdl_init(struct mlxsw_sp *mlxsw_sp)
 {
+       struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
        struct mlxsw_sp_kvdl *kvdl;
        int err;
 
        if (err)
                goto err_kvdl_parts_init;
 
+       devlink_resource_occ_get_register(devlink,
+                                         MLXSW_SP_RESOURCE_KVD_LINEAR,
+                                         mlxsw_sp_kvdl_occ_get,
+                                         mlxsw_sp);
+       devlink_resource_occ_get_register(devlink,
+                                         MLXSW_SP_RESOURCE_KVD_LINEAR_SINGLE,
+                                         mlxsw_sp_kvdl_single_occ_get,
+                                         mlxsw_sp);
+       devlink_resource_occ_get_register(devlink,
+                                         MLXSW_SP_RESOURCE_KVD_LINEAR_CHUNKS,
+                                         mlxsw_sp_kvdl_chunks_occ_get,
+                                         mlxsw_sp);
+       devlink_resource_occ_get_register(devlink,
+                                         MLXSW_SP_RESOURCE_KVD_LINEAR_LARGE_CHUNKS,
+                                         mlxsw_sp_kvdl_large_chunks_occ_get,
+                                         mlxsw_sp);
+
        return 0;
 
 err_kvdl_parts_init:
 
 void mlxsw_sp_kvdl_fini(struct mlxsw_sp *mlxsw_sp)
 {
+       struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
+
+       devlink_resource_occ_get_unregister(devlink,
+                                           MLXSW_SP_RESOURCE_KVD_LINEAR_LARGE_CHUNKS);
+       devlink_resource_occ_get_unregister(devlink,
+                                           MLXSW_SP_RESOURCE_KVD_LINEAR_CHUNKS);
+       devlink_resource_occ_get_unregister(devlink,
+                                           MLXSW_SP_RESOURCE_KVD_LINEAR_SINGLE);
+       devlink_resource_occ_get_unregister(devlink,
+                                           MLXSW_SP_RESOURCE_KVD_LINEAR);
        mlxsw_sp_kvdl_parts_fini(mlxsw_sp);
        kfree(mlxsw_sp->kvdl);
 }
 
 
 /* IPv4
  */
-static u64 nsim_ipv4_fib_resource_occ_get(struct devlink *devlink)
+static u64 nsim_ipv4_fib_resource_occ_get(void *priv)
 {
-       struct net *net = nsim_devlink_net(devlink);
+       struct net *net = priv;
 
        return nsim_fib_get_val(net, NSIM_RESOURCE_IPV4_FIB, false);
 }
 
-static struct devlink_resource_ops nsim_ipv4_fib_res_ops = {
-       .occ_get = nsim_ipv4_fib_resource_occ_get,
-};
-
-static u64 nsim_ipv4_fib_rules_res_occ_get(struct devlink *devlink)
+static u64 nsim_ipv4_fib_rules_res_occ_get(void *priv)
 {
-       struct net *net = nsim_devlink_net(devlink);
+       struct net *net = priv;
 
        return nsim_fib_get_val(net, NSIM_RESOURCE_IPV4_FIB_RULES, false);
 }
 
-static struct devlink_resource_ops nsim_ipv4_fib_rules_res_ops = {
-       .occ_get = nsim_ipv4_fib_rules_res_occ_get,
-};
-
 /* IPv6
  */
-static u64 nsim_ipv6_fib_resource_occ_get(struct devlink *devlink)
+static u64 nsim_ipv6_fib_resource_occ_get(void *priv)
 {
-       struct net *net = nsim_devlink_net(devlink);
+       struct net *net = priv;
 
        return nsim_fib_get_val(net, NSIM_RESOURCE_IPV6_FIB, false);
 }
 
-static struct devlink_resource_ops nsim_ipv6_fib_res_ops = {
-       .occ_get = nsim_ipv6_fib_resource_occ_get,
-};
-
-static u64 nsim_ipv6_fib_rules_res_occ_get(struct devlink *devlink)
+static u64 nsim_ipv6_fib_rules_res_occ_get(void *priv)
 {
-       struct net *net = nsim_devlink_net(devlink);
+       struct net *net = priv;
 
        return nsim_fib_get_val(net, NSIM_RESOURCE_IPV6_FIB_RULES, false);
 }
 
-static struct devlink_resource_ops nsim_ipv6_fib_rules_res_ops = {
-       .occ_get = nsim_ipv6_fib_rules_res_occ_get,
-};
-
 static int devlink_resources_register(struct devlink *devlink)
 {
        struct devlink_resource_size_params params = {
        err = devlink_resource_register(devlink, "IPv4", (u64)-1,
                                        NSIM_RESOURCE_IPV4,
                                        DEVLINK_RESOURCE_ID_PARENT_TOP,
-                                       ¶ms, NULL);
+                                       ¶ms);
        if (err) {
                pr_err("Failed to register IPv4 top resource\n");
                goto out;
        n = nsim_fib_get_val(net, NSIM_RESOURCE_IPV4_FIB, true);
        err = devlink_resource_register(devlink, "fib", n,
                                        NSIM_RESOURCE_IPV4_FIB,
-                                       NSIM_RESOURCE_IPV4,
-                                       ¶ms, &nsim_ipv4_fib_res_ops);
+                                       NSIM_RESOURCE_IPV4, ¶ms);
        if (err) {
                pr_err("Failed to register IPv4 FIB resource\n");
                return err;
        n = nsim_fib_get_val(net, NSIM_RESOURCE_IPV4_FIB_RULES, true);
        err = devlink_resource_register(devlink, "fib-rules", n,
                                        NSIM_RESOURCE_IPV4_FIB_RULES,
-                                       NSIM_RESOURCE_IPV4,
-                                       ¶ms, &nsim_ipv4_fib_rules_res_ops);
+                                       NSIM_RESOURCE_IPV4, ¶ms);
        if (err) {
                pr_err("Failed to register IPv4 FIB rules resource\n");
                return err;
        err = devlink_resource_register(devlink, "IPv6", (u64)-1,
                                        NSIM_RESOURCE_IPV6,
                                        DEVLINK_RESOURCE_ID_PARENT_TOP,
-                                       ¶ms, NULL);
+                                       ¶ms);
        if (err) {
                pr_err("Failed to register IPv6 top resource\n");
                goto out;
        n = nsim_fib_get_val(net, NSIM_RESOURCE_IPV6_FIB, true);
        err = devlink_resource_register(devlink, "fib", n,
                                        NSIM_RESOURCE_IPV6_FIB,
-                                       NSIM_RESOURCE_IPV6,
-                                       ¶ms, &nsim_ipv6_fib_res_ops);
+                                       NSIM_RESOURCE_IPV6, ¶ms);
        if (err) {
                pr_err("Failed to register IPv6 FIB resource\n");
                return err;
        n = nsim_fib_get_val(net, NSIM_RESOURCE_IPV6_FIB_RULES, true);
        err = devlink_resource_register(devlink, "fib-rules", n,
                                        NSIM_RESOURCE_IPV6_FIB_RULES,
-                                       NSIM_RESOURCE_IPV6,
-                                       ¶ms, &nsim_ipv6_fib_rules_res_ops);
+                                       NSIM_RESOURCE_IPV6, ¶ms);
        if (err) {
                pr_err("Failed to register IPv6 FIB rules resource\n");
                return err;
        }
+
+       devlink_resource_occ_get_register(devlink,
+                                         NSIM_RESOURCE_IPV4_FIB,
+                                         nsim_ipv4_fib_resource_occ_get,
+                                         net);
+       devlink_resource_occ_get_register(devlink,
+                                         NSIM_RESOURCE_IPV4_FIB_RULES,
+                                         nsim_ipv4_fib_rules_res_occ_get,
+                                         net);
+       devlink_resource_occ_get_register(devlink,
+                                         NSIM_RESOURCE_IPV6_FIB,
+                                         nsim_ipv6_fib_resource_occ_get,
+                                         net);
+       devlink_resource_occ_get_register(devlink,
+                                         NSIM_RESOURCE_IPV6_FIB_RULES,
+                                         nsim_ipv6_fib_rules_res_occ_get,
+                                         net);
 out:
        return err;
 }
 
        unsigned int headers_count;
 };
 
-/**
- * struct devlink_resource_ops - resource ops
- * @occ_get: get the occupied size
- */
-struct devlink_resource_ops {
-       u64 (*occ_get)(struct devlink *devlink);
-};
-
 /**
  * struct devlink_resource_size_params - resource's size parameters
  * @size_min: minimum size which can be set
        size_params->unit = unit;
 }
 
+typedef u64 devlink_resource_occ_get_t(void *priv);
+
 /**
  * struct devlink_resource - devlink resource
  * @name: name of the resource
  * @size_params: size parameters
  * @list: parent list
  * @resource_list: list of child resources
- * @resource_ops: resource ops
  */
 struct devlink_resource {
        const char *name;
        struct devlink_resource_size_params size_params;
        struct list_head list;
        struct list_head resource_list;
-       const struct devlink_resource_ops *resource_ops;
+       devlink_resource_occ_get_t *occ_get;
+       void *occ_get_priv;
 };
 
 #define DEVLINK_RESOURCE_ID_PARENT_TOP 0
                              u64 resource_size,
                              u64 resource_id,
                              u64 parent_resource_id,
-                             const struct devlink_resource_size_params *size_params,
-                             const struct devlink_resource_ops *resource_ops);
+                             const struct devlink_resource_size_params *size_params);
 void devlink_resources_unregister(struct devlink *devlink,
                                  struct devlink_resource *resource);
 int devlink_resource_size_get(struct devlink *devlink,
 int devlink_dpipe_table_resource_set(struct devlink *devlink,
                                     const char *table_name, u64 resource_id,
                                     u64 resource_units);
+void devlink_resource_occ_get_register(struct devlink *devlink,
+                                      u64 resource_id,
+                                      devlink_resource_occ_get_t *occ_get,
+                                      void *occ_get_priv);
+void devlink_resource_occ_get_unregister(struct devlink *devlink,
+                                        u64 resource_id);
 
 #else
 
                          u64 resource_size,
                          u64 resource_id,
                          u64 parent_resource_id,
-                         const struct devlink_resource_size_params *size_params,
-                         const struct devlink_resource_ops *resource_ops)
+                         const struct devlink_resource_size_params *size_params)
 {
        return 0;
 }
        return -EOPNOTSUPP;
 }
 
+static inline void
+devlink_resource_occ_get_register(struct devlink *devlink,
+                                 u64 resource_id,
+                                 devlink_resource_occ_get_t *occ_get,
+                                 void *occ_get_priv)
+{
+}
+
+static inline void
+devlink_resource_occ_get_unregister(struct devlink *devlink,
+                                   u64 resource_id)
+{
+}
+
 #endif
 
 #endif /* _NET_DEVLINK_H_ */
 
        return 0;
 }
 
+static int devlink_resource_occ_put(struct devlink_resource *resource,
+                                   struct sk_buff *skb)
+{
+       if (!resource->occ_get)
+               return 0;
+       return nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_OCC,
+                                resource->occ_get(resource->occ_get_priv),
+                                DEVLINK_ATTR_PAD);
+}
+
 static int devlink_resource_put(struct devlink *devlink, struct sk_buff *skb,
                                struct devlink_resource *resource)
 {
        if (resource->size != resource->size_new)
                nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_NEW,
                                  resource->size_new, DEVLINK_ATTR_PAD);
-       if (resource->resource_ops && resource->resource_ops->occ_get)
-               if (nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_OCC,
-                                     resource->resource_ops->occ_get(devlink),
-                                     DEVLINK_ATTR_PAD))
-                       goto nla_put_failure;
+       if (devlink_resource_occ_put(resource, skb))
+               goto nla_put_failure;
        if (devlink_resource_size_params_put(resource, skb))
                goto nla_put_failure;
        if (list_empty(&resource->resource_list))
  *     @resource_id: resource's id
  *     @parent_reosurce_id: resource's parent id
  *     @size params: size parameters
- *     @resource_ops: resource ops
  */
 int devlink_resource_register(struct devlink *devlink,
                              const char *resource_name,
                              u64 resource_size,
                              u64 resource_id,
                              u64 parent_resource_id,
-                             const struct devlink_resource_size_params *size_params,
-                             const struct devlink_resource_ops *resource_ops)
+                             const struct devlink_resource_size_params *size_params)
 {
        struct devlink_resource *resource;
        struct list_head *resource_list;
        resource->size = resource_size;
        resource->size_new = resource_size;
        resource->id = resource_id;
-       resource->resource_ops = resource_ops;
        resource->size_valid = true;
        memcpy(&resource->size_params, size_params,
               sizeof(resource->size_params));
 }
 EXPORT_SYMBOL_GPL(devlink_dpipe_table_resource_set);
 
+/**
+ *     devlink_resource_occ_get_register - register occupancy getter
+ *
+ *     @devlink: devlink
+ *     @resource_id: resource id
+ *     @occ_get: occupancy getter callback
+ *     @occ_get_priv: occupancy getter callback priv
+ */
+void devlink_resource_occ_get_register(struct devlink *devlink,
+                                      u64 resource_id,
+                                      devlink_resource_occ_get_t *occ_get,
+                                      void *occ_get_priv)
+{
+       struct devlink_resource *resource;
+
+       mutex_lock(&devlink->lock);
+       resource = devlink_resource_find(devlink, NULL, resource_id);
+       if (WARN_ON(!resource))
+               goto out;
+       WARN_ON(resource->occ_get);
+
+       resource->occ_get = occ_get;
+       resource->occ_get_priv = occ_get_priv;
+out:
+       mutex_unlock(&devlink->lock);
+}
+EXPORT_SYMBOL_GPL(devlink_resource_occ_get_register);
+
+/**
+ *     devlink_resource_occ_get_unregister - unregister occupancy getter
+ *
+ *     @devlink: devlink
+ *     @resource_id: resource id
+ */
+void devlink_resource_occ_get_unregister(struct devlink *devlink,
+                                        u64 resource_id)
+{
+       struct devlink_resource *resource;
+
+       mutex_lock(&devlink->lock);
+       resource = devlink_resource_find(devlink, NULL, resource_id);
+       if (WARN_ON(!resource))
+               goto out;
+       WARN_ON(!resource->occ_get);
+
+       resource->occ_get = NULL;
+       resource->occ_get_priv = NULL;
+out:
+       mutex_unlock(&devlink->lock);
+}
+EXPORT_SYMBOL_GPL(devlink_resource_occ_get_unregister);
+
 static int __init devlink_module_init(void)
 {
        return genl_register_family(&devlink_nl_family);