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/agent.h> 19 #include <asm/sn/arch.h> 20 #include <asm/sn/gda.h> 21 #include <asm/sn/intr.h> 22 #include <asm/sn/klconfig.h> 23 #include <asm/sn/launch.h> 24 #include <asm/sn/mapped_kernel.h> 25 #include <asm/sn/types.h> 26 27 #include "ip27-common.h" 28 29 static int node_scan_cpus(nasid_t nasid, int highest) 30 { 31 static int cpus_found; 32 lboard_t *brd; 33 klcpu_t *acpu; 34 cpuid_t cpuid; 35 36 brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IP27); 37 38 do { 39 acpu = (klcpu_t *)find_first_component(brd, KLSTRUCT_CPU); 40 while (acpu) { 41 cpuid = acpu->cpu_info.virtid; 42 /* Only let it join in if it's marked enabled */ 43 if ((acpu->cpu_info.flags & KLINFO_ENABLE) && 44 (cpus_found != NR_CPUS)) { 45 if (cpuid > highest) 46 highest = cpuid; 47 set_cpu_possible(cpuid, true); 48 cputonasid(cpus_found) = nasid; 49 cputoslice(cpus_found) = acpu->cpu_info.physid; 50 sn_cpu_info[cpus_found].p_speed = 51 acpu->cpu_speed; 52 cpus_found++; 53 } 54 acpu = (klcpu_t *)find_component(brd, (klinfo_t *)acpu, 55 KLSTRUCT_CPU); 56 } 57 brd = KLCF_NEXT(brd); 58 if (!brd) 59 break; 60 61 brd = find_lboard(brd, KLTYPE_IP27); 62 } while (brd); 63 64 return highest; 65 } 66 67 void cpu_node_probe(void) 68 { 69 int i, highest = 0; 70 gda_t *gdap = GDA; 71 72 nodes_clear(node_online_map); 73 nodes_clear(node_possible_map); 74 for (i = 0; i < MAX_NUMNODES; i++) { 75 nasid_t nasid = gdap->g_nasidtable[i]; 76 if (nasid == INVALID_NASID) 77 break; 78 node_set_online(nasid); 79 node_set(nasid, node_possible_map); 80 highest = node_scan_cpus(nasid, highest); 81 } 82 83 printk("Discovered %d cpus on %d nodes\n", highest + 1, num_online_nodes()); 84 } 85 86 static __init void intr_clear_all(nasid_t nasid) 87 { 88 int i; 89 90 REMOTE_HUB_S(nasid, PI_INT_MASK0_A, 0); 91 REMOTE_HUB_S(nasid, PI_INT_MASK0_B, 0); 92 REMOTE_HUB_S(nasid, PI_INT_MASK1_A, 0); 93 REMOTE_HUB_S(nasid, PI_INT_MASK1_B, 0); 94 95 for (i = 0; i < 128; i++) 96 REMOTE_HUB_CLR_INTR(nasid, i); 97 } 98 99 static void ip27_send_ipi_single(int destid, unsigned int action) 100 { 101 int irq; 102 103 switch (action) { 104 case SMP_RESCHEDULE_YOURSELF: 105 irq = CPU_RESCHED_A_IRQ; 106 break; 107 case SMP_CALL_FUNCTION: 108 irq = CPU_CALL_A_IRQ; 109 break; 110 default: 111 panic("sendintr"); 112 } 113 114 irq += cputoslice(destid); 115 116 /* 117 * Set the interrupt bit associated with the CPU we want to 118 * send the interrupt to. 119 */ 120 REMOTE_HUB_SEND_INTR(cpu_to_node(destid), irq); 121 } 122 123 static void ip27_send_ipi_mask(const struct cpumask *mask, unsigned int action) 124 { 125 unsigned int i; 126 127 for_each_cpu(i, mask) 128 ip27_send_ipi_single(i, action); 129 } 130 131 static void ip27_init_cpu(void) 132 { 133 per_cpu_init(); 134 } 135 136 static void ip27_smp_finish(void) 137 { 138 hub_rt_clock_event_init(); 139 local_irq_enable(); 140 } 141 142 /* 143 * Launch a slave into smp_bootstrap(). It doesn't take an argument, and we 144 * set sp to the kernel stack of the newly created idle process, gp to the proc 145 * struct so that current_thread_info() will work. 146 */ 147 static int ip27_boot_secondary(int cpu, struct task_struct *idle) 148 { 149 unsigned long gp = (unsigned long)task_thread_info(idle); 150 unsigned long sp = __KSTK_TOS(idle); 151 152 LAUNCH_SLAVE(cputonasid(cpu), cputoslice(cpu), 153 (launch_proc_t)MAPPED_KERN_RW_TO_K0(smp_bootstrap), 154 0, (void *) sp, (void *) gp); 155 return 0; 156 } 157 158 static void __init ip27_smp_setup(void) 159 { 160 nasid_t nasid; 161 162 for_each_online_node(nasid) { 163 if (nasid == 0) 164 continue; 165 intr_clear_all(nasid); 166 } 167 168 replicate_kernel_text(); 169 170 /* 171 * PROM sets up system, that boot cpu is always first CPU on nasid 0 172 */ 173 cputonasid(0) = 0; 174 cputoslice(0) = LOCAL_HUB_L(PI_CPU_NUM); 175 } 176 177 static void __init ip27_prepare_cpus(unsigned int max_cpus) 178 { 179 /* We already did everything necessary earlier */ 180 } 181 182 const struct plat_smp_ops ip27_smp_ops = { 183 .send_ipi_single = ip27_send_ipi_single, 184 .send_ipi_mask = ip27_send_ipi_mask, 185 .init_secondary = ip27_init_cpu, 186 .smp_finish = ip27_smp_finish, 187 .boot_secondary = ip27_boot_secondary, 188 .smp_setup = ip27_smp_setup, 189 .prepare_cpus = ip27_prepare_cpus, 190 .prepare_boot_cpu = ip27_init_cpu, 191 }; 192