diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2010-02-03 22:33:54 -0500 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2010-02-03 22:33:54 -0500 |
commit | efec959f63de850fbd2442189f7dfc9c38efe251 (patch) | |
tree | 63824395c5ddb427cbcd115f975154b09ebb1334 /arch/powerpc/kernel/prom_init.c | |
parent | 28bb9ee13aa0ee4c57dc3568f539cc84920b43aa (diff) |
powerpc/pseries: Pass more accurate number of supported cores to firmware
Updated variant of a patch by Joel Schopp.
The field containing the number of supported cores which we pass to
firmware via the ibm,client-architecture call was set by a previous
patch statically as high as is possible (NR_CPUS).
However, that value isn't quite right for a system that supports
multiple threads per core, thus permitting the firmware to assign
more cores to a Linux partition than it can really cope with.
This patch improves it by using the device-tree to determine the
number of threads supported by the processors in order to adjust
the value passed to firmware.
Signed-off-by: Joel Schopp <jschopp@austin.ibm.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/kernel/prom_init.c')
-rw-r--r-- | arch/powerpc/kernel/prom_init.c | 64 |
1 files changed, 63 insertions, 1 deletions
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index 59d5bd1c064d..5f306c4946e5 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c | |||
@@ -710,7 +710,12 @@ static unsigned char ibm_architecture_vec[] = { | |||
710 | 0, | 710 | 0, |
711 | 0, | 711 | 0, |
712 | 0, | 712 | 0, |
713 | W(NR_CPUS), /* number of cores supported*/ | 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 */ | ||
714 | 719 | ||
715 | /* option vector 6: IBM PAPR hints */ | 720 | /* option vector 6: IBM PAPR hints */ |
716 | 4 - 2, /* length */ | 721 | 4 - 2, /* length */ |
@@ -807,13 +812,70 @@ static struct fake_elf { | |||
807 | } | 812 | } |
808 | }; | 813 | }; |
809 | 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 | |||
810 | static void __init prom_send_capabilities(void) | 854 | static void __init prom_send_capabilities(void) |
811 | { | 855 | { |
812 | ihandle elfloader, root; | 856 | ihandle elfloader, root; |
813 | prom_arg_t ret; | 857 | prom_arg_t ret; |
858 | u32 *cores; | ||
814 | 859 | ||
815 | root = call_prom("open", 1, 1, ADDR("/")); | 860 | root = call_prom("open", 1, 1, ADDR("/")); |
816 | 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 | |||
817 | /* try calling the ibm,client-architecture-support method */ | 879 | /* try calling the ibm,client-architecture-support method */ |
818 | prom_printf("Calling ibm,client-architecture-support..."); | 880 | prom_printf("Calling ibm,client-architecture-support..."); |
819 | if (call_prom_ret("call-method", 3, 2, &ret, | 881 | if (call_prom_ret("call-method", 3, 2, &ret, |