misc: fastrpc: Add fdlist implementation
authorVamsi Krishna Gattupalli <quic_vgattupa@quicinc.com>
Mon, 14 Feb 2022 16:10:00 +0000 (16:10 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 18 Mar 2022 13:11:00 +0000 (14:11 +0100)
Add fdlist implementation to support dma handles. fdlist is populated by
DSP if any map is no longer used and it is freed during put_args.

Signed-off-by: Vamsi Krishna Gattupalli <quic_vgattupa@quicinc.com>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Link: https://lore.kernel.org/r/20220214161002.6831-11-srinivas.kandagatla@linaro.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/misc/fastrpc.c

index 2cf6286bb717d8cd8d9a4eecc9d2d40e8c673be4..e11b790ce52674d6428954176e48a80fb8f3a7c5 100644 (file)
@@ -320,7 +320,8 @@ static void fastrpc_map_get(struct fastrpc_map *map)
                kref_get(&map->refcount);
 }
 
-static int fastrpc_map_find(struct fastrpc_user *fl, int fd,
+
+static int fastrpc_map_lookup(struct fastrpc_user *fl, int fd,
                            struct fastrpc_map **ppmap)
 {
        struct fastrpc_map *map = NULL;
@@ -328,7 +329,6 @@ static int fastrpc_map_find(struct fastrpc_user *fl, int fd,
        mutex_lock(&fl->mutex);
        list_for_each_entry(map, &fl->maps, node) {
                if (map->fd == fd) {
-                       fastrpc_map_get(map);
                        *ppmap = map;
                        mutex_unlock(&fl->mutex);
                        return 0;
@@ -339,6 +339,17 @@ static int fastrpc_map_find(struct fastrpc_user *fl, int fd,
        return -ENOENT;
 }
 
+static int fastrpc_map_find(struct fastrpc_user *fl, int fd,
+                           struct fastrpc_map **ppmap)
+{
+       int ret = fastrpc_map_lookup(fl, fd, ppmap);
+
+       if (!ret)
+               fastrpc_map_get(*ppmap);
+
+       return ret;
+}
+
 static void fastrpc_buf_free(struct fastrpc_buf *buf)
 {
        dma_free_coherent(buf->dev, buf->size, buf->virt,
@@ -411,7 +422,7 @@ static void fastrpc_context_free(struct kref *ref)
        ctx = container_of(ref, struct fastrpc_invoke_ctx, refcount);
        cctx = ctx->cctx;
 
-       for (i = 0; i < ctx->nscalars; i++)
+       for (i = 0; i < ctx->nbufs; i++)
                fastrpc_map_put(ctx->maps[i]);
 
        if (ctx->buf)
@@ -969,9 +980,19 @@ static int fastrpc_put_args(struct fastrpc_invoke_ctx *ctx,
                            u32 kernel)
 {
        struct fastrpc_remote_arg *rpra = ctx->rpra;
-       int i, inbufs;
+       struct fastrpc_user *fl = ctx->fl;
+       struct fastrpc_map *mmap = NULL;
+       struct fastrpc_invoke_buf *list;
+       struct fastrpc_phy_page *pages;
+       u64 *fdlist;
+       int i, inbufs, outbufs, handles;
 
        inbufs = REMOTE_SCALARS_INBUFS(ctx->sc);
+       outbufs = REMOTE_SCALARS_OUTBUFS(ctx->sc);
+       handles = REMOTE_SCALARS_INHANDLES(ctx->sc) + REMOTE_SCALARS_OUTHANDLES(ctx->sc);
+       list = fastrpc_invoke_buf_start(rpra, ctx->nscalars);
+       pages = fastrpc_phy_page_start(list, ctx->nscalars);
+       fdlist = (uint64_t *)(pages + inbufs + outbufs + handles);
 
        for (i = inbufs; i < ctx->nbufs; ++i) {
                if (!ctx->maps[i]) {
@@ -988,6 +1009,13 @@ 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))
+                       fastrpc_map_put(mmap);
+       }
+
        return 0;
 }