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