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

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

Merge "msm: sde: avoid commit kickoff if no inline start"

parents a8aefe81 3ce07c04
Loading
Loading
Loading
Loading
+109 −45
Original line number Diff line number Diff line
@@ -914,6 +914,44 @@ static int sde_rotator_is_hw_available(struct sde_rot_mgr *mgr,
	}
}

/*
 * sde_rotator_req_wait_for_idle - wait for hw for a request to be idle
 * @mgr: Pointer to rotator manager
 * @req: Pointer to rotation request
 */
static void sde_rotator_req_wait_for_idle(struct sde_rot_mgr *mgr,
		struct sde_rot_entry_container *req)
{
	struct sde_rot_queue *queue;
	struct sde_rot_hw_resource *hw;
	int i, ret;

	if (!mgr || !req) {
		SDEROT_ERR("invalid params\n");
		return;
	}

	for (i = 0; i < req->count; i++) {
		queue = req->entries[i].commitq;
		if (!queue || !queue->hw)
			continue;
		hw = queue->hw;
		while (atomic_read(&hw->num_active) > 1) {
			sde_rot_mgr_unlock(mgr);
			ret = wait_event_timeout(hw->wait_queue,
				atomic_read(&hw->num_active) <= 1,
				msecs_to_jiffies(mgr->hwacquire_timeout));
			sde_rot_mgr_lock(mgr);
			if (!ret) {
				SDEROT_ERR(
					"timeout waiting for hw idle, a:%d\n",
					atomic_read(&hw->num_active));
				return;
			}
		}
	}
}

/*
 * sde_rotator_get_hw_resource - block waiting for hw availability or timeout
 * @queue: Pointer to rotator queue
@@ -1220,6 +1258,11 @@ void sde_rotator_queue_request(struct sde_rot_mgr *mgr,
		return;
	}

	if (!req->entries) {
		SDEROT_DBG("no entries in request\n");
		return;
	}

	for (i = 0; i < req->count; i++) {
		entry = req->entries + i;
		queue = entry->commitq;
@@ -1542,10 +1585,23 @@ static void sde_rotator_commit_handler(struct kthread_work *work)
		goto error;
	}

	if (entry->item.ts)
		entry->item.ts[SDE_ROTATOR_TS_START] = ktime_get();

	ret = sde_rotator_req_wait_start(mgr, request);
	if (ret) {
		SDEROT_WARN("timeout waiting for inline start\n");
		SDEROT_EVTLOG(entry->item.session_id, entry->item.sequence_id,
				SDE_ROT_EVTLOG_ERROR);
		goto kickoff_error;
	}

	ret = mgr->ops_kickoff_entry(hw, entry);
	if (ret) {
		SDEROT_ERR("fail to do kickoff %d\n", ret);
		goto error;
		SDEROT_EVTLOG(entry->item.session_id, entry->item.sequence_id,
				SDE_ROT_EVTLOG_ERROR);
		goto kickoff_error;
	}

	if (entry->item.ts)
@@ -1556,6 +1612,13 @@ static void sde_rotator_commit_handler(struct kthread_work *work)
	kthread_queue_work(&entry->doneq->rot_kw, &entry->done_work);
	sde_rot_mgr_unlock(mgr);
	return;
kickoff_error:
	/*
	 * Wait for any pending operations to complete before cancelling this
	 * one so that the system is left in a consistent state.
	 */
	sde_rotator_req_wait_for_idle(mgr, request);
	mgr->ops_cancel_hw(hw, entry);
error:
	sde_smmu_ctrl(0);
smmu_error:
@@ -1609,18 +1672,6 @@ static void sde_rotator_done_handler(struct kthread_work *work)
		entry->item.flags,
		entry->dnsc_factor_w, entry->dnsc_factor_h);

	ret = wait_for_completion_timeout(
			&entry->item.inline_start,
			msecs_to_jiffies(ROT_INLINE_START_TIMEOUT_IN_MS));
	if (!ret) {
		SDEROT_WARN("timeout waiting for inline start\n");
		SDEROT_EVTLOG(entry->item.session_id, entry->item.sequence_id,
				SDE_ROT_EVTLOG_ERROR);
	}

	if (entry->item.ts)
		entry->item.ts[SDE_ROTATOR_TS_START] = ktime_get();

	SDEROT_EVTLOG(entry->item.session_id, 0);
	ret = mgr->ops_wait_for_entry(hw, entry);
	if (ret) {
@@ -2164,34 +2215,6 @@ int sde_rotator_validate_request(struct sde_rot_mgr *mgr,
	return ret;
}

/*
 * sde_rotator_commit_request - commit the request to hardware
 * @mgr: pointer to rotator manager
 * @private: pointer to per file context
 * @req: pointer to rotation request
 *
 * This differs from sde_rotator_queue_request in that this
 * function will wait until request is committed to hardware.
 */
void sde_rotator_commit_request(struct sde_rot_mgr *mgr,
	struct sde_rot_file_private *ctx,
	struct sde_rot_entry_container *req)
{
	int i;

	if (!mgr || !ctx || !req || !req->entries) {
		SDEROT_ERR("null parameters\n");
		return;
	}

	sde_rotator_queue_request(mgr, ctx, req);

	sde_rot_mgr_unlock(mgr);
	for (i = 0; i < req->count; i++)
		kthread_flush_work(&req->entries[i].commit_work);
	sde_rot_mgr_lock(mgr);
}

static int sde_rotator_open_session(struct sde_rot_mgr *mgr,
	struct sde_rot_file_private *private, u32 session_id)
{
@@ -2408,26 +2431,67 @@ struct sde_rot_entry_container *sde_rotator_req_init(
	return req;
}

void sde_rotator_req_reset_start(struct sde_rot_entry_container *req)
void sde_rotator_req_reset_start(struct sde_rot_mgr *mgr,
		struct sde_rot_entry_container *req)
{
	int i;

	if (!req)
	if (!mgr || !req)
		return;

	for (i = 0; i < req->count; i++)
		reinit_completion(&req->entries[i].item.inline_start);
}

void sde_rotator_req_set_start(struct sde_rot_entry_container *req)
void sde_rotator_req_set_start(struct sde_rot_mgr *mgr,
		struct sde_rot_entry_container *req)
{
	struct kthread_work *commit_work;
	int i;

	if (!req)
	if (!mgr || !req || !req->entries)
		return;

	/* signal ready to start */
	for (i = 0; i < req->count; i++)
		complete_all(&req->entries[i].item.inline_start);

	for (i = 0; i < req->count; i++) {
		commit_work = &req->entries[i].commit_work;

		SDEROT_EVTLOG(i, req->count);

		sde_rot_mgr_unlock(mgr);
		kthread_flush_work(commit_work);
		sde_rot_mgr_lock(mgr);
	}
}

int sde_rotator_req_wait_start(struct sde_rot_mgr *mgr,
		struct sde_rot_entry_container *req)
{
	struct completion *inline_start;
	int i, ret;

	if (!mgr || !req || !req->entries)
		return -EINVAL;

	/* only wait for sbuf mode */
	if (!mgr->sbuf_ctx || !req->count ||
			mgr->sbuf_ctx != req->entries[0].private)
		return 0;

	for (i = 0; i < req->count; i++) {
		inline_start = &req->entries[i].item.inline_start;

		sde_rot_mgr_unlock(mgr);
		ret = wait_for_completion_timeout(inline_start,
			msecs_to_jiffies(ROT_INLINE_START_TIMEOUT_IN_MS));
		sde_rot_mgr_lock(mgr);
	}

	/* wait call returns zero on timeout */
	return ret ? 0 : -EBUSY;
}

void sde_rotator_req_finish(struct sde_rot_mgr *mgr,
+19 −16
Original line number Diff line number Diff line
@@ -115,8 +115,8 @@ enum sde_rotator_ts {
	SDE_ROTATOR_TS_FENCE,		/* wait for source buffer fence */
	SDE_ROTATOR_TS_QUEUE,		/* wait for h/w resource */
	SDE_ROTATOR_TS_COMMIT,		/* prepare h/w command */
	SDE_ROTATOR_TS_START,		/* wait for h/w kickoff rdy (inline) */
	SDE_ROTATOR_TS_FLUSH,		/* initiate h/w processing */
	SDE_ROTATOR_TS_START,		/* h/w triggered (if inline) */
	SDE_ROTATOR_TS_DONE,		/* receive h/w completion */
	SDE_ROTATOR_TS_RETIRE,		/* signal destination buffer fence */
	SDE_ROTATOR_TS_SRCDQB,		/* dequeue source buffer */
@@ -448,6 +448,8 @@ struct sde_rot_mgr {

	int (*ops_config_hw)(struct sde_rot_hw_resource *hw,
			struct sde_rot_entry *entry);
	int (*ops_cancel_hw)(struct sde_rot_hw_resource *hw,
			struct sde_rot_entry *entry);
	int (*ops_kickoff_entry)(struct sde_rot_hw_resource *hw,
			struct sde_rot_entry *entry);
	int (*ops_wait_for_entry)(struct sde_rot_hw_resource *hw,
@@ -622,20 +624,33 @@ struct sde_rot_entry_container *sde_rotator_req_init(
 *	indicator that allows the rotator to delay its rotator
 *	timeout waiting until such time as the inline rotation has
 *	really started.
 * @mgr: Pointer to rotator manager
 * @req: Pointer to rotation request
 */
void sde_rotator_req_reset_start(struct sde_rot_entry_container *req);
void sde_rotator_req_reset_start(struct sde_rot_mgr *mgr,
		struct sde_rot_entry_container *req);

/*
 * sde_rotator_req_set_start - set inline h/w 'start' indicator
 * @mgr: Pointer to rotator manager
 * @req: Pointer to rotation request
 */
void sde_rotator_req_set_start(struct sde_rot_entry_container *req);
void sde_rotator_req_set_start(struct sde_rot_mgr *mgr,
		struct sde_rot_entry_container *req);

/*
 * sde_rotator_req_wait_start - wait for inline h/w 'start' indicator
 * @mgr: Pointer to rotator manager
 * @req: Pointer to rotation request
 * return: Zero on success
 */
int sde_rotator_req_wait_start(struct sde_rot_mgr *mgr,
		struct sde_rot_entry_container *req);

/*
 * sde_rotator_req_finish - notify manager that client is finished with the
 *	given request and manager can release the request as required
 * @rot_dev: Pointer to rotator device
 * @mgr: Pointer to rotator manager
 * @private: Pointer to rotator manager per file context
 * @req: Pointer to rotation request
 * return: none
@@ -667,18 +682,6 @@ void sde_rotator_queue_request(struct sde_rot_mgr *rot_dev,
	struct sde_rot_file_private *ctx,
	struct sde_rot_entry_container *req);

/*
 * sde_rotator_commit_request - queue/schedule the given request and wait
 *	until h/w commit
 * @rot_dev: Pointer to rotator device
 * @private: Pointer to rotator manager per file context
 * @req: Pointer to rotation request
 * return: 0 if success; error code otherwise
 */
void sde_rotator_commit_request(struct sde_rot_mgr *mgr,
	struct sde_rot_file_private *ctx,
	struct sde_rot_entry_container *req);

/*
 * sde_rotator_verify_config_all - verify given rotation configuration
 * @rot_dev: Pointer to rotator device
+5 −5
Original line number Diff line number Diff line
@@ -793,7 +793,7 @@ static int sde_rotator_stat_show(struct seq_file *s, void *data)
					start_time));

		seq_printf(s,
			"s:%d sq:%lld dq:%lld fe:%lld q:%lld c:%lld fl:%lld st:%lld d:%lld sdq:%lld ddq:%lld t:%lld oht:%lld\n",
			"s:%d sq:%lld dq:%lld fe:%lld q:%lld c:%lld st:%lld fl:%lld d:%lld sdq:%lld ddq:%lld t:%lld oht:%lld\n",
			i,
			ktime_to_us(ktime_sub(ts[SDE_ROTATOR_TS_FENCE],
					ts[SDE_ROTATOR_TS_SRCQB])),
@@ -803,12 +803,12 @@ static int sde_rotator_stat_show(struct seq_file *s, void *data)
					ts[SDE_ROTATOR_TS_FENCE])),
			ktime_to_us(ktime_sub(ts[SDE_ROTATOR_TS_COMMIT],
					ts[SDE_ROTATOR_TS_QUEUE])),
			ktime_to_us(ktime_sub(ts[SDE_ROTATOR_TS_FLUSH],
					ts[SDE_ROTATOR_TS_COMMIT])),
			ktime_to_us(ktime_sub(ts[SDE_ROTATOR_TS_START],
					ts[SDE_ROTATOR_TS_FLUSH])),
			ktime_to_us(ktime_sub(ts[SDE_ROTATOR_TS_DONE],
					ts[SDE_ROTATOR_TS_COMMIT])),
			ktime_to_us(ktime_sub(ts[SDE_ROTATOR_TS_FLUSH],
					ts[SDE_ROTATOR_TS_START])),
			ktime_to_us(ktime_sub(ts[SDE_ROTATOR_TS_DONE],
					ts[SDE_ROTATOR_TS_FLUSH])),
			ktime_to_us(ktime_sub(ts[SDE_ROTATOR_TS_RETIRE],
					ts[SDE_ROTATOR_TS_DONE])),
			ktime_to_us(ktime_sub(ts[SDE_ROTATOR_TS_SRCDQB],
+3 −3
Original line number Diff line number Diff line
@@ -1686,9 +1686,9 @@ int sde_rotator_inline_commit(void *handle, struct sde_rotator_inline_cmd *cmd,
			goto error_handle_request;
		}

		sde_rotator_req_reset_start(req);
		sde_rotator_req_reset_start(rot_dev->mgr, req);

		sde_rotator_commit_request(rot_dev->mgr, ctx->private, req);
		sde_rotator_queue_request(rot_dev->mgr, ctx->private, req);

		request->committed = true;

@@ -1703,7 +1703,7 @@ int sde_rotator_inline_commit(void *handle, struct sde_rotator_inline_cmd *cmd,
		}

		request = cmd->priv_handle;
		sde_rotator_req_set_start(request->req);
		sde_rotator_req_set_start(rot_dev->mgr, request->req);
	} else if (cmd_type == SDE_ROTATOR_INLINE_CMD_CLEANUP) {
		if (!cmd->priv_handle) {
			ret = -EINVAL;
+7 −0
Original line number Diff line number Diff line
@@ -343,6 +343,12 @@ static int sde_rotator_config_hw(struct sde_rot_hw_resource *hw,
	return ret;
}

static int sde_rotator_cancel_hw(struct sde_rot_hw_resource *hw,
	struct sde_rot_entry *entry)
{
	return 0;
}

static int sde_rotator_kickoff_entry(struct sde_rot_hw_resource *hw,
	struct sde_rot_entry *entry)
{
@@ -684,6 +690,7 @@ int sde_rotator_r1_init(struct sde_rot_mgr *mgr)

	mgr->hw_data = hw_data;
	mgr->ops_config_hw = sde_rotator_config_hw;
	mgr->ops_cancel_hw = sde_rotator_cancel_hw;
	mgr->ops_kickoff_entry = sde_rotator_kickoff_entry;
	mgr->ops_wait_for_entry = sde_rotator_wait_for_entry;
	mgr->ops_hw_alloc = sde_rotator_hw_alloc_ext;
Loading