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 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * This file implements the IBMF message related functions. 29 */ 30 31 #include <sys/ib/mgt/ibmf/ibmf_impl.h> 32 33 extern int ibmf_trace_level; 34 35 /* 36 * ibmf_i_client_add_msg(): 37 * Add the message to the client message list 38 */ 39 void 40 ibmf_i_client_add_msg(ibmf_client_t *clientp, ibmf_msg_impl_t *msgimplp) 41 { 42 IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4, 43 ibmf_i_client_add_msg_start, IBMF_TNF_TRACE, "", 44 "ibmf_i_client_add_msg(): clientp = 0x%p, msgp = 0x%p\n", 45 tnf_opaque, clientp, clientp, tnf_opaque, msg, msgimplp); 46 47 ASSERT(MUTEX_NOT_HELD(&msgimplp->im_mutex)); 48 49 mutex_enter(&clientp->ic_msg_mutex); 50 51 /* 52 * If this is a termination message, add the message to 53 * the termination message list else add the message 54 * to the regular message list. 55 */ 56 mutex_enter(&msgimplp->im_mutex); 57 if (msgimplp->im_flags & IBMF_MSG_FLAGS_TERMINATION) { 58 59 mutex_exit(&msgimplp->im_mutex); 60 /* Put the message on the list */ 61 if (clientp->ic_term_msg_list == NULL) { 62 clientp->ic_term_msg_list = clientp->ic_term_msg_last = 63 msgimplp; 64 } else { 65 msgimplp->im_msg_prev = clientp->ic_term_msg_last; 66 clientp->ic_term_msg_last->im_msg_next = msgimplp; 67 clientp->ic_term_msg_last = msgimplp; 68 } 69 } else { 70 71 mutex_exit(&msgimplp->im_mutex); 72 /* 73 * Increment the counter and kstats for active messages 74 */ 75 clientp->ic_msgs_active++; 76 mutex_enter(&clientp->ic_kstat_mutex); 77 IBMF_ADD32_KSTATS(clientp, msgs_active, 1); 78 mutex_exit(&clientp->ic_kstat_mutex); 79 80 /* Put the message on the list */ 81 if (clientp->ic_msg_list == NULL) { 82 clientp->ic_msg_list = clientp->ic_msg_last = msgimplp; 83 } else { 84 msgimplp->im_msg_prev = clientp->ic_msg_last; 85 clientp->ic_msg_last->im_msg_next = msgimplp; 86 clientp->ic_msg_last = msgimplp; 87 } 88 } 89 90 msgimplp->im_msg_next = NULL; 91 92 /* Set the message flags to indicate the message is on the list */ 93 mutex_enter(&msgimplp->im_mutex); 94 msgimplp->im_flags |= IBMF_MSG_FLAGS_ON_LIST; 95 mutex_exit(&msgimplp->im_mutex); 96 97 mutex_exit(&clientp->ic_msg_mutex); 98 99 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, 100 ibmf_i_client_add_msg_end, IBMF_TNF_TRACE, "", 101 "ibmf_i_client_add_msg() exit\n"); 102 } 103 104 /* 105 * ibmf_i_client_rem_msg(): 106 * Remove the message from the client's message list 107 * The refcnt will hold the message reference count at the time 108 * the message was removed from the message list. Any packets 109 * arriving after this point for the message will be dropped. 110 * The message reference count is used by the threads processing 111 * the message to decide which one should notify the client 112 * (the one that decrements the reference count to zero). 113 */ 114 void 115 ibmf_i_client_rem_msg(ibmf_client_t *clientp, ibmf_msg_impl_t *msgimplp, 116 uint_t *refcnt) 117 { 118 ibmf_msg_impl_t *tmpmsg, *prevmsg = NULL; 119 120 ASSERT(MUTEX_NOT_HELD(&msgimplp->im_mutex)); 121 122 IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4, 123 ibmf_i_client_rem_msg_start, IBMF_TNF_TRACE, "", 124 "ibmf_i_client_rem_msg(): clientp = 0x%p, msgp = 0x%p\n", 125 tnf_opaque, clientp, clientp, tnf_opaque, msg, msgimplp); 126 127 mutex_enter(&clientp->ic_msg_mutex); 128 129 /* 130 * If this is a termination message, remove the message from 131 * the termination message list else remove the message 132 * from the regular message list. 133 */ 134 mutex_enter(&msgimplp->im_mutex); 135 if (msgimplp->im_flags & IBMF_MSG_FLAGS_TERMINATION) { 136 137 mutex_exit(&msgimplp->im_mutex); 138 tmpmsg = clientp->ic_term_msg_list; 139 140 while (tmpmsg != NULL) { 141 if (tmpmsg == msgimplp) 142 break; 143 prevmsg = tmpmsg; 144 tmpmsg = tmpmsg->im_msg_next; 145 } 146 147 ASSERT(tmpmsg != NULL); 148 149 if (tmpmsg->im_msg_next == NULL) 150 clientp->ic_term_msg_last = prevmsg; 151 else 152 tmpmsg->im_msg_next->im_msg_prev = prevmsg; 153 154 if (prevmsg != NULL) 155 prevmsg->im_msg_next = tmpmsg->im_msg_next; 156 else 157 clientp->ic_term_msg_list = tmpmsg->im_msg_next; 158 } else { 159 160 mutex_exit(&msgimplp->im_mutex); 161 /* 162 * Decrement the counter and kstats for active messages 163 */ 164 ASSERT(clientp->ic_msgs_active != 0); 165 clientp->ic_msgs_active--; 166 mutex_enter(&clientp->ic_kstat_mutex); 167 IBMF_SUB32_KSTATS(clientp, msgs_active, 1); 168 mutex_exit(&clientp->ic_kstat_mutex); 169 170 tmpmsg = clientp->ic_msg_list; 171 172 while (tmpmsg != NULL) { 173 if (tmpmsg == msgimplp) 174 break; 175 prevmsg = tmpmsg; 176 tmpmsg = tmpmsg->im_msg_next; 177 } 178 179 ASSERT(tmpmsg != NULL); 180 181 if (tmpmsg->im_msg_next == NULL) 182 clientp->ic_msg_last = prevmsg; 183 else 184 tmpmsg->im_msg_next->im_msg_prev = prevmsg; 185 186 if (prevmsg != NULL) 187 prevmsg->im_msg_next = tmpmsg->im_msg_next; 188 else 189 clientp->ic_msg_list = tmpmsg->im_msg_next; 190 } 191 192 /* Save away the message reference count and clear the list flag */ 193 mutex_enter(&msgimplp->im_mutex); 194 *refcnt = msgimplp->im_ref_count; 195 msgimplp->im_flags &= ~IBMF_MSG_FLAGS_ON_LIST; 196 mutex_exit(&msgimplp->im_mutex); 197 198 mutex_exit(&clientp->ic_msg_mutex); 199 200 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, 201 ibmf_i_client_rem_msg_end, IBMF_TNF_TRACE, "", 202 "ibmf_i_client_rem_msg() exit\n"); 203 } 204 205 /* 206 * ibmf_i_find_msg(): 207 * Walk the client message list for the message corresponding to 208 * the parameters specified 209 * The msg_list parameter should be either IBMF_REG_MSG_LIST 210 * or IBMF_TERM_MSG_LIST for the termination message list. 211 */ 212 ibmf_msg_impl_t * 213 ibmf_i_find_msg(ibmf_client_t *clientp, uint64_t tid, uint8_t mgt_class, 214 uint8_t r_method, ib_lid_t lid, ib_gid_t *gid, boolean_t gid_pr, 215 ibmf_rmpp_hdr_t *rmpp_hdr, boolean_t msg_list) 216 { 217 ibmf_msg_impl_t *msgimplp; 218 ib_gid_t *ctx_gidp; 219 int msg_found; 220 221 IBMF_TRACE_5(IBMF_TNF_DEBUG, DPRINT_L4, 222 ibmf_i_find_msg_start, IBMF_TNF_TRACE, "", 223 "ibmf_i_find_msg(): clientp = 0x%p, tid = 0x%p, mgmt_class = 0x%x, " 224 "lid = 0x%x, gidp = 0x%p\n", tnf_opaque, clientp, clientp, 225 tnf_opaque, tid, tid, tnf_opaque, mgt_class, mgt_class, 226 tnf_opaque, lid, lid, tnf_opaque, gid, gid); 227 228 msg_found = B_FALSE; 229 230 mutex_enter(&clientp->ic_msg_mutex); 231 232 if (msg_list == IBMF_REG_MSG_LIST) 233 msgimplp = clientp->ic_msg_list; 234 else 235 msgimplp = clientp->ic_term_msg_list; 236 237 /* 238 * Look for a transaction (message) context that matches the 239 * transaction ID, gid or lid, and management class of the 240 * incoming packet. 241 * 242 * If the client decides to do a non-rmpp or rmpp send only, 243 * despite expecting a response, then the response should check 244 * if the message context for the send still exists. 245 * If it does, it should be skipped. 246 */ 247 while (msgimplp != NULL) { 248 249 if (gid_pr == B_TRUE) { 250 251 ctx_gidp = &msgimplp->im_global_addr.ig_sender_gid; 252 253 /* first match gid */ 254 if ((ctx_gidp->gid_prefix != gid->gid_prefix) || 255 (ctx_gidp->gid_guid != gid->gid_guid)) { 256 257 msgimplp = msgimplp->im_msg_next; 258 continue; 259 } 260 } else { 261 262 IBMF_TRACE_5(IBMF_TNF_DEBUG, DPRINT_L3, 263 ibmf_i_find_msg, IBMF_TNF_TRACE, "", 264 "ibmf_i_find_msg(): %s, msgp = 0x%p, tid = 0x%p, " 265 "remote_lid = 0x%x, mgmt_class = 0x%x\n", 266 tnf_string, msg, "Comparing to msg", 267 tnf_opaque, msg, msgimplp, 268 tnf_opaque, tid, msgimplp->im_tid, 269 tnf_opaque, remote_lid, 270 msgimplp->im_local_addr.ia_remote_lid, 271 tnf_opaque, class, msgimplp->im_mgt_class); 272 273 /* first match lid */ 274 if (msgimplp->im_local_addr.ia_remote_lid != lid) { 275 msgimplp = msgimplp->im_msg_next; 276 continue; 277 } 278 } 279 280 /* next match tid and class */ 281 if ((msgimplp->im_tid != tid) || 282 (msgimplp->im_mgt_class != mgt_class)) { 283 284 msgimplp = msgimplp->im_msg_next; 285 continue; 286 } 287 288 /* 289 * For unsolicited transactions, the message is found 290 * if the method matches, but, 291 * If the response is an ACK, and the transaction is 292 * in RMPP receiver mode, then skip this message. 293 */ 294 if (msgimplp->im_unsolicited == B_TRUE) { 295 ibmf_rmpp_ctx_t *rmpp_ctx; 296 ibmf_msg_bufs_t *msgbufp; 297 298 mutex_enter(&msgimplp->im_mutex); 299 rmpp_ctx = &msgimplp->im_rmpp_ctx; 300 301 if ((msgimplp->im_flags & IBMF_MSG_FLAGS_RECV_RMPP) && 302 ((rmpp_ctx->rmpp_state == 303 IBMF_RMPP_STATE_RECEVR_ACTIVE) || 304 (rmpp_ctx->rmpp_state == 305 IBMF_RMPP_STATE_RECEVR_TERMINATE))) { 306 /* Continue if ACK packet */ 307 if (rmpp_hdr->rmpp_type == IBMF_RMPP_TYPE_ACK) { 308 mutex_exit(&msgimplp->im_mutex); 309 msgimplp = msgimplp->im_msg_next; 310 continue; 311 } 312 } 313 314 if (msgimplp->im_trans_state_flags == 315 IBMF_TRANS_STATE_FLAG_RECV_ACTIVE) { 316 msgbufp = &msgimplp->im_msgbufs_recv; 317 if (msgbufp->im_bufs_mad_hdr->R_Method == 318 r_method) { 319 mutex_exit(&msgimplp->im_mutex); 320 msg_found = B_TRUE; 321 break; 322 } 323 } 324 325 mutex_exit(&msgimplp->im_mutex); 326 } 327 328 /* 329 * if this was an unsequenced, non-RMPP transaction there should 330 * be no incoming packets 331 */ 332 if ((!(msgimplp->im_transp_op_flags & 333 IBMF_MSG_TRANS_FLAG_RMPP)) && 334 (!(msgimplp->im_transp_op_flags & 335 IBMF_MSG_TRANS_FLAG_SEQ))) { 336 337 msgimplp = msgimplp->im_msg_next; 338 continue; 339 } 340 341 342 /* 343 * if this is a sequenced transaction, 344 * (the send and response may or may not be RMPP) 345 * and the method of the incoming MAD is the same as the 346 * method in the send message context with the response bit 347 * set then this message matches. 348 */ 349 if (msgimplp->im_transp_op_flags & IBMF_MSG_TRANS_FLAG_SEQ) { 350 ibmf_msg_bufs_t *msgbufp; 351 352 mutex_enter(&msgimplp->im_mutex); 353 354 msgbufp = &msgimplp->im_msgbufs_send; 355 356 if ((msgbufp->im_bufs_mad_hdr->R_Method | 357 IBMF_RMPP_METHOD_RESP_BIT) == r_method) { 358 mutex_exit(&msgimplp->im_mutex); 359 msg_found = B_TRUE; 360 break; 361 } 362 363 mutex_exit(&msgimplp->im_mutex); 364 } 365 366 /* 367 * if this is an RMPP SEND transaction there should only 368 * be ACK, STOP, and ABORTS RMPP packets. 369 * The response data packets would have been detected in 370 * the check above. 371 */ 372 if (msgimplp->im_transp_op_flags & IBMF_MSG_TRANS_FLAG_RMPP) { 373 ibmf_rmpp_ctx_t *rmpp_ctx = &msgimplp->im_rmpp_ctx; 374 ibmf_msg_bufs_t *msgbufp; 375 376 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*rmpp_ctx)) 377 378 if ((rmpp_hdr != NULL) && 379 (rmpp_hdr->rmpp_flags & IBMF_RMPP_FLAGS_ACTIVE)) { 380 381 /* 382 * If non-sequenced, then there should be 383 * no DATA packets incoming for this transaction 384 */ 385 if (!(msgimplp->im_transp_op_flags & 386 IBMF_MSG_TRANS_FLAG_SEQ)) { 387 /* Continue if DATA packet */ 388 if (rmpp_hdr->rmpp_type == 389 IBMF_RMPP_TYPE_DATA) { 390 msgimplp = 391 msgimplp->im_msg_next; 392 continue; 393 } 394 } 395 396 397 /* Skip if R_Method does not match */ 398 if ((rmpp_ctx->rmpp_state == 399 IBMF_RMPP_STATE_SENDER_ACTIVE) || 400 (rmpp_ctx->rmpp_state == 401 IBMF_RMPP_STATE_SENDER_SWITCH)) { 402 /* Continue if DATA packet */ 403 if (rmpp_hdr->rmpp_type == 404 IBMF_RMPP_TYPE_DATA) { 405 msgimplp = 406 msgimplp->im_msg_next; 407 continue; 408 } 409 410 /* 411 * Continue if method does not match 412 * Ignore response bit during match. 413 */ 414 msgbufp = &msgimplp->im_msgbufs_send; 415 if ((msgbufp->im_bufs_mad_hdr-> 416 R_Method & MAD_METHOD_MASK) != 417 (r_method & MAD_METHOD_MASK)) { 418 msgimplp = msgimplp-> 419 im_msg_next; 420 continue; 421 } 422 } 423 424 /* Skip if R_Method does not match */ 425 if ((rmpp_ctx->rmpp_state == 426 IBMF_RMPP_STATE_RECEVR_ACTIVE) || 427 (rmpp_ctx->rmpp_state == 428 IBMF_RMPP_STATE_RECEVR_TERMINATE)) { 429 /* Continue if ACK packet */ 430 if (rmpp_hdr->rmpp_type == 431 IBMF_RMPP_TYPE_ACK) { 432 msgimplp = 433 msgimplp->im_msg_next; 434 continue; 435 } 436 437 /* Continue if method does not match */ 438 msgbufp = &msgimplp->im_msgbufs_recv; 439 if (msgbufp->im_bufs_mad_hdr-> 440 R_Method != r_method) { 441 msgimplp = msgimplp-> 442 im_msg_next; 443 continue; 444 } 445 } 446 } 447 } 448 449 /* 450 * For a sequenced non-RMPP transaction, if the 451 * TID/LID/MgtClass are the same, and if the method 452 * of the incoming MAD and the message context are the 453 * same, then the MAD is likely to be a new request from 454 * the remote entity, so skip this message. 455 */ 456 if ((msgimplp->im_transp_op_flags & IBMF_MSG_TRANS_FLAG_SEQ) && 457 !(msgimplp->im_transp_op_flags & 458 IBMF_MSG_TRANS_FLAG_RMPP)) { 459 ibmf_msg_bufs_t *msgbufp; 460 461 mutex_enter(&msgimplp->im_mutex); 462 463 msgbufp = &msgimplp->im_msgbufs_send; 464 465 mutex_exit(&msgimplp->im_mutex); 466 467 /* Continue if method is the same */ 468 if (msgbufp->im_bufs_mad_hdr-> 469 R_Method == r_method) { 470 msgimplp = msgimplp-> im_msg_next; 471 continue; 472 } 473 } 474 475 /* everything matches, found the correct message */ 476 msg_found = B_TRUE; 477 break; 478 } 479 480 if (msg_found == B_TRUE) { 481 482 mutex_enter(&msgimplp->im_mutex); 483 484 IBMF_MSG_INCR_REFCNT(msgimplp); 485 486 IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L3, 487 ibmf_i_find_msg, IBMF_TNF_TRACE, "", 488 "ibmf_i_find_msg(): %s, msgp = 0x%p, ref_cnt = 0x%d\n", 489 tnf_string, msg, "Found message. Inc ref count", 490 tnf_opaque, msgimplp, msgimplp, 491 tnf_uint, ref_count, msgimplp->im_ref_count); 492 493 mutex_exit(&msgimplp->im_mutex); 494 } 495 496 mutex_exit(&clientp->ic_msg_mutex); 497 498 IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, 499 ibmf_i_find_msg_end, IBMF_TNF_TRACE, "", 500 "ibmf_i_find_msg() exit, msgp = 0x%p\n", tnf_opaque, msg, msgimplp); 501 502 return (msgimplp); 503 } 504 505 /* 506 * ibmf_i_find_msg_client(): 507 * Walk the client message list to find the specified message 508 */ 509 boolean_t 510 ibmf_i_find_msg_client(ibmf_client_t *clp, ibmf_msg_impl_t *msgimplp, 511 boolean_t inc_refcnt) 512 { 513 ibmf_msg_impl_t *msgp; 514 boolean_t found = B_FALSE; 515 516 IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4, 517 ibmf_i_find_msg_client_start, IBMF_TNF_TRACE, "", 518 "ibmf_i_find_msg_client(): clientp = 0x%p, msgp = 0x%p\n", 519 tnf_opaque, clientp, clp, tnf_opaque, msg, msgimplp); 520 521 mutex_enter(&clp->ic_msg_mutex); 522 523 msgp = clp->ic_msg_list; 524 while (msgp != NULL) { 525 526 if (msgp == msgimplp) { 527 528 /* grab the mutex */ 529 mutex_enter(&msgimplp->im_mutex); 530 531 if (inc_refcnt == B_TRUE) 532 IBMF_MSG_INCR_REFCNT(msgimplp); 533 534 IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L3, 535 ibmf_i_find_msg_client, IBMF_TNF_TRACE, "", 536 "ibmf_i_find_msg_client(): %s, msgp = 0x%p, " 537 "ref_cnt = 0x%d\n", 538 tnf_string, msg, "Found message. Inc ref count", 539 tnf_opaque, msgimplp, msgimplp, 540 tnf_uint, ref_count, msgimplp->im_ref_count); 541 542 mutex_exit(&msgimplp->im_mutex); 543 544 found = B_TRUE; 545 546 break; 547 } 548 msgp = msgp->im_msg_next; 549 } 550 551 /* 552 * If not found on the regular message list, 553 * look in the termination list. 554 */ 555 if (found == B_FALSE) { 556 msgp = clp->ic_term_msg_list; 557 while (msgp != NULL) { 558 if (msgp == msgimplp) { 559 560 /* grab the mutex */ 561 mutex_enter(&msgimplp->im_mutex); 562 563 if (inc_refcnt == B_TRUE) 564 IBMF_MSG_INCR_REFCNT(msgimplp); 565 566 IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L3, 567 ibmf_i_find_msg_client, IBMF_TNF_TRACE, "", 568 "ibmf_i_find_msg_client(): %s, " 569 "msgp = 0x%p, ref_cnt = 0x%d\n", tnf_string, 570 msg, "Found message. Inc ref count", 571 tnf_opaque, msgimplp, msgimplp, tnf_uint, 572 ref_count, msgimplp->im_ref_count); 573 574 mutex_exit(&msgimplp->im_mutex); 575 found = B_TRUE; 576 break; 577 } 578 msgp = msgp->im_msg_next; 579 } 580 } 581 582 mutex_exit(&clp->ic_msg_mutex); 583 584 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, 585 ibmf_i_find_msg_client_end, IBMF_TNF_TRACE, "", 586 "ibmf_i_find_msg_client() exit\n"); 587 588 return (found); 589 } 590 591 /* 592 * ibmf_setup_recvbuf_on_error(): 593 * 594 * This function is used to set up the receive buffers to provide 595 * a context for sending ABORT MADs in cases where the protocol 596 * fails before the receive buffers have been setup. This can happen 597 * if the initial receive MAD has a bad version, or an unexpected 598 * segment number, for example. 599 * We allocate IBMF_MAD_SIZE memory as we only need the information 600 * stored in the MAD header and the class header to be able to send 601 * the ABORT. 602 */ 603 int 604 ibmf_setup_recvbuf_on_error(ibmf_msg_impl_t *msgimplp, uchar_t *mad) 605 { 606 size_t offset; 607 uint32_t cl_hdr_sz, cl_hdr_off; 608 ib_mad_hdr_t *mad_hdr; 609 uchar_t *msgbufp; 610 ibmf_client_t *clientp = (ibmf_client_t *)msgimplp->im_client; 611 612 ASSERT(msgimplp->im_msgbufs_recv.im_bufs_mad_hdr == NULL); 613 614 /* 615 * Allocate enough memory for the MAD headers only. 616 */ 617 msgimplp->im_msgbufs_recv.im_bufs_mad_hdr = 618 (ib_mad_hdr_t *)kmem_zalloc(IBMF_MAD_SIZE, KM_NOSLEEP); 619 if (msgimplp->im_msgbufs_recv.im_bufs_mad_hdr == NULL) { 620 IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1, 621 ibmf_setup_recvbuf_on_error, IBMF_TNF_ERROR, "", 622 "ibmf_setup_recvbuf_on_error(): %s\n", tnf_string, msg, 623 "recv buf mem allocation failure"); 624 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, 625 ibmf_setup_recvbuf_on_error_end, IBMF_TNF_TRACE, "", 626 "ibmf_setup_recvbuf_on_error() exit\n"); 627 return (IBMF_NO_RESOURCES); 628 } 629 630 mutex_enter(&clientp->ic_kstat_mutex); 631 IBMF_ADD32_KSTATS(clientp, recv_bufs_alloced, 1); 632 mutex_exit(&clientp->ic_kstat_mutex); 633 634 mad_hdr = (ib_mad_hdr_t *)mad; 635 636 /* Get the class header size and offset */ 637 ibmf_i_mgt_class_to_hdr_sz_off(mad_hdr->MgmtClass, &cl_hdr_sz, 638 &cl_hdr_off); 639 640 msgbufp = (uchar_t *)msgimplp->im_msgbufs_recv.im_bufs_mad_hdr; 641 642 /* copy the MAD and class header */ 643 bcopy((const void *)mad, (void *)msgbufp, 644 sizeof (ib_mad_hdr_t) + cl_hdr_off + cl_hdr_sz); 645 646 /* offset of the class header */ 647 offset = sizeof (ib_mad_hdr_t) + cl_hdr_off; 648 649 /* initialize class header pointer */ 650 if (cl_hdr_sz == 0) { 651 msgimplp->im_msgbufs_recv.im_bufs_cl_hdr = NULL; 652 } else { 653 msgimplp->im_msgbufs_recv.im_bufs_cl_hdr = 654 (void *)(msgbufp + offset); 655 } 656 657 /* Set the class header length */ 658 msgimplp->im_msgbufs_recv.im_bufs_cl_hdr_len = cl_hdr_sz; 659 660 /* offset of the class data */ 661 offset += cl_hdr_sz; 662 663 /* initialize data area pointer */ 664 msgimplp->im_msgbufs_recv.im_bufs_cl_data = (void *)(msgbufp + offset); 665 msgimplp->im_msgbufs_recv.im_bufs_cl_data_len = IBMF_MAD_SIZE - 666 sizeof (ib_mad_hdr_t) - cl_hdr_off - cl_hdr_sz; 667 668 return (IBMF_SUCCESS); 669 } 670