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

Commit a0a9abc9 authored by Raghavendra Rao Ananta's avatar Raghavendra Rao Ananta
Browse files

pil: Fix minidump collection during SSR



By default, the ramdump driver expects the virtual address of the
segments to be set in order to collect the dumps. However, the
minidump collection path in the PIL driver doesn't honor this
requirement. Hence, generate a mapping on the physical address
and use that to collect the minidumps.

Change-Id: Icb7b20dc5f31daab6d1f1be5b7046e4c18dea31a
Signed-off-by: default avatarRaghavendra Rao Ananta <rananta@codeaurora.org>
parent ead4c53f
Loading
Loading
Loading
Loading
+39 −6
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2010-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2010-2020, The Linux Foundation. All rights reserved.
 */

#include <linux/module.h>
@@ -237,6 +237,22 @@ static void unmap_aux_minidump_regions(struct aux_minidump_info *aux_mdump,
	}
}

/**
 * unmap_minidump_segments() - unmap the individual segments that were mapped
 * @rd_segs: The array of ramdump segments
 * @num_valid_segs: The number of valid segments from rd_segs
 *
 * The function unmaps the valid regions for the segments that were mapped.
 */
static void unmap_minidump_segments(struct ramdump_segment *rd_segs,
					int num_valid_segs)
{
	while (num_valid_segs--) {
		iounmap(rd_segs->v_address);
		rd_segs++;
	}
}

/**
 * prepare_minidump_segments() - Fills in the necessary information for the
 * ramdump driver to dump a region of memory, described by a segment.
@@ -271,6 +287,12 @@ static unsigned int prepare_minidump_segments(struct ramdump_segment *rd_segs,
			offset = offset +
				sizeof(region_info->region_base_address);
			rd_segs->size = __raw_readl(offset);

			rd_segs->v_address = ioremap_wc(rd_segs->address,
							rd_segs->size);
			if (!rd_segs->v_address)
				return -ENOMEM;

			pr_debug("Minidump : Dumping segment %s with address 0x%lx and size 0x%x\n",
				rd_segs->name, rd_segs->address,
				(unsigned int)rd_segs->size);
@@ -301,14 +323,14 @@ static unsigned int prepare_minidump_segments(struct ramdump_segment *rd_segs,
 * describe the regions that should be dumped by the ramdump driver for a set
 * of auxiliary minidump IDs.
 */
static void prepare_aux_minidump_segments(struct ramdump_segment *rd_segs,
static int prepare_aux_minidump_segments(struct ramdump_segment *rd_segs,
					  struct aux_minidump_info *aux_mdump,
					  int *ss_valid_seg_cnt,
					  int num_aux_md_ids)
{
	unsigned int i;
	struct ramdump_segment *s = rd_segs;
	unsigned int next_offset = 0;
	int next_offset = 0;

	for (i = 0; i < num_aux_md_ids; i++) {
		s = &rd_segs[next_offset];
@@ -316,7 +338,11 @@ static void prepare_aux_minidump_segments(struct ramdump_segment *rd_segs,
					aux_mdump[i].region_info_aux,
					aux_mdump[i].seg_cnt,
					ss_valid_seg_cnt);
		if (next_offset < 0)
			return next_offset;
	}

	return 0;
}

static int pil_do_minidump(struct pil_desc *desc, void *ramdump_dev)
@@ -329,7 +355,7 @@ static int pil_do_minidump(struct pil_desc *desc, void *ramdump_dev)
	int ss_valid_seg_cnt;
	int ret;
	struct aux_minidump_info *aux_minidump_data = NULL;
	unsigned int next_offset;
	int next_offset;

	if (!ramdump_dev)
		return -ENODEV;
@@ -372,12 +398,17 @@ static int pil_do_minidump(struct pil_desc *desc, void *ramdump_dev)
	next_offset = prepare_minidump_segments(ramdump_segs, region_info_ss,
						 ss_mdump_seg_cnt_ss,
						 &ss_valid_seg_cnt);
	if (next_offset < 0)
		goto seg_mapping_fail;

	if (desc->num_aux_minidump_ids > 0)
		prepare_aux_minidump_segments(&ramdump_segs[next_offset],
	if (desc->num_aux_minidump_ids > 0) {
		ret = prepare_aux_minidump_segments(&ramdump_segs[next_offset],
					      aux_minidump_data,
					      &ss_valid_seg_cnt,
					      desc->num_aux_minidump_ids);
		if (ret < 0)
			goto seg_mapping_fail;
	}

	ret = do_minidump(ramdump_dev, ramdump_segs, ss_valid_seg_cnt);
	if (ret)
@@ -388,6 +419,8 @@ static int pil_do_minidump(struct pil_desc *desc, void *ramdump_dev)
		ret = pil_assign_mem_to_subsys(desc, priv->region_start,
			(priv->region_end - priv->region_start));

seg_mapping_fail:
	unmap_minidump_segments(ramdump_segs, ss_valid_seg_cnt);
	kfree(ramdump_segs);
mapping_fail:
	unmap_aux_minidump_regions(aux_minidump_data,
+1 −1
Original line number Diff line number Diff line
@@ -140,7 +140,7 @@ static unsigned long offset_translate(loff_t user_offset,
		*data_left);

	if (rd_dev->segments[i].v_address)
		*vaddr = rd_dev->segments[i].v_address + user_offset;
		*vaddr = (void *) rd_dev->segments[i].v_address + user_offset;

	return rd_dev->segments[i].address + user_offset;
}
+1 −1
Original line number Diff line number Diff line
@@ -11,7 +11,7 @@ struct device;
struct ramdump_segment {
	char *name;
	unsigned long address;
	void *v_address;
	volatile void __iomem *v_address;
	unsigned long size;
};