diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-09-02 19:21:03 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-09-02 19:21:03 -0400 |
commit | 62109b43176b87e78b2b6d91bcfe16128c30229b (patch) | |
tree | 1b308b37ad78c2a8edd31934bc99f74066fa6430 /kernel/power | |
parent | 69e273c0b0a3c337a521d083374c918dc52c666f (diff) |
PM / sleep: Fix test_suspend= command line option
After commit d431cbc53cb7 (PM / sleep: Simplify sleep states sysfs
interface code) the pm_states[] array is not populated initially,
which causes setup_test_suspend() to always fail and the suspend
testing during boot doesn't work any more.
Fix the problem by using pm_labels[] instead of pm_states[] in
setup_test_suspend() and storing a pointer to the label of the
sleep state to test rather than the number representing it,
because the connection between the state numbers and labels is
only established by suspend_set_ops().
Fixes: d431cbc53cb7 (PM / sleep: Simplify sleep states sysfs interface code)
Reported-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'kernel/power')
-rw-r--r-- | kernel/power/power.h | 1 | ||||
-rw-r--r-- | kernel/power/suspend.c | 2 | ||||
-rw-r--r-- | kernel/power/suspend_test.c | 31 |
3 files changed, 21 insertions, 13 deletions
diff --git a/kernel/power/power.h b/kernel/power/power.h index 5d49dcac2537..2df883a9d3cb 100644 --- a/kernel/power/power.h +++ b/kernel/power/power.h | |||
@@ -179,6 +179,7 @@ extern void swsusp_show_speed(struct timeval *, struct timeval *, | |||
179 | 179 | ||
180 | #ifdef CONFIG_SUSPEND | 180 | #ifdef CONFIG_SUSPEND |
181 | /* kernel/power/suspend.c */ | 181 | /* kernel/power/suspend.c */ |
182 | extern const char *pm_labels[]; | ||
182 | extern const char *pm_states[]; | 183 | extern const char *pm_states[]; |
183 | 184 | ||
184 | extern int suspend_devices_and_enter(suspend_state_t state); | 185 | extern int suspend_devices_and_enter(suspend_state_t state); |
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c index 6dadb25cb0d8..18c62195660f 100644 --- a/kernel/power/suspend.c +++ b/kernel/power/suspend.c | |||
@@ -31,7 +31,7 @@ | |||
31 | 31 | ||
32 | #include "power.h" | 32 | #include "power.h" |
33 | 33 | ||
34 | static const char *pm_labels[] = { "mem", "standby", "freeze", }; | 34 | const char *pm_labels[] = { "mem", "standby", "freeze", NULL }; |
35 | const char *pm_states[PM_SUSPEND_MAX]; | 35 | const char *pm_states[PM_SUSPEND_MAX]; |
36 | 36 | ||
37 | static const struct platform_suspend_ops *suspend_ops; | 37 | static const struct platform_suspend_ops *suspend_ops; |
diff --git a/kernel/power/suspend_test.c b/kernel/power/suspend_test.c index 2f524928b6aa..bd91bc177c93 100644 --- a/kernel/power/suspend_test.c +++ b/kernel/power/suspend_test.c | |||
@@ -129,20 +129,20 @@ static int __init has_wakealarm(struct device *dev, const void *data) | |||
129 | * at startup time. They're normally disabled, for faster boot and because | 129 | * at startup time. They're normally disabled, for faster boot and because |
130 | * we can't know which states really work on this particular system. | 130 | * we can't know which states really work on this particular system. |
131 | */ | 131 | */ |
132 | static suspend_state_t test_state __initdata = PM_SUSPEND_ON; | 132 | static const char *test_state_label __initdata; |
133 | 133 | ||
134 | static char warn_bad_state[] __initdata = | 134 | static char warn_bad_state[] __initdata = |
135 | KERN_WARNING "PM: can't test '%s' suspend state\n"; | 135 | KERN_WARNING "PM: can't test '%s' suspend state\n"; |
136 | 136 | ||
137 | static int __init setup_test_suspend(char *value) | 137 | static int __init setup_test_suspend(char *value) |
138 | { | 138 | { |
139 | suspend_state_t i; | 139 | int i; |
140 | 140 | ||
141 | /* "=mem" ==> "mem" */ | 141 | /* "=mem" ==> "mem" */ |
142 | value++; | 142 | value++; |
143 | for (i = PM_SUSPEND_MIN; i < PM_SUSPEND_MAX; i++) | 143 | for (i = 0; pm_labels[i]; i++) |
144 | if (!strcmp(pm_states[i], value)) { | 144 | if (!strcmp(pm_labels[i], value)) { |
145 | test_state = i; | 145 | test_state_label = pm_labels[i]; |
146 | return 0; | 146 | return 0; |
147 | } | 147 | } |
148 | 148 | ||
@@ -158,13 +158,21 @@ static int __init test_suspend(void) | |||
158 | 158 | ||
159 | struct rtc_device *rtc = NULL; | 159 | struct rtc_device *rtc = NULL; |
160 | struct device *dev; | 160 | struct device *dev; |
161 | suspend_state_t test_state; | ||
161 | 162 | ||
162 | /* PM is initialized by now; is that state testable? */ | 163 | /* PM is initialized by now; is that state testable? */ |
163 | if (test_state == PM_SUSPEND_ON) | 164 | if (!test_state_label) |
164 | goto done; | 165 | return 0; |
165 | if (!pm_states[test_state]) { | 166 | |
166 | printk(warn_bad_state, pm_states[test_state]); | 167 | for (test_state = PM_SUSPEND_MIN; test_state < PM_SUSPEND_MAX; test_state++) { |
167 | goto done; | 168 | const char *state_label = pm_states[test_state]; |
169 | |||
170 | if (state_label && !strcmp(test_state_label, state_label)) | ||
171 | break; | ||
172 | } | ||
173 | if (test_state == PM_SUSPEND_MAX) { | ||
174 | printk(warn_bad_state, test_state_label); | ||
175 | return 0; | ||
168 | } | 176 | } |
169 | 177 | ||
170 | /* RTCs have initialized by now too ... can we use one? */ | 178 | /* RTCs have initialized by now too ... can we use one? */ |
@@ -173,13 +181,12 @@ static int __init test_suspend(void) | |||
173 | rtc = rtc_class_open(dev_name(dev)); | 181 | rtc = rtc_class_open(dev_name(dev)); |
174 | if (!rtc) { | 182 | if (!rtc) { |
175 | printk(warn_no_rtc); | 183 | printk(warn_no_rtc); |
176 | goto done; | 184 | return 0; |
177 | } | 185 | } |
178 | 186 | ||
179 | /* go for it */ | 187 | /* go for it */ |
180 | test_wakealarm(rtc, test_state); | 188 | test_wakealarm(rtc, test_state); |
181 | rtc_class_close(rtc); | 189 | rtc_class_close(rtc); |
182 | done: | ||
183 | return 0; | 190 | return 0; |
184 | } | 191 | } |
185 | late_initcall(test_suspend); | 192 | late_initcall(test_suspend); |