struct mlx5_core_dev *dev; /* To refer from notifier context. */
struct xarray function_ids; /* function id based lookup. */
struct mutex sf_state_lock; /* Serializes sf state among user cmds & vhca event handler. */
- struct notifier_block esw_nb;
- struct notifier_block vhca_nb;
- struct notifier_block mdev_nb;
};
static struct mlx5_sf *
static int mlx5_sf_vhca_event(struct notifier_block *nb, unsigned long opcode, void *data)
{
- struct mlx5_sf_table *table = container_of(nb, struct mlx5_sf_table, vhca_nb);
+ struct mlx5_core_dev *dev = container_of(nb, struct mlx5_core_dev,
+ priv.sf_table_vhca_nb);
+ struct mlx5_sf_table *table = dev->priv.sf_table;
const struct mlx5_vhca_state_event *event = data;
bool update = false;
struct mlx5_sf *sf;
+ if (!table)
+ return 0;
+
mutex_lock(&table->sf_state_lock);
sf = mlx5_sf_lookup_by_function_id(table, event->function_id);
if (!sf)
update = mlx5_sf_state_update_check(sf, event->new_vhca_state);
if (update)
sf->hw_state = event->new_vhca_state;
- trace_mlx5_sf_update_state(table->dev, sf->port_index, sf->controller,
+ trace_mlx5_sf_update_state(dev, sf->port_index, sf->controller,
sf->hw_fn_id, sf->hw_state);
unlock:
mutex_unlock(&table->sf_state_lock);
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);
+ struct mlx5_core_dev *dev = container_of(nb, struct mlx5_core_dev,
+ priv.sf_table_esw_nb);
const struct mlx5_esw_event_info *mode = data;
+ if (!dev->priv.sf_table)
+ return 0;
+
switch (mode->new_mode) {
case MLX5_ESWITCH_LEGACY:
- mlx5_sf_del_all(table);
+ mlx5_sf_del_all(dev->priv.sf_table);
break;
default:
break;
static int mlx5_sf_mdev_event(struct notifier_block *nb, unsigned long event, void *data)
{
- struct mlx5_sf_table *table = container_of(nb, struct mlx5_sf_table, mdev_nb);
+ struct mlx5_core_dev *dev = container_of(nb, struct mlx5_core_dev,
+ priv.sf_table_mdev_nb);
struct mlx5_sf_peer_devlink_event_ctx *event_ctx = data;
+ struct mlx5_sf_table *table = dev->priv.sf_table;
int ret = NOTIFY_DONE;
struct mlx5_sf *sf;
- if (event != MLX5_DRIVER_EVENT_SF_PEER_DEVLINK)
+ if (!table || event != MLX5_DRIVER_EVENT_SF_PEER_DEVLINK)
return NOTIFY_DONE;
-
mutex_lock(&table->sf_state_lock);
sf = mlx5_sf_lookup_by_function_id(table, event_ctx->fn_id);
if (!sf)
return ret;
}
+int mlx5_sf_notifiers_init(struct mlx5_core_dev *dev)
+{
+ int err;
+
+ if (mlx5_core_is_sf(dev))
+ return 0;
+
+ dev->priv.sf_table_esw_nb.notifier_call = mlx5_sf_esw_event;
+ err = mlx5_esw_event_notifier_register(dev, &dev->priv.sf_table_esw_nb);
+ if (err)
+ return err;
+
+ dev->priv.sf_table_vhca_nb.notifier_call = mlx5_sf_vhca_event;
+ err = mlx5_vhca_event_notifier_register(dev,
+ &dev->priv.sf_table_vhca_nb);
+ if (err)
+ goto vhca_err;
+
+ dev->priv.sf_table_mdev_nb.notifier_call = mlx5_sf_mdev_event;
+ err = mlx5_blocking_notifier_register(dev, &dev->priv.sf_table_mdev_nb);
+ if (err)
+ goto mdev_err;
+
+ return 0;
+mdev_err:
+ mlx5_vhca_event_notifier_unregister(dev, &dev->priv.sf_table_vhca_nb);
+vhca_err:
+ mlx5_esw_event_notifier_unregister(dev, &dev->priv.sf_table_esw_nb);
+ return err;
+}
+
int mlx5_sf_table_init(struct mlx5_core_dev *dev)
{
struct mlx5_sf_table *table;
- int err;
if (!mlx5_sf_table_supported(dev) || !mlx5_vhca_event_supported(dev))
return 0;
table->dev = dev;
xa_init(&table->function_ids);
dev->priv.sf_table = table;
- table->esw_nb.notifier_call = mlx5_sf_esw_event;
- err = mlx5_esw_event_notifier_register(dev, &table->esw_nb);
- if (err)
- goto reg_err;
-
- table->vhca_nb.notifier_call = mlx5_sf_vhca_event;
- err = mlx5_vhca_event_notifier_register(table->dev, &table->vhca_nb);
- if (err)
- goto vhca_err;
-
- table->mdev_nb.notifier_call = mlx5_sf_mdev_event;
- mlx5_blocking_notifier_register(dev, &table->mdev_nb);
return 0;
+}
-vhca_err:
- mlx5_esw_event_notifier_unregister(dev, &table->esw_nb);
-reg_err:
- mutex_destroy(&table->sf_state_lock);
- kfree(table);
- dev->priv.sf_table = NULL;
- return err;
+void mlx5_sf_notifiers_cleanup(struct mlx5_core_dev *dev)
+{
+ if (mlx5_core_is_sf(dev))
+ return;
+
+ mlx5_blocking_notifier_unregister(dev, &dev->priv.sf_table_mdev_nb);
+ mlx5_vhca_event_notifier_unregister(dev, &dev->priv.sf_table_vhca_nb);
+ mlx5_esw_event_notifier_unregister(dev, &dev->priv.sf_table_esw_nb);
}
void mlx5_sf_table_cleanup(struct mlx5_core_dev *dev)
if (!table)
return;
- mlx5_blocking_notifier_unregister(dev, &table->mdev_nb);
- mlx5_vhca_event_notifier_unregister(table->dev, &table->vhca_nb);
- mlx5_esw_event_notifier_unregister(dev, &table->esw_nb);
mutex_destroy(&table->sf_state_lock);
WARN_ON(!xa_empty(&table->function_ids));
kfree(table);