[PATCH 09/11] drm/i915: Use sgl_alloc_order_min_max for internal objects

Tvrtko Ursulin tursulin at ursulin.net
Fri Mar 2 10:55:04 UTC 2018


From: Tvrtko Ursulin <tvrtko.ursulin at intel.com>

Replace our n-order page allocator for internal objects by the newly added
sgl_alloc_order_min_max library function and select it by default.

Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin at intel.com>
---
 drivers/gpu/drm/i915/Kconfig             |  1 +
 drivers/gpu/drm/i915/i915_gem_internal.c | 86 ++++++++------------------------
 2 files changed, 22 insertions(+), 65 deletions(-)

diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig
index dfd95889f4b7..c0245d15d7d6 100644
--- a/drivers/gpu/drm/i915/Kconfig
+++ b/drivers/gpu/drm/i915/Kconfig
@@ -23,6 +23,7 @@ config DRM_I915
 	select SYNC_FILE
 	select IOSF_MBI
 	select CRC32
+	select SGL_ALLOC
 	help
 	  Choose this option if you have a system that has "Intel Graphics
 	  Media Accelerator" or "HD Graphics" integrated graphics,
diff --git a/drivers/gpu/drm/i915/i915_gem_internal.c b/drivers/gpu/drm/i915/i915_gem_internal.c
index 0d0144b2104c..45e9e5acd45e 100644
--- a/drivers/gpu/drm/i915/i915_gem_internal.c
+++ b/drivers/gpu/drm/i915/i915_gem_internal.c
@@ -26,32 +26,17 @@
 #include <drm/i915_drm.h>
 #include "i915_drv.h"
 
-#define QUIET (__GFP_NORETRY | __GFP_NOWARN)
-#define MAYFAIL (__GFP_RETRY_MAYFAIL | __GFP_NOWARN)
 
 /* convert swiotlb segment size into sensible units (pages)! */
 #define IO_TLB_SEGPAGES (IO_TLB_SEGSIZE << IO_TLB_SHIFT >> PAGE_SHIFT)
 
-static void internal_free_pages(struct sg_table *st)
-{
-	struct scatterlist *sg;
-
-	for (sg = st->sgl; sg; sg = __sg_next(sg)) {
-		if (sg_page(sg))
-			__free_pages(sg_page(sg), get_order(sg->length));
-	}
-
-	sg_free_table(st);
-	kfree(st);
-}
-
 static int i915_gem_object_get_pages_internal(struct drm_i915_gem_object *obj)
 {
 	struct drm_i915_private *i915 = to_i915(obj->base.dev);
-	struct sg_table *st;
-	struct scatterlist *sg;
 	unsigned int sg_page_sizes;
-	unsigned int npages;
+	struct scatterlist *sg;
+	struct sg_table *st;
+	unsigned int i;
 	int max_order;
 	gfp_t gfp;
 
@@ -76,58 +61,32 @@ static int i915_gem_object_get_pages_internal(struct drm_i915_gem_object *obj)
 		gfp |= __GFP_DMA32;
 	}
 
-create_st:
 	st = kmalloc(sizeof(*st), GFP_KERNEL);
 	if (!st)
 		return -ENOMEM;
 
-	npages = obj->base.size / PAGE_SIZE;
-	if (sg_alloc_table(st, npages, GFP_KERNEL)) {
+create_sg:
+	st->sgl = sgl_alloc_order_min_max(obj->base.size, 0, max_order, false,
+					  gfp, &st->nents);
+	if (!st->sgl) {
 		kfree(st);
 		return -ENOMEM;
 	}
 
-	sg = st->sgl;
-	st->nents = 0;
-	sg_page_sizes = 0;
-
-	do {
-		int order = min(fls(npages) - 1, max_order);
-		struct page *page;
-
-		do {
-			page = alloc_pages(gfp | (order ? QUIET : MAYFAIL),
-					   order);
-			if (page)
-				break;
-			if (!order--)
-				goto err;
-
-			/* Limit subsequent allocations as well */
-			max_order = order;
-		} while (1);
-
-		sg_set_page(sg, page, PAGE_SIZE << order, 0);
-		sg_page_sizes |= PAGE_SIZE << order;
-		st->nents++;
-
-		npages -= 1 << order;
-		if (!npages) {
-			sg_mark_end(sg);
-			break;
-		}
-
-		sg = __sg_next(sg);
-	} while (1);
+	st->orig_nents = st->nents;
 
 	if (i915_gem_gtt_prepare_pages(obj, st)) {
+		unsigned order = get_order(st->sgl->length);
+
 		/* Failed to dma-map try again with single page sg segments */
-		if (get_order(st->sgl->length)) {
-			internal_free_pages(st);
+		sgl_free_n(st->sgl, st->nents);
+		if (order) {
 			max_order = 0;
-			goto create_st;
+			goto create_sg;
 		}
-		goto err;
+
+		kfree(st);
+		return -ENOMEM;
 	}
 
 	/* Mark the pages as dontneed whilst they are still pinned. As soon
@@ -137,23 +96,20 @@ static int i915_gem_object_get_pages_internal(struct drm_i915_gem_object *obj)
 	 */
 	obj->mm.madv = I915_MADV_DONTNEED;
 
+	sg_page_sizes = 0;
+	for_each_sg(st->sgl, sg, st->nents, i)
+		sg_page_sizes |= PAGE_SIZE << get_order(sg->length);
 	__i915_gem_object_set_pages(obj, st, sg_page_sizes);
 
 	return 0;
-
-err:
-	sg_set_page(sg, NULL, 0, 0);
-	sg_mark_end(sg);
-	internal_free_pages(st);
-
-	return -ENOMEM;
 }
 
 static void i915_gem_object_put_pages_internal(struct drm_i915_gem_object *obj,
 					       struct sg_table *pages)
 {
 	i915_gem_gtt_finish_pages(obj, pages);
-	internal_free_pages(pages);
+	sgl_free_n(pages->sgl, pages->nents);
+	kfree(pages);
 
 	obj->mm.dirty = false;
 	obj->mm.madv = I915_MADV_WILLNEED;
-- 
2.14.1



More information about the Intel-gfx-trybot mailing list