From e042a450aa2b4bc1588f308754f68d00b6786123 Mon Sep 17 00:00:00 2001 From: Vinayak Katoch Date: Thu, 28 May 2026 01:08:12 +0530 Subject: [PATCH 1/9] Revert "FROMLIST: misc: fastrpc: Allow fastrpc_buf_free() to accept NULL" This change corresponds to the v4 version shared with the upstream community. Revert it to apply the complete v6 revision, which includes additional fixes and updates not present in the earlier version. This reverts commit 0aef3f9745233d4f40710a31d0581bfb27994e92. Signed-off-by: Vinayak Katoch --- drivers/misc/fastrpc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index da5ab16d4ea8e..5edbcf2d44d9d 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -416,9 +416,6 @@ static int fastrpc_map_lookup(struct fastrpc_user *fl, int fd, static void fastrpc_buf_free(struct fastrpc_buf *buf) { - if (!buf) - return; - dma_free_coherent(buf->dev, buf->size, buf->virt, FASTRPC_PHYS(buf->phys)); kfree(buf); @@ -557,7 +554,8 @@ static void fastrpc_context_free(struct kref *ref) for (i = 0; i < ctx->nbufs; i++) fastrpc_map_put(ctx->maps[i]); - fastrpc_buf_free(ctx->buf); + if (ctx->buf) + fastrpc_buf_free(ctx->buf); spin_lock_irqsave(&cctx->lock, flags); idr_remove(&cctx->ctx_idr, ctx->ctxid >> 8); From 42df760574e426bfb33d4256007d1210f5288f10 Mon Sep 17 00:00:00 2001 From: Vinayak Katoch Date: Thu, 28 May 2026 01:18:23 +0530 Subject: [PATCH 2/9] Revert "FROMLIST: misc: fastrpc: Allocate entire reserved memory for Audio PD in probe" This change corresponds to the v4 version shared with the upstream community. Revert it to apply the complete v6 revision, which includes additional fixes and updates not present in the earlier version. This reverts commit ba1bd9d4712e17fe412a41b0193de58c2548017d. Signed-off-by: Vinayak Katoch --- drivers/misc/fastrpc.c | 101 ++++++++++++++++++++--------------------- 1 file changed, 50 insertions(+), 51 deletions(-) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index 5edbcf2d44d9d..51eb7b49102bd 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -294,8 +294,6 @@ struct fastrpc_channel_ctx { struct kref refcount; /* Flag if dsp attributes are cached */ bool valid_attributes; - /* Flag if audio PD init mem was allocated */ - bool audio_init_mem; u32 dsp_attributes[FASTRPC_MAX_DSP_ATTRIBUTES]; struct fastrpc_device *secure_fdevice; struct fastrpc_device *fdevice; @@ -1417,16 +1415,15 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl, struct fastrpc_init_create_static init; struct fastrpc_invoke_args *args; struct fastrpc_phy_page pages[1]; - struct fastrpc_channel_ctx *cctx = fl->cctx; char *name; int err; + bool scm_done = false; struct { int client_id; u32 namelen; u32 pageslen; } inbuf; u32 sc; - unsigned long flags; args = kcalloc(FASTRPC_CREATE_STATIC_PROCESS_NARGS, sizeof(*args), GFP_KERNEL); if (!args) @@ -1450,6 +1447,29 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl, inbuf.client_id = fl->client_id; inbuf.namelen = init.namelen; inbuf.pageslen = 0; + if (!fl->cctx->remote_heap) { + err = fastrpc_remote_heap_alloc(fl, fl->sctx->dev, init.memlen, + &fl->cctx->remote_heap); + if (err) + goto err_name; + + /* Map if we have any heap VMIDs associated with this ADSP Static Process. */ + if (fl->cctx->vmcount) { + u64 src_perms = BIT(QCOM_SCM_VMID_HLOS); + + err = qcom_scm_assign_mem(fl->cctx->remote_heap->phys, + (u64)fl->cctx->remote_heap->size, + &src_perms, + fl->cctx->vmperms, fl->cctx->vmcount); + if (err) { + dev_err(fl->sctx->dev, "Failed to assign memory with phys 0x%llx size 0x%llx err %d\n", + fl->cctx->remote_heap->phys, fl->cctx->remote_heap->size, err); + goto err_map; + } + scm_done = true; + inbuf.pageslen = 1; + } + } fl->pd = USER_PD; @@ -1461,25 +1481,8 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl, args[1].length = inbuf.namelen; args[1].fd = -1; - spin_lock_irqsave(&cctx->lock, flags); - if (!fl->cctx->audio_init_mem) { - if (!fl->cctx->remote_heap || - !fl->cctx->remote_heap->phys || - !fl->cctx->remote_heap->size) { - spin_unlock_irqrestore(&cctx->lock, flags); - err = -ENOMEM; - goto err; - } - - pages[0].addr = fl->cctx->remote_heap->phys; - pages[0].size = fl->cctx->remote_heap->size; - fl->cctx->audio_init_mem = true; - inbuf.pageslen = 1; - } else { - pages[0].addr = 0; - pages[0].size = 0; - } - spin_unlock_irqrestore(&cctx->lock, flags); + pages[0].addr = fl->cctx->remote_heap->phys; + pages[0].size = fl->cctx->remote_heap->size; args[2].ptr = (u64)(uintptr_t) pages; args[2].length = sizeof(*pages); @@ -1497,7 +1500,26 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl, return 0; err_invoke: - fl->cctx->audio_init_mem = false; + if (fl->cctx->vmcount && scm_done) { + u64 src_perms = 0; + struct qcom_scm_vmperm dst_perms; + u32 i; + + for (i = 0; i < fl->cctx->vmcount; i++) + src_perms |= BIT(fl->cctx->vmperms[i].vmid); + + dst_perms.vmid = QCOM_SCM_VMID_HLOS; + dst_perms.perm = QCOM_SCM_PERM_RWX; + err = qcom_scm_assign_mem(fl->cctx->remote_heap->phys, + (u64)fl->cctx->remote_heap->size, + &src_perms, &dst_perms, 1); + if (err) + dev_err(fl->sctx->dev, "Failed to assign memory phys 0x%llx size 0x%llx err %d\n", + fl->cctx->remote_heap->phys, fl->cctx->remote_heap->size, err); + } +err_map: + fastrpc_buf_free(fl->cctx->remote_heap); +err_name: kfree(name); err: kfree(args); @@ -2445,7 +2467,7 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev) } } - if (domain_id == SDSP_DOMAIN_ID || domain_id == ADSP_DOMAIN_ID) { + if (domain_id == SDSP_DOMAIN_ID) { struct resource res; u64 src_perms; @@ -2458,15 +2480,7 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev) if (err) goto err_free_data; } - if (domain_id == ADSP_DOMAIN_ID) { - data->remote_heap = - kzalloc(sizeof(*data->remote_heap), GFP_KERNEL); - if (!data->remote_heap) - return -ENOMEM; - - data->remote_heap->phys = res.start; - data->remote_heap->size = resource_size(&res); - } + } secure_dsp = !(of_property_read_bool(rdev->of_node, "qcom,non-secure-domain")); @@ -2546,7 +2560,6 @@ static void fastrpc_rpmsg_remove(struct rpmsg_device *rpdev) struct fastrpc_buf *buf, *b; struct fastrpc_user *user; unsigned long flags; - int err; /* No invocations past this point */ spin_lock_irqsave(&cctx->lock, flags); @@ -2564,22 +2577,8 @@ static void fastrpc_rpmsg_remove(struct rpmsg_device *rpdev) list_for_each_entry_safe(buf, b, &cctx->invoke_interrupted_mmaps, node) list_del(&buf->node); - if (cctx->remote_heap && cctx->vmcount) { - u64 src_perms = 0; - struct qcom_scm_vmperm dst_perms; - - for (u32 i = 0; i < cctx->vmcount; i++) - src_perms |= BIT(cctx->vmperms[i].vmid); - - dst_perms.vmid = QCOM_SCM_VMID_HLOS; - dst_perms.perm = QCOM_SCM_PERM_RWX; - - err = qcom_scm_assign_mem(cctx->remote_heap->phys, - cctx->remote_heap->size, &src_perms, - &dst_perms, 1); - if (!err) - fastrpc_buf_free(cctx->remote_heap); - } + if (cctx->remote_heap) + fastrpc_buf_free(cctx->remote_heap); of_platform_depopulate(&rpdev->dev); From b6efbd9293a29ae4baccc10f8ed6ca0417416745 Mon Sep 17 00:00:00 2001 From: Vinayak Katoch Date: Thu, 28 May 2026 01:19:10 +0530 Subject: [PATCH 3/9] Revert "FROMLIST: misc: fastrpc: Remove buffer from list prior to unmap operation" This change corresponds to the v4 version shared with the upstream community. Revert it to apply the complete v6 revision, which includes additional fixes and updates not present in the earlier version. This reverts commit 3ca00e4f7b860349e4c4ef1771405368be15faa6. Signed-off-by: Vinayak Katoch --- drivers/misc/fastrpc.c | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index 51eb7b49102bd..b241593e2cd84 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -1960,6 +1960,9 @@ static int fastrpc_req_munmap_impl(struct fastrpc_user *fl, struct fastrpc_buf * &args[0]); if (!err) { dev_dbg(dev, "unmmap\tpt 0x%09lx OK\n", buf->raddr); + spin_lock(&fl->lock); + list_del(&buf->node); + spin_unlock(&fl->lock); fastrpc_buf_free(buf); } else { dev_err(dev, "unmmap\tpt 0x%09lx ERROR\n", buf->raddr); @@ -1973,7 +1976,6 @@ static int fastrpc_req_munmap(struct fastrpc_user *fl, char __user *argp) struct fastrpc_buf *buf = NULL, *iter, *b; struct fastrpc_req_munmap req; struct device *dev = fl->sctx->dev; - int err; if (copy_from_user(&req, argp, sizeof(req))) return -EFAULT; @@ -1981,7 +1983,6 @@ static int fastrpc_req_munmap(struct fastrpc_user *fl, char __user *argp) spin_lock(&fl->lock); list_for_each_entry_safe(iter, b, &fl->mmaps, node) { if ((iter->raddr == req.vaddrout) && (iter->size == req.size)) { - list_del(&iter->node); buf = iter; break; } @@ -1994,14 +1995,7 @@ static int fastrpc_req_munmap(struct fastrpc_user *fl, char __user *argp) return -EINVAL; } - err = fastrpc_req_munmap_impl(fl, buf); - if (err) { - spin_lock(&fl->lock); - list_add_tail(&buf->node, &fl->mmaps); - spin_unlock(&fl->lock); - } - - return err; + return fastrpc_req_munmap_impl(fl, buf); } static int fastrpc_req_mmap(struct fastrpc_user *fl, char __user *argp) @@ -2091,17 +2085,14 @@ static int fastrpc_req_mmap(struct fastrpc_user *fl, char __user *argp) if (copy_to_user((void __user *)argp, &req, sizeof(req))) { err = -EFAULT; - goto err_copy; + goto err_assign; } dev_dbg(dev, "mmap\t\tpt 0x%09lx OK [len 0x%08llx]\n", buf->raddr, buf->size); return 0; -err_copy: - spin_lock(&fl->lock); - list_del(&buf->node); - spin_unlock(&fl->lock); + err_assign: fastrpc_req_munmap_impl(fl, buf); From 6976f48846245d0008680034d699d42da7f3e147 Mon Sep 17 00:00:00 2001 From: Vinayak Katoch Date: Thu, 28 May 2026 01:19:58 +0530 Subject: [PATCH 4/9] Revert "FROMLIST: misc: fastrpc: Fix initial memory allocation for Audio PD memory pool" This change corresponds to the v4 version shared with the upstream community. Revert it to apply the complete v6 revision, which includes additional fixes and updates not present in the earlier version. This reverts commit d782578fdbda4e8144078704b692461a725b8af0. Signed-off-by: Vinayak Katoch --- drivers/misc/fastrpc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index b241593e2cd84..86dc3e0da9862 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -1444,9 +1444,7 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl, err = PTR_ERR(name); goto err; } - inbuf.client_id = fl->client_id; - inbuf.namelen = init.namelen; - inbuf.pageslen = 0; + if (!fl->cctx->remote_heap) { err = fastrpc_remote_heap_alloc(fl, fl->sctx->dev, init.memlen, &fl->cctx->remote_heap); @@ -1467,10 +1465,12 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl, goto err_map; } scm_done = true; - inbuf.pageslen = 1; } } + inbuf.client_id = fl->client_id; + inbuf.namelen = init.namelen; + inbuf.pageslen = 0; fl->pd = USER_PD; args[0].ptr = (u64)(uintptr_t)&inbuf; From ba2e1456af712ff4cf419eae76cb9b9da10597e3 Mon Sep 17 00:00:00 2001 From: Ekansh Gupta Date: Tue, 26 May 2026 19:11:20 +0800 Subject: [PATCH 5/9] FROMLIST: misc: fastrpc: Fix initial memory allocation for Audio PD memory pool The initial buffer allocated for the Audio PD memory pool is never added to the pool because pageslen is set to 0. As a result, the buffer is not registered with Audio PD and is never used, causing a memory leak. Audio PD immediately falls back to allocating memory from the remote heap since the pool starts out empty. Fix this by setting pageslen to 1 so that the initially allocated buffer is correctly registered and becomes part of the Audio PD memory pool. Link: https://lore.kernel.org/all/20260526111124.515-2-jianping.li@oss.qualcomm.com/ Fixes: 0871561055e66 ("misc: fastrpc: Add support for audiopd") Cc: stable@kernel.org Signed-off-by: Ekansh Gupta Signed-off-by: Jianping Li Signed-off-by: Vinayak Katoch --- drivers/misc/fastrpc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index 86dc3e0da9862..b241593e2cd84 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -1444,7 +1444,9 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl, err = PTR_ERR(name); goto err; } - + inbuf.client_id = fl->client_id; + inbuf.namelen = init.namelen; + inbuf.pageslen = 0; if (!fl->cctx->remote_heap) { err = fastrpc_remote_heap_alloc(fl, fl->sctx->dev, init.memlen, &fl->cctx->remote_heap); @@ -1465,12 +1467,10 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl, goto err_map; } scm_done = true; + inbuf.pageslen = 1; } } - inbuf.client_id = fl->client_id; - inbuf.namelen = init.namelen; - inbuf.pageslen = 0; fl->pd = USER_PD; args[0].ptr = (u64)(uintptr_t)&inbuf; From e2b9a15188f07900d825393f4c311200657df858 Mon Sep 17 00:00:00 2001 From: Ekansh Gupta Date: Tue, 26 May 2026 19:11:21 +0800 Subject: [PATCH 6/9] FROMLIST: misc: fastrpc: Remove buffer from list prior to unmap operation fastrpc_req_munmap_impl() is called to unmap any buffer. The buffer is getting removed from the list after it is unmapped from DSP. This can create potential race conditions if multiple threads invoke unmap concurrently, where one thread may remove the entry from the list while another thread's unmap operation is still ongoing. Fix this by removing the buffer entry from the list before calling the unmap operation. If the unmap fails, the entry is re-added to the list so that userspace can retry the unmap, or alternatively, the buffer will be cleaned up during device release when the DSP process is torn down and all DSP-side mappings are freed along with remaining buffers in the list. Link: https://lore.kernel.org/all/20260526111124.515-3-jianping.li@oss.qualcomm.com/ Fixes: 2419e55e532de ("misc: fastrpc: add mmap/unmap support") Cc: stable@kernel.org Signed-off-by: Ekansh Gupta Signed-off-by: Jianping Li Signed-off-by: Vinayak Katoch --- drivers/misc/fastrpc.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index b241593e2cd84..4562e9411a3d7 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -1960,9 +1960,6 @@ static int fastrpc_req_munmap_impl(struct fastrpc_user *fl, struct fastrpc_buf * &args[0]); if (!err) { dev_dbg(dev, "unmmap\tpt 0x%09lx OK\n", buf->raddr); - spin_lock(&fl->lock); - list_del(&buf->node); - spin_unlock(&fl->lock); fastrpc_buf_free(buf); } else { dev_err(dev, "unmmap\tpt 0x%09lx ERROR\n", buf->raddr); @@ -1976,6 +1973,7 @@ static int fastrpc_req_munmap(struct fastrpc_user *fl, char __user *argp) struct fastrpc_buf *buf = NULL, *iter, *b; struct fastrpc_req_munmap req; struct device *dev = fl->sctx->dev; + int err; if (copy_from_user(&req, argp, sizeof(req))) return -EFAULT; @@ -1983,6 +1981,7 @@ static int fastrpc_req_munmap(struct fastrpc_user *fl, char __user *argp) spin_lock(&fl->lock); list_for_each_entry_safe(iter, b, &fl->mmaps, node) { if ((iter->raddr == req.vaddrout) && (iter->size == req.size)) { + list_del(&iter->node); buf = iter; break; } @@ -1995,7 +1994,14 @@ static int fastrpc_req_munmap(struct fastrpc_user *fl, char __user *argp) return -EINVAL; } - return fastrpc_req_munmap_impl(fl, buf); + err = fastrpc_req_munmap_impl(fl, buf); + if (err) { + spin_lock(&fl->lock); + list_add_tail(&buf->node, &fl->mmaps); + spin_unlock(&fl->lock); + } + + return err; } static int fastrpc_req_mmap(struct fastrpc_user *fl, char __user *argp) From 08682f3b10baad5f97833cb69ca5c74816771fdd Mon Sep 17 00:00:00 2001 From: Jianping Li Date: Tue, 26 May 2026 19:11:22 +0800 Subject: [PATCH 7/9] FROMLIST: misc: fastrpc: Fail Audio PD init when reserved memory is missing Audio PD static process creation assumes that a reserved-memory region is defined in DT and exposed via cctx->remote_heap. If reserved-memory is missing or incomplete, the driver may pass invalid address/size information to the DSP, leading to undefined behavior or crashes. Add explicit validation for remote_heap presence and size before sending the memory to DSP, and fail early if the configuration is invalid. Link: https://lore.kernel.org/all/20260526111124.515-4-jianping.li@oss.qualcomm.com/ Fixes: 0871561055e66 ("misc: fastrpc: Add support for audiopd") Cc: stable@kernel.org Signed-off-by: Jianping Li Signed-off-by: Vinayak Katoch --- drivers/misc/fastrpc.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index 4562e9411a3d7..61a0349f7e8ad 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -1425,6 +1425,14 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl, } inbuf; u32 sc; + if (!fl->cctx->remote_heap || + !fl->cctx->remote_heap->phys || + !fl->cctx->remote_heap->size) { + err = -ENOMEM; + dev_dbg(fl->sctx->dev, "remote heap memory region is not added\n"); + return err; + } + args = kcalloc(FASTRPC_CREATE_STATIC_PROCESS_NARGS, sizeof(*args), GFP_KERNEL); if (!args) return -ENOMEM; From d0656f358d4713d4f3d8618a6926727b7b56d382 Mon Sep 17 00:00:00 2001 From: Jianping Li Date: Tue, 26 May 2026 19:11:23 +0800 Subject: [PATCH 8/9] FROMLIST: misc: fastrpc: Allocate entire reserved memory for Audio PD in probe Allocating and freeing Audio PD memory from userspace is unsafe because the kernel cannot reliably determine when the DSP has finished using the memory. Userspace may free buffers while they are still in use by the DSP, and remote free requests cannot be safely trusted. Additionally, the current implementation allows userspace to repeatedly grow the Audio PD heap, but does not support shrinking it. This can lead to unbounded memory usage over time, effectively causing a memory leak. Fix this by allocating the entire Audio PD reserved-memory region during rpmsg probe and tying its lifetime to the rpmsg channel. This removes userspace-controlled alloc/free and ensures that memory is reclaimed only when the DSP process is torn down. Link: https://lore.kernel.org/all/20260526111124.515-5-jianping.li@oss.qualcomm.com/ Fixes: 0871561055e66 ("misc: fastrpc: Add support for audiopd") Cc: stable@kernel.org Signed-off-by: Jianping Li Signed-off-by: Vinayak Katoch --- drivers/misc/fastrpc.c | 93 +++++++++++++++++++----------------------- 1 file changed, 43 insertions(+), 50 deletions(-) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index 61a0349f7e8ad..5a4c5a85b0a21 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -294,6 +294,8 @@ struct fastrpc_channel_ctx { struct kref refcount; /* Flag if dsp attributes are cached */ bool valid_attributes; + /* Flag if audio PD init mem was allocated */ + bool audio_init_mem; u32 dsp_attributes[FASTRPC_MAX_DSP_ATTRIBUTES]; struct fastrpc_device *secure_fdevice; struct fastrpc_device *fdevice; @@ -1415,15 +1417,16 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl, struct fastrpc_init_create_static init; struct fastrpc_invoke_args *args; struct fastrpc_phy_page pages[1]; + struct fastrpc_channel_ctx *cctx = fl->cctx; char *name; int err; - bool scm_done = false; struct { int client_id; u32 namelen; u32 pageslen; } inbuf; u32 sc; + unsigned long flags; if (!fl->cctx->remote_heap || !fl->cctx->remote_heap->phys || @@ -1455,29 +1458,6 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl, inbuf.client_id = fl->client_id; inbuf.namelen = init.namelen; inbuf.pageslen = 0; - if (!fl->cctx->remote_heap) { - err = fastrpc_remote_heap_alloc(fl, fl->sctx->dev, init.memlen, - &fl->cctx->remote_heap); - if (err) - goto err_name; - - /* Map if we have any heap VMIDs associated with this ADSP Static Process. */ - if (fl->cctx->vmcount) { - u64 src_perms = BIT(QCOM_SCM_VMID_HLOS); - - err = qcom_scm_assign_mem(fl->cctx->remote_heap->phys, - (u64)fl->cctx->remote_heap->size, - &src_perms, - fl->cctx->vmperms, fl->cctx->vmcount); - if (err) { - dev_err(fl->sctx->dev, "Failed to assign memory with phys 0x%llx size 0x%llx err %d\n", - fl->cctx->remote_heap->phys, fl->cctx->remote_heap->size, err); - goto err_map; - } - scm_done = true; - inbuf.pageslen = 1; - } - } fl->pd = USER_PD; @@ -1489,8 +1469,17 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl, args[1].length = inbuf.namelen; args[1].fd = -1; - pages[0].addr = fl->cctx->remote_heap->phys; - pages[0].size = fl->cctx->remote_heap->size; + spin_lock_irqsave(&cctx->lock, flags); + if (!fl->cctx->audio_init_mem) { + pages[0].addr = fl->cctx->remote_heap->phys; + pages[0].size = fl->cctx->remote_heap->size; + fl->cctx->audio_init_mem = true; + inbuf.pageslen = 1; + } else { + pages[0].addr = 0; + pages[0].size = 0; + } + spin_unlock_irqrestore(&cctx->lock, flags); args[2].ptr = (u64)(uintptr_t) pages; args[2].length = sizeof(*pages); @@ -1508,26 +1497,7 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl, return 0; err_invoke: - if (fl->cctx->vmcount && scm_done) { - u64 src_perms = 0; - struct qcom_scm_vmperm dst_perms; - u32 i; - - for (i = 0; i < fl->cctx->vmcount; i++) - src_perms |= BIT(fl->cctx->vmperms[i].vmid); - - dst_perms.vmid = QCOM_SCM_VMID_HLOS; - dst_perms.perm = QCOM_SCM_PERM_RWX; - err = qcom_scm_assign_mem(fl->cctx->remote_heap->phys, - (u64)fl->cctx->remote_heap->size, - &src_perms, &dst_perms, 1); - if (err) - dev_err(fl->sctx->dev, "Failed to assign memory phys 0x%llx size 0x%llx err %d\n", - fl->cctx->remote_heap->phys, fl->cctx->remote_heap->size, err); - } -err_map: - fastrpc_buf_free(fl->cctx->remote_heap); -err_name: + fl->cctx->audio_init_mem = false; kfree(name); err: kfree(args); @@ -2472,12 +2442,21 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev) } } - if (domain_id == SDSP_DOMAIN_ID) { + if (domain_id == SDSP_DOMAIN_ID || domain_id == ADSP_DOMAIN_ID) { struct resource res; u64 src_perms; err = of_reserved_mem_region_to_resource(rdev->of_node, 0, &res); if (!err) { + if (domain_id == ADSP_DOMAIN_ID) { + data->remote_heap = + kzalloc(sizeof(*data->remote_heap), GFP_KERNEL); + if (!data->remote_heap) + return -ENOMEM; + + data->remote_heap->phys = res.start; + data->remote_heap->size = resource_size(&res); + } src_perms = BIT(QCOM_SCM_VMID_HLOS); err = qcom_scm_assign_mem(res.start, resource_size(&res), &src_perms, @@ -2485,7 +2464,6 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev) if (err) goto err_free_data; } - } secure_dsp = !(of_property_read_bool(rdev->of_node, "qcom,non-secure-domain")); @@ -2565,6 +2543,7 @@ static void fastrpc_rpmsg_remove(struct rpmsg_device *rpdev) struct fastrpc_buf *buf, *b; struct fastrpc_user *user; unsigned long flags; + int err; /* No invocations past this point */ spin_lock_irqsave(&cctx->lock, flags); @@ -2582,8 +2561,22 @@ static void fastrpc_rpmsg_remove(struct rpmsg_device *rpdev) list_for_each_entry_safe(buf, b, &cctx->invoke_interrupted_mmaps, node) list_del(&buf->node); - if (cctx->remote_heap) - fastrpc_buf_free(cctx->remote_heap); + if (cctx->remote_heap && cctx->vmcount) { + u64 src_perms = 0; + struct qcom_scm_vmperm dst_perms; + + for (u32 i = 0; i < cctx->vmcount; i++) + src_perms |= BIT(cctx->vmperms[i].vmid); + + dst_perms.vmid = QCOM_SCM_VMID_HLOS; + dst_perms.perm = QCOM_SCM_PERM_RWX; + + err = qcom_scm_assign_mem(cctx->remote_heap->phys, + cctx->remote_heap->size, &src_perms, + &dst_perms, 1); + if (!err) + kfree(cctx->remote_heap); + } of_platform_depopulate(&rpdev->dev); From a6a27eef49696472c26e65afb2282e3e5f4cefd1 Mon Sep 17 00:00:00 2001 From: Ekansh Gupta Date: Tue, 26 May 2026 19:11:24 +0800 Subject: [PATCH 9/9] FROMLIST: misc: fastrpc: Allow fastrpc_buf_free() to accept NULL Make fastrpc_buf_free() a no-op when passed a NULL pointer, allowing callers to avoid open-coded NULL checks. Link: https://lore.kernel.org/all/20260526111124.515-6-jianping.li@oss.qualcomm.com/ Signed-off-by: Ekansh Gupta Signed-off-by: Jianping Li Signed-off-by: Vinayak Katoch --- drivers/misc/fastrpc.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index 5a4c5a85b0a21..897452de3dbe6 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -416,6 +416,9 @@ static int fastrpc_map_lookup(struct fastrpc_user *fl, int fd, static void fastrpc_buf_free(struct fastrpc_buf *buf) { + if (!buf) + return; + dma_free_coherent(buf->dev, buf->size, buf->virt, FASTRPC_PHYS(buf->phys)); kfree(buf); @@ -508,8 +511,7 @@ static void fastrpc_user_free(struct kref *ref) struct fastrpc_map *map, *m; struct fastrpc_buf *buf, *b; - if (fl->init_mem) - fastrpc_buf_free(fl->init_mem); + fastrpc_buf_free(fl->init_mem); list_for_each_entry_safe(ctx, n, &fl->pending, node) { list_del(&ctx->node); @@ -554,8 +556,7 @@ static void fastrpc_context_free(struct kref *ref) for (i = 0; i < ctx->nbufs; i++) fastrpc_map_put(ctx->maps[i]); - if (ctx->buf) - fastrpc_buf_free(ctx->buf); + fastrpc_buf_free(ctx->buf); spin_lock_irqsave(&cctx->lock, flags); idr_remove(&cctx->ctx_idr, ctx->ctxid >> 8);