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 /*
23 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
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
ibmf_register(ibmf_register_info_t * client_infop,uint_t ibmf_version,uint_t flags,ibmf_async_event_cb_t client_cb,void * client_cb_args,ibmf_handle_t * ibmf_handlep,ibmf_impl_caps_t * ibmf_impl_features)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
ibmf_unregister(ibmf_handle_t * ibmf_handlep,uint_t flags)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
ibmf_setup_async_cb(ibmf_handle_t ibmf_handle,ibmf_qp_handle_t ibmf_qp_handle,ibmf_msg_cb_t async_msg_cb,void * async_msg_cb_args,uint_t flags)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
ibmf_tear_down_async_cb(ibmf_handle_t ibmf_handle,ibmf_qp_handle_t ibmf_qp_handle,uint_t flags)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
ibmf_alloc_msg(ibmf_handle_t ibmf_handle,int flag,ibmf_msg_t ** ibmf_msgpp)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
ibmf_free_msg(ibmf_handle_t ibmf_handle,ibmf_msg_t ** ibmf_msgpp)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
ibmf_msg_transport(ibmf_handle_t ibmf_handle,ibmf_qp_handle_t ibmf_qp_handle,ibmf_msg_t * msgp,ibmf_retrans_t * retrans,ibmf_msg_cb_t msg_cb,void * msg_cb_args,uint_t flags)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_ADM_AGENT) &&
905 (clientp->ic_client_info.client_class != SUBN_MANAGER))) {
906
907 if ((msgp->im_local_addr.ia_p_key != IBMF_P_KEY_DEF_FULL) &&
908 (msgp->im_local_addr.ia_p_key != IBMF_P_KEY_DEF_LIMITED)) {
909 (void) sprintf(errmsg,
910 "PKey in packet not default PKey");
911 error = B_TRUE;
912 status = IBMF_BAD_QP_HANDLE;
913 goto bail;
914 }
915
916 if (msgp->im_local_addr.ia_q_key != IBMF_MGMT_Q_KEY) {
917 (void) sprintf(errmsg, "QKey in packet not Mgt QKey");
918 error = B_TRUE;
919 status = IBMF_BAD_QP_HANDLE;
920 goto bail;
921 }
922 } else if (ibmf_qp_handle != IBMF_QP_HANDLE_DEFAULT) {
923 ibmf_alt_qp_t *qpp = (ibmf_alt_qp_t *)ibmf_qp_handle;
924
925 /* alternate QP context */
926
927 mutex_enter(&qpp->isq_mutex);
928
929 if (msgp->im_local_addr.ia_p_key != qpp->isq_pkey) {
930 mutex_exit(&qpp->isq_mutex);
931 (void) sprintf(errmsg, "PKey in packet does not match "
932 "PKey in the QP context");
933 error = B_TRUE;
934 status = IBMF_BAD_QP_HANDLE;
935 goto bail;
936 }
937
938 if (msgp->im_local_addr.ia_q_key != qpp->isq_qkey) {
939 mutex_exit(&qpp->isq_mutex);
940 (void) sprintf(errmsg, "QKey in packet does not match "
941 "QKey in the QP context");
942 error = B_TRUE;
943 status = IBMF_BAD_QP_HANDLE;
944 goto bail;
945 }
946
947 mutex_exit(&qpp->isq_mutex);
948 }
949
950 msgimplp = (ibmf_msg_impl_t *)msgp;
951
952 ASSERT(msgimplp->im_client != NULL);
953 ASSERT(msgimplp->im_client == clientp);
954
955 msgimplp->im_transp_op_flags = flags;
956
957 mutex_enter(&msgimplp->im_mutex);
958
959 if (ibmf_qp_handle == IBMF_QP_HANDLE_DEFAULT) {
960 if (msgimplp->im_msgbufs_send.im_bufs_mad_hdr == NULL) {
961 mutex_exit(&msgimplp->im_mutex);
962 (void) sprintf(errmsg, "Send buffer MAD header data "
963 "not provided for special QP");
964 error = B_TRUE;
965 status = IBMF_BAD_SIZE;
966 goto bail;
967 }
968 } else {
969 ibmf_alt_qp_t *qpp = (ibmf_alt_qp_t *)ibmf_qp_handle;
970
971 mutex_enter(&qpp->isq_mutex);
972
973 if (((qpp->isq_flags & IBMF_RAW_ONLY) == 0) &&
974 (msgimplp->im_msgbufs_send.im_bufs_mad_hdr == NULL)) {
975 mutex_exit(&qpp->isq_mutex);
976 mutex_exit(&msgimplp->im_mutex);
977 (void) sprintf(errmsg, "Send buffer MAD header data "
978 "not provided for alternate QP");
979 error = B_TRUE;
980 status = IBMF_BAD_SIZE;
981 goto bail;
982 }
983 mutex_exit(&qpp->isq_mutex);
984 }
985
986 /* check if client has freed the message by calling ibmf_free_msg() */
987 if (msgimplp->im_flags & IBMF_MSG_FLAGS_FREE) {
988 mutex_exit(&msgimplp->im_mutex);
989 (void) sprintf(errmsg, "Message is being freed");
990 error = B_TRUE;
991 status = IBMF_BUSY;
992 goto bail;
993 }
994
995 /*
996 * check if the message is already in use in an
997 * ibmf_msg_transport() call
998 */
999 if (msgimplp->im_flags & IBMF_MSG_FLAGS_BUSY) {
1000 mutex_exit(&msgimplp->im_mutex);
1001 (void) sprintf(errmsg,
1002 "Message is being processed by an other thread");
1003 error = B_TRUE;
1004 status = IBMF_BUSY;
1005 goto bail;
1006 }
1007
1008 msgimplp->im_flags = IBMF_MSG_FLAGS_BUSY;
1009
1010 mutex_exit(&msgimplp->im_mutex);
1011
1012 /* check for the Directed Route SMP loopback case */
1013 loopback = B_FALSE;
1014 dr_hdr = (sm_dr_mad_hdr_t *)msgimplp->im_msgbufs_send.im_bufs_mad_hdr;
1015 if ((dr_hdr->MgmtClass == MAD_MGMT_CLASS_SUBN_DIRECT_ROUTE) &&
1016 (dr_hdr->HopCount == 0)) {
1017 loopback = B_TRUE;
1018 }
1019
1020 /* check for and perform DR loopback on tavor */
1021 status = ibmf_i_check_for_loopback(msgimplp, msg_cb, msg_cb_args,
1022 retrans, &loopback);
1023 if (status != IBMF_SUCCESS) {
1024 (void) sprintf(errmsg, "dr_loopback_check failed");
1025 error = B_TRUE;
1026 mutex_enter(&msgimplp->im_mutex);
1027 msgimplp->im_flags &= ~IBMF_MSG_FLAGS_BUSY;
1028 mutex_exit(&msgimplp->im_mutex);
1029 goto bail;
1030 }
1031 if (loopback == B_TRUE) {
1032 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
1033 ibmf_msg_transport_end, IBMF_TNF_TRACE, "",
1034 "ibmf_msg_transport() exit, dr_loopback ok\n");
1035 return (IBMF_SUCCESS);
1036 }
1037
1038 if (msg_cb == NULL) {
1039 blocking = B_TRUE;
1040 } else {
1041 blocking = B_FALSE;
1042 }
1043
1044 /* initialize the message context */
1045 ibmf_i_init_msg(msgimplp, msg_cb, msg_cb_args, retrans, blocking);
1046
1047 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*msgp,*msgimplp))
1048
1049 /* call the internal function to transport the message */
1050 status = ibmf_i_msg_transport(clientp, ibmf_qp_handle, msgimplp,
1051 blocking);
1052 if (status != IBMF_SUCCESS) {
1053 (void) sprintf(errmsg, "message transport failed");
1054 error = B_TRUE;
1055 mutex_enter(&msgimplp->im_mutex);
1056 msgimplp->im_flags &= ~IBMF_MSG_FLAGS_BUSY;
1057 mutex_exit(&msgimplp->im_mutex);
1058 goto bail;
1059 }
1060
1061 bail:
1062 if (error) {
1063 IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
1064 ibmf_msg_transport_err, IBMF_TNF_ERROR, "",
1065 "ibmf_msg_transport(): %s\n", tnf_string, msg, errmsg);
1066 }
1067
1068 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_msg_transport_end,
1069 IBMF_TNF_TRACE, "", "ibmf_msg_transport() exit\n");
1070
1071 return (status);
1072 }
1073
1074
1075 /* ARGSUSED */
1076 int
ibmf_alloc_qp(ibmf_handle_t ibmf_handle,ib_pkey_t p_key,ib_qkey_t q_key,uint_t flags,ibmf_qp_handle_t * ibmf_qp_handlep)1077 ibmf_alloc_qp(ibmf_handle_t ibmf_handle, ib_pkey_t p_key, ib_qkey_t q_key,
1078 uint_t flags, ibmf_qp_handle_t *ibmf_qp_handlep)
1079 {
1080 ibmf_client_t *clientp = (ibmf_client_t *)ibmf_handle;
1081 uint_t alloc_flags;
1082 ibmf_alt_qp_t *qp_ctx;
1083 boolean_t error = B_FALSE;
1084 int status = IBMF_SUCCESS;
1085 char errmsg[128];
1086
1087 IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_alloc_qp_start,
1088 IBMF_TNF_TRACE, "", "ibmf_alloc_qp() enter, "
1089 "ibmf_handlep = %p, p_key = 0x%x, q_key = 0x%x\n",
1090 tnf_opaque, ibmf_handle, ibmf_handle,
1091 tnf_uint, pkey, p_key, tnf_uint, qkey, q_key);
1092
1093 /* check for null ibmf_handle and ibmf_qp_handle */
1094 if ((ibmf_handle == NULL) || (ibmf_qp_handlep == NULL)) {
1095 (void) sprintf(errmsg,
1096 "invalid argument, NULL pointer argument");
1097 error = B_TRUE;
1098 status = IBMF_INVALID_ARG;
1099 goto bail;
1100 }
1101
1102 /* validate ibmf_handle */
1103 if (ibmf_i_is_ibmf_handle_valid(ibmf_handle) != IBMF_SUCCESS) {
1104 (void) sprintf(errmsg, "bad ibmf registration handle");
1105 error = B_TRUE;
1106 status = IBMF_BAD_HANDLE;
1107 goto bail;
1108 }
1109
1110 /* check signature */
1111 if (IBMF_VERIFY_CLIENT_SIGNATURE(clientp) == B_FALSE) {
1112 (void) sprintf(errmsg, "bad signature");
1113 error = B_TRUE;
1114 status = IBMF_BAD_HANDLE;
1115 goto bail;
1116 }
1117
1118 /* validate PKey */
1119 if (IBMF_INVALID_PKEY(p_key)) {
1120 (void) sprintf(errmsg, "invalid value in p_key argument");
1121 error = B_TRUE;
1122 status = IBMF_INVALID_ARG;
1123 goto bail;
1124 }
1125
1126 if (((flags & IBMF_ALT_QP_MAD_NO_RMPP) == 0) &&
1127 ((flags & IBMF_ALT_QP_MAD_RMPP) == 0) &&
1128 ((flags & IBMF_ALT_QP_RAW_ONLY) == 0)) {
1129 (void) sprintf(errmsg, "invalid flags combination");
1130 error = B_TRUE;
1131 status = IBMF_BAD_FLAGS;
1132 goto bail;
1133 }
1134
1135 alloc_flags = IBMF_ALLOC_SLEEP;
1136
1137 /* call the internal function to allocate the alternate QP context */
1138 status = ibmf_i_alloc_qp(clientp, p_key, q_key, alloc_flags,
1139 ibmf_qp_handlep);
1140 if (status != IBMF_SUCCESS) {
1141 mutex_enter(&clientp->ic_kstat_mutex);
1142 IBMF_ADD32_KSTATS(clientp, alt_qp_allocs_failed, 1);
1143 mutex_exit(&clientp->ic_kstat_mutex);
1144 (void) sprintf(errmsg, "unable to allocate QP");
1145 error = B_TRUE;
1146 status = IBMF_NO_RESOURCES;
1147 goto bail;
1148 }
1149
1150 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*qp_ctx))
1151
1152 qp_ctx = (ibmf_alt_qp_t *)*ibmf_qp_handlep;
1153
1154 /* initialize the alternate qp context */
1155 if (flags & IBMF_ALT_QP_MAD_NO_RMPP)
1156 qp_ctx->isq_flags |= IBMF_MAD_ONLY;
1157
1158 if (flags & IBMF_ALT_QP_RAW_ONLY)
1159 qp_ctx->isq_flags |= IBMF_RAW_ONLY;
1160
1161 if (flags & IBMF_ALT_QP_MAD_RMPP)
1162 qp_ctx->isq_supports_rmpp = B_TRUE;
1163 else
1164 qp_ctx->isq_supports_rmpp = B_FALSE;
1165
1166 bail:
1167 if (error) {
1168 IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
1169 ibmf_alloc_qp_err, IBMF_TNF_ERROR, "",
1170 "ibmf_alloc_qp(): %s\n", tnf_string, msg, errmsg);
1171 }
1172
1173 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_alloc_qp_end,
1174 IBMF_TNF_TRACE, "", "ibmf_alloc_qp() exit\n");
1175
1176
1177 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*qp_ctx))
1178
1179 return (status);
1180 }
1181
1182
1183 /* ARGSUSED */
1184 int
ibmf_query_qp(ibmf_handle_t ibmf_handle,ibmf_qp_handle_t ibmf_qp_handle,uint_t * qp_num,ib_pkey_t * p_key,ib_qkey_t * q_key,uint8_t * portnum,uint_t flags)1185 ibmf_query_qp(ibmf_handle_t ibmf_handle, ibmf_qp_handle_t ibmf_qp_handle,
1186 uint_t *qp_num, ib_pkey_t *p_key, ib_qkey_t *q_key, uint8_t *portnum,
1187 uint_t flags)
1188 {
1189 ibmf_client_t *clientp = (ibmf_client_t *)ibmf_handle;
1190 ibmf_alt_qp_t *qp_ctx = (ibmf_alt_qp_t *)ibmf_qp_handle;
1191 uint_t query_flags;
1192 boolean_t error = B_FALSE;
1193 int status = IBMF_SUCCESS;
1194 char errmsg[128];
1195
1196 IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_query_qp_start,
1197 IBMF_TNF_TRACE, "", "ibmf_query_qp() enter, "
1198 "ibmf_handlep = %p, ibmf_qp_handle = %p\n",
1199 tnf_opaque, ibmf_handle, ibmf_handle,
1200 tnf_opaque, ibmf_qp_handle, ibmf_qp_handle);
1201
1202 /* check for null args */
1203 if ((ibmf_handle == NULL) || (ibmf_qp_handle == NULL) ||
1204 (qp_num == NULL) || (p_key == NULL) || (q_key == NULL) ||
1205 (portnum == NULL)) {
1206 (void) sprintf(errmsg,
1207 "invalid argument, NULL pointer argument");
1208 error = B_TRUE;
1209 status = IBMF_INVALID_ARG;
1210 goto bail;
1211 }
1212
1213 /* validate ibmf_handle */
1214 if (ibmf_i_is_ibmf_handle_valid(ibmf_handle) != IBMF_SUCCESS) {
1215 (void) sprintf(errmsg, "bad ibmf registration handle");
1216 error = B_TRUE;
1217 status = IBMF_BAD_HANDLE;
1218 goto bail;
1219 }
1220
1221 /* validate ibmf_qp_handle */
1222 if (ibmf_i_is_qp_handle_valid(ibmf_handle, ibmf_qp_handle) !=
1223 IBMF_SUCCESS) {
1224 (void) sprintf(errmsg, "bad qp handle");
1225 error = B_TRUE;
1226 status = IBMF_BAD_QP_HANDLE;
1227 goto bail;
1228 }
1229
1230 /* validate ibmf_qp_handle */
1231 if (ibmf_qp_handle == IBMF_QP_HANDLE_DEFAULT) {
1232 (void) sprintf(errmsg, "bad qp handle (default)");
1233 error = B_TRUE;
1234 status = IBMF_BAD_QP_HANDLE;
1235 goto bail;
1236 }
1237
1238 /* check signature */
1239 if (IBMF_VERIFY_CLIENT_SIGNATURE(clientp) == B_FALSE) {
1240 (void) sprintf(errmsg, "bad client signature");
1241 error = B_TRUE;
1242 status = IBMF_BAD_HANDLE;
1243 goto bail;
1244 }
1245
1246 /* validate client context handle */
1247 if (qp_ctx->isq_client_hdl != clientp) {
1248 (void) sprintf(errmsg, "bad QP handle");
1249 error = B_TRUE;
1250 status = IBMF_BAD_QP_HANDLE;
1251 goto bail;
1252 }
1253
1254 query_flags = IBMF_ALLOC_NOSLEEP;
1255
1256 /* call the internal function to query the alternate qp */
1257 status = ibmf_i_query_qp(ibmf_qp_handle, query_flags, qp_num, p_key,
1258 q_key, portnum);
1259 if (status != IBMF_SUCCESS) {
1260 (void) sprintf(errmsg, "unable to query QP");
1261 error = B_TRUE;
1262 goto bail;
1263 }
1264
1265 bail:
1266 if (error) {
1267 IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
1268 ibmf_query_qp_err, IBMF_TNF_ERROR, "",
1269 "ibmf_query_qp(): %s\n", tnf_string, msg, errmsg);
1270 }
1271
1272 IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_query_qp_end,
1273 IBMF_TNF_TRACE, "", "ibmf_query_qp() exit, qp = %d, "
1274 "pkey = 0x%x, qkey = 0x%x\n", tnf_uint, qp_num, *qp_num,
1275 tnf_uint, pkey, *p_key, tnf_uint, qkey, *q_key);
1276
1277 return (status);
1278 }
1279
1280
1281 /* ARGSUSED */
1282 int
ibmf_modify_qp(ibmf_handle_t ibmf_handle,ibmf_qp_handle_t ibmf_qp_handle,ib_pkey_t p_key,ib_qkey_t q_key,uint_t flags)1283 ibmf_modify_qp(ibmf_handle_t ibmf_handle, ibmf_qp_handle_t ibmf_qp_handle,
1284 ib_pkey_t p_key, ib_qkey_t q_key, uint_t flags)
1285 {
1286 ibmf_client_t *clientp = (ibmf_client_t *)ibmf_handle;
1287 ibmf_alt_qp_t *qp_ctx = (ibmf_alt_qp_t *)ibmf_qp_handle;
1288 uint_t modify_flags;
1289 boolean_t error = B_FALSE;
1290 int status = IBMF_SUCCESS;
1291 char errmsg[128];
1292
1293 IBMF_TRACE_4(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_modify_qp_start,
1294 IBMF_TNF_TRACE, "", "ibmf_modify_qp() enter, "
1295 "ibmf_handlep = %p, ibmf_qp_handle = %p, pkey = 0x%x, "
1296 "qkey = 0x%x\n", tnf_opaque, ibmf_handle, ibmf_handle,
1297 tnf_opaque, ibmf_qp_handle, ibmf_qp_handle,
1298 tnf_uint, p_key, p_key, tnf_uint, q_key, q_key);
1299
1300 /* check for null args */
1301 if ((ibmf_handle == NULL) || (ibmf_qp_handle == NULL)) {
1302 (void) sprintf(errmsg,
1303 "invalid argument, NULL pointer argument");
1304 error = B_TRUE;
1305 status = IBMF_INVALID_ARG;
1306 goto bail;
1307 }
1308
1309 /* validate ibmf_handle */
1310 if (ibmf_i_is_ibmf_handle_valid(ibmf_handle) != IBMF_SUCCESS) {
1311 (void) sprintf(errmsg, "bad ibmf registration handle");
1312 error = B_TRUE;
1313 status = IBMF_BAD_HANDLE;
1314 goto bail;
1315 }
1316
1317 /* validate ibmf_qp_handle */
1318 if (ibmf_i_is_qp_handle_valid(ibmf_handle, ibmf_qp_handle) !=
1319 IBMF_SUCCESS) {
1320 (void) sprintf(errmsg, "bad qp handle");
1321 error = B_TRUE;
1322 status = IBMF_BAD_QP_HANDLE;
1323 goto bail;
1324 }
1325
1326 /* validate ibmf_qp_handle */
1327 if (ibmf_qp_handle == IBMF_QP_HANDLE_DEFAULT) {
1328 (void) sprintf(errmsg, "bad qp handle (default)");
1329 error = B_TRUE;
1330 status = IBMF_BAD_QP_HANDLE;
1331 goto bail;
1332 }
1333
1334 /* check signature */
1335 if (IBMF_VERIFY_CLIENT_SIGNATURE(clientp) == B_FALSE) {
1336 (void) sprintf(errmsg, "bad client signature");
1337 error = B_TRUE;
1338 status = IBMF_BAD_HANDLE;
1339 goto bail;
1340 }
1341
1342 /* validate PKey */
1343 if (IBMF_INVALID_PKEY(p_key)) {
1344 (void) sprintf(errmsg, "invalid value in p_key argument");
1345 error = B_TRUE;
1346 status = IBMF_INVALID_ARG;
1347 goto bail;
1348 }
1349
1350 if (qp_ctx->isq_client_hdl != clientp) {
1351 (void) sprintf(errmsg, "bad QP handle");
1352 error = B_TRUE;
1353 status = IBMF_BAD_QP_HANDLE;
1354 goto bail;
1355 }
1356
1357 modify_flags = IBMF_ALLOC_SLEEP;
1358
1359 /* call the internal function to modify the qp */
1360 status = ibmf_i_modify_qp(ibmf_qp_handle, p_key, q_key, modify_flags);
1361 if (status != IBMF_SUCCESS) {
1362 (void) sprintf(errmsg, "unable to modify QP");
1363 error = B_TRUE;
1364 goto bail;
1365 }
1366
1367 bail:
1368 if (error) {
1369 IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
1370 ibmf_modify_qp_err, IBMF_TNF_ERROR, "",
1371 "ibmf_modify_qp(): %s\n", tnf_string, msg, errmsg);
1372 }
1373
1374 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_modify_qp_end,
1375 IBMF_TNF_TRACE, "", "ibmf_modify_qp() exit\n");
1376
1377 return (status);
1378 }
1379
1380 /* ARGSUSED */
1381 int
ibmf_free_qp(ibmf_handle_t ibmf_handle,ibmf_qp_handle_t * ibmf_qp_handle,uint_t flags)1382 ibmf_free_qp(ibmf_handle_t ibmf_handle, ibmf_qp_handle_t *ibmf_qp_handle,
1383 uint_t flags)
1384 {
1385 ibmf_client_t *clientp = (ibmf_client_t *)ibmf_handle;
1386 ibmf_alt_qp_t *qp_ctx = (ibmf_alt_qp_t *)*ibmf_qp_handle;
1387 uint_t modify_flags;
1388 boolean_t error = B_FALSE;
1389 int status = IBMF_SUCCESS;
1390 char errmsg[128];
1391
1392 IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_free_qp_start,
1393 IBMF_TNF_TRACE, "", "ibmf_free_qp() enter, "
1394 "ibmf_handlep = %p, ibmf_qp_handle = %p\n",
1395 tnf_opaque, ibmf_handle, ibmf_handle,
1396 tnf_opaque, ibmf_qp_handle, *ibmf_qp_handle);
1397
1398 /* check for null args */
1399 if ((ibmf_handle == NULL) || (ibmf_qp_handle == NULL)) {
1400 (void) sprintf(errmsg,
1401 "invalid argument, NULL pointer argument");
1402 error = B_TRUE;
1403 status = IBMF_INVALID_ARG;
1404 goto bail;
1405 }
1406
1407 /* validate ibmf_handle */
1408 if (ibmf_i_is_ibmf_handle_valid(ibmf_handle) != IBMF_SUCCESS) {
1409 (void) sprintf(errmsg, "bad ibmf registration handle");
1410 error = B_TRUE;
1411 status = IBMF_BAD_HANDLE;
1412 goto bail;
1413 }
1414
1415 /* validate ibmf_qp_handle */
1416 if (ibmf_i_is_qp_handle_valid(ibmf_handle, *ibmf_qp_handle) !=
1417 IBMF_SUCCESS) {
1418 (void) sprintf(errmsg, "bad qp handle");
1419 error = B_TRUE;
1420 status = IBMF_BAD_QP_HANDLE;
1421 goto bail;
1422 }
1423
1424 /* validate ibmf_qp_handle */
1425 if (*ibmf_qp_handle == IBMF_QP_HANDLE_DEFAULT) {
1426 (void) sprintf(errmsg, "bad qp handle (default)");
1427 error = B_TRUE;
1428 status = IBMF_BAD_QP_HANDLE;
1429 goto bail;
1430 }
1431
1432 /* check signature */
1433 if (IBMF_VERIFY_CLIENT_SIGNATURE(clientp) == B_FALSE) {
1434 (void) sprintf(errmsg, "bad client signature");
1435 error = B_TRUE;
1436 status = IBMF_BAD_HANDLE;
1437 goto bail;
1438 }
1439
1440 /* validate client context handle */
1441 if (qp_ctx->isq_client_hdl != clientp) {
1442 (void) sprintf(errmsg, "bad QP handle");
1443 error = B_TRUE;
1444 status = IBMF_BAD_QP_HANDLE;
1445 goto bail;
1446 }
1447
1448 mutex_enter(&qp_ctx->isq_mutex);
1449
1450 if (qp_ctx->isq_recv_cb != NULL) {
1451 mutex_exit(&qp_ctx->isq_mutex);
1452 (void) sprintf(errmsg, "QP busy, callback active");
1453 error = B_TRUE;
1454 status = IBMF_BUSY;
1455 goto bail;
1456 }
1457
1458 mutex_exit(&qp_ctx->isq_mutex);
1459
1460 modify_flags = IBMF_ALLOC_SLEEP;
1461
1462 status = ibmf_i_free_qp(*ibmf_qp_handle, modify_flags);
1463 if (status != IBMF_SUCCESS) {
1464 (void) sprintf(errmsg, "unable to free QP");
1465 error = B_TRUE;
1466 goto bail;
1467 }
1468
1469 *ibmf_qp_handle = NULL;
1470
1471 bail:
1472 if (error) {
1473 IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
1474 ibmf_free_qp_err, IBMF_TNF_ERROR, "",
1475 "ibmf_free_qp(): %s\n", tnf_string, msg, errmsg);
1476 }
1477
1478 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_free_qp_end,
1479 IBMF_TNF_TRACE, "", "ibmf_free_qp() exit\n");
1480
1481 return (status);
1482 }
1483