drm/nouveau/core/object: support lookup of specific object types
authorBen Skeggs <bskeggs@redhat.com>
Thu, 22 Dec 2016 05:22:25 +0000 (15:22 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Fri, 17 Feb 2017 05:14:56 +0000 (15:14 +1000)
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 <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/include/nvkm/core/object.h
drivers/gpu/drm/nouveau/nvkm/core/object.c

index dcd048b..96dda35 100644 (file)
@@ -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;
index 67aa722..218f932 100644 (file)
 #include <core/client.h>
 #include <core/engine.h>
 
+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;