diff options
-rw-r--r-- | fs/pstore/Kconfig | 10 | ||||
-rw-r--r-- | fs/pstore/Makefile | 2 | ||||
-rw-r--r-- | fs/pstore/inode.c | 26 | ||||
-rw-r--r-- | fs/pstore/internal.h | 6 | ||||
-rw-r--r-- | fs/pstore/platform.c | 5 | ||||
-rw-r--r-- | fs/pstore/pmsg.c | 114 | ||||
-rw-r--r-- | fs/pstore/ram.c | 53 | ||||
-rw-r--r-- | include/linux/pstore.h | 1 | ||||
-rw-r--r-- | include/linux/pstore_ram.h | 1 |
9 files changed, 193 insertions, 25 deletions
diff --git a/fs/pstore/Kconfig b/fs/pstore/Kconfig index 983d9510becc..916b8e23d968 100644 --- a/fs/pstore/Kconfig +++ b/fs/pstore/Kconfig | |||
@@ -21,6 +21,16 @@ config PSTORE_CONSOLE | |||
21 | When the option is enabled, pstore will log all kernel | 21 | When the option is enabled, pstore will log all kernel |
22 | messages, even if no oops or panic happened. | 22 | messages, even if no oops or panic happened. |
23 | 23 | ||
24 | config PSTORE_PMSG | ||
25 | bool "Log user space messages" | ||
26 | depends on PSTORE | ||
27 | help | ||
28 | When the option is enabled, pstore will export a character | ||
29 | interface /dev/pmsg0 to log user space messages. On reboot | ||
30 | data can be retrieved from /sys/fs/pstore/pmsg-ramoops-[ID]. | ||
31 | |||
32 | If unsure, say N. | ||
33 | |||
24 | config PSTORE_FTRACE | 34 | config PSTORE_FTRACE |
25 | bool "Persistent function tracer" | 35 | bool "Persistent function tracer" |
26 | depends on PSTORE | 36 | depends on PSTORE |
diff --git a/fs/pstore/Makefile b/fs/pstore/Makefile index 4c9095c2781e..e647d8e81712 100644 --- a/fs/pstore/Makefile +++ b/fs/pstore/Makefile | |||
@@ -7,5 +7,7 @@ obj-y += pstore.o | |||
7 | pstore-objs += inode.o platform.o | 7 | pstore-objs += inode.o platform.o |
8 | obj-$(CONFIG_PSTORE_FTRACE) += ftrace.o | 8 | obj-$(CONFIG_PSTORE_FTRACE) += ftrace.o |
9 | 9 | ||
10 | obj-$(CONFIG_PSTORE_PMSG) += pmsg.o | ||
11 | |||
10 | ramoops-objs += ram.o ram_core.o | 12 | ramoops-objs += ram.o ram_core.o |
11 | obj-$(CONFIG_PSTORE_RAM) += ramoops.o | 13 | obj-$(CONFIG_PSTORE_RAM) += ramoops.o |
diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c index 50416602774d..b32ce53d24ee 100644 --- a/fs/pstore/inode.c +++ b/fs/pstore/inode.c | |||
@@ -338,32 +338,38 @@ int pstore_mkfile(enum pstore_type_id type, char *psname, u64 id, int count, | |||
338 | 338 | ||
339 | switch (type) { | 339 | switch (type) { |
340 | case PSTORE_TYPE_DMESG: | 340 | case PSTORE_TYPE_DMESG: |
341 | sprintf(name, "dmesg-%s-%lld%s", psname, id, | 341 | scnprintf(name, sizeof(name), "dmesg-%s-%lld%s", |
342 | compressed ? ".enc.z" : ""); | 342 | psname, id, compressed ? ".enc.z" : ""); |
343 | break; | 343 | break; |
344 | case PSTORE_TYPE_CONSOLE: | 344 | case PSTORE_TYPE_CONSOLE: |
345 | sprintf(name, "console-%s-%lld", psname, id); | 345 | scnprintf(name, sizeof(name), "console-%s-%lld", psname, id); |
346 | break; | 346 | break; |
347 | case PSTORE_TYPE_FTRACE: | 347 | case PSTORE_TYPE_FTRACE: |
348 | sprintf(name, "ftrace-%s-%lld", psname, id); | 348 | scnprintf(name, sizeof(name), "ftrace-%s-%lld", psname, id); |
349 | break; | 349 | break; |
350 | case PSTORE_TYPE_MCE: | 350 | case PSTORE_TYPE_MCE: |
351 | sprintf(name, "mce-%s-%lld", psname, id); | 351 | scnprintf(name, sizeof(name), "mce-%s-%lld", psname, id); |
352 | break; | 352 | break; |
353 | case PSTORE_TYPE_PPC_RTAS: | 353 | case PSTORE_TYPE_PPC_RTAS: |
354 | sprintf(name, "rtas-%s-%lld", psname, id); | 354 | scnprintf(name, sizeof(name), "rtas-%s-%lld", psname, id); |
355 | break; | 355 | break; |
356 | case PSTORE_TYPE_PPC_OF: | 356 | case PSTORE_TYPE_PPC_OF: |
357 | sprintf(name, "powerpc-ofw-%s-%lld", psname, id); | 357 | scnprintf(name, sizeof(name), "powerpc-ofw-%s-%lld", |
358 | psname, id); | ||
358 | break; | 359 | break; |
359 | case PSTORE_TYPE_PPC_COMMON: | 360 | case PSTORE_TYPE_PPC_COMMON: |
360 | sprintf(name, "powerpc-common-%s-%lld", psname, id); | 361 | scnprintf(name, sizeof(name), "powerpc-common-%s-%lld", |
362 | psname, id); | ||
363 | break; | ||
364 | case PSTORE_TYPE_PMSG: | ||
365 | scnprintf(name, sizeof(name), "pmsg-%s-%lld", psname, id); | ||
361 | break; | 366 | break; |
362 | case PSTORE_TYPE_UNKNOWN: | 367 | case PSTORE_TYPE_UNKNOWN: |
363 | sprintf(name, "unknown-%s-%lld", psname, id); | 368 | scnprintf(name, sizeof(name), "unknown-%s-%lld", psname, id); |
364 | break; | 369 | break; |
365 | default: | 370 | default: |
366 | sprintf(name, "type%d-%s-%lld", type, psname, id); | 371 | scnprintf(name, sizeof(name), "type%d-%s-%lld", |
372 | type, psname, id); | ||
367 | break; | 373 | break; |
368 | } | 374 | } |
369 | 375 | ||
diff --git a/fs/pstore/internal.h b/fs/pstore/internal.h index 3b3d305277c4..c36ba2cd0b5d 100644 --- a/fs/pstore/internal.h +++ b/fs/pstore/internal.h | |||
@@ -45,6 +45,12 @@ extern void pstore_register_ftrace(void); | |||
45 | static inline void pstore_register_ftrace(void) {} | 45 | static inline void pstore_register_ftrace(void) {} |
46 | #endif | 46 | #endif |
47 | 47 | ||
48 | #ifdef CONFIG_PSTORE_PMSG | ||
49 | extern void pstore_register_pmsg(void); | ||
50 | #else | ||
51 | static inline void pstore_register_pmsg(void) {} | ||
52 | #endif | ||
53 | |||
48 | extern struct pstore_info *psinfo; | 54 | extern struct pstore_info *psinfo; |
49 | 55 | ||
50 | extern void pstore_set_kmsg_bytes(int); | 56 | extern void pstore_set_kmsg_bytes(int); |
diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index 0a9b72cdfeca..c4c9a10c5760 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c | |||
@@ -301,7 +301,7 @@ static void pstore_dump(struct kmsg_dumper *dumper, | |||
301 | 301 | ||
302 | if (big_oops_buf) { | 302 | if (big_oops_buf) { |
303 | dst = big_oops_buf; | 303 | dst = big_oops_buf; |
304 | hsize = sprintf(dst, "%s#%d Part%d\n", why, | 304 | hsize = sprintf(dst, "%s#%d Part%u\n", why, |
305 | oopscount, part); | 305 | oopscount, part); |
306 | size = big_oops_buf_sz - hsize; | 306 | size = big_oops_buf_sz - hsize; |
307 | 307 | ||
@@ -321,7 +321,7 @@ static void pstore_dump(struct kmsg_dumper *dumper, | |||
321 | } | 321 | } |
322 | } else { | 322 | } else { |
323 | dst = psinfo->buf; | 323 | dst = psinfo->buf; |
324 | hsize = sprintf(dst, "%s#%d Part%d\n", why, oopscount, | 324 | hsize = sprintf(dst, "%s#%d Part%u\n", why, oopscount, |
325 | part); | 325 | part); |
326 | size = psinfo->bufsize - hsize; | 326 | size = psinfo->bufsize - hsize; |
327 | dst += hsize; | 327 | dst += hsize; |
@@ -447,6 +447,7 @@ int pstore_register(struct pstore_info *psi) | |||
447 | if ((psi->flags & PSTORE_FLAGS_FRAGILE) == 0) { | 447 | if ((psi->flags & PSTORE_FLAGS_FRAGILE) == 0) { |
448 | pstore_register_console(); | 448 | pstore_register_console(); |
449 | pstore_register_ftrace(); | 449 | pstore_register_ftrace(); |
450 | pstore_register_pmsg(); | ||
450 | } | 451 | } |
451 | 452 | ||
452 | if (pstore_update_ms >= 0) { | 453 | if (pstore_update_ms >= 0) { |
diff --git a/fs/pstore/pmsg.c b/fs/pstore/pmsg.c new file mode 100644 index 000000000000..feb5dd2948b4 --- /dev/null +++ b/fs/pstore/pmsg.c | |||
@@ -0,0 +1,114 @@ | |||
1 | /* | ||
2 | * Copyright 2014 Google, Inc. | ||
3 | * | ||
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 | ||
6 | * may be copied, distributed, and modified under those terms. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | */ | ||
13 | |||
14 | #include <linux/cdev.h> | ||
15 | #include <linux/device.h> | ||
16 | #include <linux/fs.h> | ||
17 | #include <linux/uaccess.h> | ||
18 | #include <linux/vmalloc.h> | ||
19 | #include "internal.h" | ||
20 | |||
21 | static DEFINE_MUTEX(pmsg_lock); | ||
22 | #define PMSG_MAX_BOUNCE_BUFFER_SIZE (2*PAGE_SIZE) | ||
23 | |||
24 | static ssize_t write_pmsg(struct file *file, const char __user *buf, | ||
25 | size_t count, loff_t *ppos) | ||
26 | { | ||
27 | size_t i, buffer_size; | ||
28 | char *buffer; | ||
29 | |||
30 | if (!count) | ||
31 | return 0; | ||
32 | |||
33 | if (!access_ok(VERIFY_READ, buf, count)) | ||
34 | return -EFAULT; | ||
35 | |||
36 | buffer_size = count; | ||
37 | if (buffer_size > PMSG_MAX_BOUNCE_BUFFER_SIZE) | ||
38 | buffer_size = PMSG_MAX_BOUNCE_BUFFER_SIZE; | ||
39 | buffer = vmalloc(buffer_size); | ||
40 | |||
41 | mutex_lock(&pmsg_lock); | ||
42 | for (i = 0; i < count; ) { | ||
43 | size_t c = min(count - i, buffer_size); | ||
44 | u64 id; | ||
45 | long ret; | ||
46 | |||
47 | ret = __copy_from_user(buffer, buf + i, c); | ||
48 | if (unlikely(ret != 0)) { | ||
49 | mutex_unlock(&pmsg_lock); | ||
50 | vfree(buffer); | ||
51 | return -EFAULT; | ||
52 | } | ||
53 | psinfo->write_buf(PSTORE_TYPE_PMSG, 0, &id, 0, buffer, 0, c, | ||
54 | psinfo); | ||
55 | |||
56 | i += c; | ||
57 | } | ||
58 | |||
59 | mutex_unlock(&pmsg_lock); | ||
60 | vfree(buffer); | ||
61 | return count; | ||
62 | } | ||
63 | |||
64 | static const struct file_operations pmsg_fops = { | ||
65 | .owner = THIS_MODULE, | ||
66 | .llseek = noop_llseek, | ||
67 | .write = write_pmsg, | ||
68 | }; | ||
69 | |||
70 | static struct class *pmsg_class; | ||
71 | static int pmsg_major; | ||
72 | #define PMSG_NAME "pmsg" | ||
73 | #undef pr_fmt | ||
74 | #define pr_fmt(fmt) PMSG_NAME ": " fmt | ||
75 | |||
76 | static char *pmsg_devnode(struct device *dev, umode_t *mode) | ||
77 | { | ||
78 | if (mode) | ||
79 | *mode = 0220; | ||
80 | return NULL; | ||
81 | } | ||
82 | |||
83 | void pstore_register_pmsg(void) | ||
84 | { | ||
85 | struct device *pmsg_device; | ||
86 | |||
87 | pmsg_major = register_chrdev(0, PMSG_NAME, &pmsg_fops); | ||
88 | if (pmsg_major < 0) { | ||
89 | pr_err("register_chrdev failed\n"); | ||
90 | goto err; | ||
91 | } | ||
92 | |||
93 | pmsg_class = class_create(THIS_MODULE, PMSG_NAME); | ||
94 | if (IS_ERR(pmsg_class)) { | ||
95 | pr_err("device class file already in use\n"); | ||
96 | goto err_class; | ||
97 | } | ||
98 | pmsg_class->devnode = pmsg_devnode; | ||
99 | |||
100 | pmsg_device = device_create(pmsg_class, NULL, MKDEV(pmsg_major, 0), | ||
101 | NULL, "%s%d", PMSG_NAME, 0); | ||
102 | if (IS_ERR(pmsg_device)) { | ||
103 | pr_err("failed to create device\n"); | ||
104 | goto err_device; | ||
105 | } | ||
106 | return; | ||
107 | |||
108 | err_device: | ||
109 | class_destroy(pmsg_class); | ||
110 | err_class: | ||
111 | unregister_chrdev(pmsg_major, PMSG_NAME); | ||
112 | err: | ||
113 | return; | ||
114 | } | ||
diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c index 8613e5b35c22..39d1373128e9 100644 --- a/fs/pstore/ram.c +++ b/fs/pstore/ram.c | |||
@@ -51,6 +51,10 @@ static ulong ramoops_ftrace_size = MIN_MEM_SIZE; | |||
51 | module_param_named(ftrace_size, ramoops_ftrace_size, ulong, 0400); | 51 | module_param_named(ftrace_size, ramoops_ftrace_size, ulong, 0400); |
52 | MODULE_PARM_DESC(ftrace_size, "size of ftrace log"); | 52 | MODULE_PARM_DESC(ftrace_size, "size of ftrace log"); |
53 | 53 | ||
54 | static ulong ramoops_pmsg_size = MIN_MEM_SIZE; | ||
55 | module_param_named(pmsg_size, ramoops_pmsg_size, ulong, 0400); | ||
56 | MODULE_PARM_DESC(pmsg_size, "size of user space message log"); | ||
57 | |||
54 | static ulong mem_address; | 58 | static ulong mem_address; |
55 | module_param(mem_address, ulong, 0400); | 59 | module_param(mem_address, ulong, 0400); |
56 | MODULE_PARM_DESC(mem_address, | 60 | MODULE_PARM_DESC(mem_address, |
@@ -82,12 +86,14 @@ struct ramoops_context { | |||
82 | struct persistent_ram_zone **przs; | 86 | struct persistent_ram_zone **przs; |
83 | struct persistent_ram_zone *cprz; | 87 | struct persistent_ram_zone *cprz; |
84 | struct persistent_ram_zone *fprz; | 88 | struct persistent_ram_zone *fprz; |
89 | struct persistent_ram_zone *mprz; | ||
85 | phys_addr_t phys_addr; | 90 | phys_addr_t phys_addr; |
86 | unsigned long size; | 91 | unsigned long size; |
87 | unsigned int memtype; | 92 | unsigned int memtype; |
88 | size_t record_size; | 93 | size_t record_size; |
89 | size_t console_size; | 94 | size_t console_size; |
90 | size_t ftrace_size; | 95 | size_t ftrace_size; |
96 | size_t pmsg_size; | ||
91 | int dump_oops; | 97 | int dump_oops; |
92 | struct persistent_ram_ecc_info ecc_info; | 98 | struct persistent_ram_ecc_info ecc_info; |
93 | unsigned int max_dump_cnt; | 99 | unsigned int max_dump_cnt; |
@@ -96,6 +102,7 @@ struct ramoops_context { | |||
96 | unsigned int dump_read_cnt; | 102 | unsigned int dump_read_cnt; |
97 | unsigned int console_read_cnt; | 103 | unsigned int console_read_cnt; |
98 | unsigned int ftrace_read_cnt; | 104 | unsigned int ftrace_read_cnt; |
105 | unsigned int pmsg_read_cnt; | ||
99 | struct pstore_info pstore; | 106 | struct pstore_info pstore; |
100 | }; | 107 | }; |
101 | 108 | ||
@@ -109,6 +116,7 @@ static int ramoops_pstore_open(struct pstore_info *psi) | |||
109 | cxt->dump_read_cnt = 0; | 116 | cxt->dump_read_cnt = 0; |
110 | cxt->console_read_cnt = 0; | 117 | cxt->console_read_cnt = 0; |
111 | cxt->ftrace_read_cnt = 0; | 118 | cxt->ftrace_read_cnt = 0; |
119 | cxt->pmsg_read_cnt = 0; | ||
112 | return 0; | 120 | return 0; |
113 | } | 121 | } |
114 | 122 | ||
@@ -164,6 +172,12 @@ static int ramoops_read_kmsg_hdr(char *buffer, struct timespec *time, | |||
164 | return header_length; | 172 | return header_length; |
165 | } | 173 | } |
166 | 174 | ||
175 | static bool prz_ok(struct persistent_ram_zone *prz) | ||
176 | { | ||
177 | return !!prz && !!(persistent_ram_old_size(prz) + | ||
178 | persistent_ram_ecc_string(prz, NULL, 0)); | ||
179 | } | ||
180 | |||
167 | static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type, | 181 | static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type, |
168 | int *count, struct timespec *time, | 182 | int *count, struct timespec *time, |
169 | char **buf, bool *compressed, | 183 | char **buf, bool *compressed, |
@@ -178,13 +192,16 @@ static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type, | |||
178 | prz = ramoops_get_next_prz(cxt->przs, &cxt->dump_read_cnt, | 192 | prz = ramoops_get_next_prz(cxt->przs, &cxt->dump_read_cnt, |
179 | cxt->max_dump_cnt, id, type, | 193 | cxt->max_dump_cnt, id, type, |
180 | PSTORE_TYPE_DMESG, 1); | 194 | PSTORE_TYPE_DMESG, 1); |
181 | if (!prz) | 195 | if (!prz_ok(prz)) |
182 | prz = ramoops_get_next_prz(&cxt->cprz, &cxt->console_read_cnt, | 196 | prz = ramoops_get_next_prz(&cxt->cprz, &cxt->console_read_cnt, |
183 | 1, id, type, PSTORE_TYPE_CONSOLE, 0); | 197 | 1, id, type, PSTORE_TYPE_CONSOLE, 0); |
184 | if (!prz) | 198 | if (!prz_ok(prz)) |
185 | prz = ramoops_get_next_prz(&cxt->fprz, &cxt->ftrace_read_cnt, | 199 | prz = ramoops_get_next_prz(&cxt->fprz, &cxt->ftrace_read_cnt, |
186 | 1, id, type, PSTORE_TYPE_FTRACE, 0); | 200 | 1, id, type, PSTORE_TYPE_FTRACE, 0); |
187 | if (!prz) | 201 | if (!prz_ok(prz)) |
202 | prz = ramoops_get_next_prz(&cxt->mprz, &cxt->pmsg_read_cnt, | ||
203 | 1, id, type, PSTORE_TYPE_PMSG, 0); | ||
204 | if (!prz_ok(prz)) | ||
188 | return 0; | 205 | return 0; |
189 | 206 | ||
190 | if (!persistent_ram_old(prz)) | 207 | if (!persistent_ram_old(prz)) |
@@ -252,6 +269,11 @@ static int notrace ramoops_pstore_write_buf(enum pstore_type_id type, | |||
252 | return -ENOMEM; | 269 | return -ENOMEM; |
253 | persistent_ram_write(cxt->fprz, buf, size); | 270 | persistent_ram_write(cxt->fprz, buf, size); |
254 | return 0; | 271 | return 0; |
272 | } else if (type == PSTORE_TYPE_PMSG) { | ||
273 | if (!cxt->mprz) | ||
274 | return -ENOMEM; | ||
275 | persistent_ram_write(cxt->mprz, buf, size); | ||
276 | return 0; | ||
255 | } | 277 | } |
256 | 278 | ||
257 | if (type != PSTORE_TYPE_DMESG) | 279 | if (type != PSTORE_TYPE_DMESG) |
@@ -309,6 +331,9 @@ static int ramoops_pstore_erase(enum pstore_type_id type, u64 id, int count, | |||
309 | case PSTORE_TYPE_FTRACE: | 331 | case PSTORE_TYPE_FTRACE: |
310 | prz = cxt->fprz; | 332 | prz = cxt->fprz; |
311 | break; | 333 | break; |
334 | case PSTORE_TYPE_PMSG: | ||
335 | prz = cxt->mprz; | ||
336 | break; | ||
312 | default: | 337 | default: |
313 | return -EINVAL; | 338 | return -EINVAL; |
314 | } | 339 | } |
@@ -435,7 +460,7 @@ static int ramoops_probe(struct platform_device *pdev) | |||
435 | goto fail_out; | 460 | goto fail_out; |
436 | 461 | ||
437 | if (!pdata->mem_size || (!pdata->record_size && !pdata->console_size && | 462 | if (!pdata->mem_size || (!pdata->record_size && !pdata->console_size && |
438 | !pdata->ftrace_size)) { | 463 | !pdata->ftrace_size && !pdata->pmsg_size)) { |
439 | pr_err("The memory size and the record/console size must be " | 464 | pr_err("The memory size and the record/console size must be " |
440 | "non-zero\n"); | 465 | "non-zero\n"); |
441 | goto fail_out; | 466 | goto fail_out; |
@@ -447,6 +472,8 @@ static int ramoops_probe(struct platform_device *pdev) | |||
447 | pdata->console_size = rounddown_pow_of_two(pdata->console_size); | 472 | pdata->console_size = rounddown_pow_of_two(pdata->console_size); |
448 | if (pdata->ftrace_size && !is_power_of_2(pdata->ftrace_size)) | 473 | if (pdata->ftrace_size && !is_power_of_2(pdata->ftrace_size)) |
449 | pdata->ftrace_size = rounddown_pow_of_two(pdata->ftrace_size); | 474 | pdata->ftrace_size = rounddown_pow_of_two(pdata->ftrace_size); |
475 | if (pdata->pmsg_size && !is_power_of_2(pdata->pmsg_size)) | ||
476 | pdata->pmsg_size = rounddown_pow_of_two(pdata->pmsg_size); | ||
450 | 477 | ||
451 | cxt->size = pdata->mem_size; | 478 | cxt->size = pdata->mem_size; |
452 | cxt->phys_addr = pdata->mem_address; | 479 | cxt->phys_addr = pdata->mem_address; |
@@ -454,12 +481,14 @@ static int ramoops_probe(struct platform_device *pdev) | |||
454 | cxt->record_size = pdata->record_size; | 481 | cxt->record_size = pdata->record_size; |
455 | cxt->console_size = pdata->console_size; | 482 | cxt->console_size = pdata->console_size; |
456 | cxt->ftrace_size = pdata->ftrace_size; | 483 | cxt->ftrace_size = pdata->ftrace_size; |
484 | cxt->pmsg_size = pdata->pmsg_size; | ||
457 | cxt->dump_oops = pdata->dump_oops; | 485 | cxt->dump_oops = pdata->dump_oops; |
458 | cxt->ecc_info = pdata->ecc_info; | 486 | cxt->ecc_info = pdata->ecc_info; |
459 | 487 | ||
460 | paddr = cxt->phys_addr; | 488 | paddr = cxt->phys_addr; |
461 | 489 | ||
462 | dump_mem_sz = cxt->size - cxt->console_size - cxt->ftrace_size; | 490 | dump_mem_sz = cxt->size - cxt->console_size - cxt->ftrace_size |
491 | - cxt->pmsg_size; | ||
463 | err = ramoops_init_przs(dev, cxt, &paddr, dump_mem_sz); | 492 | err = ramoops_init_przs(dev, cxt, &paddr, dump_mem_sz); |
464 | if (err) | 493 | if (err) |
465 | goto fail_out; | 494 | goto fail_out; |
@@ -474,13 +503,9 @@ static int ramoops_probe(struct platform_device *pdev) | |||
474 | if (err) | 503 | if (err) |
475 | goto fail_init_fprz; | 504 | goto fail_init_fprz; |
476 | 505 | ||
477 | if (!cxt->przs && !cxt->cprz && !cxt->fprz) { | 506 | err = ramoops_init_prz(dev, cxt, &cxt->mprz, &paddr, cxt->pmsg_size, 0); |
478 | pr_err("memory size too small, minimum is %zu\n", | 507 | if (err) |
479 | cxt->console_size + cxt->record_size + | 508 | goto fail_init_mprz; |
480 | cxt->ftrace_size); | ||
481 | err = -EINVAL; | ||
482 | goto fail_cnt; | ||
483 | } | ||
484 | 509 | ||
485 | cxt->pstore.data = cxt; | 510 | cxt->pstore.data = cxt; |
486 | /* | 511 | /* |
@@ -525,7 +550,8 @@ fail_buf: | |||
525 | kfree(cxt->pstore.buf); | 550 | kfree(cxt->pstore.buf); |
526 | fail_clear: | 551 | fail_clear: |
527 | cxt->pstore.bufsize = 0; | 552 | cxt->pstore.bufsize = 0; |
528 | fail_cnt: | 553 | kfree(cxt->mprz); |
554 | fail_init_mprz: | ||
529 | kfree(cxt->fprz); | 555 | kfree(cxt->fprz); |
530 | fail_init_fprz: | 556 | fail_init_fprz: |
531 | kfree(cxt->cprz); | 557 | kfree(cxt->cprz); |
@@ -583,6 +609,7 @@ static void ramoops_register_dummy(void) | |||
583 | dummy_data->record_size = record_size; | 609 | dummy_data->record_size = record_size; |
584 | dummy_data->console_size = ramoops_console_size; | 610 | dummy_data->console_size = ramoops_console_size; |
585 | dummy_data->ftrace_size = ramoops_ftrace_size; | 611 | dummy_data->ftrace_size = ramoops_ftrace_size; |
612 | dummy_data->pmsg_size = ramoops_pmsg_size; | ||
586 | dummy_data->dump_oops = dump_oops; | 613 | dummy_data->dump_oops = dump_oops; |
587 | /* | 614 | /* |
588 | * For backwards compatibility ramoops.ecc=1 means 16 bytes ECC | 615 | * For backwards compatibility ramoops.ecc=1 means 16 bytes ECC |
diff --git a/include/linux/pstore.h b/include/linux/pstore.h index ece0c6bbfcc5..8884f6e507f7 100644 --- a/include/linux/pstore.h +++ b/include/linux/pstore.h | |||
@@ -39,6 +39,7 @@ enum pstore_type_id { | |||
39 | PSTORE_TYPE_PPC_RTAS = 4, | 39 | PSTORE_TYPE_PPC_RTAS = 4, |
40 | PSTORE_TYPE_PPC_OF = 5, | 40 | PSTORE_TYPE_PPC_OF = 5, |
41 | PSTORE_TYPE_PPC_COMMON = 6, | 41 | PSTORE_TYPE_PPC_COMMON = 6, |
42 | PSTORE_TYPE_PMSG = 7, | ||
42 | PSTORE_TYPE_UNKNOWN = 255 | 43 | PSTORE_TYPE_UNKNOWN = 255 |
43 | }; | 44 | }; |
44 | 45 | ||
diff --git a/include/linux/pstore_ram.h b/include/linux/pstore_ram.h index 4af3fdc85b01..9c9d6c154c8e 100644 --- a/include/linux/pstore_ram.h +++ b/include/linux/pstore_ram.h | |||
@@ -81,6 +81,7 @@ struct ramoops_platform_data { | |||
81 | unsigned long record_size; | 81 | unsigned long record_size; |
82 | unsigned long console_size; | 82 | unsigned long console_size; |
83 | unsigned long ftrace_size; | 83 | unsigned long ftrace_size; |
84 | unsigned long pmsg_size; | ||
84 | int dump_oops; | 85 | int dump_oops; |
85 | struct persistent_ram_ecc_info ecc_info; | 86 | struct persistent_ram_ecc_info ecc_info; |
86 | }; | 87 | }; |