]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
RDMA/mlx5: Check enabled UCAPs when creating ucontext
authorChiara Meiohas <cmeiohas@nvidia.com>
Thu, 6 Mar 2025 11:51:29 +0000 (13:51 +0200)
committerLeon Romanovsky <leon@kernel.org>
Sun, 9 Mar 2025 17:13:02 +0000 (13:13 -0400)
Verify that the enabled UCAPs are supported by the device before
creating the ucontext.
If supported, create the ucontext with the associated capabilities.

Store the privileged ucontext UID on creation and remove it when
destroying the privileged ucontext. This allows the command interface
to recognize privileged commands through its UID.

Signed-off-by: Chiara Meiohas <cmeiohas@nvidia.com>
Link: https://patch.msgid.link/8b180583a207cb30deb7a2967934079749cdcc44.1741261611.git.leon@kernel.org
Reviewed-by: Yishai Hadas <yishaih@nvidia.com>
Signed-off-by: Leon Romanovsky <leon@kernel.org>
drivers/infiniband/hw/mlx5/devx.c
drivers/infiniband/hw/mlx5/devx.h
drivers/infiniband/hw/mlx5/main.c

index 39304cae5b10ee6b270b83b4879a14ce9838ce7c..2479da8620ca9185a570b5927b97cdf6268d5823 100644 (file)
@@ -13,6 +13,7 @@
 #include <rdma/uverbs_std_types.h>
 #include <linux/mlx5/driver.h>
 #include <linux/mlx5/fs.h>
+#include <rdma/ib_ucaps.h>
 #include "mlx5_ib.h"
 #include "devx.h"
 #include "qp.h"
@@ -122,7 +123,27 @@ devx_ufile2uctx(const struct uverbs_attr_bundle *attrs)
        return to_mucontext(ib_uverbs_get_ucontext(attrs));
 }
 
-int mlx5_ib_devx_create(struct mlx5_ib_dev *dev, bool is_user)
+static int set_uctx_ucaps(struct mlx5_ib_dev *dev, u64 req_ucaps, u32 *cap)
+{
+       if (UCAP_ENABLED(req_ucaps, RDMA_UCAP_MLX5_CTRL_LOCAL)) {
+               if (MLX5_CAP_GEN(dev->mdev, uctx_cap) & MLX5_UCTX_CAP_RDMA_CTRL)
+                       *cap |= MLX5_UCTX_CAP_RDMA_CTRL;
+               else
+                       return -EOPNOTSUPP;
+       }
+
+       if (UCAP_ENABLED(req_ucaps, RDMA_UCAP_MLX5_CTRL_OTHER_VHCA)) {
+               if (MLX5_CAP_GEN(dev->mdev, uctx_cap) &
+                   MLX5_UCTX_CAP_RDMA_CTRL_OTHER_VHCA)
+                       *cap |= MLX5_UCTX_CAP_RDMA_CTRL_OTHER_VHCA;
+               else
+                       return -EOPNOTSUPP;
+       }
+
+       return 0;
+}
+
+int mlx5_ib_devx_create(struct mlx5_ib_dev *dev, bool is_user, u64 req_ucaps)
 {
        u32 in[MLX5_ST_SZ_DW(create_uctx_in)] = {};
        u32 out[MLX5_ST_SZ_DW(create_uctx_out)] = {};
@@ -146,6 +167,12 @@ int mlx5_ib_devx_create(struct mlx5_ib_dev *dev, bool is_user)
            capable(CAP_SYS_RAWIO))
                cap |= MLX5_UCTX_CAP_INTERNAL_DEV_RES;
 
+       if (req_ucaps) {
+               err = set_uctx_ucaps(dev, req_ucaps, &cap);
+               if (err)
+                       return err;
+       }
+
        MLX5_SET(create_uctx_in, in, opcode, MLX5_CMD_OP_CREATE_UCTX);
        MLX5_SET(uctx, uctx, cap, cap);
 
@@ -2575,7 +2602,7 @@ int mlx5_ib_devx_init(struct mlx5_ib_dev *dev)
        struct mlx5_devx_event_table *table = &dev->devx_event_table;
        int uid;
 
-       uid = mlx5_ib_devx_create(dev, false);
+       uid = mlx5_ib_devx_create(dev, false, 0);
        if (uid > 0) {
                dev->devx_whitelist_uid = uid;
                xa_init(&table->event_xa);
index 1344bf4c9d21fe09a91d7536eb180f030d0b25ee..ee9e7d3af93ffcec1b7b6142e2e755075acbba1e 100644 (file)
@@ -24,13 +24,14 @@ struct devx_obj {
        struct list_head event_sub; /* holds devx_event_subscription entries */
 };
 #if IS_ENABLED(CONFIG_INFINIBAND_USER_ACCESS)
-int mlx5_ib_devx_create(struct mlx5_ib_dev *dev, bool is_user);
+int mlx5_ib_devx_create(struct mlx5_ib_dev *dev, bool is_user, u64 req_ucaps);
 void mlx5_ib_devx_destroy(struct mlx5_ib_dev *dev, u16 uid);
 int mlx5_ib_devx_init(struct mlx5_ib_dev *dev);
 void mlx5_ib_devx_cleanup(struct mlx5_ib_dev *dev);
 void mlx5_ib_ufile_hw_cleanup(struct ib_uverbs_file *ufile);
 #else
-static inline int mlx5_ib_devx_create(struct mlx5_ib_dev *dev, bool is_user)
+static inline int mlx5_ib_devx_create(struct mlx5_ib_dev *dev, bool is_user,
+                                     u64 req_ucaps)
 {
        return -EOPNOTSUPP;
 }
index 04b489a6a44931f5712d6a7d7f0803c423c54a6a..d07cacaa0abd00488fd34bd05a3dd65fe9c7fe68 100644 (file)
@@ -1935,6 +1935,12 @@ static int set_ucontext_resp(struct ib_ucontext *uctx,
        return 0;
 }
 
+static bool uctx_rdma_ctrl_is_enabled(u64 enabled_caps)
+{
+       return UCAP_ENABLED(enabled_caps, RDMA_UCAP_MLX5_CTRL_LOCAL) ||
+              UCAP_ENABLED(enabled_caps, RDMA_UCAP_MLX5_CTRL_OTHER_VHCA);
+}
+
 static int mlx5_ib_alloc_ucontext(struct ib_ucontext *uctx,
                                  struct ib_udata *udata)
 {
@@ -1977,10 +1983,17 @@ static int mlx5_ib_alloc_ucontext(struct ib_ucontext *uctx,
                return -EINVAL;
 
        if (req.flags & MLX5_IB_ALLOC_UCTX_DEVX) {
-               err = mlx5_ib_devx_create(dev, true);
+               err = mlx5_ib_devx_create(dev, true, uctx->enabled_caps);
                if (err < 0)
                        goto out_ctx;
                context->devx_uid = err;
+
+               if (uctx_rdma_ctrl_is_enabled(uctx->enabled_caps)) {
+                       err = mlx5_cmd_add_privileged_uid(dev->mdev,
+                                                         context->devx_uid);
+                       if (err)
+                               goto out_devx;
+               }
        }
 
        lib_uar_4k = req.lib_caps & MLX5_LIB_CAP_4K_UAR;
@@ -1995,7 +2008,7 @@ static int mlx5_ib_alloc_ucontext(struct ib_ucontext *uctx,
        /* updates req->total_num_bfregs */
        err = calc_total_bfregs(dev, lib_uar_4k, &req, bfregi);
        if (err)
-               goto out_devx;
+               goto out_ucap;
 
        mutex_init(&bfregi->lock);
        bfregi->lib_uar_4k = lib_uar_4k;
@@ -2003,7 +2016,7 @@ static int mlx5_ib_alloc_ucontext(struct ib_ucontext *uctx,
                                GFP_KERNEL);
        if (!bfregi->count) {
                err = -ENOMEM;
-               goto out_devx;
+               goto out_ucap;
        }
 
        bfregi->sys_pages = kcalloc(bfregi->num_sys_pages,
@@ -2067,6 +2080,11 @@ out_sys_pages:
 out_count:
        kfree(bfregi->count);
 
+out_ucap:
+       if (req.flags & MLX5_IB_ALLOC_UCTX_DEVX &&
+           uctx_rdma_ctrl_is_enabled(uctx->enabled_caps))
+               mlx5_cmd_remove_privileged_uid(dev->mdev, context->devx_uid);
+
 out_devx:
        if (req.flags & MLX5_IB_ALLOC_UCTX_DEVX)
                mlx5_ib_devx_destroy(dev, context->devx_uid);
@@ -2111,8 +2129,12 @@ static void mlx5_ib_dealloc_ucontext(struct ib_ucontext *ibcontext)
        kfree(bfregi->sys_pages);
        kfree(bfregi->count);
 
-       if (context->devx_uid)
+       if (context->devx_uid) {
+               if (uctx_rdma_ctrl_is_enabled(ibcontext->enabled_caps))
+                       mlx5_cmd_remove_privileged_uid(dev->mdev,
+                                                      context->devx_uid);
                mlx5_ib_devx_destroy(dev, context->devx_uid);
+       }
 }
 
 static phys_addr_t uar_index2pfn(struct mlx5_ib_dev *dev,