summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/nouveau/nvkm/core
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2015-08-20 14:54:16 +1000
committerBen Skeggs <bskeggs@redhat.com>2015-08-28 12:40:32 +1000
commitbf81df9be28657eea4aca8c6ab4ed3e69f8a051c (patch)
treea4a7e6f3d4e46696584c930bb7d6b4b2fd941337 /drivers/gpu/drm/nouveau/nvkm/core
parenta01ca78c8f118e5a24f1527ecf078ab56ddd4805 (diff)
drm/nouveau/nvif: replace path-based object identification
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.c50
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/handle.c22
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/ioctl.c51
3 files changed, 76 insertions, 47 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/client.c b/drivers/gpu/drm/nouveau/nvkm/core/client.c
index 7615cdd75294..bfe5357d7334 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/client.c
+++ b/drivers/gpu/drm/nouveau/nvkm/core/client.c
@@ -183,6 +183,55 @@ nvkm_client_oclass = {
},
};
+void
+nvkm_client_remove(struct nvkm_client *client, struct nvkm_handle *object)
+{
+ if (!RB_EMPTY_NODE(&object->rb))
+ rb_erase(&object->rb, &client->objroot);
+}
+
+bool
+nvkm_client_insert(struct nvkm_client *client, struct nvkm_handle *object)
+{
+ struct rb_node **ptr = &client->objroot.rb_node;
+ struct rb_node *parent = NULL;
+
+ while (*ptr) {
+ struct nvkm_handle *this =
+ container_of(*ptr, typeof(*this), rb);
+ parent = *ptr;
+ if (object->handle < this->handle)
+ ptr = &parent->rb_left;
+ else
+ if (object->handle > this->handle)
+ ptr = &parent->rb_right;
+ else
+ return false;
+ }
+
+ rb_link_node(&object->rb, parent, ptr);
+ rb_insert_color(&object->rb, &client->objroot);
+ return true;
+}
+
+struct nvkm_handle *
+nvkm_client_search(struct nvkm_client *client, u64 handle)
+{
+ struct rb_node *node = client->objroot.rb_node;
+ while (node) {
+ struct nvkm_handle *object =
+ container_of(node, typeof(*object), rb);
+ if (handle < object->handle)
+ node = node->rb_left;
+ else
+ if (handle > object->handle)
+ node = node->rb_right;
+ else
+ return object;
+ }
+ return NULL;
+}
+
int
nvkm_client_fini(struct nvkm_client *client, bool suspend)
{
@@ -256,6 +305,7 @@ nvkm_client_new(const char *name, u64 device, const char *cfg,
client->device = device;
snprintf(client->name, sizeof(client->name), "%s", name);
client->debug = nvkm_dbgopt(dbg, "CLIENT");
+ client->objroot = RB_ROOT;
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/handle.c b/drivers/gpu/drm/nouveau/nvkm/core/handle.c
index 6230eaece64d..a12ab8001701 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/handle.c
+++ b/drivers/gpu/drm/nouveau/nvkm/core/handle.c
@@ -113,6 +113,7 @@ nvkm_handle_create(struct nvkm_object *parent, u32 _parent, u32 _handle,
INIT_LIST_HEAD(&handle->tree);
handle->name = _handle;
handle->priv = ~0;
+ RB_CLEAR_NODE(&handle->rb);
ret = nvkm_namedb_insert(nv_namedb(namedb), _handle, object, handle);
if (ret) {
@@ -149,12 +150,15 @@ nvkm_handle_create(struct nvkm_object *parent, u32 _parent, u32 _handle,
void
nvkm_handle_destroy(struct nvkm_handle *handle)
{
+ struct nvkm_client *client = nvkm_client(handle->object);
struct nvkm_handle *item, *temp;
hprintk(handle, TRACE, "destroy running\n");
list_for_each_entry_safe(item, temp, &handle->tree, head) {
nvkm_handle_destroy(item);
}
+
+ nvkm_client_remove(client, handle);
list_del(&handle->head);
if (handle->priv != ~0) {
@@ -167,24 +171,6 @@ nvkm_handle_destroy(struct nvkm_handle *handle)
kfree(handle);
}
-struct nvkm_object *
-nvkm_handle_ref(struct nvkm_object *parent, u32 name)
-{
- struct nvkm_object *object = NULL;
- struct nvkm_handle *handle;
-
- while (!nv_iclass(parent, NV_NAMEDB_CLASS))
- parent = parent->parent;
-
- handle = nvkm_namedb_get(nv_namedb(parent), name);
- if (handle) {
- nvkm_object_ref(handle->object, &object);
- nvkm_namedb_put(handle);
- }
-
- return object;
-}
-
struct nvkm_handle *
nvkm_handle_get_class(struct nvkm_object *engctx, u16 oclass)
{
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c b/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c
index 7434958846f7..7654783e8350 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c
+++ b/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c
@@ -103,9 +103,9 @@ nvkm_ioctl_new(struct nvkm_handle *handle, void *data, u32 size)
return ret;
nvif_ioctl(handle->object, "new vers %d handle %08x class %08x "
- "route %02x token %llx\n",
+ "route %02x token %llx object %016llx\n",
args->v0.version, _handle, _oclass,
- args->v0.route, args->v0.token);
+ args->v0.route, args->v0.token, args->v0.object);
if (!nv_iclass(handle->object, NV_PARENT_CLASS)) {
nvif_debug(handle->object, "cannot have children (ctor)\n");
@@ -166,6 +166,8 @@ nvkm_ioctl_new(struct nvkm_handle *handle, void *data, u32 size)
if (ret)
nvkm_handle_destroy(handle);
+ handle->handle = args->v0.object;
+ nvkm_client_insert(client, handle);
fail_handle:
nvkm_object_dec(object, false);
fail_init:
@@ -438,40 +440,31 @@ nvkm_ioctl_v0[] = {
};
static int
-nvkm_ioctl_path(struct nvkm_handle *parent, u32 type, u32 nr, u32 *path,
+nvkm_ioctl_path(struct nvkm_client *client, u64 handle, u32 type,
void *data, u32 size, u8 owner, u8 *route, u64 *token)
{
- struct nvkm_handle *handle = parent;
- struct nvkm_namedb *namedb;
- struct nvkm_object *object;
+ struct nvkm_handle *object;
int ret;
- while ((object = parent->object), nr--) {
- nvif_ioctl(object, "path 0x%08x\n", path[nr]);
- if (!nv_iclass(object, NV_PARENT_CLASS)) {
- nvif_debug(object, "cannot have children (path)\n");
- return -EINVAL;
- }
-
- if (!(namedb = (void *)nv_pclass(object, NV_NAMEDB_CLASS)) ||
- !(handle = nvkm_namedb_get(namedb, path[nr]))) {
- nvif_debug(object, "handle 0x%08x not found\n", path[nr]);
- return -ENOENT;
- }
- nvkm_namedb_put(handle);
- parent = handle;
+ if (handle)
+ object = nvkm_client_search(client, handle);
+ else
+ object = client->root;
+ if (unlikely(!object)) {
+ nvif_ioctl(&client->namedb.parent.object, "object not found\n");
+ return -ENOENT;
}
- if (owner != NVIF_IOCTL_V0_OWNER_ANY && owner != handle->route) {
- nvif_ioctl(object, "object route != owner\n");
+ if (owner != NVIF_IOCTL_V0_OWNER_ANY && owner != object->route) {
+ nvif_ioctl(&client->namedb.parent.object, "route != owner\n");
return -EACCES;
}
- *route = handle->route;
- *token = handle->token;
+ *route = object->route;
+ *token = object->token;
if (ret = -EINVAL, type < ARRAY_SIZE(nvkm_ioctl_v0)) {
if (nvkm_ioctl_v0[type].version == 0)
- ret = nvkm_ioctl_v0[type].func(handle, data, size);
+ ret = nvkm_ioctl_v0[type].func(object, data, size);
}
return ret;
@@ -491,11 +484,11 @@ nvkm_ioctl(struct nvkm_client *client, bool supervisor,
nvif_ioctl(object, "size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, true)) {
- nvif_ioctl(object, "vers %d type %02x path %d owner %02x\n",
- args->v0.version, args->v0.type, args->v0.path_nr,
+ nvif_ioctl(object,
+ "vers %d type %02x object %016llx owner %02x\n",
+ args->v0.version, args->v0.type, args->v0.object,
args->v0.owner);
- ret = nvkm_ioctl_path(client->root, args->v0.type,
- args->v0.path_nr, args->v0.path,
+ ret = nvkm_ioctl_path(client, args->v0.object, args->v0.type,
data, size, args->v0.owner,
&args->v0.route, &args->v0.token);
}