xref: /illumos-gate/usr/src/uts/common/io/ib/ibtl/ibtl_hca.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * ibtl_hca.c
31  *
32  * This file contains Transport API functions related to
33  * Host Channel Adapter (HCA) Verbs.
34  */
35 
36 #include <sys/ib/ibtl/impl/ibtl.h>
37 
38 static char ibtf_hca[] = "ibtl_hca";
39 
40 /* Prototype declarations. */
41 static ibt_status_t ibtl_query_hca_ports(ibtl_hca_devinfo_t *hca_devp,
42     uint8_t port, ibt_hca_portinfo_t **port_info_p, uint_t *ports_p,
43     uint_t *size_p, int use_cache);
44 
45 /*
46  * Function:
47  *      ibt_open_hca
48  * Input:
49  *      ibt_hdl    - IBT Client Handle
50  *      hca_guid   - HCA's node GUID.
51  * Output:
52  *      hca_hdl_p  - IBT HCA Handle.
53  * Returns:
54  *      IBT_SUCCESS
55  *      IBT_HCA_IN_USE
56  *      IBT_HCA_INVALID
57  * Description:
58  *      Open a HCA. HCA can only be opened/closed once. This routine allocates
59  *      and returns a unique IBT Client HCA handle. Clients passes this
60  *      handle on its subsequent references to this device. Once opened by a
61  *      client, a specific HCA cannot be opened again until after it is closed.
62  *      The IBT_HCA_IN_USE error is returned if client tries to open multiple
63  *      times. In this case, previously allocated IBT HCA handle is returned to
64  *      the client. Opening the HCA prepares the HCA for use by the client.
65  */
66 ibt_status_t
67 ibt_open_hca(ibt_clnt_hdl_t ibt_hdl, ib_guid_t hca_guid,
68     ibt_hca_hdl_t *hca_hdl_p)
69 {
70 	ibtl_hca_t  		*hca_infop;
71 	ibtl_hca_devinfo_t	*hca_devp;		/* HCA Dev Info */
72 
73 	IBTF_DPRINTF_L3(ibtf_hca, "ibt_open_hca(%p, %llX)", ibt_hdl, hca_guid);
74 
75 
76 	/*
77 	 * Get HCA Device Info Structure, referenced by HCA GUID.
78 	 */
79 	mutex_enter(&ibtl_clnt_list_mutex);
80 	hca_devp = ibtl_get_hcadevinfo(hca_guid);
81 	if (hca_devp == NULL) {
82 		/*
83 		 * If we are here, then the requested HCA device is not present.
84 		 * Return the status as Invalid HCA GUID.
85 		 */
86 		mutex_exit(&ibtl_clnt_list_mutex);
87 
88 		IBTF_DPRINTF_L2(ibtf_hca, "ibt_open_hca: "
89 		    "HCA Device Not Found: Invalid HCA GUID");
90 
91 		*hca_hdl_p = NULL;
92 		return (IBT_HCA_INVALID);
93 	}
94 
95 	/*
96 	 * Check whether open is allowed for this dip
97 	 */
98 	if (ibt_hdl->clnt_dip) {
99 		if (ddi_get_parent(ibt_hdl->clnt_dip) == hca_devp->hd_hca_dip) {
100 			if (hca_guid != hca_devp->hd_hca_attr->hca_node_guid) {
101 				mutex_exit(&ibtl_clnt_list_mutex);
102 				return (IBT_FAILURE);
103 			}
104 		}
105 	}
106 
107 	if (hca_devp->hd_state != IBTL_HCA_DEV_ATTACHED) {
108 		/*
109 		 * If we are here, then the requested HCA device has detached,
110 		 * or is in the process of detaching.
111 		 */
112 		mutex_exit(&ibtl_clnt_list_mutex);
113 
114 		IBTF_DPRINTF_L2(ibtf_hca, "ibt_open_hca: "
115 		    "HCA is busy trying to detach");
116 
117 		*hca_hdl_p = NULL;
118 		return (IBT_HCA_BUSY_DETACHING);
119 	}
120 
121 	/*
122 	 * Yes, we found a HCA Device registered with IBTF, which matches with
123 	 * the requested HCA_GUID.
124 	 *
125 	 * Check out whether this client has already opened this HCA device,
126 	 * if yes return the status as IBT_HCA_IN_USE.
127 	 */
128 	hca_infop = hca_devp->hd_clnt_list;
129 
130 	while (hca_infop != NULL) {
131 		if (ibt_hdl == hca_infop->ha_clnt_devp) {
132 			IBTF_DPRINTF_L3(ibtf_hca,
133 			    "ibt_open_hca: Already Open");
134 
135 			if (hca_infop->ha_flags & IBTL_HA_CLOSING) {
136 				mutex_exit(&ibtl_clnt_list_mutex);
137 				*hca_hdl_p = NULL;
138 				return (IBT_HCA_BUSY_CLOSING);
139 			}
140 			mutex_exit(&ibtl_clnt_list_mutex);
141 
142 			/* Already Opened. Return back old HCA Handle. */
143 			*hca_hdl_p = hca_infop;
144 
145 			return (IBT_HCA_IN_USE);
146 		}
147 		hca_infop = hca_infop->ha_clnt_link;
148 	}
149 
150 	/* Create a new HCA Info entity. */
151 	hca_infop = kmem_zalloc(sizeof (ibtl_hca_t), KM_SLEEP);
152 
153 	/* Initialize HCA Mutex. */
154 	mutex_init(&hca_infop->ha_mutex, NULL, MUTEX_DEFAULT, NULL);
155 
156 	/* Update the HCA Info entity */
157 	hca_infop->ha_hca_devp  = hca_devp;	/* HCA Device Info */
158 	hca_infop->ha_clnt_devp = ibt_hdl;	/* Client Info */
159 
160 	/* Update the HCA List, to keep track about the clients using it. */
161 	hca_infop->ha_clnt_link = hca_devp->hd_clnt_list;
162 	hca_devp->hd_clnt_list = hca_infop;
163 
164 
165 	/* Update the client's list to depict that it uses this HCA device. */
166 	hca_infop->ha_hca_link = ibt_hdl->clnt_hca_list;
167 	ibt_hdl->clnt_hca_list = hca_infop;
168 
169 	mutex_exit(&ibtl_clnt_list_mutex);
170 
171 	/*
172 	 * Return back the address of ibtl_hca_t structure as an opaque
173 	 * IBT HCA handle for the clients, to be used in future calls.
174 	 */
175 	*hca_hdl_p = hca_infop;
176 
177 	return (IBT_SUCCESS);
178 }
179 
180 
181 /*
182  * Function:
183  *      ibt_close_hca
184  * Input:
185  *      hca_hdl  - The HCA handle as returned during its open.
186  * Output:
187  *      none
188  * Returns:
189  *      IBT_SUCCESS
190  *      IBT_HCA_HDL_INVALID
191  *      IBT_HCA_RESOURCES_NOT_FREED
192  * Description:
193  *      Close a HCA.
194  */
195 ibt_status_t
196 ibt_close_hca(ibt_hca_hdl_t hca_hdl)
197 {
198 	ibtl_hca_devinfo_t	*hca_devp, *tmp_devp;
199 	ibtl_hca_t		**hcapp;
200 	ibtl_clnt_t		*clntp = hca_hdl->ha_clnt_devp;
201 
202 	IBTF_DPRINTF_L3(ibtf_hca, "ibt_close_hca(%p)", hca_hdl);
203 
204 	/*
205 	 * Verify the Input HCA Handle, if fake return error as
206 	 * invalid HCA Handle.
207 	 */
208 	mutex_enter(&ibtl_clnt_list_mutex);
209 	hca_devp = hca_hdl->ha_hca_devp;
210 	tmp_devp = ibtl_hca_list;
211 
212 	for (; tmp_devp != NULL; tmp_devp = tmp_devp->hd_hca_dev_link)
213 		if (tmp_devp == hca_devp)
214 			break;
215 
216 	if (tmp_devp == NULL) {
217 		mutex_exit(&ibtl_clnt_list_mutex);
218 		IBTF_DPRINTF_L2(ibtf_hca, "ibt_close_hca: "
219 		    "Unable to find this on global HCA list");
220 		return (IBT_HCA_HDL_INVALID);
221 	}
222 
223 	mutex_enter(&hca_hdl->ha_mutex);
224 
225 	/* Make sure resources have been freed. */
226 	if (hca_hdl->ha_qp_cnt | hca_hdl->ha_cq_cnt | hca_hdl->ha_eec_cnt |
227 	    hca_hdl->ha_ah_cnt | hca_hdl->ha_mr_cnt | hca_hdl->ha_mw_cnt |
228 	    hca_hdl->ha_pd_cnt) {
229 		IBTF_DPRINTF_L2(ibtf_hca, "ibt_close_hca: "
230 		    "some resources have not been freed by '%s': hca_hdl = %p",
231 		    hca_hdl->ha_clnt_devp->clnt_modinfop->mi_clnt_name,
232 		    hca_hdl);
233 		mutex_exit(&hca_hdl->ha_mutex);
234 		mutex_exit(&ibtl_clnt_list_mutex);
235 		return (IBT_HCA_RESOURCES_NOT_FREED);
236 	}
237 	mutex_exit(&hca_hdl->ha_mutex);	/* ok to drop this now */
238 
239 	/* we are now committed to closing the HCA */
240 	hca_hdl->ha_flags |= IBTL_HA_CLOSING;
241 	while (hca_hdl->ha_qpn_cnt > 0)
242 		cv_wait(&ibtl_close_hca_cv, &ibtl_clnt_list_mutex);
243 
244 	/*
245 	 * Remove this HCA Device entry form Client's current list of HCA
246 	 * Device Instances being used by it.
247 	 */
248 	hcapp = &clntp->clnt_hca_list;
249 
250 	for (; *hcapp != NULL; hcapp = &(*hcapp)->ha_hca_link)
251 		if (*hcapp == hca_hdl)
252 			break;
253 
254 	if (*hcapp == NULL) {
255 		IBTF_DPRINTF_L2(ibtf_hca, "ibt_close_hca: "
256 		    "Unable to find this HCA on client list");
257 		mutex_exit(&ibtl_clnt_list_mutex);
258 		return (IBT_HCA_HDL_INVALID);
259 	}
260 
261 	/* hcapp now points to a link that points to us */
262 	*hcapp = hca_hdl->ha_hca_link;		/* remove us */
263 
264 	/*
265 	 * Remove this Client's entry from this HCA Device's Clients list.
266 	 */
267 	hcapp = &hca_devp->hd_clnt_list;
268 
269 	for (; *hcapp != NULL; hcapp = &(*hcapp)->ha_clnt_link)
270 		if (*hcapp == hca_hdl)
271 			break;
272 
273 	if (*hcapp == NULL) {
274 		mutex_exit(&ibtl_clnt_list_mutex);
275 		IBTF_DPRINTF_L2(ibtf_hca, "ibt_close_hca: "
276 		    "Unable to find this HCA on the client's HCA list");
277 		return (IBT_HCA_HDL_INVALID);
278 	}
279 
280 	/* hcapp now points to a link that points to us */
281 	*hcapp = hca_hdl->ha_clnt_link;		/* remove us */
282 	mutex_exit(&ibtl_clnt_list_mutex);
283 
284 	/* Un-Initialize HCA Mutex. */
285 	mutex_destroy(&hca_hdl->ha_mutex);
286 
287 	/* Free memory for this HCA Handle */
288 	ibtl_free_hca_async_check(hca_hdl);
289 
290 	return (IBT_SUCCESS);
291 }
292 
293 void
294 ibtl_close_hca_check(ibt_hca_hdl_t hca_hdl)
295 {
296 	IBTF_DPRINTF_L3(ibtf_hca, "ibtl_close_hca_check(%p)", hca_hdl);
297 
298 	mutex_enter(&ibtl_clnt_list_mutex);
299 	if ((--hca_hdl->ha_qpn_cnt == 0) &&
300 	    (hca_hdl->ha_flags & IBTL_HA_CLOSING)) {
301 		cv_signal(&ibtl_close_hca_cv);
302 	}
303 	mutex_exit(&ibtl_clnt_list_mutex);
304 }
305 
306 /*
307  * Function:
308  *      ibt_get_hca_list
309  * Input:
310  *      hca_list_p -  Address of pointer updated here.
311  * Output:
312  *      hca_list_p -  Points to an array of ib_guid_t's allocated here.
313  * Returns:
314  *      The actual number of valid ib_guid_t's returned.
315  * Description:
316  *	If hca_list_p is not NULL then the memory for the array of GUIDs is
317  *	allocated here and should be freed by the caller using
318  *	ibt_free_hca_list(). If hca_list_p is NULL then no memory is allocated
319  *	by ibt_get_hca_list and only the number of HCAs in a system is returned.
320  */
321 uint_t
322 ibt_get_hca_list(ib_guid_t **hca_list_p)
323 {
324 	uint_t			hca_count = 0;
325 	ibtl_hca_devinfo_t	*hca_devp;
326 	ib_guid_t		*hca_listp;
327 
328 	IBTF_DPRINTF_L3(ibtf_hca, "ibt_get_hca_list(%p)", hca_list_p);
329 
330 	mutex_enter(&ibtl_clnt_list_mutex);
331 
332 	hca_devp = ibtl_hca_list;
333 	while (hca_devp != NULL) {
334 		hca_count++;
335 		hca_devp = hca_devp->hd_hca_dev_link;
336 	}
337 
338 	if (hca_count == 0)
339 		IBTF_DPRINTF_L2(ibtf_hca, "ibt_get_hca_list: "
340 		    "HCA device not found");
341 
342 	if ((hca_count == 0) || (hca_list_p == NULL)) {
343 		mutex_exit(&ibtl_clnt_list_mutex);
344 		return (hca_count);
345 	}
346 
347 	hca_listp = kmem_alloc(hca_count * sizeof (ib_guid_t), KM_SLEEP);
348 	*hca_list_p = hca_listp;
349 
350 	hca_devp = ibtl_hca_list;
351 	while (hca_devp != NULL) {
352 		/* Traverse Global HCA List & retrieve HCA Node GUIDs. */
353 		*hca_listp++ = hca_devp->hd_hca_attr->hca_node_guid;
354 		hca_devp = hca_devp->hd_hca_dev_link;
355 	}
356 	mutex_exit(&ibtl_clnt_list_mutex);
357 
358 	IBTF_DPRINTF_L3(ibtf_hca, "ibt_get_hca_list: "
359 	    "Returned <%d> entries @0x%p", hca_count, *hca_list_p);
360 
361 	return (hca_count);
362 }
363 
364 /*
365  * Function:
366  *      ibt_free_hca_list
367  * Input:
368  *      hca_list  - The address of an ib_guid_t pointer.
369  *      entries   - The number of ib_guid_t entries to be freed.
370  * Output:
371  *      none.
372  * Returns:
373  *      none.
374  * Description:
375  *      The memory allocated in ibt_get_hca_list() is freed in this function.
376  */
377 void
378 ibt_free_hca_list(ib_guid_t *hca_list, uint_t entries)
379 {
380 	IBTF_DPRINTF_L3(ibtf_hca, "ibt_free_hca_list: "
381 	    "Free <%d> entries from 0x%p", entries, hca_list);
382 
383 	if ((hca_list != NULL) && (entries > 0))
384 		kmem_free(hca_list, entries * sizeof (ib_guid_t));
385 }
386 
387 /*
388  * ibtl_portinfo_locked() is called when the portinfo cache is being
389  * updated.  If this port's info update is in progress, we return 0
390  * immediately and have the c
391  * unless it's already in progress (distinguished by return value).
392  * When done updating the portinfo, they call ibtl_portinfo_unlock().
393  */
394 
395 static int
396 ibtl_portinfo_locked(ibtl_hca_devinfo_t *hca_devp, uint8_t port)
397 {
398 	ASSERT(MUTEX_HELD(&ibtl_clnt_list_mutex));
399 
400 	for (;;) {
401 		if (hca_devp->hd_portinfo_locked_port == 0) {
402 			hca_devp->hd_portinfo_locked_port = port;
403 			return (1); /* not busy, so OK to initiate update */
404 		} else if (hca_devp->hd_portinfo_locked_port == port) {
405 			IBTF_DPRINTF_L3(ibtf_hca, "ibtl_portinfo_locked: "
406 			    "HCA %p port %d is already locked",
407 			    hca_devp, port);
408 			hca_devp->hd_portinfo_waiters = 1;
409 			cv_wait(&hca_devp->hd_portinfo_cv,
410 			    &ibtl_clnt_list_mutex);
411 			return (0); /* it's now done, so no need to initiate */
412 		} else {
413 			/* need to wait for other port before we try again */
414 			hca_devp->hd_portinfo_waiters = 1;
415 			cv_wait(&hca_devp->hd_portinfo_cv,
416 			    &ibtl_clnt_list_mutex);
417 		}
418 	}
419 }
420 
421 static void
422 ibtl_portinfo_unlock(ibtl_hca_devinfo_t *hca_devp, uint8_t port)
423 {
424 	ASSERT(MUTEX_HELD(&ibtl_clnt_list_mutex));
425 	ASSERT(hca_devp->hd_portinfo_locked_port == port);
426 	hca_devp->hd_portinfo_locked_port = 0;
427 	if (hca_devp->hd_portinfo_waiters) {
428 		hca_devp->hd_portinfo_waiters = 0;
429 		cv_broadcast(&hca_devp->hd_portinfo_cv);
430 		IBTF_DPRINTF_L3(ibtf_hca, "ibtl_portinfo_unlock: "
431 		    "waking up waiters for port %d info on HCA %p",
432 		    port, hca_devp);
433 	}
434 }
435 
436 /*
437  * Function:
438  *      ibt_get_port_state
439  * Input:
440  *      hca_devp    - The HCA Dev Info pointer.
441  *	port        - Port number to query.
442  * Output:
443  *      sgid_p	    - Returned sgid[0], NULL implies no return value.
444  *      base_lid_p  - Returned base_lid, NULL implies no return value.
445  * Returns:
446  *      IBT_SUCCESS
447  *	IBT_HCA_PORT_INVALID
448  * Description:
449  *      Returns HCA port attributes for one of the HCA ports.
450  */
451 static ibt_status_t
452 ibtl_get_port_state(ibtl_hca_devinfo_t *hca_devp, uint8_t port,
453     ib_gid_t *sgid_p, ib_lid_t *base_lid_p)
454 {
455 	ibt_hca_portinfo_t *portinfop;
456 
457 	ASSERT(MUTEX_HELD(&ibtl_clnt_list_mutex));
458 
459 	if ((port < 1) || (port > hca_devp->hd_hca_attr->hca_nports)) {
460 		IBTF_DPRINTF_L2(ibtf_hca, "ibtl_get_port_state: "
461 		    "invalid port %d, nports = %d", port,
462 		    hca_devp->hd_hca_attr->hca_nports);
463 		return (IBT_HCA_PORT_INVALID);
464 	}
465 	portinfop = hca_devp->hd_portinfop + port - 1;
466 
467 	if (sgid_p)
468 		*sgid_p = portinfop->p_sgid_tbl[0];
469 	if (base_lid_p)
470 		*base_lid_p = portinfop->p_base_lid;
471 	if (portinfop->p_linkstate != IBT_PORT_ACTIVE) {
472 		IBTF_DPRINTF_L2(ibtf_hca, "ibtl_get_port_state: "
473 		    "port %d, port_state %d, base_lid %d",
474 		    port, portinfop->p_linkstate, portinfop->p_base_lid);
475 		return (IBT_HCA_PORT_NOT_ACTIVE);
476 	}
477 	IBTF_DPRINTF_L3(ibtf_hca, "ibtl_get_port_state: "
478 	    "port %d, port_state %d, base_lid %d",
479 	    port, portinfop->p_linkstate, portinfop->p_base_lid);
480 	return (IBT_SUCCESS);
481 }
482 
483 /*
484  * Function:
485  *      ibt_get_port_state
486  * Input:
487  *      hca_hdl	    - The HCA handle.
488  *	port        - Port number to query.
489  * Output:
490  *      sgid_p	    - Returned sgid[0], NULL implies no return value.
491  *      base_lid_p  - Returned base_lid, NULL implies no return value.
492  * Returns:
493  *      IBT_SUCCESS
494  *	IBT_HCA_PORT_INVALID
495  * Description:
496  *      Returns HCA port attributes for one of the HCA ports.
497  */
498 ibt_status_t
499 ibt_get_port_state(ibt_hca_hdl_t hca_hdl, uint8_t port,
500     ib_gid_t *sgid_p, ib_lid_t *base_lid_p)
501 {
502 	ibt_status_t		retval;
503 
504 	IBTF_DPRINTF_L3(ibtf_hca, "ibt_get_port_state(%p, %d, %p, %p)",
505 	    hca_hdl, port, sgid_p, base_lid_p);
506 	mutex_enter(&ibtl_clnt_list_mutex);
507 	retval = ibtl_get_port_state(hca_hdl->ha_hca_devp, port, sgid_p,
508 	    base_lid_p);
509 	mutex_exit(&ibtl_clnt_list_mutex);
510 	return (retval);
511 }
512 
513 
514 /*
515  * Function:
516  *      ibt_get_port_state_byguid
517  * Input:
518  *      hca_guid    - The HCA node GUID.
519  *	port        - Port number to query.
520  * Output:
521  *      sgid_p	    - Returned sgid[0], NULL implies no return value.
522  *      base_lid_p  - Returned base_lid, NULL implies no return value.
523  * Returns:
524  *      IBT_SUCCESS
525  *	IBT_HCA_PORT_INVALID
526  *      IBT_HCA_INVALID
527  * Description:
528  *      Returns HCA port attributes for one of the HCA ports.
529  */
530 ibt_status_t
531 ibt_get_port_state_byguid(ib_guid_t hca_guid, uint8_t port,
532     ib_gid_t *sgid_p, ib_lid_t *base_lid_p)
533 {
534 	ibtl_hca_devinfo_t	*hca_devp;		/* HCA Dev Info */
535 	ibt_status_t		retval;
536 
537 	IBTF_DPRINTF_L3(ibtf_hca, "ibt_get_port_state_byguid(%llx, %d, %p, "
538 	    "%p)", (longlong_t)hca_guid, port, sgid_p, base_lid_p);
539 	mutex_enter(&ibtl_clnt_list_mutex);
540 	hca_devp = ibtl_get_hcadevinfo(hca_guid);
541 	if (hca_devp == NULL)
542 		retval = IBT_HCA_INVALID;
543 	else
544 		retval = ibtl_get_port_state(hca_devp, port, sgid_p,
545 		    base_lid_p);
546 	mutex_exit(&ibtl_clnt_list_mutex);
547 	return (retval);
548 }
549 
550 
551 /*
552  * Function:
553  *      ibt_query_hca_byguid
554  * Input:
555  *      hca_guid  - The HCA node GUID.
556  * Output:
557  *      hca_attrs - A pointer to a ibt_hca_attr_t allocated by the caller,
558  *                  into which the HCA Attributes are copied.
559  * Returns:
560  *      IBT_SUCCESS
561  *      IBT_INVALID_PARAM
562  *      IBT_HCA_INVALID
563  * Description:
564  *      Returns the static attributes of the specified HCA.
565  */
566 ibt_status_t
567 ibt_query_hca_byguid(ib_guid_t hca_guid, ibt_hca_attr_t *hca_attrs)
568 {
569 	ibtl_hca_devinfo_t	*hca_devp;	/* HCA Dev Info. */
570 
571 	IBTF_DPRINTF_L3(ibtf_hca, "ibt_query_hca_byguid(%llX)", hca_guid);
572 
573 	mutex_enter(&ibtl_clnt_list_mutex);
574 	/* Get HCA Dev Info Structure, referenced by HCA GUID. */
575 	hca_devp = ibtl_get_hcadevinfo(hca_guid);
576 	if (hca_devp == NULL) {
577 		/*
578 		 * If we are here, then the requested HCA device is not present.
579 		 */
580 		mutex_exit(&ibtl_clnt_list_mutex);
581 		IBTF_DPRINTF_L2(ibtf_hca, "ibt_query_hca_byguid: "
582 		    "Device Not Found");
583 		return (IBT_HCA_INVALID);
584 	}
585 
586 	/* Return back the static HCA attributes */
587 	bcopy(hca_devp->hd_hca_attr, hca_attrs, sizeof (ibt_hca_attr_t));
588 
589 	mutex_exit(&ibtl_clnt_list_mutex);
590 
591 	return (IBT_SUCCESS);
592 }
593 
594 
595 /*
596  * Function:
597  *      ibt_query_hca
598  * Input:
599  *      hca_hdl   - The HCA handle.
600  * Output:
601  *      hca_attrs - A pointer to a ibt_hca_attr_t allocated by the caller,
602  *                  into which the HCA Attributes are copied.
603  * Returns:
604  *      IBT_SUCCESS
605  *
606  * Description:
607  *      Returns the static attributes of the specified HCA.
608  */
609 ibt_status_t
610 ibt_query_hca(ibt_hca_hdl_t hca_hdl, ibt_hca_attr_t *hca_attrs)
611 {
612 	IBTF_DPRINTF_L3(ibtf_hca, "ibt_query_hca(%p)", hca_hdl);
613 
614 	/* Return back the static HCA attributes */
615 	bcopy(hca_hdl->ha_hca_devp->hd_hca_attr, hca_attrs,
616 	    sizeof (ibt_hca_attr_t));
617 
618 	return (IBT_SUCCESS);
619 }
620 
621 #define	ROUNDUP(x, y)	((((x)+((y)-1))/(y))*(y))
622 
623 /*
624  * Function:
625  *      ibt_query_hca_ports
626  * Input:
627  *      hca_hdl	    - The HCA handle.
628  *	port        - Port number.  If "0", then query ALL Ports.
629  * Output:
630  *      port_info_p - The address of a pointer to a ibt_hca_portinfo_t struct.
631  *      ports_p     - The number of hca ports on the specified HCA.
632  *      size_p      - Size of the memory allocated by IBTL to get portinfo,
633  *                   to be freed by calling ibt_free_portinfo().
634  * Returns:
635  *      IBT_SUCCESS
636  *      IBT_HCA_HDL_INVALID
637  *      IBT_HCA_INVALID
638  * Description:
639  *      Returns HCA port attributes for either "one", or "all" of the HCA ports.
640  */
641 ibt_status_t
642 ibt_query_hca_ports(ibt_hca_hdl_t hca_hdl, uint8_t port,
643     ibt_hca_portinfo_t **port_info_p, uint_t *ports_p, uint_t *size_p)
644 {
645 	ibt_status_t	retval;
646 
647 	IBTF_DPRINTF_L3(ibtf_hca, "ibt_query_hca_ports(%p, %d)",
648 	    hca_hdl, port);
649 
650 	mutex_enter(&ibtl_clnt_list_mutex);
651 
652 	retval = ibtl_query_hca_ports(hca_hdl->ha_hca_devp, port, port_info_p,
653 	    ports_p, size_p, 0);
654 
655 	mutex_exit(&ibtl_clnt_list_mutex);
656 
657 	return (retval);
658 }
659 
660 /*
661  * Function:
662  *      ibt_query_hca_ports_byguid
663  * Input:
664  *      hca_guid    - The HCA node GUID.
665  *	port        - Port number.  If "0", then query ALL Ports.
666  * Output:
667  *      port_info_p - The address of a pointer to a ibt_hca_portinfo_t struct.
668  *      ports_p     - The number of hca ports on the specified HCA.
669  *      size_p      - Size of the memory allocated by IBTL to get portinfo,
670  *                   to be freed by calling ibt_free_portinfo().
671  * Returns:
672  *      IBT_SUCCESS
673  *      IBT_HCA_HDL_INVALID
674  *      IBT_HCA_INVALID
675  * Description:
676  *      Returns HCA port attributes for either "one", or "all" of the HCA ports.
677  */
678 ibt_status_t
679 ibt_query_hca_ports_byguid(ib_guid_t hca_guid, uint8_t port,
680     ibt_hca_portinfo_t **port_info_p, uint_t *ports_p, uint_t *size_p)
681 {
682 	ibtl_hca_devinfo_t	*hca_devp;	/* HCA Dev Info */
683 	ibt_status_t		retval;
684 
685 	mutex_enter(&ibtl_clnt_list_mutex);
686 	hca_devp = ibtl_get_hcadevinfo(hca_guid);
687 	if (hca_devp == NULL) {
688 		/*
689 		 * If we are here, then the requested HCA device is not present.
690 		 * Return the status as Invalid HCA GUID.
691 		 */
692 		*ports_p = *size_p = 0;
693 		*port_info_p = NULL;
694 		mutex_exit(&ibtl_clnt_list_mutex);
695 		IBTF_DPRINTF_L2(ibtf_hca, "ibt_query_hca_ports_byguid: "
696 		    "HCA Device Not Found. ");
697 		return (IBT_HCA_INVALID);
698 	}
699 
700 	retval = ibtl_query_hca_ports(hca_devp, port, port_info_p, ports_p,
701 	    size_p, 0);
702 
703 	mutex_exit(&ibtl_clnt_list_mutex);
704 
705 	return (retval);
706 }
707 
708 /*
709  * Define the above function for CM's use that uses the cached copy.
710  */
711 ibt_status_t
712 ibtl_cm_query_hca_ports_byguid(ib_guid_t hca_guid, uint8_t port,
713     ibt_hca_portinfo_t **port_info_p, uint_t *ports_p, uint_t *size_p)
714 {
715 	ibtl_hca_devinfo_t	*hca_devp;	/* HCA Dev Info */
716 	ibt_status_t		retval;
717 
718 	mutex_enter(&ibtl_clnt_list_mutex);
719 	hca_devp = ibtl_get_hcadevinfo(hca_guid);
720 	if (hca_devp == NULL) {
721 		/*
722 		 * If we are here, then the requested HCA device is not present.
723 		 * Return the status as Invalid HCA GUID.
724 		 */
725 		*ports_p = *size_p = 0;
726 		*port_info_p = NULL;
727 		mutex_exit(&ibtl_clnt_list_mutex);
728 		IBTF_DPRINTF_L2(ibtf_hca, "ibt_query_hca_ports_byguid: "
729 		    "HCA Device Not Found. ");
730 		return (IBT_HCA_INVALID);
731 	}
732 
733 	retval = ibtl_query_hca_ports(hca_devp, port, port_info_p, ports_p,
734 	    size_p, 1);
735 
736 	mutex_exit(&ibtl_clnt_list_mutex);
737 
738 	return (retval);
739 }
740 
741 
742 /*
743  * ibtl_query_one_port - fill in portinfo for one port.
744  */
745 static ibt_status_t
746 ibtl_query_one_port(ibtl_hca_devinfo_t *hca_devp, uint8_t port,
747     ibt_hca_portinfo_t **port_info_p, uint_t *ports_p, uint_t *size_p,
748     int use_cache)
749 {
750 	ibt_hca_portinfo_t	*sp1;	/* src */
751 	ibt_hca_portinfo_t	*p1;	/* dst */
752 	caddr_t			p2;
753 	uint_t			len;
754 	uint_t			sgid_tbl_len, pkey_tbl_len;
755 
756 	ASSERT(MUTEX_HELD(&ibtl_clnt_list_mutex));
757 
758 	IBTF_DPRINTF_L3(ibtf_hca, "ibtl_query_one_port(%p, %d)",
759 	    hca_devp, port);
760 
761 	if (port > hca_devp->hd_hca_attr->hca_nports) {
762 		IBTF_DPRINTF_L2(ibtf_hca, "ibtl_query_one_port: "
763 		    "invalid port %d", port);
764 		return (IBT_HCA_PORT_INVALID);
765 	}
766 
767 	/* If the PORT_UP event is not supported, we need to query */
768 	sp1 = hca_devp->hd_portinfop + port - 1;
769 	if (use_cache == 0)
770 		ibtl_reinit_hca_portinfo(hca_devp, port);
771 
772 	*ports_p = 1;
773 
774 	/*
775 	 * Calculate how much memory we need for one port, and allocate it.
776 	 */
777 	sgid_tbl_len = ROUNDUP(sp1->p_sgid_tbl_sz * sizeof (ib_gid_t),
778 	    _LONG_LONG_ALIGNMENT);
779 	pkey_tbl_len = ROUNDUP(sp1->p_pkey_tbl_sz * sizeof (ib_pkey_t),
780 	    _LONG_LONG_ALIGNMENT);
781 
782 	len = sizeof (ibt_hca_portinfo_t) + sgid_tbl_len + pkey_tbl_len;
783 	*size_p = len;
784 
785 	p1 = kmem_zalloc(len, KM_SLEEP);
786 	*port_info_p = p1;
787 	bcopy(sp1, p1, sizeof (ibt_hca_portinfo_t));
788 
789 	/* initialize the p_pkey_tbl & p_sgid_tbl pointers. */
790 	p2 = (caddr_t)(p1 + 1);	/* pkeys follow the struct ibt_hca_portinfo_s */
791 	bcopy(sp1->p_pkey_tbl, p2, pkey_tbl_len);
792 	p1->p_pkey_tbl = (ib_pkey_t *)p2;
793 
794 	p2 += pkey_tbl_len;	/* sgids follow the pkeys */
795 	bcopy(sp1->p_sgid_tbl, p2, sgid_tbl_len);
796 	p1->p_sgid_tbl = (ib_gid_t *)p2;
797 
798 	return (IBT_SUCCESS);
799 }
800 
801 /*
802  * ibtl_query_hca_ports - worker routine to get port_info for clients.
803  */
804 static ibt_status_t
805 ibtl_query_hca_ports(ibtl_hca_devinfo_t *hca_devp, uint8_t port,
806     ibt_hca_portinfo_t **port_info_p, uint_t *ports_p, uint_t *size_p,
807     int use_cache)
808 {
809 	ibt_hca_portinfo_t	*sp1;	/* src */
810 	ibt_hca_portinfo_t	*p1;	/* dst */
811 	uint_t			i, nports;
812 	caddr_t			p2;
813 	uint_t			len;
814 	uint_t			sgid_tbl_len, pkey_tbl_len;
815 
816 	ASSERT(MUTEX_HELD(&ibtl_clnt_list_mutex));
817 
818 	/*
819 	 * If user has specified the port num, then query only that port,
820 	 * else query all ports.
821 	 */
822 	if (port)
823 		return (ibtl_query_one_port(hca_devp, port, port_info_p,
824 		    ports_p, size_p, use_cache));
825 
826 	IBTF_DPRINTF_L3(ibtf_hca, "ibtl_query_hca_ports(%p, ALL)", hca_devp);
827 
828 	nports = hca_devp->hd_hca_attr->hca_nports;
829 	*ports_p = nports;
830 
831 	/* If the PORT_UP event is not supported, we need to query */
832 	if (use_cache == 0)
833 		for (i = 0; i < nports; i++)
834 			ibtl_reinit_hca_portinfo(hca_devp, i + 1);
835 
836 	sp1 = hca_devp->hd_portinfop;
837 
838 	/*
839 	 * Calculate how much memory we need for all ports, and allocate it.
840 	 */
841 	sgid_tbl_len = ROUNDUP(sp1->p_sgid_tbl_sz * sizeof (ib_gid_t),
842 	    _LONG_LONG_ALIGNMENT);
843 	pkey_tbl_len = ROUNDUP(sp1->p_pkey_tbl_sz * sizeof (ib_pkey_t),
844 	    _LONG_LONG_ALIGNMENT);
845 
846 	len = (sizeof (ibt_hca_portinfo_t) + sgid_tbl_len + pkey_tbl_len) *
847 	    nports;
848 	*size_p = len;
849 
850 	ASSERT(len == hca_devp->hd_portinfo_len);
851 
852 	p1 = kmem_zalloc(len, KM_SLEEP);
853 	*port_info_p = p1;
854 	bcopy(sp1, p1, len);	/* start with an exact copy of our cache */
855 
856 	p2 = (caddr_t)(p1 + nports);
857 
858 	/* For each port, update the p_pkey_tbl & p_sgid_tbl ptrs. */
859 	for (i = 0; i < nports; i++) {
860 		p1->p_pkey_tbl = (ib_pkey_t *)p2;
861 		p2 += pkey_tbl_len;
862 		p1->p_sgid_tbl = (ib_gid_t *)p2;
863 		p2 += sgid_tbl_len;
864 		p1++;
865 	}
866 	return (IBT_SUCCESS);
867 }
868 
869 /*
870  *	Search for a Full pkey.  Use the pkey at index 0 if not found.
871  */
872 static void
873 ibtl_set_default_pkey_ix(ibt_hca_portinfo_t *p1)
874 {
875 	uint16_t	pkey_ix;
876 
877 	for (pkey_ix = 0; pkey_ix < p1->p_pkey_tbl_sz; pkey_ix++) {
878 		if ((p1->p_pkey_tbl[pkey_ix] & 0x8000) &&
879 		    (p1->p_pkey_tbl[pkey_ix] != IB_PKEY_INVALID_FULL)) {
880 			p1->p_def_pkey_ix = pkey_ix;
881 			IBTF_DPRINTF_L3(ibtf_hca,
882 			    "ibtl_set_default_pkey_ix: portinfop %p, "
883 			    "FULL PKEY 0x%x found, pkey_ix is %d",
884 			    p1, p1->p_pkey_tbl[pkey_ix], pkey_ix);
885 			return;
886 		}
887 	}
888 	IBTF_DPRINTF_L2(ibtf_hca,
889 	    "ibtl_set_default_pkey_ix: portinfop %p: failed "
890 	    "to find a default PKEY in the table, using PKey 0x%x",
891 	    p1, p1->p_pkey_tbl[0]);
892 	p1->p_def_pkey_ix = 0;
893 }
894 
895 /*
896  * ibtl_reinit_hca_portinfo - update the portinfo cache for use by IBTL.
897  *
898  * We have the HCA driver fill in a temporary portinfo, then we bcopy
899  * it into our cache while holding the appropriate lock.
900  */
901 void
902 ibtl_reinit_hca_portinfo(ibtl_hca_devinfo_t *hca_devp, uint8_t port)
903 {
904 	ibt_status_t		status;
905 	ibt_hca_portinfo_t	*p1, *sp1;
906 	ibt_port_state_t	old_linkstate;
907 	uint_t			len, sgid_tbl_len, pkey_tbl_len;
908 	ib_pkey_t		*saved_pkey_tbl;
909 	ib_gid_t		*saved_sgid_tbl;
910 	ib_sn_prefix_t		sn_pfx = 0;
911 	uint_t			multiSM;
912 	int			i;
913 
914 	IBTF_DPRINTF_L3(ibtf_hca, "ibtl_reinit_hca_portinfo(%p, %d)",
915 	    hca_devp, port);
916 
917 	ASSERT(MUTEX_HELD(&ibtl_clnt_list_mutex));
918 	ASSERT(port != 0);
919 
920 	if (ibtl_portinfo_locked(hca_devp, port)) {
921 		/* we got the lock, so we need to do the portinfo update */
922 
923 		/* invalidate fast_gid_cache */
924 		ibtl_fast_gid_cache_valid = B_FALSE;
925 
926 		p1 = hca_devp->hd_portinfop + port - 1;
927 		sgid_tbl_len = ROUNDUP(p1->p_sgid_tbl_sz * sizeof (ib_gid_t),
928 		    _LONG_LONG_ALIGNMENT);
929 		pkey_tbl_len = ROUNDUP(p1->p_pkey_tbl_sz * sizeof (ib_pkey_t),
930 		    _LONG_LONG_ALIGNMENT);
931 		len = sizeof (ibt_hca_portinfo_t) + sgid_tbl_len + pkey_tbl_len;
932 
933 		/* update was NOT in progress, so we do it here */
934 		mutex_exit(&ibtl_clnt_list_mutex);
935 
936 		IBTF_DPRINTF_L3(ibtf_hca, "ibtl_reinit_hca_portinfo(%p, %d): "
937 		    "calling ibc_query_hca_ports", hca_devp, port);
938 
939 		sp1 = kmem_zalloc(len, KM_SLEEP);
940 		sp1->p_pkey_tbl = (ib_pkey_t *)(sp1 + 1);
941 		sp1->p_sgid_tbl =
942 		    (ib_gid_t *)((caddr_t)sp1->p_pkey_tbl + pkey_tbl_len);
943 		status = IBTL_HDIP2CIHCAOPS_P(hca_devp)->ibc_query_hca_ports(
944 		    IBTL_HDIP2CIHCA(hca_devp), port, sp1);
945 
946 		mutex_enter(&ibtl_clnt_list_mutex);
947 		if (status != IBT_SUCCESS) {
948 			IBTF_DPRINTF_L2(ibtf_hca,
949 			    "ibtl_reinit_hca_portinfo(%p, %d): "
950 			    "ibc_query_hca_ports() failed: status = %d",
951 			    hca_devp, port, status);
952 		} else {
953 			old_linkstate = p1->p_linkstate;
954 			bcopy(sp1->p_pkey_tbl, p1->p_pkey_tbl, pkey_tbl_len);
955 			bcopy(sp1->p_sgid_tbl, p1->p_sgid_tbl, sgid_tbl_len);
956 			saved_pkey_tbl = p1->p_pkey_tbl;
957 			saved_sgid_tbl = p1->p_sgid_tbl;
958 			bcopy(sp1, p1, sizeof (ibt_hca_portinfo_t));
959 			p1->p_pkey_tbl = saved_pkey_tbl;
960 			p1->p_sgid_tbl = saved_sgid_tbl;
961 			if (p1->p_linkstate == IBT_PORT_ACTIVE) {
962 				ibtl_set_default_pkey_ix(p1);
963 				if (p1->p_linkstate != old_linkstate)
964 					IBTF_DPRINTF_L2(ibtf_hca,
965 					    "ibtl_reinit_hca_portinfo(%p, %d): "
966 					    "PORT UP", hca_devp, port);
967 			} else {
968 				p1->p_base_lid = 0;
969 				if (p1->p_linkstate != old_linkstate)
970 					IBTF_DPRINTF_L2(ibtf_hca,
971 					    "ibtl_reinit_hca_portinfo(%p, %d): "
972 					    "PORT DOWN", hca_devp, port);
973 			}
974 		}
975 		kmem_free(sp1, len);
976 
977 		/* Set multism bit accordingly. */
978 		multiSM = 0;
979 		p1 = hca_devp->hd_portinfop;
980 		for (i = 0; i < hca_devp->hd_hca_attr->hca_nports; i++) {
981 			if (p1->p_linkstate == IBT_PORT_ACTIVE) {
982 				if (sn_pfx == 0) {
983 					sn_pfx = p1->p_sgid_tbl[0].gid_prefix;
984 				} else if (sn_pfx !=
985 				    p1->p_sgid_tbl[0].gid_prefix) {
986 					multiSM = 1;
987 					IBTF_DPRINTF_L3(ibtf_hca,
988 					    "ibtl_reinit_hca_portinfo: "
989 					    "MULTI SM, Port1 SnPfx=0x%llX, "
990 					    "Port2 SnPfx=0x%llX", sn_pfx,
991 					    p1->p_sgid_tbl[0].gid_prefix);
992 				}
993 			}
994 			p1++;
995 		}
996 		hca_devp->hd_multism = multiSM;
997 
998 		ibtl_portinfo_unlock(hca_devp, port);
999 	}
1000 }
1001 
1002 /*
1003  * ibtl_init_hca_portinfo - fill in the portinfo cache for use by IBTL.
1004  */
1005 ibt_status_t
1006 ibtl_init_hca_portinfo(ibtl_hca_devinfo_t *hca_devp)
1007 {
1008 	ibt_hca_portinfo_t	*p1;
1009 	ibt_status_t		retval;
1010 	uint_t			i, nports;
1011 	caddr_t			p2;
1012 	uint_t			len;
1013 	uint_t			sgid_tbl_len, pkey_tbl_len;
1014 	uint_t			sgid_tbl_sz, pkey_tbl_sz;
1015 	ib_sn_prefix_t		sn_pfx = 0;
1016 	uint_t			multiSM;
1017 
1018 	IBTF_DPRINTF_L2(ibtf_hca, "ibtl_init_hca_portinfo(%p)", hca_devp);
1019 
1020 	ASSERT(MUTEX_HELD(&ibtl_clnt_list_mutex));
1021 
1022 	nports = hca_devp->hd_hca_attr->hca_nports;
1023 
1024 	/*
1025 	 * Calculate how much memory we need for all ports, and allocate it.
1026 	 */
1027 	pkey_tbl_sz = IBTL_HDIP2PKEYTBLSZ(hca_devp);
1028 	sgid_tbl_sz = IBTL_HDIP2SGIDTBLSZ(hca_devp);
1029 	pkey_tbl_len = ROUNDUP(pkey_tbl_sz * sizeof (ib_pkey_t),
1030 	    _LONG_LONG_ALIGNMENT);
1031 	sgid_tbl_len = ROUNDUP(sgid_tbl_sz * sizeof (ib_gid_t),
1032 	    _LONG_LONG_ALIGNMENT);
1033 
1034 	len = (sizeof (ibt_hca_portinfo_t) + sgid_tbl_len + pkey_tbl_len) *
1035 	    nports;
1036 
1037 	p1 = kmem_zalloc(len, KM_SLEEP);
1038 	p2 = (caddr_t)(p1 + nports);
1039 
1040 	hca_devp->hd_portinfop = p1;
1041 	hca_devp->hd_portinfo_len = len;
1042 
1043 	/* For each port initialize the p_pkey_tbl & p_sgid_tbl ptrs. */
1044 	for (i = 0; i < nports; i++) {
1045 		p1->p_pkey_tbl_sz = pkey_tbl_sz;
1046 		p1->p_sgid_tbl_sz = sgid_tbl_sz;
1047 		p1->p_pkey_tbl = (ib_pkey_t *)p2;
1048 		p2 += pkey_tbl_len;
1049 		p1->p_sgid_tbl = (ib_gid_t *)p2;
1050 		p2 += sgid_tbl_len;
1051 		p1++;
1052 	}
1053 	p1 = hca_devp->hd_portinfop;
1054 	mutex_exit(&ibtl_clnt_list_mutex);
1055 
1056 	/* re-direct the call to CI's call */
1057 	retval = IBTL_HDIP2CIHCAOPS_P(hca_devp)->ibc_query_hca_ports(
1058 	    IBTL_HDIP2CIHCA(hca_devp), 0, p1);
1059 
1060 	mutex_enter(&ibtl_clnt_list_mutex);
1061 	if (retval != IBT_SUCCESS) {
1062 		IBTF_DPRINTF_L2(ibtf_hca, "ibtl_init_hca_portinfo(%p): "
1063 		    "ibc_query_hca_ports() failed: status = %d",
1064 		    hca_devp, retval);
1065 		kmem_free(hca_devp->hd_portinfop, len);
1066 		hca_devp->hd_portinfop = NULL;
1067 		hca_devp->hd_portinfo_len = 0;
1068 		return (retval);
1069 	}
1070 
1071 	p1 = hca_devp->hd_portinfop;
1072 	multiSM = 0;
1073 	for (i = 0; i < nports; i++) {
1074 		if (p1->p_linkstate == IBT_PORT_ACTIVE) {
1075 			ibtl_set_default_pkey_ix(p1);
1076 			if (sn_pfx == 0) {
1077 				sn_pfx = p1->p_sgid_tbl[0].gid_prefix;
1078 			} else if (p1->p_sgid_tbl[0].gid_prefix != sn_pfx) {
1079 				multiSM = 1;
1080 				IBTF_DPRINTF_L3(ibtf_hca,
1081 				    "ibtl_init_hca_portinfo: MULTI SM, "
1082 				    "Port1 SnPfx=0x%llX, Port2 SnPfx=0x%llX",
1083 				    sn_pfx, p1->p_sgid_tbl[0].gid_prefix);
1084 			}
1085 		} else {
1086 			p1->p_base_lid = 0;
1087 		}
1088 		p1++;
1089 	}
1090 	hca_devp->hd_multism = multiSM;
1091 
1092 	return (IBT_SUCCESS);
1093 }
1094 
1095 /*
1096  * Function:
1097  *	ibt_modify_system_image
1098  * Input:
1099  *	hca_hdl	 - The HCA handle.
1100  *	sys_guid - The New system image GUID.
1101  * Description:
1102  *	Modify specified HCA's system image GUID.
1103  */
1104 ibt_status_t
1105 ibt_modify_system_image(ibt_hca_hdl_t hca_hdl, ib_guid_t sys_guid)
1106 {
1107 	ibt_status_t		retval;
1108 
1109 	IBTF_DPRINTF_L3(ibtf_hca, "ibt_modify_system_image(%p, %llX)",
1110 	    hca_hdl, sys_guid);
1111 
1112 	mutex_enter(&ibtl_clnt_list_mutex);
1113 	/* Get HCA Dev Info Structure, referenced by HCA GUID. */
1114 
1115 	/* re-direct the call to CI's call */
1116 	retval = IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_modify_system_image(
1117 	    IBTL_HCA2CIHCA(hca_hdl), sys_guid);
1118 
1119 	mutex_exit(&ibtl_clnt_list_mutex);
1120 	return (retval);
1121 }
1122 
1123 /*
1124  * Function:
1125  *	ibt_modify_system_image_byguid
1126  *
1127  * Input:
1128  *	hca_guid - The HCA Node GUID.
1129  *	sys_guid - The New system image GUID.
1130  * Description:
1131  *	Modify specified HCA's system image GUID.
1132  */
1133 ibt_status_t
1134 ibt_modify_system_image_byguid(ib_guid_t hca_guid, ib_guid_t sys_guid)
1135 {
1136 	ibtl_hca_devinfo_t	*hca_devp;	/* HCA Dev Info. */
1137 	ibt_status_t		retval;
1138 
1139 	IBTF_DPRINTF_L3(ibtf_hca, "ibt_modify_system_image_byguid(%llX, %llX)",
1140 	    hca_guid, sys_guid);
1141 
1142 	mutex_enter(&ibtl_clnt_list_mutex);
1143 	/* Get HCA Dev Info Structure, referenced by HCA GUID. */
1144 	hca_devp = ibtl_get_hcadevinfo(hca_guid);
1145 	if (hca_devp == NULL) {
1146 		/*
1147 		 * If we are here, then the requested HCA device is not present.
1148 		 */
1149 		mutex_exit(&ibtl_clnt_list_mutex);
1150 		return (IBT_HCA_INVALID);
1151 	}
1152 
1153 	/* re-direct the call to CI's call */
1154 	retval = IBTL_HDIP2CIHCAOPS_P(hca_devp)->ibc_modify_system_image(
1155 	    IBTL_HDIP2CIHCA(hca_devp), sys_guid);
1156 
1157 	mutex_exit(&ibtl_clnt_list_mutex);
1158 	return (retval);
1159 }
1160 
1161 /*
1162  * Function:
1163  *      ibt_modify_port_byguid
1164  * Input:
1165  *      hca_guid - The HCA Guid.
1166  *      cmds     - A pointer to an array of ibt_port_modify_t cmds. The
1167  *                 pmod_port field specifies the port to modify (all ports if 0)
1168  *                 and the pmod_flags field specifies which attribute to reset.
1169  *      num_cmds - The number of commands in the cmds array.
1170  * Output:
1171  *      none.
1172  * Returns:
1173  *      IBT_SUCCESS
1174  *      IBT_HCA_HDL_INVALID
1175  *      IBT_HCA_CNTR_INVALID
1176  *      IBT_HCA_CNTR_VAL_INVALID
1177  * Description:
1178  *      Reset the specified port, or all ports attribute(s).
1179  */
1180 ibt_status_t
1181 ibt_modify_port_byguid(ib_guid_t hca_guid,  uint8_t port,
1182     ibt_port_modify_flags_t flags, uint8_t init_type)
1183 {
1184 	ibtl_hca_devinfo_t	*hca_devp;	/* HCA Dev Info. */
1185 	ibt_status_t		retval;
1186 
1187 	IBTF_DPRINTF_L3(ibtf_hca, "ibt_modify_port_byguid(%llX, %d, %X, %X)",
1188 	    hca_guid, port, flags, init_type);
1189 
1190 	mutex_enter(&ibtl_clnt_list_mutex);
1191 	/* Get HCA Dev Info Structure, referenced by HCA GUID. */
1192 	hca_devp = ibtl_get_hcadevinfo(hca_guid);
1193 	if (hca_devp == NULL) {
1194 		/*
1195 		 * If we are here, then the requested HCA device is not present.
1196 		 */
1197 		mutex_exit(&ibtl_clnt_list_mutex);
1198 		return (IBT_HCA_INVALID);
1199 	}
1200 
1201 	/* re-direct the call to CI's call */
1202 	retval = IBTL_HDIP2CIHCAOPS_P(hca_devp)->ibc_modify_ports(
1203 	    IBTL_HDIP2CIHCA(hca_devp), port, flags, init_type);
1204 
1205 	mutex_exit(&ibtl_clnt_list_mutex);
1206 	return (retval);
1207 }
1208 
1209 /*
1210  * Function:
1211  *      ibt_modify_port
1212  * Input:
1213  *      hca_hdl  - The HCA handle.
1214  *      cmds     - A pointer to an array of ibt_port_modify_t cmds. The
1215  *                 pmod_port field specifies the port to modify (all ports if 0)
1216  *                 and the pmod_flags field specifies which attribute to reset.
1217  *      num_cmds - The number of commands in the cmds array.
1218  * Output:
1219  *      none.
1220  * Returns:
1221  *      IBT_SUCCESS
1222  *      IBT_HCA_HDL_INVALID
1223  *      IBT_HCA_CNTR_INVALID
1224  *      IBT_HCA_CNTR_VAL_INVALID
1225  * Description:
1226  *      Reset the specified port, or all ports attribute(s).
1227  */
1228 ibt_status_t
1229 ibt_modify_port(ibt_hca_hdl_t hca_hdl, uint8_t port,
1230     ibt_port_modify_flags_t flags, uint8_t init_type)
1231 
1232 {
1233 	ibt_status_t		retval;
1234 
1235 	IBTF_DPRINTF_L3(ibtf_hca, "ibt_modify_port(%p, %d, %X, %X)",
1236 	    hca_hdl, port, flags, init_type);
1237 
1238 	mutex_enter(&ibtl_clnt_list_mutex);
1239 
1240 	/* re-direct the call to CI's call */
1241 	retval = IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_modify_ports(
1242 	    IBTL_HCA2CIHCA(hca_hdl), port, flags, init_type);
1243 
1244 	mutex_exit(&ibtl_clnt_list_mutex);
1245 	return (retval);
1246 }
1247 
1248 /*
1249  * Function:
1250  *      ibt_free_portinfo
1251  * Input:
1252  *      port_info  - The address of an array to a ibt_hca_portinfo_t struct.
1253  *	size	   - Memory Size as returned from ibt_query_hca_ports().
1254  * Output:
1255  *      none
1256  * Returns:
1257  *      none
1258  * Description:
1259  *      Frees the memory allocated for a specified ibt_hca_portinfo_t struct.
1260  */
1261 void
1262 ibt_free_portinfo(ibt_hca_portinfo_t *port_info, uint_t size)
1263 {
1264 	IBTF_DPRINTF_L3(ibtf_hca, "ibt_free_portinfo(%p, %d)",
1265 	    port_info, size);
1266 
1267 	if ((port_info == NULL) || (size == 0)) {
1268 		IBTF_DPRINTF_L2(ibtf_hca, "ibt_free_portinfo: NULL Pointer");
1269 	} else {
1270 		kmem_free(port_info, size);
1271 	}
1272 }
1273 
1274 
1275 /*
1276  * Function:
1277  *      ibt_get_hcadevinfo
1278  * Input:
1279  *      hca_guid - The HCA's node GUID.
1280  * Output:
1281  *      none.
1282  * Returns:
1283  *      Pointer to HCA Device Info structure whose HCA GUID is requested or NULL
1284  * Description:
1285  *      Get a pointer to HCA Device Info Structure for the requested HCA GUID.
1286  *      If no matching HCA GUID Device info is found, NULL is returned.
1287  */
1288 ibtl_hca_devinfo_t *
1289 ibtl_get_hcadevinfo(ib_guid_t hca_guid)
1290 {
1291 	ibtl_hca_devinfo_t	*hca_devp;	/* HCA Dev Info */
1292 
1293 	IBTF_DPRINTF_L3(ibtf_hca, "ibtl_get_hcadevinfo(%llX)", hca_guid);
1294 
1295 	ASSERT(MUTEX_HELD(&ibtl_clnt_list_mutex));
1296 
1297 	hca_devp = ibtl_hca_list;
1298 
1299 	/*
1300 	 * Check whether a HCA device with requested Node GUID is available.
1301 	 * This is done, by searching the global HCA devinfo list and
1302 	 * comparing the Node GUID from the device attribute info.
1303 	 */
1304 	while (hca_devp != NULL) {
1305 		if (hca_devp->hd_hca_attr->hca_node_guid == hca_guid) {
1306 			/* Match Found. */
1307 			break;
1308 		}
1309 		hca_devp = hca_devp->hd_hca_dev_link;
1310 	}
1311 	return (hca_devp);
1312 }
1313 
1314 
1315 /*
1316  * Function:
1317  *      ibtl_pkey2index
1318  * Input:
1319  *      hca_devp     - The IBTL HCA Device Info.
1320  *      port_num     - The HCA port number.
1321  *      pkey         - The input PKey value, whose index we are interested in.
1322  * Output:
1323  *      pkey_ix      - The PKey index returned for the specified PKey.
1324  * Returns:
1325  *      IBT_SUCCESS/IBT_HCA_PORT_INVALID/IBT_INVALID_PARAM
1326  * Description:
1327  *      Returns the PKey Index for the specified PKey, the device as specified
1328  *      by IBT HCA Handle.
1329  */
1330 static ibt_status_t
1331 ibtl_pkey2index(ibtl_hca_devinfo_t *hca_devp, uint8_t port_num,
1332     ib_pkey_t pkey, uint16_t *pkey_ix)
1333 {
1334 	ibt_hca_portinfo_t 	*port_infop;
1335 	uint_t			ports;
1336 	uint_t			i;
1337 
1338 	IBTF_DPRINTF_L3(ibtf_hca, "ibtl_pkey2index(%p, %d, %d)",
1339 	    hca_devp, port_num, pkey);
1340 
1341 	ASSERT(MUTEX_HELD(&ibtl_clnt_list_mutex));
1342 
1343 	if ((pkey == IB_PKEY_INVALID_FULL) ||
1344 	    (pkey == IB_PKEY_INVALID_LIMITED))
1345 		return (IBT_INVALID_PARAM);
1346 
1347 	ports = hca_devp->hd_hca_attr->hca_nports;
1348 	if ((port_num == 0) || (port_num > ports)) {
1349 		IBTF_DPRINTF_L2(ibtf_hca, "ibtl_pkey2index: "
1350 		    "Invalid port_num %d, range is (1 to %d)", port_num, ports);
1351 		return (IBT_HCA_PORT_INVALID);
1352 	}
1353 
1354 	port_infop = hca_devp->hd_portinfop + port_num - 1;
1355 	for (i = 0; i < port_infop->p_pkey_tbl_sz; i++) {
1356 		if (pkey == port_infop->p_pkey_tbl[i]) {
1357 			*pkey_ix = i;
1358 			return (IBT_SUCCESS);
1359 		}
1360 	}
1361 	return (IBT_INVALID_PARAM);
1362 }
1363 
1364 /*
1365  * Function:
1366  *      ibtl_index2pkey
1367  * Input:
1368  *      hca_devp     - The IBTL HCA Device Info.
1369  *      port_num     - The HCA port
1370  *      pkey_ix      - The input PKey index, whose PKey we are interested in.
1371  * Output:
1372  *      pkey         - The returned PKey value.
1373  * Returns:
1374  *      IBT_SUCCESS/IBT_PKEY_IX_ILLEGAL/IBT_PKEY_IX_INVALID/IBT_HCA_PORT_INVALID
1375  * Description:
1376  *      Returns the PKey value for the specified PKey index, the device as
1377  *      specified by IBT HCA Handle.
1378  */
1379 static ibt_status_t
1380 ibtl_index2pkey(ibtl_hca_devinfo_t *hca_devp, uint8_t port_num,
1381     uint16_t pkey_ix, ib_pkey_t *pkey)
1382 {
1383 	ibt_hca_portinfo_t 	*port_infop;
1384 	uint_t			ports;
1385 
1386 	IBTF_DPRINTF_L3(ibtf_hca, "ibtl_index2pkey(%p, %d, %d)",
1387 	    hca_devp, port_num, pkey_ix);
1388 
1389 	ASSERT(MUTEX_HELD(&ibtl_clnt_list_mutex));
1390 
1391 	ports = hca_devp->hd_hca_attr->hca_nports;
1392 	if ((port_num == 0) || (port_num > ports)) {
1393 		IBTF_DPRINTF_L2(ibtf_hca, "ibtl_index2pkey: "
1394 		    "Invalid port_num %d, range is (1 to %d)", port_num, ports);
1395 		return (IBT_HCA_PORT_INVALID);
1396 	}
1397 
1398 	port_infop = hca_devp->hd_portinfop + port_num - 1;
1399 	if (pkey_ix >= port_infop->p_pkey_tbl_sz) {
1400 		IBTF_DPRINTF_L2(ibtf_hca, "ibtl_index2pkey: "
1401 		    "pkey index %d out of range (0, %d)",
1402 		    pkey_ix, port_infop->p_pkey_tbl_sz - 1);
1403 		return (IBT_PKEY_IX_ILLEGAL);
1404 	}
1405 
1406 	*pkey = port_infop->p_pkey_tbl[pkey_ix];
1407 	if ((*pkey == IB_PKEY_INVALID_FULL) ||
1408 	    (*pkey == IB_PKEY_INVALID_LIMITED))
1409 		return (IBT_PKEY_IX_INVALID);
1410 	return (IBT_SUCCESS);
1411 }
1412 
1413 /*
1414  * Function:
1415  *      ibt_pkey2index
1416  * Input:
1417  *      hca_hdl      - The IBT HCA handle.
1418  *      port_num     - The HCA port number.
1419  *      pkey         - The input PKey value, whose index we are interested in.
1420  * Output:
1421  *      pkey_ix      - The PKey index returned for the specified PKey.
1422  * Returns:
1423  *      IBT_SUCCESS/IBT_HCA_PORT_INVALID/IBT_INVALID_PARAM
1424  * Description:
1425  *      Returns the PKey Index for the specified PKey, the device as specified
1426  *      by IBT HCA Handle.
1427  */
1428 ibt_status_t
1429 ibt_pkey2index(ibt_hca_hdl_t hca_hdl, uint8_t port_num, ib_pkey_t pkey,
1430     uint16_t *pkey_ix)
1431 {
1432 	ibt_status_t		retval;
1433 
1434 	IBTF_DPRINTF_L3(ibtf_hca, "ibt_pkey2index(%p, %d, %d)",
1435 	    hca_hdl, port_num, pkey);
1436 
1437 	mutex_enter(&ibtl_clnt_list_mutex);
1438 	retval = ibtl_pkey2index(hca_hdl->ha_hca_devp, port_num, pkey, pkey_ix);
1439 	mutex_exit(&ibtl_clnt_list_mutex);
1440 
1441 	return (retval);
1442 }
1443 
1444 /*
1445  * Function:
1446  *      ibt_pkey2index_byguid
1447  * Input:
1448  *      hca_guid     - The HCA's node GUID.
1449  *      port_num     - The HCA port number.
1450  *      pkey         - The input PKey value, whose index we are interested in.
1451  * Output:
1452  *      pkey_ix      - The PKey Index returned for the specified PKey.
1453  * Returns:
1454  *      IBT_SUCCESS/IBT_HCA_PORT_INVALID/IBT_INVALID_PARAM/IBT_HCA_INVALID
1455  * Description:
1456  *      Returns the PKey Index for the specified PKey, the device as specified
1457  *      by HCA GUID Info.
1458  */
1459 ibt_status_t
1460 ibt_pkey2index_byguid(ib_guid_t hca_guid, uint8_t port_num, ib_pkey_t pkey,
1461     uint16_t *pkey_ix)
1462 {
1463 	ibt_status_t		retval;
1464 	ibtl_hca_devinfo_t	*hca_devp;	/* HCA Dev Info */
1465 
1466 	IBTF_DPRINTF_L3(ibtf_hca, "ibt_pkey2index_byguid(%llX, %d, %d)",
1467 	    hca_guid, port_num, pkey);
1468 
1469 	mutex_enter(&ibtl_clnt_list_mutex);
1470 	hca_devp = ibtl_get_hcadevinfo(hca_guid);
1471 	if (hca_devp == NULL) {
1472 		IBTF_DPRINTF_L2(ibtf_hca, "ibt_pkey2index_byguid: "
1473 		    "Invalid HCA GUID 0x%llx", hca_guid);
1474 		mutex_exit(&ibtl_clnt_list_mutex);
1475 		return (IBT_HCA_INVALID);
1476 	}
1477 	retval = ibtl_pkey2index(hca_devp, port_num, pkey, pkey_ix);
1478 	mutex_exit(&ibtl_clnt_list_mutex);
1479 
1480 	return (retval);
1481 }
1482 
1483 
1484 /*
1485  * Function:
1486  *      ibt_index2pkey
1487  * Input:
1488  *      hca_hdl      - The IBT HCA handle.
1489  *      port_num     - The HCA port
1490  *      pkey_ix      - The input PKey index, whose PKey we are interested in.
1491  * Output:
1492  *      pkey         - The returned PKey value.
1493  * Returns:
1494  *      IBT_SUCCESS/IBT_PKEY_IX_ILLEGAL/IBT_PKEY_IX_INVALID/IBT_HCA_PORT_INVALID
1495  * Description:
1496  *      Returns the PKey value for the specified PKey index, the device as
1497  *      specified by IBT HCA Handle.
1498  */
1499 ibt_status_t
1500 ibt_index2pkey(ibt_hca_hdl_t hca_hdl, uint8_t port_num, uint16_t pkey_ix,
1501     ib_pkey_t *pkey)
1502 {
1503 	ibt_status_t		retval;
1504 
1505 	IBTF_DPRINTF_L3(ibtf_hca, "ibt_index2pkey(%p, %d, %d)",
1506 	    hca_hdl, port_num, pkey_ix);
1507 
1508 	mutex_enter(&ibtl_clnt_list_mutex);
1509 	retval = ibtl_index2pkey(hca_hdl->ha_hca_devp, port_num, pkey_ix, pkey);
1510 	mutex_exit(&ibtl_clnt_list_mutex);
1511 
1512 	return (retval);
1513 }
1514 
1515 /*
1516  * Function:
1517  *      ibt_index2pkey_byguid
1518  * Input:
1519  *      hca_guid     - The HCA's node GUID.
1520  *      port_num     - The HCA port
1521  *      pkey_ix      - The input PKey index, whose PKey we are interested in.
1522  * Output:
1523  *      pkey         - The returned PKey value, for the specified index.
1524  * Returns:
1525  *      IBT_SUCCESS/IBT_PKEY_IX_ILLEGAL/IBT_PKEY_IX_INVALID/
1526  *	IBT_HCA_PORT_INVALID/IBT_HCA_INVALID
1527  * Description:
1528  *      Returns the PKey Index for the specified PKey, the device as specified
1529  *      by HCA GUID Info.
1530  */
1531 ibt_status_t
1532 ibt_index2pkey_byguid(ib_guid_t hca_guid, uint8_t port_num, uint16_t pkey_ix,
1533     ib_pkey_t *pkey)
1534 {
1535 	ibt_status_t		retval;
1536 	ibtl_hca_devinfo_t	*hca_devp;	/* HCA Dev Info */
1537 
1538 	IBTF_DPRINTF_L3(ibtf_hca, "ibt_index2pkey_byguid(%llX, %d, %d)",
1539 	    hca_guid, port_num, pkey_ix);
1540 
1541 	mutex_enter(&ibtl_clnt_list_mutex);
1542 	hca_devp = ibtl_get_hcadevinfo(hca_guid);
1543 	if (hca_devp == NULL) {
1544 		IBTF_DPRINTF_L2(ibtf_hca, "ibt_index2pkey_byguid: "
1545 		    "Invalid HCA GUID 0x%llx", hca_guid);
1546 		mutex_exit(&ibtl_clnt_list_mutex);
1547 		return (IBT_HCA_INVALID);
1548 	}
1549 	retval = ibtl_index2pkey(hca_devp, port_num, pkey_ix, pkey);
1550 	mutex_exit(&ibtl_clnt_list_mutex);
1551 
1552 	return (retval);
1553 }
1554 
1555 
1556 _NOTE(SCHEME_PROTECTS_DATA("client managed", ibtl_hca_s::ha_clnt_private))
1557 
1558 /*
1559  * Function:
1560  *      ibt_set_hca_private
1561  * Input:
1562  *      hca_hdl		The ibt_hca_hdl_t of the opened HCA.
1563  *      clnt_private	The client private data.
1564  * Output:
1565  *	none.
1566  * Returns:
1567  *      none
1568  * Description:
1569  *      Sets the client private data.
1570  */
1571 void
1572 ibt_set_hca_private(ibt_hca_hdl_t hca_hdl, void *clnt_private)
1573 {
1574 	hca_hdl->ha_clnt_private = clnt_private;
1575 }
1576 
1577 
1578 /*
1579  * Function:
1580  *      ibt_get_hca_private
1581  * Input:
1582  *      hca_hdl		The ibt_hca_hdl_t of the opened HCA.
1583  * Output:
1584  *      none
1585  * Returns:
1586  *      The client private data.
1587  * Description:
1588  *      Retrieves the private data from a specified HCA.
1589  */
1590 void *
1591 ibt_get_hca_private(ibt_hca_hdl_t hca_hdl)
1592 {
1593 	return (hca_hdl->ha_clnt_private);
1594 }
1595 
1596 /*
1597  * Function:
1598  *	ibt_hca_handle_to_guid
1599  * Input:
1600  *	hca		HCA Handle.
1601  * Output:
1602  *	none.
1603  * Returns:
1604  *	hca_guid	Returned HCA GUID on which the specified Channel is
1605  *			allocated. Valid if it is non-NULL on return.
1606  * Description:
1607  *	A helper function to retrieve HCA GUID for the specified handle.
1608  */
1609 ib_guid_t
1610 ibt_hca_handle_to_guid(ibt_hca_hdl_t hca)
1611 {
1612 	IBTF_DPRINTF_L3(ibtf_hca, "ibt_hca_handle_to_guid(%p)", hca);
1613 	return (IBTL_HCA2HCAGUID(hca));
1614 }
1615 
1616 /*
1617  * Function:
1618  *	ibt_hca_guid_to_handle
1619  * Input:
1620  *	ibt_hdl		The handle returned to the client by the IBTF from
1621  *                      an ibt_attach() call.
1622  *	hca_guid	HCA GUID
1623  * Output:
1624  *	hca_hdl		Returned ibt_hca_hdl_t.
1625  * Returns:
1626  *      IBT_SUCCESS
1627  *      IBT_HCA_INVALID
1628  * Description:
1629  *	A helper function to retrieve a hca handle from a HCA GUID.
1630  */
1631 ibt_status_t
1632 ibt_hca_guid_to_handle(ibt_clnt_hdl_t ibt_hdl, ib_guid_t hca_guid,
1633     ibt_hca_hdl_t *hca_hdl)
1634 {
1635 	ibtl_hca_t  		*hca_infop;
1636 	ibtl_hca_devinfo_t	*hca_devp;		/* HCA Dev Info */
1637 	ibt_status_t		rval = IBT_HCA_INVALID;
1638 
1639 	IBTF_DPRINTF_L3(ibtf_hca, "ibt_hca_guid_to_handle(%p, %llX)",
1640 	    ibt_hdl, hca_guid);
1641 
1642 	mutex_enter(&ibtl_clnt_list_mutex);
1643 
1644 	/*
1645 	 * Get HCA Device Info Structure, referenced by HCA GUID.
1646 	 */
1647 	hca_devp = ibtl_get_hcadevinfo(hca_guid);
1648 	if (hca_devp == NULL) {
1649 		/*
1650 		 * If we are here, then the requested HCA device is not present.
1651 		 * Return the status as Invalid HCA GUID.
1652 		 */
1653 		mutex_exit(&ibtl_clnt_list_mutex);
1654 
1655 		IBTF_DPRINTF_L2(ibtf_hca, "ibt_hca_guid_to_handle: "
1656 		    "HCA Device Not Found: Invalid HCA GUID");
1657 
1658 		*hca_hdl = NULL;
1659 		return (rval);
1660 	}
1661 
1662 	/*
1663 	 * Yes, we found a HCA Device registered with IBTF, which matches with
1664 	 * the requested HCA_GUID.
1665 	 */
1666 	hca_infop = hca_devp->hd_clnt_list;
1667 
1668 	while (hca_infop != NULL) {
1669 		if (ibt_hdl == hca_infop->ha_clnt_devp) {
1670 			rval = IBT_SUCCESS;
1671 			break;
1672 		}
1673 		hca_infop = hca_infop->ha_clnt_link;
1674 	}
1675 
1676 	mutex_exit(&ibtl_clnt_list_mutex);
1677 	*hca_hdl = hca_infop;
1678 	return (rval);
1679 }
1680