diff options
| -rw-r--r-- | drivers/gpu/drm/drm_atomic.c | 106 | ||||
| -rw-r--r-- | drivers/gpu/drm/drm_crtc_internal.h | 1 | ||||
| -rw-r--r-- | drivers/gpu/drm/drm_framebuffer.c | 7 | ||||
| -rw-r--r-- | include/uapi/linux/Kbuild | 1 |
4 files changed, 115 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 | ||
| 2049 | int 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 | |||
| 2067 | retry: | ||
| 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 | |||
| 2127 | unlock: | ||
| 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 | |||
| 2049 | int drm_mode_atomic_ioctl(struct drm_device *dev, | 2155 | int 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); |
| 184 | int drm_mode_atomic_ioctl(struct drm_device *dev, | 184 | int drm_mode_atomic_ioctl(struct drm_device *dev, |
| 185 | void *data, struct drm_file *file_priv); | 185 | void *data, struct drm_file *file_priv); |
| 186 | int 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 | ||
| 799 | out: | ||
| 793 | drm_framebuffer_unreference(fb); | 800 | drm_framebuffer_unreference(fb); |
| 794 | } | 801 | } |
| 795 | EXPORT_SYMBOL(drm_framebuffer_remove); | 802 | EXPORT_SYMBOL(drm_framebuffer_remove); |
diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild index f330ba4547cf..900129c8f6cf 100644 --- a/include/uapi/linux/Kbuild +++ b/include/uapi/linux/Kbuild | |||
| @@ -109,6 +109,7 @@ header-y += dlm_netlink.h | |||
| 109 | header-y += dlm_plock.h | 109 | header-y += dlm_plock.h |
| 110 | header-y += dm-ioctl.h | 110 | header-y += dm-ioctl.h |
| 111 | header-y += dm-log-userspace.h | 111 | header-y += dm-log-userspace.h |
| 112 | header-y += dma-buf.h | ||
| 112 | header-y += dn.h | 113 | header-y += dn.h |
| 113 | header-y += dqblk_xfs.h | 114 | header-y += dqblk_xfs.h |
| 114 | header-y += edd.h | 115 | header-y += edd.h |
