IB/mlx5: Fix reported max SGE calculation
authorEli Cohen <eli@mellanox.com>
Thu, 27 Oct 2016 13:36:45 +0000 (16:36 +0300)
committerDoug Ledford <dledford@redhat.com>
Thu, 17 Nov 2016 01:04:48 +0000 (20:04 -0500)
Add the 512 bytes limit of RDMA READ and the size of remote
address to the max SGE calculation.

Fixes: e126ba97dba9 ('mlx5: Add driver for Mellanox Connect-IB adapters')
Signed-off-by: Eli Cohen <eli@mellanox.com>
Signed-off-by: Maor Gottlieb <maorg@mellanox.com>
Signed-off-by: Leon Romanovsky <leon@kernel.org>
Signed-off-by: Doug Ledford <dledford@redhat.com>
drivers/infiniband/hw/mlx5/main.c
drivers/infiniband/hw/mlx5/qp.c

index 16ac41d89dfcfc27de7ef452357e8a84d1ed6d7b..46facd30e6727f5a1e4ab17a2aaa58fce0924a88 100644 (file)
@@ -496,6 +496,7 @@ static int mlx5_ib_query_device(struct ib_device *ibdev,
        struct mlx5_ib_dev *dev = to_mdev(ibdev);
        struct mlx5_core_dev *mdev = dev->mdev;
        int err = -ENOMEM;
+       int max_sq_desc;
        int max_rq_sg;
        int max_sq_sg;
        u64 min_page_size = 1ull << MLX5_CAP_GEN(mdev, log_pg_sz);
@@ -618,9 +619,10 @@ static int mlx5_ib_query_device(struct ib_device *ibdev,
        props->max_qp_wr           = 1 << MLX5_CAP_GEN(mdev, log_max_qp_sz);
        max_rq_sg =  MLX5_CAP_GEN(mdev, max_wqe_sz_rq) /
                     sizeof(struct mlx5_wqe_data_seg);
-       max_sq_sg = (MLX5_CAP_GEN(mdev, max_wqe_sz_sq) -
-                    sizeof(struct mlx5_wqe_ctrl_seg)) /
-                    sizeof(struct mlx5_wqe_data_seg);
+       max_sq_desc = min_t(int, MLX5_CAP_GEN(mdev, max_wqe_sz_sq), 512);
+       max_sq_sg = (max_sq_desc - sizeof(struct mlx5_wqe_ctrl_seg) -
+                    sizeof(struct mlx5_wqe_raddr_seg)) /
+               sizeof(struct mlx5_wqe_data_seg);
        props->max_sge = min(max_rq_sg, max_sq_sg);
        props->max_sge_rd          = MLX5_MAX_SGE_RD;
        props->max_cq              = 1 << MLX5_CAP_GEN(mdev, log_max_cq);
index 5bdf20c676fee0e6d37f5d550ba26f1f15f3a61d..c84b07f9f111f3bcc8d55bbd474371f441b833ad 100644 (file)
@@ -352,6 +352,29 @@ static int calc_send_wqe(struct ib_qp_init_attr *attr)
                return ALIGN(max_t(int, inl_size, size), MLX5_SEND_WQE_BB);
 }
 
+static int get_send_sge(struct ib_qp_init_attr *attr, int wqe_size)
+{
+       int max_sge;
+
+       if (attr->qp_type == IB_QPT_RC)
+               max_sge = (min_t(int, wqe_size, 512) -
+                          sizeof(struct mlx5_wqe_ctrl_seg) -
+                          sizeof(struct mlx5_wqe_raddr_seg)) /
+                       sizeof(struct mlx5_wqe_data_seg);
+       else if (attr->qp_type == IB_QPT_XRC_INI)
+               max_sge = (min_t(int, wqe_size, 512) -
+                          sizeof(struct mlx5_wqe_ctrl_seg) -
+                          sizeof(struct mlx5_wqe_xrc_seg) -
+                          sizeof(struct mlx5_wqe_raddr_seg)) /
+                       sizeof(struct mlx5_wqe_data_seg);
+       else
+               max_sge = (wqe_size - sq_overhead(attr)) /
+                       sizeof(struct mlx5_wqe_data_seg);
+
+       return min_t(int, max_sge, wqe_size - sq_overhead(attr) /
+                    sizeof(struct mlx5_wqe_data_seg));
+}
+
 static int calc_sq_size(struct mlx5_ib_dev *dev, struct ib_qp_init_attr *attr,
                        struct mlx5_ib_qp *qp)
 {
@@ -388,7 +411,11 @@ static int calc_sq_size(struct mlx5_ib_dev *dev, struct ib_qp_init_attr *attr,
                return -ENOMEM;
        }
        qp->sq.wqe_shift = ilog2(MLX5_SEND_WQE_BB);
-       qp->sq.max_gs = attr->cap.max_send_sge;
+       qp->sq.max_gs = get_send_sge(attr, wqe_size);
+       if (qp->sq.max_gs < attr->cap.max_send_sge)
+               return -ENOMEM;
+
+       attr->cap.max_send_sge = qp->sq.max_gs;
        qp->sq.max_post = wq_size / wqe_size;
        attr->cap.max_send_wr = qp->sq.max_post;