msm: adsprpc: API to get DSP capability

This API will be initiated from a user application. If the DSP information
is not on the kernel it will make a call to the DSP and retrieve the
information.
Then the information will be cached on the kernel and returned to the user
program. Subsequent API calls will retrieve the previously cached
information from the kernel.

Change-Id: Ib89ad25e857f02f1e1ca02180c0363e1543503b4
Acked-by: Edgar Flores <edgarf@qti.qualcomm.com>
Signed-off-by: Tharun Kumar Merugu <mtharu@codeaurora.org>
This commit is contained in:
Tharun Kumar Merugu 2019-02-23 02:08:48 +05:30
parent 44f1094a8e
commit 3357850e90
3 changed files with 202 additions and 16 deletions

View File

@ -49,6 +49,7 @@
#include <soc/qcom/ramdump.h>
#include <linux/debugfs.h>
#include <linux/pm_qos.h>
#include <linux/stat.h>
#define TZ_PIL_PROTECT_MEM_SUBSYS_ID 0x0C
#define TZ_PIL_CLEAR_PROTECT_MEM_SUBSYS_ID 0x0D
@ -99,7 +100,8 @@
#define PERF_KEYS \
"count:flush:map:copy:rpmsg:getargs:putargs:invalidate:invoke:tid:ptr"
#define FASTRPC_STATIC_HANDLE_KERNEL (1)
#define FASTRPC_STATIC_HANDLE_PROCESS_GROUP (1)
#define FASTRPC_STATIC_HANDLE_DSP_UTILITIES (2)
#define FASTRPC_STATIC_HANDLE_LISTENER (3)
#define FASTRPC_STATIC_HANDLE_MAX (20)
#define FASTRPC_LATENCY_CTRL_ENB (1)
@ -287,6 +289,7 @@ struct fastrpc_channel_ctx {
void *remoteheap_ramdump_dev;
/* Indicates, if channel is restricted to secure node only */
int secure;
struct fastrpc_dsp_capabilities dsp_cap_kernel;
};
struct fastrpc_apps {
@ -1856,10 +1859,13 @@ static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode,
getnstimeofday(&invoket);
if (!kernel) {
VERIFY(err, invoke->handle != FASTRPC_STATIC_HANDLE_KERNEL);
VERIFY(err, invoke->handle !=
FASTRPC_STATIC_HANDLE_PROCESS_GROUP);
VERIFY(err, invoke->handle !=
FASTRPC_STATIC_HANDLE_DSP_UTILITIES);
if (err) {
pr_err("adsprpc: ERROR: %s: user application %s trying to send a kernel RPC message to channel %d",
__func__, current->comm, cid);
pr_err("adsprpc: ERROR: %s: user application %s trying to send a kernel RPC message to channel %d, handle 0x%x",
__func__, current->comm, cid, invoke->handle);
goto bail;
}
}
@ -2002,7 +2008,7 @@ static int fastrpc_init_process(struct fastrpc_file *fl,
ra[0].buf.pv = (void *)&tgid;
ra[0].buf.len = sizeof(tgid);
ioctl.inv.handle = FASTRPC_STATIC_HANDLE_KERNEL;
ioctl.inv.handle = FASTRPC_STATIC_HANDLE_PROCESS_GROUP;
ioctl.inv.sc = REMOTE_SCALARS_MAKE(0, 1, 0);
ioctl.inv.pra = ra;
ioctl.fds = NULL;
@ -2099,7 +2105,7 @@ static int fastrpc_init_process(struct fastrpc_file *fl,
ra[5].buf.len = sizeof(inbuf.siglen);
fds[5] = 0;
ioctl.inv.handle = FASTRPC_STATIC_HANDLE_KERNEL;
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);
@ -2188,7 +2194,7 @@ static int fastrpc_init_process(struct fastrpc_file *fl,
ra[2].buf.pv = (void *)pages;
ra[2].buf.len = sizeof(*pages);
fds[2] = 0;
ioctl.inv.handle = FASTRPC_STATIC_HANDLE_KERNEL;
ioctl.inv.handle = FASTRPC_STATIC_HANDLE_PROCESS_GROUP;
ioctl.inv.sc = REMOTE_SCALARS_MAKE(8, 3, 0);
ioctl.inv.pra = ra;
@ -2227,6 +2233,137 @@ bail:
return err;
}
static int fastrpc_kstat(const char *filename, struct kstat *stat)
{
int result;
mm_segment_t fs_old;
fs_old = get_fs();
set_fs(KERNEL_DS);
result = vfs_stat((const char __user *)filename, stat);
set_fs(fs_old);
return result;
}
static int fastrpc_get_info_from_dsp(struct fastrpc_file *fl,
uint32_t *dsp_attr, uint32_t dsp_attr_size,
uint32_t domain)
{
int err = 0, dsp_cap_buff_size, dsp_support = 0;
struct fastrpc_ioctl_invoke_crc ioctl;
remote_arg_t ra[2];
struct kstat sb;
// Querying device about DSP support
switch (domain) {
case ADSP_DOMAIN_ID:
if (!fastrpc_kstat("/dev/subsys_adsp", &sb))
dsp_support = 1;
break;
case MDSP_DOMAIN_ID:
//Modem not supported for fastRPC
break;
case SDSP_DOMAIN_ID:
if (!fastrpc_kstat("/dev/subsys_slpi", &sb))
dsp_support = 1;
break;
case CDSP_DOMAIN_ID:
if (!fastrpc_kstat("/dev/subsys_cdsp", &sb))
dsp_support = 1;
break;
default:
dsp_support = 0;
break;
}
dsp_attr[0] = dsp_support;
// If domain not supported, skip querying capabilities
if (dsp_support == 0)
goto bail;
err = fastrpc_channel_open(fl);
if (err)
goto bail;
dsp_cap_buff_size = dsp_attr_size - sizeof(uint32_t);
ra[0].buf.pv = (void *)&dsp_cap_buff_size;
ra[0].buf.len = sizeof(dsp_cap_buff_size);
ra[1].buf.pv = (void *)(&dsp_attr[1]);
ra[1].buf.len = dsp_cap_buff_size * sizeof(uint32_t);
ioctl.inv.handle = FASTRPC_STATIC_HANDLE_DSP_UTILITIES;
ioctl.inv.sc = REMOTE_SCALARS_MAKE(0, 1, 1);
ioctl.inv.pra = ra;
ioctl.fds = NULL;
ioctl.attrs = NULL;
ioctl.crc = NULL;
fl->pd = 1;
// Querying DSP about capabilities support
err = fastrpc_internal_invoke(fl, FASTRPC_MODE_PARALLEL, 1, &ioctl);
bail:
if (err)
pr_err("adsprpc: %s: %s: could not obtain dsp information, err val 0x%x",
current->comm, __func__, err);
return err;
}
static int fastrpc_get_info_from_kernel(
struct fastrpc_dsp_capabilities *dsp_cap,
struct fastrpc_file *fl)
{
int err = 0;
uint32_t domain_support;
uint32_t domain = dsp_cap->domain;
if (!gcinfo[domain].dsp_cap_kernel.is_cached) {
/*
* Information not on kernel, query device for information
* and cache on kernel
*/
err = fastrpc_get_info_from_dsp(fl, dsp_cap->dsp_attributes,
sizeof(dsp_cap->dsp_attributes),
domain);
if (err)
goto bail;
domain_support = dsp_cap->dsp_attributes[0];
switch (domain_support) {
case 0:
memset(dsp_cap->dsp_attributes, 0,
sizeof(dsp_cap->dsp_attributes));
memset(&gcinfo[domain].dsp_cap_kernel.dsp_attributes,
0, sizeof(dsp_cap->dsp_attributes));
break;
case 1:
memcpy(&gcinfo[domain].dsp_cap_kernel.dsp_attributes,
dsp_cap->dsp_attributes,
sizeof(dsp_cap->dsp_attributes));
break;
default:
err = -1;
/*
* Reset is_cached flag to 0 so subsequent calls
* can try to query dsp again
*/
gcinfo[domain].dsp_cap_kernel.is_cached = 0;
pr_warn("adsprpc: %s: %s: returned bad domain support value %d",
current->comm,
__func__,
domain_support);
goto bail;
}
gcinfo[domain].dsp_cap_kernel.is_cached = 1;
} else {
// Information on Kernel, pass it to user
memcpy(dsp_cap->dsp_attributes,
&gcinfo[domain].dsp_cap_kernel.dsp_attributes,
sizeof(dsp_cap->dsp_attributes));
}
bail:
return err;
}
static int fastrpc_release_current_dsp_process(struct fastrpc_file *fl)
{
int err = 0;
@ -2249,7 +2386,7 @@ static int fastrpc_release_current_dsp_process(struct fastrpc_file *fl)
tgid = fl->tgid;
ra[0].buf.pv = (void *)&tgid;
ra[0].buf.len = sizeof(tgid);
ioctl.inv.handle = FASTRPC_STATIC_HANDLE_KERNEL;
ioctl.inv.handle = FASTRPC_STATIC_HANDLE_PROCESS_GROUP;
ioctl.inv.sc = REMOTE_SCALARS_MAKE(1, 1, 0);
ioctl.inv.pra = ra;
ioctl.fds = NULL;
@ -2298,7 +2435,7 @@ static int fastrpc_mmap_on_dsp(struct fastrpc_file *fl, uint32_t flags,
ra[2].buf.pv = (void *)&routargs;
ra[2].buf.len = sizeof(routargs);
ioctl.inv.handle = FASTRPC_STATIC_HANDLE_KERNEL;
ioctl.inv.handle = FASTRPC_STATIC_HANDLE_PROCESS_GROUP;
if (fl->apps->compat)
ioctl.inv.sc = REMOTE_SCALARS_MAKE(4, 2, 1);
else
@ -2361,7 +2498,7 @@ static int fastrpc_munmap_on_dsp_rh(struct fastrpc_file *fl, uint64_t phys,
ra[1].buf.pv = (void *)&routargs;
ra[1].buf.len = sizeof(routargs);
ioctl.inv.handle = FASTRPC_STATIC_HANDLE_KERNEL;
ioctl.inv.handle = FASTRPC_STATIC_HANDLE_PROCESS_GROUP;
ioctl.inv.sc = REMOTE_SCALARS_MAKE(9, 1, 1);
ioctl.inv.pra = ra;
ioctl.fds = NULL;
@ -2413,7 +2550,7 @@ static int fastrpc_munmap_on_dsp(struct fastrpc_file *fl, uintptr_t raddr,
ra[0].buf.pv = (void *)&inargs;
ra[0].buf.len = sizeof(inargs);
ioctl.inv.handle = FASTRPC_STATIC_HANDLE_KERNEL;
ioctl.inv.handle = FASTRPC_STATIC_HANDLE_PROCESS_GROUP;
if (fl->apps->compat)
ioctl.inv.sc = REMOTE_SCALARS_MAKE(5, 1, 0);
else
@ -3347,6 +3484,14 @@ static int fastrpc_internal_control(struct fastrpc_file *fl,
case FASTRPC_CONTROL_KALLOC:
cp->kalloc.kalloc_support = 1;
break;
case FASTRPC_GET_DSP_INFO:
VERIFY(err, cp->dsp_cap.domain < NUM_CHANNELS);
if (err)
goto bail;
err = fastrpc_get_info_from_kernel(&cp->dsp_cap, fl);
if (err)
goto bail;
break;
default:
err = -ENOTTY;
break;
@ -3533,7 +3678,8 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num,
VERIFY(err, 0 == (err = fastrpc_internal_control(fl, &p.cp)));
if (err)
goto bail;
if (p.cp.req == FASTRPC_CONTROL_KALLOC) {
if (p.cp.req == FASTRPC_CONTROL_KALLOC ||
p.cp.req == FASTRPC_GET_DSP_INFO) {
K_COPY_TO_USER(err, 0, param, &p.cp, sizeof(p.cp));
if (err)
goto bail;
@ -3573,7 +3719,6 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num,
if (err)
goto bail;
break;
default:
err = -ENOTTY;
pr_info("bad ioctl: %d\n", ioctl_num);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
* Copyright (c) 2014-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -137,11 +137,18 @@ struct compat_fastrpc_ctrl_kalloc {
compat_uint_t kalloc_support; /* Remote memory allocation from kernel */
};
#define FASTRPC_GET_DSP_INFO (4)
struct compat_fastrpc_dsp_capabilities {
compat_uint_t domain; /* DSP domain to query capabilities */
compat_uint_t dsp_attributes[FASTRPC_MAX_DSP_ATTRIBUTES];
};
struct compat_fastrpc_ioctl_control {
compat_uint_t req;
union {
struct compat_fastrpc_ctrl_latency lp;
struct compat_fastrpc_ctrl_kalloc kalloc;
struct compat_fastrpc_dsp_capabilities dsp_cap;
};
};
@ -338,6 +345,9 @@ static int compat_get_fastrpc_ioctl_control(
err |= put_user(p, &ctrl->lp.enable);
err |= get_user(p, &ctrl32->lp.level);
err |= put_user(p, &ctrl->lp.level);
} else if (p == FASTRPC_GET_DSP_INFO) {
err |= get_user(p, &ctrl32->dsp_cap.domain);
err |= put_user(p, &ctrl->dsp_cap.domain);
}
return err;
@ -383,6 +393,23 @@ static int compat_get_fastrpc_ioctl_init(
return err;
}
static int compat_put_fastrpc_get_dsp_info(
struct compat_fastrpc_ioctl_control __user *ctrl32,
struct fastrpc_ioctl_control __user *ctrl)
{
compat_uint_t u, *dsp_attr, *dsp_attr_32;
int err, ii;
dsp_attr = ctrl->dsp_cap.dsp_attributes;
dsp_attr_32 = ctrl32->dsp_cap.dsp_attributes;
for (ii = 0, err = 0; ii < FASTRPC_MAX_DSP_ATTRIBUTES; ii++) {
err |= get_user(u, dsp_attr++);
err |= put_user(u, dsp_attr_32++);
}
return err;
}
long compat_fastrpc_device_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg)
{
@ -555,7 +582,9 @@ long compat_fastrpc_device_ioctl(struct file *filp, unsigned int cmd,
if (p == FASTRPC_CONTROL_KALLOC) {
err = get_user(p, &ctrl->kalloc.kalloc_support);
err |= put_user(p, &ctrl32->kalloc.kalloc_support);
}
} else if (p == FASTRPC_GET_DSP_INFO)
err |= compat_put_fastrpc_get_dsp_info(ctrl32, ctrl);
return err;
}
case COMPAT_FASTRPC_IOCTL_GETPERF:

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -241,6 +241,8 @@ struct fastrpc_ioctl_perf { /* kernel performance data */
uintptr_t keys;
};
#define FASTRPC_MAX_DSP_ATTRIBUTES (7)
#define FASTRPC_CONTROL_LATENCY (1)
struct fastrpc_ctrl_latency {
uint32_t enable; /* latency control enable */
@ -252,11 +254,21 @@ struct fastrpc_ctrl_kalloc {
uint32_t kalloc_support; /* Remote memory allocation from kernel */
};
/* FASTRPC_CONTROL value 2 is reserved in user space */
#define FASTRPC_GET_DSP_INFO (4)
struct fastrpc_dsp_capabilities {
union {
uint32_t is_cached; //! Flag if dsp attributes are cached
uint32_t domain; //! DSP domain to query capabilities
};
uint32_t dsp_attributes[FASTRPC_MAX_DSP_ATTRIBUTES];
};
struct fastrpc_ioctl_control {
uint32_t req;
union {
struct fastrpc_ctrl_latency lp;
struct fastrpc_ctrl_kalloc kalloc;
struct fastrpc_dsp_capabilities dsp_cap;
};
};