IB/mlx5: Enable QP creation with a given blue flame index
authorYishai Hadas <yishaih@mellanox.com>
Sun, 24 Dec 2017 14:31:36 +0000 (16:31 +0200)
committerJason Gunthorpe <jgg@mellanox.com>
Thu, 28 Dec 2017 18:37:46 +0000 (11:37 -0700)
This patch enables QP creation with a given BF index, this allows the
user space driver to share same BF between few QPs or alternatively have
a dedicated BF per QP.

Signed-off-by: Yishai Hadas <yishaih@mellanox.com>
Signed-off-by: Leon Romanovsky <leon@kernel.org>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
drivers/infiniband/hw/mlx5/mlx5_ib.h
drivers/infiniband/hw/mlx5/qp.c
include/uapi/rdma/mlx5-abi.h

index 6c0bdc9a92c4dadc63da16abb6082052e35a37d0..5fabd5807db63393b08c54f00a607a96a7260fd4 100644 (file)
@@ -115,6 +115,7 @@ enum {
 
 enum {
        MLX5_IB_INVALID_UAR_INDEX       = BIT(31),
+       MLX5_IB_INVALID_BFREG           = BIT(31),
 };
 
 struct mlx5_ib_vma_private_data {
index ddf52dc4a78a4f5f6dae3ed84ee63eebee6a96a0..45b9aba599c892292c277a5cb67f71c52ae863ab 100644 (file)
@@ -627,7 +627,8 @@ static void mlx5_ib_unlock_cqs(struct mlx5_ib_cq *send_cq,
                               struct mlx5_ib_cq *recv_cq);
 
 static int bfregn_to_uar_index(struct mlx5_ib_dev *dev,
-                              struct mlx5_bfreg_info *bfregi, int bfregn)
+                              struct mlx5_bfreg_info *bfregi, int bfregn,
+                              bool dyn_bfreg)
 {
        int bfregs_per_sys_page;
        int index_of_sys_page;
@@ -637,8 +638,16 @@ static int bfregn_to_uar_index(struct mlx5_ib_dev *dev,
                                MLX5_NON_FP_BFREGS_PER_UAR;
        index_of_sys_page = bfregn / bfregs_per_sys_page;
 
-       offset = bfregn % bfregs_per_sys_page / MLX5_NON_FP_BFREGS_PER_UAR;
+       if (dyn_bfreg) {
+               index_of_sys_page += bfregi->num_static_sys_pages;
+               if (bfregn > bfregi->num_dyn_bfregs ||
+                   bfregi->sys_pages[index_of_sys_page] == MLX5_IB_INVALID_UAR_INDEX) {
+                       mlx5_ib_dbg(dev, "Invalid dynamic uar index\n");
+                       return -EINVAL;
+               }
+       }
 
+       offset = bfregn % bfregs_per_sys_page / MLX5_NON_FP_BFREGS_PER_UAR;
        return bfregi->sys_pages[index_of_sys_page] + offset;
 }
 
@@ -764,7 +773,7 @@ static int create_user_qp(struct mlx5_ib_dev *dev, struct ib_pd *pd,
        struct mlx5_ib_create_qp ucmd;
        struct mlx5_ib_ubuffer *ubuffer = &base->ubuffer;
        int page_shift = 0;
-       int uar_index;
+       int uar_index = 0;
        int npages;
        u32 offset = 0;
        int bfregn;
@@ -780,12 +789,20 @@ static int create_user_qp(struct mlx5_ib_dev *dev, struct ib_pd *pd,
        }
 
        context = to_mucontext(pd->uobject->context);
-       /*
-        * TBD: should come from the verbs when we have the API
-        */
-       if (qp->flags & MLX5_IB_QP_CROSS_CHANNEL)
+       if (ucmd.flags & MLX5_QP_FLAG_BFREG_INDEX) {
+               uar_index = bfregn_to_uar_index(dev, &context->bfregi,
+                                               ucmd.bfreg_index, true);
+               if (uar_index < 0)
+                       return uar_index;
+
+               bfregn = MLX5_IB_INVALID_BFREG;
+       } else if (qp->flags & MLX5_IB_QP_CROSS_CHANNEL) {
+               /*
+                * TBD: should come from the verbs when we have the API
+                */
                /* In CROSS_CHANNEL CQ and QP must use the same UAR */
                bfregn = MLX5_CROSS_CHANNEL_BFREG;
+       }
        else {
                bfregn = alloc_bfreg(dev, &context->bfregi, MLX5_IB_LATENCY_CLASS_HIGH);
                if (bfregn < 0) {
@@ -804,8 +821,10 @@ static int create_user_qp(struct mlx5_ib_dev *dev, struct ib_pd *pd,
                }
        }
 
-       uar_index = bfregn_to_uar_index(dev, &context->bfregi, bfregn);
        mlx5_ib_dbg(dev, "bfregn 0x%x, uar_index 0x%x\n", bfregn, uar_index);
+       if (bfregn != MLX5_IB_INVALID_BFREG)
+               uar_index = bfregn_to_uar_index(dev, &context->bfregi, bfregn,
+                                               false);
 
        qp->rq.offset = 0;
        qp->sq.wqe_shift = ilog2(MLX5_SEND_WQE_BB);
@@ -845,7 +864,10 @@ static int create_user_qp(struct mlx5_ib_dev *dev, struct ib_pd *pd,
        MLX5_SET(qpc, qpc, page_offset, offset);
 
        MLX5_SET(qpc, qpc, uar_page, uar_index);
-       resp->bfreg_index = adjust_bfregn(dev, &context->bfregi, bfregn);
+       if (bfregn != MLX5_IB_INVALID_BFREG)
+               resp->bfreg_index = adjust_bfregn(dev, &context->bfregi, bfregn);
+       else
+               resp->bfreg_index = MLX5_IB_INVALID_BFREG;
        qp->bfregn = bfregn;
 
        err = mlx5_ib_db_map_user(context, ucmd.db_addr, &qp->db);
@@ -874,7 +896,8 @@ err_umem:
                ib_umem_release(ubuffer->umem);
 
 err_bfreg:
-       mlx5_ib_free_bfreg(dev, &context->bfregi, bfregn);
+       if (bfregn != MLX5_IB_INVALID_BFREG)
+               mlx5_ib_free_bfreg(dev, &context->bfregi, bfregn);
        return err;
 }
 
@@ -887,7 +910,13 @@ static void destroy_qp_user(struct mlx5_ib_dev *dev, struct ib_pd *pd,
        mlx5_ib_db_unmap_user(context, &qp->db);
        if (base->ubuffer.umem)
                ib_umem_release(base->ubuffer.umem);
-       mlx5_ib_free_bfreg(dev, &context->bfregi, qp->bfregn);
+
+       /*
+        * Free only the BFREGs which are handled by the kernel.
+        * BFREGs of UARs allocated dynamically are handled by user.
+        */
+       if (qp->bfregn != MLX5_IB_INVALID_BFREG)
+               mlx5_ib_free_bfreg(dev, &context->bfregi, qp->bfregn);
 }
 
 static int create_kernel_qp(struct mlx5_ib_dev *dev,
index 12c523a1dd182e472e44902f93154e0bb9b2b649..0f7e45680ce5dad431b551167709967a60991ca0 100644 (file)
@@ -41,6 +41,7 @@ enum {
        MLX5_QP_FLAG_SIGNATURE          = 1 << 0,
        MLX5_QP_FLAG_SCATTER_CQE        = 1 << 1,
        MLX5_QP_FLAG_TUNNEL_OFFLOADS    = 1 << 2,
+       MLX5_QP_FLAG_BFREG_INDEX        = 1 << 3,
 };
 
 enum {
@@ -282,7 +283,7 @@ struct mlx5_ib_create_qp {
        __u32   rq_wqe_shift;
        __u32   flags;
        __u32   uidx;
-       __u32   reserved0;
+       __u32   bfreg_index;
        __u64   sq_buf_addr;
 };