root/drivers/gpu/drm/drm_mode_object.c

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

DEFINITIONS

This source file includes following definitions.
  1. __drm_mode_object_add
  2. drm_mode_object_add
  3. drm_mode_object_register
  4. drm_mode_object_unregister
  5. drm_mode_object_lease_required
  6. __drm_mode_object_find
  7. drm_mode_object_find
  8. drm_mode_object_put
  9. drm_mode_object_get
  10. drm_object_attach_property
  11. drm_object_property_set_value
  12. __drm_object_property_get_value
  13. drm_object_property_get_value
  14. drm_mode_object_get_properties
  15. drm_mode_obj_get_properties_ioctl
  16. drm_mode_obj_find_prop_id
  17. set_property_legacy
  18. set_property_atomic
  19. drm_mode_obj_set_property_ioctl

   1 /*
   2  * Copyright (c) 2016 Intel Corporation
   3  *
   4  * Permission to use, copy, modify, distribute, and sell this software and its
   5  * documentation for any purpose is hereby granted without fee, provided that
   6  * the above copyright notice appear in all copies and that both that copyright
   7  * notice and this permission notice appear in supporting documentation, and
   8  * that the name of the copyright holders not be used in advertising or
   9  * publicity pertaining to distribution of the software without specific,
  10  * written prior permission.  The copyright holders make no representations
  11  * about the suitability of this software for any purpose.  It is provided "as
  12  * is" without express or implied warranty.
  13  *
  14  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  16  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  20  * OF THIS SOFTWARE.
  21  */
  22 
  23 #include <linux/export.h>
  24 #include <linux/uaccess.h>
  25 
  26 #include <drm/drm_atomic.h>
  27 #include <drm/drm_drv.h>
  28 #include <drm/drm_device.h>
  29 #include <drm/drm_file.h>
  30 #include <drm/drm_mode_object.h>
  31 #include <drm/drm_print.h>
  32 
  33 #include "drm_crtc_internal.h"
  34 
  35 /*
  36  * Internal function to assign a slot in the object idr and optionally
  37  * register the object into the idr.
  38  */
  39 int __drm_mode_object_add(struct drm_device *dev, struct drm_mode_object *obj,
  40                           uint32_t obj_type, bool register_obj,
  41                           void (*obj_free_cb)(struct kref *kref))
  42 {
  43         int ret;
  44 
  45         WARN_ON(!dev->driver->load && dev->registered && !obj_free_cb);
  46 
  47         mutex_lock(&dev->mode_config.idr_mutex);
  48         ret = idr_alloc(&dev->mode_config.object_idr, register_obj ? obj : NULL,
  49                         1, 0, GFP_KERNEL);
  50         if (ret >= 0) {
  51                 /*
  52                  * Set up the object linking under the protection of the idr
  53                  * lock so that other users can't see inconsistent state.
  54                  */
  55                 obj->id = ret;
  56                 obj->type = obj_type;
  57                 if (obj_free_cb) {
  58                         obj->free_cb = obj_free_cb;
  59                         kref_init(&obj->refcount);
  60                 }
  61         }
  62         mutex_unlock(&dev->mode_config.idr_mutex);
  63 
  64         return ret < 0 ? ret : 0;
  65 }
  66 
  67 /**
  68  * drm_mode_object_add - allocate a new modeset identifier
  69  * @dev: DRM device
  70  * @obj: object pointer, used to generate unique ID
  71  * @obj_type: object type
  72  *
  73  * Create a unique identifier based on @ptr in @dev's identifier space.  Used
  74  * for tracking modes, CRTCs and connectors.
  75  *
  76  * Returns:
  77  * Zero on success, error code on failure.
  78  */
  79 int drm_mode_object_add(struct drm_device *dev,
  80                         struct drm_mode_object *obj, uint32_t obj_type)
  81 {
  82         return __drm_mode_object_add(dev, obj, obj_type, true, NULL);
  83 }
  84 
  85 void drm_mode_object_register(struct drm_device *dev,
  86                               struct drm_mode_object *obj)
  87 {
  88         mutex_lock(&dev->mode_config.idr_mutex);
  89         idr_replace(&dev->mode_config.object_idr, obj, obj->id);
  90         mutex_unlock(&dev->mode_config.idr_mutex);
  91 }
  92 
  93 /**
  94  * drm_mode_object_unregister - free a modeset identifer
  95  * @dev: DRM device
  96  * @object: object to free
  97  *
  98  * Free @id from @dev's unique identifier pool.
  99  * This function can be called multiple times, and guards against
 100  * multiple removals.
 101  * These modeset identifiers are _not_ reference counted. Hence don't use this
 102  * for reference counted modeset objects like framebuffers.
 103  */
 104 void drm_mode_object_unregister(struct drm_device *dev,
 105                                 struct drm_mode_object *object)
 106 {
 107         WARN_ON(!dev->driver->load && dev->registered && !object->free_cb);
 108 
 109         mutex_lock(&dev->mode_config.idr_mutex);
 110         if (object->id) {
 111                 idr_remove(&dev->mode_config.object_idr, object->id);
 112                 object->id = 0;
 113         }
 114         mutex_unlock(&dev->mode_config.idr_mutex);
 115 }
 116 
 117 /**
 118  * drm_lease_required - check types which must be leased to be used
 119  * @type: type of object
 120  *
 121  * Returns whether the provided type of drm_mode_object must
 122  * be owned or leased to be used by a process.
 123  */
 124 bool drm_mode_object_lease_required(uint32_t type)
 125 {
 126         switch(type) {
 127         case DRM_MODE_OBJECT_CRTC:
 128         case DRM_MODE_OBJECT_CONNECTOR:
 129         case DRM_MODE_OBJECT_PLANE:
 130                 return true;
 131         default:
 132                 return false;
 133         }
 134 }
 135 
 136 struct drm_mode_object *__drm_mode_object_find(struct drm_device *dev,
 137                                                struct drm_file *file_priv,
 138                                                uint32_t id, uint32_t type)
 139 {
 140         struct drm_mode_object *obj = NULL;
 141 
 142         mutex_lock(&dev->mode_config.idr_mutex);
 143         obj = idr_find(&dev->mode_config.object_idr, id);
 144         if (obj && type != DRM_MODE_OBJECT_ANY && obj->type != type)
 145                 obj = NULL;
 146         if (obj && obj->id != id)
 147                 obj = NULL;
 148 
 149         if (obj && drm_mode_object_lease_required(obj->type) &&
 150             !_drm_lease_held(file_priv, obj->id))
 151                 obj = NULL;
 152 
 153         if (obj && obj->free_cb) {
 154                 if (!kref_get_unless_zero(&obj->refcount))
 155                         obj = NULL;
 156         }
 157         mutex_unlock(&dev->mode_config.idr_mutex);
 158 
 159         return obj;
 160 }
 161 
 162 /**
 163  * drm_mode_object_find - look up a drm object with static lifetime
 164  * @dev: drm device
 165  * @file_priv: drm file
 166  * @id: id of the mode object
 167  * @type: type of the mode object
 168  *
 169  * This function is used to look up a modeset object. It will acquire a
 170  * reference for reference counted objects. This reference must be dropped again
 171  * by callind drm_mode_object_put().
 172  */
 173 struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,
 174                 struct drm_file *file_priv,
 175                 uint32_t id, uint32_t type)
 176 {
 177         struct drm_mode_object *obj = NULL;
 178 
 179         obj = __drm_mode_object_find(dev, file_priv, id, type);
 180         return obj;
 181 }
 182 EXPORT_SYMBOL(drm_mode_object_find);
 183 
 184 /**
 185  * drm_mode_object_put - release a mode object reference
 186  * @obj: DRM mode object
 187  *
 188  * This function decrements the object's refcount if it is a refcounted modeset
 189  * object. It is a no-op on any other object. This is used to drop references
 190  * acquired with drm_mode_object_get().
 191  */
 192 void drm_mode_object_put(struct drm_mode_object *obj)
 193 {
 194         if (obj->free_cb) {
 195                 DRM_DEBUG("OBJ ID: %d (%d)\n", obj->id, kref_read(&obj->refcount));
 196                 kref_put(&obj->refcount, obj->free_cb);
 197         }
 198 }
 199 EXPORT_SYMBOL(drm_mode_object_put);
 200 
 201 /**
 202  * drm_mode_object_get - acquire a mode object reference
 203  * @obj: DRM mode object
 204  *
 205  * This function increments the object's refcount if it is a refcounted modeset
 206  * object. It is a no-op on any other object. References should be dropped again
 207  * by calling drm_mode_object_put().
 208  */
 209 void drm_mode_object_get(struct drm_mode_object *obj)
 210 {
 211         if (obj->free_cb) {
 212                 DRM_DEBUG("OBJ ID: %d (%d)\n", obj->id, kref_read(&obj->refcount));
 213                 kref_get(&obj->refcount);
 214         }
 215 }
 216 EXPORT_SYMBOL(drm_mode_object_get);
 217 
 218 /**
 219  * drm_object_attach_property - attach a property to a modeset object
 220  * @obj: drm modeset object
 221  * @property: property to attach
 222  * @init_val: initial value of the property
 223  *
 224  * This attaches the given property to the modeset object with the given initial
 225  * value. Currently this function cannot fail since the properties are stored in
 226  * a statically sized array.
 227  */
 228 void drm_object_attach_property(struct drm_mode_object *obj,
 229                                 struct drm_property *property,
 230                                 uint64_t init_val)
 231 {
 232         int count = obj->properties->count;
 233 
 234         if (count == DRM_OBJECT_MAX_PROPERTY) {
 235                 WARN(1, "Failed to attach object property (type: 0x%x). Please "
 236                         "increase DRM_OBJECT_MAX_PROPERTY by 1 for each time "
 237                         "you see this message on the same object type.\n",
 238                         obj->type);
 239                 return;
 240         }
 241 
 242         obj->properties->properties[count] = property;
 243         obj->properties->values[count] = init_val;
 244         obj->properties->count++;
 245 }
 246 EXPORT_SYMBOL(drm_object_attach_property);
 247 
 248 /**
 249  * drm_object_property_set_value - set the value of a property
 250  * @obj: drm mode object to set property value for
 251  * @property: property to set
 252  * @val: value the property should be set to
 253  *
 254  * This function sets a given property on a given object. This function only
 255  * changes the software state of the property, it does not call into the
 256  * driver's ->set_property callback.
 257  *
 258  * Note that atomic drivers should not have any need to call this, the core will
 259  * ensure consistency of values reported back to userspace through the
 260  * appropriate ->atomic_get_property callback. Only legacy drivers should call
 261  * this function to update the tracked value (after clamping and other
 262  * restrictions have been applied).
 263  *
 264  * Returns:
 265  * Zero on success, error code on failure.
 266  */
 267 int drm_object_property_set_value(struct drm_mode_object *obj,
 268                                   struct drm_property *property, uint64_t val)
 269 {
 270         int i;
 271 
 272         WARN_ON(drm_drv_uses_atomic_modeset(property->dev) &&
 273                 !(property->flags & DRM_MODE_PROP_IMMUTABLE));
 274 
 275         for (i = 0; i < obj->properties->count; i++) {
 276                 if (obj->properties->properties[i] == property) {
 277                         obj->properties->values[i] = val;
 278                         return 0;
 279                 }
 280         }
 281 
 282         return -EINVAL;
 283 }
 284 EXPORT_SYMBOL(drm_object_property_set_value);
 285 
 286 static int __drm_object_property_get_value(struct drm_mode_object *obj,
 287                                            struct drm_property *property,
 288                                            uint64_t *val)
 289 {
 290         int i;
 291 
 292         /* read-only properties bypass atomic mechanism and still store
 293          * their value in obj->properties->values[].. mostly to avoid
 294          * having to deal w/ EDID and similar props in atomic paths:
 295          */
 296         if (drm_drv_uses_atomic_modeset(property->dev) &&
 297                         !(property->flags & DRM_MODE_PROP_IMMUTABLE))
 298                 return drm_atomic_get_property(obj, property, val);
 299 
 300         for (i = 0; i < obj->properties->count; i++) {
 301                 if (obj->properties->properties[i] == property) {
 302                         *val = obj->properties->values[i];
 303                         return 0;
 304                 }
 305 
 306         }
 307 
 308         return -EINVAL;
 309 }
 310 
 311 /**
 312  * drm_object_property_get_value - retrieve the value of a property
 313  * @obj: drm mode object to get property value from
 314  * @property: property to retrieve
 315  * @val: storage for the property value
 316  *
 317  * This function retrieves the softare state of the given property for the given
 318  * property. Since there is no driver callback to retrieve the current property
 319  * value this might be out of sync with the hardware, depending upon the driver
 320  * and property.
 321  *
 322  * Atomic drivers should never call this function directly, the core will read
 323  * out property values through the various ->atomic_get_property callbacks.
 324  *
 325  * Returns:
 326  * Zero on success, error code on failure.
 327  */
 328 int drm_object_property_get_value(struct drm_mode_object *obj,
 329                                   struct drm_property *property, uint64_t *val)
 330 {
 331         WARN_ON(drm_drv_uses_atomic_modeset(property->dev));
 332 
 333         return __drm_object_property_get_value(obj, property, val);
 334 }
 335 EXPORT_SYMBOL(drm_object_property_get_value);
 336 
 337 /* helper for getconnector and getproperties ioctls */
 338 int drm_mode_object_get_properties(struct drm_mode_object *obj, bool atomic,
 339                                    uint32_t __user *prop_ptr,
 340                                    uint64_t __user *prop_values,
 341                                    uint32_t *arg_count_props)
 342 {
 343         int i, ret, count;
 344 
 345         for (i = 0, count = 0; i < obj->properties->count; i++) {
 346                 struct drm_property *prop = obj->properties->properties[i];
 347                 uint64_t val;
 348 
 349                 if ((prop->flags & DRM_MODE_PROP_ATOMIC) && !atomic)
 350                         continue;
 351 
 352                 if (*arg_count_props > count) {
 353                         ret = __drm_object_property_get_value(obj, prop, &val);
 354                         if (ret)
 355                                 return ret;
 356 
 357                         if (put_user(prop->base.id, prop_ptr + count))
 358                                 return -EFAULT;
 359 
 360                         if (put_user(val, prop_values + count))
 361                                 return -EFAULT;
 362                 }
 363 
 364                 count++;
 365         }
 366         *arg_count_props = count;
 367 
 368         return 0;
 369 }
 370 
 371 /**
 372  * drm_mode_obj_get_properties_ioctl - get the current value of a object's property
 373  * @dev: DRM device
 374  * @data: ioctl data
 375  * @file_priv: DRM file info
 376  *
 377  * This function retrieves the current value for an object's property. Compared
 378  * to the connector specific ioctl this one is extended to also work on crtc and
 379  * plane objects.
 380  *
 381  * Called by the user via ioctl.
 382  *
 383  * Returns:
 384  * Zero on success, negative errno on failure.
 385  */
 386 int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data,
 387                                       struct drm_file *file_priv)
 388 {
 389         struct drm_mode_obj_get_properties *arg = data;
 390         struct drm_mode_object *obj;
 391         int ret = 0;
 392 
 393         if (!drm_core_check_feature(dev, DRIVER_MODESET))
 394                 return -EOPNOTSUPP;
 395 
 396         drm_modeset_lock_all(dev);
 397 
 398         obj = drm_mode_object_find(dev, file_priv, arg->obj_id, arg->obj_type);
 399         if (!obj) {
 400                 ret = -ENOENT;
 401                 goto out;
 402         }
 403         if (!obj->properties) {
 404                 ret = -EINVAL;
 405                 goto out_unref;
 406         }
 407 
 408         ret = drm_mode_object_get_properties(obj, file_priv->atomic,
 409                         (uint32_t __user *)(unsigned long)(arg->props_ptr),
 410                         (uint64_t __user *)(unsigned long)(arg->prop_values_ptr),
 411                         &arg->count_props);
 412 
 413 out_unref:
 414         drm_mode_object_put(obj);
 415 out:
 416         drm_modeset_unlock_all(dev);
 417         return ret;
 418 }
 419 
 420 struct drm_property *drm_mode_obj_find_prop_id(struct drm_mode_object *obj,
 421                                                uint32_t prop_id)
 422 {
 423         int i;
 424 
 425         for (i = 0; i < obj->properties->count; i++)
 426                 if (obj->properties->properties[i]->base.id == prop_id)
 427                         return obj->properties->properties[i];
 428 
 429         return NULL;
 430 }
 431 
 432 static int set_property_legacy(struct drm_mode_object *obj,
 433                                struct drm_property *prop,
 434                                uint64_t prop_value)
 435 {
 436         struct drm_device *dev = prop->dev;
 437         struct drm_mode_object *ref;
 438         int ret = -EINVAL;
 439 
 440         if (!drm_property_change_valid_get(prop, prop_value, &ref))
 441                 return -EINVAL;
 442 
 443         drm_modeset_lock_all(dev);
 444         switch (obj->type) {
 445         case DRM_MODE_OBJECT_CONNECTOR:
 446                 ret = drm_connector_set_obj_prop(obj, prop, prop_value);
 447                 break;
 448         case DRM_MODE_OBJECT_CRTC:
 449                 ret = drm_mode_crtc_set_obj_prop(obj, prop, prop_value);
 450                 break;
 451         case DRM_MODE_OBJECT_PLANE:
 452                 ret = drm_mode_plane_set_obj_prop(obj_to_plane(obj),
 453                                                   prop, prop_value);
 454                 break;
 455         }
 456         drm_property_change_valid_put(prop, ref);
 457         drm_modeset_unlock_all(dev);
 458 
 459         return ret;
 460 }
 461 
 462 static int set_property_atomic(struct drm_mode_object *obj,
 463                                struct drm_file *file_priv,
 464                                struct drm_property *prop,
 465                                uint64_t prop_value)
 466 {
 467         struct drm_device *dev = prop->dev;
 468         struct drm_atomic_state *state;
 469         struct drm_modeset_acquire_ctx ctx;
 470         int ret;
 471 
 472         state = drm_atomic_state_alloc(dev);
 473         if (!state)
 474                 return -ENOMEM;
 475 
 476         drm_modeset_acquire_init(&ctx, 0);
 477         state->acquire_ctx = &ctx;
 478 
 479 retry:
 480         if (prop == state->dev->mode_config.dpms_property) {
 481                 if (obj->type != DRM_MODE_OBJECT_CONNECTOR) {
 482                         ret = -EINVAL;
 483                         goto out;
 484                 }
 485 
 486                 ret = drm_atomic_connector_commit_dpms(state,
 487                                                        obj_to_connector(obj),
 488                                                        prop_value);
 489         } else {
 490                 ret = drm_atomic_set_property(state, file_priv, obj, prop, prop_value);
 491                 if (ret)
 492                         goto out;
 493                 ret = drm_atomic_commit(state);
 494         }
 495 out:
 496         if (ret == -EDEADLK) {
 497                 drm_atomic_state_clear(state);
 498                 drm_modeset_backoff(&ctx);
 499                 goto retry;
 500         }
 501 
 502         drm_atomic_state_put(state);
 503 
 504         drm_modeset_drop_locks(&ctx);
 505         drm_modeset_acquire_fini(&ctx);
 506 
 507         return ret;
 508 }
 509 
 510 int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,
 511                                     struct drm_file *file_priv)
 512 {
 513         struct drm_mode_obj_set_property *arg = data;
 514         struct drm_mode_object *arg_obj;
 515         struct drm_property *property;
 516         int ret = -EINVAL;
 517 
 518         if (!drm_core_check_feature(dev, DRIVER_MODESET))
 519                 return -EOPNOTSUPP;
 520 
 521         arg_obj = drm_mode_object_find(dev, file_priv, arg->obj_id, arg->obj_type);
 522         if (!arg_obj)
 523                 return -ENOENT;
 524 
 525         if (!arg_obj->properties)
 526                 goto out_unref;
 527 
 528         property = drm_mode_obj_find_prop_id(arg_obj, arg->prop_id);
 529         if (!property)
 530                 goto out_unref;
 531 
 532         if (drm_drv_uses_atomic_modeset(property->dev))
 533                 ret = set_property_atomic(arg_obj, file_priv, property, arg->value);
 534         else
 535                 ret = set_property_legacy(arg_obj, property, arg->value);
 536 
 537 out_unref:
 538         drm_mode_object_put(arg_obj);
 539         return ret;
 540 }

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