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