patch-2.4.23 linux-2.4.23/arch/ia64/sn/kernel/setup.c
Next file: linux-2.4.23/arch/ia64/sn/kernel/sn2/Makefile
Previous file: linux-2.4.23/arch/ia64/sn/kernel/led.c
Back to the patch index
Back to the overall index
- Lines: 341
- Date:
2003-11-28 10:26:19.000000000 -0800
- Orig file:
linux-2.4.22/arch/ia64/sn/kernel/setup.c
- Orig date:
2003-08-25 04:44:39.000000000 -0700
diff -urN linux-2.4.22/arch/ia64/sn/kernel/setup.c linux-2.4.23/arch/ia64/sn/kernel/setup.c
@@ -56,8 +56,10 @@
#include <asm/machvec.h>
#include <asm/system.h>
#include <asm/processor.h>
+#include <asm/pgalloc.h>
#include <asm/sn/sgi.h>
#include <asm/sn/io.h>
+#include <asm/sn/pci/pciio.h>
#include <asm/sn/arch.h>
#include <asm/sn/addrs.h>
#include <asm/sn/pda.h>
@@ -71,7 +73,7 @@
#include <asm/sn/sn_sal.h>
#include <asm/sn/sn2/shub.h>
-#define pxm_to_nasid(pxm) ((pxm)<<1)
+#define pxm_to_nasid(pxm) (((pxm)<<1) | (get_nasid() & ~0x1ff))
#define MAX_PHYS_MEMORY (1UL << 49) /* 1 TB */
@@ -79,8 +81,12 @@
extern void bte_init_cpu (void);
extern void sn_timer_init(void);
extern unsigned long last_time_offset;
+extern void init_platform_hubinfo(nodepda_t **nodepdaindr);
extern void (*ia64_mark_idle)(int);
+extern void (*ia64_platform_timer_extras)(void);
+extern void sn_timer_interrupt_extras(void);
extern void snidle(int);
+extern unsigned char acpi_kbd_controller_present;
unsigned long sn_rtc_cycles_per_second;
@@ -90,6 +96,7 @@
short physical_node_map[MAX_PHYSNODE_ID];
+int numionodes;
/*
* This is the address of the RRegs in the HSpace of the global
* master. It is used by a hack in serial.c (serial_[in|out],
@@ -223,7 +230,77 @@
shub_1_1_found = 1;
}
+/*
+ * SN2 requires very slightly different alternate data-TLB miss handle than what
+ * the mainline linux kernel provides. At some point this approach could be used
+ * to allow the use of the low-memory thrown away on other platforms when VGA is
+ * present.
+ *
+ * On SN2 we want to load small TCs for granule-0 (and aliases of) faulting
+ * addresses. The details of this are more sublte than at which they first
+ * appear.
+ */
+static void __init
+sn2_replace_ivt(void)
+{
+ extern unsigned char alt_dtlb_miss[], ia64_ivt_page_fault[];
+ extern unsigned char sn2_alt_dtlb_miss[], sn2_alt_dtlb_miss_end[];
+ extern unsigned char sn2_alt_dtlb_miss_patch1[];
+
+ unsigned char *s, *d;
+ u64 *p;
+ u64 len = (u64)sn2_alt_dtlb_miss_end - (u64)sn2_alt_dtlb_miss;
+ u64 broffs = (ia64_ivt_page_fault - alt_dtlb_miss) - (sn2_alt_dtlb_miss_patch1 - sn2_alt_dtlb_miss);
+ u64 psr;
+ int i;
+
+ /* printk(KERN_DEBUG "Replacing alternate data-TLB miss handler.\n"); */
+
+ /* Check the code isn't too large */
+ if (len > 1024) {
+ printk(KERN_ERR "SGI: Specific alt_dtlb_misse too large! Not replacing\n");
+ return;
+ }
+
+ /* check the offset is sane (should always be) */
+ if ((broffs>>4) + (1<<20) >= (1<<21)) {
+ printk(KERN_ERR "SGI: IVT patch ivt offset %ld invalid! Not replacing!\n", broffs);
+ return;
+ }
+
+ /* 2nd half of bundle to patch (has slot 2) */
+ p = (u64*)sn2_alt_dtlb_miss_patch1 + 1;
+ /* patch the offset into slot 2 (imm20b + s) */
+ *p = (*p & ~(0x8fffff000000000)) | ((broffs & 0x1000000) << 35) | ((broffs & 0x0fffff0) << 32);
+
+ /* don't want any interrupts when doing this */
+ psr = ia64_clear_ic();
+
+ /* copy over the existing code, flush i-cache as required */
+ d = alt_dtlb_miss;
+ s = sn2_alt_dtlb_miss;
+ for (i=0; i<len; ++i, ++s) {
+ *d++ = *s;
+ if ((((u64)s) & 63) == 63) {
+ ia64_insn_group_barrier();
+ ia64_fc((void*)s);
+ }
+ }
+ ia64_insn_group_barrier();
+ ia64_fc((void*)s);
+
+ /* sync & serialize instruction stream */
+ ia64_sync_i();
+ ia64_srlz_i();
+
+ /* restore interrupt status */
+ ia64_set_psr(psr);
+ /* flush any TC's we have had previously loaded that could cause problems here */
+ local_flush_tlb_all();
+
+ printk(KERN_DEBUG "SGI: Replaced alt_dtlb_miss handler.\n");
+}
/**
* sn_setup - SN platform setup routine
@@ -237,12 +314,27 @@
sn_setup(char **cmdline_p)
{
long status, ticks_per_sec, drift;
- int i, pxm;
+ int pxm;
int major = sn_sal_rev_major(), minor = sn_sal_rev_minor();
- extern void io_sh_swapper(int, int);
- extern nasid_t get_master_baseio_nasid(void);
extern void sn_cpu_init(void);
+ /*
+ * If the generic code has enabled vga console support - lets
+ * get rid of it again. This is a kludge for the fact that ACPI
+ * currtently has no way of informing us if legacy VGA is available
+ * or not.
+ */
+#if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE)
+ if (conswitchp == &vga_con) {
+ printk(KERN_DEBUG "SGI: Disabling VGA console\n");
+#ifdef CONFIG_DUMMY_CONSOLE
+ conswitchp = &dummy_con;
+#else
+ conswitchp = NULL;
+#endif /* CONFIG_DUMMY_CONSOLE */
+ }
+#endif /* def(CONFIG_VT) && def(CONFIG_VGA_CONSOLE) */
+
MAX_DMA_ADDRESS = PAGE_OFFSET + MAX_PHYS_MEMORY;
memset(physical_node_map, -1, sizeof(physical_node_map));
@@ -250,6 +342,19 @@
if (pxm_to_nid_map[pxm] != -1)
physical_node_map[pxm_to_nasid(pxm)] = pxm_to_nid_map[pxm];
+
+ /*
+ * Old PROMs do not provide an ACPI FADT. Disable legacy keyboard
+ * support here so we don't have to listen to failed keyboard probe
+ * messages.
+ */
+ if ((major < 2 || (major == 2 && minor <= 9)) &&
+ acpi_kbd_controller_present) {
+ printk(KERN_INFO "Disabling legacy keyboard support as prom "
+ "is too old and doesn't provide FADT\n");
+ acpi_kbd_controller_present = 0;
+ }
+
printk("SGI SAL version %x.%02x\n", major, minor);
/*
@@ -262,11 +367,12 @@
panic("PROM version too old\n");
}
- io_sh_swapper(get_nasid(), 0);
+ /* Patch the ivt */
+ sn2_replace_ivt();
master_nasid = get_nasid();
- (void)get_console_nasid();
- (void)get_master_baseio_nasid();
+ (void)snia_get_console_nasid();
+ (void)snia_get_master_baseio_nasid();
status = ia64_sal_freq_base(SAL_FREQ_BASE_REALTIME_CLOCK, &ticks_per_sec, &drift);
if (status != 0 || ticks_per_sec < 100000) {
@@ -277,7 +383,7 @@
else
sn_rtc_cycles_per_second = ticks_per_sec;
- platform_intr_list[ACPI_INTERRUPT_CPEI] = IA64_PCE_VECTOR;
+ platform_intr_list[ACPI_INTERRUPT_CPEI] = IA64_CPE_VECTOR;
if ( IS_RUNNING_ON_SIMULATOR() )
@@ -298,11 +404,6 @@
*/
sn_init_pdas(cmdline_p);
- /*
- * Check for WARs.
- */
- sn_check_for_wars();
-
ia64_mark_idle = &snidle;
/*
@@ -311,11 +412,18 @@
*/
sn_cpu_init();
+ /*
+ * Setup hubinfo stuff. Has to happen AFTER sn_cpu_init(),
+ * because it uses the cnode to nasid tables.
+ */
+ init_platform_hubinfo(nodepdaindr);
#ifdef CONFIG_SMP
init_smp_config();
#endif
screen_info = sn_screen_info;
+ ia64_platform_timer_extras = &sn_timer_interrupt_extras;
+
sn_timer_init();
}
@@ -328,6 +436,7 @@
sn_init_pdas(char **cmdline_p)
{
cnodeid_t cnode;
+ void scan_for_ionodes(void);
/*
* Make sure that the PDA fits entirely in the same page as the
@@ -340,6 +449,9 @@
for (cnode=0; cnode<numnodes; cnode++)
pda.cnodeid_to_nasid_table[cnode] = pxm_to_nasid(nid_to_pxm_map[cnode]);
+ numionodes = numnodes;
+ scan_for_ionodes();
+
/*
* Allocate & initalize the nodepda for each node.
*/
@@ -348,10 +460,18 @@
memset(nodepdaindr[cnode], 0, sizeof(nodepda_t));
}
+ /*
+ * Allocate & initialize nodepda for TIOs. For now, put them on node 0.
+ */
+ for (cnode = numnodes; cnode < numionodes; cnode ++) {
+ nodepdaindr[cnode] = alloc_bootmem_node(NODE_DATA(0), sizeof(nodepda_t));
+ memset(nodepdaindr[cnode], 0, sizeof(nodepda_t));
+ }
+
/*
* Now copy the array of nodepda pointers to each nodepda.
*/
- for (cnode=0; cnode < numnodes; cnode++)
+ for (cnode=0; cnode < numionodes; cnode++)
memcpy(nodepdaindr[cnode]->pernode_pdaindr, nodepdaindr, sizeof(nodepdaindr));
@@ -362,8 +482,16 @@
*/
for (cnode = 0; cnode < numnodes; cnode++) {
init_platform_nodepda(nodepdaindr[cnode], cnode);
+ spin_lock_init(&nodepdaindr[cnode]->bist_lock);
bte_init_node (nodepdaindr[cnode], cnode);
}
+
+ /*
+ * Handle TIO differently .. we do not do BTE init ..
+ */
+ for (cnode = numnodes; cnode < numionodes; cnode++) {
+ init_platform_nodepda(nodepdaindr[cnode], cnode);
+ }
}
/**
@@ -383,6 +511,7 @@
int nasid;
int slice;
int cnode, i;
+ static int wars_have_been_checked = 0;
/*
* The boot cpu makes this call again after platform initialization is
@@ -407,11 +536,22 @@
pda.hb_count = HZ/2;
pda.hb_state = 0;
pda.idle_flag = 0;
- pda.shub_1_1_found = shub_1_1_found;
memset(pda.cnodeid_to_nasid_table, -1, sizeof(pda.cnodeid_to_nasid_table));
for (i=0; i<numnodes; i++)
pda.cnodeid_to_nasid_table[i] = pxm_to_nasid(nid_to_pxm_map[i]);
+ /*
+ * Check for WARs.
+ * Only needs to be done once, on BSP.
+ * Has to be done after loop above, because it uses pda.cnodeid_to_nasid_table[i].
+ * Has to be done before assignment below.
+ */
+ if (!wars_have_been_checked) {
+ sn_check_for_wars();
+ wars_have_been_checked = 1;
+ }
+
+ pda.shub_1_1_found = shub_1_1_found;
if (local_node_data->active_cpu_count == 1)
nodepda->node_first_cpu = cpuid;
@@ -444,3 +584,27 @@
bte_init_cpu();
}
+
+/*
+ * Scan klconfig for TIO's. Add the TIO nasids to the
+ * physical_node_map and the pda and increment numionodes.
+ */
+
+void
+scan_for_ionodes() {
+ int nasid = 0;
+ lboard_t *brd;
+
+ /* Scan all compute nodes. */
+ for (nasid = 0; nasid < MAX_PHYSNODE_ID; nasid +=2) {
+ /* if there's no nasid, don't try to read the klconfig on the node */
+ if (physical_node_map[nasid] == -1) continue;
+ brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_TIO);
+ while (brd) {
+ pda.cnodeid_to_nasid_table[numionodes] = brd->brd_nasid;
+ physical_node_map[brd->brd_nasid] = numionodes++;
+ brd = KLCF_NEXT(brd);
+ brd = find_lboard(brd, KLTYPE_TIO);
+ }
+ }
+}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)