Commit e7c215c1 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] swsusp does not stop DMA properly during resume

From: Pavel Machek <pavel@ucw.cz>

To correctly stop all DMA activity, make the boot kernel put all devices
into suspend state before entering the resume kernel image.
parent e100952f
......@@ -59,6 +59,7 @@
#include <linux/buffer_head.h>
#include <linux/swapops.h>
#include <linux/bootmem.h>
#include <linux/console.h>
#include <asm/uaccess.h>
#include <asm/mmu_context.h>
......@@ -488,33 +489,6 @@ static void free_some_memory(void)
printk("|\n");
}
/* Make disk drivers accept operations, again */
static void drivers_unsuspend(void)
{
device_resume();
}
/* Called from process context */
static int drivers_suspend(void)
{
return device_suspend(4);
}
#define RESUME_PHASE1 1 /* Called from interrupts disabled */
#define RESUME_PHASE2 2 /* Called with interrupts enabled */
#define RESUME_ALL_PHASES (RESUME_PHASE1 | RESUME_PHASE2)
static void drivers_resume(int flags)
{
if (flags & RESUME_PHASE1) {
device_resume();
}
if (flags & RESUME_PHASE2) {
#ifdef SUSPEND_CONSOLE
update_screen(fg_console); /* Hmm, is this the problem? */
#endif
}
}
static int suspend_prepare_image(void)
{
struct sysinfo i;
......@@ -569,7 +543,7 @@ static int suspend_prepare_image(void)
static void suspend_save_image(void)
{
drivers_unsuspend();
device_resume();
lock_swapdevices();
write_suspend_image();
......@@ -615,6 +589,7 @@ void do_magic_resume_1(void)
mb();
spin_lock_irq(&suspend_pagedir_lock); /* Done to disable interrupts */
device_power_down(4);
PRINTK( "Waiting for DMAs to settle down...\n");
mdelay(1000); /* We do not want some readahead with DMA to corrupt our memory, right?
Do it with disabled interrupts for best effect. That way, if some
......@@ -630,8 +605,13 @@ void do_magic_resume_2(void)
PRINTK( "Freeing prev allocated pagedir\n" );
free_suspend_pagedir((unsigned long) pagedir_save);
device_power_up();
spin_unlock_irq(&suspend_pagedir_lock);
drivers_resume(RESUME_ALL_PHASES);
device_resume();
acquire_console_sem();
update_screen(fg_console); /* Hmm, is this the problem? */
release_console_sem();
PRINTK( "Fixing swap signatures... " );
mark_swapfiles(((swp_entry_t) {0}), MARK_SWAP_RESUME);
......@@ -672,7 +652,9 @@ void do_magic_suspend_2(void)
{
int is_problem;
read_swapfiles();
device_power_down(4);
is_problem = suspend_prepare_image();
device_power_up();
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 */
......@@ -716,7 +698,7 @@ static void do_software_suspend(void)
blk_run_queues();
/* Save state of all device drivers, and stop them. */
if(drivers_suspend()==0)
if ((res = device_suspend(4))==0)
/* If stopping device drivers worked, we proceed basically into
* suspend_save_image.
*
......@@ -1091,6 +1073,7 @@ static int __init software_resume(void)
printk( "resuming from %s\n", resume_file);
if (read_suspend_image(resume_file, 0))
goto read_failure;
device_suspend(4);
do_magic(1);
panic("This never returns");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment