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