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 /* 1563 * Function: 1564 * ibt_set_hca_private 1565 * Input: 1566 * hca_hdl The ibt_hca_hdl_t of the opened HCA. 1567 * clnt_private The client private data. 1568 * Output: 1569 * none. 1570 * Returns: 1571 * none 1572 * Description: 1573 * Sets the client private data. 1574 */ 1575 void 1576 ibt_set_hca_private(ibt_hca_hdl_t hca_hdl, void *clnt_private) 1577 { 1578 hca_hdl->ha_clnt_private = clnt_private; 1579 } 1580 1581 1582 /* 1583 * Function: 1584 * ibt_get_hca_private 1585 * Input: 1586 * hca_hdl The ibt_hca_hdl_t of the opened HCA. 1587 * Output: 1588 * none 1589 * Returns: 1590 * The client private data. 1591 * Description: 1592 * Retrieves the private data from a specified HCA. 1593 */ 1594 void * 1595 ibt_get_hca_private(ibt_hca_hdl_t hca_hdl) 1596 { 1597 return (hca_hdl->ha_clnt_private); 1598 } 1599 1600 /* 1601 * Function: 1602 * ibt_hca_handle_to_guid 1603 * Input: 1604 * hca HCA Handle. 1605 * Output: 1606 * none. 1607 * Returns: 1608 * hca_guid Returned HCA GUID on which the specified Channel is 1609 * allocated. Valid if it is non-NULL on return. 1610 * Description: 1611 * A helper function to retrieve HCA GUID for the specified handle. 1612 */ 1613 ib_guid_t 1614 ibt_hca_handle_to_guid(ibt_hca_hdl_t hca) 1615 { 1616 IBTF_DPRINTF_L3(ibtf_hca, "ibt_hca_handle_to_guid(%p)", hca); 1617 return (IBTL_HCA2HCAGUID(hca)); 1618 } 1619 1620 /* 1621 * Function: 1622 * ibt_hca_guid_to_handle 1623 * Input: 1624 * ibt_hdl The handle returned to the client by the IBTF from 1625 * an ibt_attach() call. 1626 * hca_guid HCA GUID 1627 * Output: 1628 * hca_hdl Returned ibt_hca_hdl_t. 1629 * Returns: 1630 * IBT_SUCCESS 1631 * IBT_HCA_INVALID 1632 * Description: 1633 * A helper function to retrieve a hca handle from a HCA GUID. 1634 */ 1635 ibt_status_t 1636 ibt_hca_guid_to_handle(ibt_clnt_hdl_t ibt_hdl, ib_guid_t hca_guid, 1637 ibt_hca_hdl_t *hca_hdl) 1638 { 1639 ibtl_hca_t *hca_infop; 1640 ibtl_hca_devinfo_t *hca_devp; /* HCA Dev Info */ 1641 ibt_status_t rval = IBT_HCA_INVALID; 1642 1643 IBTF_DPRINTF_L3(ibtf_hca, "ibt_hca_guid_to_handle(%p, %llX)", 1644 ibt_hdl, hca_guid); 1645 1646 mutex_enter(&ibtl_clnt_list_mutex); 1647 1648 /* 1649 * Get HCA Device Info Structure, referenced by HCA GUID. 1650 */ 1651 hca_devp = ibtl_get_hcadevinfo(hca_guid); 1652 if (hca_devp == NULL) { 1653 /* 1654 * If we are here, then the requested HCA device is not present. 1655 * Return the status as Invalid HCA GUID. 1656 */ 1657 mutex_exit(&ibtl_clnt_list_mutex); 1658 1659 IBTF_DPRINTF_L2(ibtf_hca, "ibt_hca_guid_to_handle: " 1660 "HCA Device Not Found: Invalid HCA GUID"); 1661 1662 *hca_hdl = NULL; 1663 return (rval); 1664 } 1665 1666 /* 1667 * Yes, we found a HCA Device registered with IBTF, which matches with 1668 * the requested HCA_GUID. 1669 */ 1670 hca_infop = hca_devp->hd_clnt_list; 1671 1672 while (hca_infop != NULL) { 1673 if (ibt_hdl == hca_infop->ha_clnt_devp) { 1674 rval = IBT_SUCCESS; 1675 break; 1676 } 1677 hca_infop = hca_infop->ha_clnt_link; 1678 } 1679 1680 mutex_exit(&ibtl_clnt_list_mutex); 1681 *hca_hdl = hca_infop; 1682 return (rval); 1683 }