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