diff options
-rw-r--r-- | arch/powerpc/platforms/pseries/xics.c | 68 |
1 files changed, 49 insertions, 19 deletions
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index d071abe78ab1..b5b2b1103de8 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c | |||
@@ -656,13 +656,38 @@ static void __init xics_setup_8259_cascade(void) | |||
656 | set_irq_chained_handler(cascade, pseries_8259_cascade); | 656 | set_irq_chained_handler(cascade, pseries_8259_cascade); |
657 | } | 657 | } |
658 | 658 | ||
659 | static struct device_node *cpuid_to_of_node(int cpu) | ||
660 | { | ||
661 | struct device_node *np; | ||
662 | u32 hcpuid = get_hard_smp_processor_id(cpu); | ||
663 | |||
664 | for_each_node_by_type(np, "cpu") { | ||
665 | int i, len; | ||
666 | const u32 *intserv; | ||
667 | |||
668 | intserv = get_property(np, "ibm,ppc-interrupt-server#s", &len); | ||
669 | |||
670 | if (!intserv) | ||
671 | intserv = get_property(np, "reg", &len); | ||
672 | |||
673 | i = len / sizeof(u32); | ||
674 | |||
675 | while (i--) | ||
676 | if (intserv[i] == hcpuid) | ||
677 | return np; | ||
678 | } | ||
679 | |||
680 | return NULL; | ||
681 | } | ||
682 | |||
659 | void __init xics_init_IRQ(void) | 683 | void __init xics_init_IRQ(void) |
660 | { | 684 | { |
661 | int i; | 685 | int i, j; |
662 | struct device_node *np; | 686 | struct device_node *np; |
663 | u32 ilen, indx = 0; | 687 | u32 ilen, indx = 0; |
664 | const u32 *ireg; | 688 | const u32 *ireg, *isize; |
665 | int found = 0; | 689 | int found = 0; |
690 | u32 hcpuid; | ||
666 | 691 | ||
667 | ppc64_boot_msg(0x20, "XICS Init"); | 692 | ppc64_boot_msg(0x20, "XICS Init"); |
668 | 693 | ||
@@ -683,26 +708,31 @@ void __init xics_init_IRQ(void) | |||
683 | xics_init_host(); | 708 | xics_init_host(); |
684 | 709 | ||
685 | /* Find the server numbers for the boot cpu. */ | 710 | /* Find the server numbers for the boot cpu. */ |
686 | for (np = of_find_node_by_type(NULL, "cpu"); | 711 | np = cpuid_to_of_node(boot_cpuid); |
687 | np; | 712 | BUG_ON(!np); |
688 | np = of_find_node_by_type(np, "cpu")) { | 713 | ireg = get_property(np, "ibm,ppc-interrupt-gserver#s", &ilen); |
689 | ireg = get_property(np, "reg", &ilen); | 714 | if (!ireg) |
690 | if (ireg && ireg[0] == get_hard_smp_processor_id(boot_cpuid)) { | 715 | goto skip_gserver_check; |
691 | ireg = get_property(np, | 716 | i = ilen / sizeof(int); |
692 | "ibm,ppc-interrupt-gserver#s", &ilen); | 717 | hcpuid = get_hard_smp_processor_id(boot_cpuid); |
693 | i = ilen / sizeof(int); | 718 | |
694 | if (ireg && i > 0) { | 719 | /* Global interrupt distribution server is specified in the last |
695 | default_server = ireg[0]; | 720 | * entry of "ibm,ppc-interrupt-gserver#s" property. Get the last |
696 | /* take last element */ | 721 | * entry fom this property for current boot cpu id and use it as |
697 | default_distrib_server = ireg[i-1]; | 722 | * default distribution server |
698 | } | 723 | */ |
699 | ireg = get_property(np, | 724 | for (j = 0; j < i; j += 2) { |
725 | if (ireg[j] == hcpuid) { | ||
726 | default_server = hcpuid; | ||
727 | default_distrib_server = ireg[j+1]; | ||
728 | |||
729 | isize = get_property(np, | ||
700 | "ibm,interrupt-server#-size", NULL); | 730 | "ibm,interrupt-server#-size", NULL); |
701 | if (ireg) | 731 | if (isize) |
702 | interrupt_server_size = *ireg; | 732 | interrupt_server_size = *isize; |
703 | break; | ||
704 | } | 733 | } |
705 | } | 734 | } |
735 | skip_gserver_check: | ||
706 | of_node_put(np); | 736 | of_node_put(np); |
707 | 737 | ||
708 | if (firmware_has_feature(FW_FEATURE_LPAR)) | 738 | if (firmware_has_feature(FW_FEATURE_LPAR)) |