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