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:
Коммит
6ce4436c9c
|
@ -14,11 +14,19 @@ survive after a restart.
|
|||
|
||||
1. Ramoops concepts
|
||||
|
||||
Ramoops uses a predefined memory area to store the dump. The start and size of
|
||||
the memory area are set using two variables:
|
||||
Ramoops uses a predefined memory area to store the dump. The start and size
|
||||
and type of the memory area are set using three variables:
|
||||
* "mem_address" for the start
|
||||
* "mem_size" for the size. The memory size will be rounded down to a
|
||||
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
|
||||
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 = {
|
||||
.mem_size = <...>,
|
||||
.mem_address = <...>,
|
||||
.mem_type = <...>,
|
||||
.record_size = <...>,
|
||||
.dump_oops = <...>,
|
||||
.ecc = <...>,
|
||||
|
|
|
@ -61,6 +61,11 @@ module_param(mem_size, ulong, 0400);
|
|||
MODULE_PARM_DESC(mem_size,
|
||||
"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;
|
||||
module_param(dump_oops, int, 0600);
|
||||
MODULE_PARM_DESC(dump_oops,
|
||||
|
@ -79,6 +84,7 @@ struct ramoops_context {
|
|||
struct persistent_ram_zone *fprz;
|
||||
phys_addr_t phys_addr;
|
||||
unsigned long size;
|
||||
unsigned int memtype;
|
||||
size_t record_size;
|
||||
size_t console_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;
|
||||
|
||||
cxt->przs[i] = persistent_ram_new(*paddr, sz, 0,
|
||||
&cxt->ecc_info);
|
||||
&cxt->ecc_info,
|
||||
cxt->memtype);
|
||||
if (IS_ERR(cxt->przs[i])) {
|
||||
err = PTR_ERR(cxt->przs[i]);
|
||||
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;
|
||||
}
|
||||
|
||||
*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)) {
|
||||
int err = PTR_ERR(*prz);
|
||||
|
||||
|
@ -443,6 +450,7 @@ static int ramoops_probe(struct platform_device *pdev)
|
|||
|
||||
cxt->size = pdata->mem_size;
|
||||
cxt->phys_addr = pdata->mem_address;
|
||||
cxt->memtype = pdata->mem_type;
|
||||
cxt->record_size = pdata->record_size;
|
||||
cxt->console_size = pdata->console_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_address = mem_address;
|
||||
dummy_data->mem_type = 0;
|
||||
dummy_data->record_size = record_size;
|
||||
dummy_data->console_size = ramoops_console_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);
|
||||
}
|
||||
|
||||
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;
|
||||
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_count = DIV_ROUND_UP(size + offset_in_page(start), PAGE_SIZE);
|
||||
|
||||
if (memtype)
|
||||
prot = pgprot_noncached(PAGE_KERNEL);
|
||||
else
|
||||
prot = pgprot_writecombine(PAGE_KERNEL);
|
||||
|
||||
pages = kmalloc_array(page_count, sizeof(struct page *), GFP_KERNEL);
|
||||
if (!pages) {
|
||||
|
@ -411,8 +415,11 @@ static void *persistent_ram_vmap(phys_addr_t start, size_t size)
|
|||
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")) {
|
||||
pr_err("request mem region (0x%llx@0x%llx) failed\n",
|
||||
(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_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,
|
||||
struct persistent_ram_zone *prz)
|
||||
struct persistent_ram_zone *prz, int memtype)
|
||||
{
|
||||
prz->paddr = start;
|
||||
prz->size = size;
|
||||
|
||||
if (pfn_valid(start >> PAGE_SHIFT))
|
||||
prz->vaddr = persistent_ram_vmap(start, size);
|
||||
prz->vaddr = persistent_ram_vmap(start, size, memtype);
|
||||
else
|
||||
prz->vaddr = persistent_ram_iomap(start, size);
|
||||
prz->vaddr = persistent_ram_iomap(start, size, memtype);
|
||||
|
||||
if (!prz->vaddr) {
|
||||
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,
|
||||
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;
|
||||
int ret = -ENOMEM;
|
||||
|
@ -511,7 +524,7 @@ struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size,
|
|||
goto err;
|
||||
}
|
||||
|
||||
ret = persistent_ram_buffer_map(start, size, prz);
|
||||
ret = persistent_ram_buffer_map(start, size, prz, memtype);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
|
|
|
@ -53,7 +53,8 @@ struct persistent_ram_zone {
|
|||
};
|
||||
|
||||
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_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 {
|
||||
unsigned long mem_size;
|
||||
unsigned long mem_address;
|
||||
unsigned int mem_type;
|
||||
unsigned long record_size;
|
||||
unsigned long console_size;
|
||||
unsigned long ftrace_size;
|
||||
|
|
Загрузка…
Ссылка в новой задаче