1 /*
2 * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
3 * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
4 * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
5 *
6 * This software is available to you under a choice of one of two
7 * licenses. You may choose to be licensed under the terms of the GNU
8 * General Public License (GPL) Version 2, available from the file
9 * COPYING in the main directory of this source tree, or the
10 * OpenIB.org BSD license below:
11 *
12 * Redistribution and use in source and binary forms, with or
13 * without modification, are permitted provided that the following
14 * conditions are met:
15 *
16 * - Redistributions of source code must retain the above
17 * copyright notice, this list of conditions and the following
18 * disclaimer.
19 *
20 * - Redistributions in binary form must reproduce the above
21 * copyright notice, this list of conditions and the following
22 * disclaimer in the documentation and/or other materials
23 * provided with the distribution.
24 *
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32 * SOFTWARE.
33 *
34 */
35
36 #if HAVE_CONFIG_H
37 # include <config.h>
38 #endif /* HAVE_CONFIG_H */
39
40 #if defined(OSM_VENDOR_INTF_MTL) | defined(OSM_VENDOR_INTF_TS)
41 #undef IN
42 #undef OUT
43 #include <vendor/osm_vendor_api.h>
44 #include <opensm/osm_log.h>
45 #include <stdlib.h>
46 #include <stdio.h>
47 #include <sys/types.h>
48 #include <dirent.h>
49 #include <stdio.h>
50 #include <sys/stat.h>
51 #include <stdint.h>
52 #include <fcntl.h>
53
54 /********************************************************************************
55 *
56 * Provides the functionality for selecting an HCA Port and Obtaining it's guid.
57 * This version is based on /proc/infiniband file system. So it is limited to
58 * The gen1 of openib.org stack.
59 *
60 ********************************************************************************/
61
62 typedef struct _osm_ca_info {
63 ib_net64_t guid;
64 size_t attr_size;
65 ib_ca_attr_t *p_attr;
66
67 } osm_ca_info_t;
68
69 /**********************************************************************
70 * Returns a pointer to the port attribute of the specified port
71 * owned by this CA.
72 ************************************************************************/
__osm_ca_info_get_port_attr_ptr(IN const osm_ca_info_t * const p_ca_info,IN const uint8_t index)73 static ib_port_attr_t *__osm_ca_info_get_port_attr_ptr(IN const osm_ca_info_t *
74 const p_ca_info,
75 IN const uint8_t index)
76 {
77 return (&p_ca_info->p_attr->p_port_attr[index]);
78 }
79
80 /**********************************************************************
81 * Obtain the number of local CAs by scanning /proc/infiniband/core
82 **********************************************************************/
__hca_pfs_get_num_cas()83 int __hca_pfs_get_num_cas()
84 {
85 int num_cas = 0;
86 DIR *dp;
87 struct dirent *ep;
88
89 dp = opendir("/proc/infiniband/core");
90 if (dp != NULL) {
91 while ((ep = readdir(dp))) {
92 /* CAs are directories with the format ca[1-9][0-9]* */
93 if ((ep->d_type == DT_DIR)
94 && !strncmp(ep->d_name, "ca", 2)) {
95 num_cas++;
96 }
97 }
98 closedir(dp);
99 }
100 return num_cas;
101 }
102
103 /*
104 name: InfiniHost0
105 provider: tavor
106 node GUID: 0002:c900:0120:3470
107 ports: 2
108 vendor ID: 0x2c9
109 device ID: 0x5a44
110 HW revision: 0xa1
111 FW revision: 0x300020080
112 */
113 typedef struct _pfs_ca_info {
114 char name[32];
115 char provider[32];
116 uint64_t guid;
117 uint8_t num_ports;
118 uint32_t vend_id;
119 uint16_t dev_id;
120 uint16_t rev_id;
121 uint64_t fw_rev;
122 } pfs_ca_info_t;
123
124 /**********************************************************************
125 * Parse the CA Info file available in /proc/infiniband/core/caN/info
126 **********************************************************************/
127 static ib_api_status_t
__parse_ca_info_file(IN osm_vendor_t * const p_vend,IN uint32_t idx,OUT pfs_ca_info_t * pfs_ca_info)128 __parse_ca_info_file(IN osm_vendor_t * const p_vend,
129 IN uint32_t idx, OUT pfs_ca_info_t * pfs_ca_info)
130 {
131 ib_api_status_t status = IB_ERROR;
132 int info_file;
133 char file_name[256];
134 char file_buffer[3200];
135 char *p_ch;
136 int g1, g2, g3, g4;
137 int num_ports;
138 uint32_t len;
139
140 OSM_LOG_ENTER(p_vend->p_log);
141
142 osm_log(p_vend->p_log, OSM_LOG_DEBUG,
143 "__parse_ca_info_file: " "Querying CA %d.\n", idx);
144
145 /* we use the proc file system so we must be able to open the info file .. */
146 sprintf(file_name, "/proc/infiniband/core/ca%d/info", idx);
147 info_file = open(file_name, O_RDONLY);
148 if (!info_file) {
149 osm_log(p_vend->p_log, OSM_LOG_ERROR,
150 "__parse_ca_info_file: ERR 5205: "
151 "Fail to open HCA:%d info file:(%s).\n", idx,
152 file_name);
153 goto Exit;
154 }
155
156 /* read in the file */
157 len = read(info_file, file_buffer, 3200);
158 close(info_file);
159 file_buffer[len] = '\0';
160
161 /*
162 parse the file ...
163 name: InfiniHost0
164 provider: tavor
165 node GUID: 0002:c900:0120:3470
166 ports: 2
167 vendor ID: 0x2c9
168 device ID: 0x5a44
169 HW revision: 0xa1
170 FW revision: 0x300020080
171 */
172 if (!(p_ch = strstr(file_buffer, "name:"))) {
173 osm_log(p_vend->p_log, OSM_LOG_ERROR,
174 "__parse_ca_info_file: ERR 5206: "
175 "Fail to obtain HCA name. In info file:(%s).\n",
176 file_buffer);
177 goto Exit;
178 }
179 if (sscanf(p_ch, "name: %s", pfs_ca_info->name) != 1) {
180 osm_log(p_vend->p_log, OSM_LOG_ERROR,
181 "__parse_ca_info_file: ERR 5207: "
182 "Fail to parse name in info file:(%s).\n", p_ch);
183 goto Exit;
184 }
185
186 /* get the guid of the HCA */
187 if (!(p_ch = strstr(file_buffer, "node GUID:"))) {
188 osm_log(p_vend->p_log, OSM_LOG_ERROR,
189 "__parse_ca_info_file: ERR 5208: "
190 "Fail to obtain GUID in info file:(%s).\n",
191 file_buffer);
192 goto Exit;
193 }
194 if (sscanf(p_ch, "node GUID: %x:%x:%x:%x", &g1, &g2, &g3, &g4) != 4) {
195 osm_log(p_vend->p_log, OSM_LOG_ERROR,
196 "__parse_ca_info_file: ERR 5209: "
197 "Fail to parse GUID in info file:(%s).\n", p_ch);
198 goto Exit;
199 }
200 pfs_ca_info->guid = (uint64_t) g1 << 48 | (uint64_t) g1 << 32
201 | (uint64_t) g1 << 16 | (uint64_t) g3;
202
203 /* obtain number of ports */
204 if (!(p_ch = strstr(file_buffer, "ports:"))) {
205 osm_log(p_vend->p_log, OSM_LOG_ERROR,
206 "__parse_ca_info_file: ERR 5210: "
207 "Fail to obtain number of ports in info file:(%s).\n",
208 file_buffer);
209 goto Exit;
210 }
211 if (sscanf(p_ch, "ports: %d", &num_ports) != 1) {
212 osm_log(p_vend->p_log, OSM_LOG_ERROR,
213 "__parse_ca_info_file: ERR 5211: "
214 "Fail to parse num ports in info file:(%s).\n", p_ch);
215 goto Exit;
216 }
217 pfs_ca_info->num_ports = num_ports;
218
219 osm_log(p_vend->p_log, OSM_LOG_DEBUG,
220 "__parse_ca_info_file: "
221 "CA1 = name:%s guid:0x%016llx ports:%d\n",
222 pfs_ca_info->name, pfs_ca_info->guid, pfs_ca_info->num_ports);
223
224 status = IB_SUCCESS;
225 Exit:
226 OSM_LOG_EXIT(p_vend->p_log);
227 return status;
228 }
229
230 /*
231 state: ACTIVE
232 LID: 0x0001
233 LMC: 0x0000
234 SM LID: 0x0001
235 SM SL: 0x0000
236 Capabilities: IsSM
237 IsTrapSupported
238 IsAutomaticMigrationSupported
239 IsSLMappingSupported
240 IsLEDInfoSupported
241 IsSystemImageGUIDSupported
242 IsVendorClassSupported
243 IsCapabilityMaskNoticeSupported
244 */
245 typedef struct _pfs_port_info {
246 uint8_t state;
247 uint16_t lid;
248 uint8_t lmc;
249 uint16_t sm_lid;
250 uint8_t sm_sl;
251 } pfs_port_info_t;
252
253 /**********************************************************************
254 * Parse the Port Info file available in /proc/infiniband/core/caN/portM/info
255 * Port num is 1..N
256 **********************************************************************/
257 static ib_api_status_t
__parse_port_info_file(IN osm_vendor_t * const p_vend,IN uint32_t hca_idx,IN uint8_t port_num,OUT pfs_port_info_t * pfs_port_info)258 __parse_port_info_file(IN osm_vendor_t * const p_vend,
259 IN uint32_t hca_idx,
260 IN uint8_t port_num, OUT pfs_port_info_t * pfs_port_info)
261 {
262 ib_api_status_t status = IB_ERROR;
263 int info_file;
264 char file_name[256];
265 char file_buffer[3200];
266 char state[12];
267 char *p_ch;
268 int lid, sm_lid, lmc, sm_sl;
269 uint32_t len;
270
271 OSM_LOG_ENTER(p_vend->p_log);
272
273 osm_log(p_vend->p_log, OSM_LOG_DEBUG,
274 "__parse_port_info_file: "
275 "Parsing Proc File System Port Info CA %d Port %d.\n", hca_idx,
276 port_num);
277
278 /* we use the proc file system so we must be able to open the info file .. */
279 sprintf(file_name, "/proc/infiniband/core/ca%d/port%d/info", hca_idx,
280 port_num);
281 info_file = open(file_name, O_RDONLY);
282 if (!info_file) {
283 osm_log(p_vend->p_log, OSM_LOG_ERROR,
284 "__parse_port_info_file: ERR 5212: "
285 "Fail to open HCA:%d Port:%d info file:(%s).\n",
286 hca_idx, port_num, file_name);
287 goto Exit;
288 }
289
290 /* read in the file */
291 len = read(info_file, file_buffer, 3200);
292 close(info_file);
293 file_buffer[len] = '\0';
294
295 /*
296 parse the file ...
297 state: ACTIVE
298 LID: 0x0001
299 LMC: 0x0000
300 SM LID: 0x0001
301 SM SL: 0x0000
302 ...
303 */
304 if (!(p_ch = strstr(file_buffer, "state:"))) {
305 osm_log(p_vend->p_log, OSM_LOG_ERROR,
306 "__parse_port_info_file: ERR 5213: "
307 "Fail to obtain port state. In info file:(%s).\n",
308 file_buffer);
309 goto Exit;
310 }
311 if (sscanf(p_ch, "state: %s", state) != 1) {
312 osm_log(p_vend->p_log, OSM_LOG_ERROR,
313 "__parse_port_info_file: ERR 5214: "
314 "Fail to parse state from info file:(%s).\n", p_ch);
315 goto Exit;
316 }
317
318 if (!strcmp(state, "ACTIVE"))
319 pfs_port_info->state = IB_LINK_ACTIVE;
320 else if (!strcmp(state, "DOWN"))
321 pfs_port_info->state = IB_LINK_DOWN;
322 else if (!strcmp(state, "INIT"))
323 pfs_port_info->state = IB_LINK_INIT;
324 else if (!strcmp(state, "ARMED"))
325 pfs_port_info->state = IB_LINK_ARMED;
326 else
327 pfs_port_info->state = 0;
328
329 /* get lid */
330 if (!(p_ch = strstr(file_buffer, "LID:"))) {
331 osm_log(p_vend->p_log, OSM_LOG_ERROR,
332 "__parse_port_info_file: ERR 5215: "
333 "Fail to obtain port lid. In info file:(%s).\n",
334 file_buffer);
335 goto Exit;
336 }
337 if (sscanf(p_ch, "LID: %x", &lid) != 1) {
338 osm_log(p_vend->p_log, OSM_LOG_ERROR,
339 "__parse_port_info_file: ERR 5216: "
340 "Fail to parse lid from info file:(%s).\n", p_ch);
341 goto Exit;
342 }
343 pfs_port_info->lid = lid;
344 /* get LMC */
345 if (!(p_ch = strstr(file_buffer, "LMC:"))) {
346 osm_log(p_vend->p_log, OSM_LOG_ERROR,
347 "__parse_port_info_file: ERR 5217: "
348 "Fail to obtain port LMC. In info file:(%s).\n",
349 file_buffer);
350 goto Exit;
351 }
352 if (sscanf(p_ch, "LMC: %x", &lmc) != 1) {
353 osm_log(p_vend->p_log, OSM_LOG_ERROR,
354 "__parse_port_info_file: ERR 5218: "
355 "Fail to parse LMC from info file:(%s).\n", p_ch);
356 goto Exit;
357 }
358 pfs_port_info->lmc = lmc;
359
360 /* get SM LID */
361 if (!(p_ch = strstr(file_buffer, "SM LID:"))) {
362 osm_log(p_vend->p_log, OSM_LOG_ERROR,
363 "__parse_port_info_file: ERR 5219: "
364 "Fail to obtain port SM LID. In info file:(%s).\n",
365 file_buffer);
366 goto Exit;
367 }
368 if (sscanf(p_ch, "SM LID: %x", &sm_lid) != 1) {
369 osm_log(p_vend->p_log, OSM_LOG_ERROR,
370 "__parse_port_info_file: ERR 5220: "
371 "Fail to parse SM LID from info file:(%s).\n", p_ch);
372 goto Exit;
373 }
374 pfs_port_info->sm_lid = sm_lid;
375
376 /* get SM LID */
377 if (!(p_ch = strstr(file_buffer, "SM SL:"))) {
378 osm_log(p_vend->p_log, OSM_LOG_ERROR,
379 "__parse_port_info_file: ERR 5221: "
380 "Fail to obtain port SM SL. In info file:(%s).\n",
381 file_buffer);
382 goto Exit;
383 }
384 if (sscanf(p_ch, "SM SL: %x", &sm_sl) != 1) {
385 osm_log(p_vend->p_log, OSM_LOG_ERROR,
386 "__parse_port_info_file: ERR 5222: "
387 "Fail to parse SM SL from info file:(%s).\n", p_ch);
388 goto Exit;
389 }
390 pfs_port_info->sm_sl = sm_sl;
391 osm_log(p_vend->p_log, OSM_LOG_DEBUG,
392 "__parse_port_info_file: "
393 "Obtained Port:%d = state:%d, lid:0x%04X, lmc:%d, sm_lid:0x%04X, sm_sl:%d\n",
394 port_num, pfs_port_info->state, pfs_port_info->lid,
395 pfs_port_info->lmc, pfs_port_info->sm_lid,
396 pfs_port_info->sm_sl);
397
398 status = IB_SUCCESS;
399 Exit:
400 OSM_LOG_EXIT(p_vend->p_log);
401 return status;
402 }
403
404 /**********************************************************************
405 * Parse the port guid_tbl file to obtain the port guid.
406 * File format is:
407 * [ 0] fe80:0000:0000:0000:0002:c900:0120:3472
408 **********************************************************************/
409 static ib_api_status_t
__get_port_guid_from_port_gid_tbl(IN osm_vendor_t * const p_vend,IN uint32_t hca_idx,IN uint8_t port_num,OUT uint64_t * port_guid)410 __get_port_guid_from_port_gid_tbl(IN osm_vendor_t * const p_vend,
411 IN uint32_t hca_idx,
412 IN uint8_t port_num, OUT uint64_t * port_guid)
413 {
414 ib_api_status_t status = IB_ERROR;
415 int info_file;
416 char file_name[256];
417 char file_buffer[3200];
418 char *p_ch;
419 int g[8];
420 uint32_t len;
421
422 OSM_LOG_ENTER(p_vend->p_log);
423
424 osm_log(p_vend->p_log, OSM_LOG_DEBUG,
425 "__get_port_guid_from_port_gid_tbl: "
426 "Parsing Proc File System Port Guid Table CA %d Port %d.\n",
427 hca_idx, port_num);
428
429 /* we use the proc file system so we must be able to open the info file .. */
430 sprintf(file_name, "/proc/infiniband/core/ca%d/port%d/gid_table",
431 hca_idx, port_num);
432 info_file = open(file_name, O_RDONLY);
433 if (!info_file) {
434 osm_log(p_vend->p_log, OSM_LOG_ERROR,
435 "__get_port_guid_from_port_gid_tbl: ERR 5223: "
436 "Fail to open HCA:%d Port:%d gid_table file:(%s).\n",
437 hca_idx, port_num, file_name);
438 goto Exit;
439 }
440
441 /* read in the file */
442 len = read(info_file, file_buffer, 3200);
443 close(info_file);
444 file_buffer[len] = '\0';
445
446 /*
447 parse the file ...
448 [ 0] fe80:0000:0000:0000:0002:c900:0120:3472
449 ...
450 */
451 if (!(p_ch = strstr(file_buffer, "[ 0]"))) {
452 osm_log(p_vend->p_log, OSM_LOG_ERROR,
453 "__get_port_guid_from_port_gid_tbl: ERR 5224: "
454 "Fail to obtain first gid index. In gid_table file:(%s).\n",
455 file_buffer);
456 goto Exit;
457 }
458 if (sscanf(p_ch + 6, "%x:%x:%x:%x:%x:%x:%x:%x",
459 &g[7], &g[6], &g[5], &g[4], &g[3], &g[2], &g[1], &g[0]) != 8)
460 {
461 osm_log(p_vend->p_log, OSM_LOG_ERROR,
462 "__get_port_guid_from_port_gid_tbl: ERR 5225: "
463 "Fail to parse gid from gid_table file:(%s).\n", p_ch);
464 goto Exit;
465 }
466
467 *port_guid =
468 (uint64_t) g[3] << 48 | (uint64_t) g[2] << 32 | (uint64_t) g[1] <<
469 16 | g[0];
470 status = IB_SUCCESS;
471 Exit:
472 OSM_LOG_EXIT(p_vend->p_log);
473 return status;
474 }
475
476 /**********************************************************************
477 * Initialize an Info Struct for the Given HCA by its index 1..N
478 **********************************************************************/
479 static ib_api_status_t
__osm_ca_info_init(IN osm_vendor_t * const p_vend,IN uint32_t const idx,OUT osm_ca_info_t * const p_ca_info)480 __osm_ca_info_init(IN osm_vendor_t * const p_vend,
481 IN uint32_t const idx, OUT osm_ca_info_t * const p_ca_info)
482 {
483 ib_api_status_t status = IB_ERROR;
484 uint8_t port_num;
485 uint64_t port_guid;
486
487 pfs_ca_info_t pfs_ca_info;
488
489 OSM_LOG_ENTER(p_vend->p_log);
490
491 /* parse the CA info file */
492 if (__parse_ca_info_file(p_vend, idx, &pfs_ca_info) != IB_SUCCESS)
493 goto Exit;
494
495 p_ca_info->guid = cl_hton64(pfs_ca_info.guid);
496
497 /* set size of attributes and allocate them */
498 p_ca_info->attr_size = 1;
499 p_ca_info->p_attr = (ib_ca_attr_t *) malloc(sizeof(ib_ca_attr_t));
500
501 p_ca_info->p_attr->ca_guid = p_ca_info->guid;
502 p_ca_info->p_attr->num_ports = pfs_ca_info.num_ports;
503
504 /* now obtain the attributes of the ports */
505 p_ca_info->p_attr->p_port_attr =
506 (ib_port_attr_t *) malloc(pfs_ca_info.num_ports *
507 sizeof(ib_port_attr_t));
508
509 /* get all the ports info */
510 for (port_num = 1; port_num <= pfs_ca_info.num_ports; port_num++) {
511 pfs_port_info_t pfs_port_info;
512 /* query the port attributes */
513 if (__parse_port_info_file
514 (p_vend, idx, port_num, &pfs_port_info)) {
515 osm_log(p_vend->p_log, OSM_LOG_ERROR,
516 "__osm_ca_info_init: ERR 5226: "
517 "Fail to get HCA:%d Port:%d Attributes.\n", idx,
518 port_num);
519 goto Exit;
520 }
521
522 /* HACK: the lids should have been converted to network but the rest of the code
523 is wrong and provdes them as is (host order) - so we stick with it. */
524 p_ca_info->p_attr->p_port_attr[port_num - 1].lid =
525 pfs_port_info.lid;
526 p_ca_info->p_attr->p_port_attr[port_num - 1].link_state =
527 pfs_port_info.state;
528 p_ca_info->p_attr->p_port_attr[port_num - 1].sm_lid =
529 pfs_port_info.sm_lid;
530
531 /* get the port guid */
532 if (__get_port_guid_from_port_gid_tbl
533 (p_vend, idx, port_num, &port_guid)) {
534 osm_log(p_vend->p_log, OSM_LOG_ERROR,
535 "__osm_ca_info_init: ERR 5227: "
536 "Fail to get HCA:%d Port:%d Guid.\n", idx,
537 port_num);
538 goto Exit;
539 }
540 p_ca_info->p_attr->p_port_attr[port_num - 1].port_guid =
541 cl_hton64(port_guid);
542 }
543
544 status = IB_SUCCESS;
545 Exit:
546 OSM_LOG_EXIT(p_vend->p_log);
547 return (status);
548 }
549
550 void
osm_ca_info_destroy(IN osm_vendor_t * const p_vend,IN osm_ca_info_t * const p_ca_info,IN uint8_t num_ca)551 osm_ca_info_destroy(IN osm_vendor_t * const p_vend,
552 IN osm_ca_info_t * const p_ca_info, IN uint8_t num_ca)
553 {
554 osm_ca_info_t *p_ca;
555 uint8_t i;
556
557 OSM_LOG_ENTER(p_vend->p_log);
558
559 for (i = 0; i < num_ca; i++) {
560 p_ca = &p_ca_info[i];
561
562 if (NULL != p_ca->p_attr) {
563 if (0 != p_ca->p_attr->num_ports) {
564 free(p_ca->p_attr->p_port_attr);
565 }
566
567 free(p_ca->p_attr);
568 }
569 }
570
571 free(p_ca_info);
572
573 OSM_LOG_EXIT(p_vend->p_log);
574 }
575
576 /**********************************************************************
577 * Fill in the array of port_attr with all available ports on ALL the
578 * avilable CAs on this machine.
579 **********************************************************************/
580 ib_api_status_t
osm_vendor_get_all_port_attr(IN osm_vendor_t * const p_vend,IN ib_port_attr_t * const p_attr_array,IN uint32_t * const p_num_ports)581 osm_vendor_get_all_port_attr(IN osm_vendor_t * const p_vend,
582 IN ib_port_attr_t * const p_attr_array,
583 IN uint32_t * const p_num_ports)
584 {
585 ib_api_status_t status = IB_SUCCESS;
586
587 uint32_t caIdx;
588 uint32_t ca_count = 0;
589 uint32_t port_count = 0;
590 uint8_t port_num;
591 uint32_t total_ports = 0;
592 osm_ca_info_t *p_ca_infos = NULL;
593 uint32_t attr_array_sz = *p_num_ports;
594
595 OSM_LOG_ENTER(p_vend->p_log);
596
597 CL_ASSERT(p_vend);
598
599 /* determine the number of CA's */
600 ca_count = __hca_pfs_get_num_cas();
601 if (!ca_count) {
602 osm_log(p_vend->p_log, OSM_LOG_ERROR,
603 "osm_vendor_get_all_port_attr: ERR 5228: "
604 "Fail to get Any CA Ids.\n");
605 goto Exit;
606 }
607
608 /* Allocate an array big enough to hold the ca info objects */
609 p_ca_infos = malloc(ca_count * sizeof(osm_ca_info_t));
610 if (p_ca_infos == NULL) {
611 osm_log(p_vend->p_log, OSM_LOG_ERROR,
612 "osm_vendor_get_all_port_attr: ERR 5229: "
613 "Unable to allocate CA information array.\n");
614 goto Exit;
615 }
616
617 memset(p_ca_infos, 0, ca_count * sizeof(osm_ca_info_t));
618
619 /*
620 * For each CA, retrieve the CA info attributes
621 */
622 for (caIdx = 1; caIdx <= ca_count; caIdx++) {
623 status =
624 __osm_ca_info_init(p_vend, caIdx, &p_ca_infos[caIdx - 1]);
625 if (status != IB_SUCCESS) {
626 osm_log(p_vend->p_log, OSM_LOG_ERROR,
627 "osm_vendor_get_all_port_attr: ERR 5230: "
628 "Unable to initialize CA Info object (%s).\n",
629 ib_get_err_str(status));
630 goto Exit;
631 }
632 total_ports += p_ca_infos[caIdx - 1].p_attr->num_ports;
633 }
634
635 *p_num_ports = total_ports;
636 osm_log(p_vend->p_log, OSM_LOG_DEBUG,
637 "osm_vendor_get_all_port_attr: total ports:%u \n", total_ports);
638
639 /*
640 * If the user supplied enough storage, return the port guids,
641 * otherwise, return the appropriate error.
642 */
643 if (attr_array_sz >= total_ports) {
644 for (caIdx = 1; caIdx <= ca_count; caIdx++) {
645 uint32_t num_ports;
646
647 num_ports = p_ca_infos[caIdx - 1].p_attr->num_ports;
648
649 for (port_num = 0; port_num < num_ports; port_num++) {
650 p_attr_array[port_count] =
651 *__osm_ca_info_get_port_attr_ptr(&p_ca_infos
652 [caIdx -
653 1],
654 port_num);
655 port_count++;
656 }
657 }
658 } else {
659 status = IB_INSUFFICIENT_MEMORY;
660 goto Exit;
661 }
662
663 status = IB_SUCCESS;
664
665 Exit:
666 if (p_ca_infos) {
667 osm_ca_info_destroy(p_vend, p_ca_infos, ca_count);
668 }
669
670 OSM_LOG_EXIT(p_vend->p_log);
671 return (status);
672 }
673
674 /**********************************************************************
675 * Given the vendor obj and a port guid
676 * return the ca id and port number that have that guid
677 **********************************************************************/
678
679 ib_api_status_t
osm_vendor_get_guid_ca_and_port(IN osm_vendor_t * const p_vend,IN ib_net64_t const guid,OUT uint32_t * p_hca_hndl,OUT char * p_hca_id,OUT uint8_t * p_hca_idx,OUT uint32_t * p_port_num)680 osm_vendor_get_guid_ca_and_port(IN osm_vendor_t * const p_vend,
681 IN ib_net64_t const guid,
682 OUT uint32_t * p_hca_hndl,
683 OUT char *p_hca_id,
684 OUT uint8_t * p_hca_idx,
685 OUT uint32_t * p_port_num)
686 {
687 uint32_t caIdx;
688 uint32_t ca_count = 0;
689 uint8_t port_num;
690 ib_api_status_t status = IB_ERROR;
691
692 OSM_LOG_ENTER(p_vend->p_log);
693
694 CL_ASSERT(p_vend);
695
696 /* determine the number of CA's */
697 ca_count = __hca_pfs_get_num_cas();
698 if (!ca_count) {
699 osm_log(p_vend->p_log, OSM_LOG_ERROR,
700 "osm_vendor_get_guid_ca_and_port: ERR 5231: "
701 "Fail to get Any CA Ids.\n");
702 goto Exit;
703 }
704
705 /*
706 * For each CA, retrieve the CA info attributes
707 */
708 for (caIdx = 1; caIdx <= ca_count; caIdx++) {
709 pfs_ca_info_t pfs_ca_info;
710 if (__parse_ca_info_file(p_vend, caIdx, &pfs_ca_info) ==
711 IB_SUCCESS) {
712 /* get all the ports info */
713 for (port_num = 1; port_num <= pfs_ca_info.num_ports;
714 port_num++) {
715 uint64_t port_guid;
716 if (!__get_port_guid_from_port_gid_tbl
717 (p_vend, caIdx, port_num, &port_guid)) {
718 if (cl_hton64(port_guid) == guid) {
719 osm_log(p_vend->p_log,
720 OSM_LOG_DEBUG,
721 "osm_vendor_get_guid_ca_and_port: "
722 "Found Matching guid on HCA:%d Port:%d.\n",
723 caIdx, port_num);
724 strcpy(p_hca_id,
725 pfs_ca_info.name);
726 *p_port_num = port_num;
727 *p_hca_idx = caIdx - 1;
728 *p_hca_hndl = 0;
729 status = IB_SUCCESS;
730 goto Exit;
731 }
732 }
733 }
734 }
735 }
736
737 osm_log(p_vend->p_log, OSM_LOG_ERROR,
738 "osm_vendor_get_guid_ca_and_port: ERR 5232: "
739 "Fail to find HCA and Port for Port Guid 0x%" PRIx64 "\n",
740 cl_ntoh64(guid));
741 status = IB_INVALID_GUID;
742
743 Exit:
744
745 OSM_LOG_EXIT(p_vend->p_log);
746 return (status);
747 }
748
749 #endif
750