Line data Source code
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 :
58 601 : static bool drm_property_flags_valid(u32 flags)
59 : {
60 601 : u32 legacy_type = flags & DRM_MODE_PROP_LEGACY_TYPE;
61 601 : u32 ext_type = flags & DRM_MODE_PROP_EXTENDED_TYPE;
62 :
63 : /* Reject undefined/deprecated flags */
64 601 : 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 601 : if (!legacy_type == !ext_type)
72 : return false;
73 :
74 : /* Only one legacy type at a time please */
75 1117 : if (legacy_type && !is_power_of_2(legacy_type))
76 : return false;
77 :
78 601 : 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 : */
96 601 : struct drm_property *drm_property_create(struct drm_device *dev,
97 : u32 flags, const char *name,
98 : int num_values)
99 : {
100 601 : struct drm_property *property = NULL;
101 : int ret;
102 :
103 601 : if (WARN_ON(!drm_property_flags_valid(flags)))
104 : return NULL;
105 :
106 601 : if (WARN_ON(strlen(name) >= DRM_PROP_NAME_LEN))
107 : return NULL;
108 :
109 601 : property = kzalloc(sizeof(struct drm_property), GFP_KERNEL);
110 601 : if (!property)
111 : return NULL;
112 :
113 601 : property->dev = dev;
114 :
115 601 : if (num_values) {
116 860 : property->values = kcalloc(num_values, sizeof(uint64_t),
117 : GFP_KERNEL);
118 430 : if (!property->values)
119 : goto fail;
120 : }
121 :
122 601 : ret = drm_mode_object_add(dev, &property->base, DRM_MODE_OBJECT_PROPERTY);
123 601 : if (ret)
124 : goto fail;
125 :
126 601 : property->flags = flags;
127 601 : property->num_values = num_values;
128 1202 : INIT_LIST_HEAD(&property->enum_list);
129 :
130 601 : strscpy_pad(property->name, name, DRM_PROP_NAME_LEN);
131 :
132 1202 : list_add_tail(&property->head, &dev->mode_config.property_list);
133 :
134 601 : return property;
135 : fail:
136 0 : kfree(property->values);
137 0 : kfree(property);
138 0 : 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 : */
161 72 : 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 72 : flags |= DRM_MODE_PROP_ENUM;
170 :
171 72 : property = drm_property_create(dev, flags, name, num_values);
172 72 : if (!property)
173 : return NULL;
174 :
175 233 : for (i = 0; i < num_values; i++) {
176 466 : ret = drm_property_add_enum(property,
177 233 : props[i].type,
178 233 : props[i].name);
179 233 : if (ret) {
180 0 : drm_property_destroy(dev, property);
181 0 : 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 : */
209 0 : 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 0 : int num_values = hweight64(supported_bits);
218 :
219 0 : flags |= DRM_MODE_PROP_BITMASK;
220 :
221 0 : property = drm_property_create(dev, flags, name, num_values);
222 0 : if (!property)
223 : return NULL;
224 0 : for (i = 0; i < num_props; i++) {
225 0 : if (!(supported_bits & (1ULL << props[i].type)))
226 0 : continue;
227 :
228 0 : ret = drm_property_add_enum(property,
229 : props[i].type,
230 : props[i].name);
231 0 : if (ret) {
232 0 : drm_property_destroy(dev, property);
233 0 : return NULL;
234 : }
235 : }
236 :
237 : return property;
238 : }
239 : EXPORT_SYMBOL(drm_property_create_bitmask);
240 :
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 325 : property = drm_property_create(dev, flags, name, 2);
248 325 : if (!property)
249 : return NULL;
250 :
251 325 : property->values[0] = min;
252 325 : 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 : */
276 223 : 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 548 : 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 : */
304 51 : 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 153 : 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 : */
331 34 : 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 34 : flags |= DRM_MODE_PROP_OBJECT;
338 :
339 34 : if (WARN_ON(!(flags & DRM_MODE_PROP_ATOMIC)))
340 : return NULL;
341 :
342 34 : property = drm_property_create(dev, flags, name, 1);
343 34 : if (!property)
344 : return NULL;
345 :
346 34 : property->values[0] = type;
347 :
348 34 : 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 : */
368 51 : struct drm_property *drm_property_create_bool(struct drm_device *dev,
369 : u32 flags, const char *name)
370 : {
371 51 : 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 : */
389 233 : 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 233 : int index = 0;
394 :
395 233 : if (WARN_ON(strlen(name) >= DRM_PROP_NAME_LEN))
396 : return -EINVAL;
397 :
398 466 : 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 466 : if (WARN_ON(drm_property_type_is(property, DRM_MODE_PROP_BITMASK) &&
407 : value > 63))
408 : return -EINVAL;
409 :
410 547 : list_for_each_entry(prop_enum, &property->enum_list, head) {
411 314 : if (WARN_ON(prop_enum->value == value))
412 : return -EINVAL;
413 314 : index++;
414 : }
415 :
416 233 : if (WARN_ON(index >= property->num_values))
417 : return -EINVAL;
418 :
419 233 : prop_enum = kzalloc(sizeof(struct drm_property_enum), GFP_KERNEL);
420 233 : if (!prop_enum)
421 : return -ENOMEM;
422 :
423 233 : strscpy_pad(prop_enum->name, name, DRM_PROP_NAME_LEN);
424 233 : prop_enum->value = value;
425 :
426 233 : property->values[index] = value;
427 466 : list_add_tail(&prop_enum->head, &property->enum_list);
428 233 : 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 : */
440 601 : void drm_property_destroy(struct drm_device *dev, struct drm_property *property)
441 : {
442 : struct drm_property_enum *prop_enum, *pt;
443 :
444 834 : list_for_each_entry_safe(prop_enum, pt, &property->enum_list, head) {
445 466 : list_del(&prop_enum->head);
446 233 : kfree(prop_enum);
447 : }
448 :
449 601 : if (property->num_values)
450 430 : kfree(property->values);
451 601 : drm_mode_object_unregister(dev, &property->base);
452 1202 : list_del(&property->head);
453 601 : kfree(property);
454 601 : }
455 : EXPORT_SYMBOL(drm_property_destroy);
456 :
457 0 : int drm_mode_getproperty_ioctl(struct drm_device *dev,
458 : void *data, struct drm_file *file_priv)
459 : {
460 0 : struct drm_mode_get_property *out_resp = data;
461 : struct drm_property *property;
462 0 : int enum_count = 0;
463 0 : 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 0 : if (!drm_core_check_feature(dev, DRIVER_MODESET))
470 : return -EOPNOTSUPP;
471 :
472 0 : property = drm_property_find(dev, file_priv, out_resp->prop_id);
473 0 : if (!property)
474 : return -ENOENT;
475 :
476 0 : strscpy_pad(out_resp->name, property->name, DRM_PROP_NAME_LEN);
477 0 : out_resp->flags = property->flags;
478 :
479 0 : value_count = property->num_values;
480 0 : values_ptr = u64_to_user_ptr(out_resp->values_ptr);
481 :
482 0 : for (i = 0; i < value_count; i++) {
483 0 : if (i < out_resp->count_values &&
484 0 : put_user(property->values[i], values_ptr + i)) {
485 : return -EFAULT;
486 : }
487 : }
488 0 : out_resp->count_values = value_count;
489 :
490 0 : copied = 0;
491 0 : enum_ptr = u64_to_user_ptr(out_resp->enum_blob_ptr);
492 :
493 0 : if (drm_property_type_is(property, DRM_MODE_PROP_ENUM) ||
494 0 : drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
495 0 : list_for_each_entry(prop_enum, &property->enum_list, head) {
496 0 : enum_count++;
497 0 : if (out_resp->count_enum_blobs < enum_count)
498 0 : continue;
499 :
500 0 : if (copy_to_user(&enum_ptr[copied].value,
501 0 : &prop_enum->value, sizeof(uint64_t)))
502 : return -EFAULT;
503 :
504 0 : if (copy_to_user(&enum_ptr[copied].name,
505 0 : &prop_enum->name, DRM_PROP_NAME_LEN))
506 : return -EFAULT;
507 0 : copied++;
508 : }
509 0 : 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 0 : if (drm_property_type_is(property, DRM_MODE_PROP_BLOB))
521 0 : out_resp->count_enum_blobs = 0;
522 :
523 : return 0;
524 : }
525 :
526 0 : static void drm_property_free_blob(struct kref *kref)
527 : {
528 0 : struct drm_property_blob *blob =
529 0 : container_of(kref, struct drm_property_blob, base.refcount);
530 :
531 0 : mutex_lock(&blob->dev->mode_config.blob_lock);
532 0 : list_del(&blob->head_global);
533 0 : mutex_unlock(&blob->dev->mode_config.blob_lock);
534 :
535 0 : drm_mode_object_unregister(blob->dev, &blob->base);
536 :
537 0 : kvfree(blob);
538 0 : }
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 *
555 0 : 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 0 : if (!length || length > INT_MAX - sizeof(struct drm_property_blob))
562 : return ERR_PTR(-EINVAL);
563 :
564 0 : blob = kvzalloc(sizeof(struct drm_property_blob)+length, GFP_KERNEL);
565 0 : 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 0 : INIT_LIST_HEAD(&blob->head_file);
571 0 : blob->data = (void *)blob + sizeof(*blob);
572 0 : blob->length = length;
573 0 : blob->dev = dev;
574 :
575 0 : if (data)
576 0 : memcpy(blob->data, data, length);
577 :
578 0 : ret = __drm_mode_object_add(dev, &blob->base, DRM_MODE_OBJECT_BLOB,
579 : true, drm_property_free_blob);
580 0 : if (ret) {
581 0 : kvfree(blob);
582 0 : return ERR_PTR(-EINVAL);
583 : }
584 :
585 0 : mutex_lock(&dev->mode_config.blob_lock);
586 0 : list_add_tail(&blob->head_global,
587 : &dev->mode_config.property_blob_list);
588 0 : mutex_unlock(&dev->mode_config.blob_lock);
589 :
590 0 : 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 : */
600 0 : void drm_property_blob_put(struct drm_property_blob *blob)
601 : {
602 0 : if (!blob)
603 : return;
604 :
605 0 : drm_mode_object_put(&blob->base);
606 : }
607 : EXPORT_SYMBOL(drm_property_blob_put);
608 :
609 0 : 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 0 : list_for_each_entry_safe(blob, bt, &file_priv->blobs, head_file) {
619 0 : list_del_init(&blob->head_file);
620 0 : drm_property_blob_put(blob);
621 : }
622 0 : }
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 : */
631 0 : struct drm_property_blob *drm_property_blob_get(struct drm_property_blob *blob)
632 : {
633 0 : drm_mode_object_get(&blob->base);
634 0 : 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 : */
650 0 : struct drm_property_blob *drm_property_lookup_blob(struct drm_device *dev,
651 : uint32_t id)
652 : {
653 : struct drm_mode_object *obj;
654 0 : struct drm_property_blob *blob = NULL;
655 :
656 0 : obj = __drm_mode_object_find(dev, NULL, id, DRM_MODE_OBJECT_BLOB);
657 0 : if (obj)
658 0 : blob = obj_to_blob(obj);
659 0 : 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 : */
690 0 : 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 0 : struct drm_property_blob *new_blob = NULL;
698 0 : struct drm_property_blob *old_blob = NULL;
699 : int ret;
700 :
701 0 : WARN_ON(replace == NULL);
702 :
703 0 : old_blob = *replace;
704 :
705 0 : if (length && data) {
706 0 : new_blob = drm_property_create_blob(dev, length, data);
707 0 : if (IS_ERR(new_blob))
708 0 : return PTR_ERR(new_blob);
709 : }
710 :
711 0 : if (obj_holds_id) {
712 0 : ret = drm_object_property_set_value(obj_holds_id,
713 : prop_holds_id,
714 : new_blob ?
715 0 : new_blob->base.id : 0);
716 0 : if (ret != 0)
717 : goto err_created;
718 : }
719 :
720 0 : drm_property_blob_put(old_blob);
721 0 : *replace = new_blob;
722 :
723 0 : 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 : */
738 0 : bool drm_property_replace_blob(struct drm_property_blob **blob,
739 : struct drm_property_blob *new_blob)
740 : {
741 0 : struct drm_property_blob *old_blob = *blob;
742 :
743 0 : if (old_blob == new_blob)
744 : return false;
745 :
746 0 : drm_property_blob_put(old_blob);
747 0 : if (new_blob)
748 : drm_property_blob_get(new_blob);
749 0 : *blob = new_blob;
750 0 : return true;
751 : }
752 : EXPORT_SYMBOL(drm_property_replace_blob);
753 :
754 0 : int drm_mode_getblob_ioctl(struct drm_device *dev,
755 : void *data, struct drm_file *file_priv)
756 : {
757 0 : struct drm_mode_get_blob *out_resp = data;
758 : struct drm_property_blob *blob;
759 0 : int ret = 0;
760 :
761 0 : if (!drm_core_check_feature(dev, DRIVER_MODESET))
762 : return -EOPNOTSUPP;
763 :
764 0 : blob = drm_property_lookup_blob(dev, out_resp->blob_id);
765 0 : if (!blob)
766 : return -ENOENT;
767 :
768 0 : if (out_resp->length == blob->length) {
769 0 : if (copy_to_user(u64_to_user_ptr(out_resp->data),
770 0 : blob->data,
771 : blob->length)) {
772 : ret = -EFAULT;
773 : goto unref;
774 : }
775 : }
776 0 : out_resp->length = blob->length;
777 : unref:
778 0 : drm_property_blob_put(blob);
779 :
780 0 : return ret;
781 : }
782 :
783 0 : int drm_mode_createblob_ioctl(struct drm_device *dev,
784 : void *data, struct drm_file *file_priv)
785 : {
786 0 : struct drm_mode_create_blob *out_resp = data;
787 : struct drm_property_blob *blob;
788 0 : int ret = 0;
789 :
790 0 : if (!drm_core_check_feature(dev, DRIVER_MODESET))
791 : return -EOPNOTSUPP;
792 :
793 0 : blob = drm_property_create_blob(dev, out_resp->length, NULL);
794 0 : if (IS_ERR(blob))
795 0 : return PTR_ERR(blob);
796 :
797 0 : if (copy_from_user(blob->data,
798 0 : u64_to_user_ptr(out_resp->data),
799 0 : out_resp->length)) {
800 0 : 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 0 : mutex_lock(&dev->mode_config.blob_lock);
808 0 : out_resp->blob_id = blob->base.id;
809 0 : list_add_tail(&blob->head_file, &file_priv->blobs);
810 0 : mutex_unlock(&dev->mode_config.blob_lock);
811 :
812 0 : return 0;
813 :
814 : out_blob:
815 : drm_property_blob_put(blob);
816 : return ret;
817 : }
818 :
819 0 : int drm_mode_destroyblob_ioctl(struct drm_device *dev,
820 : void *data, struct drm_file *file_priv)
821 : {
822 0 : struct drm_mode_destroy_blob *out_resp = data;
823 0 : struct drm_property_blob *blob = NULL, *bt;
824 0 : bool found = false;
825 0 : int ret = 0;
826 :
827 0 : if (!drm_core_check_feature(dev, DRIVER_MODESET))
828 : return -EOPNOTSUPP;
829 :
830 0 : blob = drm_property_lookup_blob(dev, out_resp->blob_id);
831 0 : if (!blob)
832 : return -ENOENT;
833 :
834 0 : mutex_lock(&dev->mode_config.blob_lock);
835 : /* Ensure the property was actually created by this user. */
836 0 : list_for_each_entry(bt, &file_priv->blobs, head_file) {
837 0 : if (bt == blob) {
838 : found = true;
839 : break;
840 : }
841 : }
842 :
843 0 : if (!found) {
844 0 : 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 0 : list_del_init(&blob->head_file);
851 0 : mutex_unlock(&dev->mode_config.blob_lock);
852 :
853 : /* One reference from lookup, and one from the filp. */
854 0 : drm_property_blob_put(blob);
855 0 : drm_property_blob_put(blob);
856 :
857 0 : return 0;
858 :
859 : err:
860 0 : mutex_unlock(&dev->mode_config.blob_lock);
861 0 : drm_property_blob_put(blob);
862 :
863 0 : 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 : */
874 0 : 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 0 : if (property->flags & DRM_MODE_PROP_IMMUTABLE)
880 : return false;
881 :
882 0 : *ref = NULL;
883 :
884 0 : if (drm_property_type_is(property, DRM_MODE_PROP_RANGE)) {
885 0 : if (value < property->values[0] || value > property->values[1])
886 : return false;
887 0 : return true;
888 0 : } else if (drm_property_type_is(property, DRM_MODE_PROP_SIGNED_RANGE)) {
889 0 : int64_t svalue = U642I64(value);
890 :
891 0 : if (svalue < U642I64(property->values[0]) ||
892 0 : svalue > U642I64(property->values[1]))
893 : return false;
894 : return true;
895 0 : } else if (drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
896 : uint64_t valid_mask = 0;
897 :
898 0 : for (i = 0; i < property->num_values; i++)
899 0 : valid_mask |= (1ULL << property->values[i]);
900 0 : return !(value & ~valid_mask);
901 0 : } else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB)) {
902 : struct drm_property_blob *blob;
903 :
904 0 : if (value == 0)
905 : return true;
906 :
907 0 : blob = drm_property_lookup_blob(property->dev, value);
908 0 : if (blob) {
909 0 : *ref = &blob->base;
910 0 : return true;
911 : } else {
912 : return false;
913 : }
914 0 : } else if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) {
915 : /* a zero value for an object property translates to null: */
916 0 : if (value == 0)
917 : return true;
918 :
919 0 : *ref = __drm_mode_object_find(property->dev, NULL, value,
920 0 : property->values[0]);
921 0 : return *ref != NULL;
922 : }
923 :
924 0 : for (i = 0; i < property->num_values; i++)
925 0 : if (property->values[i] == value)
926 : return true;
927 : return false;
928 : }
929 :
930 0 : void drm_property_change_valid_put(struct drm_property *property,
931 : struct drm_mode_object *ref)
932 : {
933 0 : if (!ref)
934 : return;
935 :
936 0 : if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) {
937 0 : drm_mode_object_put(ref);
938 0 : } else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB))
939 0 : drm_property_blob_put(obj_to_blob(ref));
940 : }
|