Skip to contentSkip to conversation

drm/ttm: add page order in page pool

PATCH In review Roger He 6 participants 11 messages Nov 22, 2017 4 messages not in the archive

Subsystems (3)
lore
Share & tools
lore

Roger He

author
#0 lore raw

PATCH 1/4 drm/ttm: add page order in page pool

to indicate page order for each element in the pool

Change-Id Ic609925ca5d2a5d4ad49d6becf505388ce3624cf
---
 drivers/gpu/drm/ttm/ttm_page_alloc.c | 42 ++++++++++++++++++++++++++----------
 1 file changed, 31 insertions(+), 11 deletions(-)
drivers/gpu/drm/ttm/ttm_page_alloc.c +31 -11
index 72ea037..0a0c653 100644
@@ -81,6 +81,7 @@ struct ttm_page_pool {
 	char			*name;
 	unsigned long		nfrees;
 	unsigned long		nrefills;
+	unsigned int		order;
 };
 
 /**
@@ -412,6 +413,7 @@ ttm_pool_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
 	struct ttm_page_pool *pool;
 	int shrink_pages = sc->nr_to_scan;
 	unsigned long freed = 0;
+	unsigned int nr_free_pool;
 
 	if (!mutex_trylock(&lock))
 		return SHRINK_STOP;
@@ -421,10 +423,15 @@ ttm_pool_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
 		unsigned nr_free = shrink_pages;
 		if (shrink_pages == 0)
 			break;
+
 		pool = &_manager->pools[(i + pool_offset)%NUM_POOLS];
 		/* OK to use static buffer since global mutex is held. */
-		shrink_pages = ttm_page_pool_free(pool, nr_free, true);
-		freed += nr_free - shrink_pages;
+		nr_free_pool = (nr_free >> pool->order);
+		if (nr_free_pool == 0)
+			continue;
+
+		shrink_pages = ttm_page_pool_free(pool, nr_free_pool, true);
+		freed += ((nr_free_pool - shrink_pages) << pool->order);
 	}
 	mutex_unlock(&lock);
 	return freed;
@@ -436,9 +443,12 @@ ttm_pool_shrink_count(struct shrinker *shrink, struct shrink_control *sc)
 {
 	unsigned i;
 	unsigned long count = 0;
+	struct ttm_page_pool *pool;
 
-	for (i = 0; i < NUM_POOLS; ++i)
-		count += _manager->pools[i].npages;
+	for (i = 0; i < NUM_POOLS; ++i) {
+		pool = &_manager->pools[i];
+		count += (pool->npages << pool->order);
+	}
 
 	return count;
 }
@@ -932,7 +942,7 @@ static int ttm_get_pages(struct page **pages, unsigned npages, int flags,
 }
 
 static void ttm_page_pool_init_locked(struct ttm_page_pool *pool, gfp_t flags,
-		char *name)
+		char *name, unsigned int order)
 {
 	spin_lock_init(&pool->lock);
 	pool->fill_lock = false;
@@ -940,8 +950,18 @@ static void ttm_page_pool_init_locked(struct ttm_page_pool *pool, gfp_t flags,
 	pool->npages = pool->nfrees = 0;
 	pool->gfp_flags = flags;
 	pool->name = name;
+	pool->order = order;
 }
 
+/**
+ * Actually if TRANSPARENT_HUGEPAGE not enabled, we will not use
+ * wc_pool_huge and uc_pool_huge, so no matter whatever the page
+ * order are for those two pools
+ */
+#ifndef CONFIG_TRANSPARENT_HUGEPAGE
+#define	HPAGE_PMD_ORDER	9
+#endif
+
 int ttm_page_alloc_init(struct ttm_mem_global *glob, unsigned max_pages)
 {
 	int ret;
@@ -952,23 +972,23 @@ int ttm_page_alloc_init(struct ttm_mem_global *glob, unsigned max_pages)
 
 	_manager = kzalloc(sizeof(*_manager), GFP_KERNEL);
 
-	ttm_page_pool_init_locked(&_manager->wc_pool, GFP_HIGHUSER, "wc");
+	ttm_page_pool_init_locked(&_manager->wc_pool, GFP_HIGHUSER, "wc", 0);
 
-	ttm_page_pool_init_locked(&_manager->uc_pool, GFP_HIGHUSER, "uc");
+	ttm_page_pool_init_locked(&_manager->uc_pool, GFP_HIGHUSER, "uc", 0);
 
 	ttm_page_pool_init_locked(&_manager->wc_pool_dma32,
-				  GFP_USER | GFP_DMA32, "wc dma");
+				  GFP_USER | GFP_DMA32, "wc dma", 0);
 
 	ttm_page_pool_init_locked(&_manager->uc_pool_dma32,
-				  GFP_USER | GFP_DMA32, "uc dma");
+				  GFP_USER | GFP_DMA32, "uc dma", 0);
 
 	ttm_page_pool_init_locked(&_manager->wc_pool_huge,
 				  GFP_TRANSHUGE	& ~(__GFP_MOVABLE | __GFP_COMP),
-				  "wc huge");
+				  "wc huge", HPAGE_PMD_ORDER);
 
 	ttm_page_pool_init_locked(&_manager->uc_pool_huge,
 				  GFP_TRANSHUGE	& ~(__GFP_MOVABLE | __GFP_COMP)
-				  , "uc huge");
+				  , "uc huge", HPAGE_PMD_ORDER);
 
 	_manager->options.max_size = max_pages;
 	_manager->options.small = SMALL_ALLOCATION;
Signature · 6 lines
2.7.4

_______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx
#1 lore raw

PATCH 2/4 drm/ttm: add page order support in ttm_pages_put

Change-Id Ia55b206d95812c5afcfd6cec29f580758d1f50f0
---
 drivers/gpu/drm/ttm/ttm_page_alloc.c | 42 +++++++++++++++++++++++++++++-------
 1 file changed, 34 insertions(+), 8 deletions(-)
drivers/gpu/drm/ttm/ttm_page_alloc.c +34 -8
index 0a0c653..de64209 100644
@@ -285,13 +285,39 @@ static struct ttm_page_pool *ttm_get_pool(int flags, bool huge,
 }
 
 /* set memory back to wb and free the pages. */
-static void ttm_pages_put(struct page *pages[], unsigned npages)
+static void ttm_pages_put(struct page *pages[], unsigned npages,
+		unsigned int order)
 {
-	unsigned i;
-	if (set_pages_array_wb(pages, npages))
-		pr_err("Failed to set %d pages to wb!\n", npages);
-	for (i = 0; i < npages; ++i)
-		__free_page(pages[i]);
+	struct page **pages_to_free = NULL;
+	struct page **pages_array;
+	struct page *p;
+	unsigned int i, j, pages_nr = (1 << order);
+
+	if (order > 0) {
+		pages_to_free = kmalloc_array(pages_nr, sizeof(struct page *),
+					GFP_KERNEL);
+		if (!pages_to_free) {
+			pr_err("Failed to allocate memory for ttm pages put operation\n");
+			return;
+		}
+	}
+
+	for (i = 0; i < npages; ++i) {
+		if (order > 0) {
+			p = pages[i];
+			for (j = 0; j < pages_nr; ++j)
+				pages_to_free[j] = p++;
+
+			pages_array = pages_to_free;
+		} else
+			pages_array = pages;
+
+		if (set_pages_array_wb(pages_array, pages_nr))
+			pr_err("Failed to set %d pages to wb!\n", pages_nr);
+		__free_pages(pages[i], order);
+	}
+
+	kfree(pages_to_free);
 }
 
 static void ttm_pool_update_free_locked(struct ttm_page_pool *pool,
@@ -354,7 +380,7 @@ static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free,
 			 */
 			spin_unlock_irqrestore(&pool->lock, irq_flags);
 
-			ttm_pages_put(pages_to_free, freed_pages);
+			ttm_pages_put(pages_to_free, freed_pages, pool->order);
 			if (likely(nr_free != FREE_ALL_PAGES))
 				nr_free -= freed_pages;
 
@@ -389,7 +415,7 @@ static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free,
 	spin_unlock_irqrestore(&pool->lock, irq_flags);
 
 	if (freed_pages)
-		ttm_pages_put(pages_to_free, freed_pages);
+		ttm_pages_put(pages_to_free, freed_pages, pool->order);
 out:
 	if (pages_to_free != static_buf)
 		kfree(pages_to_free);
Signature · 6 lines
2.7.4

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
#2 lore raw

Re: [PATCH 2/4] drm/ttm: add page order support in ttm_pages_put

Quoted 30 lines · Roger He
Change-Id Ia55b206d95812c5afcfd6cec29f580758d1f50f0
---
  drivers/gpu/drm/ttm/ttm_page_alloc.c | 42 +++++++++++++++++++++++++++++-------
  1 file changed, 34 insertions(+), 8 deletions(-)
drivers/gpu/drm/ttm/ttm_page_alloc.c +9 -6
index 0a0c653..de64209 100644
@@ -285,13 +285,39 @@ static struct ttm_page_pool *ttm_get_pool(int flags, bool huge,
  }
 
  /* set memory back to wb and free the pages. */
-static void ttm_pages_put(struct page *pages[], unsigned npages)
+static void ttm_pages_put(struct page *pages[], unsigned npages,
+		unsigned int order)
  {
-	unsigned i;
-	if (set_pages_array_wb(pages, npages))
-		pr_err("Failed to set %d pages to wb!\n", npages);
-	for (i = 0; i < npages; ++i)
-		__free_page(pages[i]);
+	struct page **pages_to_free = NULL;
+	struct page **pages_array;
+	struct page *p;
+	unsigned int i, j, pages_nr = (1 << order);
+
+	if (order > 0) {
+		pages_to_free = kmalloc_array(pages_nr, sizeof(struct page *),

drivers/gpu/drm/ttm/ttm_page_alloc.c static struct ttm_page_pool *ttm_get_pool(int flags, bool huge, · line 307

Quoted 10 lines
drivers/gpu/drm/ttm/ttm_page_alloc.c +9 -0
+					GFP_KERNEL);
+		if (!pages_to_free) {
+			pr_err("Failed to allocate memory for ttm pages put operation\n");
+			return;
+		}
+	}
+
+	for (i = 0; i < npages; ++i) {
+ if (order > 0) { + p = pages[i]; + for (j = 0; j < pages_nr; ++j) + 
 pages_to_free[j] = p++; + + pages_array = pages_to_free; + } else + pages_array = pages; + + if (set_pages_array_wb(pages_array, pages_nr))

you can use set_pages_wb(pages[i], 1 << order) to instead of creating page array marked red, this way, you will not need to kmalloc and patch#3.

and more, if you select set_pages_wb, you also need to clone it in TTM like set_pages_array_wb for non-x86 case.

Regards,
David Zhou

Quoted 18 lines
drivers/gpu/drm/ttm/ttm_page_alloc.c +6 -1
+			pr_err("Failed to set %d pages to wb!\n", pages_nr);
+		__free_pages(pages[i], order);
+	}
+
+	kfree(pages_to_free);
  }
 
  static void ttm_pool_update_free_locked(struct ttm_page_pool *pool,
@@ -354,7 +380,7 @@ static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free,
  			 */
  			spin_unlock_irqrestore(&pool->lock, irq_flags);
 
-			ttm_pages_put(pages_to_free, freed_pages);
+			ttm_pages_put(pages_to_free, freed_pages, pool->order);
  			if (likely(nr_free != FREE_ALL_PAGES))
  				nr_free -= freed_pages;
 

drivers/gpu/drm/ttm/ttm_page_alloc.c static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free, · line 421

Quoted 8 lines
drivers/gpu/drm/ttm/ttm_page_alloc.c +1 -1
@@ -389,7 +415,7 @@ static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free,
  	spin_unlock_irqrestore(&pool->lock, irq_flags);
 
  	if (freed_pages)
-		ttm_pages_put(pages_to_free, freed_pages);
+		ttm_pages_put(pages_to_free, freed_pages, pool->order);
  out:
  	if (pages_to_free != static_buf)
  		kfree(pages_to_free);

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel

#3 lore raw

RE: [PATCH 2/4] drm/ttm: add page order support in ttm_pages_put

From: dri-devel [mailto:[email protected]] On Behalf Of Chunming Zhou
Sent: Wednesday, November 22, 2017 2:02 PM
To: [email protected]
Subject: Re: [PATCH 2/4] drm/ttm: add page order support in ttm_pages_put

On 2017年11月22日 13:36, Roger He wrote:

Change-Id: Ia55b206d95812c5afcfd6cec29f580758d1f50f0

---

 drivers/gpu/drm/ttm/ttm_page_alloc.c | 42 +++++++++++++++++++++++++++++-------
 1 file changed, 34 insertions(+), 8 deletions(-)
drivers/gpu/drm/ttm/ttm_page_alloc.c +0 -0

index 0a0c653..de64209 100644

--- a/drivers/gpu/drm/ttm/ttm_page_alloc.c

+++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c

@@ -285,13 +285,39 @@ static struct ttm_page_pool *ttm_get_pool(int flags, bool huge,

}

/* set memory back to wb and free the pages. */

-static void ttm_pages_put(struct page *pages[], unsigned npages)

+static void ttm_pages_put(struct page *pages[], unsigned npages,

+ unsigned int order)

{

- unsigned i;

- if (set_pages_array_wb(pages, npages))

- pr_err("Failed to set %d pages to wb!\n", npages);

- for (i = 0; i < npages; ++i)

- __free_page(pages[i]);

+ struct page **pages_to_free = NULL;

+ struct page **pages_array;

+ struct page *p;

+ unsigned int i, j, pages_nr = (1 << order);

+

+ if (order > 0) {

+ pages_to_free = kmalloc_array(pages_nr, sizeof(struct page *),

+ GFP_KERNEL);

+ if (!pages_to_free) {

+ pr_err("Failed to allocate memory for ttm pages put operation\n");

+ return;

+ }

+ }

+

+ for (i = 0; i < npages; ++i) {

+ if (order > 0) {

+ p = pages[i];

+ for (j = 0; j < pages_nr; ++j)

+ pages_to_free[j] = p++;

+

+ pages_array = pages_to_free;

+ } else

+ pages_array = pages;

+

+ if (set_pages_array_wb(pages_array, pages_nr))
you can use set_pages_wb(pages[i], 1 << order) to instead of creating page array marked red, this way, you will not need to kmalloc and patch#3.

and more, if you select set_pages_wb, you also need to clone it in TTM like set_pages_array_wb for non-x86 case.

good idea, going to refine code.

Thanks
Roger(Hongbo.He)

Regards,
David Zhou

+ pr_err("Failed to set %d pages to wb!\n", pages_nr);

+ __free_pages(pages[i], order);

+ }

+

+ kfree(pages_to_free);

}

static void ttm_pool_update_free_locked(struct ttm_page_pool *pool,

@@ -354,7 +380,7 @@ static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free,

                  */

                 spin_unlock_irqrestore(&pool->lock, irq_flags);

- ttm_pages_put(pages_to_free, freed_pages);

+ ttm_pages_put(pages_to_free, freed_pages, pool->order);

                 if (likely(nr_free != FREE_ALL_PAGES))

                         nr_free -= freed_pages;

@@ -389,7 +415,7 @@ static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free,

  spin_unlock_irqrestore(&pool->lock, irq_flags);

if (freed_pages)

- ttm_pages_put(pages_to_free, freed_pages);

+ ttm_pages_put(pages_to_free, freed_pages, pool->order);

out:

if (pages_to_free != static_buf)

         kfree(pages_to_free);

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel

A message that is not in the archive (sent off-list or not yet received): 1511329016-552-2-git-send-email-Hongbo.He-5C7GfCeVMHo@public.gmane.org

#5 lore raw

Re: [PATCH 2/4] drm/ttm: add page order support in ttm_pages_put

I would rather completely nuke ttm_pages_put() instead of coming up with more workarounds here.

Going to provide a cleanup patch to show what I mean, just give me a minute.

Regards,
Christian.

Am 22.11.2017 um 06:36 schrieb Roger He:

Quoted 66 lines
Change-Id Ia55b206d95812c5afcfd6cec29f580758d1f50f0
---
  drivers/gpu/drm/ttm/ttm_page_alloc.c | 42 +++++++++++++++++++++++++++++-------
  1 file changed, 34 insertions(+), 8 deletions(-)
drivers/gpu/drm/ttm/ttm_page_alloc.c +33 -7
index 0a0c653..de64209 100644
@@ -285,13 +285,39 @@ static struct ttm_page_pool *ttm_get_pool(int flags, bool huge,
  }
 
  /* set memory back to wb and free the pages. */
-static void ttm_pages_put(struct page *pages[], unsigned npages)
+static void ttm_pages_put(struct page *pages[], unsigned npages,
+		unsigned int order)
  {
-	unsigned i;
-	if (set_pages_array_wb(pages, npages))
-		pr_err("Failed to set %d pages to wb!\n", npages);
-	for (i = 0; i < npages; ++i)
-		__free_page(pages[i]);
+	struct page **pages_to_free = NULL;
+	struct page **pages_array;
+	struct page *p;
+	unsigned int i, j, pages_nr = (1 << order);
+
+	if (order > 0) {
+		pages_to_free = kmalloc_array(pages_nr, sizeof(struct page *),
+					GFP_KERNEL);
+		if (!pages_to_free) {
+			pr_err("Failed to allocate memory for ttm pages put operation\n");
+			return;
+		}
+	}
+
+	for (i = 0; i < npages; ++i) {
+		if (order > 0) {
+			p = pages[i];
+			for (j = 0; j < pages_nr; ++j)
+				pages_to_free[j] = p++;
+
+			pages_array = pages_to_free;
+		} else
+			pages_array = pages;
+
+		if (set_pages_array_wb(pages_array, pages_nr))
+			pr_err("Failed to set %d pages to wb!\n", pages_nr);
+		__free_pages(pages[i], order);
+	}
+
+	kfree(pages_to_free);
  }
 
  static void ttm_pool_update_free_locked(struct ttm_page_pool *pool,
@@ -354,7 +380,7 @@ static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free,
  			 */
  			spin_unlock_irqrestore(&pool->lock, irq_flags);
 
-			ttm_pages_put(pages_to_free, freed_pages);
+			ttm_pages_put(pages_to_free, freed_pages, pool->order);
  			if (likely(nr_free != FREE_ALL_PAGES))
  				nr_free -= freed_pages;
 

drivers/gpu/drm/ttm/ttm_page_alloc.c static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free, · line 421

Quoted 8 lines
drivers/gpu/drm/ttm/ttm_page_alloc.c +1 -1
@@ -389,7 +415,7 @@ static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free,
  	spin_unlock_irqrestore(&pool->lock, irq_flags);
 
  	if (freed_pages)
-		ttm_pages_put(pages_to_free, freed_pages);
+		ttm_pages_put(pages_to_free, freed_pages, pool->order);
  out:
  	if (pages_to_free != static_buf)
  		kfree(pages_to_free);

_______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

A message that is not in the archive (sent off-list or not yet received): b6c683f7-0fda-e6cd-f1d4-6037c889eca6-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org

author
#7 lore raw

RE: [PATCH 2/4] drm/ttm: add page order support in ttm_pages_put

Hi Christian:

This is old patch, I already send new patches. And it is clean and simple. Please check that.

Thanks
Roger(Hongbo.He)

-----Original Message-----
From: Christian König [mailto:[email protected]]
Sent: Wednesday, November 22, 2017 5:29 PM
To: He, Roger <[email protected]>; [email protected]; [email protected]
Cc: Koenig, Christian <[email protected]>
Subject: Re: [PATCH 2/4] drm/ttm: add page order support in ttm_pages_put

I would rather completely nuke ttm_pages_put() instead of coming up with more workarounds here.

Going to provide a cleanup patch to show what I mean, just give me a minute.

Regards,
Christian.

Am 22.11.2017 um 06:36 schrieb Roger He:

Quoted 67 lines
Change-Id Ia55b206d95812c5afcfd6cec29f580758d1f50f0
---
  drivers/gpu/drm/ttm/ttm_page_alloc.c | 42 +++++++++++++++++++++++++++++-------
  1 file changed, 34 insertions(+), 8 deletions(-)
drivers/gpu/drm/ttm/ttm_page_alloc.c +33 -6
index 0a0c653..de64209 100644
@@ -285,13 +285,39 @@ static struct ttm_page_pool *ttm_get_pool(int flags, bool huge,
  }
 
  /* set memory back to wb and free the pages. */ -static void 
 ttm_pages_put(struct page *pages[], unsigned npages)
+static void ttm_pages_put(struct page *pages[], unsigned npages,
+		unsigned int order)
  {
-	unsigned i;
-	if (set_pages_array_wb(pages, npages))
-		pr_err("Failed to set %d pages to wb!\n", npages);
-	for (i = 0; i < npages; ++i)
-		__free_page(pages[i]);
+	struct page **pages_to_free = NULL;
+	struct page **pages_array;
+	struct page *p;
+	unsigned int i, j, pages_nr = (1 << order);
+
+	if (order > 0) {
+		pages_to_free = kmalloc_array(pages_nr, sizeof(struct page *),
+					GFP_KERNEL);
+		if (!pages_to_free) {
+			pr_err("Failed to allocate memory for ttm pages put operation\n");
+			return;
+		}
+	}
+
+	for (i = 0; i < npages; ++i) {
+		if (order > 0) {
+			p = pages[i];
+			for (j = 0; j < pages_nr; ++j)
+				pages_to_free[j] = p++;
+
+			pages_array = pages_to_free;
+		} else
+			pages_array = pages;
+
+		if (set_pages_array_wb(pages_array, pages_nr))
+			pr_err("Failed to set %d pages to wb!\n", pages_nr);
+		__free_pages(pages[i], order);
+	}
+
+	kfree(pages_to_free);
  }
 
  static void ttm_pool_update_free_locked(struct ttm_page_pool *pool, 
@@ -354,7 +380,7 @@ static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free,
  			 */
  			spin_unlock_irqrestore(&pool->lock, irq_flags);
 
-			ttm_pages_put(pages_to_free, freed_pages);
+			ttm_pages_put(pages_to_free, freed_pages, pool->order);
  			if (likely(nr_free != FREE_ALL_PAGES))
  				nr_free -= freed_pages;
 

drivers/gpu/drm/ttm/ttm_page_alloc.c static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free, · line 421

Quoted 8 lines
drivers/gpu/drm/ttm/ttm_page_alloc.c +1 -1
@@ -389,7 +415,7 @@ static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free,
  	spin_unlock_irqrestore(&pool->lock, irq_flags);
 
  	if (freed_pages)
-		ttm_pages_put(pages_to_free, freed_pages);
+		ttm_pages_put(pages_to_free, freed_pages, pool->order);
  out:
  	if (pages_to_free != static_buf)
  		kfree(pages_to_free);

_______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

A message that is not in the archive (sent off-list or not yet received): 1511329016-552-1-git-send-email-Hongbo.He-5C7GfCeVMHo@public.gmane.org

author
#9 lore raw

PATCH 3/4 drm/ttm: add static buffer for ttm_pages_put to support pool shrink

Change-Id Ic20c016eb3043d7cfedc2e3648790a017168da6c
---
 drivers/gpu/drm/ttm/ttm_page_alloc.c | 28 +++++++++++++++++++---------
 1 file changed, 19 insertions(+), 9 deletions(-)
drivers/gpu/drm/ttm/ttm_page_alloc.c +19 -9
index de64209..37c2f2f 100644
@@ -285,20 +285,27 @@ static struct ttm_page_pool *ttm_get_pool(int flags, bool huge,
 }
 
 /* set memory back to wb and free the pages. */
+#define STATIC_BUF_PUT_SIZE 512
 static void ttm_pages_put(struct page *pages[], unsigned npages,
-		unsigned int order)
+		unsigned int order, bool use_static)
 {
+	static struct page *static_buf_put[STATIC_BUF_PUT_SIZE];
 	struct page **pages_to_free = NULL;
 	struct page **pages_array;
 	struct page *p;
 	unsigned int i, j, pages_nr = (1 << order);
 
+	BUG_ON(use_static && pages_nr > STATIC_BUF_PUT_SIZE);
 	if (order > 0) {
-		pages_to_free = kmalloc_array(pages_nr, sizeof(struct page *),
-					GFP_KERNEL);
-		if (!pages_to_free) {
-			pr_err("Failed to allocate memory for ttm pages put operation\n");
-			return;
+		if (use_static)
+			pages_to_free = static_buf_put;
+		else {
+			pages_to_free = kmalloc_array(pages_nr,
+				sizeof(struct page *), GFP_KERNEL);
+			if (!pages_to_free) {
+				pr_err("Failed to allocate memory for ttm pages put operation\n");
+				return;
+			}
 		}
 	}
 
@@ -317,7 +324,8 @@ static void ttm_pages_put(struct page *pages[], unsigned npages,
 		__free_pages(pages[i], order);
 	}
 
-	kfree(pages_to_free);
+	if (!use_static)
+		kfree(pages_to_free);
 }
 
 static void ttm_pool_update_free_locked(struct ttm_page_pool *pool,
@@ -380,7 +388,8 @@ static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free,
 			 */
 			spin_unlock_irqrestore(&pool->lock, irq_flags);
 
-			ttm_pages_put(pages_to_free, freed_pages, pool->order);
+			ttm_pages_put(pages_to_free, freed_pages, pool->order,
+					use_static);
 			if (likely(nr_free != FREE_ALL_PAGES))
 				nr_free -= freed_pages;
 
@@ -415,7 +424,8 @@ static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free,
 	spin_unlock_irqrestore(&pool->lock, irq_flags);
 
 	if (freed_pages)
-		ttm_pages_put(pages_to_free, freed_pages, pool->order);
+		ttm_pages_put(pages_to_free, freed_pages, pool->order,
+			use_static);
 out:
 	if (pages_to_free != static_buf)
 		kfree(pages_to_free);
Signature · 6 lines
2.7.4

_______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx
author
#10 lore raw

PATCH 4/4 drm/ttm: free one in huge pool even shrink request less than one element

In reply to a message not in the archive
Change-Id Id8bd4d1ecff9f3ab14355e2dbd1c59b9fe824e01
---
 drivers/gpu/drm/ttm/ttm_page_alloc.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/gpu/drm/ttm/ttm_page_alloc.c +4 -2
index 37c2f2f..f80fc5b 100644
@@ -463,11 +463,13 @@ ttm_pool_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
 		pool = &_manager->pools[(i + pool_offset)%NUM_POOLS];
 		/* OK to use static buffer since global mutex is held. */
 		nr_free_pool = (nr_free >> pool->order);
-		if (nr_free_pool == 0)
-			continue;
+		if (!nr_free_pool && pool->order)
+			nr_free_pool = 1;
 
 		shrink_pages = ttm_page_pool_free(pool, nr_free_pool, true);
 		freed += ((nr_free_pool - shrink_pages) << pool->order);
+		if (freed >= sc->nr_to_scan)
+			break;
 	}
 	mutex_unlock(&lock);
 	return freed;
Signature · 6 lines
2.7.4

_______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx
#11 lore raw
In reply to a message not in the archive
Quoted 29 lines · Roger He

to indicate page order for each element in the pool

Change-Id Ic609925ca5d2a5d4ad49d6becf505388ce3624cf
---
  drivers/gpu/drm/ttm/ttm_page_alloc.c | 42 ++++++++++++++++++++++++++----------
  1 file changed, 31 insertions(+), 11 deletions(-)
drivers/gpu/drm/ttm/ttm_page_alloc.c +2 -0
index 72ea037..0a0c653 100644
@@ -81,6 +81,7 @@ struct ttm_page_pool {
  	char			*name;
  	unsigned long		nfrees;
  	unsigned long		nrefills;
+	unsigned int		order;
  };
 
  /**
@@ -412,6 +413,7 @@ ttm_pool_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
  	struct ttm_page_pool *pool;
  	int shrink_pages = sc->nr_to_scan;
  	unsigned long freed = 0;
+	unsigned int nr_free_pool;
 
  	if (!mutex_trylock(&lock))
  		return SHRINK_STOP;

drivers/gpu/drm/ttm/ttm_page_alloc.c ttm_pool_shrink_scan(struct shrinker *shrink, struct shrink_control *sc) · line 429

Quoted 9 lines
drivers/gpu/drm/ttm/ttm_page_alloc.c +2 -2
@@ -421,10 +423,15 @@ ttm_pool_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
  		unsigned nr_free = shrink_pages;
  		if (shrink_pages == 0)
  			break;
+
  		pool = &_manager->pools[(i + pool_offset)%NUM_POOLS];
  		/* OK to use static buffer since global mutex is held. */
-		shrink_pages = ttm_page_pool_free(pool, nr_free, true);
-		freed += nr_free - shrink_pages;
+		nr_free_pool = (nr_free >> pool->order);

How about nr_free_pool = roundup(nr_free >> pool->order, 1)? this way, your patch#4 is not need.

Regards,
David Zhou

Quoted 71 lines
drivers/gpu/drm/ttm/ttm_page_alloc.c +25 -7
+		if (nr_free_pool == 0)
+			continue;
+
+		shrink_pages = ttm_page_pool_free(pool, nr_free_pool, true);
+		freed += ((nr_free_pool - shrink_pages) << pool->order);
  	}
  	mutex_unlock(&lock);
  	return freed;
@@ -436,9 +443,12 @@ ttm_pool_shrink_count(struct shrinker *shrink, struct shrink_control *sc)
  {
  	unsigned i;
  	unsigned long count = 0;
+	struct ttm_page_pool *pool;
 
-	for (i = 0; i < NUM_POOLS; ++i)
-		count += _manager->pools[i].npages;
+	for (i = 0; i < NUM_POOLS; ++i) {
+		pool = &_manager->pools[i];
+		count += (pool->npages << pool->order);
+	}
 
  	return count;
  }
@@ -932,7 +942,7 @@ static int ttm_get_pages(struct page **pages, unsigned npages, int flags,
  }
 
  static void ttm_page_pool_init_locked(struct ttm_page_pool *pool, gfp_t flags,
-		char *name)
+		char *name, unsigned int order)
  {
  	spin_lock_init(&pool->lock);
  	pool->fill_lock = false;
@@ -940,8 +950,18 @@ static void ttm_page_pool_init_locked(struct ttm_page_pool *pool, gfp_t flags,
  	pool->npages = pool->nfrees = 0;
  	pool->gfp_flags = flags;
  	pool->name = name;
+	pool->order = order;
  }
 
+/**
+ * Actually if TRANSPARENT_HUGEPAGE not enabled, we will not use
+ * wc_pool_huge and uc_pool_huge, so no matter whatever the page
+ * order are for those two pools
+ */
+#ifndef CONFIG_TRANSPARENT_HUGEPAGE
+#define	HPAGE_PMD_ORDER	9
+#endif
+
  int ttm_page_alloc_init(struct ttm_mem_global *glob, unsigned max_pages)
  {
  	int ret;
@@ -952,23 +972,23 @@ int ttm_page_alloc_init(struct ttm_mem_global *glob, unsigned max_pages)
 
  	_manager = kzalloc(sizeof(*_manager), GFP_KERNEL);
 
-	ttm_page_pool_init_locked(&_manager->wc_pool, GFP_HIGHUSER, "wc");
+	ttm_page_pool_init_locked(&_manager->wc_pool, GFP_HIGHUSER, "wc", 0);
 
-	ttm_page_pool_init_locked(&_manager->uc_pool, GFP_HIGHUSER, "uc");
+	ttm_page_pool_init_locked(&_manager->uc_pool, GFP_HIGHUSER, "uc", 0);
 
  	ttm_page_pool_init_locked(&_manager->wc_pool_dma32,
-				  GFP_USER | GFP_DMA32, "wc dma");
+				  GFP_USER | GFP_DMA32, "wc dma", 0);
 
  	ttm_page_pool_init_locked(&_manager->uc_pool_dma32,
-				  GFP_USER | GFP_DMA32, "uc dma");
+				  GFP_USER | GFP_DMA32, "uc dma", 0);
 
  	ttm_page_pool_init_locked(&_manager->wc_pool_huge,
  				  GFP_TRANSHUGE	& ~(__GFP_MOVABLE | __GFP_COMP),

drivers/gpu/drm/ttm/ttm_page_alloc.c int ttm_page_alloc_init(struct ttm_mem_global *glob, unsigned max_pages) · line 994

Quoted 10 lines
drivers/gpu/drm/ttm/ttm_page_alloc.c +2 -2
-				  "wc huge");
+				  "wc huge", HPAGE_PMD_ORDER);
 
  	ttm_page_pool_init_locked(&_manager->uc_pool_huge,
  				  GFP_TRANSHUGE	& ~(__GFP_MOVABLE | __GFP_COMP)
-				  , "uc huge");
+				  , "uc huge", HPAGE_PMD_ORDER);
 
  	_manager->options.max_size = max_pages;
  	_manager->options.small = SMALL_ALLOCATION;

_______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

#12 lore raw
In reply to a message not in the archive

Am 22.11.2017 um 06:36 schrieb Roger He:

Quoted 76 lines

to indicate page order for each element in the pool

Change-Id Ic609925ca5d2a5d4ad49d6becf505388ce3624cf
---
  drivers/gpu/drm/ttm/ttm_page_alloc.c | 42 ++++++++++++++++++++++++++----------
  1 file changed, 31 insertions(+), 11 deletions(-)
drivers/gpu/drm/ttm/ttm_page_alloc.c +16 -5
index 72ea037..0a0c653 100644
@@ -81,6 +81,7 @@ struct ttm_page_pool {
  	char			*name;
  	unsigned long		nfrees;
  	unsigned long		nrefills;
+	unsigned int		order;
  };
 
  /**
@@ -412,6 +413,7 @@ ttm_pool_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
  	struct ttm_page_pool *pool;
  	int shrink_pages = sc->nr_to_scan;
  	unsigned long freed = 0;
+	unsigned int nr_free_pool;
 
  	if (!mutex_trylock(&lock))
  		return SHRINK_STOP;
@@ -421,10 +423,15 @@ ttm_pool_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
  		unsigned nr_free = shrink_pages;
  		if (shrink_pages == 0)
  			break;
+
  		pool = &_manager->pools[(i + pool_offset)%NUM_POOLS];
  		/* OK to use static buffer since global mutex is held. */
-		shrink_pages = ttm_page_pool_free(pool, nr_free, true);
-		freed += nr_free - shrink_pages;
+		nr_free_pool = (nr_free >> pool->order);
+		if (nr_free_pool == 0)
+			continue;
+
+		shrink_pages = ttm_page_pool_free(pool, nr_free_pool, true);
+		freed += ((nr_free_pool - shrink_pages) << pool->order);
  	}
  	mutex_unlock(&lock);
  	return freed;
@@ -436,9 +443,12 @@ ttm_pool_shrink_count(struct shrinker *shrink, struct shrink_control *sc)
  {
  	unsigned i;
  	unsigned long count = 0;
+	struct ttm_page_pool *pool;
 
-	for (i = 0; i < NUM_POOLS; ++i)
-		count += _manager->pools[i].npages;
+	for (i = 0; i < NUM_POOLS; ++i) {
+		pool = &_manager->pools[i];
+		count += (pool->npages << pool->order);
+	}
 
  	return count;
  }
@@ -932,7 +942,7 @@ static int ttm_get_pages(struct page **pages, unsigned npages, int flags,
  }
 
  static void ttm_page_pool_init_locked(struct ttm_page_pool *pool, gfp_t flags,
-		char *name)
+		char *name, unsigned int order)
  {
  	spin_lock_init(&pool->lock);
  	pool->fill_lock = false;
@@ -940,8 +950,18 @@ static void ttm_page_pool_init_locked(struct ttm_page_pool *pool, gfp_t flags,
  	pool->npages = pool->nfrees = 0;
  	pool->gfp_flags = flags;
  	pool->name = name;
+	pool->order = order;
  }

drivers/gpu/drm/ttm/ttm_page_alloc.c static void ttm_page_pool_init_locked(struct ttm_page_pool *pool, gfp_t flags, · line 964

Quoted 10 lines
drivers/gpu/drm/ttm/ttm_page_alloc.c +9 -0
 
+/**
+ * Actually if TRANSPARENT_HUGEPAGE not enabled, we will not use
+ * wc_pool_huge and uc_pool_huge, so no matter whatever the page
+ * order are for those two pools
+ */
+#ifndef CONFIG_TRANSPARENT_HUGEPAGE
+#define	HPAGE_PMD_ORDER	9
+#endif
+

That still won't work and sorry I wasn't 100% clear in the last mail.

When CONFIG_TRANSPARENT_HUGEPAGE isn't set HPAGE_PMD_ORDER is defined as BUILD_BUG().

So you will still run into problems when that config option isn't set.

drivers/gpu/drm/ttm/ttm_page_alloc.c static void ttm_page_pool_init_locked(struct ttm_page_pool *pool, gfp_t flags, · line 967

Quoted 3 lines
drivers/gpu/drm/ttm/ttm_page_alloc.c +0 -0
  int ttm_page_alloc_init(struct ttm_mem_global *glob, unsigned max_pages)
  {
  	int ret;

I suggest to just handle it here like this

#ifdef CONFIG_TRANSPARENT_HUGEPAGE
    unsigned order = HPAGE_PMD_ORDER;
#else
    unsigned order = 0;
#endif

Apart from that the patch looks good to me,
Christian.

Quoted 20 lines
drivers/gpu/drm/ttm/ttm_page_alloc.c +4 -4
@@ -952,23 +972,23 @@ int ttm_page_alloc_init(struct ttm_mem_global *glob, unsigned max_pages)
 
  	_manager = kzalloc(sizeof(*_manager), GFP_KERNEL);
 
-	ttm_page_pool_init_locked(&_manager->wc_pool, GFP_HIGHUSER, "wc");
+	ttm_page_pool_init_locked(&_manager->wc_pool, GFP_HIGHUSER, "wc", 0);
 
-	ttm_page_pool_init_locked(&_manager->uc_pool, GFP_HIGHUSER, "uc");
+	ttm_page_pool_init_locked(&_manager->uc_pool, GFP_HIGHUSER, "uc", 0);
 
  	ttm_page_pool_init_locked(&_manager->wc_pool_dma32,
-				  GFP_USER | GFP_DMA32, "wc dma");
+				  GFP_USER | GFP_DMA32, "wc dma", 0);
 
  	ttm_page_pool_init_locked(&_manager->uc_pool_dma32,
-				  GFP_USER | GFP_DMA32, "uc dma");
+				  GFP_USER | GFP_DMA32, "uc dma", 0);
 
  	ttm_page_pool_init_locked(&_manager->wc_pool_huge,
  				  GFP_TRANSHUGE	& ~(__GFP_MOVABLE | __GFP_COMP),

drivers/gpu/drm/ttm/ttm_page_alloc.c int ttm_page_alloc_init(struct ttm_mem_global *glob, unsigned max_pages) · line 994

Quoted 10 lines
drivers/gpu/drm/ttm/ttm_page_alloc.c +2 -2
-				  "wc huge");
+				  "wc huge", HPAGE_PMD_ORDER);
 
  	ttm_page_pool_init_locked(&_manager->uc_pool_huge,
  				  GFP_TRANSHUGE	& ~(__GFP_MOVABLE | __GFP_COMP)
-				  , "uc huge");
+				  , "uc huge", HPAGE_PMD_ORDER);
 
  	_manager->options.max_size = max_pages;
  	_manager->options.small = SMALL_ALLOCATION;

_______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

A message that is not in the archive (sent off-list or not yet received): 6c134a88-2322-b131-d79f-0e5e3b74cd17-5C7GfCeVMHo@public.gmane.org

author
#14 lore raw

-----Original Message-----
From: Koenig, Christian
Sent: Wednesday, November 22, 2017 3:48 PM
To: He, Roger <[email protected]>; [email protected]; [email protected]
Subject: Re: [PATCH 1/4] drm/ttm: add page order in page pool

Am 22.11.2017 um 06:36 schrieb Roger He:

Quoted 77 lines

to indicate page order for each element in the pool

Change-Id Ic609925ca5d2a5d4ad49d6becf505388ce3624cf
---
  drivers/gpu/drm/ttm/ttm_page_alloc.c | 42 ++++++++++++++++++++++++++----------
  1 file changed, 31 insertions(+), 11 deletions(-)
drivers/gpu/drm/ttm/ttm_page_alloc.c +16 -5
index 72ea037..0a0c653 100644
@@ -81,6 +81,7 @@ struct ttm_page_pool {
  	char			*name;
  	unsigned long		nfrees;
  	unsigned long		nrefills;
+	unsigned int		order;
  };
 
  /**
@@ -412,6 +413,7 @@ ttm_pool_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
  	struct ttm_page_pool *pool;
  	int shrink_pages = sc->nr_to_scan;
  	unsigned long freed = 0;
+	unsigned int nr_free_pool;
 
  	if (!mutex_trylock(&lock))
  		return SHRINK_STOP;
@@ -421,10 +423,15 @@ ttm_pool_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
  		unsigned nr_free = shrink_pages;
  		if (shrink_pages == 0)
  			break;
+
  		pool = &_manager->pools[(i + pool_offset)%NUM_POOLS];
  		/* OK to use static buffer since global mutex is held. */
-		shrink_pages = ttm_page_pool_free(pool, nr_free, true);
-		freed += nr_free - shrink_pages;
+		nr_free_pool = (nr_free >> pool->order);
+		if (nr_free_pool == 0)
+			continue;
+
+		shrink_pages = ttm_page_pool_free(pool, nr_free_pool, true);
+		freed += ((nr_free_pool - shrink_pages) << pool->order);
  	}
  	mutex_unlock(&lock);
  	return freed;
@@ -436,9 +443,12 @@ ttm_pool_shrink_count(struct shrinker *shrink, struct shrink_control *sc)
  {
  	unsigned i;
  	unsigned long count = 0;
+	struct ttm_page_pool *pool;
 
-	for (i = 0; i < NUM_POOLS; ++i)
-		count += _manager->pools[i].npages;
+	for (i = 0; i < NUM_POOLS; ++i) {
+		pool = &_manager->pools[i];
+		count += (pool->npages << pool->order);
+	}
 
  	return count;
  }
@@ -932,7 +942,7 @@ static int ttm_get_pages(struct page **pages, unsigned npages, int flags,
  }
 
  static void ttm_page_pool_init_locked(struct ttm_page_pool *pool, gfp_t flags,
-		char *name)
+		char *name, unsigned int order)
  {
  	spin_lock_init(&pool->lock);
  	pool->fill_lock = false;
@@ -940,8 +950,18 @@ static void ttm_page_pool_init_locked(struct ttm_page_pool *pool, gfp_t flags,
  	pool->npages = pool->nfrees = 0;
  	pool->gfp_flags = flags;
  	pool->name = name;
+	pool->order = order;
  }

drivers/gpu/drm/ttm/ttm_page_alloc.c static void ttm_page_pool_init_locked(struct ttm_page_pool *pool, gfp_t flags, · line 964

Quoted 10 lines
drivers/gpu/drm/ttm/ttm_page_alloc.c +9 -0
 
+/**
+ * Actually if TRANSPARENT_HUGEPAGE not enabled, we will not use
+ * wc_pool_huge and uc_pool_huge, so no matter whatever the page
+ * order are for those two pools
+ */
+#ifndef CONFIG_TRANSPARENT_HUGEPAGE
+#define	HPAGE_PMD_ORDER	9
+#endif
+

That still won't work and sorry I wasn't 100% clear in the last mail.

When CONFIG_TRANSPARENT_HUGEPAGE isn't set HPAGE_PMD_ORDER is defined as BUILD_BUG().

So you will still run into problems when that config option isn't set.

drivers/gpu/drm/ttm/ttm_page_alloc.c static void ttm_page_pool_init_locked(struct ttm_page_pool *pool, gfp_t flags, · line 967

Quoted 3 lines
drivers/gpu/drm/ttm/ttm_page_alloc.c +0 -0
  int ttm_page_alloc_init(struct ttm_mem_global *glob, unsigned max_pages)
  {
  	int ret;

I suggest to just handle it here like this

#ifdef CONFIG_TRANSPARENT_HUGEPAGE
    unsigned order = HPAGE_PMD_ORDER;
#else
    unsigned order = 0;
#endif

Apart from that the patch looks good to me, Christian.

Ok, going to modify it. Thanks!

Thanks
Roger(Hongbo.He)

Quoted 23 lines
drivers/gpu/drm/ttm/ttm_page_alloc.c +6 -4
@@ -952,23 +972,23 @@ int ttm_page_alloc_init(struct ttm_mem_global 
 *glob, unsigned max_pages)
 
  	_manager = kzalloc(sizeof(*_manager), GFP_KERNEL);
 
-	ttm_page_pool_init_locked(&_manager->wc_pool, GFP_HIGHUSER, "wc");
+	ttm_page_pool_init_locked(&_manager->wc_pool, GFP_HIGHUSER, "wc", 
+0);
 
-	ttm_page_pool_init_locked(&_manager->uc_pool, GFP_HIGHUSER, "uc");
+	ttm_page_pool_init_locked(&_manager->uc_pool, GFP_HIGHUSER, "uc", 
+0);
 
  	ttm_page_pool_init_locked(&_manager->wc_pool_dma32,
-				  GFP_USER | GFP_DMA32, "wc dma");
+				  GFP_USER | GFP_DMA32, "wc dma", 0);
 
  	ttm_page_pool_init_locked(&_manager->uc_pool_dma32,
-				  GFP_USER | GFP_DMA32, "uc dma");
+				  GFP_USER | GFP_DMA32, "uc dma", 0);
 
  	ttm_page_pool_init_locked(&_manager->wc_pool_huge,
  				  GFP_TRANSHUGE	& ~(__GFP_MOVABLE | __GFP_COMP),

drivers/gpu/drm/ttm/ttm_page_alloc.c int ttm_page_alloc_init(struct ttm_mem_global · line 994

Quoted 10 lines
drivers/gpu/drm/ttm/ttm_page_alloc.c +2 -2
-				  "wc huge");
+				  "wc huge", HPAGE_PMD_ORDER);
 
  	ttm_page_pool_init_locked(&_manager->uc_pool_huge,
  				  GFP_TRANSHUGE	& ~(__GFP_MOVABLE | __GFP_COMP)
-				  , "uc huge");
+				  , "uc huge", HPAGE_PMD_ORDER);
 
  	_manager->options.max_size = max_pages;
  	_manager->options.small = SMALL_ALLOCATION;

_______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx