patch-2.2.14 linux/arch/ppc/kernel/smp.c
Next file: linux/arch/ppc/mm/init.c
Previous file: linux/arch/ppc/kernel/sleep.S
Back to the patch index
Back to the overall index
- Lines: 310
- Date:
Tue Jan 4 10:12:12 2000
- Orig file:
v2.2.13/linux/arch/ppc/kernel/smp.c
- Orig date:
Tue Oct 19 17:10:36 1999
diff -u --recursive --new-file v2.2.13/linux/arch/ppc/kernel/smp.c linux/arch/ppc/kernel/smp.c
@@ -34,8 +34,11 @@
#include <asm/init.h>
#include <asm/io.h>
#include <asm/prom.h>
+#include <asm/gemini.h>
#include "time.h"
+#include "open_pic.h"
+
int first_cpu_booted = 0;
int smp_threads_ready = 0;
volatile int smp_commenced = 0;
@@ -109,34 +112,8 @@
}
}
-/*
- * Dirty hack to get smp message passing working.
- *
- * As it is now, if we're sending two message at the same time
- * we have race conditions. The PowerSurge doesn't easily
- * allow us to send IPI messages so we put the messages in
- * smp_message[].
- *
- * This is because don't have several IPI's on the PowerSurge even though
- * we do on the chrp. It would be nice to use the actual IPI's on the chrp
- * rather than this but having two methods of doing IPI isn't a good idea
- * right now.
- * -- Cort
- */
-int smp_message[NR_CPUS];
-void smp_message_recv(void)
+void smp_message_recv(int msg)
{
- int msg = smp_message[smp_processor_id()];
-
- if ( _machine == _MACH_Pmac )
- {
- /* clear interrupt */
- out_be32(PSURGE_INTR, ~0);
- }
-
- /* make sure msg is for us */
- if ( msg == -1 ) return;
-
ipi_count++;
switch( msg )
@@ -145,25 +122,72 @@
__cli();
while (1) ;
break;
- case MSG_RESCHEDULE:
+ case MSG_RESCHEDULE:
current->need_resched = 1;
break;
- case 0xf0f0: /* syncing time bases - just return */
+ case MSG_INVALIDATE_TLB:
+ _tlbia();
+ case 0xf0f0: /* pmac syncing time bases - just return */
break;
default:
printk("SMP %d: smp_message_recv(): unknown msg %d\n",
smp_processor_id(), msg);
break;
}
+}
+
+/*
+ * As it is now, if we're sending two message at the same time
+ * we have race conditions on Pmac. The PowerSurge doesn't easily
+ * allow us to send IPI messages so we put the messages in
+ * smp_message[].
+ *
+ * This is because don't have several IPI's on the PowerSurge even though
+ * we do on the chrp. It would be nice to use actual IPI's such as with openpic
+ * rather than this.
+ * -- Cort
+ */
+int pmac_smp_message[NR_CPUS];
+void pmac_smp_message_recv(void)
+{
+ int msg = pmac_smp_message[smp_processor_id()];
+
+ /* clear interrupt */
+ out_be32(PSURGE_INTR, ~0);
+
+ /* make sure msg is for us */
+ if ( msg == -1 ) return;
+
+ smp_message_recv(msg);
+
/* reset message */
- smp_message[smp_processor_id()] = -1;
+ pmac_smp_message[smp_processor_id()] = -1;
+}
+
+
+/*
+ * 750's don't broadcast tlb invalidates so
+ * we have to emulate that behavior.
+ * -- Cort
+ */
+void smp_send_tlb_invalidate(int cpu)
+{
+ if ( (_get_PVR()>>16) == 8 )
+ smp_message_pass(MSG_ALL_BUT_SELF, MSG_INVALIDATE_TLB, 0, 0);
}
void smp_send_reschedule(int cpu)
{
- /* This is only used if `cpu' is running an idle task,
- so it will reschedule itself anyway... */
- /*smp_message_pass(cpu, MSG_RESCHEDULE, 0, 0);*/
+ /*
+ * This is only used if `cpu' is running an idle task,
+ * so it will reschedule itself anyway...
+ *
+ * This isn't the case anymore since the other CPU could be
+ * sleeping and won't reschedule until the next interrupt (such
+ * as the timer).
+ * -- Cort
+ */
+ smp_message_pass(cpu, MSG_RESCHEDULE, 0, 0);
}
void smp_send_stop(void)
@@ -171,38 +195,39 @@
smp_message_pass(MSG_ALL_BUT_SELF, MSG_STOP_CPU, 0, 0);
}
-spinlock_t mesg_pass_lock = SPIN_LOCK_UNLOCKED;
void smp_message_pass(int target, int msg, unsigned long data, int wait)
{
int i;
- if ( !(_machine & (_MACH_Pmac|_MACH_chrp|_MACH_prep)) )
+
+ if ( !(_machine & (_MACH_Pmac|_MACH_chrp|_MACH_prep|_MACH_gemini)) )
return;
- spin_lock(&mesg_pass_lock);
-
- /*
- * We assume here that the msg is not -1. If it is,
- * the recipient won't know the message was destined
- * for it. -- Cort
- */
-
- switch( target )
- {
- case MSG_ALL:
- smp_message[smp_processor_id()] = msg;
- /* fall through */
- case MSG_ALL_BUT_SELF:
- for ( i = 0 ; i < smp_num_cpus ; i++ )
- if ( i != smp_processor_id () )
- smp_message[i] = msg;
- break;
- default:
- smp_message[target] = msg;
- break;
- }
-
switch (_machine) {
case _MACH_Pmac:
+ /*
+ * IPI's on the Pmac are a hack but without reasonable
+ * IPI hardware SMP on Pmac is a hack.
+ *
+ * We assume here that the msg is not -1. If it is,
+ * the recipient won't know the message was destined
+ * for it. -- Cort
+ */
+ for ( i = 0; i <= smp_num_cpus ; i++ )
+ pmac_smp_message[i] = -1;
+ switch( target )
+ {
+ case MSG_ALL:
+ pmac_smp_message[smp_processor_id()] = msg;
+ /* fall through */
+ case MSG_ALL_BUT_SELF:
+ for ( i = 0 ; i < smp_num_cpus ; i++ )
+ if ( i != smp_processor_id () )
+ pmac_smp_message[i] = msg;
+ break;
+ default:
+ pmac_smp_message[target] = msg;
+ break;
+ }
/* interrupt secondary processor */
out_be32(PSURGE_INTR, ~0);
out_be32(PSURGE_INTR, 0);
@@ -213,35 +238,27 @@
/* interrupt primary */
/**(volatile unsigned long *)(0xf3019000);*/
break;
-
case _MACH_chrp:
case _MACH_prep:
- /*
- * There has to be some way of doing this better -
- * perhaps a sent-to-all or send-to-all-but-self
- * in the openpic. This gets us going for now, though.
- * -- Cort
- */
+ case _MACH_gemini:
+ /* make sure we're sending something that translates to an IPI */
+ if ( msg > 0x3 )
+ break;
switch ( target )
{
case MSG_ALL:
- for ( i = 0 ; i < smp_num_cpus ; i++ )
- openpic_cause_IPI(i, 0, 0xffffffff );
+ openpic_cause_IPI(smp_processor_id(), msg, 0xffffffff);
break;
case MSG_ALL_BUT_SELF:
- for ( i = 0 ; i < smp_num_cpus ; i++ )
- if ( i != smp_processor_id () )
- openpic_cause_IPI(i, 0,
- 0xffffffff & ~(1 << smp_processor_id()));
+ openpic_cause_IPI(smp_processor_id(), msg,
+ 0xffffffff & ~(1 << smp_processor_id()));
break;
default:
- openpic_cause_IPI(target, 0, 1U << target);
+ openpic_cause_IPI(smp_processor_id(), msg, 1<<target);
break;
}
break;
}
-
- spin_unlock(&mesg_pass_lock);
}
void __init smp_boot_cpus(void)
@@ -296,6 +313,10 @@
cpu_nr = 2;
break;
}
+ case _MACH_gemini:
+ cpu_nr = (readb(GEMINI_CPUSTAT) & GEMINI_CPU_COUNT_MASK)>>2;
+ cpu_nr = (cpu_nr == 0) ? 4 : cpu_nr;
+ break;
default:
printk("SMP not supported on this machine.\n");
return;
@@ -338,25 +359,16 @@
case _MACH_chrp:
*(unsigned long *)KERNELBASE = i;
asm volatile("dcbf 0,%0"::"r"(KERNELBASE):"memory");
-#if 0
- device = find_type_devices("cpu");
- /* assume cpu device list is in order, find the ith cpu */
- for ( a = i; device && a; device = device->next, a-- )
- ;
- if ( !device )
- break;
- printk( "Starting %s (%lu): ", device->full_name,
- *(ulong *)get_property(device, "reg", NULL) );
- call_rtas( "start-cpu", 3, 1, NULL,
- *(ulong *)get_property(device, "reg", NULL),
- __pa(__secondary_start_chrp), i);
-#endif
break;
case _MACH_prep:
*MotSave_SmpIar = (unsigned long)__secondary_start_psurge - KERNELBASE;
*MotSave_CpusState[1] = CPU_GOOD;
printk("CPU1 reset, waiting\n");
break;
+ case _MACH_gemini:
+ openpic_init_processor( 1<<i );
+ openpic_init_processor( 0 );
+ break;
}
/*
@@ -379,6 +391,8 @@
}
}
+ if ( _machine & (_MACH_gemini|_MACH_chrp|_MACH_prep) )
+ do_openpic_setup_cpu();
if ( _machine == _MACH_Pmac )
{
/* reset the entry point so if we get another intr we won't
@@ -420,6 +434,13 @@
#endif
init_idle();
cpu_callin_map[current->processor] = 1;
+ /*
+ * Each processor has to do this and this is the best
+ * place to stick it for now.
+ * -- Cort
+ */
+ if ( _machine & (_MACH_gemini|_MACH_chrp|_MACH_prep) )
+ do_openpic_setup_cpu();
while(!smp_commenced)
barrier();
__sti();
@@ -437,8 +458,8 @@
void __init smp_store_cpu_info(int id)
{
struct cpuinfo_PPC *c = &cpu_data[id];
-
/* assume bogomips are same for everything */
c->loops_per_sec = loops_per_sec;
c->pvr = _get_PVR();
}
+
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)