drm/i915: Performed deferred clflush inside set-cache-level
authorChris Wilson <chris@chris-wilson.co.uk>
Tue, 13 Jan 2015 13:32:52 +0000 (13:32 +0000)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Tue, 27 Jan 2015 08:51:07 +0000 (09:51 +0100)
Currently we are hitting the WARN inside
i915_gem_object_set_cache_level() as we can now have an unbound object
in the GTT write domain (due to 43566dedde54f9 "drm/i915: Broaden
application of set-domain(GTT)"). To avoid the warning, we need to track
when we elided the clflush on a cacheable object and then evict the
cache for the object when we move the object out of a cacheable domain.

Reported-by: Jani Nikula <jani.nikula@linux.intel.com>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Jani Nikula <jani.nikula@linux.intel.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Tested-by: Jani Nikula <jani.nikula@intel.com>
Testcase: igt/gem_mmap_wc/set-cache-level
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=88607
Tested-by: huax.lu@intel.com
[danvet: Split if into nested if as discussion on the m-l.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c

index de304d78e2bf3b3f97c5263cbd2ca7c225dc0587..0ad8dbf896c0a29eb8881e31cac1229b7cb25da6 100644 (file)
@@ -2055,6 +2055,7 @@ struct drm_i915_gem_object {
         */
        unsigned long gt_ro:1;
        unsigned int cache_level:3;
+       unsigned int cache_dirty:1;
 
        unsigned int has_dma_mapping:1;
 
index 2a4d1f01118dd1836f3b9ba0e0383b96a2db6d67..a0264aa5cf510ff545d59578227f4418f584694a 100644 (file)
@@ -3637,11 +3637,14 @@ i915_gem_clflush_object(struct drm_i915_gem_object *obj,
         * snooping behaviour occurs naturally as the result of our domain
         * tracking.
         */
-       if (!force && cpu_cache_is_coherent(obj->base.dev, obj->cache_level))
+       if (!force && cpu_cache_is_coherent(obj->base.dev, obj->cache_level)) {
+               obj->cache_dirty = true;
                return false;
+       }
 
        trace_i915_gem_object_clflush(obj);
        drm_clflush_sg(obj->pages);
+       obj->cache_dirty = false;
 
        return true;
 }
@@ -3824,27 +3827,11 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
                vma->node.color = cache_level;
        obj->cache_level = cache_level;
 
-       if (cpu_write_needs_clflush(obj)) {
-               u32 old_read_domains, old_write_domain;
-
-               /* If we're coming from LLC cached, then we haven't
-                * actually been tracking whether the data is in the
-                * CPU cache or not, since we only allow one bit set
-                * in obj->write_domain and have been skipping the clflushes.
-                * Just set it to the CPU cache for now.
-                */
-               i915_gem_object_retire(obj);
-               WARN_ON(obj->base.write_domain & ~I915_GEM_DOMAIN_CPU);
-
-               old_read_domains = obj->base.read_domains;
-               old_write_domain = obj->base.write_domain;
-
-               obj->base.read_domains = I915_GEM_DOMAIN_CPU;
-               obj->base.write_domain = I915_GEM_DOMAIN_CPU;
-
-               trace_i915_gem_object_change_domain(obj,
-                                                   old_read_domains,
-                                                   old_write_domain);
+       if (obj->cache_dirty &&
+           obj->base.write_domain != I915_GEM_DOMAIN_CPU &&
+           cpu_write_needs_clflush(obj)) {
+               if (i915_gem_clflush_object(obj, true))
+                       i915_gem_chipset_flush(obj->base.dev);
        }
 
        return 0;