From 2fb25cbc0f918c12b60853722f7ee466316381bd Mon Sep 17 00:00:00 2001 From: Prasad Sodagudi Date: Tue, 17 Sep 2019 17:16:17 -0700 Subject: [PATCH] soc: qcom: Unify the memory dump entries registration cpu context, cache dump table entries are getting registered from different drivers. Idea is to unify all the dump table entries registration for all entries from kernel. Change-Id: I159ee826345ea7eefb6a085c3e78447317a4b4a3 Signed-off-by: Prasad Sodagudi Signed-off-by: Tingwei Zhang --- drivers/soc/qcom/memory_dump_v2.c | 159 +++++++++++++++++++----------- 1 file changed, 101 insertions(+), 58 deletions(-) diff --git a/drivers/soc/qcom/memory_dump_v2.c b/drivers/soc/qcom/memory_dump_v2.c index db1aa1957ff3..736e13140756 100644 --- a/drivers/soc/qcom/memory_dump_v2.c +++ b/drivers/soc/qcom/memory_dump_v2.c @@ -12,7 +12,8 @@ #include #include #include -#include +#include +#include #include #include #include @@ -163,7 +164,7 @@ int msm_dump_data_register_nominidump(enum msm_dump_table_ids id, } EXPORT_SYMBOL(msm_dump_data_register_nominidump); -static int __init init_memory_dump(void) +static int init_memory_dump(void *dump_vaddr, phys_addr_t phys_addr) { struct msm_dump_table *table; struct msm_dump_entry entry; @@ -184,47 +185,31 @@ static int __init init_memory_dump(void) return -ENOMEM; } - memdump.table = kzalloc(sizeof(struct msm_dump_table), GFP_KERNEL); - if (!memdump.table) { - ret = -ENOMEM; - goto err0; - } + memdump.table = dump_vaddr; memdump.table->version = MSM_DUMP_TABLE_VERSION; - memdump.table_phys = virt_to_phys(memdump.table); - memcpy_toio(imem_base, &memdump.table_phys, sizeof(memdump.table_phys)); + memdump.table_phys = phys_addr; + memcpy_toio(imem_base, &memdump.table_phys, + sizeof(memdump.table_phys)); /* Ensure write to imem_base is complete before unmapping */ mb(); pr_info("MSM Memory Dump base table set up\n"); iounmap(imem_base); - - table = kzalloc(sizeof(struct msm_dump_table), GFP_KERNEL); - if (!table) { - ret = -ENOMEM; - goto err1; - } + dump_vaddr += sizeof(*table); + phys_addr += sizeof(*table); + table = dump_vaddr; table->version = MSM_DUMP_TABLE_VERSION; - entry.id = MSM_DUMP_TABLE_APPS; - entry.addr = virt_to_phys(table); + entry.addr = phys_addr; ret = msm_dump_table_register(&entry); if (ret) { - pr_info("mem dump apps data table register failed\n"); - goto err2; + pr_err("mem dump apps data table register failed\n"); + return ret; } pr_info("MSM Memory Dump apps data table set up\n"); return 0; -err2: - kfree(table); -err1: - kfree(memdump.table); - return ret; -err0: - iounmap(imem_base); - return ret; } -early_initcall(init_memory_dump); static int mem_dump_reserve_mem(struct device *dev) { @@ -246,20 +231,30 @@ static int mem_dump_reserve_mem(struct device *dev) return 0; } -static int mem_dump_probe(struct platform_device *pdev) +#define MSM_DUMP_DATA_SIZE sizeof(struct msm_dump_data) +static int mem_dump_alloc(struct platform_device *pdev) { struct device_node *child_node; const struct device_node *node = pdev->dev.of_node; - static dma_addr_t dump_addr; - static void *dump_vaddr; struct msm_dump_data *dump_data; struct msm_dump_entry dump_entry; - int ret; + struct md_region md_entry; + size_t total_size; u32 size, id; + int ret, no_of_nodes; + dma_addr_t dma_handle; + phys_addr_t phys_addr; + struct sg_table mem_dump_sgt; + void *dump_vaddr; + uint32_t ns_vmids[] = {VMID_HLOS}; + uint32_t ns_vm_perms[] = {PERM_READ | PERM_WRITE}; + u64 shm_bridge_handle; if (mem_dump_reserve_mem(&pdev->dev) != 0) return -ENOMEM; - + total_size = size = ret = no_of_nodes = 0; + /* For dump table registration with IMEM */ + total_size = sizeof(struct msm_dump_table) * 2; for_each_available_child_of_node(node, child_node) { ret = of_property_read_u32(child_node, "qcom,dump-size", &size); if (ret) { @@ -268,6 +263,51 @@ static int mem_dump_probe(struct platform_device *pdev) continue; } + total_size += size; + no_of_nodes++; + } + + total_size += (MSM_DUMP_DATA_SIZE * no_of_nodes); + total_size = ALIGN(total_size, SZ_4K); + dump_vaddr = dma_alloc_coherent(&pdev->dev, total_size, + &dma_handle, GFP_KERNEL); + if (!dump_vaddr) + return -ENOMEM; + + dma_get_sgtable(&pdev->dev, &mem_dump_sgt, dump_vaddr, + dma_handle, total_size); + phys_addr = page_to_phys(sg_page(mem_dump_sgt.sgl)); + sg_free_table(&mem_dump_sgt); + + ret = qtee_shmbridge_register(phys_addr, total_size, ns_vmids, + ns_vm_perms, 1, PERM_READ|PERM_WRITE, &shm_bridge_handle); + + if (ret) { + dev_err(&pdev->dev, "Failed to create shm bridge.ret=%d\n", + ret); + dma_free_coherent(&pdev->dev, total_size, + dump_vaddr, dma_handle); + return ret; + } + + memset(dump_vaddr, 0x0, total_size); + + ret = init_memory_dump(dump_vaddr, phys_addr); + if (ret) { + dev_err(&pdev->dev, "Memory Dump table set up is failed\n"); + qtee_shmbridge_deregister(shm_bridge_handle); + dma_free_coherent(&pdev->dev, total_size, + dump_vaddr, dma_handle); + return ret; + } + + dump_vaddr += (sizeof(struct msm_dump_table) * 2); + phys_addr += (sizeof(struct msm_dump_table) * 2); + for_each_available_child_of_node(node, child_node) { + ret = of_property_read_u32(child_node, "qcom,dump-size", &size); + if (ret) + continue; + ret = of_property_read_u32(child_node, "qcom,dump-id", &id); if (ret) { dev_err(&pdev->dev, "Unable to find id for %s\n", @@ -275,38 +315,41 @@ static int mem_dump_probe(struct platform_device *pdev) continue; } - dump_vaddr = dma_alloc_coherent(&pdev->dev, size, - &dump_addr, GFP_KERNEL); - - if (!dump_vaddr) { - dev_err(&pdev->dev, "Couldn't get memory for dumping\n"); - continue; - } - - dump_data = devm_kzalloc(&pdev->dev, - sizeof(struct msm_dump_data), GFP_KERNEL); - if (!dump_data) { - dma_free_coherent(&pdev->dev, size, dump_vaddr, - dump_addr); - continue; - } - - dump_data->addr = dump_addr; + dump_data = dump_vaddr; + dump_data->addr = phys_addr + MSM_DUMP_DATA_SIZE; dump_data->len = size; dump_entry.id = id; strlcpy(dump_data->name, child_node->name, sizeof(dump_data->name)); - dump_entry.addr = virt_to_phys(dump_data); - ret = msm_dump_data_register(MSM_DUMP_TABLE_APPS, &dump_entry); - if (ret) { + dump_entry.addr = phys_addr; + ret = msm_dump_data_register_nominidump(MSM_DUMP_TABLE_APPS, + &dump_entry); + if (ret) dev_err(&pdev->dev, "Data dump setup failed, id = %d\n", id); - dma_free_coherent(&pdev->dev, size, dump_vaddr, - dump_addr); - devm_kfree(&pdev->dev, dump_data); - } + + md_entry.phys_addr = dump_data->addr; + md_entry.virt_addr = (uintptr_t)dump_vaddr + MSM_DUMP_DATA_SIZE; + 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)) + dev_err(&pdev->dev, "Mini dump entry failed id = %d\n", + id); + + dump_vaddr += (size + MSM_DUMP_DATA_SIZE); + phys_addr += (size + MSM_DUMP_DATA_SIZE); } - return 0; + + return ret; +} + +static int mem_dump_probe(struct platform_device *pdev) +{ + int ret; + + ret = mem_dump_alloc(pdev); + return ret; } static const struct of_device_id mem_dump_match_table[] = {