* [Suspend2][ 00/10] Suspend2 Atomic Copy Patches
@ 2006-06-27 4:38 Nigel Cunningham
2006-06-27 4:38 ` [Suspend2][ 01/10] [Suspend2] Atomic copy file header Nigel Cunningham
` (9 more replies)
0 siblings, 10 replies; 11+ messages in thread
From: Nigel Cunningham @ 2006-06-27 4:38 UTC (permalink / raw)
To: linux-kernel
This set of patches contains routeines in kernel/power/atomic_copy.c.
These are routines to doing the atomic copy and restoration of data. When
resuming, most of the work is done by the swsusp lowlevel code, but we
still need to generate the pbes it uses from our bitmaps.
^ permalink raw reply [flat|nested] 11+ messages in thread
* [Suspend2][ 01/10] [Suspend2] Atomic copy file header.
2006-06-27 4:38 [Suspend2][ 00/10] Suspend2 Atomic Copy Patches Nigel Cunningham
@ 2006-06-27 4:38 ` Nigel Cunningham
2006-06-27 4:38 ` [Suspend2][ 02/10] [Suspend2] Initialise nosave zone table Nigel Cunningham
` (8 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Nigel Cunningham @ 2006-06-27 4:38 UTC (permalink / raw)
To: linux-kernel
Add the header for the atomic copy file. This file contains the routines
related to doing the copying and restoration of pages that need to be
atomically copied.
Signed-off-by: Nigel Cunningham <nigel@suspend2.net>
kernel/power/atomic_copy.c | 52 ++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 52 insertions(+), 0 deletions(-)
diff --git a/kernel/power/atomic_copy.c b/kernel/power/atomic_copy.c
new file mode 100644
index 0000000..e54de43
--- /dev/null
+++ b/kernel/power/atomic_copy.c
@@ -0,0 +1,52 @@
+/*
+ * kernel/power/atomic_copy.c
+ *
+ * Copyright 2004-2006 Nigel Cunningham <nigel@suspend2.net>
+ *
+ * Distributed under GPLv2.
+ *
+ * Routines for doing the atomic save/restore.
+ */
+
+#include <linux/suspend.h>
+#include <linux/highmem.h>
+#include <linux/bootmem.h>
+#include <asm/setup.h>
+#include "suspend2_common.h"
+#include "storage.h"
+#include "power_off.h"
+#include "version.h"
+#include "ui.h"
+#include "power.h"
+#include "io.h"
+#include "prepare_image.h"
+#include "pageflags.h"
+#include "extent.h"
+
+static int state1 __nosavedata = 0;
+static int state2 __nosavedata = 0;
+static int state3 __nosavedata = 0;
+static int io_speed_save[2][2] __nosavedata;
+__nosavedata char suspend_resume_commandline[COMMAND_LINE_SIZE];
+
+extern void suspend_power_down(void);
+extern int swsusp_resume(void);
+extern int suspend2_in_suspend __nosavedata;
+int extra_pd1_pages_used;
+
+#ifdef CONFIG_HIGHMEM
+static dyn_pageflags_t __nosavedata origmap;
+static dyn_pageflags_t __nosavedata copymap;
+static unsigned long __nosavedata origoffset;
+static unsigned long __nosavedata copyoffset;
+static __nosavedata int o_zone_num, c_zone_num;
+
+struct zone_data {
+ unsigned long start_pfn;
+ unsigned long end_pfn;
+ int is_highmem;
+};
+
+static __nosavedata struct zone_data *zone_nosave;
+static __nosavedata int num_zones;
+
--
Nigel Cunningham nigel at suspend2 dot net
^ permalink raw reply [flat|nested] 11+ messages in thread
* [Suspend2][ 02/10] [Suspend2] Initialise nosave zone table
2006-06-27 4:38 [Suspend2][ 00/10] Suspend2 Atomic Copy Patches Nigel Cunningham
2006-06-27 4:38 ` [Suspend2][ 01/10] [Suspend2] Atomic copy file header Nigel Cunningham
@ 2006-06-27 4:38 ` Nigel Cunningham
2006-06-27 4:38 ` [Suspend2][ 03/10] [Suspend2] Atomic copy get_next_bit_on routine Nigel Cunningham
` (7 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Nigel Cunningham @ 2006-06-27 4:38 UTC (permalink / raw)
To: linux-kernel
Suspend2 uses swsusp code to restore lowmem pages, but (like swsusp) has a
separate routine for restoring highmem pages. This routine sets up a copy
of the start and end pfn numbers for use in restoring highmem pages. It is
invoked prior to the atomic restore beginning.
Signed-off-by: Nigel Cunningham <nigel@suspend2.net>
kernel/power/atomic_copy.c | 25 +++++++++++++++++++++++++
1 files changed, 25 insertions(+), 0 deletions(-)
diff --git a/kernel/power/atomic_copy.c b/kernel/power/atomic_copy.c
index e54de43..07b418c 100644
--- a/kernel/power/atomic_copy.c
+++ b/kernel/power/atomic_copy.c
@@ -50,3 +50,28 @@ struct zone_data {
static __nosavedata struct zone_data *zone_nosave;
static __nosavedata int num_zones;
+/**
+ * suspend_init_nosave_zone_table: Set up nosave copy of zone table data.
+ *
+ * Zone information might be overwritten during the copy back, so we copy
+ * the fields we need to a non-conflicting page and use it.
+ **/
+static void suspend_init_nosave_zone_table(void)
+{
+ struct zone *zone;
+
+ zone_nosave = (struct zone_data *) suspend_get_nonconflicting_page();
+
+ BUG_ON(!zone_nosave);
+
+ for_each_zone(zone) {
+ if (zone->spanned_pages) {
+ zone_nosave[num_zones].start_pfn = zone->zone_start_pfn;
+ zone_nosave[num_zones].end_pfn = zone->zone_start_pfn +
+ zone->spanned_pages - 1;
+ zone_nosave[num_zones].is_highmem = is_highmem(zone);
+ }
+ num_zones++;
+ }
+}
+
--
Nigel Cunningham nigel at suspend2 dot net
^ permalink raw reply [flat|nested] 11+ messages in thread
* [Suspend2][ 03/10] [Suspend2] Atomic copy get_next_bit_on routine.
2006-06-27 4:38 [Suspend2][ 00/10] Suspend2 Atomic Copy Patches Nigel Cunningham
2006-06-27 4:38 ` [Suspend2][ 01/10] [Suspend2] Atomic copy file header Nigel Cunningham
2006-06-27 4:38 ` [Suspend2][ 02/10] [Suspend2] Initialise nosave zone table Nigel Cunningham
@ 2006-06-27 4:38 ` Nigel Cunningham
2006-06-27 4:39 ` [Suspend2][ 04/10] [Suspend2] Prepare pbe list for atomic restore Nigel Cunningham
` (6 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Nigel Cunningham @ 2006-06-27 4:38 UTC (permalink / raw)
To: linux-kernel
This routine is used find the next bit in a bitmap that is on. It is used
during the atomic restore of highmem pages.
Signed-off-by: Nigel Cunningham <nigel@suspend2.net>
kernel/power/atomic_copy.c | 60 ++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 60 insertions(+), 0 deletions(-)
diff --git a/kernel/power/atomic_copy.c b/kernel/power/atomic_copy.c
index 07b418c..6d1bc68 100644
--- a/kernel/power/atomic_copy.c
+++ b/kernel/power/atomic_copy.c
@@ -75,3 +75,63 @@ static void suspend_init_nosave_zone_tab
}
}
+/**
+ * __suspend_get_next_bit_on: Atomic-copy safe location of next bit on in a bitmap.
+ *
+ * @bitmap: The bitmap we are traversing.
+ * @zone_num: Which zone we are in.
+ * @counter: The current pfn.
+ *
+ * A version of __get_next_bit_on that can be used when doing the atomic
+ * copy. While doing it, we can't rely on the zone information being in
+ * a constant location.
+ **/
+static unsigned long __suspend_get_next_bit_on(dyn_pageflags_t bitmap,
+ int *zone_num, long counter)
+{
+ unsigned long *ul_ptr = NULL;
+ int reset_ul_ptr = 1;
+ BUG_ON(*zone_num == num_zones);
+
+ if (counter == -1) {
+ *zone_num = 0;
+
+ /*
+ * Test the end because the start can validly
+ * be zero.
+ */
+ while (!zone_nosave[*zone_num].end_pfn)
+ (*zone_num)++;
+ counter = zone_nosave[*zone_num].start_pfn - 1;
+ }
+
+ do {
+ counter++;
+ if (counter > zone_nosave[*zone_num].end_pfn) {
+ (*zone_num)++;
+ while (!zone_nosave[*zone_num].end_pfn &&
+ *zone_num < num_zones)
+ (*zone_num)++;
+
+ if (*zone_num == num_zones)
+ return -1;
+ counter = zone_nosave[*zone_num].start_pfn;
+ reset_ul_ptr = 1;
+ } else
+ if (!(counter & BIT_NUM_MASK))
+ reset_ul_ptr = 1;
+
+ if (reset_ul_ptr) {
+ reset_ul_ptr = 0;
+ ul_ptr = PAGE_UL_PTR(bitmap, *zone_num,
+ (counter - zone_nosave[*zone_num].start_pfn));
+ if (!*ul_ptr) {
+ counter += BIT_NUM_MASK - 1;
+ continue;
+ }
+ }
+ } while(!test_bit(PAGEBIT(counter), ul_ptr));
+
+ return counter;
+}
+
--
Nigel Cunningham nigel at suspend2 dot net
^ permalink raw reply [flat|nested] 11+ messages in thread
* [Suspend2][ 04/10] [Suspend2] Prepare pbe list for atomic restore.
2006-06-27 4:38 [Suspend2][ 00/10] Suspend2 Atomic Copy Patches Nigel Cunningham
` (2 preceding siblings ...)
2006-06-27 4:38 ` [Suspend2][ 03/10] [Suspend2] Atomic copy get_next_bit_on routine Nigel Cunningham
@ 2006-06-27 4:39 ` Nigel Cunningham
2006-06-27 4:39 ` [Suspend2][ 05/10] [Suspend2] Highmem copyback routine Nigel Cunningham
` (5 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Nigel Cunningham @ 2006-06-27 4:39 UTC (permalink / raw)
To: linux-kernel
This routine prepares the list of page backup entries that is used by the
swsusp lowlevel code in doing the atomic restore.
Signed-off-by: Nigel Cunningham <nigel@suspend2.net>
kernel/power/atomic_copy.c | 50 ++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 50 insertions(+), 0 deletions(-)
diff --git a/kernel/power/atomic_copy.c b/kernel/power/atomic_copy.c
index 6d1bc68..556e481 100644
--- a/kernel/power/atomic_copy.c
+++ b/kernel/power/atomic_copy.c
@@ -135,3 +135,53 @@ static unsigned long __suspend_get_next_
return counter;
}
+/*
+ * prepare_suspend2_pbe_list
+ *
+ * Prepare pageset2 pages for doing the atomic copy. If necessary,
+ * we allocate extra pages.
+ *
+ */
+
+void prepare_suspend2_pbe_list(void)
+{
+ int orig_pfn, copy_pfn, i = 1;
+ struct pbe *this_pbe = NULL, *last_pbe = NULL;
+
+ orig_pfn = copy_pfn = -1;
+
+ pagedir_nosave = NULL;
+
+ do {
+ if (!this_pbe ||
+ ((((unsigned long) this_pbe) & (PAGE_SIZE - 1))
+ + 2 * sizeof(struct pbe)) > PAGE_SIZE) {
+ /* Get the next page for pbes */
+ this_pbe = (struct pbe *) suspend_get_nonconflicting_page();
+ BUG_ON(!this_pbe);
+ BUG_ON(PagePageset1(virt_to_page(this_pbe)));
+ } else
+ this_pbe++;
+
+ do {
+ orig_pfn = get_next_bit_on(pageset1_map, orig_pfn);
+ if (orig_pfn < 0)
+ return;
+ copy_pfn = get_next_bit_on(pageset1_copy_map, copy_pfn);
+ } while (PageHighMem(pfn_to_page(orig_pfn)));
+
+ if (!last_pbe)
+ pagedir_nosave = this_pbe;
+ else
+ last_pbe->next = this_pbe;
+
+ last_pbe = this_pbe;
+ this_pbe->orig_address = (unsigned long) page_address(pfn_to_page(orig_pfn));
+ this_pbe->address = (unsigned long) page_address(pfn_to_page(copy_pfn));
+ this_pbe->next = NULL; /* get_nonconflicting_page doesn't get zeroed pages */
+
+ i++;
+
+ } while (1);
+}
+
--
Nigel Cunningham nigel at suspend2 dot net
^ permalink raw reply [flat|nested] 11+ messages in thread
* [Suspend2][ 05/10] [Suspend2] Highmem copyback routine.
2006-06-27 4:38 [Suspend2][ 00/10] Suspend2 Atomic Copy Patches Nigel Cunningham
` (3 preceding siblings ...)
2006-06-27 4:39 ` [Suspend2][ 04/10] [Suspend2] Prepare pbe list for atomic restore Nigel Cunningham
@ 2006-06-27 4:39 ` Nigel Cunningham
2006-06-27 4:39 ` [Suspend2][ 06/10] [Suspend2] Post-atomic restore routine Nigel Cunningham
` (4 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Nigel Cunningham @ 2006-06-27 4:39 UTC (permalink / raw)
To: linux-kernel
A routine to restore highmem pages which were atomically copied. We use
data allocated prior to the atomic restore of lowmem, so also have to do
this before other processes are allowed to run.
Signed-off-by: Nigel Cunningham <nigel@suspend2.net>
kernel/power/atomic_copy.c | 32 ++++++++++++++++++++++++++++++++
1 files changed, 32 insertions(+), 0 deletions(-)
diff --git a/kernel/power/atomic_copy.c b/kernel/power/atomic_copy.c
index 556e481..e565bf3 100644
--- a/kernel/power/atomic_copy.c
+++ b/kernel/power/atomic_copy.c
@@ -136,6 +136,38 @@ static unsigned long __suspend_get_next_
}
/*
+ * copyback_high: Restore highmem pages.
+ *
+ * Iterate through the source and destination bitmaps, restoring
+ * highmem pages that were atomically copied.
+ */
+void copyback_high(void)
+{
+ unsigned long *origpage;
+ unsigned long *copypage;
+
+ origoffset = __suspend_get_next_bit_on(origmap, &o_zone_num, -1);
+ copyoffset = __suspend_get_next_bit_on(copymap, &c_zone_num, -1);
+
+ while (o_zone_num < num_zones) {
+ if (zone_nosave[o_zone_num].is_highmem) {
+ origpage = (unsigned long *) kmap_atomic(pfn_to_page(origoffset), KM_USER1);
+ copypage = (unsigned long *) __va(copyoffset << PAGE_SHIFT);
+
+ memcpy(origpage, copypage, PAGE_SIZE);
+
+ kunmap_atomic(origpage, KM_USER1);
+ }
+
+ origoffset = __suspend_get_next_bit_on(origmap, &o_zone_num, origoffset);
+ copyoffset = __suspend_get_next_bit_on(copymap, &c_zone_num, copyoffset);
+ }
+}
+#else
+void copyback_high(void) { }
+#endif
+
+/*
* prepare_suspend2_pbe_list
*
* Prepare pageset2 pages for doing the atomic copy. If necessary,
--
Nigel Cunningham nigel at suspend2 dot net
^ permalink raw reply [flat|nested] 11+ messages in thread
* [Suspend2][ 06/10] [Suspend2] Post-atomic restore routine
2006-06-27 4:38 [Suspend2][ 00/10] Suspend2 Atomic Copy Patches Nigel Cunningham
` (4 preceding siblings ...)
2006-06-27 4:39 ` [Suspend2][ 05/10] [Suspend2] Highmem copyback routine Nigel Cunningham
@ 2006-06-27 4:39 ` Nigel Cunningham
2006-06-27 4:39 ` [Suspend2][ 07/10] [Suspend2] Post suspend context-save routine Nigel Cunningham
` (3 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Nigel Cunningham @ 2006-06-27 4:39 UTC (permalink / raw)
To: linux-kernel
After doing the atomic restore, we need to restore the values of variables
that were saved at resume time and get the remainder of the image loaded.
At the end of this routine, the contents of memory are virtually the same
as prior to beginning the cycle.
Signed-off-by: Nigel Cunningham <nigel@suspend2.net>
kernel/power/atomic_copy.c | 45 ++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 45 insertions(+), 0 deletions(-)
diff --git a/kernel/power/atomic_copy.c b/kernel/power/atomic_copy.c
index e565bf3..a834623 100644
--- a/kernel/power/atomic_copy.c
+++ b/kernel/power/atomic_copy.c
@@ -217,3 +217,48 @@ void prepare_suspend2_pbe_list(void)
} while (1);
}
+/*
+ * copyback_post: Post atomic-restore actions.
+ *
+ * After doing the atomic restore, we have a few more things to do:
+ * 1) We want to retain some values across the restore, so we now copy
+ * these from the nosave variables to the normal ones.
+ * 2) Set the status flags.
+ * 3) Resume devices.
+ * 4) Get userui to redraw.
+ * 5) Reread the page cache.
+ */
+
+void copyback_post(void)
+{
+ int loop;
+
+ suspend_action = state1;
+ suspend_debug_state = state2;
+ console_loglevel = state3;
+
+ for (loop = 0; loop < 4; loop++)
+ suspend_io_time[loop/2][loop%2] =
+ io_speed_save[loop/2][loop%2];
+
+ set_suspend_state(SUSPEND_NOW_RESUMING);
+ set_suspend_state(SUSPEND_PAGESET2_NOT_LOADED);
+
+ if (pm_ops && pm_ops->finish && suspend_powerdown_method > 3)
+ pm_ops->finish(suspend_powerdown_method);
+
+ if (suspend_activate_storage(1))
+ panic("Failed to reactivate our storage.");
+
+ userui_redraw();
+
+ suspend_cond_pause(1, "About to reload secondary pagedir.");
+
+ if (read_pageset2(0))
+ panic("Unable to successfully reread the page cache.");
+
+ clear_suspend_state(SUSPEND_PAGESET2_NOT_LOADED);
+
+ suspend_prepare_status(DONT_CLEAR_BAR, "Cleaning up...");
+}
+
--
Nigel Cunningham nigel at suspend2 dot net
^ permalink raw reply [flat|nested] 11+ messages in thread
* [Suspend2][ 07/10] [Suspend2] Post suspend context-save routine
2006-06-27 4:38 [Suspend2][ 00/10] Suspend2 Atomic Copy Patches Nigel Cunningham
` (5 preceding siblings ...)
2006-06-27 4:39 ` [Suspend2][ 06/10] [Suspend2] Post-atomic restore routine Nigel Cunningham
@ 2006-06-27 4:39 ` Nigel Cunningham
2006-06-27 4:39 ` [Suspend2][ 08/10] [Suspend2] Atomic copy routine Nigel Cunningham
` (2 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Nigel Cunningham @ 2006-06-27 4:39 UTC (permalink / raw)
To: linux-kernel
At suspend-time, after saving the cpu context using the swsusp code, this
routine is invoked to save the atomic copy, enter the chosen state
(possibly suspend to ram), and cleanup if we come back from that state.
Signed-off-by: Nigel Cunningham <nigel@suspend2.net>
kernel/power/atomic_copy.c | 40 ++++++++++++++++++++++++++++++++++++++++
1 files changed, 40 insertions(+), 0 deletions(-)
diff --git a/kernel/power/atomic_copy.c b/kernel/power/atomic_copy.c
index a834623..cb3663c 100644
--- a/kernel/power/atomic_copy.c
+++ b/kernel/power/atomic_copy.c
@@ -262,3 +262,43 @@ void copyback_post(void)
suspend_prepare_status(DONT_CLEAR_BAR, "Cleaning up...");
}
+/*
+ * suspend_post_context_save: Steps after saving the cpu context.
+ *
+ * Steps taken after saving the CPU state to make the actual
+ * atomic copy.
+ *
+ * Called from swsusp_save in snapshot.c.
+ */
+
+int suspend_post_context_save(void)
+{
+ int old_ps1_size = pagedir1.pageset_size;
+ int old_ps2_size = pagedir2.pageset_size;
+
+ BUG_ON(!irqs_disabled());
+
+ suspend_recalculate_image_contents(1);
+
+ extra_pd1_pages_used = pagedir1.pageset_size - old_ps1_size;
+
+ if ((pagedir1.pageset_size - old_ps1_size) > extra_pd1_pages_allowance) {
+ abort_suspend("Pageset1 has grown by %d pages."
+ " Only %d growth is allowed for!\n",
+ pagedir1.pageset_size - old_ps1_size,
+ extra_pd1_pages_allowance);
+ return -1;
+ }
+
+ BUG_ON(old_ps2_size != pagedir2.pageset_size);
+
+ BUG_ON(!irqs_disabled());
+
+ if (!test_action_state(SUSPEND_TEST_FILTER_SPEED) &&
+ !test_action_state(SUSPEND_TEST_BIO))
+ suspend_copy_pageset1();
+
+
+ return 0;
+}
+
--
Nigel Cunningham nigel at suspend2 dot net
^ permalink raw reply [flat|nested] 11+ messages in thread
* [Suspend2][ 08/10] [Suspend2] Atomic copy routine
2006-06-27 4:38 [Suspend2][ 00/10] Suspend2 Atomic Copy Patches Nigel Cunningham
` (6 preceding siblings ...)
2006-06-27 4:39 ` [Suspend2][ 07/10] [Suspend2] Post suspend context-save routine Nigel Cunningham
@ 2006-06-27 4:39 ` Nigel Cunningham
2006-06-27 4:39 ` [Suspend2][ 09/10] [Suspend2] Atomic copy highlevel routine Nigel Cunningham
2006-06-27 4:39 ` [Suspend2][ 10/10] [Suspend2] Atomic restore " Nigel Cunningham
9 siblings, 0 replies; 11+ messages in thread
From: Nigel Cunningham @ 2006-06-27 4:39 UTC (permalink / raw)
To: linux-kernel
When suspending, this routine is used to make the atomic copy of memory.
Like swsusp, it is done in C.
Signed-off-by: Nigel Cunningham <nigel@suspend2.net>
kernel/power/atomic_copy.c | 47 ++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 47 insertions(+), 0 deletions(-)
diff --git a/kernel/power/atomic_copy.c b/kernel/power/atomic_copy.c
index cb3663c..75e3beb 100644
--- a/kernel/power/atomic_copy.c
+++ b/kernel/power/atomic_copy.c
@@ -302,3 +302,50 @@ int suspend_post_context_save(void)
return 0;
}
+/* suspend_copy_pageset1: Do the atomic copy of pageset1.
+ *
+ * Make the atomic copy of pageset1. We can't use copy_page (as we once did)
+ * because we can't be sure what side effects it has. On my old Duron, with
+ * 3DNOW, kernel_fpu_begin increments preempt count, making our preempt
+ * count at resume time 4 instead of 3.
+ *
+ * We don't want to call kmap_atomic unconditionally because it has the side
+ * effect of incrementing the preempt count, which will leave it one too high
+ * post resume (the page containing the preempt count will be copied after
+ * its incremented. This is essentially the same problem.
+ */
+
+void suspend_copy_pageset1(void)
+{
+ int i, source_index, dest_index;
+
+ source_index = get_next_bit_on(pageset1_map, -1);
+ dest_index = get_next_bit_on(pageset1_copy_map, -1);
+
+ for (i = 0; i < pagedir1.pageset_size; i++) {
+ unsigned long *origvirt, *copyvirt;
+ struct page *origpage;
+ int loop = (PAGE_SIZE / sizeof(unsigned long)) - 1;
+
+ origpage = pfn_to_page(source_index);
+
+ if (PageHighMem(origpage))
+ origvirt = kmap_atomic(origpage, KM_USER0);
+ else
+ origvirt = page_address(origpage);
+
+ copyvirt = (unsigned long *) page_address(pfn_to_page(dest_index));
+
+ while (loop >= 0) {
+ *(copyvirt + loop) = *(origvirt + loop);
+ loop--;
+ }
+
+ if (PageHighMem(origpage))
+ kunmap_atomic(origvirt, KM_USER0);
+
+ source_index = get_next_bit_on(pageset1_map, source_index);
+ dest_index = get_next_bit_on(pageset1_copy_map, dest_index);
+ }
+}
+
--
Nigel Cunningham nigel at suspend2 dot net
^ permalink raw reply [flat|nested] 11+ messages in thread
* [Suspend2][ 09/10] [Suspend2] Atomic copy highlevel routine.
2006-06-27 4:38 [Suspend2][ 00/10] Suspend2 Atomic Copy Patches Nigel Cunningham
` (7 preceding siblings ...)
2006-06-27 4:39 ` [Suspend2][ 08/10] [Suspend2] Atomic copy routine Nigel Cunningham
@ 2006-06-27 4:39 ` Nigel Cunningham
2006-06-27 4:39 ` [Suspend2][ 10/10] [Suspend2] Atomic restore " Nigel Cunningham
9 siblings, 0 replies; 11+ messages in thread
From: Nigel Cunningham @ 2006-06-27 4:39 UTC (permalink / raw)
To: linux-kernel
This routine essentially duplicates the swsusp_suspend routine, which does
high level steps of the atomic copy. Rather than modifying that routine to
include a number of if (suspend2) else clauses, it seemed better to put a
suspend2ised copy here.
Signed-off-by: Nigel Cunningham <nigel@suspend2.net>
kernel/power/atomic_copy.c | 31 +++++++++++++++++++++++++++++++
1 files changed, 31 insertions(+), 0 deletions(-)
diff --git a/kernel/power/atomic_copy.c b/kernel/power/atomic_copy.c
index 75e3beb..bb5d74f 100644
--- a/kernel/power/atomic_copy.c
+++ b/kernel/power/atomic_copy.c
@@ -349,3 +349,34 @@ void suspend_copy_pageset1(void)
}
}
+int suspend2_suspend(void)
+{
+ int error;
+
+ if ((error = arch_prepare_suspend()))
+ return error;
+ local_irq_disable();
+ /* At this point, device_suspend() has been called, but *not*
+ * device_power_down(). We *must* device_power_down() now.
+ * Otherwise, drivers for some devices (e.g. interrupt controllers)
+ * become desynchronized with the actual state of the hardware
+ * at resume time, and evil weirdness ensues.
+ */
+ if ((error = device_power_down(PMSG_FREEZE))) {
+ printk(KERN_ERR "Some devices failed to power down, aborting suspend\n");
+ goto enable_irqs;
+ }
+
+ save_processor_state();
+ if ((error = swsusp_arch_suspend()))
+ printk(KERN_ERR "Error %d suspending\n", error);
+ /* Restore control flow appears here */
+ restore_processor_state();
+ if (!suspend2_in_suspend)
+ copyback_high();
+ device_power_up();
+enable_irqs:
+ local_irq_enable();
+ return error;
+}
+
--
Nigel Cunningham nigel at suspend2 dot net
^ permalink raw reply [flat|nested] 11+ messages in thread
* [Suspend2][ 10/10] [Suspend2] Atomic restore highlevel routine.
2006-06-27 4:38 [Suspend2][ 00/10] Suspend2 Atomic Copy Patches Nigel Cunningham
` (8 preceding siblings ...)
2006-06-27 4:39 ` [Suspend2][ 09/10] [Suspend2] Atomic copy highlevel routine Nigel Cunningham
@ 2006-06-27 4:39 ` Nigel Cunningham
9 siblings, 0 replies; 11+ messages in thread
From: Nigel Cunningham @ 2006-06-27 4:39 UTC (permalink / raw)
To: linux-kernel
This routine essentially duplicates the swsusp_resume routine, which does
high level steps of the atomic restore. Rather than modifying that routine
to include a number of if (suspend2) else clauses, it seemed better to put
a suspend2ised version here.
Signed-off-by: Nigel Cunningham <nigel@suspend2.net>
kernel/power/atomic_copy.c | 55 ++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 55 insertions(+), 0 deletions(-)
diff --git a/kernel/power/atomic_copy.c b/kernel/power/atomic_copy.c
index bb5d74f..e4aa9f9 100644
--- a/kernel/power/atomic_copy.c
+++ b/kernel/power/atomic_copy.c
@@ -380,3 +380,58 @@ enable_irqs:
return error;
}
+/*
+ * suspend_atomic_restore
+ *
+ * Get ready to do the atomic restore. This part gets us into the same
+ * state we are in prior to do calling do_suspend2_lowlevel while
+ * suspending: hotunplugging secondary cpus and freeze processes,
+ * before starting the thread that will do the restore.
+ */
+int suspend_atomic_restore(void)
+{
+ int error, loop;
+
+ disable_nonboot_cpus();
+
+ suspend_prepare_status(DONT_CLEAR_BAR, "Atomic restore preparation");
+ prepare_suspend2_pbe_list();
+
+ suspend_cond_pause(1, "Device suspend next.\n");
+
+ if ((error = device_suspend(PMSG_FREEZE))) {
+ printk("Some devices failed to suspend\n");
+ BUG();
+ }
+
+#ifdef CONFIG_HIGHMEM
+ origmap = pageset1_map;
+ copymap = pageset1_copy_map;
+ suspend_init_nosave_zone_table();
+#endif
+
+ state1 = suspend_action;
+ state2 = suspend_debug_state;
+ state3 = console_loglevel;
+
+ for (loop = 0; loop < 4; loop++)
+ io_speed_save[loop/2][loop%2] =
+ suspend_io_time[loop/2][loop%2];
+ memcpy(suspend_resume_commandline, saved_command_line, COMMAND_LINE_SIZE);
+
+ local_irq_disable();
+ if (device_power_down(PMSG_FREEZE))
+ printk(KERN_ERR "Some devices failed to power down. Very bad.\n");
+
+ local_irq_disable();
+
+ /* We'll ignore saved state, but this gets preempt count (etc) right */
+ save_processor_state();
+ error = swsusp_arch_resume();
+ /* Code below is only ever reached in case of failure. Otherwise
+ * execution continues at place where swsusp_arch_suspend was called.
+ */
+ BUG();
+ return 1;
+}
+
--
Nigel Cunningham nigel at suspend2 dot net
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2006-06-27 5:12 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-06-27 4:38 [Suspend2][ 00/10] Suspend2 Atomic Copy Patches Nigel Cunningham
2006-06-27 4:38 ` [Suspend2][ 01/10] [Suspend2] Atomic copy file header Nigel Cunningham
2006-06-27 4:38 ` [Suspend2][ 02/10] [Suspend2] Initialise nosave zone table Nigel Cunningham
2006-06-27 4:38 ` [Suspend2][ 03/10] [Suspend2] Atomic copy get_next_bit_on routine Nigel Cunningham
2006-06-27 4:39 ` [Suspend2][ 04/10] [Suspend2] Prepare pbe list for atomic restore Nigel Cunningham
2006-06-27 4:39 ` [Suspend2][ 05/10] [Suspend2] Highmem copyback routine Nigel Cunningham
2006-06-27 4:39 ` [Suspend2][ 06/10] [Suspend2] Post-atomic restore routine Nigel Cunningham
2006-06-27 4:39 ` [Suspend2][ 07/10] [Suspend2] Post suspend context-save routine Nigel Cunningham
2006-06-27 4:39 ` [Suspend2][ 08/10] [Suspend2] Atomic copy routine Nigel Cunningham
2006-06-27 4:39 ` [Suspend2][ 09/10] [Suspend2] Atomic copy highlevel routine Nigel Cunningham
2006-06-27 4:39 ` [Suspend2][ 10/10] [Suspend2] Atomic restore " Nigel Cunningham
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®