1219820Sjeff/*
2219820Sjeff * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
3219820Sjeff * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
4219820Sjeff * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
5219820Sjeff *
6219820Sjeff * This software is available to you under a choice of one of two
7219820Sjeff * licenses.  You may choose to be licensed under the terms of the GNU
8219820Sjeff * General Public License (GPL) Version 2, available from the file
9219820Sjeff * COPYING in the main directory of this source tree, or the
10219820Sjeff * OpenIB.org BSD license below:
11219820Sjeff *
12219820Sjeff *     Redistribution and use in source and binary forms, with or
13219820Sjeff *     without modification, are permitted provided that the following
14219820Sjeff *     conditions are met:
15219820Sjeff *
16219820Sjeff *      - Redistributions of source code must retain the above
17219820Sjeff *        copyright notice, this list of conditions and the following
18219820Sjeff *        disclaimer.
19219820Sjeff *
20219820Sjeff *      - Redistributions in binary form must reproduce the above
21219820Sjeff *        copyright notice, this list of conditions and the following
22219820Sjeff *        disclaimer in the documentation and/or other materials
23219820Sjeff *        provided with the distribution.
24219820Sjeff *
25219820Sjeff * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26219820Sjeff * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27219820Sjeff * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28219820Sjeff * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29219820Sjeff * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30219820Sjeff * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31219820Sjeff * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32219820Sjeff * SOFTWARE.
33219820Sjeff *
34219820Sjeff */
35219820Sjeff
36219820Sjeff#if HAVE_CONFIG_H
37219820Sjeff#  include <config.h>
38219820Sjeff#endif				/* HAVE_CONFIG_H */
39219820Sjeff
40219820Sjeff#if defined(OSM_VENDOR_INTF_MTL) | defined(OSM_VENDOR_INTF_TS)
41219820Sjeff#undef IN
42219820Sjeff#undef OUT
43219820Sjeff#include <vendor/osm_vendor_api.h>
44219820Sjeff#include <opensm/osm_log.h>
45219820Sjeff#include <stdlib.h>
46219820Sjeff#include <stdio.h>
47219820Sjeff#include <sys/types.h>
48219820Sjeff#include <dirent.h>
49219820Sjeff#include <stdio.h>
50219820Sjeff#include <sys/stat.h>
51219820Sjeff#include <stdint.h>
52219820Sjeff#include <fcntl.h>
53219820Sjeff
54219820Sjeff/********************************************************************************
55219820Sjeff *
56219820Sjeff * Provides the functionality for selecting an HCA Port and Obtaining it's guid.
57219820Sjeff * This version is based on /proc/infiniband file system. So it is limited to
58219820Sjeff * The gen1 of openib.org stack.
59219820Sjeff *
60219820Sjeff ********************************************************************************/
61219820Sjeff
62219820Sjefftypedef struct _osm_ca_info {
63219820Sjeff	ib_net64_t guid;
64219820Sjeff	size_t attr_size;
65219820Sjeff	ib_ca_attr_t *p_attr;
66219820Sjeff
67219820Sjeff} osm_ca_info_t;
68219820Sjeff
69219820Sjeff/**********************************************************************
70219820Sjeff * Returns a pointer to the port attribute of the specified port
71219820Sjeff * owned by this CA.
72219820Sjeff ************************************************************************/
73219820Sjeffstatic ib_port_attr_t *__osm_ca_info_get_port_attr_ptr(IN const osm_ca_info_t *
74219820Sjeff						       const p_ca_info,
75219820Sjeff						       IN const uint8_t index)
76219820Sjeff{
77219820Sjeff	return (&p_ca_info->p_attr->p_port_attr[index]);
78219820Sjeff}
79219820Sjeff
80219820Sjeff/**********************************************************************
81219820Sjeff * Obtain the number of local CAs by scanning /proc/infiniband/core
82219820Sjeff **********************************************************************/
83219820Sjeffint __hca_pfs_get_num_cas()
84219820Sjeff{
85219820Sjeff	int num_cas = 0;
86219820Sjeff	DIR *dp;
87219820Sjeff	struct dirent *ep;
88219820Sjeff
89219820Sjeff	dp = opendir("/proc/infiniband/core");
90219820Sjeff	if (dp != NULL) {
91219820Sjeff		while ((ep = readdir(dp))) {
92219820Sjeff			/* CAs are directories with the format ca[1-9][0-9]* */
93219820Sjeff			if ((ep->d_type == DT_DIR)
94219820Sjeff			    && !strncmp(ep->d_name, "ca", 2)) {
95219820Sjeff				num_cas++;
96219820Sjeff			}
97219820Sjeff		}
98219820Sjeff		closedir(dp);
99219820Sjeff	}
100219820Sjeff	return num_cas;
101219820Sjeff}
102219820Sjeff
103219820Sjeff/*
104219820Sjeff  name:          InfiniHost0
105219820Sjeff  provider:      tavor
106219820Sjeff  node GUID:     0002:c900:0120:3470
107219820Sjeff  ports:         2
108219820Sjeff  vendor ID:     0x2c9
109219820Sjeff  device ID:     0x5a44
110219820Sjeff  HW revision:   0xa1
111219820Sjeff  FW revision:   0x300020080
112219820Sjeff*/
113219820Sjefftypedef struct _pfs_ca_info {
114219820Sjeff	char name[32];
115219820Sjeff	char provider[32];
116219820Sjeff	uint64_t guid;
117219820Sjeff	uint8_t num_ports;
118219820Sjeff	uint32_t vend_id;
119219820Sjeff	uint16_t dev_id;
120219820Sjeff	uint16_t rev_id;
121219820Sjeff	uint64_t fw_rev;
122219820Sjeff} pfs_ca_info_t;
123219820Sjeff
124219820Sjeff/**********************************************************************
125219820Sjeff * Parse the CA Info file available in /proc/infiniband/core/caN/info
126219820Sjeff **********************************************************************/
127219820Sjeffstatic ib_api_status_t
128219820Sjeff__parse_ca_info_file(IN osm_vendor_t * const p_vend,
129219820Sjeff		     IN uint32_t idx, OUT pfs_ca_info_t * pfs_ca_info)
130219820Sjeff{
131219820Sjeff	ib_api_status_t status = IB_ERROR;
132219820Sjeff	int info_file;
133219820Sjeff	char file_name[256];
134219820Sjeff	char file_buffer[3200];
135219820Sjeff	char *p_ch;
136219820Sjeff	int g1, g2, g3, g4;
137219820Sjeff	int num_ports;
138219820Sjeff	uint32_t len;
139219820Sjeff
140219820Sjeff	OSM_LOG_ENTER(p_vend->p_log);
141219820Sjeff
142219820Sjeff	osm_log(p_vend->p_log, OSM_LOG_DEBUG,
143219820Sjeff		"__parse_ca_info_file: " "Querying CA %d.\n", idx);
144219820Sjeff
145219820Sjeff	/* we use the proc file system so we must be able to open the info file .. */
146219820Sjeff	sprintf(file_name, "/proc/infiniband/core/ca%d/info", idx);
147219820Sjeff	info_file = open(file_name, O_RDONLY);
148219820Sjeff	if (!info_file) {
149219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
150219820Sjeff			"__parse_ca_info_file: ERR 5205: "
151219820Sjeff			"Fail to open HCA:%d info file:(%s).\n", idx,
152219820Sjeff			file_name);
153219820Sjeff		goto Exit;
154219820Sjeff	}
155219820Sjeff
156219820Sjeff	/* read in the file */
157219820Sjeff	len = read(info_file, file_buffer, 3200);
158219820Sjeff	close(info_file);
159219820Sjeff	file_buffer[len] = '\0';
160219820Sjeff
161219820Sjeff	/*
162219820Sjeff	   parse the file ...
163219820Sjeff	   name:          InfiniHost0
164219820Sjeff	   provider:      tavor
165219820Sjeff	   node GUID:     0002:c900:0120:3470
166219820Sjeff	   ports:         2
167219820Sjeff	   vendor ID:     0x2c9
168219820Sjeff	   device ID:     0x5a44
169219820Sjeff	   HW revision:   0xa1
170219820Sjeff	   FW revision:   0x300020080
171219820Sjeff	 */
172219820Sjeff	if (!(p_ch = strstr(file_buffer, "name:"))) {
173219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
174219820Sjeff			"__parse_ca_info_file: ERR 5206: "
175219820Sjeff			"Fail to obtain HCA name. In info file:(%s).\n",
176219820Sjeff			file_buffer);
177219820Sjeff		goto Exit;
178219820Sjeff	}
179219820Sjeff	if (sscanf(p_ch, "name: %s", pfs_ca_info->name) != 1) {
180219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
181219820Sjeff			"__parse_ca_info_file: ERR 5207: "
182219820Sjeff			"Fail to parse name in info file:(%s).\n", p_ch);
183219820Sjeff		goto Exit;
184219820Sjeff	}
185219820Sjeff
186219820Sjeff	/* get the guid of the HCA */
187219820Sjeff	if (!(p_ch = strstr(file_buffer, "node GUID:"))) {
188219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
189219820Sjeff			"__parse_ca_info_file: ERR 5208: "
190219820Sjeff			"Fail to obtain GUID in info file:(%s).\n",
191219820Sjeff			file_buffer);
192219820Sjeff		goto Exit;
193219820Sjeff	}
194219820Sjeff	if (sscanf(p_ch, "node GUID: %x:%x:%x:%x", &g1, &g2, &g3, &g4) != 4) {
195219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
196219820Sjeff			"__parse_ca_info_file: ERR 5209: "
197219820Sjeff			"Fail to parse GUID in info file:(%s).\n", p_ch);
198219820Sjeff		goto Exit;
199219820Sjeff	}
200219820Sjeff	pfs_ca_info->guid = (uint64_t) g1 << 48 | (uint64_t) g1 << 32
201219820Sjeff	    | (uint64_t) g1 << 16 | (uint64_t) g3;
202219820Sjeff
203219820Sjeff	/* obtain number of ports */
204219820Sjeff	if (!(p_ch = strstr(file_buffer, "ports:"))) {
205219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
206219820Sjeff			"__parse_ca_info_file: ERR 5210: "
207219820Sjeff			"Fail to obtain number of ports in info file:(%s).\n",
208219820Sjeff			file_buffer);
209219820Sjeff		goto Exit;
210219820Sjeff	}
211219820Sjeff	if (sscanf(p_ch, "ports: %d", &num_ports) != 1) {
212219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
213219820Sjeff			"__parse_ca_info_file: ERR 5211: "
214219820Sjeff			"Fail to parse num ports in info file:(%s).\n", p_ch);
215219820Sjeff		goto Exit;
216219820Sjeff	}
217219820Sjeff	pfs_ca_info->num_ports = num_ports;
218219820Sjeff
219219820Sjeff	osm_log(p_vend->p_log, OSM_LOG_DEBUG,
220219820Sjeff		"__parse_ca_info_file: "
221219820Sjeff		"CA1 = name:%s guid:0x%016llx ports:%d\n",
222219820Sjeff		pfs_ca_info->name, pfs_ca_info->guid, pfs_ca_info->num_ports);
223219820Sjeff
224219820Sjeff	status = IB_SUCCESS;
225219820SjeffExit:
226219820Sjeff	OSM_LOG_EXIT(p_vend->p_log);
227219820Sjeff	return status;
228219820Sjeff}
229219820Sjeff
230219820Sjeff/*
231219820Sjeff  state:         ACTIVE
232219820Sjeff  LID:           0x0001
233219820Sjeff  LMC:           0x0000
234219820Sjeff  SM LID:        0x0001
235219820Sjeff  SM SL:         0x0000
236219820Sjeff  Capabilities:  IsSM
237219820Sjeff  IsTrapSupported
238219820Sjeff  IsAutomaticMigrationSupported
239219820Sjeff  IsSLMappingSupported
240219820Sjeff  IsLEDInfoSupported
241219820Sjeff  IsSystemImageGUIDSupported
242219820Sjeff  IsVendorClassSupported
243219820Sjeff  IsCapabilityMaskNoticeSupported
244219820Sjeff*/
245219820Sjefftypedef struct _pfs_port_info {
246219820Sjeff	uint8_t state;
247219820Sjeff	uint16_t lid;
248219820Sjeff	uint8_t lmc;
249219820Sjeff	uint16_t sm_lid;
250219820Sjeff	uint8_t sm_sl;
251219820Sjeff} pfs_port_info_t;
252219820Sjeff
253219820Sjeff/**********************************************************************
254219820Sjeff * Parse the Port Info file available in /proc/infiniband/core/caN/portM/info
255219820Sjeff * Port num is 1..N
256219820Sjeff **********************************************************************/
257219820Sjeffstatic ib_api_status_t
258219820Sjeff__parse_port_info_file(IN osm_vendor_t * const p_vend,
259219820Sjeff		       IN uint32_t hca_idx,
260219820Sjeff		       IN uint8_t port_num, OUT pfs_port_info_t * pfs_port_info)
261219820Sjeff{
262219820Sjeff	ib_api_status_t status = IB_ERROR;
263219820Sjeff	int info_file;
264219820Sjeff	char file_name[256];
265219820Sjeff	char file_buffer[3200];
266219820Sjeff	char state[12];
267219820Sjeff	char *p_ch;
268219820Sjeff	int lid, sm_lid, lmc, sm_sl;
269219820Sjeff	uint32_t len;
270219820Sjeff
271219820Sjeff	OSM_LOG_ENTER(p_vend->p_log);
272219820Sjeff
273219820Sjeff	osm_log(p_vend->p_log, OSM_LOG_DEBUG,
274219820Sjeff		"__parse_port_info_file: "
275219820Sjeff		"Parsing Proc File System Port Info CA %d Port %d.\n", hca_idx,
276219820Sjeff		port_num);
277219820Sjeff
278219820Sjeff	/* we use the proc file system so we must be able to open the info file .. */
279219820Sjeff	sprintf(file_name, "/proc/infiniband/core/ca%d/port%d/info", hca_idx,
280219820Sjeff		port_num);
281219820Sjeff	info_file = open(file_name, O_RDONLY);
282219820Sjeff	if (!info_file) {
283219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
284219820Sjeff			"__parse_port_info_file: ERR 5212: "
285219820Sjeff			"Fail to open HCA:%d Port:%d info file:(%s).\n",
286219820Sjeff			hca_idx, port_num, file_name);
287219820Sjeff		goto Exit;
288219820Sjeff	}
289219820Sjeff
290219820Sjeff	/* read in the file */
291219820Sjeff	len = read(info_file, file_buffer, 3200);
292219820Sjeff	close(info_file);
293219820Sjeff	file_buffer[len] = '\0';
294219820Sjeff
295219820Sjeff	/*
296219820Sjeff	   parse the file ...
297219820Sjeff	   state:         ACTIVE
298219820Sjeff	   LID:           0x0001
299219820Sjeff	   LMC:           0x0000
300219820Sjeff	   SM LID:        0x0001
301219820Sjeff	   SM SL:         0x0000
302219820Sjeff	   ...
303219820Sjeff	 */
304219820Sjeff	if (!(p_ch = strstr(file_buffer, "state:"))) {
305219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
306219820Sjeff			"__parse_port_info_file: ERR 5213: "
307219820Sjeff			"Fail to obtain port state. In info file:(%s).\n",
308219820Sjeff			file_buffer);
309219820Sjeff		goto Exit;
310219820Sjeff	}
311219820Sjeff	if (sscanf(p_ch, "state: %s", state) != 1) {
312219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
313219820Sjeff			"__parse_port_info_file: ERR 5214: "
314219820Sjeff			"Fail to parse state from info file:(%s).\n", p_ch);
315219820Sjeff		goto Exit;
316219820Sjeff	}
317219820Sjeff
318219820Sjeff	if (!strcmp(state, "ACTIVE"))
319219820Sjeff		pfs_port_info->state = IB_LINK_ACTIVE;
320219820Sjeff	else if (!strcmp(state, "DOWN"))
321219820Sjeff		pfs_port_info->state = IB_LINK_DOWN;
322219820Sjeff	else if (!strcmp(state, "INIT"))
323219820Sjeff		pfs_port_info->state = IB_LINK_INIT;
324219820Sjeff	else if (!strcmp(state, "ARMED"))
325219820Sjeff		pfs_port_info->state = IB_LINK_ARMED;
326219820Sjeff	else
327219820Sjeff		pfs_port_info->state = 0;
328219820Sjeff
329219820Sjeff	/* get lid */
330219820Sjeff	if (!(p_ch = strstr(file_buffer, "LID:"))) {
331219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
332219820Sjeff			"__parse_port_info_file: ERR 5215: "
333219820Sjeff			"Fail to obtain port lid. In info file:(%s).\n",
334219820Sjeff			file_buffer);
335219820Sjeff		goto Exit;
336219820Sjeff	}
337219820Sjeff	if (sscanf(p_ch, "LID: %x", &lid) != 1) {
338219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
339219820Sjeff			"__parse_port_info_file: ERR 5216: "
340219820Sjeff			"Fail to parse lid from info file:(%s).\n", p_ch);
341219820Sjeff		goto Exit;
342219820Sjeff	}
343219820Sjeff	pfs_port_info->lid = lid;
344219820Sjeff	/* get LMC */
345219820Sjeff	if (!(p_ch = strstr(file_buffer, "LMC:"))) {
346219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
347219820Sjeff			"__parse_port_info_file: ERR 5217: "
348219820Sjeff			"Fail to obtain port LMC. In info file:(%s).\n",
349219820Sjeff			file_buffer);
350219820Sjeff		goto Exit;
351219820Sjeff	}
352219820Sjeff	if (sscanf(p_ch, "LMC: %x", &lmc) != 1) {
353219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
354219820Sjeff			"__parse_port_info_file: ERR 5218: "
355219820Sjeff			"Fail to parse LMC from info file:(%s).\n", p_ch);
356219820Sjeff		goto Exit;
357219820Sjeff	}
358219820Sjeff	pfs_port_info->lmc = lmc;
359219820Sjeff
360219820Sjeff	/* get SM LID */
361219820Sjeff	if (!(p_ch = strstr(file_buffer, "SM LID:"))) {
362219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
363219820Sjeff			"__parse_port_info_file: ERR 5219: "
364219820Sjeff			"Fail to obtain port SM LID. In info file:(%s).\n",
365219820Sjeff			file_buffer);
366219820Sjeff		goto Exit;
367219820Sjeff	}
368219820Sjeff	if (sscanf(p_ch, "SM LID: %x", &sm_lid) != 1) {
369219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
370219820Sjeff			"__parse_port_info_file: ERR 5220: "
371219820Sjeff			"Fail to parse SM LID from info file:(%s).\n", p_ch);
372219820Sjeff		goto Exit;
373219820Sjeff	}
374219820Sjeff	pfs_port_info->sm_lid = sm_lid;
375219820Sjeff
376219820Sjeff	/* get SM LID */
377219820Sjeff	if (!(p_ch = strstr(file_buffer, "SM SL:"))) {
378219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
379219820Sjeff			"__parse_port_info_file: ERR 5221: "
380219820Sjeff			"Fail to obtain port SM SL. In info file:(%s).\n",
381219820Sjeff			file_buffer);
382219820Sjeff		goto Exit;
383219820Sjeff	}
384219820Sjeff	if (sscanf(p_ch, "SM SL: %x", &sm_sl) != 1) {
385219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
386219820Sjeff			"__parse_port_info_file: ERR 5222: "
387219820Sjeff			"Fail to parse SM SL from info file:(%s).\n", p_ch);
388219820Sjeff		goto Exit;
389219820Sjeff	}
390219820Sjeff	pfs_port_info->sm_sl = sm_sl;
391219820Sjeff	osm_log(p_vend->p_log, OSM_LOG_DEBUG,
392219820Sjeff		"__parse_port_info_file:  "
393219820Sjeff		"Obtained Port:%d = state:%d, lid:0x%04X, lmc:%d, sm_lid:0x%04X, sm_sl:%d\n",
394219820Sjeff		port_num, pfs_port_info->state, pfs_port_info->lid,
395219820Sjeff		pfs_port_info->lmc, pfs_port_info->sm_lid,
396219820Sjeff		pfs_port_info->sm_sl);
397219820Sjeff
398219820Sjeff	status = IB_SUCCESS;
399219820SjeffExit:
400219820Sjeff	OSM_LOG_EXIT(p_vend->p_log);
401219820Sjeff	return status;
402219820Sjeff}
403219820Sjeff
404219820Sjeff/**********************************************************************
405219820Sjeff * Parse the port guid_tbl file to obtain the port guid.
406219820Sjeff * File format is:
407219820Sjeff * [  0] fe80:0000:0000:0000:0002:c900:0120:3472
408219820Sjeff **********************************************************************/
409219820Sjeffstatic ib_api_status_t
410219820Sjeff__get_port_guid_from_port_gid_tbl(IN osm_vendor_t * const p_vend,
411219820Sjeff				  IN uint32_t hca_idx,
412219820Sjeff				  IN uint8_t port_num, OUT uint64_t * port_guid)
413219820Sjeff{
414219820Sjeff	ib_api_status_t status = IB_ERROR;
415219820Sjeff	int info_file;
416219820Sjeff	char file_name[256];
417219820Sjeff	char file_buffer[3200];
418219820Sjeff	char *p_ch;
419219820Sjeff	int g[8];
420219820Sjeff	uint32_t len;
421219820Sjeff
422219820Sjeff	OSM_LOG_ENTER(p_vend->p_log);
423219820Sjeff
424219820Sjeff	osm_log(p_vend->p_log, OSM_LOG_DEBUG,
425219820Sjeff		"__get_port_guid_from_port_gid_tbl: "
426219820Sjeff		"Parsing Proc File System Port Guid Table CA %d Port %d.\n",
427219820Sjeff		hca_idx, port_num);
428219820Sjeff
429219820Sjeff	/* we use the proc file system so we must be able to open the info file .. */
430219820Sjeff	sprintf(file_name, "/proc/infiniband/core/ca%d/port%d/gid_table",
431219820Sjeff		hca_idx, port_num);
432219820Sjeff	info_file = open(file_name, O_RDONLY);
433219820Sjeff	if (!info_file) {
434219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
435219820Sjeff			"__get_port_guid_from_port_gid_tbl: ERR 5223: "
436219820Sjeff			"Fail to open HCA:%d Port:%d gid_table file:(%s).\n",
437219820Sjeff			hca_idx, port_num, file_name);
438219820Sjeff		goto Exit;
439219820Sjeff	}
440219820Sjeff
441219820Sjeff	/* read in the file */
442219820Sjeff	len = read(info_file, file_buffer, 3200);
443219820Sjeff	close(info_file);
444219820Sjeff	file_buffer[len] = '\0';
445219820Sjeff
446219820Sjeff	/*
447219820Sjeff	   parse the file ...
448219820Sjeff	   [  0] fe80:0000:0000:0000:0002:c900:0120:3472
449219820Sjeff	   ...
450219820Sjeff	 */
451219820Sjeff	if (!(p_ch = strstr(file_buffer, "[  0]"))) {
452219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
453219820Sjeff			"__get_port_guid_from_port_gid_tbl: ERR 5224: "
454219820Sjeff			"Fail to obtain first gid index. In gid_table file:(%s).\n",
455219820Sjeff			file_buffer);
456219820Sjeff		goto Exit;
457219820Sjeff	}
458219820Sjeff	if (sscanf(p_ch + 6, "%x:%x:%x:%x:%x:%x:%x:%x",
459219820Sjeff		   &g[7], &g[6], &g[5], &g[4], &g[3], &g[2], &g[1], &g[0]) != 8)
460219820Sjeff	{
461219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
462219820Sjeff			"__get_port_guid_from_port_gid_tbl: ERR 5225: "
463219820Sjeff			"Fail to parse gid from gid_table file:(%s).\n", p_ch);
464219820Sjeff		goto Exit;
465219820Sjeff	}
466219820Sjeff
467219820Sjeff	*port_guid =
468219820Sjeff	    (uint64_t) g[3] << 48 | (uint64_t) g[2] << 32 | (uint64_t) g[1] <<
469219820Sjeff	    16 | g[0];
470219820Sjeff	status = IB_SUCCESS;
471219820SjeffExit:
472219820Sjeff	OSM_LOG_EXIT(p_vend->p_log);
473219820Sjeff	return status;
474219820Sjeff}
475219820Sjeff
476219820Sjeff/**********************************************************************
477219820Sjeff * Initialize an Info Struct for the Given HCA by its index 1..N
478219820Sjeff **********************************************************************/
479219820Sjeffstatic ib_api_status_t
480219820Sjeff__osm_ca_info_init(IN osm_vendor_t * const p_vend,
481219820Sjeff		   IN uint32_t const idx, OUT osm_ca_info_t * const p_ca_info)
482219820Sjeff{
483219820Sjeff	ib_api_status_t status = IB_ERROR;
484219820Sjeff	uint8_t port_num;
485219820Sjeff	uint64_t port_guid;
486219820Sjeff
487219820Sjeff	pfs_ca_info_t pfs_ca_info;
488219820Sjeff
489219820Sjeff	OSM_LOG_ENTER(p_vend->p_log);
490219820Sjeff
491219820Sjeff	/* parse the CA info file */
492219820Sjeff	if (__parse_ca_info_file(p_vend, idx, &pfs_ca_info) != IB_SUCCESS)
493219820Sjeff		goto Exit;
494219820Sjeff
495219820Sjeff	p_ca_info->guid = cl_hton64(pfs_ca_info.guid);
496219820Sjeff
497219820Sjeff	/* set size of attributes and allocate them */
498219820Sjeff	p_ca_info->attr_size = 1;
499219820Sjeff	p_ca_info->p_attr = (ib_ca_attr_t *) malloc(sizeof(ib_ca_attr_t));
500219820Sjeff
501219820Sjeff	p_ca_info->p_attr->ca_guid = p_ca_info->guid;
502219820Sjeff	p_ca_info->p_attr->num_ports = pfs_ca_info.num_ports;
503219820Sjeff
504219820Sjeff	/* now obtain the attributes of the ports */
505219820Sjeff	p_ca_info->p_attr->p_port_attr =
506219820Sjeff	    (ib_port_attr_t *) malloc(pfs_ca_info.num_ports *
507219820Sjeff				      sizeof(ib_port_attr_t));
508219820Sjeff
509219820Sjeff	/* get all the ports info */
510219820Sjeff	for (port_num = 1; port_num <= pfs_ca_info.num_ports; port_num++) {
511219820Sjeff		pfs_port_info_t pfs_port_info;
512219820Sjeff		/* query the port attributes */
513219820Sjeff		if (__parse_port_info_file
514219820Sjeff		    (p_vend, idx, port_num, &pfs_port_info)) {
515219820Sjeff			osm_log(p_vend->p_log, OSM_LOG_ERROR,
516219820Sjeff				"__osm_ca_info_init: ERR 5226: "
517219820Sjeff				"Fail to get HCA:%d Port:%d Attributes.\n", idx,
518219820Sjeff				port_num);
519219820Sjeff			goto Exit;
520219820Sjeff		}
521219820Sjeff
522219820Sjeff		/* HACK: the lids should have been converted to network but the rest of the code
523219820Sjeff		   is wrong and provdes them as is (host order) - so we stick with it. */
524219820Sjeff		p_ca_info->p_attr->p_port_attr[port_num - 1].lid =
525219820Sjeff		    pfs_port_info.lid;
526219820Sjeff		p_ca_info->p_attr->p_port_attr[port_num - 1].link_state =
527219820Sjeff		    pfs_port_info.state;
528219820Sjeff		p_ca_info->p_attr->p_port_attr[port_num - 1].sm_lid =
529219820Sjeff		    pfs_port_info.sm_lid;
530219820Sjeff
531219820Sjeff		/* get the port guid */
532219820Sjeff		if (__get_port_guid_from_port_gid_tbl
533219820Sjeff		    (p_vend, idx, port_num, &port_guid)) {
534219820Sjeff			osm_log(p_vend->p_log, OSM_LOG_ERROR,
535219820Sjeff				"__osm_ca_info_init: ERR 5227: "
536219820Sjeff				"Fail to get HCA:%d Port:%d Guid.\n", idx,
537219820Sjeff				port_num);
538219820Sjeff			goto Exit;
539219820Sjeff		}
540219820Sjeff		p_ca_info->p_attr->p_port_attr[port_num - 1].port_guid =
541219820Sjeff		    cl_hton64(port_guid);
542219820Sjeff	}
543219820Sjeff
544219820Sjeff	status = IB_SUCCESS;
545219820SjeffExit:
546219820Sjeff	OSM_LOG_EXIT(p_vend->p_log);
547219820Sjeff	return (status);
548219820Sjeff}
549219820Sjeff
550219820Sjeff/**********************************************************************
551219820Sjeff **********************************************************************/
552219820Sjeffvoid
553219820Sjeffosm_ca_info_destroy(IN osm_vendor_t * const p_vend,
554219820Sjeff		    IN osm_ca_info_t * const p_ca_info, IN uint8_t num_ca)
555219820Sjeff{
556219820Sjeff	osm_ca_info_t *p_ca;
557219820Sjeff	uint8_t i;
558219820Sjeff
559219820Sjeff	OSM_LOG_ENTER(p_vend->p_log);
560219820Sjeff
561219820Sjeff	for (i = 0; i < num_ca; i++) {
562219820Sjeff		p_ca = &p_ca_info[i];
563219820Sjeff
564219820Sjeff		if (NULL != p_ca->p_attr) {
565219820Sjeff			if (0 != p_ca->p_attr->num_ports) {
566219820Sjeff				free(p_ca->p_attr->p_port_attr);
567219820Sjeff			}
568219820Sjeff
569219820Sjeff			free(p_ca->p_attr);
570219820Sjeff		}
571219820Sjeff	}
572219820Sjeff
573219820Sjeff	free(p_ca_info);
574219820Sjeff
575219820Sjeff	OSM_LOG_EXIT(p_vend->p_log);
576219820Sjeff}
577219820Sjeff
578219820Sjeff/**********************************************************************
579219820Sjeff * Fill in the array of port_attr with all available ports on ALL the
580219820Sjeff * avilable CAs on this machine.
581219820Sjeff **********************************************************************/
582219820Sjeffib_api_status_t
583219820Sjeffosm_vendor_get_all_port_attr(IN osm_vendor_t * const p_vend,
584219820Sjeff			     IN ib_port_attr_t * const p_attr_array,
585219820Sjeff			     IN uint32_t * const p_num_ports)
586219820Sjeff{
587219820Sjeff	ib_api_status_t status = IB_SUCCESS;
588219820Sjeff
589219820Sjeff	uint32_t caIdx;
590219820Sjeff	uint32_t ca_count = 0;
591219820Sjeff	uint32_t port_count = 0;
592219820Sjeff	uint8_t port_num;
593219820Sjeff	uint32_t total_ports = 0;
594219820Sjeff	osm_ca_info_t *p_ca_infos = NULL;
595219820Sjeff	uint32_t attr_array_sz = *p_num_ports;
596219820Sjeff
597219820Sjeff	OSM_LOG_ENTER(p_vend->p_log);
598219820Sjeff
599219820Sjeff	CL_ASSERT(p_vend);
600219820Sjeff
601219820Sjeff	/* determine the number of CA's */
602219820Sjeff	ca_count = __hca_pfs_get_num_cas();
603219820Sjeff	if (!ca_count) {
604219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
605219820Sjeff			"osm_vendor_get_all_port_attr: ERR 5228: "
606219820Sjeff			"Fail to get Any CA Ids.\n");
607219820Sjeff		goto Exit;
608219820Sjeff	}
609219820Sjeff
610219820Sjeff	/* Allocate an array big enough to hold the ca info objects */
611219820Sjeff	p_ca_infos = malloc(ca_count * sizeof(osm_ca_info_t));
612219820Sjeff	if (p_ca_infos == NULL) {
613219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
614219820Sjeff			"osm_vendor_get_all_port_attr: ERR 5229: "
615219820Sjeff			"Unable to allocate CA information array.\n");
616219820Sjeff		goto Exit;
617219820Sjeff	}
618219820Sjeff
619219820Sjeff	memset(p_ca_infos, 0, ca_count * sizeof(osm_ca_info_t));
620219820Sjeff
621219820Sjeff	/*
622219820Sjeff	 * For each CA, retrieve the CA info attributes
623219820Sjeff	 */
624219820Sjeff	for (caIdx = 1; caIdx <= ca_count; caIdx++) {
625219820Sjeff		status =
626219820Sjeff		    __osm_ca_info_init(p_vend, caIdx, &p_ca_infos[caIdx - 1]);
627219820Sjeff		if (status != IB_SUCCESS) {
628219820Sjeff			osm_log(p_vend->p_log, OSM_LOG_ERROR,
629219820Sjeff				"osm_vendor_get_all_port_attr: ERR 5230: "
630219820Sjeff				"Unable to initialize CA Info object (%s).\n",
631219820Sjeff				ib_get_err_str(status));
632219820Sjeff			goto Exit;
633219820Sjeff		}
634219820Sjeff		total_ports += p_ca_infos[caIdx - 1].p_attr->num_ports;
635219820Sjeff	}
636219820Sjeff
637219820Sjeff	*p_num_ports = total_ports;
638219820Sjeff	osm_log(p_vend->p_log, OSM_LOG_DEBUG,
639219820Sjeff		"osm_vendor_get_all_port_attr: total ports:%u \n", total_ports);
640219820Sjeff
641219820Sjeff	/*
642219820Sjeff	 * If the user supplied enough storage, return the port guids,
643219820Sjeff	 * otherwise, return the appropriate error.
644219820Sjeff	 */
645219820Sjeff	if (attr_array_sz >= total_ports) {
646219820Sjeff		for (caIdx = 1; caIdx <= ca_count; caIdx++) {
647219820Sjeff			uint32_t num_ports;
648219820Sjeff
649219820Sjeff			num_ports = p_ca_infos[caIdx - 1].p_attr->num_ports;
650219820Sjeff
651219820Sjeff			for (port_num = 0; port_num < num_ports; port_num++) {
652219820Sjeff				p_attr_array[port_count] =
653219820Sjeff				    *__osm_ca_info_get_port_attr_ptr(&p_ca_infos
654219820Sjeff								     [caIdx -
655219820Sjeff								      1],
656219820Sjeff								     port_num);
657219820Sjeff				port_count++;
658219820Sjeff			}
659219820Sjeff		}
660219820Sjeff	} else {
661219820Sjeff		status = IB_INSUFFICIENT_MEMORY;
662219820Sjeff		goto Exit;
663219820Sjeff	}
664219820Sjeff
665219820Sjeff	status = IB_SUCCESS;
666219820Sjeff
667219820SjeffExit:
668219820Sjeff	if (p_ca_infos) {
669219820Sjeff		osm_ca_info_destroy(p_vend, p_ca_infos, ca_count);
670219820Sjeff	}
671219820Sjeff
672219820Sjeff	OSM_LOG_EXIT(p_vend->p_log);
673219820Sjeff	return (status);
674219820Sjeff}
675219820Sjeff
676219820Sjeff/**********************************************************************
677219820Sjeff * Given the vendor obj and a port guid
678219820Sjeff * return the ca id and port number that have that guid
679219820Sjeff **********************************************************************/
680219820Sjeff
681219820Sjeffib_api_status_t
682219820Sjeffosm_vendor_get_guid_ca_and_port(IN osm_vendor_t * const p_vend,
683219820Sjeff				IN ib_net64_t const guid,
684219820Sjeff				OUT uint32_t * p_hca_hndl,
685219820Sjeff				OUT char *p_hca_id,
686219820Sjeff				OUT uint8_t * p_hca_idx,
687219820Sjeff				OUT uint32_t * p_port_num)
688219820Sjeff{
689219820Sjeff	uint32_t caIdx;
690219820Sjeff	uint32_t ca_count = 0;
691219820Sjeff	uint8_t port_num;
692219820Sjeff	ib_api_status_t status = IB_ERROR;
693219820Sjeff
694219820Sjeff	OSM_LOG_ENTER(p_vend->p_log);
695219820Sjeff
696219820Sjeff	CL_ASSERT(p_vend);
697219820Sjeff
698219820Sjeff	/* determine the number of CA's */
699219820Sjeff	ca_count = __hca_pfs_get_num_cas();
700219820Sjeff	if (!ca_count) {
701219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
702219820Sjeff			"osm_vendor_get_guid_ca_and_port: ERR 5231: "
703219820Sjeff			"Fail to get Any CA Ids.\n");
704219820Sjeff		goto Exit;
705219820Sjeff	}
706219820Sjeff
707219820Sjeff	/*
708219820Sjeff	 * For each CA, retrieve the CA info attributes
709219820Sjeff	 */
710219820Sjeff	for (caIdx = 1; caIdx <= ca_count; caIdx++) {
711219820Sjeff		pfs_ca_info_t pfs_ca_info;
712219820Sjeff		if (__parse_ca_info_file(p_vend, caIdx, &pfs_ca_info) ==
713219820Sjeff		    IB_SUCCESS) {
714219820Sjeff			/* get all the ports info */
715219820Sjeff			for (port_num = 1; port_num <= pfs_ca_info.num_ports;
716219820Sjeff			     port_num++) {
717219820Sjeff				uint64_t port_guid;
718219820Sjeff				if (!__get_port_guid_from_port_gid_tbl
719219820Sjeff				    (p_vend, caIdx, port_num, &port_guid)) {
720219820Sjeff					if (cl_hton64(port_guid) == guid) {
721219820Sjeff						osm_log(p_vend->p_log,
722219820Sjeff							OSM_LOG_DEBUG,
723219820Sjeff							"osm_vendor_get_guid_ca_and_port: "
724219820Sjeff							"Found Matching guid on HCA:%d Port:%d.\n",
725219820Sjeff							caIdx, port_num);
726219820Sjeff						strcpy(p_hca_id,
727219820Sjeff						       pfs_ca_info.name);
728219820Sjeff						*p_port_num = port_num;
729219820Sjeff						*p_hca_idx = caIdx - 1;
730219820Sjeff						*p_hca_hndl = 0;
731219820Sjeff						status = IB_SUCCESS;
732219820Sjeff						goto Exit;
733219820Sjeff					}
734219820Sjeff				}
735219820Sjeff			}
736219820Sjeff		}
737219820Sjeff	}
738219820Sjeff
739219820Sjeff	osm_log(p_vend->p_log, OSM_LOG_ERROR,
740219820Sjeff		"osm_vendor_get_guid_ca_and_port: ERR 5232: "
741219820Sjeff		"Fail to find HCA and Port for Port Guid 0x%" PRIx64 "\n",
742219820Sjeff		cl_ntoh64(guid));
743219820Sjeff	status = IB_INVALID_GUID;
744219820Sjeff
745219820SjeffExit:
746219820Sjeff
747219820Sjeff	OSM_LOG_EXIT(p_vend->p_log);
748219820Sjeff	return (status);
749219820Sjeff}
750219820Sjeff
751219820Sjeff#endif
752