Unverified Commit b99c2c95 authored by Maxime Ripard's avatar Maxime Ripard
Browse files

drm: Introduce a drm_crtc_commit_wait helper



There's currently four users of the same logic to wait for a commit to
be flipped: three for the CRTCs, connectors and planes in
drm_atomic_helper_wait_for_dependencies, and one in vc4.

Let's consolidate this a bit to avoid any code duplication.

Suggested-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Reviewed-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: default avatarMaxime Ripard <maxime@cerno.tech>
Link: https://patchwork.freedesktop.org/patch/msgid/20210111084401.117152-1-maxime@cerno.tech
parent d1a73c64
Loading
Loading
Loading
Loading
+39 −0
Original line number Diff line number Diff line
@@ -52,6 +52,45 @@ void __drm_crtc_commit_free(struct kref *kref)
}
EXPORT_SYMBOL(__drm_crtc_commit_free);

/**
 * drm_crtc_commit_wait - Waits for a commit to complete
 * @commit: &drm_crtc_commit to wait for
 *
 * Waits for a given &drm_crtc_commit to be programmed into the
 * hardware and flipped to.
 *
 * Returns:
 *
 * 0 on success, a negative error code otherwise.
 */
int drm_crtc_commit_wait(struct drm_crtc_commit *commit)
{
	unsigned long timeout = 10 * HZ;
	int ret;

	if (!commit)
		return 0;

	ret = wait_for_completion_timeout(&commit->hw_done, timeout);
	if (!ret) {
		DRM_ERROR("hw_done timed out\n");
		return -ETIMEDOUT;
	}

	/*
	 * Currently no support for overwriting flips, hence
	 * stall for previous one to execute completely.
	 */
	ret = wait_for_completion_timeout(&commit->flip_done, timeout);
	if (!ret) {
		DRM_ERROR("flip_done timed out\n");
		return -ETIMEDOUT;
	}

	return 0;
}
EXPORT_SYMBOL(drm_crtc_commit_wait);

/**
 * drm_atomic_state_default_release -
 * release memory initialized by drm_atomic_state_init
+9 −52
Original line number Diff line number Diff line
@@ -2202,70 +2202,27 @@ void drm_atomic_helper_wait_for_dependencies(struct drm_atomic_state *old_state)
	struct drm_plane_state *old_plane_state;
	struct drm_connector *conn;
	struct drm_connector_state *old_conn_state;
	struct drm_crtc_commit *commit;
	int i;
	long ret;

	for_each_old_crtc_in_state(old_state, crtc, old_crtc_state, i) {
		commit = old_crtc_state->commit;

		if (!commit)
			continue;

		ret = wait_for_completion_timeout(&commit->hw_done,
						  10*HZ);
		if (ret == 0)
			DRM_ERROR("[CRTC:%d:%s] hw_done timed out\n",
				  crtc->base.id, crtc->name);

		/* Currently no support for overwriting flips, hence
		 * stall for previous one to execute completely. */
		ret = wait_for_completion_timeout(&commit->flip_done,
						  10*HZ);
		if (ret == 0)
			DRM_ERROR("[CRTC:%d:%s] flip_done timed out\n",
		ret = drm_crtc_commit_wait(old_crtc_state->commit);
		if (ret)
			DRM_ERROR("[CRTC:%d:%s] commit wait timed out\n",
				  crtc->base.id, crtc->name);
	}

	for_each_old_connector_in_state(old_state, conn, old_conn_state, i) {
		commit = old_conn_state->commit;

		if (!commit)
			continue;

		ret = wait_for_completion_timeout(&commit->hw_done,
						  10*HZ);
		if (ret == 0)
			DRM_ERROR("[CONNECTOR:%d:%s] hw_done timed out\n",
				  conn->base.id, conn->name);

		/* Currently no support for overwriting flips, hence
		 * stall for previous one to execute completely. */
		ret = wait_for_completion_timeout(&commit->flip_done,
						  10*HZ);
		if (ret == 0)
			DRM_ERROR("[CONNECTOR:%d:%s] flip_done timed out\n",
		ret = drm_crtc_commit_wait(old_conn_state->commit);
		if (ret)
			DRM_ERROR("[CONNECTOR:%d:%s] commit wait timed out\n",
				  conn->base.id, conn->name);
	}

	for_each_old_plane_in_state(old_state, plane, old_plane_state, i) {
		commit = old_plane_state->commit;

		if (!commit)
			continue;

		ret = wait_for_completion_timeout(&commit->hw_done,
						  10*HZ);
		if (ret == 0)
			DRM_ERROR("[PLANE:%d:%s] hw_done timed out\n",
				  plane->base.id, plane->name);

		/* Currently no support for overwriting flips, hence
		 * stall for previous one to execute completely. */
		ret = wait_for_completion_timeout(&commit->flip_done,
						  10*HZ);
		if (ret == 0)
			DRM_ERROR("[PLANE:%d:%s] flip_done timed out\n",
		ret = drm_crtc_commit_wait(old_plane_state->commit);
		if (ret)
			DRM_ERROR("[PLANE:%d:%s] commit wait timed out\n",
				  plane->base.id, plane->name);
	}
}
+4 −13
Original line number Diff line number Diff line
@@ -363,9 +363,8 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state)
	for_each_old_crtc_in_state(state, crtc, old_crtc_state, i) {
		struct vc4_crtc_state *vc4_crtc_state =
			to_vc4_crtc_state(old_crtc_state);
		struct drm_crtc_commit *commit;
		unsigned int channel = vc4_crtc_state->assigned_channel;
		unsigned long done;
		int ret;

		if (channel == VC4_HVS_CHANNEL_DISABLED)
			continue;
@@ -373,17 +372,9 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state)
		if (!old_hvs_state->fifo_state[channel].in_use)
			continue;

		commit = old_hvs_state->fifo_state[i].pending_commit;
		if (!commit)
			continue;

		done = wait_for_completion_timeout(&commit->hw_done, 10 * HZ);
		if (!done)
			drm_err(dev, "Timed out waiting for hw_done\n");

		done = wait_for_completion_timeout(&commit->flip_done, 10 * HZ);
		if (!done)
			drm_err(dev, "Timed out waiting for flip_done\n");
		ret = drm_crtc_commit_wait(old_hvs_state->fifo_state[i].pending_commit);
		if (ret)
			drm_err(dev, "Timed out waiting for commit\n");
	}

	drm_atomic_helper_commit_modeset_disables(dev, state);
+4 −0
Original line number Diff line number Diff line
@@ -66,6 +66,8 @@
 *
 * For an implementation of how to use this look at
 * drm_atomic_helper_setup_commit() from the atomic helper library.
 *
 * See also drm_crtc_commit_wait().
 */
struct drm_crtc_commit {
	/**
@@ -436,6 +438,8 @@ static inline void drm_crtc_commit_put(struct drm_crtc_commit *commit)
	kref_put(&commit->ref, __drm_crtc_commit_free);
}

int drm_crtc_commit_wait(struct drm_crtc_commit *commit);

struct drm_atomic_state * __must_check
drm_atomic_state_alloc(struct drm_device *dev);
void drm_atomic_state_clear(struct drm_atomic_state *state);