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

Commit 6b6c2964 authored by Dhaval Patel's avatar Dhaval Patel Committed by Gerrit - the friendly Code Review server
Browse files

msm: sde: avoid dynamic kthread create for each rot session



Each rotator session open request creates a thread and
destroys it on close session. These threads are created
to trigger rotation complete fences. Such dynamic allocation
can easily be avoided by creating threads at probe time.

Change-Id: I1a443ca8627b5cf2b2e770ad7ea2863c52aa7d9b
Signed-off-by: default avatarDhaval Patel <pdhaval@codeaurora.org>
parent 150e5aba
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -3400,7 +3400,7 @@ int sde_rotator_resume(struct platform_device *dev)
 */
int sde_rotator_session_open(struct sde_rot_mgr *mgr,
	struct sde_rot_file_private **pprivate, int session_id,
	struct sde_rot_queue *queue)
	struct sde_rot_queue_v1 *queue)
{
	int ret;
	struct sde_rot_file_private *private;
+10 −4
Original line number Diff line number Diff line
/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2015-2018, 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
@@ -242,6 +242,12 @@ struct sde_rot_queue {
	struct sde_rot_hw_resource *hw;
};

struct sde_rot_queue_v1 {
	struct kthread_worker *rot_kw;
	struct task_struct *rot_thread;
	struct sde_rot_timeline *timeline;
	struct sde_rot_hw_resource *hw;
};
/*
 * struct sde_rot_entry_container - rotation request
 * @list: list of active requests managed by rotator manager
@@ -294,7 +300,7 @@ struct sde_rot_entry {
	struct kthread_work commit_work;
	struct kthread_work done_work;
	struct sde_rot_queue *commitq;
	struct sde_rot_queue *fenceq;
	struct sde_rot_queue_v1 *fenceq;
	struct sde_rot_queue *doneq;
	struct sde_rot_entry_container *request;

@@ -351,7 +357,7 @@ struct sde_rot_file_private {
	struct list_head req_list;
	struct list_head perf_list;
	struct sde_rot_mgr *mgr;
	struct sde_rot_queue *fenceq;
	struct sde_rot_queue_v1 *fenceq;
};

/*
@@ -586,7 +592,7 @@ void sde_rotator_core_dump(struct sde_rot_mgr *mgr);
 */
int sde_rotator_session_open(struct sde_rot_mgr *mgr,
	struct sde_rot_file_private **pprivate, int session_id,
	struct sde_rot_queue *queue);
	struct sde_rot_queue_v1 *queue);

/*
 * sde_rotator_session_close - close the given rotator per file session
+52 −21
Original line number Diff line number Diff line
/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2015-2018, 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
@@ -925,6 +925,7 @@ struct sde_rotator_ctx *sde_rotator_ctx_open(
	ctx->rotate = 0;
	ctx->secure = 0;
	ctx->abort_pending = 0;
	ctx->kthread_id = -1;
	ctx->format_cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	ctx->format_cap.fmt.pix.pixelformat = SDE_PIX_FMT_Y_CBCR_H2V2;
	ctx->format_cap.fmt.pix.width = 640;
@@ -982,18 +983,22 @@ struct sde_rotator_ctx *sde_rotator_ctx_open(
		goto error_create_sysfs;
	}

	snprintf(name, sizeof(name), "rot_fenceq_%d_%d", rot_dev->dev->id,
			ctx->session_id);
	kthread_init_worker(&ctx->work_queue.rot_kw);
	ctx->work_queue.rot_thread = kthread_run(kthread_worker_fn,
			&ctx->work_queue.rot_kw, name);
	if (IS_ERR(ctx->work_queue.rot_thread)) {
		SDEDEV_ERR(ctx->rot_dev->dev, "fail allocate kthread\n");
		ret = -EPERM;
		ctx->work_queue.rot_thread = NULL;
		goto error_alloc_workqueue;
	for (i = 0; i < MAX_ROT_OPEN_SESSION; i++) {
		if (rot_dev->kthread_free[i]) {
			rot_dev->kthread_free[i] = false;
			ctx->kthread_id = i;
			ctx->work_queue.rot_kw = &rot_dev->rot_kw[i];
			ctx->work_queue.rot_thread = rot_dev->rot_thread[i];
			break;
		}
	}

	if (ctx->kthread_id < 0) {
		SDEDEV_ERR(ctx->rot_dev->dev,
				"fail to acquire the kthread\n");
		ret = -EINVAL;
		goto error_alloc_kthread;
	}
	SDEDEV_DBG(ctx->rot_dev->dev, "kthread name=%s\n", name);

	snprintf(name, sizeof(name), "%d_%d", rot_dev->dev->id,
			ctx->session_id);
@@ -1052,9 +1057,9 @@ struct sde_rotator_ctx *sde_rotator_ctx_open(
error_open_session:
	sde_rot_mgr_unlock(rot_dev->mgr);
	sde_rotator_destroy_timeline(ctx->work_queue.timeline);
	kthread_flush_worker(&ctx->work_queue.rot_kw);
	kthread_stop(ctx->work_queue.rot_thread);
error_alloc_workqueue:
	rot_dev->kthread_free[ctx->kthread_id] = true;
	ctx->kthread_id = -1;
error_alloc_kthread:
	sysfs_remove_group(&ctx->kobj, &sde_rotator_fs_attr_group);
error_create_sysfs:
	kobject_put(&ctx->kobj);
@@ -1129,8 +1134,10 @@ static int sde_rotator_ctx_release(struct sde_rotator_ctx *ctx,
	mutex_lock(&rot_dev->lock);
	SDEDEV_DBG(rot_dev->dev, "release context s:%d\n", session_id);
	sde_rotator_destroy_timeline(ctx->work_queue.timeline);
	kthread_flush_worker(&ctx->work_queue.rot_kw);
	kthread_stop(ctx->work_queue.rot_thread);
	if (ctx->kthread_id >= 0 && ctx->work_queue.rot_kw) {
		kthread_flush_worker(ctx->work_queue.rot_kw);
		rot_dev->kthread_free[ctx->kthread_id] = true;
	}
	sysfs_remove_group(&ctx->kobj, &sde_rotator_fs_attr_group);
	kobject_put(&ctx->kobj);
	if (ctx->file) {
@@ -1817,7 +1824,7 @@ int sde_rotator_inline_commit(void *handle, struct sde_rotator_inline_cmd *cmd,
		} else {
			SDEROT_ERR("invalid stats timestamp\n");
		}
		req->retire_kw = &ctx->work_queue.rot_kw;
		req->retire_kw = ctx->work_queue.rot_kw;
		req->retire_work = &request->retire_work;

		trace_rot_entry_fence(
@@ -3170,7 +3177,7 @@ static int sde_rotator_process_buffers(struct sde_rotator_ctx *ctx,
		goto error_init_request;
	}

	req->retire_kw = &ctx->work_queue.rot_kw;
	req->retire_kw = ctx->work_queue.rot_kw;
	req->retire_work = &request->retire_work;

	ret = sde_rotator_handle_request_common(
@@ -3468,7 +3475,7 @@ static int sde_rotator_job_ready(void *priv)
			list_del_init(&request->list);
			list_add_tail(&request->list, &ctx->pending_list);
			spin_unlock(&ctx->list_lock);
			kthread_queue_work(&ctx->work_queue.rot_kw,
			kthread_queue_work(ctx->work_queue.rot_kw,
					&request->submit_work);
		}
	} else if (request && !atomic_read(&request->req->pending_count)) {
@@ -3522,7 +3529,8 @@ static int sde_rotator_probe(struct platform_device *pdev)
{
	struct sde_rotator_device *rot_dev;
	struct video_device *vdev;
	int ret;
	int ret, i;
	char name[32];

	SDEDEV_DBG(&pdev->dev, "SDE v4l2 rotator probed\n");

@@ -3605,9 +3613,29 @@ static int sde_rotator_probe(struct platform_device *pdev)

	rot_dev->debugfs_root = sde_rotator_create_debugfs(rot_dev);

	for (i = 0; i < MAX_ROT_OPEN_SESSION; i++) {
		snprintf(name, sizeof(name), "rot_fenceq_%d_%d",
			rot_dev->dev->id, i);
		kthread_init_worker(&rot_dev->rot_kw[i]);
		rot_dev->rot_thread[i] = kthread_run(kthread_worker_fn,
			&rot_dev->rot_kw[i], name);
		if (IS_ERR(rot_dev->rot_thread[i])) {
			SDEDEV_ERR(rot_dev->dev,
				"fail allocate kthread i:%d\n", i);
			ret = -EPERM;
			goto error_kthread_create;
		}
		rot_dev->kthread_free[i] = true;
	}

	SDEDEV_INFO(&pdev->dev, "SDE v4l2 rotator probe success\n");

	return 0;
error_kthread_create:
	for (i--; i >= 0; i--)
		kthread_stop(rot_dev->rot_thread[i]);
	sde_rotator_destroy_debugfs(rot_dev->debugfs_root);
	video_unregister_device(rot_dev->vdev);
error_video_register:
	video_device_release(vdev);
error_alloc_video_device:
@@ -3630,6 +3658,7 @@ static int sde_rotator_probe(struct platform_device *pdev)
static int sde_rotator_remove(struct platform_device *pdev)
{
	struct sde_rotator_device *rot_dev;
	int i;

	rot_dev = platform_get_drvdata(pdev);
	if (rot_dev == NULL) {
@@ -3638,6 +3667,8 @@ static int sde_rotator_remove(struct platform_device *pdev)
	}

	sde_rotator_pm_qos_remove(rot_dev->mdata);
	for (i = MAX_ROT_OPEN_SESSION - 1; i >= 0; i--)
		kthread_stop(rot_dev->rot_thread[i]);
	sde_rotator_destroy_debugfs(rot_dev->debugfs_root);
	video_unregister_device(rot_dev->vdev);
	video_device_release(rot_dev->vdev);
+14 −2
Original line number Diff line number Diff line
/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2015-2018, 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
@@ -41,6 +41,8 @@
/* maximum number of outstanding requests per ctx session */
#define SDE_ROTATOR_REQUEST_MAX		2

#define MAX_ROT_OPEN_SESSION 16

struct sde_rotator_device;
struct sde_rotator_ctx;

@@ -137,6 +139,7 @@ struct sde_rotator_request {
 * @retired_list: list of retired/free request
 * @requests: static allocation of free requests
 * @rotcfg: current core rotation configuration
 * @kthread_id: thread_id used for fence management
 */
struct sde_rotator_ctx {
	struct kobject kobj;
@@ -161,7 +164,7 @@ struct sde_rotator_ctx {
	struct sde_rotator_vbinfo *vbinfo_cap;
	struct sde_rotator_vbinfo *vbinfo_out;
	wait_queue_head_t wait_queue;
	struct sde_rot_queue work_queue;
	struct sde_rot_queue_v1 work_queue;
	struct sde_rot_file_private *private;
	struct llcc_slice_desc *slice;
	u32 commit_sequence_id;
@@ -171,6 +174,8 @@ struct sde_rotator_ctx {
	struct list_head retired_list;
	struct sde_rotator_request requests[SDE_ROTATOR_REQUEST_MAX];
	struct sde_rotation_config rotcfg;

	int kthread_id;
};

/*
@@ -209,6 +214,9 @@ struct sde_rotator_statistics {
 * @open_timeout: maximum wait time for ctx open in msec
 * @open_wq: wait queue for ctx open
 * @excl_ctx: Pointer to exclusive ctx
 * @rot_kw: rotator thread work
 * @rot_thread: rotator threads
 * @kthread_free: check if thread is available or not
 */
struct sde_rotator_device {
	struct mutex lock;
@@ -234,6 +242,10 @@ struct sde_rotator_device {
	u32 open_timeout;
	wait_queue_head_t open_wq;
	struct sde_rotator_ctx *excl_ctx;

	struct kthread_worker rot_kw[MAX_ROT_OPEN_SESSION];
	struct task_struct *rot_thread[MAX_ROT_OPEN_SESSION];
	bool kthread_free[MAX_ROT_OPEN_SESSION];
};

static inline