[PATCH 4/4] remoteproc: qcom: pas: Add Glymur OOBMSS coredump support

From: Anvesh Jain P

Date: Fri Oct 09 2026 - 03:20:21 EST


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 <anvesh.p@xxxxxxxxxxxxxxxx>
---
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