Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (c) 2016 Intel Corporation
0003  *
0004  * Permission to use, copy, modify, distribute, and sell this software and its
0005  * documentation for any purpose is hereby granted without fee, provided that
0006  * the above copyright notice appear in all copies and that both that copyright
0007  * notice and this permission notice appear in supporting documentation, and
0008  * that the name of the copyright holders not be used in advertising or
0009  * publicity pertaining to distribution of the software without specific,
0010  * written prior permission.  The copyright holders make no representations
0011  * about the suitability of this software for any purpose.  It is provided "as
0012  * is" without express or implied warranty.
0013  *
0014  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
0015  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
0016  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
0017  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
0018  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
0019  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
0020  * OF THIS SOFTWARE.
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  * DOC: overview
0036  *
0037  * Properties as represented by &drm_property are used to extend the modeset
0038  * interface exposed to userspace. For the atomic modeset IOCTL properties are
0039  * even the only way to transport metadata about the desired new modeset
0040  * configuration from userspace to the kernel. Properties have a well-defined
0041  * value range, which is enforced by the drm core. See the documentation of the
0042  * flags member of &struct drm_property for an overview of the different
0043  * property types and ranges.
0044  *
0045  * Properties don't store the current value directly, but need to be
0046  * instantiated by attaching them to a &drm_mode_object with
0047  * drm_object_attach_property().
0048  *
0049  * Property values are only 64bit. To support bigger piles of data (like gamma
0050  * tables, color correction matrices or large structures) a property can instead
0051  * point at a &drm_property_blob with that additional data.
0052  *
0053  * Properties are defined by their symbolic name, userspace must keep a
0054  * per-object mapping from those names to the property ID used in the atomic
0055  * IOCTL and in the get/set property IOCTL.
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     /* Reject undefined/deprecated flags */
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     /* We want either a legacy type or an extended type, but not both */
0071     if (!legacy_type == !ext_type)
0072         return false;
0073 
0074     /* Only one legacy type at a time please */
0075     if (legacy_type && !is_power_of_2(legacy_type))
0076         return false;
0077 
0078     return true;
0079 }
0080 
0081 /**
0082  * drm_property_create - create a new property type
0083  * @dev: drm device
0084  * @flags: flags specifying the property type
0085  * @name: name of the property
0086  * @num_values: number of pre-defined values
0087  *
0088  * This creates a new generic drm property which can then be attached to a drm
0089  * object with drm_object_attach_property(). The returned property object must
0090  * be freed with drm_property_destroy(), which is done automatically when
0091  * calling drm_mode_config_cleanup().
0092  *
0093  * Returns:
0094  * A pointer to the newly created property on success, NULL on failure.
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  * drm_property_create_enum - create a new enumeration property type
0144  * @dev: drm device
0145  * @flags: flags specifying the property type
0146  * @name: name of the property
0147  * @props: enumeration lists with property values
0148  * @num_values: number of pre-defined values
0149  *
0150  * This creates a new generic drm property which can then be attached to a drm
0151  * object with drm_object_attach_property(). The returned property object must
0152  * be freed with drm_property_destroy(), which is done automatically when
0153  * calling drm_mode_config_cleanup().
0154  *
0155  * Userspace is only allowed to set one of the predefined values for enumeration
0156  * properties.
0157  *
0158  * Returns:
0159  * A pointer to the newly created property on success, NULL on failure.
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  * drm_property_create_bitmask - create a new bitmask property type
0191  * @dev: drm device
0192  * @flags: flags specifying the property type
0193  * @name: name of the property
0194  * @props: enumeration lists with property bitflags
0195  * @num_props: size of the @props array
0196  * @supported_bits: bitmask of all supported enumeration values
0197  *
0198  * This creates a new bitmask drm property which can then be attached to a drm
0199  * object with drm_object_attach_property(). The returned property object must
0200  * be freed with drm_property_destroy(), which is done automatically when
0201  * calling drm_mode_config_cleanup().
0202  *
0203  * Compared to plain enumeration properties userspace is allowed to set any
0204  * or'ed together combination of the predefined property bitflag values
0205  *
0206  * Returns:
0207  * A pointer to the newly created property on success, NULL on failure.
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  * drm_property_create_range - create a new unsigned ranged property type
0259  * @dev: drm device
0260  * @flags: flags specifying the property type
0261  * @name: name of the property
0262  * @min: minimum value of the property
0263  * @max: maximum value of the property
0264  *
0265  * This creates a new generic drm property which can then be attached to a drm
0266  * object with drm_object_attach_property(). The returned property object must
0267  * be freed with drm_property_destroy(), which is done automatically when
0268  * calling drm_mode_config_cleanup().
0269  *
0270  * Userspace is allowed to set any unsigned integer value in the (min, max)
0271  * range inclusive.
0272  *
0273  * Returns:
0274  * A pointer to the newly created property on success, NULL on failure.
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  * drm_property_create_signed_range - create a new signed ranged property type
0287  * @dev: drm device
0288  * @flags: flags specifying the property type
0289  * @name: name of the property
0290  * @min: minimum value of the property
0291  * @max: maximum value of the property
0292  *
0293  * This creates a new generic drm property which can then be attached to a drm
0294  * object with drm_object_attach_property(). The returned property object must
0295  * be freed with drm_property_destroy(), which is done automatically when
0296  * calling drm_mode_config_cleanup().
0297  *
0298  * Userspace is allowed to set any signed integer value in the (min, max)
0299  * range inclusive.
0300  *
0301  * Returns:
0302  * A pointer to the newly created property on success, NULL on failure.
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  * drm_property_create_object - create a new object property type
0315  * @dev: drm device
0316  * @flags: flags specifying the property type
0317  * @name: name of the property
0318  * @type: object type from DRM_MODE_OBJECT_* defines
0319  *
0320  * This creates a new generic drm property which can then be attached to a drm
0321  * object with drm_object_attach_property(). The returned property object must
0322  * be freed with drm_property_destroy(), which is done automatically when
0323  * calling drm_mode_config_cleanup().
0324  *
0325  * Userspace is only allowed to set this to any property value of the given
0326  * @type. Only useful for atomic properties, which is enforced.
0327  *
0328  * Returns:
0329  * A pointer to the newly created property on success, NULL on failure.
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  * drm_property_create_bool - create a new boolean property type
0354  * @dev: drm device
0355  * @flags: flags specifying the property type
0356  * @name: name of the property
0357  *
0358  * This creates a new generic drm property which can then be attached to a drm
0359  * object with drm_object_attach_property(). The returned property object must
0360  * be freed with drm_property_destroy(), which is done automatically when
0361  * calling drm_mode_config_cleanup().
0362  *
0363  * This is implemented as a ranged property with only {0, 1} as valid values.
0364  *
0365  * Returns:
0366  * A pointer to the newly created property on success, NULL on failure.
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  * drm_property_add_enum - add a possible value to an enumeration property
0377  * @property: enumeration property to change
0378  * @value: value of the new enumeration
0379  * @name: symbolic name of the new enumeration
0380  *
0381  * This functions adds enumerations to a property.
0382  *
0383  * It's use is deprecated, drivers should use one of the more specific helpers
0384  * to directly create the property with all enumerations already attached.
0385  *
0386  * Returns:
0387  * Zero on success, error code on failure.
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      * Bitmask enum properties have the additional constraint of values
0404      * from 0 to 63
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  * drm_property_destroy - destroy a drm property
0434  * @dev: drm device
0435  * @property: property to destroy
0436  *
0437  * This function frees a property including any attached resources like
0438  * enumeration values.
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      * NOTE: The idea seems to have been to use this to read all the blob
0514      * property values. But nothing ever added them to the corresponding
0515      * list, userspace always used the special-purpose get_blob ioctl to
0516      * read the value for a blob property. It also doesn't make a lot of
0517      * sense to return values here when everything else is just metadata for
0518      * the property itself.
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  * drm_property_create_blob - Create new blob property
0542  * @dev: DRM device to create property for
0543  * @length: Length to allocate for blob data
0544  * @data: If specified, copies data into blob
0545  *
0546  * Creates a new blob property for a specified DRM device, optionally
0547  * copying data. Note that blob properties are meant to be invariant, hence the
0548  * data must be filled out before the blob is used as the value of any property.
0549  *
0550  * Returns:
0551  * New blob property with a single reference on success, or an ERR_PTR
0552  * value on failure.
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     /* This must be explicitly initialised, so we can safely call list_del
0569      * on it in the removal handler, even if it isn't in a file list. */
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  * drm_property_blob_put - release a blob property reference
0596  * @blob: DRM blob property
0597  *
0598  * Releases a reference to a blob property. May free the object.
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      * When the file gets released that means no one else can access the
0616      * blob list any more, so no need to grab dev->blob_lock.
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  * drm_property_blob_get - acquire blob property reference
0626  * @blob: DRM blob property
0627  *
0628  * Acquires a reference to an existing blob property. Returns @blob, which
0629  * allows this to be used as a shorthand in assignments.
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  * drm_property_lookup_blob - look up a blob property and take a reference
0640  * @dev: drm device
0641  * @id: id of the blob property
0642  *
0643  * If successful, this takes an additional reference to the blob property.
0644  * callers need to make sure to eventually unreferenced the returned property
0645  * again, using drm_property_blob_put().
0646  *
0647  * Return:
0648  * NULL on failure, pointer to the blob on success.
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  * drm_property_replace_global_blob - replace existing blob property
0665  * @dev: drm device
0666  * @replace: location of blob property pointer to be replaced
0667  * @length: length of data for new blob, or 0 for no data
0668  * @data: content for new blob, or NULL for no data
0669  * @obj_holds_id: optional object for property holding blob ID
0670  * @prop_holds_id: optional property holding blob ID
0671  * @return 0 on success or error on failure
0672  *
0673  * This function will replace a global property in the blob list, optionally
0674  * updating a property which holds the ID of that property.
0675  *
0676  * If length is 0 or data is NULL, no new blob will be created, and the holding
0677  * property, if specified, will be set to 0.
0678  *
0679  * Access to the replace pointer is assumed to be protected by the caller, e.g.
0680  * by holding the relevant modesetting object lock for its parent.
0681  *
0682  * For example, a drm_connector has a 'PATH' property, which contains the ID
0683  * of a blob property with the value of the MST path information. Calling this
0684  * function with replace pointing to the connector's path_blob_ptr, length and
0685  * data set for the new path information, obj_holds_id set to the connector's
0686  * base object, and prop_holds_id set to the path property name, will perform
0687  * a completely atomic update. The access to path_blob_ptr is protected by the
0688  * caller holding a lock on the connector.
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  * drm_property_replace_blob - replace a blob property
0733  * @blob: a pointer to the member blob to be replaced
0734  * @new_blob: the new blob to replace with
0735  *
0736  * Return: true if the blob was in fact replaced.
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     /* Dropping the lock between create_blob and our access here is safe
0805      * as only the same file_priv can remove the blob; at this point, it is
0806      * not associated with any file_priv. */
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     /* Ensure the property was actually created by this user. */
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     /* We must drop head_file here, because we may not be the last
0849      * reference on the blob. */
0850     list_del_init(&blob->head_file);
0851     mutex_unlock(&dev->mode_config.blob_lock);
0852 
0853     /* One reference from lookup, and one from the filp. */
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 /* Some properties could refer to dynamic refcnt'd objects, or things that
0867  * need special locking to handle lifetime issues (ie. to ensure the prop
0868  * value doesn't become invalid part way through the property update due to
0869  * race).  The value returned by reference via 'obj' should be passed back
0870  * to drm_property_change_valid_put() after the property is set (and the
0871  * object to which the property is attached has a chance to take its own
0872  * reference).
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         /* a zero value for an object property translates to null: */
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 }