root/arch/powerpc/kernel/dbell.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. doorbell_global_ipi
  2. doorbell_core_ipi
  3. doorbell_try_core_ipi
  4. doorbell_exception
  5. doorbell_exception

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Author: Kumar Gala <galak@kernel.crashing.org>
   4  *
   5  * Copyright 2009 Freescale Semiconductor Inc.
   6  */
   7 
   8 #include <linux/stddef.h>
   9 #include <linux/kernel.h>
  10 #include <linux/smp.h>
  11 #include <linux/threads.h>
  12 #include <linux/hardirq.h>
  13 
  14 #include <asm/dbell.h>
  15 #include <asm/irq_regs.h>
  16 #include <asm/kvm_ppc.h>
  17 #include <asm/trace.h>
  18 
  19 #ifdef CONFIG_SMP
  20 
  21 /*
  22  * Doorbells must only be used if CPU_FTR_DBELL is available.
  23  * msgsnd is used in HV, and msgsndp is used in !HV.
  24  *
  25  * These should be used by platform code that is aware of restrictions.
  26  * Other arch code should use ->cause_ipi.
  27  *
  28  * doorbell_global_ipi() sends a dbell to any target CPU.
  29  * Must be used only by architectures that address msgsnd target
  30  * by PIR/get_hard_smp_processor_id.
  31  */
  32 void doorbell_global_ipi(int cpu)
  33 {
  34         u32 tag = get_hard_smp_processor_id(cpu);
  35 
  36         kvmppc_set_host_ipi(cpu);
  37         /* Order previous accesses vs. msgsnd, which is treated as a store */
  38         ppc_msgsnd_sync();
  39         ppc_msgsnd(PPC_DBELL_MSGTYPE, 0, tag);
  40 }
  41 
  42 /*
  43  * doorbell_core_ipi() sends a dbell to a target CPU in the same core.
  44  * Must be used only by architectures that address msgsnd target
  45  * by TIR/cpu_thread_in_core.
  46  */
  47 void doorbell_core_ipi(int cpu)
  48 {
  49         u32 tag = cpu_thread_in_core(cpu);
  50 
  51         kvmppc_set_host_ipi(cpu);
  52         /* Order previous accesses vs. msgsnd, which is treated as a store */
  53         ppc_msgsnd_sync();
  54         ppc_msgsnd(PPC_DBELL_MSGTYPE, 0, tag);
  55 }
  56 
  57 /*
  58  * Attempt to cause a core doorbell if destination is on the same core.
  59  * Returns 1 on success, 0 on failure.
  60  */
  61 int doorbell_try_core_ipi(int cpu)
  62 {
  63         int this_cpu = get_cpu();
  64         int ret = 0;
  65 
  66         if (cpumask_test_cpu(cpu, cpu_sibling_mask(this_cpu))) {
  67                 doorbell_core_ipi(cpu);
  68                 ret = 1;
  69         }
  70 
  71         put_cpu();
  72 
  73         return ret;
  74 }
  75 
  76 void doorbell_exception(struct pt_regs *regs)
  77 {
  78         struct pt_regs *old_regs = set_irq_regs(regs);
  79 
  80         irq_enter();
  81         trace_doorbell_entry(regs);
  82 
  83         ppc_msgsync();
  84 
  85         may_hard_irq_enable();
  86 
  87         kvmppc_clear_host_ipi(smp_processor_id());
  88         __this_cpu_inc(irq_stat.doorbell_irqs);
  89 
  90         smp_ipi_demux_relaxed(); /* already performed the barrier */
  91 
  92         trace_doorbell_exit(regs);
  93         irq_exit();
  94         set_irq_regs(old_regs);
  95 }
  96 #else /* CONFIG_SMP */
  97 void doorbell_exception(struct pt_regs *regs)
  98 {
  99         printk(KERN_WARNING "Received doorbell on non-smp system\n");
 100 }
 101 #endif /* CONFIG_SMP */
 102 

/* [<][>][^][v][top][bottom][index][help] */