[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250806115114.688814-5-quic_lxu5@quicinc.com>
Date: Wed, 6 Aug 2025 17:21:14 +0530
From: Ling Xu <quic_lxu5@...cinc.com>
To: <srini@...nel.org>, <amahesh@....qualcomm.com>, <arnd@...db.de>,
<gregkh@...uxfoundation.org>, <sumit.semwal@...aro.org>,
<christian.koenig@....com>, <thierry.escande@...aro.org>,
<quic_vgattupa@...cinc.com>
CC: <quic_kuiw@...cinc.com>, <ekansh.gupta@....qualcomm.com>,
<dri-devel@...ts.freedesktop.org>, <linux-arm-msm@...r.kernel.org>,
<linux-media@...r.kernel.org>, <linaro-mm-sig@...ts.linaro.org>,
<linux-kernel@...r.kernel.org>, Ling Xu <quic_lxu5@...cinc.com>,
<stable@...nel.org>
Subject: [PATCH v2 4/4] misc: fastrpc: Skip reference for DMA handles
If multiple dma handles are passed with same fd over a remote call
the kernel driver takes a reference and expects that put for the
map will be called as many times to free the map. But DSP only
updates the fd one time in the fd list when the DSP refcount
goes to zero and hence kernel make put call only once for the
fd. This can cause SMMU fault issue as the same fd can be used
in future for some other call.
Fixes: 35a82b87135d ("misc: fastrpc: Add dma handle implementation")
Cc: stable@...nel.org
Co-developed-by: Ekansh Gupta <ekansh.gupta@....qualcomm.com>
Signed-off-by: Ekansh Gupta <ekansh.gupta@....qualcomm.com>
Signed-off-by: Ling Xu <quic_lxu5@...cinc.com>
---
drivers/misc/fastrpc.c | 44 ++++++++++++++++++++++++++----------------
1 file changed, 27 insertions(+), 17 deletions(-)
diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c
index d950a179bff8..3b7ad4a043eb 100644
--- a/drivers/misc/fastrpc.c
+++ b/drivers/misc/fastrpc.c
@@ -363,7 +363,7 @@ static int fastrpc_map_get(struct fastrpc_map *map)
static int fastrpc_map_lookup(struct fastrpc_user *fl, int fd,
- struct fastrpc_map **ppmap, bool take_ref)
+ struct fastrpc_map **ppmap)
{
struct fastrpc_session_ctx *sess = fl->sctx;
struct fastrpc_map *map = NULL;
@@ -379,15 +379,6 @@ static int fastrpc_map_lookup(struct fastrpc_user *fl, int fd,
if (map->fd != fd || map->buf != buf)
continue;
- if (take_ref) {
- ret = fastrpc_map_get(map);
- if (ret) {
- dev_dbg(sess->dev, "%s: Failed to get map fd=%d ret=%d\n",
- __func__, fd, ret);
- break;
- }
- }
-
*ppmap = map;
ret = 0;
break;
@@ -757,7 +748,7 @@ static const struct dma_buf_ops fastrpc_dma_buf_ops = {
.release = fastrpc_release,
};
-static int fastrpc_map_create(struct fastrpc_user *fl, int fd,
+static int fastrpc_map_attach(struct fastrpc_user *fl, int fd,
u64 len, u32 attr, struct fastrpc_map **ppmap)
{
struct fastrpc_session_ctx *sess = fl->sctx;
@@ -766,9 +757,6 @@ static int fastrpc_map_create(struct fastrpc_user *fl, int fd,
struct scatterlist *sgl = NULL;
int err = 0, sgl_index = 0;
- if (!fastrpc_map_lookup(fl, fd, ppmap, true))
- return 0;
-
map = kzalloc(sizeof(*map), GFP_KERNEL);
if (!map)
return -ENOMEM;
@@ -853,6 +841,24 @@ static int fastrpc_map_create(struct fastrpc_user *fl, int fd,
return err;
}
+static int fastrpc_map_create(struct fastrpc_user *fl, int fd,
+ u64 len, u32 attr, struct fastrpc_map **ppmap)
+{
+ struct fastrpc_session_ctx *sess = fl->sctx;
+ int err = 0;
+
+ if (!fastrpc_map_lookup(fl, fd, ppmap)) {
+ if (!fastrpc_map_get(*ppmap))
+ return 0;
+ dev_dbg(sess->dev, "%s: Failed to get map fd=%d\n",
+ __func__, fd);
+ }
+
+ err = fastrpc_map_attach(fl, fd, len, attr, ppmap);
+
+ return err;
+}
+
/*
* Fastrpc payload buffer with metadata looks like:
*
@@ -925,8 +931,12 @@ static int fastrpc_create_maps(struct fastrpc_invoke_ctx *ctx)
ctx->args[i].length == 0)
continue;
- err = fastrpc_map_create(ctx->fl, ctx->args[i].fd,
- ctx->args[i].length, ctx->args[i].attr, &ctx->maps[i]);
+ if (i < ctx->nbufs)
+ err = fastrpc_map_create(ctx->fl, ctx->args[i].fd,
+ ctx->args[i].length, ctx->args[i].attr, &ctx->maps[i]);
+ else
+ err = fastrpc_map_attach(ctx->fl, ctx->args[i].fd,
+ ctx->args[i].length, ctx->args[i].attr, &ctx->maps[i]);
if (err) {
dev_err(dev, "Error Creating map %d\n", err);
return -EINVAL;
@@ -1116,7 +1126,7 @@ static int fastrpc_put_args(struct fastrpc_invoke_ctx *ctx,
for (i = 0; i < FASTRPC_MAX_FDLIST; i++) {
if (!fdlist[i])
break;
- if (!fastrpc_map_lookup(fl, (int)fdlist[i], &mmap, false))
+ if (!fastrpc_map_lookup(fl, (int)fdlist[i], &mmap))
fastrpc_map_put(mmap);
}
--
2.34.1
Powered by blists - more mailing lists