xref: /freebsd/contrib/ofed/libibnetdisc/chassis.c (revision 87181516ef48be852d5e5fee53c6e0dbfc62f21e)
1*d6b92ffaSHans Petter Selasky /*
2*d6b92ffaSHans Petter Selasky  * Copyright (c) 2004-2009 Voltaire Inc.  All rights reserved.
3*d6b92ffaSHans Petter Selasky  * Copyright (c) 2007 Xsigo Systems Inc.  All rights reserved.
4*d6b92ffaSHans Petter Selasky  * Copyright (c) 2008 Lawrence Livermore National Lab.  All rights reserved.
5*d6b92ffaSHans Petter Selasky  * Copyright (c) 2010 HNR Consulting.  All rights reserved.
6*d6b92ffaSHans Petter Selasky  *
7*d6b92ffaSHans Petter Selasky  * This software is available to you under a choice of one of two
8*d6b92ffaSHans Petter Selasky  * licenses.  You may choose to be licensed under the terms of the GNU
9*d6b92ffaSHans Petter Selasky  * General Public License (GPL) Version 2, available from the file
10*d6b92ffaSHans Petter Selasky  * COPYING in the main directory of this source tree, or the
11*d6b92ffaSHans Petter Selasky  * OpenIB.org BSD license below:
12*d6b92ffaSHans Petter Selasky  *
13*d6b92ffaSHans Petter Selasky  *     Redistribution and use in source and binary forms, with or
14*d6b92ffaSHans Petter Selasky  *     without modification, are permitted provided that the following
15*d6b92ffaSHans Petter Selasky  *     conditions are met:
16*d6b92ffaSHans Petter Selasky  *
17*d6b92ffaSHans Petter Selasky  *      - Redistributions of source code must retain the above
18*d6b92ffaSHans Petter Selasky  *        copyright notice, this list of conditions and the following
19*d6b92ffaSHans Petter Selasky  *        disclaimer.
20*d6b92ffaSHans Petter Selasky  *
21*d6b92ffaSHans Petter Selasky  *      - Redistributions in binary form must reproduce the above
22*d6b92ffaSHans Petter Selasky  *        copyright notice, this list of conditions and the following
23*d6b92ffaSHans Petter Selasky  *        disclaimer in the documentation and/or other materials
24*d6b92ffaSHans Petter Selasky  *        provided with the distribution.
25*d6b92ffaSHans Petter Selasky  *
26*d6b92ffaSHans Petter Selasky  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27*d6b92ffaSHans Petter Selasky  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28*d6b92ffaSHans Petter Selasky  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29*d6b92ffaSHans Petter Selasky  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
30*d6b92ffaSHans Petter Selasky  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
31*d6b92ffaSHans Petter Selasky  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
32*d6b92ffaSHans Petter Selasky  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33*d6b92ffaSHans Petter Selasky  * SOFTWARE.
34*d6b92ffaSHans Petter Selasky  *
35*d6b92ffaSHans Petter Selasky  */
36*d6b92ffaSHans Petter Selasky 
37*d6b92ffaSHans Petter Selasky /*========================================================*/
38*d6b92ffaSHans Petter Selasky /*               FABRIC SCANNER SPECIFIC DATA             */
39*d6b92ffaSHans Petter Selasky /*========================================================*/
40*d6b92ffaSHans Petter Selasky 
41*d6b92ffaSHans Petter Selasky #if HAVE_CONFIG_H
42*d6b92ffaSHans Petter Selasky #include <config.h>
43*d6b92ffaSHans Petter Selasky #endif				/* HAVE_CONFIG_H */
44*d6b92ffaSHans Petter Selasky 
45*d6b92ffaSHans Petter Selasky #include <stdlib.h>
46*d6b92ffaSHans Petter Selasky #include <inttypes.h>
47*d6b92ffaSHans Petter Selasky 
48*d6b92ffaSHans Petter Selasky #include <infiniband/mad.h>
49*d6b92ffaSHans Petter Selasky 
50*d6b92ffaSHans Petter Selasky #include "internal.h"
51*d6b92ffaSHans Petter Selasky #include "chassis.h"
52*d6b92ffaSHans Petter Selasky 
53*d6b92ffaSHans Petter Selasky static char *ChassisTypeStr[] =
54*d6b92ffaSHans Petter Selasky { "", "ISR9288", "ISR9096", "ISR2012", "ISR2004", "ISR4700", "ISR4200" };
55*d6b92ffaSHans Petter Selasky static char *ChassisSlotTypeStr[] = { "", "Line", "Spine", "SRBD" };
56*d6b92ffaSHans Petter Selasky 
57*d6b92ffaSHans Petter Selasky typedef struct chassis_scan {
58*d6b92ffaSHans Petter Selasky 	ibnd_chassis_t *first_chassis;
59*d6b92ffaSHans Petter Selasky 	ibnd_chassis_t *current_chassis;
60*d6b92ffaSHans Petter Selasky 	ibnd_chassis_t *last_chassis;
61*d6b92ffaSHans Petter Selasky } chassis_scan_t;
62*d6b92ffaSHans Petter Selasky 
ibnd_get_chassis_type(ibnd_node_t * node)63*d6b92ffaSHans Petter Selasky char *ibnd_get_chassis_type(ibnd_node_t * node)
64*d6b92ffaSHans Petter Selasky {
65*d6b92ffaSHans Petter Selasky 	int chassis_type;
66*d6b92ffaSHans Petter Selasky 
67*d6b92ffaSHans Petter Selasky 	if (!node) {
68*d6b92ffaSHans Petter Selasky 		IBND_DEBUG("node parameter NULL\n");
69*d6b92ffaSHans Petter Selasky 		return NULL;
70*d6b92ffaSHans Petter Selasky 	}
71*d6b92ffaSHans Petter Selasky 
72*d6b92ffaSHans Petter Selasky 	if (!node->chassis)
73*d6b92ffaSHans Petter Selasky 		return NULL;
74*d6b92ffaSHans Petter Selasky 
75*d6b92ffaSHans Petter Selasky 	chassis_type = mad_get_field(node->info, 0, IB_NODE_VENDORID_F);
76*d6b92ffaSHans Petter Selasky 
77*d6b92ffaSHans Petter Selasky 	switch (chassis_type)
78*d6b92ffaSHans Petter Selasky 	{
79*d6b92ffaSHans Petter Selasky 		case VTR_VENDOR_ID: /* Voltaire chassis */
80*d6b92ffaSHans Petter Selasky 		{
81*d6b92ffaSHans Petter Selasky 			if (node->ch_type == UNRESOLVED_CT || node->ch_type > ISR4200_CT)
82*d6b92ffaSHans Petter Selasky 				return NULL;
83*d6b92ffaSHans Petter Selasky 			return ChassisTypeStr[node->ch_type];
84*d6b92ffaSHans Petter Selasky 		}
85*d6b92ffaSHans Petter Selasky 		case MLX_VENDOR_ID:
86*d6b92ffaSHans Petter Selasky 		{
87*d6b92ffaSHans Petter Selasky 			if (node->ch_type_str[0] == '\0')
88*d6b92ffaSHans Petter Selasky 				return NULL;
89*d6b92ffaSHans Petter Selasky 			return node->ch_type_str;
90*d6b92ffaSHans Petter Selasky 		}
91*d6b92ffaSHans Petter Selasky 		default:
92*d6b92ffaSHans Petter Selasky 		{
93*d6b92ffaSHans Petter Selasky 			break;
94*d6b92ffaSHans Petter Selasky 		}
95*d6b92ffaSHans Petter Selasky 	}
96*d6b92ffaSHans Petter Selasky 	return NULL;
97*d6b92ffaSHans Petter Selasky }
98*d6b92ffaSHans Petter Selasky 
ibnd_get_chassis_slot_str(ibnd_node_t * node,char * str,size_t size)99*d6b92ffaSHans Petter Selasky char *ibnd_get_chassis_slot_str(ibnd_node_t * node, char *str, size_t size)
100*d6b92ffaSHans Petter Selasky {
101*d6b92ffaSHans Petter Selasky 	int vendor_id;
102*d6b92ffaSHans Petter Selasky 
103*d6b92ffaSHans Petter Selasky 	if (!node) {
104*d6b92ffaSHans Petter Selasky 		IBND_DEBUG("node parameter NULL\n");
105*d6b92ffaSHans Petter Selasky 		return NULL;
106*d6b92ffaSHans Petter Selasky 	}
107*d6b92ffaSHans Petter Selasky 
108*d6b92ffaSHans Petter Selasky 	/* Currently, only if Voltaire or Mellanox chassis */
109*d6b92ffaSHans Petter Selasky 	vendor_id = mad_get_field(node->info, 0,IB_NODE_VENDORID_F);
110*d6b92ffaSHans Petter Selasky 
111*d6b92ffaSHans Petter Selasky 	if ((vendor_id != VTR_VENDOR_ID) && (vendor_id != MLX_VENDOR_ID))
112*d6b92ffaSHans Petter Selasky 		return NULL;
113*d6b92ffaSHans Petter Selasky 	if (!node->chassis)
114*d6b92ffaSHans Petter Selasky 		return NULL;
115*d6b92ffaSHans Petter Selasky 	if (node->ch_slot == UNRESOLVED_CS || node->ch_slot > SRBD_CS)
116*d6b92ffaSHans Petter Selasky 		return NULL;
117*d6b92ffaSHans Petter Selasky 	if (!str)
118*d6b92ffaSHans Petter Selasky 		return NULL;
119*d6b92ffaSHans Petter Selasky 	snprintf(str, size, "%s %d Chip %d", ChassisSlotTypeStr[node->ch_slot],
120*d6b92ffaSHans Petter Selasky 		 node->ch_slotnum, node->ch_anafanum);
121*d6b92ffaSHans Petter Selasky 	return str;
122*d6b92ffaSHans Petter Selasky }
123*d6b92ffaSHans Petter Selasky 
find_chassisnum(ibnd_fabric_t * fabric,unsigned char chassisnum)124*d6b92ffaSHans Petter Selasky static ibnd_chassis_t *find_chassisnum(ibnd_fabric_t * fabric,
125*d6b92ffaSHans Petter Selasky 				       unsigned char chassisnum)
126*d6b92ffaSHans Petter Selasky {
127*d6b92ffaSHans Petter Selasky 	ibnd_chassis_t *current;
128*d6b92ffaSHans Petter Selasky 
129*d6b92ffaSHans Petter Selasky 	for (current = fabric->chassis; current; current = current->next)
130*d6b92ffaSHans Petter Selasky 		if (current->chassisnum == chassisnum)
131*d6b92ffaSHans Petter Selasky 			return current;
132*d6b92ffaSHans Petter Selasky 
133*d6b92ffaSHans Petter Selasky 	return NULL;
134*d6b92ffaSHans Petter Selasky }
135*d6b92ffaSHans Petter Selasky 
topspin_chassisguid(uint64_t guid)136*d6b92ffaSHans Petter Selasky static uint64_t topspin_chassisguid(uint64_t guid)
137*d6b92ffaSHans Petter Selasky {
138*d6b92ffaSHans Petter Selasky 	/* Byte 3 in system image GUID is chassis type, and */
139*d6b92ffaSHans Petter Selasky 	/* Byte 4 is location ID (slot) so just mask off byte 4 */
140*d6b92ffaSHans Petter Selasky 	return guid & 0xffffffff00ffffffULL;
141*d6b92ffaSHans Petter Selasky }
142*d6b92ffaSHans Petter Selasky 
ibnd_is_xsigo_guid(uint64_t guid)143*d6b92ffaSHans Petter Selasky int ibnd_is_xsigo_guid(uint64_t guid)
144*d6b92ffaSHans Petter Selasky {
145*d6b92ffaSHans Petter Selasky 	if ((guid & 0xffffff0000000000ULL) == 0x0013970000000000ULL)
146*d6b92ffaSHans Petter Selasky 		return 1;
147*d6b92ffaSHans Petter Selasky 	else
148*d6b92ffaSHans Petter Selasky 		return 0;
149*d6b92ffaSHans Petter Selasky }
150*d6b92ffaSHans Petter Selasky 
is_xsigo_leafone(uint64_t guid)151*d6b92ffaSHans Petter Selasky static int is_xsigo_leafone(uint64_t guid)
152*d6b92ffaSHans Petter Selasky {
153*d6b92ffaSHans Petter Selasky 	if ((guid & 0xffffffffff000000ULL) == 0x0013970102000000ULL)
154*d6b92ffaSHans Petter Selasky 		return 1;
155*d6b92ffaSHans Petter Selasky 	else
156*d6b92ffaSHans Petter Selasky 		return 0;
157*d6b92ffaSHans Petter Selasky }
158*d6b92ffaSHans Petter Selasky 
ibnd_is_xsigo_hca(uint64_t guid)159*d6b92ffaSHans Petter Selasky int ibnd_is_xsigo_hca(uint64_t guid)
160*d6b92ffaSHans Petter Selasky {
161*d6b92ffaSHans Petter Selasky 	/* NodeType 2 is HCA */
162*d6b92ffaSHans Petter Selasky 	if ((guid & 0xffffffff00000000ULL) == 0x0013970200000000ULL)
163*d6b92ffaSHans Petter Selasky 		return 1;
164*d6b92ffaSHans Petter Selasky 	else
165*d6b92ffaSHans Petter Selasky 		return 0;
166*d6b92ffaSHans Petter Selasky }
167*d6b92ffaSHans Petter Selasky 
ibnd_is_xsigo_tca(uint64_t guid)168*d6b92ffaSHans Petter Selasky int ibnd_is_xsigo_tca(uint64_t guid)
169*d6b92ffaSHans Petter Selasky {
170*d6b92ffaSHans Petter Selasky 	/* NodeType 3 is TCA */
171*d6b92ffaSHans Petter Selasky 	if ((guid & 0xffffffff00000000ULL) == 0x0013970300000000ULL)
172*d6b92ffaSHans Petter Selasky 		return 1;
173*d6b92ffaSHans Petter Selasky 	else
174*d6b92ffaSHans Petter Selasky 		return 0;
175*d6b92ffaSHans Petter Selasky }
176*d6b92ffaSHans Petter Selasky 
is_xsigo_ca(uint64_t guid)177*d6b92ffaSHans Petter Selasky static int is_xsigo_ca(uint64_t guid)
178*d6b92ffaSHans Petter Selasky {
179*d6b92ffaSHans Petter Selasky 	if (ibnd_is_xsigo_hca(guid) || ibnd_is_xsigo_tca(guid))
180*d6b92ffaSHans Petter Selasky 		return 1;
181*d6b92ffaSHans Petter Selasky 	else
182*d6b92ffaSHans Petter Selasky 		return 0;
183*d6b92ffaSHans Petter Selasky }
184*d6b92ffaSHans Petter Selasky 
is_xsigo_switch(uint64_t guid)185*d6b92ffaSHans Petter Selasky static int is_xsigo_switch(uint64_t guid)
186*d6b92ffaSHans Petter Selasky {
187*d6b92ffaSHans Petter Selasky 	if ((guid & 0xffffffff00000000ULL) == 0x0013970100000000ULL)
188*d6b92ffaSHans Petter Selasky 		return 1;
189*d6b92ffaSHans Petter Selasky 	else
190*d6b92ffaSHans Petter Selasky 		return 0;
191*d6b92ffaSHans Petter Selasky }
192*d6b92ffaSHans Petter Selasky 
xsigo_chassisguid(ibnd_node_t * node)193*d6b92ffaSHans Petter Selasky static uint64_t xsigo_chassisguid(ibnd_node_t * node)
194*d6b92ffaSHans Petter Selasky {
195*d6b92ffaSHans Petter Selasky 	uint64_t sysimgguid =
196*d6b92ffaSHans Petter Selasky 	    mad_get_field64(node->info, 0, IB_NODE_SYSTEM_GUID_F);
197*d6b92ffaSHans Petter Selasky 	uint64_t remote_sysimgguid;
198*d6b92ffaSHans Petter Selasky 
199*d6b92ffaSHans Petter Selasky 	if (!is_xsigo_ca(sysimgguid)) {
200*d6b92ffaSHans Petter Selasky 		/* Byte 3 is NodeType and byte 4 is PortType */
201*d6b92ffaSHans Petter Selasky 		/* If NodeType is 1 (switch), PortType is masked */
202*d6b92ffaSHans Petter Selasky 		if (is_xsigo_switch(sysimgguid))
203*d6b92ffaSHans Petter Selasky 			return sysimgguid & 0xffffffff00ffffffULL;
204*d6b92ffaSHans Petter Selasky 		else
205*d6b92ffaSHans Petter Selasky 			return sysimgguid;
206*d6b92ffaSHans Petter Selasky 	} else {
207*d6b92ffaSHans Petter Selasky 		if (!node->ports || !node->ports[1])
208*d6b92ffaSHans Petter Selasky 			return 0;
209*d6b92ffaSHans Petter Selasky 
210*d6b92ffaSHans Petter Selasky 		/* Is there a peer port ? */
211*d6b92ffaSHans Petter Selasky 		if (!node->ports[1]->remoteport)
212*d6b92ffaSHans Petter Selasky 			return sysimgguid;
213*d6b92ffaSHans Petter Selasky 
214*d6b92ffaSHans Petter Selasky 		/* If peer port is Leaf 1, use its chassis GUID */
215*d6b92ffaSHans Petter Selasky 		remote_sysimgguid =
216*d6b92ffaSHans Petter Selasky 		    mad_get_field64(node->ports[1]->remoteport->node->info, 0,
217*d6b92ffaSHans Petter Selasky 				    IB_NODE_SYSTEM_GUID_F);
218*d6b92ffaSHans Petter Selasky 		if (is_xsigo_leafone(remote_sysimgguid))
219*d6b92ffaSHans Petter Selasky 			return remote_sysimgguid & 0xffffffff00ffffffULL;
220*d6b92ffaSHans Petter Selasky 		else
221*d6b92ffaSHans Petter Selasky 			return sysimgguid;
222*d6b92ffaSHans Petter Selasky 	}
223*d6b92ffaSHans Petter Selasky }
224*d6b92ffaSHans Petter Selasky 
get_chassisguid(ibnd_node_t * node)225*d6b92ffaSHans Petter Selasky static uint64_t get_chassisguid(ibnd_node_t * node)
226*d6b92ffaSHans Petter Selasky {
227*d6b92ffaSHans Petter Selasky 	uint32_t vendid = mad_get_field(node->info, 0, IB_NODE_VENDORID_F);
228*d6b92ffaSHans Petter Selasky 	uint64_t sysimgguid =
229*d6b92ffaSHans Petter Selasky 	    mad_get_field64(node->info, 0, IB_NODE_SYSTEM_GUID_F);
230*d6b92ffaSHans Petter Selasky 
231*d6b92ffaSHans Petter Selasky 	if (vendid == TS_VENDOR_ID || vendid == SS_VENDOR_ID)
232*d6b92ffaSHans Petter Selasky 		return topspin_chassisguid(sysimgguid);
233*d6b92ffaSHans Petter Selasky 	else if (vendid == XS_VENDOR_ID || ibnd_is_xsigo_guid(sysimgguid))
234*d6b92ffaSHans Petter Selasky 		return xsigo_chassisguid(node);
235*d6b92ffaSHans Petter Selasky 	else
236*d6b92ffaSHans Petter Selasky 		return sysimgguid;
237*d6b92ffaSHans Petter Selasky }
238*d6b92ffaSHans Petter Selasky 
find_chassisguid(ibnd_fabric_t * fabric,ibnd_node_t * node)239*d6b92ffaSHans Petter Selasky static ibnd_chassis_t *find_chassisguid(ibnd_fabric_t * fabric,
240*d6b92ffaSHans Petter Selasky 					ibnd_node_t * node)
241*d6b92ffaSHans Petter Selasky {
242*d6b92ffaSHans Petter Selasky 	ibnd_chassis_t *current;
243*d6b92ffaSHans Petter Selasky 	uint64_t chguid;
244*d6b92ffaSHans Petter Selasky 
245*d6b92ffaSHans Petter Selasky 	chguid = get_chassisguid(node);
246*d6b92ffaSHans Petter Selasky 	for (current = fabric->chassis; current; current = current->next)
247*d6b92ffaSHans Petter Selasky 		if (current->chassisguid == chguid)
248*d6b92ffaSHans Petter Selasky 			return current;
249*d6b92ffaSHans Petter Selasky 
250*d6b92ffaSHans Petter Selasky 	return NULL;
251*d6b92ffaSHans Petter Selasky }
252*d6b92ffaSHans Petter Selasky 
ibnd_get_chassis_guid(ibnd_fabric_t * fabric,unsigned char chassisnum)253*d6b92ffaSHans Petter Selasky uint64_t ibnd_get_chassis_guid(ibnd_fabric_t * fabric, unsigned char chassisnum)
254*d6b92ffaSHans Petter Selasky {
255*d6b92ffaSHans Petter Selasky 	ibnd_chassis_t *chassis;
256*d6b92ffaSHans Petter Selasky 
257*d6b92ffaSHans Petter Selasky 	if (!fabric) {
258*d6b92ffaSHans Petter Selasky 		IBND_DEBUG("fabric parameter NULL\n");
259*d6b92ffaSHans Petter Selasky 		return 0;
260*d6b92ffaSHans Petter Selasky 	}
261*d6b92ffaSHans Petter Selasky 
262*d6b92ffaSHans Petter Selasky 	chassis = find_chassisnum(fabric, chassisnum);
263*d6b92ffaSHans Petter Selasky 	if (chassis)
264*d6b92ffaSHans Petter Selasky 		return chassis->chassisguid;
265*d6b92ffaSHans Petter Selasky 	else
266*d6b92ffaSHans Petter Selasky 		return 0;
267*d6b92ffaSHans Petter Selasky }
268*d6b92ffaSHans Petter Selasky 
is_router(ibnd_node_t * n)269*d6b92ffaSHans Petter Selasky static int is_router(ibnd_node_t * n)
270*d6b92ffaSHans Petter Selasky {
271*d6b92ffaSHans Petter Selasky 	uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F);
272*d6b92ffaSHans Petter Selasky 	return (devid == VTR_DEVID_IB_FC_ROUTER ||
273*d6b92ffaSHans Petter Selasky 		devid == VTR_DEVID_IB_IP_ROUTER);
274*d6b92ffaSHans Petter Selasky }
275*d6b92ffaSHans Petter Selasky 
is_spine_9096(ibnd_node_t * n)276*d6b92ffaSHans Petter Selasky static int is_spine_9096(ibnd_node_t * n)
277*d6b92ffaSHans Petter Selasky {
278*d6b92ffaSHans Petter Selasky 	uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F);
279*d6b92ffaSHans Petter Selasky 	return (devid == VTR_DEVID_SFB4 || devid == VTR_DEVID_SFB4_DDR);
280*d6b92ffaSHans Petter Selasky }
281*d6b92ffaSHans Petter Selasky 
is_spine_9288(ibnd_node_t * n)282*d6b92ffaSHans Petter Selasky static int is_spine_9288(ibnd_node_t * n)
283*d6b92ffaSHans Petter Selasky {
284*d6b92ffaSHans Petter Selasky 	uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F);
285*d6b92ffaSHans Petter Selasky 	return (devid == VTR_DEVID_SFB12 || devid == VTR_DEVID_SFB12_DDR);
286*d6b92ffaSHans Petter Selasky }
287*d6b92ffaSHans Petter Selasky 
is_spine_2004(ibnd_node_t * n)288*d6b92ffaSHans Petter Selasky static int is_spine_2004(ibnd_node_t * n)
289*d6b92ffaSHans Petter Selasky {
290*d6b92ffaSHans Petter Selasky 	uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F);
291*d6b92ffaSHans Petter Selasky 	return (devid == VTR_DEVID_SFB2004);
292*d6b92ffaSHans Petter Selasky }
293*d6b92ffaSHans Petter Selasky 
is_spine_2012(ibnd_node_t * n)294*d6b92ffaSHans Petter Selasky static int is_spine_2012(ibnd_node_t * n)
295*d6b92ffaSHans Petter Selasky {
296*d6b92ffaSHans Petter Selasky 	uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F);
297*d6b92ffaSHans Petter Selasky 	return (devid == VTR_DEVID_SFB2012);
298*d6b92ffaSHans Petter Selasky }
299*d6b92ffaSHans Petter Selasky 
is_spine_4700(ibnd_node_t * n)300*d6b92ffaSHans Petter Selasky static int is_spine_4700(ibnd_node_t * n)
301*d6b92ffaSHans Petter Selasky {
302*d6b92ffaSHans Petter Selasky 	uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F);
303*d6b92ffaSHans Petter Selasky 	return (devid == VTR_DEVID_SFB4700);
304*d6b92ffaSHans Petter Selasky }
305*d6b92ffaSHans Petter Selasky 
is_spine_4700x2(ibnd_node_t * n)306*d6b92ffaSHans Petter Selasky static int is_spine_4700x2(ibnd_node_t * n)
307*d6b92ffaSHans Petter Selasky {
308*d6b92ffaSHans Petter Selasky 	uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F);
309*d6b92ffaSHans Petter Selasky 	return (devid == VTR_DEVID_SFB4700X2);
310*d6b92ffaSHans Petter Selasky }
311*d6b92ffaSHans Petter Selasky 
is_spine_4200(ibnd_node_t * n)312*d6b92ffaSHans Petter Selasky static int is_spine_4200(ibnd_node_t * n)
313*d6b92ffaSHans Petter Selasky {
314*d6b92ffaSHans Petter Selasky 	uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F);
315*d6b92ffaSHans Petter Selasky 	return (devid == VTR_DEVID_SFB4200);
316*d6b92ffaSHans Petter Selasky }
317*d6b92ffaSHans Petter Selasky 
is_spine(ibnd_node_t * n)318*d6b92ffaSHans Petter Selasky static int is_spine(ibnd_node_t * n)
319*d6b92ffaSHans Petter Selasky {
320*d6b92ffaSHans Petter Selasky 	return (is_spine_9096(n) || is_spine_9288(n) ||
321*d6b92ffaSHans Petter Selasky 		is_spine_2004(n) || is_spine_2012(n) ||
322*d6b92ffaSHans Petter Selasky 		is_spine_4700(n) || is_spine_4700x2(n) ||
323*d6b92ffaSHans Petter Selasky 		is_spine_4200(n));
324*d6b92ffaSHans Petter Selasky }
325*d6b92ffaSHans Petter Selasky 
is_line_24(ibnd_node_t * n)326*d6b92ffaSHans Petter Selasky static int is_line_24(ibnd_node_t * n)
327*d6b92ffaSHans Petter Selasky {
328*d6b92ffaSHans Petter Selasky 	uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F);
329*d6b92ffaSHans Petter Selasky 	return (devid == VTR_DEVID_SLB24 ||
330*d6b92ffaSHans Petter Selasky 		devid == VTR_DEVID_SLB24_DDR || devid == VTR_DEVID_SRB2004);
331*d6b92ffaSHans Petter Selasky }
332*d6b92ffaSHans Petter Selasky 
is_line_8(ibnd_node_t * n)333*d6b92ffaSHans Petter Selasky static int is_line_8(ibnd_node_t * n)
334*d6b92ffaSHans Petter Selasky {
335*d6b92ffaSHans Petter Selasky 	uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F);
336*d6b92ffaSHans Petter Selasky 	return (devid == VTR_DEVID_SLB8);
337*d6b92ffaSHans Petter Selasky }
338*d6b92ffaSHans Petter Selasky 
is_line_2024(ibnd_node_t * n)339*d6b92ffaSHans Petter Selasky static int is_line_2024(ibnd_node_t * n)
340*d6b92ffaSHans Petter Selasky {
341*d6b92ffaSHans Petter Selasky 	uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F);
342*d6b92ffaSHans Petter Selasky 	return (devid == VTR_DEVID_SLB2024);
343*d6b92ffaSHans Petter Selasky }
344*d6b92ffaSHans Petter Selasky 
is_line_4700(ibnd_node_t * n)345*d6b92ffaSHans Petter Selasky static int is_line_4700(ibnd_node_t * n)
346*d6b92ffaSHans Petter Selasky {
347*d6b92ffaSHans Petter Selasky 	uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F);
348*d6b92ffaSHans Petter Selasky 	return (devid == VTR_DEVID_SLB4018);
349*d6b92ffaSHans Petter Selasky }
350*d6b92ffaSHans Petter Selasky 
is_line(ibnd_node_t * n)351*d6b92ffaSHans Petter Selasky static int is_line(ibnd_node_t * n)
352*d6b92ffaSHans Petter Selasky {
353*d6b92ffaSHans Petter Selasky 	return (is_line_24(n) || is_line_8(n) ||
354*d6b92ffaSHans Petter Selasky 		is_line_2024(n) || is_line_4700(n));
355*d6b92ffaSHans Petter Selasky }
356*d6b92ffaSHans Petter Selasky 
is_chassis_switch(ibnd_node_t * n)357*d6b92ffaSHans Petter Selasky int is_chassis_switch(ibnd_node_t * n)
358*d6b92ffaSHans Petter Selasky {
359*d6b92ffaSHans Petter Selasky 	return (is_spine(n) || is_line(n));
360*d6b92ffaSHans Petter Selasky }
361*d6b92ffaSHans Petter Selasky 
362*d6b92ffaSHans Petter Selasky /* these structs help find Line (Anafa) slot number while using spine portnum */
363*d6b92ffaSHans Petter Selasky char line_slot_2_sfb4[37] = {
364*d6b92ffaSHans Petter Selasky 	0,
365*d6b92ffaSHans Petter Selasky 	1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3,
366*d6b92ffaSHans Petter Selasky 	4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
367*d6b92ffaSHans Petter Selasky };
368*d6b92ffaSHans Petter Selasky char anafa_line_slot_2_sfb4[37] = {
369*d6b92ffaSHans Petter Selasky 	0,
370*d6b92ffaSHans Petter Selasky 	1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2,
371*d6b92ffaSHans Petter Selasky 	1, 1, 1, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
372*d6b92ffaSHans Petter Selasky };
373*d6b92ffaSHans Petter Selasky 
374*d6b92ffaSHans Petter Selasky char line_slot_2_sfb12[37] = {
375*d6b92ffaSHans Petter Selasky 	0,
376*d6b92ffaSHans Petter Selasky 	1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,
377*d6b92ffaSHans Petter Selasky 	10, 10, 11, 11, 12, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
378*d6b92ffaSHans Petter Selasky };
379*d6b92ffaSHans Petter Selasky char anafa_line_slot_2_sfb12[37] = {
380*d6b92ffaSHans Petter Selasky 	0,
381*d6b92ffaSHans Petter Selasky 	1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2,
382*d6b92ffaSHans Petter Selasky 	1, 2, 1, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
383*d6b92ffaSHans Petter Selasky };
384*d6b92ffaSHans Petter Selasky 
385*d6b92ffaSHans Petter Selasky /* LB slot = table[spine port] */
386*d6b92ffaSHans Petter Selasky char line_slot_2_sfb18[37] = {
387*d6b92ffaSHans Petter Selasky 	0,
388*d6b92ffaSHans Petter Selasky 	1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,
389*d6b92ffaSHans Petter Selasky 	10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18};
390*d6b92ffaSHans Petter Selasky /* LB asic num = table[spine port] */
391*d6b92ffaSHans Petter Selasky char anafa_line_slot_2_sfb18[37] = {
392*d6b92ffaSHans Petter Selasky 	0,
393*d6b92ffaSHans Petter Selasky 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
394*d6b92ffaSHans Petter Selasky 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
395*d6b92ffaSHans Petter Selasky };
396*d6b92ffaSHans Petter Selasky 
397*d6b92ffaSHans Petter Selasky /* LB slot = table[spine port] */
398*d6b92ffaSHans Petter Selasky char line_slot_2_sfb18x2[37] = {
399*d6b92ffaSHans Petter Selasky 	0,
400*d6b92ffaSHans Petter Selasky 	1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
401*d6b92ffaSHans Petter Selasky 	0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0};
402*d6b92ffaSHans Petter Selasky /* LB asic num = table[spine port] */
403*d6b92ffaSHans Petter Selasky char anafa_line_slot_2_sfb18x2[37] = {
404*d6b92ffaSHans Petter Selasky 	0,
405*d6b92ffaSHans Petter Selasky 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
406*d6b92ffaSHans Petter Selasky 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
407*d6b92ffaSHans Petter Selasky };
408*d6b92ffaSHans Petter Selasky 
409*d6b92ffaSHans Petter Selasky /* LB slot = table[spine port] */
410*d6b92ffaSHans Petter Selasky char line_slot_2_sfb4200[37] = {
411*d6b92ffaSHans Petter Selasky 	0,
412*d6b92ffaSHans Petter Selasky 	1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5,
413*d6b92ffaSHans Petter Selasky 	5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9};
414*d6b92ffaSHans Petter Selasky /* LB asic num = table[spine port] */
415*d6b92ffaSHans Petter Selasky char anafa_line_slot_2_sfb4200[37] = {
416*d6b92ffaSHans Petter Selasky 	0,
417*d6b92ffaSHans Petter Selasky 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
418*d6b92ffaSHans Petter Selasky 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
419*d6b92ffaSHans Petter Selasky };
420*d6b92ffaSHans Petter Selasky 
421*d6b92ffaSHans Petter Selasky /* IPR FCR modules connectivity while using sFB4 port as reference */
422*d6b92ffaSHans Petter Selasky char ipr_slot_2_sfb4_port[37] = {
423*d6b92ffaSHans Petter Selasky 	0,
424*d6b92ffaSHans Petter Selasky 	3, 2, 1, 3, 2, 1, 3, 2, 1, 3, 2, 1, 3, 2, 1, 3, 2, 1,
425*d6b92ffaSHans Petter Selasky 	3, 2, 1, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
426*d6b92ffaSHans Petter Selasky };
427*d6b92ffaSHans Petter Selasky 
428*d6b92ffaSHans Petter Selasky /* these structs help find Spine (Anafa) slot number while using spine portnum */
429*d6b92ffaSHans Petter Selasky char spine12_slot_2_slb[37] = {
430*d6b92ffaSHans Petter Selasky 	0,
431*d6b92ffaSHans Petter Selasky 	1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 0, 0, 0, 0, 0, 0,
432*d6b92ffaSHans Petter Selasky 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
433*d6b92ffaSHans Petter Selasky };
434*d6b92ffaSHans Petter Selasky char anafa_spine12_slot_2_slb[37] = {
435*d6b92ffaSHans Petter Selasky 	0,
436*d6b92ffaSHans Petter Selasky 	1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 0, 0, 0, 0, 0, 0,
437*d6b92ffaSHans Petter Selasky 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
438*d6b92ffaSHans Petter Selasky };
439*d6b92ffaSHans Petter Selasky 
440*d6b92ffaSHans Petter Selasky char spine4_slot_2_slb[37] = {
441*d6b92ffaSHans Petter Selasky 	0,
442*d6b92ffaSHans Petter Selasky 	1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 0, 0, 0, 0, 0, 0,
443*d6b92ffaSHans Petter Selasky 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
444*d6b92ffaSHans Petter Selasky };
445*d6b92ffaSHans Petter Selasky char anafa_spine4_slot_2_slb[37] = {
446*d6b92ffaSHans Petter Selasky 	0,
447*d6b92ffaSHans Petter Selasky 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
448*d6b92ffaSHans Petter Selasky 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
449*d6b92ffaSHans Petter Selasky };
450*d6b92ffaSHans Petter Selasky 
451*d6b92ffaSHans Petter Selasky /* FB slot = table[line port] */
452*d6b92ffaSHans Petter Selasky char spine18_slot_2_slb[37] = {
453*d6b92ffaSHans Petter Selasky 	0,
454*d6b92ffaSHans Petter Selasky 	1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,
455*d6b92ffaSHans Petter Selasky 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
456*d6b92ffaSHans Petter Selasky };
457*d6b92ffaSHans Petter Selasky /* FB asic = table[line port] */
458*d6b92ffaSHans Petter Selasky char anafa_spine18_slot_2_slb[37] = {
459*d6b92ffaSHans Petter Selasky 	0,
460*d6b92ffaSHans Petter Selasky 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
461*d6b92ffaSHans Petter Selasky 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
462*d6b92ffaSHans Petter Selasky };
463*d6b92ffaSHans Petter Selasky char anafa_spine18x2_slot_2_slb[37] = {
464*d6b92ffaSHans Petter Selasky 	0,
465*d6b92ffaSHans Petter Selasky 	2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1,
466*d6b92ffaSHans Petter Selasky 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
467*d6b92ffaSHans Petter Selasky };
468*d6b92ffaSHans Petter Selasky 
469*d6b92ffaSHans Petter Selasky /* FB slot = table[line port] */
470*d6b92ffaSHans Petter Selasky char sfb4200_slot_2_slb[37] = {
471*d6b92ffaSHans Petter Selasky 	0,
472*d6b92ffaSHans Petter Selasky 	1, 1, 1, 1, 0, 0, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4,
473*d6b92ffaSHans Petter Selasky 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
474*d6b92ffaSHans Petter Selasky };
475*d6b92ffaSHans Petter Selasky /* FB asic = table[line port] */
476*d6b92ffaSHans Petter Selasky char anafa_sfb4200_slot_2_slb[37] = {
477*d6b92ffaSHans Petter Selasky 	0,
478*d6b92ffaSHans Petter Selasky 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
479*d6b92ffaSHans Petter Selasky 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
480*d6b92ffaSHans Petter Selasky };
481*d6b92ffaSHans Petter Selasky 
482*d6b92ffaSHans Petter Selasky /*	reference                     { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 }; */
483*d6b92ffaSHans Petter Selasky 
get_sfb_slot(ibnd_node_t * n,ibnd_port_t * lineport)484*d6b92ffaSHans Petter Selasky static int get_sfb_slot(ibnd_node_t * n, ibnd_port_t * lineport)
485*d6b92ffaSHans Petter Selasky {
486*d6b92ffaSHans Petter Selasky 	n->ch_slot = SPINE_CS;
487*d6b92ffaSHans Petter Selasky 	if (is_spine_9096(n)) {
488*d6b92ffaSHans Petter Selasky 		n->ch_type = ISR9096_CT;
489*d6b92ffaSHans Petter Selasky 		n->ch_slotnum = spine4_slot_2_slb[lineport->portnum];
490*d6b92ffaSHans Petter Selasky 		n->ch_anafanum = anafa_spine4_slot_2_slb[lineport->portnum];
491*d6b92ffaSHans Petter Selasky 	} else if (is_spine_9288(n)) {
492*d6b92ffaSHans Petter Selasky 		n->ch_type = ISR9288_CT;
493*d6b92ffaSHans Petter Selasky 		n->ch_slotnum = spine12_slot_2_slb[lineport->portnum];
494*d6b92ffaSHans Petter Selasky 		n->ch_anafanum = anafa_spine12_slot_2_slb[lineport->portnum];
495*d6b92ffaSHans Petter Selasky 	} else if (is_spine_2012(n)) {
496*d6b92ffaSHans Petter Selasky 		n->ch_type = ISR2012_CT;
497*d6b92ffaSHans Petter Selasky 		n->ch_slotnum = spine12_slot_2_slb[lineport->portnum];
498*d6b92ffaSHans Petter Selasky 		n->ch_anafanum = anafa_spine12_slot_2_slb[lineport->portnum];
499*d6b92ffaSHans Petter Selasky 	} else if (is_spine_2004(n)) {
500*d6b92ffaSHans Petter Selasky 		n->ch_type = ISR2004_CT;
501*d6b92ffaSHans Petter Selasky 		n->ch_slotnum = spine4_slot_2_slb[lineport->portnum];
502*d6b92ffaSHans Petter Selasky 		n->ch_anafanum = anafa_spine4_slot_2_slb[lineport->portnum];
503*d6b92ffaSHans Petter Selasky 	} else if (is_spine_4700(n)) {
504*d6b92ffaSHans Petter Selasky 		n->ch_type = ISR4700_CT;
505*d6b92ffaSHans Petter Selasky 		n->ch_slotnum = spine18_slot_2_slb[lineport->portnum];
506*d6b92ffaSHans Petter Selasky 		n->ch_anafanum = anafa_spine18_slot_2_slb[lineport->portnum];
507*d6b92ffaSHans Petter Selasky 	} else if (is_spine_4700x2(n)) {
508*d6b92ffaSHans Petter Selasky 		n->ch_type = ISR4700_CT;
509*d6b92ffaSHans Petter Selasky 		n->ch_slotnum = spine18_slot_2_slb[lineport->portnum];
510*d6b92ffaSHans Petter Selasky 		n->ch_anafanum = anafa_spine18x2_slot_2_slb[lineport->portnum];
511*d6b92ffaSHans Petter Selasky 	} else if (is_spine_4200(n)) {
512*d6b92ffaSHans Petter Selasky 		n->ch_type = ISR4200_CT;
513*d6b92ffaSHans Petter Selasky 		n->ch_slotnum = sfb4200_slot_2_slb[lineport->portnum];
514*d6b92ffaSHans Petter Selasky 		n->ch_anafanum = anafa_sfb4200_slot_2_slb[lineport->portnum];
515*d6b92ffaSHans Petter Selasky 	} else {
516*d6b92ffaSHans Petter Selasky 		IBND_ERROR("Unexpected node found: guid 0x%016" PRIx64 "\n",
517*d6b92ffaSHans Petter Selasky 			   n->guid);
518*d6b92ffaSHans Petter Selasky 	}
519*d6b92ffaSHans Petter Selasky 	return 0;
520*d6b92ffaSHans Petter Selasky }
521*d6b92ffaSHans Petter Selasky 
get_router_slot(ibnd_node_t * n,ibnd_port_t * spineport)522*d6b92ffaSHans Petter Selasky static int get_router_slot(ibnd_node_t * n, ibnd_port_t * spineport)
523*d6b92ffaSHans Petter Selasky {
524*d6b92ffaSHans Petter Selasky 	uint64_t guessnum = 0;
525*d6b92ffaSHans Petter Selasky 
526*d6b92ffaSHans Petter Selasky 	n->ch_found = 1;
527*d6b92ffaSHans Petter Selasky 
528*d6b92ffaSHans Petter Selasky 	n->ch_slot = SRBD_CS;
529*d6b92ffaSHans Petter Selasky 	if (is_spine_9096(spineport->node)) {
530*d6b92ffaSHans Petter Selasky 		n->ch_type = ISR9096_CT;
531*d6b92ffaSHans Petter Selasky 		n->ch_slotnum = line_slot_2_sfb4[spineport->portnum];
532*d6b92ffaSHans Petter Selasky 		n->ch_anafanum = ipr_slot_2_sfb4_port[spineport->portnum];
533*d6b92ffaSHans Petter Selasky 	} else if (is_spine_9288(spineport->node)) {
534*d6b92ffaSHans Petter Selasky 		n->ch_type = ISR9288_CT;
535*d6b92ffaSHans Petter Selasky 		n->ch_slotnum = line_slot_2_sfb12[spineport->portnum];
536*d6b92ffaSHans Petter Selasky 		/* this is a smart guess based on nodeguids order on sFB-12 module */
537*d6b92ffaSHans Petter Selasky 		guessnum = spineport->node->guid % 4;
538*d6b92ffaSHans Petter Selasky 		/* module 1 <--> remote anafa 3 */
539*d6b92ffaSHans Petter Selasky 		/* module 2 <--> remote anafa 2 */
540*d6b92ffaSHans Petter Selasky 		/* module 3 <--> remote anafa 1 */
541*d6b92ffaSHans Petter Selasky 		n->ch_anafanum = (guessnum == 3 ? 1 : (guessnum == 1 ? 3 : 2));
542*d6b92ffaSHans Petter Selasky 	} else if (is_spine_2012(spineport->node)) {
543*d6b92ffaSHans Petter Selasky 		n->ch_type = ISR2012_CT;
544*d6b92ffaSHans Petter Selasky 		n->ch_slotnum = line_slot_2_sfb12[spineport->portnum];
545*d6b92ffaSHans Petter Selasky 		/* this is a smart guess based on nodeguids order on sFB-12 module */
546*d6b92ffaSHans Petter Selasky 		guessnum = spineport->node->guid % 4;
547*d6b92ffaSHans Petter Selasky 		// module 1 <--> remote anafa 3
548*d6b92ffaSHans Petter Selasky 		// module 2 <--> remote anafa 2
549*d6b92ffaSHans Petter Selasky 		// module 3 <--> remote anafa 1
550*d6b92ffaSHans Petter Selasky 		n->ch_anafanum = (guessnum == 3 ? 1 : (guessnum == 1 ? 3 : 2));
551*d6b92ffaSHans Petter Selasky 	} else if (is_spine_2004(spineport->node)) {
552*d6b92ffaSHans Petter Selasky 		n->ch_type = ISR2004_CT;
553*d6b92ffaSHans Petter Selasky 		n->ch_slotnum = line_slot_2_sfb4[spineport->portnum];
554*d6b92ffaSHans Petter Selasky 		n->ch_anafanum = ipr_slot_2_sfb4_port[spineport->portnum];
555*d6b92ffaSHans Petter Selasky 	} else {
556*d6b92ffaSHans Petter Selasky 		IBND_ERROR("Unexpected node found: guid 0x%016" PRIx64 "\n",
557*d6b92ffaSHans Petter Selasky 			   spineport->node->guid);
558*d6b92ffaSHans Petter Selasky 	}
559*d6b92ffaSHans Petter Selasky 	return 0;
560*d6b92ffaSHans Petter Selasky }
561*d6b92ffaSHans Petter Selasky 
get_slb_slot(ibnd_node_t * n,ibnd_port_t * spineport)562*d6b92ffaSHans Petter Selasky static int get_slb_slot(ibnd_node_t * n, ibnd_port_t * spineport)
563*d6b92ffaSHans Petter Selasky {
564*d6b92ffaSHans Petter Selasky 	n->ch_slot = LINE_CS;
565*d6b92ffaSHans Petter Selasky 	if (is_spine_9096(spineport->node)) {
566*d6b92ffaSHans Petter Selasky 		n->ch_type = ISR9096_CT;
567*d6b92ffaSHans Petter Selasky 		n->ch_slotnum = line_slot_2_sfb4[spineport->portnum];
568*d6b92ffaSHans Petter Selasky 		n->ch_anafanum = anafa_line_slot_2_sfb4[spineport->portnum];
569*d6b92ffaSHans Petter Selasky 	} else if (is_spine_9288(spineport->node)) {
570*d6b92ffaSHans Petter Selasky 		n->ch_type = ISR9288_CT;
571*d6b92ffaSHans Petter Selasky 		n->ch_slotnum = line_slot_2_sfb12[spineport->portnum];
572*d6b92ffaSHans Petter Selasky 		n->ch_anafanum = anafa_line_slot_2_sfb12[spineport->portnum];
573*d6b92ffaSHans Petter Selasky 	} else if (is_spine_2012(spineport->node)) {
574*d6b92ffaSHans Petter Selasky 		n->ch_type = ISR2012_CT;
575*d6b92ffaSHans Petter Selasky 		n->ch_slotnum = line_slot_2_sfb12[spineport->portnum];
576*d6b92ffaSHans Petter Selasky 		n->ch_anafanum = anafa_line_slot_2_sfb12[spineport->portnum];
577*d6b92ffaSHans Petter Selasky 	} else if (is_spine_2004(spineport->node)) {
578*d6b92ffaSHans Petter Selasky 		n->ch_type = ISR2004_CT;
579*d6b92ffaSHans Petter Selasky 		n->ch_slotnum = line_slot_2_sfb4[spineport->portnum];
580*d6b92ffaSHans Petter Selasky 		n->ch_anafanum = anafa_line_slot_2_sfb4[spineport->portnum];
581*d6b92ffaSHans Petter Selasky 	} else if (is_spine_4700(spineport->node)) {
582*d6b92ffaSHans Petter Selasky 		n->ch_type = ISR4700_CT;
583*d6b92ffaSHans Petter Selasky 		n->ch_slotnum = line_slot_2_sfb18[spineport->portnum];
584*d6b92ffaSHans Petter Selasky 		n->ch_anafanum = anafa_line_slot_2_sfb18[spineport->portnum];
585*d6b92ffaSHans Petter Selasky 	} else if (is_spine_4700x2(spineport->node)) {
586*d6b92ffaSHans Petter Selasky 		n->ch_type = ISR4700_CT;
587*d6b92ffaSHans Petter Selasky 		n->ch_slotnum = line_slot_2_sfb18x2[spineport->portnum];
588*d6b92ffaSHans Petter Selasky 		n->ch_anafanum = anafa_line_slot_2_sfb18x2[spineport->portnum];
589*d6b92ffaSHans Petter Selasky 	} else if (is_spine_4200(spineport->node)) {
590*d6b92ffaSHans Petter Selasky 		n->ch_type = ISR4200_CT;
591*d6b92ffaSHans Petter Selasky 		n->ch_slotnum = line_slot_2_sfb4200[spineport->portnum];
592*d6b92ffaSHans Petter Selasky 		n->ch_anafanum = anafa_line_slot_2_sfb4200[spineport->portnum];
593*d6b92ffaSHans Petter Selasky 	} else {
594*d6b92ffaSHans Petter Selasky 		IBND_ERROR("Unexpected node found: guid 0x%016" PRIx64 "\n",
595*d6b92ffaSHans Petter Selasky 			   spineport->node->guid);
596*d6b92ffaSHans Petter Selasky 	}
597*d6b92ffaSHans Petter Selasky 	return 0;
598*d6b92ffaSHans Petter Selasky }
599*d6b92ffaSHans Petter Selasky 
600*d6b92ffaSHans Petter Selasky 
601*d6b92ffaSHans Petter Selasky /*
602*d6b92ffaSHans Petter Selasky 	This function called for every Mellanox node in fabric
603*d6b92ffaSHans Petter Selasky */
fill_mellanox_chassis_record(ibnd_node_t * node)604*d6b92ffaSHans Petter Selasky static int fill_mellanox_chassis_record(ibnd_node_t * node)
605*d6b92ffaSHans Petter Selasky {
606*d6b92ffaSHans Petter Selasky 	int p = 0;
607*d6b92ffaSHans Petter Selasky 	ibnd_port_t *port;
608*d6b92ffaSHans Petter Selasky 
609*d6b92ffaSHans Petter Selasky 	char node_desc[IB_SMP_DATA_SIZE];
610*d6b92ffaSHans Petter Selasky 	char *system_name;
611*d6b92ffaSHans Petter Selasky 	char *system_type;
612*d6b92ffaSHans Petter Selasky 	char *system_slot_name;
613*d6b92ffaSHans Petter Selasky 	char *node_index;
614*d6b92ffaSHans Petter Selasky 	char *iter;
615*d6b92ffaSHans Petter Selasky 	int dev_id;
616*d6b92ffaSHans Petter Selasky 
617*d6b92ffaSHans Petter Selasky 	/*
618*d6b92ffaSHans Petter Selasky 	The node description has the following format:
619*d6b92ffaSHans Petter Selasky 
620*d6b92ffaSHans Petter Selasky 	'MF0;<system name>:<system type>/<system slot name>[:board type]/U<node index>'
621*d6b92ffaSHans Petter Selasky 
622*d6b92ffaSHans Petter Selasky      - System slot name in our systems can be L[01-36] , S[01-18]
623*d6b92ffaSHans Petter Selasky      - Node index is always 1 (we don.t have boards with multiple IS4 chips).
624*d6b92ffaSHans Petter Selasky      - System name is taken from the currently configured host name.
625*d6b92ffaSHans Petter Selasky      -The board type is optional and we don.t set it currently  - A leaf or spine slot can currently hold a single type of board.
626*d6b92ffaSHans Petter Selasky 	 */
627*d6b92ffaSHans Petter Selasky 
628*d6b92ffaSHans Petter Selasky 	memcpy(node_desc, node->nodedesc, IB_SMP_DATA_SIZE);
629*d6b92ffaSHans Petter Selasky 
630*d6b92ffaSHans Petter Selasky 	IBND_DEBUG("fill_mellanox_chassis_record: node_desc:%s \n",node_desc);
631*d6b92ffaSHans Petter Selasky 
632*d6b92ffaSHans Petter Selasky 	if (node->ch_found)	/* somehow this node has already been passed */
633*d6b92ffaSHans Petter Selasky 		return 0;
634*d6b92ffaSHans Petter Selasky 
635*d6b92ffaSHans Petter Selasky 	/* All mellanox IS4 switches have the same vendor id*/
636*d6b92ffaSHans Petter Selasky 	dev_id = mad_get_field(node->info, 0,IB_NODE_DEVID_F);
637*d6b92ffaSHans Petter Selasky 	if (dev_id != MLX_DEVID_IS4)
638*d6b92ffaSHans Petter Selasky 		return 0;
639*d6b92ffaSHans Petter Selasky 
640*d6b92ffaSHans Petter Selasky 	if((node_desc[0] != 'M') ||
641*d6b92ffaSHans Petter Selasky 	   (node_desc[1] != 'F') ||
642*d6b92ffaSHans Petter Selasky 	   (node_desc[2] != '0') ||
643*d6b92ffaSHans Petter Selasky 	   (node_desc[3] != ';')) {
644*d6b92ffaSHans Petter Selasky 		IBND_DEBUG("fill_mellanox_chassis_record: Unsupported node description format:%s \n",node_desc);
645*d6b92ffaSHans Petter Selasky 		return 0;
646*d6b92ffaSHans Petter Selasky 	}
647*d6b92ffaSHans Petter Selasky 
648*d6b92ffaSHans Petter Selasky 	/* parse system name*/
649*d6b92ffaSHans Petter Selasky 	system_name = &node_desc[4];
650*d6b92ffaSHans Petter Selasky 	for (iter = system_name ; (*iter != ':') && (*iter != '\0') ; iter++);
651*d6b92ffaSHans Petter Selasky 	if(*iter == '\0'){
652*d6b92ffaSHans Petter Selasky 		IBND_DEBUG("fill_mellanox_chassis_record: Unsupported node description format:%s - (get system_name failed) \n",node_desc);
653*d6b92ffaSHans Petter Selasky 		return 0;
654*d6b92ffaSHans Petter Selasky 	}
655*d6b92ffaSHans Petter Selasky 	*iter = '\0';
656*d6b92ffaSHans Petter Selasky 	iter++;
657*d6b92ffaSHans Petter Selasky 	/* parse system type*/
658*d6b92ffaSHans Petter Selasky 	system_type = iter;
659*d6b92ffaSHans Petter Selasky 	for ( ; (*iter != '/') && (*iter != '\0') ; iter++);
660*d6b92ffaSHans Petter Selasky 	if(*iter == '\0'){
661*d6b92ffaSHans Petter Selasky 		IBND_DEBUG("fill_mellanox_chassis_record: Unsupported node description format:%s - (get system_type failed) \n",node_desc);
662*d6b92ffaSHans Petter Selasky 		return 0;
663*d6b92ffaSHans Petter Selasky 	}
664*d6b92ffaSHans Petter Selasky 	*iter = '\0';
665*d6b92ffaSHans Petter Selasky 	iter++;
666*d6b92ffaSHans Petter Selasky 	/* parse system slot name*/
667*d6b92ffaSHans Petter Selasky 	system_slot_name = iter;
668*d6b92ffaSHans Petter Selasky 	for ( ; (*iter != '/') && (*iter != ':') && (*iter != '\0') ; iter++);
669*d6b92ffaSHans Petter Selasky 	if(*iter == '\0'){
670*d6b92ffaSHans Petter Selasky 		IBND_DEBUG("fill_mellanox_chassis_record: Unsupported node description format:%s - (get system_slot_name failed) \n",node_desc);
671*d6b92ffaSHans Petter Selasky 		return 0;
672*d6b92ffaSHans Petter Selasky 	}
673*d6b92ffaSHans Petter Selasky 	if(*iter == ':'){
674*d6b92ffaSHans Petter Selasky 		*iter = '\0';
675*d6b92ffaSHans Petter Selasky 		iter++;
676*d6b92ffaSHans Petter Selasky 		for ( ; (*iter != '/') && (*iter != '\0') ; iter++);
677*d6b92ffaSHans Petter Selasky 		if(*iter == '\0'){
678*d6b92ffaSHans Petter Selasky 			IBND_DEBUG("fill_mellanox_chassis_record: Unsupported node description format:%s - (get board type failed) \n",node_desc);
679*d6b92ffaSHans Petter Selasky 			return 0;
680*d6b92ffaSHans Petter Selasky 		}
681*d6b92ffaSHans Petter Selasky 	}
682*d6b92ffaSHans Petter Selasky 	*iter = '\0';
683*d6b92ffaSHans Petter Selasky 	iter++;
684*d6b92ffaSHans Petter Selasky 	node_index = iter;
685*d6b92ffaSHans Petter Selasky 	if(node_index[0] != 'U'){
686*d6b92ffaSHans Petter Selasky 		IBND_DEBUG("fill_mellanox_chassis_record: Unsupported node description format:%s - (get node index) \n",node_desc);
687*d6b92ffaSHans Petter Selasky 		return 0;
688*d6b92ffaSHans Petter Selasky 	}
689*d6b92ffaSHans Petter Selasky 
690*d6b92ffaSHans Petter Selasky 	/* set Chip number (node index) */
691*d6b92ffaSHans Petter Selasky 	node->ch_anafanum = (unsigned char) atoi(&node_index[1]);
692*d6b92ffaSHans Petter Selasky 	if(node->ch_anafanum != 1){
693*d6b92ffaSHans Petter Selasky 		IBND_DEBUG("Unexpected Chip number:%d \n",node->ch_anafanum);
694*d6b92ffaSHans Petter Selasky 	}
695*d6b92ffaSHans Petter Selasky 
696*d6b92ffaSHans Petter Selasky 
697*d6b92ffaSHans Petter Selasky 	/* set Line Spine numbers */
698*d6b92ffaSHans Petter Selasky 	if(system_slot_name[0] == 'L')
699*d6b92ffaSHans Petter Selasky 		node->ch_slot = LINE_CS;
700*d6b92ffaSHans Petter Selasky 	else if(system_slot_name[0] == 'S')
701*d6b92ffaSHans Petter Selasky 		node->ch_slot = SPINE_CS;
702*d6b92ffaSHans Petter Selasky 	else{
703*d6b92ffaSHans Petter Selasky 		IBND_DEBUG("fill_mellanox_chassis_record: Unsupported system_slot_name:%s \n",system_slot_name);
704*d6b92ffaSHans Petter Selasky 		return 0;
705*d6b92ffaSHans Petter Selasky 	}
706*d6b92ffaSHans Petter Selasky 
707*d6b92ffaSHans Petter Selasky 	/* The switch will be displayed under Line or Spine and not under Chassis switches */
708*d6b92ffaSHans Petter Selasky 	node->ch_found = 1;
709*d6b92ffaSHans Petter Selasky 
710*d6b92ffaSHans Petter Selasky 	node->ch_slotnum = (unsigned char) atoi(&system_slot_name[1]);
711*d6b92ffaSHans Petter Selasky 	if((node->ch_slot == LINE_CS && (node->ch_slotnum >  (LINES_MAX_NUM + 1))) ||
712*d6b92ffaSHans Petter Selasky 	   (node->ch_slot == SPINE_CS && (node->ch_slotnum > (SPINES_MAX_NUM + 1)))){
713*d6b92ffaSHans Petter Selasky 		IBND_ERROR("fill_mellanox_chassis_record: invalid slot number:%d \n",node->ch_slotnum);
714*d6b92ffaSHans Petter Selasky 		node->ch_slotnum = 0;
715*d6b92ffaSHans Petter Selasky 		return 0;
716*d6b92ffaSHans Petter Selasky 	}
717*d6b92ffaSHans Petter Selasky 
718*d6b92ffaSHans Petter Selasky 	/*set ch_type_str*/
719*d6b92ffaSHans Petter Selasky 	strncpy(node->ch_type_str , system_type, sizeof(node->ch_type_str)-1);
720*d6b92ffaSHans Petter Selasky 
721*d6b92ffaSHans Petter Selasky 	/* Line ports 1-18 are mapped to external ports 1-18*/
722*d6b92ffaSHans Petter Selasky 	if(node->ch_slot == LINE_CS)
723*d6b92ffaSHans Petter Selasky 	{
724*d6b92ffaSHans Petter Selasky 		for (p = 1; p <= node->numports && p <= 18 ; p++) {
725*d6b92ffaSHans Petter Selasky 			port = node->ports[p];
726*d6b92ffaSHans Petter Selasky 			if (!port)
727*d6b92ffaSHans Petter Selasky 				continue;
728*d6b92ffaSHans Petter Selasky 			port->ext_portnum = p;
729*d6b92ffaSHans Petter Selasky 		}
730*d6b92ffaSHans Petter Selasky 	}
731*d6b92ffaSHans Petter Selasky 
732*d6b92ffaSHans Petter Selasky 	return 0;
733*d6b92ffaSHans Petter Selasky }
734*d6b92ffaSHans Petter Selasky 
insert_mellanox_line_and_spine(ibnd_node_t * node,ibnd_chassis_t * chassis)735*d6b92ffaSHans Petter Selasky static int insert_mellanox_line_and_spine(ibnd_node_t * node, ibnd_chassis_t * chassis)
736*d6b92ffaSHans Petter Selasky {
737*d6b92ffaSHans Petter Selasky 	if (node->ch_slot == LINE_CS){
738*d6b92ffaSHans Petter Selasky 
739*d6b92ffaSHans Petter Selasky 		if (chassis->linenode[node->ch_slotnum])
740*d6b92ffaSHans Petter Selasky 			return 0;	/* already filled slot */
741*d6b92ffaSHans Petter Selasky 
742*d6b92ffaSHans Petter Selasky 		chassis->linenode[node->ch_slotnum] = node;
743*d6b92ffaSHans Petter Selasky 	}
744*d6b92ffaSHans Petter Selasky 	else if (node->ch_slot == SPINE_CS){
745*d6b92ffaSHans Petter Selasky 
746*d6b92ffaSHans Petter Selasky 		if (chassis->spinenode[node->ch_slotnum])
747*d6b92ffaSHans Petter Selasky 			return 0;	/* already filled slot */
748*d6b92ffaSHans Petter Selasky 
749*d6b92ffaSHans Petter Selasky 		chassis->spinenode[node->ch_slotnum] = node;
750*d6b92ffaSHans Petter Selasky 	}
751*d6b92ffaSHans Petter Selasky 	else
752*d6b92ffaSHans Petter Selasky 		return 0;
753*d6b92ffaSHans Petter Selasky 
754*d6b92ffaSHans Petter Selasky 	node->chassis = chassis;
755*d6b92ffaSHans Petter Selasky 
756*d6b92ffaSHans Petter Selasky 	return 0;
757*d6b92ffaSHans Petter Selasky }
758*d6b92ffaSHans Petter Selasky 
759*d6b92ffaSHans Petter Selasky 
760*d6b92ffaSHans Petter Selasky /* forward declare this */
761*d6b92ffaSHans Petter Selasky static void voltaire_portmap(ibnd_port_t * port);
762*d6b92ffaSHans Petter Selasky /*
763*d6b92ffaSHans Petter Selasky 	This function called for every Voltaire node in fabric
764*d6b92ffaSHans Petter Selasky 	It could be optimized so, but time overhead is very small
765*d6b92ffaSHans Petter Selasky 	and its only diag.util
766*d6b92ffaSHans Petter Selasky */
fill_voltaire_chassis_record(ibnd_node_t * node)767*d6b92ffaSHans Petter Selasky static int fill_voltaire_chassis_record(ibnd_node_t * node)
768*d6b92ffaSHans Petter Selasky {
769*d6b92ffaSHans Petter Selasky 	int p = 0;
770*d6b92ffaSHans Petter Selasky 	ibnd_port_t *port;
771*d6b92ffaSHans Petter Selasky 	ibnd_node_t *remnode = 0;
772*d6b92ffaSHans Petter Selasky 
773*d6b92ffaSHans Petter Selasky 	if (node->ch_found)	/* somehow this node has already been passed */
774*d6b92ffaSHans Petter Selasky 		return 0;
775*d6b92ffaSHans Petter Selasky 	node->ch_found = 1;
776*d6b92ffaSHans Petter Selasky 
777*d6b92ffaSHans Petter Selasky 	/* node is router only in case of using unique lid */
778*d6b92ffaSHans Petter Selasky 	/* (which is lid of chassis router port) */
779*d6b92ffaSHans Petter Selasky 	/* in such case node->ports is actually a requested port... */
780*d6b92ffaSHans Petter Selasky 	if (is_router(node))
781*d6b92ffaSHans Petter Selasky 		/* find the remote node */
782*d6b92ffaSHans Petter Selasky 		for (p = 1; p <= node->numports; p++) {
783*d6b92ffaSHans Petter Selasky 			port = node->ports[p];
784*d6b92ffaSHans Petter Selasky 			if (port && is_spine(port->remoteport->node))
785*d6b92ffaSHans Petter Selasky 				get_router_slot(node, port->remoteport);
786*d6b92ffaSHans Petter Selasky 		}
787*d6b92ffaSHans Petter Selasky 	else if (is_spine(node)) {
788*d6b92ffaSHans Petter Selasky 		int is_4700x2 = is_spine_4700x2(node);
789*d6b92ffaSHans Petter Selasky 
790*d6b92ffaSHans Petter Selasky 		for (p = 1; p <= node->numports; p++) {
791*d6b92ffaSHans Petter Selasky 			port = node->ports[p];
792*d6b92ffaSHans Petter Selasky 			if (!port || !port->remoteport)
793*d6b92ffaSHans Petter Selasky 				continue;
794*d6b92ffaSHans Petter Selasky 
795*d6b92ffaSHans Petter Selasky 			/*
796*d6b92ffaSHans Petter Selasky 			 * Skip ISR4700 double density fabric boards ports 19-36
797*d6b92ffaSHans Petter Selasky 			 * as they are chassis external ports
798*d6b92ffaSHans Petter Selasky 			 */
799*d6b92ffaSHans Petter Selasky 			if (is_4700x2 && (port->portnum > 18))
800*d6b92ffaSHans Petter Selasky 				continue;
801*d6b92ffaSHans Petter Selasky 
802*d6b92ffaSHans Petter Selasky 			remnode = port->remoteport->node;
803*d6b92ffaSHans Petter Selasky 			if (remnode->type != IB_NODE_SWITCH) {
804*d6b92ffaSHans Petter Selasky 				if (!remnode->ch_found)
805*d6b92ffaSHans Petter Selasky 					get_router_slot(remnode, port);
806*d6b92ffaSHans Petter Selasky 				continue;
807*d6b92ffaSHans Petter Selasky 			}
808*d6b92ffaSHans Petter Selasky 			if (!node->ch_type)
809*d6b92ffaSHans Petter Selasky 				/* we assume here that remoteport belongs to line */
810*d6b92ffaSHans Petter Selasky 				get_sfb_slot(node, port->remoteport);
811*d6b92ffaSHans Petter Selasky 
812*d6b92ffaSHans Petter Selasky 			/* we could break here, but need to find if more routers connected */
813*d6b92ffaSHans Petter Selasky 		}
814*d6b92ffaSHans Petter Selasky 
815*d6b92ffaSHans Petter Selasky 	} else if (is_line(node)) {
816*d6b92ffaSHans Petter Selasky 		int is_4700_line = is_line_4700(node);
817*d6b92ffaSHans Petter Selasky 
818*d6b92ffaSHans Petter Selasky 		for (p = 1; p <= node->numports; p++) {
819*d6b92ffaSHans Petter Selasky 			port = node->ports[p];
820*d6b92ffaSHans Petter Selasky 			if (!port || !port->remoteport)
821*d6b92ffaSHans Petter Selasky 				continue;
822*d6b92ffaSHans Petter Selasky 
823*d6b92ffaSHans Petter Selasky 			if ((is_4700_line && (port->portnum > 18)) ||
824*d6b92ffaSHans Petter Selasky 			    (!is_4700_line && (port->portnum > 12)))
825*d6b92ffaSHans Petter Selasky 				continue;
826*d6b92ffaSHans Petter Selasky 
827*d6b92ffaSHans Petter Selasky 			/* we assume here that remoteport belongs to spine */
828*d6b92ffaSHans Petter Selasky 			get_slb_slot(node, port->remoteport);
829*d6b92ffaSHans Petter Selasky 			break;
830*d6b92ffaSHans Petter Selasky 		}
831*d6b92ffaSHans Petter Selasky 	}
832*d6b92ffaSHans Petter Selasky 
833*d6b92ffaSHans Petter Selasky 	/* for each port of this node, map external ports */
834*d6b92ffaSHans Petter Selasky 	for (p = 1; p <= node->numports; p++) {
835*d6b92ffaSHans Petter Selasky 		port = node->ports[p];
836*d6b92ffaSHans Petter Selasky 		if (!port)
837*d6b92ffaSHans Petter Selasky 			continue;
838*d6b92ffaSHans Petter Selasky 		voltaire_portmap(port);
839*d6b92ffaSHans Petter Selasky 	}
840*d6b92ffaSHans Petter Selasky 
841*d6b92ffaSHans Petter Selasky 	return 0;
842*d6b92ffaSHans Petter Selasky }
843*d6b92ffaSHans Petter Selasky 
get_line_index(ibnd_node_t * node)844*d6b92ffaSHans Petter Selasky static int get_line_index(ibnd_node_t * node)
845*d6b92ffaSHans Petter Selasky {
846*d6b92ffaSHans Petter Selasky 	int retval;
847*d6b92ffaSHans Petter Selasky 
848*d6b92ffaSHans Petter Selasky 	if (is_line_4700(node))
849*d6b92ffaSHans Petter Selasky 		retval = node->ch_slotnum;
850*d6b92ffaSHans Petter Selasky 	else
851*d6b92ffaSHans Petter Selasky 		retval = 3 * (node->ch_slotnum - 1) + node->ch_anafanum;
852*d6b92ffaSHans Petter Selasky 
853*d6b92ffaSHans Petter Selasky 	if (retval > LINES_MAX_NUM || retval < 1) {
854*d6b92ffaSHans Petter Selasky 		printf("%s: retval = %d\n", __FUNCTION__, retval);
855*d6b92ffaSHans Petter Selasky 		IBND_ERROR("Internal error\n");
856*d6b92ffaSHans Petter Selasky 		return -1;
857*d6b92ffaSHans Petter Selasky 	}
858*d6b92ffaSHans Petter Selasky 	return retval;
859*d6b92ffaSHans Petter Selasky }
860*d6b92ffaSHans Petter Selasky 
get_spine_index(ibnd_node_t * node)861*d6b92ffaSHans Petter Selasky static int get_spine_index(ibnd_node_t * node)
862*d6b92ffaSHans Petter Selasky {
863*d6b92ffaSHans Petter Selasky 	int retval;
864*d6b92ffaSHans Petter Selasky 
865*d6b92ffaSHans Petter Selasky 	if (is_spine_9288(node) || is_spine_2012(node))
866*d6b92ffaSHans Petter Selasky 		retval = 3 * (node->ch_slotnum - 1) + node->ch_anafanum;
867*d6b92ffaSHans Petter Selasky 	else if (is_spine_4700(node) || is_spine_4700x2(node))
868*d6b92ffaSHans Petter Selasky 		retval = 2 * (node->ch_slotnum - 1) + node->ch_anafanum;
869*d6b92ffaSHans Petter Selasky 	else
870*d6b92ffaSHans Petter Selasky 		retval = node->ch_slotnum;
871*d6b92ffaSHans Petter Selasky 
872*d6b92ffaSHans Petter Selasky 	if (retval > SPINES_MAX_NUM || retval < 1) {
873*d6b92ffaSHans Petter Selasky 		IBND_ERROR("Internal error\n");
874*d6b92ffaSHans Petter Selasky 		return -1;
875*d6b92ffaSHans Petter Selasky 	}
876*d6b92ffaSHans Petter Selasky 	return retval;
877*d6b92ffaSHans Petter Selasky }
878*d6b92ffaSHans Petter Selasky 
insert_line_router(ibnd_node_t * node,ibnd_chassis_t * chassis)879*d6b92ffaSHans Petter Selasky static int insert_line_router(ibnd_node_t * node, ibnd_chassis_t * chassis)
880*d6b92ffaSHans Petter Selasky {
881*d6b92ffaSHans Petter Selasky 	int i = get_line_index(node);
882*d6b92ffaSHans Petter Selasky 
883*d6b92ffaSHans Petter Selasky 	if (i < 0)
884*d6b92ffaSHans Petter Selasky 		return i;
885*d6b92ffaSHans Petter Selasky 
886*d6b92ffaSHans Petter Selasky 	if (chassis->linenode[i])
887*d6b92ffaSHans Petter Selasky 		return 0;	/* already filled slot */
888*d6b92ffaSHans Petter Selasky 
889*d6b92ffaSHans Petter Selasky 	chassis->linenode[i] = node;
890*d6b92ffaSHans Petter Selasky 	node->chassis = chassis;
891*d6b92ffaSHans Petter Selasky 	return 0;
892*d6b92ffaSHans Petter Selasky }
893*d6b92ffaSHans Petter Selasky 
insert_spine(ibnd_node_t * node,ibnd_chassis_t * chassis)894*d6b92ffaSHans Petter Selasky static int insert_spine(ibnd_node_t * node, ibnd_chassis_t * chassis)
895*d6b92ffaSHans Petter Selasky {
896*d6b92ffaSHans Petter Selasky 	int i = get_spine_index(node);
897*d6b92ffaSHans Petter Selasky 
898*d6b92ffaSHans Petter Selasky 	if (i < 0)
899*d6b92ffaSHans Petter Selasky 		return i;
900*d6b92ffaSHans Petter Selasky 
901*d6b92ffaSHans Petter Selasky 	if (chassis->spinenode[i])
902*d6b92ffaSHans Petter Selasky 		return 0;	/* already filled slot */
903*d6b92ffaSHans Petter Selasky 
904*d6b92ffaSHans Petter Selasky 	chassis->spinenode[i] = node;
905*d6b92ffaSHans Petter Selasky 	node->chassis = chassis;
906*d6b92ffaSHans Petter Selasky 	return 0;
907*d6b92ffaSHans Petter Selasky }
908*d6b92ffaSHans Petter Selasky 
pass_on_lines_catch_spines(ibnd_chassis_t * chassis)909*d6b92ffaSHans Petter Selasky static int pass_on_lines_catch_spines(ibnd_chassis_t * chassis)
910*d6b92ffaSHans Petter Selasky {
911*d6b92ffaSHans Petter Selasky 	ibnd_node_t *node, *remnode;
912*d6b92ffaSHans Petter Selasky 	ibnd_port_t *port;
913*d6b92ffaSHans Petter Selasky 	int i, p;
914*d6b92ffaSHans Petter Selasky 
915*d6b92ffaSHans Petter Selasky 	for (i = 1; i <= LINES_MAX_NUM; i++) {
916*d6b92ffaSHans Petter Selasky 		int is_4700_line;
917*d6b92ffaSHans Petter Selasky 
918*d6b92ffaSHans Petter Selasky 		node = chassis->linenode[i];
919*d6b92ffaSHans Petter Selasky 
920*d6b92ffaSHans Petter Selasky 		if (!(node && is_line(node)))
921*d6b92ffaSHans Petter Selasky 			continue;	/* empty slot or router */
922*d6b92ffaSHans Petter Selasky 
923*d6b92ffaSHans Petter Selasky 		is_4700_line = is_line_4700(node);
924*d6b92ffaSHans Petter Selasky 
925*d6b92ffaSHans Petter Selasky 		for (p = 1; p <= node->numports; p++) {
926*d6b92ffaSHans Petter Selasky 
927*d6b92ffaSHans Petter Selasky 			port = node->ports[p];
928*d6b92ffaSHans Petter Selasky 			if (!port || !port->remoteport)
929*d6b92ffaSHans Petter Selasky 				continue;
930*d6b92ffaSHans Petter Selasky 
931*d6b92ffaSHans Petter Selasky 			if ((is_4700_line && (port->portnum > 18)) ||
932*d6b92ffaSHans Petter Selasky 			    (!is_4700_line && (port->portnum > 12)))
933*d6b92ffaSHans Petter Selasky 				continue;
934*d6b92ffaSHans Petter Selasky 
935*d6b92ffaSHans Petter Selasky 			remnode = port->remoteport->node;
936*d6b92ffaSHans Petter Selasky 
937*d6b92ffaSHans Petter Selasky 			if (!remnode->ch_found)
938*d6b92ffaSHans Petter Selasky 				continue;	/* some error - spine not initialized ? FIXME */
939*d6b92ffaSHans Petter Selasky 			if (insert_spine(remnode, chassis))
940*d6b92ffaSHans Petter Selasky 				return -1;
941*d6b92ffaSHans Petter Selasky 		}
942*d6b92ffaSHans Petter Selasky 	}
943*d6b92ffaSHans Petter Selasky 	return 0;
944*d6b92ffaSHans Petter Selasky }
945*d6b92ffaSHans Petter Selasky 
pass_on_spines_catch_lines(ibnd_chassis_t * chassis)946*d6b92ffaSHans Petter Selasky static int pass_on_spines_catch_lines(ibnd_chassis_t * chassis)
947*d6b92ffaSHans Petter Selasky {
948*d6b92ffaSHans Petter Selasky 	ibnd_node_t *node, *remnode;
949*d6b92ffaSHans Petter Selasky 	ibnd_port_t *port;
950*d6b92ffaSHans Petter Selasky 	int i, p;
951*d6b92ffaSHans Petter Selasky 
952*d6b92ffaSHans Petter Selasky 	for (i = 1; i <= SPINES_MAX_NUM; i++) {
953*d6b92ffaSHans Petter Selasky 		int is_4700x2;
954*d6b92ffaSHans Petter Selasky 
955*d6b92ffaSHans Petter Selasky 		node = chassis->spinenode[i];
956*d6b92ffaSHans Petter Selasky 		if (!node)
957*d6b92ffaSHans Petter Selasky 			continue;	/* empty slot */
958*d6b92ffaSHans Petter Selasky 
959*d6b92ffaSHans Petter Selasky 		is_4700x2 = is_spine_4700x2(node);
960*d6b92ffaSHans Petter Selasky 
961*d6b92ffaSHans Petter Selasky 		for (p = 1; p <= node->numports; p++) {
962*d6b92ffaSHans Petter Selasky 			port = node->ports[p];
963*d6b92ffaSHans Petter Selasky 			if (!port || !port->remoteport)
964*d6b92ffaSHans Petter Selasky 				continue;
965*d6b92ffaSHans Petter Selasky 
966*d6b92ffaSHans Petter Selasky 			/*
967*d6b92ffaSHans Petter Selasky 			 * ISR4700 double density fabric board ports 19-36 are
968*d6b92ffaSHans Petter Selasky 			 * chassis external ports, so skip them
969*d6b92ffaSHans Petter Selasky 			 */
970*d6b92ffaSHans Petter Selasky 			if (is_4700x2 && (port->portnum > 18))
971*d6b92ffaSHans Petter Selasky 				continue;
972*d6b92ffaSHans Petter Selasky 
973*d6b92ffaSHans Petter Selasky 			remnode = port->remoteport->node;
974*d6b92ffaSHans Petter Selasky 
975*d6b92ffaSHans Petter Selasky 			if (!remnode->ch_found)
976*d6b92ffaSHans Petter Selasky 				continue;	/* some error - line/router not initialized ? FIXME */
977*d6b92ffaSHans Petter Selasky 
978*d6b92ffaSHans Petter Selasky 			if (insert_line_router(remnode, chassis))
979*d6b92ffaSHans Petter Selasky 				return -1;
980*d6b92ffaSHans Petter Selasky 		}
981*d6b92ffaSHans Petter Selasky 	}
982*d6b92ffaSHans Petter Selasky 	return 0;
983*d6b92ffaSHans Petter Selasky }
984*d6b92ffaSHans Petter Selasky 
985*d6b92ffaSHans Petter Selasky /*
986*d6b92ffaSHans Petter Selasky 	Stupid interpolation algorithm...
987*d6b92ffaSHans Petter Selasky 	But nothing to do - have to be compliant with VoltaireSM/NMS
988*d6b92ffaSHans Petter Selasky */
pass_on_spines_interpolate_chguid(ibnd_chassis_t * chassis)989*d6b92ffaSHans Petter Selasky static void pass_on_spines_interpolate_chguid(ibnd_chassis_t * chassis)
990*d6b92ffaSHans Petter Selasky {
991*d6b92ffaSHans Petter Selasky 	ibnd_node_t *node;
992*d6b92ffaSHans Petter Selasky 	int i;
993*d6b92ffaSHans Petter Selasky 
994*d6b92ffaSHans Petter Selasky 	for (i = 1; i <= SPINES_MAX_NUM; i++) {
995*d6b92ffaSHans Petter Selasky 		node = chassis->spinenode[i];
996*d6b92ffaSHans Petter Selasky 		if (!node)
997*d6b92ffaSHans Petter Selasky 			continue;	/* skip the empty slots */
998*d6b92ffaSHans Petter Selasky 
999*d6b92ffaSHans Petter Selasky 		/* take first guid minus one to be consistent with SM */
1000*d6b92ffaSHans Petter Selasky 		chassis->chassisguid = node->guid - 1;
1001*d6b92ffaSHans Petter Selasky 		break;
1002*d6b92ffaSHans Petter Selasky 	}
1003*d6b92ffaSHans Petter Selasky }
1004*d6b92ffaSHans Petter Selasky 
1005*d6b92ffaSHans Petter Selasky /*
1006*d6b92ffaSHans Petter Selasky 	This function fills chassis structure with all nodes
1007*d6b92ffaSHans Petter Selasky 	in that chassis
1008*d6b92ffaSHans Petter Selasky 	chassis structure = structure of one standalone chassis
1009*d6b92ffaSHans Petter Selasky */
build_chassis(ibnd_node_t * node,ibnd_chassis_t * chassis)1010*d6b92ffaSHans Petter Selasky static int build_chassis(ibnd_node_t * node, ibnd_chassis_t * chassis)
1011*d6b92ffaSHans Petter Selasky {
1012*d6b92ffaSHans Petter Selasky 	int p = 0;
1013*d6b92ffaSHans Petter Selasky 	ibnd_node_t *remnode = 0;
1014*d6b92ffaSHans Petter Selasky 	ibnd_port_t *port = 0;
1015*d6b92ffaSHans Petter Selasky 
1016*d6b92ffaSHans Petter Selasky 	/* we get here with node = chassis_spine */
1017*d6b92ffaSHans Petter Selasky 	if (insert_spine(node, chassis))
1018*d6b92ffaSHans Petter Selasky 		return -1;
1019*d6b92ffaSHans Petter Selasky 
1020*d6b92ffaSHans Petter Selasky 	/* loop: pass on all ports of node */
1021*d6b92ffaSHans Petter Selasky 	for (p = 1; p <= node->numports; p++) {
1022*d6b92ffaSHans Petter Selasky 
1023*d6b92ffaSHans Petter Selasky 		port = node->ports[p];
1024*d6b92ffaSHans Petter Selasky 		if (!port || !port->remoteport)
1025*d6b92ffaSHans Petter Selasky 			continue;
1026*d6b92ffaSHans Petter Selasky 
1027*d6b92ffaSHans Petter Selasky 		/*
1028*d6b92ffaSHans Petter Selasky 		 * ISR4700 double density fabric board ports 19-36 are
1029*d6b92ffaSHans Petter Selasky 		 * chassis external ports, so skip them
1030*d6b92ffaSHans Petter Selasky 		 */
1031*d6b92ffaSHans Petter Selasky 		if (is_spine_4700x2(node) && (port->portnum > 18))
1032*d6b92ffaSHans Petter Selasky 			continue;
1033*d6b92ffaSHans Petter Selasky 
1034*d6b92ffaSHans Petter Selasky 		remnode = port->remoteport->node;
1035*d6b92ffaSHans Petter Selasky 
1036*d6b92ffaSHans Petter Selasky 		if (!remnode->ch_found)
1037*d6b92ffaSHans Petter Selasky 			continue;	/* some error - line or router not initialized ? FIXME */
1038*d6b92ffaSHans Petter Selasky 
1039*d6b92ffaSHans Petter Selasky 		insert_line_router(remnode, chassis);
1040*d6b92ffaSHans Petter Selasky 	}
1041*d6b92ffaSHans Petter Selasky 
1042*d6b92ffaSHans Petter Selasky 	if (pass_on_lines_catch_spines(chassis))
1043*d6b92ffaSHans Petter Selasky 		return -1;
1044*d6b92ffaSHans Petter Selasky 	/* this pass needed for to catch routers, since routers connected only */
1045*d6b92ffaSHans Petter Selasky 	/* to spines in slot 1 or 4 and we could miss them first time */
1046*d6b92ffaSHans Petter Selasky 	if (pass_on_spines_catch_lines(chassis))
1047*d6b92ffaSHans Petter Selasky 		return -1;
1048*d6b92ffaSHans Petter Selasky 
1049*d6b92ffaSHans Petter Selasky 	/* additional 2 passes needed for to overcome a problem of pure "in-chassis" */
1050*d6b92ffaSHans Petter Selasky 	/* connectivity - extra pass to ensure that all related chips/modules */
1051*d6b92ffaSHans Petter Selasky 	/* inserted into the chassis */
1052*d6b92ffaSHans Petter Selasky 	if (pass_on_lines_catch_spines(chassis))
1053*d6b92ffaSHans Petter Selasky 		return -1;
1054*d6b92ffaSHans Petter Selasky 	if (pass_on_spines_catch_lines(chassis))
1055*d6b92ffaSHans Petter Selasky 		return -1;
1056*d6b92ffaSHans Petter Selasky 	pass_on_spines_interpolate_chguid(chassis);
1057*d6b92ffaSHans Petter Selasky 
1058*d6b92ffaSHans Petter Selasky 	return 0;
1059*d6b92ffaSHans Petter Selasky }
1060*d6b92ffaSHans Petter Selasky 
1061*d6b92ffaSHans Petter Selasky /*========================================================*/
1062*d6b92ffaSHans Petter Selasky /*                INTERNAL TO EXTERNAL PORT MAPPING       */
1063*d6b92ffaSHans Petter Selasky /*========================================================*/
1064*d6b92ffaSHans Petter Selasky 
1065*d6b92ffaSHans Petter Selasky /*
1066*d6b92ffaSHans Petter Selasky Description : On ISR9288/9096 external ports indexing
1067*d6b92ffaSHans Petter Selasky               is not matching the internal ( anafa ) port
1068*d6b92ffaSHans Petter Selasky               indexes. Use this MAP to translate the data you get from
1069*d6b92ffaSHans Petter Selasky               the OpenIB diagnostics (smpquery, ibroute, ibtracert, etc.)
1070*d6b92ffaSHans Petter Selasky 
1071*d6b92ffaSHans Petter Selasky Module : sLB-24
1072*d6b92ffaSHans Petter Selasky                 anafa 1             anafa 2
1073*d6b92ffaSHans Petter Selasky ext port | 13 14 15 16 17 18 | 19 20 21 22 23 24
1074*d6b92ffaSHans Petter Selasky int port | 22 23 24 18 17 16 | 22 23 24 18 17 16
1075*d6b92ffaSHans Petter Selasky ext port | 1  2  3  4  5  6  | 7  8  9  10 11 12
1076*d6b92ffaSHans Petter Selasky int port | 19 20 21 15 14 13 | 19 20 21 15 14 13
1077*d6b92ffaSHans Petter Selasky ------------------------------------------------
1078*d6b92ffaSHans Petter Selasky 
1079*d6b92ffaSHans Petter Selasky Module : sLB-8
1080*d6b92ffaSHans Petter Selasky                 anafa 1             anafa 2
1081*d6b92ffaSHans Petter Selasky ext port | 13 14 15 16 17 18 | 19 20 21 22 23 24
1082*d6b92ffaSHans Petter Selasky int port | 24 23 22 18 17 16 | 24 23 22 18 17 16
1083*d6b92ffaSHans Petter Selasky ext port | 1  2  3  4  5  6  | 7  8  9  10 11 12
1084*d6b92ffaSHans Petter Selasky int port | 21 20 19 15 14 13 | 21 20 19 15 14 13
1085*d6b92ffaSHans Petter Selasky 
1086*d6b92ffaSHans Petter Selasky ----------->
1087*d6b92ffaSHans Petter Selasky                 anafa 1             anafa 2
1088*d6b92ffaSHans Petter Selasky ext port | -  -  5  -  -  6  | -  -  7  -  -  8
1089*d6b92ffaSHans Petter Selasky int port | 24 23 22 18 17 16 | 24 23 22 18 17 16
1090*d6b92ffaSHans Petter Selasky ext port | -  -  1  -  -  2  | -  -  3  -  -  4
1091*d6b92ffaSHans Petter Selasky int port | 21 20 19 15 14 13 | 21 20 19 15 14 13
1092*d6b92ffaSHans Petter Selasky ------------------------------------------------
1093*d6b92ffaSHans Petter Selasky 
1094*d6b92ffaSHans Petter Selasky Module : sLB-2024
1095*d6b92ffaSHans Petter Selasky 
1096*d6b92ffaSHans Petter Selasky ext port | 13 14 15 16 17 18 19 20 21 22 23 24
1097*d6b92ffaSHans Petter Selasky A1 int port| 13 14 15 16 17 18 19 20 21 22 23 24
1098*d6b92ffaSHans Petter Selasky ext port | 1 2 3 4 5 6 7 8 9 10 11 12
1099*d6b92ffaSHans Petter Selasky A2 int port| 13 14 15 16 17 18 19 20 21 22 23 24
1100*d6b92ffaSHans Petter Selasky ---------------------------------------------------
1101*d6b92ffaSHans Petter Selasky 
1102*d6b92ffaSHans Petter Selasky Module : sLB-4018
1103*d6b92ffaSHans Petter Selasky 
1104*d6b92ffaSHans Petter Selasky int port | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
1105*d6b92ffaSHans Petter Selasky ext port |  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18
1106*d6b92ffaSHans Petter Selasky ---------------------------------------------------
1107*d6b92ffaSHans Petter Selasky 
1108*d6b92ffaSHans Petter Selasky Module : sFB-4700X2
1109*d6b92ffaSHans Petter Selasky 
1110*d6b92ffaSHans Petter Selasky   12X port -> 3 x 4X ports:
1111*d6b92ffaSHans Petter Selasky 
1112*d6b92ffaSHans Petter Selasky A1 int port | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
1113*d6b92ffaSHans Petter Selasky    ext port |  7  7  7  8  8  8  9  9  9 10 10 10 11 11 11 12 12 12
1114*d6b92ffaSHans Petter Selasky A2 int port | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
1115*d6b92ffaSHans Petter Selasky    ext port |  1  1  1  2  2  2  3  3  3  4  4  4  5  5  5  6  6  6
1116*d6b92ffaSHans Petter Selasky 
1117*d6b92ffaSHans Petter Selasky */
1118*d6b92ffaSHans Petter Selasky 
1119*d6b92ffaSHans Petter Selasky int int2ext_map_slb24[2][25] = {
1120*d6b92ffaSHans Petter Selasky 	{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 5, 4, 18, 17, 16, 1, 2, 3,
1121*d6b92ffaSHans Petter Selasky 	 13, 14, 15},
1122*d6b92ffaSHans Petter Selasky 	{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 11, 10, 24, 23, 22, 7, 8, 9,
1123*d6b92ffaSHans Petter Selasky 	 19, 20, 21}
1124*d6b92ffaSHans Petter Selasky };
1125*d6b92ffaSHans Petter Selasky 
1126*d6b92ffaSHans Petter Selasky int int2ext_map_slb8[2][25] = {
1127*d6b92ffaSHans Petter Selasky 	{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 6, 6, 6, 1, 1, 1, 5, 5,
1128*d6b92ffaSHans Petter Selasky 	 5},
1129*d6b92ffaSHans Petter Selasky 	{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 8, 8, 8, 3, 3, 3, 7, 7,
1130*d6b92ffaSHans Petter Selasky 	 7}
1131*d6b92ffaSHans Petter Selasky };
1132*d6b92ffaSHans Petter Selasky 
1133*d6b92ffaSHans Petter Selasky int int2ext_map_slb2024[2][25] = {
1134*d6b92ffaSHans Petter Selasky 	{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 14, 15, 16, 17, 18, 19, 20,
1135*d6b92ffaSHans Petter Selasky 	 21, 22, 23, 24},
1136*d6b92ffaSHans Petter Selasky 	{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
1137*d6b92ffaSHans Petter Selasky 	 11, 12}
1138*d6b92ffaSHans Petter Selasky };
1139*d6b92ffaSHans Petter Selasky 
1140*d6b92ffaSHans Petter Selasky int int2ext_map_slb4018[37] = {
1141*d6b92ffaSHans Petter Selasky 	0,
1142*d6b92ffaSHans Petter Selasky 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1143*d6b92ffaSHans Petter Selasky 	1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18
1144*d6b92ffaSHans Petter Selasky };
1145*d6b92ffaSHans Petter Selasky 
1146*d6b92ffaSHans Petter Selasky int int2ext_map_sfb4700x2[2][37] = {
1147*d6b92ffaSHans Petter Selasky 	{0,
1148*d6b92ffaSHans Petter Selasky 	 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1149*d6b92ffaSHans Petter Selasky 	 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 11, 12, 12, 12},
1150*d6b92ffaSHans Petter Selasky 	{0,
1151*d6b92ffaSHans Petter Selasky 	 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1152*d6b92ffaSHans Petter Selasky 	 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6}
1153*d6b92ffaSHans Petter Selasky };
1154*d6b92ffaSHans Petter Selasky 
1155*d6b92ffaSHans Petter Selasky /*	reference			{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 }; */
1156*d6b92ffaSHans Petter Selasky 
1157*d6b92ffaSHans Petter Selasky /* map internal ports to external ports if appropriate */
voltaire_portmap(ibnd_port_t * port)1158*d6b92ffaSHans Petter Selasky static void voltaire_portmap(ibnd_port_t * port)
1159*d6b92ffaSHans Petter Selasky {
1160*d6b92ffaSHans Petter Selasky 	int portnum = port->portnum;
1161*d6b92ffaSHans Petter Selasky 	int chipnum = 0;
1162*d6b92ffaSHans Petter Selasky 	ibnd_node_t *node = port->node;
1163*d6b92ffaSHans Petter Selasky 	int is_4700_line = is_line_4700(node);
1164*d6b92ffaSHans Petter Selasky 	int is_4700x2_spine = is_spine_4700x2(node);
1165*d6b92ffaSHans Petter Selasky 
1166*d6b92ffaSHans Petter Selasky 	if (!node->ch_found || (!is_line(node) && !is_4700x2_spine)) {
1167*d6b92ffaSHans Petter Selasky 		port->ext_portnum = 0;
1168*d6b92ffaSHans Petter Selasky 		return;
1169*d6b92ffaSHans Petter Selasky 	}
1170*d6b92ffaSHans Petter Selasky 
1171*d6b92ffaSHans Petter Selasky 	if (((is_4700_line || is_4700x2_spine) &&
1172*d6b92ffaSHans Petter Selasky 	     (portnum < 19 || portnum > 36)) ||
1173*d6b92ffaSHans Petter Selasky 	    ((!is_4700_line && !is_4700x2_spine) &&
1174*d6b92ffaSHans Petter Selasky 	     (portnum < 13 || portnum > 24))) {
1175*d6b92ffaSHans Petter Selasky 			port->ext_portnum = 0;
1176*d6b92ffaSHans Petter Selasky 		return;
1177*d6b92ffaSHans Petter Selasky 	}
1178*d6b92ffaSHans Petter Selasky 
1179*d6b92ffaSHans Petter Selasky 	if (port->node->ch_anafanum < 1 || port->node->ch_anafanum > 2) {
1180*d6b92ffaSHans Petter Selasky 		port->ext_portnum = 0;
1181*d6b92ffaSHans Petter Selasky 		return;
1182*d6b92ffaSHans Petter Selasky 	}
1183*d6b92ffaSHans Petter Selasky 
1184*d6b92ffaSHans Petter Selasky 	chipnum = port->node->ch_anafanum - 1;
1185*d6b92ffaSHans Petter Selasky 
1186*d6b92ffaSHans Petter Selasky 	if (is_line_24(node))
1187*d6b92ffaSHans Petter Selasky 		port->ext_portnum = int2ext_map_slb24[chipnum][portnum];
1188*d6b92ffaSHans Petter Selasky 	else if (is_line_2024(node))
1189*d6b92ffaSHans Petter Selasky 		port->ext_portnum = int2ext_map_slb2024[chipnum][portnum];
1190*d6b92ffaSHans Petter Selasky 	/* sLB-4018: Only one asic per LB */
1191*d6b92ffaSHans Petter Selasky 	else if (is_4700_line)
1192*d6b92ffaSHans Petter Selasky 		port->ext_portnum = int2ext_map_slb4018[portnum];
1193*d6b92ffaSHans Petter Selasky 	/* sFB-4700X2 4X port */
1194*d6b92ffaSHans Petter Selasky 	else if (is_4700x2_spine)
1195*d6b92ffaSHans Petter Selasky 		port->ext_portnum = int2ext_map_sfb4700x2[chipnum][portnum];
1196*d6b92ffaSHans Petter Selasky 	else
1197*d6b92ffaSHans Petter Selasky 		port->ext_portnum = int2ext_map_slb8[chipnum][portnum];
1198*d6b92ffaSHans Petter Selasky }
1199*d6b92ffaSHans Petter Selasky 
add_chassis(chassis_scan_t * chassis_scan)1200*d6b92ffaSHans Petter Selasky static int add_chassis(chassis_scan_t * chassis_scan)
1201*d6b92ffaSHans Petter Selasky {
1202*d6b92ffaSHans Petter Selasky 	if (!(chassis_scan->current_chassis =
1203*d6b92ffaSHans Petter Selasky 	      calloc(1, sizeof(ibnd_chassis_t)))) {
1204*d6b92ffaSHans Petter Selasky 		IBND_ERROR("OOM: failed to allocate chassis object\n");
1205*d6b92ffaSHans Petter Selasky 		return -1;
1206*d6b92ffaSHans Petter Selasky 	}
1207*d6b92ffaSHans Petter Selasky 
1208*d6b92ffaSHans Petter Selasky 	if (chassis_scan->first_chassis == NULL) {
1209*d6b92ffaSHans Petter Selasky 		chassis_scan->first_chassis = chassis_scan->current_chassis;
1210*d6b92ffaSHans Petter Selasky 		chassis_scan->last_chassis = chassis_scan->current_chassis;
1211*d6b92ffaSHans Petter Selasky 	} else {
1212*d6b92ffaSHans Petter Selasky 		chassis_scan->last_chassis->next =
1213*d6b92ffaSHans Petter Selasky 		    chassis_scan->current_chassis;
1214*d6b92ffaSHans Petter Selasky 		chassis_scan->last_chassis = chassis_scan->current_chassis;
1215*d6b92ffaSHans Petter Selasky 	}
1216*d6b92ffaSHans Petter Selasky 	return 0;
1217*d6b92ffaSHans Petter Selasky }
1218*d6b92ffaSHans Petter Selasky 
add_node_to_chassis(ibnd_chassis_t * chassis,ibnd_node_t * node)1219*d6b92ffaSHans Petter Selasky static void add_node_to_chassis(ibnd_chassis_t * chassis, ibnd_node_t * node)
1220*d6b92ffaSHans Petter Selasky {
1221*d6b92ffaSHans Petter Selasky 	node->chassis = chassis;
1222*d6b92ffaSHans Petter Selasky 	node->next_chassis_node = chassis->nodes;
1223*d6b92ffaSHans Petter Selasky 	chassis->nodes = node;
1224*d6b92ffaSHans Petter Selasky }
1225*d6b92ffaSHans Petter Selasky 
1226*d6b92ffaSHans Petter Selasky /*
1227*d6b92ffaSHans Petter Selasky 	Main grouping function
1228*d6b92ffaSHans Petter Selasky 	Algorithm:
1229*d6b92ffaSHans Petter Selasky 	1. pass on every Voltaire node
1230*d6b92ffaSHans Petter Selasky 	2. catch spine chip for every Voltaire node
1231*d6b92ffaSHans Petter Selasky 		2.1 build/interpolate chassis around this chip
1232*d6b92ffaSHans Petter Selasky 		2.2 go to 1.
1233*d6b92ffaSHans Petter Selasky 	3. pass on non Voltaire nodes (SystemImageGUID based grouping)
1234*d6b92ffaSHans Petter Selasky 	4. now group non Voltaire nodes by SystemImageGUID
1235*d6b92ffaSHans Petter Selasky 	Returns:
1236*d6b92ffaSHans Petter Selasky 	0 on success, -1 on failure
1237*d6b92ffaSHans Petter Selasky */
group_nodes(ibnd_fabric_t * fabric)1238*d6b92ffaSHans Petter Selasky int group_nodes(ibnd_fabric_t * fabric)
1239*d6b92ffaSHans Petter Selasky {
1240*d6b92ffaSHans Petter Selasky 	ibnd_node_t *node;
1241*d6b92ffaSHans Petter Selasky 	int chassisnum = 0;
1242*d6b92ffaSHans Petter Selasky 	ibnd_chassis_t *chassis;
1243*d6b92ffaSHans Petter Selasky 	ibnd_chassis_t *ch, *ch_next;
1244*d6b92ffaSHans Petter Selasky 	chassis_scan_t chassis_scan;
1245*d6b92ffaSHans Petter Selasky 	int vendor_id;
1246*d6b92ffaSHans Petter Selasky 
1247*d6b92ffaSHans Petter Selasky 	chassis_scan.first_chassis = NULL;
1248*d6b92ffaSHans Petter Selasky 	chassis_scan.current_chassis = NULL;
1249*d6b92ffaSHans Petter Selasky 	chassis_scan.last_chassis = NULL;
1250*d6b92ffaSHans Petter Selasky 
1251*d6b92ffaSHans Petter Selasky 	/* first pass on switches and build for every Voltaire node */
1252*d6b92ffaSHans Petter Selasky 	/* an appropriate chassis record (slotnum and position) */
1253*d6b92ffaSHans Petter Selasky 	/* according to internal connectivity */
1254*d6b92ffaSHans Petter Selasky 	/* not very efficient but clear code so... */
1255*d6b92ffaSHans Petter Selasky 	for (node = fabric->switches; node; node = node->type_next) {
1256*d6b92ffaSHans Petter Selasky 
1257*d6b92ffaSHans Petter Selasky 		vendor_id = mad_get_field(node->info, 0,IB_NODE_VENDORID_F);
1258*d6b92ffaSHans Petter Selasky 
1259*d6b92ffaSHans Petter Selasky 		if (vendor_id == VTR_VENDOR_ID
1260*d6b92ffaSHans Petter Selasky 		    && fill_voltaire_chassis_record(node))
1261*d6b92ffaSHans Petter Selasky 			goto cleanup;
1262*d6b92ffaSHans Petter Selasky 		else if (vendor_id == MLX_VENDOR_ID
1263*d6b92ffaSHans Petter Selasky 			&& fill_mellanox_chassis_record(node))
1264*d6b92ffaSHans Petter Selasky 			goto cleanup;
1265*d6b92ffaSHans Petter Selasky 
1266*d6b92ffaSHans Petter Selasky 	}
1267*d6b92ffaSHans Petter Selasky 
1268*d6b92ffaSHans Petter Selasky 	/* separate every Voltaire chassis from each other and build linked list of them */
1269*d6b92ffaSHans Petter Selasky 	/* algorithm: catch spine and find all surrounding nodes */
1270*d6b92ffaSHans Petter Selasky 	for (node = fabric->switches; node; node = node->type_next) {
1271*d6b92ffaSHans Petter Selasky 		if (mad_get_field(node->info, 0,
1272*d6b92ffaSHans Petter Selasky 				  IB_NODE_VENDORID_F) != VTR_VENDOR_ID)
1273*d6b92ffaSHans Petter Selasky 			continue;
1274*d6b92ffaSHans Petter Selasky 		if (!node->ch_found
1275*d6b92ffaSHans Petter Selasky 		    || (node->chassis && node->chassis->chassisnum)
1276*d6b92ffaSHans Petter Selasky 		    || !is_spine(node))
1277*d6b92ffaSHans Petter Selasky 			continue;
1278*d6b92ffaSHans Petter Selasky 		if (add_chassis(&chassis_scan))
1279*d6b92ffaSHans Petter Selasky 			goto cleanup;
1280*d6b92ffaSHans Petter Selasky 		chassis_scan.current_chassis->chassisnum = ++chassisnum;
1281*d6b92ffaSHans Petter Selasky 		if (build_chassis(node, chassis_scan.current_chassis))
1282*d6b92ffaSHans Petter Selasky 			goto cleanup;
1283*d6b92ffaSHans Petter Selasky 	}
1284*d6b92ffaSHans Petter Selasky 
1285*d6b92ffaSHans Petter Selasky 	/* now make pass on nodes for chassis which are not Voltaire */
1286*d6b92ffaSHans Petter Selasky 	/* grouped by common SystemImageGUID */
1287*d6b92ffaSHans Petter Selasky 	for (node = fabric->nodes; node; node = node->next) {
1288*d6b92ffaSHans Petter Selasky 		if (mad_get_field(node->info, 0,
1289*d6b92ffaSHans Petter Selasky 				  IB_NODE_VENDORID_F) == VTR_VENDOR_ID)
1290*d6b92ffaSHans Petter Selasky 			continue;
1291*d6b92ffaSHans Petter Selasky 		if (mad_get_field64(node->info, 0, IB_NODE_SYSTEM_GUID_F)) {
1292*d6b92ffaSHans Petter Selasky 			chassis = find_chassisguid(fabric, node);
1293*d6b92ffaSHans Petter Selasky 			if (chassis)
1294*d6b92ffaSHans Petter Selasky 				chassis->nodecount++;
1295*d6b92ffaSHans Petter Selasky 			else {
1296*d6b92ffaSHans Petter Selasky 				/* Possible new chassis */
1297*d6b92ffaSHans Petter Selasky 				if (add_chassis(&chassis_scan))
1298*d6b92ffaSHans Petter Selasky 					goto cleanup;
1299*d6b92ffaSHans Petter Selasky 				chassis_scan.current_chassis->chassisguid =
1300*d6b92ffaSHans Petter Selasky 				    get_chassisguid(node);
1301*d6b92ffaSHans Petter Selasky 				chassis_scan.current_chassis->nodecount = 1;
1302*d6b92ffaSHans Petter Selasky 				if (!fabric->chassis)
1303*d6b92ffaSHans Petter Selasky 					fabric->chassis = chassis_scan.first_chassis;
1304*d6b92ffaSHans Petter Selasky 			}
1305*d6b92ffaSHans Petter Selasky 		}
1306*d6b92ffaSHans Petter Selasky 	}
1307*d6b92ffaSHans Petter Selasky 
1308*d6b92ffaSHans Petter Selasky 	/* now, make another pass to see which nodes are part of chassis */
1309*d6b92ffaSHans Petter Selasky 	/* (defined as chassis->nodecount > 1) */
1310*d6b92ffaSHans Petter Selasky 	for (node = fabric->nodes; node; node = node->next) {
1311*d6b92ffaSHans Petter Selasky 
1312*d6b92ffaSHans Petter Selasky 		vendor_id = mad_get_field(node->info, 0,IB_NODE_VENDORID_F);
1313*d6b92ffaSHans Petter Selasky 
1314*d6b92ffaSHans Petter Selasky 		if (vendor_id == VTR_VENDOR_ID)
1315*d6b92ffaSHans Petter Selasky 			continue;
1316*d6b92ffaSHans Petter Selasky 		if (mad_get_field64(node->info, 0, IB_NODE_SYSTEM_GUID_F)) {
1317*d6b92ffaSHans Petter Selasky 			chassis = find_chassisguid(fabric, node);
1318*d6b92ffaSHans Petter Selasky 			if (chassis && chassis->nodecount > 1) {
1319*d6b92ffaSHans Petter Selasky 				if (!chassis->chassisnum)
1320*d6b92ffaSHans Petter Selasky 					chassis->chassisnum = ++chassisnum;
1321*d6b92ffaSHans Petter Selasky 				if (!node->ch_found) {
1322*d6b92ffaSHans Petter Selasky 					node->ch_found = 1;
1323*d6b92ffaSHans Petter Selasky 					add_node_to_chassis(chassis, node);
1324*d6b92ffaSHans Petter Selasky 				}
1325*d6b92ffaSHans Petter Selasky 				else if (vendor_id == MLX_VENDOR_ID){
1326*d6b92ffaSHans Petter Selasky 					insert_mellanox_line_and_spine(node, chassis);
1327*d6b92ffaSHans Petter Selasky 				}
1328*d6b92ffaSHans Petter Selasky 			}
1329*d6b92ffaSHans Petter Selasky 		}
1330*d6b92ffaSHans Petter Selasky 	}
1331*d6b92ffaSHans Petter Selasky 
1332*d6b92ffaSHans Petter Selasky 	fabric->chassis = chassis_scan.first_chassis;
1333*d6b92ffaSHans Petter Selasky 	return 0;
1334*d6b92ffaSHans Petter Selasky 
1335*d6b92ffaSHans Petter Selasky cleanup:
1336*d6b92ffaSHans Petter Selasky 	ch = chassis_scan.first_chassis;
1337*d6b92ffaSHans Petter Selasky 	while (ch) {
1338*d6b92ffaSHans Petter Selasky 		ch_next = ch->next;
1339*d6b92ffaSHans Petter Selasky 		free(ch);
1340*d6b92ffaSHans Petter Selasky 		ch = ch_next;
1341*d6b92ffaSHans Petter Selasky 	}
1342*d6b92ffaSHans Petter Selasky 	fabric->chassis = NULL;
1343*d6b92ffaSHans Petter Selasky 	return -1;
1344*d6b92ffaSHans Petter Selasky }
1345