diff options
Diffstat (limited to 'drivers/gpu/drm/ttm/ttm_tt.c')
-rw-r--r-- | drivers/gpu/drm/ttm/ttm_tt.c | 260 |
1 files changed, 74 insertions, 186 deletions
diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index f43fa69a1e65..da9eeffe0c6d 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c @@ -37,10 +37,8 @@ #include <linux/file.h> #include <drm/drm_cache.h> #include <drm/ttm/ttm_bo_driver.h> -#include <drm/ttm/ttm_page_alloc.h> -#include <drm/ttm/ttm_set_memory.h> -/** +/* * Allocates a ttm structure for the given BO. */ int ttm_tt_create(struct ttm_buffer_object *bo, bool zero_alloc) @@ -53,12 +51,6 @@ int ttm_tt_create(struct ttm_buffer_object *bo, bool zero_alloc) if (bo->ttm) return 0; - if (bdev->need_dma32) - page_flags |= TTM_PAGE_FLAG_DMA32; - - if (bdev->no_retry) - page_flags |= TTM_PAGE_FLAG_NO_RETRY; - switch (bo->type) { case ttm_bo_type_device: if (zero_alloc) @@ -81,7 +73,7 @@ int ttm_tt_create(struct ttm_buffer_object *bo, bool zero_alloc) return 0; } -/** +/* * Allocates storage for pointers to the pages that back the ttm. */ static int ttm_tt_alloc_page_directory(struct ttm_tt *ttm) @@ -93,21 +85,22 @@ static int ttm_tt_alloc_page_directory(struct ttm_tt *ttm) return 0; } -static int ttm_dma_tt_alloc_page_directory(struct ttm_dma_tt *ttm) +static int ttm_dma_tt_alloc_page_directory(struct ttm_tt *ttm) { - ttm->ttm.pages = kvmalloc_array(ttm->ttm.num_pages, - sizeof(*ttm->ttm.pages) + - sizeof(*ttm->dma_address), - GFP_KERNEL | __GFP_ZERO); - if (!ttm->ttm.pages) + ttm->pages = kvmalloc_array(ttm->num_pages, + sizeof(*ttm->pages) + + sizeof(*ttm->dma_address), + GFP_KERNEL | __GFP_ZERO); + if (!ttm->pages) return -ENOMEM; - ttm->dma_address = (void *) (ttm->ttm.pages + ttm->ttm.num_pages); + + ttm->dma_address = (void *)(ttm->pages + ttm->num_pages); return 0; } -static int ttm_sg_tt_alloc_page_directory(struct ttm_dma_tt *ttm) +static int ttm_sg_tt_alloc_page_directory(struct ttm_tt *ttm) { - ttm->dma_address = kvmalloc_array(ttm->ttm.num_pages, + ttm->dma_address = kvmalloc_array(ttm->num_pages, sizeof(*ttm->dma_address), GFP_KERNEL | __GFP_ZERO); if (!ttm->dma_address) @@ -115,104 +108,11 @@ static int ttm_sg_tt_alloc_page_directory(struct ttm_dma_tt *ttm) return 0; } -static int ttm_tt_set_page_caching(struct page *p, - enum ttm_caching_state c_old, - enum ttm_caching_state c_new) -{ - int ret = 0; - - if (PageHighMem(p)) - return 0; - - if (c_old != tt_cached) { - /* p isn't in the default caching state, set it to - * writeback first to free its current memtype. */ - - ret = ttm_set_pages_wb(p, 1); - if (ret) - return ret; - } - - if (c_new == tt_wc) - ret = ttm_set_pages_wc(p, 1); - else if (c_new == tt_uncached) - ret = ttm_set_pages_uc(p, 1); - - return ret; -} - -/* - * Change caching policy for the linear kernel map - * for range of pages in a ttm. - */ - -static int ttm_tt_set_caching(struct ttm_tt *ttm, - enum ttm_caching_state c_state) -{ - int i, j; - struct page *cur_page; - int ret; - - if (ttm->caching_state == c_state) - return 0; - - if (!ttm_tt_is_populated(ttm)) { - /* Change caching but don't populate */ - ttm->caching_state = c_state; - return 0; - } - - if (ttm->caching_state == tt_cached) - drm_clflush_pages(ttm->pages, ttm->num_pages); - - for (i = 0; i < ttm->num_pages; ++i) { - cur_page = ttm->pages[i]; - if (likely(cur_page != NULL)) { - ret = ttm_tt_set_page_caching(cur_page, - ttm->caching_state, - c_state); - if (unlikely(ret != 0)) - goto out_err; - } - } - - ttm->caching_state = c_state; - - return 0; - -out_err: - for (j = 0; j < i; ++j) { - cur_page = ttm->pages[j]; - if (likely(cur_page != NULL)) { - (void)ttm_tt_set_page_caching(cur_page, c_state, - ttm->caching_state); - } - } - - return ret; -} - -int ttm_tt_set_placement_caching(struct ttm_tt *ttm, uint32_t placement) -{ - enum ttm_caching_state state; - - if (placement & TTM_PL_FLAG_WC) - state = tt_wc; - else if (placement & TTM_PL_FLAG_UNCACHED) - state = tt_uncached; - else - state = tt_cached; - - return ttm_tt_set_caching(ttm, state); -} -EXPORT_SYMBOL(ttm_tt_set_placement_caching); - void ttm_tt_destroy_common(struct ttm_bo_device *bdev, struct ttm_tt *ttm) { ttm_tt_unpopulate(bdev, ttm); - if (!(ttm->page_flags & TTM_PAGE_FLAG_PERSISTENT_SWAP) && - ttm->swap_storage) + if (ttm->swap_storage) fput(ttm->swap_storage); ttm->swap_storage = NULL; @@ -226,20 +126,22 @@ void ttm_tt_destroy(struct ttm_bo_device *bdev, struct ttm_tt *ttm) static void ttm_tt_init_fields(struct ttm_tt *ttm, struct ttm_buffer_object *bo, - uint32_t page_flags) + uint32_t page_flags, + enum ttm_caching caching) { ttm->num_pages = bo->num_pages; - ttm->caching_state = tt_cached; + ttm->caching = ttm_cached; ttm->page_flags = page_flags; - ttm_tt_set_unpopulated(ttm); + ttm->dma_address = NULL; ttm->swap_storage = NULL; ttm->sg = bo->sg; + ttm->caching = caching; } int ttm_tt_init(struct ttm_tt *ttm, struct ttm_buffer_object *bo, - uint32_t page_flags) + uint32_t page_flags, enum ttm_caching caching) { - ttm_tt_init_fields(ttm, bo, page_flags); + ttm_tt_init_fields(ttm, bo, page_flags, caching); if (ttm_tt_alloc_page_directory(ttm)) { pr_err("Failed allocating page table\n"); @@ -251,20 +153,21 @@ EXPORT_SYMBOL(ttm_tt_init); void ttm_tt_fini(struct ttm_tt *ttm) { - kvfree(ttm->pages); + if (ttm->pages) + kvfree(ttm->pages); + else + kvfree(ttm->dma_address); ttm->pages = NULL; + ttm->dma_address = NULL; } EXPORT_SYMBOL(ttm_tt_fini); -int ttm_dma_tt_init(struct ttm_dma_tt *ttm_dma, struct ttm_buffer_object *bo, - uint32_t page_flags) +int ttm_dma_tt_init(struct ttm_tt *ttm, struct ttm_buffer_object *bo, + uint32_t page_flags, enum ttm_caching caching) { - struct ttm_tt *ttm = &ttm_dma->ttm; - - ttm_tt_init_fields(ttm, bo, page_flags); + ttm_tt_init_fields(ttm, bo, page_flags, caching); - INIT_LIST_HEAD(&ttm_dma->pages_list); - if (ttm_dma_tt_alloc_page_directory(ttm_dma)) { + if (ttm_dma_tt_alloc_page_directory(ttm)) { pr_err("Failed allocating page table\n"); return -ENOMEM; } @@ -272,19 +175,17 @@ int ttm_dma_tt_init(struct ttm_dma_tt *ttm_dma, struct ttm_buffer_object *bo, } EXPORT_SYMBOL(ttm_dma_tt_init); -int ttm_sg_tt_init(struct ttm_dma_tt *ttm_dma, struct ttm_buffer_object *bo, - uint32_t page_flags) +int ttm_sg_tt_init(struct ttm_tt *ttm, struct ttm_buffer_object *bo, + uint32_t page_flags, enum ttm_caching caching) { - struct ttm_tt *ttm = &ttm_dma->ttm; int ret; - ttm_tt_init_fields(ttm, bo, page_flags); + ttm_tt_init_fields(ttm, bo, page_flags, caching); - INIT_LIST_HEAD(&ttm_dma->pages_list); if (page_flags & TTM_PAGE_FLAG_SG) - ret = ttm_sg_tt_alloc_page_directory(ttm_dma); + ret = ttm_sg_tt_alloc_page_directory(ttm); else - ret = ttm_dma_tt_alloc_page_directory(ttm_dma); + ret = ttm_dma_tt_alloc_page_directory(ttm); if (ret) { pr_err("Failed allocating page table\n"); return -ENOMEM; @@ -293,92 +194,69 @@ int ttm_sg_tt_init(struct ttm_dma_tt *ttm_dma, struct ttm_buffer_object *bo, } EXPORT_SYMBOL(ttm_sg_tt_init); -void ttm_dma_tt_fini(struct ttm_dma_tt *ttm_dma) -{ - struct ttm_tt *ttm = &ttm_dma->ttm; - - if (ttm->pages) - kvfree(ttm->pages); - else - kvfree(ttm_dma->dma_address); - ttm->pages = NULL; - ttm_dma->dma_address = NULL; -} -EXPORT_SYMBOL(ttm_dma_tt_fini); - int ttm_tt_swapin(struct ttm_tt *ttm) { struct address_space *swap_space; struct file *swap_storage; struct page *from_page; struct page *to_page; - int i; - int ret = -ENOMEM; + gfp_t gfp_mask; + int i, ret; swap_storage = ttm->swap_storage; BUG_ON(swap_storage == NULL); swap_space = swap_storage->f_mapping; + gfp_mask = mapping_gfp_mask(swap_space); for (i = 0; i < ttm->num_pages; ++i) { - gfp_t gfp_mask = mapping_gfp_mask(swap_space); - - gfp_mask |= (ttm->page_flags & TTM_PAGE_FLAG_NO_RETRY ? __GFP_RETRY_MAYFAIL : 0); - from_page = shmem_read_mapping_page_gfp(swap_space, i, gfp_mask); - + from_page = shmem_read_mapping_page_gfp(swap_space, i, + gfp_mask); if (IS_ERR(from_page)) { ret = PTR_ERR(from_page); goto out_err; } to_page = ttm->pages[i]; - if (unlikely(to_page == NULL)) + if (unlikely(to_page == NULL)) { + ret = -ENOMEM; goto out_err; + } copy_highpage(to_page, from_page); put_page(from_page); } - if (!(ttm->page_flags & TTM_PAGE_FLAG_PERSISTENT_SWAP)) - fput(swap_storage); + fput(swap_storage); ttm->swap_storage = NULL; ttm->page_flags &= ~TTM_PAGE_FLAG_SWAPPED; return 0; + out_err: return ret; } -int ttm_tt_swapout(struct ttm_bo_device *bdev, - struct ttm_tt *ttm, struct file *persistent_swap_storage) +int ttm_tt_swapout(struct ttm_bo_device *bdev, struct ttm_tt *ttm) { struct address_space *swap_space; struct file *swap_storage; struct page *from_page; struct page *to_page; - int i; - int ret = -ENOMEM; - - BUG_ON(ttm->caching_state != tt_cached); - - if (!persistent_swap_storage) { - swap_storage = shmem_file_setup("ttm swap", - ttm->num_pages << PAGE_SHIFT, - 0); - if (IS_ERR(swap_storage)) { - pr_err("Failed allocating swap storage\n"); - return PTR_ERR(swap_storage); - } - } else { - swap_storage = persistent_swap_storage; + gfp_t gfp_mask; + int i, ret; + + swap_storage = shmem_file_setup("ttm swap", + ttm->num_pages << PAGE_SHIFT, + 0); + if (IS_ERR(swap_storage)) { + pr_err("Failed allocating swap storage\n"); + return PTR_ERR(swap_storage); } swap_space = swap_storage->f_mapping; + gfp_mask = mapping_gfp_mask(swap_space); for (i = 0; i < ttm->num_pages; ++i) { - gfp_t gfp_mask = mapping_gfp_mask(swap_space); - - gfp_mask |= (ttm->page_flags & TTM_PAGE_FLAG_NO_RETRY ? __GFP_RETRY_MAYFAIL : 0); - from_page = ttm->pages[i]; if (unlikely(from_page == NULL)) continue; @@ -397,13 +275,11 @@ int ttm_tt_swapout(struct ttm_bo_device *bdev, ttm_tt_unpopulate(bdev, ttm); ttm->swap_storage = swap_storage; ttm->page_flags |= TTM_PAGE_FLAG_SWAPPED; - if (persistent_swap_storage) - ttm->page_flags |= TTM_PAGE_FLAG_PERSISTENT_SWAP; return 0; + out_err: - if (!persistent_swap_storage) - fput(swap_storage); + fput(swap_storage); return ret; } @@ -433,10 +309,21 @@ int ttm_tt_populate(struct ttm_bo_device *bdev, if (bdev->driver->ttm_tt_populate) ret = bdev->driver->ttm_tt_populate(bdev, ttm, ctx); else - ret = ttm_pool_populate(ttm, ctx); - if (!ret) - ttm_tt_add_mapping(bdev, ttm); - return ret; + ret = ttm_pool_alloc(&bdev->pool, ttm, ctx); + if (ret) + return ret; + + ttm_tt_add_mapping(bdev, ttm); + ttm->page_flags |= TTM_PAGE_FLAG_PRIV_POPULATED; + if (unlikely(ttm->page_flags & TTM_PAGE_FLAG_SWAPPED)) { + ret = ttm_tt_swapin(ttm); + if (unlikely(ret != 0)) { + ttm_tt_unpopulate(bdev, ttm); + return ret; + } + } + + return 0; } EXPORT_SYMBOL(ttm_tt_populate); @@ -464,5 +351,6 @@ void ttm_tt_unpopulate(struct ttm_bo_device *bdev, if (bdev->driver->ttm_tt_unpopulate) bdev->driver->ttm_tt_unpopulate(bdev, ttm); else - ttm_pool_unpopulate(ttm); + ttm_pool_free(&bdev->pool, ttm); + ttm->page_flags &= ~TTM_PAGE_FLAG_PRIV_POPULATED; } |