diff options
-rw-r--r-- | Documentation/ramoops.txt | 6 | ||||
-rw-r--r-- | fs/pstore/ram.c | 15 | ||||
-rw-r--r-- | include/linux/pstore_ram.h | 1 |
3 files changed, 19 insertions, 3 deletions
diff --git a/Documentation/ramoops.txt b/Documentation/ramoops.txt index 470d2c4db6ff..4ba7db231cb2 100644 --- a/Documentation/ramoops.txt +++ b/Documentation/ramoops.txt | |||
@@ -30,6 +30,11 @@ variable while setting 0 in that variable dumps only the panics. | |||
30 | The module uses a counter to record multiple dumps but the counter gets reset | 30 | The module uses a counter to record multiple dumps but the counter gets reset |
31 | on restart (i.e. new dumps after the restart will overwrite old ones). | 31 | on restart (i.e. new dumps after the restart will overwrite old ones). |
32 | 32 | ||
33 | Ramoops also supports software ECC protection of persistent memory regions. | ||
34 | This might be useful when a hardware reset was used to bring the machine back | ||
35 | to life (i.e. a watchdog triggered). In such cases, RAM may be somewhat | ||
36 | corrupt, but usually it is restorable. | ||
37 | |||
33 | 2. Setting the parameters | 38 | 2. Setting the parameters |
34 | 39 | ||
35 | Setting the ramoops parameters can be done in 2 different manners: | 40 | Setting the ramoops parameters can be done in 2 different manners: |
@@ -46,6 +51,7 @@ static struct ramoops_platform_data ramoops_data = { | |||
46 | .mem_address = <...>, | 51 | .mem_address = <...>, |
47 | .record_size = <...>, | 52 | .record_size = <...>, |
48 | .dump_oops = <...>, | 53 | .dump_oops = <...>, |
54 | .ecc = <...>, | ||
49 | }; | 55 | }; |
50 | 56 | ||
51 | static struct platform_device ramoops_dev = { | 57 | static struct platform_device ramoops_dev = { |
diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c index 62b13eda4691..9123cce28c1e 100644 --- a/fs/pstore/ram.c +++ b/fs/pstore/ram.c | |||
@@ -56,12 +56,18 @@ module_param(dump_oops, int, 0600); | |||
56 | MODULE_PARM_DESC(dump_oops, | 56 | MODULE_PARM_DESC(dump_oops, |
57 | "set to 1 to dump oopses, 0 to only dump panics (default 1)"); | 57 | "set to 1 to dump oopses, 0 to only dump panics (default 1)"); |
58 | 58 | ||
59 | static int ramoops_ecc; | ||
60 | module_param_named(ecc, ramoops_ecc, int, 0600); | ||
61 | MODULE_PARM_DESC(ramoops_ecc, | ||
62 | "set to 1 to enable ECC support"); | ||
63 | |||
59 | struct ramoops_context { | 64 | struct ramoops_context { |
60 | struct persistent_ram_zone **przs; | 65 | struct persistent_ram_zone **przs; |
61 | phys_addr_t phys_addr; | 66 | phys_addr_t phys_addr; |
62 | unsigned long size; | 67 | unsigned long size; |
63 | size_t record_size; | 68 | size_t record_size; |
64 | int dump_oops; | 69 | int dump_oops; |
70 | bool ecc; | ||
65 | unsigned int count; | 71 | unsigned int count; |
66 | unsigned int max_count; | 72 | unsigned int max_count; |
67 | unsigned int read_count; | 73 | unsigned int read_count; |
@@ -236,6 +242,7 @@ static int __init ramoops_probe(struct platform_device *pdev) | |||
236 | cxt->phys_addr = pdata->mem_address; | 242 | cxt->phys_addr = pdata->mem_address; |
237 | cxt->record_size = pdata->record_size; | 243 | cxt->record_size = pdata->record_size; |
238 | cxt->dump_oops = pdata->dump_oops; | 244 | cxt->dump_oops = pdata->dump_oops; |
245 | cxt->ecc = pdata->ecc; | ||
239 | 246 | ||
240 | cxt->przs = kzalloc(sizeof(*cxt->przs) * cxt->max_count, GFP_KERNEL); | 247 | cxt->przs = kzalloc(sizeof(*cxt->przs) * cxt->max_count, GFP_KERNEL); |
241 | if (!cxt->przs) { | 248 | if (!cxt->przs) { |
@@ -248,7 +255,7 @@ static int __init ramoops_probe(struct platform_device *pdev) | |||
248 | size_t sz = cxt->record_size; | 255 | size_t sz = cxt->record_size; |
249 | phys_addr_t start = cxt->phys_addr + sz * i; | 256 | phys_addr_t start = cxt->phys_addr + sz * i; |
250 | 257 | ||
251 | cxt->przs[i] = persistent_ram_new(start, sz, 0); | 258 | cxt->przs[i] = persistent_ram_new(start, sz, cxt->ecc); |
252 | if (IS_ERR(cxt->przs[i])) { | 259 | if (IS_ERR(cxt->przs[i])) { |
253 | err = PTR_ERR(cxt->przs[i]); | 260 | err = PTR_ERR(cxt->przs[i]); |
254 | dev_err(dev, "failed to request mem region (0x%zx@0x%llx): %d\n", | 261 | dev_err(dev, "failed to request mem region (0x%zx@0x%llx): %d\n", |
@@ -281,9 +288,10 @@ static int __init ramoops_probe(struct platform_device *pdev) | |||
281 | record_size = pdata->record_size; | 288 | record_size = pdata->record_size; |
282 | dump_oops = pdata->dump_oops; | 289 | dump_oops = pdata->dump_oops; |
283 | 290 | ||
284 | pr_info("attached 0x%lx@0x%llx (%ux0x%zx)\n", | 291 | pr_info("attached 0x%lx@0x%llx (%ux0x%zx), ecc: %s\n", |
285 | cxt->size, (unsigned long long)cxt->phys_addr, | 292 | cxt->size, (unsigned long long)cxt->phys_addr, |
286 | cxt->max_count, cxt->record_size); | 293 | cxt->max_count, cxt->record_size, |
294 | ramoops_ecc ? "on" : "off"); | ||
287 | 295 | ||
288 | return 0; | 296 | return 0; |
289 | 297 | ||
@@ -347,6 +355,7 @@ static int __init ramoops_init(void) | |||
347 | dummy_data->mem_address = mem_address; | 355 | dummy_data->mem_address = mem_address; |
348 | dummy_data->record_size = record_size; | 356 | dummy_data->record_size = record_size; |
349 | dummy_data->dump_oops = dump_oops; | 357 | dummy_data->dump_oops = dump_oops; |
358 | dummy_data->ecc = ramoops_ecc; | ||
350 | dummy = platform_create_bundle(&ramoops_driver, ramoops_probe, | 359 | dummy = platform_create_bundle(&ramoops_driver, ramoops_probe, |
351 | NULL, 0, dummy_data, | 360 | NULL, 0, dummy_data, |
352 | sizeof(struct ramoops_platform_data)); | 361 | sizeof(struct ramoops_platform_data)); |
diff --git a/include/linux/pstore_ram.h b/include/linux/pstore_ram.h index ffe24a52c5af..7ed7fd4dba49 100644 --- a/include/linux/pstore_ram.h +++ b/include/linux/pstore_ram.h | |||
@@ -92,6 +92,7 @@ struct ramoops_platform_data { | |||
92 | unsigned long mem_address; | 92 | unsigned long mem_address; |
93 | unsigned long record_size; | 93 | unsigned long record_size; |
94 | int dump_oops; | 94 | int dump_oops; |
95 | bool ecc; | ||
95 | }; | 96 | }; |
96 | 97 | ||
97 | #endif | 98 | #endif |