Commit 44c2200a authored by Chris Wilson's avatar Chris Wilson

drm/i915/gem: Flush coherency domains on first set-domain-ioctl

Avoid skipping what appears to be a no-op set-domain-ioctl if the cache
coherency state is inconsistent with our target domain. This also has
the utility of using the population of the pages to validate the backing
store.

The danger in skipping the first set-domain is leaving the cache
inconsistent and submitting stale data, or worse leaving the clean data
in the cache and not flushing it to the GPU. The impact should be small
as it requires a no-op set-domain as the very first ioctl in a
particular sequence not found in typical userspace.
Reported-by: default avatarZbigniew Kempczyński <zbigniew.kempczynski@intel.com>
Fixes: 754a2544 ("drm/i915: Skip object locking around a no-op set-domain ioctl")
Testcase: igt/gem_mmap_offset/blt-coherency
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Cc: Matthew Auld <matthew.william.auld@gmail.com>
Cc: Zbigniew Kempczyński <zbigniew.kempczynski@intel.com>
Cc: <stable@vger.kernel.org> # v5.2+
Reviewed-by: default avatarMatthew Auld <matthew.auld@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20201019203825.10966-1-chris@chris-wilson.co.uk
parent 83ebef47
...@@ -508,21 +508,6 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data, ...@@ -508,21 +508,6 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
if (!obj) if (!obj)
return -ENOENT; return -ENOENT;
/*
* Already in the desired write domain? Nothing for us to do!
*
* We apply a little bit of cunning here to catch a broader set of
* no-ops. If obj->write_domain is set, we must be in the same
* obj->read_domains, and only that domain. Therefore, if that
* obj->write_domain matches the request read_domains, we are
* already in the same read/write domain and can skip the operation,
* without having to further check the requested write_domain.
*/
if (READ_ONCE(obj->write_domain) == read_domains) {
err = 0;
goto out;
}
/* /*
* Try to flush the object off the GPU without holding the lock. * Try to flush the object off the GPU without holding the lock.
* We will repeat the flush holding the lock in the normal manner * We will repeat the flush holding the lock in the normal manner
...@@ -560,6 +545,19 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data, ...@@ -560,6 +545,19 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
if (err) if (err)
goto out; goto out;
/*
* Already in the desired write domain? Nothing for us to do!
*
* We apply a little bit of cunning here to catch a broader set of
* no-ops. If obj->write_domain is set, we must be in the same
* obj->read_domains, and only that domain. Therefore, if that
* obj->write_domain matches the request read_domains, we are
* already in the same read/write domain and can skip the operation,
* without having to further check the requested write_domain.
*/
if (READ_ONCE(obj->write_domain) == read_domains)
goto out_unpin;
err = i915_gem_object_lock_interruptible(obj, NULL); err = i915_gem_object_lock_interruptible(obj, NULL);
if (err) if (err)
goto out_unpin; goto out_unpin;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment