@@ -2012,7 +2012,7 @@ int drm_atomic_helper_commit(struct drm_device *dev,
20122012 return ret ;
20132013
20142014 drm_atomic_helper_async_commit (dev , state );
2015- drm_atomic_helper_cleanup_planes (dev , state );
2015+ drm_atomic_helper_unprepare_planes (dev , state );
20162016
20172017 return 0 ;
20182018 }
@@ -2072,7 +2072,7 @@ int drm_atomic_helper_commit(struct drm_device *dev,
20722072 return 0 ;
20732073
20742074err :
2075- drm_atomic_helper_cleanup_planes (dev , state );
2075+ drm_atomic_helper_unprepare_planes (dev , state );
20762076 return ret ;
20772077}
20782078EXPORT_SYMBOL (drm_atomic_helper_commit );
@@ -2650,6 +2650,39 @@ int drm_atomic_helper_prepare_planes(struct drm_device *dev,
26502650}
26512651EXPORT_SYMBOL (drm_atomic_helper_prepare_planes );
26522652
2653+ /**
2654+ * drm_atomic_helper_unprepare_planes - release plane resources on aborts
2655+ * @dev: DRM device
2656+ * @state: atomic state object with old state structures
2657+ *
2658+ * This function cleans up plane state, specifically framebuffers, from the
2659+ * atomic state. It undoes the effects of drm_atomic_helper_prepare_planes()
2660+ * when aborting an atomic commit. For cleaning up after a successful commit
2661+ * use drm_atomic_helper_cleanup_planes().
2662+ */
2663+ void drm_atomic_helper_unprepare_planes (struct drm_device * dev ,
2664+ struct drm_atomic_state * state )
2665+ {
2666+ struct drm_plane * plane ;
2667+ struct drm_plane_state * new_plane_state ;
2668+ int i ;
2669+
2670+ for_each_new_plane_in_state (state , plane , new_plane_state , i ) {
2671+ const struct drm_plane_helper_funcs * funcs = plane -> helper_private ;
2672+
2673+ if (funcs -> end_fb_access )
2674+ funcs -> end_fb_access (plane , new_plane_state );
2675+ }
2676+
2677+ for_each_new_plane_in_state (state , plane , new_plane_state , i ) {
2678+ const struct drm_plane_helper_funcs * funcs = plane -> helper_private ;
2679+
2680+ if (funcs -> cleanup_fb )
2681+ funcs -> cleanup_fb (plane , new_plane_state );
2682+ }
2683+ }
2684+ EXPORT_SYMBOL (drm_atomic_helper_unprepare_planes );
2685+
26532686static bool plane_crtc_active (const struct drm_plane_state * state )
26542687{
26552688 return state -> crtc && state -> crtc -> state -> active ;
@@ -2784,6 +2817,17 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev,
27842817
27852818 funcs -> atomic_flush (crtc , old_state );
27862819 }
2820+
2821+ /*
2822+ * Signal end of framebuffer access here before hw_done. After hw_done,
2823+ * a later commit might have already released the plane state.
2824+ */
2825+ for_each_old_plane_in_state (old_state , plane , old_plane_state , i ) {
2826+ const struct drm_plane_helper_funcs * funcs = plane -> helper_private ;
2827+
2828+ if (funcs -> end_fb_access )
2829+ funcs -> end_fb_access (plane , old_plane_state );
2830+ }
27872831}
27882832EXPORT_SYMBOL (drm_atomic_helper_commit_planes );
27892833
@@ -2911,40 +2955,22 @@ EXPORT_SYMBOL(drm_atomic_helper_disable_planes_on_crtc);
29112955 * configuration. Hence the old configuration must be perserved in @old_state to
29122956 * be able to call this function.
29132957 *
2914- * This function must also be called on the new state when the atomic update
2915- * fails at any point after calling drm_atomic_helper_prepare_planes().
2958+ * This function may not be called on the new state when the atomic update
2959+ * fails at any point after calling drm_atomic_helper_prepare_planes(). Use
2960+ * drm_atomic_helper_unprepare_planes() in this case.
29162961 */
29172962void drm_atomic_helper_cleanup_planes (struct drm_device * dev ,
29182963 struct drm_atomic_state * old_state )
29192964{
29202965 struct drm_plane * plane ;
2921- struct drm_plane_state * old_plane_state , * new_plane_state ;
2966+ struct drm_plane_state * old_plane_state ;
29222967 int i ;
29232968
2924- for_each_oldnew_plane_in_state (old_state , plane , old_plane_state , new_plane_state , i ) {
2969+ for_each_old_plane_in_state (old_state , plane , old_plane_state , i ) {
29252970 const struct drm_plane_helper_funcs * funcs = plane -> helper_private ;
29262971
2927- if (funcs -> end_fb_access )
2928- funcs -> end_fb_access (plane , new_plane_state );
2929- }
2930-
2931- for_each_oldnew_plane_in_state (old_state , plane , old_plane_state , new_plane_state , i ) {
2932- const struct drm_plane_helper_funcs * funcs ;
2933- struct drm_plane_state * plane_state ;
2934-
2935- /*
2936- * This might be called before swapping when commit is aborted,
2937- * in which case we have to cleanup the new state.
2938- */
2939- if (old_plane_state == plane -> state )
2940- plane_state = new_plane_state ;
2941- else
2942- plane_state = old_plane_state ;
2943-
2944- funcs = plane -> helper_private ;
2945-
29462972 if (funcs -> cleanup_fb )
2947- funcs -> cleanup_fb (plane , plane_state );
2973+ funcs -> cleanup_fb (plane , old_plane_state );
29482974 }
29492975}
29502976EXPORT_SYMBOL (drm_atomic_helper_cleanup_planes );
0 commit comments