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