]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
remoteproc: qcom: Register segments for core dump
authorSarangdhar Joshi <spjoshi@codeaurora.org>
Sat, 6 Jan 2018 00:04:20 +0000 (16:04 -0800)
committerBjorn Andersson <bjorn.andersson@linaro.org>
Mon, 12 Feb 2018 19:05:46 +0000 (11:05 -0800)
Register MDT segments with the remoteproc core dump functionality in
order to include them in a core dump, in case of a recovery of the remote
processor.

Signed-off-by: Sarangdhar Joshi <spjoshi@codeaurora.org>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
drivers/remoteproc/qcom_adsp_pil.c
drivers/remoteproc/qcom_common.c
drivers/remoteproc/qcom_common.h
drivers/remoteproc/qcom_wcnss.c

index ca2bda9bc71d6c9e2ace83f1a1438da2a37b3f1f..ac8f9a77b82108e59f31d08ee8b2d56035070769 100644 (file)
@@ -179,6 +179,7 @@ static const struct rproc_ops adsp_ops = {
        .start = adsp_start,
        .stop = adsp_stop,
        .da_to_va = adsp_da_to_va,
+       .parse_fw = qcom_register_dump_segments,
        .load = adsp_load,
 };
 
index 00602499713f43e3b82d92852c4225ab748fe0ef..b7d53a9cf21ff75fe65df9eda17681bfa76368b4 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/remoteproc.h>
 #include <linux/rpmsg/qcom_glink.h>
 #include <linux/rpmsg/qcom_smd.h>
+#include <linux/soc/qcom/mdt_loader.h>
 
 #include "remoteproc_internal.h"
 #include "qcom_common.h"
@@ -79,6 +80,49 @@ void qcom_remove_glink_subdev(struct rproc *rproc, struct qcom_rproc_glink *glin
 }
 EXPORT_SYMBOL_GPL(qcom_remove_glink_subdev);
 
+/**
+ * qcom_register_dump_segments() - register segments for coredump
+ * @rproc:     remoteproc handle
+ * @fw:                firmware header
+ *
+ * Register all segments of the ELF in the remoteproc coredump segment list
+ *
+ * Return: 0 on success, negative errno on failure.
+ */
+int qcom_register_dump_segments(struct rproc *rproc,
+                               const struct firmware *fw)
+{
+       const struct elf32_phdr *phdrs;
+       const struct elf32_phdr *phdr;
+       const struct elf32_hdr *ehdr;
+       int ret;
+       int i;
+
+       ehdr = (struct elf32_hdr *)fw->data;
+       phdrs = (struct elf32_phdr *)(ehdr + 1);
+
+       for (i = 0; i < ehdr->e_phnum; i++) {
+               phdr = &phdrs[i];
+
+               if (phdr->p_type != PT_LOAD)
+                       continue;
+
+               if ((phdr->p_flags & QCOM_MDT_TYPE_MASK) == QCOM_MDT_TYPE_HASH)
+                       continue;
+
+               if (!phdr->p_memsz)
+                       continue;
+
+               ret = rproc_coredump_add_segment(rproc, phdr->p_paddr,
+                                                phdr->p_memsz);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(qcom_register_dump_segments);
+
 static int smd_subdev_probe(struct rproc_subdev *subdev)
 {
        struct qcom_rproc_subdev *smd = to_smd_subdev(subdev);
index 728be9834d8b2196eac80865f261acd40ffc1b87..7e614520fb691ab35a1fe5d20d6c5991b8c0ae19 100644 (file)
@@ -30,6 +30,8 @@ struct qcom_rproc_ssr {
 void qcom_add_glink_subdev(struct rproc *rproc, struct qcom_rproc_glink *glink);
 void qcom_remove_glink_subdev(struct rproc *rproc, struct qcom_rproc_glink *glink);
 
+int qcom_register_dump_segments(struct rproc *rproc, const struct firmware *fw);
+
 void qcom_add_smd_subdev(struct rproc *rproc, struct qcom_rproc_subdev *smd);
 void qcom_remove_smd_subdev(struct rproc *rproc, struct qcom_rproc_subdev *smd);
 
index f1ae5ecbc392dce66b184d7a4c09b0ab18b10a84..32a3a53589dcab6fc61560051c63ff4ce5b31928 100644 (file)
@@ -309,6 +309,7 @@ static const struct rproc_ops wcnss_ops = {
        .start = wcnss_start,
        .stop = wcnss_stop,
        .da_to_va = wcnss_da_to_va,
+       .parse_fw = qcom_register_dump_segments,
        .load = wcnss_load,
 };