diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2015-02-26 18:39:56 -0500 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2015-02-28 17:46:39 -0500 |
commit | 31a3409065d1d5bf0f12ad76b8c7f471134bf596 (patch) | |
tree | 857d4b8dca6271110b933685db69540a2854ce05 /drivers/cpuidle/cpuidle.c | |
parent | 01e04f466e12e883907937eb04a9010533363f55 (diff) |
cpuidle / sleep: Do sanity checks in cpuidle_enter_freeze() too
Modify cpuidle_enter_freeze() to do the sanity checks done by
cpuidle_select() to avoid crashing the suspend-to-idle code
path in case something is missing.
Fixes: 381063133246 (PM / sleep: Re-implement suspend-to-idle handling)
Original-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Diffstat (limited to 'drivers/cpuidle/cpuidle.c')
-rw-r--r-- | drivers/cpuidle/cpuidle.c | 23 |
1 files changed, 16 insertions, 7 deletions
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index b573f584b15a..8b3e132b6a01 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c | |||
@@ -44,6 +44,12 @@ void disable_cpuidle(void) | |||
44 | off = 1; | 44 | off = 1; |
45 | } | 45 | } |
46 | 46 | ||
47 | static bool cpuidle_not_available(struct cpuidle_driver *drv, | ||
48 | struct cpuidle_device *dev) | ||
49 | { | ||
50 | return off || !initialized || !drv || !dev || !dev->enabled; | ||
51 | } | ||
52 | |||
47 | /** | 53 | /** |
48 | * cpuidle_play_dead - cpu off-lining | 54 | * cpuidle_play_dead - cpu off-lining |
49 | * | 55 | * |
@@ -126,6 +132,9 @@ void cpuidle_enter_freeze(void) | |||
126 | struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev); | 132 | struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev); |
127 | int index; | 133 | int index; |
128 | 134 | ||
135 | if (cpuidle_not_available(drv, dev)) | ||
136 | goto fallback; | ||
137 | |||
129 | /* | 138 | /* |
130 | * Find the deepest state with ->enter_freeze present, which guarantees | 139 | * Find the deepest state with ->enter_freeze present, which guarantees |
131 | * that interrupts won't be enabled when it exits and allows the tick to | 140 | * that interrupts won't be enabled when it exits and allows the tick to |
@@ -143,10 +152,13 @@ void cpuidle_enter_freeze(void) | |||
143 | * at all and try to enter it normally. | 152 | * at all and try to enter it normally. |
144 | */ | 153 | */ |
145 | index = cpuidle_find_deepest_state(drv, dev, false); | 154 | index = cpuidle_find_deepest_state(drv, dev, false); |
146 | if (index >= 0) | 155 | if (index >= 0) { |
147 | cpuidle_enter(drv, dev, index); | 156 | cpuidle_enter(drv, dev, index); |
148 | else | 157 | return; |
149 | arch_cpu_idle(); | 158 | } |
159 | |||
160 | fallback: | ||
161 | arch_cpu_idle(); | ||
150 | } | 162 | } |
151 | 163 | ||
152 | /** | 164 | /** |
@@ -205,12 +217,9 @@ int cpuidle_enter_state(struct cpuidle_device *dev, struct cpuidle_driver *drv, | |||
205 | */ | 217 | */ |
206 | int cpuidle_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) | 218 | int cpuidle_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) |
207 | { | 219 | { |
208 | if (off || !initialized) | 220 | if (cpuidle_not_available(drv, dev)) |
209 | return -ENODEV; | 221 | return -ENODEV; |
210 | 222 | ||
211 | if (!drv || !dev || !dev->enabled) | ||
212 | return -EBUSY; | ||
213 | |||
214 | return cpuidle_curr_governor->select(drv, dev); | 223 | return cpuidle_curr_governor->select(drv, dev); |
215 | } | 224 | } |
216 | 225 | ||