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