aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/pseries/xics.c
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 /arch/powerpc/platforms/pseries/xics.c
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>
Diffstat (limited to 'arch/powerpc/platforms/pseries/xics.c')
-rw-r--r--arch/powerpc/platforms/pseries/xics.c61
1 files changed, 45 insertions, 16 deletions
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index c95697912fe..c0cb356833f 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)