[parisc-linux-cvs] smp.c patch

Grant Grundler grundler@cup.hp.com
Tue, 13 Feb 2001 14:23:15 -0800 (PST)


Fix the problem with IPI not working.
bits in cpu_data[].pending_ipi weren't getting set correctly.

Other stuff is just debug output cleanup.

ipi_interrupt() output is wrong and I don't understand why.
The "ipiIRQ" output line "pending_ipi" doesn't match the
behaviour later in the switch() statement.

grant

Index: arch/parisc/kernel/smp.c
===================================================================
RCS file: /home/cvs/parisc/linux/arch/parisc/kernel/smp.c,v
retrieving revision 1.6
diff -u -p -r1.6 smp.c
--- smp.c	2001/02/08 12:49:42	1.6
+++ smp.c	2001/02/13 22:02:04
@@ -72,7 +72,6 @@ static volatile unsigned long cpu_callin
 int smp_num_cpus = 1;
 int smp_threads_ready = 0;
 static int max_cpus = -1;			     /* Command line */
-static unsigned long ipi_op[NR_CPUS];
 struct smp_call_struct {
 	void (*func) (void *info);
 	void *info;
@@ -83,7 +82,8 @@ struct smp_call_struct {
 static volatile struct smp_call_struct *smp_call_function_data;
 
 enum ipi_message_type {
-	IPI_RESCHEDULE,
+	IPI_NOP=0,
+	IPI_RESCHEDULE=1,
 	IPI_CALL_FUNC,
 	IPI_CPU_START,
 	IPI_CPU_STOP,
@@ -147,37 +147,38 @@ void
 ipi_interrupt(int irq, void *dev_id, struct pt_regs *regs) 
 {
 	int this_cpu = smp_processor_id();
-	unsigned long *pending_ipis = &ipi_op[this_cpu];
+	unsigned long *ipis = &(cpu_data[this_cpu].pending_ipi);
 	unsigned long ops;
 
 	/* Count this now; we may make a call that never returns. */
 	cpu_data[this_cpu].ipi_count++;
 
 	mb();	/* Order interrupt and bit testing. */
-	while ((ops = xchg(pending_ipis, 0)) != 0) {
+printk("ipiIRQ() CPU%d  %lx\n", this_cpu, *ipis);
+mdelay(200);
+
+	while ((ops = xchg(ipis, 0)) != 0) {
 	  mb();	/* Order bit clearing and data access. */
 	  do {
-		unsigned long which;
-
-printk("ipi_interrupt(%d,...) on %d ops = 0x%lx ", irq, this_cpu, ops);
+		unsigned long which = ffz(~ops);
 
-		which = ffz(~ops);
-		ops &= ~(1 << which);
-
-printk("(which = %ld)\n", which);
-		
 		switch (which) {
 		case IPI_RESCHEDULE:
 #if (kDEBUG>=100)
-			printk("CPU:%d got reschedule interrupt\n",this_cpu);
+			printk("CPU%d IPI_RESCHEDULE\n",this_cpu);
 #endif /* kDEBUG */
+			ops &= ~(1 << IPI_RESCHEDULE);
 			/* 
-			 * Reschedule callback.  Everything to be done is done by the 
-			 * interrupt return path.  
+			 * Reschedule callback.  Everything to be done is
+			 * done by the interrupt return path.  
 			 */
 			break;
 			
 		case IPI_CALL_FUNC: 
+#if (kDEBUG>=100)
+			printk("CPU%d IPI_CALL_FUNC\n",this_cpu);
+#endif /* kDEBUG */
+			ops &= ~(1 << IPI_CALL_FUNC);
 			{
 				volatile struct smp_call_struct *data;
 				void (*func)(void *info);
@@ -203,12 +204,20 @@ printk("(which = %ld)\n", which);
 			break;
 
 		case IPI_CPU_START:
+#if (kDEBUG>=100)
+			printk("CPU%d IPI_CPU_START\n",this_cpu);
+#endif /* kDEBUG */
+			ops &= ~(1 << IPI_CPU_START);
 #ifdef ENTRY_SYS_CPUS
 			cpu_data[this_cpu].state = STATE_RUNNING;
 #endif
 			break;
 
 		case IPI_CPU_STOP:
+#if (kDEBUG>=100)
+			printk("CPU%d IPI_CPU_STOP\n",this_cpu);
+#endif /* kDEBUG */
+			ops &= ~(1 << IPI_CPU_STOP);
 #ifdef ENTRY_SYS_CPUS
 #else
 			halt_processor();
@@ -217,12 +226,14 @@ printk("(which = %ld)\n", which);
 
 		case IPI_CPU_TEST:
 #if (kDEBUG>=100)
-			printk("CPU:%d is alive\n",this_cpu);
+			printk("CPU%d is alive!\n",this_cpu);
 #endif /* kDEBUG */
+			ops &= ~(1 << IPI_CPU_TEST);
 			break;
 
 		default:
-			printk(KERN_CRIT "Unknown IPI num on CPU %d: %lu\n", this_cpu, which);
+			printk(KERN_CRIT "Unknown IPI num on CPU%d: %lu\n", this_cpu, which);
+			ops &= ~(1 << which);
 			return;
 		} /* Switch */
 	  } while (ops);
@@ -236,25 +247,28 @@ printk("(which = %ld)\n", which);
 static inline void
 ipi_send(int cpu, enum ipi_message_type op)
 {
-	set_bit(1<< op, &(cpu_data[cpu].pending_ipi));
+#if 0
+	set_bit(op, &(cpu_data[cpu].pending_ipi));
+#else
+	cpu_data[cpu].pending_ipi |= 1 << op;
+#endif
 
-	/*
-	** Just in case it's directed at ourselves, we want to make
-	** sure the interrupt doesn't get delivered until we are out
-	** of real mode again. I think it's cheaper to disable IRQ's
-	** briefly than test for it.
-	*/
-	local_irq_disable();
+#if 0
+printk("ipi_send() CPU%d sending %d/%d to CPU%d (%lx)\n", smp_processor_id(),
+			IRQ_OFFSET(IPI_IRQ), op, cpu, cpu_data[cpu].hpa);
+#endif
+
 	gsc_writel(IRQ_OFFSET(IPI_IRQ), cpu_data[cpu].hpa);
-	local_irq_enable();
 }
 
 
 static inline void
 send_IPI_single(int dest_cpu, enum ipi_message_type op)
 {
-	if (dest_cpu == NO_PROC_ID) 
+	if (dest_cpu == NO_PROC_ID) {
+		BUG();
         	return;
+	}
 
 	ipi_send(dest_cpu, op);
 }
@@ -483,27 +497,15 @@ void __init smp_callin(unsigned long pdc
 	int slave_id = cpu_now_booting;
 
 	smp_cpu_init(slave_id);
-
+	current->active_mm = &init_mm;
 
-printk("SMP: CPU:%d  CR15 %lx CR22 %lx CR23 %lx\n", slave_id,
-		mfctl(15), mfctl(22), mfctl(23));
+	local_irq_enable();  /* Interrupts have been off until now */
 
 	/* Slave's wait here until Big Poppa daddy say "jump" */
 	mb();	/* PARANOID */
 	while (!smp_commenced) ;
 	mb();	/* PARANOID */
 
-	local_irq_enable();  /* Interrupts have been off until now */
-
-printk("SMP: CPU:%d  CR15 %lx CR22 %lx CR23 %lx\n", slave_id,
-		mfctl(15), mfctl(22), mfctl(23));
-
-mdelay(300);
-/* spin_lock (&smp_lock); */
-
-printk("SMP: CPU:%d calling cpu_idle()\n", slave_id);
-mdelay(300);
-/* spin_unlock (&smp_lock); */
 	cpu_idle();      /* Wait for timer to schedule some work */
 	/* NOTREACHED */
 panic("smp_callin() AAAAaaaaahhhh....\n");
@@ -571,8 +573,6 @@ STATIC int smp_boot_one_cpu(int cpuid, i
 	if (!idle)
 		panic("SMP: No idle process for CPU:%d", cpuid);
 
-printk("sboc: task 0x%p for %d/%d\n", idle, cpuid, cpunum);
-
 	__cpu_number_map[cpuid] = cpunum;
 	__cpu_logical_map[cpunum] = cpuid;
 
@@ -583,9 +583,6 @@ printk("sboc: task 0x%p for %d/%d\n", id
 	idle->processor = cpunum;
 	idle->has_cpu = 1;	/* Schedule the first task manually */
 
-printk("sboc: CPU %d state 0x%lx flags 0x%lx\n",
-	cpunum, idle->state, idle->flags);
-
 	/* Let _start know what logical CPU we're booting
 	** (offset into init_tasks[],cpu_data[])
 	*/
@@ -631,6 +628,8 @@ printk("sboc: CPU %d state 0x%lx flags 0
 	return -1;
 
 alive:
+	__cpu_logical_map[cpunum] = cpuid;
+	__cpu_number_map[cpuid] = cpunum;
 	/* Remember the Slave data */
 #if (kDEBUG>=100)
 	printk("SMP: CPU:%d (num %d) came alive after %ld _us\n",
@@ -674,13 +673,13 @@ void __init smp_boot_cpus(void)
         printk("SMP: bootstrap CPU ID is %d\n",bootstrap_processor);
 	init_task.processor = 0; 
 	current->processor = 0;	/*These are set already*/
+        current->active_mm = &init_mm;
 	cpu_callin_map = 1; /* Mark Boostrap processor as present */
 
 #ifdef ENTRY_SYS_CPUS
 	cpu_data[0].state = STATE_RUNNING;
 #endif
 
-	init_idle();
 
 	/* Nothing to do when told not to.  */
 	if (max_cpus == 0) {
@@ -727,20 +726,13 @@ void __init smp_boot_cpus(void)
 }
 
 /* 
- * Called from main.c by each Monarch Processor.
+ * Called from main.c by Monarch Processor.
  * After this, any CPU can schedule any task.
  */
 void smp_commence(void)
 {
-printk("SMP: BSP before\n");
-mdelay(1000);
-
 	smp_commenced = 1;
 	mb();
-
-mdelay(10000);
-printk("SMP: BSP proceeding\n");
-mdelay(300);
 	return;
 }