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 #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                                 continue;
 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 
 769 char *
 770 ibtl_cm_get_clnt_name(ibt_clnt_hdl_t ibt_hdl)
 771 {
 772         if (ibt_hdl)
 773                 return (ibt_hdl->clnt_name);
 774         else
 775                 return (NULL);
 776 }