aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2015-08-20 00:54:22 -0400
committerBen Skeggs <bskeggs@redhat.com>2015-08-27 22:40:47 -0400
commitfbd58ebda9c8572ca6285b88e3348c7712f125ec (patch)
tree1c72cee029d928003eadb62cbee945dee2c5298e
parent68f3f702b6a430a8d1e909455a60d26c0f2da530 (diff)
drm/nouveau/object: merge with handle
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/client.h23
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/handle.h34
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/object.h23
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_abi16.c1
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_chan.c34
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drm.c10
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/Kbuild1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/client.c59
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/handle.c139
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/ioctl.c99
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/object.c213
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/oproxy.c18
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c1
18 files changed, 219 insertions, 442 deletions
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/client.h b/drivers/gpu/drm/nouveau/include/nvkm/core/client.h
index 5485bbac5677..eaf5905a87a3 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/core/client.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/core/client.h
@@ -12,8 +12,6 @@ struct nvkm_client {
12 struct rb_root objroot; 12 struct rb_root objroot;
13 struct rb_root dmaroot; 13 struct rb_root dmaroot;
14 14
15 struct nvkm_handle *root;
16
17 bool super; 15 bool super;
18 void *data; 16 void *data;
19 int (*ntfy)(const void *, u32, const void *, u32); 17 int (*ntfy)(const void *, u32, const void *, u32);
@@ -21,9 +19,9 @@ struct nvkm_client {
21 struct nvkm_vm *vm; 19 struct nvkm_vm *vm;
22}; 20};
23 21
24bool nvkm_client_insert(struct nvkm_client *, struct nvkm_handle *); 22bool nvkm_client_insert(struct nvkm_client *, struct nvkm_object *);
25void nvkm_client_remove(struct nvkm_client *, struct nvkm_handle *); 23void nvkm_client_remove(struct nvkm_client *, struct nvkm_object *);
26struct nvkm_handle *nvkm_client_search(struct nvkm_client *, u64 handle); 24struct nvkm_object *nvkm_client_search(struct nvkm_client *, u64 object);
27 25
28int nvkm_client_new(const char *name, u64 device, const char *cfg, 26int nvkm_client_new(const char *name, u64 device, const char *cfg,
29 const char *dbg, struct nvkm_client **); 27 const char *dbg, struct nvkm_client **);
@@ -31,14 +29,6 @@ void nvkm_client_del(struct nvkm_client **);
31int nvkm_client_init(struct nvkm_client *); 29int nvkm_client_init(struct nvkm_client *);
32int nvkm_client_fini(struct nvkm_client *, bool suspend); 30int nvkm_client_fini(struct nvkm_client *, bool suspend);
33 31
34static inline struct nvkm_client *
35nvkm_client(struct nvkm_object *object)
36{
37 while (object && object->parent)
38 object = object->parent;
39 return container_of(object, struct nvkm_client, object);
40}
41
42int nvkm_client_notify_new(struct nvkm_object *, struct nvkm_event *, 32int nvkm_client_notify_new(struct nvkm_object *, struct nvkm_event *,
43 void *data, u32 size); 33 void *data, u32 size);
44int nvkm_client_notify_del(struct nvkm_client *, int index); 34int nvkm_client_notify_del(struct nvkm_client *, int index);
@@ -48,12 +38,15 @@ int nvkm_client_notify_put(struct nvkm_client *, int index);
48/* logging for client-facing objects */ 38/* logging for client-facing objects */
49#define nvif_printk(o,l,p,f,a...) do { \ 39#define nvif_printk(o,l,p,f,a...) do { \
50 struct nvkm_object *_object = (o); \ 40 struct nvkm_object *_object = (o); \
51 struct nvkm_client *_client = nvkm_client(_object); \ 41 struct nvkm_client *_client = _object->client; \
52 if (_client->debug >= NV_DBG_##l) \ 42 if (_client->debug >= NV_DBG_##l) \
53 printk(KERN_##p "nouveau: %s: "f, _client->name, ##a); \ 43 printk(KERN_##p "nouveau: %s:%08x:%08x: "f, _client->name, \
44 _object->handle, _object->oclass, ##a); \
54} while(0) 45} while(0)
46#define nvif_fatal(o,f,a...) nvif_printk((o), FATAL, CRIT, f, ##a)
55#define nvif_error(o,f,a...) nvif_printk((o), ERROR, ERR, f, ##a) 47#define nvif_error(o,f,a...) nvif_printk((o), ERROR, ERR, f, ##a)
56#define nvif_debug(o,f,a...) nvif_printk((o), DEBUG, INFO, f, ##a) 48#define nvif_debug(o,f,a...) nvif_printk((o), DEBUG, INFO, f, ##a)
57#define nvif_trace(o,f,a...) nvif_printk((o), TRACE, INFO, f, ##a) 49#define nvif_trace(o,f,a...) nvif_printk((o), TRACE, INFO, f, ##a)
50#define nvif_info(o,f,a...) nvif_printk((o), INFO, INFO, f, ##a)
58#define nvif_ioctl(o,f,a...) nvif_trace((o), "ioctl: "f, ##a) 51#define nvif_ioctl(o,f,a...) nvif_trace((o), "ioctl: "f, ##a)
59#endif 52#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/handle.h b/drivers/gpu/drm/nouveau/include/nvkm/core/handle.h
deleted file mode 100644
index 539278916d23..000000000000
--- a/drivers/gpu/drm/nouveau/include/nvkm/core/handle.h
+++ /dev/null
@@ -1,34 +0,0 @@
1#ifndef __NVKM_HANDLE_H__
2#define __NVKM_HANDLE_H__
3#include <core/os.h>
4struct nvkm_object;
5
6struct nvkm_handle {
7 struct list_head node;
8
9 struct list_head head;
10 struct list_head tree;
11 u32 name;
12 u32 priv;
13
14 u8 route;
15 u64 token;
16
17 struct nvkm_handle *parent;
18 struct nvkm_object *object;
19
20 struct rb_node rb;
21 u64 handle;
22};
23
24int nvkm_handle_create(struct nvkm_handle *, u32 handle,
25 struct nvkm_object *, struct nvkm_handle **);
26void nvkm_handle_destroy(struct nvkm_handle *);
27int nvkm_handle_init(struct nvkm_handle *);
28int nvkm_handle_fini(struct nvkm_handle *, bool suspend);
29
30struct nvkm_handle *nvkm_handle_get_class(struct nvkm_object *, u16);
31struct nvkm_handle *nvkm_handle_get_vinst(struct nvkm_object *, u64);
32struct nvkm_handle *nvkm_handle_get_cinst(struct nvkm_object *, u32);
33void nvkm_handle_put(struct nvkm_handle *);
34#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/object.h b/drivers/gpu/drm/nouveau/include/nvkm/core/object.h
index b4b822f6155c..dcd048b91fac 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/core/object.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/core/object.h
@@ -10,12 +10,15 @@ struct nvkm_object {
10 const struct nvkm_object_func *func; 10 const struct nvkm_object_func *func;
11 struct nvkm_client *client; 11 struct nvkm_client *client;
12 struct nvkm_engine *engine; 12 struct nvkm_engine *engine;
13 u32 oclass; 13 s32 oclass;
14 u32 handle; 14 u32 handle;
15 struct nvkm_object *parent; 15
16 u32 pclass; 16 struct list_head head;
17 atomic_t refcount; 17 struct list_head tree;
18 atomic_t usecount; 18 u8 route;
19 u64 token;
20 u64 object;
21 struct rb_node node;
19}; 22};
20 23
21struct nvkm_object_func { 24struct nvkm_object_func {
@@ -43,6 +46,8 @@ int nvkm_object_new_(const struct nvkm_object_func *,
43 struct nvkm_object **); 46 struct nvkm_object **);
44int nvkm_object_new(const struct nvkm_oclass *, void *data, u32 size, 47int nvkm_object_new(const struct nvkm_oclass *, void *data, u32 size,
45 struct nvkm_object **); 48 struct nvkm_object **);
49void nvkm_object_del(struct nvkm_object **);
50void *nvkm_object_dtor(struct nvkm_object *);
46int nvkm_object_init(struct nvkm_object *); 51int nvkm_object_init(struct nvkm_object *);
47int nvkm_object_fini(struct nvkm_object *, bool suspend); 52int nvkm_object_fini(struct nvkm_object *, bool suspend);
48int nvkm_object_mthd(struct nvkm_object *, u32 mthd, void *data, u32 size); 53int nvkm_object_mthd(struct nvkm_object *, u32 mthd, void *data, u32 size);
@@ -72,14 +77,12 @@ struct nvkm_oclass {
72 struct nvkm_sclass base; 77 struct nvkm_sclass base;
73 const void *priv; 78 const void *priv;
74 const void *engn; 79 const void *engn;
75 s32 handle; 80 u32 handle;
81 u8 route;
82 u64 token;
76 u64 object; 83 u64 object;
77 struct nvkm_client *client; 84 struct nvkm_client *client;
78 struct nvkm_object *parent; 85 struct nvkm_object *parent;
79 struct nvkm_engine *engine; 86 struct nvkm_engine *engine;
80}; 87};
81
82void nvkm_object_ref(struct nvkm_object *, struct nvkm_object **);
83int nvkm_object_inc(struct nvkm_object *);
84int nvkm_object_dec(struct nvkm_object *, bool suspend);
85#endif 88#endif
diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.c b/drivers/gpu/drm/nouveau/nouveau_abi16.c
index 6634f420ded3..40a903b79343 100644
--- a/drivers/gpu/drm/nouveau/nouveau_abi16.c
+++ b/drivers/gpu/drm/nouveau/nouveau_abi16.c
@@ -134,6 +134,7 @@ nouveau_abi16_chan_fini(struct nouveau_abi16 *abi16,
134 /* destroy channel object, all children will be killed too */ 134 /* destroy channel object, all children will be killed too */
135 if (chan->chan) { 135 if (chan->chan) {
136 abi16->handles &= ~(1ULL << (chan->chan->user.handle & 0xffff)); 136 abi16->handles &= ~(1ULL << (chan->chan->user.handle & 0xffff));
137 nouveau_channel_idle(chan->chan);
137 nouveau_channel_del(&chan->chan); 138 nouveau_channel_del(&chan->chan);
138 } 139 }
139 140
diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c
index 4a13bda1475b..8c88c5e5bf0b 100644
--- a/drivers/gpu/drm/nouveau/nouveau_chan.c
+++ b/drivers/gpu/drm/nouveau/nouveau_chan.c
@@ -43,20 +43,26 @@ module_param_named(vram_pushbuf, nouveau_vram_pushbuf, int, 0400);
43int 43int
44nouveau_channel_idle(struct nouveau_channel *chan) 44nouveau_channel_idle(struct nouveau_channel *chan)
45{ 45{
46 struct nouveau_cli *cli = (void *)chan->user.client; 46 if (likely(chan && chan->fence)) {
47 struct nouveau_fence *fence = NULL; 47 struct nouveau_cli *cli = (void *)chan->user.client;
48 int ret; 48 struct nouveau_fence *fence = NULL;
49 int ret;
50
51 ret = nouveau_fence_new(chan, false, &fence);
52 if (!ret) {
53 ret = nouveau_fence_wait(fence, false, false);
54 nouveau_fence_unref(&fence);
55 }
49 56
50 ret = nouveau_fence_new(chan, false, &fence); 57 if (ret) {
51 if (!ret) { 58 NV_PRINTK(err, cli, "failed to idle channel "
52 ret = nouveau_fence_wait(fence, false, false); 59 "0x%08x [%s]\n",
53 nouveau_fence_unref(&fence); 60 chan->user.handle,
61 nvxx_client(&cli->base)->name);
62 return ret;
63 }
54 } 64 }
55 65 return 0;
56 if (ret)
57 NV_PRINTK(err, cli, "failed to idle channel 0x%08x [%s]\n",
58 chan->user.handle, nvxx_client(&cli->base)->name);
59 return ret;
60} 66}
61 67
62void 68void
@@ -64,10 +70,8 @@ nouveau_channel_del(struct nouveau_channel **pchan)
64{ 70{
65 struct nouveau_channel *chan = *pchan; 71 struct nouveau_channel *chan = *pchan;
66 if (chan) { 72 if (chan) {
67 if (chan->fence) { 73 if (chan->fence)
68 nouveau_channel_idle(chan);
69 nouveau_fence(chan->drm)->context_del(chan); 74 nouveau_fence(chan->drm)->context_del(chan);
70 }
71 nvif_object_fini(&chan->nvsw); 75 nvif_object_fini(&chan->nvsw);
72 nvif_object_fini(&chan->gart); 76 nvif_object_fini(&chan->gart);
73 nvif_object_fini(&chan->vram); 77 nvif_object_fini(&chan->vram);
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index d04d08cc546d..14a13486c27f 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -139,13 +139,17 @@ nouveau_cli_destroy(struct nouveau_cli *cli)
139static void 139static void
140nouveau_accel_fini(struct nouveau_drm *drm) 140nouveau_accel_fini(struct nouveau_drm *drm)
141{ 141{
142 nvif_notify_fini(&drm->flip); 142 nouveau_channel_idle(drm->channel);
143 nouveau_channel_del(&drm->channel);
144 nvif_object_fini(&drm->ntfy); 143 nvif_object_fini(&drm->ntfy);
145 nvkm_gpuobj_del(&drm->notify); 144 nvkm_gpuobj_del(&drm->notify);
145 nvif_notify_fini(&drm->flip);
146 nvif_object_fini(&drm->nvsw); 146 nvif_object_fini(&drm->nvsw);
147 nouveau_channel_del(&drm->cechan); 147 nouveau_channel_del(&drm->channel);
148
149 nouveau_channel_idle(drm->cechan);
148 nvif_object_fini(&drm->ttm.copy); 150 nvif_object_fini(&drm->ttm.copy);
151 nouveau_channel_del(&drm->cechan);
152
149 if (drm->fence) 153 if (drm->fence)
150 nouveau_fence(drm)->dtor(drm); 154 nouveau_fence(drm)->dtor(drm);
151} 155}
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/Kbuild b/drivers/gpu/drm/nouveau/nvkm/core/Kbuild
index 09044cf0d9ff..7f66963f305c 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/Kbuild
+++ b/drivers/gpu/drm/nouveau/nvkm/core/Kbuild
@@ -3,7 +3,6 @@ nvkm-y += nvkm/core/engine.o
3nvkm-y += nvkm/core/enum.o 3nvkm-y += nvkm/core/enum.o
4nvkm-y += nvkm/core/event.o 4nvkm-y += nvkm/core/event.o
5nvkm-y += nvkm/core/gpuobj.o 5nvkm-y += nvkm/core/gpuobj.o
6nvkm-y += nvkm/core/handle.o
7nvkm-y += nvkm/core/ioctl.o 6nvkm-y += nvkm/core/ioctl.o
8nvkm-y += nvkm/core/memory.o 7nvkm-y += nvkm/core/memory.o
9nvkm-y += nvkm/core/mm.o 8nvkm-y += nvkm/core/mm.o
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/client.c b/drivers/gpu/drm/nouveau/nvkm/core/client.c
index ab98f8c45950..297e1e953fa6 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/client.c
+++ b/drivers/gpu/drm/nouveau/nvkm/core/client.c
@@ -23,7 +23,6 @@
23 */ 23 */
24#include <core/client.h> 24#include <core/client.h>
25#include <core/device.h> 25#include <core/device.h>
26#include <core/handle.h>
27#include <core/notify.h> 26#include <core/notify.h>
28#include <core/option.h> 27#include <core/option.h>
29 28
@@ -91,7 +90,7 @@ int
91nvkm_client_notify_new(struct nvkm_object *object, 90nvkm_client_notify_new(struct nvkm_object *object,
92 struct nvkm_event *event, void *data, u32 size) 91 struct nvkm_event *event, void *data, u32 size)
93{ 92{
94 struct nvkm_client *client = nvkm_client(object); 93 struct nvkm_client *client = object->client;
95 struct nvkm_client_notify *notify; 94 struct nvkm_client_notify *notify;
96 union { 95 union {
97 struct nvif_notify_req_v0 v0; 96 struct nvif_notify_req_v0 v0;
@@ -207,47 +206,47 @@ nvkm_client_object_func = {
207}; 206};
208 207
209void 208void
210nvkm_client_remove(struct nvkm_client *client, struct nvkm_handle *object) 209nvkm_client_remove(struct nvkm_client *client, struct nvkm_object *object)
211{ 210{
212 if (!RB_EMPTY_NODE(&object->rb)) 211 if (!RB_EMPTY_NODE(&object->node))
213 rb_erase(&object->rb, &client->objroot); 212 rb_erase(&object->node, &client->objroot);
214} 213}
215 214
216bool 215bool
217nvkm_client_insert(struct nvkm_client *client, struct nvkm_handle *object) 216nvkm_client_insert(struct nvkm_client *client, struct nvkm_object *object)
218{ 217{
219 struct rb_node **ptr = &client->objroot.rb_node; 218 struct rb_node **ptr = &client->objroot.rb_node;
220 struct rb_node *parent = NULL; 219 struct rb_node *parent = NULL;
221 220
222 while (*ptr) { 221 while (*ptr) {
223 struct nvkm_handle *this = 222 struct nvkm_object *this =
224 container_of(*ptr, typeof(*this), rb); 223 container_of(*ptr, typeof(*this), node);
225 parent = *ptr; 224 parent = *ptr;
226 if (object->handle < this->handle) 225 if (object->object < this->object)
227 ptr = &parent->rb_left; 226 ptr = &parent->rb_left;
228 else 227 else
229 if (object->handle > this->handle) 228 if (object->object > this->object)
230 ptr = &parent->rb_right; 229 ptr = &parent->rb_right;
231 else 230 else
232 return false; 231 return false;
233 } 232 }
234 233
235 rb_link_node(&object->rb, parent, ptr); 234 rb_link_node(&object->node, parent, ptr);
236 rb_insert_color(&object->rb, &client->objroot); 235 rb_insert_color(&object->node, &client->objroot);
237 return true; 236 return true;
238} 237}
239 238
240struct nvkm_handle * 239struct nvkm_object *
241nvkm_client_search(struct nvkm_client *client, u64 handle) 240nvkm_client_search(struct nvkm_client *client, u64 handle)
242{ 241{
243 struct rb_node *node = client->objroot.rb_node; 242 struct rb_node *node = client->objroot.rb_node;
244 while (node) { 243 while (node) {
245 struct nvkm_handle *object = 244 struct nvkm_object *object =
246 container_of(node, typeof(*object), rb); 245 container_of(node, typeof(*object), node);
247 if (handle < object->handle) 246 if (handle < object->object)
248 node = node->rb_left; 247 node = node->rb_left;
249 else 248 else
250 if (handle > object->handle) 249 if (handle > object->object)
251 node = node->rb_right; 250 node = node->rb_right;
252 else 251 else
253 return object; 252 return object;
@@ -260,26 +259,17 @@ nvkm_client_fini(struct nvkm_client *client, bool suspend)
260{ 259{
261 struct nvkm_object *object = &client->object; 260 struct nvkm_object *object = &client->object;
262 const char *name[2] = { "fini", "suspend" }; 261 const char *name[2] = { "fini", "suspend" };
263 int ret, i; 262 int i;
264 nvif_trace(object, "%s running\n", name[suspend]); 263 nvif_debug(object, "%s notify\n", name[suspend]);
265 nvif_trace(object, "%s notify\n", name[suspend]);
266 for (i = 0; i < ARRAY_SIZE(client->notify); i++) 264 for (i = 0; i < ARRAY_SIZE(client->notify); i++)
267 nvkm_client_notify_put(client, i); 265 nvkm_client_notify_put(client, i);
268 nvif_trace(object, "%s object\n", name[suspend]); 266 return nvkm_object_fini(&client->object, suspend);
269 ret = nvkm_handle_fini(client->root, suspend);
270 nvif_trace(object, "%s completed with %d\n", name[suspend], ret);
271 return ret;
272} 267}
273 268
274int 269int
275nvkm_client_init(struct nvkm_client *client) 270nvkm_client_init(struct nvkm_client *client)
276{ 271{
277 struct nvkm_object *object = &client->object; 272 return nvkm_object_init(&client->object);
278 int ret;
279 nvif_trace(object, "init running\n");
280 ret = nvkm_handle_init(client->root);
281 nvif_trace(object, "init completed with %d\n", ret);
282 return ret;
283} 273}
284 274
285void 275void
@@ -291,7 +281,7 @@ nvkm_client_del(struct nvkm_client **pclient)
291 nvkm_client_fini(client, false); 281 nvkm_client_fini(client, false);
292 for (i = 0; i < ARRAY_SIZE(client->notify); i++) 282 for (i = 0; i < ARRAY_SIZE(client->notify); i++)
293 nvkm_client_notify_del(client, i); 283 nvkm_client_notify_del(client, i);
294 nvkm_handle_destroy(client->root); 284 nvkm_object_dtor(&client->object);
295 kfree(*pclient); 285 kfree(*pclient);
296 *pclient = NULL; 286 *pclient = NULL;
297 } 287 }
@@ -303,7 +293,6 @@ nvkm_client_new(const char *name, u64 device, const char *cfg,
303{ 293{
304 struct nvkm_oclass oclass = {}; 294 struct nvkm_oclass oclass = {};
305 struct nvkm_client *client; 295 struct nvkm_client *client;
306 int ret;
307 296
308 if (!(client = *pclient = kzalloc(sizeof(*client), GFP_KERNEL))) 297 if (!(client = *pclient = kzalloc(sizeof(*client), GFP_KERNEL)))
309 return -ENOMEM; 298 return -ENOMEM;
@@ -315,9 +304,5 @@ nvkm_client_new(const char *name, u64 device, const char *cfg,
315 client->debug = nvkm_dbgopt(dbg, "CLIENT"); 304 client->debug = nvkm_dbgopt(dbg, "CLIENT");
316 client->objroot = RB_ROOT; 305 client->objroot = RB_ROOT;
317 client->dmaroot = RB_ROOT; 306 client->dmaroot = RB_ROOT;
318 307 return 0;
319 ret = nvkm_handle_create(NULL, ~0, &client->object, &client->root);
320 if (ret)
321 nvkm_client_del(pclient);
322 return ret;
323} 308}
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/handle.c b/drivers/gpu/drm/nouveau/nvkm/core/handle.c
deleted file mode 100644
index d185cae0fbba..000000000000
--- a/drivers/gpu/drm/nouveau/nvkm/core/handle.c
+++ /dev/null
@@ -1,139 +0,0 @@
1/*
2 * Copyright 2012 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs
23 */
24#include <core/handle.h>
25#include <core/client.h>
26
27#define hprintk(h,l,f,a...) do { \
28 struct nvkm_handle *p = (h)->parent; u32 n = p ? p->name : ~0; \
29 nvif_printk((h)->object, l, INFO, "0x%08x:0x%08x "f, n, (h)->name, ##a);\
30} while(0)
31
32int
33nvkm_handle_init(struct nvkm_handle *handle)
34{
35 struct nvkm_handle *item;
36 int ret;
37
38 hprintk(handle, TRACE, "init running\n");
39 ret = nvkm_object_inc(handle->object);
40 if (ret)
41 return ret;
42
43 hprintk(handle, TRACE, "init children\n");
44 list_for_each_entry(item, &handle->tree, head) {
45 ret = nvkm_handle_init(item);
46 if (ret)
47 goto fail;
48 }
49
50 hprintk(handle, TRACE, "init completed\n");
51 return 0;
52fail:
53 hprintk(handle, ERROR, "init failed with %d\n", ret);
54 list_for_each_entry_continue_reverse(item, &handle->tree, head) {
55 nvkm_handle_fini(item, false);
56 }
57
58 nvkm_object_dec(handle->object, false);
59 return ret;
60}
61
62int
63nvkm_handle_fini(struct nvkm_handle *handle, bool suspend)
64{
65 static char *name[2] = { "fini", "suspend" };
66 struct nvkm_handle *item;
67 int ret;
68
69 hprintk(handle, TRACE, "%s children\n", name[suspend]);
70 list_for_each_entry(item, &handle->tree, head) {
71 ret = nvkm_handle_fini(item, suspend);
72 if (ret && suspend)
73 goto fail;
74 }
75
76 hprintk(handle, TRACE, "%s running\n", name[suspend]);
77 if (handle->object) {
78 ret = nvkm_object_dec(handle->object, suspend);
79 if (ret && suspend)
80 goto fail;
81 }
82
83 hprintk(handle, TRACE, "%s completed\n", name[suspend]);
84 return 0;
85fail:
86 hprintk(handle, ERROR, "%s failed with %d\n", name[suspend], ret);
87 list_for_each_entry_continue_reverse(item, &handle->tree, head) {
88 int rret = nvkm_handle_init(item);
89 if (rret)
90 hprintk(handle, FATAL, "failed to restart, %d\n", rret);
91 }
92
93 return ret;
94}
95
96int
97nvkm_handle_create(struct nvkm_handle *parent, u32 _handle,
98 struct nvkm_object *object, struct nvkm_handle **phandle)
99{
100 struct nvkm_handle *handle;
101
102 handle = kzalloc(sizeof(*handle), GFP_KERNEL);
103 if (!handle)
104 return -ENOMEM;
105
106 INIT_LIST_HEAD(&handle->head);
107 INIT_LIST_HEAD(&handle->tree);
108 handle->name = _handle;
109 handle->priv = ~0;
110 RB_CLEAR_NODE(&handle->rb);
111 handle->parent = parent;
112 nvkm_object_ref(object, &handle->object);
113
114 if (parent)
115 list_add(&handle->head, &handle->parent->tree);
116
117 hprintk(handle, TRACE, "created\n");
118 *phandle = handle;
119 return 0;
120}
121
122void
123nvkm_handle_destroy(struct nvkm_handle *handle)
124{
125 struct nvkm_client *client = nvkm_client(handle->object);
126 struct nvkm_handle *item, *temp;
127
128 hprintk(handle, TRACE, "destroy running\n");
129 list_for_each_entry_safe(item, temp, &handle->tree, head) {
130 nvkm_handle_destroy(item);
131 }
132
133 nvkm_client_remove(client, handle);
134 list_del(&handle->head);
135
136 hprintk(handle, TRACE, "destroy completed\n");
137 nvkm_object_ref(NULL, &handle->object);
138 kfree(handle);
139}
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c b/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c
index d9bb0394d83f..d87d6ab03cc7 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c
+++ b/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c
@@ -24,15 +24,13 @@
24#include <core/ioctl.h> 24#include <core/ioctl.h>
25#include <core/client.h> 25#include <core/client.h>
26#include <core/engine.h> 26#include <core/engine.h>
27#include <core/handle.h>
28 27
29#include <nvif/unpack.h> 28#include <nvif/unpack.h>
30#include <nvif/ioctl.h> 29#include <nvif/ioctl.h>
31 30
32static int 31static int
33nvkm_ioctl_nop(struct nvkm_handle *handle, void *data, u32 size) 32nvkm_ioctl_nop(struct nvkm_object *object, void *data, u32 size)
34{ 33{
35 struct nvkm_object *object = handle->object;
36 union { 34 union {
37 struct nvif_ioctl_nop_v0 v0; 35 struct nvif_ioctl_nop_v0 v0;
38 } *args = data; 36 } *args = data;
@@ -48,9 +46,8 @@ nvkm_ioctl_nop(struct nvkm_handle *handle, void *data, u32 size)
48} 46}
49 47
50static int 48static int
51nvkm_ioctl_sclass(struct nvkm_handle *handle, void *data, u32 size) 49nvkm_ioctl_sclass(struct nvkm_object *object, void *data, u32 size)
52{ 50{
53 struct nvkm_object *object = handle->object;
54 union { 51 union {
55 struct nvif_ioctl_sclass_v0 v0; 52 struct nvif_ioctl_sclass_v0 v0;
56 } *args = data; 53 } *args = data;
@@ -81,13 +78,12 @@ nvkm_ioctl_sclass(struct nvkm_handle *handle, void *data, u32 size)
81} 78}
82 79
83static int 80static int
84nvkm_ioctl_new(struct nvkm_handle *handle, void *data, u32 size) 81nvkm_ioctl_new(struct nvkm_object *parent, void *data, u32 size)
85{ 82{
86 union { 83 union {
87 struct nvif_ioctl_new_v0 v0; 84 struct nvif_ioctl_new_v0 v0;
88 } *args = data; 85 } *args = data;
89 struct nvkm_client *client = handle->object->client; 86 struct nvkm_client *client = parent->client;
90 struct nvkm_object *parent = handle->object;
91 struct nvkm_object *object = NULL; 87 struct nvkm_object *object = NULL;
92 struct nvkm_oclass oclass; 88 struct nvkm_oclass oclass;
93 int ret, i = 0; 89 int ret, i = 0;
@@ -124,38 +120,30 @@ nvkm_ioctl_new(struct nvkm_handle *handle, void *data, u32 size)
124 } 120 }
125 121
126 ret = oclass.ctor(&oclass, data, size, &object); 122 ret = oclass.ctor(&oclass, data, size, &object);
127 if (ret)
128 goto fail_object;
129
130 ret = nvkm_object_inc(object);
131 if (ret)
132 goto fail_object;
133
134 ret = nvkm_handle_create(handle, args->v0.handle, object, &handle);
135 if (ret)
136 goto fail_handle;
137
138 ret = nvkm_handle_init(handle);
139 handle->route = args->v0.route;
140 handle->token = args->v0.token;
141 if (ret)
142 nvkm_handle_destroy(handle);
143
144 handle->handle = args->v0.object;
145 nvkm_client_insert(client, handle);
146 client->data = object;
147fail_handle:
148 nvkm_object_dec(object, false);
149fail_object:
150 nvkm_object_ref(NULL, &object);
151 nvkm_engine_unref(&oclass.engine); 123 nvkm_engine_unref(&oclass.engine);
124 if (ret == 0) {
125 ret = nvkm_object_init(object);
126 if (ret == 0) {
127 list_add(&object->head, &parent->tree);
128 object->route = args->v0.route;
129 object->token = args->v0.token;
130 object->object = args->v0.object;
131 if (nvkm_client_insert(client, object)) {
132 client->data = object;
133 return 0;
134 }
135 ret = -EEXIST;
136 }
137 nvkm_object_fini(object, false);
138 }
139
140 nvkm_object_del(&object);
152 return ret; 141 return ret;
153} 142}
154 143
155static int 144static int
156nvkm_ioctl_del(struct nvkm_handle *handle, void *data, u32 size) 145nvkm_ioctl_del(struct nvkm_object *object, void *data, u32 size)
157{ 146{
158 struct nvkm_object *object = handle->object;
159 union { 147 union {
160 struct nvif_ioctl_del none; 148 struct nvif_ioctl_del none;
161 } *args = data; 149 } *args = data;
@@ -164,17 +152,16 @@ nvkm_ioctl_del(struct nvkm_handle *handle, void *data, u32 size)
164 nvif_ioctl(object, "delete size %d\n", size); 152 nvif_ioctl(object, "delete size %d\n", size);
165 if (nvif_unvers(args->none)) { 153 if (nvif_unvers(args->none)) {
166 nvif_ioctl(object, "delete\n"); 154 nvif_ioctl(object, "delete\n");
167 nvkm_handle_fini(handle, false); 155 nvkm_object_fini(object, false);
168 nvkm_handle_destroy(handle); 156 nvkm_object_del(&object);
169 } 157 }
170 158
171 return ret; 159 return ret;
172} 160}
173 161
174static int 162static int
175nvkm_ioctl_mthd(struct nvkm_handle *handle, void *data, u32 size) 163nvkm_ioctl_mthd(struct nvkm_object *object, void *data, u32 size)
176{ 164{
177 struct nvkm_object *object = handle->object;
178 union { 165 union {
179 struct nvif_ioctl_mthd_v0 v0; 166 struct nvif_ioctl_mthd_v0 v0;
180 } *args = data; 167 } *args = data;
@@ -192,9 +179,8 @@ nvkm_ioctl_mthd(struct nvkm_handle *handle, void *data, u32 size)
192 179
193 180
194static int 181static int
195nvkm_ioctl_rd(struct nvkm_handle *handle, void *data, u32 size) 182nvkm_ioctl_rd(struct nvkm_object *object, void *data, u32 size)
196{ 183{
197 struct nvkm_object *object = handle->object;
198 union { 184 union {
199 struct nvif_ioctl_rd_v0 v0; 185 struct nvif_ioctl_rd_v0 v0;
200 } *args = data; 186 } *args = data;
@@ -232,9 +218,8 @@ nvkm_ioctl_rd(struct nvkm_handle *handle, void *data, u32 size)
232} 218}
233 219
234static int 220static int
235nvkm_ioctl_wr(struct nvkm_handle *handle, void *data, u32 size) 221nvkm_ioctl_wr(struct nvkm_object *object, void *data, u32 size)
236{ 222{
237 struct nvkm_object *object = handle->object;
238 union { 223 union {
239 struct nvif_ioctl_wr_v0 v0; 224 struct nvif_ioctl_wr_v0 v0;
240 } *args = data; 225 } *args = data;
@@ -261,9 +246,8 @@ nvkm_ioctl_wr(struct nvkm_handle *handle, void *data, u32 size)
261} 246}
262 247
263static int 248static int
264nvkm_ioctl_map(struct nvkm_handle *handle, void *data, u32 size) 249nvkm_ioctl_map(struct nvkm_object *object, void *data, u32 size)
265{ 250{
266 struct nvkm_object *object = handle->object;
267 union { 251 union {
268 struct nvif_ioctl_map_v0 v0; 252 struct nvif_ioctl_map_v0 v0;
269 } *args = data; 253 } *args = data;
@@ -280,9 +264,8 @@ nvkm_ioctl_map(struct nvkm_handle *handle, void *data, u32 size)
280} 264}
281 265
282static int 266static int
283nvkm_ioctl_unmap(struct nvkm_handle *handle, void *data, u32 size) 267nvkm_ioctl_unmap(struct nvkm_object *object, void *data, u32 size)
284{ 268{
285 struct nvkm_object *object = handle->object;
286 union { 269 union {
287 struct nvif_ioctl_unmap none; 270 struct nvif_ioctl_unmap none;
288 } *args = data; 271 } *args = data;
@@ -297,9 +280,8 @@ nvkm_ioctl_unmap(struct nvkm_handle *handle, void *data, u32 size)
297} 280}
298 281
299static int 282static int
300nvkm_ioctl_ntfy_new(struct nvkm_handle *handle, void *data, u32 size) 283nvkm_ioctl_ntfy_new(struct nvkm_object *object, void *data, u32 size)
301{ 284{
302 struct nvkm_object *object = handle->object;
303 union { 285 union {
304 struct nvif_ioctl_ntfy_new_v0 v0; 286 struct nvif_ioctl_ntfy_new_v0 v0;
305 } *args = data; 287 } *args = data;
@@ -324,10 +306,9 @@ nvkm_ioctl_ntfy_new(struct nvkm_handle *handle, void *data, u32 size)
324} 306}
325 307
326static int 308static int
327nvkm_ioctl_ntfy_del(struct nvkm_handle *handle, void *data, u32 size) 309nvkm_ioctl_ntfy_del(struct nvkm_object *object, void *data, u32 size)
328{ 310{
329 struct nvkm_client *client = nvkm_client(handle->object); 311 struct nvkm_client *client = object->client;
330 struct nvkm_object *object = handle->object;
331 union { 312 union {
332 struct nvif_ioctl_ntfy_del_v0 v0; 313 struct nvif_ioctl_ntfy_del_v0 v0;
333 } *args = data; 314 } *args = data;
@@ -344,10 +325,9 @@ nvkm_ioctl_ntfy_del(struct nvkm_handle *handle, void *data, u32 size)
344} 325}
345 326
346static int 327static int
347nvkm_ioctl_ntfy_get(struct nvkm_handle *handle, void *data, u32 size) 328nvkm_ioctl_ntfy_get(struct nvkm_object *object, void *data, u32 size)
348{ 329{
349 struct nvkm_client *client = nvkm_client(handle->object); 330 struct nvkm_client *client = object->client;
350 struct nvkm_object *object = handle->object;
351 union { 331 union {
352 struct nvif_ioctl_ntfy_get_v0 v0; 332 struct nvif_ioctl_ntfy_get_v0 v0;
353 } *args = data; 333 } *args = data;
@@ -364,10 +344,9 @@ nvkm_ioctl_ntfy_get(struct nvkm_handle *handle, void *data, u32 size)
364} 344}
365 345
366static int 346static int
367nvkm_ioctl_ntfy_put(struct nvkm_handle *handle, void *data, u32 size) 347nvkm_ioctl_ntfy_put(struct nvkm_object *object, void *data, u32 size)
368{ 348{
369 struct nvkm_client *client = nvkm_client(handle->object); 349 struct nvkm_client *client = object->client;
370 struct nvkm_object *object = handle->object;
371 union { 350 union {
372 struct nvif_ioctl_ntfy_put_v0 v0; 351 struct nvif_ioctl_ntfy_put_v0 v0;
373 } *args = data; 352 } *args = data;
@@ -385,7 +364,7 @@ nvkm_ioctl_ntfy_put(struct nvkm_handle *handle, void *data, u32 size)
385 364
386static struct { 365static struct {
387 int version; 366 int version;
388 int (*func)(struct nvkm_handle *, void *, u32); 367 int (*func)(struct nvkm_object *, void *, u32);
389} 368}
390nvkm_ioctl_v0[] = { 369nvkm_ioctl_v0[] = {
391 { 0x00, nvkm_ioctl_nop }, 370 { 0x00, nvkm_ioctl_nop },
@@ -407,13 +386,13 @@ static int
407nvkm_ioctl_path(struct nvkm_client *client, u64 handle, u32 type, 386nvkm_ioctl_path(struct nvkm_client *client, u64 handle, u32 type,
408 void *data, u32 size, u8 owner, u8 *route, u64 *token) 387 void *data, u32 size, u8 owner, u8 *route, u64 *token)
409{ 388{
410 struct nvkm_handle *object; 389 struct nvkm_object *object;
411 int ret; 390 int ret;
412 391
413 if (handle) 392 if (handle)
414 object = nvkm_client_search(client, handle); 393 object = nvkm_client_search(client, handle);
415 else 394 else
416 object = client->root; 395 object = &client->object;
417 if (unlikely(!object)) { 396 if (unlikely(!object)) {
418 nvif_ioctl(&client->object, "object not found\n"); 397 nvif_ioctl(&client->object, "object not found\n");
419 return -ENOENT; 398 return -ENOENT;
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/object.c b/drivers/gpu/drm/nouveau/nvkm/core/object.c
index 8976526b1c8f..67aa7223dcd7 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/object.c
+++ b/drivers/gpu/drm/nouveau/nvkm/core/object.c
@@ -22,6 +22,7 @@
22 * Authors: Ben Skeggs 22 * Authors: Ben Skeggs
23 */ 23 */
24#include <core/object.h> 24#include <core/object.h>
25#include <core/client.h>
25#include <core/engine.h> 26#include <core/engine.h>
26 27
27int 28int
@@ -109,28 +110,112 @@ nvkm_object_bind(struct nvkm_object *object, struct nvkm_gpuobj *gpuobj,
109int 110int
110nvkm_object_fini(struct nvkm_object *object, bool suspend) 111nvkm_object_fini(struct nvkm_object *object, bool suspend)
111{ 112{
112 if (object->func->fini) 113 const char *action = suspend ? "suspend" : "fini";
113 return object->func->fini(object, suspend); 114 struct nvkm_object *child;
115 s64 time;
116 int ret;
117
118 nvif_debug(object, "%s children...\n", action);
119 time = ktime_to_us(ktime_get());
120 list_for_each_entry(child, &object->tree, head) {
121 ret = nvkm_object_fini(child, suspend);
122 if (ret && suspend)
123 goto fail_child;
124 }
125
126 nvif_debug(object, "%s running...\n", action);
127 if (object->func->fini) {
128 ret = object->func->fini(object, suspend);
129 if (ret) {
130 nvif_error(object, "%s failed with %d\n", action, ret);
131 if (suspend)
132 goto fail;
133 }
134 }
135
136 time = ktime_to_us(ktime_get()) - time;
137 nvif_debug(object, "%s completed in %lldus\n", action, time);
114 return 0; 138 return 0;
139
140fail:
141 if (object->func->init) {
142 int rret = object->func->init(object);
143 if (rret)
144 nvif_fatal(object, "failed to restart, %d\n", rret);
145 }
146fail_child:
147 list_for_each_entry_continue_reverse(child, &object->tree, head) {
148 nvkm_object_init(child);
149 }
150 return ret;
115} 151}
116 152
117int 153int
118nvkm_object_init(struct nvkm_object *object) 154nvkm_object_init(struct nvkm_object *object)
119{ 155{
120 if (object->func->init) 156 struct nvkm_object *child;
121 return object->func->init(object); 157 s64 time;
158 int ret;
159
160 nvif_debug(object, "init running...\n");
161 time = ktime_to_us(ktime_get());
162 if (object->func->init) {
163 ret = object->func->init(object);
164 if (ret)
165 goto fail;
166 }
167
168 nvif_debug(object, "init children...\n");
169 list_for_each_entry(child, &object->tree, head) {
170 ret = nvkm_object_init(child);
171 if (ret)
172 goto fail_child;
173 }
174
175 time = ktime_to_us(ktime_get()) - time;
176 nvif_debug(object, "init completed in %lldus\n", time);
122 return 0; 177 return 0;
178
179fail_child:
180 list_for_each_entry_continue_reverse(child, &object->tree, head)
181 nvkm_object_fini(child, false);
182fail:
183 nvif_error(object, "init failed with %d\n", ret);
184 if (object->func->fini)
185 object->func->fini(object, false);
186 return ret;
123} 187}
124 188
125static void 189void *
190nvkm_object_dtor(struct nvkm_object *object)
191{
192 struct nvkm_object *child, *ctemp;
193 void *data = object;
194 s64 time;
195
196 nvif_debug(object, "destroy children...\n");
197 time = ktime_to_us(ktime_get());
198 list_for_each_entry_safe(child, ctemp, &object->tree, head) {
199 nvkm_object_del(&child);
200 }
201
202 nvif_debug(object, "destroy running...\n");
203 if (object->func->dtor)
204 data = object->func->dtor(object);
205 nvkm_engine_unref(&object->engine);
206 time = ktime_to_us(ktime_get()) - time;
207 nvif_debug(object, "destroy completed in %lldus...\n", time);
208 return data;
209}
210
211void
126nvkm_object_del(struct nvkm_object **pobject) 212nvkm_object_del(struct nvkm_object **pobject)
127{ 213{
128 struct nvkm_object *object = *pobject; 214 struct nvkm_object *object = *pobject;
129
130 if (object && !WARN_ON(!object->func)) { 215 if (object && !WARN_ON(!object->func)) {
131 if (object->func->dtor) 216 *pobject = nvkm_object_dtor(object);
132 *pobject = object->func->dtor(object); 217 nvkm_client_remove(object->client, object);
133 nvkm_engine_unref(&object->engine); 218 list_del(&object->head);
134 kfree(*pobject); 219 kfree(*pobject);
135 *pobject = NULL; 220 *pobject = NULL;
136 } 221 }
@@ -145,9 +230,10 @@ nvkm_object_ctor(const struct nvkm_object_func *func,
145 object->engine = nvkm_engine_ref(oclass->engine); 230 object->engine = nvkm_engine_ref(oclass->engine);
146 object->oclass = oclass->base.oclass; 231 object->oclass = oclass->base.oclass;
147 object->handle = oclass->handle; 232 object->handle = oclass->handle;
148 object->parent = oclass->parent; 233 INIT_LIST_HEAD(&object->head);
149 atomic_set(&object->refcount, 1); 234 INIT_LIST_HEAD(&object->tree);
150 atomic_set(&object->usecount, 0); 235 RB_CLEAR_NODE(&object->node);
236 WARN_ON(oclass->engine && !object->engine);
151} 237}
152 238
153int 239int
@@ -176,106 +262,3 @@ nvkm_object_new(const struct nvkm_oclass *oclass, void *data, u32 size,
176 oclass->base.func ? oclass->base.func : &nvkm_object_func; 262 oclass->base.func ? oclass->base.func : &nvkm_object_func;
177 return nvkm_object_new_(func, oclass, data, size, pobject); 263 return nvkm_object_new_(func, oclass, data, size, pobject);
178} 264}
179
180void
181nvkm_object_ref(struct nvkm_object *obj, struct nvkm_object **ref)
182{
183 if (obj) {
184 atomic_inc(&obj->refcount);
185 }
186
187 if (*ref) {
188 int dead = atomic_dec_and_test(&(*ref)->refcount);
189 if (dead)
190 nvkm_object_del(ref);
191 }
192
193 *ref = obj;
194}
195
196int
197nvkm_object_inc(struct nvkm_object *object)
198{
199 int ref = atomic_add_return(1, &object->usecount);
200 int ret;
201
202 if (ref != 1)
203 return 0;
204
205 if (object->parent) {
206 ret = nvkm_object_inc(object->parent);
207 if (ret)
208 goto fail_parent;
209 }
210
211 ret = nvkm_object_init(object);
212 atomic_set(&object->usecount, 1);
213 if (ret)
214 goto fail_self;
215
216 return 0;
217
218fail_self:
219 if (object->parent)
220 nvkm_object_dec(object->parent, false);
221fail_parent:
222 atomic_dec(&object->usecount);
223 return ret;
224}
225
226static int
227nvkm_object_decf(struct nvkm_object *object)
228{
229 nvkm_object_fini(object, false);
230 atomic_set(&object->usecount, 0);
231
232 if (object->parent)
233 nvkm_object_dec(object->parent, false);
234
235 return 0;
236}
237
238static int
239nvkm_object_decs(struct nvkm_object *object)
240{
241 int ret;
242
243 ret = nvkm_object_fini(object, true);
244 atomic_set(&object->usecount, 0);
245 if (ret)
246 return ret;
247
248 if (object->parent) {
249 ret = nvkm_object_dec(object->parent, true);
250 if (ret)
251 goto fail_parent;
252 }
253
254 return 0;
255
256fail_parent:
257 nvkm_object_init(object);
258
259 return ret;
260}
261
262int
263nvkm_object_dec(struct nvkm_object *object, bool suspend)
264{
265 int ref = atomic_add_return(-1, &object->usecount);
266 int ret;
267
268 if (ref == 0) {
269 if (suspend)
270 ret = nvkm_object_decs(object);
271 else
272 ret = nvkm_object_decf(object);
273
274 if (ret) {
275 atomic_inc(&object->usecount);
276 return ret;
277 }
278 }
279
280 return 0;
281}
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/oproxy.c b/drivers/gpu/drm/nouveau/nvkm/core/oproxy.c
index f32aa0dc425b..e31a0479add0 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/oproxy.c
+++ b/drivers/gpu/drm/nouveau/nvkm/core/oproxy.c
@@ -109,9 +109,11 @@ nvkm_oproxy_fini(struct nvkm_object *object, bool suspend)
109 return ret; 109 return ret;
110 } 110 }
111 111
112 ret = nvkm_object_fini(oproxy->object, suspend); 112 if (oproxy->object->func->fini) {
113 if (ret && suspend) 113 ret = oproxy->object->func->fini(oproxy->object, suspend);
114 return ret; 114 if (ret && suspend)
115 return ret;
116 }
115 117
116 if (oproxy->func->fini[1]) { 118 if (oproxy->func->fini[1]) {
117 ret = oproxy->func->fini[1](oproxy, suspend); 119 ret = oproxy->func->fini[1](oproxy, suspend);
@@ -134,9 +136,11 @@ nvkm_oproxy_init(struct nvkm_object *object)
134 return ret; 136 return ret;
135 } 137 }
136 138
137 ret = nvkm_object_init(oproxy->object); 139 if (oproxy->object->func->init) {
138 if (ret) 140 ret = oproxy->object->func->init(oproxy->object);
139 return ret; 141 if (ret)
142 return ret;
143 }
140 144
141 if (oproxy->func->init[1]) { 145 if (oproxy->func->init[1]) {
142 ret = oproxy->func->init[1](oproxy); 146 ret = oproxy->func->init[1](oproxy);
@@ -153,7 +157,7 @@ nvkm_oproxy_dtor(struct nvkm_object *object)
153 struct nvkm_oproxy *oproxy = nvkm_oproxy(object); 157 struct nvkm_oproxy *oproxy = nvkm_oproxy(object);
154 if (oproxy->func->dtor[0]) 158 if (oproxy->func->dtor[0])
155 oproxy->func->dtor[0](oproxy); 159 oproxy->func->dtor[0](oproxy);
156 nvkm_object_ref(NULL, &oproxy->object); 160 nvkm_object_del(&oproxy->object);
157 if (oproxy->func->dtor[1]) 161 if (oproxy->func->dtor[1])
158 oproxy->func->dtor[1](oproxy); 162 oproxy->func->dtor[1](oproxy);
159 return oproxy; 163 return oproxy;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c
index b05c04a209be..9c6645a357b9 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c
@@ -25,7 +25,6 @@
25#include "rootnv50.h" 25#include "rootnv50.h"
26 26
27#include <core/client.h> 27#include <core/client.h>
28#include <core/handle.h>
29#include <core/oproxy.h> 28#include <core/oproxy.h>
30#include <core/ramht.h> 29#include <core/ramht.h>
31#include <subdev/fb.h> 30#include <subdev/fb.h>
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c
index a56e56eed57b..9921482fc162 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c
@@ -116,7 +116,7 @@ nvkm_fifo_chan_child_del(struct nvkm_oproxy *base)
116 if (!--engn->refcount) { 116 if (!--engn->refcount) {
117 if (chan->func->engine_dtor) 117 if (chan->func->engine_dtor)
118 chan->func->engine_dtor(chan, engine); 118 chan->func->engine_dtor(chan, engine);
119 nvkm_object_ref(NULL, &engn->object); 119 nvkm_object_del(&engn->object);
120 if (chan->vm) 120 if (chan->vm)
121 atomic_dec(&chan->vm->engref[engine->subdev.index]); 121 atomic_dec(&chan->vm->engref[engine->subdev.index]);
122 } 122 }
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c
index 172f24301113..ff6fcbda615b 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c
@@ -27,7 +27,6 @@
27#include <core/client.h> 27#include <core/client.h>
28#include <core/enum.h> 28#include <core/enum.h>
29#include <core/gpuobj.h> 29#include <core/gpuobj.h>
30#include <core/handle.h>
31#include <subdev/bar.h> 30#include <subdev/bar.h>
32#include <engine/sw.h> 31#include <engine/sw.h>
33 32
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c
index fc0ff2d37d06..98970a0b7a66 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c
@@ -27,7 +27,6 @@
27#include <core/client.h> 27#include <core/client.h>
28#include <core/enum.h> 28#include <core/enum.h>
29#include <core/gpuobj.h> 29#include <core/gpuobj.h>
30#include <core/handle.h>
31#include <subdev/bar.h> 30#include <subdev/bar.h>
32#include <engine/sw.h> 31#include <engine/sw.h>
33 32
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c
index e6f04e87139a..ad707ff176cc 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c
@@ -26,7 +26,6 @@
26#include "regsnv04.h" 26#include "regsnv04.h"
27 27
28#include <core/client.h> 28#include <core/client.h>
29#include <core/handle.h>
30#include <core/ramht.h> 29#include <core/ramht.h>
31#include <subdev/instmem.h> 30#include <subdev/instmem.h>
32#include <subdev/timer.h> 31#include <subdev/timer.h>
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c
index ef36ba18bff8..a381196af69d 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c
@@ -24,7 +24,6 @@
24#include "nv50.h" 24#include "nv50.h"
25 25
26#include <core/gpuobj.h> 26#include <core/gpuobj.h>
27#include <core/handle.h>
28#include <engine/disp.h> 27#include <engine/disp.h>
29#include <engine/fifo/chan.h> 28#include <engine/fifo/chan.h>
30#include <subdev/bar.h> 29#include <subdev/bar.h>