mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-08 14:13:53 +00:00
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.us Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
1c5cc01233
@ -349,7 +349,6 @@ int mlx5_attach_device(struct mlx5_core_dev *dev)
|
||||
devl_assert_locked(priv_to_devlink(dev));
|
||||
mutex_lock(&mlx5_intf_mutex);
|
||||
priv->flags &= ~MLX5_PRIV_FLAGS_DETACH;
|
||||
priv->flags |= MLX5_PRIV_FLAGS_MLX5E_LOCKED_FLOW;
|
||||
for (i = 0; i < ARRAY_SIZE(mlx5_adev_devices); i++) {
|
||||
if (!priv->adev[i]) {
|
||||
bool is_supported = false;
|
||||
@ -397,7 +396,6 @@ int mlx5_attach_device(struct mlx5_core_dev *dev)
|
||||
break;
|
||||
}
|
||||
}
|
||||
priv->flags &= ~MLX5_PRIV_FLAGS_MLX5E_LOCKED_FLOW;
|
||||
mutex_unlock(&mlx5_intf_mutex);
|
||||
return ret;
|
||||
}
|
||||
@ -412,7 +410,6 @@ void mlx5_detach_device(struct mlx5_core_dev *dev)
|
||||
|
||||
devl_assert_locked(priv_to_devlink(dev));
|
||||
mutex_lock(&mlx5_intf_mutex);
|
||||
priv->flags |= MLX5_PRIV_FLAGS_MLX5E_LOCKED_FLOW;
|
||||
for (i = ARRAY_SIZE(mlx5_adev_devices) - 1; i >= 0; i--) {
|
||||
if (!priv->adev[i])
|
||||
continue;
|
||||
@ -441,7 +438,6 @@ void mlx5_detach_device(struct mlx5_core_dev *dev)
|
||||
del_adev(&priv->adev[i]->adev);
|
||||
priv->adev[i] = NULL;
|
||||
}
|
||||
priv->flags &= ~MLX5_PRIV_FLAGS_MLX5E_LOCKED_FLOW;
|
||||
priv->flags |= MLX5_PRIV_FLAGS_DETACH;
|
||||
mutex_unlock(&mlx5_intf_mutex);
|
||||
}
|
||||
@ -540,22 +536,16 @@ static void delete_drivers(struct mlx5_core_dev *dev)
|
||||
int mlx5_rescan_drivers_locked(struct mlx5_core_dev *dev)
|
||||
{
|
||||
struct mlx5_priv *priv = &dev->priv;
|
||||
int err = 0;
|
||||
|
||||
lockdep_assert_held(&mlx5_intf_mutex);
|
||||
if (priv->flags & MLX5_PRIV_FLAGS_DETACH)
|
||||
return 0;
|
||||
|
||||
priv->flags |= MLX5_PRIV_FLAGS_MLX5E_LOCKED_FLOW;
|
||||
delete_drivers(dev);
|
||||
if (priv->flags & MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV)
|
||||
goto out;
|
||||
return 0;
|
||||
|
||||
err = add_drivers(dev);
|
||||
|
||||
out:
|
||||
priv->flags &= ~MLX5_PRIV_FLAGS_MLX5E_LOCKED_FLOW;
|
||||
return err;
|
||||
return add_drivers(dev);
|
||||
}
|
||||
|
||||
bool mlx5_same_hw_devs(struct mlx5_core_dev *dev, struct mlx5_core_dev *peer_dev)
|
||||
|
@ -971,6 +971,10 @@ struct mlx5e_priv {
|
||||
struct dentry *dfs_root;
|
||||
};
|
||||
|
||||
struct mlx5e_dev {
|
||||
struct mlx5e_priv *priv;
|
||||
};
|
||||
|
||||
struct mlx5e_rx_handlers {
|
||||
mlx5e_fp_handle_rx_cqe handle_rx_cqe;
|
||||
mlx5e_fp_handle_rx_cqe handle_rx_cqe_mpwqe;
|
||||
|
@ -4,6 +4,29 @@
|
||||
#include "en/devlink.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
|
||||
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
|
||||
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 netdev_phys_item_id ppid = {};
|
||||
struct devlink_port *dl_port;
|
||||
unsigned int dl_port_index;
|
||||
int ret;
|
||||
|
||||
if (mlx5_core_is_pf(priv->mdev)) {
|
||||
attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
|
||||
@ -42,23 +65,12 @@ int mlx5e_devlink_port_register(struct mlx5e_priv *priv)
|
||||
memset(dl_port, 0, sizeof(*dl_port));
|
||||
devlink_port_attrs_set(dl_port, &attrs);
|
||||
|
||||
if (!(priv->mdev->priv.flags & MLX5_PRIV_FLAGS_MLX5E_LOCKED_FLOW))
|
||||
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;
|
||||
return devlink_port_register(devlink, dl_port, dl_port_index);
|
||||
}
|
||||
|
||||
void mlx5e_devlink_port_unregister(struct mlx5e_priv *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))
|
||||
devl_lock(devlink);
|
||||
devl_port_unregister(dl_port);
|
||||
if (!(priv->mdev->priv.flags & MLX5_PRIV_FLAGS_MLX5E_LOCKED_FLOW))
|
||||
devl_unlock(devlink);
|
||||
devlink_port_unregister(dl_port);
|
||||
}
|
||||
|
@ -7,7 +7,10 @@
|
||||
#include <net/devlink.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);
|
||||
|
||||
static inline struct devlink_port *
|
||||
|
@ -754,6 +754,6 @@ void mlx5e_reporter_rx_destroy(struct mlx5e_priv *priv)
|
||||
if (!priv->rx_reporter)
|
||||
return;
|
||||
|
||||
devlink_port_health_reporter_destroy(priv->rx_reporter);
|
||||
devlink_health_reporter_destroy(priv->rx_reporter);
|
||||
priv->rx_reporter = NULL;
|
||||
}
|
||||
|
@ -609,6 +609,6 @@ void mlx5e_reporter_tx_destroy(struct mlx5e_priv *priv)
|
||||
if (!priv->tx_reporter)
|
||||
return;
|
||||
|
||||
devlink_port_health_reporter_destroy(priv->tx_reporter);
|
||||
devlink_health_reporter_destroy(priv->tx_reporter);
|
||||
priv->tx_reporter = NULL;
|
||||
}
|
||||
|
@ -5876,7 +5876,8 @@ void mlx5e_destroy_netdev(struct mlx5e_priv *priv)
|
||||
static int mlx5e_resume(struct auxiliary_device *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 mlx5_core_dev *mdev = edev->mdev;
|
||||
int err;
|
||||
@ -5899,7 +5900,8 @@ static int mlx5e_resume(struct auxiliary_device *adev)
|
||||
|
||||
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 mlx5_core_dev *mdev = priv->mdev;
|
||||
|
||||
@ -5917,21 +5919,28 @@ static int mlx5e_probe(struct auxiliary_device *adev,
|
||||
struct mlx5_adev *edev = container_of(adev, struct mlx5_adev, adev);
|
||||
const struct mlx5e_profile *profile = &mlx5e_nic_profile;
|
||||
struct mlx5_core_dev *mdev = edev->mdev;
|
||||
struct mlx5e_dev *mlx5e_dev;
|
||||
struct net_device *netdev;
|
||||
pm_message_t state = {};
|
||||
struct mlx5e_priv *priv;
|
||||
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);
|
||||
if (!netdev) {
|
||||
mlx5_core_err(mdev, "mlx5e_create_netdev failed\n");
|
||||
return -ENOMEM;
|
||||
err = -ENOMEM;
|
||||
goto err_devlink_unregister;
|
||||
}
|
||||
|
||||
mlx5e_build_nic_netdev(netdev);
|
||||
|
||||
priv = netdev_priv(netdev);
|
||||
auxiliary_set_drvdata(adev, priv);
|
||||
mlx5e_dev->priv = priv;
|
||||
|
||||
priv->profile = profile;
|
||||
priv->ppriv = NULL;
|
||||
@ -5939,7 +5948,7 @@ static int mlx5e_probe(struct auxiliary_device *adev,
|
||||
priv->dfs_root = debugfs_create_dir("nic",
|
||||
mlx5_debugfs_get_dev_root(priv->mdev));
|
||||
|
||||
err = mlx5e_devlink_port_register(priv);
|
||||
err = mlx5e_devlink_port_register(mlx5e_dev, priv);
|
||||
if (err) {
|
||||
mlx5_core_err(mdev, "mlx5e_devlink_port_register failed, %d\n", err);
|
||||
goto err_destroy_netdev;
|
||||
@ -5978,12 +5987,15 @@ static int mlx5e_probe(struct auxiliary_device *adev,
|
||||
err_destroy_netdev:
|
||||
debugfs_remove_recursive(priv->dfs_root);
|
||||
mlx5e_destroy_netdev(priv);
|
||||
err_devlink_unregister:
|
||||
mlx5e_destroy_devlink(mlx5e_dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
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 = {};
|
||||
|
||||
mlx5e_dcbnl_delete_app(priv);
|
||||
@ -5993,6 +6005,7 @@ static void mlx5e_remove(struct auxiliary_device *adev)
|
||||
mlx5e_devlink_port_unregister(priv);
|
||||
debugfs_remove_recursive(priv->dfs_root);
|
||||
mlx5e_destroy_netdev(priv);
|
||||
mlx5e_destroy_devlink(mlx5e_dev);
|
||||
}
|
||||
|
||||
static const struct auxiliary_device_id mlx5e_id_table[] = {
|
||||
|
@ -2051,8 +2051,8 @@ static int mlxsw_core_health_init(struct mlxsw_core *mlxsw_core)
|
||||
if (!(mlxsw_core->bus->features & MLXSW_BUS_F_TXRX))
|
||||
return 0;
|
||||
|
||||
fw_fatal = devlink_health_reporter_create(devlink, &mlxsw_core_health_fw_fatal_ops,
|
||||
0, mlxsw_core);
|
||||
fw_fatal = devl_health_reporter_create(devlink, &mlxsw_core_health_fw_fatal_ops,
|
||||
0, mlxsw_core);
|
||||
if (IS_ERR(fw_fatal)) {
|
||||
dev_err(mlxsw_core->bus_info->dev, "Failed to create fw fatal reporter");
|
||||
return PTR_ERR(fw_fatal);
|
||||
@ -2072,7 +2072,7 @@ static int mlxsw_core_health_init(struct mlxsw_core *mlxsw_core)
|
||||
err_fw_fatal_config:
|
||||
mlxsw_core_trap_unregister(mlxsw_core, &mlxsw_core_health_listener, mlxsw_core);
|
||||
err_trap_register:
|
||||
devlink_health_reporter_destroy(mlxsw_core->health.fw_fatal);
|
||||
devl_health_reporter_destroy(mlxsw_core->health.fw_fatal);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -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);
|
||||
/* Make sure there is no more event work scheduled */
|
||||
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)
|
||||
|
@ -1259,9 +1259,9 @@ static int mlxsw_linecard_init(struct mlxsw_core *mlxsw_core,
|
||||
linecard->linecards = linecards;
|
||||
mutex_init(&linecard->lock);
|
||||
|
||||
devlink_linecard = devlink_linecard_create(priv_to_devlink(mlxsw_core),
|
||||
slot_index, &mlxsw_linecard_ops,
|
||||
linecard);
|
||||
devlink_linecard = devl_linecard_create(priv_to_devlink(mlxsw_core),
|
||||
slot_index, &mlxsw_linecard_ops,
|
||||
linecard);
|
||||
if (IS_ERR(devlink_linecard))
|
||||
return PTR_ERR(devlink_linecard);
|
||||
|
||||
@ -1285,7 +1285,7 @@ static void mlxsw_linecard_fini(struct mlxsw_core *mlxsw_core,
|
||||
if (linecard->active)
|
||||
mlxsw_linecard_active_clear(linecard);
|
||||
mlxsw_linecard_bdev_del(linecard);
|
||||
devlink_linecard_destroy(linecard->devlink_linecard);
|
||||
devl_linecard_destroy(linecard->devlink_linecard);
|
||||
mutex_destroy(&linecard->lock);
|
||||
}
|
||||
|
||||
|
@ -233,16 +233,16 @@ int nsim_dev_health_init(struct nsim_dev *nsim_dev, struct devlink *devlink)
|
||||
int err;
|
||||
|
||||
health->empty_reporter =
|
||||
devlink_health_reporter_create(devlink,
|
||||
&nsim_dev_empty_reporter_ops,
|
||||
0, health);
|
||||
devl_health_reporter_create(devlink,
|
||||
&nsim_dev_empty_reporter_ops,
|
||||
0, health);
|
||||
if (IS_ERR(health->empty_reporter))
|
||||
return PTR_ERR(health->empty_reporter);
|
||||
|
||||
health->dummy_reporter =
|
||||
devlink_health_reporter_create(devlink,
|
||||
&nsim_dev_dummy_reporter_ops,
|
||||
0, health);
|
||||
devl_health_reporter_create(devlink,
|
||||
&nsim_dev_dummy_reporter_ops,
|
||||
0, health);
|
||||
if (IS_ERR(health->dummy_reporter)) {
|
||||
err = PTR_ERR(health->dummy_reporter);
|
||||
goto err_empty_reporter_destroy;
|
||||
@ -266,9 +266,9 @@ int nsim_dev_health_init(struct nsim_dev *nsim_dev, struct devlink *devlink)
|
||||
return 0;
|
||||
|
||||
err_dummy_reporter_destroy:
|
||||
devlink_health_reporter_destroy(health->dummy_reporter);
|
||||
devl_health_reporter_destroy(health->dummy_reporter);
|
||||
err_empty_reporter_destroy:
|
||||
devlink_health_reporter_destroy(health->empty_reporter);
|
||||
devl_health_reporter_destroy(health->empty_reporter);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -278,6 +278,6 @@ void nsim_dev_health_exit(struct nsim_dev *nsim_dev)
|
||||
|
||||
debugfs_remove_recursive(health->ddir);
|
||||
kfree(health->recovered_break_msg);
|
||||
devlink_health_reporter_destroy(health->dummy_reporter);
|
||||
devlink_health_reporter_destroy(health->empty_reporter);
|
||||
devl_health_reporter_destroy(health->dummy_reporter);
|
||||
devl_health_reporter_destroy(health->empty_reporter);
|
||||
}
|
||||
|
@ -554,10 +554,6 @@ enum {
|
||||
* creation/deletion on drivers rescan. Unset during device attach.
|
||||
*/
|
||||
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 {
|
||||
|
@ -146,7 +146,6 @@ struct devlink_port {
|
||||
initialized:1;
|
||||
struct delayed_work type_warn_dw;
|
||||
struct list_head reporter_list;
|
||||
struct mutex reporters_lock; /* Protects reporter_list */
|
||||
|
||||
struct devlink_rate *devlink_rate;
|
||||
struct devlink_linecard *linecard;
|
||||
@ -1687,9 +1686,9 @@ void devl_rate_nodes_destroy(struct devlink *devlink);
|
||||
void devlink_port_linecard_set(struct devlink_port *devlink_port,
|
||||
struct devlink_linecard *linecard);
|
||||
struct devlink_linecard *
|
||||
devlink_linecard_create(struct devlink *devlink, unsigned int linecard_index,
|
||||
const struct devlink_linecard_ops *ops, void *priv);
|
||||
void devlink_linecard_destroy(struct devlink_linecard *linecard);
|
||||
devl_linecard_create(struct devlink *devlink, unsigned int linecard_index,
|
||||
const struct devlink_linecard_ops *ops, void *priv);
|
||||
void devl_linecard_destroy(struct devlink_linecard *linecard);
|
||||
void devlink_linecard_provision_set(struct devlink_linecard *linecard,
|
||||
const char *type);
|
||||
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,
|
||||
const void *value, u32 value_len);
|
||||
|
||||
struct devlink_health_reporter *
|
||||
devlink_health_reporter_create(struct devlink *devlink,
|
||||
const struct devlink_health_reporter_ops *ops,
|
||||
u64 graceful_period, void *priv);
|
||||
devl_port_health_reporter_create(struct devlink_port *port,
|
||||
const struct devlink_health_reporter_ops *ops,
|
||||
u64 graceful_period, void *priv);
|
||||
|
||||
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);
|
||||
|
||||
void
|
||||
devlink_health_reporter_destroy(struct devlink_health_reporter *reporter);
|
||||
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
|
||||
devlink_port_health_reporter_destroy(struct devlink_health_reporter *reporter);
|
||||
devl_health_reporter_destroy(struct devlink_health_reporter *reporter);
|
||||
|
||||
void
|
||||
devlink_health_reporter_destroy(struct devlink_health_reporter *reporter);
|
||||
|
||||
void *
|
||||
devlink_health_reporter_priv(struct devlink_health_reporter *reporter);
|
||||
|
@ -246,8 +246,6 @@ struct devlink *devlink_alloc_ns(const struct devlink_ops *ops,
|
||||
lockdep_register_key(&devlink->lock_key);
|
||||
mutex_init(&devlink->lock);
|
||||
lockdep_set_class(&devlink->lock, &devlink->lock_key);
|
||||
mutex_init(&devlink->reporters_lock);
|
||||
mutex_init(&devlink->linecards_lock);
|
||||
refcount_set(&devlink->refcount, 1);
|
||||
|
||||
return devlink;
|
||||
@ -269,8 +267,6 @@ void devlink_free(struct devlink *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_group_list));
|
||||
WARN_ON(!list_empty(&devlink->trap_list));
|
||||
|
@ -32,13 +32,11 @@ struct devlink {
|
||||
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;
|
||||
struct list_head linecard_list;
|
||||
struct mutex linecards_lock; /* protects linecard_list */
|
||||
const struct devlink_ops *ops;
|
||||
u64 features;
|
||||
struct xarray snapshot_ids;
|
||||
@ -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)
|
||||
{
|
||||
/* To prevent races the caller must hold the instance lock
|
||||
* or another lock taken during unregistration.
|
||||
*/
|
||||
devl_assert_locked(devlink);
|
||||
return xa_get_mark(&devlinks, devlink->index, DEVLINK_REGISTERED);
|
||||
}
|
||||
|
||||
@ -125,17 +121,6 @@ struct devlink_gen_cmd {
|
||||
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];
|
||||
|
||||
struct devlink *
|
||||
@ -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_region;
|
||||
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_group;
|
||||
extern const struct devlink_gen_cmd devl_gen_trap_policer;
|
||||
extern const struct devlink_gen_cmd devl_gen_linecard;
|
||||
|
||||
/* Ports */
|
||||
int devlink_port_netdevice_event(struct notifier_block *nb,
|
||||
@ -194,7 +181,6 @@ struct devlink_linecard;
|
||||
|
||||
struct devlink_linecard *
|
||||
devlink_linecard_get_from_info(struct devlink *devlink, struct genl_info *info);
|
||||
void devlink_linecard_put(struct devlink_linecard *linecard);
|
||||
|
||||
/* Rates */
|
||||
extern const struct devlink_gen_cmd devl_gen_rate_get;
|
||||
|
@ -37,7 +37,6 @@ struct devlink_linecard {
|
||||
struct list_head list;
|
||||
struct devlink *devlink;
|
||||
unsigned int index;
|
||||
refcount_t refcount;
|
||||
const struct devlink_linecard_ops *ops;
|
||||
void *priv;
|
||||
enum devlink_linecard_state state;
|
||||
@ -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]);
|
||||
struct devlink_linecard *linecard;
|
||||
|
||||
mutex_lock(&devlink->linecards_lock);
|
||||
linecard = devlink_linecard_get_by_index(devlink, linecard_index);
|
||||
if (linecard)
|
||||
refcount_inc(&linecard->refcount);
|
||||
mutex_unlock(&devlink->linecards_lock);
|
||||
if (!linecard)
|
||||
return ERR_PTR(-ENODEV);
|
||||
return linecard;
|
||||
@ -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);
|
||||
}
|
||||
|
||||
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 list_head list;
|
||||
unsigned int index;
|
||||
@ -2118,50 +2105,42 @@ static int devlink_nl_cmd_linecard_get_doit(struct sk_buff *skb,
|
||||
return genlmsg_reply(msg, info);
|
||||
}
|
||||
|
||||
static int devlink_nl_cmd_linecard_get_dumpit(struct sk_buff *msg,
|
||||
struct netlink_callback *cb)
|
||||
static int devlink_nl_cmd_linecard_get_dump_one(struct sk_buff *msg,
|
||||
struct devlink *devlink,
|
||||
struct netlink_callback *cb)
|
||||
{
|
||||
struct devlink_nl_dump_state *state = devlink_dump_state(cb);
|
||||
struct devlink_linecard *linecard;
|
||||
struct devlink *devlink;
|
||||
int err;
|
||||
int idx = 0;
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
list_for_each_entry(linecard, &devlink->linecard_list, list) {
|
||||
if (idx < state->idx) {
|
||||
idx++;
|
||||
continue;
|
||||
}
|
||||
next_devlink:
|
||||
mutex_unlock(&devlink->linecards_lock);
|
||||
devlink_put(devlink);
|
||||
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) {
|
||||
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 *
|
||||
devlink_linecard_type_lookup(struct devlink_linecard *linecard,
|
||||
const char *type)
|
||||
@ -7282,7 +7261,6 @@ struct devlink_health_reporter {
|
||||
u64 error_count;
|
||||
u64 recovery_count;
|
||||
u64 last_recovery_ts;
|
||||
refcount_t refcount;
|
||||
};
|
||||
|
||||
void *
|
||||
@ -7294,12 +7272,10 @@ EXPORT_SYMBOL_GPL(devlink_health_reporter_priv);
|
||||
|
||||
static struct devlink_health_reporter *
|
||||
__devlink_health_reporter_find_by_name(struct list_head *reporter_list,
|
||||
struct mutex *list_lock,
|
||||
const char *reporter_name)
|
||||
{
|
||||
struct devlink_health_reporter *reporter;
|
||||
|
||||
lockdep_assert_held(list_lock);
|
||||
list_for_each_entry(reporter, reporter_list, list)
|
||||
if (!strcmp(reporter->ops->name, reporter_name))
|
||||
return reporter;
|
||||
@ -7311,7 +7287,6 @@ devlink_health_reporter_find_by_name(struct devlink *devlink,
|
||||
const char *reporter_name)
|
||||
{
|
||||
return __devlink_health_reporter_find_by_name(&devlink->reporter_list,
|
||||
&devlink->reporters_lock,
|
||||
reporter_name);
|
||||
}
|
||||
|
||||
@ -7320,7 +7295,6 @@ devlink_port_health_reporter_find_by_name(struct devlink_port *devlink_port,
|
||||
const char *reporter_name)
|
||||
{
|
||||
return __devlink_health_reporter_find_by_name(&devlink_port->reporter_list,
|
||||
&devlink_port->reporters_lock,
|
||||
reporter_name);
|
||||
}
|
||||
|
||||
@ -7345,54 +7319,88 @@ __devlink_health_reporter_create(struct devlink *devlink,
|
||||
reporter->auto_recover = !!ops->recover;
|
||||
reporter->auto_dump = !!ops->dump;
|
||||
mutex_init(&reporter->dump_lock);
|
||||
refcount_set(&reporter->refcount, 1);
|
||||
return reporter;
|
||||
}
|
||||
|
||||
/**
|
||||
* devlink_port_health_reporter_create - create devlink health reporter for
|
||||
* specified port instance
|
||||
* devl_port_health_reporter_create - create devlink health reporter for
|
||||
* specified port instance
|
||||
*
|
||||
* @port: devlink_port which should contain the new reporter
|
||||
* @ops: ops
|
||||
* @graceful_period: to avoid recovery loops, in msecs
|
||||
* @priv: priv
|
||||
*/
|
||||
struct devlink_health_reporter *
|
||||
devl_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;
|
||||
|
||||
devl_assert_locked(port->devlink);
|
||||
|
||||
if (__devlink_health_reporter_find_by_name(&port->reporter_list,
|
||||
ops->name))
|
||||
return ERR_PTR(-EEXIST);
|
||||
|
||||
reporter = __devlink_health_reporter_create(port->devlink, ops,
|
||||
graceful_period, priv);
|
||||
if (IS_ERR(reporter))
|
||||
return reporter;
|
||||
|
||||
reporter->devlink_port = port;
|
||||
list_add_tail(&reporter->list, &port->reporter_list);
|
||||
return reporter;
|
||||
}
|
||||
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;
|
||||
|
||||
mutex_lock(&port->reporters_lock);
|
||||
if (__devlink_health_reporter_find_by_name(&port->reporter_list,
|
||||
&port->reporters_lock, ops->name)) {
|
||||
reporter = ERR_PTR(-EEXIST);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
reporter = __devlink_health_reporter_create(port->devlink, ops,
|
||||
devl_lock(devlink);
|
||||
reporter = devl_port_health_reporter_create(port, ops,
|
||||
graceful_period, priv);
|
||||
if (IS_ERR(reporter))
|
||||
goto unlock;
|
||||
|
||||
reporter->devlink_port = port;
|
||||
list_add_tail(&reporter->list, &port->reporter_list);
|
||||
unlock:
|
||||
mutex_unlock(&port->reporters_lock);
|
||||
devl_unlock(devlink);
|
||||
return reporter;
|
||||
}
|
||||
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
|
||||
* @ops: ops
|
||||
* @graceful_period: to avoid recovery loops, in msecs
|
||||
* @priv: 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 *reporter;
|
||||
|
||||
devl_assert_locked(devlink);
|
||||
|
||||
if (devlink_health_reporter_find_by_name(devlink, ops->name))
|
||||
return ERR_PTR(-EEXIST);
|
||||
|
||||
reporter = __devlink_health_reporter_create(devlink, ops,
|
||||
graceful_period, priv);
|
||||
if (IS_ERR(reporter))
|
||||
return reporter;
|
||||
|
||||
list_add_tail(&reporter->list, &devlink->reporter_list);
|
||||
return reporter;
|
||||
}
|
||||
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,
|
||||
@ -7400,20 +7408,10 @@ devlink_health_reporter_create(struct devlink *devlink,
|
||||
{
|
||||
struct devlink_health_reporter *reporter;
|
||||
|
||||
mutex_lock(&devlink->reporters_lock);
|
||||
if (devlink_health_reporter_find_by_name(devlink, ops->name)) {
|
||||
reporter = ERR_PTR(-EEXIST);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
reporter = __devlink_health_reporter_create(devlink, ops,
|
||||
graceful_period, priv);
|
||||
if (IS_ERR(reporter))
|
||||
goto unlock;
|
||||
|
||||
list_add_tail(&reporter->list, &devlink->reporter_list);
|
||||
unlock:
|
||||
mutex_unlock(&devlink->reporters_lock);
|
||||
devl_lock(devlink);
|
||||
reporter = devl_health_reporter_create(devlink, ops,
|
||||
graceful_period, priv);
|
||||
devl_unlock(devlink);
|
||||
return reporter;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devlink_health_reporter_create);
|
||||
@ -7427,52 +7425,32 @@ devlink_health_reporter_free(struct devlink_health_reporter *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
|
||||
*/
|
||||
void
|
||||
devl_health_reporter_destroy(struct devlink_health_reporter *reporter)
|
||||
{
|
||||
devl_assert_locked(reporter->devlink);
|
||||
|
||||
list_del(&reporter->list);
|
||||
devlink_health_reporter_free(reporter);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devl_health_reporter_destroy);
|
||||
|
||||
void
|
||||
devlink_health_reporter_destroy(struct devlink_health_reporter *reporter)
|
||||
{
|
||||
struct mutex *lock = &reporter->devlink->reporters_lock;
|
||||
struct devlink *devlink = reporter->devlink;
|
||||
|
||||
mutex_lock(lock);
|
||||
__devlink_health_reporter_destroy(reporter);
|
||||
mutex_unlock(lock);
|
||||
devl_lock(devlink);
|
||||
devl_health_reporter_destroy(reporter);
|
||||
devl_unlock(devlink);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devlink_health_reporter_destroy);
|
||||
|
||||
/**
|
||||
* devlink_port_health_reporter_destroy - destroy devlink port health reporter
|
||||
*
|
||||
* @reporter: devlink health reporter to destroy
|
||||
*/
|
||||
void
|
||||
devlink_port_health_reporter_destroy(struct devlink_health_reporter *reporter)
|
||||
{
|
||||
struct mutex *lock = &reporter->devlink_port->reporters_lock;
|
||||
|
||||
mutex_lock(lock);
|
||||
__devlink_health_reporter_destroy(reporter);
|
||||
mutex_unlock(lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devlink_port_health_reporter_destroy);
|
||||
|
||||
static int
|
||||
devlink_nl_health_reporter_fill(struct sk_buff *msg,
|
||||
struct devlink_health_reporter *reporter,
|
||||
@ -7702,7 +7680,6 @@ static struct devlink_health_reporter *
|
||||
devlink_health_reporter_get_from_attrs(struct devlink *devlink,
|
||||
struct nlattr **attrs)
|
||||
{
|
||||
struct devlink_health_reporter *reporter;
|
||||
struct devlink_port *devlink_port;
|
||||
char *reporter_name;
|
||||
|
||||
@ -7711,21 +7688,12 @@ devlink_health_reporter_get_from_attrs(struct devlink *devlink,
|
||||
|
||||
reporter_name = nla_data(attrs[DEVLINK_ATTR_HEALTH_REPORTER_NAME]);
|
||||
devlink_port = devlink_port_get_from_attrs(devlink, attrs);
|
||||
if (IS_ERR(devlink_port)) {
|
||||
mutex_lock(&devlink->reporters_lock);
|
||||
reporter = devlink_health_reporter_find_by_name(devlink, reporter_name);
|
||||
if (reporter)
|
||||
refcount_inc(&reporter->refcount);
|
||||
mutex_unlock(&devlink->reporters_lock);
|
||||
} 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;
|
||||
if (IS_ERR(devlink_port))
|
||||
return devlink_health_reporter_find_by_name(devlink,
|
||||
reporter_name);
|
||||
else
|
||||
return devlink_port_health_reporter_find_by_name(devlink_port,
|
||||
reporter_name);
|
||||
}
|
||||
|
||||
static struct devlink_health_reporter *
|
||||
@ -7784,10 +7752,8 @@ static int devlink_nl_cmd_health_reporter_get_doit(struct sk_buff *skb,
|
||||
return -EINVAL;
|
||||
|
||||
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
||||
if (!msg) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
if (!msg)
|
||||
return -ENOMEM;
|
||||
|
||||
err = devlink_nl_health_reporter_fill(msg, reporter,
|
||||
DEVLINK_CMD_HEALTH_REPORTER_GET,
|
||||
@ -7795,98 +7761,72 @@ static int devlink_nl_cmd_health_reporter_get_doit(struct sk_buff *skb,
|
||||
0);
|
||||
if (err) {
|
||||
nlmsg_free(msg);
|
||||
goto out;
|
||||
return err;
|
||||
}
|
||||
|
||||
err = genlmsg_reply(msg, info);
|
||||
out:
|
||||
devlink_health_reporter_put(reporter);
|
||||
return err;
|
||||
return genlmsg_reply(msg, info);
|
||||
}
|
||||
|
||||
static int
|
||||
devlink_nl_cmd_health_reporter_get_dumpit(struct sk_buff *msg,
|
||||
struct netlink_callback *cb)
|
||||
devlink_nl_cmd_health_reporter_get_dump_one(struct sk_buff *msg,
|
||||
struct devlink *devlink,
|
||||
struct netlink_callback *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;
|
||||
|
||||
devlink_dump_for_each_instance_get(msg, state, devlink) {
|
||||
struct devlink_health_reporter *reporter;
|
||||
struct devlink_port *port;
|
||||
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);
|
||||
list_for_each_entry(reporter, &devlink->reporter_list, list) {
|
||||
if (idx < state->idx) {
|
||||
idx++;
|
||||
continue;
|
||||
}
|
||||
|
||||
list_for_each_entry(reporter, &devlink->reporter_list,
|
||||
list) {
|
||||
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) {
|
||||
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) {
|
||||
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);
|
||||
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(&devlink->reporters_lock);
|
||||
devlink_put(devlink);
|
||||
state->idx = idx;
|
||||
goto out;
|
||||
return err;
|
||||
}
|
||||
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
|
||||
devlink_nl_cmd_health_reporter_set_doit(struct sk_buff *skb,
|
||||
struct genl_info *info)
|
||||
{
|
||||
struct devlink *devlink = info->user_ptr[0];
|
||||
struct devlink_health_reporter *reporter;
|
||||
int err;
|
||||
|
||||
reporter = devlink_health_reporter_get_from_info(devlink, info);
|
||||
if (!reporter)
|
||||
@ -7894,15 +7834,12 @@ devlink_nl_cmd_health_reporter_set_doit(struct sk_buff *skb,
|
||||
|
||||
if (!reporter->ops->recover &&
|
||||
(info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD] ||
|
||||
info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER])) {
|
||||
err = -EOPNOTSUPP;
|
||||
goto out;
|
||||
}
|
||||
info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER]))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!reporter->ops->dump &&
|
||||
info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_DUMP]) {
|
||||
err = -EOPNOTSUPP;
|
||||
goto out;
|
||||
}
|
||||
info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_DUMP])
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD])
|
||||
reporter->graceful_period =
|
||||
@ -7916,11 +7853,7 @@ devlink_nl_cmd_health_reporter_set_doit(struct sk_buff *skb,
|
||||
reporter->auto_dump =
|
||||
nla_get_u8(info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_DUMP]);
|
||||
|
||||
devlink_health_reporter_put(reporter);
|
||||
return 0;
|
||||
out:
|
||||
devlink_health_reporter_put(reporter);
|
||||
return err;
|
||||
}
|
||||
|
||||
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_health_reporter *reporter;
|
||||
int err;
|
||||
|
||||
reporter = devlink_health_reporter_get_from_info(devlink, info);
|
||||
if (!reporter)
|
||||
return -EINVAL;
|
||||
|
||||
err = devlink_health_reporter_recover(reporter, NULL, info->extack);
|
||||
|
||||
devlink_health_reporter_put(reporter);
|
||||
return err;
|
||||
return devlink_health_reporter_recover(reporter, NULL, info->extack);
|
||||
}
|
||||
|
||||
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)
|
||||
return -EINVAL;
|
||||
|
||||
if (!reporter->ops->diagnose) {
|
||||
devlink_health_reporter_put(reporter);
|
||||
if (!reporter->ops->diagnose)
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
fmsg = devlink_fmsg_alloc();
|
||||
if (!fmsg) {
|
||||
devlink_health_reporter_put(reporter);
|
||||
if (!fmsg)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
err = devlink_fmsg_obj_nest_start(fmsg);
|
||||
if (err)
|
||||
goto out;
|
||||
return err;
|
||||
|
||||
err = reporter->ops->diagnose(reporter, fmsg, info->extack);
|
||||
if (err)
|
||||
goto out;
|
||||
return err;
|
||||
|
||||
err = devlink_fmsg_obj_nest_end(fmsg);
|
||||
if (err)
|
||||
goto out;
|
||||
return err;
|
||||
|
||||
err = devlink_fmsg_snd(fmsg, info,
|
||||
DEVLINK_CMD_HEALTH_REPORTER_DIAGNOSE, 0);
|
||||
|
||||
out:
|
||||
devlink_fmsg_free(fmsg);
|
||||
devlink_health_reporter_put(reporter);
|
||||
return err;
|
||||
return devlink_fmsg_snd(fmsg, info,
|
||||
DEVLINK_CMD_HEALTH_REPORTER_DIAGNOSE, 0);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -7996,10 +7916,9 @@ devlink_nl_cmd_health_reporter_dump_get_dumpit(struct sk_buff *skb,
|
||||
if (!reporter)
|
||||
return -EINVAL;
|
||||
|
||||
if (!reporter->ops->dump) {
|
||||
err = -EOPNOTSUPP;
|
||||
goto out;
|
||||
}
|
||||
if (!reporter->ops->dump)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
mutex_lock(&reporter->dump_lock);
|
||||
if (!state->idx) {
|
||||
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,
|
||||
DEVLINK_CMD_HEALTH_REPORTER_DUMP_GET);
|
||||
unlock:
|
||||
mutex_unlock(&reporter->dump_lock);
|
||||
out:
|
||||
devlink_health_reporter_put(reporter);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -8033,15 +7950,12 @@ devlink_nl_cmd_health_reporter_dump_clear_doit(struct sk_buff *skb,
|
||||
if (!reporter)
|
||||
return -EINVAL;
|
||||
|
||||
if (!reporter->ops->dump) {
|
||||
devlink_health_reporter_put(reporter);
|
||||
if (!reporter->ops->dump)
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
mutex_lock(&reporter->dump_lock);
|
||||
devlink_health_dump_clear(reporter);
|
||||
mutex_unlock(&reporter->dump_lock);
|
||||
devlink_health_reporter_put(reporter);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -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_health_reporter *reporter;
|
||||
int err;
|
||||
|
||||
reporter = devlink_health_reporter_get_from_info(devlink, info);
|
||||
if (!reporter)
|
||||
return -EINVAL;
|
||||
|
||||
if (!reporter->ops->test) {
|
||||
devlink_health_reporter_put(reporter);
|
||||
if (!reporter->ops->test)
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
err = reporter->ops->test(reporter, info->extack);
|
||||
|
||||
devlink_health_reporter_put(reporter);
|
||||
return err;
|
||||
return reporter->ops->test(reporter, info->extack);
|
||||
}
|
||||
|
||||
struct devlink_stats {
|
||||
@ -9083,7 +8991,7 @@ const struct genl_small_ops devlink_nl_ops[56] = {
|
||||
{
|
||||
.cmd = DEVLINK_CMD_LINECARD_GET,
|
||||
.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,
|
||||
/* can be retrieved by unprivileged users */
|
||||
},
|
||||
@ -9274,7 +9182,7 @@ const struct genl_small_ops devlink_nl_ops[56] = {
|
||||
.cmd = DEVLINK_CMD_HEALTH_REPORTER_GET,
|
||||
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
|
||||
.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,
|
||||
/* can be retrieved by unprivileged users */
|
||||
},
|
||||
@ -9591,12 +9499,9 @@ int devl_port_register(struct devlink *devlink,
|
||||
devlink_port->index = port_index;
|
||||
spin_lock_init(&devlink_port->type_lock);
|
||||
INIT_LIST_HEAD(&devlink_port->reporter_list);
|
||||
mutex_init(&devlink_port->reporters_lock);
|
||||
err = xa_insert(&devlink->ports, port_index, devlink_port, GFP_KERNEL);
|
||||
if (err) {
|
||||
mutex_destroy(&devlink_port->reporters_lock);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
INIT_DELAYED_WORK(&devlink_port->type_warn_dw, &devlink_port_type_warn);
|
||||
devlink_port_type_warn_schedule(devlink_port);
|
||||
@ -9647,7 +9552,6 @@ void devl_port_unregister(struct devlink_port *devlink_port)
|
||||
devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_DEL);
|
||||
xa_erase(&devlink_port->devlink->ports, devlink_port->index);
|
||||
WARN_ON(!list_empty(&devlink_port->reporter_list));
|
||||
mutex_destroy(&devlink_port->reporters_lock);
|
||||
devlink_port->registered = false;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devl_port_unregister);
|
||||
@ -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
|
||||
* @linecard_index: driver-specific numerical identifier of the 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.
|
||||
*/
|
||||
struct devlink_linecard *
|
||||
devlink_linecard_create(struct devlink *devlink, unsigned int linecard_index,
|
||||
const struct devlink_linecard_ops *ops, void *priv)
|
||||
devl_linecard_create(struct devlink *devlink, unsigned int linecard_index,
|
||||
const struct devlink_linecard_ops *ops, void *priv)
|
||||
{
|
||||
struct devlink_linecard *linecard;
|
||||
int err;
|
||||
@ -10246,17 +10150,12 @@ devlink_linecard_create(struct devlink *devlink, unsigned int linecard_index,
|
||||
!ops->types_count || !ops->types_get))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
mutex_lock(&devlink->linecards_lock);
|
||||
if (devlink_linecard_index_exists(devlink, linecard_index)) {
|
||||
mutex_unlock(&devlink->linecards_lock);
|
||||
if (devlink_linecard_index_exists(devlink, linecard_index))
|
||||
return ERR_PTR(-EEXIST);
|
||||
}
|
||||
|
||||
linecard = kzalloc(sizeof(*linecard), GFP_KERNEL);
|
||||
if (!linecard) {
|
||||
mutex_unlock(&devlink->linecards_lock);
|
||||
if (!linecard)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
linecard->devlink = devlink;
|
||||
linecard->index = linecard_index;
|
||||
@ -10269,35 +10168,29 @@ devlink_linecard_create(struct devlink *devlink, unsigned int linecard_index,
|
||||
if (err) {
|
||||
mutex_destroy(&linecard->state_lock);
|
||||
kfree(linecard);
|
||||
mutex_unlock(&devlink->linecards_lock);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
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);
|
||||
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
|
||||
*/
|
||||
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);
|
||||
mutex_lock(&devlink->linecards_lock);
|
||||
list_del(&linecard->list);
|
||||
devlink_linecard_types_fini(linecard);
|
||||
mutex_unlock(&devlink->linecards_lock);
|
||||
devlink_linecard_put(linecard);
|
||||
mutex_destroy(&linecard->state_lock);
|
||||
kfree(linecard);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devlink_linecard_destroy);
|
||||
EXPORT_SYMBOL_GPL(devl_linecard_destroy);
|
||||
|
||||
/**
|
||||
* devlink_linecard_provision_set - Set provisioning on linecard
|
||||
|
@ -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,
|
||||
struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
struct devlink_linecard *linecard;
|
||||
struct devlink *devlink;
|
||||
|
||||
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);
|
||||
devlink_put(devlink);
|
||||
}
|
||||
@ -192,10 +187,12 @@ static const struct devlink_gen_cmd *devl_gen_cmds[] = {
|
||||
[DEVLINK_CMD_PARAM_GET] = &devl_gen_param,
|
||||
[DEVLINK_CMD_REGION_GET] = &devl_gen_region,
|
||||
[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_TRAP_GET] = &devl_gen_trap,
|
||||
[DEVLINK_CMD_TRAP_GROUP_GET] = &devl_gen_trap_group,
|
||||
[DEVLINK_CMD_TRAP_POLICER_GET] = &devl_gen_trap_policer,
|
||||
[DEVLINK_CMD_LINECARD_GET] = &devl_gen_linecard,
|
||||
[DEVLINK_CMD_SELFTESTS_GET] = &devl_gen_selftests,
|
||||
};
|
||||
|
||||
@ -210,7 +207,8 @@ int devlink_nl_instance_iter_dump(struct sk_buff *msg,
|
||||
|
||||
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);
|
||||
|
||||
if (devl_is_registered(devlink))
|
||||
@ -224,6 +222,8 @@ int devlink_nl_instance_iter_dump(struct sk_buff *msg,
|
||||
if (err)
|
||||
break;
|
||||
|
||||
state->instance++;
|
||||
|
||||
/* restart sub-object walk for the next instance */
|
||||
state->idx = 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user