aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/pseries/xics.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/platforms/pseries/xics.c')
-rw-r--r--arch/powerpc/platforms/pseries/xics.c73
1 files changed, 51 insertions, 22 deletions
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index d071abe78ab1..81d172d65038 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -224,7 +224,6 @@ static void xics_unmask_irq(unsigned int virq)
224static void xics_mask_real_irq(unsigned int irq) 224static void xics_mask_real_irq(unsigned int irq)
225{ 225{
226 int call_status; 226 int call_status;
227 unsigned int server;
228 227
229 if (irq == XICS_IPI) 228 if (irq == XICS_IPI)
230 return; 229 return;
@@ -236,9 +235,9 @@ static void xics_mask_real_irq(unsigned int irq)
236 return; 235 return;
237 } 236 }
238 237
239 server = get_irq_server(irq);
240 /* Have to set XIVE to 0xff to be able to remove a slot */ 238 /* Have to set XIVE to 0xff to be able to remove a slot */
241 call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server, 0xff); 239 call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq,
240 default_server, 0xff);
242 if (call_status != 0) { 241 if (call_status != 0) {
243 printk(KERN_ERR "xics_disable_irq: irq=%u: ibm_set_xive(0xff)" 242 printk(KERN_ERR "xics_disable_irq: irq=%u: ibm_set_xive(0xff)"
244 " returned %d\n", irq, call_status); 243 " returned %d\n", irq, call_status);
@@ -656,13 +655,38 @@ static void __init xics_setup_8259_cascade(void)
656 set_irq_chained_handler(cascade, pseries_8259_cascade); 655 set_irq_chained_handler(cascade, pseries_8259_cascade);
657} 656}
658 657
658static struct device_node *cpuid_to_of_node(int cpu)
659{
660 struct device_node *np;
661 u32 hcpuid = get_hard_smp_processor_id(cpu);
662
663 for_each_node_by_type(np, "cpu") {
664 int i, len;
665 const u32 *intserv;
666
667 intserv = get_property(np, "ibm,ppc-interrupt-server#s", &len);
668
669 if (!intserv)
670 intserv = get_property(np, "reg", &len);
671
672 i = len / sizeof(u32);
673
674 while (i--)
675 if (intserv[i] == hcpuid)
676 return np;
677 }
678
679 return NULL;
680}
681
659void __init xics_init_IRQ(void) 682void __init xics_init_IRQ(void)
660{ 683{
661 int i; 684 int i, j;
662 struct device_node *np; 685 struct device_node *np;
663 u32 ilen, indx = 0; 686 u32 ilen, indx = 0;
664 const u32 *ireg; 687 const u32 *ireg, *isize;
665 int found = 0; 688 int found = 0;
689 u32 hcpuid;
666 690
667 ppc64_boot_msg(0x20, "XICS Init"); 691 ppc64_boot_msg(0x20, "XICS Init");
668 692
@@ -683,26 +707,31 @@ void __init xics_init_IRQ(void)
683 xics_init_host(); 707 xics_init_host();
684 708
685 /* Find the server numbers for the boot cpu. */ 709 /* Find the server numbers for the boot cpu. */
686 for (np = of_find_node_by_type(NULL, "cpu"); 710 np = cpuid_to_of_node(boot_cpuid);
687 np; 711 BUG_ON(!np);
688 np = of_find_node_by_type(np, "cpu")) { 712 ireg = get_property(np, "ibm,ppc-interrupt-gserver#s", &ilen);
689 ireg = get_property(np, "reg", &ilen); 713 if (!ireg)
690 if (ireg && ireg[0] == get_hard_smp_processor_id(boot_cpuid)) { 714 goto skip_gserver_check;
691 ireg = get_property(np, 715 i = ilen / sizeof(int);
692 "ibm,ppc-interrupt-gserver#s", &ilen); 716 hcpuid = get_hard_smp_processor_id(boot_cpuid);
693 i = ilen / sizeof(int); 717
694 if (ireg && i > 0) { 718 /* Global interrupt distribution server is specified in the last
695 default_server = ireg[0]; 719 * entry of "ibm,ppc-interrupt-gserver#s" property. Get the last
696 /* take last element */ 720 * entry fom this property for current boot cpu id and use it as
697 default_distrib_server = ireg[i-1]; 721 * default distribution server
698 } 722 */
699 ireg = get_property(np, 723 for (j = 0; j < i; j += 2) {
724 if (ireg[j] == hcpuid) {
725 default_server = hcpuid;
726 default_distrib_server = ireg[j+1];
727
728 isize = get_property(np,
700 "ibm,interrupt-server#-size", NULL); 729 "ibm,interrupt-server#-size", NULL);
701 if (ireg) 730 if (isize)
702 interrupt_server_size = *ireg; 731 interrupt_server_size = *isize;
703 break;
704 } 732 }
705 } 733 }
734skip_gserver_check:
706 of_node_put(np); 735 of_node_put(np);
707 736
708 if (firmware_has_feature(FW_FEATURE_LPAR)) 737 if (firmware_has_feature(FW_FEATURE_LPAR))