drm: s/enum_blob_list/enum_list/ in drm_property
[deliverable/linux.git] / drivers / gpu / drm / drm_crtc.c
index e79c8d3700d838ff87f1095bcb92a773dbe36018..589a921d4313295df390142396bf12cc058b90f0 100644 (file)
@@ -683,7 +683,7 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
        drm_modeset_lock_init(&crtc->mutex);
        ret = drm_mode_object_get(dev, &crtc->base, DRM_MODE_OBJECT_CRTC);
        if (ret)
-               goto out;
+               return ret;
 
        crtc->base.properties = &crtc->properties;
 
@@ -697,9 +697,7 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
        if (cursor)
                cursor->possible_crtcs = 1 << drm_crtc_index(crtc);
 
- out:
-
-       return ret;
+       return 0;
 }
 EXPORT_SYMBOL(drm_crtc_init_with_planes);
 
@@ -766,7 +764,6 @@ static void drm_mode_remove(struct drm_connector *connector,
 /**
  * drm_connector_get_cmdline_mode - reads the user's cmdline mode
  * @connector: connector to quwery
- * @mode: returned mode
  *
  * The kernel supports per-connector configration of its consoles through
  * use of the video= parameter. This function parses that option and
@@ -870,6 +867,8 @@ int drm_connector_init(struct drm_device *dev,
 
        drm_connector_get_cmdline_mode(connector);
 
+       /* We should add connectors at the end to avoid upsetting the connector
+        * index too much. */
        list_add_tail(&connector->head, &dev->mode_config.connector_list);
        dev->mode_config.num_connector++;
 
@@ -933,6 +932,9 @@ unsigned int drm_connector_index(struct drm_connector *connector)
 {
        unsigned int index = 0;
        struct drm_connector *tmp;
+       struct drm_mode_config *config = &connector->dev->mode_config;
+
+       WARN_ON(!drm_modeset_is_locked(&config->connection_mutex));
 
        list_for_each_entry(tmp, &connector->dev->mode_config.connector_list, head) {
                if (tmp == connector)
@@ -1153,11 +1155,11 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
 {
        int ret;
 
-       drm_modeset_lock_all(dev);
-
        ret = drm_mode_object_get(dev, &plane->base, DRM_MODE_OBJECT_PLANE);
        if (ret)
-               goto out;
+               return ret;
+
+       drm_modeset_lock_init(&plane->mutex);
 
        plane->base.properties = &plane->properties;
        plane->dev = dev;
@@ -1167,8 +1169,7 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
        if (!plane->format_types) {
                DRM_DEBUG_KMS("out of memory when allocating plane\n");
                drm_mode_object_put(dev, &plane->base);
-               ret = -ENOMEM;
-               goto out;
+               return -ENOMEM;
        }
 
        memcpy(plane->format_types, formats, format_count * sizeof(uint32_t));
@@ -1185,10 +1186,7 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
                                   dev->mode_config.plane_type_property,
                                   plane->type);
 
- out:
-       drm_modeset_unlock_all(dev);
-
-       return ret;
+       return 0;
 }
 EXPORT_SYMBOL(drm_universal_plane_init);
 
@@ -1388,12 +1386,13 @@ EXPORT_SYMBOL(drm_mode_create_dvi_i_properties);
  * responsible for allocating a list of format names and passing them to
  * this routine.
  */
-int drm_mode_create_tv_properties(struct drm_device *dev, int num_modes,
+int drm_mode_create_tv_properties(struct drm_device *dev,
+                                 unsigned int num_modes,
                                  char *modes[])
 {
        struct drm_property *tv_selector;
        struct drm_property *tv_subconnector;
-       int i;
+       unsigned int i;
 
        if (dev->mode_config.tv_select_subconnector_property)
                return 0;
@@ -1491,7 +1490,7 @@ EXPORT_SYMBOL(drm_mode_create_scaling_mode_property);
  * connectors.
  *
  * Returns:
- * Zero on success, errno on failure.
+ * Zero on success, negative errno on failure.
  */
 int drm_mode_create_aspect_ratio_property(struct drm_device *dev)
 {
@@ -1535,6 +1534,30 @@ int drm_mode_create_dirty_info_property(struct drm_device *dev)
 }
 EXPORT_SYMBOL(drm_mode_create_dirty_info_property);
 
+/**
+ * drm_mode_create_suggested_offset_properties - create suggests offset properties
+ * @dev: DRM device
+ *
+ * Create the the suggested x/y offset property for connectors.
+ */
+int drm_mode_create_suggested_offset_properties(struct drm_device *dev)
+{
+       if (dev->mode_config.suggested_x_property && dev->mode_config.suggested_y_property)
+               return 0;
+
+       dev->mode_config.suggested_x_property =
+               drm_property_create_range(dev, DRM_MODE_PROP_IMMUTABLE, "suggested X", 0, 0xffffffff);
+
+       dev->mode_config.suggested_y_property =
+               drm_property_create_range(dev, DRM_MODE_PROP_IMMUTABLE, "suggested Y", 0, 0xffffffff);
+
+       if (dev->mode_config.suggested_x_property == NULL ||
+           dev->mode_config.suggested_y_property == NULL)
+               return -ENOMEM;
+       return 0;
+}
+EXPORT_SYMBOL(drm_mode_create_suggested_offset_properties);
+
 static int drm_mode_group_init(struct drm_device *dev, struct drm_mode_group *group)
 {
        uint32_t total_objects = 0;
@@ -1651,7 +1674,7 @@ static void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out,
  * the caller.
  *
  * Returns:
- * Zero on success, errno on failure.
+ * Zero on success, negative errno on failure.
  */
 static int drm_crtc_convert_umode(struct drm_display_mode *out,
                                  const struct drm_mode_modeinfo *in)
@@ -1694,7 +1717,7 @@ static int drm_crtc_convert_umode(struct drm_display_mode *out,
  * Called by the user via ioctl.
  *
  * Returns:
- * Zero on success, errno on failure.
+ * Zero on success, negative errno on failure.
  */
 int drm_mode_getresources(struct drm_device *dev, void *data,
                          struct drm_file *file_priv)
@@ -1745,7 +1768,9 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
        card_res->count_fbs = fb_count;
        mutex_unlock(&file_priv->fbs_lock);
 
-       drm_modeset_lock_all(dev);
+       /* mode_config.mutex protects the connector list against e.g. DP MST
+        * connector hot-adding. CRTC/Plane lists are invariant. */
+       mutex_lock(&dev->mode_config.mutex);
        if (!drm_is_primary_client(file_priv)) {
 
                mode_group = NULL;
@@ -1865,7 +1890,7 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
                  card_res->count_connectors, card_res->count_encoders);
 
 out:
-       drm_modeset_unlock_all(dev);
+       mutex_unlock(&dev->mode_config.mutex);
        return ret;
 }
 
@@ -1880,26 +1905,22 @@ out:
  * Called by the user via ioctl.
  *
  * Returns:
- * Zero on success, errno on failure.
+ * Zero on success, negative errno on failure.
  */
 int drm_mode_getcrtc(struct drm_device *dev,
                     void *data, struct drm_file *file_priv)
 {
        struct drm_mode_crtc *crtc_resp = data;
        struct drm_crtc *crtc;
-       int ret = 0;
 
        if (!drm_core_check_feature(dev, DRIVER_MODESET))
                return -EINVAL;
 
-       drm_modeset_lock_all(dev);
-
        crtc = drm_crtc_find(dev, crtc_resp->crtc_id);
-       if (!crtc) {
-               ret = -ENOENT;
-               goto out;
-       }
+       if (!crtc)
+               return -ENOENT;
 
+       drm_modeset_lock_crtc(crtc, crtc->primary);
        crtc_resp->x = crtc->x;
        crtc_resp->y = crtc->y;
        crtc_resp->gamma_size = crtc->gamma_size;
@@ -1916,10 +1937,9 @@ int drm_mode_getcrtc(struct drm_device *dev,
        } else {
                crtc_resp->mode_valid = 0;
        }
+       drm_modeset_unlock_crtc(crtc);
 
-out:
-       drm_modeset_unlock_all(dev);
-       return ret;
+       return 0;
 }
 
 static bool drm_mode_expose_to_userspace(const struct drm_display_mode *mode,
@@ -1946,7 +1966,7 @@ static bool drm_mode_expose_to_userspace(const struct drm_display_mode *mode,
  * Called by the user via ioctl.
  *
  * Returns:
- * Zero on success, errno on failure.
+ * Zero on success, negative errno on failure.
  */
 int drm_mode_getconnector(struct drm_device *dev, void *data,
                          struct drm_file *file_priv)
@@ -2090,37 +2110,34 @@ out:
  * Called by the user via ioctl.
  *
  * Returns:
- * Zero on success, errno on failure.
+ * Zero on success, negative errno on failure.
  */
 int drm_mode_getencoder(struct drm_device *dev, void *data,
                        struct drm_file *file_priv)
 {
        struct drm_mode_get_encoder *enc_resp = data;
        struct drm_encoder *encoder;
-       int ret = 0;
 
        if (!drm_core_check_feature(dev, DRIVER_MODESET))
                return -EINVAL;
 
-       drm_modeset_lock_all(dev);
        encoder = drm_encoder_find(dev, enc_resp->encoder_id);
-       if (!encoder) {
-               ret = -ENOENT;
-               goto out;
-       }
+       if (!encoder)
+               return -ENOENT;
 
+       drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
        if (encoder->crtc)
                enc_resp->crtc_id = encoder->crtc->base.id;
        else
                enc_resp->crtc_id = 0;
+       drm_modeset_unlock(&dev->mode_config.connection_mutex);
+
        enc_resp->encoder_type = encoder->encoder_type;
        enc_resp->encoder_id = encoder->base.id;
        enc_resp->possible_crtcs = encoder->possible_crtcs;
        enc_resp->possible_clones = encoder->possible_clones;
 
-out:
-       drm_modeset_unlock_all(dev);
-       return ret;
+       return 0;
 }
 
 /**
@@ -2134,7 +2151,7 @@ out:
  * Called by the user via ioctl.
  *
  * Returns:
- * Zero on success, errno on failure.
+ * Zero on success, negative errno on failure.
  */
 int drm_mode_getplane_res(struct drm_device *dev, void *data,
                          struct drm_file *file_priv)
@@ -2143,13 +2160,12 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data,
        struct drm_mode_config *config;
        struct drm_plane *plane;
        uint32_t __user *plane_ptr;
-       int copied = 0, ret = 0;
+       int copied = 0;
        unsigned num_planes;
 
        if (!drm_core_check_feature(dev, DRIVER_MODESET))
                return -EINVAL;
 
-       drm_modeset_lock_all(dev);
        config = &dev->mode_config;
 
        if (file_priv->universal_planes)
@@ -2165,6 +2181,7 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data,
            (plane_resp->count_planes >= num_planes)) {
                plane_ptr = (uint32_t __user *)(unsigned long)plane_resp->plane_id_ptr;
 
+               /* Plane lists are invariant, no locking needed. */
                list_for_each_entry(plane, &config->plane_list, head) {
                        /*
                         * Unless userspace set the 'universal planes'
@@ -2174,18 +2191,14 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data,
                            !file_priv->universal_planes)
                                continue;
 
-                       if (put_user(plane->base.id, plane_ptr + copied)) {
-                               ret = -EFAULT;
-                               goto out;
-                       }
+                       if (put_user(plane->base.id, plane_ptr + copied))
+                               return -EFAULT;
                        copied++;
                }
        }
        plane_resp->count_planes = num_planes;
 
-out:
-       drm_modeset_unlock_all(dev);
-       return ret;
+       return 0;
 }
 
 /**
@@ -2199,7 +2212,7 @@ out:
  * Called by the user via ioctl.
  *
  * Returns:
- * Zero on success, errno on failure.
+ * Zero on success, negative errno on failure.
  */
 int drm_mode_getplane(struct drm_device *dev, void *data,
                      struct drm_file *file_priv)
@@ -2207,18 +2220,15 @@ int drm_mode_getplane(struct drm_device *dev, void *data,
        struct drm_mode_get_plane *plane_resp = data;
        struct drm_plane *plane;
        uint32_t __user *format_ptr;
-       int ret = 0;
 
        if (!drm_core_check_feature(dev, DRIVER_MODESET))
                return -EINVAL;
 
-       drm_modeset_lock_all(dev);
        plane = drm_plane_find(dev, plane_resp->plane_id);
-       if (!plane) {
-               ret = -ENOENT;
-               goto out;
-       }
+       if (!plane)
+               return -ENOENT;
 
+       drm_modeset_lock(&plane->mutex, NULL);
        if (plane->crtc)
                plane_resp->crtc_id = plane->crtc->base.id;
        else
@@ -2228,6 +2238,7 @@ int drm_mode_getplane(struct drm_device *dev, void *data,
                plane_resp->fb_id = plane->fb->base.id;
        else
                plane_resp->fb_id = 0;
+       drm_modeset_unlock(&plane->mutex);
 
        plane_resp->plane_id = plane->base.id;
        plane_resp->possible_crtcs = plane->possible_crtcs;
@@ -2243,15 +2254,12 @@ int drm_mode_getplane(struct drm_device *dev, void *data,
                if (copy_to_user(format_ptr,
                                 plane->format_types,
                                 sizeof(uint32_t) * plane->format_count)) {
-                       ret = -EFAULT;
-                       goto out;
+                       return -EFAULT;
                }
        }
        plane_resp->count_format_types = plane->format_count;
 
-out:
-       drm_modeset_unlock_all(dev);
-       return ret;
+       return 0;
 }
 
 /*
@@ -2274,7 +2282,7 @@ static int __setplane_internal(struct drm_plane *plane,
 {
        int ret = 0;
        unsigned int fb_width, fb_height;
-       int i;
+       unsigned int i;
 
        /* No fb means shut it down */
        if (!fb) {
@@ -2378,7 +2386,7 @@ static int setplane_internal(struct drm_plane *plane,
  * valid crtc).
  *
  * Returns:
- * Zero on success, errno on failure.
+ * Zero on success, negative errno on failure.
  */
 int drm_mode_setplane(struct drm_device *dev, void *data,
                      struct drm_file *file_priv)
@@ -2453,7 +2461,7 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
  * interface. The only thing it adds is correct refcounting dance.
  * 
  * Returns:
- * Zero on success, errno on failure.
+ * Zero on success, negative errno on failure.
  */
 int drm_mode_set_config_internal(struct drm_mode_set *set)
 {
@@ -2546,7 +2554,7 @@ EXPORT_SYMBOL(drm_crtc_check_viewport);
  * Called by the user via ioctl.
  *
  * Returns:
- * Zero on success, errno on failure.
+ * Zero on success, negative errno on failure.
  */
 int drm_mode_setcrtc(struct drm_device *dev, void *data,
                     struct drm_file *file_priv)
@@ -2709,7 +2717,7 @@ out:
  * userspace wants to make use of these capabilities.
  *
  * Returns:
- * Zero on success, errno on failure.
+ * Zero on success, negative errno on failure.
  */
 static int drm_mode_cursor_universal(struct drm_crtc *crtc,
                                     struct drm_mode_cursor2 *req,
@@ -2810,7 +2818,7 @@ static int drm_mode_cursor_common(struct drm_device *dev,
         * If this crtc has a universal cursor plane, call that plane's update
         * handler rather than using legacy cursor handlers.
         */
-       drm_modeset_lock_crtc(crtc);
+       drm_modeset_lock_crtc(crtc, crtc->cursor);
        if (crtc->cursor) {
                ret = drm_mode_cursor_universal(crtc, req, file_priv);
                goto out;
@@ -2857,7 +2865,7 @@ out:
  * Called by the user via ioctl.
  *
  * Returns:
- * Zero on success, errno on failure.
+ * Zero on success, negative errno on failure.
  */
 int drm_mode_cursor_ioctl(struct drm_device *dev,
                          void *data, struct drm_file *file_priv)
@@ -2884,7 +2892,7 @@ int drm_mode_cursor_ioctl(struct drm_device *dev,
  * Called by the user via ioctl.
  *
  * Returns:
- * Zero on success, errno on failure.
+ * Zero on success, negative errno on failure.
  */
 int drm_mode_cursor2_ioctl(struct drm_device *dev,
                           void *data, struct drm_file *file_priv)
@@ -2943,23 +2951,21 @@ EXPORT_SYMBOL(drm_mode_legacy_fb_format);
  * @file_priv: drm file for the ioctl call
  *
  * Add a new FB to the specified CRTC, given a user request. This is the
- * original addfb ioclt which only supported RGB formats.
+ * original addfb ioctl which only supported RGB formats.
  *
  * Called by the user via ioctl.
  *
  * Returns:
- * Zero on success, errno on failure.
+ * Zero on success, negative errno on failure.
  */
 int drm_mode_addfb(struct drm_device *dev,
                   void *data, struct drm_file *file_priv)
 {
        struct drm_mode_fb_cmd *or = data;
        struct drm_mode_fb_cmd2 r = {};
-       struct drm_mode_config *config = &dev->mode_config;
-       struct drm_framebuffer *fb;
-       int ret = 0;
+       int ret;
 
-       /* Use new struct with format internally */
+       /* convert to new format and call new ioctl */
        r.fb_id = or->fb_id;
        r.width = or->width;
        r.height = or->height;
@@ -2967,28 +2973,13 @@ int drm_mode_addfb(struct drm_device *dev,
        r.pixel_format = drm_mode_legacy_fb_format(or->bpp, or->depth);
        r.handles[0] = or->handle;
 
-       if (!drm_core_check_feature(dev, DRIVER_MODESET))
-               return -EINVAL;
-
-       if ((config->min_width > r.width) || (r.width > config->max_width))
-               return -EINVAL;
-
-       if ((config->min_height > r.height) || (r.height > config->max_height))
-               return -EINVAL;
-
-       fb = dev->mode_config.funcs->fb_create(dev, file_priv, &r);
-       if (IS_ERR(fb)) {
-               DRM_DEBUG_KMS("could not create framebuffer\n");
-               return PTR_ERR(fb);
-       }
+       ret = drm_mode_addfb2(dev, &r, file_priv);
+       if (ret)
+               return ret;
 
-       mutex_lock(&file_priv->fbs_lock);
-       or->fb_id = fb->base.id;
-       list_add(&fb->filp_head, &file_priv->fbs);
-       DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id);
-       mutex_unlock(&file_priv->fbs_lock);
+       or->fb_id = r.fb_id;
 
-       return ret;
+       return 0;
 }
 
 static int format_check(const struct drm_mode_fb_cmd2 *r)
@@ -3080,7 +3071,7 @@ static int framebuffer_check(const struct drm_mode_fb_cmd2 *r)
        num_planes = drm_format_num_planes(r->pixel_format);
 
        if (r->width == 0 || r->width % hsub) {
-               DRM_DEBUG_KMS("bad framebuffer width %u\n", r->height);
+               DRM_DEBUG_KMS("bad framebuffer width %u\n", r->width);
                return -EINVAL;
        }
 
@@ -3170,7 +3161,7 @@ static struct drm_framebuffer *add_framebuffer_internal(struct drm_device *dev,
  * Called by the user via ioctl.
  *
  * Returns:
- * Zero on success, errno on failure.
+ * Zero on success, negative errno on failure.
  */
 int drm_mode_addfb2(struct drm_device *dev,
                    void *data, struct drm_file *file_priv)
@@ -3198,7 +3189,7 @@ int drm_mode_addfb2(struct drm_device *dev,
  * Called by the user via ioctl.
  *
  * Returns:
- * Zero on success, errno on failure.
+ * Zero on success, negative errno on failure.
  */
 int drm_mode_rmfb(struct drm_device *dev,
                   void *data, struct drm_file *file_priv)
@@ -3252,7 +3243,7 @@ fail_lookup:
  * Called by the user via ioctl.
  *
  * Returns:
- * Zero on success, errno on failure.
+ * Zero on success, negative errno on failure.
  */
 int drm_mode_getfb(struct drm_device *dev,
                   void *data, struct drm_file *file_priv)
@@ -3313,7 +3304,7 @@ int drm_mode_getfb(struct drm_device *dev,
  * Called by the user via ioctl.
  *
  * Returns:
- * Zero on success, errno on failure.
+ * Zero on success, negative errno on failure.
  */
 int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
                           void *data, struct drm_file *file_priv)
@@ -3393,7 +3384,7 @@ out_err1:
  * Called by the user via ioctl.
  *
  * Returns:
- * Zero on success, errno on failure.
+ * Zero on success, negative errno on failure.
  */
 void drm_fb_release(struct drm_file *priv)
 {
@@ -3435,6 +3426,10 @@ void drm_fb_release(struct drm_file *priv)
  * object with drm_object_attach_property. The returned property object must be
  * freed with drm_property_destroy.
  *
+ * Note that the DRM core keeps a per-device list of properties and that, if
+ * drm_mode_config_cleanup() is called, it will destroy all properties created
+ * by the driver.
+ *
  * Returns:
  * A pointer to the newly created property on success, NULL on failure.
  */
@@ -3462,7 +3457,7 @@ struct drm_property *drm_property_create(struct drm_device *dev, int flags,
 
        property->flags = flags;
        property->num_values = num_values;
-       INIT_LIST_HEAD(&property->enum_blob_list);
+       INIT_LIST_HEAD(&property->enum_list);
 
        if (name) {
                strncpy(property->name, name, DRM_PROP_NAME_LEN);
@@ -3611,7 +3606,7 @@ static struct drm_property *property_create_range(struct drm_device *dev,
  * object with drm_object_attach_property. The returned property object must be
  * freed with drm_property_destroy.
  *
- * Userspace is allowed to set any interger value in the (min, max) range
+ * Userspace is allowed to set any integer value in the (min, max) range
  * inclusive.
  *
  * Returns:
@@ -3684,8 +3679,8 @@ int drm_property_add_enum(struct drm_property *property, int index,
                        (value > 63))
                return -EINVAL;
 
-       if (!list_empty(&property->enum_blob_list)) {
-               list_for_each_entry(prop_enum, &property->enum_blob_list, head) {
+       if (!list_empty(&property->enum_list)) {
+               list_for_each_entry(prop_enum, &property->enum_list, head) {
                        if (prop_enum->value == value) {
                                strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN);
                                prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0';
@@ -3703,7 +3698,7 @@ int drm_property_add_enum(struct drm_property *property, int index,
        prop_enum->value = value;
 
        property->values[index] = value;
-       list_add_tail(&prop_enum->head, &property->enum_blob_list);
+       list_add_tail(&prop_enum->head, &property->enum_list);
        return 0;
 }
 EXPORT_SYMBOL(drm_property_add_enum);
@@ -3720,7 +3715,7 @@ void drm_property_destroy(struct drm_device *dev, struct drm_property *property)
 {
        struct drm_property_enum *prop_enum, *pt;
 
-       list_for_each_entry_safe(prop_enum, pt, &property->enum_blob_list, head) {
+       list_for_each_entry_safe(prop_enum, pt, &property->enum_list, head) {
                list_del(&prop_enum->head);
                kfree(prop_enum);
        }
@@ -3823,17 +3818,20 @@ int drm_object_property_get_value(struct drm_mode_object *obj,
 EXPORT_SYMBOL(drm_object_property_get_value);
 
 /**
- * drm_mode_getproperty_ioctl - get the current value of a connector's property
+ * drm_mode_getproperty_ioctl - get the property metadata
  * @dev: DRM device
  * @data: ioctl data
  * @file_priv: DRM file info
  *
- * This function retrieves the current value for an connectors's property.
+ * This function retrieves the metadata for a given property, like the different
+ * possible values for an enum property or the limits for a range property.
+ *
+ * Blob properties are special
  *
  * Called by the user via ioctl.
  *
  * Returns:
- * Zero on success, errno on failure.
+ * Zero on success, negative errno on failure.
  */
 int drm_mode_getproperty_ioctl(struct drm_device *dev,
                               void *data, struct drm_file *file_priv)
@@ -3841,16 +3839,12 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev,
        struct drm_mode_get_property *out_resp = data;
        struct drm_property *property;
        int enum_count = 0;
-       int blob_count = 0;
        int value_count = 0;
        int ret = 0, i;
        int copied;
        struct drm_property_enum *prop_enum;
        struct drm_mode_property_enum __user *enum_ptr;
-       struct drm_property_blob *prop_blob;
-       uint32_t __user *blob_id_ptr;
        uint64_t __user *values_ptr;
-       uint32_t __user *blob_length_ptr;
 
        if (!drm_core_check_feature(dev, DRIVER_MODESET))
                return -EINVAL;
@@ -3864,11 +3858,8 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev,
 
        if (drm_property_type_is(property, DRM_MODE_PROP_ENUM) ||
                        drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
-               list_for_each_entry(prop_enum, &property->enum_blob_list, head)
+               list_for_each_entry(prop_enum, &property->enum_list, head)
                        enum_count++;
-       } else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB)) {
-               list_for_each_entry(prop_blob, &property->enum_blob_list, head)
-                       blob_count++;
        }
 
        value_count = property->num_values;
@@ -3893,7 +3884,7 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev,
                if ((out_resp->count_enum_blobs >= enum_count) && enum_count) {
                        copied = 0;
                        enum_ptr = (struct drm_mode_property_enum __user *)(unsigned long)out_resp->enum_blob_ptr;
-                       list_for_each_entry(prop_enum, &property->enum_blob_list, head) {
+                       list_for_each_entry(prop_enum, &property->enum_list, head) {
 
                                if (copy_to_user(&enum_ptr[copied].value, &prop_enum->value, sizeof(uint64_t))) {
                                        ret = -EFAULT;
@@ -3911,35 +3902,24 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev,
                out_resp->count_enum_blobs = enum_count;
        }
 
-       if (drm_property_type_is(property, DRM_MODE_PROP_BLOB)) {
-               if ((out_resp->count_enum_blobs >= blob_count) && blob_count) {
-                       copied = 0;
-                       blob_id_ptr = (uint32_t __user *)(unsigned long)out_resp->enum_blob_ptr;
-                       blob_length_ptr = (uint32_t __user *)(unsigned long)out_resp->values_ptr;
-
-                       list_for_each_entry(prop_blob, &property->enum_blob_list, head) {
-                               if (put_user(prop_blob->base.id, blob_id_ptr + copied)) {
-                                       ret = -EFAULT;
-                                       goto done;
-                               }
-
-                               if (put_user(prop_blob->length, blob_length_ptr + copied)) {
-                                       ret = -EFAULT;
-                                       goto done;
-                               }
-
-                               copied++;
-                       }
-               }
-               out_resp->count_enum_blobs = blob_count;
-       }
+       /*
+        * NOTE: The idea seems to have been to use this to read all the blob
+        * property values. But nothing ever added them to the corresponding
+        * list, userspace always used the special-purpose get_blob ioctl to
+        * read the value for a blob property. It also doesn't make a lot of
+        * sense to return values here when everything else is just metadata for
+        * the property itself.
+        */
+       if (drm_property_type_is(property, DRM_MODE_PROP_BLOB))
+               out_resp->count_enum_blobs = 0;
 done:
        drm_modeset_unlock_all(dev);
        return ret;
 }
 
-static struct drm_property_blob *drm_property_create_blob(struct drm_device *dev, int length,
-                                                         void *data)
+static struct drm_property_blob *
+drm_property_create_blob(struct drm_device *dev, size_t length,
+                        const void *data)
 {
        struct drm_property_blob *blob;
        int ret;
@@ -3985,7 +3965,7 @@ static void drm_property_destroy_blob(struct drm_device *dev,
  * Called by the user via ioctl.
  *
  * Returns:
- * Zero on success, errno on failure.
+ * Zero on success, negative errno on failure.
  */
 int drm_mode_getblob_ioctl(struct drm_device *dev,
                           void *data, struct drm_file *file_priv)
@@ -4019,12 +3999,25 @@ done:
        return ret;
 }
 
+/**
+ * drm_mode_connector_set_path_property - set tile property on connector
+ * @connector: connector to set property on.
+ * @path: path to use for property.
+ *
+ * This creates a property to expose to userspace to specify a
+ * connector path. This is mainly used for DisplayPort MST where
+ * connectors have a topology and we want to allow userspace to give
+ * them more meaningful names.
+ *
+ * Returns:
+ * Zero on success, negative errno on failure.
+ */
 int drm_mode_connector_set_path_property(struct drm_connector *connector,
-                                        char *path)
+                                        const char *path)
 {
        struct drm_device *dev = connector->dev;
-       int ret, size;
-       size = strlen(path) + 1;
+       size_t size = strlen(path) + 1;
+       int ret;
 
        connector->path_blob_ptr = drm_property_create_blob(connector->dev,
                                                            size, path);
@@ -4047,13 +4040,14 @@ EXPORT_SYMBOL(drm_mode_connector_set_path_property);
  * connector's edid property.
  *
  * Returns:
- * Zero on success, errno on failure.
+ * Zero on success, negative errno on failure.
  */
 int drm_mode_connector_update_edid_property(struct drm_connector *connector,
-                                           struct edid *edid)
+                                           const struct edid *edid)
 {
        struct drm_device *dev = connector->dev;
-       int ret, size;
+       size_t size;
+       int ret;
 
        /* ignore requests to set edid when overridden */
        if (connector->override_edid)
@@ -4143,7 +4137,7 @@ static bool drm_property_change_is_valid(struct drm_property *property,
  * Called by the user via ioctl.
  *
  * Returns:
- * Zero on success, errno on failure.
+ * Zero on success, negative errno on failure.
  */
 int drm_mode_connector_property_set_ioctl(struct drm_device *dev,
                                       void *data, struct drm_file *file_priv)
@@ -4226,7 +4220,7 @@ int drm_mode_plane_set_obj_prop(struct drm_plane *plane,
 EXPORT_SYMBOL(drm_mode_plane_set_obj_prop);
 
 /**
- * drm_mode_getproperty_ioctl - get the current value of a object's property
+ * drm_mode_obj_get_properties_ioctl - get the current value of a object's property
  * @dev: DRM device
  * @data: ioctl data
  * @file_priv: DRM file info
@@ -4238,7 +4232,7 @@ EXPORT_SYMBOL(drm_mode_plane_set_obj_prop);
  * Called by the user via ioctl.
  *
  * Returns:
- * Zero on success, errno on failure.
+ * Zero on success, negative errno on failure.
  */
 int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data,
                                      struct drm_file *file_priv)
@@ -4310,7 +4304,7 @@ out:
  * Called by the user via ioctl.
  *
  * Returns:
- * Zero on success, errno on failure.
+ * Zero on success, negative errno on failure.
  */
 int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,
                                    struct drm_file *file_priv)
@@ -4382,7 +4376,7 @@ out:
  * possible_clones and possible_crtcs bitmasks.
  *
  * Returns:
- * Zero on success, errno on failure.
+ * Zero on success, negative errno on failure.
  */
 int drm_mode_connector_attach_encoder(struct drm_connector *connector,
                                      struct drm_encoder *encoder)
@@ -4409,7 +4403,7 @@ EXPORT_SYMBOL(drm_mode_connector_attach_encoder);
  * fixed gamma table size.
  *
  * Returns:
- * Zero on success, errno on failure.
+ * Zero on success, negative errno on failure.
  */
 int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc,
                                 int gamma_size)
@@ -4438,7 +4432,7 @@ EXPORT_SYMBOL(drm_mode_crtc_set_gamma_size);
  * Called by the user via ioctl.
  *
  * Returns:
- * Zero on success, errno on failure.
+ * Zero on success, negative errno on failure.
  */
 int drm_mode_gamma_set_ioctl(struct drm_device *dev,
                             void *data, struct drm_file *file_priv)
@@ -4510,7 +4504,7 @@ out:
  * Called by the user via ioctl.
  *
  * Returns:
- * Zero on success, errno on failure.
+ * Zero on success, negative errno on failure.
  */
 int drm_mode_gamma_get_ioctl(struct drm_device *dev,
                             void *data, struct drm_file *file_priv)
@@ -4576,7 +4570,7 @@ out:
  * Called by the user via ioctl.
  *
  * Returns:
- * Zero on success, errno on failure.
+ * Zero on success, negative errno on failure.
  */
 int drm_mode_page_flip_ioctl(struct drm_device *dev,
                             void *data, struct drm_file *file_priv)
@@ -4599,7 +4593,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
        if (!crtc)
                return -ENOENT;
 
-       drm_modeset_lock_crtc(crtc);
+       drm_modeset_lock_crtc(crtc, crtc->primary);
        if (crtc->primary->fb == NULL) {
                /* The framebuffer is currently unbound, presumably
                 * due to a hotplug event, that userspace has not
@@ -4742,7 +4736,7 @@ EXPORT_SYMBOL(drm_mode_config_reset);
  * Called by the user via ioctl.
  *
  * Returns:
- * Zero on success, errno on failure.
+ * Zero on success, negative errno on failure.
  */
 int drm_mode_create_dumb_ioctl(struct drm_device *dev,
                               void *data, struct drm_file *file_priv)
@@ -4769,6 +4763,16 @@ int drm_mode_create_dumb_ioctl(struct drm_device *dev,
        if (PAGE_ALIGN(size) == 0)
                return -EINVAL;
 
+       /*
+        * handle, pitch and size are output parameters. Zero them out to
+        * prevent drivers from accidentally using uninitialized data. Since
+        * not all existing userspace is clearing these fields properly we
+        * cannot reject IOCTL with garbage in them.
+        */
+       args->handle = 0;
+       args->pitch = 0;
+       args->size = 0;
+
        return dev->driver->dumb_create(file_priv, dev, args);
 }
 
@@ -4784,7 +4788,7 @@ int drm_mode_create_dumb_ioctl(struct drm_device *dev,
  * Called by the user via ioctl.
  *
  * Returns:
- * Zero on success, errno on failure.
+ * Zero on success, negative errno on failure.
  */
 int drm_mode_mmap_dumb_ioctl(struct drm_device *dev,
                             void *data, struct drm_file *file_priv)
@@ -4811,7 +4815,7 @@ int drm_mode_mmap_dumb_ioctl(struct drm_device *dev,
  * Called by the user via ioctl.
  *
  * Returns:
- * Zero on success, errno on failure.
+ * Zero on success, negative errno on failure.
  */
 int drm_mode_destroy_dumb_ioctl(struct drm_device *dev,
                                void *data, struct drm_file *file_priv)
This page took 0.039174 seconds and 5 git commands to generate.