|
@@ -66,6 +66,7 @@ enum ipi_msg_type {
|
|
|
IPI_CALL_FUNC,
|
|
|
IPI_CALL_FUNC_SINGLE,
|
|
|
IPI_CPU_STOP,
|
|
|
+ IPI_COMPLETION,
|
|
|
};
|
|
|
|
|
|
static DECLARE_COMPLETION(cpu_running);
|
|
@@ -456,6 +457,7 @@ static const char *ipi_types[NR_IPI] = {
|
|
|
S(IPI_CALL_FUNC, "Function call interrupts"),
|
|
|
S(IPI_CALL_FUNC_SINGLE, "Single function call interrupts"),
|
|
|
S(IPI_CPU_STOP, "CPU stop interrupts"),
|
|
|
+ S(IPI_COMPLETION, "completion interrupts"),
|
|
|
};
|
|
|
|
|
|
void show_ipi_list(struct seq_file *p, int prec)
|
|
@@ -515,6 +517,19 @@ static void ipi_cpu_stop(unsigned int cpu)
|
|
|
cpu_relax();
|
|
|
}
|
|
|
|
|
|
+static DEFINE_PER_CPU(struct completion *, cpu_completion);
|
|
|
+
|
|
|
+int register_ipi_completion(struct completion *completion, int cpu)
|
|
|
+{
|
|
|
+ per_cpu(cpu_completion, cpu) = completion;
|
|
|
+ return IPI_COMPLETION;
|
|
|
+}
|
|
|
+
|
|
|
+static void ipi_complete(unsigned int cpu)
|
|
|
+{
|
|
|
+ complete(per_cpu(cpu_completion, cpu));
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* Main handler for inter-processor interrupts
|
|
|
*/
|
|
@@ -565,6 +580,12 @@ void handle_IPI(int ipinr, struct pt_regs *regs)
|
|
|
irq_exit();
|
|
|
break;
|
|
|
|
|
|
+ case IPI_COMPLETION:
|
|
|
+ irq_enter();
|
|
|
+ ipi_complete(cpu);
|
|
|
+ irq_exit();
|
|
|
+ break;
|
|
|
+
|
|
|
default:
|
|
|
printk(KERN_CRIT "CPU%u: Unknown IPI message 0x%x\n",
|
|
|
cpu, ipinr);
|