msm: adsprpc: Option to keep maps persistent

ATTR_KEEP_MAP should allow the maps to be persistent and
unmap happens during file close or explicit unmap request.

Change-Id: I16b8738be21dcc9f9ae0b1e87e37810c3829bde3
Acked-by: Bharath Kumar <bkumar@qti.qualcomm.com>
Signed-off-by: Tharun Kumar Merugu <mtharu@codeaurora.org>
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index 122ebd2..ec4590e 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -520,7 +520,7 @@
 	return -ENOTTY;
 }
 
-static void fastrpc_mmap_free(struct fastrpc_mmap *map)
+static void fastrpc_mmap_free(struct fastrpc_mmap *map, uint32_t flags)
 {
 	struct fastrpc_apps *me = &gfa;
 	struct fastrpc_file *fl;
@@ -537,15 +537,17 @@
 		if (!map->refs)
 			hlist_del_init(&map->hn);
 		spin_unlock(&me->hlock);
+		if (map->refs > 0)
+			return;
 	} else {
 		spin_lock(&fl->hlock);
 		map->refs--;
 		if (!map->refs)
 			hlist_del_init(&map->hn);
 		spin_unlock(&fl->hlock);
+		if (map->refs > 0 && !flags)
+			return;
 	}
-	if (map->refs > 0)
-		return;
 	if (map->flags == ADSP_MMAP_HEAP_ADDR ||
 				map->flags == ADSP_MMAP_REMOTE_HEAP_ADDR) {
 
@@ -635,6 +637,11 @@
 		map->size = len;
 		map->va = (uintptr_t __user)map->phys;
 	} else {
+		if (map->attr && (map->attr & FASTRPC_ATTR_KEEP_MAP)) {
+			pr_info("adsprpc: buffer mapped with persist attr %x\n",
+				(unsigned int)map->attr);
+			map->refs = 2;
+		}
 		VERIFY(err, !IS_ERR_OR_NULL(map->handle =
 				ion_import_dma_buf_fd(fl->apps->client, fd)));
 		if (err)
@@ -724,7 +731,7 @@
 
 bail:
 	if (err && map)
-		fastrpc_mmap_free(map);
+		fastrpc_mmap_free(map, 0);
 	return err;
 }
 
@@ -995,7 +1002,7 @@
 	hlist_del_init(&ctx->hn);
 	spin_unlock(&ctx->fl->hlock);
 	for (i = 0; i < nbufs; ++i)
-		fastrpc_mmap_free(ctx->maps[i]);
+		fastrpc_mmap_free(ctx->maps[i], 0);
 	fastrpc_buf_free(ctx->buf, 1);
 	ctx->magic = 0;
 	kfree(ctx);
@@ -1345,7 +1352,7 @@
 			if (err)
 				goto bail;
 		} else {
-			fastrpc_mmap_free(ctx->maps[i]);
+			fastrpc_mmap_free(ctx->maps[i], 0);
 			ctx->maps[i] = NULL;
 		}
 	}
@@ -1355,7 +1362,7 @@
 				break;
 			if (!fastrpc_mmap_find(ctx->fl, (int)fdlist[i], 0, 0,
 						0, 0, &mmap))
-				fastrpc_mmap_free(mmap);
+				fastrpc_mmap_free(mmap, 0);
 		}
 	}
 	if (ctx->crc && crclist && rpra)
@@ -1782,10 +1789,10 @@
 		if (mem->flags == ADSP_MMAP_REMOTE_HEAP_ADDR)
 			hyp_assign_phys(mem->phys, (uint64_t)mem->size,
 					destVM, 1, srcVM, hlosVMperm, 1);
-		fastrpc_mmap_free(mem);
+		fastrpc_mmap_free(mem, 0);
 	}
 	if (file)
-		fastrpc_mmap_free(file);
+		fastrpc_mmap_free(file, 0);
 	return err;
 }
 
@@ -2016,7 +2023,7 @@
 					kfree(ramdump_segments_rh);
 				}
 			}
-			fastrpc_mmap_free(match);
+			fastrpc_mmap_free(match, 0);
 		}
 	} while (match);
 bail:
@@ -2042,13 +2049,36 @@
 	VERIFY(err, !fastrpc_munmap_on_dsp(fl, map));
 	if (err)
 		goto bail;
-	fastrpc_mmap_free(map);
+	fastrpc_mmap_free(map, 0);
 bail:
 	if (err && map)
 		fastrpc_mmap_add(map);
 	return err;
 }
 
+static int fastrpc_internal_munmap_fd(struct fastrpc_file *fl,
+					struct fastrpc_ioctl_munmap_fd *ud) {
+	int err = 0;
+	struct fastrpc_mmap *map = NULL;
+
+	VERIFY(err, (fl && ud));
+	if (err)
+		goto bail;
+
+	if (!fastrpc_mmap_find(fl, ud->fd, ud->va, ud->len, 0, 0, &map)) {
+		pr_err("mapping not found to unamp %x va %llx %x\n",
+			ud->fd, (unsigned long long)ud->va,
+			(unsigned int)ud->len);
+		err = -1;
+		goto bail;
+	}
+	if (map)
+	fastrpc_mmap_free(map, 0);
+bail:
+	return err;
+}
+
+
 static int fastrpc_internal_mmap(struct fastrpc_file *fl,
 				 struct fastrpc_ioctl_mmap *ud)
 {
@@ -2071,7 +2101,7 @@
 	ud->vaddrout = map->raddr;
  bail:
 	if (err && map)
-		fastrpc_mmap_free(map);
+		fastrpc_mmap_free(map, 0);
 	return err;
 }
 
@@ -2239,7 +2269,7 @@
 	fastrpc_context_list_dtor(fl);
 	fastrpc_buf_list_free(fl);
 	hlist_for_each_entry_safe(map, n, &fl->maps, hn) {
-		fastrpc_mmap_free(map);
+		fastrpc_mmap_free(map, 1);
 	}
 	if (fl->ssrcount == fl->apps->channel[cid].ssrcount)
 		kref_put_mutex(&fl->apps->channel[cid].kref,
@@ -2655,6 +2685,7 @@
 		struct fastrpc_ioctl_invoke_crc inv;
 		struct fastrpc_ioctl_mmap mmap;
 		struct fastrpc_ioctl_munmap munmap;
+		struct fastrpc_ioctl_munmap_fd munmap_fd;
 		struct fastrpc_ioctl_init_attrs init;
 		struct fastrpc_ioctl_perf perf;
 		struct fastrpc_ioctl_control cp;
@@ -2721,6 +2752,16 @@
 		if (err)
 			goto bail;
 		break;
+	case FASTRPC_IOCTL_MUNMAP_FD:
+		K_COPY_FROM_USER(err, 0, &p.munmap_fd, param,
+			sizeof(p.munmap_fd));
+		if (err)
+			goto bail;
+		VERIFY(err, 0 == (err = fastrpc_internal_munmap_fd(fl,
+			&p.munmap_fd)));
+		if (err)
+			goto bail;
+		break;
 	case FASTRPC_IOCTL_SETMODE:
 		switch ((uint32_t)ioctl_param) {
 		case FASTRPC_MODE_PARALLEL: