提交 fbd58ebd 编写于 作者: B Ben Skeggs

drm/nouveau/object: merge with handle

Signed-off-by: NBen Skeggs <bskeggs@redhat.com>
上级 68f3f702
master alk-4.19.24 alk-4.19.30 alk-4.19.34 alk-4.19.36 alk-4.19.43 alk-4.19.48 alk-4.19.57 ck-4.19.67 ck-4.19.81 ck-4.19.91 github/fork/deepanshu1422/fix-typo-in-comment github/fork/haosdent/fix-typo linux-next v4.19.91 v4.19.90 v4.19.89 v4.19.88 v4.19.87 v4.19.86 v4.19.85 v4.19.84 v4.19.83 v4.19.82 v4.19.81 v4.19.80 v4.19.79 v4.19.78 v4.19.77 v4.19.76 v4.19.75 v4.19.74 v4.19.73 v4.19.72 v4.19.71 v4.19.70 v4.19.69 v4.19.68 v4.19.67 v4.19.66 v4.19.65 v4.19.64 v4.19.63 v4.19.62 v4.19.61 v4.19.60 v4.19.59 v4.19.58 v4.19.57 v4.19.56 v4.19.55 v4.19.54 v4.19.53 v4.19.52 v4.19.51 v4.19.50 v4.19.49 v4.19.48 v4.19.47 v4.19.46 v4.19.45 v4.19.44 v4.19.43 v4.19.42 v4.19.41 v4.19.40 v4.19.39 v4.19.38 v4.19.37 v4.19.36 v4.19.35 v4.19.34 v4.19.33 v4.19.32 v4.19.31 v4.19.30 v4.19.29 v4.19.28 v4.19.27 v4.19.26 v4.19.25 v4.19.24 v4.19.23 v4.19.22 v4.19.21 v4.19.20 v4.19.19 v4.19.18 v4.19.17 v4.19.16 v4.19.15 v4.19.14 v4.19.13 v4.19.12 v4.19.11 v4.19.10 v4.19.9 v4.19.8 v4.19.7 v4.19.6 v4.19.5 v4.19.4 v4.19.3 v4.19.2 v4.19.1 v4.19 v4.19-rc8 v4.19-rc7 v4.19-rc6 v4.19-rc5 v4.19-rc4 v4.19-rc3 v4.19-rc2 v4.19-rc1 ck-release-21 ck-release-20 ck-release-19.2 ck-release-19.1 ck-release-19 ck-release-18 ck-release-17.2 ck-release-17.1 ck-release-17 ck-release-16 ck-release-15.1 ck-release-15 ck-release-14 ck-release-13.2 ck-release-13 ck-release-12 ck-release-11 ck-release-10 ck-release-9 ck-release-7 alk-release-15 alk-release-14 alk-release-13.2 alk-release-13 alk-release-12 alk-release-11 alk-release-10 alk-release-9 alk-release-7
无相关合并请求
......@@ -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
#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 {
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
......@@ -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);
}
......
......@@ -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);
......
......@@ -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);
}
......
......@@ -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
......
......@@ -23,7 +23,6 @@
*/
#include <core/client.h>
#include <core/device.h>
#include <core/handle.h>
#include <core/notify.h>
#include <core/option.h>
......@@ -91,7 +90,7 @@ int
nvkm_client_notify_new(struct nvkm_object *object,
struct nvkm_event *event, void *data, u32 size)
{
struct nvkm_client *client = nvkm_client(object);
struct nvkm_client *client = object->client;
struct nvkm_client_notify *notify;
union {
struct nvif_notify_req_v0 v0;
......@@ -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;
}
/*
* 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 @@
#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;
......@@ -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;
......
......@@ -22,6 +22,7 @@
* Authors: Ben Skeggs
*/
#include <core/object.h>
#include <core/client.h>
#include <core/engine.h>
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;
}
......@@ -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;
......
......@@ -25,7 +25,6 @@
#include "rootnv50.h"
#include <core/client.h>
#include <core/handle.h>
#include <core/oproxy.h>
#include <core/ramht.h>
#include <subdev/fb.h>
......
......@@ -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]);
}
......
......@@ -27,7 +27,6 @@
#include <core/client.h>
#include <core/enum.h>
#include <core/gpuobj.h>
#include <core/handle.h>
#include <subdev/bar.h>
#include <engine/sw.h>
......
......@@ -27,7 +27,6 @@
#include <core/client.h>
#include <core/enum.h>
#include <core/gpuobj.h>
#include <core/handle.h>
#include <subdev/bar.h>
#include <engine/sw.h>
......
......@@ -26,7 +26,6 @@
#include "regsnv04.h"
#include <core/client.h>
#include <core/handle.h>
#include <core/ramht.h>
#include <subdev/instmem.h>
#include <subdev/timer.h>
......
......@@ -24,7 +24,6 @@
#include "nv50.h"
#include <core/gpuobj.h>
#include <core/handle.h>
#include <engine/disp.h>
#include <engine/fifo/chan.h>
#include <subdev/bar.h>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册
反馈
建议
客服 返回
顶部