[MIPS] SMP: Implement smp_call_function_mask().

Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
diff --git a/arch/mips/kernel/gdb-stub.c b/arch/mips/kernel/gdb-stub.c
index c33f6f2..bd128fa 100644
--- a/arch/mips/kernel/gdb-stub.c
+++ b/arch/mips/kernel/gdb-stub.c
@@ -676,15 +676,18 @@
 static int kgdb_smp_call_kgdb_wait(void)
 {
 #ifdef CONFIG_SMP
+	cpumask_t mask = cpu_online_map;
 	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;
 
@@ -711,10 +714,7 @@
 	call_data = &data;
 	mb();
 
-	/* Send a message to all other CPUs and wait for them to respond */
-	for (i = 0; i < NR_CPUS; i++)
-		if (cpu_online(i) && 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 */
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index 500a7ec..481ba53 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -97,6 +97,8 @@
 
 /*
  * 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.
@@ -121,18 +123,20 @@
  * 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;
 
@@ -151,9 +155,7 @@
 	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 */
@@ -169,6 +171,11 @@
 	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)
 {
@@ -199,8 +206,7 @@
 int smp_call_function_single(int cpu, void (*func) (void *info), void *info,
 			     int retry, int wait)
 {
-	struct call_data_struct data;
-	int me;
+	int ret, me;
 
 	/*
 	 * Can die spectacularly if this CPU isn't yet marked online
@@ -219,33 +225,8 @@
 		return 0;
 	}
 
-	/* Can deadlock when called with interrupts disabled */
-	WARN_ON(irqs_disabled());
-
-	data.func = func;
-	data.info = info;
-	atomic_set(&data.started, 0);
-	data.wait = wait;
-	if (wait)
-		atomic_set(&data.finished, 0);
-
-	spin_lock(&smp_call_lock);
-	call_data = &data;
-	smp_mb();
-
-	/* Send a message to the other CPU */
-	core_send_ipi(cpu, SMP_CALL_FUNCTION);
-
-	/* Wait for response */
-	/* FIXME: lock-up detection, backtrace on lock-up */
-	while (atomic_read(&data.started) != 1)
-		barrier();
-
-	if (wait)
-		while (atomic_read(&data.finished) != 1)
-			barrier();
-	call_data = NULL;
-	spin_unlock(&smp_call_lock);
+	ret = smp_call_function_mask(cpumask_of_cpu(cpu), func, info, retry,
+				     wait);
 
 	put_cpu();
 	return 0;
diff --git a/include/asm-mips/smp.h b/include/asm-mips/smp.h
index 13aef6a..dc770025 100644
--- a/include/asm-mips/smp.h
+++ b/include/asm-mips/smp.h
@@ -60,6 +60,15 @@
  */
 extern void core_send_ipi(int cpu, unsigned int action);
 
+static inline void core_send_ipi_mask(cpumask_t mask, unsigned int action)
+{
+	unsigned int i;
+
+	for_each_cpu_mask(i, mask)
+		core_send_ipi(i, action);
+}
+
+
 /*
  * Firmware CPU startup hook
  */