From: Ben Skeggs Date: Thu, 22 Dec 2016 05:22:25 +0000 (+1000) Subject: drm/nouveau/core/object: support lookup of specific object types X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=110cccff955313c66dccd2817f62368f106d9bf2;p=GitHub%2FLineageOS%2Fandroid_kernel_motorola_exynos9610.git drm/nouveau/core/object: support lookup of specific object types It turns out we have a nice and convenient way of looking up a specific object type already, by using the func pointer as a key. This will be used to remove the separate object trees for each type we need to be able to search for. Signed-off-by: Ben Skeggs --- diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/object.h b/drivers/gpu/drm/nouveau/include/nvkm/core/object.h index dcd048b91fac..96dda350ada3 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/object.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/object.h @@ -62,6 +62,11 @@ int nvkm_object_wr32(struct nvkm_object *, u64 addr, u32 data); int nvkm_object_bind(struct nvkm_object *, struct nvkm_gpuobj *, int align, struct nvkm_gpuobj **); +bool nvkm_object_insert(struct nvkm_object *); +void nvkm_object_remove(struct nvkm_object *); +struct nvkm_object *nvkm_object_search(struct nvkm_client *, u64 object, + const struct nvkm_object_func *); + struct nvkm_sclass { int minver; int maxver; diff --git a/drivers/gpu/drm/nouveau/nvkm/core/object.c b/drivers/gpu/drm/nouveau/nvkm/core/object.c index 67aa7223dcd7..218f932b1022 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/object.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/object.c @@ -25,6 +25,65 @@ #include #include +struct nvkm_object * +nvkm_object_search(struct nvkm_client *client, u64 handle, + const struct nvkm_object_func *func) +{ + struct nvkm_object *object; + + if (handle) { + struct rb_node *node = client->objroot.rb_node; + while (node) { + object = rb_entry(node, typeof(*object), node); + if (handle < object->object) + node = node->rb_left; + else + if (handle > object->object) + node = node->rb_right; + else + goto done; + } + return ERR_PTR(-ENOENT); + } else { + object = &client->object; + } + +done: + if (unlikely(func && object->func != func)) + return ERR_PTR(-EINVAL); + return object; +} + +void +nvkm_object_remove(struct nvkm_object *object) +{ + if (!RB_EMPTY_NODE(&object->node)) + rb_erase(&object->node, &object->client->objroot); +} + +bool +nvkm_object_insert(struct nvkm_object *object) +{ + struct rb_node **ptr = &object->client->objroot.rb_node; + struct rb_node *parent = NULL; + + while (*ptr) { + struct nvkm_object *this = rb_entry(*ptr, typeof(*this), node); + parent = *ptr; + if (object->object < this->object) + ptr = &parent->rb_left; + else + if (object->object > this->object) + ptr = &parent->rb_right; + else + return false; + } + + rb_link_node(&object->node, parent, ptr); + rb_insert_color(&object->node, &object->client->objroot); + return true; +} + int nvkm_object_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size) { @@ -214,7 +273,7 @@ nvkm_object_del(struct nvkm_object **pobject) struct nvkm_object *object = *pobject; if (object && !WARN_ON(!object->func)) { *pobject = nvkm_object_dtor(object); - nvkm_client_remove(object->client, object); + nvkm_object_remove(object); list_del(&object->head); kfree(*pobject); *pobject = NULL;