Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * This file is subject to the terms and conditions of the GNU General
0003  * Public License.  See the file "COPYING" in the main directory of this
0004  * archive for more details.
0005  *
0006  * Copyright (C) 2000 - 2001 by Kanoj Sarcar (kanoj@sgi.com)
0007  * Copyright (C) 2000 - 2001 by Silicon Graphics, Inc.
0008  */
0009 #include <linux/init.h>
0010 #include <linux/sched.h>
0011 #include <linux/sched/task_stack.h>
0012 #include <linux/topology.h>
0013 #include <linux/nodemask.h>
0014 
0015 #include <asm/page.h>
0016 #include <asm/processor.h>
0017 #include <asm/ptrace.h>
0018 #include <asm/sn/agent.h>
0019 #include <asm/sn/arch.h>
0020 #include <asm/sn/gda.h>
0021 #include <asm/sn/intr.h>
0022 #include <asm/sn/klconfig.h>
0023 #include <asm/sn/launch.h>
0024 #include <asm/sn/mapped_kernel.h>
0025 #include <asm/sn/types.h>
0026 
0027 #include "ip27-common.h"
0028 
0029 static int node_scan_cpus(nasid_t nasid, int highest)
0030 {
0031     static int cpus_found;
0032     lboard_t *brd;
0033     klcpu_t *acpu;
0034     cpuid_t cpuid;
0035 
0036     brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IP27);
0037 
0038     do {
0039         acpu = (klcpu_t *)find_first_component(brd, KLSTRUCT_CPU);
0040         while (acpu) {
0041             cpuid = acpu->cpu_info.virtid;
0042             /* Only let it join in if it's marked enabled */
0043             if ((acpu->cpu_info.flags & KLINFO_ENABLE) &&
0044                 (cpus_found != NR_CPUS)) {
0045                 if (cpuid > highest)
0046                     highest = cpuid;
0047                 set_cpu_possible(cpuid, true);
0048                 cputonasid(cpus_found) = nasid;
0049                 cputoslice(cpus_found) = acpu->cpu_info.physid;
0050                 sn_cpu_info[cpus_found].p_speed =
0051                             acpu->cpu_speed;
0052                 cpus_found++;
0053             }
0054             acpu = (klcpu_t *)find_component(brd, (klinfo_t *)acpu,
0055                                 KLSTRUCT_CPU);
0056         }
0057         brd = KLCF_NEXT(brd);
0058         if (!brd)
0059             break;
0060 
0061         brd = find_lboard(brd, KLTYPE_IP27);
0062     } while (brd);
0063 
0064     return highest;
0065 }
0066 
0067 void cpu_node_probe(void)
0068 {
0069     int i, highest = 0;
0070     gda_t *gdap = GDA;
0071 
0072     nodes_clear(node_online_map);
0073     for (i = 0; i < MAX_NUMNODES; i++) {
0074         nasid_t nasid = gdap->g_nasidtable[i];
0075         if (nasid == INVALID_NASID)
0076             break;
0077         node_set_online(nasid);
0078         highest = node_scan_cpus(nasid, highest);
0079     }
0080 
0081     printk("Discovered %d cpus on %d nodes\n", highest + 1, num_online_nodes());
0082 }
0083 
0084 static __init void intr_clear_all(nasid_t nasid)
0085 {
0086     int i;
0087 
0088     REMOTE_HUB_S(nasid, PI_INT_MASK0_A, 0);
0089     REMOTE_HUB_S(nasid, PI_INT_MASK0_B, 0);
0090     REMOTE_HUB_S(nasid, PI_INT_MASK1_A, 0);
0091     REMOTE_HUB_S(nasid, PI_INT_MASK1_B, 0);
0092 
0093     for (i = 0; i < 128; i++)
0094         REMOTE_HUB_CLR_INTR(nasid, i);
0095 }
0096 
0097 static void ip27_send_ipi_single(int destid, unsigned int action)
0098 {
0099     int irq;
0100 
0101     switch (action) {
0102     case SMP_RESCHEDULE_YOURSELF:
0103         irq = CPU_RESCHED_A_IRQ;
0104         break;
0105     case SMP_CALL_FUNCTION:
0106         irq = CPU_CALL_A_IRQ;
0107         break;
0108     default:
0109         panic("sendintr");
0110     }
0111 
0112     irq += cputoslice(destid);
0113 
0114     /*
0115      * Set the interrupt bit associated with the CPU we want to
0116      * send the interrupt to.
0117      */
0118     REMOTE_HUB_SEND_INTR(cpu_to_node(destid), irq);
0119 }
0120 
0121 static void ip27_send_ipi_mask(const struct cpumask *mask, unsigned int action)
0122 {
0123     unsigned int i;
0124 
0125     for_each_cpu(i, mask)
0126         ip27_send_ipi_single(i, action);
0127 }
0128 
0129 static void ip27_init_cpu(void)
0130 {
0131     per_cpu_init();
0132 }
0133 
0134 static void ip27_smp_finish(void)
0135 {
0136     hub_rt_clock_event_init();
0137     local_irq_enable();
0138 }
0139 
0140 /*
0141  * Launch a slave into smp_bootstrap().  It doesn't take an argument, and we
0142  * set sp to the kernel stack of the newly created idle process, gp to the proc
0143  * struct so that current_thread_info() will work.
0144  */
0145 static int ip27_boot_secondary(int cpu, struct task_struct *idle)
0146 {
0147     unsigned long gp = (unsigned long)task_thread_info(idle);
0148     unsigned long sp = __KSTK_TOS(idle);
0149 
0150     LAUNCH_SLAVE(cputonasid(cpu), cputoslice(cpu),
0151         (launch_proc_t)MAPPED_KERN_RW_TO_K0(smp_bootstrap),
0152         0, (void *) sp, (void *) gp);
0153     return 0;
0154 }
0155 
0156 static void __init ip27_smp_setup(void)
0157 {
0158     nasid_t nasid;
0159 
0160     for_each_online_node(nasid) {
0161         if (nasid == 0)
0162             continue;
0163         intr_clear_all(nasid);
0164     }
0165 
0166     replicate_kernel_text();
0167 
0168     /*
0169      * PROM sets up system, that boot cpu is always first CPU on nasid 0
0170      */
0171     cputonasid(0) = 0;
0172     cputoslice(0) = LOCAL_HUB_L(PI_CPU_NUM);
0173 }
0174 
0175 static void __init ip27_prepare_cpus(unsigned int max_cpus)
0176 {
0177     /* We already did everything necessary earlier */
0178 }
0179 
0180 const struct plat_smp_ops ip27_smp_ops = {
0181     .send_ipi_single    = ip27_send_ipi_single,
0182     .send_ipi_mask      = ip27_send_ipi_mask,
0183     .init_secondary     = ip27_init_cpu,
0184     .smp_finish     = ip27_smp_finish,
0185     .boot_secondary     = ip27_boot_secondary,
0186     .smp_setup      = ip27_smp_setup,
0187     .prepare_cpus       = ip27_prepare_cpus,
0188     .prepare_boot_cpu   = ip27_init_cpu,
0189 };