1*9e39c5baSBill Taylor /*
2*9e39c5baSBill Taylor  * CDDL HEADER START
3*9e39c5baSBill Taylor  *
4*9e39c5baSBill Taylor  * The contents of this file are subject to the terms of the
5*9e39c5baSBill Taylor  * Common Development and Distribution License (the "License").
6*9e39c5baSBill Taylor  * You may not use this file except in compliance with the License.
7*9e39c5baSBill Taylor  *
8*9e39c5baSBill Taylor  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*9e39c5baSBill Taylor  * or http://www.opensolaris.org/os/licensing.
10*9e39c5baSBill Taylor  * See the License for the specific language governing permissions
11*9e39c5baSBill Taylor  * and limitations under the License.
12*9e39c5baSBill Taylor  *
13*9e39c5baSBill Taylor  * When distributing Covered Code, include this CDDL HEADER in each
14*9e39c5baSBill Taylor  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*9e39c5baSBill Taylor  * If applicable, add the following below this CDDL HEADER, with the
16*9e39c5baSBill Taylor  * fields enclosed by brackets "[]" replaced with your own identifying
17*9e39c5baSBill Taylor  * information: Portions Copyright [yyyy] [name of copyright owner]
18*9e39c5baSBill Taylor  *
19*9e39c5baSBill Taylor  * CDDL HEADER END
20*9e39c5baSBill Taylor  */
21*9e39c5baSBill Taylor 
22*9e39c5baSBill Taylor /*
23*9e39c5baSBill Taylor  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24*9e39c5baSBill Taylor  * Use is subject to license terms.
25*9e39c5baSBill Taylor  */
26*9e39c5baSBill Taylor 
27*9e39c5baSBill Taylor #include "dapl.h"
28*9e39c5baSBill Taylor #include "dapl_adapter_util.h"
29*9e39c5baSBill Taylor #include "dapl_lmr_util.h"
30*9e39c5baSBill Taylor #include "dapl_rmr_util.h"
31*9e39c5baSBill Taylor #include "dapl_cookie.h"
32*9e39c5baSBill Taylor 
33*9e39c5baSBill Taylor #include "dapl_tavor_ibtf_impl.h"
34*9e39c5baSBill Taylor 
35*9e39c5baSBill Taylor /*
36*9e39c5baSBill Taylor  *
37*9e39c5baSBill Taylor  *
38*9e39c5baSBill Taylor  * MODULE: dapl_tavor_ibtf_dto.c
39*9e39c5baSBill Taylor  *
40*9e39c5baSBill Taylor  * PURPOSE: Utility routines for data transfer operations
41*9e39c5baSBill Taylor  *
42*9e39c5baSBill Taylor  */
43*9e39c5baSBill Taylor 
44*9e39c5baSBill Taylor 
45*9e39c5baSBill Taylor /*
46*9e39c5baSBill Taylor  * dapls_ib_post_recv
47*9e39c5baSBill Taylor  *
48*9e39c5baSBill Taylor  * Provider specific Post RECV function
49*9e39c5baSBill Taylor  */
50*9e39c5baSBill Taylor DAT_RETURN
dapls_ib_post_recv(IN DAPL_EP * ep_ptr,IN DAPL_COOKIE * cookie,IN DAT_COUNT num_segments,IN DAT_LMR_TRIPLET * local_iov,IN DAT_COMPLETION_FLAGS completion_flags)51*9e39c5baSBill Taylor dapls_ib_post_recv(
52*9e39c5baSBill Taylor 	IN DAPL_EP		*ep_ptr,
53*9e39c5baSBill Taylor 	IN DAPL_COOKIE		*cookie,
54*9e39c5baSBill Taylor 	IN DAT_COUNT		num_segments,
55*9e39c5baSBill Taylor 	IN DAT_LMR_TRIPLET	*local_iov,
56*9e39c5baSBill Taylor 	IN DAT_COMPLETION_FLAGS completion_flags)
57*9e39c5baSBill Taylor {
58*9e39c5baSBill Taylor 	ibt_recv_wr_t		pr_wr;
59*9e39c5baSBill Taylor 	ibt_wr_ds_t		pr_sgl_arr[DAPL_MAX_IOV];
60*9e39c5baSBill Taylor 	ibt_wr_ds_t		*pr_sgl;
61*9e39c5baSBill Taylor 	boolean_t		suppress_notification;
62*9e39c5baSBill Taylor 	DAT_COUNT		total_len;
63*9e39c5baSBill Taylor 	int			retval;
64*9e39c5baSBill Taylor 	int			i;
65*9e39c5baSBill Taylor 
66*9e39c5baSBill Taylor 	total_len = 0;
67*9e39c5baSBill Taylor 
68*9e39c5baSBill Taylor 	if (ep_ptr->qp_handle == NULL) {
69*9e39c5baSBill Taylor 		dapl_dbg_log(DAPL_DBG_TYPE_EP, "dapls_ib_post_recv: "
70*9e39c5baSBill Taylor 		    "qp_handle == NULL\n");
71*9e39c5baSBill Taylor 		return (DAT_INVALID_PARAMETER);
72*9e39c5baSBill Taylor 	}
73*9e39c5baSBill Taylor 
74*9e39c5baSBill Taylor 	/* allocate scatter-gather list on the heap if its large */
75*9e39c5baSBill Taylor 	if (num_segments > DAPL_MAX_IOV) {
76*9e39c5baSBill Taylor 		pr_sgl = dapl_os_alloc(num_segments * sizeof (ibt_wr_ds_t));
77*9e39c5baSBill Taylor 		if (NULL == pr_sgl) {
78*9e39c5baSBill Taylor 			dapl_dbg_log(DAPL_DBG_TYPE_ERR,
79*9e39c5baSBill Taylor 			    "dapls_ib_post_recv: pr_sgl alloc failed");
80*9e39c5baSBill Taylor 			return (DAT_INSUFFICIENT_RESOURCES);
81*9e39c5baSBill Taylor 		}
82*9e39c5baSBill Taylor 	} else {
83*9e39c5baSBill Taylor 		pr_sgl = pr_sgl_arr;
84*9e39c5baSBill Taylor 	}
85*9e39c5baSBill Taylor 
86*9e39c5baSBill Taylor 	for (i = 0; i < num_segments; i++) {
87*9e39c5baSBill Taylor 		pr_sgl[i].ds_va = (ib_vaddr_t)local_iov[i].virtual_address;
88*9e39c5baSBill Taylor 		pr_sgl[i].ds_key = (ibt_lkey_t)local_iov[i].lmr_context;
89*9e39c5baSBill Taylor 		pr_sgl[i].ds_len = (ib_msglen_t)local_iov[i].segment_length;
90*9e39c5baSBill Taylor 
91*9e39c5baSBill Taylor 		total_len += pr_sgl[i].ds_len;
92*9e39c5baSBill Taylor 		dapl_dbg_log(DAPL_DBG_TYPE_EP, "dapls_ib_post_recv: "
93*9e39c5baSBill Taylor 		    "i(%d) va(%p), lmrctxt(0x%x), len(%llu)\n", i,
94*9e39c5baSBill Taylor 		    pr_sgl[i].ds_va, pr_sgl[i].ds_key, pr_sgl[i].ds_len);
95*9e39c5baSBill Taylor 	}
96*9e39c5baSBill Taylor 
97*9e39c5baSBill Taylor 	if (cookie != NULL) {
98*9e39c5baSBill Taylor 		cookie->val.dto.size =  total_len;
99*9e39c5baSBill Taylor 		dapl_dbg_log(DAPL_DBG_TYPE_EP,
100*9e39c5baSBill Taylor 		    "dapls_ib_post_recv: dto_cookie(%p), num_seg(%d), "
101*9e39c5baSBill Taylor 		    "size(%d) hkey(%016llx)\n", cookie, num_segments,
102*9e39c5baSBill Taylor 		    cookie->val.dto.size, ep_ptr->qp_handle->ep_hkey);
103*9e39c5baSBill Taylor 	}
104*9e39c5baSBill Taylor 
105*9e39c5baSBill Taylor 	pr_wr.wr_id = (ibt_wrid_t)(uintptr_t)cookie;
106*9e39c5baSBill Taylor 	pr_wr.wr_nds = (uint32_t)num_segments;
107*9e39c5baSBill Taylor 	if (num_segments > 0) {
108*9e39c5baSBill Taylor 		pr_wr.wr_sgl = &pr_sgl[0];
109*9e39c5baSBill Taylor 	} else {
110*9e39c5baSBill Taylor 		pr_wr.wr_sgl = NULL;
111*9e39c5baSBill Taylor 	}
112*9e39c5baSBill Taylor 
113*9e39c5baSBill Taylor 	if (ep_ptr->param.ep_attr.recv_completion_flags &
114*9e39c5baSBill Taylor 	    DAT_COMPLETION_UNSIGNALLED_FLAG) {
115*9e39c5baSBill Taylor 		/* This flag is used to control notification of completions */
116*9e39c5baSBill Taylor 		suppress_notification = (completion_flags &
117*9e39c5baSBill Taylor 		    DAT_COMPLETION_UNSIGNALLED_FLAG) ? B_TRUE : B_FALSE;
118*9e39c5baSBill Taylor 	} else {
119*9e39c5baSBill Taylor 		/*
120*9e39c5baSBill Taylor 		 * The evd waiter will use threshold to control wakeups
121*9e39c5baSBill Taylor 		 * Hence the event notification will be done via arming the
122*9e39c5baSBill Taylor 		 * CQ so we do not need special notification generation
123*9e39c5baSBill Taylor 		 * hence set suppression to true
124*9e39c5baSBill Taylor 		 */
125*9e39c5baSBill Taylor 		suppress_notification = B_TRUE;
126*9e39c5baSBill Taylor 	}
127*9e39c5baSBill Taylor 
128*9e39c5baSBill Taylor 	retval = DAPL_RECV(ep_ptr)(ep_ptr, &pr_wr, suppress_notification);
129*9e39c5baSBill Taylor 
130*9e39c5baSBill Taylor 	if (retval != 0) {
131*9e39c5baSBill Taylor 		dapl_dbg_log(DAPL_DBG_TYPE_EP,
132*9e39c5baSBill Taylor 		    "dapls_ib_post_recv: post_recv failed %s\n",
133*9e39c5baSBill Taylor 		    strerror(errno));
134*9e39c5baSBill Taylor 	}
135*9e39c5baSBill Taylor 
136*9e39c5baSBill Taylor 	/* free the pr_sgl if we had allocated it */
137*9e39c5baSBill Taylor 	if (num_segments > DAPL_MAX_IOV) {
138*9e39c5baSBill Taylor 		dapl_os_free(pr_sgl, num_segments*sizeof (ibt_wr_ds_t));
139*9e39c5baSBill Taylor 	}
140*9e39c5baSBill Taylor 
141*9e39c5baSBill Taylor 	return (retval);
142*9e39c5baSBill Taylor }
143*9e39c5baSBill Taylor 
144*9e39c5baSBill Taylor /*
145*9e39c5baSBill Taylor  * dapls_ib_post_recv_one
146*9e39c5baSBill Taylor  *
147*9e39c5baSBill Taylor  * Provider specific Post RECV function
148*9e39c5baSBill Taylor  */
149*9e39c5baSBill Taylor DAT_RETURN
dapls_ib_post_recv_one(IN DAPL_EP * ep_ptr,IN DAPL_COOKIE * cookie,IN DAT_LMR_TRIPLET * local_iov)150*9e39c5baSBill Taylor dapls_ib_post_recv_one(
151*9e39c5baSBill Taylor 	IN DAPL_EP		*ep_ptr,
152*9e39c5baSBill Taylor 	IN DAPL_COOKIE		*cookie,
153*9e39c5baSBill Taylor 	IN DAT_LMR_TRIPLET	*local_iov)
154*9e39c5baSBill Taylor {
155*9e39c5baSBill Taylor 	ibt_recv_wr_t		pr_wr;
156*9e39c5baSBill Taylor 	ibt_wr_ds_t		pr_sgl;
157*9e39c5baSBill Taylor 	boolean_t		suppress_notification;
158*9e39c5baSBill Taylor 	DAT_COUNT		total_len;
159*9e39c5baSBill Taylor 	int			retval;
160*9e39c5baSBill Taylor 
161*9e39c5baSBill Taylor 	if (ep_ptr->qp_handle == NULL) {
162*9e39c5baSBill Taylor 		dapl_dbg_log(DAPL_DBG_TYPE_EP, "dapls_ib_post_recv_one: "
163*9e39c5baSBill Taylor 		    "qp_handle == NULL\n");
164*9e39c5baSBill Taylor 		return (DAT_INVALID_PARAMETER);
165*9e39c5baSBill Taylor 	}
166*9e39c5baSBill Taylor 
167*9e39c5baSBill Taylor 	pr_sgl.ds_va = (ib_vaddr_t)local_iov->virtual_address;
168*9e39c5baSBill Taylor 	pr_sgl.ds_key = (ibt_lkey_t)local_iov->lmr_context;
169*9e39c5baSBill Taylor 	pr_sgl.ds_len = (ib_msglen_t)local_iov->segment_length;
170*9e39c5baSBill Taylor 
171*9e39c5baSBill Taylor 	total_len = pr_sgl.ds_len;
172*9e39c5baSBill Taylor 	dapl_dbg_log(DAPL_DBG_TYPE_EP, "dapls_ib_post_recv_one: "
173*9e39c5baSBill Taylor 	    "va(%p), lmrctxt(0x%x), len(%llu)\n",
174*9e39c5baSBill Taylor 	    pr_sgl.ds_va, pr_sgl.ds_key, pr_sgl.ds_len);
175*9e39c5baSBill Taylor 
176*9e39c5baSBill Taylor 	if (cookie != NULL) {
177*9e39c5baSBill Taylor 		cookie->val.dto.size =  total_len;
178*9e39c5baSBill Taylor 		dapl_dbg_log(DAPL_DBG_TYPE_EP,
179*9e39c5baSBill Taylor 		    "dapls_ib_post_recv_one: dto_cookie(%p), num_seg(1), "
180*9e39c5baSBill Taylor 		    "size(%d) hkey(%016llx)\n", cookie,
181*9e39c5baSBill Taylor 		    cookie->val.dto.size, ep_ptr->qp_handle->ep_hkey);
182*9e39c5baSBill Taylor 	}
183*9e39c5baSBill Taylor 
184*9e39c5baSBill Taylor 	pr_wr.wr_id = (ibt_wrid_t)(uintptr_t)cookie;
185*9e39c5baSBill Taylor 	pr_wr.wr_nds = 1;
186*9e39c5baSBill Taylor 	pr_wr.wr_sgl = &pr_sgl;
187*9e39c5baSBill Taylor 
188*9e39c5baSBill Taylor 	if (ep_ptr->param.ep_attr.recv_completion_flags &
189*9e39c5baSBill Taylor 	    DAT_COMPLETION_UNSIGNALLED_FLAG) {
190*9e39c5baSBill Taylor 		/* This flag is used to control notification of completions */
191*9e39c5baSBill Taylor 		suppress_notification = B_FALSE;
192*9e39c5baSBill Taylor 	} else {
193*9e39c5baSBill Taylor 		/*
194*9e39c5baSBill Taylor 		 * The evd waiter will use threshold to control wakeups
195*9e39c5baSBill Taylor 		 * Hence the event notification will be done via arming the
196*9e39c5baSBill Taylor 		 * CQ so we do not need special notification generation
197*9e39c5baSBill Taylor 		 * hence set suppression to true
198*9e39c5baSBill Taylor 		 */
199*9e39c5baSBill Taylor 		suppress_notification = B_TRUE;
200*9e39c5baSBill Taylor 	}
201*9e39c5baSBill Taylor 
202*9e39c5baSBill Taylor 	retval = DAPL_RECV(ep_ptr)(ep_ptr, &pr_wr, suppress_notification);
203*9e39c5baSBill Taylor 
204*9e39c5baSBill Taylor 	if (retval != 0) {
205*9e39c5baSBill Taylor 		dapl_dbg_log(DAPL_DBG_TYPE_EP,
206*9e39c5baSBill Taylor 		    "dapls_ib_post_recv_one: post_recv failed %s\n",
207*9e39c5baSBill Taylor 		    strerror(errno));
208*9e39c5baSBill Taylor 	}
209*9e39c5baSBill Taylor 
210*9e39c5baSBill Taylor 	return (retval);
211*9e39c5baSBill Taylor }
212*9e39c5baSBill Taylor 
213*9e39c5baSBill Taylor /*
214*9e39c5baSBill Taylor  * dapls_ib_srq_post_recv
215*9e39c5baSBill Taylor  *
216*9e39c5baSBill Taylor  * Provider specific SRQ Post RECV function
217*9e39c5baSBill Taylor  */
218*9e39c5baSBill Taylor DAT_RETURN
dapls_ib_post_srq(IN DAPL_SRQ * srq_ptr,IN DAPL_COOKIE * cookie,IN DAT_COUNT num_segments,IN DAT_LMR_TRIPLET * local_iov)219*9e39c5baSBill Taylor dapls_ib_post_srq(
220*9e39c5baSBill Taylor 	IN DAPL_SRQ		*srq_ptr,
221*9e39c5baSBill Taylor 	IN DAPL_COOKIE		*cookie,
222*9e39c5baSBill Taylor 	IN DAT_COUNT		num_segments,
223*9e39c5baSBill Taylor 	IN DAT_LMR_TRIPLET	*local_iov)
224*9e39c5baSBill Taylor {
225*9e39c5baSBill Taylor 	ibt_recv_wr_t		pr_wr;
226*9e39c5baSBill Taylor 	ibt_wr_ds_t		pr_sgl_arr[DAPL_MAX_IOV];
227*9e39c5baSBill Taylor 	ibt_wr_ds_t		*pr_sgl;
228*9e39c5baSBill Taylor 	DAT_COUNT		total_len;
229*9e39c5baSBill Taylor 	int			retval;
230*9e39c5baSBill Taylor 	int			i;
231*9e39c5baSBill Taylor 
232*9e39c5baSBill Taylor 	total_len = 0;
233*9e39c5baSBill Taylor 
234*9e39c5baSBill Taylor 	if (srq_ptr->srq_handle == NULL) {
235*9e39c5baSBill Taylor 		dapl_dbg_log(DAPL_DBG_TYPE_EP, "dapls_ib_post_srq: "
236*9e39c5baSBill Taylor 		    "srq_handle == NULL\n");
237*9e39c5baSBill Taylor 		return (DAT_INVALID_PARAMETER);
238*9e39c5baSBill Taylor 	}
239*9e39c5baSBill Taylor 
240*9e39c5baSBill Taylor 	/* allocate scatter-gather list on the heap if its large */
241*9e39c5baSBill Taylor 	if (num_segments > DAPL_MAX_IOV) {
242*9e39c5baSBill Taylor 		pr_sgl = dapl_os_alloc(num_segments * sizeof (ibt_wr_ds_t));
243*9e39c5baSBill Taylor 		if (NULL == pr_sgl) {
244*9e39c5baSBill Taylor 			dapl_dbg_log(DAPL_DBG_TYPE_ERR,
245*9e39c5baSBill Taylor 			    "dapls_ib_post_srq: pr_sgl alloc failed");
246*9e39c5baSBill Taylor 			return (DAT_INSUFFICIENT_RESOURCES);
247*9e39c5baSBill Taylor 		}
248*9e39c5baSBill Taylor 	} else {
249*9e39c5baSBill Taylor 		pr_sgl = pr_sgl_arr;
250*9e39c5baSBill Taylor 	}
251*9e39c5baSBill Taylor 
252*9e39c5baSBill Taylor 	for (i = 0; i < num_segments; i++) {
253*9e39c5baSBill Taylor 		pr_sgl[i].ds_va = (ib_vaddr_t)local_iov[i].virtual_address;
254*9e39c5baSBill Taylor 		pr_sgl[i].ds_key = (ibt_lkey_t)local_iov[i].lmr_context;
255*9e39c5baSBill Taylor 		pr_sgl[i].ds_len = (ib_msglen_t)local_iov[i].segment_length;
256*9e39c5baSBill Taylor 
257*9e39c5baSBill Taylor 		total_len += pr_sgl[i].ds_len;
258*9e39c5baSBill Taylor 		dapl_dbg_log(DAPL_DBG_TYPE_EP, "dapls_ib_post_srq: "
259*9e39c5baSBill Taylor 		    "i(%d) va(%p), lmrctxt(0x%x), len(%u)\n", i,
260*9e39c5baSBill Taylor 		    pr_sgl[i].ds_va, pr_sgl[i].ds_key, pr_sgl[i].ds_len);
261*9e39c5baSBill Taylor 	}
262*9e39c5baSBill Taylor 
263*9e39c5baSBill Taylor 	if (cookie != NULL) {
264*9e39c5baSBill Taylor 		cookie->val.dto.size =  total_len;
265*9e39c5baSBill Taylor 		dapl_dbg_log(DAPL_DBG_TYPE_EP,
266*9e39c5baSBill Taylor 		    "dapls_ib_post_srq: dto_cookie(%p), num_seg(%d), "
267*9e39c5baSBill Taylor 		    "size(%d) hkey(%016llx)\n", cookie, num_segments,
268*9e39c5baSBill Taylor 		    cookie->val.dto.size, srq_ptr->srq_handle->srq_hkey);
269*9e39c5baSBill Taylor 	}
270*9e39c5baSBill Taylor 
271*9e39c5baSBill Taylor 	pr_wr.wr_id = (ibt_wrid_t)(uintptr_t)cookie;
272*9e39c5baSBill Taylor 	pr_wr.wr_nds = (uint32_t)num_segments;
273*9e39c5baSBill Taylor 	if (num_segments > 0) {
274*9e39c5baSBill Taylor 		pr_wr.wr_sgl = &pr_sgl[0];
275*9e39c5baSBill Taylor 	} else {
276*9e39c5baSBill Taylor 		pr_wr.wr_sgl = NULL;
277*9e39c5baSBill Taylor 	}
278*9e39c5baSBill Taylor 
279*9e39c5baSBill Taylor 	retval = DAPL_SRECV(srq_ptr)(srq_ptr, &pr_wr, B_TRUE);
280*9e39c5baSBill Taylor 
281*9e39c5baSBill Taylor 	if (retval != 0) {
282*9e39c5baSBill Taylor 		dapl_dbg_log(DAPL_DBG_TYPE_EP,
283*9e39c5baSBill Taylor 		    "dapls_ib_post_srq: post_recv failed %s\n",
284*9e39c5baSBill Taylor 		    strerror(errno));
285*9e39c5baSBill Taylor 	}
286*9e39c5baSBill Taylor 
287*9e39c5baSBill Taylor 	/* free the pr_sgl if we had allocated it */
288*9e39c5baSBill Taylor 	if (num_segments > DAPL_MAX_IOV) {
289*9e39c5baSBill Taylor 		dapl_os_free(pr_sgl, num_segments*sizeof (ibt_wr_ds_t));
290*9e39c5baSBill Taylor 	}
291*9e39c5baSBill Taylor 
292*9e39c5baSBill Taylor 	return (retval);
293*9e39c5baSBill Taylor }
294*9e39c5baSBill Taylor 
295*9e39c5baSBill Taylor /*
296*9e39c5baSBill Taylor  * dapls_ib_post_send
297*9e39c5baSBill Taylor  *
298*9e39c5baSBill Taylor  * Provider specific Post SEND function
299*9e39c5baSBill Taylor  */
300*9e39c5baSBill Taylor DAT_RETURN
dapls_ib_post_send(IN DAPL_EP * ep_ptr,IN ib_send_op_type_t op_type,IN DAPL_COOKIE * cookie,IN DAT_COUNT num_segments,IN DAT_LMR_TRIPLET * local_iov,IN const DAT_RMR_TRIPLET * remote_iov,IN DAT_COMPLETION_FLAGS completion_flags)301*9e39c5baSBill Taylor dapls_ib_post_send(IN DAPL_EP *ep_ptr,
302*9e39c5baSBill Taylor     IN ib_send_op_type_t op_type,
303*9e39c5baSBill Taylor     IN DAPL_COOKIE *cookie,
304*9e39c5baSBill Taylor     IN DAT_COUNT num_segments,
305*9e39c5baSBill Taylor     IN DAT_LMR_TRIPLET *local_iov,
306*9e39c5baSBill Taylor     IN const DAT_RMR_TRIPLET *remote_iov,
307*9e39c5baSBill Taylor     IN DAT_COMPLETION_FLAGS completion_flags)
308*9e39c5baSBill Taylor {
309*9e39c5baSBill Taylor 	ibt_send_wr_t		ps_wr;
310*9e39c5baSBill Taylor 	ibt_wr_ds_t		ps_sgl_arr[DAPL_MAX_IOV];
311*9e39c5baSBill Taylor 	ibt_wr_ds_t		*ps_sgl;
312*9e39c5baSBill Taylor 	DAT_COUNT		total_len;
313*9e39c5baSBill Taylor 	boolean_t		suppress_notification;
314*9e39c5baSBill Taylor 	int			retval;
315*9e39c5baSBill Taylor 	int			i;
316*9e39c5baSBill Taylor 
317*9e39c5baSBill Taylor 	total_len = 0;
318*9e39c5baSBill Taylor 	retval = DAT_SUCCESS;
319*9e39c5baSBill Taylor 
320*9e39c5baSBill Taylor 	if (ep_ptr->qp_handle == NULL) {
321*9e39c5baSBill Taylor 		dapl_dbg_log(DAPL_DBG_TYPE_EP, "dapls_ib_post_send: "
322*9e39c5baSBill Taylor 		    "qp_handle == NULL\n");
323*9e39c5baSBill Taylor 		return (DAT_INVALID_PARAMETER);
324*9e39c5baSBill Taylor 	}
325*9e39c5baSBill Taylor 
326*9e39c5baSBill Taylor 	/* allocate scatter-gather list on the heap if its large */
327*9e39c5baSBill Taylor 	if (num_segments > DAPL_MAX_IOV) {
328*9e39c5baSBill Taylor 		ps_sgl = dapl_os_alloc(num_segments * sizeof (ibt_wr_ds_t));
329*9e39c5baSBill Taylor 		if (NULL == ps_sgl) {
330*9e39c5baSBill Taylor 			dapl_dbg_log(DAPL_DBG_TYPE_ERR,
331*9e39c5baSBill Taylor 			    "dapls_ib_post_send: pr_sgl alloc failed");
332*9e39c5baSBill Taylor 			return (DAT_INSUFFICIENT_RESOURCES);
333*9e39c5baSBill Taylor 		}
334*9e39c5baSBill Taylor 	} else {
335*9e39c5baSBill Taylor 		ps_sgl = ps_sgl_arr;
336*9e39c5baSBill Taylor 	}
337*9e39c5baSBill Taylor 
338*9e39c5baSBill Taylor 	for (i = 0; i < num_segments; i++) {
339*9e39c5baSBill Taylor 		ps_sgl[i].ds_va = (ib_vaddr_t)local_iov[i].virtual_address;
340*9e39c5baSBill Taylor 		ps_sgl[i].ds_key = (ibt_lkey_t)local_iov[i].lmr_context;
341*9e39c5baSBill Taylor 		ps_sgl[i].ds_len = (ib_msglen_t)local_iov[i].segment_length;
342*9e39c5baSBill Taylor 		total_len += ps_sgl[i].ds_len;
343*9e39c5baSBill Taylor 
344*9e39c5baSBill Taylor 		dapl_dbg_log(DAPL_DBG_TYPE_EP, "dapls_ib_post_send: "
345*9e39c5baSBill Taylor 		    "i(%d), va(0x%llx), lmrctxt(0x%x), len(%u)\n",
346*9e39c5baSBill Taylor 		    i, ps_sgl[i].ds_va, ps_sgl[i].ds_key, ps_sgl[i].ds_len);
347*9e39c5baSBill Taylor 	}
348*9e39c5baSBill Taylor 
349*9e39c5baSBill Taylor 	if (cookie != NULL)	{
350*9e39c5baSBill Taylor 		cookie->val.dto.size =  total_len;
351*9e39c5baSBill Taylor 		dapl_dbg_log(DAPL_DBG_TYPE_EVD,
352*9e39c5baSBill Taylor 		    "dapls_ib_post_send: op_type(%d), cookie(%p) "
353*9e39c5baSBill Taylor 		    "num_seg(%d) size(%d) hkey(%016llx)\n", op_type,
354*9e39c5baSBill Taylor 		    cookie, num_segments, cookie->val.dto.size,
355*9e39c5baSBill Taylor 		    ep_ptr->qp_handle->ep_hkey);
356*9e39c5baSBill Taylor 	}
357*9e39c5baSBill Taylor 
358*9e39c5baSBill Taylor 	ps_wr.wr_id = (ibt_wrid_t)(uintptr_t)cookie;
359*9e39c5baSBill Taylor 	/* Translate dapl flags */
360*9e39c5baSBill Taylor 	ps_wr.wr_flags = (DAT_COMPLETION_BARRIER_FENCE_FLAG &
361*9e39c5baSBill Taylor 	    completion_flags) ? IBT_WR_SEND_FENCE : 0;
362*9e39c5baSBill Taylor 	/* suppress completions */
363*9e39c5baSBill Taylor 	ps_wr.wr_flags |= (DAT_COMPLETION_SUPPRESS_FLAG &
364*9e39c5baSBill Taylor 	    completion_flags) ? 0 : IBT_WR_SEND_SIGNAL;
365*9e39c5baSBill Taylor 
366*9e39c5baSBill Taylor 	/* Solicited wait flag is valid only for post_send */
367*9e39c5baSBill Taylor 	if (op_type == OP_SEND) {
368*9e39c5baSBill Taylor 		ps_wr.wr_flags |= (DAT_COMPLETION_SOLICITED_WAIT_FLAG &
369*9e39c5baSBill Taylor 		    completion_flags) ? IBT_WR_SEND_SOLICIT : 0;
370*9e39c5baSBill Taylor 	}
371*9e39c5baSBill Taylor 
372*9e39c5baSBill Taylor 	ps_wr.wr_opcode = (ibt_wrc_opcode_t)op_type;
373*9e39c5baSBill Taylor 	ps_wr.wr_nds = (uint32_t)num_segments;
374*9e39c5baSBill Taylor 	if (num_segments > 0) {
375*9e39c5baSBill Taylor 		ps_wr.wr_sgl = &ps_sgl[0];
376*9e39c5baSBill Taylor 		if (op_type == OP_RDMA_READ || op_type == OP_RDMA_WRITE) {
377*9e39c5baSBill Taylor 			if (remote_iov == NULL) {
378*9e39c5baSBill Taylor 				/* free the ps_sgl if we had allocated it */
379*9e39c5baSBill Taylor 				if (num_segments > DAPL_MAX_IOV) {
380*9e39c5baSBill Taylor 					dapl_os_free(ps_sgl,
381*9e39c5baSBill Taylor 					    num_segments*sizeof (ibt_wr_ds_t));
382*9e39c5baSBill Taylor 				}
383*9e39c5baSBill Taylor 				dapl_dbg_log(DAPL_DBG_TYPE_EP,
384*9e39c5baSBill Taylor 				    "dapls_ib_post_send: "
385*9e39c5baSBill Taylor 				    "remote_iov == NULL\n");
386*9e39c5baSBill Taylor 				return (DAT_INVALID_PARAMETER);
387*9e39c5baSBill Taylor 			}
388*9e39c5baSBill Taylor 
389*9e39c5baSBill Taylor 			if (remote_iov->segment_length != (DAT_VLEN)total_len) {
390*9e39c5baSBill Taylor 				/* free the ps_sgl if we had allocated it */
391*9e39c5baSBill Taylor 				if (num_segments > DAPL_MAX_IOV) {
392*9e39c5baSBill Taylor 					dapl_os_free(ps_sgl,
393*9e39c5baSBill Taylor 					    num_segments*sizeof (ibt_wr_ds_t));
394*9e39c5baSBill Taylor 				}
395*9e39c5baSBill Taylor 				dapl_dbg_log(DAPL_DBG_TYPE_EP,
396*9e39c5baSBill Taylor 				    "dapls_ib_post_send: "
397*9e39c5baSBill Taylor 				    "remote_iov length(%llu != %llu)\n",
398*9e39c5baSBill Taylor 				    (DAT_VLEN)total_len,
399*9e39c5baSBill Taylor 				    remote_iov->segment_length);
400*9e39c5baSBill Taylor 				return (DAT_LENGTH_ERROR);
401*9e39c5baSBill Taylor 			}
402*9e39c5baSBill Taylor 
403*9e39c5baSBill Taylor 			ps_wr.wr.rc.rcwr.rdma.rdma_raddr =
404*9e39c5baSBill Taylor 			    (ib_vaddr_t)remote_iov->target_address;
405*9e39c5baSBill Taylor 			ps_wr.wr.rc.rcwr.rdma.rdma_rkey =
406*9e39c5baSBill Taylor 			    (ibt_rkey_t)remote_iov->rmr_context;
407*9e39c5baSBill Taylor 
408*9e39c5baSBill Taylor 			dapl_dbg_log(DAPL_DBG_TYPE_EP,
409*9e39c5baSBill Taylor 			    "dapls_ib_post_send: remote_iov taddr(0x%llx), "
410*9e39c5baSBill Taylor 			    "rmr(0x%x)\n", remote_iov->target_address,
411*9e39c5baSBill Taylor 			    remote_iov->rmr_context);
412*9e39c5baSBill Taylor 		}
413*9e39c5baSBill Taylor 	} else {
414*9e39c5baSBill Taylor 		ps_wr.wr_sgl = NULL;
415*9e39c5baSBill Taylor 	}
416*9e39c5baSBill Taylor 
417*9e39c5baSBill Taylor 	if (ep_ptr->param.ep_attr.recv_completion_flags &
418*9e39c5baSBill Taylor 	    DAT_COMPLETION_UNSIGNALLED_FLAG) {
419*9e39c5baSBill Taylor 		/* This flag is used to control notification of completions */
420*9e39c5baSBill Taylor 		suppress_notification = (completion_flags &
421*9e39c5baSBill Taylor 		    DAT_COMPLETION_UNSIGNALLED_FLAG) ? B_TRUE : B_FALSE;
422*9e39c5baSBill Taylor 	} else {
423*9e39c5baSBill Taylor 		/*
424*9e39c5baSBill Taylor 		 * The evd waiter will use threshold to control wakeups
425*9e39c5baSBill Taylor 		 * Hence the event notification will be done via arming the
426*9e39c5baSBill Taylor 		 * CQ so we do not need special notification generation
427*9e39c5baSBill Taylor 		 * hence set suppression to true
428*9e39c5baSBill Taylor 		 */
429*9e39c5baSBill Taylor 		suppress_notification = B_TRUE;
430*9e39c5baSBill Taylor 	}
431*9e39c5baSBill Taylor 
432*9e39c5baSBill Taylor 	retval = DAPL_SEND(ep_ptr)(ep_ptr, &ps_wr, suppress_notification);
433*9e39c5baSBill Taylor 
434*9e39c5baSBill Taylor 	if (retval != 0) {
435*9e39c5baSBill Taylor 		dapl_dbg_log(DAPL_DBG_TYPE_EP,
436*9e39c5baSBill Taylor 		    "dapls_ib_post_send: post_send failed %d\n", retval);
437*9e39c5baSBill Taylor 	}
438*9e39c5baSBill Taylor 
439*9e39c5baSBill Taylor 	/* free the pr_sgl if we had allocated it */
440*9e39c5baSBill Taylor 	if (num_segments > DAPL_MAX_IOV) {
441*9e39c5baSBill Taylor 		dapl_os_free(ps_sgl, num_segments*sizeof (ibt_wr_ds_t));
442*9e39c5baSBill Taylor 	}
443*9e39c5baSBill Taylor 
444*9e39c5baSBill Taylor 	return (retval);
445*9e39c5baSBill Taylor }
446*9e39c5baSBill Taylor 
447*9e39c5baSBill Taylor /*
448*9e39c5baSBill Taylor  * dapls_ib_post_send_one
449*9e39c5baSBill Taylor  *
450*9e39c5baSBill Taylor  * Provider specific Post SEND function - special case for the common case of
451*9e39c5baSBill Taylor  * sgl num_segments == 1 and completion_flags == DAT_COMPLETION_DEFAULT_FLAG.
452*9e39c5baSBill Taylor  */
453*9e39c5baSBill Taylor DAT_RETURN
dapls_ib_post_send_one(IN DAPL_EP * ep_ptr,IN ib_send_op_type_t op_type,IN DAPL_COOKIE * cookie,IN DAT_LMR_TRIPLET * local_iov,IN const DAT_RMR_TRIPLET * remote_iov)454*9e39c5baSBill Taylor dapls_ib_post_send_one(IN DAPL_EP *ep_ptr,
455*9e39c5baSBill Taylor     IN ib_send_op_type_t op_type,
456*9e39c5baSBill Taylor     IN DAPL_COOKIE *cookie,
457*9e39c5baSBill Taylor     IN DAT_LMR_TRIPLET *local_iov,
458*9e39c5baSBill Taylor     IN const DAT_RMR_TRIPLET *remote_iov)
459*9e39c5baSBill Taylor {
460*9e39c5baSBill Taylor 	ibt_send_wr_t		ps_wr;
461*9e39c5baSBill Taylor 	ibt_wr_ds_t		ps_sgl;
462*9e39c5baSBill Taylor 	boolean_t		suppress_notification;
463*9e39c5baSBill Taylor 	int			retval;
464*9e39c5baSBill Taylor 
465*9e39c5baSBill Taylor 	if (ep_ptr->qp_handle == NULL) {
466*9e39c5baSBill Taylor 		dapl_dbg_log(DAPL_DBG_TYPE_EP, "dapls_ib_post_send_one: "
467*9e39c5baSBill Taylor 		    "qp_handle == NULL\n");
468*9e39c5baSBill Taylor 		return (DAT_INVALID_PARAMETER);
469*9e39c5baSBill Taylor 	}
470*9e39c5baSBill Taylor 
471*9e39c5baSBill Taylor 	ps_sgl.ds_va = (ib_vaddr_t)local_iov[0].virtual_address;
472*9e39c5baSBill Taylor 	ps_sgl.ds_key = (ibt_lkey_t)local_iov[0].lmr_context;
473*9e39c5baSBill Taylor 	ps_sgl.ds_len = (ib_msglen_t)local_iov[0].segment_length;
474*9e39c5baSBill Taylor 
475*9e39c5baSBill Taylor 	dapl_dbg_log(DAPL_DBG_TYPE_EP, "dapls_ib_post_send_one: "
476*9e39c5baSBill Taylor 	    "i(%d), va(0x%llx), lmrctxt(0x%x), len(%u)\n",
477*9e39c5baSBill Taylor 	    0, ps_sgl.ds_va, ps_sgl.ds_key, ps_sgl.ds_len);
478*9e39c5baSBill Taylor 
479*9e39c5baSBill Taylor 	cookie->val.dto.size =  ps_sgl.ds_len;
480*9e39c5baSBill Taylor 	dapl_dbg_log(DAPL_DBG_TYPE_EVD,
481*9e39c5baSBill Taylor 	    "dapls_ib_post_send_one: op_type(%d), cookie(%p) "
482*9e39c5baSBill Taylor 	    "num_seg(%d) size(%d) hkey(%016llx)\n", op_type,
483*9e39c5baSBill Taylor 	    cookie, 1, cookie->val.dto.size,
484*9e39c5baSBill Taylor 	    ep_ptr->qp_handle->ep_hkey);
485*9e39c5baSBill Taylor 
486*9e39c5baSBill Taylor 	ps_wr.wr_id = (ibt_wrid_t)(uintptr_t)cookie;
487*9e39c5baSBill Taylor 	/* suppress completions */
488*9e39c5baSBill Taylor 	ps_wr.wr_flags = IBT_WR_SEND_SIGNAL;
489*9e39c5baSBill Taylor 
490*9e39c5baSBill Taylor 	ps_wr.wr_opcode = (ibt_wrc_opcode_t)op_type;
491*9e39c5baSBill Taylor 	ps_wr.wr_nds = 1;
492*9e39c5baSBill Taylor 
493*9e39c5baSBill Taylor 	ps_wr.wr_sgl = &ps_sgl;
494*9e39c5baSBill Taylor 	if (op_type == OP_RDMA_READ || op_type == OP_RDMA_WRITE) {
495*9e39c5baSBill Taylor 		if (remote_iov == NULL) {
496*9e39c5baSBill Taylor 			/* free the ps_sgl if we had allocated it */
497*9e39c5baSBill Taylor 			dapl_dbg_log(DAPL_DBG_TYPE_EP,
498*9e39c5baSBill Taylor 			    "dapls_ib_post_send_one: "
499*9e39c5baSBill Taylor 			    "remote_iov == NULL\n");
500*9e39c5baSBill Taylor 			return (DAT_INVALID_PARAMETER);
501*9e39c5baSBill Taylor 		}
502*9e39c5baSBill Taylor 
503*9e39c5baSBill Taylor 		if (remote_iov->segment_length != (DAT_VLEN)ps_sgl.ds_len) {
504*9e39c5baSBill Taylor 			dapl_dbg_log(DAPL_DBG_TYPE_EP,
505*9e39c5baSBill Taylor 			    "dapls_ib_post_send_one: "
506*9e39c5baSBill Taylor 			    "remote_iov length(%llu != %llu)\n",
507*9e39c5baSBill Taylor 			    (DAT_VLEN)ps_sgl.ds_len,
508*9e39c5baSBill Taylor 			    remote_iov->segment_length);
509*9e39c5baSBill Taylor 			return (DAT_LENGTH_ERROR);
510*9e39c5baSBill Taylor 		}
511*9e39c5baSBill Taylor 
512*9e39c5baSBill Taylor 		ps_wr.wr.rc.rcwr.rdma.rdma_raddr =
513*9e39c5baSBill Taylor 		    (ib_vaddr_t)remote_iov->target_address;
514*9e39c5baSBill Taylor 		ps_wr.wr.rc.rcwr.rdma.rdma_rkey =
515*9e39c5baSBill Taylor 		    (ibt_rkey_t)remote_iov->rmr_context;
516*9e39c5baSBill Taylor 
517*9e39c5baSBill Taylor 		dapl_dbg_log(DAPL_DBG_TYPE_EP,
518*9e39c5baSBill Taylor 		    "dapls_ib_post_send_one: remote_iov taddr(0x%llx), "
519*9e39c5baSBill Taylor 		    "rmr(0x%x)\n", remote_iov->target_address,
520*9e39c5baSBill Taylor 		    remote_iov->rmr_context);
521*9e39c5baSBill Taylor 	}
522*9e39c5baSBill Taylor 
523*9e39c5baSBill Taylor 	if (ep_ptr->param.ep_attr.recv_completion_flags &
524*9e39c5baSBill Taylor 	    DAT_COMPLETION_UNSIGNALLED_FLAG) {
525*9e39c5baSBill Taylor 		/* This flag is used to control notification of completions */
526*9e39c5baSBill Taylor 		suppress_notification = B_FALSE;
527*9e39c5baSBill Taylor 	} else {
528*9e39c5baSBill Taylor 		/*
529*9e39c5baSBill Taylor 		 * The evd waiter will use threshold to control wakeups
530*9e39c5baSBill Taylor 		 * Hence the event notification will be done via arming the
531*9e39c5baSBill Taylor 		 * CQ so we do not need special notification generation
532*9e39c5baSBill Taylor 		 * hence set suppression to true
533*9e39c5baSBill Taylor 		 */
534*9e39c5baSBill Taylor 		suppress_notification = B_TRUE;
535*9e39c5baSBill Taylor 	}
536*9e39c5baSBill Taylor 
537*9e39c5baSBill Taylor 	retval = DAPL_SEND(ep_ptr)(ep_ptr, &ps_wr, suppress_notification);
538*9e39c5baSBill Taylor 
539*9e39c5baSBill Taylor 	if (retval != 0) {
540*9e39c5baSBill Taylor 		dapl_dbg_log(DAPL_DBG_TYPE_EP,
541*9e39c5baSBill Taylor 		    "dapls_ib_post_send_one: post_send failed %d\n", retval);
542*9e39c5baSBill Taylor 	}
543*9e39c5baSBill Taylor 
544*9e39c5baSBill Taylor 	return (retval);
545*9e39c5baSBill Taylor }
546