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