mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-14 08:36:12 -04:00
Merge "msm: adsprpc: split init process function into smaller methods"
This commit is contained in:
commit
e323b2a635
1 changed files with 379 additions and 323 deletions
|
|
@ -65,14 +65,17 @@
|
|||
#define UL_SIZE 25
|
||||
#define PID_SIZE 10
|
||||
|
||||
#define AUDIO_PDR_ADSP_DTSI_PROPERTY_NAME "qcom,fastrpc-adsp-audio-pdr"
|
||||
#define AUDIO_PDR_SERVICE_LOCATION_CLIENT_NAME "audio_pdr_adsprpc"
|
||||
#define AUDIO_PDR_ADSP_SERVICE_NAME "avs/audio"
|
||||
#define ADSP_AUDIOPD_NAME "msm/adsp/audio_pd"
|
||||
|
||||
#define SENSORS_PDR_ADSP_DTSI_PROPERTY_NAME "qcom,fastrpc-adsp-sensors-pdr"
|
||||
#define SENSORS_PDR_ADSP_SERVICE_LOCATION_CLIENT_NAME "sensors_pdr_adsprpc"
|
||||
#define SENSORS_PDR_ADSP_SERVICE_NAME "tms/servreg"
|
||||
#define ADSP_SENSORPD_NAME "msm/adsp/sensor_pd"
|
||||
|
||||
#define SENSORS_PDR_SLPI_DTSI_PROPERTY_NAME "qcom,fastrpc-slpi-sensors-pdr"
|
||||
#define SENSORS_PDR_SLPI_SERVICE_LOCATION_CLIENT_NAME "sensors_pdr_sdsprpc"
|
||||
#define SENSORS_PDR_SLPI_SERVICE_NAME SENSORS_PDR_ADSP_SERVICE_NAME
|
||||
#define SLPI_SENSORPD_NAME "msm/slpi/sensor_pd"
|
||||
|
|
@ -200,6 +203,12 @@
|
|||
(int64_t *)(perf_ptr + offset)\
|
||||
: (int64_t *)NULL) : (int64_t *)NULL)
|
||||
|
||||
/* Macro for comparing local client and PD names with those from callback */
|
||||
#define COMPARE_SERVICE_LOCATOR_NAMES(cb_client, local_client, \
|
||||
cb_pdname, local_pdname) \
|
||||
((!strcmp(cb_client, local_client)) \
|
||||
&& (!strcmp(cb_pdname, local_pdname)))
|
||||
|
||||
#define IS_ASYNC_FASTRPC_AVAILABLE (1)
|
||||
|
||||
static int fastrpc_pdr_notifier_cb(struct notifier_block *nb,
|
||||
|
|
@ -2706,29 +2715,24 @@ static int fastrpc_mmap_remove_pdr(struct fastrpc_file *fl);
|
|||
static int fastrpc_channel_open(struct fastrpc_file *fl);
|
||||
static int fastrpc_mmap_remove_ssr(struct fastrpc_file *fl);
|
||||
|
||||
static void fastrpc_check_privileged_process(struct fastrpc_file *fl,
|
||||
struct fastrpc_ioctl_init_attrs *uproc)
|
||||
{
|
||||
unsigned int gid = sorted_lists_intersection(fl->gidlist.gids,
|
||||
fl->gidlist.gidcount, gfa.gidlist.gids, gfa.gidlist.gidcount);
|
||||
|
||||
/* disregard any privilege bits from userspace */
|
||||
uproc->attrs &= (~FASTRPC_MODE_PRIVILEGED);
|
||||
if (gid) {
|
||||
pr_info("adsprpc: %s: %s (PID %d, GID %u) is a privileged process\n",
|
||||
__func__, current->comm, fl->tgid, gid);
|
||||
uproc->attrs |= FASTRPC_MODE_PRIVILEGED;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This function makes a call to create a thread group in the root
|
||||
* process or static process on the remote subsystem.
|
||||
* Examples:
|
||||
* - guestOS daemons on all DSPs
|
||||
* - sensors daemon on sensorsPD on SLPI/ADSP
|
||||
*/
|
||||
static int fastrpc_init_attach_process(struct fastrpc_file *fl,
|
||||
struct fastrpc_ioctl_init *init)
|
||||
{
|
||||
int err = 0;
|
||||
int err = 0, tgid = fl->tgid;
|
||||
remote_arg_t ra[1];
|
||||
struct fastrpc_ioctl_invoke_async ioctl;
|
||||
int tgid = fl->tgid;
|
||||
|
||||
/*
|
||||
* Prepare remote arguments for creating thread group
|
||||
* in guestOS/staticPD on the remote subsystem.
|
||||
*/
|
||||
ra[0].buf.pv = (void *)&tgid;
|
||||
ra[0].buf.len = sizeof(tgid);
|
||||
ioctl.inv.handle = FASTRPC_STATIC_HANDLE_PROCESS_GROUP;
|
||||
|
|
@ -2738,6 +2742,7 @@ static int fastrpc_init_attach_process(struct fastrpc_file *fl,
|
|||
ioctl.attrs = NULL;
|
||||
ioctl.crc = NULL;
|
||||
ioctl.job = NULL;
|
||||
|
||||
if (init->flags == FASTRPC_INIT_ATTACH)
|
||||
fl->pd = 0;
|
||||
else if (init->flags == FASTRPC_INIT_ATTACH_SENSORS) {
|
||||
|
|
@ -2747,256 +2752,164 @@ static int fastrpc_init_attach_process(struct fastrpc_file *fl,
|
|||
else if (fl->cid == SDSP_DOMAIN_ID)
|
||||
fl->servloc_name =
|
||||
SENSORS_PDR_SLPI_SERVICE_LOCATION_CLIENT_NAME;
|
||||
/* Setting to 2 will route the message to sensorsPD */
|
||||
fl->pd = 2;
|
||||
}
|
||||
VERIFY(err, !(err = fastrpc_internal_invoke(fl,
|
||||
FASTRPC_MODE_PARALLEL, 1, &ioctl)));
|
||||
|
||||
err = fastrpc_internal_invoke(fl, FASTRPC_MODE_PARALLEL, 1, &ioctl);
|
||||
if (err)
|
||||
goto bail;
|
||||
bail:
|
||||
return err;
|
||||
}
|
||||
static int fastrpc_init_process(struct fastrpc_file *fl,
|
||||
|
||||
/*
|
||||
* This function makes a call to spawn a dynamic process
|
||||
* on the remote subsystem.
|
||||
* Example: all compute offloads to CDSP
|
||||
*/
|
||||
static int fastrpc_init_create_dynamic_process(struct fastrpc_file *fl,
|
||||
struct fastrpc_ioctl_init_attrs *uproc)
|
||||
{
|
||||
int err = 0, rh_hyp_done = 0;
|
||||
struct fastrpc_apps *me = &gfa;
|
||||
int err = 0, memlen = 0, mflags = 0;
|
||||
struct fastrpc_ioctl_invoke_async ioctl;
|
||||
struct fastrpc_ioctl_init *init = &uproc->init;
|
||||
struct smq_phy_page pages[1];
|
||||
struct fastrpc_mmap *file = NULL, *mem = NULL;
|
||||
struct fastrpc_mmap *file = NULL;
|
||||
struct fastrpc_buf *imem = NULL;
|
||||
unsigned long imem_dma_attr = 0;
|
||||
char *proc_name = NULL;
|
||||
remote_arg_t ra[6];
|
||||
int fds[6];
|
||||
unsigned int gid = 0, one_mb = 1024*1024;
|
||||
struct {
|
||||
int pgid;
|
||||
unsigned int namelen;
|
||||
unsigned int filelen;
|
||||
unsigned int pageslen;
|
||||
int attrs;
|
||||
int siglen;
|
||||
} inbuf;
|
||||
|
||||
VERIFY(err, init->filelen >= 0 &&
|
||||
init->filelen < INIT_FILELEN_MAX);
|
||||
inbuf.pgid = fl->tgid;
|
||||
inbuf.namelen = strlen(current->comm) + 1;
|
||||
inbuf.filelen = init->filelen;
|
||||
fl->pd = 1;
|
||||
|
||||
/* Check if file memory passed by userspace is valid */
|
||||
VERIFY(err, access_ok((void __user *)init->file, init->filelen));
|
||||
if (err)
|
||||
goto bail;
|
||||
VERIFY(err, init->memlen >= 0 &&
|
||||
init->memlen < INIT_MEMLEN_MAX);
|
||||
if (err)
|
||||
goto bail;
|
||||
VERIFY(err, 0 == (err = fastrpc_channel_open(fl)));
|
||||
if (err)
|
||||
goto bail;
|
||||
if (init->flags == FASTRPC_INIT_ATTACH ||
|
||||
init->flags == FASTRPC_INIT_ATTACH_SENSORS) {
|
||||
VERIFY(err, !(err = fastrpc_init_attach_process(fl, init)));
|
||||
if (init->filelen) {
|
||||
/* Map the shell file buffer to remote subsystem */
|
||||
mutex_lock(&fl->map_mutex);
|
||||
err = fastrpc_mmap_create(fl, init->filefd, 0,
|
||||
init->file, init->filelen, mflags, &file);
|
||||
mutex_unlock(&fl->map_mutex);
|
||||
if (err)
|
||||
goto bail;
|
||||
} else if (init->flags == FASTRPC_INIT_CREATE) {
|
||||
int memlen;
|
||||
}
|
||||
inbuf.pageslen = 1;
|
||||
|
||||
remote_arg_t ra[6];
|
||||
int fds[6];
|
||||
int mflags = 0;
|
||||
struct {
|
||||
int pgid;
|
||||
unsigned int namelen;
|
||||
unsigned int filelen;
|
||||
unsigned int pageslen;
|
||||
int attrs;
|
||||
int siglen;
|
||||
} inbuf;
|
||||
/* Disregard any privilege bits from userspace */
|
||||
uproc->attrs &= (~FASTRPC_MODE_PRIVILEGED);
|
||||
|
||||
inbuf.pgid = fl->tgid;
|
||||
inbuf.namelen = strlen(current->comm) + 1;
|
||||
inbuf.filelen = init->filelen;
|
||||
fl->pd = 1;
|
||||
/*
|
||||
* Check if the primary or supplementary group(s) of the process is
|
||||
* one of the 'privileged' fastrpc GIDs stored in the device-tree.
|
||||
*/
|
||||
gid = sorted_lists_intersection(fl->gidlist.gids,
|
||||
fl->gidlist.gidcount, gfa.gidlist.gids, gfa.gidlist.gidcount);
|
||||
if (gid) {
|
||||
pr_info("adsprpc: %s: %s (PID %d, GID %u) is a privileged process\n",
|
||||
__func__, current->comm, fl->tgid, gid);
|
||||
uproc->attrs |= FASTRPC_MODE_PRIVILEGED;
|
||||
}
|
||||
|
||||
VERIFY(err, access_ok((void __user *)init->file,
|
||||
init->filelen));
|
||||
if (err)
|
||||
goto bail;
|
||||
if (init->filelen) {
|
||||
mutex_lock(&fl->map_mutex);
|
||||
VERIFY(err, !fastrpc_mmap_create(fl, init->filefd, 0,
|
||||
init->file, init->filelen, mflags, &file));
|
||||
mutex_unlock(&fl->map_mutex);
|
||||
if (err)
|
||||
goto bail;
|
||||
}
|
||||
inbuf.pageslen = 1;
|
||||
|
||||
fastrpc_check_privileged_process(fl, uproc);
|
||||
|
||||
VERIFY(err, !init->mem);
|
||||
if (err) {
|
||||
err = -EINVAL;
|
||||
pr_err("adsprpc: %s: %s: ERROR: donated memory allocated in userspace\n",
|
||||
current->comm, __func__);
|
||||
goto bail;
|
||||
}
|
||||
memlen = ALIGN(max(1024*1024*3, (int)init->filelen * 4),
|
||||
1024*1024);
|
||||
imem_dma_attr = DMA_ATTR_EXEC_MAPPING |
|
||||
DMA_ATTR_DELAYED_UNMAP |
|
||||
DMA_ATTR_NO_KERNEL_MAPPING;
|
||||
err = fastrpc_buf_alloc(fl, memlen, imem_dma_attr, 0, 0, &imem);
|
||||
if (err)
|
||||
goto bail;
|
||||
if (fl->init_mem)
|
||||
fastrpc_buf_free(fl->init_mem, 0);
|
||||
|
||||
fl->init_mem = imem;
|
||||
inbuf.pageslen = 1;
|
||||
ra[0].buf.pv = (void *)&inbuf;
|
||||
ra[0].buf.len = sizeof(inbuf);
|
||||
fds[0] = -1;
|
||||
|
||||
ra[1].buf.pv = (void *)current->comm;
|
||||
ra[1].buf.len = inbuf.namelen;
|
||||
fds[1] = -1;
|
||||
|
||||
ra[2].buf.pv = (void *)init->file;
|
||||
ra[2].buf.len = inbuf.filelen;
|
||||
fds[2] = init->filefd;
|
||||
|
||||
pages[0].addr = imem->phys;
|
||||
pages[0].size = imem->size;
|
||||
ra[3].buf.pv = (void *)pages;
|
||||
ra[3].buf.len = 1 * sizeof(*pages);
|
||||
fds[3] = -1;
|
||||
|
||||
inbuf.attrs = uproc->attrs;
|
||||
ra[4].buf.pv = (void *)&(inbuf.attrs);
|
||||
ra[4].buf.len = sizeof(inbuf.attrs);
|
||||
fds[4] = -1;
|
||||
|
||||
inbuf.siglen = uproc->siglen;
|
||||
ra[5].buf.pv = (void *)&(inbuf.siglen);
|
||||
ra[5].buf.len = sizeof(inbuf.siglen);
|
||||
fds[5] = -1;
|
||||
|
||||
ioctl.inv.handle = FASTRPC_STATIC_HANDLE_PROCESS_GROUP;
|
||||
ioctl.inv.sc = REMOTE_SCALARS_MAKE(6, 4, 0);
|
||||
if (uproc->attrs)
|
||||
ioctl.inv.sc = REMOTE_SCALARS_MAKE(7, 6, 0);
|
||||
ioctl.inv.pra = ra;
|
||||
ioctl.fds = fds;
|
||||
ioctl.attrs = NULL;
|
||||
ioctl.crc = NULL;
|
||||
ioctl.job = NULL;
|
||||
VERIFY(err, !(err = fastrpc_internal_invoke(fl,
|
||||
FASTRPC_MODE_PARALLEL, 1, &ioctl)));
|
||||
if (err)
|
||||
goto bail;
|
||||
} else if (init->flags == FASTRPC_INIT_CREATE_STATIC) {
|
||||
remote_arg_t ra[3];
|
||||
uint64_t phys = 0;
|
||||
size_t size = 0;
|
||||
int fds[3];
|
||||
struct {
|
||||
int pgid;
|
||||
unsigned int namelen;
|
||||
unsigned int pageslen;
|
||||
} inbuf;
|
||||
|
||||
if (!init->filelen)
|
||||
goto bail;
|
||||
|
||||
proc_name = kzalloc(init->filelen, GFP_KERNEL);
|
||||
VERIFY(err, !IS_ERR_OR_NULL(proc_name));
|
||||
if (err)
|
||||
goto bail;
|
||||
VERIFY(err, 0 == copy_from_user((void *)proc_name,
|
||||
(void __user *)init->file, init->filelen));
|
||||
if (err)
|
||||
goto bail;
|
||||
|
||||
fl->pd = 1;
|
||||
inbuf.pgid = current->tgid;
|
||||
inbuf.namelen = init->filelen;
|
||||
inbuf.pageslen = 0;
|
||||
|
||||
if (!strcmp(proc_name, "audiopd")) {
|
||||
fl->servloc_name =
|
||||
AUDIO_PDR_SERVICE_LOCATION_CLIENT_NAME;
|
||||
VERIFY(err, !fastrpc_mmap_remove_pdr(fl));
|
||||
if (err)
|
||||
goto bail;
|
||||
}
|
||||
|
||||
if (!me->staticpd_flags && !(me->legacy_remote_heap)) {
|
||||
inbuf.pageslen = 1;
|
||||
mutex_lock(&fl->map_mutex);
|
||||
err = fastrpc_mmap_create(fl, -1, 0, init->mem,
|
||||
init->memlen, ADSP_MMAP_REMOTE_HEAP_ADDR,
|
||||
&mem);
|
||||
mutex_unlock(&fl->map_mutex);
|
||||
if (err)
|
||||
goto bail;
|
||||
phys = mem->phys;
|
||||
size = mem->size;
|
||||
if (me->channel[fl->cid].rhvm.vmid) {
|
||||
err = hyp_assign_phys(phys,
|
||||
(uint64_t)size, hlosvm, 1,
|
||||
me->channel[fl->cid].rhvm.vmid,
|
||||
me->channel[fl->cid].rhvm.vmperm,
|
||||
me->channel[fl->cid].rhvm.vmcount);
|
||||
if (err) {
|
||||
pr_err("adsprpc: %s: rh hyp assign failed with %d for phys 0x%llx, size %zd\n",
|
||||
__func__, err, phys, size);
|
||||
goto bail;
|
||||
}
|
||||
rh_hyp_done = 1;
|
||||
}
|
||||
me->staticpd_flags = 1;
|
||||
}
|
||||
|
||||
ra[0].buf.pv = (void *)&inbuf;
|
||||
ra[0].buf.len = sizeof(inbuf);
|
||||
fds[0] = -1;
|
||||
|
||||
ra[1].buf.pv = (void *)proc_name;
|
||||
ra[1].buf.len = inbuf.namelen;
|
||||
fds[1] = -1;
|
||||
|
||||
pages[0].addr = phys;
|
||||
pages[0].size = size;
|
||||
|
||||
ra[2].buf.pv = (void *)pages;
|
||||
ra[2].buf.len = sizeof(*pages);
|
||||
fds[2] = -1;
|
||||
ioctl.inv.handle = FASTRPC_STATIC_HANDLE_PROCESS_GROUP;
|
||||
|
||||
ioctl.inv.sc = REMOTE_SCALARS_MAKE(8, 3, 0);
|
||||
ioctl.inv.pra = ra;
|
||||
ioctl.fds = NULL;
|
||||
ioctl.attrs = NULL;
|
||||
ioctl.crc = NULL;
|
||||
ioctl.job = NULL;
|
||||
VERIFY(err, !(err = fastrpc_internal_invoke(fl,
|
||||
FASTRPC_MODE_PARALLEL, 1, &ioctl)));
|
||||
if (err)
|
||||
goto bail;
|
||||
} else {
|
||||
err = -ENOTTY;
|
||||
/*
|
||||
* Userspace client should try to allocate the initial memory donated
|
||||
* to remote subsystem as only the kernel and DSP should have access
|
||||
* to that memory.
|
||||
*/
|
||||
VERIFY(err, !init->mem);
|
||||
if (err) {
|
||||
err = -EINVAL;
|
||||
pr_err("adsprpc: %s: %s: ERROR: donated memory allocated in userspace\n",
|
||||
current->comm, __func__);
|
||||
goto bail;
|
||||
}
|
||||
fl->dsp_proc_init = 1;
|
||||
bail:
|
||||
kfree(proc_name);
|
||||
if (err && (init->flags == FASTRPC_INIT_CREATE_STATIC))
|
||||
me->staticpd_flags = 0;
|
||||
if (mem && err) {
|
||||
if (mem->flags == ADSP_MMAP_REMOTE_HEAP_ADDR
|
||||
&& me->channel[fl->cid].rhvm.vmid && rh_hyp_done) {
|
||||
int hyp_err = 0;
|
||||
/* Free any previous donated memory */
|
||||
if (fl->init_mem)
|
||||
fastrpc_buf_free(fl->init_mem, 0);
|
||||
|
||||
hyp_err = hyp_assign_phys(mem->phys,
|
||||
(uint64_t)mem->size,
|
||||
me->channel[fl->cid].rhvm.vmid,
|
||||
me->channel[fl->cid].rhvm.vmcount,
|
||||
hlosvm, hlosvmperm, 1);
|
||||
if (hyp_err)
|
||||
pr_warn("adsprpc: %s: %s: rh hyp unassign failed with %d for phys 0x%llx of size %zd\n",
|
||||
__func__, current->comm,
|
||||
hyp_err, mem->phys, mem->size);
|
||||
}
|
||||
/* Allocate DMA buffer in kernel for donating to remote process */
|
||||
memlen = ALIGN(max(3*one_mb, init->filelen * 4), one_mb);
|
||||
imem_dma_attr = DMA_ATTR_EXEC_MAPPING |
|
||||
DMA_ATTR_DELAYED_UNMAP |
|
||||
DMA_ATTR_NO_KERNEL_MAPPING;
|
||||
err = fastrpc_buf_alloc(fl, memlen, imem_dma_attr, 0, 0, &imem);
|
||||
if (err)
|
||||
goto bail;
|
||||
fl->init_mem = imem;
|
||||
|
||||
/*
|
||||
* Prepare remote arguments for dynamic process create
|
||||
* call to remote subsystem.
|
||||
*/
|
||||
inbuf.pageslen = 1;
|
||||
ra[0].buf.pv = (void *)&inbuf;
|
||||
ra[0].buf.len = sizeof(inbuf);
|
||||
fds[0] = -1;
|
||||
|
||||
ra[1].buf.pv = (void *)current->comm;
|
||||
ra[1].buf.len = inbuf.namelen;
|
||||
fds[1] = -1;
|
||||
|
||||
ra[2].buf.pv = (void *)init->file;
|
||||
ra[2].buf.len = inbuf.filelen;
|
||||
fds[2] = init->filefd;
|
||||
|
||||
pages[0].addr = imem->phys;
|
||||
pages[0].size = imem->size;
|
||||
ra[3].buf.pv = (void *)pages;
|
||||
ra[3].buf.len = 1 * sizeof(*pages);
|
||||
fds[3] = -1;
|
||||
|
||||
inbuf.attrs = uproc->attrs;
|
||||
ra[4].buf.pv = (void *)&(inbuf.attrs);
|
||||
ra[4].buf.len = sizeof(inbuf.attrs);
|
||||
fds[4] = -1;
|
||||
|
||||
inbuf.siglen = uproc->siglen;
|
||||
ra[5].buf.pv = (void *)&(inbuf.siglen);
|
||||
ra[5].buf.len = sizeof(inbuf.siglen);
|
||||
fds[5] = -1;
|
||||
|
||||
ioctl.inv.handle = FASTRPC_STATIC_HANDLE_PROCESS_GROUP;
|
||||
/*
|
||||
* Choose appropriate remote method ID depending on whether the
|
||||
* HLOS process has any attributes enabled (like unsignedPD,
|
||||
* critical process, adaptive QoS, CRC checks etc).
|
||||
*/
|
||||
ioctl.inv.sc = REMOTE_SCALARS_MAKE(6, 4, 0);
|
||||
if (uproc->attrs)
|
||||
ioctl.inv.sc = REMOTE_SCALARS_MAKE(7, 6, 0);
|
||||
ioctl.inv.pra = ra;
|
||||
ioctl.fds = fds;
|
||||
ioctl.attrs = NULL;
|
||||
ioctl.crc = NULL;
|
||||
ioctl.job = NULL;
|
||||
err = fastrpc_internal_invoke(fl, FASTRPC_MODE_PARALLEL, 1, &ioctl);
|
||||
if (err)
|
||||
goto bail;
|
||||
bail:
|
||||
/*
|
||||
* Shell is loaded into the donated memory on remote subsystem. So, the
|
||||
* original file buffer can be DMA unmapped. In case of a failure also,
|
||||
* the mapping needs to be removed.
|
||||
*/
|
||||
if (file) {
|
||||
mutex_lock(&fl->map_mutex);
|
||||
fastrpc_mmap_free(mem, 0);
|
||||
fastrpc_mmap_free(file, 0);
|
||||
mutex_unlock(&fl->map_mutex);
|
||||
}
|
||||
if (err) {
|
||||
|
|
@ -3005,14 +2918,179 @@ bail:
|
|||
fl->init_mem = NULL;
|
||||
}
|
||||
}
|
||||
if (file) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function makes a call to create a thread group in the static
|
||||
* process on the remote subsystem.
|
||||
* Example: audio daemon 'adsprpcd' on audioPD on ADSP
|
||||
*/
|
||||
static int fastrpc_init_create_static_process(struct fastrpc_file *fl,
|
||||
struct fastrpc_ioctl_init *init)
|
||||
{
|
||||
int err = 0, rh_hyp_done = 0;
|
||||
struct fastrpc_apps *me = &gfa;
|
||||
struct fastrpc_ioctl_invoke_async ioctl;
|
||||
struct smq_phy_page pages[1];
|
||||
struct fastrpc_mmap *mem = NULL;
|
||||
char *proc_name = NULL;
|
||||
remote_arg_t ra[3];
|
||||
uint64_t phys = 0;
|
||||
size_t size = 0;
|
||||
int fds[3];
|
||||
struct secure_vm *rhvm = &me->channel[fl->cid].rhvm;
|
||||
struct {
|
||||
int pgid;
|
||||
unsigned int namelen;
|
||||
unsigned int pageslen;
|
||||
} inbuf;
|
||||
|
||||
if (!init->filelen)
|
||||
goto bail;
|
||||
|
||||
proc_name = kzalloc(init->filelen, GFP_KERNEL);
|
||||
VERIFY(err, !IS_ERR_OR_NULL(proc_name));
|
||||
if (err)
|
||||
goto bail;
|
||||
err = copy_from_user((void *)proc_name,
|
||||
(void __user *)init->file, init->filelen);
|
||||
if (err)
|
||||
goto bail;
|
||||
|
||||
fl->pd = 1;
|
||||
inbuf.pgid = fl->tgid;
|
||||
inbuf.namelen = init->filelen;
|
||||
inbuf.pageslen = 0;
|
||||
|
||||
if (!strcmp(proc_name, "audiopd")) {
|
||||
fl->servloc_name = AUDIO_PDR_SERVICE_LOCATION_CLIENT_NAME;
|
||||
/*
|
||||
* Remove any previous mappings in case process is trying
|
||||
* to reconnect after a PD restart on remote subsystem.
|
||||
*/
|
||||
err = fastrpc_mmap_remove_pdr(fl);
|
||||
if (err)
|
||||
goto bail;
|
||||
}
|
||||
|
||||
if (!me->staticpd_flags && !me->legacy_remote_heap) {
|
||||
inbuf.pageslen = 1;
|
||||
mutex_lock(&fl->map_mutex);
|
||||
fastrpc_mmap_free(file, 0);
|
||||
err = fastrpc_mmap_create(fl, -1, 0, init->mem,
|
||||
init->memlen, ADSP_MMAP_REMOTE_HEAP_ADDR, &mem);
|
||||
mutex_unlock(&fl->map_mutex);
|
||||
if (err)
|
||||
goto bail;
|
||||
phys = mem->phys;
|
||||
size = mem->size;
|
||||
/*
|
||||
* If remote-heap VMIDs are defined in DTSI, then do
|
||||
* hyp_assign from HLOS to those VMs (LPASS, ADSP).
|
||||
*/
|
||||
if (rhvm->vmid) {
|
||||
err = hyp_assign_phys(phys, (uint64_t)size,
|
||||
hlosvm, 1,
|
||||
rhvm->vmid, rhvm->vmperm, rhvm->vmcount);
|
||||
if (err) {
|
||||
pr_err("adsprpc: %s: %s: rh hyp assign failed with %d for phys 0x%llx, size %zu\n",
|
||||
__func__, current->comm,
|
||||
err, phys, size);
|
||||
goto bail;
|
||||
}
|
||||
rh_hyp_done = 1;
|
||||
}
|
||||
me->staticpd_flags = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prepare remote arguments for static process create
|
||||
* call to remote subsystem.
|
||||
*/
|
||||
ra[0].buf.pv = (void *)&inbuf;
|
||||
ra[0].buf.len = sizeof(inbuf);
|
||||
fds[0] = -1;
|
||||
|
||||
ra[1].buf.pv = (void *)proc_name;
|
||||
ra[1].buf.len = inbuf.namelen;
|
||||
fds[1] = -1;
|
||||
|
||||
pages[0].addr = phys;
|
||||
pages[0].size = size;
|
||||
|
||||
ra[2].buf.pv = (void *)pages;
|
||||
ra[2].buf.len = sizeof(*pages);
|
||||
fds[2] = -1;
|
||||
ioctl.inv.handle = FASTRPC_STATIC_HANDLE_PROCESS_GROUP;
|
||||
|
||||
ioctl.inv.sc = REMOTE_SCALARS_MAKE(8, 3, 0);
|
||||
ioctl.inv.pra = ra;
|
||||
ioctl.fds = NULL;
|
||||
ioctl.attrs = NULL;
|
||||
ioctl.crc = NULL;
|
||||
ioctl.job = NULL;
|
||||
err = fastrpc_internal_invoke(fl, FASTRPC_MODE_PARALLEL, 1, &ioctl);
|
||||
if (err)
|
||||
goto bail;
|
||||
bail:
|
||||
kfree(proc_name);
|
||||
if (err) {
|
||||
me->staticpd_flags = 0;
|
||||
if (rh_hyp_done) {
|
||||
int hyp_err = 0;
|
||||
|
||||
/* Assign memory back to HLOS in case of errors */
|
||||
hyp_err = hyp_assign_phys(phys, (uint64_t)size,
|
||||
rhvm->vmid, rhvm->vmcount,
|
||||
hlosvm, hlosvmperm, 1);
|
||||
if (hyp_err)
|
||||
pr_warn("adsprpc: %s: %s: rh hyp unassign failed with %d for phys 0x%llx of size %zu\n",
|
||||
__func__, current->comm,
|
||||
hyp_err, phys, size);
|
||||
}
|
||||
mutex_lock(&fl->map_mutex);
|
||||
fastrpc_mmap_free(mem, 0);
|
||||
mutex_unlock(&fl->map_mutex);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static int fastrpc_init_process(struct fastrpc_file *fl,
|
||||
struct fastrpc_ioctl_init_attrs *uproc)
|
||||
{
|
||||
int err = 0;
|
||||
struct fastrpc_ioctl_init *init = &uproc->init;
|
||||
|
||||
VERIFY(err, init->filelen < INIT_FILELEN_MAX
|
||||
&& init->memlen < INIT_MEMLEN_MAX);
|
||||
if (err)
|
||||
goto bail;
|
||||
err = fastrpc_channel_open(fl);
|
||||
if (err)
|
||||
goto bail;
|
||||
|
||||
switch (init->flags) {
|
||||
case FASTRPC_INIT_ATTACH:
|
||||
case FASTRPC_INIT_ATTACH_SENSORS:
|
||||
err = fastrpc_init_attach_process(fl, init);
|
||||
break;
|
||||
case FASTRPC_INIT_CREATE:
|
||||
err = fastrpc_init_create_dynamic_process(fl, uproc);
|
||||
break;
|
||||
case FASTRPC_INIT_CREATE_STATIC:
|
||||
err = fastrpc_init_create_static_process(fl, init);
|
||||
break;
|
||||
default:
|
||||
err = -ENOTTY;
|
||||
break;
|
||||
}
|
||||
if (err)
|
||||
goto bail;
|
||||
fl->dsp_proc_init = 1;
|
||||
bail:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int fastrpc_kstat(const char *filename, struct kstat *stat)
|
||||
{
|
||||
int result;
|
||||
|
|
@ -4882,35 +4960,44 @@ static int fastrpc_pdr_notifier_cb(struct notifier_block *pdrnb,
|
|||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
/*
|
||||
* The service locator callback function where the PDR notification
|
||||
* callback functions are registered.
|
||||
* (like audioPD on ADSP, sensorPD on SLPI/ADSP)
|
||||
*/
|
||||
static int fastrpc_get_service_location_notify(struct notifier_block *nb,
|
||||
unsigned long opcode, void *data)
|
||||
{
|
||||
struct fastrpc_static_pd *spd;
|
||||
struct pd_qmi_client_data *pdr = data;
|
||||
int curr_state = 0, i = 0;
|
||||
char *cb_pdname = NULL, *subsys = NULL;
|
||||
uint32_t instance_id = 0;
|
||||
|
||||
spd = container_of(nb, struct fastrpc_static_pd, get_service_nb);
|
||||
subsys = gcinfo[spd->cid].subsys;
|
||||
if (opcode == LOCATOR_DOWN) {
|
||||
pr_warn("adsprpc: %s: PDR notifier locator for %s is down for %s\n",
|
||||
__func__, gcinfo[spd->cid].subsys,
|
||||
spd->servloc_name);
|
||||
__func__, subsys, spd->servloc_name);
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
for (i = 0; i < pdr->total_domains; i++) {
|
||||
if ((!strcmp(spd->servloc_name,
|
||||
AUDIO_PDR_SERVICE_LOCATION_CLIENT_NAME))
|
||||
&& (!strcmp(pdr->domain_list[i].name,
|
||||
ADSP_AUDIOPD_NAME))) {
|
||||
goto pdr_register;
|
||||
} else if ((!strcmp(spd->servloc_name,
|
||||
SENSORS_PDR_ADSP_SERVICE_LOCATION_CLIENT_NAME))
|
||||
&& (!strcmp(pdr->domain_list[i].name,
|
||||
ADSP_SENSORPD_NAME))) {
|
||||
goto pdr_register;
|
||||
} else if ((!strcmp(spd->servloc_name,
|
||||
SENSORS_PDR_SLPI_SERVICE_LOCATION_CLIENT_NAME))
|
||||
&& (!strcmp(pdr->domain_list[i].name,
|
||||
SLPI_SENSORPD_NAME))) {
|
||||
cb_pdname = pdr->domain_list[i].name;
|
||||
instance_id = pdr->domain_list[i].instance_id;
|
||||
|
||||
/* Check the client and staticPD in the callback */
|
||||
if (COMPARE_SERVICE_LOCATOR_NAMES(spd->servloc_name,
|
||||
AUDIO_PDR_SERVICE_LOCATION_CLIENT_NAME,
|
||||
cb_pdname, ADSP_AUDIOPD_NAME) ||
|
||||
|
||||
COMPARE_SERVICE_LOCATOR_NAMES(spd->servloc_name,
|
||||
SENSORS_PDR_ADSP_SERVICE_LOCATION_CLIENT_NAME,
|
||||
cb_pdname, ADSP_SENSORPD_NAME) ||
|
||||
|
||||
COMPARE_SERVICE_LOCATOR_NAMES(spd->servloc_name,
|
||||
SENSORS_PDR_SLPI_SERVICE_LOCATION_CLIENT_NAME,
|
||||
cb_pdname, SLPI_SENSORPD_NAME)) {
|
||||
|
||||
goto pdr_register;
|
||||
}
|
||||
}
|
||||
|
|
@ -4918,35 +5005,28 @@ static int fastrpc_get_service_location_notify(struct notifier_block *nb,
|
|||
|
||||
pdr_register:
|
||||
if (!spd->pdrhandle) {
|
||||
spd->pdrhandle =
|
||||
service_notif_register_notifier(
|
||||
pdr->domain_list[i].name,
|
||||
pdr->domain_list[i].instance_id,
|
||||
&spd->pdrnb, &curr_state);
|
||||
/* Register the PDR notifier callback function */
|
||||
spd->pdrhandle = service_notif_register_notifier(cb_pdname,
|
||||
instance_id, &spd->pdrnb, &curr_state);
|
||||
if (IS_ERR_OR_NULL(spd->pdrhandle))
|
||||
pr_warn("adsprpc: %s: PDR notifier for %s register failed for %s (%s) with err %ld\n",
|
||||
__func__, gcinfo[spd->cid].subsys,
|
||||
pdr->domain_list[i].name, spd->servloc_name,
|
||||
__func__, subsys, cb_pdname, spd->servloc_name,
|
||||
PTR_ERR(spd->pdrhandle));
|
||||
else
|
||||
pr_info("adsprpc: %s: PDR notifier for %s registered for %s (%s)\n",
|
||||
__func__, gcinfo[spd->cid].subsys,
|
||||
pdr->domain_list[i].name, spd->servloc_name);
|
||||
__func__, subsys, cb_pdname, spd->servloc_name);
|
||||
} else {
|
||||
pr_warn("adsprpc: %s: %s (%s) notifier is already registered for %s\n",
|
||||
__func__, pdr->domain_list[i].name,
|
||||
spd->servloc_name, gcinfo[spd->cid].subsys);
|
||||
__func__, cb_pdname, spd->servloc_name, subsys);
|
||||
}
|
||||
|
||||
if (curr_state == SERVREG_NOTIF_SERVICE_STATE_UP_V01) {
|
||||
pr_info("adsprpc: %s: %s (%s) PDR service for %s is up\n",
|
||||
__func__, spd->servloc_name, pdr->domain_list[i].name,
|
||||
gcinfo[spd->cid].subsys);
|
||||
__func__, spd->servloc_name, cb_pdname, subsys);
|
||||
spd->ispdup = 1;
|
||||
} else if (curr_state == SERVREG_NOTIF_SERVICE_STATE_UNINIT_V01) {
|
||||
pr_info("adsprpc: %s: %s (%s) PDR service for %s is uninitialized\n",
|
||||
__func__, spd->servloc_name, pdr->domain_list[i].name,
|
||||
gcinfo[spd->cid].subsys);
|
||||
__func__, spd->servloc_name, cb_pdname, subsys);
|
||||
}
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
|
@ -5146,6 +5226,36 @@ static void configure_secure_channels(uint32_t secure_domains)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is used to create the service locator required for
|
||||
* registering for remote process restart (PDR) notifications if that
|
||||
* PDR property has been enabled in the fastrpc node on the DTSI.
|
||||
*/
|
||||
static int fastrpc_setup_service_locator(struct device *dev,
|
||||
const char *propname, char *client_name, char *service_name)
|
||||
{
|
||||
int err = 0, session = -1, cid = -1;
|
||||
struct fastrpc_apps *me = &gfa;
|
||||
|
||||
if (of_property_read_bool(dev->of_node, propname)) {
|
||||
err = fastrpc_get_spd_session(client_name, &session, &cid);
|
||||
if (err)
|
||||
goto bail;
|
||||
/* Register the service locator's callback function */
|
||||
me->channel[cid].spd[session].get_service_nb.notifier_call =
|
||||
fastrpc_get_service_location_notify;
|
||||
err = get_service_location(client_name, service_name,
|
||||
&me->channel[cid].spd[session].get_service_nb);
|
||||
if (err)
|
||||
pr_warn("adsprpc: %s: get service location failed with %d for %s (%s)\n",
|
||||
__func__, err, service_name, client_name);
|
||||
else
|
||||
pr_info("adsprpc: %s: service location enabled for %s (%s)\n",
|
||||
__func__, service_name, client_name);
|
||||
}
|
||||
bail:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int fastrpc_probe(struct platform_device *pdev)
|
||||
{
|
||||
|
|
@ -5153,8 +5263,7 @@ static int fastrpc_probe(struct platform_device *pdev)
|
|||
struct fastrpc_apps *me = &gfa;
|
||||
struct device *dev = &pdev->dev;
|
||||
int ret = 0;
|
||||
uint32_t secure_domains;
|
||||
int session = -1, cid = -1;
|
||||
uint32_t secure_domains = 0;
|
||||
|
||||
if (of_device_is_compatible(dev->of_node,
|
||||
"qcom,msm-fastrpc-compute")) {
|
||||
|
|
@ -5192,70 +5301,17 @@ static int fastrpc_probe(struct platform_device *pdev)
|
|||
}
|
||||
me->legacy_remote_heap = of_property_read_bool(dev->of_node,
|
||||
"qcom,fastrpc-legacy-remote-heap");
|
||||
if (of_property_read_bool(dev->of_node,
|
||||
"qcom,fastrpc-adsp-audio-pdr")) {
|
||||
err = fastrpc_get_spd_session(
|
||||
AUDIO_PDR_SERVICE_LOCATION_CLIENT_NAME, &session, &cid);
|
||||
if (err)
|
||||
goto spdbail;
|
||||
me->channel[cid].spd[session].get_service_nb.notifier_call =
|
||||
fastrpc_get_service_location_notify;
|
||||
ret = get_service_location(
|
||||
AUDIO_PDR_SERVICE_LOCATION_CLIENT_NAME,
|
||||
AUDIO_PDR_ADSP_SERVICE_NAME,
|
||||
&me->channel[cid].spd[session].get_service_nb);
|
||||
if (ret)
|
||||
pr_warn("adsprpc: %s: get service location failed with %d for %s (%s)\n",
|
||||
__func__, ret, AUDIO_PDR_ADSP_SERVICE_NAME,
|
||||
AUDIO_PDR_SERVICE_LOCATION_CLIENT_NAME);
|
||||
else
|
||||
pr_info("adsprpc: %s: service location enabled for %s (%s)\n",
|
||||
__func__, AUDIO_PDR_ADSP_SERVICE_NAME,
|
||||
AUDIO_PDR_SERVICE_LOCATION_CLIENT_NAME);
|
||||
}
|
||||
if (of_property_read_bool(dev->of_node,
|
||||
"qcom,fastrpc-adsp-sensors-pdr")) {
|
||||
err = fastrpc_get_spd_session(
|
||||
SENSORS_PDR_ADSP_SERVICE_LOCATION_CLIENT_NAME, &session, &cid);
|
||||
if (err)
|
||||
goto spdbail;
|
||||
me->channel[cid].spd[session].get_service_nb.notifier_call =
|
||||
fastrpc_get_service_location_notify;
|
||||
ret = get_service_location(
|
||||
SENSORS_PDR_ADSP_SERVICE_LOCATION_CLIENT_NAME,
|
||||
SENSORS_PDR_ADSP_SERVICE_NAME,
|
||||
&me->channel[cid].spd[session].get_service_nb);
|
||||
if (ret)
|
||||
pr_warn("adsprpc: %s: get service location failed with %d for %s (%s)\n",
|
||||
__func__, ret, SENSORS_PDR_SLPI_SERVICE_NAME,
|
||||
SENSORS_PDR_ADSP_SERVICE_LOCATION_CLIENT_NAME);
|
||||
else
|
||||
pr_info("adsprpc: %s: service location enabled for %s (%s)\n",
|
||||
__func__, SENSORS_PDR_SLPI_SERVICE_NAME,
|
||||
SENSORS_PDR_ADSP_SERVICE_LOCATION_CLIENT_NAME);
|
||||
}
|
||||
if (of_property_read_bool(dev->of_node,
|
||||
"qcom,fastrpc-slpi-sensors-pdr")) {
|
||||
err = fastrpc_get_spd_session(
|
||||
SENSORS_PDR_SLPI_SERVICE_LOCATION_CLIENT_NAME, &session, &cid);
|
||||
if (err)
|
||||
goto spdbail;
|
||||
me->channel[cid].spd[session].get_service_nb.notifier_call =
|
||||
fastrpc_get_service_location_notify;
|
||||
ret = get_service_location(
|
||||
SENSORS_PDR_SLPI_SERVICE_LOCATION_CLIENT_NAME,
|
||||
SENSORS_PDR_SLPI_SERVICE_NAME,
|
||||
&me->channel[cid].spd[session].get_service_nb);
|
||||
if (ret)
|
||||
pr_warn("adsprpc: %s: get service location failed with %d for %s (%s)\n",
|
||||
__func__, ret, SENSORS_PDR_SLPI_SERVICE_NAME,
|
||||
SENSORS_PDR_SLPI_SERVICE_LOCATION_CLIENT_NAME);
|
||||
else
|
||||
pr_info("adsprpc: %s: service location enabled for %s (%s)\n",
|
||||
__func__, SENSORS_PDR_SLPI_SERVICE_NAME,
|
||||
SENSORS_PDR_SLPI_SERVICE_LOCATION_CLIENT_NAME);
|
||||
}
|
||||
spdbail:
|
||||
|
||||
fastrpc_setup_service_locator(dev, AUDIO_PDR_ADSP_DTSI_PROPERTY_NAME,
|
||||
AUDIO_PDR_SERVICE_LOCATION_CLIENT_NAME,
|
||||
AUDIO_PDR_ADSP_SERVICE_NAME);
|
||||
fastrpc_setup_service_locator(dev, SENSORS_PDR_ADSP_DTSI_PROPERTY_NAME,
|
||||
SENSORS_PDR_ADSP_SERVICE_LOCATION_CLIENT_NAME,
|
||||
SENSORS_PDR_ADSP_SERVICE_NAME);
|
||||
fastrpc_setup_service_locator(dev, SENSORS_PDR_SLPI_DTSI_PROPERTY_NAME,
|
||||
SENSORS_PDR_SLPI_SERVICE_LOCATION_CLIENT_NAME,
|
||||
SENSORS_PDR_SLPI_SERVICE_NAME);
|
||||
|
||||
err = of_platform_populate(pdev->dev.of_node,
|
||||
fastrpc_match_table,
|
||||
NULL, &pdev->dev);
|
||||
|
|
|
|||
Loading…
Reference in a new issue