summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/char/adsprpc.c26
1 files changed, 18 insertions, 8 deletions
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index 3f1ec8dab244..1662707f0d1a 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2012-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -299,7 +299,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 {
@@ -556,7 +557,7 @@ static int fastrpc_mmap_remove(struct fastrpc_file *fl, uintptr_t va,
hlist_for_each_entry_safe(map, n, &me->maps, hn) {
if (map->refs == 1 && map->raddr == va &&
map->raddr + map->len == va + len &&
- /*Remove map if not used in process initialization*/
+ /* Remove map if not used in process initialization */
!map->is_filemap) {
match = map;
hlist_del_init(&map->hn);
@@ -569,9 +570,10 @@ static int fastrpc_mmap_remove(struct fastrpc_file *fl, uintptr_t va,
return 0;
}
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*/
+ /* Remove map if not used in process initialization */
!map->is_filemap) {
match = map;
hlist_del_init(&map->hn);
@@ -609,11 +611,11 @@ static void fastrpc_mmap_free(struct fastrpc_mmap *map)
if (map->flags == ADSP_MMAP_HEAP_ADDR ||
map->flags == ADSP_MMAP_REMOTE_HEAP_ADDR) {
map->refs--;
- if (!map->refs)
+ if (!map->refs && !map->ctx_refs)
hlist_del_init(&map->hn);
} else {
map->refs--;
- if (!map->refs)
+ if (!map->refs && !map->ctx_refs)
hlist_del_init(&map->hn);
}
if (map->refs > 0)
@@ -706,6 +708,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);
@@ -1124,8 +1127,11 @@ static void context_free(struct smq_invoke_ctx *ctx)
hlist_del_init(&ctx->hn);
spin_unlock(&ctx->fl->hlock);
mutex_lock(&ctx->fl->map_mutex);
- 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]);
+ }
mutex_unlock(&ctx->fl->map_mutex);
fastrpc_buf_free(ctx->buf, 1);
fastrpc_buf_free(ctx->lbuf, 1);
@@ -1271,6 +1277,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++;
mutex_unlock(&ctx->fl->map_mutex);
ipage += 1;
}
@@ -1489,6 +1497,8 @@ static int put_args(uint32_t kernel, struct smq_invoke_ctx *ctx,
goto bail;
} else {
mutex_lock(&ctx->fl->map_mutex);
+ if (ctx->maps[i]->ctx_refs)
+ ctx->maps[i]->ctx_refs--;
fastrpc_mmap_free(ctx->maps[i]);
mutex_unlock(&ctx->fl->map_mutex);
ctx->maps[i] = NULL;