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

Commit e20ea0d5 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: update frame pending in client context during disable"

parents 4a2e5ba5 79b44396
Loading
Loading
Loading
Loading
+15 −9
Original line number Diff line number Diff line
@@ -1490,6 +1490,7 @@ 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");
@@ -1515,6 +1516,9 @@ 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) ||
@@ -1528,9 +1532,6 @@ static void sde_crtc_frame_event_work(struct kthread_work *work)
					atomic_read(&sde_crtc->frame_pending));
			SDE_EVT32(DRMID(crtc), fevent->event,
							SDE_EVTLOG_FUNC_CASE1);

			/* don't propagate unexpected frame done events */
			return;
		} else if (atomic_dec_return(&sde_crtc->frame_pending) == 0) {
			/* release bandwidth and other resources */
			SDE_DEBUG("crtc%d ts:%lld last pending\n",
@@ -1538,13 +1539,15 @@ 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)
		if (fevent->event == SDE_ENCODER_FRAME_EVENT_DONE &&
							!disable_inprogress)
			sde_core_perf_crtc_update(crtc, 0, false);
	} else {
		SDE_ERROR("crtc%d ts:%lld unknown event %u\n", crtc->base.id,
@@ -1580,7 +1583,7 @@ static void sde_crtc_frame_event_cb(void *data, u32 event)
	pipe_id = drm_crtc_index(crtc);

	SDE_DEBUG("crtc%d\n", crtc->base.id);
	SDE_EVT32_VERBOSE(DRMID(crtc));
	SDE_EVT32_VERBOSE(DRMID(crtc), event);

	spin_lock_irqsave(&sde_crtc->spin_lock, flags);
	fevent = list_first_entry_or_null(&sde_crtc->frame_event_list,
@@ -1599,7 +1602,11 @@ static void sde_crtc_frame_event_cb(void *data, u32 event)
	fevent->event = event;
	fevent->crtc = crtc;
	fevent->ts = ktime_get();
	kthread_queue_work(&priv->disp_thread[pipe_id].worker, &fevent->work);
	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);
}

void sde_crtc_complete_commit(struct drm_crtc *crtc,
@@ -2415,8 +2422,7 @@ 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_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);
+16 −12
Original line number Diff line number Diff line
@@ -142,7 +142,6 @@ enum sde_enc_rc_states {
 *				Bit0 = phys_encs[0] etc.
 * @crtc_frame_event_cb:	callback handler for frame event
 * @crtc_frame_event_cb_data:	callback handler private data
 * @crtc_frame_event:		callback event
 * @frame_done_timeout:		frame done timeout in Hz
 * @frame_done_timer:		watchdog timer for frame done event
 * @rsc_client:			rsc client pointer
@@ -160,6 +159,7 @@ 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;
@@ -184,7 +184,6 @@ struct sde_encoder_virt {
	DECLARE_BITMAP(frame_busy_mask, MAX_PHYS_ENCODERS_PER_VIRTUAL);
	void (*crtc_frame_event_cb)(void *, u32 event);
	void *crtc_frame_event_cb_data;
	u32 crtc_frame_event;

	atomic_t frame_done_timeout;
	struct timer_list frame_done_timer;
@@ -204,6 +203,7 @@ 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)
@@ -1456,6 +1456,7 @@ 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];

@@ -1514,6 +1515,7 @@ 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));

@@ -1664,7 +1666,6 @@ static void sde_encoder_frame_done_callback(
	for (i = 0; i < sde_enc->num_phys_encs; i++)
		if (sde_enc->phys_encs[i] == ready_phys) {
			clear_bit(i, sde_enc->frame_busy_mask);
			sde_enc->crtc_frame_event |= event;
			SDE_EVT32_VERBOSE(DRMID(drm_enc), i,
					sde_enc->frame_busy_mask[0]);
		}
@@ -1676,10 +1677,12 @@ 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,
					sde_enc->crtc_frame_event);
				sde_enc->crtc_frame_event_cb_data, event);
	}
}

@@ -1861,7 +1864,6 @@ static void _sde_encoder_kickoff_phys(struct sde_encoder_virt *sde_enc)
	}

	pending_flush = 0x0;
	sde_enc->crtc_frame_event = 0;

	/* update pending counts and trigger kickoff ctl flush atomically */
	spin_lock_irqsave(&sde_enc->enc_spinlock, lock_flags);
@@ -2679,6 +2681,7 @@ static void sde_encoder_frame_done_timeout(unsigned long data)
	struct drm_encoder *drm_enc = (struct drm_encoder *) data;
	struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc);
	struct msm_drm_private *priv;
	u32 event;

	if (!drm_enc || !drm_enc->dev || !drm_enc->dev->dev_private) {
		SDE_ERROR("invalid parameters\n");
@@ -2696,13 +2699,14 @@ static void sde_encoder_frame_done_timeout(unsigned long data)
		return;
	}

	SDE_EVT32(DRMID(drm_enc), 2, sde_enc->crtc_frame_event);
	SDE_ERROR_ENC(sde_enc, "frame done timeout, frame_event %d\n",
			sde_enc->crtc_frame_event);
	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_enc->crtc_frame_event_cb(sde_enc->crtc_frame_event_cb_data,
			sde_enc->crtc_frame_event |
			SDE_ENCODER_FRAME_EVENT_ERROR);
	SDE_EVT32(DRMID(drm_enc), event);
	sde_enc->crtc_frame_event_cb(sde_enc->crtc_frame_event_cb_data, event);
}

static const struct drm_encoder_helper_funcs sde_encoder_helper_funcs = {
+1 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#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