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/gpuobj.h>
28 #include <subdev/instmem.h>
29 #include <subdev/bar.h>
30 #include <subdev/vm.h>
33 nouveau_gpuobj_destroy(struct nouveau_gpuobj
*gpuobj
)
37 if (gpuobj
->flags
& NVOBJ_FLAG_ZERO_FREE
) {
38 for (i
= 0; i
< gpuobj
->size
; i
+= 4)
39 nv_wo32(gpuobj
, i
, 0x00000000);
43 nouveau_mm_free(&nv_gpuobj(gpuobj
->parent
)->heap
,
47 if (gpuobj
->heap
.block_size
)
48 nouveau_mm_fini(&gpuobj
->heap
);
50 nouveau_object_destroy(&gpuobj
->base
);
54 nouveau_gpuobj_create_(struct nouveau_object
*parent
,
55 struct nouveau_object
*engine
,
56 struct nouveau_oclass
*oclass
, u32 pclass
,
57 struct nouveau_object
*pargpu
,
58 u32 size
, u32 align
, u32 flags
,
59 int length
, void **pobject
)
61 struct nouveau_instmem
*imem
= nouveau_instmem(parent
);
62 struct nouveau_bar
*bar
= nouveau_bar(parent
);
63 struct nouveau_gpuobj
*gpuobj
;
64 struct nouveau_mm
*heap
= NULL
;
71 while ((pargpu
= nv_pclass(pargpu
, NV_GPUOBJ_CLASS
))) {
72 if (nv_gpuobj(pargpu
)->heap
.block_size
)
74 pargpu
= pargpu
->parent
;
77 if (unlikely(pargpu
== NULL
)) {
78 nv_error(parent
, "no gpuobj heap\n");
82 addr
= nv_gpuobj(pargpu
)->addr
;
83 heap
= &nv_gpuobj(pargpu
)->heap
;
84 atomic_inc(&parent
->refcount
);
86 ret
= imem
->alloc(imem
, parent
, size
, align
, &parent
);
91 addr
= nv_memobj(pargpu
)->addr
;
92 size
= nv_memobj(pargpu
)->size
;
94 if (bar
&& bar
->alloc
) {
95 struct nouveau_instobj
*iobj
= (void *)parent
;
96 struct nouveau_mem
**mem
= (void *)(iobj
+ 1);
97 struct nouveau_mem
*node
= *mem
;
98 if (!bar
->alloc(bar
, parent
, node
, &pargpu
)) {
99 nouveau_object_ref(NULL
, &parent
);
105 ret
= nouveau_object_create_(parent
, engine
, oclass
, pclass
|
106 NV_GPUOBJ_CLASS
, length
, pobject
);
107 nouveau_object_ref(NULL
, &parent
);
112 gpuobj
->parent
= pargpu
;
113 gpuobj
->flags
= flags
;
118 ret
= nouveau_mm_head(heap
, 1, size
, size
,
119 max(align
, (u32
)1), &gpuobj
->node
);
123 gpuobj
->addr
+= gpuobj
->node
->offset
;
126 if (gpuobj
->flags
& NVOBJ_FLAG_HEAP
) {
127 ret
= nouveau_mm_init(&gpuobj
->heap
, 0, gpuobj
->size
, 1);
132 if (flags
& NVOBJ_FLAG_ZERO_ALLOC
) {
133 for (i
= 0; i
< gpuobj
->size
; i
+= 4)
134 nv_wo32(gpuobj
, i
, 0x00000000);
140 struct nouveau_gpuobj_class
{
141 struct nouveau_object
*pargpu
;
148 _nouveau_gpuobj_ctor(struct nouveau_object
*parent
,
149 struct nouveau_object
*engine
,
150 struct nouveau_oclass
*oclass
, void *data
, u32 size
,
151 struct nouveau_object
**pobject
)
153 struct nouveau_gpuobj_class
*args
= data
;
154 struct nouveau_gpuobj
*object
;
157 ret
= nouveau_gpuobj_create(parent
, engine
, oclass
, 0, args
->pargpu
,
158 args
->size
, args
->align
, args
->flags
,
160 *pobject
= nv_object(object
);
168 _nouveau_gpuobj_dtor(struct nouveau_object
*object
)
170 nouveau_gpuobj_destroy(nv_gpuobj(object
));
174 _nouveau_gpuobj_init(struct nouveau_object
*object
)
176 return nouveau_gpuobj_init(nv_gpuobj(object
));
180 _nouveau_gpuobj_fini(struct nouveau_object
*object
, bool suspend
)
182 return nouveau_gpuobj_fini(nv_gpuobj(object
), suspend
);
186 _nouveau_gpuobj_rd32(struct nouveau_object
*object
, u32 addr
)
188 struct nouveau_gpuobj
*gpuobj
= nv_gpuobj(object
);
189 struct nouveau_ofuncs
*pfuncs
= nv_ofuncs(gpuobj
->parent
);
191 addr
+= gpuobj
->node
->offset
;
192 return pfuncs
->rd32(gpuobj
->parent
, addr
);
196 _nouveau_gpuobj_wr32(struct nouveau_object
*object
, u32 addr
, u32 data
)
198 struct nouveau_gpuobj
*gpuobj
= nv_gpuobj(object
);
199 struct nouveau_ofuncs
*pfuncs
= nv_ofuncs(gpuobj
->parent
);
201 addr
+= gpuobj
->node
->offset
;
202 pfuncs
->wr32(gpuobj
->parent
, addr
, data
);
205 static struct nouveau_oclass
206 _nouveau_gpuobj_oclass
= {
207 .handle
= 0x00000000,
208 .ofuncs
= &(struct nouveau_ofuncs
) {
209 .ctor
= _nouveau_gpuobj_ctor
,
210 .dtor
= _nouveau_gpuobj_dtor
,
211 .init
= _nouveau_gpuobj_init
,
212 .fini
= _nouveau_gpuobj_fini
,
213 .rd32
= _nouveau_gpuobj_rd32
,
214 .wr32
= _nouveau_gpuobj_wr32
,
219 nouveau_gpuobj_new(struct nouveau_object
*parent
, struct nouveau_object
*pargpu
,
220 u32 size
, u32 align
, u32 flags
,
221 struct nouveau_gpuobj
**pgpuobj
)
223 struct nouveau_object
*engine
= parent
;
224 struct nouveau_gpuobj_class args
= {
231 if (!nv_iclass(engine
, NV_SUBDEV_CLASS
))
232 engine
= engine
->engine
;
233 BUG_ON(engine
== NULL
);
235 return nouveau_object_ctor(parent
, engine
, &_nouveau_gpuobj_oclass
,
237 (struct nouveau_object
**)pgpuobj
);
241 nouveau_gpuobj_map(struct nouveau_gpuobj
*gpuobj
, u32 access
,
242 struct nouveau_vma
*vma
)
244 struct nouveau_bar
*bar
= nouveau_bar(gpuobj
);
247 if (bar
&& bar
->umap
) {
248 struct nouveau_instobj
*iobj
= (void *)
249 nv_pclass(nv_object(gpuobj
), NV_MEMOBJ_CLASS
);
250 struct nouveau_mem
**mem
= (void *)(iobj
+ 1);
251 ret
= bar
->umap(bar
, *mem
, access
, vma
);
258 nouveau_gpuobj_map_vm(struct nouveau_gpuobj
*gpuobj
, struct nouveau_vm
*vm
,
259 u32 access
, struct nouveau_vma
*vma
)
261 struct nouveau_instobj
*iobj
= (void *)
262 nv_pclass(nv_object(gpuobj
), NV_MEMOBJ_CLASS
);
263 struct nouveau_mem
**mem
= (void *)(iobj
+ 1);
266 ret
= nouveau_vm_get(vm
, gpuobj
->size
, 12, access
, vma
);
270 nouveau_vm_map(vma
, *mem
);
275 nouveau_gpuobj_unmap(struct nouveau_vma
*vma
)
278 nouveau_vm_unmap(vma
);
283 /* the below is basically only here to support sharing the paged dma object
284 * for PCI(E)GART on <=nv4x chipsets, and should *not* be expected to work
289 nouveau_gpudup_dtor(struct nouveau_object
*object
)
291 struct nouveau_gpuobj
*gpuobj
= (void *)object
;
292 nouveau_object_ref(NULL
, &gpuobj
->parent
);
293 nouveau_object_destroy(&gpuobj
->base
);
296 static struct nouveau_oclass
297 nouveau_gpudup_oclass
= {
298 .handle
= NV_GPUOBJ_CLASS
,
299 .ofuncs
= &(struct nouveau_ofuncs
) {
300 .dtor
= nouveau_gpudup_dtor
,
301 .init
= nouveau_object_init
,
302 .fini
= nouveau_object_fini
,
307 nouveau_gpuobj_dup(struct nouveau_object
*parent
, struct nouveau_gpuobj
*base
,
308 struct nouveau_gpuobj
**pgpuobj
)
310 struct nouveau_gpuobj
*gpuobj
;
313 ret
= nouveau_object_create(parent
, parent
->engine
,
314 &nouveau_gpudup_oclass
, 0, &gpuobj
);
319 nouveau_object_ref(nv_object(base
), &gpuobj
->parent
);
320 gpuobj
->addr
= base
->addr
;
321 gpuobj
->size
= base
->size
;