18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright 2008 Advanced Micro Devices, Inc. 38c2ecf20Sopenharmony_ci * Copyright 2008 Red Hat Inc. 48c2ecf20Sopenharmony_ci * Copyright 2009 Jerome Glisse. 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 78c2ecf20Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 88c2ecf20Sopenharmony_ci * to deal in the Software without restriction, including without limitation 98c2ecf20Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 108c2ecf20Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 118c2ecf20Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 128c2ecf20Sopenharmony_ci * 138c2ecf20Sopenharmony_ci * The above copyright notice and this permission notice shall be included in 148c2ecf20Sopenharmony_ci * all copies or substantial portions of the Software. 158c2ecf20Sopenharmony_ci * 168c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 178c2ecf20Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 188c2ecf20Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 198c2ecf20Sopenharmony_ci * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 208c2ecf20Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 218c2ecf20Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 228c2ecf20Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE. 238c2ecf20Sopenharmony_ci * 248c2ecf20Sopenharmony_ci * Authors: Dave Airlie 258c2ecf20Sopenharmony_ci * Alex Deucher 268c2ecf20Sopenharmony_ci * Jerome Glisse 278c2ecf20Sopenharmony_ci */ 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#include <linux/pci.h> 308c2ecf20Sopenharmony_ci#include <linux/vmalloc.h> 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci#include <drm/radeon_drm.h> 338c2ecf20Sopenharmony_ci#ifdef CONFIG_X86 348c2ecf20Sopenharmony_ci#include <asm/set_memory.h> 358c2ecf20Sopenharmony_ci#endif 368c2ecf20Sopenharmony_ci#include "radeon.h" 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci/* 398c2ecf20Sopenharmony_ci * GART 408c2ecf20Sopenharmony_ci * The GART (Graphics Aperture Remapping Table) is an aperture 418c2ecf20Sopenharmony_ci * in the GPU's address space. System pages can be mapped into 428c2ecf20Sopenharmony_ci * the aperture and look like contiguous pages from the GPU's 438c2ecf20Sopenharmony_ci * perspective. A page table maps the pages in the aperture 448c2ecf20Sopenharmony_ci * to the actual backing pages in system memory. 458c2ecf20Sopenharmony_ci * 468c2ecf20Sopenharmony_ci * Radeon GPUs support both an internal GART, as described above, 478c2ecf20Sopenharmony_ci * and AGP. AGP works similarly, but the GART table is configured 488c2ecf20Sopenharmony_ci * and maintained by the northbridge rather than the driver. 498c2ecf20Sopenharmony_ci * Radeon hw has a separate AGP aperture that is programmed to 508c2ecf20Sopenharmony_ci * point to the AGP aperture provided by the northbridge and the 518c2ecf20Sopenharmony_ci * requests are passed through to the northbridge aperture. 528c2ecf20Sopenharmony_ci * Both AGP and internal GART can be used at the same time, however 538c2ecf20Sopenharmony_ci * that is not currently supported by the driver. 548c2ecf20Sopenharmony_ci * 558c2ecf20Sopenharmony_ci * This file handles the common internal GART management. 568c2ecf20Sopenharmony_ci */ 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci/* 598c2ecf20Sopenharmony_ci * Common GART table functions. 608c2ecf20Sopenharmony_ci */ 618c2ecf20Sopenharmony_ci/** 628c2ecf20Sopenharmony_ci * radeon_gart_table_ram_alloc - allocate system ram for gart page table 638c2ecf20Sopenharmony_ci * 648c2ecf20Sopenharmony_ci * @rdev: radeon_device pointer 658c2ecf20Sopenharmony_ci * 668c2ecf20Sopenharmony_ci * Allocate system memory for GART page table 678c2ecf20Sopenharmony_ci * (r1xx-r3xx, non-pcie r4xx, rs400). These asics require the 688c2ecf20Sopenharmony_ci * gart table to be in system memory. 698c2ecf20Sopenharmony_ci * Returns 0 for success, -ENOMEM for failure. 708c2ecf20Sopenharmony_ci */ 718c2ecf20Sopenharmony_ciint radeon_gart_table_ram_alloc(struct radeon_device *rdev) 728c2ecf20Sopenharmony_ci{ 738c2ecf20Sopenharmony_ci void *ptr; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci ptr = dma_alloc_coherent(&rdev->pdev->dev, rdev->gart.table_size, 768c2ecf20Sopenharmony_ci &rdev->gart.table_addr, GFP_KERNEL); 778c2ecf20Sopenharmony_ci if (ptr == NULL) { 788c2ecf20Sopenharmony_ci return -ENOMEM; 798c2ecf20Sopenharmony_ci } 808c2ecf20Sopenharmony_ci#ifdef CONFIG_X86 818c2ecf20Sopenharmony_ci if (rdev->family == CHIP_RS400 || rdev->family == CHIP_RS480 || 828c2ecf20Sopenharmony_ci rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) { 838c2ecf20Sopenharmony_ci set_memory_uc((unsigned long)ptr, 848c2ecf20Sopenharmony_ci rdev->gart.table_size >> PAGE_SHIFT); 858c2ecf20Sopenharmony_ci } 868c2ecf20Sopenharmony_ci#endif 878c2ecf20Sopenharmony_ci rdev->gart.ptr = ptr; 888c2ecf20Sopenharmony_ci return 0; 898c2ecf20Sopenharmony_ci} 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci/** 928c2ecf20Sopenharmony_ci * radeon_gart_table_ram_free - free system ram for gart page table 938c2ecf20Sopenharmony_ci * 948c2ecf20Sopenharmony_ci * @rdev: radeon_device pointer 958c2ecf20Sopenharmony_ci * 968c2ecf20Sopenharmony_ci * Free system memory for GART page table 978c2ecf20Sopenharmony_ci * (r1xx-r3xx, non-pcie r4xx, rs400). These asics require the 988c2ecf20Sopenharmony_ci * gart table to be in system memory. 998c2ecf20Sopenharmony_ci */ 1008c2ecf20Sopenharmony_civoid radeon_gart_table_ram_free(struct radeon_device *rdev) 1018c2ecf20Sopenharmony_ci{ 1028c2ecf20Sopenharmony_ci if (rdev->gart.ptr == NULL) { 1038c2ecf20Sopenharmony_ci return; 1048c2ecf20Sopenharmony_ci } 1058c2ecf20Sopenharmony_ci#ifdef CONFIG_X86 1068c2ecf20Sopenharmony_ci if (rdev->family == CHIP_RS400 || rdev->family == CHIP_RS480 || 1078c2ecf20Sopenharmony_ci rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) { 1088c2ecf20Sopenharmony_ci set_memory_wb((unsigned long)rdev->gart.ptr, 1098c2ecf20Sopenharmony_ci rdev->gart.table_size >> PAGE_SHIFT); 1108c2ecf20Sopenharmony_ci } 1118c2ecf20Sopenharmony_ci#endif 1128c2ecf20Sopenharmony_ci dma_free_coherent(&rdev->pdev->dev, rdev->gart.table_size, 1138c2ecf20Sopenharmony_ci (void *)rdev->gart.ptr, rdev->gart.table_addr); 1148c2ecf20Sopenharmony_ci rdev->gart.ptr = NULL; 1158c2ecf20Sopenharmony_ci rdev->gart.table_addr = 0; 1168c2ecf20Sopenharmony_ci} 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci/** 1198c2ecf20Sopenharmony_ci * radeon_gart_table_vram_alloc - allocate vram for gart page table 1208c2ecf20Sopenharmony_ci * 1218c2ecf20Sopenharmony_ci * @rdev: radeon_device pointer 1228c2ecf20Sopenharmony_ci * 1238c2ecf20Sopenharmony_ci * Allocate video memory for GART page table 1248c2ecf20Sopenharmony_ci * (pcie r4xx, r5xx+). These asics require the 1258c2ecf20Sopenharmony_ci * gart table to be in video memory. 1268c2ecf20Sopenharmony_ci * Returns 0 for success, error for failure. 1278c2ecf20Sopenharmony_ci */ 1288c2ecf20Sopenharmony_ciint radeon_gart_table_vram_alloc(struct radeon_device *rdev) 1298c2ecf20Sopenharmony_ci{ 1308c2ecf20Sopenharmony_ci int r; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci if (rdev->gart.robj == NULL) { 1338c2ecf20Sopenharmony_ci r = radeon_bo_create(rdev, rdev->gart.table_size, 1348c2ecf20Sopenharmony_ci PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM, 1358c2ecf20Sopenharmony_ci 0, NULL, NULL, &rdev->gart.robj); 1368c2ecf20Sopenharmony_ci if (r) { 1378c2ecf20Sopenharmony_ci return r; 1388c2ecf20Sopenharmony_ci } 1398c2ecf20Sopenharmony_ci } 1408c2ecf20Sopenharmony_ci return 0; 1418c2ecf20Sopenharmony_ci} 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci/** 1448c2ecf20Sopenharmony_ci * radeon_gart_table_vram_pin - pin gart page table in vram 1458c2ecf20Sopenharmony_ci * 1468c2ecf20Sopenharmony_ci * @rdev: radeon_device pointer 1478c2ecf20Sopenharmony_ci * 1488c2ecf20Sopenharmony_ci * Pin the GART page table in vram so it will not be moved 1498c2ecf20Sopenharmony_ci * by the memory manager (pcie r4xx, r5xx+). These asics require the 1508c2ecf20Sopenharmony_ci * gart table to be in video memory. 1518c2ecf20Sopenharmony_ci * Returns 0 for success, error for failure. 1528c2ecf20Sopenharmony_ci */ 1538c2ecf20Sopenharmony_ciint radeon_gart_table_vram_pin(struct radeon_device *rdev) 1548c2ecf20Sopenharmony_ci{ 1558c2ecf20Sopenharmony_ci uint64_t gpu_addr; 1568c2ecf20Sopenharmony_ci int r; 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci r = radeon_bo_reserve(rdev->gart.robj, false); 1598c2ecf20Sopenharmony_ci if (unlikely(r != 0)) 1608c2ecf20Sopenharmony_ci return r; 1618c2ecf20Sopenharmony_ci r = radeon_bo_pin(rdev->gart.robj, 1628c2ecf20Sopenharmony_ci RADEON_GEM_DOMAIN_VRAM, &gpu_addr); 1638c2ecf20Sopenharmony_ci if (r) { 1648c2ecf20Sopenharmony_ci radeon_bo_unreserve(rdev->gart.robj); 1658c2ecf20Sopenharmony_ci return r; 1668c2ecf20Sopenharmony_ci } 1678c2ecf20Sopenharmony_ci r = radeon_bo_kmap(rdev->gart.robj, &rdev->gart.ptr); 1688c2ecf20Sopenharmony_ci if (r) 1698c2ecf20Sopenharmony_ci radeon_bo_unpin(rdev->gart.robj); 1708c2ecf20Sopenharmony_ci radeon_bo_unreserve(rdev->gart.robj); 1718c2ecf20Sopenharmony_ci rdev->gart.table_addr = gpu_addr; 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci if (!r) { 1748c2ecf20Sopenharmony_ci int i; 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci /* We might have dropped some GART table updates while it wasn't 1778c2ecf20Sopenharmony_ci * mapped, restore all entries 1788c2ecf20Sopenharmony_ci */ 1798c2ecf20Sopenharmony_ci for (i = 0; i < rdev->gart.num_gpu_pages; i++) 1808c2ecf20Sopenharmony_ci radeon_gart_set_page(rdev, i, rdev->gart.pages_entry[i]); 1818c2ecf20Sopenharmony_ci mb(); 1828c2ecf20Sopenharmony_ci radeon_gart_tlb_flush(rdev); 1838c2ecf20Sopenharmony_ci } 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci return r; 1868c2ecf20Sopenharmony_ci} 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci/** 1898c2ecf20Sopenharmony_ci * radeon_gart_table_vram_unpin - unpin gart page table in vram 1908c2ecf20Sopenharmony_ci * 1918c2ecf20Sopenharmony_ci * @rdev: radeon_device pointer 1928c2ecf20Sopenharmony_ci * 1938c2ecf20Sopenharmony_ci * Unpin the GART page table in vram (pcie r4xx, r5xx+). 1948c2ecf20Sopenharmony_ci * These asics require the gart table to be in video memory. 1958c2ecf20Sopenharmony_ci */ 1968c2ecf20Sopenharmony_civoid radeon_gart_table_vram_unpin(struct radeon_device *rdev) 1978c2ecf20Sopenharmony_ci{ 1988c2ecf20Sopenharmony_ci int r; 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci if (rdev->gart.robj == NULL) { 2018c2ecf20Sopenharmony_ci return; 2028c2ecf20Sopenharmony_ci } 2038c2ecf20Sopenharmony_ci r = radeon_bo_reserve(rdev->gart.robj, false); 2048c2ecf20Sopenharmony_ci if (likely(r == 0)) { 2058c2ecf20Sopenharmony_ci radeon_bo_kunmap(rdev->gart.robj); 2068c2ecf20Sopenharmony_ci radeon_bo_unpin(rdev->gart.robj); 2078c2ecf20Sopenharmony_ci radeon_bo_unreserve(rdev->gart.robj); 2088c2ecf20Sopenharmony_ci rdev->gart.ptr = NULL; 2098c2ecf20Sopenharmony_ci } 2108c2ecf20Sopenharmony_ci} 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci/** 2138c2ecf20Sopenharmony_ci * radeon_gart_table_vram_free - free gart page table vram 2148c2ecf20Sopenharmony_ci * 2158c2ecf20Sopenharmony_ci * @rdev: radeon_device pointer 2168c2ecf20Sopenharmony_ci * 2178c2ecf20Sopenharmony_ci * Free the video memory used for the GART page table 2188c2ecf20Sopenharmony_ci * (pcie r4xx, r5xx+). These asics require the gart table to 2198c2ecf20Sopenharmony_ci * be in video memory. 2208c2ecf20Sopenharmony_ci */ 2218c2ecf20Sopenharmony_civoid radeon_gart_table_vram_free(struct radeon_device *rdev) 2228c2ecf20Sopenharmony_ci{ 2238c2ecf20Sopenharmony_ci if (rdev->gart.robj == NULL) { 2248c2ecf20Sopenharmony_ci return; 2258c2ecf20Sopenharmony_ci } 2268c2ecf20Sopenharmony_ci radeon_bo_unref(&rdev->gart.robj); 2278c2ecf20Sopenharmony_ci} 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci/* 2308c2ecf20Sopenharmony_ci * Common gart functions. 2318c2ecf20Sopenharmony_ci */ 2328c2ecf20Sopenharmony_ci/** 2338c2ecf20Sopenharmony_ci * radeon_gart_unbind - unbind pages from the gart page table 2348c2ecf20Sopenharmony_ci * 2358c2ecf20Sopenharmony_ci * @rdev: radeon_device pointer 2368c2ecf20Sopenharmony_ci * @offset: offset into the GPU's gart aperture 2378c2ecf20Sopenharmony_ci * @pages: number of pages to unbind 2388c2ecf20Sopenharmony_ci * 2398c2ecf20Sopenharmony_ci * Unbinds the requested pages from the gart page table and 2408c2ecf20Sopenharmony_ci * replaces them with the dummy page (all asics). 2418c2ecf20Sopenharmony_ci */ 2428c2ecf20Sopenharmony_civoid radeon_gart_unbind(struct radeon_device *rdev, unsigned offset, 2438c2ecf20Sopenharmony_ci int pages) 2448c2ecf20Sopenharmony_ci{ 2458c2ecf20Sopenharmony_ci unsigned t; 2468c2ecf20Sopenharmony_ci unsigned p; 2478c2ecf20Sopenharmony_ci int i, j; 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci if (!rdev->gart.ready) { 2508c2ecf20Sopenharmony_ci WARN(1, "trying to unbind memory from uninitialized GART !\n"); 2518c2ecf20Sopenharmony_ci return; 2528c2ecf20Sopenharmony_ci } 2538c2ecf20Sopenharmony_ci t = offset / RADEON_GPU_PAGE_SIZE; 2548c2ecf20Sopenharmony_ci p = t / (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); 2558c2ecf20Sopenharmony_ci for (i = 0; i < pages; i++, p++) { 2568c2ecf20Sopenharmony_ci if (rdev->gart.pages[p]) { 2578c2ecf20Sopenharmony_ci rdev->gart.pages[p] = NULL; 2588c2ecf20Sopenharmony_ci for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) { 2598c2ecf20Sopenharmony_ci rdev->gart.pages_entry[t] = rdev->dummy_page.entry; 2608c2ecf20Sopenharmony_ci if (rdev->gart.ptr) { 2618c2ecf20Sopenharmony_ci radeon_gart_set_page(rdev, t, 2628c2ecf20Sopenharmony_ci rdev->dummy_page.entry); 2638c2ecf20Sopenharmony_ci } 2648c2ecf20Sopenharmony_ci } 2658c2ecf20Sopenharmony_ci } 2668c2ecf20Sopenharmony_ci } 2678c2ecf20Sopenharmony_ci if (rdev->gart.ptr) { 2688c2ecf20Sopenharmony_ci mb(); 2698c2ecf20Sopenharmony_ci radeon_gart_tlb_flush(rdev); 2708c2ecf20Sopenharmony_ci } 2718c2ecf20Sopenharmony_ci} 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci/** 2748c2ecf20Sopenharmony_ci * radeon_gart_bind - bind pages into the gart page table 2758c2ecf20Sopenharmony_ci * 2768c2ecf20Sopenharmony_ci * @rdev: radeon_device pointer 2778c2ecf20Sopenharmony_ci * @offset: offset into the GPU's gart aperture 2788c2ecf20Sopenharmony_ci * @pages: number of pages to bind 2798c2ecf20Sopenharmony_ci * @pagelist: pages to bind 2808c2ecf20Sopenharmony_ci * @dma_addr: DMA addresses of pages 2818c2ecf20Sopenharmony_ci * @flags: RADEON_GART_PAGE_* flags 2828c2ecf20Sopenharmony_ci * 2838c2ecf20Sopenharmony_ci * Binds the requested pages to the gart page table 2848c2ecf20Sopenharmony_ci * (all asics). 2858c2ecf20Sopenharmony_ci * Returns 0 for success, -EINVAL for failure. 2868c2ecf20Sopenharmony_ci */ 2878c2ecf20Sopenharmony_ciint radeon_gart_bind(struct radeon_device *rdev, unsigned offset, 2888c2ecf20Sopenharmony_ci int pages, struct page **pagelist, dma_addr_t *dma_addr, 2898c2ecf20Sopenharmony_ci uint32_t flags) 2908c2ecf20Sopenharmony_ci{ 2918c2ecf20Sopenharmony_ci unsigned t; 2928c2ecf20Sopenharmony_ci unsigned p; 2938c2ecf20Sopenharmony_ci uint64_t page_base, page_entry; 2948c2ecf20Sopenharmony_ci int i, j; 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci if (!rdev->gart.ready) { 2978c2ecf20Sopenharmony_ci WARN(1, "trying to bind memory to uninitialized GART !\n"); 2988c2ecf20Sopenharmony_ci return -EINVAL; 2998c2ecf20Sopenharmony_ci } 3008c2ecf20Sopenharmony_ci t = offset / RADEON_GPU_PAGE_SIZE; 3018c2ecf20Sopenharmony_ci p = t / (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci for (i = 0; i < pages; i++, p++) { 3048c2ecf20Sopenharmony_ci rdev->gart.pages[p] = pagelist[i]; 3058c2ecf20Sopenharmony_ci page_base = dma_addr[i]; 3068c2ecf20Sopenharmony_ci for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) { 3078c2ecf20Sopenharmony_ci page_entry = radeon_gart_get_page_entry(page_base, flags); 3088c2ecf20Sopenharmony_ci rdev->gart.pages_entry[t] = page_entry; 3098c2ecf20Sopenharmony_ci if (rdev->gart.ptr) { 3108c2ecf20Sopenharmony_ci radeon_gart_set_page(rdev, t, page_entry); 3118c2ecf20Sopenharmony_ci } 3128c2ecf20Sopenharmony_ci page_base += RADEON_GPU_PAGE_SIZE; 3138c2ecf20Sopenharmony_ci } 3148c2ecf20Sopenharmony_ci } 3158c2ecf20Sopenharmony_ci if (rdev->gart.ptr) { 3168c2ecf20Sopenharmony_ci mb(); 3178c2ecf20Sopenharmony_ci radeon_gart_tlb_flush(rdev); 3188c2ecf20Sopenharmony_ci } 3198c2ecf20Sopenharmony_ci return 0; 3208c2ecf20Sopenharmony_ci} 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci/** 3238c2ecf20Sopenharmony_ci * radeon_gart_init - init the driver info for managing the gart 3248c2ecf20Sopenharmony_ci * 3258c2ecf20Sopenharmony_ci * @rdev: radeon_device pointer 3268c2ecf20Sopenharmony_ci * 3278c2ecf20Sopenharmony_ci * Allocate the dummy page and init the gart driver info (all asics). 3288c2ecf20Sopenharmony_ci * Returns 0 for success, error for failure. 3298c2ecf20Sopenharmony_ci */ 3308c2ecf20Sopenharmony_ciint radeon_gart_init(struct radeon_device *rdev) 3318c2ecf20Sopenharmony_ci{ 3328c2ecf20Sopenharmony_ci int r, i; 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci if (rdev->gart.pages) { 3358c2ecf20Sopenharmony_ci return 0; 3368c2ecf20Sopenharmony_ci } 3378c2ecf20Sopenharmony_ci /* We need PAGE_SIZE >= RADEON_GPU_PAGE_SIZE */ 3388c2ecf20Sopenharmony_ci if (PAGE_SIZE < RADEON_GPU_PAGE_SIZE) { 3398c2ecf20Sopenharmony_ci DRM_ERROR("Page size is smaller than GPU page size!\n"); 3408c2ecf20Sopenharmony_ci return -EINVAL; 3418c2ecf20Sopenharmony_ci } 3428c2ecf20Sopenharmony_ci r = radeon_dummy_page_init(rdev); 3438c2ecf20Sopenharmony_ci if (r) 3448c2ecf20Sopenharmony_ci return r; 3458c2ecf20Sopenharmony_ci /* Compute table size */ 3468c2ecf20Sopenharmony_ci rdev->gart.num_cpu_pages = rdev->mc.gtt_size / PAGE_SIZE; 3478c2ecf20Sopenharmony_ci rdev->gart.num_gpu_pages = rdev->mc.gtt_size / RADEON_GPU_PAGE_SIZE; 3488c2ecf20Sopenharmony_ci DRM_INFO("GART: num cpu pages %u, num gpu pages %u\n", 3498c2ecf20Sopenharmony_ci rdev->gart.num_cpu_pages, rdev->gart.num_gpu_pages); 3508c2ecf20Sopenharmony_ci /* Allocate pages table */ 3518c2ecf20Sopenharmony_ci rdev->gart.pages = vzalloc(array_size(sizeof(void *), 3528c2ecf20Sopenharmony_ci rdev->gart.num_cpu_pages)); 3538c2ecf20Sopenharmony_ci if (rdev->gart.pages == NULL) { 3548c2ecf20Sopenharmony_ci radeon_gart_fini(rdev); 3558c2ecf20Sopenharmony_ci return -ENOMEM; 3568c2ecf20Sopenharmony_ci } 3578c2ecf20Sopenharmony_ci rdev->gart.pages_entry = vmalloc(array_size(sizeof(uint64_t), 3588c2ecf20Sopenharmony_ci rdev->gart.num_gpu_pages)); 3598c2ecf20Sopenharmony_ci if (rdev->gart.pages_entry == NULL) { 3608c2ecf20Sopenharmony_ci radeon_gart_fini(rdev); 3618c2ecf20Sopenharmony_ci return -ENOMEM; 3628c2ecf20Sopenharmony_ci } 3638c2ecf20Sopenharmony_ci /* set GART entry to point to the dummy page by default */ 3648c2ecf20Sopenharmony_ci for (i = 0; i < rdev->gart.num_gpu_pages; i++) 3658c2ecf20Sopenharmony_ci rdev->gart.pages_entry[i] = rdev->dummy_page.entry; 3668c2ecf20Sopenharmony_ci return 0; 3678c2ecf20Sopenharmony_ci} 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci/** 3708c2ecf20Sopenharmony_ci * radeon_gart_fini - tear down the driver info for managing the gart 3718c2ecf20Sopenharmony_ci * 3728c2ecf20Sopenharmony_ci * @rdev: radeon_device pointer 3738c2ecf20Sopenharmony_ci * 3748c2ecf20Sopenharmony_ci * Tear down the gart driver info and free the dummy page (all asics). 3758c2ecf20Sopenharmony_ci */ 3768c2ecf20Sopenharmony_civoid radeon_gart_fini(struct radeon_device *rdev) 3778c2ecf20Sopenharmony_ci{ 3788c2ecf20Sopenharmony_ci if (rdev->gart.ready) { 3798c2ecf20Sopenharmony_ci /* unbind pages */ 3808c2ecf20Sopenharmony_ci radeon_gart_unbind(rdev, 0, rdev->gart.num_cpu_pages); 3818c2ecf20Sopenharmony_ci } 3828c2ecf20Sopenharmony_ci rdev->gart.ready = false; 3838c2ecf20Sopenharmony_ci vfree(rdev->gart.pages); 3848c2ecf20Sopenharmony_ci vfree(rdev->gart.pages_entry); 3858c2ecf20Sopenharmony_ci rdev->gart.pages = NULL; 3868c2ecf20Sopenharmony_ci rdev->gart.pages_entry = NULL; 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_ci radeon_dummy_page_fini(rdev); 3898c2ecf20Sopenharmony_ci} 390