Skip to content

Commit a91576d

Browse files
Tetsuo Handaairlied
authored andcommitted
drm/ttm: Pass GFP flags in order to avoid deadlock.
Commit 7dc19d5 "drivers: convert shrinkers to new count/scan API" added deadlock warnings that ttm_page_pool_free() and ttm_dma_page_pool_free() are currently doing GFP_KERNEL allocation. But these functions did not get updated to receive gfp_t argument. This patch explicitly passes sc->gfp_mask or GFP_KERNEL to these functions, and removes the deadlock warning. Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Cc: stable <stable@kernel.org> [2.6.35+] Signed-off-by: Dave Airlie <airlied@redhat.com>
1 parent 71336e0 commit a91576d

File tree

2 files changed

+19
-19
lines changed

2 files changed

+19
-19
lines changed

drivers/gpu/drm/ttm/ttm_page_alloc.c

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -297,8 +297,10 @@ static void ttm_pool_update_free_locked(struct ttm_page_pool *pool,
297297
*
298298
* @pool: to free the pages from
299299
* @free_all: If set to true will free all pages in pool
300+
* @gfp: GFP flags.
300301
**/
301-
static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free)
302+
static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free,
303+
gfp_t gfp)
302304
{
303305
unsigned long irq_flags;
304306
struct page *p;
@@ -309,8 +311,7 @@ static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free)
309311
if (NUM_PAGES_TO_ALLOC < nr_free)
310312
npages_to_free = NUM_PAGES_TO_ALLOC;
311313

312-
pages_to_free = kmalloc(npages_to_free * sizeof(struct page *),
313-
GFP_KERNEL);
314+
pages_to_free = kmalloc(npages_to_free * sizeof(struct page *), gfp);
314315
if (!pages_to_free) {
315316
pr_err("Failed to allocate memory for pool free operation\n");
316317
return 0;
@@ -382,9 +383,7 @@ static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free)
382383
*
383384
* XXX: (dchinner) Deadlock warning!
384385
*
385-
* ttm_page_pool_free() does memory allocation using GFP_KERNEL. that means
386-
* this can deadlock when called a sc->gfp_mask that is not equal to
387-
* GFP_KERNEL.
386+
* We need to pass sc->gfp_mask to ttm_page_pool_free().
388387
*
389388
* This code is crying out for a shrinker per pool....
390389
*/
@@ -408,7 +407,8 @@ ttm_pool_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
408407
if (shrink_pages == 0)
409408
break;
410409
pool = &_manager->pools[(i + pool_offset)%NUM_POOLS];
411-
shrink_pages = ttm_page_pool_free(pool, nr_free);
410+
shrink_pages = ttm_page_pool_free(pool, nr_free,
411+
sc->gfp_mask);
412412
freed += nr_free - shrink_pages;
413413
}
414414
mutex_unlock(&lock);
@@ -710,7 +710,7 @@ static void ttm_put_pages(struct page **pages, unsigned npages, int flags,
710710
}
711711
spin_unlock_irqrestore(&pool->lock, irq_flags);
712712
if (npages)
713-
ttm_page_pool_free(pool, npages);
713+
ttm_page_pool_free(pool, npages, GFP_KERNEL);
714714
}
715715

716716
/*
@@ -850,7 +850,8 @@ void ttm_page_alloc_fini(void)
850850
ttm_pool_mm_shrink_fini(_manager);
851851

852852
for (i = 0; i < NUM_POOLS; ++i)
853-
ttm_page_pool_free(&_manager->pools[i], FREE_ALL_PAGES);
853+
ttm_page_pool_free(&_manager->pools[i], FREE_ALL_PAGES,
854+
GFP_KERNEL);
854855

855856
kobject_put(&_manager->kobj);
856857
_manager = NULL;

drivers/gpu/drm/ttm/ttm_page_alloc_dma.c

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -411,8 +411,10 @@ static void ttm_dma_page_put(struct dma_pool *pool, struct dma_page *d_page)
411411
*
412412
* @pool: to free the pages from
413413
* @nr_free: If set to true will free all pages in pool
414+
* @gfp: GFP flags.
414415
**/
415-
static unsigned ttm_dma_page_pool_free(struct dma_pool *pool, unsigned nr_free)
416+
static unsigned ttm_dma_page_pool_free(struct dma_pool *pool, unsigned nr_free,
417+
gfp_t gfp)
416418
{
417419
unsigned long irq_flags;
418420
struct dma_page *dma_p, *tmp;
@@ -430,8 +432,7 @@ static unsigned ttm_dma_page_pool_free(struct dma_pool *pool, unsigned nr_free)
430432
npages_to_free, nr_free);
431433
}
432434
#endif
433-
pages_to_free = kmalloc(npages_to_free * sizeof(struct page *),
434-
GFP_KERNEL);
435+
pages_to_free = kmalloc(npages_to_free * sizeof(struct page *), gfp);
435436

436437
if (!pages_to_free) {
437438
pr_err("%s: Failed to allocate memory for pool free operation\n",
@@ -530,7 +531,7 @@ static void ttm_dma_free_pool(struct device *dev, enum pool_type type)
530531
if (pool->type != type)
531532
continue;
532533
/* Takes a spinlock.. */
533-
ttm_dma_page_pool_free(pool, FREE_ALL_PAGES);
534+
ttm_dma_page_pool_free(pool, FREE_ALL_PAGES, GFP_KERNEL);
534535
WARN_ON(((pool->npages_in_use + pool->npages_free) != 0));
535536
/* This code path is called after _all_ references to the
536537
* struct device has been dropped - so nobody should be
@@ -983,7 +984,7 @@ void ttm_dma_unpopulate(struct ttm_dma_tt *ttm_dma, struct device *dev)
983984

984985
/* shrink pool if necessary (only on !is_cached pools)*/
985986
if (npages)
986-
ttm_dma_page_pool_free(pool, npages);
987+
ttm_dma_page_pool_free(pool, npages, GFP_KERNEL);
987988
ttm->state = tt_unpopulated;
988989
}
989990
EXPORT_SYMBOL_GPL(ttm_dma_unpopulate);
@@ -993,10 +994,7 @@ EXPORT_SYMBOL_GPL(ttm_dma_unpopulate);
993994
*
994995
* XXX: (dchinner) Deadlock warning!
995996
*
996-
* ttm_dma_page_pool_free() does GFP_KERNEL memory allocation, and so attention
997-
* needs to be paid to sc->gfp_mask to determine if this can be done or not.
998-
* GFP_KERNEL memory allocation in a GFP_ATOMIC reclaim context woul dbe really
999-
* bad.
997+
* We need to pass sc->gfp_mask to ttm_dma_page_pool_free().
1000998
*
1001999
* I'm getting sadder as I hear more pathetical whimpers about needing per-pool
10021000
* shrinkers
@@ -1030,7 +1028,8 @@ ttm_dma_pool_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
10301028
if (++idx < pool_offset)
10311029
continue;
10321030
nr_free = shrink_pages;
1033-
shrink_pages = ttm_dma_page_pool_free(p->pool, nr_free);
1031+
shrink_pages = ttm_dma_page_pool_free(p->pool, nr_free,
1032+
sc->gfp_mask);
10341033
freed += nr_free - shrink_pages;
10351034

10361035
pr_debug("%s: (%s:%d) Asked to shrink %d, have %d more to go\n",

0 commit comments

Comments
 (0)