[ofa-general] [PATCH] libmlx4: Re-calculate number of inline segments

Vincent Rizza vinnie at sgi.com
Sun Oct 19 21:16:40 PDT 2008


From: Brett Grandbois <brettg at sgi.com>

Supplying an ibv_qp_cap.max_inline_data value of 460 for mlx4_create_qp
was getting back ENOMEM when the max should have been 928. Tracked the bug
to the inline segment calculation. Here's the fix.

Signed-off-by: Vincent Rizza <vinnie at sgi.com>
Signed-off-by: Brett Grandbois <brettg at sgi.com>
Signed-off-by: Greg Banks <gnb at sgi.com>
Signed-off-by: Max Matveev <makc at sgi.com>
Signed-off-by: Ken Sandars <ksandars at sgi.com>
---
 src/qp.c |   51 ++++++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 40 insertions(+), 11 deletions(-)

diff --git a/src/qp.c b/src/qp.c
index bb98c09..759ef51 100644
--- a/src/qp.c
+++ b/src/qp.c
@@ -497,6 +497,13 @@ out:
 
 static int num_inline_segs(int data, enum ibv_qp_type type)
 {
+	int initial_seg;
+	int num_segs = 0;
+
+	/* ask for nothing, get nothing */
+	if (!data)
+		goto out;
+
 	/*
 	 * Inline data segments are not allowed to cross 64 byte
 	 * boundaries.  For UD QPs, the data segments always start
@@ -505,18 +512,40 @@ static int num_inline_segs(int data, enum ibv_qp_type type)
 	 * control segment and possibly a 16 byte remote address
 	 * segment, so in the worst case there will be only 32 bytes
 	 * available for the first data segment.
+	 * So we need to do a little overhead processing only in the
+	 * case of a non-UD QP.
 	 */
-	if (type == IBV_QPT_UD)
-		data += (sizeof (struct mlx4_wqe_ctrl_seg) +
-			 sizeof (struct mlx4_wqe_datagram_seg)) %
-			MLX4_INLINE_ALIGN;
-	else
-		data += (sizeof (struct mlx4_wqe_ctrl_seg) +
-			 sizeof (struct mlx4_wqe_raddr_seg)) %
-			MLX4_INLINE_ALIGN;
+	if (type != IBV_QPT_UD) {
+
+		initial_seg = MLX4_INLINE_ALIGN -
+			(sizeof (struct mlx4_wqe_ctrl_seg)  +
+			 sizeof (struct mlx4_wqe_raddr_seg) +
+			 sizeof (struct mlx4_wqe_inline_seg));
+
+		num_segs = 1;
+		/*
+	 	 * no point continuing if everything fits in the
+	 	 * initial segment
+	 	 */
+		if (data <= initial_seg)
+			goto out;
 
-	return (data + MLX4_INLINE_ALIGN - sizeof (struct mlx4_wqe_inline_seg) - 1) /
-		(MLX4_INLINE_ALIGN - sizeof (struct mlx4_wqe_inline_seg));
+		/*
+		* If there's room in the initial segment, make sure we
+		* account for it before doing the full segment calcs
+		*/
+		data -= initial_seg;
+	}
+
+	/*  at this point we are just interested in how many segments are needed */
+	num_segs += data / (MLX4_INLINE_ALIGN - sizeof (struct mlx4_wqe_inline_seg));
+
+	/* account for any leftovers */
+	if (data % (MLX4_INLINE_ALIGN - sizeof (struct mlx4_wqe_inline_seg)))
+		num_segs++;
+
+out:
+	return num_segs;
 }
 
 void mlx4_calc_sq_wqe_size(struct ibv_qp_cap *cap, enum ibv_qp_type type,




More information about the general mailing list