--- zzzz-none-000/linux-4.9.276/fs/pstore/ram.c 2021-07-20 14:21:16.000000000 +0000 +++ falcon-5530-750/linux-4.9.276/fs/pstore/ram.c 2023-04-05 08:19:02.000000000 +0000 @@ -53,8 +53,8 @@ module_param_named(ftrace_size, ramoops_ftrace_size, ulong, 0400); MODULE_PARM_DESC(ftrace_size, "size of ftrace log"); -static ulong ramoops_pmsg_size = MIN_MEM_SIZE; -module_param_named(pmsg_size, ramoops_pmsg_size, ulong, 0400); +static char *ramoops_pmsg_size_str; +module_param_named(pmsg_size, ramoops_pmsg_size_str, charp, 0400); MODULE_PARM_DESC(pmsg_size, "size of user space message log"); static unsigned long long mem_address; @@ -88,14 +88,14 @@ struct persistent_ram_zone **przs; struct persistent_ram_zone *cprz; struct persistent_ram_zone *fprz; - struct persistent_ram_zone *mprz; + struct persistent_ram_zone **mprzs; phys_addr_t phys_addr; unsigned long size; unsigned int memtype; size_t record_size; size_t console_size; size_t ftrace_size; - size_t pmsg_size; + size_t *pmsg_size; int dump_oops; struct persistent_ram_ecc_info ecc_info; unsigned int max_dump_cnt; @@ -222,9 +222,12 @@ if (!prz_ok(prz)) prz = ramoops_get_next_prz(&cxt->fprz, &cxt->ftrace_read_cnt, 1, id, type, PSTORE_TYPE_FTRACE, 0); - if (!prz_ok(prz)) - prz = ramoops_get_next_prz(&cxt->mprz, &cxt->pmsg_read_cnt, - 1, id, type, PSTORE_TYPE_PMSG, 0); + + while (cxt->pmsg_read_cnt < cxt->pstore.num_pmsg && !prz_ok(prz)) + /* get pmsg prz */ + prz = ramoops_get_next_prz(cxt->mprzs, &cxt->pmsg_read_cnt, + cxt->pstore.num_pmsg, id, type, + PSTORE_TYPE_PMSG, 0); if (!prz_ok(prz)) return 0; @@ -288,9 +291,9 @@ persistent_ram_write(cxt->fprz, buf, size); return 0; } else if (type == PSTORE_TYPE_PMSG) { - if (!cxt->mprz) + if (!cxt->mprzs) return -ENOMEM; - persistent_ram_write(cxt->mprz, buf, size); + persistent_ram_write(cxt->mprzs[part], buf, size); return 0; } @@ -352,9 +355,9 @@ if (type == PSTORE_TYPE_PMSG) { struct ramoops_context *cxt = psi->data; - if (!cxt->mprz) + if (!cxt->mprzs) return -ENOMEM; - return persistent_ram_write_user(cxt->mprz, buf, size); + return persistent_ram_write_user(cxt->mprzs[part], buf, size); } return -EINVAL; @@ -379,7 +382,9 @@ prz = cxt->fprz; break; case PSTORE_TYPE_PMSG: - prz = cxt->mprz; + if (id >= cxt->pstore.num_pmsg) + return -EINVAL; + prz = cxt->mprzs[id]; break; default: return -EINVAL; @@ -403,18 +408,51 @@ }, }; -static void ramoops_free_przs(struct ramoops_context *cxt) +static void ramoops_free_przs(struct persistent_ram_zone **przs) { int i; - if (!cxt->przs) + if (!przs) return; - for (i = 0; i < cxt->max_dump_cnt; i++) - persistent_ram_free(cxt->przs[i]); + for (i = 0; !IS_ERR_OR_NULL(przs[i]); i++) + persistent_ram_free(przs[i]); - kfree(cxt->przs); - cxt->max_dump_cnt = 0; + kfree(przs); +} + +static int __ramoops_init_prz(struct device *dev, struct ramoops_context *cxt, + struct persistent_ram_zone **prz, + phys_addr_t *paddr, size_t sz, u32 sig, + u32 flags, bool zap) +{ + if (!sz) + return 0; + + if (zap && *paddr + sz - cxt->phys_addr > cxt->size) { + dev_err(dev, "no room for mem region (0x%zx@0x%llx) in (0x%lx@0x%llx)\n", + sz, (unsigned long long)*paddr, + cxt->size, (unsigned long long)cxt->phys_addr); + return -ENOMEM; + } + + *prz = persistent_ram_new(*paddr, sz, sig, &cxt->ecc_info, + cxt->memtype, flags); + if (IS_ERR(prz)) { + int err = PTR_ERR(prz); + + dev_err(dev, "failed to request mem region (0x%zx@0x%llx): %d\n", + sz, (unsigned long long)*paddr, err); + + return err; + } + + if (zap) + persistent_ram_zap(*prz); + + *paddr += sz; + + return 0; } static int ramoops_init_przs(struct device *dev, struct ramoops_context *cxt, @@ -443,21 +481,15 @@ } for (i = 0; i < cxt->max_dump_cnt; i++) { - cxt->przs[i] = persistent_ram_new(*paddr, cxt->record_size, 0, - &cxt->ecc_info, - cxt->memtype, 0); - 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", - cxt->record_size, (unsigned long long)*paddr, err); - + err = __ramoops_init_prz(dev, cxt, &cxt->przs[i], paddr, + cxt->record_size, 0, 0, false); + if (err) { while (i > 0) { i--; persistent_ram_free(cxt->przs[i]); } goto fail_prz; } - *paddr += cxt->record_size; } return 0; @@ -468,35 +500,49 @@ return err; } -static int ramoops_init_prz(struct device *dev, struct ramoops_context *cxt, - struct persistent_ram_zone **prz, - phys_addr_t *paddr, size_t sz, u32 sig) +/* int function for pmsg przs */ +static int ramoops_init_mprzs(struct device *dev, struct ramoops_context *cxt, + phys_addr_t *paddr, unsigned long total) { - if (!sz) + int err = -ENOMEM; + int i; + + if (!total) return 0; - if (*paddr + sz - cxt->phys_addr > cxt->size) { - dev_err(dev, "no room for mem region (0x%zx@0x%llx) in (0x%lx@0x%llx)\n", - sz, (unsigned long long)*paddr, - cxt->size, (unsigned long long)cxt->phys_addr); + if (*paddr + total - cxt->phys_addr > cxt->size) { + dev_err(dev, "no room for pmsg\n"); return -ENOMEM; } - *prz = persistent_ram_new(*paddr, sz, sig, &cxt->ecc_info, - cxt->memtype, 0); - if (IS_ERR(*prz)) { - int err = PTR_ERR(*prz); + cxt->mprzs = kcalloc(cxt->pstore.num_pmsg, sizeof(*cxt->mprzs), + GFP_KERNEL); + if (!cxt->mprzs) + return -ENOMEM; - dev_err(dev, "failed to request mem region (0x%zx@0x%llx): %d\n", - sz, (unsigned long long)*paddr, err); - return err; + for (i = 0; i < cxt->pstore.num_pmsg; i++) { + err = __ramoops_init_prz(dev, cxt, &cxt->mprzs[i], paddr, + cxt->pmsg_size[i], 0, 0, true); + if (err) { + while (i > 0) { + i--; + persistent_ram_free(cxt->mprzs[i]); + } + goto fail_mprz; + } } - persistent_ram_zap(*prz); - - *paddr += sz; - return 0; +fail_mprz: + kfree(cxt->mprzs); + return err; +} + +static int ramoops_init_prz(struct device *dev, struct ramoops_context *cxt, + struct persistent_ram_zone **prz, + phys_addr_t *paddr, size_t sz, u32 sig) +{ + return __ramoops_init_prz(dev, cxt, prz, paddr, sz, sig, 0, true); } static int ramoops_parse_dt_size(struct platform_device *pdev, @@ -527,7 +573,8 @@ struct device_node *of_node = pdev->dev.of_node; struct resource *res; u32 value; - int ret; + int ret, i; + unsigned int num_pmsg; dev_dbg(&pdev->dev, "using Device Tree\n"); @@ -553,13 +600,70 @@ parse_size("record-size", pdata->record_size); parse_size("console-size", pdata->console_size); parse_size("ftrace-size", pdata->ftrace_size); - parse_size("pmsg-size", pdata->pmsg_size); parse_size("ecc-size", pdata->ecc_info.ecc_size); #undef parse_size + /* Parse pmesg size */ + if (!of_find_property(of_node, "pmsg-size", &num_pmsg)) + return 0; /* no data */ + + num_pmsg = num_pmsg / sizeof(u32); + + pdata->pmsg_size = + devm_kzalloc(&pdev->dev, sizeof(size_t) * (num_pmsg + 1), + GFP_KERNEL); + if (!pdata->pmsg_size) + return -ENOMEM; + + for (i = 0; i < num_pmsg; i++) { + ret = of_property_read_u32_index(of_node, "pmsg-size", + i, &value); + if (ret) { + dev_warn(&pdev->dev, + "%s: failed to read pmsg-size[%d]: %d\n", + __func__, i, ret); + return -EINVAL; + } + + /* CHECK INT_MAX */ + if (value > INT_MAX) { + dev_err(&pdev->dev, "value %x > INT_MAX\n", value); + return -EOVERFLOW; + } + pdata->pmsg_size[i] = value; + } + + return 0; +} + +#define ADDR_STRING_SIZE 10 /* "0x00000000" */ +static int update_pmsg_size_mod_param(size_t *pmsg_size, int num) +{ + int i, len; + char str[ADDR_STRING_SIZE + 2]; + + /* string size + commas count + NULL-terminated */ + len = ADDR_STRING_SIZE * num + (num - 1) + 1; + + /* using commandline or already allocation buffer.*/ + if (ramoops_pmsg_size_str) + goto out; + + ramoops_pmsg_size_str = kzalloc(len, GFP_KERNEL); + if (!ramoops_pmsg_size_str) + return -ENOMEM; + + for (i = 0 ; i < num; i++) { + const char *format = i == (num - 1) ? "0x%x" : "0x%x,"; + + snprintf(str, sizeof(str), format, pmsg_size[i]); + strcat(ramoops_pmsg_size_str, str); + } +out: return 0; } +#undef ADDR_STRING_SIZE static int ramoops_probe(struct platform_device *pdev) { @@ -569,6 +673,8 @@ size_t dump_mem_sz; phys_addr_t paddr; int err = -EINVAL; + unsigned long pmsg_size_total = 0; + unsigned int num_pmsg = 0; if (dev_of_node(dev) && !pdata) { pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); @@ -601,8 +707,21 @@ pdata->console_size = rounddown_pow_of_two(pdata->console_size); if (pdata->ftrace_size && !is_power_of_2(pdata->ftrace_size)) pdata->ftrace_size = rounddown_pow_of_two(pdata->ftrace_size); - if (pdata->pmsg_size && !is_power_of_2(pdata->pmsg_size)) - pdata->pmsg_size = rounddown_pow_of_two(pdata->pmsg_size); + + if (pdata->pmsg_size) { + for (;; num_pmsg++) { + unsigned long size = pdata->pmsg_size[num_pmsg]; + + if (!size) + break; + + if (!is_power_of_2(size)) + pdata->pmsg_size[num_pmsg] + = rounddown_pow_of_two(size); + + pmsg_size_total += size; + } + } cxt->size = pdata->mem_size; cxt->phys_addr = pdata->mem_address; @@ -610,17 +729,26 @@ cxt->record_size = pdata->record_size; cxt->console_size = pdata->console_size; cxt->ftrace_size = pdata->ftrace_size; - cxt->pmsg_size = pdata->pmsg_size; cxt->dump_oops = pdata->dump_oops; cxt->ecc_info = pdata->ecc_info; + cxt->pstore.num_pmsg = num_pmsg; - paddr = cxt->phys_addr; + if (num_pmsg) { + cxt->pmsg_size = kcalloc(num_pmsg, sizeof(size_t), GFP_KERNEL); + if (!cxt->pmsg_size) { + err = -ENOMEM; + goto fail_out; + } + memcpy(cxt->pmsg_size, pdata->pmsg_size, + sizeof(size_t) * num_pmsg); + } + paddr = cxt->phys_addr; dump_mem_sz = cxt->size - cxt->console_size - cxt->ftrace_size - - cxt->pmsg_size; + - pmsg_size_total; err = ramoops_init_przs(dev, cxt, &paddr, dump_mem_sz); if (err) - goto fail_out; + goto fail_init_dprzs; err = ramoops_init_prz(dev, cxt, &cxt->cprz, &paddr, cxt->console_size, 0); @@ -632,9 +760,9 @@ if (err) goto fail_init_fprz; - err = ramoops_init_prz(dev, cxt, &cxt->mprz, &paddr, cxt->pmsg_size, 0); + err = ramoops_init_mprzs(dev, cxt, &paddr, pmsg_size_total); if (err) - goto fail_init_mprz; + goto fail_init_mprzs; cxt->pstore.data = cxt; /* @@ -677,8 +805,8 @@ record_size = pdata->record_size; dump_oops = pdata->dump_oops; ramoops_console_size = pdata->console_size; - ramoops_pmsg_size = pdata->pmsg_size; ramoops_ftrace_size = pdata->ftrace_size; + update_pmsg_size_mod_param(cxt->pmsg_size, cxt->pstore.num_pmsg); pr_info("attached 0x%lx@0x%llx, ecc: %d/%d\n", cxt->size, (unsigned long long)cxt->phys_addr, @@ -690,13 +818,16 @@ kfree(cxt->pstore.buf); fail_clear: cxt->pstore.bufsize = 0; - persistent_ram_free(cxt->mprz); -fail_init_mprz: + ramoops_free_przs(cxt->mprzs); +fail_init_mprzs: persistent_ram_free(cxt->fprz); fail_init_fprz: persistent_ram_free(cxt->cprz); fail_init_cprz: - ramoops_free_przs(cxt); + cxt->max_dump_cnt = 0; + ramoops_free_przs(cxt->przs); +fail_init_dprzs: + kfree(cxt->pmsg_size); fail_out: return err; } @@ -709,11 +840,15 @@ kfree(cxt->pstore.buf); cxt->pstore.bufsize = 0; + kfree(cxt->pmsg_size); - persistent_ram_free(cxt->mprz); + ramoops_free_przs(cxt->mprzs); + cxt->pstore.num_pmsg = 0; persistent_ram_free(cxt->fprz); persistent_ram_free(cxt->cprz); - ramoops_free_przs(cxt); + + cxt->max_dump_cnt = 0; + ramoops_free_przs(cxt->przs); return 0; } @@ -732,6 +867,46 @@ }, }; +static unsigned long *parse_size_str(char *size_str) +{ + int i, ret; + unsigned long *size_array, count = 1; + + if (size_str) { + char *s = size_str; + + /* Necessary array size is the number of commas + 1 */ + for (; (s = strchr(s, ',')); s++) + count++; + } + + /* Add NULL-terminated */ + count++; + + size_array = kcalloc(count, sizeof(unsigned long), GFP_KERNEL); + if (!size_array) + goto out; + + if (size_str) { + for (i = 0; i < count; i++) { + int tmp; + + ret = get_option(&size_str, &tmp); + size_array[i] = tmp; + if (ret == 1) + break; + else if (ret != 2) { + size_array[i] = 0; + break; + } + } + } else + size_array[0] = MIN_MEM_SIZE; + +out: + return size_array; +} + static void ramoops_register_dummy(void) { if (!mem_size) @@ -751,7 +926,10 @@ dummy_data->record_size = record_size; dummy_data->console_size = ramoops_console_size; dummy_data->ftrace_size = ramoops_ftrace_size; - dummy_data->pmsg_size = ramoops_pmsg_size; + dummy_data->pmsg_size = parse_size_str(ramoops_pmsg_size_str); + + if (!dummy_data->pmsg_size) + goto fail_pmsg_size; dummy_data->dump_oops = dump_oops; /* * For backwards compatibility ramoops.ecc=1 means 16 bytes ECC @@ -764,7 +942,13 @@ if (IS_ERR(dummy)) { pr_info("could not create platform device: %ld\n", PTR_ERR(dummy)); + goto fail_pdev; } + return; +fail_pdev: + kfree(dummy_data->pmsg_size); +fail_pmsg_size: + kfree(dummy_data); } static int __init ramoops_init(void) @@ -778,6 +962,7 @@ { platform_driver_unregister(&ramoops_driver); platform_device_unregister(dummy); + kfree(dummy_data->pmsg_size); kfree(dummy_data); } module_exit(ramoops_exit);