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

Commit 69b6d362 authored by Yashwanth's avatar Yashwanth
Browse files

disp: msm: update vblank queue mechanism



If vblank call is queued to both commit & event thread,
in few cases, the order in which vblank call is queued and
order in which the execution takes place might differ
resulting in bad state machine. This change adds mutex lock
mechanism to avoid enabling irq duing modeset and also
reverts earlier commit 7ba450fa ("disp: msm: queue
vblank work on disp thread during modeset").

Change-Id: Ifdf0502aee3f4cf911b1596aae2a9f2f648d9919
Signed-off-by: default avatarYashwanth <yvulapu@codeaurora.org>
parent 313dae2c
Loading
Loading
Loading
Loading
+1 −9
Original line number Diff line number Diff line
@@ -339,14 +339,6 @@ static int vblank_ctrl_queue_work(struct msm_drm_private *priv,
	cur_work->crtc_id = crtc_id;
	cur_work->enable = enable;
	cur_work->priv = priv;

	/* During modeset scenario, vblank request is queued to
	 * display thread to avoid enabling irq resulting in
	 * vblank refcount mismatch
	 */
	if (crtc->state && drm_atomic_crtc_needs_modeset(crtc->state))
		worker = &priv->disp_thread[crtc_id].worker;
	else
	worker = &priv->event_thread[crtc_id].worker;

	kthread_queue_work(worker, &cur_work->work);
+3 −0
Original line number Diff line number Diff line
@@ -4839,6 +4839,7 @@ int sde_crtc_vblank(struct drm_crtc *crtc, bool en)
	}
	sde_crtc = to_sde_crtc(crtc);

	mutex_lock(&sde_crtc->vblank_modeset_ctrl_lock);
	mutex_lock(&sde_crtc->crtc_lock);
	SDE_EVT32(DRMID(&sde_crtc->base), en, sde_crtc->enabled);
	ret = _sde_crtc_vblank_enable_no_lock(sde_crtc, en);
@@ -4847,6 +4848,7 @@ int sde_crtc_vblank(struct drm_crtc *crtc, bool en)
				sde_crtc->name, ret);

	mutex_unlock(&sde_crtc->crtc_lock);
	mutex_unlock(&sde_crtc->vblank_modeset_ctrl_lock);

	return 0;
}
@@ -6132,6 +6134,7 @@ struct drm_crtc *sde_crtc_init(struct drm_device *dev, struct drm_plane *plane)
	mutex_init(&sde_crtc->crtc_lock);
	spin_lock_init(&sde_crtc->spin_lock);
	atomic_set(&sde_crtc->frame_pending, 0);
	mutex_init(&sde_crtc->vblank_modeset_ctrl_lock);

	sde_crtc->enabled = false;

+3 −0
Original line number Diff line number Diff line
@@ -236,6 +236,8 @@ struct sde_crtc_misr_info {
 * @ad_dirty      : list containing ad properties that are dirty
 * @ad_active     : list containing ad properties that are active
 * @crtc_lock     : crtc lock around create, destroy and access.
 * @vblank_modeset_ctrl_lock     : lock used for controlling vblank
				during modeset
 * @frame_pending : Whether or not an update is pending
 * @frame_events  : static allocation of in-flight frame events
 * @frame_event_list : available frame event list
@@ -309,6 +311,7 @@ struct sde_crtc {

	struct mutex crtc_lock;
	struct mutex crtc_cp_lock;
	struct mutex vblank_modeset_ctrl_lock;

	atomic_t frame_pending;
	struct sde_crtc_frame_event frame_events[SDE_CRTC_FRAME_EVENT_SIZE];
+24 −18
Original line number Diff line number Diff line
@@ -82,6 +82,11 @@
		((x) == SDE_RM_TOPOLOGY_DUALPIPE_3DMERGE) || \
		((x) == SDE_RM_TOPOLOGY_DUALPIPE_3DMERGE_DSC))

#define REQ_SEAMLESS_MODESET_LOCK(adj_mode, is_cmd_mode) \
		(msm_is_mode_seamless_dms(adj_mode) || \
		(msm_is_mode_seamless_dyn_clk(adj_mode) && \
		is_cmd_mode) || msm_is_mode_seamless_poms(adj_mode))

/**
 * enum sde_enc_rc_events - events for resource control state machine
 * @SDE_ENC_RC_EVENT_KICKOFF:
@@ -2878,9 +2883,12 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
	enum sde_intf_mode intf_mode;
	bool is_cmd_mode = false;
	int i = 0, ret;
	struct sde_crtc *sde_crtc;
	bool modeset_lock = false;

	if (!drm_enc) {
		SDE_ERROR("invalid encoder\n");
	if (!drm_enc || !drm_enc->crtc) {
		SDE_ERROR("invalid params %d %d\n",
			!drm_enc, drm_enc ? !drm_enc->crtc : -1);
		return;
	}

@@ -2901,25 +2909,16 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,

	SDE_EVT32(DRMID(drm_enc));

	/*
	 * cache the crtc in sde_enc on enable for duration of use case
	 * for correctly servicing asynchronous irq events and timers
	 */
	if (!drm_enc->crtc) {
		SDE_ERROR("invalid crtc\n");
		return;
	}
	sde_enc->crtc = drm_enc->crtc;
	sde_crtc = to_sde_crtc(sde_enc->crtc);

	list_for_each_entry(conn_iter, connector_list, head)
		if (conn_iter->encoder == drm_enc)
			conn = conn_iter;

	if (!conn) {
		SDE_ERROR_ENC(sde_enc, "failed to find attached connector\n");
		return;
	} else if (!conn->state) {
		SDE_ERROR_ENC(sde_enc, "invalid connector state\n");
	if (!conn || !conn->state) {
		SDE_ERROR_ENC(sde_enc, "invalid connector %d %d\n",
			!conn, conn ? !conn->state : -1);
		return;
	}

@@ -2930,6 +2929,10 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,

	sde_crtc_set_compression_ratio(sde_enc->mode_info, sde_enc->crtc);

	modeset_lock = REQ_SEAMLESS_MODESET_LOCK(adj_mode,
					is_cmd_mode);
	if (modeset_lock)
		mutex_lock(&sde_crtc->vblank_modeset_ctrl_lock);
	/* release resources before seamless mode change */
	if (msm_is_mode_seamless_dms(adj_mode) ||
			(msm_is_mode_seamless_dyn_clk(adj_mode) &&
@@ -2941,7 +2944,7 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
			SDE_ERROR_ENC(sde_enc,
					"sde resource control failed: %d\n",
					ret);
			return;
			goto exit;
		}

		/*
@@ -2961,7 +2964,7 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
	if (ret) {
		SDE_ERROR_ENC(sde_enc,
				"failed to reserve hw resources, %d\n", ret);
		return;
		goto exit;
	}

	sde_rm_init_hw_iter(&pp_iter, drm_enc->base.id, SDE_HW_BLK_PINGPONG);
@@ -3017,7 +3020,7 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
			if (!sde_enc->hw_pp[i] && sde_enc->topology.num_intf) {
				SDE_ERROR_ENC(sde_enc,
				    "invalid pingpong block for the encoder\n");
				return;
				goto exit;
			}
			phys->hw_pp = sde_enc->hw_pp[i];
			phys->connector = conn->state->connector;
@@ -3035,6 +3038,9 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
	else if (msm_is_mode_seamless_poms(adj_mode))
		_sde_encoder_modeset_helper_locked(drm_enc,
						SDE_ENC_RC_EVENT_POST_MODESET);
exit:
	if (modeset_lock)
		mutex_unlock(&sde_crtc->vblank_modeset_ctrl_lock);
}

void sde_encoder_control_te(struct drm_encoder *drm_enc, bool enable)