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

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

drm/msm/sde: signal pageflip event after frame kickoff



sde_crtc module updates the event status before frame
kickoff and triggers the pageflip event on vsync callback.
That may lead to trigger pageflip event before actual
frame kickoff if there is pending vsync process. This
change updates the crtc event status after frame kickoff
and triggers the pageflip event in wait_for_commit done
to avoid race condition.

Change-Id: Ibfbef206495cbd66e2c401afaf4ba056439cf738
Signed-off-by: default avatarDhaval Patel <pdhaval@codeaurora.org>
parent a2514510
Loading
Loading
Loading
Loading
+28 −43
Original line number Diff line number Diff line
@@ -2186,7 +2186,7 @@ void sde_crtc_prepare_commit(struct drm_crtc *crtc,
}

/**
 *  _sde_crtc_complete_flip - signal pending page_flip events
 *  sde_crtc_complete_flip - signal pending page_flip events
 * Any pending vblank events are added to the vblank_event_list
 * so that the next vblank interrupt shall signal them.
 * However PAGE_FLIP events are not handled through the vblank_event_list.
@@ -2196,7 +2196,7 @@ void sde_crtc_prepare_commit(struct drm_crtc *crtc,
 * @crtc: Pointer to drm crtc structure
 * @file: Pointer to drm file
 */
static void _sde_crtc_complete_flip(struct drm_crtc *crtc,
void sde_crtc_complete_flip(struct drm_crtc *crtc,
		struct drm_file *file)
{
	struct sde_crtc *sde_crtc = to_sde_crtc(crtc);
@@ -2206,8 +2206,11 @@ static void _sde_crtc_complete_flip(struct drm_crtc *crtc,

	spin_lock_irqsave(&dev->event_lock, flags);
	event = sde_crtc->event;
	if (event) {
		/* if regular vblank case (!file) or if cancel-flip from
	if (!event)
		goto end;

	/*
	 * if regular vblank case (!file) or if cancel-flip from
	 * preclose on file that requested flip, then send the
	 * event:
	 */
@@ -2218,7 +2221,8 @@ static void _sde_crtc_complete_flip(struct drm_crtc *crtc,
		SDE_EVT32_VERBOSE(DRMID(crtc));
		drm_crtc_send_vblank_event(crtc, event);
	}
	}

end:
	spin_unlock_irqrestore(&dev->event_lock, flags);
}

@@ -2252,7 +2256,6 @@ static void sde_crtc_vblank_cb(void *data)
	sde_crtc->vblank_last_cb_time = ktime_get();
	sysfs_notify_dirent(sde_crtc->vsync_event_sf);

	_sde_crtc_complete_flip(crtc, NULL);
	drm_crtc_handle_vblank(crtc);
	DRM_DEBUG_VBL("crtc%d\n", crtc->base.id);
	SDE_EVT32_VERBOSE(DRMID(crtc));
@@ -3054,7 +3057,6 @@ static void sde_crtc_atomic_begin(struct drm_crtc *crtc,
	struct sde_crtc *sde_crtc;
	struct drm_encoder *encoder;
	struct drm_device *dev;
	unsigned long flags;
	struct sde_kms *sde_kms;

	if (!crtc) {
@@ -3088,14 +3090,6 @@ static void sde_crtc_atomic_begin(struct drm_crtc *crtc,
		_sde_crtc_setup_lm_bounds(crtc, crtc->state);
	}

	if (sde_crtc->event) {
		WARN_ON(sde_crtc->event);
	} else {
		spin_lock_irqsave(&dev->event_lock, flags);
		sde_crtc->event = crtc->state->event;
		spin_unlock_irqrestore(&dev->event_lock, flags);
	}

	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
		if (encoder->crtc != crtc)
			continue;
@@ -3148,7 +3142,6 @@ static void sde_crtc_atomic_flush(struct drm_crtc *crtc,
	struct drm_plane *plane;
	struct msm_drm_private *priv;
	struct msm_drm_thread *event_thread;
	unsigned long flags;
	struct sde_crtc_state *cstate;
	struct sde_kms *sde_kms;
	int idle_time = 0;
@@ -3190,14 +3183,6 @@ static void sde_crtc_atomic_flush(struct drm_crtc *crtc,
	event_thread = &priv->event_thread[crtc->index];
	idle_time = sde_crtc_get_property(cstate, CRTC_PROP_IDLE_TIMEOUT);

	if (sde_crtc->event) {
		SDE_DEBUG("already received sde_crtc->event\n");
	} else {
		spin_lock_irqsave(&dev->event_lock, flags);
		sde_crtc->event = crtc->state->event;
		spin_unlock_irqrestore(&dev->event_lock, flags);
	}

	/*
	 * If no mixers has been allocated in sde_crtc_atomic_check(),
	 * it means we are trying to flush a CRTC whose state is disabled:
@@ -3638,6 +3623,7 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc,
	struct sde_kms *sde_kms;
	struct sde_crtc_state *cstate;
	bool is_error, reset_req, recovery_events;
	unsigned long flags;

	if (!crtc) {
		SDE_ERROR("invalid argument\n");
@@ -3738,6 +3724,15 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc,
		sde_encoder_kickoff(encoder, false);
	}

	/* store the event after frame trigger */
	if (sde_crtc->event) {
		WARN_ON(sde_crtc->event);
	} else {
		spin_lock_irqsave(&dev->event_lock, flags);
		sde_crtc->event = crtc->state->event;
		spin_unlock_irqrestore(&dev->event_lock, flags);
	}

	SDE_ATRACE_END("crtc_commit");
}

@@ -4907,16 +4902,6 @@ int sde_crtc_vblank(struct drm_crtc *crtc, bool en)
	return 0;
}

void sde_crtc_cancel_pending_flip(struct drm_crtc *crtc, struct drm_file *file)
{
	struct sde_crtc *sde_crtc = to_sde_crtc(crtc);

	SDE_DEBUG("%s: cancel: %pK\n", sde_crtc->name, file);
	_sde_crtc_complete_flip(crtc, file);
}



/**
 * sde_crtc_install_properties - install all drm properties for crtc
 * @crtc: Pointer to drm crtc structure
+2 −2
Original line number Diff line number Diff line
@@ -526,11 +526,11 @@ struct drm_crtc *sde_crtc_init(struct drm_device *dev, struct drm_plane *plane);
int sde_crtc_post_init(struct drm_device *dev, struct drm_crtc *crtc);

/**
 * sde_crtc_cancel_pending_flip - complete flip for clients on lastclose
 * sde_crtc_complete_flip - complete flip for clients
 * @crtc: Pointer to drm crtc object
 * @file: client to cancel's file handle
 */
void sde_crtc_cancel_pending_flip(struct drm_crtc *crtc, struct drm_file *file);
void sde_crtc_complete_flip(struct drm_crtc *crtc, struct drm_file *file);

/**
 * sde_crtc_register_custom_event - api for enabling/disabling crtc event
+4 −1
Original line number Diff line number Diff line
@@ -1096,6 +1096,8 @@ static void sde_kms_wait_for_commit_done(struct msm_kms *kms,
			SDE_ERROR("wait for commit done returned %d\n", ret);
			break;
		}

		sde_crtc_complete_flip(crtc, NULL);
	}
}

@@ -1928,8 +1930,9 @@ static void sde_kms_preclose(struct msm_kms *kms, struct drm_file *file)
	struct drm_modeset_acquire_ctx ctx;
	int ret = 0;

	/* cancel pending flip event */
	for (i = 0; i < priv->num_crtcs; i++)
		sde_crtc_cancel_pending_flip(priv->crtcs[i], file);
		sde_crtc_complete_flip(priv->crtcs[i], file);

	drm_modeset_acquire_init(&ctx, 0);
retry: