Commit fbd58ebd authored by Ben Skeggs's avatar Ben Skeggs

drm/nouveau/object: merge with handle

Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 68f3f702
...@@ -12,8 +12,6 @@ struct nvkm_client { ...@@ -12,8 +12,6 @@ struct nvkm_client {
struct rb_root objroot; struct rb_root objroot;
struct rb_root dmaroot; struct rb_root dmaroot;
struct nvkm_handle *root;
bool super; bool super;
void *data; void *data;
int (*ntfy)(const void *, u32, const void *, u32); int (*ntfy)(const void *, u32, const void *, u32);
...@@ -21,9 +19,9 @@ struct nvkm_client { ...@@ -21,9 +19,9 @@ struct nvkm_client {
struct nvkm_vm *vm; struct nvkm_vm *vm;
}; };
bool nvkm_client_insert(struct nvkm_client *, struct nvkm_handle *); bool nvkm_client_insert(struct nvkm_client *, struct nvkm_object *);
void nvkm_client_remove(struct nvkm_client *, struct nvkm_handle *); void nvkm_client_remove(struct nvkm_client *, struct nvkm_object *);
struct nvkm_handle *nvkm_client_search(struct nvkm_client *, u64 handle); struct nvkm_object *nvkm_client_search(struct nvkm_client *, u64 object);
int nvkm_client_new(const char *name, u64 device, const char *cfg, int nvkm_client_new(const char *name, u64 device, const char *cfg,
const char *dbg, struct nvkm_client **); const char *dbg, struct nvkm_client **);
...@@ -31,14 +29,6 @@ void nvkm_client_del(struct nvkm_client **); ...@@ -31,14 +29,6 @@ void nvkm_client_del(struct nvkm_client **);
int nvkm_client_init(struct nvkm_client *); int nvkm_client_init(struct nvkm_client *);
int nvkm_client_fini(struct nvkm_client *, bool suspend); 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 *, int nvkm_client_notify_new(struct nvkm_object *, struct nvkm_event *,
void *data, u32 size); void *data, u32 size);
int nvkm_client_notify_del(struct nvkm_client *, int index); int nvkm_client_notify_del(struct nvkm_client *, int index);
...@@ -48,12 +38,15 @@ int nvkm_client_notify_put(struct nvkm_client *, int index); ...@@ -48,12 +38,15 @@ int nvkm_client_notify_put(struct nvkm_client *, int index);
/* logging for client-facing objects */ /* logging for client-facing objects */
#define nvif_printk(o,l,p,f,a...) do { \ #define nvif_printk(o,l,p,f,a...) do { \
struct nvkm_object *_object = (o); \ struct nvkm_object *_object = (o); \
struct nvkm_client *_client = nvkm_client(_object); \ struct nvkm_client *_client = _object->client; \
if (_client->debug >= NV_DBG_##l) \ 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) } 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_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_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_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) #define nvif_ioctl(o,f,a...) nvif_trace((o), "ioctl: "f, ##a)
#endif #endif
#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
...@@ -10,12 +10,15 @@ struct nvkm_object { ...@@ -10,12 +10,15 @@ struct nvkm_object {
const struct nvkm_object_func *func; const struct nvkm_object_func *func;
struct nvkm_client *client; struct nvkm_client *client;
struct nvkm_engine *engine; struct nvkm_engine *engine;
u32 oclass; s32 oclass;
u32 handle; u32 handle;
struct nvkm_object *parent;
u32 pclass; struct list_head head;
atomic_t refcount; struct list_head tree;
atomic_t usecount; u8 route;
u64 token;
u64 object;
struct rb_node node;
}; };
struct nvkm_object_func { struct nvkm_object_func {
...@@ -43,6 +46,8 @@ int nvkm_object_new_(const struct nvkm_object_func *, ...@@ -43,6 +46,8 @@ int nvkm_object_new_(const struct nvkm_object_func *,
struct nvkm_object **); struct nvkm_object **);
int nvkm_object_new(const struct nvkm_oclass *, void *data, u32 size, int nvkm_object_new(const struct nvkm_oclass *, void *data, u32 size,
struct nvkm_object **); 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_init(struct nvkm_object *);
int nvkm_object_fini(struct nvkm_object *, bool suspend); int nvkm_object_fini(struct nvkm_object *, bool suspend);
int nvkm_object_mthd(struct nvkm_object *, u32 mthd, void *data, u32 size); int nvkm_object_mthd(struct nvkm_object *, u32 mthd, void *data, u32 size);
...@@ -72,14 +77,12 @@ struct nvkm_oclass { ...@@ -72,14 +77,12 @@ struct nvkm_oclass {
struct nvkm_sclass base; struct nvkm_sclass base;
const void *priv; const void *priv;
const void *engn; const void *engn;
s32 handle; u32 handle;
u8 route;
u64 token;
u64 object; u64 object;
struct nvkm_client *client; struct nvkm_client *client;
struct nvkm_object *parent; struct nvkm_object *parent;
struct nvkm_engine *engine; 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 #endif
...@@ -134,6 +134,7 @@ nouveau_abi16_chan_fini(struct nouveau_abi16 *abi16, ...@@ -134,6 +134,7 @@ nouveau_abi16_chan_fini(struct nouveau_abi16 *abi16,
/* destroy channel object, all children will be killed too */ /* destroy channel object, all children will be killed too */
if (chan->chan) { if (chan->chan) {
abi16->handles &= ~(1ULL << (chan->chan->user.handle & 0xffff)); abi16->handles &= ~(1ULL << (chan->chan->user.handle & 0xffff));
nouveau_channel_idle(chan->chan);
nouveau_channel_del(&chan->chan); nouveau_channel_del(&chan->chan);
} }
......
...@@ -43,6 +43,7 @@ module_param_named(vram_pushbuf, nouveau_vram_pushbuf, int, 0400); ...@@ -43,6 +43,7 @@ module_param_named(vram_pushbuf, nouveau_vram_pushbuf, int, 0400);
int int
nouveau_channel_idle(struct nouveau_channel *chan) nouveau_channel_idle(struct nouveau_channel *chan)
{ {
if (likely(chan && chan->fence)) {
struct nouveau_cli *cli = (void *)chan->user.client; struct nouveau_cli *cli = (void *)chan->user.client;
struct nouveau_fence *fence = NULL; struct nouveau_fence *fence = NULL;
int ret; int ret;
...@@ -53,10 +54,15 @@ nouveau_channel_idle(struct nouveau_channel *chan) ...@@ -53,10 +54,15 @@ nouveau_channel_idle(struct nouveau_channel *chan)
nouveau_fence_unref(&fence); nouveau_fence_unref(&fence);
} }
if (ret) if (ret) {
NV_PRINTK(err, cli, "failed to idle channel 0x%08x [%s]\n", NV_PRINTK(err, cli, "failed to idle channel "
chan->user.handle, nvxx_client(&cli->base)->name); "0x%08x [%s]\n",
chan->user.handle,
nvxx_client(&cli->base)->name);
return ret; return ret;
}
}
return 0;
} }
void void
...@@ -64,10 +70,8 @@ nouveau_channel_del(struct nouveau_channel **pchan) ...@@ -64,10 +70,8 @@ nouveau_channel_del(struct nouveau_channel **pchan)
{ {
struct nouveau_channel *chan = *pchan; struct nouveau_channel *chan = *pchan;
if (chan) { if (chan) {
if (chan->fence) { if (chan->fence)
nouveau_channel_idle(chan);
nouveau_fence(chan->drm)->context_del(chan); nouveau_fence(chan->drm)->context_del(chan);
}
nvif_object_fini(&chan->nvsw); nvif_object_fini(&chan->nvsw);
nvif_object_fini(&chan->gart); nvif_object_fini(&chan->gart);
nvif_object_fini(&chan->vram); nvif_object_fini(&chan->vram);
......
...@@ -139,13 +139,17 @@ nouveau_cli_destroy(struct nouveau_cli *cli) ...@@ -139,13 +139,17 @@ nouveau_cli_destroy(struct nouveau_cli *cli)
static void static void
nouveau_accel_fini(struct nouveau_drm *drm) nouveau_accel_fini(struct nouveau_drm *drm)
{ {
nvif_notify_fini(&drm->flip); nouveau_channel_idle(drm->channel);
nouveau_channel_del(&drm->channel);
nvif_object_fini(&drm->ntfy); nvif_object_fini(&drm->ntfy);
nvkm_gpuobj_del(&drm->notify); nvkm_gpuobj_del(&drm->notify);
nvif_notify_fini(&drm->flip);
nvif_object_fini(&drm->nvsw); 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); nvif_object_fini(&drm->ttm.copy);
nouveau_channel_del(&drm->cechan);
if (drm->fence) if (drm->fence)
nouveau_fence(drm)->dtor(drm); nouveau_fence(drm)->dtor(drm);
} }
......
...@@ -3,7 +3,6 @@ nvkm-y += nvkm/core/engine.o ...@@ -3,7 +3,6 @@ nvkm-y += nvkm/core/engine.o
nvkm-y += nvkm/core/enum.o nvkm-y += nvkm/core/enum.o
nvkm-y += nvkm/core/event.o nvkm-y += nvkm/core/event.o
nvkm-y += nvkm/core/gpuobj.o nvkm-y += nvkm/core/gpuobj.o
nvkm-y += nvkm/core/handle.o
nvkm-y += nvkm/core/ioctl.o nvkm-y += nvkm/core/ioctl.o
nvkm-y += nvkm/core/memory.o nvkm-y += nvkm/core/memory.o
nvkm-y += nvkm/core/mm.o nvkm-y += nvkm/core/mm.o
......
...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
*/ */
#include <core/client.h> #include <core/client.h>
#include <core/device.h> #include <core/device.h>
#include <core/handle.h>
#include <core/notify.h> #include <core/notify.h>
#include <core/option.h> #include <core/option.h>
...@@ -91,7 +90,7 @@ int ...@@ -91,7 +90,7 @@ int
nvkm_client_notify_new(struct nvkm_object *object, nvkm_client_notify_new(struct nvkm_object *object,
struct nvkm_event *event, void *data, u32 size) 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; struct nvkm_client_notify *notify;
union { union {
struct nvif_notify_req_v0 v0; struct nvif_notify_req_v0 v0;
...@@ -207,47 +206,47 @@ nvkm_client_object_func = { ...@@ -207,47 +206,47 @@ nvkm_client_object_func = {
}; };
void 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)) if (!RB_EMPTY_NODE(&object->node))
rb_erase(&object->rb, &client->objroot); rb_erase(&object->node, &client->objroot);
} }
bool 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 **ptr = &client->objroot.rb_node;
struct rb_node *parent = NULL; struct rb_node *parent = NULL;
while (*ptr) { while (*ptr) {
struct nvkm_handle *this = struct nvkm_object *this =
container_of(*ptr, typeof(*this), rb); container_of(*ptr, typeof(*this), node);
parent = *ptr; parent = *ptr;
if (object->handle < this->handle) if (object->object < this->object)
ptr = &parent->rb_left; ptr = &parent->rb_left;
else else
if (object->handle > this->handle) if (object->object > this->object)
ptr = &parent->rb_right; ptr = &parent->rb_right;
else else
return false; return false;
} }
rb_link_node(&object->rb, parent, ptr); rb_link_node(&object->node, parent, ptr);
rb_insert_color(&object->rb, &client->objroot); rb_insert_color(&object->node, &client->objroot);
return true; return true;
} }
struct nvkm_handle * struct nvkm_object *
nvkm_client_search(struct nvkm_client *client, u64 handle) nvkm_client_search(struct nvkm_client *client, u64 handle)
{ {
struct rb_node *node = client->objroot.rb_node; struct rb_node *node = client->objroot.rb_node;
while (node) { while (node) {
struct nvkm_handle *object = struct nvkm_object *object =
container_of(node, typeof(*object), rb); container_of(node, typeof(*object), node);
if (handle < object->handle) if (handle < object->object)
node = node->rb_left; node = node->rb_left;
else else
if (handle > object->handle) if (handle > object->object)
node = node->rb_right; node = node->rb_right;
else else
return object; return object;
...@@ -260,26 +259,17 @@ nvkm_client_fini(struct nvkm_client *client, bool suspend) ...@@ -260,26 +259,17 @@ nvkm_client_fini(struct nvkm_client *client, bool suspend)
{ {
struct nvkm_object *object = &client->object; struct nvkm_object *object = &client->object;
const char *name[2] = { "fini", "suspend" }; const char *name[2] = { "fini", "suspend" };
int ret, i; int i;
nvif_trace(object, "%s running\n", name[suspend]); nvif_debug(object, "%s notify\n", name[suspend]);
nvif_trace(object, "%s notify\n", name[suspend]);
for (i = 0; i < ARRAY_SIZE(client->notify); i++) for (i = 0; i < ARRAY_SIZE(client->notify); i++)
nvkm_client_notify_put(client, i); nvkm_client_notify_put(client, i);
nvif_trace(object, "%s object\n", name[suspend]); return nvkm_object_fini(&client->object, suspend);
ret = nvkm_handle_fini(client->root, suspend);
nvif_trace(object, "%s completed with %d\n", name[suspend], ret);
return ret;
} }
int int
nvkm_client_init(struct nvkm_client *client) nvkm_client_init(struct nvkm_client *client)
{ {
struct nvkm_object *object = &client->object; return nvkm_object_init(&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;
} }
void void
...@@ -291,7 +281,7 @@ nvkm_client_del(struct nvkm_client **pclient) ...@@ -291,7 +281,7 @@ nvkm_client_del(struct nvkm_client **pclient)
nvkm_client_fini(client, false); nvkm_client_fini(client, false);
for (i = 0; i < ARRAY_SIZE(client->notify); i++) for (i = 0; i < ARRAY_SIZE(client->notify); i++)
nvkm_client_notify_del(client, i); nvkm_client_notify_del(client, i);
nvkm_handle_destroy(client->root); nvkm_object_dtor(&client->object);
kfree(*pclient); kfree(*pclient);
*pclient = NULL; *pclient = NULL;
} }
...@@ -303,7 +293,6 @@ nvkm_client_new(const char *name, u64 device, const char *cfg, ...@@ -303,7 +293,6 @@ nvkm_client_new(const char *name, u64 device, const char *cfg,
{ {
struct nvkm_oclass oclass = {}; struct nvkm_oclass oclass = {};
struct nvkm_client *client; struct nvkm_client *client;
int ret;
if (!(client = *pclient = kzalloc(sizeof(*client), GFP_KERNEL))) if (!(client = *pclient = kzalloc(sizeof(*client), GFP_KERNEL)))
return -ENOMEM; return -ENOMEM;
...@@ -315,9 +304,5 @@ nvkm_client_new(const char *name, u64 device, const char *cfg, ...@@ -315,9 +304,5 @@ nvkm_client_new(const char *name, u64 device, const char *cfg,
client->debug = nvkm_dbgopt(dbg, "CLIENT"); client->debug = nvkm_dbgopt(dbg, "CLIENT");
client->objroot = RB_ROOT; client->objroot = RB_ROOT;
client->dmaroot = RB_ROOT; client->dmaroot = RB_ROOT;
return 0;
ret = nvkm_handle_create(NULL, ~0, &client->object, &client->root);
if (ret)
nvkm_client_del(pclient);
return ret;
} }
/*
* 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);
}
...@@ -24,15 +24,13 @@ ...@@ -24,15 +24,13 @@
#include <core/ioctl.h> #include <core/ioctl.h>
#include <core/client.h> #include <core/client.h>
#include <core/engine.h> #include <core/engine.h>
#include <core/handle.h>
#include <nvif/unpack.h> #include <nvif/unpack.h>
#include <nvif/ioctl.h> #include <nvif/ioctl.h>
static int 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 { union {
struct nvif_ioctl_nop_v0 v0; struct nvif_ioctl_nop_v0 v0;
} *args = data; } *args = data;
...@@ -48,9 +46,8 @@ nvkm_ioctl_nop(struct nvkm_handle *handle, void *data, u32 size) ...@@ -48,9 +46,8 @@ nvkm_ioctl_nop(struct nvkm_handle *handle, void *data, u32 size)
} }
static int 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 { union {
struct nvif_ioctl_sclass_v0 v0; struct nvif_ioctl_sclass_v0 v0;
} *args = data; } *args = data;
...@@ -81,13 +78,12 @@ nvkm_ioctl_sclass(struct nvkm_handle *handle, void *data, u32 size) ...@@ -81,13 +78,12 @@ nvkm_ioctl_sclass(struct nvkm_handle *handle, void *data, u32 size)
} }
static int 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 { union {
struct nvif_ioctl_new_v0 v0; struct nvif_ioctl_new_v0 v0;
} *args = data; } *args = data;
struct nvkm_client *client = handle->object->client; struct nvkm_client *client = parent->client;
struct nvkm_object *parent = handle->object;
struct nvkm_object *object = NULL; struct nvkm_object *object = NULL;
struct nvkm_oclass oclass; struct nvkm_oclass oclass;
int ret, i = 0; int ret, i = 0;
...@@ -124,38 +120,30 @@ nvkm_ioctl_new(struct nvkm_handle *handle, void *data, u32 size) ...@@ -124,38 +120,30 @@ nvkm_ioctl_new(struct nvkm_handle *handle, void *data, u32 size)
} }
ret = oclass.ctor(&oclass, data, size, &object); 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); 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; return ret;
} }
static int 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 { union {
struct nvif_ioctl_del none; struct nvif_ioctl_del none;
} *args = data; } *args = data;
...@@ -164,17 +152,16 @@ nvkm_ioctl_del(struct nvkm_handle *handle, void *data, u32 size) ...@@ -164,17 +152,16 @@ nvkm_ioctl_del(struct nvkm_handle *handle, void *data, u32 size)
nvif_ioctl(object, "delete size %d\n", size); nvif_ioctl(object, "delete size %d\n", size);
if (nvif_unvers(args->none)) { if (nvif_unvers(args->none)) {
nvif_ioctl(object, "delete\n"); nvif_ioctl(object, "delete\n");
nvkm_handle_fini(handle, false); nvkm_object_fini(object, false);
nvkm_handle_destroy(handle); nvkm_object_del(&object);
} }
return ret; return ret;
} }
static int 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 { union {
struct nvif_ioctl_mthd_v0 v0; struct nvif_ioctl_mthd_v0 v0;
} *args = data; } *args = data;
...@@ -192,9 +179,8 @@ nvkm_ioctl_mthd(struct nvkm_handle *handle, void *data, u32 size) ...@@ -192,9 +179,8 @@ nvkm_ioctl_mthd(struct nvkm_handle *handle, void *data, u32 size)
static int 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 { union {
struct nvif_ioctl_rd_v0 v0; struct nvif_ioctl_rd_v0 v0;
} *args = data; } *args = data;
...@@ -232,9 +218,8 @@ nvkm_ioctl_rd(struct nvkm_handle *handle, void *data, u32 size) ...@@ -232,9 +218,8 @@ nvkm_ioctl_rd(struct nvkm_handle *handle, void *data, u32 size)
} }
static int 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 { union {
struct nvif_ioctl_wr_v0 v0; struct nvif_ioctl_wr_v0 v0;
} *args = data; } *args = data;
...@@ -261,9 +246,8 @@ nvkm_ioctl_wr(struct nvkm_handle *handle, void *data, u32 size) ...@@ -261,9 +246,8 @@ nvkm_ioctl_wr(struct nvkm_handle *handle, void *data, u32 size)
} }
static int 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 { union {
struct nvif_ioctl_map_v0 v0; struct nvif_ioctl_map_v0 v0;
} *args = data; } *args = data;
...@@ -280,9 +264,8 @@ nvkm_ioctl_map(struct nvkm_handle *handle, void *data, u32 size) ...@@ -280,9 +264,8 @@ nvkm_ioctl_map(struct nvkm_handle *handle, void *data, u32 size)
} }
static int 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 { union {
struct nvif_ioctl_unmap none; struct nvif_ioctl_unmap none;
} *args = data; } *args = data;
...@@ -297,9 +280,8 @@ nvkm_ioctl_unmap(struct nvkm_handle *handle, void *data, u32 size) ...@@ -297,9 +280,8 @@ nvkm_ioctl_unmap(struct nvkm_handle *handle, void *data, u32 size)
} }
static int 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 { union {
struct nvif_ioctl_ntfy_new_v0 v0; struct nvif_ioctl_ntfy_new_v0 v0;
} *args = data; } *args = data;
...@@ -324,10 +306,9 @@ nvkm_ioctl_ntfy_new(struct nvkm_handle *handle, void *data, u32 size) ...@@ -324,10 +306,9 @@ nvkm_ioctl_ntfy_new(struct nvkm_handle *handle, void *data, u32 size)
} }
static int 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_client *client = object->client;
struct nvkm_object *object = handle->object;
union { union {
struct nvif_ioctl_ntfy_del_v0 v0; struct nvif_ioctl_ntfy_del_v0 v0;
} *args = data; } *args = data;
...@@ -344,10 +325,9 @@ nvkm_ioctl_ntfy_del(struct nvkm_handle *handle, void *data, u32 size) ...@@ -344,10 +325,9 @@ nvkm_ioctl_ntfy_del(struct nvkm_handle *handle, void *data, u32 size)
} }
static int 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_client *client = object->client;
struct nvkm_object *object = handle->object;
union { union {
struct nvif_ioctl_ntfy_get_v0 v0; struct nvif_ioctl_ntfy_get_v0 v0;
} *args = data; } *args = data;
...@@ -364,10 +344,9 @@ nvkm_ioctl_ntfy_get(struct nvkm_handle *handle, void *data, u32 size) ...@@ -364,10 +344,9 @@ nvkm_ioctl_ntfy_get(struct nvkm_handle *handle, void *data, u32 size)
} }
static int 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_client *client = object->client;
struct nvkm_object *object = handle->object;
union { union {
struct nvif_ioctl_ntfy_put_v0 v0; struct nvif_ioctl_ntfy_put_v0 v0;
} *args = data; } *args = data;
...@@ -385,7 +364,7 @@ nvkm_ioctl_ntfy_put(struct nvkm_handle *handle, void *data, u32 size) ...@@ -385,7 +364,7 @@ nvkm_ioctl_ntfy_put(struct nvkm_handle *handle, void *data, u32 size)
static struct { static struct {
int version; int version;
int (*func)(struct nvkm_handle *, void *, u32); int (*func)(struct nvkm_object *, void *, u32);
} }
nvkm_ioctl_v0[] = { nvkm_ioctl_v0[] = {
{ 0x00, nvkm_ioctl_nop }, { 0x00, nvkm_ioctl_nop },
...@@ -407,13 +386,13 @@ static int ...@@ -407,13 +386,13 @@ static int
nvkm_ioctl_path(struct nvkm_client *client, u64 handle, u32 type, nvkm_ioctl_path(struct nvkm_client *client, u64 handle, u32 type,
void *data, u32 size, u8 owner, u8 *route, u64 *token) void *data, u32 size, u8 owner, u8 *route, u64 *token)
{ {
struct nvkm_handle *object; struct nvkm_object *object;
int ret; int ret;
if (handle) if (handle)
object = nvkm_client_search(client, handle); object = nvkm_client_search(client, handle);
else else
object = client->root; object = &client->object;
if (unlikely(!object)) { if (unlikely(!object)) {
nvif_ioctl(&client->object, "object not found\n"); nvif_ioctl(&client->object, "object not found\n");
return -ENOENT; return -ENOENT;
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
* Authors: Ben Skeggs * Authors: Ben Skeggs
*/ */
#include <core/object.h> #include <core/object.h>
#include <core/client.h>
#include <core/engine.h> #include <core/engine.h>
int int
...@@ -109,28 +110,112 @@ nvkm_object_bind(struct nvkm_object *object, struct nvkm_gpuobj *gpuobj, ...@@ -109,28 +110,112 @@ nvkm_object_bind(struct nvkm_object *object, struct nvkm_gpuobj *gpuobj,
int int
nvkm_object_fini(struct nvkm_object *object, bool suspend) nvkm_object_fini(struct nvkm_object *object, bool suspend)
{ {
if (object->func->fini) const char *action = suspend ? "suspend" : "fini";
return object->func->fini(object, suspend); 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; 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 int
nvkm_object_init(struct nvkm_object *object) nvkm_object_init(struct nvkm_object *object)
{ {
if (object->func->init) struct nvkm_object *child;
return object->func->init(object); 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; 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_del(struct nvkm_object **pobject) nvkm_object_dtor(struct nvkm_object *object)
{ {
struct nvkm_object *object = *pobject; 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);
}
if (object && !WARN_ON(!object->func)) { nvif_debug(object, "destroy running...\n");
if (object->func->dtor) if (object->func->dtor)
*pobject = object->func->dtor(object); data = object->func->dtor(object);
nvkm_engine_unref(&object->engine); 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)) {
*pobject = nvkm_object_dtor(object);
nvkm_client_remove(object->client, object);
list_del(&object->head);
kfree(*pobject); kfree(*pobject);
*pobject = NULL; *pobject = NULL;
} }
...@@ -145,9 +230,10 @@ nvkm_object_ctor(const struct nvkm_object_func *func, ...@@ -145,9 +230,10 @@ nvkm_object_ctor(const struct nvkm_object_func *func,
object->engine = nvkm_engine_ref(oclass->engine); object->engine = nvkm_engine_ref(oclass->engine);
object->oclass = oclass->base.oclass; object->oclass = oclass->base.oclass;
object->handle = oclass->handle; object->handle = oclass->handle;
object->parent = oclass->parent; INIT_LIST_HEAD(&object->head);
atomic_set(&object->refcount, 1); INIT_LIST_HEAD(&object->tree);
atomic_set(&object->usecount, 0); RB_CLEAR_NODE(&object->node);
WARN_ON(oclass->engine && !object->engine);
} }
int int
...@@ -176,106 +262,3 @@ nvkm_object_new(const struct nvkm_oclass *oclass, void *data, u32 size, ...@@ -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; oclass->base.func ? oclass->base.func : &nvkm_object_func;
return nvkm_object_new_(func, oclass, data, size, pobject); 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;
}
...@@ -109,9 +109,11 @@ nvkm_oproxy_fini(struct nvkm_object *object, bool suspend) ...@@ -109,9 +109,11 @@ nvkm_oproxy_fini(struct nvkm_object *object, bool suspend)
return ret; return ret;
} }
ret = nvkm_object_fini(oproxy->object, suspend); if (oproxy->object->func->fini) {
ret = oproxy->object->func->fini(oproxy->object, suspend);
if (ret && suspend) if (ret && suspend)
return ret; return ret;
}
if (oproxy->func->fini[1]) { if (oproxy->func->fini[1]) {
ret = oproxy->func->fini[1](oproxy, suspend); ret = oproxy->func->fini[1](oproxy, suspend);
...@@ -134,9 +136,11 @@ nvkm_oproxy_init(struct nvkm_object *object) ...@@ -134,9 +136,11 @@ nvkm_oproxy_init(struct nvkm_object *object)
return ret; return ret;
} }
ret = nvkm_object_init(oproxy->object); if (oproxy->object->func->init) {
ret = oproxy->object->func->init(oproxy->object);
if (ret) if (ret)
return ret; return ret;
}
if (oproxy->func->init[1]) { if (oproxy->func->init[1]) {
ret = oproxy->func->init[1](oproxy); ret = oproxy->func->init[1](oproxy);
...@@ -153,7 +157,7 @@ nvkm_oproxy_dtor(struct nvkm_object *object) ...@@ -153,7 +157,7 @@ nvkm_oproxy_dtor(struct nvkm_object *object)
struct nvkm_oproxy *oproxy = nvkm_oproxy(object); struct nvkm_oproxy *oproxy = nvkm_oproxy(object);
if (oproxy->func->dtor[0]) if (oproxy->func->dtor[0])
oproxy->func->dtor[0](oproxy); oproxy->func->dtor[0](oproxy);
nvkm_object_ref(NULL, &oproxy->object); nvkm_object_del(&oproxy->object);
if (oproxy->func->dtor[1]) if (oproxy->func->dtor[1])
oproxy->func->dtor[1](oproxy); oproxy->func->dtor[1](oproxy);
return oproxy; return oproxy;
......
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
#include "rootnv50.h" #include "rootnv50.h"
#include <core/client.h> #include <core/client.h>
#include <core/handle.h>
#include <core/oproxy.h> #include <core/oproxy.h>
#include <core/ramht.h> #include <core/ramht.h>
#include <subdev/fb.h> #include <subdev/fb.h>
......
...@@ -116,7 +116,7 @@ nvkm_fifo_chan_child_del(struct nvkm_oproxy *base) ...@@ -116,7 +116,7 @@ nvkm_fifo_chan_child_del(struct nvkm_oproxy *base)
if (!--engn->refcount) { if (!--engn->refcount) {
if (chan->func->engine_dtor) if (chan->func->engine_dtor)
chan->func->engine_dtor(chan, engine); chan->func->engine_dtor(chan, engine);
nvkm_object_ref(NULL, &engn->object); nvkm_object_del(&engn->object);
if (chan->vm) if (chan->vm)
atomic_dec(&chan->vm->engref[engine->subdev.index]); atomic_dec(&chan->vm->engref[engine->subdev.index]);
} }
......
...@@ -27,7 +27,6 @@ ...@@ -27,7 +27,6 @@
#include <core/client.h> #include <core/client.h>
#include <core/enum.h> #include <core/enum.h>
#include <core/gpuobj.h> #include <core/gpuobj.h>
#include <core/handle.h>
#include <subdev/bar.h> #include <subdev/bar.h>
#include <engine/sw.h> #include <engine/sw.h>
......
...@@ -27,7 +27,6 @@ ...@@ -27,7 +27,6 @@
#include <core/client.h> #include <core/client.h>
#include <core/enum.h> #include <core/enum.h>
#include <core/gpuobj.h> #include <core/gpuobj.h>
#include <core/handle.h>
#include <subdev/bar.h> #include <subdev/bar.h>
#include <engine/sw.h> #include <engine/sw.h>
......
...@@ -26,7 +26,6 @@ ...@@ -26,7 +26,6 @@
#include "regsnv04.h" #include "regsnv04.h"
#include <core/client.h> #include <core/client.h>
#include <core/handle.h>
#include <core/ramht.h> #include <core/ramht.h>
#include <subdev/instmem.h> #include <subdev/instmem.h>
#include <subdev/timer.h> #include <subdev/timer.h>
......
...@@ -24,7 +24,6 @@ ...@@ -24,7 +24,6 @@
#include "nv50.h" #include "nv50.h"
#include <core/gpuobj.h> #include <core/gpuobj.h>
#include <core/handle.h>
#include <engine/disp.h> #include <engine/disp.h>
#include <engine/fifo/chan.h> #include <engine/fifo/chan.h>
#include <subdev/bar.h> #include <subdev/bar.h>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment