Commit b8587daa756141da776e3d4c3a5a315f5af78708
Committed by
Greg Kroah-Hartman
1 parent
958502d836
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
pstore/ram_core: Remove now unused code
The code tried to maintain the global list of persistent ram zones, which isn't a great idea overall, plus since Android's ram_console is no longer there, we can remove some unused functions. Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org> Acked-by: Kees Cook <keescook@chromium.org> Acked-by: Colin Cross <ccross@android.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Showing 2 changed files with 0 additions and 96 deletions Inline Diff
fs/pstore/ram_core.c
1 | /* | 1 | /* |
2 | * Copyright (C) 2012 Google, Inc. | 2 | * Copyright (C) 2012 Google, Inc. |
3 | * | 3 | * |
4 | * This software is licensed under the terms of the GNU General Public | 4 | * This software is licensed under the terms of the GNU General Public |
5 | * License version 2, as published by the Free Software Foundation, and | 5 | * License version 2, as published by the Free Software Foundation, and |
6 | * may be copied, distributed, and modified under those terms. | 6 | * may be copied, distributed, and modified under those terms. |
7 | * | 7 | * |
8 | * This program is distributed in the hope that it will be useful, | 8 | * This program is distributed in the hope that it will be useful, |
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
11 | * GNU General Public License for more details. | 11 | * GNU General Public License for more details. |
12 | * | 12 | * |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/device.h> | 15 | #include <linux/device.h> |
16 | #include <linux/err.h> | 16 | #include <linux/err.h> |
17 | #include <linux/errno.h> | 17 | #include <linux/errno.h> |
18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
19 | #include <linux/init.h> | 19 | #include <linux/init.h> |
20 | #include <linux/io.h> | 20 | #include <linux/io.h> |
21 | #include <linux/list.h> | 21 | #include <linux/list.h> |
22 | #include <linux/memblock.h> | 22 | #include <linux/memblock.h> |
23 | #include <linux/rslib.h> | 23 | #include <linux/rslib.h> |
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | #include <linux/vmalloc.h> | 25 | #include <linux/vmalloc.h> |
26 | #include <linux/pstore_ram.h> | 26 | #include <linux/pstore_ram.h> |
27 | #include <asm/page.h> | 27 | #include <asm/page.h> |
28 | 28 | ||
29 | struct persistent_ram_buffer { | 29 | struct persistent_ram_buffer { |
30 | uint32_t sig; | 30 | uint32_t sig; |
31 | atomic_t start; | 31 | atomic_t start; |
32 | atomic_t size; | 32 | atomic_t size; |
33 | uint8_t data[0]; | 33 | uint8_t data[0]; |
34 | }; | 34 | }; |
35 | 35 | ||
36 | #define PERSISTENT_RAM_SIG (0x43474244) /* DBGC */ | 36 | #define PERSISTENT_RAM_SIG (0x43474244) /* DBGC */ |
37 | 37 | ||
38 | static __initdata LIST_HEAD(persistent_ram_list); | ||
39 | |||
40 | static inline size_t buffer_size(struct persistent_ram_zone *prz) | 38 | static inline size_t buffer_size(struct persistent_ram_zone *prz) |
41 | { | 39 | { |
42 | return atomic_read(&prz->buffer->size); | 40 | return atomic_read(&prz->buffer->size); |
43 | } | 41 | } |
44 | 42 | ||
45 | static inline size_t buffer_start(struct persistent_ram_zone *prz) | 43 | static inline size_t buffer_start(struct persistent_ram_zone *prz) |
46 | { | 44 | { |
47 | return atomic_read(&prz->buffer->start); | 45 | return atomic_read(&prz->buffer->start); |
48 | } | 46 | } |
49 | 47 | ||
50 | /* increase and wrap the start pointer, returning the old value */ | 48 | /* increase and wrap the start pointer, returning the old value */ |
51 | static inline size_t buffer_start_add(struct persistent_ram_zone *prz, size_t a) | 49 | static inline size_t buffer_start_add(struct persistent_ram_zone *prz, size_t a) |
52 | { | 50 | { |
53 | int old; | 51 | int old; |
54 | int new; | 52 | int new; |
55 | 53 | ||
56 | do { | 54 | do { |
57 | old = atomic_read(&prz->buffer->start); | 55 | old = atomic_read(&prz->buffer->start); |
58 | new = old + a; | 56 | new = old + a; |
59 | while (unlikely(new > prz->buffer_size)) | 57 | while (unlikely(new > prz->buffer_size)) |
60 | new -= prz->buffer_size; | 58 | new -= prz->buffer_size; |
61 | } while (atomic_cmpxchg(&prz->buffer->start, old, new) != old); | 59 | } while (atomic_cmpxchg(&prz->buffer->start, old, new) != old); |
62 | 60 | ||
63 | return old; | 61 | return old; |
64 | } | 62 | } |
65 | 63 | ||
66 | /* increase the size counter until it hits the max size */ | 64 | /* increase the size counter until it hits the max size */ |
67 | static inline void buffer_size_add(struct persistent_ram_zone *prz, size_t a) | 65 | static inline void buffer_size_add(struct persistent_ram_zone *prz, size_t a) |
68 | { | 66 | { |
69 | size_t old; | 67 | size_t old; |
70 | size_t new; | 68 | size_t new; |
71 | 69 | ||
72 | if (atomic_read(&prz->buffer->size) == prz->buffer_size) | 70 | if (atomic_read(&prz->buffer->size) == prz->buffer_size) |
73 | return; | 71 | return; |
74 | 72 | ||
75 | do { | 73 | do { |
76 | old = atomic_read(&prz->buffer->size); | 74 | old = atomic_read(&prz->buffer->size); |
77 | new = old + a; | 75 | new = old + a; |
78 | if (new > prz->buffer_size) | 76 | if (new > prz->buffer_size) |
79 | new = prz->buffer_size; | 77 | new = prz->buffer_size; |
80 | } while (atomic_cmpxchg(&prz->buffer->size, old, new) != old); | 78 | } while (atomic_cmpxchg(&prz->buffer->size, old, new) != old); |
81 | } | 79 | } |
82 | 80 | ||
83 | static void notrace persistent_ram_encode_rs8(struct persistent_ram_zone *prz, | 81 | static void notrace persistent_ram_encode_rs8(struct persistent_ram_zone *prz, |
84 | uint8_t *data, size_t len, uint8_t *ecc) | 82 | uint8_t *data, size_t len, uint8_t *ecc) |
85 | { | 83 | { |
86 | int i; | 84 | int i; |
87 | uint16_t par[prz->ecc_size]; | 85 | uint16_t par[prz->ecc_size]; |
88 | 86 | ||
89 | /* Initialize the parity buffer */ | 87 | /* Initialize the parity buffer */ |
90 | memset(par, 0, sizeof(par)); | 88 | memset(par, 0, sizeof(par)); |
91 | encode_rs8(prz->rs_decoder, data, len, par, 0); | 89 | encode_rs8(prz->rs_decoder, data, len, par, 0); |
92 | for (i = 0; i < prz->ecc_size; i++) | 90 | for (i = 0; i < prz->ecc_size; i++) |
93 | ecc[i] = par[i]; | 91 | ecc[i] = par[i]; |
94 | } | 92 | } |
95 | 93 | ||
96 | static int persistent_ram_decode_rs8(struct persistent_ram_zone *prz, | 94 | static int persistent_ram_decode_rs8(struct persistent_ram_zone *prz, |
97 | void *data, size_t len, uint8_t *ecc) | 95 | void *data, size_t len, uint8_t *ecc) |
98 | { | 96 | { |
99 | int i; | 97 | int i; |
100 | uint16_t par[prz->ecc_size]; | 98 | uint16_t par[prz->ecc_size]; |
101 | 99 | ||
102 | for (i = 0; i < prz->ecc_size; i++) | 100 | for (i = 0; i < prz->ecc_size; i++) |
103 | par[i] = ecc[i]; | 101 | par[i] = ecc[i]; |
104 | return decode_rs8(prz->rs_decoder, data, par, len, | 102 | return decode_rs8(prz->rs_decoder, data, par, len, |
105 | NULL, 0, NULL, 0, NULL); | 103 | NULL, 0, NULL, 0, NULL); |
106 | } | 104 | } |
107 | 105 | ||
108 | static void notrace persistent_ram_update_ecc(struct persistent_ram_zone *prz, | 106 | static void notrace persistent_ram_update_ecc(struct persistent_ram_zone *prz, |
109 | unsigned int start, unsigned int count) | 107 | unsigned int start, unsigned int count) |
110 | { | 108 | { |
111 | struct persistent_ram_buffer *buffer = prz->buffer; | 109 | struct persistent_ram_buffer *buffer = prz->buffer; |
112 | uint8_t *buffer_end = buffer->data + prz->buffer_size; | 110 | uint8_t *buffer_end = buffer->data + prz->buffer_size; |
113 | uint8_t *block; | 111 | uint8_t *block; |
114 | uint8_t *par; | 112 | uint8_t *par; |
115 | int ecc_block_size = prz->ecc_block_size; | 113 | int ecc_block_size = prz->ecc_block_size; |
116 | int ecc_size = prz->ecc_size; | 114 | int ecc_size = prz->ecc_size; |
117 | int size = prz->ecc_block_size; | 115 | int size = prz->ecc_block_size; |
118 | 116 | ||
119 | if (!prz->ecc) | 117 | if (!prz->ecc) |
120 | return; | 118 | return; |
121 | 119 | ||
122 | block = buffer->data + (start & ~(ecc_block_size - 1)); | 120 | block = buffer->data + (start & ~(ecc_block_size - 1)); |
123 | par = prz->par_buffer + (start / ecc_block_size) * prz->ecc_size; | 121 | par = prz->par_buffer + (start / ecc_block_size) * prz->ecc_size; |
124 | 122 | ||
125 | do { | 123 | do { |
126 | if (block + ecc_block_size > buffer_end) | 124 | if (block + ecc_block_size > buffer_end) |
127 | size = buffer_end - block; | 125 | size = buffer_end - block; |
128 | persistent_ram_encode_rs8(prz, block, size, par); | 126 | persistent_ram_encode_rs8(prz, block, size, par); |
129 | block += ecc_block_size; | 127 | block += ecc_block_size; |
130 | par += ecc_size; | 128 | par += ecc_size; |
131 | } while (block < buffer->data + start + count); | 129 | } while (block < buffer->data + start + count); |
132 | } | 130 | } |
133 | 131 | ||
134 | static void persistent_ram_update_header_ecc(struct persistent_ram_zone *prz) | 132 | static void persistent_ram_update_header_ecc(struct persistent_ram_zone *prz) |
135 | { | 133 | { |
136 | struct persistent_ram_buffer *buffer = prz->buffer; | 134 | struct persistent_ram_buffer *buffer = prz->buffer; |
137 | 135 | ||
138 | if (!prz->ecc) | 136 | if (!prz->ecc) |
139 | return; | 137 | return; |
140 | 138 | ||
141 | persistent_ram_encode_rs8(prz, (uint8_t *)buffer, sizeof(*buffer), | 139 | persistent_ram_encode_rs8(prz, (uint8_t *)buffer, sizeof(*buffer), |
142 | prz->par_header); | 140 | prz->par_header); |
143 | } | 141 | } |
144 | 142 | ||
145 | static void persistent_ram_ecc_old(struct persistent_ram_zone *prz) | 143 | static void persistent_ram_ecc_old(struct persistent_ram_zone *prz) |
146 | { | 144 | { |
147 | struct persistent_ram_buffer *buffer = prz->buffer; | 145 | struct persistent_ram_buffer *buffer = prz->buffer; |
148 | uint8_t *block; | 146 | uint8_t *block; |
149 | uint8_t *par; | 147 | uint8_t *par; |
150 | 148 | ||
151 | if (!prz->ecc) | 149 | if (!prz->ecc) |
152 | return; | 150 | return; |
153 | 151 | ||
154 | block = buffer->data; | 152 | block = buffer->data; |
155 | par = prz->par_buffer; | 153 | par = prz->par_buffer; |
156 | while (block < buffer->data + buffer_size(prz)) { | 154 | while (block < buffer->data + buffer_size(prz)) { |
157 | int numerr; | 155 | int numerr; |
158 | int size = prz->ecc_block_size; | 156 | int size = prz->ecc_block_size; |
159 | if (block + size > buffer->data + prz->buffer_size) | 157 | if (block + size > buffer->data + prz->buffer_size) |
160 | size = buffer->data + prz->buffer_size - block; | 158 | size = buffer->data + prz->buffer_size - block; |
161 | numerr = persistent_ram_decode_rs8(prz, block, size, par); | 159 | numerr = persistent_ram_decode_rs8(prz, block, size, par); |
162 | if (numerr > 0) { | 160 | if (numerr > 0) { |
163 | pr_devel("persistent_ram: error in block %p, %d\n", | 161 | pr_devel("persistent_ram: error in block %p, %d\n", |
164 | block, numerr); | 162 | block, numerr); |
165 | prz->corrected_bytes += numerr; | 163 | prz->corrected_bytes += numerr; |
166 | } else if (numerr < 0) { | 164 | } else if (numerr < 0) { |
167 | pr_devel("persistent_ram: uncorrectable error in block %p\n", | 165 | pr_devel("persistent_ram: uncorrectable error in block %p\n", |
168 | block); | 166 | block); |
169 | prz->bad_blocks++; | 167 | prz->bad_blocks++; |
170 | } | 168 | } |
171 | block += prz->ecc_block_size; | 169 | block += prz->ecc_block_size; |
172 | par += prz->ecc_size; | 170 | par += prz->ecc_size; |
173 | } | 171 | } |
174 | } | 172 | } |
175 | 173 | ||
176 | static int persistent_ram_init_ecc(struct persistent_ram_zone *prz, | 174 | static int persistent_ram_init_ecc(struct persistent_ram_zone *prz, |
177 | size_t buffer_size) | 175 | size_t buffer_size) |
178 | { | 176 | { |
179 | int numerr; | 177 | int numerr; |
180 | struct persistent_ram_buffer *buffer = prz->buffer; | 178 | struct persistent_ram_buffer *buffer = prz->buffer; |
181 | int ecc_blocks; | 179 | int ecc_blocks; |
182 | 180 | ||
183 | if (!prz->ecc) | 181 | if (!prz->ecc) |
184 | return 0; | 182 | return 0; |
185 | 183 | ||
186 | prz->ecc_block_size = 128; | 184 | prz->ecc_block_size = 128; |
187 | prz->ecc_size = 16; | 185 | prz->ecc_size = 16; |
188 | prz->ecc_symsize = 8; | 186 | prz->ecc_symsize = 8; |
189 | prz->ecc_poly = 0x11d; | 187 | prz->ecc_poly = 0x11d; |
190 | 188 | ||
191 | ecc_blocks = DIV_ROUND_UP(prz->buffer_size, prz->ecc_block_size); | 189 | ecc_blocks = DIV_ROUND_UP(prz->buffer_size, prz->ecc_block_size); |
192 | prz->buffer_size -= (ecc_blocks + 1) * prz->ecc_size; | 190 | prz->buffer_size -= (ecc_blocks + 1) * prz->ecc_size; |
193 | 191 | ||
194 | if (prz->buffer_size > buffer_size) { | 192 | if (prz->buffer_size > buffer_size) { |
195 | pr_err("persistent_ram: invalid size %zu, non-ecc datasize %zu\n", | 193 | pr_err("persistent_ram: invalid size %zu, non-ecc datasize %zu\n", |
196 | buffer_size, prz->buffer_size); | 194 | buffer_size, prz->buffer_size); |
197 | return -EINVAL; | 195 | return -EINVAL; |
198 | } | 196 | } |
199 | 197 | ||
200 | prz->par_buffer = buffer->data + prz->buffer_size; | 198 | prz->par_buffer = buffer->data + prz->buffer_size; |
201 | prz->par_header = prz->par_buffer + ecc_blocks * prz->ecc_size; | 199 | prz->par_header = prz->par_buffer + ecc_blocks * prz->ecc_size; |
202 | 200 | ||
203 | /* | 201 | /* |
204 | * first consecutive root is 0 | 202 | * first consecutive root is 0 |
205 | * primitive element to generate roots = 1 | 203 | * primitive element to generate roots = 1 |
206 | */ | 204 | */ |
207 | prz->rs_decoder = init_rs(prz->ecc_symsize, prz->ecc_poly, 0, 1, | 205 | prz->rs_decoder = init_rs(prz->ecc_symsize, prz->ecc_poly, 0, 1, |
208 | prz->ecc_size); | 206 | prz->ecc_size); |
209 | if (prz->rs_decoder == NULL) { | 207 | if (prz->rs_decoder == NULL) { |
210 | pr_info("persistent_ram: init_rs failed\n"); | 208 | pr_info("persistent_ram: init_rs failed\n"); |
211 | return -EINVAL; | 209 | return -EINVAL; |
212 | } | 210 | } |
213 | 211 | ||
214 | prz->corrected_bytes = 0; | 212 | prz->corrected_bytes = 0; |
215 | prz->bad_blocks = 0; | 213 | prz->bad_blocks = 0; |
216 | 214 | ||
217 | numerr = persistent_ram_decode_rs8(prz, buffer, sizeof(*buffer), | 215 | numerr = persistent_ram_decode_rs8(prz, buffer, sizeof(*buffer), |
218 | prz->par_header); | 216 | prz->par_header); |
219 | if (numerr > 0) { | 217 | if (numerr > 0) { |
220 | pr_info("persistent_ram: error in header, %d\n", numerr); | 218 | pr_info("persistent_ram: error in header, %d\n", numerr); |
221 | prz->corrected_bytes += numerr; | 219 | prz->corrected_bytes += numerr; |
222 | } else if (numerr < 0) { | 220 | } else if (numerr < 0) { |
223 | pr_info("persistent_ram: uncorrectable error in header\n"); | 221 | pr_info("persistent_ram: uncorrectable error in header\n"); |
224 | prz->bad_blocks++; | 222 | prz->bad_blocks++; |
225 | } | 223 | } |
226 | 224 | ||
227 | return 0; | 225 | return 0; |
228 | } | 226 | } |
229 | 227 | ||
230 | ssize_t persistent_ram_ecc_string(struct persistent_ram_zone *prz, | 228 | ssize_t persistent_ram_ecc_string(struct persistent_ram_zone *prz, |
231 | char *str, size_t len) | 229 | char *str, size_t len) |
232 | { | 230 | { |
233 | ssize_t ret; | 231 | ssize_t ret; |
234 | 232 | ||
235 | if (prz->corrected_bytes || prz->bad_blocks) | 233 | if (prz->corrected_bytes || prz->bad_blocks) |
236 | ret = snprintf(str, len, "" | 234 | ret = snprintf(str, len, "" |
237 | "\n%d Corrected bytes, %d unrecoverable blocks\n", | 235 | "\n%d Corrected bytes, %d unrecoverable blocks\n", |
238 | prz->corrected_bytes, prz->bad_blocks); | 236 | prz->corrected_bytes, prz->bad_blocks); |
239 | else | 237 | else |
240 | ret = snprintf(str, len, "\nNo errors detected\n"); | 238 | ret = snprintf(str, len, "\nNo errors detected\n"); |
241 | 239 | ||
242 | return ret; | 240 | return ret; |
243 | } | 241 | } |
244 | 242 | ||
245 | static void notrace persistent_ram_update(struct persistent_ram_zone *prz, | 243 | static void notrace persistent_ram_update(struct persistent_ram_zone *prz, |
246 | const void *s, unsigned int start, unsigned int count) | 244 | const void *s, unsigned int start, unsigned int count) |
247 | { | 245 | { |
248 | struct persistent_ram_buffer *buffer = prz->buffer; | 246 | struct persistent_ram_buffer *buffer = prz->buffer; |
249 | memcpy(buffer->data + start, s, count); | 247 | memcpy(buffer->data + start, s, count); |
250 | persistent_ram_update_ecc(prz, start, count); | 248 | persistent_ram_update_ecc(prz, start, count); |
251 | } | 249 | } |
252 | 250 | ||
253 | void persistent_ram_save_old(struct persistent_ram_zone *prz) | 251 | void persistent_ram_save_old(struct persistent_ram_zone *prz) |
254 | { | 252 | { |
255 | struct persistent_ram_buffer *buffer = prz->buffer; | 253 | struct persistent_ram_buffer *buffer = prz->buffer; |
256 | size_t size = buffer_size(prz); | 254 | size_t size = buffer_size(prz); |
257 | size_t start = buffer_start(prz); | 255 | size_t start = buffer_start(prz); |
258 | 256 | ||
259 | if (!size) | 257 | if (!size) |
260 | return; | 258 | return; |
261 | 259 | ||
262 | if (!prz->old_log) { | 260 | if (!prz->old_log) { |
263 | persistent_ram_ecc_old(prz); | 261 | persistent_ram_ecc_old(prz); |
264 | prz->old_log = kmalloc(size, GFP_KERNEL); | 262 | prz->old_log = kmalloc(size, GFP_KERNEL); |
265 | } | 263 | } |
266 | if (!prz->old_log) { | 264 | if (!prz->old_log) { |
267 | pr_err("persistent_ram: failed to allocate buffer\n"); | 265 | pr_err("persistent_ram: failed to allocate buffer\n"); |
268 | return; | 266 | return; |
269 | } | 267 | } |
270 | 268 | ||
271 | prz->old_log_size = size; | 269 | prz->old_log_size = size; |
272 | memcpy(prz->old_log, &buffer->data[start], size - start); | 270 | memcpy(prz->old_log, &buffer->data[start], size - start); |
273 | memcpy(prz->old_log + size - start, &buffer->data[0], start); | 271 | memcpy(prz->old_log + size - start, &buffer->data[0], start); |
274 | } | 272 | } |
275 | 273 | ||
276 | int notrace persistent_ram_write(struct persistent_ram_zone *prz, | 274 | int notrace persistent_ram_write(struct persistent_ram_zone *prz, |
277 | const void *s, unsigned int count) | 275 | const void *s, unsigned int count) |
278 | { | 276 | { |
279 | int rem; | 277 | int rem; |
280 | int c = count; | 278 | int c = count; |
281 | size_t start; | 279 | size_t start; |
282 | 280 | ||
283 | if (unlikely(c > prz->buffer_size)) { | 281 | if (unlikely(c > prz->buffer_size)) { |
284 | s += c - prz->buffer_size; | 282 | s += c - prz->buffer_size; |
285 | c = prz->buffer_size; | 283 | c = prz->buffer_size; |
286 | } | 284 | } |
287 | 285 | ||
288 | buffer_size_add(prz, c); | 286 | buffer_size_add(prz, c); |
289 | 287 | ||
290 | start = buffer_start_add(prz, c); | 288 | start = buffer_start_add(prz, c); |
291 | 289 | ||
292 | rem = prz->buffer_size - start; | 290 | rem = prz->buffer_size - start; |
293 | if (unlikely(rem < c)) { | 291 | if (unlikely(rem < c)) { |
294 | persistent_ram_update(prz, s, start, rem); | 292 | persistent_ram_update(prz, s, start, rem); |
295 | s += rem; | 293 | s += rem; |
296 | c -= rem; | 294 | c -= rem; |
297 | start = 0; | 295 | start = 0; |
298 | } | 296 | } |
299 | persistent_ram_update(prz, s, start, c); | 297 | persistent_ram_update(prz, s, start, c); |
300 | 298 | ||
301 | persistent_ram_update_header_ecc(prz); | 299 | persistent_ram_update_header_ecc(prz); |
302 | 300 | ||
303 | return count; | 301 | return count; |
304 | } | 302 | } |
305 | 303 | ||
306 | size_t persistent_ram_old_size(struct persistent_ram_zone *prz) | 304 | size_t persistent_ram_old_size(struct persistent_ram_zone *prz) |
307 | { | 305 | { |
308 | return prz->old_log_size; | 306 | return prz->old_log_size; |
309 | } | 307 | } |
310 | 308 | ||
311 | void *persistent_ram_old(struct persistent_ram_zone *prz) | 309 | void *persistent_ram_old(struct persistent_ram_zone *prz) |
312 | { | 310 | { |
313 | return prz->old_log; | 311 | return prz->old_log; |
314 | } | 312 | } |
315 | 313 | ||
316 | void persistent_ram_free_old(struct persistent_ram_zone *prz) | 314 | void persistent_ram_free_old(struct persistent_ram_zone *prz) |
317 | { | 315 | { |
318 | kfree(prz->old_log); | 316 | kfree(prz->old_log); |
319 | prz->old_log = NULL; | 317 | prz->old_log = NULL; |
320 | prz->old_log_size = 0; | 318 | prz->old_log_size = 0; |
321 | } | 319 | } |
322 | 320 | ||
323 | void persistent_ram_zap(struct persistent_ram_zone *prz) | 321 | void persistent_ram_zap(struct persistent_ram_zone *prz) |
324 | { | 322 | { |
325 | atomic_set(&prz->buffer->start, 0); | 323 | atomic_set(&prz->buffer->start, 0); |
326 | atomic_set(&prz->buffer->size, 0); | 324 | atomic_set(&prz->buffer->size, 0); |
327 | persistent_ram_update_header_ecc(prz); | 325 | persistent_ram_update_header_ecc(prz); |
328 | } | 326 | } |
329 | 327 | ||
330 | static void *persistent_ram_vmap(phys_addr_t start, size_t size) | 328 | static void *persistent_ram_vmap(phys_addr_t start, size_t size) |
331 | { | 329 | { |
332 | struct page **pages; | 330 | struct page **pages; |
333 | phys_addr_t page_start; | 331 | phys_addr_t page_start; |
334 | unsigned int page_count; | 332 | unsigned int page_count; |
335 | pgprot_t prot; | 333 | pgprot_t prot; |
336 | unsigned int i; | 334 | unsigned int i; |
337 | void *vaddr; | 335 | void *vaddr; |
338 | 336 | ||
339 | page_start = start - offset_in_page(start); | 337 | page_start = start - offset_in_page(start); |
340 | page_count = DIV_ROUND_UP(size + offset_in_page(start), PAGE_SIZE); | 338 | page_count = DIV_ROUND_UP(size + offset_in_page(start), PAGE_SIZE); |
341 | 339 | ||
342 | prot = pgprot_noncached(PAGE_KERNEL); | 340 | prot = pgprot_noncached(PAGE_KERNEL); |
343 | 341 | ||
344 | pages = kmalloc(sizeof(struct page *) * page_count, GFP_KERNEL); | 342 | pages = kmalloc(sizeof(struct page *) * page_count, GFP_KERNEL); |
345 | if (!pages) { | 343 | if (!pages) { |
346 | pr_err("%s: Failed to allocate array for %u pages\n", __func__, | 344 | pr_err("%s: Failed to allocate array for %u pages\n", __func__, |
347 | page_count); | 345 | page_count); |
348 | return NULL; | 346 | return NULL; |
349 | } | 347 | } |
350 | 348 | ||
351 | for (i = 0; i < page_count; i++) { | 349 | for (i = 0; i < page_count; i++) { |
352 | phys_addr_t addr = page_start + i * PAGE_SIZE; | 350 | phys_addr_t addr = page_start + i * PAGE_SIZE; |
353 | pages[i] = pfn_to_page(addr >> PAGE_SHIFT); | 351 | pages[i] = pfn_to_page(addr >> PAGE_SHIFT); |
354 | } | 352 | } |
355 | vaddr = vmap(pages, page_count, VM_MAP, prot); | 353 | vaddr = vmap(pages, page_count, VM_MAP, prot); |
356 | kfree(pages); | 354 | kfree(pages); |
357 | 355 | ||
358 | return vaddr; | 356 | return vaddr; |
359 | } | 357 | } |
360 | 358 | ||
361 | static void *persistent_ram_iomap(phys_addr_t start, size_t size) | 359 | static void *persistent_ram_iomap(phys_addr_t start, size_t size) |
362 | { | 360 | { |
363 | if (!request_mem_region(start, size, "persistent_ram")) { | 361 | if (!request_mem_region(start, size, "persistent_ram")) { |
364 | pr_err("request mem region (0x%llx@0x%llx) failed\n", | 362 | pr_err("request mem region (0x%llx@0x%llx) failed\n", |
365 | (unsigned long long)size, (unsigned long long)start); | 363 | (unsigned long long)size, (unsigned long long)start); |
366 | return NULL; | 364 | return NULL; |
367 | } | 365 | } |
368 | 366 | ||
369 | return ioremap(start, size); | 367 | return ioremap(start, size); |
370 | } | 368 | } |
371 | 369 | ||
372 | static int persistent_ram_buffer_map(phys_addr_t start, phys_addr_t size, | 370 | static int persistent_ram_buffer_map(phys_addr_t start, phys_addr_t size, |
373 | struct persistent_ram_zone *prz) | 371 | struct persistent_ram_zone *prz) |
374 | { | 372 | { |
375 | prz->paddr = start; | 373 | prz->paddr = start; |
376 | prz->size = size; | 374 | prz->size = size; |
377 | 375 | ||
378 | if (pfn_valid(start >> PAGE_SHIFT)) | 376 | if (pfn_valid(start >> PAGE_SHIFT)) |
379 | prz->vaddr = persistent_ram_vmap(start, size); | 377 | prz->vaddr = persistent_ram_vmap(start, size); |
380 | else | 378 | else |
381 | prz->vaddr = persistent_ram_iomap(start, size); | 379 | prz->vaddr = persistent_ram_iomap(start, size); |
382 | 380 | ||
383 | if (!prz->vaddr) { | 381 | if (!prz->vaddr) { |
384 | pr_err("%s: Failed to map 0x%llx pages at 0x%llx\n", __func__, | 382 | pr_err("%s: Failed to map 0x%llx pages at 0x%llx\n", __func__, |
385 | (unsigned long long)size, (unsigned long long)start); | 383 | (unsigned long long)size, (unsigned long long)start); |
386 | return -ENOMEM; | 384 | return -ENOMEM; |
387 | } | 385 | } |
388 | 386 | ||
389 | prz->buffer = prz->vaddr + offset_in_page(start); | 387 | prz->buffer = prz->vaddr + offset_in_page(start); |
390 | prz->buffer_size = size - sizeof(struct persistent_ram_buffer); | 388 | prz->buffer_size = size - sizeof(struct persistent_ram_buffer); |
391 | 389 | ||
392 | return 0; | 390 | return 0; |
393 | } | 391 | } |
394 | 392 | ||
395 | static int __init persistent_ram_post_init(struct persistent_ram_zone *prz, bool ecc) | 393 | static int __init persistent_ram_post_init(struct persistent_ram_zone *prz, bool ecc) |
396 | { | 394 | { |
397 | int ret; | 395 | int ret; |
398 | 396 | ||
399 | prz->ecc = ecc; | 397 | prz->ecc = ecc; |
400 | 398 | ||
401 | ret = persistent_ram_init_ecc(prz, prz->buffer_size); | 399 | ret = persistent_ram_init_ecc(prz, prz->buffer_size); |
402 | if (ret) | 400 | if (ret) |
403 | return ret; | 401 | return ret; |
404 | 402 | ||
405 | if (prz->buffer->sig == PERSISTENT_RAM_SIG) { | 403 | if (prz->buffer->sig == PERSISTENT_RAM_SIG) { |
406 | if (buffer_size(prz) > prz->buffer_size || | 404 | if (buffer_size(prz) > prz->buffer_size || |
407 | buffer_start(prz) > buffer_size(prz)) | 405 | buffer_start(prz) > buffer_size(prz)) |
408 | pr_info("persistent_ram: found existing invalid buffer," | 406 | pr_info("persistent_ram: found existing invalid buffer," |
409 | " size %zu, start %zu\n", | 407 | " size %zu, start %zu\n", |
410 | buffer_size(prz), buffer_start(prz)); | 408 | buffer_size(prz), buffer_start(prz)); |
411 | else { | 409 | else { |
412 | pr_debug("persistent_ram: found existing buffer," | 410 | pr_debug("persistent_ram: found existing buffer," |
413 | " size %zu, start %zu\n", | 411 | " size %zu, start %zu\n", |
414 | buffer_size(prz), buffer_start(prz)); | 412 | buffer_size(prz), buffer_start(prz)); |
415 | persistent_ram_save_old(prz); | 413 | persistent_ram_save_old(prz); |
416 | return 0; | 414 | return 0; |
417 | } | 415 | } |
418 | } else { | 416 | } else { |
419 | pr_debug("persistent_ram: no valid data in buffer" | 417 | pr_debug("persistent_ram: no valid data in buffer" |
420 | " (sig = 0x%08x)\n", prz->buffer->sig); | 418 | " (sig = 0x%08x)\n", prz->buffer->sig); |
421 | } | 419 | } |
422 | 420 | ||
423 | prz->buffer->sig = PERSISTENT_RAM_SIG; | 421 | prz->buffer->sig = PERSISTENT_RAM_SIG; |
424 | persistent_ram_zap(prz); | 422 | persistent_ram_zap(prz); |
425 | 423 | ||
426 | return 0; | 424 | return 0; |
427 | } | 425 | } |
428 | 426 | ||
429 | void persistent_ram_free(struct persistent_ram_zone *prz) | 427 | void persistent_ram_free(struct persistent_ram_zone *prz) |
430 | { | 428 | { |
431 | if (pfn_valid(prz->paddr >> PAGE_SHIFT)) { | 429 | if (pfn_valid(prz->paddr >> PAGE_SHIFT)) { |
432 | vunmap(prz->vaddr); | 430 | vunmap(prz->vaddr); |
433 | } else { | 431 | } else { |
434 | iounmap(prz->vaddr); | 432 | iounmap(prz->vaddr); |
435 | release_mem_region(prz->paddr, prz->size); | 433 | release_mem_region(prz->paddr, prz->size); |
436 | } | 434 | } |
437 | persistent_ram_free_old(prz); | 435 | persistent_ram_free_old(prz); |
438 | kfree(prz); | 436 | kfree(prz); |
439 | } | 437 | } |
440 | 438 | ||
441 | struct persistent_ram_zone * __init persistent_ram_new(phys_addr_t start, | 439 | struct persistent_ram_zone * __init persistent_ram_new(phys_addr_t start, |
442 | size_t size, | 440 | size_t size, |
443 | bool ecc) | 441 | bool ecc) |
444 | { | 442 | { |
445 | struct persistent_ram_zone *prz; | 443 | struct persistent_ram_zone *prz; |
446 | int ret = -ENOMEM; | 444 | int ret = -ENOMEM; |
447 | 445 | ||
448 | prz = kzalloc(sizeof(struct persistent_ram_zone), GFP_KERNEL); | 446 | prz = kzalloc(sizeof(struct persistent_ram_zone), GFP_KERNEL); |
449 | if (!prz) { | 447 | if (!prz) { |
450 | pr_err("persistent_ram: failed to allocate persistent ram zone\n"); | 448 | pr_err("persistent_ram: failed to allocate persistent ram zone\n"); |
451 | goto err; | 449 | goto err; |
452 | } | 450 | } |
453 | 451 | ||
454 | ret = persistent_ram_buffer_map(start, size, prz); | 452 | ret = persistent_ram_buffer_map(start, size, prz); |
455 | if (ret) | 453 | if (ret) |
456 | goto err; | 454 | goto err; |
457 | 455 | ||
458 | persistent_ram_post_init(prz, ecc); | 456 | persistent_ram_post_init(prz, ecc); |
459 | 457 | ||
460 | return prz; | 458 | return prz; |
461 | err: | 459 | err: |
462 | kfree(prz); | 460 | kfree(prz); |
463 | return ERR_PTR(ret); | 461 | return ERR_PTR(ret); |
464 | } | 462 | } |
465 | |||
466 | #ifndef MODULE | ||
467 | static int __init persistent_ram_buffer_init(const char *name, | ||
468 | struct persistent_ram_zone *prz) | ||
469 | { | ||
470 | int i; | ||
471 | struct persistent_ram *ram; | ||
472 | struct persistent_ram_descriptor *desc; | ||
473 | phys_addr_t start; | ||
474 | |||
475 | list_for_each_entry(ram, &persistent_ram_list, node) { | ||
476 | start = ram->start; | ||
477 | for (i = 0; i < ram->num_descs; i++) { | ||
478 | desc = &ram->descs[i]; | ||
479 | if (!strcmp(desc->name, name)) | ||
480 | return persistent_ram_buffer_map(start, | ||
481 | desc->size, prz); | ||
482 | start += desc->size; | ||
483 | } | ||
484 | } | ||
485 | |||
486 | return -EINVAL; | ||
487 | } | ||
488 | |||
489 | static __init | ||
490 | struct persistent_ram_zone *__persistent_ram_init(struct device *dev, bool ecc) | ||
491 | { | ||
492 | struct persistent_ram_zone *prz; | ||
493 | int ret = -ENOMEM; | ||
494 | |||
495 | prz = kzalloc(sizeof(struct persistent_ram_zone), GFP_KERNEL); | ||
496 | if (!prz) { | ||
497 | pr_err("persistent_ram: failed to allocate persistent ram zone\n"); | ||
498 | goto err; | ||
499 | } | ||
500 | |||
501 | ret = persistent_ram_buffer_init(dev_name(dev), prz); | ||
502 | if (ret) { | ||
503 | pr_err("persistent_ram: failed to initialize buffer\n"); | ||
504 | goto err; | ||
505 | } | ||
506 | |||
507 | persistent_ram_post_init(prz, ecc); | ||
508 | |||
509 | return prz; | ||
510 | err: | ||
511 | kfree(prz); | ||
512 | return ERR_PTR(ret); | ||
513 | } | ||
514 | |||
515 | struct persistent_ram_zone * __init | ||
516 | persistent_ram_init_ringbuffer(struct device *dev, bool ecc) | ||
517 | { | ||
518 | return __persistent_ram_init(dev, ecc); | ||
519 | } | ||
520 | |||
521 | int __init persistent_ram_early_init(struct persistent_ram *ram) | ||
522 | { | ||
523 | int ret; | ||
524 | |||
525 | ret = memblock_reserve(ram->start, ram->size); | ||
526 | if (ret) { | ||
527 | pr_err("Failed to reserve persistent memory from %08lx-%08lx\n", | ||
528 | (long)ram->start, (long)(ram->start + ram->size - 1)); | ||
529 | return ret; | ||
530 | } | ||
531 | |||
532 | list_add_tail(&ram->node, &persistent_ram_list); | ||
533 | |||
534 | pr_info("Initialized persistent memory from %08lx-%08lx\n", | ||
535 | (long)ram->start, (long)(ram->start + ram->size - 1)); | ||
536 | |||
537 | return 0; | ||
538 | } | ||
539 | #endif | ||
540 | 463 |
include/linux/pstore_ram.h
1 | /* | 1 | /* |
2 | * Copyright (C) 2010 Marco Stornelli <marco.stornelli@gmail.com> | 2 | * Copyright (C) 2010 Marco Stornelli <marco.stornelli@gmail.com> |
3 | * Copyright (C) 2011 Kees Cook <keescook@chromium.org> | 3 | * Copyright (C) 2011 Kees Cook <keescook@chromium.org> |
4 | * Copyright (C) 2011 Google, Inc. | 4 | * Copyright (C) 2011 Google, Inc. |
5 | * | 5 | * |
6 | * This software is licensed under the terms of the GNU General Public | 6 | * This software is licensed under the terms of the GNU General Public |
7 | * License version 2, as published by the Free Software Foundation, and | 7 | * License version 2, as published by the Free Software Foundation, and |
8 | * may be copied, distributed, and modified under those terms. | 8 | * may be copied, distributed, and modified under those terms. |
9 | * | 9 | * |
10 | * This program is distributed in the hope that it will be useful, | 10 | * This program is distributed in the hope that it will be useful, |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | * GNU General Public License for more details. | 13 | * GNU General Public License for more details. |
14 | * | 14 | * |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #ifndef __LINUX_PSTORE_RAM_H__ | 17 | #ifndef __LINUX_PSTORE_RAM_H__ |
18 | #define __LINUX_PSTORE_RAM_H__ | 18 | #define __LINUX_PSTORE_RAM_H__ |
19 | 19 | ||
20 | #include <linux/device.h> | 20 | #include <linux/device.h> |
21 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
22 | #include <linux/list.h> | 22 | #include <linux/list.h> |
23 | #include <linux/types.h> | 23 | #include <linux/types.h> |
24 | #include <linux/init.h> | 24 | #include <linux/init.h> |
25 | 25 | ||
26 | struct persistent_ram_buffer; | 26 | struct persistent_ram_buffer; |
27 | 27 | ||
28 | struct persistent_ram_descriptor { | ||
29 | const char *name; | ||
30 | phys_addr_t size; | ||
31 | }; | ||
32 | |||
33 | struct persistent_ram { | ||
34 | phys_addr_t start; | ||
35 | phys_addr_t size; | ||
36 | |||
37 | int num_descs; | ||
38 | struct persistent_ram_descriptor *descs; | ||
39 | |||
40 | struct list_head node; | ||
41 | }; | ||
42 | |||
43 | struct persistent_ram_zone { | 28 | struct persistent_ram_zone { |
44 | phys_addr_t paddr; | 29 | phys_addr_t paddr; |
45 | size_t size; | 30 | size_t size; |
46 | void *vaddr; | 31 | void *vaddr; |
47 | struct persistent_ram_buffer *buffer; | 32 | struct persistent_ram_buffer *buffer; |
48 | size_t buffer_size; | 33 | size_t buffer_size; |
49 | 34 | ||
50 | /* ECC correction */ | 35 | /* ECC correction */ |
51 | bool ecc; | 36 | bool ecc; |
52 | char *par_buffer; | 37 | char *par_buffer; |
53 | char *par_header; | 38 | char *par_header; |
54 | struct rs_control *rs_decoder; | 39 | struct rs_control *rs_decoder; |
55 | int corrected_bytes; | 40 | int corrected_bytes; |
56 | int bad_blocks; | 41 | int bad_blocks; |
57 | int ecc_block_size; | 42 | int ecc_block_size; |
58 | int ecc_size; | 43 | int ecc_size; |
59 | int ecc_symsize; | 44 | int ecc_symsize; |
60 | int ecc_poly; | 45 | int ecc_poly; |
61 | 46 | ||
62 | char *old_log; | 47 | char *old_log; |
63 | size_t old_log_size; | 48 | size_t old_log_size; |
64 | }; | 49 | }; |
65 | 50 | ||
66 | int persistent_ram_early_init(struct persistent_ram *ram); | ||
67 | |||
68 | struct persistent_ram_zone * __init persistent_ram_new(phys_addr_t start, | 51 | struct persistent_ram_zone * __init persistent_ram_new(phys_addr_t start, |
69 | size_t size, | 52 | size_t size, |
70 | bool ecc); | 53 | bool ecc); |
71 | void persistent_ram_free(struct persistent_ram_zone *prz); | 54 | void persistent_ram_free(struct persistent_ram_zone *prz); |
72 | void persistent_ram_zap(struct persistent_ram_zone *prz); | 55 | void persistent_ram_zap(struct persistent_ram_zone *prz); |
73 | struct persistent_ram_zone *persistent_ram_init_ringbuffer(struct device *dev, | ||
74 | bool ecc); | ||
75 | 56 | ||
76 | int persistent_ram_write(struct persistent_ram_zone *prz, const void *s, | 57 | int persistent_ram_write(struct persistent_ram_zone *prz, const void *s, |
77 | unsigned int count); | 58 | unsigned int count); |
78 | 59 | ||
79 | void persistent_ram_save_old(struct persistent_ram_zone *prz); | 60 | void persistent_ram_save_old(struct persistent_ram_zone *prz); |
80 | size_t persistent_ram_old_size(struct persistent_ram_zone *prz); | 61 | size_t persistent_ram_old_size(struct persistent_ram_zone *prz); |
81 | void *persistent_ram_old(struct persistent_ram_zone *prz); | 62 | void *persistent_ram_old(struct persistent_ram_zone *prz); |
82 | void persistent_ram_free_old(struct persistent_ram_zone *prz); | 63 | void persistent_ram_free_old(struct persistent_ram_zone *prz); |
83 | ssize_t persistent_ram_ecc_string(struct persistent_ram_zone *prz, | 64 | ssize_t persistent_ram_ecc_string(struct persistent_ram_zone *prz, |
84 | char *str, size_t len); | 65 | char *str, size_t len); |
85 | 66 | ||
86 | /* | 67 | /* |
87 | * Ramoops platform data | 68 | * Ramoops platform data |
88 | * @mem_size memory size for ramoops | 69 | * @mem_size memory size for ramoops |
89 | * @mem_address physical memory address to contain ramoops | 70 | * @mem_address physical memory address to contain ramoops |
90 | */ | 71 | */ |
91 | 72 | ||
92 | struct ramoops_platform_data { | 73 | struct ramoops_platform_data { |
93 | unsigned long mem_size; | 74 | unsigned long mem_size; |
94 | unsigned long mem_address; | 75 | unsigned long mem_address; |
95 | unsigned long record_size; | 76 | unsigned long record_size; |
96 | unsigned long console_size; | 77 | unsigned long console_size; |
97 | int dump_oops; | 78 | int dump_oops; |
98 | bool ecc; | 79 | bool ecc; |
99 | }; | 80 | }; |
100 | 81 | ||
101 | #endif | 82 | #endif |
102 | 83 |