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
ibmf_sa_session_open(ib_guid_t port_guid,ib_smkey_t sm_key,ibmf_saa_subnet_event_args_t * event_args,uint_t ibmf_version,uint_t flags,ibmf_saa_handle_t * ibmf_saa_handle)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
ibmf_sa_session_close(ibmf_saa_handle_t * ibmf_saa_handle,uint_t flags)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
ibmf_sa_access(ibmf_saa_handle_t ibmf_saa_handle,ibmf_saa_access_args_t * access_args,uint_t flags,size_t * length,void ** result)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
ibmf_saa_gid_to_pathrecords(ibmf_saa_handle_t ibmf_saa_handle,ib_gid_t sgid,ib_gid_t dgid,ib_pkey_t p_key,ib_mtu_t mtu,boolean_t reversible,uint8_t * num_paths,uint_t flags,size_t * length,sa_path_record_t ** result)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
ibmf_saa_paths_from_gid(ibmf_saa_handle_t ibmf_saa_handle,ib_gid_t sgid,ib_pkey_t p_key,boolean_t reversible,uint_t flags,uint_t * num_paths,size_t * length,sa_path_record_t ** result)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
ibmf_saa_name_to_service_record(ibmf_saa_handle_t ibmf_saa_handle,char * service_name,ib_pkey_t p_key,uint_t flags,uint_t * num_records,size_t * length,sa_service_record_t ** result)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
ibmf_saa_id_to_service_record(ibmf_saa_handle_t ibmf_saa_handle,ib_svc_id_t service_id,ib_pkey_t p_key,uint_t flags,uint_t * num_records,size_t * length,sa_service_record_t ** result)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
ibmf_saa_update_service_record(ibmf_saa_handle_t ibmf_saa_handle,sa_service_record_t * service_record,ibmf_saa_access_type_t access_type,uint_t flags)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