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 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #include <sys/ib/ibtl/impl/ibtl.h>
27 #include <sys/ib/ibtl/impl/ibtl_cm.h>
28
29 /*
30 * ibtl_cm.c
31 * These routines tie the Communication Manager into IBTL.
32 */
33
34 /*
35 * Globals.
36 */
37 static char ibtf_cm[] = "ibtl_cm";
38 boolean_t ibtl_fast_gid_cache_valid = B_FALSE;
39
40 /*
41 * Function:
42 * ibtl_cm_set_chan_private
43 * Input:
44 * chan Channel Handle.
45 * cm_private CM private data.
46 * Output:
47 * none.
48 * Returns:
49 * none.
50 * Description:
51 * A helper function to store CM's Private data in the specified channel.
52 */
53 void
54 ibtl_cm_set_chan_private(ibt_channel_hdl_t chan, void *cm_private)
55 {
56 IBTF_DPRINTF_L3(ibtf_cm, "ibtl_cm_set_chan_private(%p, %p)",
57 chan, cm_private);
58
59 mutex_enter(&chan->ch_cm_mutex);
60 chan->ch_cm_private = cm_private;
61 if (cm_private == NULL)
62 cv_signal(&chan->ch_cm_cv);
63 mutex_exit(&chan->ch_cm_mutex);
64 }
65
66
67 /*
68 * Function:
69 * ibtl_cm_get_chan_private
70 * Input:
71 * chan Channel Handle.
72 * Output:
73 * cm_private_p The CM private data.
74 * Returns:
75 * CM private data.
76 * Description:
77 * A helper function to get CM's Private data for the specified channel.
78 */
79 void *
80 ibtl_cm_get_chan_private(ibt_channel_hdl_t chan)
81 {
82 void *cm_private;
83
84 IBTF_DPRINTF_L3(ibtf_cm, "ibtl_cm_get_chan_private(%p)", chan);
85 mutex_enter(&chan->ch_cm_mutex);
86 cm_private = chan->ch_cm_private;
87 /* IBCM will call the release function if cm_private is non-NULL */
88 if (cm_private == NULL)
89 mutex_exit(&chan->ch_cm_mutex);
90 return (cm_private);
91 }
92
93 void
94 ibtl_cm_release_chan_private(ibt_channel_hdl_t chan)
95 {
96 mutex_exit(&chan->ch_cm_mutex);
97 }
98
99 void
100 ibtl_cm_wait_chan_private(ibt_channel_hdl_t chan)
101 {
102 mutex_enter(&chan->ch_cm_mutex);
103 if (chan->ch_cm_private != NULL)
104 cv_wait(&chan->ch_cm_cv, &chan->ch_cm_mutex);
105 mutex_exit(&chan->ch_cm_mutex);
106 delay(drv_usectohz(50000));
107 }
108
109
110 /*
111 * Function:
112 * ibtl_cm_get_chan_type
113 * Input:
114 * chan Channel Handle.
115 * Output:
116 * none.
117 * Returns:
118 * Channel transport type.
119 * Description:
120 * A helper function to get channel transport type.
121 */
122 ibt_tran_srv_t
123 ibtl_cm_get_chan_type(ibt_channel_hdl_t chan)
124 {
125 IBTF_DPRINTF_L3(ibtf_cm, "ibtl_cm_get_chan_type(%p)", chan);
126
127 return (chan->ch_qp.qp_type);
128 }
129
130 /*
131 * Function:
132 * ibtl_cm_change_service_cnt
133 * Input:
134 * ibt_hdl Client's IBT Handle.
135 * delta_num_sids The change in the number of service ids
136 * (positive for ibt_register_service() and
137 * negative fo ibt_service_deregister()).
138 */
139 void
140 ibtl_cm_change_service_cnt(ibt_clnt_hdl_t ibt_hdl, int delta_num_sids)
141 {
142 IBTF_DPRINTF_L3(ibtf_cm, "ibtl_cm_change_service_cnt(%p. %d)",
143 ibt_hdl, delta_num_sids);
144
145 mutex_enter(&ibtl_clnt_list_mutex);
146 if ((delta_num_sids < 0) && (-delta_num_sids > ibt_hdl->clnt_srv_cnt)) {
147 IBTF_DPRINTF_L2(ibtf_cm, "ibtl_cm_change_service_cnt: "
148 "ERROR: service registration counter underflow\n"
149 "current count = %d, requested delta = %d",
150 ibt_hdl->clnt_srv_cnt, delta_num_sids);
151 }
152 ibt_hdl->clnt_srv_cnt += delta_num_sids;
153 mutex_exit(&ibtl_clnt_list_mutex);
154 }
155
156
157 /*
158 * Function:
159 * ibtl_cm_get_hca_port
160 * Input:
161 * gid Source GID.
162 * hca_guid Optional source HCA GUID on which SGID is available.
163 * Ignored if zero.
164 * Output:
165 * hca_port Pointer to ibtl_cm_hca_port_t struct.
166 * Returns:
167 * IBT_SUCCESS.
168 * Description:
169 * A helper function to get HCA node GUID, Base LID, SGID Index,
170 * port number, LMC and MTU for the specified SGID.
171 * Also filling default SGID, to be used in ibmf_sa_session_open.
172 */
173 ibt_status_t
174 ibtl_cm_get_hca_port(ib_gid_t gid, ib_guid_t hca_guid,
175 ibtl_cm_hca_port_t *hca_port)
176 {
177 ibtl_hca_devinfo_t *hca_devp; /* HCA Dev Info */
178 ibt_hca_portinfo_t *portinfop;
179 uint_t ports, port;
180 uint_t i;
181 ib_gid_t *sgid;
182 static ib_gid_t fast_gid; /* fast_gid_cache data */
183 static uint8_t fast_sgid_ix;
184 static ibt_hca_portinfo_t *fast_portinfop;
185 static ib_guid_t fast_node_guid;
186 static ib_guid_t fast_port_guid;
187
188 IBTF_DPRINTF_L3(ibtf_cm, "ibtl_cm_get_hca_port(%llX:%llX, %llX)",
189 gid.gid_prefix, gid.gid_guid, hca_guid);
190
191 if ((gid.gid_prefix == 0) || (gid.gid_guid == 0)) {
192 IBTF_DPRINTF_L2(ibtf_cm, "ibtl_cm_get_hca_port: "
193 "NULL SGID specified.");
194 return (IBT_INVALID_PARAM);
195 }
196
197 mutex_enter(&ibtl_clnt_list_mutex);
198
199 if ((ibtl_fast_gid_cache_valid == B_TRUE) &&
200 (gid.gid_guid == fast_gid.gid_guid) &&
201 (gid.gid_prefix == fast_gid.gid_prefix)) {
202
203 if ((hca_guid != 0) && (hca_guid != fast_node_guid)) {
204 IBTF_DPRINTF_L3(ibtf_cm, "ibtl_cm_get_hca_port: "
205 "Mis-match hca_guid v/s sgid combination.");
206 mutex_exit(&ibtl_clnt_list_mutex);
207 return (IBT_INVALID_PARAM);
208 }
209
210 portinfop = fast_portinfop;
211 hca_port->hp_base_lid = portinfop->p_base_lid;
212 hca_port->hp_port = portinfop->p_port_num;
213 hca_port->hp_sgid_ix = fast_sgid_ix;
214 hca_port->hp_lmc = portinfop->p_lmc;
215 hca_port->hp_mtu = portinfop->p_mtu;
216 hca_port->hp_hca_guid = fast_node_guid;
217 hca_port->hp_port_guid = fast_port_guid;
218
219 mutex_exit(&ibtl_clnt_list_mutex);
220
221 return (IBT_SUCCESS);
222 }
223
224 /* If HCA GUID is specified, then lookup in that device only. */
225 if (hca_guid) {
226 hca_devp = ibtl_get_hcadevinfo(hca_guid);
227 } else {
228 hca_devp = ibtl_hca_list;
229 }
230
231 while (hca_devp != NULL) {
232
233 ports = hca_devp->hd_hca_attr->hca_nports;
234 portinfop = hca_devp->hd_portinfop;
235
236 for (port = 0; port < ports; port++, portinfop++) {
237 if (portinfop->p_linkstate != IBT_PORT_ACTIVE)
238 continue;
239 sgid = &portinfop->p_sgid_tbl[0];
240 for (i = 0; i < portinfop->p_sgid_tbl_sz; i++, sgid++) {
241 if ((gid.gid_guid != sgid->gid_guid) ||
242 (gid.gid_prefix != sgid->gid_prefix))
243 continue;
244
245 /*
246 * Found the matching GID.
247 */
248 ibtl_fast_gid_cache_valid = B_TRUE;
249 fast_gid = gid;
250 fast_portinfop = portinfop;
251 fast_node_guid = hca_port->hp_hca_guid =
252 hca_devp->hd_hca_attr->hca_node_guid;
253 fast_sgid_ix = hca_port->hp_sgid_ix = i;
254 fast_port_guid =
255 portinfop->p_sgid_tbl[0].gid_guid;
256 hca_port->hp_port_guid = fast_port_guid;
257 hca_port->hp_base_lid = portinfop->p_base_lid;
258 hca_port->hp_port = portinfop->p_port_num;
259 hca_port->hp_lmc = portinfop->p_lmc;
260 hca_port->hp_mtu = portinfop->p_mtu;
261
262 mutex_exit(&ibtl_clnt_list_mutex);
263
264 return (IBT_SUCCESS);
265 }
266 }
267
268 /* Asked to look in the specified HCA device only?. */
269 if (hca_guid)
270 break;
271
272 /* Get next in the list */
273 hca_devp = hca_devp->hd_hca_dev_link;
274 }
275
276 mutex_exit(&ibtl_clnt_list_mutex);
277
278 /* If we are here, then we failed to get a match, so return error. */
279 return (IBT_INVALID_PARAM);
280 }
281
282
283 static ibt_status_t
284 ibtl_cm_get_cnt(ibt_path_attr_t *attr, ibt_path_flags_t flags,
285 ibtl_cm_port_list_t *plistp, uint_t *count)
286 {
287 ibtl_hca_devinfo_t *hdevp;
288 ibt_hca_portinfo_t *pinfop;
289 ib_guid_t hca_guid, tmp_hca_guid = 0;
290 ib_gid_t gid;
291 uint_t pcount = 0, tmp_pcount = 0;
292 uint_t cnt = *count;
293 ibt_status_t retval = IBT_SUCCESS;
294 uint_t i, j;
295
296 *count = 0;
297
298 /* If HCA GUID is specified, then lookup in that device only. */
299 if (attr->pa_hca_guid) {
300 hdevp = ibtl_get_hcadevinfo(attr->pa_hca_guid);
301 } else {
302 hdevp = ibtl_hca_list;
303 }
304
305 while (hdevp != NULL) {
306 hca_guid = hdevp->hd_hca_attr->hca_node_guid;
307
308 if ((flags & IBT_PATH_APM) &&
309 (!(hdevp->hd_hca_attr->hca_flags &
310 IBT_HCA_AUTO_PATH_MIG))) {
311
312 IBTF_DPRINTF_L2(ibtf_cm, "ibtl_cm_get_cnt: "
313 "HCA (%llX) - APM NOT SUPPORTED ", hca_guid);
314
315 retval = IBT_APM_NOT_SUPPORTED;
316
317 if (attr->pa_hca_guid)
318 break;
319 goto search_next;
320 }
321
322 for (i = 0; i < hdevp->hd_hca_attr->hca_nports; i++) {
323
324 if ((attr->pa_hca_port_num) &&
325 (attr->pa_hca_port_num != (i + 1))) {
326 IBTF_DPRINTF_L3(ibtf_cm, "ibtl_cm_get_cnt: "
327 "Asked only on Port# %d, so skip this "
328 "port(%d)", attr->pa_hca_port_num, (i + 1));
329 continue;
330 }
331 pinfop = hdevp->hd_portinfop + i;
332
333 if (pinfop->p_linkstate != IBT_PORT_ACTIVE) {
334 retval = IBT_HCA_PORT_NOT_ACTIVE;
335 continue;
336 }
337 if (attr->pa_mtu.r_mtu) {
338 if ((attr->pa_mtu.r_selector == IBT_GT) &&
339 (attr->pa_mtu.r_mtu >= pinfop->p_mtu))
340 continue;
341 else if ((attr->pa_mtu.r_selector == IBT_EQU) &&
342 (attr->pa_mtu.r_mtu > pinfop->p_mtu))
343 continue;
344 }
345
346 if ((flags & IBT_PATH_APM) && (!attr->pa_hca_guid) &&
347 attr->pa_sgid.gid_prefix &&
348 attr->pa_sgid.gid_guid) {
349 for (j = 0; j < pinfop->p_sgid_tbl_sz; j++) {
350 gid = pinfop->p_sgid_tbl[j];
351 if (gid.gid_prefix && gid.gid_guid) {
352 if ((attr->pa_sgid.gid_prefix !=
353 gid.gid_prefix) ||
354 (attr->pa_sgid.gid_guid !=
355 gid.gid_guid)) {
356 continue;
357 } else {
358 attr->pa_hca_guid =
359 hca_guid;
360 goto got_apm_hca_info;
361 }
362 }
363 }
364 continue;
365 }
366 got_apm_hca_info:
367 for (j = 0; j < pinfop->p_sgid_tbl_sz; j++) {
368 gid = pinfop->p_sgid_tbl[j];
369 if (gid.gid_prefix && gid.gid_guid) {
370 if (!(flags & IBT_PATH_APM) &&
371 attr->pa_sgid.gid_prefix &&
372 attr->pa_sgid.gid_guid) {
373 if ((attr->pa_sgid.gid_prefix !=
374 gid.gid_prefix) ||
375 (attr->pa_sgid.gid_guid !=
376 gid.gid_guid))
377 continue;
378 }
379 pcount++;
380 if (plistp) {
381 plistp->p_hca_guid = hca_guid;
382 plistp->p_mtu = pinfop->p_mtu;
383 plistp->p_base_lid =
384 pinfop->p_base_lid;
385 plistp->p_port_num =
386 pinfop->p_port_num;
387 plistp->p_sgid_ix = j;
388 plistp->p_sgid = gid;
389 plistp->p_count = cnt;
390 if (hdevp->hd_multism)
391 plistp->p_multi |=
392 IBTL_CM_MULTI_SM;
393
394 IBTF_DPRINTF_L3(ibtf_cm,
395 "ibtl_cm_get_cnt: HCA"
396 "(%llX,%d) SGID(%llX:%llX)",
397 plistp->p_hca_guid,
398 plistp->p_port_num,
399 plistp->p_sgid.gid_prefix,
400 plistp->p_sgid.gid_guid);
401
402 plistp++;
403 }
404 }
405 }
406 }
407 /* Asked to look in the specified HCA device only?. */
408 if (attr->pa_hca_guid)
409 break;
410
411 if (flags & IBT_PATH_APM) {
412 if (pcount == 2) {
413 attr->pa_hca_guid = hca_guid;
414 break;
415 } else if (pcount == 1) {
416 if (hdevp->hd_hca_dev_link) {
417 tmp_hca_guid = hca_guid;
418 tmp_pcount = pcount;
419 pcount = 0;
420 } else if (tmp_hca_guid) {
421 attr->pa_hca_guid = tmp_hca_guid;
422 } else {
423 attr->pa_hca_guid = hca_guid;
424 }
425 } else if ((pcount == 0) && (tmp_hca_guid)) {
426 attr->pa_hca_guid = tmp_hca_guid;
427 pcount = tmp_pcount;
428 }
429 }
430 search_next:
431 hdevp = hdevp->hd_hca_dev_link;
432 }
433
434 *count = pcount;
435
436 if (pcount) {
437 retval = IBT_SUCCESS;
438 } else {
439 IBTF_DPRINTF_L2(ibtf_cm, "ibtl_cm_get_cnt: "
440 "Appropriate Source Points NOT found");
441 if (retval == IBT_SUCCESS)
442 retval = IBT_NO_HCAS_AVAILABLE;
443 }
444
445 return (retval);
446 }
447
448
449 ibt_status_t
450 ibtl_cm_get_active_plist(ibt_path_attr_t *attr, ibt_path_flags_t flags,
451 ibtl_cm_port_list_t **port_list_p)
452 {
453 ibtl_cm_port_list_t *p_listp, tmp;
454 uint_t i, j;
455 uint_t count, rcount;
456 boolean_t multi_hca = B_FALSE;
457 ibt_status_t retval = IBT_SUCCESS;
458
459 IBTF_DPRINTF_L3(ibtf_cm, "ibtl_cm_get_active_plist(%p, %X)",
460 attr, flags);
461
462 get_plist_start:
463 *port_list_p = NULL;
464
465 /* Get "number of active src points" so that we can allocate memory. */
466 mutex_enter(&ibtl_clnt_list_mutex);
467 retval = ibtl_cm_get_cnt(attr, flags, NULL, &count);
468 mutex_exit(&ibtl_clnt_list_mutex);
469
470 IBTF_DPRINTF_L3(ibtf_cm, "ibtl_cm_get_active_plist: Found %d SrcPoint",
471 count);
472 if (retval != IBT_SUCCESS)
473 return (retval);
474
475 /* Allocate Memory to hold Src Point information. */
476 p_listp = kmem_zalloc(count * sizeof (ibtl_cm_port_list_t), KM_SLEEP);
477
478 /*
479 * Verify that the count we got previously is still valid, as we had
480 * dropped mutex to allocate memory. If not, restart the process.
481 */
482 mutex_enter(&ibtl_clnt_list_mutex);
483 retval = ibtl_cm_get_cnt(attr, flags, NULL, &rcount);
484 if (retval != IBT_SUCCESS) {
485 mutex_exit(&ibtl_clnt_list_mutex);
486 kmem_free(p_listp, count * sizeof (ibtl_cm_port_list_t));
487 return (retval);
488 } else if (rcount != count) {
489 mutex_exit(&ibtl_clnt_list_mutex);
490 kmem_free(p_listp, count * sizeof (ibtl_cm_port_list_t));
491 goto get_plist_start;
492 }
493
494 *port_list_p = p_listp;
495 /*
496 * Src count hasn't changed, still holding the lock fill-in the
497 * required source point information.
498 */
499 retval = ibtl_cm_get_cnt(attr, flags, p_listp, &rcount);
500 mutex_exit(&ibtl_clnt_list_mutex);
501 if (retval != IBT_SUCCESS) {
502 kmem_free(p_listp, count * sizeof (ibtl_cm_port_list_t));
503 *port_list_p = NULL;
504 return (retval);
505 }
506
507 p_listp = *port_list_p;
508
509 for (i = 0; i < count - 1; i++) {
510 for (j = 0; j < count - 1 - i; j++) {
511 if (p_listp[j].p_hca_guid != p_listp[j+1].p_hca_guid) {
512 multi_hca = B_TRUE;
513 break;
514 }
515 }
516 if (multi_hca == B_TRUE)
517 break;
518 }
519
520 if (multi_hca == B_TRUE)
521 for (i = 0; i < count; i++)
522 p_listp[i].p_multi |= IBTL_CM_MULTI_HCA;
523
524 /*
525 * Sort (bubble sort) the list based on MTU quality (higher on top).
526 * Sorting is only performed, if IBT_PATH_AVAIL is set.
527 */
528 if (((attr->pa_mtu.r_selector == IBT_GT) || (flags & IBT_PATH_AVAIL)) &&
529 (!(flags & IBT_PATH_APM))) {
530 for (i = 0; i < count - 1; i++) {
531 for (j = 0; j < count - 1 - i; j++) {
532 if (p_listp[j].p_mtu < p_listp[j+1].p_mtu) {
533 tmp = p_listp[j];
534 p_listp[j] = p_listp[j+1];
535 p_listp[j+1] = tmp;
536 }
537 }
538 }
539 }
540
541 if ((p_listp->p_multi & IBTL_CM_MULTI_HCA) &&
542 (flags & IBT_PATH_AVAIL) && (!(flags & IBT_PATH_APM))) {
543 /* Avoid having same HCA next to each other in the list. */
544 for (i = 0; i < count - 1; i++) {
545 for (j = 0; j < (count - 1 - i); j++) {
546 if ((p_listp[j].p_hca_guid ==
547 p_listp[j+1].p_hca_guid) &&
548 (j+2 < count)) {
549 tmp = p_listp[j+1];
550 p_listp[j+1] = p_listp[j+2];
551 p_listp[j+2] = tmp;
552 }
553 }
554 }
555 }
556
557 /*
558 * If SGID is specified, then make sure that SGID info is first
559 * in the array.
560 */
561 if (attr->pa_sgid.gid_guid && (p_listp->p_count > 1) &&
562 (p_listp[0].p_sgid.gid_guid != attr->pa_sgid.gid_guid)) {
563 for (i = 1; i < count; i++) {
564 if (p_listp[i].p_sgid.gid_guid ==
565 attr->pa_sgid.gid_guid) {
566 tmp = p_listp[i];
567 p_listp[i] = p_listp[0];
568 p_listp[0] = tmp;
569 }
570 }
571 }
572
573 IBTF_DPRINTF_L3(ibtf_cm, "ibtl_cm_get_active_plist: "
574 "Returned <%d> entries @0x%p", count, *port_list_p);
575
576 return (retval);
577 }
578
579
580 void
581 ibtl_cm_free_active_plist(ibtl_cm_port_list_t *plist)
582 {
583 int count;
584
585 IBTF_DPRINTF_L3(ibtf_cm, "ibtl_cm_free_active_plist(%p)", plist);
586
587 if (plist != NULL) {
588 count = plist->p_count;
589 kmem_free(plist, count * sizeof (ibtl_cm_port_list_t));
590 }
591 }
592
593 /*
594 * Function:
595 * ibtl_cm_get_1st_full_pkey_ix
596 * Input:
597 * hca_guid HCA GUID.
598 * port Port Number.
599 * Output:
600 * None.
601 * Returns:
602 * P_Key Index of the first full member available from the P_Key table
603 * of the specified HCA<->Port.
604 * Description:
605 * A helper function to get P_Key Index of the first full member P_Key
606 * available on the specified HCA and Port combination.
607 */
608 uint16_t
609 ibtl_cm_get_1st_full_pkey_ix(ib_guid_t hca_guid, uint8_t port)
610 {
611 ibtl_hca_devinfo_t *hca_devp; /* HCA Dev Info */
612 uint16_t pkey_ix = 0;
613
614 IBTF_DPRINTF_L3(ibtf_cm, "ibtl_cm_get_1st_full_pkey_ix(%llX, %d)",
615 hca_guid, port);
616
617 mutex_enter(&ibtl_clnt_list_mutex);
618 hca_devp = ibtl_get_hcadevinfo(hca_guid);
619
620 if ((hca_devp != NULL) && (port <= hca_devp->hd_hca_attr->hca_nports) &&
621 (port != 0)) {
622 pkey_ix = hca_devp->hd_portinfop[port - 1].p_def_pkey_ix;
623 } else {
624 IBTF_DPRINTF_L2(ibtf_cm, "ibtl_cm_get_1st_full_pkey_ix: "
625 "Invalid HCA (%llX), Port (%d) specified.", hca_guid, port);
626 }
627 mutex_exit(&ibtl_clnt_list_mutex);
628
629 return (pkey_ix);
630 }
631
632
633 ibt_status_t
634 ibtl_cm_get_local_comp_gids(ib_guid_t hca_guid, ib_gid_t gid, ib_gid_t **gids_p,
635 uint_t *num_gids_p)
636 {
637 ibtl_hca_devinfo_t *hdevp; /* HCA Dev Info */
638 ibt_hca_portinfo_t *pinfop;
639 ib_gid_t sgid;
640 ib_gid_t *gidp = NULL;
641 int i, j, k;
642 int count = 0;
643 int gid_specified;
644
645 IBTF_DPRINTF_L3(ibtf_cm, "ibtl_cm_get_local_comp_gids(%llX, %llX:%llX)",
646 hca_guid, gid.gid_prefix, gid.gid_guid);
647
648 mutex_enter(&ibtl_clnt_list_mutex);
649 hdevp = ibtl_get_hcadevinfo(hca_guid);
650
651 if (hdevp == NULL) {
652 IBTF_DPRINTF_L3(ibtf_cm, "ibtl_cm_get_local_comp_gids: ",
653 "NO HCA (%llX) availble", hca_guid);
654 mutex_exit(&ibtl_clnt_list_mutex);
655 return (IBT_NO_HCAS_AVAILABLE);
656 }
657
658 if (gid.gid_prefix && gid.gid_guid)
659 gid_specified = 1;
660 else
661 gid_specified = 0;
662
663 for (i = 0; i < hdevp->hd_hca_attr->hca_nports; i++) {
664 pinfop = hdevp->hd_portinfop + i;
665
666 if (pinfop->p_linkstate != IBT_PORT_ACTIVE)
667 continue;
668
669 for (j = 0; j < pinfop->p_sgid_tbl_sz; j++) {
670 sgid = pinfop->p_sgid_tbl[j];
671 if (sgid.gid_prefix && sgid.gid_guid) {
672 if (gid_specified &&
673 ((gid.gid_prefix == sgid.gid_prefix) &&
674 (gid.gid_guid == sgid.gid_guid))) {
675 /*
676 * Don't return the input specified
677 * GID
678 */
679 continue;
680 }
681 count++;
682 }
683 }
684 }
685
686 if (count == 0) {
687 IBTF_DPRINTF_L2(ibtf_cm, "ibtl_cm_get_local_comp_gids: "
688 "Companion GIDs not available");
689 mutex_exit(&ibtl_clnt_list_mutex);
690 return (IBT_GIDS_NOT_FOUND);
691 }
692
693 gidp = kmem_zalloc(count * sizeof (ib_gid_t), KM_SLEEP);
694 *num_gids_p = count;
695 *gids_p = gidp;
696 k = 0;
697
698 for (i = 0; i < hdevp->hd_hca_attr->hca_nports; i++) {
699 pinfop = hdevp->hd_portinfop + i;
700
701 if (pinfop->p_linkstate != IBT_PORT_ACTIVE)
702 continue;
703
704 for (j = 0; j < pinfop->p_sgid_tbl_sz; j++) {
705 sgid = pinfop->p_sgid_tbl[j];
706 if (sgid.gid_prefix && sgid.gid_guid) {
707 if (gid_specified &&
708 ((gid.gid_prefix == sgid.gid_prefix) &&
709 (gid.gid_guid == sgid.gid_guid)))
710 continue;
711
712 gidp[k].gid_prefix = sgid.gid_prefix;
713 gidp[k].gid_guid = sgid.gid_guid;
714
715 IBTF_DPRINTF_L3(ibtf_cm,
716 "ibtl_cm_get_local_comp_gids: GID[%d]="
717 "%llX:%llX", k, gidp[k].gid_prefix,
718 gidp[k].gid_guid);
719 k++;
720 if (k == count)
721 break;
722 }
723 }
724 if (k == count)
725 break;
726 }
727 mutex_exit(&ibtl_clnt_list_mutex);
728
729 return (IBT_SUCCESS);
730 }
731
732
733 int
734 ibtl_cm_is_multi_sm(ib_guid_t hca_guid)
735 {
736 ibtl_hca_devinfo_t *hdevp; /* HCA Dev Info */
737 uint_t multi_sm;
738
739 mutex_enter(&ibtl_clnt_list_mutex);
740 hdevp = ibtl_get_hcadevinfo(hca_guid);
741 if (hdevp == NULL) {
742 IBTF_DPRINTF_L2(ibtf_cm, "ibtl_cm_is_multi_sm: NO HCA (%llX) "
743 "availble", hca_guid);
744 mutex_exit(&ibtl_clnt_list_mutex);
745 return (-1);
746 }
747 multi_sm = hdevp->hd_multism;
748 mutex_exit(&ibtl_clnt_list_mutex);
749
750 IBTF_DPRINTF_L3(ibtf_cm, "ibtl_cm_is_multi_sm(%llX): %d", hca_guid,
751 multi_sm);
752
753 return (multi_sm);
754 }
755
756 char *
757 ibtl_cm_get_clnt_name(ibt_clnt_hdl_t ibt_hdl)
758 {
759 if (ibt_hdl)
760 return (ibt_hdl->clnt_name);
761 else
762 return (NULL);
763 }