struct rb_root objroot;
struct rb_root dmaroot;
- struct nvkm_handle *root;
-
bool super;
void *data;
int (*ntfy)(const void *, u32, const void *, u32);
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 **);
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);
/* 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
+++ /dev/null
-#ifndef __NVKM_HANDLE_H__
-#define __NVKM_HANDLE_H__
-#include <core/os.h>
-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
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 {
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);
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
/* 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);
}
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
{
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);
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);
}
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
*/
#include <core/client.h>
#include <core/device.h>
-#include <core/handle.h>
#include <core/notify.h>
#include <core/option.h>
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;
};
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;
{
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
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;
}
{
struct nvkm_oclass oclass = {};
struct nvkm_client *client;
- int ret;
if (!(client = *pclient = kzalloc(sizeof(*client), GFP_KERNEL)))
return -ENOMEM;
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;
}
+++ /dev/null
-/*
- * 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 <core/handle.h>
-#include <core/client.h>
-
-#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);
-}
#include <core/ioctl.h>
#include <core/client.h>
#include <core/engine.h>
-#include <core/handle.h>
#include <nvif/unpack.h>
#include <nvif/ioctl.h>
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;
}
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;
}
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;
}
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;
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;
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
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 },
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;
* Authors: Ben Skeggs
*/
#include <core/object.h>
+#include <core/client.h>
#include <core/engine.h>
int
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;
}
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
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;
-}
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);
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);
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;
#include "rootnv50.h"
#include <core/client.h>
-#include <core/handle.h>
#include <core/oproxy.h>
#include <core/ramht.h>
#include <subdev/fb.h>
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]);
}
#include <core/client.h>
#include <core/enum.h>
#include <core/gpuobj.h>
-#include <core/handle.h>
#include <subdev/bar.h>
#include <engine/sw.h>
#include <core/client.h>
#include <core/enum.h>
#include <core/gpuobj.h>
-#include <core/handle.h>
#include <subdev/bar.h>
#include <engine/sw.h>
#include "regsnv04.h"
#include <core/client.h>
-#include <core/handle.h>
#include <core/ramht.h>
#include <subdev/instmem.h>
#include <subdev/timer.h>
#include "nv50.h"
#include <core/gpuobj.h>
-#include <core/handle.h>
#include <engine/disp.h>
#include <engine/fifo/chan.h>
#include <subdev/bar.h>