aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTony Lindgren <tony@atomide.com>2014-09-16 16:50:01 -0400
committerTony Luck <tony.luck@intel.com>2014-12-11 16:38:31 -0500
commit027bc8b08242c59e19356b4b2c189f2d849ab660 (patch)
tree4bd5ad81fef12692af2c9d278f14903d15ddfb60
parent7ae9cb81933515dc7db1aa3c47ef7653717e3090 (diff)
pstore-ram: Allow optional mapping with pgprot_noncached
On some ARMs the memory can be mapped pgprot_noncached() and still be working for atomic operations. As pointed out by Colin Cross <ccross@android.com>, in some cases you do want to use pgprot_noncached() if the SoC supports it to see a debug printk just before a write hanging the system. On ARMs, the atomic operations on strongly ordered memory are implementation defined. So let's provide an optional kernel parameter for configuring pgprot_noncached(), and use pgprot_writecombine() by default. Cc: Arnd Bergmann <arnd@arndb.de> Cc: Rob Herring <robherring2@gmail.com> Cc: Randy Dunlap <rdunlap@infradead.org> Cc: Anton Vorontsov <anton@enomsg.org> Cc: Colin Cross <ccross@android.com> Cc: Olof Johansson <olof@lixom.net> Cc: Russell King <linux@arm.linux.org.uk> Cc: stable@vger.kernel.org Acked-by: Kees Cook <keescook@chromium.org> Signed-off-by: Tony Lindgren <tony@atomide.com> Signed-off-by: Tony Luck <tony.luck@intel.com>
-rw-r--r--Documentation/ramoops.txt13
-rw-r--r--fs/pstore/ram.c13
-rw-r--r--fs/pstore/ram_core.c31
-rw-r--r--include/linux/pstore_ram.h4
4 files changed, 47 insertions, 14 deletions
diff --git a/Documentation/ramoops.txt b/Documentation/ramoops.txt
index 69b3cac4749d..5d8675615e59 100644
--- a/Documentation/ramoops.txt
+++ b/Documentation/ramoops.txt
@@ -14,11 +14,19 @@ survive after a restart.
14 14
151. Ramoops concepts 151. Ramoops concepts
16 16
17Ramoops uses a predefined memory area to store the dump. The start and size of 17Ramoops uses a predefined memory area to store the dump. The start and size
18the memory area are set using two variables: 18and type of the memory area are set using three variables:
19 * "mem_address" for the start 19 * "mem_address" for the start
20 * "mem_size" for the size. The memory size will be rounded down to a 20 * "mem_size" for the size. The memory size will be rounded down to a
21 power of two. 21 power of two.
22 * "mem_type" to specifiy if the memory type (default is pgprot_writecombine).
23
24Typically the default value of mem_type=0 should be used as that sets the pstore
25mapping to pgprot_writecombine. Setting mem_type=1 attempts to use
26pgprot_noncached, which only works on some platforms. This is because pstore
27depends on atomic operations. At least on ARM, pgprot_noncached causes the
28memory to be mapped strongly ordered, and atomic operations on strongly ordered
29memory are implementation defined, and won't work on many ARMs such as omaps.
22 30
23The memory area is divided into "record_size" chunks (also rounded down to 31The memory area is divided into "record_size" chunks (also rounded down to
24power of two) and each oops/panic writes a "record_size" chunk of 32power of two) and each oops/panic writes a "record_size" chunk of
@@ -55,6 +63,7 @@ Setting the ramoops parameters can be done in 2 different manners:
55static struct ramoops_platform_data ramoops_data = { 63static struct ramoops_platform_data ramoops_data = {
56 .mem_size = <...>, 64 .mem_size = <...>,
57 .mem_address = <...>, 65 .mem_address = <...>,
66 .mem_type = <...>,
58 .record_size = <...>, 67 .record_size = <...>,
59 .dump_oops = <...>, 68 .dump_oops = <...>,
60 .ecc = <...>, 69 .ecc = <...>,
diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c
index ec881b312700..2f389ce5023c 100644
--- a/fs/pstore/ram.c
+++ b/fs/pstore/ram.c
@@ -61,6 +61,11 @@ module_param(mem_size, ulong, 0400);
61MODULE_PARM_DESC(mem_size, 61MODULE_PARM_DESC(mem_size,
62 "size of reserved RAM used to store oops/panic logs"); 62 "size of reserved RAM used to store oops/panic logs");
63 63
64static unsigned int mem_type;
65module_param(mem_type, uint, 0600);
66MODULE_PARM_DESC(mem_type,
67 "set to 1 to try to use unbuffered memory (default 0)");
68
64static int dump_oops = 1; 69static int dump_oops = 1;
65module_param(dump_oops, int, 0600); 70module_param(dump_oops, int, 0600);
66MODULE_PARM_DESC(dump_oops, 71MODULE_PARM_DESC(dump_oops,
@@ -79,6 +84,7 @@ struct ramoops_context {
79 struct persistent_ram_zone *fprz; 84 struct persistent_ram_zone *fprz;
80 phys_addr_t phys_addr; 85 phys_addr_t phys_addr;
81 unsigned long size; 86 unsigned long size;
87 unsigned int memtype;
82 size_t record_size; 88 size_t record_size;
83 size_t console_size; 89 size_t console_size;
84 size_t ftrace_size; 90 size_t ftrace_size;
@@ -366,7 +372,8 @@ static int ramoops_init_przs(struct device *dev, struct ramoops_context *cxt,
366 size_t sz = cxt->record_size; 372 size_t sz = cxt->record_size;
367 373
368 cxt->przs[i] = persistent_ram_new(*paddr, sz, 0, 374 cxt->przs[i] = persistent_ram_new(*paddr, sz, 0,
369 &cxt->ecc_info); 375 &cxt->ecc_info,
376 cxt->memtype);
370 if (IS_ERR(cxt->przs[i])) { 377 if (IS_ERR(cxt->przs[i])) {
371 err = PTR_ERR(cxt->przs[i]); 378 err = PTR_ERR(cxt->przs[i]);
372 dev_err(dev, "failed to request mem region (0x%zx@0x%llx): %d\n", 379 dev_err(dev, "failed to request mem region (0x%zx@0x%llx): %d\n",
@@ -396,7 +403,7 @@ static int ramoops_init_prz(struct device *dev, struct ramoops_context *cxt,
396 return -ENOMEM; 403 return -ENOMEM;
397 } 404 }
398 405
399 *prz = persistent_ram_new(*paddr, sz, sig, &cxt->ecc_info); 406 *prz = persistent_ram_new(*paddr, sz, sig, &cxt->ecc_info, cxt->memtype);
400 if (IS_ERR(*prz)) { 407 if (IS_ERR(*prz)) {
401 int err = PTR_ERR(*prz); 408 int err = PTR_ERR(*prz);
402 409
@@ -443,6 +450,7 @@ static int ramoops_probe(struct platform_device *pdev)
443 450
444 cxt->size = pdata->mem_size; 451 cxt->size = pdata->mem_size;
445 cxt->phys_addr = pdata->mem_address; 452 cxt->phys_addr = pdata->mem_address;
453 cxt->memtype = pdata->mem_type;
446 cxt->record_size = pdata->record_size; 454 cxt->record_size = pdata->record_size;
447 cxt->console_size = pdata->console_size; 455 cxt->console_size = pdata->console_size;
448 cxt->ftrace_size = pdata->ftrace_size; 456 cxt->ftrace_size = pdata->ftrace_size;
@@ -572,6 +580,7 @@ static void ramoops_register_dummy(void)
572 580
573 dummy_data->mem_size = mem_size; 581 dummy_data->mem_size = mem_size;
574 dummy_data->mem_address = mem_address; 582 dummy_data->mem_address = mem_address;
583 dummy_data->mem_type = 0;
575 dummy_data->record_size = record_size; 584 dummy_data->record_size = record_size;
576 dummy_data->console_size = ramoops_console_size; 585 dummy_data->console_size = ramoops_console_size;
577 dummy_data->ftrace_size = ramoops_ftrace_size; 586 dummy_data->ftrace_size = ramoops_ftrace_size;
diff --git a/fs/pstore/ram_core.c b/fs/pstore/ram_core.c
index 24f94b0f2270..76c3f80efdfa 100644
--- a/fs/pstore/ram_core.c
+++ b/fs/pstore/ram_core.c
@@ -380,7 +380,8 @@ void persistent_ram_zap(struct persistent_ram_zone *prz)
380 persistent_ram_update_header_ecc(prz); 380 persistent_ram_update_header_ecc(prz);
381} 381}
382 382
383static void *persistent_ram_vmap(phys_addr_t start, size_t size) 383static void *persistent_ram_vmap(phys_addr_t start, size_t size,
384 unsigned int memtype)
384{ 385{
385 struct page **pages; 386 struct page **pages;
386 phys_addr_t page_start; 387 phys_addr_t page_start;
@@ -392,7 +393,10 @@ static void *persistent_ram_vmap(phys_addr_t start, size_t size)
392 page_start = start - offset_in_page(start); 393 page_start = start - offset_in_page(start);
393 page_count = DIV_ROUND_UP(size + offset_in_page(start), PAGE_SIZE); 394 page_count = DIV_ROUND_UP(size + offset_in_page(start), PAGE_SIZE);
394 395
395 prot = pgprot_writecombine(PAGE_KERNEL); 396 if (memtype)
397 prot = pgprot_noncached(PAGE_KERNEL);
398 else
399 prot = pgprot_writecombine(PAGE_KERNEL);
396 400
397 pages = kmalloc_array(page_count, sizeof(struct page *), GFP_KERNEL); 401 pages = kmalloc_array(page_count, sizeof(struct page *), GFP_KERNEL);
398 if (!pages) { 402 if (!pages) {
@@ -411,8 +415,11 @@ static void *persistent_ram_vmap(phys_addr_t start, size_t size)
411 return vaddr; 415 return vaddr;
412} 416}
413 417
414static void *persistent_ram_iomap(phys_addr_t start, size_t size) 418static void *persistent_ram_iomap(phys_addr_t start, size_t size,
419 unsigned int memtype)
415{ 420{
421 void *va;
422
416 if (!request_mem_region(start, size, "persistent_ram")) { 423 if (!request_mem_region(start, size, "persistent_ram")) {
417 pr_err("request mem region (0x%llx@0x%llx) failed\n", 424 pr_err("request mem region (0x%llx@0x%llx) failed\n",
418 (unsigned long long)size, (unsigned long long)start); 425 (unsigned long long)size, (unsigned long long)start);
@@ -422,19 +429,24 @@ static void *persistent_ram_iomap(phys_addr_t start, size_t size)
422 buffer_start_add = buffer_start_add_locked; 429 buffer_start_add = buffer_start_add_locked;
423 buffer_size_add = buffer_size_add_locked; 430 buffer_size_add = buffer_size_add_locked;
424 431
425 return ioremap_wc(start, size); 432 if (memtype)
433 va = ioremap(start, size);
434 else
435 va = ioremap_wc(start, size);
436
437 return va;
426} 438}
427 439
428static int persistent_ram_buffer_map(phys_addr_t start, phys_addr_t size, 440static int persistent_ram_buffer_map(phys_addr_t start, phys_addr_t size,
429 struct persistent_ram_zone *prz) 441 struct persistent_ram_zone *prz, int memtype)
430{ 442{
431 prz->paddr = start; 443 prz->paddr = start;
432 prz->size = size; 444 prz->size = size;
433 445
434 if (pfn_valid(start >> PAGE_SHIFT)) 446 if (pfn_valid(start >> PAGE_SHIFT))
435 prz->vaddr = persistent_ram_vmap(start, size); 447 prz->vaddr = persistent_ram_vmap(start, size, memtype);
436 else 448 else
437 prz->vaddr = persistent_ram_iomap(start, size); 449 prz->vaddr = persistent_ram_iomap(start, size, memtype);
438 450
439 if (!prz->vaddr) { 451 if (!prz->vaddr) {
440 pr_err("%s: Failed to map 0x%llx pages at 0x%llx\n", __func__, 452 pr_err("%s: Failed to map 0x%llx pages at 0x%llx\n", __func__,
@@ -500,7 +512,8 @@ void persistent_ram_free(struct persistent_ram_zone *prz)
500} 512}
501 513
502struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size, 514struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size,
503 u32 sig, struct persistent_ram_ecc_info *ecc_info) 515 u32 sig, struct persistent_ram_ecc_info *ecc_info,
516 unsigned int memtype)
504{ 517{
505 struct persistent_ram_zone *prz; 518 struct persistent_ram_zone *prz;
506 int ret = -ENOMEM; 519 int ret = -ENOMEM;
@@ -511,7 +524,7 @@ struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size,
511 goto err; 524 goto err;
512 } 525 }
513 526
514 ret = persistent_ram_buffer_map(start, size, prz); 527 ret = persistent_ram_buffer_map(start, size, prz, memtype);
515 if (ret) 528 if (ret)
516 goto err; 529 goto err;
517 530
diff --git a/include/linux/pstore_ram.h b/include/linux/pstore_ram.h
index 9974975d40db..4af3fdc85b01 100644
--- a/include/linux/pstore_ram.h
+++ b/include/linux/pstore_ram.h
@@ -53,7 +53,8 @@ struct persistent_ram_zone {
53}; 53};
54 54
55struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size, 55struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size,
56 u32 sig, struct persistent_ram_ecc_info *ecc_info); 56 u32 sig, struct persistent_ram_ecc_info *ecc_info,
57 unsigned int memtype);
57void persistent_ram_free(struct persistent_ram_zone *prz); 58void persistent_ram_free(struct persistent_ram_zone *prz);
58void persistent_ram_zap(struct persistent_ram_zone *prz); 59void persistent_ram_zap(struct persistent_ram_zone *prz);
59 60
@@ -76,6 +77,7 @@ ssize_t persistent_ram_ecc_string(struct persistent_ram_zone *prz,
76struct ramoops_platform_data { 77struct ramoops_platform_data {
77 unsigned long mem_size; 78 unsigned long mem_size;
78 unsigned long mem_address; 79 unsigned long mem_address;
80 unsigned int mem_type;
79 unsigned long record_size; 81 unsigned long record_size;
80 unsigned long console_size; 82 unsigned long console_size;
81 unsigned long ftrace_size; 83 unsigned long ftrace_size;