diff options
author | André Fabian Silva Delgado <emulatorman@parabola.nu> | 2015-12-15 14:52:16 -0300 |
---|---|---|
committer | André Fabian Silva Delgado <emulatorman@parabola.nu> | 2015-12-15 14:52:16 -0300 |
commit | 8d91c1e411f55d7ea91b1183a2e9f8088fb4d5be (patch) | |
tree | e9891aa6c295060d065adffd610c4f49ecf884f3 /drivers/gpu/drm/nouveau/nvkm/core/client.c | |
parent | a71852147516bc1cb5b0b3cbd13639bfd4022dc8 (diff) |
Linux-libre 4.3.2-gnu
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/core/client.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/core/client.c | 188 |
1 files changed, 115 insertions, 73 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/client.c b/drivers/gpu/drm/nouveau/nvkm/core/client.c index 878a82f8f..297e1e953 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/client.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/client.c @@ -23,7 +23,6 @@ */ #include <core/client.h> #include <core/device.h> -#include <core/handle.h> #include <core/notify.h> #include <core/option.h> @@ -91,7 +90,7 @@ int nvkm_client_notify_new(struct nvkm_object *object, struct nvkm_event *event, void *data, u32 size) { - struct nvkm_client *client = nvkm_client(object); + struct nvkm_client *client = object->client; struct nvkm_client_notify *notify; union { struct nvif_notify_req_v0 v0; @@ -111,11 +110,11 @@ nvkm_client_notify_new(struct nvkm_object *object, if (!notify) return -ENOMEM; - nv_ioctl(client, "notify new size %d\n", size); + nvif_ioctl(object, "notify new size %d\n", size); if (nvif_unpack(req->v0, 0, 0, true)) { - nv_ioctl(client, "notify new vers %d reply %d route %02x " - "token %llx\n", req->v0.version, - req->v0.reply, req->v0.route, req->v0.token); + nvif_ioctl(object, "notify new vers %d reply %d route %02x " + "token %llx\n", req->v0.version, + req->v0.reply, req->v0.route, req->v0.token); notify->version = req->v0.version; notify->size = sizeof(notify->rep.v0); notify->rep.v0.version = req->v0.version; @@ -146,10 +145,10 @@ nvkm_client_mthd_devlist(struct nvkm_object *object, void *data, u32 size) } *args = data; int ret; - nv_ioctl(object, "client devlist size %d\n", size); + nvif_ioctl(object, "client devlist size %d\n", size); if (nvif_unpack(args->v0, 0, 0, true)) { - nv_ioctl(object, "client devlist vers %d count %d\n", - args->v0.version, args->v0.count); + nvif_ioctl(object, "client devlist vers %d count %d\n", + args->v0.version, args->v0.count); if (size == sizeof(args->v0.device[0]) * args->v0.count) { ret = nvkm_device_list(args->v0.device, args->v0.count); if (ret >= 0) { @@ -176,91 +175,134 @@ nvkm_client_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size) return -EINVAL; } -static void -nvkm_client_dtor(struct nvkm_object *object) +static int +nvkm_client_child_new(const struct nvkm_oclass *oclass, + void *data, u32 size, struct nvkm_object **pobject) { - struct nvkm_client *client = (void *)object; - int i; - for (i = 0; i < ARRAY_SIZE(client->notify); i++) - nvkm_client_notify_del(client, i); - nvkm_object_ref(NULL, &client->device); - nvkm_handle_destroy(client->root); - nvkm_namedb_destroy(&client->namedb); + return oclass->base.ctor(oclass, data, size, pobject); } -static struct nvkm_oclass -nvkm_client_oclass = { - .ofuncs = &(struct nvkm_ofuncs) { - .dtor = nvkm_client_dtor, - .mthd = nvkm_client_mthd, - }, -}; - -int -nvkm_client_create_(const char *name, u64 devname, const char *cfg, - const char *dbg, int length, void **pobject) +static int +nvkm_client_child_get(struct nvkm_object *object, int index, + struct nvkm_oclass *oclass) { - struct nvkm_object *device; - struct nvkm_client *client; - int ret; + const struct nvkm_sclass *sclass; + + switch (index) { + case 0: sclass = &nvkm_udevice_sclass; break; + default: + return -EINVAL; + } - device = (void *)nvkm_device_find(devname); - if (!device) - return -ENODEV; + oclass->ctor = nvkm_client_child_new; + oclass->base = *sclass; + return 0; +} + +static const struct nvkm_object_func +nvkm_client_object_func = { + .mthd = nvkm_client_mthd, + .sclass = nvkm_client_child_get, +}; - ret = nvkm_namedb_create_(NULL, NULL, &nvkm_client_oclass, - NV_CLIENT_CLASS, NULL, - (1ULL << NVDEV_ENGINE_DEVICE), - length, pobject); - client = *pobject; - if (ret) - return ret; +void +nvkm_client_remove(struct nvkm_client *client, struct nvkm_object *object) +{ + if (!RB_EMPTY_NODE(&object->node)) + rb_erase(&object->node, &client->objroot); +} - ret = nvkm_handle_create(nv_object(client), ~0, ~0, nv_object(client), - &client->root); - if (ret) - return ret; +bool +nvkm_client_insert(struct nvkm_client *client, struct nvkm_object *object) +{ + struct rb_node **ptr = &client->objroot.rb_node; + struct rb_node *parent = NULL; - /* prevent init/fini being called, os in in charge of this */ - atomic_set(&nv_object(client)->usecount, 2); + while (*ptr) { + struct nvkm_object *this = + container_of(*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; + } - nvkm_object_ref(device, &client->device); - snprintf(client->name, sizeof(client->name), "%s", name); - client->debug = nvkm_dbgopt(dbg, "CLIENT"); - return 0; + rb_link_node(&object->node, parent, ptr); + rb_insert_color(&object->node, &client->objroot); + return true; } -int -nvkm_client_init(struct nvkm_client *client) +struct nvkm_object * +nvkm_client_search(struct nvkm_client *client, u64 handle) { - int ret; - nv_debug(client, "init running\n"); - ret = nvkm_handle_init(client->root); - nv_debug(client, "init completed with %d\n", ret); - return ret; + struct rb_node *node = client->objroot.rb_node; + while (node) { + struct nvkm_object *object = + container_of(node, typeof(*object), node); + if (handle < object->object) + node = node->rb_left; + else + if (handle > object->object) + node = node->rb_right; + else + return object; + } + return NULL; } int nvkm_client_fini(struct nvkm_client *client, bool suspend) { + struct nvkm_object *object = &client->object; const char *name[2] = { "fini", "suspend" }; - int ret, i; - nv_debug(client, "%s running\n", name[suspend]); - nv_debug(client, "%s notify\n", name[suspend]); + int i; + nvif_debug(object, "%s notify\n", name[suspend]); for (i = 0; i < ARRAY_SIZE(client->notify); i++) nvkm_client_notify_put(client, i); - nv_debug(client, "%s object\n", name[suspend]); - ret = nvkm_handle_fini(client->root, suspend); - nv_debug(client, "%s completed with %d\n", name[suspend], ret); - return ret; + return nvkm_object_fini(&client->object, suspend); +} + +int +nvkm_client_init(struct nvkm_client *client) +{ + return nvkm_object_init(&client->object); +} + +void +nvkm_client_del(struct nvkm_client **pclient) +{ + struct nvkm_client *client = *pclient; + int i; + if (client) { + nvkm_client_fini(client, false); + for (i = 0; i < ARRAY_SIZE(client->notify); i++) + nvkm_client_notify_del(client, i); + nvkm_object_dtor(&client->object); + kfree(*pclient); + *pclient = NULL; + } } -const char * -nvkm_client_name(void *obj) +int +nvkm_client_new(const char *name, u64 device, const char *cfg, + const char *dbg, struct nvkm_client **pclient) { - const char *client_name = "unknown"; - struct nvkm_client *client = nvkm_client(obj); - if (client) - client_name = client->name; - return client_name; + struct nvkm_oclass oclass = {}; + struct nvkm_client *client; + + if (!(client = *pclient = kzalloc(sizeof(*client), GFP_KERNEL))) + return -ENOMEM; + oclass.client = client; + + nvkm_object_ctor(&nvkm_client_object_func, &oclass, &client->object); + snprintf(client->name, sizeof(client->name), "%s", name); + client->device = device; + client->debug = nvkm_dbgopt(dbg, "CLIENT"); + client->objroot = RB_ROOT; + client->dmaroot = RB_ROOT; + return 0; } |