|
72 | 72 | #define FASTRPC_RMID_INIT_CREATE 6 |
73 | 73 | #define FASTRPC_RMID_INIT_CREATE_ATTR 7 |
74 | 74 | #define FASTRPC_RMID_INIT_CREATE_STATIC 8 |
| 75 | +#define FASTRPC_RMID_INIT_MEM_MAP 10 |
| 76 | +#define FASTRPC_RMID_INIT_MEM_UNMAP 11 |
75 | 77 |
|
76 | 78 | /* Protection Domain(PD) ids */ |
77 | 79 | #define AUDIO_PD (0) /* also GUEST_OS PD? */ |
@@ -108,12 +110,29 @@ struct fastrpc_mmap_req_msg { |
108 | 110 | s32 num; |
109 | 111 | }; |
110 | 112 |
|
| 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 | + |
111 | 123 | struct fastrpc_munmap_req_msg { |
112 | 124 | s32 pgid; |
113 | 125 | u64 vaddr; |
114 | 126 | u64 size; |
115 | 127 | }; |
116 | 128 |
|
| 129 | +struct fastrpc_mem_unmap_req_msg { |
| 130 | + s32 pgid; |
| 131 | + s32 fd; |
| 132 | + u64 vaddrin; |
| 133 | + u64 len; |
| 134 | +}; |
| 135 | + |
117 | 136 | struct fastrpc_msg { |
118 | 137 | int pid; /* process group id */ |
119 | 138 | int tid; /* thread id */ |
@@ -170,6 +189,7 @@ struct fastrpc_map { |
170 | 189 | u64 size; |
171 | 190 | void *va; |
172 | 191 | u64 len; |
| 192 | + u64 raddr; |
173 | 193 | struct kref refcount; |
174 | 194 | }; |
175 | 195 |
|
@@ -1500,6 +1520,134 @@ static int fastrpc_req_mmap(struct fastrpc_user *fl, char __user *argp) |
1500 | 1520 | return err; |
1501 | 1521 | } |
1502 | 1522 |
|
| 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 | + |
1503 | 1651 | static long fastrpc_device_ioctl(struct file *file, unsigned int cmd, |
1504 | 1652 | unsigned long arg) |
1505 | 1653 | { |
@@ -1529,6 +1677,12 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int cmd, |
1529 | 1677 | case FASTRPC_IOCTL_MUNMAP: |
1530 | 1678 | err = fastrpc_req_munmap(fl, argp); |
1531 | 1679 | 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; |
1532 | 1686 | default: |
1533 | 1687 | err = -ENOTTY; |
1534 | 1688 | break; |
|
0 commit comments