aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorNathan Fontenot <nfont@austin.ibm.com>2008-02-06 15:37:40 -0500
committerPaul Mackerras <paulus@samba.org>2008-02-06 19:40:19 -0500
commitde0723dcca6e593a12a259798a54eb0e82628fb8 (patch)
tree1f0ac73239f572250831d7b632c3e2cd424981a3 /arch
parentb99e62608b5b9f8066629e7403a5f15401049b98 (diff)
[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')
-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)
160 160
161/* High level handlers and init code */ 161/* High level handlers and init code */
162 162
163static void xics_update_irq_servers(void)
164{
165 int i, j;
166 struct device_node *np;
167 u32 ilen;
168 const u32 *ireg, *isize;
169 u32 hcpuid;
170
171 /* Find the server numbers for the boot cpu. */
172 np = of_get_cpu_node(boot_cpuid, NULL);
173 BUG_ON(!np);
174
175 ireg = of_get_property(np, "ibm,ppc-interrupt-gserver#s", &ilen);
176 if (!ireg) {
177 of_node_put(np);
178 return;
179 }
180
181 i = ilen / sizeof(int);
182 hcpuid = get_hard_smp_processor_id(boot_cpuid);
183
184 /* Global interrupt distribution server is specified in the last
185 * entry of "ibm,ppc-interrupt-gserver#s" property. Get the last
186 * entry fom this property for current boot cpu id and use it as
187 * default distribution server
188 */
189 for (j = 0; j < i; j += 2) {
190 if (ireg[j] == hcpuid) {
191 default_server = hcpuid;
192 default_distrib_server = ireg[j+1];
193
194 isize = of_get_property(np,
195 "ibm,interrupt-server#-size", NULL);
196 if (isize)
197 interrupt_server_size = *isize;
198 }
199 }
200
201 of_node_put(np);
202}
163 203
164#ifdef CONFIG_SMP 204#ifdef CONFIG_SMP
165static int get_irq_server(unsigned int virq, unsigned int strict_check) 205static 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)
169 cpumask_t cpumask = irq_desc[virq].affinity; 209 cpumask_t cpumask = irq_desc[virq].affinity;
170 cpumask_t tmp = CPU_MASK_NONE; 210 cpumask_t tmp = CPU_MASK_NONE;
171 211
212 if (! cpu_isset(default_server, cpu_online_map))
213 xics_update_irq_servers();
214
172 if (!distribute_irqs) 215 if (!distribute_irqs)
173 return default_server; 216 return default_server;
174 217
@@ -660,12 +703,9 @@ static void __init xics_setup_8259_cascade(void)
660 703
661void __init xics_init_IRQ(void) 704void __init xics_init_IRQ(void)
662{ 705{
663 int i, j;
664 struct device_node *np; 706 struct device_node *np;
665 u32 ilen, indx = 0; 707 u32 indx = 0;
666 const u32 *ireg, *isize;
667 int found = 0; 708 int found = 0;
668 u32 hcpuid;
669 709
670 ppc64_boot_msg(0x20, "XICS Init"); 710 ppc64_boot_msg(0x20, "XICS Init");
671 711
@@ -684,34 +724,7 @@ void __init xics_init_IRQ(void)
684 return; 724 return;
685 725
686 xics_init_host(); 726 xics_init_host();
687 727 xics_update_irq_servers();
688 /* Find the server numbers for the boot cpu. */
689 np = of_get_cpu_node(boot_cpuid, NULL);
690 BUG_ON(!np);
691 ireg = of_get_property(np, "ibm,ppc-interrupt-gserver#s", &ilen);
692 if (!ireg)
693 goto skip_gserver_check;
694 i = ilen / sizeof(int);
695 hcpuid = get_hard_smp_processor_id(boot_cpuid);
696
697 /* Global interrupt distribution server is specified in the last
698 * entry of "ibm,ppc-interrupt-gserver#s" property. Get the last
699 * entry fom this property for current boot cpu id and use it as
700 * default distribution server
701 */
702 for (j = 0; j < i; j += 2) {
703 if (ireg[j] == hcpuid) {
704 default_server = hcpuid;
705 default_distrib_server = ireg[j+1];
706
707 isize = of_get_property(np,
708 "ibm,interrupt-server#-size", NULL);
709 if (isize)
710 interrupt_server_size = *isize;
711 }
712 }
713skip_gserver_check:
714 of_node_put(np);
715 728
716 if (firmware_has_feature(FW_FEATURE_LPAR)) 729 if (firmware_has_feature(FW_FEATURE_LPAR))
717 ppc_md.get_irq = xics_get_irq_lpar; 730 ppc_md.get_irq = xics_get_irq_lpar;