]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/ofed/management/opensm/libvendor/osm_vendor_mlx_hca_sim.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / ofed / management / opensm / libvendor / osm_vendor_mlx_hca_sim.c
1 /*
2  * Copyright (c) 2004-2006 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_SIM)
41 #undef IN
42 #undef OUT
43
44 #include <unistd.h>
45 #include <vendor/osm_vendor_api.h>
46 #include <opensm/osm_log.h>
47 #include <stdlib.h>
48 #include <stdio.h>
49 #include <sys/types.h>
50 #include <dirent.h>
51 #include <stdlib.h>
52 #include <sys/stat.h>
53 #include <stdint.h>
54 #include <fcntl.h>
55
56 /******************************************************************************
57 *
58 * Provides the functionality for selecting an HCA Port and Obtaining it's guid.
59 * This version is based on $IBMGTSIM_DIR/$IBMGTSIM_NODE file system.
60 * This is a mimic of the OpenIB gen1 file system
61 *
62 ******************************************************************************/
63
64 char *__get_simulator_dir(void)
65 {
66         static char *ibmgtSimDir = NULL;
67         static char *defaultIbmgtSimDir = "/tmp/ibmgtsim";
68         static char *ibmgtSimNode = NULL;
69         static char dirName[1024];
70
71         /* we use the first pointer to know if we were here */
72         if (ibmgtSimDir == NULL) {
73                 /* obtain the simulator directory */
74                 ibmgtSimDir = getenv("IBMGTSIM_DIR");
75                 if (ibmgtSimDir == NULL) {
76                         printf
77                             ("-W- Environment variable: IBMGTSIM_DIR does not exist.\n");
78                         printf
79                             ("    Please create one used by the simulator.\n");
80                         printf("    Using /tmp/ibmgtsim as default.\n");
81                         ibmgtSimDir = defaultIbmgtSimDir;
82                 }
83
84                 /* obtain the node name we simulate */
85                 ibmgtSimNode = getenv("IBMGTSIM_NODE");
86                 if (ibmgtSimNode == NULL) {
87                         printf
88                             ("-W- Environment variable: IBMGTSIM_NODE does not exist.\n");
89                         printf
90                             ("    This variable should be the name of the node you wish to simulate.\n");
91                         printf("    Using H-1 as default.\n");
92                         ibmgtSimNode = "H-1";
93                 }
94                 sprintf(dirName, "%s/%s", ibmgtSimDir, ibmgtSimNode);
95         }
96
97         return dirName;
98 }
99
100 typedef struct _osm_ca_info {
101         ib_net64_t guid;
102         size_t attr_size;
103         ib_ca_attr_t *p_attr;
104
105 } osm_ca_info_t;
106
107 /**********************************************************************
108  * Returns a pointer to the port attribute of the specified port
109  * owned by this CA.
110  ************************************************************************/
111 static ib_port_attr_t *__osm_ca_info_get_port_attr_ptr(IN const osm_ca_info_t *
112                                                        const p_ca_info,
113                                                        IN const uint8_t index)
114 {
115         return (&p_ca_info->p_attr->p_port_attr[index]);
116 }
117
118 /**********************************************************************
119  * Obtain the number of local CAs by scanning /proc/infiniband/core
120  **********************************************************************/
121 int __hca_sim_get_num_cas(void)
122 {
123         int num_cas = 0;
124         DIR *dp;
125         struct dirent *ep;
126
127         dp = opendir(__get_simulator_dir());
128
129         if (dp != NULL) {
130                 while ((ep = readdir(dp))) {
131                         /* CAs are directories with the format ca[1-9][0-9]* */
132                         /*  if ((ep->d_type == DT_DIR) && !strncmp(ep->d_name, "ca", 2)) */
133                         if (!strncmp(ep->d_name, "ca", 2)) {
134                                 num_cas++;
135                         }
136                 }
137                 closedir(dp);
138         } else {
139                 printf("__hca_sim_get_num_cas: ERROR : ail to open dir %s\n",
140                        __get_simulator_dir());
141                 exit(1);
142         }
143
144         if (!num_cas)
145                 exit(1);
146         return num_cas;
147 }
148
149 /*
150   name:          InfiniHost0
151   provider:      tavor
152   node GUID:     0002:c900:0120:3470
153   ports:         2
154   vendor ID:     0x2c9
155   device ID:     0x5a44
156   HW revision:   0xa1
157   FW revision:   0x300020080
158 */
159 typedef struct _sim_ca_info {
160         char name[32];
161         char provider[32];
162         uint64_t guid;
163         uint8_t num_ports;
164         uint32_t vend_id;
165         uint16_t dev_id;
166         uint16_t rev_id;
167         uint64_t fw_rev;
168 } sim_ca_info_t;
169
170 /**********************************************************************
171  * Parse the CA Info file available in ibmgtSimDir/caN/info
172  **********************************************************************/
173 static ib_api_status_t
174 __parse_ca_info_file(IN osm_vendor_t * const p_vend,
175                      IN uint32_t idx, OUT sim_ca_info_t * sim_ca_info)
176 {
177         ib_api_status_t status = IB_ERROR;
178         int info_file;
179         char file_name[256];
180         char file_buffer[3200];
181         char *p_ch;
182         int g1, g2, g3, g4;
183         int num_ports;
184         uint32_t len;
185
186         OSM_LOG_ENTER(p_vend->p_log);
187
188         osm_log(p_vend->p_log, OSM_LOG_DEBUG,
189                 "__parse_ca_info_file: " "Querying CA %d.\n", idx);
190
191         /* we use the proc file system so we must be able to open the info file .. */
192         sprintf(file_name, "%s/ca%d/info", __get_simulator_dir(), idx);
193         info_file = open(file_name, O_RDONLY);
194         if (!info_file) {
195                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
196                         "__parse_ca_info_file: ERR 5105: "
197                         "Fail to open HCA:%d info file:(%s).\n", idx,
198                         file_name);
199                 goto Exit;
200         }
201
202         /* read in the file */
203         len = read(info_file, file_buffer, 3200);
204         close(info_file);
205         file_buffer[len] = '\0';
206
207         /*
208            parse the file ...
209            name:          InfiniHost0
210            provider:      tavor
211            node GUID:     0002:c900:0120:3470
212            ports:         2
213            vendor ID:     0x2c9
214            device ID:     0x5a44
215            HW revision:   0xa1
216            FW revision:   0x300020080
217          */
218         if (!(p_ch = strstr(file_buffer, "name:"))) {
219                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
220                         "__parse_ca_info_file: ERR 5106: "
221                         "Fail to obtain HCA name. In info file:(%s).\n",
222                         file_buffer);
223                 goto Exit;
224         }
225         if (sscanf(p_ch, "name: %s", sim_ca_info->name) != 1) {
226                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
227                         "__parse_ca_info_file: ERR 5107: "
228                         "Fail to parse name in info file:(%s).\n", p_ch);
229                 goto Exit;
230         }
231
232         /* get the guid of the HCA */
233         if (!(p_ch = strstr(file_buffer, "node GUID:"))) {
234                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
235                         "__parse_ca_info_file: ERR 5108: "
236                         "Fail to obtain GUID in info file:(%s).\n",
237                         file_buffer);
238                 goto Exit;
239         }
240         if (sscanf(p_ch, "node GUID: %x:%x:%x:%x", &g1, &g2, &g3, &g4) != 4) {
241                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
242                         "__parse_ca_info_file: ERR 5109: "
243                         "Fail to parse GUID in info file:(%s).\n", p_ch);
244                 goto Exit;
245         }
246         sim_ca_info->guid = (uint64_t) g1 << 48 | (uint64_t) g1 << 32
247             | (uint64_t) g1 << 16 | (uint64_t) g3;
248
249         /* obtain number of ports */
250         if (!(p_ch = strstr(file_buffer, "ports:"))) {
251                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
252                         "__parse_ca_info_file: ERR 5110: "
253                         "Fail to obtain number of ports in info file:(%s).\n",
254                         file_buffer);
255                 goto Exit;
256         }
257         if (sscanf(p_ch, "ports: %d", &num_ports) != 1) {
258                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
259                         "__parse_ca_info_file: ERR 5111: "
260                         "Fail to parse num ports in info file:(%s).\n", p_ch);
261                 goto Exit;
262         }
263         sim_ca_info->num_ports = num_ports;
264
265         osm_log(p_vend->p_log, OSM_LOG_DEBUG,
266                 "__parse_ca_info_file: "
267                 "CA1 = name:%s guid:0x%016llx ports:%d\n",
268                 sim_ca_info->name, sim_ca_info->guid, sim_ca_info->num_ports);
269
270         status = IB_SUCCESS;
271 Exit:
272         OSM_LOG_EXIT(p_vend->p_log);
273         return status;
274 }
275
276 /*
277   state:         ACTIVE
278   LID:           0x0001
279   LMC:           0x0000
280   SM LID:        0x0001
281   SM SL:         0x0000
282   Capabilities:  IsSM
283   IsTrapSupported
284   IsAutomaticMigrationSupported
285   IsSLMappingSupported
286   IsLEDInfoSupported
287   IsSystemImageGUIDSupported
288   IsVendorClassSupported
289   IsCapabilityMaskNoticeSupported
290 */
291 typedef struct _sim_port_info {
292         uint8_t state;
293         uint16_t lid;
294         uint8_t lmc;
295         uint16_t sm_lid;
296         uint8_t sm_sl;
297 } sim_port_info_t;
298
299 /**********************************************************************
300  * Parse the Port Info file available in ibmgtSimDir/caN/portM/info
301  * Port num is 1..N
302  **********************************************************************/
303 static ib_api_status_t
304 __parse_port_info_file(IN osm_vendor_t * const p_vend,
305                        IN uint32_t hca_idx,
306                        IN uint8_t port_num, OUT sim_port_info_t * sim_port_info)
307 {
308         ib_api_status_t status = IB_ERROR;
309         int info_file;
310         char file_name[256];
311         char file_buffer[3200];
312         char state[12];
313         char *p_ch;
314         int lid, sm_lid, lmc, sm_sl;
315         uint32_t len;
316
317         OSM_LOG_ENTER(p_vend->p_log);
318
319         osm_log(p_vend->p_log, OSM_LOG_DEBUG,
320                 "__parse_port_info_file: "
321                 "Parsing Proc File System Port Info CA %d Port %d.\n", hca_idx,
322                 port_num);
323
324         /* we use the proc file system so we must be able to open the info file .. */
325         sprintf(file_name, "%s/ca%d/port%d/info", __get_simulator_dir(),
326                 hca_idx, port_num);
327         info_file = open(file_name, O_RDONLY);
328         if (!info_file) {
329                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
330                         "__parse_port_info_file: ERR 5112: "
331                         "Fail to open HCA:%d Port:%d info file:(%s).\n",
332                         hca_idx, port_num, file_name);
333                 goto Exit;
334         }
335
336         /* read in the file */
337         len = read(info_file, file_buffer, 3200);
338         close(info_file);
339         file_buffer[len] = '\0';
340
341         /*
342            parse the file ...
343            state:         ACTIVE
344            LID:           0x0001
345            LMC:           0x0000
346            SM LID:        0x0001
347            SM SL:         0x0000
348            ...
349          */
350         if (!(p_ch = strstr(file_buffer, "state:"))) {
351                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
352                         "__parse_port_info_file: ERR 5113: "
353                         "Fail to obtain port state. In info file:(%s).\n",
354                         file_buffer);
355                 goto Exit;
356         }
357         if (sscanf(p_ch, "state: %s", state) != 1) {
358                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
359                         "__parse_port_info_file: ERR 5114: "
360                         "Fail to parse state from info file:(%s).\n", p_ch);
361                 goto Exit;
362         }
363
364         if (!strcmp(state, "ACTIVE"))
365                 sim_port_info->state = IB_LINK_ACTIVE;
366         else if (!strcmp(state, "DOWN"))
367                 sim_port_info->state = IB_LINK_DOWN;
368         else if (!strcmp(state, "INIT"))
369                 sim_port_info->state = IB_LINK_INIT;
370         else if (!strcmp(state, "ARMED"))
371                 sim_port_info->state = IB_LINK_ARMED;
372         else
373                 sim_port_info->state = 0;
374
375         /* get lid */
376         if (!(p_ch = strstr(file_buffer, "LID:"))) {
377                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
378                         "__parse_port_info_file: ERR 5115: "
379                         "Fail to obtain port lid. In info file:(%s).\n",
380                         file_buffer);
381                 goto Exit;
382         }
383         if (sscanf(p_ch, "LID: %x", &lid) != 1) {
384                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
385                         "__parse_port_info_file: ERR 5116: "
386                         "Fail to parse lid from info file:(%s).\n", p_ch);
387                 goto Exit;
388         }
389         sim_port_info->lid = lid;
390         /* get LMC */
391         if (!(p_ch = strstr(file_buffer, "LMC:"))) {
392                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
393                         "__parse_port_info_file: ERR 5117: "
394                         "Fail to obtain port LMC. In info file:(%s).\n",
395                         file_buffer);
396                 goto Exit;
397         }
398         if (sscanf(p_ch, "LMC: %x", &lmc) != 1) {
399                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
400                         "__parse_port_info_file: ERR 5118: "
401                         "Fail to parse LMC from info file:(%s).\n", p_ch);
402                 goto Exit;
403         }
404         sim_port_info->lmc = lmc;
405
406         /* get SM LID */
407         if (!(p_ch = strstr(file_buffer, "SM LID:"))) {
408                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
409                         "__parse_port_info_file: ERR 5119: "
410                         "Fail to obtain port SM LID. In info file:(%s).\n",
411                         file_buffer);
412                 goto Exit;
413         }
414         if (sscanf(p_ch, "SM LID: %x", &sm_lid) != 1) {
415                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
416                         "__parse_port_info_file: ERR 5120: "
417                         "Fail to parse SM LID from info file:(%s).\n", p_ch);
418                 goto Exit;
419         }
420         sim_port_info->sm_lid = sm_lid;
421
422         /* get SM LID */
423         if (!(p_ch = strstr(file_buffer, "SM SL:"))) {
424                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
425                         "__parse_port_info_file: ERR 5121: "
426                         "Fail to obtain port SM SL. In info file:(%s).\n",
427                         file_buffer);
428                 goto Exit;
429         }
430         if (sscanf(p_ch, "SM SL: %x", &sm_sl) != 1) {
431                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
432                         "__parse_port_info_file: ERR 5122: "
433                         "Fail to parse SM SL from info file:(%s).\n", p_ch);
434                 goto Exit;
435         }
436         sim_port_info->sm_sl = sm_sl;
437         osm_log(p_vend->p_log, OSM_LOG_DEBUG,
438                 "__parse_port_info_file:  "
439                 "Obtained Port:%d = state:%d, lid:0x%04X, lmc:%d, sm_lid:0x%04X, sm_sl:%d\n",
440                 port_num, sim_port_info->state, sim_port_info->lid,
441                 sim_port_info->lmc, sim_port_info->sm_lid,
442                 sim_port_info->sm_sl);
443
444         status = IB_SUCCESS;
445 Exit:
446         OSM_LOG_EXIT(p_vend->p_log);
447         return status;
448 }
449
450 /**********************************************************************
451  * Parse the port guid_tbl file to obtain the port guid.
452  * File format is:
453  * [  0] fe80:0000:0000:0000:0002:c900:0120:3472
454  **********************************************************************/
455 static ib_api_status_t
456 __get_port_guid_from_port_gid_tbl(IN osm_vendor_t * const p_vend,
457                                   IN uint32_t hca_idx,
458                                   IN uint8_t port_num, OUT uint64_t * port_guid)
459 {
460         ib_api_status_t status = IB_ERROR;
461         int info_file;
462         char file_name[256];
463         char file_buffer[3200];
464         char *p_ch;
465         int g[8];
466         uint32_t len;
467
468         OSM_LOG_ENTER(p_vend->p_log);
469
470         osm_log(p_vend->p_log, OSM_LOG_DEBUG,
471                 "__get_port_guid_from_port_gid_tbl: "
472                 "Parsing Proc File System Port Guid Table CA %d Port %d.\n",
473                 hca_idx, port_num);
474
475         /* we use the proc file system so we must be able to open the info file .. */
476         sprintf(file_name, "%s/ca%d/port%d/gid_table",
477                 __get_simulator_dir(), hca_idx, port_num);
478         info_file = open(file_name, O_RDONLY);
479         if (!info_file) {
480                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
481                         "__get_port_guid_from_port_gid_tbl: ERR 5123: "
482                         "Fail to open HCA:%d Port:%d gid_table file:(%s).\n",
483                         hca_idx, port_num, file_name);
484                 goto Exit;
485         }
486
487         /* read in the file */
488         len = read(info_file, file_buffer, 3200);
489         close(info_file);
490         file_buffer[len] = '\0';
491
492         /*
493            parse the file ...
494            [  0] fe80:0000:0000:0000:0002:c900:0120:3472
495            ...
496          */
497         if (!(p_ch = strstr(file_buffer, "[  0]"))) {
498                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
499                         "__get_port_guid_from_port_gid_tbl: ERR 5124: "
500                         "Fail to obtain first gid index. In gid_table file:(%s).\n",
501                         file_buffer);
502                 goto Exit;
503         }
504         if (sscanf(p_ch + 6, "%x:%x:%x:%x:%x:%x:%x:%x",
505                    &g[7], &g[6], &g[5], &g[4], &g[3], &g[2], &g[1], &g[0]) != 8)
506         {
507                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
508                         "__get_port_guid_from_port_gid_tbl: ERR 5125: "
509                         "Fail to parse gid from gid_table file:(%s).\n", p_ch);
510                 goto Exit;
511         }
512
513         *port_guid =
514             (uint64_t) g[3] << 48 | (uint64_t) g[2] << 32 | (uint64_t) g[1] <<
515             16 | g[0];
516         status = IB_SUCCESS;
517 Exit:
518         OSM_LOG_EXIT(p_vend->p_log);
519         return status;
520 }
521
522 /**********************************************************************
523  * Initialize an Info Struct for the Given HCA by its index 1..N
524  **********************************************************************/
525 static ib_api_status_t
526 __osm_ca_info_init(IN osm_vendor_t * const p_vend,
527                    IN uint32_t const idx, OUT osm_ca_info_t * const p_ca_info)
528 {
529         ib_api_status_t status = IB_ERROR;
530         uint8_t port_num;
531         uint64_t port_guid;
532
533         sim_ca_info_t sim_ca_info;
534
535         OSM_LOG_ENTER(p_vend->p_log);
536
537         /* parse the CA info file */
538         if (__parse_ca_info_file(p_vend, idx, &sim_ca_info) != IB_SUCCESS)
539                 goto Exit;
540
541         p_ca_info->guid = cl_hton64(sim_ca_info.guid);
542
543         /* set size of attributes and allocate them */
544         p_ca_info->attr_size = 1;
545         p_ca_info->p_attr = (ib_ca_attr_t *) malloc(sizeof(ib_ca_attr_t));
546
547         p_ca_info->p_attr->ca_guid = p_ca_info->guid;
548         p_ca_info->p_attr->num_ports = sim_ca_info.num_ports;
549
550         /* now obtain the attributes of the ports */
551         p_ca_info->p_attr->p_port_attr =
552             (ib_port_attr_t *) malloc(sim_ca_info.num_ports *
553                                       sizeof(ib_port_attr_t));
554
555         /* get all the ports info */
556         for (port_num = 1; port_num <= sim_ca_info.num_ports; port_num++) {
557                 sim_port_info_t sim_port_info;
558                 /* query the port attributes */
559                 if (__parse_port_info_file
560                     (p_vend, idx, port_num, &sim_port_info)) {
561                         osm_log(p_vend->p_log, OSM_LOG_ERROR,
562                                 "__osm_ca_info_init: ERR 5126: "
563                                 "Fail to get HCA:%d Port:%d Attributes.\n", idx,
564                                 port_num);
565                         goto Exit;
566                 }
567
568                 /* HACK: the lids should have been converted to network but the rest of the code
569                    is wrong and provdes them as is (host order) - so we stick with it. */
570                 p_ca_info->p_attr->p_port_attr[port_num - 1].lid =
571                     sim_port_info.lid;
572                 p_ca_info->p_attr->p_port_attr[port_num - 1].link_state =
573                     sim_port_info.state;
574                 p_ca_info->p_attr->p_port_attr[port_num - 1].sm_lid =
575                     sim_port_info.sm_lid;
576
577                 /* get the port guid */
578                 if (__get_port_guid_from_port_gid_tbl
579                     (p_vend, idx, port_num, &port_guid)) {
580                         osm_log(p_vend->p_log, OSM_LOG_ERROR,
581                                 "__osm_ca_info_init: ERR 5127: "
582                                 "Fail to get HCA:%d Port:%d Guid.\n", idx,
583                                 port_num);
584                         goto Exit;
585                 }
586                 p_ca_info->p_attr->p_port_attr[port_num - 1].port_guid =
587                     cl_hton64(port_guid);
588         }
589
590         status = IB_SUCCESS;
591 Exit:
592         OSM_LOG_EXIT(p_vend->p_log);
593         return (status);
594 }
595
596 /**********************************************************************
597  **********************************************************************/
598 void
599 osm_ca_info_destroy(IN osm_vendor_t * const p_vend,
600                     IN osm_ca_info_t * const p_ca_info, IN uint8_t num_ca)
601 {
602         osm_ca_info_t *p_ca;
603         uint8_t i;
604
605         OSM_LOG_ENTER(p_vend->p_log);
606
607         for (i = 0; i < num_ca; i++) {
608                 p_ca = &p_ca_info[i];
609
610                 if (NULL != p_ca->p_attr) {
611                         if (0 != p_ca->p_attr->num_ports) {
612                                 free(p_ca->p_attr->p_port_attr);
613                         }
614
615                         free(p_ca->p_attr);
616                 }
617         }
618
619         free(p_ca_info);
620
621         OSM_LOG_EXIT(p_vend->p_log);
622 }
623
624 /**********************************************************************
625  * Fill in the array of port_attr with all available ports on ALL the
626  * avilable CAs on this machine.
627  **********************************************************************/
628 ib_api_status_t
629 osm_vendor_get_all_port_attr(IN osm_vendor_t * const p_vend,
630                              IN ib_port_attr_t * const p_attr_array,
631                              IN uint32_t * const p_num_ports)
632 {
633         ib_api_status_t status = IB_SUCCESS;
634
635         uint32_t caIdx;
636         uint32_t ca_count = 0;
637         uint32_t port_count = 0;
638         uint8_t port_num;
639         uint32_t total_ports = 0;
640         osm_ca_info_t *p_ca_infos = NULL;
641         uint32_t attr_array_sz = *p_num_ports;
642
643         OSM_LOG_ENTER(p_vend->p_log);
644
645         CL_ASSERT(p_vend);
646
647         /* determine the number of CA's */
648         ca_count = __hca_sim_get_num_cas();
649         if (!ca_count) {
650                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
651                         "osm_vendor_get_all_port_attr: ERR 5128: "
652                         "Fail to get Any CA Ids.\n");
653                 goto Exit;
654         }
655
656         /* Allocate an array big enough to hold the ca info objects */
657         p_ca_infos = malloc(ca_count * sizeof(osm_ca_info_t));
658         if (p_ca_infos == NULL) {
659                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
660                         "osm_vendor_get_all_port_attr: ERR 5129: "
661                         "Unable to allocate CA information array.\n");
662                 goto Exit;
663         }
664
665         memset(p_ca_infos, 0, ca_count * sizeof(osm_ca_info_t));
666
667         /*
668          * For each CA, retrieve the CA info attributes
669          */
670         for (caIdx = 1; caIdx <= ca_count; caIdx++) {
671                 status =
672                     __osm_ca_info_init(p_vend, caIdx, &p_ca_infos[caIdx - 1]);
673                 if (status != IB_SUCCESS) {
674                         osm_log(p_vend->p_log, OSM_LOG_ERROR,
675                                 "osm_vendor_get_all_port_attr: ERR 5130: "
676                                 "Unable to initialize CA Info object (%s).\n",
677                                 ib_get_err_str(status));
678                         goto Exit;
679                 }
680                 total_ports += p_ca_infos[caIdx - 1].p_attr->num_ports;
681         }
682
683         *p_num_ports = total_ports;
684         osm_log(p_vend->p_log, OSM_LOG_DEBUG,
685                 "osm_vendor_get_all_port_attr: total ports:%u \n", total_ports);
686
687         /*
688          * If the user supplied enough storage, return the port guids,
689          * otherwise, return the appropriate error.
690          */
691         if (attr_array_sz >= total_ports) {
692                 for (caIdx = 1; caIdx <= ca_count; caIdx++) {
693                         uint32_t num_ports;
694
695                         num_ports = p_ca_infos[caIdx - 1].p_attr->num_ports;
696
697                         for (port_num = 0; port_num < num_ports; port_num++) {
698                                 p_attr_array[port_count] =
699                                     *__osm_ca_info_get_port_attr_ptr(&p_ca_infos
700                                                                      [caIdx -
701                                                                       1],
702                                                                      port_num);
703                                 port_count++;
704                         }
705                 }
706         } else {
707                 status = IB_INSUFFICIENT_MEMORY;
708                 goto Exit;
709         }
710
711         status = IB_SUCCESS;
712
713 Exit:
714         if (p_ca_infos) {
715                 osm_ca_info_destroy(p_vend, p_ca_infos, ca_count);
716         }
717
718         OSM_LOG_EXIT(p_vend->p_log);
719         return (status);
720 }
721
722 /**********************************************************************
723  * Given the vendor obj and a port guid
724  * return the ca id and port number that have that guid
725  **********************************************************************/
726
727 ib_api_status_t
728 osm_vendor_get_guid_ca_and_port(IN osm_vendor_t * const p_vend,
729                                 IN ib_net64_t const guid,
730                                 OUT uint32_t * p_hca_hndl,
731                                 OUT char *p_hca_id,
732                                 OUT uint8_t * p_hca_idx,
733                                 OUT uint32_t * p_port_num)
734 {
735         uint32_t caIdx;
736         uint32_t ca_count = 0;
737         uint8_t port_num;
738         ib_api_status_t status = IB_ERROR;
739
740         OSM_LOG_ENTER(p_vend->p_log);
741
742         CL_ASSERT(p_vend);
743
744         /* determine the number of CA's */
745         ca_count = __hca_sim_get_num_cas();
746         if (!ca_count) {
747                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
748                         "osm_vendor_get_guid_ca_and_port: ERR 5131: "
749                         "Fail to get Any CA Ids.\n");
750                 goto Exit;
751         }
752
753         /*
754          * For each CA, retrieve the CA info attributes
755          */
756         for (caIdx = 1; caIdx <= ca_count; caIdx++) {
757                 sim_ca_info_t sim_ca_info;
758                 if (__parse_ca_info_file(p_vend, caIdx, &sim_ca_info) ==
759                     IB_SUCCESS) {
760                         /* get all the ports info */
761                         for (port_num = 1; port_num <= sim_ca_info.num_ports;
762                              port_num++) {
763                                 uint64_t port_guid;
764                                 if (!__get_port_guid_from_port_gid_tbl
765                                     (p_vend, caIdx, port_num, &port_guid)) {
766                                         if (cl_hton64(port_guid) == guid) {
767                                                 osm_log(p_vend->p_log,
768                                                         OSM_LOG_DEBUG,
769                                                         "osm_vendor_get_guid_ca_and_port: "
770                                                         "Found Matching guid on HCA:%d Port:%d.\n",
771                                                         caIdx, port_num);
772                                                 strcpy(p_hca_id,
773                                                        sim_ca_info.name);
774                                                 *p_port_num = port_num;
775                                                 *p_hca_idx = caIdx - 1;
776                                                 *p_hca_hndl = 0;
777                                                 status = IB_SUCCESS;
778                                                 goto Exit;
779                                         }
780                                 }
781                         }
782                 }
783         }
784
785         osm_log(p_vend->p_log, OSM_LOG_ERROR,
786                 "osm_vendor_get_guid_ca_and_port: ERR 5132: "
787                 "Fail to find HCA and Port for Port Guid 0x%" PRIx64 "\n",
788                 cl_ntoh64(guid));
789         status = IB_INVALID_GUID;
790
791 Exit:
792
793         OSM_LOG_EXIT(p_vend->p_log);
794         return (status);
795 }
796
797 /**********************************************************************
798  * Given the vendor obj HCA ID and Port Num
799  * update the given port guid if found. Return 0 on success.
800  **********************************************************************/
801
802 ib_api_status_t
803 osm_vendor_get_guid_by_ca_and_port(IN osm_vendor_t * const p_vend,
804                                    IN char *hca_id,
805                                    IN uint32_t port_num,
806                                    OUT uint64_t * p_port_guid)
807 {
808         uint32_t caIdx;
809         uint32_t ca_count = 0;
810         ib_api_status_t status = IB_ERROR;
811
812         OSM_LOG_ENTER(p_vend->p_log);
813
814         CL_ASSERT(p_vend);
815
816         /* determine the number of CA's */
817         ca_count = __hca_sim_get_num_cas();
818         if (!ca_count) {
819                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
820                         "osm_vendor_get_guid_by_ca_and_port: ERR 5133: "
821                         "Fail to get Any CA Ids.\n");
822                 goto Exit;
823         }
824
825         /*
826          * For each CA, retrieve the CA info attributes
827          */
828         for (caIdx = 1; caIdx <= ca_count; caIdx++) {
829                 sim_ca_info_t sim_ca_info;
830                 if (__parse_ca_info_file(p_vend, caIdx, &sim_ca_info) ==
831                     IB_SUCCESS) {
832                         /* if not identical by id - go to next one */
833                         if (strcmp(sim_ca_info.name, hca_id))
834                                 continue;
835
836                         if ((port_num < 1)
837                             || (port_num > sim_ca_info.num_ports)) {
838                                 return 1;
839                         }
840
841                         if (!__get_port_guid_from_port_gid_tbl
842                             (p_vend, caIdx, port_num, p_port_guid)) {
843                                 osm_log(p_vend->p_log, OSM_LOG_DEBUG,
844                                         "osm_vendor_get_guid_by_ca_and_port: "
845                                         "Found Matching guid on HCA:%d Port:%d.\n",
846                                         caIdx, port_num);
847                                 status = IB_SUCCESS;
848                                 goto Exit;
849                         }
850                 }
851         }
852
853         osm_log(p_vend->p_log, OSM_LOG_ERROR,
854                 "osm_vendor_get_guid_by_ca_and_port: ERR 5134: "
855                 "Fail to find HCA:%s\n", hca_id);
856         status = IB_INVALID_GUID;
857
858 Exit:
859
860         OSM_LOG_EXIT(p_vend->p_log);
861         return (status);
862 }
863
864 #endif