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; }