[PATCH v6 15/15] ARM: hotplug: add cpu_lowpower as an alternative to cpu_die

Nicolas Pitre nico at fluxnic.net
Wed Feb 8 19:21:57 EST 2012


On Wed, 8 Feb 2012, Marc Zyngier wrote:

> Most platforms don't actually implement cpu_die, but instead
> a "go into low power mode" operation.
> 
> Factor these similar implementations into a single one called
> from platform_cpu_die().
> 
> Cc: Arnd Bergmann <arnd at arndb.de>
> Cc: Colin Cross <ccross at android.com>
> Cc: David Brown <davidb at codeaurora.org>
> Cc: Kukjin Kim <kgene.kim at samsung.com>
> Cc: Linus Walleij <linus.walleij at stericsson.com>
> Cc: Nicolas Pitre <nico at fluxnic.net>
> Cc: Santosh Shilimkar <santosh.shilimkar at ti.com>
> Cc: Stephen Warren <swarren at nvidia.com>
> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>

Acked-by: Nicolas Pitre <nico at linaro.org>


> ---
>  arch/arm/include/asm/soc.h               |    1 +
>  arch/arm/kernel/smp.c                    |   16 ++++++++-
>  arch/arm/mach-exynos/common.h            |    2 +-
>  arch/arm/mach-exynos/hotplug.c           |   27 +--------------
>  arch/arm/mach-exynos/platsmp.c           |    2 +-
>  arch/arm/mach-msm/core.h                 |    2 +-
>  arch/arm/mach-msm/hotplug.c              |   22 +-----------
>  arch/arm/mach-msm/platsmp.c              |    2 +-
>  arch/arm/mach-realview/core.h            |    2 +-
>  arch/arm/mach-realview/hotplug.c         |   27 +--------------
>  arch/arm/mach-realview/platsmp.c         |    2 +-
>  arch/arm/mach-tegra/common.h             |    2 +-
>  arch/arm/mach-tegra/hotplug.c            |   53 ++++--------------------------
>  arch/arm/mach-tegra/platsmp.c            |    2 +-
>  arch/arm/mach-ux500/hotplug.c            |   14 +-------
>  arch/arm/mach-ux500/include/mach/setup.h |    2 +-
>  arch/arm/mach-ux500/platsmp.c            |    2 +-
>  arch/arm/mach-vexpress/core.h            |    2 +-
>  arch/arm/mach-vexpress/hotplug.c         |   27 +--------------
>  arch/arm/mach-vexpress/platsmp.c         |    2 +-
>  20 files changed, 44 insertions(+), 167 deletions(-)
> 
> diff --git a/arch/arm/include/asm/soc.h b/arch/arm/include/asm/soc.h
> index 1bcc58c..f1b6c45 100644
> --- a/arch/arm/include/asm/soc.h
> +++ b/arch/arm/include/asm/soc.h
> @@ -38,6 +38,7 @@ struct arm_soc_smp_ops {
>  #ifdef CONFIG_HOTPLUG_CPU
>  	int  (*cpu_kill)(unsigned int cpu);
>  	void (*cpu_die)(unsigned int cpu);
> +	void (*cpu_lowpower)(unsigned int cpu, int *spurious);
>  	int  (*cpu_disable)(unsigned int cpu);
>  #endif
>  };
> diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
> index e0d1622..34318aa 100644
> --- a/arch/arm/kernel/smp.c
> +++ b/arch/arm/kernel/smp.c
> @@ -202,8 +202,20 @@ static int __cpuinit platform_cpu_kill(unsigned int cpu)
>  
>  static void __cpuinit platform_cpu_die(unsigned int cpu)
>  {
> -	if (soc_smp_ops && soc_smp_ops->cpu_die)
> -		soc_smp_ops->cpu_die(cpu);
> +	if (soc_smp_ops) {
> +		if (soc_smp_ops->cpu_die) {
> +			soc_smp_ops->cpu_die(cpu);
> +			return;
> +		}
> +
> +		if (soc_smp_ops->cpu_lowpower) {
> +			int spurious = 0;
> +			soc_smp_ops->cpu_lowpower(cpu, &spurious);
> +			if (spurious)
> +				pr_warn("CPU%u: %u spurious wakeup calls\n",
> +					cpu, spurious);
> +		}
> +	}
>  }
>  
>  static int __cpuinit platform_cpu_disable(unsigned int cpu)
> diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h
> index f13631a..d664f6e 100644
> --- a/arch/arm/mach-exynos/common.h
> +++ b/arch/arm/mach-exynos/common.h
> @@ -31,7 +31,7 @@ extern struct arm_soc_smp_init_ops	exynos4_soc_smp_init_ops;
>  extern struct arm_soc_smp_ops		exynos4_soc_smp_ops;
>  extern struct arm_soc_desc		exynos4_soc_desc;
>  
> -extern void exynos4_cpu_die(unsigned int cpu);
> +extern void exynos4_cpu_lowpower(unsigned int cpu, int *spurious);
>  
>  #ifdef CONFIG_ARCH_EXYNOS
>  extern  int exynos_init(void);
> diff --git a/arch/arm/mach-exynos/hotplug.c b/arch/arm/mach-exynos/hotplug.c
> index be7a96b..aed75cb 100644
> --- a/arch/arm/mach-exynos/hotplug.c
> +++ b/arch/arm/mach-exynos/hotplug.c
> @@ -62,8 +62,9 @@ static inline void cpu_leave_lowpower(void)
>  	  : "cc");
>  }
>  
> -static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
> +void exynos4_cpu_lowpower(unsigned int cpu, int *spurious)
>  {
> +	cpu_enter_lowpower();
>  	for (;;) {
>  
>  		/* make cpu1 to be turned off at next WFI command */
> @@ -94,29 +95,5 @@ static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
>  		 */
>  		(*spurious)++;
>  	}
> -}
> -
> -/*
> - * platform-specific code to shutdown a CPU
> - *
> - * Called with IRQs disabled
> - */
> -void exynos4_cpu_die(unsigned int cpu)
> -{
> -	int spurious = 0;
> -
> -	/*
> -	 * we're ready for shutdown now, so do it
> -	 */
> -	cpu_enter_lowpower();
> -	platform_do_lowpower(cpu, &spurious);
> -
> -	/*
> -	 * bring this CPU back into the world of cache
> -	 * coherency, and then restore interrupts
> -	 */
>  	cpu_leave_lowpower();
> -
> -	if (spurious)
> -		pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
>  }
> diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c
> index 4d22c2a..8469ac8 100644
> --- a/arch/arm/mach-exynos/platsmp.c
> +++ b/arch/arm/mach-exynos/platsmp.c
> @@ -208,7 +208,7 @@ struct arm_soc_smp_ops exynos4_soc_smp_ops __initdata = {
>  	.smp_boot_secondary	= exynos4_boot_secondary,
>  #ifdef CONFIG_HOTPLUG_CPU
>  	.cpu_kill		= dummy_cpu_kill,
> -	.cpu_die		= exynos4_cpu_die,
> +	.cpu_lowpower		= exynos4_cpu_lowpower,
>  	.cpu_disable		= dummy_cpu_disable,
>  #endif
>  };
> diff --git a/arch/arm/mach-msm/core.h b/arch/arm/mach-msm/core.h
> index 623474a..a5c50c4 100644
> --- a/arch/arm/mach-msm/core.h
> +++ b/arch/arm/mach-msm/core.h
> @@ -4,4 +4,4 @@ extern struct arm_soc_smp_init_ops	msm_soc_smp_init_ops;
>  extern struct arm_soc_smp_ops		msm_soc_smp_ops;
>  extern struct arm_soc_desc		msm_soc_desc;
>  
> -extern void msm_cpu_die(unsigned int cpu);
> +extern void msm_cpu_lowpower(unsigned int cpu, int *spurious);
> diff --git a/arch/arm/mach-msm/hotplug.c b/arch/arm/mach-msm/hotplug.c
> index d0f79e8..6e6ed2d 100644
> --- a/arch/arm/mach-msm/hotplug.c
> +++ b/arch/arm/mach-msm/hotplug.c
> @@ -28,9 +28,10 @@ static inline void cpu_leave_lowpower(void)
>  {
>  }
>  
> -static inline void platform_do_lowpower(unsigned int cpu)
> +void msm_cpu_lowpower(unsigned int cpu, int *spurious)
>  {
>  	/* Just enter wfi for now. TODO: Properly shut off the cpu. */
> +	cpu_enter_lowpower();
>  	for (;;) {
>  		/*
>  		 * here's the WFI
> @@ -57,24 +58,5 @@ static inline void platform_do_lowpower(unsigned int cpu)
>  		 */
>  		pr_debug("CPU%u: spurious wakeup call\n", cpu);
>  	}
> -}
> -
> -/*
> - * platform-specific code to shutdown a CPU
> - *
> - * Called with IRQs disabled
> - */
> -void msm_cpu_die(unsigned int cpu)
> -{
> -	/*
> -	 * we're ready for shutdown now, so do it
> -	 */
> -	cpu_enter_lowpower();
> -	platform_do_lowpower(cpu);
> -
> -	/*
> -	 * bring this CPU back into the world of cache
> -	 * coherency, and then restore interrupts
> -	 */
>  	cpu_leave_lowpower();
>  }
> diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c
> index f7e27d9..5e153cf 100644
> --- a/arch/arm/mach-msm/platsmp.c
> +++ b/arch/arm/mach-msm/platsmp.c
> @@ -184,7 +184,7 @@ struct arm_soc_smp_ops msm_soc_smp_ops __initdata = {
>  	.smp_boot_secondary	= msm_boot_secondary,
>  #ifdef CONFIG_HOTPLUG_CPU
>  	.cpu_kill		= dummy_cpu_kill,
> -	.cpu_die		= msm_cpu_die,
> +	.cpu_lowpower		= msm_cpu_lowpower,
>  	.cpu_disable		= dummy_cpu_disable,
>  #endif
>  };
> diff --git a/arch/arm/mach-realview/core.h b/arch/arm/mach-realview/core.h
> index dd4bcdb..b593b36 100644
> --- a/arch/arm/mach-realview/core.h
> +++ b/arch/arm/mach-realview/core.h
> @@ -71,6 +71,6 @@ extern struct arm_soc_desc		realview_soc_desc;
>  extern struct arm_soc_smp_init_ops	realview_soc_smp_init_ops;
>  extern struct arm_soc_smp_ops		realview_soc_smp_ops;
>  
> -extern void realview_cpu_die(unsigned int cpu);
> +extern void realview_cpu_lowpower(unsigned int cpu, int *spurious);
>  
>  #endif
> diff --git a/arch/arm/mach-realview/hotplug.c b/arch/arm/mach-realview/hotplug.c
> index 12af634..4d45d07 100644
> --- a/arch/arm/mach-realview/hotplug.c
> +++ b/arch/arm/mach-realview/hotplug.c
> @@ -54,13 +54,14 @@ static inline void cpu_leave_lowpower(void)
>  	  : "cc");
>  }
>  
> -static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
> +void realview_cpu_lowpower(unsigned int cpu, int *spurious)
>  {
>  	/*
>  	 * there is no power-control hardware on this platform, so all
>  	 * we can do is put the core into WFI; this is safe as the calling
>  	 * code will have already disabled interrupts
>  	 */
> +	cpu_enter_lowpower();
>  	for (;;) {
>  		/*
>  		 * here's the WFI
> @@ -86,29 +87,5 @@ static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
>  		 */
>  		(*spurious)++;
>  	}
> -}
> -
> -/*
> - * platform-specific code to shutdown a CPU
> - *
> - * Called with IRQs disabled
> - */
> -void realview_cpu_die(unsigned int cpu)
> -{
> -	int spurious = 0;
> -
> -	/*
> -	 * we're ready for shutdown now, so do it
> -	 */
> -	cpu_enter_lowpower();
> -	platform_do_lowpower(cpu, &spurious);
> -
> -	/*
> -	 * bring this CPU back into the world of cache
> -	 * coherency, and then restore interrupts
> -	 */
>  	cpu_leave_lowpower();
> -
> -	if (spurious)
> -		pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
>  }
> diff --git a/arch/arm/mach-realview/platsmp.c b/arch/arm/mach-realview/platsmp.c
> index 5b7535d..eb6b532 100644
> --- a/arch/arm/mach-realview/platsmp.c
> +++ b/arch/arm/mach-realview/platsmp.c
> @@ -90,7 +90,7 @@ struct arm_soc_smp_ops realview_soc_smp_ops __initdata = {
>  	.smp_boot_secondary	= versatile_boot_secondary,
>  #ifdef CONFIG_HOTPLUG_CPU
>  	.cpu_kill		= dummy_cpu_kill,
> -	.cpu_die		= realview_cpu_die,
> +	.cpu_lowpower		= realview_cpu_lowpower,
>  	.cpu_disable		= dummy_cpu_disable,
>  #endif
>  };
> diff --git a/arch/arm/mach-tegra/common.h b/arch/arm/mach-tegra/common.h
> index b02cc87..38b9ea4 100644
> --- a/arch/arm/mach-tegra/common.h
> +++ b/arch/arm/mach-tegra/common.h
> @@ -6,4 +6,4 @@ struct arm_soc_smp_ops;
>  extern struct arm_soc_smp_init_ops	tegra_soc_smp_init_ops;
>  extern struct arm_soc_smp_ops		tegra_soc_smp_ops;
>  
> -extern void tegra_cpu_die(unsigned int cpu);
> +extern void tegra_cpu_lowpower(unsigned int cpu, int *spurious);
> diff --git a/arch/arm/mach-tegra/hotplug.c b/arch/arm/mach-tegra/hotplug.c
> index 15433b2..455a077 100644
> --- a/arch/arm/mach-tegra/hotplug.c
> +++ b/arch/arm/mach-tegra/hotplug.c
> @@ -52,61 +52,22 @@ static inline void cpu_leave_lowpower(void)
>  	  : "cc");
>  }
>  
> -static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
> +void tegra_cpu_lowpower(unsigned int cpu, int *spurious)
>  {
>  	/*
>  	 * there is no power-control hardware on this platform, so all
>  	 * we can do is put the core into WFI; this is safe as the calling
>  	 * code will have already disabled interrupts
>  	 */
> -	for (;;) {
> -		/*
> -		 * here's the WFI
> -		 */
> -		asm(".word	0xe320f003\n"
> -		    :
> -		    :
> -		    : "memory", "cc");
> -
> -		/*if (pen_release == cpu) {*/
> -			/*
> -			 * OK, proper wakeup, we're done
> -			 */
> -			break;
> -		/*}*/
> -
> -		/*
> -		 * Getting here, means that we have come out of WFI without
> -		 * having been woken up - this shouldn't happen
> -		 *
> -		 * Just note it happening - when we're woken, we can report
> -		 * its occurrence.
> -		 */
> -		(*spurious)++;
> -	}
> -}
> -
> -/*
> - * platform-specific code to shutdown a CPU
> - *
> - * Called with IRQs disabled
> - */
> -void tegra_cpu_die(unsigned int cpu)
> -{
> -	int spurious = 0;
> -
> -	/*
> -	 * we're ready for shutdown now, so do it
> -	 */
>  	cpu_enter_lowpower();
> -	platform_do_lowpower(cpu, &spurious);
>  
>  	/*
> -	 * bring this CPU back into the world of cache
> -	 * coherency, and then restore interrupts
> +	 * here's the WFI
>  	 */
> -	cpu_leave_lowpower();
> +	asm("wfi\n"
> +	    :
> +	    :
> +	    : "memory", "cc");
>  
> -	if (spurious)
> -		pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
> +	cpu_leave_lowpower();
>  }
> diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c
> index 4edc8ab..5d1593c 100644
> --- a/arch/arm/mach-tegra/platsmp.c
> +++ b/arch/arm/mach-tegra/platsmp.c
> @@ -146,7 +146,7 @@ struct arm_soc_smp_ops tegra_soc_smp_ops __initdata = {
>  	.smp_boot_secondary	= tegra_boot_secondary,
>  #ifdef CONFIG_HOTPLUG_CPU
>  	.cpu_kill		= dummy_cpu_kill,
> -	.cpu_die		= tegra_cpu_die,
> +	.cpu_lowpower		= tegra_cpu_lowpower,
>  	.cpu_disable		= dummy_cpu_disable,
>  #endif
>  };
> diff --git a/arch/arm/mach-ux500/hotplug.c b/arch/arm/mach-ux500/hotplug.c
> index ec1c77f..c46b01d 100644
> --- a/arch/arm/mach-ux500/hotplug.c
> +++ b/arch/arm/mach-ux500/hotplug.c
> @@ -19,7 +19,7 @@
>  
>  extern volatile int pen_release;
>  
> -static inline void platform_do_lowpower(unsigned int cpu)
> +void ux500_cpu_lowpower(unsigned int cpu, int *spurious)
>  {
>  	flush_cache_all();
>  
> @@ -33,16 +33,6 @@ static inline void platform_do_lowpower(unsigned int cpu)
>  			 */
>  			break;
>  		}
> +		(*spurious)++;
>  	}
>  }
> -
> -/*
> - * platform-specific code to shutdown a CPU
> - *
> - * Called with IRQs disabled
> - */
> -void ux500_cpu_die(unsigned int cpu)
> -{
> -	/* directly enter low power state, skipping secure registers */
> -	platform_do_lowpower(cpu);
> -}
> diff --git a/arch/arm/mach-ux500/include/mach/setup.h b/arch/arm/mach-ux500/include/mach/setup.h
> index 2935f85..127fd0b 100644
> --- a/arch/arm/mach-ux500/include/mach/setup.h
> +++ b/arch/arm/mach-ux500/include/mach/setup.h
> @@ -55,6 +55,6 @@ extern struct arm_soc_smp_init_ops ux500_soc_smp_init_ops;
>  extern struct arm_soc_smp_ops ux500_soc_smp_ops;
>  extern struct arm_soc_desc ux500_soc_desc;
>  
> -extern void ux500_cpu_die(unsigned int cpu);
> +extern void ux500_cpu_lowpower(unsigned int cpu, int *spurious)l
>  
>  #endif /*  __ASM_ARCH_SETUP_H */
> diff --git a/arch/arm/mach-ux500/platsmp.c b/arch/arm/mach-ux500/platsmp.c
> index bbd6480..f19ba4e 100644
> --- a/arch/arm/mach-ux500/platsmp.c
> +++ b/arch/arm/mach-ux500/platsmp.c
> @@ -186,7 +186,7 @@ struct arm_soc_smp_ops ux500_soc_smp_ops __initdata = {
>  	.smp_boot_secondary	= ux500_boot_secondary,
>  #ifdef CONFIG_HOTPLUG_CPU
>  	.cpu_kill		= dummy_cpu_kill,
> -	.cpu_die		= ux500_cpu_die,
> +	.cpu_lowpower		= ux500_cpu_lowpower,
>  	.cpu_disable		= dummy_cpu_disable,
>  #endif
>  };
> diff --git a/arch/arm/mach-vexpress/core.h b/arch/arm/mach-vexpress/core.h
> index d9b1ec0..413e889 100644
> --- a/arch/arm/mach-vexpress/core.h
> +++ b/arch/arm/mach-vexpress/core.h
> @@ -24,4 +24,4 @@ struct arm_soc_smp_ops;
>  extern struct arm_soc_smp_init_ops	vexpress_soc_smp_init_ops;
>  extern struct arm_soc_smp_ops		vexpress_soc_smp_ops;
>  
> -extern void vexpress_cpu_die(unsigned int cpu);
> +extern void vexpress_cpu_lowpower(unsigned int cpu, int *spurious)
> diff --git a/arch/arm/mach-vexpress/hotplug.c b/arch/arm/mach-vexpress/hotplug.c
> index e1a7fef..4c87adc 100644
> --- a/arch/arm/mach-vexpress/hotplug.c
> +++ b/arch/arm/mach-vexpress/hotplug.c
> @@ -56,13 +56,14 @@ static inline void cpu_leave_lowpower(void)
>  	  : "cc");
>  }
>  
> -static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
> +void vexpress_cpu_lowpower(unsigned int cpu, int *spurious)
>  {
>  	/*
>  	 * there is no power-control hardware on this platform, so all
>  	 * we can do is put the core into WFI; this is safe as the calling
>  	 * code will have already disabled interrupts
>  	 */
> +	cpu_enter_lowpower();
>  	for (;;) {
>  		wfi();
>  
> @@ -82,29 +83,5 @@ static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
>  		 */
>  		(*spurious)++;
>  	}
> -}
> -
> -/*
> - * platform-specific code to shutdown a CPU
> - *
> - * Called with IRQs disabled
> - */
> -void vexpress_cpu_die(unsigned int cpu)
> -{
> -	int spurious = 0;
> -
> -	/*
> -	 * we're ready for shutdown now, so do it
> -	 */
> -	cpu_enter_lowpower();
> -	platform_do_lowpower(cpu, &spurious);
> -
> -	/*
> -	 * bring this CPU back into the world of cache
> -	 * coherency, and then restore interrupts
> -	 */
>  	cpu_leave_lowpower();
> -
> -	if (spurious)
> -		pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
>  }
> diff --git a/arch/arm/mach-vexpress/platsmp.c b/arch/arm/mach-vexpress/platsmp.c
> index a5196f87..5630d2b 100644
> --- a/arch/arm/mach-vexpress/platsmp.c
> +++ b/arch/arm/mach-vexpress/platsmp.c
> @@ -61,7 +61,7 @@ struct arm_soc_smp_ops vexpress_soc_smp_ops __initdata = {
>  	.smp_boot_secondary	= versatile_boot_secondary,
>  #ifdef CONFIG_HOTPLUG_CPU
>  	.cpu_kill		= dummy_cpu_kill,
> -	.cpu_die		= vexpress_cpu_die,
> +	.cpu_lowpower		= vexpress_cpu_lowpower,
>  	.cpu_disable		= dummy_cpu_disable,
>  #endif
>  };
> -- 
> 1.7.3.4
> 



More information about the linux-arm-kernel mailing list