diff options
-rw-r--r-- | kernel/power/power.h | 20 | ||||
-rw-r--r-- | kernel/power/snapshot.c | 53 |
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 | ||
19 | extern int arch_hibernation_header_save(void *addr, unsigned int max_size); | ||
20 | extern int arch_hibernation_header_restore(void *addr); | ||
21 | |||
22 | static inline int init_header_complete(struct swsusp_info *info) | ||
23 | { | ||
24 | return arch_hibernation_header_save(info, MAX_ARCH_HEADER_SIZE); | ||
25 | } | ||
26 | |||
27 | static 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 | ||
1242 | static void init_header(struct swsusp_info *info) | 1242 | #ifndef CONFIG_ARCH_HIBERNATION_HEADER |
1243 | static 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 | |||
1250 | static 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 | |||
1266 | static 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(©_bm); | 1335 | memory_bm_position_reset(©_bm); |
@@ -1394,22 +1420,13 @@ duplicate_memory_bitmap(struct memory_bitmap *dst, struct memory_bitmap *src) | |||
1394 | } | 1420 | } |
1395 | } | 1421 | } |
1396 | 1422 | ||
1397 | static inline int check_header(struct swsusp_info *info) | 1423 | static 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; |