Commit ddadd408 authored by Maxime Ripard's avatar Maxime Ripard

drm: Introduce an atomic_commit_setup function

Private objects storing a state shared across all CRTCs need to be
carefully handled to avoid a use-after-free issue.

The proper way to do this to track all the commits using that shared
state and wait for the previous commits to be done before going on with
the current one to avoid the reordering of commits that could occur.

However, this commit setup needs to be done after
drm_atomic_helper_setup_commit(), because before the CRTC commit
structure hasn't been allocated before, and before the workqueue is
scheduled, because we would be potentially reordered already otherwise.

That means that drivers currently have to roll their own
drm_atomic_helper_commit() function, even though it would be identical
if not for the commit setup.

Let's introduce a hook to do so that would be called as part of
drm_atomic_helper_commit, allowing us to reuse the atomic helpers.
Reviewed-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Suggested-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: default avatarMaxime Ripard <maxime@cerno.tech>
Link: https://patchwork.freedesktop.org/patch/msgid/20201204151138.1739736-2-maxime@cerno.tech
parent ae75a043
...@@ -2040,6 +2040,9 @@ crtc_or_fake_commit(struct drm_atomic_state *state, struct drm_crtc *crtc) ...@@ -2040,6 +2040,9 @@ crtc_or_fake_commit(struct drm_atomic_state *state, struct drm_crtc *crtc)
* should always call this function from their * should always call this function from their
* &drm_mode_config_funcs.atomic_commit hook. * &drm_mode_config_funcs.atomic_commit hook.
* *
* Drivers that need to extend the commit setup to private objects can use the
* &drm_mode_config_helper_funcs.atomic_commit_setup hook.
*
* To be able to use this support drivers need to use a few more helper * To be able to use this support drivers need to use a few more helper
* functions. drm_atomic_helper_wait_for_dependencies() must be called before * functions. drm_atomic_helper_wait_for_dependencies() must be called before
* actually committing the hardware state, and for nonblocking commits this call * actually committing the hardware state, and for nonblocking commits this call
...@@ -2083,8 +2086,11 @@ int drm_atomic_helper_setup_commit(struct drm_atomic_state *state, ...@@ -2083,8 +2086,11 @@ int drm_atomic_helper_setup_commit(struct drm_atomic_state *state,
struct drm_plane *plane; struct drm_plane *plane;
struct drm_plane_state *old_plane_state, *new_plane_state; struct drm_plane_state *old_plane_state, *new_plane_state;
struct drm_crtc_commit *commit; struct drm_crtc_commit *commit;
const struct drm_mode_config_helper_funcs *funcs;
int i, ret; int i, ret;
funcs = state->dev->mode_config.helper_private;
for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
commit = kzalloc(sizeof(*commit), GFP_KERNEL); commit = kzalloc(sizeof(*commit), GFP_KERNEL);
if (!commit) if (!commit)
...@@ -2169,6 +2175,9 @@ int drm_atomic_helper_setup_commit(struct drm_atomic_state *state, ...@@ -2169,6 +2175,9 @@ int drm_atomic_helper_setup_commit(struct drm_atomic_state *state,
new_plane_state->commit = drm_crtc_commit_get(commit); new_plane_state->commit = drm_crtc_commit_get(commit);
} }
if (funcs && funcs->atomic_commit_setup)
return funcs->atomic_commit_setup(state);
return 0; return 0;
} }
EXPORT_SYMBOL(drm_atomic_helper_setup_commit); EXPORT_SYMBOL(drm_atomic_helper_setup_commit);
......
...@@ -1395,6 +1395,27 @@ struct drm_mode_config_helper_funcs { ...@@ -1395,6 +1395,27 @@ struct drm_mode_config_helper_funcs {
* drm_atomic_helper_commit_tail(). * drm_atomic_helper_commit_tail().
*/ */
void (*atomic_commit_tail)(struct drm_atomic_state *state); void (*atomic_commit_tail)(struct drm_atomic_state *state);
/**
* @atomic_commit_setup:
*
* This hook is used by the default atomic_commit() hook implemented in
* drm_atomic_helper_commit() together with the nonblocking helpers (see
* drm_atomic_helper_setup_commit()) to extend the DRM commit setup. It
* is not used by the atomic helpers.
*
* This function is called at the end of
* drm_atomic_helper_setup_commit(), so once the commit has been
* properly setup across the generic DRM object states. It allows
* drivers to do some additional commit tracking that isn't related to a
* CRTC, plane or connector, tracked in a &drm_private_obj structure.
*
* Note that the documentation of &drm_private_obj has more details on
* how one should implement this.
*
* This hook is optional.
*/
int (*atomic_commit_setup)(struct drm_atomic_state *state);
}; };
#endif #endif
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