Re: [PATCH] gpu/drm/ttm: Pass GFP flags in order to avoid deadlock.

2014-05-20 Thread Konrad Rzeszutek Wilk
On Tue, May 20, 2014 at 01:40:40AM +0100, Dave Airlie wrote:
> 
> cc'ing dri-devel.

It looks pretty simple and correct . I can test it tomorrow and make sure it 
works
right.
> 
> > >From d0d57745ba23faf605b0f249b57d283fe1a8ee60 Mon Sep 17 00:00:00 2001
> > From: Tetsuo Handa 
> > Date: Mon, 19 May 2014 17:59:03 +0900
> > Subject: [PATCH] gpu/drm/ttm: Pass GFP flags in order to avoid deadlock.
> > 
> > Commit 7dc19d5a "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 
> > ---
> >  drivers/gpu/drm/ttm/ttm_page_alloc.c | 19 ++-
> >  drivers/gpu/drm/ttm/ttm_page_alloc_dma.c | 19 +--
> >  2 files changed, 19 insertions(+), 19 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c 
> > b/drivers/gpu/drm/ttm/ttm_page_alloc.c
> > index 863bef9..ba8f78e 100644
> > --- a/drivers/gpu/drm/ttm/ttm_page_alloc.c
> > +++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c
> > @@ -297,8 +297,10 @@ static void ttm_pool_update_free_locked(struct 
> > ttm_page_pool *pool,
> >   *
> >   * @pool: to free the pages from
> >   * @free_all: If set to true will free all pages in pool
> > + * @gfp: GFP flags.
> >   **/
> > -static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free)
> > +static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free,
> > + gfp_t gfp)
> >  {
> > unsigned long irq_flags;
> > struct page *p;
> > @@ -309,8 +311,7 @@ static int ttm_page_pool_free(struct ttm_page_pool 
> > *pool, unsigned nr_free)
> > if (NUM_PAGES_TO_ALLOC < nr_free)
> > npages_to_free = NUM_PAGES_TO_ALLOC;
> >  
> > -   pages_to_free = kmalloc(npages_to_free * sizeof(struct page *),
> > -   GFP_KERNEL);
> > +   pages_to_free = kmalloc(npages_to_free * sizeof(struct page *), gfp);
> > if (!pages_to_free) {
> > pr_err("Failed to allocate memory for pool free operation\n");
> > return 0;
> > @@ -382,9 +383,7 @@ out:
> >   *
> >   * XXX: (dchinner) Deadlock warning!
> >   *
> > - * ttm_page_pool_free() does memory allocation using GFP_KERNEL.  that 
> > means
> > - * this can deadlock when called a sc->gfp_mask that is not equal to
> > - * GFP_KERNEL.
> > + * We need to pass sc->gfp_mask to ttm_page_pool_free().
> >   *
> >   * This code is crying out for a shrinker per pool
> >   */
> > @@ -405,7 +404,8 @@ ttm_pool_shrink_scan(struct shrinker *shrink, struct 
> > shrink_control *sc)
> > if (shrink_pages == 0)
> > break;
> > pool = &_manager->pools[(i + pool_offset)%NUM_POOLS];
> > -   shrink_pages = ttm_page_pool_free(pool, nr_free);
> > +   shrink_pages = ttm_page_pool_free(pool, nr_free,
> > + sc->gfp_mask);
> > freed += nr_free - shrink_pages;
> > }
> > return freed;
> > @@ -706,7 +706,7 @@ static void ttm_put_pages(struct page **pages, unsigned 
> > npages, int flags,
> > }
> > spin_unlock_irqrestore(>lock, irq_flags);
> > if (npages)
> > -   ttm_page_pool_free(pool, npages);
> > +   ttm_page_pool_free(pool, npages, GFP_KERNEL);
> >  }
> >  
> >  /*
> > @@ -846,7 +846,8 @@ void ttm_page_alloc_fini(void)
> > ttm_pool_mm_shrink_fini(_manager);
> >  
> > for (i = 0; i < NUM_POOLS; ++i)
> > -   ttm_page_pool_free(&_manager->pools[i], FREE_ALL_PAGES);
> > +   ttm_page_pool_free(&_manager->pools[i], FREE_ALL_PAGES,
> > +  GFP_KERNEL);
> >  
> > kobject_put(&_manager->kobj);
> > _manager = NULL;
> > diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c 
> > b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
> > index fb8259f..1b79bf0 100644
> > --- a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
> > +++ b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
> > @@ -411,8 +411,10 @@ static void ttm_dma_page_put(struct dma_pool *pool, 
> > struct dma_page *d_page)
> >   *
>

Re: [PATCH] gpu/drm/ttm: Pass GFP flags in order to avoid deadlock.

2014-05-20 Thread Konrad Rzeszutek Wilk
On Tue, May 20, 2014 at 01:40:40AM +0100, Dave Airlie wrote:
 
 cc'ing dri-devel.

It looks pretty simple and correct . I can test it tomorrow and make sure it 
works
right.
 
  From d0d57745ba23faf605b0f249b57d283fe1a8ee60 Mon Sep 17 00:00:00 2001
  From: Tetsuo Handa penguin-ker...@i-love.sakura.ne.jp
  Date: Mon, 19 May 2014 17:59:03 +0900
  Subject: [PATCH] gpu/drm/ttm: Pass GFP flags in order to avoid deadlock.
  
  Commit 7dc19d5a 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-ker...@i-love.sakura.ne.jp
  ---
   drivers/gpu/drm/ttm/ttm_page_alloc.c | 19 ++-
   drivers/gpu/drm/ttm/ttm_page_alloc_dma.c | 19 +--
   2 files changed, 19 insertions(+), 19 deletions(-)
  
  diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c 
  b/drivers/gpu/drm/ttm/ttm_page_alloc.c
  index 863bef9..ba8f78e 100644
  --- a/drivers/gpu/drm/ttm/ttm_page_alloc.c
  +++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c
  @@ -297,8 +297,10 @@ static void ttm_pool_update_free_locked(struct 
  ttm_page_pool *pool,
*
* @pool: to free the pages from
* @free_all: If set to true will free all pages in pool
  + * @gfp: GFP flags.
**/
  -static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free)
  +static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free,
  + gfp_t gfp)
   {
  unsigned long irq_flags;
  struct page *p;
  @@ -309,8 +311,7 @@ static int ttm_page_pool_free(struct ttm_page_pool 
  *pool, unsigned nr_free)
  if (NUM_PAGES_TO_ALLOC  nr_free)
  npages_to_free = NUM_PAGES_TO_ALLOC;
   
  -   pages_to_free = kmalloc(npages_to_free * sizeof(struct page *),
  -   GFP_KERNEL);
  +   pages_to_free = kmalloc(npages_to_free * sizeof(struct page *), gfp);
  if (!pages_to_free) {
  pr_err(Failed to allocate memory for pool free operation\n);
  return 0;
  @@ -382,9 +383,7 @@ out:
*
* XXX: (dchinner) Deadlock warning!
*
  - * ttm_page_pool_free() does memory allocation using GFP_KERNEL.  that 
  means
  - * this can deadlock when called a sc-gfp_mask that is not equal to
  - * GFP_KERNEL.
  + * We need to pass sc-gfp_mask to ttm_page_pool_free().
*
* This code is crying out for a shrinker per pool
*/
  @@ -405,7 +404,8 @@ ttm_pool_shrink_scan(struct shrinker *shrink, struct 
  shrink_control *sc)
  if (shrink_pages == 0)
  break;
  pool = _manager-pools[(i + pool_offset)%NUM_POOLS];
  -   shrink_pages = ttm_page_pool_free(pool, nr_free);
  +   shrink_pages = ttm_page_pool_free(pool, nr_free,
  + sc-gfp_mask);
  freed += nr_free - shrink_pages;
  }
  return freed;
  @@ -706,7 +706,7 @@ static void ttm_put_pages(struct page **pages, unsigned 
  npages, int flags,
  }
  spin_unlock_irqrestore(pool-lock, irq_flags);
  if (npages)
  -   ttm_page_pool_free(pool, npages);
  +   ttm_page_pool_free(pool, npages, GFP_KERNEL);
   }
   
   /*
  @@ -846,7 +846,8 @@ void ttm_page_alloc_fini(void)
  ttm_pool_mm_shrink_fini(_manager);
   
  for (i = 0; i  NUM_POOLS; ++i)
  -   ttm_page_pool_free(_manager-pools[i], FREE_ALL_PAGES);
  +   ttm_page_pool_free(_manager-pools[i], FREE_ALL_PAGES,
  +  GFP_KERNEL);
   
  kobject_put(_manager-kobj);
  _manager = NULL;
  diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c 
  b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
  index fb8259f..1b79bf0 100644
  --- a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
  +++ b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
  @@ -411,8 +411,10 @@ static void ttm_dma_page_put(struct dma_pool *pool, 
  struct dma_page *d_page)
*
* @pool: to free the pages from
* @nr_free: If set to true will free all pages in pool
  + * @gfp: GFP flags.
**/
  -static unsigned ttm_dma_page_pool_free(struct dma_pool *pool, unsigned 
  nr_free)
  +static unsigned ttm_dma_page_pool_free(struct dma_pool *pool, unsigned 
  nr_free,
  +  gfp_t gfp)
   {
  unsigned long irq_flags;
  struct dma_page *dma_p, *tmp;
  @@ -430,8 +432,7 @@ static unsigned ttm_dma_page_pool_free(struct dma_pool 
  *pool, unsigned nr_free)
   npages_to_free, nr_free);
  }
   #endif
  -   pages_to_free = kmalloc(npages_to_free * sizeof(struct page *),
  -   GFP_KERNEL);
  +   pages_to_free = kmalloc(npages_to_free * sizeof(struct page *), gfp);
   
  if (!pages_to_free) {
  pr_err(%s

Re: [PATCH] gpu/drm/ttm: Pass GFP flags in order to avoid deadlock.

2014-05-19 Thread Dave Airlie

cc'ing dri-devel.

> >From d0d57745ba23faf605b0f249b57d283fe1a8ee60 Mon Sep 17 00:00:00 2001
> From: Tetsuo Handa 
> Date: Mon, 19 May 2014 17:59:03 +0900
> Subject: [PATCH] gpu/drm/ttm: Pass GFP flags in order to avoid deadlock.
> 
> Commit 7dc19d5a "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 
> ---
>  drivers/gpu/drm/ttm/ttm_page_alloc.c | 19 ++-
>  drivers/gpu/drm/ttm/ttm_page_alloc_dma.c | 19 +--
>  2 files changed, 19 insertions(+), 19 deletions(-)
> 
> diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c 
> b/drivers/gpu/drm/ttm/ttm_page_alloc.c
> index 863bef9..ba8f78e 100644
> --- a/drivers/gpu/drm/ttm/ttm_page_alloc.c
> +++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c
> @@ -297,8 +297,10 @@ static void ttm_pool_update_free_locked(struct 
> ttm_page_pool *pool,
>   *
>   * @pool: to free the pages from
>   * @free_all: If set to true will free all pages in pool
> + * @gfp: GFP flags.
>   **/
> -static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free)
> +static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free,
> +   gfp_t gfp)
>  {
>   unsigned long irq_flags;
>   struct page *p;
> @@ -309,8 +311,7 @@ static int ttm_page_pool_free(struct ttm_page_pool *pool, 
> unsigned nr_free)
>   if (NUM_PAGES_TO_ALLOC < nr_free)
>   npages_to_free = NUM_PAGES_TO_ALLOC;
>  
> - pages_to_free = kmalloc(npages_to_free * sizeof(struct page *),
> - GFP_KERNEL);
> + pages_to_free = kmalloc(npages_to_free * sizeof(struct page *), gfp);
>   if (!pages_to_free) {
>   pr_err("Failed to allocate memory for pool free operation\n");
>   return 0;
> @@ -382,9 +383,7 @@ out:
>   *
>   * XXX: (dchinner) Deadlock warning!
>   *
> - * ttm_page_pool_free() does memory allocation using GFP_KERNEL.  that means
> - * this can deadlock when called a sc->gfp_mask that is not equal to
> - * GFP_KERNEL.
> + * We need to pass sc->gfp_mask to ttm_page_pool_free().
>   *
>   * This code is crying out for a shrinker per pool
>   */
> @@ -405,7 +404,8 @@ ttm_pool_shrink_scan(struct shrinker *shrink, struct 
> shrink_control *sc)
>   if (shrink_pages == 0)
>   break;
>   pool = &_manager->pools[(i + pool_offset)%NUM_POOLS];
> - shrink_pages = ttm_page_pool_free(pool, nr_free);
> + shrink_pages = ttm_page_pool_free(pool, nr_free,
> +   sc->gfp_mask);
>   freed += nr_free - shrink_pages;
>   }
>   return freed;
> @@ -706,7 +706,7 @@ static void ttm_put_pages(struct page **pages, unsigned 
> npages, int flags,
>   }
>   spin_unlock_irqrestore(>lock, irq_flags);
>   if (npages)
> - ttm_page_pool_free(pool, npages);
> + ttm_page_pool_free(pool, npages, GFP_KERNEL);
>  }
>  
>  /*
> @@ -846,7 +846,8 @@ void ttm_page_alloc_fini(void)
>   ttm_pool_mm_shrink_fini(_manager);
>  
>   for (i = 0; i < NUM_POOLS; ++i)
> - ttm_page_pool_free(&_manager->pools[i], FREE_ALL_PAGES);
> + ttm_page_pool_free(&_manager->pools[i], FREE_ALL_PAGES,
> +GFP_KERNEL);
>  
>   kobject_put(&_manager->kobj);
>   _manager = NULL;
> diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c 
> b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
> index fb8259f..1b79bf0 100644
> --- a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
> +++ b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
> @@ -411,8 +411,10 @@ static void ttm_dma_page_put(struct dma_pool *pool, 
> struct dma_page *d_page)
>   *
>   * @pool: to free the pages from
>   * @nr_free: If set to true will free all pages in pool
> + * @gfp: GFP flags.
>   **/
> -static unsigned ttm_dma_page_pool_free(struct dma_pool *pool, unsigned 
> nr_free)
> +static unsigned ttm_dma_page_pool_free(struct dma_pool *pool, unsigned 
> nr_free,
> +gfp_t gfp)
>  {
>   unsigned long irq_flags;
>   struct dma_page *dma_p, *tmp;
> @@ -430,8 +432,7 @@ static unsigned ttm_dma_page_pool_free(struct dma_pool 
> *pool, unsigned nr_free)
>npages_to_f

[PATCH] gpu/drm/ttm: Pass GFP flags in order to avoid deadlock.

2014-05-19 Thread Tetsuo Handa
>From d0d57745ba23faf605b0f249b57d283fe1a8ee60 Mon Sep 17 00:00:00 2001
From: Tetsuo Handa 
Date: Mon, 19 May 2014 17:59:03 +0900
Subject: [PATCH] gpu/drm/ttm: Pass GFP flags in order to avoid deadlock.

Commit 7dc19d5a "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 
---
 drivers/gpu/drm/ttm/ttm_page_alloc.c | 19 ++-
 drivers/gpu/drm/ttm/ttm_page_alloc_dma.c | 19 +--
 2 files changed, 19 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c 
b/drivers/gpu/drm/ttm/ttm_page_alloc.c
index 863bef9..ba8f78e 100644
--- a/drivers/gpu/drm/ttm/ttm_page_alloc.c
+++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c
@@ -297,8 +297,10 @@ static void ttm_pool_update_free_locked(struct 
ttm_page_pool *pool,
  *
  * @pool: to free the pages from
  * @free_all: If set to true will free all pages in pool
+ * @gfp: GFP flags.
  **/
-static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free)
+static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free,
+ gfp_t gfp)
 {
unsigned long irq_flags;
struct page *p;
@@ -309,8 +311,7 @@ static int ttm_page_pool_free(struct ttm_page_pool *pool, 
unsigned nr_free)
if (NUM_PAGES_TO_ALLOC < nr_free)
npages_to_free = NUM_PAGES_TO_ALLOC;
 
-   pages_to_free = kmalloc(npages_to_free * sizeof(struct page *),
-   GFP_KERNEL);
+   pages_to_free = kmalloc(npages_to_free * sizeof(struct page *), gfp);
if (!pages_to_free) {
pr_err("Failed to allocate memory for pool free operation\n");
return 0;
@@ -382,9 +383,7 @@ out:
  *
  * XXX: (dchinner) Deadlock warning!
  *
- * ttm_page_pool_free() does memory allocation using GFP_KERNEL.  that means
- * this can deadlock when called a sc->gfp_mask that is not equal to
- * GFP_KERNEL.
+ * We need to pass sc->gfp_mask to ttm_page_pool_free().
  *
  * This code is crying out for a shrinker per pool
  */
@@ -405,7 +404,8 @@ ttm_pool_shrink_scan(struct shrinker *shrink, struct 
shrink_control *sc)
if (shrink_pages == 0)
break;
pool = &_manager->pools[(i + pool_offset)%NUM_POOLS];
-   shrink_pages = ttm_page_pool_free(pool, nr_free);
+   shrink_pages = ttm_page_pool_free(pool, nr_free,
+ sc->gfp_mask);
freed += nr_free - shrink_pages;
}
return freed;
@@ -706,7 +706,7 @@ static void ttm_put_pages(struct page **pages, unsigned 
npages, int flags,
}
spin_unlock_irqrestore(>lock, irq_flags);
if (npages)
-   ttm_page_pool_free(pool, npages);
+   ttm_page_pool_free(pool, npages, GFP_KERNEL);
 }
 
 /*
@@ -846,7 +846,8 @@ void ttm_page_alloc_fini(void)
ttm_pool_mm_shrink_fini(_manager);
 
for (i = 0; i < NUM_POOLS; ++i)
-   ttm_page_pool_free(&_manager->pools[i], FREE_ALL_PAGES);
+   ttm_page_pool_free(&_manager->pools[i], FREE_ALL_PAGES,
+  GFP_KERNEL);
 
kobject_put(&_manager->kobj);
_manager = NULL;
diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c 
b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
index fb8259f..1b79bf0 100644
--- a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
+++ b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
@@ -411,8 +411,10 @@ static void ttm_dma_page_put(struct dma_pool *pool, struct 
dma_page *d_page)
  *
  * @pool: to free the pages from
  * @nr_free: If set to true will free all pages in pool
+ * @gfp: GFP flags.
  **/
-static unsigned ttm_dma_page_pool_free(struct dma_pool *pool, unsigned nr_free)
+static unsigned ttm_dma_page_pool_free(struct dma_pool *pool, unsigned nr_free,
+  gfp_t gfp)
 {
unsigned long irq_flags;
struct dma_page *dma_p, *tmp;
@@ -430,8 +432,7 @@ static unsigned ttm_dma_page_pool_free(struct dma_pool 
*pool, unsigned nr_free)
 npages_to_free, nr_free);
}
 #endif
-   pages_to_free = kmalloc(npages_to_free * sizeof(struct page *),
-   GFP_KERNEL);
+   pages_to_free = kmalloc(npages_to_free * sizeof(struct page *), gfp);
 
if (!pages_to_free) {
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)
if (pool->type != type)
continue;

Re: [PATCH] gpu/drm/ttm: Pass GFP flags in order to avoid deadlock.

2014-05-19 Thread Dave Airlie

cc'ing dri-devel.

 From d0d57745ba23faf605b0f249b57d283fe1a8ee60 Mon Sep 17 00:00:00 2001
 From: Tetsuo Handa penguin-ker...@i-love.sakura.ne.jp
 Date: Mon, 19 May 2014 17:59:03 +0900
 Subject: [PATCH] gpu/drm/ttm: Pass GFP flags in order to avoid deadlock.
 
 Commit 7dc19d5a 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-ker...@i-love.sakura.ne.jp
 ---
  drivers/gpu/drm/ttm/ttm_page_alloc.c | 19 ++-
  drivers/gpu/drm/ttm/ttm_page_alloc_dma.c | 19 +--
  2 files changed, 19 insertions(+), 19 deletions(-)
 
 diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c 
 b/drivers/gpu/drm/ttm/ttm_page_alloc.c
 index 863bef9..ba8f78e 100644
 --- a/drivers/gpu/drm/ttm/ttm_page_alloc.c
 +++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c
 @@ -297,8 +297,10 @@ static void ttm_pool_update_free_locked(struct 
 ttm_page_pool *pool,
   *
   * @pool: to free the pages from
   * @free_all: If set to true will free all pages in pool
 + * @gfp: GFP flags.
   **/
 -static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free)
 +static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free,
 +   gfp_t gfp)
  {
   unsigned long irq_flags;
   struct page *p;
 @@ -309,8 +311,7 @@ static int ttm_page_pool_free(struct ttm_page_pool *pool, 
 unsigned nr_free)
   if (NUM_PAGES_TO_ALLOC  nr_free)
   npages_to_free = NUM_PAGES_TO_ALLOC;
  
 - pages_to_free = kmalloc(npages_to_free * sizeof(struct page *),
 - GFP_KERNEL);
 + pages_to_free = kmalloc(npages_to_free * sizeof(struct page *), gfp);
   if (!pages_to_free) {
   pr_err(Failed to allocate memory for pool free operation\n);
   return 0;
 @@ -382,9 +383,7 @@ out:
   *
   * XXX: (dchinner) Deadlock warning!
   *
 - * ttm_page_pool_free() does memory allocation using GFP_KERNEL.  that means
 - * this can deadlock when called a sc-gfp_mask that is not equal to
 - * GFP_KERNEL.
 + * We need to pass sc-gfp_mask to ttm_page_pool_free().
   *
   * This code is crying out for a shrinker per pool
   */
 @@ -405,7 +404,8 @@ ttm_pool_shrink_scan(struct shrinker *shrink, struct 
 shrink_control *sc)
   if (shrink_pages == 0)
   break;
   pool = _manager-pools[(i + pool_offset)%NUM_POOLS];
 - shrink_pages = ttm_page_pool_free(pool, nr_free);
 + shrink_pages = ttm_page_pool_free(pool, nr_free,
 +   sc-gfp_mask);
   freed += nr_free - shrink_pages;
   }
   return freed;
 @@ -706,7 +706,7 @@ static void ttm_put_pages(struct page **pages, unsigned 
 npages, int flags,
   }
   spin_unlock_irqrestore(pool-lock, irq_flags);
   if (npages)
 - ttm_page_pool_free(pool, npages);
 + ttm_page_pool_free(pool, npages, GFP_KERNEL);
  }
  
  /*
 @@ -846,7 +846,8 @@ void ttm_page_alloc_fini(void)
   ttm_pool_mm_shrink_fini(_manager);
  
   for (i = 0; i  NUM_POOLS; ++i)
 - ttm_page_pool_free(_manager-pools[i], FREE_ALL_PAGES);
 + ttm_page_pool_free(_manager-pools[i], FREE_ALL_PAGES,
 +GFP_KERNEL);
  
   kobject_put(_manager-kobj);
   _manager = NULL;
 diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c 
 b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
 index fb8259f..1b79bf0 100644
 --- a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
 +++ b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
 @@ -411,8 +411,10 @@ static void ttm_dma_page_put(struct dma_pool *pool, 
 struct dma_page *d_page)
   *
   * @pool: to free the pages from
   * @nr_free: If set to true will free all pages in pool
 + * @gfp: GFP flags.
   **/
 -static unsigned ttm_dma_page_pool_free(struct dma_pool *pool, unsigned 
 nr_free)
 +static unsigned ttm_dma_page_pool_free(struct dma_pool *pool, unsigned 
 nr_free,
 +gfp_t gfp)
  {
   unsigned long irq_flags;
   struct dma_page *dma_p, *tmp;
 @@ -430,8 +432,7 @@ static unsigned ttm_dma_page_pool_free(struct dma_pool 
 *pool, unsigned nr_free)
npages_to_free, nr_free);
   }
  #endif
 - pages_to_free = kmalloc(npages_to_free * sizeof(struct page *),
 - GFP_KERNEL);
 + pages_to_free = kmalloc(npages_to_free * sizeof(struct page *), gfp);
  
   if (!pages_to_free) {
   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)
   if (pool-type != type

[PATCH] gpu/drm/ttm: Pass GFP flags in order to avoid deadlock.

2014-05-19 Thread Tetsuo Handa
From d0d57745ba23faf605b0f249b57d283fe1a8ee60 Mon Sep 17 00:00:00 2001
From: Tetsuo Handa penguin-ker...@i-love.sakura.ne.jp
Date: Mon, 19 May 2014 17:59:03 +0900
Subject: [PATCH] gpu/drm/ttm: Pass GFP flags in order to avoid deadlock.

Commit 7dc19d5a 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-ker...@i-love.sakura.ne.jp
---
 drivers/gpu/drm/ttm/ttm_page_alloc.c | 19 ++-
 drivers/gpu/drm/ttm/ttm_page_alloc_dma.c | 19 +--
 2 files changed, 19 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c 
b/drivers/gpu/drm/ttm/ttm_page_alloc.c
index 863bef9..ba8f78e 100644
--- a/drivers/gpu/drm/ttm/ttm_page_alloc.c
+++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c
@@ -297,8 +297,10 @@ static void ttm_pool_update_free_locked(struct 
ttm_page_pool *pool,
  *
  * @pool: to free the pages from
  * @free_all: If set to true will free all pages in pool
+ * @gfp: GFP flags.
  **/
-static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free)
+static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free,
+ gfp_t gfp)
 {
unsigned long irq_flags;
struct page *p;
@@ -309,8 +311,7 @@ static int ttm_page_pool_free(struct ttm_page_pool *pool, 
unsigned nr_free)
if (NUM_PAGES_TO_ALLOC  nr_free)
npages_to_free = NUM_PAGES_TO_ALLOC;
 
-   pages_to_free = kmalloc(npages_to_free * sizeof(struct page *),
-   GFP_KERNEL);
+   pages_to_free = kmalloc(npages_to_free * sizeof(struct page *), gfp);
if (!pages_to_free) {
pr_err(Failed to allocate memory for pool free operation\n);
return 0;
@@ -382,9 +383,7 @@ out:
  *
  * XXX: (dchinner) Deadlock warning!
  *
- * ttm_page_pool_free() does memory allocation using GFP_KERNEL.  that means
- * this can deadlock when called a sc-gfp_mask that is not equal to
- * GFP_KERNEL.
+ * We need to pass sc-gfp_mask to ttm_page_pool_free().
  *
  * This code is crying out for a shrinker per pool
  */
@@ -405,7 +404,8 @@ ttm_pool_shrink_scan(struct shrinker *shrink, struct 
shrink_control *sc)
if (shrink_pages == 0)
break;
pool = _manager-pools[(i + pool_offset)%NUM_POOLS];
-   shrink_pages = ttm_page_pool_free(pool, nr_free);
+   shrink_pages = ttm_page_pool_free(pool, nr_free,
+ sc-gfp_mask);
freed += nr_free - shrink_pages;
}
return freed;
@@ -706,7 +706,7 @@ static void ttm_put_pages(struct page **pages, unsigned 
npages, int flags,
}
spin_unlock_irqrestore(pool-lock, irq_flags);
if (npages)
-   ttm_page_pool_free(pool, npages);
+   ttm_page_pool_free(pool, npages, GFP_KERNEL);
 }
 
 /*
@@ -846,7 +846,8 @@ void ttm_page_alloc_fini(void)
ttm_pool_mm_shrink_fini(_manager);
 
for (i = 0; i  NUM_POOLS; ++i)
-   ttm_page_pool_free(_manager-pools[i], FREE_ALL_PAGES);
+   ttm_page_pool_free(_manager-pools[i], FREE_ALL_PAGES,
+  GFP_KERNEL);
 
kobject_put(_manager-kobj);
_manager = NULL;
diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c 
b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
index fb8259f..1b79bf0 100644
--- a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
+++ b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
@@ -411,8 +411,10 @@ static void ttm_dma_page_put(struct dma_pool *pool, struct 
dma_page *d_page)
  *
  * @pool: to free the pages from
  * @nr_free: If set to true will free all pages in pool
+ * @gfp: GFP flags.
  **/
-static unsigned ttm_dma_page_pool_free(struct dma_pool *pool, unsigned nr_free)
+static unsigned ttm_dma_page_pool_free(struct dma_pool *pool, unsigned nr_free,
+  gfp_t gfp)
 {
unsigned long irq_flags;
struct dma_page *dma_p, *tmp;
@@ -430,8 +432,7 @@ static unsigned ttm_dma_page_pool_free(struct dma_pool 
*pool, unsigned nr_free)
 npages_to_free, nr_free);
}
 #endif
-   pages_to_free = kmalloc(npages_to_free * sizeof(struct page *),
-   GFP_KERNEL);
+   pages_to_free = kmalloc(npages_to_free * sizeof(struct page *), gfp);
 
if (!pages_to_free) {
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)
if (pool-type != type)
continue;
/* Takes a spinlock