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_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
62typedef 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 ************************************************************************/
73static 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 **********************************************************************/
83int __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*/
113typedef 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 **********************************************************************/
127static ib_api_status_t
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;
225Exit:
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*/
245typedef 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 **********************************************************************/
257static ib_api_status_t
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;
399Exit:
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 **********************************************************************/
409static ib_api_status_t
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;
471Exit:
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 **********************************************************************/
479static ib_api_status_t
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;
545Exit:
546	OSM_LOG_EXIT(p_vend->p_log);
547	return (status);
548}
549
550/**********************************************************************
551 **********************************************************************/
552void
553osm_ca_info_destroy(IN osm_vendor_t * const p_vend,
554		    IN osm_ca_info_t * const p_ca_info, IN uint8_t num_ca)
555{
556	osm_ca_info_t *p_ca;
557	uint8_t i;
558
559	OSM_LOG_ENTER(p_vend->p_log);
560
561	for (i = 0; i < num_ca; i++) {
562		p_ca = &p_ca_info[i];
563
564		if (NULL != p_ca->p_attr) {
565			if (0 != p_ca->p_attr->num_ports) {
566				free(p_ca->p_attr->p_port_attr);
567			}
568
569			free(p_ca->p_attr);
570		}
571	}
572
573	free(p_ca_info);
574
575	OSM_LOG_EXIT(p_vend->p_log);
576}
577
578/**********************************************************************
579 * Fill in the array of port_attr with all available ports on ALL the
580 * avilable CAs on this machine.
581 **********************************************************************/
582ib_api_status_t
583osm_vendor_get_all_port_attr(IN osm_vendor_t * const p_vend,
584			     IN ib_port_attr_t * const p_attr_array,
585			     IN uint32_t * const p_num_ports)
586{
587	ib_api_status_t status = IB_SUCCESS;
588
589	uint32_t caIdx;
590	uint32_t ca_count = 0;
591	uint32_t port_count = 0;
592	uint8_t port_num;
593	uint32_t total_ports = 0;
594	osm_ca_info_t *p_ca_infos = NULL;
595	uint32_t attr_array_sz = *p_num_ports;
596
597	OSM_LOG_ENTER(p_vend->p_log);
598
599	CL_ASSERT(p_vend);
600
601	/* determine the number of CA's */
602	ca_count = __hca_pfs_get_num_cas();
603	if (!ca_count) {
604		osm_log(p_vend->p_log, OSM_LOG_ERROR,
605			"osm_vendor_get_all_port_attr: ERR 5228: "
606			"Fail to get Any CA Ids.\n");
607		goto Exit;
608	}
609
610	/* Allocate an array big enough to hold the ca info objects */
611	p_ca_infos = malloc(ca_count * sizeof(osm_ca_info_t));
612	if (p_ca_infos == NULL) {
613		osm_log(p_vend->p_log, OSM_LOG_ERROR,
614			"osm_vendor_get_all_port_attr: ERR 5229: "
615			"Unable to allocate CA information array.\n");
616		goto Exit;
617	}
618
619	memset(p_ca_infos, 0, ca_count * sizeof(osm_ca_info_t));
620
621	/*
622	 * For each CA, retrieve the CA info attributes
623	 */
624	for (caIdx = 1; caIdx <= ca_count; caIdx++) {
625		status =
626		    __osm_ca_info_init(p_vend, caIdx, &p_ca_infos[caIdx - 1]);
627		if (status != IB_SUCCESS) {
628			osm_log(p_vend->p_log, OSM_LOG_ERROR,
629				"osm_vendor_get_all_port_attr: ERR 5230: "
630				"Unable to initialize CA Info object (%s).\n",
631				ib_get_err_str(status));
632			goto Exit;
633		}
634		total_ports += p_ca_infos[caIdx - 1].p_attr->num_ports;
635	}
636
637	*p_num_ports = total_ports;
638	osm_log(p_vend->p_log, OSM_LOG_DEBUG,
639		"osm_vendor_get_all_port_attr: total ports:%u \n", total_ports);
640
641	/*
642	 * If the user supplied enough storage, return the port guids,
643	 * otherwise, return the appropriate error.
644	 */
645	if (attr_array_sz >= total_ports) {
646		for (caIdx = 1; caIdx <= ca_count; caIdx++) {
647			uint32_t num_ports;
648
649			num_ports = p_ca_infos[caIdx - 1].p_attr->num_ports;
650
651			for (port_num = 0; port_num < num_ports; port_num++) {
652				p_attr_array[port_count] =
653				    *__osm_ca_info_get_port_attr_ptr(&p_ca_infos
654								     [caIdx -
655								      1],
656								     port_num);
657				port_count++;
658			}
659		}
660	} else {
661		status = IB_INSUFFICIENT_MEMORY;
662		goto Exit;
663	}
664
665	status = IB_SUCCESS;
666
667Exit:
668	if (p_ca_infos) {
669		osm_ca_info_destroy(p_vend, p_ca_infos, ca_count);
670	}
671
672	OSM_LOG_EXIT(p_vend->p_log);
673	return (status);
674}
675
676/**********************************************************************
677 * Given the vendor obj and a port guid
678 * return the ca id and port number that have that guid
679 **********************************************************************/
680
681ib_api_status_t
682osm_vendor_get_guid_ca_and_port(IN osm_vendor_t * const p_vend,
683				IN ib_net64_t const guid,
684				OUT uint32_t * p_hca_hndl,
685				OUT char *p_hca_id,
686				OUT uint8_t * p_hca_idx,
687				OUT uint32_t * p_port_num)
688{
689	uint32_t caIdx;
690	uint32_t ca_count = 0;
691	uint8_t port_num;
692	ib_api_status_t status = IB_ERROR;
693
694	OSM_LOG_ENTER(p_vend->p_log);
695
696	CL_ASSERT(p_vend);
697
698	/* determine the number of CA's */
699	ca_count = __hca_pfs_get_num_cas();
700	if (!ca_count) {
701		osm_log(p_vend->p_log, OSM_LOG_ERROR,
702			"osm_vendor_get_guid_ca_and_port: ERR 5231: "
703			"Fail to get Any CA Ids.\n");
704		goto Exit;
705	}
706
707	/*
708	 * For each CA, retrieve the CA info attributes
709	 */
710	for (caIdx = 1; caIdx <= ca_count; caIdx++) {
711		pfs_ca_info_t pfs_ca_info;
712		if (__parse_ca_info_file(p_vend, caIdx, &pfs_ca_info) ==
713		    IB_SUCCESS) {
714			/* get all the ports info */
715			for (port_num = 1; port_num <= pfs_ca_info.num_ports;
716			     port_num++) {
717				uint64_t port_guid;
718				if (!__get_port_guid_from_port_gid_tbl
719				    (p_vend, caIdx, port_num, &port_guid)) {
720					if (cl_hton64(port_guid) == guid) {
721						osm_log(p_vend->p_log,
722							OSM_LOG_DEBUG,
723							"osm_vendor_get_guid_ca_and_port: "
724							"Found Matching guid on HCA:%d Port:%d.\n",
725							caIdx, port_num);
726						strcpy(p_hca_id,
727						       pfs_ca_info.name);
728						*p_port_num = port_num;
729						*p_hca_idx = caIdx - 1;
730						*p_hca_hndl = 0;
731						status = IB_SUCCESS;
732						goto Exit;
733					}
734				}
735			}
736		}
737	}
738
739	osm_log(p_vend->p_log, OSM_LOG_ERROR,
740		"osm_vendor_get_guid_ca_and_port: ERR 5232: "
741		"Fail to find HCA and Port for Port Guid 0x%" PRIx64 "\n",
742		cl_ntoh64(guid));
743	status = IB_INVALID_GUID;
744
745Exit:
746
747	OSM_LOG_EXIT(p_vend->p_log);
748	return (status);
749}
750
751#endif
752