struct devlink *devlink);
 
 static int mlx4_devlink_reload_down(struct devlink *devlink, bool netns_change,
+                                   enum devlink_reload_action action,
                                    struct netlink_ext_ack *extack)
 {
        struct mlx4_priv *priv = devlink_priv(devlink);
        return 0;
 }
 
-static int mlx4_devlink_reload_up(struct devlink *devlink,
-                                 struct netlink_ext_ack *extack)
+static int mlx4_devlink_reload_up(struct devlink *devlink, enum devlink_reload_action action,
+                                 u32 *actions_performed, struct netlink_ext_ack *extack)
 {
        struct mlx4_priv *priv = devlink_priv(devlink);
        struct mlx4_dev *dev = &priv->dev;
        struct mlx4_dev_persistent *persist = dev->persist;
        int err;
 
+       *actions_performed = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT);
        err = mlx4_restart_one_up(persist->pdev, true, devlink);
        if (err)
                mlx4_err(persist->dev, "mlx4_restart_one_up failed, ret=%d\n",
 
 static const struct devlink_ops mlx4_devlink_ops = {
        .port_type_set  = mlx4_devlink_port_type_set,
+       .reload_actions = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT),
        .reload_down    = mlx4_devlink_reload_down,
        .reload_up      = mlx4_devlink_reload_up,
 };
 
 }
 
 static int mlx5_devlink_reload_down(struct devlink *devlink, bool netns_change,
+                                   enum devlink_reload_action action,
                                    struct netlink_ext_ack *extack)
 {
        struct mlx5_core_dev *dev = devlink_priv(devlink);
        return 0;
 }
 
-static int mlx5_devlink_reload_up(struct devlink *devlink,
-                                 struct netlink_ext_ack *extack)
+static int mlx5_devlink_reload_up(struct devlink *devlink, enum devlink_reload_action action,
+                                 u32 *actions_performed, struct netlink_ext_ack *extack)
 {
        struct mlx5_core_dev *dev = devlink_priv(devlink);
 
+       *actions_performed = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT);
        return mlx5_load_one(dev, false);
 }
 
 #endif
        .flash_update = mlx5_devlink_flash_update,
        .info_get = mlx5_devlink_info_get,
+       .reload_actions = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT),
        .reload_down = mlx5_devlink_reload_down,
        .reload_up = mlx5_devlink_reload_up,
 };
 
 
 static int
 mlxsw_devlink_core_bus_device_reload_down(struct devlink *devlink,
-                                         bool netns_change,
+                                         bool netns_change, enum devlink_reload_action action,
                                          struct netlink_ext_ack *extack)
 {
        struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
 }
 
 static int
-mlxsw_devlink_core_bus_device_reload_up(struct devlink *devlink,
-                                       struct netlink_ext_ack *extack)
+mlxsw_devlink_core_bus_device_reload_up(struct devlink *devlink, enum devlink_reload_action action,
+                                       u32 *actions_performed, struct netlink_ext_ack *extack)
 {
        struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
 
+       *actions_performed = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT) |
+                            BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE);
        return mlxsw_core_bus_device_register(mlxsw_core->bus_info,
                                              mlxsw_core->bus,
                                              mlxsw_core->bus_priv, true,
 }
 
 static const struct devlink_ops mlxsw_devlink_ops = {
+       .reload_actions         = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT) |
+                                 BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE),
        .reload_down            = mlxsw_devlink_core_bus_device_reload_down,
        .reload_up              = mlxsw_devlink_core_bus_device_reload_up,
        .port_type_set                  = mlxsw_devlink_port_type_set,
 
 static void nsim_dev_reload_destroy(struct nsim_dev *nsim_dev);
 
 static int nsim_dev_reload_down(struct devlink *devlink, bool netns_change,
-                               struct netlink_ext_ack *extack)
+                               enum devlink_reload_action action, struct netlink_ext_ack *extack)
 {
        struct nsim_dev *nsim_dev = devlink_priv(devlink);
 
        return 0;
 }
 
-static int nsim_dev_reload_up(struct devlink *devlink,
-                             struct netlink_ext_ack *extack)
+static int nsim_dev_reload_up(struct devlink *devlink, enum devlink_reload_action action,
+                             u32 *actions_performed, struct netlink_ext_ack *extack)
 {
        struct nsim_dev *nsim_dev = devlink_priv(devlink);
 
                return -EINVAL;
        }
 
+       *actions_performed = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT);
        return nsim_dev_reload_create(nsim_dev, extack);
 }
 
 static const struct devlink_ops nsim_dev_devlink_ops = {
        .supported_flash_update_params = DEVLINK_SUPPORT_FLASH_UPDATE_COMPONENT |
                                         DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK,
+       .reload_actions = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT),
        .reload_down = nsim_dev_reload_down,
        .reload_up = nsim_dev_reload_up,
        .info_get = nsim_dev_info_get,
 
         * implemementation.
         */
        u32 supported_flash_update_params;
+       unsigned long reload_actions;
        int (*reload_down)(struct devlink *devlink, bool netns_change,
-                          struct netlink_ext_ack *extack);
-       int (*reload_up)(struct devlink *devlink,
-                        struct netlink_ext_ack *extack);
+                          enum devlink_reload_action action, struct netlink_ext_ack *extack);
+       int (*reload_up)(struct devlink *devlink, enum devlink_reload_action action,
+                        u32 *actions_performed, struct netlink_ext_ack *extack);
        int (*port_type_set)(struct devlink_port *devlink_port,
                             enum devlink_port_type port_type);
        int (*port_split)(struct devlink *devlink, unsigned int port_index,
 
        DEVLINK_ATTR_TRAP_METADATA_TYPE_FA_COOKIE,
 };
 
+enum devlink_reload_action {
+       DEVLINK_RELOAD_ACTION_UNSPEC,
+       DEVLINK_RELOAD_ACTION_DRIVER_REINIT,    /* Driver entities re-instantiation */
+       DEVLINK_RELOAD_ACTION_FW_ACTIVATE,      /* FW activate */
+
+       /* Add new reload actions above */
+       __DEVLINK_RELOAD_ACTION_MAX,
+       DEVLINK_RELOAD_ACTION_MAX = __DEVLINK_RELOAD_ACTION_MAX - 1
+};
+
 enum devlink_attr {
        /* don't change the order or add anything between, this is ABI! */
        DEVLINK_ATTR_UNSPEC,
        DEVLINK_ATTR_FLASH_UPDATE_STATUS_TIMEOUT,       /* u64 */
        DEVLINK_ATTR_FLASH_UPDATE_OVERWRITE_MASK,       /* bitfield32 */
 
+       DEVLINK_ATTR_RELOAD_ACTION,             /* u8 */
+       DEVLINK_ATTR_RELOAD_ACTIONS_PERFORMED,  /* bitfield32 */
+
        /* add new attributes above here, update the policy in devlink.c */
 
        __DEVLINK_ATTR_MAX,
 
        return 0;
 }
 
+static bool
+devlink_reload_action_is_supported(struct devlink *devlink, enum devlink_reload_action action)
+{
+       return test_bit(action, &devlink->ops->reload_actions);
+}
+
 static int devlink_nl_fill(struct sk_buff *msg, struct devlink *devlink,
                           enum devlink_command cmd, u32 portid,
                           u32 seq, int flags)
 EXPORT_SYMBOL_GPL(devlink_is_reload_failed);
 
 static int devlink_reload(struct devlink *devlink, struct net *dest_net,
+                         enum devlink_reload_action action, u32 *actions_performed,
                          struct netlink_ext_ack *extack)
 {
        int err;
        if (!devlink->reload_enabled)
                return -EOPNOTSUPP;
 
-       err = devlink->ops->reload_down(devlink, !!dest_net, extack);
+       err = devlink->ops->reload_down(devlink, !!dest_net, action, extack);
        if (err)
                return err;
 
        if (dest_net && !net_eq(dest_net, devlink_net(devlink)))
                devlink_reload_netns_change(devlink, dest_net);
 
-       err = devlink->ops->reload_up(devlink, extack);
+       err = devlink->ops->reload_up(devlink, action, actions_performed, extack);
        devlink_reload_failed_set(devlink, !!err);
-       return err;
+       if (err)
+               return err;
+
+       WARN_ON(!(*actions_performed & BIT(action)));
+       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;
        struct net *dest_net = NULL;
+       u32 actions_performed;
        int err;
 
        if (!devlink_reload_supported(devlink->ops))
                        return PTR_ERR(dest_net);
        }
 
-       err = devlink_reload(devlink, dest_net, info->extack);
+       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;
+       }
+
+       err = devlink_reload(devlink, dest_net, action, &actions_performed, info->extack);
 
        if (dest_net)
                put_net(dest_net);
 
-       return err;
+       if (err)
+               return err;
+       /* For backward compatibility generate reply only if attributes used by user */
+       if (!info->attrs[DEVLINK_ATTR_RELOAD_ACTION])
+               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,
        [DEVLINK_ATTR_TRAP_POLICER_RATE] = { .type = NLA_U64 },
        [DEVLINK_ATTR_TRAP_POLICER_BURST] = { .type = NLA_U64 },
        [DEVLINK_ATTR_PORT_FUNCTION] = { .type = NLA_NESTED },
+       [DEVLINK_ATTR_RELOAD_ACTION] = NLA_POLICY_RANGE(NLA_U8, DEVLINK_RELOAD_ACTION_DRIVER_REINIT,
+                                                       DEVLINK_RELOAD_ACTION_MAX),
 };
 
 static const struct genl_small_ops devlink_nl_ops[] = {
        .n_mcgrps       = ARRAY_SIZE(devlink_nl_mcgrps),
 };
 
+static bool devlink_reload_actions_valid(const struct devlink_ops *ops)
+{
+       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;
+       return true;
+}
+
 /**
  *     devlink_alloc - Allocate new devlink instance resources
  *
        if (WARN_ON(!ops))
                return NULL;
 
+       if (!devlink_reload_actions_valid(ops))
+               return NULL;
+
        devlink = kzalloc(sizeof(*devlink) + priv_size, GFP_KERNEL);
        if (!devlink)
                return NULL;
 static void __net_exit devlink_pernet_pre_exit(struct net *net)
 {
        struct devlink *devlink;
+       u32 actions_performed;
        int err;
 
        /* In case network namespace is getting destroyed, reload
                if (net_eq(devlink_net(devlink), net)) {
                        if (WARN_ON(!devlink_reload_supported(devlink->ops)))
                                continue;
-                       err = devlink_reload(devlink, &init_net, NULL);
+                       err = devlink_reload(devlink, &init_net,
+                                            DEVLINK_RELOAD_ACTION_DRIVER_REINIT,
+                                            &actions_performed, NULL);
                        if (err && err != -EOPNOTSUPP)
                                pr_warn("Failed to reload devlink instance into init_net\n");
                }