aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpreeti <preeti@linux.vnet.ibm.com>2015-06-24 02:48:01 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-07-10 12:49:35 -0400
commitb9d118e11a1b94c155a1cc985f1a2d3a9e03da2f (patch)
tree24b324c2a4c751fa4f32dec31e2f3d9de7638f7b
parent301773b62355e8a6028a8023be2d04c7317915d9 (diff)
tick/idle/powerpc: Do not register idle states with CPUIDLE_FLAG_TIMER_STOP set in periodic mode
commit cc5a2f7b8f39e7db559778f7913a2410257b3e50 upstream. On some archs, the local clockevent device stops in deep cpuidle states. The broadcast framework is used to wakeup cpus in these idle states, in which either an external clockevent device is used to send wakeup ipis or the hrtimer broadcast framework kicks in in the absence of such a device. One cpu is nominated as the broadcast cpu and this cpu sends wakeup ipis to sleeping cpus at the appropriate time. This is the implementation in the oneshot mode of broadcast. In periodic mode of broadcast however, the presence of such cpuidle states results in the cpuidle driver calling tick_broadcast_enable() which shuts down the local clockevent devices of all the cpus and appoints the tick broadcast device as the clockevent device for each of them. This works on those archs where the tick broadcast device is a real clockevent device. But on archs which depend on the hrtimer mode of broadcast, the tick broadcast device hapens to be a pseudo device. The consequence is that the local clockevent devices of all cpus are shutdown and the kernel hangs at boot time in periodic mode. Let us thus not register the cpuidle states which have CPUIDLE_FLAG_TIMER_STOP flag set, on archs which depend on the hrtimer mode of broadcast in periodic mode. This patch takes care of doing this on powerpc. The cpus would not have entered into such deep cpuidle states in periodic mode on powerpc anyway. So there is no loss here. Signed-off-by: Preeti U Murthy <preeti@linux.vnet.ibm.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/cpuidle/cpuidle-powernv.c15
1 files changed, 12 insertions, 3 deletions
diff --git a/drivers/cpuidle/cpuidle-powernv.c b/drivers/cpuidle/cpuidle-powernv.c
index 59372077ec7c..3442764a5293 100644
--- a/drivers/cpuidle/cpuidle-powernv.c
+++ b/drivers/cpuidle/cpuidle-powernv.c
@@ -60,6 +60,8 @@ static int nap_loop(struct cpuidle_device *dev,
60 return index; 60 return index;
61} 61}
62 62
63/* Register for fastsleep only in oneshot mode of broadcast */
64#ifdef CONFIG_TICK_ONESHOT
63static int fastsleep_loop(struct cpuidle_device *dev, 65static int fastsleep_loop(struct cpuidle_device *dev,
64 struct cpuidle_driver *drv, 66 struct cpuidle_driver *drv,
65 int index) 67 int index)
@@ -83,7 +85,7 @@ static int fastsleep_loop(struct cpuidle_device *dev,
83 85
84 return index; 86 return index;
85} 87}
86 88#endif
87/* 89/*
88 * States for dedicated partition case. 90 * States for dedicated partition case.
89 */ 91 */
@@ -209,7 +211,14 @@ static int powernv_add_idle_states(void)
209 powernv_states[nr_idle_states].flags = 0; 211 powernv_states[nr_idle_states].flags = 0;
210 powernv_states[nr_idle_states].target_residency = 100; 212 powernv_states[nr_idle_states].target_residency = 100;
211 powernv_states[nr_idle_states].enter = &nap_loop; 213 powernv_states[nr_idle_states].enter = &nap_loop;
212 } else if (flags[i] & OPAL_PM_SLEEP_ENABLED || 214 }
215
216 /*
217 * All cpuidle states with CPUIDLE_FLAG_TIMER_STOP set must come
218 * within this config dependency check.
219 */
220#ifdef CONFIG_TICK_ONESHOT
221 if (flags[i] & OPAL_PM_SLEEP_ENABLED ||
213 flags[i] & OPAL_PM_SLEEP_ENABLED_ER1) { 222 flags[i] & OPAL_PM_SLEEP_ENABLED_ER1) {
214 /* Add FASTSLEEP state */ 223 /* Add FASTSLEEP state */
215 strcpy(powernv_states[nr_idle_states].name, "FastSleep"); 224 strcpy(powernv_states[nr_idle_states].name, "FastSleep");
@@ -218,7 +227,7 @@ static int powernv_add_idle_states(void)
218 powernv_states[nr_idle_states].target_residency = 300000; 227 powernv_states[nr_idle_states].target_residency = 300000;
219 powernv_states[nr_idle_states].enter = &fastsleep_loop; 228 powernv_states[nr_idle_states].enter = &fastsleep_loop;
220 } 229 }
221 230#endif
222 powernv_states[nr_idle_states].exit_latency = 231 powernv_states[nr_idle_states].exit_latency =
223 ((unsigned int)latency_ns[i]) / 1000; 232 ((unsigned int)latency_ns[i]) / 1000;
224 233