xref: /openbmc/linux/arch/mips/sgi-ip27/ip27-smp.c (revision 2d68bb26)
1 /*
2  * This file is subject to the terms and conditions of the GNU General
3  * Public License.  See the file "COPYING" in the main directory of this
4  * archive for more details.
5  *
6  * Copyright (C) 2000 - 2001 by Kanoj Sarcar (kanoj@sgi.com)
7  * Copyright (C) 2000 - 2001 by Silicon Graphics, Inc.
8  */
9 #include <linux/init.h>
10 #include <linux/sched.h>
11 #include <linux/sched/task_stack.h>
12 #include <linux/topology.h>
13 #include <linux/nodemask.h>
14 
15 #include <asm/page.h>
16 #include <asm/processor.h>
17 #include <asm/ptrace.h>
18 #include <asm/sn/arch.h>
19 #include <asm/sn/gda.h>
20 #include <asm/sn/intr.h>
21 #include <asm/sn/klconfig.h>
22 #include <asm/sn/launch.h>
23 #include <asm/sn/mapped_kernel.h>
24 #include <asm/sn/sn_private.h>
25 #include <asm/sn/types.h>
26 #include <asm/sn/sn0/hubpi.h>
27 #include <asm/sn/sn0/hubio.h>
28 #include <asm/sn/sn0/ip27.h>
29 
30 #include "ip27-common.h"
31 
32 /*
33  * Takes as first input the PROM assigned cpu id, and the kernel
34  * assigned cpu id as the second.
35  */
36 static void alloc_cpupda(nasid_t nasid, cpuid_t cpu, int cpunum)
37 {
38 	cputonasid(cpunum) = nasid;
39 	cputoslice(cpunum) = get_cpu_slice(cpu);
40 }
41 
42 static int do_cpumask(nasid_t nasid, int highest)
43 {
44 	static int tot_cpus_found = 0;
45 	lboard_t *brd;
46 	klcpu_t *acpu;
47 	int cpus_found = 0;
48 	cpuid_t cpuid;
49 
50 	brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IP27);
51 
52 	do {
53 		acpu = (klcpu_t *)find_first_component(brd, KLSTRUCT_CPU);
54 		while (acpu) {
55 			cpuid = acpu->cpu_info.virtid;
56 			/* Only let it join in if it's marked enabled */
57 			if ((acpu->cpu_info.flags & KLINFO_ENABLE) &&
58 			    (tot_cpus_found != NR_CPUS)) {
59 				if (cpuid > highest)
60 					highest = cpuid;
61 				set_cpu_possible(cpuid, true);
62 				alloc_cpupda(nasid, cpuid, tot_cpus_found);
63 				cpus_found++;
64 				tot_cpus_found++;
65 			}
66 			acpu = (klcpu_t *)find_component(brd, (klinfo_t *)acpu,
67 								KLSTRUCT_CPU);
68 		}
69 		brd = KLCF_NEXT(brd);
70 		if (!brd)
71 			break;
72 
73 		brd = find_lboard(brd, KLTYPE_IP27);
74 	} while (brd);
75 
76 	return highest;
77 }
78 
79 void cpu_node_probe(void)
80 {
81 	int i, highest = 0;
82 	gda_t *gdap = GDA;
83 
84 	nodes_clear(node_online_map);
85 	for (i = 0; i < MAX_NUMNODES; i++) {
86 		nasid_t nasid = gdap->g_nasidtable[i];
87 		if (nasid == INVALID_NASID)
88 			break;
89 		node_set_online(nasid);
90 		highest = do_cpumask(nasid, highest);
91 	}
92 
93 	printk("Discovered %d cpus on %d nodes\n", highest + 1, num_online_nodes());
94 }
95 
96 static __init void intr_clear_all(nasid_t nasid)
97 {
98 	int i;
99 
100 	REMOTE_HUB_S(nasid, PI_INT_MASK0_A, 0);
101 	REMOTE_HUB_S(nasid, PI_INT_MASK0_B, 0);
102 	REMOTE_HUB_S(nasid, PI_INT_MASK1_A, 0);
103 	REMOTE_HUB_S(nasid, PI_INT_MASK1_B, 0);
104 
105 	for (i = 0; i < 128; i++)
106 		REMOTE_HUB_CLR_INTR(nasid, i);
107 }
108 
109 static void ip27_send_ipi_single(int destid, unsigned int action)
110 {
111 	int irq;
112 
113 	switch (action) {
114 	case SMP_RESCHEDULE_YOURSELF:
115 		irq = CPU_RESCHED_A_IRQ;
116 		break;
117 	case SMP_CALL_FUNCTION:
118 		irq = CPU_CALL_A_IRQ;
119 		break;
120 	default:
121 		panic("sendintr");
122 	}
123 
124 	irq += cputoslice(destid);
125 
126 	/*
127 	 * Set the interrupt bit associated with the CPU we want to
128 	 * send the interrupt to.
129 	 */
130 	REMOTE_HUB_SEND_INTR(cpu_to_node(destid), irq);
131 }
132 
133 static void ip27_send_ipi_mask(const struct cpumask *mask, unsigned int action)
134 {
135 	unsigned int i;
136 
137 	for_each_cpu(i, mask)
138 		ip27_send_ipi_single(i, action);
139 }
140 
141 static void ip27_init_cpu(void)
142 {
143 	per_cpu_init();
144 }
145 
146 static void ip27_smp_finish(void)
147 {
148 	hub_rt_clock_event_init();
149 	local_irq_enable();
150 }
151 
152 /*
153  * Launch a slave into smp_bootstrap().	 It doesn't take an argument, and we
154  * set sp to the kernel stack of the newly created idle process, gp to the proc
155  * struct so that current_thread_info() will work.
156  */
157 static int ip27_boot_secondary(int cpu, struct task_struct *idle)
158 {
159 	unsigned long gp = (unsigned long)task_thread_info(idle);
160 	unsigned long sp = __KSTK_TOS(idle);
161 
162 	LAUNCH_SLAVE(cputonasid(cpu), cputoslice(cpu),
163 		(launch_proc_t)MAPPED_KERN_RW_TO_K0(smp_bootstrap),
164 		0, (void *) sp, (void *) gp);
165 	return 0;
166 }
167 
168 static void __init ip27_smp_setup(void)
169 {
170 	nasid_t nasid;
171 
172 	for_each_online_node(nasid) {
173 		if (nasid == 0)
174 			continue;
175 		intr_clear_all(nasid);
176 	}
177 
178 	replicate_kernel_text();
179 
180 	/*
181 	 * PROM sets up system, that boot cpu is always first CPU on nasid 0
182 	 */
183 	alloc_cpupda(0, 0, 0);
184 }
185 
186 static void __init ip27_prepare_cpus(unsigned int max_cpus)
187 {
188 	/* We already did everything necessary earlier */
189 }
190 
191 const struct plat_smp_ops ip27_smp_ops = {
192 	.send_ipi_single	= ip27_send_ipi_single,
193 	.send_ipi_mask		= ip27_send_ipi_mask,
194 	.init_secondary		= ip27_init_cpu,
195 	.smp_finish		= ip27_smp_finish,
196 	.boot_secondary		= ip27_boot_secondary,
197 	.smp_setup		= ip27_smp_setup,
198 	.prepare_cpus		= ip27_prepare_cpus,
199 	.prepare_boot_cpu	= ip27_init_cpu,
200 };
201