devlink: Move devlink dev reload code to dev
authorMoshe Shemesh <moshe@nvidia.com>
Thu, 2 Feb 2023 14:47:01 +0000 (16:47 +0200)
committerJakub Kicinski <kuba@kernel.org>
Sat, 4 Feb 2023 03:25:25 +0000 (19:25 -0800)
Move devlink dev reload callback and related code from leftover.c to
file dev.c. No functional change in this patch.

Signed-off-by: Moshe Shemesh <moshe@nvidia.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/devlink/dev.c
net/devlink/devl_internal.h
net/devlink/leftover.c

index 6a26dc7..0d6c14b 100644 (file)
@@ -5,8 +5,131 @@
  */
 
 #include <net/genetlink.h>
+#include <net/sock.h>
 #include "devl_internal.h"
 
+struct devlink_reload_combination {
+       enum devlink_reload_action action;
+       enum devlink_reload_limit limit;
+};
+
+static const struct devlink_reload_combination devlink_reload_invalid_combinations[] = {
+       {
+               /* can't reinitialize driver with no down time */
+               .action = DEVLINK_RELOAD_ACTION_DRIVER_REINIT,
+               .limit = DEVLINK_RELOAD_LIMIT_NO_RESET,
+       },
+};
+
+static bool
+devlink_reload_combination_is_invalid(enum devlink_reload_action action,
+                                     enum devlink_reload_limit limit)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(devlink_reload_invalid_combinations); i++)
+               if (devlink_reload_invalid_combinations[i].action == action &&
+                   devlink_reload_invalid_combinations[i].limit == limit)
+                       return true;
+       return false;
+}
+
+static bool
+devlink_reload_action_is_supported(struct devlink *devlink, enum devlink_reload_action action)
+{
+       return test_bit(action, &devlink->ops->reload_actions);
+}
+
+static bool
+devlink_reload_limit_is_supported(struct devlink *devlink, enum devlink_reload_limit limit)
+{
+       return test_bit(limit, &devlink->ops->reload_limits);
+}
+
+static int devlink_reload_stat_put(struct sk_buff *msg,
+                                  enum devlink_reload_limit limit, u32 value)
+{
+       struct nlattr *reload_stats_entry;
+
+       reload_stats_entry = nla_nest_start(msg, DEVLINK_ATTR_RELOAD_STATS_ENTRY);
+       if (!reload_stats_entry)
+               return -EMSGSIZE;
+
+       if (nla_put_u8(msg, DEVLINK_ATTR_RELOAD_STATS_LIMIT, limit) ||
+           nla_put_u32(msg, DEVLINK_ATTR_RELOAD_STATS_VALUE, value))
+               goto nla_put_failure;
+       nla_nest_end(msg, reload_stats_entry);
+       return 0;
+
+nla_put_failure:
+       nla_nest_cancel(msg, reload_stats_entry);
+       return -EMSGSIZE;
+}
+
+static int
+devlink_reload_stats_put(struct sk_buff *msg, struct devlink *devlink, bool is_remote)
+{
+       struct nlattr *reload_stats_attr, *act_info, *act_stats;
+       int i, j, stat_idx;
+       u32 value;
+
+       if (!is_remote)
+               reload_stats_attr = nla_nest_start(msg, DEVLINK_ATTR_RELOAD_STATS);
+       else
+               reload_stats_attr = nla_nest_start(msg, DEVLINK_ATTR_REMOTE_RELOAD_STATS);
+
+       if (!reload_stats_attr)
+               return -EMSGSIZE;
+
+       for (i = 0; i <= DEVLINK_RELOAD_ACTION_MAX; i++) {
+               if ((!is_remote &&
+                    !devlink_reload_action_is_supported(devlink, i)) ||
+                   i == DEVLINK_RELOAD_ACTION_UNSPEC)
+                       continue;
+               act_info = nla_nest_start(msg, DEVLINK_ATTR_RELOAD_ACTION_INFO);
+               if (!act_info)
+                       goto nla_put_failure;
+
+               if (nla_put_u8(msg, DEVLINK_ATTR_RELOAD_ACTION, i))
+                       goto action_info_nest_cancel;
+               act_stats = nla_nest_start(msg, DEVLINK_ATTR_RELOAD_ACTION_STATS);
+               if (!act_stats)
+                       goto action_info_nest_cancel;
+
+               for (j = 0; j <= DEVLINK_RELOAD_LIMIT_MAX; j++) {
+                       /* Remote stats are shown even if not locally supported.
+                        * Stats of actions with unspecified limit are shown
+                        * though drivers don't need to register unspecified
+                        * limit.
+                        */
+                       if ((!is_remote && j != DEVLINK_RELOAD_LIMIT_UNSPEC &&
+                            !devlink_reload_limit_is_supported(devlink, j)) ||
+                           devlink_reload_combination_is_invalid(i, j))
+                               continue;
+
+                       stat_idx = j * __DEVLINK_RELOAD_ACTION_MAX + i;
+                       if (!is_remote)
+                               value = devlink->stats.reload_stats[stat_idx];
+                       else
+                               value = devlink->stats.remote_reload_stats[stat_idx];
+                       if (devlink_reload_stat_put(msg, j, value))
+                               goto action_stats_nest_cancel;
+               }
+               nla_nest_end(msg, act_stats);
+               nla_nest_end(msg, act_info);
+       }
+       nla_nest_end(msg, reload_stats_attr);
+       return 0;
+
+action_stats_nest_cancel:
+       nla_nest_cancel(msg, act_stats);
+action_info_nest_cancel:
+       nla_nest_cancel(msg, act_info);
+nla_put_failure:
+       nla_nest_cancel(msg, reload_stats_attr);
+       return -EMSGSIZE;
+}
+
 static int devlink_nl_fill(struct sk_buff *msg, struct devlink *devlink,
                           enum devlink_command cmd, u32 portid,
                           u32 seq, int flags)
@@ -97,3 +220,297 @@ devlink_nl_cmd_get_dump_one(struct sk_buff *msg, struct devlink *devlink,
 const struct devlink_cmd devl_cmd_get = {
        .dump_one               = devlink_nl_cmd_get_dump_one,
 };
+
+static void devlink_reload_failed_set(struct devlink *devlink,
+                                     bool reload_failed)
+{
+       if (devlink->reload_failed == reload_failed)
+               return;
+       devlink->reload_failed = reload_failed;
+       devlink_notify(devlink, DEVLINK_CMD_NEW);
+}
+
+bool devlink_is_reload_failed(const struct devlink *devlink)
+{
+       return devlink->reload_failed;
+}
+EXPORT_SYMBOL_GPL(devlink_is_reload_failed);
+
+static void
+__devlink_reload_stats_update(struct devlink *devlink, u32 *reload_stats,
+                             enum devlink_reload_limit limit, u32 actions_performed)
+{
+       unsigned long actions = actions_performed;
+       int stat_idx;
+       int action;
+
+       for_each_set_bit(action, &actions, __DEVLINK_RELOAD_ACTION_MAX) {
+               stat_idx = limit * __DEVLINK_RELOAD_ACTION_MAX + action;
+               reload_stats[stat_idx]++;
+       }
+       devlink_notify(devlink, DEVLINK_CMD_NEW);
+}
+
+static void
+devlink_reload_stats_update(struct devlink *devlink, enum devlink_reload_limit limit,
+                           u32 actions_performed)
+{
+       __devlink_reload_stats_update(devlink, devlink->stats.reload_stats, limit,
+                                     actions_performed);
+}
+
+/**
+ *     devlink_remote_reload_actions_performed - Update devlink on reload actions
+ *       performed which are not a direct result of devlink reload call.
+ *
+ *     This should be called by a driver after performing reload actions in case it was not
+ *     a result of devlink reload call. For example fw_activate was performed as a result
+ *     of devlink reload triggered fw_activate on another host.
+ *     The motivation for this function is to keep data on reload actions performed on this
+ *     function whether it was done due to direct devlink reload call or not.
+ *
+ *     @devlink: devlink
+ *     @limit: reload limit
+ *     @actions_performed: bitmask of actions performed
+ */
+void devlink_remote_reload_actions_performed(struct devlink *devlink,
+                                            enum devlink_reload_limit limit,
+                                            u32 actions_performed)
+{
+       if (WARN_ON(!actions_performed ||
+                   actions_performed & BIT(DEVLINK_RELOAD_ACTION_UNSPEC) ||
+                   actions_performed >= BIT(__DEVLINK_RELOAD_ACTION_MAX) ||
+                   limit > DEVLINK_RELOAD_LIMIT_MAX))
+               return;
+
+       __devlink_reload_stats_update(devlink, devlink->stats.remote_reload_stats, limit,
+                                     actions_performed);
+}
+EXPORT_SYMBOL_GPL(devlink_remote_reload_actions_performed);
+
+static struct net *devlink_netns_get(struct sk_buff *skb,
+                                    struct genl_info *info)
+{
+       struct nlattr *netns_pid_attr = info->attrs[DEVLINK_ATTR_NETNS_PID];
+       struct nlattr *netns_fd_attr = info->attrs[DEVLINK_ATTR_NETNS_FD];
+       struct nlattr *netns_id_attr = info->attrs[DEVLINK_ATTR_NETNS_ID];
+       struct net *net;
+
+       if (!!netns_pid_attr + !!netns_fd_attr + !!netns_id_attr > 1) {
+               NL_SET_ERR_MSG_MOD(info->extack, "multiple netns identifying attributes specified");
+               return ERR_PTR(-EINVAL);
+       }
+
+       if (netns_pid_attr) {
+               net = get_net_ns_by_pid(nla_get_u32(netns_pid_attr));
+       } else if (netns_fd_attr) {
+               net = get_net_ns_by_fd(nla_get_u32(netns_fd_attr));
+       } else if (netns_id_attr) {
+               net = get_net_ns_by_id(sock_net(skb->sk),
+                                      nla_get_u32(netns_id_attr));
+               if (!net)
+                       net = ERR_PTR(-EINVAL);
+       } else {
+               WARN_ON(1);
+               net = ERR_PTR(-EINVAL);
+       }
+       if (IS_ERR(net)) {
+               NL_SET_ERR_MSG_MOD(info->extack, "Unknown network namespace");
+               return ERR_PTR(-EINVAL);
+       }
+       if (!netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN)) {
+               put_net(net);
+               return ERR_PTR(-EPERM);
+       }
+       return net;
+}
+
+static void devlink_reload_netns_change(struct devlink *devlink,
+                                       struct net *curr_net,
+                                       struct net *dest_net)
+{
+       /* Userspace needs to be notified about devlink objects
+        * removed from original and entering new network namespace.
+        * The rest of the devlink objects are re-created during
+        * reload process so the notifications are generated separatelly.
+        */
+       devlink_notify_unregister(devlink);
+       move_netdevice_notifier_net(curr_net, dest_net,
+                                   &devlink->netdevice_nb);
+       write_pnet(&devlink->_net, dest_net);
+       devlink_notify_register(devlink);
+}
+
+int devlink_reload(struct devlink *devlink, struct net *dest_net,
+                  enum devlink_reload_action action,
+                  enum devlink_reload_limit limit,
+                  u32 *actions_performed, struct netlink_ext_ack *extack)
+{
+       u32 remote_reload_stats[DEVLINK_RELOAD_STATS_ARRAY_SIZE];
+       struct net *curr_net;
+       int err;
+
+       memcpy(remote_reload_stats, devlink->stats.remote_reload_stats,
+              sizeof(remote_reload_stats));
+
+       err = devlink->ops->reload_down(devlink, !!dest_net, action, limit, extack);
+       if (err)
+               return err;
+
+       curr_net = devlink_net(devlink);
+       if (dest_net && !net_eq(dest_net, curr_net))
+               devlink_reload_netns_change(devlink, curr_net, dest_net);
+
+       err = devlink->ops->reload_up(devlink, action, limit, actions_performed, extack);
+       devlink_reload_failed_set(devlink, !!err);
+       if (err)
+               return err;
+
+       WARN_ON(!(*actions_performed & BIT(action)));
+       /* Catch driver on updating the remote action within devlink reload */
+       WARN_ON(memcmp(remote_reload_stats, devlink->stats.remote_reload_stats,
+                      sizeof(remote_reload_stats)));
+       devlink_reload_stats_update(devlink, limit, *actions_performed);
+       return 0;
+}
+
+static int
+devlink_nl_reload_actions_performed_snd(struct devlink *devlink, u32 actions_performed,
+                                       enum devlink_command cmd, struct genl_info *info)
+{
+       struct sk_buff *msg;
+       void *hdr;
+
+       msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+       if (!msg)
+               return -ENOMEM;
+
+       hdr = genlmsg_put(msg, info->snd_portid, info->snd_seq, &devlink_nl_family, 0, cmd);
+       if (!hdr)
+               goto free_msg;
+
+       if (devlink_nl_put_handle(msg, devlink))
+               goto nla_put_failure;
+
+       if (nla_put_bitfield32(msg, DEVLINK_ATTR_RELOAD_ACTIONS_PERFORMED, actions_performed,
+                              actions_performed))
+               goto nla_put_failure;
+       genlmsg_end(msg, hdr);
+
+       return genlmsg_reply(msg, info);
+
+nla_put_failure:
+       genlmsg_cancel(msg, hdr);
+free_msg:
+       nlmsg_free(msg);
+       return -EMSGSIZE;
+}
+
+int devlink_nl_cmd_reload(struct sk_buff *skb, struct genl_info *info)
+{
+       struct devlink *devlink = info->user_ptr[0];
+       enum devlink_reload_action action;
+       enum devlink_reload_limit limit;
+       struct net *dest_net = NULL;
+       u32 actions_performed;
+       int err;
+
+       err = devlink_resources_validate(devlink, NULL, info);
+       if (err) {
+               NL_SET_ERR_MSG_MOD(info->extack, "resources size validation failed");
+               return err;
+       }
+
+       if (info->attrs[DEVLINK_ATTR_RELOAD_ACTION])
+               action = nla_get_u8(info->attrs[DEVLINK_ATTR_RELOAD_ACTION]);
+       else
+               action = DEVLINK_RELOAD_ACTION_DRIVER_REINIT;
+
+       if (!devlink_reload_action_is_supported(devlink, action)) {
+               NL_SET_ERR_MSG_MOD(info->extack,
+                                  "Requested reload action is not supported by the driver");
+               return -EOPNOTSUPP;
+       }
+
+       limit = DEVLINK_RELOAD_LIMIT_UNSPEC;
+       if (info->attrs[DEVLINK_ATTR_RELOAD_LIMITS]) {
+               struct nla_bitfield32 limits;
+               u32 limits_selected;
+
+               limits = nla_get_bitfield32(info->attrs[DEVLINK_ATTR_RELOAD_LIMITS]);
+               limits_selected = limits.value & limits.selector;
+               if (!limits_selected) {
+                       NL_SET_ERR_MSG_MOD(info->extack, "Invalid limit selected");
+                       return -EINVAL;
+               }
+               for (limit = 0 ; limit <= DEVLINK_RELOAD_LIMIT_MAX ; limit++)
+                       if (limits_selected & BIT(limit))
+                               break;
+               /* UAPI enables multiselection, but currently it is not used */
+               if (limits_selected != BIT(limit)) {
+                       NL_SET_ERR_MSG_MOD(info->extack,
+                                          "Multiselection of limit is not supported");
+                       return -EOPNOTSUPP;
+               }
+               if (!devlink_reload_limit_is_supported(devlink, limit)) {
+                       NL_SET_ERR_MSG_MOD(info->extack,
+                                          "Requested limit is not supported by the driver");
+                       return -EOPNOTSUPP;
+               }
+               if (devlink_reload_combination_is_invalid(action, limit)) {
+                       NL_SET_ERR_MSG_MOD(info->extack,
+                                          "Requested limit is invalid for this action");
+                       return -EINVAL;
+               }
+       }
+       if (info->attrs[DEVLINK_ATTR_NETNS_PID] ||
+           info->attrs[DEVLINK_ATTR_NETNS_FD] ||
+           info->attrs[DEVLINK_ATTR_NETNS_ID]) {
+               dest_net = devlink_netns_get(skb, info);
+               if (IS_ERR(dest_net))
+                       return PTR_ERR(dest_net);
+       }
+
+       err = devlink_reload(devlink, dest_net, action, limit, &actions_performed, info->extack);
+
+       if (dest_net)
+               put_net(dest_net);
+
+       if (err)
+               return err;
+       /* For backward compatibility generate reply only if attributes used by user */
+       if (!info->attrs[DEVLINK_ATTR_RELOAD_ACTION] && !info->attrs[DEVLINK_ATTR_RELOAD_LIMITS])
+               return 0;
+
+       return devlink_nl_reload_actions_performed_snd(devlink, actions_performed,
+                                                      DEVLINK_CMD_RELOAD, info);
+}
+
+bool devlink_reload_actions_valid(const struct devlink_ops *ops)
+{
+       const struct devlink_reload_combination *comb;
+       int i;
+
+       if (!devlink_reload_supported(ops)) {
+               if (WARN_ON(ops->reload_actions))
+                       return false;
+               return true;
+       }
+
+       if (WARN_ON(!ops->reload_actions ||
+                   ops->reload_actions & BIT(DEVLINK_RELOAD_ACTION_UNSPEC) ||
+                   ops->reload_actions >= BIT(__DEVLINK_RELOAD_ACTION_MAX)))
+               return false;
+
+       if (WARN_ON(ops->reload_limits & BIT(DEVLINK_RELOAD_LIMIT_UNSPEC) ||
+                   ops->reload_limits >= BIT(__DEVLINK_RELOAD_LIMIT_MAX)))
+               return false;
+
+       for (i = 0; i < ARRAY_SIZE(devlink_reload_invalid_combinations); i++)  {
+               comb = &devlink_reload_invalid_combinations[i];
+               if (ops->reload_actions == BIT(comb->action) &&
+                   ops->reload_limits == BIT(comb->limit))
+                       return false;
+       }
+       return true;
+}
index 60dce85..cb4a89a 100644 (file)
@@ -179,8 +179,6 @@ devlink_port_get_from_info(struct devlink *devlink, struct genl_info *info);
 
 /* Reload */
 bool devlink_reload_actions_valid(const struct devlink_ops *ops);
-int devlink_reload_stats_put(struct sk_buff *msg, struct devlink *devlink,
-                            bool is_remote);
 int devlink_reload(struct devlink *devlink, struct net *dest_net,
                   enum devlink_reload_action action,
                   enum devlink_reload_limit limit,
@@ -191,6 +189,12 @@ static inline bool devlink_reload_supported(const struct devlink_ops *ops)
        return ops->reload_down && ops->reload_up;
 }
 
+/* Resources */
+struct devlink_resource;
+int devlink_resources_validate(struct devlink *devlink,
+                              struct devlink_resource *resource,
+                              struct genl_info *info);
+
 /* Line cards */
 struct devlink_linecard;
 
@@ -205,3 +209,4 @@ devlink_rate_node_get_from_info(struct devlink *devlink,
                                struct genl_info *info);
 /* Devlink nl cmds */
 int devlink_nl_cmd_get_doit(struct sk_buff *skb, struct genl_info *info);
+int devlink_nl_cmd_reload(struct sk_buff *skb, struct genl_info *info);
index 54c8ea8..703a03d 100644 (file)
@@ -632,127 +632,6 @@ size_t devlink_nl_port_handle_size(struct devlink_port *devlink_port)
             + nla_total_size(4); /* DEVLINK_ATTR_PORT_INDEX */
 }
 
-struct devlink_reload_combination {
-       enum devlink_reload_action action;
-       enum devlink_reload_limit limit;
-};
-
-static const struct devlink_reload_combination devlink_reload_invalid_combinations[] = {
-       {
-               /* can't reinitialize driver with no down time */
-               .action = DEVLINK_RELOAD_ACTION_DRIVER_REINIT,
-               .limit = DEVLINK_RELOAD_LIMIT_NO_RESET,
-       },
-};
-
-static bool
-devlink_reload_combination_is_invalid(enum devlink_reload_action action,
-                                     enum devlink_reload_limit limit)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(devlink_reload_invalid_combinations); i++)
-               if (devlink_reload_invalid_combinations[i].action == action &&
-                   devlink_reload_invalid_combinations[i].limit == limit)
-                       return true;
-       return false;
-}
-
-static bool
-devlink_reload_action_is_supported(struct devlink *devlink, enum devlink_reload_action action)
-{
-       return test_bit(action, &devlink->ops->reload_actions);
-}
-
-static bool
-devlink_reload_limit_is_supported(struct devlink *devlink, enum devlink_reload_limit limit)
-{
-       return test_bit(limit, &devlink->ops->reload_limits);
-}
-
-static int devlink_reload_stat_put(struct sk_buff *msg,
-                                  enum devlink_reload_limit limit, u32 value)
-{
-       struct nlattr *reload_stats_entry;
-
-       reload_stats_entry = nla_nest_start(msg, DEVLINK_ATTR_RELOAD_STATS_ENTRY);
-       if (!reload_stats_entry)
-               return -EMSGSIZE;
-
-       if (nla_put_u8(msg, DEVLINK_ATTR_RELOAD_STATS_LIMIT, limit) ||
-           nla_put_u32(msg, DEVLINK_ATTR_RELOAD_STATS_VALUE, value))
-               goto nla_put_failure;
-       nla_nest_end(msg, reload_stats_entry);
-       return 0;
-
-nla_put_failure:
-       nla_nest_cancel(msg, reload_stats_entry);
-       return -EMSGSIZE;
-}
-
-int devlink_reload_stats_put(struct sk_buff *msg, struct devlink *devlink, bool is_remote)
-{
-       struct nlattr *reload_stats_attr, *act_info, *act_stats;
-       int i, j, stat_idx;
-       u32 value;
-
-       if (!is_remote)
-               reload_stats_attr = nla_nest_start(msg, DEVLINK_ATTR_RELOAD_STATS);
-       else
-               reload_stats_attr = nla_nest_start(msg, DEVLINK_ATTR_REMOTE_RELOAD_STATS);
-
-       if (!reload_stats_attr)
-               return -EMSGSIZE;
-
-       for (i = 0; i <= DEVLINK_RELOAD_ACTION_MAX; i++) {
-               if ((!is_remote &&
-                    !devlink_reload_action_is_supported(devlink, i)) ||
-                   i == DEVLINK_RELOAD_ACTION_UNSPEC)
-                       continue;
-               act_info = nla_nest_start(msg, DEVLINK_ATTR_RELOAD_ACTION_INFO);
-               if (!act_info)
-                       goto nla_put_failure;
-
-               if (nla_put_u8(msg, DEVLINK_ATTR_RELOAD_ACTION, i))
-                       goto action_info_nest_cancel;
-               act_stats = nla_nest_start(msg, DEVLINK_ATTR_RELOAD_ACTION_STATS);
-               if (!act_stats)
-                       goto action_info_nest_cancel;
-
-               for (j = 0; j <= DEVLINK_RELOAD_LIMIT_MAX; j++) {
-                       /* Remote stats are shown even if not locally supported.
-                        * Stats of actions with unspecified limit are shown
-                        * though drivers don't need to register unspecified
-                        * limit.
-                        */
-                       if ((!is_remote && j != DEVLINK_RELOAD_LIMIT_UNSPEC &&
-                            !devlink_reload_limit_is_supported(devlink, j)) ||
-                           devlink_reload_combination_is_invalid(i, j))
-                               continue;
-
-                       stat_idx = j * __DEVLINK_RELOAD_ACTION_MAX + i;
-                       if (!is_remote)
-                               value = devlink->stats.reload_stats[stat_idx];
-                       else
-                               value = devlink->stats.remote_reload_stats[stat_idx];
-                       if (devlink_reload_stat_put(msg, j, value))
-                               goto action_stats_nest_cancel;
-               }
-               nla_nest_end(msg, act_stats);
-               nla_nest_end(msg, act_info);
-       }
-       nla_nest_end(msg, reload_stats_attr);
-       return 0;
-
-action_stats_nest_cancel:
-       nla_nest_cancel(msg, act_stats);
-action_info_nest_cancel:
-       nla_nest_cancel(msg, act_info);
-nla_put_failure:
-       nla_nest_cancel(msg, reload_stats_attr);
-       return -EMSGSIZE;
-}
-
 static int devlink_nl_port_attrs_put(struct sk_buff *msg,
                                     struct devlink_port *devlink_port)
 {
@@ -4070,10 +3949,9 @@ static int devlink_nl_cmd_resource_dump(struct sk_buff *skb,
        return devlink_resource_fill(info, DEVLINK_CMD_RESOURCE_DUMP, 0);
 }
 
-static int
-devlink_resources_validate(struct devlink *devlink,
-                          struct devlink_resource *resource,
-                          struct genl_info *info)
+int devlink_resources_validate(struct devlink *devlink,
+                              struct devlink_resource *resource,
+                              struct genl_info *info)
 {
        struct list_head *resource_list;
        int err = 0;
@@ -4093,271 +3971,6 @@ devlink_resources_validate(struct devlink *devlink,
        return err;
 }
 
-static struct net *devlink_netns_get(struct sk_buff *skb,
-                                    struct genl_info *info)
-{
-       struct nlattr *netns_pid_attr = info->attrs[DEVLINK_ATTR_NETNS_PID];
-       struct nlattr *netns_fd_attr = info->attrs[DEVLINK_ATTR_NETNS_FD];
-       struct nlattr *netns_id_attr = info->attrs[DEVLINK_ATTR_NETNS_ID];
-       struct net *net;
-
-       if (!!netns_pid_attr + !!netns_fd_attr + !!netns_id_attr > 1) {
-               NL_SET_ERR_MSG_MOD(info->extack, "multiple netns identifying attributes specified");
-               return ERR_PTR(-EINVAL);
-       }
-
-       if (netns_pid_attr) {
-               net = get_net_ns_by_pid(nla_get_u32(netns_pid_attr));
-       } else if (netns_fd_attr) {
-               net = get_net_ns_by_fd(nla_get_u32(netns_fd_attr));
-       } else if (netns_id_attr) {
-               net = get_net_ns_by_id(sock_net(skb->sk),
-                                      nla_get_u32(netns_id_attr));
-               if (!net)
-                       net = ERR_PTR(-EINVAL);
-       } else {
-               WARN_ON(1);
-               net = ERR_PTR(-EINVAL);
-       }
-       if (IS_ERR(net)) {
-               NL_SET_ERR_MSG_MOD(info->extack, "Unknown network namespace");
-               return ERR_PTR(-EINVAL);
-       }
-       if (!netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN)) {
-               put_net(net);
-               return ERR_PTR(-EPERM);
-       }
-       return net;
-}
-
-static void devlink_reload_netns_change(struct devlink *devlink,
-                                       struct net *curr_net,
-                                       struct net *dest_net)
-{
-       /* Userspace needs to be notified about devlink objects
-        * removed from original and entering new network namespace.
-        * The rest of the devlink objects are re-created during
-        * reload process so the notifications are generated separatelly.
-        */
-       devlink_notify_unregister(devlink);
-       move_netdevice_notifier_net(curr_net, dest_net,
-                                   &devlink->netdevice_nb);
-       write_pnet(&devlink->_net, dest_net);
-       devlink_notify_register(devlink);
-}
-
-static void devlink_reload_failed_set(struct devlink *devlink,
-                                     bool reload_failed)
-{
-       if (devlink->reload_failed == reload_failed)
-               return;
-       devlink->reload_failed = reload_failed;
-       devlink_notify(devlink, DEVLINK_CMD_NEW);
-}
-
-bool devlink_is_reload_failed(const struct devlink *devlink)
-{
-       return devlink->reload_failed;
-}
-EXPORT_SYMBOL_GPL(devlink_is_reload_failed);
-
-static void
-__devlink_reload_stats_update(struct devlink *devlink, u32 *reload_stats,
-                             enum devlink_reload_limit limit, u32 actions_performed)
-{
-       unsigned long actions = actions_performed;
-       int stat_idx;
-       int action;
-
-       for_each_set_bit(action, &actions, __DEVLINK_RELOAD_ACTION_MAX) {
-               stat_idx = limit * __DEVLINK_RELOAD_ACTION_MAX + action;
-               reload_stats[stat_idx]++;
-       }
-       devlink_notify(devlink, DEVLINK_CMD_NEW);
-}
-
-static void
-devlink_reload_stats_update(struct devlink *devlink, enum devlink_reload_limit limit,
-                           u32 actions_performed)
-{
-       __devlink_reload_stats_update(devlink, devlink->stats.reload_stats, limit,
-                                     actions_performed);
-}
-
-/**
- *     devlink_remote_reload_actions_performed - Update devlink on reload actions
- *       performed which are not a direct result of devlink reload call.
- *
- *     This should be called by a driver after performing reload actions in case it was not
- *     a result of devlink reload call. For example fw_activate was performed as a result
- *     of devlink reload triggered fw_activate on another host.
- *     The motivation for this function is to keep data on reload actions performed on this
- *     function whether it was done due to direct devlink reload call or not.
- *
- *     @devlink: devlink
- *     @limit: reload limit
- *     @actions_performed: bitmask of actions performed
- */
-void devlink_remote_reload_actions_performed(struct devlink *devlink,
-                                            enum devlink_reload_limit limit,
-                                            u32 actions_performed)
-{
-       if (WARN_ON(!actions_performed ||
-                   actions_performed & BIT(DEVLINK_RELOAD_ACTION_UNSPEC) ||
-                   actions_performed >= BIT(__DEVLINK_RELOAD_ACTION_MAX) ||
-                   limit > DEVLINK_RELOAD_LIMIT_MAX))
-               return;
-
-       __devlink_reload_stats_update(devlink, devlink->stats.remote_reload_stats, limit,
-                                     actions_performed);
-}
-EXPORT_SYMBOL_GPL(devlink_remote_reload_actions_performed);
-
-int devlink_reload(struct devlink *devlink, struct net *dest_net,
-                  enum devlink_reload_action action,
-                  enum devlink_reload_limit limit,
-                  u32 *actions_performed, struct netlink_ext_ack *extack)
-{
-       u32 remote_reload_stats[DEVLINK_RELOAD_STATS_ARRAY_SIZE];
-       struct net *curr_net;
-       int err;
-
-       memcpy(remote_reload_stats, devlink->stats.remote_reload_stats,
-              sizeof(remote_reload_stats));
-
-       err = devlink->ops->reload_down(devlink, !!dest_net, action, limit, extack);
-       if (err)
-               return err;
-
-       curr_net = devlink_net(devlink);
-       if (dest_net && !net_eq(dest_net, curr_net))
-               devlink_reload_netns_change(devlink, curr_net, dest_net);
-
-       err = devlink->ops->reload_up(devlink, action, limit, actions_performed, extack);
-       devlink_reload_failed_set(devlink, !!err);
-       if (err)
-               return err;
-
-       WARN_ON(!(*actions_performed & BIT(action)));
-       /* Catch driver on updating the remote action within devlink reload */
-       WARN_ON(memcmp(remote_reload_stats, devlink->stats.remote_reload_stats,
-                      sizeof(remote_reload_stats)));
-       devlink_reload_stats_update(devlink, limit, *actions_performed);
-       return 0;
-}
-
-static int
-devlink_nl_reload_actions_performed_snd(struct devlink *devlink, u32 actions_performed,
-                                       enum devlink_command cmd, struct genl_info *info)
-{
-       struct sk_buff *msg;
-       void *hdr;
-
-       msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
-       if (!msg)
-               return -ENOMEM;
-
-       hdr = genlmsg_put(msg, info->snd_portid, info->snd_seq, &devlink_nl_family, 0, cmd);
-       if (!hdr)
-               goto free_msg;
-
-       if (devlink_nl_put_handle(msg, devlink))
-               goto nla_put_failure;
-
-       if (nla_put_bitfield32(msg, DEVLINK_ATTR_RELOAD_ACTIONS_PERFORMED, actions_performed,
-                              actions_performed))
-               goto nla_put_failure;
-       genlmsg_end(msg, hdr);
-
-       return genlmsg_reply(msg, info);
-
-nla_put_failure:
-       genlmsg_cancel(msg, hdr);
-free_msg:
-       nlmsg_free(msg);
-       return -EMSGSIZE;
-}
-
-static int devlink_nl_cmd_reload(struct sk_buff *skb, struct genl_info *info)
-{
-       struct devlink *devlink = info->user_ptr[0];
-       enum devlink_reload_action action;
-       enum devlink_reload_limit limit;
-       struct net *dest_net = NULL;
-       u32 actions_performed;
-       int err;
-
-       err = devlink_resources_validate(devlink, NULL, info);
-       if (err) {
-               NL_SET_ERR_MSG_MOD(info->extack, "resources size validation failed");
-               return err;
-       }
-
-       if (info->attrs[DEVLINK_ATTR_RELOAD_ACTION])
-               action = nla_get_u8(info->attrs[DEVLINK_ATTR_RELOAD_ACTION]);
-       else
-               action = DEVLINK_RELOAD_ACTION_DRIVER_REINIT;
-
-       if (!devlink_reload_action_is_supported(devlink, action)) {
-               NL_SET_ERR_MSG_MOD(info->extack,
-                                  "Requested reload action is not supported by the driver");
-               return -EOPNOTSUPP;
-       }
-
-       limit = DEVLINK_RELOAD_LIMIT_UNSPEC;
-       if (info->attrs[DEVLINK_ATTR_RELOAD_LIMITS]) {
-               struct nla_bitfield32 limits;
-               u32 limits_selected;
-
-               limits = nla_get_bitfield32(info->attrs[DEVLINK_ATTR_RELOAD_LIMITS]);
-               limits_selected = limits.value & limits.selector;
-               if (!limits_selected) {
-                       NL_SET_ERR_MSG_MOD(info->extack, "Invalid limit selected");
-                       return -EINVAL;
-               }
-               for (limit = 0 ; limit <= DEVLINK_RELOAD_LIMIT_MAX ; limit++)
-                       if (limits_selected & BIT(limit))
-                               break;
-               /* UAPI enables multiselection, but currently it is not used */
-               if (limits_selected != BIT(limit)) {
-                       NL_SET_ERR_MSG_MOD(info->extack,
-                                          "Multiselection of limit is not supported");
-                       return -EOPNOTSUPP;
-               }
-               if (!devlink_reload_limit_is_supported(devlink, limit)) {
-                       NL_SET_ERR_MSG_MOD(info->extack,
-                                          "Requested limit is not supported by the driver");
-                       return -EOPNOTSUPP;
-               }
-               if (devlink_reload_combination_is_invalid(action, limit)) {
-                       NL_SET_ERR_MSG_MOD(info->extack,
-                                          "Requested limit is invalid for this action");
-                       return -EINVAL;
-               }
-       }
-       if (info->attrs[DEVLINK_ATTR_NETNS_PID] ||
-           info->attrs[DEVLINK_ATTR_NETNS_FD] ||
-           info->attrs[DEVLINK_ATTR_NETNS_ID]) {
-               dest_net = devlink_netns_get(skb, info);
-               if (IS_ERR(dest_net))
-                       return PTR_ERR(dest_net);
-       }
-
-       err = devlink_reload(devlink, dest_net, action, limit, &actions_performed, info->extack);
-
-       if (dest_net)
-               put_net(dest_net);
-
-       if (err)
-               return err;
-       /* For backward compatibility generate reply only if attributes used by user */
-       if (!info->attrs[DEVLINK_ATTR_RELOAD_ACTION] && !info->attrs[DEVLINK_ATTR_RELOAD_LIMITS])
-               return 0;
-
-       return devlink_nl_reload_actions_performed_snd(devlink, actions_performed,
-                                                      DEVLINK_CMD_RELOAD, info);
-}
-
 static int devlink_nl_flash_update_fill(struct sk_buff *msg,
                                        struct devlink *devlink,
                                        enum devlink_command cmd,
@@ -9157,35 +8770,6 @@ const struct genl_small_ops devlink_nl_ops[56] = {
        /* -- No new ops here! Use split ops going forward! -- */
 };
 
-bool devlink_reload_actions_valid(const struct devlink_ops *ops)
-{
-       const struct devlink_reload_combination *comb;
-       int i;
-
-       if (!devlink_reload_supported(ops)) {
-               if (WARN_ON(ops->reload_actions))
-                       return false;
-               return true;
-       }
-
-       if (WARN_ON(!ops->reload_actions ||
-                   ops->reload_actions & BIT(DEVLINK_RELOAD_ACTION_UNSPEC) ||
-                   ops->reload_actions >= BIT(__DEVLINK_RELOAD_ACTION_MAX)))
-               return false;
-
-       if (WARN_ON(ops->reload_limits & BIT(DEVLINK_RELOAD_LIMIT_UNSPEC) ||
-                   ops->reload_limits >= BIT(__DEVLINK_RELOAD_LIMIT_MAX)))
-               return false;
-
-       for (i = 0; i < ARRAY_SIZE(devlink_reload_invalid_combinations); i++)  {
-               comb = &devlink_reload_invalid_combinations[i];
-               if (ops->reload_actions == BIT(comb->action) &&
-                   ops->reload_limits == BIT(comb->limit))
-                       return false;
-       }
-       return true;
-}
-
 static void
 devlink_trap_policer_notify(struct devlink *devlink,
                            const struct devlink_trap_policer_item *policer_item,