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