summaryrefslogtreecommitdiff
path: root/drivers/char/adsprpc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/adsprpc.c')
-rw-r--r--drivers/char/adsprpc.c21
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;
}