1219820SjeffFrom 6f9c7b5c83a832884b3e47a6ce52145991073586 Mon Sep 17 00:00:00 2001
2219820SjeffFrom: Eli Cohen <eli@mellanox.co.il>
3219820SjeffDate: Sun, 19 Sep 2010 11:28:40 +0200
4219820SjeffSubject: [PATCH] libmlx4: fix possible inline size
5219820Sjeff
6219820SjeffThe current driver checks required inline size by making sure it does not
7219820Sjeffexceed 1024. This is wrong since the whole WQE is limited to 1008 bytes.
8219820SjeffMoreover, a more careful claculation is required to avoid cases where the
9219820Sjeffapplication requests inline support in a certain size that when used later
10219820Sjeffcould cause connections to stall due to bad WQEs. This patch takes into account
11219820Sjeffthe size of the WQE, the segements used to create a WQE and the overhead
12219820Sjeffincured by the inline segments themselves.
13219820Sjeff
14219820SjeffSigned-off-by: Eli Cohen <eli@mellanox.co.il>
15219820Sjeff---
16219820Sjeff src/verbs.c |   45 ++++++++++++++++++++++++++++++++++++++++-----
17219820Sjeff 1 files changed, 40 insertions(+), 5 deletions(-)
18219820Sjeff
19219820SjeffIndex: libmlx4/src/verbs.c
20219820Sjeff===================================================================
21219820Sjeff--- libmlx4.orig/src/verbs.c	2010-09-29 11:10:17.691587848 +0200
22219820Sjeff+++ libmlx4/src/verbs.c	2010-09-29 11:16:11.031586721 +0200
23219820Sjeff@@ -402,6 +402,44 @@ int mlx4_destroy_srq(struct ibv_srq *ibs
24219820Sjeff 	return 0;
25219820Sjeff }
26219820Sjeff 
27219820Sjeff+static int verify_sizes(struct ibv_qp_init_attr *attr, struct mlx4_context *context)
28219820Sjeff+{
29219820Sjeff+	int size;
30219820Sjeff+	int nsegs;
31219820Sjeff+
32219820Sjeff+	if (attr->cap.max_send_wr     > context->max_qp_wr ||
33219820Sjeff+	    attr->cap.max_recv_wr     > context->max_qp_wr ||
34219820Sjeff+	    attr->cap.max_send_sge    > context->max_sge   ||
35219820Sjeff+	    attr->cap.max_recv_sge    > context->max_sge)
36219820Sjeff+		return -1;
37219820Sjeff+
38219820Sjeff+	if (attr->cap.max_inline_data) {
39219820Sjeff+		nsegs = num_inline_segs(attr->cap.max_inline_data, attr->qp_type);
40219820Sjeff+		size = MLX4_MAX_WQE_SIZE - nsegs * sizeof (struct mlx4_wqe_inline_seg);
41219820Sjeff+		switch (attr->qp_type) {
42219820Sjeff+		case IBV_QPT_UD:
43219820Sjeff+			size -= (sizeof (struct mlx4_wqe_ctrl_seg) +
44219820Sjeff+				 sizeof (struct mlx4_wqe_datagram_seg));
45219820Sjeff+			break;
46219820Sjeff+
47219820Sjeff+		case IBV_QPT_RC:
48219820Sjeff+		case IBV_QPT_UC:
49219820Sjeff+		case IBV_QPT_XRC:
50219820Sjeff+			size -= (sizeof (struct mlx4_wqe_ctrl_seg) +
51219820Sjeff+				 sizeof (struct mlx4_wqe_raddr_seg));
52219820Sjeff+			break;
53219820Sjeff+
54219820Sjeff+		default:
55219820Sjeff+			return 0;
56219820Sjeff+		}
57219820Sjeff+
58219820Sjeff+		if (attr->cap.max_inline_data > size)
59219820Sjeff+			return -1;
60219820Sjeff+	}
61219820Sjeff+
62219820Sjeff+	return 0;
63219820Sjeff+}
64219820Sjeff+
65219820Sjeff struct ibv_qp *mlx4_create_qp(struct ibv_pd *pd, struct ibv_qp_init_attr *attr)
66219820Sjeff {
67219820Sjeff 	struct mlx4_create_qp     cmd;
68219820Sjeff@@ -412,11 +450,7 @@ struct ibv_qp *mlx4_create_qp(struct ibv
69219820Sjeff 
70219820Sjeff 
71219820Sjeff 	/* Sanity check QP size before proceeding */
72219820Sjeff-	if (attr->cap.max_send_wr     > context->max_qp_wr ||
73219820Sjeff-	    attr->cap.max_recv_wr     > context->max_qp_wr ||
74219820Sjeff-	    attr->cap.max_send_sge    > context->max_sge   ||
75219820Sjeff-	    attr->cap.max_recv_sge    > context->max_sge   ||
76219820Sjeff-	    attr->cap.max_inline_data > 1024)
77219820Sjeff+	if (verify_sizes(attr, context))
78219820Sjeff 		return NULL;
79219820Sjeff 
80219820Sjeff 	qp = malloc(sizeof *qp);
81219820SjeffIndex: libmlx4/src/mlx4.h
82219820Sjeff===================================================================
83219820Sjeff--- libmlx4.orig/src/mlx4.h	2010-09-29 11:10:17.691587848 +0200
84219820Sjeff+++ libmlx4/src/mlx4.h	2010-09-29 11:11:35.559586971 +0200
85219820Sjeff@@ -159,6 +159,10 @@ enum {
86219820Sjeff 	MLX4_CQE_OPCODE_RESIZE		= 0x16,
87219820Sjeff };
88219820Sjeff 
89219820Sjeff+enum {
90219820Sjeff+	MLX4_MAX_WQE_SIZE = 1008
91219820Sjeff+};
92219820Sjeff+
93219820Sjeff struct mlx4_device {
94219820Sjeff 	struct ibv_device		ibv_dev;
95219820Sjeff 	int				page_size;
96219820Sjeff@@ -410,6 +414,7 @@ int mlx4_post_recv(struct ibv_qp *ibqp, 
97219820Sjeff 			  struct ibv_recv_wr **bad_wr);
98219820Sjeff void mlx4_calc_sq_wqe_size(struct ibv_qp_cap *cap, enum ibv_qp_type type,
99219820Sjeff 			   struct mlx4_qp *qp);
100219820Sjeff+int num_inline_segs(int data, enum ibv_qp_type type);
101219820Sjeff int mlx4_alloc_qp_buf(struct ibv_pd *pd, struct ibv_qp_cap *cap,
102219820Sjeff 		       enum ibv_qp_type type, struct mlx4_qp *qp);
103219820Sjeff void mlx4_set_sq_sizes(struct mlx4_qp *qp, struct ibv_qp_cap *cap,
104219820SjeffIndex: libmlx4/src/qp.c
105219820Sjeff===================================================================
106219820Sjeff--- libmlx4.orig/src/qp.c	2010-09-29 11:10:17.691587848 +0200
107219820Sjeff+++ libmlx4/src/qp.c	2010-09-29 11:12:14.931587492 +0200
108219820Sjeff@@ -505,7 +505,7 @@ out:
109219820Sjeff 	return ret;
110219820Sjeff }
111219820Sjeff 
112219820Sjeff-static int num_inline_segs(int data, enum ibv_qp_type type)
113219820Sjeff+int num_inline_segs(int data, enum ibv_qp_type type)
114219820Sjeff {
115219820Sjeff 	/*
116219820Sjeff 	 * Inline data segments are not allowed to cross 64 byte
117219820Sjeff@@ -634,7 +634,8 @@ void mlx4_set_sq_sizes(struct mlx4_qp *q
118219820Sjeff 	int wqe_size;
119219820Sjeff 	struct mlx4_context *ctx = to_mctx(qp->ibv_qp.context);
120219820Sjeff 
121219820Sjeff-	wqe_size = (1 << qp->sq.wqe_shift) - sizeof (struct mlx4_wqe_ctrl_seg);
122219820Sjeff+	wqe_size = min((1 << qp->sq.wqe_shift), MLX4_MAX_WQE_SIZE) -
123219820Sjeff+		sizeof (struct mlx4_wqe_ctrl_seg);
124219820Sjeff 	switch (type) {
125219820Sjeff 	case IBV_QPT_UD:
126219820Sjeff 		wqe_size -= sizeof (struct mlx4_wqe_datagram_seg);
127