#include <linux/module.h>
#include <linux/sched.h>
#include <linux/smp.h>
-#include <linux/smp_lock.h>
#include <linux/interrupt.h>
-#include <linux/kernel_stat.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/spinlock.h>
#include <asm/io.h>
#include <asm/prom.h>
#include <asm/smp.h>
-#include <asm/naca.h>
#include <asm/paca.h>
#include <asm/time.h>
-#include <asm/ppcdebug.h>
#include <asm/machdep.h>
#include <asm/xics.h>
#include <asm/cputable.h>
#define DBG(fmt...)
#endif
-extern void pseries_secondary_smp_init(unsigned long);
+extern void pSeries_secondary_smp_init(unsigned long);
/* Get state of physical CPU.
* Return codes:
#ifdef CONFIG_HOTPLUG_CPU
-int __cpu_disable(void)
+int pSeries_cpu_disable(void)
{
- /* FIXME: go put this in a header somewhere */
- extern void xics_migrate_irqs_away(void);
-
systemcfg->processorCount--;
/*fix boot_cpuid here*/
return 0;
}
-void __cpu_die(unsigned int cpu)
+void pSeries_cpu_die(unsigned int cpu)
{
int tries;
int cpu_status;
cpu_status = query_cpu_stopped(pcpu);
if (cpu_status == 0 || cpu_status == -1)
break;
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ/5);
+ msleep(200);
}
if (cpu_status != 0) {
printk("Querying DEAD? cpu %i (%i) shows %i\n",
{
int status;
unsigned long start_here = __pa((u32)*((unsigned long *)
- pseries_secondary_smp_init));
+ pSeries_secondary_smp_init));
unsigned int pcpu;
/* At boot time the cpus are already spinning in hold
}
}
-extern void xics_request_IPIs(void);
-
static int __init smp_xics_probe(void)
{
xics_request_IPIs();
{
if (cpu != boot_cpuid)
xics_setup_cpu();
+
+ if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR)
+ vpa_init(cpu);
+
+ /*
+ * Put the calling processor into the GIQ. This is really only
+ * necessary from a secondary thread as the OF start-cpu interface
+ * performs this function for us on primary threads.
+ */
+ rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE,
+ (1UL << interrupt_server_size) - 1 - default_distrib_server, 1);
}
-static spinlock_t timebase_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(timebase_lock);
static unsigned long timebase = 0;
static void __devinit pSeries_give_timebase(void)
spin_unlock(&timebase_lock);
}
-static void __devinit pSeries_late_setup_cpu(int cpu)
-{
- extern unsigned int default_distrib_server;
-
- if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {
- vpa_init(cpu);
- }
-
-#ifdef CONFIG_IRQ_ALL_CPUS
- /* Put the calling processor into the GIQ. This is really only
- * necessary from a secondary thread as the OF start-cpu interface
- * performs this function for us on primary threads.
- */
- /* TODO: 9005 is #defined in rtas-proc.c -- move to a header */
- rtas_set_indicator(9005, default_distrib_server, 1);
-#endif
-}
-
-
-void __devinit smp_pSeries_kick_cpu(int nr)
+static void __devinit smp_pSeries_kick_cpu(int nr)
{
BUG_ON(nr < 0 || nr >= NR_CPUS);
.probe = smp_mpic_probe,
.kick_cpu = smp_pSeries_kick_cpu,
.setup_cpu = smp_mpic_setup_cpu,
- .late_setup_cpu = pSeries_late_setup_cpu,
};
static struct smp_ops_t pSeries_xics_smp_ops = {
.probe = smp_xics_probe,
.kick_cpu = smp_pSeries_kick_cpu,
.setup_cpu = smp_xics_setup_cpu,
- .late_setup_cpu = pSeries_late_setup_cpu,
};
/* This is called very early */
DBG(" -> smp_init_pSeries()\n");
- if (naca->interrupt_controller == IC_OPEN_PIC)
+ if (ppc64_interrupt_controller == IC_OPEN_PIC)
smp_ops = &pSeries_mpic_smp_ops;
else
smp_ops = &pSeries_xics_smp_ops;
+#ifdef CONFIG_HOTPLUG_CPU
+ smp_ops->cpu_disable = pSeries_cpu_disable;
+ smp_ops->cpu_die = pSeries_cpu_die;
+#endif
+
/* Start secondary threads on SMT systems; primary threads
* are already in the running state.
*/
rtas_call(rtas_token("start-cpu"), 3, 1, &ret,
get_hard_smp_processor_id(i),
__pa((u32)*((unsigned long *)
- pseries_secondary_smp_init)),
+ pSeries_secondary_smp_init)),
i);
}
}
- if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR)
- vpa_init(boot_cpuid);
-
/* Non-lpar has additional take/give timebase */
if (rtas_token("freeze-time-base") != RTAS_UNKNOWN_SERVICE) {
smp_ops->give_timebase = pSeries_give_timebase;