From 495e168bc086aee778464b6b24b15ba746104ce7 Mon Sep 17 00:00:00 2001 From: Jeya R Date: Mon, 24 May 2021 16:09:15 +0530 Subject: [PATCH] msm: ADSPRPC: Re-use persistent map on static pd restart Persistent map is not freed and if not reused properly, CMA memory leak scenario is observed. This happens because for dynamic loading mapping, re-usage of persistent map is not considered. Change-Id: Id285a12446894085a986c97e6c53b28c6b927a2e Acked-by: Ekansh Gupta Signed-off-by: Jeya R --- drivers/char/adsprpc.c | 55 +++++++++++++++++++++++++++++++++--------- 1 file changed, 44 insertions(+), 11 deletions(-) diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index 939c27c92079..24008d67a721 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -567,9 +567,10 @@ struct fastrpc_mmap { uintptr_t raddr; int uncached; int secure; - bool is_persistent; //the map is persistenet across sessions - int frpc_md_index; //Minidump unique index + bool is_persistent; /* Indicates whether map is persistent */ + int frpc_md_index; /* Minidump unique index */ uintptr_t attr; + bool in_use; /* Indicates if persistent map is in use*/ struct timespec64 map_start_time; struct timespec64 map_end_time; }; @@ -1259,6 +1260,11 @@ static void fastrpc_mmap_free(struct fastrpc_mmap *map, uint32_t flags) map->size, map->va, map->refs); return; } + if (map->is_persistent && map->in_use) { + spin_lock(&me->hlock); + map->in_use = false; + spin_unlock(&me->hlock); + } } else { map->refs--; if (!map->refs) @@ -1332,6 +1338,27 @@ static void fastrpc_mmap_free(struct fastrpc_mmap *map, uint32_t flags) static int fastrpc_session_alloc(struct fastrpc_channel_ctx *chan, int secure, struct fastrpc_session_ctx **session); +static inline bool fastrpc_get_persistent_map(size_t len, struct fastrpc_mmap **pers_map) +{ + struct fastrpc_apps *me = &gfa; + struct fastrpc_mmap *map = NULL; + struct hlist_node *n = NULL; + bool found = false; + + spin_lock(&me->hlock); + hlist_for_each_entry_safe(map, n, &me->maps, hn) { + if (len == map->len && + map->is_persistent && !map->in_use) { + *pers_map = map; + map->in_use = true; + found = true; + break; + } + } + spin_unlock(&me->hlock); + return found; +} + static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd, unsigned int attr, uintptr_t va, size_t len, int mflags, struct fastrpc_mmap **ppmap) @@ -3853,12 +3880,17 @@ static int fastrpc_init_create_static_process(struct fastrpc_file *fl, if (!me->staticpd_flags && !me->legacy_remote_heap) { inbuf.pageslen = 1; - mutex_lock(&fl->map_mutex); - err = fastrpc_mmap_create(fl, -1, 0, init->mem, - init->memlen, ADSP_MMAP_REMOTE_HEAP_ADDR, &mem); - mutex_unlock(&fl->map_mutex); - if (err) - goto bail; + if (!fastrpc_get_persistent_map(init->memlen, &mem)) { + mutex_lock(&fl->map_mutex); + err = fastrpc_mmap_create(fl, -1, 0, init->mem, + init->memlen, ADSP_MMAP_REMOTE_HEAP_ADDR, &mem); + mutex_unlock(&fl->map_mutex); + if (err) + goto bail; + spin_lock(&me->hlock); + mem->in_use = true; + spin_unlock(&me->hlock); + } phys = mem->phys; size = mem->size; /* @@ -3929,9 +3961,9 @@ bail: "rh hyp unassign failed with %d for phys 0x%llx of size %zu\n", hyp_err, phys, size); } - mutex_lock(&fl->map_mutex); - fastrpc_mmap_free(mem, 0); - mutex_unlock(&fl->map_mutex); + mutex_lock(&fl->map_mutex); + fastrpc_mmap_free(mem, 0); + mutex_unlock(&fl->map_mutex); } return err; } @@ -4520,6 +4552,7 @@ static int fastrpc_mmap_remove_ssr(struct fastrpc_file *fl) hlist_for_each_entry_safe(map, n, &me->maps, hn) { match = map; if (map->is_persistent) { + map->in_use = false; match = NULL; continue; }