net/mlx5: SF, Implement peer devlink set for SF representor devlink port
authorJiri Pirko <jiri@nvidia.com>
Wed, 13 Sep 2023 07:12:40 +0000 (09:12 +0200)
committerDavid S. Miller <davem@davemloft.net>
Sun, 17 Sep 2023 13:01:47 +0000 (14:01 +0100)
Benefit from the existence of internal mlx5 notifier and extend it by
event MLX5_DRIVER_EVENT_SF_PEER_DEVLINK. Use this event from SF
auxiliary device probe/remove functions to pass the registered SF
devlink instance to the SF representor.

Process the new event in SF representor code and call
devl_port_fn_devlink_set() to do the assignments. Implement this in work
to avoid possible deadlock when probe/remove function of SF may be
called with devlink instance lock held during devlink reload.

Signed-off-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mellanox/mlx5/core/sf/dev/dev.h
drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c
drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c
include/linux/mlx5/device.h

index 2a66a427ef15a3eeb1ae7b10330e1a0a99866ac3..b99131e95e37e9940cc8877b842ea53a4e2e9548 100644 (file)
@@ -19,6 +19,12 @@ struct mlx5_sf_dev {
        u16 fn_id;
 };
 
+struct mlx5_sf_peer_devlink_event_ctx {
+       u16 fn_id;
+       struct devlink *devlink;
+       int err;
+};
+
 void mlx5_sf_dev_table_create(struct mlx5_core_dev *dev);
 void mlx5_sf_dev_table_destroy(struct mlx5_core_dev *dev);
 
index 8fe82f1191bb92694f96c1d1742f393405b43904..169c2c68ed5c254b45e33ee324abe1647d328a6e 100644 (file)
@@ -8,6 +8,20 @@
 #include "dev.h"
 #include "devlink.h"
 
+static int mlx5_core_peer_devlink_set(struct mlx5_sf_dev *sf_dev, struct devlink *devlink)
+{
+       struct mlx5_sf_peer_devlink_event_ctx event_ctx = {
+               .fn_id = sf_dev->fn_id,
+               .devlink = devlink,
+       };
+       int ret;
+
+       ret = mlx5_blocking_notifier_call_chain(sf_dev->parent_mdev,
+                                               MLX5_DRIVER_EVENT_SF_PEER_DEVLINK,
+                                               &event_ctx);
+       return ret == NOTIFY_OK ? event_ctx.err : 0;
+}
+
 static int mlx5_sf_dev_probe(struct auxiliary_device *adev, const struct auxiliary_device_id *id)
 {
        struct mlx5_sf_dev *sf_dev = container_of(adev, struct mlx5_sf_dev, adev);
@@ -54,9 +68,21 @@ static int mlx5_sf_dev_probe(struct auxiliary_device *adev, const struct auxilia
                mlx5_core_warn(mdev, "mlx5_init_one err=%d\n", err);
                goto init_one_err;
        }
+
+       err = mlx5_core_peer_devlink_set(sf_dev, devlink);
+       if (err) {
+               mlx5_core_warn(mdev, "mlx5_core_peer_devlink_set err=%d\n", err);
+               goto peer_devlink_set_err;
+       }
+
        devlink_register(devlink);
        return 0;
 
+peer_devlink_set_err:
+       if (mlx5_dev_is_lightweight(sf_dev->mdev))
+               mlx5_uninit_one_light(sf_dev->mdev);
+       else
+               mlx5_uninit_one(sf_dev->mdev);
 init_one_err:
        iounmap(mdev->iseg);
 remap_err:
index e34a8f88c518c123a6a74926a3e42b6ad59b549e..964a5b1876f303b6d446302ca8ca0e1bab82ce46 100644 (file)
@@ -28,6 +28,7 @@ struct mlx5_sf_table {
        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 *
@@ -511,6 +512,35 @@ static int mlx5_sf_esw_event(struct notifier_block *nb, unsigned long event, voi
        return 0;
 }
 
+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_sf_peer_devlink_event_ctx *event_ctx = data;
+       int ret = NOTIFY_DONE;
+       struct mlx5_sf *sf;
+
+       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);
+       if (!sf)
+               goto out;
+
+       event_ctx->err = devl_port_fn_devlink_set(&sf->dl_port.dl_port,
+                                                 event_ctx->devlink);
+
+       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) &&
@@ -544,6 +574,9 @@ int mlx5_sf_table_init(struct mlx5_core_dev *dev)
        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:
@@ -562,6 +595,7 @@ 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->priv.eswitch, &table->esw_nb);
        WARN_ON(refcount_read(&table->refcount));
index 4d5be378fa8cccd431c7d22cc24275efea4225bb..8fbe22de16ef566e8a5a7ba4fb0960fada92171d 100644 (file)
@@ -366,6 +366,7 @@ enum mlx5_driver_event {
        MLX5_DRIVER_EVENT_UPLINK_NETDEV,
        MLX5_DRIVER_EVENT_MACSEC_SA_ADDED,
        MLX5_DRIVER_EVENT_MACSEC_SA_DELETED,
+       MLX5_DRIVER_EVENT_SF_PEER_DEVLINK,
 };
 
 enum {