aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64/sn/kernel/setup.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ia64/sn/kernel/setup.c')
-rw-r--r--arch/ia64/sn/kernel/setup.c317
1 files changed, 204 insertions, 113 deletions
diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c
index 6f8c5883716b..e510dce9971f 100644
--- a/arch/ia64/sn/kernel/setup.c
+++ b/arch/ia64/sn/kernel/setup.c
@@ -30,6 +30,7 @@
30#include <linux/root_dev.h> 30#include <linux/root_dev.h>
31#include <linux/nodemask.h> 31#include <linux/nodemask.h>
32#include <linux/pm.h> 32#include <linux/pm.h>
33#include <linux/efi.h>
33 34
34#include <asm/io.h> 35#include <asm/io.h>
35#include <asm/sal.h> 36#include <asm/sal.h>
@@ -59,8 +60,6 @@ DEFINE_PER_CPU(struct pda_s, pda_percpu);
59 60
60#define MAX_PHYS_MEMORY (1UL << IA64_MAX_PHYS_BITS) /* Max physical address supported */ 61#define MAX_PHYS_MEMORY (1UL << IA64_MAX_PHYS_BITS) /* Max physical address supported */
61 62
62lboard_t *root_lboard[MAX_COMPACT_NODES];
63
64extern void bte_init_node(nodepda_t *, cnodeid_t); 63extern void bte_init_node(nodepda_t *, cnodeid_t);
65 64
66extern void sn_timer_init(void); 65extern void sn_timer_init(void);
@@ -97,15 +96,15 @@ u8 sn_region_size;
97EXPORT_SYMBOL(sn_region_size); 96EXPORT_SYMBOL(sn_region_size);
98int sn_prom_type; /* 0=hardware, 1=medusa/realprom, 2=medusa/fakeprom */ 97int sn_prom_type; /* 0=hardware, 1=medusa/realprom, 2=medusa/fakeprom */
99 98
100short physical_node_map[MAX_PHYSNODE_ID]; 99short physical_node_map[MAX_NUMALINK_NODES];
101static unsigned long sn_prom_features[MAX_PROM_FEATURE_SETS]; 100static unsigned long sn_prom_features[MAX_PROM_FEATURE_SETS];
102 101
103EXPORT_SYMBOL(physical_node_map); 102EXPORT_SYMBOL(physical_node_map);
104 103
105int numionodes; 104int num_cnodes;
106 105
107static void sn_init_pdas(char **); 106static void sn_init_pdas(char **);
108static void scan_for_ionodes(void); 107static void build_cnode_tables(void);
109 108
110static nodepda_t *nodepdaindr[MAX_COMPACT_NODES]; 109static nodepda_t *nodepdaindr[MAX_COMPACT_NODES];
111 110
@@ -140,19 +139,6 @@ char drive_info[4 * 16];
140#endif 139#endif
141 140
142/* 141/*
143 * Get nasid of current cpu early in boot before nodepda is initialized
144 */
145static int
146boot_get_nasid(void)
147{
148 int nasid;
149
150 if (ia64_sn_get_sapic_info(get_sapicid(), &nasid, NULL, NULL))
151 BUG();
152 return nasid;
153}
154
155/*
156 * This routine can only be used during init, since 142 * This routine can only be used during init, since
157 * smp_boot_data is an init data structure. 143 * smp_boot_data is an init data structure.
158 * We have to use smp_boot_data.cpu_phys_id to find 144 * We have to use smp_boot_data.cpu_phys_id to find
@@ -223,7 +209,6 @@ void __init early_sn_setup(void)
223} 209}
224 210
225extern int platform_intr_list[]; 211extern int platform_intr_list[];
226extern nasid_t master_nasid;
227static int __initdata shub_1_1_found = 0; 212static int __initdata shub_1_1_found = 0;
228 213
229/* 214/*
@@ -258,6 +243,135 @@ static void __init sn_check_for_wars(void)
258 } 243 }
259} 244}
260 245
246/*
247 * Scan the EFI PCDP table (if it exists) for an acceptable VGA console
248 * output device. If one exists, pick it and set sn_legacy_{io,mem} to
249 * reflect the bus offsets needed to address it.
250 *
251 * Since pcdp support in SN is not supported in the 2.4 kernel (or at least
252 * the one lbs is based on) just declare the needed structs here.
253 *
254 * Reference spec http://www.dig64.org/specifications/DIG64_PCDPv20.pdf
255 *
256 * Returns 0 if no acceptable vga is found, !0 otherwise.
257 *
258 * Note: This stuff is duped here because Altix requires the PCDP to
259 * locate a usable VGA device due to lack of proper ACPI support. Structures
260 * could be used from drivers/firmware/pcdp.h, but it was decided that moving
261 * this file to a more public location just for Altix use was undesireable.
262 */
263
264struct hcdp_uart_desc {
265 u8 pad[45];
266};
267
268struct pcdp {
269 u8 signature[4]; /* should be 'HCDP' */
270 u32 length;
271 u8 rev; /* should be >=3 for pcdp, <3 for hcdp */
272 u8 sum;
273 u8 oem_id[6];
274 u64 oem_tableid;
275 u32 oem_rev;
276 u32 creator_id;
277 u32 creator_rev;
278 u32 num_type0;
279 struct hcdp_uart_desc uart[0]; /* num_type0 of these */
280 /* pcdp descriptors follow */
281} __attribute__((packed));
282
283struct pcdp_device_desc {
284 u8 type;
285 u8 primary;
286 u16 length;
287 u16 index;
288 /* interconnect specific structure follows */
289 /* device specific structure follows that */
290} __attribute__((packed));
291
292struct pcdp_interface_pci {
293 u8 type; /* 1 == pci */
294 u8 reserved;
295 u16 length;
296 u8 segment;
297 u8 bus;
298 u8 dev;
299 u8 fun;
300 u16 devid;
301 u16 vendid;
302 u32 acpi_interrupt;
303 u64 mmio_tra;
304 u64 ioport_tra;
305 u8 flags;
306 u8 translation;
307} __attribute__((packed));
308
309struct pcdp_vga_device {
310 u8 num_eas_desc;
311 /* ACPI Extended Address Space Desc follows */
312} __attribute__((packed));
313
314/* from pcdp_device_desc.primary */
315#define PCDP_PRIMARY_CONSOLE 0x01
316
317/* from pcdp_device_desc.type */
318#define PCDP_CONSOLE_INOUT 0x0
319#define PCDP_CONSOLE_DEBUG 0x1
320#define PCDP_CONSOLE_OUT 0x2
321#define PCDP_CONSOLE_IN 0x3
322#define PCDP_CONSOLE_TYPE_VGA 0x8
323
324#define PCDP_CONSOLE_VGA (PCDP_CONSOLE_TYPE_VGA | PCDP_CONSOLE_OUT)
325
326/* from pcdp_interface_pci.type */
327#define PCDP_IF_PCI 1
328
329/* from pcdp_interface_pci.translation */
330#define PCDP_PCI_TRANS_IOPORT 0x02
331#define PCDP_PCI_TRANS_MMIO 0x01
332
333static void
334sn_scan_pcdp(void)
335{
336 u8 *bp;
337 struct pcdp *pcdp;
338 struct pcdp_device_desc device;
339 struct pcdp_interface_pci if_pci;
340 extern struct efi efi;
341
342 pcdp = efi.hcdp;
343 if (! pcdp)
344 return; /* no hcdp/pcdp table */
345
346 if (pcdp->rev < 3)
347 return; /* only support PCDP (rev >= 3) */
348
349 for (bp = (u8 *)&pcdp->uart[pcdp->num_type0];
350 bp < (u8 *)pcdp + pcdp->length;
351 bp += device.length) {
352 memcpy(&device, bp, sizeof(device));
353 if (! (device.primary & PCDP_PRIMARY_CONSOLE))
354 continue; /* not primary console */
355
356 if (device.type != PCDP_CONSOLE_VGA)
357 continue; /* not VGA descriptor */
358
359 memcpy(&if_pci, bp+sizeof(device), sizeof(if_pci));
360 if (if_pci.type != PCDP_IF_PCI)
361 continue; /* not PCI interconnect */
362
363 if (if_pci.translation & PCDP_PCI_TRANS_IOPORT)
364 vga_console_iobase =
365 if_pci.ioport_tra | __IA64_UNCACHED_OFFSET;
366
367 if (if_pci.translation & PCDP_PCI_TRANS_MMIO)
368 vga_console_membase =
369 if_pci.mmio_tra | __IA64_UNCACHED_OFFSET;
370
371 break; /* once we find the primary, we're done */
372 }
373}
374
261/** 375/**
262 * sn_setup - SN platform setup routine 376 * sn_setup - SN platform setup routine
263 * @cmdline_p: kernel command line 377 * @cmdline_p: kernel command line
@@ -269,7 +383,6 @@ static void __init sn_check_for_wars(void)
269void __init sn_setup(char **cmdline_p) 383void __init sn_setup(char **cmdline_p)
270{ 384{
271 long status, ticks_per_sec, drift; 385 long status, ticks_per_sec, drift;
272 int pxm;
273 u32 version = sn_sal_rev(); 386 u32 version = sn_sal_rev();
274 extern void sn_cpu_init(void); 387 extern void sn_cpu_init(void);
275 388
@@ -280,16 +393,35 @@ void __init sn_setup(char **cmdline_p)
280 393
281#if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE) 394#if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE)
282 /* 395 /*
283 * If there was a primary vga adapter identified through the 396 * Handle SN vga console.
284 * EFI PCDP table, make it the preferred console. Otherwise 397 *
285 * zero out conswitchp. 398 * SN systems do not have enough ACPI table information
399 * being passed from prom to identify VGA adapters and the legacy
400 * addresses to access them. Until that is done, SN systems rely
401 * on the PCDP table to identify the primary VGA console if one
402 * exists.
403 *
404 * However, kernel PCDP support is optional, and even if it is built
405 * into the kernel, it will not be used if the boot cmdline contains
406 * console= directives.
407 *
408 * So, to work around this mess, we duplicate some of the PCDP code
409 * here so that the primary VGA console (as defined by PCDP) will
410 * work on SN systems even if a different console (e.g. serial) is
411 * selected on the boot line (or CONFIG_EFI_PCDP is off).
286 */ 412 */
287 413
414 if (! vga_console_membase)
415 sn_scan_pcdp();
416
288 if (vga_console_membase) { 417 if (vga_console_membase) {
289 /* usable vga ... make tty0 the preferred default console */ 418 /* usable vga ... make tty0 the preferred default console */
290 add_preferred_console("tty", 0, NULL); 419 if (!strstr(*cmdline_p, "console="))
420 add_preferred_console("tty", 0, NULL);
291 } else { 421 } else {
292 printk(KERN_DEBUG "SGI: Disabling VGA console\n"); 422 printk(KERN_DEBUG "SGI: Disabling VGA console\n");
423 if (!strstr(*cmdline_p, "console="))
424 add_preferred_console("ttySG", 0, NULL);
293#ifdef CONFIG_DUMMY_CONSOLE 425#ifdef CONFIG_DUMMY_CONSOLE
294 conswitchp = &dummy_con; 426 conswitchp = &dummy_con;
295#else 427#else
@@ -300,11 +432,10 @@ void __init sn_setup(char **cmdline_p)
300 432
301 MAX_DMA_ADDRESS = PAGE_OFFSET + MAX_PHYS_MEMORY; 433 MAX_DMA_ADDRESS = PAGE_OFFSET + MAX_PHYS_MEMORY;
302 434
303 memset(physical_node_map, -1, sizeof(physical_node_map)); 435 /*
304 for (pxm = 0; pxm < MAX_PXM_DOMAINS; pxm++) 436 * Build the tables for managing cnodes.
305 if (pxm_to_nid_map[pxm] != -1) 437 */
306 physical_node_map[pxm_to_nasid(pxm)] = 438 build_cnode_tables();
307 pxm_to_nid_map[pxm];
308 439
309 /* 440 /*
310 * Old PROMs do not provide an ACPI FADT. Disable legacy keyboard 441 * Old PROMs do not provide an ACPI FADT. Disable legacy keyboard
@@ -319,8 +450,6 @@ void __init sn_setup(char **cmdline_p)
319 450
320 printk("SGI SAL version %x.%02x\n", version >> 8, version & 0x00FF); 451 printk("SGI SAL version %x.%02x\n", version >> 8, version & 0x00FF);
321 452
322 master_nasid = boot_get_nasid();
323
324 status = 453 status =
325 ia64_sal_freq_base(SAL_FREQ_BASE_REALTIME_CLOCK, &ticks_per_sec, 454 ia64_sal_freq_base(SAL_FREQ_BASE_REALTIME_CLOCK, &ticks_per_sec,
326 &drift); 455 &drift);
@@ -378,15 +507,6 @@ static void __init sn_init_pdas(char **cmdline_p)
378{ 507{
379 cnodeid_t cnode; 508 cnodeid_t cnode;
380 509
381 memset(sn_cnodeid_to_nasid, -1,
382 sizeof(__ia64_per_cpu_var(__sn_cnodeid_to_nasid)));
383 for_each_online_node(cnode)
384 sn_cnodeid_to_nasid[cnode] =
385 pxm_to_nasid(nid_to_pxm_map[cnode]);
386
387 numionodes = num_online_nodes();
388 scan_for_ionodes();
389
390 /* 510 /*
391 * Allocate & initalize the nodepda for each node. 511 * Allocate & initalize the nodepda for each node.
392 */ 512 */
@@ -402,7 +522,7 @@ static void __init sn_init_pdas(char **cmdline_p)
402 /* 522 /*
403 * Allocate & initialize nodepda for TIOs. For now, put them on node 0. 523 * Allocate & initialize nodepda for TIOs. For now, put them on node 0.
404 */ 524 */
405 for (cnode = num_online_nodes(); cnode < numionodes; cnode++) { 525 for (cnode = num_online_nodes(); cnode < num_cnodes; cnode++) {
406 nodepdaindr[cnode] = 526 nodepdaindr[cnode] =
407 alloc_bootmem_node(NODE_DATA(0), sizeof(nodepda_t)); 527 alloc_bootmem_node(NODE_DATA(0), sizeof(nodepda_t));
408 memset(nodepdaindr[cnode], 0, sizeof(nodepda_t)); 528 memset(nodepdaindr[cnode], 0, sizeof(nodepda_t));
@@ -411,7 +531,7 @@ static void __init sn_init_pdas(char **cmdline_p)
411 /* 531 /*
412 * Now copy the array of nodepda pointers to each nodepda. 532 * Now copy the array of nodepda pointers to each nodepda.
413 */ 533 */
414 for (cnode = 0; cnode < numionodes; cnode++) 534 for (cnode = 0; cnode < num_cnodes; cnode++)
415 memcpy(nodepdaindr[cnode]->pernode_pdaindr, nodepdaindr, 535 memcpy(nodepdaindr[cnode]->pernode_pdaindr, nodepdaindr,
416 sizeof(nodepdaindr)); 536 sizeof(nodepdaindr));
417 537
@@ -428,7 +548,7 @@ static void __init sn_init_pdas(char **cmdline_p)
428 * Initialize the per node hubdev. This includes IO Nodes and 548 * Initialize the per node hubdev. This includes IO Nodes and
429 * headless/memless nodes. 549 * headless/memless nodes.
430 */ 550 */
431 for (cnode = 0; cnode < numionodes; cnode++) { 551 for (cnode = 0; cnode < num_cnodes; cnode++) {
432 hubdev_init_node(nodepdaindr[cnode], cnode); 552 hubdev_init_node(nodepdaindr[cnode], cnode);
433 } 553 }
434} 554}
@@ -553,87 +673,58 @@ void __init sn_cpu_init(void)
553} 673}
554 674
555/* 675/*
556 * Scan klconfig for ionodes. Add the nasids to the 676 * Build tables for converting between NASIDs and cnodes.
557 * physical_node_map and the pda and increment numionodes.
558 */ 677 */
678static inline int __init board_needs_cnode(int type)
679{
680 return (type == KLTYPE_SNIA || type == KLTYPE_TIO);
681}
559 682
560static void __init scan_for_ionodes(void) 683void __init build_cnode_tables(void)
561{ 684{
562 int nasid = 0; 685 int nasid;
686 int node;
563 lboard_t *brd; 687 lboard_t *brd;
564 688
565 /* fakeprom does not support klgraph */ 689 memset(physical_node_map, -1, sizeof(physical_node_map));
566 if (IS_RUNNING_ON_FAKE_PROM()) 690 memset(sn_cnodeid_to_nasid, -1,
567 return; 691 sizeof(__ia64_per_cpu_var(__sn_cnodeid_to_nasid)));
568
569 /* Setup ionodes with memory */
570 for (nasid = 0; nasid < MAX_PHYSNODE_ID; nasid += 2) {
571 char *klgraph_header;
572 cnodeid_t cnodeid;
573
574 if (physical_node_map[nasid] == -1)
575 continue;
576 692
577 cnodeid = -1; 693 /*
578 klgraph_header = __va(ia64_sn_get_klconfig_addr(nasid)); 694 * First populate the tables with C/M bricks. This ensures that
579 if (!klgraph_header) { 695 * cnode == node for all C & M bricks.
580 BUG(); /* All nodes must have klconfig tables! */ 696 */
581 } 697 for_each_online_node(node) {
582 cnodeid = nasid_to_cnodeid(nasid); 698 nasid = pxm_to_nasid(nid_to_pxm_map[node]);
583 root_lboard[cnodeid] = (lboard_t *) 699 sn_cnodeid_to_nasid[node] = nasid;
584 NODE_OFFSET_TO_LBOARD((nasid), 700 physical_node_map[nasid] = node;
585 ((kl_config_hdr_t
586 *) (klgraph_header))->
587 ch_board_info);
588 } 701 }
589 702
590 /* Scan headless/memless IO Nodes. */ 703 /*
591 for (nasid = 0; nasid < MAX_PHYSNODE_ID; nasid += 2) { 704 * num_cnodes is total number of C/M/TIO bricks. Because of the 256 node
592 /* if there's no nasid, don't try to read the klconfig on the node */ 705 * limit on the number of nodes, we can't use the generic node numbers
593 if (physical_node_map[nasid] == -1) 706 * for this. Note that num_cnodes is incremented below as TIOs or
594 continue; 707 * headless/memoryless nodes are discovered.
595 brd = find_lboard_any((lboard_t *) 708 */
596 root_lboard[nasid_to_cnodeid(nasid)], 709 num_cnodes = num_online_nodes();
597 KLTYPE_SNIA);
598 if (brd) {
599 brd = KLCF_NEXT_ANY(brd); /* Skip this node's lboard */
600 if (!brd)
601 continue;
602 }
603
604 brd = find_lboard_any(brd, KLTYPE_SNIA);
605 710
606 while (brd) { 711 /* fakeprom does not support klgraph */
607 sn_cnodeid_to_nasid[numionodes] = brd->brd_nasid; 712 if (IS_RUNNING_ON_FAKE_PROM())
608 physical_node_map[brd->brd_nasid] = numionodes; 713 return;
609 root_lboard[numionodes] = brd;
610 numionodes++;
611 brd = KLCF_NEXT_ANY(brd);
612 if (!brd)
613 break;
614
615 brd = find_lboard_any(brd, KLTYPE_SNIA);
616 }
617 }
618 714
619 /* Scan for TIO nodes. */ 715 /* Find TIOs & headless/memoryless nodes and add them to the tables */
620 for (nasid = 0; nasid < MAX_PHYSNODE_ID; nasid += 2) { 716 for_each_online_node(node) {
621 /* if there's no nasid, don't try to read the klconfig on the node */ 717 kl_config_hdr_t *klgraph_header;
622 if (physical_node_map[nasid] == -1) 718 nasid = cnodeid_to_nasid(node);
623 continue; 719 if ((klgraph_header = ia64_sn_get_klconfig_addr(nasid)) == NULL)
624 brd = find_lboard_any((lboard_t *) 720 BUG();
625 root_lboard[nasid_to_cnodeid(nasid)], 721 brd = NODE_OFFSET_TO_LBOARD(nasid, klgraph_header->ch_board_info);
626 KLTYPE_TIO);
627 while (brd) { 722 while (brd) {
628 sn_cnodeid_to_nasid[numionodes] = brd->brd_nasid; 723 if (board_needs_cnode(brd->brd_type) && physical_node_map[brd->brd_nasid] < 0) {
629 physical_node_map[brd->brd_nasid] = numionodes; 724 sn_cnodeid_to_nasid[num_cnodes] = brd->brd_nasid;
630 root_lboard[numionodes] = brd; 725 physical_node_map[brd->brd_nasid] = num_cnodes++;
631 numionodes++; 726 }
632 brd = KLCF_NEXT_ANY(brd); 727 brd = find_lboard_next(brd);
633 if (!brd)
634 break;
635
636 brd = find_lboard_any(brd, KLTYPE_TIO);
637 } 728 }
638 } 729 }
639} 730}