1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * ibcm_utils.c 31 * 32 * contains internal lookup functions of IB CM module 33 * along with some other miscellaneous stuff 34 * 35 * TBD: 36 * 1. Code needed to ensure that if any clients are using a service then 37 * don't de-register it. 38 */ 39 40 #include <sys/ib/mgt/ibcm/ibcm_impl.h> 41 #include <sys/ddi.h> 42 43 44 /* statics */ 45 static vmem_t *ibcm_local_sid_arena; 46 static ib_svc_id_t ibcm_local_sid_seed; 47 static ib_com_id_t ibcm_local_cid_seed; 48 _NOTE(READ_ONLY_DATA({ibcm_local_sid_arena ibcm_local_sid_seed 49 ibcm_local_cid_seed})) 50 static void ibcm_delete_state_from_avl(ibcm_state_data_t *statep); 51 static void ibcm_init_conn_trace(ibcm_state_data_t *statep); 52 static void ibcm_fini_conn_trace(ibcm_state_data_t *statep); 53 static void ibcm_dump_conn_trbuf(void *statep, char *line_prefix, 54 char *buf, int buf_size); 55 56 /* 57 * ibcm_lookup_msg: 58 * 59 * Retrieves an existing state structure or creates a new one if none found. 60 * This function is used during 61 * Passive connection side for INCOMING REQ/REJ/RTU/MRA/DREQ/DREP/LAP msgs 62 * Active connection side for INCOMING REP/REJ/MRA/DREQ/DREP/APR msgs 63 * Active side CM for outgoing REQ message. 64 * 65 * NOTE: Only return IBCM_LOOKUP_FAIL if lookup failed to find a match. 66 * 67 * Arguments are:- 68 * event_type - type of message 69 * incoming REQ, REP, REJ, MRA, RTU 70 * remote_qpn - Remote QP number 71 * comid - local/remote comid 72 * remote_hca_guid - Remote HCA GUID 73 * hcap - HCA entry ptr 74 * rstatep - return statep pointer 75 * 76 * Return Values: 77 * IBCM_LOOKUP_NEW - new statep allocated 78 * IBCM_LOOKUP_EXISTS - found an existing entry 79 * IBCM_LOOKUP_FAIL - No lookup entry found 80 * IBCM_MEMORY_FAILURE - Memory allocs failed 81 */ 82 ibcm_status_t 83 ibcm_lookup_msg(ibcm_event_type_t event_type, ib_com_id_t comid, 84 ib_qpn_t remote_qpn, ib_guid_t remote_hca_guid, ibcm_hca_info_t *hcap, 85 ibcm_state_data_t **rstatep) 86 { 87 avl_index_t where; 88 ibcm_state_data_t *sp; 89 90 IBTF_DPRINTF_L4(cmlog, "ibcm_lookup_msg: event = 0x%x, comid = 0x%lx", 91 event_type, comid); 92 IBTF_DPRINTF_L4(cmlog, "ibcm_lookup_msg: rem_qpn = 0x%lX, " 93 "rem_hca_guid = 0x%llX", remote_qpn, remote_hca_guid); 94 95 ASSERT(rw_lock_held(&hcap->hca_state_rwlock)); 96 97 /* 98 * Lookup in "hca_passive_tree" for IBCM_INCOMING_REQ and 99 * IBCM_INCOMING_REP_STALE; 100 * 101 * Lookup in "hca_passive_comid_tree" for IBCM_INCOMING_REQ_STALE 102 * 103 * All other lookups in "hca_active_tree". 104 * 105 * NOTE: "hca_active_tree" lookups are based on the local comid. 106 * "hca_passive_state_tree" lookups are based on remote QPN 107 * and remote hca GUID. 108 * 109 * Call avl_find to lookup in the respective tree and save result in 110 * "sp". If "sp" is null it implies that no match was found. If so, 111 * allocate a new ibcm_state_data_t and insert it into the AVL tree(s). 112 */ 113 if ((event_type == IBCM_INCOMING_REQ) || 114 (event_type == IBCM_INCOMING_REP_STALE)) { 115 ibcm_passive_node_info_t info; 116 117 info.info_qpn = remote_qpn; 118 info.info_hca_guid = remote_hca_guid; 119 120 /* Lookup based on Remote QPN and Remote GUID in Passive Tree */ 121 sp = avl_find(&hcap->hca_passive_tree, &info, &where); 122 } else if ((event_type == IBCM_INCOMING_REQ_STALE) || 123 (event_type == IBCM_INCOMING_REJ_RCOMID)) { 124 ibcm_passive_comid_node_info_t info; 125 126 info.info_comid = comid; 127 info.info_hca_guid = remote_hca_guid; 128 129 /* Lookup based on Remote COMID in Passive Tree */ 130 sp = avl_find(&hcap->hca_passive_comid_tree, &info, &where); 131 } else { /* any other event including IBCM_OUTGOING_REQ */ 132 /* Lookup based on Local comid in Active Tree */ 133 sp = avl_find(&hcap->hca_active_tree, &comid, &where); 134 } 135 136 /* matching entry found !! */ 137 if (sp != NULL) { 138 IBTF_DPRINTF_L4(cmlog, "ibcm_lookup_msg: match found " 139 "statep = %p", sp); 140 if (event_type == IBCM_INCOMING_REQ) 141 kmem_free(*rstatep, sizeof (ibcm_state_data_t)); 142 *rstatep = sp; /* return the matched statep */ 143 144 mutex_enter(&(sp->state_mutex)); 145 IBCM_REF_CNT_INCR(sp); /* increment the ref count */ 146 mutex_exit(&(sp->state_mutex)); 147 148 return (IBCM_LOOKUP_EXISTS); 149 } 150 151 /* 152 * If we came here then it implies that CM didn't 153 * find a matching entry. We will create a new entry in avl tree, 154 * if event_type is INCOMING/OUTGOING REQ, REQ_STALE/REP_STALE. 155 * statep is created for INCOMING/OUTGOING REQ. 156 * For all other event_types we return lookup failure 157 */ 158 if (!((event_type == IBCM_INCOMING_REQ) || 159 (event_type == IBCM_INCOMING_REQ_STALE) || 160 (event_type == IBCM_INCOMING_REP_STALE) || 161 (event_type == IBCM_OUTGOING_REQ))) { 162 IBTF_DPRINTF_L2(cmlog, "ibcm_lookup_msg: failed for " 163 "event type %x", event_type); 164 165 return (IBCM_LOOKUP_FAIL); 166 } 167 168 if ((event_type == IBCM_INCOMING_REQ) || 169 (event_type == IBCM_OUTGOING_REQ)) { 170 171 /* fill in the new ibcm_state_data */ 172 sp = *rstatep; 173 174 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*sp)) 175 176 /* initialize statep */ 177 mutex_init(&sp->state_mutex, NULL, MUTEX_DEFAULT, NULL); 178 cv_init(&sp->block_client_cv, NULL, CV_DRIVER, NULL); 179 cv_init(&sp->block_mad_cv, NULL, CV_DRIVER, NULL); 180 181 sp->hcap = hcap; 182 IBCM_REF_CNT_INCR(sp); 183 sp->local_comid = comid; 184 185 if (ibcm_enable_trace != 0) 186 ibcm_init_conn_trace(sp); 187 188 if (event_type == IBCM_INCOMING_REQ) { /* Passive side */ 189 sp->state = IBCM_STATE_REQ_RCVD; 190 sp->clnt_proceed = IBCM_BLOCK; 191 sp->close_nocb_state = IBCM_UNBLOCK; 192 sp->remote_hca_guid = remote_hca_guid; 193 sp->remote_qpn = remote_qpn; 194 195 } else if (event_type == IBCM_OUTGOING_REQ) { /* Active side */ 196 sp->close_nocb_state = IBCM_UNBLOCK; 197 sp->state = IBCM_STATE_IDLE; 198 } 199 200 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*sp)) 201 202 } else { 203 sp = *rstatep; /* for incoming REQ/REP STALE only */ 204 } 205 206 if ((event_type == IBCM_INCOMING_REQ) || 207 (event_type == IBCM_INCOMING_REP_STALE)) { 208 209 /* First, insert a new "sp" into "hca_passive_tree" @ "where" */ 210 avl_insert(&(hcap->hca_passive_tree), (void *)sp, where); 211 212 if (event_type == IBCM_INCOMING_REQ) { /* Only INCOMING_REQ */ 213 /* 214 * We have to do an avl_find() to figure out 215 * "where" to insert the statep into the active tree. 216 * 217 * CM doesn't care for avl_find's retval. 218 */ 219 (void) avl_find(&hcap->hca_active_tree, 220 &sp->local_comid, &where); 221 222 /* Next, insert the "sp" into "hca_active_tree" */ 223 avl_insert(&hcap->hca_active_tree, (void *)sp, where); 224 } 225 } else if (event_type == IBCM_INCOMING_REQ_STALE) { 226 avl_insert(&(hcap->hca_passive_comid_tree), (void *)sp, where); 227 } else { /* IBCM_OUTGOING_REQ */ 228 /* Insert the new sp only into "hca_active_tree", @ "where" */ 229 avl_insert(&(hcap->hca_active_tree), (void *)sp, where); 230 } 231 232 return (IBCM_LOOKUP_NEW); /* return new lookup */ 233 } 234 235 236 /* 237 * ibcm_active_node_compare: 238 * - AVL active tree node compare 239 * 240 * Arguments: 241 * p1 : pointer to local comid 242 * p2 : pointer to passed ibcm_state_data_t 243 * 244 * Return values: 245 * 0 : match found 246 * -1 : no match but insert to left side of the tree 247 * +1 : no match but insert to right side of the tree 248 */ 249 int 250 ibcm_active_node_compare(const void *p1, const void *p2) 251 { 252 ib_com_id_t *local_comid = (ib_com_id_t *)p1; 253 ibcm_state_data_t *statep = (ibcm_state_data_t *)p2; 254 255 IBTF_DPRINTF_L5(cmlog, "ibcm_active_node_compare: " 256 "comid: 0x%x, statep: 0x%p", *local_comid, statep); 257 258 if (*local_comid > statep->local_comid) { 259 return (+1); 260 } else if (*local_comid < statep->local_comid) { 261 return (-1); 262 } else { 263 return (0); 264 } 265 } 266 267 268 /* 269 * ibcm_passive_node_compare: 270 * - AVL passive tree node compare (passive side) 271 * 272 * Arguments: 273 * p1 : pointer to ibcm_passive_node_info (remote qpn and remote guid) 274 * p2 : pointer to passed ibcm_state_data_t 275 * 276 * Return values: 277 * 0 : match found 278 * -1 : no match but insert to left side of the tree 279 * +1 : no match but insert to right side of the tree 280 */ 281 int 282 ibcm_passive_node_compare(const void *p1, const void *p2) 283 { 284 ibcm_state_data_t *statep = (ibcm_state_data_t *)p2; 285 ibcm_passive_node_info_t *infop = (ibcm_passive_node_info_t *)p1; 286 287 IBTF_DPRINTF_L5(cmlog, "ibcm_passive_node_compare: " 288 "statep: 0x%p, p1: 0x%p", statep, p1); 289 290 /* 291 * PASSIVE SIDE: (REQ, REP, MRA, REJ) 292 * always search by active COMID 293 */ 294 if (infop->info_qpn > statep->remote_qpn) { 295 return (+1); 296 } else if (infop->info_qpn < statep->remote_qpn) { 297 return (-1); 298 } else { 299 if (infop->info_hca_guid < statep->remote_hca_guid) { 300 return (-1); 301 } else if (infop->info_hca_guid > statep->remote_hca_guid) { 302 return (+1); 303 } else { 304 return (0); 305 } 306 } 307 } 308 309 /* 310 * ibcm_passive_comid_node_compare: 311 * - AVL passive comid tree node compare (passive side) 312 * 313 * Arguments: 314 * p1 : pointer to ibcm_passive_comid_node_info 315 * (remote comid and remote guid) 316 * p2 : pointer to passed ibcm_state_data_t 317 * 318 * Return values: 319 * 0 : match found 320 * -1 : no match but insert to left side of the tree 321 * +1 : no match but insert to right side of the tree 322 */ 323 int 324 ibcm_passive_comid_node_compare(const void *p1, const void *p2) 325 { 326 ibcm_state_data_t *statep = (ibcm_state_data_t *)p2; 327 ibcm_passive_comid_node_info_t *infop = 328 (ibcm_passive_comid_node_info_t *)p1; 329 330 IBTF_DPRINTF_L5(cmlog, "ibcm_passive_comid_node_compare: " 331 "statep: 0x%p, p1: 0x%p", statep, p1); 332 333 if (infop->info_comid > statep->remote_comid) { 334 return (+1); 335 } else if (infop->info_comid < statep->remote_comid) { 336 return (-1); 337 } else { 338 if (infop->info_hca_guid < statep->remote_hca_guid) { 339 return (-1); 340 } else if (infop->info_hca_guid > statep->remote_hca_guid) { 341 return (+1); 342 } else { 343 return (0); 344 } 345 } 346 } 347 348 349 void 350 ibcm_delete_state_from_avl(ibcm_state_data_t *statep) 351 { 352 avl_index_t a_where = 0; 353 avl_index_t p_where = 0; 354 avl_index_t pcomid_where = 0; 355 ibcm_hca_info_t *hcap; 356 ibcm_state_data_t *active_nodep, *passive_nodep, 357 *passive_comid_nodep; 358 ibcm_passive_node_info_t info; 359 ibcm_passive_comid_node_info_t info_comid; 360 361 IBTF_DPRINTF_L4(cmlog, "ibcm_delete_state_from_avl: statep 0x%p", 362 statep); 363 364 if (statep == NULL) { 365 IBTF_DPRINTF_L2(cmlog, "ibcm_delete_state_from_avl: statep" 366 " NULL"); 367 return; 368 } 369 370 hcap = statep->hcap; 371 372 /* 373 * Once the avl tree lock is acquired, no other thread can increment 374 * ref cnt, until tree lock is exit'ed. Since the statep is removed 375 * from the avl's after acquiring lock below, no other thread can 376 * increment the ref cnt after acquiring the lock below 377 */ 378 379 rw_enter(&hcap->hca_state_rwlock, RW_WRITER); 380 381 /* Lookup based on Local comid in the active tree */ 382 active_nodep = avl_find(&hcap->hca_active_tree, &(statep->local_comid), 383 &a_where); 384 385 /* Lookup based on Remote QPN and Remote GUID in the passive tree */ 386 info.info_qpn = statep->remote_qpn; 387 info.info_hca_guid = statep->remote_hca_guid; 388 passive_nodep = avl_find(&hcap->hca_passive_tree, &info, &p_where); 389 390 /* Lookup based on Remote Comid and Remote GUID in the passive tree */ 391 info_comid.info_comid = statep->remote_comid; 392 info_comid.info_hca_guid = statep->remote_hca_guid; 393 passive_comid_nodep = avl_find(&hcap->hca_passive_comid_tree, 394 &info_comid, &pcomid_where); 395 396 /* remove it from the tree, destroy record and the nodep */ 397 if (active_nodep == statep) { 398 avl_remove(&hcap->hca_active_tree, active_nodep); 399 } 400 401 if (passive_nodep == statep) { 402 avl_remove(&hcap->hca_passive_tree, passive_nodep); 403 } 404 405 if (passive_comid_nodep == statep) { 406 avl_remove(&hcap->hca_passive_comid_tree, passive_comid_nodep); 407 } 408 409 rw_exit(&hcap->hca_state_rwlock); 410 } 411 412 /* 413 * ibcm_dealloc_state_data: 414 * Deallocates all buffers and the memory of state structure 415 * This routine can be called on statep that has ref_cnt of 0, and that is 416 * already deleted from the avl tree's 417 * 418 * Arguments are:- 419 * statep - statep to be deleted 420 * 421 * Return Values: NONE 422 */ 423 void 424 ibcm_dealloc_state_data(ibcm_state_data_t *statep) 425 { 426 timeout_id_t timer_val; 427 IBTF_DPRINTF_L4(cmlog, "ibcm_dealloc_state_data: statep 0x%p", statep); 428 429 if (statep == NULL) { 430 IBTF_DPRINTF_L2(cmlog, "ibcm_dealloc_state_data: statep NULL"); 431 return; 432 } 433 434 /* ref_cnt is 0 */ 435 /* If timer is running - expire it */ 436 mutex_enter(&statep->state_mutex); 437 timer_val = statep->timerid; 438 if (timer_val != 0) { 439 statep->timerid = 0; 440 mutex_exit(&statep->state_mutex); 441 (void) untimeout(timer_val); 442 } else 443 mutex_exit(&statep->state_mutex); 444 445 /* release the ref cnt on the associated ibmf qp */ 446 if (statep->stored_reply_addr.cm_qp_entry != NULL) 447 ibcm_release_qp(statep->stored_reply_addr.cm_qp_entry); 448 449 if (statep->stored_msg != NULL) 450 (void) ibcm_free_out_msg(statep->stored_reply_addr.ibmf_hdl, 451 &statep->stored_msg); 452 453 if (statep->dreq_msg != NULL) 454 (void) ibcm_free_out_msg(statep->stored_reply_addr.ibmf_hdl, 455 &statep->dreq_msg); 456 457 if (statep->drep_msg != NULL) 458 (void) ibcm_free_out_msg(statep->stored_reply_addr.ibmf_hdl, 459 &statep->drep_msg); 460 461 if (statep->mra_msg != NULL) 462 (void) ibcm_free_out_msg(statep->stored_reply_addr.ibmf_hdl, 463 &statep->mra_msg); 464 465 if (statep->lapr_msg != NULL) 466 (void) ibcm_free_out_msg(statep->stored_reply_addr.ibmf_hdl, 467 &statep->lapr_msg); 468 469 if (statep->defer_cm_msg != NULL) 470 kmem_free(statep->defer_cm_msg, IBCM_MSG_SIZE); 471 472 IBTF_DPRINTF_L4(cmlog, "ibcm_dealloc_state_data: done for sp = 0x%p", 473 statep); 474 475 /* Ensure the thread doing ref cnt decr releases the mutex */ 476 mutex_enter(&statep->state_mutex); 477 mutex_exit(&statep->state_mutex); 478 479 /* 480 * now call the mutex_destroy() and cv_destroy() 481 */ 482 mutex_destroy(&statep->state_mutex); 483 484 cv_destroy(&statep->block_client_cv); 485 cv_destroy(&statep->block_mad_cv); 486 487 /* free the comid */ 488 ibcm_free_comid(statep->hcap, statep->local_comid); 489 490 /* Decrement the resource on hcap */ 491 ibcm_dec_hca_res_cnt(statep->hcap); 492 493 /* dump the trace data into ibtf_debug_buf */ 494 if (ibcm_enable_trace & 4) 495 ibcm_dump_conn_trace(statep); 496 497 ibcm_fini_conn_trace(statep); 498 499 /* free the statep */ 500 kmem_free(statep, sizeof (ibcm_state_data_t)); 501 } 502 503 /* 504 * ibcm_delete_state_data: 505 * Deletes the state from avl trees, and tries to deallocate state 506 * 507 * Arguments are:- 508 * statep - statep to be deleted 509 * 510 * Return Values: NONE 511 */ 512 void 513 ibcm_delete_state_data(ibcm_state_data_t *statep) 514 { 515 IBTF_DPRINTF_L4(cmlog, "ibcm_delete_state_data:"); 516 517 ibcm_delete_state_from_avl(statep); 518 519 /* Must acquire the state mutex to set delete_state_data */ 520 mutex_enter(&statep->state_mutex); 521 if (statep->ref_cnt > 0) { 522 statep->delete_state_data = B_TRUE; 523 IBTF_DPRINTF_L4(cmlog, "ibcm_delete_state_data: statep 0x%p " 524 "ref_cnt = %x", statep, statep->ref_cnt); 525 mutex_exit(&statep->state_mutex); 526 return; 527 } 528 mutex_exit(&statep->state_mutex); 529 530 ibcm_dealloc_state_data(statep); 531 } 532 533 /* 534 * ibcm_find_sidr_entry: 535 * Routines for CM SIDR state structure list manipulation. 536 * Finds an entry based on lid, gid and grh exists fields 537 * 538 * INPUTS: 539 * lid: LID of incoming SIDR REQ 540 * gid: GID of incoming SIDR REQ 541 * grh_exists: TRUE if GRH exists in the incoming SIDR REQ 542 * req_id: Request ID 543 * hcap: CM State table to search for SIDR state structure 544 * statep: Returns a valid state structure, if one exists based 545 * on lid, gid and grh_exists fields 546 * flag: IBCM_FLAG_LOOKUP - just lookup 547 * IBCM_FLAG_LOOKUP_AND_ADD - if lookup fails, add it. 548 * Return Values: 549 * IBCM_LOOKUP_EXISTS - found an existing entry 550 * IBCM_LOOKUP_FAIL - failed to find an entry 551 * IBCM_LOOKUP_NEW - created a new entry 552 */ 553 ibcm_status_t 554 ibcm_find_sidr_entry(ibcm_sidr_srch_t *srch_param, ibcm_hca_info_t *hcap, 555 ibcm_ud_state_data_t **ud_statep, ibcm_lookup_flag_t flag) 556 { 557 ibcm_status_t status; 558 ibcm_ud_state_data_t *usp; 559 560 IBTF_DPRINTF_L5(cmlog, "ibcm_find_sidr_entry: srch_params are:" 561 "lid=%x, (%llX, %llX), grh: %x, id: %x", 562 srch_param->srch_lid, srch_param->srch_gid.gid_prefix, 563 srch_param->srch_gid.gid_guid, srch_param->srch_grh_exists, 564 srch_param->srch_req_id); 565 566 if (flag == IBCM_FLAG_ADD) { 567 *ud_statep = ibcm_add_sidr_entry(srch_param, hcap); 568 return (IBCM_LOOKUP_NEW); 569 } 570 571 usp = hcap->hca_sidr_list; /* Point to the list */ 572 573 /* traverse the list for a matching entry */ 574 while (usp != NULL) { 575 IBTF_DPRINTF_L5(cmlog, "ibcm_find_sidr_entry: " 576 "lid=%x, (%llX, %llX), grh: %x, id: %x", 577 usp->ud_sidr_req_lid, usp->ud_sidr_req_gid.gid_prefix, 578 usp->ud_sidr_req_gid.gid_guid, usp->ud_grh_exists, 579 usp->ud_req_id); 580 581 if ((usp->ud_sidr_req_lid == srch_param->srch_lid) && 582 ((srch_param->srch_gid.gid_prefix == 0) || 583 (srch_param->srch_gid.gid_prefix == 584 usp->ud_sidr_req_gid.gid_prefix)) && 585 ((srch_param->srch_gid.gid_guid == 0) || 586 (srch_param->srch_gid.gid_guid == 587 usp->ud_sidr_req_gid.gid_guid)) && 588 (srch_param->srch_req_id == usp->ud_req_id) && 589 (usp->ud_grh_exists == srch_param->srch_grh_exists) && 590 (usp->ud_mode == srch_param->srch_mode)) { /* found match */ 591 *ud_statep = usp; 592 IBTF_DPRINTF_L5(cmlog, "ibcm_find_sidr_entry: " 593 "found usp = %p", usp); 594 mutex_enter(&usp->ud_state_mutex); 595 IBCM_UD_REF_CNT_INCR(usp); 596 mutex_exit(&usp->ud_state_mutex); 597 598 return (IBCM_LOOKUP_EXISTS); 599 } 600 usp = usp->ud_nextp; 601 } 602 603 /* 604 * If code came here --> it couldn't find a match. 605 * OR 606 * the "hcap->hca_sidr_list" was NULL 607 */ 608 if (flag == IBCM_FLAG_LOOKUP) { 609 IBTF_DPRINTF_L3(cmlog, "ibcm_find_sidr_entry: no match found " 610 "lid=%x, (%llX, %llX), grh: %x, id: %x", 611 srch_param->srch_lid, srch_param->srch_gid.gid_prefix, 612 srch_param->srch_gid.gid_guid, srch_param->srch_grh_exists, 613 srch_param->srch_req_id); 614 status = IBCM_LOOKUP_FAIL; 615 } else { 616 *ud_statep = ibcm_add_sidr_entry(srch_param, hcap); 617 status = IBCM_LOOKUP_NEW; 618 } 619 620 return (status); 621 } 622 623 624 /* 625 * ibcm_add_sidr_entry: 626 * Adds a SIDR entry. Called *ONLY* from ibcm_find_sidr_entry() 627 * 628 * INPUTS: 629 * lid: LID of incoming SIDR REQ 630 * gid: GID of incoming SIDR REQ 631 * grh_exists: TRUE if GRH exists in the incoming SIDR REQ 632 * req_id: Request ID 633 * hcap: CM State table to search for SIDR state structure 634 * Return Values: NONE 635 */ 636 ibcm_ud_state_data_t * 637 ibcm_add_sidr_entry(ibcm_sidr_srch_t *srch_param, ibcm_hca_info_t *hcap) 638 { 639 ibcm_ud_state_data_t *ud_statep; 640 641 IBTF_DPRINTF_L5(cmlog, "ibcm_add_sidr_entry: lid=%x, guid=%llX, " 642 "grh = %x req_id = %lx", srch_param->srch_lid, 643 srch_param->srch_gid.gid_guid, srch_param->srch_grh_exists, 644 srch_param->srch_req_id); 645 646 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*ud_statep)) 647 648 /* didn't find the entry - so create new */ 649 ud_statep = kmem_zalloc(sizeof (ibcm_ud_state_data_t), KM_SLEEP); 650 651 mutex_init(&ud_statep->ud_state_mutex, NULL, MUTEX_DEFAULT, NULL); 652 cv_init(&ud_statep->ud_block_client_cv, NULL, CV_DRIVER, NULL); 653 654 /* Initialize some ud_statep fields */ 655 mutex_enter(&ud_statep->ud_state_mutex); 656 ud_statep->ud_hcap = hcap; 657 ud_statep->ud_req_id = srch_param->srch_req_id; 658 ud_statep->ud_ref_cnt = 1; 659 ud_statep->ud_grh_exists = srch_param->srch_grh_exists; 660 ud_statep->ud_sidr_req_lid = srch_param->srch_lid; 661 ud_statep->ud_sidr_req_gid = srch_param->srch_gid; 662 ud_statep->ud_mode = srch_param->srch_mode; 663 ud_statep->ud_max_cm_retries = ibcm_max_retries; 664 mutex_exit(&ud_statep->ud_state_mutex); 665 666 /* Update the list */ 667 ud_statep->ud_nextp = hcap->hca_sidr_list; 668 hcap->hca_sidr_list = ud_statep; 669 670 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*ud_statep)) 671 672 return (ud_statep); 673 } 674 675 676 /* 677 * ibcm_delete_ud_state_data: 678 * Deletes a given state structure 679 * 680 * Arguments are:- 681 * statep - statep to be deleted 682 * 683 * Return Values: NONE 684 */ 685 void 686 ibcm_delete_ud_state_data(ibcm_ud_state_data_t *ud_statep) 687 { 688 ibcm_ud_state_data_t *prevp, *headp; 689 ibcm_hca_info_t *hcap; 690 691 IBTF_DPRINTF_L4(cmlog, "ibcm_delete_ud_state_data: ud_statep 0x%p", 692 ud_statep); 693 694 if (ud_statep == NULL || ud_statep->ud_hcap == NULL) { 695 IBTF_DPRINTF_L2(cmlog, "ibcm_delete_ud_state_data: " 696 "ud_statep or hcap is NULL"); 697 return; 698 } 699 700 hcap = ud_statep->ud_hcap; 701 702 rw_enter(&hcap->hca_sidr_list_lock, RW_WRITER); 703 704 /* Next, remove this from the HCA SIDR list */ 705 if (hcap->hca_sidr_list != NULL) { 706 prevp = NULL; 707 headp = hcap->hca_sidr_list; 708 709 while (headp != NULL) { 710 /* delete the matching entry */ 711 if (headp == ud_statep) { 712 if (prevp) { 713 prevp->ud_nextp = headp->ud_nextp; 714 } else { 715 prevp = headp->ud_nextp; 716 hcap->hca_sidr_list = prevp; 717 } 718 break; 719 } 720 prevp = headp; 721 headp = headp->ud_nextp; 722 } 723 } 724 725 rw_exit(&hcap->hca_sidr_list_lock); 726 727 /* 728 * While ref_cnt > 0 729 * - implies someone else is accessing the statep (possibly in 730 * a timeout function handler etc.) 731 * - don't delete statep unless they are done otherwise potentially 732 * one could access released memory and panic. 733 */ 734 mutex_enter(&ud_statep->ud_state_mutex); 735 if (ud_statep->ud_ref_cnt > 0) { 736 ud_statep->ud_delete_state_data = B_TRUE; 737 IBTF_DPRINTF_L4(cmlog, "ibcm_delete_ud_state_data: " 738 "ud_statep 0x%p ud_ref_cnt = %x", ud_statep, 739 ud_statep->ud_ref_cnt); 740 mutex_exit(&ud_statep->ud_state_mutex); 741 return; 742 } 743 mutex_exit(&ud_statep->ud_state_mutex); 744 745 ibcm_dealloc_ud_state_data(ud_statep); 746 } 747 748 /* 749 * ibcm_ud_dealloc_state_data: 750 * Deallocates a given ud state structure 751 * 752 * Arguments are:- 753 * ud statep - ud statep to be deleted 754 * 755 * Return Values: NONE 756 */ 757 void 758 ibcm_dealloc_ud_state_data(ibcm_ud_state_data_t *ud_statep) 759 { 760 timeout_id_t timer_val; 761 762 IBTF_DPRINTF_L4(cmlog, "ibcm_dealloc_ud_state_data: ud_statep 0x%p", 763 ud_statep); 764 765 /* If timer is running - expire it */ 766 mutex_enter(&ud_statep->ud_state_mutex); 767 if (ud_statep->ud_timerid) { 768 timer_val = ud_statep->ud_timerid; 769 ud_statep->ud_timerid = 0; 770 mutex_exit(&ud_statep->ud_state_mutex); 771 (void) untimeout(timer_val); 772 IBTF_DPRINTF_L2(cmlog, "ibcm_dealloc_ud_state_data: " 773 "Unexpected timer id 0x%p ud_statep 0x%p", timer_val, 774 ud_statep); 775 } else 776 mutex_exit(&ud_statep->ud_state_mutex); 777 778 if (ud_statep->ud_stored_msg != NULL) { 779 (void) ibcm_free_out_msg( 780 ud_statep->ud_stored_reply_addr.ibmf_hdl, 781 &ud_statep->ud_stored_msg); 782 } 783 784 /* release the ref cnt on the associated ibmf qp */ 785 ASSERT(ud_statep->ud_stored_reply_addr.cm_qp_entry != NULL); 786 ibcm_release_qp(ud_statep->ud_stored_reply_addr.cm_qp_entry); 787 788 /* Ensure the thread doing ref cnt decr releases the mutex */ 789 mutex_enter(&ud_statep->ud_state_mutex); 790 mutex_exit(&ud_statep->ud_state_mutex); 791 792 /* now do the mutex_destroy() and cv_destroy() */ 793 mutex_destroy(&ud_statep->ud_state_mutex); 794 795 cv_destroy(&ud_statep->ud_block_client_cv); 796 797 /* free the req id on SIDR REQ sender side */ 798 if (ud_statep->ud_mode == IBCM_ACTIVE_MODE) 799 ibcm_free_reqid(ud_statep->ud_hcap, ud_statep->ud_req_id); 800 801 /* Decrement the resource on hcap */ 802 ibcm_dec_hca_res_cnt(ud_statep->ud_hcap); 803 804 /* free the statep */ 805 kmem_free(ud_statep, sizeof (ibcm_ud_state_data_t)); 806 } 807 808 809 /* 810 * ibcm_init_ids: 811 * Create the vmem arenas for the various global ids 812 * 813 * Arguments are:- 814 * NONE 815 * 816 * Return Values: ibcm_status_t 817 */ 818 819 ibcm_status_t 820 ibcm_init_ids(void) 821 { 822 timespec_t tv; 823 824 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(ibcm_local_sid_arena)) 825 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(ibcm_local_sid_seed)) 826 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(ibcm_local_cid_seed)) 827 828 ibcm_local_sid_arena = vmem_create("ibcm_local_sid", 829 (void *)IBCM_INITIAL_SID, IBCM_MAX_LOCAL_SIDS, 1, NULL, NULL, NULL, 830 0, VM_SLEEP | VMC_IDENTIFIER); 831 832 if (!ibcm_local_sid_arena) 833 return (IBCM_FAILURE); 834 835 /* create a random starting value for local service ids */ 836 gethrestime(&tv); 837 ibcm_local_sid_seed = ((uint64_t)tv.tv_sec << 20) & 0x007FFFFFFFF00000; 838 ASSERT((ibcm_local_sid_seed & IB_SID_AGN_MASK) == 0); 839 ibcm_local_sid_seed |= IB_SID_AGN_LOCAL; 840 ibcm_local_cid_seed = (ib_com_id_t)tv.tv_sec; 841 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(ibcm_local_sid_arena)) 842 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(ibcm_local_sid_seed)) 843 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(ibcm_local_cid_seed)) 844 845 return (IBCM_SUCCESS); 846 } 847 848 849 /* 850 * ibcm_init_hca_ids: 851 * Create the vmem arenas for the various hca level ids 852 * 853 * Arguments are:- 854 * hcap pointer to ibcm_hca_info_t 855 * 856 * Return Values: ibcm_status_t 857 */ 858 ibcm_status_t 859 ibcm_init_hca_ids(ibcm_hca_info_t *hcap) 860 { 861 hcap->hca_comid_arena = vmem_create("ibcm_com_ids", 862 (void *)IBCM_INITIAL_COMID, IBCM_MAX_COMIDS, 863 1, NULL, NULL, NULL, 0, VM_SLEEP | VMC_IDENTIFIER); 864 865 if (!hcap->hca_comid_arena) 866 return (IBCM_FAILURE); 867 868 hcap->hca_reqid_arena = vmem_create("ibcm_req_ids", 869 (void *)IBCM_INITIAL_REQID, IBCM_MAX_REQIDS, 870 1, NULL, NULL, NULL, 0, VM_SLEEP | VMC_IDENTIFIER); 871 872 if (!hcap->hca_reqid_arena) { 873 vmem_destroy(hcap->hca_comid_arena); 874 return (IBCM_FAILURE); 875 } 876 877 return (IBCM_SUCCESS); 878 } 879 880 /* 881 * ibcm_free_ids: 882 * Destroy the vmem arenas for the various ids 883 * 884 * Arguments are:- 885 * NONE 886 * 887 * Return Values: NONE 888 */ 889 void 890 ibcm_fini_ids(void) 891 { 892 /* All arenas shall be valid */ 893 vmem_destroy(ibcm_local_sid_arena); 894 } 895 896 /* 897 * ibcm_free_hca_ids: 898 * Destroy the vmem arenas for the various ids 899 * 900 * Arguments are:- 901 * hcap pointer to ibcm_hca_info_t 902 * 903 * Return Values: NONE 904 */ 905 void 906 ibcm_fini_hca_ids(ibcm_hca_info_t *hcap) 907 { 908 /* All arenas shall be valid */ 909 vmem_destroy(hcap->hca_comid_arena); 910 vmem_destroy(hcap->hca_reqid_arena); 911 } 912 913 /* Communication id management routines ie., allocate, free up comids */ 914 915 /* 916 * ibcm_alloc_comid: 917 * Allocate a new communication id 918 * 919 * Arguments are:- 920 * hcap : pointer to ibcm_hca_info_t 921 * comid: pointer to the newly allocated communication id 922 * 923 * Return Values: ibt_status_t 924 */ 925 ibcm_status_t 926 ibcm_alloc_comid(ibcm_hca_info_t *hcap, ib_com_id_t *comidp) 927 { 928 ib_com_id_t comid; 929 930 /* Use next fit, so least recently used com id is allocated */ 931 comid = (ib_com_id_t)(uintptr_t)vmem_alloc(hcap->hca_comid_arena, 1, 932 VM_SLEEP | VM_NEXTFIT); 933 934 IBTF_DPRINTF_L4(cmlog, "ibcm_alloc_comid: hcap 0x%p comid 0x%lX", hcap, 935 comid); 936 937 /* 938 * As comid is 32 bits, and maximum connections possible are 2^24 939 * per hca, comid allocation would never fail 940 */ 941 *comidp = comid + ibcm_local_cid_seed; 942 if (comid == 0) { 943 IBTF_DPRINTF_L2(cmlog, "ibcm_alloc_comid: hcap 0x%p" 944 "no more comids available", hcap); 945 return (IBCM_FAILURE); 946 } 947 948 return (IBCM_SUCCESS); 949 } 950 951 /* 952 * ibcm_free_comid: 953 * Releases the given Communication Id 954 * 955 * Arguments are: 956 * hcap : pointer to ibcm_hca_info_t 957 * comid : Communication id to be free'd 958 * 959 * Return Values: NONE 960 */ 961 void 962 ibcm_free_comid(ibcm_hca_info_t *hcap, ib_com_id_t comid) 963 { 964 IBTF_DPRINTF_L4(cmlog, "ibcm_free_comid: hcap 0x%p" 965 "comid %x", hcap, comid); 966 comid -= ibcm_local_cid_seed; 967 vmem_free(hcap->hca_comid_arena, (void *)(uintptr_t)comid, 1); 968 } 969 970 /* Allocate and Free local service ids */ 971 972 /* 973 * ibcm_alloc_local_sids: 974 * Create and destroy the vmem arenas for the service ids 975 * 976 * Arguments are:- 977 * Number of contiguous SIDs needed 978 * 979 * Return Values: starting SID 980 */ 981 ib_svc_id_t 982 ibcm_alloc_local_sids(int num_sids) 983 { 984 ib_svc_id_t sid; 985 986 sid = (ib_svc_id_t)(uintptr_t)vmem_alloc(ibcm_local_sid_arena, 987 num_sids, VM_SLEEP | VM_NEXTFIT); 988 989 IBTF_DPRINTF_L4(cmlog, "ibcm_alloc_local_sids: ServiceID 0x%llX " 990 "num_sids %d", sid, num_sids); 991 if (sid == 0) { 992 IBTF_DPRINTF_L2(cmlog, "ibcm_alloc_local_sids: " 993 "no more local sids available"); 994 } else { 995 ASSERT((ibcm_local_sid_seed & IB_SID_AGN_MASK) == 996 IB_SID_AGN_LOCAL); 997 sid += ibcm_local_sid_seed; 998 IBTF_DPRINTF_L4(cmlog, "ibcm_alloc_local_sids: Success: " 999 "allocated 0x%llX:%d", sid, num_sids); 1000 } 1001 return (sid); 1002 } 1003 1004 /* 1005 * ibcm_free_local_sids: 1006 * Releases the given Local service id 1007 * 1008 * Arguments are: 1009 * num_sids: Number of local service id's to be free'd 1010 * service_id: Starting local service id that needs to be free'd 1011 * 1012 * Return Values: NONE 1013 */ 1014 void 1015 ibcm_free_local_sids(ib_svc_id_t service_id, int num_sids) 1016 { 1017 service_id -= ibcm_local_sid_seed; 1018 IBTF_DPRINTF_L4(cmlog, "ibcm_free_local_sids: " 1019 "service_id 0x%llX num_sids %d", service_id, num_sids); 1020 vmem_free(ibcm_local_sid_arena, 1021 (void *)(uintptr_t)service_id, num_sids); 1022 } 1023 1024 /* Allocate and free request id routines for SIDR */ 1025 1026 /* 1027 * ibcm_alloc_reqid: 1028 * Allocate a new SIDR REQ request id 1029 * 1030 * Arguments are:- 1031 * hcap : pointer to ibcm_hca_info_t 1032 * *reqid : pointer to the new request id returned 1033 * 1034 * Return Values: ibcm_status_t 1035 */ 1036 ibcm_status_t 1037 ibcm_alloc_reqid(ibcm_hca_info_t *hcap, uint32_t *reqid) 1038 { 1039 /* Use next fit, so least recently used com id is allocated */ 1040 *reqid = (uint32_t)(uintptr_t)vmem_alloc(hcap->hca_reqid_arena, 1, 1041 VM_SLEEP | VM_NEXTFIT); 1042 1043 IBTF_DPRINTF_L4(cmlog, "ibcm_alloc_reqid: hcap 0x%p reqid %x", hcap, 1044 *reqid); 1045 if (!(*reqid)) { 1046 IBTF_DPRINTF_L2(cmlog, "ibcm_alloc_reqid: " 1047 "no more req ids available"); 1048 return (IBCM_FAILURE); 1049 } 1050 return (IBCM_SUCCESS); 1051 } 1052 1053 /* 1054 * ibcm_free_reqid: 1055 * Releases the given SIDR REQ request id 1056 * 1057 * Arguments are: 1058 * hcap : pointer to ibcm_hca_info_t 1059 * reqid : Request id to be free'd 1060 * 1061 * Return Values: NONE 1062 */ 1063 void 1064 ibcm_free_reqid(ibcm_hca_info_t *hcap, uint32_t reqid) 1065 { 1066 IBTF_DPRINTF_L4(cmlog, "ibcm_free_reqid: hcap 0x%p reqid %x", hcap, 1067 reqid); 1068 vmem_free(hcap->hca_reqid_arena, (void *)(uintptr_t)reqid, 1); 1069 } 1070 1071 /* 1072 * ibcm_generate_tranid: 1073 * Generate a new transaction id based on args 1074 * 1075 * Arguments are:- 1076 * event_type CM Message REQ/DREQ/LAP 1077 * id 32 bit identifier 1078 * cm_tran_priv CM private data to be filled in top 28 MSB bits of 1079 * tran id 1080 * 1081 * 1082 * Return Value: uint64_t 1083 */ 1084 uint64_t 1085 ibcm_generate_tranid(uint8_t event, uint32_t id, uint32_t cm_tran_priv) 1086 { 1087 /* 1088 * copy comid to bits 31-0 of tran id, 1089 * attr id to bits 35-32 of tran id, 1090 * cm_priv to bits 63-36 of tran id 1091 */ 1092 if (cm_tran_priv == 0) 1093 /* 1094 * The below ensures that no duplicate transaction id is 1095 * generated atleast for next 6 months. Calculations: 1096 * (2^28)/(1000 * 60 * 24 * 30) = 6 approx 1097 */ 1098 cm_tran_priv = gethrtime() >> 20; /* ~time in ms */ 1099 1100 return ((((uint64_t)cm_tran_priv << 36) | (uint64_t)event << 32) | id); 1101 } 1102 1103 #ifdef DEBUG 1104 1105 /* 1106 * ibcm_decode_tranid: 1107 * Decodes a given transaction id, assuming certain format. 1108 * 1109 * Arguments are:- 1110 * tran_id Transaction id to be decoded 1111 * cm_tran_priv CM private data retrieved from transaction id 1112 * 1113 * Return Value: None 1114 */ 1115 void 1116 ibcm_decode_tranid(uint64_t tran_id, uint32_t *cm_tran_priv) 1117 { 1118 ib_com_id_t id; 1119 ibcm_event_type_t event; 1120 1121 id = tran_id & 0xFFFFFFFF; 1122 event = (tran_id >> 32) & 0xF; 1123 1124 IBTF_DPRINTF_L5(cmlog, "ibcm_decode_tranid: id = 0x%lx, event = %x", 1125 id, event); 1126 1127 if (cm_tran_priv) { 1128 *cm_tran_priv = tran_id >> 36; 1129 IBTF_DPRINTF_L5(cmlog, "ibcm_decode_tranid: " 1130 "cm_tran_priv = %x", *cm_tran_priv); 1131 } 1132 } 1133 1134 #endif 1135 1136 /* 1137 * Service ID entry create and lookup functions 1138 */ 1139 1140 /* 1141 * ibcm_svc_compare: 1142 * - AVL svc tree node compare 1143 * 1144 * Arguments: 1145 * p1 : pointer to local comid 1146 * p2 : pointer to passed ibcm_state_data_t 1147 * 1148 * Return values: 1149 * 0 : match found 1150 * -1 : no match but insert to left side of the tree 1151 * +1 : no match but insert to right side of the tree 1152 */ 1153 int 1154 ibcm_svc_compare(const void *p1, const void *p2) 1155 { 1156 ibcm_svc_lookup_t *sidp = (ibcm_svc_lookup_t *)p1; 1157 ibcm_svc_info_t *svcp = (ibcm_svc_info_t *)p2; 1158 ib_svc_id_t start_sid = sidp->sid; 1159 ib_svc_id_t end_sid = start_sid + sidp->num_sids - 1; 1160 1161 IBTF_DPRINTF_L5(cmlog, "ibcm_svc_compare: " 1162 "sid: 0x%llx, numsids: %d, node_sid: 0x%llx node_num_sids: %d", 1163 sidp->sid, sidp->num_sids, svcp->svc_id, svcp->svc_num_sids); 1164 1165 ASSERT(MUTEX_HELD(&ibcm_svc_info_lock)); 1166 1167 if (svcp->svc_id > end_sid) 1168 return (-1); 1169 if (svcp->svc_id + svcp->svc_num_sids - 1 < start_sid) 1170 return (+1); 1171 return (0); /* means there is some overlap of SIDs */ 1172 } 1173 1174 1175 /* 1176 * ibcm_create_svc_entry: 1177 * Make sure no conflicting entry exists, then allocate it. 1178 * Fill in the critical "look up" details that are provided 1179 * in the arguments before dropping the lock. 1180 * 1181 * Return values: 1182 * Pointer to ibcm_svc_info_t, if created, otherwise NULL. 1183 */ 1184 ibcm_svc_info_t * 1185 ibcm_create_svc_entry(ib_svc_id_t sid, int num_sids) 1186 { 1187 ibcm_svc_info_t *svcp; 1188 ibcm_svc_info_t *svcinfop; 1189 ibcm_svc_lookup_t svc; 1190 avl_index_t where = 0; 1191 1192 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*svcinfop)) 1193 1194 /* assume success, and avoid kmem while holding the writer lock */ 1195 svcinfop = kmem_zalloc(sizeof (*svcinfop), KM_SLEEP); 1196 svcinfop->svc_id = sid; 1197 svcinfop->svc_num_sids = num_sids; 1198 1199 svc.sid = sid; 1200 svc.num_sids = num_sids; 1201 1202 mutex_enter(&ibcm_svc_info_lock); 1203 #ifdef __lock_lint 1204 ibcm_svc_compare(NULL, NULL); 1205 #endif 1206 svcp = avl_find(&ibcm_svc_avl_tree, &svc, &where); 1207 if (svcp != NULL) { /* overlab exists */ 1208 mutex_exit(&ibcm_svc_info_lock); 1209 kmem_free(svcinfop, sizeof (*svcinfop)); 1210 return (NULL); 1211 } 1212 avl_insert(&ibcm_svc_avl_tree, (void *)svcinfop, where); 1213 mutex_exit(&ibcm_svc_info_lock); 1214 1215 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*svcinfop)) 1216 1217 return (svcinfop); 1218 } 1219 1220 /* 1221 * ibcm_find_svc_entry: 1222 * Finds a ibcm_svc_info_t entry into the CM's global table. 1223 * The search done here assumes the list is sorted by SID. 1224 * 1225 * Arguments are: 1226 * sid - Service ID to look up 1227 * 1228 * Return values: 1229 * Pointer to ibcm_svc_info_t, if found, otherwise NULL. 1230 */ 1231 ibcm_svc_info_t * 1232 ibcm_find_svc_entry(ib_svc_id_t sid) 1233 { 1234 ibcm_svc_info_t *svcp; 1235 ibcm_svc_lookup_t svc; 1236 1237 IBTF_DPRINTF_L3(cmlog, "ibcm_find_svc_entry: finding SID 0x%llX", sid); 1238 1239 ASSERT(MUTEX_HELD(&ibcm_svc_info_lock)); 1240 1241 svc.sid = sid; 1242 svc.num_sids = 1; 1243 #ifdef __lock_lint 1244 ibcm_svc_compare(NULL, NULL); 1245 #endif 1246 svcp = avl_find(&ibcm_svc_avl_tree, &svc, NULL); 1247 if (svcp != NULL) { 1248 IBTF_DPRINTF_L3(cmlog, "ibcm_find_svc_entry: " 1249 "found SID = 0x%llX", sid); 1250 return (svcp); /* found it */ 1251 } 1252 IBTF_DPRINTF_L3(cmlog, "ibcm_find_svc_entry: SID %llX not found", sid); 1253 return (NULL); 1254 } 1255 1256 /* 1257 * ibcm_alloc_ibmf_msg: 1258 * Allocate an ibmf message structure and the additional memory required for 1259 * sending an outgoing CM mad. The ibmf message structure contains two 1260 * ibmf_msg_bufs_t fields, one for the incoming MAD and one for the outgoing 1261 * MAD. The CM must allocate the memory for the outgoing MAD. The msg_buf 1262 * field has three buffers: the mad header, the class header, and the class 1263 * data. To simplify the code and reduce the number of kmem_zalloc() calls, 1264 * ibcm_alloc_ibmf_msg will allocate one buffer and set the pointers to the 1265 * right offsets. No class header is needed so only the mad header and class 1266 * data fields are used. 1267 */ 1268 ibt_status_t 1269 ibcm_alloc_out_msg(ibmf_handle_t ibmf_handle, ibmf_msg_t **ibmf_msgpp, 1270 uint8_t method) 1271 { 1272 ib_mad_hdr_t *output_mad_hdr; 1273 int sa_retval; 1274 1275 if ((sa_retval = 1276 ibmf_alloc_msg(ibmf_handle, IBMF_ALLOC_SLEEP, ibmf_msgpp)) != 1277 IBMF_SUCCESS) { 1278 IBTF_DPRINTF_L1(cmlog, "ibcm_alloc_out_msg: " 1279 "ibmf_alloc_msg failed with IBMF_ALLOC_SLEEP"); 1280 return (ibcm_ibmf_analyze_error(sa_retval)); 1281 } 1282 1283 (*ibmf_msgpp)->im_msgbufs_send.im_bufs_mad_hdr = kmem_zalloc( 1284 IBCM_MAD_SIZE, KM_SLEEP); 1285 1286 (*ibmf_msgpp)->im_msgbufs_send.im_bufs_cl_data_len = IBCM_MSG_SIZE; 1287 (*ibmf_msgpp)->im_msgbufs_send.im_bufs_cl_data = 1288 (uchar_t *)((*ibmf_msgpp)->im_msgbufs_send.im_bufs_mad_hdr) + 1289 IBCM_MAD_HDR_SIZE; 1290 1291 /* initialize generic CM MAD header fields */ 1292 output_mad_hdr = IBCM_OUT_HDRP((*ibmf_msgpp)); 1293 output_mad_hdr->BaseVersion = IBCM_MAD_BASE_VERSION; 1294 output_mad_hdr->MgmtClass = MAD_MGMT_CLASS_COMM_MGT; 1295 output_mad_hdr->ClassVersion = IBCM_MAD_CLASS_VERSION; 1296 output_mad_hdr->R_Method = method; 1297 1298 return (IBT_SUCCESS); 1299 } 1300 1301 /* 1302 * ibcm_free_ibmf_msg: 1303 * Frees the buffer and ibmf message associated with an outgoing CM message. 1304 * This function should only be used to free messages created by 1305 * ibcm_alloc_out_msg. Will return IBCM_FAILURE if the ibmf_free_msg() call 1306 * fails and IBCM_SUCCESS otherwise. 1307 */ 1308 ibcm_status_t 1309 ibcm_free_out_msg(ibmf_handle_t ibmf_handle, ibmf_msg_t **ibmf_msgpp) 1310 { 1311 int ibmf_status; 1312 1313 kmem_free((*ibmf_msgpp)->im_msgbufs_send.im_bufs_mad_hdr, 1314 IBCM_MAD_SIZE); 1315 1316 if ((ibmf_status = ibmf_free_msg(ibmf_handle, ibmf_msgpp)) != 1317 IBMF_SUCCESS) { 1318 IBTF_DPRINTF_L2(cmlog, "ibcm_free_out_msg: " 1319 "ibmf_free_msg failed %d", ibmf_status); 1320 return (IBCM_FAILURE); 1321 } else 1322 return (IBCM_SUCCESS); 1323 } 1324 1325 ibcm_qp_list_t * 1326 ibcm_find_qp(ibcm_hca_info_t *hcap, int port_no, ib_pkey_t pkey) 1327 { 1328 ibcm_qp_list_t *entry; 1329 ibmf_qp_handle_t ibmf_qp; 1330 int ibmf_status; 1331 1332 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*entry)) 1333 1334 mutex_enter(&ibcm_qp_list_lock); 1335 1336 /* 1337 * CM currently does not track port up and down status. If tracking of 1338 * " port status" is added in the future, then CM could be optimized to 1339 * re-use other ports on hcap, if the port associated with the above 1340 * port_no is down. But, the issue of "reachability" needs to be 1341 * handled, before selecting an alternative port different from above. 1342 */ 1343 entry = hcap->hca_port_info[port_no-1].port_qplist; 1344 while (entry != NULL) { 1345 if (entry->qp_pkey == pkey) { 1346 ++entry->qp_ref_cnt; 1347 mutex_exit(&ibcm_qp_list_lock); 1348 return (entry); 1349 } 1350 entry = entry->qp_next; 1351 } 1352 1353 /* 1354 * entry not found, attempt to alloc a qp 1355 * This may be optimized in the future, to allocate ibmf qp's 1356 * once the "CM mgmt pkeys" are precisely known. 1357 */ 1358 ibmf_status = ibmf_alloc_qp( 1359 hcap->hca_port_info[port_no-1].port_ibmf_hdl, pkey, IB_GSI_QKEY, 1360 IBMF_ALT_QP_MAD_NO_RMPP, &ibmf_qp); 1361 1362 if (ibmf_status != IBMF_SUCCESS) { 1363 mutex_exit(&ibcm_qp_list_lock); 1364 IBTF_DPRINTF_L2(cmlog, "ibcm_find_qp: failed to alloc IBMF QP" 1365 "for Pkey = %x port_no = %x status = %d hcaguid = %llXp", 1366 pkey, port_no, ibmf_status, hcap->hca_guid); 1367 /* 1368 * This may be optimized in the future, so as CM would attempt 1369 * to re-use other QP's whose ref cnt is 0 in the respective 1370 * port_qplist, by doing an ibmf_modify_qp with pkey above. 1371 */ 1372 return (NULL); 1373 } 1374 1375 entry = kmem_alloc(sizeof (ibcm_qp_list_t), KM_SLEEP); 1376 entry->qp_next = hcap->hca_port_info[port_no-1].port_qplist; 1377 hcap->hca_port_info[port_no-1].port_qplist = entry; 1378 entry->qp_cm = ibmf_qp; 1379 entry->qp_ref_cnt = 1; 1380 entry->qp_pkey = pkey; 1381 entry->qp_port = &(hcap->hca_port_info[port_no-1]); 1382 1383 mutex_exit(&ibcm_qp_list_lock); 1384 1385 /* set-up the handler */ 1386 ibmf_status = ibmf_setup_async_cb( 1387 hcap->hca_port_info[port_no-1].port_ibmf_hdl, ibmf_qp, 1388 ibcm_recv_cb, entry, 0); 1389 1390 ASSERT(ibmf_status == IBMF_SUCCESS); 1391 1392 #ifdef DEBUG 1393 ibcm_query_qp(hcap->hca_port_info[port_no-1].port_ibmf_hdl, ibmf_qp); 1394 #endif 1395 1396 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*entry)) 1397 1398 return (entry); 1399 } 1400 1401 void 1402 ibcm_release_qp(ibcm_qp_list_t *cm_qp_entry) 1403 { 1404 mutex_enter(&ibcm_qp_list_lock); 1405 --cm_qp_entry->qp_ref_cnt; 1406 ASSERT(cm_qp_entry->qp_ref_cnt >= 0); 1407 mutex_exit(&ibcm_qp_list_lock); 1408 } 1409 1410 1411 /* called holding the ibcm_qp_list_lock mutex */ 1412 ibcm_status_t 1413 ibcm_free_qp(ibcm_qp_list_t *cm_qp_entry) 1414 { 1415 int ibmf_status; 1416 1417 IBTF_DPRINTF_L5(cmlog, "ibcm_free_qp: qp_hdl %p ref_cnt %d pkey %x", 1418 cm_qp_entry->qp_cm, cm_qp_entry->qp_ref_cnt, cm_qp_entry->qp_pkey); 1419 1420 /* check, there are no users of this ibmf qp */ 1421 if (cm_qp_entry->qp_ref_cnt != 0) 1422 return (IBCM_FAILURE); 1423 1424 /* Tear down the receive callback */ 1425 ibmf_status = ibmf_tear_down_async_cb( 1426 cm_qp_entry->qp_port->port_ibmf_hdl, cm_qp_entry->qp_cm, 0); 1427 if (ibmf_status != IBMF_SUCCESS) { 1428 IBTF_DPRINTF_L2(cmlog, "ibcm_free_qp: " 1429 "ibmf_tear_down_async_cb failed %d port_num %d", 1430 ibmf_status, cm_qp_entry->qp_port->port_num); 1431 return (IBCM_FAILURE); 1432 } 1433 1434 ibmf_status = ibmf_free_qp(cm_qp_entry->qp_port->port_ibmf_hdl, 1435 &cm_qp_entry->qp_cm, 0); 1436 if (ibmf_status != IBMF_SUCCESS) { 1437 IBTF_DPRINTF_L2(cmlog, "ibcm_free_qp: ibmf_free_qp failed for" 1438 " ibmf_status %d qp hdl %p port_no %x", ibmf_status, 1439 cm_qp_entry->qp_cm, cm_qp_entry->qp_port->port_num); 1440 return (IBCM_FAILURE); 1441 } 1442 1443 return (IBCM_SUCCESS); 1444 } 1445 1446 ibcm_status_t 1447 ibcm_free_allqps(ibcm_hca_info_t *hcap, int port_no) 1448 { 1449 ibcm_qp_list_t *entry, *freed; 1450 ibcm_status_t ibcm_status = IBCM_SUCCESS; 1451 1452 IBTF_DPRINTF_L5(cmlog, "ibcm_free_allqps: hcap %p port_no %d", hcap, 1453 port_no); 1454 1455 mutex_enter(&ibcm_qp_list_lock); 1456 entry = hcap->hca_port_info[port_no-1].port_qplist; 1457 while ((entry != NULL) && 1458 ((ibcm_status = ibcm_free_qp(entry)) == IBCM_SUCCESS)) { 1459 freed = entry; 1460 entry = entry->qp_next; 1461 kmem_free(freed, sizeof (ibcm_qp_list_t)); 1462 } 1463 1464 if (ibcm_status != IBCM_SUCCESS) /* sanity the linked list */ 1465 hcap->hca_port_info[port_no-1].port_qplist = entry; 1466 else /* all ibmf qp's of port must have been free'd successfully */ 1467 hcap->hca_port_info[port_no-1].port_qplist = NULL; 1468 1469 mutex_exit(&ibcm_qp_list_lock); 1470 return (ibcm_status); 1471 } 1472 1473 /* 1474 * ibt_bind_service() and ibt_get_paths() needs the following helper function 1475 * to handle endianess in case of Service Data. 1476 */ 1477 void 1478 ibcm_swizzle_from_srv(ibt_srv_data_t *sb_data, uint8_t *service_bytes) 1479 { 1480 uint8_t *p8 = service_bytes; 1481 uint16_t *p16; 1482 uint32_t *p32; 1483 uint64_t *p64; 1484 int i; 1485 1486 for (i = 0; i < 16; i++) 1487 *p8++ = sb_data->s_data8[i]; 1488 1489 p16 = (uint16_t *)p8; 1490 for (i = 0; i < 8; i++) 1491 *p16++ = h2b16(sb_data->s_data16[i]); 1492 1493 p32 = (uint32_t *)p16; 1494 for (i = 0; i < 4; i++) 1495 *p32++ = h2b32(sb_data->s_data32[i]); 1496 1497 p64 = (uint64_t *)p32; 1498 for (i = 0; i < 2; i++) 1499 *p64++ = h2b64(sb_data->s_data64[i]); 1500 } 1501 1502 void 1503 ibcm_swizzle_to_srv(uint8_t *service_bytes, ibt_srv_data_t *sb_data) 1504 { 1505 uint8_t *p8 = service_bytes; 1506 uint16_t *p16; 1507 uint32_t *p32; 1508 uint64_t *p64; 1509 int i; 1510 1511 for (i = 0; i < 16; i++) 1512 sb_data->s_data8[i] = *p8++; 1513 1514 p16 = (uint16_t *)p8; 1515 for (i = 0; i < 8; i++) 1516 sb_data->s_data16[i] = h2b16(*p16++); 1517 1518 p32 = (uint32_t *)p16; 1519 for (i = 0; i < 4; i++) 1520 sb_data->s_data32[i] = h2b32(*p32++); 1521 p64 = (uint64_t *)p32; 1522 1523 for (i = 0; i < 2; i++) 1524 sb_data->s_data64[i] = h2b64(*p64++); 1525 } 1526 1527 /* Trace related functions */ 1528 1529 void 1530 ibcm_init_conn_trace(ibcm_state_data_t *sp) 1531 { 1532 IBTF_DPRINTF_L5(cmlog, "ibcm_init_conn_trace: statep %p", sp); 1533 1534 /* Initialize trace related fields */ 1535 1536 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*sp->conn_trace)) 1537 sp->conn_trace = kmem_zalloc(sizeof (ibcm_conn_trace_t), KM_SLEEP); 1538 if ((ibcm_enable_trace & 1) == 0) 1539 sp->conn_trace->conn_base_tm = gethrtime(); 1540 sp->conn_trace->conn_allocated_trcnt = ibcm_conn_max_trcnt; 1541 sp->conn_trace->conn_trace_events = 1542 kmem_zalloc(sp->conn_trace->conn_allocated_trcnt, KM_SLEEP); 1543 sp->conn_trace->conn_trace_event_times = 1544 kmem_zalloc(sp->conn_trace->conn_allocated_trcnt * 1545 sizeof (tm_diff_type), KM_SLEEP); 1546 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*sp->conn_trace)) 1547 } 1548 1549 void 1550 ibcm_fini_conn_trace(ibcm_state_data_t *statep) 1551 { 1552 IBTF_DPRINTF_L5(cmlog, "ibcm_fini_conn_trace: statep %p tracep %p", 1553 statep, statep->conn_trace); 1554 1555 /* free the trace data */ 1556 if (statep->conn_trace) { 1557 if (statep->conn_trace->conn_trace_events) 1558 kmem_free(statep->conn_trace->conn_trace_events, 1559 statep->conn_trace->conn_allocated_trcnt); 1560 if (statep->conn_trace->conn_trace_event_times) 1561 kmem_free(statep->conn_trace->conn_trace_event_times, 1562 statep->conn_trace->conn_allocated_trcnt * 1563 sizeof (tm_diff_type)); 1564 1565 kmem_free(statep->conn_trace, sizeof (ibcm_conn_trace_t)); 1566 } 1567 } 1568 1569 void 1570 ibcm_insert_trace(void *statep, ibcm_state_rc_trace_qualifier_t event_qualifier) 1571 { 1572 ibcm_conn_trace_t *conn_trace; 1573 uint8_t conn_trace_ind; 1574 hrtime_t time_diff; 1575 hrtime_t hrt; 1576 1577 if (!(((ibcm_state_data_t *)statep)->conn_trace)) 1578 return; 1579 1580 conn_trace = ((ibcm_state_data_t *)statep)->conn_trace; 1581 1582 if (!conn_trace->conn_trace_events) 1583 return; 1584 1585 IBTF_DPRINTF_L5(cmlog, "ibcm_insert_trace: statep %p event %d", 1586 statep, event_qualifier); 1587 1588 mutex_enter(&ibcm_trace_mutex); 1589 1590 /* No more trace memory available, hence return */ 1591 if (conn_trace->conn_trace_ind == conn_trace->conn_allocated_trcnt) { 1592 mutex_exit(&ibcm_trace_mutex); 1593 return; 1594 } else 1595 ++conn_trace->conn_trace_ind; 1596 1597 conn_trace_ind = conn_trace->conn_trace_ind - 1; 1598 1599 conn_trace->conn_trace_events[conn_trace_ind] = event_qualifier; 1600 1601 if ((ibcm_enable_trace & 1) == 0) { 1602 hrt = gethrtime(); 1603 time_diff = (hrt - conn_trace->conn_base_tm) >> 10; 1604 if (time_diff >= TM_DIFF_MAX) { 1605 /* RESET, future times are relative to new base time. */ 1606 conn_trace->conn_base_tm = hrt; 1607 time_diff = 0; 1608 } 1609 conn_trace->conn_trace_event_times[conn_trace_ind] = time_diff; 1610 } 1611 1612 mutex_exit(&ibcm_trace_mutex); 1613 1614 IBTF_DPRINTF_L5(cmlog, "ibcm_insert_trace: statep %p inserted event %d", 1615 statep, event_qualifier); 1616 } 1617 1618 void 1619 ibcm_dump_conn_trace(void *statep) 1620 { 1621 IBTF_DPRINTF_L5(cmlog, "ibcm_dump_conn_trace: statep %p", 1622 statep); 1623 1624 mutex_enter(&ibcm_trace_print_mutex); 1625 ibcm_debug_buf[0] = '\0'; 1626 ibcm_dump_conn_trbuf(statep, "ibcm: ", ibcm_debug_buf, 1627 IBCM_DEBUG_BUF_SIZE); 1628 if (ibcm_debug_buf[0] != '\0') 1629 IBTF_DPRINTF_L2(cmlog, "\n%s", ibcm_debug_buf); 1630 1631 #ifdef DEBUG 1632 1633 if (ibcm_test_mode > 1) 1634 cmn_err(CE_CONT, "IBCM DEBUG TRACE:\n%s", ibcm_debug_buf); 1635 #endif 1636 1637 mutex_exit(&ibcm_trace_print_mutex); 1638 } 1639 1640 void 1641 ibcm_dump_conn_trbuf(void *statep, char *line_prefix, char *buf, int buf_size) 1642 { 1643 ibcm_conn_trace_t *conn_trace; 1644 int tr_ind; 1645 ibcm_state_data_t *sp; 1646 int cur_size = 0; /* size of item copied */ 1647 int rem_size; /* remaining size in trace buffer */ 1648 int next_data = 0; /* location where next item copied */ 1649 1650 if ((buf == NULL) || (buf_size <= 0)) 1651 return; 1652 1653 sp = (ibcm_state_data_t *)statep; 1654 1655 if (!sp->conn_trace) 1656 return; 1657 1658 conn_trace = sp->conn_trace; 1659 1660 if (!conn_trace->conn_trace_events) 1661 return; 1662 1663 rem_size = buf_size; 1664 1665 /* Print connection level global data */ 1666 1667 /* Print statep, local comid, local qpn */ 1668 cur_size = snprintf(&buf[next_data], rem_size, "%s%s0x%p\n%s%s0x%p\n" 1669 "%s%s0x%x/%llx/%d\n%s%s0x%x\n%s%s0x%x/%llx\n%s%s0x%x\n%s%s%llu\n", 1670 line_prefix, event_str[IBCM_DISPLAY_SID], (void *)sp, 1671 line_prefix, event_str[IBCM_DISPLAY_CHAN], (void *)sp->channel, 1672 line_prefix, event_str[IBCM_DISPLAY_LCID], sp->local_comid, 1673 (longlong_t)sp->local_hca_guid, sp->prim_port, 1674 line_prefix, event_str[IBCM_DISPLAY_LQPN], sp->local_qpn, 1675 line_prefix, event_str[IBCM_DISPLAY_RCID], sp->remote_comid, 1676 (longlong_t)sp->remote_hca_guid, 1677 line_prefix, event_str[IBCM_DISPLAY_RQPN], sp->remote_qpn, 1678 line_prefix, event_str[IBCM_DISPLAY_TM], conn_trace->conn_base_tm); 1679 1680 rem_size = rem_size - cur_size; 1681 if (rem_size <= 0) { 1682 buf[buf_size-1] = '\n'; 1683 return; 1684 } 1685 1686 next_data = next_data + cur_size; 1687 1688 for (tr_ind = 0; tr_ind < conn_trace->conn_trace_ind; tr_ind++) { 1689 cur_size = snprintf(&buf[next_data], rem_size, 1690 "%s%sTM_DIFF %u\n", line_prefix, 1691 event_str[conn_trace->conn_trace_events[tr_ind]], 1692 conn_trace->conn_trace_event_times[tr_ind]); 1693 rem_size = rem_size - cur_size; 1694 if (rem_size <= 0) { 1695 buf[buf_size-1] = '\n'; 1696 return; 1697 } 1698 next_data = next_data + cur_size; 1699 } 1700 1701 buf[next_data] = '\0'; 1702 IBTF_DPRINTF_L5(cmlog, "ibcm_dump_conn_trbuf: statep %p " 1703 "debug buf size %d bytes", statep, next_data); 1704 } 1705 1706 1707 #ifdef DEBUG 1708 1709 void 1710 ibcm_query_qp(ibmf_handle_t ibmf_hdl, ibmf_qp_handle_t ibmf_qp) 1711 { 1712 uint8_t qp_port_num; 1713 ib_qpn_t qp_num; 1714 ib_pkey_t qp_pkey; 1715 ib_qkey_t qp_qkey; 1716 int ibmf_status; 1717 1718 if (ibmf_qp == IBMF_QP_HANDLE_DEFAULT) { 1719 IBTF_DPRINTF_L4(cmlog, "ibcm_query_qp: QP1"); 1720 return; 1721 } 1722 1723 ibmf_status = 1724 ibmf_query_qp(ibmf_hdl, ibmf_qp, &qp_num, &qp_pkey, &qp_qkey, 1725 &qp_port_num, 0); 1726 1727 ASSERT(ibmf_status == IBMF_SUCCESS); 1728 1729 IBTF_DPRINTF_L5(cmlog, "ibcm_query_qp: qpn %lx qkey %x pkey %x port %d", 1730 qp_num, qp_qkey, qp_pkey, qp_port_num); 1731 } 1732 1733 /* 1734 * ibcm_dump_raw_message: 1735 * dumps 256 bytes of data of a raw message (REP/REQ/DREQ ...) 1736 * (can be called from the kernel debugger w/ the message pointer) 1737 * 1738 * Arguments: 1739 * msgp - the messages that needs to be dumped 1740 * 1741 * Return values: NONE 1742 */ 1743 void 1744 ibcm_dump_raw_message(uchar_t *c) 1745 { 1746 int i; 1747 1748 for (i = 0; i < IBCM_MAD_SIZE; i += 16) { 1749 /* print in batches of 16 chars at a time */ 1750 IBTF_DPRINTF_L4(cmlog, 1751 "%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x", 1752 c[i], c[i + 1], c[i + 2], c[i + 3], c[i + 4], c[i + 5], 1753 c[i + 6], c[i + 7], c[i + 8], c[i + 9], c[i + 10], 1754 c[i + 11], c[i + 12], c[i + 13], c[i + 14], c[i + 15]); 1755 } 1756 } 1757 1758 1759 /* 1760 * ibcm_dump_srv_rec: 1761 * Dumps Service Records. 1762 * 1763 * Arguments: 1764 * srv_rec - the pointer to sa_service_record_t struct. 1765 * 1766 * Return values: NONE 1767 */ 1768 void 1769 ibcm_dump_srvrec(sa_service_record_t *srv_rec) 1770 { 1771 uint8_t i; 1772 1773 IBTF_DPRINTF_L4(cmlog, "ibcm_dump_srvrec: Service Records"); 1774 IBTF_DPRINTF_L4(cmlog, "SID : 0x%016llX", srv_rec->ServiceID); 1775 IBTF_DPRINTF_L4(cmlog, "Svc GID : 0x%016llX:0x%016llX", 1776 srv_rec->ServiceGID.gid_prefix, srv_rec->ServiceGID.gid_guid); 1777 IBTF_DPRINTF_L4(cmlog, "Svc PKey : 0x%X", srv_rec->ServiceP_Key); 1778 1779 IBTF_DPRINTF_L4(cmlog, "Svc Lease : 0x%lX", srv_rec->ServiceLease); 1780 IBTF_DPRINTF_L4(cmlog, "Svc Key-hi: 0x%016llX", srv_rec->ServiceKey_hi); 1781 IBTF_DPRINTF_L4(cmlog, "Svc Key-lo: 0x%016llX", srv_rec->ServiceKey_lo); 1782 IBTF_DPRINTF_L4(cmlog, "Svc Name : %s", srv_rec->ServiceName); 1783 IBTF_DPRINTF_L4(cmlog, "Svc Data : "); 1784 for (i = 0; i < IB_SVC_DATA_LEN; i += 8) { 1785 IBTF_DPRINTF_L4(cmlog, 1786 "\t 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X", 1787 srv_rec->ServiceData[i], srv_rec->ServiceData[i+1], 1788 srv_rec->ServiceData[i+2], srv_rec->ServiceData[i+3], 1789 srv_rec->ServiceData[i+4], srv_rec->ServiceData[i+5], 1790 srv_rec->ServiceData[i+6], srv_rec->ServiceData[i+7]); 1791 } 1792 } 1793 1794 1795 /* 1796 * ibcm_dump_pathrec: 1797 * Dumps Path Records. 1798 * 1799 * Arguments: 1800 * path_rec - the pointer to sa_path_record_t struct. 1801 * 1802 * Return values: NONE 1803 */ 1804 void 1805 ibcm_dump_pathrec(sa_path_record_t *path_rec) 1806 { 1807 IBTF_DPRINTF_L5(cmlog, "Path Record:"); 1808 IBTF_DPRINTF_L5(cmlog, "SGID: (sn_prefix) %016llX", 1809 path_rec->SGID.gid_prefix); 1810 IBTF_DPRINTF_L5(cmlog, "SGID: (GUID) %016llX", 1811 path_rec->SGID.gid_guid); 1812 IBTF_DPRINTF_L5(cmlog, "DGID: (sn_prefix) %016llX", 1813 path_rec->DGID.gid_prefix); 1814 IBTF_DPRINTF_L5(cmlog, "DGID: (GUID) %016llX", 1815 path_rec->DGID.gid_guid); 1816 IBTF_DPRINTF_L5(cmlog, "SLID: %04X", path_rec->SLID); 1817 IBTF_DPRINTF_L5(cmlog, "DLID: %04X", path_rec->DLID); 1818 IBTF_DPRINTF_L5(cmlog, "Raw Traffic: %01X", path_rec->RawTraffic); 1819 IBTF_DPRINTF_L5(cmlog, "Flow Label: %05X", path_rec->FlowLabel); 1820 IBTF_DPRINTF_L5(cmlog, "Hop Limit: %02X", path_rec->HopLimit); 1821 IBTF_DPRINTF_L5(cmlog, "TClass: %02X", path_rec->TClass); 1822 IBTF_DPRINTF_L5(cmlog, "Reversible: %01X", path_rec->Reversible); 1823 IBTF_DPRINTF_L5(cmlog, "Numb Paths: %02d", path_rec->NumbPath); 1824 IBTF_DPRINTF_L5(cmlog, "P_Key: %04X", path_rec->P_Key); 1825 IBTF_DPRINTF_L5(cmlog, "SL: %02X", path_rec->SL); 1826 IBTF_DPRINTF_L5(cmlog, "Path MTU Selector: %01X", 1827 path_rec->MtuSelector); 1828 IBTF_DPRINTF_L5(cmlog, "Path MTU: %02X", path_rec->Mtu); 1829 IBTF_DPRINTF_L5(cmlog, "Path Rate Selector:%01X", 1830 path_rec->RateSelector); 1831 IBTF_DPRINTF_L5(cmlog, "Path Rate: %02X", path_rec->Rate); 1832 IBTF_DPRINTF_L5(cmlog, "Packet LT Selector:%01X", 1833 path_rec->PacketLifeTimeSelector); 1834 IBTF_DPRINTF_L5(cmlog, "Packet Life Time: %d (dec)", 1835 path_rec->PacketLifeTime); 1836 IBTF_DPRINTF_L5(cmlog, "Preference Bit: %02X", path_rec->Preference); 1837 } 1838 1839 1840 /* 1841 * ibcm_dump_node_rec: 1842 * Dumps Node Records. 1843 * 1844 * Arguments: 1845 * nrec - the pointer to sa_node_record_t struct. 1846 * 1847 * Return values: NONE 1848 */ 1849 void 1850 ibcm_dump_noderec(sa_node_record_t *nrec) 1851 { 1852 IBTF_DPRINTF_L5(cmlog, "ibcm_dump_noderec: Node Info Record"); 1853 IBTF_DPRINTF_L5(cmlog, "LID : %04X", nrec->LID); 1854 IBTF_DPRINTF_L5(cmlog, "Base Ver : %02X", nrec->NodeInfo.BaseVersion); 1855 IBTF_DPRINTF_L5(cmlog, "Class Ver : %02X", nrec->NodeInfo.ClassVersion); 1856 IBTF_DPRINTF_L5(cmlog, "Node Type : %02d", nrec->NodeInfo.NodeType); 1857 IBTF_DPRINTF_L5(cmlog, "Num Ports : %02X", nrec->NodeInfo.NumPorts); 1858 IBTF_DPRINTF_L5(cmlog, "SysImgGUID: %016llX", 1859 nrec->NodeInfo.SystemImageGUID); 1860 IBTF_DPRINTF_L5(cmlog, "NODE GUID : %016llX", nrec->NodeInfo.NodeGUID); 1861 IBTF_DPRINTF_L5(cmlog, "Port GUID : %016llX", nrec->NodeInfo.PortGUID); 1862 IBTF_DPRINTF_L5(cmlog, "PartionCap: %04X", nrec->NodeInfo.PartitionCap); 1863 IBTF_DPRINTF_L5(cmlog, "Device ID : %04X", nrec->NodeInfo.DeviceID); 1864 IBTF_DPRINTF_L5(cmlog, "Revision : %06X", nrec->NodeInfo.Revision); 1865 IBTF_DPRINTF_L5(cmlog, "LocalPort#: %02X", nrec->NodeInfo.LocalPortNum); 1866 IBTF_DPRINTF_L5(cmlog, "Vendor ID : %06X", nrec->NodeInfo.VendorID); 1867 IBTF_DPRINTF_L5(cmlog, "Description: %s", 1868 (char *)&nrec->NodeDescription); 1869 } 1870 #endif 1871 1872 1873 /* 1874 * ibcm_ibmf_analyze_error: 1875 * Checks IBMF status and determines appropriate ibt status. 1876 * 1877 * Arguments: 1878 * ibmf_status - IBMF Status 1879 * 1880 * Return values: 1881 * ibt_status_t 1882 */ 1883 ibt_status_t 1884 ibcm_ibmf_analyze_error(int ibmf_status) 1885 { 1886 if (ibt_check_failure(ibmf_status, NULL) != IBT_FAILURE_STANDARD) { 1887 /* 1888 * IBMF specific failure, return special error code 1889 * to the client so that it can retrieve any associated ENA. 1890 */ 1891 return (ibmf_status); 1892 } else { 1893 /* 1894 * IBMF failed for some other reason, invalid arguments etc. 1895 * Analyze, log ENA with IBTF and obtain a special ibt_status_t 1896 * that indicates IBMF failure. 1897 */ 1898 if ((ibmf_status == IBMF_BAD_CLASS) || 1899 (ibmf_status == IBMF_BAD_HANDLE) || 1900 (ibmf_status == IBMF_BAD_QP_HANDLE) || 1901 (ibmf_status == IBMF_BAD_NODE) || 1902 (ibmf_status == IBMF_BAD_PORT) || 1903 (ibmf_status == IBMF_BAD_VERSION) || 1904 (ibmf_status == IBMF_BAD_FLAGS) || 1905 (ibmf_status == IBMF_BAD_SIZE) || 1906 (ibmf_status == IBMF_INVALID_GID) || 1907 (ibmf_status == IBMF_INVALID_ARG) || 1908 (ibmf_status == IBMF_INVALID_FIELD) || 1909 (ibmf_status == IBMF_UNSUPP_METHOD) || 1910 (ibmf_status == IBMF_UNSUPP_METHOD_ATTR)) { 1911 1912 /* 1913 * These errors, we should not see... 1914 * something really bad happened!. 1915 */ 1916 IBTF_DPRINTF_L2(cmlog, "ibcm_ibmf_analyze_error: " 1917 "Unexpected ERROR from IBMF - %d", ibmf_status); 1918 } 1919 return (ibt_get_module_failure(IBT_FAILURE_IBMF, 0)); 1920 } 1921 } 1922