diff options
Diffstat (limited to 'fs/pstore/ram.c')
| -rw-r--r-- | fs/pstore/ram.c | 112 |
1 files changed, 107 insertions, 5 deletions
diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c index 1376e5a8f0d..52274a0f813 100644 --- a/fs/pstore/ram.c +++ b/fs/pstore/ram.c @@ -34,6 +34,7 @@ #include <linux/slab.h> #include <linux/compiler.h> #include <linux/pstore_ram.h> +#include <linux/of.h> #define RAMOOPS_KERNMSG_HDR "====" #define MIN_MEM_SIZE 4096UL @@ -51,6 +52,10 @@ static ulong ramoops_ftrace_size = MIN_MEM_SIZE; module_param_named(ftrace_size, ramoops_ftrace_size, ulong, 0400); MODULE_PARM_DESC(ftrace_size, "size of ftrace log"); +static ulong ramoops_annotate_size = MIN_MEM_SIZE; +module_param_named(annotate_size, ramoops_annotate_size, ulong, 0400); +MODULE_PARM_DESC(annotate_size, "size of annotation"); + static ulong mem_address; module_param(mem_address, ulong, 0400); MODULE_PARM_DESC(mem_address, @@ -77,11 +82,13 @@ struct ramoops_context { struct persistent_ram_zone **przs; struct persistent_ram_zone *cprz; struct persistent_ram_zone *fprz; + struct persistent_ram_zone *aprz; phys_addr_t phys_addr; unsigned long size; size_t record_size; size_t console_size; size_t ftrace_size; + size_t annotate_size; int dump_oops; struct persistent_ram_ecc_info ecc_info; unsigned int max_dump_cnt; @@ -89,6 +96,7 @@ struct ramoops_context { unsigned int dump_read_cnt; unsigned int console_read_cnt; unsigned int ftrace_read_cnt; + unsigned int annotate_read_cnt; struct pstore_info pstore; }; @@ -101,6 +109,7 @@ static int ramoops_pstore_open(struct pstore_info *psi) cxt->dump_read_cnt = 0; cxt->console_read_cnt = 0; + cxt->annotate_read_cnt = 0; return 0; } @@ -150,6 +159,9 @@ static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type, prz = ramoops_get_next_prz(&cxt->fprz, &cxt->ftrace_read_cnt, 1, id, type, PSTORE_TYPE_FTRACE, 0); if (!prz) + prz = ramoops_get_next_prz(&cxt->aprz, &cxt->annotate_read_cnt, + 1, id, type, PSTORE_TYPE_ANNOTATE, 0); + if (!prz) return 0; /* TODO(kees): Bogus time for the moment. */ @@ -212,6 +224,11 @@ static int notrace ramoops_pstore_write_buf(enum pstore_type_id type, return -ENOMEM; persistent_ram_write(cxt->fprz, buf, size); return 0; + } else if (type == PSTORE_TYPE_ANNOTATE) { + if (!cxt->aprz) + return -ENOMEM; + persistent_ram_write(cxt->aprz, buf, size); + return 0; } if (type != PSTORE_TYPE_DMESG) @@ -269,6 +286,9 @@ static int ramoops_pstore_erase(enum pstore_type_id type, u64 id, int count, case PSTORE_TYPE_FTRACE: prz = cxt->fprz; break; + case PSTORE_TYPE_ANNOTATE: + prz = cxt->aprz; + break; default: return -EINVAL; } @@ -377,15 +397,79 @@ static int ramoops_init_prz(struct device *dev, struct ramoops_context *cxt, return 0; } +#ifdef CONFIG_OF +static struct of_device_id ramoops_of_match[] = { + { .compatible = "ramoops", }, + { }, +}; + +MODULE_DEVICE_TABLE(of, ramoops_of_match); +static void ramoops_of_init(struct platform_device *pdev) +{ + const struct device *dev = &pdev->dev; + struct ramoops_platform_data *pdata; + struct device_node *np = pdev->dev.of_node; + u32 start, size, console, annotate = 0; + int ret; + + pdata = dev_get_drvdata(dev); + if (!pdata) { + pr_err("private data is empty!\n"); + return; + } + ret = of_property_read_u32(np, "android,ramoops-buffer-start", + &start); + if (ret) + return; + + ret = of_property_read_u32(np, "android,ramoops-buffer-size", + &size); + if (ret) + return; + + ret = of_property_read_u32(np, "android,ramoops-console-size", + &console); + if (ret) + return; + + ret = of_property_read_u32(np, "android,ramoops-annotate-size", + &annotate); + if (ret) + pr_info("annotation buffer not configured"); + + pdata->mem_address = start; + pdata->mem_size = size; + pdata->console_size = console; + pdata->annotate_size = annotate; +} +#else +static inline void ramoops_of_init(struct platform_device *pdev) +{ + return; +} +#endif static int ramoops_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct ramoops_platform_data *pdata = pdev->dev.platform_data; + struct ramoops_platform_data *pdata; struct ramoops_context *cxt = &oops_cxt; size_t dump_mem_sz; phys_addr_t paddr; int err = -EINVAL; + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) { + pr_err("could not allocate ramoops_platform_data\n"); + return -ENOMEM; + } + + err = dev_set_drvdata(dev, pdata); + if (err) + goto fail_out; + + if (pdev->dev.of_node) + ramoops_of_init(pdev); + /* Only a single ramoops area allowed at a time, so fail extra * probes. */ @@ -393,7 +477,7 @@ static int ramoops_probe(struct platform_device *pdev) goto fail_out; if (!pdata->mem_size || (!pdata->record_size && !pdata->console_size && - !pdata->ftrace_size)) { + !pdata->ftrace_size && !pdata->annotate_size)) { pr_err("The memory size and the record/console size must be " "non-zero\n"); goto fail_out; @@ -407,6 +491,13 @@ static int ramoops_probe(struct platform_device *pdev) pdata->console_size = rounddown_pow_of_two(pdata->console_size); if (!is_power_of_2(pdata->ftrace_size)) pdata->ftrace_size = rounddown_pow_of_two(pdata->ftrace_size); + if (!is_power_of_2(pdata->annotate_size)) + pdata->annotate_size = + rounddown_pow_of_two(pdata->annotate_size); + + pr_debug("All %#lx record %#lx console %#lx ftrace %#lx annotate %#lx\n", + pdata->mem_size, pdata->record_size, pdata->console_size, + pdata->ftrace_size, pdata->annotate_size); cxt->dump_read_cnt = 0; cxt->size = pdata->mem_size; @@ -414,12 +505,14 @@ static int ramoops_probe(struct platform_device *pdev) cxt->record_size = pdata->record_size; cxt->console_size = pdata->console_size; cxt->ftrace_size = pdata->ftrace_size; + cxt->annotate_size = pdata->annotate_size; cxt->dump_oops = pdata->dump_oops; cxt->ecc_info = pdata->ecc_info; paddr = cxt->phys_addr; - dump_mem_sz = cxt->size - cxt->console_size - cxt->ftrace_size; + dump_mem_sz = cxt->size - cxt->console_size - cxt->ftrace_size + - cxt->annotate_size; err = ramoops_init_przs(dev, cxt, &paddr, dump_mem_sz); if (err) goto fail_out; @@ -434,10 +527,15 @@ static int ramoops_probe(struct platform_device *pdev) if (err) goto fail_init_fprz; - if (!cxt->przs && !cxt->cprz && !cxt->fprz) { + err = ramoops_init_prz(dev, cxt, &cxt->aprz, &paddr, + cxt->annotate_size, 0); + if (err) + goto fail_init_aprz; + + if (!cxt->przs && !cxt->cprz && !cxt->fprz && !cxt->aprz) { pr_err("memory size too small, minimum is %zu\n", cxt->console_size + cxt->record_size + - cxt->ftrace_size); + cxt->ftrace_size + cxt->annotate_size); err = -EINVAL; goto fail_cnt; } @@ -487,6 +585,8 @@ fail_clear: cxt->pstore.bufsize = 0; cxt->max_dump_cnt = 0; fail_cnt: + kfree(cxt->aprz); +fail_init_aprz: kfree(cxt->fprz); fail_init_fprz: kfree(cxt->cprz); @@ -522,6 +622,7 @@ static struct platform_driver ramoops_driver = { .remove = __exit_p(ramoops_remove), .driver = { .name = "ramoops", + .of_match_table = of_match_ptr(ramoops_of_match), .owner = THIS_MODULE, }, }; @@ -544,6 +645,7 @@ static void ramoops_register_dummy(void) dummy_data->record_size = record_size; dummy_data->console_size = ramoops_console_size; dummy_data->ftrace_size = ramoops_ftrace_size; + dummy_data->annotate_size = ramoops_annotate_size; dummy_data->dump_oops = dump_oops; /* * For backwards compatibility ramoops.ecc=1 means 16 bytes ECC |