remoteproc: qcom: q6v5_mpd: Add custom coredump segments

Message ID 20231213181314.271484-1-quic_viswanat@quicinc.com
State New
Headers
Series remoteproc: qcom: q6v5_mpd: Add custom coredump segments |

Commit Message

Vignesh Viswanathan Dec. 13, 2023, 6:13 p.m. UTC
  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@quicinc.com/

Signed-off-by: Vignesh Viswanathan <quic_viswanat@quicinc.com>
---
 drivers/remoteproc/qcom_q6v5_mpd.c | 71 +++++++++++++++++++++++++++++-
 1 file changed, 70 insertions(+), 1 deletion(-)
  

Patch

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;