aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/power/power.h20
-rw-r--r--kernel/power/snapshot.c53
2 files changed, 54 insertions, 19 deletions
diff --git a/kernel/power/power.h b/kernel/power/power.h
index 95fbf2dd3fe3..a0204dfc6c4c 100644
--- a/kernel/power/power.h
+++ b/kernel/power/power.h
@@ -11,14 +11,32 @@ struct swsusp_info {
11 unsigned long size; 11 unsigned long size;
12} __attribute__((aligned(PAGE_SIZE))); 12} __attribute__((aligned(PAGE_SIZE)));
13 13
14#ifdef CONFIG_HIBERNATION
15#ifdef CONFIG_ARCH_HIBERNATION_HEADER
16/* Maximum size of architecture specific data in a hibernation header */
17#define MAX_ARCH_HEADER_SIZE (sizeof(struct new_utsname) + 4)
14 18
19extern int arch_hibernation_header_save(void *addr, unsigned int max_size);
20extern int arch_hibernation_header_restore(void *addr);
21
22static inline int init_header_complete(struct swsusp_info *info)
23{
24 return arch_hibernation_header_save(info, MAX_ARCH_HEADER_SIZE);
25}
26
27static inline char *check_image_kernel(struct swsusp_info *info)
28{
29 return arch_hibernation_header_restore(info) ?
30 "architecture specific data" : NULL;
31}
32#endif /* CONFIG_ARCH_HIBERNATION_HEADER */
15 33
16#ifdef CONFIG_HIBERNATION
17/* 34/*
18 * Keep some memory free so that I/O operations can succeed without paging 35 * Keep some memory free so that I/O operations can succeed without paging
19 * [Might this be more than 4 MB?] 36 * [Might this be more than 4 MB?]
20 */ 37 */
21#define PAGES_FOR_IO ((4096 * 1024) >> PAGE_SHIFT) 38#define PAGES_FOR_IO ((4096 * 1024) >> PAGE_SHIFT)
39
22/* 40/*
23 * Keep 1 MB of memory free so that device drivers can allocate some pages in 41 * Keep 1 MB of memory free so that device drivers can allocate some pages in
24 * their .suspend() routines without breaking the suspend to disk. 42 * their .suspend() routines without breaking the suspend to disk.
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
index a686590d88c1..ccc95ac07bed 100644
--- a/kernel/power/snapshot.c
+++ b/kernel/power/snapshot.c
@@ -1239,17 +1239,39 @@ asmlinkage int swsusp_save(void)
1239 return 0; 1239 return 0;
1240} 1240}
1241 1241
1242static void init_header(struct swsusp_info *info) 1242#ifndef CONFIG_ARCH_HIBERNATION_HEADER
1243static int init_header_complete(struct swsusp_info *info)
1243{ 1244{
1244 memset(info, 0, sizeof(struct swsusp_info)); 1245 memcpy(&info->uts, init_utsname(), sizeof(struct new_utsname));
1245 info->version_code = LINUX_VERSION_CODE; 1246 info->version_code = LINUX_VERSION_CODE;
1247 return 0;
1248}
1249
1250static char *check_image_kernel(struct swsusp_info *info)
1251{
1252 if (info->version_code != LINUX_VERSION_CODE)
1253 return "kernel version";
1254 if (strcmp(info->uts.sysname,init_utsname()->sysname))
1255 return "system type";
1256 if (strcmp(info->uts.release,init_utsname()->release))
1257 return "kernel release";
1258 if (strcmp(info->uts.version,init_utsname()->version))
1259 return "version";
1260 if (strcmp(info->uts.machine,init_utsname()->machine))
1261 return "machine";
1262 return NULL;
1263}
1264#endif /* CONFIG_ARCH_HIBERNATION_HEADER */
1265
1266static int init_header(struct swsusp_info *info)
1267{
1268 memset(info, 0, sizeof(struct swsusp_info));
1246 info->num_physpages = num_physpages; 1269 info->num_physpages = num_physpages;
1247 memcpy(&info->uts, init_utsname(), sizeof(struct new_utsname));
1248 info->cpus = num_online_cpus();
1249 info->image_pages = nr_copy_pages; 1270 info->image_pages = nr_copy_pages;
1250 info->pages = nr_copy_pages + nr_meta_pages + 1; 1271 info->pages = nr_copy_pages + nr_meta_pages + 1;
1251 info->size = info->pages; 1272 info->size = info->pages;
1252 info->size <<= PAGE_SHIFT; 1273 info->size <<= PAGE_SHIFT;
1274 return init_header_complete(info);
1253} 1275}
1254 1276
1255/** 1277/**
@@ -1303,7 +1325,11 @@ int snapshot_read_next(struct snapshot_handle *handle, size_t count)
1303 return -ENOMEM; 1325 return -ENOMEM;
1304 } 1326 }
1305 if (!handle->offset) { 1327 if (!handle->offset) {
1306 init_header((struct swsusp_info *)buffer); 1328 int error;
1329
1330 error = init_header((struct swsusp_info *)buffer);
1331 if (error)
1332 return error;
1307 handle->buffer = buffer; 1333 handle->buffer = buffer;
1308 memory_bm_position_reset(&orig_bm); 1334 memory_bm_position_reset(&orig_bm);
1309 memory_bm_position_reset(&copy_bm); 1335 memory_bm_position_reset(&copy_bm);
@@ -1394,22 +1420,13 @@ duplicate_memory_bitmap(struct memory_bitmap *dst, struct memory_bitmap *src)
1394 } 1420 }
1395} 1421}
1396 1422
1397static inline int check_header(struct swsusp_info *info) 1423static int check_header(struct swsusp_info *info)
1398{ 1424{
1399 char *reason = NULL; 1425 char *reason;
1400 1426
1401 if (info->version_code != LINUX_VERSION_CODE) 1427 reason = check_image_kernel(info);
1402 reason = "kernel version"; 1428 if (!reason && info->num_physpages != num_physpages)
1403 if (info->num_physpages != num_physpages)
1404 reason = "memory size"; 1429 reason = "memory size";
1405 if (strcmp(info->uts.sysname,init_utsname()->sysname))
1406 reason = "system type";
1407 if (strcmp(info->uts.release,init_utsname()->release))
1408 reason = "kernel release";
1409 if (strcmp(info->uts.version,init_utsname()->version))
1410 reason = "version";
1411 if (strcmp(info->uts.machine,init_utsname()->machine))
1412 reason = "machine";
1413 if (reason) { 1430 if (reason) {
1414 printk(KERN_ERR "swsusp: Resume mismatch: %s\n", reason); 1431 printk(KERN_ERR "swsusp: Resume mismatch: %s\n", reason);
1415 return -EPERM; 1432 return -EPERM;