Home | History | Annotate | Line # | Download | only in core
      1 /*	$NetBSD: nouveau_nvkm_core_gpuobj.c,v 1.5 2021/12/18 23:45:34 riastradh Exp $	*/
      2 
      3 /*
      4  * Copyright 2012 Red Hat Inc.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the "Software"),
      8  * to deal in the Software without restriction, including without limitation
      9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     10  * and/or sell copies of the Software, and to permit persons to whom the
     11  * Software is furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice shall be included in
     14  * all copies or substantial portions of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     19  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
     20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     22  * OTHER DEALINGS IN THE SOFTWARE.
     23  *
     24  * Authors: Ben Skeggs
     25  */
     26 #include <sys/cdefs.h>
     27 __KERNEL_RCSID(0, "$NetBSD: nouveau_nvkm_core_gpuobj.c,v 1.5 2021/12/18 23:45:34 riastradh Exp $");
     28 
     29 #include <core/gpuobj.h>
     30 #include <core/engine.h>
     31 
     32 #include <subdev/instmem.h>
     33 #include <subdev/bar.h>
     34 #include <subdev/mmu.h>
     35 
     36 #ifdef __NetBSD__
     37 
     38 /*
     39  * XXX I think this should be done with bus_space, but the depth of
     40  * abstractions is dizzying and I'm not actually sure where these
     41  * pointers come from.
     42  */
     43 
     44 #  define	__iomem			__nvkm_gpuobj_iomem
     45 #  define	ioread32_native		fake_ioread32_native
     46 #  define	iowrite32_native	fake_iowrite32_native
     47 
     48 static inline uint32_t
     49 ioread32_native(const void __iomem *ptr)
     50 {
     51 	uint32_t v;
     52 
     53 	v = *(const uint32_t __iomem *)ptr;
     54 	membar_consumer();
     55 
     56 	return v;
     57 }
     58 
     59 static inline void
     60 iowrite32_native(uint32_t v, void __iomem *ptr)
     61 {
     62 
     63 	membar_producer();
     64 	*(uint32_t __iomem *)ptr = v;
     65 }
     66 
     67 #endif
     68 
     69 /* fast-path, where backend is able to provide direct pointer to memory */
     70 static u32
     71 nvkm_gpuobj_rd32_fast(struct nvkm_gpuobj *gpuobj, u32 offset)
     72 {
     73 	return ioread32_native((const char __iomem *)gpuobj->map + offset);
     74 }
     75 
     76 static void
     77 nvkm_gpuobj_wr32_fast(struct nvkm_gpuobj *gpuobj, u32 offset, u32 data)
     78 {
     79 	iowrite32_native(data, (char __iomem *)gpuobj->map + offset);
     80 }
     81 
     82 #ifdef __NetBSD__
     83 #  undef	ioread32_native
     84 #  undef	iowrite32_native
     85 #endif
     86 
     87 /* accessor functions for gpuobjs allocated directly from instmem */
     88 static int
     89 nvkm_gpuobj_heap_map(struct nvkm_gpuobj *gpuobj, u64 offset,
     90 		     struct nvkm_vmm *vmm, struct nvkm_vma *vma,
     91 		     void *argv, u32 argc)
     92 {
     93 	return nvkm_memory_map(gpuobj->memory, offset, vmm, vma, argv, argc);
     94 }
     95 
     96 static u32
     97 nvkm_gpuobj_heap_rd32(struct nvkm_gpuobj *gpuobj, u32 offset)
     98 {
     99 	return nvkm_ro32(gpuobj->memory, offset);
    100 }
    101 
    102 static void
    103 nvkm_gpuobj_heap_wr32(struct nvkm_gpuobj *gpuobj, u32 offset, u32 data)
    104 {
    105 	nvkm_wo32(gpuobj->memory, offset, data);
    106 }
    107 
    108 static const struct nvkm_gpuobj_func nvkm_gpuobj_heap;
    109 static void
    110 nvkm_gpuobj_heap_release(struct nvkm_gpuobj *gpuobj)
    111 {
    112 	gpuobj->func = &nvkm_gpuobj_heap;
    113 	nvkm_done(gpuobj->memory);
    114 }
    115 
    116 static const struct nvkm_gpuobj_func
    117 nvkm_gpuobj_heap_fast = {
    118 	.release = nvkm_gpuobj_heap_release,
    119 	.rd32 = nvkm_gpuobj_rd32_fast,
    120 	.wr32 = nvkm_gpuobj_wr32_fast,
    121 	.map = nvkm_gpuobj_heap_map,
    122 };
    123 
    124 static const struct nvkm_gpuobj_func
    125 nvkm_gpuobj_heap_slow = {
    126 	.release = nvkm_gpuobj_heap_release,
    127 	.rd32 = nvkm_gpuobj_heap_rd32,
    128 	.wr32 = nvkm_gpuobj_heap_wr32,
    129 	.map = nvkm_gpuobj_heap_map,
    130 };
    131 
    132 static void *
    133 nvkm_gpuobj_heap_acquire(struct nvkm_gpuobj *gpuobj)
    134 {
    135 	gpuobj->map = nvkm_kmap(gpuobj->memory);
    136 	if (likely(gpuobj->map))
    137 		gpuobj->func = &nvkm_gpuobj_heap_fast;
    138 	else
    139 		gpuobj->func = &nvkm_gpuobj_heap_slow;
    140 	return gpuobj->map;
    141 }
    142 
    143 static const struct nvkm_gpuobj_func
    144 nvkm_gpuobj_heap = {
    145 	.acquire = nvkm_gpuobj_heap_acquire,
    146 	.map = nvkm_gpuobj_heap_map,
    147 };
    148 
    149 /* accessor functions for gpuobjs sub-allocated from a parent gpuobj */
    150 static int
    151 nvkm_gpuobj_map(struct nvkm_gpuobj *gpuobj, u64 offset,
    152 		struct nvkm_vmm *vmm, struct nvkm_vma *vma,
    153 		void *argv, u32 argc)
    154 {
    155 	return nvkm_memory_map(gpuobj->parent, gpuobj->node->offset + offset,
    156 			       vmm, vma, argv, argc);
    157 }
    158 
    159 static u32
    160 nvkm_gpuobj_rd32(struct nvkm_gpuobj *gpuobj, u32 offset)
    161 {
    162 	return nvkm_ro32(gpuobj->parent, gpuobj->node->offset + offset);
    163 }
    164 
    165 static void
    166 nvkm_gpuobj_wr32(struct nvkm_gpuobj *gpuobj, u32 offset, u32 data)
    167 {
    168 	nvkm_wo32(gpuobj->parent, gpuobj->node->offset + offset, data);
    169 }
    170 
    171 static const struct nvkm_gpuobj_func nvkm_gpuobj_func;
    172 static void
    173 nvkm_gpuobj_release(struct nvkm_gpuobj *gpuobj)
    174 {
    175 	gpuobj->func = &nvkm_gpuobj_func;
    176 	nvkm_done(gpuobj->parent);
    177 }
    178 
    179 static const struct nvkm_gpuobj_func
    180 nvkm_gpuobj_fast = {
    181 	.release = nvkm_gpuobj_release,
    182 	.rd32 = nvkm_gpuobj_rd32_fast,
    183 	.wr32 = nvkm_gpuobj_wr32_fast,
    184 	.map = nvkm_gpuobj_map,
    185 };
    186 
    187 static const struct nvkm_gpuobj_func
    188 nvkm_gpuobj_slow = {
    189 	.release = nvkm_gpuobj_release,
    190 	.rd32 = nvkm_gpuobj_rd32,
    191 	.wr32 = nvkm_gpuobj_wr32,
    192 	.map = nvkm_gpuobj_map,
    193 };
    194 
    195 static void *
    196 nvkm_gpuobj_acquire(struct nvkm_gpuobj *gpuobj)
    197 {
    198 	gpuobj->map = nvkm_kmap(gpuobj->parent);
    199 	if (likely(gpuobj->map)) {
    200 		gpuobj->map  = (u8 *)gpuobj->map + gpuobj->node->offset;
    201 		gpuobj->func = &nvkm_gpuobj_fast;
    202 	} else {
    203 		gpuobj->func = &nvkm_gpuobj_slow;
    204 	}
    205 	return gpuobj->map;
    206 }
    207 
    208 static const struct nvkm_gpuobj_func
    209 nvkm_gpuobj_func = {
    210 	.acquire = nvkm_gpuobj_acquire,
    211 	.map = nvkm_gpuobj_map,
    212 };
    213 
    214 static int
    215 nvkm_gpuobj_ctor(struct nvkm_device *device, u32 size, int align, bool zero,
    216 		 struct nvkm_gpuobj *parent, struct nvkm_gpuobj *gpuobj)
    217 {
    218 	u32 offset;
    219 	int ret;
    220 
    221 	if (parent) {
    222 		if (align >= 0) {
    223 			ret = nvkm_mm_head(&parent->heap, 0, 1, size, size,
    224 					   max(align, 1), &gpuobj->node);
    225 		} else {
    226 			ret = nvkm_mm_tail(&parent->heap, 0, 1, size, size,
    227 					   -align, &gpuobj->node);
    228 		}
    229 		if (ret)
    230 			return ret;
    231 
    232 		gpuobj->parent = parent;
    233 		gpuobj->func = &nvkm_gpuobj_func;
    234 		gpuobj->addr = parent->addr + gpuobj->node->offset;
    235 		gpuobj->size = gpuobj->node->length;
    236 
    237 		if (zero) {
    238 			nvkm_kmap(gpuobj);
    239 			for (offset = 0; offset < gpuobj->size; offset += 4)
    240 				nvkm_wo32(gpuobj, offset, 0x00000000);
    241 			nvkm_done(gpuobj);
    242 		}
    243 	} else {
    244 		ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, size,
    245 				      abs(align), zero, &gpuobj->memory);
    246 		if (ret)
    247 			return ret;
    248 
    249 		gpuobj->func = &nvkm_gpuobj_heap;
    250 		gpuobj->addr = nvkm_memory_addr(gpuobj->memory);
    251 		gpuobj->size = nvkm_memory_size(gpuobj->memory);
    252 	}
    253 
    254 	return nvkm_mm_init(&gpuobj->heap, 0, 0, gpuobj->size, 1);
    255 }
    256 
    257 void
    258 nvkm_gpuobj_del(struct nvkm_gpuobj **pgpuobj)
    259 {
    260 	struct nvkm_gpuobj *gpuobj = *pgpuobj;
    261 	if (gpuobj) {
    262 		if (gpuobj->parent)
    263 			nvkm_mm_free(&gpuobj->parent->heap, &gpuobj->node);
    264 		nvkm_mm_fini(&gpuobj->heap);
    265 		nvkm_memory_unref(&gpuobj->memory);
    266 		kfree(*pgpuobj);
    267 		*pgpuobj = NULL;
    268 	}
    269 }
    270 
    271 int
    272 nvkm_gpuobj_new(struct nvkm_device *device, u32 size, int align, bool zero,
    273 		struct nvkm_gpuobj *parent, struct nvkm_gpuobj **pgpuobj)
    274 {
    275 	struct nvkm_gpuobj *gpuobj;
    276 	int ret;
    277 
    278 	if (!(gpuobj = *pgpuobj = kzalloc(sizeof(*gpuobj), GFP_KERNEL)))
    279 		return -ENOMEM;
    280 
    281 	ret = nvkm_gpuobj_ctor(device, size, align, zero, parent, gpuobj);
    282 	if (ret)
    283 		nvkm_gpuobj_del(pgpuobj);
    284 	return ret;
    285 }
    286 
    287 /* the below is basically only here to support sharing the paged dma object
    288  * for PCI(E)GART on <=nv4x chipsets, and should *not* be expected to work
    289  * anywhere else.
    290  */
    291 
    292 int
    293 nvkm_gpuobj_wrap(struct nvkm_memory *memory, struct nvkm_gpuobj **pgpuobj)
    294 {
    295 	if (!(*pgpuobj = kzalloc(sizeof(**pgpuobj), GFP_KERNEL)))
    296 		return -ENOMEM;
    297 
    298 	(*pgpuobj)->addr = nvkm_memory_addr(memory);
    299 	(*pgpuobj)->size = nvkm_memory_size(memory);
    300 	return 0;
    301 }
    302 
    303 void
    304 nvkm_gpuobj_memcpy_to(struct nvkm_gpuobj *dst, u32 dstoffset, void *src,
    305 		      u32 length)
    306 {
    307 	int i;
    308 
    309 	for (i = 0; i < length; i += 4)
    310 		nvkm_wo32(dst, dstoffset + i, *(u32 *)(src + i));
    311 }
    312 
    313 void
    314 nvkm_gpuobj_memcpy_from(void *dst, struct nvkm_gpuobj *src, u32 srcoffset,
    315 			u32 length)
    316 {
    317 	int i;
    318 
    319 	for (i = 0; i < length; i += 4)
    320 		((u32 *)src)[i / 4] = nvkm_ro32(src, srcoffset + i);
    321 }
    322