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 } 541