Commit 524bdbf2 authored by Ben Skeggs's avatar Ben Skeggs

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

Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 6cf813fb
...@@ -23,13 +23,12 @@ void nvkm_client_remove(struct nvkm_client *, struct nvkm_handle *); ...@@ -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); struct nvkm_handle *nvkm_client_search(struct nvkm_client *, u64 handle);
static inline struct nvkm_client * static inline struct nvkm_client *
nvkm_client(void *obj) nvkm_client(struct nvkm_object *object)
{ {
struct nvkm_object *client = nv_object(obj); while (object && object->parent)
while (client && client->parent) object = object->parent;
client = client->parent; if (object && nv_iclass(object, NV_CLIENT_CLASS))
if (client && nv_iclass(client, NV_CLIENT_CLASS)) return container_of(object, struct nvkm_client, namedb.parent.object);
return (void *)client;
return NULL; return NULL;
} }
......
...@@ -22,7 +22,7 @@ struct nvkm_handle { ...@@ -22,7 +22,7 @@ struct nvkm_handle {
u64 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 **); struct nvkm_object *, struct nvkm_handle **);
void nvkm_handle_destroy(struct nvkm_handle *); void nvkm_handle_destroy(struct nvkm_handle *);
int nvkm_handle_init(struct nvkm_handle *); int nvkm_handle_init(struct nvkm_handle *);
......
...@@ -294,8 +294,7 @@ nvkm_client_new(const char *name, u64 device, const char *cfg, ...@@ -294,8 +294,7 @@ nvkm_client_new(const char *name, u64 device, const char *cfg,
if (ret) if (ret)
return ret; return ret;
ret = nvkm_handle_create(nv_object(client), ~0, ~0, nv_object(client), ret = nvkm_handle_create(NULL, ~0, nv_object(client), &client->root);
&client->root);
if (ret) if (ret)
return ret; return ret;
......
...@@ -104,7 +104,7 @@ void ...@@ -104,7 +104,7 @@ void
nvkm_engctx_destroy(struct nvkm_engctx *engctx) nvkm_engctx_destroy(struct nvkm_engctx *engctx)
{ {
struct nvkm_engine *engine = engctx->gpuobj.object.engine; 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; unsigned long save;
nvkm_gpuobj_unmap(&engctx->vma); nvkm_gpuobj_unmap(&engctx->vma);
......
...@@ -94,15 +94,15 @@ nvkm_handle_fini(struct nvkm_handle *handle, bool suspend) ...@@ -94,15 +94,15 @@ nvkm_handle_fini(struct nvkm_handle *handle, bool suspend)
} }
int 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 *object, struct nvkm_handle **phandle)
{ {
struct nvkm_object *namedb; struct nvkm_object *namedb;
struct nvkm_handle *handle; struct nvkm_handle *handle;
int ret; int ret;
namedb = parent; namedb = parent ? parent->object : NULL;
while (!nv_iclass(namedb, NV_NAMEDB_CLASS)) while (namedb && !nv_iclass(namedb, NV_NAMEDB_CLASS))
namedb = namedb->parent; namedb = namedb->parent;
handle = kzalloc(sizeof(*handle), GFP_KERNEL); handle = kzalloc(sizeof(*handle), GFP_KERNEL);
...@@ -114,32 +114,32 @@ nvkm_handle_create(struct nvkm_object *parent, u32 _parent, u32 _handle, ...@@ -114,32 +114,32 @@ nvkm_handle_create(struct nvkm_object *parent, u32 _parent, u32 _handle,
handle->name = _handle; handle->name = _handle;
handle->priv = ~0; handle->priv = ~0;
RB_CLEAR_NODE(&handle->rb); RB_CLEAR_NODE(&handle->rb);
handle->parent = parent;
ret = nvkm_namedb_insert(nv_namedb(namedb), _handle, object, handle); nvkm_object_ref(object, &handle->object);
if (ret) {
kfree(handle); if (namedb) {
return ret; ret = nvkm_namedb_insert(nv_namedb(namedb), _handle,
} object, handle);
if (ret) {
if (nv_parent(parent)->object_attach) { kfree(handle);
ret = nv_parent(parent)->object_attach(parent, object, _handle);
if (ret < 0) {
nvkm_handle_destroy(handle);
return ret; return ret;
} }
handle->priv = ret;
} }
if (object != namedb) { if (parent) {
while (!nv_iclass(namedb, NV_CLIENT_CLASS)) if (nv_iclass(parent->object, NV_PARENT_CLASS) &&
namedb = namedb->parent; nv_parent(parent->object)->object_attach) {
ret = nv_parent(parent->object)->
handle->parent = nvkm_namedb_get(nv_namedb(namedb), _parent); object_attach(parent->object, object, _handle);
if (handle->parent) { if (ret < 0) {
list_add(&handle->head, &handle->parent->tree); nvkm_handle_destroy(handle);
nvkm_namedb_put(handle->parent); return ret;
}
handle->priv = ret;
} }
list_add(&handle->head, &handle->parent->tree);
} }
hprintk(handle, TRACE, "created\n"); hprintk(handle, TRACE, "created\n");
......
...@@ -55,34 +55,45 @@ nvkm_ioctl_sclass(struct nvkm_handle *handle, void *data, u32 size) ...@@ -55,34 +55,45 @@ nvkm_ioctl_sclass(struct nvkm_handle *handle, void *data, u32 size)
union { union {
struct nvif_ioctl_sclass_v0 v0; struct nvif_ioctl_sclass_v0 v0;
} *args = data; } *args = data;
int ret; struct nvkm_oclass oclass;
int ret, i = 0;
nvif_ioctl(object, "sclass size %d\n", size); nvif_ioctl(object, "sclass size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, true)) { if (nvif_unpack(args->v0, 0, 0, true)) {
nvif_ioctl(object, "sclass vers %d count %d\n", nvif_ioctl(object, "sclass vers %d count %d\n",
args->v0.version, args->v0.count); 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)) { if (nv_iclass(object, NV_PARENT_CLASS)) {
ret = nvkm_parent_lclass(object, ret = nvkm_parent_lclass(object,
args->v0.oclass, args->v0.oclass,
args->v0.count); args->v0.count);
} else {
ret = 0;
} }
if (ret >= 0) {
args->v0.count = ret; args->v0.count = ret;
ret = 0; 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 { i++;
ret = -EINVAL;
} }
args->v0.count = i;
} }
return ret; return ret;
} }
static int 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 { union {
struct nvif_ioctl_new_v0 v0; struct nvif_ioctl_new_v0 v0;
...@@ -152,7 +163,6 @@ nvkm_ioctl_new(struct nvkm_handle *handle, void *data, u32 size) ...@@ -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 */ /* finally, create new object and bind it to its handle */
ret = nvkm_object_old(engctx, &engine->subdev.object, oclass, ret = nvkm_object_old(engctx, &engine->subdev.object, oclass,
data, size, &object); data, size, &object);
client->data = object;
if (ret) if (ret)
goto fail_ctor; goto fail_ctor;
...@@ -162,8 +172,7 @@ nvkm_ioctl_new(struct nvkm_handle *handle, void *data, u32 size) ...@@ -162,8 +172,7 @@ nvkm_ioctl_new(struct nvkm_handle *handle, void *data, u32 size)
if (ret) if (ret)
goto fail_init; goto fail_init;
ret = nvkm_handle_create(&parent->object, handle->name, ret = nvkm_handle_create(handle, _handle, object, &handle);
_handle, object, &handle);
if (ret) if (ret)
goto fail_handle; goto fail_handle;
...@@ -175,6 +184,7 @@ nvkm_ioctl_new(struct nvkm_handle *handle, void *data, u32 size) ...@@ -175,6 +184,7 @@ nvkm_ioctl_new(struct nvkm_handle *handle, void *data, u32 size)
handle->handle = args->v0.object; handle->handle = args->v0.object;
nvkm_client_insert(client, handle); nvkm_client_insert(client, handle);
client->data = object;
fail_handle: fail_handle:
nvkm_object_dec(object, false); nvkm_object_dec(object, false);
fail_init: fail_init:
...@@ -187,6 +197,81 @@ nvkm_ioctl_new(struct nvkm_handle *handle, void *data, u32 size) ...@@ -187,6 +197,81 @@ nvkm_ioctl_new(struct nvkm_handle *handle, void *data, u32 size)
return ret; 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 static int
nvkm_ioctl_del(struct nvkm_handle *handle, void *data, u32 size) nvkm_ioctl_del(struct nvkm_handle *handle, void *data, u32 size)
{ {
......
...@@ -104,9 +104,11 @@ nvkm_namedb_remove(struct nvkm_handle *handle) ...@@ -104,9 +104,11 @@ nvkm_namedb_remove(struct nvkm_handle *handle)
{ {
struct nvkm_namedb *namedb = handle->namedb; struct nvkm_namedb *namedb = handle->namedb;
struct nvkm_object *object = handle->object; struct nvkm_object *object = handle->object;
write_lock_irq(&namedb->lock); if (handle->namedb) {
list_del(&handle->node); write_lock_irq(&namedb->lock);
write_unlock_irq(&namedb->lock); list_del(&handle->node);
write_unlock_irq(&namedb->lock);
}
nvkm_object_ref(NULL, &object); nvkm_object_ref(NULL, &object);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment