#include <rdma/uverbs_ioctl.h>
 #include <rdma/mlx5_user_ioctl_verbs.h>
 #include <rdma/mlx5_user_ioctl_cmds.h>
+#include <rdma/ib_ucaps.h>
 #include "macsec.h"
 #include "data_direct.h"
 
        return (var_table->bitmap) ? 0 : -ENOMEM;
 }
 
+static void mlx5_ib_cleanup_ucaps(struct mlx5_ib_dev *dev)
+{
+       if (MLX5_CAP_GEN(dev->mdev, uctx_cap) & MLX5_UCTX_CAP_RDMA_CTRL)
+               ib_remove_ucap(RDMA_UCAP_MLX5_CTRL_LOCAL);
+
+       if (MLX5_CAP_GEN(dev->mdev, uctx_cap) &
+           MLX5_UCTX_CAP_RDMA_CTRL_OTHER_VHCA)
+               ib_remove_ucap(RDMA_UCAP_MLX5_CTRL_OTHER_VHCA);
+}
+
+static int mlx5_ib_init_ucaps(struct mlx5_ib_dev *dev)
+{
+       int ret;
+
+       if (MLX5_CAP_GEN(dev->mdev, uctx_cap) & MLX5_UCTX_CAP_RDMA_CTRL) {
+               ret = ib_create_ucap(RDMA_UCAP_MLX5_CTRL_LOCAL);
+               if (ret)
+                       return ret;
+       }
+
+       if (MLX5_CAP_GEN(dev->mdev, uctx_cap) &
+           MLX5_UCTX_CAP_RDMA_CTRL_OTHER_VHCA) {
+               ret = ib_create_ucap(RDMA_UCAP_MLX5_CTRL_OTHER_VHCA);
+               if (ret)
+                       goto remove_local;
+       }
+
+       return 0;
+
+remove_local:
+       if (MLX5_CAP_GEN(dev->mdev, uctx_cap) & MLX5_UCTX_CAP_RDMA_CTRL)
+               ib_remove_ucap(RDMA_UCAP_MLX5_CTRL_LOCAL);
+       return ret;
+}
+
 static void mlx5_ib_stage_caps_cleanup(struct mlx5_ib_dev *dev)
 {
+       if (MLX5_CAP_GEN_2_64(dev->mdev, general_obj_types_127_64) &
+           MLX5_HCA_CAP_2_GENERAL_OBJECT_TYPES_RDMA_CTRL)
+               mlx5_ib_cleanup_ucaps(dev);
+
        bitmap_free(dev->var_table.bitmap);
 }
 
                        return err;
        }
 
+       if (MLX5_CAP_GEN_2_64(dev->mdev, general_obj_types_127_64) &
+           MLX5_HCA_CAP_2_GENERAL_OBJECT_TYPES_RDMA_CTRL) {
+               err = mlx5_ib_init_ucaps(dev);
+               if (err)
+                       return err;
+       }
+
        dev->ib_dev.use_cq_dim = true;
 
        return 0;