Commit 581e49fe authored by Maarten Lankhorst's avatar Maarten Lankhorst Committed by Daniel Vetter

drm/atomic: Add new iterators over all state, v3.

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.
Changes since v2:
- Use commit_duplicated_state for i915 load detection.
- Add WARN_ON(old_state != obj->state) before swapping.
Signed-off-by: default avatarMaarten Lankhorst <maarten.lankhorst@linux.intel.com>
Reviewed-by: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Link: http://patchwork.freedesktop.org/patch/msgid/1484559464-27107-2-git-send-email-maarten.lankhorst@linux.intel.com
parent 5b47d089
...@@ -275,6 +275,8 @@ drm_atomic_get_crtc_state(struct drm_atomic_state *state, ...@@ -275,6 +275,8 @@ drm_atomic_get_crtc_state(struct drm_atomic_state *state,
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
state->crtcs[index].state = crtc_state; 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; state->crtcs[index].ptr = crtc;
crtc_state->state = state; crtc_state->state = state;
...@@ -689,6 +691,8 @@ drm_atomic_get_plane_state(struct drm_atomic_state *state, ...@@ -689,6 +691,8 @@ drm_atomic_get_plane_state(struct drm_atomic_state *state,
state->planes[index].state = plane_state; state->planes[index].state = plane_state;
state->planes[index].ptr = plane; state->planes[index].ptr = plane;
state->planes[index].old_state = plane->state;
state->planes[index].new_state = plane_state;
plane_state->state = state; plane_state->state = state;
DRM_DEBUG_ATOMIC("Added [PLANE:%d:%s] %p state to %p\n", DRM_DEBUG_ATOMIC("Added [PLANE:%d:%s] %p state to %p\n",
...@@ -1028,6 +1032,8 @@ drm_atomic_get_connector_state(struct drm_atomic_state *state, ...@@ -1028,6 +1032,8 @@ drm_atomic_get_connector_state(struct drm_atomic_state *state,
drm_connector_reference(connector); drm_connector_reference(connector);
state->connectors[index].state = connector_state; 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; state->connectors[index].ptr = connector;
connector_state->state = state; connector_state->state = state;
......
...@@ -1977,11 +1977,11 @@ void drm_atomic_helper_swap_state(struct drm_atomic_state *state, ...@@ -1977,11 +1977,11 @@ void drm_atomic_helper_swap_state(struct drm_atomic_state *state,
int i; int i;
long ret; long ret;
struct drm_connector *connector; struct drm_connector *connector;
struct drm_connector_state *conn_state; struct drm_connector_state *conn_state, *old_conn_state;
struct drm_crtc *crtc; struct drm_crtc *crtc;
struct drm_crtc_state *crtc_state; struct drm_crtc_state *crtc_state, *old_crtc_state;
struct drm_plane *plane; struct drm_plane *plane;
struct drm_plane_state *plane_state; struct drm_plane_state *plane_state, *old_plane_state;
struct drm_crtc_commit *commit; struct drm_crtc_commit *commit;
if (stall) { if (stall) {
...@@ -2005,13 +2005,17 @@ void drm_atomic_helper_swap_state(struct drm_atomic_state *state, ...@@ -2005,13 +2005,17 @@ void drm_atomic_helper_swap_state(struct drm_atomic_state *state,
} }
} }
for_each_connector_in_state(state, connector, conn_state, i) { for_each_oldnew_connector_in_state(state, connector, old_conn_state, conn_state, i) {
WARN_ON(connector->state != old_conn_state);
connector->state->state = state; connector->state->state = state;
swap(state->connectors[i].state, connector->state); swap(state->connectors[i].state, connector->state);
connector->state->state = NULL; connector->state->state = NULL;
} }
for_each_crtc_in_state(state, crtc, crtc_state, i) { for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, crtc_state, i) {
WARN_ON(crtc->state != old_crtc_state);
crtc->state->state = state; crtc->state->state = state;
swap(state->crtcs[i].state, crtc->state); swap(state->crtcs[i].state, crtc->state);
crtc->state->state = NULL; crtc->state->state = NULL;
...@@ -2026,7 +2030,9 @@ void drm_atomic_helper_swap_state(struct drm_atomic_state *state, ...@@ -2026,7 +2030,9 @@ void drm_atomic_helper_swap_state(struct drm_atomic_state *state,
} }
} }
for_each_plane_in_state(state, plane, plane_state, i) { for_each_oldnew_plane_in_state(state, plane, old_plane_state, plane_state, i) {
WARN_ON(plane->state != old_plane_state);
plane->state->state = state; plane->state->state = state;
swap(state->planes[i].state, plane->state); swap(state->planes[i].state, plane->state);
plane->state->state = NULL; plane->state->state = NULL;
...@@ -2477,7 +2483,7 @@ EXPORT_SYMBOL(drm_atomic_helper_disable_all); ...@@ -2477,7 +2483,7 @@ EXPORT_SYMBOL(drm_atomic_helper_disable_all);
* *
* See also: * See also:
* drm_atomic_helper_duplicate_state(), drm_atomic_helper_disable_all(), * 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) struct drm_atomic_state *drm_atomic_helper_suspend(struct drm_device *dev)
{ {
...@@ -2517,6 +2523,47 @@ struct drm_atomic_state *drm_atomic_helper_suspend(struct drm_device *dev) ...@@ -2517,6 +2523,47 @@ struct drm_atomic_state *drm_atomic_helper_suspend(struct drm_device *dev)
} }
EXPORT_SYMBOL(drm_atomic_helper_suspend); 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 * drm_atomic_helper_resume - subsystem-level resume helper
* @dev: DRM device * @dev: DRM device
...@@ -2540,9 +2587,9 @@ int drm_atomic_helper_resume(struct drm_device *dev, ...@@ -2540,9 +2587,9 @@ int drm_atomic_helper_resume(struct drm_device *dev,
int err; int err;
drm_mode_config_reset(dev); drm_mode_config_reset(dev);
drm_modeset_lock_all(dev); drm_modeset_lock_all(dev);
state->acquire_ctx = config->acquire_ctx; err = drm_atomic_helper_commit_duplicated_state(state, config->acquire_ctx);
err = drm_atomic_commit(state);
drm_modeset_unlock_all(dev); drm_modeset_unlock_all(dev);
return err; return err;
......
...@@ -3481,7 +3481,8 @@ static void intel_update_primary_planes(struct drm_device *dev) ...@@ -3481,7 +3481,8 @@ static void intel_update_primary_planes(struct drm_device *dev)
static int static int
__intel_display_resume(struct drm_device *dev, __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_state *crtc_state;
struct drm_crtc *crtc; struct drm_crtc *crtc;
...@@ -3505,7 +3506,7 @@ __intel_display_resume(struct drm_device *dev, ...@@ -3505,7 +3506,7 @@ __intel_display_resume(struct drm_device *dev,
/* ignore any reset values/BIOS leftovers in the WM registers */ /* ignore any reset values/BIOS leftovers in the WM registers */
to_intel_atomic_state(state)->skip_intermediate_wm = true; 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); WARN_ON(ret == -EDEADLK);
return ret; return ret;
...@@ -3595,7 +3596,7 @@ void intel_finish_reset(struct drm_i915_private *dev_priv) ...@@ -3595,7 +3596,7 @@ void intel_finish_reset(struct drm_i915_private *dev_priv)
*/ */
intel_update_primary_planes(dev); intel_update_primary_planes(dev);
} else { } else {
ret = __intel_display_resume(dev, state); ret = __intel_display_resume(dev, state, ctx);
if (ret) if (ret)
DRM_ERROR("Restoring old state failed with %i\n", ret); DRM_ERROR("Restoring old state failed with %i\n", ret);
} }
...@@ -3615,7 +3616,7 @@ void intel_finish_reset(struct drm_i915_private *dev_priv) ...@@ -3615,7 +3616,7 @@ void intel_finish_reset(struct drm_i915_private *dev_priv)
dev_priv->display.hpd_irq_setup(dev_priv); dev_priv->display.hpd_irq_setup(dev_priv);
spin_unlock_irq(&dev_priv->irq_lock); spin_unlock_irq(&dev_priv->irq_lock);
ret = __intel_display_resume(dev, state); ret = __intel_display_resume(dev, state, ctx);
if (ret) if (ret)
DRM_ERROR("Restoring old state failed with %i\n", ret); DRM_ERROR("Restoring old state failed with %i\n", ret);
...@@ -11316,7 +11317,7 @@ void intel_release_load_detect_pipe(struct drm_connector *connector, ...@@ -11316,7 +11317,7 @@ void intel_release_load_detect_pipe(struct drm_connector *connector,
if (!state) if (!state)
return; return;
ret = drm_atomic_commit(state); ret = drm_atomic_helper_commit_duplicated_state(state, ctx);
if (ret) if (ret)
DRM_DEBUG_KMS("Couldn't release load detect pipe: %i\n", ret); DRM_DEBUG_KMS("Couldn't release load detect pipe: %i\n", ret);
drm_atomic_state_put(state); drm_atomic_state_put(state);
...@@ -17212,7 +17213,7 @@ void intel_display_resume(struct drm_device *dev) ...@@ -17212,7 +17213,7 @@ void intel_display_resume(struct drm_device *dev)
} }
if (!ret) if (!ret)
ret = __intel_display_resume(dev, state); ret = __intel_display_resume(dev, state, &ctx);
drm_modeset_drop_locks(&ctx); drm_modeset_drop_locks(&ctx);
drm_modeset_acquire_fini(&ctx); drm_modeset_acquire_fini(&ctx);
......
...@@ -138,12 +138,12 @@ struct drm_crtc_commit { ...@@ -138,12 +138,12 @@ struct drm_crtc_commit {
struct __drm_planes_state { struct __drm_planes_state {
struct drm_plane *ptr; struct drm_plane *ptr;
struct drm_plane_state *state; struct drm_plane_state *state, *old_state, *new_state;
}; };
struct __drm_crtcs_state { struct __drm_crtcs_state {
struct drm_crtc *ptr; 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_crtc_commit *commit;
s64 __user *out_fence_ptr; s64 __user *out_fence_ptr;
unsigned last_vblank_count; unsigned last_vblank_count;
...@@ -151,7 +151,7 @@ struct __drm_crtcs_state { ...@@ -151,7 +151,7 @@ struct __drm_crtcs_state {
struct __drm_connnectors_state { struct __drm_connnectors_state {
struct drm_connector *ptr; struct drm_connector *ptr;
struct drm_connector_state *state; struct drm_connector_state *state, *old_state, *new_state;
}; };
/** /**
...@@ -398,6 +398,31 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p); ...@@ -398,6 +398,31 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p);
(__i)++) \ (__i)++) \
for_each_if (connector) 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) \ #define for_each_crtc_in_state(__state, crtc, crtc_state, __i) \
for ((__i) = 0; \ for ((__i) = 0; \
(__i) < (__state)->dev->mode_config.num_crtc && \ (__i) < (__state)->dev->mode_config.num_crtc && \
...@@ -406,6 +431,31 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p); ...@@ -406,6 +431,31 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p);
(__i)++) \ (__i)++) \
for_each_if (crtc_state) 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) \ #define for_each_plane_in_state(__state, plane, plane_state, __i) \
for ((__i) = 0; \ for ((__i) = 0; \
(__i) < (__state)->dev->mode_config.num_total_plane && \ (__i) < (__state)->dev->mode_config.num_total_plane && \
...@@ -414,6 +464,31 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p); ...@@ -414,6 +464,31 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p);
(__i)++) \ (__i)++) \
for_each_if (plane_state) 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 * drm_atomic_crtc_needs_modeset - compute combined modeset need
* @state: &drm_crtc_state for the CRTC * @state: &drm_crtc_state for the CRTC
......
...@@ -105,6 +105,8 @@ int __drm_atomic_helper_set_config(struct drm_mode_set *set, ...@@ -105,6 +105,8 @@ int __drm_atomic_helper_set_config(struct drm_mode_set *set,
int drm_atomic_helper_disable_all(struct drm_device *dev, int drm_atomic_helper_disable_all(struct drm_device *dev,
struct drm_modeset_acquire_ctx *ctx); struct drm_modeset_acquire_ctx *ctx);
struct drm_atomic_state *drm_atomic_helper_suspend(struct drm_device *dev); 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, int drm_atomic_helper_resume(struct drm_device *dev,
struct drm_atomic_state *state); struct drm_atomic_state *state);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment