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