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 * Note that all properties must be attached before the object itself is 229 * registered and accessible from userspace. 230 */ 231 void drm_object_attach_property(struct drm_mode_object *obj, 232 struct drm_property *property, 233 uint64_t init_val) 234 { 235 int count = obj->properties->count; 236 struct drm_device *dev = property->dev; 237 238 239 if (obj->type == DRM_MODE_OBJECT_CONNECTOR) { 240 struct drm_connector *connector = obj_to_connector(obj); 241 242 WARN_ON(!dev->driver->load && 243 connector->registration_state == DRM_CONNECTOR_REGISTERED); 244 } else { 245 WARN_ON(!dev->driver->load && dev->registered); 246 } 247 248 if (count == DRM_OBJECT_MAX_PROPERTY) { 249 WARN(1, "Failed to attach object property (type: 0x%x). Please " 250 "increase DRM_OBJECT_MAX_PROPERTY by 1 for each time " 251 "you see this message on the same object type.\n", 252 obj->type); 253 return; 254 } 255 256 obj->properties->properties[count] = property; 257 obj->properties->values[count] = init_val; 258 obj->properties->count++; 259 } 260 EXPORT_SYMBOL(drm_object_attach_property); 261 262 /** 263 * drm_object_property_set_value - set the value of a property 264 * @obj: drm mode object to set property value for 265 * @property: property to set 266 * @val: value the property should be set to 267 * 268 * This function sets a given property on a given object. This function only 269 * changes the software state of the property, it does not call into the 270 * driver's ->set_property callback. 271 * 272 * Note that atomic drivers should not have any need to call this, the core will 273 * ensure consistency of values reported back to userspace through the 274 * appropriate ->atomic_get_property callback. Only legacy drivers should call 275 * this function to update the tracked value (after clamping and other 276 * restrictions have been applied). 277 * 278 * Returns: 279 * Zero on success, error code on failure. 280 */ 281 int drm_object_property_set_value(struct drm_mode_object *obj, 282 struct drm_property *property, uint64_t val) 283 { 284 int i; 285 286 WARN_ON(drm_drv_uses_atomic_modeset(property->dev) && 287 !(property->flags & DRM_MODE_PROP_IMMUTABLE)); 288 289 for (i = 0; i < obj->properties->count; i++) { 290 if (obj->properties->properties[i] == property) { 291 obj->properties->values[i] = val; 292 return 0; 293 } 294 } 295 296 return -EINVAL; 297 } 298 EXPORT_SYMBOL(drm_object_property_set_value); 299 300 static int __drm_object_property_get_value(struct drm_mode_object *obj, 301 struct drm_property *property, 302 uint64_t *val) 303 { 304 int i; 305 306 /* read-only properties bypass atomic mechanism and still store 307 * their value in obj->properties->values[].. mostly to avoid 308 * having to deal w/ EDID and similar props in atomic paths: 309 */ 310 if (drm_drv_uses_atomic_modeset(property->dev) && 311 !(property->flags & DRM_MODE_PROP_IMMUTABLE)) 312 return drm_atomic_get_property(obj, property, val); 313 314 for (i = 0; i < obj->properties->count; i++) { 315 if (obj->properties->properties[i] == property) { 316 *val = obj->properties->values[i]; 317 return 0; 318 } 319 320 } 321 322 return -EINVAL; 323 } 324 325 /** 326 * drm_object_property_get_value - retrieve the value of a property 327 * @obj: drm mode object to get property value from 328 * @property: property to retrieve 329 * @val: storage for the property value 330 * 331 * This function retrieves the softare state of the given property for the given 332 * property. Since there is no driver callback to retrieve the current property 333 * value this might be out of sync with the hardware, depending upon the driver 334 * and property. 335 * 336 * Atomic drivers should never call this function directly, the core will read 337 * out property values through the various ->atomic_get_property callbacks. 338 * 339 * Returns: 340 * Zero on success, error code on failure. 341 */ 342 int drm_object_property_get_value(struct drm_mode_object *obj, 343 struct drm_property *property, uint64_t *val) 344 { 345 WARN_ON(drm_drv_uses_atomic_modeset(property->dev)); 346 347 return __drm_object_property_get_value(obj, property, val); 348 } 349 EXPORT_SYMBOL(drm_object_property_get_value); 350 351 /* helper for getconnector and getproperties ioctls */ 352 int drm_mode_object_get_properties(struct drm_mode_object *obj, bool atomic, 353 uint32_t __user *prop_ptr, 354 uint64_t __user *prop_values, 355 uint32_t *arg_count_props) 356 { 357 int i, ret, count; 358 359 for (i = 0, count = 0; i < obj->properties->count; i++) { 360 struct drm_property *prop = obj->properties->properties[i]; 361 uint64_t val; 362 363 if ((prop->flags & DRM_MODE_PROP_ATOMIC) && !atomic) 364 continue; 365 366 if (*arg_count_props > count) { 367 ret = __drm_object_property_get_value(obj, prop, &val); 368 if (ret) 369 return ret; 370 371 if (put_user(prop->base.id, prop_ptr + count)) 372 return -EFAULT; 373 374 if (put_user(val, prop_values + count)) 375 return -EFAULT; 376 } 377 378 count++; 379 } 380 *arg_count_props = count; 381 382 return 0; 383 } 384 385 /** 386 * drm_mode_obj_get_properties_ioctl - get the current value of a object's property 387 * @dev: DRM device 388 * @data: ioctl data 389 * @file_priv: DRM file info 390 * 391 * This function retrieves the current value for an object's property. Compared 392 * to the connector specific ioctl this one is extended to also work on crtc and 393 * plane objects. 394 * 395 * Called by the user via ioctl. 396 * 397 * Returns: 398 * Zero on success, negative errno on failure. 399 */ 400 int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data, 401 struct drm_file *file_priv) 402 { 403 struct drm_mode_obj_get_properties *arg = data; 404 struct drm_mode_object *obj; 405 int ret = 0; 406 407 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 408 return -EOPNOTSUPP; 409 410 drm_modeset_lock_all(dev); 411 412 obj = drm_mode_object_find(dev, file_priv, arg->obj_id, arg->obj_type); 413 if (!obj) { 414 ret = -ENOENT; 415 goto out; 416 } 417 if (!obj->properties) { 418 ret = -EINVAL; 419 goto out_unref; 420 } 421 422 ret = drm_mode_object_get_properties(obj, file_priv->atomic, 423 (uint32_t __user *)(unsigned long)(arg->props_ptr), 424 (uint64_t __user *)(unsigned long)(arg->prop_values_ptr), 425 &arg->count_props); 426 427 out_unref: 428 drm_mode_object_put(obj); 429 out: 430 drm_modeset_unlock_all(dev); 431 return ret; 432 } 433 434 struct drm_property *drm_mode_obj_find_prop_id(struct drm_mode_object *obj, 435 uint32_t prop_id) 436 { 437 int i; 438 439 for (i = 0; i < obj->properties->count; i++) 440 if (obj->properties->properties[i]->base.id == prop_id) 441 return obj->properties->properties[i]; 442 443 return NULL; 444 } 445 446 static int set_property_legacy(struct drm_mode_object *obj, 447 struct drm_property *prop, 448 uint64_t prop_value) 449 { 450 struct drm_device *dev = prop->dev; 451 struct drm_mode_object *ref; 452 int ret = -EINVAL; 453 454 if (!drm_property_change_valid_get(prop, prop_value, &ref)) 455 return -EINVAL; 456 457 drm_modeset_lock_all(dev); 458 switch (obj->type) { 459 case DRM_MODE_OBJECT_CONNECTOR: 460 ret = drm_connector_set_obj_prop(obj, prop, prop_value); 461 break; 462 case DRM_MODE_OBJECT_CRTC: 463 ret = drm_mode_crtc_set_obj_prop(obj, prop, prop_value); 464 break; 465 case DRM_MODE_OBJECT_PLANE: 466 ret = drm_mode_plane_set_obj_prop(obj_to_plane(obj), 467 prop, prop_value); 468 break; 469 } 470 drm_property_change_valid_put(prop, ref); 471 drm_modeset_unlock_all(dev); 472 473 return ret; 474 } 475 476 static int set_property_atomic(struct drm_mode_object *obj, 477 struct drm_file *file_priv, 478 struct drm_property *prop, 479 uint64_t prop_value) 480 { 481 struct drm_device *dev = prop->dev; 482 struct drm_atomic_state *state; 483 struct drm_modeset_acquire_ctx ctx; 484 int ret; 485 486 state = drm_atomic_state_alloc(dev); 487 if (!state) 488 return -ENOMEM; 489 490 drm_modeset_acquire_init(&ctx, 0); 491 state->acquire_ctx = &ctx; 492 493 retry: 494 if (prop == state->dev->mode_config.dpms_property) { 495 if (obj->type != DRM_MODE_OBJECT_CONNECTOR) { 496 ret = -EINVAL; 497 goto out; 498 } 499 500 ret = drm_atomic_connector_commit_dpms(state, 501 obj_to_connector(obj), 502 prop_value); 503 } else { 504 ret = drm_atomic_set_property(state, file_priv, obj, prop, prop_value); 505 if (ret) 506 goto out; 507 ret = drm_atomic_commit(state); 508 } 509 out: 510 if (ret == -EDEADLK) { 511 drm_atomic_state_clear(state); 512 drm_modeset_backoff(&ctx); 513 goto retry; 514 } 515 516 drm_atomic_state_put(state); 517 518 drm_modeset_drop_locks(&ctx); 519 drm_modeset_acquire_fini(&ctx); 520 521 return ret; 522 } 523 524 int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data, 525 struct drm_file *file_priv) 526 { 527 struct drm_mode_obj_set_property *arg = data; 528 struct drm_mode_object *arg_obj; 529 struct drm_property *property; 530 int ret = -EINVAL; 531 532 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 533 return -EOPNOTSUPP; 534 535 arg_obj = drm_mode_object_find(dev, file_priv, arg->obj_id, arg->obj_type); 536 if (!arg_obj) 537 return -ENOENT; 538 539 if (!arg_obj->properties) 540 goto out_unref; 541 542 property = drm_mode_obj_find_prop_id(arg_obj, arg->prop_id); 543 if (!property) 544 goto out_unref; 545 546 if (drm_drv_uses_atomic_modeset(property->dev)) 547 ret = set_property_atomic(arg_obj, file_priv, property, arg->value); 548 else 549 ret = set_property_legacy(arg_obj, property, arg->value); 550 551 out_unref: 552 drm_mode_object_put(arg_obj); 553 return ret; 554 } 555