drivers: power: report battery voltage in AOSP compatible format
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / kernel / power / tuxonice_highlevel.c
1 /*
2 * kernel/power/tuxonice_highlevel.c
3 */
4 /** \mainpage TuxOnIce.
5 *
6 * TuxOnIce provides support for saving and restoring an image of
7 * system memory to an arbitrary storage device, either on the local computer,
8 * or across some network. The support is entirely OS based, so TuxOnIce
9 * works without requiring BIOS, APM or ACPI support. The vast majority of the
10 * code is also architecture independant, so it should be very easy to port
11 * the code to new architectures. TuxOnIce includes support for SMP, 4G HighMem
12 * and preemption. Initramfses and initrds are also supported.
13 *
14 * TuxOnIce uses a modular design, in which the method of storing the image is
15 * completely abstracted from the core code, as are transformations on the data
16 * such as compression and/or encryption (multiple 'modules' can be used to
17 * provide arbitrary combinations of functionality). The user interface is also
18 * modular, so that arbitrarily simple or complex interfaces can be used to
19 * provide anything from debugging information through to eye candy.
20 *
21 * \section Copyright
22 *
23 * TuxOnIce is released under the GPLv2.
24 *
25 * Copyright (C) 1998-2001 Gabor Kuti <seasons@fornax.hu><BR>
26 * Copyright (C) 1998,2001,2002 Pavel Machek <pavel@suse.cz><BR>
27 * Copyright (C) 2002-2003 Florent Chabaud <fchabaud@free.fr><BR>
28 * Copyright (C) 2002-2010 Nigel Cunningham (nigel at tuxonice net)<BR>
29 *
30 * \section Credits
31 *
32 * Nigel would like to thank the following people for their work:
33 *
34 * Bernard Blackham <bernard@blackham.com.au><BR>
35 * Web page & Wiki administration, some coding. A person without whom
36 * TuxOnIce would not be where it is.
37 *
38 * Michael Frank <mhf@linuxmail.org><BR>
39 * Extensive testing and help with improving stability. I was constantly
40 * amazed by the quality and quantity of Michael's help.
41 *
42 * Pavel Machek <pavel@ucw.cz><BR>
43 * Modifications, defectiveness pointing, being with Gabor at the very
44 * beginning, suspend to swap space, stop all tasks. Port to 2.4.18-ac and
45 * 2.5.17. Even though Pavel and I disagree on the direction suspend to
46 * disk should take, I appreciate the valuable work he did in helping Gabor
47 * get the concept working.
48 *
49 * ..and of course the myriads of TuxOnIce users who have helped diagnose
50 * and fix bugs, made suggestions on how to improve the code, proofread
51 * documentation, and donated time and money.
52 *
53 * Thanks also to corporate sponsors:
54 *
55 * <B>Redhat.</B>Sometime employer from May 2006 (my fault, not Redhat's!).
56 *
57 * <B>Cyclades.com.</B> Nigel's employers from Dec 2004 until May 2006, who
58 * allowed him to work on TuxOnIce and PM related issues on company time.
59 *
60 * <B>LinuxFund.org.</B> Sponsored Nigel's work on TuxOnIce for four months Oct
61 * 2003 to Jan 2004.
62 *
63 * <B>LAC Linux.</B> Donated P4 hardware that enabled development and ongoing
64 * maintenance of SMP and Highmem support.
65 *
66 * <B>OSDL.</B> Provided access to various hardware configurations, make
67 * occasional small donations to the project.
68 */
69
70 #include <linux/suspend.h>
71 #include <linux/freezer.h>
72 #include <generated/utsrelease.h>
73 #include <linux/cpu.h>
74 #include <linux/console.h>
75 #include <linux/writeback.h>
76 #include <linux/uaccess.h> /* for get/set_fs & KERNEL_DS on i386 */
77 #include <linux/bio.h>
78 #include <linux/kgdb.h>
79
80 #include "tuxonice.h"
81 #include "tuxonice_modules.h"
82 #include "tuxonice_sysfs.h"
83 #include "tuxonice_prepare_image.h"
84 #include "tuxonice_io.h"
85 #include "tuxonice_ui.h"
86 #include "tuxonice_power_off.h"
87 #include "tuxonice_storage.h"
88 #include "tuxonice_checksum.h"
89 #include "tuxonice_builtin.h"
90 #include "tuxonice_atomic_copy.h"
91 #include "tuxonice_alloc.h"
92 #include "tuxonice_cluster.h"
93
94 /*! Pageset metadata. */
95 struct pagedir pagedir2 = { 2 };
96
97 EXPORT_SYMBOL_GPL(pagedir2);
98
99 static mm_segment_t oldfs;
100 static DEFINE_MUTEX(tuxonice_in_use);
101 static int block_dump_save;
102
103 /* Binary signature if an image is present */
104 char tuxonice_signature[9] = "\xed\xc3\x02\xe9\x98\x56\xe5\x0c";
105 EXPORT_SYMBOL_GPL(tuxonice_signature);
106
107 unsigned long boot_kernel_data_buffer;
108
109 #if 0 /* JJ: removed it */
110 static char *result_strings[] = {
111 "Hibernation was aborted",
112 "The user requested that we cancel the hibernation",
113 "No storage was available",
114 "Insufficient storage was available",
115 "Freezing filesystems and/or tasks failed",
116 "A pre-existing image was used",
117 "We would free memory, but image size limit doesn't allow this",
118 "Unable to free enough memory to hibernate",
119 "Unable to obtain the Power Management Semaphore",
120 "A device suspend/resume returned an error",
121 "A system device suspend/resume returned an error",
122 "The extra pages allowance is too small",
123 "We were unable to successfully prepare an image",
124 "TuxOnIce module initialisation failed",
125 "TuxOnIce module cleanup failed",
126 "I/O errors were encountered",
127 "Ran out of memory",
128 "An error was encountered while reading the image",
129 "Platform preparation failed",
130 "CPU Hotplugging failed",
131 "Architecture specific preparation failed",
132 "Pages needed resaving, but we were told to abort if this happens",
133 "We can't hibernate at the moment (invalid resume= or filewriter " "target?)",
134 "A hibernation preparation notifier chain member cancelled the " "hibernation",
135 "Pre-snapshot preparation failed",
136 "Pre-restore preparation failed",
137 "Failed to disable usermode helpers",
138 "Can't resume from alternate image",
139 "Header reservation too small",
140 "Device Power Management Preparation failed",
141 };
142 #endif
143
144 /**
145 * toi_finish_anything - cleanup after doing anything
146 * @hibernate_or_resume: Whether finishing a cycle or attempt at
147 * resuming.
148 *
149 * This is our basic clean-up routine, matching start_anything below. We
150 * call cleanup routines, drop module references and restore process fs and
151 * cpus allowed masks, together with the global block_dump variable's value.
152 **/
153 void toi_finish_anything(int hibernate_or_resume)
154 {
155 hib_log("hibernate_or_resume(%d)\n", hibernate_or_resume);
156 toi_cleanup_modules(hibernate_or_resume);
157 toi_put_modules();
158 if (hibernate_or_resume) {
159 block_dump = block_dump_save;
160 set_cpus_allowed_ptr(current, cpu_all_mask);
161 toi_alloc_print_debug_stats();
162 atomic_inc(&snapshot_device_available);
163 unlock_system_sleep();
164 }
165
166 set_fs(oldfs);
167 mutex_unlock(&tuxonice_in_use);
168 }
169
170 /**
171 * toi_start_anything - basic initialisation for TuxOnIce
172 * @toi_or_resume: Whether starting a cycle or attempt at resuming.
173 *
174 * Our basic initialisation routine. Take references on modules, use the
175 * kernel segment, recheck resume= if no active allocator is set, initialise
176 * modules, save and reset block_dump and ensure we're running on CPU0.
177 **/
178 int toi_start_anything(int hibernate_or_resume)
179 {
180 mutex_lock(&tuxonice_in_use);
181
182 oldfs = get_fs();
183 set_fs(KERNEL_DS);
184
185 if (hibernate_or_resume) {
186 lock_system_sleep();
187
188 if (!atomic_add_unless(&snapshot_device_available, -1, 0))
189 goto snapshotdevice_unavailable;
190 }
191
192 if (hibernate_or_resume == SYSFS_HIBERNATE)
193 toi_print_modules();
194
195 if (toi_get_modules()) {
196 printk(KERN_INFO "TuxOnIce: Get modules failed!\n");
197 goto prehibernate_err;
198 }
199
200 if (hibernate_or_resume) {
201 block_dump_save = block_dump;
202 block_dump = 0;
203 set_cpus_allowed_ptr(current, cpumask_of(cpumask_first(cpu_online_mask)));
204 }
205
206 if (toi_initialise_modules_early(hibernate_or_resume))
207 goto early_init_err;
208
209 if (!toiActiveAllocator) {
210 hib_log("hibernate_or_resume(0x%08x), resume_file=\"%s\"\n", hibernate_or_resume,
211 resume_file);
212 toi_attempt_to_parse_resume_device(!hibernate_or_resume);
213 }
214
215 if (!toi_initialise_modules_late(hibernate_or_resume))
216 return 0;
217
218 toi_cleanup_modules(hibernate_or_resume);
219 early_init_err:
220 if (hibernate_or_resume) {
221 block_dump_save = block_dump;
222 set_cpus_allowed_ptr(current, cpu_all_mask);
223 }
224 toi_put_modules();
225 prehibernate_err:
226 if (hibernate_or_resume)
227 atomic_inc(&snapshot_device_available);
228 snapshotdevice_unavailable:
229 if (hibernate_or_resume)
230 mutex_unlock(&pm_mutex);
231 set_fs(oldfs);
232 mutex_unlock(&tuxonice_in_use);
233 return -EBUSY;
234 }
235
236 /*
237 * Nosave page tracking.
238 *
239 * Here rather than in prepare_image because we want to do it once only at the
240 * start of a cycle.
241 */
242
243 /**
244 * mark_nosave_pages - set up our Nosave bitmap
245 *
246 * Build a bitmap of Nosave pages from the list. The bitmap allows faster
247 * use when preparing the image.
248 **/
249 static void mark_nosave_pages(void)
250 {
251 struct nosave_region *region;
252
253 list_for_each_entry(region, &nosave_regions, list) {
254 unsigned long pfn;
255
256 for (pfn = region->start_pfn; pfn < region->end_pfn; pfn++)
257 if (pfn_valid(pfn))
258 SetPageNosave(pfn_to_page(pfn));
259 }
260 }
261
262 static int toi_alloc_bitmap(struct memory_bitmap **bm)
263 {
264 int result = 0;
265
266 *bm = kzalloc(sizeof(struct memory_bitmap), GFP_KERNEL);
267 if (!*bm) {
268 printk(KERN_ERR "Failed to kzalloc memory for a bitmap.\n");
269 return -ENOMEM;
270 }
271
272 result = memory_bm_create(*bm, GFP_KERNEL, 0);
273
274 if (result) {
275 printk(KERN_ERR "Failed to create a bitmap.\n");
276 kfree(*bm);
277 *bm = NULL;
278 }
279
280 return result;
281 }
282
283 /**
284 * allocate_bitmaps - allocate bitmaps used to record page states
285 *
286 * Allocate the bitmaps we use to record the various TuxOnIce related
287 * page states.
288 **/
289 static int allocate_bitmaps(void)
290 {
291 if (toi_alloc_bitmap(&pageset1_map) ||
292 toi_alloc_bitmap(&pageset1_copy_map) ||
293 toi_alloc_bitmap(&pageset2_map) ||
294 toi_alloc_bitmap(&io_map) ||
295 toi_alloc_bitmap(&nosave_map) ||
296 toi_alloc_bitmap(&free_map) || toi_alloc_bitmap(&page_resave_map))
297 return 1;
298
299 return 0;
300 }
301
302 static void toi_free_bitmap(struct memory_bitmap **bm)
303 {
304 if (!*bm)
305 return;
306
307 memory_bm_free(*bm, 0);
308 kfree(*bm);
309 *bm = NULL;
310 }
311
312 /**
313 * free_bitmaps - free the bitmaps used to record page states
314 *
315 * Free the bitmaps allocated above. It is not an error to call
316 * memory_bm_free on a bitmap that isn't currently allocated.
317 **/
318 static void free_bitmaps(void)
319 {
320 toi_free_bitmap(&pageset1_map);
321 toi_free_bitmap(&pageset1_copy_map);
322 toi_free_bitmap(&pageset2_map);
323 toi_free_bitmap(&io_map);
324 toi_free_bitmap(&nosave_map);
325 toi_free_bitmap(&free_map);
326 toi_free_bitmap(&page_resave_map);
327 }
328
329 /**
330 * io_MB_per_second - return the number of MB/s read or written
331 * @write: Whether to return the speed at which we wrote.
332 *
333 * Calculate the number of megabytes per second that were read or written.
334 **/
335 static int io_MB_per_second(int write)
336 {
337 return (toi_bkd.toi_io_time[write][1]) ?
338 MB((unsigned long)toi_bkd.toi_io_time[write][0]) * HZ /
339 toi_bkd.toi_io_time[write][1] : 0;
340 }
341
342 #define SNPRINTF(a...) do { len += scnprintf(((char *) buffer) + len, \
343 count - len - 1, ## a); } while (0)
344
345 /**
346 * get_debug_info - fill a buffer with debugging information
347 * @buffer: The buffer to be filled.
348 * @count: The size of the buffer, in bytes.
349 *
350 * Fill a (usually PAGE_SIZEd) buffer with the debugging info that we will
351 * either printk or return via sysfs.
352 **/
353 static int get_toi_debug_info(const char *buffer, int count)
354 {
355 int len = 0, i, first_result = 1;
356
357 SNPRINTF("TuxOnIce debugging info:\n");
358 SNPRINTF("- TuxOnIce core : " TOI_CORE_VERSION "\n");
359 SNPRINTF("- Kernel Version : " UTS_RELEASE "\n");
360 SNPRINTF("- Compiler vers. : %d.%d\n", __GNUC__, __GNUC_MINOR__);
361 SNPRINTF("- Attempt number : %d\n", nr_hibernates);
362 SNPRINTF("- Parameters : %ld %ld %ld %d %ld %ld\n",
363 toi_result,
364 toi_bkd.toi_action,
365 toi_bkd.toi_debug_state,
366 toi_bkd.toi_default_console_level, image_size_limit, toi_poweroff_method);
367 SNPRINTF("- Overall expected compression percentage: %d.\n",
368 100 - toi_expected_compression_ratio());
369 len += toi_print_module_debug_info(((char *)buffer) + len, count - len - 1);
370 if (toi_bkd.toi_io_time[0][1]) {
371 if ((io_MB_per_second(0) < 5) || (io_MB_per_second(1) < 5)) {
372 SNPRINTF("- I/O speed: Write %ld KB/s",
373 (KB((unsigned long)toi_bkd.toi_io_time[0][0]) * HZ /
374 toi_bkd.toi_io_time[0][1]));
375 if (toi_bkd.toi_io_time[1][1])
376 SNPRINTF(", Read %ld KB/s", (KB((unsigned long)
377 toi_bkd.toi_io_time[1][0]) * HZ /
378 toi_bkd.toi_io_time[1][1]));
379 } else {
380 SNPRINTF("- I/O speed: Write %ld MB/s",
381 (MB((unsigned long)toi_bkd.toi_io_time[0][0]) * HZ /
382 toi_bkd.toi_io_time[0][1]));
383 if (toi_bkd.toi_io_time[1][1])
384 SNPRINTF(", Read %ld MB/s", (MB((unsigned long)
385 toi_bkd.toi_io_time[1][0]) * HZ /
386 toi_bkd.toi_io_time[1][1]));
387 }
388 SNPRINTF(".\n");
389 } else
390 SNPRINTF("- No I/O speed stats available.\n");
391 SNPRINTF("- Extra pages : %lu used/%lu.\n",
392 extra_pd1_pages_used, extra_pd1_pages_allowance);
393
394 for (i = 0; i < TOI_NUM_RESULT_STATES; i++)
395 if (test_result_state(i)) {
396 #if 0 /* JJ: removed it */
397 SNPRINTF("%s: %s.\n", first_result ?
398 "- Result " : " ", result_strings[i]);
399 #endif
400 first_result = 0;
401 }
402 if (first_result) {
403 #if 0 /* JJ: removed it */
404 SNPRINTF("- Result : %s.\n", nr_hibernates ?
405 "Succeeded" : "No hibernation attempts so far");
406 #endif
407 }
408 return len;
409 }
410
411 /**
412 * do_cleanup - cleanup after attempting to hibernate or resume
413 * @get_debug_info: Whether to allocate and return debugging info.
414 *
415 * Cleanup after attempting to hibernate or resume, possibly getting
416 * debugging info as we do so.
417 **/
418 static void do_cleanup(int get_debug_info, int restarting)
419 {
420 int i = 0;
421 char *buffer = NULL;
422
423 trap_non_toi_io = 0;
424
425 if (get_debug_info)
426 toi_prepare_status(DONT_CLEAR_BAR, "Cleaning up...");
427 #if !defined(HIB_TOI_DEBUG) /* turn off the verbose when debug off */
428 hib_warn("Turn off debug info\n");
429 get_debug_info = 0;
430 #endif
431
432 #ifdef CONFIG_TOI_ENHANCE
433 toi_actual_compression_ratio(); /* keep the actual compressed ratio for reference */
434 #endif
435
436 free_checksum_pages();
437
438 if (get_debug_info)
439 buffer = (char *)toi_get_zeroed_page(20, TOI_ATOMIC_GFP);
440
441 if (buffer)
442 i = get_toi_debug_info(buffer, PAGE_SIZE);
443
444 toi_free_extra_pagedir_memory();
445
446 pagedir1.size = 0;
447 pagedir2.size = 0;
448 set_highmem_size(pagedir1, 0);
449 set_highmem_size(pagedir2, 0);
450
451 if (boot_kernel_data_buffer) {
452 if (!test_toi_state(TOI_BOOT_KERNEL))
453 toi_free_page(37, boot_kernel_data_buffer);
454 boot_kernel_data_buffer = 0;
455 }
456
457 clear_toi_state(TOI_BOOT_KERNEL);
458 thaw_processes();
459
460 if (!restarting)
461 toi_stop_other_threads();
462
463 if (test_action_state(TOI_KEEP_IMAGE) && !test_result_state(TOI_ABORTED)) {
464 toi_message(TOI_ANY_SECTION, TOI_LOW, 1,
465 "TuxOnIce: Not invalidating the image due "
466 "to Keep Image being enabled.");
467 set_result_state(TOI_KEPT_IMAGE);
468 } else if (toiActiveAllocator)
469 toiActiveAllocator->remove_image();
470
471 free_bitmaps();
472 usermodehelper_enable();
473
474 if (test_toi_state(TOI_NOTIFIERS_PREPARE)) {
475 pm_notifier_call_chain(PM_POST_HIBERNATION);
476 clear_toi_state(TOI_NOTIFIERS_PREPARE);
477 }
478
479 if (buffer && i) {
480 /* Printk can only handle 1023 bytes, including
481 * its level mangling. */
482 for (i = 0; i < 3; i++)
483 printk(KERN_ERR "%s", buffer + (1023 * i));
484 toi_free_page(20, (unsigned long)buffer);
485 }
486
487 if (!test_action_state(TOI_LATE_CPU_HOTPLUG))
488 enable_nonboot_cpus();
489
490 if (!restarting)
491 toi_cleanup_console();
492
493 free_attention_list();
494
495 if (!restarting)
496 toi_deactivate_storage(0);
497
498 clear_toi_state(TOI_IGNORE_LOGLEVEL);
499 clear_toi_state(TOI_TRYING_TO_RESUME);
500 clear_toi_state(TOI_NOW_RESUMING);
501 }
502
503 /**
504 * check_still_keeping_image - we kept an image; check whether to reuse it.
505 *
506 * We enter this routine when we have kept an image. If the user has said they
507 * want to still keep it, all we need to do is powerdown. If powering down
508 * means hibernating to ram and the power doesn't run out, we'll return 1.
509 * If we do power off properly or the battery runs out, we'll resume via the
510 * normal paths.
511 *
512 * If the user has said they want to remove the previously kept image, we
513 * remove it, and return 0. We'll then store a new image.
514 **/
515 static int check_still_keeping_image(void)
516 {
517 if (test_action_state(TOI_KEEP_IMAGE)) {
518 printk(KERN_INFO "Image already stored: powering down " "immediately.");
519 do_toi_step(STEP_HIBERNATE_POWERDOWN);
520 return 1; /* Just in case we're using S3 */
521 }
522
523 printk(KERN_INFO "Invalidating previous image.\n");
524 toiActiveAllocator->remove_image();
525
526 return 0;
527 }
528
529 /**
530 * toi_init - prepare to hibernate to disk
531 *
532 * Initialise variables & data structures, in preparation for
533 * hibernating to disk.
534 **/
535 static int toi_init(int restarting)
536 {
537 int result, i, j;
538
539 #ifdef CONFIG_TOI_FIXUP
540 if (test_result_state(TOI_ABORTED))
541 return 1;
542 #endif
543
544 toi_result = 0;
545
546 printk(KERN_INFO "Initiating a hibernation cycle.\n");
547
548 nr_hibernates++;
549
550 for (i = 0; i < 2; i++)
551 for (j = 0; j < 2; j++)
552 toi_bkd.toi_io_time[i][j] = 0;
553
554 if (!test_toi_state(TOI_CAN_HIBERNATE) || allocate_bitmaps())
555 return 1;
556
557 mark_nosave_pages();
558
559 if (!restarting)
560 toi_prepare_console();
561
562 result = pm_notifier_call_chain(PM_HIBERNATION_PREPARE);
563 if (result) {
564 set_result_state(TOI_NOTIFIERS_PREPARE_FAILED);
565 return 1;
566 }
567 set_toi_state(TOI_NOTIFIERS_PREPARE);
568
569 if (!restarting) {
570 int num_threaded;
571 num_threaded = toi_start_other_threads();
572 printk(KERN_ERR "Starting other threads (%d).", num_threaded);
573 }
574
575 result = usermodehelper_disable();
576 if (result) {
577 printk(KERN_ERR "TuxOnIce: Failed to disable usermode " "helpers\n");
578 set_result_state(TOI_USERMODE_HELPERS_ERR);
579 return 1;
580 }
581
582 boot_kernel_data_buffer = toi_get_zeroed_page(37, TOI_ATOMIC_GFP);
583 if (!boot_kernel_data_buffer) {
584 printk(KERN_ERR "TuxOnIce: Failed to allocate " "boot_kernel_data_buffer.\n");
585 set_result_state(TOI_OUT_OF_MEMORY);
586 return 1;
587 }
588
589 if (!test_action_state(TOI_LATE_CPU_HOTPLUG) && disable_nonboot_cpus()) {
590 set_abort_result(TOI_CPU_HOTPLUG_FAILED);
591 return 1;
592 }
593
594 return 0;
595 }
596
597 /**
598 * can_hibernate - perform basic 'Can we hibernate?' tests
599 *
600 * Perform basic tests that must pass if we're going to be able to hibernate:
601 * Can we get the pm_mutex? Is resume= valid (we need to know where to write
602 * the image header).
603 **/
604 static int can_hibernate(void)
605 {
606 if (!test_toi_state(TOI_CAN_HIBERNATE))
607 toi_attempt_to_parse_resume_device(0);
608
609 if (!test_toi_state(TOI_CAN_HIBERNATE)) {
610 printk(KERN_INFO "TuxOnIce: Hibernation is disabled.\n"
611 "This may be because you haven't put something along "
612 "the lines of\n\nresume=swap:/dev/hda1\n\n"
613 "in lilo.conf or equivalent. (Where /dev/hda1 is your "
614 "swap partition).\n");
615 set_abort_result(TOI_CANT_SUSPEND);
616 return 0;
617 }
618
619 if (strlen(alt_resume_param)) {
620 attempt_to_parse_alt_resume_param();
621
622 if (!strlen(alt_resume_param)) {
623 printk(KERN_INFO "Alternate resume parameter now " "invalid. Aborting.\n");
624 set_abort_result(TOI_CANT_USE_ALT_RESUME);
625 return 0;
626 }
627 }
628
629 hib_log("passed!\n");
630
631 return 1;
632 }
633
634 /**
635 * do_post_image_write - having written an image, figure out what to do next
636 *
637 * After writing an image, we might load an alternate image or power down.
638 * Powering down might involve hibernating to ram, in which case we also
639 * need to handle reloading pageset2.
640 **/
641 static int do_post_image_write(void)
642 {
643 /* If switching images fails, do normal powerdown */
644 if (alt_resume_param[0])
645 do_toi_step(STEP_RESUME_ALT_IMAGE);
646
647 toi_power_down();
648
649 barrier();
650 mb();
651 return 0;
652 }
653
654 /**
655 * __save_image - do the hard work of saving the image
656 *
657 * High level routine for getting the image saved. The key assumptions made
658 * are that processes have been frozen and sufficient memory is available.
659 *
660 * We also exit through here at resume time, coming back from toi_hibernate
661 * after the atomic restore. This is the reason for the toi_in_hibernate
662 * test.
663 **/
664 static int __save_image(void)
665 {
666 int temp_result, did_copy = 0;
667
668 toi_prepare_status(DONT_CLEAR_BAR, "Starting to save the image..");
669
670 toi_message(TOI_ANY_SECTION, TOI_LOW, 1,
671 " - Final values: %d and %d.", pagedir1.size, pagedir2.size);
672
673 toi_cond_pause(1, "About to write pagedir2.");
674
675 temp_result = write_pageset(&pagedir2);
676
677 if (temp_result == -1 || test_result_state(TOI_ABORTED))
678 return 1;
679
680 toi_cond_pause(1, "About to copy pageset 1.");
681
682 if (test_result_state(TOI_ABORTED))
683 return 1;
684
685 toi_deactivate_storage(1);
686
687 toi_prepare_status(DONT_CLEAR_BAR, "Doing atomic copy/restore.");
688
689 toi_in_hibernate = 1;
690
691 if (toi_go_atomic(PMSG_FREEZE, 1))
692 goto Failed;
693
694 hib_log("calling toi_hibernate()\n");
695 temp_result = toi_hibernate();
696
697 #ifdef CONFIG_KGDB
698 if (test_action_state(TOI_POST_RESUME_BREAKPOINT))
699 kgdb_breakpoint();
700 #endif
701
702 if (!temp_result)
703 did_copy = 1;
704
705 hib_log("calling toi_end_atomic() toi_in_hibernate(%d) temp_result(%d)\n", toi_in_hibernate,
706 temp_result);
707 /* We return here at resume time too! */
708 toi_end_atomic(ATOMIC_ALL_STEPS, toi_in_hibernate, temp_result);
709
710 Failed:
711 if (toi_activate_storage(1))
712 panic("Failed to reactivate our storage.");
713
714 /* Resume time? */
715 if (!toi_in_hibernate) {
716 hib_log("last resume here ...\n");
717 copyback_post();
718 return 0;
719 }
720
721 /* Nope. Hibernating. So, see if we can save the image... */
722
723 if (temp_result || test_result_state(TOI_ABORTED)) {
724 if (did_copy)
725 goto abort_reloading_pagedir_two;
726 else
727 return 1;
728 }
729
730 hib_log("@line:%d\n", __LINE__);
731 toi_update_status(pagedir2.size, pagedir1.size + pagedir2.size, NULL);
732
733 if (test_result_state(TOI_ABORTED))
734 goto abort_reloading_pagedir_two;
735
736 toi_cond_pause(1, "About to write pageset1.");
737
738 toi_message(TOI_ANY_SECTION, TOI_LOW, 1, "-- Writing pageset1");
739
740 temp_result = write_pageset(&pagedir1);
741
742 /* We didn't overwrite any memory, so no reread needs to be done. */
743 if (test_action_state(TOI_TEST_FILTER_SPEED) || test_action_state(TOI_TEST_BIO))
744 return 1;
745
746 if (temp_result == 1 || test_result_state(TOI_ABORTED))
747 goto abort_reloading_pagedir_two;
748
749 toi_cond_pause(1, "About to write header.");
750
751 if (test_result_state(TOI_ABORTED))
752 goto abort_reloading_pagedir_two;
753
754 temp_result = write_image_header();
755
756 if (!temp_result && !test_result_state(TOI_ABORTED))
757 return 0;
758
759 abort_reloading_pagedir_two:
760 temp_result = read_pageset2(1);
761
762 /* If that failed, we're sunk. Panic! */
763 if (temp_result)
764 panic("Attempt to reload pagedir 2 while aborting " "a hibernate failed.");
765
766 return 1;
767 }
768
769 static void map_ps2_pages(int enable)
770 {
771 unsigned long pfn = 0;
772
773 pfn = memory_bm_next_pfn(pageset2_map);
774
775 while (pfn != BM_END_OF_MAP) {
776 struct page *page = pfn_to_page(pfn);
777 kernel_map_pages(page, 1, enable);
778 pfn = memory_bm_next_pfn(pageset2_map);
779 }
780 }
781
782 /**
783 * do_save_image - save the image and handle the result
784 *
785 * Save the prepared image. If we fail or we're in the path returning
786 * from the atomic restore, cleanup.
787 **/
788 static int do_save_image(void)
789 {
790 int result;
791 map_ps2_pages(0);
792 result = __save_image();
793 map_ps2_pages(1);
794 return result;
795 }
796
797 /**
798 * do_prepare_image - try to prepare an image
799 *
800 * Seek to initialise and prepare an image to be saved. On failure,
801 * cleanup.
802 **/
803 static int do_prepare_image(void)
804 {
805 int restarting = test_result_state(TOI_EXTRA_PAGES_ALLOW_TOO_SMALL);
806
807 if (!restarting && toi_activate_storage(0))
808 return 1;
809
810 hib_log("step 1 @line:%d\n", __LINE__);
811 /*
812 * If kept image and still keeping image and hibernating to RAM, we will
813 * return 1 after hibernating and resuming (provided the power doesn't
814 * run out. In that case, we skip directly to cleaning up and exiting.
815 */
816
817 if (!can_hibernate() || (test_result_state(TOI_KEPT_IMAGE) && check_still_keeping_image()))
818 return 1;
819
820 hib_log("step 2 @line:%d\n", __LINE__);
821
822 if (toi_init(restarting) || toi_prepare_image() || test_result_state(TOI_ABORTED))
823 return 1;
824
825 hib_log("step 3 @line:%d\n", __LINE__);
826
827 trap_non_toi_io = 1;
828
829 return 0;
830 }
831
832 /**
833 * do_check_can_resume - find out whether an image has been stored
834 *
835 * Read whether an image exists. We use the same routine as the
836 * image_exists sysfs entry, and just look to see whether the
837 * first character in the resulting buffer is a '1'.
838 **/
839 int do_check_can_resume(void)
840 {
841 int result = -1;
842
843 if (toi_activate_storage(0))
844 return -1;
845
846 if (!test_toi_state(TOI_RESUME_DEVICE_OK))
847 toi_attempt_to_parse_resume_device(1);
848
849 if (toiActiveAllocator)
850 result = toiActiveAllocator->image_exists(1);
851
852 toi_deactivate_storage(0);
853 return result;
854 }
855 EXPORT_SYMBOL_GPL(do_check_can_resume);
856
857 /**
858 * do_load_atomic_copy - load the first part of an image, if it exists
859 *
860 * Check whether we have an image. If one exists, do sanity checking
861 * (possibly invalidating the image or even rebooting if the user
862 * requests that) before loading it into memory in preparation for the
863 * atomic restore.
864 *
865 * If and only if we have an image loaded and ready to restore, we return 1.
866 **/
867 static int do_load_atomic_copy(void)
868 {
869 int read_image_result = 0;
870
871 if (sizeof(swp_entry_t) != sizeof(long)) {
872 printk(KERN_WARNING "TuxOnIce: The size of swp_entry_t != size"
873 " of long. Please report this!\n");
874 return 1;
875 }
876
877 if (!resume_file[0])
878 printk(KERN_WARNING "TuxOnIce: "
879 "You need to use a resume= command line parameter to "
880 "tell TuxOnIce where to look for an image.\n");
881
882 toi_activate_storage(0);
883
884 if (!(test_toi_state(TOI_RESUME_DEVICE_OK)) && !toi_attempt_to_parse_resume_device(0)) {
885 /*
886 * Without a usable storage device we can do nothing -
887 * even if noresume is given
888 */
889
890 if (!toiNumAllocators)
891 printk(KERN_ALERT "TuxOnIce: "
892 "No storage allocators have been registered.\n");
893 else
894 printk(KERN_ALERT "TuxOnIce: "
895 "Missing or invalid storage location "
896 "(resume= parameter). Please correct and "
897 "rerun lilo (or equivalent) before " "hibernating.\n");
898 toi_deactivate_storage(0);
899 return 1;
900 }
901
902 if (allocate_bitmaps())
903 return 1;
904
905 read_image_result = read_pageset1(); /* non fatal error ignored */
906
907 if (test_toi_state(TOI_NORESUME_SPECIFIED))
908 clear_toi_state(TOI_NORESUME_SPECIFIED);
909
910 toi_deactivate_storage(0);
911
912 if (read_image_result)
913 return 1;
914
915 return 0;
916 }
917
918 /**
919 * prepare_restore_load_alt_image - save & restore alt image variables
920 *
921 * Save and restore the pageset1 maps, when loading an alternate image.
922 **/
923 static void prepare_restore_load_alt_image(int prepare)
924 {
925 static struct memory_bitmap *pageset1_map_save, *pageset1_copy_map_save;
926
927 if (prepare) {
928 pageset1_map_save = pageset1_map;
929 pageset1_map = NULL;
930 pageset1_copy_map_save = pageset1_copy_map;
931 pageset1_copy_map = NULL;
932 set_toi_state(TOI_LOADING_ALT_IMAGE);
933 toi_reset_alt_image_pageset2_pfn();
934 } else {
935 memory_bm_free(pageset1_map, 0);
936 pageset1_map = pageset1_map_save;
937 memory_bm_free(pageset1_copy_map, 0);
938 pageset1_copy_map = pageset1_copy_map_save;
939 clear_toi_state(TOI_NOW_RESUMING);
940 clear_toi_state(TOI_LOADING_ALT_IMAGE);
941 }
942 }
943
944 /**
945 * do_toi_step - perform a step in hibernating or resuming
946 *
947 * Perform a step in hibernating or resuming an image. This abstraction
948 * is in preparation for implementing cluster support, and perhaps replacing
949 * uswsusp too (haven't looked whether that's possible yet).
950 **/
951 int do_toi_step(int step)
952 {
953 switch (step) {
954 case STEP_HIBERNATE_PREPARE_IMAGE:
955 return do_prepare_image();
956 case STEP_HIBERNATE_SAVE_IMAGE:
957 return do_save_image();
958 case STEP_HIBERNATE_POWERDOWN:
959 return do_post_image_write();
960 case STEP_RESUME_CAN_RESUME:
961 return do_check_can_resume();
962 case STEP_RESUME_LOAD_PS1:
963 return do_load_atomic_copy();
964 case STEP_RESUME_DO_RESTORE:
965 /*
966 * If we succeed, this doesn't return.
967 * Instead, we return from do_save_image() in the
968 * hibernated kernel.
969 */
970 return toi_atomic_restore();
971 case STEP_RESUME_ALT_IMAGE:
972 printk(KERN_INFO "Trying to resume alternate image.\n");
973 toi_in_hibernate = 0;
974 save_restore_alt_param(SAVE, NOQUIET);
975 prepare_restore_load_alt_image(1);
976 if (!do_check_can_resume()) {
977 printk(KERN_INFO "Nothing to resume from.\n");
978 goto out;
979 }
980 if (!do_load_atomic_copy())
981 toi_atomic_restore();
982
983 printk(KERN_INFO "Failed to load image.\n");
984 out:
985 prepare_restore_load_alt_image(0);
986 save_restore_alt_param(RESTORE, NOQUIET);
987 break;
988 case STEP_CLEANUP:
989 do_cleanup(1, 0);
990 break;
991 case STEP_QUIET_CLEANUP:
992 do_cleanup(0, 0);
993 break;
994 }
995
996 return 0;
997 }
998 EXPORT_SYMBOL_GPL(do_toi_step);
999
1000 /* -- Functions for kickstarting a hibernate or resume --- */
1001
1002 /**
1003 * toi_try_resume - try to do the steps in resuming
1004 *
1005 * Check if we have an image and if so try to resume. Clear the status
1006 * flags too.
1007 **/
1008 void toi_try_resume(void)
1009 {
1010 int num_threaded;
1011
1012 hib_log("entering...\n");
1013 set_toi_state(TOI_TRYING_TO_RESUME);
1014 resume_attempted = 1;
1015
1016 current->flags |= PF_MEMALLOC;
1017
1018 get_online_cpus(); /* to protect against hotplug interference */
1019 num_threaded = toi_start_other_threads();
1020 printk(KERN_ERR "[resume] Starting other threads (%d).", num_threaded);
1021
1022 if (do_toi_step(STEP_RESUME_CAN_RESUME) && !do_toi_step(STEP_RESUME_LOAD_PS1)) {
1023 put_online_cpus(); /* to protect against hotplug interference */
1024 do_toi_step(STEP_RESUME_DO_RESTORE);
1025 } else {
1026 put_online_cpus(); /* to protect against hotplug interference */
1027 }
1028
1029 toi_stop_other_threads();
1030 do_cleanup(0, 0);
1031
1032 current->flags &= ~PF_MEMALLOC;
1033
1034 clear_toi_state(TOI_IGNORE_LOGLEVEL);
1035 clear_toi_state(TOI_TRYING_TO_RESUME);
1036 clear_toi_state(TOI_NOW_RESUMING);
1037 }
1038
1039 /**
1040 * toi_sys_power_disk_try_resume - wrapper calling toi_try_resume
1041 *
1042 * Wrapper for when __toi_try_resume is called from swsusp resume path,
1043 * rather than from echo > /sys/power/tuxonice/do_resume.
1044 **/
1045 static void toi_sys_power_disk_try_resume(void)
1046 {
1047 resume_attempted = 1;
1048
1049 /*
1050 * There's a comment in kernel/power/disk.c that indicates
1051 * we should be able to use mutex_lock_nested below. That
1052 * doesn't seem to cut it, though, so let's just turn lockdep
1053 * off for now.
1054 */
1055 lockdep_off();
1056
1057 if (toi_start_anything(SYSFS_RESUMING))
1058 goto out;
1059
1060 toi_try_resume();
1061
1062 /*
1063 * For initramfs, we have to clear the boot time
1064 * flag after trying to resume
1065 */
1066 clear_toi_state(TOI_BOOT_TIME);
1067
1068 toi_finish_anything(SYSFS_RESUMING);
1069 out:
1070 lockdep_on();
1071 }
1072
1073 /**
1074 * toi_try_hibernate - try to start a hibernation cycle
1075 *
1076 * Start a hibernation cycle, coming in from either
1077 * echo > /sys/power/tuxonice/do_suspend
1078 *
1079 * or
1080 *
1081 * echo disk > /sys/power/state
1082 *
1083 * In the later case, we come in without pm_sem taken; in the
1084 * former, it has been taken.
1085 **/
1086 int toi_try_hibernate(void)
1087 {
1088 int result = 0, sys_power_disk = 0, retries = 0;
1089
1090 if (!mutex_is_locked(&tuxonice_in_use)) {
1091 /* Came in via /sys/power/disk */
1092 if (toi_start_anything(SYSFS_HIBERNATING))
1093 return -EBUSY;
1094 sys_power_disk = 1;
1095 }
1096
1097 current->flags |= PF_MEMALLOC;
1098
1099 if (test_toi_state(TOI_CLUSTER_MODE)) {
1100 toi_initiate_cluster_hibernate();
1101 goto out;
1102 }
1103
1104 prepare:
1105 result = do_toi_step(STEP_HIBERNATE_PREPARE_IMAGE);
1106 hib_log("after calling do_toi_step(STEP_HIBERNATE_PREPARE_IMAGE), result(%d)\n", result);
1107
1108 if (result)
1109 goto out;
1110
1111 if (test_action_state(TOI_FREEZER_TEST))
1112 goto out_restore_gfp_mask;
1113
1114 result = do_toi_step(STEP_HIBERNATE_SAVE_IMAGE);
1115
1116 if (test_result_state(TOI_EXTRA_PAGES_ALLOW_TOO_SMALL)) {
1117 if (retries < 2) {
1118 hib_log("failed and calling do_cleanup(0, 1)\n");
1119 do_cleanup(0, 1);
1120 retries++;
1121 clear_result_state(TOI_ABORTED);
1122 extra_pd1_pages_allowance = extra_pd1_pages_used + 500;
1123 printk(KERN_INFO "Automatically adjusting the extra"
1124 " pages allowance to %ld and restarting.\n",
1125 extra_pd1_pages_allowance);
1126 pm_restore_gfp_mask();
1127 goto prepare;
1128 }
1129
1130 printk(KERN_INFO "Adjusted extra pages allowance twice and "
1131 "still couldn't hibernate successfully. Giving up.");
1132 }
1133
1134 /* This code runs at resume time too! */
1135 if (!result && toi_in_hibernate)
1136 result = do_toi_step(STEP_HIBERNATE_POWERDOWN);
1137
1138 out_restore_gfp_mask:
1139 pm_restore_gfp_mask();
1140 out:
1141 do_cleanup(1, 0);
1142 current->flags &= ~PF_MEMALLOC;
1143
1144 if (sys_power_disk)
1145 toi_finish_anything(SYSFS_HIBERNATING);
1146
1147 return result;
1148 }
1149
1150 /*
1151 * channel_no: If !0, -c <channel_no> is added to args (userui).
1152 */
1153 int toi_launch_userspace_program(char *command, int channel_no, int wait, int debug)
1154 {
1155 int retval;
1156 static char *envp[] = {
1157 "HOME=/",
1158 "TERM=linux",
1159 "PATH=/sbin:/usr/sbin:/bin:/usr/bin",
1160 NULL
1161 };
1162 static char *argv[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
1163 };
1164 char *channel = NULL;
1165 int arg = 0, size;
1166 char test_read[255];
1167 char *orig_posn = command;
1168
1169 if (!strlen(orig_posn))
1170 return 1;
1171
1172 if (channel_no) {
1173 channel = toi_kzalloc(4, 6, GFP_KERNEL);
1174 if (!channel) {
1175 printk(KERN_INFO "Failed to allocate memory in "
1176 "preparing to launch userspace program.\n");
1177 return 1;
1178 }
1179 }
1180
1181 /* Up to 6 args supported */
1182 while (arg < 6) {
1183 sscanf(orig_posn, "%254s", test_read);
1184 size = strlen(test_read);
1185 if (!(size))
1186 break;
1187 argv[arg] = toi_kzalloc(5, size + 1, TOI_ATOMIC_GFP);
1188 strcpy(argv[arg], test_read);
1189 orig_posn += size + 1;
1190 *test_read = 0;
1191 arg++;
1192 }
1193
1194 if (channel_no) {
1195 sprintf(channel, "-c%d", channel_no);
1196 argv[arg] = channel;
1197 } else
1198 arg--;
1199
1200 if (debug) {
1201 argv[++arg] = toi_kzalloc(5, 8, TOI_ATOMIC_GFP);
1202 strcpy(argv[arg], "--debug");
1203 }
1204
1205 retval = call_usermodehelper(argv[0], argv, envp, wait);
1206
1207 /*
1208 * If the program reports an error, retval = 256. Don't complain
1209 * about that here.
1210 */
1211 if (retval && retval != 256)
1212 printk(KERN_ERR "Failed to launch userspace program '%s': "
1213 "Error %d\n", command, retval);
1214
1215 {
1216 int i;
1217 for (i = 0; i < arg; i++)
1218 if (argv[i] && argv[i] != channel)
1219 toi_kfree(5, argv[i], sizeof(*argv[i]));
1220 }
1221
1222 toi_kfree(4, channel, sizeof(*channel));
1223
1224 return retval;
1225 }
1226
1227 #ifdef CONFIG_TOI_ENHANCE
1228 int toi_abort_hibernate(void)
1229 {
1230 if (test_result_state(TOI_ABORTED))
1231 return 0;
1232
1233 set_result_state(TOI_ABORTED);
1234
1235 return 0;
1236 }
1237 EXPORT_SYMBOL_GPL(toi_abort_hibernate);
1238
1239 int toi_hibernate_fatalerror(void)
1240 {
1241 if (test_result_state(TOI_ARCH_PREPARE_FAILED))
1242 return 1;
1243 else
1244 return 0;
1245 }
1246 EXPORT_SYMBOL_GPL(toi_hibernate_fatalerror);
1247 #endif
1248
1249 /*
1250 * This array contains entries that are automatically registered at
1251 * boot. Modules and the console code register their own entries separately.
1252 */
1253 static struct toi_sysfs_data sysfs_params[] = {
1254 SYSFS_LONG("extra_pages_allowance", SYSFS_RW,
1255 &extra_pd1_pages_allowance, 0, LONG_MAX, 0),
1256 SYSFS_CUSTOM("image_exists", SYSFS_RW, image_exists_read,
1257 image_exists_write, SYSFS_NEEDS_SM_FOR_BOTH, NULL),
1258 SYSFS_STRING("resume", SYSFS_RW, resume_file, 255,
1259 SYSFS_NEEDS_SM_FOR_WRITE,
1260 attempt_to_parse_resume_device2),
1261 SYSFS_STRING("alt_resume_param", SYSFS_RW, alt_resume_param, 255,
1262 SYSFS_NEEDS_SM_FOR_WRITE,
1263 attempt_to_parse_alt_resume_param),
1264 SYSFS_CUSTOM("debug_info", SYSFS_READONLY, get_toi_debug_info, NULL, 0,
1265 NULL),
1266 SYSFS_BIT("ignore_rootfs", SYSFS_RW, &toi_bkd.toi_action,
1267 TOI_IGNORE_ROOTFS, 0),
1268 SYSFS_LONG("image_size_limit", SYSFS_RW, &image_size_limit, -2,
1269 INT_MAX, 0),
1270 SYSFS_UL("last_result", SYSFS_RW, &toi_result, 0, 0, 0),
1271 SYSFS_BIT("no_multithreaded_io", SYSFS_RW, &toi_bkd.toi_action,
1272 TOI_NO_MULTITHREADED_IO, 0),
1273 SYSFS_BIT("no_flusher_thread", SYSFS_RW, &toi_bkd.toi_action,
1274 TOI_NO_FLUSHER_THREAD, 0),
1275 SYSFS_BIT("full_pageset2", SYSFS_RW, &toi_bkd.toi_action,
1276 TOI_PAGESET2_FULL, 0),
1277 SYSFS_BIT("reboot", SYSFS_RW, &toi_bkd.toi_action, TOI_REBOOT, 0),
1278 SYSFS_BIT("replace_swsusp", SYSFS_RW, &toi_bkd.toi_action,
1279 TOI_REPLACE_SWSUSP, 0),
1280 SYSFS_STRING("resume_commandline", SYSFS_RW,
1281 toi_bkd.toi_nosave_commandline, COMMAND_LINE_SIZE, 0,
1282 NULL),
1283 SYSFS_STRING("version", SYSFS_READONLY, TOI_CORE_VERSION, 0, 0, NULL),
1284 SYSFS_BIT("freezer_test", SYSFS_RW, &toi_bkd.toi_action,
1285 TOI_FREEZER_TEST, 0),
1286 SYSFS_BIT("test_bio", SYSFS_RW, &toi_bkd.toi_action, TOI_TEST_BIO, 0),
1287 SYSFS_BIT("test_filter_speed", SYSFS_RW, &toi_bkd.toi_action,
1288 TOI_TEST_FILTER_SPEED, 0),
1289 SYSFS_BIT("no_pageset2", SYSFS_RW, &toi_bkd.toi_action,
1290 TOI_NO_PAGESET2, 0),
1291 SYSFS_BIT("no_pageset2_if_unneeded", SYSFS_RW, &toi_bkd.toi_action,
1292 TOI_NO_PS2_IF_UNNEEDED, 0),
1293 SYSFS_BIT("late_cpu_hotplug", SYSFS_RW, &toi_bkd.toi_action,
1294 TOI_LATE_CPU_HOTPLUG, 0),
1295 SYSFS_STRING("binary_signature", SYSFS_READONLY,
1296 tuxonice_signature, 9, 0, NULL),
1297 SYSFS_INT("max_workers", SYSFS_RW, &toi_max_workers, 0, NR_CPUS, 0,
1298 NULL),
1299 #ifdef CONFIG_KGDB
1300 SYSFS_BIT("post_resume_breakpoint", SYSFS_RW, &toi_bkd.toi_action,
1301 TOI_POST_RESUME_BREAKPOINT, 0),
1302 #endif
1303 SYSFS_BIT("no_readahead", SYSFS_RW, &toi_bkd.toi_action,
1304 TOI_NO_READAHEAD, 0),
1305 #ifdef CONFIG_TOI_KEEP_IMAGE
1306 SYSFS_BIT("keep_image", SYSFS_RW, &toi_bkd.toi_action, TOI_KEEP_IMAGE,
1307 0),
1308 #endif
1309 };
1310
1311 static struct toi_core_fns my_fns = {
1312 .get_nonconflicting_page = __toi_get_nonconflicting_page,
1313 .post_context_save = __toi_post_context_save,
1314 .try_hibernate = toi_try_hibernate,
1315 .try_resume = toi_sys_power_disk_try_resume,
1316 };
1317
1318 /**
1319 * core_load - initialisation of TuxOnIce core
1320 *
1321 * Initialise the core, beginning with sysfs. Checksum and so on are part of
1322 * the core, but have their own initialisation routines because they either
1323 * aren't compiled in all the time or have their own subdirectories.
1324 **/
1325 static __init int core_load(void)
1326 {
1327 int i, numfiles = sizeof(sysfs_params) / sizeof(struct toi_sysfs_data);
1328
1329 printk(KERN_INFO "TuxOnIce " TOI_CORE_VERSION " (http://tuxonice.net)\n");
1330
1331 if (toi_sysfs_init())
1332 return 1;
1333
1334 for (i = 0; i < numfiles; i++)
1335 toi_register_sysfs_file(tuxonice_kobj, &sysfs_params[i]);
1336
1337 toi_core_fns = &my_fns;
1338
1339 if (toi_alloc_init())
1340 return 1;
1341 if (toi_checksum_init())
1342 return 1;
1343 if (toi_usm_init())
1344 return 1;
1345 if (toi_ui_init())
1346 return 1;
1347 if (toi_poweroff_init())
1348 return 1;
1349 if (toi_cluster_init())
1350 return 1;
1351
1352 return 0;
1353 }
1354
1355 #ifdef MODULE
1356 /**
1357 * core_unload: Prepare to unload the core code.
1358 **/
1359 static __exit void core_unload(void)
1360 {
1361 int i, numfiles = sizeof(sysfs_params) / sizeof(struct toi_sysfs_data);
1362
1363 toi_alloc_exit();
1364 toi_checksum_exit();
1365 toi_poweroff_exit();
1366 toi_ui_exit();
1367 toi_usm_exit();
1368 toi_cluster_exit();
1369
1370 for (i = 0; i < numfiles; i++)
1371 toi_unregister_sysfs_file(tuxonice_kobj, &sysfs_params[i]);
1372
1373 toi_core_fns = NULL;
1374
1375 toi_sysfs_exit();
1376 }
1377
1378 MODULE_LICENSE("GPL");
1379 module_init(core_load);
1380 module_exit(core_unload);
1381 #else
1382 late_initcall(core_load);
1383 #endif