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