Home | History | Annotate | Line # | Download | only in drm
      1 /*	$NetBSD: drm_property.c,v 1.4 2021/12/19 09:50:27 riastradh Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2016 Intel Corporation
      5  *
      6  * Permission to use, copy, modify, distribute, and sell this software and its
      7  * documentation for any purpose is hereby granted without fee, provided that
      8  * the above copyright notice appear in all copies and that both that copyright
      9  * notice and this permission notice appear in supporting documentation, and
     10  * that the name of the copyright holders not be used in advertising or
     11  * publicity pertaining to distribution of the software without specific,
     12  * written prior permission.  The copyright holders make no representations
     13  * about the suitability of this software for any purpose.  It is provided "as
     14  * is" without express or implied warranty.
     15  *
     16  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
     17  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
     18  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
     19  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
     20  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
     21  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
     22  * OF THIS SOFTWARE.
     23  */
     24 
     25 #include <sys/cdefs.h>
     26 __KERNEL_RCSID(0, "$NetBSD: drm_property.c,v 1.4 2021/12/19 09:50:27 riastradh Exp $");
     27 
     28 #include <linux/mm.h>
     29 #include <linux/export.h>
     30 #include <linux/uaccess.h>
     31 
     32 #include <drm/drm_crtc.h>
     33 #include <drm/drm_drv.h>
     34 #include <drm/drm_file.h>
     35 #include <drm/drm_framebuffer.h>
     36 #include <drm/drm_property.h>
     37 
     38 #include "drm_crtc_internal.h"
     39 
     40 /**
     41  * DOC: overview
     42  *
     43  * Properties as represented by &drm_property are used to extend the modeset
     44  * interface exposed to userspace. For the atomic modeset IOCTL properties are
     45  * even the only way to transport metadata about the desired new modeset
     46  * configuration from userspace to the kernel. Properties have a well-defined
     47  * value range, which is enforced by the drm core. See the documentation of the
     48  * flags member of &struct drm_property for an overview of the different
     49  * property types and ranges.
     50  *
     51  * Properties don't store the current value directly, but need to be
     52  * instatiated by attaching them to a &drm_mode_object with
     53  * drm_object_attach_property().
     54  *
     55  * Property values are only 64bit. To support bigger piles of data (like gamma
     56  * tables, color correction matrices or large structures) a property can instead
     57  * point at a &drm_property_blob with that additional data.
     58  *
     59  * Properties are defined by their symbolic name, userspace must keep a
     60  * per-object mapping from those names to the property ID used in the atomic
     61  * IOCTL and in the get/set property IOCTL.
     62  */
     63 
     64 static bool drm_property_flags_valid(u32 flags)
     65 {
     66 	u32 legacy_type = flags & DRM_MODE_PROP_LEGACY_TYPE;
     67 	u32 ext_type = flags & DRM_MODE_PROP_EXTENDED_TYPE;
     68 
     69 	/* Reject undefined/deprecated flags */
     70 	if (flags & ~(DRM_MODE_PROP_LEGACY_TYPE |
     71 		      DRM_MODE_PROP_EXTENDED_TYPE |
     72 		      DRM_MODE_PROP_IMMUTABLE |
     73 		      DRM_MODE_PROP_ATOMIC))
     74 		return false;
     75 
     76 	/* We want either a legacy type or an extended type, but not both */
     77 	if (!legacy_type == !ext_type)
     78 		return false;
     79 
     80 	/* Only one legacy type at a time please */
     81 	if (legacy_type && !is_power_of_2(legacy_type))
     82 		return false;
     83 
     84 	return true;
     85 }
     86 
     87 /**
     88  * drm_property_create - create a new property type
     89  * @dev: drm device
     90  * @flags: flags specifying the property type
     91  * @name: name of the property
     92  * @num_values: number of pre-defined values
     93  *
     94  * This creates a new generic drm property which can then be attached to a drm
     95  * object with drm_object_attach_property(). The returned property object must
     96  * be freed with drm_property_destroy(), which is done automatically when
     97  * calling drm_mode_config_cleanup().
     98  *
     99  * Returns:
    100  * A pointer to the newly created property on success, NULL on failure.
    101  */
    102 struct drm_property *drm_property_create(struct drm_device *dev,
    103 					 u32 flags, const char *name,
    104 					 int num_values)
    105 {
    106 	struct drm_property *property = NULL;
    107 	int ret;
    108 
    109 	if (WARN_ON(!drm_property_flags_valid(flags)))
    110 		return NULL;
    111 
    112 	if (WARN_ON(strlen(name) >= DRM_PROP_NAME_LEN))
    113 		return NULL;
    114 
    115 	property = kzalloc(sizeof(struct drm_property), GFP_KERNEL);
    116 	if (!property)
    117 		return NULL;
    118 
    119 	property->dev = dev;
    120 
    121 	if (num_values) {
    122 		property->values = kcalloc(num_values, sizeof(uint64_t),
    123 					   GFP_KERNEL);
    124 		if (!property->values)
    125 			goto fail;
    126 	}
    127 
    128 	ret = drm_mode_object_add(dev, &property->base, DRM_MODE_OBJECT_PROPERTY);
    129 	if (ret)
    130 		goto fail;
    131 
    132 	property->flags = flags;
    133 	property->num_values = num_values;
    134 	INIT_LIST_HEAD(&property->enum_list);
    135 
    136 	strncpy(property->name, name, DRM_PROP_NAME_LEN);
    137 	property->name[DRM_PROP_NAME_LEN-1] = '\0';
    138 
    139 	list_add_tail(&property->head, &dev->mode_config.property_list);
    140 
    141 	return property;
    142 fail:
    143 	kfree(property->values);
    144 	kfree(property);
    145 	return NULL;
    146 }
    147 EXPORT_SYMBOL(drm_property_create);
    148 
    149 /**
    150  * drm_property_create_enum - create a new enumeration property type
    151  * @dev: drm device
    152  * @flags: flags specifying the property type
    153  * @name: name of the property
    154  * @props: enumeration lists with property values
    155  * @num_values: number of pre-defined values
    156  *
    157  * This creates a new generic drm property which can then be attached to a drm
    158  * object with drm_object_attach_property(). The returned property object must
    159  * be freed with drm_property_destroy(), which is done automatically when
    160  * calling drm_mode_config_cleanup().
    161  *
    162  * Userspace is only allowed to set one of the predefined values for enumeration
    163  * properties.
    164  *
    165  * Returns:
    166  * A pointer to the newly created property on success, NULL on failure.
    167  */
    168 struct drm_property *drm_property_create_enum(struct drm_device *dev,
    169 					      u32 flags, const char *name,
    170 					      const struct drm_prop_enum_list *props,
    171 					      int num_values)
    172 {
    173 	struct drm_property *property;
    174 	int i, ret;
    175 
    176 	flags |= DRM_MODE_PROP_ENUM;
    177 
    178 	property = drm_property_create(dev, flags, name, num_values);
    179 	if (!property)
    180 		return NULL;
    181 
    182 	for (i = 0; i < num_values; i++) {
    183 		ret = drm_property_add_enum(property,
    184 					    props[i].type,
    185 					    props[i].name);
    186 		if (ret) {
    187 			drm_property_destroy(dev, property);
    188 			return NULL;
    189 		}
    190 	}
    191 
    192 	return property;
    193 }
    194 EXPORT_SYMBOL(drm_property_create_enum);
    195 
    196 /**
    197  * drm_property_create_bitmask - create a new bitmask property type
    198  * @dev: drm device
    199  * @flags: flags specifying the property type
    200  * @name: name of the property
    201  * @props: enumeration lists with property bitflags
    202  * @num_props: size of the @props array
    203  * @supported_bits: bitmask of all supported enumeration values
    204  *
    205  * This creates a new bitmask drm property which can then be attached to a drm
    206  * object with drm_object_attach_property(). The returned property object must
    207  * be freed with drm_property_destroy(), which is done automatically when
    208  * calling drm_mode_config_cleanup().
    209  *
    210  * Compared to plain enumeration properties userspace is allowed to set any
    211  * or'ed together combination of the predefined property bitflag values
    212  *
    213  * Returns:
    214  * A pointer to the newly created property on success, NULL on failure.
    215  */
    216 struct drm_property *drm_property_create_bitmask(struct drm_device *dev,
    217 						 u32 flags, const char *name,
    218 						 const struct drm_prop_enum_list *props,
    219 						 int num_props,
    220 						 uint64_t supported_bits)
    221 {
    222 	struct drm_property *property;
    223 	int i, ret;
    224 	int num_values = hweight64(supported_bits);
    225 
    226 	flags |= DRM_MODE_PROP_BITMASK;
    227 
    228 	property = drm_property_create(dev, flags, name, num_values);
    229 	if (!property)
    230 		return NULL;
    231 	for (i = 0; i < num_props; i++) {
    232 		if (!(supported_bits & (1ULL << props[i].type)))
    233 			continue;
    234 
    235 		ret = drm_property_add_enum(property,
    236 					    props[i].type,
    237 					    props[i].name);
    238 		if (ret) {
    239 			drm_property_destroy(dev, property);
    240 			return NULL;
    241 		}
    242 	}
    243 
    244 	return property;
    245 }
    246 EXPORT_SYMBOL(drm_property_create_bitmask);
    247 
    248 static struct drm_property *property_create_range(struct drm_device *dev,
    249 						  u32 flags, const char *name,
    250 						  uint64_t min, uint64_t max)
    251 {
    252 	struct drm_property *property;
    253 
    254 	property = drm_property_create(dev, flags, name, 2);
    255 	if (!property)
    256 		return NULL;
    257 
    258 	property->values[0] = min;
    259 	property->values[1] = max;
    260 
    261 	return property;
    262 }
    263 
    264 /**
    265  * drm_property_create_range - create a new unsigned ranged property type
    266  * @dev: drm device
    267  * @flags: flags specifying the property type
    268  * @name: name of the property
    269  * @min: minimum value of the property
    270  * @max: maximum value of the property
    271  *
    272  * This creates a new generic drm property which can then be attached to a drm
    273  * object with drm_object_attach_property(). The returned property object must
    274  * be freed with drm_property_destroy(), which is done automatically when
    275  * calling drm_mode_config_cleanup().
    276  *
    277  * Userspace is allowed to set any unsigned integer value in the (min, max)
    278  * range inclusive.
    279  *
    280  * Returns:
    281  * A pointer to the newly created property on success, NULL on failure.
    282  */
    283 struct drm_property *drm_property_create_range(struct drm_device *dev,
    284 					       u32 flags, const char *name,
    285 					       uint64_t min, uint64_t max)
    286 {
    287 	return property_create_range(dev, DRM_MODE_PROP_RANGE | flags,
    288 			name, min, max);
    289 }
    290 EXPORT_SYMBOL(drm_property_create_range);
    291 
    292 /**
    293  * drm_property_create_signed_range - create a new signed ranged property type
    294  * @dev: drm device
    295  * @flags: flags specifying the property type
    296  * @name: name of the property
    297  * @min: minimum value of the property
    298  * @max: maximum value of the property
    299  *
    300  * This creates a new generic drm property which can then be attached to a drm
    301  * object with drm_object_attach_property(). The returned property object must
    302  * be freed with drm_property_destroy(), which is done automatically when
    303  * calling drm_mode_config_cleanup().
    304  *
    305  * Userspace is allowed to set any signed integer value in the (min, max)
    306  * range inclusive.
    307  *
    308  * Returns:
    309  * A pointer to the newly created property on success, NULL on failure.
    310  */
    311 struct drm_property *drm_property_create_signed_range(struct drm_device *dev,
    312 						      u32 flags, const char *name,
    313 						      int64_t min, int64_t max)
    314 {
    315 	return property_create_range(dev, DRM_MODE_PROP_SIGNED_RANGE | flags,
    316 			name, I642U64(min), I642U64(max));
    317 }
    318 EXPORT_SYMBOL(drm_property_create_signed_range);
    319 
    320 /**
    321  * drm_property_create_object - create a new object property type
    322  * @dev: drm device
    323  * @flags: flags specifying the property type
    324  * @name: name of the property
    325  * @type: object type from DRM_MODE_OBJECT_* defines
    326  *
    327  * This creates a new generic drm property which can then be attached to a drm
    328  * object with drm_object_attach_property(). The returned property object must
    329  * be freed with drm_property_destroy(), which is done automatically when
    330  * calling drm_mode_config_cleanup().
    331  *
    332  * Userspace is only allowed to set this to any property value of the given
    333  * @type. Only useful for atomic properties, which is enforced.
    334  *
    335  * Returns:
    336  * A pointer to the newly created property on success, NULL on failure.
    337  */
    338 struct drm_property *drm_property_create_object(struct drm_device *dev,
    339 						u32 flags, const char *name,
    340 						uint32_t type)
    341 {
    342 	struct drm_property *property;
    343 
    344 	flags |= DRM_MODE_PROP_OBJECT;
    345 
    346 	if (WARN_ON(!(flags & DRM_MODE_PROP_ATOMIC)))
    347 		return NULL;
    348 
    349 	property = drm_property_create(dev, flags, name, 1);
    350 	if (!property)
    351 		return NULL;
    352 
    353 	property->values[0] = type;
    354 
    355 	return property;
    356 }
    357 EXPORT_SYMBOL(drm_property_create_object);
    358 
    359 /**
    360  * drm_property_create_bool - create a new boolean property type
    361  * @dev: drm device
    362  * @flags: flags specifying the property type
    363  * @name: name of the property
    364  *
    365  * This creates a new generic drm property which can then be attached to a drm
    366  * object with drm_object_attach_property(). The returned property object must
    367  * be freed with drm_property_destroy(), which is done automatically when
    368  * calling drm_mode_config_cleanup().
    369  *
    370  * This is implemented as a ranged property with only {0, 1} as valid values.
    371  *
    372  * Returns:
    373  * A pointer to the newly created property on success, NULL on failure.
    374  */
    375 struct drm_property *drm_property_create_bool(struct drm_device *dev,
    376 					      u32 flags, const char *name)
    377 {
    378 	return drm_property_create_range(dev, flags, name, 0, 1);
    379 }
    380 EXPORT_SYMBOL(drm_property_create_bool);
    381 
    382 /**
    383  * drm_property_add_enum - add a possible value to an enumeration property
    384  * @property: enumeration property to change
    385  * @value: value of the new enumeration
    386  * @name: symbolic name of the new enumeration
    387  *
    388  * This functions adds enumerations to a property.
    389  *
    390  * It's use is deprecated, drivers should use one of the more specific helpers
    391  * to directly create the property with all enumerations already attached.
    392  *
    393  * Returns:
    394  * Zero on success, error code on failure.
    395  */
    396 int drm_property_add_enum(struct drm_property *property,
    397 			  uint64_t value, const char *name)
    398 {
    399 	struct drm_property_enum *prop_enum;
    400 	int index = 0;
    401 
    402 	if (WARN_ON(strlen(name) >= DRM_PROP_NAME_LEN))
    403 		return -EINVAL;
    404 
    405 	if (WARN_ON(!drm_property_type_is(property, DRM_MODE_PROP_ENUM) &&
    406 		    !drm_property_type_is(property, DRM_MODE_PROP_BITMASK)))
    407 		return -EINVAL;
    408 
    409 	/*
    410 	 * Bitmask enum properties have the additional constraint of values
    411 	 * from 0 to 63
    412 	 */
    413 	if (WARN_ON(drm_property_type_is(property, DRM_MODE_PROP_BITMASK) &&
    414 		    value > 63))
    415 		return -EINVAL;
    416 
    417 	list_for_each_entry(prop_enum, &property->enum_list, head) {
    418 		if (WARN_ON(prop_enum->value == value))
    419 			return -EINVAL;
    420 		index++;
    421 	}
    422 
    423 	if (WARN_ON(index >= property->num_values))
    424 		return -EINVAL;
    425 
    426 	prop_enum = kzalloc(sizeof(struct drm_property_enum), GFP_KERNEL);
    427 	if (!prop_enum)
    428 		return -ENOMEM;
    429 
    430 	strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN);
    431 	prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0';
    432 	prop_enum->value = value;
    433 
    434 	property->values[index] = value;
    435 	list_add_tail(&prop_enum->head, &property->enum_list);
    436 	return 0;
    437 }
    438 EXPORT_SYMBOL(drm_property_add_enum);
    439 
    440 /**
    441  * drm_property_destroy - destroy a drm property
    442  * @dev: drm device
    443  * @property: property to destry
    444  *
    445  * This function frees a property including any attached resources like
    446  * enumeration values.
    447  */
    448 void drm_property_destroy(struct drm_device *dev, struct drm_property *property)
    449 {
    450 	struct drm_property_enum *prop_enum, *pt;
    451 
    452 	list_for_each_entry_safe(prop_enum, pt, &property->enum_list, head) {
    453 		list_del(&prop_enum->head);
    454 		kfree(prop_enum);
    455 	}
    456 
    457 	if (property->num_values)
    458 		kfree(property->values);
    459 	drm_mode_object_unregister(dev, &property->base);
    460 	list_del(&property->head);
    461 	kfree(property);
    462 }
    463 EXPORT_SYMBOL(drm_property_destroy);
    464 
    465 int drm_mode_getproperty_ioctl(struct drm_device *dev,
    466 			       void *data, struct drm_file *file_priv)
    467 {
    468 	struct drm_mode_get_property *out_resp = data;
    469 	struct drm_property *property;
    470 	int enum_count = 0;
    471 	int value_count = 0;
    472 	int i, copied;
    473 	struct drm_property_enum *prop_enum;
    474 	struct drm_mode_property_enum __user *enum_ptr;
    475 	uint64_t __user *values_ptr;
    476 
    477 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
    478 		return -EOPNOTSUPP;
    479 
    480 	property = drm_property_find(dev, file_priv, out_resp->prop_id);
    481 	if (!property)
    482 		return -ENOENT;
    483 
    484 	strncpy(out_resp->name, property->name, DRM_PROP_NAME_LEN);
    485 	out_resp->name[DRM_PROP_NAME_LEN-1] = 0;
    486 	out_resp->flags = property->flags;
    487 
    488 	value_count = property->num_values;
    489 	values_ptr = u64_to_user_ptr(out_resp->values_ptr);
    490 
    491 	for (i = 0; i < value_count; i++) {
    492 		if (i < out_resp->count_values &&
    493 		    put_user(property->values[i], values_ptr + i)) {
    494 			return -EFAULT;
    495 		}
    496 	}
    497 	out_resp->count_values = value_count;
    498 
    499 	copied = 0;
    500 	enum_ptr = u64_to_user_ptr(out_resp->enum_blob_ptr);
    501 
    502 	if (drm_property_type_is(property, DRM_MODE_PROP_ENUM) ||
    503 	    drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
    504 		list_for_each_entry(prop_enum, &property->enum_list, head) {
    505 			enum_count++;
    506 			if (out_resp->count_enum_blobs < enum_count)
    507 				continue;
    508 
    509 			if (copy_to_user(&enum_ptr[copied].value,
    510 					 &prop_enum->value, sizeof(uint64_t)))
    511 				return -EFAULT;
    512 
    513 			if (copy_to_user(&enum_ptr[copied].name,
    514 					 &prop_enum->name, DRM_PROP_NAME_LEN))
    515 				return -EFAULT;
    516 			copied++;
    517 		}
    518 		out_resp->count_enum_blobs = enum_count;
    519 	}
    520 
    521 	/*
    522 	 * NOTE: The idea seems to have been to use this to read all the blob
    523 	 * property values. But nothing ever added them to the corresponding
    524 	 * list, userspace always used the special-purpose get_blob ioctl to
    525 	 * read the value for a blob property. It also doesn't make a lot of
    526 	 * sense to return values here when everything else is just metadata for
    527 	 * the property itself.
    528 	 */
    529 	if (drm_property_type_is(property, DRM_MODE_PROP_BLOB))
    530 		out_resp->count_enum_blobs = 0;
    531 
    532 	return 0;
    533 }
    534 
    535 static void drm_property_free_blob(struct kref *kref)
    536 {
    537 	struct drm_property_blob *blob =
    538 		container_of(kref, struct drm_property_blob, base.refcount);
    539 
    540 	mutex_lock(&blob->dev->mode_config.blob_lock);
    541 	list_del(&blob->head_global);
    542 	mutex_unlock(&blob->dev->mode_config.blob_lock);
    543 
    544 	drm_mode_object_unregister(blob->dev, &blob->base);
    545 
    546 	kvfree(blob);
    547 }
    548 
    549 /**
    550  * drm_property_create_blob - Create new blob property
    551  * @dev: DRM device to create property for
    552  * @length: Length to allocate for blob data
    553  * @data: If specified, copies data into blob
    554  *
    555  * Creates a new blob property for a specified DRM device, optionally
    556  * copying data. Note that blob properties are meant to be invariant, hence the
    557  * data must be filled out before the blob is used as the value of any property.
    558  *
    559  * Returns:
    560  * New blob property with a single reference on success, or an ERR_PTR
    561  * value on failure.
    562  */
    563 struct drm_property_blob *
    564 drm_property_create_blob(struct drm_device *dev, size_t length,
    565 			 const void *data)
    566 {
    567 	struct drm_property_blob *blob;
    568 	int ret;
    569 
    570 	if (!length || length > INT_MAX - sizeof(struct drm_property_blob))
    571 		return ERR_PTR(-EINVAL);
    572 
    573 	blob = kvzalloc(sizeof(struct drm_property_blob)+length, GFP_KERNEL);
    574 	if (!blob)
    575 		return ERR_PTR(-ENOMEM);
    576 
    577 	/* This must be explicitly initialised, so we can safely call list_del
    578 	 * on it in the removal handler, even if it isn't in a file list. */
    579 	INIT_LIST_HEAD(&blob->head_file);
    580 	blob->data = (char *)blob + sizeof(*blob);
    581 	blob->length = length;
    582 	blob->dev = dev;
    583 
    584 	if (data)
    585 		memcpy(blob->data, data, length);
    586 
    587 	ret = __drm_mode_object_add(dev, &blob->base, DRM_MODE_OBJECT_BLOB,
    588 				    true, drm_property_free_blob);
    589 	if (ret) {
    590 		kvfree(blob);
    591 		return ERR_PTR(-EINVAL);
    592 	}
    593 
    594 	mutex_lock(&dev->mode_config.blob_lock);
    595 	list_add_tail(&blob->head_global,
    596 	              &dev->mode_config.property_blob_list);
    597 	mutex_unlock(&dev->mode_config.blob_lock);
    598 
    599 	return blob;
    600 }
    601 EXPORT_SYMBOL(drm_property_create_blob);
    602 
    603 /**
    604  * drm_property_blob_put - release a blob property reference
    605  * @blob: DRM blob property
    606  *
    607  * Releases a reference to a blob property. May free the object.
    608  */
    609 void drm_property_blob_put(struct drm_property_blob *blob)
    610 {
    611 	if (!blob)
    612 		return;
    613 
    614 	drm_mode_object_put(&blob->base);
    615 }
    616 EXPORT_SYMBOL(drm_property_blob_put);
    617 
    618 void drm_property_destroy_user_blobs(struct drm_device *dev,
    619 				     struct drm_file *file_priv)
    620 {
    621 	struct drm_property_blob *blob, *bt;
    622 
    623 	/*
    624 	 * When the file gets released that means no one else can access the
    625 	 * blob list any more, so no need to grab dev->blob_lock.
    626 	 */
    627 	list_for_each_entry_safe(blob, bt, &file_priv->blobs, head_file) {
    628 		list_del_init(&blob->head_file);
    629 		drm_property_blob_put(blob);
    630 	}
    631 }
    632 
    633 /**
    634  * drm_property_blob_get - acquire blob property reference
    635  * @blob: DRM blob property
    636  *
    637  * Acquires a reference to an existing blob property. Returns @blob, which
    638  * allows this to be used as a shorthand in assignments.
    639  */
    640 struct drm_property_blob *drm_property_blob_get(struct drm_property_blob *blob)
    641 {
    642 	drm_mode_object_get(&blob->base);
    643 	return blob;
    644 }
    645 EXPORT_SYMBOL(drm_property_blob_get);
    646 
    647 /**
    648  * drm_property_lookup_blob - look up a blob property and take a reference
    649  * @dev: drm device
    650  * @id: id of the blob property
    651  *
    652  * If successful, this takes an additional reference to the blob property.
    653  * callers need to make sure to eventually unreference the returned property
    654  * again, using drm_property_blob_put().
    655  *
    656  * Return:
    657  * NULL on failure, pointer to the blob on success.
    658  */
    659 struct drm_property_blob *drm_property_lookup_blob(struct drm_device *dev,
    660 					           uint32_t id)
    661 {
    662 	struct drm_mode_object *obj;
    663 	struct drm_property_blob *blob = NULL;
    664 
    665 	obj = __drm_mode_object_find(dev, NULL, id, DRM_MODE_OBJECT_BLOB);
    666 	if (obj)
    667 		blob = obj_to_blob(obj);
    668 	return blob;
    669 }
    670 EXPORT_SYMBOL(drm_property_lookup_blob);
    671 
    672 /**
    673  * drm_property_replace_global_blob - replace existing blob property
    674  * @dev: drm device
    675  * @replace: location of blob property pointer to be replaced
    676  * @length: length of data for new blob, or 0 for no data
    677  * @data: content for new blob, or NULL for no data
    678  * @obj_holds_id: optional object for property holding blob ID
    679  * @prop_holds_id: optional property holding blob ID
    680  * @return 0 on success or error on failure
    681  *
    682  * This function will replace a global property in the blob list, optionally
    683  * updating a property which holds the ID of that property.
    684  *
    685  * If length is 0 or data is NULL, no new blob will be created, and the holding
    686  * property, if specified, will be set to 0.
    687  *
    688  * Access to the replace pointer is assumed to be protected by the caller, e.g.
    689  * by holding the relevant modesetting object lock for its parent.
    690  *
    691  * For example, a drm_connector has a 'PATH' property, which contains the ID
    692  * of a blob property with the value of the MST path information. Calling this
    693  * function with replace pointing to the connector's path_blob_ptr, length and
    694  * data set for the new path information, obj_holds_id set to the connector's
    695  * base object, and prop_holds_id set to the path property name, will perform
    696  * a completely atomic update. The access to path_blob_ptr is protected by the
    697  * caller holding a lock on the connector.
    698  */
    699 int drm_property_replace_global_blob(struct drm_device *dev,
    700 				     struct drm_property_blob **replace,
    701 				     size_t length,
    702 				     const void *data,
    703 				     struct drm_mode_object *obj_holds_id,
    704 				     struct drm_property *prop_holds_id)
    705 {
    706 	struct drm_property_blob *new_blob = NULL;
    707 	struct drm_property_blob *old_blob = NULL;
    708 	int ret;
    709 
    710 	WARN_ON(replace == NULL);
    711 
    712 	old_blob = *replace;
    713 
    714 	if (length && data) {
    715 		new_blob = drm_property_create_blob(dev, length, data);
    716 		if (IS_ERR(new_blob))
    717 			return PTR_ERR(new_blob);
    718 	}
    719 
    720 	if (obj_holds_id) {
    721 		ret = drm_object_property_set_value(obj_holds_id,
    722 						    prop_holds_id,
    723 						    new_blob ?
    724 						        new_blob->base.id : 0);
    725 		if (ret != 0)
    726 			goto err_created;
    727 	}
    728 
    729 	drm_property_blob_put(old_blob);
    730 	*replace = new_blob;
    731 
    732 	return 0;
    733 
    734 err_created:
    735 	drm_property_blob_put(new_blob);
    736 	return ret;
    737 }
    738 EXPORT_SYMBOL(drm_property_replace_global_blob);
    739 
    740 /**
    741  * drm_property_replace_blob - replace a blob property
    742  * @blob: a pointer to the member blob to be replaced
    743  * @new_blob: the new blob to replace with
    744  *
    745  * Return: true if the blob was in fact replaced.
    746  */
    747 bool drm_property_replace_blob(struct drm_property_blob **blob,
    748 			       struct drm_property_blob *new_blob)
    749 {
    750 	struct drm_property_blob *old_blob = *blob;
    751 
    752 	if (old_blob == new_blob)
    753 		return false;
    754 
    755 	drm_property_blob_put(old_blob);
    756 	if (new_blob)
    757 		drm_property_blob_get(new_blob);
    758 	*blob = new_blob;
    759 	return true;
    760 }
    761 EXPORT_SYMBOL(drm_property_replace_blob);
    762 
    763 int drm_mode_getblob_ioctl(struct drm_device *dev,
    764 			   void *data, struct drm_file *file_priv)
    765 {
    766 	struct drm_mode_get_blob *out_resp = data;
    767 	struct drm_property_blob *blob;
    768 	int ret = 0;
    769 
    770 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
    771 		return -EOPNOTSUPP;
    772 
    773 	blob = drm_property_lookup_blob(dev, out_resp->blob_id);
    774 	if (!blob)
    775 		return -ENOENT;
    776 
    777 	if (out_resp->length == blob->length) {
    778 		if (copy_to_user(u64_to_user_ptr(out_resp->data),
    779 				 blob->data,
    780 				 blob->length)) {
    781 			ret = -EFAULT;
    782 			goto unref;
    783 		}
    784 	}
    785 	out_resp->length = blob->length;
    786 unref:
    787 	drm_property_blob_put(blob);
    788 
    789 	return ret;
    790 }
    791 
    792 int drm_mode_createblob_ioctl(struct drm_device *dev,
    793 			      void *data, struct drm_file *file_priv)
    794 {
    795 	struct drm_mode_create_blob *out_resp = data;
    796 	struct drm_property_blob *blob;
    797 	int ret = 0;
    798 
    799 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
    800 		return -EOPNOTSUPP;
    801 
    802 	blob = drm_property_create_blob(dev, out_resp->length, NULL);
    803 	if (IS_ERR(blob))
    804 		return PTR_ERR(blob);
    805 
    806 	if (copy_from_user(blob->data,
    807 			   u64_to_user_ptr(out_resp->data),
    808 			   out_resp->length)) {
    809 		ret = -EFAULT;
    810 		goto out_blob;
    811 	}
    812 
    813 	/* Dropping the lock between create_blob and our access here is safe
    814 	 * as only the same file_priv can remove the blob; at this point, it is
    815 	 * not associated with any file_priv. */
    816 	mutex_lock(&dev->mode_config.blob_lock);
    817 	out_resp->blob_id = blob->base.id;
    818 	list_add_tail(&blob->head_file, &file_priv->blobs);
    819 	mutex_unlock(&dev->mode_config.blob_lock);
    820 
    821 	return 0;
    822 
    823 out_blob:
    824 	drm_property_blob_put(blob);
    825 	return ret;
    826 }
    827 
    828 int drm_mode_destroyblob_ioctl(struct drm_device *dev,
    829 			       void *data, struct drm_file *file_priv)
    830 {
    831 	struct drm_mode_destroy_blob *out_resp = data;
    832 	struct drm_property_blob *blob = NULL, *bt;
    833 	bool found = false;
    834 	int ret = 0;
    835 
    836 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
    837 		return -EOPNOTSUPP;
    838 
    839 	blob = drm_property_lookup_blob(dev, out_resp->blob_id);
    840 	if (!blob)
    841 		return -ENOENT;
    842 
    843 	mutex_lock(&dev->mode_config.blob_lock);
    844 	/* Ensure the property was actually created by this user. */
    845 	list_for_each_entry(bt, &file_priv->blobs, head_file) {
    846 		if (bt == blob) {
    847 			found = true;
    848 			break;
    849 		}
    850 	}
    851 
    852 	if (!found) {
    853 		ret = -EPERM;
    854 		goto err;
    855 	}
    856 
    857 	/* We must drop head_file here, because we may not be the last
    858 	 * reference on the blob. */
    859 	list_del_init(&blob->head_file);
    860 	mutex_unlock(&dev->mode_config.blob_lock);
    861 
    862 	/* One reference from lookup, and one from the filp. */
    863 	drm_property_blob_put(blob);
    864 	drm_property_blob_put(blob);
    865 
    866 	return 0;
    867 
    868 err:
    869 	mutex_unlock(&dev->mode_config.blob_lock);
    870 	drm_property_blob_put(blob);
    871 
    872 	return ret;
    873 }
    874 
    875 /* Some properties could refer to dynamic refcnt'd objects, or things that
    876  * need special locking to handle lifetime issues (ie. to ensure the prop
    877  * value doesn't become invalid part way through the property update due to
    878  * race).  The value returned by reference via 'obj' should be passed back
    879  * to drm_property_change_valid_put() after the property is set (and the
    880  * object to which the property is attached has a chance to take its own
    881  * reference).
    882  */
    883 bool drm_property_change_valid_get(struct drm_property *property,
    884 				   uint64_t value, struct drm_mode_object **ref)
    885 {
    886 	int i;
    887 
    888 	if (property->flags & DRM_MODE_PROP_IMMUTABLE)
    889 		return false;
    890 
    891 	*ref = NULL;
    892 
    893 	if (drm_property_type_is(property, DRM_MODE_PROP_RANGE)) {
    894 		if (value < property->values[0] || value > property->values[1])
    895 			return false;
    896 		return true;
    897 	} else if (drm_property_type_is(property, DRM_MODE_PROP_SIGNED_RANGE)) {
    898 		int64_t svalue = U642I64(value);
    899 
    900 		if (svalue < U642I64(property->values[0]) ||
    901 				svalue > U642I64(property->values[1]))
    902 			return false;
    903 		return true;
    904 	} else if (drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
    905 		uint64_t valid_mask = 0;
    906 
    907 		for (i = 0; i < property->num_values; i++)
    908 			valid_mask |= (1ULL << property->values[i]);
    909 		return !(value & ~valid_mask);
    910 	} else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB)) {
    911 		struct drm_property_blob *blob;
    912 
    913 		if (value == 0)
    914 			return true;
    915 
    916 		blob = drm_property_lookup_blob(property->dev, value);
    917 		if (blob) {
    918 			*ref = &blob->base;
    919 			return true;
    920 		} else {
    921 			return false;
    922 		}
    923 	} else if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) {
    924 		/* a zero value for an object property translates to null: */
    925 		if (value == 0)
    926 			return true;
    927 
    928 		*ref = __drm_mode_object_find(property->dev, NULL, value,
    929 					      property->values[0]);
    930 		return *ref != NULL;
    931 	}
    932 
    933 	for (i = 0; i < property->num_values; i++)
    934 		if (property->values[i] == value)
    935 			return true;
    936 	return false;
    937 }
    938 
    939 void drm_property_change_valid_put(struct drm_property *property,
    940 		struct drm_mode_object *ref)
    941 {
    942 	if (!ref)
    943 		return;
    944 
    945 	if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) {
    946 		drm_mode_object_put(ref);
    947 	} else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB))
    948 		drm_property_blob_put(obj_to_blob(ref));
    949 }
    950