summaryrefslogtreecommitdiff
path: root/fs/pstore/ram.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/pstore/ram.c')
-rw-r--r--fs/pstore/ram.c112
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