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