Home | History | Annotate | Download | only in ibmf
      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