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