aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel
diff options
context:
space:
mode:
authorNicolas Pitre <nicolas.pitre@linaro.org>2012-11-27 21:54:41 -0500
committerNicolas Pitre <nicolas.pitre@linaro.org>2013-09-23 18:47:26 -0400
commit5135d875e1457ef946a055003d8f80713e862135 (patch)
tree6cd37d9a8fd486ac2af3205b9baf2dce20ac0040 /arch/arm/kernel
parent108a9640abfada2599b6cb08c7cc00a4eebf8f8f (diff)
ARM: SMP: basic IPI triggered completion support
We need a mechanism to let an inbound CPU signal that it is alive before even getting into the kernel environment i.e. from early assembly code. Using an IPI is the simplest way to achieve that. This adds some basic infrastructure to register a struct completion pointer to be "completed" when the dedicated IPI for this task is received. Signed-off-by: Nicolas Pitre <nico@linaro.org>
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r--arch/arm/kernel/smp.c21
1 files changed, 21 insertions, 0 deletions
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 72024ea8a3a6..7d80a549cae5 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -66,6 +66,7 @@ enum ipi_msg_type {
66 IPI_CALL_FUNC, 66 IPI_CALL_FUNC,
67 IPI_CALL_FUNC_SINGLE, 67 IPI_CALL_FUNC_SINGLE,
68 IPI_CPU_STOP, 68 IPI_CPU_STOP,
69 IPI_COMPLETION,
69}; 70};
70 71
71static DECLARE_COMPLETION(cpu_running); 72static DECLARE_COMPLETION(cpu_running);
@@ -456,6 +457,7 @@ static const char *ipi_types[NR_IPI] = {
456 S(IPI_CALL_FUNC, "Function call interrupts"), 457 S(IPI_CALL_FUNC, "Function call interrupts"),
457 S(IPI_CALL_FUNC_SINGLE, "Single function call interrupts"), 458 S(IPI_CALL_FUNC_SINGLE, "Single function call interrupts"),
458 S(IPI_CPU_STOP, "CPU stop interrupts"), 459 S(IPI_CPU_STOP, "CPU stop interrupts"),
460 S(IPI_COMPLETION, "completion interrupts"),
459}; 461};
460 462
461void show_ipi_list(struct seq_file *p, int prec) 463void show_ipi_list(struct seq_file *p, int prec)
@@ -515,6 +517,19 @@ static void ipi_cpu_stop(unsigned int cpu)
515 cpu_relax(); 517 cpu_relax();
516} 518}
517 519
520static DEFINE_PER_CPU(struct completion *, cpu_completion);
521
522int register_ipi_completion(struct completion *completion, int cpu)
523{
524 per_cpu(cpu_completion, cpu) = completion;
525 return IPI_COMPLETION;
526}
527
528static void ipi_complete(unsigned int cpu)
529{
530 complete(per_cpu(cpu_completion, cpu));
531}
532
518/* 533/*
519 * Main handler for inter-processor interrupts 534 * Main handler for inter-processor interrupts
520 */ 535 */
@@ -565,6 +580,12 @@ void handle_IPI(int ipinr, struct pt_regs *regs)
565 irq_exit(); 580 irq_exit();
566 break; 581 break;
567 582
583 case IPI_COMPLETION:
584 irq_enter();
585 ipi_complete(cpu);
586 irq_exit();
587 break;
588
568 default: 589 default:
569 printk(KERN_CRIT "CPU%u: Unknown IPI message 0x%x\n", 590 printk(KERN_CRIT "CPU%u: Unknown IPI message 0x%x\n",
570 cpu, ipinr); 591 cpu, ipinr);