[PATCH 15/16] drm: keep track of which node holds which resource
Ilija Hadzic
ihadzic at research.bell-labs.com
Thu Mar 29 09:41:37 PDT 2012
Add fields to drm_crtc, drm_encoder and drm_connector 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.
Signed-off-by: Ilija Hadzic <ihadzic at research.bell-labs.com>
---
drivers/gpu/drm/drm_crtc.c | 3 +
drivers/gpu/drm/drm_stub.c | 104 ++++++++++++++++++++++++++++++++++++++++++++
include/drm/drm_crtc.h | 4 ++
3 files changed, 111 insertions(+), 0 deletions(-)
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 9af822b..199ef94 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;
diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
index 5b6459f..b025ad8 100644
--- a/drivers/gpu/drm/drm_stub.c
+++ b/drivers/gpu/drm/drm_stub.c
@@ -446,6 +446,90 @@ 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;
+
+ 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;
+ 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;
@@ -474,10 +558,18 @@ 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;
+ 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);
@@ -493,8 +585,16 @@ 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;
+ 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);
@@ -649,6 +749,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 86f4d9a..d4e6a8e 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;
--
1.7.8.5
More information about the dri-devel
mailing list