diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 498 |
1 files changed, 316 insertions, 182 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index d792959fac43..ad5bf86ee8a3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | |||
| @@ -42,7 +42,9 @@ | |||
| 42 | #include <linux/swap.h> | 42 | #include <linux/swap.h> |
| 43 | #include <linux/pagemap.h> | 43 | #include <linux/pagemap.h> |
| 44 | #include <linux/debugfs.h> | 44 | #include <linux/debugfs.h> |
| 45 | #include <linux/iommu.h> | ||
| 45 | #include "amdgpu.h" | 46 | #include "amdgpu.h" |
| 47 | #include "amdgpu_object.h" | ||
| 46 | #include "amdgpu_trace.h" | 48 | #include "amdgpu_trace.h" |
| 47 | #include "bif/bif_4_1_d.h" | 49 | #include "bif/bif_4_1_d.h" |
| 48 | 50 | ||
| @@ -208,7 +210,7 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo, | |||
| 208 | placement->num_busy_placement = 1; | 210 | placement->num_busy_placement = 1; |
| 209 | return; | 211 | return; |
| 210 | } | 212 | } |
| 211 | abo = container_of(bo, struct amdgpu_bo, tbo); | 213 | abo = ttm_to_amdgpu_bo(bo); |
| 212 | switch (bo->mem.mem_type) { | 214 | switch (bo->mem.mem_type) { |
| 213 | case TTM_PL_VRAM: | 215 | case TTM_PL_VRAM: |
| 214 | if (adev->mman.buffer_funcs && | 216 | if (adev->mman.buffer_funcs && |
| @@ -256,7 +258,7 @@ gtt: | |||
| 256 | 258 | ||
| 257 | static int amdgpu_verify_access(struct ttm_buffer_object *bo, struct file *filp) | 259 | static int amdgpu_verify_access(struct ttm_buffer_object *bo, struct file *filp) |
| 258 | { | 260 | { |
| 259 | struct amdgpu_bo *abo = container_of(bo, struct amdgpu_bo, tbo); | 261 | struct amdgpu_bo *abo = ttm_to_amdgpu_bo(bo); |
| 260 | 262 | ||
| 261 | if (amdgpu_ttm_tt_get_usermm(bo->ttm)) | 263 | if (amdgpu_ttm_tt_get_usermm(bo->ttm)) |
| 262 | return -EPERM; | 264 | return -EPERM; |
| @@ -288,97 +290,177 @@ static uint64_t amdgpu_mm_node_addr(struct ttm_buffer_object *bo, | |||
| 288 | return addr; | 290 | return addr; |
| 289 | } | 291 | } |
| 290 | 292 | ||
| 291 | static int amdgpu_move_blit(struct ttm_buffer_object *bo, | 293 | /** |
| 292 | bool evict, bool no_wait_gpu, | 294 | * amdgpu_find_mm_node - Helper function finds the drm_mm_node |
| 293 | struct ttm_mem_reg *new_mem, | 295 | * corresponding to @offset. It also modifies the offset to be |
| 294 | struct ttm_mem_reg *old_mem) | 296 | * within the drm_mm_node returned |
| 297 | */ | ||
| 298 | static struct drm_mm_node *amdgpu_find_mm_node(struct ttm_mem_reg *mem, | ||
| 299 | unsigned long *offset) | ||
| 295 | { | 300 | { |
| 296 | struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev); | 301 | struct drm_mm_node *mm_node = mem->mm_node; |
| 297 | struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring; | ||
| 298 | 302 | ||
| 299 | struct drm_mm_node *old_mm, *new_mm; | 303 | while (*offset >= (mm_node->size << PAGE_SHIFT)) { |
| 300 | uint64_t old_start, old_size, new_start, new_size; | 304 | *offset -= (mm_node->size << PAGE_SHIFT); |
| 301 | unsigned long num_pages; | 305 | ++mm_node; |
| 302 | struct dma_fence *fence = NULL; | 306 | } |
| 303 | int r; | 307 | return mm_node; |
| 308 | } | ||
| 304 | 309 | ||
| 305 | BUILD_BUG_ON((PAGE_SIZE % AMDGPU_GPU_PAGE_SIZE) != 0); | 310 | /** |
| 311 | * amdgpu_copy_ttm_mem_to_mem - Helper function for copy | ||
| 312 | * | ||
| 313 | * The function copies @size bytes from {src->mem + src->offset} to | ||
| 314 | * {dst->mem + dst->offset}. src->bo and dst->bo could be same BO for a | ||
| 315 | * move and different for a BO to BO copy. | ||
| 316 | * | ||
| 317 | * @f: Returns the last fence if multiple jobs are submitted. | ||
| 318 | */ | ||
| 319 | int amdgpu_ttm_copy_mem_to_mem(struct amdgpu_device *adev, | ||
| 320 | struct amdgpu_copy_mem *src, | ||
| 321 | struct amdgpu_copy_mem *dst, | ||
| 322 | uint64_t size, | ||
| 323 | struct reservation_object *resv, | ||
| 324 | struct dma_fence **f) | ||
| 325 | { | ||
| 326 | struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring; | ||
| 327 | struct drm_mm_node *src_mm, *dst_mm; | ||
| 328 | uint64_t src_node_start, dst_node_start, src_node_size, | ||
| 329 | dst_node_size, src_page_offset, dst_page_offset; | ||
| 330 | struct dma_fence *fence = NULL; | ||
| 331 | int r = 0; | ||
| 332 | const uint64_t GTT_MAX_BYTES = (AMDGPU_GTT_MAX_TRANSFER_SIZE * | ||
| 333 | AMDGPU_GPU_PAGE_SIZE); | ||
| 306 | 334 | ||
| 307 | if (!ring->ready) { | 335 | if (!ring->ready) { |
| 308 | DRM_ERROR("Trying to move memory with ring turned off.\n"); | 336 | DRM_ERROR("Trying to move memory with ring turned off.\n"); |
| 309 | return -EINVAL; | 337 | return -EINVAL; |
| 310 | } | 338 | } |
| 311 | 339 | ||
| 312 | old_mm = old_mem->mm_node; | 340 | src_mm = amdgpu_find_mm_node(src->mem, &src->offset); |
| 313 | old_size = old_mm->size; | 341 | src_node_start = amdgpu_mm_node_addr(src->bo, src_mm, src->mem) + |
| 314 | old_start = amdgpu_mm_node_addr(bo, old_mm, old_mem); | 342 | src->offset; |
| 343 | src_node_size = (src_mm->size << PAGE_SHIFT) - src->offset; | ||
| 344 | src_page_offset = src_node_start & (PAGE_SIZE - 1); | ||
| 315 | 345 | ||
| 316 | new_mm = new_mem->mm_node; | 346 | dst_mm = amdgpu_find_mm_node(dst->mem, &dst->offset); |
| 317 | new_size = new_mm->size; | 347 | dst_node_start = amdgpu_mm_node_addr(dst->bo, dst_mm, dst->mem) + |
| 318 | new_start = amdgpu_mm_node_addr(bo, new_mm, new_mem); | 348 | dst->offset; |
| 349 | dst_node_size = (dst_mm->size << PAGE_SHIFT) - dst->offset; | ||
| 350 | dst_page_offset = dst_node_start & (PAGE_SIZE - 1); | ||
| 319 | 351 | ||
| 320 | num_pages = new_mem->num_pages; | ||
| 321 | mutex_lock(&adev->mman.gtt_window_lock); | 352 | mutex_lock(&adev->mman.gtt_window_lock); |
| 322 | while (num_pages) { | 353 | |
| 323 | unsigned long cur_pages = min(min(old_size, new_size), | 354 | while (size) { |
| 324 | (u64)AMDGPU_GTT_MAX_TRANSFER_SIZE); | 355 | unsigned long cur_size; |
| 325 | uint64_t from = old_start, to = new_start; | 356 | uint64_t from = src_node_start, to = dst_node_start; |
| 326 | struct dma_fence *next; | 357 | struct dma_fence *next; |
| 327 | 358 | ||
| 328 | if (old_mem->mem_type == TTM_PL_TT && | 359 | /* Copy size cannot exceed GTT_MAX_BYTES. So if src or dst |
| 329 | !amdgpu_gtt_mgr_is_allocated(old_mem)) { | 360 | * begins at an offset, then adjust the size accordingly |
| 330 | r = amdgpu_map_buffer(bo, old_mem, cur_pages, | 361 | */ |
| 331 | old_start, 0, ring, &from); | 362 | cur_size = min3(min(src_node_size, dst_node_size), size, |
| 363 | GTT_MAX_BYTES); | ||
| 364 | if (cur_size + src_page_offset > GTT_MAX_BYTES || | ||
| 365 | cur_size + dst_page_offset > GTT_MAX_BYTES) | ||
| 366 | cur_size -= max(src_page_offset, dst_page_offset); | ||
| 367 | |||
| 368 | /* Map only what needs to be accessed. Map src to window 0 and | ||
| 369 | * dst to window 1 | ||
| 370 | */ | ||
| 371 | if (src->mem->mem_type == TTM_PL_TT && | ||
| 372 | !amdgpu_gtt_mgr_is_allocated(src->mem)) { | ||
| 373 | r = amdgpu_map_buffer(src->bo, src->mem, | ||
| 374 | PFN_UP(cur_size + src_page_offset), | ||
| 375 | src_node_start, 0, ring, | ||
| 376 | &from); | ||
| 332 | if (r) | 377 | if (r) |
| 333 | goto error; | 378 | goto error; |
| 379 | /* Adjust the offset because amdgpu_map_buffer returns | ||
| 380 | * start of mapped page | ||
| 381 | */ | ||
| 382 | from += src_page_offset; | ||
| 334 | } | 383 | } |
| 335 | 384 | ||
| 336 | if (new_mem->mem_type == TTM_PL_TT && | 385 | if (dst->mem->mem_type == TTM_PL_TT && |
| 337 | !amdgpu_gtt_mgr_is_allocated(new_mem)) { | 386 | !amdgpu_gtt_mgr_is_allocated(dst->mem)) { |
| 338 | r = amdgpu_map_buffer(bo, new_mem, cur_pages, | 387 | r = amdgpu_map_buffer(dst->bo, dst->mem, |
| 339 | new_start, 1, ring, &to); | 388 | PFN_UP(cur_size + dst_page_offset), |
| 389 | dst_node_start, 1, ring, | ||
| 390 | &to); | ||
| 340 | if (r) | 391 | if (r) |
| 341 | goto error; | 392 | goto error; |
| 393 | to += dst_page_offset; | ||
| 342 | } | 394 | } |
| 343 | 395 | ||
| 344 | r = amdgpu_copy_buffer(ring, from, to, | 396 | r = amdgpu_copy_buffer(ring, from, to, cur_size, |
| 345 | cur_pages * PAGE_SIZE, | 397 | resv, &next, false, true); |
| 346 | bo->resv, &next, false, true); | ||
| 347 | if (r) | 398 | if (r) |
| 348 | goto error; | 399 | goto error; |
| 349 | 400 | ||
| 350 | dma_fence_put(fence); | 401 | dma_fence_put(fence); |
| 351 | fence = next; | 402 | fence = next; |
| 352 | 403 | ||
