Home | History | Annotate | Line # | Download | only in amdgpu
amdgpu_gart.c revision 1.7
      1 /*	$NetBSD: amdgpu_gart.c,v 1.7 2021/12/19 12:21:29 riastradh Exp $	*/
      2 
      3 /*
      4  * Copyright 2008 Advanced Micro Devices, Inc.
      5  * Copyright 2008 Red Hat Inc.
      6  * Copyright 2009 Jerome Glisse.
      7  *
      8  * Permission is hereby granted, free of charge, to any person obtaining a
      9  * copy of this software and associated documentation files (the "Software"),
     10  * to deal in the Software without restriction, including without limitation
     11  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     12  * and/or sell copies of the Software, and to permit persons to whom the
     13  * Software is furnished to do so, subject to the following conditions:
     14  *
     15  * The above copyright notice and this permission notice shall be included in
     16  * all copies or substantial portions of the Software.
     17  *
     18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     21  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
     22  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     23  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     24  * OTHER DEALINGS IN THE SOFTWARE.
     25  *
     26  * Authors: Dave Airlie
     27  *          Alex Deucher
     28  *          Jerome Glisse
     29  */
     30 
     31 #include <sys/cdefs.h>
     32 __KERNEL_RCSID(0, "$NetBSD: amdgpu_gart.c,v 1.7 2021/12/19 12:21:29 riastradh Exp $");
     33 
     34 #include <linux/pci.h>
     35 #include <linux/vmalloc.h>
     36 
     37 #include <drm/amdgpu_drm.h>
     38 #ifdef CONFIG_X86
     39 #include <asm/set_memory.h>
     40 #endif
     41 #include "amdgpu.h"
     42 
     43 /*
     44  * GART
     45  * The GART (Graphics Aperture Remapping Table) is an aperture
     46  * in the GPU's address space.  System pages can be mapped into
     47  * the aperture and look like contiguous pages from the GPU's
     48  * perspective.  A page table maps the pages in the aperture
     49  * to the actual backing pages in system memory.
     50  *
     51  * Radeon GPUs support both an internal GART, as described above,
     52  * and AGP.  AGP works similarly, but the GART table is configured
     53  * and maintained by the northbridge rather than the driver.
     54  * Radeon hw has a separate AGP aperture that is programmed to
     55  * point to the AGP aperture provided by the northbridge and the
     56  * requests are passed through to the northbridge aperture.
     57  * Both AGP and internal GART can be used at the same time, however
     58  * that is not currently supported by the driver.
     59  *
     60  * This file handles the common internal GART management.
     61  */
     62 
     63 /*
     64  * Common GART table functions.
     65  */
     66 
     67 /**
     68  * amdgpu_dummy_page_init - init dummy page used by the driver
     69  *
     70  * @adev: amdgpu_device pointer
     71  *
     72  * Allocate the dummy page used by the driver (all asics).
     73  * This dummy page is used by the driver as a filler for gart entries
     74  * when pages are taken out of the GART
     75  * Returns 0 on sucess, -ENOMEM on failure.
     76  */
     77 static int amdgpu_gart_dummy_page_init(struct amdgpu_device *adev)
     78 {
     79 #ifdef __NetBSD__
     80 	int rsegs;
     81 	int error;
     82 
     83 	/* XXX Can this be called more than once??  */
     84 	if (adev->dummy_page_map != NULL)
     85 		return 0;
     86 
     87 	error = bus_dmamem_alloc(adev->ddev->dmat, PAGE_SIZE, PAGE_SIZE, 0,
     88 	    &adev->dummy_page_seg, 1, &rsegs, BUS_DMA_WAITOK);
     89 	if (error)
     90 		goto fail0;
     91 	KASSERT(rsegs == 1);
     92 	error = bus_dmamap_create(adev->ddev->dmat, PAGE_SIZE, 1, PAGE_SIZE, 0,
     93 	    BUS_DMA_WAITOK, &adev->dummy_page_map);
     94 	if (error)
     95 		goto fail1;
     96 	error = bus_dmamap_load_raw(adev->ddev->dmat, adev->dummy_page_map,
     97 	    &adev->dummy_page_seg, 1, PAGE_SIZE, BUS_DMA_WAITOK);
     98 	if (error)
     99 		goto fail2;
    100 
    101 	/* Success!  */
    102 	adev->dummy_page_addr = adev->dummy_page_map->dm_segs[0].ds_addr;
    103 	return 0;
    104 
    105 fail3: __unused
    106 	bus_dmamap_unload(adev->ddev->dmat, adev->dummy_page_map);
    107 fail2:	bus_dmamap_destroy(adev->ddev->dmat, adev->dummy_page_map);
    108 fail1:	bus_dmamem_free(adev->ddev->dmat, &adev->dummy_page_seg, 1);
    109 fail0:	KASSERT(error);
    110 	adev->dummy_page_map = NULL;
    111 	adev->dummy_page_addr = 0; /* paranoia */
    112 	/* XXX errno NetBSD->Linux */
    113 	return -error;
    114 #else  /* __NetBSD__ */
    115 	struct page *dummy_page = ttm_bo_glob.dummy_read_page;
    116 
    117 	if (adev->dummy_page_addr)
    118 		return 0;
    119 	adev->dummy_page_addr = pci_map_page(adev->pdev, dummy_page, 0,
    120 					     PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
    121 	if (pci_dma_mapping_error(adev->pdev, adev->dummy_page_addr)) {
    122 		dev_err(&adev->pdev->dev, "Failed to DMA MAP the dummy page\n");
    123 		adev->dummy_page_addr = 0;
    124 		return -ENOMEM;
    125 	}
    126 	return 0;
    127 #endif	/* __NetBSD__ */
    128 }
    129 
    130 /**
    131  * amdgpu_dummy_page_fini - free dummy page used by the driver
    132  *
    133  * @adev: amdgpu_device pointer
    134  *
    135  * Frees the dummy page used by the driver (all asics).
    136  */
    137 static void amdgpu_gart_dummy_page_fini(struct amdgpu_device *adev)
    138 {
    139 	if (!adev->dummy_page_addr)
    140 		return;
    141 #ifdef __NetBSD__
    142 	bus_dmamap_unload(adev->ddev->dmat, adev->dummy_page_map);
    143 	bus_dmamap_destroy(adev->ddev->dmat, adev->dummy_page_map);
    144 	bus_dmamem_free(adev->ddev->dmat, &adev->dummy_page_seg, 1);
    145 	adev->dummy_page_map = NULL;
    146 #else
    147 	pci_unmap_page(adev->pdev, adev->dummy_page_addr,
    148 		       PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
    149 #endif
    150 	adev->dummy_page_addr = 0;
    151 }
    152 
    153 /**
    154  * amdgpu_gart_table_vram_alloc - allocate vram for gart page table
    155  *
    156  * @adev: amdgpu_device pointer
    157  *
    158  * Allocate video memory for GART page table
    159  * (pcie r4xx, r5xx+).  These asics require the
    160  * gart table to be in video memory.
    161  * Returns 0 for success, error for failure.
    162  */
    163 int amdgpu_gart_table_vram_alloc(struct amdgpu_device *adev)
    164 {
    165 	int r;
    166 
    167 	if (adev->gart.bo == NULL) {
    168 		struct amdgpu_bo_param bp;
    169 
    170 		memset(&bp, 0, sizeof(bp));
    171 		bp.size = adev->gart.table_size;
    172 		bp.byte_align = PAGE_SIZE;
    173 		bp.domain = AMDGPU_GEM_DOMAIN_VRAM;
    174 		bp.flags = AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED |
    175 			AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS;
    176 		bp.type = ttm_bo_type_kernel;
    177 		bp.resv = NULL;
    178 		r = amdgpu_bo_create(adev, &bp, &adev->gart.bo);
    179 		if (r) {
    180 			return r;
    181 		}
    182 	}
    183 	return 0;
    184 }
    185 
    186 /**
    187  * amdgpu_gart_table_vram_pin - pin gart page table in vram
    188  *
    189  * @adev: amdgpu_device pointer
    190  *
    191  * Pin the GART page table in vram so it will not be moved
    192  * by the memory manager (pcie r4xx, r5xx+).  These asics require the
    193  * gart table to be in video memory.
    194  * Returns 0 for success, error for failure.
    195  */
    196 int amdgpu_gart_table_vram_pin(struct amdgpu_device *adev)
    197 {
    198 	int r;
    199 
    200 	r = amdgpu_bo_reserve(adev->gart.bo, false);
    201 	if (unlikely(r != 0))
    202 		return r;
    203 	r = amdgpu_bo_pin(adev->gart.bo, AMDGPU_GEM_DOMAIN_VRAM);
    204 	if (r) {
    205 		amdgpu_bo_unreserve(adev->gart.bo);
    206 		return r;
    207 	}
    208 	r = amdgpu_bo_kmap(adev->gart.bo, &adev->gart.ptr);
    209 	if (r)
    210 		amdgpu_bo_unpin(adev->gart.bo);
    211 	amdgpu_bo_unreserve(adev->gart.bo);
    212 	return r;
    213 }
    214 
    215 /**
    216  * amdgpu_gart_table_vram_unpin - unpin gart page table in vram
    217  *
    218  * @adev: amdgpu_device pointer
    219  *
    220  * Unpin the GART page table in vram (pcie r4xx, r5xx+).
    221  * These asics require the gart table to be in video memory.
    222  */
    223 void amdgpu_gart_table_vram_unpin(struct amdgpu_device *adev)
    224 {
    225 	int r;
    226 
    227 	if (adev->gart.bo == NULL) {
    228 		return;
    229 	}
    230 	r = amdgpu_bo_reserve(adev->gart.bo, true);
    231 	if (likely(r == 0)) {
    232 		amdgpu_bo_kunmap(adev->gart.bo);
    233 		amdgpu_bo_unpin(adev->gart.bo);
    234 		amdgpu_bo_unreserve(adev->gart.bo);
    235 		adev->gart.ptr = NULL;
    236 	}
    237 }
    238 
    239 /**
    240  * amdgpu_gart_table_vram_free - free gart page table vram
    241  *
    242  * @adev: amdgpu_device pointer
    243  *
    244  * Free the video memory used for the GART page table
    245  * (pcie r4xx, r5xx+).  These asics require the gart table to
    246  * be in video memory.
    247  */
    248 void amdgpu_gart_table_vram_free(struct amdgpu_device *adev)
    249 {
    250 	if (adev->gart.bo == NULL) {
    251 		return;
    252 	}
    253 	amdgpu_bo_unref(&adev->gart.bo);
    254 }
    255 
    256 #ifdef __NetBSD__
    257 static void
    258 amdgpu_gart_pre_update(struct amdgpu_device *adev, unsigned gpu_pgstart,
    259     unsigned gpu_npages)
    260 {
    261 
    262 	if (adev->gart.ag_table_map != NULL) {
    263 		const unsigned entsize =
    264 		    adev->gart.table_size / adev->gart.num_gpu_pages;
    265 
    266 		bus_dmamap_sync(adev->ddev->dmat, adev->gart.ag_table_map,
    267 		    gpu_pgstart*entsize, gpu_npages*entsize,
    268 		    BUS_DMASYNC_POSTWRITE);
    269 	}
    270 }
    271 
    272 static void
    273 amdgpu_gart_post_update(struct amdgpu_device *adev, unsigned gpu_pgstart,
    274     unsigned gpu_npages)
    275 {
    276 	unsigned i;
    277 
    278 	if (adev->gart.ag_table_map != NULL) {
    279 		const unsigned entsize =
    280 		    adev->gart.table_size / adev->gart.num_gpu_pages;
    281 
    282 		bus_dmamap_sync(adev->ddev->dmat, adev->gart.ag_table_map,
    283 		    gpu_pgstart*entsize, gpu_npages*entsize,
    284 		    BUS_DMASYNC_PREWRITE);
    285 	}
    286 	mb();			/* XXX why is bus_dmamap_sync not enough? */
    287 	amdgpu_asic_flush_hdp(adev, NULL);
    288 	for (i = 0; i < adev->num_vmhubs; i++)
    289 		amdgpu_gmc_flush_gpu_tlb(adev, 0, i, 0);
    290 }
    291 #endif
    292 
    293 /*
    294  * Common gart functions.
    295  */
    296 #ifdef __NetBSD__
    297 int
    298 amdgpu_gart_unbind(struct amdgpu_device *adev, uint64_t gpu_start,
    299     unsigned npages)
    300 {
    301 	const unsigned gpu_per_cpu = AMDGPU_GPU_PAGES_IN_CPU_PAGE;
    302 	const unsigned gpu_npages = (npages * gpu_per_cpu);
    303 	const uint64_t gpu_pgstart = (gpu_start / AMDGPU_GPU_PAGE_SIZE);
    304 	const uint64_t pgstart = (gpu_pgstart / gpu_per_cpu);
    305 	uint64_t pgno, gpu_pgno;
    306 	uint32_t flags = AMDGPU_PTE_SYSTEM;
    307 
    308 	KASSERT(pgstart == (gpu_start / PAGE_SIZE));
    309 	KASSERT(npages <= adev->gart.num_cpu_pages);
    310 	KASSERT(gpu_npages <= adev->gart.num_cpu_pages);
    311 
    312 	if (!adev->gart.ready) {
    313 		WARN(1, "trying to bind memory to uninitialized GART !\n");
    314 		return -EINVAL;
    315 	}
    316 
    317 	amdgpu_gart_pre_update(adev, gpu_pgstart, gpu_npages);
    318 	for (pgno = 0; pgno < npages; pgno++) {
    319 #ifdef CONFIG_DRM_AMDGPU_GART_DEBUGFS
    320 		adev->gart.pages[pgstart + pgno] = NULL;
    321 #endif
    322 
    323 		if (adev->gart.ptr == NULL)
    324 			continue;
    325 		for (gpu_pgno = 0; gpu_pgno < gpu_per_cpu; gpu_pgno++) {
    326 			amdgpu_gmc_set_pte_pde(adev, adev->gart.ptr,
    327 			    gpu_pgstart + gpu_per_cpu*pgno + gpu_pgno,
    328 			    adev->dummy_page_addr, flags);
    329 		}
    330 	}
    331 	amdgpu_gart_post_update(adev, gpu_pgstart, gpu_npages);
    332 
    333 	return 0;
    334 }
    335 #else  /* __NetBSD__ */
    336 /**
    337  * amdgpu_gart_unbind - unbind pages from the gart page table
    338  *
    339  * @adev: amdgpu_device pointer
    340  * @offset: offset into the GPU's gart aperture
    341  * @pages: number of pages to unbind
    342  *
    343  * Unbinds the requested pages from the gart page table and
    344  * replaces them with the dummy page (all asics).
    345  * Returns 0 for success, -EINVAL for failure.
    346  */
    347 int amdgpu_gart_unbind(struct amdgpu_device *adev, uint64_t offset,
    348 			int pages)
    349 {
    350 	unsigned t;
    351 	unsigned p;
    352 	int i, j;
    353 	u64 page_base;
    354 	/* Starting from VEGA10, system bit must be 0 to mean invalid. */
    355 	uint64_t flags = 0;
    356 
    357 	if (!adev->gart.ready) {
    358 		WARN(1, "trying to unbind memory from uninitialized GART !\n");
    359 		return -EINVAL;
    360 	}
    361 
    362 	t = offset / AMDGPU_GPU_PAGE_SIZE;
    363 	p = t / AMDGPU_GPU_PAGES_IN_CPU_PAGE;
    364 	for (i = 0; i < pages; i++, p++) {
    365 #ifdef CONFIG_DRM_AMDGPU_GART_DEBUGFS
    366 		adev->gart.pages[p] = NULL;
    367 #endif
    368 		page_base = adev->dummy_page_addr;
    369 		if (!adev->gart.ptr)
    370 			continue;
    371 
    372 		for (j = 0; j < AMDGPU_GPU_PAGES_IN_CPU_PAGE; j++, t++) {
    373 			amdgpu_gmc_set_pte_pde(adev, adev->gart.ptr,
    374 					       t, page_base, flags);
    375 			page_base += AMDGPU_GPU_PAGE_SIZE;
    376 		}
    377 	}
    378 	mb();
    379 	amdgpu_asic_flush_hdp(adev, NULL);
    380 	for (i = 0; i < adev->num_vmhubs; i++)
    381 		amdgpu_gmc_flush_gpu_tlb(adev, 0, i, 0);
    382 
    383 	return 0;
    384 }
    385 #endif	/* __NetBSD__ */
    386 
    387 /**
    388  * amdgpu_gart_map - map dma_addresses into GART entries
    389  *
    390  * @adev: amdgpu_device pointer
    391  * @offset: offset into the GPU's gart aperture
    392  * @pages: number of pages to bind
    393  * @dma_addr: DMA addresses of pages
    394  * @flags: page table entry flags
    395  * @dst: CPU address of the gart table
    396  *
    397  * Map the dma_addresses into GART entries (all asics).
    398  * Returns 0 for success, -EINVAL for failure.
    399  */
    400 #ifdef __NetBSD__
    401 int amdgpu_gart_map(struct amdgpu_device *adev, uint64_t gpu_start,
    402     unsigned npages, bus_size_t map_start, bus_dmamap_t dmamap, uint32_t flags,
    403     void *dst)
    404 {
    405 	bus_size_t seg_off = 0;
    406 	unsigned i, j, t;
    407 
    408 	CTASSERT(AMDGPU_GPU_PAGE_SIZE <= PAGE_SIZE);
    409 	CTASSERT((PAGE_SIZE % AMDGPU_GPU_PAGE_SIZE) == 0);
    410 
    411 	KASSERT((gpu_start & (PAGE_SIZE - 1)) == 0);
    412 
    413 	if (!adev->gart.ready) {
    414 		WARN(1, "trying to bind memory to uninitialized GART !\n");
    415 		return -EINVAL;
    416 	}
    417 
    418 	for (i = 0; i < dmamap->dm_nsegs; i++) {
    419 		KASSERT((dmamap->dm_segs[i].ds_len & (PAGE_SIZE - 1)) == 0);
    420 		if (map_start == 0)
    421 			break;
    422 		if (map_start < dmamap->dm_segs[i].ds_len) {
    423 			seg_off = map_start;
    424 			break;
    425 		}
    426 		map_start -= dmamap->dm_segs[i].ds_len;
    427 	}
    428 	KASSERT(i < dmamap->dm_nsegs);
    429 
    430 	t = gpu_start / AMDGPU_GPU_PAGE_SIZE;
    431 
    432 	for (i = 0; npages --> 0;) {
    433 		KASSERT(i < dmamap->dm_nsegs);
    434 		for (j = 0; j < AMDGPU_GPU_PAGES_IN_CPU_PAGE; j++) {
    435 			amdgpu_gmc_set_pte_pde(adev, dst, t,
    436 			    dmamap->dm_segs[i].ds_addr + seg_off, flags);
    437 			seg_off += AMDGPU_GPU_PAGE_SIZE;
    438 			if (seg_off == dmamap->dm_segs[i].ds_len) {
    439 				i++;
    440 				seg_off = 0;
    441 			}
    442 			KASSERT(seg_off < dmamap->dm_segs[i].ds_len);
    443 		}
    444 	}
    445 
    446 	return 0;
    447 }
    448 #else
    449 int amdgpu_gart_map(struct amdgpu_device *adev, uint64_t offset,
    450 		    int pages, dma_addr_t *dma_addr, uint64_t flags,
    451 		    void *dst)
    452 {
    453 	uint64_t page_base;
    454 	unsigned i, j, t;
    455 
    456 	if (!adev->gart.ready) {
    457 		WARN(1, "trying to bind memory to uninitialized GART !\n");
    458 		return -EINVAL;
    459 	}
    460 
    461 	t = offset / AMDGPU_GPU_PAGE_SIZE;
    462 
    463 	for (i = 0; i < pages; i++) {
    464 		page_base = dma_addr[i];
    465 		for (j = 0; j < AMDGPU_GPU_PAGES_IN_CPU_PAGE; j++, t++) {
    466 			amdgpu_gmc_set_pte_pde(adev, dst, t, page_base, flags);
    467 			page_base += AMDGPU_GPU_PAGE_SIZE;
    468 		}
    469 	}
    470 	return 0;
    471 }
    472 #endif	/* __NetBSD__ */
    473 
    474 #ifdef __NetBSD__
    475 int
    476 amdgpu_gart_bind(struct amdgpu_device *adev, uint64_t gpu_start,
    477     unsigned npages, struct page **pages, bus_dmamap_t dmamap, uint32_t flags)
    478 {
    479 	const unsigned gpu_per_cpu = AMDGPU_GPU_PAGES_IN_CPU_PAGE;
    480 	const unsigned gpu_npages = (npages * gpu_per_cpu);
    481 	const uint64_t gpu_pgstart = (gpu_start / AMDGPU_GPU_PAGE_SIZE);
    482 	const uint64_t pgstart = (gpu_pgstart / gpu_per_cpu);
    483 	uint64_t pgno, gpu_pgno;
    484 
    485 	KASSERT(pgstart == (gpu_start / PAGE_SIZE));
    486 	KASSERT(npages == dmamap->dm_nsegs);
    487 	KASSERT(npages <= adev->gart.num_cpu_pages);
    488 	KASSERT(gpu_npages <= adev->gart.num_cpu_pages);
    489 
    490 	if (!adev->gart.ready) {
    491 		WARN(1, "trying to bind memory to uninitialized GART !\n");
    492 		return -EINVAL;
    493 	}
    494 
    495 	amdgpu_gart_pre_update(adev, gpu_pgstart, gpu_npages);
    496 	for (pgno = 0; pgno < npages; pgno++) {
    497 		const bus_addr_t addr = dmamap->dm_segs[pgno].ds_addr;
    498 
    499 		KASSERT(dmamap->dm_segs[pgno].ds_len == PAGE_SIZE);
    500 #ifdef CONFIG_DRM_AMDGPU_GART_DEBUGFS
    501 		adev->gart.pages[pgstart + pgno] = NULL;
    502 #endif
    503 
    504 		if (adev->gart.ptr == NULL)
    505 			continue;
    506 
    507 		for (gpu_pgno = 0; gpu_pgno < gpu_per_cpu; gpu_pgno++) {
    508 			amdgpu_gmc_set_pte_pde(adev, adev->gart.ptr,
    509 			    gpu_pgstart + gpu_per_cpu*pgno + gpu_pgno,
    510 			    addr + gpu_pgno*AMDGPU_GPU_PAGE_SIZE, flags);
    511 		}
    512 	}
    513 	amdgpu_gart_post_update(adev, gpu_pgstart, gpu_npages);
    514 
    515 	return 0;
    516 }
    517 #else  /* __NetBSD__ */
    518 /**
    519  * amdgpu_gart_bind - bind pages into the gart page table
    520  *
    521  * @adev: amdgpu_device pointer
    522  * @offset: offset into the GPU's gart aperture
    523  * @pages: number of pages to bind
    524  * @pagelist: pages to bind
    525  * @dma_addr: DMA addresses of pages
    526  * @flags: page table entry flags
    527  *
    528  * Binds the requested pages to the gart page table
    529  * (all asics).
    530  * Returns 0 for success, -EINVAL for failure.
    531  */
    532 int amdgpu_gart_bind(struct amdgpu_device *adev, uint64_t offset,
    533 		     int pages, struct page **pagelist, dma_addr_t *dma_addr,
    534 		     uint64_t flags)
    535 {
    536 #ifdef CONFIG_DRM_AMDGPU_GART_DEBUGFS
    537 	unsigned t,p;
    538 #endif
    539 	int r, i;
    540 
    541 	if (!adev->gart.ready) {
    542 		WARN(1, "trying to bind memory to uninitialized GART !\n");
    543 		return -EINVAL;
    544 	}
    545 
    546 #ifdef CONFIG_DRM_AMDGPU_GART_DEBUGFS
    547 	t = offset / AMDGPU_GPU_PAGE_SIZE;
    548 	p = t / AMDGPU_GPU_PAGES_IN_CPU_PAGE;
    549 	for (i = 0; i < pages; i++, p++)
    550 		adev->gart.pages[p] = pagelist ? pagelist[i] : NULL;
    551 #endif
    552 
    553 	if (!adev->gart.ptr)
    554 		return 0;
    555 
    556 	r = amdgpu_gart_map(adev, offset, pages, dma_addr, flags,
    557 		    adev->gart.ptr);
    558 	if (r)
    559 		return r;
    560 
    561 	mb();
    562 	amdgpu_asic_flush_hdp(adev, NULL);
    563 	for (i = 0; i < adev->num_vmhubs; i++)
    564 		amdgpu_gmc_flush_gpu_tlb(adev, 0, i, 0);
    565 	return 0;
    566 }
    567 #endif
    568 
    569 /**
    570  * amdgpu_gart_init - init the driver info for managing the gart
    571  *
    572  * @adev: amdgpu_device pointer
    573  *
    574  * Allocate the dummy page and init the gart driver info (all asics).
    575  * Returns 0 for success, error for failure.
    576  */
    577 int amdgpu_gart_init(struct amdgpu_device *adev)
    578 {
    579 	int r;
    580 
    581 	if (adev->dummy_page_addr)
    582 		return 0;
    583 
    584 	/* We need PAGE_SIZE >= AMDGPU_GPU_PAGE_SIZE */
    585 	if (PAGE_SIZE < AMDGPU_GPU_PAGE_SIZE) {
    586 		DRM_ERROR("Page size is smaller than GPU page size!\n");
    587 		return -EINVAL;
    588 	}
    589 	r = amdgpu_gart_dummy_page_init(adev);
    590 	if (r)
    591 		return r;
    592 	/* Compute table size */
    593 	adev->gart.num_cpu_pages = adev->gmc.gart_size / PAGE_SIZE;
    594 	adev->gart.num_gpu_pages = adev->gmc.gart_size / AMDGPU_GPU_PAGE_SIZE;
    595 	DRM_INFO("GART: num cpu pages %u, num gpu pages %u\n",
    596 		 adev->gart.num_cpu_pages, adev->gart.num_gpu_pages);
    597 
    598 #ifdef CONFIG_DRM_AMDGPU_GART_DEBUGFS
    599 	/* Allocate pages table */
    600 	adev->gart.pages = vzalloc(array_size(sizeof(void *),
    601 					      adev->gart.num_cpu_pages));
    602 	if (adev->gart.pages == NULL)
    603 		return -ENOMEM;
    604 #endif
    605 
    606 	return 0;
    607 }
    608 
    609 /**
    610  * amdgpu_gart_fini - tear down the driver info for managing the gart
    611  *
    612  * @adev: amdgpu_device pointer
    613  *
    614  * Tear down the gart driver info and free the dummy page (all asics).
    615  */
    616 void amdgpu_gart_fini(struct amdgpu_device *adev)
    617 {
    618 #ifdef CONFIG_DRM_AMDGPU_GART_DEBUGFS
    619 	vfree(adev->gart.pages);
    620 	adev->gart.pages = NULL;
    621 #endif
    622 	amdgpu_gart_dummy_page_fini(adev);
    623 }
    624