|
@@ -1064,10 +1064,52 @@ static void *q6v5_da_to_va(struct rproc *rproc, u64 da, int len)
|
|
|
return qproc->mpss_region + offset;
|
|
|
}
|
|
|
|
|
|
+static int qcom_q6v5_register_dump_segments(struct rproc *rproc,
|
|
|
+ const struct firmware *mba_fw)
|
|
|
+{
|
|
|
+ const struct firmware *fw;
|
|
|
+ const struct elf32_phdr *phdrs;
|
|
|
+ const struct elf32_phdr *phdr;
|
|
|
+ const struct elf32_hdr *ehdr;
|
|
|
+ struct q6v5 *qproc = rproc->priv;
|
|
|
+ unsigned long i;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ ret = request_firmware(&fw, "modem.mdt", qproc->dev);
|
|
|
+ if (ret < 0) {
|
|
|
+ dev_err(qproc->dev, "unable to load modem.mdt\n");
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ ehdr = (struct elf32_hdr *)fw->data;
|
|
|
+ phdrs = (struct elf32_phdr *)(ehdr + 1);
|
|
|
+ qproc->dump_complete_mask = 0;
|
|
|
+
|
|
|
+ for (i = 0; i < ehdr->e_phnum; i++) {
|
|
|
+ phdr = &phdrs[i];
|
|
|
+
|
|
|
+ if (!q6v5_phdr_valid(phdr))
|
|
|
+ continue;
|
|
|
+
|
|
|
+ ret = rproc_coredump_add_custom_segment(rproc, phdr->p_paddr,
|
|
|
+ phdr->p_memsz,
|
|
|
+ qcom_q6v5_dump_segment,
|
|
|
+ (void *)i);
|
|
|
+ if (ret)
|
|
|
+ break;
|
|
|
+
|
|
|
+ qproc->dump_complete_mask |= BIT(i);
|
|
|
+ }
|
|
|
+
|
|
|
+ release_firmware(fw);
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
static const struct rproc_ops q6v5_ops = {
|
|
|
.start = q6v5_start,
|
|
|
.stop = q6v5_stop,
|
|
|
.da_to_va = q6v5_da_to_va,
|
|
|
+ .parse_fw = qcom_q6v5_register_dump_segments,
|
|
|
.load = q6v5_load,
|
|
|
};
|
|
|
|