2 * Copyright 2012 Red Hat Inc.
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
24 #include <core/object.h>
25 #include <core/client.h>
26 #include <core/engine.h>
29 nvkm_object_search(struct nvkm_client
*client
, u64 handle
,
30 const struct nvkm_object_func
*func
)
32 struct nvkm_object
*object
;
35 struct rb_node
*node
= client
->objroot
.rb_node
;
37 object
= rb_entry(node
, typeof(*object
), node
);
38 if (handle
< object
->object
)
41 if (handle
> object
->object
)
42 node
= node
->rb_right
;
46 return ERR_PTR(-ENOENT
);
48 object
= &client
->object
;
52 if (unlikely(func
&& object
->func
!= func
))
53 return ERR_PTR(-EINVAL
);
58 nvkm_object_remove(struct nvkm_object
*object
)
60 if (!RB_EMPTY_NODE(&object
->node
))
61 rb_erase(&object
->node
, &object
->client
->objroot
);
65 nvkm_object_insert(struct nvkm_object
*object
)
67 struct rb_node
**ptr
= &object
->client
->objroot
.rb_node
;
68 struct rb_node
*parent
= NULL
;
71 struct nvkm_object
*this = rb_entry(*ptr
, typeof(*this), node
);
73 if (object
->object
< this->object
)
74 ptr
= &parent
->rb_left
;
76 if (object
->object
> this->object
)
77 ptr
= &parent
->rb_right
;
82 rb_link_node(&object
->node
, parent
, ptr
);
83 rb_insert_color(&object
->node
, &object
->client
->objroot
);
88 nvkm_object_mthd(struct nvkm_object
*object
, u32 mthd
, void *data
, u32 size
)
90 if (likely(object
->func
->mthd
))
91 return object
->func
->mthd(object
, mthd
, data
, size
);
96 nvkm_object_ntfy(struct nvkm_object
*object
, u32 mthd
,
97 struct nvkm_event
**pevent
)
99 if (likely(object
->func
->ntfy
))
100 return object
->func
->ntfy(object
, mthd
, pevent
);
105 nvkm_object_map(struct nvkm_object
*object
, void *argv
, u32 argc
,
106 enum nvkm_object_map
*type
, u64
*addr
, u64
*size
)
108 if (likely(object
->func
->map
))
109 return object
->func
->map(object
, argv
, argc
, type
, addr
, size
);
114 nvkm_object_unmap(struct nvkm_object
*object
)
116 if (likely(object
->func
->unmap
))
117 return object
->func
->unmap(object
);
122 nvkm_object_rd08(struct nvkm_object
*object
, u64 addr
, u8
*data
)
124 if (likely(object
->func
->rd08
))
125 return object
->func
->rd08(object
, addr
, data
);
130 nvkm_object_rd16(struct nvkm_object
*object
, u64 addr
, u16
*data
)
132 if (likely(object
->func
->rd16
))
133 return object
->func
->rd16(object
, addr
, data
);
138 nvkm_object_rd32(struct nvkm_object
*object
, u64 addr
, u32
*data
)
140 if (likely(object
->func
->rd32
))
141 return object
->func
->rd32(object
, addr
, data
);
146 nvkm_object_wr08(struct nvkm_object
*object
, u64 addr
, u8 data
)
148 if (likely(object
->func
->wr08
))
149 return object
->func
->wr08(object
, addr
, data
);
154 nvkm_object_wr16(struct nvkm_object
*object
, u64 addr
, u16 data
)
156 if (likely(object
->func
->wr16
))
157 return object
->func
->wr16(object
, addr
, data
);
162 nvkm_object_wr32(struct nvkm_object
*object
, u64 addr
, u32 data
)
164 if (likely(object
->func
->wr32
))
165 return object
->func
->wr32(object
, addr
, data
);
170 nvkm_object_bind(struct nvkm_object
*object
, struct nvkm_gpuobj
*gpuobj
,
171 int align
, struct nvkm_gpuobj
**pgpuobj
)
173 if (object
->func
->bind
)
174 return object
->func
->bind(object
, gpuobj
, align
, pgpuobj
);
179 nvkm_object_fini(struct nvkm_object
*object
, bool suspend
)
181 const char *action
= suspend
? "suspend" : "fini";
182 struct nvkm_object
*child
;
186 nvif_debug(object
, "%s children...\n", action
);
187 time
= ktime_to_us(ktime_get());
188 list_for_each_entry(child
, &object
->tree
, head
) {
189 ret
= nvkm_object_fini(child
, suspend
);
194 nvif_debug(object
, "%s running...\n", action
);
195 if (object
->func
->fini
) {
196 ret
= object
->func
->fini(object
, suspend
);
198 nvif_error(object
, "%s failed with %d\n", action
, ret
);
204 time
= ktime_to_us(ktime_get()) - time
;
205 nvif_debug(object
, "%s completed in %lldus\n", action
, time
);
209 if (object
->func
->init
) {
210 int rret
= object
->func
->init(object
);
212 nvif_fatal(object
, "failed to restart, %d\n", rret
);
215 list_for_each_entry_continue_reverse(child
, &object
->tree
, head
) {
216 nvkm_object_init(child
);
222 nvkm_object_init(struct nvkm_object
*object
)
224 struct nvkm_object
*child
;
228 nvif_debug(object
, "init running...\n");
229 time
= ktime_to_us(ktime_get());
230 if (object
->func
->init
) {
231 ret
= object
->func
->init(object
);
236 nvif_debug(object
, "init children...\n");
237 list_for_each_entry(child
, &object
->tree
, head
) {
238 ret
= nvkm_object_init(child
);
243 time
= ktime_to_us(ktime_get()) - time
;
244 nvif_debug(object
, "init completed in %lldus\n", time
);
248 list_for_each_entry_continue_reverse(child
, &object
->tree
, head
)
249 nvkm_object_fini(child
, false);
251 nvif_error(object
, "init failed with %d\n", ret
);
252 if (object
->func
->fini
)
253 object
->func
->fini(object
, false);
258 nvkm_object_dtor(struct nvkm_object
*object
)
260 struct nvkm_object
*child
, *ctemp
;
264 nvif_debug(object
, "destroy children...\n");
265 time
= ktime_to_us(ktime_get());
266 list_for_each_entry_safe(child
, ctemp
, &object
->tree
, head
) {
267 nvkm_object_del(&child
);
270 nvif_debug(object
, "destroy running...\n");
271 nvkm_object_unmap(object
);
272 if (object
->func
->dtor
)
273 data
= object
->func
->dtor(object
);
274 nvkm_engine_unref(&object
->engine
);
275 time
= ktime_to_us(ktime_get()) - time
;
276 nvif_debug(object
, "destroy completed in %lldus...\n", time
);
281 nvkm_object_del(struct nvkm_object
**pobject
)
283 struct nvkm_object
*object
= *pobject
;
284 if (object
&& !WARN_ON(!object
->func
)) {
285 *pobject
= nvkm_object_dtor(object
);
286 nvkm_object_remove(object
);
287 list_del(&object
->head
);
294 nvkm_object_ctor(const struct nvkm_object_func
*func
,
295 const struct nvkm_oclass
*oclass
, struct nvkm_object
*object
)
298 object
->client
= oclass
->client
;
299 object
->engine
= nvkm_engine_ref(oclass
->engine
);
300 object
->oclass
= oclass
->base
.oclass
;
301 object
->handle
= oclass
->handle
;
302 object
->route
= oclass
->route
;
303 object
->token
= oclass
->token
;
304 object
->object
= oclass
->object
;
305 INIT_LIST_HEAD(&object
->head
);
306 INIT_LIST_HEAD(&object
->tree
);
307 RB_CLEAR_NODE(&object
->node
);
308 WARN_ON(IS_ERR(object
->engine
));
312 nvkm_object_new_(const struct nvkm_object_func
*func
,
313 const struct nvkm_oclass
*oclass
, void *data
, u32 size
,
314 struct nvkm_object
**pobject
)
317 if (!(*pobject
= kzalloc(sizeof(**pobject
), GFP_KERNEL
)))
319 nvkm_object_ctor(func
, oclass
, *pobject
);
325 static const struct nvkm_object_func
330 nvkm_object_new(const struct nvkm_oclass
*oclass
, void *data
, u32 size
,
331 struct nvkm_object
**pobject
)
333 const struct nvkm_object_func
*func
=
334 oclass
->base
.func
? oclass
->base
.func
: &nvkm_object_func
;
335 return nvkm_object_new_(func
, oclass
, data
, size
, pobject
);