blob: fe8627fb7ae6c80ea678668eb8a0c6bbac717b4f [file] [log] [blame]
Daniel Vetter59e71ee2016-08-29 10:27:55 +02001/*
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 <drm/drmP.h>
25#include <drm/drm_property.h>
26
27#include "drm_crtc_internal.h"
28
Daniel Vetterc8458c72016-08-29 10:27:57 +020029/**
30 * DOC: overview
31 *
32 * Properties as represented by &drm_property are used to extend the modeset
33 * interface exposed to userspace. For the atomic modeset IOCTL properties are
34 * even the only way to transport metadata about the desired new modeset
35 * configuration from userspace to the kernel. Properties have a well-defined
36 * value range, which is enforced by the drm core. See the documentation of the
Daniel Vetterea0dd852016-12-29 21:48:26 +010037 * flags member of &struct drm_property for an overview of the different
Daniel Vetterc8458c72016-08-29 10:27:57 +020038 * property types and ranges.
39 *
40 * Properties don't store the current value directly, but need to be
41 * instatiated by attaching them to a &drm_mode_object with
42 * drm_object_attach_property().
43 *
44 * Property values are only 64bit. To support bigger piles of data (like gamma
Daniel Vetterd5745282017-01-25 07:26:45 +010045 * tables, color correction matrices or large structures) a property can instead
46 * point at a &drm_property_blob with that additional data.
Daniel Vetterc8458c72016-08-29 10:27:57 +020047 *
48 * Properties are defined by their symbolic name, userspace must keep a
49 * per-object mapping from those names to the property ID used in the atomic
50 * IOCTL and in the get/set property IOCTL.
51 */
52
Daniel Vetter59e71ee2016-08-29 10:27:55 +020053static bool drm_property_type_valid(struct drm_property *property)
54{
55 if (property->flags & DRM_MODE_PROP_EXTENDED_TYPE)
56 return !(property->flags & DRM_MODE_PROP_LEGACY_TYPE);
57 return !!(property->flags & DRM_MODE_PROP_LEGACY_TYPE);
58}
59
60/**
61 * drm_property_create - create a new property type
62 * @dev: drm device
63 * @flags: flags specifying the property type
64 * @name: name of the property
65 * @num_values: number of pre-defined values
66 *
67 * This creates a new generic drm property which can then be attached to a drm
Daniel Vetter6a8a66e2016-11-23 20:23:27 +010068 * object with drm_object_attach_property(). The returned property object must
69 * be freed with drm_property_destroy(), which is done automatically when
70 * calling drm_mode_config_cleanup().
Daniel Vetter59e71ee2016-08-29 10:27:55 +020071 *
72 * Returns:
73 * A pointer to the newly created property on success, NULL on failure.
74 */
75struct drm_property *drm_property_create(struct drm_device *dev, int flags,
76 const char *name, int num_values)
77{
78 struct drm_property *property = NULL;
79 int ret;
80
81 property = kzalloc(sizeof(struct drm_property), GFP_KERNEL);
82 if (!property)
83 return NULL;
84
85 property->dev = dev;
86
87 if (num_values) {
88 property->values = kcalloc(num_values, sizeof(uint64_t),
89 GFP_KERNEL);
90 if (!property->values)
91 goto fail;
92 }
93
Thierry Reding2135ea72017-02-28 15:46:37 +010094 ret = drm_mode_object_add(dev, &property->base, DRM_MODE_OBJECT_PROPERTY);
Daniel Vetter59e71ee2016-08-29 10:27:55 +020095 if (ret)
96 goto fail;
97
98 property->flags = flags;
99 property->num_values = num_values;
100 INIT_LIST_HEAD(&property->enum_list);
101
Ville Syrjälä8e5e83a2018-03-02 15:25:42 +0200102 strncpy(property->name, name, DRM_PROP_NAME_LEN);
103 property->name[DRM_PROP_NAME_LEN-1] = '\0';
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200104
105 list_add_tail(&property->head, &dev->mode_config.property_list);
106
107 WARN_ON(!drm_property_type_valid(property));
108
109 return property;
110fail:
111 kfree(property->values);
112 kfree(property);
113 return NULL;
114}
115EXPORT_SYMBOL(drm_property_create);
116
117/**
118 * drm_property_create_enum - create a new enumeration property type
119 * @dev: drm device
120 * @flags: flags specifying the property type
121 * @name: name of the property
122 * @props: enumeration lists with property values
123 * @num_values: number of pre-defined values
124 *
125 * This creates a new generic drm property which can then be attached to a drm
Daniel Vetter6a8a66e2016-11-23 20:23:27 +0100126 * object with drm_object_attach_property(). The returned property object must
127 * be freed with drm_property_destroy(), which is done automatically when
128 * calling drm_mode_config_cleanup().
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200129 *
130 * Userspace is only allowed to set one of the predefined values for enumeration
131 * properties.
132 *
133 * Returns:
134 * A pointer to the newly created property on success, NULL on failure.
135 */
136struct drm_property *drm_property_create_enum(struct drm_device *dev, int flags,
137 const char *name,
138 const struct drm_prop_enum_list *props,
139 int num_values)
140{
141 struct drm_property *property;
142 int i, ret;
143
144 flags |= DRM_MODE_PROP_ENUM;
145
146 property = drm_property_create(dev, flags, name, num_values);
147 if (!property)
148 return NULL;
149
150 for (i = 0; i < num_values; i++) {
151 ret = drm_property_add_enum(property, i,
152 props[i].type,
153 props[i].name);
154 if (ret) {
155 drm_property_destroy(dev, property);
156 return NULL;
157 }
158 }
159
160 return property;
161}
162EXPORT_SYMBOL(drm_property_create_enum);
163
164/**
165 * drm_property_create_bitmask - create a new bitmask property type
166 * @dev: drm device
167 * @flags: flags specifying the property type
168 * @name: name of the property
169 * @props: enumeration lists with property bitflags
170 * @num_props: size of the @props array
171 * @supported_bits: bitmask of all supported enumeration values
172 *
173 * This creates a new bitmask drm property which can then be attached to a drm
Daniel Vetter6a8a66e2016-11-23 20:23:27 +0100174 * object with drm_object_attach_property(). The returned property object must
175 * be freed with drm_property_destroy(), which is done automatically when
176 * calling drm_mode_config_cleanup().
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200177 *
178 * Compared to plain enumeration properties userspace is allowed to set any
179 * or'ed together combination of the predefined property bitflag values
180 *
181 * Returns:
182 * A pointer to the newly created property on success, NULL on failure.
183 */
184struct drm_property *drm_property_create_bitmask(struct drm_device *dev,
185 int flags, const char *name,
186 const struct drm_prop_enum_list *props,
187 int num_props,
188 uint64_t supported_bits)
189{
190 struct drm_property *property;
191 int i, ret, index = 0;
192 int num_values = hweight64(supported_bits);
193
194 flags |= DRM_MODE_PROP_BITMASK;
195
196 property = drm_property_create(dev, flags, name, num_values);
197 if (!property)
198 return NULL;
199 for (i = 0; i < num_props; i++) {
200 if (!(supported_bits & (1ULL << props[i].type)))
201 continue;
202
203 if (WARN_ON(index >= num_values)) {
204 drm_property_destroy(dev, property);
205 return NULL;
206 }
207
208 ret = drm_property_add_enum(property, index++,
209 props[i].type,
210 props[i].name);
211 if (ret) {
212 drm_property_destroy(dev, property);
213 return NULL;
214 }
215 }
216
217 return property;
218}
219EXPORT_SYMBOL(drm_property_create_bitmask);
220
221static struct drm_property *property_create_range(struct drm_device *dev,
222 int flags, const char *name,
223 uint64_t min, uint64_t max)
224{
225 struct drm_property *property;
226
227 property = drm_property_create(dev, flags, name, 2);
228 if (!property)
229 return NULL;
230
231 property->values[0] = min;
232 property->values[1] = max;
233
234 return property;
235}
236
237/**
238 * drm_property_create_range - create a new unsigned ranged property type
239 * @dev: drm device
240 * @flags: flags specifying the property type
241 * @name: name of the property
242 * @min: minimum value of the property
243 * @max: maximum value of the property
244 *
245 * This creates a new generic drm property which can then be attached to a drm
Daniel Vetter6a8a66e2016-11-23 20:23:27 +0100246 * object with drm_object_attach_property(). The returned property object must
247 * be freed with drm_property_destroy(), which is done automatically when
248 * calling drm_mode_config_cleanup().
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200249 *
250 * Userspace is allowed to set any unsigned integer value in the (min, max)
251 * range inclusive.
252 *
253 * Returns:
254 * A pointer to the newly created property on success, NULL on failure.
255 */
256struct drm_property *drm_property_create_range(struct drm_device *dev, int flags,
257 const char *name,
258 uint64_t min, uint64_t max)
259{
260 return property_create_range(dev, DRM_MODE_PROP_RANGE | flags,
261 name, min, max);
262}
263EXPORT_SYMBOL(drm_property_create_range);
264
265/**
266 * drm_property_create_signed_range - create a new signed ranged property type
267 * @dev: drm device
268 * @flags: flags specifying the property type
269 * @name: name of the property
270 * @min: minimum value of the property
271 * @max: maximum value of the property
272 *
273 * This creates a new generic drm property which can then be attached to a drm
Daniel Vetter6a8a66e2016-11-23 20:23:27 +0100274 * object with drm_object_attach_property(). The returned property object must
275 * be freed with drm_property_destroy(), which is done automatically when
276 * calling drm_mode_config_cleanup().
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200277 *
278 * Userspace is allowed to set any signed integer value in the (min, max)
279 * range inclusive.
280 *
281 * Returns:
282 * A pointer to the newly created property on success, NULL on failure.
283 */
284struct drm_property *drm_property_create_signed_range(struct drm_device *dev,
285 int flags, const char *name,
286 int64_t min, int64_t max)
287{
288 return property_create_range(dev, DRM_MODE_PROP_SIGNED_RANGE | flags,
289 name, I642U64(min), I642U64(max));
290}
291EXPORT_SYMBOL(drm_property_create_signed_range);
292
293/**
294 * drm_property_create_object - create a new object property type
295 * @dev: drm device
296 * @flags: flags specifying the property type
297 * @name: name of the property
298 * @type: object type from DRM_MODE_OBJECT_* defines
299 *
300 * This creates a new generic drm property which can then be attached to a drm
Daniel Vetter6a8a66e2016-11-23 20:23:27 +0100301 * 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().
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200304 *
305 * Userspace is only allowed to set this to any property value of the given
306 * @type. Only useful for atomic properties, which is enforced.
307 *
308 * Returns:
309 * A pointer to the newly created property on success, NULL on failure.
310 */
311struct drm_property *drm_property_create_object(struct drm_device *dev,
Daniel Vetterc8458c72016-08-29 10:27:57 +0200312 int flags, const char *name,
313 uint32_t type)
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200314{
315 struct drm_property *property;
316
317 flags |= DRM_MODE_PROP_OBJECT;
318
319 if (WARN_ON(!(flags & DRM_MODE_PROP_ATOMIC)))
320 return NULL;
321
322 property = drm_property_create(dev, flags, name, 1);
323 if (!property)
324 return NULL;
325
326 property->values[0] = type;
327
328 return property;
329}
330EXPORT_SYMBOL(drm_property_create_object);
331
332/**
333 * drm_property_create_bool - create a new boolean property type
334 * @dev: drm device
335 * @flags: flags specifying the property type
336 * @name: name of the property
337 *
338 * This creates a new generic drm property which can then be attached to a drm
Daniel Vetter6a8a66e2016-11-23 20:23:27 +0100339 * object with drm_object_attach_property(). The returned property object must
340 * be freed with drm_property_destroy(), which is done automatically when
341 * calling drm_mode_config_cleanup().
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200342 *
343 * This is implemented as a ranged property with only {0, 1} as valid values.
344 *
345 * Returns:
346 * A pointer to the newly created property on success, NULL on failure.
347 */
348struct drm_property *drm_property_create_bool(struct drm_device *dev, int flags,
Daniel Vetterc8458c72016-08-29 10:27:57 +0200349 const char *name)
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200350{
351 return drm_property_create_range(dev, flags, name, 0, 1);
352}
353EXPORT_SYMBOL(drm_property_create_bool);
354
355/**
356 * drm_property_add_enum - add a possible value to an enumeration property
357 * @property: enumeration property to change
358 * @index: index of the new enumeration
359 * @value: value of the new enumeration
360 * @name: symbolic name of the new enumeration
361 *
362 * This functions adds enumerations to a property.
363 *
364 * It's use is deprecated, drivers should use one of the more specific helpers
365 * to directly create the property with all enumerations already attached.
366 *
367 * Returns:
368 * Zero on success, error code on failure.
369 */
370int drm_property_add_enum(struct drm_property *property, int index,
371 uint64_t value, const char *name)
372{
373 struct drm_property_enum *prop_enum;
374
375 if (!(drm_property_type_is(property, DRM_MODE_PROP_ENUM) ||
376 drm_property_type_is(property, DRM_MODE_PROP_BITMASK)))
377 return -EINVAL;
378
379 /*
380 * Bitmask enum properties have the additional constraint of values
381 * from 0 to 63
382 */
383 if (drm_property_type_is(property, DRM_MODE_PROP_BITMASK) &&
384 (value > 63))
385 return -EINVAL;
386
387 if (!list_empty(&property->enum_list)) {
388 list_for_each_entry(prop_enum, &property->enum_list, head) {
389 if (prop_enum->value == value) {
390 strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN);
391 prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0';
392 return 0;
393 }
394 }
395 }
396
397 prop_enum = kzalloc(sizeof(struct drm_property_enum), GFP_KERNEL);
398 if (!prop_enum)
399 return -ENOMEM;
400
401 strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN);
402 prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0';
403 prop_enum->value = value;
404
405 property->values[index] = value;
406 list_add_tail(&prop_enum->head, &property->enum_list);
407 return 0;
408}
409EXPORT_SYMBOL(drm_property_add_enum);
410
411/**
412 * drm_property_destroy - destroy a drm property
413 * @dev: drm device
414 * @property: property to destry
415 *
416 * This function frees a property including any attached resources like
417 * enumeration values.
418 */
419void drm_property_destroy(struct drm_device *dev, struct drm_property *property)
420{
421 struct drm_property_enum *prop_enum, *pt;
422
423 list_for_each_entry_safe(prop_enum, pt, &property->enum_list, head) {
424 list_del(&prop_enum->head);
425 kfree(prop_enum);
426 }
427
428 if (property->num_values)
429 kfree(property->values);
430 drm_mode_object_unregister(dev, &property->base);
431 list_del(&property->head);
432 kfree(property);
433}
434EXPORT_SYMBOL(drm_property_destroy);
435
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200436int drm_mode_getproperty_ioctl(struct drm_device *dev,
437 void *data, struct drm_file *file_priv)
438{
439 struct drm_mode_get_property *out_resp = data;
440 struct drm_property *property;
441 int enum_count = 0;
442 int value_count = 0;
Daniel Vettereb8eb022017-04-03 10:32:55 +0200443 int i, copied;
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200444 struct drm_property_enum *prop_enum;
445 struct drm_mode_property_enum __user *enum_ptr;
446 uint64_t __user *values_ptr;
447
448 if (!drm_core_check_feature(dev, DRIVER_MODESET))
449 return -EINVAL;
450
Keith Packard418da172017-03-14 23:25:07 -0700451 property = drm_property_find(dev, file_priv, out_resp->prop_id);
Daniel Vettereb8eb022017-04-03 10:32:55 +0200452 if (!property)
453 return -ENOENT;
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200454
455 strncpy(out_resp->name, property->name, DRM_PROP_NAME_LEN);
456 out_resp->name[DRM_PROP_NAME_LEN-1] = 0;
457 out_resp->flags = property->flags;
458
Daniel Vettereb8eb022017-04-03 10:32:55 +0200459 value_count = property->num_values;
460 values_ptr = u64_to_user_ptr(out_resp->values_ptr);
461
462 for (i = 0; i < value_count; i++) {
463 if (i < out_resp->count_values &&
464 put_user(property->values[i], values_ptr + i)) {
465 return -EFAULT;
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200466 }
467 }
468 out_resp->count_values = value_count;
469
Daniel Vettereb8eb022017-04-03 10:32:55 +0200470 copied = 0;
471 enum_ptr = u64_to_user_ptr(out_resp->enum_blob_ptr);
472
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200473 if (drm_property_type_is(property, DRM_MODE_PROP_ENUM) ||
Daniel Vettereb8eb022017-04-03 10:32:55 +0200474 drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
475 list_for_each_entry(prop_enum, &property->enum_list, head) {
476 enum_count++;
Daniel Vetter8cb68c82017-04-10 13:54:45 +0200477 if (out_resp->count_enum_blobs < enum_count)
Daniel Vettereb8eb022017-04-03 10:32:55 +0200478 continue;
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200479
Daniel Vettereb8eb022017-04-03 10:32:55 +0200480 if (copy_to_user(&enum_ptr[copied].value,
481 &prop_enum->value, sizeof(uint64_t)))
482 return -EFAULT;
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200483
Daniel Vettereb8eb022017-04-03 10:32:55 +0200484 if (copy_to_user(&enum_ptr[copied].name,
485 &prop_enum->name, DRM_PROP_NAME_LEN))
486 return -EFAULT;
487 copied++;
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200488 }
489 out_resp->count_enum_blobs = enum_count;
490 }
491
492 /*
493 * NOTE: The idea seems to have been to use this to read all the blob
494 * property values. But nothing ever added them to the corresponding
495 * list, userspace always used the special-purpose get_blob ioctl to
496 * read the value for a blob property. It also doesn't make a lot of
497 * sense to return values here when everything else is just metadata for
498 * the property itself.
499 */
500 if (drm_property_type_is(property, DRM_MODE_PROP_BLOB))
501 out_resp->count_enum_blobs = 0;
Daniel Vettereb8eb022017-04-03 10:32:55 +0200502
503 return 0;
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200504}
505
506static void drm_property_free_blob(struct kref *kref)
507{
508 struct drm_property_blob *blob =
509 container_of(kref, struct drm_property_blob, base.refcount);
510
511 mutex_lock(&blob->dev->mode_config.blob_lock);
512 list_del(&blob->head_global);
513 mutex_unlock(&blob->dev->mode_config.blob_lock);
514
515 drm_mode_object_unregister(blob->dev, &blob->base);
516
517 kfree(blob);
518}
519
520/**
521 * drm_property_create_blob - Create new blob property
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200522 * @dev: DRM device to create property for
523 * @length: Length to allocate for blob data
524 * @data: If specified, copies data into blob
525 *
Daniel Vetterc8458c72016-08-29 10:27:57 +0200526 * Creates a new blob property for a specified DRM device, optionally
527 * copying data. Note that blob properties are meant to be invariant, hence the
528 * data must be filled out before the blob is used as the value of any property.
529 *
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200530 * Returns:
531 * New blob property with a single reference on success, or an ERR_PTR
532 * value on failure.
533 */
534struct drm_property_blob *
535drm_property_create_blob(struct drm_device *dev, size_t length,
536 const void *data)
537{
538 struct drm_property_blob *blob;
539 int ret;
540
541 if (!length || length > ULONG_MAX - sizeof(struct drm_property_blob))
542 return ERR_PTR(-EINVAL);
543
544 blob = kzalloc(sizeof(struct drm_property_blob)+length, GFP_KERNEL);
545 if (!blob)
546 return ERR_PTR(-ENOMEM);
547
548 /* This must be explicitly initialised, so we can safely call list_del
549 * on it in the removal handler, even if it isn't in a file list. */
550 INIT_LIST_HEAD(&blob->head_file);
551 blob->length = length;
552 blob->dev = dev;
553
554 if (data)
555 memcpy(blob->data, data, length);
556
Thierry Reding2135ea72017-02-28 15:46:37 +0100557 ret = __drm_mode_object_add(dev, &blob->base, DRM_MODE_OBJECT_BLOB,
558 true, drm_property_free_blob);
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200559 if (ret) {
560 kfree(blob);
561 return ERR_PTR(-EINVAL);
562 }
563
564 mutex_lock(&dev->mode_config.blob_lock);
565 list_add_tail(&blob->head_global,
566 &dev->mode_config.property_blob_list);
567 mutex_unlock(&dev->mode_config.blob_lock);
568
569 return blob;
570}
571EXPORT_SYMBOL(drm_property_create_blob);
572
573/**
Thierry Reding6472e502017-02-28 15:46:42 +0100574 * drm_property_blob_put - release a blob property reference
575 * @blob: DRM blob property
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200576 *
Thierry Reding6472e502017-02-28 15:46:42 +0100577 * Releases a reference to a blob property. May free the object.
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200578 */
Thierry Reding6472e502017-02-28 15:46:42 +0100579void drm_property_blob_put(struct drm_property_blob *blob)
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200580{
581 if (!blob)
582 return;
583
Thierry Reding020a2182017-02-28 15:46:38 +0100584 drm_mode_object_put(&blob->base);
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200585}
Thierry Reding6472e502017-02-28 15:46:42 +0100586EXPORT_SYMBOL(drm_property_blob_put);
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200587
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200588void drm_property_destroy_user_blobs(struct drm_device *dev,
589 struct drm_file *file_priv)
590{
591 struct drm_property_blob *blob, *bt;
592
593 /*
594 * When the file gets released that means no one else can access the
595 * blob list any more, so no need to grab dev->blob_lock.
596 */
597 list_for_each_entry_safe(blob, bt, &file_priv->blobs, head_file) {
598 list_del_init(&blob->head_file);
Thierry Reding6472e502017-02-28 15:46:42 +0100599 drm_property_blob_put(blob);
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200600 }
601}
602
603/**
Thierry Reding6472e502017-02-28 15:46:42 +0100604 * drm_property_blob_get - acquire blob property reference
605 * @blob: DRM blob property
Daniel Vetterc8458c72016-08-29 10:27:57 +0200606 *
Thierry Reding6472e502017-02-28 15:46:42 +0100607 * Acquires a reference to an existing blob property. Returns @blob, which
Daniel Vetterc8458c72016-08-29 10:27:57 +0200608 * allows this to be used as a shorthand in assignments.
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200609 */
Thierry Reding6472e502017-02-28 15:46:42 +0100610struct drm_property_blob *drm_property_blob_get(struct drm_property_blob *blob)
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200611{
Thierry Reding020a2182017-02-28 15:46:38 +0100612 drm_mode_object_get(&blob->base);
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200613 return blob;
614}
Thierry Reding6472e502017-02-28 15:46:42 +0100615EXPORT_SYMBOL(drm_property_blob_get);
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200616
617/**
618 * drm_property_lookup_blob - look up a blob property and take a reference
619 * @dev: drm device
620 * @id: id of the blob property
621 *
622 * If successful, this takes an additional reference to the blob property.
623 * callers need to make sure to eventually unreference the returned property
Thierry Reding6472e502017-02-28 15:46:42 +0100624 * again, using drm_property_blob_put().
Daniel Vetterc8458c72016-08-29 10:27:57 +0200625 *
626 * Return:
627 * NULL on failure, pointer to the blob on success.
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200628 */
629struct drm_property_blob *drm_property_lookup_blob(struct drm_device *dev,
630 uint32_t id)
631{
632 struct drm_mode_object *obj;
633 struct drm_property_blob *blob = NULL;
634
Keith Packard418da172017-03-14 23:25:07 -0700635 obj = __drm_mode_object_find(dev, NULL, id, DRM_MODE_OBJECT_BLOB);
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200636 if (obj)
637 blob = obj_to_blob(obj);
638 return blob;
639}
640EXPORT_SYMBOL(drm_property_lookup_blob);
641
642/**
Daniel Vetterc8458c72016-08-29 10:27:57 +0200643 * drm_property_replace_global_blob - replace existing blob property
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200644 * @dev: drm device
645 * @replace: location of blob property pointer to be replaced
646 * @length: length of data for new blob, or 0 for no data
647 * @data: content for new blob, or NULL for no data
648 * @obj_holds_id: optional object for property holding blob ID
649 * @prop_holds_id: optional property holding blob ID
650 * @return 0 on success or error on failure
651 *
Daniel Vetterc8458c72016-08-29 10:27:57 +0200652 * This function will replace a global property in the blob list, optionally
653 * updating a property which holds the ID of that property.
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200654 *
655 * If length is 0 or data is NULL, no new blob will be created, and the holding
656 * property, if specified, will be set to 0.
657 *
658 * Access to the replace pointer is assumed to be protected by the caller, e.g.
659 * by holding the relevant modesetting object lock for its parent.
660 *
661 * For example, a drm_connector has a 'PATH' property, which contains the ID
662 * of a blob property with the value of the MST path information. Calling this
663 * function with replace pointing to the connector's path_blob_ptr, length and
664 * data set for the new path information, obj_holds_id set to the connector's
665 * base object, and prop_holds_id set to the path property name, will perform
666 * a completely atomic update. The access to path_blob_ptr is protected by the
667 * caller holding a lock on the connector.
668 */
669int drm_property_replace_global_blob(struct drm_device *dev,
670 struct drm_property_blob **replace,
671 size_t length,
672 const void *data,
673 struct drm_mode_object *obj_holds_id,
674 struct drm_property *prop_holds_id)
675{
676 struct drm_property_blob *new_blob = NULL;
677 struct drm_property_blob *old_blob = NULL;
678 int ret;
679
680 WARN_ON(replace == NULL);
681
682 old_blob = *replace;
683
684 if (length && data) {
685 new_blob = drm_property_create_blob(dev, length, data);
686 if (IS_ERR(new_blob))
687 return PTR_ERR(new_blob);
688 }
689
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200690 if (obj_holds_id) {
691 ret = drm_object_property_set_value(obj_holds_id,
692 prop_holds_id,
693 new_blob ?
694 new_blob->base.id : 0);
695 if (ret != 0)
696 goto err_created;
697 }
698
Thierry Reding6472e502017-02-28 15:46:42 +0100699 drm_property_blob_put(old_blob);
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200700 *replace = new_blob;
701
702 return 0;
703
704err_created:
Thierry Reding6472e502017-02-28 15:46:42 +0100705 drm_property_blob_put(new_blob);
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200706 return ret;
707}
708EXPORT_SYMBOL(drm_property_replace_global_blob);
709
Peter Rosin5f057ff2017-07-13 18:25:25 +0200710/**
711 * drm_property_replace_blob - replace a blob property
712 * @blob: a pointer to the member blob to be replaced
713 * @new_blob: the new blob to replace with
714 *
715 * Return: true if the blob was in fact replaced.
716 */
717bool drm_property_replace_blob(struct drm_property_blob **blob,
718 struct drm_property_blob *new_blob)
719{
720 struct drm_property_blob *old_blob = *blob;
721
722 if (old_blob == new_blob)
723 return false;
724
725 drm_property_blob_put(old_blob);
726 if (new_blob)
727 drm_property_blob_get(new_blob);
728 *blob = new_blob;
729 return true;
730}
731EXPORT_SYMBOL(drm_property_replace_blob);
732
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200733int drm_mode_getblob_ioctl(struct drm_device *dev,
734 void *data, struct drm_file *file_priv)
735{
736 struct drm_mode_get_blob *out_resp = data;
737 struct drm_property_blob *blob;
738 int ret = 0;
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200739
740 if (!drm_core_check_feature(dev, DRIVER_MODESET))
741 return -EINVAL;
742
743 blob = drm_property_lookup_blob(dev, out_resp->blob_id);
744 if (!blob)
745 return -ENOENT;
746
747 if (out_resp->length == blob->length) {
Chris Wilson75df6242016-11-27 17:09:08 +0000748 if (copy_to_user(u64_to_user_ptr(out_resp->data),
749 blob->data,
750 blob->length)) {
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200751 ret = -EFAULT;
752 goto unref;
753 }
754 }
755 out_resp->length = blob->length;
756unref:
Thierry Reding6472e502017-02-28 15:46:42 +0100757 drm_property_blob_put(blob);
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200758
759 return ret;
760}
761
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200762int drm_mode_createblob_ioctl(struct drm_device *dev,
763 void *data, struct drm_file *file_priv)
764{
765 struct drm_mode_create_blob *out_resp = data;
766 struct drm_property_blob *blob;
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200767 int ret = 0;
768
769 if (!drm_core_check_feature(dev, DRIVER_MODESET))
770 return -EINVAL;
771
772 blob = drm_property_create_blob(dev, out_resp->length, NULL);
773 if (IS_ERR(blob))
774 return PTR_ERR(blob);
775
Chris Wilson75df6242016-11-27 17:09:08 +0000776 if (copy_from_user(blob->data,
777 u64_to_user_ptr(out_resp->data),
778 out_resp->length)) {
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200779 ret = -EFAULT;
780 goto out_blob;
781 }
782
783 /* Dropping the lock between create_blob and our access here is safe
784 * as only the same file_priv can remove the blob; at this point, it is
785 * not associated with any file_priv. */
786 mutex_lock(&dev->mode_config.blob_lock);
787 out_resp->blob_id = blob->base.id;
788 list_add_tail(&blob->head_file, &file_priv->blobs);
789 mutex_unlock(&dev->mode_config.blob_lock);
790
791 return 0;
792
793out_blob:
Thierry Reding6472e502017-02-28 15:46:42 +0100794 drm_property_blob_put(blob);
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200795 return ret;
796}
797
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200798int drm_mode_destroyblob_ioctl(struct drm_device *dev,
799 void *data, struct drm_file *file_priv)
800{
801 struct drm_mode_destroy_blob *out_resp = data;
802 struct drm_property_blob *blob = NULL, *bt;
803 bool found = false;
804 int ret = 0;
805
806 if (!drm_core_check_feature(dev, DRIVER_MODESET))
807 return -EINVAL;
808
809 blob = drm_property_lookup_blob(dev, out_resp->blob_id);
810 if (!blob)
811 return -ENOENT;
812
813 mutex_lock(&dev->mode_config.blob_lock);
814 /* Ensure the property was actually created by this user. */
815 list_for_each_entry(bt, &file_priv->blobs, head_file) {
816 if (bt == blob) {
817 found = true;
818 break;
819 }
820 }
821
822 if (!found) {
823 ret = -EPERM;
824 goto err;
825 }
826
827 /* We must drop head_file here, because we may not be the last
828 * reference on the blob. */
829 list_del_init(&blob->head_file);
830 mutex_unlock(&dev->mode_config.blob_lock);
831
832 /* One reference from lookup, and one from the filp. */
Thierry Reding6472e502017-02-28 15:46:42 +0100833 drm_property_blob_put(blob);
834 drm_property_blob_put(blob);
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200835
836 return 0;
837
838err:
839 mutex_unlock(&dev->mode_config.blob_lock);
Thierry Reding6472e502017-02-28 15:46:42 +0100840 drm_property_blob_put(blob);
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200841
842 return ret;
843}
844
845/* Some properties could refer to dynamic refcnt'd objects, or things that
846 * need special locking to handle lifetime issues (ie. to ensure the prop
847 * value doesn't become invalid part way through the property update due to
848 * race). The value returned by reference via 'obj' should be passed back
849 * to drm_property_change_valid_put() after the property is set (and the
850 * object to which the property is attached has a chance to take it's own
851 * reference).
852 */
853bool drm_property_change_valid_get(struct drm_property *property,
Daniel Vetterc8458c72016-08-29 10:27:57 +0200854 uint64_t value, struct drm_mode_object **ref)
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200855{
856 int i;
857
858 if (property->flags & DRM_MODE_PROP_IMMUTABLE)
859 return false;
860
861 *ref = NULL;
862
863 if (drm_property_type_is(property, DRM_MODE_PROP_RANGE)) {
864 if (value < property->values[0] || value > property->values[1])
865 return false;
866 return true;
867 } else if (drm_property_type_is(property, DRM_MODE_PROP_SIGNED_RANGE)) {
868 int64_t svalue = U642I64(value);
869
870 if (svalue < U642I64(property->values[0]) ||
871 svalue > U642I64(property->values[1]))
872 return false;
873 return true;
874 } else if (drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
875 uint64_t valid_mask = 0;
876
877 for (i = 0; i < property->num_values; i++)
878 valid_mask |= (1ULL << property->values[i]);
879 return !(value & ~valid_mask);
Maarten Lankhorst30c06572016-09-07 11:52:40 +0200880 } else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB)) {
881 struct drm_property_blob *blob;
882
883 if (value == 0)
884 return true;
885
886 blob = drm_property_lookup_blob(property->dev, value);
887 if (blob) {
888 *ref = &blob->base;
889 return true;
890 } else {
891 return false;
892 }
893 } else if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) {
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200894 /* a zero value for an object property translates to null: */
895 if (value == 0)
896 return true;
897
Keith Packard418da172017-03-14 23:25:07 -0700898 *ref = __drm_mode_object_find(property->dev, NULL, value,
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200899 property->values[0]);
900 return *ref != NULL;
901 }
902
903 for (i = 0; i < property->num_values; i++)
904 if (property->values[i] == value)
905 return true;
906 return false;
907}
908
909void drm_property_change_valid_put(struct drm_property *property,
Maarten Lankhorst30c06572016-09-07 11:52:40 +0200910 struct drm_mode_object *ref)
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200911{
912 if (!ref)
913 return;
914
Maarten Lankhorst30c06572016-09-07 11:52:40 +0200915 if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) {
Thierry Reding020a2182017-02-28 15:46:38 +0100916 drm_mode_object_put(ref);
Maarten Lankhorst30c06572016-09-07 11:52:40 +0200917 } else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB))
Thierry Reding6472e502017-02-28 15:46:42 +0100918 drm_property_blob_put(obj_to_blob(ref));
Daniel Vetter59e71ee2016-08-29 10:27:55 +0200919}