0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023 #include <linux/export.h>
0024 #include <linux/uaccess.h>
0025
0026 #include <drm/drm_crtc.h>
0027 #include <drm/drm_drv.h>
0028 #include <drm/drm_file.h>
0029 #include <drm/drm_framebuffer.h>
0030 #include <drm/drm_property.h>
0031
0032 #include "drm_crtc_internal.h"
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058 static bool drm_property_flags_valid(u32 flags)
0059 {
0060 u32 legacy_type = flags & DRM_MODE_PROP_LEGACY_TYPE;
0061 u32 ext_type = flags & DRM_MODE_PROP_EXTENDED_TYPE;
0062
0063
0064 if (flags & ~(DRM_MODE_PROP_LEGACY_TYPE |
0065 DRM_MODE_PROP_EXTENDED_TYPE |
0066 DRM_MODE_PROP_IMMUTABLE |
0067 DRM_MODE_PROP_ATOMIC))
0068 return false;
0069
0070
0071 if (!legacy_type == !ext_type)
0072 return false;
0073
0074
0075 if (legacy_type && !is_power_of_2(legacy_type))
0076 return false;
0077
0078 return true;
0079 }
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096 struct drm_property *drm_property_create(struct drm_device *dev,
0097 u32 flags, const char *name,
0098 int num_values)
0099 {
0100 struct drm_property *property = NULL;
0101 int ret;
0102
0103 if (WARN_ON(!drm_property_flags_valid(flags)))
0104 return NULL;
0105
0106 if (WARN_ON(strlen(name) >= DRM_PROP_NAME_LEN))
0107 return NULL;
0108
0109 property = kzalloc(sizeof(struct drm_property), GFP_KERNEL);
0110 if (!property)
0111 return NULL;
0112
0113 property->dev = dev;
0114
0115 if (num_values) {
0116 property->values = kcalloc(num_values, sizeof(uint64_t),
0117 GFP_KERNEL);
0118 if (!property->values)
0119 goto fail;
0120 }
0121
0122 ret = drm_mode_object_add(dev, &property->base, DRM_MODE_OBJECT_PROPERTY);
0123 if (ret)
0124 goto fail;
0125
0126 property->flags = flags;
0127 property->num_values = num_values;
0128 INIT_LIST_HEAD(&property->enum_list);
0129
0130 strscpy_pad(property->name, name, DRM_PROP_NAME_LEN);
0131
0132 list_add_tail(&property->head, &dev->mode_config.property_list);
0133
0134 return property;
0135 fail:
0136 kfree(property->values);
0137 kfree(property);
0138 return NULL;
0139 }
0140 EXPORT_SYMBOL(drm_property_create);
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161 struct drm_property *drm_property_create_enum(struct drm_device *dev,
0162 u32 flags, const char *name,
0163 const struct drm_prop_enum_list *props,
0164 int num_values)
0165 {
0166 struct drm_property *property;
0167 int i, ret;
0168
0169 flags |= DRM_MODE_PROP_ENUM;
0170
0171 property = drm_property_create(dev, flags, name, num_values);
0172 if (!property)
0173 return NULL;
0174
0175 for (i = 0; i < num_values; i++) {
0176 ret = drm_property_add_enum(property,
0177 props[i].type,
0178 props[i].name);
0179 if (ret) {
0180 drm_property_destroy(dev, property);
0181 return NULL;
0182 }
0183 }
0184
0185 return property;
0186 }
0187 EXPORT_SYMBOL(drm_property_create_enum);
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209 struct drm_property *drm_property_create_bitmask(struct drm_device *dev,
0210 u32 flags, const char *name,
0211 const struct drm_prop_enum_list *props,
0212 int num_props,
0213 uint64_t supported_bits)
0214 {
0215 struct drm_property *property;
0216 int i, ret;
0217 int num_values = hweight64(supported_bits);
0218
0219 flags |= DRM_MODE_PROP_BITMASK;
0220
0221 property = drm_property_create(dev, flags, name, num_values);
0222 if (!property)
0223 return NULL;
0224 for (i = 0; i < num_props; i++) {
0225 if (!(supported_bits & (1ULL << props[i].type)))
0226 continue;
0227
0228 ret = drm_property_add_enum(property,
0229 props[i].type,
0230 props[i].name);
0231 if (ret) {
0232 drm_property_destroy(dev, property);
0233 return NULL;
0234 }
0235 }
0236
0237 return property;
0238 }
0239 EXPORT_SYMBOL(drm_property_create_bitmask);
0240
0241 static struct drm_property *property_create_range(struct drm_device *dev,
0242 u32 flags, const char *name,
0243 uint64_t min, uint64_t max)
0244 {
0245 struct drm_property *property;
0246
0247 property = drm_property_create(dev, flags, name, 2);
0248 if (!property)
0249 return NULL;
0250
0251 property->values[0] = min;
0252 property->values[1] = max;
0253
0254 return property;
0255 }
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276 struct drm_property *drm_property_create_range(struct drm_device *dev,
0277 u32 flags, const char *name,
0278 uint64_t min, uint64_t max)
0279 {
0280 return property_create_range(dev, DRM_MODE_PROP_RANGE | flags,
0281 name, min, max);
0282 }
0283 EXPORT_SYMBOL(drm_property_create_range);
0284
0285
0286
0287
0288
0289
0290
0291
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301
0302
0303
0304 struct drm_property *drm_property_create_signed_range(struct drm_device *dev,
0305 u32 flags, const char *name,
0306 int64_t min, int64_t max)
0307 {
0308 return property_create_range(dev, DRM_MODE_PROP_SIGNED_RANGE | flags,
0309 name, I642U64(min), I642U64(max));
0310 }
0311 EXPORT_SYMBOL(drm_property_create_signed_range);
0312
0313
0314
0315
0316
0317
0318
0319
0320
0321
0322
0323
0324
0325
0326
0327
0328
0329
0330
0331 struct drm_property *drm_property_create_object(struct drm_device *dev,
0332 u32 flags, const char *name,
0333 uint32_t type)
0334 {
0335 struct drm_property *property;
0336
0337 flags |= DRM_MODE_PROP_OBJECT;
0338
0339 if (WARN_ON(!(flags & DRM_MODE_PROP_ATOMIC)))
0340 return NULL;
0341
0342 property = drm_property_create(dev, flags, name, 1);
0343 if (!property)
0344 return NULL;
0345
0346 property->values[0] = type;
0347
0348 return property;
0349 }
0350 EXPORT_SYMBOL(drm_property_create_object);
0351
0352
0353
0354
0355
0356
0357
0358
0359
0360
0361
0362
0363
0364
0365
0366
0367
0368 struct drm_property *drm_property_create_bool(struct drm_device *dev,
0369 u32 flags, const char *name)
0370 {
0371 return drm_property_create_range(dev, flags, name, 0, 1);
0372 }
0373 EXPORT_SYMBOL(drm_property_create_bool);
0374
0375
0376
0377
0378
0379
0380
0381
0382
0383
0384
0385
0386
0387
0388
0389 int drm_property_add_enum(struct drm_property *property,
0390 uint64_t value, const char *name)
0391 {
0392 struct drm_property_enum *prop_enum;
0393 int index = 0;
0394
0395 if (WARN_ON(strlen(name) >= DRM_PROP_NAME_LEN))
0396 return -EINVAL;
0397
0398 if (WARN_ON(!drm_property_type_is(property, DRM_MODE_PROP_ENUM) &&
0399 !drm_property_type_is(property, DRM_MODE_PROP_BITMASK)))
0400 return -EINVAL;
0401
0402
0403
0404
0405
0406 if (WARN_ON(drm_property_type_is(property, DRM_MODE_PROP_BITMASK) &&
0407 value > 63))
0408 return -EINVAL;
0409
0410 list_for_each_entry(prop_enum, &property->enum_list, head) {
0411 if (WARN_ON(prop_enum->value == value))
0412 return -EINVAL;
0413 index++;
0414 }
0415
0416 if (WARN_ON(index >= property->num_values))
0417 return -EINVAL;
0418
0419 prop_enum = kzalloc(sizeof(struct drm_property_enum), GFP_KERNEL);
0420 if (!prop_enum)
0421 return -ENOMEM;
0422
0423 strscpy_pad(prop_enum->name, name, DRM_PROP_NAME_LEN);
0424 prop_enum->value = value;
0425
0426 property->values[index] = value;
0427 list_add_tail(&prop_enum->head, &property->enum_list);
0428 return 0;
0429 }
0430 EXPORT_SYMBOL(drm_property_add_enum);
0431
0432
0433
0434
0435
0436
0437
0438
0439
0440 void drm_property_destroy(struct drm_device *dev, struct drm_property *property)
0441 {
0442 struct drm_property_enum *prop_enum, *pt;
0443
0444 list_for_each_entry_safe(prop_enum, pt, &property->enum_list, head) {
0445 list_del(&prop_enum->head);
0446 kfree(prop_enum);
0447 }
0448
0449 if (property->num_values)
0450 kfree(property->values);
0451 drm_mode_object_unregister(dev, &property->base);
0452 list_del(&property->head);
0453 kfree(property);
0454 }
0455 EXPORT_SYMBOL(drm_property_destroy);
0456
0457 int drm_mode_getproperty_ioctl(struct drm_device *dev,
0458 void *data, struct drm_file *file_priv)
0459 {
0460 struct drm_mode_get_property *out_resp = data;
0461 struct drm_property *property;
0462 int enum_count = 0;
0463 int value_count = 0;
0464 int i, copied;
0465 struct drm_property_enum *prop_enum;
0466 struct drm_mode_property_enum __user *enum_ptr;
0467 uint64_t __user *values_ptr;
0468
0469 if (!drm_core_check_feature(dev, DRIVER_MODESET))
0470 return -EOPNOTSUPP;
0471
0472 property = drm_property_find(dev, file_priv, out_resp->prop_id);
0473 if (!property)
0474 return -ENOENT;
0475
0476 strscpy_pad(out_resp->name, property->name, DRM_PROP_NAME_LEN);
0477 out_resp->flags = property->flags;
0478
0479 value_count = property->num_values;
0480 values_ptr = u64_to_user_ptr(out_resp->values_ptr);
0481
0482 for (i = 0; i < value_count; i++) {
0483 if (i < out_resp->count_values &&
0484 put_user(property->values[i], values_ptr + i)) {
0485 return -EFAULT;
0486 }
0487 }
0488 out_resp->count_values = value_count;
0489
0490 copied = 0;
0491 enum_ptr = u64_to_user_ptr(out_resp->enum_blob_ptr);
0492
0493 if (drm_property_type_is(property, DRM_MODE_PROP_ENUM) ||
0494 drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
0495 list_for_each_entry(prop_enum, &property->enum_list, head) {
0496 enum_count++;
0497 if (out_resp->count_enum_blobs < enum_count)
0498 continue;
0499
0500 if (copy_to_user(&enum_ptr[copied].value,
0501 &prop_enum->value, sizeof(uint64_t)))
0502 return -EFAULT;
0503
0504 if (copy_to_user(&enum_ptr[copied].name,
0505 &prop_enum->name, DRM_PROP_NAME_LEN))
0506 return -EFAULT;
0507 copied++;
0508 }
0509 out_resp->count_enum_blobs = enum_count;
0510 }
0511
0512
0513
0514
0515
0516
0517
0518
0519
0520 if (drm_property_type_is(property, DRM_MODE_PROP_BLOB))
0521 out_resp->count_enum_blobs = 0;
0522
0523 return 0;
0524 }
0525
0526 static void drm_property_free_blob(struct kref *kref)
0527 {
0528 struct drm_property_blob *blob =
0529 container_of(kref, struct drm_property_blob, base.refcount);
0530
0531 mutex_lock(&blob->dev->mode_config.blob_lock);
0532 list_del(&blob->head_global);
0533 mutex_unlock(&blob->dev->mode_config.blob_lock);
0534
0535 drm_mode_object_unregister(blob->dev, &blob->base);
0536
0537 kvfree(blob);
0538 }
0539
0540
0541
0542
0543
0544
0545
0546
0547
0548
0549
0550
0551
0552
0553
0554 struct drm_property_blob *
0555 drm_property_create_blob(struct drm_device *dev, size_t length,
0556 const void *data)
0557 {
0558 struct drm_property_blob *blob;
0559 int ret;
0560
0561 if (!length || length > INT_MAX - sizeof(struct drm_property_blob))
0562 return ERR_PTR(-EINVAL);
0563
0564 blob = kvzalloc(sizeof(struct drm_property_blob)+length, GFP_KERNEL);
0565 if (!blob)
0566 return ERR_PTR(-ENOMEM);
0567
0568
0569
0570 INIT_LIST_HEAD(&blob->head_file);
0571 blob->data = (void *)blob + sizeof(*blob);
0572 blob->length = length;
0573 blob->dev = dev;
0574
0575 if (data)
0576 memcpy(blob->data, data, length);
0577
0578 ret = __drm_mode_object_add(dev, &blob->base, DRM_MODE_OBJECT_BLOB,
0579 true, drm_property_free_blob);
0580 if (ret) {
0581 kvfree(blob);
0582 return ERR_PTR(-EINVAL);
0583 }
0584
0585 mutex_lock(&dev->mode_config.blob_lock);
0586 list_add_tail(&blob->head_global,
0587 &dev->mode_config.property_blob_list);
0588 mutex_unlock(&dev->mode_config.blob_lock);
0589
0590 return blob;
0591 }
0592 EXPORT_SYMBOL(drm_property_create_blob);
0593
0594
0595
0596
0597
0598
0599
0600 void drm_property_blob_put(struct drm_property_blob *blob)
0601 {
0602 if (!blob)
0603 return;
0604
0605 drm_mode_object_put(&blob->base);
0606 }
0607 EXPORT_SYMBOL(drm_property_blob_put);
0608
0609 void drm_property_destroy_user_blobs(struct drm_device *dev,
0610 struct drm_file *file_priv)
0611 {
0612 struct drm_property_blob *blob, *bt;
0613
0614
0615
0616
0617
0618 list_for_each_entry_safe(blob, bt, &file_priv->blobs, head_file) {
0619 list_del_init(&blob->head_file);
0620 drm_property_blob_put(blob);
0621 }
0622 }
0623
0624
0625
0626
0627
0628
0629
0630
0631 struct drm_property_blob *drm_property_blob_get(struct drm_property_blob *blob)
0632 {
0633 drm_mode_object_get(&blob->base);
0634 return blob;
0635 }
0636 EXPORT_SYMBOL(drm_property_blob_get);
0637
0638
0639
0640
0641
0642
0643
0644
0645
0646
0647
0648
0649
0650 struct drm_property_blob *drm_property_lookup_blob(struct drm_device *dev,
0651 uint32_t id)
0652 {
0653 struct drm_mode_object *obj;
0654 struct drm_property_blob *blob = NULL;
0655
0656 obj = __drm_mode_object_find(dev, NULL, id, DRM_MODE_OBJECT_BLOB);
0657 if (obj)
0658 blob = obj_to_blob(obj);
0659 return blob;
0660 }
0661 EXPORT_SYMBOL(drm_property_lookup_blob);
0662
0663
0664
0665
0666
0667
0668
0669
0670
0671
0672
0673
0674
0675
0676
0677
0678
0679
0680
0681
0682
0683
0684
0685
0686
0687
0688
0689
0690 int drm_property_replace_global_blob(struct drm_device *dev,
0691 struct drm_property_blob **replace,
0692 size_t length,
0693 const void *data,
0694 struct drm_mode_object *obj_holds_id,
0695 struct drm_property *prop_holds_id)
0696 {
0697 struct drm_property_blob *new_blob = NULL;
0698 struct drm_property_blob *old_blob = NULL;
0699 int ret;
0700
0701 WARN_ON(replace == NULL);
0702
0703 old_blob = *replace;
0704
0705 if (length && data) {
0706 new_blob = drm_property_create_blob(dev, length, data);
0707 if (IS_ERR(new_blob))
0708 return PTR_ERR(new_blob);
0709 }
0710
0711 if (obj_holds_id) {
0712 ret = drm_object_property_set_value(obj_holds_id,
0713 prop_holds_id,
0714 new_blob ?
0715 new_blob->base.id : 0);
0716 if (ret != 0)
0717 goto err_created;
0718 }
0719
0720 drm_property_blob_put(old_blob);
0721 *replace = new_blob;
0722
0723 return 0;
0724
0725 err_created:
0726 drm_property_blob_put(new_blob);
0727 return ret;
0728 }
0729 EXPORT_SYMBOL(drm_property_replace_global_blob);
0730
0731
0732
0733
0734
0735
0736
0737
0738 bool drm_property_replace_blob(struct drm_property_blob **blob,
0739 struct drm_property_blob *new_blob)
0740 {
0741 struct drm_property_blob *old_blob = *blob;
0742
0743 if (old_blob == new_blob)
0744 return false;
0745
0746 drm_property_blob_put(old_blob);
0747 if (new_blob)
0748 drm_property_blob_get(new_blob);
0749 *blob = new_blob;
0750 return true;
0751 }
0752 EXPORT_SYMBOL(drm_property_replace_blob);
0753
0754 int drm_mode_getblob_ioctl(struct drm_device *dev,
0755 void *data, struct drm_file *file_priv)
0756 {
0757 struct drm_mode_get_blob *out_resp = data;
0758 struct drm_property_blob *blob;
0759 int ret = 0;
0760
0761 if (!drm_core_check_feature(dev, DRIVER_MODESET))
0762 return -EOPNOTSUPP;
0763
0764 blob = drm_property_lookup_blob(dev, out_resp->blob_id);
0765 if (!blob)
0766 return -ENOENT;
0767
0768 if (out_resp->length == blob->length) {
0769 if (copy_to_user(u64_to_user_ptr(out_resp->data),
0770 blob->data,
0771 blob->length)) {
0772 ret = -EFAULT;
0773 goto unref;
0774 }
0775 }
0776 out_resp->length = blob->length;
0777 unref:
0778 drm_property_blob_put(blob);
0779
0780 return ret;
0781 }
0782
0783 int drm_mode_createblob_ioctl(struct drm_device *dev,
0784 void *data, struct drm_file *file_priv)
0785 {
0786 struct drm_mode_create_blob *out_resp = data;
0787 struct drm_property_blob *blob;
0788 int ret = 0;
0789
0790 if (!drm_core_check_feature(dev, DRIVER_MODESET))
0791 return -EOPNOTSUPP;
0792
0793 blob = drm_property_create_blob(dev, out_resp->length, NULL);
0794 if (IS_ERR(blob))
0795 return PTR_ERR(blob);
0796
0797 if (copy_from_user(blob->data,
0798 u64_to_user_ptr(out_resp->data),
0799 out_resp->length)) {
0800 ret = -EFAULT;
0801 goto out_blob;
0802 }
0803
0804
0805
0806
0807 mutex_lock(&dev->mode_config.blob_lock);
0808 out_resp->blob_id = blob->base.id;
0809 list_add_tail(&blob->head_file, &file_priv->blobs);
0810 mutex_unlock(&dev->mode_config.blob_lock);
0811
0812 return 0;
0813
0814 out_blob:
0815 drm_property_blob_put(blob);
0816 return ret;
0817 }
0818
0819 int drm_mode_destroyblob_ioctl(struct drm_device *dev,
0820 void *data, struct drm_file *file_priv)
0821 {
0822 struct drm_mode_destroy_blob *out_resp = data;
0823 struct drm_property_blob *blob = NULL, *bt;
0824 bool found = false;
0825 int ret = 0;
0826
0827 if (!drm_core_check_feature(dev, DRIVER_MODESET))
0828 return -EOPNOTSUPP;
0829
0830 blob = drm_property_lookup_blob(dev, out_resp->blob_id);
0831 if (!blob)
0832 return -ENOENT;
0833
0834 mutex_lock(&dev->mode_config.blob_lock);
0835
0836 list_for_each_entry(bt, &file_priv->blobs, head_file) {
0837 if (bt == blob) {
0838 found = true;
0839 break;
0840 }
0841 }
0842
0843 if (!found) {
0844 ret = -EPERM;
0845 goto err;
0846 }
0847
0848
0849
0850 list_del_init(&blob->head_file);
0851 mutex_unlock(&dev->mode_config.blob_lock);
0852
0853
0854 drm_property_blob_put(blob);
0855 drm_property_blob_put(blob);
0856
0857 return 0;
0858
0859 err:
0860 mutex_unlock(&dev->mode_config.blob_lock);
0861 drm_property_blob_put(blob);
0862
0863 return ret;
0864 }
0865
0866
0867
0868
0869
0870
0871
0872
0873
0874 bool drm_property_change_valid_get(struct drm_property *property,
0875 uint64_t value, struct drm_mode_object **ref)
0876 {
0877 int i;
0878
0879 if (property->flags & DRM_MODE_PROP_IMMUTABLE)
0880 return false;
0881
0882 *ref = NULL;
0883
0884 if (drm_property_type_is(property, DRM_MODE_PROP_RANGE)) {
0885 if (value < property->values[0] || value > property->values[1])
0886 return false;
0887 return true;
0888 } else if (drm_property_type_is(property, DRM_MODE_PROP_SIGNED_RANGE)) {
0889 int64_t svalue = U642I64(value);
0890
0891 if (svalue < U642I64(property->values[0]) ||
0892 svalue > U642I64(property->values[1]))
0893 return false;
0894 return true;
0895 } else if (drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
0896 uint64_t valid_mask = 0;
0897
0898 for (i = 0; i < property->num_values; i++)
0899 valid_mask |= (1ULL << property->values[i]);
0900 return !(value & ~valid_mask);
0901 } else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB)) {
0902 struct drm_property_blob *blob;
0903
0904 if (value == 0)
0905 return true;
0906
0907 blob = drm_property_lookup_blob(property->dev, value);
0908 if (blob) {
0909 *ref = &blob->base;
0910 return true;
0911 } else {
0912 return false;
0913 }
0914 } else if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) {
0915
0916 if (value == 0)
0917 return true;
0918
0919 *ref = __drm_mode_object_find(property->dev, NULL, value,
0920 property->values[0]);
0921 return *ref != NULL;
0922 }
0923
0924 for (i = 0; i < property->num_values; i++)
0925 if (property->values[i] == value)
0926 return true;
0927 return false;
0928 }
0929
0930 void drm_property_change_valid_put(struct drm_property *property,
0931 struct drm_mode_object *ref)
0932 {
0933 if (!ref)
0934 return;
0935
0936 if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) {
0937 drm_mode_object_put(ref);
0938 } else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB))
0939 drm_property_blob_put(obj_to_blob(ref));
0940 }