All of lore.kernel.org
 help / color / mirror / Atom feed
From: Daniel Vetter <daniel.vetter@ffwll.ch>
To: DRI Development <dri-devel@lists.freedesktop.org>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>,
	Intel Graphics Development <intel-gfx@lists.freedesktop.org>,
	Daniel Vetter <daniel.vetter@intel.com>
Subject: [PATCH 09/13] drm: Tighten locking in drm_mode_getconnector
Date: Wed, 14 Dec 2016 00:08:10 +0100	[thread overview]
Message-ID: <20161213230814.19598-10-daniel.vetter@ffwll.ch> (raw)
In-Reply-To: <20161213230814.19598-1-daniel.vetter@ffwll.ch>

- 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(-)

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

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

  parent reply	other threads:[~2016-12-13 23:08 UTC|newest]

Thread overview: 41+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-12-13 23:08 [PATCH 00/13] some stuff, and then connector_list locking Daniel Vetter
2016-12-13 23:08 ` [PATCH 01/13] drm/irq: drm_legacy_ prefix for legacy ioctls Daniel Vetter
2016-12-16 15:02   ` Sean Paul
2016-12-13 23:08 ` [PATCH 02/13] drm: Move atomic debugfs functions into drm_crtc_internal.h Daniel Vetter
2016-12-16 15:02   ` Sean Paul
2016-12-13 23:08 ` [PATCH 03/13] drm/radeon|amdgpu: Remove redundant num_connectors check Daniel Vetter
2016-12-14 16:59   ` Alex Deucher
2016-12-13 23:08 ` [PATCH 04/13] drm: Drop locking cargo-cult from drm_mode_config_init Daniel Vetter
2016-12-14  9:23   ` [Intel-gfx] " Daniel Stone
2016-12-16 15:03   ` Sean Paul
2016-12-13 23:08 ` [PATCH 05/13] drm: locking&new iterators for connector_list Daniel Vetter
2016-12-14  8:35   ` Chris Wilson
2016-12-14 11:22   ` Jani Nikula
2016-12-14 12:26     ` Daniel Vetter
2016-12-14 15:04       ` [Intel-gfx] " Jani Nikula
2016-12-16 15:03   ` Sean Paul
2016-12-13 23:08 ` [PATCH 06/13] drm: Convert all helpers to drm_connector_list_iter Daniel Vetter
2016-12-15 14:34   ` Harry Wentland
2016-12-15 15:58   ` [PATCH] " Daniel Vetter
2016-12-15 16:32     ` Harry Wentland
2016-12-15 22:47     ` kbuild test robot
2016-12-15 22:59     ` kbuild test robot
2016-12-16  7:29       ` Daniel Vetter
2016-12-16  7:41         ` [kbuild-all] " Fengguang Wu
2016-12-18 18:04           ` Ye Xiaolong
2016-12-16 15:03     ` Sean Paul
2016-12-13 23:08 ` [PATCH 07/13] drm: Clean up connectors by unreferencing them Daniel Vetter
2016-12-15 15:45   ` Harry Wentland
2016-12-16 15:03   ` Sean Paul
2016-12-13 23:08 ` [PATCH 08/13] drm: prevent double-(un)registration for connectors Daniel Vetter
2016-12-13 23:52   ` Chris Wilson
2016-12-16 15:03   ` Sean Paul
2016-12-13 23:08 ` Daniel Vetter [this message]
2016-12-16 15:03   ` [PATCH 09/13] drm: Tighten locking in drm_mode_getconnector Sean Paul
2016-12-18 13:40     ` Daniel Vetter
2016-12-13 23:08 ` [PATCH 10/13] drm/i915: Use drm_connector_list_iter in debugfs Daniel Vetter
2016-12-14 14:44   ` Jani Nikula
2016-12-14 14:51     ` [Intel-gfx] " Daniel Vetter
2016-12-13 23:08 ` [PATCH 11/13] drm/i915: use drm_connector_list_iter in intel_hotplug.c Daniel Vetter
2016-12-13 23:08 ` [PATCH 12/13] drm/i915: use drm_connector_list_iter in intel_opregion.c Daniel Vetter
2016-12-13 23:08 ` [PATCH 13/13] drm/i915: Make intel_get_pipe_from_connector atomic Daniel Vetter

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20161213230814.19598-10-daniel.vetter@ffwll.ch \
    --to=daniel.vetter@ffwll.ch \
    --cc=daniel.vetter@intel.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=intel-gfx@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.