Blame view

arch/mips/sgi-ip27/ip27-smp.c 5.97 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
  /*
   * This file is subject to the terms and conditions of the GNU General
   * Public License.  See the file "COPYING" in the main directory of this
   * archive for more details.
   *
   * Copyright (C) 2000 - 2001 by Kanoj Sarcar (kanoj@sgi.com)
   * Copyright (C) 2000 - 2001 by Silicon Graphics, Inc.
   */
  #include <linux/init.h>
  #include <linux/sched.h>
  #include <linux/nodemask.h>
  #include <asm/page.h>
  #include <asm/processor.h>
  #include <asm/sn/arch.h>
  #include <asm/sn/gda.h>
  #include <asm/sn/intr.h>
  #include <asm/sn/klconfig.h>
  #include <asm/sn/launch.h>
  #include <asm/sn/mapped_kernel.h>
  #include <asm/sn/sn_private.h>
  #include <asm/sn/types.h>
  #include <asm/sn/sn0/hubpi.h>
  #include <asm/sn/sn0/hubio.h>
  #include <asm/sn/sn0/ip27.h>
  
  /*
   * Takes as first input the PROM assigned cpu id, and the kernel
   * assigned cpu id as the second.
   */
  static void alloc_cpupda(cpuid_t cpu, int cpunum)
  {
  	cnodeid_t node = get_cpu_cnode(cpu);
  	nasid_t nasid = COMPACT_TO_NASID_NODEID(node);
  
  	cputonasid(cpunum) = nasid;
cc6e8e081   Ralf Baechle   [MIPS] Remove IP2...
36
  	sn_cpu_info[cpunum].p_nodeid = node;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
  	cputoslice(cpunum) = get_cpu_slice(cpu);
  }
  
  static nasid_t get_actual_nasid(lboard_t *brd)
  {
  	klhub_t *hub;
  
  	if (!brd)
  		return INVALID_NASID;
  
  	/* find out if we are a completely disabled brd. */
  	hub  = (klhub_t *)find_first_component(brd, KLSTRUCT_HUB);
  	if (!hub)
  		return INVALID_NASID;
  	if (!(hub->hub_info.flags & KLINFO_ENABLE))	/* disabled node brd */
  		return hub->hub_info.physid;
  	else
  		return brd->brd_nasid;
  }
  
  static int do_cpumask(cnodeid_t cnode, nasid_t nasid, int highest)
  {
  	static int tot_cpus_found = 0;
  	lboard_t *brd;
  	klcpu_t *acpu;
  	int cpus_found = 0;
  	cpuid_t cpuid;
  
  	brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IP27);
  
  	do {
  		acpu = (klcpu_t *)find_first_component(brd, KLSTRUCT_CPU);
  		while (acpu) {
  			cpuid = acpu->cpu_info.virtid;
  			/* cnode is not valid for completely disabled brds */
  			if (get_actual_nasid(brd) == brd->brd_nasid)
  				cpuid_to_compact_node[cpuid] = cnode;
  			if (cpuid > highest)
  				highest = cpuid;
  			/* Only let it join in if it's marked enabled */
  			if ((acpu->cpu_info.flags & KLINFO_ENABLE) &&
  			    (tot_cpus_found != NR_CPUS)) {
98a79d6a5   Rusty Russell   cpumask: centrali...
79
  				cpu_set(cpuid, cpu_possible_map);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
  				alloc_cpupda(cpuid, tot_cpus_found);
  				cpus_found++;
  				tot_cpus_found++;
  			}
  			acpu = (klcpu_t *)find_component(brd, (klinfo_t *)acpu,
  								KLSTRUCT_CPU);
  		}
  		brd = KLCF_NEXT(brd);
  		if (!brd)
  			break;
  
  		brd = find_lboard(brd, KLTYPE_IP27);
  	} while (brd);
  
  	return highest;
  }
  
  void cpu_node_probe(void)
  {
  	int i, highest = 0;
  	gda_t *gdap = GDA;
  
  	/*
  	 * Initialize the arrays to invalid nodeid (-1)
  	 */
  	for (i = 0; i < MAX_COMPACT_NODES; i++)
  		compact_to_nasid_node[i] = INVALID_NASID;
  	for (i = 0; i < MAX_NASIDS; i++)
  		nasid_to_compact_node[i] = INVALID_CNODEID;
  	for (i = 0; i < MAXCPUS; i++)
  		cpuid_to_compact_node[i] = INVALID_CNODEID;
  
  	/*
  	 * MCD - this whole "compact node" stuff can probably be dropped,
  	 * as we can handle sparse numbering now
  	 */
  	nodes_clear(node_online_map);
  	for (i = 0; i < MAX_COMPACT_NODES; i++) {
  		nasid_t nasid = gdap->g_nasidtable[i];
  		if (nasid == INVALID_NASID)
  			break;
  		compact_to_nasid_node[i] = nasid;
  		nasid_to_compact_node[nasid] = i;
  		node_set_online(num_online_nodes());
  		highest = do_cpumask(i, nasid, highest);
  	}
  
  	printk("Discovered %d cpus on %d nodes
  ", highest + 1, num_online_nodes());
  }
39408c6af   Ralf Baechle   Replace the compl...
130
  static __init void intr_clear_all(nasid_t nasid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
131
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
132
  	int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
133
134
135
136
  	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);
39408c6af   Ralf Baechle   Replace the compl...
137
138
139
  
  	for (i = 0; i < 128; i++)
  		REMOTE_HUB_CLR_INTR(nasid, i);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
140
  }
87353d8ac   Ralf Baechle   [MIPS] SMP: Call ...
141
  static void ip27_send_ipi_single(int destid, unsigned int action)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
142
  {
87353d8ac   Ralf Baechle   [MIPS] SMP: Call ...
143
  	int irq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
144

87353d8ac   Ralf Baechle   [MIPS] SMP: Call ...
145
146
147
148
149
150
151
152
153
  	switch (action) {
  	case SMP_RESCHEDULE_YOURSELF:
  		irq = CPU_RESCHED_A_IRQ;
  		break;
  	case SMP_CALL_FUNCTION:
  		irq = CPU_CALL_A_IRQ;
  		break;
  	default:
  		panic("sendintr");
de1db6ffe   Ralf Baechle   It's unwise to di...
154
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
155

87353d8ac   Ralf Baechle   [MIPS] SMP: Call ...
156
  	irq += cputoslice(destid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
157
158
  
  	/*
87353d8ac   Ralf Baechle   [MIPS] SMP: Call ...
159
160
161
  	 * Convert the compact hub number to the NASID to get the correct
  	 * part of the address space.  Then set the interrupt bit associated
  	 * with the CPU we want to send the interrupt to.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
162
  	 */
87353d8ac   Ralf Baechle   [MIPS] SMP: Call ...
163
  	REMOTE_HUB_SEND_INTR(COMPACT_TO_NASID_NODEID(cpu_to_node(destid)), irq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
164
  }
b533e652d   Ralf Baechle   MIPS: SMP: Fix bu...
165
  static void ip27_send_ipi_mask(const struct cpumask *mask, unsigned int action)
87353d8ac   Ralf Baechle   [MIPS] SMP: Call ...
166
167
  {
  	unsigned int i;
48a048fed   Rusty Russell   cpumask: arch_sen...
168
  	for_each_cpu(i, mask)
87353d8ac   Ralf Baechle   [MIPS] SMP: Call ...
169
170
171
172
173
174
  		ip27_send_ipi_single(i, action);
  }
  
  static void __cpuinit ip27_init_secondary(void)
  {
  	per_cpu_init();
87353d8ac   Ralf Baechle   [MIPS] SMP: Call ...
175
176
177
178
  }
  
  static void __cpuinit ip27_smp_finish(void)
  {
b32bb803f   Thomas Bogendoerfer   [MIPS] IP27: Fix ...
179
180
181
182
  	extern void hub_rt_clock_event_init(void);
  
  	hub_rt_clock_event_init();
  	local_irq_enable();
87353d8ac   Ralf Baechle   [MIPS] SMP: Call ...
183
184
185
  }
  
  static void __init ip27_cpus_done(void)
9b6695a8a   Ralf Baechle   [MIPS] SMP: Fix i...
186
  {
9b6695a8a   Ralf Baechle   [MIPS] SMP: Fix i...
187
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
188
189
190
191
192
  /*
   * Launch a slave into smp_bootstrap().  It doesn't take an argument, and we
   * set sp to the kernel stack of the newly created idle process, gp to the proc
   * struct so that current_thread_info() will work.
   */
87353d8ac   Ralf Baechle   [MIPS] SMP: Call ...
193
  static void __cpuinit ip27_boot_secondary(int cpu, struct task_struct *idle)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
194
  {
dc8f6029c   Al Viro   [PATCH] mips: tas...
195
196
  	unsigned long gp = (unsigned long)task_thread_info(idle);
  	unsigned long sp = __KSTK_TOS(idle);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
197

21a151d8c   Ralf Baechle   [MIPS] checkfiles...
198
  	LAUNCH_SLAVE(cputonasid(cpu), cputoslice(cpu),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
199
200
201
  		(launch_proc_t)MAPPED_KERN_RW_TO_K0(smp_bootstrap),
  		0, (void *) sp, (void *) gp);
  }
87353d8ac   Ralf Baechle   [MIPS] SMP: Call ...
202
  static void __init ip27_smp_setup(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
203
  {
87353d8ac   Ralf Baechle   [MIPS] SMP: Call ...
204
  	cnodeid_t	cnode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
205

87353d8ac   Ralf Baechle   [MIPS] SMP: Call ...
206
207
208
209
  	for_each_online_node(cnode) {
  		if (cnode == 0)
  			continue;
  		intr_clear_all(COMPACT_TO_NASID_NODEID(cnode));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
210
  	}
87353d8ac   Ralf Baechle   [MIPS] SMP: Call ...
211
  	replicate_kernel_text();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
212
213
  
  	/*
87353d8ac   Ralf Baechle   [MIPS] SMP: Call ...
214
215
216
  	 * Assumption to be fixed: we're always booted on logical / physical
  	 * processor 0.  While we're always running on logical processor 0
  	 * this still means this is physical processor zero; it might for
877d03105   Nick Andrew   trivial: Fix miss...
217
  	 * example be disabled in the firmware.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
218
  	 */
87353d8ac   Ralf Baechle   [MIPS] SMP: Call ...
219
  	alloc_cpupda(0, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
220
  }
87353d8ac   Ralf Baechle   [MIPS] SMP: Call ...
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
  
  static void __init ip27_prepare_cpus(unsigned int max_cpus)
  {
  	/* We already did everything necessary earlier */
  }
  
  struct plat_smp_ops ip27_smp_ops = {
  	.send_ipi_single	= ip27_send_ipi_single,
  	.send_ipi_mask		= ip27_send_ipi_mask,
  	.init_secondary		= ip27_init_secondary,
  	.smp_finish		= ip27_smp_finish,
  	.cpus_done		= ip27_cpus_done,
  	.boot_secondary		= ip27_boot_secondary,
  	.smp_setup		= ip27_smp_setup,
  	.prepare_cpus		= ip27_prepare_cpus,
  };