diff options
Diffstat (limited to 'arch/powerpc/kernel/prom_init.c')
-rw-r--r-- | arch/powerpc/kernel/prom_init.c | 49 |
1 files changed, 43 insertions, 6 deletions
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index 12e656ffe60e..cb64a6e1dc51 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c | |||
@@ -196,6 +196,8 @@ static int __initdata mem_reserve_cnt; | |||
196 | 196 | ||
197 | static cell_t __initdata regbuf[1024]; | 197 | static cell_t __initdata regbuf[1024]; |
198 | 198 | ||
199 | static bool rtas_has_query_cpu_stopped; | ||
200 | |||
199 | 201 | ||
200 | /* | 202 | /* |
201 | * Error results ... some OF calls will return "-1" on error, some | 203 | * Error results ... some OF calls will return "-1" on error, some |
@@ -856,7 +858,8 @@ static void __init prom_send_capabilities(void) | |||
856 | { | 858 | { |
857 | ihandle root; | 859 | ihandle root; |
858 | prom_arg_t ret; | 860 | prom_arg_t ret; |
859 | __be32 *cores; | 861 | u32 cores; |
862 | unsigned char *ptcores; | ||
860 | 863 | ||
861 | root = call_prom("open", 1, 1, ADDR("/")); | 864 | root = call_prom("open", 1, 1, ADDR("/")); |
862 | if (root != 0) { | 865 | if (root != 0) { |
@@ -866,15 +869,30 @@ static void __init prom_send_capabilities(void) | |||
866 | * (we assume this is the same for all cores) and use it to | 869 | * (we assume this is the same for all cores) and use it to |
867 | * divide NR_CPUS. | 870 | * divide NR_CPUS. |
868 | */ | 871 | */ |
869 | cores = (__be32 *)&ibm_architecture_vec[IBM_ARCH_VEC_NRCORES_OFFSET]; | 872 | |
870 | if (be32_to_cpup(cores) != NR_CPUS) { | 873 | /* The core value may start at an odd address. If such a word |
874 | * access is made at a cache line boundary, this leads to an | ||
875 | * exception which may not be handled at this time. | ||
876 | * Forcing a per byte access to avoid exception. | ||
877 | */ | ||
878 | ptcores = &ibm_architecture_vec[IBM_ARCH_VEC_NRCORES_OFFSET]; | ||
879 | cores = 0; | ||
880 | cores |= ptcores[0] << 24; | ||
881 | cores |= ptcores[1] << 16; | ||
882 | cores |= ptcores[2] << 8; | ||
883 | cores |= ptcores[3]; | ||
884 | if (cores != NR_CPUS) { | ||
871 | prom_printf("WARNING ! " | 885 | prom_printf("WARNING ! " |
872 | "ibm_architecture_vec structure inconsistent: %lu!\n", | 886 | "ibm_architecture_vec structure inconsistent: %lu!\n", |
873 | be32_to_cpup(cores)); | 887 | cores); |
874 | } else { | 888 | } else { |
875 | *cores = cpu_to_be32(DIV_ROUND_UP(NR_CPUS, prom_count_smt_threads())); | 889 | cores = DIV_ROUND_UP(NR_CPUS, prom_count_smt_threads()); |
876 | prom_printf("Max number of cores passed to firmware: %lu (NR_CPUS = %lu)\n", | 890 | prom_printf("Max number of cores passed to firmware: %lu (NR_CPUS = %lu)\n", |
877 | be32_to_cpup(cores), NR_CPUS); | 891 | cores, NR_CPUS); |
892 | ptcores[0] = (cores >> 24) & 0xff; | ||
893 | ptcores[1] = (cores >> 16) & 0xff; | ||
894 | ptcores[2] = (cores >> 8) & 0xff; | ||
895 | ptcores[3] = cores & 0xff; | ||
878 | } | 896 | } |
879 | 897 | ||
880 | /* try calling the ibm,client-architecture-support method */ | 898 | /* try calling the ibm,client-architecture-support method */ |
@@ -1574,6 +1592,11 @@ static void __init prom_instantiate_rtas(void) | |||
1574 | prom_setprop(rtas_node, "/rtas", "linux,rtas-entry", | 1592 | prom_setprop(rtas_node, "/rtas", "linux,rtas-entry", |
1575 | &val, sizeof(val)); | 1593 | &val, sizeof(val)); |
1576 | 1594 | ||
1595 | /* Check if it supports "query-cpu-stopped-state" */ | ||
1596 | if (prom_getprop(rtas_node, "query-cpu-stopped-state", | ||
1597 | &val, sizeof(val)) != PROM_ERROR) | ||
1598 | rtas_has_query_cpu_stopped = true; | ||
1599 | |||
1577 | #if defined(CONFIG_PPC_POWERNV) && defined(__BIG_ENDIAN__) | 1600 | #if defined(CONFIG_PPC_POWERNV) && defined(__BIG_ENDIAN__) |
1578 | /* PowerVN takeover hack */ | 1601 | /* PowerVN takeover hack */ |
1579 | prom_rtas_data = base; | 1602 | prom_rtas_data = base; |
@@ -1815,6 +1838,18 @@ static void __init prom_hold_cpus(void) | |||
1815 | = (void *) LOW_ADDR(__secondary_hold_acknowledge); | 1838 | = (void *) LOW_ADDR(__secondary_hold_acknowledge); |
1816 | unsigned long secondary_hold = LOW_ADDR(__secondary_hold); | 1839 | unsigned long secondary_hold = LOW_ADDR(__secondary_hold); |
1817 | 1840 | ||
1841 | /* | ||
1842 | * On pseries, if RTAS supports "query-cpu-stopped-state", | ||
1843 | * we skip this stage, the CPUs will be started by the | ||
1844 | * kernel using RTAS. | ||
1845 | */ | ||
1846 | if ((of_platform == PLATFORM_PSERIES || | ||
1847 | of_platform == PLATFORM_PSERIES_LPAR) && | ||
1848 | rtas_has_query_cpu_stopped) { | ||
1849 | prom_printf("prom_hold_cpus: skipped\n"); | ||
1850 | return; | ||
1851 | } | ||
1852 | |||
1818 | prom_debug("prom_hold_cpus: start...\n"); | 1853 | prom_debug("prom_hold_cpus: start...\n"); |
1819 | prom_debug(" 1) spinloop = 0x%x\n", (unsigned long)spinloop); | 1854 | prom_debug(" 1) spinloop = 0x%x\n", (unsigned long)spinloop); |
1820 | prom_debug(" 1) *spinloop = 0x%x\n", *spinloop); | 1855 | prom_debug(" 1) *spinloop = 0x%x\n", *spinloop); |
@@ -3011,6 +3046,8 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, | |||
3011 | * On non-powermacs, put all CPUs in spin-loops. | 3046 | * On non-powermacs, put all CPUs in spin-loops. |
3012 | * | 3047 | * |
3013 | * PowerMacs use a different mechanism to spin CPUs | 3048 | * PowerMacs use a different mechanism to spin CPUs |
3049 | * | ||
3050 | * (This must be done after instanciating RTAS) | ||
3014 | */ | 3051 | */ |
3015 | if (of_platform != PLATFORM_POWERMAC && | 3052 | if (of_platform != PLATFORM_POWERMAC && |
3016 | of_platform != PLATFORM_OPAL) | 3053 | of_platform != PLATFORM_OPAL) |