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