root/drivers/gpu/drm/drm_atomic_uapi.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. drm_atomic_set_mode_for_crtc
  2. drm_atomic_set_mode_prop_for_crtc
  3. drm_atomic_set_crtc_for_plane
  4. drm_atomic_set_fb_for_plane
  5. drm_atomic_set_fence_for_plane
  6. drm_atomic_set_crtc_for_connector
  7. set_out_fence_for_crtc
  8. get_out_fence_for_crtc
  9. set_out_fence_for_connector
  10. get_out_fence_for_connector
  11. drm_atomic_replace_property_blob_from_id
  12. drm_atomic_crtc_set_property
  13. drm_atomic_crtc_get_property
  14. drm_atomic_plane_set_property
  15. drm_atomic_plane_get_property
  16. drm_atomic_set_writeback_fb_for_connector
  17. drm_atomic_connector_set_property
  18. drm_atomic_connector_get_property
  19. drm_atomic_get_property
  20. create_vblank_event
  21. drm_atomic_connector_commit_dpms
  22. drm_atomic_set_property
  23. setup_out_fence
  24. prepare_signaling
  25. complete_signaling
  26. drm_mode_atomic_ioctl

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

/* [<][>][^][v][top][bottom][index][help] */