blob: ecac12327d9f4eb76b0c09cd52710f5054720c74 [file] [log] [blame]
/*
* 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);
}