aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/power/user.c92
1 files changed, 58 insertions, 34 deletions
diff --git a/kernel/power/user.c b/kernel/power/user.c
index f7b7a785a5c6..4f217683455f 100644
--- a/kernel/power/user.c
+++ b/kernel/power/user.c
@@ -122,6 +122,59 @@ static ssize_t snapshot_write(struct file *filp, const char __user *buf,
122 return res; 122 return res;
123} 123}
124 124
125static inline int snapshot_suspend(void)
126{
127 int error;
128
129 mutex_lock(&pm_mutex);
130 /* Free memory before shutting down devices. */
131 error = swsusp_shrink_memory();
132 if (error)
133 goto Finish;
134
135 suspend_console();
136 error = device_suspend(PMSG_FREEZE);
137 if (error)
138 goto Resume_devices;
139
140 error = disable_nonboot_cpus();
141 if (!error) {
142 in_suspend = 1;
143 error = swsusp_suspend();
144 }
145 enable_nonboot_cpus();
146 Resume_devices:
147 device_resume();
148 resume_console();
149 Finish:
150 mutex_unlock(&pm_mutex);
151 return error;
152}
153
154static inline int snapshot_restore(void)
155{
156 int error;
157
158 mutex_lock(&pm_mutex);
159 pm_prepare_console();
160 suspend_console();
161 error = device_suspend(PMSG_PRETHAW);
162 if (error)
163 goto Resume_devices;
164
165 error = disable_nonboot_cpus();
166 if (!error)
167 error = swsusp_resume();
168
169 enable_nonboot_cpus();
170 Resume_devices:
171 device_resume();
172 resume_console();
173 pm_restore_console();
174 mutex_unlock(&pm_mutex);
175 return error;
176}
177
125static int snapshot_ioctl(struct inode *inode, struct file *filp, 178static int snapshot_ioctl(struct inode *inode, struct file *filp,
126 unsigned int cmd, unsigned long arg) 179 unsigned int cmd, unsigned long arg)
127{ 180{
@@ -145,14 +198,9 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,
145 if (data->frozen) 198 if (data->frozen)
146 break; 199 break;
147 mutex_lock(&pm_mutex); 200 mutex_lock(&pm_mutex);
148 error = disable_nonboot_cpus(); 201 if (freeze_processes()) {
149 if (!error) { 202 thaw_processes();
150 error = freeze_processes(); 203 error = -EBUSY;
151 if (error) {
152 thaw_processes();
153 enable_nonboot_cpus();
154 error = -EBUSY;
155 }
156 } 204 }
157 mutex_unlock(&pm_mutex); 205 mutex_unlock(&pm_mutex);
158 if (!error) 206 if (!error)
@@ -164,7 +212,6 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,
164 break; 212 break;
165 mutex_lock(&pm_mutex); 213 mutex_lock(&pm_mutex);
166 thaw_processes(); 214 thaw_processes();
167 enable_nonboot_cpus();
168 mutex_unlock(&pm_mutex); 215 mutex_unlock(&pm_mutex);
169 data->frozen = 0; 216 data->frozen = 0;
170 break; 217 break;
@@ -174,20 +221,7 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,
174 error = -EPERM; 221 error = -EPERM;
175 break; 222 break;
176 } 223 }
177 mutex_lock(&pm_mutex); 224 error = snapshot_suspend();
178 /* Free memory before shutting down devices. */
179 error = swsusp_shrink_memory();
180 if (!error) {
181 suspend_console();
182 error = device_suspend(PMSG_FREEZE);
183 if (!error) {
184 in_suspend = 1;
185 error = swsusp_suspend();
186 device_resume();
187 }
188 resume_console();
189 }
190 mutex_unlock(&pm_mutex);
191 if (!error) 225 if (!error)
192 error = put_user(in_suspend, (unsigned int __user *)arg); 226 error = put_user(in_suspend, (unsigned int __user *)arg);
193 if (!error) 227 if (!error)
@@ -201,17 +235,7 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,
201 error = -EPERM; 235 error = -EPERM;
202 break; 236 break;
203 } 237 }
204 mutex_lock(&pm_mutex); 238 error = snapshot_restore();
205 pm_prepare_console();
206 suspend_console();
207 error = device_suspend(PMSG_PRETHAW);
208 if (!error) {
209 error = swsusp_resume();
210 device_resume();
211 }
212 resume_console();
213 pm_restore_console();
214 mutex_unlock(&pm_mutex);
215 break; 239 break;
216 240
217 case SNAPSHOT_FREE: 241 case SNAPSHOT_FREE: