#include <linux/sched.h>
#include <linux/cpumask.h>
#include <linux/cpu.h>
+#include <linux/err.h>
#include <asm/atomic.h>
#include <asm/cpu.h>
#include <asm/system.h>
#include <asm/mmu_context.h>
#include <asm/smp.h>
+#include <asm/time.h>
#ifdef CONFIG_MIPS_MT_SMTC
#include <asm/mipsmtregs.h>
EXPORT_SYMBOL(phys_cpu_present_map);
EXPORT_SYMBOL(cpu_online_map);
-static void smp_tune_scheduling (void)
-{
- struct cache_desc *cd = ¤t_cpu_data.scache;
- unsigned long cachesize; /* kB */
- unsigned long cpu_khz;
-
- /*
- * Crude estimate until we actually meassure ...
- */
- cpu_khz = loops_per_jiffy * 2 * HZ / 1000;
-
- /*
- * Rough estimation for SMP scheduling, this is the number of
- * cycles it takes for a fully memory-limited process to flush
- * the SMP-local cache.
- *
- * (For a P5 this pretty much means we will choose another idle
- * CPU almost always at wakeup time (this is due to the small
- * L1 cache), on PIIs it's around 50-100 usecs, depending on
- * the cache size)
- */
- if (!cpu_khz)
- return;
-
- cachesize = cd->linesz * cd->sets * cd->ways;
-}
-
extern void __init calibrate_delay(void);
-extern ATTRIB_NORET void cpu_idle(void);
+extern void cpu_idle(void);
/*
* First C code run on the secondary CPUs after being started up by
* the master.
*/
-asmlinkage void start_secondary(void)
+asmlinkage __cpuinit void start_secondary(void)
{
unsigned int cpu;
cpu_probe();
cpu_report();
per_cpu_trap_init();
+ mips_clockevent_init();
prom_init_secondary();
/*
/*
* Run a function on all other CPUs.
+ *
+ * <mask> cpuset_t of all processors to run the function on.
* <func> The function to run. This must be fast and non-blocking.
* <info> An arbitrary pointer to pass to the function.
* <retry> If true, keep retrying until ready.
* Spin waiting for call_lock
* Deadlock Deadlock
*/
-int smp_call_function (void (*func) (void *info), void *info, int retry,
- int wait)
+int smp_call_function_mask(cpumask_t mask, void (*func) (void *info),
+ void *info, int retry, int wait)
{
struct call_data_struct data;
- int i, cpus = num_online_cpus() - 1;
int cpu = smp_processor_id();
+ int cpus;
/*
* Can die spectacularly if this CPU isn't yet marked online
*/
BUG_ON(!cpu_online(cpu));
+ cpu_clear(cpu, mask);
+ cpus = cpus_weight(mask);
if (!cpus)
return 0;
smp_mb();
/* Send a message to all other CPUs and wait for them to respond */
- for_each_online_cpu(i)
- if (i != cpu)
- core_send_ipi(i, SMP_CALL_FUNCTION);
+ core_send_ipi_mask(mask, SMP_CALL_FUNCTION);
/* Wait for response */
/* FIXME: lock-up detection, backtrace on lock-up */
return 0;
}
+int smp_call_function(void (*func) (void *info), void *info, int retry,
+ int wait)
+{
+ return smp_call_function_mask(cpu_online_map, func, info, retry, wait);
+}
void smp_call_function_interrupt(void)
{
}
}
+int smp_call_function_single(int cpu, void (*func) (void *info), void *info,
+ int retry, int wait)
+{
+ int ret, me;
+
+ /*
+ * Can die spectacularly if this CPU isn't yet marked online
+ */
+ if (!cpu_online(cpu))
+ return 0;
+
+ me = get_cpu();
+ BUG_ON(!cpu_online(me));
+
+ if (cpu == me) {
+ local_irq_disable();
+ func(info);
+ local_irq_enable();
+ put_cpu();
+ return 0;
+ }
+
+ ret = smp_call_function_mask(cpumask_of_cpu(cpu), func, info, retry,
+ wait);
+
+ put_cpu();
+ return 0;
+}
+
static void stop_this_cpu(void *dummy)
{
/*
{
init_new_context(current, &init_mm);
current_thread_info()->cpu = 0;
- smp_tune_scheduling();
plat_prepare_cpus(max_cpus);
#ifndef CONFIG_HOTPLUG_CPU
cpu_present_map = cpu_possible_map;