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.
25 #include <core/object.h>
26 #include <core/namedb.h>
27 #include <core/handle.h>
28 #include <core/client.h>
29 #include <core/engctx.h>
31 #include <subdev/vm.h>
34 nouveau_engctx_exists(struct nouveau_object
*parent
,
35 struct nouveau_engine
*engine
, void **pobject
)
37 struct nouveau_engctx
*engctx
;
38 struct nouveau_object
*parctx
;
40 list_for_each_entry(engctx
, &engine
->contexts
, head
) {
41 parctx
= nv_pclass(nv_object(engctx
), NV_PARENT_CLASS
);
42 if (parctx
== parent
) {
43 atomic_inc(&nv_object(engctx
)->refcount
);
53 nouveau_engctx_create_(struct nouveau_object
*parent
,
54 struct nouveau_object
*engobj
,
55 struct nouveau_oclass
*oclass
,
56 struct nouveau_object
*pargpu
,
57 u32 size
, u32 align
, u32 flags
,
58 int length
, void **pobject
)
60 struct nouveau_client
*client
= nouveau_client(parent
);
61 struct nouveau_engine
*engine
= nv_engine(engobj
);
62 struct nouveau_object
*engctx
;
66 /* check if this engine already has a context for the parent object,
67 * and reference it instead of creating a new one
69 spin_lock_irqsave(&engine
->lock
, save
);
70 ret
= nouveau_engctx_exists(parent
, engine
, pobject
);
71 spin_unlock_irqrestore(&engine
->lock
, save
);
75 /* create the new context, supports creating both raw objects and
76 * objects backed by instance memory
79 ret
= nouveau_gpuobj_create_(parent
, engobj
, oclass
,
81 pargpu
, size
, align
, flags
,
84 ret
= nouveau_object_create_(parent
, engobj
, oclass
,
85 NV_ENGCTX_CLASS
, length
, pobject
);
92 /* must take the lock again and re-check a context doesn't already
93 * exist (in case of a race) - the lock had to be dropped before as
94 * it's not possible to allocate the object with it held.
96 spin_lock_irqsave(&engine
->lock
, save
);
97 ret
= nouveau_engctx_exists(parent
, engine
, pobject
);
99 spin_unlock_irqrestore(&engine
->lock
, save
);
100 nouveau_object_ref(NULL
, &engctx
);
105 atomic_inc(&client
->vm
->engref
[nv_engidx(engine
)]);
106 list_add(&nv_engctx(engctx
)->head
, &engine
->contexts
);
107 nv_engctx(engctx
)->addr
= ~0ULL;
108 spin_unlock_irqrestore(&engine
->lock
, save
);
113 nouveau_engctx_destroy(struct nouveau_engctx
*engctx
)
115 struct nouveau_engine
*engine
= engctx
->gpuobj
.object
.engine
;
116 struct nouveau_client
*client
= nouveau_client(engctx
);
119 nouveau_gpuobj_unmap(&engctx
->vma
);
120 spin_lock_irqsave(&engine
->lock
, save
);
121 list_del(&engctx
->head
);
122 spin_unlock_irqrestore(&engine
->lock
, save
);
125 atomic_dec(&client
->vm
->engref
[nv_engidx(engine
)]);
127 if (engctx
->gpuobj
.size
)
128 nouveau_gpuobj_destroy(&engctx
->gpuobj
);
130 nouveau_object_destroy(&engctx
->gpuobj
.object
);
134 nouveau_engctx_init(struct nouveau_engctx
*engctx
)
136 struct nouveau_object
*object
= nv_object(engctx
);
137 struct nouveau_subdev
*subdev
= nv_subdev(object
->engine
);
138 struct nouveau_object
*parent
;
139 struct nouveau_subdev
*pardev
;
142 ret
= nouveau_gpuobj_init(&engctx
->gpuobj
);
146 parent
= nv_pclass(object
->parent
, NV_PARENT_CLASS
);
147 pardev
= nv_subdev(parent
->engine
);
148 if (nv_parent(parent
)->context_attach
) {
149 mutex_lock(&pardev
->mutex
);
150 ret
= nv_parent(parent
)->context_attach(parent
, object
);
151 mutex_unlock(&pardev
->mutex
);
155 nv_error(parent
, "failed to attach %s context, %d\n",
160 nv_debug(parent
, "attached %s context\n", subdev
->name
);
165 nouveau_engctx_fini(struct nouveau_engctx
*engctx
, bool suspend
)
167 struct nouveau_object
*object
= nv_object(engctx
);
168 struct nouveau_subdev
*subdev
= nv_subdev(object
->engine
);
169 struct nouveau_object
*parent
;
170 struct nouveau_subdev
*pardev
;
173 parent
= nv_pclass(object
->parent
, NV_PARENT_CLASS
);
174 pardev
= nv_subdev(parent
->engine
);
175 if (nv_parent(parent
)->context_detach
) {
176 mutex_lock(&pardev
->mutex
);
177 ret
= nv_parent(parent
)->context_detach(parent
, suspend
, object
);
178 mutex_unlock(&pardev
->mutex
);
182 nv_error(parent
, "failed to detach %s context, %d\n",
187 nv_debug(parent
, "detached %s context\n", subdev
->name
);
188 return nouveau_gpuobj_fini(&engctx
->gpuobj
, suspend
);
192 _nouveau_engctx_ctor(struct nouveau_object
*parent
,
193 struct nouveau_object
*engine
,
194 struct nouveau_oclass
*oclass
, void *data
, u32 size
,
195 struct nouveau_object
**pobject
)
197 struct nouveau_engctx
*engctx
;
200 ret
= nouveau_engctx_create(parent
, engine
, oclass
, NULL
, 256, 256,
201 NVOBJ_FLAG_ZERO_ALLOC
, &engctx
);
202 *pobject
= nv_object(engctx
);
207 _nouveau_engctx_dtor(struct nouveau_object
*object
)
209 nouveau_engctx_destroy(nv_engctx(object
));
213 _nouveau_engctx_init(struct nouveau_object
*object
)
215 return nouveau_engctx_init(nv_engctx(object
));
220 _nouveau_engctx_fini(struct nouveau_object
*object
, bool suspend
)
222 return nouveau_engctx_fini(nv_engctx(object
), suspend
);
225 struct nouveau_object
*
226 nouveau_engctx_get(struct nouveau_engine
*engine
, u64 addr
)
228 struct nouveau_engctx
*engctx
;
231 spin_lock_irqsave(&engine
->lock
, flags
);
232 list_for_each_entry(engctx
, &engine
->contexts
, head
) {
233 if (engctx
->addr
== addr
) {
234 engctx
->save
= flags
;
235 return nv_object(engctx
);
238 spin_unlock_irqrestore(&engine
->lock
, flags
);
243 nouveau_engctx_put(struct nouveau_object
*object
)
246 struct nouveau_engine
*engine
= nv_engine(object
->engine
);
247 struct nouveau_engctx
*engctx
= nv_engctx(object
);
248 spin_unlock_irqrestore(&engine
->lock
, engctx
->save
);
This page took 0.043492 seconds and 5 git commands to generate.