aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2011-04-04 04:44:39 -0400
committerKeith Packard <keithp@keithp.com>2011-06-10 00:51:16 -0400
commite4ffd173a1c2f96b43127c2537dd99d89e759bba (patch)
tree932a67f5eebb7884ba6b28a4ebf0893d84a44eec
parentd5bd144959e639443f387c34989cec7c9efff091 (diff)
drm/i915: Add an interface to dynamically change the cache level
[anholt v2: Don't forget that when going from cached to uncached, we haven't been tracking the write domain from the CPU perspective, since we haven't needed it for GPU coherency.] [ickle v3: We also need to make sure we relinquish any fences on older chipsets and clear the GTT for sane domain tracking.] Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Signed-off-by: Eric Anholt <eric@anholt.net> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h5
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c60
-rw-r--r--drivers/gpu/drm/i915/i915_gem_gtt.c7
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.c6
4 files changed, 71 insertions, 7 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 4d1a8ae70a33..e552aa6bc859 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1223,9 +1223,14 @@ void i915_gem_release(struct drm_device *dev, struct drm_file *file);
1223uint32_t 1223uint32_t
1224i915_gem_get_unfenced_gtt_alignment(struct drm_i915_gem_object *obj); 1224i915_gem_get_unfenced_gtt_alignment(struct drm_i915_gem_object *obj);
1225 1225
1226int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
1227 enum i915_cache_level cache_level);
1228
1226/* i915_gem_gtt.c */ 1229/* i915_gem_gtt.c */
1227void i915_gem_restore_gtt_mappings(struct drm_device *dev); 1230void i915_gem_restore_gtt_mappings(struct drm_device *dev);
1228int __must_check i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj); 1231int __must_check i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj);
1232void i915_gem_gtt_rebind_object(struct drm_i915_gem_object *obj,
1233 enum i915_cache_level cache_level);
1229void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj); 1234void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj);
1230 1235
1231/* i915_gem_evict.c */ 1236/* i915_gem_evict.c */
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index e78a7ef634d9..e6915072ba72 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -3034,6 +3034,66 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write)
3034 return 0; 3034 return 0;
3035} 3035}
3036 3036
3037int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
3038 enum i915_cache_level cache_level)
3039{
3040 int ret;
3041
3042 if (obj->cache_level == cache_level)
3043 return 0;
3044
3045 if (obj->pin_count) {
3046 DRM_DEBUG("can not change the cache level of pinned objects\n");
3047 return -EBUSY;
3048 }
3049
3050 if (obj->gtt_space) {
3051 ret = i915_gem_object_finish_gpu(obj);
3052 if (ret)
3053 return ret;
3054
3055 i915_gem_object_finish_gtt(obj);
3056
3057 /* Before SandyBridge, you could not use tiling or fence
3058 * registers with snooped memory, so relinquish any fences
3059 * currently pointing to our region in the aperture.
3060 */
3061 if (INTEL_INFO(obj->base.dev)->gen < 6) {
3062 ret = i915_gem_object_put_fence(obj);
3063 if (ret)
3064 return ret;
3065 }
3066
3067 i915_gem_gtt_rebind_object(obj, cache_level);
3068 }
3069
3070 if (cache_level == I915_CACHE_NONE) {
3071 u32 old_read_domains, old_write_domain;
3072
3073 /* If we're coming from LLC cached, then we haven't
3074 * actually been tracking whether the data is in the
3075 * CPU cache or not, since we only allow one bit set
3076 * in obj->write_domain and have been skipping the clflushes.
3077 * Just set it to the CPU cache for now.
3078 */
3079 WARN_ON(obj->base.write_domain & ~I915_GEM_DOMAIN_CPU);
3080 WARN_ON(obj->base.read_domains & ~I915_GEM_DOMAIN_CPU);
3081
3082 old_read_domains = obj->base.read_domains;
3083 old_write_domain = obj->base.write_domain;
3084
3085 obj->base.read_domains = I915_GEM_DOMAIN_CPU;
3086 obj->base.write_domain = I915_GEM_DOMAIN_CPU;
3087
3088 trace_i915_gem_object_change_domain(obj,
3089 old_read_domains,
3090 old_write_domain);
3091 }
3092
3093 obj->cache_level = cache_level;
3094 return 0;
3095}
3096
3037/* 3097/*
3038 * Prepare buffer for display plane. Use uninterruptible for possible flush 3098 * Prepare buffer for display plane. Use uninterruptible for possible flush
3039 * wait, as in modesetting process we're not supposed to be interrupted. 3099 * wait, as in modesetting process we're not supposed to be interrupted.
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 837033cf2ce5..7a709cd8d543 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -29,9 +29,6 @@
29#include "i915_trace.h" 29#include "i915_trace.h"
30#include "intel_drv.h" 30#include "intel_drv.h"
31 31
32static void i915_gem_gtt_rebind_object(struct drm_i915_gem_object *obj,
33 enum i915_cache_level cache_level);
34
35/* XXX kill agp_type! */ 32/* XXX kill agp_type! */
36static unsigned int cache_level_to_agp_type(struct drm_device *dev, 33static unsigned int cache_level_to_agp_type(struct drm_device *dev,
37 enum i915_cache_level cache_level) 34 enum i915_cache_level cache_level)
@@ -97,8 +94,8 @@ int i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj)
97 return 0; 94 return 0;
98} 95}
99 96
100static void i915_gem_gtt_rebind_object(struct drm_i915_gem_object *obj, 97void i915_gem_gtt_rebind_object(struct drm_i915_gem_object *obj,
101 enum i915_cache_level cache_level) 98 enum i915_cache_level cache_level)
102{ 99{
103 struct drm_device *dev = obj->base.dev; 100 struct drm_device *dev = obj->base.dev;
104 struct drm_i915_private *dev_priv = dev->dev_private; 101 struct drm_i915_private *dev_priv = dev->dev_private;
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 95c4b1429935..e9615685a39c 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -236,7 +236,8 @@ init_pipe_control(struct intel_ring_buffer *ring)
236 ret = -ENOMEM; 236 ret = -ENOMEM;
237 goto err; 237 goto err;
238 } 238 }
239 obj->cache_level = I915_CACHE_LLC; 239
240 i915_gem_object_set_cache_level(obj, I915_CACHE_LLC);
240 241
241 ret = i915_gem_object_pin(obj, 4096, true); 242 ret = i915_gem_object_pin(obj, 4096, true);
242 if (ret) 243 if (ret)
@@ -776,7 +777,8 @@ static int init_status_page(struct intel_ring_buffer *ring)
776 ret = -ENOMEM; 777 ret = -ENOMEM;
777 goto err; 778 goto err;
778 } 779 }
779 obj->cache_level = I915_CACHE_LLC; 780
781 i915_gem_object_set_cache_level(obj, I915_CACHE_LLC);
780 782
781 ret = i915_gem_object_pin(obj, 4096, true); 783 ret = i915_gem_object_pin(obj, 4096, true);
782 if (ret != 0) { 784 if (ret != 0) {