aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorNathan Fontenot <nfont@austin.ibm.com>2008-02-07 07:37:40 +1100
committerPaul Mackerras <paulus@samba.org>2008-02-07 11:40:19 +1100
commitde0723dcca6e593a12a259798a54eb0e82628fb8 (patch)
tree1f0ac73239f572250831d7b632c3e2cd424981a3 /arch/powerpc
parent[POWERPC] Remove redundant of_get_cpu_node routine (diff)
downloadlinux-dev-de0723dcca6e593a12a259798a54eb0e82628fb8.tar.xz
linux-dev-de0723dcca6e593a12a259798a54eb0e82628fb8.zip
[POWERPC] Update default irq servers when boot cpu is removed
The xics code does update the default server information when the boot cpu is removed. This patch recognizes when the boot cpu is being removed and updates the appropriate information based on the new 'boot cpu'. Failure to update this information can causes us to leave irqs pinned to cpus that are being removed, especially when removing the boot cpu. The cpu is removed from the kernel, but cpu dlpar remove operations fail since we cannot return the cpu to the hypervisor. Signed-off-by: Nathan Fonteno <nfont@austin.ibm.com> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/platforms/pseries/xics.c77
1 files changed, 45 insertions, 32 deletions
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index 9ecf75fe9b14..ca52b587166d 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -160,6 +160,46 @@ static inline void lpar_qirr_info(int n_cpu , u8 value)
/* High level handlers and init code */
+static void xics_update_irq_servers(void)
+{
+ int i, j;
+ struct device_node *np;
+ u32 ilen;
+ const u32 *ireg, *isize;
+ u32 hcpuid;
+
+ /* Find the server numbers for the boot cpu. */
+ np = of_get_cpu_node(boot_cpuid, NULL);
+ BUG_ON(!np);
+
+ ireg = of_get_property(np, "ibm,ppc-interrupt-gserver#s", &ilen);
+ if (!ireg) {
+ of_node_put(np);
+ return;
+ }
+
+ i = ilen / sizeof(int);
+ hcpuid = get_hard_smp_processor_id(boot_cpuid);
+
+ /* Global interrupt distribution server is specified in the last
+ * entry of "ibm,ppc-interrupt-gserver#s" property. Get the last
+ * entry fom this property for current boot cpu id and use it as
+ * default distribution server
+ */
+ for (j = 0; j < i; j += 2) {
+ if (ireg[j] == hcpuid) {
+ default_server = hcpuid;
+ default_distrib_server = ireg[j+1];
+
+ isize = of_get_property(np,
+ "ibm,interrupt-server#-size", NULL);
+ if (isize)
+ interrupt_server_size = *isize;
+ }
+ }
+
+ of_node_put(np);
+}
#ifdef CONFIG_SMP
static int get_irq_server(unsigned int virq, unsigned int strict_check)
@@ -169,6 +209,9 @@ static int get_irq_server(unsigned int virq, unsigned int strict_check)
cpumask_t cpumask = irq_desc[virq].affinity;
cpumask_t tmp = CPU_MASK_NONE;
+ if (! cpu_isset(default_server, cpu_online_map))
+ xics_update_irq_servers();
+
if (!distribute_irqs)
return default_server;
@@ -660,12 +703,9 @@ static void __init xics_setup_8259_cascade(void)
void __init xics_init_IRQ(void)
{
- int i, j;
struct device_node *np;
- u32 ilen, indx = 0;
- const u32 *ireg, *isize;
+ u32 indx = 0;
int found = 0;
- u32 hcpuid;
ppc64_boot_msg(0x20, "XICS Init");
@@ -684,34 +724,7 @@ void __init xics_init_IRQ(void)
return;
xics_init_host();
-
- /* Find the server numbers for the boot cpu. */
- np = of_get_cpu_node(boot_cpuid, NULL);
- BUG_ON(!np);
- ireg = of_get_property(np, "ibm,ppc-interrupt-gserver#s", &ilen);
- if (!ireg)
- goto skip_gserver_check;
- i = ilen / sizeof(int);
- hcpuid = get_hard_smp_processor_id(boot_cpuid);
-
- /* Global interrupt distribution server is specified in the last
- * entry of "ibm,ppc-interrupt-gserver#s" property. Get the last
- * entry fom this property for current boot cpu id and use it as
- * default distribution server
- */
- for (j = 0; j < i; j += 2) {
- if (ireg[j] == hcpuid) {
- default_server = hcpuid;
- default_distrib_server = ireg[j+1];
-
- isize = of_get_property(np,
- "ibm,interrupt-server#-size", NULL);
- if (isize)
- interrupt_server_size = *isize;
- }
- }
-skip_gserver_check:
- of_node_put(np);
+ xics_update_irq_servers();
if (firmware_has_feature(FW_FEATURE_LPAR))
ppc_md.get_irq = xics_get_irq_lpar;