This source file includes following definitions.
- drm_property_flags_valid
- drm_property_create
- drm_property_create_enum
- drm_property_create_bitmask
- property_create_range
- drm_property_create_range
- drm_property_create_signed_range
- drm_property_create_object
- drm_property_create_bool
- drm_property_add_enum
- drm_property_destroy
- drm_mode_getproperty_ioctl
- drm_property_free_blob
- drm_property_create_blob
- drm_property_blob_put
- drm_property_destroy_user_blobs
- drm_property_blob_get
- drm_property_lookup_blob
- drm_property_replace_global_blob
- drm_property_replace_blob
- drm_mode_getblob_ioctl
- drm_mode_createblob_ioctl
- drm_mode_destroyblob_ioctl
- drm_property_change_valid_get
- drm_property_change_valid_put
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
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
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
71 if (!legacy_type == !ext_type)
72 return false;
73
74
75 if (legacy_type && !is_power_of_2(legacy_type))
76 return false;
77
78 return true;
79 }
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
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 strncpy(property->name, name, DRM_PROP_NAME_LEN);
131 property->name[DRM_PROP_NAME_LEN-1] = '\0';
132
133 list_add_tail(&property->head, &dev->mode_config.property_list);
134
135 return property;
136 fail:
137 kfree(property->values);
138 kfree(property);
139 return NULL;
140 }
141 EXPORT_SYMBOL(drm_property_create);
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162 struct drm_property *drm_property_create_enum(struct drm_device *dev,
163 u32 flags, const char *name,
164 const struct drm_prop_enum_list *props,
165 int num_values)
166 {
167 struct drm_property *property;
168 int i, ret;
169
170 flags |= DRM_MODE_PROP_ENUM;
171
172 property = drm_property_create(dev, flags, name, num_values);
173 if (!property)
174 return NULL;
175
176 for (i = 0; i < num_values; i++) {
177 ret = drm_property_add_enum(property,
178 props[i].type,
179 props[i].name);
180 if (ret) {
181 drm_property_destroy(dev, property);
182 return NULL;
183 }
184 }
185
186 return property;
187 }
188 EXPORT_SYMBOL(drm_property_create_enum);
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210 struct drm_property *drm_property_create_bitmask(struct drm_device *dev,
211 u32 flags, const char *name,
212 const struct drm_prop_enum_list *props,
213 int num_props,
214 uint64_t supported_bits)
215 {
216 struct drm_property *property;
217 int i, ret;
218 int num_values = hweight64(supported_bits);
219
220 flags |= DRM_MODE_PROP_BITMASK;
221
222 property = drm_property_create(dev, flags, name, num_values);
223 if (!property)
224 return NULL;
225 for (i = 0; i < num_props; i++) {
226 if (!(supported_bits & (1ULL << props[i].type)))
227 continue;
228
229 ret = drm_property_add_enum(property,
230 props[i].type,
231 props[i].name);
232 if (ret) {
233 drm_property_destroy(dev, property);
234 return NULL;
235 }
236 }
237
238 return property;
239 }
240 EXPORT_SYMBOL(drm_property_create_bitmask);
241
242 static struct drm_property *property_create_range(struct drm_device *dev,
243 u32 flags, const char *name,
244 uint64_t min, uint64_t max)
245 {
246 struct drm_property *property;
247
248 property = drm_property_create(dev, flags, name, 2);
249 if (!property)
250 return NULL;
251
252 property->values[0] = min;
253 property->values[1] = max;
254
255 return property;
256 }
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277 struct drm_property *drm_property_create_range(struct drm_device *dev,
278 u32 flags, const char *name,
279 uint64_t min, uint64_t max)
280 {
281 return property_create_range(dev, DRM_MODE_PROP_RANGE | flags,
282 name, min, max);
283 }
284 EXPORT_SYMBOL(drm_property_create_range);
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305 struct drm_property *drm_property_create_signed_range(struct drm_device *dev,
306 u32 flags, const char *name,
307 int64_t min, int64_t max)
308 {
309 return property_create_range(dev, DRM_MODE_PROP_SIGNED_RANGE | flags,
310 name, I642U64(min), I642U64(max));
311 }
312 EXPORT_SYMBOL(drm_property_create_signed_range);
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332 struct drm_property *drm_property_create_object(struct drm_device *dev,
333 u32 flags, const char *name,
334 uint32_t type)
335 {
336 struct drm_property *property;
337
338 flags |= DRM_MODE_PROP_OBJECT;
339
340 if (WARN_ON(!(flags & DRM_MODE_PROP_ATOMIC)))
341 return NULL;
342
343 property = drm_property_create(dev, flags, name, 1);
344 if (!property)
345 return NULL;
346
347 property->values[0] = type;
348
349 return property;
350 }
351 EXPORT_SYMBOL(drm_property_create_object);
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369 struct drm_property *drm_property_create_bool(struct drm_device *dev,
370 u32 flags, const char *name)
371 {
372 return drm_property_create_range(dev, flags, name, 0, 1);
373 }
374 EXPORT_SYMBOL(drm_property_create_bool);
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390 int drm_property_add_enum(struct drm_property *property,
391 uint64_t value, const char *name)
392 {
393 struct drm_property_enum *prop_enum;
394 int index = 0;
395
396 if (WARN_ON(strlen(name) >= DRM_PROP_NAME_LEN))
397 return -EINVAL;
398
399 if (WARN_ON(!drm_property_type_is(property, DRM_MODE_PROP_ENUM) &&
400 !drm_property_type_is(property, DRM_MODE_PROP_BITMASK)))
401 return -EINVAL;
402
403
404
405
406
407 if (WARN_ON(drm_property_type_is(property, DRM_MODE_PROP_BITMASK) &&
408 value > 63))
409 return -EINVAL;
410
411 list_for_each_entry(prop_enum, &property->enum_list, head) {
412 if (WARN_ON(prop_enum->value == value))
413 return -EINVAL;
414 index++;
415 }
416
417 if (WARN_ON(index >= property->num_values))
418 return -EINVAL;
419
420 prop_enum = kzalloc(sizeof(struct drm_property_enum), GFP_KERNEL);
421 if (!prop_enum)
422 return -ENOMEM;
423
424 strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN);
425 prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0';
426 prop_enum->value = value;
427
428 property->values[index] = value;
429 list_add_tail(&prop_enum->head, &property->enum_list);
430 return 0;
431 }
432 EXPORT_SYMBOL(drm_property_add_enum);
433
434
435
436
437
438
439
440
441
442 void drm_property_destroy(struct drm_device *dev, struct drm_property *property)
443 {
444 struct drm_property_enum *prop_enum, *pt;
445
446 list_for_each_entry_safe(prop_enum, pt, &property->enum_list, head) {
447 list_del(&prop_enum->head);
448 kfree(prop_enum);
449 }
450
451 if (property->num_values)
452 kfree(property->values);
453 drm_mode_object_unregister(dev, &property->base);
454 list_del(&property->head);
455 kfree(property);
456 }
457 EXPORT_SYMBOL(drm_property_destroy);
458
459 int drm_mode_getproperty_ioctl(struct drm_device *dev,
460 void *data, struct drm_file *file_priv)
461 {
462 struct drm_mode_get_property *out_resp = data;
463 struct drm_property *property;
464 int enum_count = 0;
465 int value_count = 0;
466 int i, copied;
467 struct drm_property_enum *prop_enum;
468 struct drm_mode_property_enum __user *enum_ptr;
469 uint64_t __user *values_ptr;
470
471 if (!drm_core_check_feature(dev, DRIVER_MODESET))
472 return -EOPNOTSUPP;
473
474 property = drm_property_find(dev, file_priv, out_resp->prop_id);
475 if (!property)
476 return -ENOENT;
477
478 strncpy(out_resp->name, property->name, DRM_PROP_NAME_LEN);
479 out_resp->name[DRM_PROP_NAME_LEN-1] = 0;
480 out_resp->flags = property->flags;
481
482 value_count = property->num_values;
483 values_ptr = u64_to_user_ptr(out_resp->values_ptr);
484
485 for (i = 0; i < value_count; i++) {
486 if (i < out_resp->count_values &&
487 put_user(property->values[i], values_ptr + i)) {
488 return -EFAULT;
489 }
490 }
491 out_resp->count_values = value_count;
492
493 copied = 0;
494 enum_ptr = u64_to_user_ptr(out_resp->enum_blob_ptr);
495
496 if (drm_property_type_is(property, DRM_MODE_PROP_ENUM) ||
497 drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
498 list_for_each_entry(prop_enum, &property->enum_list, head) {
499 enum_count++;
500 if (out_resp->count_enum_blobs < enum_count)
501 continue;
502
503 if (copy_to_user(&enum_ptr[copied].value,
504 &prop_enum->value, sizeof(uint64_t)))
505 return -EFAULT;
506
507 if (copy_to_user(&enum_ptr[copied].name,
508 &prop_enum->name, DRM_PROP_NAME_LEN))
509 return -EFAULT;
510 copied++;
511 }
512 out_resp->count_enum_blobs = enum_count;
513 }
514
515
516
517
518
519
520
521
522
523 if (drm_property_type_is(property, DRM_MODE_PROP_BLOB))
524 out_resp->count_enum_blobs = 0;
525
526 return 0;
527 }
528
529 static void drm_property_free_blob(struct kref *kref)
530 {
531 struct drm_property_blob *blob =
532 container_of(kref, struct drm_property_blob, base.refcount);
533
534 mutex_lock(&blob->dev->mode_config.blob_lock);
535 list_del(&blob->head_global);
536 mutex_unlock(&blob->dev->mode_config.blob_lock);
537
538 drm_mode_object_unregister(blob->dev, &blob->base);
539
540 kvfree(blob);
541 }
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557 struct drm_property_blob *
558 drm_property_create_blob(struct drm_device *dev, size_t length,
559 const void *data)
560 {
561 struct drm_property_blob *blob;
562 int ret;
563
564 if (!length || length > INT_MAX - sizeof(struct drm_property_blob))
565 return ERR_PTR(-EINVAL);
566
567 blob = kvzalloc(sizeof(struct drm_property_blob)+length, GFP_KERNEL);
568 if (!blob)
569 return ERR_PTR(-ENOMEM);
570
571
572
573 INIT_LIST_HEAD(&blob->head_file);
574 blob->data = (void *)blob + sizeof(*blob);
575 blob->length = length;
576 blob->dev = dev;
577
578 if (data)
579 memcpy(blob->data, data, length);
580
581 ret = __drm_mode_object_add(dev, &blob->base, DRM_MODE_OBJECT_BLOB,
582 true, drm_property_free_blob);
583 if (ret) {
584 kvfree(blob);
585 return ERR_PTR(-EINVAL);
586 }
587
588 mutex_lock(&dev->mode_config.blob_lock);
589 list_add_tail(&blob->head_global,
590 &dev->mode_config.property_blob_list);
591 mutex_unlock(&dev->mode_config.blob_lock);
592
593 return blob;
594 }
595 EXPORT_SYMBOL(drm_property_create_blob);
596
597
598
599
600
601
602
603 void drm_property_blob_put(struct drm_property_blob *blob)
604 {
605 if (!blob)
606 return;
607
608 drm_mode_object_put(&blob->base);
609 }
610 EXPORT_SYMBOL(drm_property_blob_put);
611
612 void drm_property_destroy_user_blobs(struct drm_device *dev,
613 struct drm_file *file_priv)
614 {
615 struct drm_property_blob *blob, *bt;
616
617
618
619
620
621 list_for_each_entry_safe(blob, bt, &file_priv->blobs, head_file) {
622 list_del_init(&blob->head_file);
623 drm_property_blob_put(blob);
624 }
625 }
626
627
628
629
630
631
632
633
634 struct drm_property_blob *drm_property_blob_get(struct drm_property_blob *blob)
635 {
636 drm_mode_object_get(&blob->base);
637 return blob;
638 }
639 EXPORT_SYMBOL(drm_property_blob_get);
640
641
642
643
644
645
646
647
648
649
650
651
652
653 struct drm_property_blob *drm_property_lookup_blob(struct drm_device *dev,
654 uint32_t id)
655 {
656 struct drm_mode_object *obj;
657 struct drm_property_blob *blob = NULL;
658
659 obj = __drm_mode_object_find(dev, NULL, id, DRM_MODE_OBJECT_BLOB);
660 if (obj)
661 blob = obj_to_blob(obj);
662 return blob;
663 }
664 EXPORT_SYMBOL(drm_property_lookup_blob);
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693 int drm_property_replace_global_blob(struct drm_device *dev,
694 struct drm_property_blob **replace,
695 size_t length,
696 const void *data,
697 struct drm_mode_object *obj_holds_id,
698 struct drm_property *prop_holds_id)
699 {
700 struct drm_property_blob *new_blob = NULL;
701 struct drm_property_blob *old_blob = NULL;
702 int ret;
703
704 WARN_ON(replace == NULL);
705
706 old_blob = *replace;
707
708 if (length && data) {
709 new_blob = drm_property_create_blob(dev, length, data);
710 if (IS_ERR(new_blob))
711 return PTR_ERR(new_blob);
712 }
713
714 if (obj_holds_id) {
715 ret = drm_object_property_set_value(obj_holds_id,
716 prop_holds_id,
717 new_blob ?
718 new_blob->base.id : 0);
719 if (ret != 0)
720 goto err_created;
721 }
722
723 drm_property_blob_put(old_blob);
724 *replace = new_blob;
725
726 return 0;
727
728 err_created:
729 drm_property_blob_put(new_blob);
730 return ret;
731 }
732 EXPORT_SYMBOL(drm_property_replace_global_blob);
733
734
735
736
737
738
739
740
741 bool drm_property_replace_blob(struct drm_property_blob **blob,
742 struct drm_property_blob *new_blob)
743 {
744 struct drm_property_blob *old_blob = *blob;
745
746 if (old_blob == new_blob)
747 return false;
748
749 drm_property_blob_put(old_blob);
750 if (new_blob)
751 drm_property_blob_get(new_blob);
752 *blob = new_blob;
753 return true;
754 }
755 EXPORT_SYMBOL(drm_property_replace_blob);
756
757 int drm_mode_getblob_ioctl(struct drm_device *dev,
758 void *data, struct drm_file *file_priv)
759 {
760 struct drm_mode_get_blob *out_resp = data;
761 struct drm_property_blob *blob;
762 int ret = 0;
763
764 if (!drm_core_check_feature(dev, DRIVER_MODESET))
765 return -EOPNOTSUPP;
766
767 blob = drm_property_lookup_blob(dev, out_resp->blob_id);
768 if (!blob)
769 return -ENOENT;
770
771 if (out_resp->length == blob->length) {
772 if (copy_to_user(u64_to_user_ptr(out_resp->data),
773 blob->data,
774 blob->length)) {
775 ret = -EFAULT;
776 goto unref;
777 }
778 }
779 out_resp->length = blob->length;
780 unref:
781 drm_property_blob_put(blob);
782
783 return ret;
784 }
785
786 int drm_mode_createblob_ioctl(struct drm_device *dev,
787 void *data, struct drm_file *file_priv)
788 {
789 struct drm_mode_create_blob *out_resp = data;
790 struct drm_property_blob *blob;
791 int ret = 0;
792
793 if (!drm_core_check_feature(dev, DRIVER_MODESET))
794 return -EOPNOTSUPP;
795
796 blob = drm_property_create_blob(dev, out_resp->length, NULL);
797 if (IS_ERR(blob))
798 return PTR_ERR(blob);
799
800 if (copy_from_user(blob->data,
801 u64_to_user_ptr(out_resp->data),
802 out_resp->length)) {
803 ret = -EFAULT;
804 goto out_blob;
805 }
806
807
808
809
810 mutex_lock(&dev->mode_config.blob_lock);
811 out_resp->blob_id = blob->base.id;
812 list_add_tail(&blob->head_file, &file_priv->blobs);
813 mutex_unlock(&dev->mode_config.blob_lock);
814
815 return 0;
816
817 out_blob:
818 drm_property_blob_put(blob);
819 return ret;
820 }
821
822 int drm_mode_destroyblob_ioctl(struct drm_device *dev,
823 void *data, struct drm_file *file_priv)
824 {
825 struct drm_mode_destroy_blob *out_resp = data;
826 struct drm_property_blob *blob = NULL, *bt;
827 bool found = false;
828 int ret = 0;
829
830 if (!drm_core_check_feature(dev, DRIVER_MODESET))
831 return -EOPNOTSUPP;
832
833 blob = drm_property_lookup_blob(dev, out_resp->blob_id);
834 if (!blob)
835 return -ENOENT;
836
837 mutex_lock(&dev->mode_config.blob_lock);
838
839 list_for_each_entry(bt, &file_priv->blobs, head_file) {
840 if (bt == blob) {
841 found = true;
842 break;
843 }
844 }
845
846 if (!found) {
847 ret = -EPERM;
848 goto err;
849 }
850
851
852
853 list_del_init(&blob->head_file);
854 mutex_unlock(&dev->mode_config.blob_lock);
855
856
857 drm_property_blob_put(blob);
858 drm_property_blob_put(blob);
859
860 return 0;
861
862 err:
863 mutex_unlock(&dev->mode_config.blob_lock);
864 drm_property_blob_put(blob);
865
866 return ret;
867 }
868
869
870
871
872
873
874
875
876
877 bool drm_property_change_valid_get(struct drm_property *property,
878 uint64_t value, struct drm_mode_object **ref)
879 {
880 int i;
881
882 if (property->flags & DRM_MODE_PROP_IMMUTABLE)
883 return false;
884
885 *ref = NULL;
886
887 if (drm_property_type_is(property, DRM_MODE_PROP_RANGE)) {
888 if (value < property->values[0] || value > property->values[1])
889 return false;
890 return true;
891 } else if (drm_property_type_is(property, DRM_MODE_PROP_SIGNED_RANGE)) {
892 int64_t svalue = U642I64(value);
893
894 if (svalue < U642I64(property->values[0]) ||
895 svalue > U642I64(property->values[1]))
896 return false;
897 return true;
898 } else if (drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
899 uint64_t valid_mask = 0;
900
901 for (i = 0; i < property->num_values; i++)
902 valid_mask |= (1ULL << property->values[i]);
903 return !(value & ~valid_mask);
904 } else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB)) {
905 struct drm_property_blob *blob;
906
907 if (value == 0)
908 return true;
909
910 blob = drm_property_lookup_blob(property->dev, value);
911 if (blob) {
912 *ref = &blob->base;
913 return true;
914 } else {
915 return false;
916 }
917 } else if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) {
918
919 if (value == 0)
920 return true;
921
922 *ref = __drm_mode_object_find(property->dev, NULL, value,
923 property->values[0]);
924 return *ref != NULL;
925 }
926
927 for (i = 0; i < property->num_values; i++)
928 if (property->values[i] == value)
929 return true;
930 return false;
931 }
932
933 void drm_property_change_valid_put(struct drm_property *property,
934 struct drm_mode_object *ref)
935 {
936 if (!ref)
937 return;
938
939 if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) {
940 drm_mode_object_put(ref);
941 } else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB))
942 drm_property_blob_put(obj_to_blob(ref));
943 }