aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpreeti <preeti@linux.vnet.ibm.com>2015-06-24 02:48:01 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2015-06-25 21:28:49 -0400
commitcc5a2f7b8f39e7db559778f7913a2410257b3e50 (patch)
treeb86e06f90abde65fcf65a7b6840eaa9c99cc9598
parent78eaa10f027cf69f9bd409e64eaff902172b2327 (diff)
tick/idle/powerpc: Do not register idle states with CPUIDLE_FLAG_TIMER_STOP set in periodic mode
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> Cc: 3.19+ <stable@vger.kernel.org> # 3.19+ Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-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 1e3ef5ec4784..845bafcfa792 100644
--- a/drivers/cpuidle/cpuidle-powernv.c
+++ b/drivers/cpuidle/cpuidle-powernv.c
@@ -67,6 +67,8 @@ static int nap_loop(struct cpuidle_device *dev,
67 return index; 67 return index;
68} 68}
69 69
70/* Register for fastsleep only in oneshot mode of broadcast */
71#ifdef CONFIG_TICK_ONESHOT
70static int fastsleep_loop(struct cpuidle_device *dev, 72static int fastsleep_loop(struct cpuidle_device *dev,
71 struct cpuidle_driver *drv, 73 struct cpuidle_driver *drv,
72 int index) 74 int index)
@@ -90,7 +92,7 @@ static int fastsleep_loop(struct cpuidle_device *dev,
90 92
91 return index; 93 return index;
92} 94}
93 95#endif
94/* 96/*
95 * States for dedicated partition case. 97 * States for dedicated partition case.
96 */ 98 */
@@ -216,7 +218,14 @@ static int powernv_add_idle_states(void)
216 powernv_states[nr_idle_states].flags = 0; 218 powernv_states[nr_idle_states].flags = 0;
217 powernv_states[nr_idle_states].target_residency = 100; 219 powernv_states[nr_idle_states].target_residency = 100;
218 powernv_states[nr_idle_states].enter = &nap_loop; 220 powernv_states[nr_idle_states].enter = &nap_loop;
219 } else if (flags[i] & OPAL_PM_SLEEP_ENABLED || 221 }
222
223 /*
224 * All cpuidle states with CPUIDLE_FLAG_TIMER_STOP set must come
225 * within this config dependency check.
226 */
227#ifdef CONFIG_TICK_ONESHOT
228 if (flags[i] & OPAL_PM_SLEEP_ENABLED ||
220 flags[i] & OPAL_PM_SLEEP_ENABLED_ER1) { 229 flags[i] & OPAL_PM_SLEEP_ENABLED_ER1) {
221 /* Add FASTSLEEP state */ 230 /* Add FASTSLEEP state */
222 strcpy(powernv_states[nr_idle_states].name, "FastSleep"); 231 strcpy(powernv_states[nr_idle_states].name, "FastSleep");
@@ -225,7 +234,7 @@ static int powernv_add_idle_states(void)
225 powernv_states[nr_idle_states].target_residency = 300000; 234 powernv_states[nr_idle_states].target_residency = 300000;
226 powernv_states[nr_idle_states].enter = &fastsleep_loop; 235 powernv_states[nr_idle_states].enter = &fastsleep_loop;
227 } 236 }
228 237#endif
229 powernv_states[nr_idle_states].exit_latency = 238 powernv_states[nr_idle_states].exit_latency =
230 ((unsigned int)latency_ns[i]) / 1000; 239 ((unsigned int)latency_ns[i]) / 1000;
231 240