[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