aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/prom_init.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/prom_init.c')
-rw-r--r--arch/powerpc/kernel/prom_init.c81
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
815static 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
795static void __init prom_send_capabilities(void) 854static 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,