Skip to contentSkip to conversation

ARM: exynos: cpuidle: Fallback to WFI, when AFTR is selected

PATCH New Daniel Lezcano 3 participants 12 messages Jul 18, 2013 – Jul 24, 2013

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 1/4 ARM: exynos: cpuidle: Fallback to WFI, when AFTR is selected

When there are several cpus online, the AFTR state does not work.

The AFTR must be selected only when there is one cpu online.

The previous code was already handling this case.

Simplified the code, especially the init routine to have the same init pattern than the other drivers.

---
 arch/arm/mach-exynos/cpuidle.c |   13 ++-----------
 1 file changed, 2 insertions(+), 11 deletions(-)
arch/arm/mach-exynos/cpuidle.c +2 -11
index 17a18ff..cc4b097 100644
@@ -147,16 +147,11 @@ static int exynos4_enter_lowpower(struct cpuidle_device *dev,
 				struct cpuidle_driver *drv,
 				int index)
 {
-	int new_index = index;
-
 	/* This mode only can be entered when other core's are offline */
 	if (num_online_cpus() > 1)
-		new_index = drv->safe_state_index;
+		return drv->states[0].enter(dev, drv, 0);
 
-	if (new_index == 0)
-		return arm_cpuidle_simple_enter(dev, drv, new_index);
-	else
-		return exynos4_enter_core0_aftr(dev, drv, new_index);
+	return exynos4_enter_core0_aftr(dev, drv, index);
 }
 
 static void __init exynos5_core_down_clk(void)
@@ -209,10 +204,6 @@ static int __init exynos4_init_cpuidle(void)
 		device = &per_cpu(exynos4_cpuidle_device, cpu_id);
 		device->cpu = cpu_id;
 
-		/* Support IDLE only */
-		if (cpu_id != 0)
-			device->state_count = 1;
-
 		ret = cpuidle_register_device(device);
 		if (ret) {
 			printk(KERN_ERR "CPUidle register device failed\n");
Signature · 1 line
1.7.9.5
#1 lore raw

PATCH 2/4 ARM: exynos: cpuidle: Use the common cpuidle register routine

Now we have the same routine than the one handled by the cpuidle framework.

Let's use it.

---
 arch/arm/mach-exynos/cpuidle.c |   24 +-----------------------
 1 file changed, 1 insertion(+), 23 deletions(-)
arch/arm/mach-exynos/cpuidle.c +1 -23
index cc4b097..d8fc1a2 100644
@@ -41,8 +41,6 @@ static int exynos4_enter_lowpower(struct cpuidle_device *dev,
 				struct cpuidle_driver *drv,
 				int index);
 
-static DEFINE_PER_CPU(struct cpuidle_device, exynos4_cpuidle_device);
-
 static struct cpuidle_driver exynos4_idle_driver = {
 	.name			= "exynos4_idle",
 	.owner			= THIS_MODULE,
@@ -188,29 +186,9 @@ static void __init exynos5_core_down_clk(void)
 
 static int __init exynos4_init_cpuidle(void)
 {
-	int cpu_id, ret;
-	struct cpuidle_device *device;
-
 	if (soc_is_exynos5250())
 		exynos5_core_down_clk();
 
-	ret = cpuidle_register_driver(&exynos4_idle_driver);
-	if (ret) {
-		printk(KERN_ERR "CPUidle failed to register driver\n");
-		return ret;
-	}
-
-	for_each_online_cpu(cpu_id) {
-		device = &per_cpu(exynos4_cpuidle_device, cpu_id);
-		device->cpu = cpu_id;
-
-		ret = cpuidle_register_device(device);
-		if (ret) {
-			printk(KERN_ERR "CPUidle register device failed\n");
-			return ret;
-		}
-	}
-
-	return 0;
+	return cpuidle_register(&exynos4_idle_driver, NULL);
 }
 device_initcall(exynos4_init_cpuidle);
Signature · 1 line
1.7.9.5
#2 lore raw

PATCH 2/4 ARM: exynos: cpuidle: Use the common cpuidle register routine

Hi,

Quoted 1 line · Daniel Lezcano

Now we have the same routine than the one handled by the cpuidle framework.

Small nitpick:

To be exact the routine is not the same, on error cpuidle_register() does complete unregister operation of the cpuidle driver, exynos4_init_cpuidle() just stops the registration procedure.

The change itself is okay but the patch description could be better.

Anyway all patches (#1-4) look fine to me. Thanks for this work.

Best regards,
--
Bartlomiej Zolnierkiewicz
Samsung R&D Institute Poland
Samsung Electronics

Quoted 51 lines

Let's use it.

---
 arch/arm/mach-exynos/cpuidle.c |   24 +-----------------------
 1 file changed, 1 insertion(+), 23 deletions(-)
arch/arm/mach-exynos/cpuidle.c +1 -23
index cc4b097..d8fc1a2 100644
@@ -41,8 +41,6 @@ static int exynos4_enter_lowpower(struct cpuidle_device *dev,
 				struct cpuidle_driver *drv,
 				int index);
 
-static DEFINE_PER_CPU(struct cpuidle_device, exynos4_cpuidle_device);
-
 static struct cpuidle_driver exynos4_idle_driver = {
 	.name			= "exynos4_idle",
 	.owner			= THIS_MODULE,
@@ -188,29 +186,9 @@ static void __init exynos5_core_down_clk(void)
 
 static int __init exynos4_init_cpuidle(void)
 {
-	int cpu_id, ret;
-	struct cpuidle_device *device;
-
 	if (soc_is_exynos5250())
 		exynos5_core_down_clk();
 
-	ret = cpuidle_register_driver(&exynos4_idle_driver);
-	if (ret) {
-		printk(KERN_ERR "CPUidle failed to register driver\n");
-		return ret;
-	}
-
-	for_each_online_cpu(cpu_id) {
-		device = &per_cpu(exynos4_cpuidle_device, cpu_id);
-		device->cpu = cpu_id;
-
-		ret = cpuidle_register_device(device);
-		if (ret) {
-			printk(KERN_ERR "CPUidle register device failed\n");
-			return ret;
-		}
-	}
-
-	return 0;
+	return cpuidle_register(&exynos4_idle_driver, NULL);
 }
 device_initcall(exynos4_init_cpuidle);
#3 lore raw

PATCH 2/4 ARM: exynos: cpuidle: Use the common cpuidle register routine

Quoted 6 lines · Bartlomiej Zolnierkiewicz

Hi,

Quoted 1 line · Daniel Lezcano

Now we have the same routine than the one handled by the cpuidle framework.

Quoted 7 lines

Small nitpick:

To be exact the routine is not the same, on error cpuidle_register() does complete unregister operation of the cpuidle driver, exynos4_init_cpuidle() just stops the registration procedure.

The change itself is okay but the patch description could be better.

Ok, I will fix the changelog.

Quoted 1 line

Anyway all patches (#1-4) look fine to me. Thanks for this work.

Thanks for the review. I assume it is an acked-by right ?

Quoted 1 line

Best regards,

Kukjin,

shall I take the patchset in my tree ?

Thanks
-- Daniel

Quoted 57 lines

--
Bartlomiej Zolnierkiewicz
Samsung R&D Institute Poland
Samsung Electronics

Quoted 51 lines

Let's use it.

---
 arch/arm/mach-exynos/cpuidle.c |   24 +-----------------------
 1 file changed, 1 insertion(+), 23 deletions(-)
arch/arm/mach-exynos/cpuidle.c +1 -23
index cc4b097..d8fc1a2 100644
@@ -41,8 +41,6 @@ static int exynos4_enter_lowpower(struct cpuidle_device *dev,
 				struct cpuidle_driver *drv,
 				int index);
 
-static DEFINE_PER_CPU(struct cpuidle_device, exynos4_cpuidle_device);
-
 static struct cpuidle_driver exynos4_idle_driver = {
 	.name			= "exynos4_idle",
 	.owner			= THIS_MODULE,
@@ -188,29 +186,9 @@ static void __init exynos5_core_down_clk(void)
 
 static int __init exynos4_init_cpuidle(void)
 {
-	int cpu_id, ret;
-	struct cpuidle_device *device;
-
 	if (soc_is_exynos5250())
 		exynos5_core_down_clk();
 
-	ret = cpuidle_register_driver(&exynos4_idle_driver);
-	if (ret) {
-		printk(KERN_ERR "CPUidle failed to register driver\n");
-		return ret;
-	}
-
-	for_each_online_cpu(cpu_id) {
-		device = &per_cpu(exynos4_cpuidle_device, cpu_id);
-		device->cpu = cpu_id;
-
-		ret = cpuidle_register_device(device);
-		if (ret) {
-			printk(KERN_ERR "CPUidle register device failed\n");
-			return ret;
-		}
-	}
-
-	return 0;
+	return cpuidle_register(&exynos4_idle_driver, NULL);
 }
 device_initcall(exynos4_init_cpuidle);
Signature · 5 lines
 <http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
#4 lore raw

PATCH 2/4 ARM: exynos: cpuidle: Use the common cpuidle register routine

Quoted 13 lines · Daniel Lezcano
Quoted 12 lines · Bartlomiej Zolnierkiewicz

Hi,

Quoted 1 line · Daniel Lezcano

Now we have the same routine than the one handled by the cpuidle framework.

Small nitpick:

To be exact the routine is not the same, on error cpuidle_register() does complete unregister operation of the cpuidle driver, exynos4_init_cpuidle() just stops the registration procedure.

Quoted 7 lines
Quoted 1 line

The change itself is okay but the patch description could be better.

Ok, I will fix the changelog.

Quoted 1 line

Anyway all patches (#1-4) look fine to me. Thanks for this work.

Thanks for the review. I assume it is an acked-by right ?

Yes.

Best regards,
--
Bartlomiej Zolnierkiewicz
Samsung R&D Institute Poland
Samsung Electronics

Quoted 65 lines
Quoted 1 line

Best regards,

Kukjin,

shall I take the patchset in my tree ?

Thanks
-- Daniel

Quoted 56 lines

--
Bartlomiej Zolnierkiewicz
Samsung R&D Institute Poland
Samsung Electronics

Quoted 51 lines

Let's use it.

---
 arch/arm/mach-exynos/cpuidle.c |   24 +-----------------------
 1 file changed, 1 insertion(+), 23 deletions(-)
arch/arm/mach-exynos/cpuidle.c +1 -23
index cc4b097..d8fc1a2 100644
@@ -41,8 +41,6 @@ static int exynos4_enter_lowpower(struct cpuidle_device *dev,
 				struct cpuidle_driver *drv,
 				int index);
 
-static DEFINE_PER_CPU(struct cpuidle_device, exynos4_cpuidle_device);
-
 static struct cpuidle_driver exynos4_idle_driver = {
 	.name			= "exynos4_idle",
 	.owner			= THIS_MODULE,
@@ -188,29 +186,9 @@ static void __init exynos5_core_down_clk(void)
 
 static int __init exynos4_init_cpuidle(void)
 {
-	int cpu_id, ret;
-	struct cpuidle_device *device;
-
 	if (soc_is_exynos5250())
 		exynos5_core_down_clk();
 
-	ret = cpuidle_register_driver(&exynos4_idle_driver);
-	if (ret) {
-		printk(KERN_ERR "CPUidle failed to register driver\n");
-		return ret;
-	}
-
-	for_each_online_cpu(cpu_id) {
-		device = &per_cpu(exynos4_cpuidle_device, cpu_id);
-		device->cpu = cpu_id;
-
-		ret = cpuidle_register_device(device);
-		if (ret) {
-			printk(KERN_ERR "CPUidle register device failed\n");
-			return ret;
-		}
-	}
-
-	return 0;
+	return cpuidle_register(&exynos4_idle_driver, NULL);
 }
 device_initcall(exynos4_init_cpuidle);
#5 lore raw

PATCH 2/4 ARM: exynos: cpuidle: Use the common cpuidle register routine

In reply to Daniel Lezcano
Quoted 36 lines · On Thursday 18 of July 2013 14:54:28 Daniel Lezcano wrote:

Now we have the same routine than the one handled by the cpuidle framework.

Let's use it.

---
 arch/arm/mach-exynos/cpuidle.c |   24 +-----------------------
 1 file changed, 1 insertion(+), 23 deletions(-)
(quoted diff) +0 -0

b/arch/arm/mach-exynos/cpuidle.c index cc4b097..d8fc1a2 100644

arch/arm/mach-exynos/cpuidle.c +0 -8
@@ -41,8 +41,6 @@ static int exynos4_enter_lowpower(struct
 cpuidle_device *dev, struct cpuidle_driver *drv,
 				int index);
 
-static DEFINE_PER_CPU(struct cpuidle_device, exynos4_cpuidle_device);
-
 static struct cpuidle_driver exynos4_idle_driver = {
 	.name			= "exynos4_idle",
 	.owner			= THIS_MODULE,
@@ -188,29 +186,9 @@ static void __init exynos5_core_down_clk(void)
 
 static int __init exynos4_init_cpuidle(void)
 {
-	int cpu_id, ret;
-	struct cpuidle_device *device;
-
 	if (soc_is_exynos5250())
 		exynos5_core_down_clk();
 
-	ret = cpuidle_register_driver(&exynos4_idle_driver);
-	if (ret) {
-		printk(KERN_ERR "CPUidle failed to register driver\n");

arch/arm/mach-exynos/cpuidle.c static void __init exynos5_core_down_clk(void) · line 209

Quoted 10 lines
arch/arm/mach-exynos/cpuidle.c +0 -10
-		return ret;
-	}
-
-	for_each_online_cpu(cpu_id) {
-		device = &per_cpu(exynos4_cpuidle_device, cpu_id);
-		device->cpu = cpu_id;
-
-		ret = cpuidle_register_device(device);
-		if (ret) {
-			printk(KERN_ERR "CPUidle register device 

failed\n");

arch/arm/mach-exynos/cpuidle.c static void __init exynos5_core_down_clk(void) · line 194

Quoted 8 lines
arch/arm/mach-exynos/cpuidle.c +1 -5
-			return ret;
-		}
-	}
-
-	return 0;
+	return cpuidle_register(&exynos4_idle_driver, NULL);
 }
 device_initcall(exynos4_init_cpuidle);

This is nice, but I would like to see clarification for my question posted to patch 1/4.

Best regards,
Tomasz

#6 lore raw

PATCH 3/4 ARM: exynos: cpuidle: Move exynos4_idle_driver declaration below in the code

In reply to Daniel Lezcano

In order to prevent a pointless forward declaration, move the driver declation after the idle function callback, right before the init function.

---
 arch/arm/mach-exynos/cpuidle.c |   40 ++++++++++++++++++----------------------
 1 file changed, 18 insertions(+), 22 deletions(-)
arch/arm/mach-exynos/cpuidle.c +18 -22
index d8fc1a2..8d06128 100644
@@ -37,28 +37,6 @@
 
 #define S5P_CHECK_AFTR		0xFCBA0D10
 
-static int exynos4_enter_lowpower(struct cpuidle_device *dev,
-				struct cpuidle_driver *drv,
-				int index);
-
-static struct cpuidle_driver exynos4_idle_driver = {
-	.name			= "exynos4_idle",
-	.owner			= THIS_MODULE,
-	.states = {
-		[0] = ARM_CPUIDLE_WFI_STATE,
-		[1] = {
-			.enter			= exynos4_enter_lowpower,
-			.exit_latency		= 300,
-			.target_residency	= 100000,
-			.flags			= CPUIDLE_FLAG_TIME_VALID,
-			.name			= "C1",
-			.desc			= "ARM power down",
-		},
-	},
-	.state_count = 2,
-	.safe_state_index = 0,
-};
-
 /* Ext-GIC nIRQ/nFIQ is the only wakeup source in AFTR */
 static void exynos4_set_wakeupmask(void)
 {
@@ -184,6 +162,24 @@ static void __init exynos5_core_down_clk(void)
 	__raw_writel(tmp, EXYNOS5_PWR_CTRL2);
 }
 
+static struct cpuidle_driver exynos4_idle_driver = {
+	.name			= "exynos4_idle",
+	.owner			= THIS_MODULE,
+	.states = {
+		[0] = ARM_CPUIDLE_WFI_STATE,
+		[1] = {
+			.enter			= exynos4_enter_lowpower,
+			.exit_latency		= 300,
+			.target_residency	= 100000,
+			.flags			= CPUIDLE_FLAG_TIME_VALID,
+			.name			= "C1",
+			.desc			= "ARM power down",
+		},
+	},
+	.state_count = 2,
+	.safe_state_index = 0,
+};
+
 static int __init exynos4_init_cpuidle(void)
 {
 	if (soc_is_exynos5250())
Signature · 1 line
1.7.9.5
#7 lore raw

PATCH 3/4 ARM: exynos: cpuidle: Move exynos4_idle_driver declaration below in the code

Quoted 58 lines · On Thursday 18 of July 2013 14:54:29 Daniel Lezcano wrote:

In order to prevent a pointless forward declaration, move the driver declation after the idle function callback, right before the init function.

---
 arch/arm/mach-exynos/cpuidle.c |   40

++++++++++++++++++---------------------- 1 file changed, 18 insertions(+), 22 deletions(-)

(quoted diff) +0 -0

b/arch/arm/mach-exynos/cpuidle.c index d8fc1a2..8d06128 100644

arch/arm/mach-exynos/cpuidle.c +11 -22
@@ -37,28 +37,6 @@
 
 #define S5P_CHECK_AFTR		0xFCBA0D10
 
-static int exynos4_enter_lowpower(struct cpuidle_device *dev,
-				struct cpuidle_driver *drv,
-				int index);
-
-static struct cpuidle_driver exynos4_idle_driver = {
-	.name			= "exynos4_idle",
-	.owner			= THIS_MODULE,
-	.states = {
-		[0] = ARM_CPUIDLE_WFI_STATE,
-		[1] = {
-			.enter			= exynos4_enter_lowpower,
-			.exit_latency		= 300,
-			.target_residency	= 100000,
-			.flags			= CPUIDLE_FLAG_TIME_VALID,
-			.name			= "C1",
-			.desc			= "ARM power down",
-		},
-	},
-	.state_count = 2,
-	.safe_state_index = 0,
-};
-
 /* Ext-GIC nIRQ/nFIQ is the only wakeup source in AFTR */
 static void exynos4_set_wakeupmask(void)
 {
@@ -184,6 +162,24 @@ static void __init exynos5_core_down_clk(void)
 	__raw_writel(tmp, EXYNOS5_PWR_CTRL2);
 }
 
+static struct cpuidle_driver exynos4_idle_driver = {
+	.name			= "exynos4_idle",
+	.owner			= THIS_MODULE,
+	.states = {
+		[0] = ARM_CPUIDLE_WFI_STATE,
+		[1] = {
+			.enter			= exynos4_enter_lowpower,
+			.exit_latency		= 300,
+			.target_residency	= 100000,
+			.flags			= CPUIDLE_FLAG_TIME_VALID,
+			.name			= "C1",

arch/arm/mach-exynos/cpuidle.c static void __init exynos5_core_down_clk(void) · line 185

Quoted 10 lines
arch/arm/mach-exynos/cpuidle.c +7 -0
+			.desc			= "ARM power down",
+		},
+	},
+	.state_count = 2,
+	.safe_state_index = 0,
+};
+
 static int __init exynos4_init_cpuidle(void)
 {
 	if (soc_is_exynos5250())

Makes sense.

Best regards,
Tomasz

#8 lore raw

PATCH 4/4 ARM: exynos: cpuidle: Remove useless headers

In reply to Daniel Lezcano

The headers:

#include <linux/kernel.h>
#include <linux/export.h>
#include <linux/time.h>
#include <asm/unified.h>

are not needed. Removed them.

---
 arch/arm/mach-exynos/cpuidle.c |    4 ----
 1 file changed, 4 deletions(-)
arch/arm/mach-exynos/cpuidle.c +0 -4
index 8d06128..027f5e7 100644
@@ -8,18 +8,14 @@
  * published by the Free Software Foundation.
 */
 
-#include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/cpuidle.h>
 #include <linux/cpu_pm.h>
 #include <linux/io.h>
-#include <linux/export.h>
-#include <linux/time.h>
 
 #include <asm/proc-fns.h>
 #include <asm/smp_scu.h>
 #include <asm/suspend.h>
-#include <asm/unified.h>
 #include <asm/cpuidle.h>
 #include <mach/regs-clock.h>
 #include <mach/regs-pmu.h>
Signature · 1 line
1.7.9.5
#9 lore raw

PATCH 4/4 ARM: exynos: cpuidle: Remove useless headers

Quoted 27 lines · On Thursday 18 of July 2013 14:54:30 Daniel Lezcano wrote:

The headers:

#include <linux/kernel.h>
#include <linux/export.h>
#include <linux/time.h>
#include <asm/unified.h>

are not needed. Removed them.

---
 arch/arm/mach-exynos/cpuidle.c |    4 ----
 1 file changed, 4 deletions(-)
(quoted diff) +0 -0

b/arch/arm/mach-exynos/cpuidle.c index 8d06128..027f5e7 100644

arch/arm/mach-exynos/cpuidle.c +0 -1
@@ -8,18 +8,14 @@
  * published by the Free Software Foundation.
 */
 
-#include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/cpuidle.h>
 #include <linux/cpu_pm.h>
 #include <linux/io.h>

arch/arm/mach-exynos/cpuidle.c line 21

Quoted 10 lines
arch/arm/mach-exynos/cpuidle.c +0 -3
-#include <linux/export.h>
-#include <linux/time.h>
 
 #include <asm/proc-fns.h>
 #include <asm/smp_scu.h>
 #include <asm/suspend.h>
-#include <asm/unified.h>
 #include <asm/cpuidle.h>
 #include <mach/regs-clock.h>
 #include <mach/regs-pmu.h>

Best regards,
Tomasz

#10 lore raw

PATCH 1/4 ARM: exynos: cpuidle: Fallback to WFI, when AFTR is selected

In reply to Daniel Lezcano

Hi Daniel,

Quoted 38 lines · On Thursday 18 of July 2013 14:54:27 Daniel Lezcano wrote:

When there are several cpus online, the AFTR state does not work.

The AFTR must be selected only when there is one cpu online.

The previous code was already handling this case.

Simplified the code, especially the init routine to have the same init pattern than the other drivers.

---
 arch/arm/mach-exynos/cpuidle.c |   13 ++-----------
 1 file changed, 2 insertions(+), 11 deletions(-)
(quoted diff) +0 -0

b/arch/arm/mach-exynos/cpuidle.c index 17a18ff..cc4b097 100644

arch/arm/mach-exynos/cpuidle.c +2 -7
@@ -147,16 +147,11 @@ static int exynos4_enter_lowpower(struct
 cpuidle_device *dev, struct cpuidle_driver *drv,
 				int index)
 {
-	int new_index = index;
-
 	/* This mode only can be entered when other core's are offline */
 	if (num_online_cpus() > 1)
-		new_index = drv->safe_state_index;
+		return drv->states[0].enter(dev, drv, 0);
 
-	if (new_index == 0)
-		return arm_cpuidle_simple_enter(dev, drv, new_index);
-	else
-		return exynos4_enter_core0_aftr(dev, drv, new_index);
+	return exynos4_enter_core0_aftr(dev, drv, index);
 }
 
 static void __init exynos5_core_down_clk(void)

arch/arm/mach-exynos/cpuidle.c static int __init exynos4_init_cpuidle(void) · line 215

Quoted 7 lines
arch/arm/mach-exynos/cpuidle.c +0 -4
@@ -209,10 +204,6 @@ static int __init exynos4_init_cpuidle(void)
 		device = &per_cpu(exynos4_cpuidle_device, cpu_id);
 		device->cpu = cpu_id;
 
-		/* Support IDLE only */
-		if (cpu_id != 0)
-			device->state_count = 1;
-

Are you sure that this is okay? It means, assuming that you have CPU0 hotplug enabled, that you can enter the AFTR state if _any_ single core remains plugged in, which is technically possible, but then wake-up will occur on CPU0, which is not what cpuidle and hotplug code expect.

P.S. Please keep linux-samsung-soc at vger.kernel.org mailing list on Cc for patches related to Samsung SoCs.

Best regards,
Tomasz

#11 lore raw

PATCH 1/4 ARM: exynos: cpuidle: Fallback to WFI, when AFTR is selected

Quoted 44 lines · Tomasz Figa

Hi Daniel,

Quoted 41 lines · On Thursday 18 of July 2013 14:54:27 Daniel Lezcano wrote:

When there are several cpus online, the AFTR state does not work.

The AFTR must be selected only when there is one cpu online.

The previous code was already handling this case.

Simplified the code, especially the init routine to have the same init pattern than the other drivers.

---
 arch/arm/mach-exynos/cpuidle.c |   13 ++-----------
 1 file changed, 2 insertions(+), 11 deletions(-)
(quoted diff) +0 -0

b/arch/arm/mach-exynos/cpuidle.c index 17a18ff..cc4b097 100644

arch/arm/mach-exynos/cpuidle.c +2 -7
@@ -147,16 +147,11 @@ static int exynos4_enter_lowpower(struct
 cpuidle_device *dev, struct cpuidle_driver *drv,
 				int index)
 {
-	int new_index = index;
-
 	/* This mode only can be entered when other core's are offline */
 	if (num_online_cpus() > 1)
-		new_index = drv->safe_state_index;
+		return drv->states[0].enter(dev, drv, 0);
 
-	if (new_index == 0)
-		return arm_cpuidle_simple_enter(dev, drv, new_index);
-	else
-		return exynos4_enter_core0_aftr(dev, drv, new_index);
+	return exynos4_enter_core0_aftr(dev, drv, index);
 }
 
 static void __init exynos5_core_down_clk(void)
@@ -209,10 +204,6 @@ static int __init exynos4_init_cpuidle(void)
 		device = &per_cpu(exynos4_cpuidle_device, cpu_id);
 		device->cpu = cpu_id;
 
Quoted 9 lines

arch/arm/mach-exynos/cpuidle.c static int __init exynos4_init_cpuidle(void) · line 215

Quoted 4 lines
arch/arm/mach-exynos/cpuidle.c +0 -4
-		/* Support IDLE only */
-		if (cpu_id != 0)
-			device->state_count = 1;
-

Are you sure that this is okay? It means, assuming that you have CPU0 hotplug enabled, that you can enter the AFTR state if _any_ single core remains plugged in, which is technically possible, but then wake-up will occur on CPU0, which is not what cpuidle and hotplug code expect.

I worry that the current code is already broken in this respect as cpuidle core is using driver->state_count for everything except creating/destroying sysfs state entries. This is probably something that needs to be fixed in the cpuidle core (I suspect that governors should use device->state_count instead of driver->state_count but it would need confirmation from someone that knows this code better) but in the meantime it could be fixed by adding CPU0 check to exynos4_enter_lowpower() (if the last CPU != 0 then don't go into AFTR mode).

Best regards,
--
Bartlomiej Zolnierkiewicz
Samsung R&D Institute Poland
Samsung Electronics

Quoted 5 lines

P.S. Please keep linux-samsung-soc at vger.kernel.org mailing list on Cc for patches related to Samsung SoCs.

Best regards,
Tomasz