All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ilija Hadzic <ihadzic@research.bell-labs.com>
To: dri-devel@lists.freedesktop.org
Subject: [PATCH 18/19] drm: keep track of which node holds which resource
Date: Thu, 12 Apr 2012 14:19:43 -0400	[thread overview]
Message-ID: <1334254784-3200-19-git-send-email-ihadzic@research.bell-labs.com> (raw)
In-Reply-To: <1334254784-3200-1-git-send-email-ihadzic@research.bell-labs.com>

Add fields to drm_crtc, drm_encoder, drm_connector, and drm_plane
that keep track of which render node owns it. Assign ownership
when resource is added and revoke it when resource is destroyed.
Do not allow creation of a node that tries to claim resources
that are already in use by another node.

v2: - track planes too

Signed-off-by: Ilija Hadzic <ihadzic@research.bell-labs.com>
---
 drivers/gpu/drm/drm_crtc.c |    4 ++
 drivers/gpu/drm/drm_stub.c |  111 ++++++++++++++++++++++++++++++++++++++++++++
 include/drm/drm_crtc.h     |    5 ++
 3 files changed, 120 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index cce3d25..45a2925 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -375,6 +375,7 @@ int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
 
 	crtc->dev = dev;
 	crtc->funcs = funcs;
+	crtc->render_node_owner = -1;
 
 	mutex_lock(&dev->mode_config.mutex);
 
@@ -483,6 +484,7 @@ int drm_connector_init(struct drm_device *dev,
 
 	connector->dev = dev;
 	connector->funcs = funcs;
+	connector->render_node_owner = -1;
 	connector->connector_type = connector_type;
 	connector->connector_type_id =
 		++drm_connector_enum_list[connector_type].count; /* TODO */
@@ -553,6 +555,7 @@ int drm_encoder_init(struct drm_device *dev,
 	if (ret)
 		goto out;
 
+	encoder->render_node_owner = -1;
 	encoder->dev = dev;
 	encoder->encoder_type = encoder_type;
 	encoder->funcs = funcs;
@@ -594,6 +597,7 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
 
 	plane->dev = dev;
 	plane->funcs = funcs;
+	plane->render_node_owner = -1;
 	plane->format_types = kmalloc(sizeof(uint32_t) * format_count,
 				      GFP_KERNEL);
 	if (!plane->format_types) {
diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
index 340a7e4..13ff4c8 100644
--- a/drivers/gpu/drm/drm_stub.c
+++ b/drivers/gpu/drm/drm_stub.c
@@ -447,6 +447,95 @@ static int drm_get_render_node_resources(struct drm_device *dev,
 	return 0;
 }
 
+static int *drm_get_render_node_owner(struct drm_device *dev,
+				      uint32_t id, uint32_t type)
+{
+	struct drm_mode_object *obj;
+	struct drm_crtc *crtc;
+	struct drm_encoder *encoder;
+	struct drm_connector *connector;
+	struct drm_plane *plane;
+
+	obj = drm_mode_object_find(dev, id, type);
+	if (!obj)
+		return NULL;
+	switch (type) {
+	case DRM_MODE_OBJECT_CRTC:
+		crtc = container_of(obj, struct drm_crtc, base);
+		return &crtc->render_node_owner;
+	case DRM_MODE_OBJECT_ENCODER:
+		encoder = container_of(obj, struct drm_encoder, base);
+		return &encoder->render_node_owner;
+	case DRM_MODE_OBJECT_CONNECTOR:
+		connector = container_of(obj, struct drm_connector, base);
+		return &connector->render_node_owner;
+	case DRM_MODE_OBJECT_PLANE:
+		plane = container_of(obj, struct drm_plane, base);
+		return &plane->render_node_owner;
+
+	default:
+		return NULL;
+	}
+}
+
+static void drm_release_render_node_resources(struct drm_device *dev,
+					      uint32_t *id_list,
+					      int *resource_count,
+					      int minor)
+{
+	int *render_node_owner;
+	int s, e, i, j;
+
+	for (e = 0, j = 0; j < DRM_RN_NUM_EXP_TYPES; j++) {
+		s = e;
+		e += resource_count[j];
+		for (i = s; i < e; i++) {
+			render_node_owner =
+				drm_get_render_node_owner(dev, id_list[i],
+					expected_type_list[j]);
+			if (render_node_owner &&
+			    *render_node_owner == minor)
+				*render_node_owner = -1;
+		}
+	}
+}
+
+static int drm_claim_render_node_resources(struct drm_device *dev,
+					   uint32_t *id_list,
+					   int *resource_count,
+					   int minor)
+{
+	int *render_node_owner;
+	int s, e, i, j;
+	int ret = 0;
+
+	for (e = 0, j = 0; j < DRM_RN_NUM_EXP_TYPES; j++) {
+		s = e;
+		e += resource_count[j];
+		for (i = s; i < e; i++) {
+			render_node_owner =
+				drm_get_render_node_owner(dev, id_list[i],
+					expected_type_list[j]);
+			if (!render_node_owner) {
+				/* list was validated, not supposed to fail */
+				WARN_ON(1);
+				ret = -EFAULT;
+				goto out_release;
+			}
+			if (*render_node_owner != -1) {
+				ret = -EBUSY;
+				goto out_release;
+			}
+			*render_node_owner = minor;
+		}
+	}
+	return ret;
+
+out_release:
+	drm_release_render_node_resources(dev, id_list, resource_count, minor);
+	return ret;
+}
+
 int drm_create_render_node(struct drm_device *dev, struct drm_minor **minor_p)
 {
 	int ret;
@@ -475,10 +564,19 @@ int drm_destroy_render_node(struct drm_device *dev, int index)
 	list_for_each_entry_safe(node, tmp, &dev->render_node_list, list) {
 		if (node->minor->index == index) {
 			struct drm_mode_group *group;
+			int resource_count[DRM_RN_NUM_EXP_TYPES];
+
 			if (node->minor->open_count)
 				return -EBUSY;
 			group = &node->minor->mode_group;
 			list_del(&node->list);
+			resource_count[0] = group->num_crtcs;
+			resource_count[1] = group->num_encoders;
+			resource_count[2] = group->num_connectors;
+			resource_count[3] = group->num_planes;
+			drm_release_render_node_resources(dev, group->id_list,
+							  resource_count,
+							  node->minor->index);
 			drm_put_minor(&node->minor);
 			drm_mode_group_fini(group);
 			kfree(node);
@@ -494,8 +592,17 @@ void drm_destroy_all_render_nodes(struct drm_device *dev)
 
 	list_for_each_entry_safe(node, tmp, &dev->render_node_list, list) {
 		struct drm_mode_group *group;
+		int resource_count[DRM_RN_NUM_EXP_TYPES];
+
 		group = &node->minor->mode_group;
 		list_del(&node->list);
+		resource_count[0] = group->num_crtcs;
+		resource_count[1] = group->num_encoders;
+		resource_count[2] = group->num_connectors;
+		resource_count[3] = group->num_planes;
+		drm_release_render_node_resources(dev, group->id_list,
+						  resource_count,
+						  node->minor->index);
 		drm_put_minor(&node->minor);
 		drm_mode_group_fini(group);
 		kfree(node);
@@ -652,6 +759,10 @@ int drm_render_node_create_ioctl(struct drm_device *dev, void *data,
 					    resource_count);
 	if (ret)
 		goto out_del;
+	ret = drm_claim_render_node_resources(dev, id_list, resource_count,
+					      new_minor->index);
+	if (ret)
+		goto out_del;
 	new_minor->mode_group.num_crtcs = args->num_crtc;
 	new_minor->mode_group.num_encoders = args->num_encoder;
 	new_minor->mode_group.num_connectors = args->num_connector;
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 7c1227b..c38635d 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -374,6 +374,7 @@ struct drm_crtc {
 	struct drm_framebuffer *fb;
 
 	bool enabled;
+	int render_node_owner;
 
 	/* Requested mode from modesetting. */
 	struct drm_display_mode mode;
@@ -479,6 +480,8 @@ struct drm_encoder {
 	uint32_t possible_crtcs;
 	uint32_t possible_clones;
 
+	int render_node_owner;
+
 	struct drm_crtc *crtc;
 	const struct drm_encoder_funcs *funcs;
 	void *helper_private;
@@ -556,6 +559,7 @@ struct drm_connector {
 	struct list_head modes; /* list of modes on this connector */
 
 	enum drm_connector_status status;
+	int render_node_owner;
 
 	/* these are modes added by probing with DDC or the BIOS */
 	struct list_head probed_modes;
@@ -641,6 +645,7 @@ struct drm_plane {
 	uint16_t *gamma_store;
 
 	bool enabled;
+	int render_node_owner;
 
 	const struct drm_plane_funcs *funcs;
 	void *helper_private;
-- 
1.7.8.5

  parent reply	other threads:[~2012-04-12 18:21 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-04-12 18:19 [RFC v2] Revive the work on render-nodes branch Ilija Hadzic
2012-04-12 18:19 ` [PATCH 01/19] drm: simplify dereferencing of node type Ilija Hadzic
2012-04-12 18:19 ` [PATCH 02/19] drm: track planes in drm_mode_group structure Ilija Hadzic
2012-04-12 18:19 ` [PATCH 03/19] drm: use drm_mode_group in drm_mode_getplane_res Ilija Hadzic
2012-04-12 18:19 ` [PATCH 04/19] drm: do not push inode down into drm_open_helper Ilija Hadzic
2012-04-12 18:19 ` [PATCH 05/19] drm: move dev_mapping to the minor node Ilija Hadzic
2012-04-20 10:04   ` Dave Airlie
2012-04-30 14:48     ` Ilija Hadzic
2012-04-30 16:39       ` Dave Airlie
2012-04-30 16:52         ` Ilija Hadzic
2012-04-30 17:53           ` Dave Airlie
2012-04-30 18:04             ` Dave Airlie
2012-05-15 20:48               ` Ilija Hadzic
2012-04-12 18:19 ` [PATCH 06/19] drm: add support for render nodes Ilija Hadzic
2012-04-12 18:19 ` [PATCH 07/19] drm: initial multiple nodes ioctl work Ilija Hadzic
2012-04-20 10:15   ` Dave Airlie
2012-04-12 18:19 ` [PATCH 08/19] drm: separate render node descriptor from minor Ilija Hadzic
2012-04-12 18:19 ` [PATCH 09/19] drm: cleanup render node ioctls Ilija Hadzic
2012-04-12 18:19 ` [PATCH 10/19] drm: only allow render node ioctls through control node Ilija Hadzic
2012-04-12 18:19 ` [PATCH 11/19] drm: do not remove a render node in use Ilija Hadzic
2012-04-12 18:19 ` [PATCH 12/19] drm: allocate correct id_list size for a render node Ilija Hadzic
2012-04-12 18:19 ` [PATCH 13/19] drm: add drm_mode_group_fini function Ilija Hadzic
2012-04-12 18:19 ` [PATCH 14/19] drm: properly free id_list when a render node is removed Ilija Hadzic
2012-04-12 18:19 ` [PATCH 15/19] drm: call drm_mode_group_fini on primary node Ilija Hadzic
2012-04-12 18:19 ` [PATCH 16/19] drm: more elaborate check for resource count Ilija Hadzic
2012-04-12 18:19 ` [PATCH 17/19] drm: validate id list when creating a render node Ilija Hadzic
2012-04-12 18:19 ` Ilija Hadzic [this message]
2012-04-12 18:19 ` [PATCH 19/19] drm: hold mutex in critical sections of render-node code Ilija Hadzic
2012-04-12 18:55 ` [RFC v2] Revive the work on render-nodes branch Ville Syrjälä
2012-04-12 19:09   ` Ilija Hadzic
2012-04-20 10:20 ` Dave Airlie
2012-04-20 13:46   ` Daniel Vetter
2012-04-30 15:16   ` Ilija Hadzic
2012-04-30 19:01   ` Kristian Høgsberg

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=1334254784-3200-19-git-send-email-ihadzic@research.bell-labs.com \
    --to=ihadzic@research.bell-labs.com \
    --cc=dri-devel@lists.freedesktop.org \
    --subject='Re: [PATCH 18/19] drm: keep track of which node holds which resource' \
    /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

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.