drm/nouveau/core: prepare for new-style objects
authorBen Skeggs <bskeggs@redhat.com>
Thu, 20 Aug 2015 04:54:17 +0000 (14:54 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Fri, 28 Aug 2015 02:40:35 +0000 (12:40 +1000)
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/include/nvkm/core/client.h
drivers/gpu/drm/nouveau/include/nvkm/core/handle.h
drivers/gpu/drm/nouveau/nvkm/core/client.c
drivers/gpu/drm/nouveau/nvkm/core/engctx.c
drivers/gpu/drm/nouveau/nvkm/core/handle.c
drivers/gpu/drm/nouveau/nvkm/core/ioctl.c
drivers/gpu/drm/nouveau/nvkm/core/namedb.c

index dd0db88f8213f14cbc4e33f78676ded24a04fcea..ff6331d7e9e67506c1536515221feb4bd06e8444 100644 (file)
@@ -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;
 }
 
index 64f9e62168ff219a97f08d94dec06a43b7aba1cc..88e8bb17a280ccec46f2cb653fb6e628d2956c43 100644 (file)
@@ -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 *);
index bfe5357d7334836209958c4320a72818a6edd67a..9a7c4bc24a767b53bb80521f59858c94738cddd7 100644 (file)
@@ -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;
 
index c9c57874933824484c7f8877451d847201d3a151..be640fd24f77b5dc64c480103c0cde782f216404 100644 (file)
@@ -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);
index a12ab800170187aea5e1958595776174ca7f651a..0c7cde900df608e998ed30c259fe483dd3a5fa3e 100644 (file)
@@ -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");
index d9c26e40ae320b33a44787baa7c17eeeb737404a..b9c81369043384ed6f35ce2972ea85decdd5bb5b 100644 (file)
@@ -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)
 {
index ca625c527c57ad7a155ad9627fc248925f58c02d..9be1ce9670346aaf3ad5dac78cda14a42419e463 100644 (file)
@@ -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);
 }