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