On Wed, Aug 12, 2015 at 04:37:28PM +0200, Thierry Reding wrote:
From: Thierry Reding treding@nvidia.com
This function can be used to duplicate an atomic state object. This is useful for example to implement suspend/resume, where the state before suspend can be saved and restored upon resume.
v2: move locking to caller, be more explicit about prerequisites
Signed-off-by: Thierry Reding treding@nvidia.com
drivers/gpu/drm/drm_atomic_helper.c | 80 +++++++++++++++++++++++++++++++++++++ include/drm/drm_atomic_helper.h | 2 + 2 files changed, 82 insertions(+)
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index fd06595c2ee5..1f84df3b0a5d 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -2358,6 +2358,86 @@ drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector) EXPORT_SYMBOL(drm_atomic_helper_connector_duplicate_state);
/**
- drm_atomic_helper_duplicate_state - duplicate an atomic state object
- @dev: DRM device
- Makes a copy of the current atomic state by looping over all objects and
- duplicating their respective states. This is used for example by suspend/
- resume support code to save the state prior to suspend such that it can
- be restored upon resume.
- Note that this treats atomic state as persistent between save and restore.
- Drivers must make sure that this is guaranteed.
s/guaranteed/is possible and won't result in confusion/ maybe?
- Calls to this function must be guarded by drm_modeset_lock_all() and
- drm_modeset_unlock_all().
If you pass in the acquire ctx explicitly this isn't strictly true since you're using the get_*_state functions, which might return -EDEADLK. So maybe instead:
"Note that if callers haven't already acquired all modeset locks this might return -EDEADLK, which must be handled by the caller using rm_modeset_backoff()."
- Returns:
- A pointer to the copy of the atomic state object on success or an
- ERR_PTR()-encoded error code on failure.
- */
+struct drm_atomic_state * +drm_atomic_helper_duplicate_state(struct drm_device *dev) +{
- struct drm_atomic_state *state;
- struct drm_connector *conn;
- struct drm_plane *plane;
- struct drm_crtc *crtc;
- int err = 0;
- if (WARN_ON(!dev->mode_config.acquire_ctx))
return ERR_PTR(-EINVAL);
- state = drm_atomic_state_alloc(dev);
- if (!state)
return ERR_PTR(-ENOMEM);
- state->acquire_ctx = dev->mode_config.acquire_ctx;
The hidden acquire_ctx was just a hack to avoid needing to redo _all_ driver entry points by adding a ctx parameter. I want to remove this long-term, so please don't spread it and instead just add a ctx parameter to this function.
Didn't spot anything else. -Daniel
- drm_for_each_crtc(crtc, dev) {
struct drm_crtc_state *crtc_state;
crtc_state = drm_atomic_get_crtc_state(state, crtc);
if (IS_ERR(crtc_state)) {
err = PTR_ERR(crtc_state);
goto free;
}
- }
- drm_for_each_plane(plane, dev) {
struct drm_plane_state *plane_state;
plane_state = drm_atomic_get_plane_state(state, plane);
if (IS_ERR(plane_state)) {
err = PTR_ERR(plane_state);
goto free;
}
- }
- drm_for_each_connector(conn, dev) {
struct drm_connector_state *conn_state;
conn_state = drm_atomic_get_connector_state(state, conn);
if (IS_ERR(conn_state)) {
err = PTR_ERR(conn_state);
goto free;
}
- }
- /* clear the acquire context so that it isn't accidentally reused */
- state->acquire_ctx = NULL;
+free:
- if (err < 0) {
drm_atomic_state_free(state);
state = ERR_PTR(err);
- }
- return state;
+} +EXPORT_SYMBOL(drm_atomic_helper_duplicate_state);
+/**
- __drm_atomic_helper_connector_destroy_state - release connector state
- @connector: connector object
- @state: connector state object to release
diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h index 4ffe9dca07c4..5d27612997ce 100644 --- a/include/drm/drm_atomic_helper.h +++ b/include/drm/drm_atomic_helper.h @@ -118,6 +118,8 @@ __drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector, struct drm_connector_state *state); struct drm_connector_state * drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector); +struct drm_atomic_state * +drm_atomic_helper_duplicate_state(struct drm_device *dev); void __drm_atomic_helper_connector_destroy_state(struct drm_connector *connector, struct drm_connector_state *state); -- 2.4.5