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