Skip to content

Commit 5c1b97c

Browse files
Jeya Rgregkh
authored andcommitted
misc: fastrpc: add support for FASTRPC_IOCTL_MEM_MAP/UNMAP
Add support for IOCTL requests to map and unmap on DSP based on map flags. Signed-off-by: Jeya R <jeyr@codeaurora.org> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org> Link: https://lore.kernel.org/r/20220214161002.6831-3-srinivas.kandagatla@linaro.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 965602e commit 5c1b97c

2 files changed

Lines changed: 205 additions & 0 deletions

File tree

drivers/misc/fastrpc.c

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@
7272
#define FASTRPC_RMID_INIT_CREATE 6
7373
#define FASTRPC_RMID_INIT_CREATE_ATTR 7
7474
#define FASTRPC_RMID_INIT_CREATE_STATIC 8
75+
#define FASTRPC_RMID_INIT_MEM_MAP 10
76+
#define FASTRPC_RMID_INIT_MEM_UNMAP 11
7577

7678
/* Protection Domain(PD) ids */
7779
#define AUDIO_PD (0) /* also GUEST_OS PD? */
@@ -108,12 +110,29 @@ struct fastrpc_mmap_req_msg {
108110
s32 num;
109111
};
110112

113+
struct fastrpc_mem_map_req_msg {
114+
s32 pgid;
115+
s32 fd;
116+
s32 offset;
117+
u32 flags;
118+
u64 vaddrin;
119+
s32 num;
120+
s32 data_len;
121+
};
122+
111123
struct fastrpc_munmap_req_msg {
112124
s32 pgid;
113125
u64 vaddr;
114126
u64 size;
115127
};
116128

129+
struct fastrpc_mem_unmap_req_msg {
130+
s32 pgid;
131+
s32 fd;
132+
u64 vaddrin;
133+
u64 len;
134+
};
135+
117136
struct fastrpc_msg {
118137
int pid; /* process group id */
119138
int tid; /* thread id */
@@ -170,6 +189,7 @@ struct fastrpc_map {
170189
u64 size;
171190
void *va;
172191
u64 len;
192+
u64 raddr;
173193
struct kref refcount;
174194
};
175195

@@ -1500,6 +1520,134 @@ static int fastrpc_req_mmap(struct fastrpc_user *fl, char __user *argp)
15001520
return err;
15011521
}
15021522

1523+
static int fastrpc_req_mem_unmap_impl(struct fastrpc_user *fl, struct fastrpc_mem_unmap *req)
1524+
{
1525+
struct fastrpc_invoke_args args[1] = { [0] = { 0 } };
1526+
struct fastrpc_map *map = NULL, *m;
1527+
struct fastrpc_mem_unmap_req_msg req_msg = { 0 };
1528+
int err = 0;
1529+
u32 sc;
1530+
struct device *dev = fl->sctx->dev;
1531+
1532+
spin_lock(&fl->lock);
1533+
list_for_each_entry_safe(map, m, &fl->maps, node) {
1534+
if ((req->fd < 0 || map->fd == req->fd) && (map->raddr == req->vaddr))
1535+
break;
1536+
map = NULL;
1537+
}
1538+
1539+
spin_unlock(&fl->lock);
1540+
1541+
if (!map) {
1542+
dev_err(dev, "map not in list\n");
1543+
return -EINVAL;
1544+
}
1545+
1546+
req_msg.pgid = fl->tgid;
1547+
req_msg.len = map->len;
1548+
req_msg.vaddrin = map->raddr;
1549+
req_msg.fd = map->fd;
1550+
1551+
args[0].ptr = (u64) (uintptr_t) &req_msg;
1552+
args[0].length = sizeof(req_msg);
1553+
1554+
sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_MEM_UNMAP, 1, 0);
1555+
err = fastrpc_internal_invoke(fl, true, FASTRPC_INIT_HANDLE, sc,
1556+
&args[0]);
1557+
fastrpc_map_put(map);
1558+
if (err)
1559+
dev_err(dev, "unmmap\tpt fd = %d, 0x%09llx error\n", map->fd, map->raddr);
1560+
1561+
return err;
1562+
}
1563+
1564+
static int fastrpc_req_mem_unmap(struct fastrpc_user *fl, char __user *argp)
1565+
{
1566+
struct fastrpc_mem_unmap req;
1567+
1568+
if (copy_from_user(&req, argp, sizeof(req)))
1569+
return -EFAULT;
1570+
1571+
return fastrpc_req_mem_unmap_impl(fl, &req);
1572+
}
1573+
1574+
static int fastrpc_req_mem_map(struct fastrpc_user *fl, char __user *argp)
1575+
{
1576+
struct fastrpc_invoke_args args[4] = { [0 ... 3] = { 0 } };
1577+
struct fastrpc_mem_map_req_msg req_msg = { 0 };
1578+
struct fastrpc_mmap_rsp_msg rsp_msg = { 0 };
1579+
struct fastrpc_mem_unmap req_unmap = { 0 };
1580+
struct fastrpc_phy_page pages = { 0 };
1581+
struct fastrpc_mem_map req;
1582+
struct device *dev = fl->sctx->dev;
1583+
struct fastrpc_map *map = NULL;
1584+
int err;
1585+
u32 sc;
1586+
1587+
if (copy_from_user(&req, argp, sizeof(req)))
1588+
return -EFAULT;
1589+
1590+
/* create SMMU mapping */
1591+
err = fastrpc_map_create(fl, req.fd, req.length, &map);
1592+
if (err) {
1593+
dev_err(dev, "failed to map buffer, fd = %d\n", req.fd);
1594+
return err;
1595+
}
1596+
1597+
req_msg.pgid = fl->tgid;
1598+
req_msg.fd = req.fd;
1599+
req_msg.offset = req.offset;
1600+
req_msg.vaddrin = req.vaddrin;
1601+
map->va = (void *) (uintptr_t) req.vaddrin;
1602+
req_msg.flags = req.flags;
1603+
req_msg.num = sizeof(pages);
1604+
req_msg.data_len = 0;
1605+
1606+
args[0].ptr = (u64) (uintptr_t) &req_msg;
1607+
args[0].length = sizeof(req_msg);
1608+
1609+
pages.addr = map->phys;
1610+
pages.size = map->size;
1611+
1612+
args[1].ptr = (u64) (uintptr_t) &pages;
1613+
args[1].length = sizeof(pages);
1614+
1615+
args[2].ptr = (u64) (uintptr_t) &pages;
1616+
args[2].length = 0;
1617+
1618+
args[3].ptr = (u64) (uintptr_t) &rsp_msg;
1619+
args[3].length = sizeof(rsp_msg);
1620+
1621+
sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_MEM_MAP, 3, 1);
1622+
err = fastrpc_internal_invoke(fl, true, FASTRPC_INIT_HANDLE, sc, &args[0]);
1623+
if (err) {
1624+
dev_err(dev, "mem mmap error, fd %d, vaddr %llx, size %lld\n",
1625+
req.fd, req.vaddrin, map->size);
1626+
goto err_invoke;
1627+
}
1628+
1629+
/* update the buffer to be able to deallocate the memory on the DSP */
1630+
map->raddr = rsp_msg.vaddr;
1631+
1632+
/* let the client know the address to use */
1633+
req.vaddrout = rsp_msg.vaddr;
1634+
1635+
if (copy_to_user((void __user *)argp, &req, sizeof(req))) {
1636+
/* unmap the memory and release the buffer */
1637+
req_unmap.vaddr = (uintptr_t) rsp_msg.vaddr;
1638+
req_unmap.length = map->size;
1639+
fastrpc_req_mem_unmap_impl(fl, &req_unmap);
1640+
return -EFAULT;
1641+
}
1642+
1643+
return 0;
1644+
1645+
err_invoke:
1646+
fastrpc_map_put(map);
1647+
1648+
return err;
1649+
}
1650+
15031651
static long fastrpc_device_ioctl(struct file *file, unsigned int cmd,
15041652
unsigned long arg)
15051653
{
@@ -1529,6 +1677,12 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int cmd,
15291677
case FASTRPC_IOCTL_MUNMAP:
15301678
err = fastrpc_req_munmap(fl, argp);
15311679
break;
1680+
case FASTRPC_IOCTL_MEM_MAP:
1681+
err = fastrpc_req_mem_map(fl, argp);
1682+
break;
1683+
case FASTRPC_IOCTL_MEM_UNMAP:
1684+
err = fastrpc_req_mem_unmap(fl, argp);
1685+
break;
15321686
default:
15331687
err = -ENOTTY;
15341688
break;

include/uapi/misc/fastrpc.h

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,37 @@
1313
#define FASTRPC_IOCTL_MMAP _IOWR('R', 6, struct fastrpc_req_mmap)
1414
#define FASTRPC_IOCTL_MUNMAP _IOWR('R', 7, struct fastrpc_req_munmap)
1515
#define FASTRPC_IOCTL_INIT_ATTACH_SNS _IO('R', 8)
16+
#define FASTRPC_IOCTL_MEM_MAP _IOWR('R', 10, struct fastrpc_mem_map)
17+
#define FASTRPC_IOCTL_MEM_UNMAP _IOWR('R', 11, struct fastrpc_mem_unmap)
18+
19+
/**
20+
* enum fastrpc_map_flags - control flags for mapping memory on DSP user process
21+
* @FASTRPC_MAP_STATIC: Map memory pages with RW- permission and CACHE WRITEBACK.
22+
* The driver is responsible for cache maintenance when passed
23+
* the buffer to FastRPC calls. Same virtual address will be
24+
* assigned for subsequent FastRPC calls.
25+
* @FASTRPC_MAP_RESERVED: Reserved
26+
* @FASTRPC_MAP_FD: Map memory pages with RW- permission and CACHE WRITEBACK.
27+
* Mapping tagged with a file descriptor. User is responsible for
28+
* CPU and DSP cache maintenance for the buffer. Get virtual address
29+
* of buffer on DSP using HAP_mmap_get() and HAP_mmap_put() APIs.
30+
* @FASTRPC_MAP_FD_DELAYED: Mapping delayed until user call HAP_mmap() and HAP_munmap()
31+
* functions on DSP. It is useful to map a buffer with cache modes
32+
* other than default modes. User is responsible for CPU and DSP
33+
* cache maintenance for the buffer.
34+
* @FASTRPC_MAP_FD_NOMAP: This flag is used to skip CPU mapping,
35+
* otherwise behaves similar to FASTRPC_MAP_FD_DELAYED flag.
36+
* @FASTRPC_MAP_MAX: max count for flags
37+
*
38+
*/
39+
enum fastrpc_map_flags {
40+
FASTRPC_MAP_STATIC = 0,
41+
FASTRPC_MAP_RESERVED,
42+
FASTRPC_MAP_FD = 2,
43+
FASTRPC_MAP_FD_DELAYED,
44+
FASTRPC_MAP_FD_NOMAP = 16,
45+
FASTRPC_MAP_MAX,
46+
};
1647

1748
struct fastrpc_invoke_args {
1849
__u64 ptr;
@@ -49,9 +80,29 @@ struct fastrpc_req_mmap {
4980
__u64 vaddrout; /* dsp virtual address */
5081
};
5182

83+
struct fastrpc_mem_map {
84+
__s32 version;
85+
__s32 fd; /* fd */
86+
__s32 offset; /* buffer offset */
87+
__u32 flags; /* flags defined in enum fastrpc_map_flags */
88+
__u64 vaddrin; /* buffer virtual address */
89+
__u64 length; /* buffer length */
90+
__u64 vaddrout; /* [out] remote virtual address */
91+
__s32 attrs; /* buffer attributes used for SMMU mapping */
92+
__s32 reserved[4];
93+
};
94+
5295
struct fastrpc_req_munmap {
5396
__u64 vaddrout; /* address to unmap */
5497
__u64 size; /* size */
5598
};
5699

100+
struct fastrpc_mem_unmap {
101+
__s32 vesion;
102+
__s32 fd; /* fd */
103+
__u64 vaddr; /* remote process (dsp) virtual address */
104+
__u64 length; /* buffer size */
105+
__s32 reserved[5];
106+
};
107+
57108
#endif /* __QCOM_FASTRPC_H__ */

0 commit comments

Comments
 (0)