Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ebe00203 authored by Tharun Kumar Merugu's avatar Tharun Kumar Merugu Committed by vgattupa
Browse files

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: default avatarEdgar Flores <edgarf@qti.qualcomm.com>
Signed-off-by: default avatarTharun Kumar Merugu <mtharu@codeaurora.org>
parent 2d27b92b
Loading
Loading
Loading
Loading
+161 −15
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@
#include <linux/completion.h>
#include <linux/pagemap.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/module.h>
#include <linux/cdev.h>
@@ -32,7 +31,6 @@
#include <soc/qcom/service-notifier.h>
#include <soc/qcom/service-locator.h>
#include <linux/scatterlist.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/device.h>
#include <linux/of.h>
@@ -51,6 +49,8 @@
#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
#define TZ_PIL_AUTH_QDSP6_PROC 1
@@ -106,8 +106,9 @@
#define FASTRPC_GLINK_INTENT_NUM  (16)

#define PERF_KEYS \
	"count:flush:map:copy:glink:getargs:putargs:invalidate:invoke:tid:ptr"
#define FASTRPC_STATIC_HANDLE_KERNEL (1)
	"count:flush:map:copy:rpmsg:getargs:putargs:invalidate:invoke:tid:ptr"
#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)
@@ -285,6 +286,11 @@ struct fastrpc_glink_info {
	void *link_notify_handle;
};

struct fastrpc_dsp_capabilities {
	uint32_t is_cached;	//! Flag if dsp attributes are cached
	uint32_t dsp_attributes[FASTRPC_MAX_DSP_ATTRIBUTES];
};

struct fastrpc_channel_ctx {
	char *name;
	char *subsys;
@@ -309,6 +315,7 @@ struct fastrpc_channel_ctx {
	struct fastrpc_glink_info link;
	/* Indicates, if channel is restricted to secure node only */
	int secure;
	struct fastrpc_dsp_capabilities dsp_cap_kernel;
};

struct fastrpc_apps {
@@ -2066,10 +2073,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\n",
				__func__, current->comm, cid, invoke->handle);
			goto bail;
		}
	}
@@ -2204,7 +2214,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;
@@ -2299,7 +2309,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);
@@ -2385,7 +2395,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;
@@ -2421,6 +2431,119 @@ static int fastrpc_init_process(struct fastrpc_file *fl,
	return err;
}

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 fastrpc_apps *me = &gfa;

	// Querying device about DSP support
	switch (domain) {
	case ADSP_DOMAIN_ID:
	case SDSP_DOMAIN_ID:
	case CDSP_DOMAIN_ID:
		if (me->channel[domain].issubsystemup)
			dsp_support = 1;
		break;
	case MDSP_DOMAIN_ID:
		//Modem not supported for fastRPC
		break;
	default:
		dsp_support = 0;
		break;
	}
	dsp_attr[0] = dsp_support;

	if (dsp_support == 0) {
		err = -ENOTCONN;
		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;

	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\n",
		current->comm, __func__, err);
	return err;
}

static int fastrpc_get_info_from_kernel(
		struct fastrpc_ioctl_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\n",
					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;
@@ -2440,7 +2563,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;
@@ -2486,7 +2609,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
@@ -2547,7 +2670,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;
@@ -2609,7 +2732,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
@@ -3735,6 +3858,26 @@ static int fastrpc_internal_control(struct fastrpc_file *fl,
	return err;
}

static int fastrpc_get_dsp_info(struct fastrpc_ioctl_dsp_capabilities *dsp_cap,
				void *param, struct fastrpc_file *fl)
{
	int err = 0;

	K_COPY_FROM_USER(err, 0, dsp_cap, param,
			sizeof(struct fastrpc_ioctl_dsp_capabilities));
	VERIFY(err, dsp_cap->domain < NUM_CHANNELS);
	if (err)
		goto bail;

	err = fastrpc_get_info_from_kernel(dsp_cap, fl);
	if (err)
		goto bail;
	K_COPY_TO_USER(err, 0, param, dsp_cap,
			sizeof(struct fastrpc_ioctl_dsp_capabilities));
bail:
	return err;
}

static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num,
				 unsigned long ioctl_param)
{
@@ -3748,6 +3891,7 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num,
		struct fastrpc_ioctl_init_attrs init;
		struct fastrpc_ioctl_perf perf;
		struct fastrpc_ioctl_control cp;
		struct fastrpc_ioctl_dsp_capabilities dsp_cap;
	} p;
	union {
		struct fastrpc_ioctl_mmap mmap;
@@ -3958,7 +4102,9 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num,
		if (err)
			goto bail;
		break;

	case FASTRPC_IOCTL_GET_DSP_INFO:
		err = fastrpc_get_dsp_info(&p.dsp_cap, param, fl);
		break;
	default:
		err = -ENOTTY;
		pr_info("bad ioctl: %d\n", ioctl_num);
+57 −1
Original line number Diff line number Diff line
/*
 * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
 * Copyright (c) 2014-2021, 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
@@ -43,6 +43,8 @@
		_IOWR('R', 14, struct compat_fastrpc_ioctl_mmap_64)
#define COMPAT_FASTRPC_IOCTL_MUNMAP_64 \
		_IOWR('R', 15, struct compat_fastrpc_ioctl_munmap_64)
#define COMPAT_FASTRPC_IOCTL_GET_DSP_INFO \
		_IOWR('R', 16, struct compat_fastrpc_ioctl_dsp_capabilities)

struct compat_remote_buf {
	compat_uptr_t pv;	/* buffer pointer */
@@ -151,6 +153,11 @@ struct compat_fastrpc_ioctl_control {
	};
};

struct compat_fastrpc_ioctl_dsp_capabilities {
	compat_uint_t domain;	/* DSP domain to query capabilities */
	compat_uint_t dsp_attributes[FASTRPC_MAX_DSP_ATTRIBUTES];
};

static int compat_get_fastrpc_ioctl_invoke(
			struct compat_fastrpc_ioctl_invoke_crc __user *inv32,
			struct fastrpc_ioctl_invoke_crc __user **inva,
@@ -389,6 +396,53 @@ static int compat_get_fastrpc_ioctl_init(
	return err;
}

static int compat_put_fastrpc_ioctl_get_dsp_info(
		struct compat_fastrpc_ioctl_dsp_capabilities __user *info32,
		struct fastrpc_ioctl_dsp_capabilities __user *info)
{
	compat_uint_t u;
	int err, ii;

	for (ii = 0, err = 0; ii < FASTRPC_MAX_DSP_ATTRIBUTES; ii++) {
		err |= get_user(u, &info->dsp_attributes[ii]);
		err |= put_user(u, &info32->dsp_attributes[ii]);
	}

	return err;
}



static int compat_fastrpc_get_dsp_info(struct file *filp,
		unsigned long arg)
{
	struct compat_fastrpc_ioctl_dsp_capabilities __user *info32;
	struct fastrpc_ioctl_dsp_capabilities __user *info;
	compat_uint_t u;
	long ret;
	int err = 0;

	info32 = compat_ptr(arg);
	VERIFY(err, NULL != (info = compat_alloc_user_space(
						sizeof(*info))));
	if (err)
		return -EFAULT;

	err = get_user(u, &info32->domain);
	err |= put_user(u, &info->domain);
	if (err)
		return err;

	ret = filp->f_op->unlocked_ioctl(filp,
			FASTRPC_IOCTL_GET_DSP_INFO,
			(unsigned long)info);
	if (ret)
		return ret;

	err = compat_put_fastrpc_ioctl_get_dsp_info(info32, info);
	return err;
}

long compat_fastrpc_device_ioctl(struct file *filp, unsigned int cmd,
				unsigned long arg)
{
@@ -588,6 +642,8 @@ long compat_fastrpc_device_ioctl(struct file *filp, unsigned int cmd,
		err |= put_user(u, &perf32->numkeys);
		return err;
	}
	case COMPAT_FASTRPC_IOCTL_GET_DSP_INFO:
		return compat_fastrpc_get_dsp_info(filp, arg);
	default:
		return -ENOIOCTLCMD;
	}
+9 −1
Original line number Diff line number Diff line
/*
 * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2012-2021, 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
@@ -32,6 +32,8 @@
#define FASTRPC_IOCTL_INVOKE_CRC _IOWR('R', 11, struct fastrpc_ioctl_invoke_crc)
#define FASTRPC_IOCTL_CONTROL   _IOWR('R', 12, struct fastrpc_ioctl_control)
#define FASTRPC_IOCTL_MUNMAP_FD _IOWR('R', 13, struct fastrpc_ioctl_munmap_fd)
#define FASTRPC_IOCTL_GET_DSP_INFO \
			_IOWR('R', 16, struct fastrpc_ioctl_dsp_capabilities)

#define FASTRPC_GLINK_GUID "fastrpcglink-apps-dsp"
#define FASTRPC_SMD_GUID "fastrpcsmd-apps-dsp"
@@ -269,6 +271,12 @@ struct fastrpc_ioctl_control {
	};
};

#define FASTRPC_MAX_DSP_ATTRIBUTES	(7)
struct fastrpc_ioctl_dsp_capabilities {
	uint32_t domain;	//! DSP domain to query capabilities
	uint32_t dsp_attributes[FASTRPC_MAX_DSP_ATTRIBUTES];
};

struct smq_null_invoke {
	uint64_t ctx;			/* invoke caller context */
	uint32_t handle;	    /* handle to invoke */