Merge tag 'perf-tools-for-v5.15-2021-09-11' of git://git.kernel.org/pub/scm/linux...
[linux-2.6-microblaze.git] / drivers / vdpa / mlx5 / core / resources.c
index 6521cbd..15e266d 100644 (file)
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
 /* Copyright (c) 2020 Mellanox Technologies Ltd. */
 
+#include <linux/iova.h>
 #include <linux/mlx5/driver.h>
 #include "mlx5_vdpa.h"
 
@@ -54,6 +55,9 @@ static int create_uctx(struct mlx5_vdpa_dev *mvdev, u16 *uid)
        void *in;
        int err;
 
+       if (MLX5_CAP_GEN(mvdev->mdev, umem_uid_0))
+               return 0;
+
        /* 0 means not supported */
        if (!MLX5_CAP_GEN(mvdev->mdev, log_max_uctx))
                return -EOPNOTSUPP;
@@ -79,6 +83,9 @@ static void destroy_uctx(struct mlx5_vdpa_dev *mvdev, u32 uid)
        u32 out[MLX5_ST_SZ_DW(destroy_uctx_out)] = {};
        u32 in[MLX5_ST_SZ_DW(destroy_uctx_in)] = {};
 
+       if (!uid)
+               return;
+
        MLX5_SET(destroy_uctx_in, in, opcode, MLX5_CMD_OP_DESTROY_UCTX);
        MLX5_SET(destroy_uctx_in, in, uid, uid);
 
@@ -122,6 +129,16 @@ int mlx5_vdpa_create_rqt(struct mlx5_vdpa_dev *mvdev, void *in, int inlen, u32 *
        return err;
 }
 
+int mlx5_vdpa_modify_rqt(struct mlx5_vdpa_dev *mvdev, void *in, int inlen, u32 rqtn)
+{
+       u32 out[MLX5_ST_SZ_DW(create_rqt_out)] = {};
+
+       MLX5_SET(modify_rqt_in, in, uid, mvdev->res.uid);
+       MLX5_SET(modify_rqt_in, in, rqtn, rqtn);
+       MLX5_SET(modify_rqt_in, in, opcode, MLX5_CMD_OP_MODIFY_RQT);
+       return mlx5_cmd_exec(mvdev->mdev, in, inlen, out, sizeof(out));
+}
+
 void mlx5_vdpa_destroy_rqt(struct mlx5_vdpa_dev *mvdev, u32 rqtn)
 {
        u32 in[MLX5_ST_SZ_DW(destroy_rqt_in)] = {};
@@ -215,6 +232,22 @@ int mlx5_vdpa_destroy_mkey(struct mlx5_vdpa_dev *mvdev, struct mlx5_core_mkey *m
        return mlx5_cmd_exec_in(mvdev->mdev, destroy_mkey, in);
 }
 
+static int init_ctrl_vq(struct mlx5_vdpa_dev *mvdev)
+{
+       mvdev->cvq.iotlb = vhost_iotlb_alloc(0, 0);
+       if (!mvdev->cvq.iotlb)
+               return -ENOMEM;
+
+       vringh_set_iotlb(&mvdev->cvq.vring, mvdev->cvq.iotlb, &mvdev->cvq.iommu_lock);
+
+       return 0;
+}
+
+static void cleanup_ctrl_vq(struct mlx5_vdpa_dev *mvdev)
+{
+       vhost_iotlb_free(mvdev->cvq.iotlb);
+}
+
 int mlx5_vdpa_alloc_resources(struct mlx5_vdpa_dev *mvdev)
 {
        u64 offset = MLX5_CAP64_DEV_VDPA_EMULATION(mvdev->mdev, doorbell_bar_offset);
@@ -247,16 +280,24 @@ int mlx5_vdpa_alloc_resources(struct mlx5_vdpa_dev *mvdev)
                goto err_key;
 
        kick_addr = mdev->bar_addr + offset;
+       res->phys_kick_addr = kick_addr;
 
        res->kick_addr = ioremap(kick_addr, PAGE_SIZE);
        if (!res->kick_addr) {
                err = -ENOMEM;
                goto err_key;
        }
+
+       err = init_ctrl_vq(mvdev);
+       if (err)
+               goto err_ctrl;
+
        res->valid = true;
 
        return 0;
 
+err_ctrl:
+       iounmap(res->kick_addr);
 err_key:
        dealloc_pd(mvdev, res->pdn, res->uid);
 err_pd:
@@ -275,6 +316,7 @@ void mlx5_vdpa_free_resources(struct mlx5_vdpa_dev *mvdev)
        if (!res->valid)
                return;
 
+       cleanup_ctrl_vq(mvdev);
        iounmap(res->kick_addr);
        res->kick_addr = NULL;
        dealloc_pd(mvdev, res->pdn, res->uid);