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

Commit fd8f774f authored by Dhaval Patel's avatar Dhaval Patel
Browse files

drm/msm/sde: reset release and retire timeline for display



Reset release and retire fence timeline when crtc
disable is called. At this point; encoder is already
disabled and timing engine is also disabled for video
mode panel. Command mode panel has transferred the last
buffer. This gives assurance that display hardware is not
accessing any buffer.

Change-Id: I20908a8e8766c2cbe26ffe8b110b98bcb1fd881f
Signed-off-by: default avatarDhaval Patel <pdhaval@codeaurora.org>
parent 14416b24
Loading
Loading
Loading
Loading
+12 −1
Original line number Diff line number Diff line
@@ -903,7 +903,18 @@ void sde_connector_complete_commit(struct drm_connector *connector,
	}

	/* signal connector's retire fence */
	sde_fence_signal(&to_sde_connector(connector)->retire_fence, ts, 0);
	sde_fence_signal(&to_sde_connector(connector)->retire_fence, ts, false);
}

void sde_connector_commit_reset(struct drm_connector *connector, ktime_t ts)
{
	if (!connector) {
		SDE_ERROR("invalid connector\n");
		return;
	}

	/* signal connector's retire fence */
	sde_fence_signal(&to_sde_connector(connector)->retire_fence, ts, true);
}

static enum drm_connector_status
+7 −0
Original line number Diff line number Diff line
@@ -448,6 +448,13 @@ void sde_connector_prepare_fence(struct drm_connector *connector);
 */
void sde_connector_complete_commit(struct drm_connector *connector, ktime_t ts);

/**
 * sde_connector_commit_reset - reset the completion signal
 * @connector: Pointer to drm connector object
 * @ts: timestamp to be updated in the fence signalling
 */
void sde_connector_commit_reset(struct drm_connector *connector, ktime_t ts);

/**
 * sde_connector_get_info - query display specific information
 * @connector: Pointer to drm connector object
+11 −2
Original line number Diff line number Diff line
@@ -2041,7 +2041,7 @@ static void sde_crtc_frame_event_work(struct kthread_work *work)

	if (fevent->event & SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE) {
		SDE_ATRACE_BEGIN("signal_release_fence");
		sde_fence_signal(&sde_crtc->output_fence, fevent->ts, 0);
		sde_fence_signal(&sde_crtc->output_fence, fevent->ts, false);
		SDE_ATRACE_END("signal_release_fence");
	}

@@ -2992,7 +2992,7 @@ static void sde_crtc_disable(struct drm_crtc *crtc)
	struct sde_crtc_irq_info *node = NULL;
	struct drm_event event;
	u32 power_on;
	int ret;
	int ret, i;

	if (!crtc || !crtc->dev || !crtc->dev->dev_private || !crtc->state) {
		SDE_ERROR("invalid crtc\n");
@@ -3067,6 +3067,15 @@ static void sde_crtc_disable(struct drm_crtc *crtc)
		sde_power_handle_unregister_event(&priv->phandle,
				sde_crtc->power_event);

	/**
	 * All callbacks are unregistered and frame done waits are complete
	 * at this point. No buffers are accessed by hardware.
	 * reset the fence timeline if there is any issue.
	 */
	sde_fence_signal(&sde_crtc->output_fence, ktime_get(), true);
	for (i = 0; i < cstate->num_connectors; ++i)
		sde_connector_commit_reset(cstate->connectors[i], ktime_get());

	memset(sde_crtc->mixers, 0, sizeof(sde_crtc->mixers));
	sde_crtc->num_mixers = 0;

+17 −5
Original line number Diff line number Diff line
@@ -338,7 +338,8 @@ int sde_fence_create(struct sde_fence_context *ctx, uint64_t *val,
	return rc;
}

void sde_fence_signal(struct sde_fence_context *ctx, ktime_t ts, bool is_error)
void sde_fence_signal(struct sde_fence_context *ctx, ktime_t ts,
							bool reset_timeline)
{
	unsigned long flags;
	struct sde_fence *fc, *next;
@@ -348,14 +349,25 @@ void sde_fence_signal(struct sde_fence_context *ctx, ktime_t ts, bool is_error)
	if (!ctx) {
		SDE_ERROR("invalid ctx, %pK\n", ctx);
		return;
	} else if (is_error) {
		return;
	}

	INIT_LIST_HEAD(&local_list_head);

	spin_lock_irqsave(&ctx->lock, flags);
	if (reset_timeline) {
		if ((int)(ctx->done_count - ctx->commit_count) < 0) {
			SDE_ERROR(
				"timeline reset attempt! done count:%d commit:%d\n",
				ctx->done_count, ctx->commit_count);
			ctx->done_count = ctx->commit_count;
			SDE_EVT32(ctx->drm_id, ctx->done_count,
				ctx->commit_count, ktime_to_us(ts),
				reset_timeline, SDE_EVTLOG_FATAL);
		} else {
			spin_unlock_irqrestore(&ctx->lock, flags);
			return;
		}
	} else if ((int)(ctx->done_count - ctx->commit_count) < 0) {
		++ctx->done_count;
		SDE_DEBUG("fence_signal:done count:%d commit count:%d\n",
					ctx->done_count, ctx->commit_count);
@@ -363,7 +375,7 @@ void sde_fence_signal(struct sde_fence_context *ctx, ktime_t ts, bool is_error)
		SDE_ERROR("extra signal attempt! done count:%d commit:%d\n",
					ctx->done_count, ctx->commit_count);
		SDE_EVT32(ctx->drm_id, ctx->done_count, ctx->commit_count,
			ktime_to_us(ts), SDE_EVTLOG_FATAL);
			ktime_to_us(ts), reset_timeline, SDE_EVTLOG_FATAL);
		spin_unlock_irqrestore(&ctx->lock, flags);
		return;
	}
+3 −3
Original line number Diff line number Diff line
@@ -128,10 +128,10 @@ int sde_fence_create(struct sde_fence_context *fence, uint64_t *val,
 * sde_fence_signal - advance fence timeline to signal outstanding fences
 * @fence: Pointer fence container
 * @ts: fence timestamp
 * @is_error: Set to non-zero if the commit didn't complete successfully
 * @reset_timeline: reset the fence timeline to done count equal to commit count
 */
void sde_fence_signal(struct sde_fence_context *fence, ktime_t ts,
		bool is_error);
		bool reset_timeline);
#else
static inline void *sde_sync_get(uint64_t fd)
{
@@ -170,7 +170,7 @@ static inline int sde_fence_get(struct sde_fence_context *fence, uint64_t *val)
}

static inline void sde_fence_signal(struct sde_fence_context *fence,
						ktime_t ts, bool is_error)
						ktime_t ts, bool reset_timeline)
{
	/* do nothing */
}