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

Commit 04259ba9 authored by Tharun Kumar Merugu's avatar Tharun Kumar Merugu Committed by Gerrit - the friendly Code Review server
Browse files

msm: adsprpc: do pm stay awake vote in rpmsg callback



Vote with PM to keep the CPU awake in the rpmsg interrupt callback
itself, instead of voting from the fastrpc thread after it is
woken up and scheduled, to handle race between actual remote
subsystem response and context interruption because of CPU going
into suspend.

Change-Id: I289f4307aacc895aa73c51360f7cf83131a72a13
Acked-by: default avatarThyagarajan Venkatanarayanan <venkatan@qti.qualcomm.com>
Signed-off-by: default avatarTharun Kumar Merugu <mtharu@codeaurora.org>
parent 3f0b1f99
Loading
Loading
Loading
Loading
+17 −13
Original line number Original line Diff line number Diff line
@@ -280,6 +280,7 @@ struct smq_invoke_ctx {
	uint32_t earlyWakeTime;
	uint32_t earlyWakeTime;
	/* work done status flag */
	/* work done status flag */
	bool isWorkDone;
	bool isWorkDone;
	bool pm_awake_voted;
};
};


struct fastrpc_ctx_lst {
struct fastrpc_ctx_lst {
@@ -526,6 +527,9 @@ static struct fastrpc_channel_ctx gcinfo[NUM_CHANNELS] = {
static int hlosvm[1] = {VMID_HLOS};
static int hlosvm[1] = {VMID_HLOS};
static int hlosvmperm[1] = {PERM_READ | PERM_WRITE | PERM_EXEC};
static int hlosvmperm[1] = {PERM_READ | PERM_WRITE | PERM_EXEC};


static void fastrpc_pm_awake(int fl_wake_enable, bool *pm_awake_voted);
static void fastrpc_pm_relax(bool *pm_awake_voted);

static inline int64_t getnstimediff(struct timespec *start)
static inline int64_t getnstimediff(struct timespec *start)
{
{
	int64_t ns;
	int64_t ns;
@@ -1355,6 +1359,7 @@ static int context_alloc(struct fastrpc_file *fl, uint32_t kernel,
	ctx->magic = FASTRPC_CTX_MAGIC;
	ctx->magic = FASTRPC_CTX_MAGIC;
	ctx->rspFlags = NORMAL_RESPONSE;
	ctx->rspFlags = NORMAL_RESPONSE;
	ctx->isWorkDone = false;
	ctx->isWorkDone = false;
	ctx->pm_awake_voted = false;


	spin_lock(&fl->hlock);
	spin_lock(&fl->hlock);
	hlist_add_head(&ctx->hn, &clst->pending);
	hlist_add_head(&ctx->hn, &clst->pending);
@@ -1450,6 +1455,7 @@ static void context_notify_user(struct smq_invoke_ctx *ctx,
		break;
		break;
	}
	}
	ctx->rspFlags = (enum fastrpc_response_flags)rspFlags;
	ctx->rspFlags = (enum fastrpc_response_flags)rspFlags;
	fastrpc_pm_awake(ctx->fl->wake_enable, &ctx->pm_awake_voted);
	complete(&ctx->work);
	complete(&ctx->work);
}
}


@@ -2050,7 +2056,7 @@ static void fastrpc_init(struct fastrpc_apps *me)
	me->channel[CDSP_DOMAIN_ID].secure = NON_SECURE_CHANNEL;
	me->channel[CDSP_DOMAIN_ID].secure = NON_SECURE_CHANNEL;
}
}


static inline void fastrpc_pm_awake(int fl_wake_enable, int *wake_enable)
static inline void fastrpc_pm_awake(int fl_wake_enable, bool *pm_awake_voted)
{
{
	struct fastrpc_apps *me = &gfa;
	struct fastrpc_apps *me = &gfa;


@@ -2062,14 +2068,14 @@ static inline void fastrpc_pm_awake(int fl_wake_enable, int *wake_enable)
		__pm_stay_awake(me->wake_source);
		__pm_stay_awake(me->wake_source);
	me->wake_count++;
	me->wake_count++;
	spin_unlock(&me->hlock);
	spin_unlock(&me->hlock);
	*wake_enable = 1;
	*pm_awake_voted = true;
}
}


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


	if (!(*wake_enable))
	if (!(*pm_awake_voted))
		return;
		return;


	spin_lock(&me->hlock);
	spin_lock(&me->hlock);
@@ -2078,7 +2084,7 @@ static inline void fastrpc_pm_relax(int *wake_enable)
	if (!me->wake_count)
	if (!me->wake_count)
		__pm_relax(me->wake_source);
		__pm_relax(me->wake_source);
	spin_unlock(&me->hlock);
	spin_unlock(&me->hlock);
	*wake_enable = 0;
	*pm_awake_voted = false;
}
}


static inline int fastrpc_wait_for_response(struct smq_invoke_ctx *ctx,
static inline int fastrpc_wait_for_response(struct smq_invoke_ctx *ctx,
@@ -2188,13 +2194,12 @@ static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode,
{
{
	struct smq_invoke_ctx *ctx = NULL;
	struct smq_invoke_ctx *ctx = NULL;
	struct fastrpc_ioctl_invoke *invoke = &inv->inv;
	struct fastrpc_ioctl_invoke *invoke = &inv->inv;
	int cid = fl->cid;
	int err = 0, interrupted = 0, cid = fl->cid;
	int interrupted = 0;
	int err = 0, wake_enable = 0;
	struct timespec invoket = {0};
	struct timespec invoket = {0};
	int64_t *perf_counter = NULL;
	int64_t *perf_counter = NULL;
	bool pm_awake_voted = false;


	fastrpc_pm_awake(fl->wake_enable, &wake_enable);
	fastrpc_pm_awake(fl->wake_enable, &pm_awake_voted);
	if (fl->profile) {
	if (fl->profile) {
		perf_counter = getperfcounter(fl, PERF_COUNT);
		perf_counter = getperfcounter(fl, PERF_COUNT);
		getnstimeofday(&invoket);
		getnstimeofday(&invoket);
@@ -2263,10 +2268,9 @@ static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode,
	if (err)
	if (err)
		goto bail;
		goto bail;
 wait:
 wait:
	fastrpc_pm_relax(&wake_enable);
	fastrpc_pm_relax(&pm_awake_voted);
	fastrpc_wait_for_completion(ctx, &interrupted, kernel);
	fastrpc_wait_for_completion(ctx, &interrupted, kernel);
	if (interrupted != -ERESTARTSYS)
	pm_awake_voted = ctx->pm_awake_voted;
		fastrpc_pm_awake(fl->wake_enable, &wake_enable);
	VERIFY(err, 0 == (err = interrupted));
	VERIFY(err, 0 == (err = interrupted));
	if (err)
	if (err)
		goto bail;
		goto bail;
@@ -2305,7 +2309,7 @@ static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode,
	if (fl->profile && !interrupted)
	if (fl->profile && !interrupted)
		fastrpc_update_invoke_count(invoke->handle, perf_counter,
		fastrpc_update_invoke_count(invoke->handle, perf_counter,
						&invoket);
						&invoket);
	fastrpc_pm_relax(&wake_enable);
	fastrpc_pm_relax(&pm_awake_voted);
	return err;
	return err;
}
}