diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /kernel/power/swsusp.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'kernel/power/swsusp.c')
-rw-r--r-- | kernel/power/swsusp.c | 188 |
1 files changed, 0 insertions, 188 deletions
diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c deleted file mode 100644 index 6a07f4dbf2f8..000000000000 --- a/kernel/power/swsusp.c +++ /dev/null | |||
@@ -1,188 +0,0 @@ | |||
1 | /* | ||
2 | * linux/kernel/power/swsusp.c | ||
3 | * | ||
4 | * This file provides code to write suspend image to swap and read it back. | ||
5 | * | ||
6 | * Copyright (C) 1998-2001 Gabor Kuti <seasons@fornax.hu> | ||
7 | * Copyright (C) 1998,2001-2005 Pavel Machek <pavel@suse.cz> | ||
8 | * | ||
9 | * This file is released under the GPLv2. | ||
10 | * | ||
11 | * I'd like to thank the following people for their work: | ||
12 | * | ||
13 | * Pavel Machek <pavel@ucw.cz>: | ||
14 | * Modifications, defectiveness pointing, being with me at the very beginning, | ||
15 | * suspend to swap space, stop all tasks. Port to 2.4.18-ac and 2.5.17. | ||
16 | * | ||
17 | * Steve Doddi <dirk@loth.demon.co.uk>: | ||
18 | * Support the possibility of hardware state restoring. | ||
19 | * | ||
20 | * Raph <grey.havens@earthling.net>: | ||
21 | * Support for preserving states of network devices and virtual console | ||
22 | * (including X and svgatextmode) | ||
23 | * | ||
24 | * Kurt Garloff <garloff@suse.de>: | ||
25 | * Straightened the critical function in order to prevent compilers from | ||
26 | * playing tricks with local variables. | ||
27 | * | ||
28 | * Andreas Mohr <a.mohr@mailto.de> | ||
29 | * | ||
30 | * Alex Badea <vampire@go.ro>: | ||
31 | * Fixed runaway init | ||
32 | * | ||
33 | * Rafael J. Wysocki <rjw@sisk.pl> | ||
34 | * Reworked the freeing of memory and the handling of swap | ||
35 | * | ||
36 | * More state savers are welcome. Especially for the scsi layer... | ||
37 | * | ||
38 | * For TODOs,FIXMEs also look in Documentation/power/swsusp.txt | ||
39 | */ | ||
40 | |||
41 | #include <linux/mm.h> | ||
42 | #include <linux/suspend.h> | ||
43 | #include <linux/spinlock.h> | ||
44 | #include <linux/kernel.h> | ||
45 | #include <linux/major.h> | ||
46 | #include <linux/swap.h> | ||
47 | #include <linux/pm.h> | ||
48 | #include <linux/swapops.h> | ||
49 | #include <linux/bootmem.h> | ||
50 | #include <linux/syscalls.h> | ||
51 | #include <linux/highmem.h> | ||
52 | #include <linux/time.h> | ||
53 | #include <linux/rbtree.h> | ||
54 | #include <linux/io.h> | ||
55 | |||
56 | #include "power.h" | ||
57 | |||
58 | int in_suspend __nosavedata = 0; | ||
59 | |||
60 | /** | ||
61 | * The following functions are used for tracing the allocated | ||
62 | * swap pages, so that they can be freed in case of an error. | ||
63 | */ | ||
64 | |||
65 | struct swsusp_extent { | ||
66 | struct rb_node node; | ||
67 | unsigned long start; | ||
68 | unsigned long end; | ||
69 | }; | ||
70 | |||
71 | static struct rb_root swsusp_extents = RB_ROOT; | ||
72 | |||
73 | static int swsusp_extents_insert(unsigned long swap_offset) | ||
74 | { | ||
75 | struct rb_node **new = &(swsusp_extents.rb_node); | ||
76 | struct rb_node *parent = NULL; | ||
77 | struct swsusp_extent *ext; | ||
78 | |||
79 | /* Figure out where to put the new node */ | ||
80 | while (*new) { | ||
81 | ext = container_of(*new, struct swsusp_extent, node); | ||
82 | parent = *new; | ||
83 | if (swap_offset < ext->start) { | ||
84 | /* Try to merge */ | ||
85 | if (swap_offset == ext->start - 1) { | ||
86 | ext->start--; | ||
87 | return 0; | ||
88 | } | ||
89 | new = &((*new)->rb_left); | ||
90 | } else if (swap_offset > ext->end) { | ||
91 | /* Try to merge */ | ||
92 | if (swap_offset == ext->end + 1) { | ||
93 | ext->end++; | ||
94 | return 0; | ||
95 | } | ||
96 | new = &((*new)->rb_right); | ||
97 | } else { | ||
98 | /* It already is in the tree */ | ||
99 | return -EINVAL; | ||
100 | } | ||
101 | } | ||
102 | /* Add the new node and rebalance the tree. */ | ||
103 | ext = kzalloc(sizeof(struct swsusp_extent), GFP_KERNEL); | ||
104 | if (!ext) | ||
105 | return -ENOMEM; | ||
106 | |||
107 | ext->start = swap_offset; | ||
108 | ext->end = swap_offset; | ||
109 | rb_link_node(&ext->node, parent, new); | ||
110 | rb_insert_color(&ext->node, &swsusp_extents); | ||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | /** | ||
115 | * alloc_swapdev_block - allocate a swap page and register that it has | ||
116 | * been allocated, so that it can be freed in case of an error. | ||
117 | */ | ||
118 | |||
119 | sector_t alloc_swapdev_block(int swap) | ||
120 | { | ||
121 | unsigned long offset; | ||
122 | |||
123 | offset = swp_offset(get_swap_page_of_type(swap)); | ||
124 | if (offset) { | ||
125 | if (swsusp_extents_insert(offset)) | ||
126 | swap_free(swp_entry(swap, offset)); | ||
127 | else | ||
128 | return swapdev_block(swap, offset); | ||
129 | } | ||
130 | return 0; | ||
131 | } | ||
132 | |||
133 | /** | ||
134 | * free_all_swap_pages - free swap pages allocated for saving image data. | ||
135 | * It also frees the extents used to register which swap entres had been | ||
136 | * allocated. | ||
137 | */ | ||
138 | |||
139 | void free_all_swap_pages(int swap) | ||
140 | { | ||
141 | struct rb_node *node; | ||
142 | |||
143 | while ((node = swsusp_extents.rb_node)) { | ||
144 | struct swsusp_extent *ext; | ||
145 | unsigned long offset; | ||
146 | |||
147 | ext = container_of(node, struct swsusp_extent, node); | ||
148 | rb_erase(node, &swsusp_extents); | ||
149 | for (offset = ext->start; offset <= ext->end; offset++) | ||
150 | swap_free(swp_entry(swap, offset)); | ||
151 | |||
152 | kfree(ext); | ||
153 | } | ||
154 | } | ||
155 | |||
156 | int swsusp_swap_in_use(void) | ||
157 | { | ||
158 | return (swsusp_extents.rb_node != NULL); | ||
159 | } | ||
160 | |||
161 | /** | ||
162 | * swsusp_show_speed - print the time elapsed between two events represented by | ||
163 | * @start and @stop | ||
164 | * | ||
165 | * @nr_pages - number of pages processed between @start and @stop | ||
166 | * @msg - introductory message to print | ||
167 | */ | ||
168 | |||
169 | void swsusp_show_speed(struct timeval *start, struct timeval *stop, | ||
170 | unsigned nr_pages, char *msg) | ||
171 | { | ||
172 | s64 elapsed_centisecs64; | ||
173 | int centisecs; | ||
174 | int k; | ||
175 | int kps; | ||
176 | |||
177 | elapsed_centisecs64 = timeval_to_ns(stop) - timeval_to_ns(start); | ||
178 | do_div(elapsed_centisecs64, NSEC_PER_SEC / 100); | ||
179 | centisecs = elapsed_centisecs64; | ||
180 | if (centisecs == 0) | ||
181 | centisecs = 1; /* avoid div-by-zero */ | ||
182 | k = nr_pages * (PAGE_SIZE / 1024); | ||
183 | kps = (k * 100) / centisecs; | ||
184 | printk(KERN_INFO "PM: %s %d kbytes in %d.%02d seconds (%d.%02d MB/s)\n", | ||
185 | msg, k, | ||
186 | centisecs / 100, centisecs % 100, | ||
187 | kps / 1000, (kps % 1000) / 10); | ||
188 | } | ||