aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaarten Lankhorst <maarten.lankhorst@linux.intel.com>2017-01-25 06:30:47 -0500
committerJani Nikula <jani.nikula@intel.com>2017-02-15 08:40:57 -0500
commit1592364de3912dad264262f4bcc61552984c9523 (patch)
treeaf56aa8c0edc37d11e55f7fe82aa48a5dbdfeaf4
parent2220fc1ab363e6fab1f321430d69be17a8b92bd7 (diff)
drm: Resurrect atomic rmfb code, v3
This was somehow lost between v3 and the merged version in Maarten's patch merged as: commit f2d580b9a8149735cbc4b59c4a8df60173658140 Author: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Date: Wed May 4 14:38:26 2016 +0200 drm/core: Do not preserve framebuffer on rmfb, v4. This introduces a slight behavioral change to rmfb. Instead of disabling a crtc when the primary plane is disabled, we try to preserve it. Apart from old versions of the vmwgfx xorg driver, there is nothing depending on rmfb disabling a crtc. Since vmwgfx is a legacy driver we can safely only disable the plane with atomic. If this commit is rejected by the driver then we will still fall back to the old behavior and turn off the crtc. v2: - Remove plane->fb assignment, done by drm_atomic_clean_old_fb. - Add WARN_ON when atomic_remove_fb fails. - Always call drm_atomic_state_put. v3: - Use drm_drv_uses_atomic_modeset - Handle the case where the first plane-disable-only commit fails with -EINVAL. Some drivers do not support this, fall back to disabling all crtc's in this case. Signed-off-by: Daniel Vetter <daniel.vetter@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Signed-off-by: Jani Nikula <jani.nikula@intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/66fc3da5-697b-1613-0a67-a5293209f0dc@linux.intel.com
-rw-r--r--drivers/gpu/drm/drm_atomic.c106
-rw-r--r--drivers/gpu/drm/drm_crtc_internal.h1
-rw-r--r--drivers/gpu/drm/drm_framebuffer.c7
3 files changed, 114 insertions, 0 deletions
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index c97588a28216..11f102e7ddfd 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -2046,6 +2046,112 @@ static void complete_crtc_signaling(struct drm_device *dev,
2046 kfree(fence_state); 2046 kfree(fence_state);
2047} 2047}
2048 2048
2049int drm_atomic_remove_fb(struct drm_framebuffer *fb)
2050{
2051 struct drm_modeset_acquire_ctx ctx;
2052 struct drm_device *dev = fb->dev;
2053 struct drm_atomic_state *state;
2054 struct drm_plane *plane;
2055 struct drm_connector *conn;
2056 struct drm_connector_state *conn_state;
2057 int i, ret = 0;
2058 unsigned plane_mask, disable_crtcs = false;
2059
2060 state = drm_atomic_state_alloc(dev);
2061 if (!state)
2062 return -ENOMEM;
2063
2064 drm_modeset_acquire_init(&ctx, 0);
2065 state->acquire_ctx = &ctx;
2066
2067retry:
2068 plane_mask = 0;
2069 ret = drm_modeset_lock_all_ctx(dev, &ctx);
2070 if (ret)
2071 goto unlock;
2072
2073 drm_for_each_plane(plane, dev) {
2074 struct drm_plane_state *plane_state;
2075
2076 if (plane->state->fb != fb)
2077 continue;
2078
2079 plane_state = drm_atomic_get_plane_state(state, plane);
2080 if (IS_ERR(plane_state)) {
2081 ret = PTR_ERR(plane_state);
2082 goto unlock;
2083 }
2084
2085 /*
2086 * Some drivers do not support keeping crtc active with the
2087 * primary plane disabled. If we fail to commit with -EINVAL
2088 * then we will try to perform the same commit but with all
2089 * crtc's disabled for primary planes as well.
2090 */
2091 if (disable_crtcs && plane_state->crtc->primary == plane) {
2092 struct drm_crtc_state *crtc_state;
2093
2094 crtc_state = drm_atomic_get_existing_crtc_state(state, plane_state->crtc);
2095
2096 ret = drm_atomic_add_affected_connectors(state, plane_state->crtc);
2097 if (ret)
2098 goto unlock;
2099
2100 crtc_state->active = false;
2101 ret = drm_atomic_set_mode_for_crtc(crtc_state, NULL);
2102 if (ret)
2103 goto unlock;
2104 }
2105
2106 drm_atomic_set_fb_for_plane(plane_state, NULL);
2107 ret = drm_atomic_set_crtc_for_plane(plane_state, NULL);
2108 if (ret)
2109 goto unlock;
2110
2111 plane_mask |= BIT(drm_plane_index(plane));
2112
2113 plane->old_fb = plane->fb;
2114 }
2115
2116 /* This list is only not empty when disable_crtcs is set. */
2117 for_each_connector_in_state(state, conn, conn_state, i) {
2118 ret = drm_atomic_set_crtc_for_connector(conn_state, NULL);
2119
2120 if (ret)
2121 goto unlock;
2122 }
2123
2124 if (plane_mask)
2125 ret = drm_atomic_commit(state);
2126
2127unlock:
2128 if (plane_mask)
2129 drm_atomic_clean_old_fb(dev, plane_mask, ret);
2130
2131 if (ret == -EDEADLK) {
2132 drm_modeset_backoff(&ctx);
2133 goto retry;
2134 }
2135
2136 drm_atomic_state_put(state);
2137
2138 if (ret == -EINVAL && !disable_crtcs) {
2139 disable_crtcs = true;
2140
2141 state = drm_atomic_state_alloc(dev);
2142 if (state) {
2143 state->acquire_ctx = &ctx;
2144 goto retry;
2145 }
2146 ret = -ENOMEM;
2147 }
2148
2149 drm_modeset_drop_locks(&ctx);
2150 drm_modeset_acquire_fini(&ctx);
2151
2152 return ret;
2153}
2154
2049int drm_mode_atomic_ioctl(struct drm_device *dev, 2155int drm_mode_atomic_ioctl(struct drm_device *dev,
2050 void *data, struct drm_file *file_priv) 2156 void *data, struct drm_file *file_priv)
2051{ 2157{
diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h
index 955c5690bf64..e0678f8a51cf 100644
--- a/drivers/gpu/drm/drm_crtc_internal.h
+++ b/drivers/gpu/drm/drm_crtc_internal.h
@@ -183,6 +183,7 @@ int drm_atomic_get_property(struct drm_mode_object *obj,
183 struct drm_property *property, uint64_t *val); 183 struct drm_property *property, uint64_t *val);
184int drm_mode_atomic_ioctl(struct drm_device *dev, 184int drm_mode_atomic_ioctl(struct drm_device *dev,
185 void *data, struct drm_file *file_priv); 185 void *data, struct drm_file *file_priv);
186int drm_atomic_remove_fb(struct drm_framebuffer *fb);
186 187
187 188
188/* drm_plane.c */ 189/* drm_plane.c */
diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c
index 28a0108a1ab8..c0e593a7f9b4 100644
--- a/drivers/gpu/drm/drm_framebuffer.c
+++ b/drivers/gpu/drm/drm_framebuffer.c
@@ -773,6 +773,12 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)
773 * in this manner. 773 * in this manner.
774 */ 774 */
775 if (drm_framebuffer_read_refcount(fb) > 1) { 775 if (drm_framebuffer_read_refcount(fb) > 1) {
776 if (drm_drv_uses_atomic_modeset(dev)) {
777 int ret = drm_atomic_remove_fb(fb);
778 WARN(ret, "atomic remove_fb failed with %i\n", ret);
779 goto out;
780 }
781
776 drm_modeset_lock_all(dev); 782 drm_modeset_lock_all(dev);
777 /* remove from any CRTC */ 783 /* remove from any CRTC */
778 drm_for_each_crtc(crtc, dev) { 784 drm_for_each_crtc(crtc, dev) {
@@ -790,6 +796,7 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)
790 drm_modeset_unlock_all(dev); 796 drm_modeset_unlock_all(dev);
791 } 797 }
792 798
799out:
793 drm_framebuffer_unreference(fb); 800 drm_framebuffer_unreference(fb);
794} 801}
795EXPORT_SYMBOL(drm_framebuffer_remove); 802EXPORT_SYMBOL(drm_framebuffer_remove);