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

Commit 29636127 authored by Tharun Kumar Merugu's avatar Tharun Kumar Merugu Committed by Mohammed Nayeem Ur Rahman
Browse files

msm: adsprpc: vote for CPU to stay awake during RPC call



Vote with PM for CPU to stay awake while processing RPC call and
to relax when waiting for response from remote subsystem. Print
error if the maximum remote session concurrency is hit.

Change-Id: Iabf43fbc53f8799e4d446335f1c0cae80d27491f
Acked-by: default avatarThyagarajan Venkatanarayanan <venkatan@qti.qualcomm.com>
Signed-off-by: default avatarTharun Kumar Merugu <mtharu@codeaurora.org>
Signed-off-by: default avatarMohammed Nayeem Ur Rahman <mohara@codeaurora.org>
parent 945eeb02
Loading
Loading
Loading
Loading
+70 −16
Original line number Diff line number Diff line
@@ -224,6 +224,7 @@ struct smq_invoke_ctx {
	struct fastrpc_buf *lbuf;
	size_t used;
	struct fastrpc_file *fl;
	uint32_t handle;
	uint32_t sc;
	struct overlap *overs;
	struct overlap **overps;
@@ -308,6 +309,8 @@ struct fastrpc_apps {
	spinlock_t ctxlock;
	struct smq_invoke_ctx *ctxtable[FASTRPC_CTX_MAX];
	bool legacy_remote_heap;
	struct wakeup_source *wake_source;
	unsigned int wake_count;
};

struct fastrpc_mmap {
@@ -389,6 +392,8 @@ struct fastrpc_file {
	/* Identifies the device (MINOR_NUM_DEV / MINOR_NUM_SECURE_DEV) */
	int dev_minor;
	char *debug_buf;
	/* Flag to enable PM wake/relax voting for every remote invoke */
	int wake_enable;
};

static struct fastrpc_apps gfa;
@@ -1199,6 +1204,7 @@ static int context_alloc(struct fastrpc_file *fl, uint32_t kernel,
			goto bail;
	}
	ctx->crc = (uint32_t *)invokefd->crc;
	ctx->handle = invoke->handle;
	ctx->sc = invoke->sc;
	if (bufs) {
		VERIFY(err, 0 == context_build_overlap(ctx));
@@ -1872,7 +1878,36 @@ static void fastrpc_init(struct fastrpc_apps *me)
	me->channel[CDSP_DOMAIN_ID].secure = NON_SECURE_CHANNEL;
}

static int fastrpc_release_current_dsp_process(struct fastrpc_file *fl);
static inline void fastrpc_pm_awake(int fl_wake_enable, int *wake_enable)
{
	struct fastrpc_apps *me = &gfa;

	if (!fl_wake_enable)
		return;

	spin_lock(&me->hlock);
	if (!me->wake_count)
		__pm_stay_awake(me->wake_source);
	me->wake_count++;
	spin_unlock(&me->hlock);
	*wake_enable = 1;
}

static inline void fastrpc_pm_relax(int *wake_enable)
{
	struct fastrpc_apps *me = &gfa;

	if (!(*wake_enable))
		return;

	spin_lock(&me->hlock);
	if (me->wake_count)
		me->wake_count--;
	if (!me->wake_count)
		__pm_relax(me->wake_source);
	spin_unlock(&me->hlock);
	*wake_enable = 0;
}

static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode,
				   uint32_t kernel,
@@ -1882,10 +1917,11 @@ static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode,
	struct fastrpc_ioctl_invoke *invoke = &inv->inv;
	int cid = fl->cid;
	int interrupted = 0;
	int err = 0;
	int err = 0, wake_enable = 0;
	struct timespec invoket = {0};
	int64_t *perf_counter = getperfcounter(fl, PERF_COUNT);

	fastrpc_pm_awake(fl->wake_enable, &wake_enable);
	if (fl->profile)
		getnstimeofday(&invoket);

@@ -1900,7 +1936,7 @@ static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode,

	VERIFY(err, fl->cid >= 0 && fl->cid < NUM_CHANNELS && fl->sctx != NULL);
	if (err) {
		pr_err("adsprpc: ERROR: %s: user application %s domain is not set\n",
		pr_err("adsprpc: ERROR: %s: kernel session not initialized yet for %s\n",
			__func__, current->comm);
		err = -EBADR;
		goto bail;
@@ -1946,14 +1982,15 @@ static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode,
	if (err)
		goto bail;
 wait:
	fastrpc_pm_relax(&wake_enable);
	if (kernel)
		wait_for_completion(&ctx->work);
	else {
	else
		interrupted = wait_for_completion_interruptible(&ctx->work);
	fastrpc_pm_awake(fl->wake_enable, &wake_enable);
	VERIFY(err, 0 == (err = interrupted));
	if (err)
		goto bail;
	}

	PERF(fl->profile, GET_COUNTER(perf_counter, PERF_INVARGS),
	inv_args(ctx);
@@ -1990,6 +2027,7 @@ static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode,
				*count = *count+1;
		}
	}
	fastrpc_pm_relax(&wake_enable);
	return err;
}

@@ -2760,9 +2798,12 @@ static int fastrpc_session_alloc_locked(struct fastrpc_channel_ctx *chan,
				break;
			}
		}
		VERIFY(err, idx < chan->sesscount);
		if (err)
		if (idx >= chan->sesscount) {
			err = -EUSERS;
			pr_err("adsprpc: ERROR %d: %s: max concurrent sessions limit (%d) already reached on %s\n",
				err, __func__, chan->sesscount, chan->subsys);
			goto bail;
		}
		chan->session[idx].smmu.faults = 0;
	} else {
		VERIFY(err, me->dev != NULL);
@@ -3218,7 +3259,7 @@ static int fastrpc_channel_open(struct fastrpc_file *fl)

	VERIFY(err, fl && fl->sctx && fl->cid >= 0 && fl->cid < NUM_CHANNELS);
	if (err) {
		pr_err("adsprpc: ERROR: %s: user application %s domain is not set\n",
		pr_err("adsprpc: ERROR: %s: kernel session not initialized yet for %s\n",
			__func__, current->comm);
		err = -EBADR;
		return err;
@@ -3361,8 +3402,8 @@ static int fastrpc_get_info(struct fastrpc_file *fl, uint32_t *info)
		fl->cid = cid;
		fl->ssrcount = fl->apps->channel[cid].ssrcount;
		mutex_lock(&fl->apps->channel[cid].smd_mutex);
		VERIFY(err, !fastrpc_session_alloc_locked(
				&fl->apps->channel[cid], 0, &fl->sctx));
		err = fastrpc_session_alloc_locked(&fl->apps->channel[cid],
				0, &fl->sctx);
		mutex_unlock(&fl->apps->channel[cid].smd_mutex);
		if (err)
			goto bail;
@@ -3405,8 +3446,11 @@ static int fastrpc_internal_control(struct fastrpc_file *fl,
	case FASTRPC_CONTROL_KALLOC:
		cp->kalloc.kalloc_support = 1;
		break;
	case FASTRPC_CONTROL_WAKELOCK:
		fl->wake_enable = cp->wp.enable;
		break;
	default:
		err = -ENOTTY;
		err = -EBADRQC;
		break;
	}
bail:
@@ -4303,11 +4347,19 @@ static int __init fastrpc_device_init(void)

	err = register_rpmsg_driver(&fastrpc_rpmsg_client);
	if (err) {
		pr_err("adsprpc: register_rpmsg_driver: failed with err %d\n",
			err);
		pr_err("adsprpc: %s: register_rpmsg_driver failed with err %d\n",
			__func__, err);
		goto device_create_bail;
	}
	me->rpmsg_register = 1;

	me->wake_source = wakeup_source_register("adsprpc");
	VERIFY(err, !IS_ERR_OR_NULL(me->wake_source));
	if (err) {
		pr_err("adsprpc: Error: %s: wakeup_source_register failed with err %d\n",
					__func__, PTR_ERR(me->wake_source));
		goto device_create_bail;
	}
	return 0;
device_create_bail:
	for (i = 0; i < NUM_CHANNELS; i++) {
@@ -4356,6 +4408,8 @@ static void __exit fastrpc_device_exit(void)
	unregister_chrdev_region(me->dev_no, NUM_CHANNELS);
	if (me->rpmsg_register == 1)
		unregister_rpmsg_driver(&fastrpc_rpmsg_client);
	if (me->wake_source)
		wakeup_source_unregister(me->wake_source);
	debugfs_remove_recursive(debugfs_root);
}

+13 −3
Original line number Diff line number Diff line
@@ -241,22 +241,32 @@ struct fastrpc_ioctl_perf { /* kernel performance data */
	uintptr_t keys;
};

#define FASTRPC_CONTROL_LATENCY	(1)
enum fastrpc_control_type {
	FASTRPC_CONTROL_LATENCY		=	1,
	FASTRPC_CONTROL_SMMU		=	2,
	FASTRPC_CONTROL_KALLOC		=	3,
	FASTRPC_CONTROL_WAKELOCK	=	4,
};

struct fastrpc_ctrl_latency {
	uint32_t enable;	/* latency control enable */
	uint32_t level;		/* level of control */
};

#define FASTRPC_CONTROL_KALLOC	(3)
struct fastrpc_ctrl_kalloc {
	uint32_t kalloc_support;  /* Remote memory allocation from kernel */
};
/* FASTRPC_CONTROL value 2 is reserved in user space */

struct fastrpc_ctrl_wakelock {
	uint32_t enable;	/* wakelock control enable */
};

struct fastrpc_ioctl_control {
	uint32_t req;
	union {
		struct fastrpc_ctrl_latency lp;
		struct fastrpc_ctrl_kalloc kalloc;
		struct fastrpc_ctrl_wakelock wp;
	};
};