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

Commit aa0ba2c4 authored by Komal Seelam's avatar Komal Seelam
Browse files

cnss-sdio: Dynamically allocate ramdump memory



Existing solution to reserve the memory region for CNSS ramdump
collection has it's own limitations because of reserving the
memory region for each platforms even before CNSS driver is
probed. Add implementation to allocate the required memory for
CNSS ramdump using dma_alloc_coherent API and update the physical
address in dump table so that tools can find the starting address
of the CNSS ramdump in the crash dump.

Change-Id: I9fb3d77fdd35de54ca2a7a27d4a55bd12049311f
Signed-off-by: default avatarKomal Seelam <kseelam@codeaurora.org>
CRs-Fixed: 957203
parent 5f47fa47
Loading
Loading
Loading
Loading
+88 −25
Original line number Diff line number Diff line
@@ -39,6 +39,11 @@
#define WLAN_VREG_XTAL_MIN	1800000
#define POWER_ON_DELAY		4

/* Values for Dynamic Ramdump Collection*/
#define CNSS_DUMP_FORMAT_VER	0x11
#define CNSS_DUMP_MAGIC_VER_V2	0x42445953
#define CNSS_DUMP_NAME		"CNSS_WLAN"

struct cnss_unsafe_channel_list {
	u16 unsafe_ch_count;
	u16 unsafe_ch_list[CNSS_MAX_CH_NUM];
@@ -70,6 +75,8 @@ struct cnss_ssr_info {
	unsigned long ramdump_size;
	void *ramdump_addr;
	phys_addr_t ramdump_phys;
	struct msm_dump_data dump_data;
	bool ramdump_dynamic;
	char subsys_name[10];
};

@@ -354,19 +361,45 @@ static void cnss_subsys_exit(void)
	ssr_info->subsys = NULL;
}

static int cnss_configure_dump_table(struct cnss_ssr_info *ssr_info)
{
	struct msm_dump_entry dump_entry;
	int ret;

	ssr_info->dump_data.addr = ssr_info->ramdump_phys;
	ssr_info->dump_data.len = ssr_info->ramdump_size;
	ssr_info->dump_data.version = CNSS_DUMP_FORMAT_VER;
	ssr_info->dump_data.magic = CNSS_DUMP_MAGIC_VER_V2;
	strlcpy(ssr_info->dump_data.name, CNSS_DUMP_NAME,
		sizeof(ssr_info->dump_data.name));

	dump_entry.id = MSM_DUMP_DATA_CNSS_WLAN;
	dump_entry.addr = virt_to_phys(&ssr_info->dump_data);

	ret = msm_dump_data_register(MSM_DUMP_TABLE_APPS, &dump_entry);
	if (ret)
		pr_err("%s: Dump table setup failed: %d\n", __func__, ret);

	return ret;
}

static int cnss_configure_ramdump(void)
{
	struct cnss_ssr_info *ssr_info;
	int ret = 0;
	struct resource *res;
	const char *name;
	u32 ramdump_size = 0;
	struct device *dev;

	if (!cnss_pdata)
		return -ENODEV;

	dev = &cnss_pdata->pdev->dev;

	ssr_info = &cnss_pdata->ssr_info;

	ret = of_property_read_string(cnss_pdata->pdev->dev.of_node,
				      CNSS_SUBSYS_NAME_KEY,
	ret = of_property_read_string(dev->of_node, CNSS_SUBSYS_NAME_KEY,
				      &name);
	if (ret) {
		pr_err("%s: cnss missing DT key '%s'\n", __func__,
@@ -374,44 +407,65 @@ static int cnss_configure_ramdump(void)
		ret = -ENODEV;
		goto err_subsys_name_query;
	}

	strlcpy(ssr_info->subsys_name, name, sizeof(ssr_info->subsys_name));

	if (of_property_read_u32(dev->of_node, "qcom,wlan-ramdump-dynamic",
				 &ramdump_size) == 0) {
		ssr_info->ramdump_addr = dma_alloc_coherent(dev, ramdump_size,
							&ssr_info->ramdump_phys,
							GFP_KERNEL);
		if (ssr_info->ramdump_addr)
			ssr_info->ramdump_size = ramdump_size;
		ssr_info->ramdump_dynamic = true;
	} else {
		res = platform_get_resource_byname(cnss_pdata->pdev,
						   IORESOURCE_MEM, "ramdump");
		if (res) {
			ssr_info->ramdump_phys = res->start;
		ssr_info->ramdump_size = resource_size(res);
	} else {
		pr_err("%s: CNSS ramdump mem not available\n", __func__);
		return 0;
			ramdump_size = resource_size(res);
			ssr_info->ramdump_addr = ioremap(ssr_info->ramdump_phys,
								ramdump_size);
			if (ssr_info->ramdump_addr)
				ssr_info->ramdump_size = ramdump_size;
			ssr_info->ramdump_dynamic = false;
		}
	}

	ssr_info->ramdump_addr = ioremap(ssr_info->ramdump_phys,
		ssr_info->ramdump_size);
	pr_info("%s: ramdump addr: %p, phys: %pa subsys:'%s'\n", __func__,
		ssr_info->ramdump_addr, &ssr_info->ramdump_phys,
		ssr_info->subsys_name);

	if (!ssr_info->ramdump_addr || ssr_info->ramdump_size == 0) {
		ssr_info->ramdump_size = 0;
		ssr_info->ramdump_addr = NULL;
		pr_err("%s: CNSS ramdump will not be collected\n", __func__);
	if (ssr_info->ramdump_size == 0) {
		pr_info("%s: CNSS ramdump will not be collected", __func__);
		return 0;
	}

	pr_info("%s: ramdump addr: %p, phys: %pa subsys:'%s'\n", __func__,
		ssr_info->ramdump_addr,
		&ssr_info->ramdump_phys,
		ssr_info->subsys_name);
	if (ssr_info->ramdump_dynamic) {
		ret = cnss_configure_dump_table(ssr_info);
		if (ret)
			goto err_configure_dump_table;
	}

	ssr_info->ramdump_dev = create_ramdump_device(ssr_info->subsys_name,
		&cnss_pdata->pdev->dev);
									dev);
	if (!ssr_info->ramdump_dev) {
		ret = -ENOMEM;
		pr_err("%s: ramdump dev create failed: error=%d\n",
		       __func__, ret);
		goto err_create_ramdump;
		goto err_configure_dump_table;
	}

	return 0;
err_create_ramdump:

err_configure_dump_table:
	if (ssr_info->ramdump_dynamic)
		dma_free_coherent(dev, ssr_info->ramdump_size,
				  ssr_info->ramdump_addr,
				  ssr_info->ramdump_phys);
	else
		iounmap(ssr_info->ramdump_addr);

	ssr_info->ramdump_addr = NULL;
	ssr_info->ramdump_size = 0;
err_subsys_name_query:
@@ -421,13 +475,22 @@ err_subsys_name_query:
static void cnss_ramdump_cleanup(void)
{
	struct cnss_ssr_info *ssr_info;
	struct device *dev;

	if (!cnss_pdata)
		return;

	dev = &cnss_pdata->pdev->dev;
	ssr_info = &cnss_pdata->ssr_info;
	if (ssr_info->ramdump_addr)
	if (ssr_info->ramdump_addr) {
		if (ssr_info->ramdump_dynamic)
			dma_free_coherent(dev, ssr_info->ramdump_size,
					  ssr_info->ramdump_addr,
					  ssr_info->ramdump_phys);
		else
			iounmap(ssr_info->ramdump_addr);
	}

	ssr_info->ramdump_addr = NULL;
	if (ssr_info->ramdump_dev)
		destroy_ramdump_device(ssr_info->ramdump_dev);