11/*
22 * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved.
3+ * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
34 *
45 * This program is free software; you can redistribute it and/or modify
56 * it under the terms of the GNU General Public License version 2 and
@@ -356,7 +357,8 @@ struct fastrpc_mmap {
356357 int uncached ;
357358 int secure ;
358359 uintptr_t attr ;
359- bool is_filemap ; /*flag to indicate map used in process init*/
360+ bool is_filemap ; /* flag to indicate map used in process init */
361+ unsigned int ctx_refs ; /* Indicates reference count for context map */
360362};
361363
362364enum fastrpc_perfkeys {
@@ -719,7 +721,7 @@ static int fastrpc_mmap_remove(struct fastrpc_file *fl, uintptr_t va,
719721 hlist_for_each_entry_safe (map , n , & me -> maps , hn ) {
720722 if (map -> refs == 1 && map -> raddr == va &&
721723 map -> raddr + map -> len == va + len &&
722- /*Remove map if not used in process initialization*/
724+ /* Remove map if not used in process initialization */
723725 !map -> is_filemap ) {
724726 match = map ;
725727 hlist_del_init (& map -> hn );
@@ -732,9 +734,10 @@ static int fastrpc_mmap_remove(struct fastrpc_file *fl, uintptr_t va,
732734 return 0 ;
733735 }
734736 hlist_for_each_entry_safe (map , n , & fl -> maps , hn ) {
735- if (map -> refs == 1 && map -> raddr == va &&
737+ /* Remove if only one reference map and no context map */
738+ if (map -> refs == 1 && !map -> ctx_refs && map -> raddr == va &&
736739 map -> raddr + map -> len == va + len &&
737- /*Remove map if not used in process initialization*/
740+ /* Remove map if not used in process initialization */
738741 !map -> is_filemap ) {
739742 match = map ;
740743 hlist_del_init (& map -> hn );
@@ -773,14 +776,14 @@ static void fastrpc_mmap_free(struct fastrpc_mmap *map, uint32_t flags)
773776 map -> flags == ADSP_MMAP_REMOTE_HEAP_ADDR ) {
774777 spin_lock (& me -> hlock );
775778 map -> refs -- ;
776- if (!map -> refs )
779+ if (!map -> refs && ! map -> ctx_refs )
777780 hlist_del_init (& map -> hn );
778781 spin_unlock (& me -> hlock );
779782 if (map -> refs > 0 )
780783 return ;
781784 } else {
782785 map -> refs -- ;
783- if (!map -> refs )
786+ if (!map -> refs && ! map -> ctx_refs )
784787 hlist_del_init (& map -> hn );
785788 if (map -> refs > 0 && !flags )
786789 return ;
@@ -878,6 +881,7 @@ static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd,
878881 map -> fd = fd ;
879882 map -> attr = attr ;
880883 map -> is_filemap = false;
884+ map -> ctx_refs = 0 ;
881885 if (mflags == ADSP_MMAP_HEAP_ADDR ||
882886 mflags == ADSP_MMAP_REMOTE_HEAP_ADDR ) {
883887 unsigned long dma_attrs = DMA_ATTR_SKIP_ZEROING |
@@ -1336,9 +1340,11 @@ static void context_free(struct smq_invoke_ctx *ctx)
13361340 hlist_del_init (& ctx -> hn );
13371341 spin_unlock (& ctx -> fl -> hlock );
13381342 mutex_lock (& ctx -> fl -> fl_map_mutex );
1339- for (i = 0 ; i < nbufs ; ++ i )
1343+ for (i = 0 ; i < nbufs ; ++ i ) {
1344+ if (ctx -> maps [i ] && ctx -> maps [i ]-> ctx_refs )
1345+ ctx -> maps [i ]-> ctx_refs -- ;
13401346 fastrpc_mmap_free (ctx -> maps [i ], 0 );
1341-
1347+ }
13421348 mutex_unlock (& ctx -> fl -> fl_map_mutex );
13431349 fastrpc_buf_free (ctx -> buf , 1 );
13441350 fastrpc_buf_free (ctx -> lbuf , 1 );
@@ -1527,6 +1533,8 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx)
15271533 attrs , buf , len ,
15281534 mflags , & ctx -> maps [i ]);
15291535 }
1536+ if (ctx -> maps [i ])
1537+ ctx -> maps [i ]-> ctx_refs ++ ;
15301538 mutex_unlock (& ctx -> fl -> fl_map_mutex );
15311539 ipage += 1 ;
15321540 }
@@ -1540,6 +1548,8 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx)
15401548 dmaflags = FASTRPC_DMAHANDLE_NOMAP ;
15411549 VERIFY (err , !fastrpc_mmap_create (ctx -> fl , ctx -> fds [i ],
15421550 FASTRPC_ATTR_NOVA , 0 , 0 , dmaflags , & ctx -> maps [i ]));
1551+ if (!err && ctx -> maps [i ])
1552+ ctx -> maps [i ]-> ctx_refs ++ ;
15431553 if (err ) {
15441554 mutex_unlock (& ctx -> fl -> fl_map_mutex );
15451555 goto bail ;
@@ -1786,6 +1796,8 @@ static int put_args(uint32_t kernel, struct smq_invoke_ctx *ctx,
17861796 goto bail ;
17871797 } else {
17881798 mutex_lock (& ctx -> fl -> fl_map_mutex );
1799+ if (ctx -> maps [i ]-> ctx_refs )
1800+ ctx -> maps [i ]-> ctx_refs -- ;
17891801 fastrpc_mmap_free (ctx -> maps [i ], 0 );
17901802 mutex_unlock (& ctx -> fl -> fl_map_mutex );
17911803 ctx -> maps [i ] = NULL ;
@@ -1797,8 +1809,11 @@ static int put_args(uint32_t kernel, struct smq_invoke_ctx *ctx,
17971809 if (!fdlist [i ])
17981810 break ;
17991811 if (!fastrpc_mmap_find (ctx -> fl , (int )fdlist [i ], 0 , 0 ,
1800- 0 , 0 , & mmap ))
1812+ 0 , 0 , & mmap )) {
1813+ if (mmap && mmap -> ctx_refs )
1814+ mmap -> ctx_refs -- ;
18011815 fastrpc_mmap_free (mmap , 0 );
1816+ }
18021817 }
18031818 }
18041819 mutex_unlock (& ctx -> fl -> fl_map_mutex );
0 commit comments