drm: Introduce a drm_crtc_commit_wait helper
authorMaxime Ripard <maxime@cerno.tech>
Mon, 11 Jan 2021 08:44:01 +0000 (09:44 +0100)
committerMaxime Ripard <maxime@cerno.tech>
Thu, 21 Jan 2021 11:11:04 +0000 (12:11 +0100)
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: Daniel Vetter <daniel.vetter@ffwll.ch>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Link: https://patchwork.freedesktop.org/patch/msgid/20210111084401.117152-1-maxime@cerno.tech
drivers/gpu/drm/drm_atomic.c
drivers/gpu/drm/drm_atomic_helper.c
drivers/gpu/drm/vc4/vc4_kms.c
include/drm/drm_atomic.h

index dda60051854b121b6eec6968fc31a73c9b8a0392..b1efa9322be2f0bb364bb01cc1c4b7e526586e15 100644 (file)
@@ -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
index a84dc427cf82301ab783a787e7b0caede18935ea..9fa3f97223a1584467419d165dea8ee402bbc423 100644 (file)
@@ -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);
        }
 }
index f09254c2497d5e0b46431ce68587b832db8092fc..bb5529a7a9c28bea238222189598579dea865597 100644 (file)
@@ -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);
index ce7023e9115d789dd2ddc4f951a33531d6f2175d..ac5a28eff2c8684b56a300d29de8f4f1aa08f153 100644 (file)
@@ -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);