aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoger He <Hongbo.He@amd.com>2018-01-15 00:06:38 -0500
committerAlex Deucher <alexander.deucher@amd.com>2018-01-18 16:07:26 -0500
commit8f2112f84c3c2acd3fcc8b922e78b6758db902db (patch)
tree1f5e88f225fa4ae80d976d87333ef881bdba74cc
parent8159e509203c50d0684483b4311b20e5d40553e8 (diff)
drm/ttm: add VADDR_FLAG_UPDATED_COUNT to correctly update dma_page global count
add this for correctly updating global mem count in ttm_mem_zone. before that when ttm_mem_global_alloc_page fails, we would update all dma_page's global mem count in ttm_dma->pages_list. but actually here we should not update for the last dma_page. v2: only the update of last dma_page is not right v3: use lower bits of dma_page vaddr Signed-off-by: Roger He <Hongbo.He@amd.com> Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r--drivers/gpu/drm/ttm/ttm_page_alloc_dma.c55
1 files changed, 29 insertions, 26 deletions
diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
index c7f01a4d924c..a88051552ace 100644
--- a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
+++ b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
@@ -61,6 +61,7 @@
61#define SMALL_ALLOCATION 4 61#define SMALL_ALLOCATION 4
62#define FREE_ALL_PAGES (~0U) 62#define FREE_ALL_PAGES (~0U)
63#define VADDR_FLAG_HUGE_POOL 1UL 63#define VADDR_FLAG_HUGE_POOL 1UL
64#define VADDR_FLAG_UPDATED_COUNT 2UL
64 65
65enum pool_type { 66enum pool_type {
66 IS_UNDEFINED = 0, 67 IS_UNDEFINED = 0,
@@ -874,18 +875,18 @@ static int ttm_dma_page_pool_fill_locked(struct dma_pool *pool,
874} 875}
875 876
876/* 877/*
877 * @return count of pages still required to fulfill the request.
878 * The populate list is actually a stack (not that is matters as TTM 878 * The populate list is actually a stack (not that is matters as TTM
879 * allocates one page at a time. 879 * allocates one page at a time.
880 * return dma_page pointer if success, otherwise NULL.
880 */ 881 */
881static int ttm_dma_pool_get_pages(struct dma_pool *pool, 882static struct dma_page *ttm_dma_pool_get_pages(struct dma_pool *pool,
882 struct ttm_dma_tt *ttm_dma, 883 struct ttm_dma_tt *ttm_dma,
883 unsigned index) 884 unsigned index)
884{ 885{
885 struct dma_page *d_page; 886 struct dma_page *d_page = NULL;
886 struct ttm_tt *ttm = &ttm_dma->ttm; 887 struct ttm_tt *ttm = &ttm_dma->ttm;
887 unsigned long irq_flags; 888 unsigned long irq_flags;
888 int count, r = -ENOMEM; 889 int count;
889 890
890 spin_lock_irqsave(&pool->lock, irq_flags); 891 spin_lock_irqsave(&pool->lock, irq_flags);
891 count = ttm_dma_page_pool_fill_locked(pool, &irq_flags); 892 count = ttm_dma_page_pool_fill_locked(pool, &irq_flags);
@@ -894,12 +895,11 @@ static int ttm_dma_pool_get_pages(struct dma_pool *pool,
894 ttm->pages[index] = d_page->p; 895 ttm->pages[index] = d_page->p;
895 ttm_dma->dma_address[index] = d_page->dma; 896 ttm_dma->dma_address[index] = d_page->dma;
896 list_move_tail(&d_page->page_list, &ttm_dma->pages_list); 897 list_move_tail(&d_page->page_list, &ttm_dma->pages_list);
897 r = 0;
898 pool->npages_in_use += 1; 898 pool->npages_in_use += 1;
899 pool->npages_free -= 1; 899 pool->npages_free -= 1;
900 } 900 }
901 spin_unlock_irqrestore(&pool->lock, irq_flags); 901 spin_unlock_irqrestore(&pool->lock, irq_flags);
902 return r; 902 return d_page;
903} 903}
904 904
905static gfp_t ttm_dma_pool_gfp_flags(struct ttm_dma_tt *ttm_dma, bool huge) 905static gfp_t ttm_dma_pool_gfp_flags(struct ttm_dma_tt *ttm_dma, bool huge)
@@ -934,6 +934,7 @@ int ttm_dma_populate(struct ttm_dma_tt *ttm_dma, struct device *dev,
934 struct ttm_mem_global *mem_glob = ttm->glob->mem_glob; 934 struct ttm_mem_global *mem_glob = ttm->glob->mem_glob;
935 unsigned long num_pages = ttm->num_pages; 935 unsigned long num_pages = ttm->num_pages;
936 struct dma_pool *pool; 936 struct dma_pool *pool;
937 struct dma_page *d_page;
937 enum pool_type type; 938 enum pool_type type;
938 unsigned i; 939 unsigned i;
939 int ret; 940 int ret;
@@ -962,8 +963,8 @@ int ttm_dma_populate(struct ttm_dma_tt *ttm_dma, struct device *dev,
962 while (num_pages >= HPAGE_PMD_NR) { 963 while (num_pages >= HPAGE_PMD_NR) {
963 unsigned j; 964 unsigned j;
964 965
965 ret = ttm_dma_pool_get_pages(pool, ttm_dma, i); 966 d_page = ttm_dma_pool_get_pages(pool, ttm_dma, i);
966 if (ret != 0) 967 if (!d_page)
967 break; 968 break;
968 969
969 ret = ttm_mem_global_alloc_page(mem_glob, ttm->pages[i], 970 ret = ttm_mem_global_alloc_page(mem_glob, ttm->pages[i],
@@ -973,6 +974,7 @@ int ttm_dma_populate(struct ttm_dma_tt *ttm_dma, struct device *dev,
973 return -ENOMEM; 974 return -ENOMEM;
974 } 975 }
975 976
977 d_page->vaddr |= VADDR_FLAG_UPDATED_COUNT;
976 for (j = i + 1; j < (i + HPAGE_PMD_NR); ++j) { 978 for (j = i + 1; j < (i + HPAGE_PMD_NR); ++j) {
977 ttm->pages[j] = ttm->pages[j - 1] + 1; 979 ttm->pages[j] = ttm->pages[j - 1] + 1;
978 ttm_dma->dma_address[j] = ttm_dma->dma_address[j - 1] + 980 ttm_dma->dma_address[j] = ttm_dma->dma_address[j - 1] +
@@ -996,8 +998,8 @@ skip_huge:
996 } 998 }
997 999
998 while (num_pages) { 1000 while (num_pages) {
999 ret = ttm_dma_pool_get_pages(pool, ttm_dma, i); 1001 d_page = ttm_dma_pool_get_pages(pool, ttm_dma, i);
1000 if (ret != 0) { 1002 if (!d_page) {
1001 ttm_dma_unpopulate(ttm_dma, dev); 1003 ttm_dma_unpopulate(ttm_dma, dev);
1002 return -ENOMEM; 1004 return -ENOMEM;
1003 } 1005 }
@@ -1009,6 +1011,7 @@ skip_huge:
1009 return -ENOMEM; 1011 return -ENOMEM;
1010 } 1012 }
1011 1013
1014 d_page->vaddr |= VADDR_FLAG_UPDATED_COUNT;
1012 ++i; 1015 ++i;
1013 --num_pages; 1016 --num_pages;
1014 } 1017 }
@@ -1049,8 +1052,11 @@ void ttm_dma_unpopulate(struct ttm_dma_tt *ttm_dma, struct device *dev)
1049 continue; 1052 continue;
1050 1053
1051 count++; 1054 count++;
1052 ttm_mem_global_free_page(ttm->glob->mem_glob, 1055 if (d_page->vaddr & VADDR_FLAG_UPDATED_COUNT) {
1053 d_page->p, pool->size); 1056 ttm_mem_global_free_page(ttm->glob->mem_glob,
1057 d_page->p, pool->size);
1058 d_page->vaddr &= ~VADDR_FLAG_UPDATED_COUNT;
1059 }
1054 ttm_dma_page_put(pool, d_page); 1060 ttm_dma_page_put(pool, d_page);
1055 } 1061 }
1056 1062
@@ -1070,9 +1076,19 @@ void ttm_dma_unpopulate(struct ttm_dma_tt *ttm_dma, struct device *dev)
1070 1076
1071 /* make sure pages array match list and count number of pages */ 1077 /* make sure pages array match list and count number of pages */
1072 count = 0; 1078 count = 0;
1073 list_for_each_entry(d_page, &ttm_dma->pages_list, page_list) { 1079 list_for_each_entry_safe(d_page, next, &ttm_dma->pages_list,
1080 page_list) {
1074 ttm->pages[count] = d_page->p; 1081 ttm->pages[count] = d_page->p;
1075 count++; 1082 count++;
1083
1084 if (d_page->vaddr & VADDR_FLAG_UPDATED_COUNT) {
1085 ttm_mem_global_free_page(ttm->glob->mem_glob,
1086 d_page->p, pool->size);
1087 d_page->vaddr &= ~VADDR_FLAG_UPDATED_COUNT;
1088 }
1089
1090 if (is_cached)
1091 ttm_dma_page_put(pool, d_page);
1076 } 1092 }
1077 1093
1078 spin_lock_irqsave(&pool->lock, irq_flags); 1094 spin_lock_irqsave(&pool->lock, irq_flags);
@@ -1092,19 +1108,6 @@ void ttm_dma_unpopulate(struct ttm_dma_tt *ttm_dma, struct device *dev)
1092 } 1108 }
1093 spin_unlock_irqrestore(&pool->lock, irq_flags); 1109 spin_unlock_irqrestore(&pool->lock, irq_flags);
1094 1110
1095 if (is_cached) {
1096 list_for_each_entry_safe(d_page, next, &ttm_dma->pages_list, page_list) {
1097 ttm_mem_global_free_page(ttm->glob->mem_glob,
1098 d_page->p, pool->size);
1099 ttm_dma_page_put(pool, d_page);
1100 }
1101 } else {
1102 for (i = 0; i < count; i++) {
1103 ttm_mem_global_free_page(ttm->glob->mem_glob,
1104 ttm->pages[i], pool->size);
1105 }
1106 }
1107
1108 INIT_LIST_HEAD(&ttm_dma->pages_list); 1111 INIT_LIST_HEAD(&ttm_dma->pages_list);
1109 for (i = 0; i < ttm->num_pages; i++) { 1112 for (i = 0; i < ttm->num_pages; i++) {
1110 ttm->pages[i] = NULL; 1113 ttm->pages[i] = NULL;