summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMilton Miller <miltonm@bga.com>2008-10-10 03:56:34 +0200
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2008-10-13 07:24:18 +0200
commitb4963255ad5a426f04a0bb15c4315fa4bb40cde9 (patch)
tree18ed300d89d30e20ade63a94f49934b24e76afec
parentpowerpc/xics: Initialization code cleanups (diff)
downloadlinux-b4963255ad5a426f04a0bb15c4315fa4bb40cde9.tar.xz
linux-b4963255ad5a426f04a0bb15c4315fa4bb40cde9.zip
powerpc/xics: Factor out cpu joining/unjoining the GIQ
This factors out processors joining and unjoining the Global Interrupt Queue into a separate function. There is a bit of math to calculate the arguments to rtas to join or leave the global interrupt queue, and a warning on failure afterwards. Make a helper for the 3 callers. Signed-off-by: Milton Miller <miltonm@bga.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-rw-r--r--arch/powerpc/platforms/pseries/xics.c33
1 files changed, 13 insertions, 20 deletions
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index 27327fc86055..0bb553331f4f 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -727,20 +727,19 @@ static void xics_set_cpu_priority(unsigned char cppr)
iosync();
}
+/* Have the calling processor join or leave the specified global queue */
+static void xics_set_cpu_giq(unsigned int gserver, unsigned int join)
+{
+ int status = rtas_set_indicator_fast(GLOBAL_INTERRUPT_QUEUE,
+ (1UL << interrupt_server_size) - 1 - gserver, join);
+ WARN_ON(status < 0);
+}
void xics_setup_cpu(void)
{
xics_set_cpu_priority(0xff);
- /*
- * Put the calling processor into the GIQ. This is really only
- * necessary from a secondary thread as the OF start-cpu interface
- * performs this function for us on primary threads.
- *
- * XXX: undo of teardown on kexec needs this too, as may hotplug
- */
- rtas_set_indicator_fast(GLOBAL_INTERRUPT_QUEUE,
- (1UL << interrupt_server_size) - 1 - default_distrib_server, 1);
+ xics_set_cpu_giq(default_distrib_server, 1);
}
void xics_teardown_cpu(void)
@@ -749,9 +748,7 @@ void xics_teardown_cpu(void)
xics_set_cpu_priority(0);
- /*
- * Clear IPI
- */
+ /* Clear any pending IPI request */
if (firmware_has_feature(FW_FEATURE_LPAR))
lpar_qirr_info(cpu, 0xff);
else
@@ -785,9 +782,7 @@ void xics_kexec_teardown_cpu(int secondary)
* so leave the master cpu in the group.
*/
if (secondary)
- rtas_set_indicator_fast(GLOBAL_INTERRUPT_QUEUE,
- (1UL << interrupt_server_size) - 1 -
- default_distrib_server, 0);
+ xics_set_cpu_giq(default_distrib_server, 0);
}
#ifdef CONFIG_HOTPLUG_CPU
@@ -795,7 +790,6 @@ void xics_kexec_teardown_cpu(int secondary)
/* Interrupts are disabled. */
void xics_migrate_irqs_away(void)
{
- int status;
int cpu = smp_processor_id(), hw_cpu = hard_smp_processor_id();
unsigned int irq, virq;
@@ -806,10 +800,8 @@ void xics_migrate_irqs_away(void)
/* Reject any interrupt that was queued to us... */
xics_set_cpu_priority(0);
- /* remove ourselves from the global interrupt queue */
- status = rtas_set_indicator_fast(GLOBAL_INTERRUPT_QUEUE,
- (1UL << interrupt_server_size) - 1 - default_distrib_server, 0);
- WARN_ON(status < 0);
+ /* Remove ourselves from the global interrupt queue */
+ xics_set_cpu_giq(default_distrib_server, 0);
/* Allow IPIs again... */
xics_set_cpu_priority(DEFAULT_PRIORITY);
@@ -817,6 +809,7 @@ void xics_migrate_irqs_away(void)
for_each_irq(virq) {
struct irq_desc *desc;
int xics_status[2];
+ int status;
unsigned long flags;
/* We cant set affinity on ISA interrupts */