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