| 1 | |
| 2 | * Copyright 2008 Advanced Micro Devices, Inc.
|
| 3 | * Copyright 2008 Red Hat Inc.
|
| 4 | * Copyright 2009 Jerome Glisse.
|
| 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 | * Authors: Dave Airlie
|
| 25 | * Alex Deucher
|
| 26 | * Jerome Glisse
|
| 27 |
|
| 28 |
|
| 29 | #include <linux/pci.h>
|
| 30 | #include <linux/vmalloc.h>
|
| 31 |
|
| 32 | #include <drm/amdgpu_drm.h>
|
| 33 | #ifdef CONFIG_X86
|
| 34 | #include <asm/set_memory.h>
|
| 35 | #endif
|
| 36 | #include "amdgpu.h"
|
| 37 | #include "amdgpu_reset.h"
|
| 38 | #include <drm/drm_drv.h>
|
| 39 | #include <drm/ttm/ttm_tt.h>
|
| 40 |
|
| 41 | |
| 42 | * GART
|
| 43 | * The GART (Graphics Aperture Remapping Table) is an aperture
|
| 44 | * in the GPU's address space. System pages can be mapped into
|
| 45 | * the aperture and look like contiguous pages from the GPU's
|
| 46 | * perspective. A page table maps the pages in the aperture
|
| 47 | * to the actual backing pages in system memory.
|
| 48 | *
|
| 49 | * Radeon GPUs support both an internal GART, as described above,
|
| 50 | * and AGP. AGP works similarly, but the GART table is configured
|
| 51 | * and maintained by the northbridge rather than the driver.
|
| 52 | * Radeon hw has a separate AGP aperture that is programmed to
|
| 53 | * point to the AGP aperture provided by the northbridge and the
|
| 54 | * requests are passed through to the northbridge aperture.
|
| 55 | * Both AGP and internal GART can be used at the same time, however
|
| 56 | * that is not currently supported by the driver.
|
| 57 | *
|
| 58 | * This file handles the common internal GART management.
|
| 59 |
|
| 60 |
|
| 61 | |
| 62 | * Common GART table functions.
|
| 63 |
|
| 64 |
|
| 65 | |
| 66 | * amdgpu_gart_dummy_page_init - init dummy page used by the driver
|
| 67 | *
|
| 68 | * @adev: amdgpu_device pointer
|
| 69 | *
|
| 70 | * Allocate the dummy page used by the driver (all asics).
|
| 71 | * This dummy page is used by the driver as a filler for gart entries
|
| 72 | * when pages are taken out of the GART
|
| 73 | * Returns 0 on sucess, -ENOMEM on failure.
|
| 74 |
|
| 75 | static int amdgpu_gart_dummy_page_init(struct amdgpu_device *adev)
|
| 76 | {
|
| 77 | struct page *dummy_page = ttm_glob.dummy_read_page;
|
| 78 |
|
| 79 | if (adev->dummy_page_addr)
|
| 80 | return 0;
|
| 81 | adev->dummy_page_addr = dma_map_page_attrs(&adev->pdev->dev, dummy_page, 0,
|
| 82 | PAGE_SIZE, DMA_BIDIRECTIONAL,
|
| 83 | DMA_ATTR_SKIP_CPU_SYNC);
|
| 84 | if (dma_mapping_error(&adev->pdev->dev, adev->dummy_page_addr)) {
|
| 85 | dev_err(&adev->pdev->dev, "Failed to DMA MAP the dummy page\n");
|
| 86 | adev->dummy_page_addr = 0;
|
| 87 | return -ENOMEM;
|
| 88 | }
|
| 89 | return 0;
|
| 90 | }
|
| 91 |
|
| 92 | |
| 93 | * amdgpu_gart_dummy_page_fini - free dummy page used by the driver
|
| 94 | *
|
| 95 | * @adev: amdgpu_device pointer
|
| 96 | *
|
| 97 | * Frees the dummy page used by the driver (all asics).
|
| 98 |
|
| 99 | void amdgpu_gart_dummy_page_fini(struct amdgpu_device *adev)
|
| 100 | {
|
| 101 | if (!adev->dummy_page_addr)
|
| 102 | return;
|
| 103 | dma_unmap_page_attrs(&adev->pdev->dev, adev->dummy_page_addr, PAGE_SIZE,
|
| 104 | DMA_BIDIRECTIONAL,
|
| 105 | DMA_ATTR_SKIP_CPU_SYNC);
|
| 106 | adev->dummy_page_addr = 0;
|
| 107 | }
|
| 108 |
|
| 109 | |
| 110 | * amdgpu_gart_table_ram_alloc - allocate system ram for gart page table
|
| 111 | *
|
| 112 | * @adev: amdgpu_device pointer
|
| 113 | *
|
| 114 | * Allocate system memory for GART page table for ASICs that don't have
|
| 115 | * dedicated VRAM.
|
| 116 | * Returns 0 for success, error for failure.
|
| 117 |
|
| 118 | int amdgpu_gart_table_ram_alloc(struct amdgpu_device *adev)
|
| 119 | {
|
| 120 | unsigned int order = get_order(adev->gart.table_size);
|
| 121 | gfp_t gfp_flags = GFP_KERNEL | __GFP_ZERO;
|
| 122 | struct amdgpu_bo *bo = NULL;
|
| 123 | struct sg_table *sg = NULL;
|
| 124 | struct amdgpu_bo_param bp;
|
| 125 | dma_addr_t dma_addr;
|
| 126 | struct page *p;
|
| 127 | unsigned long x;
|
| 128 | int ret;
|
| 129 |
|
| 130 | if (adev->gart.bo != NULL)
|
| 131 | return 0;
|
| 132 |
|
| 133 | p = alloc_pages(gfp_flags, order);
|
| 134 | if (!p)
|
| 135 | return -ENOMEM;
|
| 136 |
|
| 137 |
|
| 138 | for (x = 0; x < (1UL << order); x++)
|
| 139 | p[x].mapping = adev->mman.bdev.dev_mapping;
|
| 140 |
|
| 141 | |
| 142 | * then set_memory_wc() could be used as a workaround to mark the pages
|
| 143 | * as write combine memory.
|
| 144 |
|
| 145 | dma_addr = dma_map_page(&adev->pdev->dev, p, 0, adev->gart.table_size,
|
| 146 | DMA_BIDIRECTIONAL);
|
| 147 | if (dma_mapping_error(&adev->pdev->dev, dma_addr)) {
|
| 148 | dev_err(&adev->pdev->dev, "Failed to DMA MAP the GART BO page\n");
|
| 149 | __free_pages(p, order);
|
| 150 | p = NULL;
|
| 151 | return -EFAULT;
|
| 152 | }
|
| 153 |
|
| 154 | dev_info(adev->dev, "%s dma_addr:%pad\n", __func__, &dma_addr);
|
| 155 |
|
| 156 | sg = kmalloc_obj(*sg);
|
| 157 | if (!sg) {
|
| 158 | ret = -ENOMEM;
|
| 159 | goto error;
|
| 160 | }
|
| 161 | ret = sg_alloc_table(sg, 1, GFP_KERNEL);
|
| 162 | if (ret)
|
| 163 | goto error;
|
| 164 |
|
| 165 | sg_dma_address(sg->sgl) = dma_addr;
|
| 166 | sg->sgl->length = adev->gart.table_size;
|
| 167 | #ifdef CONFIG_NEED_SG_DMA_LENGTH
|
| 168 | sg->sgl->dma_length = adev->gart.table_size;
|
| 169 | #endif
|
| 170 |
|
| 171 | memset(&bp, 0, sizeof(bp));
|
| 172 | bp.size = adev->gart.table_size;
|
| 173 | bp.byte_align = PAGE_SIZE;
|
| 174 | bp.domain = AMDGPU_GEM_DOMAIN_CPU;
|
| 175 | bp.type = ttm_bo_type_sg;
|
| 176 | bp.resv = NULL;
|
| 177 | bp.bo_ptr_size = sizeof(struct amdgpu_bo);
|
| 178 | bp.flags = 0;
|
| 179 | ret = amdgpu_bo_create(adev, &bp, &bo);
|
| 180 | if (ret)
|
| 181 | goto error;
|
| 182 |
|
| 183 | bo->tbo.sg = sg;
|
| 184 | bo->tbo.ttm->sg = sg;
|
| 185 | bo->allowed_domains = AMDGPU_GEM_DOMAIN_GTT;
|
| 186 | bo->preferred_domains = AMDGPU_GEM_DOMAIN_GTT;
|
| 187 |
|
| 188 | ret = amdgpu_bo_reserve(bo, true);
|
| 189 | if (ret) {
|
| 190 | dev_err(adev->dev, "(%d) failed to reserve bo for GART system bo\n", ret);
|
| 191 | goto error;
|
| 192 | }
|
| 193 |
|
| 194 | ret = amdgpu_bo_pin(bo, AMDGPU_GEM_DOMAIN_GTT);
|
| 195 | WARN(ret, "Pinning the GART table failed");
|
| 196 | if (ret)
|
| 197 | goto error_resv;
|
| 198 |
|
| 199 | adev->gart.bo = bo;
|
| 200 | adev->gart.ptr = page_to_virt(p);
|
| 201 |
|
| 202 | ret = amdgpu_ttm_alloc_gart(&adev->gart.bo->tbo);
|
| 203 | if (ret)
|
| 204 | amdgpu_gart_table_ram_free(adev);
|
| 205 | amdgpu_bo_unreserve(bo);
|
| 206 |
|
| 207 | return 0;
|
| 208 |
|
| 209 | error_resv:
|
| 210 | amdgpu_bo_unreserve(bo);
|
| 211 | error:
|
| 212 | amdgpu_bo_unref(&bo);
|
| 213 | if (sg) {
|
| 214 | sg_free_table(sg);
|
| 215 | kfree(sg);
|
| 216 | }
|
| 217 | __free_pages(p, order);
|
| 218 | return ret;
|
| 219 | }
|
| 220 |
|
| 221 | |
| 222 | * amdgpu_gart_table_ram_free - free gart page table system ram
|
| 223 | *
|
| 224 | * @adev: amdgpu_device pointer
|
| 225 | *
|
| 226 | * Free the system memory used for the GART page tableon ASICs that don't
|
| 227 | * have dedicated VRAM.
|
| 228 |
|
| 229 | void amdgpu_gart_table_ram_free(struct amdgpu_device *adev)
|
| 230 | {
|
| 231 | unsigned int order = get_order(adev->gart.table_size);
|
| 232 | struct sg_table *sg = adev->gart.bo->tbo.sg;
|
| 233 | struct page *p;
|
| 234 | unsigned long x;
|
| 235 | int ret;
|
| 236 |
|
| 237 | ret = amdgpu_bo_reserve(adev->gart.bo, false);
|
| 238 | if (!ret) {
|
| 239 | amdgpu_bo_unpin(adev->gart.bo);
|
| 240 | amdgpu_bo_unreserve(adev->gart.bo);
|
| 241 | }
|
| 242 | amdgpu_bo_unref(&adev->gart.bo);
|
| 243 | sg_free_table(sg);
|
| 244 | kfree(sg);
|
| 245 | p = virt_to_page(adev->gart.ptr);
|
| 246 | for (x = 0; x < (1UL << order); x++)
|
| 247 | p[x].mapping = NULL;
|
| 248 | __free_pages(p, order);
|
| 249 |
|
| 250 | adev->gart.ptr = NULL;
|
| 251 | }
|
| 252 |
|
| 253 | |
| 254 | * amdgpu_gart_table_vram_alloc - allocate vram for gart page table
|
| 255 | *
|
| 256 | * @adev: amdgpu_device pointer
|
| 257 | *
|
| 258 | * Allocate video memory for GART page table
|
| 259 | * (pcie r4xx, r5xx+). These asics require the
|
| 260 | * gart table to be in video memory.
|
| 261 | * Returns 0 for success, error for failure.
|
| 262 |
|
| 263 | int amdgpu_gart_table_vram_alloc(struct amdgpu_device *adev)
|
| 264 | {
|
| 265 | int r;
|
| 266 |
|
| 267 | if (adev->gart.bo != NULL)
|
| 268 | return 0;
|
| 269 |
|
| 270 | r = amdgpu_bo_create_kernel(adev, adev->gart.table_size, PAGE_SIZE,
|
| 271 | AMDGPU_GEM_DOMAIN_VRAM, &adev->gart.bo,
|
| 272 | NULL, (void *)&adev->gart.ptr);
|
| 273 | if (r)
|
| 274 | return r;
|
| 275 |
|
| 276 | memset_io(adev->gart.ptr, adev->gart.gart_pte_flags, adev->gart.table_size);
|
| 277 | return 0;
|
| 278 | }
|
| 279 |
|
| 280 | |
| 281 | * amdgpu_gart_table_vram_free - free gart page table vram
|
| 282 | *
|
| 283 | * @adev: amdgpu_device pointer
|
| 284 | *
|
| 285 | * Free the video memory used for the GART page table
|
| 286 | * (pcie r4xx, r5xx+). These asics require the gart table to
|
| 287 | * be in video memory.
|
| 288 |
|
| 289 | void amdgpu_gart_table_vram_free(struct amdgpu_device *adev)
|
| 290 | {
|
| 291 | amdgpu_bo_free_kernel(&adev->gart.bo, NULL, (void *)&adev->gart.ptr);
|
| 292 | }
|
| 293 |
|
| 294 | |
| 295 | * Common gart functions.
|
| 296 |
|
| 297 | |
| 298 | * amdgpu_gart_unbind - unbind pages from the gart page table
|
| 299 | *
|
| 300 | * @adev: amdgpu_device pointer
|
| 301 | * @offset: offset into the GPU's gart aperture
|
| 302 | * @pages: number of pages to unbind
|
| 303 | *
|
| 304 | * Unbinds the requested pages from the gart page table and
|
| 305 | * replaces them with the dummy page (all asics).
|
| 306 | * Returns 0 for success, -EINVAL for failure.
|
| 307 |
|
| 308 | void amdgpu_gart_unbind(struct amdgpu_device *adev, uint64_t offset,
|
| 309 | int pages)
|
| 310 | {
|
| 311 | unsigned t;
|
| 312 | int i, j;
|
| 313 | u64 page_base;
|
| 314 |
|
| 315 | uint64_t flags = 0;
|
| 316 | int idx;
|
| 317 |
|
| 318 | if (!adev->gart.ptr)
|
| 319 | return;
|
| 320 |
|
| 321 | if (!drm_dev_enter(adev_to_drm(adev), &idx))
|
| 322 | return;
|
| 323 |
|
| 324 | t = offset / AMDGPU_GPU_PAGE_SIZE;
|
| 325 | for (i = 0; i < pages; i++) {
|
| 326 | page_base = adev->dummy_page_addr;
|
| 327 | if (!adev->gart.ptr)
|
| 328 | continue;
|
| 329 |
|
| 330 | for (j = 0; j < AMDGPU_GPU_PAGES_IN_CPU_PAGE; j++, t++) {
|
| 331 | amdgpu_gmc_set_pte_pde(adev, adev->gart.ptr,
|
| 332 | t, page_base, flags);
|
| 333 | page_base += AMDGPU_GPU_PAGE_SIZE;
|
| 334 | }
|
| 335 | }
|
| 336 | amdgpu_gart_invalidate_tlb(adev);
|
| 337 |
|
| 338 | drm_dev_exit(idx);
|
| 339 | }
|
| 340 |
|
| 341 | |
| 342 | * amdgpu_gart_map - map dma_addresses into GART entries
|
| 343 | *
|
| 344 | * @adev: amdgpu_device pointer
|
| 345 | * @offset: offset into the GPU's gart aperture
|
| 346 | * @pages: number of pages to bind
|
| 347 | * @dma_addr: DMA addresses of pages
|
| 348 | * @flags: page table entry flags
|
| 349 | * @dst: CPU address of the gart table
|
| 350 | *
|
| 351 | * Map the dma_addresses into GART entries (all asics).
|
| 352 | * Returns 0 for success, -EINVAL for failure.
|
| 353 |
|
| 354 | void amdgpu_gart_map(struct amdgpu_device *adev, uint64_t offset,
|
| 355 | int pages, dma_addr_t *dma_addr, uint64_t flags,
|
| 356 | void *dst)
|
| 357 | {
|
| 358 | uint64_t page_base;
|
| 359 | unsigned i, j, t;
|
| 360 | int idx;
|
| 361 |
|
| 362 | if (!drm_dev_enter(adev_to_drm(adev), &idx))
|
| 363 | return;
|
| 364 |
|
| 365 | t = offset / AMDGPU_GPU_PAGE_SIZE;
|
| 366 |
|
| 367 | for (i = 0; i < pages; i++) {
|
| 368 | page_base = dma_addr[i];
|
| 369 | for (j = 0; j < AMDGPU_GPU_PAGES_IN_CPU_PAGE; j++, t++) {
|
| 370 | amdgpu_gmc_set_pte_pde(adev, dst, t, page_base, flags);
|
| 371 | page_base += AMDGPU_GPU_PAGE_SIZE;
|
| 372 | }
|
| 373 | }
|
| 374 | drm_dev_exit(idx);
|
| 375 | }
|
| 376 |
|
| 377 | |
| 378 | * amdgpu_gart_map_vram_range - map VRAM pages into the GART page table
|
| 379 | *
|
| 380 | * @adev: amdgpu_device pointer
|
| 381 | * @pa: physical address of the first page to be mapped
|
| 382 | * @start_page: first page to map in the GART aperture
|
| 383 | * @num_pages: number of pages to be mapped
|
| 384 | * @flags: page table entry flags
|
| 385 | * @dst: valid CPU address of GART table, cannot be null
|
| 386 | *
|
| 387 | * Binds a BO that is allocated in VRAM to the GART page table
|
| 388 | * (all ASICs).
|
| 389 | *
|
| 390 | * Useful when a kernel BO is located in VRAM but
|
| 391 | * needs to be accessed from the GART address space.
|
| 392 |
|
| 393 | void amdgpu_gart_map_vram_range(struct amdgpu_device *adev, uint64_t pa,
|
| 394 | uint64_t start_page, uint64_t num_pages,
|
| 395 | uint64_t flags, void *dst)
|
| 396 | {
|
| 397 | u32 i, j, t, idx;
|
| 398 | u64 page_base;
|
| 399 |
|
| 400 |
|
| 401 | WARN_ON_ONCE(flags & AMDGPU_PTE_SYSTEM);
|
| 402 |
|
| 403 | if (!drm_dev_enter(adev_to_drm(adev), &idx))
|
| 404 | return;
|
| 405 |
|
| 406 | page_base = pa;
|
| 407 | for (i = 0, t = 0; i < num_pages; i++) {
|
| 408 | for (j = 0; j < AMDGPU_GPU_PAGES_IN_CPU_PAGE; j++, t++) {
|
| 409 | amdgpu_gmc_set_pte_pde(adev, dst, start_page + t, page_base, flags);
|
| 410 | page_base += AMDGPU_GPU_PAGE_SIZE;
|
| 411 | }
|
| 412 | }
|
| 413 |
|
| 414 | drm_dev_exit(idx);
|
| 415 | }
|
| 416 |
|
| 417 | |
| 418 | * amdgpu_gart_map_gfx9_mqd - map mqd and ctrl_stack dma_addresses into GART entries
|
| 419 | *
|
| 420 | * @adev: amdgpu_device pointer
|
| 421 | * @offset: offset into the GPU's gart aperture
|
| 422 | * @pages: number of pages to bind
|
| 423 | * @dma_addr: DMA addresses of pages
|
| 424 | * @flags: page table entry flags
|
| 425 | *
|
| 426 | * Map the MQD and control stack addresses into GART entries with the correct
|
| 427 | * memory types on gfxv9. The MQD occupies the first 4KB and is followed by
|
| 428 | * the control stack. The MQD uses UC (uncached) memory, while the control stack
|
| 429 | * uses NC (non-coherent) memory.
|
| 430 |
|
| 431 | void amdgpu_gart_map_gfx9_mqd(struct amdgpu_device *adev, uint64_t offset,
|
| 432 | int pages, dma_addr_t *dma_addr, uint64_t flags)
|
| 433 | {
|
| 434 | uint64_t page_base;
|
| 435 | unsigned int i, j, t;
|
| 436 | int idx;
|
| 437 | uint64_t ctrl_flags = AMDGPU_PTE_MTYPE_VG10(flags, AMDGPU_MTYPE_NC);
|
| 438 | void *dst;
|
| 439 |
|
| 440 | if (!adev->gart.ptr)
|
| 441 | return;
|
| 442 |
|
| 443 | if (!drm_dev_enter(adev_to_drm(adev), &idx))
|
| 444 | return;
|
| 445 |
|
| 446 | t = offset / AMDGPU_GPU_PAGE_SIZE;
|
| 447 | dst = adev->gart.ptr;
|
| 448 | for (i = 0; i < pages; i++) {
|
| 449 | page_base = dma_addr[i];
|
| 450 | for (j = 0; j < AMDGPU_GPU_PAGES_IN_CPU_PAGE; j++, t++) {
|
| 451 | if ((i == 0) && (j == 0))
|
| 452 | amdgpu_gmc_set_pte_pde(adev, dst, t, page_base, flags);
|
| 453 | else
|
| 454 | amdgpu_gmc_set_pte_pde(adev, dst, t, page_base, ctrl_flags);
|
| 455 | page_base += AMDGPU_GPU_PAGE_SIZE;
|
| 456 | }
|
| 457 | }
|
| 458 | drm_dev_exit(idx);
|
| 459 | }
|
| 460 |
|
| 461 | |
| 462 | * amdgpu_gart_bind - bind pages into the gart page table
|
| 463 | *
|
| 464 | * @adev: amdgpu_device pointer
|
| 465 | * @offset: offset into the GPU's gart aperture
|
| 466 | * @pages: number of pages to bind
|
| 467 | * @dma_addr: DMA addresses of pages
|
| 468 | * @flags: page table entry flags
|
| 469 | *
|
| 470 | * Binds the requested pages to the gart page table
|
| 471 | * (all asics).
|
| 472 | * Returns 0 for success, -EINVAL for failure.
|
| 473 |
|
| 474 | void amdgpu_gart_bind(struct amdgpu_device *adev, uint64_t offset,
|
| 475 | int pages, dma_addr_t *dma_addr,
|
| 476 | uint64_t flags)
|
| 477 | {
|
| 478 | if (!adev->gart.ptr)
|
| 479 | return;
|
| 480 |
|
| 481 | amdgpu_gart_map(adev, offset, pages, dma_addr, flags, adev->gart.ptr);
|
| 482 | }
|
| 483 |
|
| 484 | |
| 485 | * amdgpu_gart_invalidate_tlb - invalidate gart TLB
|
| 486 | *
|
| 487 | * @adev: amdgpu device driver pointer
|
| 488 | *
|
| 489 | * Invalidate gart TLB which can be use as a way to flush gart changes
|
| 490 | *
|
| 491 |
|
| 492 | void amdgpu_gart_invalidate_tlb(struct amdgpu_device *adev)
|
| 493 | {
|
| 494 | int i;
|
| 495 |
|
| 496 | if (!adev->gart.ptr)
|
| 497 | return;
|
| 498 |
|
| 499 | mb();
|
| 500 | if (down_read_trylock(&adev->reset_domain->sem)) {
|
| 501 | amdgpu_device_flush_hdp(adev, NULL);
|
| 502 | up_read(&adev->reset_domain->sem);
|
| 503 | }
|
| 504 | for_each_set_bit(i, adev->vmhubs_mask, AMDGPU_MAX_VMHUBS)
|
| 505 | amdgpu_gmc_flush_gpu_tlb(adev, 0, i, 0);
|
| 506 | }
|
| 507 |
|
| 508 | |
| 509 | * amdgpu_gart_init - init the driver info for managing the gart
|
| 510 | *
|
| 511 | * @adev: amdgpu_device pointer
|
| 512 | *
|
| 513 | * Allocate the dummy page and init the gart driver info (all asics).
|
| 514 | * Returns 0 for success, error for failure.
|
| 515 |
|
| 516 | int amdgpu_gart_init(struct amdgpu_device *adev)
|
| 517 | {
|
| 518 | int r;
|
| 519 |
|
| 520 | if (adev->dummy_page_addr)
|
| 521 | return 0;
|
| 522 |
|
| 523 |
|
| 524 | if (PAGE_SIZE < AMDGPU_GPU_PAGE_SIZE) {
|
| 525 | DRM_ERROR("Page size is smaller than GPU page size!\n");
|
| 526 | return -EINVAL;
|
| 527 | }
|
| 528 | r = amdgpu_gart_dummy_page_init(adev);
|
| 529 | if (r)
|
| 530 | return r;
|
| 531 |
|
| 532 | adev->gart.num_cpu_pages = adev->gmc.gart_size / PAGE_SIZE;
|
| 533 | adev->gart.num_gpu_pages = adev->gmc.gart_size / AMDGPU_GPU_PAGE_SIZE;
|
| 534 | drm_info(adev_to_drm(adev), "GART: num cpu pages %u, num gpu pages %u\n",
|
| 535 | adev->gart.num_cpu_pages, adev->gart.num_gpu_pages);
|
| 536 |
|
| 537 | return 0;
|
| 538 | }
|