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