drivers/firmware/qcom/qcom_scm.c | 10 +++++++--- drivers/remoteproc/qcom_q6v5_pas.c | 3 +++ include/linux/firmware/qcom/qcom_pas.h | 1 + 3 files changed, 11 insertions(+), 3 deletions(-)
The PAS image initialization path always retains the metadata buffer
when a valid qcom_scm_pas_context is provided, even if the caller does
not require it. This implicit behavior leads to unclear buffer ownership
and forces new users of qcom_mdt_pas_load() to manually release
metadata, which is error‑ prone and incorrect.
Add a keep_mdt_buf flag to struct qcom_scm_pas_context to make metadata
retention explicit. Metadata buffers are now freed by default and are
only preserved when this flag is set. qcom_q6v5_pas enables this during
probe for contexts that require retained metadata for subsequent PAS
operations, while existing callers continue to work unchanged.
Signed-off-by: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com>
---
Changes in v7:
- Since qcom_scm_pas_context is removed, v6 needs to be rebased removing
the changes related to it.
- Link to v6: https://lore.kernel.org/lkml/20260805133759.2790755-1-mukesh.ojha@oss.qualcomm.com/
Changes in v6:
- Other patches from the series is merged.
- Removed dependency on below series by adding keep_mdt_buf
into qcom_scm_pas_context structure as well.
https://lore.kernel.org/lkml/20260702115835.167602-1-sumit.garg@kernel.org/
- Addressed minor comment on the documentationi.
- Link to v5: 6/6 of https://lore.kernel.org/lkml/20260724182858.1868271-7-mukesh.ojha@oss.qualcomm.com/
drivers/firmware/qcom/qcom_scm.c | 10 +++++++---
drivers/remoteproc/qcom_q6v5_pas.c | 3 +++
include/linux/firmware/qcom/qcom_pas.h | 1 +
3 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c
index 28411a76d1bf..81bb38401d54 100644
--- a/drivers/firmware/qcom/qcom_scm.c
+++ b/drivers/firmware/qcom/qcom_scm.c
@@ -625,7 +625,7 @@ static int qcom_scm_pas_prep_and_init_image(struct device *dev,
mdata_phys = qcom_tzmem_to_phys(mdata_buf);
ret = __qcom_scm_pas_init_image(dev, ctx->pas_id, mdata_phys, &res);
- if (ret < 0)
+ if (ret < 0 || !ctx->keep_mdt_buf)
qcom_tzmem_free(mdata_buf);
else
ctx->ptr = mdata_buf;
@@ -664,9 +664,13 @@ static int qcom_scm_pas_init_image(struct device *dev, u32 pas_id,
memcpy(mdata_buf, metadata, size);
ret = __qcom_scm_pas_init_image(dev, pas_id, mdata_phys, &res);
- if (ret < 0 || !ctx) {
+
+ /*
+ * free the metadata on error or if client didn't request us to keep it.
+ */
+ if (ret < 0 || !ctx || !ctx->keep_mdt_buf) {
dma_free_coherent(dev, size, mdata_buf, mdata_phys);
- } else if (ctx) {
+ } else {
ctx->ptr = mdata_buf;
ctx->phys = mdata_phys;
ctx->size = size;
diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
index 96a2436b777d..40cd0f101a67 100644
--- a/drivers/remoteproc/qcom_q6v5_pas.c
+++ b/drivers/remoteproc/qcom_q6v5_pas.c
@@ -733,6 +733,7 @@ static int qcom_pas_alloc_memory_region(struct qcom_pas *pas)
if (IS_ERR(pas->pas_ctx))
return PTR_ERR(pas->pas_ctx);
+ pas->pas_ctx->keep_mdt_buf = true;
if (!pas->dtb_pas_id)
return 0;
@@ -751,6 +752,8 @@ static int qcom_pas_alloc_memory_region(struct qcom_pas *pas)
if (IS_ERR(pas->dtb_pas_ctx))
return PTR_ERR(pas->dtb_pas_ctx);
+ pas->dtb_pas_ctx->keep_mdt_buf = true;
+
return 0;
}
diff --git a/include/linux/firmware/qcom/qcom_pas.h b/include/linux/firmware/qcom/qcom_pas.h
index fb2ec3be6a16..1d132e89536e 100644
--- a/include/linux/firmware/qcom/qcom_pas.h
+++ b/include/linux/firmware/qcom/qcom_pas.h
@@ -22,6 +22,7 @@ struct qcom_pas_context {
dma_addr_t phys;
ssize_t size;
bool use_tzmem;
+ bool keep_mdt_buf;
};
static inline void __iomem *qcom_pas_ctx_map(struct qcom_pas_context *ctx)
--
2.55.0
Hi Mukesh,
On Sun, Sep 20, 2026 at 1:19 PM Mukesh Ojha
<mukesh.ojha@oss.qualcomm.com> wrote:
>
> The PAS image initialization path always retains the metadata buffer
> when a valid qcom_scm_pas_context is provided, even if the caller does
> not require it. This implicit behavior leads to unclear buffer ownership
> and forces new users of qcom_mdt_pas_load() to manually release
> metadata, which is error‑ prone and incorrect.
>
> Add a keep_mdt_buf flag to struct qcom_scm_pas_context to make metadata
> retention explicit. Metadata buffers are now freed by default and are
> only preserved when this flag is set. qcom_q6v5_pas enables this during
> probe for contexts that require retained metadata for subsequent PAS
> operations, while existing callers continue to work unchanged.
>
> Signed-off-by: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com>
> ---
> Changes in v7:
> - Since qcom_scm_pas_context is removed, v6 needs to be rebased removing
> the changes related to it.
> - Link to v6: https://lore.kernel.org/lkml/20260805133759.2790755-1-mukesh.ojha@oss.qualcomm.com/
>
Please update the commit message to use qcom_pas_context instead.
Also, why don't we handle this case in the generic PAS wrapper since
it sounds like it would affect OP-TEE backend too?
-Sumit
> Changes in v6:
> - Other patches from the series is merged.
> - Removed dependency on below series by adding keep_mdt_buf
> into qcom_scm_pas_context structure as well.
> https://lore.kernel.org/lkml/20260702115835.167602-1-sumit.garg@kernel.org/
> - Addressed minor comment on the documentationi.
> - Link to v5: 6/6 of https://lore.kernel.org/lkml/20260724182858.1868271-7-mukesh.ojha@oss.qualcomm.com/
>
>
>
> drivers/firmware/qcom/qcom_scm.c | 10 +++++++---
> drivers/remoteproc/qcom_q6v5_pas.c | 3 +++
> include/linux/firmware/qcom/qcom_pas.h | 1 +
> 3 files changed, 11 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c
> index 28411a76d1bf..81bb38401d54 100644
> --- a/drivers/firmware/qcom/qcom_scm.c
> +++ b/drivers/firmware/qcom/qcom_scm.c
> @@ -625,7 +625,7 @@ static int qcom_scm_pas_prep_and_init_image(struct device *dev,
> mdata_phys = qcom_tzmem_to_phys(mdata_buf);
>
> ret = __qcom_scm_pas_init_image(dev, ctx->pas_id, mdata_phys, &res);
> - if (ret < 0)
> + if (ret < 0 || !ctx->keep_mdt_buf)
> qcom_tzmem_free(mdata_buf);
> else
> ctx->ptr = mdata_buf;
> @@ -664,9 +664,13 @@ static int qcom_scm_pas_init_image(struct device *dev, u32 pas_id,
> memcpy(mdata_buf, metadata, size);
>
> ret = __qcom_scm_pas_init_image(dev, pas_id, mdata_phys, &res);
> - if (ret < 0 || !ctx) {
> +
> + /*
> + * free the metadata on error or if client didn't request us to keep it.
> + */
> + if (ret < 0 || !ctx || !ctx->keep_mdt_buf) {
> dma_free_coherent(dev, size, mdata_buf, mdata_phys);
> - } else if (ctx) {
> + } else {
> ctx->ptr = mdata_buf;
> ctx->phys = mdata_phys;
> ctx->size = size;
> diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
> index 96a2436b777d..40cd0f101a67 100644
> --- a/drivers/remoteproc/qcom_q6v5_pas.c
> +++ b/drivers/remoteproc/qcom_q6v5_pas.c
> @@ -733,6 +733,7 @@ static int qcom_pas_alloc_memory_region(struct qcom_pas *pas)
> if (IS_ERR(pas->pas_ctx))
> return PTR_ERR(pas->pas_ctx);
>
> + pas->pas_ctx->keep_mdt_buf = true;
> if (!pas->dtb_pas_id)
> return 0;
>
> @@ -751,6 +752,8 @@ static int qcom_pas_alloc_memory_region(struct qcom_pas *pas)
> if (IS_ERR(pas->dtb_pas_ctx))
> return PTR_ERR(pas->dtb_pas_ctx);
>
> + pas->dtb_pas_ctx->keep_mdt_buf = true;
> +
> return 0;
> }
>
> diff --git a/include/linux/firmware/qcom/qcom_pas.h b/include/linux/firmware/qcom/qcom_pas.h
> index fb2ec3be6a16..1d132e89536e 100644
> --- a/include/linux/firmware/qcom/qcom_pas.h
> +++ b/include/linux/firmware/qcom/qcom_pas.h
> @@ -22,6 +22,7 @@ struct qcom_pas_context {
> dma_addr_t phys;
> ssize_t size;
> bool use_tzmem;
> + bool keep_mdt_buf;
> };
>
> static inline void __iomem *qcom_pas_ctx_map(struct qcom_pas_context *ctx)
> --
> 2.55.0
>
© 2016 - 2026 Red Hat, Inc.