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