]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blobdiff - drivers/gpu/drm/drm_mode_config.c
drm: locking&new iterators for connector_list
[mirror_ubuntu-hirsute-kernel.git] / drivers / gpu / drm / drm_mode_config.c
index a9a40dc629d39a6f33403371c26e91c43446f82f..649f1da3596fb8ffc5d2376861dd84c8022771b0 100644 (file)
@@ -94,6 +94,7 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
        uint32_t __user *crtc_id;
        uint32_t __user *connector_id;
        uint32_t __user *encoder_id;
+       struct drm_connector_list_iter conn_iter;
 
        if (!drm_core_check_feature(dev, DRIVER_MODESET))
                return -EINVAL;
@@ -113,9 +114,6 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
        card_res->count_fbs = count;
        mutex_unlock(&file_priv->fbs_lock);
 
-       /* 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);
        card_res->max_height = dev->mode_config.max_height;
        card_res->min_height = dev->mode_config.min_height;
        card_res->max_width = dev->mode_config.max_width;
@@ -125,10 +123,8 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
        crtc_id = u64_to_user_ptr(card_res->crtc_id_ptr);
        drm_for_each_crtc(crtc, dev) {
                if (count < card_res->count_crtcs &&
-                   put_user(crtc->base.id, crtc_id + count)) {
-                       ret = -EFAULT;
-                       goto out;
-               }
+                   put_user(crtc->base.id, crtc_id + count))
+                       return -EFAULT;
                count++;
        }
        card_res->count_crtcs = count;
@@ -137,28 +133,26 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
        encoder_id = u64_to_user_ptr(card_res->encoder_id_ptr);
        drm_for_each_encoder(encoder, dev) {
                if (count < card_res->count_encoders &&
-                   put_user(encoder->base.id, encoder_id + count)) {
-                       ret = -EFAULT;
-                       goto out;
-               }
+                   put_user(encoder->base.id, encoder_id + count))
+                       return -EFAULT;
                count++;
        }
        card_res->count_encoders = count;
 
+       drm_connector_list_iter_get(dev, &conn_iter);
        count = 0;
        connector_id = u64_to_user_ptr(card_res->connector_id_ptr);
-       drm_for_each_connector(connector, dev) {
+       drm_for_each_connector_iter(connector, &conn_iter) {
                if (count < card_res->count_connectors &&
                    put_user(connector->base.id, connector_id + count)) {
-                       ret = -EFAULT;
-                       goto out;
+                       drm_connector_list_iter_put(&conn_iter);
+                       return -EFAULT;
                }
                count++;
        }
        card_res->count_connectors = count;
+       drm_connector_list_iter_put(&conn_iter);
 
-out:
-       mutex_unlock(&dev->mode_config.mutex);
        return ret;
 }
 
@@ -176,6 +170,7 @@ void drm_mode_config_reset(struct drm_device *dev)
        struct drm_plane *plane;
        struct drm_encoder *encoder;
        struct drm_connector *connector;
+       struct drm_connector_list_iter conn_iter;
 
        drm_for_each_plane(plane, dev)
                if (plane->funcs->reset)
@@ -189,11 +184,11 @@ void drm_mode_config_reset(struct drm_device *dev)
                if (encoder->funcs->reset)
                        encoder->funcs->reset(encoder);
 
-       mutex_lock(&dev->mode_config.mutex);
-       drm_for_each_connector(connector, dev)
+       drm_connector_list_iter_get(dev, &conn_iter);
+       drm_for_each_connector_iter(connector, &conn_iter)
                if (connector->funcs->reset)
                        connector->funcs->reset(connector);
-       mutex_unlock(&dev->mode_config.mutex);
+       drm_connector_list_iter_put(&conn_iter);
 }
 EXPORT_SYMBOL(drm_mode_config_reset);
 
@@ -374,6 +369,7 @@ void drm_mode_config_init(struct drm_device *dev)
        idr_init(&dev->mode_config.crtc_idr);
        idr_init(&dev->mode_config.tile_idr);
        ida_init(&dev->mode_config.connector_ida);
+       spin_lock_init(&dev->mode_config.connector_list_lock);
 
        drm_mode_create_standard_properties(dev);