]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
drm/i915: Use Write-Through cacheing for the display plane on Iris
authorChris Wilson <chris@chris-wilson.co.uk>
Thu, 8 Aug 2013 13:41:10 +0000 (14:41 +0100)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Thu, 22 Aug 2013 11:31:38 +0000 (13:31 +0200)
Haswell GT3e has the unique feature of supporting Write-Through cacheing
of objects within the eLLC/LLC. The purpose of this is to enable the display
plane to remain coherent whilst objects lie resident in the eLLC/LLC - so
that we, in theory, get the best of both worlds, perfect display and fast
access.

However, we still need to be careful as the CPU does not see the WT when
accessing the cache. In particular, this means that we need to flush the
cache lines after writing to an object through the CPU, and on
transitioning from a cached state to WT.

v2: Actually do the clflush on transition to WT, nagging by Ville.
v3: Flush the CPU cache after writes into WT objects.
v4: Rease onto LLC updates and report WT as "uncached" for
get_cache_level_ioctl to remain symmetric with set_cache_level_ioctl.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_gtt.c
include/uapi/drm/i915_drm.h

index ce098c3ccc00fa710b945d7f9e7759e5044b2a4b..f4231185ec7d826144d82143a079076ac1fe6b6c 100644 (file)
@@ -976,6 +976,9 @@ static int i915_getparam(struct drm_device *dev, void *data,
        case I915_PARAM_HAS_LLC:
                value = HAS_LLC(dev);
                break;
+       case I915_PARAM_HAS_WT:
+               value = HAS_WT(dev);
+               break;
        case I915_PARAM_HAS_ALIASING_PPGTT:
                value = dev_priv->mm.aliasing_ppgtt ? 1 : 0;
                break;
index 1af59d72ddc7821c533392702f7334cd5e8d953f..6d07467d0e7e205d3f7f7e8e5f77ce3578439eb9 100644 (file)
@@ -454,6 +454,7 @@ enum i915_cache_level {
                              caches, eg sampler/render caches, and the
                              large Last-Level-Cache. LLC is coherent with
                              the CPU, but L3 is only visible to the GPU. */
+       I915_CACHE_WT, /* hsw:gt3e WriteThrough for scanouts */
 };
 
 typedef uint32_t gen6_gtt_pte_t;
@@ -1385,7 +1386,7 @@ struct drm_i915_gem_object {
        unsigned int pending_fenced_gpu_access:1;
        unsigned int fenced_gpu_access:1;
 
-       unsigned int cache_level:2;
+       unsigned int cache_level:3;
 
        unsigned int has_aliasing_ppgtt_mapping:1;
        unsigned int has_global_gtt_mapping:1;
@@ -1530,6 +1531,7 @@ struct drm_i915_file_private {
 #define HAS_BLT(dev)            (INTEL_INFO(dev)->has_blt_ring)
 #define HAS_VEBOX(dev)          (INTEL_INFO(dev)->has_vebox_ring)
 #define HAS_LLC(dev)            (INTEL_INFO(dev)->has_llc)
+#define HAS_WT(dev)            (IS_HASWELL(dev) && to_i915(dev)->ellc_size)
 #define I915_NEED_GFX_HWS(dev) (INTEL_INFO(dev)->need_gfx_hws)
 
 #define HAS_HW_CONTEXTS(dev)   (INTEL_INFO(dev)->gen >= 6)
index 474748ffa7b6865e093d784825c63051c02da92b..4064fdf15abefbe1ec63ffbe6e1fd354c2f316c2 100644 (file)
@@ -3471,7 +3471,16 @@ int i915_gem_get_caching_ioctl(struct drm_device *dev, void *data,
                goto unlock;
        }
 
-       args->caching = obj->cache_level != I915_CACHE_NONE;
+       switch (obj->cache_level) {
+       case I915_CACHE_LLC:
+       case I915_CACHE_L3_LLC:
+               args->caching = I915_CACHING_CACHED;
+               break;
+
+       default:
+               args->caching = I915_CACHING_NONE;
+               break;
+       }
 
        drm_gem_object_unreference(&obj->base);
 unlock:
@@ -3565,7 +3574,8 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
         * of uncaching, which would allow us to flush all the LLC-cached data
         * with that bit in the PTE to main memory with just one PIPE_CONTROL.
         */
-       ret = i915_gem_object_set_cache_level(obj, I915_CACHE_NONE);
+       ret = i915_gem_object_set_cache_level(obj,
+                                             HAS_WT(obj->base.dev) ? I915_CACHE_WT : I915_CACHE_NONE);
        if (ret)
                goto err_unpin_display;
 
index c9420c280cf00838989d5af48acfb3cedcf3bc21..212f6d8c35ec6593cc54957ecd24445196d26657 100644 (file)
@@ -55,6 +55,7 @@
 #define HSW_WB_LLC_AGE3                        HSW_CACHEABILITY_CONTROL(0x2)
 #define HSW_WB_LLC_AGE0                        HSW_CACHEABILITY_CONTROL(0x3)
 #define HSW_WB_ELLC_LLC_AGE0           HSW_CACHEABILITY_CONTROL(0xb)
+#define HSW_WT_ELLC_LLC_AGE0           HSW_CACHEABILITY_CONTROL(0x6)
 
 static gen6_gtt_pte_t snb_pte_encode(dma_addr_t addr,
                                     enum i915_cache_level level)
@@ -138,8 +139,16 @@ static gen6_gtt_pte_t iris_pte_encode(dma_addr_t addr,
        gen6_gtt_pte_t pte = GEN6_PTE_VALID;
        pte |= HSW_PTE_ADDR_ENCODE(addr);
 
-       if (level != I915_CACHE_NONE)
+       switch (level) {
+       case I915_CACHE_NONE:
+               break;
+       case I915_CACHE_WT:
+               pte |= HSW_WT_ELLC_LLC_AGE0;
+               break;
+       default:
                pte |= HSW_WB_ELLC_LLC_AGE0;
+               break;
+       }
 
        return pte;
 }
index 0bb3e5524382250a31b91d20ae7c24d30f44cb9f..55bb5729bd78a534da094f07fe74714e162a2c9c 100644 (file)
@@ -334,6 +334,7 @@ typedef struct drm_i915_irq_wait {
 #define I915_PARAM_HAS_PINNED_BATCHES   24
 #define I915_PARAM_HAS_EXEC_NO_RELOC    25
 #define I915_PARAM_HAS_EXEC_HANDLE_LUT   26
+#define I915_PARAM_HAS_WT               27
 
 typedef struct drm_i915_getparam {
        int param;