aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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;