aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2017-03-17 15:46:48 -0400
committerChris Wilson <chris@chris-wilson.co.uk>2017-03-17 18:55:56 -0400
commitbe062fa42738822b8b91351752ff89275e25b516 (patch)
tree00337fe19c9571cf13cb7f0c62fdeac4d35858c3
parentf3ddd2c14fdc08798a7fa2d32b39786585162f50 (diff)
drm/i915: Initialise i915_gem_object_create_from_data() directly
Use pagecache_write to avoid shmemfs clearing the pages prior to us immediately overwriting them with our data. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Link: http://patchwork.freedesktop.org/patch/msgid/20170317194648.12468-2-chris@chris-wilson.co.uk Reviewed-by: Matthew Auld <matthew.auld@intel.com>
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c45
1 files changed, 29 insertions, 16 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 3492f8d27c32..58e1db77d70e 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -4953,9 +4953,9 @@ i915_gem_object_create_from_data(struct drm_i915_private *dev_priv,
4953 const void *data, size_t size) 4953 const void *data, size_t size)
4954{ 4954{
4955 struct drm_i915_gem_object *obj; 4955 struct drm_i915_gem_object *obj;
4956 struct sg_table *sg; 4956 struct file *file;
4957 size_t bytes; 4957 size_t offset;
4958 int ret; 4958 int err;
4959 4959
4960 obj = i915_gem_object_create(dev_priv, round_up(size, PAGE_SIZE)); 4960 obj = i915_gem_object_create(dev_priv, round_up(size, PAGE_SIZE));
4961 if (IS_ERR(obj)) 4961 if (IS_ERR(obj))
@@ -4963,26 +4963,39 @@ i915_gem_object_create_from_data(struct drm_i915_private *dev_priv,
4963 4963
4964 GEM_BUG_ON(obj->base.write_domain != I915_GEM_DOMAIN_CPU); 4964 GEM_BUG_ON(obj->base.write_domain != I915_GEM_DOMAIN_CPU);
4965 4965
4966 ret = i915_gem_object_pin_pages(obj); 4966 file = obj->base.filp;
4967 if (ret) 4967 offset = 0;
4968 goto fail; 4968 do {
4969 unsigned int len = min_t(typeof(size), size, PAGE_SIZE);
4970 struct page *page;
4971 void *pgdata, *vaddr;
4969 4972
4970 sg = obj->mm.pages; 4973 err = pagecache_write_begin(file, file->f_mapping,
4971 bytes = sg_copy_from_buffer(sg->sgl, sg->nents, (void *)data, size); 4974 offset, len, 0,
4972 obj->mm.dirty = true; /* Backing store is now out of date */ 4975 &page, &pgdata);
4973 i915_gem_object_unpin_pages(obj); 4976 if (err < 0)
4977 goto fail;
4974 4978
4975 if (WARN_ON(bytes != size)) { 4979 vaddr = kmap(page);
4976 DRM_ERROR("Incomplete copy, wrote %zu of %zu", bytes, size); 4980 memcpy(vaddr, data, len);
4977 ret = -EFAULT; 4981 kunmap(page);
4978 goto fail; 4982
4979 } 4983 err = pagecache_write_end(file, file->f_mapping,
4984 offset, len, len,
4985 page, pgdata);
4986 if (err < 0)
4987 goto fail;
4988
4989 size -= len;
4990 data += len;
4991 offset += len;
4992 } while (size);
4980 4993
4981 return obj; 4994 return obj;
4982 4995
4983fail: 4996fail:
4984 i915_gem_object_put(obj); 4997 i915_gem_object_put(obj);
4985 return ERR_PTR(ret); 4998 return ERR_PTR(err);
4986} 4999}
4987 5000
4988struct scatterlist * 5001struct scatterlist *