|
@@ -32,6 +32,7 @@ static inline unsigned long sun4d_swap(volatile unsigned long *ptr, unsigned lon
|
|
|
return val;
|
|
|
}
|
|
|
|
|
|
+static void smp4d_ipi_init(void);
|
|
|
static void smp_setup_percpu_timer(void);
|
|
|
|
|
|
static unsigned char cpu_leds[32];
|
|
@@ -118,6 +119,7 @@ void __cpuinit smp4d_callin(void)
|
|
|
*/
|
|
|
void __init smp4d_boot_cpus(void)
|
|
|
{
|
|
|
+ smp4d_ipi_init();
|
|
|
if (boot_cpu_id)
|
|
|
current_set[0] = NULL;
|
|
|
smp_setup_percpu_timer();
|
|
@@ -189,6 +191,80 @@ void __init smp4d_smp_done(void)
|
|
|
sun4d_distribute_irqs();
|
|
|
}
|
|
|
|
|
|
+/* Memory structure giving interrupt handler information about IPI generated */
|
|
|
+struct sun4d_ipi_work {
|
|
|
+ int single;
|
|
|
+ int msk;
|
|
|
+ int resched;
|
|
|
+};
|
|
|
+
|
|
|
+static DEFINE_PER_CPU_SHARED_ALIGNED(struct sun4d_ipi_work, sun4d_ipi_work);
|
|
|
+
|
|
|
+/* Initialize IPIs on the SUN4D SMP machine */
|
|
|
+static void __init smp4d_ipi_init(void)
|
|
|
+{
|
|
|
+ int cpu;
|
|
|
+ struct sun4d_ipi_work *work;
|
|
|
+
|
|
|
+ printk(KERN_INFO "smp4d: setup IPI at IRQ %d\n", SUN4D_IPI_IRQ);
|
|
|
+
|
|
|
+ for_each_possible_cpu(cpu) {
|
|
|
+ work = &per_cpu(sun4d_ipi_work, cpu);
|
|
|
+ work->single = work->msk = work->resched = 0;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void sun4d_ipi_interrupt(void)
|
|
|
+{
|
|
|
+ struct sun4d_ipi_work *work = &__get_cpu_var(sun4d_ipi_work);
|
|
|
+
|
|
|
+ if (work->single) {
|
|
|
+ work->single = 0;
|
|
|
+ smp_call_function_single_interrupt();
|
|
|
+ }
|
|
|
+ if (work->msk) {
|
|
|
+ work->msk = 0;
|
|
|
+ smp_call_function_interrupt();
|
|
|
+ }
|
|
|
+ if (work->resched) {
|
|
|
+ work->resched = 0;
|
|
|
+ smp_resched_interrupt();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static void smp4d_ipi_single(int cpu)
|
|
|
+{
|
|
|
+ struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu);
|
|
|
+
|
|
|
+ /* Mark work */
|
|
|
+ work->single = 1;
|
|
|
+
|
|
|
+ /* Generate IRQ on the CPU */
|
|
|
+ sun4d_send_ipi(cpu, SUN4D_IPI_IRQ);
|
|
|
+}
|
|
|
+
|
|
|
+static void smp4d_ipi_mask_one(int cpu)
|
|
|
+{
|
|
|
+ struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu);
|
|
|
+
|
|
|
+ /* Mark work */
|
|
|
+ work->msk = 1;
|
|
|
+
|
|
|
+ /* Generate IRQ on the CPU */
|
|
|
+ sun4d_send_ipi(cpu, SUN4D_IPI_IRQ);
|
|
|
+}
|
|
|
+
|
|
|
+static void smp4d_ipi_resched(int cpu)
|
|
|
+{
|
|
|
+ struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu);
|
|
|
+
|
|
|
+ /* Mark work */
|
|
|
+ work->resched = 1;
|
|
|
+
|
|
|
+ /* Generate IRQ on the CPU (any IRQ will cause resched) */
|
|
|
+ sun4d_send_ipi(cpu, SUN4D_IPI_IRQ);
|
|
|
+}
|
|
|
+
|
|
|
static struct smp_funcall {
|
|
|
smpfunc_t func;
|
|
|
unsigned long arg1;
|
|
@@ -354,6 +430,9 @@ void __init sun4d_init_smp(void)
|
|
|
BTFIXUPSET_BLACKBOX(load_current, smp4d_blackbox_current);
|
|
|
BTFIXUPSET_CALL(smp_cross_call, smp4d_cross_call, BTFIXUPCALL_NORM);
|
|
|
BTFIXUPSET_CALL(__hard_smp_processor_id, __smp4d_processor_id, BTFIXUPCALL_NORM);
|
|
|
+ BTFIXUPSET_CALL(smp_ipi_resched, smp4d_ipi_resched, BTFIXUPCALL_NORM);
|
|
|
+ BTFIXUPSET_CALL(smp_ipi_single, smp4d_ipi_single, BTFIXUPCALL_NORM);
|
|
|
+ BTFIXUPSET_CALL(smp_ipi_mask_one, smp4d_ipi_mask_one, BTFIXUPCALL_NORM);
|
|
|
|
|
|
for (i = 0; i < NR_CPUS; i++) {
|
|
|
ccall_info.processors_in[i] = 1;
|