Commit 0e258cec authored by Jakub Kicinski's avatar Jakub Kicinski

Merge branch 'devlink-reload-simplification'

Leon Romanovsky says:

====================
devlink reload simplification

Simplify devlink reload APIs.
====================

Link: https://lore.kernel.org/r/cover.1634044267.git.leonro@nvidia.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 177c9235 82465bec
......@@ -119,8 +119,8 @@ int hclge_devlink_init(struct hclge_dev *hdev)
priv->hdev = hdev;
hdev->devlink = devlink;
devlink_set_features(devlink, DEVLINK_F_RELOAD);
devlink_register(devlink);
devlink_reload_enable(devlink);
return 0;
}
......@@ -128,8 +128,6 @@ void hclge_devlink_uninit(struct hclge_dev *hdev)
{
struct devlink *devlink = hdev->devlink;
devlink_reload_disable(devlink);
devlink_unregister(devlink);
devlink_free(devlink);
......
......@@ -121,8 +121,8 @@ int hclgevf_devlink_init(struct hclgevf_dev *hdev)
priv->hdev = hdev;
hdev->devlink = devlink;
devlink_set_features(devlink, DEVLINK_F_RELOAD);
devlink_register(devlink);
devlink_reload_enable(devlink);
return 0;
}
......@@ -130,8 +130,6 @@ void hclgevf_devlink_uninit(struct hclgevf_dev *hdev)
{
struct devlink *devlink = hdev->devlink;
devlink_reload_disable(devlink);
devlink_unregister(devlink);
devlink_free(devlink);
......
......@@ -4025,8 +4025,8 @@ static int mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
goto err_params_unregister;
pci_save_state(pdev);
devlink_set_features(devlink, DEVLINK_F_RELOAD);
devlink_register(devlink);
devlink_reload_enable(devlink);
return 0;
err_params_unregister:
......@@ -4135,7 +4135,6 @@ static void mlx4_remove_one(struct pci_dev *pdev)
struct devlink *devlink = priv_to_devlink(priv);
int active_vfs = 0;
devlink_reload_disable(devlink);
devlink_unregister(devlink);
if (mlx4_is_slave(dev))
......
......@@ -796,6 +796,7 @@ static void mlx5_devlink_traps_unregister(struct devlink *devlink)
int mlx5_devlink_register(struct devlink *devlink)
{
struct mlx5_core_dev *dev = devlink_priv(devlink);
int err;
err = devlink_params_register(devlink, mlx5_devlink_params,
......@@ -813,6 +814,9 @@ int mlx5_devlink_register(struct devlink *devlink)
if (err)
goto traps_reg_err;
if (!mlx5_core_is_mp_slave(dev))
devlink_set_features(devlink, DEVLINK_F_RELOAD);
return 0;
traps_reg_err:
......
......@@ -1538,8 +1538,6 @@ static int probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
pci_save_state(pdev);
devlink_register(devlink);
if (!mlx5_core_is_mp_slave(dev))
devlink_reload_enable(devlink);
return 0;
err_init_one:
......@@ -1559,7 +1557,6 @@ static void remove_one(struct pci_dev *pdev)
struct mlx5_core_dev *dev = pci_get_drvdata(pdev);
struct devlink *devlink = priv_to_devlink(dev);
devlink_reload_disable(devlink);
devlink_unregister(devlink);
mlx5_crdump_disable(dev);
mlx5_drain_health_wq(dev);
......
......@@ -47,7 +47,6 @@ static int mlx5_sf_dev_probe(struct auxiliary_device *adev, const struct auxilia
goto init_one_err;
}
devlink_register(devlink);
devlink_reload_enable(devlink);
return 0;
init_one_err:
......@@ -62,10 +61,8 @@ static int mlx5_sf_dev_probe(struct auxiliary_device *adev, const struct auxilia
static void mlx5_sf_dev_remove(struct auxiliary_device *adev)
{
struct mlx5_sf_dev *sf_dev = container_of(adev, struct mlx5_sf_dev, adev);
struct devlink *devlink;
struct devlink *devlink = priv_to_devlink(sf_dev->mdev);
devlink = priv_to_devlink(sf_dev->mdev);
devlink_reload_disable(devlink);
devlink_unregister(devlink);
mlx5_uninit_one(sf_dev->mdev);
iounmap(sf_dev->mdev->iseg);
......
......@@ -19,7 +19,7 @@ struct mlxfw_dev {
static inline
struct device *mlxfw_dev_dev(struct mlxfw_dev *mlxfw_dev)
{
return mlxfw_dev->devlink->dev;
return devlink_to_dev(mlxfw_dev->devlink);
}
#define MLXFW_PRFX "mlxfw: "
......
......@@ -2008,10 +2008,9 @@ __mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info,
}
if (!reload) {
devlink_set_features(devlink, DEVLINK_F_RELOAD);
devlink_register(devlink);
devlink_reload_enable(devlink);
}
return 0;
err_driver_init:
......@@ -2075,10 +2074,9 @@ void mlxsw_core_bus_device_unregister(struct mlxsw_core *mlxsw_core,
{
struct devlink *devlink = priv_to_devlink(mlxsw_core);
if (!reload) {
devlink_reload_disable(devlink);
if (!reload)
devlink_unregister(devlink);
}
if (devlink_is_reload_failed(devlink)) {
if (!reload)
/* Only the parts that were not de-initialized in the
......
......@@ -1511,8 +1511,8 @@ int nsim_dev_probe(struct nsim_bus_dev *nsim_bus_dev)
goto err_psample_exit;
nsim_dev->esw_mode = DEVLINK_ESWITCH_MODE_LEGACY;
devlink_set_features(devlink, DEVLINK_F_RELOAD);
devlink_register(devlink);
devlink_reload_enable(devlink);
return 0;
err_psample_exit:
......@@ -1566,9 +1566,7 @@ void nsim_dev_remove(struct nsim_bus_dev *nsim_bus_dev)
struct nsim_dev *nsim_dev = dev_get_drvdata(&nsim_bus_dev->dev);
struct devlink *devlink = priv_to_devlink(nsim_dev);
devlink_reload_disable(devlink);
devlink_unregister(devlink);
nsim_dev_reload_destroy(nsim_dev);
nsim_bpf_dev_exit(nsim_dev);
......
......@@ -21,45 +21,7 @@
#include <linux/xarray.h>
#include <linux/firmware.h>
#define DEVLINK_RELOAD_STATS_ARRAY_SIZE \
(__DEVLINK_RELOAD_LIMIT_MAX * __DEVLINK_RELOAD_ACTION_MAX)
struct devlink_dev_stats {
u32 reload_stats[DEVLINK_RELOAD_STATS_ARRAY_SIZE];
u32 remote_reload_stats[DEVLINK_RELOAD_STATS_ARRAY_SIZE];
};
struct devlink_ops;
struct devlink {
u32 index;
struct list_head port_list;
struct list_head rate_list;
struct list_head sb_list;
struct list_head dpipe_table_list;
struct list_head resource_list;
struct list_head param_list;
struct list_head region_list;
struct list_head reporter_list;
struct mutex reporters_lock; /* protects reporter_list */
struct devlink_dpipe_headers *dpipe_headers;
struct list_head trap_list;
struct list_head trap_group_list;
struct list_head trap_policer_list;
const struct devlink_ops *ops;
struct xarray snapshot_ids;
struct devlink_dev_stats stats;
struct device *dev;
possible_net_t _net;
struct mutex lock; /* Serializes access to devlink instance specific objects such as
* port, sb, dpipe, resource, params, region, traps and more.
*/
u8 reload_failed:1,
reload_enabled:1;
refcount_t refcount;
struct completion comp;
char priv[0] __aligned(NETDEV_ALIGN);
};
struct devlink;
struct devlink_port_phys_attrs {
u32 port_number; /* Same value as "split group".
......@@ -1224,6 +1186,11 @@ enum devlink_trap_group_generic_id {
.min_burst = _min_burst, \
}
enum {
/* device supports reload operations */
DEVLINK_F_RELOAD = 1UL << 0,
};
struct devlink_ops {
/**
* @supported_flash_update_params:
......@@ -1520,34 +1487,9 @@ struct devlink_ops {
struct netlink_ext_ack *extack);
};
static inline void *devlink_priv(struct devlink *devlink)
{
BUG_ON(!devlink);
return &devlink->priv;
}
static inline struct devlink *priv_to_devlink(void *priv)
{
BUG_ON(!priv);
return container_of(priv, struct devlink, priv);
}
static inline struct devlink_port *
netdev_to_devlink_port(struct net_device *dev)
{
if (dev->netdev_ops->ndo_get_devlink_port)
return dev->netdev_ops->ndo_get_devlink_port(dev);
return NULL;
}
static inline struct devlink *netdev_to_devlink(struct net_device *dev)
{
struct devlink_port *devlink_port = netdev_to_devlink_port(dev);
if (devlink_port)
return devlink_port->devlink;
return NULL;
}
void *devlink_priv(struct devlink *devlink);
struct devlink *priv_to_devlink(void *priv);
struct device *devlink_to_dev(const struct devlink *devlink);
struct ib_device;
......@@ -1566,10 +1508,9 @@ static inline struct devlink *devlink_alloc(const struct devlink_ops *ops,
{
return devlink_alloc_ns(ops, priv_size, &init_net, dev);
}
void devlink_set_features(struct devlink *devlink, u64 features);
void devlink_register(struct devlink *devlink);
void devlink_unregister(struct devlink *devlink);
void devlink_reload_enable(struct devlink *devlink);
void devlink_reload_disable(struct devlink *devlink);
void devlink_free(struct devlink *devlink);
int devlink_port_register(struct devlink *devlink,
struct devlink_port *devlink_port,
......
......@@ -21,9 +21,9 @@ TRACE_EVENT(devlink_hwmsg,
TP_ARGS(devlink, incoming, type, buf, len),
TP_STRUCT__entry(
__string(bus_name, devlink->dev->bus->name)
__string(dev_name, dev_name(devlink->dev))
__string(driver_name, devlink->dev->driver->name)
__string(bus_name, devlink_to_dev(devlink)->bus->name)
__string(dev_name, dev_name(devlink_to_dev(devlink)))
__string(driver_name, devlink_to_dev(devlink)->driver->name)
__field(bool, incoming)
__field(unsigned long, type)
__dynamic_array(u8, buf, len)
......@@ -31,9 +31,9 @@ TRACE_EVENT(devlink_hwmsg,
),
TP_fast_assign(
__assign_str(bus_name, devlink->dev->bus->name);
__assign_str(dev_name, dev_name(devlink->dev));
__assign_str(driver_name, devlink->dev->driver->name);
__assign_str(bus_name, devlink_to_dev(devlink)->bus->name);
__assign_str(dev_name, dev_name(devlink_to_dev(devlink)));
__assign_str(driver_name, devlink_to_dev(devlink)->driver->name);
__entry->incoming = incoming;
__entry->type = type;
memcpy(__get_dynamic_array(buf), buf, len);
......@@ -55,17 +55,17 @@ TRACE_EVENT(devlink_hwerr,
TP_ARGS(devlink, err, msg),
TP_STRUCT__entry(
__string(bus_name, devlink->dev->bus->name)
__string(dev_name, dev_name(devlink->dev))
__string(driver_name, devlink->dev->driver->name)
__string(bus_name, devlink_to_dev(devlink)->bus->name)
__string(dev_name, dev_name(devlink_to_dev(devlink)))
__string(driver_name, devlink_to_dev(devlink)->driver->name)
__field(int, err)
__string(msg, msg)
),
TP_fast_assign(
__assign_str(bus_name, devlink->dev->bus->name);
__assign_str(dev_name, dev_name(devlink->dev));
__assign_str(driver_name, devlink->dev->driver->name);
__assign_str(bus_name, devlink_to_dev(devlink)->bus->name);
__assign_str(dev_name, dev_name(devlink_to_dev(devlink)));
__assign_str(driver_name, devlink_to_dev(devlink)->driver->name);
__entry->err = err;
__assign_str(msg, msg);
),
......@@ -85,17 +85,17 @@ TRACE_EVENT(devlink_health_report,
TP_ARGS(devlink, reporter_name, msg),
TP_STRUCT__entry(
__string(bus_name, devlink->dev->bus->name)
__string(dev_name, dev_name(devlink->dev))
__string(driver_name, devlink->dev->driver->name)
__string(bus_name, devlink_to_dev(devlink)->bus->name)
__string(dev_name, dev_name(devlink_to_dev(devlink)))
__string(driver_name, devlink_to_dev(devlink)->driver->name)
__string(reporter_name, msg)
__string(msg, msg)
),
TP_fast_assign(
__assign_str(bus_name, devlink->dev->bus->name);
__assign_str(dev_name, dev_name(devlink->dev));
__assign_str(driver_name, devlink->dev->driver->name);
__assign_str(bus_name, devlink_to_dev(devlink)->bus->name);
__assign_str(dev_name, dev_name(devlink_to_dev(devlink)));
__assign_str(driver_name, devlink_to_dev(devlink)->driver->name);
__assign_str(reporter_name, reporter_name);
__assign_str(msg, msg);
),
......@@ -116,18 +116,18 @@ TRACE_EVENT(devlink_health_recover_aborted,
TP_ARGS(devlink, reporter_name, health_state, time_since_last_recover),
TP_STRUCT__entry(
__string(bus_name, devlink->dev->bus->name)
__string(dev_name, dev_name(devlink->dev))
__string(driver_name, devlink->dev->driver->name)
__string(bus_name, devlink_to_dev(devlink)->bus->name)
__string(dev_name, dev_name(devlink_to_dev(devlink)))
__string(driver_name, devlink_to_dev(devlink)->driver->name)
__string(reporter_name, reporter_name)
__field(bool, health_state)
__field(u64, time_since_last_recover)
),
TP_fast_assign(
__assign_str(bus_name, devlink->dev->bus->name);
__assign_str(dev_name, dev_name(devlink->dev));
__assign_str(driver_name, devlink->dev->driver->name);
__assign_str(bus_name, devlink_to_dev(devlink)->bus->name);
__assign_str(dev_name, dev_name(devlink_to_dev(devlink)));
__assign_str(driver_name, devlink_to_dev(devlink)->driver->name);
__assign_str(reporter_name, reporter_name);
__entry->health_state = health_state;
__entry->time_since_last_recover = time_since_last_recover;
......@@ -150,17 +150,17 @@ TRACE_EVENT(devlink_health_reporter_state_update,
TP_ARGS(devlink, reporter_name, new_state),
TP_STRUCT__entry(
__string(bus_name, devlink->dev->bus->name)
__string(dev_name, dev_name(devlink->dev))
__string(driver_name, devlink->dev->driver->name)
__string(bus_name, devlink_to_dev(devlink)->bus->name)
__string(dev_name, dev_name(devlink_to_dev(devlink)))
__string(driver_name, devlink_to_dev(devlink)->driver->name)
__string(reporter_name, reporter_name)
__field(u8, new_state)
),
TP_fast_assign(
__assign_str(bus_name, devlink->dev->bus->name);
__assign_str(dev_name, dev_name(devlink->dev));
__assign_str(driver_name, devlink->dev->driver->name);
__assign_str(bus_name, devlink_to_dev(devlink)->bus->name);
__assign_str(dev_name, dev_name(devlink_to_dev(devlink)));
__assign_str(driver_name, devlink_to_dev(devlink)->driver->name);
__assign_str(reporter_name, reporter_name);
__entry->new_state = new_state;
),
......@@ -181,9 +181,9 @@ TRACE_EVENT(devlink_trap_report,
TP_ARGS(devlink, skb, metadata),
TP_STRUCT__entry(
__string(bus_name, devlink->dev->bus->name)
__string(dev_name, dev_name(devlink->dev))
__string(driver_name, devlink->dev->driver->name)
__string(bus_name, devlink_to_dev(devlink)->bus->name)
__string(dev_name, dev_name(devlink_to_dev(devlink)))
__string(driver_name, devlink_to_dev(devlink)->driver->name)
__string(trap_name, metadata->trap_name)
__string(trap_group_name, metadata->trap_group_name)
__dynamic_array(char, input_dev_name, IFNAMSIZ)
......@@ -192,9 +192,9 @@ TRACE_EVENT(devlink_trap_report,
TP_fast_assign(
struct net_device *input_dev = metadata->input_dev;
__assign_str(bus_name, devlink->dev->bus->name);
__assign_str(dev_name, dev_name(devlink->dev));
__assign_str(driver_name, devlink->dev->driver->name);
__assign_str(bus_name, devlink_to_dev(devlink)->bus->name);
__assign_str(dev_name, dev_name(devlink_to_dev(devlink)));
__assign_str(driver_name, devlink_to_dev(devlink)->driver->name);
__assign_str(trap_name, metadata->trap_name);
__assign_str(trap_group_name, metadata->trap_group_name);
__assign_str(input_dev_name,
......
......@@ -30,6 +30,63 @@
#define CREATE_TRACE_POINTS
#include <trace/events/devlink.h>
#define DEVLINK_RELOAD_STATS_ARRAY_SIZE \
(__DEVLINK_RELOAD_LIMIT_MAX * __DEVLINK_RELOAD_ACTION_MAX)
struct devlink_dev_stats {
u32 reload_stats[DEVLINK_RELOAD_STATS_ARRAY_SIZE];
u32 remote_reload_stats[DEVLINK_RELOAD_STATS_ARRAY_SIZE];
};
struct devlink {
u32 index;
struct list_head port_list;
struct list_head rate_list;
struct list_head sb_list;
struct list_head dpipe_table_list;
struct list_head resource_list;
struct list_head param_list;
struct list_head region_list;
struct list_head reporter_list;
struct mutex reporters_lock; /* protects reporter_list */
struct devlink_dpipe_headers *dpipe_headers;
struct list_head trap_list;
struct list_head trap_group_list;
struct list_head trap_policer_list;
const struct devlink_ops *ops;
u64 features;
struct xarray snapshot_ids;
struct devlink_dev_stats stats;
struct device *dev;
possible_net_t _net;
/* Serializes access to devlink instance specific objects such as
* port, sb, dpipe, resource, params, region, traps and more.
*/
struct mutex lock;
u8 reload_failed:1;
refcount_t refcount;
struct completion comp;
char priv[0] __aligned(NETDEV_ALIGN);
};
void *devlink_priv(struct devlink *devlink)
{
return &devlink->priv;
}
EXPORT_SYMBOL_GPL(devlink_priv);
struct devlink *priv_to_devlink(void *priv)
{
return container_of(priv, struct devlink, priv);
}
EXPORT_SYMBOL_GPL(priv_to_devlink);
struct device *devlink_to_dev(const struct devlink *devlink)
{
return devlink->dev;
}
EXPORT_SYMBOL_GPL(devlink_to_dev);
static struct devlink_dpipe_field devlink_dpipe_fields_ethernet[] = {
{
.name = "destination mac",
......@@ -95,6 +152,22 @@ static const struct nla_policy devlink_function_nl_policy[DEVLINK_PORT_FUNCTION_
static DEFINE_XARRAY_FLAGS(devlinks, XA_FLAGS_ALLOC);
#define DEVLINK_REGISTERED XA_MARK_1
/* devlink instances are open to the access from the user space after
* devlink_register() call. Such logical barrier allows us to have certain
* expectations related to locking.
*
* Before *_register() - we are in initialization stage and no parallel
* access possible to the devlink instance. All drivers perform that phase
* by implicitly holding device_lock.
*
* After *_register() - users and driver can access devlink instance at
* the same time.
*/
#define ASSERT_DEVLINK_REGISTERED(d) \
WARN_ON_ONCE(!xa_get_mark(&devlinks, (d)->index, DEVLINK_REGISTERED))
#define ASSERT_DEVLINK_NOT_REGISTERED(d) \
WARN_ON_ONCE(xa_get_mark(&devlinks, (d)->index, DEVLINK_REGISTERED))
/* devlink_mutex
*
* An overall lock guarding every operation coming from userspace.
......@@ -3959,9 +4032,6 @@ static int devlink_reload(struct devlink *devlink, struct net *dest_net,
struct net *curr_net;
int err;
if (!devlink->reload_enabled)
return -EOPNOTSUPP;
memcpy(remote_reload_stats, devlink->stats.remote_reload_stats,
sizeof(remote_reload_stats));
......@@ -4029,7 +4099,7 @@ static int devlink_nl_cmd_reload(struct sk_buff *skb, struct genl_info *info)
u32 actions_performed;
int err;
if (!devlink_reload_supported(devlink->ops))
if (!(devlink->features & DEVLINK_F_RELOAD))
return -EOPNOTSUPP;
err = devlink_resources_validate(devlink, NULL, info);
......@@ -8912,6 +8982,25 @@ static bool devlink_reload_actions_valid(const struct devlink_ops *ops)
return true;
}
/**
* devlink_set_features - Set devlink supported features
*
* @devlink: devlink
* @features: devlink support features
*
* This interface allows us to set reload ops separatelly from
* the devlink_alloc.
*/
void devlink_set_features(struct devlink *devlink, u64 features)
{
ASSERT_DEVLINK_NOT_REGISTERED(devlink);
WARN_ON(features & DEVLINK_F_RELOAD &&
!devlink_reload_supported(devlink->ops));
devlink->features = features;
}
EXPORT_SYMBOL_GPL(devlink_set_features);
/**
* devlink_alloc_ns - Allocate new devlink instance resources
* in specific namespace
......@@ -9056,6 +9145,10 @@ static void devlink_notify_unregister(struct devlink *devlink)
*/
void devlink_register(struct devlink *devlink)
{
ASSERT_DEVLINK_NOT_REGISTERED(devlink);
/* Make sure that we are in .probe() routine */
device_lock_assert(devlink->dev);
mutex_lock(&devlink_mutex);
xa_set_mark(&devlinks, devlink->index, DEVLINK_REGISTERED);
devlink_notify_register(devlink);
......@@ -9070,53 +9163,20 @@ EXPORT_SYMBOL_GPL(devlink_register);
*/
void devlink_unregister(struct devlink *devlink)
{
ASSERT_DEVLINK_REGISTERED(devlink);
/* Make sure that we are in .remove() routine */
device_lock_assert(devlink->dev);
devlink_put(devlink);
wait_for_completion(&devlink->comp);
mutex_lock(&devlink_mutex);
WARN_ON(devlink_reload_supported(devlink->ops) &&
devlink->reload_enabled);
devlink_notify_unregister(devlink);
xa_clear_mark(&devlinks, devlink->index, DEVLINK_REGISTERED);
mutex_unlock(&devlink_mutex);
}
EXPORT_SYMBOL_GPL(devlink_unregister);
/**
* devlink_reload_enable - Enable reload of devlink instance
*
* @devlink: devlink
*
* Should be called at end of device initialization
* process when reload operation is supported.
*/
void devlink_reload_enable(struct devlink *devlink)
{
mutex_lock(&devlink_mutex);
devlink->reload_enabled = true;
mutex_unlock(&devlink_mutex);
}
EXPORT_SYMBOL_GPL(devlink_reload_enable);
/**
* devlink_reload_disable - Disable reload of devlink instance
*
* @devlink: devlink
*
* Should be called at the beginning of device cleanup
* process when reload operation is supported.
*/
void devlink_reload_disable(struct devlink *devlink)
{
mutex_lock(&devlink_mutex);
/* Mutex is taken which ensures that no reload operation is in
* progress while setting up forbidded flag.
*/
devlink->reload_enabled = false;
mutex_unlock(&devlink_mutex);
}
EXPORT_SYMBOL_GPL(devlink_reload_disable);
/**
* devlink_free - Free devlink instance resources
*
......@@ -9124,6 +9184,8 @@ EXPORT_SYMBOL_GPL(devlink_reload_disable);
*/
void devlink_free(struct devlink *devlink)
{
ASSERT_DEVLINK_NOT_REGISTERED(devlink);
mutex_destroy(&devlink->reporters_lock);
mutex_destroy(&devlink->lock);
WARN_ON(!list_empty(&devlink->trap_policer_list));
......@@ -11324,6 +11386,24 @@ static void __devlink_compat_running_version(struct devlink *devlink,
nlmsg_free(msg);
}
static struct devlink_port *netdev_to_devlink_port(struct net_device *dev)
{
if (!dev->netdev_ops->ndo_get_devlink_port)
return NULL;
return dev->netdev_ops->ndo_get_devlink_port(dev);
}
static struct devlink *netdev_to_devlink(struct net_device *dev)
{
struct devlink_port *devlink_port = netdev_to_devlink_port(dev);
if (!devlink_port)
return NULL;
return devlink_port->devlink;
}
void devlink_compat_running_version(struct net_device *dev,
char *buf, size_t len)
{
......@@ -11433,7 +11513,7 @@ static void __net_exit devlink_pernet_pre_exit(struct net *net)
if (!net_eq(devlink_net(devlink), net))
goto retry;
WARN_ON(!devlink_reload_supported(devlink->ops));
WARN_ON(!(devlink->features & DEVLINK_F_RELOAD));
err = devlink_reload(devlink, &init_net,
DEVLINK_RELOAD_ACTION_DRIVER_REINIT,
DEVLINK_RELOAD_LIMIT_UNSPEC,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment