Couple of pstore-ram enhancements to allow use of different memory attributes
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJUi0B6AAoJEKurIx+X31iByH8P/jfMgzyUO+KpJMA1DbgCAG7x WPJgbMUyPwB63DH09RyMEmiwf61Rl1klXTPVNY0Dnj7qRJOmpB9U3vGIfO4HpD84 5IZMBlc+Jl+kJCxSAJYbTJTZLsIMjFGOfuVTvlY+HnMBitQVBumKptmC0DoBBqgz yYy5MHRMaVoHcogyMyBiknmxdxu6/ruUKY+6yyvdUESt0SCcJG8V6Qik7TMmnx47 NvIIPzfibvvLLnd8IOEj2fwh8XMtJdfcCxPpAEvEaNq0jZEDF9K22jttTQvl9r92 NQf7JKQQrNfzloRZ3flKax5ZMGi9RkcirTLLdJ4I2xMGVHOA4XUAjsSCYR6INuuJ Ox00FnuiIrADNw37m52Y+ujPTF1C2PQUNK69gwsLd84MSjy+95F2dlC5cC3Yt4N5 rpstXxWELZTqjMGD8GTPOpv6zlg799IbFexr4H6KTc+47EX0MNayJiI6L597gYnq gIiPmDnnz6WlWp4HHgBIwjNAH3Tbf/uU3MlgzqS3Ftd7YkYmLnxvClhrwgErviFn Nfnz2LtGuMxMHSt0uSWxODVEaR4reKRVJBvhRSGWL1PufylEyt0YWayiqpohuKD9 6X/RufWK5qdCBHytoGyMUZ57oqxth9QSVG4RBkGPmaZgMq/5DdyOhBfW0yInjMuo AuDMmqrU5yFTitLMGcsG =kcmD -----END PGP SIGNATURE----- Merge tag 'please-pull-morepstore' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux Pull pstore update #2 from Tony Luck: "Couple of pstore-ram enhancements to allow use of different memory attributes" * tag 'please-pull-morepstore' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux: pstore-ram: Allow optional mapping with pgprot_noncached pstore-ram: Fix hangs by using write-combine mappings
This commit is contained in:
commit
6ce4436c9c
|
@ -14,11 +14,19 @@ survive after a restart.
|
||||||
|
|
||||||
1. Ramoops concepts
|
1. Ramoops concepts
|
||||||
|
|
||||||
Ramoops uses a predefined memory area to store the dump. The start and size of
|
Ramoops uses a predefined memory area to store the dump. The start and size
|
||||||
the memory area are set using two variables:
|
and type of the memory area are set using three variables:
|
||||||
* "mem_address" for the start
|
* "mem_address" for the start
|
||||||
* "mem_size" for the size. The memory size will be rounded down to a
|
* "mem_size" for the size. The memory size will be rounded down to a
|
||||||
power of two.
|
power of two.
|
||||||
|
* "mem_type" to specifiy if the memory type (default is pgprot_writecombine).
|
||||||
|
|
||||||
|
Typically the default value of mem_type=0 should be used as that sets the pstore
|
||||||
|
mapping to pgprot_writecombine. Setting mem_type=1 attempts to use
|
||||||
|
pgprot_noncached, which only works on some platforms. This is because pstore
|
||||||
|
depends on atomic operations. At least on ARM, pgprot_noncached causes the
|
||||||
|
memory to be mapped strongly ordered, and atomic operations on strongly ordered
|
||||||
|
memory are implementation defined, and won't work on many ARMs such as omaps.
|
||||||
|
|
||||||
The memory area is divided into "record_size" chunks (also rounded down to
|
The memory area is divided into "record_size" chunks (also rounded down to
|
||||||
power of two) and each oops/panic writes a "record_size" chunk of
|
power 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:
|
||||||
static struct ramoops_platform_data ramoops_data = {
|
static struct ramoops_platform_data ramoops_data = {
|
||||||
.mem_size = <...>,
|
.mem_size = <...>,
|
||||||
.mem_address = <...>,
|
.mem_address = <...>,
|
||||||
|
.mem_type = <...>,
|
||||||
.record_size = <...>,
|
.record_size = <...>,
|
||||||
.dump_oops = <...>,
|
.dump_oops = <...>,
|
||||||
.ecc = <...>,
|
.ecc = <...>,
|
||||||
|
|
|
@ -61,6 +61,11 @@ module_param(mem_size, ulong, 0400);
|
||||||
MODULE_PARM_DESC(mem_size,
|
MODULE_PARM_DESC(mem_size,
|
||||||
"size of reserved RAM used to store oops/panic logs");
|
"size of reserved RAM used to store oops/panic logs");
|
||||||
|
|
||||||
|
static unsigned int mem_type;
|
||||||
|
module_param(mem_type, uint, 0600);
|
||||||
|
MODULE_PARM_DESC(mem_type,
|
||||||
|
"set to 1 to try to use unbuffered memory (default 0)");
|
||||||
|
|
||||||
static int dump_oops = 1;
|
static int dump_oops = 1;
|
||||||
module_param(dump_oops, int, 0600);
|
module_param(dump_oops, int, 0600);
|
||||||
MODULE_PARM_DESC(dump_oops,
|
MODULE_PARM_DESC(dump_oops,
|
||||||
|
@ -79,6 +84,7 @@ struct ramoops_context {
|
||||||
struct persistent_ram_zone *fprz;
|
struct persistent_ram_zone *fprz;
|
||||||
phys_addr_t phys_addr;
|
phys_addr_t phys_addr;
|
||||||
unsigned long size;
|
unsigned long size;
|
||||||
|
unsigned int memtype;
|
||||||
size_t record_size;
|
size_t record_size;
|
||||||
size_t console_size;
|
size_t console_size;
|
||||||
size_t ftrace_size;
|
size_t ftrace_size;
|
||||||
|
@ -366,7 +372,8 @@ static int ramoops_init_przs(struct device *dev, struct ramoops_context *cxt,
|
||||||
size_t sz = cxt->record_size;
|
size_t sz = cxt->record_size;
|
||||||
|
|
||||||
cxt->przs[i] = persistent_ram_new(*paddr, sz, 0,
|
cxt->przs[i] = persistent_ram_new(*paddr, sz, 0,
|
||||||
&cxt->ecc_info);
|
&cxt->ecc_info,
|
||||||
|
cxt->memtype);
|
||||||
if (IS_ERR(cxt->przs[i])) {
|
if (IS_ERR(cxt->przs[i])) {
|
||||||
err = PTR_ERR(cxt->przs[i]);
|
err = PTR_ERR(cxt->przs[i]);
|
||||||
dev_err(dev, "failed to request mem region (0x%zx@0x%llx): %d\n",
|
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,
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
*prz = persistent_ram_new(*paddr, sz, sig, &cxt->ecc_info);
|
*prz = persistent_ram_new(*paddr, sz, sig, &cxt->ecc_info, cxt->memtype);
|
||||||
if (IS_ERR(*prz)) {
|
if (IS_ERR(*prz)) {
|
||||||
int err = PTR_ERR(*prz);
|
int err = PTR_ERR(*prz);
|
||||||
|
|
||||||
|
@ -443,6 +450,7 @@ static int ramoops_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
cxt->size = pdata->mem_size;
|
cxt->size = pdata->mem_size;
|
||||||
cxt->phys_addr = pdata->mem_address;
|
cxt->phys_addr = pdata->mem_address;
|
||||||
|
cxt->memtype = pdata->mem_type;
|
||||||
cxt->record_size = pdata->record_size;
|
cxt->record_size = pdata->record_size;
|
||||||
cxt->console_size = pdata->console_size;
|
cxt->console_size = pdata->console_size;
|
||||||
cxt->ftrace_size = pdata->ftrace_size;
|
cxt->ftrace_size = pdata->ftrace_size;
|
||||||
|
@ -572,6 +580,7 @@ static void ramoops_register_dummy(void)
|
||||||
|
|
||||||
dummy_data->mem_size = mem_size;
|
dummy_data->mem_size = mem_size;
|
||||||
dummy_data->mem_address = mem_address;
|
dummy_data->mem_address = mem_address;
|
||||||
|
dummy_data->mem_type = 0;
|
||||||
dummy_data->record_size = record_size;
|
dummy_data->record_size = record_size;
|
||||||
dummy_data->console_size = ramoops_console_size;
|
dummy_data->console_size = ramoops_console_size;
|
||||||
dummy_data->ftrace_size = ramoops_ftrace_size;
|
dummy_data->ftrace_size = ramoops_ftrace_size;
|
||||||
|
|
|
@ -380,7 +380,8 @@ void persistent_ram_zap(struct persistent_ram_zone *prz)
|
||||||
persistent_ram_update_header_ecc(prz);
|
persistent_ram_update_header_ecc(prz);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *persistent_ram_vmap(phys_addr_t start, size_t size)
|
static void *persistent_ram_vmap(phys_addr_t start, size_t size,
|
||||||
|
unsigned int memtype)
|
||||||
{
|
{
|
||||||
struct page **pages;
|
struct page **pages;
|
||||||
phys_addr_t page_start;
|
phys_addr_t page_start;
|
||||||
|
@ -392,7 +393,10 @@ static void *persistent_ram_vmap(phys_addr_t start, size_t size)
|
||||||
page_start = start - offset_in_page(start);
|
page_start = start - offset_in_page(start);
|
||||||
page_count = DIV_ROUND_UP(size + offset_in_page(start), PAGE_SIZE);
|
page_count = DIV_ROUND_UP(size + offset_in_page(start), PAGE_SIZE);
|
||||||
|
|
||||||
prot = pgprot_noncached(PAGE_KERNEL);
|
if (memtype)
|
||||||
|
prot = pgprot_noncached(PAGE_KERNEL);
|
||||||
|
else
|
||||||
|
prot = pgprot_writecombine(PAGE_KERNEL);
|
||||||
|
|
||||||
pages = kmalloc_array(page_count, sizeof(struct page *), GFP_KERNEL);
|
pages = kmalloc_array(page_count, sizeof(struct page *), GFP_KERNEL);
|
||||||
if (!pages) {
|
if (!pages) {
|
||||||
|
@ -411,8 +415,11 @@ static void *persistent_ram_vmap(phys_addr_t start, size_t size)
|
||||||
return vaddr;
|
return vaddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *persistent_ram_iomap(phys_addr_t start, size_t size)
|
static void *persistent_ram_iomap(phys_addr_t start, size_t size,
|
||||||
|
unsigned int memtype)
|
||||||
{
|
{
|
||||||
|
void *va;
|
||||||
|
|
||||||
if (!request_mem_region(start, size, "persistent_ram")) {
|
if (!request_mem_region(start, size, "persistent_ram")) {
|
||||||
pr_err("request mem region (0x%llx@0x%llx) failed\n",
|
pr_err("request mem region (0x%llx@0x%llx) failed\n",
|
||||||
(unsigned long long)size, (unsigned long long)start);
|
(unsigned long long)size, (unsigned long long)start);
|
||||||
|
@ -422,19 +429,24 @@ static void *persistent_ram_iomap(phys_addr_t start, size_t size)
|
||||||
buffer_start_add = buffer_start_add_locked;
|
buffer_start_add = buffer_start_add_locked;
|
||||||
buffer_size_add = buffer_size_add_locked;
|
buffer_size_add = buffer_size_add_locked;
|
||||||
|
|
||||||
return ioremap(start, size);
|
if (memtype)
|
||||||
|
va = ioremap(start, size);
|
||||||
|
else
|
||||||
|
va = ioremap_wc(start, size);
|
||||||
|
|
||||||
|
return va;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int persistent_ram_buffer_map(phys_addr_t start, phys_addr_t size,
|
static int persistent_ram_buffer_map(phys_addr_t start, phys_addr_t size,
|
||||||
struct persistent_ram_zone *prz)
|
struct persistent_ram_zone *prz, int memtype)
|
||||||
{
|
{
|
||||||
prz->paddr = start;
|
prz->paddr = start;
|
||||||
prz->size = size;
|
prz->size = size;
|
||||||
|
|
||||||
if (pfn_valid(start >> PAGE_SHIFT))
|
if (pfn_valid(start >> PAGE_SHIFT))
|
||||||
prz->vaddr = persistent_ram_vmap(start, size);
|
prz->vaddr = persistent_ram_vmap(start, size, memtype);
|
||||||
else
|
else
|
||||||
prz->vaddr = persistent_ram_iomap(start, size);
|
prz->vaddr = persistent_ram_iomap(start, size, memtype);
|
||||||
|
|
||||||
if (!prz->vaddr) {
|
if (!prz->vaddr) {
|
||||||
pr_err("%s: Failed to map 0x%llx pages at 0x%llx\n", __func__,
|
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size,
|
struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size,
|
||||||
u32 sig, struct persistent_ram_ecc_info *ecc_info)
|
u32 sig, struct persistent_ram_ecc_info *ecc_info,
|
||||||
|
unsigned int memtype)
|
||||||
{
|
{
|
||||||
struct persistent_ram_zone *prz;
|
struct persistent_ram_zone *prz;
|
||||||
int ret = -ENOMEM;
|
int ret = -ENOMEM;
|
||||||
|
@ -511,7 +524,7 @@ struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size,
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = persistent_ram_buffer_map(start, size, prz);
|
ret = persistent_ram_buffer_map(start, size, prz, memtype);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,8 @@ struct persistent_ram_zone {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size,
|
struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size,
|
||||||
u32 sig, struct persistent_ram_ecc_info *ecc_info);
|
u32 sig, struct persistent_ram_ecc_info *ecc_info,
|
||||||
|
unsigned int memtype);
|
||||||
void persistent_ram_free(struct persistent_ram_zone *prz);
|
void persistent_ram_free(struct persistent_ram_zone *prz);
|
||||||
void persistent_ram_zap(struct persistent_ram_zone *prz);
|
void persistent_ram_zap(struct persistent_ram_zone *prz);
|
||||||
|
|
||||||
|
@ -76,6 +77,7 @@ ssize_t persistent_ram_ecc_string(struct persistent_ram_zone *prz,
|
||||||
struct ramoops_platform_data {
|
struct ramoops_platform_data {
|
||||||
unsigned long mem_size;
|
unsigned long mem_size;
|
||||||
unsigned long mem_address;
|
unsigned long mem_address;
|
||||||
|
unsigned int mem_type;
|
||||||
unsigned long record_size;
|
unsigned long record_size;
|
||||||
unsigned long console_size;
|
unsigned long console_size;
|
||||||
unsigned long ftrace_size;
|
unsigned long ftrace_size;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user