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