summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c120
1 files changed, 23 insertions, 97 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c b/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c
index c8a043b2a8e0..6c11e075cab0 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c
@@ -30,8 +30,6 @@ static void *mlx5_sf_by_dl_port(struct devlink_port *dl_port)
struct mlx5_sf_table {
struct mlx5_core_dev *dev; /* To refer from notifier context. */
struct xarray function_ids; /* function id based lookup. */
- refcount_t refcount;
- struct completion disable_complete;
struct mutex sf_state_lock; /* Serializes sf state among user cmds & vhca event handler. */
struct notifier_block esw_nb;
struct notifier_block vhca_nb;
@@ -111,22 +109,6 @@ static void mlx5_sf_free(struct mlx5_sf_table *table, struct mlx5_sf *sf)
kfree(sf);
}
-static struct mlx5_sf_table *mlx5_sf_table_try_get(struct mlx5_core_dev *dev)
-{
- struct mlx5_sf_table *table = dev->priv.sf_table;
-
- if (!table)
- return NULL;
-
- return refcount_inc_not_zero(&table->refcount) ? table : NULL;
-}
-
-static void mlx5_sf_table_put(struct mlx5_sf_table *table)
-{
- if (refcount_dec_and_test(&table->refcount))
- complete(&table->disable_complete);
-}
-
static enum devlink_port_fn_state mlx5_sf_to_devlink_state(u8 hw_state)
{
switch (hw_state) {
@@ -166,18 +148,13 @@ int mlx5_devlink_sf_port_fn_state_get(struct devlink_port *dl_port,
struct netlink_ext_ack *extack)
{
struct mlx5_core_dev *dev = devlink_priv(dl_port->devlink);
+ struct mlx5_sf_table *table = dev->priv.sf_table;
struct mlx5_sf *sf = mlx5_sf_by_dl_port(dl_port);
- struct mlx5_sf_table *table;
-
- table = mlx5_sf_table_try_get(dev);
- if (!table)
- return -EOPNOTSUPP;
mutex_lock(&table->sf_state_lock);
*state = mlx5_sf_to_devlink_state(sf->hw_state);
*opstate = mlx5_sf_to_devlink_opstate(sf->hw_state);
mutex_unlock(&table->sf_state_lock);
- mlx5_sf_table_put(table);
return 0;
}
@@ -244,19 +221,10 @@ int mlx5_devlink_sf_port_fn_state_set(struct devlink_port *dl_port,
struct netlink_ext_ack *extack)
{
struct mlx5_core_dev *dev = devlink_priv(dl_port->devlink);
+ struct mlx5_sf_table *table = dev->priv.sf_table;
struct mlx5_sf *sf = mlx5_sf_by_dl_port(dl_port);
- struct mlx5_sf_table *table;
- int err;
- table = mlx5_sf_table_try_get(dev);
- if (!table) {
- NL_SET_ERR_MSG_MOD(extack,
- "Port state set is only supported in eswitch switchdev mode or SF ports are disabled.");
- return -EOPNOTSUPP;
- }
- err = mlx5_sf_state_set(dev, table, sf, state, extack);
- mlx5_sf_table_put(table);
- return err;
+ return mlx5_sf_state_set(dev, table, sf, state, extack);
}
static int mlx5_sf_add(struct mlx5_core_dev *dev, struct mlx5_sf_table *table,
@@ -315,28 +283,37 @@ mlx5_sf_new_check_attr(struct mlx5_core_dev *dev, const struct devlink_port_new_
return 0;
}
+static bool mlx5_sf_table_supported(const struct mlx5_core_dev *dev)
+{
+ return dev->priv.eswitch && MLX5_ESWITCH_MANAGER(dev) &&
+ mlx5_sf_hw_table_supported(dev);
+}
+
int mlx5_devlink_sf_port_new(struct devlink *devlink,
const struct devlink_port_new_attrs *new_attr,
struct netlink_ext_ack *extack,
struct devlink_port **dl_port)
{
struct mlx5_core_dev *dev = devlink_priv(devlink);
- struct mlx5_sf_table *table;
+ struct mlx5_sf_table *table = dev->priv.sf_table;
int err;
err = mlx5_sf_new_check_attr(dev, new_attr, extack);
if (err)
return err;
- table = mlx5_sf_table_try_get(dev);
- if (!table) {
+ if (!mlx5_sf_table_supported(dev)) {
+ NL_SET_ERR_MSG_MOD(extack, "SF ports are not supported.");
+ return -EOPNOTSUPP;
+ }
+
+ if (!is_mdev_switchdev_mode(dev)) {
NL_SET_ERR_MSG_MOD(extack,
- "Port add is only supported in eswitch switchdev mode or SF ports are disabled.");
+ "SF ports are only supported in eswitch switchdev mode.");
return -EOPNOTSUPP;
}
- err = mlx5_sf_add(dev, table, new_attr, extack, dl_port);
- mlx5_sf_table_put(table);
- return err;
+
+ return mlx5_sf_add(dev, table, new_attr, extack, dl_port);
}
static void mlx5_sf_dealloc(struct mlx5_sf_table *table, struct mlx5_sf *sf)
@@ -377,18 +354,10 @@ int mlx5_devlink_sf_port_del(struct devlink *devlink,
struct netlink_ext_ack *extack)
{
struct mlx5_core_dev *dev = devlink_priv(devlink);
+ struct mlx5_sf_table *table = dev->priv.sf_table;
struct mlx5_sf *sf = mlx5_sf_by_dl_port(dl_port);
- struct mlx5_sf_table *table;
-
- table = mlx5_sf_table_try_get(dev);
- if (!table) {
- NL_SET_ERR_MSG_MOD(extack,
- "Port del is only supported in eswitch switchdev mode or SF ports are disabled.");
- return -EOPNOTSUPP;
- }
mlx5_sf_del(table, sf);
- mlx5_sf_table_put(table);
return 0;
}
@@ -414,14 +383,10 @@ static int mlx5_sf_vhca_event(struct notifier_block *nb, unsigned long opcode, v
bool update = false;
struct mlx5_sf *sf;
- table = mlx5_sf_table_try_get(table->dev);
- if (!table)
- return 0;
-
mutex_lock(&table->sf_state_lock);
sf = mlx5_sf_lookup_by_function_id(table, event->function_id);
if (!sf)
- goto sf_err;
+ goto unlock;
/* When driver is attached or detached to a function, an event
* notifies such state change.
@@ -431,55 +396,28 @@ static int mlx5_sf_vhca_event(struct notifier_block *nb, unsigned long opcode, v
sf->hw_state = event->new_vhca_state;
trace_mlx5_sf_update_state(table->dev, sf->port_index, sf->controller,
sf->hw_fn_id, sf->hw_state);
-sf_err:
+unlock:
mutex_unlock(&table->sf_state_lock);
- mlx5_sf_table_put(table);
return 0;
}
-static void mlx5_sf_table_enable(struct mlx5_sf_table *table)
-{
- init_completion(&table->disable_complete);
- refcount_set(&table->refcount, 1);
-}
-
static void mlx5_sf_del_all(struct mlx5_sf_table *table)
{
unsigned long index;
struct mlx5_sf *sf;
- /* At this point, no new user commands can start and no vhca event can
- * arrive. It is safe to destroy all user created SFs.
- */
xa_for_each(&table->function_ids, index, sf)
mlx5_sf_del(table, sf);
}
-static void mlx5_sf_table_disable(struct mlx5_sf_table *table)
-{
- if (!refcount_read(&table->refcount))
- return;
-
- /* Balances with refcount_set; drop the reference so that new user cmd cannot start
- * and new vhca event handler cannot run.
- */
- mlx5_sf_table_put(table);
- wait_for_completion(&table->disable_complete);
-
- mlx5_sf_del_all(table);
-}
-
static int mlx5_sf_esw_event(struct notifier_block *nb, unsigned long event, void *data)
{
struct mlx5_sf_table *table = container_of(nb, struct mlx5_sf_table, esw_nb);
const struct mlx5_esw_event_info *mode = data;
switch (mode->new_mode) {
- case MLX5_ESWITCH_OFFLOADS:
- mlx5_sf_table_enable(table);
- break;
case MLX5_ESWITCH_LEGACY:
- mlx5_sf_table_disable(table);
+ mlx5_sf_del_all(table);
break;
default:
break;
@@ -498,9 +436,6 @@ static int mlx5_sf_mdev_event(struct notifier_block *nb, unsigned long event, vo
if (event != MLX5_DRIVER_EVENT_SF_PEER_DEVLINK)
return NOTIFY_DONE;
- table = mlx5_sf_table_try_get(table->dev);
- if (!table)
- return NOTIFY_DONE;
mutex_lock(&table->sf_state_lock);
sf = mlx5_sf_lookup_by_function_id(table, event_ctx->fn_id);
@@ -513,16 +448,9 @@ static int mlx5_sf_mdev_event(struct notifier_block *nb, unsigned long event, vo
ret = NOTIFY_OK;
out:
mutex_unlock(&table->sf_state_lock);
- mlx5_sf_table_put(table);
return ret;
}
-static bool mlx5_sf_table_supported(const struct mlx5_core_dev *dev)
-{
- return dev->priv.eswitch && MLX5_ESWITCH_MANAGER(dev) &&
- mlx5_sf_hw_table_supported(dev);
-}
-
int mlx5_sf_table_init(struct mlx5_core_dev *dev)
{
struct mlx5_sf_table *table;
@@ -539,7 +467,6 @@ int mlx5_sf_table_init(struct mlx5_core_dev *dev)
table->dev = dev;
xa_init(&table->function_ids);
dev->priv.sf_table = table;
- refcount_set(&table->refcount, 0);
table->esw_nb.notifier_call = mlx5_sf_esw_event;
err = mlx5_esw_event_notifier_register(dev->priv.eswitch, &table->esw_nb);
if (err)
@@ -574,7 +501,6 @@ void mlx5_sf_table_cleanup(struct mlx5_core_dev *dev)
mlx5_blocking_notifier_unregister(dev, &table->mdev_nb);
mlx5_vhca_event_notifier_unregister(table->dev, &table->vhca_nb);
mlx5_esw_event_notifier_unregister(dev->priv.eswitch, &table->esw_nb);
- WARN_ON(refcount_read(&table->refcount));
mutex_destroy(&table->sf_state_lock);
WARN_ON(!xa_empty(&table->function_ids));
kfree(table);