Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm: handle kernel fences in drm_gem_plane_helper_prepare_fb v2

drm_gem_plane_helper_prepare_fb() was using
drm_atomic_set_fence_for_plane() which ignores all implicit fences when an
explicit fence is already set. That's rather unfortunate when the fb still
has a kernel fence we need to wait for to avoid presenting garbage on the
screen.

So instead update the fence in the plane state directly. While at it also
take care of all potential GEM objects and not just the first one.

Also remove the now unused drm_atomic_set_fence_for_plane() function, new
drivers should probably use the atomic helpers directly.

v2: improve kerneldoc, use local variable and num_planes, WARN_ON_ONCE
on missing planes.

Signed-off-by: Christian König <christian.koenig@amd.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> (v1)
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20220429134230.24334-1-christian.koenig@amd.com

+62 -64
+5 -42
drivers/gpu/drm/drm_atomic_uapi.c
··· 255 255 EXPORT_SYMBOL(drm_atomic_set_fb_for_plane); 256 256 257 257 /** 258 - * drm_atomic_set_fence_for_plane - set fence for plane 259 - * @plane_state: atomic state object for the plane 260 - * @fence: dma_fence to use for the plane 261 - * 262 - * Helper to setup the plane_state fence in case it is not set yet. 263 - * By using this drivers doesn't need to worry if the user choose 264 - * implicit or explicit fencing. 265 - * 266 - * This function will not set the fence to the state if it was set 267 - * via explicit fencing interfaces on the atomic ioctl. In that case it will 268 - * drop the reference to the fence as we are not storing it anywhere. 269 - * Otherwise, if &drm_plane_state.fence is not set this function we just set it 270 - * with the received implicit fence. In both cases this function consumes a 271 - * reference for @fence. 272 - * 273 - * This way explicit fencing can be used to overrule implicit fencing, which is 274 - * important to make explicit fencing use-cases work: One example is using one 275 - * buffer for 2 screens with different refresh rates. Implicit fencing will 276 - * clamp rendering to the refresh rate of the slower screen, whereas explicit 277 - * fence allows 2 independent render and display loops on a single buffer. If a 278 - * driver allows obeys both implicit and explicit fences for plane updates, then 279 - * it will break all the benefits of explicit fencing. 280 - */ 281 - void 282 - drm_atomic_set_fence_for_plane(struct drm_plane_state *plane_state, 283 - struct dma_fence *fence) 284 - { 285 - if (plane_state->fence) { 286 - dma_fence_put(fence); 287 - return; 288 - } 289 - 290 - plane_state->fence = fence; 291 - } 292 - EXPORT_SYMBOL(drm_atomic_set_fence_for_plane); 293 - 294 - /** 295 258 * drm_atomic_set_crtc_for_connector - set CRTC for connector 296 259 * @conn_state: atomic state object for the connector 297 260 * @crtc: CRTC to use for the connector ··· 1040 1077 * 1041 1078 * As a contrast, with implicit fencing the kernel keeps track of any 1042 1079 * ongoing rendering, and automatically ensures that the atomic update waits 1043 - * for any pending rendering to complete. For shared buffers represented with 1044 - * a &struct dma_buf this is tracked in &struct dma_resv. 1045 - * Implicit syncing is how Linux traditionally worked (e.g. DRI2/3 on X.org), 1046 - * whereas explicit fencing is what Android wants. 1080 + * for any pending rendering to complete. This is usually tracked in &struct 1081 + * dma_resv which can also contain mandatory kernel fences. Implicit syncing 1082 + * is how Linux traditionally worked (e.g. DRI2/3 on X.org), whereas explicit 1083 + * fencing is what Android wants. 1047 1084 * 1048 1085 * "IN_FENCE_FD”: 1049 1086 * Use this property to pass a fence that DRM should wait on before ··· 1058 1095 * 1059 1096 * On the driver side the fence is stored on the @fence parameter of 1060 1097 * &struct drm_plane_state. Drivers which also support implicit fencing 1061 - * should set the implicit fence using drm_atomic_set_fence_for_plane(), 1098 + * should extract the implicit fence using drm_gem_plane_helper_prepare_fb(), 1062 1099 * to make sure there's consistent behaviour between drivers in precedence 1063 1100 * of implicit vs. explicit fencing. 1064 1101 *
+56 -17
drivers/gpu/drm/drm_gem_atomic_helper.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0-or-later 2 2 3 3 #include <linux/dma-resv.h> 4 + #include <linux/dma-fence-chain.h> 4 5 5 6 #include <drm/drm_atomic_state_helper.h> 6 7 #include <drm/drm_atomic_uapi.h> ··· 138 137 * 139 138 * This function is the default implementation for GEM drivers of 140 139 * &drm_plane_helper_funcs.prepare_fb if no callback is provided. 141 - * 142 - * See drm_atomic_set_fence_for_plane() for a discussion of implicit and 143 - * explicit fencing in atomic modeset updates. 144 140 */ 145 - int drm_gem_plane_helper_prepare_fb(struct drm_plane *plane, struct drm_plane_state *state) 141 + int drm_gem_plane_helper_prepare_fb(struct drm_plane *plane, 142 + struct drm_plane_state *state) 146 143 { 147 - struct drm_gem_object *obj; 148 - struct dma_fence *fence; 144 + struct dma_fence *fence = dma_fence_get(state->fence); 145 + enum dma_resv_usage usage; 146 + size_t i; 149 147 int ret; 150 148 151 149 if (!state->fb) 152 150 return 0; 153 151 154 - obj = drm_gem_fb_get_obj(state->fb, 0); 155 - ret = dma_resv_get_singleton(obj->resv, DMA_RESV_USAGE_WRITE, &fence); 156 - if (ret) 157 - return ret; 158 - 159 - /* TODO: drm_atomic_set_fence_for_plane() should be changed to be able 160 - * to handle more fences in general for multiple BOs per fb. 152 + /* 153 + * Only add the kernel fences here if there is already a fence set via 154 + * explicit fencing interfaces on the atomic ioctl. 155 + * 156 + * This way explicit fencing can be used to overrule implicit fencing, 157 + * which is important to make explicit fencing use-cases work: One 158 + * example is using one buffer for 2 screens with different refresh 159 + * rates. Implicit fencing will clamp rendering to the refresh rate of 160 + * the slower screen, whereas explicit fence allows 2 independent 161 + * render and display loops on a single buffer. If a driver allows 162 + * obeys both implicit and explicit fences for plane updates, then it 163 + * will break all the benefits of explicit fencing. 161 164 */ 162 - drm_atomic_set_fence_for_plane(state, fence); 165 + usage = fence ? DMA_RESV_USAGE_KERNEL : DMA_RESV_USAGE_WRITE; 166 + 167 + for (i = 0; i < state->fb->format->num_planes; ++i) { 168 + struct drm_gem_object *obj = drm_gem_fb_get_obj(state->fb, i); 169 + struct dma_fence *new; 170 + 171 + if (WARN_ON_ONCE(!obj)) 172 + continue; 173 + 174 + ret = dma_resv_get_singleton(obj->resv, usage, &new); 175 + if (ret) 176 + goto error; 177 + 178 + if (new && fence) { 179 + struct dma_fence_chain *chain = dma_fence_chain_alloc(); 180 + 181 + if (!chain) { 182 + ret = -ENOMEM; 183 + goto error; 184 + } 185 + 186 + dma_fence_chain_init(chain, fence, new, 1); 187 + fence = &chain->base; 188 + 189 + } else if (new) { 190 + fence = new; 191 + } 192 + } 193 + 194 + dma_fence_put(state->fence); 195 + state->fence = fence; 163 196 return 0; 197 + 198 + error: 199 + dma_fence_put(fence); 200 + return ret; 164 201 } 165 202 EXPORT_SYMBOL_GPL(drm_gem_plane_helper_prepare_fb); 166 203 ··· 207 168 * @pipe: Simple display pipe 208 169 * @plane_state: Plane state 209 170 * 210 - * This function uses drm_gem_plane_helper_prepare_fb() to extract the exclusive fence 211 - * from &drm_gem_object.resv and attaches it to plane state for the atomic 171 + * This function uses drm_gem_plane_helper_prepare_fb() to extract the fences 172 + * from &drm_gem_object.resv and attaches them to the plane state for the atomic 212 173 * helper to wait on. This is necessary to correctly implement implicit 213 174 * synchronization for any buffers shared as a struct &dma_buf. Drivers can use 214 175 * this as their &drm_simple_display_pipe_funcs.prepare_fb callback. 215 176 * 216 - * See drm_atomic_set_fence_for_plane() for a discussion of implicit and 177 + * See drm_gem_plane_helper_prepare_fb() for a discussion of implicit and 217 178 * explicit fencing in atomic modeset updates. 218 179 */ 219 180 int drm_gem_simple_display_pipe_prepare_fb(struct drm_simple_display_pipe *pipe,
-2
include/drm/drm_atomic_uapi.h
··· 49 49 struct drm_crtc *crtc); 50 50 void drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state, 51 51 struct drm_framebuffer *fb); 52 - void drm_atomic_set_fence_for_plane(struct drm_plane_state *plane_state, 53 - struct dma_fence *fence); 54 52 int __must_check 55 53 drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state, 56 54 struct drm_crtc *crtc);
+1 -3
include/drm/drm_plane.h
··· 74 74 * 75 75 * Optional fence to wait for before scanning out @fb. The core atomic 76 76 * code will set this when userspace is using explicit fencing. Do not 77 - * write this field directly for a driver's implicit fence, use 78 - * drm_atomic_set_fence_for_plane() to ensure that an explicit fence is 79 - * preserved. 77 + * write this field directly for a driver's implicit fence. 80 78 * 81 79 * Drivers should store any implicit fence in this from their 82 80 * &drm_plane_helper_funcs.prepare_fb callback. See drm_gem_plane_helper_prepare_fb()