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