diff options
Diffstat (limited to 'arch/mips/sgi-ip27')
-rw-r--r-- | arch/mips/sgi-ip27/Kconfig | 54 | ||||
-rw-r--r-- | arch/mips/sgi-ip27/ip27-berr.c | 1 | ||||
-rw-r--r-- | arch/mips/sgi-ip27/ip27-console.c | 4 | ||||
-rw-r--r-- | arch/mips/sgi-ip27/ip27-init.c | 50 | ||||
-rw-r--r-- | arch/mips/sgi-ip27/ip27-irq.c | 66 | ||||
-rw-r--r-- | arch/mips/sgi-ip27/ip27-smp.c | 25 |
6 files changed, 121 insertions, 79 deletions
diff --git a/arch/mips/sgi-ip27/Kconfig b/arch/mips/sgi-ip27/Kconfig new file mode 100644 index 00000000000..7b0bc443724 --- /dev/null +++ b/arch/mips/sgi-ip27/Kconfig @@ -0,0 +1,54 @@ +#config SGI_SN0_XXL +# bool "IP27 XXL" +# depends on SGI_IP27 +# This options adds support for userspace processes upto 16TB size. +# Normally the limit is just .5TB. + +config SGI_SN0_N_MODE + bool "IP27 N-Mode" + depends on SGI_IP27 + help + The nodes of Origin 200, Origin 2000 and Onyx 2 systems can be + configured in either N-Modes which allows for more nodes or M-Mode + which allows for more memory. Your system is most probably + running in M-Mode, so you should say N here. + +config ARCH_DISCONTIGMEM_ENABLE + bool + default y if SGI_IP27 + help + Say Y to upport efficient handling of discontiguous physical memory, + for architectures which are either NUMA (Non-Uniform Memory Access) + or have huge holes in the physical address space for other reasons. + See <file:Documentation/vm/numa> for more. + +config NUMA + bool "NUMA Support" + depends on SGI_IP27 + help + Say Y to compile the kernel to support NUMA (Non-Uniform Memory + Access). This option is for configuring high-end multiprocessor + server machines. If in doubt, say N. + +config MAPPED_KERNEL + bool "Mapped kernel support" + depends on SGI_IP27 + help + Change the way a Linux kernel is loaded into memory on a MIPS64 + machine. This is required in order to support text replication and + NUMA. If you need to understand it, read the source code. + +config REPLICATE_KTEXT + bool "Kernel text replication support" + depends on SGI_IP27 + help + Say Y here to enable replicating the kernel text across multiple + nodes in a NUMA cluster. This trades memory for speed. + +config REPLICATE_EXHANDLERS + bool "Exception handler replication support" + depends on SGI_IP27 + help + Say Y here to enable replicating the kernel exception handlers + across multiple nodes in a NUMA cluster. This trades memory for + speed. diff --git a/arch/mips/sgi-ip27/ip27-berr.c b/arch/mips/sgi-ip27/ip27-berr.c index e1829a5d3b1..07631a97670 100644 --- a/arch/mips/sgi-ip27/ip27-berr.c +++ b/arch/mips/sgi-ip27/ip27-berr.c @@ -10,6 +10,7 @@ #include <linux/init.h> #include <linux/kernel.h> #include <linux/module.h> +#include <linux/signal.h> /* for SIGBUS */ #include <asm/module.h> #include <asm/sn/addrs.h> diff --git a/arch/mips/sgi-ip27/ip27-console.c b/arch/mips/sgi-ip27/ip27-console.c index d97f5b5ef84..3e1ac299b80 100644 --- a/arch/mips/sgi-ip27/ip27-console.c +++ b/arch/mips/sgi-ip27/ip27-console.c @@ -30,8 +30,10 @@ static inline struct ioc3_uartregs *console_uart(void) { struct ioc3 *ioc3; + nasid_t nasid; - ioc3 = (struct ioc3 *)KL_CONFIG_CH_CONS_INFO(get_nasid())->memory_base; + nasid = (master_nasid == INVALID_NASID) ? get_nasid() : master_nasid; + ioc3 = (struct ioc3 *)KL_CONFIG_CH_CONS_INFO(nasid)->memory_base; return &ioc3->sregs.uarta; } diff --git a/arch/mips/sgi-ip27/ip27-init.c b/arch/mips/sgi-ip27/ip27-init.c index 6dcee5c46c7..8651a0e7540 100644 --- a/arch/mips/sgi-ip27/ip27-init.c +++ b/arch/mips/sgi-ip27/ip27-init.c @@ -56,12 +56,12 @@ static void __init per_hub_init(cnodeid_t cnode) { struct hub_data *hub = hub_data(cnode); nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode); + int i; cpu_set(smp_processor_id(), hub->h_cpus); if (test_and_set_bit(cnode, hub_init_mask)) return; - /* * Set CRB timeout at 5ms, (< PI timeout of 10ms) */ @@ -88,6 +88,24 @@ static void __init per_hub_init(cnodeid_t cnode) __flush_cache_all(); } #endif + + /* + * Some interrupts are reserved by hardware or by software convention. + * Mark these as reserved right away so they won't be used accidently + * later. + */ + for (i = 0; i <= BASE_PCI_IRQ; i++) { + __set_bit(i, hub->irq_alloc_mask); + LOCAL_HUB_CLR_INTR(INT_PEND0_BASELVL + i); + } + + __set_bit(IP_PEND0_6_63, hub->irq_alloc_mask); + LOCAL_HUB_S(PI_INT_PEND_MOD, IP_PEND0_6_63); + + for (i = NI_BRDCAST_ERR_A; i <= MSC_PANIC_INTR; i++) { + __set_bit(i, hub->irq_alloc_mask); + LOCAL_HUB_CLR_INTR(INT_PEND1_BASELVL + i); + } } void __init per_cpu_init(void) @@ -104,30 +122,12 @@ void __init per_cpu_init(void) clear_c0_status(ST0_IM); + per_hub_init(cnode); + for (i = 0; i < LEVELS_PER_SLICE; i++) si->level_to_irq[i] = -1; /* - * Some interrupts are reserved by hardware or by software convention. - * Mark these as reserved right away so they won't be used accidently - * later. - */ - for (i = 0; i <= BASE_PCI_IRQ; i++) { - __set_bit(i, si->irq_alloc_mask); - LOCAL_HUB_S(PI_INT_PEND_MOD, i); - } - - __set_bit(IP_PEND0_6_63, si->irq_alloc_mask); - LOCAL_HUB_S(PI_INT_PEND_MOD, IP_PEND0_6_63); - - for (i = NI_BRDCAST_ERR_A; i <= MSC_PANIC_INTR; i++) { - __set_bit(i, si->irq_alloc_mask + 1); - LOCAL_HUB_S(PI_INT_PEND_MOD, i); - } - - LOCAL_HUB_L(PI_INT_PEND0); - - /* * We use this so we can find the local hub's data as fast as only * possible. */ @@ -140,8 +140,6 @@ void __init per_cpu_init(void) install_cpu_nmi_handler(cputoslice(cpu)); set_c0_status(SRB_DEV0 | SRB_DEV1); - - per_hub_init(cnode); } /* @@ -198,7 +196,7 @@ extern void ip27_setup_console(void); extern void ip27_time_init(void); extern void ip27_reboot_setup(void); -static int __init ip27_setup(void) +void __init plat_setup(void) { hubreg_t p, e, n_mode; nasid_t nid; @@ -245,8 +243,4 @@ static int __init ip27_setup(void) set_io_port_base(IO_BASE); board_time_init = ip27_time_init; - - return 0; } - -early_initcall(ip27_setup); diff --git a/arch/mips/sgi-ip27/ip27-irq.c b/arch/mips/sgi-ip27/ip27-irq.c index 61817a18aed..73e5e52781d 100644 --- a/arch/mips/sgi-ip27/ip27-irq.c +++ b/arch/mips/sgi-ip27/ip27-irq.c @@ -5,6 +5,9 @@ * Copyright (C) 1999, 2000 Silicon Graphics, Inc. * Copyright (C) 1999 - 2001 Kanoj Sarcar */ + +#undef DEBUG + #include <linux/config.h> #include <linux/init.h> #include <linux/irq.h> @@ -14,11 +17,11 @@ #include <linux/types.h> #include <linux/interrupt.h> #include <linux/ioport.h> -#include <linux/irq.h> #include <linux/timex.h> #include <linux/slab.h> #include <linux/random.h> #include <linux/smp_lock.h> +#include <linux/kernel.h> #include <linux/kernel_stat.h> #include <linux/delay.h> #include <linux/bitops.h> @@ -37,13 +40,6 @@ #include <asm/sn/hub.h> #include <asm/sn/intr.h> -#undef DEBUG_IRQ -#ifdef DEBUG_IRQ -#define DBG(x...) printk(x) -#else -#define DBG(x...) -#endif - /* * Linux has a controller-independent x86 interrupt architecture. * every controller has a 'controller-template', that is used @@ -74,14 +70,15 @@ extern int irq_to_slot[]; static inline int alloc_level(int cpu, int irq) { + struct hub_data *hub = hub_data(cpu_to_node(cpu)); struct slice_data *si = cpu_data[cpu].data; - int level; /* pre-allocated entries */ + int level; - level = find_first_zero_bit(si->irq_alloc_mask, LEVELS_PER_SLICE); + level = find_first_zero_bit(hub->irq_alloc_mask, LEVELS_PER_SLICE); if (level >= LEVELS_PER_SLICE) panic("Cpu %d flooded with devices\n", cpu); - __set_bit(level, si->irq_alloc_mask); + __set_bit(level, hub->irq_alloc_mask); si->level_to_irq[level] = irq; return level; @@ -216,9 +213,11 @@ static int intr_connect_level(int cpu, int bit) { nasid_t nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(cpu)); struct slice_data *si = cpu_data[cpu].data; + unsigned long flags; - __set_bit(bit, si->irq_enable_mask); + set_bit(bit, si->irq_enable_mask); + local_irq_save(flags); if (!cputoslice(cpu)) { REMOTE_HUB_S(nasid, PI_INT_MASK0_A, si->irq_enable_mask[0]); REMOTE_HUB_S(nasid, PI_INT_MASK1_A, si->irq_enable_mask[1]); @@ -226,6 +225,7 @@ static int intr_connect_level(int cpu, int bit) REMOTE_HUB_S(nasid, PI_INT_MASK0_B, si->irq_enable_mask[0]); REMOTE_HUB_S(nasid, PI_INT_MASK1_B, si->irq_enable_mask[1]); } + local_irq_restore(flags); return 0; } @@ -235,7 +235,7 @@ static int intr_disconnect_level(int cpu, int bit) nasid_t nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(cpu)); struct slice_data *si = cpu_data[cpu].data; - __clear_bit(bit, si->irq_enable_mask); + clear_bit(bit, si->irq_enable_mask); if (!cputoslice(cpu)) { REMOTE_HUB_S(nasid, PI_INT_MASK0_A, si->irq_enable_mask[0]); @@ -261,7 +261,7 @@ static unsigned int startup_bridge_irq(unsigned int irq) bc = IRQ_TO_BRIDGE(irq); bridge = bc->base; - DBG("bridge_startup(): irq= 0x%x pin=%d\n", irq, pin); + pr_debug("bridge_startup(): irq= 0x%x pin=%d\n", irq, pin); /* * "map" irq to a swlevel greater than 6 since the first 6 bits * of INT_PEND0 are taken @@ -298,12 +298,13 @@ static unsigned int startup_bridge_irq(unsigned int irq) static void shutdown_bridge_irq(unsigned int irq) { struct bridge_controller *bc = IRQ_TO_BRIDGE(irq); + struct hub_data *hub = hub_data(cpu_to_node(bc->irq_cpu)); bridge_t *bridge = bc->base; struct slice_data *si = cpu_data[bc->irq_cpu].data; int pin, swlevel; cpuid_t cpu; - DBG("bridge_shutdown: irq 0x%x\n", irq); + pr_debug("bridge_shutdown: irq 0x%x\n", irq); pin = SLOT_FROM_PCI_IRQ(irq); /* @@ -313,7 +314,7 @@ static void shutdown_bridge_irq(unsigned int irq) swlevel = find_level(&cpu, irq); intr_disconnect_level(cpu, swlevel); - __clear_bit(swlevel, si->irq_alloc_mask); + __clear_bit(swlevel, hub->irq_alloc_mask); si->level_to_irq[swlevel] = -1; bridge->b_int_enable &= ~(1 << pin); @@ -433,25 +434,24 @@ void install_ipi(void) int slice = LOCAL_HUB_L(PI_CPU_NUM); int cpu = smp_processor_id(); struct slice_data *si = cpu_data[cpu].data; - hubreg_t mask, set; + struct hub_data *hub = hub_data(cpu_to_node(cpu)); + int resched, call; + + resched = CPU_RESCHED_A_IRQ + slice; + __set_bit(resched, hub->irq_alloc_mask); + __set_bit(resched, si->irq_enable_mask); + LOCAL_HUB_CLR_INTR(resched); + + call = CPU_CALL_A_IRQ + slice; + __set_bit(call, hub->irq_alloc_mask); + __set_bit(call, si->irq_enable_mask); + LOCAL_HUB_CLR_INTR(call); if (slice == 0) { - LOCAL_HUB_CLR_INTR(CPU_RESCHED_A_IRQ); - LOCAL_HUB_CLR_INTR(CPU_CALL_A_IRQ); - mask = LOCAL_HUB_L(PI_INT_MASK0_A); /* Slice A */ - set = (1UL << CPU_RESCHED_A_IRQ) | (1UL << CPU_CALL_A_IRQ); - mask |= set; - si->irq_enable_mask[0] |= set; - si->irq_alloc_mask[0] |= set; - LOCAL_HUB_S(PI_INT_MASK0_A, mask); + LOCAL_HUB_S(PI_INT_MASK0_A, si->irq_enable_mask[0]); + LOCAL_HUB_S(PI_INT_MASK1_A, si->irq_enable_mask[1]); } else { - LOCAL_HUB_CLR_INTR(CPU_RESCHED_B_IRQ); - LOCAL_HUB_CLR_INTR(CPU_CALL_B_IRQ); - mask = LOCAL_HUB_L(PI_INT_MASK0_B); /* Slice B */ - set = (1UL << CPU_RESCHED_B_IRQ) | (1UL << CPU_CALL_B_IRQ); - mask |= set; - si->irq_enable_mask[1] |= set; - si->irq_alloc_mask[1] |= set; - LOCAL_HUB_S(PI_INT_MASK0_B, mask); + LOCAL_HUB_S(PI_INT_MASK0_B, si->irq_enable_mask[0]); + LOCAL_HUB_S(PI_INT_MASK1_B, si->irq_enable_mask[1]); } } diff --git a/arch/mips/sgi-ip27/ip27-smp.c b/arch/mips/sgi-ip27/ip27-smp.c index 17f768cba94..3a8291b7d26 100644 --- a/arch/mips/sgi-ip27/ip27-smp.c +++ b/arch/mips/sgi-ip27/ip27-smp.c @@ -127,37 +127,28 @@ void cpu_node_probe(void) printk("Discovered %d cpus on %d nodes\n", highest + 1, num_online_nodes()); } -static void intr_clear_bits(nasid_t nasid, volatile hubreg_t *pend, - int base_level) +static __init void intr_clear_all(nasid_t nasid) { - volatile hubreg_t bits; int i; - /* Check pending interrupts */ - if ((bits = HUB_L(pend)) != 0) - for (i = 0; i < N_INTPEND_BITS; i++) - if (bits & (1 << i)) - LOCAL_HUB_CLR_INTR(base_level + i); -} - -static void intr_clear_all(nasid_t nasid) -{ REMOTE_HUB_S(nasid, PI_INT_MASK0_A, 0); REMOTE_HUB_S(nasid, PI_INT_MASK0_B, 0); REMOTE_HUB_S(nasid, PI_INT_MASK1_A, 0); REMOTE_HUB_S(nasid, PI_INT_MASK1_B, 0); - intr_clear_bits(nasid, REMOTE_HUB_ADDR(nasid, PI_INT_PEND0), - INT_PEND0_BASELVL); - intr_clear_bits(nasid, REMOTE_HUB_ADDR(nasid, PI_INT_PEND1), - INT_PEND1_BASELVL); + + for (i = 0; i < 128; i++) + REMOTE_HUB_CLR_INTR(nasid, i); } void __init prom_prepare_cpus(unsigned int max_cpus) { cnodeid_t cnode; - for_each_online_node(cnode) + for_each_online_node(cnode) { + if (cnode == 0) + continue; intr_clear_all(COMPACT_TO_NASID_NODEID(cnode)); + } replicate_kernel_text(); |