diff options
Diffstat (limited to 'arch/powerpc/kernel/prom_init.c')
-rw-r--r-- | arch/powerpc/kernel/prom_init.c | 81 |
1 files changed, 79 insertions, 2 deletions
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index bafac2e41ae1..5f306c4946e5 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c | |||
@@ -654,6 +654,9 @@ static void __init early_cmdline_parse(void) | |||
654 | #define OV5_CMO 0x00 | 654 | #define OV5_CMO 0x00 |
655 | #endif | 655 | #endif |
656 | 656 | ||
657 | /* Option Vector 6: IBM PAPR hints */ | ||
658 | #define OV6_LINUX 0x02 /* Linux is our OS */ | ||
659 | |||
657 | /* | 660 | /* |
658 | * The architecture vector has an array of PVR mask/value pairs, | 661 | * The architecture vector has an array of PVR mask/value pairs, |
659 | * followed by # option vectors - 1, followed by the option vectors. | 662 | * followed by # option vectors - 1, followed by the option vectors. |
@@ -665,7 +668,7 @@ static unsigned char ibm_architecture_vec[] = { | |||
665 | W(0xffffffff), W(0x0f000003), /* all 2.06-compliant */ | 668 | W(0xffffffff), W(0x0f000003), /* all 2.06-compliant */ |
666 | W(0xffffffff), W(0x0f000002), /* all 2.05-compliant */ | 669 | W(0xffffffff), W(0x0f000002), /* all 2.05-compliant */ |
667 | W(0xfffffffe), W(0x0f000001), /* all 2.04-compliant and earlier */ | 670 | W(0xfffffffe), W(0x0f000001), /* all 2.04-compliant and earlier */ |
668 | 5 - 1, /* 5 option vectors */ | 671 | 6 - 1, /* 6 option vectors */ |
669 | 672 | ||
670 | /* option vector 1: processor architectures supported */ | 673 | /* option vector 1: processor architectures supported */ |
671 | 3 - 2, /* length */ | 674 | 3 - 2, /* length */ |
@@ -697,12 +700,29 @@ static unsigned char ibm_architecture_vec[] = { | |||
697 | 0, /* don't halt */ | 700 | 0, /* don't halt */ |
698 | 701 | ||
699 | /* option vector 5: PAPR/OF options */ | 702 | /* option vector 5: PAPR/OF options */ |
700 | 5 - 2, /* length */ | 703 | 13 - 2, /* length */ |
701 | 0, /* don't ignore, don't halt */ | 704 | 0, /* don't ignore, don't halt */ |
702 | OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY | | 705 | OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY | |
703 | OV5_DONATE_DEDICATE_CPU | OV5_MSI, | 706 | OV5_DONATE_DEDICATE_CPU | OV5_MSI, |
704 | 0, | 707 | 0, |
705 | OV5_CMO, | 708 | OV5_CMO, |
709 | 0, | ||
710 | 0, | ||
711 | 0, | ||
712 | 0, | ||
713 | /* WARNING: The offset of the "number of cores" field below | ||
714 | * must match by the macro below. Update the definition if | ||
715 | * the structure layout changes. | ||
716 | */ | ||
717 | #define IBM_ARCH_VEC_NRCORES_OFFSET 100 | ||
718 | W(NR_CPUS), /* number of cores supported */ | ||
719 | |||
720 | /* option vector 6: IBM PAPR hints */ | ||
721 | 4 - 2, /* length */ | ||
722 | 0, | ||
723 | 0, | ||
724 | OV6_LINUX, | ||
725 | |||
706 | }; | 726 | }; |
707 | 727 | ||
708 | /* Old method - ELF header with PT_NOTE sections */ | 728 | /* Old method - ELF header with PT_NOTE sections */ |
@@ -792,13 +812,70 @@ static struct fake_elf { | |||
792 | } | 812 | } |
793 | }; | 813 | }; |
794 | 814 | ||
815 | static int __init prom_count_smt_threads(void) | ||
816 | { | ||
817 | phandle node; | ||
818 | char type[64]; | ||
819 | unsigned int plen; | ||
820 | |||
821 | /* Pick up th first CPU node we can find */ | ||
822 | for (node = 0; prom_next_node(&node); ) { | ||
823 | type[0] = 0; | ||
824 | prom_getprop(node, "device_type", type, sizeof(type)); | ||
825 | |||
826 | if (strcmp(type, RELOC("cpu"))) | ||
827 | continue; | ||
828 | /* | ||
829 | * There is an entry for each smt thread, each entry being | ||
830 | * 4 bytes long. All cpus should have the same number of | ||
831 | * smt threads, so return after finding the first. | ||
832 | */ | ||
833 | plen = prom_getproplen(node, "ibm,ppc-interrupt-server#s"); | ||
834 | if (plen == PROM_ERROR) | ||
835 | break; | ||
836 | plen >>= 2; | ||
837 | prom_debug("Found 0x%x smt threads per core\n", (unsigned long)plen); | ||
838 | |||
839 | /* Sanity check */ | ||
840 | if (plen < 1 || plen > 64) { | ||
841 | prom_printf("Threads per core 0x%x out of bounds, assuming 1\n", | ||
842 | (unsigned long)plen); | ||
843 | return 1; | ||
844 | } | ||
845 | return plen; | ||
846 | } | ||
847 | prom_debug("No threads found, assuming 1 per core\n"); | ||
848 | |||
849 | return 1; | ||
850 | |||
851 | } | ||
852 | |||
853 | |||
795 | static void __init prom_send_capabilities(void) | 854 | static void __init prom_send_capabilities(void) |
796 | { | 855 | { |
797 | ihandle elfloader, root; | 856 | ihandle elfloader, root; |
798 | prom_arg_t ret; | 857 | prom_arg_t ret; |
858 | u32 *cores; | ||
799 | 859 | ||
800 | root = call_prom("open", 1, 1, ADDR("/")); | 860 | root = call_prom("open", 1, 1, ADDR("/")); |
801 | if (root != 0) { | 861 | if (root != 0) { |
862 | /* We need to tell the FW about the number of cores we support. | ||
863 | * | ||
864 | * To do that, we count the number of threads on the first core | ||
865 | * (we assume this is the same for all cores) and use it to | ||
866 | * divide NR_CPUS. | ||
867 | */ | ||
868 | cores = (u32 *)PTRRELOC(&ibm_architecture_vec[IBM_ARCH_VEC_NRCORES_OFFSET]); | ||
869 | if (*cores != NR_CPUS) { | ||
870 | prom_printf("WARNING ! " | ||
871 | "ibm_architecture_vec structure inconsistent: 0x%x !\n", | ||
872 | *cores); | ||
873 | } else { | ||
874 | *cores = NR_CPUS / prom_count_smt_threads(); | ||
875 | prom_printf("Max number of cores passed to firmware: 0x%x\n", | ||
876 | (unsigned long)*cores); | ||
877 | } | ||
878 | |||
802 | /* try calling the ibm,client-architecture-support method */ | 879 | /* try calling the ibm,client-architecture-support method */ |
803 | prom_printf("Calling ibm,client-architecture-support..."); | 880 | prom_printf("Calling ibm,client-architecture-support..."); |
804 | if (call_prom_ret("call-method", 3, 2, &ret, | 881 | if (call_prom_ret("call-method", 3, 2, &ret, |