diff options
Diffstat (limited to 'src/rpcmem_android.c')
-rw-r--r-- | src/rpcmem_android.c | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/src/rpcmem_android.c b/src/rpcmem_android.c new file mode 100644 index 0000000..ecac123 --- /dev/null +++ b/src/rpcmem_android.c @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "rpcmem.h" +#include "verify.h" +#include "fastrpc_internal.h" +#include "AEEQList.h" +#include "AEEstd.h" +#include "apps_std.h" + +#include <stdlib.h> +#include <stdio.h> +#include <pthread.h> +#include <fcntl.h> +#include <string.h> +#include <unistd.h> +#include <sys/ioctl.h> +#include <sys/mman.h> +#include <errno.h> + +#define PAGE_SIZE 4096 +#define PAGE_MASK ~((uintptr_t)PAGE_SIZE - 1) + +static QList rpclst; +static pthread_mutex_t rpcmt; +struct rpc_info +{ + QNode qn; + void *buf; + void *aligned_buf; + int size; + int fd; +}; + +extern int open_device_node(int domain); +static int rpcmem_open_dev() +{ + return open_device_node(3); +} + +void rpcmem_init() +{ + int fd; + QList_Ctor(&rpclst); + pthread_mutex_init(&rpcmt, 0); +} + +void rpcmem_deinit() +{ + pthread_mutex_destroy(&rpcmt); +} + +int rpcmem_to_fd_internal(void *po) { + struct rpc_info *rinfo, *rfree = 0; + QNode *pn, *pnn; + + pthread_mutex_lock(&rpcmt); + QLIST_NEXTSAFE_FOR_ALL(&rpclst, pn, pnn) + { + rinfo = STD_RECOVER_REC(struct rpc_info, qn, pn); + if (rinfo->aligned_buf == po) + { + rfree = rinfo; + break; + } + } + pthread_mutex_unlock(&rpcmt); + + if (rfree) + return rfree->fd; + + return -1; +} + +int rpcmem_to_fd(void *po) { + return rpcmem_to_fd_internal(po); +} + + +void *rpcmem_alloc_internal(int heapid, uint32 flags, int size) +{ + struct rpc_info *rinfo; + struct fastrpc_alloc_dma_buf buf; + int nErr = 0; + (void)heapid; + (void)flags; + int dev = rpcmem_open_dev(); + + VERIFY(0 != (rinfo = calloc(1, sizeof(*rinfo)))); + + buf.size = size + PAGE_SIZE; + buf.fd = -1; + buf.flags = 0; + + VERIFY((0 == ioctl(dev, FASTRPC_IOCTL_ALLOC_DMA_BUFF, (unsigned long)&buf)) || errno == ENOTTY); + VERIFY(0 != (rinfo->buf = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, buf.fd, 0))); + rinfo->fd = buf.fd; + rinfo->aligned_buf = (void *)(((uintptr_t)rinfo->buf /*+ PAGE_SIZE*/) & PAGE_MASK); + rinfo->aligned_buf = rinfo->buf; + rinfo->size = size; + pthread_mutex_lock(&rpcmt); + QList_AppendNode(&rpclst, &rinfo->qn); + pthread_mutex_unlock(&rpcmt); + + return rinfo->aligned_buf; +bail: + if (nErr) + { + if (rinfo) + { + if (rinfo->buf) + { + free(rinfo->buf); + } + free(rinfo); + } + } + return 0; +} + +void rpcmem_free_internal(void *po) +{ + struct rpc_info *rinfo, *rfree = 0; + QNode *pn, *pnn; + int nErr = 0; + + pthread_mutex_lock(&rpcmt); + QLIST_NEXTSAFE_FOR_ALL(&rpclst, pn, pnn) + { + rinfo = STD_RECOVER_REC(struct rpc_info, qn, pn); + if (rinfo->aligned_buf == po) + { + rfree = rinfo; + QNode_Dequeue(&rinfo->qn); + break; + } + } + pthread_mutex_unlock(&rpcmt); + if (rfree) + { + int dev = rpcmem_open_dev(); + + munmap(rfree->buf, rfree->size); + free(rfree); + } +bail: + return; + +} + +void rpcmem_free(void* po) { + rpcmem_free_internal(po); +} + +void* rpcmem_alloc(int heapid, uint32 flags, int size) { + return rpcmem_alloc_internal(heapid, flags, size); +} |