Commit d13f7208 authored by Milton Miller's avatar Milton Miller Committed by Benjamin Herrenschmidt

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: default avatarMilton Miller <miltonm@bga.com>
Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
parent 78b5b626
...@@ -37,7 +37,6 @@ ...@@ -37,7 +37,6 @@
#include <asm/paca.h> #include <asm/paca.h>
#include <asm/time.h> #include <asm/time.h>
#include <asm/machdep.h> #include <asm/machdep.h>
#include "xics.h"
#include <asm/cputable.h> #include <asm/cputable.h>
#include <asm/firmware.h> #include <asm/firmware.h>
#include <asm/system.h> #include <asm/system.h>
...@@ -49,6 +48,7 @@ ...@@ -49,6 +48,7 @@
#include "plpar_wrappers.h" #include "plpar_wrappers.h"
#include "pseries.h" #include "pseries.h"
#include "xics.h"
/* /*
...@@ -105,36 +105,6 @@ static inline int __devinit smp_startup_cpu(unsigned int lcpu) ...@@ -105,36 +105,6 @@ static inline int __devinit smp_startup_cpu(unsigned int lcpu)
} }
#ifdef CONFIG_XICS #ifdef CONFIG_XICS
static inline void smp_xics_do_message(int cpu, int msg)
{
set_bit(msg, &xics_ipi_message[cpu].value);
mb();
xics_cause_IPI(cpu);
}
static void smp_xics_message_pass(int target, int msg)
{
unsigned int i;
if (target < NR_CPUS) {
smp_xics_do_message(target, msg);
} else {
for_each_online_cpu(i) {
if (target == MSG_ALL_BUT_SELF
&& i == smp_processor_id())
continue;
smp_xics_do_message(i, msg);
}
}
}
static int __init smp_xics_probe(void)
{
xics_request_IPIs();
return cpus_weight(cpu_possible_map);
}
static void __devinit smp_xics_setup_cpu(int cpu) static void __devinit smp_xics_setup_cpu(int cpu)
{ {
if (cpu != boot_cpuid) if (cpu != boot_cpuid)
......
...@@ -71,11 +71,6 @@ static unsigned int interrupt_server_size = 8; ...@@ -71,11 +71,6 @@ static unsigned int interrupt_server_size = 8;
static struct irq_host *xics_host; static struct irq_host *xics_host;
/*
* XICS only has a single IPI, so encode the messages per CPU
*/
struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned;
/* RTAS service tokens */ /* RTAS service tokens */
static int ibm_get_xive; static int ibm_get_xive;
static int ibm_set_xive; static int ibm_set_xive;
...@@ -201,6 +196,15 @@ static void xics_update_irq_servers(void) ...@@ -201,6 +196,15 @@ static void xics_update_irq_servers(void)
} }
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
/*
* XICS only has a single IPI, so encode the messages per CPU
*/
struct xics_ipi_struct {
unsigned long value;
} ____cacheline_aligned;
static struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned;
static int get_irq_server(unsigned int virq, unsigned int strict_check) static int get_irq_server(unsigned int virq, unsigned int strict_check)
{ {
int server; int server;
...@@ -387,7 +391,6 @@ static unsigned int xics_get_irq_lpar(void) ...@@ -387,7 +391,6 @@ static unsigned int xics_get_irq_lpar(void)
} }
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
static irqreturn_t xics_ipi_dispatch(int cpu) static irqreturn_t xics_ipi_dispatch(int cpu)
{ {
WARN_ON(cpu_is_offline(cpu)); WARN_ON(cpu_is_offline(cpu));
...@@ -419,6 +422,33 @@ static irqreturn_t xics_ipi_dispatch(int cpu) ...@@ -419,6 +422,33 @@ static irqreturn_t xics_ipi_dispatch(int cpu)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static inline void smp_xics_do_message(int cpu, int msg)
{
set_bit(msg, &xics_ipi_message[cpu].value);
mb();
if (firmware_has_feature(FW_FEATURE_LPAR))
lpar_qirr_info(cpu, IPI_PRIORITY);
else
direct_qirr_info(cpu, IPI_PRIORITY);
}
void smp_xics_message_pass(int target, int msg)
{
unsigned int i;
if (target < NR_CPUS) {
smp_xics_do_message(target, msg);
} else {
for_each_online_cpu(i) {
if (target == MSG_ALL_BUT_SELF
&& i == smp_processor_id())
continue;
smp_xics_do_message(i, msg);
}
}
}
static irqreturn_t xics_ipi_action_direct(int irq, void *dev_id) static irqreturn_t xics_ipi_action_direct(int irq, void *dev_id)
{ {
int cpu = smp_processor_id(); int cpu = smp_processor_id();
...@@ -436,15 +466,6 @@ static irqreturn_t xics_ipi_action_lpar(int irq, void *dev_id) ...@@ -436,15 +466,6 @@ static irqreturn_t xics_ipi_action_lpar(int irq, void *dev_id)
return xics_ipi_dispatch(cpu); return xics_ipi_dispatch(cpu);
} }
void xics_cause_IPI(int cpu)
{
if (firmware_has_feature(FW_FEATURE_LPAR))
lpar_qirr_info(cpu, IPI_PRIORITY);
else
direct_qirr_info(cpu, IPI_PRIORITY);
}
#endif /* CONFIG_SMP */ #endif /* CONFIG_SMP */
static void xics_set_cpu_priority(unsigned char cppr) static void xics_set_cpu_priority(unsigned char cppr)
...@@ -697,7 +718,7 @@ void __init xics_init_IRQ(void) ...@@ -697,7 +718,7 @@ void __init xics_init_IRQ(void)
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
void xics_request_IPIs(void) static void xics_request_ipi(void)
{ {
unsigned int ipi; unsigned int ipi;
int rc; int rc;
...@@ -718,6 +739,14 @@ void xics_request_IPIs(void) ...@@ -718,6 +739,14 @@ void xics_request_IPIs(void)
"IPI", NULL); "IPI", NULL);
BUG_ON(rc); BUG_ON(rc);
} }
int __init smp_xics_probe(void)
{
xics_request_ipi();
return cpus_weight(cpu_possible_map);
}
#endif /* CONFIG_SMP */ #endif /* CONFIG_SMP */
void xics_teardown_cpu(void) void xics_teardown_cpu(void)
......
...@@ -12,20 +12,12 @@ ...@@ -12,20 +12,12 @@
#ifndef _POWERPC_KERNEL_XICS_H #ifndef _POWERPC_KERNEL_XICS_H
#define _POWERPC_KERNEL_XICS_H #define _POWERPC_KERNEL_XICS_H
#include <linux/cache.h>
extern void xics_init_IRQ(void); extern void xics_init_IRQ(void);
extern void xics_setup_cpu(void); extern void xics_setup_cpu(void);
extern void xics_teardown_cpu(void); extern void xics_teardown_cpu(void);
extern void xics_kexec_teardown_cpu(int secondary); extern void xics_kexec_teardown_cpu(int secondary);
extern void xics_cause_IPI(int cpu);
extern void xics_request_IPIs(void);
extern void xics_migrate_irqs_away(void); extern void xics_migrate_irqs_away(void);
extern int smp_xics_probe(void);
struct xics_ipi_struct { extern void smp_xics_message_pass(int target, int msg);
volatile unsigned long value;
} ____cacheline_aligned;
extern struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned;
#endif /* _POWERPC_KERNEL_XICS_H */ #endif /* _POWERPC_KERNEL_XICS_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment