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 #include <sys/ib/ibtl/impl/ibtl.h> 27 #include <sys/ib/ibtl/impl/ibtl_cm.h> 28 29 /* 30 * ibtl_cm.c 31 * These routines tie the Communication Manager into IBTL. 32 */ 33 34 /* 35 * Globals. 36 */ 37 static char ibtf_cm[] = "ibtl_cm"; 38 boolean_t ibtl_fast_gid_cache_valid = B_FALSE; 39 40 /* 41 * Function: 42 * ibtl_cm_set_chan_private 43 * Input: 44 * chan Channel Handle. 45 * cm_private CM private data. 46 * Output: 47 * none. 48 * Returns: 49 * none. 50 * Description: 51 * A helper function to store CM's Private data in the specified channel. 52 */ 53 void 54 ibtl_cm_set_chan_private(ibt_channel_hdl_t chan, void *cm_private) 55 { 56 IBTF_DPRINTF_L3(ibtf_cm, "ibtl_cm_set_chan_private(%p, %p)", 57 chan, cm_private); 58 59 mutex_enter(&chan->ch_cm_mutex); 60 chan->ch_cm_private = cm_private; 61 if (cm_private == NULL) 62 cv_signal(&chan->ch_cm_cv); 63 mutex_exit(&chan->ch_cm_mutex); 64 } 65 66 67 /* 68 * Function: 69 * ibtl_cm_get_chan_private 70 * Input: 71 * chan Channel Handle. 72 * Output: 73 * cm_private_p The CM private data. 74 * Returns: 75 * CM private data. 76 * Description: 77 * A helper function to get CM's Private data for the specified channel. 78 */ 79 void * 80 ibtl_cm_get_chan_private(ibt_channel_hdl_t chan) 81 { 82 void *cm_private; 83 84 IBTF_DPRINTF_L3(ibtf_cm, "ibtl_cm_get_chan_private(%p)", chan); 85 mutex_enter(&chan->ch_cm_mutex); 86 cm_private = chan->ch_cm_private; 87 /* IBCM will call the release function if cm_private is non-NULL */ 88 if (cm_private == NULL) 89 mutex_exit(&chan->ch_cm_mutex); 90 return (cm_private); 91 } 92 93 void 94 ibtl_cm_release_chan_private(ibt_channel_hdl_t chan) 95 { 96 mutex_exit(&chan->ch_cm_mutex); 97 } 98 99 void 100 ibtl_cm_wait_chan_private(ibt_channel_hdl_t chan) 101 { 102 mutex_enter(&chan->ch_cm_mutex); 103 if (chan->ch_cm_private != NULL) 104 cv_wait(&chan->ch_cm_cv, &chan->ch_cm_mutex); 105 mutex_exit(&chan->ch_cm_mutex); 106 delay(drv_usectohz(50000)); 107 } 108 109 110 /* 111 * Function: 112 * ibtl_cm_get_chan_type 113 * Input: 114 * chan Channel Handle. 115 * Output: 116 * none. 117 * Returns: 118 * Channel transport type. 119 * Description: 120 * A helper function to get channel transport type. 121 */ 122 ibt_tran_srv_t 123 ibtl_cm_get_chan_type(ibt_channel_hdl_t chan) 124 { 125 IBTF_DPRINTF_L3(ibtf_cm, "ibtl_cm_get_chan_type(%p)", chan); 126 127 return (chan->ch_qp.qp_type); 128 } 129 130 /* 131 * Function: 132 * ibtl_cm_change_service_cnt 133 * Input: 134 * ibt_hdl Client's IBT Handle. 135 * delta_num_sids The change in the number of service ids 136 * (positive for ibt_register_service() and 137 * negative fo ibt_service_deregister()). 138 */ 139 void 140 ibtl_cm_change_service_cnt(ibt_clnt_hdl_t ibt_hdl, int delta_num_sids) 141 { 142 IBTF_DPRINTF_L3(ibtf_cm, "ibtl_cm_change_service_cnt(%p. %d)", 143 ibt_hdl, delta_num_sids); 144 145 mutex_enter(&ibtl_clnt_list_mutex); 146 if ((delta_num_sids < 0) && (-delta_num_sids > ibt_hdl->clnt_srv_cnt)) { 147 IBTF_DPRINTF_L2(ibtf_cm, "ibtl_cm_change_service_cnt: " 148 "ERROR: service registration counter underflow\n" 149 "current count = %d, requested delta = %d", 150 ibt_hdl->clnt_srv_cnt, delta_num_sids); 151 } 152 ibt_hdl->clnt_srv_cnt += delta_num_sids; 153 mutex_exit(&ibtl_clnt_list_mutex); 154 } 155 156 157 /* 158 * Function: 159 * ibtl_cm_get_hca_port 160 * Input: 161 * gid Source GID. 162 * hca_guid Optional source HCA GUID on which SGID is available. 163 * Ignored if zero. 164 * Output: 165 * hca_port Pointer to ibtl_cm_hca_port_t struct. 166 * Returns: 167 * IBT_SUCCESS. 168 * Description: 169 * A helper function to get HCA node GUID, Base LID, SGID Index, 170 * port number, LMC and MTU for the specified SGID. 171 * Also filling default SGID, to be used in ibmf_sa_session_open. 172 */ 173 ibt_status_t 174 ibtl_cm_get_hca_port(ib_gid_t gid, ib_guid_t hca_guid, 175 ibtl_cm_hca_port_t *hca_port) 176 { 177 ibtl_hca_devinfo_t *hca_devp; /* HCA Dev Info */ 178 ibt_hca_portinfo_t *portinfop; 179 uint_t ports, port; 180 uint_t i; 181 ib_gid_t *sgid; 182 static ib_gid_t fast_gid; /* fast_gid_cache data */ 183 static uint8_t fast_sgid_ix; 184 static ibt_hca_portinfo_t *fast_portinfop; 185 static ib_guid_t fast_node_guid; 186 static ib_guid_t fast_port_guid; 187 188 IBTF_DPRINTF_L3(ibtf_cm, "ibtl_cm_get_hca_port(%llX:%llX, %llX)", 189 gid.gid_prefix, gid.gid_guid, hca_guid); 190 191 if ((gid.gid_prefix == 0) || (gid.gid_guid == 0)) { 192 IBTF_DPRINTF_L2(ibtf_cm, "ibtl_cm_get_hca_port: " 193 "NULL SGID specified."); 194 return (IBT_INVALID_PARAM); 195 } 196 197 mutex_enter(&ibtl_clnt_list_mutex); 198 199 if ((ibtl_fast_gid_cache_valid == B_TRUE) && 200 (gid.gid_guid == fast_gid.gid_guid) && 201 (gid.gid_prefix == fast_gid.gid_prefix)) { 202 203 if ((hca_guid != 0) && (hca_guid != fast_node_guid)) { 204 IBTF_DPRINTF_L3(ibtf_cm, "ibtl_cm_get_hca_port: " 205 "Mis-match hca_guid v/s sgid combination."); 206 mutex_exit(&ibtl_clnt_list_mutex); 207 return (IBT_INVALID_PARAM); 208 } 209 210 portinfop = fast_portinfop; 211 hca_port->hp_base_lid = portinfop->p_base_lid; 212 hca_port->hp_port = portinfop->p_port_num; 213 hca_port->hp_sgid_ix = fast_sgid_ix; 214 hca_port->hp_lmc = portinfop->p_lmc; 215 hca_port->hp_mtu = portinfop->p_mtu; 216 hca_port->hp_hca_guid = fast_node_guid; 217 hca_port->hp_port_guid = fast_port_guid; 218 219 mutex_exit(&ibtl_clnt_list_mutex); 220 221 return (IBT_SUCCESS); 222 } 223 224 /* If HCA GUID is specified, then lookup in that device only. */ 225 if (hca_guid) { 226 hca_devp = ibtl_get_hcadevinfo(hca_guid); 227 } else { 228 hca_devp = ibtl_hca_list; 229 } 230 231 while (hca_devp != NULL) { 232 233 ports = hca_devp->hd_hca_attr->hca_nports; 234 portinfop = hca_devp->hd_portinfop; 235 236 for (port = 0; port < ports; port++, portinfop++) { 237 if (portinfop->p_linkstate != IBT_PORT_ACTIVE) 238 continue; 239 sgid = &portinfop->p_sgid_tbl[0]; 240 for (i = 0; i < portinfop->p_sgid_tbl_sz; i++, sgid++) { 241 if ((gid.gid_guid != sgid->gid_guid) || 242 (gid.gid_prefix != sgid->gid_prefix)) 243 continue; 244 245 /* 246 * Found the matching GID. 247 */ 248 ibtl_fast_gid_cache_valid = B_TRUE; 249 fast_gid = gid; 250 fast_portinfop = portinfop; 251 fast_node_guid = hca_port->hp_hca_guid = 252 hca_devp->hd_hca_attr->hca_node_guid; 253 fast_sgid_ix = hca_port->hp_sgid_ix = i; 254 fast_port_guid = 255 portinfop->p_sgid_tbl[0].gid_guid; 256 hca_port->hp_port_guid = fast_port_guid; 257 hca_port->hp_base_lid = portinfop->p_base_lid; 258 hca_port->hp_port = portinfop->p_port_num; 259 hca_port->hp_lmc = portinfop->p_lmc; 260 hca_port->hp_mtu = portinfop->p_mtu; 261 262 mutex_exit(&ibtl_clnt_list_mutex); 263 264 return (IBT_SUCCESS); 265 } 266 } 267 268 /* Asked to look in the specified HCA device only?. */ 269 if (hca_guid) 270 break; 271 272 /* Get next in the list */ 273 hca_devp = hca_devp->hd_hca_dev_link; 274 } 275 276 mutex_exit(&ibtl_clnt_list_mutex); 277 278 /* If we are here, then we failed to get a match, so return error. */ 279 return (IBT_INVALID_PARAM); 280 } 281 282 283 static ibt_status_t 284 ibtl_cm_get_cnt(ibt_path_attr_t *attr, ibt_path_flags_t flags, 285 ibtl_cm_port_list_t *plistp, uint_t *count) 286 { 287 ibtl_hca_devinfo_t *hdevp; 288 ibt_hca_portinfo_t *pinfop; 289 ib_guid_t hca_guid, tmp_hca_guid = 0; 290 ib_gid_t gid; 291 uint_t pcount = 0, tmp_pcount = 0; 292 uint_t cnt = *count; 293 ibt_status_t retval = IBT_SUCCESS; 294 uint_t i, j; 295 296 *count = 0; 297 298 /* If HCA GUID is specified, then lookup in that device only. */ 299 if (attr->pa_hca_guid) { 300 hdevp = ibtl_get_hcadevinfo(attr->pa_hca_guid); 301 } else { 302 hdevp = ibtl_hca_list; 303 } 304 305 while (hdevp != NULL) { 306 hca_guid = hdevp->hd_hca_attr->hca_node_guid; 307 308 if ((flags & IBT_PATH_APM) && 309 (!(hdevp->hd_hca_attr->hca_flags & 310 IBT_HCA_AUTO_PATH_MIG))) { 311 312 IBTF_DPRINTF_L2(ibtf_cm, "ibtl_cm_get_cnt: " 313 "HCA (%llX) - APM NOT SUPPORTED ", hca_guid); 314 315 retval = IBT_APM_NOT_SUPPORTED; 316 317 if (attr->pa_hca_guid) 318 break; 319 goto search_next; 320 } 321 322 for (i = 0; i < hdevp->hd_hca_attr->hca_nports; i++) { 323 324 if ((attr->pa_hca_port_num) && 325 (attr->pa_hca_port_num != (i + 1))) { 326 IBTF_DPRINTF_L3(ibtf_cm, "ibtl_cm_get_cnt: " 327 "Asked only on Port# %d, so skip this " 328 "port(%d)", attr->pa_hca_port_num, (i + 1)); 329 continue; 330 } 331 pinfop = hdevp->hd_portinfop + i; 332 333 if (pinfop->p_linkstate != IBT_PORT_ACTIVE) { 334 retval = IBT_HCA_PORT_NOT_ACTIVE; 335 continue; 336 } 337 if (attr->pa_mtu.r_mtu) { 338 if ((attr->pa_mtu.r_selector == IBT_GT) && 339 (attr->pa_mtu.r_mtu >= pinfop->p_mtu)) 340 continue; 341 else if ((attr->pa_mtu.r_selector == IBT_EQU) && 342 (attr->pa_mtu.r_mtu > pinfop->p_mtu)) 343 continue; 344 } 345 346 if ((flags & IBT_PATH_APM) && (!attr->pa_hca_guid) && 347 attr->pa_sgid.gid_prefix && 348 attr->pa_sgid.gid_guid) { 349 for (j = 0; j < pinfop->p_sgid_tbl_sz; j++) { 350 gid = pinfop->p_sgid_tbl[j]; 351 if (gid.gid_prefix && gid.gid_guid) { 352 if ((attr->pa_sgid.gid_prefix != 353 gid.gid_prefix) || 354 (attr->pa_sgid.gid_guid != 355 gid.gid_guid)) { 356 continue; 357 } else { 358 attr->pa_hca_guid = 359 hca_guid; 360 goto got_apm_hca_info; 361 } 362 } 363 } 364 continue; 365 } 366 got_apm_hca_info: 367 for (j = 0; j < pinfop->p_sgid_tbl_sz; j++) { 368 gid = pinfop->p_sgid_tbl[j]; 369 if (gid.gid_prefix && gid.gid_guid) { 370 if (!(flags & IBT_PATH_APM) && 371 attr->pa_sgid.gid_prefix && 372 attr->pa_sgid.gid_guid) { 373 if ((attr->pa_sgid.gid_prefix != 374 gid.gid_prefix) || 375 (attr->pa_sgid.gid_guid != 376 gid.gid_guid)) 377 continue; 378 } 379 pcount++; 380 if (plistp) { 381 plistp->p_hca_guid = hca_guid; 382 plistp->p_mtu = pinfop->p_mtu; 383 plistp->p_base_lid = 384 pinfop->p_base_lid; 385 plistp->p_port_num = 386 pinfop->p_port_num; 387 plistp->p_sgid_ix = j; 388 plistp->p_sgid = gid; 389 plistp->p_count = cnt; 390 if (hdevp->hd_multism) 391 plistp->p_multi |= 392 IBTL_CM_MULTI_SM; 393 394 IBTF_DPRINTF_L3(ibtf_cm, 395 "ibtl_cm_get_cnt: HCA" 396 "(%llX,%d) SGID(%llX:%llX)", 397 plistp->p_hca_guid, 398 plistp->p_port_num, 399 plistp->p_sgid.gid_prefix, 400 plistp->p_sgid.gid_guid); 401 402 plistp++; 403 } 404 } 405 } 406 } 407 /* Asked to look in the specified HCA device only?. */ 408 if (attr->pa_hca_guid) 409 break; 410 411 if (flags & IBT_PATH_APM) { 412 if (pcount == 2) { 413 attr->pa_hca_guid = hca_guid; 414 break; 415 } else if (pcount == 1) { 416 if (hdevp->hd_hca_dev_link) { 417 tmp_hca_guid = hca_guid; 418 tmp_pcount = pcount; 419 pcount = 0; 420 } else if (tmp_hca_guid) { 421 attr->pa_hca_guid = tmp_hca_guid; 422 } else { 423 attr->pa_hca_guid = hca_guid; 424 } 425 } else if ((pcount == 0) && (tmp_hca_guid)) { 426 attr->pa_hca_guid = tmp_hca_guid; 427 pcount = tmp_pcount; 428 } 429 } 430 search_next: 431 hdevp = hdevp->hd_hca_dev_link; 432 } 433 434 *count = pcount; 435 436 if (pcount) { 437 retval = IBT_SUCCESS; 438 } else { 439 IBTF_DPRINTF_L2(ibtf_cm, "ibtl_cm_get_cnt: " 440 "Appropriate Source Points NOT found"); 441 if (retval == IBT_SUCCESS) 442 retval = IBT_NO_HCAS_AVAILABLE; 443 } 444 445 return (retval); 446 } 447 448 449 ibt_status_t 450 ibtl_cm_get_active_plist(ibt_path_attr_t *attr, ibt_path_flags_t flags, 451 ibtl_cm_port_list_t **port_list_p) 452 { 453 ibtl_cm_port_list_t *p_listp, tmp; 454 uint_t i, j; 455 uint_t count, rcount; 456 boolean_t multi_hca = B_FALSE; 457 ibt_status_t retval = IBT_SUCCESS; 458 459 IBTF_DPRINTF_L3(ibtf_cm, "ibtl_cm_get_active_plist(%p, %X)", 460 attr, flags); 461 462 get_plist_start: 463 *port_list_p = NULL; 464 465 /* Get "number of active src points" so that we can allocate memory. */ 466 mutex_enter(&ibtl_clnt_list_mutex); 467 retval = ibtl_cm_get_cnt(attr, flags, NULL, &count); 468 mutex_exit(&ibtl_clnt_list_mutex); 469 470 IBTF_DPRINTF_L3(ibtf_cm, "ibtl_cm_get_active_plist: Found %d SrcPoint", 471 count); 472 if (retval != IBT_SUCCESS) 473 return (retval); 474 475 /* Allocate Memory to hold Src Point information. */ 476 p_listp = kmem_zalloc(count * sizeof (ibtl_cm_port_list_t), KM_SLEEP); 477 478 /* 479 * Verify that the count we got previously is still valid, as we had 480 * dropped mutex to allocate memory. If not, restart the process. 481 */ 482 mutex_enter(&ibtl_clnt_list_mutex); 483 retval = ibtl_cm_get_cnt(attr, flags, NULL, &rcount); 484 if (retval != IBT_SUCCESS) { 485 mutex_exit(&ibtl_clnt_list_mutex); 486 kmem_free(p_listp, count * sizeof (ibtl_cm_port_list_t)); 487 return (retval); 488 } else if (rcount != count) { 489 mutex_exit(&ibtl_clnt_list_mutex); 490 kmem_free(p_listp, count * sizeof (ibtl_cm_port_list_t)); 491 goto get_plist_start; 492 } 493 494 *port_list_p = p_listp; 495 /* 496 * Src count hasn't changed, still holding the lock fill-in the 497 * required source point information. 498 */ 499 retval = ibtl_cm_get_cnt(attr, flags, p_listp, &rcount); 500 mutex_exit(&ibtl_clnt_list_mutex); 501 if (retval != IBT_SUCCESS) { 502 kmem_free(p_listp, count * sizeof (ibtl_cm_port_list_t)); 503 *port_list_p = NULL; 504 return (retval); 505 } 506 507 p_listp = *port_list_p; 508 509 for (i = 0; i < count - 1; i++) { 510 for (j = 0; j < count - 1 - i; j++) { 511 if (p_listp[j].p_hca_guid != p_listp[j+1].p_hca_guid) { 512 multi_hca = B_TRUE; 513 break; 514 } 515 } 516 if (multi_hca == B_TRUE) 517 break; 518 } 519 520 if (multi_hca == B_TRUE) 521 for (i = 0; i < count; i++) 522 p_listp[i].p_multi |= IBTL_CM_MULTI_HCA; 523 524 /* 525 * Sort (bubble sort) the list based on MTU quality (higher on top). 526 * Sorting is only performed, if IBT_PATH_AVAIL is set. 527 */ 528 if (((attr->pa_mtu.r_selector == IBT_GT) || (flags & IBT_PATH_AVAIL)) && 529 (!(flags & IBT_PATH_APM))) { 530 for (i = 0; i < count - 1; i++) { 531 for (j = 0; j < count - 1 - i; j++) { 532 if (p_listp[j].p_mtu < p_listp[j+1].p_mtu) { 533 tmp = p_listp[j]; 534 p_listp[j] = p_listp[j+1]; 535 p_listp[j+1] = tmp; 536 } 537 } 538 } 539 } 540 541 if ((p_listp->p_multi & IBTL_CM_MULTI_HCA) && 542 (flags & IBT_PATH_AVAIL) && (!(flags & IBT_PATH_APM))) { 543 /* Avoid having same HCA next to each other in the list. */ 544 for (i = 0; i < count - 1; i++) { 545 for (j = 0; j < (count - 1 - i); j++) { 546 if ((p_listp[j].p_hca_guid == 547 p_listp[j+1].p_hca_guid) && 548 (j+2 < count)) { 549 tmp = p_listp[j+1]; 550 p_listp[j+1] = p_listp[j+2]; 551 p_listp[j+2] = tmp; 552 } 553 } 554 } 555 } 556 557 /* 558 * If SGID is specified, then make sure that SGID info is first 559 * in the array. 560 */ 561 if (attr->pa_sgid.gid_guid && (p_listp->p_count > 1) && 562 (p_listp[0].p_sgid.gid_guid != attr->pa_sgid.gid_guid)) { 563 for (i = 1; i < count; i++) { 564 if (p_listp[i].p_sgid.gid_guid == 565 attr->pa_sgid.gid_guid) { 566 tmp = p_listp[i]; 567 p_listp[i] = p_listp[0]; 568 p_listp[0] = tmp; 569 } 570 } 571 } 572 573 IBTF_DPRINTF_L3(ibtf_cm, "ibtl_cm_get_active_plist: " 574 "Returned <%d> entries @0x%p", count, *port_list_p); 575 576 return (retval); 577 } 578 579 580 void 581 ibtl_cm_free_active_plist(ibtl_cm_port_list_t *plist) 582 { 583 int count; 584 585 IBTF_DPRINTF_L3(ibtf_cm, "ibtl_cm_free_active_plist(%p)", plist); 586 587 if (plist != NULL) { 588 count = plist->p_count; 589 kmem_free(plist, count * sizeof (ibtl_cm_port_list_t)); 590 } 591 } 592 593 /* 594 * Function: 595 * ibtl_cm_get_1st_full_pkey_ix 596 * Input: 597 * hca_guid HCA GUID. 598 * port Port Number. 599 * Output: 600 * None. 601 * Returns: 602 * P_Key Index of the first full member available from the P_Key table 603 * of the specified HCA<->Port. 604 * Description: 605 * A helper function to get P_Key Index of the first full member P_Key 606 * available on the specified HCA and Port combination. 607 */ 608 uint16_t 609 ibtl_cm_get_1st_full_pkey_ix(ib_guid_t hca_guid, uint8_t port) 610 { 611 ibtl_hca_devinfo_t *hca_devp; /* HCA Dev Info */ 612 uint16_t pkey_ix = 0; 613 614 IBTF_DPRINTF_L3(ibtf_cm, "ibtl_cm_get_1st_full_pkey_ix(%llX, %d)", 615 hca_guid, port); 616 617 mutex_enter(&ibtl_clnt_list_mutex); 618 hca_devp = ibtl_get_hcadevinfo(hca_guid); 619 620 if ((hca_devp != NULL) && (port <= hca_devp->hd_hca_attr->hca_nports) && 621 (port != 0)) { 622 pkey_ix = hca_devp->hd_portinfop[port - 1].p_def_pkey_ix; 623 } else { 624 IBTF_DPRINTF_L2(ibtf_cm, "ibtl_cm_get_1st_full_pkey_ix: " 625 "Invalid HCA (%llX), Port (%d) specified.", hca_guid, port); 626 } 627 mutex_exit(&ibtl_clnt_list_mutex); 628 629 return (pkey_ix); 630 } 631 632 633 ibt_status_t 634 ibtl_cm_get_local_comp_gids(ib_guid_t hca_guid, ib_gid_t gid, ib_gid_t **gids_p, 635 uint_t *num_gids_p) 636 { 637 ibtl_hca_devinfo_t *hdevp; /* HCA Dev Info */ 638 ibt_hca_portinfo_t *pinfop; 639 ib_gid_t sgid; 640 ib_gid_t *gidp = NULL; 641 int i, j, k; 642 int count = 0; 643 int gid_specified; 644 645 IBTF_DPRINTF_L3(ibtf_cm, "ibtl_cm_get_local_comp_gids(%llX, %llX:%llX)", 646 hca_guid, gid.gid_prefix, gid.gid_guid); 647 648 mutex_enter(&ibtl_clnt_list_mutex); 649 hdevp = ibtl_get_hcadevinfo(hca_guid); 650 651 if (hdevp == NULL) { 652 IBTF_DPRINTF_L3(ibtf_cm, "ibtl_cm_get_local_comp_gids: ", 653 "NO HCA (%llX) availble", hca_guid); 654 mutex_exit(&ibtl_clnt_list_mutex); 655 return (IBT_NO_HCAS_AVAILABLE); 656 } 657 658 if (gid.gid_prefix && gid.gid_guid) 659 gid_specified = 1; 660 else 661 gid_specified = 0; 662 663 for (i = 0; i < hdevp->hd_hca_attr->hca_nports; i++) { 664 pinfop = hdevp->hd_portinfop + i; 665 666 if (pinfop->p_linkstate != IBT_PORT_ACTIVE) 667 continue; 668 669 for (j = 0; j < pinfop->p_sgid_tbl_sz; j++) { 670 sgid = pinfop->p_sgid_tbl[j]; 671 if (sgid.gid_prefix && sgid.gid_guid) { 672 if (gid_specified && 673 ((gid.gid_prefix == sgid.gid_prefix) && 674 (gid.gid_guid == sgid.gid_guid))) { 675 /* 676 * Don't return the input specified 677 * GID 678 */ 679 continue; 680 } 681 count++; 682 } 683 } 684 } 685 686 if (count == 0) { 687 IBTF_DPRINTF_L2(ibtf_cm, "ibtl_cm_get_local_comp_gids: " 688 "Companion GIDs not available"); 689 mutex_exit(&ibtl_clnt_list_mutex); 690 return (IBT_GIDS_NOT_FOUND); 691 } 692 693 gidp = kmem_zalloc(count * sizeof (ib_gid_t), KM_SLEEP); 694 *num_gids_p = count; 695 *gids_p = gidp; 696 k = 0; 697 698 for (i = 0; i < hdevp->hd_hca_attr->hca_nports; i++) { 699 pinfop = hdevp->hd_portinfop + i; 700 701 if (pinfop->p_linkstate != IBT_PORT_ACTIVE) 702 continue; 703 704 for (j = 0; j < pinfop->p_sgid_tbl_sz; j++) { 705 sgid = pinfop->p_sgid_tbl[j]; 706 if (sgid.gid_prefix && sgid.gid_guid) { 707 if (gid_specified && 708 ((gid.gid_prefix == sgid.gid_prefix) && 709 (gid.gid_guid == sgid.gid_guid))) 710 continue; 711 712 gidp[k].gid_prefix = sgid.gid_prefix; 713 gidp[k].gid_guid = sgid.gid_guid; 714 715 IBTF_DPRINTF_L3(ibtf_cm, 716 "ibtl_cm_get_local_comp_gids: GID[%d]=" 717 "%llX:%llX", k, gidp[k].gid_prefix, 718 gidp[k].gid_guid); 719 k++; 720 if (k == count) 721 break; 722 } 723 } 724 if (k == count) 725 break; 726 } 727 mutex_exit(&ibtl_clnt_list_mutex); 728 729 return (IBT_SUCCESS); 730 } 731 732 733 int 734 ibtl_cm_is_multi_sm(ib_guid_t hca_guid) 735 { 736 ibtl_hca_devinfo_t *hdevp; /* HCA Dev Info */ 737 uint_t multi_sm; 738 739 mutex_enter(&ibtl_clnt_list_mutex); 740 hdevp = ibtl_get_hcadevinfo(hca_guid); 741 if (hdevp == NULL) { 742 IBTF_DPRINTF_L2(ibtf_cm, "ibtl_cm_is_multi_sm: NO HCA (%llX) " 743 "availble", hca_guid); 744 mutex_exit(&ibtl_clnt_list_mutex); 745 return (-1); 746 } 747 multi_sm = hdevp->hd_multism; 748 mutex_exit(&ibtl_clnt_list_mutex); 749 750 IBTF_DPRINTF_L3(ibtf_cm, "ibtl_cm_is_multi_sm(%llX): %d", hca_guid, 751 multi_sm); 752 753 return (multi_sm); 754 } 755 756 char * 757 ibtl_cm_get_clnt_name(ibt_clnt_hdl_t ibt_hdl) 758 { 759 if (ibt_hdl) 760 return (ibt_hdl->clnt_name); 761 else 762 return (NULL); 763 }