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 EXPORT_SYMBOL_FOR_TESTS_ONLY(drm_mode_object_add); 85 86 void drm_mode_object_register(struct drm_device *dev, 87 struct drm_mode_object *obj) 88 { 89 mutex_lock(&dev->mode_config.idr_mutex); 90 idr_replace(&dev->mode_config.object_idr, obj, obj->id); 91 mutex_unlock(&dev->mode_config.idr_mutex); 92 } 93 94 /** 95 * drm_mode_object_unregister - free a modeset identifier 96 * @dev: DRM device 97 * @object: object to free 98 * 99 * Free @id from @dev's unique identifier pool. 100 * This function can be called multiple times, and guards against 101 * multiple removals. 102 * These modeset identifiers are _not_ reference counted. Hence don't use this 103 * for reference counted modeset objects like framebuffers. 104 */ 105 void drm_mode_object_unregister(struct drm_device *dev, 106 struct drm_mode_object *object) 107 { 108 WARN_ON(!dev->driver->load && dev->registered && !object->free_cb); 109 110 mutex_lock(&dev->mode_config.idr_mutex); 111 if (object->id) { 112 idr_remove(&dev->mode_config.object_idr, object->id); 113 object->id = 0; 114 } 115 mutex_unlock(&dev->mode_config.idr_mutex); 116 } 117 118 /** 119 * drm_mode_object_lease_required - check types which must be leased to be used 120 * @type: type of object 121 * 122 * Returns whether the provided type of drm_mode_object must 123 * be owned or leased to be used by a process. 124 */ 125 bool drm_mode_object_lease_required(uint32_t type) 126 { 127 switch(type) { 128 case DRM_MODE_OBJECT_CRTC: 129 case DRM_MODE_OBJECT_CONNECTOR: 130 case DRM_MODE_OBJECT_PLANE: 131 return true; 132 default: 133 return false; 134 } 135 } 136 137 struct drm_mode_object *__drm_mode_object_find(struct drm_device *dev, 138 struct drm_file *file_priv, 139 uint32_t id, uint32_t type) 140 { 141 struct drm_mode_object *obj = NULL; 142 143 mutex_lock(&dev->mode_config.idr_mutex); 144 obj = idr_find(&dev->mode_config.object_idr, id); 145 if (obj && type != DRM_MODE_OBJECT_ANY && obj->type != type) 146 obj = NULL; 147 if (obj && obj->id != id) 148 obj = NULL; 149 150 if (obj && drm_mode_object_lease_required(obj->type) && 151 !_drm_lease_held(file_priv, obj->id)) { 152 drm_dbg_kms(dev, "[OBJECT:%d] not included in lease", id); 153 obj = NULL; 154 } 155 156 if (obj && obj->free_cb) { 157 if (!kref_get_unless_zero(&obj->refcount)) 158 obj = NULL; 159 } 160 mutex_unlock(&dev->mode_config.idr_mutex); 161 162 return obj; 163 } 164 165 /** 166 * drm_mode_object_find - look up a drm object with static lifetime 167 * @dev: drm device 168 * @file_priv: drm file 169 * @id: id of the mode object 170 * @type: type of the mode object 171 * 172 * This function is used to look up a modeset object. It will acquire a 173 * reference for reference counted objects. This reference must be dropped again 174 * by callind drm_mode_object_put(). 175 */ 176 struct drm_mode_object *drm_mode_object_find(struct drm_device *dev, 177 struct drm_file *file_priv, 178 uint32_t id, uint32_t type) 179 { 180 struct drm_mode_object *obj = NULL; 181 182 obj = __drm_mode_object_find(dev, file_priv, id, type); 183 return obj; 184 } 185 EXPORT_SYMBOL(drm_mode_object_find); 186 187 /** 188 * drm_mode_object_put - release a mode object reference 189 * @obj: DRM mode object 190 * 191 * This function decrements the object's refcount if it is a refcounted modeset 192 * object. It is a no-op on any other object. This is used to drop references 193 * acquired with drm_mode_object_get(). 194 */ 195 void drm_mode_object_put(struct drm_mode_object *obj) 196 { 197 if (obj->free_cb) { 198 DRM_DEBUG("OBJ ID: %d (%d)\n", obj->id, kref_read(&obj->refcount)); 199 kref_put(&obj->refcount, obj->free_cb); 200 } 201 } 202 EXPORT_SYMBOL(drm_mode_object_put); 203 204 /** 205 * drm_mode_object_get - acquire a mode object reference 206 * @obj: DRM mode object 207 * 208 * This function increments the object's refcount if it is a refcounted modeset 209 * object. It is a no-op on any other object. References should be dropped again 210 * by calling drm_mode_object_put(). 211 */ 212 void drm_mode_object_get(struct drm_mode_object *obj) 213 { 214 if (obj->free_cb) { 215 DRM_DEBUG("OBJ ID: %d (%d)\n", obj->id, kref_read(&obj->refcount)); 216 kref_get(&obj->refcount); 217 } 218 } 219 EXPORT_SYMBOL(drm_mode_object_get); 220 221 /** 222 * drm_object_attach_property - attach a property to a modeset object 223 * @obj: drm modeset object 224 * @property: property to attach 225 * @init_val: initial value of the property 226 * 227 * This attaches the given property to the modeset object with the given initial 228 * value. Currently this function cannot fail since the properties are stored in 229 * a statically sized array. 230 * 231 * Note that all properties must be attached before the object itself is 232 * registered and accessible from userspace. 233 */ 234 void drm_object_attach_property(struct drm_mode_object *obj, 235 struct drm_property *property, 236 uint64_t init_val) 237 { 238 int count = obj->properties->count; 239 struct drm_device *dev = property->dev; 240 241 242 if (obj->type == DRM_MODE_OBJECT_CONNECTOR) { 243 struct drm_connector *connector = obj_to_connector(obj); 244 245 WARN_ON(!dev->driver->load && 246 connector->registration_state == DRM_CONNECTOR_REGISTERED); 247 } else { 248 WARN_ON(!dev->driver->load && dev->registered); 249 } 250 251 if (count == DRM_OBJECT_MAX_PROPERTY) { 252 WARN(1, "Failed to attach object property (type: 0x%x). Please " 253 "increase DRM_OBJECT_MAX_PROPERTY by 1 for each time " 254 "you see this message on the same object type.\n", 255 obj->type); 256 return; 257 } 258 259 obj->properties->properties[count] = property; 260 obj->properties->values[count] = init_val; 261 obj->properties->count++; 262 } 263 EXPORT_SYMBOL(drm_object_attach_property); 264 265 /** 266 * drm_object_property_set_value - set the value of a property 267 * @obj: drm mode object to set property value for 268 * @property: property to set 269 * @val: value the property should be set to 270 * 271 * This function sets a given property on a given object. This function only 272 * changes the software state of the property, it does not call into the 273 * driver's ->set_property callback. 274 * 275 * Note that atomic drivers should not have any need to call this, the core will 276 * ensure consistency of values reported back to userspace through the 277 * appropriate ->atomic_get_property callback. Only legacy drivers should call 278 * this function to update the tracked value (after clamping and other 279 * restrictions have been applied). 280 * 281 * Returns: 282 * Zero on success, error code on failure. 283 */ 284 int drm_object_property_set_value(struct drm_mode_object *obj, 285 struct drm_property *property, uint64_t val) 286 { 287 int i; 288 289 WARN_ON(drm_drv_uses_atomic_modeset(property->dev) && 290 !(property->flags & DRM_MODE_PROP_IMMUTABLE)); 291 292 for (i = 0; i < obj->properties->count; i++) { 293 if (obj->properties->properties[i] == property) { 294 obj->properties->values[i] = val; 295 return 0; 296 } 297 } 298 299 return -EINVAL; 300 } 301 EXPORT_SYMBOL(drm_object_property_set_value); 302 303 static int __drm_object_property_get_prop_value(struct drm_mode_object *obj, 304 struct drm_property *property, 305 uint64_t *val) 306 { 307 int i; 308 309 for (i = 0; i < obj->properties->count; i++) { 310 if (obj->properties->properties[i] == property) { 311 *val = obj->properties->values[i]; 312 return 0; 313 } 314 } 315 316 return -EINVAL; 317 } 318 319 static int __drm_object_property_get_value(struct drm_mode_object *obj, 320 struct drm_property *property, 321 uint64_t *val) 322 { 323 324 /* read-only properties bypass atomic mechanism and still store 325 * their value in obj->properties->values[].. mostly to avoid 326 * having to deal w/ EDID and similar props in atomic paths: 327 */ 328 if (drm_drv_uses_atomic_modeset(property->dev) && 329 !(property->flags & DRM_MODE_PROP_IMMUTABLE)) 330 return drm_atomic_get_property(obj, property, val); 331 332 return __drm_object_property_get_prop_value(obj, property, val); 333 } 334 335 /** 336 * drm_object_property_get_value - retrieve the value of a property 337 * @obj: drm mode object to get property value from 338 * @property: property to retrieve 339 * @val: storage for the property value 340 * 341 * This function retrieves the softare state of the given property for the given 342 * property. Since there is no driver callback to retrieve the current property 343 * value this might be out of sync with the hardware, depending upon the driver 344 * and property. 345 * 346 * Atomic drivers should never call this function directly, the core will read 347 * out property values through the various ->atomic_get_property callbacks. 348 * 349 * Returns: 350 * Zero on success, error code on failure. 351 */ 352 int drm_object_property_get_value(struct drm_mode_object *obj, 353 struct drm_property *property, uint64_t *val) 354 { 355 WARN_ON(drm_drv_uses_atomic_modeset(property->dev)); 356 357 return __drm_object_property_get_value(obj, property, val); 358 } 359 EXPORT_SYMBOL(drm_object_property_get_value); 360 361 /** 362 * drm_object_property_get_default_value - retrieve the default value of a 363 * property when in atomic mode. 364 * @obj: drm mode object to get property value from 365 * @property: property to retrieve 366 * @val: storage for the property value 367 * 368 * This function retrieves the default state of the given property as passed in 369 * to drm_object_attach_property 370 * 371 * Only atomic drivers should call this function directly, as for non-atomic 372 * drivers it will return the current value. 373 * 374 * Returns: 375 * Zero on success, error code on failure. 376 */ 377 int drm_object_property_get_default_value(struct drm_mode_object *obj, 378 struct drm_property *property, 379 uint64_t *val) 380 { 381 WARN_ON(!drm_drv_uses_atomic_modeset(property->dev)); 382 383 return __drm_object_property_get_prop_value(obj, property, val); 384 } 385 EXPORT_SYMBOL(drm_object_property_get_default_value); 386 387 /* helper for getconnector and getproperties ioctls */ 388 int drm_mode_object_get_properties(struct drm_mode_object *obj, bool atomic, 389 uint32_t __user *prop_ptr, 390 uint64_t __user *prop_values, 391 uint32_t *arg_count_props) 392 { 393 int i, ret, count; 394 395 for (i = 0, count = 0; i < obj->properties->count; i++) { 396 struct drm_property *prop = obj->properties->properties[i]; 397 uint64_t val; 398 399 if ((prop->flags & DRM_MODE_PROP_ATOMIC) && !atomic) 400 continue; 401 402 if (*arg_count_props > count) { 403 ret = __drm_object_property_get_value(obj, prop, &val); 404 if (ret) 405 return ret; 406 407 if (put_user(prop->base.id, prop_ptr + count)) 408 return -EFAULT; 409 410 if (put_user(val, prop_values + count)) 411 return -EFAULT; 412 } 413 414 count++; 415 } 416 *arg_count_props = count; 417 418 return 0; 419 } 420 421 /** 422 * drm_mode_obj_get_properties_ioctl - get the current value of a object's property 423 * @dev: DRM device 424 * @data: ioctl data 425 * @file_priv: DRM file info 426 * 427 * This function retrieves the current value for an object's property. Compared 428 * to the connector specific ioctl this one is extended to also work on crtc and 429 * plane objects. 430 * 431 * Called by the user via ioctl. 432 * 433 * Returns: 434 * Zero on success, negative errno on failure. 435 */ 436 int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data, 437 struct drm_file *file_priv) 438 { 439 struct drm_mode_obj_get_properties *arg = data; 440 struct drm_mode_object *obj; 441 struct drm_modeset_acquire_ctx ctx; 442 int ret = 0; 443 444 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 445 return -EOPNOTSUPP; 446 447 DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx, 0, ret); 448 449 obj = drm_mode_object_find(dev, file_priv, arg->obj_id, arg->obj_type); 450 if (!obj) { 451 ret = -ENOENT; 452 goto out; 453 } 454 if (!obj->properties) { 455 ret = -EINVAL; 456 goto out_unref; 457 } 458 459 ret = drm_mode_object_get_properties(obj, file_priv->atomic, 460 (uint32_t __user *)(unsigned long)(arg->props_ptr), 461 (uint64_t __user *)(unsigned long)(arg->prop_values_ptr), 462 &arg->count_props); 463 464 out_unref: 465 drm_mode_object_put(obj); 466 out: 467 DRM_MODESET_LOCK_ALL_END(dev, ctx, ret); 468 return ret; 469 } 470 471 struct drm_property *drm_mode_obj_find_prop_id(struct drm_mode_object *obj, 472 uint32_t prop_id) 473 { 474 int i; 475 476 for (i = 0; i < obj->properties->count; i++) 477 if (obj->properties->properties[i]->base.id == prop_id) 478 return obj->properties->properties[i]; 479 480 return NULL; 481 } 482 EXPORT_SYMBOL_FOR_TESTS_ONLY(drm_mode_obj_find_prop_id); 483 484 static int set_property_legacy(struct drm_mode_object *obj, 485 struct drm_property *prop, 486 uint64_t prop_value) 487 { 488 struct drm_device *dev = prop->dev; 489 struct drm_mode_object *ref; 490 struct drm_modeset_acquire_ctx ctx; 491 int ret = -EINVAL; 492 493 if (!drm_property_change_valid_get(prop, prop_value, &ref)) 494 return -EINVAL; 495 496 DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx, 0, ret); 497 switch (obj->type) { 498 case DRM_MODE_OBJECT_CONNECTOR: 499 ret = drm_connector_set_obj_prop(obj, prop, prop_value); 500 break; 501 case DRM_MODE_OBJECT_CRTC: 502 ret = drm_mode_crtc_set_obj_prop(obj, prop, prop_value); 503 break; 504 case DRM_MODE_OBJECT_PLANE: 505 ret = drm_mode_plane_set_obj_prop(obj_to_plane(obj), 506 prop, prop_value); 507 break; 508 } 509 drm_property_change_valid_put(prop, ref); 510 DRM_MODESET_LOCK_ALL_END(dev, ctx, ret); 511 512 return ret; 513 } 514 515 static int set_property_atomic(struct drm_mode_object *obj, 516 struct drm_file *file_priv, 517 struct drm_property *prop, 518 uint64_t prop_value) 519 { 520 struct drm_device *dev = prop->dev; 521 struct drm_atomic_state *state; 522 struct drm_modeset_acquire_ctx ctx; 523 int ret; 524 525 state = drm_atomic_state_alloc(dev); 526 if (!state) 527 return -ENOMEM; 528 529 drm_modeset_acquire_init(&ctx, 0); 530 state->acquire_ctx = &ctx; 531 532 retry: 533 if (prop == state->dev->mode_config.dpms_property) { 534 if (obj->type != DRM_MODE_OBJECT_CONNECTOR) { 535 ret = -EINVAL; 536 goto out; 537 } 538 539 ret = drm_atomic_connector_commit_dpms(state, 540 obj_to_connector(obj), 541 prop_value); 542 } else { 543 ret = drm_atomic_set_property(state, file_priv, obj, prop, prop_value, false); 544 if (ret) 545 goto out; 546 ret = drm_atomic_commit(state); 547 } 548 out: 549 if (ret == -EDEADLK) { 550 drm_atomic_state_clear(state); 551 drm_modeset_backoff(&ctx); 552 goto retry; 553 } 554 555 drm_atomic_state_put(state); 556 557 drm_modeset_drop_locks(&ctx); 558 drm_modeset_acquire_fini(&ctx); 559 560 return ret; 561 } 562 563 int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data, 564 struct drm_file *file_priv) 565 { 566 struct drm_mode_obj_set_property *arg = data; 567 struct drm_mode_object *arg_obj; 568 struct drm_property *property; 569 int ret = -EINVAL; 570 571 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 572 return -EOPNOTSUPP; 573 574 arg_obj = drm_mode_object_find(dev, file_priv, arg->obj_id, arg->obj_type); 575 if (!arg_obj) 576 return -ENOENT; 577 578 if (!arg_obj->properties) 579 goto out_unref; 580 581 property = drm_mode_obj_find_prop_id(arg_obj, arg->prop_id); 582 if (!property) 583 goto out_unref; 584 585 if (drm_drv_uses_atomic_modeset(property->dev)) 586 ret = set_property_atomic(arg_obj, file_priv, property, arg->value); 587 else 588 ret = set_property_legacy(arg_obj, property, arg->value); 589 590 out_unref: 591 drm_mode_object_put(arg_obj); 592 return ret; 593 } 594