Loading drivers/net/wireless/cnss2/main.c +1 −1 Original line number Diff line number Diff line Loading @@ -2183,7 +2183,7 @@ int cnss_minidump_add_region(struct cnss_plat_data *plat_priv, md_entry.name, va, &pa, size); ret = msm_minidump_add_region(&md_entry); if (ret) if (ret < 0) cnss_pr_err("Failed to add mini dump region, err = %d\n", ret); return ret; Loading drivers/soc/qcom/dcc_v2.c +1 −1 Original line number Diff line number Diff line Loading @@ -1849,7 +1849,7 @@ static int dcc_probe(struct platform_device *pdev) md_entry.virt_addr = (uintptr_t)drvdata->ram_base; md_entry.phys_addr = res->start; md_entry.size = drvdata->ram_size; if (msm_minidump_add_region(&md_entry)) if (msm_minidump_add_region(&md_entry) < 0) dev_err(drvdata->dev, "Failed to add DCC data in Minidump\n"); return 0; Loading drivers/soc/qcom/memory_dump_v2.c +2 −2 Original line number Diff line number Diff line Loading @@ -662,7 +662,7 @@ int msm_dump_data_register(enum msm_dump_table_ids id, ret = register_dump_table_entry(id, entry); if (!ret) if (msm_dump_data_add_minidump(entry)) if (msm_dump_data_add_minidump(entry) < 0) pr_err("Failed to add entry in Minidump table\n"); return ret; Loading Loading @@ -856,7 +856,7 @@ static int mem_dump_alloc(struct platform_device *pdev) md_entry.size = size; md_entry.id = id; strlcpy(md_entry.name, child_node->name, sizeof(md_entry.name)); if (msm_minidump_add_region(&md_entry)) if (msm_minidump_add_region(&md_entry) < 0) dev_err(&pdev->dev, "Mini dump entry failed id = %d\n", id); Loading drivers/soc/qcom/minidump_log.c +44 −6 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include <linux/module.h> Loading @@ -11,6 +11,7 @@ #include <linux/thread_info.h> #include <soc/qcom/minidump.h> #include <asm/sections.h> #include <asm/stacktrace.h> #include <linux/mm.h> #include <linux/sched/task.h> #include <linux/vmalloc.h> Loading @@ -32,7 +33,7 @@ static void __init register_log_buf(void) md_entry.virt_addr = (uintptr_t) (*log_bufp); md_entry.phys_addr = virt_to_phys(*log_bufp); md_entry.size = *log_buf_lenp; if (msm_minidump_add_region(&md_entry)) if (msm_minidump_add_region(&md_entry) < 0) pr_err("Failed to add logbuf in Minidump\n"); } Loading @@ -51,7 +52,7 @@ static void register_stack_entry(struct md_region *ksp_entry, u64 sp, u64 size, ksp_entry->phys_addr = virt_to_phys((uintptr_t *)sp); } if (msm_minidump_add_region(ksp_entry)) if (msm_minidump_add_region(ksp_entry) < 0) pr_err("Failed to add stack of cpu %d in Minidump\n", cpu); } Loading @@ -67,7 +68,7 @@ static void __init register_kernel_sections(void) ksec_entry.virt_addr = (uintptr_t)_sdata; ksec_entry.phys_addr = virt_to_phys(_sdata); ksec_entry.size = roundup((__bss_stop - _sdata), 4); if (msm_minidump_add_region(&ksec_entry)) if (msm_minidump_add_region(&ksec_entry) < 0) pr_err("Failed to add data section in Minidump\n"); /* Add percpu static sections */ Loading @@ -80,7 +81,7 @@ static void __init register_kernel_sections(void) ksec_entry.virt_addr = (uintptr_t)start; ksec_entry.phys_addr = per_cpu_ptr_to_phys(start); ksec_entry.size = static_size; if (msm_minidump_add_region(&ksec_entry)) if (msm_minidump_add_region(&ksec_entry) < 0) pr_err("Failed to add percpu sections in Minidump\n"); } } Loading Loading @@ -152,13 +153,50 @@ void dump_stack_minidump(u64 sp) ktsk_entry.virt_addr = (u64)current; ktsk_entry.phys_addr = virt_to_phys((uintptr_t *)current); ktsk_entry.size = sizeof(struct task_struct); if (msm_minidump_add_region(&ktsk_entry)) if (msm_minidump_add_region(&ktsk_entry) < 0) pr_err("Failed to add current task %d in Minidump\n", cpu); } #ifdef CONFIG_ARM64 static void register_irq_stack(void) { int cpu; unsigned int i; int irq_stack_pages_count; u64 irq_stack_base; struct md_region irq_sp_entry; u64 sp; for_each_possible_cpu(cpu) { irq_stack_base = (u64)per_cpu(irq_stack_ptr, cpu); if (IS_ENABLED(CONFIG_VMAP_STACK)) { irq_stack_pages_count = IRQ_STACK_SIZE / PAGE_SIZE; sp = irq_stack_base & ~(PAGE_SIZE - 1); for (i = 0; i < irq_stack_pages_count; i++) { scnprintf(irq_sp_entry.name, sizeof(irq_sp_entry.name), "KISTACK%d_%d", cpu, i); register_stack_entry(&irq_sp_entry, sp, PAGE_SIZE, cpu); sp += PAGE_SIZE; } } else { sp = irq_stack_base; scnprintf(irq_sp_entry.name, sizeof(irq_sp_entry.name), "KISTACK%d", cpu); register_stack_entry(&irq_sp_entry, sp, IRQ_STACK_SIZE, cpu); } } } #else static inline void register_irq_stack(void) {} #endif static int __init msm_minidump_log_init(void) { register_kernel_sections(); register_irq_stack(); register_log_buf(); return 0; } Loading drivers/soc/qcom/msm_minidump.c +75 −6 Original line number Diff line number Diff line Loading @@ -55,8 +55,11 @@ struct md_elfhdr { /* Protect elfheader and smem table from deferred calls contention */ static DEFINE_SPINLOCK(mdt_lock); static DEFINE_RWLOCK(mdt_remove_lock); static struct md_table minidump_table; static struct md_elfhdr minidump_elfheader; static int first_removed_entry = INT_MAX; static bool md_init_done; /* Number of pending entries to be added in ToC regions */ static unsigned int pendings; Loading Loading @@ -166,11 +169,8 @@ bool msm_minidump_enabled(void) } EXPORT_SYMBOL(msm_minidump_enabled); int msm_minidump_add_region(const struct md_region *entry) static inline int validate_region(const struct md_region *entry) { u32 entries; struct md_region *mdr; if (!entry) return -EINVAL; Loading @@ -180,6 +180,68 @@ int msm_minidump_add_region(const struct md_region *entry) return -EINVAL; } return 0; } int msm_minidump_update_region(int regno, const struct md_region *entry) { int ret = 0; struct md_region *mdr; struct md_ss_region *mdssr; struct elfhdr *hdr = minidump_elfheader.ehdr; struct elf_shdr *shdr; struct elf_phdr *phdr; /* Ensure that init completes before we update regions */ if (!smp_load_acquire(&md_init_done)) return -EINVAL; if (validate_region(entry) || (regno >= MAX_NUM_ENTRIES)) return -EINVAL; read_lock(&mdt_remove_lock); if (regno >= first_removed_entry) { pr_err("Region:[%s] was moved\n", entry->name); ret = -EINVAL; goto err_unlock; } if (md_entry_num(entry) < 0) { pr_err("Region:[%s] does not exist to update.\n", entry->name); ret = -ENOMEM; goto err_unlock; } mdr = &minidump_table.entry[regno]; mdr->virt_addr = entry->virt_addr; mdr->phys_addr = entry->phys_addr; mdssr = &minidump_table.md_regions[regno + 1]; mdssr->region_base_address = entry->phys_addr; shdr = elf_section(hdr, regno + 4); phdr = elf_program(hdr, regno + 1); shdr->sh_addr = (elf_addr_t)entry->virt_addr; phdr->p_vaddr = entry->virt_addr; phdr->p_paddr = entry->phys_addr; err_unlock: read_unlock(&mdt_remove_lock); return ret; } EXPORT_SYMBOL(msm_minidump_update_region); int msm_minidump_add_region(const struct md_region *entry) { u32 entries; struct md_region *mdr; if (validate_region(entry)) return -EINVAL; spin_lock(&mdt_lock); if (md_entry_num(entry) >= 0) { pr_err("Entry name already exist.\n"); Loading Loading @@ -212,7 +274,7 @@ int msm_minidump_add_region(const struct md_region *entry) spin_unlock(&mdt_lock); return 0; return entries; } EXPORT_SYMBOL(msm_minidump_add_region); Loading Loading @@ -301,6 +363,7 @@ int msm_minidump_remove_region(const struct md_region *entry) return -EINVAL; spin_lock(&mdt_lock); write_lock(&mdt_remove_lock); ecount = minidump_table.num_regions; rcount = minidump_table.md_ss_toc->ss_region_count; rgno = md_entry_num(entry); Loading @@ -309,6 +372,8 @@ int msm_minidump_remove_region(const struct md_region *entry) goto out; } if (first_removed_entry > rgno) first_removed_entry = rgno; minidump_table.md_ss_toc->md_ss_toc_init = 0; /* Remove entry from: entry list, ss region list and elf header */ Loading Loading @@ -338,9 +403,11 @@ int msm_minidump_remove_region(const struct md_region *entry) minidump_table.md_ss_toc->md_ss_toc_init = 1; minidump_table.num_regions--; write_unlock(&mdt_remove_lock); spin_unlock(&mdt_lock); return 0; out: write_unlock(&mdt_remove_lock); spin_unlock(&mdt_lock); pr_err("Minidump is broken..disable Minidump collection\n"); return -EINVAL; Loading Loading @@ -507,6 +574,8 @@ static int __init msm_minidump_init(void) pr_info("Enabled with max number of regions %d\n", CONFIG_MINIDUMP_MAX_ENTRIES); /* All updates above should be visible, before init completes */ smp_store_release(&md_init_done, true); return 0; } subsys_initcall(msm_minidump_init) Loading
drivers/net/wireless/cnss2/main.c +1 −1 Original line number Diff line number Diff line Loading @@ -2183,7 +2183,7 @@ int cnss_minidump_add_region(struct cnss_plat_data *plat_priv, md_entry.name, va, &pa, size); ret = msm_minidump_add_region(&md_entry); if (ret) if (ret < 0) cnss_pr_err("Failed to add mini dump region, err = %d\n", ret); return ret; Loading
drivers/soc/qcom/dcc_v2.c +1 −1 Original line number Diff line number Diff line Loading @@ -1849,7 +1849,7 @@ static int dcc_probe(struct platform_device *pdev) md_entry.virt_addr = (uintptr_t)drvdata->ram_base; md_entry.phys_addr = res->start; md_entry.size = drvdata->ram_size; if (msm_minidump_add_region(&md_entry)) if (msm_minidump_add_region(&md_entry) < 0) dev_err(drvdata->dev, "Failed to add DCC data in Minidump\n"); return 0; Loading
drivers/soc/qcom/memory_dump_v2.c +2 −2 Original line number Diff line number Diff line Loading @@ -662,7 +662,7 @@ int msm_dump_data_register(enum msm_dump_table_ids id, ret = register_dump_table_entry(id, entry); if (!ret) if (msm_dump_data_add_minidump(entry)) if (msm_dump_data_add_minidump(entry) < 0) pr_err("Failed to add entry in Minidump table\n"); return ret; Loading Loading @@ -856,7 +856,7 @@ static int mem_dump_alloc(struct platform_device *pdev) md_entry.size = size; md_entry.id = id; strlcpy(md_entry.name, child_node->name, sizeof(md_entry.name)); if (msm_minidump_add_region(&md_entry)) if (msm_minidump_add_region(&md_entry) < 0) dev_err(&pdev->dev, "Mini dump entry failed id = %d\n", id); Loading
drivers/soc/qcom/minidump_log.c +44 −6 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include <linux/module.h> Loading @@ -11,6 +11,7 @@ #include <linux/thread_info.h> #include <soc/qcom/minidump.h> #include <asm/sections.h> #include <asm/stacktrace.h> #include <linux/mm.h> #include <linux/sched/task.h> #include <linux/vmalloc.h> Loading @@ -32,7 +33,7 @@ static void __init register_log_buf(void) md_entry.virt_addr = (uintptr_t) (*log_bufp); md_entry.phys_addr = virt_to_phys(*log_bufp); md_entry.size = *log_buf_lenp; if (msm_minidump_add_region(&md_entry)) if (msm_minidump_add_region(&md_entry) < 0) pr_err("Failed to add logbuf in Minidump\n"); } Loading @@ -51,7 +52,7 @@ static void register_stack_entry(struct md_region *ksp_entry, u64 sp, u64 size, ksp_entry->phys_addr = virt_to_phys((uintptr_t *)sp); } if (msm_minidump_add_region(ksp_entry)) if (msm_minidump_add_region(ksp_entry) < 0) pr_err("Failed to add stack of cpu %d in Minidump\n", cpu); } Loading @@ -67,7 +68,7 @@ static void __init register_kernel_sections(void) ksec_entry.virt_addr = (uintptr_t)_sdata; ksec_entry.phys_addr = virt_to_phys(_sdata); ksec_entry.size = roundup((__bss_stop - _sdata), 4); if (msm_minidump_add_region(&ksec_entry)) if (msm_minidump_add_region(&ksec_entry) < 0) pr_err("Failed to add data section in Minidump\n"); /* Add percpu static sections */ Loading @@ -80,7 +81,7 @@ static void __init register_kernel_sections(void) ksec_entry.virt_addr = (uintptr_t)start; ksec_entry.phys_addr = per_cpu_ptr_to_phys(start); ksec_entry.size = static_size; if (msm_minidump_add_region(&ksec_entry)) if (msm_minidump_add_region(&ksec_entry) < 0) pr_err("Failed to add percpu sections in Minidump\n"); } } Loading Loading @@ -152,13 +153,50 @@ void dump_stack_minidump(u64 sp) ktsk_entry.virt_addr = (u64)current; ktsk_entry.phys_addr = virt_to_phys((uintptr_t *)current); ktsk_entry.size = sizeof(struct task_struct); if (msm_minidump_add_region(&ktsk_entry)) if (msm_minidump_add_region(&ktsk_entry) < 0) pr_err("Failed to add current task %d in Minidump\n", cpu); } #ifdef CONFIG_ARM64 static void register_irq_stack(void) { int cpu; unsigned int i; int irq_stack_pages_count; u64 irq_stack_base; struct md_region irq_sp_entry; u64 sp; for_each_possible_cpu(cpu) { irq_stack_base = (u64)per_cpu(irq_stack_ptr, cpu); if (IS_ENABLED(CONFIG_VMAP_STACK)) { irq_stack_pages_count = IRQ_STACK_SIZE / PAGE_SIZE; sp = irq_stack_base & ~(PAGE_SIZE - 1); for (i = 0; i < irq_stack_pages_count; i++) { scnprintf(irq_sp_entry.name, sizeof(irq_sp_entry.name), "KISTACK%d_%d", cpu, i); register_stack_entry(&irq_sp_entry, sp, PAGE_SIZE, cpu); sp += PAGE_SIZE; } } else { sp = irq_stack_base; scnprintf(irq_sp_entry.name, sizeof(irq_sp_entry.name), "KISTACK%d", cpu); register_stack_entry(&irq_sp_entry, sp, IRQ_STACK_SIZE, cpu); } } } #else static inline void register_irq_stack(void) {} #endif static int __init msm_minidump_log_init(void) { register_kernel_sections(); register_irq_stack(); register_log_buf(); return 0; } Loading
drivers/soc/qcom/msm_minidump.c +75 −6 Original line number Diff line number Diff line Loading @@ -55,8 +55,11 @@ struct md_elfhdr { /* Protect elfheader and smem table from deferred calls contention */ static DEFINE_SPINLOCK(mdt_lock); static DEFINE_RWLOCK(mdt_remove_lock); static struct md_table minidump_table; static struct md_elfhdr minidump_elfheader; static int first_removed_entry = INT_MAX; static bool md_init_done; /* Number of pending entries to be added in ToC regions */ static unsigned int pendings; Loading Loading @@ -166,11 +169,8 @@ bool msm_minidump_enabled(void) } EXPORT_SYMBOL(msm_minidump_enabled); int msm_minidump_add_region(const struct md_region *entry) static inline int validate_region(const struct md_region *entry) { u32 entries; struct md_region *mdr; if (!entry) return -EINVAL; Loading @@ -180,6 +180,68 @@ int msm_minidump_add_region(const struct md_region *entry) return -EINVAL; } return 0; } int msm_minidump_update_region(int regno, const struct md_region *entry) { int ret = 0; struct md_region *mdr; struct md_ss_region *mdssr; struct elfhdr *hdr = minidump_elfheader.ehdr; struct elf_shdr *shdr; struct elf_phdr *phdr; /* Ensure that init completes before we update regions */ if (!smp_load_acquire(&md_init_done)) return -EINVAL; if (validate_region(entry) || (regno >= MAX_NUM_ENTRIES)) return -EINVAL; read_lock(&mdt_remove_lock); if (regno >= first_removed_entry) { pr_err("Region:[%s] was moved\n", entry->name); ret = -EINVAL; goto err_unlock; } if (md_entry_num(entry) < 0) { pr_err("Region:[%s] does not exist to update.\n", entry->name); ret = -ENOMEM; goto err_unlock; } mdr = &minidump_table.entry[regno]; mdr->virt_addr = entry->virt_addr; mdr->phys_addr = entry->phys_addr; mdssr = &minidump_table.md_regions[regno + 1]; mdssr->region_base_address = entry->phys_addr; shdr = elf_section(hdr, regno + 4); phdr = elf_program(hdr, regno + 1); shdr->sh_addr = (elf_addr_t)entry->virt_addr; phdr->p_vaddr = entry->virt_addr; phdr->p_paddr = entry->phys_addr; err_unlock: read_unlock(&mdt_remove_lock); return ret; } EXPORT_SYMBOL(msm_minidump_update_region); int msm_minidump_add_region(const struct md_region *entry) { u32 entries; struct md_region *mdr; if (validate_region(entry)) return -EINVAL; spin_lock(&mdt_lock); if (md_entry_num(entry) >= 0) { pr_err("Entry name already exist.\n"); Loading Loading @@ -212,7 +274,7 @@ int msm_minidump_add_region(const struct md_region *entry) spin_unlock(&mdt_lock); return 0; return entries; } EXPORT_SYMBOL(msm_minidump_add_region); Loading Loading @@ -301,6 +363,7 @@ int msm_minidump_remove_region(const struct md_region *entry) return -EINVAL; spin_lock(&mdt_lock); write_lock(&mdt_remove_lock); ecount = minidump_table.num_regions; rcount = minidump_table.md_ss_toc->ss_region_count; rgno = md_entry_num(entry); Loading @@ -309,6 +372,8 @@ int msm_minidump_remove_region(const struct md_region *entry) goto out; } if (first_removed_entry > rgno) first_removed_entry = rgno; minidump_table.md_ss_toc->md_ss_toc_init = 0; /* Remove entry from: entry list, ss region list and elf header */ Loading Loading @@ -338,9 +403,11 @@ int msm_minidump_remove_region(const struct md_region *entry) minidump_table.md_ss_toc->md_ss_toc_init = 1; minidump_table.num_regions--; write_unlock(&mdt_remove_lock); spin_unlock(&mdt_lock); return 0; out: write_unlock(&mdt_remove_lock); spin_unlock(&mdt_lock); pr_err("Minidump is broken..disable Minidump collection\n"); return -EINVAL; Loading Loading @@ -507,6 +574,8 @@ static int __init msm_minidump_init(void) pr_info("Enabled with max number of regions %d\n", CONFIG_MINIDUMP_MAX_ENTRIES); /* All updates above should be visible, before init completes */ smp_store_release(&md_init_done, true); return 0; } subsys_initcall(msm_minidump_init)