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 }