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 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_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 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 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 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 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 }