diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2017-03-17 15:46:48 -0400 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2017-03-17 18:55:56 -0400 |
commit | be062fa42738822b8b91351752ff89275e25b516 (patch) | |
tree | 00337fe19c9571cf13cb7f0c62fdeac4d35858c3 | |
parent | f3ddd2c14fdc08798a7fa2d32b39786585162f50 (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.c | 45 |
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 | ||
4983 | fail: | 4996 | fail: |
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 | ||
4988 | struct scatterlist * | 5001 | struct scatterlist * |