Only allow updates on colorops that are part of an active pipeline.
Check if a colorop in a new state belongs to a color pipeline which was
set as a plane color_pipeline property and therefore is an active color
pipeline. If not, reject the atomic state. Performing this check later
in drm_atomic_check_only() to remove the ordering dependency that would
exist if done at the time of colorop property setting.

Suggested-by: Chaitanya Kumar Borah <[email protected]>
Signed-off-by: Melissa Wen <[email protected]>
---
 drivers/gpu/drm/drm_atomic.c | 38 ++++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 28831a548b0c..659cf56150e5 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -812,6 +812,33 @@ static int drm_atomic_plane_check(const struct 
drm_plane_state *old_plane_state,
        return 0;
 }
 
+/**
+ * drm_atomic_colorop_check - check new colorop state
+ * @new_colorop_state: new colorop state to check
+ *
+ * Ensure that the colorop in @new_colorop_state belongs to an active color
+ * pipeline, i.e. it's in the chain of colorops set to the color_pipeline
+ * property of a plane state.
+ *
+ * Returns: 0 on success, -EINVAL otherwise.
+ */
+static int drm_atomic_colorop_check(const struct drm_colorop_state 
*new_colorop_state)
+{
+       struct drm_colorop *colorop, *color_pipeline;
+       struct drm_plane_state *new_plane_state;
+
+       new_plane_state = 
drm_atomic_get_new_plane_state(new_colorop_state->state,
+                                                        
new_colorop_state->colorop->plane);
+       color_pipeline = new_plane_state ? new_plane_state->color_pipeline :
+                        
new_colorop_state->colorop->plane->state->color_pipeline;
+
+       for (colorop = color_pipeline; colorop; colorop = colorop->next)
+               if (colorop == new_colorop_state->colorop)
+                       return 0;
+
+       return -EINVAL;
+}
+
 static void drm_atomic_colorop_print_state(struct drm_printer *p,
                                           const struct drm_colorop_state 
*state)
 {
@@ -1665,6 +1692,8 @@ int drm_atomic_check_only(struct drm_atomic_commit *state)
        struct drm_plane *plane;
        struct drm_plane_state *old_plane_state;
        struct drm_plane_state *new_plane_state;
+       struct drm_colorop *colorop;
+       struct drm_colorop_state *new_colorop_state;
        struct drm_crtc *crtc;
        struct drm_crtc_state *old_crtc_state;
        struct drm_crtc_state *new_crtc_state;
@@ -1681,6 +1710,15 @@ int drm_atomic_check_only(struct drm_atomic_commit 
*state)
                        requested_crtc |= drm_crtc_mask(crtc);
        }
 
+       for_each_new_colorop_in_state(state, colorop, new_colorop_state, i) {
+               ret = drm_atomic_colorop_check(new_colorop_state);
+               if (ret) {
+                       drm_dbg_atomic(dev, "[COLOROP:%d:%d] is not part of an 
active color pipeline.\n",
+                                      colorop->base.id, colorop->type);
+                       return ret;
+               }
+       }
+
        for_each_oldnew_plane_in_state(state, plane, old_plane_state, 
new_plane_state, i) {
                ret = drm_atomic_plane_check(old_plane_state, new_plane_state);
                if (ret) {
-- 
2.53.0

Reply via email to