- spin_unlock_irq(&suspend_pagedir_lock);
- if (!is_problem) {
- kernel_fpu_end(); /* save_processor_state() does kernel_fpu_begin, and we need to revert it in order to pass in_atomic() checks */
- BUG_ON(in_atomic());
- suspend_save_image();
- suspend_power_down(); /* FIXME: if suspend_power_down is commented out, console is lost after few suspends ?! */
- }
-
- printk(KERN_EMERG "%sSuspend failed, trying to recover...\n", name_suspend);
- MDELAY(1000); /* So user can wait and report us messages if armageddon comes :-) */
-
- barrier();
- mb();
- spin_lock_irq(&suspend_pagedir_lock); /* Done to disable interrupts */
- mdelay(1000);
-
- free_pages((unsigned long) pagedir_nosave, pagedir_order);
- spin_unlock_irq(&suspend_pagedir_lock);
-
- device_resume();
- PRINTK( "Fixing swap signatures... " );
- mark_swapfiles(((swp_entry_t) {0}), MARK_SWAP_RESUME);
- PRINTK( "ok\n" );
-}
-
-/*
- * This is main interface to the outside world. It needs to be
- * called from process context.
- */
-int software_suspend(void)
-{
- int res;
- if (!software_suspend_enabled)
- return -EAGAIN;
-
- software_suspend_enabled = 0;
- might_sleep();
-
- if (arch_prepare_suspend()) {
- printk("%sArchitecture failed to prepare\n", name_suspend);
- return -EPERM;
- }
- if (pm_prepare_console())
- printk( "%sCan't allocate a console... proceeding\n", name_suspend);
- if (!prepare_suspend_processes()) {
-
- /* At this point, all user processes and "dangerous"
- kernel threads are stopped. Free some memory, as we
- need half of memory free. */
-
- free_some_memory();
-
- /* Save state of all device drivers, and stop them. */
- if ((res = device_suspend(4))==0)
- /* If stopping device drivers worked, we proceed basically into
- * suspend_save_image.
- *
- * do_magic(0) returns after system is resumed.
- *
- * do_magic() copies all "used" memory to "free" memory, then
- * unsuspends all device drivers, and writes memory to disk
- * using normal kernel mechanism.
- */
- do_magic(0);
- thaw_processes();
- } else
- res = -EBUSY;
- software_suspend_enabled = 1;
- MDELAY(1000);
- pm_restore_console();
- return res;