1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * ibmf_saa.c 29 * 30 */ 31 32 #include <sys/ib/mgt/ibmf/ibmf_saa_impl.h> 33 34 /* 35 * As a primitive error checking scheme, the first 4 bytes of the client state 36 * have a well-known pattern. We write this pattern during session_open, make 37 * sure all subsequent calls still have this pattern in the client state, and 38 * clear the pattern on session_close. Clients could still run into trouble 39 * providing a bad handle since we don't check a known list of handles. But 40 * this mechanism will protect against making ibmf_saa calls after the session 41 * has been closed. 42 */ 43 #define IBMF_SAA_SET_CLIENT_SIGNATURE(clientp) { \ 44 (clientp)->saa_client_sig = (void *)0xACEDFACE; \ 45 } 46 47 #define IBMF_SAA_VERIFY_CLIENT_SIGNATURE(clientp) \ 48 (((clientp) != NULL && (clientp)->saa_client_sig == \ 49 (void *)0xACEDFACE) ? B_TRUE: B_FALSE) 50 51 #define IBMF_SAA_CLEAR_CLIENT_SIGNATURE(clientp) { \ 52 (clientp)->saa_client_sig = 0; \ 53 } 54 55 /* Global Sa_access State Pointer */ 56 extern saa_state_t *saa_statep; 57 extern int ibmf_trace_level; 58 59 /* 60 * Locking scheme: 61 * ibmf_saa maintains a linked list of port entries. Each element of the list 62 * contains information about a certain port. There may be multiple clients 63 * associated with each of these entries. The list is synchronized with a state 64 * port_list_mutex. Each of the entries has their own individual mutex. When 65 * adding a new port entry to the mutex the client, with the list mutex, marks 66 * the port as registering, adds the port, and releases the list mutex. 67 * Subsequent clients aquire the list mutex, find the port, acquire the port 68 * mutex, release the list mutex, and wait if the port is marked as registering. 69 * Clients should never try to acquire the list mutex when they have a port 70 * mutex. 71 */ 72 73 /* 74 * ibmf_sa_session_open(): 75 * 76 * Before using the ibmf_saa interface, consumers should register with the 77 * ibmf_saa interface by calling ibmf_sa_session_open(). Upon a successful 78 * registration, a handle is returned for use in subsequent interaction with the 79 * ibmf_saa interface; this handle is also provided as an argument to subnet 80 * event notification function. 81 * 82 * Consumers can register to be notified of subnet events such as GID 83 * being available/unavailable. Clients which provide a non-NULL event args 84 * structure will have the is_event_callback function called when an event is 85 * received or there is a failure in subscribing for events. This callback may 86 * be generated before the ibmf_sa_session_open() call returns. 87 * 88 * This interface blocks allocating memory, but not waiting for any packet 89 * responses. 90 * 91 * Arguments: 92 * port_guid - GUID of the port. 93 * event_args - subnet event registration details 94 * sm_key - only filled in if the consumer is an SM 95 * ibmf_version - version of the interface (IBMF_VERSION) 96 * flags - unused 97 * 98 * Output Arguments: 99 * ibmf_sa_handle - pointer to ibmf_saa_handle to be used in future calls 100 * 101 * Return values: 102 * IBMF_SUCCESS - registration succeeded 103 * IBMF_BAD_PORT - registration failed; active port not found 104 * IBMF_BAD_PORT_STATE - registration failed; port found but not active or 105 * previous registration failed 106 * IBMF_NO_MEMORY - registration failed; could not allocate memory 107 * IBMF_NO_RESOURCES - registration failed due to a resource issue 108 * IBMF_BUSY - registration failed; too many clients registered 109 * for this port 110 * IBMF_TRANSPORT_FAILURE - failure with underlying transport framework 111 * IBMF_INVALID_ARG - ibmf_saa_handle arg was NULL 112 * 113 * The ibmf_saa module maintains a linked list of ports which it knows about. 114 * For each port, a reference count is kept. When the first client for a 115 * port registers with ibmf_saa, ibmf_saa registers with ibmf. 116 * The reference count checking must be serialized to 117 * ensure that only one client modifies the reference count at a time. 118 * When a client determines that it is responsible for registering it 119 * sets the state field to "registering" in the port. Clients registering with 120 * sa_acess will cv_wait on this field before modifying the reference count. 121 * Unregistering clients do not need to wait on this field since no one else 122 * will be registering while they are completing (the port's ref count will 123 * be greater than 0). 124 * If ibmf registration fails, the entry is set to "invalid"; we decrement 125 * the reference count that we just incremented. 126 * 127 * WARNING: after decrementing the reference count, NO further access to 128 * the entry should be performed in the same thread, because invalid entries 129 * with ref counts of 0 are purged. 130 */ 131 /* ARGSUSED */ 132 int 133 ibmf_sa_session_open(ib_guid_t port_guid, ib_smkey_t sm_key, 134 ibmf_saa_subnet_event_args_t *event_args, uint_t ibmf_version, 135 uint_t flags, ibmf_saa_handle_t *ibmf_saa_handle) 136 { 137 saa_port_t *saa_portp = NULL; 138 int status = IBMF_SUCCESS; 139 saa_client_data_t *saa_client = NULL; 140 141 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, 142 ibmf_sa_session_open_start, IBMF_TNF_TRACE, "", 143 "ibmf_sa_session_open() enter\n"); 144 145 if (ibmf_version != IBMF_VERSION) { 146 147 IBMF_TRACE_0(IBMF_TNF_NODEBUG, DPRINT_L1, 148 ibmf_sa_session_open_err, IBMF_TNF_ERROR, "", 149 "ibmf_sa_session_open: Bad Version\n"); 150 151 status = IBMF_BAD_VERSION; 152 goto bail; 153 } 154 155 if (ibmf_saa_handle == NULL) { 156 157 IBMF_TRACE_0(IBMF_TNF_NODEBUG, DPRINT_L1, 158 ibmf_sa_session_open_err, IBMF_TNF_ERROR, "", 159 "ibmf_sa_session_open: invalid argument, null pointer\n"); 160 161 status = IBMF_INVALID_ARG; 162 goto bail; 163 } 164 165 IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3, 166 ibmf_sa_session_open, IBMF_TNF_TRACE, "", 167 "ibmf_sa_session_open: %s, guid = %016" PRIx64 ", prefix = %016" 168 PRIx64 "\n", tnf_string, msg, "opening session", 169 tnf_opaque, guid, port_guid); 170 171 /* 172 * Find a valid entry matching the port guid 173 * Refcount is immediately incremented 174 */ 175 176 /* acquire list mutex (and keep it locked until after creation) */ 177 mutex_enter(&saa_statep->saa_port_list_mutex); 178 179 saa_portp = saa_statep->saa_port_list; 180 while (saa_portp != NULL) { 181 182 if (saa_portp->saa_pt_port_guid == port_guid && 183 ibmf_saa_is_valid(saa_portp, B_TRUE) == B_TRUE) { 184 185 break; 186 } 187 saa_portp = saa_portp->next; 188 } 189 190 if (saa_portp != NULL) { 191 192 IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3, 193 ibmf_sa_session_open, IBMF_TNF_TRACE, "", 194 "ibmf_sa_session_open(): %s\n", 195 tnf_string, msg, "port exists\n"); 196 197 /* release list mutex */ 198 mutex_exit(&saa_statep->saa_port_list_mutex); 199 200 /* 201 * now add client to existing port 202 * (will wait till end of ibmf registering) 203 * Note that the state may have changed in the meantime... 204 */ 205 status = ibmf_saa_impl_add_client(saa_portp); 206 207 if (status != IBMF_SUCCESS) { 208 209 IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1, 210 ibmf_sa_session_open_err, IBMF_TNF_ERROR, "", 211 "ibmf_sa_session_open: %s, status = %d\n", 212 tnf_string, msg, "ibmf_saa_impl_add_client()" 213 " failed", tnf_int, status, status); 214 215 goto bail; 216 } 217 } else { 218 219 /* create minimal port entry, non blocking */ 220 status = ibmf_saa_impl_create_port(port_guid, &saa_portp); 221 222 if (status != IBMF_SUCCESS) { 223 224 /* release list mutex */ 225 mutex_exit(&saa_statep->saa_port_list_mutex); 226 227 IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1, 228 ibmf_sa_session_open_err, IBMF_TNF_ERROR, "", 229 "ibmf_sa_session_open: %s, status = %d\n", 230 tnf_string, msg, "ibmf_saa_impl_create_port()" 231 " failed", tnf_int, status, status); 232 233 goto bail; 234 } 235 236 /* link to list */ 237 saa_portp->next = saa_statep->saa_port_list; 238 saa_statep->saa_port_list = saa_portp; 239 240 /* 241 * release the list mutex since we now have the minimum amount 242 * of port data initialized to prevent subsequent clients from 243 * continuing with registration (they will cv_wait on registe- 244 * -ring state). We don't want to hold the list mutex since 245 * other ports may need it and since we're about to make calls 246 * to functions which may block. 247 * 248 * We do not need the port registering mutex since clients will 249 * not proceed while saa_pt_state == 250 * IBMF_SAA_PORT_STATE_REGISTERING. 251 */ 252 mutex_exit(&saa_statep->saa_port_list_mutex); 253 254 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(saa_portp->saa_pt_kstatp)) 255 256 status = ibmf_saa_impl_init_kstats(saa_portp); 257 258 if (status != IBMF_SUCCESS) { 259 260 IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1, 261 ibmf_sa_session_open_err, IBMF_TNF_ERROR, "", 262 "ibmf_sa_session_open: %s, status = %d\n", 263 tnf_string, msg, "could not initialize kstats", 264 tnf_int, status, status); 265 266 ibmf_saa_impl_register_failed(saa_portp); 267 268 goto bail; 269 } 270 271 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*saa_portp)) 272 273 status = ibmf_saa_impl_register_port(saa_portp); 274 275 if (status != IBMF_SUCCESS) { 276 277 IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1, 278 ibmf_sa_session_open_err, IBMF_TNF_ERROR, "", 279 "ibmf_sa_session_open: %s, ibmf_status = %d\n", 280 tnf_string, msg, 281 "ibmf_saa_impl_register_port failed", 282 tnf_int, ibmf_status, status); 283 284 ibmf_saa_impl_register_failed(saa_portp); 285 286 /* 287 * Note: we don't update kstats as this entry 288 * will eventually go away... 289 */ 290 goto bail; 291 292 } 293 294 IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3, 295 ibmf_sa_session_open, IBMF_TNF_TRACE, "", 296 "ibmf_sa_session_open: %s, prefix = %016" PRIx64 297 "\n", tnf_string, msg, "successfully initialized port"); 298 299 /* mark port as registered */ 300 mutex_enter(&saa_portp->saa_pt_mutex); 301 302 /* incremement reference count to account for cpi */ 303 saa_portp->saa_pt_reference_count++; 304 305 saa_portp->saa_pt_state = IBMF_SAA_PORT_STATE_READY; 306 307 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*saa_portp)) 308 309 /* kick waiters */ 310 cv_broadcast(&saa_portp->saa_pt_ibmf_reg_cv); 311 312 mutex_exit(&saa_portp->saa_pt_mutex); 313 314 IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3, 315 ibmf_sa_session_open, IBMF_TNF_TRACE, "", 316 "ibmf_sa_session_open: %s\n", tnf_string, msg, 317 "port is up. Sending classportinfo request"); 318 319 ibmf_saa_impl_get_classportinfo(saa_portp); 320 } 321 322 mutex_enter(&saa_portp->saa_pt_kstat_mutex); 323 324 IBMF_SAA_ADD32_KSTATS(saa_portp, clients_registered, 1); 325 326 mutex_exit(&saa_portp->saa_pt_kstat_mutex); 327 328 /* create new client structure */ 329 saa_client = kmem_zalloc(sizeof (saa_client_data_t), KM_SLEEP); 330 331 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*saa_client)) 332 333 IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3, 334 ibmf_sa_session_open, IBMF_TNF_TRACE, "", 335 "ibmf_sa_session_open: clientp = %p, subnetp = %p\n", 336 tnf_opaque, clientp, saa_client, 337 tnf_opaque, subnetp, saa_portp); 338 339 saa_client->saa_client_port = saa_portp; 340 mutex_init(&saa_client->saa_client_mutex, NULL, MUTEX_DRIVER, 341 NULL); 342 cv_init(&saa_client->saa_client_state_cv, NULL, CV_DRIVER, NULL); 343 cv_init(&saa_client->saa_client_event_cb_cv, NULL, CV_DRIVER, NULL); 344 345 IBMF_SAA_SET_CLIENT_SIGNATURE(saa_client); 346 347 saa_client->saa_client_state = SAA_CLIENT_STATE_ACTIVE; 348 saa_client->saa_client_sm_key = sm_key; 349 350 *ibmf_saa_handle = (ibmf_saa_handle_t)saa_client; 351 352 /* if client is interested in subnet event notifications */ 353 if (event_args != NULL) { 354 ibmf_saa_add_event_subscriber(saa_client, event_args); 355 } 356 357 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*saa_client)) 358 359 360 bail: 361 /* purge invalid entries */ 362 ibmf_saa_impl_purge(); 363 364 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_sa_session_open_end, 365 IBMF_TNF_TRACE, "", "ibmf_sa_session_open() exit\n"); 366 367 return (status); 368 } 369 370 371 /* 372 * ibmf_sa_session_close() 373 * 374 * Unregister a consumer of the SA_Access interface 375 * 376 * This interface blocks. 377 * 378 * Arguments: 379 * SA_Access handle 380 * 381 * Return values: 382 * IBMF_SUCCESS - unregistration succeeded 383 * IBMF_FAILURE - unregistration failed for unknown reasons 384 * 385 * All outstanding callbacks will be canceled before this function returns. 386 * 387 */ 388 /* ARGSUSED */ 389 int 390 ibmf_sa_session_close(ibmf_saa_handle_t *ibmf_saa_handle, uint_t flags) 391 { 392 saa_client_data_t *client_data = NULL; 393 saa_port_t *saa_portp = NULL; 394 int status = IBMF_SUCCESS; 395 saa_client_data_t *curr_clientp, *prev_clientp; 396 uint8_t port_state; 397 398 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, 399 ibmf_sa_session_close_start, IBMF_TNF_TRACE, "", 400 "ibmf_sa_session_close() enter\n"); 401 402 if (ibmf_saa_handle == NULL) { 403 404 IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1, 405 ibmf_sa_session_close_err, IBMF_TNF_ERROR, "", 406 "ibmf_sa_session_close: %s\n", 407 tnf_string, msg, "invalid argument, NULL pointer argument"); 408 409 status = IBMF_INVALID_ARG; 410 goto bail; 411 } 412 413 /* ibmf_saa_handle is pointer to the client data structure */ 414 client_data = (saa_client_data_t *)*ibmf_saa_handle; 415 416 /* sanity check to make sure nothing happened to handle */ 417 if (IBMF_SAA_VERIFY_CLIENT_SIGNATURE(client_data) == B_FALSE) { 418 419 IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1, 420 ibmf_sa_session_close_err, IBMF_TNF_ERROR, "", 421 "ibmf_sa_session_close: %s\n", 422 tnf_string, msg, "bad handle"); 423 424 status = IBMF_BAD_HANDLE; 425 goto bail; 426 } 427 428 saa_portp = client_data->saa_client_port; 429 430 IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3, 431 ibmf_sa_session_close, IBMF_TNF_TRACE, 432 "", "ibmf_sa_session_close: saa_portp = %p\n", 433 tnf_opaque, saa_portp, saa_portp); 434 435 mutex_enter(&saa_portp->saa_pt_mutex); 436 437 port_state = saa_portp->saa_pt_state; 438 439 mutex_exit(&saa_portp->saa_pt_mutex); 440 441 /* 442 * if there are pending async transactions, wait for them to finish 443 * note that we wait only once, not loop.... 444 * note we test the state outside saa_pt_mutex 445 */ 446 mutex_enter(&client_data->saa_client_mutex); 447 448 if ((client_data->saa_client_num_pending_trans > 0) && 449 (port_state == IBMF_SAA_PORT_STATE_READY)) { 450 451 IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3, 452 ibmf_sa_session_close, IBMF_TNF_TRACE, 453 "", "ibmf_sa_session_close: %s, num_pending_trans = %d\n", 454 tnf_string, msg, "waiting for async callbacks", 455 tnf_uint, num_pending_trans, 456 client_data->saa_client_num_pending_trans); 457 458 client_data->saa_client_state = SAA_CLIENT_STATE_WAITING; 459 460 /* 461 * we rely on IBMF calling the callback in all cases, 462 * callback signals cv 463 */ 464 cv_wait(&client_data->saa_client_state_cv, 465 &client_data->saa_client_mutex); 466 467 IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_sa_session_close, 468 IBMF_TNF_TRACE, "", "ibmf_sa_session_close: %s\n", 469 tnf_string, msg, "done waiting"); 470 } 471 472 /* mark state as closed so no more event callbacks will be generated */ 473 client_data->saa_client_state = SAA_CLIENT_STATE_CLOSED; 474 475 /* 476 * if there are pending subnet event callbacks wait for them to finish 477 */ 478 if (client_data->saa_client_event_cb_num_active > 0) { 479 480 IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3, 481 ibmf_sa_session_close, IBMF_TNF_TRACE, 482 "", "ibmf_sa_session_close: %s, num_active_cb = %d\n", 483 tnf_string, msg, "waiting for event callbacks", 484 tnf_uint, num_active_cb, 485 client_data->saa_client_event_cb_num_active); 486 487 cv_wait(&client_data->saa_client_event_cb_cv, 488 &client_data->saa_client_mutex); 489 } 490 491 mutex_exit(&client_data->saa_client_mutex); 492 493 mutex_enter(&saa_portp->saa_pt_kstat_mutex); 494 495 IBMF_SAA_SUB32_KSTATS(saa_portp, clients_registered, 1); 496 497 mutex_exit(&saa_portp->saa_pt_kstat_mutex); 498 499 /* 500 * if client was subscribed for events then remove the callback from the 501 * list, and possibly unsubscribe from the SA 502 */ 503 if (client_data->saa_client_event_cb != NULL) { 504 505 /* remove the client from the port's list of clients */ 506 mutex_enter(&saa_portp->saa_pt_event_sub_mutex); 507 508 curr_clientp = saa_portp->saa_pt_event_sub_client_list; 509 prev_clientp = NULL; 510 while (curr_clientp != NULL) { 511 512 if (curr_clientp == client_data) { 513 514 break; 515 } 516 517 prev_clientp = curr_clientp; 518 curr_clientp = curr_clientp->next; 519 } 520 521 /* should have found the client */ 522 ASSERT(curr_clientp != NULL); 523 524 if (curr_clientp == NULL) { 525 526 IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1, 527 ibmf_sa_session_close, IBMF_TNF_ERROR, "", 528 "ibmf_sa_session_close: %s. ref_count = %d\n", 529 tnf_string, msg, "could not find client in list", 530 tnf_opaque, client, client_data); 531 } else { 532 533 if (prev_clientp == NULL) { 534 535 saa_portp->saa_pt_event_sub_client_list = 536 curr_clientp->next; 537 538 } else 539 prev_clientp->next = curr_clientp->next; 540 541 IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3, 542 ibmf_sa_session_close, IBMF_TNF_TRACE, "", 543 "ibmf_sa_session_close: %s\n", tnf_string, msg, 544 "Removed client from event subscriber list"); 545 } 546 547 548 mutex_exit(&saa_portp->saa_pt_event_sub_mutex); 549 550 } 551 552 /* decrementing refcount is last thing we do on port entry */ 553 mutex_enter(&saa_portp->saa_pt_mutex); 554 555 ASSERT(saa_portp->saa_pt_reference_count > 0); 556 saa_portp->saa_pt_reference_count--; 557 558 IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_sa_session_close, 559 IBMF_TNF_TRACE, "", 560 "ibmf_sa_session_close: ref_count = %d\n", 561 tnf_uint, port_ref_count, 562 saa_portp->saa_pt_reference_count); 563 564 mutex_exit(&saa_portp->saa_pt_mutex); 565 566 IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3, 567 ibmf_sa_session_close, IBMF_TNF_TRACE, "", 568 "ibmf_sa_session_close: %s, clientp = %p\n", tnf_string, msg, 569 "freeing client memory", tnf_opaque, clientp, *ibmf_saa_handle); 570 571 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*client_data)) 572 573 /* destroy client */ 574 mutex_destroy(&client_data->saa_client_mutex); 575 576 cv_destroy(&client_data->saa_client_state_cv); 577 cv_destroy(&client_data->saa_client_event_cb_cv); 578 579 IBMF_SAA_CLEAR_CLIENT_SIGNATURE(client_data); 580 581 kmem_free(*ibmf_saa_handle, sizeof (saa_client_data_t)); 582 583 *ibmf_saa_handle = NULL; 584 585 bail: 586 /* purge invalid entries */ 587 ibmf_saa_impl_purge(); 588 589 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_sa_session_close_end, 590 IBMF_TNF_TRACE, "", "ibmf_sa_session_close() exit\n"); 591 592 return (status); 593 } 594 595 /* 596 * ibmf_sa_access 597 * 598 * Retrieve records from the SA given an AttributeID, ComponentMask, 599 * and a template 600 * 601 * This interface blocks if the callback parameter is NULL. 602 * 603 * Input Arguments: 604 * ibmf_saa_handle - handle returned from ibmf_sa_session_open() 605 * access_args - structure containing various parameters for the query 606 * flags - unsused 607 * 608 * Output Arguments: 609 * length - size of buffer returned 610 * result - pointer to buffer of records returned in response. 611 * Buffer is host-endian, unpacked and can be cast to one 612 * of the record types in sa_recs.h 613 * Return values: 614 * IBMF_SUCCESS - query succeeded 615 * IBMF_BAD_HANDLE - sa session handle is invalid 616 * IBMF_BAD_PORT_STATE - port in incorrect state 617 * IBMF_INVALID_ARG - one of the pointer parameters was NULL 618 * IBMF_NO_RESOURCES - ibmf could not allocate ib resources or SA returned 619 * ERR_NO_RESOURCES 620 * IBMF_TRANS_TIMEOUT - transaction timed out 621 * IBMF_TRANS_FAILURE - transaction failure 622 * IBMF_NO_MEMORY - ibmf could not allocate memory 623 * IBMF_REQ_INVALID - send and recv buffer the same for a sequenced 624 * transaction or the SA returned an ERR_REQ_INVALID 625 * IBMF_NO_RECORDS - no records matched query 626 * IBMF_TOO_MANY_RECORDS- SA returned SA_ERR_TOO_MANY_RECORDS 627 * IBMF_INVALID_GID - SA returned SA_INVALID_GID 628 * IBMF_INSUFF_COMPS - SA returned SA_ERR_INSUFFICIENT_COMPS 629 * IBMF_UNSUPP_METHOD - SA returned MAD_STATUS_UNSUPP_METHOD 630 * IBMF_UNSUPP_METHOD_ATTR - SA returned MAD_STATUS_UNSUPP_METHOD_ATTR 631 * IBMF_INVALID_FIELD - SA returned MAD_STATUS_INVALID_FIELD 632 * 633 * Upon successful completion, result points to a buffer containing the records. 634 * length is the size in bytes of the buffer returned in result. If there are 635 * no records or the call failed the length is 0. 636 * 637 * The consumer is responsible for freeing the memory associated with result. 638 */ 639 /* ARGSUSED */ 640 int 641 ibmf_sa_access(ibmf_saa_handle_t ibmf_saa_handle, 642 ibmf_saa_access_args_t *access_args, uint_t flags, size_t *length, 643 void **result) 644 { 645 int res = IBMF_SUCCESS; 646 647 saa_impl_trans_info_t *trans_info; 648 saa_client_data_t *clientp; 649 saa_port_t *saa_portp; 650 651 IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L3, 652 ibmf_sa_access_start, IBMF_TNF_TRACE, "", 653 "ibmf_sa_access_start() enter. attr_id = 0x%x, access_type =" 654 " 0x%x, comp_mask = %016" PRIx64 "\n", 655 tnf_opaque, attr_id, access_args->sq_attr_id, 656 tnf_opaque, access_type, access_args->sq_access_type, 657 tnf_opaque, comp_mask, access_args->sq_component_mask); 658 659 if ((access_args == NULL) || (length == NULL) || (result == NULL)) { 660 661 IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1, 662 ibmf_sa_access_err, IBMF_TNF_ERROR, "", 663 "ibmf_sa_access: %s\n", 664 tnf_string, msg, "invalid argument, NULL pointer argument"); 665 666 res = IBMF_INVALID_ARG; 667 goto bail; 668 } 669 670 /* sanity check to make sure nothing happened to handle */ 671 if (IBMF_SAA_VERIFY_CLIENT_SIGNATURE( 672 (saa_client_data_t *)ibmf_saa_handle) == B_FALSE) { 673 674 IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1, 675 ibmf_sa_access_err, IBMF_TNF_ERROR, "", 676 "ibmf_sa_access: %s\n", 677 tnf_string, msg, "bad handle"); 678 679 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, 680 ibmf_sa_access_end, IBMF_TNF_TRACE, 681 "", "ibmf_sa_access() exit\n"); 682 683 res = IBMF_BAD_HANDLE; 684 goto bail; 685 } 686 687 if (access_args->sq_callback == NULL) { 688 689 trans_info = kmem_zalloc(sizeof (saa_impl_trans_info_t), 690 KM_SLEEP); 691 } else { 692 trans_info = kmem_zalloc(sizeof (saa_impl_trans_info_t), 693 KM_NOSLEEP); 694 if (trans_info == NULL) { 695 696 IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1, 697 ibmf_sa_access_err, IBMF_TNF_ERROR, "", 698 "ibmf_sa_access: %s\n", tnf_string, msg, 699 "could not allocate memory for trans_info"); 700 701 res = IBMF_NO_MEMORY; 702 goto bail; 703 } 704 } 705 706 clientp = (saa_client_data_t *)ibmf_saa_handle; 707 saa_portp = clientp->saa_client_port; 708 709 trans_info->si_trans_client_data = clientp; 710 trans_info->si_trans_port = saa_portp; 711 712 /* 713 * method is get_multi if attribute is multipath; otherwise method is 714 * based on query type 715 */ 716 if (access_args->sq_attr_id == SA_MULTIPATHRECORD_ATTRID) { 717 718 if (access_args->sq_access_type != IBMF_SAA_RETRIEVE) { 719 720 IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1, 721 ibmf_sa_access_err, IBMF_TNF_ERROR, "", 722 "ibmf_sa_access: %s, access_type = 0x%x\n", 723 tnf_string, msg, "access_type for multi-path" 724 " records must be IBMF_SAA_RETRIEVE", 725 tnf_opaque, access_type, 726 access_args->sq_access_type); 727 728 kmem_free(trans_info, sizeof (saa_impl_trans_info_t)); 729 730 res = IBMF_REQ_INVALID; 731 goto bail; 732 } 733 734 trans_info->si_trans_method = SA_SUBN_ADM_GET_MULTI; 735 } else if (access_args->sq_attr_id == SA_TRACERECORD_ATTRID) { 736 737 if (access_args->sq_access_type != IBMF_SAA_RETRIEVE) { 738 739 IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1, 740 ibmf_sa_access_err, IBMF_TNF_ERROR, "", 741 "ibmf_sa_access: %s, access_type = 0x%x\n", 742 tnf_string, msg, "access_type for trace" 743 " records must be IBMF_SAA_RETRIEVE", 744 tnf_opaque, access_type, 745 access_args->sq_access_type); 746 747 kmem_free(trans_info, sizeof (saa_impl_trans_info_t)); 748 749 res = IBMF_REQ_INVALID; 750 goto bail; 751 } 752 753 trans_info->si_trans_method = SA_SUBN_ADM_GET_TRACE_TABLE; 754 } else { 755 756 switch (access_args->sq_access_type) { 757 758 case IBMF_SAA_RETRIEVE: 759 trans_info->si_trans_method = 760 SA_SUBN_ADM_GET_TABLE; 761 break; 762 case IBMF_SAA_UPDATE: 763 trans_info->si_trans_method = SA_SUBN_ADM_SET; 764 break; 765 case IBMF_SAA_DELETE: 766 trans_info->si_trans_method = 767 SA_SUBN_ADM_DELETE; 768 break; 769 default: 770 771 IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1, 772 ibmf_sa_access_err, IBMF_TNF_ERROR, "", 773 "ibmf_sa_access: %s, access_type = 0x%x\n", 774 tnf_string, msg, "unknown access_type", 775 tnf_opaque, access_type, 776 access_args->sq_access_type); 777 778 kmem_free(trans_info, 779 sizeof (saa_impl_trans_info_t)); 780 781 res = IBMF_REQ_INVALID; 782 goto bail; 783 } 784 } 785 786 trans_info->si_trans_attr_id = access_args->sq_attr_id; 787 trans_info->si_trans_component_mask = access_args->sq_component_mask; 788 trans_info->si_trans_template = access_args->sq_template; 789 trans_info->si_trans_template_length = access_args->sq_template_length; 790 trans_info->si_trans_callback = access_args->sq_callback; 791 trans_info->si_trans_callback_arg = access_args->sq_callback_arg; 792 793 mutex_enter(&saa_portp->saa_pt_kstat_mutex); 794 795 IBMF_SAA_ADD32_KSTATS(saa_portp, outstanding_requests, 1); 796 IBMF_SAA_ADD32_KSTATS(saa_portp, total_requests, 1); 797 798 mutex_exit(&saa_portp->saa_pt_kstat_mutex); 799 800 res = ibmf_saa_impl_send_request(trans_info); 801 if (res != IBMF_SUCCESS) { 802 803 IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1, 804 ibmf_sa_access_err, IBMF_TNF_ERROR, "", 805 "ibmf_sa_access: %s, ibmf_status = %d\n", 806 tnf_string, msg, "ibmf_saa_impl_send_request() failed", 807 tnf_int, ibmf_status, res); 808 809 *length = 0; 810 *result = NULL; 811 812 kmem_free(trans_info, sizeof (saa_impl_trans_info_t)); 813 814 mutex_enter(&saa_portp->saa_pt_kstat_mutex); 815 816 IBMF_SAA_SUB32_KSTATS(saa_portp, outstanding_requests, 1); 817 IBMF_SAA_ADD32_KSTATS(saa_portp, failed_requests, 1); 818 819 if (res == IBMF_TRANS_TIMEOUT) 820 IBMF_SAA_ADD32_KSTATS(saa_portp, requests_timedout, 821 1); 822 823 mutex_exit(&saa_portp->saa_pt_kstat_mutex); 824 825 goto bail; 826 } 827 828 /* 829 * if async call don't do anything as callback will take care of 830 * everything; for sync call, copy parameters back to client and free 831 * trans_info structure 832 */ 833 if (access_args->sq_callback == NULL) { 834 *length = trans_info->si_trans_length; 835 *result = trans_info->si_trans_result; 836 res = trans_info->si_trans_status; 837 838 mutex_enter(&saa_portp->saa_pt_kstat_mutex); 839 840 IBMF_SAA_SUB32_KSTATS(saa_portp, outstanding_requests, 1); 841 842 if (res != IBMF_SUCCESS) 843 IBMF_SAA_ADD32_KSTATS(saa_portp, failed_requests, 844 1); 845 846 if (res == IBMF_TRANS_TIMEOUT) 847 IBMF_SAA_ADD32_KSTATS(saa_portp, requests_timedout, 848 1); 849 850 mutex_exit(&saa_portp->saa_pt_kstat_mutex); 851 852 kmem_free(trans_info, sizeof (saa_impl_trans_info_t)); 853 } 854 855 bail: 856 857 if (res != IBMF_SUCCESS) { 858 if (length != NULL) 859 *length = 0; 860 if (result != NULL) 861 *result = NULL; 862 } 863 864 IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_sa_access, IBMF_TNF_TRACE, 865 "", "ibmf_sa_access() exit: result = 0x%x\n", 866 tnf_opaque, result, res); 867 868 return (res); 869 } 870 871 /* 872 * Helper Functions. 873 * Ease of use functions so that the consumer doesn't 874 * have to do the overhead of calling ibmf_sa_access for 875 * commonly used queries 876 */ 877 878 /* 879 * ibmf_saa_gid_to_pathrecords 880 * Given a source gid and a destination gid, return paths 881 * between the gids. 882 * 883 * This interface blocks. 884 * 885 * Input Arguments: 886 * ibmf_saa_handle - handle returned from ibmf_sa_session_open() 887 * sgid - source gid of path 888 * dgid - destination gid of path 889 * p_key - partition of path. This value may be wildcarded with 890 * IBMF_SAA_PKEY_WC. 891 * mtu - preferred MTU of the path. This argument may be 892 * wildcarded with IBMF_SAA_MTU_WC. 893 * reversible - if B_TRUE, ibmf will query only reversible paths 894 * see Infiniband Specification table 171 895 * num_paths - maximum number of paths to return 896 * num_paths should be checked for the actual number of 897 * records returned. 898 * flags - unused 899 * 900 * Output Arguments: 901 * num_paths - actual number of paths returned 902 * length - size of buffer returned 903 * result - pointer to buffer of path records returned in response 904 * 905 * Return values: 906 * Error codes are the same as ibmf_sa_access() return values 907 * 908 * Upon successful completion, result points to a buffer containing the records. 909 * length is the size in bytes of the buffer returned in result. If there are 910 * no records or the call failed the length is 0. 911 * 912 * The consumer is responsible for freeing the memory associated with result. 913 */ 914 /* ARGSUSED */ 915 int 916 ibmf_saa_gid_to_pathrecords(ibmf_saa_handle_t ibmf_saa_handle, ib_gid_t sgid, 917 ib_gid_t dgid, ib_pkey_t p_key, ib_mtu_t mtu, boolean_t reversible, 918 uint8_t *num_paths, uint_t flags, size_t *length, sa_path_record_t **result) 919 { 920 sa_path_record_t path_record; 921 uint64_t comp_mask; 922 int res; 923 ibmf_saa_access_args_t access_args; 924 925 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, 926 ibmf_saa_gid_to_pathrecords_start, IBMF_TNF_TRACE, "", 927 "ibmf_saa_gid_to_pathrecords() enter\n"); 928 929 /* 930 * check num_paths pointer here since we dereference before calling 931 * ibmf_sa_access 932 */ 933 if (num_paths == NULL) { 934 935 IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1, 936 ibmf_saa_gid_to_pathrecords_err, IBMF_TNF_ERROR, "", 937 "ibmf_saa_gid_to_pathrecords: %s\n", 938 tnf_string, msg, "invalid argument, NULL pointer argument"); 939 940 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, 941 ibmf_saa_gid_to_pathrecords_end, IBMF_TNF_TRACE, 942 "", "ibmf_saa_gid_to_pathrecords() exit\n"); 943 944 if (length != NULL) 945 *length = 0; 946 if (result != NULL) 947 *result = NULL; 948 949 return (IBMF_INVALID_ARG); 950 } 951 952 /* check valid handle; in non-debug system ibmf_sa_access() will fail */ 953 ASSERT(ibmf_saa_handle != NULL); 954 955 ASSERT(length != NULL); 956 ASSERT(result != NULL); 957 958 *length = 0; 959 *result = NULL; 960 961 comp_mask = SA_PR_COMPMASK_SGID | SA_PR_COMPMASK_DGID | 962 SA_PR_COMPMASK_NUMBPATH; 963 964 bzero(&path_record, sizeof (sa_path_record_t)); 965 966 path_record.SGID = sgid; 967 path_record.DGID = dgid; 968 path_record.NumbPath = *num_paths; 969 970 if (reversible == B_TRUE) { 971 path_record.Reversible = 1; 972 comp_mask |= SA_PR_COMPMASK_REVERSIBLE; 973 } 974 975 if (p_key != IBMF_SAA_PKEY_WC) { 976 977 path_record.P_Key = p_key; 978 comp_mask |= SA_PR_COMPMASK_PKEY; 979 } 980 981 /* 982 * gid_to_pathrecords specifies greater than or equal to MTU. Path 983 * records can only do strictly greater. Set the mtu value to one 984 * less than the mtu parameter. If it's the lowest value possible (256) 985 * don't do anything and any path mtu will be allowed. 986 */ 987 if ((mtu != IBMF_SAA_MTU_WC) && (mtu > IB_MTU_256)) { 988 989 path_record.MtuSelector = SA_PR_MTU_SEL_GREATER; 990 path_record.Mtu = (mtu - 1); 991 992 comp_mask |= SA_PR_COMPMASK_MTUSELECTOR | SA_PR_COMPMASK_MTU; 993 } 994 995 access_args.sq_attr_id = SA_PATHRECORD_ATTRID; 996 access_args.sq_access_type = IBMF_SAA_RETRIEVE; 997 access_args.sq_component_mask = comp_mask; 998 access_args.sq_template = &path_record; 999 access_args.sq_callback = NULL; 1000 access_args.sq_callback_arg = NULL; 1001 1002 res = ibmf_sa_access(ibmf_saa_handle, &access_args, 0, length, 1003 (void **)result); 1004 if (res != IBMF_SUCCESS) { 1005 1006 IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L2, 1007 ibmf_saa_gid_to_pathrecords, IBMF_TNF_TRACE, "", 1008 "ibmf_saa_gid_to_pathrecords: %s, ibmf_status = %d\n", 1009 tnf_string, msg, "ibmf_sa_access() failed", 1010 tnf_int, ibmf_status, res); 1011 } 1012 1013 *num_paths = *length / sizeof (sa_path_record_t); 1014 1015 IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3, 1016 ibmf_saa_gid_to_pathrecords_end, IBMF_TNF_TRACE, "", 1017 "ibmf_saa_gid_to_pathrecords() exit: result = 0x%x\n", 1018 tnf_opaque, result, res); 1019 1020 return (res); 1021 } 1022 1023 /* 1024 * ibmf_saa_paths_from_gid 1025 * Given a source GID, return a path from the source gid 1026 * to every other port on the subnet. It is assumed that the 1027 * subnet is fully connected. Only one path per port on the subnet 1028 * is returned. 1029 * 1030 * This interface blocks. 1031 * 1032 * Input Arguments: 1033 * ibmf_saa_handle - handle returned from ibmf_sa_session_open() 1034 * sgid - source gid of path 1035 * pkey - paritition of path. This value may be wildcarded with 1036 * IBMF_SAA_PKEY_WC. 1037 * reversible - if B_TRUE, ibmf will query only reversible paths; 1038 * see Infiniband Specification table 171 1039 * flags - unused 1040 * 1041 * Output Arguments: 1042 * num_paths - number of paths returned 1043 * length - size of buffer returned 1044 * result - pointer to buffer of path records returned in response 1045 * 1046 * Return values: 1047 * Error codes are the same as ibmf_sa_access() return values 1048 * 1049 * Upon successful completion, result points to a buffer containing the records. 1050 * and num_records is the number of path records returned. length is the size 1051 * in bytes of the buffer returned in result. If there are no records or the 1052 * call failed the length is 0. 1053 * 1054 * The consumer is responsible for freeing the memory associated with result. 1055 */ 1056 /* ARGSUSED */ 1057 int 1058 ibmf_saa_paths_from_gid(ibmf_saa_handle_t ibmf_saa_handle, ib_gid_t sgid, 1059 ib_pkey_t p_key, boolean_t reversible, uint_t flags, uint_t *num_paths, 1060 size_t *length, sa_path_record_t **result) 1061 { 1062 sa_path_record_t path_record; 1063 uint64_t comp_mask; 1064 int res; 1065 ibmf_saa_access_args_t access_args; 1066 1067 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, 1068 ibmf_saa_paths_from_gid_start, IBMF_TNF_TRACE, "", 1069 "ibmf_saa_paths_from_gid() enter\n"); 1070 1071 /* check valid handle; in non-debug system ibmf_sa_access() will fail */ 1072 ASSERT(ibmf_saa_handle != NULL); 1073 1074 ASSERT(length != NULL); 1075 ASSERT(result != NULL); 1076 1077 comp_mask = SA_PR_COMPMASK_SGID | SA_PR_COMPMASK_NUMBPATH; 1078 1079 bzero(&path_record, sizeof (sa_path_record_t)); 1080 1081 path_record.SGID = sgid; 1082 path_record.NumbPath = 1; 1083 1084 if (reversible == B_TRUE) { 1085 path_record.Reversible = 1; 1086 comp_mask |= SA_PR_COMPMASK_REVERSIBLE; 1087 } 1088 1089 if (p_key != IBMF_SAA_PKEY_WC) { 1090 1091 path_record.P_Key = p_key; 1092 comp_mask |= SA_PR_COMPMASK_PKEY; 1093 } 1094 1095 access_args.sq_attr_id = SA_PATHRECORD_ATTRID; 1096 access_args.sq_access_type = IBMF_SAA_RETRIEVE; 1097 access_args.sq_component_mask = comp_mask; 1098 access_args.sq_template = &path_record; 1099 access_args.sq_callback = NULL; 1100 access_args.sq_callback_arg = NULL; 1101 1102 res = ibmf_sa_access(ibmf_saa_handle, &access_args, 0, length, 1103 (void **)result); 1104 if (res != IBMF_SUCCESS) { 1105 1106 IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L2, 1107 ibmf_saa_gid_to_pathrecords, IBMF_TNF_TRACE, "", 1108 "ibmf_saa_gid_to_pathrecords: %s, ibmf_status = %d\n", 1109 tnf_string, msg, "ibmf_sa_access() failed", 1110 tnf_int, ibmf_status, res); 1111 } 1112 1113 *num_paths = *length / sizeof (sa_path_record_t); 1114 1115 IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3, 1116 ibmf_saa_paths_from_gid_end, IBMF_TNF_TRACE, "", 1117 "ibmf_saa_paths_from_gid() exit: result = 0x%x\n", 1118 tnf_opaque, result, res); 1119 1120 return (res); 1121 } 1122 1123 /* 1124 * ibmf_saa_name_to_service_record: 1125 * Given a service name, return the service records associated 1126 * with it. 1127 * 1128 * This interface blocks. 1129 * 1130 * Input Arguments: 1131 * ibmf_saa_handle - handle returned from ibmf_sa_session_open() 1132 * name - service name, a null terminated string 1133 * p_key - partition that the service is requested on. This 1134 * value may be wildcarded with IBMF_SAA_PKEY_WC. 1135 * flags - unused 1136 * 1137 * Output Arguments: 1138 * num_records - number of service records returned 1139 * length - size of buffer returned 1140 * result - pointer to buffer of service records returned in 1141 * response 1142 * Return values: 1143 * Error codes are the same as ibmf_sa_access() return values 1144 * 1145 * Upon successful completion, result points to a buffer containing the records. 1146 * and num_records is the number of service records returned. length is the 1147 * size in bytes of the buffer returned in result. If there are no records or 1148 * the call failed the length is 0. 1149 * 1150 * The consumer is responsible for freeing the memory associated with result. 1151 */ 1152 /* ARGSUSED */ 1153 int 1154 ibmf_saa_name_to_service_record(ibmf_saa_handle_t ibmf_saa_handle, 1155 char *service_name, ib_pkey_t p_key, uint_t flags, 1156 uint_t *num_records, size_t *length, sa_service_record_t **result) 1157 { 1158 sa_service_record_t service_record; 1159 int res; 1160 ibmf_saa_access_args_t access_args; 1161 1162 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, 1163 ibmf_saa_name_to_service_record_start, IBMF_TNF_TRACE, "", 1164 "ibmf_saa_name_to_service_record() enter\n"); 1165 1166 /* check valid handle; in non-debug system ibmf_sa_access() will fail */ 1167 ASSERT(ibmf_saa_handle != NULL); 1168 1169 ASSERT(num_records != NULL); 1170 ASSERT(length != NULL); 1171 ASSERT(result != NULL); 1172 1173 bzero((void *)&service_record, sizeof (sa_service_record_t)); 1174 1175 if (strlen(service_name) >= IB_SVC_NAME_LEN) { 1176 1177 IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1, 1178 ibmf_saa_name_to_service_record_err, IBMF_TNF_ERROR, "", 1179 "ibmf_saa_gid_to_pathrecords: %s, service_name = %s\n", 1180 tnf_string, msg, "service name too long", 1181 tnf_string, service_name, service_name); 1182 1183 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, 1184 ibmf_saa_name_to_service_record_end, IBMF_TNF_TRACE, "", 1185 "ibmf_saa_name_to_service_record() exit\n"); 1186 1187 *num_records = 0; 1188 *length = 0; 1189 *result = NULL; 1190 1191 return (IBMF_REQ_INVALID); 1192 } 1193 1194 /* copy IB_SVC_NAME_LEN bytes, leaving room at end for null char */ 1195 (void) strncpy((char *)(service_record.ServiceName), service_name, 1196 IB_SVC_NAME_LEN-1); 1197 1198 if (p_key != IBMF_SAA_PKEY_WC) { 1199 service_record.ServiceP_Key = p_key; 1200 access_args.sq_component_mask = SA_SR_COMPMASK_NAME | 1201 SA_SR_COMPMASK_PKEY; 1202 } else 1203 access_args.sq_component_mask = SA_SR_COMPMASK_NAME; 1204 1205 access_args.sq_attr_id = SA_SERVICERECORD_ATTRID; 1206 access_args.sq_access_type = IBMF_SAA_RETRIEVE; 1207 access_args.sq_template = &service_record; 1208 access_args.sq_callback = NULL; 1209 access_args.sq_callback_arg = NULL; 1210 1211 res = ibmf_sa_access(ibmf_saa_handle, &access_args, 0, length, 1212 (void *)result); 1213 if (res != IBMF_SUCCESS) { 1214 1215 IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L2, 1216 ibmf_saa_name_to_service_record, IBMF_TNF_TRACE, "", 1217 "ibmf_saa_name_to_service_record: %s, ibmf_status = %d\n", 1218 tnf_string, msg, "ibmf_sa_access() failed", 1219 tnf_int, ibmf_status, res); 1220 } 1221 1222 *num_records = *length / sizeof (sa_service_record_t); 1223 1224 IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3, 1225 ibmf_saa_name_to_service_record_end, IBMF_TNF_TRACE, "", 1226 "ibmf_saa_name_to_service_record() exit: result = 0x%x\n", 1227 tnf_opaque, result, res); 1228 1229 return (res); 1230 } 1231 1232 /* 1233 * ibmf_saa_id_to_service_record: 1234 * Given a service id, return the service records associated 1235 * with it. 1236 * 1237 * This interface blocks. 1238 * 1239 * Input Arguments: 1240 * ibmf_saa_handle - handle returned from ibmf_sa_session_open() 1241 * id - service id 1242 * p_key - partition that the service is requested on. This 1243 * value may be wildcarded with IBMF_SAA_PKEY_WC. 1244 * flags - unused 1245 * 1246 * Output Arguments: 1247 * num_records - number of service records returned 1248 * length - size of buffer returned 1249 * result - pointer to buffer of service records returned in 1250 * response 1251 * 1252 * Return values: 1253 * Error codes are the same as ibmf_sa_access() return values 1254 * 1255 * Upon successful completion, result points to a buffer containing the records. 1256 * and num_records is the number of service records returned. length is the 1257 * size in bytes of the buffer returned in result. If there are no records or 1258 * the call failed the length is 0. 1259 * 1260 * The consumer is responsible for freeing the memory associated with result. 1261 */ 1262 /* ARGSUSED */ 1263 int 1264 ibmf_saa_id_to_service_record(ibmf_saa_handle_t ibmf_saa_handle, 1265 ib_svc_id_t service_id, ib_pkey_t p_key, uint_t flags, uint_t *num_records, 1266 size_t *length, sa_service_record_t **result) 1267 { 1268 sa_service_record_t service_record; 1269 int res; 1270 ibmf_saa_access_args_t access_args; 1271 1272 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, 1273 ibmf_saa_id_to_service_record_start, IBMF_TNF_TRACE, "", 1274 "ibmf_saa_id_to_service_record() enter\n"); 1275 1276 /* check valid handle; in non-debug system ibmf_sa_access() will fail */ 1277 ASSERT(ibmf_saa_handle != NULL); 1278 1279 ASSERT(num_records != NULL); 1280 ASSERT(length != NULL); 1281 ASSERT(result != NULL); 1282 1283 bzero((void *)&service_record, sizeof (sa_service_record_t)); 1284 1285 service_record.ServiceID = service_id; 1286 1287 if (p_key != IBMF_SAA_PKEY_WC) { 1288 service_record.ServiceP_Key = p_key; 1289 access_args.sq_component_mask = SA_SR_COMPMASK_ID | 1290 SA_SR_COMPMASK_PKEY; 1291 } else 1292 access_args.sq_component_mask = SA_SR_COMPMASK_ID; 1293 1294 access_args.sq_attr_id = SA_SERVICERECORD_ATTRID; 1295 access_args.sq_access_type = IBMF_SAA_RETRIEVE; 1296 access_args.sq_template = &service_record; 1297 access_args.sq_callback = NULL; 1298 access_args.sq_callback_arg = NULL; 1299 1300 res = ibmf_sa_access(ibmf_saa_handle, &access_args, 0, length, 1301 (void **)result); 1302 if (res != IBMF_SUCCESS) { 1303 1304 IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L2, 1305 ibmf_saa_id_to_service_record, IBMF_TNF_TRACE, "", 1306 "ibmf_saa_id_to_service_record: %s, ibmf_status = %d\n", 1307 tnf_string, msg, "ibmf_sa_access() failed", 1308 tnf_int, ibmf_status, res); 1309 } 1310 1311 *num_records = *length / sizeof (sa_service_record_t); 1312 1313 IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3, 1314 ibmf_saa_id_to_service_record_end, IBMF_TNF_TRACE, "", 1315 "ibmf_saa_id_to_service_record() exit: result = 0x%x\n", 1316 tnf_opaque, result, res); 1317 1318 return (res); 1319 } 1320 1321 /* 1322 * ibmf_saa_update_service_record 1323 * Given a pointer to a service record, either insert or delete it 1324 * 1325 * This interface blocks. 1326 * 1327 * Input Arguments: 1328 * ibmf_saa_handle - handle returned from ibmf_sa_session_open() 1329 * service_record - service record is to be inserted or deleted. To 1330 * delete a service record the GID, ID, P_Key, and 1331 * Service Key must match what is in the SA. 1332 * access_type - indicates whether this is an insertion or deletion. 1333 * valid values are IBMF_SAA_UPDATE or IBMF_SAA_DELETE 1334 * flags - unused 1335 * 1336 * Output Arguments 1337 * none 1338 * 1339 * Return values: 1340 * Error codes are the same as ibmf_sa_access() return values 1341 */ 1342 /* ARGSUSED */ 1343 int 1344 ibmf_saa_update_service_record(ibmf_saa_handle_t ibmf_saa_handle, 1345 sa_service_record_t *service_record, ibmf_saa_access_type_t access_type, 1346 uint_t flags) 1347 { 1348 size_t length; 1349 void *result; 1350 int res; 1351 uint64_t comp_mask; 1352 ibmf_saa_access_args_t access_args; 1353 1354 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, 1355 ibmf_saa_update_service_record_start, IBMF_TNF_TRACE, "", 1356 "ibmf_saa_update_service_record() enter\n"); 1357 1358 /* check valid handle; in non-debug system ibmf_sa_access() will fail */ 1359 ASSERT(ibmf_saa_handle != NULL); 1360 1361 if ((access_type != IBMF_SAA_UPDATE) && 1362 (access_type != IBMF_SAA_DELETE)) { 1363 1364 IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1, 1365 ibmf_saa_update_service_record_err, IBMF_TNF_ERROR, "", 1366 "ibmf_saa_update_service_record: %s, access_type = 0x%x\n", 1367 tnf_string, msg, "invalid query type", 1368 tnf_opaque, access_type, access_type); 1369 1370 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, 1371 ibmf_saa_update_service_record_end, IBMF_TNF_TRACE, "", 1372 "ibmf_saa_update_service_record() exit\n"); 1373 1374 return (IBMF_REQ_INVALID); 1375 } 1376 1377 /* 1378 * call ibmf_sa_access with the following special parameters: 1379 * attrid : service_record 1380 * component_mask : RID fields of service record (GID, ID, and P_key) 1381 * and service key 1382 */ 1383 comp_mask = SA_SR_COMPMASK_ID | SA_SR_COMPMASK_GID | 1384 SA_SR_COMPMASK_PKEY | SA_SR_COMPMASK_KEY; 1385 1386 access_args.sq_attr_id = SA_SERVICERECORD_ATTRID; 1387 access_args.sq_access_type = access_type; 1388 access_args.sq_component_mask = comp_mask; 1389 access_args.sq_template = service_record; 1390 access_args.sq_callback = NULL; 1391 access_args.sq_callback_arg = NULL; 1392 1393 res = ibmf_sa_access(ibmf_saa_handle, &access_args, 0, &length, 1394 &result); 1395 1396 /* if a valid add request, response buffer should be one service rec */ 1397 if (res == IBMF_SUCCESS && length > 0) { 1398 1399 if (length > sizeof (sa_service_record_t)) { 1400 1401 IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L1, 1402 ibmf_saa_update_service_record, IBMF_TNF_TRACE, "", 1403 "ibmf_saa_update_service_record: %s\n", 1404 tnf_string, msg, 1405 "SA returned more than one record"); 1406 } 1407 1408 kmem_free(result, length); 1409 } 1410 1411 IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3, 1412 ibmf_saa_update_service_record_end, IBMF_TNF_TRACE, "", 1413 "ibmf_saa_update_service_record() exit: result = 0x%x\n", 1414 tnf_opaque, result, res); 1415 1416 return (res); 1417 } 1418