aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorChristian König <christian.koenig@amd.com>2017-10-05 08:27:34 -0400
committerAlex Deucher <alexander.deucher@amd.com>2017-10-19 15:27:02 -0400
commit6ed4e2e673d348df6623012a628a8ab8624e3222 (patch)
tree473b06c3130fc33b8be9c3505c0a6e1b573ee736 /drivers/gpu
parent8593e9b85e0aa67db62ec395774021a139efc2cd (diff)
drm/ttm: add transparent huge page support for wc or uc allocations v2
Add a new huge page pool and try to allocate from it when it makes sense. v2: avoid compound pages for now Signed-off-by: Christian König <christian.koenig@amd.com> Acked-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/ttm/ttm_page_alloc.c136
1 files changed, 109 insertions, 27 deletions
diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c b/drivers/gpu/drm/ttm/ttm_page_alloc.c
index 39747326bf3e..b6f16e7ffff3 100644
--- a/drivers/gpu/drm/ttm/ttm_page_alloc.c
+++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c
@@ -95,7 +95,7 @@ struct ttm_pool_opts {
95 unsigned small; 95 unsigned small;
96}; 96};
97 97
98#define NUM_POOLS 4 98#define NUM_POOLS 6
99 99
100/** 100/**
101 * struct ttm_pool_manager - Holds memory pools for fst allocation 101 * struct ttm_pool_manager - Holds memory pools for fst allocation
@@ -122,6 +122,8 @@ struct ttm_pool_manager {
122 struct ttm_page_pool uc_pool; 122 struct ttm_page_pool uc_pool;
123 struct ttm_page_pool wc_pool_dma32; 123 struct ttm_page_pool wc_pool_dma32;
124 struct ttm_page_pool uc_pool_dma32; 124 struct ttm_page_pool uc_pool_dma32;
125 struct ttm_page_pool wc_pool_huge;
126 struct ttm_page_pool uc_pool_huge;
125 } ; 127 } ;
126 }; 128 };
127}; 129};
@@ -256,8 +258,8 @@ static int set_pages_array_uc(struct page **pages, int addrinarray)
256 258
257/** 259/**
258 * Select the right pool or requested caching state and ttm flags. */ 260 * Select the right pool or requested caching state and ttm flags. */
259static struct ttm_page_pool *ttm_get_pool(int flags, 261static struct ttm_page_pool *ttm_get_pool(int flags, bool huge,
260 enum ttm_caching_state cstate) 262 enum ttm_caching_state cstate)
261{ 263{
262 int pool_index; 264 int pool_index;
263 265
@@ -269,9 +271,15 @@ static struct ttm_page_pool *ttm_get_pool(int flags,
269 else 271 else
270 pool_index = 0x1; 272 pool_index = 0x1;
271 273
272 if (flags & TTM_PAGE_FLAG_DMA32) 274 if (flags & TTM_PAGE_FLAG_DMA32) {
275 if (huge)
276 return NULL;
273 pool_index |= 0x2; 277 pool_index |= 0x2;
274 278
279 } else if (huge) {
280 pool_index |= 0x4;
281 }
282
275 return &_manager->pools[pool_index]; 283 return &_manager->pools[pool_index];
276} 284}
277 285
@@ -494,12 +502,14 @@ static void ttm_handle_caching_state_failure(struct list_head *pages,
494 * pages returned in pages array. 502 * pages returned in pages array.
495 */ 503 */
496static int ttm_alloc_new_pages(struct list_head *pages, gfp_t gfp_flags, 504static int ttm_alloc_new_pages(struct list_head *pages, gfp_t gfp_flags,
497 int ttm_flags, enum ttm_caching_state cstate, unsigned count) 505 int ttm_flags, enum ttm_caching_state cstate,
506 unsigned count, unsigned order)
498{ 507{
499 struct page **caching_array; 508 struct page **caching_array;
500 struct page *p; 509 struct page *p;
501 int r = 0; 510 int r = 0;
502 unsigned i, cpages; 511 unsigned i, j, cpages;
512 unsigned npages = 1 << order;
503 unsigned max_cpages = min(count, 513 unsigned max_cpages = min(count,
504 (unsigned)(PAGE_SIZE/sizeof(struct page *))); 514 (unsigned)(PAGE_SIZE/sizeof(struct page *)));
505 515
@@ -512,7 +522,7 @@ static int ttm_alloc_new_pages(struct list_head *pages, gfp_t gfp_flags,
512 } 522 }
513 523
514 for (i = 0, cpages = 0; i < count; ++i) { 524 for (i = 0, cpages = 0; i < count; ++i) {
515 p = alloc_page(gfp_flags); 525 p = alloc_pages(gfp_flags, order);
516 526
517 if (!p) { 527 if (!p) {
518 pr_err("Unable to get page %u\n", i); 528 pr_err("Unable to get page %u\n", i);
@@ -531,14 +541,18 @@ static int ttm_alloc_new_pages(struct list_head *pages, gfp_t gfp_flags,
531 goto out; 541 goto out;
532 } 542 }
533 543
544 list_add(&p->lru, pages);
545
534#ifdef CONFIG_HIGHMEM 546#ifdef CONFIG_HIGHMEM
535 /* gfp flags of highmem page should never be dma32 so we 547 /* gfp flags of highmem page should never be dma32 so we
536 * we should be fine in such case 548 * we should be fine in such case
537 */ 549 */
538 if (!PageHighMem(p)) 550 if (PageHighMem(p))
551 continue;
552
539#endif 553#endif
540 { 554 for (j = 0; j < npages; ++j) {
541 caching_array[cpages++] = p; 555 caching_array[cpages++] = p++;
542 if (cpages == max_cpages) { 556 if (cpages == max_cpages) {
543 557
544 r = ttm_set_pages_caching(caching_array, 558 r = ttm_set_pages_caching(caching_array,
@@ -552,8 +566,6 @@ static int ttm_alloc_new_pages(struct list_head *pages, gfp_t gfp_flags,
552 cpages = 0; 566 cpages = 0;
553 } 567 }
554 } 568 }
555
556 list_add(&p->lru, pages);
557 } 569 }
558 570
559 if (cpages) { 571 if (cpages) {
@@ -573,9 +585,9 @@ out:
573 * Fill the given pool if there aren't enough pages and the requested number of 585 * Fill the given pool if there aren't enough pages and the requested number of
574 * pages is small. 586 * pages is small.
575 */ 587 */
576static void ttm_page_pool_fill_locked(struct ttm_page_pool *pool, 588static void ttm_page_pool_fill_locked(struct ttm_page_pool *pool, int ttm_flags,
577 int ttm_flags, enum ttm_caching_state cstate, unsigned count, 589 enum ttm_caching_state cstate,
578 unsigned long *irq_flags) 590 unsigned count, unsigned long *irq_flags)
579{ 591{
580 struct page *p; 592 struct page *p;
581 int r; 593 int r;
@@ -605,7 +617,7 @@ static void ttm_page_pool_fill_locked(struct ttm_page_pool *pool,
605 617
606 INIT_LIST_HEAD(&new_pages); 618 INIT_LIST_HEAD(&new_pages);
607 r = ttm_alloc_new_pages(&new_pages, pool->gfp_flags, ttm_flags, 619 r = ttm_alloc_new_pages(&new_pages, pool->gfp_flags, ttm_flags,
608 cstate, alloc_size); 620 cstate, alloc_size, 0);
609 spin_lock_irqsave(&pool->lock, *irq_flags); 621 spin_lock_irqsave(&pool->lock, *irq_flags);
610 622
611 if (!r) { 623 if (!r) {
@@ -635,7 +647,7 @@ static int ttm_page_pool_get_pages(struct ttm_page_pool *pool,
635 struct list_head *pages, 647 struct list_head *pages,
636 int ttm_flags, 648 int ttm_flags,
637 enum ttm_caching_state cstate, 649 enum ttm_caching_state cstate,
638 unsigned count) 650 unsigned count, unsigned order)
639{ 651{
640 unsigned long irq_flags; 652 unsigned long irq_flags;
641 struct list_head *p; 653 struct list_head *p;
@@ -643,7 +655,9 @@ static int ttm_page_pool_get_pages(struct ttm_page_pool *pool,
643 int r = 0; 655 int r = 0;
644 656
645 spin_lock_irqsave(&pool->lock, irq_flags); 657 spin_lock_irqsave(&pool->lock, irq_flags);
646 ttm_page_pool_fill_locked(pool, ttm_flags, cstate, count, &irq_flags); 658 if (!order)
659 ttm_page_pool_fill_locked(pool, ttm_flags, cstate, count,
660 &irq_flags);
647 661
648 if (count >= pool->npages) { 662 if (count >= pool->npages) {
649 /* take all pages from the pool */ 663 /* take all pages from the pool */
@@ -698,7 +712,7 @@ out:
698 * multiple requests in parallel. 712 * multiple requests in parallel.
699 **/ 713 **/
700 r = ttm_alloc_new_pages(pages, gfp_flags, ttm_flags, cstate, 714 r = ttm_alloc_new_pages(pages, gfp_flags, ttm_flags, cstate,
701 count); 715 count, order);
702 } 716 }
703 717
704 return r; 718 return r;
@@ -708,8 +722,9 @@ out:
708static void ttm_put_pages(struct page **pages, unsigned npages, int flags, 722static void ttm_put_pages(struct page **pages, unsigned npages, int flags,
709 enum ttm_caching_state cstate) 723 enum ttm_caching_state cstate)
710{ 724{
725 struct ttm_page_pool *pool = ttm_get_pool(flags, false, cstate);
726 struct ttm_page_pool *huge = ttm_get_pool(flags, true, cstate);
711 unsigned long irq_flags; 727 unsigned long irq_flags;
712 struct ttm_page_pool *pool = ttm_get_pool(flags, cstate);
713 unsigned i; 728 unsigned i;
714 729
715 if (pool == NULL) { 730 if (pool == NULL) {
@@ -737,8 +752,48 @@ static void ttm_put_pages(struct page **pages, unsigned npages, int flags,
737 return; 752 return;
738 } 753 }
739 754
755 i = 0;
756#ifdef CONFIG_TRANSPARENT_HUGEPAGE
757 if (huge) {
758 unsigned max_size, n2free;
759
760 spin_lock_irqsave(&huge->lock, irq_flags);
761 while (i < npages) {
762 struct page *p = pages[i];
763 unsigned j;
764
765 if (!p)
766 break;
767
768 for (j = 0; j < HPAGE_PMD_NR; ++j)
769 if (p++ != pages[i + j])
770 break;
771
772 if (j != HPAGE_PMD_NR)
773 break;
774
775 list_add_tail(&pages[i]->lru, &huge->list);
776
777 for (j = 0; j < HPAGE_PMD_NR; ++j)
778 pages[i++] = NULL;
779 huge->npages++;
780 }
781
782 /* Check that we don't go over the pool limit */
783 max_size = _manager->options.max_size;
784 max_size /= HPAGE_PMD_NR;
785 if (huge->npages > max_size)
786 n2free = huge->npages - max_size;
787 else
788 n2free = 0;
789 spin_unlock_irqrestore(&huge->lock, irq_flags);
790 if (n2free)
791 ttm_page_pool_free(huge, n2free, false);
792 }
793#endif
794
740 spin_lock_irqsave(&pool->lock, irq_flags); 795 spin_lock_irqsave(&pool->lock, irq_flags);
741 for (i = 0; i < npages; i++) { 796 while (i < npages) {
742 if (pages[i]) { 797 if (pages[i]) {
743 if (page_count(pages[i]) != 1) 798 if (page_count(pages[i]) != 1)
744 pr_err("Erroneous page count. Leaking pages.\n"); 799 pr_err("Erroneous page count. Leaking pages.\n");
@@ -746,6 +801,7 @@ static void ttm_put_pages(struct page **pages, unsigned npages, int flags,
746 pages[i] = NULL; 801 pages[i] = NULL;
747 pool->npages++; 802 pool->npages++;
748 } 803 }
804 ++i;
749 } 805 }
750 /* Check that we don't go over the pool limit */ 806 /* Check that we don't go over the pool limit */
751 npages = 0; 807 npages = 0;
@@ -768,7 +824,8 @@ static void ttm_put_pages(struct page **pages, unsigned npages, int flags,
768static int ttm_get_pages(struct page **pages, unsigned npages, int flags, 824static int ttm_get_pages(struct page **pages, unsigned npages, int flags,
769 enum ttm_caching_state cstate) 825 enum ttm_caching_state cstate)
770{ 826{
771 struct ttm_page_pool *pool = ttm_get_pool(flags, cstate); 827 struct ttm_page_pool *pool = ttm_get_pool(flags, false, cstate);
828 struct ttm_page_pool *huge = ttm_get_pool(flags, true, cstate);
772 struct list_head plist; 829 struct list_head plist;
773 struct page *p = NULL; 830 struct page *p = NULL;
774 unsigned count; 831 unsigned count;
@@ -821,11 +878,28 @@ static int ttm_get_pages(struct page **pages, unsigned npages, int flags,
821 return 0; 878 return 0;
822 } 879 }
823 880
824 /* First we take pages from the pool */ 881 count = 0;
882
883#ifdef CONFIG_TRANSPARENT_HUGEPAGE
884 if (huge && npages >= HPAGE_PMD_NR) {
885 INIT_LIST_HEAD(&plist);
886 ttm_page_pool_get_pages(huge, &plist, flags, cstate,
887 npages / HPAGE_PMD_NR,
888 HPAGE_PMD_ORDER);
889
890 list_for_each_entry(p, &plist, lru) {
891 unsigned j;
892
893 for (j = 0; j < HPAGE_PMD_NR; ++j)
894 pages[count++] = &p[j];
895 }
896 }
897#endif
898
825 INIT_LIST_HEAD(&plist); 899 INIT_LIST_HEAD(&plist);
826 r = ttm_page_pool_get_pages(pool, &plist, flags, cstate, npages); 900 r = ttm_page_pool_get_pages(pool, &plist, flags, cstate,
901 npages - count, 0);
827 902
828 count = 0;
829 list_for_each_entry(p, &plist, lru) 903 list_for_each_entry(p, &plist, lru)
830 pages[count++] = p; 904 pages[count++] = p;
831 905
@@ -872,6 +946,14 @@ int ttm_page_alloc_init(struct ttm_mem_global *glob, unsigned max_pages)
872 ttm_page_pool_init_locked(&_manager->uc_pool_dma32, 946 ttm_page_pool_init_locked(&_manager->uc_pool_dma32,
873 GFP_USER | GFP_DMA32, "uc dma"); 947 GFP_USER | GFP_DMA32, "uc dma");
874 948
949 ttm_page_pool_init_locked(&_manager->wc_pool_huge,
950 GFP_TRANSHUGE & ~(__GFP_MOVABLE | __GFP_COMP),
951 "wc huge");
952
953 ttm_page_pool_init_locked(&_manager->uc_pool_huge,
954 GFP_TRANSHUGE & ~(__GFP_MOVABLE | __GFP_COMP)
955 , "uc huge");
956
875 _manager->options.max_size = max_pages; 957 _manager->options.max_size = max_pages;
876 _manager->options.small = SMALL_ALLOCATION; 958 _manager->options.small = SMALL_ALLOCATION;
877 _manager->options.alloc_size = NUM_PAGES_TO_ALLOC; 959 _manager->options.alloc_size = NUM_PAGES_TO_ALLOC;
@@ -1041,12 +1123,12 @@ int ttm_page_alloc_debugfs(struct seq_file *m, void *data)
1041 seq_printf(m, "No pool allocator running.\n"); 1123 seq_printf(m, "No pool allocator running.\n");
1042 return 0; 1124 return 0;
1043 } 1125 }
1044 seq_printf(m, "%6s %12s %13s %8s\n", 1126 seq_printf(m, "%7s %12s %13s %8s\n",
1045 h[0], h[1], h[2], h[3]); 1127 h[0], h[1], h[2], h[3]);
1046 for (i = 0; i < NUM_POOLS; ++i) { 1128 for (i = 0; i < NUM_POOLS; ++i) {
1047 p = &_manager->pools[i]; 1129 p = &_manager->pools[i];
1048 1130
1049 seq_printf(m, "%6s %12ld %13ld %8d\n", 1131 seq_printf(m, "%7s %12ld %13ld %8d\n",
1050 p->name, p->nrefills, 1132 p->name, p->nrefills,
1051 p->nfrees, p->npages); 1133 p->nfrees, p->npages);
1052 } 1134 }