xref: /titanic_51/usr/src/uts/common/io/ib/mgt/ibmf/ibmf_wqe.c (revision 50949b65f899967ea5560e87f773889a1d917b64)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*
27  * This file implements the Work Queue Entry (WQE) management in IBMF.
28  */
29 
30 #include <sys/ib/mgt/ibmf/ibmf_impl.h>
31 
32 extern int ibmf_trace_level;
33 extern int ibmf_send_wqes_per_port, ibmf_recv_wqes_per_port;
34 
35 #define	IBMF_INIT_SG_ELEMENT(sg, mem, lkey, size)	{ \
36 	(sg).ds_va = (ib_vaddr_t)(uintptr_t)(mem);	\
37 	(sg).ds_key = (lkey);				\
38 	(sg).ds_len = (size);				\
39 }
40 
41 #define	IBMF_ADDR_TO_SEND_WR_ID(ptr, id)		\
42 	(id) = (ibt_wrid_t)(uintptr_t)(ptr)
43 
44 #define	IBMF_ADDR_TO_RECV_WR_ID(ptr, id)		 \
45 	(id) = ((ibt_wrid_t)(uintptr_t)(ptr) | IBMF_RCV_CQE)
46 
47 #define	IBMF_INIT_RMPP_HDR(hdrp, ver, type, respt, flg, status, seg, lennwl) { \
48 	(hdrp)->rmpp_version = (ver);			\
49 	(hdrp)->rmpp_type = (type);			\
50 	(hdrp)->rmpp_resp_time = (respt);		\
51 	(hdrp)->rmpp_flags = (flg);			\
52 	(hdrp)->rmpp_status = (status);			\
53 	(hdrp)->rmpp_segnum = (h2b32(seg));		\
54 	(hdrp)->rmpp_pyldlen_nwl = (h2b32(lennwl));	\
55 }
56 
57 static int ibmf_send_wqe_cache_constructor(void *buf, void *cdrarg,
58     int kmflags);
59 static void ibmf_send_wqe_cache_destructor(void *buf, void *cdrarg);
60 static int ibmf_recv_wqe_cache_constructor(void *buf, void *cdrarg,
61     int kmflags);
62 static void ibmf_recv_wqe_cache_destructor(void *buf, void *cdrarg);
63 static int ibmf_i_extend_wqe_mem(ibmf_ci_t *cip,
64     ibmf_qp_handle_t ibmf_qp_handle, ibmf_wqe_mgt_t *wqe_mgt,
65     boolean_t block);
66 
67 /*
68  * ibmf_send_wqe_cache_constructor():
69  *	Constructor for the kmem cache used for send WQEs for special QPs
70  */
71 /* ARGSUSED */
72 static int
73 ibmf_send_wqe_cache_constructor(void *buf, void *cdrarg, int kmflags)
74 {
75 	ibmf_send_wqe_t		*send_wqe = (ibmf_send_wqe_t *)buf;
76 	ibmf_ci_t		*cip = (ibmf_ci_t *)cdrarg;
77 	ibmf_wqe_mgt_t		*wqe_mgt;
78 
79 	IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4,
80 	    ibmf_send_wqe_cache_constructor_start, IBMF_TNF_TRACE, "",
81 	    "ibmf_send_wqe_cache_constructor() enter, buf = %p, cdarg = %p\n",
82 	    tnf_opaque, buf, buf, tnf_opaque, cdrarg, cdrarg);
83 
84 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*send_wqe))
85 
86 	/* initialize send WQE context */
87 	send_wqe->send_sg_mem =
88 	    (ib_vaddr_t)(uintptr_t)vmem_alloc(cip->ci_wqe_ib_vmem,
89 	    IBMF_MEM_PER_WQE, kmflags == KM_SLEEP ? VM_SLEEP : VM_NOSLEEP);
90 	if (send_wqe->send_sg_mem == NULL) {
91 		IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
92 		    ibmf_send_wqe_cache_constructor_err, IBMF_TNF_ERROR, "",
93 		    "ibmf_send_wqe_cache_constructor(): %s\n", tnf_string, msg,
94 		    "Failed vmem allocation in send WQE cache constructor");
95 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
96 		    ibmf_send_wqe_cache_constructor_end, IBMF_TNF_TRACE, "",
97 		    "ibmf_send_wqe_cache_constructor() exit\n");
98 		return (-1);
99 	}
100 
101 	mutex_enter(&cip->ci_wqe_mutex);
102 	wqe_mgt = cip->ci_wqe_mgt_list;
103 
104 	/* Look for the WQE management struct that includes this address */
105 	while (wqe_mgt != NULL) {
106 		mutex_enter(&wqe_mgt->wqes_mutex);
107 		if ((send_wqe->send_sg_mem >= wqe_mgt->wqes_ib_mem) &&
108 		    (send_wqe->send_sg_mem < (wqe_mgt->wqes_ib_mem +
109 		    wqe_mgt->wqes_kmem_sz))) {
110 			mutex_exit(&wqe_mgt->wqes_mutex);
111 			break;
112 		}
113 		mutex_exit(&wqe_mgt->wqes_mutex);
114 		wqe_mgt = wqe_mgt->wqe_mgt_next;
115 	}
116 
117 	if (wqe_mgt == NULL) {
118 		mutex_exit(&cip->ci_wqe_mutex);
119 		vmem_free(cip->ci_wqe_ib_vmem,
120 		    (void *)(uintptr_t)send_wqe->send_sg_mem, IBMF_MEM_PER_WQE);
121 		IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
122 		    ibmf_send_wqe_cache_constructor_err, IBMF_TNF_ERROR, "",
123 		    "ibmf_send_wqe_cache_constructor(): %s\n", tnf_string, msg,
124 		    "Address not found in WQE mgt list");
125 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
126 		    ibmf_send_wqe_cache_constructor_end, IBMF_TNF_TRACE, "",
127 		    "ibmf_send_wqe_cache_constructor() exit\n");
128 		return (-1);
129 	}
130 
131 	mutex_enter(&wqe_mgt->wqes_mutex);
132 
133 	send_wqe->send_mem = (caddr_t)((uintptr_t)wqe_mgt->wqes_kmem +
134 	    (uintptr_t)(send_wqe->send_sg_mem - wqe_mgt->wqes_ib_mem));
135 	bzero(send_wqe->send_mem, IBMF_MEM_PER_WQE);
136 	send_wqe->send_sg_lkey = wqe_mgt->wqes_ib_lkey;
137 	send_wqe->send_mem_hdl = wqe_mgt->wqes_ib_mem_hdl;
138 	send_wqe->send_wqe_flags = 0;
139 	send_wqe->send_wqe_next = NULL;
140 
141 	mutex_exit(&wqe_mgt->wqes_mutex);
142 	mutex_exit(&cip->ci_wqe_mutex);
143 
144 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
145 	    ibmf_send_wqe_cache_constructor_end, IBMF_TNF_TRACE, "",
146 	    "ibmf_send_wqe_cache_constructor() exit\n");
147 
148 	return (0);
149 }
150 
151 /*
152  * ibmf_send_wqe_cache_destructor():
153  *	Destructor for send WQE kmem cache for special QPs
154  */
155 /* ARGSUSED */
156 static void
157 ibmf_send_wqe_cache_destructor(void *buf, void *cdrarg)
158 {
159 	ibmf_send_wqe_t		*send_wqe = (ibmf_send_wqe_t *)buf;
160 	ibmf_ci_t		*cip = (ibmf_ci_t *)cdrarg;
161 
162 	IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4,
163 	    ibmf_i_send_wqe_cache_destructor_start, IBMF_TNF_TRACE, "",
164 	    "ibmf_send_wqe_cache_destructor() enter, buf = %p, cdarg = %p\n",
165 	    tnf_opaque, buf, buf, tnf_opaque, cdrarg, cdrarg);
166 
167 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*send_wqe))
168 
169 	/* Free the vmem allocated for the WQE */
170 	vmem_free(cip->ci_wqe_ib_vmem,
171 	    (void *)(uintptr_t)send_wqe->send_sg_mem, IBMF_MEM_PER_WQE);
172 	send_wqe->send_mem = NULL;
173 
174 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
175 	    ibmf_i_send_wqe_cache_destructor_end, IBMF_TNF_TRACE, "",
176 	    "ibmf_send_wqe_cache_destructor() exit\n");
177 }
178 
179 /*
180  * ibmf_recv_wqe_cache_constructor():
181  *	Constructor for receive WQE kmem cache for special QPs
182  */
183 /* ARGSUSED */
184 static int
185 ibmf_recv_wqe_cache_constructor(void *buf, void *cdrarg, int kmflags)
186 {
187 	ibmf_recv_wqe_t		*recv_wqe = (ibmf_recv_wqe_t *)buf;
188 	ibmf_ci_t		*cip = (ibmf_ci_t *)cdrarg;
189 	ibmf_wqe_mgt_t		*wqe_mgt;
190 
191 	IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4,
192 	    ibmf_i_recv_wqe_cache_constructor_start, IBMF_TNF_TRACE, "",
193 	    "ibmf_recv_wqe_cache_constructor() enter, buf = %p, cdarg = %p\n",
194 	    tnf_opaque, buf, buf, tnf_opaque, cdrarg, cdrarg);
195 
196 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*recv_wqe))
197 
198 	/* initialize recv WQE context */
199 	recv_wqe->recv_sg_mem =
200 	    (ib_vaddr_t)(uintptr_t)vmem_alloc(cip->ci_wqe_ib_vmem,
201 	    IBMF_MEM_PER_WQE, kmflags == KM_SLEEP ? VM_SLEEP : VM_NOSLEEP);
202 	if (recv_wqe->recv_sg_mem == NULL) {
203 		IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
204 		    ibmf_recv_wqe_cache_constructor_err, IBMF_TNF_ERROR, "",
205 		    "ibmf_recv_wqe_cache_constructor(): %s\n", tnf_string, msg,
206 		    "Failed vmem allocation in receive WQE cache constructor");
207 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
208 		    ibmf_recv_wqe_cache_constructor_end, IBMF_TNF_TRACE, "",
209 		    "ibmf_recv_wqe_cache_constructor() exit\n");
210 		return (-1);
211 	}
212 
213 	mutex_enter(&cip->ci_wqe_mutex);
214 	wqe_mgt = cip->ci_wqe_mgt_list;
215 
216 	/* Look for the WQE management struct that includes this address */
217 	while (wqe_mgt != NULL) {
218 		mutex_enter(&wqe_mgt->wqes_mutex);
219 		if ((recv_wqe->recv_sg_mem >= wqe_mgt->wqes_ib_mem) &&
220 		    (recv_wqe->recv_sg_mem < (wqe_mgt->wqes_ib_mem +
221 		    wqe_mgt->wqes_kmem_sz))) {
222 			mutex_exit(&wqe_mgt->wqes_mutex);
223 			break;
224 		}
225 		mutex_exit(&wqe_mgt->wqes_mutex);
226 		wqe_mgt = wqe_mgt->wqe_mgt_next;
227 	}
228 
229 	if (wqe_mgt == NULL) {
230 		mutex_exit(&cip->ci_wqe_mutex);
231 		vmem_free(cip->ci_wqe_ib_vmem,
232 		    (void *)(uintptr_t)recv_wqe->recv_sg_mem, IBMF_MEM_PER_WQE);
233 		IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
234 		    ibmf_recv_wqe_cache_constructor_err, IBMF_TNF_ERROR, "",
235 		    "ibmf_recv_wqe_cache_constructor(): %s\n", tnf_string, msg,
236 		    "Address not found in WQE mgt list");
237 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
238 		    ibmf_recv_wqe_cache_constructor_end, IBMF_TNF_TRACE, "",
239 		    "ibmf_recv_wqe_cache_constructor() exit\n");
240 		return (-1);
241 	}
242 
243 	mutex_enter(&wqe_mgt->wqes_mutex);
244 
245 	recv_wqe->recv_mem = (caddr_t)((uintptr_t)wqe_mgt->wqes_kmem +
246 	    (uintptr_t)(recv_wqe->recv_sg_mem - wqe_mgt->wqes_ib_mem));
247 	bzero(recv_wqe->recv_mem, IBMF_MEM_PER_WQE);
248 	recv_wqe->recv_sg_lkey = wqe_mgt->wqes_ib_lkey;
249 	recv_wqe->recv_mem_hdl = wqe_mgt->wqes_ib_mem_hdl;
250 	recv_wqe->recv_wqe_next = NULL;
251 	recv_wqe->recv_msg = NULL;
252 	recv_wqe->recv_wqe_flags = 0;
253 
254 	mutex_exit(&wqe_mgt->wqes_mutex);
255 	mutex_exit(&cip->ci_wqe_mutex);
256 
257 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
258 	    ibmf_i_recv_wqe_cache_constructor_end, IBMF_TNF_TRACE, "",
259 	    "ibmf_recv_wqe_cache_constructor() exit\n");
260 
261 	return (0);
262 }
263 
264 /*
265  * ibmf_recv_wqe_cache_destructor():
266  *	Destructor for receive WQE kmem cache for special QPs
267  */
268 /* ARGSUSED */
269 static void
270 ibmf_recv_wqe_cache_destructor(void *buf, void *cdrarg)
271 {
272 	ibmf_recv_wqe_t		*recv_wqe = (ibmf_recv_wqe_t *)buf;
273 	ibmf_ci_t		*cip = (ibmf_ci_t *)cdrarg;
274 
275 	IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4,
276 	    ibmf_i_recv_wqe_cache_destructor_start, IBMF_TNF_TRACE, "",
277 	    "ibmf_recv_wqe_cache_destructor() enter, buf = %p, cdarg = %p\n",
278 	    tnf_opaque, buf, buf, tnf_opaque, cdrarg, cdrarg);
279 
280 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*recv_wqe))
281 
282 	/* Free the vmem allocated for the WQE */
283 	vmem_free(cip->ci_wqe_ib_vmem,
284 	    (void *)(uintptr_t)recv_wqe->recv_sg_mem, IBMF_MEM_PER_WQE);
285 	recv_wqe->recv_mem = NULL;
286 
287 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
288 	    ibmf_i_recv_wqe_cache_destructor_end, IBMF_TNF_TRACE, "",
289 	    "ibmf_recv_wqe_cache_destructor() exit\n");
290 }
291 
292 /*
293  * ibmf_altqp_send_wqe_cache_constructor():
294  *	Constructor for the kmem cache used for send WQEs for alternate QPs
295  */
296 /* ARGSUSED */
297 int
298 ibmf_altqp_send_wqe_cache_constructor(void *buf, void *cdrarg, int kmflags)
299 {
300 	ibmf_send_wqe_t	*send_wqe = (ibmf_send_wqe_t *)buf;
301 	ibmf_alt_qp_t	*qp_ctx = (ibmf_alt_qp_t *)cdrarg;
302 	ibmf_wqe_mgt_t	*wqe_mgt;
303 
304 	IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4,
305 	    ibmf_altqp_send_wqe_cache_constructor_start, IBMF_TNF_TRACE, "",
306 	    "ibmf_altqp_send_wqe_cache_constructor() enter, buf = %p, "
307 	    "cdarg = %p\n", tnf_opaque, buf, buf, tnf_opaque, cdrarg, cdrarg);
308 
309 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*send_wqe))
310 
311 	/* initialize send WQE context */
312 	send_wqe->send_sg_mem = (ib_vaddr_t)(uintptr_t)vmem_alloc(
313 	    qp_ctx->isq_wqe_ib_vmem, IBMF_MEM_PER_WQE,
314 	    kmflags == KM_SLEEP ? VM_SLEEP : VM_NOSLEEP);
315 	if (send_wqe->send_sg_mem == NULL) {
316 		IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
317 		    ibmf_altqp_send_wqe_cache_constructor_err, IBMF_TNF_ERROR,
318 		    "", "ibmf_altqp_send_wqe_cache_constructor(): %s\n",
319 		    tnf_string, msg, "Failed vmem allocation in "
320 		    "alternate QP send WQE cache constructor");
321 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
322 		    ibmf_altqp_send_wqe_cache_constructor_end, IBMF_TNF_TRACE,
323 		    "", "ibmf_altqp_send_wqe_cache_constructor() exit\n");
324 		return (-1);
325 	}
326 
327 	mutex_enter(&qp_ctx->isq_wqe_mutex);
328 	wqe_mgt = qp_ctx->isq_wqe_mgt_list;
329 
330 	/* Look for the WQE management struct that includes this address */
331 	while (wqe_mgt != NULL) {
332 		mutex_enter(&wqe_mgt->wqes_mutex);
333 		if ((send_wqe->send_sg_mem >= wqe_mgt->wqes_ib_mem) &&
334 		    (send_wqe->send_sg_mem < (wqe_mgt->wqes_ib_mem +
335 		    wqe_mgt->wqes_kmem_sz))) {
336 			mutex_exit(&wqe_mgt->wqes_mutex);
337 			break;
338 		}
339 		mutex_exit(&wqe_mgt->wqes_mutex);
340 		wqe_mgt = wqe_mgt->wqe_mgt_next;
341 	}
342 
343 	if (wqe_mgt == NULL) {
344 		mutex_exit(&qp_ctx->isq_wqe_mutex);
345 		vmem_free(qp_ctx->isq_wqe_ib_vmem,
346 		    (void *)(uintptr_t)send_wqe->send_sg_mem, IBMF_MEM_PER_WQE);
347 		IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
348 		    ibmf_altqp_send_wqe_cache_constructor_err, IBMF_TNF_ERROR,
349 		    "", "ibmf_altqp_send_wqe_cache_constructor(): %s\n",
350 		    tnf_string, msg, "Address not found in WQE mgt list");
351 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
352 		    ibmf_altqp_send_wqe_cache_constructor_end,
353 		    IBMF_TNF_TRACE, "",
354 		    "ibmf_altqp_send_wqe_cache_constructor() exit\n");
355 		return (-1);
356 	}
357 
358 	mutex_enter(&wqe_mgt->wqes_mutex);
359 
360 	send_wqe->send_mem = (caddr_t)((uintptr_t)wqe_mgt->wqes_kmem +
361 	    (uintptr_t)(send_wqe->send_sg_mem - wqe_mgt->wqes_ib_mem));
362 	bzero(send_wqe->send_mem, IBMF_MEM_PER_WQE);
363 	send_wqe->send_sg_lkey = wqe_mgt->wqes_ib_lkey;
364 	send_wqe->send_mem_hdl = wqe_mgt->wqes_ib_mem_hdl;
365 	send_wqe->send_wqe_flags = 0;
366 
367 	mutex_exit(&wqe_mgt->wqes_mutex);
368 	mutex_exit(&qp_ctx->isq_wqe_mutex);
369 
370 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
371 	    ibmf_i_altqp_send_wqe_cache_constructor_end, IBMF_TNF_TRACE, "",
372 	    "ibmf_altqp_send_wqe_cache_constructor() exit\n");
373 
374 	return (0);
375 }
376 
377 /*
378  * ibmf_altqp_send_wqe_cache_destructor():
379  *	Destructor for send WQE kmem cache for alternate QPs
380  */
381 /* ARGSUSED */
382 void
383 ibmf_altqp_send_wqe_cache_destructor(void *buf, void *cdrarg)
384 {
385 	ibmf_send_wqe_t	*send_wqe = (ibmf_send_wqe_t *)buf;
386 	ibmf_alt_qp_t	*qp_ctx = (ibmf_alt_qp_t *)cdrarg;
387 
388 	IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4,
389 	    ibmf_i_altqp_send_wqe_cache_destructor_start, IBMF_TNF_TRACE, "",
390 	    "ibmf_altqp_send_wqe_cache_destructor() enter, buf = %p, "
391 	    "cdarg = %p\n", tnf_opaque, buf, buf, tnf_opaque, cdrarg, cdrarg);
392 
393 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*send_wqe))
394 
395 	/* Free the vmem allocated for the WQE */
396 	vmem_free(qp_ctx->isq_wqe_ib_vmem,
397 	    (void *)(uintptr_t)send_wqe->send_sg_mem, IBMF_MEM_PER_WQE);
398 	send_wqe->send_mem = NULL;
399 
400 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
401 	    ibmf_i_altqp_send_wqe_cache_destructor_end, IBMF_TNF_TRACE, "",
402 	    "ibmf_altqp_send_wqe_cache_destructor() exit\n");
403 }
404 
405 /*
406  * ibmf_altqp_recv_wqe_cache_constructor():
407  *	Constructor for receive WQE kmem cache for alternate QPs
408  */
409 /* ARGSUSED */
410 int
411 ibmf_altqp_recv_wqe_cache_constructor(void *buf, void *cdrarg, int kmflags)
412 {
413 	ibmf_recv_wqe_t	*recv_wqe = (ibmf_recv_wqe_t *)buf;
414 	ibmf_alt_qp_t	*qp_ctx = (ibmf_alt_qp_t *)cdrarg;
415 	ibmf_wqe_mgt_t	*wqe_mgt;
416 
417 	IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4,
418 	    ibmf_i_altqp_recv_wqe_cache_constructor_start, IBMF_TNF_TRACE, "",
419 	    "ibmf_altqp_recv_wqe_cache_constructor() enter, buf = %p, "
420 	    "cdarg = %p\n", tnf_opaque, buf, buf, tnf_opaque, cdrarg, cdrarg);
421 
422 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*recv_wqe))
423 
424 	/* initialize recv WQE context */
425 	recv_wqe->recv_sg_mem = (ib_vaddr_t)(uintptr_t)vmem_alloc(
426 	    qp_ctx->isq_wqe_ib_vmem, IBMF_MEM_PER_WQE,
427 	    kmflags == KM_SLEEP ? VM_SLEEP : VM_NOSLEEP);
428 	if (recv_wqe->recv_sg_mem == NULL) {
429 		IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
430 		    ibmf_altqp_recv_wqe_cache_constructor_err, IBMF_TNF_ERROR,
431 		    "", "ibmf_altqp_recv_wqe_cache_constructor(): %s\n",
432 		    tnf_string, msg,
433 		    "Failed vmem allocation in recv WQE cache constructor");
434 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
435 		    ibmf_altqp_recv_wqe_cache_constructor_end, IBMF_TNF_TRACE,
436 		    "", "ibmf_altqp_recv_wqe_cache_constructor() exit\n");
437 		return (-1);
438 	}
439 
440 	mutex_enter(&qp_ctx->isq_wqe_mutex);
441 	wqe_mgt = qp_ctx->isq_wqe_mgt_list;
442 
443 	/* Look for the WQE management struct that includes this address */
444 	while (wqe_mgt != NULL) {
445 		mutex_enter(&wqe_mgt->wqes_mutex);
446 		if ((recv_wqe->recv_sg_mem >= wqe_mgt->wqes_ib_mem) &&
447 		    (recv_wqe->recv_sg_mem < (wqe_mgt->wqes_ib_mem +
448 		    wqe_mgt->wqes_kmem_sz))) {
449 			mutex_exit(&wqe_mgt->wqes_mutex);
450 			break;
451 		}
452 		mutex_exit(&wqe_mgt->wqes_mutex);
453 		wqe_mgt = wqe_mgt->wqe_mgt_next;
454 	}
455 
456 	if (wqe_mgt == NULL) {
457 		mutex_exit(&qp_ctx->isq_wqe_mutex);
458 		vmem_free(qp_ctx->isq_wqe_ib_vmem,
459 		    (void *)(uintptr_t)recv_wqe->recv_sg_mem, IBMF_MEM_PER_WQE);
460 		IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
461 		    ibmf_recv_wqe_cache_constructor_err, IBMF_TNF_ERROR, "",
462 		    "ibmf_altqp_recv_wqe_cache_constructor(): %s\n",
463 		    tnf_string, msg, "Address not found in WQE mgt list");
464 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
465 		    ibmf_recv_wqe_cache_constructor_end, IBMF_TNF_TRACE, "",
466 		    "ibmf_recv_wqe_cache_constructor() exit\n");
467 		return (-1);
468 	}
469 
470 	mutex_enter(&wqe_mgt->wqes_mutex);
471 
472 	recv_wqe->recv_mem = (caddr_t)((uintptr_t)wqe_mgt->wqes_kmem +
473 	    (uintptr_t)(recv_wqe->recv_sg_mem - wqe_mgt->wqes_ib_mem));
474 	bzero(recv_wqe->recv_mem, IBMF_MEM_PER_WQE);
475 	recv_wqe->recv_sg_lkey = wqe_mgt->wqes_ib_lkey;
476 	recv_wqe->recv_mem_hdl = wqe_mgt->wqes_ib_mem_hdl;
477 	recv_wqe->recv_wqe_flags = 0;
478 
479 	mutex_exit(&wqe_mgt->wqes_mutex);
480 	mutex_exit(&qp_ctx->isq_wqe_mutex);
481 
482 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
483 	    ibmf_i_altqp_recv_wqe_cache_constructor_end, IBMF_TNF_TRACE, "",
484 	    "ibmf_altqp_recv_wqe_cache_constructor() exit\n");
485 
486 	return (0);
487 }
488 
489 /*
490  * ibmf_altqp_recv_wqe_cache_destructor():
491  *	Destructor for receive WQE kmem cache for alternate QPs
492  */
493 /* ARGSUSED */
494 void
495 ibmf_altqp_recv_wqe_cache_destructor(void *buf, void *cdrarg)
496 {
497 	ibmf_recv_wqe_t	*recv_wqe = (ibmf_recv_wqe_t *)buf;
498 	ibmf_alt_qp_t	*qp_ctx = (ibmf_alt_qp_t *)cdrarg;
499 
500 	IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4,
501 	    ibmf_i_altqp_recv_wqe_cache_destructor_start, IBMF_TNF_TRACE, "",
502 	    "ibmf_altqp_recv_wqe_cache_destructor() enter, buf = %p, "
503 	    "cdarg = %p\n", tnf_opaque, buf, buf, tnf_opaque, cdrarg, cdrarg);
504 
505 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*recv_wqe))
506 
507 	/* Free the vmem allocated for the WQE */
508 	vmem_free(qp_ctx->isq_wqe_ib_vmem,
509 	    (void *)(uintptr_t)recv_wqe->recv_sg_mem, IBMF_MEM_PER_WQE);
510 	recv_wqe->recv_mem = NULL;
511 
512 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
513 	    ibmf_i_altqp_recv_wqe_cache_destructor_end, IBMF_TNF_TRACE, "",
514 	    "ibmf_altqp_recv_wqe_cache_destructor() exit\n");
515 }
516 
517 /*
518  * ibmf_i_init_wqes():
519  *	Create the kmem cache for send and receive WQEs
520  */
521 int
522 ibmf_i_init_wqes(ibmf_ci_t *cip)
523 {
524 	ibt_status_t		status;
525 	ibt_mr_hdl_t		mem_hdl;
526 	ibt_mr_desc_t		mem_desc;
527 	ibt_mr_attr_t		mem_attr;
528 	ibmf_wqe_mgt_t		*wqe_mgtp;
529 	char			string[128];
530 
531 	IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_wqes_start,
532 	    IBMF_TNF_TRACE, "", "ibmf_i_init_wqes() enter, cip = %p\n",
533 	    tnf_opaque, cip, cip);
534 
535 	/*
536 	 * Allocate memory for the WQE management structure
537 	 */
538 	wqe_mgtp = kmem_zalloc(sizeof (ibmf_wqe_mgt_t), KM_SLEEP);
539 	mutex_init(&wqe_mgtp->wqes_mutex, NULL, MUTEX_DRIVER, NULL);
540 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*wqe_mgtp))
541 
542 	/*
543 	 * Allocate memory for the WQEs to be used by the special QPs on this CI
544 	 * There are two special QPs per CI port
545 	 */
546 	wqe_mgtp->wqes_kmem_sz = cip->ci_nports * 2 *
547 	    ((IBMF_MEM_PER_WQE * ibmf_send_wqes_per_port) +
548 	    (IBMF_MEM_PER_WQE * ibmf_recv_wqes_per_port));
549 	wqe_mgtp->wqes_kmem =
550 	    kmem_zalloc(wqe_mgtp->wqes_kmem_sz, KM_SLEEP);
551 
552 	mem_attr.mr_vaddr = (ib_vaddr_t)(uintptr_t)wqe_mgtp->wqes_kmem;
553 	mem_attr.mr_len = wqe_mgtp->wqes_kmem_sz;
554 	mem_attr.mr_flags = IBT_MR_SLEEP | IBT_MR_ENABLE_LOCAL_WRITE;
555 	mem_attr.mr_as = NULL;
556 
557 	/* Register the allocated memory */
558 	status = ibt_register_mr(cip->ci_ci_handle, cip->ci_pd, &mem_attr,
559 	    &mem_hdl, &mem_desc);
560 	if (status != IBT_SUCCESS) {
561 		kmem_free(wqe_mgtp->wqes_kmem,
562 		    wqe_mgtp->wqes_kmem_sz);
563 		IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
564 		    ibmf_i_init_wqes_err, IBMF_TNF_ERROR, "",
565 		    "ibmf_i_init_wqes(): %s, status = %d\n", tnf_string, msg,
566 		    "register of WQE mem failed", tnf_uint, status, status);
567 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
568 		    ibmf_i_init_wqes_end, IBMF_TNF_TRACE, "",
569 		    "ibmf_i_init_wqes() exit\n");
570 		return (IBMF_NO_RESOURCES);
571 	}
572 
573 	/* Store the memory registration information */
574 	wqe_mgtp->wqes_ib_mem = mem_desc.md_vaddr;
575 	wqe_mgtp->wqes_ib_lkey = mem_desc.md_lkey;
576 	wqe_mgtp->wqes_ib_mem_hdl = mem_hdl;
577 
578 	/* Create a vmem arena for the IB virtual address space */
579 	bzero(string, 128);
580 	(void) sprintf(string, "ibmf_%016" PRIx64 "_wqes", cip->ci_node_guid);
581 	cip->ci_wqe_ib_vmem = vmem_create(string,
582 	    (void *)(uintptr_t)wqe_mgtp->wqes_ib_mem, wqe_mgtp->wqes_kmem_sz,
583 	    sizeof (uint64_t), NULL, NULL, NULL, 0, VM_SLEEP);
584 
585 	mutex_enter(&cip->ci_wqe_mutex);
586 	cip->ci_wqe_mgt_list = wqe_mgtp;
587 	mutex_exit(&cip->ci_wqe_mutex);
588 
589 	bzero(string, 128);
590 	(void) sprintf(string, "ibmf_%016" PRIx64 "_swqe", cip->ci_node_guid);
591 	/* create a kmem cache for the send WQEs */
592 	cip->ci_send_wqes_cache = kmem_cache_create(string,
593 	    sizeof (ibmf_send_wqe_t), 0, ibmf_send_wqe_cache_constructor,
594 	    ibmf_send_wqe_cache_destructor, NULL, (void *)cip, NULL, 0);
595 
596 	bzero(string, 128);
597 	(void) sprintf(string, "ibmf_%016" PRIx64 "_rwqe", cip->ci_node_guid);
598 	/* create a kmem cache for the receive WQEs */
599 	cip->ci_recv_wqes_cache = kmem_cache_create(string,
600 	    sizeof (ibmf_recv_wqe_t), 0, ibmf_recv_wqe_cache_constructor,
601 	    ibmf_recv_wqe_cache_destructor, NULL, (void *)cip, NULL, 0);
602 
603 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_wqes_end,
604 	    IBMF_TNF_TRACE, "", "ibmf_i_init_wqes() exit\n");
605 
606 	return (IBMF_SUCCESS);
607 }
608 
609 /*
610  * ibmf_i_fini_wqes():
611  *	Destroy the kmem cache for send and receive WQEs
612  */
613 void
614 ibmf_i_fini_wqes(ibmf_ci_t *cip)
615 {
616 	ibmf_wqe_mgt_t	*wqe_mgt;
617 	ibt_mr_hdl_t	wqe_ib_mem_hdl;
618 	void		*wqe_kmem;
619 	uint64_t	wqe_kmem_sz;
620 
621 	IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_fini_wqes_start,
622 	    IBMF_TNF_TRACE, "", "ibmf_i_fini_wqes() enter, cip = %p\n",
623 	    tnf_opaque, cip, cip);
624 
625 	mutex_enter(&cip->ci_wqe_mutex);
626 
627 	wqe_mgt = cip->ci_wqe_mgt_list;
628 	while (wqe_mgt != NULL) {
629 		/* Remove the WQE mgt struct from the list */
630 		cip->ci_wqe_mgt_list = wqe_mgt->wqe_mgt_next;
631 		mutex_exit(&cip->ci_wqe_mutex);
632 
633 		mutex_enter(&wqe_mgt->wqes_mutex);
634 		wqe_ib_mem_hdl = wqe_mgt->wqes_ib_mem_hdl;
635 		wqe_kmem = wqe_mgt->wqes_kmem;
636 		wqe_kmem_sz = wqe_mgt->wqes_kmem_sz;
637 		mutex_exit(&wqe_mgt->wqes_mutex);
638 
639 		/* Deregister the memory allocated for the WQEs */
640 		(void) ibt_deregister_mr(cip->ci_ci_handle, wqe_ib_mem_hdl);
641 
642 		/* Free the kmem allocated for the WQEs */
643 		kmem_free(wqe_kmem, wqe_kmem_sz);
644 
645 		/* Destroy the mutex */
646 		mutex_destroy(&wqe_mgt->wqes_mutex);
647 
648 		/* Free the WQE management structure */
649 		kmem_free(wqe_mgt, sizeof (ibmf_wqe_mgt_t));
650 
651 		mutex_enter(&cip->ci_wqe_mutex);
652 		wqe_mgt = cip->ci_wqe_mgt_list;
653 	}
654 
655 	mutex_exit(&cip->ci_wqe_mutex);
656 
657 	/* Destroy the kmem_cache for the send WQE */
658 	kmem_cache_destroy(cip->ci_send_wqes_cache);
659 	/* Destroy the kmem_cache for the receive WQE */
660 	kmem_cache_destroy(cip->ci_recv_wqes_cache);
661 
662 	/*
663 	 * Destroy the vmem arena for the WQEs
664 	 * This must be done after the kmem_cache_destroy() calls since
665 	 * the cache destructors call vmem_free()
666 	 */
667 	vmem_destroy((void *)cip->ci_wqe_ib_vmem);
668 
669 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_fini_wqes_end,
670 	    IBMF_TNF_TRACE, "", "ibmf_i_fini_wqes() exit\n");
671 }
672 
673 /*
674  * ibmf_i_init_altqp_wqes():
675  *	Create the kmem cache for send and receive WQEs used by alternate QPs
676  */
677 int
678 ibmf_i_init_altqp_wqes(ibmf_alt_qp_t *qp_ctx)
679 {
680 	ibt_status_t		status;
681 	ibt_mr_hdl_t		mem_hdl;
682 	ibt_mr_desc_t		mem_desc;
683 	ibt_mr_attr_t		mem_attr;
684 	ibmf_wqe_mgt_t		*wqe_mgtp;
685 	char			string[128];
686 
687 	IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_altqp_wqes_start,
688 	    IBMF_TNF_TRACE, "", "ibmf_i_init_altqp_wqes() enter, qp_ctx = %p\n",
689 	    tnf_opaque, qp, qp_ctx);
690 
691 	/*
692 	 * Allocate memory for the WQE management structure
693 	 */
694 	wqe_mgtp = kmem_zalloc(sizeof (ibmf_wqe_mgt_t), KM_SLEEP);
695 	mutex_init(&wqe_mgtp->wqes_mutex, NULL, MUTEX_DRIVER, NULL);
696 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*wqe_mgtp))
697 
698 	/*
699 	 * Allocate memory for all the WQEs to be used by this alternate QP
700 	 */
701 	wqe_mgtp->wqes_kmem_sz = (IBMF_MEM_PER_WQE * ibmf_send_wqes_per_port) +
702 	    (IBMF_MEM_PER_WQE * ibmf_recv_wqes_per_port);
703 	wqe_mgtp->wqes_kmem = kmem_zalloc(wqe_mgtp->wqes_kmem_sz, KM_SLEEP);
704 
705 	mem_attr.mr_vaddr = (ib_vaddr_t)(uintptr_t)wqe_mgtp->wqes_kmem;
706 	mem_attr.mr_len = wqe_mgtp->wqes_kmem_sz;
707 	mem_attr.mr_flags = IBT_MR_SLEEP | IBT_MR_ENABLE_LOCAL_WRITE;
708 	mem_attr.mr_as = NULL;
709 
710 	/* Register the allocated memory */
711 	status = ibt_register_mr(qp_ctx->isq_client_hdl->ic_myci->ci_ci_handle,
712 	    qp_ctx->isq_client_hdl->ic_myci->ci_pd, &mem_attr, &mem_hdl,
713 	    &mem_desc);
714 	if (status != IBT_SUCCESS) {
715 		kmem_free(wqe_mgtp->wqes_kmem, wqe_mgtp->wqes_kmem_sz);
716 		IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
717 		    ibmf_i_init_altqp_wqes_err, IBMF_TNF_ERROR, "",
718 		    "ibmf_i_init_altqp_wqes(): %s, status = %d\n",
719 		    tnf_string, msg,
720 		    "register of WQE mem failed", tnf_uint, status, status);
721 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
722 		    ibmf_i_init_altqp_wqes_end, IBMF_TNF_TRACE, "",
723 		    "ibmf_i_init_altqp_wqes() exit\n");
724 		return (IBMF_NO_RESOURCES);
725 	}
726 
727 	/* Store the memory registration information */
728 	wqe_mgtp->wqes_ib_mem = mem_desc.md_vaddr;
729 	wqe_mgtp->wqes_ib_lkey = mem_desc.md_lkey;
730 	wqe_mgtp->wqes_ib_mem_hdl = mem_hdl;
731 
732 	/* Create a vmem arena for the IB virtual address space */
733 	bzero(string, 128);
734 	(void) sprintf(string, "ibmf_%016" PRIx64 "_%x_wqes",
735 	    qp_ctx->isq_client_hdl->ic_client_info.ci_guid, qp_ctx->isq_qpn);
736 	qp_ctx->isq_wqe_ib_vmem = vmem_create(string,
737 	    (void *)(uintptr_t)wqe_mgtp->wqes_ib_mem, wqe_mgtp->wqes_kmem_sz,
738 	    sizeof (uint64_t), NULL, NULL, NULL, 0, VM_SLEEP);
739 
740 	bzero(string, 128);
741 	/*
742 	 * CAUTION: Do not exceed 32 characters for the kmem cache name, else,
743 	 * mdb does not exit (bug 4878751). There is some connection between
744 	 * mdb walkers and kmem_caches with the limitation likely to be in the
745 	 * mdb code.
746 	 */
747 	(void) sprintf(string, "ibmf%016" PRIx64 "_%xs",
748 	    qp_ctx->isq_client_hdl->ic_client_info.ci_guid, qp_ctx->isq_qpn);
749 	/* create a kmem cache for the send WQEs */
750 	qp_ctx->isq_send_wqes_cache = kmem_cache_create(string,
751 	    sizeof (ibmf_send_wqe_t), 0, ibmf_altqp_send_wqe_cache_constructor,
752 	    ibmf_altqp_send_wqe_cache_destructor, NULL, (void *)qp_ctx,
753 	    NULL, 0);
754 
755 	bzero(string, 128);
756 	(void) sprintf(string, "ibmf%016" PRIx64 "_%xr",
757 	    qp_ctx->isq_client_hdl->ic_client_info.ci_guid, qp_ctx->isq_qpn);
758 	/* create a kmem cache for the receive WQEs */
759 	qp_ctx->isq_recv_wqes_cache = kmem_cache_create(string,
760 	    sizeof (ibmf_recv_wqe_t), 0, ibmf_altqp_recv_wqe_cache_constructor,
761 	    ibmf_altqp_recv_wqe_cache_destructor, NULL, (void *)qp_ctx,
762 	    NULL, 0);
763 
764 	mutex_enter(&qp_ctx->isq_wqe_mutex);
765 	qp_ctx->isq_wqe_mgt_list = wqe_mgtp;
766 	mutex_exit(&qp_ctx->isq_wqe_mutex);
767 
768 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_altqp_wqes_end,
769 	    IBMF_TNF_TRACE, "", "ibmf_i_init_altqp_wqes() exit\n");
770 
771 	return (IBMF_SUCCESS);
772 }
773 
774 /*
775  * ibmf_i_fini_altqp_wqes():
776  *	Destroy the kmem cache for send and receive WQEs for alternate QPs
777  */
778 void
779 ibmf_i_fini_altqp_wqes(ibmf_alt_qp_t *qp_ctx)
780 {
781 	ibmf_wqe_mgt_t	*wqe_mgt;
782 	ibt_mr_hdl_t	wqe_ib_mem_hdl;
783 	void		*wqe_kmem;
784 	uint64_t	wqe_kmem_sz;
785 
786 	IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_fini_wqes_start,
787 	    IBMF_TNF_TRACE, "", "ibmf_i_fini_wqes() enter, qp_ctx = %p\n",
788 	    tnf_opaque, qp, qp_ctx);
789 
790 	mutex_enter(&qp_ctx->isq_wqe_mutex);
791 	wqe_mgt = qp_ctx->isq_wqe_mgt_list;
792 	while (wqe_mgt != NULL) {
793 		/* Remove the WQE mgt struct from the list */
794 		qp_ctx->isq_wqe_mgt_list = wqe_mgt->wqe_mgt_next;
795 		mutex_exit(&qp_ctx->isq_wqe_mutex);
796 
797 		mutex_enter(&wqe_mgt->wqes_mutex);
798 		wqe_ib_mem_hdl = wqe_mgt->wqes_ib_mem_hdl;
799 		wqe_kmem = wqe_mgt->wqes_kmem;
800 		wqe_kmem_sz = wqe_mgt->wqes_kmem_sz;
801 		mutex_exit(&wqe_mgt->wqes_mutex);
802 
803 		/* Deregister the memory allocated for the WQEs */
804 		(void) ibt_deregister_mr(
805 		    qp_ctx->isq_client_hdl->ic_myci->ci_ci_handle,
806 		    wqe_ib_mem_hdl);
807 
808 		/* Free the kmem allocated for the WQEs */
809 		kmem_free(wqe_kmem, wqe_kmem_sz);
810 
811 		/* Destroy the WQE mgt struct mutex */
812 		mutex_destroy(&wqe_mgt->wqes_mutex);
813 
814 		/* Free the WQE management structure */
815 		kmem_free(wqe_mgt, sizeof (ibmf_wqe_mgt_t));
816 
817 		mutex_enter(&qp_ctx->isq_wqe_mutex);
818 		wqe_mgt = qp_ctx->isq_wqe_mgt_list;
819 	}
820 
821 	mutex_exit(&qp_ctx->isq_wqe_mutex);
822 
823 	/* Destroy the kmem_cache for the send WQE */
824 	kmem_cache_destroy(qp_ctx->isq_send_wqes_cache);
825 	/* Destroy the kmem_cache for the receive WQE */
826 	kmem_cache_destroy(qp_ctx->isq_recv_wqes_cache);
827 
828 	/*
829 	 * Destroy the vmem arena for the WQEs
830 	 * This must be done after the kmem_cache_destroy() calls since
831 	 * the cache destructors call vmem_free()
832 	 */
833 	vmem_destroy((void *)qp_ctx->isq_wqe_ib_vmem);
834 
835 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_fini_wqes_end,
836 	    IBMF_TNF_TRACE, "", "ibmf_i_fini_wqes() exit\n");
837 }
838 
839 /*
840  * ibmf_i_init_send_wqe():
841  *	Initialize a send WQE
842  */
843 /* ARGSUSED */
844 void
845 ibmf_i_init_send_wqe(ibmf_client_t *clientp, ibmf_msg_impl_t *msgimplp,
846     ibt_wr_ds_t *sglp, ibmf_send_wqe_t *wqep, ibt_ud_dest_hdl_t ud_dest,
847     ibt_qp_hdl_t ibt_qp_handle, ibmf_qp_handle_t ibmf_qp_handle)
848 {
849 	ibmf_msg_bufs_t	*ipbufs = &msgimplp->im_msgbufs_send;
850 	ibmf_msg_bufs_t	*hdr_ipbufs;
851 	ib_mad_hdr_t	*ibmadhdrp;
852 	ibmf_rmpp_ctx_t	*rmpp_ctx = &msgimplp->im_rmpp_ctx;
853 	ibmf_rmpp_hdr_t	*rmpp_hdr;
854 	ibt_send_wr_t	*swrp;
855 	uchar_t		*buf;
856 	size_t		data_sz, offset;
857 	uint32_t	cl_hdr_sz, cl_hdr_off;
858 
859 	IBMF_TRACE_5(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_send_wqe_start,
860 	    IBMF_TNF_TRACE, "", "ibmf_i_init_send_wqe() enter, "
861 	    "clientp = %p, msg = %p, sglp = %p , wqep = %p, qp_hdl = %p\n",
862 	    tnf_opaque, clientp, clientp, tnf_opaque, msg, msgimplp,
863 	    tnf_opaque, sglp, sglp, tnf_opaque, wqep, wqep,
864 	    tnf_opaque, qp_hdl, ibmf_qp_handle);
865 
866 	_NOTE(ASSUMING_PROTECTED(*wqep))
867 	_NOTE(ASSUMING_PROTECTED(*sglp))
868 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*swrp))
869 
870 	swrp = &wqep->send_wr;
871 	/* use send wqe pointer as the WR ID */
872 	IBMF_ADDR_TO_SEND_WR_ID(wqep, swrp->wr_id);
873 	ASSERT(swrp->wr_id != NULL);
874 	swrp->wr_flags = IBT_WR_NO_FLAGS;
875 	swrp->wr_opcode = IBT_WRC_SEND;
876 	swrp->wr_trans = IBT_UD_SRV;
877 	wqep->send_client = clientp;
878 	wqep->send_msg = msgimplp;
879 
880 	IBMF_INIT_SG_ELEMENT(sglp[0], wqep->send_mem, wqep->send_sg_lkey,
881 	    IBMF_MAD_SIZE);
882 
883 	bzero(wqep->send_mem, IBMF_MAD_SIZE);
884 	if (msgimplp->im_flags & IBMF_MSG_FLAGS_SEND_RMPP) {
885 		buf = (uchar_t *)ipbufs->im_bufs_cl_data +
886 		    (rmpp_ctx->rmpp_ns - 1) * rmpp_ctx->rmpp_pkt_data_sz;
887 		data_sz = (rmpp_ctx->rmpp_ns == rmpp_ctx->rmpp_num_pkts) ?
888 		    rmpp_ctx->rmpp_last_pkt_sz : rmpp_ctx->rmpp_pkt_data_sz;
889 	} else {
890 		buf = ipbufs->im_bufs_cl_data;
891 		data_sz = ipbufs->im_bufs_cl_data_len;
892 	}
893 
894 	/*
895 	 * We pick the correct msgbuf based on the nature of the transaction.
896 	 * Where the send msgbuf is available, we pick it to provide the
897 	 * context of the outgoing MAD. Note that if this is a termination
898 	 * context, then  the send buffer is invalid even if the sequenced
899 	 * flags is set because the termination message only has a receive
900 	 * buffer set up.
901 	 */
902 	if ((msgimplp->im_flags & IBMF_MSG_FLAGS_SEQUENCED) &&
903 	    ((msgimplp->im_flags & IBMF_MSG_FLAGS_TERMINATION) == 0)) {
904 		hdr_ipbufs = &msgimplp->im_msgbufs_send;
905 	} else if (msgimplp->im_flags & IBMF_MSG_FLAGS_RECV_RMPP) {
906 		hdr_ipbufs = &msgimplp->im_msgbufs_recv;
907 	} else if (msgimplp->im_flags & IBMF_MSG_FLAGS_SEND_RMPP) {
908 		hdr_ipbufs = &msgimplp->im_msgbufs_send;
909 	} else {
910 		if (msgimplp->im_unsolicited == B_TRUE) {
911 			hdr_ipbufs = &msgimplp->im_msgbufs_recv;
912 		} else {
913 			hdr_ipbufs = &msgimplp->im_msgbufs_send;
914 		}
915 	}
916 
917 	bcopy((void *)hdr_ipbufs->im_bufs_mad_hdr,
918 	    (void *)wqep->send_mem, sizeof (ib_mad_hdr_t));
919 
920 	/*
921 	 * For unsolicited messages, we only have the sender's MAD at hand.
922 	 * So, we must flip the response bit in the method for the outgoing MAD.
923 	 */
924 	ibmadhdrp = (ib_mad_hdr_t *)wqep->send_mem;
925 	if (msgimplp->im_unsolicited == B_TRUE) {
926 		ibmadhdrp->R_Method = IBMF_FLIP_RESP_BIT(ibmadhdrp->R_Method);
927 	}
928 
929 	offset = sizeof (ib_mad_hdr_t);
930 
931 	if ((msgimplp->im_flags & IBMF_MSG_FLAGS_SEND_RMPP) ||
932 	    (msgimplp->im_flags & IBMF_MSG_FLAGS_RECV_RMPP)) {
933 
934 		rmpp_hdr = (ibmf_rmpp_hdr_t *)
935 		    ((uintptr_t)wqep->send_mem + offset);
936 
937 		_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*rmpp_hdr));
938 
939 		IBMF_TRACE_4(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_i_init_send_wqe,
940 		    IBMF_TNF_TRACE, "",
941 		    "ibmf_init_send_wqe: msgimplp = %p, rmpp_type = %d,"
942 		    " next_seg = %d, num_pkts = %d\n",
943 		    tnf_opaque, msgimplp, msgimplp,
944 		    tnf_opaque, rmpp_type, rmpp_ctx->rmpp_type,
945 		    tnf_opaque, next_seg, rmpp_ctx->rmpp_ns,
946 		    tnf_opaque, num_pkts, rmpp_ctx->rmpp_num_pkts);
947 
948 		/*
949 		 * Initialize the RMPP header
950 		 */
951 		rmpp_ctx->rmpp_flags = IBMF_RMPP_FLAGS_ACTIVE;
952 
953 		/* first, last packet flags set only for type DATA */
954 		if (rmpp_ctx->rmpp_type == IBMF_RMPP_TYPE_DATA) {
955 
956 			if (rmpp_ctx->rmpp_ns == 1)
957 				rmpp_ctx->rmpp_flags |=
958 				    IBMF_RMPP_FLAGS_FIRST_PKT;
959 			else
960 				rmpp_ctx->rmpp_respt = IBMF_RMPP_DEFAULT_RRESPT;
961 
962 			if (rmpp_ctx->rmpp_ns == rmpp_ctx->rmpp_num_pkts)
963 				rmpp_ctx->rmpp_flags |=
964 				    IBMF_RMPP_FLAGS_LAST_PKT;
965 		} else {
966 			data_sz = 0;
967 			rmpp_ctx->rmpp_respt = IBMF_RMPP_TERM_RRESPT;
968 		}
969 
970 		IBMF_INIT_RMPP_HDR(rmpp_hdr,
971 		    IBMF_RMPP_VERSION, rmpp_ctx->rmpp_type,
972 		    rmpp_ctx->rmpp_respt, rmpp_ctx->rmpp_flags,
973 		    rmpp_ctx->rmpp_status, rmpp_ctx->rmpp_word3,
974 		    rmpp_ctx->rmpp_word4)
975 
976 		IBMF_TRACE_5(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_i_init_send_wqe,
977 		    IBMF_TNF_TRACE, "",
978 		    "ibmf_init_send_wqe: msgimplp = %p, rmpp_type = %d,"
979 		    " rmpp_flags = 0x%x, rmpp_segnum = %d, pyld_nwl = %d\n",
980 		    tnf_opaque, msgimplp, msgimplp,
981 		    tnf_opaque, rmpp_type, rmpp_hdr->rmpp_type,
982 		    tnf_opaque, rmpp_flags, rmpp_hdr->rmpp_flags,
983 		    tnf_opaque, rmpp_segnum, b2h32(rmpp_hdr->rmpp_segnum),
984 		    tnf_opaque, pyld_nwl, b2h32(rmpp_hdr->rmpp_pyldlen_nwl));
985 
986 		_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(rmpp_hdr));
987 	}
988 
989 	/* determine offset to start class header */
990 	ibmf_i_mgt_class_to_hdr_sz_off(
991 	    hdr_ipbufs->im_bufs_mad_hdr->MgmtClass,
992 	    &cl_hdr_sz, &cl_hdr_off);
993 	offset += cl_hdr_off;
994 	if (hdr_ipbufs->im_bufs_cl_hdr != NULL) {
995 		bcopy((void *)hdr_ipbufs->im_bufs_cl_hdr,
996 		    (void *)((uintptr_t)wqep->send_mem + offset),
997 		    hdr_ipbufs->im_bufs_cl_hdr_len);
998 		offset += hdr_ipbufs->im_bufs_cl_hdr_len;
999 	}
1000 	bcopy((void *)buf, (void *)((uintptr_t)wqep->send_mem + offset),
1001 	    data_sz);
1002 	swrp->wr_sgl = sglp;
1003 	swrp->wr_nds = 1;
1004 	swrp->wr.ud.udwr_dest = ud_dest;
1005 	wqep->send_port_num = clientp->ic_client_info.port_num;
1006 	wqep->send_qp_handle = ibt_qp_handle;
1007 	wqep->send_ibmf_qp_handle = ibmf_qp_handle;
1008 
1009 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*swrp))
1010 
1011 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_send_wqe_end,
1012 	    IBMF_TNF_TRACE, "", "ibmf_i_init_send_wqe() exit\n");
1013 }
1014 
1015 /*
1016  * ibmf_i_init_recv_wqe():
1017  *	Initialize a receive WQE
1018  */
1019 void
1020 ibmf_i_init_recv_wqe(ibmf_qp_t *qpp, ibt_wr_ds_t *sglp,
1021     ibmf_recv_wqe_t *wqep, ibt_qp_hdl_t ibt_qp_handle,
1022     ibmf_qp_handle_t ibmf_qp_handle)
1023 {
1024 	ibt_recv_wr_t		*rwrp;
1025 
1026 	IBMF_TRACE_4(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_recv_wqe_start,
1027 	    IBMF_TNF_TRACE, "", "ibmf_i_init_recv_wqe() enter, "
1028 	    "qpp = %p, sglp = %p , wqep = %p, ud_dest = %p, qp_hdl = %p\n",
1029 	    tnf_opaque, qpp, qpp, tnf_opaque, sglp, sglp, tnf_opaque,
1030 	    wqep, wqep, tnf_opaque, qp_hdl, ibmf_qp_handle);
1031 
1032 	_NOTE(ASSUMING_PROTECTED(*wqep))
1033 	_NOTE(ASSUMING_PROTECTED(*sglp))
1034 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*rwrp))
1035 
1036 	rwrp = &wqep->recv_wr;
1037 
1038 	/*
1039 	 * we set a bit in the WR ID to be able to easily distinguish
1040 	 * between send completions and recv completions
1041 	 */
1042 	IBMF_ADDR_TO_RECV_WR_ID(wqep, rwrp->wr_id);
1043 
1044 	IBMF_INIT_SG_ELEMENT(sglp[0], wqep->recv_mem, wqep->recv_sg_lkey,
1045 	    sizeof (ib_grh_t) + IBMF_MAD_SIZE);
1046 
1047 	rwrp->wr_sgl = sglp;
1048 	rwrp->wr_nds = IBMF_MAX_RQ_WR_SGL_ELEMENTS;
1049 	if (ibmf_qp_handle == IBMF_QP_HANDLE_DEFAULT) {
1050 		wqep->recv_port_num = qpp->iq_port_num;
1051 	} else {
1052 		ibmf_alt_qp_t	*altqp = (ibmf_alt_qp_t *)ibmf_qp_handle;
1053 		wqep->recv_port_num = altqp->isq_port_num;
1054 	}
1055 	wqep->recv_qpp = qpp;
1056 	wqep->recv_qp_handle = ibt_qp_handle;
1057 	wqep->recv_ibmf_qp_handle = ibmf_qp_handle;
1058 
1059 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*rwrp))
1060 
1061 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_recv_wqe_end,
1062 	    IBMF_TNF_TRACE, "", "ibmf_i_init_recv_wqe() exit\n");
1063 }
1064 
1065 /*
1066  * ibmf_i_extend_wqe_cache():
1067  *	Extend the kmem WQE cache
1068  */
1069 int
1070 ibmf_i_extend_wqe_cache(ibmf_ci_t *cip, ibmf_qp_handle_t ibmf_qp_handle,
1071     boolean_t block)
1072 {
1073 	ibmf_wqe_mgt_t		*wqe_mgt;
1074 
1075 	IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L4,
1076 	    ibmf_i_extend_wqe_cache_start, IBMF_TNF_TRACE, "",
1077 	    "ibmf_i_extend_wqe_cache() enter, cip = %p, qp_hdl = %p, "
1078 	    " block = %d\n", tnf_opaque, cip, cip, tnf_opaque, qp_hdl,
1079 	    ibmf_qp_handle, tnf_uint, block, block);
1080 
1081 	/*
1082 	 * Allocate memory for the WQE management structure
1083 	 */
1084 	wqe_mgt = kmem_zalloc(sizeof (ibmf_wqe_mgt_t),
1085 	    (block == B_TRUE ? KM_SLEEP : KM_NOSLEEP));
1086 	if (wqe_mgt == NULL) {
1087 		IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
1088 		    ibmf_i_extend_wqe_cache_err, IBMF_TNF_ERROR, "",
1089 		    "ibmf_i_extend_wqe_cache(): %s\n",
1090 		    tnf_string, msg, "wqe mgt alloc failed");
1091 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
1092 		    ibmf_i_extend_wqe_cache_end, IBMF_TNF_TRACE, "",
1093 		    "ibmf_i_extend_wqe_cache() exit\n");
1094 		return (IBMF_NO_RESOURCES);
1095 	}
1096 	mutex_init(&wqe_mgt->wqes_mutex, NULL, MUTEX_DRIVER, NULL);
1097 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*wqe_mgt))
1098 
1099 	/* Allocate and register more WQE memory */
1100 	if (ibmf_i_extend_wqe_mem(cip, ibmf_qp_handle, wqe_mgt,
1101 	    block) != IBMF_SUCCESS) {
1102 		mutex_destroy(&wqe_mgt->wqes_mutex);
1103 		kmem_free(wqe_mgt, sizeof (ibmf_wqe_mgt_t));
1104 		IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
1105 		    ibmf_i_extend_wqe_cache_err, IBMF_TNF_ERROR, "",
1106 		    "ibmf_i_extend_wqe_cache(): %s\n",
1107 		    tnf_string, msg, "extension of WQE pool failed");
1108 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
1109 		    ibmf_i_extend_wqe_cache_end, IBMF_TNF_TRACE, "",
1110 		    "ibmf_i_extend_wqe_cache() exit\n");
1111 		return (IBMF_NO_RESOURCES);
1112 	}
1113 
1114 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
1115 	    ibmf_i_extend_wqe_cache_end, IBMF_TNF_TRACE, "",
1116 	    "ibmf_i_extend_wqe_cache() exit\n");
1117 
1118 	return (IBMF_SUCCESS);
1119 }
1120 
1121 /*
1122  * ibmf_i_extend_wqe_mem():
1123  *	Allocate and register more WQE memory, and expand the VMEM arena
1124  */
1125 static int
1126 ibmf_i_extend_wqe_mem(ibmf_ci_t *cip, ibmf_qp_handle_t ibmf_qp_handle,
1127     ibmf_wqe_mgt_t *wqe_mgt, boolean_t block)
1128 {
1129 	ibt_status_t		status;
1130 	ibt_mr_hdl_t		mem_hdl;
1131 	ibt_mr_desc_t		mem_desc;
1132 	ibt_mr_attr_t		mem_attr;
1133 	ibmf_alt_qp_t		*qp_ctx;
1134 	ibmf_wqe_mgt_t		*pwqe_mgt;
1135 	vmem_t			*wqe_vmem_arena;
1136 
1137 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*wqe_mgt))
1138 
1139 	IBMF_TRACE_4(IBMF_TNF_DEBUG, DPRINT_L4,
1140 	    ibmf_i_extend_wqe_cache_start, IBMF_TNF_TRACE, "",
1141 	    "ibmf_i_extend_wqe_cache() enter, cip = %p, qp_hdl = %p"
1142 	    "wqe_mgt = %p, block = %d\n",
1143 	    tnf_opaque, cip, cip, tnf_opaque, qp_hdl, ibmf_qp_handle,
1144 	    tnf_opaque, wqe_mgt, wqe_mgt, tnf_uint, block, block);
1145 
1146 	/*
1147 	 * Allocate more memory for the WQEs to be used by the
1148 	 * specified QP
1149 	 */
1150 	wqe_mgt->wqes_kmem_sz = cip->ci_nports * 2 *
1151 	    ((IBMF_MEM_PER_WQE * ibmf_send_wqes_per_port) +
1152 	    (IBMF_MEM_PER_WQE * ibmf_recv_wqes_per_port));
1153 	wqe_mgt->wqes_kmem = kmem_zalloc(wqe_mgt->wqes_kmem_sz,
1154 	    (block == B_TRUE ? KM_SLEEP : KM_NOSLEEP));
1155 	if (wqe_mgt->wqes_kmem == NULL) {
1156 		IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
1157 		    ibmf_i_extend_wqe_mem_err, IBMF_TNF_ERROR, "",
1158 		    "ibmf_i_extend_wqe_mem(): %s\n",
1159 		    tnf_string, msg, "extension of WQE pool failed");
1160 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
1161 		    ibmf_i_extend_wqe_mem_end, IBMF_TNF_TRACE, "",
1162 		    "ibmf_i_extend_wqe_mem() exit\n");
1163 		return (IBMF_NO_RESOURCES);
1164 	}
1165 
1166 	mem_attr.mr_vaddr = (ib_vaddr_t)(uintptr_t)wqe_mgt->wqes_kmem;
1167 	mem_attr.mr_len = wqe_mgt->wqes_kmem_sz;
1168 	mem_attr.mr_flags = (block == B_TRUE ? IBT_MR_SLEEP : IBT_MR_NOSLEEP)
1169 	    | IBT_MR_ENABLE_LOCAL_WRITE;
1170 	mem_attr.mr_as = NULL;
1171 
1172 	/* Register the allocated memory */
1173 	status = ibt_register_mr(cip->ci_ci_handle, cip->ci_pd,
1174 	    &mem_attr, &mem_hdl, &mem_desc);
1175 	if (status != IBT_SUCCESS) {
1176 		kmem_free(wqe_mgt->wqes_kmem, wqe_mgt->wqes_kmem_sz);
1177 		IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
1178 		    ibmf_i_extend_wqe_mem_err, IBMF_TNF_ERROR, "",
1179 		    "ibmf_i_extend_wqe_mem(): %s\n",
1180 		    tnf_string, msg, "wqe extension MR failed");
1181 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
1182 		    ibmf_i_extend_wqe_mem_end, IBMF_TNF_TRACE, "",
1183 		    "ibmf_i_extend_wqe_mem() exit\n");
1184 		return (IBMF_NO_RESOURCES);
1185 	}
1186 
1187 	/* Store the memory registration information */
1188 	wqe_mgt->wqes_ib_mem = mem_desc.md_vaddr;
1189 	wqe_mgt->wqes_ib_lkey = mem_desc.md_lkey;
1190 	wqe_mgt->wqes_ib_mem_hdl = mem_hdl;
1191 
1192 	/* Get the VMEM arena based on the QP type */
1193 	if (ibmf_qp_handle == IBMF_QP_HANDLE_DEFAULT) {
1194 		wqe_vmem_arena = cip->ci_wqe_ib_vmem;
1195 	} else {
1196 		qp_ctx = (ibmf_alt_qp_t *)ibmf_qp_handle;
1197 		wqe_vmem_arena = qp_ctx->isq_wqe_ib_vmem;
1198 	}
1199 
1200 	/* Add these addresses to the vmem arena */
1201 	if (vmem_add(wqe_vmem_arena, (void *)(uintptr_t)wqe_mgt->wqes_ib_mem,
1202 	    wqe_mgt->wqes_kmem_sz,
1203 	    (block == B_TRUE ? VM_SLEEP : VM_NOSLEEP)) == NULL) {
1204 		(void) ibt_deregister_mr(cip->ci_ci_handle,
1205 		    wqe_mgt->wqes_ib_mem_hdl);
1206 		kmem_free(wqe_mgt->wqes_kmem, wqe_mgt->wqes_kmem_sz);
1207 		IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
1208 		    ibmf_i_extend_wqe_mem_err, IBMF_TNF_ERROR, "",
1209 		    "ibmf_i_extend_wqe_mem(): %s\n",
1210 		    tnf_string, msg, "wqe extension vmem_add failed");
1211 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
1212 		    ibmf_i_extend_wqe_mem_end, IBMF_TNF_TRACE, "",
1213 		    "ibmf_i_extend_wqe_mem() exit\n");
1214 		return (IBMF_NO_RESOURCES);
1215 	}
1216 
1217 	/* Get the WQE management pointers based on the QP type */
1218 	if (ibmf_qp_handle == IBMF_QP_HANDLE_DEFAULT) {
1219 		mutex_enter(&cip->ci_wqe_mutex);
1220 		pwqe_mgt = cip->ci_wqe_mgt_list;
1221 
1222 		/* Add the new wqe management struct to the end of the list */
1223 		while (pwqe_mgt->wqe_mgt_next != NULL)
1224 			pwqe_mgt = pwqe_mgt->wqe_mgt_next;
1225 		pwqe_mgt->wqe_mgt_next = wqe_mgt;
1226 
1227 		mutex_exit(&cip->ci_wqe_mutex);
1228 	} else {
1229 		mutex_enter(&qp_ctx->isq_wqe_mutex);
1230 		pwqe_mgt = qp_ctx->isq_wqe_mgt_list;
1231 
1232 		/* Add the new wqe management struct to the end of the list */
1233 		while (pwqe_mgt->wqe_mgt_next != NULL)
1234 			pwqe_mgt = pwqe_mgt->wqe_mgt_next;
1235 		pwqe_mgt->wqe_mgt_next = wqe_mgt;
1236 
1237 		mutex_exit(&qp_ctx->isq_wqe_mutex);
1238 	}
1239 
1240 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_extend_wqe_mem_end,
1241 	    IBMF_TNF_TRACE, "", "ibmf_i_extend_wqe_mem() exit\n");
1242 
1243 	return (IBMF_SUCCESS);
1244 }
1245 
1246 /*
1247  * ibmf_i_alloc_send_resources():
1248  *	Allocate send resources (the send WQE)
1249  */
1250 int
1251 ibmf_i_alloc_send_resources(ibmf_ci_t *cip, ibmf_msg_impl_t *msgimplp,
1252     boolean_t block, ibmf_send_wqe_t **swqepp)
1253 {
1254 	ibmf_send_wqe_t		*send_wqep;
1255 	struct kmem_cache	*kmem_cachep;
1256 	ibmf_qp_handle_t	ibmf_qp_handle = msgimplp->im_qp_hdl;
1257 	ibmf_alt_qp_t		*altqp;
1258 
1259 	IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L4,
1260 	    ibmf_i_alloc_send_resources_start, IBMF_TNF_TRACE, "",
1261 	    "ibmf_i_alloc_send_resources() enter, cip = %p, msg = %p, "
1262 	    " block = %d\n", tnf_opaque, cip, cip, tnf_opaque, msg,
1263 	    msgimplp, tnf_uint, block, block);
1264 
1265 	/* Get the WQE kmem cache pointer based on the QP type */
1266 	if (ibmf_qp_handle == IBMF_QP_HANDLE_DEFAULT)
1267 		kmem_cachep = cip->ci_send_wqes_cache;
1268 	else {
1269 		altqp = (ibmf_alt_qp_t *)ibmf_qp_handle;
1270 		kmem_cachep = altqp->isq_send_wqes_cache;
1271 	}
1272 
1273 	/*
1274 	 * Allocate a send WQE from the send WQE kmem cache
1275 	 * Do not block here as we are holding the msgimpl mutex.
1276 	 */
1277 	send_wqep = kmem_cache_alloc(kmem_cachep, KM_NOSLEEP);
1278 	if (send_wqep == NULL) {
1279 		/*
1280 		 * Attempt to extend the cache and then retry the
1281 		 * kmem_cache_alloc()
1282 		 * The block argument (third) is set to B_FALSE.
1283 		 */
1284 		if (ibmf_i_extend_wqe_cache(cip, ibmf_qp_handle, B_FALSE) ==
1285 		    IBMF_NO_RESOURCES) {
1286 			mutex_enter(&cip->ci_mutex);
1287 			IBMF_ADD32_PORT_KSTATS(cip, swqe_allocs_failed, 1);
1288 			mutex_exit(&cip->ci_mutex);
1289 			IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
1290 			    ibmf_i_alloc_send_resources_err, IBMF_TNF_ERROR, "",
1291 			    "ibmf_i_alloc_send_resources(): %s\n",
1292 			    tnf_string, msg, "alloc send_wqe failed");
1293 			IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
1294 			    ibmf_i_alloc_send_resources_end, IBMF_TNF_TRACE, "",
1295 			    "ibmf_i_alloc_send_resources() exit\n");
1296 			return (IBMF_NO_RESOURCES);
1297 		} else {
1298 			send_wqep = kmem_cache_alloc(kmem_cachep, KM_NOSLEEP);
1299 			if (send_wqep == NULL) {
1300 				/* Allocation failed again. Give up here. */
1301 				mutex_enter(&cip->ci_mutex);
1302 				IBMF_ADD32_PORT_KSTATS(cip, swqe_allocs_failed,
1303 				    1);
1304 				mutex_exit(&cip->ci_mutex);
1305 				IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
1306 				    ibmf_i_alloc_send_resources_err,
1307 				    IBMF_TNF_ERROR, "",
1308 				    "ibmf_i_alloc_send_resources(): %s\n",
1309 				    tnf_string, msg, "alloc send_wqe failed");
1310 				IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
1311 				    ibmf_i_alloc_send_resources_end,
1312 				    IBMF_TNF_TRACE, "",
1313 				    "ibmf_i_alloc_send_resources() exit\n");
1314 				return (IBMF_NO_RESOURCES);
1315 			}
1316 		}
1317 	}
1318 
1319 	mutex_enter(&cip->ci_mutex);
1320 	IBMF_ADD32_PORT_KSTATS(cip, send_wqes_alloced, 1);
1321 	mutex_exit(&cip->ci_mutex);
1322 	if (ibmf_qp_handle == IBMF_QP_HANDLE_DEFAULT) {
1323 		mutex_enter(&cip->ci_mutex);
1324 		cip->ci_wqes_alloced++;
1325 		mutex_exit(&cip->ci_mutex);
1326 	} else {
1327 		mutex_enter(&altqp->isq_mutex);
1328 		altqp->isq_wqes_alloced++;
1329 		mutex_exit(&altqp->isq_mutex);
1330 	}
1331 
1332 	send_wqep->send_msg = msgimplp;
1333 	*swqepp = send_wqep;
1334 
1335 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
1336 	    ibmf_i_alloc_send_resources_end, IBMF_TNF_TRACE, "",
1337 	    "ibmf_i_alloc_send_resources() exit\n");
1338 
1339 	return (IBMF_SUCCESS);
1340 }
1341 
1342 /*
1343  * ibmf_i_free_send_resources():
1344  *	Free send resources (just the send WQE)
1345  */
1346 /* ARGSUSED */
1347 void
1348 ibmf_i_free_send_resources(ibmf_ci_t *cip, ibmf_msg_impl_t *msgimplp,
1349     ibmf_send_wqe_t *swqep)
1350 {
1351 	struct kmem_cache	*kmem_cachep;
1352 	ibmf_qp_handle_t	ibmf_qp_handle = msgimplp->im_qp_hdl;
1353 	ibmf_alt_qp_t		*altqp;
1354 
1355 	IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L4,
1356 	    ibmf_i_free_send_resources_start, IBMF_TNF_TRACE, "",
1357 	    "ibmf_i_free_send_resources() enter, cip = %p, msg = %p, "
1358 	    " swqep = %p\n", tnf_opaque, cip, cip, tnf_opaque, msg,
1359 	    msgimplp, tnf_opaque, swqep, swqep);
1360 
1361 	/* Get the WQE kmem cache pointer based on the QP type */
1362 	if (ibmf_qp_handle == IBMF_QP_HANDLE_DEFAULT)
1363 		kmem_cachep = cip->ci_send_wqes_cache;
1364 	else {
1365 		altqp = (ibmf_alt_qp_t *)ibmf_qp_handle;
1366 		kmem_cachep = altqp->isq_send_wqes_cache;
1367 	}
1368 
1369 	/* return the send WQE to the kmem cache */
1370 	kmem_cache_free(kmem_cachep, swqep);
1371 
1372 	mutex_enter(&cip->ci_mutex);
1373 	IBMF_SUB32_PORT_KSTATS(cip, send_wqes_alloced, 1);
1374 	mutex_exit(&cip->ci_mutex);
1375 	if (ibmf_qp_handle == IBMF_QP_HANDLE_DEFAULT) {
1376 		mutex_enter(&cip->ci_mutex);
1377 		cip->ci_wqes_alloced--;
1378 		if (cip->ci_wqes_alloced == 0)
1379 			cv_signal(&cip->ci_wqes_cv);
1380 		mutex_exit(&cip->ci_mutex);
1381 	} else {
1382 		mutex_enter(&altqp->isq_mutex);
1383 		altqp->isq_wqes_alloced--;
1384 		if (altqp->isq_wqes_alloced == 0)
1385 			cv_signal(&altqp->isq_wqes_cv);
1386 		mutex_exit(&altqp->isq_mutex);
1387 	}
1388 
1389 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
1390 	    ibmf_i_free_send_resources_end, IBMF_TNF_TRACE, "",
1391 	    "ibmf_i_free_send_resources() exit\n");
1392 }
1393