aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/remoteproc/qcom_common.c
diff options
context:
space:
mode:
authorSarangdhar Joshi <spjoshi@codeaurora.org>2018-01-05 16:04:20 -0800
committerBjorn Andersson <bjorn.andersson@linaro.org>2018-02-12 11:05:46 -0800
commitdcb57ed43d9ec5e16628c337143cd6b387f42778 (patch)
treef62daf90f0f53b6c78530c8b0af682f19ff49ebb /drivers/remoteproc/qcom_common.c
parentsoc: qcom: mdt-loader: Return relocation base (diff)
downloadlinux-dev-dcb57ed43d9ec5e16628c337143cd6b387f42778.tar.xz
linux-dev-dcb57ed43d9ec5e16628c337143cd6b387f42778.zip
remoteproc: qcom: Register segments for core dump
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>
Diffstat (limited to 'drivers/remoteproc/qcom_common.c')
-rw-r--r--drivers/remoteproc/qcom_common.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/drivers/remoteproc/qcom_common.c b/drivers/remoteproc/qcom_common.c
index 00602499713f..b7d53a9cf21f 100644
--- a/drivers/remoteproc/qcom_common.c
+++ b/drivers/remoteproc/qcom_common.c
@@ -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);