aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMilton Miller <miltonm@bga.com>2008-10-09 21:56:29 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2008-10-13 01:24:16 -0400
commitd13f7208b211dd3613bdb04e2647081a5160d68f (patch)
tree10ee3124943a30157f5598deb5bb800cc2db15d8
parent78b5b626fa9048337530cc3ba4ceb9e4ee96a386 (diff)
powerpc/xics: Consolidate ipi message encode and decode
xics supports only one ipi per cpu, and expects software to use some queue to know why the interrupt was sent. In Linux, we use a an array of bitmaps indexed by cpu to identify the message. Currently the bits are set in smp.c and decoded in xics.c, with the data structure in a header file. Consolidate the code in xics.c similar to mpic and other interrupt controllers. Also, while making the the array static, the message word doesn't need to be volatile as set_bit and test_clear_bit take care of it for us, and put it under ifdef smp. Signed-off-by: Milton Miller <miltonm@bga.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-rw-r--r--arch/powerpc/platforms/pseries/smp.c32
-rw-r--r--arch/powerpc/platforms/pseries/xics.c61
-rw-r--r--arch/powerpc/platforms/pseries/xics.h12
3 files changed, 48 insertions, 57 deletions
diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c
index 9d8f8c84ab89..e00f96baa381 100644
--- a/arch/powerpc/platforms/pseries/smp.c
+++ b/arch/powerpc/platforms/pseries/smp.c
@@ -37,7 +37,6 @@
37#include <asm/paca.h> 37#include <asm/paca.h>
38#include <asm/time.h> 38#include <asm/time.h>
39#include <asm/machdep.h> 39#include <asm/machdep.h>
40#include "xics.h"
41#include <asm/cputable.h> 40#include <asm/cputable.h>
42#include <asm/firmware.h> 41#include <asm/firmware.h>
43#include <asm/system.h> 42#include <asm/system.h>
@@ -49,6 +48,7 @@
49 48
50#include "plpar_wrappers.h" 49#include "plpar_wrappers.h"
51#include "pseries.h" 50#include "pseries.h"
51#include "xics.h"
52 52
53 53
54/* 54/*
@@ -105,36 +105,6 @@ static inline int __devinit smp_startup_cpu(unsigned int lcpu)
105} 105}
106 106
107#ifdef CONFIG_XICS 107#ifdef CONFIG_XICS
108static inline void smp_xics_do_message(int cpu, int msg)
109{
110 set_bit(msg, &xics_ipi_message[cpu].value);
111 mb();
112 xics_cause_IPI(cpu);
113}
114
115static void smp_xics_message_pass(int target, int msg)
116{
117 unsigned int i;
118
119 if (target < NR_CPUS) {
120 smp_xics_do_message(target, msg);
121 } else {
122 for_each_online_cpu(i) {
123 if (target == MSG_ALL_BUT_SELF
124 && i == smp_processor_id())
125 continue;
126 smp_xics_do_message(i, msg);
127 }
128 }
129}
130
131static int __init smp_xics_probe(void)
132{
133 xics_request_IPIs();
134
135 return cpus_weight(cpu_possible_map);
136}
137
138static void __devinit smp_xics_setup_cpu(int cpu) 108static void __devinit smp_xics_setup_cpu(int cpu)
139{ 109{
140 if (cpu != boot_cpuid) 110 if (cpu != boot_cpuid)
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index c95697912fea..c0cb356833fa 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -71,11 +71,6 @@ static unsigned int interrupt_server_size = 8;
71 71
72static struct irq_host *xics_host; 72static struct irq_host *xics_host;
73 73
74/*
75 * XICS only has a single IPI, so encode the messages per CPU
76 */
77struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned;
78
79/* RTAS service tokens */ 74/* RTAS service tokens */
80static int ibm_get_xive; 75static int ibm_get_xive;
81static int ibm_set_xive; 76static int ibm_set_xive;
@@ -201,6 +196,15 @@ static void xics_update_irq_servers(void)
201} 196}
202 197
203#ifdef CONFIG_SMP 198#ifdef CONFIG_SMP
199/*
200 * XICS only has a single IPI, so encode the messages per CPU
201 */
202struct xics_ipi_struct {
203 unsigned long value;
204 } ____cacheline_aligned;
205
206static struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned;
207
204static int get_irq_server(unsigned int virq, unsigned int strict_check) 208static int get_irq_server(unsigned int virq, unsigned int strict_check)
205{ 209{
206 int server; 210 int server;
@@ -387,7 +391,6 @@ static unsigned int xics_get_irq_lpar(void)
387} 391}
388 392
389#ifdef CONFIG_SMP 393#ifdef CONFIG_SMP
390
391static irqreturn_t xics_ipi_dispatch(int cpu) 394static irqreturn_t xics_ipi_dispatch(int cpu)
392{ 395{
393 WARN_ON(cpu_is_offline(cpu)); 396 WARN_ON(cpu_is_offline(cpu));
@@ -419,6 +422,33 @@ static irqreturn_t xics_ipi_dispatch(int cpu)
419 return IRQ_HANDLED; 422 return IRQ_HANDLED;
420} 423}
421 424
425static inline void smp_xics_do_message(int cpu, int msg)
426{
427 set_bit(msg, &xics_ipi_message[cpu].value);
428 mb();
429 if (firmware_has_feature(FW_FEATURE_LPAR))
430 lpar_qirr_info(cpu, IPI_PRIORITY);
431 else
432 direct_qirr_info(cpu, IPI_PRIORITY);
433}
434
435void smp_xics_message_pass(int target, int msg)
436{
437 unsigned int i;
438
439 if (target < NR_CPUS) {
440 smp_xics_do_message(target, msg);
441 } else {
442 for_each_online_cpu(i) {
443 if (target == MSG_ALL_BUT_SELF
444 && i == smp_processor_id())
445 continue;
446 smp_xics_do_message(i, msg);
447 }
448 }
449}
450
451
422static irqreturn_t xics_ipi_action_direct(int irq, void *dev_id) 452static irqreturn_t xics_ipi_action_direct(int irq, void *dev_id)
423{ 453{
424 int cpu = smp_processor_id(); 454 int cpu = smp_processor_id();
@@ -436,15 +466,6 @@ static irqreturn_t xics_ipi_action_lpar(int irq, void *dev_id)
436 466
437 return xics_ipi_dispatch(cpu); 467 return xics_ipi_dispatch(cpu);
438} 468}
439
440void xics_cause_IPI(int cpu)
441{
442 if (firmware_has_feature(FW_FEATURE_LPAR))
443 lpar_qirr_info(cpu, IPI_PRIORITY);
444 else
445 direct_qirr_info(cpu, IPI_PRIORITY);
446}
447
448#endif /* CONFIG_SMP */ 469#endif /* CONFIG_SMP */
449 470
450static void xics_set_cpu_priority(unsigned char cppr) 471static void xics_set_cpu_priority(unsigned char cppr)
@@ -697,7 +718,7 @@ void __init xics_init_IRQ(void)
697 718
698 719
699#ifdef CONFIG_SMP 720#ifdef CONFIG_SMP
700void xics_request_IPIs(void) 721static void xics_request_ipi(void)
701{ 722{
702 unsigned int ipi; 723 unsigned int ipi;
703 int rc; 724 int rc;
@@ -718,6 +739,14 @@ void xics_request_IPIs(void)
718 "IPI", NULL); 739 "IPI", NULL);
719 BUG_ON(rc); 740 BUG_ON(rc);
720} 741}
742
743int __init smp_xics_probe(void)
744{
745 xics_request_ipi();
746
747 return cpus_weight(cpu_possible_map);
748}
749
721#endif /* CONFIG_SMP */ 750#endif /* CONFIG_SMP */
722 751
723void xics_teardown_cpu(void) 752void xics_teardown_cpu(void)
diff --git a/arch/powerpc/platforms/pseries/xics.h b/arch/powerpc/platforms/pseries/xics.h
index 1c5321ae8f2f..d1d5a83039ae 100644
--- a/arch/powerpc/platforms/pseries/xics.h
+++ b/arch/powerpc/platforms/pseries/xics.h
@@ -12,20 +12,12 @@
12#ifndef _POWERPC_KERNEL_XICS_H 12#ifndef _POWERPC_KERNEL_XICS_H
13#define _POWERPC_KERNEL_XICS_H 13#define _POWERPC_KERNEL_XICS_H
14 14
15#include <linux/cache.h>
16
17extern void xics_init_IRQ(void); 15extern void xics_init_IRQ(void);
18extern void xics_setup_cpu(void); 16extern void xics_setup_cpu(void);
19extern void xics_teardown_cpu(void); 17extern void xics_teardown_cpu(void);
20extern void xics_kexec_teardown_cpu(int secondary); 18extern void xics_kexec_teardown_cpu(int secondary);
21extern void xics_cause_IPI(int cpu);
22extern void xics_request_IPIs(void);
23extern void xics_migrate_irqs_away(void); 19extern void xics_migrate_irqs_away(void);
24 20extern int smp_xics_probe(void);
25struct xics_ipi_struct { 21extern void smp_xics_message_pass(int target, int msg);
26 volatile unsigned long value;
27} ____cacheline_aligned;
28
29extern struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned;
30 22
31#endif /* _POWERPC_KERNEL_XICS_H */ 23#endif /* _POWERPC_KERNEL_XICS_H */