diff options
author | Tom St Denis <tom.stdenis@amd.com> | 2018-05-09 14:22:29 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2018-05-18 17:08:19 -0400 |
commit | 50da51744f005f4afd44b69c03e6f2068abfaed8 (patch) | |
tree | b3af3b2b014749e2b1d99393514e8111dbf2ce9f /drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | |
parent | fa19a6e9d0e7b46bedaa526ba71ff1bf376dd93f (diff) |
drm/amd/amdgpu: Code comments for the amdgpu_ttm.c driver. (v2)
NFC just comments.
(v2): Updated based on feedback from Alex Deucher.
Signed-off-by: Tom St Denis <tom.stdenis@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 348 |
1 files changed, 341 insertions, 7 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 69a2b25b3696..e93a0a237dc3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | |||
@@ -63,16 +63,44 @@ static void amdgpu_ttm_debugfs_fini(struct amdgpu_device *adev); | |||
63 | /* | 63 | /* |
64 | * Global memory. | 64 | * Global memory. |
65 | */ | 65 | */ |
66 | |||
67 | /** | ||
68 | * amdgpu_ttm_mem_global_init - Initialize and acquire reference to | ||
69 | * memory object | ||
70 | * | ||
71 | * @ref: Object for initialization. | ||
72 | * | ||
73 | * This is called by drm_global_item_ref() when an object is being | ||
74 | * initialized. | ||
75 | */ | ||
66 | static int amdgpu_ttm_mem_global_init(struct drm_global_reference *ref) | 76 | static int amdgpu_ttm_mem_global_init(struct drm_global_reference *ref) |
67 | { | 77 | { |
68 | return ttm_mem_global_init(ref->object); | 78 | return ttm_mem_global_init(ref->object); |
69 | } | 79 | } |
70 | 80 | ||
81 | /** | ||
82 | * amdgpu_ttm_mem_global_release - Drop reference to a memory object | ||
83 | * | ||
84 | * @ref: Object being removed | ||
85 | * | ||
86 | * This is called by drm_global_item_unref() when an object is being | ||
87 | * released. | ||
88 | */ | ||
71 | static void amdgpu_ttm_mem_global_release(struct drm_global_reference *ref) | 89 | static void amdgpu_ttm_mem_global_release(struct drm_global_reference *ref) |
72 | { | 90 | { |
73 | ttm_mem_global_release(ref->object); | 91 | ttm_mem_global_release(ref->object); |
74 | } | 92 | } |
75 | 93 | ||
94 | /** | ||
95 | * amdgpu_ttm_global_init - Initialize global TTM memory reference | ||
96 | * structures. | ||
97 | * | ||
98 | * @adev: AMDGPU device for which the global structures need to be | ||
99 | * registered. | ||
100 | * | ||
101 | * This is called as part of the AMDGPU ttm init from amdgpu_ttm_init() | ||
102 | * during bring up. | ||
103 | */ | ||
76 | static int amdgpu_ttm_global_init(struct amdgpu_device *adev) | 104 | static int amdgpu_ttm_global_init(struct amdgpu_device *adev) |
77 | { | 105 | { |
78 | struct drm_global_reference *global_ref; | 106 | struct drm_global_reference *global_ref; |
@@ -80,7 +108,9 @@ static int amdgpu_ttm_global_init(struct amdgpu_device *adev) | |||
80 | struct drm_sched_rq *rq; | 108 | struct drm_sched_rq *rq; |
81 | int r; | 109 | int r; |
82 | 110 | ||
111 | /* ensure reference is false in case init fails */ | ||
83 | adev->mman.mem_global_referenced = false; | 112 | adev->mman.mem_global_referenced = false; |
113 | |||
84 | global_ref = &adev->mman.mem_global_ref; | 114 | global_ref = &adev->mman.mem_global_ref; |
85 | global_ref->global_type = DRM_GLOBAL_TTM_MEM; | 115 | global_ref->global_type = DRM_GLOBAL_TTM_MEM; |
86 | global_ref->size = sizeof(struct ttm_mem_global); | 116 | global_ref->size = sizeof(struct ttm_mem_global); |
@@ -146,6 +176,18 @@ static int amdgpu_invalidate_caches(struct ttm_bo_device *bdev, uint32_t flags) | |||
146 | return 0; | 176 | return 0; |
147 | } | 177 | } |
148 | 178 | ||
179 | /** | ||
180 | * amdgpu_init_mem_type - Initialize a memory manager for a specific | ||
181 | * type of memory request. | ||
182 | * | ||
183 | * @bdev: The TTM BO device object (contains a reference to | ||
184 | * amdgpu_device) | ||
185 | * @type: The type of memory requested | ||
186 | * @man: | ||
187 | * | ||
188 | * This is called by ttm_bo_init_mm() when a buffer object is being | ||
189 | * initialized. | ||
190 | */ | ||
149 | static int amdgpu_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, | 191 | static int amdgpu_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, |
150 | struct ttm_mem_type_manager *man) | 192 | struct ttm_mem_type_manager *man) |
151 | { | 193 | { |
@@ -161,6 +203,7 @@ static int amdgpu_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, | |||
161 | man->default_caching = TTM_PL_FLAG_CACHED; | 203 | man->default_caching = TTM_PL_FLAG_CACHED; |
162 | break; | 204 | break; |
163 | case TTM_PL_TT: | 205 | case TTM_PL_TT: |
206 | /* GTT memory */ | ||
164 | man->func = &amdgpu_gtt_mgr_func; | 207 | man->func = &amdgpu_gtt_mgr_func; |
165 | man->gpu_offset = adev->gmc.gart_start; | 208 | man->gpu_offset = adev->gmc.gart_start; |
166 | man->available_caching = TTM_PL_MASK_CACHING; | 209 | man->available_caching = TTM_PL_MASK_CACHING; |
@@ -193,6 +236,14 @@ static int amdgpu_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, | |||
193 | return 0; | 236 | return 0; |
194 | } | 237 | } |
195 | 238 | ||
239 | /** | ||
240 | * amdgpu_evict_flags - Compute placement flags | ||
241 | * | ||
242 | * @bo: The buffer object to evict | ||
243 | * @placement: Possible destination(s) for evicted BO | ||
244 | * | ||
245 | * Fill in placement data when ttm_bo_evict() is called | ||
246 | */ | ||
196 | static void amdgpu_evict_flags(struct ttm_buffer_object *bo, | 247 | static void amdgpu_evict_flags(struct ttm_buffer_object *bo, |
197 | struct ttm_placement *placement) | 248 | struct ttm_placement *placement) |
198 | { | 249 | { |
@@ -204,12 +255,14 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo, | |||
204 | .flags = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM | 255 | .flags = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM |
205 | }; | 256 | }; |
206 | 257 | ||
258 | /* Don't handle scatter gather BOs */ | ||
207 | if (bo->type == ttm_bo_type_sg) { | 259 | if (bo->type == ttm_bo_type_sg) { |
208 | placement->num_placement = 0; | 260 | placement->num_placement = 0; |
209 | placement->num_busy_placement = 0; | 261 | placement->num_busy_placement = 0; |
210 | return; | 262 | return; |
211 | } | 263 | } |
212 | 264 | ||
265 | /* Object isn't an AMDGPU object so ignore */ | ||
213 | if (!amdgpu_ttm_bo_is_amdgpu_bo(bo)) { | 266 | if (!amdgpu_ttm_bo_is_amdgpu_bo(bo)) { |
214 | placement->placement = &placements; | 267 | placement->placement = &placements; |
215 | placement->busy_placement = &placements; | 268 | placement->busy_placement = &placements; |
@@ -217,10 +270,12 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo, | |||
217 | placement->num_busy_placement = 1; | 270 | placement->num_busy_placement = 1; |
218 | return; | 271 | return; |
219 | } | 272 | } |
273 | |||
220 | abo = ttm_to_amdgpu_bo(bo); | 274 | abo = ttm_to_amdgpu_bo(bo); |
221 | switch (bo->mem.mem_type) { | 275 | switch (bo->mem.mem_type) { |
222 | case TTM_PL_VRAM: | 276 | case TTM_PL_VRAM: |
223 | if (!adev->mman.buffer_funcs_enabled) { | 277 | if (!adev->mman.buffer_funcs_enabled) { |
278 | /* Move to system memory */ | ||
224 | amdgpu_ttm_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_CPU); | 279 | amdgpu_ttm_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_CPU); |
225 | } else if (adev->gmc.visible_vram_size < adev->gmc.real_vram_size && | 280 | } else if (adev->gmc.visible_vram_size < adev->gmc.real_vram_size && |
226 | !(abo->flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED) && | 281 | !(abo->flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED) && |
@@ -238,6 +293,7 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo, | |||
238 | abo->placement.busy_placement = &abo->placements[1]; | 293 | abo->placement.busy_placement = &abo->placements[1]; |
239 | abo->placement.num_busy_placement = 1; | 294 | abo->placement.num_busy_placement = 1; |
240 | } else { | 295 | } else { |
296 | /* Move to GTT memory */ | ||
241 | amdgpu_ttm_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_GTT); | 297 | amdgpu_ttm_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_GTT); |
242 | } | 298 | } |
243 | break; | 299 | break; |
@@ -248,6 +304,15 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo, | |||
248 | *placement = abo->placement; | 304 | *placement = abo->placement; |
249 | } | 305 | } |
250 | 306 | ||
307 | /** | ||
308 | * amdgpu_verify_access - Verify access for a mmap call | ||
309 | * | ||
310 | * @bo: The buffer object to map | ||
311 | * @filp: The file pointer from the process performing the mmap | ||
312 | * | ||
313 | * This is called by ttm_bo_mmap() to verify whether a process | ||
314 | * has the right to mmap a BO to their process space. | ||
315 | */ | ||
251 | static int amdgpu_verify_access(struct ttm_buffer_object *bo, struct file *filp) | 316 | static int amdgpu_verify_access(struct ttm_buffer_object *bo, struct file *filp) |
252 | { | 317 | { |
253 | struct amdgpu_bo *abo = ttm_to_amdgpu_bo(bo); | 318 | struct amdgpu_bo *abo = ttm_to_amdgpu_bo(bo); |
@@ -265,6 +330,15 @@ static int amdgpu_verify_access(struct ttm_buffer_object *bo, struct file *filp) | |||
265 | filp->private_data); | 330 | filp->private_data); |
266 | } | 331 | } |
267 | 332 | ||
333 | /** | ||
334 | * amdgpu_move_null - Register memory for a buffer object | ||
335 | * | ||
336 | * @bo: The bo to assign the memory to | ||
337 | * @new_mem: The memory to be assigned. | ||
338 | * | ||
339 | * Assign the memory from new_mem to the memory of the buffer object | ||
340 | * bo. | ||
341 | */ | ||
268 | static void amdgpu_move_null(struct ttm_buffer_object *bo, | 342 | static void amdgpu_move_null(struct ttm_buffer_object *bo, |
269 | struct ttm_mem_reg *new_mem) | 343 | struct ttm_mem_reg *new_mem) |
270 | { | 344 | { |
@@ -275,6 +349,10 @@ static void amdgpu_move_null(struct ttm_buffer_object *bo, | |||
275 | new_mem->mm_node = NULL; | 349 | new_mem->mm_node = NULL; |
276 | } | 350 | } |
277 | 351 | ||
352 | /** | ||
353 | * amdgpu_mm_node_addr - Compute the GPU relative offset of a GTT | ||
354 | * buffer. | ||
355 | */ | ||
278 | static uint64_t amdgpu_mm_node_addr(struct ttm_buffer_object *bo, | 356 | static uint64_t amdgpu_mm_node_addr(struct ttm_buffer_object *bo, |
279 | struct drm_mm_node *mm_node, | 357 | struct drm_mm_node *mm_node, |
280 | struct ttm_mem_reg *mem) | 358 | struct ttm_mem_reg *mem) |
@@ -289,9 +367,10 @@ static uint64_t amdgpu_mm_node_addr(struct ttm_buffer_object *bo, | |||
289 | } | 367 | } |
290 | 368 | ||
291 | /** | 369 | /** |
292 | * amdgpu_find_mm_node - Helper function finds the drm_mm_node | 370 | * amdgpu_find_mm_node - Helper function finds the drm_mm_node |
293 | * corresponding to @offset. It also modifies the offset to be | 371 | * corresponding to @offset. It also modifies |
294 | * within the drm_mm_node returned | 372 | * the offset to be within the drm_mm_node |
373 | * returned | ||
295 | */ | 374 | */ |
296 | static struct drm_mm_node *amdgpu_find_mm_node(struct ttm_mem_reg *mem, | 375 | static struct drm_mm_node *amdgpu_find_mm_node(struct ttm_mem_reg *mem, |
297 | unsigned long *offset) | 376 | unsigned long *offset) |
@@ -430,7 +509,12 @@ error: | |||
430 | return r; | 509 | return r; |
431 | } | 510 | } |
432 | 511 | ||
433 | 512 | /** | |
513 | * amdgpu_move_blit - Copy an entire buffer to another buffer | ||
514 | * | ||
515 | * This is a helper called by amdgpu_bo_move() and | ||
516 | * amdgpu_move_vram_ram() to help move buffers to and from VRAM. | ||
517 | */ | ||
434 | static int amdgpu_move_blit(struct ttm_buffer_object *bo, | 518 | static int amdgpu_move_blit(struct ttm_buffer_object *bo, |
435 | bool evict, bool no_wait_gpu, | 519 | bool evict, bool no_wait_gpu, |
436 | struct ttm_mem_reg *new_mem, | 520 | struct ttm_mem_reg *new_mem, |
@@ -465,6 +549,11 @@ error: | |||
465 | return r; | 549 | return r; |
466 | } | 550 | } |
467 | 551 | ||
552 | /** | ||
553 | * amdgpu_move_vram_ram - Copy VRAM buffer to RAM buffer | ||
554 | * | ||
555 | * Called by amdgpu_bo_move(). | ||
556 | */ | ||
468 | static int amdgpu_move_vram_ram(struct ttm_buffer_object *bo, bool evict, | 557 | static int amdgpu_move_vram_ram(struct ttm_buffer_object *bo, bool evict, |
469 | struct ttm_operation_ctx *ctx, | 558 | struct ttm_operation_ctx *ctx, |
470 | struct ttm_mem_reg *new_mem) | 559 | struct ttm_mem_reg *new_mem) |
@@ -477,6 +566,8 @@ static int amdgpu_move_vram_ram(struct ttm_buffer_object *bo, bool evict, | |||
477 | int r; | 566 | int r; |
478 | 567 | ||
479 | adev = amdgpu_ttm_adev(bo->bdev); | 568 | adev = amdgpu_ttm_adev(bo->bdev); |
569 | |||
570 | /* create space/pages for new_mem in GTT space */ | ||
480 | tmp_mem = *new_mem; | 571 | tmp_mem = *new_mem; |
481 | tmp_mem.mm_node = NULL; | 572 | tmp_mem.mm_node = NULL; |
482 | placement.num_placement = 1; | 573 | placement.num_placement = 1; |
@@ -491,25 +582,36 @@ static int amdgpu_move_vram_ram(struct ttm_buffer_object *bo, bool evict, | |||
491 | return r; | 582 | return r; |
492 | } | 583 | } |
493 | 584 | ||
585 | /* set caching flags */ | ||
494 | r = ttm_tt_set_placement_caching(bo->ttm, tmp_mem.placement); | 586 | r = ttm_tt_set_placement_caching(bo->ttm, tmp_mem.placement); |
495 | if (unlikely(r)) { | 587 | if (unlikely(r)) { |
496 | goto out_cleanup; | 588 | goto out_cleanup; |
497 | } | 589 | } |
498 | 590 | ||
591 | /* Bind the memory to the GTT space */ | ||
499 | r = ttm_tt_bind(bo->ttm, &tmp_mem, ctx); | 592 | r = ttm_tt_bind(bo->ttm, &tmp_mem, ctx); |
500 | if (unlikely(r)) { | 593 | if (unlikely(r)) { |
501 | goto out_cleanup; | 594 | goto out_cleanup; |
502 | } | 595 | } |
596 | |||
597 | /* blit VRAM to GTT */ | ||
503 | r = amdgpu_move_blit(bo, true, ctx->no_wait_gpu, &tmp_mem, old_mem); | 598 | r = amdgpu_move_blit(bo, true, ctx->no_wait_gpu, &tmp_mem, old_mem); |
504 | if (unlikely(r)) { | 599 | if (unlikely(r)) { |
505 | goto out_cleanup; | 600 | goto out_cleanup; |
506 | } | 601 | } |
602 | |||
603 | /* move BO (in tmp_mem) to new_mem */ | ||
507 | r = ttm_bo_move_ttm(bo, ctx, new_mem); | 604 | r = ttm_bo_move_ttm(bo, ctx, new_mem); |
508 | out_cleanup: | 605 | out_cleanup: |
509 | ttm_bo_mem_put(bo, &tmp_mem); | 606 | ttm_bo_mem_put(bo, &tmp_mem); |
510 | return r; | 607 | return r; |
511 | } | 608 | } |
512 | 609 | ||
610 | /** | ||
611 | * amdgpu_move_ram_vram - Copy buffer from RAM to VRAM | ||
612 | * | ||
613 | * Called by amdgpu_bo_move(). | ||
614 | */ | ||
513 | static int amdgpu_move_ram_vram(struct ttm_buffer_object *bo, bool evict, | 615 | static int amdgpu_move_ram_vram(struct ttm_buffer_object *bo, bool evict, |
514 | struct ttm_operation_ctx *ctx, | 616 | struct ttm_operation_ctx *ctx, |
515 | struct ttm_mem_reg *new_mem) | 617 | struct ttm_mem_reg *new_mem) |
@@ -522,6 +624,8 @@ static int amdgpu_move_ram_vram(struct ttm_buffer_object *bo, bool evict, | |||
522 | int r; | 624 | int r; |
523 | 625 | ||
524 | adev = amdgpu_ttm_adev(bo->bdev); | 626 | adev = amdgpu_ttm_adev(bo->bdev); |
627 | |||
628 | /* make space in GTT for old_mem buffer */ | ||
525 | tmp_mem = *new_mem; | 629 | tmp_mem = *new_mem; |
526 | tmp_mem.mm_node = NULL; | 630 | tmp_mem.mm_node = NULL; |
527 | placement.num_placement = 1; | 631 | placement.num_placement = 1; |
@@ -535,10 +639,14 @@ static int amdgpu_move_ram_vram(struct ttm_buffer_object *bo, bool evict, | |||
535 | if (unlikely(r)) { | 639 | if (unlikely(r)) { |
536 | return r; | 640 | return r; |
537 | } | 641 | } |
642 | |||
643 | /* move/bind old memory to GTT space */ | ||
538 | r = ttm_bo_move_ttm(bo, ctx, &tmp_mem); | 644 | r = ttm_bo_move_ttm(bo, ctx, &tmp_mem); |
539 | if (unlikely(r)) { | 645 | if (unlikely(r)) { |
540 | goto out_cleanup; | 646 | goto out_cleanup; |
541 | } | 647 | } |
648 | |||
649 | /* copy to VRAM */ | ||
542 | r = amdgpu_move_blit(bo, true, ctx->no_wait_gpu, new_mem, old_mem); | 650 | r = amdgpu_move_blit(bo, true, ctx->no_wait_gpu, new_mem, old_mem); |
543 | if (unlikely(r)) { | 651 | if (unlikely(r)) { |
544 | goto out_cleanup; | 652 | goto out_cleanup; |
@@ -548,6 +656,11 @@ out_cleanup: | |||
548 | return r; | 656 | return r; |
549 | } | 657 | } |
550 | 658 | ||
659 | /** | ||
660 | * amdgpu_bo_move - Move a buffer object to a new memory location | ||
661 | * | ||
662 | * Called by ttm_bo_handle_move_mem() | ||
663 | */ | ||
551 | static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict, | 664 | static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict, |
552 | struct ttm_operation_ctx *ctx, | 665 | struct ttm_operation_ctx *ctx, |
553 | struct ttm_mem_reg *new_mem) | 666 | struct ttm_mem_reg *new_mem) |
@@ -613,6 +726,11 @@ memcpy: | |||
613 | return 0; | 726 | return 0; |
614 | } | 727 | } |
615 | 728 | ||
729 | /** | ||
730 | * amdgpu_ttm_io_mem_reserve - Reserve a block of memory during a fault | ||
731 | * | ||
732 | * Called by ttm_mem_io_reserve() ultimately via ttm_bo_vm_fault() | ||
733 | */ | ||
616 | static int amdgpu_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) | 734 | static int amdgpu_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) |
617 | { | 735 | { |
618 | struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type]; | 736 | struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type]; |
@@ -690,6 +808,14 @@ struct amdgpu_ttm_tt { | |||
690 | uint32_t last_set_pages; | 808 | uint32_t last_set_pages; |
691 | }; | 809 | }; |
692 | 810 | ||
811 | /** | ||
812 | * amdgpu_ttm_tt_get_user_pages - Pin pages of memory pointed to | ||
813 | * by a USERPTR pointer to memory | ||
814 | * | ||
815 | * Called by amdgpu_gem_userptr_ioctl() and amdgpu_cs_parser_bos(). | ||
816 | * This provides a wrapper around the get_user_pages() call to provide | ||
817 | * device accessible pages that back user memory. | ||
818 | */ | ||
693 | int amdgpu_ttm_tt_get_user_pages(struct ttm_tt *ttm, struct page **pages) | 819 | int amdgpu_ttm_tt_get_user_pages(struct ttm_tt *ttm, struct page **pages) |
694 | { | 820 | { |
695 | struct amdgpu_ttm_tt *gtt = (void *)ttm; | 821 | struct amdgpu_ttm_tt *gtt = (void *)ttm; |
@@ -719,6 +845,7 @@ int amdgpu_ttm_tt_get_user_pages(struct ttm_tt *ttm, struct page **pages) | |||
719 | } | 845 | } |
720 | } | 846 | } |
721 | 847 | ||
848 | /* loop enough times using contiguous pages of memory */ | ||
722 | do { | 849 | do { |
723 | unsigned num_pages = ttm->num_pages - pinned; | 850 | unsigned num_pages = ttm->num_pages - pinned; |
724 | uint64_t userptr = gtt->userptr + pinned * PAGE_SIZE; | 851 | uint64_t userptr = gtt->userptr + pinned * PAGE_SIZE; |
@@ -757,6 +884,14 @@ release_pages: | |||
757 | return r; | 884 | return r; |
758 | } | 885 | } |
759 | 886 | ||
887 | /** | ||
888 | * amdgpu_ttm_tt_set_user_pages - Copy pages in, putting old pages | ||
889 | * as necessary. | ||
890 | * | ||
891 | * Called by amdgpu_cs_list_validate(). This creates the page list | ||
892 | * that backs user memory and will ultimately be mapped into the device | ||
893 | * address space. | ||
894 | */ | ||
760 | void amdgpu_ttm_tt_set_user_pages(struct ttm_tt *ttm, struct page **pages) | 895 | void amdgpu_ttm_tt_set_user_pages(struct ttm_tt *ttm, struct page **pages) |
761 | { | 896 | { |
762 | struct amdgpu_ttm_tt *gtt = (void *)ttm; | 897 | struct amdgpu_ttm_tt *gtt = (void *)ttm; |
@@ -771,6 +906,11 @@ void amdgpu_ttm_tt_set_user_pages(struct ttm_tt *ttm, struct page **pages) | |||
771 | } | 906 | } |
772 | } | 907 | } |
773 | 908 | ||
909 | /** | ||
910 | * amdgpu_ttm_tt_mark_user_page - Mark pages as dirty | ||
911 | * | ||
912 | * Called while unpinning userptr pages | ||
913 | */ | ||
774 | void amdgpu_ttm_tt_mark_user_pages(struct ttm_tt *ttm) | 914 | void amdgpu_ttm_tt_mark_user_pages(struct ttm_tt *ttm) |
775 | { | 915 | { |
776 | struct amdgpu_ttm_tt *gtt = (void *)ttm; | 916 | struct amdgpu_ttm_tt *gtt = (void *)ttm; |
@@ -789,7 +929,12 @@ void amdgpu_ttm_tt_mark_user_pages(struct ttm_tt *ttm) | |||
789 | } | 929 | } |
790 | } | 930 | } |
791 | 931 | ||
792 | /* prepare the sg table with the user pages */ | 932 | /** |
933 | * amdgpu_ttm_tt_pin_userptr - prepare the sg table with the | ||
934 | * user pages | ||
935 | * | ||
936 | * Called by amdgpu_ttm_backend_bind() | ||
937 | **/ | ||
793 | static int amdgpu_ttm_tt_pin_userptr(struct ttm_tt *ttm) | 938 | static int amdgpu_ttm_tt_pin_userptr(struct ttm_tt *ttm) |
794 | { | 939 | { |
795 | struct amdgpu_device *adev = amdgpu_ttm_adev(ttm->bdev); | 940 | struct amdgpu_device *adev = amdgpu_ttm_adev(ttm->bdev); |
@@ -801,17 +946,20 @@ static int amdgpu_ttm_tt_pin_userptr(struct ttm_tt *ttm) | |||
801 | enum dma_data_direction direction = write ? | 946 | enum dma_data_direction direction = write ? |
802 | DMA_BIDIRECTIONAL : DMA_TO_DEVICE; | 947 | DMA_BIDIRECTIONAL : DMA_TO_DEVICE; |
803 | 948 | ||
949 | /* Allocate an SG array and squash pages into it */ | ||
804 | r = sg_alloc_table_from_pages(ttm->sg, ttm->pages, ttm->num_pages, 0, | 950 | r = sg_alloc_table_from_pages(ttm->sg, ttm->pages, ttm->num_pages, 0, |
805 | ttm->num_pages << PAGE_SHIFT, | 951 | ttm->num_pages << PAGE_SHIFT, |
806 | GFP_KERNEL); | 952 | GFP_KERNEL); |
807 | if (r) | 953 | if (r) |
808 | goto release_sg; | 954 | goto release_sg; |
809 | 955 | ||
956 | /* Map SG to device */ | ||
810 | r = -ENOMEM; | 957 | r = -ENOMEM; |
811 | nents = dma_map_sg(adev->dev, ttm->sg->sgl, ttm->sg->nents, direction); | 958 | nents = dma_map_sg(adev->dev, ttm->sg->sgl, ttm->sg->nents, direction); |
812 | if (nents != ttm->sg->nents) | 959 | if (nents != ttm->sg->nents) |
813 | goto release_sg; | 960 | goto release_sg; |
814 | 961 | ||
962 | /* convert SG to linear array of pages and dma addresses */ | ||
815 | drm_prime_sg_to_page_addr_arrays(ttm->sg, ttm->pages, | 963 | drm_prime_sg_to_page_addr_arrays(ttm->sg, ttm->pages, |
816 | gtt->ttm.dma_address, ttm->num_pages); | 964 | gtt->ttm.dma_address, ttm->num_pages); |
817 | 965 | ||
@@ -822,6 +970,9 @@ release_sg: | |||
822 | return r; | 970 | return r; |
823 | } | 971 | } |
824 | 972 | ||
973 | /** | ||
974 | * amdgpu_ttm_tt_unpin_userptr - Unpin and unmap userptr pages | ||
975 | */ | ||
825 | static void amdgpu_ttm_tt_unpin_userptr(struct ttm_tt *ttm) | 976 | static void amdgpu_ttm_tt_unpin_userptr(struct ttm_tt *ttm) |
826 | { | 977 | { |
827 | struct amdgpu_device *adev = amdgpu_ttm_adev(ttm->bdev); | 978 | struct amdgpu_device *adev = amdgpu_ttm_adev(ttm->bdev); |
@@ -835,9 +986,10 @@ static void amdgpu_ttm_tt_unpin_userptr(struct ttm_tt *ttm) | |||
835 | if (!ttm->sg->sgl) | 986 | if (!ttm->sg->sgl) |
836 | return; | 987 | return; |
837 | 988 | ||
838 | /* free the sg table and pages again */ | 989 | /* unmap the pages mapped to the device */ |
839 | dma_unmap_sg(adev->dev, ttm->sg->sgl, ttm->sg->nents, direction); | 990 | dma_unmap_sg(adev->dev, ttm->sg->sgl, ttm->sg->nents, direction); |
840 | 991 | ||
992 | /* mark the pages as dirty */ | ||
841 | amdgpu_ttm_tt_mark_user_pages(ttm); | 993 | amdgpu_ttm_tt_mark_user_pages(ttm); |
842 | 994 | ||
843 | sg_free_table(ttm->sg); | 995 | sg_free_table(ttm->sg); |
@@ -882,6 +1034,12 @@ gart_bind_fail: | |||
882 | return r; | 1034 | return r; |
883 | } | 1035 | } |
884 | 1036 | ||
1037 | /** | ||
1038 | * amdgpu_ttm_backend_bind - Bind GTT memory | ||
1039 | * | ||
1040 | * Called by ttm_tt_bind() on behalf of ttm_bo_handle_move_mem(). | ||
1041 | * This handles binding GTT memory to the device address space. | ||
1042 | */ | ||
885 | static int amdgpu_ttm_backend_bind(struct ttm_tt *ttm, | 1043 | static int amdgpu_ttm_backend_bind(struct ttm_tt *ttm, |
886 | struct ttm_mem_reg *bo_mem) | 1044 | struct ttm_mem_reg *bo_mem) |
887 | { | 1045 | { |
@@ -912,7 +1070,10 @@ static int amdgpu_ttm_backend_bind(struct ttm_tt *ttm, | |||
912 | return 0; | 1070 | return 0; |
913 | } | 1071 | } |
914 | 1072 | ||
1073 | /* compute PTE flags relevant to this BO memory */ | ||
915 | flags = amdgpu_ttm_tt_pte_flags(adev, ttm, bo_mem); | 1074 | flags = amdgpu_ttm_tt_pte_flags(adev, ttm, bo_mem); |
1075 | |||
1076 | /* bind pages into GART page tables */ | ||
916 | gtt->offset = (u64)bo_mem->start << PAGE_SHIFT; | 1077 | gtt->offset = (u64)bo_mem->start << PAGE_SHIFT; |
917 | r = amdgpu_gart_bind(adev, gtt->offset, ttm->num_pages, | 1078 | r = amdgpu_gart_bind(adev, gtt->offset, ttm->num_pages, |
918 | ttm->pages, gtt->ttm.dma_address, flags); | 1079 | ttm->pages, gtt->ttm.dma_address, flags); |
@@ -923,6 +1084,9 @@ static int amdgpu_ttm_backend_bind(struct ttm_tt *ttm, | |||
923 | return r; | 1084 | return r; |
924 | } | 1085 | } |
925 | 1086 | ||
1087 | /** | ||
1088 | * amdgpu_ttm_alloc_gart - Allocate GART memory for buffer object | ||
1089 | */ | ||
926 | int amdgpu_ttm_alloc_gart(struct ttm_buffer_object *bo) | 1090 | int amdgpu_ttm_alloc_gart(struct ttm_buffer_object *bo) |
927 | { | 1091 | { |
928 | struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev); | 1092 | struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev); |
@@ -938,6 +1102,7 @@ int amdgpu_ttm_alloc_gart(struct ttm_buffer_object *bo) | |||
938 | amdgpu_gtt_mgr_has_gart_addr(&bo->mem)) | 1102 | amdgpu_gtt_mgr_has_gart_addr(&bo->mem)) |
939 | return 0; | 1103 | return 0; |
940 | 1104 | ||
1105 | /* allocate GTT space */ | ||
941 | tmp = bo->mem; | 1106 | tmp = bo->mem; |
942 | tmp.mm_node = NULL; | 1107 | tmp.mm_node = NULL; |
943 | placement.num_placement = 1; | 1108 | placement.num_placement = 1; |
@@ -953,7 +1118,10 @@ int amdgpu_ttm_alloc_gart(struct ttm_buffer_object *bo) | |||
953 | if (unlikely(r)) | 1118 | if (unlikely(r)) |
954 | return r; | 1119 | return r; |
955 | 1120 | ||
1121 | /* compute PTE flags for this buffer object */ | ||
956 | flags = amdgpu_ttm_tt_pte_flags(adev, bo->ttm, &tmp); | 1122 | flags = amdgpu_ttm_tt_pte_flags(adev, bo->ttm, &tmp); |
1123 | |||
1124 | /* Bind pages */ | ||
957 | gtt->offset = (u64)tmp.start << PAGE_SHIFT; | 1125 | gtt->offset = (u64)tmp.start << PAGE_SHIFT; |
958 | r = amdgpu_ttm_gart_bind(adev, bo, flags); | 1126 | r = amdgpu_ttm_gart_bind(adev, bo, flags); |
959 | if (unlikely(r)) { | 1127 | if (unlikely(r)) { |
@@ -969,6 +1137,12 @@ int amdgpu_ttm_alloc_gart(struct ttm_buffer_object *bo) | |||
969 | return 0; | 1137 | return 0; |
970 | } | 1138 | } |
971 | 1139 | ||
1140 | /** | ||
1141 | * amdgpu_ttm_recover_gart - Rebind GTT pages | ||
1142 | * | ||
1143 | * Called by amdgpu_gtt_mgr_recover() from amdgpu_device_reset() to | ||
1144 | * rebind GTT pages during a GPU reset. | ||
1145 | */ | ||
972 | int amdgpu_ttm_recover_gart(struct ttm_buffer_object *tbo) | 1146 | int amdgpu_ttm_recover_gart(struct ttm_buffer_object *tbo) |
973 | { | 1147 | { |
974 | struct amdgpu_device *adev = amdgpu_ttm_adev(tbo->bdev); | 1148 | struct amdgpu_device *adev = amdgpu_ttm_adev(tbo->bdev); |
@@ -984,12 +1158,19 @@ int amdgpu_ttm_recover_gart(struct ttm_buffer_object *tbo) | |||
984 | return r; | 1158 | return r; |
985 | } | 1159 | } |
986 | 1160 | ||
1161 | /** | ||
1162 | * amdgpu_ttm_backend_unbind - Unbind GTT mapped pages | ||
1163 | * | ||
1164 | * Called by ttm_tt_unbind() on behalf of ttm_bo_move_ttm() and | ||
1165 | * ttm_tt_destroy(). | ||
1166 | */ | ||
987 | static int amdgpu_ttm_backend_unbind(struct ttm_tt *ttm) | 1167 | static int amdgpu_ttm_backend_unbind(struct ttm_tt *ttm) |
988 | { | 1168 | { |
989 | struct amdgpu_device *adev = amdgpu_ttm_adev(ttm->bdev); | 1169 | struct amdgpu_device *adev = amdgpu_ttm_adev(ttm->bdev); |
990 | struct amdgpu_ttm_tt *gtt = (void *)ttm; | 1170 | struct amdgpu_ttm_tt *gtt = (void *)ttm; |
991 | int r; | 1171 | int r; |
992 | 1172 | ||
1173 | /* if the pages have userptr pinning then clear that first */ | ||
993 | if (gtt->userptr) | 1174 | if (gtt->userptr) |
994 | amdgpu_ttm_tt_unpin_userptr(ttm); | 1175 | amdgpu_ttm_tt_unpin_userptr(ttm); |
995 | 1176 | ||
@@ -1021,6 +1202,13 @@ static struct ttm_backend_func amdgpu_backend_func = { | |||
1021 | .destroy = &amdgpu_ttm_backend_destroy, | 1202 | .destroy = &amdgpu_ttm_backend_destroy, |
1022 | }; | 1203 | }; |
1023 | 1204 | ||
1205 | /** | ||
1206 | * amdgpu_ttm_tt_create - Create a ttm_tt object for a given BO | ||
1207 | * | ||
1208 | * @bo: The buffer object to create a GTT ttm_tt object around | ||
1209 | * | ||
1210 | * Called by ttm_tt_create(). | ||
1211 | */ | ||
1024 | static struct ttm_tt *amdgpu_ttm_tt_create(struct ttm_buffer_object *bo, | 1212 | static struct ttm_tt *amdgpu_ttm_tt_create(struct ttm_buffer_object *bo, |
1025 | uint32_t page_flags) | 1213 | uint32_t page_flags) |
1026 | { | 1214 | { |
@@ -1034,6 +1222,8 @@ static struct ttm_tt *amdgpu_ttm_tt_create(struct ttm_buffer_object *bo, | |||
1034 | return NULL; | 1222 | return NULL; |
1035 | } | 1223 | } |
1036 | gtt->ttm.ttm.func = &amdgpu_backend_func; | 1224 | gtt->ttm.ttm.func = &amdgpu_backend_func; |
1225 | |||
1226 | /* allocate space for the uninitialized page entries */ | ||
1037 | if (ttm_sg_tt_init(>t->ttm, bo, page_flags)) { | 1227 | if (ttm_sg_tt_init(>t->ttm, bo, page_flags)) { |
1038 | kfree(gtt); | 1228 | kfree(gtt); |
1039 | return NULL; | 1229 | return NULL; |
@@ -1041,6 +1231,12 @@ static struct ttm_tt *amdgpu_ttm_tt_create(struct ttm_buffer_object *bo, | |||
1041 | return >t->ttm.ttm; | 1231 | return >t->ttm.ttm; |
1042 | } | 1232 | } |
1043 | 1233 | ||
1234 | /** | ||
1235 | * amdgpu_ttm_tt_populate - Map GTT pages visible to the device | ||
1236 | * | ||
1237 | * Map the pages of a ttm_tt object to an address space visible | ||
1238 | * to the underlying device. | ||
1239 | */ | ||
1044 | static int amdgpu_ttm_tt_populate(struct ttm_tt *ttm, | 1240 | static int amdgpu_ttm_tt_populate(struct ttm_tt *ttm, |
1045 | struct ttm_operation_ctx *ctx) | 1241 | struct ttm_operation_ctx *ctx) |
1046 | { | 1242 | { |
@@ -1048,6 +1244,7 @@ static int amdgpu_ttm_tt_populate(struct ttm_tt *ttm, | |||
1048 | struct amdgpu_ttm_tt *gtt = (void *)ttm; | 1244 | struct amdgpu_ttm_tt *gtt = (void *)ttm; |
1049 | bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG); | 1245 | bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG); |
1050 | 1246 | ||
1247 | /* user pages are bound by amdgpu_ttm_tt_pin_userptr() */ | ||
1051 | if (gtt && gtt->userptr) { | 1248 | if (gtt && gtt->userptr) { |
1052 | ttm->sg = kzalloc(sizeof(struct sg_table), GFP_KERNEL); | 1249 | ttm->sg = kzalloc(sizeof(struct sg_table), GFP_KERNEL); |
1053 | if (!ttm->sg) | 1250 | if (!ttm->sg) |
@@ -1072,9 +1269,17 @@ static int amdgpu_ttm_tt_populate(struct ttm_tt *ttm, | |||
1072 | } | 1269 | } |
1073 | #endif | 1270 | #endif |
1074 | 1271 | ||
1272 | /* fall back to generic helper to populate the page array | ||
1273 | * and map them to the device */ | ||
1075 | return ttm_populate_and_map_pages(adev->dev, >t->ttm, ctx); | 1274 | return ttm_populate_and_map_pages(adev->dev, >t->ttm, ctx); |
1076 | } | 1275 | } |
1077 | 1276 | ||
1277 | /** | ||
1278 | * amdgpu_ttm_tt_unpopulate - unmap GTT pages and unpopulate page arrays | ||
1279 | * | ||
1280 | * Unmaps pages of a ttm_tt object from the device address space and | ||
1281 | * unpopulates the page array backing it. | ||
1282 | */ | ||
1078 | static void amdgpu_ttm_tt_unpopulate(struct ttm_tt *ttm) | 1283 | static void amdgpu_ttm_tt_unpopulate(struct ttm_tt *ttm) |
1079 | { | 1284 | { |
1080 | struct amdgpu_device *adev; | 1285 | struct amdgpu_device *adev; |
@@ -1100,9 +1305,21 @@ static void amdgpu_ttm_tt_unpopulate(struct ttm_tt *ttm) | |||
1100 | } | 1305 | } |
1101 | #endif | 1306 | #endif |
1102 | 1307 | ||
1308 | /* fall back to generic helper to unmap and unpopulate array */ | ||
1103 | ttm_unmap_and_unpopulate_pages(adev->dev, >t->ttm); | 1309 | ttm_unmap_and_unpopulate_pages(adev->dev, >t->ttm); |
1104 | } | 1310 | } |
1105 | 1311 | ||
1312 | /** | ||
1313 | * amdgpu_ttm_tt_set_userptr - Initialize userptr GTT ttm_tt | ||
1314 | * for the current task | ||
1315 | * | ||
1316 | * @ttm: The ttm_tt object to bind this userptr object to | ||
1317 | * @addr: The address in the current tasks VM space to use | ||
1318 | * @flags: Requirements of userptr object. | ||
1319 | * | ||
1320 | * Called by amdgpu_gem_userptr_ioctl() to bind userptr pages | ||
1321 | * to current task | ||
1322 | */ | ||
1106 | int amdgpu_ttm_tt_set_userptr(struct ttm_tt *ttm, uint64_t addr, | 1323 | int amdgpu_ttm_tt_set_userptr(struct ttm_tt *ttm, uint64_t addr, |
1107 | uint32_t flags) | 1324 | uint32_t flags) |
1108 | { | 1325 | { |
@@ -1127,6 +1344,9 @@ int amdgpu_ttm_tt_set_userptr(struct ttm_tt *ttm, uint64_t addr, | |||
1127 | return 0; | 1344 | return 0; |
1128 | } | 1345 | } |
1129 | 1346 | ||
1347 | /** | ||
1348 | * amdgpu_ttm_tt_get_usermm - Return memory manager for ttm_tt object | ||
1349 | */ | ||
1130 | struct mm_struct *amdgpu_ttm_tt_get_usermm(struct ttm_tt *ttm) | 1350 | struct mm_struct *amdgpu_ttm_tt_get_usermm(struct ttm_tt *ttm) |
1131 | { | 1351 | { |
1132 | struct amdgpu_ttm_tt *gtt = (void *)ttm; | 1352 | struct amdgpu_ttm_tt *gtt = (void *)ttm; |
@@ -1140,6 +1360,12 @@ struct mm_struct *amdgpu_ttm_tt_get_usermm(struct ttm_tt *ttm) | |||
1140 | return gtt->usertask->mm; | 1360 | return gtt->usertask->mm; |
1141 | } | 1361 | } |
1142 | 1362 | ||
1363 | /** | ||
1364 | * amdgpu_ttm_tt_affect_userptr - Determine if a ttm_tt object lays | ||
1365 | * inside an address range for the | ||
1366 | * current task. | ||
1367 | * | ||
1368 | */ | ||
1143 | bool amdgpu_ttm_tt_affect_userptr(struct ttm_tt *ttm, unsigned long start, | 1369 | bool amdgpu_ttm_tt_affect_userptr(struct ttm_tt *ttm, unsigned long start, |
1144 | unsigned long end) | 1370 | unsigned long end) |
1145 | { | 1371 | { |
@@ -1150,10 +1376,16 @@ bool amdgpu_ttm_tt_affect_userptr(struct ttm_tt *ttm, unsigned long start, | |||
1150 | if (gtt == NULL || !gtt->userptr) | 1376 | if (gtt == NULL || !gtt->userptr) |
1151 | return false; | 1377 | return false; |
1152 | 1378 | ||
1379 | /* Return false if no part of the ttm_tt object lies within | ||
1380 | * the range | ||
1381 | */ | ||
1153 | size = (unsigned long)gtt->ttm.ttm.num_pages * PAGE_SIZE; | 1382 | size = (unsigned long)gtt->ttm.ttm.num_pages * PAGE_SIZE; |
1154 | if (gtt->userptr > end || gtt->userptr + size <= start) | 1383 | if (gtt->userptr > end || gtt->userptr + size <= start) |
1155 | return false; | 1384 | return false; |
1156 | 1385 | ||
1386 | /* Search the lists of tasks that hold this mapping and see | ||
1387 | * if current is one of them. If it is return false. | ||
1388 | */ | ||
1157 | spin_lock(>t->guptasklock); | 1389 | spin_lock(>t->guptasklock); |
1158 | list_for_each_entry(entry, >t->guptasks, list) { | 1390 | list_for_each_entry(entry, >t->guptasks, list) { |
1159 | if (entry->task == current) { | 1391 | if (entry->task == current) { |
@@ -1168,6 +1400,10 @@ bool amdgpu_ttm_tt_affect_userptr(struct ttm_tt *ttm, unsigned long start, | |||
1168 | return true; | 1400 | return true; |
1169 | } | 1401 | } |
1170 | 1402 | ||
1403 | /** | ||
1404 | * amdgpu_ttm_tt_userptr_invalidated - Has the ttm_tt object been | ||
1405 | * invalidated? | ||
1406 | */ | ||
1171 | bool amdgpu_ttm_tt_userptr_invalidated(struct ttm_tt *ttm, | 1407 | bool amdgpu_ttm_tt_userptr_invalidated(struct ttm_tt *ttm, |
1172 | int *last_invalidated) | 1408 | int *last_invalidated) |
1173 | { | 1409 | { |
@@ -1178,6 +1414,12 @@ bool amdgpu_ttm_tt_userptr_invalidated(struct ttm_tt *ttm, | |||
1178 | return prev_invalidated != *last_invalidated; | 1414 | return prev_invalidated != *last_invalidated; |
1179 | } | 1415 | } |
1180 | 1416 | ||
1417 | /** | ||
1418 | * amdgpu_ttm_tt_userptr_needs_pages - Have the pages backing this | ||
1419 | * ttm_tt object been invalidated | ||
1420 | * since the last time they've | ||
1421 | * been set? | ||
1422 | */ | ||
1181 | bool amdgpu_ttm_tt_userptr_needs_pages(struct ttm_tt *ttm) | 1423 | bool amdgpu_ttm_tt_userptr_needs_pages(struct ttm_tt *ttm) |
1182 | { | 1424 | { |
1183 | struct amdgpu_ttm_tt *gtt = (void *)ttm; | 1425 | struct amdgpu_ttm_tt *gtt = (void *)ttm; |
@@ -1188,6 +1430,9 @@ bool amdgpu_ttm_tt_userptr_needs_pages(struct ttm_tt *ttm) | |||
1188 | return atomic_read(>t->mmu_invalidations) != gtt->last_set_pages; | 1430 | return atomic_read(>t->mmu_invalidations) != gtt->last_set_pages; |
1189 | } | 1431 | } |
1190 | 1432 | ||
1433 | /** | ||
1434 | * amdgpu_ttm_tt_is_readonly - Is the ttm_tt object read only? | ||
1435 | */ | ||
1191 | bool amdgpu_ttm_tt_is_readonly(struct ttm_tt *ttm) | 1436 | bool amdgpu_ttm_tt_is_readonly(struct ttm_tt *ttm) |
1192 | { | 1437 | { |
1193 | struct amdgpu_ttm_tt *gtt = (void *)ttm; | 1438 | struct amdgpu_ttm_tt *gtt = (void *)ttm; |
@@ -1198,6 +1443,12 @@ bool amdgpu_ttm_tt_is_readonly(struct ttm_tt *ttm) | |||
1198 | return !!(gtt->userflags & AMDGPU_GEM_USERPTR_READONLY); | 1443 | return !!(gtt->userflags & AMDGPU_GEM_USERPTR_READONLY); |
1199 | } | 1444 | } |
1200 | 1445 | ||
1446 | /** | ||
1447 | * amdgpu_ttm_tt_pte_flags - Compute PTE flags for ttm_tt object | ||
1448 | * | ||
1449 | * @ttm: The ttm_tt object to compute the flags for | ||
1450 | * @mem: The memory registry backing this ttm_tt object | ||
1451 | */ | ||
1201 | uint64_t amdgpu_ttm_tt_pte_flags(struct amdgpu_device *adev, struct ttm_tt *ttm, | 1452 | uint64_t amdgpu_ttm_tt_pte_flags(struct amdgpu_device *adev, struct ttm_tt *ttm, |
1202 | struct ttm_mem_reg *mem) | 1453 | struct ttm_mem_reg *mem) |
1203 | { | 1454 | { |
@@ -1222,6 +1473,16 @@ uint64_t amdgpu_ttm_tt_pte_flags(struct amdgpu_device *adev, struct ttm_tt *ttm, | |||
1222 | return flags; | 1473 | return flags; |
1223 | } | 1474 | } |
1224 | 1475 | ||
1476 | /** | ||
1477 | * amdgpu_ttm_bo_eviction_valuable - Check to see if we can evict | ||
1478 | * a buffer object. | ||
1479 | * | ||
1480 | * Return true if eviction is sensible. Called by | ||
1481 | * ttm_mem_evict_first() on behalf of ttm_bo_mem_force_space() | ||
1482 | * which tries to evict buffer objects until it can find space | ||
1483 | * for a new object and by ttm_bo_force_list_clean() which is | ||
1484 | * used to clean out a memory space. | ||
1485 | */ | ||
1225 | static bool amdgpu_ttm_bo_eviction_valuable(struct ttm_buffer_object *bo, | 1486 | static bool amdgpu_ttm_bo_eviction_valuable(struct ttm_buffer_object *bo, |
1226 | const struct ttm_place *place) | 1487 | const struct ttm_place *place) |
1227 | { | 1488 | { |
@@ -1268,6 +1529,19 @@ static bool amdgpu_ttm_bo_eviction_valuable(struct ttm_buffer_object *bo, | |||
1268 | return ttm_bo_eviction_valuable(bo, place); | 1529 | return ttm_bo_eviction_valuable(bo, place); |
1269 | } | 1530 | } |
1270 | 1531 | ||
1532 | /** | ||
1533 | * amdgpu_ttm_access_memory - Read or Write memory that backs a | ||
1534 | * buffer object. | ||
1535 | * | ||
1536 | * @bo: The buffer object to read/write | ||
1537 | * @offset: Offset into buffer object | ||
1538 | * @buf: Secondary buffer to write/read from | ||
1539 | * @len: Length in bytes of access | ||
1540 | * @write: true if writing | ||
1541 | * | ||
1542 | * This is used to access VRAM that backs a buffer object via MMIO | ||
1543 | * access for debugging purposes. | ||
1544 | */ | ||
1271 | static int amdgpu_ttm_access_memory(struct ttm_buffer_object *bo, | 1545 | static int amdgpu_ttm_access_memory(struct ttm_buffer_object *bo, |
1272 | unsigned long offset, | 1546 | unsigned long offset, |
1273 | void *buf, int len, int write) | 1547 | void *buf, int len, int write) |
@@ -1444,13 +1718,22 @@ error_create: | |||
1444 | adev->fw_vram_usage.reserved_bo = NULL; | 1718 | adev->fw_vram_usage.reserved_bo = NULL; |
1445 | return r; | 1719 | return r; |
1446 | } | 1720 | } |
1447 | 1721 | /** | |
1722 | * amdgpu_ttm_init - Init the memory management (ttm) as well as | ||
1723 | * various gtt/vram related fields. | ||
1724 | * | ||
1725 | * This initializes all of the memory space pools that the TTM layer | ||
1726 | * will need such as the GTT space (system memory mapped to the device), | ||
1727 | * VRAM (on-board memory), and on-chip memories (GDS, GWS, OA) which | ||
1728 | * can be mapped per VMID. | ||
1729 | */ | ||
1448 | int amdgpu_ttm_init(struct amdgpu_device *adev) | 1730 | int amdgpu_ttm_init(struct amdgpu_device *adev) |
1449 | { | 1731 | { |
1450 | uint64_t gtt_size; | 1732 | uint64_t gtt_size; |
1451 | int r; | 1733 | int r; |
1452 | u64 vis_vram_limit; | 1734 | u64 vis_vram_limit; |
1453 | 1735 | ||
1736 | /* initialize global references for vram/gtt */ | ||
1454 | r = amdgpu_ttm_global_init(adev); | 1737 | r = amdgpu_ttm_global_init(adev); |
1455 | if (r) { | 1738 | if (r) { |
1456 | return r; | 1739 | return r; |
@@ -1471,6 +1754,7 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) | |||
1471 | /* We opt to avoid OOM on system pages allocations */ | 1754 | /* We opt to avoid OOM on system pages allocations */ |
1472 | adev->mman.bdev.no_retry = true; | 1755 | adev->mman.bdev.no_retry = true; |
1473 | 1756 | ||
1757 | /* Initialize VRAM pool with all of VRAM divided into pages */ | ||
1474 | r = ttm_bo_init_mm(&adev->mman.bdev, TTM_PL_VRAM, | 1758 | r = ttm_bo_init_mm(&adev->mman.bdev, TTM_PL_VRAM, |
1475 | adev->gmc.real_vram_size >> PAGE_SHIFT); | 1759 | adev->gmc.real_vram_size >> PAGE_SHIFT); |
1476 | if (r) { | 1760 | if (r) { |
@@ -1500,6 +1784,10 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) | |||
1500 | return r; | 1784 | return r; |
1501 | } | 1785 | } |
1502 | 1786 | ||
1787 | /* allocate memory as required for VGA | ||
1788 | * This is used for VGA emulation and pre-OS scanout buffers to | ||
1789 | * avoid display artifacts while transitioning between pre-OS | ||
1790 | * and driver. */ | ||
1503 | if (adev->gmc.stolen_size) { | 1791 | if (adev->gmc.stolen_size) { |
1504 | r = amdgpu_bo_create_kernel(adev, adev->gmc.stolen_size, PAGE_SIZE, | 1792 | r = amdgpu_bo_create_kernel(adev, adev->gmc.stolen_size, PAGE_SIZE, |
1505 | AMDGPU_GEM_DOMAIN_VRAM, | 1793 | AMDGPU_GEM_DOMAIN_VRAM, |
@@ -1511,6 +1799,8 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) | |||
1511 | DRM_INFO("amdgpu: %uM of VRAM memory ready\n", | 1799 | DRM_INFO("amdgpu: %uM of VRAM memory ready\n", |
1512 | (unsigned) (adev->gmc.real_vram_size / (1024 * 1024))); | 1800 | (unsigned) (adev->gmc.real_vram_size / (1024 * 1024))); |
1513 | 1801 | ||
1802 | /* Compute GTT size, either bsaed on 3/4th the size of RAM size | ||
1803 | * or whatever the user passed on module init */ | ||
1514 | if (amdgpu_gtt_size == -1) { | 1804 | if (amdgpu_gtt_size == -1) { |
1515 | struct sysinfo si; | 1805 | struct sysinfo si; |
1516 | 1806 | ||
@@ -1521,6 +1811,8 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) | |||
1521 | } | 1811 | } |
1522 | else | 1812 | else |
1523 | gtt_size = (uint64_t)amdgpu_gtt_size << 20; | 1813 | gtt_size = (uint64_t)amdgpu_gtt_size << 20; |
1814 | |||
1815 | /* Initialize GTT memory pool */ | ||
1524 | r = ttm_bo_init_mm(&adev->mman.bdev, TTM_PL_TT, gtt_size >> PAGE_SHIFT); | 1816 | r = ttm_bo_init_mm(&adev->mman.bdev, TTM_PL_TT, gtt_size >> PAGE_SHIFT); |
1525 | if (r) { | 1817 | if (r) { |
1526 | DRM_ERROR("Failed initializing GTT heap.\n"); | 1818 | DRM_ERROR("Failed initializing GTT heap.\n"); |
@@ -1529,6 +1821,7 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) | |||
1529 | DRM_INFO("amdgpu: %uM of GTT memory ready.\n", | 1821 | DRM_INFO("amdgpu: %uM of GTT memory ready.\n", |
1530 | (unsigned)(gtt_size / (1024 * 1024))); | 1822 | (unsigned)(gtt_size / (1024 * 1024))); |
1531 | 1823 | ||
1824 | /* Initialize various on-chip memory pools */ | ||
1532 | adev->gds.mem.total_size = adev->gds.mem.total_size << AMDGPU_GDS_SHIFT; | 1825 | adev->gds.mem.total_size = adev->gds.mem.total_size << AMDGPU_GDS_SHIFT; |
1533 | adev->gds.mem.gfx_partition_size = adev->gds.mem.gfx_partition_size << AMDGPU_GDS_SHIFT; | 1826 | adev->gds.mem.gfx_partition_size = adev->gds.mem.gfx_partition_size << AMDGPU_GDS_SHIFT; |
1534 | adev->gds.mem.cs_partition_size = adev->gds.mem.cs_partition_size << AMDGPU_GDS_SHIFT; | 1827 | adev->gds.mem.cs_partition_size = adev->gds.mem.cs_partition_size << AMDGPU_GDS_SHIFT; |
@@ -1568,6 +1861,7 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) | |||
1568 | } | 1861 | } |
1569 | } | 1862 | } |
1570 | 1863 | ||
1864 | /* Register debugfs entries for amdgpu_ttm */ | ||
1571 | r = amdgpu_ttm_debugfs_init(adev); | 1865 | r = amdgpu_ttm_debugfs_init(adev); |
1572 | if (r) { | 1866 | if (r) { |
1573 | DRM_ERROR("Failed to init debugfs\n"); | 1867 | DRM_ERROR("Failed to init debugfs\n"); |
@@ -1576,11 +1870,19 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) | |||
1576 | return 0; | 1870 | return 0; |
1577 | } | 1871 | } |
1578 | 1872 | ||
1873 | /** | ||
1874 | * amdgpu_ttm_late_init - Handle any late initialization for | ||
1875 | * amdgpu_ttm | ||
1876 | */ | ||
1579 | void amdgpu_ttm_late_init(struct amdgpu_device *adev) | 1877 | void amdgpu_ttm_late_init(struct amdgpu_device *adev) |
1580 | { | 1878 | { |
1879 | /* return the VGA stolen memory (if any) back to VRAM */ | ||
1581 | amdgpu_bo_free_kernel(&adev->stolen_vga_memory, NULL, NULL); | 1880 | amdgpu_bo_free_kernel(&adev->stolen_vga_memory, NULL, NULL); |
1582 | } | 1881 | } |
1583 | 1882 | ||
1883 | /** | ||
1884 | * amdgpu_ttm_fini - De-initialize the TTM memory pools | ||
1885 | */ | ||
1584 | void amdgpu_ttm_fini(struct amdgpu_device *adev) | 1886 | void amdgpu_ttm_fini(struct amdgpu_device *adev) |
1585 | { | 1887 | { |
1586 | if (!adev->mman.initialized) | 1888 | if (!adev->mman.initialized) |
@@ -1908,6 +2210,11 @@ static const struct drm_info_list amdgpu_ttm_debugfs_list[] = { | |||
1908 | #endif | 2210 | #endif |
1909 | }; | 2211 | }; |
1910 | 2212 | ||
2213 | /** | ||
2214 | * amdgpu_ttm_vram_read - Linear read access to VRAM | ||
2215 | * | ||
2216 | * Accesses VRAM via MMIO for debugging purposes. | ||
2217 | */ | ||
1911 | static ssize_t amdgpu_ttm_vram_read(struct file *f, char __user *buf, | 2218 | static ssize_t amdgpu_ttm_vram_read(struct file *f, char __user *buf, |
1912 | size_t size, loff_t *pos) | 2219 | size_t size, loff_t *pos) |
1913 | { | 2220 | { |
@@ -1947,6 +2254,11 @@ static ssize_t amdgpu_ttm_vram_read(struct file *f, char __user *buf, | |||
1947 | return result; | 2254 | return result; |
1948 | } | 2255 | } |
1949 | 2256 | ||
2257 | /** | ||
2258 | * amdgpu_ttm_vram_write - Linear write access to VRAM | ||
2259 | * | ||
2260 | * Accesses VRAM via MMIO for debugging purposes. | ||
2261 | */ | ||
1950 | static ssize_t amdgpu_ttm_vram_write(struct file *f, const char __user *buf, | 2262 | static ssize_t amdgpu_ttm_vram_write(struct file *f, const char __user *buf, |
1951 | size_t size, loff_t *pos) | 2263 | size_t size, loff_t *pos) |
1952 | { | 2264 | { |
@@ -1995,6 +2307,9 @@ static const struct file_operations amdgpu_ttm_vram_fops = { | |||
1995 | 2307 | ||
1996 | #ifdef CONFIG_DRM_AMDGPU_GART_DEBUGFS | 2308 | #ifdef CONFIG_DRM_AMDGPU_GART_DEBUGFS |
1997 | 2309 | ||
2310 | /** | ||
2311 | * amdgpu_ttm_gtt_read - Linear read access to GTT memory | ||
2312 | */ | ||
1998 | static ssize_t amdgpu_ttm_gtt_read(struct file *f, char __user *buf, | 2313 | static ssize_t amdgpu_ttm_gtt_read(struct file *f, char __user *buf, |
1999 | size_t size, loff_t *pos) | 2314 | size_t size, loff_t *pos) |
2000 | { | 2315 | { |
@@ -2042,6 +2357,13 @@ static const struct file_operations amdgpu_ttm_gtt_fops = { | |||
2042 | 2357 | ||
2043 | #endif | 2358 | #endif |
2044 | 2359 | ||
2360 | /** | ||
2361 | * amdgpu_iomem_read - Virtual read access to GPU mapped memory | ||
2362 | * | ||
2363 | * This function is used to read memory that has been mapped to the | ||
2364 | * GPU and the known addresses are not physical addresses but instead | ||
2365 | * bus addresses (e.g., what you'd put in an IB or ring buffer). | ||
2366 | */ | ||
2045 | static ssize_t amdgpu_iomem_read(struct file *f, char __user *buf, | 2367 | static ssize_t amdgpu_iomem_read(struct file *f, char __user *buf, |
2046 | size_t size, loff_t *pos) | 2368 | size_t size, loff_t *pos) |
2047 | { | 2369 | { |
@@ -2050,6 +2372,7 @@ static ssize_t amdgpu_iomem_read(struct file *f, char __user *buf, | |||
2050 | ssize_t result = 0; | 2372 | ssize_t result = 0; |
2051 | int r; | 2373 | int r; |
2052 | 2374 | ||
2375 | /* retrieve the IOMMU domain if any for this device */ | ||
2053 | dom = iommu_get_domain_for_dev(adev->dev); | 2376 | dom = iommu_get_domain_for_dev(adev->dev); |
2054 | 2377 | ||
2055 | while (size) { | 2378 | while (size) { |
@@ -2062,6 +2385,10 @@ static ssize_t amdgpu_iomem_read(struct file *f, char __user *buf, | |||
2062 | 2385 | ||
2063 | bytes = bytes < size ? bytes : size; | 2386 | bytes = bytes < size ? bytes : size; |
2064 | 2387 | ||
2388 | /* Translate the bus address to a physical address. If | ||
2389 | * the domain is NULL it means there is no IOMMU active | ||
2390 | * and the address translation is the identity | ||
2391 | */ | ||
2065 | addr = dom ? iommu_iova_to_phys(dom, addr) : addr; | 2392 | addr = dom ? iommu_iova_to_phys(dom, addr) : addr; |
2066 | 2393 | ||
2067 | pfn = addr >> PAGE_SHIFT; | 2394 | pfn = addr >> PAGE_SHIFT; |
@@ -2086,6 +2413,13 @@ static ssize_t amdgpu_iomem_read(struct file *f, char __user *buf, | |||
2086 | return result; | 2413 | return result; |
2087 | } | 2414 | } |
2088 | 2415 | ||
2416 | /** | ||
2417 | * amdgpu_iomem_write - Virtual write access to GPU mapped memory | ||
2418 | * | ||
2419 | * This function is used to write memory that has been mapped to the | ||
2420 | * GPU and the known addresses are not physical addresses but instead | ||
2421 | * bus addresses (e.g., what you'd put in an IB or ring buffer). | ||
2422 | */ | ||
2089 | static ssize_t amdgpu_iomem_write(struct file *f, const char __user *buf, | 2423 | static ssize_t amdgpu_iomem_write(struct file *f, const char __user *buf, |
2090 | size_t size, loff_t *pos) | 2424 | size_t size, loff_t *pos) |
2091 | { | 2425 | { |