1 1.3 riastrad /* $NetBSD: nouveau_dmem.c,v 1.3 2021/12/19 11:34:44 riastradh Exp $ */ 2 1.1 riastrad 3 1.1 riastrad /* 4 1.1 riastrad * Copyright 2018 Red Hat Inc. 5 1.1 riastrad * 6 1.1 riastrad * Permission is hereby granted, free of charge, to any person obtaining a 7 1.1 riastrad * copy of this software and associated documentation files (the "Software"), 8 1.1 riastrad * to deal in the Software without restriction, including without limitation 9 1.1 riastrad * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 1.1 riastrad * and/or sell copies of the Software, and to permit persons to whom the 11 1.1 riastrad * Software is furnished to do so, subject to the following conditions: 12 1.1 riastrad * 13 1.1 riastrad * The above copyright notice and this permission notice shall be included in 14 1.1 riastrad * all copies or substantial portions of the Software. 15 1.1 riastrad * 16 1.1 riastrad * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 1.1 riastrad * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 1.1 riastrad * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 1.1 riastrad * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 1.1 riastrad * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 1.1 riastrad * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 1.1 riastrad * OTHER DEALINGS IN THE SOFTWARE. 23 1.1 riastrad */ 24 1.1 riastrad #include <sys/cdefs.h> 25 1.3 riastrad __KERNEL_RCSID(0, "$NetBSD: nouveau_dmem.c,v 1.3 2021/12/19 11:34:44 riastradh Exp $"); 26 1.1 riastrad 27 1.1 riastrad #include "nouveau_dmem.h" 28 1.1 riastrad #include "nouveau_drv.h" 29 1.1 riastrad #include "nouveau_chan.h" 30 1.1 riastrad #include "nouveau_dma.h" 31 1.1 riastrad #include "nouveau_mem.h" 32 1.1 riastrad #include "nouveau_bo.h" 33 1.1 riastrad 34 1.1 riastrad #include <nvif/class.h> 35 1.1 riastrad #include <nvif/object.h> 36 1.1 riastrad #include <nvif/if500b.h> 37 1.1 riastrad #include <nvif/if900b.h> 38 1.1 riastrad 39 1.1 riastrad #include <linux/sched/mm.h> 40 1.1 riastrad #include <linux/hmm.h> 41 1.1 riastrad 42 1.1 riastrad /* 43 1.1 riastrad * FIXME: this is ugly right now we are using TTM to allocate vram and we pin 44 1.1 riastrad * it in vram while in use. We likely want to overhaul memory management for 45 1.1 riastrad * nouveau to be more page like (not necessarily with system page size but a 46 1.1 riastrad * bigger page size) at lowest level and have some shim layer on top that would 47 1.1 riastrad * provide the same functionality as TTM. 48 1.1 riastrad */ 49 1.1 riastrad #define DMEM_CHUNK_SIZE (2UL << 20) 50 1.1 riastrad #define DMEM_CHUNK_NPAGES (DMEM_CHUNK_SIZE >> PAGE_SHIFT) 51 1.1 riastrad 52 1.1 riastrad enum nouveau_aper { 53 1.1 riastrad NOUVEAU_APER_VIRT, 54 1.1 riastrad NOUVEAU_APER_VRAM, 55 1.1 riastrad NOUVEAU_APER_HOST, 56 1.1 riastrad }; 57 1.1 riastrad 58 1.1 riastrad typedef int (*nouveau_migrate_copy_t)(struct nouveau_drm *drm, u64 npages, 59 1.1 riastrad enum nouveau_aper, u64 dst_addr, 60 1.1 riastrad enum nouveau_aper, u64 src_addr); 61 1.1 riastrad 62 1.1 riastrad struct nouveau_dmem_chunk { 63 1.1 riastrad struct list_head list; 64 1.1 riastrad struct nouveau_bo *bo; 65 1.1 riastrad struct nouveau_drm *drm; 66 1.1 riastrad unsigned long pfn_first; 67 1.1 riastrad unsigned long callocated; 68 1.1 riastrad unsigned long bitmap[BITS_TO_LONGS(DMEM_CHUNK_NPAGES)]; 69 1.1 riastrad spinlock_t lock; 70 1.1 riastrad }; 71 1.1 riastrad 72 1.1 riastrad struct nouveau_dmem_migrate { 73 1.1 riastrad nouveau_migrate_copy_t copy_func; 74 1.1 riastrad struct nouveau_channel *chan; 75 1.1 riastrad }; 76 1.1 riastrad 77 1.1 riastrad struct nouveau_dmem { 78 1.1 riastrad struct nouveau_drm *drm; 79 1.1 riastrad struct dev_pagemap pagemap; 80 1.1 riastrad struct nouveau_dmem_migrate migrate; 81 1.1 riastrad struct list_head chunk_free; 82 1.1 riastrad struct list_head chunk_full; 83 1.1 riastrad struct list_head chunk_empty; 84 1.1 riastrad struct mutex mutex; 85 1.1 riastrad }; 86 1.1 riastrad 87 1.1 riastrad static inline struct nouveau_dmem *page_to_dmem(struct page *page) 88 1.1 riastrad { 89 1.1 riastrad return container_of(page->pgmap, struct nouveau_dmem, pagemap); 90 1.1 riastrad } 91 1.1 riastrad 92 1.1 riastrad static unsigned long nouveau_dmem_page_addr(struct page *page) 93 1.1 riastrad { 94 1.1 riastrad struct nouveau_dmem_chunk *chunk = page->zone_device_data; 95 1.1 riastrad unsigned long idx = page_to_pfn(page) - chunk->pfn_first; 96 1.1 riastrad 97 1.1 riastrad return (idx << PAGE_SHIFT) + chunk->bo->bo.offset; 98 1.1 riastrad } 99 1.1 riastrad 100 1.1 riastrad static void nouveau_dmem_page_free(struct page *page) 101 1.1 riastrad { 102 1.1 riastrad struct nouveau_dmem_chunk *chunk = page->zone_device_data; 103 1.1 riastrad unsigned long idx = page_to_pfn(page) - chunk->pfn_first; 104 1.1 riastrad 105 1.1 riastrad /* 106 1.1 riastrad * FIXME: 107 1.1 riastrad * 108 1.1 riastrad * This is really a bad example, we need to overhaul nouveau memory 109 1.1 riastrad * management to be more page focus and allow lighter locking scheme 110 1.1 riastrad * to be use in the process. 111 1.1 riastrad */ 112 1.1 riastrad spin_lock(&chunk->lock); 113 1.1 riastrad clear_bit(idx, chunk->bitmap); 114 1.1 riastrad WARN_ON(!chunk->callocated); 115 1.1 riastrad chunk->callocated--; 116 1.1 riastrad /* 117 1.1 riastrad * FIXME when chunk->callocated reach 0 we should add the chunk to 118 1.1 riastrad * a reclaim list so that it can be freed in case of memory pressure. 119 1.1 riastrad */ 120 1.1 riastrad spin_unlock(&chunk->lock); 121 1.1 riastrad } 122 1.1 riastrad 123 1.1 riastrad static void nouveau_dmem_fence_done(struct nouveau_fence **fence) 124 1.1 riastrad { 125 1.1 riastrad if (fence) { 126 1.1 riastrad nouveau_fence_wait(*fence, true, false); 127 1.1 riastrad nouveau_fence_unref(fence); 128 1.1 riastrad } else { 129 1.1 riastrad /* 130 1.1 riastrad * FIXME wait for channel to be IDLE before calling finalizing 131 1.1 riastrad * the hmem object. 132 1.1 riastrad */ 133 1.1 riastrad } 134 1.1 riastrad } 135 1.1 riastrad 136 1.1 riastrad static vm_fault_t nouveau_dmem_fault_copy_one(struct nouveau_drm *drm, 137 1.1 riastrad struct vm_fault *vmf, struct migrate_vma *args, 138 1.1 riastrad dma_addr_t *dma_addr) 139 1.1 riastrad { 140 1.1 riastrad struct device *dev = drm->dev->dev; 141 1.1 riastrad struct page *dpage, *spage; 142 1.1 riastrad 143 1.1 riastrad spage = migrate_pfn_to_page(args->src[0]); 144 1.1 riastrad if (!spage || !(args->src[0] & MIGRATE_PFN_MIGRATE)) 145 1.1 riastrad return 0; 146 1.1 riastrad 147 1.1 riastrad dpage = alloc_page_vma(GFP_HIGHUSER, vmf->vma, vmf->address); 148 1.1 riastrad if (!dpage) 149 1.1 riastrad return VM_FAULT_SIGBUS; 150 1.1 riastrad lock_page(dpage); 151 1.1 riastrad 152 1.1 riastrad *dma_addr = dma_map_page(dev, dpage, 0, PAGE_SIZE, DMA_BIDIRECTIONAL); 153 1.1 riastrad if (dma_mapping_error(dev, *dma_addr)) 154 1.1 riastrad goto error_free_page; 155 1.1 riastrad 156 1.1 riastrad if (drm->dmem->migrate.copy_func(drm, 1, NOUVEAU_APER_HOST, *dma_addr, 157 1.1 riastrad NOUVEAU_APER_VRAM, nouveau_dmem_page_addr(spage))) 158 1.1 riastrad goto error_dma_unmap; 159 1.1 riastrad 160 1.1 riastrad args->dst[0] = migrate_pfn(page_to_pfn(dpage)) | MIGRATE_PFN_LOCKED; 161 1.1 riastrad return 0; 162 1.1 riastrad 163 1.1 riastrad error_dma_unmap: 164 1.1 riastrad dma_unmap_page(dev, *dma_addr, PAGE_SIZE, DMA_BIDIRECTIONAL); 165 1.1 riastrad error_free_page: 166 1.1 riastrad __free_page(dpage); 167 1.1 riastrad return VM_FAULT_SIGBUS; 168 1.1 riastrad } 169 1.1 riastrad 170 1.1 riastrad static vm_fault_t nouveau_dmem_migrate_to_ram(struct vm_fault *vmf) 171 1.1 riastrad { 172 1.1 riastrad struct nouveau_dmem *dmem = page_to_dmem(vmf->page); 173 1.1 riastrad struct nouveau_drm *drm = dmem->drm; 174 1.1 riastrad struct nouveau_fence *fence; 175 1.1 riastrad unsigned long src = 0, dst = 0; 176 1.1 riastrad dma_addr_t dma_addr = 0; 177 1.1 riastrad vm_fault_t ret; 178 1.1 riastrad struct migrate_vma args = { 179 1.1 riastrad .vma = vmf->vma, 180 1.1 riastrad .start = vmf->address, 181 1.1 riastrad .end = vmf->address + PAGE_SIZE, 182 1.1 riastrad .src = &src, 183 1.1 riastrad .dst = &dst, 184 1.1 riastrad }; 185 1.1 riastrad 186 1.1 riastrad /* 187 1.1 riastrad * FIXME what we really want is to find some heuristic to migrate more 188 1.1 riastrad * than just one page on CPU fault. When such fault happens it is very 189 1.1 riastrad * likely that more surrounding page will CPU fault too. 190 1.1 riastrad */ 191 1.1 riastrad if (migrate_vma_setup(&args) < 0) 192 1.1 riastrad return VM_FAULT_SIGBUS; 193 1.1 riastrad if (!args.cpages) 194 1.1 riastrad return 0; 195 1.1 riastrad 196 1.1 riastrad ret = nouveau_dmem_fault_copy_one(drm, vmf, &args, &dma_addr); 197 1.1 riastrad if (ret || dst == 0) 198 1.1 riastrad goto done; 199 1.1 riastrad 200 1.1 riastrad nouveau_fence_new(dmem->migrate.chan, false, &fence); 201 1.1 riastrad migrate_vma_pages(&args); 202 1.1 riastrad nouveau_dmem_fence_done(&fence); 203 1.1 riastrad dma_unmap_page(drm->dev->dev, dma_addr, PAGE_SIZE, DMA_BIDIRECTIONAL); 204 1.1 riastrad done: 205 1.1 riastrad migrate_vma_finalize(&args); 206 1.1 riastrad return ret; 207 1.1 riastrad } 208 1.1 riastrad 209 1.1 riastrad static const struct dev_pagemap_ops nouveau_dmem_pagemap_ops = { 210 1.1 riastrad .page_free = nouveau_dmem_page_free, 211 1.1 riastrad .migrate_to_ram = nouveau_dmem_migrate_to_ram, 212 1.1 riastrad }; 213 1.1 riastrad 214 1.1 riastrad static int 215 1.1 riastrad nouveau_dmem_chunk_alloc(struct nouveau_drm *drm) 216 1.1 riastrad { 217 1.1 riastrad struct nouveau_dmem_chunk *chunk; 218 1.1 riastrad int ret; 219 1.1 riastrad 220 1.1 riastrad if (drm->dmem == NULL) 221 1.1 riastrad return -EINVAL; 222 1.1 riastrad 223 1.1 riastrad mutex_lock(&drm->dmem->mutex); 224 1.1 riastrad chunk = list_first_entry_or_null(&drm->dmem->chunk_empty, 225 1.1 riastrad struct nouveau_dmem_chunk, 226 1.1 riastrad list); 227 1.1 riastrad if (chunk == NULL) { 228 1.1 riastrad mutex_unlock(&drm->dmem->mutex); 229 1.1 riastrad return -ENOMEM; 230 1.1 riastrad } 231 1.1 riastrad 232 1.1 riastrad list_del(&chunk->list); 233 1.1 riastrad mutex_unlock(&drm->dmem->mutex); 234 1.1 riastrad 235 1.1 riastrad ret = nouveau_bo_new(&drm->client, DMEM_CHUNK_SIZE, 0, 236 1.1 riastrad TTM_PL_FLAG_VRAM, 0, 0, NULL, NULL, 237 1.1 riastrad &chunk->bo); 238 1.1 riastrad if (ret) 239 1.1 riastrad goto out; 240 1.1 riastrad 241 1.1 riastrad ret = nouveau_bo_pin(chunk->bo, TTM_PL_FLAG_VRAM, false); 242 1.1 riastrad if (ret) { 243 1.1 riastrad nouveau_bo_ref(NULL, &chunk->bo); 244 1.1 riastrad goto out; 245 1.1 riastrad } 246 1.1 riastrad 247 1.1 riastrad bitmap_zero(chunk->bitmap, DMEM_CHUNK_NPAGES); 248 1.1 riastrad spin_lock_init(&chunk->lock); 249 1.1 riastrad 250 1.1 riastrad out: 251 1.1 riastrad mutex_lock(&drm->dmem->mutex); 252 1.1 riastrad if (chunk->bo) 253 1.1 riastrad list_add(&chunk->list, &drm->dmem->chunk_empty); 254 1.1 riastrad else 255 1.1 riastrad list_add_tail(&chunk->list, &drm->dmem->chunk_empty); 256 1.1 riastrad mutex_unlock(&drm->dmem->mutex); 257 1.1 riastrad 258 1.1 riastrad return ret; 259 1.1 riastrad } 260 1.1 riastrad 261 1.1 riastrad static struct nouveau_dmem_chunk * 262 1.1 riastrad nouveau_dmem_chunk_first_free_locked(struct nouveau_drm *drm) 263 1.1 riastrad { 264 1.1 riastrad struct nouveau_dmem_chunk *chunk; 265 1.1 riastrad 266 1.1 riastrad chunk = list_first_entry_or_null(&drm->dmem->chunk_free, 267 1.1 riastrad struct nouveau_dmem_chunk, 268 1.1 riastrad list); 269 1.1 riastrad if (chunk) 270 1.1 riastrad return chunk; 271 1.1 riastrad 272 1.1 riastrad chunk = list_first_entry_or_null(&drm->dmem->chunk_empty, 273 1.1 riastrad struct nouveau_dmem_chunk, 274 1.1 riastrad list); 275 1.1 riastrad if (chunk->bo) 276 1.1 riastrad return chunk; 277 1.1 riastrad 278 1.1 riastrad return NULL; 279 1.1 riastrad } 280 1.1 riastrad 281 1.1 riastrad static int 282 1.1 riastrad nouveau_dmem_pages_alloc(struct nouveau_drm *drm, 283 1.1 riastrad unsigned long npages, 284 1.1 riastrad unsigned long *pages) 285 1.1 riastrad { 286 1.1 riastrad struct nouveau_dmem_chunk *chunk; 287 1.1 riastrad unsigned long c; 288 1.1 riastrad int ret; 289 1.1 riastrad 290 1.1 riastrad memset(pages, 0xff, npages * sizeof(*pages)); 291 1.1 riastrad 292 1.1 riastrad mutex_lock(&drm->dmem->mutex); 293 1.1 riastrad for (c = 0; c < npages;) { 294 1.1 riastrad unsigned long i; 295 1.1 riastrad 296 1.1 riastrad chunk = nouveau_dmem_chunk_first_free_locked(drm); 297 1.1 riastrad if (chunk == NULL) { 298 1.1 riastrad mutex_unlock(&drm->dmem->mutex); 299 1.1 riastrad ret = nouveau_dmem_chunk_alloc(drm); 300 1.1 riastrad if (ret) { 301 1.1 riastrad if (c) 302 1.1 riastrad return 0; 303 1.1 riastrad return ret; 304 1.1 riastrad } 305 1.1 riastrad mutex_lock(&drm->dmem->mutex); 306 1.1 riastrad continue; 307 1.1 riastrad } 308 1.1 riastrad 309 1.1 riastrad spin_lock(&chunk->lock); 310 1.1 riastrad i = find_first_zero_bit(chunk->bitmap, DMEM_CHUNK_NPAGES); 311 1.1 riastrad while (i < DMEM_CHUNK_NPAGES && c < npages) { 312 1.1 riastrad pages[c] = chunk->pfn_first + i; 313 1.1 riastrad set_bit(i, chunk->bitmap); 314 1.1 riastrad chunk->callocated++; 315 1.1 riastrad c++; 316 1.1 riastrad 317 1.1 riastrad i = find_next_zero_bit(chunk->bitmap, 318 1.1 riastrad DMEM_CHUNK_NPAGES, i); 319 1.1 riastrad } 320 1.1 riastrad spin_unlock(&chunk->lock); 321 1.1 riastrad } 322 1.1 riastrad mutex_unlock(&drm->dmem->mutex); 323 1.1 riastrad 324 1.1 riastrad return 0; 325 1.1 riastrad } 326 1.1 riastrad 327 1.1 riastrad static struct page * 328 1.1 riastrad nouveau_dmem_page_alloc_locked(struct nouveau_drm *drm) 329 1.1 riastrad { 330 1.1 riastrad unsigned long pfns[1]; 331 1.1 riastrad struct page *page; 332 1.1 riastrad int ret; 333 1.1 riastrad 334 1.1 riastrad /* FIXME stop all the miss-match API ... */ 335 1.1 riastrad ret = nouveau_dmem_pages_alloc(drm, 1, pfns); 336 1.1 riastrad if (ret) 337 1.1 riastrad return NULL; 338 1.1 riastrad 339 1.1 riastrad page = pfn_to_page(pfns[0]); 340 1.1 riastrad get_page(page); 341 1.1 riastrad lock_page(page); 342 1.1 riastrad return page; 343 1.1 riastrad } 344 1.1 riastrad 345 1.1 riastrad static void 346 1.1 riastrad nouveau_dmem_page_free_locked(struct nouveau_drm *drm, struct page *page) 347 1.1 riastrad { 348 1.1 riastrad unlock_page(page); 349 1.1 riastrad put_page(page); 350 1.1 riastrad } 351 1.1 riastrad 352 1.1 riastrad void 353 1.1 riastrad nouveau_dmem_resume(struct nouveau_drm *drm) 354 1.1 riastrad { 355 1.1 riastrad struct nouveau_dmem_chunk *chunk; 356 1.1 riastrad int ret; 357 1.1 riastrad 358 1.1 riastrad if (drm->dmem == NULL) 359 1.1 riastrad return; 360 1.1 riastrad 361 1.1 riastrad mutex_lock(&drm->dmem->mutex); 362 1.1 riastrad list_for_each_entry (chunk, &drm->dmem->chunk_free, list) { 363 1.1 riastrad ret = nouveau_bo_pin(chunk->bo, TTM_PL_FLAG_VRAM, false); 364 1.1 riastrad /* FIXME handle pin failure */ 365 1.1 riastrad WARN_ON(ret); 366 1.1 riastrad } 367 1.1 riastrad list_for_each_entry (chunk, &drm->dmem->chunk_full, list) { 368 1.1 riastrad ret = nouveau_bo_pin(chunk->bo, TTM_PL_FLAG_VRAM, false); 369 1.1 riastrad /* FIXME handle pin failure */ 370 1.1 riastrad WARN_ON(ret); 371 1.1 riastrad } 372 1.1 riastrad mutex_unlock(&drm->dmem->mutex); 373 1.1 riastrad } 374 1.1 riastrad 375 1.1 riastrad void 376 1.1 riastrad nouveau_dmem_suspend(struct nouveau_drm *drm) 377 1.1 riastrad { 378 1.1 riastrad struct nouveau_dmem_chunk *chunk; 379 1.1 riastrad 380 1.1 riastrad if (drm->dmem == NULL) 381 1.1 riastrad return; 382 1.1 riastrad 383 1.1 riastrad mutex_lock(&drm->dmem->mutex); 384 1.1 riastrad list_for_each_entry (chunk, &drm->dmem->chunk_free, list) { 385 1.1 riastrad nouveau_bo_unpin(chunk->bo); 386 1.1 riastrad } 387 1.1 riastrad list_for_each_entry (chunk, &drm->dmem->chunk_full, list) { 388 1.1 riastrad nouveau_bo_unpin(chunk->bo); 389 1.1 riastrad } 390 1.1 riastrad mutex_unlock(&drm->dmem->mutex); 391 1.1 riastrad } 392 1.1 riastrad 393 1.1 riastrad void 394 1.1 riastrad nouveau_dmem_fini(struct nouveau_drm *drm) 395 1.1 riastrad { 396 1.1 riastrad struct nouveau_dmem_chunk *chunk, *tmp; 397 1.1 riastrad 398 1.1 riastrad if (drm->dmem == NULL) 399 1.1 riastrad return; 400 1.1 riastrad 401 1.1 riastrad mutex_lock(&drm->dmem->mutex); 402 1.1 riastrad 403 1.1 riastrad WARN_ON(!list_empty(&drm->dmem->chunk_free)); 404 1.1 riastrad WARN_ON(!list_empty(&drm->dmem->chunk_full)); 405 1.1 riastrad 406 1.1 riastrad list_for_each_entry_safe (chunk, tmp, &drm->dmem->chunk_empty, list) { 407 1.1 riastrad if (chunk->bo) { 408 1.1 riastrad nouveau_bo_unpin(chunk->bo); 409 1.1 riastrad nouveau_bo_ref(NULL, &chunk->bo); 410 1.1 riastrad } 411 1.1 riastrad list_del(&chunk->list); 412 1.3 riastrad spin_lock_destroy(&chunk->lock); 413 1.1 riastrad kfree(chunk); 414 1.1 riastrad } 415 1.1 riastrad 416 1.1 riastrad mutex_unlock(&drm->dmem->mutex); 417 1.1 riastrad } 418 1.1 riastrad 419 1.1 riastrad static int 420 1.1 riastrad nvc0b5_migrate_copy(struct nouveau_drm *drm, u64 npages, 421 1.1 riastrad enum nouveau_aper dst_aper, u64 dst_addr, 422 1.1 riastrad enum nouveau_aper src_aper, u64 src_addr) 423 1.1 riastrad { 424 1.1 riastrad struct nouveau_channel *chan = drm->dmem->migrate.chan; 425 1.1 riastrad u32 launch_dma = (1 << 9) /* MULTI_LINE_ENABLE. */ | 426 1.1 riastrad (1 << 8) /* DST_MEMORY_LAYOUT_PITCH. */ | 427 1.1 riastrad (1 << 7) /* SRC_MEMORY_LAYOUT_PITCH. */ | 428 1.1 riastrad (1 << 2) /* FLUSH_ENABLE_TRUE. */ | 429 1.1 riastrad (2 << 0) /* DATA_TRANSFER_TYPE_NON_PIPELINED. */; 430 1.1 riastrad int ret; 431 1.1 riastrad 432 1.1 riastrad ret = RING_SPACE(chan, 13); 433 1.1 riastrad if (ret) 434 1.1 riastrad return ret; 435 1.1 riastrad 436 1.1 riastrad if (src_aper != NOUVEAU_APER_VIRT) { 437 1.1 riastrad switch (src_aper) { 438 1.1 riastrad case NOUVEAU_APER_VRAM: 439 1.1 riastrad BEGIN_IMC0(chan, NvSubCopy, 0x0260, 0); 440 1.1 riastrad break; 441 1.1 riastrad case NOUVEAU_APER_HOST: 442 1.1 riastrad BEGIN_IMC0(chan, NvSubCopy, 0x0260, 1); 443 1.1 riastrad break; 444 1.1 riastrad default: 445 1.1 riastrad return -EINVAL; 446 1.1 riastrad } 447 1.1 riastrad launch_dma |= 0x00001000; /* SRC_TYPE_PHYSICAL. */ 448 1.1 riastrad } 449 1.1 riastrad 450 1.1 riastrad if (dst_aper != NOUVEAU_APER_VIRT) { 451 1.1 riastrad switch (dst_aper) { 452 1.1 riastrad case NOUVEAU_APER_VRAM: 453 1.1 riastrad BEGIN_IMC0(chan, NvSubCopy, 0x0264, 0); 454 1.1 riastrad break; 455 1.1 riastrad case NOUVEAU_APER_HOST: 456 1.1 riastrad BEGIN_IMC0(chan, NvSubCopy, 0x0264, 1); 457 1.1 riastrad break; 458 1.1 riastrad default: 459 1.1 riastrad return -EINVAL; 460 1.1 riastrad } 461 1.1 riastrad launch_dma |= 0x00002000; /* DST_TYPE_PHYSICAL. */ 462 1.1 riastrad } 463 1.1 riastrad 464 1.1 riastrad BEGIN_NVC0(chan, NvSubCopy, 0x0400, 8); 465 1.1 riastrad OUT_RING (chan, upper_32_bits(src_addr)); 466 1.1 riastrad OUT_RING (chan, lower_32_bits(src_addr)); 467 1.1 riastrad OUT_RING (chan, upper_32_bits(dst_addr)); 468 1.1 riastrad OUT_RING (chan, lower_32_bits(dst_addr)); 469 1.1 riastrad OUT_RING (chan, PAGE_SIZE); 470 1.1 riastrad OUT_RING (chan, PAGE_SIZE); 471 1.1 riastrad OUT_RING (chan, PAGE_SIZE); 472 1.1 riastrad OUT_RING (chan, npages); 473 1.1 riastrad BEGIN_NVC0(chan, NvSubCopy, 0x0300, 1); 474 1.1 riastrad OUT_RING (chan, launch_dma); 475 1.1 riastrad return 0; 476 1.1 riastrad } 477 1.1 riastrad 478 1.1 riastrad static int 479 1.1 riastrad nouveau_dmem_migrate_init(struct nouveau_drm *drm) 480 1.1 riastrad { 481 1.1 riastrad switch (drm->ttm.copy.oclass) { 482 1.1 riastrad case PASCAL_DMA_COPY_A: 483 1.1 riastrad case PASCAL_DMA_COPY_B: 484 1.1 riastrad case VOLTA_DMA_COPY_A: 485 1.1 riastrad case TURING_DMA_COPY_A: 486 1.1 riastrad drm->dmem->migrate.copy_func = nvc0b5_migrate_copy; 487 1.1 riastrad drm->dmem->migrate.chan = drm->ttm.chan; 488 1.1 riastrad return 0; 489 1.1 riastrad default: 490 1.1 riastrad break; 491 1.1 riastrad } 492 1.1 riastrad return -ENODEV; 493 1.1 riastrad } 494 1.1 riastrad 495 1.1 riastrad void 496 1.1 riastrad nouveau_dmem_init(struct nouveau_drm *drm) 497 1.1 riastrad { 498 1.1 riastrad struct device *device = drm->dev->dev; 499 1.1 riastrad struct resource *res; 500 1.1 riastrad unsigned long i, size, pfn_first; 501 1.1 riastrad int ret; 502 1.1 riastrad 503 1.1 riastrad /* This only make sense on PASCAL or newer */ 504 1.1 riastrad if (drm->client.device.info.family < NV_DEVICE_INFO_V0_PASCAL) 505 1.1 riastrad return; 506 1.1 riastrad 507 1.1 riastrad if (!(drm->dmem = kzalloc(sizeof(*drm->dmem), GFP_KERNEL))) 508 1.1 riastrad return; 509 1.1 riastrad 510 1.1 riastrad drm->dmem->drm = drm; 511 1.1 riastrad mutex_init(&drm->dmem->mutex); 512 1.1 riastrad INIT_LIST_HEAD(&drm->dmem->chunk_free); 513 1.1 riastrad INIT_LIST_HEAD(&drm->dmem->chunk_full); 514 1.1 riastrad INIT_LIST_HEAD(&drm->dmem->chunk_empty); 515 1.1 riastrad 516 1.1 riastrad size = ALIGN(drm->client.device.info.ram_user, DMEM_CHUNK_SIZE); 517 1.1 riastrad 518 1.1 riastrad /* Initialize migration dma helpers before registering memory */ 519 1.1 riastrad ret = nouveau_dmem_migrate_init(drm); 520 1.1 riastrad if (ret) 521 1.1 riastrad goto out_free; 522 1.1 riastrad 523 1.1 riastrad /* 524 1.1 riastrad * FIXME we need some kind of policy to decide how much VRAM we 525 1.1 riastrad * want to register with HMM. For now just register everything 526 1.1 riastrad * and latter if we want to do thing like over commit then we 527 1.1 riastrad * could revisit this. 528 1.1 riastrad */ 529 1.1 riastrad res = devm_request_free_mem_region(device, &iomem_resource, size); 530 1.1 riastrad if (IS_ERR(res)) 531 1.1 riastrad goto out_free; 532 1.1 riastrad drm->dmem->pagemap.type = MEMORY_DEVICE_PRIVATE; 533 1.1 riastrad drm->dmem->pagemap.res = *res; 534 1.1 riastrad drm->dmem->pagemap.ops = &nouveau_dmem_pagemap_ops; 535 1.1 riastrad if (IS_ERR(devm_memremap_pages(device, &drm->dmem->pagemap))) 536 1.1 riastrad goto out_free; 537 1.1 riastrad 538 1.1 riastrad pfn_first = res->start >> PAGE_SHIFT; 539 1.1 riastrad for (i = 0; i < (size / DMEM_CHUNK_SIZE); ++i) { 540 1.1 riastrad struct nouveau_dmem_chunk *chunk; 541 1.1 riastrad struct page *page; 542 1.1 riastrad unsigned long j; 543 1.1 riastrad 544 1.1 riastrad chunk = kzalloc(sizeof(*chunk), GFP_KERNEL); 545 1.1 riastrad if (chunk == NULL) { 546 1.1 riastrad nouveau_dmem_fini(drm); 547 1.1 riastrad return; 548 1.1 riastrad } 549 1.1 riastrad 550 1.1 riastrad chunk->drm = drm; 551 1.1 riastrad chunk->pfn_first = pfn_first + (i * DMEM_CHUNK_NPAGES); 552 1.1 riastrad list_add_tail(&chunk->list, &drm->dmem->chunk_empty); 553 1.1 riastrad 554 1.1 riastrad page = pfn_to_page(chunk->pfn_first); 555 1.1 riastrad for (j = 0; j < DMEM_CHUNK_NPAGES; ++j, ++page) 556 1.1 riastrad page->zone_device_data = chunk; 557 1.1 riastrad } 558 1.1 riastrad 559 1.1 riastrad NV_INFO(drm, "DMEM: registered %ldMB of device memory\n", size >> 20); 560 1.1 riastrad return; 561 1.1 riastrad out_free: 562 1.3 riastrad mutex_destroy(&drm->dmem->mutex); 563 1.1 riastrad kfree(drm->dmem); 564 1.1 riastrad drm->dmem = NULL; 565 1.1 riastrad } 566 1.1 riastrad 567 1.1 riastrad static unsigned long nouveau_dmem_migrate_copy_one(struct nouveau_drm *drm, 568 1.1 riastrad unsigned long src, dma_addr_t *dma_addr) 569 1.1 riastrad { 570 1.1 riastrad struct device *dev = drm->dev->dev; 571 1.1 riastrad struct page *dpage, *spage; 572 1.1 riastrad 573 1.1 riastrad spage = migrate_pfn_to_page(src); 574 1.1 riastrad if (!spage || !(src & MIGRATE_PFN_MIGRATE)) 575 1.1 riastrad goto out; 576 1.1 riastrad 577 1.1 riastrad dpage = nouveau_dmem_page_alloc_locked(drm); 578 1.1 riastrad if (!dpage) 579 1.1 riastrad return 0; 580 1.1 riastrad 581 1.1 riastrad *dma_addr = dma_map_page(dev, spage, 0, PAGE_SIZE, DMA_BIDIRECTIONAL); 582 1.1 riastrad if (dma_mapping_error(dev, *dma_addr)) 583 1.1 riastrad goto out_free_page; 584 1.1 riastrad 585 1.1 riastrad if (drm->dmem->migrate.copy_func(drm, 1, NOUVEAU_APER_VRAM, 586 1.1 riastrad nouveau_dmem_page_addr(dpage), NOUVEAU_APER_HOST, 587 1.1 riastrad *dma_addr)) 588 1.1 riastrad goto out_dma_unmap; 589 1.1 riastrad 590 1.1 riastrad return migrate_pfn(page_to_pfn(dpage)) | MIGRATE_PFN_LOCKED; 591 1.1 riastrad 592 1.1 riastrad out_dma_unmap: 593 1.1 riastrad dma_unmap_page(dev, *dma_addr, PAGE_SIZE, DMA_BIDIRECTIONAL); 594 1.1 riastrad out_free_page: 595 1.1 riastrad nouveau_dmem_page_free_locked(drm, dpage); 596 1.1 riastrad out: 597 1.1 riastrad return 0; 598 1.1 riastrad } 599 1.1 riastrad 600 1.1 riastrad static void nouveau_dmem_migrate_chunk(struct nouveau_drm *drm, 601 1.1 riastrad struct migrate_vma *args, dma_addr_t *dma_addrs) 602 1.1 riastrad { 603 1.1 riastrad struct nouveau_fence *fence; 604 1.1 riastrad unsigned long addr = args->start, nr_dma = 0, i; 605 1.1 riastrad 606 1.1 riastrad for (i = 0; addr < args->end; i++) { 607 1.1 riastrad args->dst[i] = nouveau_dmem_migrate_copy_one(drm, args->src[i], 608 1.1 riastrad dma_addrs + nr_dma); 609 1.1 riastrad if (args->dst[i]) 610 1.1 riastrad nr_dma++; 611 1.1 riastrad addr += PAGE_SIZE; 612 1.1 riastrad } 613 1.1 riastrad 614 1.1 riastrad nouveau_fence_new(drm->dmem->migrate.chan, false, &fence); 615 1.1 riastrad migrate_vma_pages(args); 616 1.1 riastrad nouveau_dmem_fence_done(&fence); 617 1.1 riastrad 618 1.1 riastrad while (nr_dma--) { 619 1.1 riastrad dma_unmap_page(drm->dev->dev, dma_addrs[nr_dma], PAGE_SIZE, 620 1.1 riastrad DMA_BIDIRECTIONAL); 621 1.1 riastrad } 622 1.1 riastrad /* 623 1.1 riastrad * FIXME optimization: update GPU page table to point to newly migrated 624 1.1 riastrad * memory. 625 1.1 riastrad */ 626 1.1 riastrad migrate_vma_finalize(args); 627 1.1 riastrad } 628 1.1 riastrad 629 1.1 riastrad int 630 1.1 riastrad nouveau_dmem_migrate_vma(struct nouveau_drm *drm, 631 1.1 riastrad struct vm_area_struct *vma, 632 1.1 riastrad unsigned long start, 633 1.1 riastrad unsigned long end) 634 1.1 riastrad { 635 1.1 riastrad unsigned long npages = (end - start) >> PAGE_SHIFT; 636 1.1 riastrad unsigned long max = min(SG_MAX_SINGLE_ALLOC, npages); 637 1.1 riastrad dma_addr_t *dma_addrs; 638 1.1 riastrad struct migrate_vma args = { 639 1.1 riastrad .vma = vma, 640 1.1 riastrad .start = start, 641 1.1 riastrad }; 642 1.1 riastrad unsigned long c, i; 643 1.1 riastrad int ret = -ENOMEM; 644 1.1 riastrad 645 1.1 riastrad args.src = kcalloc(max, sizeof(*args.src), GFP_KERNEL); 646 1.1 riastrad if (!args.src) 647 1.1 riastrad goto out; 648 1.1 riastrad args.dst = kcalloc(max, sizeof(*args.dst), GFP_KERNEL); 649 1.1 riastrad if (!args.dst) 650 1.1 riastrad goto out_free_src; 651 1.1 riastrad 652 1.1 riastrad dma_addrs = kmalloc_array(max, sizeof(*dma_addrs), GFP_KERNEL); 653 1.1 riastrad if (!dma_addrs) 654 1.1 riastrad goto out_free_dst; 655 1.1 riastrad 656 1.1 riastrad for (i = 0; i < npages; i += c) { 657 1.1 riastrad c = min(SG_MAX_SINGLE_ALLOC, npages); 658 1.1 riastrad args.end = start + (c << PAGE_SHIFT); 659 1.1 riastrad ret = migrate_vma_setup(&args); 660 1.1 riastrad if (ret) 661 1.1 riastrad goto out_free_dma; 662 1.1 riastrad 663 1.1 riastrad if (args.cpages) 664 1.1 riastrad nouveau_dmem_migrate_chunk(drm, &args, dma_addrs); 665 1.1 riastrad args.start = args.end; 666 1.1 riastrad } 667 1.1 riastrad 668 1.1 riastrad ret = 0; 669 1.1 riastrad out_free_dma: 670 1.1 riastrad kfree(dma_addrs); 671 1.1 riastrad out_free_dst: 672 1.1 riastrad kfree(args.dst); 673 1.1 riastrad out_free_src: 674 1.1 riastrad kfree(args.src); 675 1.1 riastrad out: 676 1.1 riastrad return ret; 677 1.1 riastrad } 678 1.1 riastrad 679 1.1 riastrad static inline bool 680 1.1 riastrad nouveau_dmem_page(struct nouveau_drm *drm, struct page *page) 681 1.1 riastrad { 682 1.1 riastrad return is_device_private_page(page) && drm->dmem == page_to_dmem(page); 683 1.1 riastrad } 684 1.1 riastrad 685 1.1 riastrad void 686 1.1 riastrad nouveau_dmem_convert_pfn(struct nouveau_drm *drm, 687 1.1 riastrad struct hmm_range *range) 688 1.1 riastrad { 689 1.1 riastrad unsigned long i, npages; 690 1.1 riastrad 691 1.1 riastrad npages = (range->end - range->start) >> PAGE_SHIFT; 692 1.1 riastrad for (i = 0; i < npages; ++i) { 693 1.1 riastrad struct page *page; 694 1.1 riastrad uint64_t addr; 695 1.1 riastrad 696 1.1 riastrad page = hmm_device_entry_to_page(range, range->pfns[i]); 697 1.1 riastrad if (page == NULL) 698 1.1 riastrad continue; 699 1.1 riastrad 700 1.1 riastrad if (!(range->pfns[i] & range->flags[HMM_PFN_DEVICE_PRIVATE])) { 701 1.1 riastrad continue; 702 1.1 riastrad } 703 1.1 riastrad 704 1.1 riastrad if (!nouveau_dmem_page(drm, page)) { 705 1.1 riastrad WARN(1, "Some unknown device memory !\n"); 706 1.1 riastrad range->pfns[i] = 0; 707 1.1 riastrad continue; 708 1.1 riastrad } 709 1.1 riastrad 710 1.1 riastrad addr = nouveau_dmem_page_addr(page); 711 1.1 riastrad range->pfns[i] &= ((1UL << range->pfn_shift) - 1); 712 1.1 riastrad range->pfns[i] |= (addr >> PAGE_SHIFT) << range->pfn_shift; 713 1.1 riastrad } 714 1.1 riastrad } 715