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

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

Merge "drm/msm/sde: move crtc frame event handling to event thread"

parents 6b97a0f4 7ee99097
Loading
Loading
Loading
Loading
+58 −23
Original line number Diff line number Diff line
@@ -1517,7 +1517,6 @@ static void sde_crtc_frame_event_work(struct kthread_work *work)
	struct sde_crtc_state *cstate;
	struct sde_kms *sde_kms;
	unsigned long flags;
	bool disable_inprogress = false;

	if (!work) {
		SDE_ERROR("invalid work handle\n");
@@ -1543,9 +1542,6 @@ static void sde_crtc_frame_event_work(struct kthread_work *work)

	SDE_DEBUG("crtc%d event:%u ts:%lld\n", crtc->base.id, fevent->event,
			ktime_to_ns(fevent->ts));
	disable_inprogress = fevent->event &
					SDE_ENCODER_FRAME_EVENT_DURING_DISABLE;
	fevent->event &= ~SDE_ENCODER_FRAME_EVENT_DURING_DISABLE;

	if (fevent->event == SDE_ENCODER_FRAME_EVENT_DONE ||
			(fevent->event & SDE_ENCODER_FRAME_EVENT_ERROR) ||
@@ -1566,15 +1562,17 @@ static void sde_crtc_frame_event_work(struct kthread_work *work)
					ktime_to_ns(fevent->ts));
			SDE_EVT32(DRMID(crtc), fevent->event,
							SDE_EVTLOG_FUNC_CASE2);
			if (!disable_inprogress)
			sde_core_perf_crtc_release_bw(crtc);
		} else {
			SDE_EVT32_VERBOSE(DRMID(crtc), fevent->event,
							SDE_EVTLOG_FUNC_CASE3);
		}

		if (fevent->event == SDE_ENCODER_FRAME_EVENT_DONE &&
							!disable_inprogress)
		if (fevent->event == SDE_ENCODER_FRAME_EVENT_DONE ||
			(fevent->event & SDE_ENCODER_FRAME_EVENT_ERROR))
			complete_all(&sde_crtc->frame_done_comp);

		if (fevent->event == SDE_ENCODER_FRAME_EVENT_DONE)
			sde_core_perf_crtc_update(crtc, 0, false);
	} else {
		SDE_ERROR("crtc%d ts:%lld unknown event %u\n", crtc->base.id,
@@ -1629,11 +1627,7 @@ static void sde_crtc_frame_event_cb(void *data, u32 event)
	fevent->event = event;
	fevent->crtc = crtc;
	fevent->ts = ktime_get();
	if (event & SDE_ENCODER_FRAME_EVENT_DURING_DISABLE)
		sde_crtc_frame_event_work(&fevent->work);
	else
		kthread_queue_work(&priv->disp_thread[pipe_id].worker,
								&fevent->work);
	kthread_queue_work(&sde_crtc->event_worker, &fevent->work);
}

void sde_crtc_complete_commit(struct drm_crtc *crtc,
@@ -2085,6 +2079,36 @@ static void sde_crtc_destroy_state(struct drm_crtc *crtc,
			cstate->property_values, cstate->property_blobs);
}

static int _sde_crtc_wait_for_frame_done(struct drm_crtc *crtc)
{
	struct sde_crtc *sde_crtc;
	int ret, rc = 0;

	if (!crtc) {
		SDE_ERROR("invalid argument\n");
		return -EINVAL;
	}
	sde_crtc = to_sde_crtc(crtc);

	if (!atomic_read(&sde_crtc->frame_pending)) {
		SDE_DEBUG("no frames pending\n");
		return 0;
	}

	SDE_EVT32(DRMID(crtc), SDE_EVTLOG_FUNC_ENTRY);
	ret = wait_for_completion_timeout(&sde_crtc->frame_done_comp,
			msecs_to_jiffies(SDE_FRAME_DONE_TIMEOUT));
	if (!ret) {
		SDE_ERROR("frame done completion wait timed out, ret:%d\n",
				ret);
		SDE_EVT32(DRMID(crtc), SDE_EVTLOG_FATAL);
		rc = -ETIMEDOUT;
	}
	SDE_EVT32(DRMID(crtc), SDE_EVTLOG_FUNC_EXIT);

	return rc;
}

void sde_crtc_commit_kickoff(struct drm_crtc *crtc)
{
	struct drm_encoder *encoder;
@@ -2129,19 +2153,21 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc)
		sde_encoder_prepare_for_kickoff(encoder, &params);
	}

	if (atomic_read(&sde_crtc->frame_pending) > 2) {
		/* framework allows only 1 outstanding + current */
		SDE_ERROR("crtc%d invalid frame pending\n",
				crtc->base.id);
		SDE_EVT32(DRMID(crtc), 0);
	/* wait for frame_event_done completion */
	if (_sde_crtc_wait_for_frame_done(crtc)) {
		SDE_ERROR("crtc%d wait for frame done failed;frame_pending%d\n",
				crtc->base.id,
				atomic_read(&sde_crtc->frame_pending));
		goto end;
	} else if (atomic_inc_return(&sde_crtc->frame_pending) == 1) {
	}

	if (atomic_inc_return(&sde_crtc->frame_pending) == 1) {
		/* acquire bandwidth and other resources */
		SDE_DEBUG("crtc%d first commit\n", crtc->base.id);
		SDE_EVT32(DRMID(crtc), 1);
		SDE_EVT32(DRMID(crtc), SDE_EVTLOG_FUNC_CASE1);
	} else {
		SDE_DEBUG("crtc%d commit\n", crtc->base.id);
		SDE_EVT32(DRMID(crtc), 2);
		SDE_EVT32(DRMID(crtc), SDE_EVTLOG_FUNC_CASE2);
	}
	sde_crtc->play_count++;

@@ -2151,6 +2177,9 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc)

		sde_encoder_kickoff(encoder);
	}

	reinit_completion(&sde_crtc->frame_done_comp);

end:
	SDE_ATRACE_END("crtc_commit");
	return;
@@ -2444,6 +2473,12 @@ static void sde_crtc_disable(struct drm_crtc *crtc)
	mutex_lock(&sde_crtc->crtc_lock);
	SDE_EVT32(DRMID(crtc));

	/* wait for frame_event_done completion */
	if (_sde_crtc_wait_for_frame_done(crtc))
		SDE_ERROR("crtc%d wait for frame done failed;frame_pending%d\n",
				crtc->base.id,
				atomic_read(&sde_crtc->frame_pending));

	if (atomic_read(&sde_crtc->vblank_refcount) && !sde_crtc->suspend) {
		SDE_ERROR("crtc%d invalid vblank refcount\n",
				crtc->base.id);
@@ -2455,8 +2490,6 @@ static void sde_crtc_disable(struct drm_crtc *crtc)
	}

	if (atomic_read(&sde_crtc->frame_pending)) {
		/* release bandwidth and other resources */
		SDE_ERROR("crtc%d invalid frame pending\n", crtc->base.id);
		SDE_EVT32(DRMID(crtc), atomic_read(&sde_crtc->frame_pending),
							SDE_EVTLOG_FUNC_CASE2);
		sde_core_perf_crtc_release_bw(crtc);
@@ -3714,6 +3747,8 @@ struct drm_crtc *sde_crtc_init(struct drm_device *dev, struct drm_plane *plane)
	spin_lock_init(&sde_crtc->spin_lock);
	atomic_set(&sde_crtc->frame_pending, 0);

	init_completion(&sde_crtc->frame_done_comp);

	INIT_LIST_HEAD(&sde_crtc->frame_event_list);
	INIT_LIST_HEAD(&sde_crtc->user_event_list);
	for (i = 0; i < ARRAY_SIZE(sde_crtc->frame_events); i++) {
+2 −0
Original line number Diff line number Diff line
@@ -135,6 +135,7 @@ struct sde_crtc_event {
 * @frame_events  : static allocation of in-flight frame events
 * @frame_event_list : available frame event list
 * @spin_lock     : spin lock for frame event, transaction status, etc...
 * @frame_done_comp    : for frame_event_done synchronization
 * @event_thread  : Pointer to event handler thread
 * @event_worker  : Event worker queue
 * @event_cache   : Local cache of event worker structures
@@ -186,6 +187,7 @@ struct sde_crtc {
	struct sde_crtc_frame_event frame_events[SDE_CRTC_FRAME_EVENT_SIZE];
	struct list_head frame_event_list;
	spinlock_t spin_lock;
	struct completion frame_done_comp;

	/* for handling internal event thread */
	struct task_struct *event_thread;
+2 −15
Original line number Diff line number Diff line
@@ -56,9 +56,6 @@
		(p) ? ((p)->hw_pp ? (p)->hw_pp->idx - PINGPONG_0 : -1) : -1, \
		##__VA_ARGS__)

/* timeout in frames waiting for frame done */
#define SDE_ENCODER_FRAME_DONE_TIMEOUT	60

/*
 * Two to anticipate panels that can do cmd/vid dynamic switching
 * plan is to create all possible physical encoder types, and switch between
@@ -173,7 +170,6 @@ enum sde_enc_rc_states {
 * @rsc_cfg:			rsc configuration
 * @cur_conn_roi:		current connector roi
 * @prv_conn_roi:		previous connector roi to optimize if unchanged
 * @disable_inprogress:		sde encoder disable is in progress.
 */
struct sde_encoder_virt {
	struct drm_encoder base;
@@ -217,7 +213,6 @@ struct sde_encoder_virt {
	struct sde_encoder_rsc_config rsc_cfg;
	struct sde_rect cur_conn_roi;
	struct sde_rect prv_conn_roi;
	bool disable_inprogress;
};

#define to_sde_encoder_virt(x) container_of(x, struct sde_encoder_virt, base)
@@ -1643,7 +1638,6 @@ static void sde_encoder_virt_enable(struct drm_encoder *drm_enc)
	SDE_EVT32(DRMID(drm_enc));

	sde_enc->cur_master = NULL;
	sde_enc->disable_inprogress = false;
	for (i = 0; i < sde_enc->num_phys_encs; i++) {
		struct sde_encoder_phys *phys = sde_enc->phys_encs[i];

@@ -1702,7 +1696,6 @@ static void sde_encoder_virt_disable(struct drm_encoder *drm_enc)

	priv = drm_enc->dev->dev_private;
	sde_kms = to_sde_kms(priv->kms);
	sde_enc->disable_inprogress = true;

	SDE_EVT32(DRMID(drm_enc));

@@ -1868,9 +1861,6 @@ static void sde_encoder_frame_done_callback(
		sde_encoder_resource_control(drm_enc,
				SDE_ENC_RC_EVENT_FRAME_DONE);

		if (sde_enc->disable_inprogress)
			event |= SDE_ENCODER_FRAME_EVENT_DURING_DISABLE;

		if (sde_enc->crtc_frame_event_cb)
			sde_enc->crtc_frame_event_cb(
				sde_enc->crtc_frame_event_cb_data, event);
@@ -2332,7 +2322,7 @@ void sde_encoder_kickoff(struct drm_encoder *drm_enc)
	SDE_DEBUG_ENC(sde_enc, "\n");

	atomic_set(&sde_enc->frame_done_timeout,
			SDE_ENCODER_FRAME_DONE_TIMEOUT * 1000 /
			SDE_FRAME_DONE_TIMEOUT * 1000 /
			drm_enc->crtc->state->adjusted_mode.vrefresh);
	mod_timer(&sde_enc->frame_done_timer, jiffies +
		((atomic_read(&sde_enc->frame_done_timeout) * HZ) / 1000));
@@ -2913,9 +2903,6 @@ static void sde_encoder_frame_done_timeout(unsigned long data)
	SDE_ERROR_ENC(sde_enc, "frame done timeout\n");

	event = SDE_ENCODER_FRAME_EVENT_ERROR;
	if (sde_enc->disable_inprogress)
		event |= SDE_ENCODER_FRAME_EVENT_DURING_DISABLE;

	SDE_EVT32(DRMID(drm_enc), event);
	sde_enc->crtc_frame_event_cb(sde_enc->crtc_frame_event_cb_data, event);
}
+0 −1
Original line number Diff line number Diff line
@@ -27,7 +27,6 @@
#define SDE_ENCODER_FRAME_EVENT_DONE		BIT(0)
#define SDE_ENCODER_FRAME_EVENT_ERROR		BIT(1)
#define SDE_ENCODER_FRAME_EVENT_PANEL_DEAD	BIT(2)
#define SDE_ENCODER_FRAME_EVENT_DURING_DISABLE	BIT(3)

/**
 * Encoder functions and data types
+4 −0
Original line number Diff line number Diff line
@@ -88,6 +88,10 @@

#define SDE_NAME_SIZE  12


/* timeout in frames waiting for frame done */
#define SDE_FRAME_DONE_TIMEOUT	60

/*
 * struct sde_irq_callback - IRQ callback handlers
 * @list: list to callback