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.c49
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
197static cell_t __initdata regbuf[1024]; 197static cell_t __initdata regbuf[1024];
198 198
199static 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)