drm: Add reference counting to drm_atomic_state
drm_atomic_state has a complicated single owner model that tracks the single reference from allocation through to destruction on another thread - or perhaps on a local error path. We can simplify this tracking by using reference counting (at a cost of a few more atomics). This is even more beneficial when the lifetime of the state becomes more convoluted than being passed to a single worker thread for the commit. v2: Double check !intel atomic_commit functions for missing gets v3: Update kerneldocs Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: dri-devel@lists.freedesktop.org Reviewed-by: Eric Engestrom <eric.engestrom@imgtec.com> Reviewed-by: Sean Paul <seanpaul@chromium.org> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: http://patchwork.freedesktop.org/patch/msgid/20161014121833.439-27-chris@chris-wilson.co.uk
This commit is contained in:
parent
1dfdb0ed34
commit
0853695c3b
|
@ -464,7 +464,7 @@ atmel_hlcdc_dc_atomic_complete(struct atmel_hlcdc_dc_commit *commit)
|
||||||
|
|
||||||
drm_atomic_helper_cleanup_planes(dev, old_state);
|
drm_atomic_helper_cleanup_planes(dev, old_state);
|
||||||
|
|
||||||
drm_atomic_state_free(old_state);
|
drm_atomic_state_put(old_state);
|
||||||
|
|
||||||
/* Complete the commit, wake up any waiter. */
|
/* Complete the commit, wake up any waiter. */
|
||||||
spin_lock(&dc->commit.wait.lock);
|
spin_lock(&dc->commit.wait.lock);
|
||||||
|
@ -521,6 +521,7 @@ static int atmel_hlcdc_dc_atomic_commit(struct drm_device *dev,
|
||||||
/* Swap the state, this is the point of no return. */
|
/* Swap the state, this is the point of no return. */
|
||||||
drm_atomic_helper_swap_state(state, true);
|
drm_atomic_helper_swap_state(state, true);
|
||||||
|
|
||||||
|
drm_atomic_state_get(state);
|
||||||
if (async)
|
if (async)
|
||||||
queue_work(dc->wq, &commit->work);
|
queue_work(dc->wq, &commit->work);
|
||||||
else
|
else
|
||||||
|
|
|
@ -74,6 +74,8 @@ EXPORT_SYMBOL(drm_atomic_state_default_release);
|
||||||
int
|
int
|
||||||
drm_atomic_state_init(struct drm_device *dev, struct drm_atomic_state *state)
|
drm_atomic_state_init(struct drm_device *dev, struct drm_atomic_state *state)
|
||||||
{
|
{
|
||||||
|
kref_init(&state->ref);
|
||||||
|
|
||||||
/* TODO legacy paths should maybe do a better job about
|
/* TODO legacy paths should maybe do a better job about
|
||||||
* setting this appropriately?
|
* setting this appropriately?
|
||||||
*/
|
*/
|
||||||
|
@ -215,22 +217,16 @@ void drm_atomic_state_clear(struct drm_atomic_state *state)
|
||||||
EXPORT_SYMBOL(drm_atomic_state_clear);
|
EXPORT_SYMBOL(drm_atomic_state_clear);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* drm_atomic_state_free - free all memory for an atomic state
|
* __drm_atomic_state_free - free all memory for an atomic state
|
||||||
* @state: atomic state to deallocate
|
* @ref: This atomic state to deallocate
|
||||||
*
|
*
|
||||||
* This frees all memory associated with an atomic state, including all the
|
* This frees all memory associated with an atomic state, including all the
|
||||||
* per-object state for planes, crtcs and connectors.
|
* per-object state for planes, crtcs and connectors.
|
||||||
*/
|
*/
|
||||||
void drm_atomic_state_free(struct drm_atomic_state *state)
|
void __drm_atomic_state_free(struct kref *ref)
|
||||||
{
|
{
|
||||||
struct drm_device *dev;
|
struct drm_atomic_state *state = container_of(ref, typeof(*state), ref);
|
||||||
struct drm_mode_config *config;
|
struct drm_mode_config *config = &state->dev->mode_config;
|
||||||
|
|
||||||
if (!state)
|
|
||||||
return;
|
|
||||||
|
|
||||||
dev = state->dev;
|
|
||||||
config = &dev->mode_config;
|
|
||||||
|
|
||||||
drm_atomic_state_clear(state);
|
drm_atomic_state_clear(state);
|
||||||
|
|
||||||
|
@ -243,7 +239,7 @@ void drm_atomic_state_free(struct drm_atomic_state *state)
|
||||||
kfree(state);
|
kfree(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_atomic_state_free);
|
EXPORT_SYMBOL(__drm_atomic_state_free);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* drm_atomic_get_crtc_state - get crtc state
|
* drm_atomic_get_crtc_state - get crtc state
|
||||||
|
@ -1742,7 +1738,7 @@ retry:
|
||||||
if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) {
|
if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) {
|
||||||
/*
|
/*
|
||||||
* Unlike commit, check_only does not clean up state.
|
* Unlike commit, check_only does not clean up state.
|
||||||
* Below we call drm_atomic_state_free for it.
|
* Below we call drm_atomic_state_put for it.
|
||||||
*/
|
*/
|
||||||
ret = drm_atomic_check_only(state);
|
ret = drm_atomic_check_only(state);
|
||||||
} else if (arg->flags & DRM_MODE_ATOMIC_NONBLOCK) {
|
} else if (arg->flags & DRM_MODE_ATOMIC_NONBLOCK) {
|
||||||
|
@ -1775,8 +1771,7 @@ out:
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret || arg->flags & DRM_MODE_ATOMIC_TEST_ONLY)
|
drm_atomic_state_put(state);
|
||||||
drm_atomic_state_free(state);
|
|
||||||
|
|
||||||
drm_modeset_drop_locks(&ctx);
|
drm_modeset_drop_locks(&ctx);
|
||||||
drm_modeset_acquire_fini(&ctx);
|
drm_modeset_acquire_fini(&ctx);
|
||||||
|
|
|
@ -1208,7 +1208,7 @@ static void commit_tail(struct drm_atomic_state *state)
|
||||||
|
|
||||||
drm_atomic_helper_commit_cleanup_done(state);
|
drm_atomic_helper_commit_cleanup_done(state);
|
||||||
|
|
||||||
drm_atomic_state_free(state);
|
drm_atomic_state_put(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void commit_work(struct work_struct *work)
|
static void commit_work(struct work_struct *work)
|
||||||
|
@ -1290,6 +1290,7 @@ int drm_atomic_helper_commit(struct drm_device *dev,
|
||||||
* make sure work items don't artifically stall on each another.
|
* make sure work items don't artifically stall on each another.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
drm_atomic_state_get(state);
|
||||||
if (nonblock)
|
if (nonblock)
|
||||||
queue_work(system_unbound_wq, &state->commit_work);
|
queue_work(system_unbound_wq, &state->commit_work);
|
||||||
else
|
else
|
||||||
|
@ -1591,7 +1592,7 @@ EXPORT_SYMBOL(drm_atomic_helper_commit_hw_done);
|
||||||
*
|
*
|
||||||
* This signals completion of the atomic update @state, including any cleanup
|
* This signals completion of the atomic update @state, including any cleanup
|
||||||
* work. If used, it must be called right before calling
|
* work. If used, it must be called right before calling
|
||||||
* drm_atomic_state_free().
|
* drm_atomic_state_put().
|
||||||
*
|
*
|
||||||
* This is part of the atomic helper support for nonblocking commits, see
|
* This is part of the atomic helper support for nonblocking commits, see
|
||||||
* drm_atomic_helper_setup_commit() for an overview.
|
* drm_atomic_helper_setup_commit() for an overview.
|
||||||
|
@ -2114,18 +2115,13 @@ retry:
|
||||||
state->legacy_cursor_update = true;
|
state->legacy_cursor_update = true;
|
||||||
|
|
||||||
ret = drm_atomic_commit(state);
|
ret = drm_atomic_commit(state);
|
||||||
if (ret != 0)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
/* Driver takes ownership of state on successful commit. */
|
|
||||||
return 0;
|
|
||||||
fail:
|
fail:
|
||||||
if (ret == -EDEADLK)
|
if (ret == -EDEADLK)
|
||||||
goto backoff;
|
goto backoff;
|
||||||
|
|
||||||
drm_atomic_state_free(state);
|
drm_atomic_state_put(state);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
backoff:
|
backoff:
|
||||||
drm_atomic_state_clear(state);
|
drm_atomic_state_clear(state);
|
||||||
drm_atomic_legacy_backoff(state);
|
drm_atomic_legacy_backoff(state);
|
||||||
|
@ -2187,18 +2183,13 @@ retry:
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
ret = drm_atomic_commit(state);
|
ret = drm_atomic_commit(state);
|
||||||
if (ret != 0)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
/* Driver takes ownership of state on successful commit. */
|
|
||||||
return 0;
|
|
||||||
fail:
|
fail:
|
||||||
if (ret == -EDEADLK)
|
if (ret == -EDEADLK)
|
||||||
goto backoff;
|
goto backoff;
|
||||||
|
|
||||||
drm_atomic_state_free(state);
|
drm_atomic_state_put(state);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
backoff:
|
backoff:
|
||||||
drm_atomic_state_clear(state);
|
drm_atomic_state_clear(state);
|
||||||
drm_atomic_legacy_backoff(state);
|
drm_atomic_legacy_backoff(state);
|
||||||
|
@ -2327,18 +2318,13 @@ retry:
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
ret = drm_atomic_commit(state);
|
ret = drm_atomic_commit(state);
|
||||||
if (ret != 0)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
/* Driver takes ownership of state on successful commit. */
|
|
||||||
return 0;
|
|
||||||
fail:
|
fail:
|
||||||
if (ret == -EDEADLK)
|
if (ret == -EDEADLK)
|
||||||
goto backoff;
|
goto backoff;
|
||||||
|
|
||||||
drm_atomic_state_free(state);
|
drm_atomic_state_put(state);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
backoff:
|
backoff:
|
||||||
drm_atomic_state_clear(state);
|
drm_atomic_state_clear(state);
|
||||||
drm_atomic_legacy_backoff(state);
|
drm_atomic_legacy_backoff(state);
|
||||||
|
@ -2480,11 +2466,8 @@ int drm_atomic_helper_disable_all(struct drm_device *dev,
|
||||||
}
|
}
|
||||||
|
|
||||||
err = drm_atomic_commit(state);
|
err = drm_atomic_commit(state);
|
||||||
|
|
||||||
free:
|
free:
|
||||||
if (err < 0)
|
drm_atomic_state_put(state);
|
||||||
drm_atomic_state_free(state);
|
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_atomic_helper_disable_all);
|
EXPORT_SYMBOL(drm_atomic_helper_disable_all);
|
||||||
|
@ -2535,7 +2518,7 @@ retry:
|
||||||
|
|
||||||
err = drm_atomic_helper_disable_all(dev, &ctx);
|
err = drm_atomic_helper_disable_all(dev, &ctx);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
drm_atomic_state_free(state);
|
drm_atomic_state_put(state);
|
||||||
state = ERR_PTR(err);
|
state = ERR_PTR(err);
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
|
@ -2624,18 +2607,13 @@ retry:
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
ret = drm_atomic_commit(state);
|
ret = drm_atomic_commit(state);
|
||||||
if (ret != 0)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
/* Driver takes ownership of state on successful commit. */
|
|
||||||
return 0;
|
|
||||||
fail:
|
fail:
|
||||||
if (ret == -EDEADLK)
|
if (ret == -EDEADLK)
|
||||||
goto backoff;
|
goto backoff;
|
||||||
|
|
||||||
drm_atomic_state_free(state);
|
drm_atomic_state_put(state);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
backoff:
|
backoff:
|
||||||
drm_atomic_state_clear(state);
|
drm_atomic_state_clear(state);
|
||||||
drm_atomic_legacy_backoff(state);
|
drm_atomic_legacy_backoff(state);
|
||||||
|
@ -2684,18 +2662,13 @@ retry:
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
ret = drm_atomic_commit(state);
|
ret = drm_atomic_commit(state);
|
||||||
if (ret != 0)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
/* Driver takes ownership of state on successful commit. */
|
|
||||||
return 0;
|
|
||||||
fail:
|
fail:
|
||||||
if (ret == -EDEADLK)
|
if (ret == -EDEADLK)
|
||||||
goto backoff;
|
goto backoff;
|
||||||
|
|
||||||
drm_atomic_state_free(state);
|
drm_atomic_state_put(state);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
backoff:
|
backoff:
|
||||||
drm_atomic_state_clear(state);
|
drm_atomic_state_clear(state);
|
||||||
drm_atomic_legacy_backoff(state);
|
drm_atomic_legacy_backoff(state);
|
||||||
|
@ -2744,18 +2717,13 @@ retry:
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
ret = drm_atomic_commit(state);
|
ret = drm_atomic_commit(state);
|
||||||
if (ret != 0)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
/* Driver takes ownership of state on successful commit. */
|
|
||||||
return 0;
|
|
||||||
fail:
|
fail:
|
||||||
if (ret == -EDEADLK)
|
if (ret == -EDEADLK)
|
||||||
goto backoff;
|
goto backoff;
|
||||||
|
|
||||||
drm_atomic_state_free(state);
|
drm_atomic_state_put(state);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
backoff:
|
backoff:
|
||||||
drm_atomic_state_clear(state);
|
drm_atomic_state_clear(state);
|
||||||
drm_atomic_legacy_backoff(state);
|
drm_atomic_legacy_backoff(state);
|
||||||
|
@ -2828,18 +2796,13 @@ retry:
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = drm_atomic_nonblocking_commit(state);
|
ret = drm_atomic_nonblocking_commit(state);
|
||||||
if (ret != 0)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
/* Driver takes ownership of state on successful commit. */
|
|
||||||
return 0;
|
|
||||||
fail:
|
fail:
|
||||||
if (ret == -EDEADLK)
|
if (ret == -EDEADLK)
|
||||||
goto backoff;
|
goto backoff;
|
||||||
|
|
||||||
drm_atomic_state_free(state);
|
drm_atomic_state_put(state);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
backoff:
|
backoff:
|
||||||
drm_atomic_state_clear(state);
|
drm_atomic_state_clear(state);
|
||||||
drm_atomic_legacy_backoff(state);
|
drm_atomic_legacy_backoff(state);
|
||||||
|
@ -2915,19 +2878,14 @@ retry:
|
||||||
crtc_state->active = active;
|
crtc_state->active = active;
|
||||||
|
|
||||||
ret = drm_atomic_commit(state);
|
ret = drm_atomic_commit(state);
|
||||||
if (ret != 0)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
/* Driver takes ownership of state on successful commit. */
|
|
||||||
return 0;
|
|
||||||
fail:
|
fail:
|
||||||
if (ret == -EDEADLK)
|
if (ret == -EDEADLK)
|
||||||
goto backoff;
|
goto backoff;
|
||||||
|
|
||||||
connector->dpms = old_mode;
|
connector->dpms = old_mode;
|
||||||
drm_atomic_state_free(state);
|
drm_atomic_state_put(state);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
backoff:
|
backoff:
|
||||||
drm_atomic_state_clear(state);
|
drm_atomic_state_clear(state);
|
||||||
drm_atomic_legacy_backoff(state);
|
drm_atomic_legacy_backoff(state);
|
||||||
|
@ -3334,7 +3292,7 @@ drm_atomic_helper_duplicate_state(struct drm_device *dev,
|
||||||
|
|
||||||
free:
|
free:
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
drm_atomic_state_free(state);
|
drm_atomic_state_put(state);
|
||||||
state = ERR_PTR(err);
|
state = ERR_PTR(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3449,22 +3407,14 @@ retry:
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
ret = drm_atomic_commit(state);
|
ret = drm_atomic_commit(state);
|
||||||
if (ret)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
/* Driver takes ownership of state on successful commit. */
|
|
||||||
|
|
||||||
drm_property_unreference_blob(blob);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
fail:
|
fail:
|
||||||
if (ret == -EDEADLK)
|
if (ret == -EDEADLK)
|
||||||
goto backoff;
|
goto backoff;
|
||||||
|
|
||||||
drm_atomic_state_free(state);
|
drm_atomic_state_put(state);
|
||||||
drm_property_unreference_blob(blob);
|
drm_property_unreference_blob(blob);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
backoff:
|
backoff:
|
||||||
drm_atomic_state_clear(state);
|
drm_atomic_state_clear(state);
|
||||||
drm_atomic_legacy_backoff(state);
|
drm_atomic_legacy_backoff(state);
|
||||||
|
|
|
@ -367,9 +367,7 @@ fail:
|
||||||
if (ret == -EDEADLK)
|
if (ret == -EDEADLK)
|
||||||
goto backoff;
|
goto backoff;
|
||||||
|
|
||||||
if (ret != 0)
|
drm_atomic_state_put(state);
|
||||||
drm_atomic_state_free(state);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
backoff:
|
backoff:
|
||||||
|
@ -1361,16 +1359,13 @@ retry:
|
||||||
info->var.xoffset = var->xoffset;
|
info->var.xoffset = var->xoffset;
|
||||||
info->var.yoffset = var->yoffset;
|
info->var.yoffset = var->yoffset;
|
||||||
|
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
drm_atomic_clean_old_fb(dev, plane_mask, ret);
|
drm_atomic_clean_old_fb(dev, plane_mask, ret);
|
||||||
|
|
||||||
if (ret == -EDEADLK)
|
if (ret == -EDEADLK)
|
||||||
goto backoff;
|
goto backoff;
|
||||||
|
|
||||||
if (ret != 0)
|
drm_atomic_state_put(state);
|
||||||
drm_atomic_state_free(state);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
backoff:
|
backoff:
|
||||||
|
|
|
@ -69,7 +69,7 @@ static void exynos_atomic_commit_complete(struct exynos_atomic_commit *commit)
|
||||||
|
|
||||||
drm_atomic_helper_cleanup_planes(dev, state);
|
drm_atomic_helper_cleanup_planes(dev, state);
|
||||||
|
|
||||||
drm_atomic_state_free(state);
|
drm_atomic_state_put(state);
|
||||||
|
|
||||||
spin_lock(&priv->lock);
|
spin_lock(&priv->lock);
|
||||||
priv->pending &= ~commit->crtcs;
|
priv->pending &= ~commit->crtcs;
|
||||||
|
@ -254,6 +254,7 @@ int exynos_atomic_commit(struct drm_device *dev, struct drm_atomic_state *state,
|
||||||
|
|
||||||
drm_atomic_helper_swap_state(state, true);
|
drm_atomic_helper_swap_state(state, true);
|
||||||
|
|
||||||
|
drm_atomic_state_get(state);
|
||||||
if (nonblock)
|
if (nonblock)
|
||||||
schedule_work(&commit->work);
|
schedule_work(&commit->work);
|
||||||
else
|
else
|
||||||
|
|
|
@ -3941,10 +3941,9 @@ static void hsw_trans_edp_pipe_A_crc_wa(struct drm_i915_private *dev_priv,
|
||||||
|
|
||||||
ret = drm_atomic_commit(state);
|
ret = drm_atomic_commit(state);
|
||||||
out:
|
out:
|
||||||
drm_modeset_unlock_all(dev);
|
|
||||||
WARN(ret, "Toggling workaround to %i returns %i\n", enable, ret);
|
WARN(ret, "Toggling workaround to %i returns %i\n", enable, ret);
|
||||||
if (ret)
|
drm_modeset_unlock_all(dev);
|
||||||
drm_atomic_state_free(state);
|
drm_atomic_state_put(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ivb_pipe_crc_ctl_reg(struct drm_i915_private *dev_priv,
|
static int ivb_pipe_crc_ctl_reg(struct drm_i915_private *dev_priv,
|
||||||
|
|
|
@ -3582,7 +3582,7 @@ void intel_prepare_reset(struct drm_i915_private *dev_priv)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
drm_atomic_state_free(state);
|
drm_atomic_state_put(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
void intel_finish_reset(struct drm_i915_private *dev_priv)
|
void intel_finish_reset(struct drm_i915_private *dev_priv)
|
||||||
|
@ -3643,6 +3643,8 @@ void intel_finish_reset(struct drm_i915_private *dev_priv)
|
||||||
intel_hpd_init(dev_priv);
|
intel_hpd_init(dev_priv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (state)
|
||||||
|
drm_atomic_state_put(state);
|
||||||
drm_modeset_drop_locks(ctx);
|
drm_modeset_drop_locks(ctx);
|
||||||
drm_modeset_acquire_fini(ctx);
|
drm_modeset_acquire_fini(ctx);
|
||||||
mutex_unlock(&dev->mode_config.mutex);
|
mutex_unlock(&dev->mode_config.mutex);
|
||||||
|
@ -6882,7 +6884,7 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc)
|
||||||
|
|
||||||
dev_priv->display.crtc_disable(crtc_state, state);
|
dev_priv->display.crtc_disable(crtc_state, state);
|
||||||
|
|
||||||
drm_atomic_state_free(state);
|
drm_atomic_state_put(state);
|
||||||
|
|
||||||
DRM_DEBUG_KMS("[CRTC:%d:%s] hw state adjusted, was enabled, now disabled\n",
|
DRM_DEBUG_KMS("[CRTC:%d:%s] hw state adjusted, was enabled, now disabled\n",
|
||||||
crtc->base.id, crtc->name);
|
crtc->base.id, crtc->name);
|
||||||
|
@ -11249,8 +11251,8 @@ found:
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
drm_atomic_state_free(state);
|
drm_atomic_state_put(state);
|
||||||
drm_atomic_state_free(restore_state);
|
drm_atomic_state_put(restore_state);
|
||||||
restore_state = state = NULL;
|
restore_state = state = NULL;
|
||||||
|
|
||||||
if (ret == -EDEADLK) {
|
if (ret == -EDEADLK) {
|
||||||
|
@ -11279,10 +11281,9 @@ void intel_release_load_detect_pipe(struct drm_connector *connector,
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ret = drm_atomic_commit(state);
|
ret = drm_atomic_commit(state);
|
||||||
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_free(state);
|
drm_atomic_state_put(state);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int i9xx_pll_refclk(struct drm_device *dev,
|
static int i9xx_pll_refclk(struct drm_device *dev,
|
||||||
|
@ -12350,8 +12351,7 @@ retry:
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret)
|
drm_atomic_state_put(state);
|
||||||
drm_atomic_state_free(state);
|
|
||||||
|
|
||||||
if (ret == 0 && event) {
|
if (ret == 0 && event) {
|
||||||
spin_lock_irq(&dev->event_lock);
|
spin_lock_irq(&dev->event_lock);
|
||||||
|
@ -14437,7 +14437,7 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
|
||||||
|
|
||||||
drm_atomic_helper_commit_cleanup_done(state);
|
drm_atomic_helper_commit_cleanup_done(state);
|
||||||
|
|
||||||
drm_atomic_state_free(state);
|
drm_atomic_state_put(state);
|
||||||
|
|
||||||
/* As one of the primary mmio accessors, KMS has a high likelihood
|
/* As one of the primary mmio accessors, KMS has a high likelihood
|
||||||
* of triggering bugs in unclaimed access. After we finish
|
* of triggering bugs in unclaimed access. After we finish
|
||||||
|
@ -14520,6 +14520,7 @@ static int intel_atomic_commit(struct drm_device *dev,
|
||||||
intel_shared_dpll_commit(state);
|
intel_shared_dpll_commit(state);
|
||||||
intel_atomic_track_fbs(state);
|
intel_atomic_track_fbs(state);
|
||||||
|
|
||||||
|
drm_atomic_state_get(state);
|
||||||
if (nonblock)
|
if (nonblock)
|
||||||
queue_work(system_unbound_wq, &state->commit_work);
|
queue_work(system_unbound_wq, &state->commit_work);
|
||||||
else
|
else
|
||||||
|
@ -14561,9 +14562,8 @@ retry:
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret)
|
|
||||||
out:
|
out:
|
||||||
drm_atomic_state_free(state);
|
drm_atomic_state_put(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -16305,8 +16305,8 @@ retry:
|
||||||
dev_priv->display.optimize_watermarks(cs);
|
dev_priv->display.optimize_watermarks(cs);
|
||||||
}
|
}
|
||||||
|
|
||||||
drm_atomic_state_free(state);
|
|
||||||
fail:
|
fail:
|
||||||
|
drm_atomic_state_put(state);
|
||||||
drm_modeset_drop_locks(&ctx);
|
drm_modeset_drop_locks(&ctx);
|
||||||
drm_modeset_acquire_fini(&ctx);
|
drm_modeset_acquire_fini(&ctx);
|
||||||
}
|
}
|
||||||
|
@ -16943,10 +16943,9 @@ void intel_display_resume(struct drm_device *dev)
|
||||||
drm_modeset_acquire_fini(&ctx);
|
drm_modeset_acquire_fini(&ctx);
|
||||||
mutex_unlock(&dev->mode_config.mutex);
|
mutex_unlock(&dev->mode_config.mutex);
|
||||||
|
|
||||||
if (ret) {
|
if (ret)
|
||||||
DRM_ERROR("Restoring old state failed with %i\n", ret);
|
DRM_ERROR("Restoring old state failed with %i\n", ret);
|
||||||
drm_atomic_state_free(state);
|
drm_atomic_state_put(state);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void intel_modeset_gem_init(struct drm_device *dev)
|
void intel_modeset_gem_init(struct drm_device *dev)
|
||||||
|
|
|
@ -987,9 +987,7 @@ int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
|
||||||
drm_modeset_backoff(&ctx);
|
drm_modeset_backoff(&ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret)
|
drm_atomic_state_put(state);
|
||||||
drm_atomic_state_free(state);
|
|
||||||
|
|
||||||
out:
|
out:
|
||||||
drm_modeset_drop_locks(&ctx);
|
drm_modeset_drop_locks(&ctx);
|
||||||
drm_modeset_acquire_fini(&ctx);
|
drm_modeset_acquire_fini(&ctx);
|
||||||
|
|
|
@ -83,7 +83,7 @@ static void mtk_atomic_complete(struct mtk_drm_private *private,
|
||||||
drm_atomic_helper_wait_for_vblanks(drm, state);
|
drm_atomic_helper_wait_for_vblanks(drm, state);
|
||||||
|
|
||||||
drm_atomic_helper_cleanup_planes(drm, state);
|
drm_atomic_helper_cleanup_planes(drm, state);
|
||||||
drm_atomic_state_free(state);
|
drm_atomic_state_put(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mtk_atomic_work(struct work_struct *work)
|
static void mtk_atomic_work(struct work_struct *work)
|
||||||
|
@ -110,6 +110,7 @@ static int mtk_atomic_commit(struct drm_device *drm,
|
||||||
|
|
||||||
drm_atomic_helper_swap_state(state, true);
|
drm_atomic_helper_swap_state(state, true);
|
||||||
|
|
||||||
|
drm_atomic_state_get(state);
|
||||||
if (async)
|
if (async)
|
||||||
mtk_atomic_schedule(private, state);
|
mtk_atomic_schedule(private, state);
|
||||||
else
|
else
|
||||||
|
|
|
@ -141,7 +141,7 @@ static void complete_commit(struct msm_commit *c, bool async)
|
||||||
|
|
||||||
kms->funcs->complete_commit(kms, state);
|
kms->funcs->complete_commit(kms, state);
|
||||||
|
|
||||||
drm_atomic_state_free(state);
|
drm_atomic_state_put(state);
|
||||||
|
|
||||||
commit_destroy(c);
|
commit_destroy(c);
|
||||||
}
|
}
|
||||||
|
@ -256,6 +256,7 @@ int msm_atomic_commit(struct drm_device *dev,
|
||||||
* current layout.
|
* current layout.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
drm_atomic_state_get(state);
|
||||||
if (nonblock) {
|
if (nonblock) {
|
||||||
queue_work(priv->atomic_wq, &c->work);
|
queue_work(priv->atomic_wq, &c->work);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -105,7 +105,7 @@ static void omap_atomic_complete(struct omap_atomic_state_commit *commit)
|
||||||
|
|
||||||
dispc_runtime_put();
|
dispc_runtime_put();
|
||||||
|
|
||||||
drm_atomic_state_free(old_state);
|
drm_atomic_state_put(old_state);
|
||||||
|
|
||||||
/* Complete the commit, wake up any waiter. */
|
/* Complete the commit, wake up any waiter. */
|
||||||
spin_lock(&priv->commit.lock);
|
spin_lock(&priv->commit.lock);
|
||||||
|
@ -176,6 +176,7 @@ static int omap_atomic_commit(struct drm_device *dev,
|
||||||
/* Swap the state, this is the point of no return. */
|
/* Swap the state, this is the point of no return. */
|
||||||
drm_atomic_helper_swap_state(state, true);
|
drm_atomic_helper_swap_state(state, true);
|
||||||
|
|
||||||
|
drm_atomic_state_get(state);
|
||||||
if (nonblock)
|
if (nonblock)
|
||||||
schedule_work(&commit->work);
|
schedule_work(&commit->work);
|
||||||
else
|
else
|
||||||
|
|
|
@ -264,7 +264,7 @@ static void rcar_du_atomic_complete(struct rcar_du_commit *commit)
|
||||||
|
|
||||||
drm_atomic_helper_cleanup_planes(dev, old_state);
|
drm_atomic_helper_cleanup_planes(dev, old_state);
|
||||||
|
|
||||||
drm_atomic_state_free(old_state);
|
drm_atomic_state_put(old_state);
|
||||||
|
|
||||||
/* Complete the commit, wake up any waiter. */
|
/* Complete the commit, wake up any waiter. */
|
||||||
spin_lock(&rcdu->commit.wait.lock);
|
spin_lock(&rcdu->commit.wait.lock);
|
||||||
|
@ -330,6 +330,7 @@ static int rcar_du_atomic_commit(struct drm_device *dev,
|
||||||
/* Swap the state, this is the point of no return. */
|
/* Swap the state, this is the point of no return. */
|
||||||
drm_atomic_helper_swap_state(state, true);
|
drm_atomic_helper_swap_state(state, true);
|
||||||
|
|
||||||
|
drm_atomic_state_get(state);
|
||||||
if (nonblock)
|
if (nonblock)
|
||||||
schedule_work(&commit->work);
|
schedule_work(&commit->work);
|
||||||
else
|
else
|
||||||
|
|
|
@ -184,7 +184,7 @@ static void sti_atomic_complete(struct sti_private *private,
|
||||||
drm_atomic_helper_wait_for_vblanks(drm, state);
|
drm_atomic_helper_wait_for_vblanks(drm, state);
|
||||||
|
|
||||||
drm_atomic_helper_cleanup_planes(drm, state);
|
drm_atomic_helper_cleanup_planes(drm, state);
|
||||||
drm_atomic_state_free(state);
|
drm_atomic_state_put(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sti_atomic_work(struct work_struct *work)
|
static void sti_atomic_work(struct work_struct *work)
|
||||||
|
@ -217,6 +217,7 @@ static int sti_atomic_commit(struct drm_device *drm,
|
||||||
|
|
||||||
drm_atomic_helper_swap_state(state, true);
|
drm_atomic_helper_swap_state(state, true);
|
||||||
|
|
||||||
|
drm_atomic_state_get(state);
|
||||||
if (nonblock)
|
if (nonblock)
|
||||||
sti_atomic_schedule(private, state);
|
sti_atomic_schedule(private, state);
|
||||||
else
|
else
|
||||||
|
|
|
@ -63,7 +63,7 @@ static void tegra_atomic_complete(struct tegra_drm *tegra,
|
||||||
drm_atomic_helper_wait_for_vblanks(drm, state);
|
drm_atomic_helper_wait_for_vblanks(drm, state);
|
||||||
|
|
||||||
drm_atomic_helper_cleanup_planes(drm, state);
|
drm_atomic_helper_cleanup_planes(drm, state);
|
||||||
drm_atomic_state_free(state);
|
drm_atomic_state_put(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tegra_atomic_work(struct work_struct *work)
|
static void tegra_atomic_work(struct work_struct *work)
|
||||||
|
@ -96,6 +96,7 @@ static int tegra_atomic_commit(struct drm_device *drm,
|
||||||
|
|
||||||
drm_atomic_helper_swap_state(state, true);
|
drm_atomic_helper_swap_state(state, true);
|
||||||
|
|
||||||
|
drm_atomic_state_get(state);
|
||||||
if (nonblock)
|
if (nonblock)
|
||||||
tegra_atomic_schedule(tegra, state);
|
tegra_atomic_schedule(tegra, state);
|
||||||
else
|
else
|
||||||
|
|
|
@ -143,8 +143,6 @@ static int tilcdc_commit(struct drm_device *dev,
|
||||||
|
|
||||||
drm_atomic_helper_cleanup_planes(dev, state);
|
drm_atomic_helper_cleanup_planes(dev, state);
|
||||||
|
|
||||||
drm_atomic_state_free(state);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,7 @@ vc4_atomic_complete_commit(struct vc4_commit *c)
|
||||||
|
|
||||||
drm_atomic_helper_cleanup_planes(dev, state);
|
drm_atomic_helper_cleanup_planes(dev, state);
|
||||||
|
|
||||||
drm_atomic_state_free(state);
|
drm_atomic_state_put(state);
|
||||||
|
|
||||||
up(&vc4->async_modeset);
|
up(&vc4->async_modeset);
|
||||||
|
|
||||||
|
@ -173,6 +173,7 @@ static int vc4_atomic_commit(struct drm_device *dev,
|
||||||
* current layout.
|
* current layout.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
drm_atomic_state_get(state);
|
||||||
if (nonblock) {
|
if (nonblock) {
|
||||||
vc4_queue_seqno_cb(dev, &c->cb, wait_seqno,
|
vc4_queue_seqno_cb(dev, &c->cb, wait_seqno,
|
||||||
vc4_atomic_complete_commit_seqno_cb);
|
vc4_atomic_complete_commit_seqno_cb);
|
||||||
|
|
|
@ -153,6 +153,7 @@ struct __drm_connnectors_state {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct drm_atomic_state - the global state object for atomic updates
|
* struct drm_atomic_state - the global state object for atomic updates
|
||||||
|
* @ref: count of all references to this state (will not be freed until zero)
|
||||||
* @dev: parent DRM device
|
* @dev: parent DRM device
|
||||||
* @allow_modeset: allow full modeset
|
* @allow_modeset: allow full modeset
|
||||||
* @legacy_cursor_update: hint to enforce legacy cursor IOCTL semantics
|
* @legacy_cursor_update: hint to enforce legacy cursor IOCTL semantics
|
||||||
|
@ -164,6 +165,8 @@ struct __drm_connnectors_state {
|
||||||
* @acquire_ctx: acquire context for this atomic modeset state update
|
* @acquire_ctx: acquire context for this atomic modeset state update
|
||||||
*/
|
*/
|
||||||
struct drm_atomic_state {
|
struct drm_atomic_state {
|
||||||
|
struct kref ref;
|
||||||
|
|
||||||
struct drm_device *dev;
|
struct drm_device *dev;
|
||||||
bool allow_modeset : 1;
|
bool allow_modeset : 1;
|
||||||
bool legacy_cursor_update : 1;
|
bool legacy_cursor_update : 1;
|
||||||
|
@ -193,7 +196,33 @@ static inline void drm_crtc_commit_get(struct drm_crtc_commit *commit)
|
||||||
struct drm_atomic_state * __must_check
|
struct drm_atomic_state * __must_check
|
||||||
drm_atomic_state_alloc(struct drm_device *dev);
|
drm_atomic_state_alloc(struct drm_device *dev);
|
||||||
void drm_atomic_state_clear(struct drm_atomic_state *state);
|
void drm_atomic_state_clear(struct drm_atomic_state *state);
|
||||||
void drm_atomic_state_free(struct drm_atomic_state *state);
|
|
||||||
|
/**
|
||||||
|
* drm_atomic_state_get - acquire a reference to the atomic state
|
||||||
|
* @state: The atomic state
|
||||||
|
*
|
||||||
|
* Returns a new reference to the @state
|
||||||
|
*/
|
||||||
|
static inline struct drm_atomic_state *
|
||||||
|
drm_atomic_state_get(struct drm_atomic_state *state)
|
||||||
|
{
|
||||||
|
kref_get(&state->ref);
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
void __drm_atomic_state_free(struct kref *ref);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* drm_atomic_state_put - release a reference to the atomic state
|
||||||
|
* @state: The atomic state
|
||||||
|
*
|
||||||
|
* This releases a reference to @state which is freed after removing the
|
||||||
|
* final reference. No locking required and callable from any context.
|
||||||
|
*/
|
||||||
|
static inline void drm_atomic_state_put(struct drm_atomic_state *state)
|
||||||
|
{
|
||||||
|
kref_put(&state->ref, __drm_atomic_state_free);
|
||||||
|
}
|
||||||
|
|
||||||
int __must_check
|
int __must_check
|
||||||
drm_atomic_state_init(struct drm_device *dev, struct drm_atomic_state *state);
|
drm_atomic_state_init(struct drm_device *dev, struct drm_atomic_state *state);
|
||||||
|
|
|
@ -88,7 +88,6 @@ struct drm_plane_state {
|
||||||
struct drm_atomic_state *state;
|
struct drm_atomic_state *state;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct drm_plane_funcs - driver plane control functions
|
* struct drm_plane_funcs - driver plane control functions
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in a new issue