diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2017-07-26 17:00:37 +0100 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2017-07-27 09:56:10 +0200 |
commit | 6ea1d55d31c46e2158a49e8e41cb0be4a8cd8677 (patch) | |
tree | 367b21a7ce44869b828a9fb719ada7ee8b383957 /drivers/gpu/drm/i915/i915_gem.c | |
parent | fd70075f82b7f471ff923a56dea00fb44463296c (diff) |
drm/i915: Make i915_gem_object_phys_attach() use obj->mm.lock more appropriately
Actually transferring from shmemfs to the physically contiguous set of
pages should be wholly guarded by its obj->mm.lock!
v2: Remember to free the old pages.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20170726160038.29487-2-chris@chris-wilson.co.uk
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/i915_gem.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 50 |
1 files changed, 35 insertions, 15 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 6faabf34f142..12dddba7bf6f 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -565,7 +565,8 @@ int i915_gem_object_attach_phys(struct drm_i915_gem_object *obj, int align) { - int ret; + struct sg_table *pages; + int err; if (align > obj->base.size) return -EINVAL; @@ -573,32 +574,51 @@ i915_gem_object_attach_phys(struct drm_i915_gem_object *obj, if (obj->ops == &i915_gem_phys_ops) return 0; - if (obj->mm.madv != I915_MADV_WILLNEED) - return -EFAULT; - - if (obj->base.filp == NULL) + if (obj->ops != &i915_gem_object_ops) return -EINVAL; - ret = i915_gem_object_unbind(obj); - if (ret) - return ret; + err = i915_gem_object_unbind(obj); + if (err) + return err; + + mutex_lock(&obj->mm.lock); - __i915_gem_object_put_pages(obj, I915_MM_NORMAL); - if (obj->mm.pages) - return -EBUSY; + if (obj->mm.madv != I915_MADV_WILLNEED) { + err = -EFAULT; + goto err_unlock; + } - GEM_BUG_ON(obj->ops != &i915_gem_object_ops); + if (obj->mm.quirked) { + err = -EFAULT; + goto err_unlock; + } + + if (obj->mm.mapping) { + err = -EBUSY; + goto err_unlock; + } + + pages = obj->mm.pages; obj->ops = &i915_gem_phys_ops; - ret = i915_gem_object_pin_pages(obj); - if (ret) + err = __i915_gem_object_get_pages(obj); + if (err) goto err_xfer; + /* Perma-pin (until release) the physical set of pages */ + __i915_gem_object_pin_pages(obj); + + if (!IS_ERR_OR_NULL(pages)) + i915_gem_object_ops.put_pages(obj, pages); + mutex_unlock(&obj->mm.lock); return 0; err_xfer: obj->ops = &i915_gem_object_ops; - return ret; + obj->mm.pages = pages; +err_unlock: + mutex_unlock(&obj->mm.lock); + return err; } static int |