aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/sgi-ip27
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/sgi-ip27')
-rw-r--r--arch/mips/sgi-ip27/Kconfig54
-rw-r--r--arch/mips/sgi-ip27/ip27-console.c4
-rw-r--r--arch/mips/sgi-ip27/ip27-init.c50
-rw-r--r--arch/mips/sgi-ip27/ip27-irq.c66
-rw-r--r--arch/mips/sgi-ip27/ip27-smp.c25
5 files changed, 120 insertions, 79 deletions
diff --git a/arch/mips/sgi-ip27/Kconfig b/arch/mips/sgi-ip27/Kconfig
new file mode 100644
index 000000000000..7b0bc4437243
--- /dev/null
+++ b/arch/mips/sgi-ip27/Kconfig
@@ -0,0 +1,54 @@
1#config SGI_SN0_XXL
2# bool "IP27 XXL"
3# depends on SGI_IP27
4# This options adds support for userspace processes upto 16TB size.
5# Normally the limit is just .5TB.
6
7config SGI_SN0_N_MODE
8 bool "IP27 N-Mode"
9 depends on SGI_IP27
10 help
11 The nodes of Origin 200, Origin 2000 and Onyx 2 systems can be
12 configured in either N-Modes which allows for more nodes or M-Mode
13 which allows for more memory. Your system is most probably
14 running in M-Mode, so you should say N here.
15
16config ARCH_DISCONTIGMEM_ENABLE
17 bool
18 default y if SGI_IP27
19 help
20 Say Y to upport efficient handling of discontiguous physical memory,
21 for architectures which are either NUMA (Non-Uniform Memory Access)
22 or have huge holes in the physical address space for other reasons.
23 See <file:Documentation/vm/numa> for more.
24
25config NUMA
26 bool "NUMA Support"
27 depends on SGI_IP27
28 help
29 Say Y to compile the kernel to support NUMA (Non-Uniform Memory
30 Access). This option is for configuring high-end multiprocessor
31 server machines. If in doubt, say N.
32
33config MAPPED_KERNEL
34 bool "Mapped kernel support"
35 depends on SGI_IP27
36 help
37 Change the way a Linux kernel is loaded into memory on a MIPS64
38 machine. This is required in order to support text replication and
39 NUMA. If you need to understand it, read the source code.
40
41config REPLICATE_KTEXT
42 bool "Kernel text replication support"
43 depends on SGI_IP27
44 help
45 Say Y here to enable replicating the kernel text across multiple
46 nodes in a NUMA cluster. This trades memory for speed.
47
48config REPLICATE_EXHANDLERS
49 bool "Exception handler replication support"
50 depends on SGI_IP27
51 help
52 Say Y here to enable replicating the kernel exception handlers
53 across multiple nodes in a NUMA cluster. This trades memory for
54 speed.
diff --git a/arch/mips/sgi-ip27/ip27-console.c b/arch/mips/sgi-ip27/ip27-console.c
index d97f5b5ef844..3e1ac299b804 100644
--- a/arch/mips/sgi-ip27/ip27-console.c
+++ b/arch/mips/sgi-ip27/ip27-console.c
@@ -30,8 +30,10 @@
30static inline struct ioc3_uartregs *console_uart(void) 30static inline struct ioc3_uartregs *console_uart(void)
31{ 31{
32 struct ioc3 *ioc3; 32 struct ioc3 *ioc3;
33 nasid_t nasid;
33 34
34 ioc3 = (struct ioc3 *)KL_CONFIG_CH_CONS_INFO(get_nasid())->memory_base; 35 nasid = (master_nasid == INVALID_NASID) ? get_nasid() : master_nasid;
36 ioc3 = (struct ioc3 *)KL_CONFIG_CH_CONS_INFO(nasid)->memory_base;
35 37
36 return &ioc3->sregs.uarta; 38 return &ioc3->sregs.uarta;
37} 39}
diff --git a/arch/mips/sgi-ip27/ip27-init.c b/arch/mips/sgi-ip27/ip27-init.c
index 6dcee5c46c74..8651a0e75404 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)
56{ 56{
57 struct hub_data *hub = hub_data(cnode); 57 struct hub_data *hub = hub_data(cnode);
58 nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode); 58 nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode);
59 int i;
59 60
60 cpu_set(smp_processor_id(), hub->h_cpus); 61 cpu_set(smp_processor_id(), hub->h_cpus);
61 62
62 if (test_and_set_bit(cnode, hub_init_mask)) 63 if (test_and_set_bit(cnode, hub_init_mask))
63 return; 64 return;
64
65 /* 65 /*
66 * Set CRB timeout at 5ms, (< PI timeout of 10ms) 66 * Set CRB timeout at 5ms, (< PI timeout of 10ms)
67 */ 67 */
@@ -88,6 +88,24 @@ static void __init per_hub_init(cnodeid_t cnode)
88 __flush_cache_all(); 88 __flush_cache_all();
89 } 89 }
90#endif 90#endif
91
92 /*
93 * Some interrupts are reserved by hardware or by software convention.
94 * Mark these as reserved right away so they won't be used accidently
95 * later.
96 */
97 for (i = 0; i <= BASE_PCI_IRQ; i++) {
98 __set_bit(i, hub->irq_alloc_mask);
99 LOCAL_HUB_CLR_INTR(INT_PEND0_BASELVL + i);
100 }
101
102 __set_bit(IP_PEND0_6_63, hub->irq_alloc_mask);
103 LOCAL_HUB_S(PI_INT_PEND_MOD, IP_PEND0_6_63);
104
105 for (i = NI_BRDCAST_ERR_A; i <= MSC_PANIC_INTR; i++) {
106 __set_bit(i, hub->irq_alloc_mask);
107 LOCAL_HUB_CLR_INTR(INT_PEND1_BASELVL + i);
108 }
91} 109}
92 110
93void __init per_cpu_init(void) 111void __init per_cpu_init(void)
@@ -104,30 +122,12 @@ void __init per_cpu_init(void)
104 122
105 clear_c0_status(ST0_IM); 123 clear_c0_status(ST0_IM);
106 124
125 per_hub_init(cnode);
126
107 for (i = 0; i < LEVELS_PER_SLICE; i++) 127 for (i = 0; i < LEVELS_PER_SLICE; i++)
108 si->level_to_irq[i] = -1; 128 si->level_to_irq[i] = -1;
109 129
110 /* 130 /*
111 * Some interrupts are reserved by hardware or by software convention.
112 * Mark these as reserved right away so they won't be used accidently
113 * later.
114 */
115 for (i = 0; i <= BASE_PCI_IRQ; i++) {
116 __set_bit(i, si->irq_alloc_mask);
117 LOCAL_HUB_S(PI_INT_PEND_MOD, i);
118 }
119
120 __set_bit(IP_PEND0_6_63, si->irq_alloc_mask);
121 LOCAL_HUB_S(PI_INT_PEND_MOD, IP_PEND0_6_63);
122
123 for (i = NI_BRDCAST_ERR_A; i <= MSC_PANIC_INTR; i++) {
124 __set_bit(i, si->irq_alloc_mask + 1);
125 LOCAL_HUB_S(PI_INT_PEND_MOD, i);
126 }
127
128 LOCAL_HUB_L(PI_INT_PEND0);
129
130 /*
131 * We use this so we can find the local hub's data as fast as only 131 * We use this so we can find the local hub's data as fast as only
132 * possible. 132 * possible.
133 */ 133 */
@@ -140,8 +140,6 @@ void __init per_cpu_init(void)
140 install_cpu_nmi_handler(cputoslice(cpu)); 140 install_cpu_nmi_handler(cputoslice(cpu));
141 141
142 set_c0_status(SRB_DEV0 | SRB_DEV1); 142 set_c0_status(SRB_DEV0 | SRB_DEV1);
143
144 per_hub_init(cnode);
145} 143}
146 144
147/* 145/*
@@ -198,7 +196,7 @@ extern void ip27_setup_console(void);
198extern void ip27_time_init(void); 196extern void ip27_time_init(void);
199extern void ip27_reboot_setup(void); 197extern void ip27_reboot_setup(void);
200 198
201static int __init ip27_setup(void) 199void __init plat_setup(void)
202{ 200{
203 hubreg_t p, e, n_mode; 201 hubreg_t p, e, n_mode;
204 nasid_t nid; 202 nasid_t nid;
@@ -245,8 +243,4 @@ static int __init ip27_setup(void)
245 set_io_port_base(IO_BASE); 243 set_io_port_base(IO_BASE);
246 244
247 board_time_init = ip27_time_init; 245 board_time_init = ip27_time_init;
248
249 return 0;
250} 246}
251
252early_initcall(ip27_setup);
diff --git a/arch/mips/sgi-ip27/ip27-irq.c b/arch/mips/sgi-ip27/ip27-irq.c
index 61817a18aed2..73e5e52781d8 100644
--- a/arch/mips/sgi-ip27/ip27-irq.c
+++ b/arch/mips/sgi-ip27/ip27-irq.c
@@ -5,6 +5,9 @@
5 * Copyright (C) 1999, 2000 Silicon Graphics, Inc. 5 * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
6 * Copyright (C) 1999 - 2001 Kanoj Sarcar 6 * Copyright (C) 1999 - 2001 Kanoj Sarcar
7 */ 7 */
8
9#undef DEBUG
10
8#include <linux/config.h> 11#include <linux/config.h>
9#include <linux/init.h> 12#include <linux/init.h>
10#include <linux/irq.h> 13#include <linux/irq.h>
@@ -14,11 +17,11 @@
14#include <linux/types.h> 17#include <linux/types.h>
15#include <linux/interrupt.h> 18#include <linux/interrupt.h>
16#include <linux/ioport.h> 19#include <linux/ioport.h>
17#include <linux/irq.h>
18#include <linux/timex.h> 20#include <linux/timex.h>
19#include <linux/slab.h> 21#include <linux/slab.h>
20#include <linux/random.h> 22#include <linux/random.h>
21#include <linux/smp_lock.h> 23#include <linux/smp_lock.h>
24#include <linux/kernel.h>
22#include <linux/kernel_stat.h> 25#include <linux/kernel_stat.h>
23#include <linux/delay.h> 26#include <linux/delay.h>
24#include <linux/bitops.h> 27#include <linux/bitops.h>
@@ -37,13 +40,6 @@
37#include <asm/sn/hub.h> 40#include <asm/sn/hub.h>
38#include <asm/sn/intr.h> 41#include <asm/sn/intr.h>
39 42
40#undef DEBUG_IRQ
41#ifdef DEBUG_IRQ
42#define DBG(x...) printk(x)
43#else
44#define DBG(x...)
45#endif
46
47/* 43/*
48 * Linux has a controller-independent x86 interrupt architecture. 44 * Linux has a controller-independent x86 interrupt architecture.
49 * every controller has a 'controller-template', that is used 45 * every controller has a 'controller-template', that is used
@@ -74,14 +70,15 @@ extern int irq_to_slot[];
74 70
75static inline int alloc_level(int cpu, int irq) 71static inline int alloc_level(int cpu, int irq)
76{ 72{
73 struct hub_data *hub = hub_data(cpu_to_node(cpu));
77 struct slice_data *si = cpu_data[cpu].data; 74 struct slice_data *si = cpu_data[cpu].data;
78 int level; /* pre-allocated entries */ 75 int level;
79 76
80 level = find_first_zero_bit(si->irq_alloc_mask, LEVELS_PER_SLICE); 77 level = find_first_zero_bit(hub->irq_alloc_mask, LEVELS_PER_SLICE);
81 if (level >= LEVELS_PER_SLICE) 78 if (level >= LEVELS_PER_SLICE)
82 panic("Cpu %d flooded with devices\n", cpu); 79 panic("Cpu %d flooded with devices\n", cpu);
83 80
84 __set_bit(level, si->irq_alloc_mask); 81 __set_bit(level, hub->irq_alloc_mask);
85 si->level_to_irq[level] = irq; 82 si->level_to_irq[level] = irq;
86 83
87 return level; 84 return level;
@@ -216,9 +213,11 @@ static int intr_connect_level(int cpu, int bit)
216{ 213{
217 nasid_t nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(cpu)); 214 nasid_t nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(cpu));
218 struct slice_data *si = cpu_data[cpu].data; 215 struct slice_data *si = cpu_data[cpu].data;
216 unsigned long flags;
219 217
220 __set_bit(bit, si->irq_enable_mask); 218 set_bit(bit, si->irq_enable_mask);
221 219
220 local_irq_save(flags);
222 if (!cputoslice(cpu)) { 221 if (!cputoslice(cpu)) {
223 REMOTE_HUB_S(nasid, PI_INT_MASK0_A, si->irq_enable_mask[0]); 222 REMOTE_HUB_S(nasid, PI_INT_MASK0_A, si->irq_enable_mask[0]);
224 REMOTE_HUB_S(nasid, PI_INT_MASK1_A, si->irq_enable_mask[1]); 223 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)
226 REMOTE_HUB_S(nasid, PI_INT_MASK0_B, si->irq_enable_mask[0]); 225 REMOTE_HUB_S(nasid, PI_INT_MASK0_B, si->irq_enable_mask[0]);
227 REMOTE_HUB_S(nasid, PI_INT_MASK1_B, si->irq_enable_mask[1]); 226 REMOTE_HUB_S(nasid, PI_INT_MASK1_B, si->irq_enable_mask[1]);
228 } 227 }
228 local_irq_restore(flags);
229 229
230 return 0; 230 return 0;
231} 231}
@@ -235,7 +235,7 @@ static int intr_disconnect_level(int cpu, int bit)
235 nasid_t nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(cpu)); 235 nasid_t nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(cpu));
236 struct slice_data *si = cpu_data[cpu].data; 236 struct slice_data *si = cpu_data[cpu].data;
237 237
238 __clear_bit(bit, si->irq_enable_mask); 238 clear_bit(bit, si->irq_enable_mask);
239 239
240 if (!cputoslice(cpu)) { 240 if (!cputoslice(cpu)) {
241 REMOTE_HUB_S(nasid, PI_INT_MASK0_A, si->irq_enable_mask[0]); 241 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)
261 bc = IRQ_TO_BRIDGE(irq); 261 bc = IRQ_TO_BRIDGE(irq);
262 bridge = bc->base; 262 bridge = bc->base;
263 263
264 DBG("bridge_startup(): irq= 0x%x pin=%d\n", irq, pin); 264 pr_debug("bridge_startup(): irq= 0x%x pin=%d\n", irq, pin);
265 /* 265 /*
266 * "map" irq to a swlevel greater than 6 since the first 6 bits 266 * "map" irq to a swlevel greater than 6 since the first 6 bits
267 * of INT_PEND0 are taken 267 * of INT_PEND0 are taken
@@ -298,12 +298,13 @@ static unsigned int startup_bridge_irq(unsigned int irq)
298static void shutdown_bridge_irq(unsigned int irq) 298static void shutdown_bridge_irq(unsigned int irq)
299{ 299{
300 struct bridge_controller *bc = IRQ_TO_BRIDGE(irq); 300 struct bridge_controller *bc = IRQ_TO_BRIDGE(irq);
301 struct hub_data *hub = hub_data(cpu_to_node(bc->irq_cpu));
301 bridge_t *bridge = bc->base; 302 bridge_t *bridge = bc->base;
302 struct slice_data *si = cpu_data[bc->irq_cpu].data; 303 struct slice_data *si = cpu_data[bc->irq_cpu].data;
303 int pin, swlevel; 304 int pin, swlevel;
304 cpuid_t cpu; 305 cpuid_t cpu;
305 306
306 DBG("bridge_shutdown: irq 0x%x\n", irq); 307 pr_debug("bridge_shutdown: irq 0x%x\n", irq);
307 pin = SLOT_FROM_PCI_IRQ(irq); 308 pin = SLOT_FROM_PCI_IRQ(irq);
308 309
309 /* 310 /*
@@ -313,7 +314,7 @@ static void shutdown_bridge_irq(unsigned int irq)
313 swlevel = find_level(&cpu, irq); 314 swlevel = find_level(&cpu, irq);
314 intr_disconnect_level(cpu, swlevel); 315 intr_disconnect_level(cpu, swlevel);
315 316
316 __clear_bit(swlevel, si->irq_alloc_mask); 317 __clear_bit(swlevel, hub->irq_alloc_mask);
317 si->level_to_irq[swlevel] = -1; 318 si->level_to_irq[swlevel] = -1;
318 319
319 bridge->b_int_enable &= ~(1 << pin); 320 bridge->b_int_enable &= ~(1 << pin);
@@ -433,25 +434,24 @@ void install_ipi(void)
433 int slice = LOCAL_HUB_L(PI_CPU_NUM); 434 int slice = LOCAL_HUB_L(PI_CPU_NUM);
434 int cpu = smp_processor_id(); 435 int cpu = smp_processor_id();
435 struct slice_data *si = cpu_data[cpu].data; 436 struct slice_data *si = cpu_data[cpu].data;
436 hubreg_t mask, set; 437 struct hub_data *hub = hub_data(cpu_to_node(cpu));
438 int resched, call;
439
440 resched = CPU_RESCHED_A_IRQ + slice;
441 __set_bit(resched, hub->irq_alloc_mask);
442 __set_bit(resched, si->irq_enable_mask);
443 LOCAL_HUB_CLR_INTR(resched);
444
445 call = CPU_CALL_A_IRQ + slice;
446 __set_bit(call, hub->irq_alloc_mask);
447 __set_bit(call, si->irq_enable_mask);
448 LOCAL_HUB_CLR_INTR(call);
437 449
438 if (slice == 0) { 450 if (slice == 0) {
439 LOCAL_HUB_CLR_INTR(CPU_RESCHED_A_IRQ); 451 LOCAL_HUB_S(PI_INT_MASK0_A, si->irq_enable_mask[0]);
440 LOCAL_HUB_CLR_INTR(CPU_CALL_A_IRQ); 452 LOCAL_HUB_S(PI_INT_MASK1_A, si->irq_enable_mask[1]);
441 mask = LOCAL_HUB_L(PI_INT_MASK0_A); /* Slice A */
442 set = (1UL << CPU_RESCHED_A_IRQ) | (1UL << CPU_CALL_A_IRQ);
443 mask |= set;
444 si->irq_enable_mask[0] |= set;
445 si->irq_alloc_mask[0] |= set;
446 LOCAL_HUB_S(PI_INT_MASK0_A, mask);
447 } else { 453 } else {
448 LOCAL_HUB_CLR_INTR(CPU_RESCHED_B_IRQ); 454 LOCAL_HUB_S(PI_INT_MASK0_B, si->irq_enable_mask[0]);
449 LOCAL_HUB_CLR_INTR(CPU_CALL_B_IRQ); 455 LOCAL_HUB_S(PI_INT_MASK1_B, si->irq_enable_mask[1]);
450 mask = LOCAL_HUB_L(PI_INT_MASK0_B); /* Slice B */
451 set = (1UL << CPU_RESCHED_B_IRQ) | (1UL << CPU_CALL_B_IRQ);
452 mask |= set;
453 si->irq_enable_mask[1] |= set;
454 si->irq_alloc_mask[1] |= set;
455 LOCAL_HUB_S(PI_INT_MASK0_B, mask);
456 } 456 }
457} 457}
diff --git a/arch/mips/sgi-ip27/ip27-smp.c b/arch/mips/sgi-ip27/ip27-smp.c
index 17f768cba94f..3a8291b7d26d 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)
127 printk("Discovered %d cpus on %d nodes\n", highest + 1, num_online_nodes()); 127 printk("Discovered %d cpus on %d nodes\n", highest + 1, num_online_nodes());
128} 128}
129 129
130static void intr_clear_bits(nasid_t nasid, volatile hubreg_t *pend, 130static __init void intr_clear_all(nasid_t nasid)
131 int base_level)
132{ 131{
133 volatile hubreg_t bits;
134 int i; 132 int i;
135 133
136 /* Check pending interrupts */
137 if ((bits = HUB_L(pend)) != 0)
138 for (i = 0; i < N_INTPEND_BITS; i++)
139 if (bits & (1 << i))
140 LOCAL_HUB_CLR_INTR(base_level + i);
141}
142
143static void intr_clear_all(nasid_t nasid)
144{
145 REMOTE_HUB_S(nasid, PI_INT_MASK0_A, 0); 134 REMOTE_HUB_S(nasid, PI_INT_MASK0_A, 0);
146 REMOTE_HUB_S(nasid, PI_INT_MASK0_B, 0); 135 REMOTE_HUB_S(nasid, PI_INT_MASK0_B, 0);
147 REMOTE_HUB_S(nasid, PI_INT_MASK1_A, 0); 136 REMOTE_HUB_S(nasid, PI_INT_MASK1_A, 0);
148 REMOTE_HUB_S(nasid, PI_INT_MASK1_B, 0); 137 REMOTE_HUB_S(nasid, PI_INT_MASK1_B, 0);
149 intr_clear_bits(nasid, REMOTE_HUB_ADDR(nasid, PI_INT_PEND0), 138
150 INT_PEND0_BASELVL); 139 for (i = 0; i < 128; i++)
151 intr_clear_bits(nasid, REMOTE_HUB_ADDR(nasid, PI_INT_PEND1), 140 REMOTE_HUB_CLR_INTR(nasid, i);
152 INT_PEND1_BASELVL);
153} 141}
154 142
155void __init prom_prepare_cpus(unsigned int max_cpus) 143void __init prom_prepare_cpus(unsigned int max_cpus)
156{ 144{
157 cnodeid_t cnode; 145 cnodeid_t cnode;
158 146
159 for_each_online_node(cnode) 147 for_each_online_node(cnode) {
148 if (cnode == 0)
149 continue;
160 intr_clear_all(COMPACT_TO_NASID_NODEID(cnode)); 150 intr_clear_all(COMPACT_TO_NASID_NODEID(cnode));
151 }
161 152
162 replicate_kernel_text(); 153 replicate_kernel_text();
163 154