Skip to content

Commit

Permalink
drm/i915: Trim the object sg table
Browse files Browse the repository at this point in the history
At the moment we allocate enough sg table entries assuming we
will not be able to do any coalescing. But since in practice
we most often can, and more so very effectively, this ends up
wasting a lot of memory.

A simple and effective way of trimming the over-allocated
entries is to copy the table over to a new one allocated to the
exact size.

Experiments on my freshly logged and idle desktop (KDE) showed
that by doing this we can save approximately 1 MiB of RAM, or
when running a typical benchmark like gl_manhattan I have
even seen a 6 MiB saving.

More complicated techniques such as only copying the last used
page and freeing the rest are left to the reader.

v2:
 * Update commit message.
 * Use temporary sg_table on stack. (Chris Wilson)

v3:
 * Commit message update.
 * Comment added.
 * Replace memcpy with copy assignment.
   (Chris Wilson)

Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: http://patchwork.freedesktop.org/patch/msgid/1478704423-7447-1-git-send-email-tvrtko.ursulin@linux.intel.com
  • Loading branch information
Tvrtko Ursulin committed Nov 10, 2016
1 parent 11840e2 commit 0c40ce1
Showing 1 changed file with 27 additions and 0 deletions.
27 changes: 27 additions & 0 deletions drivers/gpu/drm/i915/i915_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -2232,6 +2232,30 @@ static unsigned int swiotlb_max_size(void)
#endif
}

static void i915_sg_trim(struct sg_table *orig_st)
{
struct sg_table new_st;
struct scatterlist *sg, *new_sg;
unsigned int i;

if (orig_st->nents == orig_st->orig_nents)
return;

if (sg_alloc_table(&new_st, orig_st->nents, GFP_KERNEL))
return;

new_sg = new_st.sgl;
for_each_sg(orig_st->sgl, sg, orig_st->nents, i) {
sg_set_page(new_sg, sg_page(sg), sg->length, 0);
/* called before being DMA mapped, no need to copy sg->dma_* */
new_sg = sg_next(new_sg);
}

sg_free_table(orig_st);

*orig_st = new_st;
}

static struct sg_table *
i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
{
Expand Down Expand Up @@ -2317,6 +2341,9 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
if (sg) /* loop terminated early; short sg table */
sg_mark_end(sg);

/* Trim unused sg entries to avoid wasting memory. */
i915_sg_trim(st);

ret = i915_gem_gtt_prepare_pages(obj, st);
if (ret)
goto err_pages;
Expand Down

0 comments on commit 0c40ce1

Please sign in to comment.