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

Commit 66c83b5b authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: ADSPRPC: Awake PM with a timeout"

parents 6760688b 7f602852
Loading
Loading
Loading
Loading
+39 −26
Original line number Diff line number Diff line
@@ -111,6 +111,9 @@
#define FASTRPC_STATIC_HANDLE_MAX (20)
#define FASTRPC_LATENCY_CTRL_ENB  (1)

/* Maximum PM timeout that can be voted through fastrpc*/
#define MAX_PM_TIMEOUT_MS 50

/* timeout in us for busy polling after early response from remote processor */
#define FASTRPC_POLL_TIME (4000)

@@ -285,7 +288,6 @@ struct smq_invoke_ctx {
	uint32_t earlyWakeTime;
	/* work done status flag */
	bool isWorkDone;
	bool pm_awake_voted;
};

struct fastrpc_ctx_lst {
@@ -460,6 +462,8 @@ struct fastrpc_file {
	char *debug_buf;
	/* Flag to enable PM wake/relax voting for every remote invoke */
	int wake_enable;
	struct wakeup_source *wake_source;
	uint32_t ws_timeout;
};

static struct fastrpc_apps gfa;
@@ -532,8 +536,7 @@ static struct fastrpc_channel_ctx gcinfo[NUM_CHANNELS] = {
static int hlosvm[1] = {VMID_HLOS};
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 void fastrpc_pm_awake(struct fastrpc_file *fl);

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

	spin_lock(&fl->hlock);
	hlist_add_head(&ctx->hn, &clst->pending);
@@ -1444,7 +1446,7 @@ static void context_free(struct smq_invoke_ctx *ctx)
static void context_notify_user(struct smq_invoke_ctx *ctx,
		int retval, uint32_t rspFlags, uint32_t earlyWakeTime)
{
	fastrpc_pm_awake(ctx->fl->wake_enable, &ctx->pm_awake_voted);
	fastrpc_pm_awake(ctx->fl);
	ctx->retval = retval;
	switch (rspFlags) {
	case NORMAL_RESPONSE:
@@ -2090,24 +2092,15 @@ static void fastrpc_init(struct fastrpc_apps *me)
	me->channel[CDSP_DOMAIN_ID].secure = NON_SECURE_CHANNEL;
}

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

	if (!fl_wake_enable || *pm_awake_voted)
		return;
	__pm_stay_awake(me->wake_source);
	*pm_awake_voted = true;
}

static inline void fastrpc_pm_relax(bool *pm_awake_voted)
static inline void fastrpc_pm_awake(struct fastrpc_file *fl)
{
	struct fastrpc_apps *me = &gfa;

	if (!(*pm_awake_voted))
	if (!fl->wake_enable || !fl->wake_source)
		return;
	__pm_relax(me->wake_source);
	*pm_awake_voted = false;
	/*
	 * Vote with PM to abort any suspend in progress and
	 * keep system awake for specified timeout
	 */
	pm_wakeup_ws_event(fl->wake_source, fl->ws_timeout, true);
}

static inline int fastrpc_wait_for_response(struct smq_invoke_ctx *ctx,
@@ -2229,9 +2222,7 @@ static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode,
	int err = 0, interrupted = 0, cid = fl->cid;
	struct timespec invoket = {0};
	int64_t *perf_counter = NULL;
	bool pm_awake_voted = false;

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

@@ -3503,6 +3491,8 @@ static int fastrpc_file_free(struct fastrpc_file *fl)
	spin_lock(&fl->apps->hlock);
	hlist_del_init(&fl->hn);
	spin_unlock(&fl->apps->hlock);
	if (fl->wake_source)
		wakeup_source_unregister(fl->wake_source);
	kfree(fl->debug_buf);

	if (!fl->sctx) {
@@ -3890,6 +3880,11 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp)
	debugfs_file = debugfs_create_file(fl->debug_buf, 0644, debugfs_root,
						fl, &debugfs_fops);

	fl->wake_source = wakeup_source_register(fl->debug_buf);
	if (IS_ERR_OR_NULL(fl->wake_source)) {
		pr_err("adsprpc: Error: %s: %s: wakeup_source_register failed with err %ld\n",
			current->comm, __func__, PTR_ERR(fl->wake_source));
	}
	context_list_ctor(&fl->clst);
	spin_lock_init(&fl->hlock);
	INIT_HLIST_HEAD(&fl->maps);
@@ -4006,8 +4001,26 @@ static int fastrpc_internal_control(struct fastrpc_file *fl,
		cp->kalloc.kalloc_support = 1;
		break;
	case FASTRPC_CONTROL_WAKELOCK:
		if (fl->dev_minor != MINOR_NUM_SECURE_DEV) {
			pr_err("adsprpc: %s: %s: PM voting not allowed for non-secure device node %d\n",
				current->comm, __func__, fl->dev_minor);
			err = -EPERM;
			goto bail;
		}
		fl->wake_enable = cp->wp.enable;
		break;
	case FASTRPC_CONTROL_PM:
		if (!fl->wake_enable) {
			/* Kernel PM voting not requested by this application */
			err = -EACCES;
			goto bail;
		}
		if (cp->pm.timeout > MAX_PM_TIMEOUT_MS)
			fl->ws_timeout = MAX_PM_TIMEOUT_MS;
		else
			fl->ws_timeout = cp->pm.timeout;
		fastrpc_pm_awake(fl);
		break;
	default:
		err = -EBADRQC;
		break;
+16 −0
Original line number Diff line number Diff line
@@ -130,11 +130,21 @@ struct compat_fastrpc_ctrl_kalloc {
	compat_uint_t kalloc_support; /* Remote memory allocation from kernel */
};

struct compat_fastrpc_ctrl_wakelock {
	compat_uint_t enable;	/* wakelock control enable */
};

struct compat_fastrpc_ctrl_pm {
	compat_uint_t timeout;	/* timeout(in ms) for PM to keep system awake*/
};

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_ctrl_wakelock wp;
		struct compat_fastrpc_ctrl_pm pm;
	};
};

@@ -336,6 +346,12 @@ static int compat_get_fastrpc_ioctl_control(
		err |= put_user(p, &ctrl->lp.enable);
		err |= get_user(p, &ctrl32->lp.latency);
		err |= put_user(p, &ctrl->lp.latency);
	} else if (p == FASTRPC_CONTROL_WAKELOCK) {
		err |= get_user(p, &ctrl32->wp.enable);
		err |= put_user(p, &ctrl->wp.enable);
	} else if (p == FASTRPC_CONTROL_PM) {
		err |= get_user(p, &ctrl32->pm.timeout);
		err |= put_user(p, &ctrl->pm.timeout);
	}

	return err;
+6 −0
Original line number Diff line number Diff line
@@ -249,6 +249,7 @@ enum fastrpc_control_type {
	FASTRPC_CONTROL_SMMU		=	2,
	FASTRPC_CONTROL_KALLOC		=	3,
	FASTRPC_CONTROL_WAKELOCK	=	4,
	FASTRPC_CONTROL_PM		=	5,
};

struct fastrpc_ctrl_latency {
@@ -264,12 +265,17 @@ struct fastrpc_ctrl_wakelock {
	uint32_t enable;	/* wakelock control enable */
};

struct fastrpc_ctrl_pm {
	uint32_t timeout;	/* timeout(in ms) for PM to keep system awake*/
};

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