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:
diff --git a/drivers/char/adsprpc_shared.h b/drivers/char/adsprpc_shared.h
index 43edf71..e2f8983 100644
--- a/drivers/char/adsprpc_shared.h
+++ b/drivers/char/adsprpc_shared.h
@@ -29,6 +29,7 @@
#define FASTRPC_IOCTL_INIT_ATTRS _IOWR('R', 10, struct fastrpc_ioctl_init_attrs)
#define FASTRPC_IOCTL_INVOKE_CRC _IOWR('R', 11, struct fastrpc_ioctl_invoke_crc)
#define FASTRPC_IOCTL_CONTROL _IOWR('R', 12, struct fastrpc_ioctl_control)
+#define FASTRPC_IOCTL_MUNMAP_FD _IOWR('R', 13, struct fastrpc_ioctl_munmap_fd)
#define FASTRPC_GLINK_GUID "fastrpcglink-apps-dsp"
#define FASTRPC_SMD_GUID "fastrpcsmd-apps-dsp"
@@ -43,6 +44,9 @@
/* Set for buffers that are dma coherent */
#define FASTRPC_ATTR_COHERENT 0x4
+/* Fastrpc attribute for keeping the map persistent */
+#define FASTRPC_ATTR_KEEP_MAP 0x8
+
/* Driver should operate in parallel with the co-processor */
#define FASTRPC_MODE_PARALLEL 0
@@ -204,6 +208,13 @@
uintptr_t vaddrout; /* dsps virtual address */
};
+struct fastrpc_ioctl_munmap_fd {
+ int fd; /* fd */
+ uint32_t flags; /* control flags */
+ uintptr_t va; /* va */
+ ssize_t len; /* length */
+};
+
struct fastrpc_ioctl_perf { /* kernel performance data */
uintptr_t __user data;
uint32_t numkeys;