LCOV - code coverage report
Current view: top level - drivers/gpu/drm - drm_property.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 316 0.0 %
Date: 2022-03-28 16:04:14 Functions: 0 23 0.0 %
Branches: 0 254 0.0 %

           Branch data     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                 :            :  * instatiated 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                 :          0 : static bool drm_property_flags_valid(u32 flags)
      59                 :            : {
      60                 :          0 :         u32 legacy_type = flags & DRM_MODE_PROP_LEGACY_TYPE;
      61                 :          0 :         u32 ext_type = flags & DRM_MODE_PROP_EXTENDED_TYPE;
      62                 :            : 
      63                 :            :         /* Reject undefined/deprecated flags */
      64                 :          0 :         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         [ #  # ]:          0 :         if (!legacy_type == !ext_type)
      72                 :            :                 return false;
      73                 :            : 
      74                 :            :         /* Only one legacy type at a time please */
      75   [ #  #  #  #  :          0 :         if (legacy_type && !is_power_of_2(legacy_type))
                   #  # ]
      76                 :          0 :                 return false;
      77                 :            : 
      78                 :            :         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                 :          0 : struct drm_property *drm_property_create(struct drm_device *dev,
      97                 :            :                                          u32 flags, const char *name,
      98                 :            :                                          int num_values)
      99                 :            : {
     100                 :          0 :         struct drm_property *property = NULL;
     101                 :          0 :         int ret;
     102                 :            : 
     103   [ #  #  #  #  :          0 :         if (WARN_ON(!drm_property_flags_valid(flags)))
                   #  # ]
     104                 :            :                 return NULL;
     105                 :            : 
     106   [ #  #  #  # ]:          0 :         if (WARN_ON(strlen(name) >= DRM_PROP_NAME_LEN))
     107                 :            :                 return NULL;
     108                 :            : 
     109                 :          0 :         property = kzalloc(sizeof(struct drm_property), GFP_KERNEL);
     110         [ #  # ]:          0 :         if (!property)
     111                 :            :                 return NULL;
     112                 :            : 
     113                 :          0 :         property->dev = dev;
     114                 :            : 
     115         [ #  # ]:          0 :         if (num_values) {
     116                 :          0 :                 property->values = kcalloc(num_values, sizeof(uint64_t),
     117                 :            :                                            GFP_KERNEL);
     118         [ #  # ]:          0 :                 if (!property->values)
     119                 :          0 :                         goto fail;
     120                 :            :         }
     121                 :            : 
     122                 :          0 :         ret = drm_mode_object_add(dev, &property->base, DRM_MODE_OBJECT_PROPERTY);
     123         [ #  # ]:          0 :         if (ret)
     124                 :          0 :                 goto fail;
     125                 :            : 
     126                 :          0 :         property->flags = flags;
     127                 :          0 :         property->num_values = num_values;
     128                 :          0 :         INIT_LIST_HEAD(&property->enum_list);
     129                 :            : 
     130                 :          0 :         strncpy(property->name, name, DRM_PROP_NAME_LEN);
     131                 :          0 :         property->name[DRM_PROP_NAME_LEN-1] = '\0';
     132                 :            : 
     133                 :          0 :         list_add_tail(&property->head, &dev->mode_config.property_list);
     134                 :            : 
     135                 :          0 :         return property;
     136                 :          0 : fail:
     137                 :          0 :         kfree(property->values);
     138                 :          0 :         kfree(property);
     139                 :          0 :         return NULL;
     140                 :            : }
     141                 :            : EXPORT_SYMBOL(drm_property_create);
     142                 :            : 
     143                 :            : /**
     144                 :            :  * drm_property_create_enum - create a new enumeration property type
     145                 :            :  * @dev: drm device
     146                 :            :  * @flags: flags specifying the property type
     147                 :            :  * @name: name of the property
     148                 :            :  * @props: enumeration lists with property values
     149                 :            :  * @num_values: number of pre-defined values
     150                 :            :  *
     151                 :            :  * This creates a new generic drm property which can then be attached to a drm
     152                 :            :  * object with drm_object_attach_property(). The returned property object must
     153                 :            :  * be freed with drm_property_destroy(), which is done automatically when
     154                 :            :  * calling drm_mode_config_cleanup().
     155                 :            :  *
     156                 :            :  * Userspace is only allowed to set one of the predefined values for enumeration
     157                 :            :  * properties.
     158                 :            :  *
     159                 :            :  * Returns:
     160                 :            :  * A pointer to the newly created property on success, NULL on failure.
     161                 :            :  */
     162                 :          0 : 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                 :          0 :         struct drm_property *property;
     168                 :          0 :         int i, ret;
     169                 :            : 
     170                 :          0 :         flags |= DRM_MODE_PROP_ENUM;
     171                 :            : 
     172                 :          0 :         property = drm_property_create(dev, flags, name, num_values);
     173         [ #  # ]:          0 :         if (!property)
     174                 :            :                 return NULL;
     175                 :            : 
     176         [ #  # ]:          0 :         for (i = 0; i < num_values; i++) {
     177                 :          0 :                 ret = drm_property_add_enum(property,
     178                 :          0 :                                             props[i].type,
     179                 :          0 :                                             props[i].name);
     180         [ #  # ]:          0 :                 if (ret) {
     181                 :          0 :                         drm_property_destroy(dev, property);
     182                 :          0 :                         return NULL;
     183                 :            :                 }
     184                 :            :         }
     185                 :            : 
     186                 :            :         return property;
     187                 :            : }
     188                 :            : EXPORT_SYMBOL(drm_property_create_enum);
     189                 :            : 
     190                 :            : /**
     191                 :            :  * drm_property_create_bitmask - create a new bitmask property type
     192                 :            :  * @dev: drm device
     193                 :            :  * @flags: flags specifying the property type
     194                 :            :  * @name: name of the property
     195                 :            :  * @props: enumeration lists with property bitflags
     196                 :            :  * @num_props: size of the @props array
     197                 :            :  * @supported_bits: bitmask of all supported enumeration values
     198                 :            :  *
     199                 :            :  * This creates a new bitmask drm property which can then be attached to a drm
     200                 :            :  * object with drm_object_attach_property(). The returned property object must
     201                 :            :  * be freed with drm_property_destroy(), which is done automatically when
     202                 :            :  * calling drm_mode_config_cleanup().
     203                 :            :  *
     204                 :            :  * Compared to plain enumeration properties userspace is allowed to set any
     205                 :            :  * or'ed together combination of the predefined property bitflag values
     206                 :            :  *
     207                 :            :  * Returns:
     208                 :            :  * A pointer to the newly created property on success, NULL on failure.
     209                 :            :  */
     210                 :          0 : 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                 :          0 :         struct drm_property *property;
     217                 :          0 :         int i, ret;
     218         [ #  # ]:          0 :         int num_values = hweight64(supported_bits);
     219                 :            : 
     220                 :          0 :         flags |= DRM_MODE_PROP_BITMASK;
     221                 :            : 
     222                 :          0 :         property = drm_property_create(dev, flags, name, num_values);
     223         [ #  # ]:          0 :         if (!property)
     224                 :            :                 return NULL;
     225         [ #  # ]:          0 :         for (i = 0; i < num_props; i++) {
     226         [ #  # ]:          0 :                 if (!(supported_bits & (1ULL << props[i].type)))
     227                 :          0 :                         continue;
     228                 :            : 
     229                 :          0 :                 ret = drm_property_add_enum(property,
     230                 :            :                                             props[i].type,
     231                 :            :                                             props[i].name);
     232         [ #  # ]:          0 :                 if (ret) {
     233                 :          0 :                         drm_property_destroy(dev, property);
     234                 :          0 :                         return NULL;
     235                 :            :                 }
     236                 :            :         }
     237                 :            : 
     238                 :            :         return property;
     239                 :            : }
     240                 :            : EXPORT_SYMBOL(drm_property_create_bitmask);
     241                 :            : 
     242                 :          0 : 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                 :          0 :         struct drm_property *property;
     247                 :            : 
     248                 :          0 :         property = drm_property_create(dev, flags, name, 2);
     249   [ #  #  #  #  :          0 :         if (!property)
                   #  # ]
     250                 :            :                 return NULL;
     251                 :            : 
     252                 :          0 :         property->values[0] = min;
     253                 :          0 :         property->values[1] = max;
     254                 :            : 
     255                 :          0 :         return property;
     256                 :            : }
     257                 :            : 
     258                 :            : /**
     259                 :            :  * drm_property_create_range - create a new unsigned ranged property type
     260                 :            :  * @dev: drm device
     261                 :            :  * @flags: flags specifying the property type
     262                 :            :  * @name: name of the property
     263                 :            :  * @min: minimum value of the property
     264                 :            :  * @max: maximum value of the property
     265                 :            :  *
     266                 :            :  * This creates a new generic drm property which can then be attached to a drm
     267                 :            :  * object with drm_object_attach_property(). The returned property object must
     268                 :            :  * be freed with drm_property_destroy(), which is done automatically when
     269                 :            :  * calling drm_mode_config_cleanup().
     270                 :            :  *
     271                 :            :  * Userspace is allowed to set any unsigned integer value in the (min, max)
     272                 :            :  * range inclusive.
     273                 :            :  *
     274                 :            :  * Returns:
     275                 :            :  * A pointer to the newly created property on success, NULL on failure.
     276                 :            :  */
     277                 :          0 : 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                 :          0 :         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                 :            :  * drm_property_create_signed_range - create a new signed ranged property type
     288                 :            :  * @dev: drm device
     289                 :            :  * @flags: flags specifying the property type
     290                 :            :  * @name: name of the property
     291                 :            :  * @min: minimum value of the property
     292                 :            :  * @max: maximum value of the property
     293                 :            :  *
     294                 :            :  * This creates a new generic drm property which can then be attached to a drm
     295                 :            :  * object with drm_object_attach_property(). The returned property object must
     296                 :            :  * be freed with drm_property_destroy(), which is done automatically when
     297                 :            :  * calling drm_mode_config_cleanup().
     298                 :            :  *
     299                 :            :  * Userspace is allowed to set any signed integer value in the (min, max)
     300                 :            :  * range inclusive.
     301                 :            :  *
     302                 :            :  * Returns:
     303                 :            :  * A pointer to the newly created property on success, NULL on failure.
     304                 :            :  */
     305                 :          0 : 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                 :          0 :         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                 :            :  * drm_property_create_object - create a new object property type
     316                 :            :  * @dev: drm device
     317                 :            :  * @flags: flags specifying the property type
     318                 :            :  * @name: name of the property
     319                 :            :  * @type: object type from DRM_MODE_OBJECT_* defines
     320                 :            :  *
     321                 :            :  * This creates a new generic drm property which can then be attached to a drm
     322                 :            :  * object with drm_object_attach_property(). The returned property object must
     323                 :            :  * be freed with drm_property_destroy(), which is done automatically when
     324                 :            :  * calling drm_mode_config_cleanup().
     325                 :            :  *
     326                 :            :  * Userspace is only allowed to set this to any property value of the given
     327                 :            :  * @type. Only useful for atomic properties, which is enforced.
     328                 :            :  *
     329                 :            :  * Returns:
     330                 :            :  * A pointer to the newly created property on success, NULL on failure.
     331                 :            :  */
     332                 :          0 : struct drm_property *drm_property_create_object(struct drm_device *dev,
     333                 :            :                                                 u32 flags, const char *name,
     334                 :            :                                                 uint32_t type)
     335                 :            : {
     336                 :          0 :         struct drm_property *property;
     337                 :            : 
     338                 :          0 :         flags |= DRM_MODE_PROP_OBJECT;
     339                 :            : 
     340   [ #  #  #  # ]:          0 :         if (WARN_ON(!(flags & DRM_MODE_PROP_ATOMIC)))
     341                 :            :                 return NULL;
     342                 :            : 
     343                 :          0 :         property = drm_property_create(dev, flags, name, 1);
     344         [ #  # ]:          0 :         if (!property)
     345                 :            :                 return NULL;
     346                 :            : 
     347                 :          0 :         property->values[0] = type;
     348                 :            : 
     349                 :          0 :         return property;
     350                 :            : }
     351                 :            : EXPORT_SYMBOL(drm_property_create_object);
     352                 :            : 
     353                 :            : /**
     354                 :            :  * drm_property_create_bool - create a new boolean property type
     355                 :            :  * @dev: drm device
     356                 :            :  * @flags: flags specifying the property type
     357                 :            :  * @name: name of the property
     358                 :            :  *
     359                 :            :  * This creates a new generic drm property which can then be attached to a drm
     360                 :            :  * object with drm_object_attach_property(). The returned property object must
     361                 :            :  * be freed with drm_property_destroy(), which is done automatically when
     362                 :            :  * calling drm_mode_config_cleanup().
     363                 :            :  *
     364                 :            :  * This is implemented as a ranged property with only {0, 1} as valid values.
     365                 :            :  *
     366                 :            :  * Returns:
     367                 :            :  * A pointer to the newly created property on success, NULL on failure.
     368                 :            :  */
     369                 :          0 : struct drm_property *drm_property_create_bool(struct drm_device *dev,
     370                 :            :                                               u32 flags, const char *name)
     371                 :            : {
     372                 :          0 :         return drm_property_create_range(dev, flags, name, 0, 1);
     373                 :            : }
     374                 :            : EXPORT_SYMBOL(drm_property_create_bool);
     375                 :            : 
     376                 :            : /**
     377                 :            :  * drm_property_add_enum - add a possible value to an enumeration property
     378                 :            :  * @property: enumeration property to change
     379                 :            :  * @value: value of the new enumeration
     380                 :            :  * @name: symbolic name of the new enumeration
     381                 :            :  *
     382                 :            :  * This functions adds enumerations to a property.
     383                 :            :  *
     384                 :            :  * It's use is deprecated, drivers should use one of the more specific helpers
     385                 :            :  * to directly create the property with all enumerations already attached.
     386                 :            :  *
     387                 :            :  * Returns:
     388                 :            :  * Zero on success, error code on failure.
     389                 :            :  */
     390                 :          0 : int drm_property_add_enum(struct drm_property *property,
     391                 :            :                           uint64_t value, const char *name)
     392                 :            : {
     393                 :          0 :         struct drm_property_enum *prop_enum;
     394                 :          0 :         int index = 0;
     395                 :            : 
     396   [ #  #  #  # ]:          0 :         if (WARN_ON(strlen(name) >= DRM_PROP_NAME_LEN))
     397                 :            :                 return -EINVAL;
     398                 :            : 
     399   [ #  #  #  #  :          0 :         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                 :            :          * Bitmask enum properties have the additional constraint of values
     405                 :            :          * from 0 to 63
     406                 :            :          */
     407   [ #  #  #  #  :          0 :         if (WARN_ON(drm_property_type_is(property, DRM_MODE_PROP_BITMASK) &&
          #  #  #  #  #  
                      # ]
     408                 :            :                     value > 63))
     409                 :            :                 return -EINVAL;
     410                 :            : 
     411         [ #  # ]:          0 :         list_for_each_entry(prop_enum, &property->enum_list, head) {
     412   [ #  #  #  # ]:          0 :                 if (WARN_ON(prop_enum->value == value))
     413                 :            :                         return -EINVAL;
     414                 :          0 :                 index++;
     415                 :            :         }
     416                 :            : 
     417   [ #  #  #  # ]:          0 :         if (WARN_ON(index >= property->num_values))
     418                 :            :                 return -EINVAL;
     419                 :            : 
     420                 :          0 :         prop_enum = kzalloc(sizeof(struct drm_property_enum), GFP_KERNEL);
     421         [ #  # ]:          0 :         if (!prop_enum)
     422                 :            :                 return -ENOMEM;
     423                 :            : 
     424                 :          0 :         strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN);
     425                 :          0 :         prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0';
     426                 :          0 :         prop_enum->value = value;
     427                 :            : 
     428                 :          0 :         property->values[index] = value;
     429                 :          0 :         list_add_tail(&prop_enum->head, &property->enum_list);
     430                 :          0 :         return 0;
     431                 :            : }
     432                 :            : EXPORT_SYMBOL(drm_property_add_enum);
     433                 :            : 
     434                 :            : /**
     435                 :            :  * drm_property_destroy - destroy a drm property
     436                 :            :  * @dev: drm device
     437                 :            :  * @property: property to destry
     438                 :            :  *
     439                 :            :  * This function frees a property including any attached resources like
     440                 :            :  * enumeration values.
     441                 :            :  */
     442                 :          0 : void drm_property_destroy(struct drm_device *dev, struct drm_property *property)
     443                 :            : {
     444                 :          0 :         struct drm_property_enum *prop_enum, *pt;
     445                 :            : 
     446         [ #  # ]:          0 :         list_for_each_entry_safe(prop_enum, pt, &property->enum_list, head) {
     447                 :          0 :                 list_del(&prop_enum->head);
     448                 :          0 :                 kfree(prop_enum);
     449                 :            :         }
     450                 :            : 
     451         [ #  # ]:          0 :         if (property->num_values)
     452                 :          0 :                 kfree(property->values);
     453                 :          0 :         drm_mode_object_unregister(dev, &property->base);
     454                 :          0 :         list_del(&property->head);
     455                 :          0 :         kfree(property);
     456                 :          0 : }
     457                 :            : EXPORT_SYMBOL(drm_property_destroy);
     458                 :            : 
     459                 :          0 : int drm_mode_getproperty_ioctl(struct drm_device *dev,
     460                 :            :                                void *data, struct drm_file *file_priv)
     461                 :            : {
     462                 :          0 :         struct drm_mode_get_property *out_resp = data;
     463                 :          0 :         struct drm_property *property;
     464                 :          0 :         int enum_count = 0;
     465                 :          0 :         int value_count = 0;
     466                 :          0 :         int i, copied;
     467                 :          0 :         struct drm_property_enum *prop_enum;
     468                 :          0 :         struct drm_mode_property_enum __user *enum_ptr;
     469                 :          0 :         uint64_t __user *values_ptr;
     470                 :            : 
     471         [ #  # ]:          0 :         if (!drm_core_check_feature(dev, DRIVER_MODESET))
     472                 :            :                 return -EOPNOTSUPP;
     473                 :            : 
     474                 :          0 :         property = drm_property_find(dev, file_priv, out_resp->prop_id);
     475         [ #  # ]:          0 :         if (!property)
     476                 :            :                 return -ENOENT;
     477                 :            : 
     478                 :          0 :         strncpy(out_resp->name, property->name, DRM_PROP_NAME_LEN);
     479                 :          0 :         out_resp->name[DRM_PROP_NAME_LEN-1] = 0;
     480                 :          0 :         out_resp->flags = property->flags;
     481                 :            : 
     482                 :          0 :         value_count = property->num_values;
     483                 :          0 :         values_ptr = u64_to_user_ptr(out_resp->values_ptr);
     484                 :            : 
     485         [ #  # ]:          0 :         for (i = 0; i < value_count; i++) {
     486         [ #  # ]:          0 :                 if (i < out_resp->count_values &&
     487         [ #  # ]:          0 :                     put_user(property->values[i], values_ptr + i)) {
     488                 :            :                         return -EFAULT;
     489                 :            :                 }
     490                 :            :         }
     491                 :          0 :         out_resp->count_values = value_count;
     492                 :            : 
     493                 :          0 :         copied = 0;
     494                 :          0 :         enum_ptr = u64_to_user_ptr(out_resp->enum_blob_ptr);
     495                 :            : 
     496   [ #  #  #  #  :          0 :         if (drm_property_type_is(property, DRM_MODE_PROP_ENUM) ||
                   #  # ]
     497                 :            :             drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
     498         [ #  # ]:          0 :                 list_for_each_entry(prop_enum, &property->enum_list, head) {
     499                 :          0 :                         enum_count++;
     500         [ #  # ]:          0 :                         if (out_resp->count_enum_blobs < enum_count)
     501                 :          0 :                                 continue;
     502                 :            : 
     503         [ #  # ]:          0 :                         if (copy_to_user(&enum_ptr[copied].value,
     504         [ #  # ]:          0 :                                          &prop_enum->value, sizeof(uint64_t)))
     505                 :          0 :                                 return -EFAULT;
     506                 :            : 
     507         [ #  # ]:          0 :                         if (copy_to_user(&enum_ptr[copied].name,
     508         [ #  # ]:          0 :                                          &prop_enum->name, DRM_PROP_NAME_LEN))
     509                 :          0 :                                 return -EFAULT;
     510                 :          0 :                         copied++;
     511                 :            :                 }
     512                 :          0 :                 out_resp->count_enum_blobs = enum_count;
     513                 :            :         }
     514                 :            : 
     515                 :            :         /*
     516                 :            :          * NOTE: The idea seems to have been to use this to read all the blob
     517                 :            :          * property values. But nothing ever added them to the corresponding
     518                 :            :          * list, userspace always used the special-purpose get_blob ioctl to
     519                 :            :          * read the value for a blob property. It also doesn't make a lot of
     520                 :            :          * sense to return values here when everything else is just metadata for
     521                 :            :          * the property itself.
     522                 :            :          */
     523   [ #  #  #  # ]:          0 :         if (drm_property_type_is(property, DRM_MODE_PROP_BLOB))
     524                 :          0 :                 out_resp->count_enum_blobs = 0;
     525                 :            : 
     526                 :            :         return 0;
     527                 :            : }
     528                 :            : 
     529                 :          0 : static void drm_property_free_blob(struct kref *kref)
     530                 :            : {
     531                 :          0 :         struct drm_property_blob *blob =
     532                 :          0 :                 container_of(kref, struct drm_property_blob, base.refcount);
     533                 :            : 
     534                 :          0 :         mutex_lock(&blob->dev->mode_config.blob_lock);
     535                 :          0 :         list_del(&blob->head_global);
     536                 :          0 :         mutex_unlock(&blob->dev->mode_config.blob_lock);
     537                 :            : 
     538                 :          0 :         drm_mode_object_unregister(blob->dev, &blob->base);
     539                 :            : 
     540                 :          0 :         kvfree(blob);
     541                 :          0 : }
     542                 :            : 
     543                 :            : /**
     544                 :            :  * drm_property_create_blob - Create new blob property
     545                 :            :  * @dev: DRM device to create property for
     546                 :            :  * @length: Length to allocate for blob data
     547                 :            :  * @data: If specified, copies data into blob
     548                 :            :  *
     549                 :            :  * Creates a new blob property for a specified DRM device, optionally
     550                 :            :  * copying data. Note that blob properties are meant to be invariant, hence the
     551                 :            :  * data must be filled out before the blob is used as the value of any property.
     552                 :            :  *
     553                 :            :  * Returns:
     554                 :            :  * New blob property with a single reference on success, or an ERR_PTR
     555                 :            :  * value on failure.
     556                 :            :  */
     557                 :            : struct drm_property_blob *
     558                 :          0 : drm_property_create_blob(struct drm_device *dev, size_t length,
     559                 :            :                          const void *data)
     560                 :            : {
     561                 :          0 :         struct drm_property_blob *blob;
     562                 :          0 :         int ret;
     563                 :            : 
     564         [ #  # ]:          0 :         if (!length || length > INT_MAX - sizeof(struct drm_property_blob))
     565                 :            :                 return ERR_PTR(-EINVAL);
     566                 :            : 
     567                 :          0 :         blob = kvzalloc(sizeof(struct drm_property_blob)+length, GFP_KERNEL);
     568         [ #  # ]:          0 :         if (!blob)
     569                 :            :                 return ERR_PTR(-ENOMEM);
     570                 :            : 
     571                 :            :         /* This must be explicitly initialised, so we can safely call list_del
     572                 :            :          * on it in the removal handler, even if it isn't in a file list. */
     573         [ #  # ]:          0 :         INIT_LIST_HEAD(&blob->head_file);
     574                 :          0 :         blob->data = (void *)blob + sizeof(*blob);
     575                 :          0 :         blob->length = length;
     576                 :          0 :         blob->dev = dev;
     577                 :            : 
     578         [ #  # ]:          0 :         if (data)
     579                 :          0 :                 memcpy(blob->data, data, length);
     580                 :            : 
     581                 :          0 :         ret = __drm_mode_object_add(dev, &blob->base, DRM_MODE_OBJECT_BLOB,
     582                 :            :                                     true, drm_property_free_blob);
     583         [ #  # ]:          0 :         if (ret) {
     584                 :          0 :                 kvfree(blob);
     585                 :          0 :                 return ERR_PTR(-EINVAL);
     586                 :            :         }
     587                 :            : 
     588                 :          0 :         mutex_lock(&dev->mode_config.blob_lock);
     589                 :          0 :         list_add_tail(&blob->head_global,
     590                 :            :                       &dev->mode_config.property_blob_list);
     591                 :          0 :         mutex_unlock(&dev->mode_config.blob_lock);
     592                 :            : 
     593                 :          0 :         return blob;
     594                 :            : }
     595                 :            : EXPORT_SYMBOL(drm_property_create_blob);
     596                 :            : 
     597                 :            : /**
     598                 :            :  * drm_property_blob_put - release a blob property reference
     599                 :            :  * @blob: DRM blob property
     600                 :            :  *
     601                 :            :  * Releases a reference to a blob property. May free the object.
     602                 :            :  */
     603                 :          0 : void drm_property_blob_put(struct drm_property_blob *blob)
     604                 :            : {
     605         [ #  # ]:          0 :         if (!blob)
     606                 :            :                 return;
     607                 :            : 
     608                 :          0 :         drm_mode_object_put(&blob->base);
     609                 :            : }
     610                 :            : EXPORT_SYMBOL(drm_property_blob_put);
     611                 :            : 
     612                 :          0 : void drm_property_destroy_user_blobs(struct drm_device *dev,
     613                 :            :                                      struct drm_file *file_priv)
     614                 :            : {
     615                 :          0 :         struct drm_property_blob *blob, *bt;
     616                 :            : 
     617                 :            :         /*
     618                 :            :          * When the file gets released that means no one else can access the
     619                 :            :          * blob list any more, so no need to grab dev->blob_lock.
     620                 :            :          */
     621         [ #  # ]:          0 :         list_for_each_entry_safe(blob, bt, &file_priv->blobs, head_file) {
     622         [ #  # ]:          0 :                 list_del_init(&blob->head_file);
     623         [ #  # ]:          0 :                 drm_property_blob_put(blob);
     624                 :            :         }
     625                 :          0 : }
     626                 :            : 
     627                 :            : /**
     628                 :            :  * drm_property_blob_get - acquire blob property reference
     629                 :            :  * @blob: DRM blob property
     630                 :            :  *
     631                 :            :  * Acquires a reference to an existing blob property. Returns @blob, which
     632                 :            :  * allows this to be used as a shorthand in assignments.
     633                 :            :  */
     634                 :          0 : struct drm_property_blob *drm_property_blob_get(struct drm_property_blob *blob)
     635                 :            : {
     636                 :          0 :         drm_mode_object_get(&blob->base);
     637                 :          0 :         return blob;
     638                 :            : }
     639                 :            : EXPORT_SYMBOL(drm_property_blob_get);
     640                 :            : 
     641                 :            : /**
     642                 :            :  * drm_property_lookup_blob - look up a blob property and take a reference
     643                 :            :  * @dev: drm device
     644                 :            :  * @id: id of the blob property
     645                 :            :  *
     646                 :            :  * If successful, this takes an additional reference to the blob property.
     647                 :            :  * callers need to make sure to eventually unreference the returned property
     648                 :            :  * again, using drm_property_blob_put().
     649                 :            :  *
     650                 :            :  * Return:
     651                 :            :  * NULL on failure, pointer to the blob on success.
     652                 :            :  */
     653                 :          0 : struct drm_property_blob *drm_property_lookup_blob(struct drm_device *dev,
     654                 :            :                                                    uint32_t id)
     655                 :            : {
     656                 :          0 :         struct drm_mode_object *obj;
     657                 :          0 :         struct drm_property_blob *blob = NULL;
     658                 :            : 
     659                 :          0 :         obj = __drm_mode_object_find(dev, NULL, id, DRM_MODE_OBJECT_BLOB);
     660   [ #  #  #  #  :          0 :         if (obj)
             #  #  #  # ]
     661                 :          0 :                 blob = obj_to_blob(obj);
     662                 :          0 :         return blob;
     663                 :            : }
     664                 :            : EXPORT_SYMBOL(drm_property_lookup_blob);
     665                 :            : 
     666                 :            : /**
     667                 :            :  * drm_property_replace_global_blob - replace existing blob property
     668                 :            :  * @dev: drm device
     669                 :            :  * @replace: location of blob property pointer to be replaced
     670                 :            :  * @length: length of data for new blob, or 0 for no data
     671                 :            :  * @data: content for new blob, or NULL for no data
     672                 :            :  * @obj_holds_id: optional object for property holding blob ID
     673                 :            :  * @prop_holds_id: optional property holding blob ID
     674                 :            :  * @return 0 on success or error on failure
     675                 :            :  *
     676                 :            :  * This function will replace a global property in the blob list, optionally
     677                 :            :  * updating a property which holds the ID of that property.
     678                 :            :  *
     679                 :            :  * If length is 0 or data is NULL, no new blob will be created, and the holding
     680                 :            :  * property, if specified, will be set to 0.
     681                 :            :  *
     682                 :            :  * Access to the replace pointer is assumed to be protected by the caller, e.g.
     683                 :            :  * by holding the relevant modesetting object lock for its parent.
     684                 :            :  *
     685                 :            :  * For example, a drm_connector has a 'PATH' property, which contains the ID
     686                 :            :  * of a blob property with the value of the MST path information. Calling this
     687                 :            :  * function with replace pointing to the connector's path_blob_ptr, length and
     688                 :            :  * data set for the new path information, obj_holds_id set to the connector's
     689                 :            :  * base object, and prop_holds_id set to the path property name, will perform
     690                 :            :  * a completely atomic update. The access to path_blob_ptr is protected by the
     691                 :            :  * caller holding a lock on the connector.
     692                 :            :  */
     693                 :          0 : 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                 :          0 :         struct drm_property_blob *new_blob = NULL;
     701                 :          0 :         struct drm_property_blob *old_blob = NULL;
     702                 :          0 :         int ret;
     703                 :            : 
     704         [ #  # ]:          0 :         WARN_ON(replace == NULL);
     705                 :            : 
     706                 :          0 :         old_blob = *replace;
     707                 :            : 
     708         [ #  # ]:          0 :         if (length && data) {
     709                 :          0 :                 new_blob = drm_property_create_blob(dev, length, data);
     710         [ #  # ]:          0 :                 if (IS_ERR(new_blob))
     711                 :          0 :                         return PTR_ERR(new_blob);
     712                 :            :         }
     713                 :            : 
     714         [ #  # ]:          0 :         if (obj_holds_id) {
     715         [ #  # ]:          0 :                 ret = drm_object_property_set_value(obj_holds_id,
     716                 :            :                                                     prop_holds_id,
     717                 :            :                                                     new_blob ?
     718                 :          0 :                                                         new_blob->base.id : 0);
     719         [ #  # ]:          0 :                 if (ret != 0)
     720                 :          0 :                         goto err_created;
     721                 :            :         }
     722                 :            : 
     723         [ #  # ]:          0 :         drm_property_blob_put(old_blob);
     724                 :          0 :         *replace = new_blob;
     725                 :            : 
     726                 :          0 :         return 0;
     727                 :            : 
     728                 :            : err_created:
     729         [ #  # ]:          0 :         drm_property_blob_put(new_blob);
     730                 :            :         return ret;
     731                 :            : }
     732                 :            : EXPORT_SYMBOL(drm_property_replace_global_blob);
     733                 :            : 
     734                 :            : /**
     735                 :            :  * drm_property_replace_blob - replace a blob property
     736                 :            :  * @blob: a pointer to the member blob to be replaced
     737                 :            :  * @new_blob: the new blob to replace with
     738                 :            :  *
     739                 :            :  * Return: true if the blob was in fact replaced.
     740                 :            :  */
     741                 :          0 : bool drm_property_replace_blob(struct drm_property_blob **blob,
     742                 :            :                                struct drm_property_blob *new_blob)
     743                 :            : {
     744                 :          0 :         struct drm_property_blob *old_blob = *blob;
     745                 :            : 
     746         [ #  # ]:          0 :         if (old_blob == new_blob)
     747                 :            :                 return false;
     748                 :            : 
     749         [ #  # ]:          0 :         drm_property_blob_put(old_blob);
     750         [ #  # ]:          0 :         if (new_blob)
     751                 :          0 :                 drm_property_blob_get(new_blob);
     752                 :          0 :         *blob = new_blob;
     753                 :          0 :         return true;
     754                 :            : }
     755                 :            : EXPORT_SYMBOL(drm_property_replace_blob);
     756                 :            : 
     757                 :          0 : int drm_mode_getblob_ioctl(struct drm_device *dev,
     758                 :            :                            void *data, struct drm_file *file_priv)
     759                 :            : {
     760                 :          0 :         struct drm_mode_get_blob *out_resp = data;
     761                 :          0 :         struct drm_property_blob *blob;
     762                 :          0 :         int ret = 0;
     763                 :            : 
     764         [ #  # ]:          0 :         if (!drm_core_check_feature(dev, DRIVER_MODESET))
     765                 :            :                 return -EOPNOTSUPP;
     766                 :            : 
     767                 :          0 :         blob = drm_property_lookup_blob(dev, out_resp->blob_id);
     768                 :          0 :         if (!blob)
     769                 :            :                 return -ENOENT;
     770                 :            : 
     771         [ #  # ]:          0 :         if (out_resp->length == blob->length) {
     772         [ #  # ]:          0 :                 if (copy_to_user(u64_to_user_ptr(out_resp->data),
     773         [ #  # ]:          0 :                                  blob->data,
     774                 :            :                                  blob->length)) {
     775                 :          0 :                         ret = -EFAULT;
     776                 :          0 :                         goto unref;
     777                 :            :                 }
     778                 :            :         }
     779                 :          0 :         out_resp->length = blob->length;
     780                 :          0 : unref:
     781                 :          0 :         drm_property_blob_put(blob);
     782                 :            : 
     783                 :          0 :         return ret;
     784                 :            : }
     785                 :            : 
     786                 :          0 : int drm_mode_createblob_ioctl(struct drm_device *dev,
     787                 :            :                               void *data, struct drm_file *file_priv)
     788                 :            : {
     789                 :          0 :         struct drm_mode_create_blob *out_resp = data;
     790                 :          0 :         struct drm_property_blob *blob;
     791                 :          0 :         int ret = 0;
     792                 :            : 
     793         [ #  # ]:          0 :         if (!drm_core_check_feature(dev, DRIVER_MODESET))
     794                 :            :                 return -EOPNOTSUPP;
     795                 :            : 
     796                 :          0 :         blob = drm_property_create_blob(dev, out_resp->length, NULL);
     797         [ #  # ]:          0 :         if (IS_ERR(blob))
     798                 :          0 :                 return PTR_ERR(blob);
     799                 :            : 
     800         [ #  # ]:          0 :         if (copy_from_user(blob->data,
     801                 :          0 :                            u64_to_user_ptr(out_resp->data),
     802         [ #  # ]:          0 :                            out_resp->length)) {
     803                 :          0 :                 ret = -EFAULT;
     804                 :          0 :                 goto out_blob;
     805                 :            :         }
     806                 :            : 
     807                 :            :         /* Dropping the lock between create_blob and our access here is safe
     808                 :            :          * as only the same file_priv can remove the blob; at this point, it is
     809                 :            :          * not associated with any file_priv. */
     810                 :          0 :         mutex_lock(&dev->mode_config.blob_lock);
     811                 :          0 :         out_resp->blob_id = blob->base.id;
     812                 :          0 :         list_add_tail(&blob->head_file, &file_priv->blobs);
     813                 :          0 :         mutex_unlock(&dev->mode_config.blob_lock);
     814                 :            : 
     815                 :          0 :         return 0;
     816                 :            : 
     817                 :            : out_blob:
     818         [ #  # ]:          0 :         drm_property_blob_put(blob);
     819                 :            :         return ret;
     820                 :            : }
     821                 :            : 
     822                 :          0 : int drm_mode_destroyblob_ioctl(struct drm_device *dev,
     823                 :            :                                void *data, struct drm_file *file_priv)
     824                 :            : {
     825                 :          0 :         struct drm_mode_destroy_blob *out_resp = data;
     826                 :          0 :         struct drm_property_blob *blob = NULL, *bt;
     827                 :          0 :         bool found = false;
     828                 :          0 :         int ret = 0;
     829                 :            : 
     830         [ #  # ]:          0 :         if (!drm_core_check_feature(dev, DRIVER_MODESET))
     831                 :            :                 return -EOPNOTSUPP;
     832                 :            : 
     833                 :          0 :         blob = drm_property_lookup_blob(dev, out_resp->blob_id);
     834                 :          0 :         if (!blob)
     835                 :            :                 return -ENOENT;
     836                 :            : 
     837                 :          0 :         mutex_lock(&dev->mode_config.blob_lock);
     838                 :            :         /* Ensure the property was actually created by this user. */
     839         [ #  # ]:          0 :         list_for_each_entry(bt, &file_priv->blobs, head_file) {
     840         [ #  # ]:          0 :                 if (bt == blob) {
     841                 :            :                         found = true;
     842                 :            :                         break;
     843                 :            :                 }
     844                 :            :         }
     845                 :            : 
     846         [ #  # ]:          0 :         if (!found) {
     847                 :          0 :                 ret = -EPERM;
     848                 :          0 :                 goto err;
     849                 :            :         }
     850                 :            : 
     851                 :            :         /* We must drop head_file here, because we may not be the last
     852                 :            :          * reference on the blob. */
     853                 :          0 :         list_del_init(&blob->head_file);
     854                 :          0 :         mutex_unlock(&dev->mode_config.blob_lock);
     855                 :            : 
     856                 :            :         /* One reference from lookup, and one from the filp. */
     857                 :          0 :         drm_property_blob_put(blob);
     858                 :          0 :         drm_property_blob_put(blob);
     859                 :            : 
     860                 :          0 :         return 0;
     861                 :            : 
     862                 :            : err:
     863                 :          0 :         mutex_unlock(&dev->mode_config.blob_lock);
     864                 :          0 :         drm_property_blob_put(blob);
     865                 :            : 
     866                 :          0 :         return ret;
     867                 :            : }
     868                 :            : 
     869                 :            : /* Some properties could refer to dynamic refcnt'd objects, or things that
     870                 :            :  * need special locking to handle lifetime issues (ie. to ensure the prop
     871                 :            :  * value doesn't become invalid part way through the property update due to
     872                 :            :  * race).  The value returned by reference via 'obj' should be passed back
     873                 :            :  * to drm_property_change_valid_put() after the property is set (and the
     874                 :            :  * object to which the property is attached has a chance to take its own
     875                 :            :  * reference).
     876                 :            :  */
     877                 :          0 : bool drm_property_change_valid_get(struct drm_property *property,
     878                 :            :                                    uint64_t value, struct drm_mode_object **ref)
     879                 :            : {
     880                 :          0 :         int i;
     881                 :            : 
     882         [ #  # ]:          0 :         if (property->flags & DRM_MODE_PROP_IMMUTABLE)
     883                 :            :                 return false;
     884                 :            : 
     885                 :          0 :         *ref = NULL;
     886                 :            : 
     887   [ #  #  #  # ]:          0 :         if (drm_property_type_is(property, DRM_MODE_PROP_RANGE)) {
     888   [ #  #  #  # ]:          0 :                 if (value < property->values[0] || value > property->values[1])
     889                 :            :                         return false;
     890                 :          0 :                 return true;
     891   [ #  #  #  # ]:          0 :         } else if (drm_property_type_is(property, DRM_MODE_PROP_SIGNED_RANGE)) {
     892         [ #  # ]:          0 :                 int64_t svalue = U642I64(value);
     893                 :            : 
     894   [ #  #  #  # ]:          0 :                 if (svalue < U642I64(property->values[0]) ||
     895         [ #  # ]:          0 :                                 svalue > U642I64(property->values[1]))
     896                 :            :                         return false;
     897                 :          0 :                 return true;
     898   [ #  #  #  # ]:          0 :         } else if (drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
     899                 :            :                 uint64_t valid_mask = 0;
     900                 :            : 
     901         [ #  # ]:          0 :                 for (i = 0; i < property->num_values; i++)
     902                 :          0 :                         valid_mask |= (1ULL << property->values[i]);
     903                 :          0 :                 return !(value & ~valid_mask);
     904   [ #  #  #  # ]:          0 :         } else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB)) {
     905                 :          0 :                 struct drm_property_blob *blob;
     906                 :            : 
     907         [ #  # ]:          0 :                 if (value == 0)
     908                 :            :                         return true;
     909                 :            : 
     910                 :          0 :                 blob = drm_property_lookup_blob(property->dev, value);
     911                 :          0 :                 if (blob) {
     912                 :          0 :                         *ref = &blob->base;
     913                 :          0 :                         return true;
     914                 :            :                 } else {
     915                 :            :                         return false;
     916                 :            :                 }
     917   [ #  #  #  # ]:          0 :         } else if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) {
     918                 :            :                 /* a zero value for an object property translates to null: */
     919         [ #  # ]:          0 :                 if (value == 0)
     920                 :            :                         return true;
     921                 :            : 
     922                 :          0 :                 *ref = __drm_mode_object_find(property->dev, NULL, value,
     923                 :          0 :                                               property->values[0]);
     924                 :          0 :                 return *ref != NULL;
     925                 :            :         }
     926                 :            : 
     927         [ #  # ]:          0 :         for (i = 0; i < property->num_values; i++)
     928         [ #  # ]:          0 :                 if (property->values[i] == value)
     929                 :            :                         return true;
     930                 :            :         return false;
     931                 :            : }
     932                 :            : 
     933                 :          0 : void drm_property_change_valid_put(struct drm_property *property,
     934                 :            :                 struct drm_mode_object *ref)
     935                 :            : {
     936         [ #  # ]:          0 :         if (!ref)
     937                 :            :                 return;
     938                 :            : 
     939   [ #  #  #  # ]:          0 :         if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) {
     940                 :          0 :                 drm_mode_object_put(ref);
     941   [ #  #  #  # ]:          0 :         } else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB))
     942                 :          0 :                 drm_property_blob_put(obj_to_blob(ref));
     943                 :            : }

Generated by: LCOV version 1.14