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