diff mbox

[09/13] drm: Tighten locking in drm_mode_getconnector

Message ID 20161213230814.19598-10-daniel.vetter@ffwll.ch (mailing list archive)
State New, archived
Headers show

Commit Message

Daniel Vetter Dec. 13, 2016, 11:08 p.m. UTC
- Modeset state needs mode_config->connection mutex, that covers
  figuring out the encoder, and reading properties (since in the
  atomic case those need to look at connector->state).

- Don't hold any locks for stuff that's invariant (i.e. possible
  connectors).

- Same for connector lookup and unref, those don't need any locks.

- And finally the probe stuff is only protected by mode_config->mutex.

While at it updated the kerneldoc for these fields in drm_connector
and add docs explaining what's protected by which locks.

Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
---
 drivers/gpu/drm/drm_connector.c | 92 ++++++++++++++++++++---------------------
 include/drm/drm_connector.h     | 23 +++++++++--
 2 files changed, 63 insertions(+), 52 deletions(-)

Comments

Sean Paul Dec. 16, 2016, 3:03 p.m. UTC | #1
On Tue, Dec 13, 2016 at 6:08 PM, Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
> - Modeset state needs mode_config->connection mutex, that covers
>   figuring out the encoder, and reading properties (since in the
>   atomic case those need to look at connector->state).
>
> - Don't hold any locks for stuff that's invariant (i.e. possible
>   connectors).
>
> - Same for connector lookup and unref, those don't need any locks.
>
> - And finally the probe stuff is only protected by mode_config->mutex.
>
> While at it updated the kerneldoc for these fields in drm_connector
> and add docs explaining what's protected by which locks.
>


Reviewed-by: Sean Paul <seanpaul@chromium.org>

> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
> ---
>  drivers/gpu/drm/drm_connector.c | 92 ++++++++++++++++++++---------------------
>  include/drm/drm_connector.h     | 23 +++++++++--
>  2 files changed, 63 insertions(+), 52 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
> index 0d4728704099..44b556d5d40c 100644
> --- a/drivers/gpu/drm/drm_connector.c
> +++ b/drivers/gpu/drm/drm_connector.c
> @@ -1160,43 +1160,65 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
>
>         memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo));
>
> -       mutex_lock(&dev->mode_config.mutex);
> -
>         connector = drm_connector_lookup(dev, out_resp->connector_id);
> -       if (!connector) {
> -               ret = -ENOENT;
> -               goto out_unlock;
> -       }
> +       if (!connector)
> +               return -ENOENT;
> +
> +       drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
> +       encoder = drm_connector_get_encoder(connector);
> +       if (encoder)
> +               out_resp->encoder_id = encoder->base.id;
> +       else
> +               out_resp->encoder_id = 0;
> +
> +       ret = drm_mode_object_get_properties(&connector->base, file_priv->atomic,
> +                       (uint32_t __user *)(unsigned long)(out_resp->props_ptr),
> +                       (uint64_t __user *)(unsigned long)(out_resp->prop_values_ptr),
> +                       &out_resp->count_props);
> +       drm_modeset_unlock(&dev->mode_config.connection_mutex);
> +       if (ret)
> +               goto out_unref;
>
>         for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++)
>                 if (connector->encoder_ids[i] != 0)
>                         encoders_count++;
>
> +       if ((out_resp->count_encoders >= encoders_count) && encoders_count) {
> +               copied = 0;
> +               encoder_ptr = (uint32_t __user *)(unsigned long)(out_resp->encoders_ptr);
> +               for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
> +                       if (connector->encoder_ids[i] != 0) {
> +                               if (put_user(connector->encoder_ids[i],
> +                                            encoder_ptr + copied)) {
> +                                       ret = -EFAULT;
> +                                       goto out_unref;
> +                               }
> +                               copied++;
> +                       }
> +               }
> +       }
> +       out_resp->count_encoders = encoders_count;
> +
> +       out_resp->connector_id = connector->base.id;
> +       out_resp->connector_type = connector->connector_type;
> +       out_resp->connector_type_id = connector->connector_type_id;
> +
> +       mutex_lock(&dev->mode_config.mutex);
>         if (out_resp->count_modes == 0) {
>                 connector->funcs->fill_modes(connector,
>                                              dev->mode_config.max_width,
>                                              dev->mode_config.max_height);
>         }
>
> -       /* delayed so we get modes regardless of pre-fill_modes state */
> -       list_for_each_entry(mode, &connector->modes, head)
> -               if (drm_mode_expose_to_userspace(mode, file_priv))
> -                       mode_count++;
> -
> -       out_resp->connector_id = connector->base.id;
> -       out_resp->connector_type = connector->connector_type;
> -       out_resp->connector_type_id = connector->connector_type_id;
>         out_resp->mm_width = connector->display_info.width_mm;
>         out_resp->mm_height = connector->display_info.height_mm;
>         out_resp->subpixel = connector->display_info.subpixel_order;
>         out_resp->connection = connector->status;
>
> -       drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
> -       encoder = drm_connector_get_encoder(connector);
> -       if (encoder)
> -               out_resp->encoder_id = encoder->base.id;
> -       else
> -               out_resp->encoder_id = 0;
> +       /* delayed so we get modes regardless of pre-fill_modes state */
> +       list_for_each_entry(mode, &connector->modes, head)
> +               if (drm_mode_expose_to_userspace(mode, file_priv))
> +                       mode_count++;
>
>         /*
>          * This ioctl is called twice, once to determine how much space is
> @@ -1219,36 +1241,10 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
>                 }
>         }
>         out_resp->count_modes = mode_count;
> -
> -       ret = drm_mode_object_get_properties(&connector->base, file_priv->atomic,
> -                       (uint32_t __user *)(unsigned long)(out_resp->props_ptr),
> -                       (uint64_t __user *)(unsigned long)(out_resp->prop_values_ptr),
> -                       &out_resp->count_props);
> -       if (ret)
> -               goto out;
> -
> -       if ((out_resp->count_encoders >= encoders_count) && encoders_count) {
> -               copied = 0;
> -               encoder_ptr = (uint32_t __user *)(unsigned long)(out_resp->encoders_ptr);
> -               for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
> -                       if (connector->encoder_ids[i] != 0) {
> -                               if (put_user(connector->encoder_ids[i],
> -                                            encoder_ptr + copied)) {
> -                                       ret = -EFAULT;
> -                                       goto out;
> -                               }
> -                               copied++;
> -                       }
> -               }
> -       }
> -       out_resp->count_encoders = encoders_count;
> -
>  out:
> -       drm_modeset_unlock(&dev->mode_config.connection_mutex);
> -
> -       drm_connector_unreference(connector);
> -out_unlock:
>         mutex_unlock(&dev->mode_config.mutex);
> +out_unref:
> +       drm_connector_unreference(connector);
>
>         return ret;
>  }
> diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
> index a24559ef8bb7..9af4141165d3 100644
> --- a/include/drm/drm_connector.h
> +++ b/include/drm/drm_connector.h
> @@ -559,9 +559,6 @@ struct drm_cmdline_mode {
>   * @interlace_allowed: can this connector handle interlaced modes?
>   * @doublescan_allowed: can this connector handle doublescan?
>   * @stereo_allowed: can this connector handle stereo modes?
> - * @modes: modes available on this connector (from fill_modes() + user)
> - * @status: one of the drm_connector_status enums (connected, not, or unknown)
> - * @probed_modes: list of modes derived directly from the display
>   * @funcs: connector control functions
>   * @edid_blob_ptr: DRM property containing EDID if present
>   * @properties: property tracking for this connector
> @@ -631,11 +628,27 @@ struct drm_connector {
>          * Protected by @mutex.
>          */
>         bool registered;
> +
> +       /**
> +        * @modes:
> +        * Modes available on this connector (from fill_modes() + user).
> +        * Protected by dev->mode_config.mutex.
> +        */
>         struct list_head modes; /* list of modes on this connector */
>
> +       /**
> +        * @status:
> +        * One of the drm_connector_status enums (connected, not, or unknown).
> +        * Protected by dev->mode_config.mutex.
> +        */
>         enum drm_connector_status status;
>
> -       /* these are modes added by probing with DDC or the BIOS */
> +       /**
> +        * @probed_modes:
> +        * These are modes added by probing with DDC or the BIOS, before
> +        * filtering is applied. Used by the probe helpers.Protected by
> +        * dev->mode_config.mutex.
> +        */
>         struct list_head probed_modes;
>
>         /**
> @@ -644,6 +657,8 @@ struct drm_connector {
>          * flat panels in embedded systems, the driver should initialize the
>          * display_info.width_mm and display_info.height_mm fields with the
>          * physical size of the display.
> +        *
> +        * Protected by dev->mode_config.mutex.
>          */
>         struct drm_display_info display_info;
>         const struct drm_connector_funcs *funcs;
> --
> 2.11.0
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
Daniel Vetter Dec. 18, 2016, 1:40 p.m. UTC | #2
On Fri, Dec 16, 2016 at 10:03:32AM -0500, Sean Paul wrote:
> On Tue, Dec 13, 2016 at 6:08 PM, Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
> > - Modeset state needs mode_config->connection mutex, that covers
> >   figuring out the encoder, and reading properties (since in the
> >   atomic case those need to look at connector->state).
> >
> > - Don't hold any locks for stuff that's invariant (i.e. possible
> >   connectors).
> >
> > - Same for connector lookup and unref, those don't need any locks.
> >
> > - And finally the probe stuff is only protected by mode_config->mutex.
> >
> > While at it updated the kerneldoc for these fields in drm_connector
> > and add docs explaining what's protected by which locks.
> >
> 
> 
> Reviewed-by: Sean Paul <seanpaul@chromium.org>

Merged up to this patch to drm-misc, thanks for the reviews to everyone.
-Daniel

> 
> > Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
> > ---
> >  drivers/gpu/drm/drm_connector.c | 92 ++++++++++++++++++++---------------------
> >  include/drm/drm_connector.h     | 23 +++++++++--
> >  2 files changed, 63 insertions(+), 52 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
> > index 0d4728704099..44b556d5d40c 100644
> > --- a/drivers/gpu/drm/drm_connector.c
> > +++ b/drivers/gpu/drm/drm_connector.c
> > @@ -1160,43 +1160,65 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
> >
> >         memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo));
> >
> > -       mutex_lock(&dev->mode_config.mutex);
> > -
> >         connector = drm_connector_lookup(dev, out_resp->connector_id);
> > -       if (!connector) {
> > -               ret = -ENOENT;
> > -               goto out_unlock;
> > -       }
> > +       if (!connector)
> > +               return -ENOENT;
> > +
> > +       drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
> > +       encoder = drm_connector_get_encoder(connector);
> > +       if (encoder)
> > +               out_resp->encoder_id = encoder->base.id;
> > +       else
> > +               out_resp->encoder_id = 0;
> > +
> > +       ret = drm_mode_object_get_properties(&connector->base, file_priv->atomic,
> > +                       (uint32_t __user *)(unsigned long)(out_resp->props_ptr),
> > +                       (uint64_t __user *)(unsigned long)(out_resp->prop_values_ptr),
> > +                       &out_resp->count_props);
> > +       drm_modeset_unlock(&dev->mode_config.connection_mutex);
> > +       if (ret)
> > +               goto out_unref;
> >
> >         for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++)
> >                 if (connector->encoder_ids[i] != 0)
> >                         encoders_count++;
> >
> > +       if ((out_resp->count_encoders >= encoders_count) && encoders_count) {
> > +               copied = 0;
> > +               encoder_ptr = (uint32_t __user *)(unsigned long)(out_resp->encoders_ptr);
> > +               for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
> > +                       if (connector->encoder_ids[i] != 0) {
> > +                               if (put_user(connector->encoder_ids[i],
> > +                                            encoder_ptr + copied)) {
> > +                                       ret = -EFAULT;
> > +                                       goto out_unref;
> > +                               }
> > +                               copied++;
> > +                       }
> > +               }
> > +       }
> > +       out_resp->count_encoders = encoders_count;
> > +
> > +       out_resp->connector_id = connector->base.id;
> > +       out_resp->connector_type = connector->connector_type;
> > +       out_resp->connector_type_id = connector->connector_type_id;
> > +
> > +       mutex_lock(&dev->mode_config.mutex);
> >         if (out_resp->count_modes == 0) {
> >                 connector->funcs->fill_modes(connector,
> >                                              dev->mode_config.max_width,
> >                                              dev->mode_config.max_height);
> >         }
> >
> > -       /* delayed so we get modes regardless of pre-fill_modes state */
> > -       list_for_each_entry(mode, &connector->modes, head)
> > -               if (drm_mode_expose_to_userspace(mode, file_priv))
> > -                       mode_count++;
> > -
> > -       out_resp->connector_id = connector->base.id;
> > -       out_resp->connector_type = connector->connector_type;
> > -       out_resp->connector_type_id = connector->connector_type_id;
> >         out_resp->mm_width = connector->display_info.width_mm;
> >         out_resp->mm_height = connector->display_info.height_mm;
> >         out_resp->subpixel = connector->display_info.subpixel_order;
> >         out_resp->connection = connector->status;
> >
> > -       drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
> > -       encoder = drm_connector_get_encoder(connector);
> > -       if (encoder)
> > -               out_resp->encoder_id = encoder->base.id;
> > -       else
> > -               out_resp->encoder_id = 0;
> > +       /* delayed so we get modes regardless of pre-fill_modes state */
> > +       list_for_each_entry(mode, &connector->modes, head)
> > +               if (drm_mode_expose_to_userspace(mode, file_priv))
> > +                       mode_count++;
> >
> >         /*
> >          * This ioctl is called twice, once to determine how much space is
> > @@ -1219,36 +1241,10 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
> >                 }
> >         }
> >         out_resp->count_modes = mode_count;
> > -
> > -       ret = drm_mode_object_get_properties(&connector->base, file_priv->atomic,
> > -                       (uint32_t __user *)(unsigned long)(out_resp->props_ptr),
> > -                       (uint64_t __user *)(unsigned long)(out_resp->prop_values_ptr),
> > -                       &out_resp->count_props);
> > -       if (ret)
> > -               goto out;
> > -
> > -       if ((out_resp->count_encoders >= encoders_count) && encoders_count) {
> > -               copied = 0;
> > -               encoder_ptr = (uint32_t __user *)(unsigned long)(out_resp->encoders_ptr);
> > -               for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
> > -                       if (connector->encoder_ids[i] != 0) {
> > -                               if (put_user(connector->encoder_ids[i],
> > -                                            encoder_ptr + copied)) {
> > -                                       ret = -EFAULT;
> > -                                       goto out;
> > -                               }
> > -                               copied++;
> > -                       }
> > -               }
> > -       }
> > -       out_resp->count_encoders = encoders_count;
> > -
> >  out:
> > -       drm_modeset_unlock(&dev->mode_config.connection_mutex);
> > -
> > -       drm_connector_unreference(connector);
> > -out_unlock:
> >         mutex_unlock(&dev->mode_config.mutex);
> > +out_unref:
> > +       drm_connector_unreference(connector);
> >
> >         return ret;
> >  }
> > diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
> > index a24559ef8bb7..9af4141165d3 100644
> > --- a/include/drm/drm_connector.h
> > +++ b/include/drm/drm_connector.h
> > @@ -559,9 +559,6 @@ struct drm_cmdline_mode {
> >   * @interlace_allowed: can this connector handle interlaced modes?
> >   * @doublescan_allowed: can this connector handle doublescan?
> >   * @stereo_allowed: can this connector handle stereo modes?
> > - * @modes: modes available on this connector (from fill_modes() + user)
> > - * @status: one of the drm_connector_status enums (connected, not, or unknown)
> > - * @probed_modes: list of modes derived directly from the display
> >   * @funcs: connector control functions
> >   * @edid_blob_ptr: DRM property containing EDID if present
> >   * @properties: property tracking for this connector
> > @@ -631,11 +628,27 @@ struct drm_connector {
> >          * Protected by @mutex.
> >          */
> >         bool registered;
> > +
> > +       /**
> > +        * @modes:
> > +        * Modes available on this connector (from fill_modes() + user).
> > +        * Protected by dev->mode_config.mutex.
> > +        */
> >         struct list_head modes; /* list of modes on this connector */
> >
> > +       /**
> > +        * @status:
> > +        * One of the drm_connector_status enums (connected, not, or unknown).
> > +        * Protected by dev->mode_config.mutex.
> > +        */
> >         enum drm_connector_status status;
> >
> > -       /* these are modes added by probing with DDC or the BIOS */
> > +       /**
> > +        * @probed_modes:
> > +        * These are modes added by probing with DDC or the BIOS, before
> > +        * filtering is applied. Used by the probe helpers.Protected by
> > +        * dev->mode_config.mutex.
> > +        */
> >         struct list_head probed_modes;
> >
> >         /**
> > @@ -644,6 +657,8 @@ struct drm_connector {
> >          * flat panels in embedded systems, the driver should initialize the
> >          * display_info.width_mm and display_info.height_mm fields with the
> >          * physical size of the display.
> > +        *
> > +        * Protected by dev->mode_config.mutex.
> >          */
> >         struct drm_display_info display_info;
> >         const struct drm_connector_funcs *funcs;
> > --
> > 2.11.0
> >
> > _______________________________________________
> > dri-devel mailing list
> > dri-devel@lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/dri-devel
> 
> 
> 
> -- 
> Sean Paul, Software Engineer, Google / Chromium OS
diff mbox

Patch

diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index 0d4728704099..44b556d5d40c 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -1160,43 +1160,65 @@  int drm_mode_getconnector(struct drm_device *dev, void *data,
 
 	memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo));
 
-	mutex_lock(&dev->mode_config.mutex);
-
 	connector = drm_connector_lookup(dev, out_resp->connector_id);
-	if (!connector) {
-		ret = -ENOENT;
-		goto out_unlock;
-	}
+	if (!connector)
+		return -ENOENT;
+
+	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
+	encoder = drm_connector_get_encoder(connector);
+	if (encoder)
+		out_resp->encoder_id = encoder->base.id;
+	else
+		out_resp->encoder_id = 0;
+
+	ret = drm_mode_object_get_properties(&connector->base, file_priv->atomic,
+			(uint32_t __user *)(unsigned long)(out_resp->props_ptr),
+			(uint64_t __user *)(unsigned long)(out_resp->prop_values_ptr),
+			&out_resp->count_props);
+	drm_modeset_unlock(&dev->mode_config.connection_mutex);
+	if (ret)
+		goto out_unref;
 
 	for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++)
 		if (connector->encoder_ids[i] != 0)
 			encoders_count++;
 
+	if ((out_resp->count_encoders >= encoders_count) && encoders_count) {
+		copied = 0;
+		encoder_ptr = (uint32_t __user *)(unsigned long)(out_resp->encoders_ptr);
+		for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
+			if (connector->encoder_ids[i] != 0) {
+				if (put_user(connector->encoder_ids[i],
+					     encoder_ptr + copied)) {
+					ret = -EFAULT;
+					goto out_unref;
+				}
+				copied++;
+			}
+		}
+	}
+	out_resp->count_encoders = encoders_count;
+
+	out_resp->connector_id = connector->base.id;
+	out_resp->connector_type = connector->connector_type;
+	out_resp->connector_type_id = connector->connector_type_id;
+
+	mutex_lock(&dev->mode_config.mutex);
 	if (out_resp->count_modes == 0) {
 		connector->funcs->fill_modes(connector,
 					     dev->mode_config.max_width,
 					     dev->mode_config.max_height);
 	}
 
-	/* delayed so we get modes regardless of pre-fill_modes state */
-	list_for_each_entry(mode, &connector->modes, head)
-		if (drm_mode_expose_to_userspace(mode, file_priv))
-			mode_count++;
-
-	out_resp->connector_id = connector->base.id;
-	out_resp->connector_type = connector->connector_type;
-	out_resp->connector_type_id = connector->connector_type_id;
 	out_resp->mm_width = connector->display_info.width_mm;
 	out_resp->mm_height = connector->display_info.height_mm;
 	out_resp->subpixel = connector->display_info.subpixel_order;
 	out_resp->connection = connector->status;
 
-	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
-	encoder = drm_connector_get_encoder(connector);
-	if (encoder)
-		out_resp->encoder_id = encoder->base.id;
-	else
-		out_resp->encoder_id = 0;
+	/* delayed so we get modes regardless of pre-fill_modes state */
+	list_for_each_entry(mode, &connector->modes, head)
+		if (drm_mode_expose_to_userspace(mode, file_priv))
+			mode_count++;
 
 	/*
 	 * This ioctl is called twice, once to determine how much space is
@@ -1219,36 +1241,10 @@  int drm_mode_getconnector(struct drm_device *dev, void *data,
 		}
 	}
 	out_resp->count_modes = mode_count;
-
-	ret = drm_mode_object_get_properties(&connector->base, file_priv->atomic,
-			(uint32_t __user *)(unsigned long)(out_resp->props_ptr),
-			(uint64_t __user *)(unsigned long)(out_resp->prop_values_ptr),
-			&out_resp->count_props);
-	if (ret)
-		goto out;
-
-	if ((out_resp->count_encoders >= encoders_count) && encoders_count) {
-		copied = 0;
-		encoder_ptr = (uint32_t __user *)(unsigned long)(out_resp->encoders_ptr);
-		for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
-			if (connector->encoder_ids[i] != 0) {
-				if (put_user(connector->encoder_ids[i],
-					     encoder_ptr + copied)) {
-					ret = -EFAULT;
-					goto out;
-				}
-				copied++;
-			}
-		}
-	}
-	out_resp->count_encoders = encoders_count;
-
 out:
-	drm_modeset_unlock(&dev->mode_config.connection_mutex);
-
-	drm_connector_unreference(connector);
-out_unlock:
 	mutex_unlock(&dev->mode_config.mutex);
+out_unref:
+	drm_connector_unreference(connector);
 
 	return ret;
 }
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index a24559ef8bb7..9af4141165d3 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -559,9 +559,6 @@  struct drm_cmdline_mode {
  * @interlace_allowed: can this connector handle interlaced modes?
  * @doublescan_allowed: can this connector handle doublescan?
  * @stereo_allowed: can this connector handle stereo modes?
- * @modes: modes available on this connector (from fill_modes() + user)
- * @status: one of the drm_connector_status enums (connected, not, or unknown)
- * @probed_modes: list of modes derived directly from the display
  * @funcs: connector control functions
  * @edid_blob_ptr: DRM property containing EDID if present
  * @properties: property tracking for this connector
@@ -631,11 +628,27 @@  struct drm_connector {
 	 * Protected by @mutex.
 	 */
 	bool registered;
+
+	/**
+	 * @modes:
+	 * Modes available on this connector (from fill_modes() + user).
+	 * Protected by dev->mode_config.mutex.
+	 */
 	struct list_head modes; /* list of modes on this connector */
 
+	/**
+	 * @status:
+	 * One of the drm_connector_status enums (connected, not, or unknown).
+	 * Protected by dev->mode_config.mutex.
+	 */
 	enum drm_connector_status status;
 
-	/* these are modes added by probing with DDC or the BIOS */
+	/**
+	 * @probed_modes:
+	 * These are modes added by probing with DDC or the BIOS, before
+	 * filtering is applied. Used by the probe helpers.Protected by
+	 * dev->mode_config.mutex.
+	 */
 	struct list_head probed_modes;
 
 	/**
@@ -644,6 +657,8 @@  struct drm_connector {
 	 * flat panels in embedded systems, the driver should initialize the
 	 * display_info.width_mm and display_info.height_mm fields with the
 	 * physical size of the display.
+	 *
+	 * Protected by dev->mode_config.mutex.
 	 */
 	struct drm_display_info display_info;
 	const struct drm_connector_funcs *funcs;