Add coredump support for the secure and non-secure OOBMSS carveouts. Register fixed dump segments at probe time for attached-state recovery.
Signed-off-by: Anvesh Jain P <[email protected]> --- drivers/remoteproc/qcom_q6v5_pas.c | 85 ++++++++++++++++++++++++++++++++++---- 1 file changed, 77 insertions(+), 8 deletions(-) diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c index 31fdde351bed..0dc9985f01f9 100644 --- a/drivers/remoteproc/qcom_q6v5_pas.c +++ b/drivers/remoteproc/qcom_q6v5_pas.c @@ -117,6 +117,7 @@ struct qcom_pas { phys_addr_t region_assign_phys[MAX_ASSIGN_COUNT]; void __iomem *mem_region; + void __iomem *secondary_mem_region; size_t mem_size; size_t dtb_mem_size; @@ -162,6 +163,28 @@ static void qcom_pas_segment_dump(struct rproc *rproc, memcpy_fromio(dest, pas->mem_region + total_offset, size); } +static bool qcom_pas_has_secondary(const struct qcom_pas *pas) +{ + return pas->secondary_pas_id && pas->secondary_dtb_pas_id; +} + +static int qcom_pas_register_dump_segments(struct rproc *rproc, + struct qcom_pas *pas) +{ + int ret; + + ret = rproc_coredump_add_segment(rproc, pas->mem_phys, pas->mem_size); + if (ret) + return ret; + + ret = rproc_coredump_add_segment(rproc, pas->secondary_mem_phys, + pas->secondary_mem_size); + if (ret) + rproc_coredump_cleanup(rproc); + + return ret; +} + static void qcom_pas_minidump(struct rproc *rproc) { struct qcom_pas *pas = rproc->priv; @@ -572,16 +595,29 @@ static int qcom_pas_stop(struct rproc *rproc) static void *qcom_pas_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem) { struct qcom_pas *pas = rproc->priv; - int offset; + phys_addr_t base; + void __iomem *region; + + if (da >= pas->mem_reloc && len <= pas->mem_size && + da - pas->mem_reloc <= pas->mem_size - len) { + base = pas->mem_reloc; + region = pas->mem_region; + } else if (da >= pas->secondary_mem_reloc && + len <= pas->secondary_mem_size && + da - pas->secondary_mem_reloc <= pas->secondary_mem_size - len) { + base = pas->secondary_mem_reloc; + region = pas->secondary_mem_region; + } else { + return NULL; + } - offset = da - pas->mem_reloc; - if (offset < 0 || offset + len > pas->mem_size) + if (!region) return NULL; if (is_iomem) *is_iomem = true; - return (__force void *)pas->mem_region + offset; + return (__force void *)region + (da - base); } static int qcom_pas_parse_firmware(struct rproc *rproc, const struct firmware *fw) @@ -593,10 +629,21 @@ static int qcom_pas_parse_firmware(struct rproc *rproc, const struct firmware *f size_t table_sz; int ret; - ret = qcom_register_dump_segments(rproc, fw); - if (ret) { - dev_err(pas->dev, "Error in registering dump segments\n"); - return ret; + if (qcom_pas_has_secondary(pas)) { + if (list_empty(&rproc->dump_segments)) { + ret = qcom_pas_register_dump_segments(rproc, pas); + if (ret) { + dev_err(pas->dev, + "failed to register dump segments: %d\n", ret); + return ret; + } + } + } else { + ret = qcom_register_dump_segments(rproc, fw); + if (ret) { + dev_err(pas->dev, "Error in registering dump segments\n"); + return ret; + } } if (!rproc->has_iommu) @@ -715,7 +762,22 @@ static void qcom_pas_coredump(struct rproc *rproc) if (!pas->mem_region) return; + if (qcom_pas_has_secondary(pas)) { + pas->secondary_mem_region = + qcom_pas_ctx_map(pas->secondary_pas_ctx); + if (!pas->secondary_mem_region) { + dev_err(pas->dev, "unable to map secondary memory for coredump\n"); + iounmap(pas->mem_region); + pas->mem_region = NULL; + return; + } + } + rproc_coredump(rproc); + if (pas->secondary_mem_region) { + iounmap(pas->secondary_mem_region); + pas->secondary_mem_region = NULL; + } iounmap(pas->mem_region); pas->mem_region = NULL; } @@ -1130,6 +1192,12 @@ static int qcom_pas_probe(struct platform_device *pdev) if (desc->early_boot) pas->rproc->state = RPROC_DETACHED; + if (qcom_pas_has_secondary(pas)) { + ret = qcom_pas_register_dump_segments(rproc, pas); + if (ret) + goto remove_ssr_sysmon; + } + ret = rproc_add(rproc); if (ret) goto remove_ssr_sysmon; @@ -1141,6 +1209,7 @@ static int qcom_pas_probe(struct platform_device *pdev) return 0; remove_ssr_sysmon: + rproc_coredump_cleanup(rproc); qcom_remove_ssr_subdev(rproc, &pas->ssr_subdev); qcom_remove_sysmon_subdev(pas->sysmon); deinit_remove_pdm_smd_glink: -- 2.34.1

