diff options
-rw-r--r-- | drivers/char/adsprpc.c | 21 |
1 files changed, 15 insertions, 6 deletions
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index c94d93611d49..c452e23e7416 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -297,8 +297,8 @@ struct fastrpc_mmap { int uncached; int secure; uintptr_t attr; - bool is_filemap; - /*flag to indicate map used in process init*/ + bool is_filemap; /*flag to indicate map used in process init*/ + unsigned int ctx_refs; /* Indicates reference count for context map */ }; struct fastrpc_perf { @@ -574,7 +574,8 @@ static int fastrpc_mmap_remove(struct fastrpc_file *fl, uintptr_t va, } spin_lock(&fl->hlock); hlist_for_each_entry_safe(map, n, &fl->maps, hn) { - if (map->refs == 1 && map->raddr == va && + /* Remove if only one reference map and no context map */ + if (map->refs == 1 && !map->ctx_refs && map->raddr == va && map->raddr + map->len == va + len && /*Remove map if not used in process initialization*/ !map->is_filemap) { @@ -616,13 +617,13 @@ static void fastrpc_mmap_free(struct fastrpc_mmap *map) map->flags == ADSP_MMAP_REMOTE_HEAP_ADDR) { spin_lock(&me->hlock); map->refs--; - if (!map->refs) + if (!map->refs && !map->ctx_refs) hlist_del_init(&map->hn); spin_unlock(&me->hlock); } else { spin_lock(&fl->hlock); map->refs--; - if (!map->refs) + if (!map->refs && !map->ctx_refs) hlist_del_init(&map->hn); spin_unlock(&fl->hlock); } @@ -716,6 +717,7 @@ static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd, unsigned attr, map->fd = fd; map->attr = attr; map->is_filemap = false; + map->ctx_refs = 0; if (mflags == ADSP_MMAP_HEAP_ADDR || mflags == ADSP_MMAP_REMOTE_HEAP_ADDR) { DEFINE_DMA_ATTRS(rh_attrs); @@ -1133,8 +1135,11 @@ static void context_free(struct smq_invoke_ctx *ctx) spin_lock(&ctx->fl->hlock); hlist_del_init(&ctx->hn); spin_unlock(&ctx->fl->hlock); - for (i = 0; i < nbufs; ++i) + for (i = 0; i < nbufs; ++i) { + if (ctx->maps[i] && ctx->maps[i]->ctx_refs) + ctx->maps[i]->ctx_refs--; fastrpc_mmap_free(ctx->maps[i]); + } fastrpc_buf_free(ctx->buf, 1); fastrpc_buf_free(ctx->lbuf, 1); ctx->magic = 0; @@ -1278,6 +1283,8 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx) fastrpc_mmap_create(ctx->fl, ctx->fds[i], ctx->attrs[i], buf, len, mflags, &ctx->maps[i]); + if (ctx->maps[i]) + ctx->maps[i]->ctx_refs++; ipage += 1; } metalen = copylen = (size_t)&ipage[0]; @@ -1494,6 +1501,8 @@ static int put_args(uint32_t kernel, struct smq_invoke_ctx *ctx, if (err) goto bail; } else { + if (ctx->maps[i]->ctx_refs) + ctx->maps[i]->ctx_refs--; fastrpc_mmap_free(ctx->maps[i]); ctx->maps[i] = NULL; } |