Signed-off-by: Roger He <Hongbo.He@xxxxxxx>
---
drivers/gpu/drm/ttm/ttm_bo_vm.c | 6 +++++-
drivers/gpu/drm/ttm/ttm_memory.c | 27 +++++++++++++++++++--------
drivers/gpu/drm/ttm/ttm_page_alloc.c | 5 ++++-
drivers/gpu/drm/ttm/ttm_page_alloc_dma.c | 9 ++++++---
drivers/gpu/drm/ttm/ttm_tt.c | 2 +-
include/drm/ttm/ttm_bo_driver.h | 1 +
include/drm/ttm/ttm_memory.h | 3 ++-
7 files changed, 38 insertions(+), 15 deletions(-)
diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c
index 716e724..f03dd94 100644
--- a/drivers/gpu/drm/ttm/ttm_bo_vm.c
+++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c
@@ -233,8 +233,12 @@ static int ttm_bo_vm_fault(struct vm_fault *vmf)
cvma.vm_page_prot = ttm_io_prot(bo->mem.placement,
cvma.vm_page_prot);
+ if (ttm->page_flags & TTM_PAGE_FLAG_NO_RETRY)
+ ttm->page_flags |= TTM_PAGE_FLAG_PAGEFAULT;
/* Allocate all page at once, most common usage */
- if (ttm->bdev->driver->ttm_tt_populate(ttm, &ctx)) {
+ ret = ttm->bdev->driver->ttm_tt_populate(ttm, &ctx);
+ ttm->page_flags &= ~TTM_PAGE_FLAG_PAGEFAULT;
+ if (ret) {
ret = VM_FAULT_OOM;
goto out_io_unlock;
}
diff --git a/drivers/gpu/drm/ttm/ttm_memory.c b/drivers/gpu/drm/ttm/ttm_memory.c
index 598b14b..f5227a5 100644
--- a/drivers/gpu/drm/ttm/ttm_memory.c
+++ b/drivers/gpu/drm/ttm/ttm_memory.c
@@ -472,7 +472,8 @@ EXPORT_SYMBOL(ttm_mem_global_free);
static int ttm_mem_global_reserve(struct ttm_mem_global *glob,
struct ttm_mem_zone *single_zone,
- uint64_t amount, bool reserve)
+ uint64_t amount, bool reserve,
+ bool in_pagefault)
{
uint64_t free_swap_mem = get_nr_swap_pages() << (PAGE_SHIFT - 1);
uint64_t swap_glob_mem, limit, total_used_mem;
@@ -483,6 +484,13 @@ static int ttm_mem_global_reserve(struct ttm_mem_global *glob,
swap_glob_mem = atomic64_read(&glob->swap_glob_mem);
spin_lock(&glob->lock);
+ /*
+ * if in page_fault allow reserve successfully anyway since it
+ * already allocated system pages. Otherwise it will trigger OOM
+ */
+ if (in_pagefault)
+ goto reserve_direct;
+
/* adjust the max_swap_mem to cover the new inserted swap space */
if (glob->max_swap_mem < free_swap_mem)
glob->max_swap_mem = free_swap_mem;
@@ -501,6 +509,7 @@ static int ttm_mem_global_reserve(struct ttm_mem_global *glob,
goto out_unlock;
}
+reserve_direct:
if (reserve) {
for (i = 0; i < glob->num_zones; ++i) {
zone = glob->zones[i];
@@ -522,13 +531,13 @@ static int ttm_mem_global_reserve(struct ttm_mem_global *glob,
static int ttm_mem_global_alloc_zone(struct ttm_mem_global *glob,
struct ttm_mem_zone *single_zone,
uint64_t memory,
- struct ttm_operation_ctx *ctx)
+ struct ttm_operation_ctx *ctx,
+ bool in_pagefault)
{
int count = TTM_MEMORY_ALLOC_RETRIES;
- while (unlikely(ttm_mem_global_reserve(glob,
- single_zone,
- memory, true)
+ while (unlikely(ttm_mem_global_reserve(glob, single_zone, memory,
+ true, in_pagefault)
!= 0)) {
if (ctx->no_wait_gpu)
return -ENOMEM;
@@ -548,13 +557,14 @@ int ttm_mem_global_alloc(struct ttm_mem_global *glob, uint64_t memory,
* all zones.
*/
- return ttm_mem_global_alloc_zone(glob, NULL, memory, ctx);
+ return ttm_mem_global_alloc_zone(glob, NULL, memory, ctx, false);
}
EXPORT_SYMBOL(ttm_mem_global_alloc);
int ttm_mem_global_alloc_page(struct ttm_mem_global *glob,
struct page *page, uint64_t size,
- struct ttm_operation_ctx *ctx)
+ struct ttm_operation_ctx *ctx,
+ bool in_pagefault)
{
struct ttm_mem_zone *zone = NULL;
@@ -570,7 +580,8 @@ int ttm_mem_global_alloc_page(struct ttm_mem_global *glob,
if (glob->zone_dma32 && page_to_pfn(page) > 0x00100000UL)
zone = glob->zone_kernel;
#endif
- return ttm_mem_global_alloc_zone(glob, zone, size, ctx);
+ return ttm_mem_global_alloc_zone(glob, zone, size,
+ ctx, in_pagefault);
}
void ttm_mem_global_free_page(struct ttm_mem_global *glob, struct page *page,
diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c b/drivers/gpu/drm/ttm/ttm_page_alloc.c
index 5edcd89..15bf691 100644
--- a/drivers/gpu/drm/ttm/ttm_page_alloc.c
+++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c
@@ -1094,6 +1094,7 @@ ttm_pool_unpopulate_helper(struct ttm_tt *ttm, unsigned mem_count_update)
int ttm_pool_populate(struct ttm_tt *ttm, struct ttm_operation_ctx *ctx)
{
struct ttm_mem_global *mem_glob = ttm->glob->mem_glob;
+ bool in_pagefault;
unsigned i;
int ret;
@@ -1107,9 +1108,11 @@ int ttm_pool_populate(struct ttm_tt *ttm, struct ttm_operation_ctx *ctx)
return ret;
}
+ in_pagefault = ttm->page_flags & TTM_PAGE_FLAG_PAGEFAULT;
for (i = 0; i < ttm->num_pages; ++i) {
ret = ttm_mem_global_alloc_page(mem_glob, ttm->pages[i],
- PAGE_SIZE, ctx);
+ PAGE_SIZE, ctx,
+ in_pagefault);
if (unlikely(ret != 0)) {
ttm_pool_unpopulate_helper(ttm, i);
return -ENOMEM;
diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
index b122f6e..b8adf37 100644
--- a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
+++ b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
@@ -934,6 +934,7 @@ int ttm_dma_populate(struct ttm_dma_tt *ttm_dma, struct device *dev,
struct dma_pool *pool;
struct dma_page *d_page;
enum pool_type type;
+ bool in_pagefault;
unsigned i;
int ret;
@@ -943,8 +944,8 @@ int ttm_dma_populate(struct ttm_dma_tt *ttm_dma, struct device *dev,
INIT_LIST_HEAD(&ttm_dma->pages_list);
i = 0;
+ in_pagefault = ttm_dma->ttm.page_flags & TTM_PAGE_FLAG_PAGEFAULT;
type = ttm_to_type(ttm->page_flags, ttm->caching_state);
-
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
if (ttm->page_flags & TTM_PAGE_FLAG_DMA32)
goto skip_huge;
@@ -966,7 +967,8 @@ int ttm_dma_populate(struct ttm_dma_tt *ttm_dma, struct device *dev,
break;
ret = ttm_mem_global_alloc_page(mem_glob, ttm->pages[i],
- pool->size, ctx);
+ pool->size, ctx,
+ in_pagefault);
if (unlikely(ret != 0)) {
ttm_dma_unpopulate(ttm_dma, dev);
return -ENOMEM;
@@ -1003,7 +1005,8 @@ int ttm_dma_populate(struct ttm_dma_tt *ttm_dma, struct device *dev,
}
ret = ttm_mem_global_alloc_page(mem_glob, ttm->pages[i],
- pool->size, ctx);
+ pool->size, ctx,
+ in_pagefault);
if (unlikely(ret != 0)) {
ttm_dma_unpopulate(ttm_dma, dev);
return -ENOMEM;
diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c
index 5d441e0..a730cd6 100644
--- a/drivers/gpu/drm/ttm/ttm_tt.c
+++ b/drivers/gpu/drm/ttm/ttm_tt.c
@@ -391,7 +391,7 @@ int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistent_swap_storage)
ttm->page_flags |= TTM_PAGE_FLAG_PERSISTENT_SWAP;
else
atomic64_add_return(ttm->num_pages << PAGE_SHIFT,
- &ttm->glob->mem_glob->swap_glob_mem);
+ &ttm->glob->mem_glob->swap_glob_mem);
return 0;
out_err:
diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h
index 9b417eb..8f68781 100644
--- a/include/drm/ttm/ttm_bo_driver.h
+++ b/include/drm/ttm/ttm_bo_driver.h
@@ -87,6 +87,7 @@ struct ttm_backend_func {
#define TTM_PAGE_FLAG_DMA32 (1 << 7)
#define TTM_PAGE_FLAG_SG (1 << 8)
#define TTM_PAGE_FLAG_NO_RETRY (1 << 9)
+#define TTM_PAGE_FLAG_PAGEFAULT (1 << 10)
enum ttm_caching_state {
tt_uncached,
diff --git a/include/drm/ttm/ttm_memory.h b/include/drm/ttm/ttm_memory.h
index 6282b50..6c29b5c 100644
--- a/include/drm/ttm/ttm_memory.h
+++ b/include/drm/ttm/ttm_memory.h
@@ -89,7 +89,8 @@ extern void ttm_mem_global_free(struct ttm_mem_global *glob,
uint64_t amount);
extern int ttm_mem_global_alloc_page(struct ttm_mem_global *glob,
struct page *page, uint64_t size,
- struct ttm_operation_ctx *ctx);
+ struct ttm_operation_ctx *ctx,
+ bool in_pagefault);
extern void ttm_mem_global_free_page(struct ttm_mem_global *glob,
struct page *page, uint64_t size);
extern size_t ttm_round_pot(size_t size);