Browse Source

drm/nouveau/core: prepare for new-style objects

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Ben Skeggs 10 years ago
parent
commit
524bdbf202

+ 5 - 6
drivers/gpu/drm/nouveau/include/nvkm/core/client.h

@@ -23,13 +23,12 @@ void nvkm_client_remove(struct nvkm_client *, struct nvkm_handle *);
 struct nvkm_handle *nvkm_client_search(struct nvkm_client *, u64 handle);
 
 static inline struct nvkm_client *
-nvkm_client(void *obj)
+nvkm_client(struct nvkm_object *object)
 {
-	struct nvkm_object *client = nv_object(obj);
-	while (client && client->parent)
-		client = client->parent;
-	if (client && nv_iclass(client, NV_CLIENT_CLASS))
-		return (void *)client;
+	while (object && object->parent)
+		object = object->parent;
+	if (object && nv_iclass(object, NV_CLIENT_CLASS))
+		return container_of(object, struct nvkm_client, namedb.parent.object);
 	return NULL;
 }
 

+ 1 - 1
drivers/gpu/drm/nouveau/include/nvkm/core/handle.h

@@ -22,7 +22,7 @@ struct nvkm_handle {
 	u64 handle;
 };
 
-int  nvkm_handle_create(struct nvkm_object *, u32 parent, u32 handle,
+int  nvkm_handle_create(struct nvkm_handle *, u32 handle,
 			struct nvkm_object *, struct nvkm_handle **);
 void nvkm_handle_destroy(struct nvkm_handle *);
 int  nvkm_handle_init(struct nvkm_handle *);

+ 1 - 2
drivers/gpu/drm/nouveau/nvkm/core/client.c

@@ -294,8 +294,7 @@ nvkm_client_new(const char *name, u64 device, const char *cfg,
 	if (ret)
 		return ret;
 
-	ret = nvkm_handle_create(nv_object(client), ~0, ~0, nv_object(client),
-				 &client->root);
+	ret = nvkm_handle_create(NULL, ~0, nv_object(client), &client->root);
 	if (ret)
 		return ret;
 

+ 1 - 1
drivers/gpu/drm/nouveau/nvkm/core/engctx.c

@@ -104,7 +104,7 @@ void
 nvkm_engctx_destroy(struct nvkm_engctx *engctx)
 {
 	struct nvkm_engine *engine = engctx->gpuobj.object.engine;
-	struct nvkm_client *client = nvkm_client(engctx);
+	struct nvkm_client *client = nvkm_client(&engctx->gpuobj.object);
 	unsigned long save;
 
 	nvkm_gpuobj_unmap(&engctx->vma);

+ 24 - 24
drivers/gpu/drm/nouveau/nvkm/core/handle.c

@@ -94,15 +94,15 @@ fail:
 }
 
 int
-nvkm_handle_create(struct nvkm_object *parent, u32 _parent, u32 _handle,
+nvkm_handle_create(struct nvkm_handle *parent, u32 _handle,
 		   struct nvkm_object *object, struct nvkm_handle **phandle)
 {
 	struct nvkm_object *namedb;
 	struct nvkm_handle *handle;
 	int ret;
 
-	namedb = parent;
-	while (!nv_iclass(namedb, NV_NAMEDB_CLASS))
+	namedb = parent ? parent->object : NULL;
+	while (namedb && !nv_iclass(namedb, NV_NAMEDB_CLASS))
 		namedb = namedb->parent;
 
 	handle = kzalloc(sizeof(*handle), GFP_KERNEL);
@@ -114,32 +114,32 @@ nvkm_handle_create(struct nvkm_object *parent, u32 _parent, u32 _handle,
 	handle->name = _handle;
 	handle->priv = ~0;
 	RB_CLEAR_NODE(&handle->rb);
-
-	ret = nvkm_namedb_insert(nv_namedb(namedb), _handle, object, handle);
-	if (ret) {
-		kfree(handle);
-		return ret;
-	}
-
-	if (nv_parent(parent)->object_attach) {
-		ret = nv_parent(parent)->object_attach(parent, object, _handle);
-		if (ret < 0) {
-			nvkm_handle_destroy(handle);
+	handle->parent = parent;
+	nvkm_object_ref(object, &handle->object);
+
+	if (namedb) {
+		ret = nvkm_namedb_insert(nv_namedb(namedb), _handle,
+					 object, handle);
+		if (ret) {
+			kfree(handle);
 			return ret;
 		}
-
-		handle->priv = ret;
 	}
 
-	if (object != namedb) {
-		while (!nv_iclass(namedb, NV_CLIENT_CLASS))
-			namedb = namedb->parent;
-
-		handle->parent = nvkm_namedb_get(nv_namedb(namedb), _parent);
-		if (handle->parent) {
-			list_add(&handle->head, &handle->parent->tree);
-			nvkm_namedb_put(handle->parent);
+	if (parent) {
+		if (nv_iclass(parent->object, NV_PARENT_CLASS) &&
+		    nv_parent(parent->object)->object_attach) {
+			ret = nv_parent(parent->object)->
+				object_attach(parent->object, object, _handle);
+			if (ret < 0) {
+				nvkm_handle_destroy(handle);
+				return ret;
+			}
+
+			handle->priv = ret;
 		}
+
+		list_add(&handle->head, &handle->parent->tree);
 	}
 
 	hprintk(handle, TRACE, "created\n");

+ 98 - 13
drivers/gpu/drm/nouveau/nvkm/core/ioctl.c

@@ -55,34 +55,45 @@ nvkm_ioctl_sclass(struct nvkm_handle *handle, void *data, u32 size)
 	union {
 		struct nvif_ioctl_sclass_v0 v0;
 	} *args = data;
-	int ret;
+	struct nvkm_oclass oclass;
+	int ret, i = 0;
 
 	nvif_ioctl(object, "sclass size %d\n", size);
 	if (nvif_unpack(args->v0, 0, 0, true)) {
 		nvif_ioctl(object, "sclass vers %d count %d\n",
 			   args->v0.version, args->v0.count);
-		if (size == args->v0.count * sizeof(args->v0.oclass[0])) {
+		if (size != args->v0.count * sizeof(args->v0.oclass[0]))
+			return -EINVAL;
+
+		if (object->oclass) {
 			if (nv_iclass(object, NV_PARENT_CLASS)) {
 				ret = nvkm_parent_lclass(object,
 							 args->v0.oclass,
 							 args->v0.count);
-			} else {
-				ret = 0;
 			}
-			if (ret >= 0) {
-				args->v0.count = ret;
-				ret = 0;
+
+			args->v0.count = ret;
+			return 0;
+		}
+
+		while (object->func->sclass &&
+		       object->func->sclass(object, i, &oclass) >= 0) {
+			if (i < args->v0.count) {
+				args->v0.oclass[i].oclass = oclass.base.oclass;
+				args->v0.oclass[i].minver = oclass.base.minver;
+				args->v0.oclass[i].maxver = oclass.base.maxver;
 			}
-		} else {
-			ret = -EINVAL;
+			i++;
 		}
+
+		args->v0.count = i;
 	}
 
 	return ret;
 }
 
 static int
-nvkm_ioctl_new(struct nvkm_handle *handle, void *data, u32 size)
+nvkm_ioctl_new_old(struct nvkm_handle *handle, void *data, u32 size)
 {
 	union {
 		struct nvif_ioctl_new_v0 v0;
@@ -152,7 +163,6 @@ nvkm_ioctl_new(struct nvkm_handle *handle, void *data, u32 size)
 	/* finally, create new object and bind it to its handle */
 	ret = nvkm_object_old(engctx, &engine->subdev.object, oclass,
 			      data, size, &object);
-	client->data = object;
 	if (ret)
 		goto fail_ctor;
 
@@ -162,8 +172,7 @@ nvkm_ioctl_new(struct nvkm_handle *handle, void *data, u32 size)
 	if (ret)
 		goto fail_init;
 
-	ret = nvkm_handle_create(&parent->object, handle->name,
-				 _handle, object, &handle);
+	ret = nvkm_handle_create(handle, _handle, object, &handle);
 	if (ret)
 		goto fail_handle;
 
@@ -175,6 +184,7 @@ nvkm_ioctl_new(struct nvkm_handle *handle, void *data, u32 size)
 
 	handle->handle = args->v0.object;
 	nvkm_client_insert(client, handle);
+	client->data = object;
 fail_handle:
 	nvkm_object_dec(object, false);
 fail_init:
@@ -187,6 +197,81 @@ fail_class:
 	return ret;
 }
 
+static int
+nvkm_ioctl_new(struct nvkm_handle *handle, void *data, u32 size)
+{
+	union {
+		struct nvif_ioctl_new_v0 v0;
+	} *args = data;
+	struct nvkm_client *client = handle->object->client;
+	struct nvkm_object *parent = handle->object;
+	struct nvkm_object *object = NULL;
+	struct nvkm_oclass oclass;
+	int ret, i = 0;
+
+	if (parent->oclass)
+		return nvkm_ioctl_new_old(handle, data, size);
+
+	nvif_ioctl(parent, "new size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, true)) {
+		nvif_ioctl(parent, "new vers %d handle %08x class %08x "
+				   "route %02x token %llx object %016llx\n",
+			   args->v0.version, args->v0.handle, args->v0.oclass,
+			   args->v0.route, args->v0.token, args->v0.object);
+	} else
+		return ret;
+
+	if (!parent->func->sclass) {
+		nvif_ioctl(parent, "cannot have children\n");
+		return -EINVAL;
+	}
+
+	do {
+		memset(&oclass, 0x00, sizeof(oclass));
+		oclass.client = client;
+		oclass.handle = args->v0.handle;
+		oclass.object = args->v0.object;
+		oclass.parent = parent;
+		ret = parent->func->sclass(parent, i++, &oclass);
+		if (ret)
+			return ret;
+	} while (oclass.base.oclass != args->v0.oclass);
+
+	if (oclass.engine) {
+		oclass.engine = nvkm_engine_ref(oclass.engine);
+		if (IS_ERR(oclass.engine))
+			return PTR_ERR(oclass.engine);
+	}
+
+	ret = oclass.ctor(&oclass, data, size, &object);
+	if (ret)
+		goto fail_object;
+
+	ret = nvkm_object_inc(object);
+	if (ret)
+		goto fail_object;
+
+	ret = nvkm_handle_create(handle, args->v0.handle, object, &handle);
+	if (ret)
+		goto fail_handle;
+
+	ret = nvkm_handle_init(handle);
+	handle->route = args->v0.route;
+	handle->token = args->v0.token;
+	if (ret)
+		nvkm_handle_destroy(handle);
+
+	handle->handle = args->v0.object;
+	nvkm_client_insert(client, handle);
+	client->data = object;
+fail_handle:
+	nvkm_object_dec(object, false);
+fail_object:
+	nvkm_object_ref(NULL, &object);
+	nvkm_engine_unref(&oclass.engine);
+	return ret;
+}
+
 static int
 nvkm_ioctl_del(struct nvkm_handle *handle, void *data, u32 size)
 {

+ 5 - 3
drivers/gpu/drm/nouveau/nvkm/core/namedb.c

@@ -104,9 +104,11 @@ nvkm_namedb_remove(struct nvkm_handle *handle)
 {
 	struct nvkm_namedb *namedb = handle->namedb;
 	struct nvkm_object *object = handle->object;
-	write_lock_irq(&namedb->lock);
-	list_del(&handle->node);
-	write_unlock_irq(&namedb->lock);
+	if (handle->namedb) {
+		write_lock_irq(&namedb->lock);
+		list_del(&handle->node);
+		write_unlock_irq(&namedb->lock);
+	}
 	nvkm_object_ref(NULL, &object);
 }