aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c')
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c498
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
257static int amdgpu_verify_access(struct ttm_buffer_object *bo, struct file *filp) 259static 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
291static 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 */
298static 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 */
319int 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