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)) |
