lkml.org 
[lkml]   [2001]   [Oct]   [1]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subjectswsusp: fix realtime processes, work around random memory corruption with DMA, do not trigger oom-killer
Hi!

Yep, it fixes all of above.

Most "interesting" is stuff that prevents usb controller from
scribling over memory. cli() and msleep(1000) should do the trick ;-).

Also you can now trigger it by echo 4 > /proc/acpi/sleep. Usefull for
testing.

Pavel
PS: (Patch is relative to my 2.4.10 port, which I mailed just about
everywhere.)



--- /elf/big/2.4.10-swsusp.2/drivers/acpi/ospm/system/sm_osl.c Sun Sep 23 23:05:21 2001
+++ linux-swsusp/drivers/acpi/ospm/system/sm_osl.c Sun Sep 30 12:04:00 2001
@@ -140,7 +140,10 @@
if (system->states[value] != TRUE)
return -EINVAL;

- sm_osl_suspend(value);
+ if (value != ACPI_S4)
+ sm_osl_suspend(value);
+ else
+ software_suspend();

return (count);
}
@@ -685,6 +688,9 @@
*/
if (state == ACPI_S2 || state == ACPI_S3) {
#ifdef DONT_USE_UNTIL_LOWLEVEL_CODE_EXISTS
+ /* That && trick is *not going to work*. Read gcc
+ specs. That explicitely says: jumping from other
+ function is *not allowed*. */
wakeup_address = acpi_save_state_mem((unsigned long)&&acpi_sleep_done);

if (!wakeup_address) goto acpi_sleep_done;
@@ -692,11 +698,12 @@
acpi_set_firmware_waking_vector(
(ACPI_PHYSICAL_ADDRESS)wakeup_address);
#endif
- } else if (state == ACPI_S4)
+ } else if (state == ACPI_S4) {
#ifdef DONT_USE_UNTIL_LOWLEVEL_CODE_EXISTS
if (acpi_save_state_disk((unsigned long)&&acpi_sleep_done))
- goto acpi_sleep_done;
+ goto acpi_sleep_done
#endif
+ }

/* set status, since acpi_enter_sleep_state won't return unless something
* goes wrong, or it's just S1.
diff -urN -x .dep* -x .hdep* -x *.[oas] -x *~ -x #* -x *CVS* -x *.orig -x *.rej -x *.old -x .menu* -x asm -x local.h -x System.map -x autoconf.h -x compile.h -x version.h -x .version -x defkeymap.c -x uni_hash.tbl -x zImage -x vmlinux -x vmlinuz -x TAGS -x bootsect -x *RCS* -x conmakehash -x map -x build -x build -x configure -x *target* -x *.flags -x *.bak /elf/big/2.4.10-swsusp.2/kernel/swsusp.c linux-swsusp/kernel/swsusp.c
--- /elf/big/2.4.10-swsusp.2/kernel/swsusp.c Sat Sep 29 10:34:23 2001
+++ linux-swsusp/kernel/swsusp.c Sun Sep 30 21:04:02 2001
@@ -222,6 +222,12 @@
/* Refrigerator is place where frozen processes are stored :-). */
void refrigerator(void)
{
+#define CORRECT
+ /* You need correct to work with real-time processes.
+ OTOH, this way one process may see (via /proc/) some other
+ process in stopped state (and thereby discovered we were
+ suspended. We probably do not care.
+ */
#ifdef CORRECT
long save;
save = current->state;
@@ -708,7 +714,7 @@
void **c= eaten_memory, *m;

printk("Eating pages ");
- while ((m = (void *) get_free_page(GFP_HIGHMEM))) {
+ while ((m = (void *) get_free_page(GFP_HIGHUSER))) {
memset(m, 0, PAGE_SIZE);
eaten_memory = m;
if (!(i%5000))
@@ -749,6 +755,10 @@
pages = shrink_mem();
PRINTS( "Freed pages: %u\n", pages );
#endif
+#if 1
+ eat_memory();
+ free_memory();
+#endif
/* No need to invalidate any vfsmnt list -- they will be valid after resume, anyway.
*
* We sync here -- so you have consistent filesystem state when things go wrong.
@@ -942,8 +952,13 @@
#ifdef CONFIG_SMP_DISABLED
prepare_suspend_smp ();
#endif
- eat_memory();
- free_memory();
+
+#if 0
+ printk("Freeing memory: ");
+ while (try_to_free_pages(&contig_page_data.node_zones[ZONE_HIGHMEM], GFP_KSWAPD, 0))
+ printk(".");
+ printk("\n");
+#endif

spin_lock(&suspend_lock);
PRINTP( "Test local var: %08lx\n", local_var);
@@ -977,6 +992,11 @@
/* Critical section here: noone should touch memory from now */
spin_lock_irq(&suspend_pagedir_lock); /* Done to disable interrupts */

+ printk( "Waiting for disks 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
+ driver scheduled DMA, we have good chance for DMA to finish ;-). */
+
/* This works, because loop and loop2 are nosavedata */
for (loop=0; loop < nr_copy_pages; loop++) {
/* You may not call something (like copy_page) here:
@@ -1399,8 +1419,6 @@
error = 0;

resume_read_error:
- printk("Error resuming\n");
- mdelay(1000);
switch (error) {
case 0:
PRINTR("Reading resume file was successful\n");
@@ -1416,9 +1434,9 @@
default:
printk( "%sError %d resuming\n", name_resume, error );
}
+ mdelay(1000);
set_fs(orig_fs);
- set_blocksize(dev, blksize); /* FIXME: There's something very strange: even after successfull resume,
- old blocksize seems to be set. Ouch?! */
+ set_blocksize(dev, blksize);
MDELAY(1000);
if (different_kernel)
panic("Sorry Pavel... I like my filesystem too much.");
--
I'm pavel@ucw.cz. "In my country we have almost anarchy and I don't care."
Panos Katsaloulis describing me w.r.t. patents at discuss@linmodems.org
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

\
 
 \ /
  Last update: 2005-03-22 13:03    [W:0.027 / U:11.452 seconds]
©2003-2018 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site