diff options
author | Roger He <Hongbo.He@amd.com> | 2018-01-15 00:06:38 -0500 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2018-01-18 16:07:26 -0500 |
commit | 8f2112f84c3c2acd3fcc8b922e78b6758db902db (patch) | |
tree | 1f5e88f225fa4ae80d976d87333ef881bdba74cc | |
parent | 8159e509203c50d0684483b4311b20e5d40553e8 (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.c | 55 |
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 | ||
65 | enum pool_type { | 66 | enum 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 | */ |
881 | static int ttm_dma_pool_get_pages(struct dma_pool *pool, | 882 | static 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 | ||
905 | static gfp_t ttm_dma_pool_gfp_flags(struct ttm_dma_tt *ttm_dma, bool huge) | 905 | static 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; |