#undef DEBUG
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/sysdev.h>
#include <linux/cpu.h>
#include <linux/notifier.h>
+#include <linux/topology.h>
#include <asm/ptrace.h>
#include <asm/atomic.h>
#include <asm/cputable.h>
#include <asm/system.h>
#include <asm/mpic.h>
-#include <asm/systemcfg.h>
+#include <asm/vdso_datapage.h>
#ifdef CONFIG_PPC64
#include <asm/paca.h>
#endif
-int smp_hw_index[NR_CPUS];
-struct thread_info *secondary_ti;
-
#ifdef DEBUG
+#include <asm/udbg.h>
#define DBG(fmt...) udbg_printf(fmt)
#else
#define DBG(fmt...)
#endif
+int smp_hw_index[NR_CPUS];
+struct thread_info *secondary_ti;
+
cpumask_t cpu_possible_map = CPU_MASK_NONE;
cpumask_t cpu_online_map = CPU_MASK_NONE;
cpumask_t cpu_sibling_map[NR_CPUS] = { [0 ... NR_CPUS-1] = CPU_MASK_NONE };
int smt_enabled_at_boot = 1;
+static void (*crash_ipi_function_ptr)(struct pt_regs *) = NULL;
+
#ifdef CONFIG_MPIC
int __init smp_mpic_probe(void)
{
/* XXX Do we have to do this? */
set_need_resched();
break;
-#ifdef CONFIG_DEBUGGER
case PPC_MSG_DEBUGGER_BREAK:
+ if (crash_ipi_function_ptr) {
+ crash_ipi_function_ptr(regs);
+ break;
+ }
+#ifdef CONFIG_DEBUGGER
debugger_ipi(regs);
break;
-#endif
+#endif /* CONFIG_DEBUGGER */
+ /* FALLTHROUGH */
default:
printk("SMP %d: smp_message_recv(): unknown msg %d\n",
smp_processor_id(), msg);
void smp_send_reschedule(int cpu)
{
- smp_ops->message_pass(cpu, PPC_MSG_RESCHEDULE);
+ if (likely(smp_ops))
+ smp_ops->message_pass(cpu, PPC_MSG_RESCHEDULE);
}
#ifdef CONFIG_DEBUGGER
void smp_send_debugger_break(int cpu)
{
- smp_ops->message_pass(cpu, PPC_MSG_DEBUGGER_BREAK);
+ if (likely(smp_ops))
+ smp_ops->message_pass(cpu, PPC_MSG_DEBUGGER_BREAK);
+}
+#endif
+
+#ifdef CONFIG_KEXEC
+void crash_send_ipi(void (*crash_ipi_callback)(struct pt_regs *))
+{
+ crash_ipi_function_ptr = crash_ipi_callback;
+ if (crash_ipi_callback && smp_ops) {
+ mb();
+ smp_ops->message_pass(MSG_ALL_BUT_SELF, PPC_MSG_DEBUGGER_BREAK);
+ }
}
#endif
/* Can deadlock when called with interrupts disabled */
WARN_ON(irqs_disabled());
+ if (unlikely(smp_ops == NULL))
+ return -1;
+
data.func = func;
data.info = info;
atomic_set(&data.started, 0);
#ifdef CONFIG_PPC64
paca[cpu].__current = p;
#endif
- current_set[cpu] = p->thread_info;
- p->thread_info->cpu = cpu;
+ current_set[cpu] = task_thread_info(p);
+ task_thread_info(p)->cpu = cpu;
}
void __init smp_prepare_cpus(unsigned int max_cpus)
smp_store_cpu_info(boot_cpuid);
cpu_callin_map[boot_cpuid] = 1;
- max_cpus = smp_ops->probe();
+ if (smp_ops)
+ max_cpus = smp_ops->probe();
+ else
+ max_cpus = 1;
smp_space_timers(max_cpus);
- for_each_cpu(cpu)
+ for_each_possible_cpu(cpu)
if (cpu != boot_cpuid)
smp_create_idle(cpu);
}
#ifdef CONFIG_PPC64
paca[boot_cpuid].__current = current;
#endif
- current_set[boot_cpuid] = current->thread_info;
+ current_set[boot_cpuid] = task_thread_info(current);
}
#ifdef CONFIG_HOTPLUG_CPU
cpu_clear(cpu, cpu_online_map);
#ifdef CONFIG_PPC64
- _systemcfg->processorCount--;
+ vdso_data->processorCount--;
fixup_irqs(cpu_online_map);
#endif
return 0;
static int __devinit cpu_enable(unsigned int cpu)
{
- if (smp_ops->cpu_enable)
+ if (smp_ops && smp_ops->cpu_enable)
return smp_ops->cpu_enable(cpu);
return -ENOSYS;
if (!cpu_enable(cpu))
return 0;
- if (smp_ops->cpu_bootable && !smp_ops->cpu_bootable(cpu))
+ if (smp_ops == NULL ||
+ (smp_ops->cpu_bootable && !smp_ops->cpu_bootable(cpu)))
return -EINVAL;
-#ifdef CONFIG_PPC64
- paca[cpu].default_decr = tb_ticks_per_jiffy;
-#endif
-
/* Make sure callin-map entry is 0 (can be leftover a CPU
* hotplug
*/
* -- Cort
*/
if (system_state < SYSTEM_RUNNING)
- for (c = 5000; c && !cpu_callin_map[cpu]; c--)
+ for (c = 50000; c && !cpu_callin_map[cpu]; c--)
udelay(100);
#ifdef CONFIG_HOTPLUG_CPU
else
smp_store_cpu_info(cpu);
set_dec(tb_ticks_per_jiffy);
+ preempt_disable();
cpu_callin_map[cpu] = 1;
smp_ops->setup_cpu(cpu);
if (smp_ops->take_timebase)
smp_ops->take_timebase();
+ if (system_state > SYSTEM_BOOTING)
+ snapshot_timebase();
+
spin_lock(&call_lock);
cpu_set(cpu, cpu_online_map);
spin_unlock(&call_lock);
old_mask = current->cpus_allowed;
set_cpus_allowed(current, cpumask_of_cpu(boot_cpuid));
- smp_ops->setup_cpu(boot_cpuid);
+ if (smp_ops)
+ smp_ops->setup_cpu(boot_cpuid);
set_cpus_allowed(current, old_mask);
+
+ snapshot_timebases();
+
+ dump_numa_cpu_topology();
}
#ifdef CONFIG_HOTPLUG_CPU