1 /* 2 * Copyright 2012 Red Hat Inc. 3 * 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: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 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. 21 * 22 * Authors: Ben Skeggs 23 */ 24 #define nv50_instmem(p) container_of((p), struct nv50_instmem, base) 25 #include "priv.h" 26 27 #include <core/memory.h> 28 #include <subdev/bar.h> 29 #include <subdev/fb.h> 30 #include <subdev/gsp.h> 31 #include <subdev/mmu.h> 32 33 struct nv50_instmem { 34 struct nvkm_instmem base; 35 u64 addr; 36 37 /* Mappings that can be evicted when BAR2 space has been exhausted. */ 38 struct list_head lru; 39 }; 40 41 /****************************************************************************** 42 * instmem object implementation 43 *****************************************************************************/ 44 #define nv50_instobj(p) container_of((p), struct nv50_instobj, base.memory) 45 46 struct nv50_instobj { 47 struct nvkm_instobj base; 48 struct nv50_instmem *imem; 49 struct nvkm_memory *ram; 50 struct nvkm_vma *bar; 51 refcount_t maps; 52 void *map; 53 struct list_head lru; 54 }; 55 56 static void 57 nv50_instobj_wr32_slow(struct nvkm_memory *memory, u64 offset, u32 data) 58 { 59 struct nv50_instobj *iobj = nv50_instobj(memory); 60 struct nv50_instmem *imem = iobj->imem; 61 struct nvkm_device *device = imem->base.subdev.device; 62 u64 base = (nvkm_memory_addr(iobj->ram) + offset) & 0xffffff00000ULL; 63 u64 addr = (nvkm_memory_addr(iobj->ram) + offset) & 0x000000fffffULL; 64 unsigned long flags; 65 66 spin_lock_irqsave(&imem->base.lock, flags); 67 if (unlikely(imem->addr != base)) { 68 nvkm_wr32(device, 0x001700, base >> 16); 69 imem->addr = base; 70 } 71 nvkm_wr32(device, 0x700000 + addr, data); 72 spin_unlock_irqrestore(&imem->base.lock, flags); 73 } 74 75 static u32 76 nv50_instobj_rd32_slow(struct nvkm_memory *memory, u64 offset) 77 { 78 struct nv50_instobj *iobj = nv50_instobj(memory); 79 struct nv50_instmem *imem = iobj->imem; 80 struct nvkm_device *device = imem->base.subdev.device; 81 u64 base = (nvkm_memory_addr(iobj->ram) + offset) & 0xffffff00000ULL; 82 u64 addr = (nvkm_memory_addr(iobj->ram) + offset) & 0x000000fffffULL; 83 u32 data; 84 unsigned long flags; 85 86 spin_lock_irqsave(&imem->base.lock, flags); 87 if (unlikely(imem->addr != base)) { 88 nvkm_wr32(device, 0x001700, base >> 16); 89 imem->addr = base; 90 } 91 data = nvkm_rd32(device, 0x700000 + addr); 92 spin_unlock_irqrestore(&imem->base.lock, flags); 93 return data; 94 } 95 96 static const struct nvkm_memory_ptrs 97 nv50_instobj_slow = { 98 .rd32 = nv50_instobj_rd32_slow, 99 .wr32 = nv50_instobj_wr32_slow, 100 }; 101 102 static void 103 nv50_instobj_wr32(struct nvkm_memory *memory, u64 offset, u32 data) 104 { 105 iowrite32_native(data, nv50_instobj(memory)->map + offset); 106 } 107 108 static u32 109 nv50_instobj_rd32(struct nvkm_memory *memory, u64 offset) 110 { 111 return ioread32_native(nv50_instobj(memory)->map + offset); 112 } 113 114 static const struct nvkm_memory_ptrs 115 nv50_instobj_fast = { 116 .rd32 = nv50_instobj_rd32, 117 .wr32 = nv50_instobj_wr32, 118 }; 119 120 static void 121 nv50_instobj_kmap(struct nv50_instobj *iobj, struct nvkm_vmm *vmm) 122 { 123 struct nv50_instmem *imem = iobj->imem; 124 struct nv50_instobj *eobj; 125 struct nvkm_memory *memory = &iobj->base.memory; 126 struct nvkm_subdev *subdev = &imem->base.subdev; 127 struct nvkm_device *device = subdev->device; 128 struct nvkm_vma *bar = NULL, *ebar; 129 u64 size = nvkm_memory_size(memory); 130 void *emap; 131 int ret; 132 133 /* Attempt to allocate BAR2 address-space and map the object 134 * into it. The lock has to be dropped while doing this due 135 * to the possibility of recursion for page table allocation. 136 */ 137 mutex_unlock(&imem->base.mutex); 138 while ((ret = nvkm_vmm_get(vmm, 12, size, &bar))) { 139 /* Evict unused mappings, and keep retrying until we either 140 * succeed,or there's no more objects left on the LRU. 141 */ 142 mutex_lock(&imem->base.mutex); 143 eobj = list_first_entry_or_null(&imem->lru, typeof(*eobj), lru); 144 if (eobj) { 145 nvkm_debug(subdev, "evict %016llx %016llx @ %016llx\n", 146 nvkm_memory_addr(&eobj->base.memory), 147 nvkm_memory_size(&eobj->base.memory), 148 eobj->bar->addr); 149 list_del_init(&eobj->lru); 150 ebar = eobj->bar; 151 eobj->bar = NULL; 152 emap = eobj->map; 153 eobj->map = NULL; 154 } 155 mutex_unlock(&imem->base.mutex); 156 if (!eobj) 157 break; 158 iounmap(emap); 159 nvkm_vmm_put(vmm, &ebar); 160 } 161 162 if (ret == 0) 163 ret = nvkm_memory_map(memory, 0, vmm, bar, NULL, 0); 164 mutex_lock(&imem->base.mutex); 165 if (ret || iobj->bar) { 166 /* We either failed, or another thread beat us. */ 167 mutex_unlock(&imem->base.mutex); 168 nvkm_vmm_put(vmm, &bar); 169 mutex_lock(&imem->base.mutex); 170 return; 171 } 172 173 /* Make the mapping visible to the host. */ 174 iobj->bar = bar; 175 iobj->map = ioremap_wc(device->func->resource_addr(device, 3) + 176 (u32)iobj->bar->addr, size); 177 if (!iobj->map) { 178 nvkm_warn(subdev, "PRAMIN ioremap failed\n"); 179 nvkm_vmm_put(vmm, &iobj->bar); 180 } 181 } 182 183 static int 184 nv50_instobj_map(struct nvkm_memory *memory, u64 offset, struct nvkm_vmm *vmm, 185 struct nvkm_vma *vma, void *argv, u32 argc) 186 { 187 memory = nv50_instobj(memory)->ram; 188 return nvkm_memory_map(memory, offset, vmm, vma, argv, argc); 189 } 190 191 static void 192 nv50_instobj_release(struct nvkm_memory *memory) 193 { 194 struct nv50_instobj *iobj = nv50_instobj(memory); 195 struct nv50_instmem *imem = iobj->imem; 196 struct nvkm_subdev *subdev = &imem->base.subdev; 197 198 wmb(); 199 nvkm_bar_flush(subdev->device->bar); 200 201 if (refcount_dec_and_mutex_lock(&iobj->maps, &imem->base.mutex)) { 202 /* Add the now-unused mapping to the LRU instead of directly 203 * unmapping it here, in case we need to map it again later. 204 */ 205 if (likely(iobj->lru.next) && iobj->map) { 206 BUG_ON(!list_empty(&iobj->lru)); 207 list_add_tail(&iobj->lru, &imem->lru); 208 } 209 210 /* Switch back to NULL accessors when last map is gone. */ 211 iobj->base.memory.ptrs = NULL; 212 mutex_unlock(&imem->base.mutex); 213 } 214 } 215 216 static void __iomem * 217 nv50_instobj_acquire(struct nvkm_memory *memory) 218 { 219 struct nv50_instobj *iobj = nv50_instobj(memory); 220 struct nvkm_instmem *imem = &iobj->imem->base; 221 struct nvkm_vmm *vmm; 222 void __iomem *map = NULL; 223 224 /* Already mapped? */ 225 if (refcount_inc_not_zero(&iobj->maps)) 226 return iobj->map; 227 228 /* Take the lock, and re-check that another thread hasn't 229 * already mapped the object in the meantime. 230 */ 231 mutex_lock(&imem->mutex); 232 if (refcount_inc_not_zero(&iobj->maps)) { 233 mutex_unlock(&imem->mutex); 234 return iobj->map; 235 } 236 237 /* Attempt to get a direct CPU mapping of the object. */ 238 if ((vmm = nvkm_bar_bar2_vmm(imem->subdev.device))) { 239 if (!iobj->map) 240 nv50_instobj_kmap(iobj, vmm); 241 map = iobj->map; 242 } 243 244 if (!refcount_inc_not_zero(&iobj->maps)) { 245 /* Exclude object from eviction while it's being accessed. */ 246 if (likely(iobj->lru.next)) 247 list_del_init(&iobj->lru); 248 249 if (map) 250 iobj->base.memory.ptrs = &nv50_instobj_fast; 251 else 252 iobj->base.memory.ptrs = &nv50_instobj_slow; 253 refcount_set(&iobj->maps, 1); 254 } 255 256 mutex_unlock(&imem->mutex); 257 return map; 258 } 259 260 static void 261 nv50_instobj_boot(struct nvkm_memory *memory, struct nvkm_vmm *vmm) 262 { 263 struct nv50_instobj *iobj = nv50_instobj(memory); 264 struct nvkm_instmem *imem = &iobj->imem->base; 265 266 /* Exclude bootstrapped objects (ie. the page tables for the 267 * instmem BAR itself) from eviction. 268 */ 269 mutex_lock(&imem->mutex); 270 if (likely(iobj->lru.next)) { 271 list_del_init(&iobj->lru); 272 iobj->lru.next = NULL; 273 } 274 275 nv50_instobj_kmap(iobj, vmm); 276 nvkm_instmem_boot(imem); 277 mutex_unlock(&imem->mutex); 278 } 279 280 static u64 281 nv50_instobj_size(struct nvkm_memory *memory) 282 { 283 return nvkm_memory_size(nv50_instobj(memory)->ram); 284 } 285 286 static u64 287 nv50_instobj_addr(struct nvkm_memory *memory) 288 { 289 return nvkm_memory_addr(nv50_instobj(memory)->ram); 290 } 291 292 static u64 293 nv50_instobj_bar2(struct nvkm_memory *memory) 294 { 295 struct nv50_instobj *iobj = nv50_instobj(memory); 296 u64 addr = ~0ULL; 297 if (nv50_instobj_acquire(&iobj->base.memory)) { 298 iobj->lru.next = NULL; /* Exclude from eviction. */ 299 addr = iobj->bar->addr; 300 } 301 nv50_instobj_release(&iobj->base.memory); 302 return addr; 303 } 304 305 static enum nvkm_memory_target 306 nv50_instobj_target(struct nvkm_memory *memory) 307 { 308 return nvkm_memory_target(nv50_instobj(memory)->ram); 309 } 310 311 static void * 312 nv50_instobj_dtor(struct nvkm_memory *memory) 313 { 314 struct nv50_instobj *iobj = nv50_instobj(memory); 315 struct nvkm_instmem *imem = &iobj->imem->base; 316 struct nvkm_vma *bar; 317 void *map; 318 319 mutex_lock(&imem->mutex); 320 if (likely(iobj->lru.next)) 321 list_del(&iobj->lru); 322 map = iobj->map; 323 bar = iobj->bar; 324 mutex_unlock(&imem->mutex); 325 326 if (map) { 327 struct nvkm_vmm *vmm = nvkm_bar_bar2_vmm(imem->subdev.device); 328 iounmap(map); 329 if (likely(vmm)) /* Can be NULL during BAR destructor. */ 330 nvkm_vmm_put(vmm, &bar); 331 } 332 333 nvkm_memory_unref(&iobj->ram); 334 nvkm_instobj_dtor(imem, &iobj->base); 335 return iobj; 336 } 337 338 static const struct nvkm_memory_func 339 nv50_instobj_func = { 340 .dtor = nv50_instobj_dtor, 341 .target = nv50_instobj_target, 342 .bar2 = nv50_instobj_bar2, 343 .addr = nv50_instobj_addr, 344 .size = nv50_instobj_size, 345 .boot = nv50_instobj_boot, 346 .acquire = nv50_instobj_acquire, 347 .release = nv50_instobj_release, 348 .map = nv50_instobj_map, 349 }; 350 351 static int 352 nv50_instobj_wrap(struct nvkm_instmem *base, 353 struct nvkm_memory *memory, struct nvkm_memory **pmemory) 354 { 355 struct nv50_instmem *imem = nv50_instmem(base); 356 struct nv50_instobj *iobj; 357 358 if (!(iobj = kzalloc(sizeof(*iobj), GFP_KERNEL))) 359 return -ENOMEM; 360 *pmemory = &iobj->base.memory; 361 362 nvkm_instobj_ctor(&nv50_instobj_func, &imem->base, &iobj->base); 363 iobj->imem = imem; 364 refcount_set(&iobj->maps, 0); 365 INIT_LIST_HEAD(&iobj->lru); 366 367 iobj->ram = nvkm_memory_ref(memory); 368 return 0; 369 } 370 371 static int 372 nv50_instobj_new(struct nvkm_instmem *imem, u32 size, u32 align, bool zero, 373 struct nvkm_memory **pmemory) 374 { 375 u8 page = max(order_base_2(align), 12); 376 struct nvkm_memory *ram; 377 int ret; 378 379 ret = nvkm_ram_get(imem->subdev.device, 0, 1, page, size, true, true, &ram); 380 if (ret) 381 return ret; 382 383 ret = nv50_instobj_wrap(imem, ram, pmemory); 384 nvkm_memory_unref(&ram); 385 return ret; 386 } 387 388 /****************************************************************************** 389 * instmem subdev implementation 390 *****************************************************************************/ 391 392 static void 393 nv50_instmem_fini(struct nvkm_instmem *base) 394 { 395 nv50_instmem(base)->addr = ~0ULL; 396 } 397 398 static void * 399 nv50_instmem_dtor(struct nvkm_instmem *base) 400 { 401 return nv50_instmem(base); 402 } 403 404 static const struct nvkm_instmem_func 405 nv50_instmem = { 406 .dtor = nv50_instmem_dtor, 407 .fini = nv50_instmem_fini, 408 .suspend = nv04_instmem_suspend, 409 .resume = nv04_instmem_resume, 410 .memory_new = nv50_instobj_new, 411 .memory_wrap = nv50_instobj_wrap, 412 .zero = false, 413 }; 414 415 int 416 nv50_instmem_new_(const struct nvkm_instmem_func *func, 417 struct nvkm_device *device, enum nvkm_subdev_type type, int inst, 418 struct nvkm_instmem **pimem) 419 { 420 struct nv50_instmem *imem; 421 422 if (!(imem = kzalloc(sizeof(*imem), GFP_KERNEL))) 423 return -ENOMEM; 424 nvkm_instmem_ctor(func, device, type, inst, &imem->base); 425 INIT_LIST_HEAD(&imem->lru); 426 *pimem = &imem->base; 427 return 0; 428 } 429 430 int 431 nv50_instmem_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, 432 struct nvkm_instmem **pimem) 433 { 434 if (nvkm_gsp_rm(device->gsp)) 435 return r535_instmem_new(&nv50_instmem, device, type, inst, pimem); 436 437 return nv50_instmem_new_(&nv50_instmem, device, type, inst, pimem); 438 } 439