diff options
author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2017-04-03 04:33:03 -0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2017-04-06 04:22:43 -0400 |
commit | 941b8caaa88db02d7c287e937182a71de2751cbb (patch) | |
tree | a283859e0ece61ef3d2c962b83d81cbff09a2134 | |
parent | 3a09f737ee056e022b4c3285852c663e9d294911 (diff) |
drm: extract legacy framebuffer remove
I got confused every time I audited what that lock_all is doing in
there until realizing it's for legacy kms only. Make that a notch more
obvious by having 2 entirely different paths.
While at it also move the atomic version of this into
drm_framebuffer.c, there's no reason it needs to be in drm_atomic.c.
That way it becomes a simple static function.
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Acked-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20170403083304.9083-15-daniel.vetter@ffwll.ch
-rw-r--r-- | drivers/gpu/drm/drm_atomic.c | 88 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_crtc_internal.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_framebuffer.c | 137 |
3 files changed, 115 insertions, 111 deletions
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 9afb14371ce0..f32506a7c1d6 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c | |||
@@ -2081,94 +2081,6 @@ static void complete_crtc_signaling(struct drm_device *dev, | |||
2081 | kfree(fence_state); | 2081 | kfree(fence_state); |
2082 | } | 2082 | } |
2083 | 2083 | ||
2084 | int drm_atomic_remove_fb(struct drm_framebuffer *fb) | ||
2085 | { | ||
2086 | struct drm_modeset_acquire_ctx ctx; | ||
2087 | struct drm_device *dev = fb->dev; | ||
2088 | struct drm_atomic_state *state; | ||
2089 | struct drm_plane *plane; | ||
2090 | struct drm_connector *conn; | ||
2091 | struct drm_connector_state *conn_state; | ||
2092 | int i, ret = 0; | ||
2093 | unsigned plane_mask; | ||
2094 | |||
2095 | state = drm_atomic_state_alloc(dev); | ||
2096 | if (!state) | ||
2097 | return -ENOMEM; | ||
2098 | |||
2099 | drm_modeset_acquire_init(&ctx, 0); | ||
2100 | state->acquire_ctx = &ctx; | ||
2101 | |||
2102 | retry: | ||
2103 | plane_mask = 0; | ||
2104 | ret = drm_modeset_lock_all_ctx(dev, &ctx); | ||
2105 | if (ret) | ||
2106 | goto unlock; | ||
2107 | |||
2108 | drm_for_each_plane(plane, dev) { | ||
2109 | struct drm_plane_state *plane_state; | ||
2110 | |||
2111 | if (plane->state->fb != fb) | ||
2112 | continue; | ||
2113 | |||
2114 | plane_state = drm_atomic_get_plane_state(state, plane); | ||
2115 | if (IS_ERR(plane_state)) { | ||
2116 | ret = PTR_ERR(plane_state); | ||
2117 | goto unlock; | ||
2118 | } | ||
2119 | |||
2120 | if (plane_state->crtc->primary == plane) { | ||
2121 | struct drm_crtc_state *crtc_state; | ||
2122 | |||
2123 | crtc_state = drm_atomic_get_existing_crtc_state(state, plane_state->crtc); | ||
2124 | |||
2125 | ret = drm_atomic_add_affected_connectors(state, plane_state->crtc); | ||
2126 | if (ret) | ||
2127 | goto unlock; | ||
2128 | |||
2129 | crtc_state->active = false; | ||
2130 | ret = drm_atomic_set_mode_for_crtc(crtc_state, NULL); | ||
2131 | if (ret) | ||
2132 | goto unlock; | ||
2133 | } | ||
2134 | |||
2135 | drm_atomic_set_fb_for_plane(plane_state, NULL); | ||
2136 | ret = drm_atomic_set_crtc_for_plane(plane_state, NULL); | ||
2137 | if (ret) | ||
2138 | goto unlock; | ||
2139 | |||
2140 | plane_mask |= BIT(drm_plane_index(plane)); | ||
2141 | |||
2142 | plane->old_fb = plane->fb; | ||
2143 | } | ||
2144 | |||
2145 | for_each_connector_in_state(state, conn, conn_state, i) { | ||
2146 | ret = drm_atomic_set_crtc_for_connector(conn_state, NULL); | ||
2147 | |||
2148 | if (ret) | ||
2149 | goto unlock; | ||
2150 | } | ||
2151 | |||
2152 | if (plane_mask) | ||
2153 | ret = drm_atomic_commit(state); | ||
2154 | |||
2155 | unlock: | ||
2156 | if (plane_mask) | ||
2157 | drm_atomic_clean_old_fb(dev, plane_mask, ret); | ||
2158 | |||
2159 | if (ret == -EDEADLK) { | ||
2160 | drm_modeset_backoff(&ctx); | ||
2161 | goto retry; | ||
2162 | } | ||
2163 | |||
2164 | drm_atomic_state_put(state); | ||
2165 | |||
2166 | drm_modeset_drop_locks(&ctx); | ||
2167 | drm_modeset_acquire_fini(&ctx); | ||
2168 | |||
2169 | return ret; | ||
2170 | } | ||
2171 | |||
2172 | int drm_mode_atomic_ioctl(struct drm_device *dev, | 2084 | int drm_mode_atomic_ioctl(struct drm_device *dev, |
2173 | void *data, struct drm_file *file_priv) | 2085 | void *data, struct drm_file *file_priv) |
2174 | { | 2086 | { |
diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h index 8c04275cf226..d077c5490041 100644 --- a/drivers/gpu/drm/drm_crtc_internal.h +++ b/drivers/gpu/drm/drm_crtc_internal.h | |||
@@ -182,7 +182,6 @@ int drm_atomic_get_property(struct drm_mode_object *obj, | |||
182 | struct drm_property *property, uint64_t *val); | 182 | struct drm_property *property, uint64_t *val); |
183 | int drm_mode_atomic_ioctl(struct drm_device *dev, | 183 | int drm_mode_atomic_ioctl(struct drm_device *dev, |
184 | void *data, struct drm_file *file_priv); | 184 | void *data, struct drm_file *file_priv); |
185 | int drm_atomic_remove_fb(struct drm_framebuffer *fb); | ||
186 | 185 | ||
187 | 186 | ||
188 | /* drm_plane.c */ | 187 | /* drm_plane.c */ |
diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c index e8f9c13a0afd..fc8ef42203ec 100644 --- a/drivers/gpu/drm/drm_framebuffer.c +++ b/drivers/gpu/drm/drm_framebuffer.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <drm/drmP.h> | 24 | #include <drm/drmP.h> |
25 | #include <drm/drm_auth.h> | 25 | #include <drm/drm_auth.h> |
26 | #include <drm/drm_framebuffer.h> | 26 | #include <drm/drm_framebuffer.h> |
27 | #include <drm/drm_atomic.h> | ||
27 | 28 | ||
28 | #include "drm_crtc_internal.h" | 29 | #include "drm_crtc_internal.h" |
29 | 30 | ||
@@ -755,6 +756,117 @@ void drm_framebuffer_cleanup(struct drm_framebuffer *fb) | |||
755 | } | 756 | } |
756 | EXPORT_SYMBOL(drm_framebuffer_cleanup); | 757 | EXPORT_SYMBOL(drm_framebuffer_cleanup); |
757 | 758 | ||
759 | static int atomic_remove_fb(struct drm_framebuffer *fb) | ||
760 | { | ||
761 | struct drm_modeset_acquire_ctx ctx; | ||
762 | struct drm_device *dev = fb->dev; | ||
763 | struct drm_atomic_state *state; | ||
764 | struct drm_plane *plane; | ||
765 | struct drm_connector *conn; | ||
766 | struct drm_connector_state *conn_state; | ||
767 | int i, ret = 0; | ||
768 | unsigned plane_mask; | ||
769 | |||
770 | state = drm_atomic_state_alloc(dev); | ||
771 | if (!state) | ||
772 | return -ENOMEM; | ||
773 | |||
774 | drm_modeset_acquire_init(&ctx, 0); | ||
775 | state->acquire_ctx = &ctx; | ||
776 | |||
777 | retry: | ||
778 | plane_mask = 0; | ||
779 | ret = drm_modeset_lock_all_ctx(dev, &ctx); | ||
780 | if (ret) | ||
781 | goto unlock; | ||
782 | |||
783 | drm_for_each_plane(plane, dev) { | ||
784 | struct drm_plane_state *plane_state; | ||
785 | |||
786 | if (plane->state->fb != fb) | ||
787 | continue; | ||
788 | |||
789 | plane_state = drm_atomic_get_plane_state(state, plane); | ||
790 | if (IS_ERR(plane_state)) { | ||
791 | ret = PTR_ERR(plane_state); | ||
792 | goto unlock; | ||
793 | } | ||
794 | |||
795 | if (plane_state->crtc->primary == plane) { | ||
796 | struct drm_crtc_state *crtc_state; | ||
797 | |||
798 | crtc_state = drm_atomic_get_existing_crtc_state(state, plane_state->crtc); | ||
799 | |||
800 | ret = drm_atomic_add_affected_connectors(state, plane_state->crtc); | ||
801 | if (ret) | ||
802 | goto unlock; | ||
803 | |||
804 | crtc_state->active = false; | ||
805 | ret = drm_atomic_set_mode_for_crtc(crtc_state, NULL); | ||
806 | if (ret) | ||
807 | goto unlock; | ||
808 | } | ||
809 | |||
810 | drm_atomic_set_fb_for_plane(plane_state, NULL); | ||
811 | ret = drm_atomic_set_crtc_for_plane(plane_state, NULL); | ||
812 | if (ret) | ||
813 | goto unlock; | ||
814 | |||
815 | plane_mask |= BIT(drm_plane_index(plane)); | ||
816 | |||
817 | plane->old_fb = plane->fb; | ||
818 | } | ||
819 | |||
820 | for_each_connector_in_state(state, conn, conn_state, i) { | ||
821 | ret = drm_atomic_set_crtc_for_connector(conn_state, NULL); | ||
822 | |||
823 | if (ret) | ||
824 | goto unlock; | ||
825 | } | ||
826 | |||
827 | if (plane_mask) | ||
828 | ret = drm_atomic_commit(state); | ||
829 | |||
830 | unlock: | ||
831 | if (plane_mask) | ||
832 | drm_atomic_clean_old_fb(dev, plane_mask, ret); | ||
833 | |||
834 | if (ret == -EDEADLK) { | ||
835 | drm_modeset_backoff(&ctx); | ||
836 | goto retry; | ||
837 | } | ||
838 | |||
839 | drm_atomic_state_put(state); | ||
840 | |||
841 | drm_modeset_drop_locks(&ctx); | ||
842 | drm_modeset_acquire_fini(&ctx); | ||
843 | |||
844 | return ret; | ||
845 | } | ||
846 | |||
847 | static void legacy_remove_fb(struct drm_framebuffer *fb) | ||
848 | { | ||
849 | struct drm_device *dev = fb->dev; | ||
850 | struct drm_crtc *crtc; | ||
851 | struct drm_plane *plane; | ||
852 | |||
853 | drm_modeset_lock_all(dev); | ||
854 | /* remove from any CRTC */ | ||
855 | drm_for_each_crtc(crtc, dev) { | ||
856 | if (crtc->primary->fb == fb) { | ||
857 | /* should turn off the crtc */ | ||
858 | if (drm_crtc_force_disable(crtc)) | ||
859 | DRM_ERROR("failed to reset crtc %p when fb was deleted\n", crtc); | ||
860 | } | ||
861 | } | ||
862 | |||
863 | drm_for_each_plane(plane, dev) { | ||
864 | if (plane->fb == fb) | ||
865 | drm_plane_force_disable(plane); | ||
866 | } | ||
867 | drm_modeset_unlock_all(dev); | ||
868 | } | ||
869 | |||
758 | /** | 870 | /** |
759 | * drm_framebuffer_remove - remove and unreference a framebuffer object | 871 | * drm_framebuffer_remove - remove and unreference a framebuffer object |
760 | * @fb: framebuffer to remove | 872 | * @fb: framebuffer to remove |
@@ -770,8 +882,6 @@ EXPORT_SYMBOL(drm_framebuffer_cleanup); | |||
770 | void drm_framebuffer_remove(struct drm_framebuffer *fb) | 882 | void drm_framebuffer_remove(struct drm_framebuffer *fb) |
771 | { | 883 | { |
772 | struct drm_device *dev; | 884 | struct drm_device *dev; |
773 | struct drm_crtc *crtc; | ||
774 | struct drm_plane *plane; | ||
775 | 885 | ||
776 | if (!fb) | 886 | if (!fb) |
777 | return; | 887 | return; |
@@ -797,29 +907,12 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb) | |||
797 | */ | 907 | */ |
798 | if (drm_framebuffer_read_refcount(fb) > 1) { | 908 | if (drm_framebuffer_read_refcount(fb) > 1) { |
799 | if (drm_drv_uses_atomic_modeset(dev)) { | 909 | if (drm_drv_uses_atomic_modeset(dev)) { |
800 | int ret = drm_atomic_remove_fb(fb); | 910 | int ret = atomic_remove_fb(fb); |
801 | WARN(ret, "atomic remove_fb failed with %i\n", ret); | 911 | WARN(ret, "atomic remove_fb failed with %i\n", ret); |
802 | goto out; | 912 | } else |
803 | } | 913 | legacy_remove_fb(fb); |
804 | |||
805 | drm_modeset_lock_all(dev); | ||
806 | /* remove from any CRTC */ | ||
807 | drm_for_each_crtc(crtc, dev) { | ||
808 | if (crtc->primary->fb == fb) { | ||
809 | /* should turn off the crtc */ | ||
810 | if (drm_crtc_force_disable(crtc)) | ||
811 | DRM_ERROR("failed to reset crtc %p when fb was deleted\n", crtc); | ||
812 | } | ||
813 | } | ||
814 | |||
815 | drm_for_each_plane(plane, dev) { | ||
816 | if (plane->fb == fb) | ||
817 | drm_plane_force_disable(plane); | ||
818 | } | ||
819 | drm_modeset_unlock_all(dev); | ||
820 | } | 914 | } |
821 | 915 | ||
822 | out: | ||
823 | drm_framebuffer_put(fb); | 916 | drm_framebuffer_put(fb); |
824 | } | 917 | } |
825 | EXPORT_SYMBOL(drm_framebuffer_remove); | 918 | EXPORT_SYMBOL(drm_framebuffer_remove); |