Add for_each_(old)(new)_(plane,connector,crtc)_in_state iterators to
replace the old for_each_xxx_in_state ones. This is useful for >1 flip
depth and getting rid of all xxx->state dereferences.

This requires extra fixups done when committing a state after
duplicating, which in general isn't valid but is used by suspend/resume.
To handle these, introduce drm_atomic_helper_commit_duplicated_state
which performs those fixups before checking & committing the state.

Changes since v1:
- Remove nonblock parameter for commit_duplicated_state.

Signed-off-by: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
---
 drivers/gpu/drm/drm_atomic.c         |  6 +++
 drivers/gpu/drm/drm_atomic_helper.c  | 47 +++++++++++++++++++--
 drivers/gpu/drm/i915/intel_display.c | 11 ++---
 include/drm/drm_atomic.h             | 81 ++++++++++++++++++++++++++++++++++--
 include/drm/drm_atomic_helper.h      |  2 +
 5 files changed, 136 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 57e0a6e96f6d..e80663154858 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -279,6 +279,8 @@ drm_atomic_get_crtc_state(struct drm_atomic_state *state,
                return ERR_PTR(-ENOMEM);

        state->crtcs[index].state = crtc_state;
+       state->crtcs[index].old_state = crtc->state;
+       state->crtcs[index].new_state = crtc_state;
        state->crtcs[index].ptr = crtc;
        crtc_state->state = state;

@@ -666,6 +668,8 @@ drm_atomic_get_plane_state(struct drm_atomic_state *state,

        state->planes[index].state = plane_state;
        state->planes[index].ptr = plane;
+       state->planes[index].old_state = plane->state;
+       state->planes[index].new_state = plane_state;
        plane_state->state = state;

        DRM_DEBUG_ATOMIC("Added [PLANE:%d:%s] %p state to %p\n",
@@ -993,6 +997,8 @@ drm_atomic_get_connector_state(struct drm_atomic_state 
*state,

        drm_connector_reference(connector);
        state->connectors[index].state = connector_state;
+       state->connectors[index].old_state = connector->state;
+       state->connectors[index].new_state = connector_state;
        state->connectors[index].ptr = connector;
        connector_state->state = state;

diff --git a/drivers/gpu/drm/drm_atomic_helper.c 
b/drivers/gpu/drm/drm_atomic_helper.c
index 50077961228a..0e11bef26999 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -2491,7 +2491,7 @@ EXPORT_SYMBOL(drm_atomic_helper_disable_all);
  *
  * See also:
  * drm_atomic_helper_duplicate_state(), drm_atomic_helper_disable_all(),
- * drm_atomic_helper_resume()
+ * drm_atomic_helper_resume(), drm_atomic_helper_commit_duplicated_state()
  */
 struct drm_atomic_state *drm_atomic_helper_suspend(struct drm_device *dev)
 {
@@ -2532,6 +2532,47 @@ struct drm_atomic_state 
*drm_atomic_helper_suspend(struct drm_device *dev)
 EXPORT_SYMBOL(drm_atomic_helper_suspend);

 /**
+ * drm_atomic_helper_commit_duplicated_state - commit duplicated state
+ * @state: duplicated atomic state to commit
+ * @ctx: pointer to acquire_ctx to use for commit.
+ *
+ * The state returned by drm_atomic_helper_duplicate_state() and
+ * drm_atomic_helper_suspend() is partially invalid, and needs to
+ * be fixed up before commit.
+ *
+ * Returns:
+ * 0 on success or a negative error code on failure.
+ *
+ * See also:
+ * drm_atomic_helper_suspend()
+ */
+int drm_atomic_helper_commit_duplicated_state(struct drm_atomic_state *state,
+                                             struct drm_modeset_acquire_ctx 
*ctx)
+{
+       int i;
+       struct drm_plane *plane;
+       struct drm_plane_state *plane_state;
+       struct drm_connector *connector;
+       struct drm_connector_state *conn_state;
+       struct drm_crtc *crtc;
+       struct drm_crtc_state *crtc_state;
+
+       state->acquire_ctx = ctx;
+
+       for_each_new_plane_in_state(state, plane, plane_state, i)
+               state->planes[i].old_state = plane->state;
+
+       for_each_new_crtc_in_state(state, crtc, crtc_state, i)
+               state->crtcs[i].old_state = crtc->state;
+
+       for_each_new_connector_in_state(state, connector, conn_state, i)
+               state->connectors[i].old_state = connector->state;
+
+       return drm_atomic_commit(state);
+}
+EXPORT_SYMBOL(drm_atomic_helper_commit_duplicated_state);
+
+/**
  * drm_atomic_helper_resume - subsystem-level resume helper
  * @dev: DRM device
  * @state: atomic state to resume to
@@ -2554,9 +2595,9 @@ int drm_atomic_helper_resume(struct drm_device *dev,
        int err;

        drm_mode_config_reset(dev);
+
        drm_modeset_lock_all(dev);
-       state->acquire_ctx = config->acquire_ctx;
-       err = drm_atomic_commit(state);
+       err = drm_atomic_helper_commit_duplicated_state(state, 
config->acquire_ctx);
        drm_modeset_unlock_all(dev);

        return err;
diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index 2ebb8b833395..b2324f3b5ef1 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3496,7 +3496,8 @@ static void intel_update_primary_planes(struct drm_device 
*dev)

 static int
 __intel_display_resume(struct drm_device *dev,
-                      struct drm_atomic_state *state)
+                      struct drm_atomic_state *state,
+                      struct drm_modeset_acquire_ctx *ctx)
 {
        struct drm_crtc_state *crtc_state;
        struct drm_crtc *crtc;
@@ -3520,7 +3521,7 @@ __intel_display_resume(struct drm_device *dev,
        /* ignore any reset values/BIOS leftovers in the WM registers */
        to_intel_atomic_state(state)->skip_intermediate_wm = true;

-       ret = drm_atomic_commit(state);
+       ret = drm_atomic_helper_commit_duplicated_state(state, ctx);

        WARN_ON(ret == -EDEADLK);
        return ret;
@@ -3614,7 +3615,7 @@ void intel_finish_reset(struct drm_i915_private *dev_priv)
                         */
                        intel_update_primary_planes(dev);
                } else {
-                       ret = __intel_display_resume(dev, state);
+                       ret = __intel_display_resume(dev, state, ctx);
                        if (ret)
                                DRM_ERROR("Restoring old state failed with 
%i\n", ret);
                }
@@ -3634,7 +3635,7 @@ void intel_finish_reset(struct drm_i915_private *dev_priv)
                        dev_priv->display.hpd_irq_setup(dev_priv);
                spin_unlock_irq(&dev_priv->irq_lock);

-               ret = __intel_display_resume(dev, state);
+               ret = __intel_display_resume(dev, state, ctx);
                if (ret)
                        DRM_ERROR("Restoring old state failed with %i\n", ret);

@@ -17061,7 +17062,7 @@ void intel_display_resume(struct drm_device *dev)
        }

        if (!ret)
-               ret = __intel_display_resume(dev, state);
+               ret = __intel_display_resume(dev, state, &ctx);

        drm_modeset_drop_locks(&ctx);
        drm_modeset_acquire_fini(&ctx);
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index 331bb100b718..e527684dd394 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -137,18 +137,18 @@ struct drm_crtc_commit {

 struct __drm_planes_state {
        struct drm_plane *ptr;
-       struct drm_plane_state *state;
+       struct drm_plane_state *state, *old_state, *new_state;
 };

 struct __drm_crtcs_state {
        struct drm_crtc *ptr;
-       struct drm_crtc_state *state;
+       struct drm_crtc_state *state, *old_state, *new_state;
        struct drm_crtc_commit *commit;
 };

 struct __drm_connnectors_state {
        struct drm_connector *ptr;
-       struct drm_connector_state *state;
+       struct drm_connector_state *state, *old_state, *new_state;
 };

 /**
@@ -381,6 +381,31 @@ int drm_atomic_debugfs_init(struct drm_minor *minor);
             (__i)++)                                                   \
                for_each_if (connector)

+#define for_each_oldnew_connector_in_state(__state, connector, 
old_connector_state, new_connector_state, __i) \
+       for ((__i) = 0;                                                         
\
+            (__i) < (__state)->num_connector &&                                
\
+            ((connector) = (__state)->connectors[__i].ptr,                     
\
+            (old_connector_state) = (__state)->connectors[__i].old_state,      
\
+            (new_connector_state) = (__state)->connectors[__i].new_state, 1);  
\
+            (__i)++)                                                   \
+               for_each_if (connector)
+
+#define for_each_old_connector_in_state(__state, connector, 
old_connector_state, __i) \
+       for ((__i) = 0;                                                         
\
+            (__i) < (__state)->num_connector &&                                
\
+            ((connector) = (__state)->connectors[__i].ptr,                     
\
+            (old_connector_state) = (__state)->connectors[__i].old_state, 1);  
\
+            (__i)++)                                                   \
+               for_each_if (connector)
+
+#define for_each_new_connector_in_state(__state, connector, 
new_connector_state, __i) \
+       for ((__i) = 0;                                                         
\
+            (__i) < (__state)->num_connector &&                                
\
+            ((connector) = (__state)->connectors[__i].ptr,                     
\
+            (new_connector_state) = (__state)->connectors[__i].new_state, 1);  
\
+            (__i)++)                                                   \
+               for_each_if (connector)
+
 #define for_each_crtc_in_state(__state, crtc, crtc_state, __i) \
        for ((__i) = 0;                                         \
             (__i) < (__state)->dev->mode_config.num_crtc &&    \
@@ -389,6 +414,31 @@ int drm_atomic_debugfs_init(struct drm_minor *minor);
             (__i)++)                                           \
                for_each_if (crtc_state)

+#define for_each_oldnew_crtc_in_state(__state, crtc, old_crtc_state, 
new_crtc_state, __i) \
+       for ((__i) = 0;                                                 \
+            (__i) < (__state)->dev->mode_config.num_crtc &&            \
+            ((crtc) = (__state)->crtcs[__i].ptr,                       \
+            (old_crtc_state) = (__state)->crtcs[__i].old_state,        \
+            (new_crtc_state) = (__state)->crtcs[__i].new_state, 1);    \
+            (__i)++)                                                   \
+               for_each_if (crtc)
+
+#define for_each_old_crtc_in_state(__state, crtc, old_crtc_state, __i) \
+       for ((__i) = 0;                                                 \
+            (__i) < (__state)->dev->mode_config.num_crtc &&            \
+            ((crtc) = (__state)->crtcs[__i].ptr,                       \
+            (old_crtc_state) = (__state)->crtcs[__i].old_state, 1);    \
+            (__i)++)                                                   \
+               for_each_if (crtc)
+
+#define for_each_new_crtc_in_state(__state, crtc, new_crtc_state, __i) \
+       for ((__i) = 0;                                                 \
+            (__i) < (__state)->dev->mode_config.num_crtc &&            \
+            ((crtc) = (__state)->crtcs[__i].ptr,                       \
+            (new_crtc_state) = (__state)->crtcs[__i].new_state, 1);    \
+            (__i)++)                                                   \
+               for_each_if (crtc)
+
 #define for_each_plane_in_state(__state, plane, plane_state, __i)              
\
        for ((__i) = 0;                                                 \
             (__i) < (__state)->dev->mode_config.num_total_plane &&     \
@@ -397,6 +447,31 @@ int drm_atomic_debugfs_init(struct drm_minor *minor);
             (__i)++)                                                   \
                for_each_if (plane_state)

+#define for_each_oldnew_plane_in_state(__state, plane, old_plane_state, 
new_plane_state, __i) \
+       for ((__i) = 0;                                                 \
+            (__i) < (__state)->dev->mode_config.num_total_plane &&     \
+            ((plane) = (__state)->planes[__i].ptr,                     \
+            (old_plane_state) = (__state)->planes[__i].old_state,      \
+            (new_plane_state) = (__state)->planes[__i].new_state, 1);  \
+            (__i)++)                                                   \
+               for_each_if (plane)
+
+#define for_each_old_plane_in_state(__state, plane, old_plane_state, __i) \
+       for ((__i) = 0;                                                 \
+            (__i) < (__state)->dev->mode_config.num_total_plane &&     \
+            ((plane) = (__state)->planes[__i].ptr,                     \
+            (old_plane_state) = (__state)->planes[__i].old_state, 1);  \
+            (__i)++)                                                   \
+               for_each_if (plane)
+
+#define for_each_new_plane_in_state(__state, plane, new_plane_state, __i) \
+       for ((__i) = 0;                                                 \
+            (__i) < (__state)->dev->mode_config.num_total_plane &&     \
+            ((plane) = (__state)->planes[__i].ptr,                     \
+            (new_plane_state) = (__state)->planes[__i].new_state, 1);  \
+            (__i)++)                                                   \
+               for_each_if (plane)
+
 /**
  * drm_atomic_crtc_needs_modeset - compute combined modeset need
  * @state: &drm_crtc_state for the CRTC
diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
index 7ff92b09fd9c..f5723831a191 100644
--- a/include/drm/drm_atomic_helper.h
+++ b/include/drm/drm_atomic_helper.h
@@ -108,6 +108,8 @@ int __drm_atomic_helper_set_config(struct drm_mode_set *set,
 int drm_atomic_helper_disable_all(struct drm_device *dev,
                                  struct drm_modeset_acquire_ctx *ctx);
 struct drm_atomic_state *drm_atomic_helper_suspend(struct drm_device *dev);
+int drm_atomic_helper_commit_duplicated_state(struct drm_atomic_state *state,
+                                             struct drm_modeset_acquire_ctx 
*ctx);
 int drm_atomic_helper_resume(struct drm_device *dev,
                             struct drm_atomic_state *state);

-- 
2.7.4

Reply via email to