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