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_mmani...@quicinc.com/

Signed-off-by: Vignesh Viswanathan <quic_viswa...@quicinc.com>
---
 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


Reply via email to