Skip to content

Commit 0c40ce1

Browse files
committed
drm/i915: Trim the object sg table
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
1 parent 11840e2 commit 0c40ce1

File tree

1 file changed

+27
-0
lines changed

1 file changed

+27
-0
lines changed

drivers/gpu/drm/i915/i915_gem.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2232,6 +2232,30 @@ static unsigned int swiotlb_max_size(void)
22322232
#endif
22332233
}
22342234

2235+
static void i915_sg_trim(struct sg_table *orig_st)
2236+
{
2237+
struct sg_table new_st;
2238+
struct scatterlist *sg, *new_sg;
2239+
unsigned int i;
2240+
2241+
if (orig_st->nents == orig_st->orig_nents)
2242+
return;
2243+
2244+
if (sg_alloc_table(&new_st, orig_st->nents, GFP_KERNEL))
2245+
return;
2246+
2247+
new_sg = new_st.sgl;
2248+
for_each_sg(orig_st->sgl, sg, orig_st->nents, i) {
2249+
sg_set_page(new_sg, sg_page(sg), sg->length, 0);
2250+
/* called before being DMA mapped, no need to copy sg->dma_* */
2251+
new_sg = sg_next(new_sg);
2252+
}
2253+
2254+
sg_free_table(orig_st);
2255+
2256+
*orig_st = new_st;
2257+
}
2258+
22352259
static struct sg_table *
22362260
i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
22372261
{
@@ -2317,6 +2341,9 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
23172341
if (sg) /* loop terminated early; short sg table */
23182342
sg_mark_end(sg);
23192343

2344+
/* Trim unused sg entries to avoid wasting memory. */
2345+
i915_sg_trim(st);
2346+
23202347
ret = i915_gem_gtt_prepare_pages(obj, st);
23212348
if (ret)
23222349
goto err_pages;

0 commit comments

Comments
 (0)