Skip to content

Commit b866cc2

Browse files
npigginmpe
authored andcommitted
powerpc: Change the doorbell IPI calling convention
Change the doorbell callers to know about their msgsnd addressing, rather than have them set a per-cpu target data tag at boot that gets sent to the cause_ipi functions. The data is only used for doorbell IPI functions, no other IPI types, so it makes sense to keep that detail local to doorbell. Have the platform code understand doorbell IPIs, rather than the interrupt controller code understand them. Platform code can look at capabilities it has available and decide which to use. Signed-off-by: Nicholas Piggin <[email protected]> Signed-off-by: Michael Ellerman <[email protected]>
1 parent 9b7ff0c commit b866cc2

File tree

14 files changed

+92
-79
lines changed

14 files changed

+92
-79
lines changed

arch/powerpc/include/asm/dbell.h

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,6 @@ enum ppc_dbell {
3535
#ifdef CONFIG_PPC_BOOK3S
3636

3737
#define PPC_DBELL_MSGTYPE PPC_DBELL_SERVER
38-
#define SPRN_DOORBELL_CPUTAG SPRN_TIR
39-
#define PPC_DBELL_TAG_MASK 0x7f
4038

4139
static inline void _ppc_msgsnd(u32 msg)
4240
{
@@ -49,8 +47,6 @@ static inline void _ppc_msgsnd(u32 msg)
4947
#else /* CONFIG_PPC_BOOK3S */
5048

5149
#define PPC_DBELL_MSGTYPE PPC_DBELL
52-
#define SPRN_DOORBELL_CPUTAG SPRN_PIR
53-
#define PPC_DBELL_TAG_MASK 0x3fff
5450

5551
static inline void _ppc_msgsnd(u32 msg)
5652
{
@@ -59,9 +55,10 @@ static inline void _ppc_msgsnd(u32 msg)
5955

6056
#endif /* CONFIG_PPC_BOOK3S */
6157

62-
extern void doorbell_cause_ipi(int cpu, unsigned long data);
58+
extern void doorbell_global_ipi(int cpu);
59+
extern void doorbell_core_ipi(int cpu);
60+
extern int doorbell_try_core_ipi(int cpu);
6361
extern void doorbell_exception(struct pt_regs *regs);
64-
extern void doorbell_setup_this_cpu(void);
6562

6663
static inline void ppc_msgsnd(enum ppc_dbell type, u32 flags, u32 tag)
6764
{

arch/powerpc/include/asm/smp.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ extern int cpu_to_chip_id(int cpu);
4040
struct smp_ops_t {
4141
void (*message_pass)(int cpu, int msg);
4242
#ifdef CONFIG_PPC_SMP_MUXED_IPI
43-
void (*cause_ipi)(int cpu, unsigned long data);
43+
void (*cause_ipi)(int cpu);
4444
#endif
4545
void (*probe)(void);
4646
int (*kick_cpu)(int nr);
@@ -125,7 +125,6 @@ extern int smp_request_message_ipi(int virq, int message);
125125
extern const char *smp_ipi_name[];
126126

127127
/* for irq controllers with only a single ipi */
128-
extern void smp_muxed_ipi_set_data(int cpu, unsigned long data);
129128
extern void smp_muxed_ipi_message_pass(int cpu, int msg);
130129
extern void smp_muxed_ipi_set_message(int cpu, int msg);
131130
extern irqreturn_t smp_ipi_demux(void);

arch/powerpc/include/asm/xics.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ struct icp_ops {
5757
void (*teardown_cpu)(void);
5858
void (*flush_ipi)(void);
5959
#ifdef CONFIG_SMP
60-
void (*cause_ipi)(int cpu, unsigned long data);
60+
void (*cause_ipi)(int cpu);
6161
irq_handler_t ipi_action;
6262
#endif
6363
};

arch/powerpc/kernel/dbell.c

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,60 @@
2020
#include <asm/kvm_ppc.h>
2121

2222
#ifdef CONFIG_SMP
23-
void doorbell_setup_this_cpu(void)
23+
24+
/*
25+
* Doorbells must only be used if CPU_FTR_DBELL is available.
26+
* msgsnd is used in HV, and msgsndp is used in !HV.
27+
*
28+
* These should be used by platform code that is aware of restrictions.
29+
* Other arch code should use ->cause_ipi.
30+
*
31+
* doorbell_global_ipi() sends a dbell to any target CPU.
32+
* Must be used only by architectures that address msgsnd target
33+
* by PIR/get_hard_smp_processor_id.
34+
*/
35+
void doorbell_global_ipi(int cpu)
2436
{
25-
unsigned long tag = mfspr(SPRN_DOORBELL_CPUTAG) & PPC_DBELL_TAG_MASK;
37+
u32 tag = get_hard_smp_processor_id(cpu);
2638

27-
smp_muxed_ipi_set_data(smp_processor_id(), tag);
39+
kvmppc_set_host_ipi(cpu, 1);
40+
/* Order previous accesses vs. msgsnd, which is treated as a store */
41+
mb();
42+
ppc_msgsnd(PPC_DBELL_MSGTYPE, 0, tag);
2843
}
2944

30-
void doorbell_cause_ipi(int cpu, unsigned long data)
45+
/*
46+
* doorbell_core_ipi() sends a dbell to a target CPU in the same core.
47+
* Must be used only by architectures that address msgsnd target
48+
* by TIR/cpu_thread_in_core.
49+
*/
50+
void doorbell_core_ipi(int cpu)
3151
{
52+
u32 tag = cpu_thread_in_core(cpu);
53+
54+
kvmppc_set_host_ipi(cpu, 1);
3255
/* Order previous accesses vs. msgsnd, which is treated as a store */
3356
mb();
34-
ppc_msgsnd(PPC_DBELL_MSGTYPE, 0, data);
57+
ppc_msgsnd(PPC_DBELL_MSGTYPE, 0, tag);
58+
}
59+
60+
/*
61+
* Attempt to cause a core doorbell if destination is on the same core.
62+
* Returns 1 on success, 0 on failure.
63+
*/
64+
int doorbell_try_core_ipi(int cpu)
65+
{
66+
int this_cpu = get_cpu();
67+
int ret = 0;
68+
69+
if (cpumask_test_cpu(cpu, cpu_sibling_mask(this_cpu))) {
70+
doorbell_core_ipi(cpu);
71+
ret = 1;
72+
}
73+
74+
put_cpu();
75+
76+
return ret;
3577
}
3678

3779
void doorbell_exception(struct pt_regs *regs)

arch/powerpc/kernel/smp.c

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include <asm/irq.h>
4040
#include <asm/hw_irq.h>
4141
#include <asm/kvm_ppc.h>
42+
#include <asm/dbell.h>
4243
#include <asm/page.h>
4344
#include <asm/pgtable.h>
4445
#include <asm/prom.h>
@@ -211,17 +212,9 @@ int smp_request_message_ipi(int virq, int msg)
211212
#ifdef CONFIG_PPC_SMP_MUXED_IPI
212213
struct cpu_messages {
213214
long messages; /* current messages */
214-
unsigned long data; /* data for cause ipi */
215215
};
216216
static DEFINE_PER_CPU_SHARED_ALIGNED(struct cpu_messages, ipi_message);
217217

218-
void smp_muxed_ipi_set_data(int cpu, unsigned long data)
219-
{
220-
struct cpu_messages *info = &per_cpu(ipi_message, cpu);
221-
222-
info->data = data;
223-
}
224-
225218
void smp_muxed_ipi_set_message(int cpu, int msg)
226219
{
227220
struct cpu_messages *info = &per_cpu(ipi_message, cpu);
@@ -236,14 +229,13 @@ void smp_muxed_ipi_set_message(int cpu, int msg)
236229

237230
void smp_muxed_ipi_message_pass(int cpu, int msg)
238231
{
239-
struct cpu_messages *info = &per_cpu(ipi_message, cpu);
240-
241232
smp_muxed_ipi_set_message(cpu, msg);
233+
242234
/*
243235
* cause_ipi functions are required to include a full barrier
244236
* before doing whatever causes the IPI.
245237
*/
246-
smp_ops->cause_ipi(cpu, info->data);
238+
smp_ops->cause_ipi(cpu);
247239
}
248240

249241
#ifdef __BIG_ENDIAN__
@@ -254,11 +246,12 @@ void smp_muxed_ipi_message_pass(int cpu, int msg)
254246

255247
irqreturn_t smp_ipi_demux(void)
256248
{
257-
struct cpu_messages *info = this_cpu_ptr(&ipi_message);
249+
struct cpu_messages *info;
258250
unsigned long all;
259251

260252
mb(); /* order any irq clear */
261253

254+
info = this_cpu_ptr(&ipi_message);
262255
do {
263256
all = xchg(&info->messages, 0);
264257
#if defined(CONFIG_KVM_XICS) && defined(CONFIG_KVM_BOOK3S_HV_POSSIBLE)

arch/powerpc/platforms/85xx/smp.c

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -461,16 +461,9 @@ static void mpc85xx_smp_machine_kexec(struct kimage *image)
461461
}
462462
#endif /* CONFIG_KEXEC_CORE */
463463

464-
static void smp_85xx_basic_setup(int cpu_nr)
465-
{
466-
if (cpu_has_feature(CPU_FTR_DBELL))
467-
doorbell_setup_this_cpu();
468-
}
469-
470464
static void smp_85xx_setup_cpu(int cpu_nr)
471465
{
472466
mpic_setup_this_cpu();
473-
smp_85xx_basic_setup(cpu_nr);
474467
}
475468

476469
void __init mpc85xx_smp_init(void)
@@ -484,15 +477,15 @@ void __init mpc85xx_smp_init(void)
484477
smp_85xx_ops.setup_cpu = smp_85xx_setup_cpu;
485478
smp_85xx_ops.message_pass = smp_mpic_message_pass;
486479
} else
487-
smp_85xx_ops.setup_cpu = smp_85xx_basic_setup;
480+
smp_85xx_ops.setup_cpu = NULL;
488481

489482
if (cpu_has_feature(CPU_FTR_DBELL)) {
490483
/*
491484
* If left NULL, .message_pass defaults to
492485
* smp_muxed_ipi_message_pass
493486
*/
494487
smp_85xx_ops.message_pass = NULL;
495-
smp_85xx_ops.cause_ipi = doorbell_cause_ipi;
488+
smp_85xx_ops.cause_ipi = doorbell_global_ipi;
496489
smp_85xx_ops.probe = NULL;
497490
}
498491

arch/powerpc/platforms/powermac/smp.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ static irqreturn_t psurge_ipi_intr(int irq, void *d)
172172
return IRQ_HANDLED;
173173
}
174174

175-
static void smp_psurge_cause_ipi(int cpu, unsigned long data)
175+
static void smp_psurge_cause_ipi(int cpu)
176176
{
177177
psurge_set_ipi(cpu);
178178
}

arch/powerpc/platforms/powernv/smp.c

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,6 @@ static void pnv_smp_setup_cpu(int cpu)
5353
xive_smp_setup_cpu();
5454
else if (cpu != boot_cpuid)
5555
xics_setup_cpu();
56-
57-
#ifdef CONFIG_PPC_DOORBELL
58-
if (cpu_has_feature(CPU_FTR_DBELL))
59-
doorbell_setup_this_cpu();
60-
#endif
6156
}
6257

6358
static int pnv_smp_kick_cpu(int nr)
@@ -254,17 +249,31 @@ static int pnv_smp_prepare_cpu(int cpu)
254249
return 0;
255250
}
256251

252+
static void pnv_cause_ipi(int cpu)
253+
{
254+
if (doorbell_try_core_ipi(cpu))
255+
return;
256+
257+
icp_ops->cause_ipi(cpu);
258+
}
259+
257260
static void __init pnv_smp_probe(void)
258261
{
259262
if (xive_enabled())
260263
xive_smp_probe();
261264
else
262265
xics_smp_probe();
266+
267+
if (cpu_has_feature(CPU_FTR_DBELL) && !cpu_has_feature(CPU_FTR_ARCH_300)) {
268+
smp_ops->cause_ipi = pnv_cause_ipi;
269+
} else {
270+
smp_ops->cause_ipi = icp_ops->cause_ipi;
271+
}
263272
}
264273

265274
static struct smp_ops_t pnv_smp_ops = {
266-
.message_pass = smp_muxed_ipi_message_pass,
267-
.cause_ipi = NULL, /* Filled at runtime by xi{cs,ve}_smp_probe() */
275+
.message_pass = NULL, /* Use smp_muxed_ipi_message_pass */
276+
.cause_ipi = NULL, /* Filled at runtime by pnv_smp_probe() */
268277
.probe = pnv_smp_probe,
269278
.prepare_cpu = pnv_smp_prepare_cpu,
270279
.kick_cpu = pnv_smp_kick_cpu,

arch/powerpc/platforms/pseries/smp.c

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,6 @@
5555
*/
5656
static cpumask_var_t of_spin_mask;
5757

58-
/*
59-
* If we multiplex IPI mechanisms, store the appropriate XICS IPI mechanism here
60-
*/
61-
static void (*xics_cause_ipi)(int cpu, unsigned long data);
62-
6358
/* Query where a cpu is now. Return codes #defined in plpar_wrappers.h */
6459
int smp_query_cpu_stopped(unsigned int pcpu)
6560
{
@@ -143,8 +138,6 @@ static void smp_setup_cpu(int cpu)
143138
{
144139
if (cpu != boot_cpuid)
145140
xics_setup_cpu();
146-
if (cpu_has_feature(CPU_FTR_DBELL))
147-
doorbell_setup_this_cpu();
148141

149142
if (firmware_has_feature(FW_FEATURE_SPLPAR))
150143
vpa_init(cpu);
@@ -187,23 +180,23 @@ static int smp_pSeries_kick_cpu(int nr)
187180
return 0;
188181
}
189182

190-
/* Only used on systems that support multiple IPI mechanisms */
191-
static void pSeries_cause_ipi_mux(int cpu, unsigned long data)
183+
static void smp_pseries_cause_ipi(int cpu)
192184
{
193-
if (cpumask_test_cpu(cpu, cpu_sibling_mask(smp_processor_id())))
194-
doorbell_cause_ipi(cpu, data);
195-
else
196-
xics_cause_ipi(cpu, data);
185+
/* POWER9 should not use this handler */
186+
if (doorbell_try_core_ipi(cpu))
187+
return;
188+
189+
icp_ops->cause_ipi(cpu);
197190
}
198191

199192
static __init void pSeries_smp_probe(void)
200193
{
201194
xics_smp_probe();
202195

203-
if (cpu_has_feature(CPU_FTR_DBELL)) {
204-
xics_cause_ipi = smp_ops->cause_ipi;
205-
smp_ops->cause_ipi = pSeries_cause_ipi_mux;
206-
}
196+
if (cpu_has_feature(CPU_FTR_DBELL))
197+
smp_ops->cause_ipi = smp_pseries_cause_ipi;
198+
else
199+
smp_ops->cause_ipi = icp_ops->cause_ipi;
207200
}
208201

209202
static struct smp_ops_t pseries_smp_ops = {

arch/powerpc/sysdev/xics/icp-hv.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ static void icp_hv_set_cpu_priority(unsigned char cppr)
138138

139139
#ifdef CONFIG_SMP
140140

141-
static void icp_hv_cause_ipi(int cpu, unsigned long data)
141+
static void icp_hv_cause_ipi(int cpu)
142142
{
143143
icp_hv_set_qirr(cpu, IPI_PRIORITY);
144144
}

arch/powerpc/sysdev/xics/icp-native.c

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -143,19 +143,9 @@ static unsigned int icp_native_get_irq(void)
143143

144144
#ifdef CONFIG_SMP
145145

146-
static void icp_native_cause_ipi(int cpu, unsigned long data)
146+
static void icp_native_cause_ipi(int cpu)
147147
{
148148
kvmppc_set_host_ipi(cpu, 1);
149-
#ifdef CONFIG_PPC_DOORBELL
150-
if (cpu_has_feature(CPU_FTR_DBELL)) {
151-
if (cpumask_test_cpu(cpu, cpu_sibling_mask(get_cpu()))) {
152-
doorbell_cause_ipi(cpu, data);
153-
put_cpu();
154-
return;
155-
}
156-
put_cpu();
157-
}
158-
#endif
159149
icp_native_set_qirr(cpu, IPI_PRIORITY);
160150
}
161151

arch/powerpc/sysdev/xics/icp-opal.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ static void icp_opal_eoi(struct irq_data *d)
126126

127127
#ifdef CONFIG_SMP
128128

129-
static void icp_opal_cause_ipi(int cpu, unsigned long data)
129+
static void icp_opal_cause_ipi(int cpu)
130130
{
131131
int hw_cpu = get_hard_smp_processor_id(cpu);
132132

arch/powerpc/sysdev/xics/xics-common.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -143,9 +143,6 @@ static void xics_request_ipi(void)
143143

144144
void __init xics_smp_probe(void)
145145
{
146-
/* Setup cause_ipi callback based on which ICP is used */
147-
smp_ops->cause_ipi = icp_ops->cause_ipi;
148-
149146
/* Register all the IPIs */
150147
xics_request_ipi();
151148
}

arch/powerpc/sysdev/xive/common.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -834,15 +834,15 @@ static void xive_irq_free_data(unsigned int virq)
834834

835835
#ifdef CONFIG_SMP
836836

837-
static void xive_cause_ipi(int cpu, unsigned long msg)
837+
static void xive_cause_ipi(int cpu)
838838
{
839839
struct xive_cpu *xc;
840840
struct xive_irq_data *xd;
841841

842842
xc = per_cpu(xive_cpu, cpu);
843843

844-
DBG_VERBOSE("IPI msg#%ld CPU %d -> %d (HW IRQ 0x%x)\n",
845-
msg, smp_processor_id(), cpu, xc->hw_ipi);
844+
DBG_VERBOSE("IPI CPU %d -> %d (HW IRQ 0x%x)\n",
845+
smp_processor_id(), cpu, xc->hw_ipi);
846846

847847
xd = &xc->ipi_data;
848848
if (WARN_ON(!xd->trig_mmio))

0 commit comments

Comments
 (0)