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