Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2fb25cbc authored by Prasad Sodagudi's avatar Prasad Sodagudi Committed by Tingwei Zhang
Browse files

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: default avatarPrasad Sodagudi <psodagud@codeaurora.org>
Signed-off-by: default avatarTingwei Zhang <tingwei@codeaurora.org>
parent 09950893
Loading
Loading
Loading
Loading
+101 −58
Original line number Diff line number Diff line
@@ -12,7 +12,8 @@
#include <linux/of_address.h>
#include <soc/qcom/minidump.h>
#include <soc/qcom/memory_dump.h>
#include <linux/qcom_scm.h>
#include <linux/qtee_shmbridge.h>
#include <soc/qcom/secure_buffer.h>
#include <linux/of_device.h>
#include <linux/dma-mapping.h>
#include <linux/module.h>
@@ -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,45 +263,93 @@ static int mem_dump_probe(struct platform_device *pdev)
			continue;
		}

		ret = of_property_read_u32(child_node, "qcom,dump-id", &id);
		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, "Unable to find id for %s\n",
					child_node->name);
			continue;
		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;
	}

		dump_vaddr = dma_alloc_coherent(&pdev->dev, size,
						&dump_addr, GFP_KERNEL);
	memset(dump_vaddr, 0x0, total_size);

		if (!dump_vaddr) {
			dev_err(&pdev->dev, "Couldn't get memory for dumping\n");
			continue;
	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_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);
	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",
					child_node->name);
			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 ret;
}
	return 0;

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[] = {