From: Magnus Karlsson <[email protected]> This is a port of commit 2445bd5ff062fb45c03a4e50edd014e7d4fd885c from linux-yocto-3.10, branch standard/axxia/base, that reverts c6bc0772d9fff6571364dedfe0bf05b122d3b5c2 from the same branch.
Signed-off-by: Magnus Karlsson <[email protected]> --- arch/arm/mach-axxia/hotplug.c | 36 +++--- arch/arm/mach-axxia/lsi_power_management.c | 191 +++++++++++----------------- arch/arm/mach-axxia/lsi_power_management.h | 9 +- arch/arm/mach-axxia/platsmp.c | 39 +++--- 4 files changed, 118 insertions(+), 157 deletions(-) diff --git a/arch/arm/mach-axxia/hotplug.c b/arch/arm/mach-axxia/hotplug.c index 5def7c3..8878346 100644 --- a/arch/arm/mach-axxia/hotplug.c +++ b/arch/arm/mach-axxia/hotplug.c @@ -85,19 +85,13 @@ static inline void pm_L2_logical_shutdown(u32 cpu) : "Ir" (0x400) : "cc"); - asm volatile( - " mrc p15, 1, %0, c15, c0, 4\n" - " orr %0, %0, %1\n" - " mcr p15, 1, %0, c15, c0, 4\n" - : "=&r" (val) - : "Ir" (0x1) - : "cc"); - isb(); dsb(); + /* Clear and invalidate all L1 and L2 data cache */ flush_cache_all(); + /* Turn the DBG Double Lock quiet */ asm volatile( /* @@ -169,8 +163,6 @@ static inline void cpu_leave_lowpower(void) : "=&r" (v) : "Ir" (CR_C), "Ir" (0x40) : "cc"); - isb(); - dsb(); } static void __ref platform_do_lowpower(unsigned int cpu, int *spurious) @@ -197,9 +189,9 @@ static void __ref platform_do_lowpower(unsigned int cpu, int *spurious) phys_cpu = cluster + (phys_cpu % 4); if (pen_release == phys_cpu) { - /* - * OK, proper wakeup, we're done - */ + /* + * OK, proper wakeup, we're done + */ break; } @@ -219,9 +211,7 @@ int axxia_platform_cpu_kill(unsigned int cpu) { #ifdef CONFIG_HOTPLUG_CPU_COMPLETE_POWER_DOWN - get_cpu(); pm_cpu_shutdown(cpu); - put_cpu(); #endif return 1; } @@ -237,6 +227,21 @@ void axxia_platform_cpu_die(unsigned int cpu) #ifdef CONFIG_HOTPLUG_CPU_COMPLETE_POWER_DOWN bool last_cpu; + int timeout; + timeout = 30; + + /* make sure no migrations are happening */ + while (!axxia_is_empty(&axxia_circ_q)) { + + if (timeout-- == 0) + break; + + mdelay(1); + } + + if (timeout == 0) + pr_err("ERROR: tried to shut down and Q was still full\n"); + last_cpu = pm_cpu_last_of_cluster(cpu); if (last_cpu) pm_L2_logical_shutdown(cpu); @@ -246,6 +251,7 @@ void axxia_platform_cpu_die(unsigned int cpu) for (;;) wfi(); + #else /* CPU low power mode */ int spurious = 0; diff --git a/arch/arm/mach-axxia/lsi_power_management.c b/arch/arm/mach-axxia/lsi_power_management.c index dbf35e2..93e8ac9 100644 --- a/arch/arm/mach-axxia/lsi_power_management.c +++ b/arch/arm/mach-axxia/lsi_power_management.c @@ -53,13 +53,6 @@ PORESET_CLUSTER1, PORESET_CLUSTER2, PORESET_CLUSTER3 }; -static const u32 cluster_to_mask[MAX_CLUSTER] = { - IPI0_MASK, - IPI1_MASK, - IPI2_MASK, - IPI3_MASK -}; - static const u32 ipi_register[MAX_IPI] = { NCP_SYSCON_MASK_IPI0, NCP_SYSCON_MASK_IPI1, @@ -99,7 +92,6 @@ u32 pm_cpu_powered_down; /*======================= LOCAL FUNCTIONS ==============================*/ static void pm_set_bits_syscon_register(u32 reg, u32 data); -static void pm_or_bits_syscon_register(u32 reg, u32 data); static void pm_clear_bits_syscon_register(u32 reg, u32 data); static bool pm_test_for_bit_with_timeout(u32 reg, u32 bit); static bool pm_wait_for_bit_clear_with_timeout(u32 reg, @@ -245,11 +237,6 @@ bool pm_cpu_last_of_cluster(u32 cpu) static void pm_set_bits_syscon_register(u32 reg, u32 data) { - writel(data, syscon + reg); -} - -static void pm_or_bits_syscon_register(u32 reg, u32 data) -{ u32 tmp; tmp = readl(syscon + reg); @@ -257,7 +244,6 @@ static void pm_or_bits_syscon_register(u32 reg, u32 data) writel(tmp, syscon + reg); } - static void pm_clear_bits_syscon_register(u32 reg, u32 data) { u32 tmp; @@ -433,25 +419,23 @@ dickens_power_up: return rval; } -static void pm_disable_ipi_interrupts(u32 cpu) -{ - pm_clear_bits_syscon_register(ipi_register[cpu], IPI_IRQ_MASK); -} - -static void pm_enable_ipi_interrupts(u32 cpu) +static int pm_enable_ipi_interrupts(u32 cpu) { u32 i; + u32 cpumask = 1 << cpu; u32 powered_on_cpu = (~(pm_cpu_powered_down) & IPI_IRQ_MASK); + /* Enable the CPU IPI */ pm_set_bits_syscon_register(ipi_register[cpu], powered_on_cpu); - for (i = 0; i < MAX_CPUS; i++) { + for (i = 0; i < MAX_IPI; i++) { if ((1 << i) & powered_on_cpu) - pm_or_bits_syscon_register(ipi_register[i], (1 << cpu)); + pm_set_bits_syscon_register(ipi_register[i], cpumask); } - return; + return 0; + } void pm_init_syscon(void) @@ -499,7 +483,7 @@ void pm_cpu_shutdown(u32 cpu) if (last_cpu) { /* Disable all the interrupts to the cluster gic */ - pm_or_bits_syscon_register(NCP_SYSCON_GIC_DISABLE, cluster_mask); + pm_set_bits_syscon_register(NCP_SYSCON_GIC_DISABLE, cluster_mask); /* Remove the cluster from the Dickens coherency domain */ pm_dickens_logical_shutdown(cluster); @@ -517,7 +501,7 @@ void pm_cpu_shutdown(u32 cpu) } /* Turn off the ACE */ - pm_or_bits_syscon_register(NCP_SYSCON_PWR_ACEPWRDNRQ, cluster_mask); + pm_set_bits_syscon_register(NCP_SYSCON_PWR_ACEPWRDNRQ, cluster_mask); /* Wait for ACE to complete power off */ success = pm_wait_for_bit_clear_with_timeout(NCP_SYSCON_PWR_NACEPWRDNACK, cluster); @@ -528,7 +512,7 @@ void pm_cpu_shutdown(u32 cpu) } /* Isolate the cluster */ - pm_or_bits_syscon_register(NCP_SYSCON_PWR_ISOLATEL2MISC, cluster_mask); + pm_set_bits_syscon_register(NCP_SYSCON_PWR_ISOLATEL2MISC, cluster_mask); /* Wait for WFI L2 to go to standby */ success = pm_test_for_bit_with_timeout(NCP_SYSCON_PWR_STANDBYWFIL2, cluster); @@ -571,10 +555,21 @@ int pm_cpu_powerup(u32 cpu) u32 reqcpu = cpu_logical_map(cpu); u32 cluster = reqcpu / CORES_PER_CLUSTER; u32 cluster_mask = (0x01 << cluster); + u32 timeout; pm_init_syscon(); /* + * The key value has to be written before the CPU RST can be written. + */ + pm_set_bits_syscon_register(NCP_SYSCON_KEY, VALID_KEY_VALUE); + pm_set_bits_syscon_register(NCP_SYSCON_PWRUP_CPU_RST, cpu_mask); + + /* Hold the CPU in reset */ + pm_set_bits_syscon_register(NCP_SYSCON_KEY, VALID_KEY_VALUE); + pm_set_bits_syscon_register(NCP_SYSCON_HOLD_CPU, cpu_mask); + + /* * Is this the first cpu of a cluster to come back on? * Then power up the L2 cache. */ @@ -586,19 +581,10 @@ int pm_cpu_powerup(u32 cpu) pr_err("CPU: Failed the logical L2 power up\n"); goto pm_power_up; } - cluster_power_up[cluster] = true; pm_clear_bits_syscon_register(NCP_SYSCON_GIC_DISABLE, cluster_mask); - - - } - else { - /* Set the CPU into reset */ - pm_set_bits_syscon_register(NCP_SYSCON_KEY, VALID_KEY_VALUE); - pm_or_bits_syscon_register(NCP_SYSCON_PWRUP_CPU_RST, cpu_mask); - + cluster_power_up[cluster] = true; } - /* * Power up the CPU */ @@ -608,6 +594,22 @@ int pm_cpu_powerup(u32 cpu) goto pm_power_up; } + timeout = 30; + + /* wait max 10 ms until cpuX is on */ + while (!pm_cpu_active(cpu)) { + + if (timeout-- == 0) + break; + + mdelay(1); + } + + if (timeout == 0) { + rval = -ETIMEDOUT; + goto pm_power_up; + } + /* * The key value must be written before the CPU RST can be written. */ @@ -615,6 +617,12 @@ int pm_cpu_powerup(u32 cpu) pm_clear_bits_syscon_register(NCP_SYSCON_PWRUP_CPU_RST, cpu_mask); /* + * The key value must be written before HOLD CPU can be written. + */ + pm_set_bits_syscon_register(NCP_SYSCON_KEY, VALID_KEY_VALUE); + pm_clear_bits_syscon_register(NCP_SYSCON_HOLD_CPU, cpu_mask); + + /* * Clear the powered down mask */ pm_cpu_powered_down &= ~(1 << cpu); @@ -622,9 +630,8 @@ int pm_cpu_powerup(u32 cpu) /* Enable the CPU IPI */ pm_enable_ipi_interrupts(cpu); - - pm_power_up: + iounmap(syscon); return rval; } @@ -646,61 +653,19 @@ inline void pm_cpu_logical_powerup(void) " mrc p15, 0, %0, c1, c0, 0\n" " orr %0, %0, %2\n" " mcr p15, 0, %0, c1, c0, 0\n" + " mrc p15, 0, %0, c1, c0, 1\n" + " orr %0, %0, %3\n" + " mcr p15, 0, %0, c1, c0, 1\n" : "=&r" (v) - : "Ir" (CR_C), "Ir" (CR_I) + : "Ir" (CR_C), "Ir" (CR_I), "Ir" (0x40) : "cc"); - /* - * Iniitalize the ACTLR2 register (all cores). - */ - asm volatile( - " mrc p15, 1, %0, c15, c0, 4\n" - " bic %0, %0, %1\n" - " mcr p15, 1, %0, c15, c0, 4\n" + " mrc p15, 1, %0, c9, c0, 2\n" : "=&r" (v) : "Ir" (0x1) : "cc"); - isb(); - dsb(); -} - -inline void pm_cluster_logical_powerup(void) -{ - unsigned int v; - - /* - * Initialize the L2CTLR register (primary core in each cluster). - */ - asm volatile( - " mrc p15, 1, %0, c9, c0, 2\n" - " orr %0, %0, %1\n" - " orr %0, %0, %2\n" - " mcr p15, 1, %0, c9, c0, 2" - : "=&r" (v) - : "Ir" (0x01), "Ir" (0x1 << 21) - : "cc"); - isb(); - dsb(); - - /* - * Initialize the L2ACTLR register (primary core in each cluster). - */ - asm volatile( - " mrc p15, 1, r0, c15, c0, 0\n" - " orr %0, %0, %1\n" - " orr %0, %0, %2\n" - " orr %0, %0, %3\n" - " orr %0, %0, %4\n" - " orr %0, %0, %5\n" - " mcr p15, 1, %0, c15, c0, 0" - : "=&r" (v) - : "Ir" (0x1 << 3), "Ir" (0x1 << 7), "Ir" (0x1 << 12), "Ir" (0x1 << 13), "Ir" (0x1 << 14) - : "cc"); - isb(); - dsb(); - } static int pm_cpu_physical_isolation_and_power_down(int cpu) @@ -712,7 +677,7 @@ static int pm_cpu_physical_isolation_and_power_down(int cpu) u32 mask = (0x01 << cpu); /* Disable the CPU IPI */ - pm_disable_ipi_interrupts(cpu); + pm_clear_bits_syscon_register(ipi_register[cpu], IPI_IRQ_MASK); /* Initiate power down of the CPU's HS Rams */ pm_clear_bits_syscon_register(NCP_SYSCON_PWR_PWRUPCPURAM, mask); @@ -726,12 +691,12 @@ static int pm_cpu_physical_isolation_and_power_down(int cpu) } /* Activate the CPU's isolation clamps */ - pm_or_bits_syscon_register(NCP_SYSCON_PWR_ISOLATECPU, mask); + pm_set_bits_syscon_register(NCP_SYSCON_PWR_ISOLATECPU, mask); /* Initiate power down of the CPU logic */ pm_clear_bits_syscon_register(NCP_SYSCON_PWR_PWRUPCPUSTG2, mask); - udelay(16); + udelay(10); /* Continue power down of the CPU logic */ pm_clear_bits_syscon_register(NCP_SYSCON_PWR_PWRUPCPUSTG1, mask); @@ -756,7 +721,7 @@ static int pm_cpu_physical_connection_and_power_up(int cpu) u32 mask = (0x01 << cpu); /* Initiate power up of the CPU */ - pm_or_bits_syscon_register(NCP_SYSCON_PWR_PWRUPCPUSTG1, mask); + pm_set_bits_syscon_register(NCP_SYSCON_PWR_PWRUPCPUSTG1, mask); /* Wait until CPU logic power is compete */ success = pm_wait_for_bit_clear_with_timeout(NCP_SYSCON_PWR_NPWRUPCPUSTG1_ACK, cpu); @@ -767,12 +732,12 @@ static int pm_cpu_physical_connection_and_power_up(int cpu) } /* Continue stage 2 power up of the CPU*/ - pm_or_bits_syscon_register(NCP_SYSCON_PWR_PWRUPCPUSTG2, mask); + pm_set_bits_syscon_register(NCP_SYSCON_PWR_PWRUPCPUSTG2, mask); - udelay(16); + udelay(20); /* Initiate power up of HS Rams */ - pm_or_bits_syscon_register(NCP_SYSCON_PWR_PWRUPCPURAM, mask); + pm_set_bits_syscon_register(NCP_SYSCON_PWR_PWRUPCPURAM, mask); /* Wait until the RAM power up is complete */ success = pm_wait_for_bit_clear_with_timeout(NCP_SYSCON_PWR_NPWRUPCPURAM_ACK, cpu); @@ -785,8 +750,6 @@ static int pm_cpu_physical_connection_and_power_up(int cpu) /* Release the CPU's isolation clamps */ pm_clear_bits_syscon_register(NCP_SYSCON_PWR_ISOLATECPU, mask); - udelay(16); - power_up_cleanup: @@ -801,7 +764,7 @@ static void pm_L2_isolation_and_power_down(int cluster) u32 mask = (0x1 << cluster); /* Enable the chip select for the cluster */ - pm_or_bits_syscon_register(NCP_SYSCON_PWR_CHIPSELECTEN, mask); + pm_set_bits_syscon_register(NCP_SYSCON_PWR_CHIPSELECTEN, mask); /* Disable the hsram */ pm_clear_bits_syscon_register(NCP_SYSCON_PWR_PWRUPL2HSRAM, mask); @@ -936,7 +899,7 @@ static int pm_L2_physical_connection_and_power_up(u32 cluster) int rval = 0; /* Power up stage 1 */ - pm_or_bits_syscon_register(NCP_SYSCON_PWR_PWRUPL2LGCSTG1, mask); + pm_set_bits_syscon_register(NCP_SYSCON_PWR_PWRUPL2LGCSTG1, mask); /* Wait for the stage 1 power up to complete */ success = pm_wait_for_bit_clear_with_timeout(NCP_SYSCON_PWR_NPWRUPL2LGCSTG1_ACK, cluster); @@ -947,13 +910,13 @@ static int pm_L2_physical_connection_and_power_up(u32 cluster) } /* Power on stage 2 */ - pm_or_bits_syscon_register(NCP_SYSCON_PWR_PWRUPL2LGCSTG2, mask); + pm_set_bits_syscon_register(NCP_SYSCON_PWR_PWRUPL2LGCSTG2, mask); /* Set the chip select */ - pm_or_bits_syscon_register(NCP_SYSCON_PWR_CHIPSELECTEN, mask); + pm_set_bits_syscon_register(NCP_SYSCON_PWR_CHIPSELECTEN, mask); /* Power up the snoop ram */ - pm_or_bits_syscon_register(NCP_SYSCON_PWR_PWRUPL2HSRAM, mask); + pm_set_bits_syscon_register(NCP_SYSCON_PWR_PWRUPL2HSRAM, mask); /* Wait for the stage 1 power up to complete */ success = pm_wait_for_bit_clear_with_timeout(NCP_SYSCON_PWR_NPWRUPL2HSRAM_ACK, cluster); @@ -997,7 +960,7 @@ static int pm_L2_physical_connection_and_power_up(u32 cluster) pm_set_bits_syscon_register(syscon, NCP_SYSCON_PWR_PWRUPL21RAM_PWRUPL2RAM1, RAM_BANK0_MASK); - udelay(20); + udelay(20); pm_set_bits_syscon_register(syscon, NCP_SYSCON_PWR_PWRUPL21RAM_PWRUPL2RAM1, RAM_BANK1_LS_MASK); pm_set_bits_syscon_register(syscon, @@ -1095,37 +1058,28 @@ static int pm_L2_logical_powerup(u32 cluster, u32 cpu) u32 mask = (0x1 << cluster); int rval = 0; - u32 cluster_mask; - - if (cluster == 0) - cluster_mask = 0xe; - else - cluster_mask = 0xf << (cluster * 4); /* put the cluster into a cpu hold */ - pm_or_bits_syscon_register(NCP_SYSCON_RESET_AXIS, + pm_set_bits_syscon_register(NCP_SYSCON_RESET_AXIS, cluster_to_poreset[cluster]); - /* - * The key value has to be written before the CPU RST can be written. - */ - pm_set_bits_syscon_register(NCP_SYSCON_KEY, VALID_KEY_VALUE); - pm_or_bits_syscon_register(NCP_SYSCON_PWRUP_CPU_RST, cluster_mask); + /* Allow the L2 to be reset */ + pm_clear_bits_syscon_register(NCP_SYSCON_LRSTDISABLE, mask); /* Hold the chip debug cluster */ pm_set_bits_syscon_register(NCP_SYSCON_KEY, VALID_KEY_VALUE); - pm_or_bits_syscon_register(NCP_SYSCON_HOLD_DBG, mask); + pm_set_bits_syscon_register(NCP_SYSCON_HOLD_DBG, mask); /* Hold the L2 cluster */ pm_set_bits_syscon_register(NCP_SYSCON_KEY, VALID_KEY_VALUE); - pm_or_bits_syscon_register(NCP_SYSCON_HOLD_L2, mask); - + pm_set_bits_syscon_register(NCP_SYSCON_HOLD_L2, mask); /* Cluster physical power up */ rval = pm_L2_physical_connection_and_power_up(cluster); if (rval) goto exit_pm_L2_logical_powerup; + udelay(16); /* take the cluster out of a cpu hold */ @@ -1135,7 +1089,7 @@ static int pm_L2_logical_powerup(u32 cluster, u32 cpu) udelay(64); /* Enable the system counter */ - pm_or_bits_syscon_register(NCP_SYSCON_PWR_CSYSREQ_CNT, mask); + pm_set_bits_syscon_register(NCP_SYSCON_PWR_CSYSREQ_CNT, mask); /* Release the L2 cluster */ pm_set_bits_syscon_register(NCP_SYSCON_KEY, VALID_KEY_VALUE); @@ -1153,6 +1107,11 @@ static int pm_L2_logical_powerup(u32 cluster, u32 cpu) /* start L2 */ pm_clear_bits_syscon_register(NCP_SYSCON_PWR_ACINACTM, mask); + /* Disable the L2 reset */ + pm_set_bits_syscon_register(NCP_SYSCON_LRSTDISABLE, mask); + + udelay(64); + exit_pm_L2_logical_powerup: return rval; diff --git a/arch/arm/mach-axxia/lsi_power_management.h b/arch/arm/mach-axxia/lsi_power_management.h index ef70af3..4de6bd7 100644 --- a/arch/arm/mach-axxia/lsi_power_management.h +++ b/arch/arm/mach-axxia/lsi_power_management.h @@ -150,19 +150,12 @@ #define PORESET_CLUSTER2 (0x40000) #define PORESET_CLUSTER3 (0x80000) -/* IPI Masks */ -#define IPI0_MASK (0x1111) -#define IPI1_MASK (0x2222) -#define IPI2_MASK (0x4444) -#define IPI3_MASK (0x8888) - /* SYSCON KEY Value */ #define VALID_KEY_VALUE (0xAB) #define MAX_NUM_CLUSTERS (4) #define CORES_PER_CLUSTER (4) #define MAX_IPI (19) -#define MAX_CPUS (MAX_NUM_CLUSTERS * CORES_PER_CLUSTER) typedef struct { u32 cpu; @@ -181,9 +174,9 @@ bool pm_cpu_last_of_cluster(u32 cpu); void pm_dump_dickens(void); void pm_init_cpu(u32 cpu); void pm_cpu_logical_powerup(void); -void pm_cluster_logical_powerup(void); bool pm_cpu_active(u32 cpu); void pm_init_syscon(void); + extern bool pm_in_progress[]; extern bool cluster_power_up[]; extern u32 pm_cpu_powered_down; diff --git a/arch/arm/mach-axxia/platsmp.c b/arch/arm/mach-axxia/platsmp.c index 2804fce..4bbcbed 100644 --- a/arch/arm/mach-axxia/platsmp.c +++ b/arch/arm/mach-axxia/platsmp.c @@ -24,13 +24,11 @@ #include "axxia.h" #include "lsi_power_management.h" -#include "axxia_circular_queue.h" #include <mach/axxia-gic.h> extern void axxia_secondary_startup(void); extern void axxia_cpu_power_management_gic_control(u32 cpu, bool enable); extern void axxia_dist_power_management_gic_control(bool enable); -extern struct circular_queue_t axxia_circ_q; #define SYSCON_PHYS_ADDR 0x002010030000ULL @@ -64,7 +62,7 @@ static void __init check_fixup_sev(void __iomem *syscon) pr_info("axxia: Cross-cluster SEV fixup: %s\n", wfe_fixup ? "yes" : "no"); } -static void do_fixup_sev(void) +static void __cpuinit do_fixup_sev(void) { u32 tmp; @@ -81,9 +79,10 @@ static void do_fixup_sev(void) * observers, irrespective of whether they're taking part in coherency * or not. This is necessary for the hotplug code to work reliably. */ -static void write_pen_release(int val) +static void __cpuinit write_pen_release(int val) { pen_release = val; + /* Memory Barrier */ smp_wmb(); __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release)); outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1)); @@ -91,7 +90,7 @@ static void write_pen_release(int val) static DEFINE_RAW_SPINLOCK(boot_lock); -void axxia_secondary_init(unsigned int cpu) +void __cpuinit axxia_secondary_init(unsigned int cpu) { int phys_cpu; int phys_cluster; @@ -102,7 +101,7 @@ void axxia_secondary_init(unsigned int cpu) /* * Only execute this when powering up a cpu for hotplug. */ - if (!pm_in_progress[phys_cpu]) { + if (!pm_in_progress[cpu]) { /* Fixup for cross-cluster SEV */ do_fixup_sev(); @@ -110,16 +109,16 @@ void axxia_secondary_init(unsigned int cpu) } else { #ifdef CONFIG_HOTPLUG_CPU_COMPLETE_POWER_DOWN - if (cluster_power_up[phys_cluster]) - pm_cluster_logical_powerup(); pm_cpu_logical_powerup(); + mdelay(16); #endif - get_cpu(); + axxia_gic_secondary_init(); - put_cpu(); #ifdef CONFIG_HOTPLUG_CPU_COMPLETE_POWER_DOWN - cluster_power_up[phys_cluster] = false; + pm_cpu_logical_powerup(); + if (cluster_power_up[phys_cluster]) + cluster_power_up[phys_cluster] = false; pm_in_progress[phys_cpu] = false; #endif } @@ -137,14 +136,13 @@ void axxia_secondary_init(unsigned int cpu) _raw_spin_unlock(&boot_lock); } -int axxia_boot_secondary(unsigned int cpu, struct task_struct *idle) +int __cpuinit axxia_boot_secondary(unsigned int cpu, struct task_struct *idle) { int phys_cpu, cluster; unsigned long timeout; unsigned long powered_down_cpu; - u32 i; - u32 dummy; + int rVal = 0; /* @@ -159,7 +157,12 @@ int axxia_boot_secondary(unsigned int cpu, struct task_struct *idle) if (powered_down_cpu & (1 << phys_cpu)) { pm_in_progress[phys_cpu] = true; - pm_cpu_powerup(phys_cpu); + + rVal = pm_cpu_powerup(phys_cpu); + if (rVal) { + _raw_spin_unlock(&boot_lock); + return rVal; + } } /* @@ -193,14 +196,13 @@ int axxia_boot_secondary(unsigned int cpu, struct task_struct *idle) /* Wait for so long, then give up if nothing happens ... */ timeout = jiffies + (1 * HZ); while (time_before(jiffies, timeout)) { + /* Memory Barrier */ smp_rmb(); if (pen_release == -1) break; - /* Wait 10 cycles */ - for (i = 0; i < 10; i++) - dummy = i; + udelay(10); } /* @@ -292,6 +294,7 @@ static void __init axxia_smp_prepare_cpus(unsigned int max_cpus) else release_virt = ioremap(release_phys, PAGE_SIZE); *release_virt = virt_to_phys(axxia_secondary_startup); + /* Memory Barrier */ smp_wmb(); __cpuc_flush_dcache_area(release_virt, sizeof(u32)); if (!is_kmapped) -- 1.7.9.5 -- _______________________________________________ linux-yocto mailing list [email protected] https://lists.yoctoproject.org/listinfo/linux-yocto
