diff options
-rw-r--r-- | arch/powerpc/platforms/pseries/xics.c | 77 |
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 | ||
163 | static 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 |
165 | static int get_irq_server(unsigned int virq, unsigned int strict_check) | 205 | 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) | |||
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 | ||
661 | void __init xics_init_IRQ(void) | 704 | void __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 | } | ||
713 | skip_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; |