Commit 1c5cc012 authored by Jakub Kicinski's avatar Jakub Kicinski

Merge branch 'devlink-linecard-and-reporters-locking-cleanup'

Jiri Pirko says:

====================
devlink: linecard and reporters locking cleanup

This patchset does not change functionality.

Patches 1-2 remove linecards lock and reference counting, converting
them to be protected by devlink instance lock as the rest of
the objects.

Patches 3-4 fix the mlx5 auxiliary device devlink locking scheme whis is
needed for proper reporters lock conversion done in the following
patches.

Patches 5-8 remove reporters locks and reference counting, converting
them to be protected by devlink instance lock as the rest of
the objects.

Patches 9 and 10 convert linecards and reporters dumpit callbacks to
recently introduced devlink_nl_instance_iter_dump() infra.

Patch 11 removes no longer needed devlink_dump_for_each_instance_get()
helper.

The last patch adds assertion to devl_is_registered() as dependency on
other locks is removed.
====================

Link: https://lore.kernel.org/r/20230118152115.1113149-1-jiri@resnulli.usSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 854617f5 63ba54a5
...@@ -349,7 +349,6 @@ int mlx5_attach_device(struct mlx5_core_dev *dev) ...@@ -349,7 +349,6 @@ int mlx5_attach_device(struct mlx5_core_dev *dev)
devl_assert_locked(priv_to_devlink(dev)); devl_assert_locked(priv_to_devlink(dev));
mutex_lock(&mlx5_intf_mutex); mutex_lock(&mlx5_intf_mutex);
priv->flags &= ~MLX5_PRIV_FLAGS_DETACH; priv->flags &= ~MLX5_PRIV_FLAGS_DETACH;
priv->flags |= MLX5_PRIV_FLAGS_MLX5E_LOCKED_FLOW;
for (i = 0; i < ARRAY_SIZE(mlx5_adev_devices); i++) { for (i = 0; i < ARRAY_SIZE(mlx5_adev_devices); i++) {
if (!priv->adev[i]) { if (!priv->adev[i]) {
bool is_supported = false; bool is_supported = false;
...@@ -397,7 +396,6 @@ int mlx5_attach_device(struct mlx5_core_dev *dev) ...@@ -397,7 +396,6 @@ int mlx5_attach_device(struct mlx5_core_dev *dev)
break; break;
} }
} }
priv->flags &= ~MLX5_PRIV_FLAGS_MLX5E_LOCKED_FLOW;
mutex_unlock(&mlx5_intf_mutex); mutex_unlock(&mlx5_intf_mutex);
return ret; return ret;
} }
...@@ -412,7 +410,6 @@ void mlx5_detach_device(struct mlx5_core_dev *dev) ...@@ -412,7 +410,6 @@ void mlx5_detach_device(struct mlx5_core_dev *dev)
devl_assert_locked(priv_to_devlink(dev)); devl_assert_locked(priv_to_devlink(dev));
mutex_lock(&mlx5_intf_mutex); mutex_lock(&mlx5_intf_mutex);
priv->flags |= MLX5_PRIV_FLAGS_MLX5E_LOCKED_FLOW;
for (i = ARRAY_SIZE(mlx5_adev_devices) - 1; i >= 0; i--) { for (i = ARRAY_SIZE(mlx5_adev_devices) - 1; i >= 0; i--) {
if (!priv->adev[i]) if (!priv->adev[i])
continue; continue;
...@@ -441,7 +438,6 @@ void mlx5_detach_device(struct mlx5_core_dev *dev) ...@@ -441,7 +438,6 @@ void mlx5_detach_device(struct mlx5_core_dev *dev)
del_adev(&priv->adev[i]->adev); del_adev(&priv->adev[i]->adev);
priv->adev[i] = NULL; priv->adev[i] = NULL;
} }
priv->flags &= ~MLX5_PRIV_FLAGS_MLX5E_LOCKED_FLOW;
priv->flags |= MLX5_PRIV_FLAGS_DETACH; priv->flags |= MLX5_PRIV_FLAGS_DETACH;
mutex_unlock(&mlx5_intf_mutex); mutex_unlock(&mlx5_intf_mutex);
} }
...@@ -540,22 +536,16 @@ static void delete_drivers(struct mlx5_core_dev *dev) ...@@ -540,22 +536,16 @@ static void delete_drivers(struct mlx5_core_dev *dev)
int mlx5_rescan_drivers_locked(struct mlx5_core_dev *dev) int mlx5_rescan_drivers_locked(struct mlx5_core_dev *dev)
{ {
struct mlx5_priv *priv = &dev->priv; struct mlx5_priv *priv = &dev->priv;
int err = 0;
lockdep_assert_held(&mlx5_intf_mutex); lockdep_assert_held(&mlx5_intf_mutex);
if (priv->flags & MLX5_PRIV_FLAGS_DETACH) if (priv->flags & MLX5_PRIV_FLAGS_DETACH)
return 0; return 0;
priv->flags |= MLX5_PRIV_FLAGS_MLX5E_LOCKED_FLOW;
delete_drivers(dev); delete_drivers(dev);
if (priv->flags & MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV) if (priv->flags & MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV)
goto out; return 0;
err = add_drivers(dev);
out: return add_drivers(dev);
priv->flags &= ~MLX5_PRIV_FLAGS_MLX5E_LOCKED_FLOW;
return err;
} }
bool mlx5_same_hw_devs(struct mlx5_core_dev *dev, struct mlx5_core_dev *peer_dev) bool mlx5_same_hw_devs(struct mlx5_core_dev *dev, struct mlx5_core_dev *peer_dev)
......
...@@ -971,6 +971,10 @@ struct mlx5e_priv { ...@@ -971,6 +971,10 @@ struct mlx5e_priv {
struct dentry *dfs_root; struct dentry *dfs_root;
}; };
struct mlx5e_dev {
struct mlx5e_priv *priv;
};
struct mlx5e_rx_handlers { struct mlx5e_rx_handlers {
mlx5e_fp_handle_rx_cqe handle_rx_cqe; mlx5e_fp_handle_rx_cqe handle_rx_cqe;
mlx5e_fp_handle_rx_cqe handle_rx_cqe_mpwqe; mlx5e_fp_handle_rx_cqe handle_rx_cqe_mpwqe;
......
...@@ -4,6 +4,29 @@ ...@@ -4,6 +4,29 @@
#include "en/devlink.h" #include "en/devlink.h"
#include "eswitch.h" #include "eswitch.h"
static const struct devlink_ops mlx5e_devlink_ops = {
};
struct mlx5e_dev *mlx5e_create_devlink(struct device *dev)
{
struct mlx5e_dev *mlx5e_dev;
struct devlink *devlink;
devlink = devlink_alloc(&mlx5e_devlink_ops, sizeof(*mlx5e_dev), dev);
if (!devlink)
return ERR_PTR(-ENOMEM);
devlink_register(devlink);
return devlink_priv(devlink);
}
void mlx5e_destroy_devlink(struct mlx5e_dev *mlx5e_dev)
{
struct devlink *devlink = priv_to_devlink(mlx5e_dev);
devlink_unregister(devlink);
devlink_free(devlink);
}
static void static void
mlx5e_devlink_get_port_parent_id(struct mlx5_core_dev *dev, struct netdev_phys_item_id *ppid) mlx5e_devlink_get_port_parent_id(struct mlx5_core_dev *dev, struct netdev_phys_item_id *ppid)
{ {
...@@ -14,14 +37,14 @@ mlx5e_devlink_get_port_parent_id(struct mlx5_core_dev *dev, struct netdev_phys_i ...@@ -14,14 +37,14 @@ mlx5e_devlink_get_port_parent_id(struct mlx5_core_dev *dev, struct netdev_phys_i
memcpy(ppid->id, &parent_id, sizeof(parent_id)); memcpy(ppid->id, &parent_id, sizeof(parent_id));
} }
int mlx5e_devlink_port_register(struct mlx5e_priv *priv) int mlx5e_devlink_port_register(struct mlx5e_dev *mlx5e_dev,
struct mlx5e_priv *priv)
{ {
struct devlink *devlink = priv_to_devlink(priv->mdev); struct devlink *devlink = priv_to_devlink(mlx5e_dev);
struct devlink_port_attrs attrs = {}; struct devlink_port_attrs attrs = {};
struct netdev_phys_item_id ppid = {}; struct netdev_phys_item_id ppid = {};
struct devlink_port *dl_port; struct devlink_port *dl_port;
unsigned int dl_port_index; unsigned int dl_port_index;
int ret;
if (mlx5_core_is_pf(priv->mdev)) { if (mlx5_core_is_pf(priv->mdev)) {
attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL; attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
...@@ -42,23 +65,12 @@ int mlx5e_devlink_port_register(struct mlx5e_priv *priv) ...@@ -42,23 +65,12 @@ int mlx5e_devlink_port_register(struct mlx5e_priv *priv)
memset(dl_port, 0, sizeof(*dl_port)); memset(dl_port, 0, sizeof(*dl_port));
devlink_port_attrs_set(dl_port, &attrs); devlink_port_attrs_set(dl_port, &attrs);
if (!(priv->mdev->priv.flags & MLX5_PRIV_FLAGS_MLX5E_LOCKED_FLOW)) return devlink_port_register(devlink, dl_port, dl_port_index);
devl_lock(devlink);
ret = devl_port_register(devlink, dl_port, dl_port_index);
if (!(priv->mdev->priv.flags & MLX5_PRIV_FLAGS_MLX5E_LOCKED_FLOW))
devl_unlock(devlink);
return ret;
} }
void mlx5e_devlink_port_unregister(struct mlx5e_priv *priv) void mlx5e_devlink_port_unregister(struct mlx5e_priv *priv)
{ {
struct devlink_port *dl_port = mlx5e_devlink_get_dl_port(priv); struct devlink_port *dl_port = mlx5e_devlink_get_dl_port(priv);
struct devlink *devlink = priv_to_devlink(priv->mdev);
if (!(priv->mdev->priv.flags & MLX5_PRIV_FLAGS_MLX5E_LOCKED_FLOW)) devlink_port_unregister(dl_port);
devl_lock(devlink);
devl_port_unregister(dl_port);
if (!(priv->mdev->priv.flags & MLX5_PRIV_FLAGS_MLX5E_LOCKED_FLOW))
devl_unlock(devlink);
} }
...@@ -7,7 +7,10 @@ ...@@ -7,7 +7,10 @@
#include <net/devlink.h> #include <net/devlink.h>
#include "en.h" #include "en.h"
int mlx5e_devlink_port_register(struct mlx5e_priv *priv); struct mlx5e_dev *mlx5e_create_devlink(struct device *dev);
void mlx5e_destroy_devlink(struct mlx5e_dev *mlx5e_dev);
int mlx5e_devlink_port_register(struct mlx5e_dev *mlx5e_dev,
struct mlx5e_priv *priv);
void mlx5e_devlink_port_unregister(struct mlx5e_priv *priv); void mlx5e_devlink_port_unregister(struct mlx5e_priv *priv);
static inline struct devlink_port * static inline struct devlink_port *
......
...@@ -754,6 +754,6 @@ void mlx5e_reporter_rx_destroy(struct mlx5e_priv *priv) ...@@ -754,6 +754,6 @@ void mlx5e_reporter_rx_destroy(struct mlx5e_priv *priv)
if (!priv->rx_reporter) if (!priv->rx_reporter)
return; return;
devlink_port_health_reporter_destroy(priv->rx_reporter); devlink_health_reporter_destroy(priv->rx_reporter);
priv->rx_reporter = NULL; priv->rx_reporter = NULL;
} }
...@@ -609,6 +609,6 @@ void mlx5e_reporter_tx_destroy(struct mlx5e_priv *priv) ...@@ -609,6 +609,6 @@ void mlx5e_reporter_tx_destroy(struct mlx5e_priv *priv)
if (!priv->tx_reporter) if (!priv->tx_reporter)
return; return;
devlink_port_health_reporter_destroy(priv->tx_reporter); devlink_health_reporter_destroy(priv->tx_reporter);
priv->tx_reporter = NULL; priv->tx_reporter = NULL;
} }
...@@ -5876,7 +5876,8 @@ void mlx5e_destroy_netdev(struct mlx5e_priv *priv) ...@@ -5876,7 +5876,8 @@ void mlx5e_destroy_netdev(struct mlx5e_priv *priv)
static int mlx5e_resume(struct auxiliary_device *adev) static int mlx5e_resume(struct auxiliary_device *adev)
{ {
struct mlx5_adev *edev = container_of(adev, struct mlx5_adev, adev); struct mlx5_adev *edev = container_of(adev, struct mlx5_adev, adev);
struct mlx5e_priv *priv = auxiliary_get_drvdata(adev); struct mlx5e_dev *mlx5e_dev = auxiliary_get_drvdata(adev);
struct mlx5e_priv *priv = mlx5e_dev->priv;
struct net_device *netdev = priv->netdev; struct net_device *netdev = priv->netdev;
struct mlx5_core_dev *mdev = edev->mdev; struct mlx5_core_dev *mdev = edev->mdev;
int err; int err;
...@@ -5899,7 +5900,8 @@ static int mlx5e_resume(struct auxiliary_device *adev) ...@@ -5899,7 +5900,8 @@ static int mlx5e_resume(struct auxiliary_device *adev)
static int mlx5e_suspend(struct auxiliary_device *adev, pm_message_t state) static int mlx5e_suspend(struct auxiliary_device *adev, pm_message_t state)
{ {
struct mlx5e_priv *priv = auxiliary_get_drvdata(adev); struct mlx5e_dev *mlx5e_dev = auxiliary_get_drvdata(adev);
struct mlx5e_priv *priv = mlx5e_dev->priv;
struct net_device *netdev = priv->netdev; struct net_device *netdev = priv->netdev;
struct mlx5_core_dev *mdev = priv->mdev; struct mlx5_core_dev *mdev = priv->mdev;
...@@ -5917,21 +5919,28 @@ static int mlx5e_probe(struct auxiliary_device *adev, ...@@ -5917,21 +5919,28 @@ static int mlx5e_probe(struct auxiliary_device *adev,
struct mlx5_adev *edev = container_of(adev, struct mlx5_adev, adev); struct mlx5_adev *edev = container_of(adev, struct mlx5_adev, adev);
const struct mlx5e_profile *profile = &mlx5e_nic_profile; const struct mlx5e_profile *profile = &mlx5e_nic_profile;
struct mlx5_core_dev *mdev = edev->mdev; struct mlx5_core_dev *mdev = edev->mdev;
struct mlx5e_dev *mlx5e_dev;
struct net_device *netdev; struct net_device *netdev;
pm_message_t state = {}; pm_message_t state = {};
struct mlx5e_priv *priv; struct mlx5e_priv *priv;
int err; int err;
mlx5e_dev = mlx5e_create_devlink(&adev->dev);
if (IS_ERR(mlx5e_dev))
return PTR_ERR(mlx5e_dev);
auxiliary_set_drvdata(adev, mlx5e_dev);
netdev = mlx5e_create_netdev(mdev, profile); netdev = mlx5e_create_netdev(mdev, profile);
if (!netdev) { if (!netdev) {
mlx5_core_err(mdev, "mlx5e_create_netdev failed\n"); mlx5_core_err(mdev, "mlx5e_create_netdev failed\n");
return -ENOMEM; err = -ENOMEM;
goto err_devlink_unregister;
} }
mlx5e_build_nic_netdev(netdev); mlx5e_build_nic_netdev(netdev);
priv = netdev_priv(netdev); priv = netdev_priv(netdev);
auxiliary_set_drvdata(adev, priv); mlx5e_dev->priv = priv;
priv->profile = profile; priv->profile = profile;
priv->ppriv = NULL; priv->ppriv = NULL;
...@@ -5939,7 +5948,7 @@ static int mlx5e_probe(struct auxiliary_device *adev, ...@@ -5939,7 +5948,7 @@ static int mlx5e_probe(struct auxiliary_device *adev,
priv->dfs_root = debugfs_create_dir("nic", priv->dfs_root = debugfs_create_dir("nic",
mlx5_debugfs_get_dev_root(priv->mdev)); mlx5_debugfs_get_dev_root(priv->mdev));
err = mlx5e_devlink_port_register(priv); err = mlx5e_devlink_port_register(mlx5e_dev, priv);
if (err) { if (err) {
mlx5_core_err(mdev, "mlx5e_devlink_port_register failed, %d\n", err); mlx5_core_err(mdev, "mlx5e_devlink_port_register failed, %d\n", err);
goto err_destroy_netdev; goto err_destroy_netdev;
...@@ -5978,12 +5987,15 @@ static int mlx5e_probe(struct auxiliary_device *adev, ...@@ -5978,12 +5987,15 @@ static int mlx5e_probe(struct auxiliary_device *adev,
err_destroy_netdev: err_destroy_netdev:
debugfs_remove_recursive(priv->dfs_root); debugfs_remove_recursive(priv->dfs_root);
mlx5e_destroy_netdev(priv); mlx5e_destroy_netdev(priv);
err_devlink_unregister:
mlx5e_destroy_devlink(mlx5e_dev);
return err; return err;
} }
static void mlx5e_remove(struct auxiliary_device *adev) static void mlx5e_remove(struct auxiliary_device *adev)
{ {
struct mlx5e_priv *priv = auxiliary_get_drvdata(adev); struct mlx5e_dev *mlx5e_dev = auxiliary_get_drvdata(adev);
struct mlx5e_priv *priv = mlx5e_dev->priv;
pm_message_t state = {}; pm_message_t state = {};
mlx5e_dcbnl_delete_app(priv); mlx5e_dcbnl_delete_app(priv);
...@@ -5993,6 +6005,7 @@ static void mlx5e_remove(struct auxiliary_device *adev) ...@@ -5993,6 +6005,7 @@ static void mlx5e_remove(struct auxiliary_device *adev)
mlx5e_devlink_port_unregister(priv); mlx5e_devlink_port_unregister(priv);
debugfs_remove_recursive(priv->dfs_root); debugfs_remove_recursive(priv->dfs_root);
mlx5e_destroy_netdev(priv); mlx5e_destroy_netdev(priv);
mlx5e_destroy_devlink(mlx5e_dev);
} }
static const struct auxiliary_device_id mlx5e_id_table[] = { static const struct auxiliary_device_id mlx5e_id_table[] = {
......
...@@ -2051,8 +2051,8 @@ static int mlxsw_core_health_init(struct mlxsw_core *mlxsw_core) ...@@ -2051,8 +2051,8 @@ static int mlxsw_core_health_init(struct mlxsw_core *mlxsw_core)
if (!(mlxsw_core->bus->features & MLXSW_BUS_F_TXRX)) if (!(mlxsw_core->bus->features & MLXSW_BUS_F_TXRX))
return 0; return 0;
fw_fatal = devlink_health_reporter_create(devlink, &mlxsw_core_health_fw_fatal_ops, fw_fatal = devl_health_reporter_create(devlink, &mlxsw_core_health_fw_fatal_ops,
0, mlxsw_core); 0, mlxsw_core);
if (IS_ERR(fw_fatal)) { if (IS_ERR(fw_fatal)) {
dev_err(mlxsw_core->bus_info->dev, "Failed to create fw fatal reporter"); dev_err(mlxsw_core->bus_info->dev, "Failed to create fw fatal reporter");
return PTR_ERR(fw_fatal); return PTR_ERR(fw_fatal);
...@@ -2072,7 +2072,7 @@ static int mlxsw_core_health_init(struct mlxsw_core *mlxsw_core) ...@@ -2072,7 +2072,7 @@ static int mlxsw_core_health_init(struct mlxsw_core *mlxsw_core)
err_fw_fatal_config: err_fw_fatal_config:
mlxsw_core_trap_unregister(mlxsw_core, &mlxsw_core_health_listener, mlxsw_core); mlxsw_core_trap_unregister(mlxsw_core, &mlxsw_core_health_listener, mlxsw_core);
err_trap_register: err_trap_register:
devlink_health_reporter_destroy(mlxsw_core->health.fw_fatal); devl_health_reporter_destroy(mlxsw_core->health.fw_fatal);
return err; return err;
} }
...@@ -2085,7 +2085,7 @@ static void mlxsw_core_health_fini(struct mlxsw_core *mlxsw_core) ...@@ -2085,7 +2085,7 @@ static void mlxsw_core_health_fini(struct mlxsw_core *mlxsw_core)
mlxsw_core_trap_unregister(mlxsw_core, &mlxsw_core_health_listener, mlxsw_core); mlxsw_core_trap_unregister(mlxsw_core, &mlxsw_core_health_listener, mlxsw_core);
/* Make sure there is no more event work scheduled */ /* Make sure there is no more event work scheduled */
mlxsw_core_flush_owq(); mlxsw_core_flush_owq();
devlink_health_reporter_destroy(mlxsw_core->health.fw_fatal); devl_health_reporter_destroy(mlxsw_core->health.fw_fatal);
} }
static void mlxsw_core_irq_event_handler_init(struct mlxsw_core *mlxsw_core) static void mlxsw_core_irq_event_handler_init(struct mlxsw_core *mlxsw_core)
......
...@@ -1259,9 +1259,9 @@ static int mlxsw_linecard_init(struct mlxsw_core *mlxsw_core, ...@@ -1259,9 +1259,9 @@ static int mlxsw_linecard_init(struct mlxsw_core *mlxsw_core,
linecard->linecards = linecards; linecard->linecards = linecards;
mutex_init(&linecard->lock); mutex_init(&linecard->lock);
devlink_linecard = devlink_linecard_create(priv_to_devlink(mlxsw_core), devlink_linecard = devl_linecard_create(priv_to_devlink(mlxsw_core),
slot_index, &mlxsw_linecard_ops, slot_index, &mlxsw_linecard_ops,
linecard); linecard);
if (IS_ERR(devlink_linecard)) if (IS_ERR(devlink_linecard))
return PTR_ERR(devlink_linecard); return PTR_ERR(devlink_linecard);
...@@ -1285,7 +1285,7 @@ static void mlxsw_linecard_fini(struct mlxsw_core *mlxsw_core, ...@@ -1285,7 +1285,7 @@ static void mlxsw_linecard_fini(struct mlxsw_core *mlxsw_core,
if (linecard->active) if (linecard->active)
mlxsw_linecard_active_clear(linecard); mlxsw_linecard_active_clear(linecard);
mlxsw_linecard_bdev_del(linecard); mlxsw_linecard_bdev_del(linecard);
devlink_linecard_destroy(linecard->devlink_linecard); devl_linecard_destroy(linecard->devlink_linecard);
mutex_destroy(&linecard->lock); mutex_destroy(&linecard->lock);
} }
......
...@@ -233,16 +233,16 @@ int nsim_dev_health_init(struct nsim_dev *nsim_dev, struct devlink *devlink) ...@@ -233,16 +233,16 @@ int nsim_dev_health_init(struct nsim_dev *nsim_dev, struct devlink *devlink)
int err; int err;
health->empty_reporter = health->empty_reporter =
devlink_health_reporter_create(devlink, devl_health_reporter_create(devlink,
&nsim_dev_empty_reporter_ops, &nsim_dev_empty_reporter_ops,
0, health); 0, health);
if (IS_ERR(health->empty_reporter)) if (IS_ERR(health->empty_reporter))
return PTR_ERR(health->empty_reporter); return PTR_ERR(health->empty_reporter);
health->dummy_reporter = health->dummy_reporter =
devlink_health_reporter_create(devlink, devl_health_reporter_create(devlink,
&nsim_dev_dummy_reporter_ops, &nsim_dev_dummy_reporter_ops,
0, health); 0, health);
if (IS_ERR(health->dummy_reporter)) { if (IS_ERR(health->dummy_reporter)) {
err = PTR_ERR(health->dummy_reporter); err = PTR_ERR(health->dummy_reporter);
goto err_empty_reporter_destroy; goto err_empty_reporter_destroy;
...@@ -266,9 +266,9 @@ int nsim_dev_health_init(struct nsim_dev *nsim_dev, struct devlink *devlink) ...@@ -266,9 +266,9 @@ int nsim_dev_health_init(struct nsim_dev *nsim_dev, struct devlink *devlink)
return 0; return 0;
err_dummy_reporter_destroy: err_dummy_reporter_destroy:
devlink_health_reporter_destroy(health->dummy_reporter); devl_health_reporter_destroy(health->dummy_reporter);
err_empty_reporter_destroy: err_empty_reporter_destroy:
devlink_health_reporter_destroy(health->empty_reporter); devl_health_reporter_destroy(health->empty_reporter);
return err; return err;
} }
...@@ -278,6 +278,6 @@ void nsim_dev_health_exit(struct nsim_dev *nsim_dev) ...@@ -278,6 +278,6 @@ void nsim_dev_health_exit(struct nsim_dev *nsim_dev)
debugfs_remove_recursive(health->ddir); debugfs_remove_recursive(health->ddir);
kfree(health->recovered_break_msg); kfree(health->recovered_break_msg);
devlink_health_reporter_destroy(health->dummy_reporter); devl_health_reporter_destroy(health->dummy_reporter);
devlink_health_reporter_destroy(health->empty_reporter); devl_health_reporter_destroy(health->empty_reporter);
} }
...@@ -554,10 +554,6 @@ enum { ...@@ -554,10 +554,6 @@ enum {
* creation/deletion on drivers rescan. Unset during device attach. * creation/deletion on drivers rescan. Unset during device attach.
*/ */
MLX5_PRIV_FLAGS_DETACH = 1 << 2, MLX5_PRIV_FLAGS_DETACH = 1 << 2,
/* Distinguish between mlx5e_probe/remove called by module init/cleanup
* and called by other flows which can already hold devlink lock
*/
MLX5_PRIV_FLAGS_MLX5E_LOCKED_FLOW = 1 << 3,
}; };
struct mlx5_adev { struct mlx5_adev {
......
...@@ -146,7 +146,6 @@ struct devlink_port { ...@@ -146,7 +146,6 @@ struct devlink_port {
initialized:1; initialized:1;
struct delayed_work type_warn_dw; struct delayed_work type_warn_dw;
struct list_head reporter_list; struct list_head reporter_list;
struct mutex reporters_lock; /* Protects reporter_list */
struct devlink_rate *devlink_rate; struct devlink_rate *devlink_rate;
struct devlink_linecard *linecard; struct devlink_linecard *linecard;
...@@ -1687,9 +1686,9 @@ void devl_rate_nodes_destroy(struct devlink *devlink); ...@@ -1687,9 +1686,9 @@ void devl_rate_nodes_destroy(struct devlink *devlink);
void devlink_port_linecard_set(struct devlink_port *devlink_port, void devlink_port_linecard_set(struct devlink_port *devlink_port,
struct devlink_linecard *linecard); struct devlink_linecard *linecard);
struct devlink_linecard * struct devlink_linecard *
devlink_linecard_create(struct devlink *devlink, unsigned int linecard_index, devl_linecard_create(struct devlink *devlink, unsigned int linecard_index,
const struct devlink_linecard_ops *ops, void *priv); const struct devlink_linecard_ops *ops, void *priv);
void devlink_linecard_destroy(struct devlink_linecard *linecard); void devl_linecard_destroy(struct devlink_linecard *linecard);
void devlink_linecard_provision_set(struct devlink_linecard *linecard, void devlink_linecard_provision_set(struct devlink_linecard *linecard,
const char *type); const char *type);
void devlink_linecard_provision_clear(struct devlink_linecard *linecard); void devlink_linecard_provision_clear(struct devlink_linecard *linecard);
...@@ -1865,20 +1864,30 @@ int devlink_fmsg_binary_pair_put(struct devlink_fmsg *fmsg, const char *name, ...@@ -1865,20 +1864,30 @@ int devlink_fmsg_binary_pair_put(struct devlink_fmsg *fmsg, const char *name,
const void *value, u32 value_len); const void *value, u32 value_len);
struct devlink_health_reporter * struct devlink_health_reporter *
devlink_health_reporter_create(struct devlink *devlink, devl_port_health_reporter_create(struct devlink_port *port,
const struct devlink_health_reporter_ops *ops, const struct devlink_health_reporter_ops *ops,
u64 graceful_period, void *priv); u64 graceful_period, void *priv);
struct devlink_health_reporter * struct devlink_health_reporter *
devlink_port_health_reporter_create(struct devlink_port *port, devlink_port_health_reporter_create(struct devlink_port *port,
const struct devlink_health_reporter_ops *ops, const struct devlink_health_reporter_ops *ops,
u64 graceful_period, void *priv); u64 graceful_period, void *priv);
struct devlink_health_reporter *
devl_health_reporter_create(struct devlink *devlink,
const struct devlink_health_reporter_ops *ops,
u64 graceful_period, void *priv);
struct devlink_health_reporter *
devlink_health_reporter_create(struct devlink *devlink,
const struct devlink_health_reporter_ops *ops,
u64 graceful_period, void *priv);
void void
devlink_health_reporter_destroy(struct devlink_health_reporter *reporter); devl_health_reporter_destroy(struct devlink_health_reporter *reporter);
void void
devlink_port_health_reporter_destroy(struct devlink_health_reporter *reporter); devlink_health_reporter_destroy(struct devlink_health_reporter *reporter);
void * void *
devlink_health_reporter_priv(struct devlink_health_reporter *reporter); devlink_health_reporter_priv(struct devlink_health_reporter *reporter);
......
...@@ -246,8 +246,6 @@ struct devlink *devlink_alloc_ns(const struct devlink_ops *ops, ...@@ -246,8 +246,6 @@ struct devlink *devlink_alloc_ns(const struct devlink_ops *ops,
lockdep_register_key(&devlink->lock_key); lockdep_register_key(&devlink->lock_key);
mutex_init(&devlink->lock); mutex_init(&devlink->lock);
lockdep_set_class(&devlink->lock, &devlink->lock_key); lockdep_set_class(&devlink->lock, &devlink->lock_key);
mutex_init(&devlink->reporters_lock);
mutex_init(&devlink->linecards_lock);
refcount_set(&devlink->refcount, 1); refcount_set(&devlink->refcount, 1);
return devlink; return devlink;
...@@ -269,8 +267,6 @@ void devlink_free(struct devlink *devlink) ...@@ -269,8 +267,6 @@ void devlink_free(struct devlink *devlink)
{ {
ASSERT_DEVLINK_NOT_REGISTERED(devlink); ASSERT_DEVLINK_NOT_REGISTERED(devlink);
mutex_destroy(&devlink->linecards_lock);
mutex_destroy(&devlink->reporters_lock);
WARN_ON(!list_empty(&devlink->trap_policer_list)); WARN_ON(!list_empty(&devlink->trap_policer_list));
WARN_ON(!list_empty(&devlink->trap_group_list)); WARN_ON(!list_empty(&devlink->trap_group_list));
WARN_ON(!list_empty(&devlink->trap_list)); WARN_ON(!list_empty(&devlink->trap_list));
......
...@@ -32,13 +32,11 @@ struct devlink { ...@@ -32,13 +32,11 @@ struct devlink {
struct list_head param_list; struct list_head param_list;
struct list_head region_list; struct list_head region_list;
struct list_head reporter_list; struct list_head reporter_list;
struct mutex reporters_lock; /* protects reporter_list */
struct devlink_dpipe_headers *dpipe_headers; struct devlink_dpipe_headers *dpipe_headers;
struct list_head trap_list; struct list_head trap_list;
struct list_head trap_group_list; struct list_head trap_group_list;
struct list_head trap_policer_list; struct list_head trap_policer_list;
struct list_head linecard_list; struct list_head linecard_list;
struct mutex linecards_lock; /* protects linecard_list */
const struct devlink_ops *ops; const struct devlink_ops *ops;
u64 features; u64 features;
struct xarray snapshot_ids; struct xarray snapshot_ids;
...@@ -87,9 +85,7 @@ struct devlink *devlinks_xa_find_get(struct net *net, unsigned long *indexp); ...@@ -87,9 +85,7 @@ struct devlink *devlinks_xa_find_get(struct net *net, unsigned long *indexp);
static inline bool devl_is_registered(struct devlink *devlink) static inline bool devl_is_registered(struct devlink *devlink)
{ {
/* To prevent races the caller must hold the instance lock devl_assert_locked(devlink);
* or another lock taken during unregistration.
*/
return xa_get_mark(&devlinks, devlink->index, DEVLINK_REGISTERED); return xa_get_mark(&devlinks, devlink->index, DEVLINK_REGISTERED);
} }
...@@ -125,17 +121,6 @@ struct devlink_gen_cmd { ...@@ -125,17 +121,6 @@ struct devlink_gen_cmd {
struct netlink_callback *cb); struct netlink_callback *cb);
}; };
/* Iterate over registered devlink instances for devlink dump.
* devlink_put() needs to be called for each iterated devlink pointer
* in loop body in order to release the reference.
* Note: this is NOT a generic iterator, it makes assumptions about the use
* of @state and can only be used once per dumpit implementation.
*/
#define devlink_dump_for_each_instance_get(msg, state, devlink) \
for (; (devlink = devlinks_xa_find_get(sock_net(msg->sk), \
&state->instance)); \
state->instance++, state->idx = 0)
extern const struct genl_small_ops devlink_nl_ops[56]; extern const struct genl_small_ops devlink_nl_ops[56];
struct devlink * struct devlink *
...@@ -166,9 +151,11 @@ extern const struct devlink_gen_cmd devl_gen_selftests; ...@@ -166,9 +151,11 @@ extern const struct devlink_gen_cmd devl_gen_selftests;
extern const struct devlink_gen_cmd devl_gen_param; extern const struct devlink_gen_cmd devl_gen_param;
extern const struct devlink_gen_cmd devl_gen_region; extern const struct devlink_gen_cmd devl_gen_region;
extern const struct devlink_gen_cmd devl_gen_info; extern const struct devlink_gen_cmd devl_gen_info;
extern const struct devlink_gen_cmd devl_gen_health_reporter;
extern const struct devlink_gen_cmd devl_gen_trap; extern const struct devlink_gen_cmd devl_gen_trap;
extern const struct devlink_gen_cmd devl_gen_trap_group; extern const struct devlink_gen_cmd devl_gen_trap_group;
extern const struct devlink_gen_cmd devl_gen_trap_policer; extern const struct devlink_gen_cmd devl_gen_trap_policer;
extern const struct devlink_gen_cmd devl_gen_linecard;
/* Ports */ /* Ports */
int devlink_port_netdevice_event(struct notifier_block *nb, int devlink_port_netdevice_event(struct notifier_block *nb,
...@@ -194,7 +181,6 @@ struct devlink_linecard; ...@@ -194,7 +181,6 @@ struct devlink_linecard;
struct devlink_linecard * struct devlink_linecard *
devlink_linecard_get_from_info(struct devlink *devlink, struct genl_info *info); devlink_linecard_get_from_info(struct devlink *devlink, struct genl_info *info);
void devlink_linecard_put(struct devlink_linecard *linecard);
/* Rates */ /* Rates */
extern const struct devlink_gen_cmd devl_gen_rate_get; extern const struct devlink_gen_cmd devl_gen_rate_get;
......
...@@ -37,7 +37,6 @@ struct devlink_linecard { ...@@ -37,7 +37,6 @@ struct devlink_linecard {
struct list_head list; struct list_head list;
struct devlink *devlink; struct devlink *devlink;
unsigned int index; unsigned int index;
refcount_t refcount;
const struct devlink_linecard_ops *ops; const struct devlink_linecard_ops *ops;
void *priv; void *priv;
enum devlink_linecard_state state; enum devlink_linecard_state state;
...@@ -282,11 +281,7 @@ devlink_linecard_get_from_attrs(struct devlink *devlink, struct nlattr **attrs) ...@@ -282,11 +281,7 @@ devlink_linecard_get_from_attrs(struct devlink *devlink, struct nlattr **attrs)
u32 linecard_index = nla_get_u32(attrs[DEVLINK_ATTR_LINECARD_INDEX]); u32 linecard_index = nla_get_u32(attrs[DEVLINK_ATTR_LINECARD_INDEX]);
struct devlink_linecard *linecard; struct devlink_linecard *linecard;
mutex_lock(&devlink->linecards_lock);
linecard = devlink_linecard_get_by_index(devlink, linecard_index); linecard = devlink_linecard_get_by_index(devlink, linecard_index);
if (linecard)
refcount_inc(&linecard->refcount);
mutex_unlock(&devlink->linecards_lock);
if (!linecard) if (!linecard)
return ERR_PTR(-ENODEV); return ERR_PTR(-ENODEV);
return linecard; return linecard;
...@@ -300,14 +295,6 @@ devlink_linecard_get_from_info(struct devlink *devlink, struct genl_info *info) ...@@ -300,14 +295,6 @@ devlink_linecard_get_from_info(struct devlink *devlink, struct genl_info *info)
return devlink_linecard_get_from_attrs(devlink, info->attrs); return devlink_linecard_get_from_attrs(devlink, info->attrs);
} }
void devlink_linecard_put(struct devlink_linecard *linecard)
{
if (refcount_dec_and_test(&linecard->refcount)) {
mutex_destroy(&linecard->state_lock);
kfree(linecard);
}
}
struct devlink_sb { struct devlink_sb {
struct list_head list; struct list_head list;
unsigned int index; unsigned int index;
...@@ -2118,50 +2105,42 @@ static int devlink_nl_cmd_linecard_get_doit(struct sk_buff *skb, ...@@ -2118,50 +2105,42 @@ static int devlink_nl_cmd_linecard_get_doit(struct sk_buff *skb,
return genlmsg_reply(msg, info); return genlmsg_reply(msg, info);
} }
static int devlink_nl_cmd_linecard_get_dumpit(struct sk_buff *msg, static int devlink_nl_cmd_linecard_get_dump_one(struct sk_buff *msg,
struct netlink_callback *cb) struct devlink *devlink,
struct netlink_callback *cb)
{ {
struct devlink_nl_dump_state *state = devlink_dump_state(cb); struct devlink_nl_dump_state *state = devlink_dump_state(cb);
struct devlink_linecard *linecard; struct devlink_linecard *linecard;
struct devlink *devlink; int idx = 0;
int err; int err = 0;
devlink_dump_for_each_instance_get(msg, state, devlink) {
int idx = 0;
mutex_lock(&devlink->linecards_lock);
if (!devl_is_registered(devlink))
goto next_devlink;
list_for_each_entry(linecard, &devlink->linecard_list, list) { list_for_each_entry(linecard, &devlink->linecard_list, list) {
if (idx < state->idx) { if (idx < state->idx) {
idx++;
continue;
}
mutex_lock(&linecard->state_lock);
err = devlink_nl_linecard_fill(msg, devlink, linecard,
DEVLINK_CMD_LINECARD_NEW,
NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq,
NLM_F_MULTI,
cb->extack);
mutex_unlock(&linecard->state_lock);
if (err) {
mutex_unlock(&devlink->linecards_lock);
devlink_put(devlink);
state->idx = idx;
goto out;
}
idx++; idx++;
continue;
} }
next_devlink: mutex_lock(&linecard->state_lock);
mutex_unlock(&devlink->linecards_lock); err = devlink_nl_linecard_fill(msg, devlink, linecard,
devlink_put(devlink); DEVLINK_CMD_LINECARD_NEW,
NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq,
NLM_F_MULTI,
cb->extack);
mutex_unlock(&linecard->state_lock);
if (err) {
state->idx = idx;
break;
}
idx++;
} }
out:
return msg->len; return err;
} }
const struct devlink_gen_cmd devl_gen_linecard = {
.dump_one = devlink_nl_cmd_linecard_get_dump_one,
};
static struct devlink_linecard_type * static struct devlink_linecard_type *
devlink_linecard_type_lookup(struct devlink_linecard *linecard, devlink_linecard_type_lookup(struct devlink_linecard *linecard,
const char *type) const char *type)
...@@ -7282,7 +7261,6 @@ struct devlink_health_reporter { ...@@ -7282,7 +7261,6 @@ struct devlink_health_reporter {
u64 error_count; u64 error_count;
u64 recovery_count; u64 recovery_count;
u64 last_recovery_ts; u64 last_recovery_ts;
refcount_t refcount;
}; };
void * void *
...@@ -7294,12 +7272,10 @@ EXPORT_SYMBOL_GPL(devlink_health_reporter_priv); ...@@ -7294,12 +7272,10 @@ EXPORT_SYMBOL_GPL(devlink_health_reporter_priv);
static struct devlink_health_reporter * static struct devlink_health_reporter *
__devlink_health_reporter_find_by_name(struct list_head *reporter_list, __devlink_health_reporter_find_by_name(struct list_head *reporter_list,
struct mutex *list_lock,
const char *reporter_name) const char *reporter_name)
{ {
struct devlink_health_reporter *reporter; struct devlink_health_reporter *reporter;
lockdep_assert_held(list_lock);
list_for_each_entry(reporter, reporter_list, list) list_for_each_entry(reporter, reporter_list, list)
if (!strcmp(reporter->ops->name, reporter_name)) if (!strcmp(reporter->ops->name, reporter_name))
return reporter; return reporter;
...@@ -7311,7 +7287,6 @@ devlink_health_reporter_find_by_name(struct devlink *devlink, ...@@ -7311,7 +7287,6 @@ devlink_health_reporter_find_by_name(struct devlink *devlink,
const char *reporter_name) const char *reporter_name)
{ {
return __devlink_health_reporter_find_by_name(&devlink->reporter_list, return __devlink_health_reporter_find_by_name(&devlink->reporter_list,
&devlink->reporters_lock,
reporter_name); reporter_name);
} }
...@@ -7320,7 +7295,6 @@ devlink_port_health_reporter_find_by_name(struct devlink_port *devlink_port, ...@@ -7320,7 +7295,6 @@ devlink_port_health_reporter_find_by_name(struct devlink_port *devlink_port,
const char *reporter_name) const char *reporter_name)
{ {
return __devlink_health_reporter_find_by_name(&devlink_port->reporter_list, return __devlink_health_reporter_find_by_name(&devlink_port->reporter_list,
&devlink_port->reporters_lock,
reporter_name); reporter_name);
} }
...@@ -7345,13 +7319,12 @@ __devlink_health_reporter_create(struct devlink *devlink, ...@@ -7345,13 +7319,12 @@ __devlink_health_reporter_create(struct devlink *devlink,
reporter->auto_recover = !!ops->recover; reporter->auto_recover = !!ops->recover;
reporter->auto_dump = !!ops->dump; reporter->auto_dump = !!ops->dump;
mutex_init(&reporter->dump_lock); mutex_init(&reporter->dump_lock);
refcount_set(&reporter->refcount, 1);
return reporter; return reporter;
} }
/** /**
* devlink_port_health_reporter_create - create devlink health reporter for * devl_port_health_reporter_create - create devlink health reporter for
* specified port instance * specified port instance
* *
* @port: devlink_port which should contain the new reporter * @port: devlink_port which should contain the new reporter
* @ops: ops * @ops: ops
...@@ -7359,34 +7332,47 @@ __devlink_health_reporter_create(struct devlink *devlink, ...@@ -7359,34 +7332,47 @@ __devlink_health_reporter_create(struct devlink *devlink,
* @priv: priv * @priv: priv
*/ */
struct devlink_health_reporter * struct devlink_health_reporter *
devlink_port_health_reporter_create(struct devlink_port *port, devl_port_health_reporter_create(struct devlink_port *port,
const struct devlink_health_reporter_ops *ops, const struct devlink_health_reporter_ops *ops,
u64 graceful_period, void *priv) u64 graceful_period, void *priv)
{ {
struct devlink_health_reporter *reporter; struct devlink_health_reporter *reporter;
mutex_lock(&port->reporters_lock); devl_assert_locked(port->devlink);
if (__devlink_health_reporter_find_by_name(&port->reporter_list, if (__devlink_health_reporter_find_by_name(&port->reporter_list,
&port->reporters_lock, ops->name)) { ops->name))
reporter = ERR_PTR(-EEXIST); return ERR_PTR(-EEXIST);
goto unlock;
}
reporter = __devlink_health_reporter_create(port->devlink, ops, reporter = __devlink_health_reporter_create(port->devlink, ops,
graceful_period, priv); graceful_period, priv);
if (IS_ERR(reporter)) if (IS_ERR(reporter))
goto unlock; return reporter;
reporter->devlink_port = port; reporter->devlink_port = port;
list_add_tail(&reporter->list, &port->reporter_list); list_add_tail(&reporter->list, &port->reporter_list);
unlock: return reporter;
mutex_unlock(&port->reporters_lock); }
EXPORT_SYMBOL_GPL(devl_port_health_reporter_create);
struct devlink_health_reporter *
devlink_port_health_reporter_create(struct devlink_port *port,
const struct devlink_health_reporter_ops *ops,
u64 graceful_period, void *priv)
{
struct devlink_health_reporter *reporter;
struct devlink *devlink = port->devlink;
devl_lock(devlink);
reporter = devl_port_health_reporter_create(port, ops,
graceful_period, priv);
devl_unlock(devlink);
return reporter; return reporter;
} }
EXPORT_SYMBOL_GPL(devlink_port_health_reporter_create); EXPORT_SYMBOL_GPL(devlink_port_health_reporter_create);
/** /**
* devlink_health_reporter_create - create devlink health reporter * devl_health_reporter_create - create devlink health reporter
* *
* @devlink: devlink * @devlink: devlink
* @ops: ops * @ops: ops
...@@ -7394,26 +7380,38 @@ EXPORT_SYMBOL_GPL(devlink_port_health_reporter_create); ...@@ -7394,26 +7380,38 @@ EXPORT_SYMBOL_GPL(devlink_port_health_reporter_create);
* @priv: priv * @priv: priv
*/ */
struct devlink_health_reporter * struct devlink_health_reporter *
devlink_health_reporter_create(struct devlink *devlink, devl_health_reporter_create(struct devlink *devlink,
const struct devlink_health_reporter_ops *ops, const struct devlink_health_reporter_ops *ops,
u64 graceful_period, void *priv) u64 graceful_period, void *priv)
{ {
struct devlink_health_reporter *reporter; struct devlink_health_reporter *reporter;
mutex_lock(&devlink->reporters_lock); devl_assert_locked(devlink);
if (devlink_health_reporter_find_by_name(devlink, ops->name)) {
reporter = ERR_PTR(-EEXIST); if (devlink_health_reporter_find_by_name(devlink, ops->name))
goto unlock; return ERR_PTR(-EEXIST);
}
reporter = __devlink_health_reporter_create(devlink, ops, reporter = __devlink_health_reporter_create(devlink, ops,
graceful_period, priv); graceful_period, priv);
if (IS_ERR(reporter)) if (IS_ERR(reporter))
goto unlock; return reporter;
list_add_tail(&reporter->list, &devlink->reporter_list); list_add_tail(&reporter->list, &devlink->reporter_list);
unlock: return reporter;
mutex_unlock(&devlink->reporters_lock); }
EXPORT_SYMBOL_GPL(devl_health_reporter_create);
struct devlink_health_reporter *
devlink_health_reporter_create(struct devlink *devlink,
const struct devlink_health_reporter_ops *ops,
u64 graceful_period, void *priv)
{
struct devlink_health_reporter *reporter;
devl_lock(devlink);
reporter = devl_health_reporter_create(devlink, ops,
graceful_period, priv);
devl_unlock(devlink);
return reporter; return reporter;
} }
EXPORT_SYMBOL_GPL(devlink_health_reporter_create); EXPORT_SYMBOL_GPL(devlink_health_reporter_create);
...@@ -7427,51 +7425,31 @@ devlink_health_reporter_free(struct devlink_health_reporter *reporter) ...@@ -7427,51 +7425,31 @@ devlink_health_reporter_free(struct devlink_health_reporter *reporter)
kfree(reporter); kfree(reporter);
} }
static void
devlink_health_reporter_put(struct devlink_health_reporter *reporter)
{
if (refcount_dec_and_test(&reporter->refcount))
devlink_health_reporter_free(reporter);
}
static void
__devlink_health_reporter_destroy(struct devlink_health_reporter *reporter)
{
list_del(&reporter->list);
devlink_health_reporter_put(reporter);
}
/** /**
* devlink_health_reporter_destroy - destroy devlink health reporter * devl_health_reporter_destroy - destroy devlink health reporter
* *
* @reporter: devlink health reporter to destroy * @reporter: devlink health reporter to destroy
*/ */
void void
devlink_health_reporter_destroy(struct devlink_health_reporter *reporter) devl_health_reporter_destroy(struct devlink_health_reporter *reporter)
{ {
struct mutex *lock = &reporter->devlink->reporters_lock; devl_assert_locked(reporter->devlink);
mutex_lock(lock); list_del(&reporter->list);
__devlink_health_reporter_destroy(reporter); devlink_health_reporter_free(reporter);
mutex_unlock(lock);
} }
EXPORT_SYMBOL_GPL(devlink_health_reporter_destroy); EXPORT_SYMBOL_GPL(devl_health_reporter_destroy);
/**
* devlink_port_health_reporter_destroy - destroy devlink port health reporter
*
* @reporter: devlink health reporter to destroy
*/
void void
devlink_port_health_reporter_destroy(struct devlink_health_reporter *reporter) devlink_health_reporter_destroy(struct devlink_health_reporter *reporter)
{ {
struct mutex *lock = &reporter->devlink_port->reporters_lock; struct devlink *devlink = reporter->devlink;
mutex_lock(lock); devl_lock(devlink);
__devlink_health_reporter_destroy(reporter); devl_health_reporter_destroy(reporter);
mutex_unlock(lock); devl_unlock(devlink);
} }
EXPORT_SYMBOL_GPL(devlink_port_health_reporter_destroy); EXPORT_SYMBOL_GPL(devlink_health_reporter_destroy);
static int static int
devlink_nl_health_reporter_fill(struct sk_buff *msg, devlink_nl_health_reporter_fill(struct sk_buff *msg,
...@@ -7702,7 +7680,6 @@ static struct devlink_health_reporter * ...@@ -7702,7 +7680,6 @@ static struct devlink_health_reporter *
devlink_health_reporter_get_from_attrs(struct devlink *devlink, devlink_health_reporter_get_from_attrs(struct devlink *devlink,
struct nlattr **attrs) struct nlattr **attrs)
{ {
struct devlink_health_reporter *reporter;
struct devlink_port *devlink_port; struct devlink_port *devlink_port;
char *reporter_name; char *reporter_name;
...@@ -7711,21 +7688,12 @@ devlink_health_reporter_get_from_attrs(struct devlink *devlink, ...@@ -7711,21 +7688,12 @@ devlink_health_reporter_get_from_attrs(struct devlink *devlink,
reporter_name = nla_data(attrs[DEVLINK_ATTR_HEALTH_REPORTER_NAME]); reporter_name = nla_data(attrs[DEVLINK_ATTR_HEALTH_REPORTER_NAME]);
devlink_port = devlink_port_get_from_attrs(devlink, attrs); devlink_port = devlink_port_get_from_attrs(devlink, attrs);
if (IS_ERR(devlink_port)) { if (IS_ERR(devlink_port))
mutex_lock(&devlink->reporters_lock); return devlink_health_reporter_find_by_name(devlink,
reporter = devlink_health_reporter_find_by_name(devlink, reporter_name); reporter_name);
if (reporter) else
refcount_inc(&reporter->refcount); return devlink_port_health_reporter_find_by_name(devlink_port,
mutex_unlock(&devlink->reporters_lock); reporter_name);
} else {
mutex_lock(&devlink_port->reporters_lock);
reporter = devlink_port_health_reporter_find_by_name(devlink_port, reporter_name);
if (reporter)
refcount_inc(&reporter->refcount);
mutex_unlock(&devlink_port->reporters_lock);
}
return reporter;
} }
static struct devlink_health_reporter * static struct devlink_health_reporter *
...@@ -7784,10 +7752,8 @@ static int devlink_nl_cmd_health_reporter_get_doit(struct sk_buff *skb, ...@@ -7784,10 +7752,8 @@ static int devlink_nl_cmd_health_reporter_get_doit(struct sk_buff *skb,
return -EINVAL; return -EINVAL;
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
if (!msg) { if (!msg)
err = -ENOMEM; return -ENOMEM;
goto out;
}
err = devlink_nl_health_reporter_fill(msg, reporter, err = devlink_nl_health_reporter_fill(msg, reporter,
DEVLINK_CMD_HEALTH_REPORTER_GET, DEVLINK_CMD_HEALTH_REPORTER_GET,
...@@ -7795,98 +7761,72 @@ static int devlink_nl_cmd_health_reporter_get_doit(struct sk_buff *skb, ...@@ -7795,98 +7761,72 @@ static int devlink_nl_cmd_health_reporter_get_doit(struct sk_buff *skb,
0); 0);
if (err) { if (err) {
nlmsg_free(msg); nlmsg_free(msg);
goto out; return err;
} }
err = genlmsg_reply(msg, info); return genlmsg_reply(msg, info);
out:
devlink_health_reporter_put(reporter);
return err;
} }
static int static int
devlink_nl_cmd_health_reporter_get_dumpit(struct sk_buff *msg, devlink_nl_cmd_health_reporter_get_dump_one(struct sk_buff *msg,
struct netlink_callback *cb) struct devlink *devlink,
struct netlink_callback *cb)
{ {
struct devlink_nl_dump_state *state = devlink_dump_state(cb); struct devlink_nl_dump_state *state = devlink_dump_state(cb);
struct devlink *devlink; struct devlink_health_reporter *reporter;
struct devlink_port *port;
unsigned long port_index;
int idx = 0;
int err; int err;
devlink_dump_for_each_instance_get(msg, state, devlink) { list_for_each_entry(reporter, &devlink->reporter_list, list) {
struct devlink_health_reporter *reporter; if (idx < state->idx) {
struct devlink_port *port; idx++;
unsigned long port_index;
int idx = 0;
mutex_lock(&devlink->reporters_lock);
if (!devl_is_registered(devlink)) {
mutex_unlock(&devlink->reporters_lock);
devlink_put(devlink);
continue; continue;
} }
err = devlink_nl_health_reporter_fill(msg, reporter,
list_for_each_entry(reporter, &devlink->reporter_list, DEVLINK_CMD_HEALTH_REPORTER_GET,
list) { NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq,
NLM_F_MULTI);
if (err) {
state->idx = idx;
return err;
}
idx++;
}
xa_for_each(&devlink->ports, port_index, port) {
list_for_each_entry(reporter, &port->reporter_list, list) {
if (idx < state->idx) { if (idx < state->idx) {
idx++; idx++;
continue; continue;
} }
err = devlink_nl_health_reporter_fill( err = devlink_nl_health_reporter_fill(msg, reporter,
msg, reporter, DEVLINK_CMD_HEALTH_REPORTER_GET, DEVLINK_CMD_HEALTH_REPORTER_GET,
NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, NETLINK_CB(cb->skb).portid,
NLM_F_MULTI); cb->nlh->nlmsg_seq,
NLM_F_MULTI);
if (err) { if (err) {
mutex_unlock(&devlink->reporters_lock);
devlink_put(devlink);
state->idx = idx; state->idx = idx;
goto out; return err;
} }
idx++; idx++;
} }
mutex_unlock(&devlink->reporters_lock);
devl_lock(devlink);
if (!devl_is_registered(devlink))
goto next_devlink;
xa_for_each(&devlink->ports, port_index, port) {
mutex_lock(&port->reporters_lock);
list_for_each_entry(reporter, &port->reporter_list, list) {
if (idx < state->idx) {
idx++;
continue;
}
err = devlink_nl_health_reporter_fill(
msg, reporter,
DEVLINK_CMD_HEALTH_REPORTER_GET,
NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq, NLM_F_MULTI);
if (err) {
mutex_unlock(&port->reporters_lock);
devl_unlock(devlink);
devlink_put(devlink);
state->idx = idx;
goto out;
}
idx++;
}
mutex_unlock(&port->reporters_lock);
}
next_devlink:
devl_unlock(devlink);
devlink_put(devlink);
} }
out:
return msg->len; return 0;
} }
const struct devlink_gen_cmd devl_gen_health_reporter = {
.dump_one = devlink_nl_cmd_health_reporter_get_dump_one,
};
static int static int
devlink_nl_cmd_health_reporter_set_doit(struct sk_buff *skb, devlink_nl_cmd_health_reporter_set_doit(struct sk_buff *skb,
struct genl_info *info) struct genl_info *info)
{ {
struct devlink *devlink = info->user_ptr[0]; struct devlink *devlink = info->user_ptr[0];
struct devlink_health_reporter *reporter; struct devlink_health_reporter *reporter;
int err;
reporter = devlink_health_reporter_get_from_info(devlink, info); reporter = devlink_health_reporter_get_from_info(devlink, info);
if (!reporter) if (!reporter)
...@@ -7894,15 +7834,12 @@ devlink_nl_cmd_health_reporter_set_doit(struct sk_buff *skb, ...@@ -7894,15 +7834,12 @@ devlink_nl_cmd_health_reporter_set_doit(struct sk_buff *skb,
if (!reporter->ops->recover && if (!reporter->ops->recover &&
(info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD] || (info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD] ||
info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER])) { info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER]))
err = -EOPNOTSUPP; return -EOPNOTSUPP;
goto out;
}
if (!reporter->ops->dump && if (!reporter->ops->dump &&
info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_DUMP]) { info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_DUMP])
err = -EOPNOTSUPP; return -EOPNOTSUPP;
goto out;
}
if (info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD]) if (info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD])
reporter->graceful_period = reporter->graceful_period =
...@@ -7916,11 +7853,7 @@ devlink_nl_cmd_health_reporter_set_doit(struct sk_buff *skb, ...@@ -7916,11 +7853,7 @@ devlink_nl_cmd_health_reporter_set_doit(struct sk_buff *skb,
reporter->auto_dump = reporter->auto_dump =
nla_get_u8(info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_DUMP]); nla_get_u8(info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_DUMP]);
devlink_health_reporter_put(reporter);
return 0; return 0;
out:
devlink_health_reporter_put(reporter);
return err;
} }
static int devlink_nl_cmd_health_reporter_recover_doit(struct sk_buff *skb, static int devlink_nl_cmd_health_reporter_recover_doit(struct sk_buff *skb,
...@@ -7928,16 +7861,12 @@ static int devlink_nl_cmd_health_reporter_recover_doit(struct sk_buff *skb, ...@@ -7928,16 +7861,12 @@ static int devlink_nl_cmd_health_reporter_recover_doit(struct sk_buff *skb,
{ {
struct devlink *devlink = info->user_ptr[0]; struct devlink *devlink = info->user_ptr[0];
struct devlink_health_reporter *reporter; struct devlink_health_reporter *reporter;
int err;
reporter = devlink_health_reporter_get_from_info(devlink, info); reporter = devlink_health_reporter_get_from_info(devlink, info);
if (!reporter) if (!reporter)
return -EINVAL; return -EINVAL;
err = devlink_health_reporter_recover(reporter, NULL, info->extack); return devlink_health_reporter_recover(reporter, NULL, info->extack);
devlink_health_reporter_put(reporter);
return err;
} }
static int devlink_nl_cmd_health_reporter_diagnose_doit(struct sk_buff *skb, static int devlink_nl_cmd_health_reporter_diagnose_doit(struct sk_buff *skb,
...@@ -7952,36 +7881,27 @@ static int devlink_nl_cmd_health_reporter_diagnose_doit(struct sk_buff *skb, ...@@ -7952,36 +7881,27 @@ static int devlink_nl_cmd_health_reporter_diagnose_doit(struct sk_buff *skb,
if (!reporter) if (!reporter)
return -EINVAL; return -EINVAL;
if (!reporter->ops->diagnose) { if (!reporter->ops->diagnose)
devlink_health_reporter_put(reporter);
return -EOPNOTSUPP; return -EOPNOTSUPP;
}
fmsg = devlink_fmsg_alloc(); fmsg = devlink_fmsg_alloc();
if (!fmsg) { if (!fmsg)
devlink_health_reporter_put(reporter);
return -ENOMEM; return -ENOMEM;
}
err = devlink_fmsg_obj_nest_start(fmsg); err = devlink_fmsg_obj_nest_start(fmsg);
if (err) if (err)
goto out; return err;
err = reporter->ops->diagnose(reporter, fmsg, info->extack); err = reporter->ops->diagnose(reporter, fmsg, info->extack);
if (err) if (err)
goto out; return err;
err = devlink_fmsg_obj_nest_end(fmsg); err = devlink_fmsg_obj_nest_end(fmsg);
if (err) if (err)
goto out; return err;
err = devlink_fmsg_snd(fmsg, info,
DEVLINK_CMD_HEALTH_REPORTER_DIAGNOSE, 0);
out: return devlink_fmsg_snd(fmsg, info,
devlink_fmsg_free(fmsg); DEVLINK_CMD_HEALTH_REPORTER_DIAGNOSE, 0);
devlink_health_reporter_put(reporter);
return err;
} }
static int static int
...@@ -7996,10 +7916,9 @@ devlink_nl_cmd_health_reporter_dump_get_dumpit(struct sk_buff *skb, ...@@ -7996,10 +7916,9 @@ devlink_nl_cmd_health_reporter_dump_get_dumpit(struct sk_buff *skb,
if (!reporter) if (!reporter)
return -EINVAL; return -EINVAL;
if (!reporter->ops->dump) { if (!reporter->ops->dump)
err = -EOPNOTSUPP; return -EOPNOTSUPP;
goto out;
}
mutex_lock(&reporter->dump_lock); mutex_lock(&reporter->dump_lock);
if (!state->idx) { if (!state->idx) {
err = devlink_health_do_dump(reporter, NULL, cb->extack); err = devlink_health_do_dump(reporter, NULL, cb->extack);
...@@ -8017,8 +7936,6 @@ devlink_nl_cmd_health_reporter_dump_get_dumpit(struct sk_buff *skb, ...@@ -8017,8 +7936,6 @@ devlink_nl_cmd_health_reporter_dump_get_dumpit(struct sk_buff *skb,
DEVLINK_CMD_HEALTH_REPORTER_DUMP_GET); DEVLINK_CMD_HEALTH_REPORTER_DUMP_GET);
unlock: unlock:
mutex_unlock(&reporter->dump_lock); mutex_unlock(&reporter->dump_lock);
out:
devlink_health_reporter_put(reporter);
return err; return err;
} }
...@@ -8033,15 +7950,12 @@ devlink_nl_cmd_health_reporter_dump_clear_doit(struct sk_buff *skb, ...@@ -8033,15 +7950,12 @@ devlink_nl_cmd_health_reporter_dump_clear_doit(struct sk_buff *skb,
if (!reporter) if (!reporter)
return -EINVAL; return -EINVAL;
if (!reporter->ops->dump) { if (!reporter->ops->dump)
devlink_health_reporter_put(reporter);
return -EOPNOTSUPP; return -EOPNOTSUPP;
}
mutex_lock(&reporter->dump_lock); mutex_lock(&reporter->dump_lock);
devlink_health_dump_clear(reporter); devlink_health_dump_clear(reporter);
mutex_unlock(&reporter->dump_lock); mutex_unlock(&reporter->dump_lock);
devlink_health_reporter_put(reporter);
return 0; return 0;
} }
...@@ -8050,21 +7964,15 @@ static int devlink_nl_cmd_health_reporter_test_doit(struct sk_buff *skb, ...@@ -8050,21 +7964,15 @@ static int devlink_nl_cmd_health_reporter_test_doit(struct sk_buff *skb,
{ {
struct devlink *devlink = info->user_ptr[0]; struct devlink *devlink = info->user_ptr[0];
struct devlink_health_reporter *reporter; struct devlink_health_reporter *reporter;
int err;
reporter = devlink_health_reporter_get_from_info(devlink, info); reporter = devlink_health_reporter_get_from_info(devlink, info);
if (!reporter) if (!reporter)
return -EINVAL; return -EINVAL;
if (!reporter->ops->test) { if (!reporter->ops->test)
devlink_health_reporter_put(reporter);
return -EOPNOTSUPP; return -EOPNOTSUPP;
}
err = reporter->ops->test(reporter, info->extack);
devlink_health_reporter_put(reporter); return reporter->ops->test(reporter, info->extack);
return err;
} }
struct devlink_stats { struct devlink_stats {
...@@ -9083,7 +8991,7 @@ const struct genl_small_ops devlink_nl_ops[56] = { ...@@ -9083,7 +8991,7 @@ const struct genl_small_ops devlink_nl_ops[56] = {
{ {
.cmd = DEVLINK_CMD_LINECARD_GET, .cmd = DEVLINK_CMD_LINECARD_GET,
.doit = devlink_nl_cmd_linecard_get_doit, .doit = devlink_nl_cmd_linecard_get_doit,
.dumpit = devlink_nl_cmd_linecard_get_dumpit, .dumpit = devlink_nl_instance_iter_dump,
.internal_flags = DEVLINK_NL_FLAG_NEED_LINECARD, .internal_flags = DEVLINK_NL_FLAG_NEED_LINECARD,
/* can be retrieved by unprivileged users */ /* can be retrieved by unprivileged users */
}, },
...@@ -9274,7 +9182,7 @@ const struct genl_small_ops devlink_nl_ops[56] = { ...@@ -9274,7 +9182,7 @@ const struct genl_small_ops devlink_nl_ops[56] = {
.cmd = DEVLINK_CMD_HEALTH_REPORTER_GET, .cmd = DEVLINK_CMD_HEALTH_REPORTER_GET,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = devlink_nl_cmd_health_reporter_get_doit, .doit = devlink_nl_cmd_health_reporter_get_doit,
.dumpit = devlink_nl_cmd_health_reporter_get_dumpit, .dumpit = devlink_nl_instance_iter_dump,
.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT, .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT,
/* can be retrieved by unprivileged users */ /* can be retrieved by unprivileged users */
}, },
...@@ -9591,12 +9499,9 @@ int devl_port_register(struct devlink *devlink, ...@@ -9591,12 +9499,9 @@ int devl_port_register(struct devlink *devlink,
devlink_port->index = port_index; devlink_port->index = port_index;
spin_lock_init(&devlink_port->type_lock); spin_lock_init(&devlink_port->type_lock);
INIT_LIST_HEAD(&devlink_port->reporter_list); INIT_LIST_HEAD(&devlink_port->reporter_list);
mutex_init(&devlink_port->reporters_lock);
err = xa_insert(&devlink->ports, port_index, devlink_port, GFP_KERNEL); err = xa_insert(&devlink->ports, port_index, devlink_port, GFP_KERNEL);
if (err) { if (err)
mutex_destroy(&devlink_port->reporters_lock);
return err; return err;
}
INIT_DELAYED_WORK(&devlink_port->type_warn_dw, &devlink_port_type_warn); INIT_DELAYED_WORK(&devlink_port->type_warn_dw, &devlink_port_type_warn);
devlink_port_type_warn_schedule(devlink_port); devlink_port_type_warn_schedule(devlink_port);
...@@ -9647,7 +9552,6 @@ void devl_port_unregister(struct devlink_port *devlink_port) ...@@ -9647,7 +9552,6 @@ void devl_port_unregister(struct devlink_port *devlink_port)
devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_DEL); devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_DEL);
xa_erase(&devlink_port->devlink->ports, devlink_port->index); xa_erase(&devlink_port->devlink->ports, devlink_port->index);
WARN_ON(!list_empty(&devlink_port->reporter_list)); WARN_ON(!list_empty(&devlink_port->reporter_list));
mutex_destroy(&devlink_port->reporters_lock);
devlink_port->registered = false; devlink_port->registered = false;
} }
EXPORT_SYMBOL_GPL(devl_port_unregister); EXPORT_SYMBOL_GPL(devl_port_unregister);
...@@ -10223,7 +10127,7 @@ static void devlink_linecard_types_fini(struct devlink_linecard *linecard) ...@@ -10223,7 +10127,7 @@ static void devlink_linecard_types_fini(struct devlink_linecard *linecard)
} }
/** /**
* devlink_linecard_create - Create devlink linecard * devl_linecard_create - Create devlink linecard
* *
* @devlink: devlink * @devlink: devlink
* @linecard_index: driver-specific numerical identifier of the linecard * @linecard_index: driver-specific numerical identifier of the linecard
...@@ -10236,8 +10140,8 @@ static void devlink_linecard_types_fini(struct devlink_linecard *linecard) ...@@ -10236,8 +10140,8 @@ static void devlink_linecard_types_fini(struct devlink_linecard *linecard)
* Return: Line card structure or an ERR_PTR() encoded error code. * Return: Line card structure or an ERR_PTR() encoded error code.
*/ */
struct devlink_linecard * struct devlink_linecard *
devlink_linecard_create(struct devlink *devlink, unsigned int linecard_index, devl_linecard_create(struct devlink *devlink, unsigned int linecard_index,
const struct devlink_linecard_ops *ops, void *priv) const struct devlink_linecard_ops *ops, void *priv)
{ {
struct devlink_linecard *linecard; struct devlink_linecard *linecard;
int err; int err;
...@@ -10246,17 +10150,12 @@ devlink_linecard_create(struct devlink *devlink, unsigned int linecard_index, ...@@ -10246,17 +10150,12 @@ devlink_linecard_create(struct devlink *devlink, unsigned int linecard_index,
!ops->types_count || !ops->types_get)) !ops->types_count || !ops->types_get))
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
mutex_lock(&devlink->linecards_lock); if (devlink_linecard_index_exists(devlink, linecard_index))
if (devlink_linecard_index_exists(devlink, linecard_index)) {
mutex_unlock(&devlink->linecards_lock);
return ERR_PTR(-EEXIST); return ERR_PTR(-EEXIST);
}
linecard = kzalloc(sizeof(*linecard), GFP_KERNEL); linecard = kzalloc(sizeof(*linecard), GFP_KERNEL);
if (!linecard) { if (!linecard)
mutex_unlock(&devlink->linecards_lock);
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
}
linecard->devlink = devlink; linecard->devlink = devlink;
linecard->index = linecard_index; linecard->index = linecard_index;
...@@ -10269,35 +10168,29 @@ devlink_linecard_create(struct devlink *devlink, unsigned int linecard_index, ...@@ -10269,35 +10168,29 @@ devlink_linecard_create(struct devlink *devlink, unsigned int linecard_index,
if (err) { if (err) {
mutex_destroy(&linecard->state_lock); mutex_destroy(&linecard->state_lock);
kfree(linecard); kfree(linecard);
mutex_unlock(&devlink->linecards_lock);
return ERR_PTR(err); return ERR_PTR(err);
} }
list_add_tail(&linecard->list, &devlink->linecard_list); list_add_tail(&linecard->list, &devlink->linecard_list);
refcount_set(&linecard->refcount, 1);
mutex_unlock(&devlink->linecards_lock);
devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW); devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW);
return linecard; return linecard;
} }
EXPORT_SYMBOL_GPL(devlink_linecard_create); EXPORT_SYMBOL_GPL(devl_linecard_create);
/** /**
* devlink_linecard_destroy - Destroy devlink linecard * devl_linecard_destroy - Destroy devlink linecard
* *
* @linecard: devlink linecard * @linecard: devlink linecard
*/ */
void devlink_linecard_destroy(struct devlink_linecard *linecard) void devl_linecard_destroy(struct devlink_linecard *linecard)
{ {
struct devlink *devlink = linecard->devlink;
devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_DEL); devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_DEL);
mutex_lock(&devlink->linecards_lock);
list_del(&linecard->list); list_del(&linecard->list);
devlink_linecard_types_fini(linecard); devlink_linecard_types_fini(linecard);
mutex_unlock(&devlink->linecards_lock); mutex_destroy(&linecard->state_lock);
devlink_linecard_put(linecard); kfree(linecard);
} }
EXPORT_SYMBOL_GPL(devlink_linecard_destroy); EXPORT_SYMBOL_GPL(devl_linecard_destroy);
/** /**
* devlink_linecard_provision_set - Set provisioning on linecard * devlink_linecard_provision_set - Set provisioning on linecard
......
...@@ -170,14 +170,9 @@ static int devlink_nl_pre_doit(const struct genl_split_ops *ops, ...@@ -170,14 +170,9 @@ static int devlink_nl_pre_doit(const struct genl_split_ops *ops,
static void devlink_nl_post_doit(const struct genl_split_ops *ops, static void devlink_nl_post_doit(const struct genl_split_ops *ops,
struct sk_buff *skb, struct genl_info *info) struct sk_buff *skb, struct genl_info *info)
{ {
struct devlink_linecard *linecard;
struct devlink *devlink; struct devlink *devlink;
devlink = info->user_ptr[0]; devlink = info->user_ptr[0];
if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_LINECARD) {
linecard = info->user_ptr[1];
devlink_linecard_put(linecard);
}
devl_unlock(devlink); devl_unlock(devlink);
devlink_put(devlink); devlink_put(devlink);
} }
...@@ -192,10 +187,12 @@ static const struct devlink_gen_cmd *devl_gen_cmds[] = { ...@@ -192,10 +187,12 @@ static const struct devlink_gen_cmd *devl_gen_cmds[] = {
[DEVLINK_CMD_PARAM_GET] = &devl_gen_param, [DEVLINK_CMD_PARAM_GET] = &devl_gen_param,
[DEVLINK_CMD_REGION_GET] = &devl_gen_region, [DEVLINK_CMD_REGION_GET] = &devl_gen_region,
[DEVLINK_CMD_INFO_GET] = &devl_gen_info, [DEVLINK_CMD_INFO_GET] = &devl_gen_info,
[DEVLINK_CMD_HEALTH_REPORTER_GET] = &devl_gen_health_reporter,
[DEVLINK_CMD_RATE_GET] = &devl_gen_rate_get, [DEVLINK_CMD_RATE_GET] = &devl_gen_rate_get,
[DEVLINK_CMD_TRAP_GET] = &devl_gen_trap, [DEVLINK_CMD_TRAP_GET] = &devl_gen_trap,
[DEVLINK_CMD_TRAP_GROUP_GET] = &devl_gen_trap_group, [DEVLINK_CMD_TRAP_GROUP_GET] = &devl_gen_trap_group,
[DEVLINK_CMD_TRAP_POLICER_GET] = &devl_gen_trap_policer, [DEVLINK_CMD_TRAP_POLICER_GET] = &devl_gen_trap_policer,
[DEVLINK_CMD_LINECARD_GET] = &devl_gen_linecard,
[DEVLINK_CMD_SELFTESTS_GET] = &devl_gen_selftests, [DEVLINK_CMD_SELFTESTS_GET] = &devl_gen_selftests,
}; };
...@@ -210,7 +207,8 @@ int devlink_nl_instance_iter_dump(struct sk_buff *msg, ...@@ -210,7 +207,8 @@ int devlink_nl_instance_iter_dump(struct sk_buff *msg,
cmd = devl_gen_cmds[info->op.cmd]; cmd = devl_gen_cmds[info->op.cmd];
devlink_dump_for_each_instance_get(msg, state, devlink) { while ((devlink = devlinks_xa_find_get(sock_net(msg->sk),
&state->instance))) {
devl_lock(devlink); devl_lock(devlink);
if (devl_is_registered(devlink)) if (devl_is_registered(devlink))
...@@ -224,6 +222,8 @@ int devlink_nl_instance_iter_dump(struct sk_buff *msg, ...@@ -224,6 +222,8 @@ int devlink_nl_instance_iter_dump(struct sk_buff *msg,
if (err) if (err)
break; break;
state->instance++;
/* restart sub-object walk for the next instance */ /* restart sub-object walk for the next instance */
state->idx = 0; state->idx = 0;
} }
......
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