@@ -775,14 +775,18 @@ static int atomic_remove_fb(struct drm_framebuffer *fb)
775775 struct drm_plane * plane ;
776776 struct drm_connector * conn ;
777777 struct drm_connector_state * conn_state ;
778- int i , ret = 0 ;
778+ int i , ret ;
779779 unsigned plane_mask ;
780+ bool disable_crtcs = false;
780781
781- state = drm_atomic_state_alloc (dev );
782- if (!state )
783- return - ENOMEM ;
784-
782+ retry_disable :
785783 drm_modeset_acquire_init (& ctx , 0 );
784+
785+ state = drm_atomic_state_alloc (dev );
786+ if (!state ) {
787+ ret = - ENOMEM ;
788+ goto out ;
789+ }
786790 state -> acquire_ctx = & ctx ;
787791
788792retry :
@@ -803,7 +807,7 @@ static int atomic_remove_fb(struct drm_framebuffer *fb)
803807 goto unlock ;
804808 }
805809
806- if (plane_state -> crtc -> primary == plane ) {
810+ if (disable_crtcs && plane_state -> crtc -> primary == plane ) {
807811 struct drm_crtc_state * crtc_state ;
808812
809813 crtc_state = drm_atomic_get_existing_crtc_state (state , plane_state -> crtc );
@@ -828,6 +832,7 @@ static int atomic_remove_fb(struct drm_framebuffer *fb)
828832 plane -> old_fb = plane -> fb ;
829833 }
830834
835+ /* This list is only filled when disable_crtcs is set. */
831836 for_each_new_connector_in_state (state , conn , conn_state , i ) {
832837 ret = drm_atomic_set_crtc_for_connector (conn_state , NULL );
833838
@@ -850,9 +855,15 @@ static int atomic_remove_fb(struct drm_framebuffer *fb)
850855
851856 drm_atomic_state_put (state );
852857
858+ out :
853859 drm_modeset_drop_locks (& ctx );
854860 drm_modeset_acquire_fini (& ctx );
855861
862+ if (ret == - EINVAL && !disable_crtcs ) {
863+ disable_crtcs = true;
864+ goto retry_disable ;
865+ }
866+
856867 return ret ;
857868}
858869
0 commit comments