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