summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/nouveau/nvkm/core
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2015-08-20 14:54:17 +1000
committerBen Skeggs <bskeggs@redhat.com>2015-08-28 12:40:35 +1000
commit524bdbf2025d44cdea672511d21012a52b427374 (patch)
tree95feb6e887043e3ac5a60763379b8f8a11dbb0ca /drivers/gpu/drm/nouveau/nvkm/core
parent6cf813fb26640ef539051fb7f965af8c9ff10d92 (diff)
drm/nouveau/core: prepare for new-style objects
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/core')
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/client.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/engctx.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/handle.c48
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/ioctl.c111
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/namedb.c8
5 files changed, 129 insertions, 43 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/client.c b/drivers/gpu/drm/nouveau/nvkm/core/client.c
index bfe5357d7334..9a7c4bc24a76 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/client.c
+++ b/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;
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/engctx.c b/drivers/gpu/drm/nouveau/nvkm/core/engctx.c
index c9c578749338..be640fd24f77 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/engctx.c
+++ b/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);
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/handle.c b/drivers/gpu/drm/nouveau/nvkm/core/handle.c
index a12ab8001701..0c7cde900df6 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/handle.c
+++ b/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");
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c b/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c
index d9c26e40ae32..b9c813690433 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c
+++ b/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:
@@ -188,6 +198,81 @@ fail_class:
}
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)
{
struct nvkm_object *object = handle->object;
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/namedb.c b/drivers/gpu/drm/nouveau/nvkm/core/namedb.c
index ca625c527c57..9be1ce967034 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/namedb.c
+++ b/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);
}