1 /* $Id$
2  *
3  * This file is subject to the terms and conditions of the GNU General Public
4  * License.  See the file "COPYING" in the main directory of this archive
5  * for more details.
6  *
7  * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
8  */
9 
10 /*
11  * klgraph.c-
12  *      This file specifies the interface between the kernel and the PROM's
13  *      configuration data structures.
14  */
15 
16 #include <linux/types.h>
17 #include <linux/slab.h>
18 #include <asm/sn/sgi.h>
19 #include <asm/sn/sn_sal.h>
20 #include <asm/sn/io.h>
21 #include <asm/sn/iograph.h>
22 #include <asm/sn/invent.h>
23 #include <asm/sn/hcl.h>
24 #include <asm/sn/labelcl.h>
25 #include <asm/sn/kldir.h>
26 #include <asm/sn/klconfig.h>
27 #include <asm/sn/router.h>
28 #include <asm/sn/xtalk/xbow.h>
29 #include <asm/sn/hcl_util.h>
30 
31 // #define KLGRAPH_DEBUG 1
32 #ifdef KLGRAPH_DEBUG
33 #define GRPRINTF(x)	printk x
34 #define CE_GRPANIC	CE_PANIC
35 #else
36 #define GRPRINTF(x)
37 #define CE_GRPANIC	CE_PANIC
38 #endif
39 
40 #include <asm/sn/sn_private.h>
41 
42 extern char arg_maxnodes[];
43 extern u64 klgraph_addr[];
44 void mark_cpuvertex_as_cpu(vertex_hdl_t vhdl, cpuid_t cpuid);
45 extern int is_specified(char *);
46 
47 
48 /*
49  * Support for verbose inventory via hardware graph.
50  * klhwg_invent_alloc allocates the necessary size of inventory information
51  * and fills in the generic information.
52  */
53 invent_generic_t *
klhwg_invent_alloc(cnodeid_t cnode,int class,int size)54 klhwg_invent_alloc(cnodeid_t cnode, int class, int size)
55 {
56 	invent_generic_t *invent;
57 
58 	invent = kmalloc(size, GFP_KERNEL);
59 	if (!invent) return NULL;
60 
61 	invent->ig_module = NODE_MODULEID(cnode);
62 	invent->ig_slot = SLOTNUM_GETSLOT(NODE_SLOTID(cnode));
63 	invent->ig_invclass = class;
64 
65 	return invent;
66 }
67 
68 /*
69  * Add detailed disabled cpu inventory info to the hardware graph.
70  */
71 void
klhwg_disabled_cpu_invent_info(vertex_hdl_t cpuv,cnodeid_t cnode,klcpu_t * cpu,slotid_t slot)72 klhwg_disabled_cpu_invent_info(vertex_hdl_t cpuv,
73                                cnodeid_t cnode,
74                                klcpu_t *cpu, slotid_t slot)
75 {
76 	invent_cpuinfo_t *cpu_invent;
77 	diag_inv_t       *diag_invent;
78 
79 	cpu_invent = (invent_cpuinfo_t *)
80 	klhwg_invent_alloc(cnode, INV_PROCESSOR, sizeof(invent_cpuinfo_t));
81 	if (!cpu_invent)
82 		return;
83 
84 	/* Diag information on this processor */
85 	diag_invent = (diag_inv_t *)
86 	klhwg_invent_alloc(cnode, INV_CPUDIAGVAL, sizeof(diag_inv_t));
87 
88 	if (!diag_invent)
89 		return;
90 
91 
92 	/* Disabled CPU */
93 	cpu_invent->ic_gen.ig_flag = 0x0;
94 	cpu_invent->ic_gen.ig_slot = slot;
95 	cpu_invent->ic_cpu_info.cpuflavor = cpu->cpu_prid;
96 	cpu_invent->ic_cpu_info.cpufq = cpu->cpu_speed;
97 	cpu_invent->ic_cpu_info.sdfreq = cpu->cpu_scachespeed;
98 
99 	cpu_invent->ic_cpu_info.sdsize = cpu->cpu_scachesz;
100 	cpu_invent->ic_cpuid = cpu->cpu_info.virtid;
101 	cpu_invent->ic_slice = cpu->cpu_info.physid;
102 
103 	/* Disabled CPU label */
104 	hwgraph_info_add_LBL(cpuv, INFO_LBL_DETAIL_INVENT,
105 			(arbitrary_info_t) cpu_invent);
106 	hwgraph_info_export_LBL(cpuv, INFO_LBL_DETAIL_INVENT,
107 			sizeof(invent_cpuinfo_t));
108 
109 	/* Diagval label - stores reason for disable +{virt,phys}id +diagval*/
110 	hwgraph_info_add_LBL(cpuv, INFO_LBL_DIAGVAL,
111 			(arbitrary_info_t) diag_invent);
112 
113 	hwgraph_info_export_LBL(cpuv, INFO_LBL_DIAGVAL,
114 			sizeof(diag_inv_t));
115 }
116 
117 /*
118  * Add detailed cpu inventory info to the hardware graph.
119  */
120 void
klhwg_cpu_invent_info(vertex_hdl_t cpuv,cnodeid_t cnode,klcpu_t * cpu)121 klhwg_cpu_invent_info(vertex_hdl_t cpuv,
122 			cnodeid_t cnode,
123 			klcpu_t *cpu)
124 {
125 	invent_cpuinfo_t *cpu_invent;
126 
127 	cpu_invent = (invent_cpuinfo_t *)
128 		klhwg_invent_alloc(cnode, INV_PROCESSOR, sizeof(invent_cpuinfo_t));
129 	if (!cpu_invent)
130 		return;
131 
132 	if (KLCONFIG_INFO_ENABLED((klinfo_t *)cpu))
133 		cpu_invent->ic_gen.ig_flag = INVENT_ENABLED;
134 	else
135 		cpu_invent->ic_gen.ig_flag = 0x0;
136 
137 	cpu_invent->ic_cpu_info.cpuflavor = cpu->cpu_prid;
138 	cpu_invent->ic_cpu_info.cpufq = cpu->cpu_speed;
139 	cpu_invent->ic_cpu_info.sdfreq = cpu->cpu_scachespeed;
140 
141 	cpu_invent->ic_cpu_info.sdsize = cpu->cpu_scachesz;
142 	cpu_invent->ic_cpuid = cpu->cpu_info.virtid;
143 	cpu_invent->ic_slice = cpu_physical_id_to_slice(cpu->cpu_info.virtid);
144 
145 	hwgraph_info_add_LBL(cpuv, INFO_LBL_DETAIL_INVENT,
146 			(arbitrary_info_t) cpu_invent);
147 	hwgraph_info_export_LBL(cpuv, INFO_LBL_DETAIL_INVENT,
148 			sizeof(invent_cpuinfo_t));
149 }
150 
151 /*
152  * Add information about the baseio prom version number
153  * as a part of detailed inventory info in the hwgraph.
154  */
155 void
klhwg_baseio_inventory_add(vertex_hdl_t baseio_vhdl,cnodeid_t cnode)156 klhwg_baseio_inventory_add(vertex_hdl_t baseio_vhdl,cnodeid_t cnode)
157 {
158 	invent_miscinfo_t	*baseio_inventory;
159 	unsigned char		version = 0,revision = 0;
160 
161 	/* Allocate memory for the "detailed inventory" info
162 	 * for the baseio
163 	 */
164 	baseio_inventory = (invent_miscinfo_t *)
165 		klhwg_invent_alloc(cnode, INV_PROM, sizeof(invent_miscinfo_t));
166 	baseio_inventory->im_type = INV_IO6PROM;
167 	/* Store the revision info  in the inventory */
168 	baseio_inventory->im_version = version;
169 	baseio_inventory->im_rev = revision;
170 	/* Put the inventory info in the hardware graph */
171 	hwgraph_info_add_LBL(baseio_vhdl, INFO_LBL_DETAIL_INVENT,
172 			     (arbitrary_info_t) baseio_inventory);
173 	/* Make the information available to the user programs
174 	 * thru hwgfs.
175 	 */
176         hwgraph_info_export_LBL(baseio_vhdl, INFO_LBL_DETAIL_INVENT,
177 				sizeof(invent_miscinfo_t));
178 }
179 
180 /*
181  * Add detailed cpu inventory info to the hardware graph.
182  */
183 void
klhwg_hub_invent_info(vertex_hdl_t hubv,cnodeid_t cnode,klhub_t * hub)184 klhwg_hub_invent_info(vertex_hdl_t hubv,
185 		      cnodeid_t cnode,
186 		      klhub_t *hub)
187 {
188 	invent_miscinfo_t *hub_invent;
189 
190 	hub_invent = (invent_miscinfo_t *)
191 	    klhwg_invent_alloc(cnode, INV_MISC, sizeof(invent_miscinfo_t));
192 	if (!hub_invent)
193 	    return;
194 
195 	if (KLCONFIG_INFO_ENABLED((klinfo_t *)hub))
196 	    hub_invent->im_gen.ig_flag = INVENT_ENABLED;
197 
198 	hub_invent->im_type = INV_HUB;
199 	hub_invent->im_rev = hub->hub_info.revision;
200 	hub_invent->im_speed = hub->hub_speed;
201 	hwgraph_info_add_LBL(hubv, INFO_LBL_DETAIL_INVENT,
202 			     (arbitrary_info_t) hub_invent);
203         hwgraph_info_export_LBL(hubv, INFO_LBL_DETAIL_INVENT,
204 				sizeof(invent_miscinfo_t));
205 }
206 
207 /* ARGSUSED */
208 void
klhwg_add_ice(vertex_hdl_t node_vertex,klhub_t * hub,cnodeid_t cnode)209 klhwg_add_ice(vertex_hdl_t node_vertex, klhub_t *hub, cnodeid_t cnode)
210 {
211 	vertex_hdl_t myicev;
212 	vertex_hdl_t ice_mon;
213 	int rc;
214 	extern struct file_operations shub_mon_fops;
215 
216 	(void) hwgraph_path_add(node_vertex, EDGE_LBL_ICE, &myicev);
217 
218 	HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, myicev, NULL, "Created path for ice vertex for TIO node.\n"));
219 
220 	rc = device_master_set(myicev, node_vertex);
221 	if (rc)
222 		panic("klhwg_add_ice: Unable to create ice vertex.\n");
223 
224 	ice_mon = hwgraph_register(myicev, EDGE_LBL_PERFMON,
225 		0, DEVFS_FL_AUTO_DEVNUM,
226 		0, 0,
227 		S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0,
228 		&shub_mon_fops, (void *)(long)cnode);
229 }
230 
231 /* ARGSUSED */
232 void
klhwg_add_hub(vertex_hdl_t node_vertex,klhub_t * hub,cnodeid_t cnode)233 klhwg_add_hub(vertex_hdl_t node_vertex, klhub_t *hub, cnodeid_t cnode)
234 {
235 	vertex_hdl_t myhubv;
236 	vertex_hdl_t hub_mon;
237 	int rc;
238 	extern struct file_operations shub_mon_fops;
239 
240 	GRPRINTF(("klhwg_add_hub: adding %s\n", EDGE_LBL_HUB));
241 	(void) hwgraph_path_add(node_vertex, EDGE_LBL_HUB, &myhubv);
242 
243 	HWGRAPH_DEBUG((__FILE__, __FUNCTION__,__LINE__, myhubv, NULL, "Created path for hub vertex for Shub node.\n"));
244 
245 	rc = device_master_set(myhubv, node_vertex);
246 	if (rc)
247 		panic("klhwg_add_hub: Unable to create hub vertex.\n");
248 
249 	hub_mon = hwgraph_register(myhubv, EDGE_LBL_PERFMON,
250 		0, DEVFS_FL_AUTO_DEVNUM,
251 		0, 0,
252 		S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0,
253 		&shub_mon_fops, (void *)(long)cnode);
254 }
255 
256 /* ARGSUSED */
257 void
klhwg_add_disabled_cpu(vertex_hdl_t node_vertex,cnodeid_t cnode,klcpu_t * cpu,slotid_t slot)258 klhwg_add_disabled_cpu(vertex_hdl_t node_vertex, cnodeid_t cnode, klcpu_t *cpu, slotid_t slot)
259 {
260         vertex_hdl_t my_cpu;
261         char name[120];
262         cpuid_t cpu_id;
263 	nasid_t nasid;
264 
265 	nasid = COMPACT_TO_NASID_NODEID(cnode);
266         cpu_id = nasid_slice_to_cpuid(nasid, cpu->cpu_info.physid);
267         if(cpu_id != -1){
268 		sprintf(name, "%s/%s/%c", EDGE_LBL_DISABLED, EDGE_LBL_CPU, 'a' + cpu->cpu_info.physid);
269 		(void) hwgraph_path_add(node_vertex, name, &my_cpu);
270 
271 		HWGRAPH_DEBUG((__FILE__, __FUNCTION__,__LINE__, my_cpu, NULL, "Created path for disabled cpu slice.\n"));
272 
273 		mark_cpuvertex_as_cpu(my_cpu, cpu_id);
274 		device_master_set(my_cpu, node_vertex);
275 
276 		klhwg_disabled_cpu_invent_info(my_cpu, cnode, cpu, slot);
277 		return;
278         }
279 }
280 
281 /* ARGSUSED */
282 void
klhwg_add_cpu(vertex_hdl_t node_vertex,cnodeid_t cnode,klcpu_t * cpu)283 klhwg_add_cpu(vertex_hdl_t node_vertex, cnodeid_t cnode, klcpu_t *cpu)
284 {
285         vertex_hdl_t my_cpu, cpu_dir;
286         char name[120];
287         cpuid_t cpu_id;
288 	nasid_t nasid;
289 
290 	nasid = COMPACT_TO_NASID_NODEID(cnode);
291         cpu_id = nasid_slice_to_cpuid(nasid, cpu->cpu_info.physid);
292 
293         sprintf(name, "%s/%d/%c",
294                 EDGE_LBL_CPUBUS,
295                 0,
296                 'a' + cpu->cpu_info.physid);
297 
298         GRPRINTF(("klhwg_add_cpu: adding %s to vertex 0x%p\n", name, node_vertex));
299         (void) hwgraph_path_add(node_vertex, name, &my_cpu);
300 
301 	HWGRAPH_DEBUG((__FILE__, __FUNCTION__,__LINE__, my_cpu, NULL, "Created path for active cpu slice.\n"));
302 
303         mark_cpuvertex_as_cpu(my_cpu, cpu_id);
304         device_master_set(my_cpu, node_vertex);
305 
306         /* Add an alias under the node's CPU directory */
307         if (hwgraph_edge_get(node_vertex, EDGE_LBL_CPU, &cpu_dir) == GRAPH_SUCCESS) {
308                 sprintf(name, "%c", 'a' + cpu->cpu_info.physid);
309                 (void) hwgraph_edge_add(cpu_dir, my_cpu, name);
310 		HWGRAPH_DEBUG((__FILE__, __FUNCTION__,__LINE__, cpu_dir, my_cpu, "Created % from vhdl1 to vhdl2.\n", name));
311         }
312 
313         klhwg_cpu_invent_info(my_cpu, cnode, cpu);
314 }
315 
316 
317 void
klhwg_add_coretalk(cnodeid_t cnode,nasid_t tio_nasid)318 klhwg_add_coretalk(cnodeid_t cnode, nasid_t tio_nasid)
319 {
320 	lboard_t *brd;
321 	vertex_hdl_t coretalk_v, icev;
322 	/*REFERENCED*/
323 	graph_error_t err;
324 
325 	if ((brd = find_lboard((lboard_t *)KL_CONFIG_INFO(tio_nasid), KLTYPE_IOBRICK_XBOW)) == NULL)
326 			return;
327 
328 	if (KL_CONFIG_DUPLICATE_BOARD(brd))
329 	    return;
330 
331 	icev = cnodeid_to_vertex(cnode);
332 
333 	err = hwgraph_path_add(icev, EDGE_LBL_CORETALK, &coretalk_v);
334 	if (err != GRAPH_SUCCESS) {
335 		if (err == GRAPH_DUP)
336 			printk(KERN_WARNING  "klhwg_add_coretalk: Check for "
337                                         "working routers and router links!");
338 
339                  panic("klhwg_add_coretalkk: Failed to add "
340                              "edge: vertex 0x%p to vertex 0x%p,"
341                              "error %d\n",
342                               (void *)icev, (void *)coretalk_v, err);
343         }
344 
345 	HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, coretalk_v, NULL, "Created coretalk path for TIO node.\n"));
346 
347         NODEPDA(cnode)->xbow_vhdl = coretalk_v;
348 
349 }
350 
351 
352 void
klhwg_add_xbow(cnodeid_t cnode,nasid_t nasid)353 klhwg_add_xbow(cnodeid_t cnode, nasid_t nasid)
354 {
355 	lboard_t *brd;
356 	klxbow_t *xbow_p;
357 	nasid_t hub_nasid;
358 	cnodeid_t hub_cnode;
359 	int widgetnum;
360 	vertex_hdl_t xbow_v, hubv;
361 	/*REFERENCED*/
362 	graph_error_t err;
363 
364 	if ((brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IOBRICK_XBOW)) == NULL)
365 			return;
366 
367 	if (KL_CONFIG_DUPLICATE_BOARD(brd))
368 	    return;
369 
370 	if ((xbow_p = (klxbow_t *)find_component(brd, NULL, KLSTRUCT_XBOW))
371 	    == NULL)
372 	    return;
373 
374 	for (widgetnum = HUB_WIDGET_ID_MIN; widgetnum <= HUB_WIDGET_ID_MAX; widgetnum++) {
375 		if (!XBOW_PORT_TYPE_HUB(xbow_p, widgetnum))
376 		    continue;
377 
378 		hub_nasid = XBOW_PORT_NASID(xbow_p, widgetnum);
379 		if (hub_nasid == INVALID_NASID) {
380 			printk(KERN_WARNING  "hub widget %d, skipping xbow graph\n", widgetnum);
381 			continue;
382 		}
383 
384 		hub_cnode = NASID_TO_COMPACT_NODEID(hub_nasid);
385 
386 		if (is_specified(arg_maxnodes) && hub_cnode == INVALID_CNODEID) {
387 			continue;
388 		}
389 
390 		hubv = cnodeid_to_vertex(hub_cnode);
391 
392 		err = hwgraph_path_add(hubv, EDGE_LBL_XTALK, &xbow_v);
393                 if (err != GRAPH_SUCCESS) {
394                         if (err == GRAPH_DUP)
395                                 printk(KERN_WARNING  "klhwg_add_xbow: Check for "
396                                         "working routers and router links!");
397 
398                         panic("klhwg_add_xbow: Failed to add "
399                                 "edge: vertex 0x%p to vertex 0x%p,"
400                                 "error %d\n",
401                                 (void *)hubv, (void *)xbow_v, err);
402                 }
403 
404 		HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, xbow_v, NULL, "Created path for xtalk.\n"));
405 
406 		xswitch_vertex_init(xbow_v);
407 
408 		NODEPDA(hub_cnode)->xbow_vhdl = xbow_v;
409 
410 		/*
411 		 * XXX - This won't work is we ever hook up two hubs
412 		 * by crosstown through a crossbow.
413 		 */
414 		if (hub_nasid != nasid) {
415 			NODEPDA(hub_cnode)->xbow_peer = nasid;
416 			NODEPDA(NASID_TO_COMPACT_NODEID(nasid))->xbow_peer =
417 				hub_nasid;
418 		}
419 
420 	}
421 }
422 
423 
424 /* ARGSUSED */
425 void
klhwg_add_tionode(vertex_hdl_t hwgraph_root,cnodeid_t cnode)426 klhwg_add_tionode(vertex_hdl_t hwgraph_root, cnodeid_t cnode)
427 {
428 	nasid_t tio_nasid;
429 	lboard_t *brd;
430 	klhub_t *hub;
431 	vertex_hdl_t node_vertex = NULL;
432 	char path_buffer[100];
433 	int rv;
434 	char *s;
435 	int board_disabled = 0;
436 
437 	tio_nasid = COMPACT_TO_NASID_NODEID(cnode);
438 	brd = find_lboard((lboard_t *)KL_CONFIG_INFO(tio_nasid), KLTYPE_TIO);
439 	ASSERT(brd);
440 
441 	/* Generate a hardware graph path for this board. */
442 	board_to_path(brd, path_buffer);
443 	rv = hwgraph_path_add(hwgraph_root, path_buffer, &node_vertex);
444 	if (rv != GRAPH_SUCCESS)
445 		panic("TIO Node vertex creation failed.  "
446 					  "Path == %s", path_buffer);
447 
448 	HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, node_vertex, NULL, "Created path for TIO node.\n"));
449 	hub = (klhub_t *)find_first_component(brd, KLSTRUCT_HUB);
450 	ASSERT(hub);
451 	if(hub->hub_info.flags & KLINFO_ENABLE)
452 		board_disabled = 0;
453 	else
454 		board_disabled = 1;
455 
456 	if(!board_disabled) {
457 		mark_nodevertex_as_node(node_vertex,
458 				    cnode + board_disabled * numionodes);
459 
460 		s = dev_to_name(node_vertex, path_buffer, sizeof(path_buffer));
461 		NODEPDA(cnode)->hwg_node_name =
462 					kmalloc(strlen(s) + 1,
463 					GFP_KERNEL);
464 		ASSERT_ALWAYS(NODEPDA(cnode)->hwg_node_name != NULL);
465 		strcpy(NODEPDA(cnode)->hwg_node_name, s);
466 
467 		hubinfo_set(node_vertex, NODEPDA(cnode)->pdinfo);
468 
469 		/* Set up node board's slot */
470 		NODEPDA(cnode)->slotdesc = brd->brd_slot;
471 
472 		/* Set up the module we're in */
473 		NODEPDA(cnode)->geoid = brd->brd_geoid;
474 		NODEPDA(cnode)->module = module_lookup(geo_module(brd->brd_geoid));
475 	}
476 
477         if(!board_disabled)
478                 klhwg_add_ice(node_vertex, hub, cnode);
479 
480 }
481 
482 
483 /* ARGSUSED */
484 void
klhwg_add_node(vertex_hdl_t hwgraph_root,cnodeid_t cnode)485 klhwg_add_node(vertex_hdl_t hwgraph_root, cnodeid_t cnode)
486 {
487 	nasid_t nasid;
488 	lboard_t *brd;
489 	klhub_t *hub;
490 	vertex_hdl_t node_vertex = NULL;
491 	char path_buffer[100];
492 	int rv;
493 	char *s;
494 	int board_disabled = 0;
495 	klcpu_t *cpu;
496 
497 	nasid = COMPACT_TO_NASID_NODEID(cnode);
498 	brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_SNIA);
499 	ASSERT(brd);
500 
501 	do {
502 		vertex_hdl_t cpu_dir;
503 
504 		/* Generate a hardware graph path for this board. */
505 		board_to_path(brd, path_buffer);
506 		rv = hwgraph_path_add(hwgraph_root, path_buffer, &node_vertex);
507 		if (rv != GRAPH_SUCCESS)
508 			panic("Node vertex creation failed.  Path == %s", path_buffer);
509 
510 		HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, node_vertex, NULL, "Created path for SHUB node.\n"));
511 		hub = (klhub_t *)find_first_component(brd, KLSTRUCT_HUB);
512 		ASSERT(hub);
513 		if(hub->hub_info.flags & KLINFO_ENABLE)
514 			board_disabled = 0;
515 		else
516 			board_disabled = 1;
517 
518 		if(!board_disabled) {
519 			mark_nodevertex_as_node(node_vertex,
520 					    cnode + board_disabled * numnodes);
521 
522 			s = dev_to_name(node_vertex, path_buffer, sizeof(path_buffer));
523 			NODEPDA(cnode)->hwg_node_name =
524 						kmalloc(strlen(s) + 1,
525 						GFP_KERNEL);
526 			ASSERT_ALWAYS(NODEPDA(cnode)->hwg_node_name != NULL);
527 			strcpy(NODEPDA(cnode)->hwg_node_name, s);
528 
529 			hubinfo_set(node_vertex, NODEPDA(cnode)->pdinfo);
530 
531 			/* Set up node board's slot */
532 			NODEPDA(cnode)->slotdesc = brd->brd_slot;
533 
534 			/* Set up the module we're in */
535 			NODEPDA(cnode)->geoid = brd->brd_geoid;
536 			NODEPDA(cnode)->module = module_lookup(geo_module(brd->brd_geoid));
537 		}
538 
539 		/* Get the first CPU structure */
540 		cpu = (klcpu_t *)find_first_component(brd, KLSTRUCT_CPU);
541 
542 		/*
543 		* If there's at least 1 CPU, add a "cpu" directory to represent
544 		* the collection of all CPUs attached to this node.
545 		*/
546 		if (cpu) {
547 			graph_error_t rv;
548 
549 			rv = hwgraph_path_add(node_vertex, EDGE_LBL_CPU, &cpu_dir);
550 			if (rv != GRAPH_SUCCESS)
551 				panic("klhwg_add_node: Cannot create CPU directory\n");
552 			HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, cpu_dir, NULL, "Created cpu directiry on SHUB node.\n"));
553 
554 		}
555 
556 		/* Add each CPU */
557 		while (cpu) {
558 			cpuid_t cpu_id;
559 			cpu_id = nasid_slice_to_cpuid(nasid,cpu->cpu_info.physid);
560 			if (cpu_online(cpu_id))
561 				klhwg_add_cpu(node_vertex, cnode, cpu);
562 			else
563 				klhwg_add_disabled_cpu(node_vertex, cnode, cpu, brd->brd_slot);
564 
565 			cpu = (klcpu_t *)
566 				find_component(brd, (klinfo_t *)cpu, KLSTRUCT_CPU);
567 		} /* while */
568 
569 		if(!board_disabled)
570 			klhwg_add_hub(node_vertex, hub, cnode);
571 
572 		brd = KLCF_NEXT(brd);
573 		if (brd)
574 			brd = find_lboard(brd, KLTYPE_SNIA);
575 		else
576 			break;
577 	} while(brd);
578 }
579 
580 
581 /* ARGSUSED */
582 void
klhwg_add_all_routers(vertex_hdl_t hwgraph_root)583 klhwg_add_all_routers(vertex_hdl_t hwgraph_root)
584 {
585 	nasid_t nasid;
586 	cnodeid_t cnode;
587 	lboard_t *brd;
588 	vertex_hdl_t node_vertex;
589 	char path_buffer[100];
590 	int rv;
591 
592 	for (cnode = 0; cnode < numnodes; cnode++) {
593 		nasid = COMPACT_TO_NASID_NODEID(cnode);
594 		brd = find_lboard_class((lboard_t *)KL_CONFIG_INFO(nasid),
595 				KLTYPE_ROUTER);
596 		if (!brd)
597 			/* No routers stored in this node's memory */
598 			continue;
599 
600 		do {
601 			ASSERT(brd);
602 
603 			/* Don't add duplicate boards. */
604 			if (brd->brd_flags & DUPLICATE_BOARD)
605 				continue;
606 
607 			/* Generate a hardware graph path for this board. */
608 			board_to_path(brd, path_buffer);
609 
610 			/* Add the router */
611 			rv = hwgraph_path_add(hwgraph_root, path_buffer, &node_vertex);
612 			if (rv != GRAPH_SUCCESS)
613 				panic("Router vertex creation "
614 						  "failed.  Path == %s",
615 					path_buffer);
616 
617 			HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, node_vertex, NULL, "Created router path.\n"));
618 
619 		/* Find the rest of the routers stored on this node. */
620 		} while ( (brd = find_lboard_class(KLCF_NEXT(brd),
621 			 KLTYPE_ROUTER)) );
622 	}
623 
624 }
625 
626 /* ARGSUSED */
627 void
klhwg_connect_one_router(vertex_hdl_t hwgraph_root,lboard_t * brd,cnodeid_t cnode,nasid_t nasid)628 klhwg_connect_one_router(vertex_hdl_t hwgraph_root, lboard_t *brd,
629 			 cnodeid_t cnode, nasid_t nasid)
630 {
631 	klrou_t *router;
632 	char path_buffer[50];
633 	char dest_path[50];
634 	vertex_hdl_t router_hndl;
635 	vertex_hdl_t dest_hndl;
636 	int rc;
637 	int port;
638 	lboard_t *dest_brd;
639 
640 	/* Don't add duplicate boards. */
641 	if (brd->brd_flags & DUPLICATE_BOARD) {
642 		return;
643 	}
644 
645 	/* Generate a hardware graph path for this board. */
646 	board_to_path(brd, path_buffer);
647 
648 	rc = hwgraph_traverse(hwgraph_root, path_buffer, &router_hndl);
649 
650 	if (rc != GRAPH_SUCCESS && is_specified(arg_maxnodes))
651 			return;
652 
653 	if (rc != GRAPH_SUCCESS)
654 		printk(KERN_WARNING  "Can't find router: %s", path_buffer);
655 
656 	/* We don't know what to do with multiple router components */
657 	if (brd->brd_numcompts != 1) {
658 		panic("klhwg_connect_one_router: %d cmpts on router\n",
659 			brd->brd_numcompts);
660 		return;
661 	}
662 
663 
664 	/* Convert component 0 to klrou_t ptr */
665 	router = (klrou_t *)NODE_OFFSET_TO_K0(NASID_GET(brd),
666 					      brd->brd_compts[0]);
667 
668 	for (port = 1; port <= MAX_ROUTER_PORTS; port++) {
669 		/* See if the port's active */
670 		if (router->rou_port[port].port_nasid == INVALID_NASID) {
671 			GRPRINTF(("klhwg_connect_one_router: port %d inactive.\n",
672 				 port));
673 			continue;
674 		}
675 		if (is_specified(arg_maxnodes) && NASID_TO_COMPACT_NODEID(router->rou_port[port].port_nasid)
676 		    == INVALID_CNODEID) {
677 			continue;
678 		}
679 
680 		dest_brd = (lboard_t *)NODE_OFFSET_TO_K0(
681 				router->rou_port[port].port_nasid,
682 				router->rou_port[port].port_offset);
683 
684 		/* Generate a hardware graph path for this board. */
685 		board_to_path(dest_brd, dest_path);
686 
687 		rc = hwgraph_traverse(hwgraph_root, dest_path, &dest_hndl);
688 
689 		if (rc != GRAPH_SUCCESS) {
690 			if (is_specified(arg_maxnodes) && KL_CONFIG_DUPLICATE_BOARD(dest_brd))
691 				continue;
692 			panic("Can't find router: %s", dest_path);
693 		}
694 
695 		sprintf(dest_path, "%d", port);
696 
697 		rc = hwgraph_edge_add(router_hndl, dest_hndl, dest_path);
698 		if (rc == GRAPH_DUP) {
699 			GRPRINTF(("Skipping port %d. nasid %d %s/%s\n",
700 				  port, router->rou_port[port].port_nasid,
701 				  path_buffer, dest_path));
702 			continue;
703 		}
704 
705 		if (rc != GRAPH_SUCCESS && !is_specified(arg_maxnodes))
706 			panic("Can't create edge: %s/%s to vertex 0x%p error 0x%x\n",
707 				path_buffer, dest_path, (void *)dest_hndl, rc);
708 
709 		HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, router_hndl, dest_hndl, "Created edge %s from vhdl1 to vhdl2.\n", dest_path));
710 
711 	}
712 }
713 
714 
715 void
klhwg_connect_routers(vertex_hdl_t hwgraph_root)716 klhwg_connect_routers(vertex_hdl_t hwgraph_root)
717 {
718 	nasid_t nasid;
719 	cnodeid_t cnode;
720 	lboard_t *brd;
721 
722 	for (cnode = 0; cnode < numnodes; cnode++) {
723 		nasid = COMPACT_TO_NASID_NODEID(cnode);
724 
725 		GRPRINTF(("klhwg_connect_routers: Connecting routers on cnode %d\n",
726 			cnode));
727 
728 		brd = find_lboard_class((lboard_t *)KL_CONFIG_INFO(nasid),
729 				KLTYPE_ROUTER);
730 
731 		if (!brd)
732 			continue;
733 
734 		do {
735 
736 			nasid = COMPACT_TO_NASID_NODEID(cnode);
737 
738 			klhwg_connect_one_router(hwgraph_root, brd,
739 						 cnode, nasid);
740 
741 		/* Find the rest of the routers stored on this node. */
742 		} while ( (brd = find_lboard_class(KLCF_NEXT(brd), KLTYPE_ROUTER)) );
743 	}
744 }
745 
746 
747 
748 void
klhwg_connect_hubs(vertex_hdl_t hwgraph_root)749 klhwg_connect_hubs(vertex_hdl_t hwgraph_root)
750 {
751 	nasid_t nasid;
752 	cnodeid_t cnode;
753 	lboard_t *brd;
754 	klhub_t *hub;
755 	lboard_t *dest_brd;
756 	vertex_hdl_t hub_hndl;
757 	vertex_hdl_t dest_hndl;
758 	char path_buffer[50];
759 	char dest_path[50];
760 	graph_error_t rc;
761 	int port;
762 
763 	for (cnode = 0; cnode < numionodes; cnode++) {
764 		nasid = COMPACT_TO_NASID_NODEID(cnode);
765 
766 		if (!(nasid & 1)) {
767 			brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_SNIA);
768 			ASSERT(brd);
769 		} else {
770 			brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_TIO);
771 			ASSERT(brd);
772 		}
773 
774 		hub = (klhub_t *)find_first_component(brd, KLSTRUCT_HUB);
775 		ASSERT(hub);
776 
777 		for (port = 1; port <= MAX_NI_PORTS; port++) {
778 			/* See if the port's active */
779 			if (hub->hub_port[port].port_nasid == INVALID_NASID) {
780 				GRPRINTF(("klhwg_connect_hubs: port inactive.\n"));
781 				continue;
782 			}
783 
784 			if (is_specified(arg_maxnodes) && NASID_TO_COMPACT_NODEID(hub->hub_port[port].port_nasid) == INVALID_CNODEID)
785 				continue;
786 
787 			/* Generate a hardware graph path for this board. */
788 			board_to_path(brd, path_buffer);
789 			rc = hwgraph_traverse(hwgraph_root, path_buffer, &hub_hndl);
790 			if (rc != GRAPH_SUCCESS)
791 				printk(KERN_WARNING  "Can't find hub: %s", path_buffer);
792 
793 			dest_brd = (lboard_t *)NODE_OFFSET_TO_K0(
794 					hub->hub_port[port].port_nasid,
795 					hub->hub_port[port].port_offset);
796 
797 			/* Generate a hardware graph path for this board. */
798 			board_to_path(dest_brd, dest_path);
799 
800 			rc = hwgraph_traverse(hwgraph_root, dest_path, &dest_hndl);
801 
802 			if (rc != GRAPH_SUCCESS) {
803 				if (is_specified(arg_maxnodes) && KL_CONFIG_DUPLICATE_BOARD(dest_brd))
804 					continue;
805 				panic("Can't find board: %s", dest_path);
806 			} else {
807 				char buf[1024];
808 
809 
810 				GRPRINTF(("klhwg_connect_hubs: Link from %s to %s.\n",
811 			  	path_buffer, dest_path));
812 
813 				rc = hwgraph_path_add(hub_hndl, EDGE_LBL_INTERCONNECT, &hub_hndl);
814 
815 				HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, hub_hndl, NULL, "Created link path.\n"));
816 
817 				sprintf(buf,"%s/%s",path_buffer,EDGE_LBL_INTERCONNECT);
818 				rc = hwgraph_traverse(hwgraph_root, buf, &hub_hndl);
819 				sprintf(buf,"%d",port);
820 				rc = hwgraph_edge_add(hub_hndl, dest_hndl, buf);
821 
822 				HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, hub_hndl, dest_hndl, "Created edge %s from vhdl1 to vhdl2.\n", buf));
823 
824 				if (rc != GRAPH_SUCCESS)
825 					panic("Can't create edge: %s/%s to vertex 0x%p, error 0x%x\n",
826 					path_buffer, dest_path, (void *)dest_hndl, rc);
827 
828 			}
829 		}
830 	}
831 }
832 
833 /* Store the pci/vme disabled board information as extended administrative
834  * hints which can later be used by the drivers using the device/driver
835  * admin interface.
836  */
837 void
klhwg_device_disable_hints_add(void)838 klhwg_device_disable_hints_add(void)
839 {
840 	cnodeid_t	cnode; 		/* node we are looking at */
841 	nasid_t		nasid;		/* nasid of the node */
842 	lboard_t	*board;		/* board we are looking at */
843 	int		comp_index;	/* component index */
844 	klinfo_t	*component;	/* component in the board we are
845 					 * looking at
846 					 */
847 	char		device_name[MAXDEVNAME];
848 
849 	for(cnode = 0; cnode < numnodes; cnode++) {
850 		nasid = COMPACT_TO_NASID_NODEID(cnode);
851 		board = (lboard_t *)KL_CONFIG_INFO(nasid);
852 		/* Check out all the board info stored  on a node */
853 		while(board) {
854 			/* No need to look at duplicate boards or non-io
855 			 * boards
856 			 */
857 			if (KL_CONFIG_DUPLICATE_BOARD(board) ||
858 			    KLCLASS(board->brd_type) != KLCLASS_IO) {
859 				board = KLCF_NEXT(board);
860 				continue;
861 			}
862 			/* Check out all the components of a board */
863 			for (comp_index = 0;
864 			     comp_index < KLCF_NUM_COMPS(board);
865 			     comp_index++) {
866 				component = KLCF_COMP(board,comp_index);
867 				/* If the component is enabled move on to
868 				 * the next component
869 				 */
870 				if (KLCONFIG_INFO_ENABLED(component))
871 					continue;
872 				/* NOTE : Since the prom only supports
873 				 * the disabling of pci devices the following
874 				 * piece of code makes sense.
875 				 * Make sure that this assumption is valid
876 				 */
877 				/* This component is disabled. Store this
878 				 * hint in the extended device admin table
879 				 */
880 				/* Get the canonical name of the pci device */
881 				device_component_canonical_name_get(board,
882 							    component,
883 							    device_name);
884 #ifdef DEBUG
885 				printf("%s DISABLED\n",device_name);
886 #endif
887 			}
888 			/* go to the next board info stored on this
889 			 * node
890 			 */
891 			board = KLCF_NEXT(board);
892 		}
893 	}
894 }
895 
896 void
klhwg_add_all_modules(vertex_hdl_t hwgraph_root)897 klhwg_add_all_modules(vertex_hdl_t hwgraph_root)
898 {
899 	cmoduleid_t	cm;
900 	char		name[128];
901 	vertex_hdl_t	vhdl;
902 	vertex_hdl_t  module_vhdl;
903 	int		rc;
904 	char		buffer[16];
905 
906 	/* Add devices under each module */
907 
908 	for (cm = 0; cm < nummodules; cm++) {
909 		/* Use module as module vertex fastinfo */
910 
911 		memset(buffer, 0, 16);
912 		format_module_id(buffer, modules[cm]->id, MODULE_FORMAT_BRIEF);
913 		sprintf(name, EDGE_LBL_MODULE "/%s", buffer);
914 
915 		rc = hwgraph_path_add(hwgraph_root, name, &module_vhdl);
916 		ASSERT(rc == GRAPH_SUCCESS);
917 		rc = rc; /* Shut the compiler up */
918 		HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, module_vhdl, NULL, "Created module path.\n"));
919 
920 		hwgraph_fastinfo_set(module_vhdl, (arbitrary_info_t) modules[cm]);
921 
922 		/* Add system controller */
923 		sprintf(name,
924 			EDGE_LBL_MODULE "/%s/" EDGE_LBL_L1,
925 			buffer);
926 
927 		rc = hwgraph_path_add(hwgraph_root, name, &vhdl);
928 		ASSERT_ALWAYS(rc == GRAPH_SUCCESS);
929 		rc = rc; /* Shut the compiler up */
930 		HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, vhdl, NULL, "Created L1 path.\n"));
931 
932 		hwgraph_info_add_LBL(vhdl,
933 				     INFO_LBL_ELSC,
934 				     (arbitrary_info_t) (int64_t) 1);
935 
936 	}
937 }
938 
939 void
klhwg_add_all_nodes(vertex_hdl_t hwgraph_root)940 klhwg_add_all_nodes(vertex_hdl_t hwgraph_root)
941 {
942 	cnodeid_t	cnode;
943 
944 	for (cnode = 0; cnode < numnodes; cnode++) {
945 		klhwg_add_node(hwgraph_root, cnode);
946 	}
947 
948 	for (cnode = numnodes; cnode < numionodes; cnode++) {
949 		klhwg_add_tionode(hwgraph_root, cnode);
950 	}
951 
952 	for (cnode = 0; cnode < numnodes; cnode++) {
953 		klhwg_add_xbow(cnode, cnodeid_to_nasid(cnode));
954 	}
955 
956 	for (cnode = numnodes; cnode < numionodes; cnode++) {
957 		klhwg_add_coretalk(cnode, cnodeid_to_nasid(cnode));
958 	}
959 
960 	/*
961 	 * As for router hardware inventory information, we set this
962 	 * up in router.c.
963 	 */
964 
965 	klhwg_add_all_routers(hwgraph_root);
966 	klhwg_connect_routers(hwgraph_root);
967 	klhwg_connect_hubs(hwgraph_root);
968 
969 	/* Go through the entire system's klconfig
970 	 * to figure out which pci components have been disabled
971 	 */
972 	klhwg_device_disable_hints_add();
973 
974 }
975