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 (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  23  */
  24 
  25 /*
  26  * ibtl_hca.c
  27  *
  28  * This file contains Transport API functions related to
  29  * Host Channel Adapter (HCA) Verbs.
  30  */
  31 
  32 #include <sys/ib/ibtl/impl/ibtl.h>
  33 
  34 static char ibtf_hca[] = "ibtl_hca";
  35 
  36 /* Prototype declarations. */
  37 static ibt_status_t ibtl_query_hca_ports(ibtl_hca_devinfo_t *hca_devp,
  38     uint8_t port, ibt_hca_portinfo_t **port_info_p, uint_t *ports_p,
  39     uint_t *size_p, int use_cache);
  40 
  41 /*
  42  * Function:
  43  *      ibt_open_hca
  44  * Input:
  45  *      ibt_hdl    - IBT Client Handle
  46  *      hca_guid   - HCA's node GUID.
  47  * Output:
  48  *      hca_hdl_p  - IBT HCA Handle.
  49  * Returns:
  50  *      IBT_SUCCESS
  51  *      IBT_HCA_IN_USE
  52  *      IBT_HCA_INVALID
  53  * Description:
  54  *      Open a HCA. HCA can only be opened/closed once. This routine allocates
  55  *      and returns a unique IBT Client HCA handle. Clients passes this
  56  *      handle on its subsequent references to this device. Once opened by a
  57  *      client, a specific HCA cannot be opened again until after it is closed.
  58  *      The IBT_HCA_IN_USE error is returned if client tries to open multiple
  59  *      times. In this case, previously allocated IBT HCA handle is returned to
  60  *      the client. Opening the HCA prepares the HCA for use by the client.
  61  */
  62 ibt_status_t
  63 ibt_open_hca(ibt_clnt_hdl_t ibt_hdl, ib_guid_t hca_guid,
  64     ibt_hca_hdl_t *hca_hdl_p)
  65 {
  66         ibtl_hca_t              *hca_infop;
  67         ibtl_hca_devinfo_t      *hca_devp;              /* HCA Dev Info */
  68 
  69         IBTF_DPRINTF_L3(ibtf_hca, "ibt_open_hca(%p, %llX)", ibt_hdl, hca_guid);
  70 
  71 
  72         /*
  73          * Get HCA Device Info Structure, referenced by HCA GUID.
  74          */
  75         mutex_enter(&ibtl_clnt_list_mutex);
  76         hca_devp = ibtl_get_hcadevinfo(hca_guid);
  77         if (hca_devp == NULL) {
  78                 /*
  79                  * If we are here, then the requested HCA device is not present.
  80                  * Return the status as Invalid HCA GUID.
  81                  */
  82                 mutex_exit(&ibtl_clnt_list_mutex);
  83 
  84                 IBTF_DPRINTF_L2(ibtf_hca, "ibt_open_hca: "
  85                     "HCA Device Not Found: Invalid HCA GUID");
  86 
  87                 *hca_hdl_p = NULL;
  88                 return (IBT_HCA_INVALID);
  89         }
  90 
  91         /*
  92          * Check whether open is allowed for this dip
  93          */
  94         if (ibt_hdl->clnt_dip) {
  95                 if (ddi_get_parent(ibt_hdl->clnt_dip) == hca_devp->hd_hca_dip) {
  96                         if (hca_guid != hca_devp->hd_hca_attr->hca_node_guid) {
  97                                 mutex_exit(&ibtl_clnt_list_mutex);
  98                                 return (IBT_FAILURE);
  99                         }
 100                 }
 101         }
 102 
 103         if (hca_devp->hd_state != IBTL_HCA_DEV_ATTACHED) {
 104                 /*
 105                  * If we are here, then the requested HCA device has detached,
 106                  * or is in the process of detaching.
 107                  */
 108                 mutex_exit(&ibtl_clnt_list_mutex);
 109 
 110                 IBTF_DPRINTF_L2(ibtf_hca, "ibt_open_hca: "
 111                     "HCA is busy trying to detach");
 112 
 113                 *hca_hdl_p = NULL;
 114                 return (IBT_HCA_BUSY_DETACHING);
 115         }
 116 
 117         /*
 118          * Yes, we found a HCA Device registered with IBTF, which matches with
 119          * the requested HCA_GUID.
 120          *
 121          * Check out whether this client has already opened this HCA device,
 122          * if yes return the status as IBT_HCA_IN_USE.
 123          */
 124         hca_infop = hca_devp->hd_clnt_list;
 125 
 126         while (hca_infop != NULL) {
 127                 if (ibt_hdl == hca_infop->ha_clnt_devp) {
 128                         IBTF_DPRINTF_L3(ibtf_hca,
 129                             "ibt_open_hca: Already Open");
 130 
 131                         if (hca_infop->ha_flags & IBTL_HA_CLOSING) {
 132                                 mutex_exit(&ibtl_clnt_list_mutex);
 133                                 *hca_hdl_p = NULL;
 134                                 return (IBT_HCA_BUSY_CLOSING);
 135                         }
 136                         mutex_exit(&ibtl_clnt_list_mutex);
 137 
 138                         /* Already Opened. Return back old HCA Handle. */
 139                         *hca_hdl_p = hca_infop;
 140 
 141                         return (IBT_HCA_IN_USE);
 142                 }
 143                 hca_infop = hca_infop->ha_clnt_link;
 144         }
 145 
 146         /* Create a new HCA Info entity. */
 147         hca_infop = kmem_zalloc(sizeof (ibtl_hca_t), KM_SLEEP);
 148 
 149         /* Update the HCA Info entity */
 150         hca_infop->ha_hca_devp  = hca_devp;  /* HCA Device Info */
 151         hca_infop->ha_clnt_devp = ibt_hdl;   /* Client Info */
 152 
 153         /* Update the HCA List, to keep track about the clients using it. */
 154         hca_infop->ha_clnt_link = hca_devp->hd_clnt_list;
 155         hca_devp->hd_clnt_list = hca_infop;
 156 
 157 
 158         /* Update the client's list to depict that it uses this HCA device. */
 159         hca_infop->ha_hca_link = ibt_hdl->clnt_hca_list;
 160         ibt_hdl->clnt_hca_list = hca_infop;
 161 
 162         mutex_exit(&ibtl_clnt_list_mutex);
 163 
 164         /*
 165          * Return back the address of ibtl_hca_t structure as an opaque
 166          * IBT HCA handle for the clients, to be used in future calls.
 167          */
 168         *hca_hdl_p = hca_infop;
 169 
 170         return (IBT_SUCCESS);
 171 }
 172 
 173 static char *ibtl_close_error_fmt = "IBT CLOSE HCA failed: %d '%s' "
 174         "resources not yet freed by client '%s'\n";
 175 
 176 #define IBTL_CLOSE_RESOURCE_CHECK(counter, resource_type) \
 177         if ((cntr = atomic_add_32_nv(&(counter), 0)) != 0) {                \
 178                 cmn_err(CE_CONT, ibtl_close_error_fmt,                  \
 179                     cntr, resource_type,                                \
 180                     hca_hdl->ha_clnt_devp->clnt_modinfop->mi_clnt_name); \
 181         }                                                               \
 182         error |= cntr
 183 
 184 /*
 185  * Function:
 186  *      ibt_close_hca
 187  * Input:
 188  *      hca_hdl  - The HCA handle as returned during its open.
 189  * Output:
 190  *      none
 191  * Returns:
 192  *      IBT_SUCCESS
 193  *      IBT_HCA_HDL_INVALID
 194  *      IBT_HCA_RESOURCES_NOT_FREED
 195  * Description:
 196  *      Close a HCA.
 197  */
 198 ibt_status_t
 199 ibt_close_hca(ibt_hca_hdl_t hca_hdl)
 200 {
 201         ibtl_hca_devinfo_t      *hca_devp, *tmp_devp;
 202         ibtl_hca_t              **hcapp;
 203         ibtl_clnt_t             *clntp = hca_hdl->ha_clnt_devp;
 204         uint32_t                cntr, error;
 205 
 206         IBTF_DPRINTF_L3(ibtf_hca, "ibt_close_hca(%p)", hca_hdl);
 207 
 208         /*
 209          * Verify the Input HCA Handle, if fake return error as
 210          * invalid HCA Handle.
 211          */
 212         mutex_enter(&ibtl_clnt_list_mutex);
 213         hca_devp = hca_hdl->ha_hca_devp;
 214         tmp_devp = ibtl_hca_list;
 215 
 216         for (; tmp_devp != NULL; tmp_devp = tmp_devp->hd_hca_dev_link)
 217                 if (tmp_devp == hca_devp)
 218                         break;
 219 
 220         if (tmp_devp == NULL) {
 221                 mutex_exit(&ibtl_clnt_list_mutex);
 222                 IBTF_DPRINTF_L2(ibtf_hca, "ibt_close_hca: "
 223                     "Unable to find this on global HCA list");
 224                 return (IBT_HCA_HDL_INVALID);
 225         }
 226 
 227         /* Make sure resources have been freed. */
 228         error = 0;
 229         IBTL_CLOSE_RESOURCE_CHECK(hca_hdl->ha_qp_cnt, "QP/Channel");
 230         IBTL_CLOSE_RESOURCE_CHECK(hca_hdl->ha_eec_cnt, "EEC");
 231         IBTL_CLOSE_RESOURCE_CHECK(hca_hdl->ha_cq_cnt, "CQ");
 232         IBTL_CLOSE_RESOURCE_CHECK(hca_hdl->ha_pd_cnt, "Protection Domain");
 233         IBTL_CLOSE_RESOURCE_CHECK(hca_hdl->ha_ah_cnt, "AH");
 234         IBTL_CLOSE_RESOURCE_CHECK(hca_hdl->ha_mr_cnt, "Memory Region");
 235         IBTL_CLOSE_RESOURCE_CHECK(hca_hdl->ha_mw_cnt, "Memory Window");
 236         IBTL_CLOSE_RESOURCE_CHECK(hca_hdl->ha_qpn_cnt, "QPN");
 237         IBTL_CLOSE_RESOURCE_CHECK(hca_hdl->ha_srq_cnt, "SRQ");
 238         IBTL_CLOSE_RESOURCE_CHECK(hca_hdl->ha_fmr_pool_cnt, "FMR Pool");
 239         if (error) {
 240                 mutex_exit(&ibtl_clnt_list_mutex);
 241                 return (IBT_HCA_RESOURCES_NOT_FREED);
 242         }
 243 
 244         /* we are now committed to closing the HCA */
 245         hca_hdl->ha_flags |= IBTL_HA_CLOSING;
 246         while (hca_hdl->ha_qpn_cnt > 0)
 247                 cv_wait(&ibtl_close_hca_cv, &ibtl_clnt_list_mutex);
 248 
 249         /*
 250          * Remove this HCA Device entry form Client's current list of HCA
 251          * Device Instances being used by it.
 252          */
 253         hcapp = &clntp->clnt_hca_list;
 254 
 255         for (; *hcapp != NULL; hcapp = &(*hcapp)->ha_hca_link)
 256                 if (*hcapp == hca_hdl)
 257                         break;
 258 
 259         if (*hcapp == NULL) {
 260                 IBTF_DPRINTF_L2(ibtf_hca, "ibt_close_hca: "
 261                     "Unable to find this HCA on client list");
 262                 mutex_exit(&ibtl_clnt_list_mutex);
 263                 return (IBT_HCA_HDL_INVALID);
 264         }
 265 
 266         /* hcapp now points to a link that points to us */
 267         *hcapp = hca_hdl->ha_hca_link;               /* remove us */
 268 
 269         /*
 270          * Remove this Client's entry from this HCA Device's Clients list.
 271          */
 272         hcapp = &hca_devp->hd_clnt_list;
 273 
 274         for (; *hcapp != NULL; hcapp = &(*hcapp)->ha_clnt_link)
 275                 if (*hcapp == hca_hdl)
 276                         break;
 277 
 278         if (*hcapp == NULL) {
 279                 mutex_exit(&ibtl_clnt_list_mutex);
 280                 IBTF_DPRINTF_L2(ibtf_hca, "ibt_close_hca: "
 281                     "Unable to find this HCA on the client's HCA list");
 282                 return (IBT_HCA_HDL_INVALID);
 283         }
 284 
 285         /* hcapp now points to a link that points to us */
 286         *hcapp = hca_hdl->ha_clnt_link;              /* remove us */
 287         mutex_exit(&ibtl_clnt_list_mutex);
 288 
 289         /* Free memory for this HCA Handle */
 290         ibtl_free_hca_async_check(hca_hdl);
 291 
 292         return (IBT_SUCCESS);
 293 }
 294 
 295 void
 296 ibtl_close_hca_check(ibt_hca_hdl_t hca_hdl)
 297 {
 298         IBTF_DPRINTF_L3(ibtf_hca, "ibtl_close_hca_check(%p)", hca_hdl);
 299 
 300         mutex_enter(&ibtl_clnt_list_mutex);
 301         if ((--hca_hdl->ha_qpn_cnt == 0) &&
 302             (hca_hdl->ha_flags & IBTL_HA_CLOSING)) {
 303                 cv_signal(&ibtl_close_hca_cv);
 304         }
 305         mutex_exit(&ibtl_clnt_list_mutex);
 306 }
 307 
 308 /*
 309  * Function:
 310  *      ibt_get_hca_list
 311  * Input:
 312  *      hca_list_p -  Address of pointer updated here.
 313  * Output:
 314  *      hca_list_p -  Points to an array of ib_guid_t's allocated here.
 315  * Returns:
 316  *      The actual number of valid ib_guid_t's returned.
 317  * Description:
 318  *      If hca_list_p is not NULL then the memory for the array of GUIDs is
 319  *      allocated here and should be freed by the caller using
 320  *      ibt_free_hca_list(). If hca_list_p is NULL then no memory is allocated
 321  *      by ibt_get_hca_list and only the number of HCAs in a system is returned.
 322  */
 323 uint_t
 324 ibt_get_hca_list(ib_guid_t **hca_list_p)
 325 {
 326         uint_t                  hca_count = 0;
 327         ibtl_hca_devinfo_t      *hca_devp;
 328         ib_guid_t               *hca_listp;
 329 
 330         IBTF_DPRINTF_L3(ibtf_hca, "ibt_get_hca_list(%p)", hca_list_p);
 331 
 332         mutex_enter(&ibtl_clnt_list_mutex);
 333 
 334         hca_devp = ibtl_hca_list;
 335         while (hca_devp != NULL) {
 336                 hca_count++;
 337                 hca_devp = hca_devp->hd_hca_dev_link;
 338         }
 339 
 340         if (hca_count == 0)
 341                 IBTF_DPRINTF_L2(ibtf_hca, "ibt_get_hca_list: "
 342                     "HCA device not found");
 343 
 344         if ((hca_count == 0) || (hca_list_p == NULL)) {
 345                 mutex_exit(&ibtl_clnt_list_mutex);
 346                 return (hca_count);
 347         }
 348 
 349         hca_listp = kmem_alloc(hca_count * sizeof (ib_guid_t), KM_SLEEP);
 350         *hca_list_p = hca_listp;
 351 
 352         hca_devp = ibtl_hca_list;
 353         while (hca_devp != NULL) {
 354                 /* Traverse Global HCA List & retrieve HCA Node GUIDs. */
 355                 *hca_listp++ = hca_devp->hd_hca_attr->hca_node_guid;
 356                 hca_devp = hca_devp->hd_hca_dev_link;
 357         }
 358         mutex_exit(&ibtl_clnt_list_mutex);
 359 
 360         IBTF_DPRINTF_L3(ibtf_hca, "ibt_get_hca_list: "
 361             "Returned <%d> entries @0x%p", hca_count, *hca_list_p);
 362 
 363         return (hca_count);
 364 }
 365 
 366 /*
 367  * Function:
 368  *      ibt_free_hca_list
 369  * Input:
 370  *      hca_list  - The address of an ib_guid_t pointer.
 371  *      entries   - The number of ib_guid_t entries to be freed.
 372  * Output:
 373  *      none.
 374  * Returns:
 375  *      none.
 376  * Description:
 377  *      The memory allocated in ibt_get_hca_list() is freed in this function.
 378  */
 379 void
 380 ibt_free_hca_list(ib_guid_t *hca_list, uint_t entries)
 381 {
 382         IBTF_DPRINTF_L3(ibtf_hca, "ibt_free_hca_list: "
 383             "Free <%d> entries from 0x%p", entries, hca_list);
 384 
 385         if ((hca_list != NULL) && (entries > 0))
 386                 kmem_free(hca_list, entries * sizeof (ib_guid_t));
 387 }
 388 
 389 /*
 390  * ibtl_portinfo_locked() is called when the portinfo cache is being
 391  * updated.  If this port's info update is in progress, we return 0
 392  * immediately and have the c
 393  * unless it's already in progress (distinguished by return value).
 394  * When done updating the portinfo, they call ibtl_portinfo_unlock().
 395  */
 396 
 397 static int
 398 ibtl_portinfo_locked(ibtl_hca_devinfo_t *hca_devp, uint8_t port)
 399 {
 400         ASSERT(MUTEX_HELD(&ibtl_clnt_list_mutex));
 401 
 402         for (;;) {
 403                 if (hca_devp->hd_portinfo_locked_port == 0) {
 404                         hca_devp->hd_portinfo_locked_port = port;
 405                         return (1); /* not busy, so OK to initiate update */
 406                 } else if (hca_devp->hd_portinfo_locked_port == port) {
 407                         IBTF_DPRINTF_L3(ibtf_hca, "ibtl_portinfo_locked: "
 408                             "HCA %p port %d is already locked",
 409                             hca_devp, port);
 410                         hca_devp->hd_portinfo_waiters = 1;
 411                         cv_wait(&hca_devp->hd_portinfo_cv,
 412                             &ibtl_clnt_list_mutex);
 413                         return (0); /* it's now done, so no need to initiate */
 414                 } else {
 415                         /* need to wait for other port before we try again */
 416                         hca_devp->hd_portinfo_waiters = 1;
 417                         cv_wait(&hca_devp->hd_portinfo_cv,
 418                             &ibtl_clnt_list_mutex);
 419                 }
 420         }
 421 }
 422 
 423 static void
 424 ibtl_portinfo_unlock(ibtl_hca_devinfo_t *hca_devp, uint8_t port)
 425 {
 426         ASSERT(MUTEX_HELD(&ibtl_clnt_list_mutex));
 427         ASSERT(hca_devp->hd_portinfo_locked_port == port);
 428         hca_devp->hd_portinfo_locked_port = 0;
 429         if (hca_devp->hd_portinfo_waiters) {
 430                 hca_devp->hd_portinfo_waiters = 0;
 431                 cv_broadcast(&hca_devp->hd_portinfo_cv);
 432                 IBTF_DPRINTF_L3(ibtf_hca, "ibtl_portinfo_unlock: "
 433                     "waking up waiters for port %d info on HCA %p",
 434                     port, hca_devp);
 435         }
 436 }
 437 
 438 /*
 439  * Function:
 440  *      ibt_get_port_state
 441  * Input:
 442  *      hca_devp    - The HCA Dev Info pointer.
 443  *      port        - Port number to query.
 444  * Output:
 445  *      sgid_p      - Returned sgid[0], NULL implies no return value.
 446  *      base_lid_p  - Returned base_lid, NULL implies no return value.
 447  * Returns:
 448  *      IBT_SUCCESS
 449  *      IBT_HCA_PORT_INVALID
 450  * Description:
 451  *      Returns HCA port attributes for one of the HCA ports.
 452  */
 453 static ibt_status_t
 454 ibtl_get_port_state(ibtl_hca_devinfo_t *hca_devp, uint8_t port,
 455     ib_gid_t *sgid_p, ib_lid_t *base_lid_p)
 456 {
 457         ibt_hca_portinfo_t *portinfop;
 458 
 459         ASSERT(MUTEX_HELD(&ibtl_clnt_list_mutex));
 460 
 461         if ((port < 1) || (port > hca_devp->hd_hca_attr->hca_nports)) {
 462                 IBTF_DPRINTF_L2(ibtf_hca, "ibtl_get_port_state: "
 463                     "invalid port %d, nports = %d", port,
 464                     hca_devp->hd_hca_attr->hca_nports);
 465                 return (IBT_HCA_PORT_INVALID);
 466         }
 467         portinfop = hca_devp->hd_portinfop + port - 1;
 468         if (portinfop->p_linkstate != IBT_PORT_ACTIVE)
 469                 ibtl_reinit_hca_portinfo(hca_devp, port);
 470 
 471         if (sgid_p)
 472                 *sgid_p = portinfop->p_sgid_tbl[0];
 473         if (base_lid_p)
 474                 *base_lid_p = portinfop->p_base_lid;
 475         if (portinfop->p_linkstate != IBT_PORT_ACTIVE) {
 476                 IBTF_DPRINTF_L2(ibtf_hca, "ibtl_get_port_state: "
 477                     "port %d, port_state %d, base_lid %d",
 478                     port, portinfop->p_linkstate, portinfop->p_base_lid);
 479                 return (IBT_HCA_PORT_NOT_ACTIVE);
 480         }
 481         IBTF_DPRINTF_L3(ibtf_hca, "ibtl_get_port_state: "
 482             "port %d, port_state %d, base_lid %d",
 483             port, portinfop->p_linkstate, portinfop->p_base_lid);
 484         return (IBT_SUCCESS);
 485 }
 486 
 487 /*
 488  * Function:
 489  *      ibt_get_port_state
 490  * Input:
 491  *      hca_hdl     - The HCA handle.
 492  *      port        - Port number to query.
 493  * Output:
 494  *      sgid_p      - Returned sgid[0], NULL implies no return value.
 495  *      base_lid_p  - Returned base_lid, NULL implies no return value.
 496  * Returns:
 497  *      IBT_SUCCESS
 498  *      IBT_HCA_PORT_INVALID
 499  * Description:
 500  *      Returns HCA port attributes for one of the HCA ports.
 501  */
 502 ibt_status_t
 503 ibt_get_port_state(ibt_hca_hdl_t hca_hdl, uint8_t port,
 504     ib_gid_t *sgid_p, ib_lid_t *base_lid_p)
 505 {
 506         ibt_status_t            retval;
 507 
 508         IBTF_DPRINTF_L3(ibtf_hca, "ibt_get_port_state(%p, %d, %p, %p)",
 509             hca_hdl, port, sgid_p, base_lid_p);
 510         mutex_enter(&ibtl_clnt_list_mutex);
 511         retval = ibtl_get_port_state(hca_hdl->ha_hca_devp, port, sgid_p,
 512             base_lid_p);
 513         mutex_exit(&ibtl_clnt_list_mutex);
 514         return (retval);
 515 }
 516 
 517 
 518 /*
 519  * Function:
 520  *      ibt_get_port_state_byguid
 521  * Input:
 522  *      hca_guid    - The HCA node GUID.
 523  *      port        - Port number to query.
 524  * Output:
 525  *      sgid_p      - Returned sgid[0], NULL implies no return value.
 526  *      base_lid_p  - Returned base_lid, NULL implies no return value.
 527  * Returns:
 528  *      IBT_SUCCESS
 529  *      IBT_HCA_PORT_INVALID
 530  *      IBT_HCA_INVALID
 531  * Description:
 532  *      Returns HCA port attributes for one of the HCA ports.
 533  */
 534 ibt_status_t
 535 ibt_get_port_state_byguid(ib_guid_t hca_guid, uint8_t port,
 536     ib_gid_t *sgid_p, ib_lid_t *base_lid_p)
 537 {
 538         ibtl_hca_devinfo_t      *hca_devp;              /* HCA Dev Info */
 539         ibt_status_t            retval;
 540 
 541         IBTF_DPRINTF_L3(ibtf_hca, "ibt_get_port_state_byguid(%llx, %d, %p, "
 542             "%p)", (longlong_t)hca_guid, port, sgid_p, base_lid_p);
 543         mutex_enter(&ibtl_clnt_list_mutex);
 544         hca_devp = ibtl_get_hcadevinfo(hca_guid);
 545         if (hca_devp == NULL)
 546                 retval = IBT_HCA_INVALID;
 547         else
 548                 retval = ibtl_get_port_state(hca_devp, port, sgid_p,
 549                     base_lid_p);
 550         mutex_exit(&ibtl_clnt_list_mutex);
 551         return (retval);
 552 }
 553 
 554 
 555 /*
 556  * Function:
 557  *      ibt_query_hca_byguid
 558  * Input:
 559  *      hca_guid  - The HCA node GUID.
 560  * Output:
 561  *      hca_attrs - A pointer to a ibt_hca_attr_t allocated by the caller,
 562  *                  into which the HCA Attributes are copied.
 563  * Returns:
 564  *      IBT_SUCCESS
 565  *      IBT_INVALID_PARAM
 566  *      IBT_HCA_INVALID
 567  * Description:
 568  *      Returns the static attributes of the specified HCA.
 569  */
 570 ibt_status_t
 571 ibt_query_hca_byguid(ib_guid_t hca_guid, ibt_hca_attr_t *hca_attrs)
 572 {
 573         ibtl_hca_devinfo_t      *hca_devp;      /* HCA Dev Info. */
 574 
 575         IBTF_DPRINTF_L3(ibtf_hca, "ibt_query_hca_byguid(%llX)", hca_guid);
 576 
 577         mutex_enter(&ibtl_clnt_list_mutex);
 578         /* Get HCA Dev Info Structure, referenced by HCA GUID. */
 579         hca_devp = ibtl_get_hcadevinfo(hca_guid);
 580         if (hca_devp == NULL) {
 581                 /*
 582                  * If we are here, then the requested HCA device is not present.
 583                  */
 584                 mutex_exit(&ibtl_clnt_list_mutex);
 585                 IBTF_DPRINTF_L2(ibtf_hca, "ibt_query_hca_byguid: "
 586                     "Device Not Found");
 587                 return (IBT_HCA_INVALID);
 588         }
 589 
 590         /* Return back the static HCA attributes */
 591         bcopy(hca_devp->hd_hca_attr, hca_attrs, sizeof (ibt_hca_attr_t));
 592 
 593         mutex_exit(&ibtl_clnt_list_mutex);
 594 
 595         return (IBT_SUCCESS);
 596 }
 597 
 598 
 599 /*
 600  * Function:
 601  *      ibt_query_hca
 602  * Input:
 603  *      hca_hdl   - The HCA handle.
 604  * Output:
 605  *      hca_attrs - A pointer to a ibt_hca_attr_t allocated by the caller,
 606  *                  into which the HCA Attributes are copied.
 607  * Returns:
 608  *      IBT_SUCCESS
 609  *
 610  * Description:
 611  *      Returns the static attributes of the specified HCA.
 612  */
 613 ibt_status_t
 614 ibt_query_hca(ibt_hca_hdl_t hca_hdl, ibt_hca_attr_t *hca_attrs)
 615 {
 616         IBTF_DPRINTF_L3(ibtf_hca, "ibt_query_hca(%p)", hca_hdl);
 617 
 618         /* Return back the static HCA attributes */
 619         bcopy(hca_hdl->ha_hca_devp->hd_hca_attr, hca_attrs,
 620             sizeof (ibt_hca_attr_t));
 621 
 622         return (IBT_SUCCESS);
 623 }
 624 
 625 #define ROUNDUP(x, y)   ((((x)+((y)-1))/(y))*(y))
 626 
 627 /*
 628  * Function:
 629  *      ibt_query_hca_ports
 630  * Input:
 631  *      hca_hdl     - The HCA handle.
 632  *      port        - Port number.  If "0", then query ALL Ports.
 633  * Output:
 634  *      port_info_p - The address of a pointer to a ibt_hca_portinfo_t struct.
 635  *      ports_p     - The number of hca ports on the specified HCA.
 636  *      size_p      - Size of the memory allocated by IBTL to get portinfo,
 637  *                   to be freed by calling ibt_free_portinfo().
 638  * Returns:
 639  *      IBT_SUCCESS
 640  *      IBT_HCA_HDL_INVALID
 641  *      IBT_HCA_INVALID
 642  * Description:
 643  *      Returns HCA port attributes for either "one", or "all" of the HCA ports.
 644  */
 645 ibt_status_t
 646 ibt_query_hca_ports(ibt_hca_hdl_t hca_hdl, uint8_t port,
 647     ibt_hca_portinfo_t **port_info_p, uint_t *ports_p, uint_t *size_p)
 648 {
 649         ibt_status_t    retval;
 650 
 651         IBTF_DPRINTF_L3(ibtf_hca, "ibt_query_hca_ports(%p, %d)",
 652             hca_hdl, port);
 653 
 654         mutex_enter(&ibtl_clnt_list_mutex);
 655 
 656         retval = ibtl_query_hca_ports(hca_hdl->ha_hca_devp, port, port_info_p,
 657             ports_p, size_p, 0);
 658 
 659         mutex_exit(&ibtl_clnt_list_mutex);
 660 
 661         return (retval);
 662 }
 663 
 664 /*
 665  * Function:
 666  *      ibt_query_hca_ports_byguid
 667  * Input:
 668  *      hca_guid    - The HCA node GUID.
 669  *      port        - Port number.  If "0", then query ALL Ports.
 670  * Output:
 671  *      port_info_p - The address of a pointer to a ibt_hca_portinfo_t struct.
 672  *      ports_p     - The number of hca ports on the specified HCA.
 673  *      size_p      - Size of the memory allocated by IBTL to get portinfo,
 674  *                   to be freed by calling ibt_free_portinfo().
 675  * Returns:
 676  *      IBT_SUCCESS
 677  *      IBT_HCA_HDL_INVALID
 678  *      IBT_HCA_INVALID
 679  * Description:
 680  *      Returns HCA port attributes for either "one", or "all" of the HCA ports.
 681  */
 682 ibt_status_t
 683 ibt_query_hca_ports_byguid(ib_guid_t hca_guid, uint8_t port,
 684     ibt_hca_portinfo_t **port_info_p, uint_t *ports_p, uint_t *size_p)
 685 {
 686         ibtl_hca_devinfo_t      *hca_devp;      /* HCA Dev Info */
 687         ibt_status_t            retval;
 688 
 689         mutex_enter(&ibtl_clnt_list_mutex);
 690         hca_devp = ibtl_get_hcadevinfo(hca_guid);
 691         if (hca_devp == NULL) {
 692                 /*
 693                  * If we are here, then the requested HCA device is not present.
 694                  * Return the status as Invalid HCA GUID.
 695                  */
 696                 *ports_p = *size_p = 0;
 697                 *port_info_p = NULL;
 698                 mutex_exit(&ibtl_clnt_list_mutex);
 699                 IBTF_DPRINTF_L2(ibtf_hca, "ibt_query_hca_ports_byguid: "
 700                     "HCA Device Not Found. ");
 701                 return (IBT_HCA_INVALID);
 702         }
 703 
 704         retval = ibtl_query_hca_ports(hca_devp, port, port_info_p, ports_p,
 705             size_p, 0);
 706 
 707         mutex_exit(&ibtl_clnt_list_mutex);
 708 
 709         return (retval);
 710 }
 711 
 712 /*
 713  * Define the above function for CM's use that uses the cached copy.
 714  */
 715 ibt_status_t
 716 ibtl_cm_query_hca_ports_byguid(ib_guid_t hca_guid, uint8_t port,
 717     ibt_hca_portinfo_t **port_info_p, uint_t *ports_p, uint_t *size_p)
 718 {
 719         ibtl_hca_devinfo_t      *hca_devp;      /* HCA Dev Info */
 720         ibt_status_t            retval;
 721 
 722         mutex_enter(&ibtl_clnt_list_mutex);
 723         hca_devp = ibtl_get_hcadevinfo(hca_guid);
 724         if (hca_devp == NULL) {
 725                 /*
 726                  * If we are here, then the requested HCA device is not present.
 727                  * Return the status as Invalid HCA GUID.
 728                  */
 729                 *ports_p = *size_p = 0;
 730                 *port_info_p = NULL;
 731                 mutex_exit(&ibtl_clnt_list_mutex);
 732                 IBTF_DPRINTF_L2(ibtf_hca, "ibt_query_hca_ports_byguid: "
 733                     "HCA Device Not Found. ");
 734                 return (IBT_HCA_INVALID);
 735         }
 736 
 737         retval = ibtl_query_hca_ports(hca_devp, port, port_info_p, ports_p,
 738             size_p, 1);
 739 
 740         mutex_exit(&ibtl_clnt_list_mutex);
 741 
 742         return (retval);
 743 }
 744 
 745 
 746 /*
 747  * ibtl_query_one_port - fill in portinfo for one port.
 748  */
 749 static ibt_status_t
 750 ibtl_query_one_port(ibtl_hca_devinfo_t *hca_devp, uint8_t port,
 751     ibt_hca_portinfo_t **port_info_p, uint_t *ports_p, uint_t *size_p,
 752     int use_cache)
 753 {
 754         ibt_hca_portinfo_t      *sp1;   /* src */
 755         ibt_hca_portinfo_t      *p1;    /* dst */
 756         caddr_t                 p2;
 757         uint_t                  len;
 758         uint_t                  sgid_tbl_len, pkey_tbl_len;
 759 
 760         ASSERT(MUTEX_HELD(&ibtl_clnt_list_mutex));
 761 
 762         IBTF_DPRINTF_L3(ibtf_hca, "ibtl_query_one_port(%p, %d)",
 763             hca_devp, port);
 764 
 765         if (port > hca_devp->hd_hca_attr->hca_nports) {
 766                 IBTF_DPRINTF_L2(ibtf_hca, "ibtl_query_one_port: "
 767                     "invalid port %d", port);
 768                 return (IBT_HCA_PORT_INVALID);
 769         }
 770 
 771         /* If the PORT_UP event is not supported, we need to query */
 772         sp1 = hca_devp->hd_portinfop + port - 1;
 773         if (use_cache == 0)
 774                 ibtl_reinit_hca_portinfo(hca_devp, port);
 775 
 776         *ports_p = 1;
 777 
 778         /*
 779          * Calculate how much memory we need for one port, and allocate it.
 780          */
 781         sgid_tbl_len = ROUNDUP(sp1->p_sgid_tbl_sz * sizeof (ib_gid_t),
 782             _LONG_LONG_ALIGNMENT);
 783         pkey_tbl_len = ROUNDUP(sp1->p_pkey_tbl_sz * sizeof (ib_pkey_t),
 784             _LONG_LONG_ALIGNMENT);
 785 
 786         len = sizeof (ibt_hca_portinfo_t) + sgid_tbl_len + pkey_tbl_len;
 787         *size_p = len;
 788 
 789         p1 = kmem_zalloc(len, KM_SLEEP);
 790         *port_info_p = p1;
 791         bcopy(sp1, p1, sizeof (ibt_hca_portinfo_t));
 792 
 793         /* initialize the p_pkey_tbl & p_sgid_tbl pointers. */
 794         p2 = (caddr_t)(p1 + 1); /* pkeys follow the struct ibt_hca_portinfo_s */
 795         bcopy(sp1->p_pkey_tbl, p2, pkey_tbl_len);
 796         p1->p_pkey_tbl = (ib_pkey_t *)p2;
 797 
 798         p2 += pkey_tbl_len;     /* sgids follow the pkeys */
 799         bcopy(sp1->p_sgid_tbl, p2, sgid_tbl_len);
 800         p1->p_sgid_tbl = (ib_gid_t *)p2;
 801 
 802         return (IBT_SUCCESS);
 803 }
 804 
 805 /*
 806  * ibtl_query_hca_ports - worker routine to get port_info for clients.
 807  */
 808 static ibt_status_t
 809 ibtl_query_hca_ports(ibtl_hca_devinfo_t *hca_devp, uint8_t port,
 810     ibt_hca_portinfo_t **port_info_p, uint_t *ports_p, uint_t *size_p,
 811     int use_cache)
 812 {
 813         ibt_hca_portinfo_t      *sp1;   /* src */
 814         ibt_hca_portinfo_t      *p1;    /* dst */
 815         uint_t                  i, nports;
 816         caddr_t                 p2;
 817         uint_t                  len;
 818         uint_t                  sgid_tbl_len, pkey_tbl_len;
 819 
 820         ASSERT(MUTEX_HELD(&ibtl_clnt_list_mutex));
 821 
 822         /*
 823          * If user has specified the port num, then query only that port,
 824          * else query all ports.
 825          */
 826         if (port)
 827                 return (ibtl_query_one_port(hca_devp, port, port_info_p,
 828                     ports_p, size_p, use_cache));
 829 
 830         IBTF_DPRINTF_L3(ibtf_hca, "ibtl_query_hca_ports(%p, ALL)", hca_devp);
 831 
 832         nports = hca_devp->hd_hca_attr->hca_nports;
 833         *ports_p = nports;
 834 
 835         /* If the PORT_UP event is not supported, we need to query */
 836         if (use_cache == 0)
 837                 for (i = 0; i < nports; i++)
 838                         ibtl_reinit_hca_portinfo(hca_devp, i + 1);
 839 
 840         sp1 = hca_devp->hd_portinfop;
 841 
 842         /*
 843          * Calculate how much memory we need for all ports, and allocate it.
 844          */
 845         sgid_tbl_len = ROUNDUP(sp1->p_sgid_tbl_sz * sizeof (ib_gid_t),
 846             _LONG_LONG_ALIGNMENT);
 847         pkey_tbl_len = ROUNDUP(sp1->p_pkey_tbl_sz * sizeof (ib_pkey_t),
 848             _LONG_LONG_ALIGNMENT);
 849 
 850         len = (sizeof (ibt_hca_portinfo_t) + sgid_tbl_len + pkey_tbl_len) *
 851             nports;
 852         *size_p = len;
 853 
 854         ASSERT(len == hca_devp->hd_portinfo_len);
 855 
 856         p1 = kmem_zalloc(len, KM_SLEEP);
 857         *port_info_p = p1;
 858         bcopy(sp1, p1, len);    /* start with an exact copy of our cache */
 859 
 860         p2 = (caddr_t)(p1 + nports);
 861 
 862         /* For each port, update the p_pkey_tbl & p_sgid_tbl ptrs. */
 863         for (i = 0; i < nports; i++) {
 864                 p1->p_pkey_tbl = (ib_pkey_t *)p2;
 865                 p2 += pkey_tbl_len;
 866                 p1->p_sgid_tbl = (ib_gid_t *)p2;
 867                 p2 += sgid_tbl_len;
 868                 p1++;
 869         }
 870         return (IBT_SUCCESS);
 871 }
 872 
 873 /*
 874  *      Search for a Full pkey.  Use the pkey at index 0 if not found.
 875  */
 876 static void
 877 ibtl_set_default_pkey_ix(ibt_hca_portinfo_t *p1)
 878 {
 879         uint16_t        pkey_ix;
 880 
 881         for (pkey_ix = 0; pkey_ix < p1->p_pkey_tbl_sz; pkey_ix++) {
 882                 if ((p1->p_pkey_tbl[pkey_ix] & 0x8000) &&
 883                     (p1->p_pkey_tbl[pkey_ix] != IB_PKEY_INVALID_FULL)) {
 884                         p1->p_def_pkey_ix = pkey_ix;
 885                         IBTF_DPRINTF_L3(ibtf_hca,
 886                             "ibtl_set_default_pkey_ix: portinfop %p, "
 887                             "FULL PKEY 0x%x found, pkey_ix is %d",
 888                             p1, p1->p_pkey_tbl[pkey_ix], pkey_ix);
 889                         return;
 890                 }
 891         }
 892         IBTF_DPRINTF_L2(ibtf_hca,
 893             "ibtl_set_default_pkey_ix: portinfop %p: failed "
 894             "to find a default PKEY in the table, using PKey 0x%x",
 895             p1, p1->p_pkey_tbl[0]);
 896         p1->p_def_pkey_ix = 0;
 897 }
 898 
 899 /*
 900  * ibtl_reinit_hca_portinfo - update the portinfo cache for use by IBTL.
 901  *
 902  * We have the HCA driver fill in a temporary portinfo, then we bcopy
 903  * it into our cache while holding the appropriate lock.
 904  */
 905 void
 906 ibtl_reinit_hca_portinfo(ibtl_hca_devinfo_t *hca_devp, uint8_t port)
 907 {
 908         ibt_status_t            status;
 909         ibt_hca_portinfo_t      *p1, *sp1;
 910         ibt_port_state_t        old_linkstate;
 911         uint_t                  len, sgid_tbl_len, pkey_tbl_len;
 912         ib_pkey_t               *saved_pkey_tbl;
 913         ib_gid_t                *saved_sgid_tbl;
 914         ib_sn_prefix_t          sn_pfx = 0;
 915         uint_t                  multiSM;
 916         int                     i;
 917 
 918         IBTF_DPRINTF_L3(ibtf_hca, "ibtl_reinit_hca_portinfo(%p, %d)",
 919             hca_devp, port);
 920 
 921         ASSERT(MUTEX_HELD(&ibtl_clnt_list_mutex));
 922         ASSERT(port != 0);
 923 
 924         if (ibtl_portinfo_locked(hca_devp, port)) {
 925                 /* we got the lock, so we need to do the portinfo update */
 926 
 927                 /* invalidate fast_gid_cache */
 928                 ibtl_fast_gid_cache_valid = B_FALSE;
 929 
 930                 p1 = hca_devp->hd_portinfop + port - 1;
 931                 sgid_tbl_len = ROUNDUP(p1->p_sgid_tbl_sz * sizeof (ib_gid_t),
 932                     _LONG_LONG_ALIGNMENT);
 933                 pkey_tbl_len = ROUNDUP(p1->p_pkey_tbl_sz * sizeof (ib_pkey_t),
 934                     _LONG_LONG_ALIGNMENT);
 935                 len = sizeof (ibt_hca_portinfo_t) + sgid_tbl_len + pkey_tbl_len;
 936 
 937                 /* update was NOT in progress, so we do it here */
 938                 mutex_exit(&ibtl_clnt_list_mutex);
 939 
 940                 IBTF_DPRINTF_L3(ibtf_hca, "ibtl_reinit_hca_portinfo(%p, %d): "
 941                     "calling ibc_query_hca_ports", hca_devp, port);
 942 
 943                 sp1 = kmem_zalloc(len, KM_SLEEP);
 944                 sp1->p_pkey_tbl = (ib_pkey_t *)(sp1 + 1);
 945                 sp1->p_sgid_tbl =
 946                     (ib_gid_t *)((caddr_t)sp1->p_pkey_tbl + pkey_tbl_len);
 947                 status = IBTL_HDIP2CIHCAOPS_P(hca_devp)->ibc_query_hca_ports(
 948                     IBTL_HDIP2CIHCA(hca_devp), port, sp1);
 949 
 950                 mutex_enter(&ibtl_clnt_list_mutex);
 951                 if (status != IBT_SUCCESS) {
 952                         IBTF_DPRINTF_L2(ibtf_hca,
 953                             "ibtl_reinit_hca_portinfo(%p, %d): "
 954                             "ibc_query_hca_ports() failed: status = %d",
 955                             hca_devp, port, status);
 956                 } else {
 957                         old_linkstate = p1->p_linkstate;
 958                         bcopy(sp1->p_pkey_tbl, p1->p_pkey_tbl, pkey_tbl_len);
 959                         bcopy(sp1->p_sgid_tbl, p1->p_sgid_tbl, sgid_tbl_len);
 960                         saved_pkey_tbl = p1->p_pkey_tbl;
 961                         saved_sgid_tbl = p1->p_sgid_tbl;
 962                         bcopy(sp1, p1, sizeof (ibt_hca_portinfo_t));
 963                         p1->p_pkey_tbl = saved_pkey_tbl;
 964                         p1->p_sgid_tbl = saved_sgid_tbl;
 965                         if (p1->p_linkstate == IBT_PORT_ACTIVE) {
 966                                 ibtl_set_default_pkey_ix(p1);
 967                                 if (p1->p_linkstate != old_linkstate)
 968                                         IBTF_DPRINTF_L2(ibtf_hca,
 969                                             "ibtl_reinit_hca_portinfo(%p, %d): "
 970                                             "PORT UP", hca_devp, port);
 971                         } else {
 972                                 if (p1->p_linkstate != IBT_PORT_ARM)
 973                                         p1->p_base_lid = 0;
 974                                 if (p1->p_linkstate != old_linkstate)
 975                                         IBTF_DPRINTF_L2(ibtf_hca,
 976                                             "ibtl_reinit_hca_portinfo(%p, %d): "
 977                                             "PORT DOWN", hca_devp, port);
 978                         }
 979                 }
 980                 kmem_free(sp1, len);
 981 
 982                 /* Set multism bit accordingly. */
 983                 multiSM = 0;
 984                 p1 = hca_devp->hd_portinfop;
 985                 for (i = 0; i < hca_devp->hd_hca_attr->hca_nports; i++) {
 986                         if (p1->p_linkstate == IBT_PORT_ACTIVE) {
 987                                 if (sn_pfx == 0) {
 988                                         sn_pfx = p1->p_sgid_tbl[0].gid_prefix;
 989                                 } else if (sn_pfx !=
 990                                     p1->p_sgid_tbl[0].gid_prefix) {
 991                                         multiSM = 1;
 992                                         IBTF_DPRINTF_L3(ibtf_hca,
 993                                             "ibtl_reinit_hca_portinfo: "
 994                                             "MULTI SM, Port1 SnPfx=0x%llX, "
 995                                             "Port2 SnPfx=0x%llX", sn_pfx,
 996                                             p1->p_sgid_tbl[0].gid_prefix);
 997                                 }
 998                         }
 999                         p1++;
1000                 }
1001                 hca_devp->hd_multism = multiSM;
1002 
1003                 ibtl_portinfo_unlock(hca_devp, port);
1004         }
1005 }
1006 
1007 /*
1008  * ibtl_init_hca_portinfo - fill in the portinfo cache for use by IBTL.
1009  */
1010 ibt_status_t
1011 ibtl_init_hca_portinfo(ibtl_hca_devinfo_t *hca_devp)
1012 {
1013         ibt_hca_portinfo_t      *p1;
1014         ibt_status_t            retval;
1015         uint_t                  i, nports;
1016         caddr_t                 p2;
1017         uint_t                  len;
1018         uint_t                  sgid_tbl_len, pkey_tbl_len;
1019         uint_t                  sgid_tbl_sz, pkey_tbl_sz;
1020         ib_sn_prefix_t          sn_pfx = 0;
1021         uint_t                  multiSM;
1022 
1023         IBTF_DPRINTF_L2(ibtf_hca, "ibtl_init_hca_portinfo(%p)", hca_devp);
1024 
1025         ASSERT(MUTEX_HELD(&ibtl_clnt_list_mutex));
1026 
1027         nports = hca_devp->hd_hca_attr->hca_nports;
1028 
1029         /*
1030          * Calculate how much memory we need for all ports, and allocate it.
1031          */
1032         pkey_tbl_sz = IBTL_HDIP2PKEYTBLSZ(hca_devp);
1033         sgid_tbl_sz = IBTL_HDIP2SGIDTBLSZ(hca_devp);
1034         pkey_tbl_len = ROUNDUP(pkey_tbl_sz * sizeof (ib_pkey_t),
1035             _LONG_LONG_ALIGNMENT);
1036         sgid_tbl_len = ROUNDUP(sgid_tbl_sz * sizeof (ib_gid_t),
1037             _LONG_LONG_ALIGNMENT);
1038 
1039         len = (sizeof (ibt_hca_portinfo_t) + sgid_tbl_len + pkey_tbl_len) *
1040             nports;
1041 
1042         p1 = kmem_zalloc(len, KM_SLEEP);
1043         p2 = (caddr_t)(p1 + nports);
1044 
1045         hca_devp->hd_portinfop = p1;
1046         hca_devp->hd_portinfo_len = len;
1047 
1048         /* For each port initialize the p_pkey_tbl & p_sgid_tbl ptrs. */
1049         for (i = 0; i < nports; i++) {
1050                 p1->p_pkey_tbl_sz = pkey_tbl_sz;
1051                 p1->p_sgid_tbl_sz = sgid_tbl_sz;
1052                 p1->p_pkey_tbl = (ib_pkey_t *)p2;
1053                 p2 += pkey_tbl_len;
1054                 p1->p_sgid_tbl = (ib_gid_t *)p2;
1055                 p2 += sgid_tbl_len;
1056                 p1++;
1057         }
1058         p1 = hca_devp->hd_portinfop;
1059         mutex_exit(&ibtl_clnt_list_mutex);
1060 
1061         /* re-direct the call to CI's call */
1062         retval = IBTL_HDIP2CIHCAOPS_P(hca_devp)->ibc_query_hca_ports(
1063             IBTL_HDIP2CIHCA(hca_devp), 0, p1);
1064 
1065         mutex_enter(&ibtl_clnt_list_mutex);
1066         if (retval != IBT_SUCCESS) {
1067                 IBTF_DPRINTF_L2(ibtf_hca, "ibtl_init_hca_portinfo(%p): "
1068                     "ibc_query_hca_ports() failed: status = %d",
1069                     hca_devp, retval);
1070                 kmem_free(hca_devp->hd_portinfop, len);
1071                 hca_devp->hd_portinfop = NULL;
1072                 hca_devp->hd_portinfo_len = 0;
1073                 return (retval);
1074         }
1075 
1076         p1 = hca_devp->hd_portinfop;
1077         multiSM = 0;
1078         for (i = 0; i < nports; i++) {
1079                 if (p1->p_linkstate == IBT_PORT_ACTIVE) {
1080                         ibtl_set_default_pkey_ix(p1);
1081                         if (sn_pfx == 0) {
1082                                 sn_pfx = p1->p_sgid_tbl[0].gid_prefix;
1083                         } else if (p1->p_sgid_tbl[0].gid_prefix != sn_pfx) {
1084                                 multiSM = 1;
1085                                 IBTF_DPRINTF_L3(ibtf_hca,
1086                                     "ibtl_init_hca_portinfo: MULTI SM, "
1087                                     "Port1 SnPfx=0x%llX, Port2 SnPfx=0x%llX",
1088                                     sn_pfx, p1->p_sgid_tbl[0].gid_prefix);
1089                         }
1090                 } else {
1091                         if (p1->p_linkstate != IBT_PORT_ARM)
1092                                 p1->p_base_lid = 0;
1093                 }
1094                 p1++;
1095         }
1096         hca_devp->hd_multism = multiSM;
1097 
1098         return (IBT_SUCCESS);
1099 }
1100 
1101 /*
1102  * Function:
1103  *      ibt_modify_system_image
1104  * Input:
1105  *      hca_hdl  - The HCA handle.
1106  *      sys_guid - The New system image GUID.
1107  * Description:
1108  *      Modify specified HCA's system image GUID.
1109  */
1110 ibt_status_t
1111 ibt_modify_system_image(ibt_hca_hdl_t hca_hdl, ib_guid_t sys_guid)
1112 {
1113         ibt_status_t            retval;
1114 
1115         IBTF_DPRINTF_L3(ibtf_hca, "ibt_modify_system_image(%p, %llX)",
1116             hca_hdl, sys_guid);
1117 
1118         mutex_enter(&ibtl_clnt_list_mutex);
1119         /* Get HCA Dev Info Structure, referenced by HCA GUID. */
1120 
1121         /* re-direct the call to CI's call */
1122         retval = IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_modify_system_image(
1123             IBTL_HCA2CIHCA(hca_hdl), sys_guid);
1124 
1125         mutex_exit(&ibtl_clnt_list_mutex);
1126         return (retval);
1127 }
1128 
1129 /*
1130  * Function:
1131  *      ibt_modify_system_image_byguid
1132  *
1133  * Input:
1134  *      hca_guid - The HCA Node GUID.
1135  *      sys_guid - The New system image GUID.
1136  * Description:
1137  *      Modify specified HCA's system image GUID.
1138  */
1139 ibt_status_t
1140 ibt_modify_system_image_byguid(ib_guid_t hca_guid, ib_guid_t sys_guid)
1141 {
1142         ibtl_hca_devinfo_t      *hca_devp;      /* HCA Dev Info. */
1143         ibt_status_t            retval;
1144 
1145         IBTF_DPRINTF_L3(ibtf_hca, "ibt_modify_system_image_byguid(%llX, %llX)",
1146             hca_guid, sys_guid);
1147 
1148         mutex_enter(&ibtl_clnt_list_mutex);
1149         /* Get HCA Dev Info Structure, referenced by HCA GUID. */
1150         hca_devp = ibtl_get_hcadevinfo(hca_guid);
1151         if (hca_devp == NULL) {
1152                 /*
1153                  * If we are here, then the requested HCA device is not present.
1154                  */
1155                 mutex_exit(&ibtl_clnt_list_mutex);
1156                 return (IBT_HCA_INVALID);
1157         }
1158 
1159         /* re-direct the call to CI's call */
1160         retval = IBTL_HDIP2CIHCAOPS_P(hca_devp)->ibc_modify_system_image(
1161             IBTL_HDIP2CIHCA(hca_devp), sys_guid);
1162 
1163         mutex_exit(&ibtl_clnt_list_mutex);
1164         return (retval);
1165 }
1166 
1167 /*
1168  * Function:
1169  *      ibt_modify_port_byguid
1170  * Input:
1171  *      hca_guid - The HCA Guid.
1172  *      cmds     - A pointer to an array of ibt_port_modify_t cmds. The
1173  *                 pmod_port field specifies the port to modify (all ports if 0)
1174  *                 and the pmod_flags field specifies which attribute to reset.
1175  *      num_cmds - The number of commands in the cmds array.
1176  * Output:
1177  *      none.
1178  * Returns:
1179  *      IBT_SUCCESS
1180  *      IBT_HCA_HDL_INVALID
1181  *      IBT_HCA_CNTR_INVALID
1182  *      IBT_HCA_CNTR_VAL_INVALID
1183  * Description:
1184  *      Reset the specified port, or all ports attribute(s).
1185  */
1186 ibt_status_t
1187 ibt_modify_port_byguid(ib_guid_t hca_guid,  uint8_t port,
1188     ibt_port_modify_flags_t flags, uint8_t init_type)
1189 {
1190         ibtl_hca_devinfo_t      *hca_devp;      /* HCA Dev Info. */
1191         ibt_status_t            retval;
1192 
1193         IBTF_DPRINTF_L3(ibtf_hca, "ibt_modify_port_byguid(%llX, %d, %X, %X)",
1194             hca_guid, port, flags, init_type);
1195 
1196         mutex_enter(&ibtl_clnt_list_mutex);
1197         /* Get HCA Dev Info Structure, referenced by HCA GUID. */
1198         hca_devp = ibtl_get_hcadevinfo(hca_guid);
1199         if (hca_devp == NULL) {
1200                 /*
1201                  * If we are here, then the requested HCA device is not present.
1202                  */
1203                 mutex_exit(&ibtl_clnt_list_mutex);
1204                 return (IBT_HCA_INVALID);
1205         }
1206 
1207         /* re-direct the call to CI's call */
1208         retval = IBTL_HDIP2CIHCAOPS_P(hca_devp)->ibc_modify_ports(
1209             IBTL_HDIP2CIHCA(hca_devp), port, flags, init_type);
1210 
1211         mutex_exit(&ibtl_clnt_list_mutex);
1212         return (retval);
1213 }
1214 
1215 /*
1216  * Function:
1217  *      ibt_modify_port
1218  * Input:
1219  *      hca_hdl  - The HCA handle.
1220  *      cmds     - A pointer to an array of ibt_port_modify_t cmds. The
1221  *                 pmod_port field specifies the port to modify (all ports if 0)
1222  *                 and the pmod_flags field specifies which attribute to reset.
1223  *      num_cmds - The number of commands in the cmds array.
1224  * Output:
1225  *      none.
1226  * Returns:
1227  *      IBT_SUCCESS
1228  *      IBT_HCA_HDL_INVALID
1229  *      IBT_HCA_CNTR_INVALID
1230  *      IBT_HCA_CNTR_VAL_INVALID
1231  * Description:
1232  *      Reset the specified port, or all ports attribute(s).
1233  */
1234 ibt_status_t
1235 ibt_modify_port(ibt_hca_hdl_t hca_hdl, uint8_t port,
1236     ibt_port_modify_flags_t flags, uint8_t init_type)
1237 
1238 {
1239         ibt_status_t            retval;
1240 
1241         IBTF_DPRINTF_L3(ibtf_hca, "ibt_modify_port(%p, %d, %X, %X)",
1242             hca_hdl, port, flags, init_type);
1243 
1244         mutex_enter(&ibtl_clnt_list_mutex);
1245 
1246         /* re-direct the call to CI's call */
1247         retval = IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_modify_ports(
1248             IBTL_HCA2CIHCA(hca_hdl), port, flags, init_type);
1249 
1250         mutex_exit(&ibtl_clnt_list_mutex);
1251         return (retval);
1252 }
1253 
1254 /*
1255  * Function:
1256  *      ibt_free_portinfo
1257  * Input:
1258  *      port_info  - The address of an array to a ibt_hca_portinfo_t struct.
1259  *      size       - Memory Size as returned from ibt_query_hca_ports().
1260  * Output:
1261  *      none
1262  * Returns:
1263  *      none
1264  * Description:
1265  *      Frees the memory allocated for a specified ibt_hca_portinfo_t struct.
1266  */
1267 void
1268 ibt_free_portinfo(ibt_hca_portinfo_t *port_info, uint_t size)
1269 {
1270         IBTF_DPRINTF_L3(ibtf_hca, "ibt_free_portinfo(%p, %d)",
1271             port_info, size);
1272 
1273         if ((port_info == NULL) || (size == 0)) {
1274                 IBTF_DPRINTF_L2(ibtf_hca, "ibt_free_portinfo: NULL Pointer");
1275         } else {
1276                 kmem_free(port_info, size);
1277         }
1278 }
1279 
1280 
1281 /*
1282  * Function:
1283  *      ibt_get_hcadevinfo
1284  * Input:
1285  *      hca_guid - The HCA's node GUID.
1286  * Output:
1287  *      none.
1288  * Returns:
1289  *      Pointer to HCA Device Info structure whose HCA GUID is requested or NULL
1290  * Description:
1291  *      Get a pointer to HCA Device Info Structure for the requested HCA GUID.
1292  *      If no matching HCA GUID Device info is found, NULL is returned.
1293  */
1294 ibtl_hca_devinfo_t *
1295 ibtl_get_hcadevinfo(ib_guid_t hca_guid)
1296 {
1297         ibtl_hca_devinfo_t      *hca_devp;      /* HCA Dev Info */
1298 
1299         IBTF_DPRINTF_L3(ibtf_hca, "ibtl_get_hcadevinfo(%llX)", hca_guid);
1300 
1301         ASSERT(MUTEX_HELD(&ibtl_clnt_list_mutex));
1302 
1303         hca_devp = ibtl_hca_list;
1304 
1305         /*
1306          * Check whether a HCA device with requested Node GUID is available.
1307          * This is done, by searching the global HCA devinfo list and
1308          * comparing the Node GUID from the device attribute info.
1309          */
1310         while (hca_devp != NULL) {
1311                 if (hca_devp->hd_hca_attr->hca_node_guid == hca_guid) {
1312                         /* Match Found. */
1313                         break;
1314                 }
1315                 hca_devp = hca_devp->hd_hca_dev_link;
1316         }
1317         return (hca_devp);
1318 }
1319 
1320 
1321 /*
1322  * Function:
1323  *      ibtl_pkey2index
1324  * Input:
1325  *      hca_devp     - The IBTL HCA Device Info.
1326  *      port_num     - The HCA port number.
1327  *      pkey         - The input PKey value, whose index we are interested in.
1328  * Output:
1329  *      pkey_ix      - The PKey index returned for the specified PKey.
1330  * Returns:
1331  *      IBT_SUCCESS/IBT_HCA_PORT_INVALID/IBT_INVALID_PARAM
1332  * Description:
1333  *      Returns the PKey Index for the specified PKey, the device as specified
1334  *      by IBT HCA Handle.
1335  */
1336 static ibt_status_t
1337 ibtl_pkey2index(ibtl_hca_devinfo_t *hca_devp, uint8_t port_num,
1338     ib_pkey_t pkey, uint16_t *pkey_ix)
1339 {
1340         ibt_hca_portinfo_t      *port_infop;
1341         uint_t                  ports;
1342         uint_t                  i;
1343 
1344         IBTF_DPRINTF_L3(ibtf_hca, "ibtl_pkey2index(%p, %d, %d)",
1345             hca_devp, port_num, pkey);
1346 
1347         ASSERT(MUTEX_HELD(&ibtl_clnt_list_mutex));
1348 
1349         if ((pkey == IB_PKEY_INVALID_FULL) ||
1350             (pkey == IB_PKEY_INVALID_LIMITED))
1351                 return (IBT_INVALID_PARAM);
1352 
1353         ports = hca_devp->hd_hca_attr->hca_nports;
1354         if ((port_num == 0) || (port_num > ports)) {
1355                 IBTF_DPRINTF_L2(ibtf_hca, "ibtl_pkey2index: "
1356                     "Invalid port_num %d, range is (1 to %d)", port_num, ports);
1357                 return (IBT_HCA_PORT_INVALID);
1358         }
1359 
1360         port_infop = hca_devp->hd_portinfop + port_num - 1;
1361         for (i = 0; i < port_infop->p_pkey_tbl_sz; i++) {
1362                 if (pkey == port_infop->p_pkey_tbl[i]) {
1363                         *pkey_ix = i;
1364                         return (IBT_SUCCESS);
1365                 }
1366         }
1367         return (IBT_INVALID_PARAM);
1368 }
1369 
1370 /*
1371  * Function:
1372  *      ibtl_index2pkey
1373  * Input:
1374  *      hca_devp     - The IBTL HCA Device Info.
1375  *      port_num     - The HCA port
1376  *      pkey_ix      - The input PKey index, whose PKey we are interested in.
1377  * Output:
1378  *      pkey         - The returned PKey value.
1379  * Returns:
1380  *      IBT_SUCCESS/IBT_PKEY_IX_ILLEGAL/IBT_PKEY_IX_INVALID/IBT_HCA_PORT_INVALID
1381  * Description:
1382  *      Returns the PKey value for the specified PKey index, the device as
1383  *      specified by IBT HCA Handle.
1384  */
1385 static ibt_status_t
1386 ibtl_index2pkey(ibtl_hca_devinfo_t *hca_devp, uint8_t port_num,
1387     uint16_t pkey_ix, ib_pkey_t *pkey)
1388 {
1389         ibt_hca_portinfo_t      *port_infop;
1390         uint_t                  ports;
1391 
1392         IBTF_DPRINTF_L3(ibtf_hca, "ibtl_index2pkey(%p, %d, %d)",
1393             hca_devp, port_num, pkey_ix);
1394 
1395         ASSERT(MUTEX_HELD(&ibtl_clnt_list_mutex));
1396 
1397         ports = hca_devp->hd_hca_attr->hca_nports;
1398         if ((port_num == 0) || (port_num > ports)) {
1399                 IBTF_DPRINTF_L2(ibtf_hca, "ibtl_index2pkey: "
1400                     "Invalid port_num %d, range is (1 to %d)", port_num, ports);
1401                 return (IBT_HCA_PORT_INVALID);
1402         }
1403 
1404         port_infop = hca_devp->hd_portinfop + port_num - 1;
1405         if (pkey_ix >= port_infop->p_pkey_tbl_sz) {
1406                 IBTF_DPRINTF_L2(ibtf_hca, "ibtl_index2pkey: "
1407                     "pkey index %d out of range (0, %d)",
1408                     pkey_ix, port_infop->p_pkey_tbl_sz - 1);
1409                 return (IBT_PKEY_IX_ILLEGAL);
1410         }
1411 
1412         *pkey = port_infop->p_pkey_tbl[pkey_ix];
1413         if ((*pkey == IB_PKEY_INVALID_FULL) ||
1414             (*pkey == IB_PKEY_INVALID_LIMITED))
1415                 return (IBT_PKEY_IX_INVALID);
1416         return (IBT_SUCCESS);
1417 }
1418 
1419 /*
1420  * Function:
1421  *      ibt_pkey2index
1422  * Input:
1423  *      hca_hdl      - The IBT HCA handle.
1424  *      port_num     - The HCA port number.
1425  *      pkey         - The input PKey value, whose index we are interested in.
1426  * Output:
1427  *      pkey_ix      - The PKey index returned for the specified PKey.
1428  * Returns:
1429  *      IBT_SUCCESS/IBT_HCA_PORT_INVALID/IBT_INVALID_PARAM
1430  * Description:
1431  *      Returns the PKey Index for the specified PKey, the device as specified
1432  *      by IBT HCA Handle.
1433  */
1434 ibt_status_t
1435 ibt_pkey2index(ibt_hca_hdl_t hca_hdl, uint8_t port_num, ib_pkey_t pkey,
1436     uint16_t *pkey_ix)
1437 {
1438         ibt_status_t            retval;
1439 
1440         IBTF_DPRINTF_L3(ibtf_hca, "ibt_pkey2index(%p, %d, %d)",
1441             hca_hdl, port_num, pkey);
1442 
1443         mutex_enter(&ibtl_clnt_list_mutex);
1444         retval = ibtl_pkey2index(hca_hdl->ha_hca_devp, port_num, pkey, pkey_ix);
1445         mutex_exit(&ibtl_clnt_list_mutex);
1446 
1447         return (retval);
1448 }
1449 
1450 /*
1451  * Function:
1452  *      ibt_pkey2index_byguid
1453  * Input:
1454  *      hca_guid     - The HCA's node GUID.
1455  *      port_num     - The HCA port number.
1456  *      pkey         - The input PKey value, whose index we are interested in.
1457  * Output:
1458  *      pkey_ix      - The PKey Index returned for the specified PKey.
1459  * Returns:
1460  *      IBT_SUCCESS/IBT_HCA_PORT_INVALID/IBT_INVALID_PARAM/IBT_HCA_INVALID
1461  * Description:
1462  *      Returns the PKey Index for the specified PKey, the device as specified
1463  *      by HCA GUID Info.
1464  */
1465 ibt_status_t
1466 ibt_pkey2index_byguid(ib_guid_t hca_guid, uint8_t port_num, ib_pkey_t pkey,
1467     uint16_t *pkey_ix)
1468 {
1469         ibt_status_t            retval;
1470         ibtl_hca_devinfo_t      *hca_devp;      /* HCA Dev Info */
1471 
1472         IBTF_DPRINTF_L3(ibtf_hca, "ibt_pkey2index_byguid(%llX, %d, %d)",
1473             hca_guid, port_num, pkey);
1474 
1475         mutex_enter(&ibtl_clnt_list_mutex);
1476         hca_devp = ibtl_get_hcadevinfo(hca_guid);
1477         if (hca_devp == NULL) {
1478                 IBTF_DPRINTF_L2(ibtf_hca, "ibt_pkey2index_byguid: "
1479                     "Invalid HCA GUID 0x%llx", hca_guid);
1480                 mutex_exit(&ibtl_clnt_list_mutex);
1481                 return (IBT_HCA_INVALID);
1482         }
1483         retval = ibtl_pkey2index(hca_devp, port_num, pkey, pkey_ix);
1484         mutex_exit(&ibtl_clnt_list_mutex);
1485 
1486         return (retval);
1487 }
1488 
1489 
1490 /*
1491  * Function:
1492  *      ibt_index2pkey
1493  * Input:
1494  *      hca_hdl      - The IBT HCA handle.
1495  *      port_num     - The HCA port
1496  *      pkey_ix      - The input PKey index, whose PKey we are interested in.
1497  * Output:
1498  *      pkey         - The returned PKey value.
1499  * Returns:
1500  *      IBT_SUCCESS/IBT_PKEY_IX_ILLEGAL/IBT_PKEY_IX_INVALID/IBT_HCA_PORT_INVALID
1501  * Description:
1502  *      Returns the PKey value for the specified PKey index, the device as
1503  *      specified by IBT HCA Handle.
1504  */
1505 ibt_status_t
1506 ibt_index2pkey(ibt_hca_hdl_t hca_hdl, uint8_t port_num, uint16_t pkey_ix,
1507     ib_pkey_t *pkey)
1508 {
1509         ibt_status_t            retval;
1510 
1511         IBTF_DPRINTF_L3(ibtf_hca, "ibt_index2pkey(%p, %d, %d)",
1512             hca_hdl, port_num, pkey_ix);
1513 
1514         mutex_enter(&ibtl_clnt_list_mutex);
1515         retval = ibtl_index2pkey(hca_hdl->ha_hca_devp, port_num, pkey_ix, pkey);
1516         mutex_exit(&ibtl_clnt_list_mutex);
1517 
1518         return (retval);
1519 }
1520 
1521 /*
1522  * Function:
1523  *      ibt_index2pkey_byguid
1524  * Input:
1525  *      hca_guid     - The HCA's node GUID.
1526  *      port_num     - The HCA port
1527  *      pkey_ix      - The input PKey index, whose PKey we are interested in.
1528  * Output:
1529  *      pkey         - The returned PKey value, for the specified index.
1530  * Returns:
1531  *      IBT_SUCCESS/IBT_PKEY_IX_ILLEGAL/IBT_PKEY_IX_INVALID/
1532  *      IBT_HCA_PORT_INVALID/IBT_HCA_INVALID
1533  * Description:
1534  *      Returns the PKey Index for the specified PKey, the device as specified
1535  *      by HCA GUID Info.
1536  */
1537 ibt_status_t
1538 ibt_index2pkey_byguid(ib_guid_t hca_guid, uint8_t port_num, uint16_t pkey_ix,
1539     ib_pkey_t *pkey)
1540 {
1541         ibt_status_t            retval;
1542         ibtl_hca_devinfo_t      *hca_devp;      /* HCA Dev Info */
1543 
1544         IBTF_DPRINTF_L3(ibtf_hca, "ibt_index2pkey_byguid(%llX, %d, %d)",
1545             hca_guid, port_num, pkey_ix);
1546 
1547         mutex_enter(&ibtl_clnt_list_mutex);
1548         hca_devp = ibtl_get_hcadevinfo(hca_guid);
1549         if (hca_devp == NULL) {
1550                 IBTF_DPRINTF_L2(ibtf_hca, "ibt_index2pkey_byguid: "
1551                     "Invalid HCA GUID 0x%llx", hca_guid);
1552                 mutex_exit(&ibtl_clnt_list_mutex);
1553                 return (IBT_HCA_INVALID);
1554         }
1555         retval = ibtl_index2pkey(hca_devp, port_num, pkey_ix, pkey);
1556         mutex_exit(&ibtl_clnt_list_mutex);
1557 
1558         return (retval);
1559 }
1560 
1561 
1562 _NOTE(SCHEME_PROTECTS_DATA("client managed", ibtl_hca_s::ha_clnt_private))
1563 
1564 /*
1565  * Function:
1566  *      ibt_set_hca_private
1567  * Input:
1568  *      hca_hdl         The ibt_hca_hdl_t of the opened HCA.
1569  *      clnt_private    The client private data.
1570  * Output:
1571  *      none.
1572  * Returns:
1573  *      none
1574  * Description:
1575  *      Sets the client private data.
1576  */
1577 void
1578 ibt_set_hca_private(ibt_hca_hdl_t hca_hdl, void *clnt_private)
1579 {
1580         hca_hdl->ha_clnt_private = clnt_private;
1581 }
1582 
1583 
1584 /*
1585  * Function:
1586  *      ibt_get_hca_private
1587  * Input:
1588  *      hca_hdl         The ibt_hca_hdl_t of the opened HCA.
1589  * Output:
1590  *      none
1591  * Returns:
1592  *      The client private data.
1593  * Description:
1594  *      Retrieves the private data from a specified HCA.
1595  */
1596 void *
1597 ibt_get_hca_private(ibt_hca_hdl_t hca_hdl)
1598 {
1599         return (hca_hdl->ha_clnt_private);
1600 }
1601 
1602 /*
1603  * Function:
1604  *      ibt_hca_handle_to_guid
1605  * Input:
1606  *      hca             HCA Handle.
1607  * Output:
1608  *      none.
1609  * Returns:
1610  *      hca_guid        Returned HCA GUID on which the specified Channel is
1611  *                      allocated. Valid if it is non-NULL on return.
1612  * Description:
1613  *      A helper function to retrieve HCA GUID for the specified handle.
1614  */
1615 ib_guid_t
1616 ibt_hca_handle_to_guid(ibt_hca_hdl_t hca)
1617 {
1618         IBTF_DPRINTF_L3(ibtf_hca, "ibt_hca_handle_to_guid(%p)", hca);
1619         return (IBTL_HCA2HCAGUID(hca));
1620 }
1621 
1622 /*
1623  * Function:
1624  *      ibt_hca_guid_to_handle
1625  * Input:
1626  *      ibt_hdl         The handle returned to the client by the IBTF from
1627  *                      an ibt_attach() call.
1628  *      hca_guid        HCA GUID
1629  * Output:
1630  *      hca_hdl         Returned ibt_hca_hdl_t.
1631  * Returns:
1632  *      IBT_SUCCESS
1633  *      IBT_HCA_INVALID
1634  * Description:
1635  *      A helper function to retrieve a hca handle from a HCA GUID.
1636  */
1637 ibt_status_t
1638 ibt_hca_guid_to_handle(ibt_clnt_hdl_t ibt_hdl, ib_guid_t hca_guid,
1639     ibt_hca_hdl_t *hca_hdl)
1640 {
1641         ibtl_hca_t              *hca_infop;
1642         ibtl_hca_devinfo_t      *hca_devp;              /* HCA Dev Info */
1643         ibt_status_t            rval = IBT_HCA_INVALID;
1644 
1645         IBTF_DPRINTF_L3(ibtf_hca, "ibt_hca_guid_to_handle(%p, %llX)",
1646             ibt_hdl, hca_guid);
1647 
1648         mutex_enter(&ibtl_clnt_list_mutex);
1649 
1650         /*
1651          * Get HCA Device Info Structure, referenced by HCA GUID.
1652          */
1653         hca_devp = ibtl_get_hcadevinfo(hca_guid);
1654         if (hca_devp == NULL) {
1655                 /*
1656                  * If we are here, then the requested HCA device is not present.
1657                  * Return the status as Invalid HCA GUID.
1658                  */
1659                 mutex_exit(&ibtl_clnt_list_mutex);
1660 
1661                 IBTF_DPRINTF_L2(ibtf_hca, "ibt_hca_guid_to_handle: "
1662                     "HCA Device Not Found: Invalid HCA GUID");
1663 
1664                 *hca_hdl = NULL;
1665                 return (rval);
1666         }
1667 
1668         /*
1669          * Yes, we found a HCA Device registered with IBTF, which matches with
1670          * the requested HCA_GUID.
1671          */
1672         hca_infop = hca_devp->hd_clnt_list;
1673 
1674         while (hca_infop != NULL) {
1675                 if (ibt_hdl == hca_infop->ha_clnt_devp) {
1676                         rval = IBT_SUCCESS;
1677                         break;
1678                 }
1679                 hca_infop = hca_infop->ha_clnt_link;
1680         }
1681 
1682         mutex_exit(&ibtl_clnt_list_mutex);
1683         *hca_hdl = hca_infop;
1684         return (rval);
1685 }