1 /*
2  * Copyright (C) 2014 Red Hat
3  * Copyright (C) 2014 Intel Corp.
4  * Copyright (C) 2018 Intel Corp.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22  * OTHER DEALINGS IN THE SOFTWARE.
23  *
24  * Authors:
25  * Rob Clark <robdclark@gmail.com>
26  * Daniel Vetter <daniel.vetter@ffwll.ch>
27  */
28 
29 #include <drm/drm_atomic_uapi.h>
30 #include <drm/drm_atomic.h>
31 #include <drm/drm_print.h>
32 #include <drm/drm_drv.h>
33 #include <drm/drm_writeback.h>
34 #include <drm/drm_vblank.h>
35 
36 #include <linux/dma-fence.h>
37 #include <linux/uaccess.h>
38 #include <linux/sync_file.h>
39 #include <linux/file.h>
40 
41 #include "drm_crtc_internal.h"
42 
43 /**
44  * DOC: overview
45  *
46  * This file contains the marshalling and demarshalling glue for the atomic UAPI
47  * in all its forms: The monster ATOMIC IOCTL itself, code for GET_PROPERTY and
48  * SET_PROPERTY IOCTLs. Plus interface functions for compatibility helpers and
49  * drivers which have special needs to construct their own atomic updates, e.g.
50  * for load detect or similiar.
51  */
52 
53 /**
54  * drm_atomic_set_mode_for_crtc - set mode for CRTC
55  * @state: the CRTC whose incoming state to update
56  * @mode: kernel-internal mode to use for the CRTC, or NULL to disable
57  *
58  * Set a mode (originating from the kernel) on the desired CRTC state and update
59  * the enable property.
60  *
61  * RETURNS:
62  * Zero on success, error code on failure. Cannot return -EDEADLK.
63  */
drm_atomic_set_mode_for_crtc(struct drm_crtc_state *state, const struct drm_display_mode *mode)64 int drm_atomic_set_mode_for_crtc(struct drm_crtc_state *state, const struct drm_display_mode *mode)
65 {
66     struct drm_crtc *crtc = state->crtc;
67     struct drm_mode_modeinfo umode;
68 
69     /* Early return for no change. */
70     if (mode && memcmp(&state->mode, mode, sizeof(*mode)) == 0) {
71         return 0;
72     }
73 
74     drm_property_blob_put(state->mode_blob);
75     state->mode_blob = NULL;
76 
77     if (mode) {
78         drm_mode_convert_to_umode(&umode, mode);
79         state->mode_blob = drm_property_create_blob(state->crtc->dev, sizeof(umode), &umode);
80         if (IS_ERR(state->mode_blob)) {
81             return PTR_ERR(state->mode_blob);
82         }
83 
84         drm_mode_copy(&state->mode, mode);
85         state->enable = true;
86         DRM_DEBUG_ATOMIC("Set [MODE:%s] for [CRTC:%d:%s] state %p\n", mode->name, crtc->base.id, crtc->name, state);
87     } else {
88         memset(&state->mode, 0, sizeof(state->mode));
89         state->enable = false;
90         DRM_DEBUG_ATOMIC("Set [NOMODE] for [CRTC:%d:%s] state %p\n", crtc->base.id, crtc->name, state);
91     }
92 
93     return 0;
94 }
95 EXPORT_SYMBOL(drm_atomic_set_mode_for_crtc);
96 
97 /**
98  * drm_atomic_set_mode_prop_for_crtc - set mode for CRTC
99  * @state: the CRTC whose incoming state to update
100  * @blob: pointer to blob property to use for mode
101  *
102  * Set a mode (originating from a blob property) on the desired CRTC state.
103  * This function will take a reference on the blob property for the CRTC state,
104  * and release the reference held on the state's existing mode property, if any
105  * was set.
106  *
107  * RETURNS:
108  * Zero on success, error code on failure. Cannot return -EDEADLK.
109  */
drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state, struct drm_property_blob *blob)110 int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state, struct drm_property_blob *blob)
111 {
112     struct drm_crtc *crtc = state->crtc;
113 
114     if (blob == state->mode_blob) {
115         return 0;
116     }
117 
118     drm_property_blob_put(state->mode_blob);
119     state->mode_blob = NULL;
120 
121     memset(&state->mode, 0, sizeof(state->mode));
122 
123     if (blob) {
124         int ret;
125 
126         if (blob->length != sizeof(struct drm_mode_modeinfo)) {
127             DRM_DEBUG_ATOMIC("[CRTC:%d:%s] bad mode blob length: %zu\n", crtc->base.id, crtc->name, blob->length);
128             return -EINVAL;
129         }
130 
131         ret = drm_mode_convert_umode(crtc->dev, &state->mode, blob->data);
132         if (ret) {
133             DRM_DEBUG_ATOMIC("[CRTC:%d:%s] invalid mode (ret=%d, status=%s):\n", crtc->base.id, crtc->name, ret,
134                              drm_get_mode_status_name(state->mode.status));
135             drm_mode_debug_printmodeline(&state->mode);
136             return -EINVAL;
137         }
138 
139         state->mode_blob = drm_property_blob_get(blob);
140         state->enable = true;
141         DRM_DEBUG_ATOMIC("Set [MODE:%s] for [CRTC:%d:%s] state %p\n", state->mode.name, crtc->base.id, crtc->name,
142                          state);
143     } else {
144         state->enable = false;
145         DRM_DEBUG_ATOMIC("Set [NOMODE] for [CRTC:%d:%s] state %p\n", crtc->base.id, crtc->name, state);
146     }
147 
148     return 0;
149 }
150 EXPORT_SYMBOL(drm_atomic_set_mode_prop_for_crtc);
151 
152 /**
153  * drm_atomic_set_crtc_for_plane - set CRTC for plane
154  * @plane_state: the plane whose incoming state to update
155  * @crtc: CRTC to use for the plane
156  *
157  * Changing the assigned CRTC for a plane requires us to grab the lock and state
158  * for the new CRTC, as needed. This function takes care of all these details
159  * besides updating the pointer in the state object itself.
160  *
161  * Returns:
162  * 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK
163  * then the w/w mutex code has detected a deadlock and the entire atomic
164  * sequence must be restarted. All other errors are fatal.
165  */
drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state, struct drm_crtc *crtc)166 int drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state, struct drm_crtc *crtc)
167 {
168     struct drm_plane *plane = plane_state->plane;
169     struct drm_crtc_state *crtc_state;
170     /* Nothing to do for same crtc */
171     if (plane_state->crtc == crtc) {
172         return 0;
173     }
174     if (plane_state->crtc) {
175         crtc_state = drm_atomic_get_crtc_state(plane_state->state, plane_state->crtc);
176         if (WARN_ON(IS_ERR(crtc_state))) {
177             return PTR_ERR(crtc_state);
178         }
179 
180         crtc_state->plane_mask &= ~drm_plane_mask(plane);
181     }
182 
183     plane_state->crtc = crtc;
184 
185     if (crtc) {
186         crtc_state = drm_atomic_get_crtc_state(plane_state->state, crtc);
187         if (IS_ERR(crtc_state)) {
188             return PTR_ERR(crtc_state);
189         }
190         crtc_state->plane_mask |= drm_plane_mask(plane);
191     }
192 
193     if (crtc) {
194         DRM_DEBUG_ATOMIC("Link [PLANE:%d:%s] state %p to [CRTC:%d:%s]\n", plane->base.id, plane->name, plane_state,
195                          crtc->base.id, crtc->name);
196     } else {
197         DRM_DEBUG_ATOMIC("Link [PLANE:%d:%s] state %p to [NOCRTC]\n", plane->base.id, plane->name, plane_state);
198     }
199 
200     return 0;
201 }
202 EXPORT_SYMBOL(drm_atomic_set_crtc_for_plane);
203 
204 /**
205  * drm_atomic_set_fb_for_plane - set framebuffer for plane
206  * @plane_state: atomic state object for the plane
207  * @fb: fb to use for the plane
208  *
209  * Changing the assigned framebuffer for a plane requires us to grab a reference
210  * to the new fb and drop the reference to the old fb, if there is one. This
211  * function takes care of all these details besides updating the pointer in the
212  * state object itself.
213  */
drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state, struct drm_framebuffer *fb)214 void drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state, struct drm_framebuffer *fb)
215 {
216     struct drm_plane *plane = plane_state->plane;
217 
218     if (fb) {
219         DRM_DEBUG_ATOMIC("Set [FB:%d] for [PLANE:%d:%s] state %p\n", fb->base.id, plane->base.id, plane->name,
220                          plane_state);
221     } else {
222         DRM_DEBUG_ATOMIC("Set [NOFB] for [PLANE:%d:%s] state %p\n", plane->base.id, plane->name, plane_state);
223     }
224 
225     drm_framebuffer_assign(&plane_state->fb, fb);
226 }
227 EXPORT_SYMBOL(drm_atomic_set_fb_for_plane);
228 
229 /**
230  * drm_atomic_set_fence_for_plane - set fence for plane
231  * @plane_state: atomic state object for the plane
232  * @fence: dma_fence to use for the plane
233  *
234  * Helper to setup the plane_state fence in case it is not set yet.
235  * By using this drivers doesn't need to worry if the user choose
236  * implicit or explicit fencing.
237  *
238  * This function will not set the fence to the state if it was set
239  * via explicit fencing interfaces on the atomic ioctl. In that case it will
240  * drop the reference to the fence as we are not storing it anywhere.
241  * Otherwise, if &drm_plane_state.fence is not set this function we just set it
242  * with the received implicit fence. In both cases this function consumes a
243  * reference for @fence.
244  *
245  * This way explicit fencing can be used to overrule implicit fencing, which is
246  * important to make explicit fencing use-cases work: One example is using one
247  * buffer for 2 screens with different refresh rates. Implicit fencing will
248  * clamp rendering to the refresh rate of the slower screen, whereas explicit
249  * fence allows 2 independent render and display loops on a single buffer. If a
250  * driver allows obeys both implicit and explicit fences for plane updates, then
251  * it will break all the benefits of explicit fencing.
252  */
drm_atomic_set_fence_for_plane(struct drm_plane_state *plane_state, struct dma_fence *fence)253 void drm_atomic_set_fence_for_plane(struct drm_plane_state *plane_state, struct dma_fence *fence)
254 {
255     if (plane_state->fence) {
256         dma_fence_put(fence);
257         return;
258     }
259 
260     plane_state->fence = fence;
261 }
262 EXPORT_SYMBOL(drm_atomic_set_fence_for_plane);
263 
264 /**
265  * drm_atomic_set_crtc_for_connector - set CRTC for connector
266  * @conn_state: atomic state object for the connector
267  * @crtc: CRTC to use for the connector
268  *
269  * Changing the assigned CRTC for a connector requires us to grab the lock and
270  * state for the new CRTC, as needed. This function takes care of all these
271  * details besides updating the pointer in the state object itself.
272  *
273  * Returns:
274  * 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK
275  * then the w/w mutex code has detected a deadlock and the entire atomic
276  * sequence must be restarted. All other errors are fatal.
277  */
drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state, struct drm_crtc *crtc)278 int drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state, struct drm_crtc *crtc)
279 {
280     struct drm_connector *connector = conn_state->connector;
281     struct drm_crtc_state *crtc_state;
282 
283     if (conn_state->crtc == crtc) {
284         return 0;
285     }
286 
287     if (conn_state->crtc) {
288         crtc_state = drm_atomic_get_new_crtc_state(conn_state->state, conn_state->crtc);
289 
290         crtc_state->connector_mask &= ~drm_connector_mask(conn_state->connector);
291 
292         drm_connector_put(conn_state->connector);
293         conn_state->crtc = NULL;
294     }
295 
296     if (crtc) {
297         crtc_state = drm_atomic_get_crtc_state(conn_state->state, crtc);
298         if (IS_ERR(crtc_state)) {
299             return PTR_ERR(crtc_state);
300         }
301 
302         crtc_state->connector_mask |= drm_connector_mask(conn_state->connector);
303 
304         drm_connector_get(conn_state->connector);
305         conn_state->crtc = crtc;
306 
307         DRM_DEBUG_ATOMIC("Link [CONNECTOR:%d:%s] state %p to [CRTC:%d:%s]\n", connector->base.id, connector->name,
308                          conn_state, crtc->base.id, crtc->name);
309     } else {
310         DRM_DEBUG_ATOMIC("Link [CONNECTOR:%d:%s] state %p to [NOCRTC]\n", connector->base.id, connector->name,
311                          conn_state);
312     }
313 
314     return 0;
315 }
316 EXPORT_SYMBOL(drm_atomic_set_crtc_for_connector);
317 
set_out_fence_for_crtc(struct drm_atomic_state *state, struct drm_crtc *crtc, s32 __user *fence_ptr)318 static void set_out_fence_for_crtc(struct drm_atomic_state *state, struct drm_crtc *crtc, s32 __user *fence_ptr)
319 {
320     state->crtcs[drm_crtc_index(crtc)].out_fence_ptr = fence_ptr;
321 }
322 
get_out_fence_for_crtc(struct drm_atomic_state *state, struct drm_crtc *crtc)323 static s32 __user *get_out_fence_for_crtc(struct drm_atomic_state *state, struct drm_crtc *crtc)
324 {
325     s32 __user *fence_ptr;
326 
327     fence_ptr = state->crtcs[drm_crtc_index(crtc)].out_fence_ptr;
328     state->crtcs[drm_crtc_index(crtc)].out_fence_ptr = NULL;
329 
330     return fence_ptr;
331 }
332 
set_out_fence_for_connector(struct drm_atomic_state *state, struct drm_connector *connector, s32 __user *fence_ptr)333 static int set_out_fence_for_connector(struct drm_atomic_state *state, struct drm_connector *connector,
334                                        s32 __user *fence_ptr)
335 {
336     unsigned int index = drm_connector_index(connector);
337 
338     if (!fence_ptr) {
339         return 0;
340     }
341 
342     if (put_user(-1, fence_ptr)) {
343         return -EFAULT;
344     }
345 
346     state->connectors[index].out_fence_ptr = fence_ptr;
347 
348     return 0;
349 }
350 
get_out_fence_for_connector(struct drm_atomic_state *state, struct drm_connector *connector)351 static s32 __user *get_out_fence_for_connector(struct drm_atomic_state *state, struct drm_connector *connector)
352 {
353     unsigned int index = drm_connector_index(connector);
354     s32 __user *fence_ptr;
355 
356     fence_ptr = state->connectors[index].out_fence_ptr;
357     state->connectors[index].out_fence_ptr = NULL;
358 
359     return fence_ptr;
360 }
361 
drm_atomic_replace_property_blob_from_id(struct drm_device *dev, struct drm_property_blob **blob, uint64_t blob_id, ssize_t expected_size, ssize_t expected_elem_size, bool *replaced)362 static int drm_atomic_replace_property_blob_from_id(struct drm_device *dev, struct drm_property_blob **blob,
363                                                     uint64_t blob_id, ssize_t expected_size, ssize_t expected_elem_size,
364                                                     bool *replaced)
365 {
366     struct drm_property_blob *new_blob = NULL;
367 
368     if (blob_id != 0) {
369         new_blob = drm_property_lookup_blob(dev, blob_id);
370         if (new_blob == NULL) {
371             return -EINVAL;
372         }
373 
374         if (expected_size > 0 && new_blob->length != expected_size) {
375             drm_property_blob_put(new_blob);
376             return -EINVAL;
377         }
378         if (expected_elem_size > 0 && new_blob->length % expected_elem_size != 0) {
379             drm_property_blob_put(new_blob);
380             return -EINVAL;
381         }
382     }
383 
384     *replaced |= drm_property_replace_blob(blob, new_blob);
385     drm_property_blob_put(new_blob);
386 
387     return 0;
388 }
389 
drm_atomic_crtc_set_property(struct drm_crtc *crtc, struct drm_crtc_state *state, struct drm_property *property, uint64_t val)390 static int drm_atomic_crtc_set_property(struct drm_crtc *crtc, struct drm_crtc_state *state,
391                                         struct drm_property *property, uint64_t val)
392 {
393     struct drm_device *dev = crtc->dev;
394     struct drm_mode_config *config = &dev->mode_config;
395     bool replaced = false;
396     int ret;
397 
398     if (property == config->prop_active) {
399         state->active = val;
400     } else if (property == config->prop_mode_id) {
401         struct drm_property_blob *mode = drm_property_lookup_blob(dev, val);
402         ret = drm_atomic_set_mode_prop_for_crtc(state, mode);
403         drm_property_blob_put(mode);
404         return ret;
405     } else if (property == config->prop_vrr_enabled) {
406         state->vrr_enabled = val;
407     } else if (property == config->degamma_lut_property) {
408         ret = drm_atomic_replace_property_blob_from_id(dev, &state->degamma_lut, val, -1, sizeof(struct drm_color_lut),
409                                                        &replaced);
410         state->color_mgmt_changed |= replaced;
411         return ret;
412     } else if (property == config->ctm_property) {
413         ret = drm_atomic_replace_property_blob_from_id(dev, &state->ctm, val, sizeof(struct drm_color_ctm), -1,
414                                                        &replaced);
415         state->color_mgmt_changed |= replaced;
416         return ret;
417     } else if (property == config->gamma_lut_property) {
418         ret = drm_atomic_replace_property_blob_from_id(dev, &state->gamma_lut, val, -1, sizeof(struct drm_color_lut),
419                                                        &replaced);
420         state->color_mgmt_changed |= replaced;
421         return ret;
422 #if defined(CONFIG_ROCKCHIP_DRM_CUBIC_LUT)
423     } else if (property == config->cubic_lut_property) {
424         ret = drm_atomic_replace_property_blob_from_id(dev, &state->cubic_lut, val, -1, sizeof(struct drm_color_lut),
425                                                        &replaced);
426         state->color_mgmt_changed |= replaced;
427         return ret;
428 #endif
429     } else if (property == config->prop_out_fence_ptr) {
430         s32 __user *fence_ptr = u64_to_user_ptr(val);
431 
432         if (!fence_ptr) {
433             return 0;
434         }
435 
436         if (put_user(-1, fence_ptr)) {
437             return -EFAULT;
438         }
439 
440         set_out_fence_for_crtc(state->state, crtc, fence_ptr);
441     } else if (crtc->funcs->atomic_set_property) {
442         return crtc->funcs->atomic_set_property(crtc, state, property, val);
443     } else {
444         DRM_DEBUG_ATOMIC("[CRTC:%d:%s] unknown property [PROP:%d:%s]]\n", crtc->base.id, crtc->name, property->base.id,
445                          property->name);
446         return -EINVAL;
447     }
448 
449     return 0;
450 }
451 
drm_atomic_crtc_get_property(struct drm_crtc *crtc, const struct drm_crtc_state *state, struct drm_property *property, uint64_t *val)452 static int drm_atomic_crtc_get_property(struct drm_crtc *crtc, const struct drm_crtc_state *state,
453                                         struct drm_property *property, uint64_t *val)
454 {
455     struct drm_device *dev = crtc->dev;
456     struct drm_mode_config *config = &dev->mode_config;
457 
458     if (property == config->prop_active) {
459         *val = drm_atomic_crtc_effectively_active(state);
460     } else if (property == config->prop_mode_id) {
461         *val = (state->mode_blob) ? state->mode_blob->base.id : 0;
462     } else if (property == config->prop_vrr_enabled) {
463         *val = state->vrr_enabled;
464     } else if (property == config->degamma_lut_property) {
465         *val = (state->degamma_lut) ? state->degamma_lut->base.id : 0;
466     } else if (property == config->ctm_property) {
467         *val = (state->ctm) ? state->ctm->base.id : 0;
468     } else if (property == config->gamma_lut_property) {
469         *val = (state->gamma_lut) ? state->gamma_lut->base.id : 0;
470 #if defined(CONFIG_ROCKCHIP_DRM_CUBIC_LUT)
471     } else if (property == config->cubic_lut_property) {
472         *val = (state->cubic_lut) ? state->cubic_lut->base.id : 0;
473 #endif
474     } else if (property == config->prop_out_fence_ptr) {
475         *val = 0;
476     } else if (crtc->funcs->atomic_get_property) {
477         return crtc->funcs->atomic_get_property(crtc, state, property, val);
478     } else {
479         return -EINVAL;
480     }
481 
482     return 0;
483 }
484 
drm_atomic_plane_set_property(struct drm_plane *plane, struct drm_plane_state *state, struct drm_file *file_priv, struct drm_property *property, uint64_t val)485 static int drm_atomic_plane_set_property(struct drm_plane *plane, struct drm_plane_state *state,
486                                          struct drm_file *file_priv, struct drm_property *property, uint64_t val)
487 {
488     struct drm_device *dev = plane->dev;
489     struct drm_mode_config *config = &dev->mode_config;
490     bool replaced = false;
491     int ret;
492 
493     if (property == config->prop_fb_id) {
494         struct drm_framebuffer *fb;
495 
496         fb = drm_framebuffer_lookup(dev, file_priv, val);
497         drm_atomic_set_fb_for_plane(state, fb);
498         if (fb) {
499             drm_framebuffer_put(fb);
500         }
501     } else if (property == config->prop_in_fence_fd) {
502         if (state->fence) {
503             return -EINVAL;
504         }
505 
506         if (U642I64(val) == -1) {
507             return 0;
508         }
509 
510         state->fence = sync_file_get_fence(val);
511         if (!state->fence) {
512             return -EINVAL;
513         }
514     } else if (property == config->prop_crtc_id) {
515         struct drm_crtc *crtc = drm_crtc_find(dev, file_priv, val);
516 
517         if (val && !crtc) {
518             return -EACCES;
519         }
520         return drm_atomic_set_crtc_for_plane(state, crtc);
521     } else if (property == config->prop_crtc_x) {
522         state->crtc_x = U642I64(val);
523     } else if (property == config->prop_crtc_y) {
524         state->crtc_y = U642I64(val);
525     } else if (property == config->prop_crtc_w) {
526         state->crtc_w = val;
527     } else if (property == config->prop_crtc_h) {
528         state->crtc_h = val;
529     } else if (property == config->prop_src_x) {
530         state->src_x = val;
531     } else if (property == config->prop_src_y) {
532         state->src_y = val;
533     } else if (property == config->prop_src_w) {
534         state->src_w = val;
535     } else if (property == config->prop_src_h) {
536         state->src_h = val;
537     } else if (property == plane->alpha_property) {
538         state->alpha = val;
539     } else if (property == plane->blend_mode_property) {
540         state->pixel_blend_mode = val;
541     } else if (property == plane->rotation_property) {
542         if (!is_power_of_2(val & DRM_MODE_ROTATE_MASK)) {
543             DRM_DEBUG_ATOMIC("[PLANE:%d:%s] bad rotation bitmask: 0x%llx\n", plane->base.id, plane->name, val);
544             return -EINVAL;
545         }
546         state->rotation = val;
547     } else if (property == plane->zpos_property) {
548         state->zpos = val;
549     } else if (property == plane->color_encoding_property) {
550         state->color_encoding = val;
551     } else if (property == plane->color_range_property) {
552         state->color_range = val;
553     } else if (property == config->prop_fb_damage_clips) {
554         ret = drm_atomic_replace_property_blob_from_id(dev, &state->fb_damage_clips, val, -1, sizeof(struct drm_rect),
555                                                        &replaced);
556         return ret;
557     } else if (plane->funcs->atomic_set_property) {
558         return plane->funcs->atomic_set_property(plane, state, property, val);
559     } else {
560         DRM_DEBUG_ATOMIC("[PLANE:%d:%s] unknown property [PROP:%d:%s]]\n", plane->base.id, plane->name,
561                          property->base.id, property->name);
562         return -EINVAL;
563     }
564 
565     return 0;
566 }
567 
drm_atomic_plane_get_property(struct drm_plane *plane, const struct drm_plane_state *state, struct drm_property *property, uint64_t *val)568 static int drm_atomic_plane_get_property(struct drm_plane *plane, const struct drm_plane_state *state,
569                                          struct drm_property *property, uint64_t *val)
570 {
571     struct drm_device *dev = plane->dev;
572     struct drm_mode_config *config = &dev->mode_config;
573 
574     if (property == config->prop_fb_id) {
575         *val = (state->fb) ? state->fb->base.id : 0;
576     } else if (property == config->prop_in_fence_fd) {
577         *val = -1;
578     } else if (property == config->prop_crtc_id) {
579         *val = (state->crtc) ? state->crtc->base.id : 0;
580     } else if (property == config->prop_crtc_x) {
581         *val = I642U64(state->crtc_x);
582     } else if (property == config->prop_crtc_y) {
583         *val = I642U64(state->crtc_y);
584     } else if (property == config->prop_crtc_w) {
585         *val = state->crtc_w;
586     } else if (property == config->prop_crtc_h) {
587         *val = state->crtc_h;
588     } else if (property == config->prop_src_x) {
589         *val = state->src_x;
590     } else if (property == config->prop_src_y) {
591         *val = state->src_y;
592     } else if (property == config->prop_src_w) {
593         *val = state->src_w;
594     } else if (property == config->prop_src_h) {
595         *val = state->src_h;
596     } else if (property == plane->alpha_property) {
597         *val = state->alpha;
598     } else if (property == plane->blend_mode_property) {
599         *val = state->pixel_blend_mode;
600     } else if (property == plane->rotation_property) {
601         *val = state->rotation;
602     } else if (property == plane->zpos_property) {
603         *val = state->zpos;
604     } else if (property == plane->color_encoding_property) {
605         *val = state->color_encoding;
606     } else if (property == plane->color_range_property) {
607         *val = state->color_range;
608     } else if (property == config->prop_fb_damage_clips) {
609         *val = (state->fb_damage_clips) ? state->fb_damage_clips->base.id : 0;
610     } else if (plane->funcs->atomic_get_property) {
611         return plane->funcs->atomic_get_property(plane, state, property, val);
612     } else {
613         return -EINVAL;
614     }
615 
616     return 0;
617 }
618 
drm_atomic_set_writeback_fb_for_connector(struct drm_connector_state *conn_state, struct drm_framebuffer *fb)619 static int drm_atomic_set_writeback_fb_for_connector(struct drm_connector_state *conn_state, struct drm_framebuffer *fb)
620 {
621     int ret;
622 
623     ret = drm_writeback_set_fb(conn_state, fb);
624     if (ret < 0) {
625         return ret;
626     }
627 
628     if (fb) {
629         DRM_DEBUG_ATOMIC("Set [FB:%d] for connector state %p\n", fb->base.id, conn_state);
630     } else {
631         DRM_DEBUG_ATOMIC("Set [NOFB] for connector state %p\n", conn_state);
632     }
633 
634     return 0;
635 }
636 
drm_atomic_connector_set_property(struct drm_connector *connector, struct drm_connector_state *state, struct drm_file *file_priv, struct drm_property *property, uint64_t val)637 static int drm_atomic_connector_set_property(struct drm_connector *connector, struct drm_connector_state *state,
638                                              struct drm_file *file_priv, struct drm_property *property, uint64_t val)
639 {
640     struct drm_device *dev = connector->dev;
641     struct drm_mode_config *config = &dev->mode_config;
642     bool replaced = false;
643     int ret;
644 
645     if (property == config->prop_crtc_id) {
646         struct drm_crtc *crtc = drm_crtc_find(dev, file_priv, val);
647 
648         if (val && !crtc) {
649             return -EACCES;
650         }
651         return drm_atomic_set_crtc_for_connector(state, crtc);
652     } else if (property == config->dpms_property) {
653         /* setting DPMS property requires special handling, which
654          * is done in legacy setprop path for us.  Disallow (for
655          * now?) atomic writes to DPMS property:
656          */
657         return -EINVAL;
658     } else if (property == config->tv_select_subconnector_property) {
659         state->tv.subconnector = val;
660     } else if (property == config->tv_left_margin_property) {
661         state->tv.margins.left = val;
662     } else if (property == config->tv_right_margin_property) {
663         state->tv.margins.right = val;
664     } else if (property == config->tv_top_margin_property) {
665         state->tv.margins.top = val;
666     } else if (property == config->tv_bottom_margin_property) {
667         state->tv.margins.bottom = val;
668     } else if (property == config->tv_mode_property) {
669         state->tv.mode = val;
670     } else if (property == config->tv_brightness_property) {
671         state->tv.brightness = val;
672     } else if (property == config->tv_contrast_property) {
673         state->tv.contrast = val;
674     } else if (property == config->tv_flicker_reduction_property) {
675         state->tv.flicker_reduction = val;
676     } else if (property == config->tv_overscan_property) {
677         state->tv.overscan = val;
678     } else if (property == config->tv_saturation_property) {
679         state->tv.saturation = val;
680     } else if (property == config->tv_hue_property) {
681         state->tv.hue = val;
682     } else if (property == config->link_status_property) {
683         /* Never downgrade from GOOD to BAD on userspace's request here,
684          * only hw issues can do that.
685          *
686          * For an atomic property the userspace doesn't need to be able
687          * to understand all the properties, but needs to be able to
688          * restore the state it wants on VT switch. So if the userspace
689          * tries to change the link_status from GOOD to BAD, driver
690          * silently rejects it and returns a 0. This prevents userspace
691          * from accidently breaking  the display when it restores the
692          * state.
693          */
694         if (state->link_status != DRM_LINK_STATUS_GOOD) {
695             state->link_status = val;
696         }
697     } else if (property == config->hdr_output_metadata_property) {
698         ret = drm_atomic_replace_property_blob_from_id(dev, &state->hdr_output_metadata, val,
699                                                        sizeof(struct hdr_output_metadata), -1, &replaced);
700         return ret;
701     } else if (property == config->aspect_ratio_property) {
702         state->picture_aspect_ratio = val;
703     } else if (property == config->content_type_property) {
704         state->content_type = val;
705     } else if (property == connector->scaling_mode_property) {
706         state->scaling_mode = val;
707     } else if (property == config->content_protection_property) {
708         if (val == DRM_MODE_CONTENT_PROTECTION_ENABLED) {
709             DRM_DEBUG_KMS("only drivers can set CP Enabled\n");
710             return -EINVAL;
711         }
712         state->content_protection = val;
713     } else if (property == config->hdcp_content_type_property) {
714         state->hdcp_content_type = val;
715     } else if (property == connector->colorspace_property) {
716         state->colorspace = val;
717     } else if (property == config->writeback_fb_id_property) {
718         struct drm_framebuffer *fb;
719         int ret;
720 
721         fb = drm_framebuffer_lookup(dev, file_priv, val);
722         ret = drm_atomic_set_writeback_fb_for_connector(state, fb);
723         if (fb) {
724             drm_framebuffer_put(fb);
725         }
726         return ret;
727     } else if (property == config->writeback_out_fence_ptr_property) {
728         s32 __user *fence_ptr = u64_to_user_ptr(val);
729 
730         return set_out_fence_for_connector(state->state, connector, fence_ptr);
731     } else if (property == connector->max_bpc_property) {
732         state->max_requested_bpc = val;
733     } else if (connector->funcs->atomic_set_property) {
734         return connector->funcs->atomic_set_property(connector, state, property, val);
735     } else {
736         DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] unknown property [PROP:%d:%s]]\n", connector->base.id, connector->name,
737                          property->base.id, property->name);
738         return -EINVAL;
739     }
740 
741     return 0;
742 }
743 
drm_atomic_connector_get_property(struct drm_connector *connector, const struct drm_connector_state *state, struct drm_property *property, uint64_t *val)744 static int drm_atomic_connector_get_property(struct drm_connector *connector, const struct drm_connector_state *state,
745                                              struct drm_property *property, uint64_t *val)
746 {
747     struct drm_device *dev = connector->dev;
748     struct drm_mode_config *config = &dev->mode_config;
749 
750     if (property == config->prop_crtc_id) {
751         *val = (state->crtc) ? state->crtc->base.id : 0;
752     } else if (property == config->dpms_property) {
753         if (state->crtc && state->crtc->state->self_refresh_active) {
754             *val = DRM_MODE_DPMS_ON;
755         } else {
756             *val = connector->dpms;
757         }
758     } else if (property == config->tv_select_subconnector_property) {
759         *val = state->tv.subconnector;
760     } else if (property == config->tv_left_margin_property) {
761         *val = state->tv.margins.left;
762     } else if (property == config->tv_right_margin_property) {
763         *val = state->tv.margins.right;
764     } else if (property == config->tv_top_margin_property) {
765         *val = state->tv.margins.top;
766     } else if (property == config->tv_bottom_margin_property) {
767         *val = state->tv.margins.bottom;
768     } else if (property == config->tv_mode_property) {
769         *val = state->tv.mode;
770     } else if (property == config->tv_brightness_property) {
771         *val = state->tv.brightness;
772     } else if (property == config->tv_contrast_property) {
773         *val = state->tv.contrast;
774     } else if (property == config->tv_flicker_reduction_property) {
775         *val = state->tv.flicker_reduction;
776     } else if (property == config->tv_overscan_property) {
777         *val = state->tv.overscan;
778     } else if (property == config->tv_saturation_property) {
779         *val = state->tv.saturation;
780     } else if (property == config->tv_hue_property) {
781         *val = state->tv.hue;
782     } else if (property == config->link_status_property) {
783         *val = state->link_status;
784     } else if (property == config->aspect_ratio_property) {
785         *val = state->picture_aspect_ratio;
786     } else if (property == config->content_type_property) {
787         *val = state->content_type;
788     } else if (property == connector->colorspace_property) {
789         *val = state->colorspace;
790     } else if (property == connector->scaling_mode_property) {
791         *val = state->scaling_mode;
792     } else if (property == config->hdr_output_metadata_property) {
793         *val = state->hdr_output_metadata ? state->hdr_output_metadata->base.id : 0;
794     } else if (property == config->content_protection_property) {
795         *val = state->content_protection;
796     } else if (property == config->hdcp_content_type_property) {
797         *val = state->hdcp_content_type;
798     } else if (property == config->writeback_fb_id_property) {
799         /* Writeback framebuffer is one-shot, write and forget */
800         *val = 0;
801     } else if (property == config->writeback_out_fence_ptr_property) {
802         *val = 0;
803     } else if (property == connector->max_bpc_property) {
804         *val = state->max_requested_bpc;
805     } else if (connector->funcs->atomic_get_property) {
806         return connector->funcs->atomic_get_property(connector, state, property, val);
807     } else {
808         return -EINVAL;
809     }
810 
811     return 0;
812 }
813 
drm_atomic_get_property(struct drm_mode_object *obj, struct drm_property *property, uint64_t *val)814 int drm_atomic_get_property(struct drm_mode_object *obj, struct drm_property *property, uint64_t *val)
815 {
816     struct drm_device *dev = property->dev;
817     int ret;
818 
819     switch (obj->type) {
820         case DRM_MODE_OBJECT_CONNECTOR: {
821             struct drm_connector *connector = obj_to_connector(obj);
822 
823             WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
824             ret = drm_atomic_connector_get_property(connector, connector->state, property, val);
825             break;
826         }
827         case DRM_MODE_OBJECT_CRTC: {
828             struct drm_crtc *crtc = obj_to_crtc(obj);
829 
830             WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
831             ret = drm_atomic_crtc_get_property(crtc, crtc->state, property, val);
832             break;
833         }
834         case DRM_MODE_OBJECT_PLANE: {
835             struct drm_plane *plane = obj_to_plane(obj);
836 
837             WARN_ON(!drm_modeset_is_locked(&plane->mutex));
838             ret = drm_atomic_plane_get_property(plane, plane->state, property, val);
839             break;
840         }
841         default:
842             ret = -EINVAL;
843             break;
844     }
845 
846     return ret;
847 }
848 
849 /*
850  * The big monster ioctl
851  */
852 
create_vblank_event(struct drm_crtc *crtc, uint64_t user_data)853 static struct drm_pending_vblank_event *create_vblank_event(struct drm_crtc *crtc, uint64_t user_data)
854 {
855     struct drm_pending_vblank_event *e = NULL;
856 
857     e = kzalloc(sizeof(*e), GFP_KERNEL);
858     if (!e) {
859         return NULL;
860     }
861 
862     e->event.base.type = DRM_EVENT_FLIP_COMPLETE;
863     e->event.base.length = sizeof(e->event);
864     e->event.vbl.crtc_id = crtc->base.id;
865     e->event.vbl.user_data = user_data;
866 
867     return e;
868 }
869 
drm_atomic_connector_commit_dpms(struct drm_atomic_state *state, struct drm_connector *connector, int mode)870 int drm_atomic_connector_commit_dpms(struct drm_atomic_state *state, struct drm_connector *connector, int mode)
871 {
872     struct drm_connector *tmp_connector;
873     struct drm_connector_state *new_conn_state;
874     struct drm_crtc *crtc;
875     struct drm_crtc_state *crtc_state;
876     int i, ret, old_mode = connector->dpms;
877     bool active = false;
878 
879     ret = drm_modeset_lock(&state->dev->mode_config.connection_mutex, state->acquire_ctx);
880     if (ret) {
881         return ret;
882     }
883 
884     if (mode != DRM_MODE_DPMS_ON) {
885         mode = DRM_MODE_DPMS_OFF;
886     }
887     connector->dpms = mode;
888 
889     crtc = connector->state->crtc;
890     if (!crtc) {
891         goto out;
892     }
893     ret = drm_atomic_add_affected_connectors(state, crtc);
894     if (ret) {
895         goto out;
896     }
897 
898     crtc_state = drm_atomic_get_crtc_state(state, crtc);
899     if (IS_ERR(crtc_state)) {
900         ret = PTR_ERR(crtc_state);
901         goto out;
902     }
903 
904     for_each_new_connector_in_state(state, tmp_connector, new_conn_state, i)
905     {
906         if (new_conn_state->crtc != crtc) {
907             continue;
908         }
909         if (tmp_connector->dpms == DRM_MODE_DPMS_ON) {
910             active = true;
911             break;
912         }
913     }
914 
915     crtc_state->active = active;
916     ret = drm_atomic_commit(state);
917 out:
918     if (ret != 0) {
919         connector->dpms = old_mode;
920     }
921     return ret;
922 }
923 
drm_atomic_set_property(struct drm_atomic_state *state, struct drm_file *file_priv, struct drm_mode_object *obj, struct drm_property *prop, uint64_t prop_value)924 int drm_atomic_set_property(struct drm_atomic_state *state, struct drm_file *file_priv, struct drm_mode_object *obj,
925                             struct drm_property *prop, uint64_t prop_value)
926 {
927     struct drm_mode_object *ref;
928     int ret;
929 
930     if (!drm_property_change_valid_get(prop, prop_value, &ref)) {
931         return -EINVAL;
932     }
933 
934     switch (obj->type) {
935         case DRM_MODE_OBJECT_CONNECTOR: {
936             struct drm_connector *connector = obj_to_connector(obj);
937             struct drm_connector_state *connector_state;
938 
939             connector_state = drm_atomic_get_connector_state(state, connector);
940             if (IS_ERR(connector_state)) {
941                 ret = PTR_ERR(connector_state);
942                 break;
943             }
944 
945             ret = drm_atomic_connector_set_property(connector, connector_state, file_priv, prop, prop_value);
946             break;
947         }
948         case DRM_MODE_OBJECT_CRTC: {
949             struct drm_crtc *crtc = obj_to_crtc(obj);
950             struct drm_crtc_state *crtc_state;
951 
952             crtc_state = drm_atomic_get_crtc_state(state, crtc);
953             if (IS_ERR(crtc_state)) {
954                 ret = PTR_ERR(crtc_state);
955                 break;
956             }
957 
958             ret = drm_atomic_crtc_set_property(crtc, crtc_state, prop, prop_value);
959             break;
960         }
961         case DRM_MODE_OBJECT_PLANE: {
962             struct drm_plane *plane = obj_to_plane(obj);
963             struct drm_plane_state *plane_state;
964 
965             plane_state = drm_atomic_get_plane_state(state, plane);
966             if (IS_ERR(plane_state)) {
967                 ret = PTR_ERR(plane_state);
968                 break;
969             }
970 
971             ret = drm_atomic_plane_set_property(plane, plane_state, file_priv, prop, prop_value);
972             break;
973         }
974         default:
975             ret = -EINVAL;
976             break;
977     }
978 
979     drm_property_change_valid_put(prop, ref);
980     return ret;
981 }
982 
983 /**
984  * DOC: explicit fencing properties
985  *
986  * Explicit fencing allows userspace to control the buffer synchronization
987  * between devices. A Fence or a group of fences are transfered to/from
988  * userspace using Sync File fds and there are two DRM properties for that.
989  * IN_FENCE_FD on each DRM Plane to send fences to the kernel and
990  * OUT_FENCE_PTR on each DRM CRTC to receive fences from the kernel.
991  *
992  * As a contrast, with implicit fencing the kernel keeps track of any
993  * ongoing rendering, and automatically ensures that the atomic update waits
994  * for any pending rendering to complete. For shared buffers represented with
995  * a &struct dma_buf this is tracked in &struct dma_resv.
996  * Implicit syncing is how Linux traditionally worked (e.g. DRI2/3 on X.org),
997  * whereas explicit fencing is what Android wants.
998  *
999  * "IN_FENCE_FD”:
1000  *    Use this property to pass a fence that DRM should wait on before
1001  *    proceeding with the Atomic Commit request and show the framebuffer for
1002  *    the plane on the screen. The fence can be either a normal fence or a
1003  *    merged one, the sync_file framework will handle both cases and use a
1004  *    fence_array if a merged fence is received. Passing -1 here means no
1005  *    fences to wait on.
1006  *
1007  *    If the Atomic Commit request has the DRM_MODE_ATOMIC_TEST_ONLY flag
1008  *    it will only check if the Sync File is a valid one.
1009  *
1010  *    On the driver side the fence is stored on the @fence parameter of
1011  *    &struct drm_plane_state. Drivers which also support implicit fencing
1012  *    should set the implicit fence using drm_atomic_set_fence_for_plane(),
1013  *    to make sure there's consistent behaviour between drivers in precedence
1014  *    of implicit vs. explicit fencing.
1015  *
1016  * "OUT_FENCE_PTR”:
1017  *    Use this property to pass a file descriptor pointer to DRM. Once the
1018  *    Atomic Commit request call returns OUT_FENCE_PTR will be filled with
1019  *    the file descriptor number of a Sync File. This Sync File contains the
1020  *    CRTC fence that will be signaled when all framebuffers present on the
1021  *    Atomic Commit * request for that given CRTC are scanned out on the
1022  *    screen.
1023  *
1024  *    The Atomic Commit request fails if a invalid pointer is passed. If the
1025  *    Atomic Commit request fails for any other reason the out fence fd
1026  *    returned will be -1. On a Atomic Commit with the
1027  *    DRM_MODE_ATOMIC_TEST_ONLY flag the out fence will also be set to -1.
1028  *
1029  *    Note that out-fences don't have a special interface to drivers and are
1030  *    internally represented by a &struct drm_pending_vblank_event in struct
1031  *    &drm_crtc_state, which is also used by the nonblocking atomic commit
1032  *    helpers and for the DRM event handling for existing userspace.
1033  */
1034 
1035 struct drm_out_fence_state {
1036     s32 __user *out_fence_ptr;
1037     struct sync_file *sync_file;
1038     int fd;
1039 };
1040 
setup_out_fence(struct drm_out_fence_state *fence_state, struct dma_fence *fence)1041 static int setup_out_fence(struct drm_out_fence_state *fence_state, struct dma_fence *fence)
1042 {
1043     fence_state->fd = get_unused_fd_flags(O_CLOEXEC);
1044     if (fence_state->fd < 0) {
1045         return fence_state->fd;
1046     }
1047 
1048     if (put_user(fence_state->fd, fence_state->out_fence_ptr)) {
1049         return -EFAULT;
1050     }
1051 
1052     fence_state->sync_file = sync_file_create(fence);
1053     if (!fence_state->sync_file) {
1054         return -ENOMEM;
1055     }
1056 
1057     return 0;
1058 }
1059 
prepare_signaling(struct drm_device *dev, struct drm_atomic_state *state, struct drm_mode_atomic *arg, struct drm_file *file_priv, struct drm_out_fence_state **fence_state, unsigned int *num_fences)1060 static int prepare_signaling(struct drm_device *dev, struct drm_atomic_state *state, struct drm_mode_atomic *arg,
1061                              struct drm_file *file_priv, struct drm_out_fence_state **fence_state,
1062                              unsigned int *num_fences)
1063 {
1064     struct drm_crtc *crtc;
1065     struct drm_crtc_state *crtc_state;
1066     struct drm_connector *conn;
1067     struct drm_connector_state *conn_state;
1068     int i, c = 0, ret;
1069 
1070     if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) {
1071         return 0;
1072     }
1073 
1074     for_each_new_crtc_in_state(state, crtc, crtc_state, i)
1075     {
1076         s32 __user *fence_ptr;
1077 
1078         fence_ptr = get_out_fence_for_crtc(crtc_state->state, crtc);
1079         if ((arg->flags & DRM_MODE_PAGE_FLIP_EVENT) || fence_ptr) {
1080             struct drm_pending_vblank_event *e;
1081 
1082             e = create_vblank_event(crtc, arg->user_data);
1083             if (!e) {
1084                 return -ENOMEM;
1085             }
1086 
1087             crtc_state->event = e;
1088         }
1089 
1090         if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT) {
1091             struct drm_pending_vblank_event *e = crtc_state->event;
1092 
1093             if (!file_priv) {
1094                 continue;
1095             }
1096 
1097             ret = drm_event_reserve_init(dev, file_priv, &e->base, &e->event.base);
1098             if (ret) {
1099                 kfree(e);
1100                 crtc_state->event = NULL;
1101                 return ret;
1102             }
1103         }
1104 
1105         if (fence_ptr) {
1106             struct dma_fence *fence;
1107             struct drm_out_fence_state *f;
1108 
1109             f = krealloc(*fence_state, sizeof(**fence_state) * (*num_fences + 1), GFP_KERNEL);
1110             if (!f) {
1111                 return -ENOMEM;
1112             }
1113 
1114             memset(&f[*num_fences], 0, sizeof(*f));
1115 
1116             f[*num_fences].out_fence_ptr = fence_ptr;
1117             *fence_state = f;
1118 
1119             fence = drm_crtc_create_fence(crtc);
1120             if (!fence) {
1121                 return -ENOMEM;
1122             }
1123 
1124             ret = setup_out_fence(&f[(*num_fences)++], fence);
1125             if (ret) {
1126                 dma_fence_put(fence);
1127                 return ret;
1128             }
1129 
1130             crtc_state->event->base.fence = fence;
1131         }
1132 
1133         c++;
1134     }
1135 
1136     for_each_new_connector_in_state(state, conn, conn_state, i)
1137     {
1138         struct drm_writeback_connector *wb_conn;
1139         struct drm_out_fence_state *f;
1140         struct dma_fence *fence;
1141         s32 __user *fence_ptr;
1142 
1143         if (!conn_state->writeback_job) {
1144             continue;
1145         }
1146 
1147         fence_ptr = get_out_fence_for_connector(state, conn);
1148         if (!fence_ptr) {
1149             continue;
1150         }
1151 
1152         f = krealloc(*fence_state, sizeof(**fence_state) * (*num_fences + 1), GFP_KERNEL);
1153         if (!f) {
1154             return -ENOMEM;
1155         }
1156 
1157         memset(&f[*num_fences], 0, sizeof(*f));
1158 
1159         f[*num_fences].out_fence_ptr = fence_ptr;
1160         *fence_state = f;
1161 
1162         wb_conn = drm_connector_to_writeback(conn);
1163         fence = drm_writeback_get_out_fence(wb_conn);
1164         if (!fence) {
1165             return -ENOMEM;
1166         }
1167 
1168         ret = setup_out_fence(&f[(*num_fences)++], fence);
1169         if (ret) {
1170             dma_fence_put(fence);
1171             return ret;
1172         }
1173 
1174         conn_state->writeback_job->out_fence = fence;
1175     }
1176 
1177     /*
1178      * Having this flag means user mode pends on event which will never
1179      * reach due to lack of at least one CRTC for signaling
1180      */
1181     if (c == 0 && (arg->flags & DRM_MODE_PAGE_FLIP_EVENT)) {
1182         return -EINVAL;
1183     }
1184 
1185     return 0;
1186 }
1187 
complete_signaling(struct drm_device *dev, struct drm_atomic_state *state, struct drm_out_fence_state *fence_state, unsigned int num_fences, bool install_fds)1188 static void complete_signaling(struct drm_device *dev, struct drm_atomic_state *state,
1189                                struct drm_out_fence_state *fence_state, unsigned int num_fences, bool install_fds)
1190 {
1191     struct drm_crtc *crtc;
1192     struct drm_crtc_state *crtc_state;
1193     int i;
1194 
1195     if (install_fds) {
1196         for (i = 0; i < num_fences; i++) {
1197             fd_install(fence_state[i].fd, fence_state[i].sync_file->file);
1198         }
1199 
1200         kfree(fence_state);
1201         return;
1202     }
1203 
1204     for_each_new_crtc_in_state(state, crtc, crtc_state, i)
1205     {
1206         struct drm_pending_vblank_event *event = crtc_state->event;
1207         /*
1208          * Free the allocated event. drm_atomic_helper_setup_commit
1209          * can allocate an event too, so only free it if it's ours
1210          * to prevent a double free in drm_atomic_state_clear.
1211          */
1212         if (event && (event->base.fence || event->base.file_priv)) {
1213             drm_event_cancel_free(dev, &event->base);
1214             crtc_state->event = NULL;
1215         }
1216     }
1217 
1218     if (!fence_state) {
1219         return;
1220     }
1221 
1222     for (i = 0; i < num_fences; i++) {
1223         if (fence_state[i].sync_file) {
1224             fput(fence_state[i].sync_file->file);
1225         }
1226         if (fence_state[i].fd >= 0) {
1227             put_unused_fd(fence_state[i].fd);
1228         }
1229 
1230         /* If this fails log error to the user */
1231         if (fence_state[i].out_fence_ptr && put_user(-1, fence_state[i].out_fence_ptr)) {
1232             DRM_DEBUG_ATOMIC("Couldn't clear out_fence_ptr\n");
1233         }
1234     }
1235 
1236     kfree(fence_state);
1237 }
1238 
drm_mode_atomic_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)1239 int drm_mode_atomic_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
1240 {
1241     struct drm_mode_atomic *arg = data;
1242     uint32_t __user *objs_ptr = (uint32_t __user *)(unsigned long)(arg->objs_ptr);
1243     uint32_t __user *count_props_ptr = (uint32_t __user *)(unsigned long)(arg->count_props_ptr);
1244     uint32_t __user *props_ptr = (uint32_t __user *)(unsigned long)(arg->props_ptr);
1245     uint64_t __user *prop_values_ptr = (uint64_t __user *)(unsigned long)(arg->prop_values_ptr);
1246     unsigned int copied_objs, copied_props;
1247     struct drm_atomic_state *state;
1248     struct drm_modeset_acquire_ctx ctx;
1249     struct drm_out_fence_state *fence_state;
1250     int ret = 0;
1251     unsigned int i, j, num_fences;
1252 
1253     /* disallow for drivers not supporting atomic: */
1254     if (!drm_core_check_feature(dev, DRIVER_ATOMIC)) {
1255         return -EOPNOTSUPP;
1256     }
1257 
1258     /* disallow for userspace that has not enabled atomic cap (even
1259      * though this may be a bit overkill, since legacy userspace
1260      * wouldn't know how to call this ioctl)
1261      */
1262     if (!file_priv->atomic) {
1263         return -EINVAL;
1264     }
1265 
1266     if (arg->flags & ~DRM_MODE_ATOMIC_FLAGS) {
1267         return -EINVAL;
1268     }
1269 
1270     if (arg->reserved) {
1271         return -EINVAL;
1272     }
1273 
1274     if (arg->flags & DRM_MODE_PAGE_FLIP_ASYNC) {
1275         return -EINVAL;
1276     }
1277 
1278     /* can't test and expect an event at the same time. */
1279     if ((arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) && (arg->flags & DRM_MODE_PAGE_FLIP_EVENT)) {
1280         return -EINVAL;
1281     }
1282 
1283     state = drm_atomic_state_alloc(dev);
1284     if (!state) {
1285         return -ENOMEM;
1286     }
1287 
1288     drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
1289     state->acquire_ctx = &ctx;
1290     state->allow_modeset = !!(arg->flags & DRM_MODE_ATOMIC_ALLOW_MODESET);
1291 
1292     while (1) {
1293         copied_objs = 0;
1294         copied_props = 0;
1295         fence_state = NULL;
1296         num_fences = 0;
1297 
1298         for (i = 0; i < arg->count_objs; i++) {
1299             uint32_t obj_id, count_props;
1300             struct drm_mode_object *obj;
1301 
1302             if (get_user(obj_id, objs_ptr + copied_objs)) {
1303                 ret = -EFAULT;
1304                 goto out;
1305             }
1306 
1307             obj = drm_mode_object_find(dev, file_priv, obj_id, DRM_MODE_OBJECT_ANY);
1308             if (!obj) {
1309                 ret = -ENOENT;
1310                 goto out;
1311             }
1312 
1313             if (!obj->properties) {
1314                 drm_mode_object_put(obj);
1315                 ret = -ENOENT;
1316                 goto out;
1317             }
1318 
1319             if (get_user(count_props, count_props_ptr + copied_objs)) {
1320                 drm_mode_object_put(obj);
1321                 ret = -EFAULT;
1322                 goto out;
1323             }
1324 
1325             copied_objs++;
1326 
1327             for (j = 0; j < count_props; j++) {
1328                 uint32_t prop_id;
1329                 uint64_t prop_value;
1330                 struct drm_property *prop;
1331 
1332                 if (get_user(prop_id, props_ptr + copied_props)) {
1333                     drm_mode_object_put(obj);
1334                     ret = -EFAULT;
1335                     goto out;
1336                 }
1337 
1338                 prop = drm_mode_obj_find_prop_id(obj, prop_id);
1339                 if (!prop) {
1340                     drm_mode_object_put(obj);
1341                     ret = -ENOENT;
1342                     goto out;
1343                 }
1344 
1345                 if (copy_from_user(&prop_value, prop_values_ptr + copied_props, sizeof(prop_value))) {
1346                     drm_mode_object_put(obj);
1347                     ret = -EFAULT;
1348                     goto out;
1349                 }
1350 
1351                 ret = drm_atomic_set_property(state, file_priv, obj, prop, prop_value);
1352                 if (ret) {
1353                     drm_mode_object_put(obj);
1354                     goto out;
1355                 }
1356 
1357                 copied_props++;
1358             }
1359 
1360             drm_mode_object_put(obj);
1361         }
1362 
1363         ret = prepare_signaling(dev, state, arg, file_priv, &fence_state, &num_fences);
1364         if (ret) {
1365             goto out;
1366         }
1367 
1368         if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) {
1369             ret = drm_atomic_check_only(state);
1370         } else if (arg->flags & DRM_MODE_ATOMIC_NONBLOCK) {
1371             ret = drm_atomic_nonblocking_commit(state);
1372         } else {
1373             if (drm_debug_enabled(DRM_UT_STATE)) {
1374                 drm_atomic_print_state(state);
1375             }
1376 
1377             ret = drm_atomic_commit(state);
1378         }
1379 
1380     out:
1381         complete_signaling(dev, state, fence_state, num_fences, !ret);
1382 
1383         if (ret == -EDEADLK) {
1384             drm_atomic_state_clear(state);
1385             ret = drm_modeset_backoff(&ctx);
1386             if (!ret) {
1387                 continue;
1388             }
1389         }
1390         break;
1391     }
1392 
1393     drm_atomic_state_put(state);
1394 
1395     drm_modeset_drop_locks(&ctx);
1396     drm_modeset_acquire_fini(&ctx);
1397 
1398     return ret;
1399 }
1400