diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/client.h b/drivers/gpu/drm/nouveau/include/nvkm/core/client.h index 5485bbac56772a4035edb6f9d652a00962bebb52..eaf5905a87a3264ba2b5e533dddf71e48e2579f3 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/client.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/client.h @@ -12,8 +12,6 @@ struct nvkm_client { struct rb_root objroot; struct rb_root dmaroot; - struct nvkm_handle *root; - bool super; void *data; int (*ntfy)(const void *, u32, const void *, u32); @@ -21,9 +19,9 @@ struct nvkm_client { struct nvkm_vm *vm; }; -bool nvkm_client_insert(struct nvkm_client *, struct nvkm_handle *); -void nvkm_client_remove(struct nvkm_client *, struct nvkm_handle *); -struct nvkm_handle *nvkm_client_search(struct nvkm_client *, u64 handle); +bool nvkm_client_insert(struct nvkm_client *, struct nvkm_object *); +void nvkm_client_remove(struct nvkm_client *, struct nvkm_object *); +struct nvkm_object *nvkm_client_search(struct nvkm_client *, u64 object); int nvkm_client_new(const char *name, u64 device, const char *cfg, const char *dbg, struct nvkm_client **); @@ -31,14 +29,6 @@ void nvkm_client_del(struct nvkm_client **); int nvkm_client_init(struct nvkm_client *); int nvkm_client_fini(struct nvkm_client *, bool suspend); -static inline struct nvkm_client * -nvkm_client(struct nvkm_object *object) -{ - while (object && object->parent) - object = object->parent; - return container_of(object, struct nvkm_client, object); -} - int nvkm_client_notify_new(struct nvkm_object *, struct nvkm_event *, void *data, u32 size); int nvkm_client_notify_del(struct nvkm_client *, int index); @@ -48,12 +38,15 @@ int nvkm_client_notify_put(struct nvkm_client *, int index); /* logging for client-facing objects */ #define nvif_printk(o,l,p,f,a...) do { \ struct nvkm_object *_object = (o); \ - struct nvkm_client *_client = nvkm_client(_object); \ + struct nvkm_client *_client = _object->client; \ if (_client->debug >= NV_DBG_##l) \ - printk(KERN_##p "nouveau: %s: "f, _client->name, ##a); \ + printk(KERN_##p "nouveau: %s:%08x:%08x: "f, _client->name, \ + _object->handle, _object->oclass, ##a); \ } while(0) +#define nvif_fatal(o,f,a...) nvif_printk((o), FATAL, CRIT, f, ##a) #define nvif_error(o,f,a...) nvif_printk((o), ERROR, ERR, f, ##a) #define nvif_debug(o,f,a...) nvif_printk((o), DEBUG, INFO, f, ##a) #define nvif_trace(o,f,a...) nvif_printk((o), TRACE, INFO, f, ##a) +#define nvif_info(o,f,a...) nvif_printk((o), INFO, INFO, f, ##a) #define nvif_ioctl(o,f,a...) nvif_trace((o), "ioctl: "f, ##a) #endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/handle.h b/drivers/gpu/drm/nouveau/include/nvkm/core/handle.h deleted file mode 100644 index 539278916d23b4823e8ca32fcb799182d8f09bb9..0000000000000000000000000000000000000000 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/handle.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef __NVKM_HANDLE_H__ -#define __NVKM_HANDLE_H__ -#include -struct nvkm_object; - -struct nvkm_handle { - struct list_head node; - - struct list_head head; - struct list_head tree; - u32 name; - u32 priv; - - u8 route; - u64 token; - - struct nvkm_handle *parent; - struct nvkm_object *object; - - struct rb_node rb; - u64 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 *); -int nvkm_handle_fini(struct nvkm_handle *, bool suspend); - -struct nvkm_handle *nvkm_handle_get_class(struct nvkm_object *, u16); -struct nvkm_handle *nvkm_handle_get_vinst(struct nvkm_object *, u64); -struct nvkm_handle *nvkm_handle_get_cinst(struct nvkm_object *, u32); -void nvkm_handle_put(struct nvkm_handle *); -#endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/object.h b/drivers/gpu/drm/nouveau/include/nvkm/core/object.h index b4b822f6155cd192749db7aada1d05e4f1057fac..dcd048b91face4d6993d694f3febc76b8891b3b4 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/object.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/object.h @@ -10,12 +10,15 @@ struct nvkm_object { const struct nvkm_object_func *func; struct nvkm_client *client; struct nvkm_engine *engine; - u32 oclass; + s32 oclass; u32 handle; - struct nvkm_object *parent; - u32 pclass; - atomic_t refcount; - atomic_t usecount; + + struct list_head head; + struct list_head tree; + u8 route; + u64 token; + u64 object; + struct rb_node node; }; struct nvkm_object_func { @@ -43,6 +46,8 @@ int nvkm_object_new_(const struct nvkm_object_func *, struct nvkm_object **); int nvkm_object_new(const struct nvkm_oclass *, void *data, u32 size, struct nvkm_object **); +void nvkm_object_del(struct nvkm_object **); +void *nvkm_object_dtor(struct nvkm_object *); int nvkm_object_init(struct nvkm_object *); int nvkm_object_fini(struct nvkm_object *, bool suspend); int nvkm_object_mthd(struct nvkm_object *, u32 mthd, void *data, u32 size); @@ -72,14 +77,12 @@ struct nvkm_oclass { struct nvkm_sclass base; const void *priv; const void *engn; - s32 handle; + u32 handle; + u8 route; + u64 token; u64 object; struct nvkm_client *client; struct nvkm_object *parent; struct nvkm_engine *engine; }; - -void nvkm_object_ref(struct nvkm_object *, struct nvkm_object **); -int nvkm_object_inc(struct nvkm_object *); -int nvkm_object_dec(struct nvkm_object *, bool suspend); #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.c b/drivers/gpu/drm/nouveau/nouveau_abi16.c index 6634f420ded325534732723573a6485b4cc185a1..40a903b79343e84dfa74218f2156dfa72666105f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_abi16.c +++ b/drivers/gpu/drm/nouveau/nouveau_abi16.c @@ -134,6 +134,7 @@ nouveau_abi16_chan_fini(struct nouveau_abi16 *abi16, /* destroy channel object, all children will be killed too */ if (chan->chan) { abi16->handles &= ~(1ULL << (chan->chan->user.handle & 0xffff)); + nouveau_channel_idle(chan->chan); nouveau_channel_del(&chan->chan); } diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c index 4a13bda1475b7eb491c4dca356a8bba858f3d753..8c88c5e5bf0b243444623dcb3a30f80e2aadd4dc 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.c +++ b/drivers/gpu/drm/nouveau/nouveau_chan.c @@ -43,20 +43,26 @@ module_param_named(vram_pushbuf, nouveau_vram_pushbuf, int, 0400); int nouveau_channel_idle(struct nouveau_channel *chan) { - struct nouveau_cli *cli = (void *)chan->user.client; - struct nouveau_fence *fence = NULL; - int ret; + if (likely(chan && chan->fence)) { + struct nouveau_cli *cli = (void *)chan->user.client; + struct nouveau_fence *fence = NULL; + int ret; + + ret = nouveau_fence_new(chan, false, &fence); + if (!ret) { + ret = nouveau_fence_wait(fence, false, false); + nouveau_fence_unref(&fence); + } - ret = nouveau_fence_new(chan, false, &fence); - if (!ret) { - ret = nouveau_fence_wait(fence, false, false); - nouveau_fence_unref(&fence); + if (ret) { + NV_PRINTK(err, cli, "failed to idle channel " + "0x%08x [%s]\n", + chan->user.handle, + nvxx_client(&cli->base)->name); + return ret; + } } - - if (ret) - NV_PRINTK(err, cli, "failed to idle channel 0x%08x [%s]\n", - chan->user.handle, nvxx_client(&cli->base)->name); - return ret; + return 0; } void @@ -64,10 +70,8 @@ nouveau_channel_del(struct nouveau_channel **pchan) { struct nouveau_channel *chan = *pchan; if (chan) { - if (chan->fence) { - nouveau_channel_idle(chan); + if (chan->fence) nouveau_fence(chan->drm)->context_del(chan); - } nvif_object_fini(&chan->nvsw); nvif_object_fini(&chan->gart); nvif_object_fini(&chan->vram); diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index d04d08cc546dd3a54ff540f01a98f2be00be55ad..14a13486c27feee372d6306121d95093c2c48b62 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -139,13 +139,17 @@ nouveau_cli_destroy(struct nouveau_cli *cli) static void nouveau_accel_fini(struct nouveau_drm *drm) { - nvif_notify_fini(&drm->flip); - nouveau_channel_del(&drm->channel); + nouveau_channel_idle(drm->channel); nvif_object_fini(&drm->ntfy); nvkm_gpuobj_del(&drm->notify); + nvif_notify_fini(&drm->flip); nvif_object_fini(&drm->nvsw); - nouveau_channel_del(&drm->cechan); + nouveau_channel_del(&drm->channel); + + nouveau_channel_idle(drm->cechan); nvif_object_fini(&drm->ttm.copy); + nouveau_channel_del(&drm->cechan); + if (drm->fence) nouveau_fence(drm)->dtor(drm); } diff --git a/drivers/gpu/drm/nouveau/nvkm/core/Kbuild b/drivers/gpu/drm/nouveau/nvkm/core/Kbuild index 09044cf0d9ff36e7207d6ebbb75ed7b1406c0ab8..7f66963f305ceb3942aef15846403cae903ba945 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/core/Kbuild @@ -3,7 +3,6 @@ nvkm-y += nvkm/core/engine.o nvkm-y += nvkm/core/enum.o nvkm-y += nvkm/core/event.o nvkm-y += nvkm/core/gpuobj.o -nvkm-y += nvkm/core/handle.o nvkm-y += nvkm/core/ioctl.o nvkm-y += nvkm/core/memory.o nvkm-y += nvkm/core/mm.o diff --git a/drivers/gpu/drm/nouveau/nvkm/core/client.c b/drivers/gpu/drm/nouveau/nvkm/core/client.c index ab98f8c45950fdaad0f7ab3cef0574ace268431b..297e1e953fa6c7a8da535272339fae15967afbd8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/client.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/client.c @@ -23,7 +23,6 @@ */ #include #include -#include #include #include @@ -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; @@ -207,47 +206,47 @@ nvkm_client_object_func = { }; void -nvkm_client_remove(struct nvkm_client *client, struct nvkm_handle *object) +nvkm_client_remove(struct nvkm_client *client, struct nvkm_object *object) { - if (!RB_EMPTY_NODE(&object->rb)) - rb_erase(&object->rb, &client->objroot); + if (!RB_EMPTY_NODE(&object->node)) + rb_erase(&object->node, &client->objroot); } bool -nvkm_client_insert(struct nvkm_client *client, struct nvkm_handle *object) +nvkm_client_insert(struct nvkm_client *client, struct nvkm_object *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); + struct nvkm_object *this = + container_of(*ptr, typeof(*this), node); parent = *ptr; - if (object->handle < this->handle) + if (object->object < this->object) ptr = &parent->rb_left; else - if (object->handle > this->handle) + if (object->object > this->object) ptr = &parent->rb_right; else return false; } - rb_link_node(&object->rb, parent, ptr); - rb_insert_color(&object->rb, &client->objroot); + rb_link_node(&object->node, parent, ptr); + rb_insert_color(&object->node, &client->objroot); return true; } -struct nvkm_handle * +struct nvkm_object * 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) + struct nvkm_object *object = + container_of(node, typeof(*object), node); + if (handle < object->object) node = node->rb_left; else - if (handle > object->handle) + if (handle > object->object) node = node->rb_right; else return object; @@ -260,26 +259,17 @@ nvkm_client_fini(struct nvkm_client *client, bool suspend) { struct nvkm_object *object = &client->object; const char *name[2] = { "fini", "suspend" }; - int ret, i; - nvif_trace(object, "%s running\n", name[suspend]); - nvif_trace(object, "%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); - nvif_trace(object, "%s object\n", name[suspend]); - ret = nvkm_handle_fini(client->root, suspend); - nvif_trace(object, "%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) { - struct nvkm_object *object = &client->object; - int ret; - nvif_trace(object, "init running\n"); - ret = nvkm_handle_init(client->root); - nvif_trace(object, "init completed with %d\n", ret); - return ret; + return nvkm_object_init(&client->object); } void @@ -291,7 +281,7 @@ nvkm_client_del(struct nvkm_client **pclient) nvkm_client_fini(client, false); for (i = 0; i < ARRAY_SIZE(client->notify); i++) nvkm_client_notify_del(client, i); - nvkm_handle_destroy(client->root); + nvkm_object_dtor(&client->object); kfree(*pclient); *pclient = NULL; } @@ -303,7 +293,6 @@ nvkm_client_new(const char *name, u64 device, const char *cfg, { struct nvkm_oclass oclass = {}; struct nvkm_client *client; - int ret; if (!(client = *pclient = kzalloc(sizeof(*client), GFP_KERNEL))) return -ENOMEM; @@ -315,9 +304,5 @@ nvkm_client_new(const char *name, u64 device, const char *cfg, client->debug = nvkm_dbgopt(dbg, "CLIENT"); client->objroot = RB_ROOT; client->dmaroot = RB_ROOT; - - ret = nvkm_handle_create(NULL, ~0, &client->object, &client->root); - if (ret) - nvkm_client_del(pclient); - return ret; + return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/core/handle.c b/drivers/gpu/drm/nouveau/nvkm/core/handle.c deleted file mode 100644 index d185cae0fbba3ca8dea5ea1c35bc470971d8d8fd..0000000000000000000000000000000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/core/handle.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include -#include - -#define hprintk(h,l,f,a...) do { \ - struct nvkm_handle *p = (h)->parent; u32 n = p ? p->name : ~0; \ - nvif_printk((h)->object, l, INFO, "0x%08x:0x%08x "f, n, (h)->name, ##a);\ -} while(0) - -int -nvkm_handle_init(struct nvkm_handle *handle) -{ - struct nvkm_handle *item; - int ret; - - hprintk(handle, TRACE, "init running\n"); - ret = nvkm_object_inc(handle->object); - if (ret) - return ret; - - hprintk(handle, TRACE, "init children\n"); - list_for_each_entry(item, &handle->tree, head) { - ret = nvkm_handle_init(item); - if (ret) - goto fail; - } - - hprintk(handle, TRACE, "init completed\n"); - return 0; -fail: - hprintk(handle, ERROR, "init failed with %d\n", ret); - list_for_each_entry_continue_reverse(item, &handle->tree, head) { - nvkm_handle_fini(item, false); - } - - nvkm_object_dec(handle->object, false); - return ret; -} - -int -nvkm_handle_fini(struct nvkm_handle *handle, bool suspend) -{ - static char *name[2] = { "fini", "suspend" }; - struct nvkm_handle *item; - int ret; - - hprintk(handle, TRACE, "%s children\n", name[suspend]); - list_for_each_entry(item, &handle->tree, head) { - ret = nvkm_handle_fini(item, suspend); - if (ret && suspend) - goto fail; - } - - hprintk(handle, TRACE, "%s running\n", name[suspend]); - if (handle->object) { - ret = nvkm_object_dec(handle->object, suspend); - if (ret && suspend) - goto fail; - } - - hprintk(handle, TRACE, "%s completed\n", name[suspend]); - return 0; -fail: - hprintk(handle, ERROR, "%s failed with %d\n", name[suspend], ret); - list_for_each_entry_continue_reverse(item, &handle->tree, head) { - int rret = nvkm_handle_init(item); - if (rret) - hprintk(handle, FATAL, "failed to restart, %d\n", rret); - } - - return ret; -} - -int -nvkm_handle_create(struct nvkm_handle *parent, u32 _handle, - struct nvkm_object *object, struct nvkm_handle **phandle) -{ - struct nvkm_handle *handle; - - handle = kzalloc(sizeof(*handle), GFP_KERNEL); - if (!handle) - return -ENOMEM; - - INIT_LIST_HEAD(&handle->head); - INIT_LIST_HEAD(&handle->tree); - handle->name = _handle; - handle->priv = ~0; - RB_CLEAR_NODE(&handle->rb); - handle->parent = parent; - nvkm_object_ref(object, &handle->object); - - if (parent) - list_add(&handle->head, &handle->parent->tree); - - hprintk(handle, TRACE, "created\n"); - *phandle = handle; - return 0; -} - -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); - - hprintk(handle, TRACE, "destroy completed\n"); - nvkm_object_ref(NULL, &handle->object); - kfree(handle); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c b/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c index d9bb0394d83ff81ecf6e6a96c99365d198cf2de1..d87d6ab03cc7f1a5a67a854752de132aed64a181 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c @@ -24,15 +24,13 @@ #include #include #include -#include #include #include static int -nvkm_ioctl_nop(struct nvkm_handle *handle, void *data, u32 size) +nvkm_ioctl_nop(struct nvkm_object *object, void *data, u32 size) { - struct nvkm_object *object = handle->object; union { struct nvif_ioctl_nop_v0 v0; } *args = data; @@ -48,9 +46,8 @@ nvkm_ioctl_nop(struct nvkm_handle *handle, void *data, u32 size) } static int -nvkm_ioctl_sclass(struct nvkm_handle *handle, void *data, u32 size) +nvkm_ioctl_sclass(struct nvkm_object *object, void *data, u32 size) { - struct nvkm_object *object = handle->object; union { struct nvif_ioctl_sclass_v0 v0; } *args = data; @@ -81,13 +78,12 @@ nvkm_ioctl_sclass(struct nvkm_handle *handle, void *data, u32 size) } static int -nvkm_ioctl_new(struct nvkm_handle *handle, void *data, u32 size) +nvkm_ioctl_new(struct nvkm_object *parent, 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_client *client = parent->client; struct nvkm_object *object = NULL; struct nvkm_oclass oclass; int ret, i = 0; @@ -124,38 +120,30 @@ nvkm_ioctl_new(struct nvkm_handle *handle, void *data, u32 size) } 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); + if (ret == 0) { + ret = nvkm_object_init(object); + if (ret == 0) { + list_add(&object->head, &parent->tree); + object->route = args->v0.route; + object->token = args->v0.token; + object->object = args->v0.object; + if (nvkm_client_insert(client, object)) { + client->data = object; + return 0; + } + ret = -EEXIST; + } + nvkm_object_fini(object, false); + } + + nvkm_object_del(&object); return ret; } static int -nvkm_ioctl_del(struct nvkm_handle *handle, void *data, u32 size) +nvkm_ioctl_del(struct nvkm_object *object, void *data, u32 size) { - struct nvkm_object *object = handle->object; union { struct nvif_ioctl_del none; } *args = data; @@ -164,17 +152,16 @@ nvkm_ioctl_del(struct nvkm_handle *handle, void *data, u32 size) nvif_ioctl(object, "delete size %d\n", size); if (nvif_unvers(args->none)) { nvif_ioctl(object, "delete\n"); - nvkm_handle_fini(handle, false); - nvkm_handle_destroy(handle); + nvkm_object_fini(object, false); + nvkm_object_del(&object); } return ret; } static int -nvkm_ioctl_mthd(struct nvkm_handle *handle, void *data, u32 size) +nvkm_ioctl_mthd(struct nvkm_object *object, void *data, u32 size) { - struct nvkm_object *object = handle->object; union { struct nvif_ioctl_mthd_v0 v0; } *args = data; @@ -192,9 +179,8 @@ nvkm_ioctl_mthd(struct nvkm_handle *handle, void *data, u32 size) static int -nvkm_ioctl_rd(struct nvkm_handle *handle, void *data, u32 size) +nvkm_ioctl_rd(struct nvkm_object *object, void *data, u32 size) { - struct nvkm_object *object = handle->object; union { struct nvif_ioctl_rd_v0 v0; } *args = data; @@ -232,9 +218,8 @@ nvkm_ioctl_rd(struct nvkm_handle *handle, void *data, u32 size) } static int -nvkm_ioctl_wr(struct nvkm_handle *handle, void *data, u32 size) +nvkm_ioctl_wr(struct nvkm_object *object, void *data, u32 size) { - struct nvkm_object *object = handle->object; union { struct nvif_ioctl_wr_v0 v0; } *args = data; @@ -261,9 +246,8 @@ nvkm_ioctl_wr(struct nvkm_handle *handle, void *data, u32 size) } static int -nvkm_ioctl_map(struct nvkm_handle *handle, void *data, u32 size) +nvkm_ioctl_map(struct nvkm_object *object, void *data, u32 size) { - struct nvkm_object *object = handle->object; union { struct nvif_ioctl_map_v0 v0; } *args = data; @@ -280,9 +264,8 @@ nvkm_ioctl_map(struct nvkm_handle *handle, void *data, u32 size) } static int -nvkm_ioctl_unmap(struct nvkm_handle *handle, void *data, u32 size) +nvkm_ioctl_unmap(struct nvkm_object *object, void *data, u32 size) { - struct nvkm_object *object = handle->object; union { struct nvif_ioctl_unmap none; } *args = data; @@ -297,9 +280,8 @@ nvkm_ioctl_unmap(struct nvkm_handle *handle, void *data, u32 size) } static int -nvkm_ioctl_ntfy_new(struct nvkm_handle *handle, void *data, u32 size) +nvkm_ioctl_ntfy_new(struct nvkm_object *object, void *data, u32 size) { - struct nvkm_object *object = handle->object; union { struct nvif_ioctl_ntfy_new_v0 v0; } *args = data; @@ -324,10 +306,9 @@ nvkm_ioctl_ntfy_new(struct nvkm_handle *handle, void *data, u32 size) } static int -nvkm_ioctl_ntfy_del(struct nvkm_handle *handle, void *data, u32 size) +nvkm_ioctl_ntfy_del(struct nvkm_object *object, void *data, u32 size) { - struct nvkm_client *client = nvkm_client(handle->object); - struct nvkm_object *object = handle->object; + struct nvkm_client *client = object->client; union { struct nvif_ioctl_ntfy_del_v0 v0; } *args = data; @@ -344,10 +325,9 @@ nvkm_ioctl_ntfy_del(struct nvkm_handle *handle, void *data, u32 size) } static int -nvkm_ioctl_ntfy_get(struct nvkm_handle *handle, void *data, u32 size) +nvkm_ioctl_ntfy_get(struct nvkm_object *object, void *data, u32 size) { - struct nvkm_client *client = nvkm_client(handle->object); - struct nvkm_object *object = handle->object; + struct nvkm_client *client = object->client; union { struct nvif_ioctl_ntfy_get_v0 v0; } *args = data; @@ -364,10 +344,9 @@ nvkm_ioctl_ntfy_get(struct nvkm_handle *handle, void *data, u32 size) } static int -nvkm_ioctl_ntfy_put(struct nvkm_handle *handle, void *data, u32 size) +nvkm_ioctl_ntfy_put(struct nvkm_object *object, void *data, u32 size) { - struct nvkm_client *client = nvkm_client(handle->object); - struct nvkm_object *object = handle->object; + struct nvkm_client *client = object->client; union { struct nvif_ioctl_ntfy_put_v0 v0; } *args = data; @@ -385,7 +364,7 @@ nvkm_ioctl_ntfy_put(struct nvkm_handle *handle, void *data, u32 size) static struct { int version; - int (*func)(struct nvkm_handle *, void *, u32); + int (*func)(struct nvkm_object *, void *, u32); } nvkm_ioctl_v0[] = { { 0x00, nvkm_ioctl_nop }, @@ -407,13 +386,13 @@ static int nvkm_ioctl_path(struct nvkm_client *client, u64 handle, u32 type, void *data, u32 size, u8 owner, u8 *route, u64 *token) { - struct nvkm_handle *object; + struct nvkm_object *object; int ret; if (handle) object = nvkm_client_search(client, handle); else - object = client->root; + object = &client->object; if (unlikely(!object)) { nvif_ioctl(&client->object, "object not found\n"); return -ENOENT; diff --git a/drivers/gpu/drm/nouveau/nvkm/core/object.c b/drivers/gpu/drm/nouveau/nvkm/core/object.c index 8976526b1c8fc536de05617c02329c6657f74056..67aa7223dcd786fbf1b4a15cb6d8d0119f823d33 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/object.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/object.c @@ -22,6 +22,7 @@ * Authors: Ben Skeggs */ #include +#include #include int @@ -109,28 +110,112 @@ nvkm_object_bind(struct nvkm_object *object, struct nvkm_gpuobj *gpuobj, int nvkm_object_fini(struct nvkm_object *object, bool suspend) { - if (object->func->fini) - return object->func->fini(object, suspend); + const char *action = suspend ? "suspend" : "fini"; + struct nvkm_object *child; + s64 time; + int ret; + + nvif_debug(object, "%s children...\n", action); + time = ktime_to_us(ktime_get()); + list_for_each_entry(child, &object->tree, head) { + ret = nvkm_object_fini(child, suspend); + if (ret && suspend) + goto fail_child; + } + + nvif_debug(object, "%s running...\n", action); + if (object->func->fini) { + ret = object->func->fini(object, suspend); + if (ret) { + nvif_error(object, "%s failed with %d\n", action, ret); + if (suspend) + goto fail; + } + } + + time = ktime_to_us(ktime_get()) - time; + nvif_debug(object, "%s completed in %lldus\n", action, time); return 0; + +fail: + if (object->func->init) { + int rret = object->func->init(object); + if (rret) + nvif_fatal(object, "failed to restart, %d\n", rret); + } +fail_child: + list_for_each_entry_continue_reverse(child, &object->tree, head) { + nvkm_object_init(child); + } + return ret; } int nvkm_object_init(struct nvkm_object *object) { - if (object->func->init) - return object->func->init(object); + struct nvkm_object *child; + s64 time; + int ret; + + nvif_debug(object, "init running...\n"); + time = ktime_to_us(ktime_get()); + if (object->func->init) { + ret = object->func->init(object); + if (ret) + goto fail; + } + + nvif_debug(object, "init children...\n"); + list_for_each_entry(child, &object->tree, head) { + ret = nvkm_object_init(child); + if (ret) + goto fail_child; + } + + time = ktime_to_us(ktime_get()) - time; + nvif_debug(object, "init completed in %lldus\n", time); return 0; + +fail_child: + list_for_each_entry_continue_reverse(child, &object->tree, head) + nvkm_object_fini(child, false); +fail: + nvif_error(object, "init failed with %d\n", ret); + if (object->func->fini) + object->func->fini(object, false); + return ret; } -static void +void * +nvkm_object_dtor(struct nvkm_object *object) +{ + struct nvkm_object *child, *ctemp; + void *data = object; + s64 time; + + nvif_debug(object, "destroy children...\n"); + time = ktime_to_us(ktime_get()); + list_for_each_entry_safe(child, ctemp, &object->tree, head) { + nvkm_object_del(&child); + } + + nvif_debug(object, "destroy running...\n"); + if (object->func->dtor) + data = object->func->dtor(object); + nvkm_engine_unref(&object->engine); + time = ktime_to_us(ktime_get()) - time; + nvif_debug(object, "destroy completed in %lldus...\n", time); + return data; +} + +void nvkm_object_del(struct nvkm_object **pobject) { struct nvkm_object *object = *pobject; - if (object && !WARN_ON(!object->func)) { - if (object->func->dtor) - *pobject = object->func->dtor(object); - nvkm_engine_unref(&object->engine); + *pobject = nvkm_object_dtor(object); + nvkm_client_remove(object->client, object); + list_del(&object->head); kfree(*pobject); *pobject = NULL; } @@ -145,9 +230,10 @@ nvkm_object_ctor(const struct nvkm_object_func *func, object->engine = nvkm_engine_ref(oclass->engine); object->oclass = oclass->base.oclass; object->handle = oclass->handle; - object->parent = oclass->parent; - atomic_set(&object->refcount, 1); - atomic_set(&object->usecount, 0); + INIT_LIST_HEAD(&object->head); + INIT_LIST_HEAD(&object->tree); + RB_CLEAR_NODE(&object->node); + WARN_ON(oclass->engine && !object->engine); } int @@ -176,106 +262,3 @@ nvkm_object_new(const struct nvkm_oclass *oclass, void *data, u32 size, oclass->base.func ? oclass->base.func : &nvkm_object_func; return nvkm_object_new_(func, oclass, data, size, pobject); } - -void -nvkm_object_ref(struct nvkm_object *obj, struct nvkm_object **ref) -{ - if (obj) { - atomic_inc(&obj->refcount); - } - - if (*ref) { - int dead = atomic_dec_and_test(&(*ref)->refcount); - if (dead) - nvkm_object_del(ref); - } - - *ref = obj; -} - -int -nvkm_object_inc(struct nvkm_object *object) -{ - int ref = atomic_add_return(1, &object->usecount); - int ret; - - if (ref != 1) - return 0; - - if (object->parent) { - ret = nvkm_object_inc(object->parent); - if (ret) - goto fail_parent; - } - - ret = nvkm_object_init(object); - atomic_set(&object->usecount, 1); - if (ret) - goto fail_self; - - return 0; - -fail_self: - if (object->parent) - nvkm_object_dec(object->parent, false); -fail_parent: - atomic_dec(&object->usecount); - return ret; -} - -static int -nvkm_object_decf(struct nvkm_object *object) -{ - nvkm_object_fini(object, false); - atomic_set(&object->usecount, 0); - - if (object->parent) - nvkm_object_dec(object->parent, false); - - return 0; -} - -static int -nvkm_object_decs(struct nvkm_object *object) -{ - int ret; - - ret = nvkm_object_fini(object, true); - atomic_set(&object->usecount, 0); - if (ret) - return ret; - - if (object->parent) { - ret = nvkm_object_dec(object->parent, true); - if (ret) - goto fail_parent; - } - - return 0; - -fail_parent: - nvkm_object_init(object); - - return ret; -} - -int -nvkm_object_dec(struct nvkm_object *object, bool suspend) -{ - int ref = atomic_add_return(-1, &object->usecount); - int ret; - - if (ref == 0) { - if (suspend) - ret = nvkm_object_decs(object); - else - ret = nvkm_object_decf(object); - - if (ret) { - atomic_inc(&object->usecount); - return ret; - } - } - - return 0; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/core/oproxy.c b/drivers/gpu/drm/nouveau/nvkm/core/oproxy.c index f32aa0dc425bb2a6f0c29007289df6fbf88fe298..e31a0479add0d6930dcf932da30f4402b3350df8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/oproxy.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/oproxy.c @@ -109,9 +109,11 @@ nvkm_oproxy_fini(struct nvkm_object *object, bool suspend) return ret; } - ret = nvkm_object_fini(oproxy->object, suspend); - if (ret && suspend) - return ret; + if (oproxy->object->func->fini) { + ret = oproxy->object->func->fini(oproxy->object, suspend); + if (ret && suspend) + return ret; + } if (oproxy->func->fini[1]) { ret = oproxy->func->fini[1](oproxy, suspend); @@ -134,9 +136,11 @@ nvkm_oproxy_init(struct nvkm_object *object) return ret; } - ret = nvkm_object_init(oproxy->object); - if (ret) - return ret; + if (oproxy->object->func->init) { + ret = oproxy->object->func->init(oproxy->object); + if (ret) + return ret; + } if (oproxy->func->init[1]) { ret = oproxy->func->init[1](oproxy); @@ -153,7 +157,7 @@ nvkm_oproxy_dtor(struct nvkm_object *object) struct nvkm_oproxy *oproxy = nvkm_oproxy(object); if (oproxy->func->dtor[0]) oproxy->func->dtor[0](oproxy); - nvkm_object_ref(NULL, &oproxy->object); + nvkm_object_del(&oproxy->object); if (oproxy->func->dtor[1]) oproxy->func->dtor[1](oproxy); return oproxy; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c index b05c04a209beaf0a5ee222c541bb4338cb16cdb0..9c6645a357b93a3c063c49d31b0b6d8564b79e2d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c @@ -25,7 +25,6 @@ #include "rootnv50.h" #include -#include #include #include #include diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c index a56e56eed57bb375581f1fa82dd45949c1fc5030..9921482fc162487ffc514e55cf47542d7e9e0a7d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c @@ -116,7 +116,7 @@ nvkm_fifo_chan_child_del(struct nvkm_oproxy *base) if (!--engn->refcount) { if (chan->func->engine_dtor) chan->func->engine_dtor(chan, engine); - nvkm_object_ref(NULL, &engn->object); + nvkm_object_del(&engn->object); if (chan->vm) atomic_dec(&chan->vm->engref[engine->subdev.index]); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c index 172f243011137f6ebc8caa0e7c039d657b08a3f9..ff6fcbda615b07be29f8b6d7fd14e57332bc6228 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c index fc0ff2d37d0694fc35229c8000dc244860de959e..98970a0b7a66867b0c804c87bbadd3810f8a2af1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c index e6f04e87139a2866e8eed66c836b55c94548f1b4..ad707ff176cc757d0aa46a7114dbbeec3d1c30c9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c @@ -26,7 +26,6 @@ #include "regsnv04.h" #include -#include #include #include #include diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c index ef36ba18bff8356e956297622945b15e85a06382..a381196af69de6c679fe58785b998c8271113915 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c @@ -24,7 +24,6 @@ #include "nv50.h" #include -#include #include #include #include