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

Commit ecb7bf3f authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: ADSPRPC: Support SMD communication for legacy chipsets"

parents df1afd3b bbc78f21
Loading
Loading
Loading
Loading
+15 −14
Original line number Diff line number Diff line
@@ -47,28 +47,29 @@ Example:
Legacy SMMU v1/v2:

Required properties:
- compatible : Must be "qcom,msm-fastprc-legacy-compute-cb"
- compatible : Must be "qcom,msm-fastrpc-legacy-compute"

Required subnode:
- qcom,msm_fastrpc_compute_cb : Child nodes representing the compute context
                                banks

Required subnode properties:
- qcom,adsp-shared-phandle: phandle that describe the context bank handle
- qcom,adsp-shared-sids : A list of SID associated with the context bank
- qcom,virtual-addr-pool : Virtual address range that the context bank
                           will be using
- compatible : Must be "qcom,msm-fastrpc-legacy-compute-cb"
- label	     : Label describing the channel this context bank belongs to
- iommus     : A list of phandle and IOMMU specifier pairs that describe the
			IOMMU master interfaces of the device
- sids       : A list of SID associated with the context bank

Example:
        qcom,adsprpc_domains {
                compatible = "qcom,msm-fastrpc-legacy-compute-cb";
	qcom,msm_fastrpc {
		compatible = "qcom,msm-fastrpc-legacy-compute";
		qcom,msm_fastrpc_compute_cb {
                       qcom,adsp-shared-phandle = <&adsp_shared>;
                       qcom,adsp-shared-sids = <0x8 0x9>;
                       qcom,virtual-addr-pool = <0x80000000 0x7FFFFFFF>;
			compatible = "qcom,msm-fastrpc-legacy-compute-cb";
			label = "adsprpc-smd";
			iommus = <&apps_iommu 0x2408 0x7>;
			sids = <0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf>;
		};
	};

Remote Heap:

Required properties:
+232 −49
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@
#include <linux/msm_ion.h>
#include <soc/qcom/secure_buffer.h>
#include <soc/qcom/glink.h>
#include <soc/qcom/smd.h>
#include <soc/qcom/subsystem_notif.h>
#include <soc/qcom/subsystem_restart.h>
#include <soc/qcom/service-notifier.h>
@@ -198,7 +199,6 @@ struct smq_invoke_ctx {
	remote_arg_t *lpra;
	remote_arg64_t *rpra;
	int *fds;
	unsigned int *attrs;
	struct fastrpc_mmap **maps;
	struct fastrpc_buf *buf;
	size_t used;
@@ -207,8 +207,9 @@ struct smq_invoke_ctx {
	struct overlap *overs;
	struct overlap **overps;
	struct smq_msg msg;
	uint32_t *crc;
	unsigned int magic;
	unsigned int *attrs;
	uint32_t *crc;
};

struct fastrpc_ctx_lst {
@@ -261,6 +262,7 @@ struct fastrpc_channel_ctx {
	struct completion workport;
	struct notifier_block nb;
	struct kref kref;
	int channel;
	int sesscount;
	int ssrcount;
	void *handle;
@@ -288,6 +290,8 @@ struct fastrpc_apps {
	struct ion_client *client;
	struct device *dev;
	unsigned int latency;
	bool glink;
	bool legacy;
};

struct fastrpc_mmap {
@@ -371,6 +375,7 @@ static struct fastrpc_channel_ctx gcinfo[NUM_CHANNELS] = {
	{
		.name = "adsprpc-smd",
		.subsys = "adsp",
		.channel = SMD_APPS_QDSP,
		.link.link_info.edge = "lpass",
		.link.link_info.transport = "smem",
		.spd = {
@@ -385,12 +390,14 @@ static struct fastrpc_channel_ctx gcinfo[NUM_CHANNELS] = {
	{
		.name = "mdsprpc-smd",
		.subsys = "modem",
		.channel = SMD_APPS_MODEM,
		.link.link_info.edge = "mpss",
		.link.link_info.transport = "smem",
	},
	{
		.name = "sdsprpc-smd",
		.subsys = "slpi",
		.channel = SMD_APPS_DSPS,
		.link.link_info.edge = "dsps",
		.link.link_info.transport = "smem",
	},
@@ -1029,6 +1036,7 @@ static int context_alloc(struct fastrpc_file *fl, uint32_t kernel,
			 struct fastrpc_ioctl_invoke_crc *invokefd,
			 struct smq_invoke_ctx **po)
{
	struct fastrpc_apps *me = &gfa;
	int err = 0, bufs, size = 0;
	struct smq_invoke_ctx *ctx = NULL;
	struct fastrpc_ctx_lst *clst = &fl->clst;
@@ -1051,9 +1059,14 @@ static int context_alloc(struct fastrpc_file *fl, uint32_t kernel,
	ctx->maps = (struct fastrpc_mmap **)(&ctx[1]);
	ctx->lpra = (remote_arg_t *)(&ctx->maps[bufs]);
	ctx->fds = (int *)(&ctx->lpra[bufs]);
	if (me->legacy) {
		ctx->overs = (struct overlap *)(&ctx->fds[bufs]);
		ctx->overps = (struct overlap **)(&ctx->overs[bufs]);
	} else {
		ctx->attrs = (unsigned int *)(&ctx->fds[bufs]);
		ctx->overs = (struct overlap *)(&ctx->attrs[bufs]);
		ctx->overps = (struct overlap **)(&ctx->overs[bufs]);
	}

	K_COPY_FROM_USER(err, kernel, (void *)ctx->lpra, invoke->pra,
					bufs * sizeof(*ctx->lpra));
@@ -1237,6 +1250,7 @@ static void fastrpc_file_list_dtor(struct fastrpc_apps *me)

static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx)
{
	struct fastrpc_apps *me = &gfa;
	remote_arg64_t *rpra;
	remote_arg_t *lpra = ctx->lpra;
	struct smq_invoke_buf *list;
@@ -1266,10 +1280,16 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx)
		size_t len = lpra[i].buf.len;

		mutex_lock(&ctx->fl->fl_map_mutex);
		if (ctx->fds[i] && (ctx->fds[i] != -1))
		if (ctx->fds[i] && (ctx->fds[i] != -1)) {
			unsigned int attrs = 0;

			if (ctx->attrs)
				attrs = ctx->attrs[i];

			fastrpc_mmap_create(ctx->fl, ctx->fds[i],
					ctx->attrs[i], buf, len,
					attrs, buf, len,
					mflags, &ctx->maps[i]);
		}
		mutex_unlock(&ctx->fl->fl_map_mutex);
		ipage += 1;
	}
@@ -1286,8 +1306,13 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx)
		ipage += 1;
	}
	mutex_unlock(&ctx->fl->fl_map_mutex);
	metalen = copylen = (size_t)&ipage[0] + (sizeof(uint64_t) * M_FDLIST) +
	if (!me->legacy) {
		metalen = copylen = (size_t)&ipage[0] +
				(sizeof(uint64_t) * M_FDLIST) +
				(sizeof(uint32_t) * M_CRCLIST);
	} else {
		metalen = copylen = (size_t)&ipage[0];
	}

	/* calculate len requreed for copying */
	for (oix = 0; oix < inbufs + outbufs; ++oix) {
@@ -1383,11 +1408,13 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx)
		pages[i].addr = map->phys;
		pages[i].size = map->size;
	}
	if (!me->legacy) {
		fdlist = (uint64_t *)&pages[bufs + handles];
		for (i = 0; i < M_FDLIST; i++)
			fdlist[i] = 0;
		crclist = (uint32_t *)&fdlist[M_FDLIST];
		memset(crclist, 0, sizeof(uint32_t)*M_CRCLIST);
	}

	/* copy non ion buffers */
	PERF(ctx->fl->profile, GET_COUNTER(perf_counter, PERF_COPY),
@@ -1466,11 +1493,12 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx)
static int put_args(uint32_t kernel, struct smq_invoke_ctx *ctx,
		    remote_arg_t *upra)
{
	struct fastrpc_apps *me = &gfa;
	uint32_t sc = ctx->sc;
	struct smq_invoke_buf *list;
	struct smq_phy_page *pages;
	struct fastrpc_mmap *mmap;
	uint64_t *fdlist;
	uint64_t *fdlist = NULL;
	uint32_t *crclist = NULL;

	remote_arg64_t *rpra = ctx->rpra;
@@ -1482,8 +1510,10 @@ static int put_args(uint32_t kernel, struct smq_invoke_ctx *ctx,
	handles = REMOTE_SCALARS_INHANDLES(sc) + REMOTE_SCALARS_OUTHANDLES(sc);
	list = smq_invoke_buf_start(ctx->rpra, sc);
	pages = smq_phy_page_start(sc, list);
	if (!me->legacy) {
		fdlist = (uint64_t *)(pages + inbufs + outbufs + handles);
		crclist = (uint32_t *)(fdlist + M_FDLIST);
	}

	for (i = inbufs; i < inbufs + outbufs; ++i) {
		if (!ctx->maps[i]) {
@@ -1501,7 +1531,7 @@ static int put_args(uint32_t kernel, struct smq_invoke_ctx *ctx,
		}
	}
	mutex_lock(&ctx->fl->fl_map_mutex);
	if (inbufs + outbufs + handles) {
	if (fdlist && (inbufs + outbufs + handles)) {
		for (i = 0; i < M_FDLIST; i++) {
			if (!fdlist[i])
				break;
@@ -1601,7 +1631,7 @@ static int fastrpc_invoke_send(struct smq_invoke_ctx *ctx,
	struct smq_msg *msg = &ctx->msg;
	struct fastrpc_file *fl = ctx->fl;
	struct fastrpc_channel_ctx *channel_ctx = &fl->apps->channel[fl->cid];
	int err = 0;
	int err = 0, len;

	VERIFY(err, NULL != channel_ctx->chan);
	if (err)
@@ -1617,7 +1647,7 @@ static int fastrpc_invoke_send(struct smq_invoke_ctx *ctx,
	msg->invoke.header.sc = ctx->sc;
	msg->invoke.page.addr = ctx->buf ? ctx->buf->phys : 0;
	msg->invoke.page.size = buf_page_size(ctx->used);

	if (fl->apps->glink) {
		if (fl->ssrcount != channel_ctx->ssrcount) {
			err = -ECONNRESET;
			goto bail;
@@ -1629,10 +1659,61 @@ static int fastrpc_invoke_send(struct smq_invoke_ctx *ctx,
		err = glink_tx(channel_ctx->chan,
			(void *)&fl->apps->channel[fl->cid], msg, sizeof(*msg),
			GLINK_TX_REQ_INTENT);
	} else {
		spin_lock(&fl->apps->hlock);
		len = smd_write((smd_channel_t *)
				channel_ctx->chan,
				msg, sizeof(*msg));
		spin_unlock(&fl->apps->hlock);
		VERIFY(err, len == sizeof(*msg));
	}
 bail:
	return err;
}

static void fastrpc_smd_read_handler(int cid)
{
	struct fastrpc_apps *me = &gfa;
	struct smq_invoke_rsp rsp = {0};
	struct smq_invoke_ctx *ctx;
	int ret = 0, err = 0;

	do {
		ret = smd_read_from_cb(me->channel[cid].chan, &rsp,
					sizeof(rsp));
		if (ret != sizeof(rsp))
			break;
		ctx = (struct smq_invoke_ctx *)(uint64_to_ptr(rsp.ctx & ~1));
		VERIFY(err, (ctx && ctx->magic == FASTRPC_CTX_MAGIC));
		if (err)
			goto bail;
		context_notify_user(uint64_to_ptr(rsp.ctx & ~1), rsp.retval);
	} while (ret == sizeof(rsp));
bail:
	if (err)
		pr_err("adsprpc: invalid response or context\n");

}

static void smd_event_handler(void *priv, unsigned int event)
{
	struct fastrpc_apps *me = &gfa;
	int cid = (int)(uintptr_t)priv;

	switch (event) {
	case SMD_EVENT_OPEN:
		complete(&me->channel[cid].workport);
		break;
	case SMD_EVENT_CLOSE:
		fastrpc_notify_drivers(me, cid);
		break;
	case SMD_EVENT_DATA:
		fastrpc_smd_read_handler(cid);
		break;
	}
}


static void fastrpc_init(struct fastrpc_apps *me)
{
	int i;
@@ -2366,10 +2447,11 @@ static void fastrpc_channel_close(struct kref *kref)

	ctx = container_of(kref, struct fastrpc_channel_ctx, kref);
	cid = ctx - &gcinfo[0];
	if (!me->glink)
		smd_close(ctx->chan);
	else
		fastrpc_glink_close(ctx->chan, cid);
	ctx->chan = NULL;
	glink_unregister_link_state_cb(ctx->link.link_notify_handle);
	ctx->link.link_notify_handle = NULL;
	mutex_unlock(&me->smd_mutex);
	pr_info("'closed /dev/%s c %d %d'\n", gcinfo[cid].name,
						MAJOR(me->dev_no), cid);
@@ -2818,13 +2900,18 @@ static int fastrpc_channel_open(struct fastrpc_file *fl)
	fl->ssrcount = me->channel[cid].ssrcount;
	if ((kref_get_unless_zero(&me->channel[cid].kref) == 0) ||
	    (me->channel[cid].chan == NULL)) {
		if (me->glink) {
			VERIFY(err, 0 == fastrpc_glink_register(cid, me));
			if (err)
				goto bail;
			VERIFY(err, 0 == fastrpc_glink_open(cid));
		if (err)
			goto bail;

		} else {
		VERIFY(err, !smd_named_open_on_edge(FASTRPC_SMD_GUID,
				gcinfo[cid].channel,
				(smd_channel_t **)&me->channel[cid].chan,
				(void *)(uintptr_t)cid,
				smd_event_handler));
		}
		VERIFY(err,
			 wait_for_completion_timeout(&me->channel[cid].workport,
						RPC_TIMEOUT));
@@ -2835,13 +2922,15 @@ static int fastrpc_channel_open(struct fastrpc_file *fl)
		kref_init(&me->channel[cid].kref);
		pr_info("'opened /dev/%s c %d %d'\n", gcinfo[cid].name,
						MAJOR(me->dev_no), cid);
		if (me->glink) {
			err = glink_queue_rx_intent(me->channel[cid].chan, NULL,
				FASTRPC_GLINK_INTENT_LEN);
		err |= glink_queue_rx_intent(me->channel[cid].chan, NULL,
			FASTRPC_GLINK_INTENT_LEN);
			err |= glink_queue_rx_intent(me->channel[cid].chan,
				NULL, FASTRPC_GLINK_INTENT_LEN);
			if (err)
				pr_warn("adsprpc: initial intent fail for %d err %d\n",
					cid, err);
		}
		if (cid == 0 && me->channel[cid].ssrcount !=
				 me->channel[cid].prevssrcount) {
			if (fastrpc_mmap_remove_ssr(fl))
@@ -2881,7 +2970,6 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp)
	fl->cid = -1;
	if (debugfs_file != NULL)
		fl->debugfs_file = debugfs_file;
	memset(&fl->perf, 0, sizeof(fl->perf));
	fl->qos_request = 0;
	filp->private_data = fl;
	mutex_init(&fl->map_mutex);
@@ -3164,7 +3252,10 @@ static int fastrpc_restart_notifier_cb(struct notifier_block *nb,
		ctx->ssrcount++;
		ctx->issubsystemup = 0;
		if (ctx->chan) {
			if (me->glink)
				fastrpc_glink_close(ctx->chan, cid);
			else
				smd_close(ctx->chan);
			ctx->chan = NULL;
			pr_info("'restart notifier: closed /dev/%s c %d %d'\n",
				 gcinfo[cid].name, MAJOR(me->dev_no), cid);
@@ -3254,6 +3345,8 @@ static const struct of_device_id fastrpc_match_table[] = {
	{ .compatible = "qcom,msm-fastrpc-adsp", },
	{ .compatible = "qcom,msm-fastrpc-compute", },
	{ .compatible = "qcom,msm-fastrpc-compute-cb", },
	{ .compatible = "qcom,msm-fastrpc-legacy-compute", },
	{ .compatible = "qcom,msm-fastrpc-legacy-compute-cb", },
	{ .compatible = "qcom,msm-adsprpc-mem-region", },
	{}
};
@@ -3322,6 +3415,85 @@ static int fastrpc_cb_probe(struct device *dev)
	return err;
}

static int fastrpc_cb_legacy_probe(struct device *dev)
{
	struct fastrpc_apps *me = &gfa;
	struct fastrpc_channel_ctx *chan;
	struct fastrpc_session_ctx *first_sess = NULL, *sess = NULL;
	const char *name;
	unsigned int *sids = NULL, sids_size = 0;
	int err = 0, ret = 0, i;

	unsigned int start = 0x80000000;

	VERIFY(err, NULL != (name = of_get_property(dev->of_node,
					 "label", NULL)));
	if (err)
		goto bail;

	for (i = 0; i < NUM_CHANNELS; i++) {
		if (!gcinfo[i].name)
			continue;
		if (!strcmp(name, gcinfo[i].name))
			break;
	}
	VERIFY(err, i < NUM_CHANNELS);
	if (err)
		goto bail;

	chan = &gcinfo[i];
	VERIFY(err, chan->sesscount < NUM_SESSIONS);
	if (err)
		goto bail;

	first_sess  = &chan->session[chan->sesscount];

	VERIFY(err, NULL != of_get_property(dev->of_node,
				"sids", &sids_size));
	if (err)
		goto bail;

	VERIFY(err, NULL != (sids = kzalloc(sids_size, GFP_KERNEL)));
	if (err)
		goto bail;
	ret = of_property_read_u32_array(dev->of_node, "sids", sids,
					sids_size/sizeof(unsigned int));
	if (ret)
		goto bail;

	VERIFY(err, !IS_ERR_OR_NULL(first_sess->smmu.mapping =
				arm_iommu_create_mapping(&platform_bus_type,
						start, 0x78000000)));
	if (err)
		goto bail;

	VERIFY(err, !arm_iommu_attach_device(dev, first_sess->smmu.mapping));
	if (err)
		goto bail;


	for (i = 0; i < sids_size/sizeof(unsigned int); i++) {
		VERIFY(err, chan->sesscount < NUM_SESSIONS);
		if (err)
			goto bail;
		sess = &chan->session[chan->sesscount];
		sess->smmu.cb = sids[i];
		sess->smmu.dev = dev;
		sess->smmu.mapping = first_sess->smmu.mapping;
		sess->smmu.enabled = 1;
		sess->used = 0;
		sess->smmu.coherent = false;
		sess->smmu.secure = false;
		chan->sesscount++;
	}
	me->legacy = 1;
bail:
	kfree(sids);
	return err;
}



static void init_secure_vmid_list(struct device *dev, char *prop_name,
						struct secure_vm *destvm)
{
@@ -3388,6 +3560,16 @@ static int fastrpc_probe(struct platform_device *pdev)
					"qcom,msm-fastrpc-compute-cb"))
		return fastrpc_cb_probe(dev);

	if (of_device_is_compatible(dev->of_node,
					"qcom,msm-fastrpc-legacy-compute")) {
		me->glink = false;
	}

	if (of_device_is_compatible(dev->of_node,
					"qcom,msm-fastrpc-legacy-compute-cb")){
		return fastrpc_cb_legacy_probe(dev);
	}

	if (of_device_is_compatible(dev->of_node,
					"qcom,msm-adsprpc-mem-region")) {
		me->dev = dev;
@@ -3506,6 +3688,7 @@ static int __init fastrpc_device_init(void)

	fastrpc_init(me);
	me->dev = NULL;
	me->glink = true;
	VERIFY(err, 0 == platform_driver_register(&fastrpc_driver));
	if (err)
		goto register_bail;