[PATCH] remoteproc: qcom: q6v5_mpd: Add custom coredump segments

From: Vignesh Viswanathan
Date: Wed Dec 13 2023 - 13:13:43 EST


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/20231110091939.3025413-1-quic_mmanikan@xxxxxxxxxxx/

Signed-off-by: Vignesh Viswanathan <quic_viswanat@xxxxxxxxxxx>
---
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