diff options
author | Christian König <christian.koenig@amd.com> | 2017-09-02 07:21:31 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2017-09-12 14:23:10 -0400 |
commit | a216ab09955d6b77f3af4f0aba9255c5ddf382f5 (patch) | |
tree | 729b38ef0a74fc185972a65116b1b5a8ad900ab5 /drivers/gpu/drm/amd | |
parent | 7a9667ae197460e6c9c3bb432fe68c708fce6259 (diff) |
drm/amdgpu: fix userptr put_page handling
Move calling put_page into the unpopulate callback. Otherwise we mess up the pages
reference count when it is unbound multiple times.
Signed-off-by: Christian König <christian.koenig@amd.com>
Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 14 |
3 files changed, 16 insertions, 5 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 5809f55e0d9d..cc6de0b46326 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h | |||
@@ -1793,6 +1793,7 @@ void amdgpu_cs_report_moved_bytes(struct amdgpu_device *adev, u64 num_bytes, | |||
1793 | void amdgpu_ttm_placement_from_domain(struct amdgpu_bo *abo, u32 domain); | 1793 | void amdgpu_ttm_placement_from_domain(struct amdgpu_bo *abo, u32 domain); |
1794 | bool amdgpu_ttm_bo_is_amdgpu_bo(struct ttm_buffer_object *bo); | 1794 | bool amdgpu_ttm_bo_is_amdgpu_bo(struct ttm_buffer_object *bo); |
1795 | int amdgpu_ttm_tt_get_user_pages(struct ttm_tt *ttm, struct page **pages); | 1795 | int amdgpu_ttm_tt_get_user_pages(struct ttm_tt *ttm, struct page **pages); |
1796 | void amdgpu_ttm_tt_set_user_pages(struct ttm_tt *ttm, struct page **pages); | ||
1796 | int amdgpu_ttm_tt_set_userptr(struct ttm_tt *ttm, uint64_t addr, | 1797 | int amdgpu_ttm_tt_set_userptr(struct ttm_tt *ttm, uint64_t addr, |
1797 | uint32_t flags); | 1798 | uint32_t flags); |
1798 | bool amdgpu_ttm_tt_has_userptr(struct ttm_tt *ttm); | 1799 | bool amdgpu_ttm_tt_has_userptr(struct ttm_tt *ttm); |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 233b6f2f8427..e58db0c69c6a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | |||
@@ -474,10 +474,8 @@ static int amdgpu_cs_list_validate(struct amdgpu_cs_parser *p, | |||
474 | 474 | ||
475 | /* Check if we have user pages and nobody bound the BO already */ | 475 | /* Check if we have user pages and nobody bound the BO already */ |
476 | if (lobj->user_pages && bo->tbo.ttm->state != tt_bound) { | 476 | if (lobj->user_pages && bo->tbo.ttm->state != tt_bound) { |
477 | size_t size = sizeof(struct page *); | 477 | amdgpu_ttm_tt_set_user_pages(bo->tbo.ttm, |
478 | 478 | lobj->user_pages); | |
479 | size *= bo->tbo.ttm->num_pages; | ||
480 | memcpy(bo->tbo.ttm->pages, lobj->user_pages, size); | ||
481 | binding_userptr = true; | 479 | binding_userptr = true; |
482 | } | 480 | } |
483 | 481 | ||
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 841a5699bef0..28e121984332 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | |||
@@ -664,6 +664,18 @@ release_pages: | |||
664 | return r; | 664 | return r; |
665 | } | 665 | } |
666 | 666 | ||
667 | void amdgpu_ttm_tt_set_user_pages(struct ttm_tt *ttm, struct page **pages) | ||
668 | { | ||
669 | unsigned i; | ||
670 | |||
671 | for (i = 0; i < ttm->num_pages; ++i) { | ||
672 | if (ttm->pages[i]) | ||
673 | put_page(ttm->pages[i]); | ||
674 | |||
675 | ttm->pages[i] = pages ? pages[i] : NULL; | ||
676 | } | ||
677 | } | ||
678 | |||
667 | static void amdgpu_trace_dma_map(struct ttm_tt *ttm) | 679 | static void amdgpu_trace_dma_map(struct ttm_tt *ttm) |
668 | { | 680 | { |
669 | struct amdgpu_device *adev = amdgpu_ttm_adev(ttm->bdev); | 681 | struct amdgpu_device *adev = amdgpu_ttm_adev(ttm->bdev); |
@@ -738,7 +750,6 @@ static void amdgpu_ttm_tt_unpin_userptr(struct ttm_tt *ttm) | |||
738 | set_page_dirty(page); | 750 | set_page_dirty(page); |
739 | 751 | ||
740 | mark_page_accessed(page); | 752 | mark_page_accessed(page); |
741 | put_page(page); | ||
742 | } | 753 | } |
743 | 754 | ||
744 | amdgpu_trace_dma_unmap(ttm); | 755 | amdgpu_trace_dma_unmap(ttm); |
@@ -971,6 +982,7 @@ static void amdgpu_ttm_tt_unpopulate(struct ttm_tt *ttm) | |||
971 | bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG); | 982 | bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG); |
972 | 983 | ||
973 | if (gtt && gtt->userptr) { | 984 | if (gtt && gtt->userptr) { |
985 | amdgpu_ttm_tt_set_user_pages(ttm, NULL); | ||
974 | kfree(ttm->sg); | 986 | kfree(ttm->sg); |
975 | ttm->page_flags &= ~TTM_PAGE_FLAG_SG; | 987 | ttm->page_flags &= ~TTM_PAGE_FLAG_SG; |
976 | return; | 988 | return; |