drm/nouveau/core: prepare for new-style objects
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
parent
6cf813fb26
commit
524bdbf202
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 *);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
handle->parent = parent;
|
||||
nvkm_object_ref(object, &handle->object);
|
||||
|
||||
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);
|
||||
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;
|
||||
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->parent = nvkm_namedb_get(nv_namedb(namedb), _parent);
|
||||
if (handle->parent) {
|
||||
list_add(&handle->head, &handle->parent->tree);
|
||||
nvkm_namedb_put(handle->parent);
|
||||
handle->priv = ret;
|
||||
}
|
||||
|
||||
list_add(&handle->head, &handle->parent->tree);
|
||||
}
|
||||
|
||||
hprintk(handle, TRACE, "created\n");
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
|
||||
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;
|
||||
}
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue