aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/power/swsusp.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/power/swsusp.c')
-rw-r--r--kernel/power/swsusp.c122
1 files changed, 0 insertions, 122 deletions
diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c
index 87b901cb3927..6a07f4dbf2f8 100644
--- a/kernel/power/swsusp.c
+++ b/kernel/power/swsusp.c
@@ -186,125 +186,3 @@ void swsusp_show_speed(struct timeval *start, struct timeval *stop,
186 centisecs / 100, centisecs % 100, 186 centisecs / 100, centisecs % 100,
187 kps / 1000, (kps % 1000) / 10); 187 kps / 1000, (kps % 1000) / 10);
188} 188}
189
190/*
191 * Platforms, like ACPI, may want us to save some memory used by them during
192 * hibernation and to restore the contents of this memory during the subsequent
193 * resume. The code below implements a mechanism allowing us to do that.
194 */
195
196struct nvs_page {
197 unsigned long phys_start;
198 unsigned int size;
199 void *kaddr;
200 void *data;
201 struct list_head node;
202};
203
204static LIST_HEAD(nvs_list);
205
206/**
207 * hibernate_nvs_register - register platform NVS memory region to save
208 * @start - physical address of the region
209 * @size - size of the region
210 *
211 * The NVS region need not be page-aligned (both ends) and we arrange
212 * things so that the data from page-aligned addresses in this region will
213 * be copied into separate RAM pages.
214 */
215int hibernate_nvs_register(unsigned long start, unsigned long size)
216{
217 struct nvs_page *entry, *next;
218
219 while (size > 0) {
220 unsigned int nr_bytes;
221
222 entry = kzalloc(sizeof(struct nvs_page), GFP_KERNEL);
223 if (!entry)
224 goto Error;
225
226 list_add_tail(&entry->node, &nvs_list);
227 entry->phys_start = start;
228 nr_bytes = PAGE_SIZE - (start & ~PAGE_MASK);
229 entry->size = (size < nr_bytes) ? size : nr_bytes;
230
231 start += entry->size;
232 size -= entry->size;
233 }
234 return 0;
235
236 Error:
237 list_for_each_entry_safe(entry, next, &nvs_list, node) {
238 list_del(&entry->node);
239 kfree(entry);
240 }
241 return -ENOMEM;
242}
243
244/**
245 * hibernate_nvs_free - free data pages allocated for saving NVS regions
246 */
247void hibernate_nvs_free(void)
248{
249 struct nvs_page *entry;
250
251 list_for_each_entry(entry, &nvs_list, node)
252 if (entry->data) {
253 free_page((unsigned long)entry->data);
254 entry->data = NULL;
255 if (entry->kaddr) {
256 iounmap(entry->kaddr);
257 entry->kaddr = NULL;
258 }
259 }
260}
261
262/**
263 * hibernate_nvs_alloc - allocate memory necessary for saving NVS regions
264 */
265int hibernate_nvs_alloc(void)
266{
267 struct nvs_page *entry;
268
269 list_for_each_entry(entry, &nvs_list, node) {
270 entry->data = (void *)__get_free_page(GFP_KERNEL);
271 if (!entry->data) {
272 hibernate_nvs_free();
273 return -ENOMEM;
274 }
275 }
276 return 0;
277}
278
279/**
280 * hibernate_nvs_save - save NVS memory regions
281 */
282void hibernate_nvs_save(void)
283{
284 struct nvs_page *entry;
285
286 printk(KERN_INFO "PM: Saving platform NVS memory\n");
287
288 list_for_each_entry(entry, &nvs_list, node)
289 if (entry->data) {
290 entry->kaddr = ioremap(entry->phys_start, entry->size);
291 memcpy(entry->data, entry->kaddr, entry->size);
292 }
293}
294
295/**
296 * hibernate_nvs_restore - restore NVS memory regions
297 *
298 * This function is going to be called with interrupts disabled, so it
299 * cannot iounmap the virtual addresses used to access the NVS region.
300 */
301void hibernate_nvs_restore(void)
302{
303 struct nvs_page *entry;
304
305 printk(KERN_INFO "PM: Restoring platform NVS memory\n");
306
307 list_for_each_entry(entry, &nvs_list, node)
308 if (entry->data)
309 memcpy(entry->kaddr, entry->data, entry->size);
310}