2023-12-13 18:13:53

by Vignesh Viswanathan

[permalink] [raw]
Subject: [PATCH] remoteproc: qcom: q6v5_mpd: Add custom coredump segments

IPQ9574 and IPQ5332 can have multiple reserved memory regions that needs
to be collected as part of the coredump.

Loop through all the regions defined under reserved-memory node in the
devicetree for the remoteproc and add each as a custom segment for
coredump.

Also, update the ELF info for coredump collection for multipd
remoteprocs.

This patch depends on [1] which adds support for IPQ9574 and IPQ5332
remoteproc q5v5_mpd driver.

[1]: https://lore.kernel.org/all/[email protected]/

Signed-off-by: Vignesh Viswanathan <[email protected]>
---
drivers/remoteproc/qcom_q6v5_mpd.c | 71 +++++++++++++++++++++++++++++-
1 file changed, 70 insertions(+), 1 deletion(-)

diff --git a/drivers/remoteproc/qcom_q6v5_mpd.c b/drivers/remoteproc/qcom_q6v5_mpd.c
index 839f6a15b88d..901b0b0da8f2 100644
--- a/drivers/remoteproc/qcom_q6v5_mpd.c
+++ b/drivers/remoteproc/qcom_q6v5_mpd.c
@@ -443,11 +443,77 @@ static unsigned long q6_wcss_panic(struct rproc *rproc)
return qcom_q6v5_panic(&wcss->q6);
}

+static void q6_wcss_copy_segment(struct rproc *rproc,
+ struct rproc_dump_segment *segment,
+ void *dest, size_t offset, size_t size)
+{
+ struct q6_wcss *wcss = rproc->priv;
+ struct device *dev = wcss->dev;
+ int base;
+ void *ptr;
+
+ base = segment->da + offset - wcss->mem_reloc;
+
+ if (base < 0 || base + size > wcss->mem_size) {
+ ptr = devm_ioremap_wc(dev, segment->da, segment->size);
+ memcpy(dest, ptr + offset, size);
+ devm_iounmap(dev, ptr);
+ } else {
+ memcpy(dest, wcss->mem_region + offset, size);
+ }
+}
+
+static int q6_wcss_dump_segments(struct rproc *rproc,
+ const struct firmware *fw)
+{
+ struct device *dev = rproc->dev.parent;
+ struct reserved_mem *rmem = NULL;
+ struct device_node *node;
+ int num_segs, index = 0;
+ int ret;
+
+ /* Parse through additional reserved memory regions for the rproc
+ * and add them to the coredump segments
+ */
+ num_segs = of_count_phandle_with_args(dev->of_node,
+ "memory-region", NULL);
+ while (index < num_segs) {
+ node = of_parse_phandle(dev->of_node,
+ "memory-region", index);
+ if (!node)
+ return -EINVAL;
+
+ rmem = of_reserved_mem_lookup(node);
+ if (!rmem) {
+ dev_err(dev, "unable to acquire memory-region index %d num_segs %d\n",
+ index, num_segs);
+ return -EINVAL;
+ }
+
+ of_node_put(node);
+
+ dev_dbg(dev, "Adding segment 0x%pa size 0x%pa",
+ &rmem->base, &rmem->size);
+ ret = rproc_coredump_add_custom_segment(rproc,
+ rmem->base,
+ rmem->size,
+ q6_wcss_copy_segment,
+ NULL);
+ if (ret)
+ return ret;
+
+ index++;
+ }
+
+ return 0;
+}
+
static const struct rproc_ops wcss_ops = {
.start = wcss_pd_start,
.stop = wcss_pd_stop,
.load = wcss_pd_load,
.get_boot_addr = rproc_elf_get_boot_addr,
+ .parse_fw = q6_wcss_dump_segments,
};

static const struct rproc_ops q6_wcss_ops = {
@@ -457,6 +523,7 @@ static const struct rproc_ops q6_wcss_ops = {
.load = q6_wcss_load,
.get_boot_addr = rproc_elf_get_boot_addr,
.panic = q6_wcss_panic,
+ .parse_fw = q6_wcss_dump_segments,
};

static int q6_alloc_memory_region(struct q6_wcss *wcss)
@@ -672,6 +739,7 @@ static int q6_register_userpd(struct platform_device *pdev,
goto free_rproc;

rproc->auto_boot = false;
+ rproc_coredump_set_elf_info(rproc, ELFCLASS32, EM_NONE);
ret = rproc_add(rproc);
if (ret)
goto free_rproc;
@@ -731,9 +799,10 @@ static int q6_wcss_probe(struct platform_device *pdev)
goto free_rproc;

qcom_add_glink_subdev(rproc, &wcss->glink_subdev, "q6wcss");
- qcom_add_ssr_subdev(rproc, &wcss->ssr_subdev, "q6wcss");
+ qcom_add_ssr_subdev(rproc, &wcss->ssr_subdev, pdev->name);

rproc->auto_boot = false;
+ rproc_coredump_set_elf_info(rproc, ELFCLASS32, EM_NONE);
ret = rproc_add(rproc);
if (ret)
goto free_rproc;
--
2.41.0