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 client interfaces of the IBMF.
     28  */
     29 
     30 #include <sys/ib/mgt/ibmf/ibmf_impl.h>
     31 
     32 #define	IBMF_SET_CLIENT_SIGNATURE(clientp) {			\
     33 		(clientp)->ic_client_sig = (void *)0xf00DdEaD;	\
     34 }
     35 
     36 #define	IBMF_VERIFY_CLIENT_SIGNATURE(clientp)			\
     37 	(((clientp) != NULL && (clientp)->ic_client_sig ==	\
     38 	    (void *)0xf00DdEaD) ? B_TRUE: B_FALSE)
     39 
     40 #define	IBMF_INVALID_PKEY(pkey)	(((pkey) & 0x7FFF) == 0)
     41 #define	QP1 1
     42 
     43 extern ibmf_state_t *ibmf_statep;
     44 extern int ibmf_trace_level;
     45 
     46 /* ARGSUSED */
     47 int
     48 ibmf_register(ibmf_register_info_t *client_infop, uint_t ibmf_version,
     49     uint_t flags, ibmf_async_event_cb_t client_cb, void  *client_cb_args,
     50     ibmf_handle_t *ibmf_handlep, ibmf_impl_caps_t *ibmf_impl_features)
     51 {
     52 	ibmf_ci_t	*ibmf_cip;
     53 	ibmf_qp_t	*ibmf_qpp;
     54 	ibmf_client_t	*ibmf_clientp;
     55 	boolean_t	error = B_FALSE;
     56 	int		status = IBMF_SUCCESS;
     57 	char		errmsg[128];
     58 
     59 	IBMF_TRACE_4(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_register_start,
     60 	    IBMF_TNF_TRACE, "", "ibmf_register() enter, client_infop = %p "
     61 	    " ibmf_version = %d, flags = 0x%x, ibmf_impl_featuresp = %p\n",
     62 	    tnf_opaque, client_infop, client_infop,
     63 	    tnf_uint, ibmf_version, ibmf_version, tnf_uint, flags, flags,
     64 	    tnf_opaque, ibmf_impl_features, ibmf_impl_features);
     65 
     66 	/* validate client_infop and ibmf_handlep */
     67 	if ((client_infop == NULL) || (ibmf_handlep == NULL) ||
     68 	    (ibmf_impl_features == NULL)) {
     69 		(void) sprintf(errmsg,
     70 		    "invalid argument, NULL pointer argument");
     71 		error = B_TRUE;
     72 		status = IBMF_INVALID_ARG;
     73 		goto bail;
     74 	}
     75 
     76 	/* check IBMF version */
     77 	if (ibmf_version != IBMF_VERSION) {
     78 		(void) sprintf(errmsg, "Bad version");
     79 		error = B_TRUE;
     80 		status = IBMF_BAD_VERSION;
     81 		goto bail;
     82 	}
     83 
     84 	/* check flags validity */
     85 	if ((flags & IBMF_REG_FLAG_NO_OFFLOAD) &&
     86 	    (flags & IBMF_REG_FLAG_SINGLE_OFFLOAD)) {
     87 		(void) sprintf(errmsg, "Bad flags");
     88 		error = B_TRUE;
     89 		status = IBMF_BAD_FLAGS;
     90 		goto bail;
     91 	}
     92 
     93 	/* check client mask and size */
     94 	status = ibmf_i_validate_class_mask(client_infop);
     95 	if (status != IBMF_SUCCESS) {
     96 		(void) sprintf(errmsg, "invalid class");
     97 		error = B_TRUE;
     98 		goto bail;
     99 	}
    100 	/*
    101 	 * verify the node identified by ir_ci_guid exists and that the
    102 	 * port ir_port_num is valid.
    103 	 */
    104 	status = ibmf_i_validate_ci_guid_and_port(client_infop->ir_ci_guid,
    105 	    client_infop->ir_port_num);
    106 	if (status != IBMF_SUCCESS) {
    107 		(void) sprintf(errmsg, "guid/port validation failed");
    108 		error = B_TRUE;
    109 		goto bail;
    110 	}
    111 
    112 	/* get the ci */
    113 	status = ibmf_i_get_ci(client_infop, &ibmf_cip);
    114 	if (status != IBMF_SUCCESS) {
    115 		IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
    116 		    ibmf_register_error, IBMF_TNF_ERROR, "",
    117 		    "ibmf_register(): %s, guid = 0x%p\n",
    118 		    tnf_string, msg, "unable to get ci",
    119 		    tnf_ulonglong, guid, client_infop->ir_ci_guid);
    120 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_register_end,
    121 		    IBMF_TNF_TRACE, "", "ibmf_register() exit\n");
    122 		return (status);
    123 	}
    124 
    125 	/*
    126 	 * check if classes and port are already registered for.
    127 	 */
    128 	status = ibmf_i_validate_classes_and_port(ibmf_cip, client_infop);
    129 	if (status != IBMF_SUCCESS) {
    130 		mutex_enter(&ibmf_cip->ci_mutex);
    131 		IBMF_ADD32_PORT_KSTATS(ibmf_cip, client_regs_failed, 1);
    132 		mutex_exit(&ibmf_cip->ci_mutex);
    133 		/* release ci */
    134 		ibmf_i_release_ci(ibmf_cip);
    135 		(void) sprintf(errmsg,
    136 		    "class and port already registered for or unsupported");
    137 		error = B_TRUE;
    138 		goto bail;
    139 	}
    140 
    141 	/*
    142 	 * the class is valid, get qp and alloc the client
    143 	 */
    144 	/* obtain the qp corresponding to the port and classes */
    145 	status = ibmf_i_get_qp(ibmf_cip, client_infop->ir_port_num,
    146 	    client_infop->ir_client_class, &ibmf_qpp);
    147 	if (status != IBMF_SUCCESS) {
    148 		mutex_enter(&ibmf_cip->ci_mutex);
    149 		IBMF_ADD32_PORT_KSTATS(ibmf_cip, client_regs_failed, 1);
    150 		mutex_exit(&ibmf_cip->ci_mutex);
    151 		ibmf_i_release_ci(ibmf_cip);
    152 		IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
    153 		    ibmf_register_error, IBMF_TNF_ERROR, "",
    154 		    "ibmf_register(): %s, class = 0x%x\n",
    155 		    tnf_string, msg, "can't get qp",
    156 		    tnf_int, class, client_infop->ir_client_class);
    157 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_register_end,
    158 		    IBMF_TNF_TRACE, "", "ibmf_register() exit\n");
    159 		return (status);
    160 	}
    161 
    162 	/* alloc the client */
    163 	status = ibmf_i_alloc_client(client_infop, flags, &ibmf_clientp);
    164 	if (status != IBMF_SUCCESS) {
    165 		mutex_enter(&ibmf_cip->ci_mutex);
    166 		IBMF_ADD32_PORT_KSTATS(ibmf_cip, client_regs_failed, 1);
    167 		mutex_exit(&ibmf_cip->ci_mutex);
    168 		ibmf_i_release_ci(ibmf_cip);
    169 		IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
    170 		    ibmf_register_error, IBMF_TNF_ERROR, "",
    171 		    "ibmf_register(): %s, class = 0x%x\n",
    172 		    tnf_string, msg, "can't alloc client",
    173 		    tnf_int, class, client_infop->ir_client_class);
    174 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_register_end,
    175 		    IBMF_TNF_TRACE, "", "ibmf_register() exit\n");
    176 		return (status);
    177 	}
    178 
    179 	ASSERT(ibmf_clientp != NULL);
    180 
    181 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*ibmf_clientp))
    182 
    183 	/* initialize the IBMF client context */
    184 	ibmf_clientp->ic_myci = ibmf_cip;
    185 	ibmf_clientp->ic_qp = ibmf_qpp;
    186 	ibmf_clientp->ic_ci_handle = ibmf_cip->ci_ci_handle;
    187 
    188 	ibmf_clientp->ic_reg_flags = flags;
    189 
    190 	ibmf_clientp->ic_async_cb = client_cb;
    191 	ibmf_clientp->ic_async_cb_arg = client_cb_args;
    192 
    193 	IBMF_SET_CLIENT_SIGNATURE(ibmf_clientp);
    194 
    195 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*ibmf_clientp))
    196 
    197 	/* add the client to the list of clients */
    198 	ibmf_i_add_client(ibmf_cip, ibmf_clientp);
    199 
    200 	/* increment kstats for number of registered clients */
    201 	mutex_enter(&ibmf_cip->ci_mutex);
    202 	IBMF_ADD32_PORT_KSTATS(ibmf_cip, clients_registered, 1);
    203 	mutex_exit(&ibmf_cip->ci_mutex);
    204 
    205 	/* Setup ibmf_handlep -- handle is last allocated clientp */
    206 	*ibmf_handlep = (ibmf_handle_t)ibmf_clientp;
    207 	*ibmf_impl_features = 0;
    208 
    209 bail:
    210 	if (error) {
    211 		IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
    212 		    ibmf_register_error, IBMF_TNF_ERROR, "",
    213 		    "ibmf_register(): %s\n", tnf_string, msg, errmsg);
    214 	}
    215 
    216 	IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_register_end,
    217 	    IBMF_TNF_TRACE, "", "ibmf_register() exit, ibmf_handle = %p\n",
    218 	    tnf_opaque, ibmf_handle, *ibmf_handlep);
    219 
    220 	return (status);
    221 }
    222 
    223 /* ARGSUSED */
    224 int
    225 ibmf_unregister(ibmf_handle_t *ibmf_handlep, uint_t flags)
    226 {
    227 	ibmf_ci_t	*cip;
    228 	ibmf_client_t	*clientp;
    229 	boolean_t	error = B_FALSE;
    230 	int		status = IBMF_SUCCESS;
    231 	char		errmsg[128];
    232 	int		secs;
    233 
    234 	clientp = (ibmf_client_t *)*ibmf_handlep;
    235 
    236 	IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_unregister_start,
    237 	    IBMF_TNF_TRACE, "", "ibmf_unregister() enter, "
    238 	    "ibmf_handlep = %p, flags = 0x%x\n",
    239 	    tnf_opaque, ibmf_handle, *ibmf_handlep, tnf_uint, flags, flags);
    240 
    241 	/* check for null ibmf_handlep */
    242 	if (ibmf_handlep == NULL) {
    243 		(void) sprintf(errmsg,
    244 		    "invalid argument, NULL pointer argument");
    245 		error = B_TRUE;
    246 		status = IBMF_INVALID_ARG;
    247 		goto bail;
    248 	}
    249 
    250 	/* validate ibmf_handlep */
    251 	if (ibmf_i_is_ibmf_handle_valid(*ibmf_handlep) != IBMF_SUCCESS) {
    252 		(void) sprintf(errmsg, "bad ibmf registration handle");
    253 		error = B_TRUE;
    254 		status = IBMF_BAD_HANDLE;
    255 		goto bail;
    256 	}
    257 
    258 	/* check signature */
    259 	if (IBMF_VERIFY_CLIENT_SIGNATURE(clientp) == B_FALSE) {
    260 		(void) sprintf(errmsg, "bad client signature");
    261 		error = B_TRUE;
    262 		status = IBMF_BAD_HANDLE;
    263 		goto bail;
    264 	}
    265 
    266 	/*
    267 	 * Verify the client does not have a receive callback registered.
    268 	 * If there are messages, give some time for the messages to be
    269 	 * cleaned up.
    270 	 */
    271 	secs = 60;
    272 	mutex_enter(&clientp->ic_mutex);
    273 	while (clientp->ic_recv_cb == NULL && clientp->ic_msgs_alloced != 0 &&
    274 	    secs > 0) {
    275 		mutex_exit(&clientp->ic_mutex);
    276 		delay(drv_usectohz(1000000)); /* one second delay */
    277 		secs--;
    278 		mutex_enter(&clientp->ic_mutex);
    279 	}
    280 
    281 	if (clientp->ic_recv_cb != NULL || clientp->ic_msgs_alloced != 0) {
    282 		IBMF_TRACE_4(IBMF_TNF_NODEBUG, DPRINT_L1,
    283 		    ibmf_unregister_err, IBMF_TNF_ERROR, "",
    284 		    "ibmf_unregister(): %s, flags = 0x%x, recv_cb = 0x%p, "
    285 		    "msgs_alloced = %d\n",
    286 		    tnf_string, msg, "busy with resources", tnf_uint, ic_flags,
    287 		    clientp->ic_flags, tnf_opaque, recv_cb, clientp->ic_recv_cb,
    288 		    tnf_uint, msgs_allocd, clientp->ic_msgs_alloced);
    289 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_unregister_end,
    290 		    IBMF_TNF_TRACE, "", "ibmf_unregister() exit\n");
    291 		mutex_exit(&clientp->ic_mutex);
    292 		return (IBMF_BUSY);
    293 	}
    294 
    295 	mutex_exit(&clientp->ic_mutex);
    296 
    297 	cip = clientp->ic_myci;
    298 
    299 	/* remove the client from the list of clients */
    300 	ibmf_i_delete_client(cip, clientp);
    301 
    302 	/* release the reference to the qp */
    303 	ibmf_i_release_qp(cip, &clientp->ic_qp);
    304 
    305 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*clientp))
    306 
    307 	/* and free the client structure */
    308 	ibmf_i_free_client(clientp);
    309 
    310 	/* release the ci; this may delete & free the ci structure */
    311 	ibmf_i_release_ci(cip);
    312 
    313 	/* decrement kstats for number of registered clients */
    314 	mutex_enter(&cip->ci_mutex);
    315 	IBMF_SUB32_PORT_KSTATS(cip, clients_registered, 1);
    316 	mutex_exit(&cip->ci_mutex);
    317 
    318 	*ibmf_handlep = NULL;
    319 
    320 bail:
    321 	if (error) {
    322 		IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
    323 		    ibmf_unregister_err, IBMF_TNF_ERROR, "",
    324 		    "ibmf_unregister(): %s\n", tnf_string, msg, errmsg);
    325 	}
    326 
    327 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_unregister_end,
    328 	    IBMF_TNF_TRACE, "", "ibmf_unregister() exit\n");
    329 
    330 	return (status);
    331 }
    332 
    333 
    334 /* ARGSUSED */
    335 int
    336 ibmf_setup_async_cb(ibmf_handle_t ibmf_handle, ibmf_qp_handle_t ibmf_qp_handle,
    337     ibmf_msg_cb_t async_msg_cb, void *async_msg_cb_args, uint_t flags)
    338 {
    339 	ibmf_client_t	*clientp;
    340 	boolean_t	error = B_FALSE;
    341 	int		status = IBMF_SUCCESS;
    342 	char		errmsg[128];
    343 
    344 	clientp = (ibmf_client_t *)ibmf_handle;
    345 
    346 	IBMF_TRACE_4(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_setup_async_cb_start,
    347 	    IBMF_TNF_TRACE, "", "ibmf_setup_async_cb() enter, "
    348 	    "ibmf_handlep = %p, cb = 0x%p, cb_args = 0x%p, flags = 0x%x\n",
    349 	    tnf_opaque, ibmf_handle, ibmf_handle, tnf_opaque, cb,
    350 	    async_msg_cb, tnf_opaque, cb_args, async_msg_cb_args,
    351 	    tnf_uint, flags, flags);
    352 
    353 	/* check for null ibmf_handlep */
    354 	if (ibmf_handle == NULL) {
    355 		(void) sprintf(errmsg,
    356 		    "invalid argument, NULL pointer argument");
    357 		error = B_TRUE;
    358 		status = IBMF_INVALID_ARG;
    359 		goto bail;
    360 	}
    361 
    362 	/* validate ibmf_handle */
    363 	if (ibmf_i_is_ibmf_handle_valid(ibmf_handle) != IBMF_SUCCESS) {
    364 		(void) sprintf(errmsg, "bad ibmf registration handle");
    365 		error = B_TRUE;
    366 		status = IBMF_BAD_HANDLE;
    367 		goto bail;
    368 	}
    369 
    370 	/* validate ibmf_qp_handle */
    371 	if (ibmf_i_is_qp_handle_valid(ibmf_handle, ibmf_qp_handle) !=
    372 	    IBMF_SUCCESS) {
    373 		(void) sprintf(errmsg, "bad qp handle");
    374 		error = B_TRUE;
    375 		status = IBMF_BAD_QP_HANDLE;
    376 		goto bail;
    377 	}
    378 
    379 	/* check signature */
    380 	if (IBMF_VERIFY_CLIENT_SIGNATURE(clientp) == B_FALSE) {
    381 		(void) sprintf(errmsg, "bad signature");
    382 		error = B_TRUE;
    383 		status = IBMF_BAD_HANDLE;
    384 		goto bail;
    385 	}
    386 
    387 	ASSERT(clientp->ic_myci != NULL);
    388 
    389 	/* store the registered callback in the appropriate context */
    390 	if (ibmf_qp_handle == IBMF_QP_HANDLE_DEFAULT) {
    391 
    392 		/*
    393 		 * if using the default QP handle, store the callback in
    394 		 * the client context
    395 		 */
    396 		mutex_enter(&clientp->ic_mutex);
    397 
    398 		/* check if the callback has already been registered */
    399 		if (clientp->ic_recv_cb != NULL) {
    400 			mutex_exit(&clientp->ic_mutex);
    401 			(void) sprintf(errmsg, "cb already exists");
    402 			error = B_TRUE;
    403 			status = IBMF_CB_REGISTERED;
    404 			goto bail;
    405 		}
    406 
    407 		clientp->ic_recv_cb = async_msg_cb;
    408 		clientp->ic_recv_cb_arg = async_msg_cb_args;
    409 		mutex_exit(&clientp->ic_mutex);
    410 
    411 	} else {
    412 		ibmf_alt_qp_t *qp_ctxp = (ibmf_alt_qp_t *)ibmf_qp_handle;
    413 
    414 		/*
    415 		 * if using an alternate QP handle, store the callback in
    416 		 * the alternate QP context because there can be more than
    417 		 * one alternate QP associated with a client
    418 		 */
    419 		mutex_enter(&qp_ctxp->isq_mutex);
    420 
    421 		/* check if the callback has already been registered */
    422 		if (qp_ctxp->isq_recv_cb != NULL) {
    423 			mutex_exit(&qp_ctxp->isq_mutex);
    424 			(void) sprintf(errmsg, "cb already exists");
    425 			error = B_TRUE;
    426 			status = IBMF_CB_REGISTERED;
    427 			goto bail;
    428 		}
    429 
    430 		qp_ctxp->isq_recv_cb = async_msg_cb;
    431 		qp_ctxp->isq_recv_cb_arg = async_msg_cb_args;
    432 
    433 		mutex_exit(&qp_ctxp->isq_mutex);
    434 	}
    435 
    436 bail:
    437 	if (error) {
    438 		IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
    439 		    ibmf_setup_async_cb_err, IBMF_TNF_ERROR, "",
    440 		    "ibmf_setup_async_cb(): %s\n", tnf_string, msg, errmsg);
    441 	}
    442 
    443 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_setup_async_cb_end,
    444 	    IBMF_TNF_TRACE, "", "ibmf_setup_async_cb() exit\n");
    445 
    446 	return (status);
    447 }
    448 
    449 
    450 /* ARGSUSED */
    451 int
    452 ibmf_tear_down_async_cb(ibmf_handle_t ibmf_handle,
    453     ibmf_qp_handle_t ibmf_qp_handle, uint_t flags)
    454 {
    455 	ibmf_client_t	*clientp;
    456 	boolean_t	error = B_FALSE;
    457 	int		status = IBMF_SUCCESS;
    458 	char		errmsg[128];
    459 
    460 	clientp = (ibmf_client_t *)ibmf_handle;
    461 
    462 	IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_tear_down_async_cb_start,
    463 	    IBMF_TNF_TRACE, "", "ibmf_tear_down_async_cb() enter, "
    464 	    "ibmf_handlep = %p, ibmf_qp_handle = %p, flags = 0x%x\n",
    465 	    tnf_opaque, ibmf_handle, ibmf_handle,
    466 	    tnf_opaque, ibmf_qp_handle, ibmf_qp_handle, tnf_uint, flags, flags);
    467 
    468 	/* check for null ibmf_handlep */
    469 	if (ibmf_handle == NULL) {
    470 		(void) sprintf(errmsg,
    471 		    "invalid argument, NULL pointer argument");
    472 		error = B_TRUE;
    473 		status = IBMF_INVALID_ARG;
    474 		goto bail;
    475 	}
    476 
    477 	/* validate ibmf_handle */
    478 	if (ibmf_i_is_ibmf_handle_valid(ibmf_handle) != IBMF_SUCCESS) {
    479 		(void) sprintf(errmsg, "bad ibmf registration handle");
    480 		error = B_TRUE;
    481 		status = IBMF_BAD_HANDLE;
    482 		goto bail;
    483 	}
    484 
    485 	/* validate ibmf_qp_handle */
    486 	if (ibmf_i_is_qp_handle_valid(ibmf_handle, ibmf_qp_handle) !=
    487 	    IBMF_SUCCESS) {
    488 		(void) sprintf(errmsg, "bad qp handle");
    489 		error = B_TRUE;
    490 		status = IBMF_BAD_QP_HANDLE;
    491 		goto bail;
    492 	}
    493 
    494 	/* check signature */
    495 	if (IBMF_VERIFY_CLIENT_SIGNATURE(clientp) == B_FALSE) {
    496 		(void) sprintf(errmsg, "bad signature");
    497 		error = B_TRUE;
    498 		status = IBMF_BAD_HANDLE;
    499 		goto bail;
    500 	}
    501 
    502 	ASSERT(clientp->ic_myci != NULL);
    503 
    504 	/* remove the registered callback from the appropriate context */
    505 	if (ibmf_qp_handle == IBMF_QP_HANDLE_DEFAULT) {
    506 
    507 		mutex_enter(&clientp->ic_mutex);
    508 
    509 		/* check if callback has not been registered */
    510 		if (clientp->ic_recv_cb == NULL) {
    511 			mutex_exit(&clientp->ic_mutex);
    512 			(void) sprintf(errmsg, "no cb exists");
    513 			error = B_TRUE;
    514 			status = IBMF_CB_NOT_REGISTERED;
    515 			goto bail;
    516 		}
    517 
    518 		/*
    519 		 * if an unsolicited MAD just arrived for this
    520 		 * client, wait for it to be processed
    521 		 */
    522 		while (clientp->ic_flags & IBMF_CLIENT_RECV_CB_ACTIVE) {
    523 			clientp->ic_flags |= IBMF_CLIENT_TEAR_DOWN_CB;
    524 			cv_wait(&clientp->ic_recv_cb_teardown_cv,
    525 			    &clientp->ic_mutex);
    526 			clientp->ic_flags &= ~IBMF_CLIENT_TEAR_DOWN_CB;
    527 		}
    528 
    529 		_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(clientp->ic_recv_cb,
    530 		     clientp->ic_recv_cb_arg))
    531 
    532 		/*
    533 		 * if using the default QP handle, remove the callback from
    534 		 * the client context
    535 		 */
    536 		clientp->ic_recv_cb = NULL;
    537 		clientp->ic_recv_cb_arg = NULL;
    538 
    539 		ASSERT((clientp->ic_flags & IBMF_CLIENT_RECV_CB_ACTIVE) == 0);
    540 
    541 		mutex_exit(&clientp->ic_mutex);
    542 	} else {
    543 		ibmf_alt_qp_t *qpp = (ibmf_alt_qp_t *)ibmf_qp_handle;
    544 
    545 		mutex_enter(&qpp->isq_mutex);
    546 
    547 		/* check if callback has not been registered */
    548 		if (qpp->isq_recv_cb == NULL) {
    549 			mutex_exit(&qpp->isq_mutex);
    550 			(void) sprintf(errmsg, "no cb exists");
    551 			error = B_TRUE;
    552 			status = IBMF_CB_NOT_REGISTERED;
    553 			goto bail;
    554 		}
    555 
    556 		/*
    557 		 * if an unsolicited MAD just arrived for this
    558 		 * client on the alternate QP, wait for it to be processed
    559 		 */
    560 		while (qpp->isq_flags & IBMF_CLIENT_RECV_CB_ACTIVE) {
    561 			qpp->isq_flags |= IBMF_CLIENT_TEAR_DOWN_CB;
    562 			cv_wait(&qpp->isq_recv_cb_teardown_cv,
    563 			    &qpp->isq_mutex);
    564 			qpp->isq_flags &= ~IBMF_CLIENT_TEAR_DOWN_CB;
    565 		}
    566 
    567 		/*
    568 		 * if using an alternate QP handle, remove the callback from
    569 		 * the alternate QP context
    570 		 */
    571 		qpp->isq_recv_cb = NULL;
    572 		qpp->isq_recv_cb_arg = NULL;
    573 
    574 		ASSERT((qpp->isq_flags & IBMF_CLIENT_RECV_CB_ACTIVE) == 0);
    575 
    576 		mutex_exit(&qpp->isq_mutex);
    577 	}
    578 
    579 bail:
    580 	if (error) {
    581 		IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
    582 		    ibmf_tear_down_async_cb_err, IBMF_TNF_ERROR, "",
    583 		    "ibmf_tear_down_async_cb(): %s\n", tnf_string, msg, errmsg);
    584 	}
    585 
    586 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_tear_down_async_cb_end,
    587 	    IBMF_TNF_TRACE, "", "ibmf_tear_down_async_cb() exit\n");
    588 
    589 	return (status);
    590 }
    591 
    592 
    593 int
    594 ibmf_alloc_msg(ibmf_handle_t ibmf_handle, int flag, ibmf_msg_t **ibmf_msgpp)
    595 {
    596 	ibmf_msg_impl_t	*ibmf_msg_impl;
    597 	ibmf_client_t	*clientp;
    598 	int		km_flags;
    599 	boolean_t	error = B_FALSE;
    600 	int		status = IBMF_SUCCESS;
    601 	char		errmsg[128];
    602 
    603 	clientp = (ibmf_client_t *)ibmf_handle;
    604 
    605 	IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_alloc_msg_start,
    606 	    IBMF_TNF_TRACE, "", "ibmf_alloc_msg() enter, "
    607 	    "ibmf_handle = %p, flags = 0x%x\n",
    608 	    tnf_opaque, ibmf_handle, ibmf_handle, tnf_uint, flag, flag);
    609 
    610 	/* check for null ibmf_handle and ibmf_msgpp */
    611 	if ((ibmf_handle == NULL) || (ibmf_msgpp == NULL)) {
    612 		(void) sprintf(errmsg,
    613 		    "invalid argument, NULL pointer argument");
    614 		error = B_TRUE;
    615 		status = IBMF_INVALID_ARG;
    616 		goto bail;
    617 	}
    618 
    619 	/* validate ibmf_handle */
    620 	if (ibmf_i_is_ibmf_handle_valid(ibmf_handle) != IBMF_SUCCESS) {
    621 		(void) sprintf(errmsg, "bad ibmf registration handle");
    622 		error = B_TRUE;
    623 		status = IBMF_BAD_HANDLE;
    624 		goto bail;
    625 	}
    626 
    627 	/* check signature */
    628 	if (IBMF_VERIFY_CLIENT_SIGNATURE(clientp) == B_FALSE) {
    629 		(void) sprintf(errmsg, "bad signature");
    630 		error = B_TRUE;
    631 		status = IBMF_BAD_HANDLE;
    632 		goto bail;
    633 	}
    634 
    635 	/* validate flag */
    636 	if (flag != IBMF_ALLOC_SLEEP && flag != IBMF_ALLOC_NOSLEEP) {
    637 		(void) sprintf(errmsg, "invalid flags, flags = 0x%x", flag);
    638 		error = B_TRUE;
    639 		status = IBMF_BAD_FLAGS;
    640 		goto bail;
    641 	}
    642 
    643 	/* set flags for kmem allocaton */
    644 	km_flags = (flag == IBMF_ALLOC_SLEEP) ? KM_SLEEP : KM_NOSLEEP;
    645 
    646 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*ibmf_msg_impl))
    647 
    648 	/* call the internal function to allocate the IBMF message context */
    649 	status = ibmf_i_alloc_msg(clientp, &ibmf_msg_impl, km_flags);
    650 	if (status != IBMF_SUCCESS) {
    651 		mutex_enter(&clientp->ic_kstat_mutex);
    652 		IBMF_ADD32_KSTATS(clientp, msg_allocs_failed, 1);
    653 		mutex_exit(&clientp->ic_kstat_mutex);
    654 		(void) sprintf(errmsg, "message allocation failure");
    655 		error = B_TRUE;
    656 		goto bail;
    657 	}
    658 
    659 	/* increment counter and kstats for number of allocated messages */
    660 	mutex_enter(&clientp->ic_mutex);
    661 	clientp->ic_msgs_alloced++;
    662 	mutex_exit(&clientp->ic_mutex);
    663 	mutex_enter(&clientp->ic_kstat_mutex);
    664 	IBMF_ADD32_KSTATS(clientp, msgs_alloced, 1);
    665 	mutex_exit(&clientp->ic_kstat_mutex);
    666 
    667 	/* initialize the msg */
    668 	ibmf_msg_impl->im_client = clientp;
    669 	cv_init(&ibmf_msg_impl->im_trans_cv, NULL, CV_DRIVER, NULL);
    670 	mutex_init(&ibmf_msg_impl->im_mutex, NULL, MUTEX_DRIVER, NULL);
    671 	*ibmf_msgpp = (ibmf_msg_t *)ibmf_msg_impl;
    672 
    673 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*ibmf_msg_impl))
    674 
    675 bail:
    676 	if (error) {
    677 		IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
    678 		    ibmf_alloc_msg_err, IBMF_TNF_ERROR, "",
    679 		    "ibmf_alloc_msg(): %s\n", tnf_string, msg, errmsg);
    680 	}
    681 
    682 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_alloc_msg_end,
    683 	    IBMF_TNF_TRACE, "", "ibmf_alloc_msg() exit\n");
    684 
    685 	return (status);
    686 }
    687 
    688 
    689 int
    690 ibmf_free_msg(ibmf_handle_t ibmf_handle, ibmf_msg_t **ibmf_msgpp)
    691 {
    692 	ibmf_client_t	*clientp;
    693 	ibmf_msg_impl_t	*ibmf_msg_impl;
    694 	boolean_t	error = B_FALSE;
    695 	int		status = IBMF_SUCCESS;
    696 	char		errmsg[128];
    697 	timeout_id_t	msg_rp_set_id, msg_tr_set_id;
    698 	timeout_id_t	msg_rp_unset_id, msg_tr_unset_id;
    699 
    700 	IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_free_msg_start,
    701 	    IBMF_TNF_TRACE, "", "ibmf_free_msg() enter, " "ibmf_handle = %p\n",
    702 	    tnf_opaque, ibmf_handle, ibmf_handle);
    703 
    704 	/* check for null ibmf_handle and ibmf_msgpp */
    705 	if ((ibmf_handle == NULL) || (ibmf_msgpp == NULL)) {
    706 		(void) sprintf(errmsg,
    707 		    "invalid argument, NULL pointer argument");
    708 		error = B_TRUE;
    709 		status = IBMF_INVALID_ARG;
    710 		goto bail;
    711 	}
    712 
    713 	/* validate ibmf_handle */
    714 	if (ibmf_i_is_ibmf_handle_valid(ibmf_handle) != IBMF_SUCCESS) {
    715 		(void) sprintf(errmsg, "bad ibmf registration handle");
    716 		error = B_TRUE;
    717 		status = IBMF_BAD_HANDLE;
    718 		goto bail;
    719 	}
    720 
    721 	ibmf_msg_impl = (ibmf_msg_impl_t *)*ibmf_msgpp;
    722 
    723 	/* check for null message pointer */
    724 	if (ibmf_msg_impl == NULL) {
    725 		(void) sprintf(errmsg, "null message");
    726 		error = B_TRUE;
    727 		status = IBMF_FAILURE;
    728 		goto bail;
    729 	}
    730 
    731 	mutex_enter(&ibmf_msg_impl->im_mutex);
    732 
    733 	/* check if message context flags indicate a busy message */
    734 	if (ibmf_msg_impl->im_flags & IBMF_MSG_FLAGS_BUSY) {
    735 		mutex_exit(&ibmf_msg_impl->im_mutex);
    736 		(void) sprintf(errmsg, "message in use");
    737 		error = B_TRUE;
    738 		status = IBMF_BUSY;
    739 		goto bail;
    740 	}
    741 
    742 	ASSERT((ibmf_msg_impl->im_flags & IBMF_MSG_FLAGS_ON_LIST) == 0);
    743 
    744 	/* Initialize the timer ID holders */
    745 	msg_rp_set_id = msg_tr_set_id = 0;
    746 	msg_rp_unset_id = msg_tr_unset_id = 0;
    747 
    748 	/* Clear any timers that are still set */
    749 
    750 	if (ibmf_msg_impl->im_rp_timeout_id != 0) {
    751 		msg_rp_set_id = ibmf_msg_impl->im_rp_timeout_id;
    752 		ibmf_msg_impl->im_rp_timeout_id = 0;
    753 	}
    754 
    755 	if (ibmf_msg_impl->im_tr_timeout_id != 0) {
    756 		msg_tr_set_id = ibmf_msg_impl->im_tr_timeout_id;
    757 		ibmf_msg_impl->im_tr_timeout_id = 0;
    758 	}
    759 
    760 	if (ibmf_msg_impl->im_rp_unset_timeout_id != 0) {
    761 		msg_rp_unset_id = ibmf_msg_impl->im_rp_unset_timeout_id;
    762 		ibmf_msg_impl->im_rp_unset_timeout_id = 0;
    763 	}
    764 
    765 	if (ibmf_msg_impl->im_tr_unset_timeout_id != 0) {
    766 		msg_tr_unset_id = ibmf_msg_impl->im_tr_unset_timeout_id;
    767 		ibmf_msg_impl->im_tr_unset_timeout_id = 0;
    768 	}
    769 
    770 	/* mark the message context flags to indicate a freed message */
    771 	ibmf_msg_impl->im_flags |= IBMF_MSG_FLAGS_FREE;
    772 
    773 	mutex_exit(&ibmf_msg_impl->im_mutex);
    774 
    775 	/* cast pointer to client context */
    776 	clientp = (ibmf_client_t *)ibmf_handle;
    777 
    778 	/* check signature */
    779 	if (IBMF_VERIFY_CLIENT_SIGNATURE(clientp) == B_FALSE) {
    780 		(void) sprintf(errmsg, "bad signature");
    781 		error = B_TRUE;
    782 		status = IBMF_BAD_HANDLE;
    783 		goto bail;
    784 	}
    785 
    786 	/* Clear the timers */
    787 	if (msg_rp_unset_id != 0) {
    788 		(void) untimeout(msg_rp_unset_id);
    789 	}
    790 
    791 	if (msg_tr_unset_id != 0) {
    792 		(void) untimeout(msg_tr_unset_id);
    793 	}
    794 
    795 	if (msg_rp_set_id != 0) {
    796 		(void) untimeout(msg_rp_set_id);
    797 	}
    798 
    799 	if (msg_tr_set_id != 0) {
    800 		(void) untimeout(msg_tr_set_id);
    801 	}
    802 
    803 	/* destroy the condition variables */
    804 	cv_destroy(&ibmf_msg_impl->im_trans_cv);
    805 
    806 	/* decrement counter and kstats for number of allocated messages */
    807 	mutex_enter(&clientp->ic_mutex);
    808 	clientp->ic_msgs_alloced--;
    809 	mutex_exit(&clientp->ic_mutex);
    810 	mutex_enter(&clientp->ic_kstat_mutex);
    811 	IBMF_SUB32_KSTATS(clientp, msgs_alloced, 1);
    812 	mutex_exit(&clientp->ic_kstat_mutex);
    813 
    814 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*ibmf_msg_impl,
    815 	    ibmf_msg_impl->im_msgbufs_recv,
    816 	    ibmf_msg_impl->im_msgbufs_send))
    817 
    818 	/* call the internal function to free the message context */
    819 	ibmf_i_free_msg(ibmf_msg_impl);
    820 
    821 	*ibmf_msgpp = NULL;
    822 
    823 bail:
    824 	if (error) {
    825 		IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
    826 		    ibmf_free_msg_err, IBMF_TNF_ERROR, "",
    827 		    "ibmf_free_msg(): %s\n", tnf_string, msg, errmsg);
    828 	}
    829 
    830 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_free_msg_end,
    831 	    IBMF_TNF_TRACE, "", "ibmf_free_msg() exit\n");
    832 
    833 	return (status);
    834 }
    835 
    836 
    837 /* ARGSUSED */
    838 int
    839 ibmf_msg_transport(ibmf_handle_t ibmf_handle, ibmf_qp_handle_t ibmf_qp_handle,
    840     ibmf_msg_t *msgp, ibmf_retrans_t *retrans, ibmf_msg_cb_t msg_cb,
    841     void *msg_cb_args, uint_t flags)
    842 {
    843 	ibmf_client_t	*clientp;
    844 	ibmf_msg_impl_t	*msgimplp;
    845 	boolean_t	blocking, loopback, error = B_FALSE;
    846 	int		status = IBMF_SUCCESS;
    847 	sm_dr_mad_hdr_t	*dr_hdr;
    848 	char		errmsg[128];
    849 
    850 	IBMF_TRACE_5(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_msg_transport_start,
    851 	    IBMF_TNF_TRACE, "", "ibmf_msg_transport() enter, "
    852 	    "ibmf_handlep = %p, ibmf_qp_handle = %p, flags = 0x%x "
    853 	    "msgp = 0x%p, retrans = 0x%p\n",
    854 	    tnf_opaque, ibmf_handle, ibmf_handle,
    855 	    tnf_opaque, ibmf_qp_handle, ibmf_qp_handle, tnf_uint, flags, flags,
    856 	    tnf_opaque, msgp, msgp, tnf_opaque, retrans, retrans);
    857 
    858 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*msgp,*msgimplp))
    859 
    860 	/* check for null ibmf_handle and msgp */
    861 	if ((ibmf_handle == NULL) || (msgp == NULL)) {
    862 		(void) sprintf(errmsg,
    863 		    "invalid argument, NULL pointer argument");
    864 		error = B_TRUE;
    865 		status = IBMF_INVALID_ARG;
    866 		goto bail;
    867 	}
    868 
    869 	/* validate ibmf_handle */
    870 	if (ibmf_i_is_ibmf_handle_valid(ibmf_handle) != IBMF_SUCCESS) {
    871 		(void) sprintf(errmsg, "bad ibmf registration handle");
    872 		error = B_TRUE;
    873 		status = IBMF_BAD_HANDLE;
    874 		goto bail;
    875 	}
    876 
    877 	/* validate ibmf_qp_handle */
    878 	if (ibmf_i_is_qp_handle_valid(ibmf_handle, ibmf_qp_handle) !=
    879 	    IBMF_SUCCESS) {
    880 		(void) sprintf(errmsg, "bad qp handle");
    881 		error = B_TRUE;
    882 		status = IBMF_BAD_QP_HANDLE;
    883 		goto bail;
    884 	}
    885 
    886 	clientp = (ibmf_client_t *)ibmf_handle;
    887 
    888 	/* check signature */
    889 	if (IBMF_VERIFY_CLIENT_SIGNATURE(clientp) == B_FALSE) {
    890 		(void) sprintf(errmsg, "bad signature");
    891 		error = B_TRUE;
    892 		status = IBMF_BAD_HANDLE;
    893 		goto bail;
    894 	}
    895 
    896 	/*
    897 	 * Check the validity of the pkey and qkey in the posted packet
    898 	 * For special QPs do the check for QP1 only
    899 	 * For the alternate qps, the pkey and qkey should match the
    900 	 * pkey and qkey maintained in the ibmf cached qp context
    901 	 */
    902 	if ((ibmf_qp_handle == IBMF_QP_HANDLE_DEFAULT) &&
    903 	    ((clientp->ic_client_info.client_class != SUBN_AGENT) &&
    904 	    (clientp->ic_client_info.client_class != SUBN_MANAGER))) {
    905 
    906 		if ((msgp->im_local_addr.ia_p_key != IBMF_P_KEY_DEF_FULL) &&
    907 		    (msgp->im_local_addr.ia_p_key != IBMF_P_KEY_DEF_LIMITED)) {
    908 			(void) sprintf(errmsg,
    909 			    "PKey in packet not default PKey");
    910 			error = B_TRUE;
    911 			status = IBMF_BAD_QP_HANDLE;
    912 			goto bail;
    913 		}
    914 
    915 		if (msgp->im_local_addr.ia_q_key != IBMF_MGMT_Q_KEY) {
    916 			(void) sprintf(errmsg, "QKey in packet not Mgt QKey");
    917 			error = B_TRUE;
    918 			status = IBMF_BAD_QP_HANDLE;
    919 			goto bail;
    920 		}
    921 	} else if (ibmf_qp_handle != IBMF_QP_HANDLE_DEFAULT) {
    922 		ibmf_alt_qp_t *qpp = (ibmf_alt_qp_t *)ibmf_qp_handle;
    923 
    924 		/* alternate QP context */
    925 
    926 		mutex_enter(&qpp->isq_mutex);
    927 
    928 		if (msgp->im_local_addr.ia_p_key != qpp->isq_pkey) {
    929 			mutex_exit(&qpp->isq_mutex);
    930 			(void) sprintf(errmsg, "PKey in packet does not match "
    931 			    "PKey in the QP context");
    932 			error = B_TRUE;
    933 			status = IBMF_BAD_QP_HANDLE;
    934 			goto bail;
    935 		}
    936 
    937 		if (msgp->im_local_addr.ia_q_key != qpp->isq_qkey) {
    938 			mutex_exit(&qpp->isq_mutex);
    939 			(void) sprintf(errmsg, "QKey in packet does not match "
    940 			    "QKey in the QP context");
    941 			error = B_TRUE;
    942 			status = IBMF_BAD_QP_HANDLE;
    943 			goto bail;
    944 		}
    945 
    946 		mutex_exit(&qpp->isq_mutex);
    947 	}
    948 
    949 	msgimplp = (ibmf_msg_impl_t *)msgp;
    950 
    951 	ASSERT(msgimplp->im_client != NULL);
    952 	ASSERT(msgimplp->im_client == clientp);
    953 
    954 	msgimplp->im_transp_op_flags = flags;
    955 
    956 	mutex_enter(&msgimplp->im_mutex);
    957 
    958 	if (ibmf_qp_handle == IBMF_QP_HANDLE_DEFAULT) {
    959 		if (msgimplp->im_msgbufs_send.im_bufs_mad_hdr == NULL) {
    960 			mutex_exit(&msgimplp->im_mutex);
    961 			(void) sprintf(errmsg, "Send buffer MAD header data "
    962 			    "not provided for special QP");
    963 			error = B_TRUE;
    964 			status = IBMF_BAD_SIZE;
    965 			goto bail;
    966 		}
    967 	} else {
    968 		ibmf_alt_qp_t *qpp = (ibmf_alt_qp_t *)ibmf_qp_handle;
    969 
    970 		mutex_enter(&qpp->isq_mutex);
    971 
    972 		if (((qpp->isq_flags & IBMF_RAW_ONLY) == 0) &&
    973 		    (msgimplp->im_msgbufs_send.im_bufs_mad_hdr == NULL)) {
    974 			mutex_exit(&qpp->isq_mutex);
    975 			mutex_exit(&msgimplp->im_mutex);
    976 			(void) sprintf(errmsg, "Send buffer MAD header data "
    977 			    "not provided for alternate QP");
    978 			error = B_TRUE;
    979 			status = IBMF_BAD_SIZE;
    980 			goto bail;
    981 		}
    982 		mutex_exit(&qpp->isq_mutex);
    983 	}
    984 
    985 	/* check if client has freed the message by calling ibmf_free_msg() */
    986 	if (msgimplp->im_flags & IBMF_MSG_FLAGS_FREE) {
    987 		mutex_exit(&msgimplp->im_mutex);
    988 		(void) sprintf(errmsg, "Message is being freed");
    989 		error = B_TRUE;
    990 		status = IBMF_BUSY;
    991 		goto bail;
    992 	}
    993 
    994 	/*
    995 	 * check if the message is already in use in an
    996 	 * ibmf_msg_transport() call
    997 	 */
    998 	if (msgimplp->im_flags & IBMF_MSG_FLAGS_BUSY) {
    999 		mutex_exit(&msgimplp->im_mutex);
   1000 		(void) sprintf(errmsg,
   1001 		    "Message is being processed by an other thread");
   1002 		error = B_TRUE;
   1003 		status = IBMF_BUSY;
   1004 		goto bail;
   1005 	}
   1006 
   1007 	msgimplp->im_flags = IBMF_MSG_FLAGS_BUSY;
   1008 
   1009 	mutex_exit(&msgimplp->im_mutex);
   1010 
   1011 	/* check for the Directed Route SMP loopback case */
   1012 	loopback = B_FALSE;
   1013 	dr_hdr = (sm_dr_mad_hdr_t *)msgimplp->im_msgbufs_send.im_bufs_mad_hdr;
   1014 	if ((dr_hdr->MgmtClass == MAD_MGMT_CLASS_SUBN_DIRECT_ROUTE) &&
   1015 	    (dr_hdr->HopCount == 0)) {
   1016 		loopback = B_TRUE;
   1017 	}
   1018 
   1019 	/* check for and perform DR loopback on tavor */
   1020 	status = ibmf_i_check_for_loopback(msgimplp, msg_cb, msg_cb_args,
   1021 	    retrans, &loopback);
   1022 	if (status != IBMF_SUCCESS) {
   1023 		(void) sprintf(errmsg, "dr_loopback_check failed");
   1024 		error = B_TRUE;
   1025 		mutex_enter(&msgimplp->im_mutex);
   1026 		msgimplp->im_flags &= ~IBMF_MSG_FLAGS_BUSY;
   1027 		mutex_exit(&msgimplp->im_mutex);
   1028 		goto bail;
   1029 	}
   1030 	if (loopback == B_TRUE) {
   1031 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
   1032 		    ibmf_msg_transport_end, IBMF_TNF_TRACE, "",
   1033 		    "ibmf_msg_transport() exit, dr_loopback ok\n");
   1034 		return (IBMF_SUCCESS);
   1035 	}
   1036 
   1037 	if (msg_cb == NULL) {
   1038 		blocking = B_TRUE;
   1039 	} else {
   1040 		blocking = B_FALSE;
   1041 	}
   1042 
   1043 	/* initialize the message context */
   1044 	ibmf_i_init_msg(msgimplp, msg_cb, msg_cb_args, retrans, blocking);
   1045 
   1046 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*msgp,*msgimplp))
   1047 
   1048 	/* call the internal function to transport the message */
   1049 	status = ibmf_i_msg_transport(clientp, ibmf_qp_handle, msgimplp,
   1050 	    blocking);
   1051 	if (status != IBMF_SUCCESS) {
   1052 		(void) sprintf(errmsg, "message transport failed");
   1053 		error = B_TRUE;
   1054 		mutex_enter(&msgimplp->im_mutex);
   1055 		msgimplp->im_flags &= ~IBMF_MSG_FLAGS_BUSY;
   1056 		mutex_exit(&msgimplp->im_mutex);
   1057 		goto bail;
   1058 	}
   1059 
   1060 bail:
   1061 	if (error) {
   1062 		IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
   1063 		    ibmf_msg_transport_err, IBMF_TNF_ERROR, "",
   1064 		    "ibmf_msg_transport(): %s\n", tnf_string, msg, errmsg);
   1065 	}
   1066 
   1067 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_msg_transport_end,
   1068 	    IBMF_TNF_TRACE, "", "ibmf_msg_transport() exit\n");
   1069 
   1070 	return (status);
   1071 }
   1072 
   1073 
   1074 /* ARGSUSED */
   1075 int
   1076 ibmf_alloc_qp(ibmf_handle_t ibmf_handle, ib_pkey_t p_key, ib_qkey_t q_key,
   1077     uint_t flags, ibmf_qp_handle_t *ibmf_qp_handlep)
   1078 {
   1079 	ibmf_client_t	*clientp = (ibmf_client_t *)ibmf_handle;
   1080 	uint_t		alloc_flags;
   1081 	ibmf_alt_qp_t	*qp_ctx;
   1082 	boolean_t	error = B_FALSE;
   1083 	int		status = IBMF_SUCCESS;
   1084 	char		errmsg[128];
   1085 
   1086 	IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_alloc_qp_start,
   1087 	    IBMF_TNF_TRACE, "", "ibmf_alloc_qp() enter, "
   1088 	    "ibmf_handlep = %p, p_key = 0x%x, q_key = 0x%x\n",
   1089 	    tnf_opaque, ibmf_handle, ibmf_handle,
   1090 	    tnf_uint, pkey, p_key, tnf_uint, qkey, q_key);
   1091 
   1092 	/* check for null ibmf_handle and ibmf_qp_handle */
   1093 	if ((ibmf_handle == NULL) || (ibmf_qp_handlep == NULL)) {
   1094 		(void) sprintf(errmsg,
   1095 		    "invalid argument, NULL pointer argument");
   1096 		error = B_TRUE;
   1097 		status = IBMF_INVALID_ARG;
   1098 		goto bail;
   1099 	}
   1100 
   1101 	/* validate ibmf_handle */
   1102 	if (ibmf_i_is_ibmf_handle_valid(ibmf_handle) != IBMF_SUCCESS) {
   1103 		(void) sprintf(errmsg, "bad ibmf registration handle");
   1104 		error = B_TRUE;
   1105 		status = IBMF_BAD_HANDLE;
   1106 		goto bail;
   1107 	}
   1108 
   1109 	/* check signature */
   1110 	if (IBMF_VERIFY_CLIENT_SIGNATURE(clientp) == B_FALSE) {
   1111 		(void) sprintf(errmsg, "bad signature");
   1112 		error = B_TRUE;
   1113 		status = IBMF_BAD_HANDLE;
   1114 		goto bail;
   1115 	}
   1116 
   1117 	/* validate PKey */
   1118 	if (IBMF_INVALID_PKEY(p_key)) {
   1119 		(void) sprintf(errmsg, "invalid value in p_key argument");
   1120 		error = B_TRUE;
   1121 		status = IBMF_INVALID_ARG;
   1122 		goto bail;
   1123 	}
   1124 
   1125 	if (((flags & IBMF_ALT_QP_MAD_NO_RMPP) == 0) &&
   1126 	    ((flags & IBMF_ALT_QP_MAD_RMPP) == 0) &&
   1127 	    ((flags & IBMF_ALT_QP_RAW_ONLY) == 0)) {
   1128 		(void) sprintf(errmsg, "invalid flags combination");
   1129 		error = B_TRUE;
   1130 		status = IBMF_BAD_FLAGS;
   1131 		goto bail;
   1132 	}
   1133 
   1134 	alloc_flags = IBMF_ALLOC_SLEEP;
   1135 
   1136 	/* call the internal function to allocate the alternate QP context */
   1137 	status = ibmf_i_alloc_qp(clientp, p_key, q_key, alloc_flags,
   1138 	    ibmf_qp_handlep);
   1139 	if (status != IBMF_SUCCESS) {
   1140 		mutex_enter(&clientp->ic_kstat_mutex);
   1141 		IBMF_ADD32_KSTATS(clientp, alt_qp_allocs_failed, 1);
   1142 		mutex_exit(&clientp->ic_kstat_mutex);
   1143 		(void) sprintf(errmsg, "unable to allocate QP");
   1144 		error = B_TRUE;
   1145 		status = IBMF_NO_RESOURCES;
   1146 		goto bail;
   1147 	}
   1148 
   1149 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*qp_ctx))
   1150 
   1151 	qp_ctx = (ibmf_alt_qp_t *)*ibmf_qp_handlep;
   1152 
   1153 	/* initialize the alternate qp context */
   1154 	if (flags & IBMF_ALT_QP_MAD_NO_RMPP)
   1155 		qp_ctx->isq_flags |= IBMF_MAD_ONLY;
   1156 
   1157 	if (flags & IBMF_ALT_QP_RAW_ONLY)
   1158 		qp_ctx->isq_flags |= IBMF_RAW_ONLY;
   1159 
   1160 	if (flags & IBMF_ALT_QP_MAD_RMPP)
   1161 		qp_ctx->isq_supports_rmpp = B_TRUE;
   1162 	else
   1163 		qp_ctx->isq_supports_rmpp = B_FALSE;
   1164 
   1165 bail:
   1166 	if (error) {
   1167 		IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
   1168 		    ibmf_alloc_qp_err, IBMF_TNF_ERROR, "",
   1169 		    "ibmf_alloc_qp(): %s\n", tnf_string, msg, errmsg);
   1170 	}
   1171 
   1172 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_alloc_qp_end,
   1173 	    IBMF_TNF_TRACE, "", "ibmf_alloc_qp() exit\n");
   1174 
   1175 
   1176 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*qp_ctx))
   1177 
   1178 	return (status);
   1179 }
   1180 
   1181 
   1182 /* ARGSUSED */
   1183 int
   1184 ibmf_query_qp(ibmf_handle_t ibmf_handle, ibmf_qp_handle_t ibmf_qp_handle,
   1185     uint_t *qp_num, ib_pkey_t *p_key, ib_qkey_t *q_key, uint8_t *portnum,
   1186     uint_t flags)
   1187 {
   1188 	ibmf_client_t	*clientp = (ibmf_client_t *)ibmf_handle;
   1189 	ibmf_alt_qp_t *qp_ctx = (ibmf_alt_qp_t *)ibmf_qp_handle;
   1190 	uint_t		query_flags;
   1191 	boolean_t	error = B_FALSE;
   1192 	int		status = IBMF_SUCCESS;
   1193 	char		errmsg[128];
   1194 
   1195 	IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_query_qp_start,
   1196 	    IBMF_TNF_TRACE, "", "ibmf_query_qp() enter, "
   1197 	    "ibmf_handlep = %p, ibmf_qp_handle = %p\n",
   1198 	    tnf_opaque, ibmf_handle, ibmf_handle,
   1199 	    tnf_opaque, ibmf_qp_handle, ibmf_qp_handle);
   1200 
   1201 	/* check for null args */
   1202 	if ((ibmf_handle == NULL) || (ibmf_qp_handle == NULL) ||
   1203 	    (qp_num == NULL) || (p_key == NULL) || (q_key == NULL) ||
   1204 	    (portnum == NULL)) {
   1205 		(void) sprintf(errmsg,
   1206 		    "invalid argument, NULL pointer argument");
   1207 		error = B_TRUE;
   1208 		status = IBMF_INVALID_ARG;
   1209 		goto bail;
   1210 	}
   1211 
   1212 	/* validate ibmf_handle */
   1213 	if (ibmf_i_is_ibmf_handle_valid(ibmf_handle) != IBMF_SUCCESS) {
   1214 		(void) sprintf(errmsg, "bad ibmf registration handle");
   1215 		error = B_TRUE;
   1216 		status = IBMF_BAD_HANDLE;
   1217 		goto bail;
   1218 	}
   1219 
   1220 	/* validate ibmf_qp_handle */
   1221 	if (ibmf_i_is_qp_handle_valid(ibmf_handle, ibmf_qp_handle) !=
   1222 	    IBMF_SUCCESS) {
   1223 		(void) sprintf(errmsg, "bad qp handle");
   1224 		error = B_TRUE;
   1225 		status = IBMF_BAD_QP_HANDLE;
   1226 		goto bail;
   1227 	}
   1228 
   1229 	/* validate ibmf_qp_handle */
   1230 	if (ibmf_qp_handle == IBMF_QP_HANDLE_DEFAULT) {
   1231 		(void) sprintf(errmsg, "bad qp handle (default)");
   1232 		error = B_TRUE;
   1233 		status = IBMF_BAD_QP_HANDLE;
   1234 		goto bail;
   1235 	}
   1236 
   1237 	/* check signature */
   1238 	if (IBMF_VERIFY_CLIENT_SIGNATURE(clientp) == B_FALSE) {
   1239 		(void) sprintf(errmsg, "bad client signature");
   1240 		error = B_TRUE;
   1241 		status = IBMF_BAD_HANDLE;
   1242 		goto bail;
   1243 	}
   1244 
   1245 	/* validate client context handle */
   1246 	if (qp_ctx->isq_client_hdl != clientp) {
   1247 		(void) sprintf(errmsg, "bad QP handle");
   1248 		error = B_TRUE;
   1249 		status = IBMF_BAD_QP_HANDLE;
   1250 		goto bail;
   1251 	}
   1252 
   1253 	query_flags = IBMF_ALLOC_NOSLEEP;
   1254 
   1255 	/* call the internal function to query the alternate qp */
   1256 	status = ibmf_i_query_qp(ibmf_qp_handle, query_flags, qp_num, p_key,
   1257 	    q_key, portnum);
   1258 	if (status != IBMF_SUCCESS) {
   1259 		(void) sprintf(errmsg, "unable to query QP");
   1260 		error = B_TRUE;
   1261 		goto bail;
   1262 	}
   1263 
   1264 bail:
   1265 	if (error) {
   1266 		IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
   1267 		    ibmf_query_qp_err, IBMF_TNF_ERROR, "",
   1268 		    "ibmf_query_qp(): %s\n", tnf_string, msg, errmsg);
   1269 	}
   1270 
   1271 	IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_query_qp_end,
   1272 	    IBMF_TNF_TRACE, "", "ibmf_query_qp() exit, qp = %d, "
   1273 	    "pkey = 0x%x, qkey = 0x%x\n", tnf_uint, qp_num, *qp_num,
   1274 	    tnf_uint, pkey, *p_key, tnf_uint, qkey, *q_key);
   1275 
   1276 	return (status);
   1277 }
   1278 
   1279 
   1280 /* ARGSUSED */
   1281 int
   1282 ibmf_modify_qp(ibmf_handle_t ibmf_handle, ibmf_qp_handle_t ibmf_qp_handle,
   1283     ib_pkey_t p_key, ib_qkey_t q_key, uint_t flags)
   1284 {
   1285 	ibmf_client_t	*clientp = (ibmf_client_t *)ibmf_handle;
   1286 	ibmf_alt_qp_t *qp_ctx = (ibmf_alt_qp_t *)ibmf_qp_handle;
   1287 	uint_t		modify_flags;
   1288 	boolean_t	error = B_FALSE;
   1289 	int		status = IBMF_SUCCESS;
   1290 	char		errmsg[128];
   1291 
   1292 	IBMF_TRACE_4(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_modify_qp_start,
   1293 	    IBMF_TNF_TRACE, "", "ibmf_modify_qp() enter, "
   1294 	    "ibmf_handlep = %p, ibmf_qp_handle = %p, pkey = 0x%x, "
   1295 	    "qkey = 0x%x\n", tnf_opaque, ibmf_handle, ibmf_handle,
   1296 	    tnf_opaque, ibmf_qp_handle, ibmf_qp_handle,
   1297 	    tnf_uint, p_key, p_key, tnf_uint, q_key, q_key);
   1298 
   1299 	/* check for null args */
   1300 	if ((ibmf_handle == NULL) || (ibmf_qp_handle == NULL)) {
   1301 		(void) sprintf(errmsg,
   1302 		    "invalid argument, NULL pointer argument");
   1303 		error = B_TRUE;
   1304 		status = IBMF_INVALID_ARG;
   1305 		goto bail;
   1306 	}
   1307 
   1308 	/* validate ibmf_handle */
   1309 	if (ibmf_i_is_ibmf_handle_valid(ibmf_handle) != IBMF_SUCCESS) {
   1310 		(void) sprintf(errmsg, "bad ibmf registration handle");
   1311 		error = B_TRUE;
   1312 		status = IBMF_BAD_HANDLE;
   1313 		goto bail;
   1314 	}
   1315 
   1316 	/* validate ibmf_qp_handle */
   1317 	if (ibmf_i_is_qp_handle_valid(ibmf_handle, ibmf_qp_handle) !=
   1318 	    IBMF_SUCCESS) {
   1319 		(void) sprintf(errmsg, "bad qp handle");
   1320 		error = B_TRUE;
   1321 		status = IBMF_BAD_QP_HANDLE;
   1322 		goto bail;
   1323 	}
   1324 
   1325 	/* validate ibmf_qp_handle */
   1326 	if (ibmf_qp_handle == IBMF_QP_HANDLE_DEFAULT) {
   1327 		(void) sprintf(errmsg, "bad qp handle (default)");
   1328 		error = B_TRUE;
   1329 		status = IBMF_BAD_QP_HANDLE;
   1330 		goto bail;
   1331 	}
   1332 
   1333 	/* check signature */
   1334 	if (IBMF_VERIFY_CLIENT_SIGNATURE(clientp) == B_FALSE) {
   1335 		(void) sprintf(errmsg, "bad client signature");
   1336 		error = B_TRUE;
   1337 		status = IBMF_BAD_HANDLE;
   1338 		goto bail;
   1339 	}
   1340 
   1341 	/* validate PKey */
   1342 	if (IBMF_INVALID_PKEY(p_key)) {
   1343 		(void) sprintf(errmsg, "invalid value in p_key argument");
   1344 		error = B_TRUE;
   1345 		status = IBMF_INVALID_ARG;
   1346 		goto bail;
   1347 	}
   1348 
   1349 	if (qp_ctx->isq_client_hdl != clientp) {
   1350 		(void) sprintf(errmsg, "bad QP handle");
   1351 		error = B_TRUE;
   1352 		status = IBMF_BAD_QP_HANDLE;
   1353 		goto bail;
   1354 	}
   1355 
   1356 	modify_flags = IBMF_ALLOC_SLEEP;
   1357 
   1358 	/* call the internal function to modify the qp */
   1359 	status = ibmf_i_modify_qp(ibmf_qp_handle, p_key, q_key, modify_flags);
   1360 	if (status != IBMF_SUCCESS) {
   1361 		(void) sprintf(errmsg, "unable to modify QP");
   1362 		error = B_TRUE;
   1363 		goto bail;
   1364 	}
   1365 
   1366 bail:
   1367 	if (error) {
   1368 		IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
   1369 		    ibmf_modify_qp_err, IBMF_TNF_ERROR, "",
   1370 		    "ibmf_modify_qp(): %s\n", tnf_string, msg, errmsg);
   1371 	}
   1372 
   1373 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_modify_qp_end,
   1374 	    IBMF_TNF_TRACE, "", "ibmf_modify_qp() exit\n");
   1375 
   1376 	return (status);
   1377 }
   1378 
   1379 /* ARGSUSED */
   1380 int
   1381 ibmf_free_qp(ibmf_handle_t ibmf_handle, ibmf_qp_handle_t *ibmf_qp_handle,
   1382     uint_t flags)
   1383 {
   1384 	ibmf_client_t	*clientp = (ibmf_client_t *)ibmf_handle;
   1385 	ibmf_alt_qp_t	*qp_ctx = (ibmf_alt_qp_t *)*ibmf_qp_handle;
   1386 	uint_t		modify_flags;
   1387 	boolean_t	error = B_FALSE;
   1388 	int		status = IBMF_SUCCESS;
   1389 	char		errmsg[128];
   1390 
   1391 	IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_free_qp_start,
   1392 	    IBMF_TNF_TRACE, "", "ibmf_free_qp() enter, "
   1393 	    "ibmf_handlep = %p, ibmf_qp_handle = %p\n",
   1394 	    tnf_opaque, ibmf_handle, ibmf_handle,
   1395 	    tnf_opaque, ibmf_qp_handle, *ibmf_qp_handle);
   1396 
   1397 	/* check for null args */
   1398 	if ((ibmf_handle == NULL) || (ibmf_qp_handle == NULL)) {
   1399 		(void) sprintf(errmsg,
   1400 		    "invalid argument, NULL pointer argument");
   1401 		error = B_TRUE;
   1402 		status = IBMF_INVALID_ARG;
   1403 		goto bail;
   1404 	}
   1405 
   1406 	/* validate ibmf_handle */
   1407 	if (ibmf_i_is_ibmf_handle_valid(ibmf_handle) != IBMF_SUCCESS) {
   1408 		(void) sprintf(errmsg, "bad ibmf registration handle");
   1409 		error = B_TRUE;
   1410 		status = IBMF_BAD_HANDLE;
   1411 		goto bail;
   1412 	}
   1413 
   1414 	/* validate ibmf_qp_handle */
   1415 	if (ibmf_i_is_qp_handle_valid(ibmf_handle, *ibmf_qp_handle) !=
   1416 	    IBMF_SUCCESS) {
   1417 		(void) sprintf(errmsg, "bad qp handle");
   1418 		error = B_TRUE;
   1419 		status = IBMF_BAD_QP_HANDLE;
   1420 		goto bail;
   1421 	}
   1422 
   1423 	/* validate ibmf_qp_handle */
   1424 	if (*ibmf_qp_handle == IBMF_QP_HANDLE_DEFAULT) {
   1425 		(void) sprintf(errmsg, "bad qp handle (default)");
   1426 		error = B_TRUE;
   1427 		status = IBMF_BAD_QP_HANDLE;
   1428 		goto bail;
   1429 	}
   1430 
   1431 	/* check signature */
   1432 	if (IBMF_VERIFY_CLIENT_SIGNATURE(clientp) == B_FALSE) {
   1433 		(void) sprintf(errmsg, "bad client signature");
   1434 		error = B_TRUE;
   1435 		status = IBMF_BAD_HANDLE;
   1436 		goto bail;
   1437 	}
   1438 
   1439 	/* validate client context handle */
   1440 	if (qp_ctx->isq_client_hdl != clientp) {
   1441 		(void) sprintf(errmsg, "bad QP handle");
   1442 		error = B_TRUE;
   1443 		status = IBMF_BAD_QP_HANDLE;
   1444 		goto bail;
   1445 	}
   1446 
   1447 	mutex_enter(&qp_ctx->isq_mutex);
   1448 
   1449 	if (qp_ctx->isq_recv_cb != NULL) {
   1450 		mutex_exit(&qp_ctx->isq_mutex);
   1451 		(void) sprintf(errmsg, "QP busy, callback active");
   1452 		error = B_TRUE;
   1453 		status = IBMF_BUSY;
   1454 		goto bail;
   1455 	}
   1456 
   1457 	mutex_exit(&qp_ctx->isq_mutex);
   1458 
   1459 	modify_flags = IBMF_ALLOC_SLEEP;
   1460 
   1461 	status = ibmf_i_free_qp(*ibmf_qp_handle, modify_flags);
   1462 	if (status != IBMF_SUCCESS) {
   1463 		(void) sprintf(errmsg, "unable to free QP");
   1464 		error = B_TRUE;
   1465 		goto bail;
   1466 	}
   1467 
   1468 	*ibmf_qp_handle = NULL;
   1469 
   1470 bail:
   1471 	if (error) {
   1472 		IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
   1473 		    ibmf_free_qp_err, IBMF_TNF_ERROR, "",
   1474 		    "ibmf_free_qp(): %s\n", tnf_string, msg, errmsg);
   1475 	}
   1476 
   1477 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_free_qp_end,
   1478 	    IBMF_TNF_TRACE, "", "ibmf_free_qp() exit\n");
   1479 
   1480 	return (status);
   1481 }
   1482